create-agent-rig 0.9.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +419 -3
- package/README.md +267 -305
- package/package.json +8 -14
- package/packages/cli/dist/commands/create.js +56 -88
- package/packages/cli/dist/commands/doctor.js +213 -0
- package/packages/cli/dist/commands/init.js +111 -50
- package/packages/cli/dist/commands/integrations.js +468 -0
- package/packages/cli/dist/commands/setup-wizard.js +61 -0
- package/packages/cli/dist/commands/uninstall.js +1223 -0
- package/packages/cli/dist/commands/upgrade.js +472 -90
- package/packages/cli/dist/index.js +651 -46
- package/packages/cli/dist/integrations/declaration.js +158 -0
- package/packages/cli/dist/integrations/doctor-guards.js +126 -0
- package/packages/cli/dist/integrations/doctor-workflow.js +25 -0
- package/packages/cli/dist/integrations/mcp-json.js +107 -0
- package/packages/cli/dist/integrations/memory-doctor.js +124 -0
- package/packages/cli/dist/integrations/registry.js +22 -0
- package/packages/cli/dist/integrations/spawn.js +228 -0
- package/packages/cli/dist/integrations/spec-kit.js +280 -0
- package/packages/cli/dist/integrations/verify.js +193 -0
- package/packages/cli/dist/integrations/windows-job.js +275 -0
- package/packages/cli/dist/lib/elevated-paths.js +74 -0
- package/packages/cli/dist/lib/install-set.js +1 -44
- package/packages/cli/dist/lib/manifest.js +64 -5
- package/packages/cli/dist/lib/prompts.js +0 -23
- package/packages/cli/dist/lib/safe-path.js +193 -2
- package/packages/cli/dist/lib/safe-text.js +78 -0
- package/packages/cli/dist/lib/substitute.js +1 -52
- package/packages/cli/dist/lib/summary.js +5 -5
- package/packages/cli/dist/templates.js +4 -14
- package/scripts/prepare.mjs +28 -12
- package/templates/agent-os/subagent-routing.json +4 -4
- package/templates/agent-os/universal/.agents/skills/check-premises/SKILL.md +13 -9
- package/templates/agent-os/universal/.agents/skills/loop/SKILL.md +31 -6
- package/templates/agent-os/universal/.agents/skills/new-invariant/SKILL.md +5 -5
- package/templates/agent-os/universal/.agents/skills/pr-ship/SKILL.md +1 -1
- package/templates/agent-os/universal/.agents/skills/worktree-task/SKILL.md +3 -3
- package/templates/agent-os/universal/.claude/agents/code-reviewer.md +8 -6
- package/templates/agent-os/universal/.claude/agents/implementation-agent.md +41 -0
- package/templates/agent-os/universal/.claude/agents/prose-reviewer.md +8 -4
- package/templates/agent-os/universal/.claude/agents/security-scanner.md +4 -2
- package/templates/agent-os/universal/.claude/agents/test-writer.md +2 -2
- package/templates/agent-os/universal/.claude/hooks/inject-rules.mjs +83 -4
- package/templates/agent-os/universal/.claude/rules/autonomy.md +55 -27
- package/templates/agent-os/universal/.claude/rules/invariants.md +9 -8
- package/templates/agent-os/universal/.claude/rules/workflow.md +47 -22
- package/templates/agent-os/universal/.claude/scripts/decision-router.mjs +1 -1
- package/templates/agent-os/universal/.claude/scripts/detect-missed-gate.mjs +12 -9
- package/templates/agent-os/universal/.claude/scripts/doctor.mjs +100 -2
- package/templates/agent-os/universal/.claude/scripts/lib/claim-records.mjs +236 -6
- package/templates/agent-os/universal/.claude/scripts/queue/state.mjs +2 -2
- package/templates/agent-os/universal/.claude/scripts/reconcile-external-prs.mjs +4 -3
- package/templates/agent-os/universal/.claude/scripts/revalidate.mjs +16 -0
- package/templates/agent-os/universal/.claude/settings.json +0 -8
- package/templates/agent-os/universal/.claude/skills/check-premises/SKILL.md +13 -9
- package/templates/agent-os/universal/.claude/skills/loop/SKILL.md +31 -6
- package/templates/agent-os/universal/.claude/skills/new-invariant/SKILL.md +5 -5
- package/templates/agent-os/universal/.claude/skills/pr-ship/SKILL.md +1 -1
- package/templates/agent-os/universal/.claude/skills/worktree-task/SKILL.md +3 -3
- package/templates/agent-os/universal/.codex/agents/code-reviewer.toml +2 -2
- package/templates/agent-os/universal/.codex/agents/implementation-agent.toml +6 -0
- package/templates/agent-os/universal/.codex/agents/prose-reviewer.toml +2 -2
- package/templates/agent-os/universal/.codex/agents/security-scanner.toml +1 -1
- package/templates/agent-os/universal/.codex/agents/test-writer.toml +1 -1
- package/templates/agent-os/universal/.codex/hooks.json +0 -10
- package/templates/agent-os/universal/AGENTS.md +208 -107
- package/templates/agent-os/universal/CLAUDE.md +15 -162
- package/templates/agent-os/universal/PLAN.md +17 -10
- package/templates/agent-os/universal/docs/decisions/agents-md-canonical.md +313 -0
- package/templates/agent-os/universal/docs/decisions/codex-adapter.md +15 -10
- package/templates/agent-os/universal/docs/decisions/review-lanes.md +12 -8
- package/templates/agent-os/universal/docs/decisions/session-start-wire-format.md +206 -0
- package/templates/agent-os/universal/docs/decisions/subagent-routing.md +6 -3
- package/templates/agent-os/universal/docs/decisions/workflow-layer-split.md +235 -0
- package/templates/agent-os/universal/layers.json +25 -30
- package/templates/hash-history.json +8 -4
- package/templates/release-ledger.json +2 -1
- package/packages/cli/dist/lib/composition.js +0 -20
- package/packages/cli/dist/lib/targets.js +0 -28
- package/packages/cli/dist/policy/benchmark/corpus.js +0 -165
- package/packages/cli/dist/policy/core/adapter.js +0 -18
- package/packages/cli/dist/policy/core/coverage.js +0 -253
- package/packages/cli/dist/policy/core/decision-record.js +0 -287
- package/packages/cli/dist/policy/core/declaration.js +0 -127
- package/packages/cli/dist/policy/core/evidence-matrix.js +0 -94
- package/packages/cli/dist/policy/core/probe.js +0 -442
- package/packages/cli/dist/policy/core/registry.js +0 -115
- package/packages/cli/dist/policy/core/validation.js +0 -275
- package/packages/cli/dist/policy/core/vocabulary.js +0 -123
- package/packages/cli/dist/policy/harness/claude.js +0 -47
- package/packages/cli/dist/policy/harness/codex.js +0 -87
- package/packages/cli/dist/policy/harness/index.js +0 -15
- package/packages/cli/dist/policy/harness/shared-hooks.js +0 -28
- package/packages/cli/dist/policy/index.js +0 -17
- package/templates/agent-os/init/AGENTS.md +0 -201
- package/templates/agent-os/init/CLAUDE.md +0 -201
- package/templates/agent-os/stack/aws-cdk/.agents/skills/post-deploy-verify/SKILL.md +0 -105
- package/templates/agent-os/stack/aws-cdk/.agents/skills/ro-debug/SKILL.md +0 -117
- package/templates/agent-os/stack/aws-cdk/.claude/agents/cdk-diff-reviewer.md +0 -89
- package/templates/agent-os/stack/aws-cdk/.claude/rules/aws-cdk.md +0 -105
- package/templates/agent-os/stack/aws-cdk/.claude/skills/post-deploy-verify/SKILL.md +0 -105
- package/templates/agent-os/stack/aws-cdk/.claude/skills/ro-debug/SKILL.md +0 -117
- package/templates/agent-os/stack/aws-cdk/.codex/agents/cdk-diff-reviewer.toml +0 -6
- package/templates/agent-os/stack/node-ts/.claude/hooks/dod-checks.json +0 -1
- package/templates/agent-os/stack/node-ts/.claude/rules/node-ts.md +0 -85
- package/templates/agent-os/universal/.claude/hooks/guard-core-purity.mjs +0 -89
- package/templates/agent-os/universal/.claude/hooks/guard-web-boundary.mjs +0 -68
- package/templates/agent-os/universal/.claude/rules/architecture.md +0 -81
- package/templates/skeleton/aws-serverless/.github/workflows/ci.yml +0 -28
- package/templates/skeleton/aws-serverless/.github/workflows/deploy.yml +0 -90
- package/templates/skeleton/aws-serverless/README.md +0 -181
- package/templates/skeleton/aws-serverless/apps/web/next.config.mjs +0 -17
- package/templates/skeleton/aws-serverless/apps/web/package.json +0 -19
- package/templates/skeleton/aws-serverless/apps/web/src/app/layout.tsx +0 -17
- package/templates/skeleton/aws-serverless/apps/web/src/app/page.tsx +0 -96
- package/templates/skeleton/aws-serverless/apps/web/src/lib/api.ts +0 -36
- package/templates/skeleton/aws-serverless/apps/web/src/lib/validate.ts +0 -23
- package/templates/skeleton/aws-serverless/apps/web/test/shared-validation.test.ts +0 -38
- package/templates/skeleton/aws-serverless/apps/web/tsconfig.json +0 -14
- package/templates/skeleton/aws-serverless/eslint.config.mjs +0 -20
- package/templates/skeleton/aws-serverless/gitignore +0 -56
- package/templates/skeleton/aws-serverless/infra/bin/app.ts +0 -79
- package/templates/skeleton/aws-serverless/infra/cdk.json +0 -3
- package/templates/skeleton/aws-serverless/infra/lib/app-stack.ts +0 -248
- package/templates/skeleton/aws-serverless/infra/lib/web-stack.ts +0 -45
- package/templates/skeleton/aws-serverless/infra/package.json +0 -18
- package/templates/skeleton/aws-serverless/infra/test/allowed-origins.test.ts +0 -301
- package/templates/skeleton/aws-serverless/infra/test/app-composition.test.ts +0 -137
- package/templates/skeleton/aws-serverless/infra/test/app-stack.test.ts +0 -120
- package/templates/skeleton/aws-serverless/infra/test/web-stack.test.ts +0 -44
- package/templates/skeleton/aws-serverless/package.json +0 -30
- package/templates/skeleton/aws-serverless/packages/core/package.json +0 -11
- package/templates/skeleton/aws-serverless/packages/core/src/events.ts +0 -14
- package/templates/skeleton/aws-serverless/packages/core/src/index.ts +0 -15
- package/templates/skeleton/aws-serverless/packages/core/src/note.ts +0 -69
- package/templates/skeleton/aws-serverless/packages/core/test/events.test.ts +0 -23
- package/templates/skeleton/aws-serverless/packages/core/test/note.test.ts +0 -101
- package/templates/skeleton/aws-serverless/packages/db/package.json +0 -14
- package/templates/skeleton/aws-serverless/packages/db/src/client.ts +0 -17
- package/templates/skeleton/aws-serverless/packages/db/src/index.ts +0 -2
- package/templates/skeleton/aws-serverless/packages/db/src/note-model.ts +0 -52
- package/templates/skeleton/aws-serverless/packages/db/test/note-model.test.ts +0 -91
- package/templates/skeleton/aws-serverless/packages/shared/package.json +0 -11
- package/templates/skeleton/aws-serverless/packages/shared/src/env.ts +0 -17
- package/templates/skeleton/aws-serverless/packages/shared/src/errors.ts +0 -33
- package/templates/skeleton/aws-serverless/packages/shared/src/index.ts +0 -3
- package/templates/skeleton/aws-serverless/packages/shared/src/logger.ts +0 -20
- package/templates/skeleton/aws-serverless/packages/shared/test/env.test.ts +0 -26
- package/templates/skeleton/aws-serverless/packages/shared/test/errors.test.ts +0 -28
- package/templates/skeleton/aws-serverless/packages/shared/test/logger.test.ts +0 -19
- package/templates/skeleton/aws-serverless/pnpm-lock.yaml +0 -2855
- package/templates/skeleton/aws-serverless/pnpm-workspace.yaml +0 -14
- package/templates/skeleton/aws-serverless/services/api/package.json +0 -15
- package/templates/skeleton/aws-serverless/services/api/src/adapters/sqs-publisher.ts +0 -26
- package/templates/skeleton/aws-serverless/services/api/src/handlers/create-note.ts +0 -69
- package/templates/skeleton/aws-serverless/services/api/src/handlers/list-notes.ts +0 -37
- package/templates/skeleton/aws-serverless/services/api/src/list-main.ts +0 -12
- package/templates/skeleton/aws-serverless/services/api/src/main.ts +0 -21
- package/templates/skeleton/aws-serverless/services/api/src/usecases/create-note.ts +0 -41
- package/templates/skeleton/aws-serverless/services/api/src/usecases/list-notes.ts +0 -14
- package/templates/skeleton/aws-serverless/services/api/test/create-note.handler.test.ts +0 -211
- package/templates/skeleton/aws-serverless/services/api/test/create-note.usecase.test.ts +0 -45
- package/templates/skeleton/aws-serverless/services/api/test/list-notes.test.ts +0 -122
- package/templates/skeleton/aws-serverless/services/api/test/sqs-publisher.test.ts +0 -22
- package/templates/skeleton/aws-serverless/services/worker/package.json +0 -12
- package/templates/skeleton/aws-serverless/services/worker/src/handlers/note-created.ts +0 -15
- package/templates/skeleton/aws-serverless/services/worker/src/main.ts +0 -7
- package/templates/skeleton/aws-serverless/services/worker/src/usecases/process-note-created.ts +0 -37
- package/templates/skeleton/aws-serverless/services/worker/test/note-created.test.ts +0 -61
- package/templates/skeleton/aws-serverless/tsconfig.base.json +0 -15
- package/templates/skeleton/aws-serverless/tsconfig.json +0 -16
- package/templates/skeleton/aws-serverless/vitest.config.ts +0 -14
- package/templates/skeleton/node-service/.github/workflows/ci.yml +0 -27
- package/templates/skeleton/node-service/.github/workflows/deploy.yml +0 -29
- package/templates/skeleton/node-service/README.md +0 -104
- package/templates/skeleton/node-service/apps/web/next.config.mjs +0 -17
- package/templates/skeleton/node-service/apps/web/package.json +0 -19
- package/templates/skeleton/node-service/apps/web/src/app/layout.tsx +0 -17
- package/templates/skeleton/node-service/apps/web/src/app/page.tsx +0 -96
- package/templates/skeleton/node-service/apps/web/src/lib/api.ts +0 -29
- package/templates/skeleton/node-service/apps/web/src/lib/validate.ts +0 -23
- package/templates/skeleton/node-service/apps/web/test/shared-validation.test.ts +0 -38
- package/templates/skeleton/node-service/apps/web/tsconfig.json +0 -14
- package/templates/skeleton/node-service/eslint.config.mjs +0 -20
- package/templates/skeleton/node-service/gitignore +0 -54
- package/templates/skeleton/node-service/package.json +0 -30
- package/templates/skeleton/node-service/packages/core/package.json +0 -11
- package/templates/skeleton/node-service/packages/core/src/events.ts +0 -14
- package/templates/skeleton/node-service/packages/core/src/index.ts +0 -15
- package/templates/skeleton/node-service/packages/core/src/note.ts +0 -69
- package/templates/skeleton/node-service/packages/core/test/events.test.ts +0 -23
- package/templates/skeleton/node-service/packages/core/test/note.test.ts +0 -101
- package/templates/skeleton/node-service/packages/db/package.json +0 -12
- package/templates/skeleton/node-service/packages/db/src/index.ts +0 -1
- package/templates/skeleton/node-service/packages/db/src/note-store.ts +0 -100
- package/templates/skeleton/node-service/packages/db/test/note-store.test.ts +0 -100
- package/templates/skeleton/node-service/packages/shared/package.json +0 -11
- package/templates/skeleton/node-service/packages/shared/src/env.ts +0 -17
- package/templates/skeleton/node-service/packages/shared/src/errors.ts +0 -33
- package/templates/skeleton/node-service/packages/shared/src/index.ts +0 -3
- package/templates/skeleton/node-service/packages/shared/src/logger.ts +0 -20
- package/templates/skeleton/node-service/packages/shared/test/env.test.ts +0 -26
- package/templates/skeleton/node-service/packages/shared/test/errors.test.ts +0 -28
- package/templates/skeleton/node-service/packages/shared/test/logger.test.ts +0 -19
- package/templates/skeleton/node-service/pnpm-lock.yaml +0 -2402
- package/templates/skeleton/node-service/pnpm-workspace.yaml +0 -13
- package/templates/skeleton/node-service/scripts/build-artifact.mjs +0 -34
- package/templates/skeleton/node-service/services/api/package.json +0 -17
- package/templates/skeleton/node-service/services/api/src/adapters/spool-publisher.ts +0 -23
- package/templates/skeleton/node-service/services/api/src/handlers/create-note.ts +0 -40
- package/templates/skeleton/node-service/services/api/src/handlers/list-notes.ts +0 -23
- package/templates/skeleton/node-service/services/api/src/main.ts +0 -40
- package/templates/skeleton/node-service/services/api/src/server.ts +0 -172
- package/templates/skeleton/node-service/services/api/src/static-dir.ts +0 -20
- package/templates/skeleton/node-service/services/api/src/usecases/create-note.ts +0 -30
- package/templates/skeleton/node-service/services/api/src/usecases/list-notes.ts +0 -14
- package/templates/skeleton/node-service/services/api/test/artifact.test.ts +0 -92
- package/templates/skeleton/node-service/services/api/test/create-note.handler.test.ts +0 -64
- package/templates/skeleton/node-service/services/api/test/create-note.usecase.test.ts +0 -43
- package/templates/skeleton/node-service/services/api/test/list-notes.test.ts +0 -48
- package/templates/skeleton/node-service/services/api/test/package-manager.test.ts +0 -40
- package/templates/skeleton/node-service/services/api/test/package-manager.ts +0 -51
- package/templates/skeleton/node-service/services/api/test/server.test.ts +0 -208
- package/templates/skeleton/node-service/services/api/test/spool-publisher.test.ts +0 -32
- package/templates/skeleton/node-service/services/api/test/static-dir.test.ts +0 -29
- package/templates/skeleton/node-service/services/worker/package.json +0 -16
- package/templates/skeleton/node-service/services/worker/src/main.ts +0 -28
- package/templates/skeleton/node-service/services/worker/src/spool.ts +0 -60
- package/templates/skeleton/node-service/services/worker/src/usecases/process-note-created.ts +0 -38
- package/templates/skeleton/node-service/services/worker/test/process-note-created.test.ts +0 -34
- package/templates/skeleton/node-service/services/worker/test/spool.test.ts +0 -76
- package/templates/skeleton/node-service/tsconfig.base.json +0 -15
- package/templates/skeleton/node-service/tsconfig.json +0 -13
- package/templates/skeleton/node-service/vitest.config.ts +0 -12
|
@@ -28,7 +28,7 @@ same four steps with the diff as the code, and §4 carries what is different.
|
|
|
28
28
|
|
|
29
29
|
**What "rulebook prose" means here is not a new list** — it is the set
|
|
30
30
|
`.claude/rules/workflow.md` already uses for the `prose-reviewer` trigger: a rule
|
|
31
|
-
file, a skill, an agent spec, a decision record, `CLAUDE.md`, the README. Where a
|
|
31
|
+
file, a skill, an agent spec, a decision record, `CLAUDE.md`, `AGENTS.md`, the README. Where a
|
|
32
32
|
rulebook file exists twice (a template source and a generated copy), check the
|
|
33
33
|
**source**; the copy is composed from it. A comment in a test or a hook is in scope
|
|
34
34
|
too when it asserts behaviour — the file it lives in does not change what a claim is.
|
|
@@ -36,8 +36,8 @@ too when it asserts behaviour — the file it lives in does not change what a cl
|
|
|
36
36
|
🔴 **`PREMISE FALSE` belongs to the first entry point only.** At the second one the
|
|
37
37
|
claims are your own and the remedy is an edit, so a false one is not an escalation:
|
|
38
38
|
it is `UNMEASURED`'s neighbour — delete or correct the sentence and carry on. Reading
|
|
39
|
-
it as the escalation `loop` §6 defines would send a
|
|
40
|
-
over one sentence.
|
|
39
|
+
it as the escalation `loop` §6 (opt-in workflow layer) defines would send a
|
|
40
|
+
finished branch back to the queue over one sentence.
|
|
41
41
|
|
|
42
42
|
## Why it sits here and not in review
|
|
43
43
|
|
|
@@ -185,9 +185,13 @@ inside the block; both forms are the contract.
|
|
|
185
185
|
actually says, and `file`/`line` is the citation §3 requires.
|
|
186
186
|
- `PREMISES_HOLD` carries an empty `blockers` list; the other three name at
|
|
187
187
|
least one. A stop verdict without one is not an answer the caller can act on,
|
|
188
|
-
and the caller is what checks:
|
|
189
|
-
|
|
190
|
-
|
|
188
|
+
and the caller is what checks: `node .claude/scripts/verdict.mjs check
|
|
189
|
+
<report> check-premises` on what you return — `verdict.mjs` is Core and runs
|
|
190
|
+
standalone, so the caller is whichever session invoked this skill (this is a
|
|
191
|
+
Core skill, meant to run with no queue and no loop); the `loop` skill (opt-in
|
|
192
|
+
workflow layer) runs the same command the same way when it is the one that
|
|
193
|
+
invoked you. Nothing in this skill runs it — this skill writes nothing at
|
|
194
|
+
all.
|
|
191
195
|
- **`headSha` is the commit you read** — `git rev-parse HEAD` in the checkout
|
|
192
196
|
you examined. A premise check answers about a tree, and the tree moves.
|
|
193
197
|
|
|
@@ -231,6 +235,6 @@ is invisible to every gate downstream.
|
|
|
231
235
|
when a task starts building on an unchecked claim, and no artifact outlives the
|
|
232
236
|
step — so a run that skipped it and a run that passed it look identical
|
|
233
237
|
afterwards. That is the honest description of every rule of this shape here
|
|
234
|
-
(the `loop` skill says the same about its own
|
|
235
|
-
why the citation matters: a `file:line` in
|
|
236
|
-
later reader can re-check.
|
|
238
|
+
(the `loop` skill — opt-in workflow layer — says the same about its own
|
|
239
|
+
no-hand-feeding rule), and it is why the citation matters: a `file:line` in
|
|
240
|
+
the report is the one part of this a later reader can re-check.
|
|
@@ -12,7 +12,7 @@ decisions. This skill is the driver in between: what gets picked,
|
|
|
12
12
|
what keeps the loop going, what stops it, and where the report goes.
|
|
13
13
|
|
|
14
14
|
Per-task procedure: (worktree if another session may run) → `check-premises` on the
|
|
15
|
-
item → failing test first → implement → **`check-premises` again, on your own prose**
|
|
15
|
+
item → failing test first (`test-writer`) → implement (`implementation-agent`) → **`check-premises` again, on your own prose**
|
|
16
16
|
→ `pr-ship` → merge on the named criterion → verify the deployed surface if one
|
|
17
17
|
changed.
|
|
18
18
|
|
|
@@ -344,7 +344,7 @@ it only here. A tier outside that vocabulary **holds**, never releases
|
|
|
344
344
|
(`docs/decisions/spacing-rations-mechanisms.md`).
|
|
345
345
|
|
|
346
346
|
**The tier marker is a pre-filter, not the authority.** If an item passed as normal
|
|
347
|
-
and the work turns out to touch an elevated path (`
|
|
347
|
+
and the work turns out to touch an elevated path (`AGENTS.md` →
|
|
348
348
|
`elevated-paths`), run the gate anyway, record the verdict on the PR, and treat it
|
|
349
349
|
as this run's elevated item for spacing.
|
|
350
350
|
|
|
@@ -842,8 +842,8 @@ unbounded improvement list is another diary, and three forces a choice. Each nam
|
|
|
842
842
|
four things, and a proposal missing any of them is not ready to file:
|
|
843
843
|
|
|
844
844
|
1. the finding it came from, cited as the journal line it appears on;
|
|
845
|
-
2. the part to change — a skill, an agent spec, a hook, a rule file, `
|
|
846
|
-
the CI workflow;
|
|
845
|
+
2. the part to change — a skill, an agent spec, a hook, a rule file, `AGENTS.md`,
|
|
846
|
+
`CLAUDE.md`, the CI workflow;
|
|
847
847
|
3. the change, concretely enough to diff;
|
|
848
848
|
4. how the next run would prove it worked — the observation that would differ.
|
|
849
849
|
|
|
@@ -858,7 +858,7 @@ node --input-type=module -e '
|
|
|
858
858
|
const a = await import("./.claude/scripts/queue/plan-md.mjs"); // or github-issues / jira
|
|
859
859
|
console.log(await a.proposeTriage({
|
|
860
860
|
finding: "<the journal line it came from>",
|
|
861
|
-
part: "<skill | agent | hook | rule | CLAUDE.md | workflow>",
|
|
861
|
+
part: "<skill | agent | hook | rule | AGENTS.md | CLAUDE.md | workflow>",
|
|
862
862
|
change: "<concretely enough to diff>",
|
|
863
863
|
proof: "<the observation that would differ next run>",
|
|
864
864
|
// a pair: what the probe touched, and what is concluded from it. The
|
|
@@ -961,9 +961,34 @@ three poisons the only channel by which this project learns.
|
|
|
961
961
|
underneath it:
|
|
962
962
|
|
|
963
963
|
```bash
|
|
964
|
-
node .claude/scripts/revalidate.mjs --point BEFORE_CLOSE --ticket <item-id>
|
|
964
|
+
node .claude/scripts/revalidate.mjs --point BEFORE_CLOSE --ticket <item-id> \
|
|
965
|
+
--merge-commit "$(gh pr view <pr> --json mergeCommit -q .mergeCommit.oid)"
|
|
965
966
|
```
|
|
966
967
|
|
|
968
|
+
`--merge-commit` names the exact SHA the tracker's own PR metadata records as
|
|
969
|
+
THIS item's merge commit — one piece of evidence among several that let a
|
|
970
|
+
`targetSha` move which is nothing but that merge read as `CURRENT` instead
|
|
971
|
+
of `claim:scope` drift. Resolve it from the PR just merged, by name, never by
|
|
972
|
+
reading `git log` text, and only after the merge has landed and been
|
|
973
|
+
fetched. Omitting it (the item has not merged yet, or an older loop that
|
|
974
|
+
predates this flag) leaves any target movement holding exactly as it did
|
|
975
|
+
before this flag existed — it is purely additive to that default. Naming the
|
|
976
|
+
SHA is necessary but never sufficient: the exemption also requires the
|
|
977
|
+
target to have advanced by EXACTLY ONE commit — a genuine squash merge; a
|
|
978
|
+
merge commit or any multi-commit range still holds
|
|
979
|
+
(`test/template/revalidate.test.ts` (absent in a generated rig) › "a foreign
|
|
980
|
+
commit plus the real merge in the same range, --merge-commit correctly
|
|
981
|
+
naming the real one") — and it binds to THIS checkout: the named commit's
|
|
982
|
+
tree must equal `HEAD`'s tree here, and `HEAD` must still be the pre-merge
|
|
983
|
+
checkout, not one already fast-forwarded onto the merge
|
|
984
|
+
(`test/template/revalidate.test.ts` (absent in a generated rig) › "a single
|
|
985
|
+
FOREIGN commit named as --merge-commit does not exempt it — reproduces the
|
|
986
|
+
gate-hold attack and proves it now holds" and › "HEAD already at the merge
|
|
987
|
+
commit is vacuous, and still holds (a fast-forwarded checkout must not
|
|
988
|
+
self-satisfy the exemption)"). That binding stops a lazy or mistaken flag,
|
|
989
|
+
not an adversary who controls this run's own checkout — see
|
|
990
|
+
`isOwnMergeAdvance` in `claim-records.mjs` for the exact limit.
|
|
991
|
+
|
|
967
992
|
It compares the tracked claim's `scope` and `commentary` fingerprint sets;
|
|
968
993
|
commentary becomes hold-authoritative only here. Marker/take-up movement is
|
|
969
994
|
retained in evidence but cannot decide drift. A missing claim is
|
|
@@ -94,9 +94,9 @@ is a booby trap: someone will hit it, not understand it, and route around it.
|
|
|
94
94
|
- [ ] The rule is written down, with the hook named next to it
|
|
95
95
|
- [ ] The hook guards **one** invariant, and its scope is as narrow as the rule
|
|
96
96
|
|
|
97
|
-
##
|
|
97
|
+
## Choosing a candidate
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
Start from a rule that already matters in this project and has been violated or
|
|
100
|
+
missed in review. Do not invent a sample architecture rule just to exercise this
|
|
101
|
+
skill: the hook must protect a real local invariant, and its test must demonstrate
|
|
102
|
+
the exact violation it blocks.
|
|
@@ -257,7 +257,7 @@ blockers.
|
|
|
257
257
|
- `security-scanner` when the diff touches auth, secrets or configuration,
|
|
258
258
|
input parsing, file handling, new outbound calls, dependency changes;
|
|
259
259
|
- `prose-reviewer` when the diff touches a rule file, a skill, an agent spec,
|
|
260
|
-
a decision record under `docs/decisions/`, `CLAUDE.md` or the README — a
|
|
260
|
+
a decision record under `docs/decisions/`, `CLAUDE.md`, `AGENTS.md` or the README — a
|
|
261
261
|
rulebook that overstates its own enforcement fails silently and in the
|
|
262
262
|
direction of false confidence;
|
|
263
263
|
- an infrastructure review when it touches infrastructure (the stack layer
|
|
@@ -12,9 +12,9 @@ directories, with one `.git`. Without it, an unattended run and a hand-driven
|
|
|
12
12
|
session share a working tree and overwrite each other's edits.
|
|
13
13
|
|
|
14
14
|
**Use one when** anything else may touch this repo while you work — an
|
|
15
|
-
unattended `loop` run, a colleague, a second Claude
|
|
16
|
-
session on a quiet repo can just use a branch; the
|
|
17
|
-
optional is the branch, not the worktree.
|
|
15
|
+
unattended `loop` run (opt-in workflow layer), a colleague, a second Claude
|
|
16
|
+
session. A single attended session on a quiet repo can just use a branch; the
|
|
17
|
+
discipline that is never optional is the branch, not the worktree.
|
|
18
18
|
|
|
19
19
|
## Start
|
|
20
20
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: code-reviewer
|
|
3
|
-
description: Reviews a completed change against the checklist before a PR is opened or merged. Use after any non-trivial implementation work, and always before opening a PR
|
|
3
|
+
description: Reviews a completed change against the checklist before a PR is opened or merged. Use after any non-trivial implementation work, and always before opening a PR that reaches the `model` lane — everything the two cheap lanes do not claim (code, a rulebook document, an unclassifiable path, a derived artifact git does not report as drift, or anything a risk flag escalated), decided by `decision-router.mjs` where the opt-in workflow layer is installed, or by the same rule applied by hand otherwise. Blocking findings must be resolved, not argued with.
|
|
4
4
|
tools: Read, Grep, Glob, Bash
|
|
5
5
|
model: claude-opus-5
|
|
6
6
|
effort: high
|
|
@@ -11,9 +11,9 @@ references, and you classify every finding as **blocking** or **advisory**.
|
|
|
11
11
|
|
|
12
12
|
## Checklist (blocking findings)
|
|
13
13
|
|
|
14
|
-
1. **Boundary violations** —
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
1. **Boundary violations** — changes that bypass module ownership or layer
|
|
15
|
+
boundaries the repository itself declares. See any applicable architecture
|
|
16
|
+
rules in `.claude/rules/`.
|
|
17
17
|
2. **Test integrity** — tests deleted, skipped, weakened, or rewritten to fit
|
|
18
18
|
the implementation; implementation without a test that demonstrates it.
|
|
19
19
|
3. **Error handling** — swallowed errors, bare catch-and-continue, failure
|
|
@@ -88,5 +88,7 @@ reads; a report that never writes one is read as whatever the caller expected.
|
|
|
88
88
|
checkout you read. It is what lets `node .claude/scripts/verdict.mjs coverage
|
|
89
89
|
<commit>` tell "this gate answered for the commit being merged" from "it
|
|
90
90
|
answered two pushes ago". A verdict naming no commit is counted as neither
|
|
91
|
-
covered nor missing, so
|
|
92
|
-
|
|
91
|
+
covered nor missing, so whoever runs that check holds on it —
|
|
92
|
+
`pr-ship` where the opt-in workflow layer is installed, the session itself
|
|
93
|
+
running `node .claude/scripts/verdict.mjs coverage` by hand otherwise: no
|
|
94
|
+
hook runs it either way, so skipping the gate skips this with it.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: implementation-agent
|
|
3
|
+
description: Writes the minimum production code that makes an existing failing test pass — the Green step of TDD, and the Refactor that follows it. Use for ordinary implementation work once test-writer has produced the failing test.
|
|
4
|
+
tools: Read, Grep, Glob, Write, Edit, Bash
|
|
5
|
+
model: claude-sonnet-5
|
|
6
|
+
effort: high
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You make a failing test pass. You are the Green step of TDD, and the Refactor
|
|
10
|
+
that keeps it green — never the Red step, and never the reviewer of your own
|
|
11
|
+
work.
|
|
12
|
+
|
|
13
|
+
## Scope — hard boundaries
|
|
14
|
+
|
|
15
|
+
- You start from a failing test that already exists. If there is none, stop
|
|
16
|
+
and say so: the test comes first, from `test-writer`.
|
|
17
|
+
- You never delete, skip, weaken or rewrite a test to make it pass. If a test
|
|
18
|
+
looks wrong, stop and surface the conflict instead of editing it.
|
|
19
|
+
- You change only what the task needs. Unrelated files, formatting sweeps and
|
|
20
|
+
speculative abstractions are out of scope.
|
|
21
|
+
- You do not commit, push, merge or open pull requests; the session that
|
|
22
|
+
dispatched you owns the branch and the gates.
|
|
23
|
+
|
|
24
|
+
## How you work
|
|
25
|
+
|
|
26
|
+
1. Read the failing test and the code around it; follow the repository's
|
|
27
|
+
rules in `AGENTS.md` and `.claude/rules/`.
|
|
28
|
+
2. Write the smallest change that makes the test pass, in the style of the
|
|
29
|
+
surrounding code.
|
|
30
|
+
3. Run the new test, then the suite, lint and typecheck the rules name.
|
|
31
|
+
Report a red check as information; never retry it until it passes.
|
|
32
|
+
4. Refactor only with the tests green, then run them again.
|
|
33
|
+
5. Report back: what you changed and why, which checks you ran with their
|
|
34
|
+
results, and anything you found but did not change.
|
|
35
|
+
|
|
36
|
+
## Judgment lines
|
|
37
|
+
|
|
38
|
+
- When the change reaches an elevated area the task was not already tiered
|
|
39
|
+
for, stop and say so before changing it.
|
|
40
|
+
- When two rules in the repository conflict, stop and name both.
|
|
41
|
+
- Prefer deleting code to adding it when both satisfy the test.
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: prose-reviewer
|
|
3
|
-
description: Reviews the documents that instruct agents — rule files, skills, agent specs, CLAUDE.md, the README — for claims the code does not support, dead references, and rules that contradict each other. Use when a change touches any of them, before the PR.
|
|
3
|
+
description: Reviews the documents that instruct agents — rule files, skills, agent specs, AGENTS.md, CLAUDE.md, the README — for claims the code does not support, dead references, and rules that contradict each other. Use when a change touches any of them, before the PR.
|
|
4
4
|
tools: Read, Grep, Glob, Bash
|
|
5
5
|
model: claude-sonnet-5
|
|
6
6
|
effort: high
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
In this project the prose **is** the implementation. A rule file is what an agent
|
|
10
|
-
reads before it acts; a skill is a procedure; `
|
|
10
|
+
reads before it acts; a skill is a procedure; `AGENTS.md` is the map (`CLAUDE.md`
|
|
11
|
+
is its short Claude Code shim — see `docs/decisions/agents-md-canonical.md`).
|
|
12
|
+
When one of
|
|
11
13
|
them says something untrue, nothing fails — the next session simply acts on it,
|
|
12
14
|
confidently, and the failure surfaces somewhere unrelated hours later.
|
|
13
15
|
|
|
@@ -177,5 +179,7 @@ calling gate reads.
|
|
|
177
179
|
checkout you read. It is what lets `node .claude/scripts/verdict.mjs coverage
|
|
178
180
|
<commit>` tell "this gate answered for the commit being merged" from "it
|
|
179
181
|
answered two pushes ago". A verdict naming no commit is counted as neither
|
|
180
|
-
covered nor missing, so
|
|
181
|
-
|
|
182
|
+
covered nor missing, so whoever runs that check holds on it —
|
|
183
|
+
`pr-ship` where the opt-in workflow layer is installed, the session itself
|
|
184
|
+
running `node .claude/scripts/verdict.mjs coverage` by hand otherwise: no
|
|
185
|
+
hook runs it either way, so skipping the gate skips this with it.
|
|
@@ -78,5 +78,7 @@ the human who has to fix the finding.
|
|
|
78
78
|
checkout you read. It is what lets `node .claude/scripts/verdict.mjs coverage
|
|
79
79
|
<commit>` tell "this gate answered for the commit being merged" from "it
|
|
80
80
|
answered two pushes ago". A verdict naming no commit is counted as neither
|
|
81
|
-
covered nor missing, so
|
|
82
|
-
|
|
81
|
+
covered nor missing, so whoever runs that check holds on it —
|
|
82
|
+
`pr-ship` where the opt-in workflow layer is installed, the session itself
|
|
83
|
+
running `node .claude/scripts/verdict.mjs coverage` by hand otherwise: no
|
|
84
|
+
hook runs it either way, so skipping the gate skips this with it.
|
|
@@ -31,8 +31,8 @@ step of TDD, and only the Red step.
|
|
|
31
31
|
|
|
32
32
|
## Judgment lines
|
|
33
33
|
|
|
34
|
-
- Test behavior through public entry points
|
|
35
|
-
internals.
|
|
34
|
+
- Test behavior through public entry points and documented interfaces, not
|
|
35
|
+
private internals.
|
|
36
36
|
- One behavior per test; shared setup in fixtures, not copy-paste.
|
|
37
37
|
- If the requested behavior contradicts an existing test, stop and surface the
|
|
38
38
|
conflict instead of overwriting the old test.
|
|
@@ -28,6 +28,22 @@
|
|
|
28
28
|
// the whole file pays for it twice. That is harness behaviour, observable but
|
|
29
29
|
// not pinned here. Where it does not hold, this is a plain subtraction — which
|
|
30
30
|
// is why every ambiguity resolves toward injecting more.
|
|
31
|
+
//
|
|
32
|
+
// The output on stdout is a single JSON object —
|
|
33
|
+
// `{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":…}}`
|
|
34
|
+
// — not the plain text an earlier version of this hook wrote directly. Both
|
|
35
|
+
// Claude Code and Codex document that shape as valid SessionStart output
|
|
36
|
+
// (Claude Code: code.claude.com/docs/en/hooks; Codex:
|
|
37
|
+
// learn.chatgpt.com/docs/hooks), and Codex additionally documents plain text
|
|
38
|
+
// as accepted for `session_start` — this hook always emits the JSON form
|
|
39
|
+
// anyway, so one code path satisfies both without guessing which harness is
|
|
40
|
+
// asking. The change exists because Codex 0.154.0 on Windows was measured
|
|
41
|
+
// reporting this hook's OLD plain-text banner as invalid SessionStart JSON,
|
|
42
|
+
// so the rules refresh never reached the session; Claude Code was unaffected.
|
|
43
|
+
// The mechanism Codex used to reach that verdict is not published — a leading
|
|
44
|
+
// `[` is a plausible trigger, not a confirmed one. See
|
|
45
|
+
// `docs/decisions/session-start-wire-format.md` for what was measured and
|
|
46
|
+
// what each harness's own documentation says.
|
|
31
47
|
import { readFileSync, realpathSync } from 'node:fs';
|
|
32
48
|
import { fileURLToPath } from 'node:url';
|
|
33
49
|
import { readHookInput } from './lib/hook-input.mjs';
|
|
@@ -187,15 +203,78 @@ function main() {
|
|
|
187
203
|
? 'This is `.claude/rules/autonomy.md` in full.\n\n'
|
|
188
204
|
: 'This is `.claude/rules/autonomy.md` with the sections it marks as ' +
|
|
189
205
|
'reference removed — read the file itself for those: how the Tier-2 ' +
|
|
190
|
-
'gate is swept from outside, how external
|
|
191
|
-
'post-deploy verification, and the escalation
|
|
206
|
+
'gate is swept from outside (opt-in workflow layer), how external ' +
|
|
207
|
+
'work is reconciled, post-deploy verification, and the escalation ' +
|
|
208
|
+
'format.\n\n';
|
|
209
|
+
|
|
210
|
+
const additionalContext =
|
|
211
|
+
`[agent-os] Autonomy rules refresh — in force regardless of compaction.\n${notice}${body}\n`;
|
|
192
212
|
|
|
213
|
+
// `hookSpecificOutput.additionalContext` is the JSON shape both harnesses'
|
|
214
|
+
// hooks documentation gives an example of for SessionStart output — see the
|
|
215
|
+
// file header and `docs/decisions/session-start-wire-format.md`. No leading
|
|
216
|
+
// or trailing byte outside the object, and no trailing newline: Claude Code's
|
|
217
|
+
// OWN documented detection reads "starts with `{` ends with `}`", literally
|
|
218
|
+
// (code.claude.com/docs/en/hooks) — Codex's JSON-vs-plain-text detection is
|
|
219
|
+
// not published, so this satisfies the one contract that IS written down
|
|
220
|
+
// rather than guessing at the one that is not.
|
|
221
|
+
// A reader that vanishes mid-write — a closed pipe, a harness that tears
|
|
222
|
+
// this process down before reading — turns the queued write into an EPIPE.
|
|
223
|
+
// That specific error is silenced: it means the reader is gone and there is
|
|
224
|
+
// nothing left to report to, so failing loudly would turn an absent reader
|
|
225
|
+
// into a noisy non-zero SessionStart exit for no one to read. Anything ELSE
|
|
226
|
+
// stdout can fail with (ENOSPC, EIO, a redirect to a full or broken device)
|
|
227
|
+
// is a real write failure with an actual reader still attached, and this
|
|
228
|
+
// file does not get to treat that as a healthy session: it is reported on
|
|
229
|
+
// stderr and the exit is marked non-zero, the same "say what happened"
|
|
230
|
+
// stance the excerpt path takes by injecting MORE rather than dropping
|
|
231
|
+
// content quietly. Measured (security review, RP-185 gate): a blanket
|
|
232
|
+
// handler here made a genuine stdout write failure (stdout redirected to
|
|
233
|
+
// /dev/full) exit 0 with nothing delivered and no diagnostic — exactly the
|
|
234
|
+
// silent-loss shape this whole file exists to avoid, just moved one write
|
|
235
|
+
// call over. Pinned in hooks.test.ts (absent in a generated rig) ›
|
|
236
|
+
// "silently exits 0 when the reader is gone before the write starts
|
|
237
|
+
// (EPIPE)" and › "reports a genuine stdout write failure on stderr and
|
|
238
|
+
// marks the exit non-zero, rather than looking like a healthy session".
|
|
239
|
+
process.stdout.on('error', (err) => {
|
|
240
|
+
if (err && err.code === 'EPIPE') return;
|
|
241
|
+
process.stderr.write(`inject-rules: stdout write failed: ${err}\n`);
|
|
242
|
+
process.exitCode = 1;
|
|
243
|
+
});
|
|
193
244
|
process.stdout.write(
|
|
194
|
-
|
|
245
|
+
JSON.stringify({
|
|
246
|
+
hookSpecificOutput: { hookEventName: 'SessionStart', additionalContext },
|
|
247
|
+
}),
|
|
195
248
|
);
|
|
196
249
|
return 0;
|
|
197
250
|
}
|
|
198
251
|
|
|
199
252
|
if (invokedDirectly()) {
|
|
200
|
-
process.exit(main())
|
|
253
|
+
// NOT process.exit(main()): exit() tears the process down without waiting
|
|
254
|
+
// for a queued stdout write to drain, and this hook's payload (the whole
|
|
255
|
+
// rules excerpt, wrapped in one JSON object) can be large enough to miss a
|
|
256
|
+
// pipe's buffer in one write. A write that process.exit() cuts off mid-object
|
|
257
|
+
// is not a short excerpt, the way the old plain-text form degraded — it is
|
|
258
|
+
// invalid JSON, which is exactly the failure this hook exists to avoid.
|
|
259
|
+
// Every path through main() returns 0, so setting exitCode changes nothing
|
|
260
|
+
// about the exit STATUS. What it does change is whether the process
|
|
261
|
+
// terminates AT ALL before the write finishes: exitCode lets the event
|
|
262
|
+
// loop drain naturally, and a reader that never drains at all no longer
|
|
263
|
+
// gets a fast, wrong exit 0 — it gets a hook that stays alive, waiting on
|
|
264
|
+
// the write, for as long as the harness lets it. A probe that refuses to
|
|
265
|
+
// read until the child would already have exited measurably DEADLOCKS this
|
|
266
|
+
// version where process.exit() would have terminated (truncated). Nothing
|
|
267
|
+
// in this file bounds that wait; the calling harness's own hook timeout
|
|
268
|
+
// does. Pinned in hooks.test.ts (absent in a generated rig) ›
|
|
269
|
+
// "delivers the whole envelope even when the reader does not drain until
|
|
270
|
+
// process.exit(main()) would already have torn the process down".
|
|
271
|
+
//
|
|
272
|
+
// That is the trade made on purpose — a loud hang, bounded by the
|
|
273
|
+
// harness's timeout, over a silent truncated "success" — and it is worth
|
|
274
|
+
// stating plainly rather than leaving to be discovered: not reachable at
|
|
275
|
+
// the size this hook ships today (a few KB, done in well under a second),
|
|
276
|
+
// but a real behaviour change on a project whose autonomy.md grows large
|
|
277
|
+
// enough, or whose harness stops reading a hook's stdout at all. See
|
|
278
|
+
// `docs/decisions/session-start-wire-format.md` for the fuller record.
|
|
279
|
+
process.exitCode = main();
|
|
201
280
|
}
|
|
@@ -37,10 +37,10 @@ area *is* Tier 2 from that moment: run the gate, record the verdict on the PR,
|
|
|
37
37
|
and say in the description that the tier changed mid-work.
|
|
38
38
|
|
|
39
39
|
**Where the elevated paths of this project are written down:** the
|
|
40
|
-
`elevated-paths` block in `
|
|
41
|
-
the gate sweep reads them all and unions
|
|
42
|
-
paths that exist only in its shape.
|
|
43
|
-
nothing checks.
|
|
40
|
+
`elevated-paths` block in `AGENTS.md` (the canonical rulebook), plus
|
|
41
|
+
any such block in `.claude/rules/` — the gate sweep reads them all and unions
|
|
42
|
+
the result, so a stack layer declares the paths that exist only in its shape.
|
|
43
|
+
A path declared in none of them is a path nothing checks.
|
|
44
44
|
|
|
45
45
|
<!-- inject:skip -->
|
|
46
46
|
<!-- `inject-rules` puts this WHOLE FILE into every session's context, minus
|
|
@@ -55,7 +55,13 @@ nothing checks.
|
|
|
55
55
|
rules for whoever performs the sweep, which is not the run. If that stops
|
|
56
56
|
being true, move them out rather than arguing with the marker. -->
|
|
57
57
|
|
|
58
|
-
#### The gate is swept from outside, because a run cannot report this on itself
|
|
58
|
+
#### The gate is swept from outside (opt-in workflow layer), because a run cannot report this on itself
|
|
59
|
+
|
|
60
|
+
**`detect-missed-gate.mjs` and `reconcile-external-prs.mjs` below ship with
|
|
61
|
+
the opt-in workflow layer** (`init --layer workflow`) — see `AGENTS.md`'s "The
|
|
62
|
+
opt-in workflow layer" section. Without that layer, sweep merged PRs against
|
|
63
|
+
the elevated-paths block by hand; the rule they enforce — a Tier-2 change
|
|
64
|
+
needs a `human-review` label — does not change with or without the script.
|
|
59
65
|
|
|
60
66
|
A run that continued past the Tier-2 gate is exactly the run that **will not
|
|
61
67
|
report it** — a run that had known was a run that would have run the gate. So the
|
|
@@ -123,11 +129,16 @@ own cost figures are read next to the lane they do not cover.
|
|
|
123
129
|
from proper-prefix widening". An entry
|
|
124
130
|
outside the set — ordinary source — is not widening and is accepted. A second
|
|
125
131
|
copy in prose is a copy that goes stale, and this one did. Mechanical:
|
|
126
|
-
the hook refuses the edit while the unattended flag
|
|
127
|
-
|
|
128
|
-
nothing in an attended session.
|
|
129
|
-
|
|
130
|
-
|
|
132
|
+
the hook refuses the edit while the unattended flag is on disk
|
|
133
|
+
(`.claude/scripts/unattended-flag.mjs`, Core — usable by hand on any rig),
|
|
134
|
+
and does nothing in an attended session. **On a Core-only rig nothing arms
|
|
135
|
+
this flag automatically** — the `loop` skill, opt-in workflow layer, is
|
|
136
|
+
what writes it at claim time; without that layer the flag is only ever set
|
|
137
|
+
by someone running `unattended-flag.mjs on` directly, so `guard-rulebook`'s
|
|
138
|
+
unattended-only refusal stays dormant unless an operator arms it by hand.
|
|
139
|
+
⚠ It sees edit tool calls only — a shell redirect into a protected file is
|
|
140
|
+
not one — and the flag, not the run, is what arms it; its header states
|
|
141
|
+
the rest of its limits.
|
|
131
142
|
|
|
132
143
|
## Stop rules — by work-state, not by feelings
|
|
133
144
|
|
|
@@ -153,16 +164,23 @@ these lines is the failure mode:
|
|
|
153
164
|
stop, write a short summary of state and intent, and **start fresh** from
|
|
154
165
|
the summary. Resuming a stale session is how agents edit files that are not
|
|
155
166
|
there anymore.
|
|
156
|
-
- **A deploy that regressed.** A green pipeline is not a healthy runtime
|
|
157
|
-
|
|
167
|
+
- **A deploy that regressed.** A green pipeline is not a healthy runtime:
|
|
168
|
+
verify runtime health after every deploy, and on a regression, **revert
|
|
169
|
+
first, diagnose second** — never fix-forward blind on a broken runtime.
|
|
170
|
+
**With the opt-in workflow layer installed** (`init --layer workflow`;
|
|
171
|
+
`run-state.mjs` ships only with it — a Core-only rig has no such file),
|
|
172
|
+
both words also get recorded as a mechanical verdict:
|
|
158
173
|
`node .claude/scripts/run-state.mjs deploy HEALTHY` or `… deploy REGRESSION`.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
174
|
+
`REGRESSION` is what makes the next selection refuse to build on it, and
|
|
175
|
+
`HEALTHY` is the only thing that clears one — a run that reverts, redeploys,
|
|
176
|
+
verifies and then stops at "healthy → done" has left the refusal latched
|
|
177
|
+
behind it. Without the layer, there is no automated selection to gate, and
|
|
178
|
+
no journal either (workflow layer only, `PLAN.md`) — the verify-then-revert
|
|
179
|
+
rule still applies, and the record of it is whatever this project's own
|
|
180
|
+
operational notes are (a PR description, a commit message, telling the
|
|
181
|
+
human directly), never a file `queue/index.mjs next` reads. The procedure
|
|
182
|
+
behind the verdict is further down this file; the verdict is here because a
|
|
183
|
+
compacted run has to carry it at the moment it is under the most pressure.
|
|
166
184
|
|
|
167
185
|
<!-- inject:skip -->
|
|
168
186
|
<!-- Not carried into a session's context (see the note on the first marked
|
|
@@ -181,19 +199,29 @@ logs — the target's README says which). The verdict is binary:
|
|
|
181
199
|
- Regression → **revert first**, diagnose second. Never fix-forward blind on a
|
|
182
200
|
broken runtime.
|
|
183
201
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
202
|
+
**`run-state.mjs` and the mechanism below ship with the opt-in workflow
|
|
203
|
+
layer** (`init --layer workflow`). The rule — verify before calling a deploy
|
|
204
|
+
done, revert first on a regression — applies regardless; without this layer
|
|
205
|
+
there is no automated selection to gate, and no journal either (workflow
|
|
206
|
+
layer only, `PLAN.md`) — recording the verdict is whatever this project's own
|
|
207
|
+
operational notes are (a PR description, a commit message, telling the human
|
|
208
|
+
directly), never a file the next `queue/index.mjs next` reads.
|
|
209
|
+
|
|
210
|
+
**Record the verdict where the next selection reads it** (opt-in workflow
|
|
211
|
+
layer), or it stops nothing — an unattended run's memory of "the deploy went
|
|
212
|
+
badly" does not survive a compaction, and the queue hands out the next item
|
|
213
|
+
regardless:
|
|
187
214
|
|
|
188
215
|
```sh
|
|
189
216
|
node .claude/scripts/run-state.mjs deploy REGRESSION # or HEALTHY
|
|
190
217
|
```
|
|
191
218
|
|
|
192
|
-
It writes into the run directory the `loop` skill
|
|
193
|
-
`queue/index.mjs next` refuses to select on a
|
|
194
|
-
"start no new work on top of it" a
|
|
195
|
-
|
|
196
|
-
correct: there is no run for the
|
|
219
|
+
It writes into the run directory the `loop` skill (opt-in workflow layer)
|
|
220
|
+
declared, and the next `queue/index.mjs next` refuses to select on a
|
|
221
|
+
`REGRESSION` — which is what makes "start no new work on top of it" a
|
|
222
|
+
mechanism rather than a resolution. In an attended session with no run
|
|
223
|
+
directory the command refuses, and that is correct: there is no run for the
|
|
224
|
+
verdict to belong to.
|
|
197
225
|
|
|
198
226
|
## Escalation format
|
|
199
227
|
|
|
@@ -201,14 +201,15 @@ Two rules that follow from it:
|
|
|
201
201
|
| the check | `.claude/hooks/block-no-verify.mjs` |
|
|
202
202
|
| the test | the hook's blocking behaviour, under test |
|
|
203
203
|
|
|
204
|
-
**Every one of them is an example, not a truth.** Take
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
inherited
|
|
204
|
+
**Every one of them is an example, not a truth.** Take a rule like
|
|
205
|
+
`guard-core-purity` — "the domain core is pure". It is a good rule for a
|
|
206
|
+
project shaped with a pure domain core; it is not a law of software, and this
|
|
207
|
+
rig ships none of its own — a rig that configures agent harnesses makes no
|
|
208
|
+
promise about application architecture. Where a project has no pure core — a
|
|
209
|
+
thin CRUD service, a CLI, a data pipeline — the right move is not to borrow one
|
|
210
|
+
anyway: write the invariant the project actually has, with its own hook and
|
|
211
|
+
its own test. An inherited rule nobody chose is worse than an empty rule file:
|
|
212
|
+
the empty one is visibly incomplete, the inherited one is invisibly wrong.
|
|
212
213
|
|
|
213
214
|
The invariants worth your slots are the ones you can finish this sentence about:
|
|
214
215
|
*"the last time this went wrong, it cost us ___."* If you cannot finish it, you
|