instar 1.3.1190 → 1.3.1192
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/dist/core/InputGuard.d.ts +9 -0
- package/dist/core/InputGuard.d.ts.map +1 -1
- package/dist/core/InputGuard.js +29 -1
- package/dist/core/InputGuard.js.map +1 -1
- package/dist/core/ResumeValidator.d.ts +17 -0
- package/dist/core/ResumeValidator.d.ts.map +1 -1
- package/dist/core/ResumeValidator.js +38 -2
- package/dist/core/ResumeValidator.js.map +1 -1
- package/dist/core/StandardsRegistryParser.d.ts +1 -1
- package/dist/core/StandardsRegistryParser.d.ts.map +1 -1
- package/dist/core/StandardsRegistryParser.js +14 -0
- package/dist/core/StandardsRegistryParser.js.map +1 -1
- package/dist/core/boundedInput.d.ts +72 -0
- package/dist/core/boundedInput.d.ts.map +1 -0
- package/dist/core/boundedInput.js +163 -0
- package/dist/core/boundedInput.js.map +1 -0
- package/dist/core/crossModelReviewer.d.ts +135 -9
- package/dist/core/crossModelReviewer.d.ts.map +1 -1
- package/dist/core/crossModelReviewer.js +202 -15
- package/dist/core/crossModelReviewer.js.map +1 -1
- package/dist/data/standards-guard-index.json +74 -2
- package/dist/data/standards-guard-index.meta.json +3 -3
- package/dist/data/standards-registry.md +29 -5
- package/dist/data/standards-registry.meta.json +3 -3
- package/dist/monitoring/PromptGate.d.ts.map +1 -1
- package/dist/monitoring/PromptGate.js +20 -2
- package/dist/monitoring/PromptGate.js.map +1 -1
- package/dist/threadline/PipeSessionSpawner.d.ts.map +1 -1
- package/dist/threadline/PipeSessionSpawner.js +47 -3
- package/dist/threadline/PipeSessionSpawner.js.map +1 -1
- package/package.json +2 -2
- package/scripts/lint-bounded-judgment-input.mjs +359 -0
- package/scripts/lint-machine-local-justification.js +286 -8
- package/scripts/standards-coverage.mjs +18 -0
- package/skills/spec-converge/SKILL.md +3 -1
- package/skills/spec-converge/scripts/cross-model-review.mjs +15 -9
- package/src/data/builtin-manifest.json +2 -2
- package/src/data/standards-guard-index.json +74 -2
- package/src/data/standards-guard-index.meta.json +3 -3
- package/src/data/standards-registry.md +29 -5
- package/src/data/standards-registry.meta.json +3 -3
- package/upgrades/1.3.1191.md +32 -0
- package/upgrades/1.3.1192.md +37 -0
- package/upgrades/ratify-multi-machine-amendments-2026-08-22.eli16.md +54 -0
- package/upgrades/side-effects/ratify-multi-machine-amendments-2026-08-22.md +91 -0
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* crossModelReviewer — Step B of the tiered development process.
|
|
3
3
|
*
|
|
4
|
+
* Governed by: *Never Silently Cut the Data a Decision Depends On*
|
|
5
|
+
* (docs/STANDARDS-REGISTRY.md). This file carries the case that earned that article:
|
|
6
|
+
* `CONTEXT_BUDGET_BYTES` (derived from the transport, derivation recorded in place),
|
|
7
|
+
* `LOAD_BEARING_CONTEXT_SUBSTRINGS` (the context a review is not valid without), and the
|
|
8
|
+
* `context-incomplete` REFUSAL in `runCrossModelReview` — which exists because this file's
|
|
9
|
+
* disclosure layer was already correct and complete, and six rounds of review were conducted on a
|
|
10
|
+
* fabricated view of the world anyway. Disclosure informs a reader who reads; refusal does not
|
|
11
|
+
* depend on anyone reading.
|
|
12
|
+
*
|
|
4
13
|
* Re-platforms the `/spec-converge` external "cross-model" reviewer onto the
|
|
5
14
|
* agent's own installed `codex` CLI. The external pass that the skill used to
|
|
6
15
|
* describe as running "via the /crossreview pattern" (a never-built
|
|
@@ -66,12 +75,51 @@ export declare const REVIEWER_TIMEOUT_MAX_MS = 900000;
|
|
|
66
75
|
* so referenced context MUST be inlined; this bounds the prompt size (spec §2).
|
|
67
76
|
* The spec is always included in full; referenced context fills the remainder
|
|
68
77
|
* and is truncated (with a loud note) if it overflows.
|
|
78
|
+
*
|
|
79
|
+
* ── DERIVATION (governed by *Never Silently Cut the Data a Decision Depends On*) ─────────────
|
|
80
|
+
* This number is DERIVED from the binding constraint on the consumer, and the
|
|
81
|
+
* derivation is recorded here so it can be re-checked rather than inherited.
|
|
82
|
+
* Re-derive it whenever the transport or the supported reviewer families
|
|
83
|
+
* change; do not tune it by feel.
|
|
84
|
+
*
|
|
85
|
+
* Candidate constraint 1 — the model's context window. Every reviewer
|
|
86
|
+
* family this registry supports at the `capable` tier accepts >= 200K
|
|
87
|
+
* input tokens, i.e. roughly 800 KB of English markdown at ~4 chars/token.
|
|
88
|
+
* NOT binding.
|
|
89
|
+
*
|
|
90
|
+
* Candidate constraint 2 — the TRANSPORT. The exec-json path hands the
|
|
91
|
+
* prompt to the CLI on stdin (unbounded). But `intelligence.codexExecJson:
|
|
92
|
+
* false` is a documented rollback lever, and the plain path passes the
|
|
93
|
+
* prompt as a single argv element, which must fit inside the host's
|
|
94
|
+
* ARG_MAX *together with the whole environment* — 1 MiB on macOS, 2 MiB on
|
|
95
|
+
* typical Linux. BINDING, and binding on the smaller host.
|
|
96
|
+
*
|
|
97
|
+
* So the budget is set from the transport, at a quarter of the smaller
|
|
98
|
+
* ARG_MAX: 256 KiB. That leaves three quarters of ARG_MAX for the
|
|
99
|
+
* environment and the rest of the command line on the worst-case host, and
|
|
100
|
+
* is ~64K tokens — comfortably inside every supported model's window.
|
|
101
|
+
*
|
|
102
|
+
* WHAT THIS NUMBER DOES NOT PROMISE. It is a transport ceiling, not a
|
|
103
|
+
* guarantee that any given spec plus its parent design will fit. When the
|
|
104
|
+
* load-bearing context does NOT fit, the review does not quietly proceed on
|
|
105
|
+
* a partial view: `assembleReviewerPrompt` records the omission and
|
|
106
|
+
* `runCrossModelReview` returns `degraded` rather than a verdict. See
|
|
107
|
+
* `LOAD_BEARING_CONTEXT_SUBSTRINGS`.
|
|
108
|
+
*
|
|
109
|
+
* HISTORY. This was 60 KB from the spec's first draft until 2026-08-22, a
|
|
110
|
+
* number with no recorded derivation. At that size the budget was smaller
|
|
111
|
+
* than a single ordinary spec, so referenced context was dropped in FULL on
|
|
112
|
+
* every round of every review — the truncation note read "truncated to fit"
|
|
113
|
+
* while describing 100% loss. Six rounds of cross-model review on
|
|
114
|
+
* `placement-real-capacity-scoring` were conducted without the reviewers
|
|
115
|
+
* ever seeing the parent design, the standards registry, or the lessons doc.
|
|
116
|
+
* The disclosure machinery worked correctly throughout; nothing refused.
|
|
69
117
|
*/
|
|
70
118
|
export declare const CONTEXT_BUDGET_BYTES: number;
|
|
71
119
|
/**
|
|
72
120
|
* Deterministic priority ordering for referenced context (spec §2, F4).
|
|
73
121
|
*
|
|
74
|
-
* When the
|
|
122
|
+
* When the budget can't hold every referenced doc, truncation MUST be
|
|
75
123
|
* deterministic — the same spec + same docs always drop the same docs — so a
|
|
76
124
|
* review is reproducible and the "what got dropped" note is stable. The
|
|
77
125
|
* constitutional / lessons docs are the highest-value context for a reviewer
|
|
@@ -84,6 +132,40 @@ export declare const CONTEXT_BUDGET_BYTES: number;
|
|
|
84
132
|
* via a stable sort.
|
|
85
133
|
*/
|
|
86
134
|
export declare const CONTEXT_PRIORITY_SUBSTRINGS: readonly string[];
|
|
135
|
+
/**
|
|
136
|
+
* The subset of referenced context a cross-model review is NOT VALID WITHOUT
|
|
137
|
+
* (governed by *Never Silently Cut the Data a Decision Depends On*).
|
|
138
|
+
*
|
|
139
|
+
* The reviewer's job is to judge a spec against the design and the rules it is
|
|
140
|
+
* built on. A reviewer that received the spec but none of those documents can
|
|
141
|
+
* only check whether the spec agrees with ITSELF — a materially weaker check
|
|
142
|
+
* wearing the same name. So when a budget walk cannot admit one of these docs
|
|
143
|
+
* IN FULL, the honest outcome is not "a review with a caveat"; it is NOT A
|
|
144
|
+
* REVIEW, and `runCrossModelReview` degrades rather than returning a verdict.
|
|
145
|
+
*
|
|
146
|
+
* PARTIAL COUNTS AS OMITTED, deliberately. Half of the standards registry, cut
|
|
147
|
+
* at whatever byte the budget ran out on, is not the standards registry — the
|
|
148
|
+
* reviewer cannot know whether the clause that governs this spec was in the
|
|
149
|
+
* half it received. Treating a partial constitutional doc as "present" is the
|
|
150
|
+
* same substitution of a symbol for the state that this rule exists to stop.
|
|
151
|
+
*
|
|
152
|
+
* These coincide with `CONTEXT_PRIORITY_SUBSTRINGS` today, and that is not a
|
|
153
|
+
* coincidence — a doc is kept first BECAUSE the review is worthless without it.
|
|
154
|
+
* They are named separately because they answer different questions (what order
|
|
155
|
+
* do docs go in / what may a review proceed without), and a future doc could
|
|
156
|
+
* be worth prioritising without being load-bearing.
|
|
157
|
+
*
|
|
158
|
+
* SPELLED OUT RATHER THAN ALIASED, deliberately (independent review 2026-08-22,
|
|
159
|
+
* finding C8). This was `= CONTEXT_PRIORITY_SUBSTRINGS` — the SAME array object,
|
|
160
|
+
* which made the paragraph above false: with an alias, adding a doc to the
|
|
161
|
+
* priority list silently promotes it to a review-BLOCKER, and the divergence the
|
|
162
|
+
* comment reserves the right to have is unrepresentable. A list that claims to
|
|
163
|
+
* be separate must be separate; two lists that happen to agree are checked by
|
|
164
|
+
* `load-bearing docs are a subset of the priority order` in the unit tests.
|
|
165
|
+
*/
|
|
166
|
+
export declare const LOAD_BEARING_CONTEXT_SUBSTRINGS: readonly string[];
|
|
167
|
+
/** True when a context doc path is one the review is not valid without. */
|
|
168
|
+
export declare function isLoadBearingContext(docPath: string): boolean;
|
|
87
169
|
/**
|
|
88
170
|
* Order referenced context deterministically: constitutional/lessons docs
|
|
89
171
|
* first (per CONTEXT_PRIORITY_SUBSTRINGS), then the caller's spec-declared link
|
|
@@ -612,6 +694,35 @@ export interface AssembledPrompt {
|
|
|
612
694
|
truncated: boolean;
|
|
613
695
|
/** Byte size of the assembled prompt. */
|
|
614
696
|
bytes: number;
|
|
697
|
+
/**
|
|
698
|
+
* Repo-relative paths of LOAD-BEARING context docs
|
|
699
|
+
* (`LOAD_BEARING_CONTEXT_SUBSTRINGS`) that did not make it in whole — either
|
|
700
|
+
* cut mid-document or dropped entirely. Non-empty means the reviewer cannot
|
|
701
|
+
* do the job the review claims to do, and `runCrossModelReview` degrades
|
|
702
|
+
* instead of returning a verdict.
|
|
703
|
+
*
|
|
704
|
+
* Always present (empty when nothing load-bearing was lost) so a consumer
|
|
705
|
+
* that forgets to check reads `[]` rather than `undefined` — an absent field
|
|
706
|
+
* must never be mistakable for "nothing was lost".
|
|
707
|
+
*/
|
|
708
|
+
omittedLoadBearing: string[];
|
|
709
|
+
/**
|
|
710
|
+
* The subset of `omittedLoadBearing` that could NEVER have fitted — the doc's
|
|
711
|
+
* own byte size alone exceeds the WHOLE budget, so no spec is small enough to
|
|
712
|
+
* admit it and no amount of trimming elsewhere will ever change the outcome.
|
|
713
|
+
*
|
|
714
|
+
* Split out from `omittedLoadBearing` after the independent review of
|
|
715
|
+
* 2026-08-22 (finding C2). Both refuse, but they call for OPPOSITE actions and
|
|
716
|
+
* a single reason string sent the reader down the wrong one: an ordinary
|
|
717
|
+
* omission says *make the spec smaller*, while this says *stop passing this
|
|
718
|
+
* doc as raw context — nothing you do to the spec can help.* The live case is
|
|
719
|
+
* the standards registry, which is larger than the entire budget on its own:
|
|
720
|
+
* attaching it produced a refusal whose advice ("use a smaller spec") was
|
|
721
|
+
* unfollowable, which is a limit hiding behind its own polite notice — the
|
|
722
|
+
* exact defect *Never Silently Cut the Data a Decision Depends On* was earned
|
|
723
|
+
* from, reproduced by that article's own implementation.
|
|
724
|
+
*/
|
|
725
|
+
undeliverableLoadBearing: string[];
|
|
615
726
|
}
|
|
616
727
|
/**
|
|
617
728
|
* Assemble the cross-model reviewer prompt: the reviewer template (with
|
|
@@ -702,14 +813,6 @@ export declare function aggregateRoundOutcomes(rounds: ReviewerResult[], opts?:
|
|
|
702
813
|
* inc2 only ADDS the knob — it changes no family's default value.
|
|
703
814
|
*/
|
|
704
815
|
export declare function resolveReviewerTimeoutMs(config: ReviewerConfig | undefined, frameworkId: string): number;
|
|
705
|
-
/**
|
|
706
|
-
* The high-level entry the skill driver calls: detect, and if available run
|
|
707
|
-
* the first available framework's reviewer with the assembled prompt;
|
|
708
|
-
* otherwise return the `unavailable` flag. NEVER throws, NEVER blocks.
|
|
709
|
-
*
|
|
710
|
-
* `assembled` is produced by `assembleReviewerPrompt`. `detectInputs` and
|
|
711
|
-
* `providerOverride` exist for tests; production omits them.
|
|
712
|
-
*/
|
|
713
816
|
export declare function runCrossModelReview(args: {
|
|
714
817
|
assembled: AssembledPrompt;
|
|
715
818
|
timeoutMs?: number;
|
|
@@ -717,6 +820,29 @@ export declare function runCrossModelReview(args: {
|
|
|
717
820
|
providerOverride?: ReviewerInvokeArgs['providerOverride'];
|
|
718
821
|
/** Agent config for the config-gated claude clean-door family (§1.5). */
|
|
719
822
|
config?: ReviewerConfig;
|
|
823
|
+
/**
|
|
824
|
+
* Review through THIS family specifically, instead of the first framework
|
|
825
|
+
* detection happens to name.
|
|
826
|
+
*
|
|
827
|
+
* Added 2026-08-22 after the independent review's finding C1: the per-family
|
|
828
|
+
* path existed only in the skill driver, which called `family.review(...)`
|
|
829
|
+
* DIRECTLY — bypassing this function and therefore bypassing the load-bearing
|
|
830
|
+
* context refusal below. `ReviewerInvokeArgs` carries only `promptText`, so
|
|
831
|
+
* that path could not have refused even if it wanted to: the omission signal
|
|
832
|
+
* does not reach it. Since `SKILL.md` instructs `--family` on every call, the
|
|
833
|
+
* refusal was live on a path nothing used and absent from the path everything
|
|
834
|
+
* used — dead code wearing a passing test (the test called this function).
|
|
835
|
+
*
|
|
836
|
+
* The fix is one chokepoint rather than a check copied into four family
|
|
837
|
+
* entries (*Structure beats Willpower*): every review, per-family or not,
|
|
838
|
+
* enters here and meets the same guard.
|
|
839
|
+
*/
|
|
840
|
+
family?: string;
|
|
841
|
+
/**
|
|
842
|
+
* A detection the caller already computed (the driver detects before
|
|
843
|
+
* assembling). Skips re-probing the host; MUST still be `available`.
|
|
844
|
+
*/
|
|
845
|
+
detectionOverride?: CrossModelDetectionResult;
|
|
720
846
|
}): Promise<ReviewerResult>;
|
|
721
847
|
/**
|
|
722
848
|
* Hash the spec's REVIEWABLE body (Piece 3 delta-gating): sha256 hex of the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crossModelReviewer.d.ts","sourceRoot":"","sources":["../../src/core/crossModelReviewer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"crossModelReviewer.d.ts","sourceRoot":"","sources":["../../src/core/crossModelReviewer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* crossModelReviewer — Step B of the tiered development process.
|
|
3
3
|
*
|
|
4
|
+
* Governed by: *Never Silently Cut the Data a Decision Depends On*
|
|
5
|
+
* (docs/STANDARDS-REGISTRY.md). This file carries the case that earned that article:
|
|
6
|
+
* `CONTEXT_BUDGET_BYTES` (derived from the transport, derivation recorded in place),
|
|
7
|
+
* `LOAD_BEARING_CONTEXT_SUBSTRINGS` (the context a review is not valid without), and the
|
|
8
|
+
* `context-incomplete` REFUSAL in `runCrossModelReview` — which exists because this file's
|
|
9
|
+
* disclosure layer was already correct and complete, and six rounds of review were conducted on a
|
|
10
|
+
* fabricated view of the world anyway. Disclosure informs a reader who reads; refusal does not
|
|
11
|
+
* depend on anyone reading.
|
|
12
|
+
*
|
|
4
13
|
* Re-platforms the `/spec-converge` external "cross-model" reviewer onto the
|
|
5
14
|
* agent's own installed `codex` CLI. The external pass that the skill used to
|
|
6
15
|
* describe as running "via the /crossreview pattern" (a never-built
|
|
@@ -82,12 +91,51 @@ export const REVIEWER_TIMEOUT_MAX_MS = 900_000;
|
|
|
82
91
|
* so referenced context MUST be inlined; this bounds the prompt size (spec §2).
|
|
83
92
|
* The spec is always included in full; referenced context fills the remainder
|
|
84
93
|
* and is truncated (with a loud note) if it overflows.
|
|
94
|
+
*
|
|
95
|
+
* ── DERIVATION (governed by *Never Silently Cut the Data a Decision Depends On*) ─────────────
|
|
96
|
+
* This number is DERIVED from the binding constraint on the consumer, and the
|
|
97
|
+
* derivation is recorded here so it can be re-checked rather than inherited.
|
|
98
|
+
* Re-derive it whenever the transport or the supported reviewer families
|
|
99
|
+
* change; do not tune it by feel.
|
|
100
|
+
*
|
|
101
|
+
* Candidate constraint 1 — the model's context window. Every reviewer
|
|
102
|
+
* family this registry supports at the `capable` tier accepts >= 200K
|
|
103
|
+
* input tokens, i.e. roughly 800 KB of English markdown at ~4 chars/token.
|
|
104
|
+
* NOT binding.
|
|
105
|
+
*
|
|
106
|
+
* Candidate constraint 2 — the TRANSPORT. The exec-json path hands the
|
|
107
|
+
* prompt to the CLI on stdin (unbounded). But `intelligence.codexExecJson:
|
|
108
|
+
* false` is a documented rollback lever, and the plain path passes the
|
|
109
|
+
* prompt as a single argv element, which must fit inside the host's
|
|
110
|
+
* ARG_MAX *together with the whole environment* — 1 MiB on macOS, 2 MiB on
|
|
111
|
+
* typical Linux. BINDING, and binding on the smaller host.
|
|
112
|
+
*
|
|
113
|
+
* So the budget is set from the transport, at a quarter of the smaller
|
|
114
|
+
* ARG_MAX: 256 KiB. That leaves three quarters of ARG_MAX for the
|
|
115
|
+
* environment and the rest of the command line on the worst-case host, and
|
|
116
|
+
* is ~64K tokens — comfortably inside every supported model's window.
|
|
117
|
+
*
|
|
118
|
+
* WHAT THIS NUMBER DOES NOT PROMISE. It is a transport ceiling, not a
|
|
119
|
+
* guarantee that any given spec plus its parent design will fit. When the
|
|
120
|
+
* load-bearing context does NOT fit, the review does not quietly proceed on
|
|
121
|
+
* a partial view: `assembleReviewerPrompt` records the omission and
|
|
122
|
+
* `runCrossModelReview` returns `degraded` rather than a verdict. See
|
|
123
|
+
* `LOAD_BEARING_CONTEXT_SUBSTRINGS`.
|
|
124
|
+
*
|
|
125
|
+
* HISTORY. This was 60 KB from the spec's first draft until 2026-08-22, a
|
|
126
|
+
* number with no recorded derivation. At that size the budget was smaller
|
|
127
|
+
* than a single ordinary spec, so referenced context was dropped in FULL on
|
|
128
|
+
* every round of every review — the truncation note read "truncated to fit"
|
|
129
|
+
* while describing 100% loss. Six rounds of cross-model review on
|
|
130
|
+
* `placement-real-capacity-scoring` were conducted without the reviewers
|
|
131
|
+
* ever seeing the parent design, the standards registry, or the lessons doc.
|
|
132
|
+
* The disclosure machinery worked correctly throughout; nothing refused.
|
|
85
133
|
*/
|
|
86
|
-
export const CONTEXT_BUDGET_BYTES =
|
|
134
|
+
export const CONTEXT_BUDGET_BYTES = 256 * 1024;
|
|
87
135
|
/**
|
|
88
136
|
* Deterministic priority ordering for referenced context (spec §2, F4).
|
|
89
137
|
*
|
|
90
|
-
* When the
|
|
138
|
+
* When the budget can't hold every referenced doc, truncation MUST be
|
|
91
139
|
* deterministic — the same spec + same docs always drop the same docs — so a
|
|
92
140
|
* review is reproducible and the "what got dropped" note is stable. The
|
|
93
141
|
* constitutional / lessons docs are the highest-value context for a reviewer
|
|
@@ -105,6 +153,48 @@ export const CONTEXT_PRIORITY_SUBSTRINGS = [
|
|
|
105
153
|
'STANDARDS-REGISTRY',
|
|
106
154
|
'integrated-being',
|
|
107
155
|
];
|
|
156
|
+
/**
|
|
157
|
+
* The subset of referenced context a cross-model review is NOT VALID WITHOUT
|
|
158
|
+
* (governed by *Never Silently Cut the Data a Decision Depends On*).
|
|
159
|
+
*
|
|
160
|
+
* The reviewer's job is to judge a spec against the design and the rules it is
|
|
161
|
+
* built on. A reviewer that received the spec but none of those documents can
|
|
162
|
+
* only check whether the spec agrees with ITSELF — a materially weaker check
|
|
163
|
+
* wearing the same name. So when a budget walk cannot admit one of these docs
|
|
164
|
+
* IN FULL, the honest outcome is not "a review with a caveat"; it is NOT A
|
|
165
|
+
* REVIEW, and `runCrossModelReview` degrades rather than returning a verdict.
|
|
166
|
+
*
|
|
167
|
+
* PARTIAL COUNTS AS OMITTED, deliberately. Half of the standards registry, cut
|
|
168
|
+
* at whatever byte the budget ran out on, is not the standards registry — the
|
|
169
|
+
* reviewer cannot know whether the clause that governs this spec was in the
|
|
170
|
+
* half it received. Treating a partial constitutional doc as "present" is the
|
|
171
|
+
* same substitution of a symbol for the state that this rule exists to stop.
|
|
172
|
+
*
|
|
173
|
+
* These coincide with `CONTEXT_PRIORITY_SUBSTRINGS` today, and that is not a
|
|
174
|
+
* coincidence — a doc is kept first BECAUSE the review is worthless without it.
|
|
175
|
+
* They are named separately because they answer different questions (what order
|
|
176
|
+
* do docs go in / what may a review proceed without), and a future doc could
|
|
177
|
+
* be worth prioritising without being load-bearing.
|
|
178
|
+
*
|
|
179
|
+
* SPELLED OUT RATHER THAN ALIASED, deliberately (independent review 2026-08-22,
|
|
180
|
+
* finding C8). This was `= CONTEXT_PRIORITY_SUBSTRINGS` — the SAME array object,
|
|
181
|
+
* which made the paragraph above false: with an alias, adding a doc to the
|
|
182
|
+
* priority list silently promotes it to a review-BLOCKER, and the divergence the
|
|
183
|
+
* comment reserves the right to have is unrepresentable. A list that claims to
|
|
184
|
+
* be separate must be separate; two lists that happen to agree are checked by
|
|
185
|
+
* `load-bearing docs are a subset of the priority order` in the unit tests.
|
|
186
|
+
*/
|
|
187
|
+
export const LOAD_BEARING_CONTEXT_SUBSTRINGS = [
|
|
188
|
+
'signal-vs-authority',
|
|
189
|
+
'INSTAR-DESIGN-PRINCIPLES-AND-LESSONS',
|
|
190
|
+
'STANDARDS-REGISTRY',
|
|
191
|
+
'integrated-being',
|
|
192
|
+
];
|
|
193
|
+
/** True when a context doc path is one the review is not valid without. */
|
|
194
|
+
export function isLoadBearingContext(docPath) {
|
|
195
|
+
const lower = docPath.toLowerCase();
|
|
196
|
+
return LOAD_BEARING_CONTEXT_SUBSTRINGS.some((s) => lower.includes(s.toLowerCase()));
|
|
197
|
+
}
|
|
108
198
|
/**
|
|
109
199
|
* Return a deterministic priority rank for a context doc path: a small index
|
|
110
200
|
* for a constitutional/lessons doc (earlier substring = smaller rank), or a
|
|
@@ -1804,11 +1894,31 @@ export function assembleReviewerPrompt(inputs) {
|
|
|
1804
1894
|
' Your view of the supporting docs is PARTIAL — flag any finding that ' +
|
|
1805
1895
|
'depends on context you could not see. ---\n');
|
|
1806
1896
|
}
|
|
1897
|
+
// Which LOAD-BEARING docs failed to arrive IN FULL? A partial one counts as
|
|
1898
|
+
// omitted (see LOAD_BEARING_CONTEXT_SUBSTRINGS) — half a constitution cannot
|
|
1899
|
+
// certify a spec against the constitution.
|
|
1900
|
+
const omittedLoadBearing = [
|
|
1901
|
+
...(partialDoc && isLoadBearingContext(partialDoc) ? [partialDoc] : []),
|
|
1902
|
+
...droppedDocs.filter(isLoadBearingContext),
|
|
1903
|
+
];
|
|
1904
|
+
// Of those, which could never have fitted at ANY spec size? Measured against
|
|
1905
|
+
// the WHOLE budget, not the remainder: a doc bigger than the entire budget is
|
|
1906
|
+
// undeliverable by construction, and saying "use a smaller spec" about it is
|
|
1907
|
+
// advice that cannot be followed.
|
|
1908
|
+
const undeliverableLoadBearing = omittedLoadBearing.filter((docPath) => {
|
|
1909
|
+
const doc = context.find((d) => d.path === docPath);
|
|
1910
|
+
if (!doc)
|
|
1911
|
+
return false;
|
|
1912
|
+
const block = `\n--- CONTEXT: ${doc.path} ---\n${doc.content}\n`;
|
|
1913
|
+
return Buffer.byteLength(block, 'utf-8') > budget;
|
|
1914
|
+
});
|
|
1807
1915
|
const promptText = parts.join('');
|
|
1808
1916
|
return {
|
|
1809
1917
|
promptText,
|
|
1810
1918
|
truncated,
|
|
1811
1919
|
bytes: Buffer.byteLength(promptText, 'utf-8'),
|
|
1920
|
+
omittedLoadBearing,
|
|
1921
|
+
undeliverableLoadBearing,
|
|
1812
1922
|
};
|
|
1813
1923
|
}
|
|
1814
1924
|
/**
|
|
@@ -1922,6 +2032,65 @@ export function resolveReviewerTimeoutMs(config, frameworkId) {
|
|
|
1922
2032
|
* `assembled` is produced by `assembleReviewerPrompt`. `detectInputs` and
|
|
1923
2033
|
* `providerOverride` exist for tests; production omits them.
|
|
1924
2034
|
*/
|
|
2035
|
+
/**
|
|
2036
|
+
* THE single place a cross-model reviewer is invoked.
|
|
2037
|
+
*
|
|
2038
|
+
* Every path — the first-match default and the per-family `--family` path the
|
|
2039
|
+
* skill actually uses — enters here, so the load-bearing context refusal cannot
|
|
2040
|
+
* be routed around. That is the whole point of the function existing: before
|
|
2041
|
+
* 2026-08-22 the refusal lived inline in `runCrossModelReview` while the skill
|
|
2042
|
+
* driver called `family.review(...)` directly, so the guard was live only on the
|
|
2043
|
+
* path nothing used (independent review, finding C1). A guard reachable by one
|
|
2044
|
+
* of two callers is not a guard; it is a comment with a test attached.
|
|
2045
|
+
*/
|
|
2046
|
+
async function invokeReviewerWithContextGuard(framework, detection, args) {
|
|
2047
|
+
// We have a reviewer. Before spending it, check that the input it is about
|
|
2048
|
+
// to judge is one a review can actually be conducted on. If the budget walk
|
|
2049
|
+
// dropped (or cut) a doc the review is not valid without, this is NOT a
|
|
2050
|
+
// review with a caveat — the reviewer could only check the spec against
|
|
2051
|
+
// itself. Degrade, name exactly what was lost, and spend nothing.
|
|
2052
|
+
//
|
|
2053
|
+
// This is deliberately a REFUSAL rather than a louder disclosure. The
|
|
2054
|
+
// assembler already disclosed the loss correctly and in full, naming every
|
|
2055
|
+
// affected doc in the prompt — and six rounds of review were still conducted
|
|
2056
|
+
// and reported as review on top of it. Disclosure informs a reader who
|
|
2057
|
+
// reads; refusal does not depend on anyone reading.
|
|
2058
|
+
const omitted = args.assembled.omittedLoadBearing ?? [];
|
|
2059
|
+
if (omitted.length > 0) {
|
|
2060
|
+
// Two refusals, not one (independent review 2026-08-22, finding C2). Both
|
|
2061
|
+
// decline to review; they differ in what the reader must DO about it, and
|
|
2062
|
+
// an undeliverable doc reported as an ordinary omission hands the reader
|
|
2063
|
+
// advice ("make the spec smaller") that cannot work at any spec size.
|
|
2064
|
+
const undeliverable = args.assembled.undeliverableLoadBearing ?? [];
|
|
2065
|
+
const reason = undeliverable.length > 0
|
|
2066
|
+
? `context-undeliverable: ${undeliverable.join(', ')} — larger than the whole ` +
|
|
2067
|
+
`${CONTEXT_BUDGET_BYTES}-byte budget on its own; no spec size admits it. ` +
|
|
2068
|
+
`Do not pass it as raw context (the standards-conformance gate reads the ` +
|
|
2069
|
+
`constitution in code).`
|
|
2070
|
+
: `context-incomplete: ${omitted.join(', ')}`;
|
|
2071
|
+
return {
|
|
2072
|
+
status: 'degraded',
|
|
2073
|
+
framework: framework.id,
|
|
2074
|
+
reason,
|
|
2075
|
+
flag: `cross-model-review: ${framework.id} (degraded: ${(args.assembled.undeliverableLoadBearing ?? []).length > 0
|
|
2076
|
+
? 'context-undeliverable'
|
|
2077
|
+
: 'context-incomplete'})`,
|
|
2078
|
+
crossFamily: isCrossFamilyReviewerFramework(framework.id),
|
|
2079
|
+
};
|
|
2080
|
+
}
|
|
2081
|
+
return framework.review({
|
|
2082
|
+
promptText: args.assembled.promptText,
|
|
2083
|
+
// Per-family timeout (§3.2 / D6): an explicit caller value wins (e.g. the
|
|
2084
|
+
// script's `--timeout-ms` dev override); otherwise resolve the per-family
|
|
2085
|
+
// budget from the `specConverge.reviewers.timeoutMs` knob (absent ⇒ 120s).
|
|
2086
|
+
timeoutMs: args.timeoutMs ?? resolveReviewerTimeoutMs(args.config, framework.id),
|
|
2087
|
+
// Hand the already-computed detection down so the entry never re-probes
|
|
2088
|
+
// the host (and tests stay hermetic to the injected inputs).
|
|
2089
|
+
detectionOverride: detection,
|
|
2090
|
+
...(args.config ? { reviewerConfig: args.config } : {}),
|
|
2091
|
+
...(args.providerOverride ? { providerOverride: args.providerOverride } : {}),
|
|
2092
|
+
});
|
|
2093
|
+
}
|
|
1925
2094
|
export async function runCrossModelReview(args) {
|
|
1926
2095
|
// Derive detect inputs from config when the caller omitted them
|
|
1927
2096
|
// (round-8: every future caller inherits the enabledFrameworks plumb —
|
|
@@ -1930,7 +2099,36 @@ export async function runCrossModelReview(args) {
|
|
|
1930
2099
|
(Array.isArray(args.config?.enabledFrameworks)
|
|
1931
2100
|
? { enabledFrameworks: args.config.enabledFrameworks }
|
|
1932
2101
|
: undefined);
|
|
1933
|
-
|
|
2102
|
+
// Per-family selection (C1): resolve THIS family's entry and detection, then
|
|
2103
|
+
// fall through to exactly the same refusal + invoke below. A family the
|
|
2104
|
+
// active registry does not carry is `unavailable`, never a silent fallback to
|
|
2105
|
+
// some other model — a caller that asked for gemini must not be answered by
|
|
2106
|
+
// codex without being told.
|
|
2107
|
+
const requestedFamily = args.family;
|
|
2108
|
+
if (requestedFamily !== undefined) {
|
|
2109
|
+
const entry = resolveActiveReviewerFrameworks(args.config).find((f) => f.id === requestedFamily);
|
|
2110
|
+
if (!entry) {
|
|
2111
|
+
const flag = buildCrossModelFlag('unavailable', 'no-supported-framework');
|
|
2112
|
+
return {
|
|
2113
|
+
status: 'unavailable',
|
|
2114
|
+
reason: 'no-supported-framework',
|
|
2115
|
+
flag: flag.flag,
|
|
2116
|
+
crossFamily: isCrossFamilyReviewerFramework(requestedFamily),
|
|
2117
|
+
};
|
|
2118
|
+
}
|
|
2119
|
+
const famDetection = args.detectionOverride ?? entry.detect(effectiveDetectInputs);
|
|
2120
|
+
if (!famDetection.available) {
|
|
2121
|
+
const flag = buildCrossModelFlag('unavailable', famDetection.reason);
|
|
2122
|
+
return {
|
|
2123
|
+
status: 'unavailable',
|
|
2124
|
+
reason: famDetection.reason,
|
|
2125
|
+
flag: flag.flag,
|
|
2126
|
+
crossFamily: isCrossFamilyReviewerFramework(requestedFamily),
|
|
2127
|
+
};
|
|
2128
|
+
}
|
|
2129
|
+
return invokeReviewerWithContextGuard(entry, famDetection, args);
|
|
2130
|
+
}
|
|
2131
|
+
const detection = args.detectionOverride ?? detectCrossModelReviewer(effectiveDetectInputs, args.config);
|
|
1934
2132
|
if (!detection.available) {
|
|
1935
2133
|
const flag = buildCrossModelFlag('unavailable', detection.reason);
|
|
1936
2134
|
return {
|
|
@@ -1951,18 +2149,7 @@ export async function runCrossModelReview(args) {
|
|
|
1951
2149
|
crossFamily: false,
|
|
1952
2150
|
};
|
|
1953
2151
|
}
|
|
1954
|
-
return framework
|
|
1955
|
-
promptText: args.assembled.promptText,
|
|
1956
|
-
// Per-family timeout (§3.2 / D6): an explicit caller value wins (e.g. the
|
|
1957
|
-
// script's `--timeout-ms` dev override); otherwise resolve the per-family
|
|
1958
|
-
// budget from the `specConverge.reviewers.timeoutMs` knob (absent ⇒ 120s).
|
|
1959
|
-
timeoutMs: args.timeoutMs ?? resolveReviewerTimeoutMs(args.config, framework.id),
|
|
1960
|
-
// Hand the already-computed detection down so the entry never re-probes
|
|
1961
|
-
// the host (and tests stay hermetic to the injected inputs).
|
|
1962
|
-
detectionOverride: detection,
|
|
1963
|
-
...(args.config ? { reviewerConfig: args.config } : {}),
|
|
1964
|
-
...(args.providerOverride ? { providerOverride: args.providerOverride } : {}),
|
|
1965
|
-
});
|
|
2152
|
+
return invokeReviewerWithContextGuard(framework, detection, args);
|
|
1966
2153
|
}
|
|
1967
2154
|
// ── Delta-gating (reviewable-body hash) ─────────────────────────────────
|
|
1968
2155
|
/**
|