instar 1.3.483 → 1.3.484
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/crossModelReviewer.d.ts +139 -9
- package/dist/core/crossModelReviewer.d.ts.map +1 -1
- package/dist/core/crossModelReviewer.js +342 -16
- package/dist/core/crossModelReviewer.js.map +1 -1
- package/package.json +1 -1
- package/skills/spec-converge/SKILL.md +41 -14
- package/skills/spec-converge/scripts/cross-model-review.mjs +113 -15
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.3.484.md +37 -0
- package/upgrades/side-effects/cross-model-hardening.md +93 -0
|
@@ -22,10 +22,27 @@
|
|
|
22
22
|
* from `degraded` (framework present, this call failed) and
|
|
23
23
|
* `skipped-abbreviated` (author chose the fast path).
|
|
24
24
|
*
|
|
25
|
-
* codex is the FIRST supported framework; the
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
25
|
+
* codex is the FIRST supported framework; gemini-cli is the SECOND (Piece 3 of
|
|
26
|
+
* docs/specs/AUTONOMY-PRINCIPLES-ENFORCEMENT-SPEC.md — cross-model convergence
|
|
27
|
+
* hardening). The registry (`SUPPORTED_REVIEWER_FRAMEWORKS`) remains the single
|
|
28
|
+
* seam for further frameworks. Adding a framework is one registry entry + one
|
|
29
|
+
* `id`-union extension — no skill change.
|
|
30
|
+
*
|
|
31
|
+
* Piece 3 additions (all signal-only, never-throw, same invariants as above):
|
|
32
|
+
* - `detectGeminiReviewer` + the gemini registry entry (family diversity).
|
|
33
|
+
* - `detectAllCrossModelReviewers` — collect EVERY available framework, not
|
|
34
|
+
* just the first match, so the skill runs one external pass per family.
|
|
35
|
+
* - `isConcreteReviewerModel` — the fail-loud model canary: a tier word
|
|
36
|
+
* ('capable', 'fast', …) falling through model resolution degrades the
|
|
37
|
+
* review LOUDLY instead of silently selecting a dead reviewer.
|
|
38
|
+
* - `hashSpecReviewableBody` — delta-gating: externals re-run only when the
|
|
39
|
+
* spec's reviewable body (frontmatter stripped) actually changed.
|
|
40
|
+
* - `recordFrameworkActivationObservation` / `wasNonClaudeFrameworkActiveWithin`
|
|
41
|
+
* — the durable standing-framework baseline: activation is judged against
|
|
42
|
+
* a lookback window of recorded observations, not a just-in-time reading,
|
|
43
|
+
* so a just-before-converge framework deactivation cannot exempt a spec.
|
|
44
|
+
* - `TRUSTED_REVIEWER_FRAMEWORKS` — the provider allowlist (no spec egress
|
|
45
|
+
* to untrusted/custom endpoints).
|
|
29
46
|
*/
|
|
30
47
|
import { type IntelligenceFramework } from './intelligenceProviderFactory.js';
|
|
31
48
|
/**
|
|
@@ -70,7 +87,7 @@ export declare function orderContextDeterministically(context: readonly Referenc
|
|
|
70
87
|
* Rule-1 / auth-probe vocabulary so a report can render a specific
|
|
71
88
|
* remediation.
|
|
72
89
|
*/
|
|
73
|
-
export type CrossModelUnavailableReason = 'codex-not-installed' | 'codex-not-authed' | 'codex-auth-apikey-forbidden' | 'no-supported-framework';
|
|
90
|
+
export type CrossModelUnavailableReason = 'codex-not-installed' | 'codex-not-authed' | 'codex-auth-apikey-forbidden' | 'gemini-not-installed' | 'gemini-not-authed' | 'no-supported-framework';
|
|
74
91
|
export interface CrossModelDetectionResult {
|
|
75
92
|
available: boolean;
|
|
76
93
|
/** Present when available; the framework id that will run the review. */
|
|
@@ -99,6 +116,16 @@ export interface CrossModelDetectInputs {
|
|
|
99
116
|
env?: NodeJS.ProcessEnv;
|
|
100
117
|
/** Clock injection for the Rule-1 killswitch sunset check. */
|
|
101
118
|
now?: Date;
|
|
119
|
+
/**
|
|
120
|
+
* Path to the gemini binary if detected, else null. Defaults to
|
|
121
|
+
* `detectGeminiPath()` (PATH + known-location resolution).
|
|
122
|
+
*/
|
|
123
|
+
geminiPathDetected?: string | null;
|
|
124
|
+
/**
|
|
125
|
+
* Path to the gemini CLI's cached OAuth credentials. Defaults to
|
|
126
|
+
* `${GEMINI_HOME || ~/.gemini}/oauth_creds.json`.
|
|
127
|
+
*/
|
|
128
|
+
geminiOauthCredsPath?: string;
|
|
102
129
|
}
|
|
103
130
|
/**
|
|
104
131
|
* Detect a codex reviewer. Returns `{ available: true, framework, model }`
|
|
@@ -109,6 +136,17 @@ export interface CrossModelDetectInputs {
|
|
|
109
136
|
* real host. It NEVER throws.
|
|
110
137
|
*/
|
|
111
138
|
export declare function detectCodexReviewer(inputs?: CrossModelDetectInputs): CrossModelDetectionResult;
|
|
139
|
+
/**
|
|
140
|
+
* Detect a gemini reviewer (Piece 3 — the second family in the registry).
|
|
141
|
+
* Returns `{ available: true, framework, model }` iff BOTH of: gemini binary
|
|
142
|
+
* detected, cached OAuth credentials present (`access_token` or
|
|
143
|
+
* `refresh_token`). Any miss → a specific reason.
|
|
144
|
+
*
|
|
145
|
+
* Pure-ish: all external inputs are injectable (mirrors
|
|
146
|
+
* `detectCodexReviewer`). With no inputs it probes the real host. It NEVER
|
|
147
|
+
* throws.
|
|
148
|
+
*/
|
|
149
|
+
export declare function detectGeminiReviewer(inputs?: CrossModelDetectInputs): CrossModelDetectionResult;
|
|
112
150
|
export interface ReviewerResult {
|
|
113
151
|
/** Outcome class for the cross-model pass. */
|
|
114
152
|
status: 'ok' | 'degraded' | 'unavailable';
|
|
@@ -162,22 +200,66 @@ export interface ReviewerInvokeArgs {
|
|
|
162
200
|
timeoutMs?: number;
|
|
163
201
|
}): Promise<string>;
|
|
164
202
|
};
|
|
203
|
+
/**
|
|
204
|
+
* Optional detection override — `runCrossModelReview` passes the detection
|
|
205
|
+
* it already computed (so review never re-probes the host), and tests inject
|
|
206
|
+
* synthetic detections (e.g. a tier-word model to exercise the canary).
|
|
207
|
+
* Absent → the entry runs its own real-host detect, as before (back-compat).
|
|
208
|
+
*/
|
|
209
|
+
detectionOverride?: CrossModelDetectionResult;
|
|
165
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Fail-loud model canary (Piece 3). A cross-model review must run on a
|
|
213
|
+
* CONCRETE model id — never a bare tier word that fell through a
|
|
214
|
+
* tier→model resolution map (the `resolveModelForFramework` fall-through
|
|
215
|
+
* failure class: the literal string 'capable' is not a model, and silently
|
|
216
|
+
* passing it selects a dead reviewer). Returns false for undefined/empty
|
|
217
|
+
* strings and for bare tier words (case-insensitive). Both registry entries
|
|
218
|
+
* check this BEFORE invoking the provider and degrade LOUDLY
|
|
219
|
+
* (`model-resolution-canary`) on a failure.
|
|
220
|
+
*/
|
|
221
|
+
export declare function isConcreteReviewerModel(model: string | undefined): boolean;
|
|
166
222
|
/**
|
|
167
223
|
* The supported-reviewer registry. codex first — the order IS the preference
|
|
168
|
-
* order. gemini
|
|
224
|
+
* order. gemini second (Piece 3). Further frameworks land here as later
|
|
225
|
+
* registry entries. NOTE: the registry only ever carries first-party OAuth
|
|
226
|
+
* CLI adapters — see `TRUSTED_REVIEWER_FRAMEWORKS` below.
|
|
169
227
|
*/
|
|
170
228
|
export declare const SUPPORTED_REVIEWER_FRAMEWORKS: SupportedReviewerFramework[];
|
|
229
|
+
/**
|
|
230
|
+
* Trusted-provider allowlist (Piece 3 — no spec egress to untrusted
|
|
231
|
+
* endpoints). The registry only ever carries FIRST-PARTY OAuth CLI adapters:
|
|
232
|
+
* the full spec text is handed to the reviewer model, so it must NEVER be
|
|
233
|
+
* sent to a custom/base-URL endpoint an operator (or attacker) pointed a
|
|
234
|
+
* framework at. The pi-cli multi-provider case is deliberately EXCLUDED from
|
|
235
|
+
* cross-model review for exactly this reason — its provider may be a custom
|
|
236
|
+
* endpoint. A framework id outside this list is refused by the script
|
|
237
|
+
* wrapper (`--family`) with reason `untrusted-framework`.
|
|
238
|
+
*/
|
|
239
|
+
export declare const TRUSTED_REVIEWER_FRAMEWORKS: readonly string[];
|
|
240
|
+
/** Is `id` on the trusted first-party reviewer allowlist? */
|
|
241
|
+
export declare function isTrustedReviewerFramework(id: string): boolean;
|
|
171
242
|
/**
|
|
172
243
|
* Walk the registry in preference order and return the FIRST available
|
|
173
|
-
* framework's detection result
|
|
174
|
-
*
|
|
175
|
-
* the
|
|
244
|
+
* framework's detection result (back-compat single-reviewer entry point —
|
|
245
|
+
* the multi-family collection is `detectAllCrossModelReviewers`). If none is
|
|
246
|
+
* available, returns the preference-leader's specific reason (codex today) so
|
|
247
|
+
* the report can render a concrete remediation, rather than the generic
|
|
248
|
+
* `no-supported-framework`.
|
|
176
249
|
*
|
|
177
250
|
* SIGNAL-ONLY: never throws, never blocks. A `false` simply routes the skill
|
|
178
251
|
* to the internal-only fallback (spec §4).
|
|
179
252
|
*/
|
|
180
253
|
export declare function detectCrossModelReviewer(inputs?: CrossModelDetectInputs): CrossModelDetectionResult;
|
|
254
|
+
/**
|
|
255
|
+
* Collect EVERY available reviewer framework, in registry preference order
|
|
256
|
+
* (Piece 3 — family diversity: GPT and Gemini catch different failure
|
|
257
|
+
* classes, so the externals pass runs one review PER available family, not
|
|
258
|
+
* first-match-only). Returns an empty array when none is available.
|
|
259
|
+
*
|
|
260
|
+
* SIGNAL-ONLY: never throws, never blocks.
|
|
261
|
+
*/
|
|
262
|
+
export declare function detectAllCrossModelReviewers(inputs?: CrossModelDetectInputs): CrossModelDetectionResult[];
|
|
181
263
|
/**
|
|
182
264
|
* Map a provider rejection into a coarse `degraded` reason. The provider
|
|
183
265
|
* surfaces timeouts, non-zero exits, and (via the circuit breaker) rate
|
|
@@ -306,5 +388,53 @@ export declare function runCrossModelReview(args: {
|
|
|
306
388
|
detectInputs?: CrossModelDetectInputs;
|
|
307
389
|
providerOverride?: ReviewerInvokeArgs['providerOverride'];
|
|
308
390
|
}): Promise<ReviewerResult>;
|
|
391
|
+
/**
|
|
392
|
+
* Hash the spec's REVIEWABLE body (Piece 3 delta-gating): sha256 hex of the
|
|
393
|
+
* spec text with the leading YAML frontmatter block stripped and line endings
|
|
394
|
+
* normalized (\r\n → \n). Frontmatter is excluded so tag-writes
|
|
395
|
+
* (`review-convergence`, `approved: true`, cross-model flags) and other
|
|
396
|
+
* metadata edits do NOT change the hash — externals re-run only when the
|
|
397
|
+
* content a reviewer would actually read changed. The skill runs externals on
|
|
398
|
+
* round 1 and on any round where this hash differs from the last external
|
|
399
|
+
* pass's hash; an unchanged round records a skip-with-logged-note.
|
|
400
|
+
*/
|
|
401
|
+
export declare function hashSpecReviewableBody(specText: string): string;
|
|
402
|
+
/**
|
|
403
|
+
* One recorded observation of which reviewer frameworks were available at a
|
|
404
|
+
* moment in time. Appended (JSONL) to
|
|
405
|
+
* `<stateDir>/state/framework-activation-history.jsonl` by the script
|
|
406
|
+
* wrapper's `--detect-only --state-dir` path on every detection.
|
|
407
|
+
*/
|
|
408
|
+
export interface FrameworkActivationObservation {
|
|
409
|
+
/** ISO timestamp; defaults to now. */
|
|
410
|
+
ts?: string;
|
|
411
|
+
/** framework id → was it available/active at observation time. */
|
|
412
|
+
frameworks: Record<string, boolean>;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Append ONE observation line to the durable framework-activation history
|
|
416
|
+
* (Piece 3 — the standing-framework baseline). The externals-mandatory check
|
|
417
|
+
* is judged against this recorded history over a lookback window, NOT a
|
|
418
|
+
* just-in-time reading — so deactivating a framework right before converging
|
|
419
|
+
* cannot present the agent as "genuinely single-framework."
|
|
420
|
+
*
|
|
421
|
+
* mkdir -p's the state dir; caps the file at the most recent
|
|
422
|
+
* `ACTIVATION_HISTORY_MAX_LINES` lines on every write. Filesystem errors
|
|
423
|
+
* propagate — a silently-unrecorded baseline would quietly weaken the
|
|
424
|
+
* mandatory check (fail-loud).
|
|
425
|
+
*/
|
|
426
|
+
export declare function recordFrameworkActivationObservation(stateDir: string, observation: FrameworkActivationObservation): void;
|
|
427
|
+
/**
|
|
428
|
+
* Was ANY non-Claude reviewer framework active at ANY point within the
|
|
429
|
+
* lookback window, per the durable activation history? This is the
|
|
430
|
+
* externals-mandatory check (Piece 3): `true` means the cross-model pass is
|
|
431
|
+
* NON-SKIPPABLE for the spec — including when a framework was deactivated
|
|
432
|
+
* inside the window (a just-before-converge deactivation does not exempt the
|
|
433
|
+
* spec). The advisory "externals unavailable" floor is legitimate only when
|
|
434
|
+
* this returns `false` across the whole lookback.
|
|
435
|
+
*
|
|
436
|
+
* NEVER throws: a missing file → false; corrupt lines are skipped.
|
|
437
|
+
*/
|
|
438
|
+
export declare function wasNonClaudeFrameworkActiveWithin(stateDir: string, lookbackDays: number, now?: Date): boolean;
|
|
309
439
|
export {};
|
|
310
440
|
//# sourceMappingURL=crossModelReviewer.d.ts.map
|
|
@@ -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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"}
|
|
@@ -22,17 +22,36 @@
|
|
|
22
22
|
* from `degraded` (framework present, this call failed) and
|
|
23
23
|
* `skipped-abbreviated` (author chose the fast path).
|
|
24
24
|
*
|
|
25
|
-
* codex is the FIRST supported framework; the
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
25
|
+
* codex is the FIRST supported framework; gemini-cli is the SECOND (Piece 3 of
|
|
26
|
+
* docs/specs/AUTONOMY-PRINCIPLES-ENFORCEMENT-SPEC.md — cross-model convergence
|
|
27
|
+
* hardening). The registry (`SUPPORTED_REVIEWER_FRAMEWORKS`) remains the single
|
|
28
|
+
* seam for further frameworks. Adding a framework is one registry entry + one
|
|
29
|
+
* `id`-union extension — no skill change.
|
|
30
|
+
*
|
|
31
|
+
* Piece 3 additions (all signal-only, never-throw, same invariants as above):
|
|
32
|
+
* - `detectGeminiReviewer` + the gemini registry entry (family diversity).
|
|
33
|
+
* - `detectAllCrossModelReviewers` — collect EVERY available framework, not
|
|
34
|
+
* just the first match, so the skill runs one external pass per family.
|
|
35
|
+
* - `isConcreteReviewerModel` — the fail-loud model canary: a tier word
|
|
36
|
+
* ('capable', 'fast', …) falling through model resolution degrades the
|
|
37
|
+
* review LOUDLY instead of silently selecting a dead reviewer.
|
|
38
|
+
* - `hashSpecReviewableBody` — delta-gating: externals re-run only when the
|
|
39
|
+
* spec's reviewable body (frontmatter stripped) actually changed.
|
|
40
|
+
* - `recordFrameworkActivationObservation` / `wasNonClaudeFrameworkActiveWithin`
|
|
41
|
+
* — the durable standing-framework baseline: activation is judged against
|
|
42
|
+
* a lookback window of recorded observations, not a just-in-time reading,
|
|
43
|
+
* so a just-before-converge framework deactivation cannot exempt a spec.
|
|
44
|
+
* - `TRUSTED_REVIEWER_FRAMEWORKS` — the provider allowlist (no spec egress
|
|
45
|
+
* to untrusted/custom endpoints).
|
|
29
46
|
*/
|
|
47
|
+
import crypto from 'node:crypto';
|
|
30
48
|
import fs from 'node:fs';
|
|
31
49
|
import os from 'node:os';
|
|
32
50
|
import path from 'node:path';
|
|
33
|
-
import { detectCodexPath } from './Config.js';
|
|
51
|
+
import { detectCodexPath, detectGeminiPath } from './Config.js';
|
|
34
52
|
import { validateRule1 } from '../providers/adapters/openai-codex/credentials.js';
|
|
35
53
|
import { resolveCliModelFlag } from '../providers/adapters/openai-codex/models.js';
|
|
54
|
+
import { resolveCliModelFlag as resolveGeminiModelFlag } from '../providers/adapters/gemini-cli/models.js';
|
|
36
55
|
import { buildIntelligenceProvider, } from './intelligenceProviderFactory.js';
|
|
37
56
|
// ── Constants (tunable) ─────────────────────────────────────────────────
|
|
38
57
|
/**
|
|
@@ -154,6 +173,86 @@ export function detectCodexReviewer(inputs = {}) {
|
|
|
154
173
|
model: resolveCliModelFlag(REVIEW_MODEL_TIER),
|
|
155
174
|
};
|
|
156
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Resolve the default gemini oauth_creds.json path. DELIBERATELY no env-var
|
|
178
|
+
* override: the gemini CLI (verified v0.25.2) resolves creds at
|
|
179
|
+
* `~/.gemini/oauth_creds.json` UNCONDITIONALLY — there is no GEMINI_HOME.
|
|
180
|
+
* Honoring one here would make detection probe a path the CLI never reads
|
|
181
|
+
* (false-unavailable on an authed host -> the gemini pass silently skipped AND
|
|
182
|
+
* a false `gemini-cli:false` recorded into the activation baseline — the exact
|
|
183
|
+
* suppression Piece 3 exists to prevent). Tests inject `geminiOauthCredsPath`.
|
|
184
|
+
*/
|
|
185
|
+
function defaultGeminiOauthCredsPath() {
|
|
186
|
+
return path.join(os.homedir(), '.gemini', 'oauth_creds.json');
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Is the gemini CLI's cached OAuth credentials file an authed shape? Authed
|
|
190
|
+
* iff the file parses as JSON with a non-empty string `access_token` OR
|
|
191
|
+
* `refresh_token` (the CLI refreshes an expired access token from the refresh
|
|
192
|
+
* token, so either is a usable seat). A missing / unreadable / malformed file
|
|
193
|
+
* → false (not authed). Never throws.
|
|
194
|
+
*/
|
|
195
|
+
function geminiOauthCredsAuthed(credsPath) {
|
|
196
|
+
try {
|
|
197
|
+
const raw = fs.readFileSync(credsPath, 'utf-8');
|
|
198
|
+
const parsed = JSON.parse(raw);
|
|
199
|
+
const nonEmptyString = (v) => typeof v === 'string' && v.length > 0;
|
|
200
|
+
return nonEmptyString(parsed?.access_token) || nonEmptyString(parsed?.refresh_token);
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// @silent-fallback-ok — deny-safe: missing/unreadable/malformed creds mean
|
|
204
|
+
// "not authed" (the reviewer is reported unavailable with a named reason);
|
|
205
|
+
// mirrors the codex auth probe above.
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Detect a gemini reviewer (Piece 3 — the second family in the registry).
|
|
211
|
+
* Returns `{ available: true, framework, model }` iff BOTH of: gemini binary
|
|
212
|
+
* detected, cached OAuth credentials present (`access_token` or
|
|
213
|
+
* `refresh_token`). Any miss → a specific reason.
|
|
214
|
+
*
|
|
215
|
+
* Pure-ish: all external inputs are injectable (mirrors
|
|
216
|
+
* `detectCodexReviewer`). With no inputs it probes the real host. It NEVER
|
|
217
|
+
* throws.
|
|
218
|
+
*/
|
|
219
|
+
export function detectGeminiReviewer(inputs = {}) {
|
|
220
|
+
const env = inputs.env ?? process.env;
|
|
221
|
+
const geminiPath = inputs.geminiPathDetected !== undefined ? inputs.geminiPathDetected : detectGeminiPath();
|
|
222
|
+
const credsPath = inputs.geminiOauthCredsPath ?? defaultGeminiOauthCredsPath();
|
|
223
|
+
// 1. Binary present?
|
|
224
|
+
if (!geminiPath) {
|
|
225
|
+
return { available: false, reason: 'gemini-not-installed' };
|
|
226
|
+
}
|
|
227
|
+
// 2. Authed via the CLI's cached OAuth?
|
|
228
|
+
if (!geminiOauthCredsAuthed(credsPath)) {
|
|
229
|
+
return { available: false, reason: 'gemini-not-authed' };
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
available: true,
|
|
233
|
+
framework: 'gemini-cli',
|
|
234
|
+
model: resolveGeminiModelFlag(REVIEW_MODEL_TIER),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Fail-loud model canary (Piece 3). A cross-model review must run on a
|
|
239
|
+
* CONCRETE model id — never a bare tier word that fell through a
|
|
240
|
+
* tier→model resolution map (the `resolveModelForFramework` fall-through
|
|
241
|
+
* failure class: the literal string 'capable' is not a model, and silently
|
|
242
|
+
* passing it selects a dead reviewer). Returns false for undefined/empty
|
|
243
|
+
* strings and for bare tier words (case-insensitive). Both registry entries
|
|
244
|
+
* check this BEFORE invoking the provider and degrade LOUDLY
|
|
245
|
+
* (`model-resolution-canary`) on a failure.
|
|
246
|
+
*/
|
|
247
|
+
export function isConcreteReviewerModel(model) {
|
|
248
|
+
if (typeof model !== 'string')
|
|
249
|
+
return false;
|
|
250
|
+
const trimmed = model.trim();
|
|
251
|
+
if (trimmed.length === 0)
|
|
252
|
+
return false;
|
|
253
|
+
const TIER_WORDS = new Set(['fast', 'balanced', 'capable', 'haiku', 'sonnet', 'opus']);
|
|
254
|
+
return !TIER_WORDS.has(trimmed.toLowerCase());
|
|
255
|
+
}
|
|
157
256
|
/**
|
|
158
257
|
* The codex reviewer entry. Detection delegates to `detectCodexReviewer`;
|
|
159
258
|
* `review` routes through the factory-built `CodexCliIntelligenceProvider`.
|
|
@@ -162,9 +261,20 @@ const codexReviewer = {
|
|
|
162
261
|
id: 'codex-cli',
|
|
163
262
|
detect: (inputs) => detectCodexReviewer(inputs),
|
|
164
263
|
review: async (args) => {
|
|
165
|
-
const detection = detectCodexReviewer();
|
|
264
|
+
const detection = args.detectionOverride ?? detectCodexReviewer();
|
|
166
265
|
const model = detection.model ?? resolveCliModelFlag(REVIEW_MODEL_TIER);
|
|
167
266
|
const tag = `cross-model:codex-cli:${model}`;
|
|
267
|
+
// Fail-loud model canary (Piece 3): NEVER silently review with a
|
|
268
|
+
// tier-word model — a fall-through 'capable' is a dead reviewer.
|
|
269
|
+
if (!isConcreteReviewerModel(model)) {
|
|
270
|
+
return {
|
|
271
|
+
status: 'degraded',
|
|
272
|
+
framework: 'codex-cli',
|
|
273
|
+
model,
|
|
274
|
+
reason: 'model-resolution-canary',
|
|
275
|
+
flag: `cross-model-review: codex-cli:${model} (degraded: model-resolution-canary)`,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
168
278
|
// Build (or accept an injected) provider. The factory wraps it in the
|
|
169
279
|
// account-global circuit breaker, so a rate-limited review degrades the
|
|
170
280
|
// same way every other instar LLM call does.
|
|
@@ -210,16 +320,107 @@ const codexReviewer = {
|
|
|
210
320
|
};
|
|
211
321
|
},
|
|
212
322
|
};
|
|
323
|
+
/**
|
|
324
|
+
* The gemini reviewer entry (Piece 3 — family diversity: a second non-Claude
|
|
325
|
+
* model family alongside GPT). Detection delegates to `detectGeminiReviewer`;
|
|
326
|
+
* `review` routes through the factory-built `GeminiCliIntelligenceProvider`
|
|
327
|
+
* (same circuit-breaker wrapping, same degraded semantics as codex).
|
|
328
|
+
*/
|
|
329
|
+
const geminiReviewer = {
|
|
330
|
+
id: 'gemini-cli',
|
|
331
|
+
detect: (inputs) => detectGeminiReviewer(inputs),
|
|
332
|
+
review: async (args) => {
|
|
333
|
+
const detection = args.detectionOverride ?? detectGeminiReviewer();
|
|
334
|
+
const model = detection.model ?? resolveGeminiModelFlag(REVIEW_MODEL_TIER);
|
|
335
|
+
const tag = `cross-model:gemini-cli:${model}`;
|
|
336
|
+
// Fail-loud model canary (Piece 3): NEVER silently review with a
|
|
337
|
+
// tier-word model — a fall-through 'capable' is a dead reviewer.
|
|
338
|
+
if (!isConcreteReviewerModel(model)) {
|
|
339
|
+
return {
|
|
340
|
+
status: 'degraded',
|
|
341
|
+
framework: 'gemini-cli',
|
|
342
|
+
model,
|
|
343
|
+
reason: 'model-resolution-canary',
|
|
344
|
+
flag: `cross-model-review: gemini-cli:${model} (degraded: model-resolution-canary)`,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
// Build (or accept an injected) provider. The factory wraps it in the
|
|
348
|
+
// account-global circuit breaker, so a rate-limited review degrades the
|
|
349
|
+
// same way every other instar LLM call does.
|
|
350
|
+
const provider = args.providerOverride ??
|
|
351
|
+
buildIntelligenceProvider({ framework: 'gemini-cli' });
|
|
352
|
+
if (!provider) {
|
|
353
|
+
// Binary vanished between detect and review (or detection said
|
|
354
|
+
// unavailable and review was called anyway). Degraded, not a throw.
|
|
355
|
+
return {
|
|
356
|
+
status: 'degraded',
|
|
357
|
+
framework: 'gemini-cli',
|
|
358
|
+
model,
|
|
359
|
+
reason: 'provider-unavailable',
|
|
360
|
+
flag: `cross-model-review: gemini-cli:${model} (degraded: provider-unavailable)`,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
let raw;
|
|
364
|
+
try {
|
|
365
|
+
raw = await provider.evaluate(args.promptText, {
|
|
366
|
+
model: REVIEW_MODEL_TIER,
|
|
367
|
+
timeoutMs: args.timeoutMs,
|
|
368
|
+
attribution: { component: 'crossModelReviewer' }, // attribution for /metrics/features
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
catch (err) {
|
|
372
|
+
const reason = classifyReviewFailure(err);
|
|
373
|
+
return {
|
|
374
|
+
status: 'degraded',
|
|
375
|
+
framework: 'gemini-cli',
|
|
376
|
+
model,
|
|
377
|
+
reason,
|
|
378
|
+
flag: `cross-model-review: gemini-cli:${model} (degraded: ${reason})`,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
const parsed = parseReviewerReply(raw, tag);
|
|
382
|
+
return {
|
|
383
|
+
status: 'ok',
|
|
384
|
+
framework: 'gemini-cli',
|
|
385
|
+
model,
|
|
386
|
+
verdict: parsed.verdict,
|
|
387
|
+
findings: [parsed],
|
|
388
|
+
flag: `cross-model-review: gemini-cli:${model}`,
|
|
389
|
+
};
|
|
390
|
+
},
|
|
391
|
+
};
|
|
213
392
|
/**
|
|
214
393
|
* The supported-reviewer registry. codex first — the order IS the preference
|
|
215
|
-
* order. gemini
|
|
394
|
+
* order. gemini second (Piece 3). Further frameworks land here as later
|
|
395
|
+
* registry entries. NOTE: the registry only ever carries first-party OAuth
|
|
396
|
+
* CLI adapters — see `TRUSTED_REVIEWER_FRAMEWORKS` below.
|
|
216
397
|
*/
|
|
217
|
-
export const SUPPORTED_REVIEWER_FRAMEWORKS = [
|
|
398
|
+
export const SUPPORTED_REVIEWER_FRAMEWORKS = [
|
|
399
|
+
codexReviewer,
|
|
400
|
+
geminiReviewer,
|
|
401
|
+
];
|
|
402
|
+
/**
|
|
403
|
+
* Trusted-provider allowlist (Piece 3 — no spec egress to untrusted
|
|
404
|
+
* endpoints). The registry only ever carries FIRST-PARTY OAuth CLI adapters:
|
|
405
|
+
* the full spec text is handed to the reviewer model, so it must NEVER be
|
|
406
|
+
* sent to a custom/base-URL endpoint an operator (or attacker) pointed a
|
|
407
|
+
* framework at. The pi-cli multi-provider case is deliberately EXCLUDED from
|
|
408
|
+
* cross-model review for exactly this reason — its provider may be a custom
|
|
409
|
+
* endpoint. A framework id outside this list is refused by the script
|
|
410
|
+
* wrapper (`--family`) with reason `untrusted-framework`.
|
|
411
|
+
*/
|
|
412
|
+
export const TRUSTED_REVIEWER_FRAMEWORKS = ['codex-cli', 'gemini-cli'];
|
|
413
|
+
/** Is `id` on the trusted first-party reviewer allowlist? */
|
|
414
|
+
export function isTrustedReviewerFramework(id) {
|
|
415
|
+
return TRUSTED_REVIEWER_FRAMEWORKS.includes(id);
|
|
416
|
+
}
|
|
218
417
|
/**
|
|
219
418
|
* Walk the registry in preference order and return the FIRST available
|
|
220
|
-
* framework's detection result
|
|
221
|
-
*
|
|
222
|
-
* the
|
|
419
|
+
* framework's detection result (back-compat single-reviewer entry point —
|
|
420
|
+
* the multi-family collection is `detectAllCrossModelReviewers`). If none is
|
|
421
|
+
* available, returns the preference-leader's specific reason (codex today) so
|
|
422
|
+
* the report can render a concrete remediation, rather than the generic
|
|
423
|
+
* `no-supported-framework`.
|
|
223
424
|
*
|
|
224
425
|
* SIGNAL-ONLY: never throws, never blocks. A `false` simply routes the skill
|
|
225
426
|
* to the internal-only fallback (spec §4).
|
|
@@ -230,13 +431,29 @@ export function detectCrossModelReviewer(inputs = {}) {
|
|
|
230
431
|
if (result.available)
|
|
231
432
|
return result;
|
|
232
433
|
}
|
|
233
|
-
// Nothing available. Surface the
|
|
234
|
-
|
|
235
|
-
if (
|
|
236
|
-
return
|
|
237
|
-
}
|
|
434
|
+
// Nothing available. Surface the preference-leader's specific reason.
|
|
435
|
+
const leader = SUPPORTED_REVIEWER_FRAMEWORKS[0];
|
|
436
|
+
if (leader)
|
|
437
|
+
return leader.detect(inputs);
|
|
238
438
|
return { available: false, reason: 'no-supported-framework' };
|
|
239
439
|
}
|
|
440
|
+
/**
|
|
441
|
+
* Collect EVERY available reviewer framework, in registry preference order
|
|
442
|
+
* (Piece 3 — family diversity: GPT and Gemini catch different failure
|
|
443
|
+
* classes, so the externals pass runs one review PER available family, not
|
|
444
|
+
* first-match-only). Returns an empty array when none is available.
|
|
445
|
+
*
|
|
446
|
+
* SIGNAL-ONLY: never throws, never blocks.
|
|
447
|
+
*/
|
|
448
|
+
export function detectAllCrossModelReviewers(inputs = {}) {
|
|
449
|
+
const available = [];
|
|
450
|
+
for (const framework of SUPPORTED_REVIEWER_FRAMEWORKS) {
|
|
451
|
+
const result = framework.detect(inputs);
|
|
452
|
+
if (result.available)
|
|
453
|
+
available.push(result);
|
|
454
|
+
}
|
|
455
|
+
return available;
|
|
456
|
+
}
|
|
240
457
|
// ── Failure classification ──────────────────────────────────────────────
|
|
241
458
|
/**
|
|
242
459
|
* Map a provider rejection into a coarse `degraded` reason. The provider
|
|
@@ -484,7 +701,116 @@ export async function runCrossModelReview(args) {
|
|
|
484
701
|
return framework.review({
|
|
485
702
|
promptText: args.assembled.promptText,
|
|
486
703
|
timeoutMs: args.timeoutMs ?? REVIEW_TIMEOUT_MS,
|
|
704
|
+
// Hand the already-computed detection down so the entry never re-probes
|
|
705
|
+
// the host (and tests stay hermetic to the injected inputs).
|
|
706
|
+
detectionOverride: detection,
|
|
487
707
|
...(args.providerOverride ? { providerOverride: args.providerOverride } : {}),
|
|
488
708
|
});
|
|
489
709
|
}
|
|
710
|
+
// ── Delta-gating (reviewable-body hash) ─────────────────────────────────
|
|
711
|
+
/**
|
|
712
|
+
* Hash the spec's REVIEWABLE body (Piece 3 delta-gating): sha256 hex of the
|
|
713
|
+
* spec text with the leading YAML frontmatter block stripped and line endings
|
|
714
|
+
* normalized (\r\n → \n). Frontmatter is excluded so tag-writes
|
|
715
|
+
* (`review-convergence`, `approved: true`, cross-model flags) and other
|
|
716
|
+
* metadata edits do NOT change the hash — externals re-run only when the
|
|
717
|
+
* content a reviewer would actually read changed. The skill runs externals on
|
|
718
|
+
* round 1 and on any round where this hash differs from the last external
|
|
719
|
+
* pass's hash; an unchanged round records a skip-with-logged-note.
|
|
720
|
+
*/
|
|
721
|
+
export function hashSpecReviewableBody(specText) {
|
|
722
|
+
const normalized = (specText ?? '').replace(/\r\n/g, '\n');
|
|
723
|
+
// Strip ONE leading frontmatter block: `---\n ... \n---` at the very top,
|
|
724
|
+
// where the close fence is a WHOLE line (anchored `(\n|$)`) — `\n---\n?`
|
|
725
|
+
// could terminate mid-line on `--- text` / `----` inside the block
|
|
726
|
+
// (second-pass finding, PR 3).
|
|
727
|
+
const body = normalized.replace(/^---\n[\s\S]*?\n---(\n|$)/, '');
|
|
728
|
+
return crypto.createHash('sha256').update(body, 'utf-8').digest('hex');
|
|
729
|
+
}
|
|
730
|
+
/** Max JSONL lines retained in the activation-history file. */
|
|
731
|
+
const ACTIVATION_HISTORY_MAX_LINES = 2000;
|
|
732
|
+
function activationHistoryPath(stateDir) {
|
|
733
|
+
return path.join(stateDir, 'state', 'framework-activation-history.jsonl');
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Append ONE observation line to the durable framework-activation history
|
|
737
|
+
* (Piece 3 — the standing-framework baseline). The externals-mandatory check
|
|
738
|
+
* is judged against this recorded history over a lookback window, NOT a
|
|
739
|
+
* just-in-time reading — so deactivating a framework right before converging
|
|
740
|
+
* cannot present the agent as "genuinely single-framework."
|
|
741
|
+
*
|
|
742
|
+
* mkdir -p's the state dir; caps the file at the most recent
|
|
743
|
+
* `ACTIVATION_HISTORY_MAX_LINES` lines on every write. Filesystem errors
|
|
744
|
+
* propagate — a silently-unrecorded baseline would quietly weaken the
|
|
745
|
+
* mandatory check (fail-loud).
|
|
746
|
+
*/
|
|
747
|
+
export function recordFrameworkActivationObservation(stateDir, observation) {
|
|
748
|
+
const file = activationHistoryPath(stateDir);
|
|
749
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
750
|
+
const entry = JSON.stringify({
|
|
751
|
+
ts: observation.ts ?? new Date().toISOString(),
|
|
752
|
+
frameworks: observation.frameworks,
|
|
753
|
+
});
|
|
754
|
+
let lines = [];
|
|
755
|
+
try {
|
|
756
|
+
lines = fs.readFileSync(file, 'utf-8').split('\n').filter((l) => l.trim().length > 0);
|
|
757
|
+
}
|
|
758
|
+
catch {
|
|
759
|
+
// No file yet — first observation.
|
|
760
|
+
}
|
|
761
|
+
lines.push(entry);
|
|
762
|
+
if (lines.length > ACTIVATION_HISTORY_MAX_LINES) {
|
|
763
|
+
lines = lines.slice(-ACTIVATION_HISTORY_MAX_LINES);
|
|
764
|
+
}
|
|
765
|
+
fs.writeFileSync(file, lines.join('\n') + '\n', 'utf-8');
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Was ANY non-Claude reviewer framework active at ANY point within the
|
|
769
|
+
* lookback window, per the durable activation history? This is the
|
|
770
|
+
* externals-mandatory check (Piece 3): `true` means the cross-model pass is
|
|
771
|
+
* NON-SKIPPABLE for the spec — including when a framework was deactivated
|
|
772
|
+
* inside the window (a just-before-converge deactivation does not exempt the
|
|
773
|
+
* spec). The advisory "externals unavailable" floor is legitimate only when
|
|
774
|
+
* this returns `false` across the whole lookback.
|
|
775
|
+
*
|
|
776
|
+
* NEVER throws: a missing file → false; corrupt lines are skipped.
|
|
777
|
+
*/
|
|
778
|
+
export function wasNonClaudeFrameworkActiveWithin(stateDir, lookbackDays, now) {
|
|
779
|
+
try {
|
|
780
|
+
const file = activationHistoryPath(stateDir);
|
|
781
|
+
const raw = fs.readFileSync(file, 'utf-8');
|
|
782
|
+
const cutoff = (now ?? new Date()).getTime() - lookbackDays * 24 * 60 * 60 * 1000;
|
|
783
|
+
for (const line of raw.split('\n')) {
|
|
784
|
+
if (!line.trim())
|
|
785
|
+
continue;
|
|
786
|
+
try {
|
|
787
|
+
const parsed = JSON.parse(line);
|
|
788
|
+
const ts = typeof parsed.ts === 'string' ? Date.parse(parsed.ts) : NaN;
|
|
789
|
+
if (!Number.isFinite(ts) || ts < cutoff)
|
|
790
|
+
continue;
|
|
791
|
+
const frameworks = parsed.frameworks;
|
|
792
|
+
if (frameworks && typeof frameworks === 'object') {
|
|
793
|
+
// Only TRUSTED reviewer framework ids count toward the baseline — a
|
|
794
|
+
// stray/hand-written key (e.g. "claude-code": true) must not flip
|
|
795
|
+
// the externals-mandatory decision (second-pass finding, PR 3).
|
|
796
|
+
const entries = Object.entries(frameworks);
|
|
797
|
+
if (entries.some(([id, v]) => v === true && isTrustedReviewerFramework(id))) {
|
|
798
|
+
return true;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
catch {
|
|
803
|
+
// @silent-fallback-ok — a corrupt history line is skipped (never throws);
|
|
804
|
+
// the read is a union-over-time, so a lost line can only UNDER-report
|
|
805
|
+
// activation, which keeps externals mandatory-safe, never lies them off.
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
return false;
|
|
809
|
+
}
|
|
810
|
+
catch {
|
|
811
|
+
// @silent-fallback-ok — a missing/unreadable history file is the expected
|
|
812
|
+
// pre-first-run state: no recorded activation is the correct answer.
|
|
813
|
+
return false;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
490
816
|
//# sourceMappingURL=crossModelReviewer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crossModelReviewer.js","sourceRoot":"","sources":["../../src/core/crossModelReviewer.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"crossModelReviewer.js","sourceRoot":"","sources":["../../src/core/crossModelReviewer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-converge
|
|
3
|
-
description: Iteratively review an instar-development spec with multi-angle internal reviewers (security, scalability, adversarial, integration, decision-completeness, lessons-aware) and
|
|
3
|
+
description: Iteratively review an instar-development spec with multi-angle internal reviewers (security, scalability, adversarial, integration, decision-completeness, lessons-aware) and real cross-model external reviewers routed through the agent's own installed CLIs (codex → GPT-tier, gemini → Gemini-tier; one pass per available family) until convergence, then produce a comprehensive ELI10 convergence report. Output is a spec tagged review-convergence — one of the two tags /instar-dev requires before it will touch instar source. NOT user-invocable; run by the instar-developing agent before any spec-driven /instar-dev work.
|
|
4
4
|
metadata:
|
|
5
5
|
user_invocable: "false"
|
|
6
6
|
audience: "instar-developing agent only — NOT end users"
|
|
@@ -72,29 +72,37 @@ The skill spawns reviewers in parallel:
|
|
|
72
72
|
- **Decision-Completeness.** (Autonomy Principle 2 — `docs/specs/AUTONOMY-PRINCIPLES-ENFORCEMENT-SPEC.md` Piece 2.) Enumerates every point where the building agent would have to **stop mid-run and ask the user**. Each must be either **frontloaded** into a `## Frontloaded Decisions` section or explicitly tagged **cheap-to-change-after** because the work ships behind a named dark/dry-run/read-only phase. The reviewer **CONTESTS every cheap tag** — it independently asserts reversibility, and a closed non-cheap taxonomy overrides any tag: anything touching **durable external side-effects, money, identity, or a published/user-visible interface is NEVER cheap**, regardless of a "ships dark" label. A contested tag the reviewer rejects is a **material finding that blocks convergence**. Prompt: `templates/reviewer-decision-completeness.md`. Applies to ALL specs through this skill (D7) — no size gate, no per-spec override (D11; the rejected `disposition: override` escape hatch would reopen the exact skip-hatch Principle 2 closes).
|
|
73
73
|
- **Lessons-aware.** Loads the canonical Instar Design Principles + Lessons Learned index (`docs/INSTAR-DESIGN-PRINCIPLES-AND-LESSONS.md`) plus the running agent's local `.instar/memory/feedback_*.md` entries, then checks the spec for (a) direct contradictions of documented principles/lessons, (b) applicable lessons the spec fails to engage with, (c) behavioral lessons violated by agent-facing surfaces the spec proposes, and **(d) FOUNDATION/SUBSYSTEM AUDIT — the design the spec TESTS, EXTENDS, or BUILDS ON, not just the spec's own surface: does that foundation violate a known standard or repeat a known mistake?** The audit MUST reach one layer below the spec boundary. A spec can be internally clean while faithfully testing or extending a flawed foundation — e.g. a test-harness spec that correctly proves a permission gate which *itself* holds brittle blocking authority in violation of Signal-vs-Authority, or an extension spec built on a subsystem with an unaddressed gap. Taking the underlying subsystem "as given" is exactly how a standards violation survives review: the spec passes, the foundation's flaw is never weighed. When the foundation is flawed, the finding is "this spec is sound but the subsystem it depends on violates standard X / repeats mistake Y — surface it before building on/around it." Catches the "Phase 2" anti-pattern, the spec-converge-pre-auth-circular failure mode (see `feedback_spec_converge_pre_auth_circular`), and the foundation-not-audited gap (the Slack-permission-gate brittle-enum-as-authority that the harness convergence cleared because it audited only the harness, 2026-06-09).
|
|
74
74
|
|
|
75
|
-
**External
|
|
75
|
+
**External reviewers (cross-model, via the agent's own installed CLIs — one pass PER AVAILABLE FAMILY):**
|
|
76
76
|
|
|
77
|
-
The external "cross-model" pass is a
|
|
77
|
+
The external "cross-model" pass is a set of independent non-Claude reads that sit *outside* the Claude family to catch the blind spots Claude models share. It is **real**, routed through the agent's own CLI logins (`codex login` → GPT-tier, gemini OAuth → Gemini-tier; no new API key, no new network dependency), and implemented in code — NOT a hand-wave. **Family diversity is the point**: GPT and Gemini catch different failure classes, so the pass runs ONE review per available family (detect-all), not first-match-only. Run it like this:
|
|
78
78
|
|
|
79
|
-
1. **Detect**
|
|
79
|
+
1. **Detect** every supported reviewer framework that is installed + authed:
|
|
80
80
|
```bash
|
|
81
|
-
node skills/spec-converge/scripts/cross-model-review.mjs --spec <spec-path> --detect-only
|
|
81
|
+
node skills/spec-converge/scripts/cross-model-review.mjs --spec <spec-path> --detect-only --state-dir .instar
|
|
82
82
|
```
|
|
83
|
-
Returns `{ available, framework?, model?, reason? }
|
|
83
|
+
Returns `{ available, frameworks: [...all available...], framework?, model?, reason? }` (the single-framework fields remain for back-compat). `--state-dir` records the detection into the **durable framework-activation history** (`state/framework-activation-history.jsonl`) — the standing-framework baseline the mandatory-check in Phase 3 reads. `available:false` → set the fallback flag (see Phase 5) and continue internal-only **only if the mandatory-check permits it** (Phase 3). **Never block.**
|
|
84
84
|
|
|
85
|
-
2. **Run**
|
|
85
|
+
2. **Run** one external review per available family — pass the spec plus the same architectural context docs the internal reviewers receive (the docs the spec references):
|
|
86
86
|
```bash
|
|
87
87
|
node skills/spec-converge/scripts/cross-model-review.mjs \
|
|
88
|
-
--spec <spec-path> \
|
|
88
|
+
--spec <spec-path> --family codex-cli \
|
|
89
|
+
--context docs/foo.md --context docs/bar.md
|
|
90
|
+
node skills/spec-converge/scripts/cross-model-review.mjs \
|
|
91
|
+
--spec <spec-path> --family gemini-cli \
|
|
89
92
|
--context docs/foo.md --context docs/bar.md
|
|
90
93
|
```
|
|
91
|
-
|
|
94
|
+
Each emits a JSON `ReviewerResult` on stdout: `{ status, framework?, model?, verdict?, findings?, reason?, flag }`. Fold each `findings` into the round alongside the internal reviewers'. `status:'degraded'` (framework present but the call failed — timeout / error / rate-limited) is a *partial* cross-model pass for the round: fold in whatever came back and record the `degraded` flag — it does **not** collapse to `unavailable`. (Omitting `--family` keeps the old single-pass first-match behavior for existing callers.)
|
|
95
|
+
|
|
96
|
+
Two structural guards on the pass:
|
|
97
|
+
|
|
98
|
+
- **Fail-loud model canary.** Model selection is dynamic (the `'capable'` tier resolved per framework — never a pinned name), and a tier word that falls through resolution (`'capable'` is not a model) is caught by `isConcreteReviewerModel` BEFORE the provider is invoked: the round degrades loudly with reason `model-resolution-canary` instead of silently selecting a dead reviewer.
|
|
99
|
+
- **Trusted-provider allowlist.** `--family` only accepts frameworks on `TRUSTED_REVIEWER_FRAMEWORKS` (`codex-cli`, `gemini-cli` — first-party OAuth CLI adapters). The full spec text is handed to the reviewer, so it must NEVER be sent to a custom/base-URL endpoint; **pi-cli is deliberately excluded** from cross-model review for this reason (its provider may be a custom endpoint). An untrusted family is refused with `reason: 'untrusted-framework'`.
|
|
92
100
|
|
|
93
|
-
The detection + invocation + parsing live in the unit-tested `src/core/crossModelReviewer.ts` module (built to `dist/core/crossModelReviewer.js`); the script is a thin file-I/O wrapper. codex
|
|
101
|
+
The detection + invocation + parsing live in the unit-tested `src/core/crossModelReviewer.ts` module (built to `dist/core/crossModelReviewer.js`); the script is a thin file-I/O wrapper. codex and gemini are the supported frameworks in an extensible registry (`SUPPORTED_REVIEWER_FRAMEWORKS`) — further first-party CLIs plug in there with **no skill change**.
|
|
94
102
|
|
|
95
103
|
Each internal reviewer receives the spec, the architectural context docs referenced in the spec (`docs/signal-vs-authority.md`, `docs/integrated-being.md`, relevant subsystem docs), and a prompt specific to their perspective. Each produces a structured finding list.
|
|
96
104
|
|
|
97
|
-
The **six internal reviewers + the cross-model external
|
|
105
|
+
The **six internal reviewers + the cross-model external passes** run in parallel (one external read per available supported family — the honest mechanism, not three phantom API models). Their findings are collected.
|
|
98
106
|
|
|
99
107
|
**Code-backed reviewer — the Standards-Conformance Gate (auto-invoked).** Alongside the internal reviewers + the cross-model external pass, call the live gate: `POST /spec/conformance-check` with the spec (body `{ "specPath": "<path-within-specsDir>" }`, or `{ "markdown": "<spec text>" }`). Unlike the prompt-driven reviewers, the gate is *code that reads the living constitution* (`docs/STANDARDS-REGISTRY.md`) and returns a per-standard report — `ok` / `at-risk` / `n/a` + a reason for every standing standard. Fold its `at-risk` entries into the round's findings. It is the structural complement to the Lessons-aware reviewer: lessons-aware reads the lessons doc + local memory (prompt-driven); the gate reads the constitution itself (code), so a registry edit can never be silently missed. **Signal-only:** advisory — it surfaces violations, it does not block (blocking authority is the separate, later `scg-blocking-authority` follow-up, per *Signal vs. Authority*). **Fail-open:** if the gate is disabled/unreachable (503) or returns `degraded: true`, note that the constitutional pass was not authoritative and continue — a down gate must never stall spec review. (This auto-invocation is the dogfood-to-ship enforcement of the **Self-Hosting** standard — the gate now *runs* at spec-review rather than being a step the author must remember.)
|
|
100
108
|
|
|
@@ -110,7 +118,26 @@ Every update preserves the spec's structure. Changes are additive (new sections
|
|
|
110
118
|
|
|
111
119
|
### Phase 3 — Convergence check
|
|
112
120
|
|
|
113
|
-
After the spec is updated, the skill runs another full review round (the six internal reviewers + the cross-model external
|
|
121
|
+
After the spec is updated, the skill runs another full review round (the six internal reviewers + the cross-model external passes, in parallel, on the updated spec).
|
|
122
|
+
|
|
123
|
+
#### Delta-gating the external passes (mandatory, but not blindly every round)
|
|
124
|
+
|
|
125
|
+
The externals are **MANDATORY on round 1 and on any round where the spec's reviewable body changed** since the last external pass. "Changed" is decided by content hash, not memory:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
node skills/spec-converge/scripts/cross-model-review.mjs --spec <spec-path> --hash-only
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
prints `{ hash }` — `hashSpecReviewableBody`'s sha256 of the spec with the leading YAML frontmatter stripped and line endings normalized, so tag-writes and approval edits never change it. Record the hash alongside each external pass; when a later round's hash equals the last external pass's hash, the externals for that round are **skipped-with-logged-note** (the iteration log records "externals delta-skipped: body unchanged since round N, hash <prefix>"). This is the cost answer — redundant re-reviews of an unchanged spec are killed — and it does **NOT** count as `skipped-abbreviated`: the spec still received its external review of this exact content.
|
|
132
|
+
|
|
133
|
+
#### The mandatory-check (durable standing-framework baseline)
|
|
134
|
+
|
|
135
|
+
The external passes are **NON-SKIPPABLE** whenever a non-Claude framework was **active at ANY point in the last 7 days** per the durable activation history:
|
|
136
|
+
|
|
137
|
+
- The check is `wasNonClaudeFrameworkActiveWithin(stateDir, 7)` (exported from `src/core/crossModelReviewer.ts`), read from `state/framework-activation-history.jsonl` — the file every `--detect-only --state-dir` invocation appends to.
|
|
138
|
+
- A **just-before-converge deactivation does not exempt the spec**: activation is judged against the recorded lookback window, never a just-in-time reading. A framework deactivated inside the window keeps externals mandatory.
|
|
139
|
+
- A **mid-converge deactivation** (frameworks available at round 1, gone at round N) is logged in the iteration log and **fails report validation**.
|
|
140
|
+
- The advisory "externals unavailable" floor (Phase 5's `unavailable` flag) is legitimate ONLY for an agent that has been genuinely single-framework across the whole lookback — a recorded standing fact, not a 30-second-old flip.
|
|
114
141
|
|
|
115
142
|
Convergence criteria (BOTH must hold — additive, per Autonomy Principle 2):
|
|
116
143
|
|
|
@@ -186,7 +213,7 @@ review-convergence: "<ISO timestamp>"
|
|
|
186
213
|
review-iterations: <N>
|
|
187
214
|
review-completed-at: "<ISO timestamp>"
|
|
188
215
|
review-report: "docs/specs/reports/<slug>-convergence.md"
|
|
189
|
-
cross-model-review: "<flag>" # codex-cli:<model> | unavailable | degraded-all-rounds | skipped-abbreviated
|
|
216
|
+
cross-model-review: "<flag>" # codex-cli:<model> | gemini-cli:<model> | unavailable | degraded-all-rounds | skipped-abbreviated
|
|
190
217
|
cross-model-review-reason: "<reason>" # only when unavailable / degraded / degraded-all-rounds
|
|
191
218
|
single-run-completable: true # earned, not minted — written only when Open questions reached zero
|
|
192
219
|
frontloaded-decisions: <N> # count from the Decision-Completeness reviewer's final round
|
|
@@ -253,7 +280,7 @@ The convergence check is structural. If the LLM comparator finds new material is
|
|
|
253
280
|
A smaller finding count is NOT convergence. Convergence is zero material findings in a new round.
|
|
254
281
|
|
|
255
282
|
### Skipping a reviewer perspective to ship faster
|
|
256
|
-
All six internal reviewers (security, scalability, adversarial, integration, decision-completeness, lessons-aware) AND the cross-model external
|
|
283
|
+
All six internal reviewers (security, scalability, adversarial, integration, decision-completeness, lessons-aware) AND the cross-model external passes run on every round (subject to Phase 3's delta-gating — an unchanged-body round delta-skips with a logged note, which is NOT a skip of the perspective). Skipping is visible in the iteration log and fails the report validation. **Abbreviated convergence may NO LONGER skip the external pass when the 7-day activation history shows a non-Claude framework** (`wasNonClaudeFrameworkActiveWithin` — see Phase 3's mandatory-check): a framework that was active at any point in the lookback makes externals mandatory, and a just-before-converge deactivation does not exempt the spec. `cross-model-review: skipped-abbreviated` remains a legitimate record ONLY for genuinely single-framework agents (no non-Claude framework anywhere in the lookback; distinct from `unavailable`). In ALL abbreviated runs the lessons-aware AND decision-completeness reviewers MUST still run; lessons-aware is the only structural defense against the spec-converge-pre-auth-circular failure mode.
|
|
257
284
|
|
|
258
285
|
### Rewriting the spec between iterations to hide findings
|
|
259
286
|
Spec edits must address findings, not evade them. The iteration log records both the finding and the resolution. An edit that changes the spec to make the finding "not applicable" without actually solving the concern is caught at the next review round.
|
|
@@ -15,20 +15,37 @@
|
|
|
15
15
|
* access, so context must be inlined before the spawn.
|
|
16
16
|
*
|
|
17
17
|
* Modes:
|
|
18
|
-
* --detect-only Print detection JSON and exit (no
|
|
19
|
-
* { available,
|
|
18
|
+
* --detect-only Print detection JSON and exit (no spawn).
|
|
19
|
+
* { available, frameworks: [...all available...],
|
|
20
|
+
* framework?, model?, reason? } — the `frameworks`
|
|
21
|
+
* array is the Piece-3 family-diverse collection;
|
|
22
|
+
* the single-framework fields stay for back-compat.
|
|
23
|
+
* With --state-dir <dir>, also records the
|
|
24
|
+
* activation observation to the durable
|
|
25
|
+
* framework-activation history (the standing-
|
|
26
|
+
* framework baseline for the mandatory check).
|
|
27
|
+
* --hash-only Print { hash } — sha256 of the spec's reviewable
|
|
28
|
+
* body (frontmatter-stripped, CRLF-normalized) for
|
|
29
|
+
* the skill's delta-gating. Requires --spec.
|
|
20
30
|
* (default) Detect; if available, assemble the prompt + run
|
|
21
|
-
* the
|
|
31
|
+
* the review; print the ReviewerResult JSON. With
|
|
32
|
+
* --family <id>, run through THAT framework
|
|
33
|
+
* specifically (must be on the trusted first-party
|
|
34
|
+
* allowlist — spec text is never sent to a custom/
|
|
35
|
+
* base-URL endpoint; pi-cli is excluded by design).
|
|
22
36
|
*
|
|
23
37
|
* Usage:
|
|
24
38
|
* node skills/spec-converge/scripts/cross-model-review.mjs \
|
|
25
39
|
* --spec docs/specs/<slug>.md \
|
|
26
40
|
* [--context docs/foo.md --context docs/bar.md ...] \
|
|
27
|
-
* [--detect-only] \
|
|
41
|
+
* [--detect-only] [--state-dir .instar] \
|
|
42
|
+
* [--hash-only] \
|
|
43
|
+
* [--family codex-cli|gemini-cli] \
|
|
28
44
|
* [--timeout-ms 120000]
|
|
29
45
|
*
|
|
30
46
|
* Output: a single JSON object on stdout (machine-readable for the skill).
|
|
31
|
-
* On detect-only: the
|
|
47
|
+
* On detect-only: the detection JSON above.
|
|
48
|
+
* On hash-only: { hash }.
|
|
32
49
|
* On full run: the ReviewerResult ({ status, framework?, model?, verdict?,
|
|
33
50
|
* findings?, reason?, flag }).
|
|
34
51
|
*
|
|
@@ -60,19 +77,30 @@ function fail(msg) {
|
|
|
60
77
|
|
|
61
78
|
function parseArgs() {
|
|
62
79
|
const args = process.argv.slice(2);
|
|
63
|
-
const out = {
|
|
80
|
+
const out = {
|
|
81
|
+
spec: null,
|
|
82
|
+
context: [],
|
|
83
|
+
detectOnly: false,
|
|
84
|
+
hashOnly: false,
|
|
85
|
+
family: null,
|
|
86
|
+
stateDir: null,
|
|
87
|
+
timeoutMs: null,
|
|
88
|
+
};
|
|
64
89
|
for (let i = 0; i < args.length; i++) {
|
|
65
90
|
const a = args[i];
|
|
66
91
|
if (a === '--spec') out.spec = args[++i];
|
|
67
92
|
else if (a === '--context') out.context.push(args[++i]);
|
|
68
93
|
else if (a === '--detect-only') out.detectOnly = true;
|
|
94
|
+
else if (a === '--hash-only') out.hashOnly = true;
|
|
95
|
+
else if (a === '--family') out.family = args[++i];
|
|
96
|
+
else if (a === '--state-dir') out.stateDir = args[++i];
|
|
69
97
|
else if (a === '--timeout-ms') out.timeoutMs = parseInt(args[++i], 10);
|
|
70
98
|
else fail(`Unknown arg: ${a}`);
|
|
71
99
|
}
|
|
72
100
|
if (!out.detectOnly && !out.spec) {
|
|
73
101
|
fail(
|
|
74
102
|
'Usage: cross-model-review.mjs --spec PATH [--context PATH ...] ' +
|
|
75
|
-
'[--detect-only] [--timeout-ms N]',
|
|
103
|
+
'[--detect-only] [--hash-only] [--family ID] [--state-dir DIR] [--timeout-ms N]',
|
|
76
104
|
);
|
|
77
105
|
}
|
|
78
106
|
return out;
|
|
@@ -98,17 +126,81 @@ function readRepoFile(rel) {
|
|
|
98
126
|
}
|
|
99
127
|
|
|
100
128
|
async function main() {
|
|
101
|
-
const { spec, context, detectOnly, timeoutMs } = parseArgs();
|
|
129
|
+
const { spec, context, detectOnly, hashOnly, family, stateDir, timeoutMs } = parseArgs();
|
|
102
130
|
const mod = await loadModule();
|
|
103
131
|
|
|
104
|
-
//
|
|
105
|
-
|
|
132
|
+
// ── --hash-only: the delta-gating hash of the spec's reviewable body ──
|
|
133
|
+
if (hashOnly) {
|
|
134
|
+
if (!spec) fail('--hash-only requires --spec PATH');
|
|
135
|
+
const specMarkdown = readRepoFile(spec);
|
|
136
|
+
process.stdout.write(JSON.stringify({ hash: mod.hashSpecReviewableBody(specMarkdown) }) + '\n');
|
|
137
|
+
process.exit(0);
|
|
138
|
+
}
|
|
106
139
|
|
|
140
|
+
// ── --detect-only: report ALL available families (Piece 3) ──
|
|
107
141
|
if (detectOnly) {
|
|
108
|
-
|
|
142
|
+
const all = mod.detectAllCrossModelReviewers();
|
|
143
|
+
// Back-compat: keep the old single-framework fields (first-match shape).
|
|
144
|
+
const first = mod.detectCrossModelReviewer();
|
|
145
|
+
const report = {
|
|
146
|
+
available: all.length > 0,
|
|
147
|
+
frameworks: all,
|
|
148
|
+
...(first.framework ? { framework: first.framework } : {}),
|
|
149
|
+
...(first.model ? { model: first.model } : {}),
|
|
150
|
+
...(first.reason ? { reason: first.reason } : {}),
|
|
151
|
+
};
|
|
152
|
+
// Record the activation observation into the durable standing-framework
|
|
153
|
+
// baseline when a state dir was provided. A record failure is surfaced in
|
|
154
|
+
// the JSON (fail-loud), never silently swallowed — a missing baseline
|
|
155
|
+
// would quietly weaken the externals-mandatory check.
|
|
156
|
+
if (stateDir) {
|
|
157
|
+
const frameworks = {};
|
|
158
|
+
for (const entry of mod.SUPPORTED_REVIEWER_FRAMEWORKS) {
|
|
159
|
+
frameworks[entry.id] = all.some((d) => d.framework === entry.id);
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
mod.recordFrameworkActivationObservation(stateDir, { frameworks });
|
|
163
|
+
report.activationRecorded = true;
|
|
164
|
+
} catch (err) {
|
|
165
|
+
report.activationRecorded = false;
|
|
166
|
+
report.activationRecordError =
|
|
167
|
+
err instanceof Error ? err.message.slice(0, 200) : String(err);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
process.stdout.write(JSON.stringify(report) + '\n');
|
|
109
171
|
process.exit(0);
|
|
110
172
|
}
|
|
111
173
|
|
|
174
|
+
// ── full run ──
|
|
175
|
+
// --family: run through ONE specific framework. Allowlist-gated — the full
|
|
176
|
+
// spec text is never sent to a custom/base-URL endpoint (pi-cli excluded).
|
|
177
|
+
let familyEntry = null;
|
|
178
|
+
if (family) {
|
|
179
|
+
if (!mod.isTrustedReviewerFramework(family)) {
|
|
180
|
+
process.stdout.write(
|
|
181
|
+
JSON.stringify({
|
|
182
|
+
status: 'unavailable',
|
|
183
|
+
reason: 'untrusted-framework',
|
|
184
|
+
flag: 'cross-model-review: unavailable',
|
|
185
|
+
}) + '\n',
|
|
186
|
+
);
|
|
187
|
+
process.exit(0);
|
|
188
|
+
}
|
|
189
|
+
familyEntry = mod.SUPPORTED_REVIEWER_FRAMEWORKS.find((f) => f.id === family) ?? null;
|
|
190
|
+
if (!familyEntry) {
|
|
191
|
+
process.stdout.write(
|
|
192
|
+
JSON.stringify({
|
|
193
|
+
status: 'unavailable',
|
|
194
|
+
reason: 'no-supported-framework',
|
|
195
|
+
flag: 'cross-model-review: unavailable',
|
|
196
|
+
}) + '\n',
|
|
197
|
+
);
|
|
198
|
+
process.exit(0);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const detection = familyEntry ? familyEntry.detect() : mod.detectCrossModelReviewer();
|
|
203
|
+
|
|
112
204
|
// Unavailable → print the unavailable flag, exit 0. Never block.
|
|
113
205
|
if (!detection.available) {
|
|
114
206
|
const flag = mod.buildCrossModelFlag('unavailable', detection.reason);
|
|
@@ -130,10 +222,16 @@ async function main() {
|
|
|
130
222
|
context: contextDocs,
|
|
131
223
|
});
|
|
132
224
|
|
|
133
|
-
const result =
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
225
|
+
const result = familyEntry
|
|
226
|
+
? await familyEntry.review({
|
|
227
|
+
promptText: assembled.promptText,
|
|
228
|
+
timeoutMs: Number.isFinite(timeoutMs) ? timeoutMs : mod.REVIEW_TIMEOUT_MS,
|
|
229
|
+
detectionOverride: detection,
|
|
230
|
+
})
|
|
231
|
+
: await mod.runCrossModelReview({
|
|
232
|
+
assembled,
|
|
233
|
+
...(Number.isFinite(timeoutMs) ? { timeoutMs } : {}),
|
|
234
|
+
});
|
|
137
235
|
|
|
138
236
|
// Surface truncation in the emitted result so the skill/report can note it.
|
|
139
237
|
process.stdout.write(JSON.stringify({ ...result, promptTruncated: assembled.truncated }) + '\n');
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-06-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-06-11T00:03:52.959Z",
|
|
5
|
+
"instarVersion": "1.3.484",
|
|
6
6
|
"entryCount": 201,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: minor -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
Implements Piece 3 (final piece) of `docs/specs/AUTONOMY-PRINCIPLES-ENFORCEMENT-SPEC.md`. The spec-converge skill's external (non-Claude) review pass becomes mandatory with teeth, dynamic, and safe:
|
|
9
|
+
|
|
10
|
+
- **gemini-cli joins the reviewer registry** (`src/core/crossModelReviewer.ts`) — the registry seam's first extension beyond codex: never-throws detection (binary + cached OAuth at the path the CLI actually reads), provider via the existing factory with its own circuit breaker, identical degraded semantics.
|
|
11
|
+
- **Family-diverse**: one external pass per AVAILABLE family (detect-all), not first-match-only.
|
|
12
|
+
- **Delta-gated**: a content hash of the spec's reviewable body (frontmatter-stripped) decides when externals must re-run — round 1 and any changed round; unchanged rounds record a skip-with-logged-note instead of burning external quota.
|
|
13
|
+
- **Durable activation baseline**: framework availability observations are recorded to `state/framework-activation-history.jsonl`; externals are non-skippable whenever a non-Claude framework was active within a 7-day lookback — deactivating a framework just before converging no longer exempts a spec.
|
|
14
|
+
- **Trusted-provider allowlist**: only first-party OAuth CLIs (codex-cli, gemini-cli) can receive spec text; pi-cli/custom endpoints are structurally excluded (`untrusted-framework` refusal).
|
|
15
|
+
- **Fail-loud model canary**: a review pass degrades loudly (`model-resolution-canary`) rather than silently running with an unresolved tier-word model.
|
|
16
|
+
|
|
17
|
+
Honest scope notes: the spec's "broken `resolveModelForFramework` foundation" was already fixed on main before this build (recorded at PR #1055); the Claude-only-agent different-family floor + tracked-gap signal are disclosed residuals (see the side-effects artifact).
|
|
18
|
+
|
|
19
|
+
## What to Tell Your User
|
|
20
|
+
|
|
21
|
+
- "When I review a spec before building, I now get a second opinion from EVERY non-Claude AI family I have access to (GPT via codex, Gemini via the gemini CLI) — automatically, on every round where the spec actually changed. I can't quietly skip it anymore: a record of which frameworks I've had active in the last week keeps the outside-opinion requirement honest."
|
|
22
|
+
- "Your spec text only ever goes to first-party AI providers you've logged into — never to custom or unknown endpoints."
|
|
23
|
+
|
|
24
|
+
## Summary of New Capabilities
|
|
25
|
+
|
|
26
|
+
| Capability | How to Use |
|
|
27
|
+
|-----------|-----------|
|
|
28
|
+
| Gemini external reviewer | Automatic in spec-converge when the gemini CLI is installed + authed |
|
|
29
|
+
| Family-diverse external pass | Automatic — one pass per available family per changed round |
|
|
30
|
+
| Delta-gated externals | Automatic — unchanged rounds log a skip note instead of re-reviewing |
|
|
31
|
+
| 7-day activation baseline | Automatic — recorded on every detection; read at convergence |
|
|
32
|
+
|
|
33
|
+
## Evidence
|
|
34
|
+
|
|
35
|
+
- 32 new unit tests (`crossModelReviewer-piece3.test.ts`) + 45 existing (`crossModelReviewer.test.ts`) + 3 integration (`cross-model-review-flow.test.ts`) — all green; `tsc` exit 0; full lint clean.
|
|
36
|
+
- Live smoke on the dev machine: detect-all reported codex-cli:gpt-5.5 AND gemini-cli:gemini-2.5-pro; `--family pi-cli` refused with `untrusted-framework`; the activation observation landed in the JSONL.
|
|
37
|
+
- Independent second-pass review verified the egress allowlist end-to-end and caught a real bug (a `GEMINI_HOME` env var the CLI doesn't actually honor) — fixed before ship.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Side-Effects Review — Cross-Model Convergence Hardening (Autonomy Principles Enforcement, Piece 3)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `cross-model-hardening`
|
|
4
|
+
**Date:** `2026-06-10`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `independent reviewer subagent (see appended verdict)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Implements Piece 3 of `docs/specs/AUTONOMY-PRINCIPLES-ENFORCEMENT-SPEC.md`: cross-model convergence becomes **mandatory (with a durable activation baseline), dynamic (no pinning), family-diverse, delta-gated, allowlist-constrained, and fail-loud**. Honest scope note: the spec's headline "broken foundation" claim (`resolveModelForFramework` returning a dead tier string for gemini/pi) was **already fixed on main** before this build — recorded at PR #1055; this PR implements everything else.
|
|
11
|
+
|
|
12
|
+
- **gemini-cli reviewer registry entry** (`src/core/crossModelReviewer.ts`) — the registry seam's first extension beyond codex: injectable never-throws detection (binary + cached OAuth creds), provider via the existing factory (own circuit breaker), identical degraded semantics.
|
|
13
|
+
- **Family-diverse collection** — `detectAllCrossModelReviewers()` returns ALL available frameworks; the skill now runs one external pass per available family instead of first-match-only.
|
|
14
|
+
- **Delta-gating** — `hashSpecReviewableBody()` (sha256, frontmatter-stripped, CRLF-normalized); externals are mandatory on round 1 + any round where the reviewable body changed; an unchanged round records a skip-with-logged-note (≠ skipped-abbreviated).
|
|
15
|
+
- **Durable activation baseline** — `recordFrameworkActivationObservation()` / `wasNonClaudeFrameworkActiveWithin()` (JSONL at `state/framework-activation-history.jsonl`, 2000-line cap): externals are non-skippable whenever a non-Claude framework was active at any point in a 7-day lookback — a just-before-converge deactivation no longer exempts a spec (round-2 adversarial F-R2-3).
|
|
16
|
+
- **Trusted-provider allowlist** — `TRUSTED_REVIEWER_FRAMEWORKS = ['codex-cli','gemini-cli']`; the registry constructively carries only first-party OAuth CLIs; `--family pi-cli` (or any unlisted id) is refused (`untrusted-framework`) so the full spec text is never sent to a custom/base-URL endpoint.
|
|
17
|
+
- **Fail-loud canary** — `isConcreteReviewerModel()`: both entries degrade LOUDLY (`model-resolution-canary`) rather than silently reviewing with a bare tier word.
|
|
18
|
+
|
|
19
|
+
Files: `src/core/crossModelReviewer.ts`, `skills/spec-converge/scripts/cross-model-review.mjs`, `skills/spec-converge/SKILL.md`, `tests/unit/crossModelReviewer-piece3.test.ts` (new, 32 tests), hermeticity fixes in 2 existing test files.
|
|
20
|
+
|
|
21
|
+
## Decision-point inventory
|
|
22
|
+
|
|
23
|
+
- Cross-model framework detection/selection — **modify** — first-match → all-available (collection only; no blocking authority).
|
|
24
|
+
- `--family` allowlist guard — **add** — hard-invariant refusal of an untrusted framework id at the script edge (egress protection, enumerable set).
|
|
25
|
+
- Externals-mandatory check (SKILL.md + `wasNonClaudeFrameworkActiveWithin`) — **add** — a deterministic read over the durable history that decides whether the SKILL FLOW may skip an external pass. Process-gating inside spec review; blocks no agent action or message.
|
|
26
|
+
- Model canary — **add** — degrades a review pass; blocks nothing.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 1. Over-block
|
|
31
|
+
|
|
32
|
+
The allowlist refusing `pi-cli` could be seen as over-blocking a legitimate reviewer — deliberate: pi is multi-provider by design (its model flag may resolve to a custom endpoint), and the cost of a wrongly-allowed egress (full spec text to an attacker-controlled model) dwarfs the cost of one fewer reviewer family. The activation lookback could keep externals mandatory for an agent that genuinely uninstalled a framework yesterday — accepted: the 7-day tail is the entire point (anti-gaming), and the pass degrades to advisory-unavailable rather than hard-failing when the framework is truly gone.
|
|
33
|
+
|
|
34
|
+
## 2. Under-block
|
|
35
|
+
|
|
36
|
+
The activation history only records when `--detect-only`/review runs execute — an agent that NEVER ran spec-converge in the lookback has an empty history and presents as single-framework. Acceptable: the first detect of the current convergence records the observation, so the gaming window is "deactivate before the FIRST round" — and a genuinely deactivated-everywhere agent degrades to the advisory floor exactly as specced. The history is also local-file mutable by the agent itself (not tamper-proof) — consistent with every other instar state file; the report banner + frontmatter flag remain the human-visible disclosure.
|
|
37
|
+
|
|
38
|
+
## 3. Level-of-abstraction fit
|
|
39
|
+
|
|
40
|
+
Correct: detection/selection/hash/history are cheap structural helpers in the existing crossModelReviewer module (the registry's documented extension point); the SKILL owns the flow policy; nothing re-implements the provider factory, circuit breaker, or aggregation (`aggregateRoundOutcomes` unchanged and still computes the spec-level flag).
|
|
41
|
+
|
|
42
|
+
## 4. Signal vs authority compliance
|
|
43
|
+
|
|
44
|
+
**Required reference:** docs/signal-vs-authority.md
|
|
45
|
+
|
|
46
|
+
- [x] No — no block/allow surface over agent behavior or messages. The two refusal points (allowlist, canary) are **hard-invariant validation** over enumerable sets (the principle's explicitly-allowed class — egress protection is the "safety guards on irreversible actions" case). Review outcomes only ever DEGRADE with logged reasons; judgment stays with the reviewers and the convergence process.
|
|
47
|
+
|
|
48
|
+
## 5. Interactions
|
|
49
|
+
|
|
50
|
+
- **Back-compat:** `detectCrossModelReviewer` (first-match) and the script's default single-pass mode are unchanged; existing callers/tests pass (hermeticity fixes only — the suite previously assumed gemini absent, false on hosts with gemini installed).
|
|
51
|
+
- **Aggregation:** per-family results feed the existing per-round → spec-level aggregation unchanged; a delta-skip is recorded as a logged note, not a round outcome, so `degraded-all-rounds` semantics are preserved.
|
|
52
|
+
- **Double-fire/races:** the activation JSONL is append-with-cap from a single skill flow; worst case under concurrent convergences is a lost observation line (history is a union-over-time read, so this cannot flip mandatory→optional within the lookback).
|
|
53
|
+
- **Circuit breakers:** each framework keeps its own breaker via the factory — a rate-limited codex degrades that pass; gemini still runs (the family-diversity goal).
|
|
54
|
+
|
|
55
|
+
## 6. External surfaces
|
|
56
|
+
|
|
57
|
+
- **LLM egress:** spec text now also flows to gemini (first-party Google OAuth CLI) when available — the same egress class as the existing codex pass, now explicitly allowlist-bounded. No new third-party endpoints; pi/custom endpoints structurally excluded.
|
|
58
|
+
- **Persistent state:** `state/framework-activation-history.jsonl` (capped). No fleet surface: spec-converge remains agent-private (decision recorded in the Piece-2 artifact); no `src/` runtime route/config change — `crossModelReviewer.ts` is library code consumed by the skill script.
|
|
59
|
+
|
|
60
|
+
## 7. Rollback cost
|
|
61
|
+
|
|
62
|
+
Revert the commit. The history file is inert if orphaned. No migration, no API, no fleet propagation.
|
|
63
|
+
|
|
64
|
+
## Conclusion
|
|
65
|
+
|
|
66
|
+
Piece 3 closes the spec: externals can no longer be quietly skipped (durable 7-day baseline + delta-gating with logged notes), selection is dynamic and family-diverse with zero pinned model names, and the two real security findings from convergence (spec egress to untrusted endpoints; silent dead-model reviews) are structurally closed (allowlist + canary). Verified: tsc clean, full lint clean, 77 unit (45 existing + 32 new) + 3 integration green, live smoke on this host detected both codex + gemini and refused pi-cli. Clear to ship as the final PR of the spec.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Scope disclosure (honest residual)
|
|
71
|
+
|
|
72
|
+
Two spec clauses are NOT implemented in this PR and are tracked, not orphaned <!-- tracked: CMT-1317 -->: (a) the Claude-only-agent floor reaching a *different-family* model via the subscription-path/provider-registry fallback — a single-framework agent currently gets the honest advisory `unavailable` flag (the pre-existing behavior, loudly disclosed in the report banner), and (b) surfacing "no external family reachable at all" as a HumanAsDetector-style tracked-gap signal rather than the advisory note. Both need provider-registry plumbing that doesn't belong in this hardening pass.
|
|
73
|
+
|
|
74
|
+
## Second-pass review
|
|
75
|
+
|
|
76
|
+
**Reviewer:** independent reviewer subagent (verified findings against the actually-installed gemini CLI v0.25.2).
|
|
77
|
+
**Independent read of the artifact: concern raised → all resolved this pass.**
|
|
78
|
+
|
|
79
|
+
- MUST-FIX (resolved): `GEMINI_HOME` is not a real gemini CLI env var (zero occurrences in the CLI dist; creds are unconditionally `~/.gemini/oauth_creds.json`). Honoring it made detection probe a path the CLI never reads — a false-unavailable would silently skip the gemini pass AND poison the activation baseline with `gemini-cli:false`, the exact suppression Piece 3 prevents. Fixed: env lookup dropped; injectable test seam kept.
|
|
80
|
+
- NICE-TO-HAVE (applied): frontmatter-strip close anchor tightened to a whole-line fence (`\n---(\n|$)`) so `--- text`/`----` inside the block can't terminate the strip mid-line.
|
|
81
|
+
- INFORMATIONAL (applied anyway): `wasNonClaudeFrameworkActiveWithin` now counts only TRUSTED reviewer framework ids, so a stray `{"claude-code":true}` line can't flip the externals-mandatory decision.
|
|
82
|
+
- HONESTY (applied): the scope disclosure above was added at the reviewer's prompting — the artifact previously implied full Piece-3 coverage.
|
|
83
|
+
- Confirmed clean: `--family` allowlist guard sits before any detect/provider call; no path (default, detect-all, or detectionOverride) can route spec text to a non-registry framework — the registry⊆allowlist invariant is itself unit-tested; `buildIntelligenceProvider({framework:'gemini-cli'})` cannot reach a custom base-URL (allowlisted child env); refresh-token-only IS authed for this CLI; the canary precedes provider construction in both entries; the 2000-line cap keeps the most recent lines; the reader never throws on corruption; the existing-test edits weaken no assertion.
|
|
84
|
+
|
|
85
|
+
After fixes: tsc exit 0, 77/77 unit + 3/3 integration green.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Evidence pointers
|
|
90
|
+
|
|
91
|
+
- `tests/unit/crossModelReviewer-piece3.test.ts` (32): gemini detect triad, detect-all cardinality, canary accept/reject, hash frontmatter/CRLF stability, activation write/read/lookback/corrupt-line/cap, allowlist, gemini degraded paths.
|
|
92
|
+
- Live smoke: `--detect-only --state-dir` → codex-cli:gpt-5.5 + gemini-cli:gemini-2.5-pro both detected + observation written; `--family pi-cli` → `untrusted-framework`; `--hash-only` → stable hash.
|
|
93
|
+
- `npx tsc --noEmit` exit 0; `npm run lint` exit 0.
|