@tiphys/kernel 0.0.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +663 -0
- package/LICENSE +202 -0
- package/assurance-modes.yaml +299 -0
- package/checklists/clean-room.yaml +325 -0
- package/checklists/env-failure-diagnosis.yaml +68 -0
- package/checklists/flake-playbook.yaml +68 -0
- package/checklists/hazard-review.yaml +144 -0
- package/checklists/plan-review.yaml +103 -0
- package/dist/bin/tiphys.d.ts +2 -0
- package/dist/bin/tiphys.js +92 -0
- package/dist/src/adapters/load.d.ts +202 -0
- package/dist/src/adapters/load.js +440 -0
- package/dist/src/brief.d.ts +32 -0
- package/dist/src/brief.js +66 -0
- package/dist/src/checklists.d.ts +169 -0
- package/dist/src/checklists.js +310 -0
- package/dist/src/checks.d.ts +1539 -0
- package/dist/src/checks.js +5025 -0
- package/dist/src/cli.d.ts +9 -0
- package/dist/src/cli.js +68 -0
- package/dist/src/commands/brief.d.ts +92 -0
- package/dist/src/commands/brief.js +343 -0
- package/dist/src/commands/checklist.d.ts +42 -0
- package/dist/src/commands/checklist.js +168 -0
- package/dist/src/commands/cutover.d.ts +35 -0
- package/dist/src/commands/cutover.js +448 -0
- package/dist/src/commands/doctor.d.ts +264 -0
- package/dist/src/commands/doctor.js +1546 -0
- package/dist/src/commands/gates.d.ts +9 -0
- package/dist/src/commands/gates.js +360 -0
- package/dist/src/commands/init.d.ts +30 -0
- package/dist/src/commands/init.js +177 -0
- package/dist/src/commands/lock.d.ts +34 -0
- package/dist/src/commands/lock.js +340 -0
- package/dist/src/commands/mode.d.ts +40 -0
- package/dist/src/commands/mode.js +134 -0
- package/dist/src/commands/next.d.ts +130 -0
- package/dist/src/commands/next.js +597 -0
- package/dist/src/commands/plan.d.ts +20 -0
- package/dist/src/commands/plan.js +105 -0
- package/dist/src/commands/pool.d.ts +1 -0
- package/dist/src/commands/pool.js +139 -0
- package/dist/src/commands/resume.d.ts +1 -0
- package/dist/src/commands/resume.js +88 -0
- package/dist/src/commands/spawn.d.ts +1 -0
- package/dist/src/commands/spawn.js +195 -0
- package/dist/src/commands/status.d.ts +21 -0
- package/dist/src/commands/status.js +122 -0
- package/dist/src/commands/sync.d.ts +47 -0
- package/dist/src/commands/sync.js +341 -0
- package/dist/src/commands/teardown.d.ts +1 -0
- package/dist/src/commands/teardown.js +87 -0
- package/dist/src/commands/tuition.d.ts +21 -0
- package/dist/src/commands/tuition.js +218 -0
- package/dist/src/commands/validate.d.ts +78 -0
- package/dist/src/commands/validate.js +430 -0
- package/dist/src/commands/watch.d.ts +1 -0
- package/dist/src/commands/watch.js +172 -0
- package/dist/src/cutover.d.ts +584 -0
- package/dist/src/cutover.js +1444 -0
- package/dist/src/exclusion.d.ts +389 -0
- package/dist/src/exclusion.js +843 -0
- package/dist/src/exec/env.d.ts +278 -0
- package/dist/src/exec/env.js +334 -0
- package/dist/src/fleet.d.ts +223 -0
- package/dist/src/fleet.js +298 -0
- package/dist/src/gates/adapters/http-json.d.ts +5 -0
- package/dist/src/gates/adapters/http-json.js +283 -0
- package/dist/src/gates/adapters/migrations-command.d.ts +1 -0
- package/dist/src/gates/adapters/migrations-command.js +373 -0
- package/dist/src/gates/citations.d.ts +408 -0
- package/dist/src/gates/citations.js +1169 -0
- package/dist/src/gates/coverage.d.ts +375 -0
- package/dist/src/gates/coverage.js +836 -0
- package/dist/src/gates/credentials.d.ts +233 -0
- package/dist/src/gates/credentials.js +752 -0
- package/dist/src/gates/deploy.d.ts +1 -0
- package/dist/src/gates/deploy.js +33 -0
- package/dist/src/gates/gate-classes.d.ts +56 -0
- package/dist/src/gates/gate-classes.js +633 -0
- package/dist/src/gates/manifest.d.ts +99 -0
- package/dist/src/gates/manifest.js +208 -0
- package/dist/src/gates/merge-preconditions.d.ts +319 -0
- package/dist/src/gates/merge-preconditions.js +932 -0
- package/dist/src/gates/migrations.d.ts +1 -0
- package/dist/src/gates/migrations.js +36 -0
- package/dist/src/gates/pin.d.ts +114 -0
- package/dist/src/gates/pin.js +154 -0
- package/dist/src/gates/red-witness.d.ts +22 -0
- package/dist/src/gates/red-witness.js +482 -0
- package/dist/src/gates/release.d.ts +283 -0
- package/dist/src/gates/release.js +820 -0
- package/dist/src/gates/result.d.ts +116 -0
- package/dist/src/gates/result.js +91 -0
- package/dist/src/gates/run.d.ts +614 -0
- package/dist/src/gates/run.js +1614 -0
- package/dist/src/gates/schemas/citation-config.schema.json +59 -0
- package/dist/src/gates/schemas/coverage-config.schema.json +77 -0
- package/dist/src/gates/schemas/gate-manifest.schema.json +125 -0
- package/dist/src/gates/schemas/gate-result.schema.json +160 -0
- package/dist/src/gates/schemas/phase-declaration.schema.json +87 -0
- package/dist/src/gates/schemas/release-record.schema.json +119 -0
- package/dist/src/gates/schemas/verifier-config.schema.json +101 -0
- package/dist/src/gates/schemas/witness-spec.schema.json +110 -0
- package/dist/src/gates/scope.d.ts +131 -0
- package/dist/src/gates/scope.js +1018 -0
- package/dist/src/gates/suite.d.ts +217 -0
- package/dist/src/gates/suite.js +968 -0
- package/dist/src/gates/validate.d.ts +121 -0
- package/dist/src/gates/validate.js +414 -0
- package/dist/src/hooks.d.ts +84 -0
- package/dist/src/hooks.js +125 -0
- package/dist/src/index.d.ts +31 -0
- package/dist/src/index.js +30 -0
- package/dist/src/liveness.d.ts +321 -0
- package/dist/src/liveness.js +396 -0
- package/dist/src/lock.d.ts +256 -0
- package/dist/src/lock.js +792 -0
- package/dist/src/model-resolution.d.ts +159 -0
- package/dist/src/model-resolution.js +307 -0
- package/dist/src/modes.d.ts +149 -0
- package/dist/src/modes.js +258 -0
- package/dist/src/path-identity.d.ts +34 -0
- package/dist/src/path-identity.js +48 -0
- package/dist/src/plan.d.ts +73 -0
- package/dist/src/plan.js +153 -0
- package/dist/src/pool.d.ts +326 -0
- package/dist/src/pool.js +988 -0
- package/dist/src/roles.d.ts +461 -0
- package/dist/src/roles.js +776 -0
- package/dist/src/spawn.d.ts +482 -0
- package/dist/src/spawn.js +1003 -0
- package/dist/src/status.d.ts +116 -0
- package/dist/src/status.js +148 -0
- package/dist/src/task.d.ts +504 -0
- package/dist/src/task.js +307 -0
- package/dist/src/teardown.d.ts +39 -0
- package/dist/src/teardown.js +422 -0
- package/dist/src/tuition.d.ts +159 -0
- package/dist/src/tuition.js +311 -0
- package/dist/src/validate.d.ts +263 -0
- package/dist/src/validate.js +742 -0
- package/dist/src/version.d.ts +3 -0
- package/dist/src/version.js +38 -0
- package/dist/src/watcher.d.ts +275 -0
- package/dist/src/watcher.js +849 -0
- package/dist/src/witness/run.d.ts +299 -0
- package/dist/src/witness/run.js +1373 -0
- package/dist/src/witness/spec.d.ts +270 -0
- package/dist/src/witness/spec.js +475 -0
- package/dist/tsconfig.src.tsbuildinfo +1 -0
- package/gate-registry.yaml +526 -0
- package/gates.manifest.json +257 -0
- package/package.json +72 -3
- package/role-model-config.yaml +88 -0
- package/roles/README.md +128 -0
- package/roles/_shared-dispatch-contract.md +87 -0
- package/roles/adversarial-plan-reviewer.md +80 -0
- package/roles/clean-room-reviewer.md +140 -0
- package/roles/implementer.md +463 -0
- package/roles/investigator.md +138 -0
- package/roles/plan-writer.md +95 -0
- package/schemas/README.md +82 -0
- package/schemas/assurance-modes.schema.json +264 -0
- package/schemas/charter.schema.json +185 -0
- package/schemas/checklist.schema.json +114 -0
- package/schemas/cutover-state.schema.json +64 -0
- package/schemas/decision-record.schema.json +88 -0
- package/schemas/executor-record.schema.json +36 -0
- package/schemas/final-report.schema.json +90 -0
- package/schemas/finding.schema.json +106 -0
- package/schemas/gate-registry.schema.json +260 -0
- package/schemas/mechanism-index.schema.json +94 -0
- package/schemas/model-resolution.schema.json +362 -0
- package/schemas/plan.schema.json +300 -0
- package/schemas/report.schema.json +579 -0
- package/schemas/role-brief.schema.json +105 -0
- package/schemas/role-model-config.schema.json +90 -0
- package/schemas/status-line.schema.json +40 -0
- package/schemas/tuition.schema.json +191 -0
- package/schemas/verdict.schema.json +295 -0
- package/schemas/work-history.schema.json +183 -0
- package/schemas/write-bypass.schema.json +69 -0
- package/templates/charter.example.yaml +54 -0
- package/templates/decision-record.example.yaml +27 -0
- package/templates/final-report.example.yaml +80 -0
- package/templates/plan.example.yaml +87 -0
- package/templates/report.example.yaml +236 -0
- package/templates/warnings.md +74 -0
- package/templates/work-history.example.yaml +185 -0
- package/tuition/README.md +76 -0
- package/tuition/T-001.yaml +48 -0
- package/tuition/T-002.yaml +51 -0
- package/tuition/T-003.yaml +100 -0
- package/tuition/T-004.yaml +52 -0
- package/tuition/T-005.yaml +72 -0
- package/tuition/T-006.yaml +81 -0
- package/tuition/T-007.yaml +56 -0
- package/tuition/T-008.yaml +111 -0
- package/tuition/T-009.yaml +50 -0
- package/tuition/T-015.yaml +36 -0
- package/tuition/T-016.yaml +36 -0
- package/tuition/T-017.yaml +46 -0
- package/tuition/T-018.yaml +84 -0
- package/tuition/T-021.yaml +40 -0
- package/tuition/T-022.yaml +36 -0
- package/tuition/mechanism-index.yaml +256 -0
|
@@ -0,0 +1,1539 @@
|
|
|
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
|
+
* SAY WHAT `produced-by` ACTUALLY COMPARED, ON THE GREEN LINE (CR-VS-003).
|
|
760
|
+
*
|
|
761
|
+
* The comparison is `canonicalScalar`: NFKC, whitespace collapse, lowercase,
|
|
762
|
+
* then `!==`. Reproduced at the swept head with one variable changed: two
|
|
763
|
+
* `produced-by` strings naming two different MODELS of one vendor, in the
|
|
764
|
+
* vendor-plus-model-plus-organisation form this project's own reviews use, are
|
|
765
|
+
* certified "distinct on produced-by", green, exit 0. Two models of ONE family
|
|
766
|
+
* pass as decorrelated, which is T-001's own property failing inside the
|
|
767
|
+
* kernel's decorrelation check. The two strings are quoted verbatim in the
|
|
768
|
+
* sweep evidence rather than here, because no vendor model name may appear in
|
|
769
|
+
* the kernel's shipped surface (test/schemas.test.ts:800).
|
|
770
|
+
*
|
|
771
|
+
* WHY THIS IS A SENTENCE AND NOT A FAMILY VOCABULARY, and the reason is a
|
|
772
|
+
* settled one rather than an omission. M4-P10 deferred the family comparison to
|
|
773
|
+
* M4-P11 (delivery/work-history/m4-p10.md:654); M4-P11 DECLINED the mechanism in
|
|
774
|
+
* its own words, "a closed enum of family names was rejected: no such vocabulary
|
|
775
|
+
* can be kept current" (delivery/work-history/m4-p11.md:142). That reason holds
|
|
776
|
+
* and shipping the enum that phase rejected would be reopening it by the back
|
|
777
|
+
* door. What was never done is the OTHER half of the reviewer's own proposal:
|
|
778
|
+
* stop the green line reading as a cross-family assertion. A bundle-level green
|
|
779
|
+
* saying "distinct on produced-by" is read as "two families reviewed this", and
|
|
780
|
+
* nothing here establishes that. So the line now says what it measured.
|
|
781
|
+
*
|
|
782
|
+
* WHAT WOULD CLOSE IT, named rather than left open: a `produced-by-family`
|
|
783
|
+
* field in `schemas/verdict.schema.json`, required, compared instead of the free
|
|
784
|
+
* string, with the vocabulary OPEN (any two distinct values decorrelate) so no
|
|
785
|
+
* list has to be kept current. That is a schema change and a decision record,
|
|
786
|
+
* both outside this fix round's declared files.
|
|
787
|
+
*/
|
|
788
|
+
export declare function producedByCaveat(compared: readonly string[]): string;
|
|
789
|
+
export interface LoadedVerdict {
|
|
790
|
+
path: string;
|
|
791
|
+
record: Record<string, unknown>;
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* What reading a candidate document's own `kind` produced, in the THREE
|
|
795
|
+
* outcomes that fix round 2 exists to keep apart.
|
|
796
|
+
*
|
|
797
|
+
* THE MECHANISM FIX ROUND 2 CLOSES: `establishField` already separates ABSENT
|
|
798
|
+
* from UNUSABLE from UNCANONICAL, and both selection sites consumed it with a
|
|
799
|
+
* single `!== "established"`, which folds those outcomes back into one silent
|
|
800
|
+
* skip. So "this document declares no type" and "this document declares a type
|
|
801
|
+
* nobody could read" printed as the same fact, and that fact is the determinate
|
|
802
|
+
* negative "not a verdict". Measured at the round-1 head: a third review
|
|
803
|
+
* reading `verdict: FIX-ROUND-NEEDED` whose `kind:` was a one-element YAML list
|
|
804
|
+
* was dropped and `scripts/check-dual-review.mjs` reported that the pair
|
|
805
|
+
* approves. Eight deformations of one refusing document reached that same
|
|
806
|
+
* green, and the table is in delivery/work-history/m4-p10.md's section 13.
|
|
807
|
+
*
|
|
808
|
+
* WHERE THE LINE IS DRAWN, and it is drawn at the PRESENCE OF THE KEY rather
|
|
809
|
+
* than at the validity of its value:
|
|
810
|
+
*
|
|
811
|
+
* `verdict` the key is there and canonicalises to the word. A member.
|
|
812
|
+
* `other` the document ANSWERED and the answer is not `verdict`. That
|
|
813
|
+
* is a mapping carrying no `kind` key at all, a document that
|
|
814
|
+
* is not a mapping (a list, a scalar, an empty file), and a
|
|
815
|
+
* `kind` that reads as some other word. Each is a determinate
|
|
816
|
+
* negative: nothing here claims to be a typed document, or it
|
|
817
|
+
* claims to be a different one.
|
|
818
|
+
* `unreadable` the key IS there and its reading failed: a list, a map, a
|
|
819
|
+
* number, a boolean, null, an empty or whitespace-only string,
|
|
820
|
+
* or a string carrying a character outside printable ASCII.
|
|
821
|
+
* Writing a `kind` key is the claim to be a typed document, so
|
|
822
|
+
* a failed reading of it is a failed claim, not an absent one.
|
|
823
|
+
*
|
|
824
|
+
* WHY NOT REFUSE EVERY DOCUMENT THAT IS NOT A VERDICT. Because a project is
|
|
825
|
+
* entitled to keep other YAML beside its reviews, and a check that errored on
|
|
826
|
+
* it would be unusable. The property is not that every file is a verdict; it is
|
|
827
|
+
* that a file which LOOKS LIKE a verdict and could not be read as one is NAMED.
|
|
828
|
+
*
|
|
829
|
+
* EXPORTED, and that is the other half of the fix. `scripts/check-dual-review.mjs`
|
|
830
|
+
* had its OWN selection rule, a raw `value["kind"] !== "verdict"`, which is a
|
|
831
|
+
* second reader of one fact: it dropped `kind: Verdict` and `kind: " verdict "`
|
|
832
|
+
* that this file's canonicalisation admits. Two readers of one fact is the shape
|
|
833
|
+
* this repository's fix-round contract calls fixing the INSTANCE rather than the
|
|
834
|
+
* MECHANISM, and the sibling `establishDelegatedRegime` one screen down was
|
|
835
|
+
* lifted for exactly that reason. There is now one reader.
|
|
836
|
+
*/
|
|
837
|
+
export type VerdictKindReading = {
|
|
838
|
+
kind: "verdict";
|
|
839
|
+
record: Record<string, unknown>;
|
|
840
|
+
} | {
|
|
841
|
+
kind: "other";
|
|
842
|
+
} | {
|
|
843
|
+
kind: "unreadable";
|
|
844
|
+
found: string;
|
|
845
|
+
};
|
|
846
|
+
export declare function readVerdictKind(value: unknown): VerdictKindReading;
|
|
847
|
+
/**
|
|
848
|
+
* WHERE A CORPUS WAS READ FROM, carried WITH the corpus and never assumed.
|
|
849
|
+
*
|
|
850
|
+
* THE MECHANISM THIS TYPE EXISTS TO CLOSE (M4-P11 fix round 1, CR-M4P11-001
|
|
851
|
+
* and CR-M4P11-002). One decision was assembled out of TWO SOURCES OF TRUTH:
|
|
852
|
+
* the declaration was read from the git object database by
|
|
853
|
+
* `readReviewFamilies`, and the corpus that is supposed to refute it was read
|
|
854
|
+
* from the WORKING TREE. Two sources means the two halves can be made to
|
|
855
|
+
* disagree, and the actor the check exists to guard against controls the half
|
|
856
|
+
* that is not committed.
|
|
857
|
+
*
|
|
858
|
+
* Measured by the reviewer at ONE commit, three arms, only the working tree
|
|
859
|
+
* changing: all verdicts present gave red exit 1; an UNCOMMITTED `rm` of the
|
|
860
|
+
* contradicting verdict gave not-applicable exit 20 with the exception
|
|
861
|
+
* GRANTED; copying the file back gave red again. `git ls-tree` listed the file
|
|
862
|
+
* throughout and `git show` still read `produced-by: family-b` from it. The
|
|
863
|
+
* declaration was tamper-EVIDENT and the evidence that refutes it was not.
|
|
864
|
+
*
|
|
865
|
+
* So the source is decided ONCE per load and travels with the result, and
|
|
866
|
+
* every sentence a check prints about a corpus ends with the source it was
|
|
867
|
+
* actually read from. A reader can tell a claim about a commit from a claim
|
|
868
|
+
* about somebody's working tree, which is SC-011 applied to the CORPUS rather
|
|
869
|
+
* than to a single check's verdict.
|
|
870
|
+
*/
|
|
871
|
+
export type VerdictCorpusSource = {
|
|
872
|
+
kind: "commit";
|
|
873
|
+
ref: string;
|
|
874
|
+
refSha: string;
|
|
875
|
+
scope: string;
|
|
876
|
+
} | {
|
|
877
|
+
kind: "worktree";
|
|
878
|
+
reason: string;
|
|
879
|
+
scope: string;
|
|
880
|
+
};
|
|
881
|
+
/**
|
|
882
|
+
* The corpus, plus the source it was read from. Never one without the other.
|
|
883
|
+
*
|
|
884
|
+
* `unexaminable` IS M4-P10 FIX ROUND 2's CHANNEL, CARRIED ACROSS M4-P11's
|
|
885
|
+
* RESTRUCTURE RATHER THAN DROPPED. M4-P10 added it to the single filesystem
|
|
886
|
+
* loop this phase replaced with a commit arm and a worktree arm, and every
|
|
887
|
+
* caller seeds its violation list from it. A candidate that passed the
|
|
888
|
+
* extension filter and could not be read, did not decode, or declares a `kind`
|
|
889
|
+
* whose reading failed is NOT the determinate answer "not a verdict": it is
|
|
890
|
+
* "nobody knows whether this is a verdict", and dropping it SHRINKS the set the
|
|
891
|
+
* merge predicates reason over, which is the fail-open direction for a
|
|
892
|
+
* predicate that approves when the set is clean.
|
|
893
|
+
*/
|
|
894
|
+
export interface LoadedVerdictCorpus {
|
|
895
|
+
verdicts: LoadedVerdict[];
|
|
896
|
+
unexaminable: Diagnostic[];
|
|
897
|
+
source: VerdictCorpusSource;
|
|
898
|
+
}
|
|
899
|
+
/**
|
|
900
|
+
* How to name the set a check just looked at, in the check's own output.
|
|
901
|
+
*
|
|
902
|
+
* SC-011 one scope out: "every verdict this project has committed" and "every
|
|
903
|
+
* file that happens to be sitting in one directory right now" are different
|
|
904
|
+
* claims and must not print the same sentence. This renders a TRAILING
|
|
905
|
+
* parenthetical rather than a clause in the middle of one, so a sentence that
|
|
906
|
+
* already names its subject keeps its shape and gains a provenance tail.
|
|
907
|
+
*/
|
|
908
|
+
export declare function describeVerdictCorpusSource(source: VerdictCorpusSource): string;
|
|
909
|
+
/**
|
|
910
|
+
* How to name the source ONE context document was looked for in.
|
|
911
|
+
*
|
|
912
|
+
* FIX ROUND 2, DV-001. The regime report line used to say "no charter.yaml"
|
|
913
|
+
* about a directory with a `charter.yaml` sitting in it, because the probe had
|
|
914
|
+
* moved to the commit and the sentence had not. A record that names a document
|
|
915
|
+
* and not the SOURCE it was looked for in is unfalsifiable by the person
|
|
916
|
+
* reading it, which is the same SC-011 property `describeVerdictCorpusSource`
|
|
917
|
+
* exists for one scope out.
|
|
918
|
+
*/
|
|
919
|
+
export declare function describeContextDocumentSource(source: VerdictCorpusSource): string;
|
|
920
|
+
/**
|
|
921
|
+
* The verdict documents a PAIR decision is made over: `delivery/review/`.
|
|
922
|
+
*
|
|
923
|
+
* TWO ARMS, AND WHICH ONE RAN IS REPORTED RATHER THAN INFERRED.
|
|
924
|
+
*
|
|
925
|
+
* THE COMMIT ARM is taken whenever `<context>` resolves `ref`, and it reads
|
|
926
|
+
* the directory's entries out of the git object database. The filesystem is
|
|
927
|
+
* not consulted at all, so an uncommitted addition, deletion or edit cannot
|
|
928
|
+
* change what this returns. That is the anti-widening rule
|
|
929
|
+
* `readReviewFamilies` and `loadDeclaration` (src/gates/release.ts:817)
|
|
930
|
+
* already apply to a DECLARATION, now applied to the evidence beside it. It
|
|
931
|
+
* closes both directions of the same hole: an uncommitted DELETION can no
|
|
932
|
+
* longer remove a verdict that contradicts a declaration, and an uncommitted
|
|
933
|
+
* ADDITION can no longer manufacture the pair DR-0012 condition 2 requires.
|
|
934
|
+
*
|
|
935
|
+
* THE WORKTREE ARM is taken only when there is no resolvable ref, which is the
|
|
936
|
+
* pre-existing behaviour for a context that is not a git repository at all,
|
|
937
|
+
* and it SAYS SO in every sentence it produces. No exception can be granted on
|
|
938
|
+
* this arm, because `readReviewFamilies` resolves the same ref and returns
|
|
939
|
+
* absent or error when it cannot: with no git there is one source of truth and
|
|
940
|
+
* nothing to disagree.
|
|
941
|
+
*
|
|
942
|
+
* THE SCOPE STAYS `delivery/review/` HERE, and widening it was measured wrong.
|
|
943
|
+
* `headGroupFor` turns this set into the reviews of one `(phase, head)`, and
|
|
944
|
+
* five of the seven verdict documents in this repository's tree are fixtures
|
|
945
|
+
* for this check's own tests. See `PAPERWORK_ROOT` above; the widest set is
|
|
946
|
+
* what the FALSIFIERS use, and it is a different question.
|
|
947
|
+
*
|
|
948
|
+
* A file that does not carry `kind: verdict` is SKIPPED rather than reported,
|
|
949
|
+
* because that directory also holds this project's prose reviews and a check
|
|
950
|
+
* that reddened on a markdown file would be unusable. What is NOT skipped is
|
|
951
|
+
* the directory being unreadable, which the caller turns into a violation:
|
|
952
|
+
* "nothing to compare" and "could not look" are different facts.
|
|
953
|
+
*
|
|
954
|
+
* AND A CANDIDATE THAT COULD NOT BE LOOKED AT IS THE SECOND HALF OF THAT SAME
|
|
955
|
+
* SENTENCE, WHICH THE FIRST ROUND WROTE AND APPLIED AT ONE SITE ONLY. A
|
|
956
|
+
* `.yaml`, `.yml` or `.json` file here has passed the only filter that
|
|
957
|
+
* separates a candidate verdict from a prose review, so bytes that cannot be
|
|
958
|
+
* READ and bytes that do not DECODE are not "this is not a verdict", they are
|
|
959
|
+
* "nobody knows whether this is a verdict". Dropping such a file SHRINKS the
|
|
960
|
+
* set the merge predicates reason over, which is the fail-open direction for a
|
|
961
|
+
* predicate that approves when the set is clean: measured at the reviewed head,
|
|
962
|
+
* a third review reading FIX-ROUND-NEEDED with one malformed line left
|
|
963
|
+
* `verdict-pair-approves` printing that the pair approves. So they are returned
|
|
964
|
+
* as diagnostics and every caller seeds its violation list with them, exactly
|
|
965
|
+
* as `headGroupFor` already does for a sibling with no usable head.
|
|
966
|
+
*/
|
|
967
|
+
export declare function loadCommittedVerdicts(contextDirectory: string, source?: VerdictCorpusSource): ({
|
|
968
|
+
ok: true;
|
|
969
|
+
} & LoadedVerdictCorpus) | {
|
|
970
|
+
ok: false;
|
|
971
|
+
reason: string;
|
|
972
|
+
};
|
|
973
|
+
/**
|
|
974
|
+
* Resolve, ONCE, the source every document of one decision is read from.
|
|
975
|
+
*
|
|
976
|
+
* EXPORTED because the two merge-precondition checks each resolve it at the
|
|
977
|
+
* top of their own run and hand the SAME value to the regime reader, the
|
|
978
|
+
* declaration reader and both corpus loaders. One resolution is what makes
|
|
979
|
+
* "the halves disagree" unrepresentable rather than merely unlikely.
|
|
980
|
+
*/
|
|
981
|
+
export declare function resolveCorpusSource(contextDirectory: string, ref?: string): VerdictCorpusSource;
|
|
982
|
+
/**
|
|
983
|
+
* THE MECHANISM THIS SECTION CLOSES, STATED ONE LEVEL UP FROM THE FINDING:
|
|
984
|
+
* a gate whose verdict is about EVIDENCE THE CALLER SUPPLIED, with no check
|
|
985
|
+
* that the evidence is about the thing being audited.
|
|
986
|
+
*
|
|
987
|
+
* `headGroupFor` above groups by the head THE VERDICT DOCUMENTS THEMSELVES
|
|
988
|
+
* DECLARE. Before this section nothing compared that value to the commit the
|
|
989
|
+
* gate was running against, and nothing established that it named a commit at
|
|
990
|
+
* all. Both arms were reproduced end to end through the shipped script:
|
|
991
|
+
*
|
|
992
|
+
* ARM A two decorrelated APPROVE verdicts naming
|
|
993
|
+
* deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, which
|
|
994
|
+
* `git cat-file -t` reports as not an object, in a repository whose
|
|
995
|
+
* HEAD is a real commit -> GREEN, 2 units, exit 0
|
|
996
|
+
* ARM B the same verdicts plus a further commit of work no verdict
|
|
997
|
+
* mentions -> GREEN, exit 0
|
|
998
|
+
*
|
|
999
|
+
* So ONE committed approving pair turned this gate green for that phase at
|
|
1000
|
+
* every later head, indefinitely, on evidence about one old commit. That is
|
|
1001
|
+
* T-009's own rule ("a gate result is evidence only for the configuration it
|
|
1002
|
+
* ran under") failing inside the gate that carries DR-0012's merge grant.
|
|
1003
|
+
*
|
|
1004
|
+
* THE ASYMMETRY THAT MAKES THE FIX SOUND, and it is the whole of the design.
|
|
1005
|
+
* The AUDITED head comes from the CALLER: the gate runner passes `--head` from
|
|
1006
|
+
* the pull-request event (the registry entry now declares `parameters: [head]`,
|
|
1007
|
+
* the same mechanism `scope` has always used), and with no `--head` it is the
|
|
1008
|
+
* commit the context's own `HEAD` resolves to, which is what the checkout put
|
|
1009
|
+
* there. The DECLARED head comes from a document an agent under review wrote.
|
|
1010
|
+
* One of those two is a fact about the run and the other is a claim in the
|
|
1011
|
+
* evidence, and the claim must be measured against the fact rather than
|
|
1012
|
+
* replacing it.
|
|
1013
|
+
*/
|
|
1014
|
+
/** Resolve one ref to a full commit sha inside a context directory. */
|
|
1015
|
+
export declare function resolveCommitIn(contextDirectory: string, ref: string): {
|
|
1016
|
+
ok: true;
|
|
1017
|
+
sha: string;
|
|
1018
|
+
} | {
|
|
1019
|
+
ok: false;
|
|
1020
|
+
reason: string;
|
|
1021
|
+
};
|
|
1022
|
+
/**
|
|
1023
|
+
* The commit a merge gate's verdict is ABOUT.
|
|
1024
|
+
*
|
|
1025
|
+
* THREE OUTCOMES AND NOT TWO, for the same reason `RegimeOutcome` has three:
|
|
1026
|
+
* "there is no commit to anchor to" and "the anchor could not be established"
|
|
1027
|
+
* are different facts. `unanchored` is reached only on the WORKTREE arm with
|
|
1028
|
+
* no `--head`, which is a context that is not a git repository at all, and
|
|
1029
|
+
* every sentence built from it says so rather than implying an anchor that was
|
|
1030
|
+
* never taken.
|
|
1031
|
+
*/
|
|
1032
|
+
export type AuditedHead = {
|
|
1033
|
+
kind: "anchored";
|
|
1034
|
+
head: string;
|
|
1035
|
+
how: string;
|
|
1036
|
+
} | {
|
|
1037
|
+
kind: "unanchored";
|
|
1038
|
+
reason: string;
|
|
1039
|
+
} | {
|
|
1040
|
+
kind: "error";
|
|
1041
|
+
reason: string;
|
|
1042
|
+
};
|
|
1043
|
+
export declare function resolveAuditedHead(contextDirectory: string, requested: string | undefined, source: VerdictCorpusSource): AuditedHead;
|
|
1044
|
+
/**
|
|
1045
|
+
* THE MECHANISM THIS SECTION CLOSES, and it is the anchor above written one
|
|
1046
|
+
* relation too narrow: AN ANCHOR EXPRESSED AS EQUALITY WHERE THE RELATION THAT
|
|
1047
|
+
* CAN ACTUALLY HOLD IS ANCESTRY PLUS A CONSTRAINT ON WHAT CHANGED IN BETWEEN.
|
|
1048
|
+
*
|
|
1049
|
+
* `partitionByAuditedHead` compared the declared head to the audited one with
|
|
1050
|
+
* `===`, and no real flow can satisfy that. A reviewer reads commit X and
|
|
1051
|
+
* writes a verdict naming X; COMMITTING that verdict produces X+1; CI audits
|
|
1052
|
+
* X+1, or a merge commit above it. The declared head is therefore ALWAYS a
|
|
1053
|
+
* strict ancestor of the audited one, so under equality every real run reported
|
|
1054
|
+
* not-applicable. Measured on the branch that introduced the anchor, at
|
|
1055
|
+
* 5867a918cda809f7c5d4bc366fc7940458c140c0: the verdicts declared that commit,
|
|
1056
|
+
* the gate audited its DIRECT CHILD 0ddd06a73d49c1910449d01303bc9c2579f5f492,
|
|
1057
|
+
* and the record read not-applicable, exit 21, "is a review of other work and
|
|
1058
|
+
* is not evidence about this head".
|
|
1059
|
+
*
|
|
1060
|
+
* That is the same cannot-do-its-job shape one status along from the defect the
|
|
1061
|
+
* anchor fixed: "green forever once fed" became "never green", and a gate that
|
|
1062
|
+
* cannot go green is as uninformative as one that cannot go red (T-008's own
|
|
1063
|
+
* rule, applied to the other pole).
|
|
1064
|
+
*
|
|
1065
|
+
* WHAT MAKES THE RELAXATION SAFE, AND IT IS THE WHOLE DESIGN. Ancestry ALONE
|
|
1066
|
+
* would restore the original defect wearing a different hat: an approving pair
|
|
1067
|
+
* lands, and every later descendant carries it, including descendants full of
|
|
1068
|
+
* unreviewed source. So ancestry is admitted only when the TREES agree
|
|
1069
|
+
* everywhere except the project's own paperwork root. A verdict is evidence
|
|
1070
|
+
* about the SHIPPED CONTENT it read, and if that content is byte-identical in
|
|
1071
|
+
* the audited commit then the audited commit is the thing the reviewer
|
|
1072
|
+
* approved, whatever paperwork was committed on top of it.
|
|
1073
|
+
*
|
|
1074
|
+
* IT IS A CLAIM ABOUT THE TWO TREES, NOT ABOUT EACH INTERVENING COMMIT, and
|
|
1075
|
+
* the difference is stated rather than left to be discovered. `git diff
|
|
1076
|
+
* --name-only <declared>..<audited>` compares the endpoints, so a commit that
|
|
1077
|
+
* adds `src/x.ts` and a later one that removes it leave no entry and are
|
|
1078
|
+
* admitted, where a per-commit enumeration would refuse them. That case is
|
|
1079
|
+
* admitted DELIBERATELY: the audited tree's shipped content is then exactly
|
|
1080
|
+
* what the reviewers read, which is the property the gate is protecting. A
|
|
1081
|
+
* per-commit walk would refuse an ordinary revert-before-merge and buy nothing,
|
|
1082
|
+
* because there is no shipped byte in the audited tree that no verdict covers.
|
|
1083
|
+
*
|
|
1084
|
+
* `--no-renames` IS LOAD-BEARING. With rename detection on (git's default for
|
|
1085
|
+
* `git diff` since 2.9) a rename from `src/a.ts` to `delivery/b.md` prints the
|
|
1086
|
+
* DESTINATION ONLY, so the deletion of a source file would be invisible and the
|
|
1087
|
+
* gap would read as paperwork. Disabling it prints both sides.
|
|
1088
|
+
*/
|
|
1089
|
+
/** How a verdict's declared head stands to the commit under audit. */
|
|
1090
|
+
export type HeadRelation =
|
|
1091
|
+
/** The verdict names the audited commit itself. */
|
|
1092
|
+
{
|
|
1093
|
+
kind: "same";
|
|
1094
|
+
}
|
|
1095
|
+
/** A strict ancestor whose gap to the audited commit is paperwork only. */
|
|
1096
|
+
| {
|
|
1097
|
+
kind: "evidence-only-ancestor";
|
|
1098
|
+
changed: string[];
|
|
1099
|
+
}
|
|
1100
|
+
/** A strict ancestor, but shipped content changed in between. */
|
|
1101
|
+
| {
|
|
1102
|
+
kind: "shipped-change";
|
|
1103
|
+
shipped: string[];
|
|
1104
|
+
}
|
|
1105
|
+
/** A real commit here that the audited commit is an ancestor OF. */
|
|
1106
|
+
| {
|
|
1107
|
+
kind: "descendant";
|
|
1108
|
+
}
|
|
1109
|
+
/** A real commit here on neither side of the audited one. */
|
|
1110
|
+
| {
|
|
1111
|
+
kind: "unrelated";
|
|
1112
|
+
}
|
|
1113
|
+
/** Forty hex digits naming no commit in this repository. */
|
|
1114
|
+
| {
|
|
1115
|
+
kind: "unresolvable";
|
|
1116
|
+
reason: string;
|
|
1117
|
+
}
|
|
1118
|
+
/** git could not answer, so the relation is not known. Never admitted. */
|
|
1119
|
+
| {
|
|
1120
|
+
kind: "undetermined";
|
|
1121
|
+
reason: string;
|
|
1122
|
+
};
|
|
1123
|
+
/**
|
|
1124
|
+
* Place one declared head against the commit under audit.
|
|
1125
|
+
*
|
|
1126
|
+
* EQUAL PASSES, unchanged, and it is checked first so a context git cannot be
|
|
1127
|
+
* questioned about still answers the one relation that needs no git at all.
|
|
1128
|
+
*
|
|
1129
|
+
* A DESCENDANT IS REFUSED, and it has its own sentence rather than being folded
|
|
1130
|
+
* into "not an ancestor". A verdict naming a commit BELOW the audited one is a
|
|
1131
|
+
* review of work the audited commit does not contain, which is the fail-open
|
|
1132
|
+
* direction stated backwards: the reviewers saw more than is being merged, and
|
|
1133
|
+
* nothing here establishes that what they approved about the extra work says
|
|
1134
|
+
* anything about the tree without it.
|
|
1135
|
+
*/
|
|
1136
|
+
export declare function relateDeclaredHead(contextDirectory: string, declared: string, auditedHead: string): HeadRelation;
|
|
1137
|
+
/** A verdict admitted to the audited corpus, and the relation that admitted it. */
|
|
1138
|
+
export interface AdmittedVerdict {
|
|
1139
|
+
path: string;
|
|
1140
|
+
declared: string;
|
|
1141
|
+
relation: HeadRelation;
|
|
1142
|
+
}
|
|
1143
|
+
/** One verdict that is not about the audited commit, and why it is not. */
|
|
1144
|
+
export interface OffHeadVerdict {
|
|
1145
|
+
path: string;
|
|
1146
|
+
declared: string;
|
|
1147
|
+
/** Which route refused it. Printed, never summarised to a boolean. */
|
|
1148
|
+
relation: HeadRelation;
|
|
1149
|
+
}
|
|
1150
|
+
/** The corpus split by the commit under audit. */
|
|
1151
|
+
export interface HeadPartition {
|
|
1152
|
+
onHead: LoadedVerdict[];
|
|
1153
|
+
/**
|
|
1154
|
+
* The same verdicts, with the relation that admitted each one.
|
|
1155
|
+
*
|
|
1156
|
+
* CARRIED SEPARATELY RATHER THAN ATTACHED TO `onHead`, because `onHead` is
|
|
1157
|
+
* the set the checks are RUN OVER and its element type is what every other
|
|
1158
|
+
* caller of the loader consumes. This is the DISCLOSURE half: a green reached
|
|
1159
|
+
* through ancestry and a green reached through equality are different facts,
|
|
1160
|
+
* and a gate that printed one sentence for both would be the unfalsifiable
|
|
1161
|
+
* record `describeVerdictCorpusSource` exists to stop, one relation along.
|
|
1162
|
+
*/
|
|
1163
|
+
admitted: AdmittedVerdict[];
|
|
1164
|
+
offHead: OffHeadVerdict[];
|
|
1165
|
+
/**
|
|
1166
|
+
* Verdicts whose own `head` could not be established at all, as DOCUMENTS
|
|
1167
|
+
* and as the sentences that name them.
|
|
1168
|
+
*
|
|
1169
|
+
* BOTH SHAPES, because the two callers need different halves and deriving one
|
|
1170
|
+
* from the other by matching on a message prefix is the string-parsing shape
|
|
1171
|
+
* this file refuses everywhere else. A caller that keeps them in the corpus
|
|
1172
|
+
* needs the documents; a caller that reports them needs the sentences.
|
|
1173
|
+
*/
|
|
1174
|
+
unkeyed: Diagnostic[];
|
|
1175
|
+
unkeyedVerdicts: LoadedVerdict[];
|
|
1176
|
+
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Split a loaded corpus into the verdicts that are about the audited commit
|
|
1179
|
+
* and the ones that are not.
|
|
1180
|
+
*
|
|
1181
|
+
* FIVE REFUSAL ROUTES, AND THEY ARE STRUCTURALLY DIFFERENT RATHER THAN ONE
|
|
1182
|
+
* SHAPE FIVE TIMES, which is what makes them members of a class instead of
|
|
1183
|
+
* instances of a finding:
|
|
1184
|
+
*
|
|
1185
|
+
* RESOLUTION the declared head is not a commit in this repository. The
|
|
1186
|
+
* document is evidence about an object nobody can produce.
|
|
1187
|
+
* SHIPPED GAP the declared head IS an ancestor, and shipped content changed
|
|
1188
|
+
* between it and the audited commit. Unreviewed work is riding
|
|
1189
|
+
* in on a review of something else.
|
|
1190
|
+
* DESCENDANT the declared head is BELOW the audited commit. The reviewers
|
|
1191
|
+
* read a tree the audited commit does not contain.
|
|
1192
|
+
* UNRELATED a real commit on neither side. A review of another line.
|
|
1193
|
+
* UNDETERMINED git could not place it. Never admitted, because a relation
|
|
1194
|
+
* nobody established must not read as the one that passes.
|
|
1195
|
+
*
|
|
1196
|
+
* ADMISSION IS TWO ROUTES AND THEY ARE ALSO PRINTED: the declared head IS the
|
|
1197
|
+
* audited commit, or it is an ancestor whose whole gap is paperwork. See
|
|
1198
|
+
* `relateDeclaredHead` for why the second is safe and for what it deliberately
|
|
1199
|
+
* does not refuse.
|
|
1200
|
+
*
|
|
1201
|
+
* Every refusal leaves the verdict out of the audited group and IS PRINTED with
|
|
1202
|
+
* the route it took, because a document silently dropped from a merge
|
|
1203
|
+
* corpus is the fail-open direction this file has already been bitten by at
|
|
1204
|
+
* `loadCommittedVerdicts`, at the `phase` canonicalisation and at
|
|
1205
|
+
* `headGroupFor`. A reader is owed the fact that the corpus holds two
|
|
1206
|
+
* approving reviews of something else.
|
|
1207
|
+
*/
|
|
1208
|
+
export declare function partitionByAuditedHead(contextDirectory: string, verdicts: readonly LoadedVerdict[], auditedHead: string): HeadPartition;
|
|
1209
|
+
/** One operator-facing line per verdict the audit excluded, naming its route. */
|
|
1210
|
+
export declare function describeOffHeadVerdicts(offHead: readonly OffHeadVerdict[], auditedHead: string): string[];
|
|
1211
|
+
/** One operator-facing line per verdict the audit ADMITTED, naming its route. */
|
|
1212
|
+
export declare function describeAdmittedVerdicts(admitted: readonly AdmittedVerdict[], auditedHead: string): string[];
|
|
1213
|
+
/** The charter field DR-0038's declaration lives in (M4-D-28). */
|
|
1214
|
+
export declare const REVIEW_FAMILIES_FIELD = "review-families";
|
|
1215
|
+
/** The document that carries it. */
|
|
1216
|
+
export declare const CHARTER_DOCUMENT = "charter.yaml";
|
|
1217
|
+
/**
|
|
1218
|
+
* The documents that say WHICH merge-authority regime is in force.
|
|
1219
|
+
*
|
|
1220
|
+
* MOVED HERE FROM `scripts/check-dual-review.mjs` (FIX ROUND 2, DV-001). The
|
|
1221
|
+
* script held its own copy of this list AND its own presence probe, and the
|
|
1222
|
+
* probe read the WORKING TREE while `establishDelegatedRegime` read the
|
|
1223
|
+
* COMMIT. Two probes of one fact against two sources is the mechanism this
|
|
1224
|
+
* phase has now paid for twice: each answered correctly about its own source,
|
|
1225
|
+
* so nothing ever reported a disagreement, and an uncommitted `charter.yaml`
|
|
1226
|
+
* took the gate from error to GREEN on a correlated committed pair.
|
|
1227
|
+
*/
|
|
1228
|
+
export declare const REGIME_DOCUMENTS: string[];
|
|
1229
|
+
/**
|
|
1230
|
+
* The first regime document that is NOT present at the source a decision over
|
|
1231
|
+
* this context would be made from, or `undefined` when both are.
|
|
1232
|
+
*
|
|
1233
|
+
* WHY THE REFUSAL LIVES AT THE MERGE GATE AND THE REPORT LIVES IN THE CHECK,
|
|
1234
|
+
* unchanged from M3-P9 and restated because this round moved the probe: the
|
|
1235
|
+
* derived check runs on ANY verdict with ANY context, and M3-P7's verdict
|
|
1236
|
+
* contexts carry a plan and a work history and no charter, so a check that
|
|
1237
|
+
* reddened on an absent charter reddened eight of that phase's tests. The
|
|
1238
|
+
* check therefore REPORTS, and `scripts/check-dual-review.mjs`, which is the
|
|
1239
|
+
* command DR-0012's grant runs through, refuses. What changed is that the
|
|
1240
|
+
* refusal and the report are now ONE probe with two callers, so they cannot
|
|
1241
|
+
* answer about different sources.
|
|
1242
|
+
*
|
|
1243
|
+
* THE SOURCE IS A PARAMETER, not resolved here, so a caller that has already
|
|
1244
|
+
* resolved one (the gate script resolves it when it loads the corpus) refuses
|
|
1245
|
+
* against the SAME commit it read the verdicts from rather than a second
|
|
1246
|
+
* `rev-parse` that could land elsewhere.
|
|
1247
|
+
*/
|
|
1248
|
+
export declare function missingRegimeDocument(contextDirectory: string, source?: VerdictCorpusSource): {
|
|
1249
|
+
document: string;
|
|
1250
|
+
source: VerdictCorpusSource;
|
|
1251
|
+
reason: string;
|
|
1252
|
+
} | undefined;
|
|
1253
|
+
/**
|
|
1254
|
+
* Where a declaration was read from, so a claim nobody can refute is at least
|
|
1255
|
+
* ATTRIBUTABLE AND DATED.
|
|
1256
|
+
*
|
|
1257
|
+
* This is the honest half of DR-0038's third constraint. Two falsifiers below
|
|
1258
|
+
* catch a project whose own record contradicts the declaration. NEITHER of
|
|
1259
|
+
* them catches a project that HAS a second family available and has simply
|
|
1260
|
+
* never used it, and nothing inside the record can: the record holds what was
|
|
1261
|
+
* used, not what was reachable. So the countermeasure for that residue is
|
|
1262
|
+
* provenance rather than detection, on the src/gates/release.ts:1028 pattern,
|
|
1263
|
+
* and the gap is stated here rather than left to be found.
|
|
1264
|
+
*/
|
|
1265
|
+
export interface ReviewFamiliesProvenance {
|
|
1266
|
+
/** The path inside the commit, as `git show` was asked for it. */
|
|
1267
|
+
path: string;
|
|
1268
|
+
/** The ref the declaration was read from, as the caller spelled it. */
|
|
1269
|
+
ref: string;
|
|
1270
|
+
/** That ref resolved to a commit sha. */
|
|
1271
|
+
refSha: string;
|
|
1272
|
+
/** sha256 of the exact blob bytes the declaration was decoded from. */
|
|
1273
|
+
sha256: string;
|
|
1274
|
+
}
|
|
1275
|
+
/**
|
|
1276
|
+
* What reading `review-families` produced.
|
|
1277
|
+
*
|
|
1278
|
+
* THREE OUTCOMES AND NOT TWO, for the reason `RegimeOutcome` gives one screen
|
|
1279
|
+
* up: "no declaration" and "a declaration that could not be established" are
|
|
1280
|
+
* different facts. The first leaves DR-0012 condition 1 applying unchanged,
|
|
1281
|
+
* which is a REPORT-nothing. The second is an ERROR, because a check that
|
|
1282
|
+
* cannot establish whether an exception applies must never decide that it does
|
|
1283
|
+
* not apply and carry on (M2-C-3).
|
|
1284
|
+
*/
|
|
1285
|
+
export type ReviewFamiliesReading = {
|
|
1286
|
+
kind: "absent";
|
|
1287
|
+
} | {
|
|
1288
|
+
kind: "error";
|
|
1289
|
+
reason: string;
|
|
1290
|
+
} | {
|
|
1291
|
+
kind: "declared";
|
|
1292
|
+
/** Canonicalised, deduplicated by construction, sorted. Compared. */
|
|
1293
|
+
families: string[];
|
|
1294
|
+
/** The operator's own spelling, in document order. Printed. */
|
|
1295
|
+
declaredAs: string[];
|
|
1296
|
+
reason: string;
|
|
1297
|
+
provenance: ReviewFamiliesProvenance;
|
|
1298
|
+
};
|
|
1299
|
+
/**
|
|
1300
|
+
* Read DR-0038's declaration OUT OF THE GIT OBJECT DATABASE, never out of the
|
|
1301
|
+
* working tree.
|
|
1302
|
+
*
|
|
1303
|
+
* WHY THE COMMITTED BLOB IS THE ONLY ONE THAT COUNTS. This is the anti-widening
|
|
1304
|
+
* rule the scope auditor and `loadDeclaration` (src/gates/release.ts:817) both
|
|
1305
|
+
* already apply, one condition along: a phase must not be able to switch off,
|
|
1306
|
+
* inside its own working tree, the condition that would otherwise have refused
|
|
1307
|
+
* its merge. A declaration read from disk is one an implementer can add,
|
|
1308
|
+
* merge under, and delete, leaving a merged head whose record says the
|
|
1309
|
+
* cross-family requirement was met.
|
|
1310
|
+
*
|
|
1311
|
+
* `HEAD:./charter.yaml` AND NOT `HEAD:charter.yaml`, and the difference is not
|
|
1312
|
+
* cosmetic. A path without the leading `./` is resolved against the repository
|
|
1313
|
+
* ROOT, so a context directory that happens to sit inside a larger repository
|
|
1314
|
+
* (which every fixture staged under a checkout does) would silently read that
|
|
1315
|
+
* repository's charter instead of its own. With `./` git resolves relative to
|
|
1316
|
+
* the directory it was run in, which is the one the caller named.
|
|
1317
|
+
*/
|
|
1318
|
+
export declare function readReviewFamilies(contextDirectory: string, ref?: string): ReviewFamiliesReading;
|
|
1319
|
+
/** One line naming where a declaration came from, for a detail or a report. */
|
|
1320
|
+
export declare function reviewFamiliesProvenanceLine(provenance: ReviewFamiliesProvenance): string;
|
|
1321
|
+
/** What the single-family arm concluded about one committed corpus. */
|
|
1322
|
+
export type SingleFamilyOutcome = {
|
|
1323
|
+
kind: "not-declared";
|
|
1324
|
+
} | {
|
|
1325
|
+
kind: "error";
|
|
1326
|
+
reason: string;
|
|
1327
|
+
} | {
|
|
1328
|
+
kind: "refused";
|
|
1329
|
+
violations: Diagnostic[];
|
|
1330
|
+
} | {
|
|
1331
|
+
kind: "exempt";
|
|
1332
|
+
family: string;
|
|
1333
|
+
reading: Extract<ReviewFamiliesReading, {
|
|
1334
|
+
kind: "declared";
|
|
1335
|
+
}>;
|
|
1336
|
+
reports: string[];
|
|
1337
|
+
};
|
|
1338
|
+
/**
|
|
1339
|
+
* DR-0038's exception, and its two falsifiers, over one committed corpus.
|
|
1340
|
+
*
|
|
1341
|
+
* THE EXCEPTION NARROWS EXACTLY ONE DIMENSION. `produced-by` stops being
|
|
1342
|
+
* required to differ. `framing` and `review-contract` are untouched, because
|
|
1343
|
+
* T-007's whole finding is that model decorrelation and CONTRACT decorrelation
|
|
1344
|
+
* are different properties: a single-family environment still has two framings
|
|
1345
|
+
* and two contracts available to it, so relaxing those would be relaxing
|
|
1346
|
+
* something the environment does not force.
|
|
1347
|
+
*
|
|
1348
|
+
* FALSIFIER 1, CONTRADICTION BY THE CORPUS. If the project's own committed
|
|
1349
|
+
* verdicts carry two or more distinct canonicalised `produced-by` values, the
|
|
1350
|
+
* declaration is contradicted by the project's own record and this is RED. A
|
|
1351
|
+
* project that has demonstrably used two cannot claim one.
|
|
1352
|
+
*
|
|
1353
|
+
* FALSIFIER 2, THE NAME MUST MATCH. A verdict whose `produced-by` canonicalises
|
|
1354
|
+
* to anything other than the declared family is RED. Without this, a
|
|
1355
|
+
* declaration could name a family nothing in the record uses and still buy the
|
|
1356
|
+
* relaxation.
|
|
1357
|
+
*
|
|
1358
|
+
* THE SCOPE IS THE WHOLE COMMITTED CORPUS, NOT THE ONE (phase, head) GROUP,
|
|
1359
|
+
* and that is deliberate. "This project has one family available" is a claim
|
|
1360
|
+
* about the project, so the widest set of its own verdicts is what can refute
|
|
1361
|
+
* it. Scoping the falsifiers to the group under review would let a project
|
|
1362
|
+
* whose history carries three families declare one, provided the two reviews
|
|
1363
|
+
* in front of the check happened to agree.
|
|
1364
|
+
*
|
|
1365
|
+
* WHAT IT DOES NOT CATCH, said here and not only in the plan: a project with a
|
|
1366
|
+
* second family AVAILABLE that has simply never used it. Nothing in a record of
|
|
1367
|
+
* what WAS used reaches what COULD have been used. `readReviewFamilies` answers
|
|
1368
|
+
* that with provenance rather than detection: the claim is attributable to a
|
|
1369
|
+
* commit and a blob, so it is dated and signed even where it is not refutable.
|
|
1370
|
+
*/
|
|
1371
|
+
export declare function singleFamilyException(contextDirectory: string, loaded: LoadedVerdictCorpus): SingleFamilyOutcome;
|
|
1372
|
+
/**
|
|
1373
|
+
* DR-0012's merge precondition, made into a comparison a command can make
|
|
1374
|
+
* against the verdict FILES rather than against a session's memory (M3R-004).
|
|
1375
|
+
*
|
|
1376
|
+
* WHY THIS IS KIND B AND COULD NOT BE A KEYWORD. Every dimension it compares
|
|
1377
|
+
* lives in a DIFFERENT DOCUMENT from the instance: distinctness is a property
|
|
1378
|
+
* of a PAIR of verdicts, and no keyword under any DR-0013 option can see the
|
|
1379
|
+
* sibling.
|
|
1380
|
+
*
|
|
1381
|
+
* IT ESTABLISHES PRESENCE ITSELF AND DOES NOT BORROW IT FROM THE SCHEMA. An
|
|
1382
|
+
* earlier version of this comment said the verdict schema's `required` buys
|
|
1383
|
+
* absence-freedom, so this check only had to decide difference. That division of
|
|
1384
|
+
* labour was never composed: nothing on the shipped path validates the SIBLING
|
|
1385
|
+
* documents, so a document with `kind: verdict` and a missing required field is
|
|
1386
|
+
* loaded here and compared. The rule the whole section now follows is
|
|
1387
|
+
* `establishField`, one screen up: a value is not comparable until it has been
|
|
1388
|
+
* established, and absence, unusability and difference are three verdicts, not
|
|
1389
|
+
* one.
|
|
1390
|
+
*
|
|
1391
|
+
* IT APPLIES EXACTLY WHERE THE GRANT APPLIES. The regime is read from the
|
|
1392
|
+
* declared mode, not assumed: `charter.yaml` names the delivery mode and
|
|
1393
|
+
* `assurance-modes.yaml` says what that mode's `merge-authority` is. A mode
|
|
1394
|
+
* whose authority is not a delegated grant has no decorrelation precondition to
|
|
1395
|
+
* satisfy, and this check REPORTS that rather than passing silently, because
|
|
1396
|
+
* "nothing to check here" and "everything checked and fine" must never print
|
|
1397
|
+
* the same line (SC-011).
|
|
1398
|
+
*
|
|
1399
|
+
* FIVE DIMENSIONS, AND (e) IS NOT A REFINEMENT OF (b). T-007's whole finding is
|
|
1400
|
+
* that model decorrelation and CONTRACT decorrelation are different properties
|
|
1401
|
+
* and this project had the second by accident: two reviewers on different model
|
|
1402
|
+
* families walked all fifteen criteria of one phase, agreed on every mechanical
|
|
1403
|
+
* fact, and one missed a high-severity defect because both had been given the
|
|
1404
|
+
* criteria contract. So `review-contract` is compared separately and is
|
|
1405
|
+
* witnessed separately (criterion 7b).
|
|
1406
|
+
*
|
|
1407
|
+
* WHAT IT DOES NOT REACH, named rather than left to be found, AND BOTH ITEMS
|
|
1408
|
+
* THIS PARAGRAPH USED TO NAME HAVE BEEN CLOSED BY M4-P10. The first was
|
|
1409
|
+
* condition (d) of step 3b, that neither verdict carries an unresolved high or
|
|
1410
|
+
* medium finding; that is now the sibling check `verdict-pair-approves`, and
|
|
1411
|
+
* the schema's own root `if`/`then` was widened from [high, critical] to
|
|
1412
|
+
* [medium, high, critical] at the same time, because it had been one severity
|
|
1413
|
+
* narrower than DR-0012 condition 2 ever since it shipped. The second was that
|
|
1414
|
+
* nothing decided whether two verdicts describe the same HEAD; the schema now
|
|
1415
|
+
* requires `head` and this check groups by `(phase, head)`.
|
|
1416
|
+
*
|
|
1417
|
+
* WHAT IS STILL NOT REACHED, so the paragraph does not read as complete. This
|
|
1418
|
+
* check compares `produced-by` as a canonicalised STRING, never as a model
|
|
1419
|
+
* FAMILY, so two values naming one vendor pass as decorrelated; that was
|
|
1420
|
+
* measured twice against this repository's own reviews and recorded at
|
|
1421
|
+
* delivery/verification/m4-prototype-probes.md:1. THE DEFERRAL CHAIN FOR IT
|
|
1422
|
+
* TERMINATED WITH NO OWNER, which is what CR-VS-003 found and what this
|
|
1423
|
+
* paragraph used to hide: it said "closing it is M4-P11's declared scope", and
|
|
1424
|
+
* M4-P11 declined the mechanism (delivery/work-history/m4-p11.md:142) and
|
|
1425
|
+
* shipped the single-family EXCEPTION instead, which is a different question.
|
|
1426
|
+
* No later phase picked it up. The string comparison therefore STANDS, and what
|
|
1427
|
+
* the DR-0047 sweep changed is that the green line now says so: see
|
|
1428
|
+
* `producedByCaveat`, which also names what would close it. And a
|
|
1429
|
+
* `produced-by` line is written BY the reviewing agent, so it is forgeable; an
|
|
1430
|
+
* observed alternative exists and is M4-D-06's business, not this check's.
|
|
1431
|
+
*/
|
|
1432
|
+
export declare const dualReviewDecorrelation: DerivedCheck;
|
|
1433
|
+
/**
|
|
1434
|
+
* The severities DR-0012 condition 2 bars an APPROVE from sitting beside.
|
|
1435
|
+
*
|
|
1436
|
+
* `low` is absent DELIBERATELY and the record says why:
|
|
1437
|
+
* delivery/decisions/DR-0012-delegated-merge-authority.md:23 permits merging
|
|
1438
|
+
* with a low finding provided it is fixed or tracked with a reason. The same
|
|
1439
|
+
* three words are the escalation enum in `schemas/verdict.schema.json`, and the
|
|
1440
|
+
* two must agree; M4-P10 widened both together, because the shipped pair had
|
|
1441
|
+
* the schema stopping at `high` while the decision said `medium`.
|
|
1442
|
+
*/
|
|
1443
|
+
export declare const BLOCKING_SEVERITIES: readonly string[];
|
|
1444
|
+
/**
|
|
1445
|
+
* DR-0012 CONDITION 2, MADE INTO A PREDICATE
|
|
1446
|
+
* (delivery/decisions/DR-0012-delegated-merge-authority.md:23).
|
|
1447
|
+
*
|
|
1448
|
+
* WHAT WAS MISSING, stated as the gap rather than as a feature. Before this
|
|
1449
|
+
* check, `scripts/check-dual-review.mjs` could not see a verdict's VALUE at
|
|
1450
|
+
* all: measured against the whole of that script, `grep -c` returned 0 for
|
|
1451
|
+
* `APPROVE`, 0 for `severity` and 0 for `findings`. So two properly
|
|
1452
|
+
* decorrelated reviews that both REFUSED the merge passed the gate green, and
|
|
1453
|
+
* so did an APPROVE sitting beside a finding the review itself ranked medium.
|
|
1454
|
+
* Condition 1 looked checked and condition 2 was asserted by a human, which is
|
|
1455
|
+
* the worse of the two states because it reads as progress.
|
|
1456
|
+
*
|
|
1457
|
+
* WHY IT IS A SEPARATE CHECK RATHER THAN MORE OF `dual-review-decorrelation`.
|
|
1458
|
+
* They are different predicates over the same set, and section 2.3 rule 3's
|
|
1459
|
+
* Kind B falsification is per-check: DEREGISTERING this one must make a
|
|
1460
|
+
* refusing pair pass, which is only a witness if there is one id to deregister.
|
|
1461
|
+
* Folding condition 2 into the decorrelation check would have made that
|
|
1462
|
+
* witness unavailable and would have made one red indistinguishable from the
|
|
1463
|
+
* other in the gate's output.
|
|
1464
|
+
*
|
|
1465
|
+
* WHY IT EVALUATES THE COMMITTED GROUP AND NEVER THE INSTANCE'S OWN FIELDS,
|
|
1466
|
+
* which is the one place its shape differs from its sibling's. DR-0012
|
|
1467
|
+
* condition 2 is a property of the two reviews WRITTEN TO `delivery/review/`
|
|
1468
|
+
* AND COMMITTED. A document handed to this check that is not among them is not
|
|
1469
|
+
* a review the grant can be satisfied by, and it also cannot break the
|
|
1470
|
+
* predicate: what is asserted is about the committed set, which the stray
|
|
1471
|
+
* document is not a member of. So there is no membership test here, and the
|
|
1472
|
+
* empty case is not a hole: a `(phase, head)` selecting fewer than two
|
|
1473
|
+
* committed verdicts is refused by the pair-size rule below.
|
|
1474
|
+
*
|
|
1475
|
+
* WHAT IT DOES NOT REACH, named rather than left to be found. "Unresolved" is
|
|
1476
|
+
* a state of the review THREAD, and this check reads documents: a finding that
|
|
1477
|
+
* was raised, fixed in a later round and left in the file still reddens here.
|
|
1478
|
+
* That is the fail-closed direction and it is a real cost, paid deliberately,
|
|
1479
|
+
* because the alternative is a resolution field an author sets on their own
|
|
1480
|
+
* finding. Nothing here decides whether a `severity` was ranked honestly
|
|
1481
|
+
* either; a review that calls a critical defect `low` passes, and no keyword
|
|
1482
|
+
* reaches that.
|
|
1483
|
+
*/
|
|
1484
|
+
export declare const verdictPairApproves: DerivedCheck;
|
|
1485
|
+
/**
|
|
1486
|
+
* THE SUBJECT ECHO AGREES WITH THE RESOLUTION IT SITS BESIDE, THE RECORD WAS
|
|
1487
|
+
* WRITTEN AFTER THE TURN ENDED, AND AN OVERRIDE WAS PERMITTED BEFORE IT WAS
|
|
1488
|
+
* APPLIED.
|
|
1489
|
+
*
|
|
1490
|
+
* All three compare SIBLING FIELDS of one document, so all three are Kind B
|
|
1491
|
+
* and none of them is reachable from a keyword (schemas/README.md's Kind A and
|
|
1492
|
+
* Kind B section, DR-0013 clause 8). The schema next door can require that
|
|
1493
|
+
* `subject`, `turnEnd` and `resolution` are all PRESENT, which is what makes a
|
|
1494
|
+
* launch-time record unrepresentable, and it stops exactly there: it cannot
|
|
1495
|
+
* say that two present values agree.
|
|
1496
|
+
*
|
|
1497
|
+
* WHY THE ECHO MATTERS AT ALL, since a record that echoes itself sounds
|
|
1498
|
+
* circular. It is not the record checking itself against itself. `subject` is
|
|
1499
|
+
* a VERBATIM copy of the launch request the adapter was handed and
|
|
1500
|
+
* `resolution` is what the adapter's resolver actually consumed, and the
|
|
1501
|
+
* hazard is that those two diverge silently: a resolver that read the wrong
|
|
1502
|
+
* role's row produces a perfectly well-formed record whose family token is
|
|
1503
|
+
* then attributed to a task it was never about. That is the misattribution
|
|
1504
|
+
* guard src/gates/schemas/release-record.schema.json:26 exists for, one seam
|
|
1505
|
+
* along, and the kernel-side half of it is in src/model-resolution.ts where
|
|
1506
|
+
* the request is compared against a copy the kernel itself holds.
|
|
1507
|
+
*
|
|
1508
|
+
* THE OVERRIDE DIRECTION IS THE ONE MOST LIKELY TO BE GOT WRONG. M4-P7
|
|
1509
|
+
* criterion 7 wants BOTH directions: a role whose `charter-override` is
|
|
1510
|
+
* `allowed` takes the charter's tier, and a role whose permission is anything
|
|
1511
|
+
* else does not. The second direction is the one a resolver written from the
|
|
1512
|
+
* happy path silently drops, because nothing about it looks like a failure.
|
|
1513
|
+
*/
|
|
1514
|
+
export declare const modelResolutionSubjectEcho: DerivedCheck;
|
|
1515
|
+
/** Register a check. Later phases append their own (section 2.3's table). */
|
|
1516
|
+
export declare function registerCheck(check: DerivedCheck): void;
|
|
1517
|
+
/** Remove a check by id. Returns whether one was removed. */
|
|
1518
|
+
export declare function deregisterCheck(id: string): boolean;
|
|
1519
|
+
/** Every check registered for an artifact type, in stable id order. */
|
|
1520
|
+
export declare function checksFor(type: string): DerivedCheck[];
|
|
1521
|
+
/** Every registered check, in registration order. Read by the enumeration. */
|
|
1522
|
+
export declare function registeredChecks(): readonly DerivedCheck[];
|
|
1523
|
+
/** The outcome of running every check registered for a type. */
|
|
1524
|
+
export interface ChecksRun {
|
|
1525
|
+
/** Lines to print, in the order they should appear. */
|
|
1526
|
+
lines: string[];
|
|
1527
|
+
/** True when at least one check violated or was skipped for want of context. */
|
|
1528
|
+
failed: boolean;
|
|
1529
|
+
}
|
|
1530
|
+
/**
|
|
1531
|
+
* Run every registered check for `type`.
|
|
1532
|
+
*
|
|
1533
|
+
* A check whose `requiresContext` is true and which was given none is
|
|
1534
|
+
* SKIPPED and the run FAILS. It is deliberately not an ordinary violation:
|
|
1535
|
+
* "this rule did not run" and "this rule found a problem" are different
|
|
1536
|
+
* facts and a reader must be able to tell them apart, but both are reasons
|
|
1537
|
+
* not to trust a green.
|
|
1538
|
+
*/
|
|
1539
|
+
export declare function runChecks(type: string, instance: unknown, contextDirectory: string | undefined): ChecksRun;
|