@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,408 @@
|
|
|
1
|
+
import type { GateResultFields } from "./result.ts";
|
|
2
|
+
import type { SchemaDocument } from "./validate.ts";
|
|
3
|
+
/**
|
|
4
|
+
* THE CITATION LINTER (kernel plan M2, M2-P5).
|
|
5
|
+
*
|
|
6
|
+
* FIX ROUND ONE (2026-08-06). The round-one hazard review (`delivery/review/
|
|
7
|
+
* clean-room-m2-p5-hazard.md`) found the delivered gate exits RED on the
|
|
8
|
+
* head that delivered it (CR-1015) and reds on pre-existing content a PR did
|
|
9
|
+
* not touch (CR-1016). Both trace to ONE mechanism: the gate lints the
|
|
10
|
+
* WHOLE BODY of every changed file, and cannot tell a citation a document
|
|
11
|
+
* MAKES from one it QUOTES, nor a line the PR wrote from a line that was
|
|
12
|
+
* already there. The arbitration (`delivery/review/arbitration-m2-p5.md`)
|
|
13
|
+
* settles two design questions that this round implements rather than
|
|
14
|
+
* re-litigates:
|
|
15
|
+
*
|
|
16
|
+
* M2-D-21 (diff-read scope): a citation is resolved only when it was
|
|
17
|
+
* ADDED or MODIFIED in the diff `base...head`, computed per changed HUNK.
|
|
18
|
+
* The `citationRequired` vacuous guard still asks whether the document AS
|
|
19
|
+
* A WHOLE makes at least one citation (not hunk-scoped).
|
|
20
|
+
*
|
|
21
|
+
* M2-D-22 (made vs quoted): a citation inside an inline code span
|
|
22
|
+
* (backticks) or a fenced code block is QUOTED, not made, and is never
|
|
23
|
+
* resolved. This is the convention the repository already follows
|
|
24
|
+
* (writing `src/nope.ts:1` in prose to mean "this does not resolve").
|
|
25
|
+
*
|
|
26
|
+
* The same round also closes, at the mechanism rather than the instance:
|
|
27
|
+
*
|
|
28
|
+
* CR-1017: every content read (the document under lint, and every cited
|
|
29
|
+
* target) is now taken from the GIT OBJECT at the `--head` revision via
|
|
30
|
+
* `git cat-file`, never from the working tree / `cwd`. A gate told to
|
|
31
|
+
* judge revision X now judges X regardless of what is checked out.
|
|
32
|
+
* Structural side effect, verified rather than assumed (see the module's
|
|
33
|
+
* `readGitBlob`/`gitObjectType` doc comment): this ALSO closes CR-1018,
|
|
34
|
+
* because a git tree has no ".." entry and cannot be escaped by a
|
|
35
|
+
* traversal string, and CR-1021 (the vanish race), because the file list
|
|
36
|
+
* and the content it names now come from the SAME fixed git objects
|
|
37
|
+
* instead of two different clocks (a commit graph and a live filesystem).
|
|
38
|
+
*
|
|
39
|
+
* CR-1019: a `@sha256:` suffix that is present but does not match the
|
|
40
|
+
* 64-lowercase-hex shape is `red` naming the malformed suffix, never
|
|
41
|
+
* silently dropped to a hash-free citation.
|
|
42
|
+
*
|
|
43
|
+
* CR-1020: the vacuous guard counts SUBSTANTIVE citations (not quoted,
|
|
44
|
+
* not a citation to the document's own path), so a document that only
|
|
45
|
+
* cites itself no longer satisfies it.
|
|
46
|
+
*
|
|
47
|
+
* CR-1022: root classification checks EVERY declared root for the
|
|
48
|
+
* concrete path under test (never returns on the first match); a path
|
|
49
|
+
* matching more than one root is `ambiguous`, refused rather than
|
|
50
|
+
* guessed. The shipped default config's local and external match lists
|
|
51
|
+
* are DISJOINT (the local `bin` pattern is narrowed to `bin/*.ts`, the
|
|
52
|
+
* real files this checkout ships there, rather than `bin/**`, which used
|
|
53
|
+
* to overlap `bin/fm-*.sh` and depended on undocumented array order to
|
|
54
|
+
* resolve correctly), so the ambiguity check has nothing to silently
|
|
55
|
+
* paper over in the shipped configuration.
|
|
56
|
+
*
|
|
57
|
+
* CR-1023/1024/1025/1026: the grammar's token boundary is Unicode-aware
|
|
58
|
+
* (a token cannot be fabricated by resuming a match after a colon,
|
|
59
|
+
* backslash or a non-ASCII letter), a malformed trailing continuation
|
|
60
|
+
* (`:3-`, `:3.5`, a non-ASCII hyphen) is `red` naming the leftover text
|
|
61
|
+
* rather than silently truncated, leading zeros are an explicitly
|
|
62
|
+
* documented and intentional relaxation, and a content hash is computed
|
|
63
|
+
* over the cited lines with any trailing `\r` stripped, so a CRLF
|
|
64
|
+
* checkout does not red on a normalization difference.
|
|
65
|
+
*
|
|
66
|
+
* HAZARD CLASS (T-007, M2-D-18), restated because it still drives every
|
|
67
|
+
* design choice below: "a linter over documents it does not own, walking a
|
|
68
|
+
* tree supplied by configuration." M2-C-6 IS OBEYED BY REUSE, NOT
|
|
69
|
+
* REIMPLEMENTATION, adapted to the substrate this round moves reads onto:
|
|
70
|
+
* the config schema document (the one remaining filesystem read) still goes
|
|
71
|
+
* through the delivered `classifyEntry`/`readRegularFileIfPresent` from
|
|
72
|
+
* `src/task.ts`; every git-object read goes through `readGitBlob`/
|
|
73
|
+
* `gitObjectType`, this module's ONE answer to "may this git path be
|
|
74
|
+
* treated as file content", which establishes the object's TYPE (blob,
|
|
75
|
+
* tree, commit, or missing) before ever treating its output as text, the
|
|
76
|
+
* same probe-then-open shape `classifyEntry` uses for the filesystem. The
|
|
77
|
+
* one-shot inventory (unrelated to any `--head`, a live report over the
|
|
78
|
+
* actual checkout) is UNCHANGED by this round and still walks the
|
|
79
|
+
* filesystem through `classifyEntry`, because that is genuinely what it
|
|
80
|
+
* examines.
|
|
81
|
+
*
|
|
82
|
+
* THE RECOGNIZED GRAMMAR (step 2), stated once here and nowhere else:
|
|
83
|
+
*
|
|
84
|
+
* path:LINE a single line
|
|
85
|
+
* path:START-END an inclusive line range
|
|
86
|
+
* (either form) + @sha256:<64 lowercase hex>
|
|
87
|
+
* content-hash suffix: the cited line(s),
|
|
88
|
+
* joined by "\n" with any trailing "\r"
|
|
89
|
+
* stripped per line and no trailing newline,
|
|
90
|
+
* must hash to the given digest
|
|
91
|
+
*
|
|
92
|
+
* `path` is one or more `[A-Za-z0-9_./-]` characters ending in a recognized
|
|
93
|
+
* extension (ts, tsx, js, mjs, cjs, sh, md, json, yaml, yml). The token
|
|
94
|
+
* boundary is Unicode-aware on BOTH sides: a match cannot start immediately
|
|
95
|
+
* after a letter (any script), digit, `_`, `.`, `/`, `:` or `\`, and cannot
|
|
96
|
+
* end immediately before anything other than whitespace, end of text, a
|
|
97
|
+
* closing bracket/quote, or a `.` not itself followed by a digit (CR-1023,
|
|
98
|
+
* CR-1024). Leading zeros in the line/range numbers are accepted and
|
|
99
|
+
* normalized by decimal parsing (`:007` means line 7); this is an
|
|
100
|
+
* intentional relaxation, not an oversight (CR-1025).
|
|
101
|
+
*
|
|
102
|
+
* SECOND CALL SITE (R-025), grammar and mechanism UNCHANGED by this round:
|
|
103
|
+
* a plan review invokes the SAME executable, `node src/gates/citations.ts
|
|
104
|
+
* --result <file> --evidence <dir> --base <ref> [--head <ref>]`. CR-1017's
|
|
105
|
+
* fix is exactly what makes this call site trustworthy: `--head` now
|
|
106
|
+
* selects the CONTENT judged, not only the file list.
|
|
107
|
+
*
|
|
108
|
+
* ESCALATED, NOT THIS PHASE'S TO FIX (arbitration, final section): whether
|
|
109
|
+
* a `required` gate that reaches `not-applicable` should fail the aggregate
|
|
110
|
+
* is an M2-wide policy question for M2-P9, not resolved here. A review
|
|
111
|
+
* citing only an external root (verifying nothing) reaches `not-applicable`
|
|
112
|
+
* rather than `red` for that same, already-escalated reason.
|
|
113
|
+
*
|
|
114
|
+
* CI PRECONDITIONS THIS GATE REQUIRES (delivery/STATE.md's CR-902
|
|
115
|
+
* carry-forward): `fetch-depth: 0` in the checkout step, so `base` and
|
|
116
|
+
* `head` are both fetchable commits, not shallow-clone-absent ones.
|
|
117
|
+
*/
|
|
118
|
+
export interface CitationRoot {
|
|
119
|
+
name: string;
|
|
120
|
+
description?: string;
|
|
121
|
+
/** Explicit path globs. Segments separated by "/"; "*" matches within one
|
|
122
|
+
* segment, "**" matches zero or more whole segments. No other wildcard. */
|
|
123
|
+
match: string[];
|
|
124
|
+
}
|
|
125
|
+
export interface CitationConfig {
|
|
126
|
+
version: number;
|
|
127
|
+
/** Local roots: this checkout. */
|
|
128
|
+
roots: CitationRoot[];
|
|
129
|
+
/** Roots naming a repository this checkout does not contain. */
|
|
130
|
+
externalRoots: CitationRoot[];
|
|
131
|
+
/** Path globs identifying the configured document set (M2-D-10: diff-scoped
|
|
132
|
+
* at gate run time; walked in full only by the one-shot inventory). */
|
|
133
|
+
documents: string[];
|
|
134
|
+
/** The subset of `documents` in which zero SUBSTANTIVE citations is red
|
|
135
|
+
* (M2R-014's narrowed vacuous guard; CR-1020: substantive excludes quoted
|
|
136
|
+
* tokens and a citation to the document's own path). */
|
|
137
|
+
citationRequired: string[];
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* THE ONE COMMITTED CONFIGURATION (step 2; CR-1022 fix round).
|
|
141
|
+
*
|
|
142
|
+
* `roots[0].match` no longer includes `bin/**`. It used to, and `bin/fm-
|
|
143
|
+
* lock.sh` matched BOTH that pattern and the external `firstmate` root's
|
|
144
|
+
* `bin/fm-*.sh`; the two-root match was resolved correctly only because the
|
|
145
|
+
* code checked external roots before local ones, an implicit, undeclared
|
|
146
|
+
* precedence the hazard review named as fragile (CR-1022). The local
|
|
147
|
+
* pattern is narrowed to `bin/*.ts`, the actual files this checkout ships
|
|
148
|
+
* in `bin/` (today, `bin/tiphys.ts`), which shares no path with any
|
|
149
|
+
* `externalRoots` glob. The two root lists are therefore DISJOINT by
|
|
150
|
+
* construction, and `classifyPathAgainstRoots` needs no precedence rule at
|
|
151
|
+
* all: it checks every root and refuses ambiguity outright (CR-1022).
|
|
152
|
+
*
|
|
153
|
+
* Orchestrator decision (2026-08-07, under DR-0015; the owner delegated this
|
|
154
|
+
* scope call and is not an approval step in execution; reversible, owner may
|
|
155
|
+
* override): the gate governs FORWARD-CLAIMING delivery docs, NOT the
|
|
156
|
+
* historical delivery RECORD. Rationale recorded in
|
|
157
|
+
* delivery/work-history/m2-citations-scope.md. The `delivery/review/` and
|
|
158
|
+
* `delivery/work-history/` trees are records of what was examined at the
|
|
159
|
+
* time they were written; their `path:line` refs were valid when authored
|
|
160
|
+
* and drift as the code moves. Once the exit harness runs the full gate set
|
|
161
|
+
* on every doc PR, requiring a record's citations to still RESOLVE at head
|
|
162
|
+
* is the wrong policy: it re-litigates settled history against current code.
|
|
163
|
+
* So both trees are removed from `documents`, and review from
|
|
164
|
+
* `citationRequired`. The docs whose claims MUST hold against current code
|
|
165
|
+
* stay gated: the `delivery/plan/`, `delivery/verification/`,
|
|
166
|
+
* `delivery/decisions/`, `delivery/requirements/` trees and `delivery/STATE.md`
|
|
167
|
+
* are documents; the `delivery/plan/` and `delivery/verification/` trees are
|
|
168
|
+
* citationRequired. Anti-fabrication is preserved on every forward-claiming
|
|
169
|
+
* doc; the drift of the historical record is no longer a gate failure.
|
|
170
|
+
*/
|
|
171
|
+
export declare const DEFAULT_CITATION_CONFIG: CitationConfig;
|
|
172
|
+
export declare function citationConfigSchema(): SchemaDocument;
|
|
173
|
+
export declare function citationConfigSchemaPath(): string;
|
|
174
|
+
export declare function validateCitationConfigDocument(document: unknown): string[];
|
|
175
|
+
export interface AmbiguousGlob {
|
|
176
|
+
glob: string;
|
|
177
|
+
roots: string[];
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Config-load-time check: the identical glob STRING declared under more
|
|
181
|
+
* than one root. This is separate from, and does not replace,
|
|
182
|
+
* `classifyPathAgainstRoots`'s per-citation check (CR-1022): this one
|
|
183
|
+
* answers "did the config author write the same glob twice", which is
|
|
184
|
+
* decidable from the config alone; that one answers "does THIS concrete
|
|
185
|
+
* path match glob patterns from more than one root", which needs the
|
|
186
|
+
* concrete string and cannot be answered from the config in isolation.
|
|
187
|
+
*/
|
|
188
|
+
export declare function findAmbiguousGlobs(config: CitationConfig): AmbiguousGlob[];
|
|
189
|
+
export declare function findOrphanCitationRequired(config: CitationConfig): string[];
|
|
190
|
+
export declare function matchesGlob(pattern: string, path: string): boolean;
|
|
191
|
+
export declare function matchesAny(globs: string[], path: string): boolean;
|
|
192
|
+
export type RootClassification = {
|
|
193
|
+
kind: "external";
|
|
194
|
+
root: string;
|
|
195
|
+
} | {
|
|
196
|
+
kind: "local";
|
|
197
|
+
root: string;
|
|
198
|
+
} | {
|
|
199
|
+
kind: "unmatched";
|
|
200
|
+
} | {
|
|
201
|
+
kind: "ambiguous";
|
|
202
|
+
roots: string[];
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* Checks EVERY declared root (both lists, in full) rather than returning on
|
|
206
|
+
* the first match (CR-1022's named defect). A path matching exactly one
|
|
207
|
+
* root, of either kind, resolves to that root. A path matching two or more
|
|
208
|
+
* roots is `ambiguous`, named with every matching root, and is never
|
|
209
|
+
* guessed by declaration order. The shipped `DEFAULT_CITATION_CONFIG` has
|
|
210
|
+
* no overlap between its local and external match lists (see that
|
|
211
|
+
* constant's own doc comment), so this can only fire on a genuine
|
|
212
|
+
* configuration mistake, not on ordinary use.
|
|
213
|
+
*/
|
|
214
|
+
export declare function classifyPathAgainstRoots(config: CitationConfig, path: string): RootClassification;
|
|
215
|
+
export interface CitationToken {
|
|
216
|
+
raw: string;
|
|
217
|
+
path: string;
|
|
218
|
+
startLine: number;
|
|
219
|
+
endLine: number;
|
|
220
|
+
/** Set only when a `@sha256:` suffix was present AND valid (64 lowercase hex). */
|
|
221
|
+
hash?: string;
|
|
222
|
+
/** True when a `@sha256:` suffix was attempted but did not validate (CR-1019). */
|
|
223
|
+
hashMalformed: boolean;
|
|
224
|
+
/** Non-undefined when unsafe text immediately follows the recognized token
|
|
225
|
+
* with no separating whitespace (CR-1024): the citation is malformed, not
|
|
226
|
+
* silently narrowed. */
|
|
227
|
+
trailingMalformed?: string;
|
|
228
|
+
offset: number;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* THE ONE GRAMMAR SCAN. Quoted-range exclusion (M2-D-22) and hunk-scoping
|
|
232
|
+
* (M2-D-21) are separate, composable passes over this function's output,
|
|
233
|
+
* not a second implementation of citation recognition.
|
|
234
|
+
*/
|
|
235
|
+
export declare function extractCitations(text: string): CitationToken[];
|
|
236
|
+
/**
|
|
237
|
+
* Lines of a file body, 1-indexed by position in the returned array. A
|
|
238
|
+
* single trailing newline is not counted as an extra blank line; a
|
|
239
|
+
* completely empty body has zero lines.
|
|
240
|
+
*/
|
|
241
|
+
export declare function splitLines(body: string): string[];
|
|
242
|
+
/**
|
|
243
|
+
* Character ranges (half-open `[start, end)`, sorted) that are QUOTED
|
|
244
|
+
* rather than MADE: fenced code blocks (opened and closed by a line whose
|
|
245
|
+
* first non-space run is 3+ of the same fence character, `` ` `` or `~`,
|
|
246
|
+
* matched by CommonMark's own rule of "same character, at least as long
|
|
247
|
+
* to close") and inline code spans (a run of one or more backticks,
|
|
248
|
+
* matched by the NEXT run of the SAME length on the same line). This is a
|
|
249
|
+
* deliberately LINE-ORIENTED simplification: it does not handle an inline
|
|
250
|
+
* span whose content itself contains a shorter backtick run (needing a
|
|
251
|
+
* longer delimiter per CommonMark), which does not occur anywhere in this
|
|
252
|
+
* repository's corpus (verified by the one-shot inventory finding no
|
|
253
|
+
* citation whose surrounding text uses that construct).
|
|
254
|
+
*/
|
|
255
|
+
export declare function computeQuotedRanges(body: string): Array<[number, number]>;
|
|
256
|
+
export type TouchedLines = {
|
|
257
|
+
kind: "all";
|
|
258
|
+
} | {
|
|
259
|
+
kind: "ranges";
|
|
260
|
+
ranges: Array<[number, number]>;
|
|
261
|
+
};
|
|
262
|
+
export type GitObjectRead = {
|
|
263
|
+
kind: "blob";
|
|
264
|
+
body: string;
|
|
265
|
+
} | {
|
|
266
|
+
kind: "missing";
|
|
267
|
+
} | {
|
|
268
|
+
kind: "irregular";
|
|
269
|
+
reason: string;
|
|
270
|
+
} | {
|
|
271
|
+
kind: "error";
|
|
272
|
+
reason: string;
|
|
273
|
+
};
|
|
274
|
+
/**
|
|
275
|
+
* THE ONE ANSWER to "may this git path be treated as file content"
|
|
276
|
+
* (M2-C-6, adapted to the git-object substrate CR-1017 moves reads onto).
|
|
277
|
+
* `git cat-file -t <rev>:<path>` establishes the object's TYPE before its
|
|
278
|
+
* content is ever read, the same probe-then-open shape `classifyEntry`
|
|
279
|
+
* uses for the filesystem: `blob` is the only type this function reads;
|
|
280
|
+
* `tree` (a directory) and `commit` (a submodule gitlink) are `irregular`,
|
|
281
|
+
* named with the observed type, never opened as if they were text; a path
|
|
282
|
+
* git reports as not existing at this revision is `missing`, which is not
|
|
283
|
+
* an error (the normal shape of "the diff added a new document," or of a
|
|
284
|
+
* dangling citation).
|
|
285
|
+
*
|
|
286
|
+
* VERIFIED, not assumed (T-006): `git cat-file -t HEAD:src/../../etc/passwd`
|
|
287
|
+
* and `git cat-file -t HEAD:src/../delivery/STATE.md` (a traversal that
|
|
288
|
+
* WOULD land on a real in-repo file if resolved as a filesystem path) both
|
|
289
|
+
* report "does not exist", because git's tree lookup treats the path
|
|
290
|
+
* segment-by-segment against actual tree entries and no tree can contain a
|
|
291
|
+
* `..` entry; there is no filesystem-style traversal to close, because the
|
|
292
|
+
* data structure this function reads from has no parent pointer to walk
|
|
293
|
+
* (CR-1018, closed structurally rather than by a denylist).
|
|
294
|
+
*/
|
|
295
|
+
export declare function gitObjectType(cwd: string, rev: string, path: string): {
|
|
296
|
+
kind: "type";
|
|
297
|
+
type: string;
|
|
298
|
+
} | {
|
|
299
|
+
kind: "missing";
|
|
300
|
+
} | {
|
|
301
|
+
kind: "error";
|
|
302
|
+
reason: string;
|
|
303
|
+
};
|
|
304
|
+
export declare function readGitBlob(cwd: string, rev: string, path: string): GitObjectRead;
|
|
305
|
+
export type CitationResolution = {
|
|
306
|
+
kind: "resolved";
|
|
307
|
+
detail: string;
|
|
308
|
+
} | {
|
|
309
|
+
kind: "unresolved";
|
|
310
|
+
detail: string;
|
|
311
|
+
} | {
|
|
312
|
+
kind: "unverifiable-external";
|
|
313
|
+
root: string;
|
|
314
|
+
detail: string;
|
|
315
|
+
}
|
|
316
|
+
/** M2-C-6: the cited target is present and is not a git blob / not a
|
|
317
|
+
* regular file, depending on which read strategy is in use. */
|
|
318
|
+
| {
|
|
319
|
+
kind: "read-error";
|
|
320
|
+
path: string;
|
|
321
|
+
reason: string;
|
|
322
|
+
};
|
|
323
|
+
/** How to fetch a cited target's content: git-object (the registered gate,
|
|
324
|
+
* CR-1017) or filesystem (the one-shot inventory, which examines the live
|
|
325
|
+
* checkout by design). Parameterizing the read is what keeps resolution ONE
|
|
326
|
+
* implementation across both call sites (never a second one). */
|
|
327
|
+
export type TargetReader = (path: string) => GitObjectRead;
|
|
328
|
+
export declare function gitTargetReader(cwd: string, rev: string): TargetReader;
|
|
329
|
+
export declare function filesystemTargetReader(repoRoot: string): TargetReader;
|
|
330
|
+
export declare function resolveCitation(config: CitationConfig, token: CitationToken, readTarget: TargetReader): CitationResolution;
|
|
331
|
+
export interface DocumentAnalysis {
|
|
332
|
+
/** Non-quoted, non-self tokens: what the vacuous guard asks about,
|
|
333
|
+
* whole-document, never hunk-scoped (arbitration M2-D-21). */
|
|
334
|
+
substantiveCount: number;
|
|
335
|
+
/** Every non-quoted token, self included (for reporting). */
|
|
336
|
+
totalNonQuoted: number;
|
|
337
|
+
resolved: number;
|
|
338
|
+
/** Resolved, but the citation's path equals the citing document's own
|
|
339
|
+
* path (CR-1020): correctness is still checked, but it does not count
|
|
340
|
+
* toward `resolved` units or the vacuous guard. */
|
|
341
|
+
selfResolved: number;
|
|
342
|
+
unverifiableExternal: number;
|
|
343
|
+
unresolvedDetails: string[];
|
|
344
|
+
}
|
|
345
|
+
export type DocumentAnalysisOutcome = {
|
|
346
|
+
kind: "analyzed";
|
|
347
|
+
analysis: DocumentAnalysis;
|
|
348
|
+
} | {
|
|
349
|
+
kind: "read-error";
|
|
350
|
+
path: string;
|
|
351
|
+
reason: string;
|
|
352
|
+
};
|
|
353
|
+
/**
|
|
354
|
+
* THE ONE COUNTING PASS. `touched` selects which tokens are actually
|
|
355
|
+
* RESOLVED (M2-D-21: hunk ranges for the registered gate, `{kind:"all"}`
|
|
356
|
+
* for the one-shot inventory, which has no diff to scope by). The vacuous
|
|
357
|
+
* `substantiveCount` is NEVER hunk-scoped, per the arbitration: a document
|
|
358
|
+
* makes at least one citation, or it does not, independent of what this
|
|
359
|
+
* particular diff touched.
|
|
360
|
+
*/
|
|
361
|
+
export declare function analyzeDocument(config: CitationConfig, body: string, relativePath: string, touched: TouchedLines, readTarget: TargetReader): DocumentAnalysisOutcome;
|
|
362
|
+
export declare function listConfiguredDocuments(repoRoot: string, config?: CitationConfig, startDir?: string): string[];
|
|
363
|
+
export interface InventoryRow {
|
|
364
|
+
path: string;
|
|
365
|
+
/** resolved + selfResolved + unresolved + unverifiableExternal. */
|
|
366
|
+
total: number;
|
|
367
|
+
/** Includes self-resolved citations (folded in for this report; the
|
|
368
|
+
* registered gate's `units` excludes them, see `runCitationsGate`). */
|
|
369
|
+
resolved: number;
|
|
370
|
+
unresolved: number;
|
|
371
|
+
unverifiableExternal: number;
|
|
372
|
+
}
|
|
373
|
+
export declare function inventoryDeliveryTree(repoRoot: string, config?: CitationConfig, startDir?: string): InventoryRow[];
|
|
374
|
+
export interface CitationsGateOptions {
|
|
375
|
+
cwd: string;
|
|
376
|
+
base?: string;
|
|
377
|
+
head?: string;
|
|
378
|
+
config?: CitationConfig;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* The kernel gate entry. Lints only citations ADDED or MODIFIED in the diff
|
|
382
|
+
* `base...head` (M2-D-21), reading every byte of content -- the document
|
|
383
|
+
* under lint AND every cited local target -- from the git object at `head`
|
|
384
|
+
* (CR-1017), never from `cwd`'s working tree.
|
|
385
|
+
*
|
|
386
|
+
* `--base` absent is `error`, never `not-applicable` (M2-C-3), checked
|
|
387
|
+
* independently of the runner's own `diff-touches` precondition because
|
|
388
|
+
* R-025's second call site invokes this function directly.
|
|
389
|
+
*
|
|
390
|
+
* THE VACUOUS GUARD (M2R-014, M2-D-21, CR-1020): a `citationRequired`
|
|
391
|
+
* document with zero SUBSTANTIVE citation tokens anywhere in the WHOLE
|
|
392
|
+
* document (not quoted, not a citation to its own path) is `red`. This is
|
|
393
|
+
* intentionally NOT hunk-scoped: the arbitration is explicit that "the
|
|
394
|
+
* document as a whole makes at least one citation" is the question, so a
|
|
395
|
+
* PR that edits one unrelated line of an otherwise-empty required document
|
|
396
|
+
* still reds on it, and a PR that adds the document's first real citation
|
|
397
|
+
* still turns it green.
|
|
398
|
+
*
|
|
399
|
+
* NOT-APPLICABLE WHEN NOTHING SUBSTANTIVE WAS VERIFIED: M2-C-2 forbids a
|
|
400
|
+
* green record with zero units, so a changed set whose only in-scope
|
|
401
|
+
* citations are quoted, self-referential, or external resolves
|
|
402
|
+
* `not-applicable` rather than a fabricated green. Because `citations` is
|
|
403
|
+
* registered `required`, this still fails the aggregate; that is the
|
|
404
|
+
* escalated, M2-wide policy question the arbitration assigns to M2-P9, not
|
|
405
|
+
* this gate.
|
|
406
|
+
*/
|
|
407
|
+
export declare function runCitationsGate(options: CitationsGateOptions): GateResultFields;
|
|
408
|
+
export declare function main(argv: string[]): number;
|