@tiphys/kernel 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +611 -0
- package/LICENSE +202 -0
- package/assurance-modes.yaml +278 -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 +14 -0
- package/dist/src/brief.d.ts +32 -0
- package/dist/src/brief.js +59 -0
- package/dist/src/checklists.d.ts +169 -0
- package/dist/src/checklists.js +310 -0
- package/dist/src/checks.d.ts +828 -0
- package/dist/src/checks.js +3314 -0
- package/dist/src/cli.d.ts +9 -0
- package/dist/src/cli.js +57 -0
- package/dist/src/commands/brief.d.ts +92 -0
- package/dist/src/commands/brief.js +320 -0
- package/dist/src/commands/checklist.d.ts +42 -0
- package/dist/src/commands/checklist.js +168 -0
- package/dist/src/commands/doctor.d.ts +35 -0
- package/dist/src/commands/doctor.js +605 -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 +128 -0
- package/dist/src/commands/lock.d.ts +1 -0
- package/dist/src/commands/lock.js +229 -0
- package/dist/src/commands/mode.d.ts +40 -0
- package/dist/src/commands/mode.js +134 -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 +128 -0
- package/dist/src/commands/spawn.d.ts +1 -0
- package/dist/src/commands/spawn.js +146 -0
- package/dist/src/commands/status.d.ts +19 -0
- package/dist/src/commands/status.js +120 -0
- package/dist/src/commands/teardown.d.ts +1 -0
- package/dist/src/commands/teardown.js +79 -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 +360 -0
- package/dist/src/commands/watch.d.ts +1 -0
- package/dist/src/commands/watch.js +172 -0
- package/dist/src/exec/env.d.ts +128 -0
- package/dist/src/exec/env.js +190 -0
- package/dist/src/fleet.d.ts +51 -0
- package/dist/src/fleet.js +80 -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 +1163 -0
- package/dist/src/gates/coverage.d.ts +284 -0
- package/dist/src/gates/coverage.js +701 -0
- package/dist/src/gates/credentials.d.ts +74 -0
- package/dist/src/gates/credentials.js +533 -0
- package/dist/src/gates/deploy.d.ts +1 -0
- package/dist/src/gates/deploy.js +33 -0
- package/dist/src/gates/manifest.d.ts +99 -0
- package/dist/src/gates/manifest.js +208 -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 +390 -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 +566 -0
- package/dist/src/gates/run.js +1536 -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 +42 -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 +927 -0
- package/dist/src/gates/validate.d.ts +121 -0
- package/dist/src/gates/validate.js +414 -0
- package/dist/src/hooks.d.ts +32 -0
- package/dist/src/hooks.js +62 -0
- package/dist/src/liveness.d.ts +321 -0
- package/dist/src/liveness.js +396 -0
- package/dist/src/lock.d.ts +178 -0
- package/dist/src/lock.js +500 -0
- package/dist/src/modes.d.ts +149 -0
- package/dist/src/modes.js +258 -0
- package/dist/src/path-identity.d.ts +2 -0
- package/dist/src/path-identity.js +10 -0
- package/dist/src/plan.d.ts +73 -0
- package/dist/src/plan.js +153 -0
- package/dist/src/pool.d.ts +130 -0
- package/dist/src/pool.js +721 -0
- package/dist/src/roles.d.ts +430 -0
- package/dist/src/roles.js +734 -0
- package/dist/src/spawn.d.ts +177 -0
- package/dist/src/spawn.js +332 -0
- package/dist/src/status.d.ts +91 -0
- package/dist/src/status.js +119 -0
- package/dist/src/task.d.ts +264 -0
- package/dist/src/task.js +305 -0
- package/dist/src/teardown.d.ts +32 -0
- package/dist/src/teardown.js +314 -0
- package/dist/src/tuition.d.ts +159 -0
- package/dist/src/tuition.js +311 -0
- package/dist/src/validate.d.ts +230 -0
- package/dist/src/validate.js +732 -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 +859 -0
- package/dist/src/witness/run.d.ts +274 -0
- package/dist/src/witness/run.js +1327 -0
- package/dist/src/witness/spec.d.ts +102 -0
- package/dist/src/witness/spec.js +253 -0
- package/dist/tsconfig.src.tsbuildinfo +1 -0
- package/gate-registry.yaml +390 -0
- package/gates.manifest.json +195 -0
- package/package.json +57 -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 +460 -0
- package/roles/investigator.md +138 -0
- package/roles/plan-writer.md +95 -0
- package/schemas/README.md +81 -0
- package/schemas/assurance-modes.schema.json +264 -0
- package/schemas/charter.schema.json +166 -0
- package/schemas/checklist.schema.json +114 -0
- package/schemas/decision-record.schema.json +88 -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/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 +289 -0
- package/schemas/work-history.schema.json +183 -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,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE COVERAGE CHECKER (kernel plan M2, M2-P6).
|
|
3
|
+
*
|
|
4
|
+
* "No orphans" as a check with an exit code: every id in an INVENTORY
|
|
5
|
+
* document lands in exactly one row of a COVERAGE-TABLE document, a bucket
|
|
6
|
+
* value that does not match a declared kind is named rather than silently
|
|
7
|
+
* uncounted, a bucket kind that requires a note (`parked`) is red when the
|
|
8
|
+
* note is empty, and a coverage-table row whose id is absent from the
|
|
9
|
+
* inventory (a renumbering) is named as phantom coverage.
|
|
10
|
+
*
|
|
11
|
+
* HAZARD CLASS (T-007, M2-D-18): arithmetic over two documents that can
|
|
12
|
+
* drift, where a total can add up while a row is lost. Named defenses,
|
|
13
|
+
* each tied to a criterion:
|
|
14
|
+
*
|
|
15
|
+
* - a renumbering that leaves a bucket row pointing at a dead id: the
|
|
16
|
+
* PHANTOM check (every coverage-table row's id is required to be in
|
|
17
|
+
* the inventory), independent of the orphan check (every inventory id
|
|
18
|
+
* is required to have a coverage-table row).
|
|
19
|
+
* - a duplicated id INSIDE the inventory document itself (fix round 1,
|
|
20
|
+
* CR-985): counted once as a unit is not the same claim as "appears
|
|
21
|
+
* once in the text", so `units` is the count of DISTINCT ids and a
|
|
22
|
+
* repeated id is its own named finding (`duplicate-inventory-id`),
|
|
23
|
+
* symmetric with the coverage side's `double-bucketed` check.
|
|
24
|
+
* **CORRECTED CLAIM (fix round 1): an earlier revision of this comment
|
|
25
|
+
* said the orphan and phantom checks "scan in opposite directions on
|
|
26
|
+
* purpose, so neither can compensate for the other's blind spot." That
|
|
27
|
+
* was false for cardinality: a duplicated inventory id defeated BOTH
|
|
28
|
+
* of them (it is not an orphan, because a coverage row exists; it is
|
|
29
|
+
* not phantom, because the id is genuinely in the inventory), and
|
|
30
|
+
* inflated every count while staying green. The true property is
|
|
31
|
+
* narrower: orphan and phantom together catch every EXISTENCE
|
|
32
|
+
* mismatch (an id present on one side and not the other); cardinality
|
|
33
|
+
* mismatches (an id present more than once on one side) need the
|
|
34
|
+
* separate check named above, and a row lost from BOTH documents
|
|
35
|
+
* needs the `expectedUnits` check below, because the two documents
|
|
36
|
+
* still agree with each other in that case and existence/cardinality
|
|
37
|
+
* checks over agreeing documents find nothing.
|
|
38
|
+
* - a row lost from BOTH documents (fix round 1, CR-986): the previous
|
|
39
|
+
* bullet's residue. An optional `expectedUnits` config field states
|
|
40
|
+
* the anchor no arithmetic over the two documents alone can produce;
|
|
41
|
+
* a computed unit count that does not equal it is the
|
|
42
|
+
* `expected-units-mismatch` finding. This repository's real config
|
|
43
|
+
* sets it to 115 (kernel plan v1 Appendix A's stated total).
|
|
44
|
+
* - a bucket value matching no declared kind, silently uncounted: every
|
|
45
|
+
* bucket-kind pattern is compiled ANCHORED (`^(?:pattern)$`) and tested
|
|
46
|
+
* against the whole cell; a value none of them match is the
|
|
47
|
+
* `unknown-kind` finding, named by id and value, never absorbed into a
|
|
48
|
+
* nearby kind by a partial match.
|
|
49
|
+
* - a bucket value matching MORE than one declared kind (fix round 1,
|
|
50
|
+
* CR-992): resolved by silent first-match-wins until this round; now
|
|
51
|
+
* the `ambiguous-kind` finding, naming every kind that matched, rather
|
|
52
|
+
* than one kind's `requiresNote` silently never being consulted.
|
|
53
|
+
* - an empty inventory producing a green with nothing examined: `units`
|
|
54
|
+
* is always the number of DISTINCT ids the inventory actually
|
|
55
|
+
* produced, and this module never constructs a `GateResult` except
|
|
56
|
+
* through `makeGateResult`, whose M2-C-2 rewrite turns a
|
|
57
|
+
* green-with-zero-units record into `error` with `vacuous: true`.
|
|
58
|
+
* This gate does not duplicate that rule; it relies on the shared
|
|
59
|
+
* constructor the way M2-C-6 requires reuse of `classifyEntry` rather
|
|
60
|
+
* than a second implementation of "may this path be read".
|
|
61
|
+
* - a milestone extraction that cannot produce the totals the plan
|
|
62
|
+
* states: the milestone view and the kind view are two INDEPENDENT
|
|
63
|
+
* tallies computed from the same classification pass (`perKind` keyed
|
|
64
|
+
* by the bucket kind's name, `perMilestone` keyed by the pattern's
|
|
65
|
+
* first capture group when present, else by the kind's own name), so
|
|
66
|
+
* the two views can be compared against each other and against the
|
|
67
|
+
* plan's stated totals rather than one being asserted to imply the
|
|
68
|
+
* other.
|
|
69
|
+
* - a finding whose outcome cell is present but empty:
|
|
70
|
+
* `checkFindingOutcomeParity` treats an empty outcome as a named
|
|
71
|
+
* failure distinct from a missing row, so "the row exists" and "the
|
|
72
|
+
* row says something" are not conflated. Fix round 1, CR-987: "empty"
|
|
73
|
+
* is ONE shared predicate (`isEmptyCell`, below), applied wherever a
|
|
74
|
+
* note or an outcome is tested, so whitespace-only and zero-width-only
|
|
75
|
+
* content (U+200B, which `String.prototype.trim` does not strip) is
|
|
76
|
+
* empty on both sides rather than only where a trim happened to run.
|
|
77
|
+
* - a finding-to-outcome report carrying a PHANTOM outcome (fix round 1,
|
|
78
|
+
* CR-988): `checkFindingOutcomeParity` used to scan inventory ids
|
|
79
|
+
* only, so a report row for an id absent from the inventory (the
|
|
80
|
+
* renumbering shape the coverage side's phantom check exists for) was
|
|
81
|
+
* silently accepted. Now symmetric: a phantom outcome row is named.
|
|
82
|
+
*
|
|
83
|
+
* M2-C-6: the inventory path, the coverage-table path and an optional
|
|
84
|
+
* `--config` document are all supplied by configuration and none of them
|
|
85
|
+
* is a path this module created, so every read goes through
|
|
86
|
+
* `readRegularFileIfPresent` (which itself routes through `classifyEntry`),
|
|
87
|
+
* never a bare `readFileSync`. A named pipe at any of the three paths is
|
|
88
|
+
* `error` naming the path and the observed type, and this module never
|
|
89
|
+
* blocks on one. Fix round 1, CR-989: the same discipline now applies to
|
|
90
|
+
* the WRITE side inside the evidence directory (`counts.json`): a refused
|
|
91
|
+
* or failed write there used to be computed and discarded, leaving a
|
|
92
|
+
* silent green with empty evidence; it is now loud and makes the gate
|
|
93
|
+
* `error`, the same way a refused result-path write already did.
|
|
94
|
+
*
|
|
95
|
+
* Fix round 1 also closes the REGEX MECHANISM (CR-990/991/992): every
|
|
96
|
+
* config-supplied pattern (both `idPattern`s and every `bucketKinds[].pattern`)
|
|
97
|
+
* is VALIDATED (compiles, and is rejected if it matches a known
|
|
98
|
+
* catastrophic-backtracking shape) before it is ever executed, and every
|
|
99
|
+
* EXECUTION of a config-supplied pattern is BOUNDED by a wall-clock timeout
|
|
100
|
+
* (`boundedExec`, below), so neither a malformed pattern (CR-990, used to
|
|
101
|
+
* throw with no result record written) nor a ReDoS pattern (CR-991, used
|
|
102
|
+
* to hang indefinitely) can defeat this gate; CR-992 (overlapping kinds)
|
|
103
|
+
* is folded into the same fix because it is the same "a config string is
|
|
104
|
+
* trusted further than its syntax justifies" mechanism one property over.
|
|
105
|
+
*/
|
|
106
|
+
/** One row of the `bucketKinds` config. */
|
|
107
|
+
export interface BucketKindConfig {
|
|
108
|
+
kind: string;
|
|
109
|
+
/** Regex source, compiled anchored `^(?:pattern)$` against a bucket value. */
|
|
110
|
+
pattern: string;
|
|
111
|
+
requiresNote: boolean;
|
|
112
|
+
}
|
|
113
|
+
export interface DocumentConfig {
|
|
114
|
+
path: string;
|
|
115
|
+
/** Regex source, compiled anchored, tested against a row's first cell. */
|
|
116
|
+
idPattern: string;
|
|
117
|
+
}
|
|
118
|
+
export interface CoverageTableConfig extends DocumentConfig {
|
|
119
|
+
/** 0-based cell index (cell 0 is the id) holding the bucket value. */
|
|
120
|
+
bucketColumn: number;
|
|
121
|
+
/** 0-based cell index holding the note. */
|
|
122
|
+
noteColumn: number;
|
|
123
|
+
}
|
|
124
|
+
export interface CoverageConfig {
|
|
125
|
+
inventory: DocumentConfig;
|
|
126
|
+
coverageTable: CoverageTableConfig;
|
|
127
|
+
bucketKinds: BucketKindConfig[];
|
|
128
|
+
/**
|
|
129
|
+
* CR-986: the exact expected count of DISTINCT inventory ids. Optional;
|
|
130
|
+
* when absent, no floor is enforced. A row deleted from BOTH documents
|
|
131
|
+
* leaves the two documents agreeing with each other, which every other
|
|
132
|
+
* check in this module is powerless against, so this is a config-stated
|
|
133
|
+
* anchor rather than a derived one.
|
|
134
|
+
*/
|
|
135
|
+
expectedUnits?: number;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* THE KERNEL CONFIG (kernel plan M2-P6 step 2): this repository's real
|
|
139
|
+
* pair and the four bucket kinds the plan states verbatim. It is a plain
|
|
140
|
+
* exported constant, not a checked-in data file, because M2-C-1's
|
|
141
|
+
* verification-first reading of the plan's files-to-touch list for this
|
|
142
|
+
* phase names the module, its schema and its test, and no committed
|
|
143
|
+
* configuration document alongside them; a `--config` flag (validated
|
|
144
|
+
* against `coverage-config.schema.json`) exists for a caller that wants a
|
|
145
|
+
* different pair, and every fixture test in `test/coverage-gate.test.ts`
|
|
146
|
+
* uses it rather than editing this constant.
|
|
147
|
+
*/
|
|
148
|
+
export declare const KERNEL_COVERAGE_CONFIG: CoverageConfig;
|
|
149
|
+
/**
|
|
150
|
+
* THE SHARED EMPTINESS PREDICATE (fix round 1, CR-987).
|
|
151
|
+
*
|
|
152
|
+
* Before this round, `checkCoverage`'s note check compared a value already
|
|
153
|
+
* passed through `String.prototype.trim` (applied once, at extraction) to
|
|
154
|
+
* `""`, and `checkFindingOutcomeParity`'s outcome check compared a value
|
|
155
|
+
* that was never trimmed at all to `""`. Two definitions, only one of
|
|
156
|
+
* which trimmed, and NEITHER strips a zero-width character: `trim()`
|
|
157
|
+
* removes Unicode whitespace (which includes U+00A0 and U+FEFF) but not
|
|
158
|
+
* U+200B ZERO WIDTH SPACE, U+200C ZERO WIDTH NON-JOINER or U+200D ZERO
|
|
159
|
+
* WIDTH JOINER, so a cell or an outcome containing only one of those reads
|
|
160
|
+
* as non-empty to a bare `=== ""` comparison, trimmed or not. One
|
|
161
|
+
* predicate, called at every point this module asks "is this empty",
|
|
162
|
+
* closes both instances at once.
|
|
163
|
+
*/
|
|
164
|
+
export declare function isEmptyCell(value: string): boolean;
|
|
165
|
+
/** Wall-clock bound on one regex execution. Measured (this round): a real
|
|
166
|
+
* catastrophic pattern, `(a+)+b` against 30 a's, which never returns on
|
|
167
|
+
* its own, is interrupted within 251-267ms under this mechanism; a safe
|
|
168
|
+
* pattern executes in under a millisecond, so the bound is not on the
|
|
169
|
+
* critical path for any pattern this repository's own config uses. */
|
|
170
|
+
export declare const REGEX_EXEC_TIMEOUT_MS = 250;
|
|
171
|
+
export declare class RegexBoundExceededError extends Error {
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Execute `compiled.exec(value)` inside a v8 context with a wall-clock
|
|
175
|
+
* timeout. `node:vm`'s `timeout` option interrupts synchronous JavaScript
|
|
176
|
+
* execution, INCLUDING regex backtracking (v8 checks for the termination
|
|
177
|
+
* request during a regex match, not only between statements), which is
|
|
178
|
+
* why this bound can stop a hung `.exec()` where a plain try/catch around
|
|
179
|
+
* a synchronous call cannot: a catastrophic match never throws on its
|
|
180
|
+
* own, it simply never returns. Measured directly (this round): the same
|
|
181
|
+
* `(a+)+b` pattern against inputs of length 18 through 40 completes in
|
|
182
|
+
* under 40ms up to length 22, then 63ms, 302ms, and is interrupted at the
|
|
183
|
+
* 250ms bound from length 26 onward, rather than running to the multi-
|
|
184
|
+
* second and then multi-minute times the unbounded engine produces at
|
|
185
|
+
* length 26 and 40.
|
|
186
|
+
*/
|
|
187
|
+
export declare function boundedExec(compiled: RegExp, value: string): RegExpExecArray | null;
|
|
188
|
+
/**
|
|
189
|
+
* A STATIC heuristic for the single most common catastrophic-backtracking
|
|
190
|
+
* shape (fix round 1, CR-991): a parenthesised group containing an
|
|
191
|
+
* unbounded quantifier (`+` or `*`), itself immediately followed by
|
|
192
|
+
* another unbounded quantifier, e.g. `(a+)+`, `(a*)+`, `(a+)*`. This is
|
|
193
|
+
* exactly the shape the round's own red witness constructs
|
|
194
|
+
* (`(a+)+b`). It is a heuristic, not a proof: it does not see every
|
|
195
|
+
* catastrophic shape (a documented residue below), which is why every
|
|
196
|
+
* EXECUTION is also bounded by `boundedExec` regardless of whether a
|
|
197
|
+
* pattern passes this check.
|
|
198
|
+
*/
|
|
199
|
+
export declare function catastrophicShapeReason(pattern: string): string | undefined;
|
|
200
|
+
/**
|
|
201
|
+
* Validate one config-supplied pattern SOURCE before it is ever compiled
|
|
202
|
+
* into a live regex the gate will execute (fix round 1, CR-990/991):
|
|
203
|
+
* compiles cleanly, and does not match the static catastrophic-shape
|
|
204
|
+
* heuristic. `label` identifies which config field failed, so a config
|
|
205
|
+
* error names the field, not just "a pattern".
|
|
206
|
+
*/
|
|
207
|
+
export declare function validatePatternSource(label: string, pattern: string): string | undefined;
|
|
208
|
+
/**
|
|
209
|
+
* Validate every config-supplied pattern this module will ever compile
|
|
210
|
+
* and execute: both `idPattern`s and every `bucketKinds[].pattern`. Run
|
|
211
|
+
* once per config, before the config is used, so a malformed or dangerous
|
|
212
|
+
* pattern is a named CONFIG error (a clean result record) rather than an
|
|
213
|
+
* uncaught exception with no record (CR-990) or an unbounded hang
|
|
214
|
+
* (CR-991).
|
|
215
|
+
*/
|
|
216
|
+
export declare function validateConfigPatterns(config: CoverageConfig): string | undefined;
|
|
217
|
+
interface TableRow {
|
|
218
|
+
id: string;
|
|
219
|
+
cells: string[];
|
|
220
|
+
line: number;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Walk a document's lines and return every markdown-table row whose first
|
|
224
|
+
* cell matches `idPattern` (compiled anchored). Separator rows
|
|
225
|
+
* (`|---|:--:|---|`) are skipped by construction: every cell in one matches
|
|
226
|
+
* `/^:?-+:?$/`, which cannot also match a realistic id pattern, but the
|
|
227
|
+
* separator test is applied explicitly rather than relied on implicitly, so
|
|
228
|
+
* a future id pattern that could coincide does not silently absorb one.
|
|
229
|
+
* Every match against a config-supplied pattern is BOUNDED (fix round 1,
|
|
230
|
+
* `boundedExec`), so a hostile `idPattern` cannot hang this walk.
|
|
231
|
+
*/
|
|
232
|
+
export declare function extractIdRows(text: string, idPattern: string): TableRow[];
|
|
233
|
+
export type CoverageFindingKind = "orphan" | "double-bucketed" | "phantom" | "unknown-kind" | "ambiguous-kind" | "missing-note" | "duplicate-inventory-id" | "expected-units-mismatch";
|
|
234
|
+
export interface CoverageFinding {
|
|
235
|
+
kind: CoverageFindingKind;
|
|
236
|
+
id: string;
|
|
237
|
+
detail: string;
|
|
238
|
+
}
|
|
239
|
+
export interface CoverageReport {
|
|
240
|
+
totalInventoryIds: number;
|
|
241
|
+
perKind: Record<string, number>;
|
|
242
|
+
perMilestone: Record<string, number>;
|
|
243
|
+
findings: CoverageFinding[];
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* The core check. Pure: takes the two documents' TEXT (already read through
|
|
247
|
+
* M2-C-6's guarded read at the call site) and the config, and returns a
|
|
248
|
+
* report with nothing hidden inside a status string.
|
|
249
|
+
*/
|
|
250
|
+
export declare function checkCoverage(config: CoverageConfig, inventoryText: string, coverageTableText: string): CoverageReport;
|
|
251
|
+
/**
|
|
252
|
+
* R-089b, THE FINDING-TO-OUTCOME PARITY CONTRACT (M2-P6 step 4).
|
|
253
|
+
*
|
|
254
|
+
* Section 2 item 2 of the M2 plan states that the report contract does not
|
|
255
|
+
* exist yet, so this module defines its own input shape and M3's report
|
|
256
|
+
* schema must emit it or supersede it. The shape declared here:
|
|
257
|
+
*
|
|
258
|
+
* inventoryIds: string[] every id that must be resolved
|
|
259
|
+
* findings: { id: string; outcome: string }[] the report's rows
|
|
260
|
+
*
|
|
261
|
+
* A CONFORMING future report is a list of `{id, outcome}` pairs, one row
|
|
262
|
+
* per id, `outcome` a non-empty string. This function does not care what
|
|
263
|
+
* the outcome STRING says (that is a judgement M3 owns); it only checks
|
|
264
|
+
* that every id got exactly one non-empty say. Fix round 1 adds the
|
|
265
|
+
* direction the original version lacked: a report row whose id is not in
|
|
266
|
+
* the inventory at all (CR-988, a PHANTOM outcome, symmetric with
|
|
267
|
+
* `checkCoverage`'s phantom finding) is also named, not silently accepted.
|
|
268
|
+
*/
|
|
269
|
+
export interface FindingOutcomeRow {
|
|
270
|
+
id: string;
|
|
271
|
+
outcome: string;
|
|
272
|
+
}
|
|
273
|
+
export interface FindingParityResult {
|
|
274
|
+
ok: boolean;
|
|
275
|
+
checked: number;
|
|
276
|
+
missing: string[];
|
|
277
|
+
duplicated: string[];
|
|
278
|
+
empty: string[];
|
|
279
|
+
/** CR-988: report rows whose id is absent from `inventoryIds`. */
|
|
280
|
+
phantom: string[];
|
|
281
|
+
}
|
|
282
|
+
export declare function checkFindingOutcomeParity(inventoryIds: string[], findings: FindingOutcomeRow[]): FindingParityResult;
|
|
283
|
+
export declare function main(argv: string[]): number;
|
|
284
|
+
export {};
|