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,275 +0,0 @@
1
- /**
2
- * The small set of checks the declaration and the decision record share.
3
- *
4
- * Every check appends to a problem list instead of throwing, so a caller sees
5
- * every defect of a record at once — `validateDeclaration` › "reports every
6
- * problem at once rather than stopping at the first" in
7
- * `packages/cli/test/policy-declaration.test.ts`. Each message that refuses an
8
- * enumerated value quotes the value, because a refusal that names the field
9
- * and not the word leaves the caller guessing which of two spellings it sent.
10
- */
11
- export const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
12
- /**
13
- * Whether an outside record CARRIES a field — own and enumerable, which is
14
- * exactly the set `Object.keys` walks, and which `JSON.stringify` writes out
15
- * whenever the value is serialisable.
16
- *
17
- * ⚠ The second half is a "whenever", not an equivalence, and the earlier
18
- * wording claimed the equivalence. `{ downgradeReason: undefined }` is own and
19
- * enumerable, so this returns `true`, while `JSON.stringify` drops it — which
20
- * is why a `SUPPORTED` row written that way is refused for carrying a reason
21
- * even though its serialisation carries none. The refusal is the conservative
22
- * direction, but a reader who took "the rule is what `JSON.stringify` sees"
23
- * literally would predict acceptance. `Object.keys` is the set this actually
24
- * implements; that is the half to reason from.
25
- *
26
- * 🔴 The two halves are one rule, and each was a real false pass. A field found
27
- * on the PROTOTYPE let a hook serialising as `{}` be read as running the
28
- * generated command, and let an evidence row own nothing and still validate; a
29
- * field that is own but NOT ENUMERABLE let a row validate and then serialise
30
- * without the pointer that made it pass. Both are the same defect stated twice:
31
- * something was accepted as evidence that no serialisation of the value
32
- * carries. `unknownKeys` already judges a record by `Object.keys`, so reading
33
- * by any wider notion made the closed-shape check and the field reads disagree
34
- * about what the record even contains — and the reads were the wider of the
35
- * two.
36
- *
37
- * Held over both readers at once: `packages/cli/test/policy-coverage.test.ts`
38
- * (absent in a generated rig) › "refuses a hook entry whose command is only
39
- * inherited, because the entry itself carries no command" and › "refuses a row
40
- * whose evidence pointer is own but not enumerable, because the rule is what
41
- * JSON.stringify sees".
42
- */
43
- export const carriesField = (input, field) => Object.prototype.propertyIsEnumerable.call(input, field);
44
- /**
45
- * Read one field the way the record's own serialisation would carry it, or
46
- * `undefined` when the record does not carry it at all.
47
- *
48
- * Presence and value travel through the same predicate on purpose: a caller
49
- * that tested presence one way and read the value another is how the two
50
- * came apart the first time.
51
- */
52
- export const ownField = (input, field) => carriesField(input, field) ? input[field] : undefined;
53
- /**
54
- * A value as it appeared, escaped, for a message a person reads. Exported
55
- * because every module here that puts OUTSIDE data into a diagnostic must put
56
- * it through the same escaping — a raw newline or ANSI sequence in a matcher
57
- * can otherwise forge a line of the report it lands in (`./probe.ts`).
58
- */
59
- export const quote = (value) => {
60
- try {
61
- return JSON.stringify(value) ?? String(value);
62
- }
63
- catch {
64
- return String(value);
65
- }
66
- };
67
- const list = (vocabulary) => vocabulary.map(quote).join(', ');
68
- /**
69
- * Refuse a key the shape does not declare — the shape is closed on purpose.
70
- * A nested shape passes its own field name as `prefix`, so the problem names
71
- * `verdict.severity` rather than a bare `severity` the caller cannot place.
72
- */
73
- export const unknownKeys = (problems, input, known, prefix = '') => {
74
- for (const key of Object.keys(input)) {
75
- if (!known.includes(key)) {
76
- problems.push({ field: prefix === '' ? key : `${prefix}.${key}`, message: 'unknown field' });
77
- }
78
- }
79
- };
80
- /** Refuse a string that is absent, not a string, or empty. */
81
- export const nonEmptyString = (problems, field, value) => {
82
- if (typeof value !== 'string' || value === '') {
83
- problems.push({ field, message: `must be a non-empty string, got ${quote(value)}` });
84
- return false;
85
- }
86
- return true;
87
- };
88
- /**
89
- * Refuse a string that is absent, not a string, or has no non-space character.
90
- *
91
- * Stricter than `nonEmptyString` in exactly one place — a value of whitespace
92
- * only — and a separate helper rather than a tightening of that one, because
93
- * the shapes already validated by it are not in this change's scope. Where a
94
- * field is a fact a later reader has to act on (an exact version, a pointer to
95
- * evidence), a blank is the same defect as an absence and is refused as one.
96
- */
97
- export const nonBlankString = (problems, field, value) => {
98
- if (typeof value !== 'string' || value.trim() === '') {
99
- problems.push({ field, message: `must be a non-blank string, got ${quote(value)}` });
100
- return false;
101
- }
102
- return true;
103
- };
104
- /**
105
- * A real calendar date, `T`, time to the second (fractions allowed), and an
106
- * explicit zone.
107
- *
108
- * One spelling of one fact (`rules/invariants.md`, "One mechanism, one
109
- * implementation"). Its three readers are `./decision-record.ts`
110
- * (`recordedAt`), `./evidence-matrix.ts` (`observedAt`) and `./coverage.ts`
111
- * (`verifiedAt`, through `requireTimestamp`), so a bare date is refused the
112
- * same way whichever of them is validating — including lexically shaped but
113
- * impossible dates — `packages/cli/test/policy-coverage.test.ts`
114
- * › "refuses the probe timestamp %j, which is exactly what the shared ISO-8601
115
- * pattern refuses" imports this pattern rather than restating it, so the two
116
- * sides cannot drift apart. A timestamp is always supplied by the caller —
117
- * nothing under this directory reads a clock.
118
- */
119
- const ISO_8601_SHAPE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-](\d{2}):(\d{2}))$/;
120
- /**
121
- * A date-time shape whose `test` also proves the named calendar instant exists.
122
- * Keeping the semantic check behind the same exported predicate prevents the
123
- * coverage, decision-record and evidence-row validators from drifting apart.
124
- */
125
- export const ISO_8601 = {
126
- test(value) {
127
- const match = ISO_8601_SHAPE.exec(value);
128
- if (match === null)
129
- return false;
130
- const [, yearText, monthText, dayText, hourText, minuteText, secondText, zoneHour, zoneMinute] = match;
131
- const year = Number(yearText);
132
- const month = Number(monthText);
133
- const day = Number(dayText);
134
- const hour = Number(hourText);
135
- const minute = Number(minuteText);
136
- const second = Number(secondText);
137
- const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
138
- const daysInMonth = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
139
- return (month >= 1 &&
140
- month <= 12 &&
141
- day >= 1 &&
142
- day <= daysInMonth[month - 1] &&
143
- hour <= 23 &&
144
- minute <= 59 &&
145
- second <= 59 &&
146
- (zoneHour === undefined || (Number(zoneHour) <= 23 && Number(zoneMinute) <= 59)));
147
- },
148
- };
149
- /** Refuse a string outside a closed vocabulary, quoting the offending value. */
150
- export const member = (problems, field, value, vocabulary) => {
151
- if (typeof value === 'string' && vocabulary.includes(value))
152
- return true;
153
- problems.push({ field, message: `${quote(value)} is not one of ${list(vocabulary)}` });
154
- return false;
155
- };
156
- /**
157
- * Refuse a list that is not an array, carries a value outside the vocabulary,
158
- * repeats one, or — when `nonEmpty` — is empty.
159
- */
160
- export const members = (problems, field, value, vocabulary, { nonEmpty }) => {
161
- if (!Array.isArray(value)) {
162
- problems.push({ field, message: `must be a list, got ${quote(value)}` });
163
- return false;
164
- }
165
- let clean = true;
166
- if (nonEmpty && value.length === 0) {
167
- problems.push({ field, message: 'must not be empty' });
168
- clean = false;
169
- }
170
- const seen = new Set();
171
- for (const entry of value) {
172
- if (!member(problems, field, entry, vocabulary)) {
173
- clean = false;
174
- continue;
175
- }
176
- if (seen.has(entry)) {
177
- problems.push({ field, message: `${quote(entry)} is listed twice` });
178
- clean = false;
179
- }
180
- seen.add(entry);
181
- }
182
- return clean;
183
- };
184
- /** Refuse a string that does not match the pattern, saying what shape was expected. */
185
- export const matching = (problems, field, value, pattern, expected) => {
186
- if (typeof value === 'string' && pattern.test(value))
187
- return true;
188
- problems.push({ field, message: `must be ${expected}, got ${quote(value)}` });
189
- return false;
190
- };
191
- /**
192
- * A version that names one build rather than a set of them.
193
- *
194
- * One spelling of one fact: `./evidence-matrix.ts` refuses a matrix row on it
195
- * and `./coverage.ts` refuses a surface identity on it, so "the exact version
196
- * observed" means the same thing wherever it is written.
197
- *
198
- * 🔴 This is an ALLOWLIST, and it replaced a denylist that could not be
199
- * finished. The denylist refused five vague words, the range operator
200
- * characters, a wildcard component and two npm range spellings — and accepted
201
- * `main`, `master`, `stable`, `next`, `nightly`, `dev`, `edge`, `canary` and
202
- * `1.2.3 or 2.0.0`, because none of them is any of those things. A moving label
203
- * is not a shape you can enumerate: every branch name a harness ever publishes
204
- * from is a new entry, added by whoever notices, which is nobody. So the check
205
- * asks what a build identifier LOOKS LIKE instead of what a moving target is
206
- * called, and a word the grammar does not describe is refused whether or not
207
- * anyone anticipated it.
208
- *
209
- * Two shapes are accepted, and they are the two this rig actually reads:
210
- *
211
- * - a build NUMBER — a dotted numeric version, optionally `v`-prefixed, with an
212
- * optional pre-release or build-metadata suffix after `-` or `+`. That covers
213
- * `2.0.14`, `v2.0.14`, `1.104.2`, a date build id like `2026-09-05`, a plain
214
- * build id like `20260904.3`, and a suffix carrying any letter at all,
215
- * including `1.0.0-X` and `0.0.0-fixture`;
216
- * - a build ID — 7 to 64 hex characters, which is a git object id at every
217
- * length git itself abbreviates to.
218
- *
219
- * The distinction that costs the most to get wrong is the one between a bare
220
- * channel word and a suffix: `beta` names whatever is on that channel today and
221
- * is refused, while `1.0.0-beta.2` names one build and is accepted. The grammar
222
- * draws that line by requiring the number first — a suffix cannot stand alone.
223
- *
224
- * The value is matched AS GIVEN, with no trim. An earlier version validated
225
- * `value.trim()` while both callers stored the value verbatim, so `" 2.0.14 "`,
226
- * `"2.0.14\r\n"` and a BOM-prefixed form were accepted and then persisted with
227
- * their padding: two rows for one build that compare unequal, and a version
228
- * carrying a newline sitting in a field a report will one day render. What is
229
- * checked and what is stored are now the same string: ›
230
- * "refuses an evidence row whose harness version carries %s, because the row
231
- * would store what it was not validated on" and › "refuses to probe against a
232
- * harness version carrying %s, so two maps of one build cannot compare
233
- * unequal", with › "still accepts the same build once %s is gone, because it is
234
- * the padding that is refused and not the version" holding the other side.
235
- *
236
- * Refused, and now by construction rather than by enumeration: the vague words,
237
- * every moving branch label, range OPERATORS, wildcard components, both npm
238
- * range spellings, and any text carrying whitespace or a comma — which is what
239
- * `1.2.3 or 2.0.0` and `1.2.3, 2.0.0` are. Both readers are pinned in
240
- * `packages/cli/test/policy-coverage.test.ts` (absent in a generated rig) ›
241
- * "refuses the harness version %j, because it names a moving label or more than
242
- * one build" and › "refuses to probe against the harness version %j, because it
243
- * names a moving label or more than one build", with the other direction held
244
- * so the grammar cannot swallow a real build id: › "still accepts the harness
245
- * version %j, because it names one build" and › "still probes against the
246
- * harness version %j, because it names one build".
247
- */
248
- const BUILD_NUMBER = /^v?\d+(?:\.\d+)*(?:[-+][0-9A-Za-z][0-9A-Za-z.+-]*)?$/;
249
- const BUILD_ID = /^[0-9a-fA-F]{7,64}$/;
250
- /**
251
- * What a refusal says is expected — one spelling, read by this module and by
252
- * `./coverage.ts`, so the two cannot come to describe different grammars.
253
- */
254
- export const EXACT_VERSION_EXPECTED = 'must name one immutable build: a version number like 2.0.14, ' +
255
- 'optionally v-prefixed and optionally carrying a -pre-release or +build suffix, ' +
256
- 'or a 7-to-64-character hex build id';
257
- export const isExactVersion = (value) => BUILD_NUMBER.test(value) || BUILD_ID.test(value);
258
- /**
259
- * Refuse a version the grammar does not describe, quoting the value and naming
260
- * the two shapes that are accepted.
261
- *
262
- * The message says what would be accepted rather than what was wrong, because
263
- * the check is an allowlist: it also refuses `1.0.0.beta` and `2026_09_05`,
264
- * which are neither a range nor a moving target, and the earlier message told
265
- * their author they had written one. `./probe.ts` states the principle this
266
- * trips over — a refusal naming a cause that did not occur sends an operator
267
- * looking for something that is not there.
268
- */
269
- export const exactVersion = (problems, field, value) => {
270
- if (typeof value !== 'string' || value.trim() === '')
271
- return;
272
- if (!isExactVersion(value)) {
273
- problems.push({ field, message: `${EXACT_VERSION_EXPECTED}; got ${quote(value)}` });
274
- }
275
- };
@@ -1,123 +0,0 @@
1
- /**
2
- * The closed vocabularies of the policy declaration (RP-76).
3
- *
4
- * Every value a declaration or a decision record may carry in an enumerated
5
- * field is listed here and nowhere else. Adding a value is a schema edit — a
6
- * change to this file plus the test that pins the list — never a string a
7
- * caller invents at runtime. That is what makes a record auditable: an unknown
8
- * word is refused rather than read as something close to a known one.
9
- *
10
- * Harness-neutral by construction: nothing here names a harness, a vendor, a
11
- * native tool or a native path. The per-harness spellings live in
12
- * `../harness/`, and `test/template/policy-declaration.test.ts` › "no file
13
- * under src/policy/core mentions a harness, a vendor, a native tool or a native
14
- * path" is what keeps them out of here.
15
- */
16
- const closed = (values) => Object.freeze(values);
17
- /**
18
- * Whether a declared policy can actually be enforced on a given harness
19
- * surface. `UNSUPPORTED` and `INTEGRATION-FAILED` must never yield a silent
20
- * pass: a decision record carrying either has to qualify its verdict
21
- * `UNVERIFIABLE` (`./decision-record.ts`). The four states are defined here.
22
- *
23
- * ⚠ That is the rule, and the enforcement behind it is narrower than the rule
24
- * — see `UNENFORCEABLE_STATES` below, which states the gap once for every
25
- * reader of this file.
26
- */
27
- export const CAPABILITY_STATES = closed([
28
- 'SUPPORTED',
29
- 'DEGRADED',
30
- 'UNSUPPORTED',
31
- 'INTEGRATION-FAILED',
32
- ]);
33
- /**
34
- * The states under which no question was actually put to a working mechanism.
35
- *
36
- * One spelling of one fact (`rules/invariants.md`, "One mechanism, one
37
- * implementation"): `./decision-record.ts` refuses an unqualified verdict
38
- * carrying one of these, and `./coverage.ts` › `qualifierFor` returns
39
- * `UNVERIFIABLE` for exactly the same set. Two copies would disagree, and the
40
- * one nobody is looking at would be the one that let a silent pass through.
41
- *
42
- * ⚠ **"Refuses" now holds against a hand-built prototype too** — this note used
43
- * to say the opposite, and this is the file a reader auditing that question
44
- * lands on first, so it is corrected here rather than only where the fix landed.
45
- * `./decision-record.ts` used to decide whether a verdict carries a qualifier
46
- * with the `in` operator, so a verdict INHERITING one satisfied the check and
47
- * then serialised without it. RP-153 closed that: every field of both
48
- * `./decision-record.ts` and `./declaration.ts` is read through
49
- * `carriesField`/`ownField`, the way `./probe.ts` and `./evidence-matrix.ts`
50
- * already read theirs, and both uncarried shapes are pinned in
51
- * `packages/cli/test/policy-declaration.test.ts` › "refuses an UNSUPPORTED
52
- * record whose verdict qualifier is %s, because what it writes out is a silent
53
- * pass" — `%s` as the `it.each` case declares it, so one grep lands on it.
54
- *
55
- * What remains is narrower and is NOT this sentence's subject: a value carrying
56
- * a live accessor is validated on one read and serialised from another (RP-157),
57
- * and an array HOLE serialises as `null` while the two `forEach` loops in
58
- * `./decision-record.ts` skip it (RP-161) — those two only, since `members` in
59
- * `./validation.ts` and `./probe.ts` iterate with `for…of`, which sees a hole as
60
- * `undefined` and refuses it. `docs/decisions/capability-coverage.md`, "What
61
- * this does NOT do", carries the current limits at length.
62
- *
63
- * It is deliberately NOT derived from a rank or an ordering. `coverage.ts`
64
- * carries an enforcement ordering for deciding what counts as a downgrade;
65
- * keying verdict qualification off that would mean a future re-rank silently
66
- * changed which verdicts are unverifiable.
67
- */
68
- export const UNENFORCEABLE_STATES = closed(['UNSUPPORTED', 'INTEGRATION-FAILED']);
69
- /**
70
- * The two ways a capability status is established, and the only two.
71
- *
72
- * `probe` is one active read of the surface's own wiring, taken when the
73
- * surface changes (`PROBE_TRIGGERS`). `traffic` is passive: an operation that
74
- * was expected to produce an observable signal, and what it actually produced.
75
- * There is deliberately no third source meaning "time passed" — silence is
76
- * absence of evidence, not evidence of absence.
77
- */
78
- export const VERIFICATION_SOURCES = closed(['probe', 'traffic']);
79
- /**
80
- * The occasions on which a surface is probed. Every member is an event on the
81
- * surface; none of them is an interval.
82
- *
83
- * What this vocabulary does, exactly: `./coverage.ts` › `coverageFromProbe`
84
- * takes a trigger as a required argument and refuses a word outside this list,
85
- * so a probe must NAME its occasion and cannot name a schedule — ›
86
- * "refuses the trigger %j, because the coverage contract accepts only a
87
- * declared surface-change trigger".
88
- *
89
- * ⚠ What it does NOT do, stated because an earlier draft of this comment
90
- * claimed it: nothing here stops a caller passing `'upgrade'` on a timer. The
91
- * check refuses a LABEL outside the vocabulary, not the practice of probing
92
- * periodically. `docs/decisions/capability-coverage.md` §1 says the same, and
93
- * this file used to contradict it.
94
- */
95
- export const PROBE_TRIGGERS = closed(['install', 'upgrade', 'registration', 'reconnect']);
96
- /** The autonomy tiers of `rules/autonomy.md`; `never` is the tier the guards enforce. */
97
- export const AUTONOMY_TIERS = closed(['tier-0', 'tier-1', 'tier-2', 'never']);
98
- /** The operations a policy can apply to, named by what the agent does, not by a tool. */
99
- export const OPERATIONS = closed(['file-edit', 'shell-command']);
100
- /** When the mechanism decides, relative to the operation it judges. */
101
- export const ENFORCEMENT_TIMINGS = closed(['before-operation']);
102
- /** What a harness must provide for the mechanism to run at all. */
103
- export const HARNESS_CAPABILITIES = closed(['pre-operation-hook']);
104
- /**
105
- * The three outcomes a guard can reach: allow, block, or refuse to inspect —
106
- * the third being neither a match nor an error (`rules/invariants.md`,
107
- * "Refusing to inspect is a third outcome").
108
- */
109
- export const DECISION_OUTCOMES = closed(['allow', 'block', 'refuse-to-inspect']);
110
- /** What a mechanism does when it cannot decide: let the operation through, or stop it. */
111
- export const FAILURE_SEMANTICS = closed(['fail-open', 'fail-closed']);
112
- /** The kinds of evidence a decision record may carry, and a policy may require. */
113
- export const EVIDENCE_KINDS = closed(['exit-code', 'diagnostic-text', 'test-pointer']);
114
- /** How a mechanism treats what it matched when it reports: verbatim, or omitted. */
115
- export const REDACTION_RULES = closed(['none', 'omit-matched-values']);
116
- /** Where a policy is in its life; a `retired` policy is no longer offered by the registry. */
117
- export const LIFECYCLE_STATES = closed(['active', 'deprecated', 'retired']);
118
- /**
119
- * The two ways a verdict can say "this word is weaker than it looks": the
120
- * question could not be put (`UNVERIFIABLE`), or nothing backs the answer
121
- * (`UNMEASURED`). Either one must carry a reason.
122
- */
123
- export const VERDICT_QUALIFIERS = closed(['UNVERIFIABLE', 'UNMEASURED']);
@@ -1,47 +0,0 @@
1
- /**
2
- * The Claude Code adapter: a declaration → the native hook surface Claude Code
3
- * wires for it. The authoring surface of this rulebook is Claude-shaped
4
- * (`CLAUDE.md`, "One operating system, two harnesses"), so the hook files
5
- * themselves live in the historical directory `./shared-hooks.ts` names and are
6
- * shared by every harness.
7
- *
8
- * What is native here and nowhere in the core: the `PreToolUse` event, the
9
- * tool names in the matchers, and the snapshot path. The matcher strings are
10
- * the ones `.claude/settings.json` carries, and the correspondence test holds
11
- * the two to the SAME tool set, not a subset: a tool dropped here or gained
12
- * there is reported for this adapter —
13
- * `test/template/policy-declaration.test.ts` › "reports the no-verify policy
14
- * on %s when the shell matcher loses PowerShell (mutation: matcher)", › "reports
15
- * the no-verify policy on %s when the snapshot gains a tool the adapter does
16
- * not name (mutation: widened snapshot)" and › "reports a policy on %s whose
17
- * adapter matcher drops a tool the snapshot still wires (mutation: narrowed
18
- * adapter)". The shell matcher's tool set is owned by `shell-tools.mjs` in the
19
- * shipped scripts, and `test/template/shell-tools.test.ts` holds that
20
- * correspondence.
21
- */
22
- import { SHARED_HOOK_ROOT_ENV, SHARED_HOOKS_DIR } from './shared-hooks.js';
23
- const EVENT_OF = {
24
- 'before-operation': 'PreToolUse',
25
- };
26
- const MATCHER_OF = {
27
- 'file-edit': 'Write|Edit|MultiEdit|NotebookEdit|apply_patch',
28
- 'shell-command': 'Bash|PowerShell',
29
- };
30
- export const nativeSurfaceOf = (policy) => ({
31
- event: EVENT_OF[policy.timing],
32
- matcher: policy.operations.map((operation) => MATCHER_OF[operation]).join('|'),
33
- hookPath: `${SHARED_HOOKS_DIR}/${policy.mechanism}.mjs`,
34
- // The exact command this harness generates for a hook. The probe compares
35
- // against this rather than parsing what it finds, so this string and the one
36
- // in the shipped snapshot must agree — pinned in both directions by
37
- // `test/template/policy-coverage.test.ts` (absent in a generated rig) ›
38
- // "the %s snapshot wires %s with exactly the command that adapter generates".
39
- commands: {
40
- command: [`node "$${SHARED_HOOK_ROOT_ENV}/${SHARED_HOOKS_DIR}/${policy.mechanism}.mjs"`],
41
- },
42
- });
43
- export const claudeAdapter = Object.freeze({
44
- harness: 'claude',
45
- surfaceFile: '.claude/settings.json',
46
- nativeSurfaceOf,
47
- });
@@ -1,87 +0,0 @@
1
- /**
2
- * The Codex adapter: a declaration → the native hook surface Codex wires for
3
- * it. Codex's hook wiring (`.codex/hooks.json`) is DERIVED from the authoring
4
- * harness's snapshot by `scripts/sync-codex-adapter.mjs`
5
- * (`docs/decisions/codex-adapter.md`): it keeps the authoring harness's matcher
6
- * spellings, adds the canonical edit tool `apply_patch`, and runs the same hook
7
- * files from the shared hooks directory. So the strings below coincide with the
8
- * other adapter's today — by derivation, not by accident — and each adapter
9
- * still owns its own spelling. The correspondence test holds this adapter's
10
- * matcher and the derived snapshot's to the SAME tool set, so a tool the
11
- * snapshot gains or loses, or one this adapter drops, is reported for this
12
- * adapter alone — `test/template/policy-declaration.test.ts` › "reports the
13
- * no-verify policy on %s when the shell matcher loses PowerShell (mutation:
14
- * matcher)", › "reports the no-verify policy on %s when the snapshot gains a
15
- * tool the adapter does not name (mutation: widened snapshot)" and › "reports
16
- * a policy on %s whose adapter matcher drops a tool the snapshot still wires
17
- * (mutation: narrowed adapter)".
18
- *
19
- * The shared hooks directory is imported from `./shared-hooks.ts` rather than
20
- * restated, for the same reason the snapshot is derived rather than
21
- * hand-written: one spelling of one fact.
22
- */
23
- import { SHARED_HOOK_ROOT_ENV, SHARED_HOOKS_DIR } from './shared-hooks.js';
24
- const EVENT_OF = {
25
- 'before-operation': 'PreToolUse',
26
- };
27
- const MATCHER_OF = {
28
- 'file-edit': 'Write|Edit|MultiEdit|NotebookEdit|apply_patch',
29
- 'shell-command': 'Bash|PowerShell',
30
- };
31
- /**
32
- * The Windows spelling this harness generates for a hook.
33
- *
34
- * ⚠ A SECOND implementation of the wrapper that `scripts/sync-codex-adapter.mjs`
35
- * writes into the shipped file, and deliberately so: that script is a build tool
36
- * outside the published package, and this module may not import it. The two are
37
- * held equal by a correspondence check that goes red in BOTH directions —
38
- * `test/template/policy-coverage.test.ts` (absent in a generated rig) › "the %s
39
- * snapshot wires %s with exactly the spelling that adapter generates, in every
40
- * field it generates one for" — which is what `rules/invariants.md` ("One
41
- * mechanism, one implementation") requires of a copy that has to stay.
42
- *
43
- * The wrapper exists because PowerShell owns its stdin, so the hook would
44
- * receive an empty stream; it copies the original bytes into the child instead
45
- * of re-encoding them.
46
- */
47
- const windowsCommand = (hookPath) => {
48
- const script = [
49
- "$ErrorActionPreference = 'Stop'",
50
- '$repoRoot = git rev-parse --show-toplevel',
51
- 'if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }',
52
- `$env:${SHARED_HOOK_ROOT_ENV} = $repoRoot`,
53
- `$hookPath = Join-Path $repoRoot '${hookPath}'`,
54
- '$startInfo = New-Object System.Diagnostics.ProcessStartInfo',
55
- "$startInfo.FileName = 'node'",
56
- "$startInfo.Arguments = '\"' + $hookPath + '\"'",
57
- '$startInfo.UseShellExecute = $false',
58
- '$startInfo.RedirectStandardInput = $true',
59
- '$child = [System.Diagnostics.Process]::Start($startInfo)',
60
- '[Console]::OpenStandardInput().CopyTo($child.StandardInput.BaseStream)',
61
- '$child.StandardInput.Close()',
62
- '$child.WaitForExit()',
63
- 'exit $child.ExitCode',
64
- ].join('; ');
65
- const encoded = Buffer.from(script, 'utf16le').toString('base64');
66
- return `powershell.exe -NoProfile -NonInteractive -EncodedCommand ${encoded}`;
67
- };
68
- export const nativeSurfaceOf = (policy) => ({
69
- event: EVENT_OF[policy.timing],
70
- matcher: policy.operations.map((operation) => MATCHER_OF[operation]).join('|'),
71
- hookPath: `${SHARED_HOOKS_DIR}/${policy.mechanism}.mjs`,
72
- // Both commands this harness generates. It runs the first on POSIX and the
73
- // second on Windows, so the probe has to know both: replacing only the
74
- // Windows spelling in the shipped file used to leave every policy reading
75
- // SUPPORTED while the guard no longer ran there.
76
- commands: {
77
- command: [
78
- `repoRoot="$(git rev-parse --show-toplevel)" && ${SHARED_HOOK_ROOT_ENV}="$repoRoot" node "$repoRoot/${SHARED_HOOKS_DIR}/${policy.mechanism}.mjs"`,
79
- ],
80
- commandWindows: [windowsCommand(`${SHARED_HOOKS_DIR}/${policy.mechanism}.mjs`)],
81
- },
82
- });
83
- export const codexAdapter = Object.freeze({
84
- harness: 'codex',
85
- surfaceFile: '.codex/hooks.json',
86
- nativeSurfaceOf,
87
- });
@@ -1,15 +0,0 @@
1
- /**
2
- * The harness adapters this generator knows. Adding a harness is one new
3
- * module beside these two and one entry in the list below — nothing in
4
- * `../core/` changes, which `test/template/policy-declaration.test.ts` ›
5
- * "codex is named only by its own adapter and the adapter index" pins by
6
- * naming exactly the files that may mention each harness.
7
- */
8
- import { claudeAdapter } from './claude.js';
9
- import { codexAdapter } from './codex.js';
10
- export { claudeAdapter, codexAdapter };
11
- export { SHARED_HOOKS_DIR } from './shared-hooks.js';
12
- export const HARNESS_ADAPTERS = Object.freeze([
13
- claudeAdapter,
14
- codexAdapter,
15
- ]);
@@ -1,28 +0,0 @@
1
- /**
2
- * The one directory every harness runs its hook files from. The rulebook's
3
- * `.claude/` directory keeps its historical name but holds the shared rules,
4
- * hooks, scripts and agent specifications for both harnesses (`CLAUDE.md`,
5
- * "One operating system, two harnesses"), so a hook path is the same string
6
- * whichever adapter names it. Stated once, here, and imported by each adapter
7
- * — one spelling of one fact (`rules/invariants.md`, "One mechanism, one
8
- * implementation").
9
- */
10
- export const SHARED_HOOKS_DIR = '.claude/hooks';
11
- /**
12
- * The environment variable a shared hook reads when it needs the repository
13
- * root, and therefore the one each harness sets when it runs one.
14
- *
15
- * Not every hook needs it: of the eight this rig ships, `guard-rulebook` and
16
- * `guard-secret-file` read it, both falling back to the working directory.
17
- * The variable is still part of the wiring contract, because the harness sets
18
- * it for whichever hook it runs.
19
- *
20
- * It carries a harness's name for the same historical reason `.claude/hooks`
21
- * does — the hooks are shared, so both harnesses speak this one variable — and
22
- * this module is the one adapter-side file allowed to spell that name for both
23
- * (`test/template/policy-declaration.test.ts` › "claude is named only by its
24
- * own adapter, the shared hooks directory and the adapter index"). Stating it
25
- * here is what lets the other harness's adapter build its generated command
26
- * without naming a harness that is not its own.
27
- */
28
- export const SHARED_HOOK_ROOT_ENV = 'CLAUDE_PROJECT_DIR';
@@ -1,17 +0,0 @@
1
- /**
2
- * The policy declaration, registry, decision-record schema and harness
3
- * adapters (RP-76), plus the capability & degradation contract that says what
4
- * each of them is worth on a given surface (RP-36).
5
- *
6
- * Library surface only — nothing here is reached by the CLI commands yet;
7
- * emitting decision records at runtime, and rendering the coverage report in
8
- * `doctor`, are separate tasks.
9
- */
10
- export * from './core/vocabulary.js';
11
- export * from './core/declaration.js';
12
- export * from './core/registry.js';
13
- export * from './core/decision-record.js';
14
- export * from './core/probe.js';
15
- export * from './core/coverage.js';
16
- export * from './core/evidence-matrix.js';
17
- export * from './harness/index.js';