@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,828 @@
1
+ /**
2
+ * THE DERIVED-CHECK REGISTRY (kernel plan M3, section 2.3 Kind B; step 8).
3
+ *
4
+ * JSON Schema expresses properties of ONE document reachable by one keyword.
5
+ * A property that compares array elements to each other, resolves a reference
6
+ * into another document, computes arithmetic over sibling fields or touches
7
+ * the filesystem is not expressible by any keyword under any DR-0013 option,
8
+ * and this module is where the plan stopped pretending otherwise (M3R-002).
9
+ *
10
+ * Each check runs AFTER schema validation succeeds and reports through the
11
+ * same contract with its own id attached:
12
+ *
13
+ * INVALID <json-pointer> <message> (check: <check-id>)
14
+ *
15
+ * A check that needs a CONTEXT it was not given reports
16
+ * `SKIPPED <check-id> no context` and the command exits nonzero. That is the
17
+ * whole point of the mechanism: a cross-document rule must never be able to
18
+ * pass BY NOT RUNNING, which is the vacuous-pass shape SC-011 and M2-C-2 both
19
+ * exist to prevent, one layer up.
20
+ *
21
+ * DR-0013 clause 8: Kind B rules stay HERE and are never encoded as Ajv
22
+ * extensions. The Kind A / Kind B boundary is binding.
23
+ *
24
+ * D-M3-22: a check that belongs in section 2.3's table and is not in it is a
25
+ * PLAN DEFECT to escalate, not a script to add quietly.
26
+ */
27
+ import type { Diagnostic } from "./validate.ts";
28
+ /** What one derived check produced. */
29
+ export interface CheckOutcome {
30
+ /** Violations, each of which makes the command exit nonzero. */
31
+ violations: Diagnostic[];
32
+ /**
33
+ * Lines the check REPORTS rather than fails on. `plan-dispatchable` is the
34
+ * instance: a phase whose `fill-in` is present and unfilled is valid for
35
+ * REVIEW and invalid for DISPATCH, so the validator computes and reports
36
+ * it instead of rejecting the document.
37
+ */
38
+ reports: string[];
39
+ }
40
+ export interface DerivedCheck {
41
+ id: string;
42
+ /** The artifact type this check is registered for. */
43
+ type: string;
44
+ /**
45
+ * THE OTHER artifact types this check must ALSO run on. Added by M3-P4 fix
46
+ * round 2 for CR-001, whose MECHANISM is worth stating at the field rather
47
+ * than at the one check that tripped over it:
48
+ *
49
+ * A DERIVED CHECK IS REGISTERED PER TYPE AND READS A TYPE-SPECIFIC KEY,
50
+ * WHILE THE `$defs` IT GUARDS ARE SHARED ACROSS TYPES BY `$ref`.
51
+ * SHARING A DEFINITION THEREFORE DOES NOT SHARE ITS CHECK.
52
+ *
53
+ * Keywords travel through a `$ref` and derived checks do not, so a schema
54
+ * author who moves a rule into a shared definition gets the keyword half of
55
+ * the sharing for free and the Kind B half not at all. That asymmetry is
56
+ * invisible at the definition site, which is why `schemas/report.schema.json`
57
+ * could carry a comment saying a check applied where it did not.
58
+ *
59
+ * `guards` below names the shared definitions this check enforces, and
60
+ * `test/report-contract.test.ts` walks the TRANSITIVE closure of `$ref` in
61
+ * `schemas/`, failing when a guarded definition is reachable from a type
62
+ * this check does not list, or when a `guards` pointer resolves to nothing.
63
+ * REACHABLE was false of the ONE-HOP walk shipped before M3-P4 round 3.
64
+ */
65
+ alsoTypes?: readonly string[];
66
+ /**
67
+ * The shared `$def`s this check enforces, written as the pointer a
68
+ * cross-document `$ref` uses (`report.schema.json#/$defs/gateResult`).
69
+ * Absent means the check enforces nothing shared, which is the ordinary
70
+ * case: `plan-dispatchable` reads properties that exist in one document
71
+ * type only.
72
+ */
73
+ guards?: readonly string[];
74
+ /**
75
+ * True when the check resolves references into documents OTHER than the
76
+ * instance, so `--context <dir>` is required and its absence is a SKIP
77
+ * with a nonzero exit rather than a silent pass.
78
+ */
79
+ requiresContext: boolean;
80
+ run(instance: unknown, contextDirectory: string | undefined): CheckOutcome;
81
+ }
82
+ /** Every artifact type one check runs on, `type` first and then `alsoTypes`. */
83
+ export declare function typesOf(check: DerivedCheck): readonly string[];
84
+ /**
85
+ * A `report-code-disagreement` entry with `verified: false` names a claim
86
+ * that has NOT been confirmed against the code. R-012 says such a claim
87
+ * becomes a verification-first step: step 1 is confirm, write down, then
88
+ * build. So the owning phase must carry a step with `kind:
89
+ * verification-first`.
90
+ *
91
+ * No schema keyword reaches this: it matches an element of ONE array against
92
+ * a step nested inside an element of ANOTHER array, selected by phase id. A
93
+ * foreign-key lookup across arrays is not a keyword property.
94
+ */
95
+ export declare const planVerificationFirstPresent: DerivedCheck;
96
+ /**
97
+ * A phase whose `fill-in` is present and unfilled is VALID FOR REVIEW and
98
+ * INVALID FOR DISPATCH. That is a derived boolean over the slots rather than
99
+ * a property of any one field, so the validator computes and REPORTS it. A
100
+ * schema cannot express it, and rejecting the document would be wrong: the
101
+ * plan is legitimately reviewable in that state.
102
+ */
103
+ export declare const planDispatchable: DerivedCheck;
104
+ /**
105
+ * Every `hazard-classes[].addressed-by` must RESOLVE. Its two arms resolve
106
+ * against DIFFERENT things, which is why one witness is not a class here:
107
+ *
108
+ * `criterion <id>` resolves into the SAME phase's `acceptance[]` ids;
109
+ * `later-phase: <id>` resolves into the PLAN's `phases[]` ids.
110
+ *
111
+ * `enum` cannot express either, because the admissible values are computed
112
+ * per phase rather than fixed. The schema's `pattern` is the Kind A half and
113
+ * checks only the SHAPE of the string; a shape that resolves to nothing is
114
+ * precisely the defect section 2.6 was written after finding: a hazard class
115
+ * that names a criterion which does not exist has documented an obligation
116
+ * instead of creating one.
117
+ */
118
+ export declare const planHazardClassesAddressedByResolves: DerivedCheck;
119
+ /**
120
+ * "Downgrades are declared, never improvised" (blueprint section 8), made
121
+ * falsifiable: every stage the reference mode `full` runs and this mode does
122
+ * not must appear in this mode's `skips[]`.
123
+ *
124
+ * NO SCHEMA KEYWORD REACHES THIS. It is a set difference between the
125
+ * `pipeline` of ONE array element and the `pipeline` of a SIBLING element,
126
+ * selected by id, compared against a third field of the first (M3R-002). The
127
+ * schema's whole share is that `skips` exists and holds stage ids.
128
+ *
129
+ * TWO STRUCTURALLY DIFFERENT WAYS TO EVADE IT, and both are violations here
130
+ * rather than one being left implied:
131
+ *
132
+ * 1. a mode omits a stage and declares NOTHING (`skips: []`);
133
+ * 2. a mode omits two stages and declares ONE of them, so the document reads
134
+ * as a mode that has accounted for itself while one downgrade is silent.
135
+ *
136
+ * AND A THIRD, WHICH IS WHY THE MISSING REFERENCE IS A VIOLATION AND NOT A
137
+ * QUIET RETURN: deleting the `full` mode from the document disables the
138
+ * comparison for every remaining mode at once, so a document with one
139
+ * `direct-pr` mode, an empty `skips[]` and no `clean-room-review` would pass a
140
+ * check that returned early. That is the same defect one level up, so the
141
+ * absent reference fails closed.
142
+ *
143
+ * SOUNDNESS, THE CONVERSE DIRECTION, ADDED IN ROUND 9 (CR-002). Everything
144
+ * above asks ONE question: is every stage this mode omits DECLARED? It never
145
+ * asked the converse: is every stage this mode DECLARES actually omitted? A
146
+ * set checked in one direction only is a set nothing constrains, and `skips[]`
147
+ * is shipped DATA that any edit can change. The measured consequence was not
148
+ * hypothetical: `full` keeping its complete twelve-stage pipeline and gaining
149
+ * ONE bogus `skips[]` entry validated at exit 0, and `tiphys mode show --mode
150
+ * full` then printed that no phase of the tiphys project had ever been
151
+ * delivered under the mode this project has delivered every phase under
152
+ * (delivery/review/clean-room-m3-p3-r8-criteria.md:217).
153
+ *
154
+ * SOUNDNESS HAS TWO DIRECTIONS AND ROUND 9 SHIPPED ONE (round 10, V-1).
155
+ * `skips[]` is defined by the document itself as every stage in `full`'s
156
+ * pipeline that this mode's pipeline omits AND NOTHING ELSE, so "actually
157
+ * omitted" is measured against the REFERENCE and an entry can fail it two
158
+ * ways: (A) this mode's own pipeline runs the stage, and (B) NOTHING runs it,
159
+ * that is, it is absent from this mode's pipeline and from `full`'s as well.
160
+ * Round 9 implemented the predicate the reviewer wrote down (A) rather than
161
+ * the property the same reviewer described thirteen lines earlier, and then
162
+ * recorded in two shipped documents that the check ran in both directions.
163
+ * B was reachable on the shipped data with a one-line edit, because the stage
164
+ * vocabulary has thirteen ids and `full`'s pipeline has twelve: `direct-pr`
165
+ * gaining `orchestrator-diff-review` validated at exit 0 and `tiphys mode
166
+ * show` then reported a skipped-stage count one too high with a `skips:` row
167
+ * naming a stage that is no downgrade at all.
168
+ *
169
+ * WHICH SIDE OF THE COMPARISON IS EDITED DOES NOT MATTER, and that is why B is
170
+ * not merely "a typo in skips". Shrinking `full`'s PIPELINE, touching no
171
+ * `skips[]` anywhere, turns every other mode's previously correct entry for
172
+ * that stage into a phantom. The reference is one half of the relation and
173
+ * either half moving breaks it.
174
+ *
175
+ * THE DIRECTION-A PREDICATE RUNS OVER EVERY MODE INCLUDING THE REFERENCE, and
176
+ * that is load-bearing rather than a detail. The completeness loop `continue`s
177
+ * past `full` because a mode cannot omit a stage relative to itself; the
178
+ * soundness question is well posed for `full` too, and `full` is precisely the
179
+ * mode the sharpest member targeted. A soundness loop that inherited the
180
+ * completeness loop's skip would have been green against the finding that
181
+ * caused it to be written.
182
+ *
183
+ * DIRECTION A NEEDS NO REFERENCE MODE, so it runs BEFORE the reference is
184
+ * resolved and its violations survive an absent `full`. A document that both
185
+ * deletes `full` and carries a contradictory `skips[]` reports both facts
186
+ * rather than the first one only. DIRECTION B cannot: it is defined by the
187
+ * reference pipeline, so it runs after the resolution and an absent `full` is
188
+ * already a violation in its own right.
189
+ */
190
+ export declare const modeNoUndeclaredDowngrade: DerivedCheck;
191
+ /**
192
+ * R-024: an adversarial plan review happens before anyone builds.
193
+ *
194
+ * THE RELATIVE POSITION OF TWO VALUES IN A VARIABLE-LENGTH ARRAY IS NOT A
195
+ * KEYWORD PROPERTY (M3R-002). `contains` can say both are present and nothing
196
+ * in the vocabulary can say which comes first.
197
+ *
198
+ * The rule has TWO ARMS because there are two ways to build before a review,
199
+ * and the plan states both: reorder them, or delete the review. So a mode
200
+ * whose pipeline contains `implement` and NOT `adversarial-plan-review` must
201
+ * list the review in `skips[]`, which is the same declared-downgrade
202
+ * discipline applied to the one stage R-024 is about.
203
+ */
204
+ export declare const modeStageOrder: DerivedCheck;
205
+ /**
206
+ * Every `gate-sets[]` entry RESOLVES against `gate-registry.yaml`.
207
+ *
208
+ * WHAT "RESOLVES" MEANS HERE, stated because a checker whose promise is vague
209
+ * is a checker nobody can falsify: the entry names a gate the registry
210
+ * declares, AND that gate's own `modes` list names this mode. Both halves are
211
+ * needed, because a reference that resolves to a gate which never runs in this
212
+ * mode is a mode whose assurance is a name with no gates behind it, which is
213
+ * the hazard exactly as the plan words it.
214
+ *
215
+ * `requiresContext` is TRUE, so invoking the validator without `--context`
216
+ * prints `SKIPPED mode-gate-sets-resolve no context` and exits nonzero. That
217
+ * is the point of the mechanism (M3-P1 criterion 4c): a cross-document rule
218
+ * must never be able to pass BY NOT RUNNING.
219
+ */
220
+ export declare const modeGateSetsResolve: DerivedCheck;
221
+ /**
222
+ * The charter schema's mode enums equal the ids declared here.
223
+ *
224
+ * `schemas/charter.schema.json` declares the mode vocabulary a project charter
225
+ * may use, and this document declares what those modes ARE. Two lists, one
226
+ * fact. Without this check they are a duplication that drifts silently the
227
+ * first time a mode is added, which is the same drift hole M3-P2 closed for
228
+ * the gate list.
229
+ *
230
+ * BOTH FIELDS, not one. The charter carries `delivery-mode` AND
231
+ * `assurance-tier`, M3-P1 shipped the identical placeholder enum on both, and
232
+ * step 4 names both ("Add `mode` and `assurance-tier` validation to the
233
+ * charter schema's enum"). A check that watched only one would leave the other
234
+ * free to drift, which is the hazard rather than a smaller version of it.
235
+ */
236
+ export declare const charterModeEnumMatchesModes: DerivedCheck;
237
+ /** `modes[].id` selects exactly one mode. */
238
+ export declare const modeIdsAreUnique: DerivedCheck;
239
+ /**
240
+ * `roles[].role` selects exactly one binding. B-004: the SAME defect, in the
241
+ * document nothing consumes yet, which is why it was latent rather than
242
+ * demonstrable. It is fixed in the same act because the mechanism is one thing.
243
+ */
244
+ export declare const roleIdsAreUnique: DerivedCheck;
245
+ /**
246
+ * The QUOTABLE UNITS of a prose record: every top-level PARAGRAPH and every
247
+ * OUTERMOST LIST ITEM, each with its marker stripped and its whitespace
248
+ * normalized.
249
+ *
250
+ * WHY THIS EXISTS, and it is the whole of fix round 2. The first version of
251
+ * this check asked whether each condition OCCURRED ANYWHERE in the record, as
252
+ * one normalized blob. That is a CONTAINMENT predicate standing in for an
253
+ * EQUALITY predicate, and containment is trivially satisfiable by short
254
+ * strings: `conditions: ["a", "the", "review", "merge", "is", "of"]` replaced
255
+ * every one of DR-0012's six merge-authority conditions with junk and the
256
+ * check exited 0. Every one of those words occurs in the record.
257
+ *
258
+ * The signal was already in this phase's own evidence and was read past: an
259
+ * earlier probe fabricated `"one"` through `"six"` and got findings for
260
+ * indices 3, 4 and 5 ONLY, because "one", "two" and "three" occur inside the
261
+ * record's prose. Three of six caught looked like the check working.
262
+ *
263
+ * Comparing against UNITS rather than against the blob makes the predicate an
264
+ * equality: a condition matches only if it is a WHOLE quoted item of the
265
+ * record. Both halves matter. Whole, so a fragment cannot match; item rather
266
+ * than whole document, so a record may carry other prose around the conditions
267
+ * without anyone having to say which section holds them, which is the
268
+ * structure assumption that would have made this check project-specific.
269
+ *
270
+ * THE COST, stated because it is a real constraint on a consuming project: a
271
+ * condition must be quoted as a complete list item or paragraph of the record.
272
+ * A condition that paraphrases, or that quotes half of a longer item, is now
273
+ * a violation. That is what "quoted from the decision record rather than
274
+ * summarized" already claimed to mean, and it is now enforced rather than
275
+ * asserted.
276
+ *
277
+ * A LIST ITEM'S UNIT IS THE WHOLE ITEM. An item's continuation paragraphs and
278
+ * its nested sub-items are CONTENT OF THE ITEM in CommonMark, so emitting them
279
+ * as units of their own would leave the item's FIRST PARAGRAPH standing as a
280
+ * whole unit while the item itself carried more, which is a fragment passing as
281
+ * a whole quote: the defect this check exists to prevent, arriving through the
282
+ * extractor. It is live in this repository:
283
+ * `delivery/decisions/DR-0004-elevated-permissions.md` has the shape (an item,
284
+ * a blank, then its commands indented under it) and
285
+ * `delivery/decisions/DR-0013-schema-validator-implementation.md` has the
286
+ * nested-list form. THE COST, stated because it is real: a nested sub-item is
287
+ * not separately quotable, so a record whose conditions are sub-bullets must
288
+ * quote the enclosing item whole.
289
+ *
290
+ * ------------------------------------------------------------------
291
+ * THE BLOCK STRUCTURE IS READ FROM A COMMONMARK PARSER (DR-0022, owner
292
+ * decision, option A2). THE TEXT IS SLICED FROM THE ORIGINAL SOURCE.
293
+ * ------------------------------------------------------------------
294
+ *
295
+ * What stood here until 2026-08-09 was a HAND-ROLLED CommonMark block parser:
296
+ * a line loop carrying fence state, indented-code state, a list content column
297
+ * and a deferred-blank flag, with six sites that could end a unit. It took FIVE
298
+ * fix rounds and produced FIVE defects, the fifth a regression of a shape the
299
+ * fourth had correct. The owner's decision records the measurement that ended
300
+ * it: against two independent conformant parsers over 15,000 generated
301
+ * documents, the hand-rolled loop agreed on about 35 per cent of them.
302
+ *
303
+ * The reason the rounds could not converge is worth keeping, because it is a
304
+ * property of the problem and not of the agents. Whether a line is prose
305
+ * depends on which block encloses it, and which block encloses it depends on
306
+ * lines above and sometimes below (a setext underline retroactively makes the
307
+ * block above it a heading). A loop that decides one line at a time is
308
+ * reconstructing a parser, and every reconstruction has to be kept in agreement
309
+ * with the reference BY HAND, with no mechanism that detects divergence. That
310
+ * is the "guard narrower than the property" family, and this repository has now
311
+ * recorded it five times in this one function.
312
+ *
313
+ * TWO OF THE ELEVEN FINDINGS ACROSS THOSE ROUNDS WERE NOT DEFECTS AT ALL. V-3
314
+ * ("adjacent paragraphs merge") and the fifth member of V-5 (a nested sub-item
315
+ * followed by a dedented line) were both cases where a hand-reading of markdown
316
+ * disagreed with CommonMark and the HAND-READING WAS WRONG: lazy continuation
317
+ * makes both fusions correct. A round can only find defects it already believes
318
+ * in, which is the other half of the cost.
319
+ *
320
+ * WHY `sourcepos` SLICING AND NOT THE PARSER'S INLINE TEXT, which is the whole
321
+ * of A2 versus A and is the single most expensive detail here. Walking the AST
322
+ * and reading each paragraph's inline text is the obvious implementation and it
323
+ * SILENTLY CHANGES THE SHIPPED CONTRACT, because inline text drops markup:
324
+ * `` `delivery/review/` `` becomes `delivery/review/`. DR-0012's first
325
+ * merge-authority condition contains exactly that, so `assurance-modes.yaml`
326
+ * stops resolving, and 11 of this repository's 19 decision records produce
327
+ * different unit sets. Slicing the ORIGINAL SOURCE by the parser's own
328
+ * `sourcepos` offsets keeps the bytes as written, which is what every existing
329
+ * record and every existing condition relies on.
330
+ *
331
+ * SO: this function reads the parser for STRUCTURE ONLY. It never reads
332
+ * `literal` and never concatenates inline nodes, and a change that starts doing
333
+ * either is option A, which is a defect. `CommonMarkNode` above declares six
334
+ * members and none of them is inline text, so the type is the guard.
335
+ *
336
+ * WHAT THE FOUR PREVIOUSLY UNMODELLED BLOCK FORMS DO NOW, since the old
337
+ * docstring listed them as latent hazards:
338
+ * - block quote: its contents are treated like the document's, so the quoted
339
+ * paragraph is a unit and the `>` marker is NOT part of it. This is a
340
+ * DECLARED POLICY CHOICE (see `collectUnits`), not a derivation.
341
+ * - HTML block: contributes no unit. Corrected in round 7 (CR-003): it is
342
+ * listed in `NOT_QUOTABLE`, but under `commonmark` 0.31.2 that listing is
343
+ * not what excludes it. An `html_block` is an AST LEAF, and a unit is only
344
+ * ever emitted for a `paragraph` child, so it could contribute nothing even
345
+ * if the set were empty. Read `NOT_QUOTABLE`'s own docstring for what the
346
+ * set is really for.
347
+ * - link reference definition: excluded, and by construction rather than by a
348
+ * rule, because the parser removes it before this walk sees the document.
349
+ * - pipe table: never was a hazard. CommonMark core has no tables, so a table
350
+ * IS a paragraph and treating its lines as prose is correct.
351
+ *
352
+ * WHERE THIS IS STILL NOT AN ORACLE: it is right in the sense of "agrees with
353
+ * `commonmark` 0.31.2". Two conformant CommonMark implementations disagree on
354
+ * roughly half a per cent of generated documents (an indented line immediately
355
+ * after a link reference definition is the measured instance), and any
356
+ * structure-reading option inherits that.
357
+ */
358
+ export declare function quotableUnits(text: string): Set<string>;
359
+ export declare const modeConditionsQuoteGrantedBy: DerivedCheck;
360
+ /**
361
+ * WHERE THE SHARED `gateResult` DEFINITION IS REACHED FROM, one row per
362
+ * artifact type, naming the KEY that type stores its gate results under.
363
+ *
364
+ * This table is the concrete form of CR-001's mechanism. The definition is
365
+ * one object reached by `$ref` from two documents; the PROPERTY NAME differs
366
+ * between them (`gate-results` in a report, `gate-evidence` in a work
367
+ * history), so a check that hard-codes one key is blind on the other type
368
+ * even after it is registered for it. Both halves are needed and only one of
369
+ * them is visible from the `$ref`.
370
+ */
371
+ export declare const GATE_RESULT_SITES: readonly {
372
+ readonly type: string;
373
+ readonly key: string;
374
+ }[];
375
+ /**
376
+ * `discovered == passed + failed + skipped + did-not-run`, over one gate
377
+ * result's sibling fields.
378
+ *
379
+ * NO SCHEMA KEYWORD COMPUTES ARITHMETIC over sibling fields, which is what
380
+ * makes this Kind B rather than a keyword (M3R-002 corrected revision 0's
381
+ * classification of exactly this check). The property it guards is R-048's:
382
+ * a suite that reports fewer tests than it discovered is the
383
+ * silently-dropped-tests case, and it adds up to a green everywhere else.
384
+ *
385
+ * THREE THINGS THIS CHECKS, and the second and third are the CONVERSES the
386
+ * criterion's letter does not name. The plan's criterion 2b(a) names only
387
+ * `discovered` EXCEEDING the sum. A check that tested only that direction
388
+ * would pass a record whose sum exceeds `discovered`, which is a different
389
+ * lie with the same shape, so the test here is EQUALITY. And a count field
390
+ * that is NEGATIVE is arithmetic nonsense that equality alone can satisfy
391
+ * (`discovered: 0` with `passed: 1` and `failed: -1` adds up); negativity is
392
+ * not reachable by any keyword in the declared authoring vocabulary, which
393
+ * has no `minimum`, so it is checked here beside the sum rather than left to
394
+ * a keyword that does not exist.
395
+ *
396
+ * WHAT IT DOES NOT REACH, stated rather than implied: a gate result carrying
397
+ * NO count field at all is not examined, because the schema requires the six
398
+ * counts only of a `green`, and a `red` result that records none of them is a
399
+ * legitimate record rather than a false one. So this check cannot see a
400
+ * dropped test in a run nobody counted; it sees one in a run that claims a
401
+ * count. Nor does it reach a BALANCED loss: an author who drops the same row
402
+ * from `discovered` and from a bucket satisfies the identity, because nothing
403
+ * here anchors `discovered` to what the wrapper actually discovered.
404
+ *
405
+ * WHERE IT RUNS, and this is CR-001's whole content. It runs on EVERY type
406
+ * that reaches the shared `gateResult` definition, enumerated by
407
+ * `GATE_RESULT_SITES` rather than by one hard-coded key. Until M3-P4 fix
408
+ * round 2 it was registered for `report` alone and read `gate-results` alone,
409
+ * so a work history recording 9999 discovered and 1 passed exited 0 while the
410
+ * identical counts in a report exited 1, and the shared definition's own
411
+ * comment said the check applied.
412
+ */
413
+ export declare const reportParityArithmetic: DerivedCheck;
414
+ /**
415
+ * Every id in `inputs[]` appears in `input-findings[]`, exactly once, and no
416
+ * `input-findings[]` row names an id `inputs[]` does not carry.
417
+ *
418
+ * A CROSS-ARRAY COMPLETENESS PROPERTY, which no keyword reaches: `contains`
419
+ * asks about a fixed shape, not about a value computed from a sibling array.
420
+ * Revision 0 of the plan listed this once as a schema witness, which was
421
+ * wrong (M3R-002).
422
+ *
423
+ * THREE DIRECTIONS, and only the first is in the criterion's letter. The
424
+ * criterion names the ORPHAN: an id in `inputs[]` with no row. The PHANTOM
425
+ * (a row whose id is not an input) and the DUPLICATE (two rows for one id)
426
+ * are the converses, and they are here because M2-P6 paid for both by
427
+ * measurement rather than by argument: CR-988 records that its parity mode
428
+ * scanned inventory ids only, so a row for a renumbered id was silently
429
+ * accepted, and CR-985 records that a duplicated id defeated the orphan and
430
+ * phantom checks TOGETHER while inflating every count. A guard narrower than
431
+ * its own description is what this project keeps re-buying, so the check is
432
+ * as wide as the relation.
433
+ *
434
+ * WHAT IT DOES NOT REACH: a finding dropped from BOTH arrays. The two
435
+ * documents then agree with each other, and no comparison between them can
436
+ * see it. That is the same residue `src/gates/coverage.ts` answers with a
437
+ * config-stated `expectedUnits` anchor, and this schema has no such anchor
438
+ * because nothing in the plan states one.
439
+ */
440
+ export declare const finalReportFindingParity: DerivedCheck;
441
+ /**
442
+ * A report with an EMPTY `findings` array carries a `no-findings-statement`,
443
+ * and a report that files findings does NOT carry one.
444
+ *
445
+ * KIND B BY NECESSITY, AND THE NECESSITY IS MEASURED RATHER THAN ASSERTED.
446
+ * The natural keyword shape is `if findings has maxItems 0 then require
447
+ * no-findings-statement`, and `maxItems` is ABSENT from the sixteen keywords
448
+ * of `AUTHORING_VOCABULARY` (src/validate.ts:111). No other permitted keyword
449
+ * says "this array is empty": `minItems` says the opposite, `contains` asks
450
+ * about a member that exists, and `const: []` is not reachable because `const`
451
+ * is used on scalars here and an array `const` would pin the CONTENTS. So the
452
+ * emptiness of a sibling array is not a keyword property, which is the same
453
+ * boundary `report-parity-arithmetic` sits on one field over.
454
+ *
455
+ * WHY IT IS HERE AT ALL. `no-findings-statement` exists to price silence: a
456
+ * report claiming nothing was found must say WHY nothing was found. Optional,
457
+ * it is absent in exactly the situation it exists for, and the shipped schema
458
+ * disclosed that as a residue rather than closing it. The orchestrator's
459
+ * arbitration of M3-P4 round 1 amended section 2.3's table to three rows for
460
+ * this phase and directed the check to be written; D-M3-22 is satisfied by
461
+ * that amendment, not by this comment.
462
+ *
463
+ * BOTH DIRECTIONS, because the phase's own converse discipline demands it.
464
+ * The requirement's letter names only the empty-with-no-statement case. A
465
+ * report that files three findings and ALSO carries "no findings were found"
466
+ * is the opposite misdeclaration and is equally a false record, so it is a
467
+ * violation too.
468
+ *
469
+ * WHAT IT DOES NOT REACH: whether the statement SAYS anything. The schema
470
+ * makes an empty or whitespace-only one impossible; a statement reading "n/a"
471
+ * satisfies both this check and those keywords, and that is M3-P7's
472
+ * `contract-avoidance` probe rather than anything a schema or a check can see.
473
+ * It also does not reach a report with NO `findings` key at all, because
474
+ * `findings` is `required` and the schema rejects that before any check runs.
475
+ */
476
+ export declare const reportNoFindingsStatement: DerivedCheck;
477
+ /**
478
+ * No two probes in one checklist share an `id`.
479
+ *
480
+ * KIND B, AND THE REASON IS A KEYWORD'S SEMANTICS RATHER THAN A DOCUMENT
481
+ * BOUNDARY. `uniqueItems` compares WHOLE array items, so two probes sharing
482
+ * an id and differing in any other field are already unique to it, and the
483
+ * pair that shares an id is exactly the dangerous instance: `checklist
484
+ * resolve` looks a probe up by id, so a duplicate makes the resolved list
485
+ * depend on which one the lookup reached. Uniqueness of a NESTED PROPERTY
486
+ * across array items is not a keyword property under any DR-0013 option,
487
+ * which is why the review did not name it and why it lands here.
488
+ *
489
+ * `requiresContext` is FALSE: the whole comparison is inside one document.
490
+ */
491
+ export declare const checklistProbeIdsUnique: DerivedCheck;
492
+ /**
493
+ * No two framings in one checklist share an `id`.
494
+ *
495
+ * THE SAME SHAPE AND THE SAME KEYWORD LIMITATION AS THE PROBE CHECK ABOVE,
496
+ * one array along. `uniqueItems` on `framings` compares WHOLE items, so two
497
+ * framings sharing an id and differing in their entry point or their scope
498
+ * order are already unique to it, and that pair is exactly the dangerous
499
+ * instance: `resolveChecklist` looks a framing up with `.find()`, first match
500
+ * wins, so which of two declared entry points a reviewer is handed depends on
501
+ * FILE POSITION and nothing says so.
502
+ *
503
+ * WHY IT MATTERS MORE HERE THAN THE PROBE CASE LOOKS LIKE IT WOULD. A
504
+ * framing IS the entry point, and T-001's lesson that decorrelation comes
505
+ * from the starting question is the whole reason `--framing` exists. A
506
+ * duplicate id means the reviewer's starting question is decided by which
507
+ * copy sat first in the file, which is the phase's own hazard class ("a
508
+ * framing that reorders the list without changing the entry point") reached
509
+ * from the other side.
510
+ *
511
+ * `requiresContext` is FALSE: the whole comparison is inside one document.
512
+ */
513
+ export declare const checklistFramingIdsUnique: DerivedCheck;
514
+ /**
515
+ * The join M3-P2 deliberately left open, closed in BOTH DIRECTIONS.
516
+ *
517
+ * `gate-registry.yaml` carries entries whose `verified-by` is
518
+ * `clean-room-checklist` and whose `probe` names a probe id this phase
519
+ * supplies. Nothing on the registry side can check that the probe exists,
520
+ * because the checklist did not exist when the registry shipped.
521
+ *
522
+ * DIRECTION 1, REGISTRY TO CHECKLIST (criterion 3). Every registry entry
523
+ * verified by a checklist names a probe that RESOLVES in that checklist, and
524
+ * that probe carries the `verifies-gate` back-reference to the entry. WHICH
525
+ * checklist is derived from the registry's own vocabulary rather than
526
+ * hardcoded: `verified-by: clean-room-checklist` names the checklist whose id
527
+ * is `clean-room`, so an entry is only asserted against the document it
528
+ * actually names, and running this check on `plan-review.yaml` does not
529
+ * demand the clean-room probes there.
530
+ *
531
+ * DIRECTION 2, CHECKLIST TO REGISTRY (criterion 3c). Every probe carrying
532
+ * `verifies-gate` names a gate id present in the registry. THE ASYMMETRY IS
533
+ * THE WHOLE POINT: direction 1 starts from the registry and therefore cannot
534
+ * see a probe pointing at a gate that no longer exists, which is what the
535
+ * phase's own hazard class calls an orphan invisible by construction. The two
536
+ * ways a registry edit orphans a probe fail through DIFFERENT lookups: a gate
537
+ * id RENAMED leaves the probe pointing at a name that never existed, and a
538
+ * gate entry DELETED leaves it pointing at a name that used to. Both land
539
+ * here; neither is reachable from direction 1.
540
+ *
541
+ * `requiresContext` is TRUE, so invoking the validator without `--context`
542
+ * prints `SKIPPED gate-probes-resolve no context` and exits nonzero. A
543
+ * cross-document rule must never be able to pass BY NOT RUNNING.
544
+ */
545
+ export declare const gateProbesResolve: DerivedCheck;
546
+ /**
547
+ * A verdict's `criteria[]` carries one entry per acceptance criterion of the
548
+ * plan phase it reviews.
549
+ *
550
+ * THE DANGEROUS INSTANCE is a review that quietly skipped a criterion: every
551
+ * entry present is well formed, the schema is satisfied, and the one
552
+ * criterion nobody walked is invisible. R-053 says each criterion is quoted
553
+ * with evidence and a verdict, and "each" is a comparison against a DIFFERENT
554
+ * document, which no keyword reaches.
555
+ *
556
+ * BOTH DIRECTIONS, because they are different mistakes. A criterion the
557
+ * verdict omits is an unwalked criterion; a verdict entry naming a criterion
558
+ * the phase does not declare is a review walking something that is not in the
559
+ * contract, usually a criterion id left behind by a plan revision.
560
+ */
561
+ export declare const verdictCriteriaComplete: DerivedCheck;
562
+ /**
563
+ * A verdict's `deviations-judged[]` carries one entry per deviation declared
564
+ * in the phase's work history.
565
+ *
566
+ * M3R-005 IS WHY THIS IS A CHECK AND NOT A PROBE. R-057b's "judged, never
567
+ * assumed by the implementer" has exactly the same completeness shape as
568
+ * criteria coverage, and revision 0 had left it as a bare probe question for
569
+ * no stated reason, so a reviewer could silently skip judging one of three
570
+ * declared deviations and every criterion still passed.
571
+ *
572
+ * THE OTHER DOCUMENT IS `work-history.yaml` in the context directory, and it
573
+ * must be the work history OF THE PHASE THIS VERDICT NAMES: a work history
574
+ * for another phase would let the check pass by comparing against the wrong
575
+ * deviation list, which is a vacuous pass wearing a cross-document check's
576
+ * clothes.
577
+ */
578
+ export declare const verdictDeviationsJudged: DerivedCheck;
579
+ /**
580
+ * A HAZARD verdict's `hazard-classes-addressed[]` carries one entry per
581
+ * hazard class declared by the plan phase it reviews.
582
+ *
583
+ * T-007 IS THE INPUT AND M3R-005 IS THE SHAPE. This has exactly the shape
584
+ * `verdict-criteria-complete` has for criteria, one field along, and for
585
+ * exactly the same reason: a reviewer could otherwise silently skip one of
586
+ * three declared hazard classes while every other criterion still passed.
587
+ * T-007's measured case is a phase meeting fifteen of fifteen executed
588
+ * criteria while live-locking every supervision command.
589
+ *
590
+ * IT APPLIES EXACTLY WHERE THE CONTRACT APPLIES. A verdict whose
591
+ * `review-contract` is `criteria` is not asserted against, because the
592
+ * criteria contract is not the one that owes hazard statements, and a check
593
+ * that reddened on it would push reviewers to fill the array with nothing.
594
+ * That the criteria arm is unaffected is asserted by a test rather than left
595
+ * as an implication.
596
+ */
597
+ export declare const verdictHazardClassesAddressed: DerivedCheck;
598
+ /**
599
+ * Every `hazard-classes-addressed[].finding` names a `findings[].id` that
600
+ * exists in the SAME verdict.
601
+ *
602
+ * KIND B FOR THE SAME REASON `checklist-probe-ids-unique` IS, AND IT IS THE
603
+ * ONLY INTRA-DOCUMENT ID REFERENCE THE SHIPPED SCHEMAS DECLARE. The
604
+ * verdict schema's own `$comment` on `finding` calls it "the `findings[].id`
605
+ * this class produced", so the join is DECLARED; nothing resolved it, so it
606
+ * was a bare string with `minLength: 1`. Resolving one array's entry against
607
+ * another array's ids is not a keyword property under any DR-0013 option,
608
+ * which is why it lands here and not in the schema.
609
+ *
610
+ * WHAT IT PROTECTS, and it is not merely tidiness. The verdict schema ships
611
+ * exactly ONE rule that can force a verdict off APPROVE: a `findings[]` set
612
+ * containing a `high` or `critical` entry must carry FIX-ROUND-NEEDED. That
613
+ * rule reads `findings[]` and nothing else. So a hazard reviewer who records
614
+ * a class as having produced a finding, and leaves that finding out of
615
+ * `findings[]`, gets a schema-valid APPROVE with an empty findings array and
616
+ * the escalation rule never sees the finding it would have fired on. Measured
617
+ * at 4bfa790 before this check: such a document validated at exit 0, and the
618
+ * same document with the finding moved into `findings[]` at `severity: high`
619
+ * exited 1.
620
+ *
621
+ * A DANGLING REFERENCE IS ITSELF THE ERROR, not only one that lets the
622
+ * escalation be evaded, and the reason is that the narrower rule is not
623
+ * computable. A finding absent from `findings[]` has NO severity, so nothing
624
+ * can decide whether it would have escalated; the narrower reading would have
625
+ * to guess, and would clear exactly the document that withheld the most.
626
+ * Requiring the reference to resolve is decidable, and it puts the severity
627
+ * back under the escalation rule where the reader can see it.
628
+ *
629
+ * `requiresContext` is FALSE: the whole comparison is inside one document.
630
+ */
631
+ export declare const verdictFindingReferencesResolve: DerivedCheck;
632
+ /**
633
+ * A `structural-consequence` marked `applied` names a target path that EXISTS.
634
+ *
635
+ * KIND B BY NECESSITY: it resolves a string against the filesystem, which no
636
+ * keyword under any DR-0013 option reaches. `requiresContext` is TRUE, so
637
+ * running the validator without `--context` prints `SKIPPED
638
+ * tuition-target-exists no context` and exits nonzero rather than passing by
639
+ * not running.
640
+ *
641
+ * ONLY `applied` IS CHECKED, and that is the point rather than a limitation.
642
+ * `proposed` names a change nobody has made and `ticketed` names one carried
643
+ * by a record, so neither claims anything about the tree; `applied` claims the
644
+ * change is IN the tree, and T-003 is the entry recording that a document can
645
+ * carry exactly that claim falsely.
646
+ *
647
+ * WHAT IT DOES NOT REACH, named here because criterion 3 reads at a glance as
648
+ * though it covered the whole hazard: whether the file CONTAINS the change
649
+ * claimed. That is a semantic relation between a prose sentence and a file,
650
+ * and the plan's own hazard table assigns it to review rather than to a check
651
+ * (section 2.6 reason 1). The two halves are exactly what this project has
652
+ * repeatedly found to differ, so the check states which half it is.
653
+ */
654
+ export declare const tuitionTargetExists: DerivedCheck;
655
+ /**
656
+ * A PATH REFERENCE inside a `mechanisms[]` entry resolves against the tree,
657
+ * and a `machine-readable-form` resolves to a real document AND a real key
658
+ * inside it.
659
+ *
660
+ * T-005's checkability rule has two halves and they need two instruments. The
661
+ * SCHEMA half is `evidence` with `minItems: 1`: a rule with no citation is not
662
+ * a rule. THIS half is that a citation naming a file which does not exist is
663
+ * not a citation, which is a filesystem question and therefore Kind B.
664
+ *
665
+ * WHAT COUNTS AS A PATH REFERENCE, stated mechanically because a checker whose
666
+ * subject is vague cannot be falsified: a whitespace-delimited token holding at
667
+ * least one `/` and ending in a short extension, with surrounding backticks,
668
+ * brackets and trailing punctuation stripped. Real evidence in this feed reads
669
+ * `delivery/review/verification-m1-p3-fix-round.md V-1 and V-3`, so the
670
+ * reference is a token inside a sentence rather than the whole string.
671
+ *
672
+ * A `path.ext:LINE` CITATION IS A PATH REFERENCE (HRB-1, fix round 3). It is the
673
+ * form CLAUDE.md:155 mandates, and the earlier token test silently dropped every
674
+ * one of them; see `pathReferencesIn` for the measurement and the grammar.
675
+ *
676
+ * WHAT IT DOES NOT REACH, and these are real holes rather than tidy ones.
677
+ *
678
+ * PROSE-ONLY evidence. `M1-P5 round 4, verified pre-existing against a pristine
679
+ * build` names no path, so nothing about it is resolvable and this check says
680
+ * nothing about it. Requiring every citation to be a path would redden entries
681
+ * whose evidence is a measurement rather than a document, which is a real form
682
+ * of evidence this project uses. The residue is therefore deliberate: the check
683
+ * establishes that the paths cited EXIST, never that a rule is supported.
684
+ *
685
+ * A CITATION INTO A TREE THIS CONTEXT DOES NOT HAVE (HRB-8, fix round 3). The
686
+ * feed ships and `delivery/` does not, so in a consumer's install most citations
687
+ * name a repository that is not there. Those are REPORTED, with their count and
688
+ * the trees involved, and never counted as violations; see
689
+ * `unresolvableCitationTree` for why that is the correct answer rather than a
690
+ * softening, and for the reason it is not a silent pass.
691
+ *
692
+ * REGISTERED FOR BOTH TYPES. `mechanisms[]` appears in a tuition entry (where
693
+ * a rule is authored) and in the mechanism index (where it is projected). A
694
+ * check registered only for the first would leave the shipped index unchecked,
695
+ * which is the shared-definition asymmetry `alsoTypes` exists for.
696
+ */
697
+ export declare const mechanismRuleEvidenceResolves: DerivedCheck;
698
+ /**
699
+ * Every path-like token in one prose reference. See the check's header for the
700
+ * definition and for what it deliberately does not treat as a path.
701
+ *
702
+ * THE `:LINE` SUFFIX IS STRIPPED BEFORE THE EXTENSION TEST (HRB-1, M3-P8 fix
703
+ * round 3). CLAUDE.md:155 makes `path.ext:LINE` THE citation form in this
704
+ * project ("a bare path is not a citation at all") and src/gates/citations.ts
705
+ * is the gate that enforces it. The earlier form tested the extension at
706
+ * end-of-string, and a line number sits after it, so every citation written the
707
+ * way this repository REQUIRES resolved to nothing: an entry whose paths were
708
+ * entirely fabricated validated at exit 0, and the byte-identical entry with
709
+ * the suffixes removed went red. A check that passes exactly the mandated form
710
+ * is not a check.
711
+ *
712
+ * The suffix grammar is the citations gate's own, narrowed to what a suffix can
713
+ * be rather than re-derived: `:<line>`, an optional `-<line>` range, and an
714
+ * optional `@sha256:<hex>` content pin (src/gates/citations.ts:453). Stripping
715
+ * is deliberately conservative: a token that does not match keeps its colon and
716
+ * is then judged by the extension test as before, so `http://x/y.md` and
717
+ * `a/b.md:notaline` are unchanged.
718
+ */
719
+ export declare function pathReferencesIn(reference: string): string[];
720
+ /**
721
+ * THE TREE A CITATION IS ROOTED IN, when this context does not contain it.
722
+ * Returns that top-level name, or undefined when the citation IS resolvable
723
+ * here and absence would therefore be a real defect.
724
+ *
725
+ * WHY (HRB-8, M3-P8 fix round 3). A citation is relative to the repository that
726
+ * AUTHORED it. The tuition feed and its index ship in the npm package;
727
+ * `delivery/`, `src/`, `scripts/` and `test/` do not (package.json's `files`).
728
+ * So the checks that resolve a document-supplied path were asking a consumer's
729
+ * install a question only the kernel repository can answer, and answering it
730
+ * INVALID. Measured at 26ee653: the shipped index produced 16 INVALID lines
731
+ * from a pristine `npm pack` extraction, and eight of the fifteen shipped
732
+ * entries produced more. CI never saw it because this repository has
733
+ * `delivery/`, which is T-009's shape one scope out.
734
+ *
735
+ * schemas/mechanism-index.schema.json:5 already stated the governing fact
736
+ * before this round: resolution "is not computable from an installed package".
737
+ * This is that sentence made operative rather than decorative.
738
+ *
739
+ * THE PREDICATE IS THE TOP-LEVEL SEGMENT, and it is the coarsest one that still
740
+ * catches everything the kernel repository could catch before. A citation into a
741
+ * tree that IS present must still resolve, so a fabricated
742
+ * `delivery/review/invented.md` is as red here as it ever was; only a citation
743
+ * into a tree that is wholly absent is excused. A path with no directory
744
+ * component is NEVER excused, because the context root always exists: measured
745
+ * against the real feed, every `applied` root-level target ships, and the one
746
+ * root-level absentee (`AGENTS.md`) is `ticketed`, which the check does not read.
747
+ *
748
+ * THIS IS NOT A LICENCE TO GO QUIET. Every caller REPORTS what it declined to
749
+ * resolve and why. "Nothing to check here" and "everything checked and fine"
750
+ * must never print the same line, which is the SC-011 shape the plan's hazard
751
+ * row at delivery/plan/kernel-plan-m3.md:4042 polices.
752
+ */
753
+ export declare function unresolvableCitationTree(contextDirectory: string, path: string): string | undefined;
754
+ /** The three dimensions two verdicts of one head must differ on. */
755
+ export declare const DECORRELATION_DIMENSIONS: readonly string[];
756
+ /** The merge-authority value that makes decorrelation a precondition of merge. */
757
+ export declare const DELEGATED_MERGE_AUTHORITY = "delegated-under-conditions";
758
+ /**
759
+ * DR-0012's merge precondition, made into a comparison a command can make
760
+ * against the verdict FILES rather than against a session's memory (M3R-004).
761
+ *
762
+ * WHY THIS IS KIND B AND COULD NOT BE A KEYWORD. Every dimension it compares
763
+ * lives in a DIFFERENT DOCUMENT from the instance: distinctness is a property
764
+ * of a PAIR of verdicts, and no keyword under any DR-0013 option can see the
765
+ * sibling.
766
+ *
767
+ * IT ESTABLISHES PRESENCE ITSELF AND DOES NOT BORROW IT FROM THE SCHEMA. An
768
+ * earlier version of this comment said the verdict schema's `required` buys
769
+ * absence-freedom, so this check only had to decide difference. That division of
770
+ * labour was never composed: nothing on the shipped path validates the SIBLING
771
+ * documents, so a document with `kind: verdict` and a missing required field is
772
+ * loaded here and compared. The rule the whole section now follows is
773
+ * `establishField`, one screen up: a value is not comparable until it has been
774
+ * established, and absence, unusability and difference are three verdicts, not
775
+ * one.
776
+ *
777
+ * IT APPLIES EXACTLY WHERE THE GRANT APPLIES. The regime is read from the
778
+ * declared mode, not assumed: `charter.yaml` names the delivery mode and
779
+ * `assurance-modes.yaml` says what that mode's `merge-authority` is. A mode
780
+ * whose authority is not a delegated grant has no decorrelation precondition to
781
+ * satisfy, and this check REPORTS that rather than passing silently, because
782
+ * "nothing to check here" and "everything checked and fine" must never print
783
+ * the same line (SC-011).
784
+ *
785
+ * FIVE DIMENSIONS, AND (e) IS NOT A REFINEMENT OF (b). T-007's whole finding is
786
+ * that model decorrelation and CONTRACT decorrelation are different properties
787
+ * and this project had the second by accident: two reviewers on different model
788
+ * families walked all fifteen criteria of one phase, agreed on every mechanical
789
+ * fact, and one missed a high-severity defect because both had been given the
790
+ * criteria contract. So `review-contract` is compared separately and is
791
+ * witnessed separately (criterion 7b).
792
+ *
793
+ * WHAT IT DOES NOT REACH, named rather than left to be found. Condition (d) of
794
+ * step 3b, that neither verdict carries an unresolved high or medium finding,
795
+ * is NOT checked here: the verdict schema's own root `if`/`then` already
796
+ * forbids APPROVE beside a high or critical finding, and "unresolved" is a
797
+ * state of the review thread rather than of the document. Nothing here decides
798
+ * whether the two verdicts describe the same HEAD either: the verdict schema
799
+ * carries no head field, so `phase` is the join key and the DIRECTORY is what
800
+ * scopes a set of verdicts to one head. Both are stated in
801
+ * delivery/work-history/m3-p9.md as declared readings rather than absorbed.
802
+ */
803
+ export declare const dualReviewDecorrelation: DerivedCheck;
804
+ /** Register a check. Later phases append their own (section 2.3's table). */
805
+ export declare function registerCheck(check: DerivedCheck): void;
806
+ /** Remove a check by id. Returns whether one was removed. */
807
+ export declare function deregisterCheck(id: string): boolean;
808
+ /** Every check registered for an artifact type, in stable id order. */
809
+ export declare function checksFor(type: string): DerivedCheck[];
810
+ /** Every registered check, in registration order. Read by the enumeration. */
811
+ export declare function registeredChecks(): readonly DerivedCheck[];
812
+ /** The outcome of running every check registered for a type. */
813
+ export interface ChecksRun {
814
+ /** Lines to print, in the order they should appear. */
815
+ lines: string[];
816
+ /** True when at least one check violated or was skipped for want of context. */
817
+ failed: boolean;
818
+ }
819
+ /**
820
+ * Run every registered check for `type`.
821
+ *
822
+ * A check whose `requiresContext` is true and which was given none is
823
+ * SKIPPED and the run FAILS. It is deliberately not an ordinary violation:
824
+ * "this rule did not run" and "this rule found a problem" are different
825
+ * facts and a reader must be able to tell them apart, but both are reasons
826
+ * not to trust a green.
827
+ */
828
+ export declare function runChecks(type: string, instance: unknown, contextDirectory: string | undefined): ChecksRun;