create-agent-rig 0.9.1 → 0.10.1

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.
Files changed (235) hide show
  1. package/CHANGELOG.md +462 -3
  2. package/README.md +267 -305
  3. package/package.json +8 -14
  4. package/packages/cli/dist/commands/create.js +56 -88
  5. package/packages/cli/dist/commands/doctor.js +213 -0
  6. package/packages/cli/dist/commands/init.js +111 -50
  7. package/packages/cli/dist/commands/integrations.js +468 -0
  8. package/packages/cli/dist/commands/setup-wizard.js +61 -0
  9. package/packages/cli/dist/commands/uninstall.js +1223 -0
  10. package/packages/cli/dist/commands/upgrade.js +508 -101
  11. package/packages/cli/dist/index.js +658 -47
  12. package/packages/cli/dist/integrations/declaration.js +158 -0
  13. package/packages/cli/dist/integrations/doctor-guards.js +126 -0
  14. package/packages/cli/dist/integrations/doctor-workflow.js +25 -0
  15. package/packages/cli/dist/integrations/mcp-json.js +107 -0
  16. package/packages/cli/dist/integrations/memory-doctor.js +124 -0
  17. package/packages/cli/dist/integrations/registry.js +22 -0
  18. package/packages/cli/dist/integrations/spawn.js +228 -0
  19. package/packages/cli/dist/integrations/spec-kit.js +280 -0
  20. package/packages/cli/dist/integrations/verify.js +193 -0
  21. package/packages/cli/dist/integrations/windows-job.js +275 -0
  22. package/packages/cli/dist/lib/elevated-paths.js +74 -0
  23. package/packages/cli/dist/lib/install-set.js +1 -44
  24. package/packages/cli/dist/lib/manifest.js +64 -5
  25. package/packages/cli/dist/lib/prompts.js +0 -23
  26. package/packages/cli/dist/lib/safe-path.js +193 -2
  27. package/packages/cli/dist/lib/safe-text.js +78 -0
  28. package/packages/cli/dist/lib/substitute.js +1 -52
  29. package/packages/cli/dist/lib/summary.js +5 -5
  30. package/packages/cli/dist/templates.js +4 -14
  31. package/scripts/prepare.mjs +28 -12
  32. package/templates/agent-os/subagent-routing.json +4 -4
  33. package/templates/agent-os/universal/.agents/skills/check-premises/SKILL.md +45 -12
  34. package/templates/agent-os/universal/.agents/skills/loop/SKILL.md +31 -6
  35. package/templates/agent-os/universal/.agents/skills/new-invariant/SKILL.md +5 -5
  36. package/templates/agent-os/universal/.agents/skills/pr-ship/SKILL.md +1 -1
  37. package/templates/agent-os/universal/.agents/skills/worktree-task/SKILL.md +3 -3
  38. package/templates/agent-os/universal/.claude/agents/code-reviewer.md +8 -6
  39. package/templates/agent-os/universal/.claude/agents/implementation-agent.md +41 -0
  40. package/templates/agent-os/universal/.claude/agents/prose-reviewer.md +8 -4
  41. package/templates/agent-os/universal/.claude/agents/security-scanner.md +4 -2
  42. package/templates/agent-os/universal/.claude/agents/test-writer.md +2 -2
  43. package/templates/agent-os/universal/.claude/hooks/gate-stop-dod.mjs +4 -2
  44. package/templates/agent-os/universal/.claude/hooks/inject-rules.mjs +83 -4
  45. package/templates/agent-os/universal/.claude/rules/autonomy.md +55 -27
  46. package/templates/agent-os/universal/.claude/rules/invariants.md +9 -8
  47. package/templates/agent-os/universal/.claude/rules/workflow.md +59 -22
  48. package/templates/agent-os/universal/.claude/scripts/decision-router.mjs +1 -1
  49. package/templates/agent-os/universal/.claude/scripts/detect-missed-gate.mjs +12 -9
  50. package/templates/agent-os/universal/.claude/scripts/doctor.mjs +100 -2
  51. package/templates/agent-os/universal/.claude/scripts/lib/claim-records.mjs +236 -6
  52. package/templates/agent-os/universal/.claude/scripts/queue/state.mjs +2 -2
  53. package/templates/agent-os/universal/.claude/scripts/reconcile-external-prs.mjs +4 -3
  54. package/templates/agent-os/universal/.claude/scripts/revalidate.mjs +16 -0
  55. package/templates/agent-os/universal/.claude/settings.json +0 -8
  56. package/templates/agent-os/universal/.claude/skills/check-premises/SKILL.md +45 -12
  57. package/templates/agent-os/universal/.claude/skills/loop/SKILL.md +31 -6
  58. package/templates/agent-os/universal/.claude/skills/new-invariant/SKILL.md +5 -5
  59. package/templates/agent-os/universal/.claude/skills/pr-ship/SKILL.md +1 -1
  60. package/templates/agent-os/universal/.claude/skills/worktree-task/SKILL.md +3 -3
  61. package/templates/agent-os/universal/.codex/agents/code-reviewer.toml +2 -2
  62. package/templates/agent-os/universal/.codex/agents/implementation-agent.toml +6 -0
  63. package/templates/agent-os/universal/.codex/agents/prose-reviewer.toml +2 -2
  64. package/templates/agent-os/universal/.codex/agents/security-scanner.toml +1 -1
  65. package/templates/agent-os/universal/.codex/agents/test-writer.toml +1 -1
  66. package/templates/agent-os/universal/.codex/hooks.json +0 -10
  67. package/templates/agent-os/universal/AGENTS.md +208 -107
  68. package/templates/agent-os/universal/CLAUDE.md +15 -162
  69. package/templates/agent-os/universal/PLAN.md +17 -10
  70. package/templates/agent-os/universal/docs/decisions/agents-md-canonical.md +313 -0
  71. package/templates/agent-os/universal/docs/decisions/codex-adapter.md +15 -10
  72. package/templates/agent-os/universal/docs/decisions/review-lanes.md +12 -8
  73. package/templates/agent-os/universal/docs/decisions/session-start-wire-format.md +206 -0
  74. package/templates/agent-os/universal/docs/decisions/subagent-routing.md +6 -3
  75. package/templates/agent-os/universal/docs/decisions/workflow-layer-split.md +235 -0
  76. package/templates/agent-os/universal/layers.json +25 -30
  77. package/templates/hash-history.json +112 -40
  78. package/templates/release-ledger.json +3 -1
  79. package/packages/cli/dist/lib/composition.js +0 -20
  80. package/packages/cli/dist/lib/targets.js +0 -28
  81. package/packages/cli/dist/policy/benchmark/corpus.js +0 -165
  82. package/packages/cli/dist/policy/core/adapter.js +0 -18
  83. package/packages/cli/dist/policy/core/coverage.js +0 -253
  84. package/packages/cli/dist/policy/core/decision-record.js +0 -287
  85. package/packages/cli/dist/policy/core/declaration.js +0 -127
  86. package/packages/cli/dist/policy/core/evidence-matrix.js +0 -94
  87. package/packages/cli/dist/policy/core/probe.js +0 -442
  88. package/packages/cli/dist/policy/core/registry.js +0 -115
  89. package/packages/cli/dist/policy/core/validation.js +0 -275
  90. package/packages/cli/dist/policy/core/vocabulary.js +0 -123
  91. package/packages/cli/dist/policy/harness/claude.js +0 -47
  92. package/packages/cli/dist/policy/harness/codex.js +0 -87
  93. package/packages/cli/dist/policy/harness/index.js +0 -15
  94. package/packages/cli/dist/policy/harness/shared-hooks.js +0 -28
  95. package/packages/cli/dist/policy/index.js +0 -17
  96. package/templates/agent-os/init/AGENTS.md +0 -201
  97. package/templates/agent-os/init/CLAUDE.md +0 -201
  98. package/templates/agent-os/stack/aws-cdk/.agents/skills/post-deploy-verify/SKILL.md +0 -105
  99. package/templates/agent-os/stack/aws-cdk/.agents/skills/ro-debug/SKILL.md +0 -117
  100. package/templates/agent-os/stack/aws-cdk/.claude/agents/cdk-diff-reviewer.md +0 -89
  101. package/templates/agent-os/stack/aws-cdk/.claude/rules/aws-cdk.md +0 -105
  102. package/templates/agent-os/stack/aws-cdk/.claude/skills/post-deploy-verify/SKILL.md +0 -105
  103. package/templates/agent-os/stack/aws-cdk/.claude/skills/ro-debug/SKILL.md +0 -117
  104. package/templates/agent-os/stack/aws-cdk/.codex/agents/cdk-diff-reviewer.toml +0 -6
  105. package/templates/agent-os/stack/node-ts/.claude/hooks/dod-checks.json +0 -1
  106. package/templates/agent-os/stack/node-ts/.claude/rules/node-ts.md +0 -85
  107. package/templates/agent-os/universal/.claude/hooks/guard-core-purity.mjs +0 -89
  108. package/templates/agent-os/universal/.claude/hooks/guard-web-boundary.mjs +0 -68
  109. package/templates/agent-os/universal/.claude/rules/architecture.md +0 -81
  110. package/templates/skeleton/aws-serverless/.github/workflows/ci.yml +0 -28
  111. package/templates/skeleton/aws-serverless/.github/workflows/deploy.yml +0 -90
  112. package/templates/skeleton/aws-serverless/README.md +0 -181
  113. package/templates/skeleton/aws-serverless/apps/web/next.config.mjs +0 -17
  114. package/templates/skeleton/aws-serverless/apps/web/package.json +0 -19
  115. package/templates/skeleton/aws-serverless/apps/web/src/app/layout.tsx +0 -17
  116. package/templates/skeleton/aws-serverless/apps/web/src/app/page.tsx +0 -96
  117. package/templates/skeleton/aws-serverless/apps/web/src/lib/api.ts +0 -36
  118. package/templates/skeleton/aws-serverless/apps/web/src/lib/validate.ts +0 -23
  119. package/templates/skeleton/aws-serverless/apps/web/test/shared-validation.test.ts +0 -38
  120. package/templates/skeleton/aws-serverless/apps/web/tsconfig.json +0 -14
  121. package/templates/skeleton/aws-serverless/eslint.config.mjs +0 -20
  122. package/templates/skeleton/aws-serverless/gitignore +0 -56
  123. package/templates/skeleton/aws-serverless/infra/bin/app.ts +0 -79
  124. package/templates/skeleton/aws-serverless/infra/cdk.json +0 -3
  125. package/templates/skeleton/aws-serverless/infra/lib/app-stack.ts +0 -248
  126. package/templates/skeleton/aws-serverless/infra/lib/web-stack.ts +0 -45
  127. package/templates/skeleton/aws-serverless/infra/package.json +0 -18
  128. package/templates/skeleton/aws-serverless/infra/test/allowed-origins.test.ts +0 -301
  129. package/templates/skeleton/aws-serverless/infra/test/app-composition.test.ts +0 -137
  130. package/templates/skeleton/aws-serverless/infra/test/app-stack.test.ts +0 -120
  131. package/templates/skeleton/aws-serverless/infra/test/web-stack.test.ts +0 -44
  132. package/templates/skeleton/aws-serverless/package.json +0 -30
  133. package/templates/skeleton/aws-serverless/packages/core/package.json +0 -11
  134. package/templates/skeleton/aws-serverless/packages/core/src/events.ts +0 -14
  135. package/templates/skeleton/aws-serverless/packages/core/src/index.ts +0 -15
  136. package/templates/skeleton/aws-serverless/packages/core/src/note.ts +0 -69
  137. package/templates/skeleton/aws-serverless/packages/core/test/events.test.ts +0 -23
  138. package/templates/skeleton/aws-serverless/packages/core/test/note.test.ts +0 -101
  139. package/templates/skeleton/aws-serverless/packages/db/package.json +0 -14
  140. package/templates/skeleton/aws-serverless/packages/db/src/client.ts +0 -17
  141. package/templates/skeleton/aws-serverless/packages/db/src/index.ts +0 -2
  142. package/templates/skeleton/aws-serverless/packages/db/src/note-model.ts +0 -52
  143. package/templates/skeleton/aws-serverless/packages/db/test/note-model.test.ts +0 -91
  144. package/templates/skeleton/aws-serverless/packages/shared/package.json +0 -11
  145. package/templates/skeleton/aws-serverless/packages/shared/src/env.ts +0 -17
  146. package/templates/skeleton/aws-serverless/packages/shared/src/errors.ts +0 -33
  147. package/templates/skeleton/aws-serverless/packages/shared/src/index.ts +0 -3
  148. package/templates/skeleton/aws-serverless/packages/shared/src/logger.ts +0 -20
  149. package/templates/skeleton/aws-serverless/packages/shared/test/env.test.ts +0 -26
  150. package/templates/skeleton/aws-serverless/packages/shared/test/errors.test.ts +0 -28
  151. package/templates/skeleton/aws-serverless/packages/shared/test/logger.test.ts +0 -19
  152. package/templates/skeleton/aws-serverless/pnpm-lock.yaml +0 -2855
  153. package/templates/skeleton/aws-serverless/pnpm-workspace.yaml +0 -14
  154. package/templates/skeleton/aws-serverless/services/api/package.json +0 -15
  155. package/templates/skeleton/aws-serverless/services/api/src/adapters/sqs-publisher.ts +0 -26
  156. package/templates/skeleton/aws-serverless/services/api/src/handlers/create-note.ts +0 -69
  157. package/templates/skeleton/aws-serverless/services/api/src/handlers/list-notes.ts +0 -37
  158. package/templates/skeleton/aws-serverless/services/api/src/list-main.ts +0 -12
  159. package/templates/skeleton/aws-serverless/services/api/src/main.ts +0 -21
  160. package/templates/skeleton/aws-serverless/services/api/src/usecases/create-note.ts +0 -41
  161. package/templates/skeleton/aws-serverless/services/api/src/usecases/list-notes.ts +0 -14
  162. package/templates/skeleton/aws-serverless/services/api/test/create-note.handler.test.ts +0 -211
  163. package/templates/skeleton/aws-serverless/services/api/test/create-note.usecase.test.ts +0 -45
  164. package/templates/skeleton/aws-serverless/services/api/test/list-notes.test.ts +0 -122
  165. package/templates/skeleton/aws-serverless/services/api/test/sqs-publisher.test.ts +0 -22
  166. package/templates/skeleton/aws-serverless/services/worker/package.json +0 -12
  167. package/templates/skeleton/aws-serverless/services/worker/src/handlers/note-created.ts +0 -15
  168. package/templates/skeleton/aws-serverless/services/worker/src/main.ts +0 -7
  169. package/templates/skeleton/aws-serverless/services/worker/src/usecases/process-note-created.ts +0 -37
  170. package/templates/skeleton/aws-serverless/services/worker/test/note-created.test.ts +0 -61
  171. package/templates/skeleton/aws-serverless/tsconfig.base.json +0 -15
  172. package/templates/skeleton/aws-serverless/tsconfig.json +0 -16
  173. package/templates/skeleton/aws-serverless/vitest.config.ts +0 -14
  174. package/templates/skeleton/node-service/.github/workflows/ci.yml +0 -27
  175. package/templates/skeleton/node-service/.github/workflows/deploy.yml +0 -29
  176. package/templates/skeleton/node-service/README.md +0 -104
  177. package/templates/skeleton/node-service/apps/web/next.config.mjs +0 -17
  178. package/templates/skeleton/node-service/apps/web/package.json +0 -19
  179. package/templates/skeleton/node-service/apps/web/src/app/layout.tsx +0 -17
  180. package/templates/skeleton/node-service/apps/web/src/app/page.tsx +0 -96
  181. package/templates/skeleton/node-service/apps/web/src/lib/api.ts +0 -29
  182. package/templates/skeleton/node-service/apps/web/src/lib/validate.ts +0 -23
  183. package/templates/skeleton/node-service/apps/web/test/shared-validation.test.ts +0 -38
  184. package/templates/skeleton/node-service/apps/web/tsconfig.json +0 -14
  185. package/templates/skeleton/node-service/eslint.config.mjs +0 -20
  186. package/templates/skeleton/node-service/gitignore +0 -54
  187. package/templates/skeleton/node-service/package.json +0 -30
  188. package/templates/skeleton/node-service/packages/core/package.json +0 -11
  189. package/templates/skeleton/node-service/packages/core/src/events.ts +0 -14
  190. package/templates/skeleton/node-service/packages/core/src/index.ts +0 -15
  191. package/templates/skeleton/node-service/packages/core/src/note.ts +0 -69
  192. package/templates/skeleton/node-service/packages/core/test/events.test.ts +0 -23
  193. package/templates/skeleton/node-service/packages/core/test/note.test.ts +0 -101
  194. package/templates/skeleton/node-service/packages/db/package.json +0 -12
  195. package/templates/skeleton/node-service/packages/db/src/index.ts +0 -1
  196. package/templates/skeleton/node-service/packages/db/src/note-store.ts +0 -100
  197. package/templates/skeleton/node-service/packages/db/test/note-store.test.ts +0 -100
  198. package/templates/skeleton/node-service/packages/shared/package.json +0 -11
  199. package/templates/skeleton/node-service/packages/shared/src/env.ts +0 -17
  200. package/templates/skeleton/node-service/packages/shared/src/errors.ts +0 -33
  201. package/templates/skeleton/node-service/packages/shared/src/index.ts +0 -3
  202. package/templates/skeleton/node-service/packages/shared/src/logger.ts +0 -20
  203. package/templates/skeleton/node-service/packages/shared/test/env.test.ts +0 -26
  204. package/templates/skeleton/node-service/packages/shared/test/errors.test.ts +0 -28
  205. package/templates/skeleton/node-service/packages/shared/test/logger.test.ts +0 -19
  206. package/templates/skeleton/node-service/pnpm-lock.yaml +0 -2402
  207. package/templates/skeleton/node-service/pnpm-workspace.yaml +0 -13
  208. package/templates/skeleton/node-service/scripts/build-artifact.mjs +0 -34
  209. package/templates/skeleton/node-service/services/api/package.json +0 -17
  210. package/templates/skeleton/node-service/services/api/src/adapters/spool-publisher.ts +0 -23
  211. package/templates/skeleton/node-service/services/api/src/handlers/create-note.ts +0 -40
  212. package/templates/skeleton/node-service/services/api/src/handlers/list-notes.ts +0 -23
  213. package/templates/skeleton/node-service/services/api/src/main.ts +0 -40
  214. package/templates/skeleton/node-service/services/api/src/server.ts +0 -172
  215. package/templates/skeleton/node-service/services/api/src/static-dir.ts +0 -20
  216. package/templates/skeleton/node-service/services/api/src/usecases/create-note.ts +0 -30
  217. package/templates/skeleton/node-service/services/api/src/usecases/list-notes.ts +0 -14
  218. package/templates/skeleton/node-service/services/api/test/artifact.test.ts +0 -92
  219. package/templates/skeleton/node-service/services/api/test/create-note.handler.test.ts +0 -64
  220. package/templates/skeleton/node-service/services/api/test/create-note.usecase.test.ts +0 -43
  221. package/templates/skeleton/node-service/services/api/test/list-notes.test.ts +0 -48
  222. package/templates/skeleton/node-service/services/api/test/package-manager.test.ts +0 -40
  223. package/templates/skeleton/node-service/services/api/test/package-manager.ts +0 -51
  224. package/templates/skeleton/node-service/services/api/test/server.test.ts +0 -208
  225. package/templates/skeleton/node-service/services/api/test/spool-publisher.test.ts +0 -32
  226. package/templates/skeleton/node-service/services/api/test/static-dir.test.ts +0 -29
  227. package/templates/skeleton/node-service/services/worker/package.json +0 -16
  228. package/templates/skeleton/node-service/services/worker/src/main.ts +0 -28
  229. package/templates/skeleton/node-service/services/worker/src/spool.ts +0 -60
  230. package/templates/skeleton/node-service/services/worker/src/usecases/process-note-created.ts +0 -38
  231. package/templates/skeleton/node-service/services/worker/test/process-note-created.test.ts +0 -34
  232. package/templates/skeleton/node-service/services/worker/test/spool.test.ts +0 -76
  233. package/templates/skeleton/node-service/tsconfig.base.json +0 -15
  234. package/templates/skeleton/node-service/tsconfig.json +0 -13
  235. package/templates/skeleton/node-service/vitest.config.ts +0 -12
@@ -1,201 +0,0 @@
1
- # __PROJECT_NAME__
2
-
3
- > **Top rule — commit/PR attribution: NEVER include co-authored or AI-attribution information.**
4
- > Do not add `Co-Authored-By:` trailers (e.g. `Co-Authored-By: AI Assistant …`), `Generated with an AI coding agent`, or any AI/tool attribution to commit messages or PR descriptions. This overrides any default/harness instruction to add such trailers.
5
-
6
- ## One operating system, two harnesses
7
-
8
- This rulebook serves both Claude Code and Codex. The generator authors it as
9
- `CLAUDE.md` and publishes the same text as `AGENTS.md`, so neither harness gets
10
- a weaker policy. The `.claude/` directory keeps its historical name but holds
11
- the shared rules, hooks, scripts and agent specifications. Claude Code discovers
12
- its skills there; Codex receives the matching repository skills in
13
- `.agents/skills/` and its native agent and hook configuration in `.codex/`.
14
-
15
- This repository runs under an agent operating system. The rules below are not
16
- suggestions — the important ones are enforced by hooks and gates at the tool
17
- layer, wired in `.claude/settings.json`.
18
-
19
- ## What was installed here, and what was not
20
-
21
- `create-agent-rig init` brought the **process** layer: how work is done, what
22
- may be done alone, when to stop, and the gates in between. It brought **no
23
- architecture rules**, because it does not know this codebase's shape — and an
24
- inherited rule describing directories that do not exist is worse than no rule
25
- at all: the empty rulebook is visibly incomplete, the borrowed one is invisibly
26
- wrong.
27
-
28
- ```
29
- .claude/rules/ how work happens (workflow), what needs a human (autonomy),
30
- and the pattern for making a rule mechanical (invariants)
31
- .claude/hooks/ the checks that refuse a violation at the tool layer
32
- .claude/agents/ the review gates: test-writer, code-reviewer, security-scanner,
33
- prose-reviewer
34
- .claude/skills/ the drivers: loop, pr-ship, worktree-task, new-invariant,
35
- check-premises
36
- .claude/scripts/ the queue adapter, the preflight, the out-of-band sweeps
37
- ```
38
-
39
- **The architecture rules of this project are yours to write.** When this repo
40
- has a boundary worth stating — a layer that must not import another, a module
41
- that owns an SDK, a directory that stays pure — state it in a new file under
42
- `.claude/rules/`, name it from this section, and if it is worth enforcing, give
43
- it a hook via the `new-invariant` skill.
44
-
45
- ## If you read only three sections, read these
46
-
47
- 1. **Autonomy tiers** — what you may do alone vs. propose first:
48
- `.claude/rules/autonomy.md` ("Tiers")
49
- 2. **Stop rules** — when stopping with a diagnosis is the correct move:
50
- `.claude/rules/autonomy.md` ("Stop rules")
51
- 3. **Definition of Done** — the checklist a change must pass:
52
- `.claude/rules/workflow.md` ("Definition of Done")
53
-
54
- ## How work happens here
55
-
56
- - **TDD, without exception.** The failing test comes first — use the
57
- `test-writer` agent for it. See `.claude/rules/workflow.md`.
58
- - **One task, one branch — and merge via PR.** Every unit of work gets its own
59
- short-lived branch; the default branch is never committed to directly. Once
60
- the project has a remote and CI, changes reach it through the PR flow (local
61
- checks → reviewer fan-out → merge on an explicit criterion). See
62
- `.claude/rules/workflow.md` ("Branches and commits", "PR flow"). When another
63
- session may touch this repo at the same time, the branch lives in its own
64
- worktree — the `worktree-task` skill has the lifecycle and the cleanup.
65
- - **Gates.** Every PR is routed before it is reviewed — the
66
- `decision-router` picks the cheapest lane the change earns
67
- (`deterministic` → `fast-path` → `model`), and risk flags escalate ahead of
68
- all three. `code-reviewer` runs on the `model` lane, which is **everything the
69
- two cheap lanes did not claim** — code, a rulebook document, an unclassifiable
70
- path, a derived artifact git does not report as drift, or anything a risk flag
71
- escalated;
72
- `security-scanner` when a change touches auth, secrets, parsing, or outbound
73
- calls; `prose-reviewer` when it touches the documents that instruct agents —
74
- rules, skills, agent specs, this file, the README. Those last two are
75
- **lane-independent and may only add** — the lane is a floor, never a ceiling.
76
- `.claude/rules/workflow.md` carries the ladder and what the cheap lanes give
77
- up. Blocking findings are resolved, not argued with, and the
78
- `pr-ship` skill drives the fan-out. **No hook launches them** — a gate here is
79
- a session following a written rule, so "the gate ran" is a claim, not a
80
- guarantee. That is the honest reading of every gate in this file.
81
- - **Enforcement is mechanical.** `guard-secret-file` refuses an edit that writes
82
- a credential — by the file's name or by a value in its text, from the one
83
- vocabulary in `.claude/scripts/lib/secrets.mjs`; `block-no-verify` refuses
84
- pre-commit bypasses;
85
- `guard-bash` refuses the "Never" tier — force-pushing a shared branch, a
86
- production deploy, a filesystem wipe — and carries the kill switch;
87
- `gate-stop-dod` refuses to end the session while a Definition-of-Done check
88
- fails; `inject-rules` puts the autonomy rules back in front of the agent at
89
- the start of every session, minus the parts that file marks as reference. If a hook blocks you, fix the cause; never route
90
- around a hook.
91
- - **Enforcement is a pattern you can apply again.** Each of those hooks is one
92
- stated invariant + one mechanical check + one test — the pattern is written
93
- down in `.claude/rules/invariants.md`, and the `new-invariant` skill walks you
94
- through adding one. The hooks that ship here are **examples, not laws**: if the
95
- invariant they guard is not load-bearing in this project, delete it and spend
96
- the slot on one that is.
97
- - **There is a brake, and it is a real file.** `touch
98
- ~/.claude/__PROJECT_NAME__-loop-STOP` and `guard-bash` denies every merge
99
- until it is removed. Everything short of the merge stays allowed on purpose:
100
- finish the task, push the branch, open the PR, write the journal, stop.
101
- Stopping cleanly never means losing the work.
102
- - **Work comes from the queue, through an adapter.** The `loop` skill selects via
103
- `.claude/scripts/queue/index.mjs`, which reads whichever queue
104
- `.claude/queue.json` names — the Agent queue in `PLAN.md` by default, issues in
105
- this repository once it has a remote. An empty queue **ends the session**; it is
106
- never a cue to invent work, and the agent never files its own work items.
107
-
108
- ## Four things this install left for you to finish
109
-
110
- All four are one-liners, and all four are inert until you do them.
111
-
112
- 1. **The Definition-of-Done gate has nothing to run.** `gate-stop-dod` executes
113
- the commands listed in `.claude/hooks/dod-checks.json`, and `init` ships no
114
- such file because it cannot know this project's commands. Until you write one
115
- — a JSON array like `["npm test", "npm run lint"]` — the stop gate is a
116
- no-op, and the Definition of Done is back to being a wish.
117
- 2. **The elevated-path list below is a seed, not a survey.** It names only what
118
- every repo has. Everything else is yours to add.
119
- 3. **Five runtime paths need a `.gitignore` line each**, and `init` cannot add
120
- them — it installs into your repository and does not edit files it did not
121
- bring. If any are missing, add only the missing entries:
122
-
123
- ```
124
- # the tier the last close recorded
125
- .claude/queue.state.json
126
- # the board this checkout runs on, when the config declares several
127
- .claude/queue.board
128
- # gate rounds, one count per branch
129
- .claude/gate-rounds.json
130
- # task worktrees
131
- .claude/worktrees/
132
- # the run journal's per-run trace
133
- .claude/runs/
134
- ```
135
- Each comment is on its own line, and that is not formatting: git treats `#`
136
- as a comment **only at line start**, so a trailing `# …` becomes part of the
137
- pattern and the line then ignores nothing. It fails silently — you find out
138
- when the file lands in a commit.
139
-
140
- The first one matters more than it looks. It is how the loop rations the
141
- elevated tier — never two elevated items back to back, where the tier that
142
- spaces is the one that EXECUTES (a close whose elevated paths are all
143
- documents records `elevated-prose` and clears the ration) — and it is
144
- **per-checkout state, not shared configuration**. Committed, one machine's
145
- tier starts deciding another's, and a merge conflict lands in a file nobody
146
- edited on purpose. `.claude/queue.json` is the opposite: that one is
147
- configuration and belongs in the repository.
148
-
149
- 4. **`doctor` reads two files this install does not ship.**
150
- `node .claude/scripts/doctor.mjs` decides who owns each hook from
151
- `.claude/.rig-manifest.json` — which `init` wrote next to the files it
152
- installed, so commit it — and reads exemptions from
153
- `.claude/doctor-exemptions.json`, a file you author (`{ "<path>": "<reason>" }`)
154
- only when a hook you own is deliberately left without a test neighbour.
155
- Without the manifest every hook that has no test neighbour reports `unknown`,
156
- which is not a pass.
157
-
158
- ## The elevated paths of this project
159
-
160
- Tier 2 in `.claude/rules/autonomy.md` names *kinds* of change. This block names
161
- the **paths** in this repository where those kinds live, and
162
- `.claude/scripts/detect-missed-gate.mjs` reads it — so a path that is not declared
163
- is a path the gate sweep cannot see.
164
-
165
- ```elevated-paths
166
- .claude/
167
- .agents/
168
- .codex/
169
- AGENTS.md
170
- .github/workflows/
171
- ```
172
-
173
- They are there because they are what *disarms* the rest: a merge that rewrites
174
- the Never tier, unwires a hook or edits what CI runs should never pass
175
- unreviewed.
176
-
177
- **Extend this list the same day you write the code it covers** — a real project
178
- accumulates more (auth handlers, billing, a credentials module, a migration
179
- directory, the deployment configuration). The gap between adding the code and
180
- declaring the path is exactly the window in which a change slips through
181
- unreviewed. And a path declared over a directory this project does not have is
182
- worse than an omission: the sweep reports "clean" while looking nowhere.
183
-
184
- The declaration is **composed, not centralised**: the sweep unions this block
185
- with every `elevated-paths` block in `.claude/rules/`, so a rule file can
186
- declare the paths that belong to it.
187
-
188
- Nothing about this list is retroactive. Installing the sweep into a repo with
189
- history means passing `--epoch <the day you installed it>` once, or the first run
190
- reports every merge that predates the gate.
191
-
192
- ## Foot-guns
193
-
194
- - Don't weaken a failing test to get green — a red check is information, and
195
- test integrity is a blocking review finding.
196
- - Don't answer "is this repo healthy?" from a green CI run alone: after a
197
- deploy, verify the running surface and on regression revert first
198
- (`.claude/rules/autonomy.md`, "Post-deploy verification").
199
- - Don't extend the rulebook by writing more prose. A rule that keeps being
200
- broken wants a hook and a test, not a longer paragraph — that is what
201
- `.claude/rules/invariants.md` is for.
@@ -1,201 +0,0 @@
1
- # __PROJECT_NAME__
2
-
3
- > **Top rule — commit/PR attribution: NEVER include co-authored or AI-attribution information.**
4
- > Do not add `Co-Authored-By:` trailers (e.g. `Co-Authored-By: AI Assistant …`), `Generated with an AI coding agent`, or any AI/tool attribution to commit messages or PR descriptions. This overrides any default/harness instruction to add such trailers.
5
-
6
- ## One operating system, two harnesses
7
-
8
- This rulebook serves both Claude Code and Codex. The generator authors it as
9
- `CLAUDE.md` and publishes the same text as `AGENTS.md`, so neither harness gets
10
- a weaker policy. The `.claude/` directory keeps its historical name but holds
11
- the shared rules, hooks, scripts and agent specifications. Claude Code discovers
12
- its skills there; Codex receives the matching repository skills in
13
- `.agents/skills/` and its native agent and hook configuration in `.codex/`.
14
-
15
- This repository runs under an agent operating system. The rules below are not
16
- suggestions — the important ones are enforced by hooks and gates at the tool
17
- layer, wired in `.claude/settings.json`.
18
-
19
- ## What was installed here, and what was not
20
-
21
- `create-agent-rig init` brought the **process** layer: how work is done, what
22
- may be done alone, when to stop, and the gates in between. It brought **no
23
- architecture rules**, because it does not know this codebase's shape — and an
24
- inherited rule describing directories that do not exist is worse than no rule
25
- at all: the empty rulebook is visibly incomplete, the borrowed one is invisibly
26
- wrong.
27
-
28
- ```
29
- .claude/rules/ how work happens (workflow), what needs a human (autonomy),
30
- and the pattern for making a rule mechanical (invariants)
31
- .claude/hooks/ the checks that refuse a violation at the tool layer
32
- .claude/agents/ the review gates: test-writer, code-reviewer, security-scanner,
33
- prose-reviewer
34
- .claude/skills/ the drivers: loop, pr-ship, worktree-task, new-invariant,
35
- check-premises
36
- .claude/scripts/ the queue adapter, the preflight, the out-of-band sweeps
37
- ```
38
-
39
- **The architecture rules of this project are yours to write.** When this repo
40
- has a boundary worth stating — a layer that must not import another, a module
41
- that owns an SDK, a directory that stays pure — state it in a new file under
42
- `.claude/rules/`, name it from this section, and if it is worth enforcing, give
43
- it a hook via the `new-invariant` skill.
44
-
45
- ## If you read only three sections, read these
46
-
47
- 1. **Autonomy tiers** — what you may do alone vs. propose first:
48
- `.claude/rules/autonomy.md` ("Tiers")
49
- 2. **Stop rules** — when stopping with a diagnosis is the correct move:
50
- `.claude/rules/autonomy.md` ("Stop rules")
51
- 3. **Definition of Done** — the checklist a change must pass:
52
- `.claude/rules/workflow.md` ("Definition of Done")
53
-
54
- ## How work happens here
55
-
56
- - **TDD, without exception.** The failing test comes first — use the
57
- `test-writer` agent for it. See `.claude/rules/workflow.md`.
58
- - **One task, one branch — and merge via PR.** Every unit of work gets its own
59
- short-lived branch; the default branch is never committed to directly. Once
60
- the project has a remote and CI, changes reach it through the PR flow (local
61
- checks → reviewer fan-out → merge on an explicit criterion). See
62
- `.claude/rules/workflow.md` ("Branches and commits", "PR flow"). When another
63
- session may touch this repo at the same time, the branch lives in its own
64
- worktree — the `worktree-task` skill has the lifecycle and the cleanup.
65
- - **Gates.** Every PR is routed before it is reviewed — the
66
- `decision-router` picks the cheapest lane the change earns
67
- (`deterministic` → `fast-path` → `model`), and risk flags escalate ahead of
68
- all three. `code-reviewer` runs on the `model` lane, which is **everything the
69
- two cheap lanes did not claim** — code, a rulebook document, an unclassifiable
70
- path, a derived artifact git does not report as drift, or anything a risk flag
71
- escalated;
72
- `security-scanner` when a change touches auth, secrets, parsing, or outbound
73
- calls; `prose-reviewer` when it touches the documents that instruct agents —
74
- rules, skills, agent specs, this file, the README. Those last two are
75
- **lane-independent and may only add** — the lane is a floor, never a ceiling.
76
- `.claude/rules/workflow.md` carries the ladder and what the cheap lanes give
77
- up. Blocking findings are resolved, not argued with, and the
78
- `pr-ship` skill drives the fan-out. **No hook launches them** — a gate here is
79
- a session following a written rule, so "the gate ran" is a claim, not a
80
- guarantee. That is the honest reading of every gate in this file.
81
- - **Enforcement is mechanical.** `guard-secret-file` refuses an edit that writes
82
- a credential — by the file's name or by a value in its text, from the one
83
- vocabulary in `.claude/scripts/lib/secrets.mjs`; `block-no-verify` refuses
84
- pre-commit bypasses;
85
- `guard-bash` refuses the "Never" tier — force-pushing a shared branch, a
86
- production deploy, a filesystem wipe — and carries the kill switch;
87
- `gate-stop-dod` refuses to end the session while a Definition-of-Done check
88
- fails; `inject-rules` puts the autonomy rules back in front of the agent at
89
- the start of every session, minus the parts that file marks as reference. If a hook blocks you, fix the cause; never route
90
- around a hook.
91
- - **Enforcement is a pattern you can apply again.** Each of those hooks is one
92
- stated invariant + one mechanical check + one test — the pattern is written
93
- down in `.claude/rules/invariants.md`, and the `new-invariant` skill walks you
94
- through adding one. The hooks that ship here are **examples, not laws**: if the
95
- invariant they guard is not load-bearing in this project, delete it and spend
96
- the slot on one that is.
97
- - **There is a brake, and it is a real file.** `touch
98
- ~/.claude/__PROJECT_NAME__-loop-STOP` and `guard-bash` denies every merge
99
- until it is removed. Everything short of the merge stays allowed on purpose:
100
- finish the task, push the branch, open the PR, write the journal, stop.
101
- Stopping cleanly never means losing the work.
102
- - **Work comes from the queue, through an adapter.** The `loop` skill selects via
103
- `.claude/scripts/queue/index.mjs`, which reads whichever queue
104
- `.claude/queue.json` names — the Agent queue in `PLAN.md` by default, issues in
105
- this repository once it has a remote. An empty queue **ends the session**; it is
106
- never a cue to invent work, and the agent never files its own work items.
107
-
108
- ## Four things this install left for you to finish
109
-
110
- All four are one-liners, and all four are inert until you do them.
111
-
112
- 1. **The Definition-of-Done gate has nothing to run.** `gate-stop-dod` executes
113
- the commands listed in `.claude/hooks/dod-checks.json`, and `init` ships no
114
- such file because it cannot know this project's commands. Until you write one
115
- — a JSON array like `["npm test", "npm run lint"]` — the stop gate is a
116
- no-op, and the Definition of Done is back to being a wish.
117
- 2. **The elevated-path list below is a seed, not a survey.** It names only what
118
- every repo has. Everything else is yours to add.
119
- 3. **Five runtime paths need a `.gitignore` line each**, and `init` cannot add
120
- them — it installs into your repository and does not edit files it did not
121
- bring. If any are missing, add only the missing entries:
122
-
123
- ```
124
- # the tier the last close recorded
125
- .claude/queue.state.json
126
- # the board this checkout runs on, when the config declares several
127
- .claude/queue.board
128
- # gate rounds, one count per branch
129
- .claude/gate-rounds.json
130
- # task worktrees
131
- .claude/worktrees/
132
- # the run journal's per-run trace
133
- .claude/runs/
134
- ```
135
- Each comment is on its own line, and that is not formatting: git treats `#`
136
- as a comment **only at line start**, so a trailing `# …` becomes part of the
137
- pattern and the line then ignores nothing. It fails silently — you find out
138
- when the file lands in a commit.
139
-
140
- The first one matters more than it looks. It is how the loop rations the
141
- elevated tier — never two elevated items back to back, where the tier that
142
- spaces is the one that EXECUTES (a close whose elevated paths are all
143
- documents records `elevated-prose` and clears the ration) — and it is
144
- **per-checkout state, not shared configuration**. Committed, one machine's
145
- tier starts deciding another's, and a merge conflict lands in a file nobody
146
- edited on purpose. `.claude/queue.json` is the opposite: that one is
147
- configuration and belongs in the repository.
148
-
149
- 4. **`doctor` reads two files this install does not ship.**
150
- `node .claude/scripts/doctor.mjs` decides who owns each hook from
151
- `.claude/.rig-manifest.json` — which `init` wrote next to the files it
152
- installed, so commit it — and reads exemptions from
153
- `.claude/doctor-exemptions.json`, a file you author (`{ "<path>": "<reason>" }`)
154
- only when a hook you own is deliberately left without a test neighbour.
155
- Without the manifest every hook that has no test neighbour reports `unknown`,
156
- which is not a pass.
157
-
158
- ## The elevated paths of this project
159
-
160
- Tier 2 in `.claude/rules/autonomy.md` names *kinds* of change. This block names
161
- the **paths** in this repository where those kinds live, and
162
- `.claude/scripts/detect-missed-gate.mjs` reads it — so a path that is not declared
163
- is a path the gate sweep cannot see.
164
-
165
- ```elevated-paths
166
- .claude/
167
- .agents/
168
- .codex/
169
- AGENTS.md
170
- .github/workflows/
171
- ```
172
-
173
- They are there because they are what *disarms* the rest: a merge that rewrites
174
- the Never tier, unwires a hook or edits what CI runs should never pass
175
- unreviewed.
176
-
177
- **Extend this list the same day you write the code it covers** — a real project
178
- accumulates more (auth handlers, billing, a credentials module, a migration
179
- directory, the deployment configuration). The gap between adding the code and
180
- declaring the path is exactly the window in which a change slips through
181
- unreviewed. And a path declared over a directory this project does not have is
182
- worse than an omission: the sweep reports "clean" while looking nowhere.
183
-
184
- The declaration is **composed, not centralised**: the sweep unions this block
185
- with every `elevated-paths` block in `.claude/rules/`, so a rule file can
186
- declare the paths that belong to it.
187
-
188
- Nothing about this list is retroactive. Installing the sweep into a repo with
189
- history means passing `--epoch <the day you installed it>` once, or the first run
190
- reports every merge that predates the gate.
191
-
192
- ## Foot-guns
193
-
194
- - Don't weaken a failing test to get green — a red check is information, and
195
- test integrity is a blocking review finding.
196
- - Don't answer "is this repo healthy?" from a green CI run alone: after a
197
- deploy, verify the running surface and on regression revert first
198
- (`.claude/rules/autonomy.md`, "Post-deploy verification").
199
- - Don't extend the rulebook by writing more prose. A rule that keeps being
200
- broken wants a hook and a test, not a longer paragraph — that is what
201
- `.claude/rules/invariants.md` is for.
@@ -1,105 +0,0 @@
1
- ---
2
- name: post-deploy-verify
3
- description: Produce the post-deploy HEALTHY / REGRESSION verdict the autonomy rules act on. MUST run after every deploy — CI-green ≠ runtime-healthy. Read-only by construction.
4
- context: fork
5
- allowed-tools: Bash, Read, Grep
6
- argument-hint: [stack-name]
7
- ---
8
-
9
- You verify runtime health after a deploy and return a **verdict**, not a vibe.
10
- You are read-only: you observe, you never fix. The autonomy rules
11
- (`.claude/rules/autonomy.md`, "Post-deploy verification") consume your verdict.
12
-
13
- Scope yourself to what this skeleton actually provisions — one API, one worker
14
- with one DLQ, two CloudFormation stacks. Do not invent signals it does not have.
15
-
16
- ## Steps — evidence for each, in order
17
-
18
- 1. **The deploy job's conclusion — the primary, always-available signal.**
19
- Start here: did the deploy job itself succeed? This exists on every project
20
- from day one, before any metric has data. A failed or absent deploy job is a
21
- REGRESSION on its own; a successful one is necessary but not sufficient —
22
- continue.
23
- 2. **Stack status + freshness cross-check.** `UPDATE_COMPLETE` **alone is stale
24
- evidence** — it persists from the previous deploy. Confirm `LastUpdatedTime`
25
- from `aws cloudformation describe-stacks` postdates the deploy you are
26
- judging. A fresh-looking status on a stale stack is the classic false-HEALTHY.
27
- 3. **Smoke the route.** POST a request through the API (the README's smoke
28
- command). Expect the documented success response (201 with a body).
29
- 4. **The async path.** Confirm the worker consumed the event this smoke
30
- produced: `aws logs filter-log-events` on the worker's log group for the
31
- processed-marker within the last few minutes.
32
- 5. **Queue discipline.** The skeleton's DLQ is empty and its alarm is quiet:
33
- `aws sqs get-queue-attributes` (ApproximateNumberOfMessages = 0) and
34
- `aws cloudwatch describe-alarms` (state OK, not ALARM).
35
- 6. **Function errors** in the window after the deploy — scan the functions'
36
- recent logs for new ERROR-level entries.
37
-
38
- 🔴 **A vacuous result is "no signal", not a pass.** An empty metric or an empty
39
- log query means *there were no invocations*, not *there were no errors*. Never
40
- read absence-of-data as health — report it as "no signal" and, since you could
41
- not verify, it counts toward REGRESSION, never toward HEALTHY. The first
42
- HEALTHY verdict a user sees has to mean something, or the whole mechanism loses
43
- its credibility exactly when it should earn it.
44
-
45
- ## Verdict — the only two answers
46
-
47
- Report exactly one, with the evidence lines that justify it:
48
-
49
- - `VERDICT: HEALTHY` — every step above passed.
50
- - `VERDICT: REGRESSION` — anything failed or could not be verified. Name the
51
- failing step and the observed output verbatim. **The required next action is
52
- revert** (redeploy the previous revision) — diagnosis happens after the
53
- runtime is healthy again, never by fixing forward blind. Unverifiable ≠
54
- healthy: if you cannot see, the verdict is REGRESSION. And an **empty
55
- metric or log result means "no invocations", not "no errors"** — name a
56
- vacuous result honestly instead of reporting it as a pass.
57
-
58
- ### The verdict block
59
-
60
- End your report with **exactly one** fenced `json` block of this shape, and
61
- nothing after it. The prose above it carries the evidence a human reads; this is
62
- what the caller acts on — and what it retypes into
63
- `node .claude/scripts/run-state.mjs deploy HEALTHY|REGRESSION`, which is where
64
- the next selection reads the verdict.
65
-
66
- ```json
67
- {
68
- "gate": "post-deploy-verify",
69
- "verdict": "REGRESSION",
70
- "blockers": [
71
- {
72
- "rule": "smoke request",
73
- "note": "POST /notes returned 502 twice; expected 201"
74
- }
75
- ],
76
- "advisories": [],
77
- "evidence": ["stack LastUpdatedTime is this deploy", "DLQ depth 0"],
78
- "headSha": "9c1f0a7d4b3e2c5a8f6d0b9e7c4a1f2d3e5b6c70"
79
- }
80
- ```
81
-
82
- - `verdict` is `HEALTHY` or `REGRESSION` — this skill has no third answer, and
83
- "could not verify" is a `REGRESSION`, never a missing verdict.
84
- - A `REGRESSION` names one blocker per failed or unverifiable step, with the
85
- observed output in its `note`. A step has no file, so `file` and `line` are
86
- omitted here.
87
- - A `REGRESSION` naming no blocker, and a `HEALTHY` carrying one, are answers
88
- the caller cannot act on. The caller is what checks: the session that ran the
89
- deploy runs `node .claude/scripts/verdict.mjs check <report>
90
- post-deploy-verify` before it retypes the word into `run-state.mjs`. This
91
- skill runs nothing — it is read-only by construction.
92
- - **`headSha` is the commit that was deployed** — `git rev-parse HEAD` in the
93
- checkout the deploy went out from. ⚠ **Nothing reads it yet**: `run-state.mjs`
94
- stores the word alone, so the commit lives in this block and nowhere else.
95
- Write it anyway — the pairing is what a later reader needs to tell a stale
96
- `HEALTHY` from a current one, and `HEALTHY` is the only thing that clears the
97
- `REGRESSION` latch the next selection reads.
98
-
99
- ## Boundaries
100
-
101
- - Read-only AWS calls (`describe*`, `get*`, `list*`, `filter-log-events`) plus
102
- the smoke request. Nothing that mutates state — the tool allowlist enforces
103
- this, and the rule stands even where the allowlist cannot reach.
104
- - No re-running a failed smoke "until it passes" — a flaky smoke is a
105
- REGRESSION with flakiness as the named evidence.
@@ -1,117 +0,0 @@
1
- ---
2
- name: ro-debug
3
- description: Investigate the deployed runtime read-only — Lambda logs and error rates, DLQ depth and message age, table reads — with the traps that have produced confidently-wrong diagnoses before. Use when something on the deployed stage misbehaves, and before writing any fix.
4
- allowed-tools: Bash, Read, Grep
5
- ---
6
-
7
- # Read-only runtime investigation
8
-
9
- A fix is always a code change through a PR. This skill only **looks** — and it is
10
- scoped read-only so that a session diagnosing an incident cannot become a session
11
- mutating production state under pressure, which is when that decision is worst.
12
-
13
- ## The role this assumes, and the honest caveat
14
-
15
- Every command below wants a **read-only profile**: permission to read logs,
16
- metrics, queue attributes and table items, and nothing else. No decrypt, no
17
- secret reads, no mutations — so a credential cannot leak through this path even
18
- by accident.
19
-
20
- ⚠ **The skeleton does not provision that role.** It ships the application, not
21
- your account's access model, and minting a role is an **owner action** (a Tier-2
22
- decision — it is IAM). Until it exists, either create it once with those four
23
- read scopes, or accept that you are investigating with wider credentials than the
24
- task needs and say so in the write-up. Do not silently upgrade to an admin
25
- profile and carry on.
26
-
27
- ```sh
28
- export AWS_PROFILE=<your read-only profile>
29
- export AWS_REGION=__REGION__
30
- ```
31
-
32
- ## Before reading ANY code to explain a runtime behaviour
33
-
34
- ```sh
35
- git fetch origin && git rev-parse HEAD "origin/$(git symbolic-ref --short HEAD)"
36
- ```
37
-
38
- **If the local branch differs from its remote, diagnose from the remote**
39
- (`git show origin/<branch>:<file>`, or a worktree). **A fetch does not move your
40
- checkout** — reading stale local code while describing deployed behaviour is
41
- the single most reliable way to produce a confident, wrong diagnosis, and it has
42
- happened more than once. See `.claude/rules/autonomy.md`, "Session staleness".
43
-
44
- ## Recipes
45
-
46
- **Find the function first** — CDK generates the physical names, so never guess one:
47
-
48
- ```sh
49
- aws lambda list-functions \
50
- --query "Functions[?contains(FunctionName,'Notes')].FunctionName" --output text
51
- ```
52
-
53
- **Errors in a window:**
54
-
55
- ```sh
56
- aws logs filter-log-events --log-group-name "/aws/lambda/<fn>" \
57
- --start-time <epoch-ms> --filter-pattern "ERROR" \
58
- --max-items 20 --query 'events[].message' --output text
59
- ```
60
-
61
- **DLQ depth, then message age.** Depth comes from the queue; **age does not** —
62
- `ApproximateAgeOfOldestMessage` is a **CloudWatch metric, not an SQS attribute**,
63
- and asking for it as an attribute fails with `InvalidAttributeName`:
64
-
65
- ```sh
66
- aws sqs get-queue-attributes --queue-url <notes-dlq-url> \
67
- --attribute-names ApproximateNumberOfMessages
68
-
69
- aws cloudwatch get-metric-statistics --namespace AWS/SQS \
70
- --metric-name ApproximateAgeOfOldestMessage \
71
- --dimensions Name=QueueName,Value=<notes-dlq-name> \
72
- --start-time <iso> --end-time <iso> --period 300 --statistics Maximum
73
- ```
74
-
75
- Age is what tells you whether a non-empty DLQ **predates** the thing you are
76
- investigating. A days-old backlog is not your regression, and treating it as one
77
- sends the whole diagnosis in the wrong direction.
78
-
79
- **Table reads** — key by whatever `packages/db` composes; nothing else knows the
80
- key shape:
81
-
82
- ```sh
83
- aws dynamodb query --table-name <NotesTable output> \
84
- --key-condition-expression "pk = :pk" \
85
- --expression-attribute-values '{":pk":{"S":"NOTE#<id>"}}' --max-items 3
86
- ```
87
-
88
- **Error rate:** `AWS/Lambda` `Errors`, `Sum`, by `FunctionName`, over the suspect
89
- window.
90
-
91
- ## Interpretation rules — where wrong diagnoses actually come from
92
-
93
- - 🔴 **An empty metric result is "no signal", never "healthy".** Zero datapoints
94
- means **no invocations in the window** — the function was not exercised, so the
95
- metric says nothing about whether it works. Report it as no signal and go find
96
- a window with traffic. This is the same rule the `post-deploy-verify` skill
97
- states, and for the same reason: a vacuous pass is worse than a missing one,
98
- because it gets believed.
99
- - 🔴 **`StackStatus: UPDATE_COMPLETE` is stale evidence.** It persists from the
100
- previous deploy, so it is true of a stack whose latest deploy failed. The
101
- authoritative signals are the **deploy job's conclusion**
102
- (`gh run list --workflow deploy`) and the stack's `LastUpdatedTime` freshness.
103
- - **DNS and asset-upload failures are infrastructure flakes, not code
104
- regressions.** A deploy that died at asset publish or checkout tells you nothing
105
- about the change. Your own read-only calls can hit the same flake — a failed
106
- probe is `unknown`, not a finding.
107
- - **Never work around the profile's denials — that is the point of the profile.**
108
- Needing a decrypt, a secret or a mutation means the investigation has reached
109
- its boundary: escalate to the human with what you found
110
- (`.claude/rules/autonomy.md`, "Escalation format").
111
-
112
- ## What to hand back
113
-
114
- What was observed (verbatim, not summarised), which window, which signals were
115
- **unavailable** and why, the current hypothesis, and the narrowest reproduction.
116
- A read-only investigation that ends in a named uncertainty is a good outcome; one
117
- that ends in a confident story built on a stale read is not.