@tiphys/kernel 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/AGENTS.md +611 -0
  2. package/LICENSE +202 -0
  3. package/assurance-modes.yaml +278 -0
  4. package/checklists/clean-room.yaml +325 -0
  5. package/checklists/env-failure-diagnosis.yaml +68 -0
  6. package/checklists/flake-playbook.yaml +68 -0
  7. package/checklists/hazard-review.yaml +144 -0
  8. package/checklists/plan-review.yaml +103 -0
  9. package/dist/bin/tiphys.d.ts +2 -0
  10. package/dist/bin/tiphys.js +14 -0
  11. package/dist/src/brief.d.ts +32 -0
  12. package/dist/src/brief.js +59 -0
  13. package/dist/src/checklists.d.ts +169 -0
  14. package/dist/src/checklists.js +310 -0
  15. package/dist/src/checks.d.ts +828 -0
  16. package/dist/src/checks.js +3314 -0
  17. package/dist/src/cli.d.ts +9 -0
  18. package/dist/src/cli.js +57 -0
  19. package/dist/src/commands/brief.d.ts +92 -0
  20. package/dist/src/commands/brief.js +320 -0
  21. package/dist/src/commands/checklist.d.ts +42 -0
  22. package/dist/src/commands/checklist.js +168 -0
  23. package/dist/src/commands/doctor.d.ts +35 -0
  24. package/dist/src/commands/doctor.js +605 -0
  25. package/dist/src/commands/gates.d.ts +9 -0
  26. package/dist/src/commands/gates.js +360 -0
  27. package/dist/src/commands/init.d.ts +30 -0
  28. package/dist/src/commands/init.js +128 -0
  29. package/dist/src/commands/lock.d.ts +1 -0
  30. package/dist/src/commands/lock.js +229 -0
  31. package/dist/src/commands/mode.d.ts +40 -0
  32. package/dist/src/commands/mode.js +134 -0
  33. package/dist/src/commands/plan.d.ts +20 -0
  34. package/dist/src/commands/plan.js +105 -0
  35. package/dist/src/commands/pool.d.ts +1 -0
  36. package/dist/src/commands/pool.js +128 -0
  37. package/dist/src/commands/spawn.d.ts +1 -0
  38. package/dist/src/commands/spawn.js +146 -0
  39. package/dist/src/commands/status.d.ts +19 -0
  40. package/dist/src/commands/status.js +120 -0
  41. package/dist/src/commands/teardown.d.ts +1 -0
  42. package/dist/src/commands/teardown.js +79 -0
  43. package/dist/src/commands/tuition.d.ts +21 -0
  44. package/dist/src/commands/tuition.js +218 -0
  45. package/dist/src/commands/validate.d.ts +78 -0
  46. package/dist/src/commands/validate.js +360 -0
  47. package/dist/src/commands/watch.d.ts +1 -0
  48. package/dist/src/commands/watch.js +172 -0
  49. package/dist/src/exec/env.d.ts +128 -0
  50. package/dist/src/exec/env.js +190 -0
  51. package/dist/src/fleet.d.ts +51 -0
  52. package/dist/src/fleet.js +80 -0
  53. package/dist/src/gates/adapters/http-json.d.ts +5 -0
  54. package/dist/src/gates/adapters/http-json.js +283 -0
  55. package/dist/src/gates/adapters/migrations-command.d.ts +1 -0
  56. package/dist/src/gates/adapters/migrations-command.js +373 -0
  57. package/dist/src/gates/citations.d.ts +408 -0
  58. package/dist/src/gates/citations.js +1163 -0
  59. package/dist/src/gates/coverage.d.ts +284 -0
  60. package/dist/src/gates/coverage.js +701 -0
  61. package/dist/src/gates/credentials.d.ts +74 -0
  62. package/dist/src/gates/credentials.js +533 -0
  63. package/dist/src/gates/deploy.d.ts +1 -0
  64. package/dist/src/gates/deploy.js +33 -0
  65. package/dist/src/gates/manifest.d.ts +99 -0
  66. package/dist/src/gates/manifest.js +208 -0
  67. package/dist/src/gates/migrations.d.ts +1 -0
  68. package/dist/src/gates/migrations.js +36 -0
  69. package/dist/src/gates/pin.d.ts +114 -0
  70. package/dist/src/gates/pin.js +154 -0
  71. package/dist/src/gates/red-witness.d.ts +22 -0
  72. package/dist/src/gates/red-witness.js +390 -0
  73. package/dist/src/gates/release.d.ts +283 -0
  74. package/dist/src/gates/release.js +820 -0
  75. package/dist/src/gates/result.d.ts +116 -0
  76. package/dist/src/gates/result.js +91 -0
  77. package/dist/src/gates/run.d.ts +566 -0
  78. package/dist/src/gates/run.js +1536 -0
  79. package/dist/src/gates/schemas/citation-config.schema.json +59 -0
  80. package/dist/src/gates/schemas/coverage-config.schema.json +77 -0
  81. package/dist/src/gates/schemas/gate-manifest.schema.json +125 -0
  82. package/dist/src/gates/schemas/gate-result.schema.json +160 -0
  83. package/dist/src/gates/schemas/phase-declaration.schema.json +42 -0
  84. package/dist/src/gates/schemas/release-record.schema.json +119 -0
  85. package/dist/src/gates/schemas/verifier-config.schema.json +101 -0
  86. package/dist/src/gates/schemas/witness-spec.schema.json +110 -0
  87. package/dist/src/gates/scope.d.ts +131 -0
  88. package/dist/src/gates/scope.js +1018 -0
  89. package/dist/src/gates/suite.d.ts +217 -0
  90. package/dist/src/gates/suite.js +927 -0
  91. package/dist/src/gates/validate.d.ts +121 -0
  92. package/dist/src/gates/validate.js +414 -0
  93. package/dist/src/hooks.d.ts +32 -0
  94. package/dist/src/hooks.js +62 -0
  95. package/dist/src/liveness.d.ts +321 -0
  96. package/dist/src/liveness.js +396 -0
  97. package/dist/src/lock.d.ts +178 -0
  98. package/dist/src/lock.js +500 -0
  99. package/dist/src/modes.d.ts +149 -0
  100. package/dist/src/modes.js +258 -0
  101. package/dist/src/path-identity.d.ts +2 -0
  102. package/dist/src/path-identity.js +10 -0
  103. package/dist/src/plan.d.ts +73 -0
  104. package/dist/src/plan.js +153 -0
  105. package/dist/src/pool.d.ts +130 -0
  106. package/dist/src/pool.js +721 -0
  107. package/dist/src/roles.d.ts +430 -0
  108. package/dist/src/roles.js +734 -0
  109. package/dist/src/spawn.d.ts +177 -0
  110. package/dist/src/spawn.js +332 -0
  111. package/dist/src/status.d.ts +91 -0
  112. package/dist/src/status.js +119 -0
  113. package/dist/src/task.d.ts +264 -0
  114. package/dist/src/task.js +305 -0
  115. package/dist/src/teardown.d.ts +32 -0
  116. package/dist/src/teardown.js +314 -0
  117. package/dist/src/tuition.d.ts +159 -0
  118. package/dist/src/tuition.js +311 -0
  119. package/dist/src/validate.d.ts +230 -0
  120. package/dist/src/validate.js +732 -0
  121. package/dist/src/version.d.ts +3 -0
  122. package/dist/src/version.js +38 -0
  123. package/dist/src/watcher.d.ts +275 -0
  124. package/dist/src/watcher.js +859 -0
  125. package/dist/src/witness/run.d.ts +274 -0
  126. package/dist/src/witness/run.js +1327 -0
  127. package/dist/src/witness/spec.d.ts +102 -0
  128. package/dist/src/witness/spec.js +253 -0
  129. package/dist/tsconfig.src.tsbuildinfo +1 -0
  130. package/gate-registry.yaml +390 -0
  131. package/gates.manifest.json +195 -0
  132. package/package.json +57 -3
  133. package/role-model-config.yaml +88 -0
  134. package/roles/README.md +128 -0
  135. package/roles/_shared-dispatch-contract.md +87 -0
  136. package/roles/adversarial-plan-reviewer.md +80 -0
  137. package/roles/clean-room-reviewer.md +140 -0
  138. package/roles/implementer.md +460 -0
  139. package/roles/investigator.md +138 -0
  140. package/roles/plan-writer.md +95 -0
  141. package/schemas/README.md +81 -0
  142. package/schemas/assurance-modes.schema.json +264 -0
  143. package/schemas/charter.schema.json +166 -0
  144. package/schemas/checklist.schema.json +114 -0
  145. package/schemas/decision-record.schema.json +88 -0
  146. package/schemas/final-report.schema.json +90 -0
  147. package/schemas/finding.schema.json +106 -0
  148. package/schemas/gate-registry.schema.json +260 -0
  149. package/schemas/mechanism-index.schema.json +94 -0
  150. package/schemas/plan.schema.json +300 -0
  151. package/schemas/report.schema.json +579 -0
  152. package/schemas/role-brief.schema.json +105 -0
  153. package/schemas/role-model-config.schema.json +90 -0
  154. package/schemas/status-line.schema.json +40 -0
  155. package/schemas/tuition.schema.json +191 -0
  156. package/schemas/verdict.schema.json +289 -0
  157. package/schemas/work-history.schema.json +183 -0
  158. package/templates/charter.example.yaml +54 -0
  159. package/templates/decision-record.example.yaml +27 -0
  160. package/templates/final-report.example.yaml +80 -0
  161. package/templates/plan.example.yaml +87 -0
  162. package/templates/report.example.yaml +236 -0
  163. package/templates/warnings.md +74 -0
  164. package/templates/work-history.example.yaml +185 -0
  165. package/tuition/README.md +76 -0
  166. package/tuition/T-001.yaml +48 -0
  167. package/tuition/T-002.yaml +51 -0
  168. package/tuition/T-003.yaml +100 -0
  169. package/tuition/T-004.yaml +52 -0
  170. package/tuition/T-005.yaml +72 -0
  171. package/tuition/T-006.yaml +81 -0
  172. package/tuition/T-007.yaml +56 -0
  173. package/tuition/T-008.yaml +111 -0
  174. package/tuition/T-009.yaml +50 -0
  175. package/tuition/T-015.yaml +36 -0
  176. package/tuition/T-016.yaml +36 -0
  177. package/tuition/T-017.yaml +46 -0
  178. package/tuition/T-018.yaml +84 -0
  179. package/tuition/T-021.yaml +40 -0
  180. package/tuition/T-022.yaml +36 -0
  181. package/tuition/mechanism-index.yaml +256 -0
@@ -0,0 +1,390 @@
1
+ # THE CANONICAL GATE REGISTRY (kernel plan M3, M3-P2; R-094).
2
+ #
3
+ # This file is the canonical DECLARATION of this repository's gates, and R-094
4
+ # asks for one source that CI and the briefs both read. HOW FAR THAT IS TRUE
5
+ # TODAY, stated in the present tense only where it is:
6
+ #
7
+ # BRIEFS: delivered. The agent-rules gate section in CLAUDE.md is GENERATED
8
+ # from this file by `scripts/render-agent-rules-gates.mjs`. Editing that
9
+ # block by hand makes `node scripts/render-agent-rules-gates.mjs --check`
10
+ # exit nonzero, and the `gates` workflow runs that command as a step on both
11
+ # CI events, so a hand edit fails the build. Edit this file instead.
12
+ #
13
+ # CI: NOT YET. The `gates` workflow calls `scripts/m2-exit-test.sh`, which
14
+ # invokes the runner with `--manifest gates.manifest.json` on both arms.
15
+ # `--registry` occurs nowhere in either file. So a gate declared ONLY here
16
+ # does not run in CI, and `agent-rules-drift` is exactly that case: it runs
17
+ # because the workflow also carries a direct step for it. Closing this needs
18
+ # an edit to `scripts/m2-exit-test.sh`, which is not on M3-P2's declaration
19
+ # and is tracked with the orchestrator. The divergence is not left to be
20
+ # noticed: `test/gate-registry.test.ts` asserts it in BOTH directions, so a
21
+ # NEW script gate declared only here reddens rather than silently not
22
+ # running.
23
+ #
24
+ # PROMOTED, NOT INVENTED. Every `script` entry below is the M2-P1
25
+ # `gates.manifest.json` entry of the same id, carried across with its
26
+ # `command`, `unitLabel`, `applicability`, `parameters` and `precondition`
27
+ # byte-for-byte, plus the three fields this registry adds (`verified-by`,
28
+ # `modes`, `events`). SC-011's precondition semantics travel with the
29
+ # precondition blocks unchanged: a gate whose precondition is unmet reports
30
+ # not-applicable and NEVER green.
31
+ #
32
+ # WHAT IS NOT HERE, stated rather than left to be noticed. Kernel plan M3
33
+ # step 3 names project-specific gates `i18n`, `analytics`, `manifest regen`,
34
+ # `e2e` and `docs grep` as things to keep "declared-but-not-applicable on the
35
+ # kernel exactly as M2-P1 left them". M2-P1 left them NOWHERE: the delivered
36
+ # `gates.manifest.json` on main at 40427b6 declares eleven gates and none of
37
+ # those five is among them. Promoting a gate M2 never shipped would be
38
+ # inventing it, not promoting it, so the two entries that ARE structurally
39
+ # not-applicable on the kernel (`deploy`, `migrations`) are carried across and
40
+ # the other five are recorded as absent here and in
41
+ # delivery/work-history/m3-p2.md rather than fabricated.
42
+
43
+ kind: gate-registry
44
+ version: 1
45
+
46
+ # The ordered local commands every change must pass. Rendered into CLAUDE.md's
47
+ # gate section together with the table below, so that section has no
48
+ # hand-maintained list in it (M3-P2 criterion 6).
49
+ preflight:
50
+ - command: [npm, ci]
51
+ note: install exactly the lockfile, npm only, never pnpm or yarn
52
+ - command: [npm, run, build]
53
+ note: the type gate (tsc -b); emits dist/, which is never committed, and git status must be clean afterwards
54
+ - command: [node, --test]
55
+ note: sources are TypeScript run natively via Node type stripping, so the suite needs no prior build
56
+
57
+ gates:
58
+ - id: manifest-self-check
59
+ command: [node, bin/tiphys.ts, gates, self-check, --manifest, gates.manifest.json]
60
+ unitLabel: schema documents validated
61
+ applicability: required
62
+ verified-by: script
63
+ modes: [full, direct-pr, local-only]
64
+ events: [pull_request, push]
65
+
66
+ - id: coverage
67
+ command: [node, src/gates/coverage.ts]
68
+ unitLabel: finding ids checked
69
+ applicability: required
70
+ verified-by: script
71
+ modes: [full, direct-pr]
72
+ events: [pull_request, push]
73
+ precondition:
74
+ id: coverage-inventory-exists
75
+ kind: file-exists
76
+ path: delivery/requirements/migration-table.md
77
+
78
+ - id: credential-scrub
79
+ command: [node, src/gates/credentials.ts, credential-scrub]
80
+ unitLabel: credential sources probed
81
+ applicability: required
82
+ verified-by: script
83
+ modes: [full, direct-pr, local-only]
84
+ events: [pull_request, push]
85
+
86
+ - id: credential-token
87
+ command: [node, src/gates/credentials.ts, credential-token]
88
+ unitLabel: tokens probed
89
+ applicability: conditional
90
+ verified-by: script
91
+ modes: [full, direct-pr]
92
+ events: [pull_request]
93
+ precondition:
94
+ id: implementer-token-present-owner-action-a-3
95
+ kind: command-exit-zero
96
+ command: [node, -e, "process.exit(process.env.TIPHYS_IMPLEMENTER_TOKEN === undefined ? 1 : 0)"]
97
+
98
+ - id: suite
99
+ command: [node, src/gates/suite.ts, --pin-root, src, --pin-root, bin, --pin-root, test]
100
+ unitLabel: tests reported
101
+ applicability: required
102
+ verified-by: script
103
+ modes: [full, direct-pr, local-only]
104
+ events: [pull_request, push]
105
+ parameters: [base]
106
+
107
+ - id: citations
108
+ command: [node, src/gates/citations.ts]
109
+ unitLabel: citations resolved
110
+ applicability: required
111
+ verified-by: script
112
+ modes: [full, direct-pr]
113
+ events: [pull_request]
114
+ precondition:
115
+ id: citations-diff-touches-documents
116
+ kind: diff-touches
117
+ paths:
118
+ - delivery/plan/
119
+ - delivery/verification/
120
+ - delivery/decisions/
121
+ - delivery/tuition/
122
+ - delivery/requirements/
123
+ - delivery/STATE.md
124
+
125
+ - id: scope
126
+ command: [node, src/gates/scope.ts, --declarations, delivery/plan/phase-declarations]
127
+ unitLabel: changed paths audited
128
+ applicability: required
129
+ verified-by: script
130
+ modes: [full, direct-pr]
131
+ events: [pull_request]
132
+ parameters: [base, head]
133
+ precondition:
134
+ id: scope-branch-is-a-phase-branch
135
+ kind: branch-matches
136
+ pattern: claude/m[0-9]+-p[0-9]+-.*
137
+
138
+ - id: deploy
139
+ command: [node, src/gates/deploy.ts]
140
+ unitLabel: release verifications satisfied
141
+ applicability: conditional
142
+ verified-by: script
143
+ modes: [full]
144
+ events: [pull_request, push]
145
+ precondition:
146
+ id: "deploy-release-verification-declared (an unmet result here is STRUCTURAL in any pre-merge bundle, not local to this repository: release verification runs post-merge against a commit that exists only once the merge has happened; kernel plan M2 section 1.4, investigation observation O-3)"
147
+ kind: file-exists
148
+ path: release-verification.json
149
+
150
+ - id: migrations
151
+ command: [node, src/gates/migrations.ts]
152
+ unitLabel: migrations compared
153
+ applicability: conditional
154
+ verified-by: script
155
+ modes: [full]
156
+ events: [pull_request, push]
157
+ precondition:
158
+ id: "migrations-release-verification-declared (an unmet result here is STRUCTURAL in any pre-merge bundle, not local to this repository: release verification runs post-merge against a commit that exists only once the merge has happened; kernel plan M2 section 1.4, investigation observation O-3)"
159
+ kind: file-exists
160
+ path: release-verification.json
161
+
162
+ - id: clause-map
163
+ command: [node, scripts/check-clause-map.mjs]
164
+ unitLabel: clause-map rows checked
165
+ applicability: required
166
+ verified-by: script
167
+ modes: [full, direct-pr]
168
+ events: [pull_request]
169
+
170
+ - id: red-witness
171
+ command: [node, src/gates/red-witness.ts]
172
+ unitLabel: witnesses evaluated
173
+ applicability: required
174
+ verified-by: script
175
+ modes: [full, direct-pr]
176
+ events: [pull_request]
177
+ parameters: [base, head]
178
+ precondition:
179
+ id: red-witness-diff
180
+ kind: diff-touches
181
+ paths:
182
+ - src/
183
+ - bin/
184
+
185
+ # NEW IN M3-P2, entry one of three.
186
+ - id: agent-rules-drift
187
+ $comment: >-
188
+ R-094. The check that makes the BRIEFS half of "single source consumed by
189
+ CI and briefs" true rather than asserted: it re-renders CLAUDE.md's gate
190
+ block from this file and fails when the two differ. It is declared here
191
+ because D-M3-34 requires every M3 check to be declared in the registry,
192
+ and its `events` say which arms evaluate it. What actually EXECUTES it in
193
+ CI today is a step in the `gates` workflow, not this entry, because CI
194
+ runs `--manifest gates.manifest.json`; see this file's header. Both arms
195
+ are declared, and the workflow step carries no `if:`, because CLAUDE.md
196
+ drift is a property of `main`, not of a pull request (T-009).
197
+ command: [node, scripts/render-agent-rules-gates.mjs, --check]
198
+ unitLabel: rendered gate rows compared
199
+ applicability: required
200
+ verified-by: script
201
+ modes: [full, direct-pr, local-only]
202
+ events: [pull_request, push]
203
+
204
+ # NEW IN M3-P6 (R-094, D-M3-28, D-M3-34).
205
+ - id: brief-drift
206
+ $comment: >-
207
+ R-094's briefs half, applied to roles/implementer.md the way
208
+ agent-rules-drift applies it to CLAUDE.md: the brief's gate-list section is
209
+ a generated projection of THIS file for the mode its own begin marker
210
+ declares, and this check re-renders and compares. UNLIKE agent-rules-drift,
211
+ it is ALSO in gates.manifest.json, so on a pull request the runner executes
212
+ it as a real gate with a GateResult and M2-C-2's vacuity protection rather
213
+ than as a raw workflow step. WHY `events` IS pull_request ALONE, stated
214
+ exactly because "declared" and "runs" are not the same thing: the push arm
215
+ of scripts/m2-exit-test.sh has a hard-coded `--only` list of six gate ids
216
+ and that script is on no M3 phase's declaration, so a manifest gate outside
217
+ that list cannot run on push, and test/gate-registry.test.ts asserts
218
+ `events` against the harness rather than against a wish. The push arm is
219
+ covered instead by a direct step in .github/workflows/gates.yml carrying no
220
+ `if:`, because brief drift is a property of the default branch and not only
221
+ of a pull request (T-009). Both arms have a witness; they are not the same
222
+ witness, and that is recorded here rather than left to be discovered.
223
+ AND WHICH HALF IS THE TEETH, measured rather than assumed, because the
224
+ sentence above says the runner EXECUTES this as a gate and a reader could
225
+ take that to mean a red one fails the pull request. It does not on its own:
226
+ scripts/m2-exit-test.sh's PR expectation table lists eleven gate ids and
227
+ this is not one of them, and its assertion program compares only gates that
228
+ table names, plus global zero-error and zero-vacuous checks over every row
229
+ with no global zero-red. So an `error` here is caught by the harness and a
230
+ plain `red` is caught by the workflow step, which carries no `if:` and
231
+ therefore fails the job on either event. Adding a table row is an edit to
232
+ that harness, which is on no M3 phase's declaration.
233
+ command: [node, scripts/check-brief-drift.mjs, --check]
234
+ unitLabel: generated brief gate rows compared
235
+ applicability: required
236
+ verified-by: script
237
+ modes: [full, direct-pr, local-only]
238
+ events: [pull_request]
239
+
240
+ # NEW IN M3-P9, entry one of two (D-M3-34, section 2.2a).
241
+ - id: check-agents-references
242
+ $comment: >-
243
+ M3-P9 step 5. Every path `AGENTS.md` references exists AND the ANCHOR it
244
+ names occurs inside that path (criterion 2b), and `AGENTS.md` carries no
245
+ gate id list, no mode table and no model-tier table (criterion 3), because
246
+ section 1.5's anti-duplication rule is what stops the orchestrator brief
247
+ drifting away from the registry it summarizes. WHY BOTH EVENTS: a broken
248
+ reference on `main` is the state that matters, not only one proposed in a
249
+ pull request, which is T-009's rule that where behaviour forks on the CI
250
+ event both arms need a witness. WHAT EXECUTES IT IN CI, stated rather than
251
+ implied: `scripts/m2-exit-test.sh` invokes the runner with `--manifest
252
+ gates.manifest.json` on both arms and that file is on no M3 phase's
253
+ declaration, so a registry-only gate does not run through the runner.
254
+ A step in `.github/workflows/gates.yml` carrying no `if:` is what runs it,
255
+ exactly as for `agent-rules-drift`, and `test/gate-registry.test.ts`
256
+ records the divergence with its reason so the gap is declared rather than
257
+ discovered.
258
+ command: [node, scripts/check-agents-references.mjs]
259
+ unitLabel: references resolved
260
+ applicability: required
261
+ verified-by: script
262
+ modes: [full, direct-pr, local-only]
263
+ events: [pull_request, push]
264
+
265
+ # NEW IN M3-P9, entry two of two (M3R-004, DR-0012, T-001, T-007, D-M3-34).
266
+ - id: check-dual-review
267
+ $comment: >-
268
+ M3-P9 step 3b. The `decorrelated-review` duty made into a command with an
269
+ exit code: two verdicts for one head, distinct `produced-by` model
270
+ families (DR-0012 condition 1), distinct `framing` values (T-001), and
271
+ distinct `review-contract` values (T-007). The comparison itself is the
272
+ Kind B derived check `dual-review-decorrelation` in `src/checks.ts`; this
273
+ script is the runner around it, so deregistering the check is a real
274
+ witness rather than a simulated one (section 2.3 rule 3).
275
+ `events: [pull_request]` ALONE, and the reason is the plan's own: a merged
276
+ head has no pair of verdicts to compare. The PRECONDITION is what keeps
277
+ that from becoming a vacuous green: a gate that cannot reach a verdict
278
+ reports not-applicable with a reason, never green, which is M2-C-3 and
279
+ SC-011 applied to M3's own check. It probes with the script's own
280
+ `--precondition` arm rather than a `file-exists` path, because the
281
+ question is whether any verdict DOCUMENT exists under `delivery/review/`
282
+ and not whether that directory does; this repository has the directory and
283
+ has never had a verdict document in it.
284
+ command: [node, scripts/check-dual-review.mjs, .]
285
+ unitLabel: review verdicts examined for decorrelation
286
+ applicability: conditional
287
+ verified-by: script
288
+ modes: [full, direct-pr]
289
+ events: [pull_request]
290
+ precondition:
291
+ id: dual-review-verdicts-present
292
+ kind: command-exit-zero
293
+ command: [node, scripts/check-dual-review.mjs, --precondition, .]
294
+
295
+ # NEW IN M3-P10 (EXT-F-09, DR-0013 clause 5, D-M3-34).
296
+ - id: license
297
+ $comment: >-
298
+ M3-P10 step 2. EXT-F-09's five checks as one command with one exit code:
299
+ inventory the TRANSITIVE production dependency set, require license
300
+ metadata on every member, refuse any license off the declared allowlist,
301
+ require THIRD-PARTY-NOTICES whenever copied third-party code is declared
302
+ (plan v1 D-1's license note makes this declaration-driven, because
303
+ protocol reimplementation carries no notice obligation), and require
304
+ LICENSE in the `npm pack` listing. WHY IT IS A GATE AND NOT ONLY A RELEASE
305
+ STEP: what ships is a property of every change, not of the release that
306
+ happens to notice it, and DR-0013 marked a grown production tree the
307
+ costly direction. WHERE IT RUNS, STATED AS WHAT IS TRUE RATHER THAN AS AN
308
+ ABSOLUTE (corrected in M3-P10 fix round 1, clean-room finding HRB-7):
309
+ `.github/workflows/release.yml` runs it as an explicit STEP before
310
+ publishing, which is the enforcement point because it depends on no
311
+ lifecycle hook; `prepublishOnly` runs it on every publish path that runs
312
+ lifecycle scripts, and `--ignore-scripts` skips it, measured on npm
313
+ 11.18.0. The earlier wording said no publish path at all could skip it,
314
+ and that was false in a file that SHIPS. BOTH EVENTS, and the
315
+ reason is T-009's: a dependency added on `main` by a merge is exactly the
316
+ state that matters, and an arm with no witness is the arm that breaks.
317
+ WHAT EXECUTES IT IN CI, stated rather than implied: `scripts/m2-exit-test.sh`
318
+ invokes the runner with `--manifest gates.manifest.json` on both arms and
319
+ that file is on no M3 phase's declaration, so a registry-only gate does not
320
+ reach the runner. A step in `.github/workflows/gates.yml` carrying no `if:`
321
+ is what runs it, exactly as for `agent-rules-drift` and
322
+ `check-agents-references`, and `test/gate-registry.test.ts` records the
323
+ divergence with its reason so the gap is declared rather than discovered.
324
+ NOT CONDITIONAL, DELIBERATELY: there is no tree here with no production
325
+ dependencies, so a precondition would be a not-applicable arm that can
326
+ never be reached, and M2-C-2 already refuses a green with zero units.
327
+ command: [node, scripts/license-gate.mjs]
328
+ unitLabel: production packages licensed
329
+ applicability: required
330
+ verified-by: script
331
+ modes: [full, direct-pr, local-only]
332
+ events: [pull_request, push]
333
+
334
+ # NEW IN M3-P2, entry two of three (R-043, D-11).
335
+ - id: unit-tests-for-changed-service-methods
336
+ $comment: >-
337
+ R-043. Every changed service method has a unit test. D-11 settles that
338
+ this is NOT reliably computable from a diff (mapping changed methods to
339
+ tests produces false positives and negatives on any nontrivial codebase),
340
+ so it is verified by a clean-room checklist probe at L3 rather than by a
341
+ script at L1, and the registry says so in `verified-by` instead of leaving
342
+ a reader to infer it from a missing command. The probe id below is
343
+ M3-P7's to supply. WHAT THE RUNNER DOES WITH THIS ENTRY, stated exactly
344
+ because criterion 3c is about not confusing these two: it is NOT
345
+ executed and its precondition is NOT evaluated. There is no command to
346
+ run, so the runner selects it out before any precondition is reached and
347
+ reports it on stdout and in `summary.declaredByChecklist` as declared
348
+ and not executed. It produces no record, no evidence directory and no
349
+ status, and `not-applicable` is not among the things it can report. The
350
+ `precondition` below is a DECLARATION for M3-P7's checklist, not
351
+ something this runner evaluates.
352
+ unitLabel: changed service methods checked
353
+ applicability: conditional
354
+ verified-by: clean-room-checklist
355
+ probe: unit-tests-for-changed-service-methods
356
+ modes: [full, direct-pr]
357
+ events: [pull_request]
358
+ precondition:
359
+ id: clean-room-checklist-present
360
+ kind: file-exists
361
+ path: checklists/clean-room.yaml
362
+
363
+ # NEW IN M3-P2, entry three of three (R-044, D-11).
364
+ - id: fixtures-for-changed-component-states
365
+ $comment: >-
366
+ R-044. Every changed component state has a story or fixture. Same shape as
367
+ R-043 and settled the same way by D-11: "component state" is not
368
+ machine-enumerable, so the gate is a clean-room checklist probe. Not
369
+ executed and its precondition not evaluated, for the reason spelled out
370
+ on the entry above. Same declared precondition, so M3-P7's checklist is
371
+ what both wait on.
372
+ unitLabel: changed component states checked
373
+ applicability: conditional
374
+ verified-by: clean-room-checklist
375
+ probe: fixtures-for-changed-component-states
376
+ modes: [full, direct-pr]
377
+ events: [pull_request]
378
+ precondition:
379
+ id: clean-room-checklist-present
380
+ kind: file-exists
381
+ path: checklists/clean-room.yaml
382
+
383
+ # Carried across from gates.manifest.json unchanged. M2-P2 rule (e) DERIVES a
384
+ # witness class from this list rather than trusting an implementer to declare
385
+ # one, so shortening it weakens the red-witness gate.
386
+ destructiveCommands:
387
+ - pool destroy
388
+ - teardown
389
+ - src/pool.ts
390
+ - src/teardown.ts
@@ -0,0 +1,195 @@
1
+ {
2
+ "note": "This is the KERNEL'S OWN manifest and is repository-local by construction: gate commands invoke bin/tiphys.ts, which npm pack does not ship (files is [\"dist\"]). In CI the RUNNER is the compiled entry (dist/bin/tiphys.js, per kernel plan M2 step 9) while this gate is the source entry, so the runner resolves dist/src/gates/schemas and the gate resolves src/gates/schemas. Both copies are therefore exercised on every CI run, the runner's by its manifest load and record ingest and the gate's by self-check. Recorded here rather than left ambiguous (CR-813).",
3
+ "version": 1,
4
+ "gates": [
5
+ {
6
+ "id": "manifest-self-check",
7
+ "command": [
8
+ "node",
9
+ "bin/tiphys.ts",
10
+ "gates",
11
+ "self-check",
12
+ "--manifest",
13
+ "gates.manifest.json"
14
+ ],
15
+ "unitLabel": "schema documents validated",
16
+ "applicability": "required"
17
+ },
18
+ {
19
+ "id": "coverage",
20
+ "command": [
21
+ "node",
22
+ "src/gates/coverage.ts"
23
+ ],
24
+ "unitLabel": "finding ids checked",
25
+ "applicability": "required",
26
+ "precondition": {
27
+ "id": "coverage-inventory-exists",
28
+ "kind": "file-exists",
29
+ "path": "delivery/requirements/migration-table.md"
30
+ }
31
+ },
32
+ {
33
+ "id": "credential-scrub",
34
+ "command": [
35
+ "node",
36
+ "src/gates/credentials.ts",
37
+ "credential-scrub"
38
+ ],
39
+ "unitLabel": "credential sources probed",
40
+ "applicability": "required"
41
+ },
42
+ {
43
+ "id": "credential-token",
44
+ "command": [
45
+ "node",
46
+ "src/gates/credentials.ts",
47
+ "credential-token"
48
+ ],
49
+ "unitLabel": "tokens probed",
50
+ "applicability": "conditional",
51
+ "precondition": {
52
+ "id": "implementer-token-present-owner-action-a-3",
53
+ "kind": "command-exit-zero",
54
+ "command": [
55
+ "node",
56
+ "-e",
57
+ "process.exit(process.env.TIPHYS_IMPLEMENTER_TOKEN === undefined ? 1 : 0)"
58
+ ]
59
+ }
60
+ },
61
+ {
62
+ "id": "suite",
63
+ "command": [
64
+ "node",
65
+ "src/gates/suite.ts",
66
+ "--pin-root",
67
+ "src",
68
+ "--pin-root",
69
+ "bin",
70
+ "--pin-root",
71
+ "test"
72
+ ],
73
+ "unitLabel": "tests reported",
74
+ "applicability": "required",
75
+ "parameters": [
76
+ "base"
77
+ ]
78
+ },
79
+ {
80
+ "id": "citations",
81
+ "command": [
82
+ "node",
83
+ "src/gates/citations.ts"
84
+ ],
85
+ "unitLabel": "citations resolved",
86
+ "applicability": "required",
87
+ "precondition": {
88
+ "id": "citations-diff-touches-documents",
89
+ "kind": "diff-touches",
90
+ "paths": [
91
+ "delivery/plan/",
92
+ "delivery/verification/",
93
+ "delivery/decisions/",
94
+ "delivery/tuition/",
95
+ "delivery/requirements/",
96
+ "delivery/STATE.md"
97
+ ]
98
+ }
99
+ },
100
+ {
101
+ "id": "scope",
102
+ "command": [
103
+ "node",
104
+ "src/gates/scope.ts",
105
+ "--declarations",
106
+ "delivery/plan/phase-declarations"
107
+ ],
108
+ "unitLabel": "changed paths audited",
109
+ "applicability": "required",
110
+ "parameters": [
111
+ "base",
112
+ "head"
113
+ ],
114
+ "precondition": {
115
+ "id": "scope-branch-is-a-phase-branch",
116
+ "kind": "branch-matches",
117
+ "pattern": "claude/m[0-9]+-p[0-9]+-.*"
118
+ }
119
+ },
120
+ {
121
+ "id": "deploy",
122
+ "command": [
123
+ "node",
124
+ "src/gates/deploy.ts"
125
+ ],
126
+ "unitLabel": "release verifications satisfied",
127
+ "applicability": "conditional",
128
+ "precondition": {
129
+ "id": "deploy-release-verification-declared (an unmet result here is STRUCTURAL in any pre-merge bundle, not local to this repository: release verification runs post-merge against a commit that exists only once the merge has happened; kernel plan M2 section 1.4, investigation observation O-3)",
130
+ "kind": "file-exists",
131
+ "path": "release-verification.json"
132
+ }
133
+ },
134
+ {
135
+ "id": "migrations",
136
+ "command": [
137
+ "node",
138
+ "src/gates/migrations.ts"
139
+ ],
140
+ "unitLabel": "migrations compared",
141
+ "applicability": "conditional",
142
+ "precondition": {
143
+ "id": "migrations-release-verification-declared (an unmet result here is STRUCTURAL in any pre-merge bundle, not local to this repository: release verification runs post-merge against a commit that exists only once the merge has happened; kernel plan M2 section 1.4, investigation observation O-3)",
144
+ "kind": "file-exists",
145
+ "path": "release-verification.json"
146
+ }
147
+ },
148
+ {
149
+ "id": "clause-map",
150
+ "command": [
151
+ "node",
152
+ "scripts/check-clause-map.mjs"
153
+ ],
154
+ "unitLabel": "clause-map rows checked",
155
+ "applicability": "required"
156
+ },
157
+ {
158
+ "id": "red-witness",
159
+ "command": [
160
+ "node",
161
+ "src/gates/red-witness.ts"
162
+ ],
163
+ "unitLabel": "witnesses evaluated",
164
+ "applicability": "required",
165
+ "parameters": [
166
+ "base",
167
+ "head"
168
+ ],
169
+ "precondition": {
170
+ "id": "red-witness-diff",
171
+ "kind": "diff-touches",
172
+ "paths": [
173
+ "src/",
174
+ "bin/"
175
+ ]
176
+ }
177
+ },
178
+ {
179
+ "id": "brief-drift",
180
+ "command": [
181
+ "node",
182
+ "scripts/check-brief-drift.mjs",
183
+ "--check"
184
+ ],
185
+ "unitLabel": "generated brief gate rows compared",
186
+ "applicability": "required"
187
+ }
188
+ ],
189
+ "destructiveCommands": [
190
+ "pool destroy",
191
+ "teardown",
192
+ "src/pool.ts",
193
+ "src/teardown.ts"
194
+ ]
195
+ }
package/package.json CHANGED
@@ -1,7 +1,61 @@
1
1
  {
2
2
  "name": "@tiphys/kernel",
3
- "version": "0.0.0",
4
- "description": "Placeholder. Reserved for the Tiphys delivery-process kernel. Do not install.",
3
+ "version": "0.1.0",
4
+ "description": "Tiphys kernel: the fleet orchestration toolbelt, delivered as an npm package.",
5
+ "type": "module",
5
6
  "license": "Apache-2.0",
6
- "private": false
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/ThomasHendrickx/tiphys-ai-helmsman.git"
10
+ },
11
+ "engines": {
12
+ "node": ">=26"
13
+ },
14
+ "bin": {
15
+ "tiphys": "dist/bin/tiphys.js"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "!dist/node_modules",
20
+ "LICENSE",
21
+ "AGENTS.md",
22
+ "gate-registry.yaml",
23
+ "gates.manifest.json",
24
+ "assurance-modes.yaml",
25
+ "checklists",
26
+ "role-model-config.yaml",
27
+ "roles",
28
+ "schemas",
29
+ "templates",
30
+ "tuition"
31
+ ],
32
+ "scripts": {
33
+ "build": "tsc -b tsconfig.src.json tsconfig.test.json && npm run build:schemas && npm run build:runtime-deps",
34
+ "build:schemas": "node --input-type=module -e \"import { cpSync } from 'node:fs'; cpSync('src/gates/schemas', 'dist/src/gates/schemas', { recursive: true });\"",
35
+ "build:runtime-deps": "node --input-type=module -e \"import { cpSync, readFileSync } from 'node:fs'; const lock = JSON.parse(readFileSync('node_modules/.package-lock.json', 'utf8')); for (const [path, entry] of Object.entries(lock.packages ?? {})) { if (!path.startsWith('node_modules/') || entry?.dev === true) continue; cpSync(path, 'dist/' + path, { recursive: true }); }\"",
36
+ "test": "node --test \"test/**/*.test.ts\"",
37
+ "gate:suite": "node src/gates/suite.ts --pin-root src --pin-root bin --pin-root test",
38
+ "prepack": "npm run build",
39
+ "gate:license": "node scripts/license-gate.mjs",
40
+ "prepublishOnly": "node scripts/license-gate.mjs"
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "26.1.2",
44
+ "typescript": "7.0.2"
45
+ },
46
+ "dependencies": {
47
+ "ajv": "8.20.0",
48
+ "commonmark": "0.31.2",
49
+ "yaml": "2.9.0"
50
+ },
51
+ "tiphys": {
52
+ "licenseAllowlist": [
53
+ "Apache-2.0",
54
+ "MIT",
55
+ "ISC",
56
+ "BSD-2-Clause",
57
+ "BSD-3-Clause"
58
+ ],
59
+ "thirdPartyCode": []
60
+ }
7
61
  }