{"_id":"@cooplux/praxis","_rev":"2-c0765b8c66e51c45e81066ce5e9ed0c2","name":"@cooplux/praxis","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@cooplux/praxis","version":"0.1.0","_id":"@cooplux/praxis@0.1.0","maintainers":[{"name":"kaaterskillsawmill","email":"kaaterskillsawmill@gmail.com"}],"dist":{"shasum":"d2cb327fc5aab094fc73469bf272846405cdb2b7","tarball":"https://registry.npmjs.org/@cooplux/praxis/-/praxis-0.1.0.tgz","fileCount":1,"integrity":"sha512-UiR/Shf9mRwkkMyp0TAM8SCsZUn/cwiZxLisvWoVWrZGEqIJkdYkthMBLhRlnNdqBKcZgD++0rRzOf26RMPn7w==","signatures":[{"sig":"MEYCIQCEbGnOjHInzSMAd2ofo2vNg/yjJwPFsVHuQ7Lq3XIl8AIhAO04DIYM7a+UaILXvJIAiQ8mRaj6f72gcxjQaZYdA3gz","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":61},"private":false,"_npmUser":{"name":"kaaterskillsawmill","email":"kaaterskillsawmill@gmail.com"},"_npmVersion":"10.9.8","directories":{},"_nodeVersion":"22.23.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/praxis_0.1.0_1783916105918_0.17810175455937416","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@cooplux/praxis","version":"0.2.0","description":"Attended, resumable runbook engine (init/validate/run/resume/status/attest/verify) with an append-only, attested, hash-chained audit trail. Attestation is honor-system (recorded name + timestamp); rollback argv is printed, never auto-run.","keywords":["runbook","human-in-the-loop","attestation","audit-trail","resume","change-management","four-eyes","sop"],"author":{"name":"Dane Anthony Cooper"},"license":"MIT","type":"module","bin":{"praxis":"dist/index.js"},"engines":{"node":">=20.0.0"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/katterskillsawmill/cooplux.git","directory":"packages/praxis"},"scripts":{"build":"tsup src/index.ts --format esm --clean","dev":"tsx src/index.ts","typecheck":"tsc --noEmit","test":"node --test","prepublishOnly":"npm run build"},"dependencies":{"chalk":"^5.3.0","commander":"^12.1.0","execa":"^9.3.0"},"devDependencies":{"@types/node":"^22.0.0","tsup":"^8.2.3","tsx":"^4.16.2","typescript":"^5.5.4"},"gitHead":"eb0e07dc3144d245e353fece9038cada9404d7c7","_id":"@cooplux/praxis@0.2.0","bugs":{"url":"https://github.com/katterskillsawmill/cooplux/issues"},"homepage":"https://github.com/katterskillsawmill/cooplux#readme","_nodeVersion":"22.23.1","_npmVersion":"12.0.1","dist":{"integrity":"sha512-SuL/wYfv8ZdZQEW4u0IBCiS8hV4gdOQcEn7VYH1vWZknrUmaewTFHnZ0QCeTpjaBIQ/0nEtIEz4NUGk4qIU6ww==","shasum":"44b23293d1b9db899df401badb46fccc10a7b194","tarball":"https://registry.npmjs.org/@cooplux/praxis/-/praxis-0.2.0.tgz","fileCount":4,"unpackedSize":47081,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHDmb3eMJ7tJceK+CzHo5LbNlmZ9UoYW1VbZayxyj6nPAiB5FSQRKaNWE9c/65J+Vp/jYRVv/MqLNyNhxiVsLWCjeQ=="}]},"_npmUser":{"name":"kaaterskillsawmill","email":"kaaterskillsawmill@gmail.com"},"directories":{},"maintainers":[{"name":"kaaterskillsawmill","email":"kaaterskillsawmill@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/praxis_0.2.0_1784281330900_0.49244358185135506"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-13T04:15:05.781Z","modified":"2026-07-17T09:42:11.161Z","0.1.0":"2026-07-13T04:15:06.050Z","0.2.0":"2026-07-17T09:42:11.023Z"},"maintainers":[{"name":"kaaterskillsawmill","email":"kaaterskillsawmill@gmail.com"}],"readme":"# @cooplux/praxis\n\n> Attended, resumable runbooks with an **append-only, attested, hash-chained** audit trail.\n\n`praxis` runs a procedure one step at a time. It executes `command`/`check` steps, pauses at\n`manual` gates for a human to attest, and records every state transition to an append-only\n`receipts.jsonl` ledger whose lines are hash-chained (each line embeds the prior line's SHA-256,\nRekor-style, offline). If the process crashes mid-run, `praxis resume` picks up where it left off —\nand if a step was interrupted with an unknown outcome, it **stops and asks** rather than blindly\nre-running.\n\n> **Honest scope — read this.** Attestation is **honor-system**: a *recorded operator name +\n> timestamp*. It is **NOT** a verified login, it does **NOT** enforce segregation-of-duties, and it\n> is **NOT** a compliance certification. The ledger is append-only and **hash-chained\n> (tamper-evident)** — **nothing is cryptographically signed**. Rollback argv is recorded and\n> printed for the operator; praxis **never auto-runs it**. The trail is *evidence a team may use*,\n> not a guarantee.\n\n## Install / use\n\n```bash\nnpx @cooplux/praxis init            # scaffold praxis.json\nnpm i -g @cooplux/praxis && praxis --help\n```\n\nNode ≥ 20.\n\n## Commands\n\n- `praxis init [file]` — scaffold a starter `praxis.json` (refuses to clobber an existing one).\n- `praxis validate [file]` — validate a runbook against the contract (errors + advisory warnings).\n- `praxis run [file]` — start a new run.\n  - `--dry-run` — classify each step *safely-previewable* vs *side-effecting* and **loudly flag** the\n    latter (it does not execute anything).\n  - `--yes` — auto-attest non-`required-human` manual gates as `ci:auto` (never an operator name).\n  - `--force-lock` — override a run-lock held on another host.\n- `praxis resume [file]` — resume the latest unfinished run. Stops on any **in-doubt** step.\n  - `--resolve <id>=done|redo` (repeatable) — record the operator's decision for an in-doubt step.\n  - `--force-redo` — permit `redo` of a **non-idempotent** step (may double-apply a side effect).\n- `praxis status [file]` — read-only: per-step status, chain integrity, the run-lock, in-doubt steps,\n  and the rollback argv to run by hand after a crash.\n- `praxis attest <stepId> [file]` — record an attestation for a manual gate.\n  - `--as \"<name>\"` — the operator name to record (required unless `--yes`).\n  - `--note \"<text>\"` — an optional note.\n  - `--yes` — auto-attest as `ci:auto` (forbidden together with `--as`; **refused** on a\n    `required-human` gate).\n- `praxis verify [file]` — verify the append-only hash-chain of the ledger (offline; **not** a\n  signature check).\n\n## Runbook format (`praxis.json`)\n\n```jsonc\n{\n  \"schema\": \"cooplux.praxis.manifest.v1\",\n  \"name\": \"deploy-runbook\",\n  \"steps\": [\n    { \"id\": \"preflight\",  \"type\": \"check\",   \"run\": [\"node\", \"--version\"], \"sideEffecting\": false },\n    { \"id\": \"gate\",       \"type\": \"manual\",  \"prompt\": \"Confirm the change window is open.\", \"requiredHuman\": true },\n    { \"id\": \"apply\",      \"type\": \"command\", \"run\": [\"./deploy.sh\"], \"idempotent\": false,\n      \"sideEffecting\": true, \"rollback\": [\"./rollback.sh\"] }\n  ]\n}\n```\n\n- **`command`** — an argv executed with `execa` `shell:false` (no shell parsing, no injection). Side-effecting by default.\n- **`check`** — an argv treated as a read-only probe (previewable in `--dry-run`).\n- **`manual`** — a human gate: praxis pauses; an operator attests via `praxis attest`.\n- **`idempotent`** (default `false`) — only idempotent steps may set `attempts` > 1 and be\n  auto-retried. Non-idempotent steps are never auto-retried, and an in-doubt non-idempotent step\n  cannot be `redo`ne without `--force-redo`.\n- **`rollback`** — argv recorded/printed for the operator, **never auto-run**.\n- **`requiredHuman`** — a manual gate that **refuses** `--yes` / auto-attest.\n\n## Configuration (env-only)\n\nEverything is credential-free by default and driven by environment variables — nothing is bundled.\n**Pass secrets via the environment, never on a step's command line**; praxis additionally redacts\nsecret-shaped tokens from argv before persisting them, and does not capture step stdout/stderr into\nthe receipt.\n\n| Variable | Purpose | Default |\n| --- | --- | --- |\n| `PRAXIS_MANIFEST` | default manifest path | `praxis.json` |\n| `PRAXIS_LEDGER` | ledger path | `receipts.jsonl` beside the manifest |\n| `PRAXIS_RECEIPT_URL` | optional POST target for the summary receipt (argv stripped → hashed) | — (no publish) |\n| `PRAXIS_RECEIPT_TOKEN` | optional bearer for the publish target | — |\n\n## Crash-safety (how resume stays honest)\n\nBefore spawning any step, praxis appends a `step-start` marker to the ledger and `fsync`s it. If the\nprocess is killed between \"the step changed the world\" and \"state → ok\", that marker survives. On\n`resume`, a step that started but has no `ok`/`failed` outcome is **in-doubt**: praxis stops, shows\nthe exact argv, and asks you to inspect the system and resolve it (`--resolve <id>=done|redo`). It\nnever guesses.\n\n## Attestation honesty (`--yes`)\n\n`--yes` auto-attest always stamps `attestedBy: \"ci:auto\"`, `method: \"ci-auto\"`,\n`machine_attested: true`, `four_eyes: false` — it can **never** carry an operator name, `--as` is\nforbidden alongside it, and a `required-human` gate refuses it outright. This keeps machine sign-offs\ndistinguishable from human ones in the ledger.\n\n## Part of the CoopLux constellation\n\n`praxis` executes attended procedures; `enfilade` sequences tools; `datum` holds reference data at\nrest. Schema tags: `cooplux.praxis.manifest.v1` / `cooplux.praxis.receipt.v1`. Content hashes use the\nfamily SRI dialect `sha256-<base64>` over canonicalized content. `@qbts` = task-pipeline engine;\n`@qbtz` = quantum-env orchestrator — **not** the same tool.\n\n## License\n\nMIT © Dane Anthony Cooper\n","readmeFilename":"README.md","description":"Attended, resumable runbook engine (init/validate/run/resume/status/attest/verify) with an append-only, attested, hash-chained audit trail. Attestation is honor-system (recorded name + timestamp); rollback argv is printed, never auto-run.","homepage":"https://github.com/katterskillsawmill/cooplux#readme","keywords":["runbook","human-in-the-loop","attestation","audit-trail","resume","change-management","four-eyes","sop"],"repository":{"type":"git","url":"git+https://github.com/katterskillsawmill/cooplux.git","directory":"packages/praxis"},"author":{"name":"Dane Anthony Cooper"},"bugs":{"url":"https://github.com/katterskillsawmill/cooplux/issues"},"license":"MIT"}