instar 1.3.763 → 1.3.765
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/ClaudeCliIntelligenceProvider.d.ts +15 -0
- package/dist/core/ClaudeCliIntelligenceProvider.d.ts.map +1 -1
- package/dist/core/ClaudeCliIntelligenceProvider.js +111 -23
- package/dist/core/ClaudeCliIntelligenceProvider.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +1 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +56 -2
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/crossModelReviewer.d.ts +188 -9
- package/dist/core/crossModelReviewer.d.ts.map +1 -1
- package/dist/core/crossModelReviewer.js +360 -18
- package/dist/core/crossModelReviewer.js.map +1 -1
- package/dist/core/types.d.ts +14 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/scaffold/templates.js +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +15 -5
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/scripts/model-registry-freshness.manifest.json +8 -0
- package/skills/spec-converge/SKILL.md +4 -2
- package/skills/spec-converge/scripts/cross-model-review.mjs +36 -6
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates.ts +1 -1
- package/upgrades/1.3.764.md +45 -0
- package/upgrades/1.3.765.md +63 -0
- package/upgrades/side-effects/actionclaim-config-shape-fix.eli16.md +50 -0
- package/upgrades/side-effects/actionclaim-config-shape-fix.md +149 -0
- package/upgrades/side-effects/reviewer-door-rewiring-inc1.md +198 -0
package/package.json
CHANGED
|
@@ -91,6 +91,14 @@
|
|
|
91
91
|
"file": "src/core/ModelTierEscalation.ts",
|
|
92
92
|
"regex": "'claude-code':\\s*\\{\\s*default:\\s*'([^']+)',\\s*escalated:\\s*'([^']+)'",
|
|
93
93
|
"note": "DEFAULT_TIER_ESCALATION.frameworks['claude-code'] default + escalated ids."
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"id": "claude-clean-door-reviewer-default",
|
|
97
|
+
"door": "claude-code",
|
|
98
|
+
"tier": "capable",
|
|
99
|
+
"file": "src/core/crossModelReviewer.ts",
|
|
100
|
+
"regex": "CLAUDE_REVIEWER_DEFAULT_MODEL\\s*=\\s*'((?:claude|gpt|gemini)-[^']+)'",
|
|
101
|
+
"note": "CLAUDE_REVIEWER_DEFAULT_MODEL — the Anthropic clean-door reviewer pin (REVIEWER-DOOR-REWIRING §1.3). Extraction matches a frontier CONSTANT (not a capable:'…' tier decl), so the non-vacuity test (tests/unit/model-registry-freshness-reviewer-pin.test.ts) rots this constant and asserts the strict lint fails — closing the vacuous-tooth risk."
|
|
94
102
|
}
|
|
95
103
|
],
|
|
96
104
|
"$flaggedStaleNote": "Both prior flagged pins RESOLVED (operator-confirmed 2026-07-03): gemini capable swapped gemini-2.5-pro -> gemini-3.1-pro-preview (pin + topModels updated in the same change); codex capable stays gpt-5.5 (GA flagship — gpt-5.6-sol is preview-only/gov-gated/unreachable, NOT pinned). Nothing pending confirmation.",
|
|
@@ -115,12 +115,14 @@ The external "cross-model" pass is a set of independent non-Claude reads that si
|
|
|
115
115
|
--spec <spec-path> --family gemini-cli \
|
|
116
116
|
--context docs/foo.md --context docs/bar.md
|
|
117
117
|
```
|
|
118
|
-
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.)
|
|
118
|
+
Each emits a JSON `ReviewerResult` on stdout: `{ status, framework?, model?, verdict?, findings?, reason?, flag, crossFamily }`. 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.)
|
|
119
|
+
|
|
120
|
+
**Anthropic clean-door reviewer (`--family claude-code`) — a clean-door SECOND READ, NOT a cross-model opinion (REVIEWER-DOOR-REWIRING).** A third family reads the spec through the clean `claude -p` door on the strongest model (`claude-fable-5`), off the measured-penalized `opus × coding-harness` pair. It is **config-gated** (`specConverge.reviewers.anthropic.enabled` — omitted ⇒ live on a development agent, DARK on the fleet) and its result carries `crossFamily: false`, so it books into its OWN disclosure field **`clean-door-anthropic-review: claude-code:<model>`** — NEVER the `cross-model-review:` flag. A claude-only round therefore aggregates to `degraded-all-rounds`/`unavailable` exactly as before; the clean-door read can never launder a cross-model pass. Run it (when enabled) exactly like the others: `--family claude-code`. **D7 per-round-model disclosure:** the six INTERNAL reviewers run on the authoring session's model (opus, or `claude-fable-5` under tier-escalation — a quota-refused escalation silently drops them to opus-via-harness); record the ACTUAL per-round session/subagent model in the iteration log so a silent drop to opus is VISIBLE, not assumed.
|
|
119
121
|
|
|
120
122
|
Two structural guards on the pass:
|
|
121
123
|
|
|
122
124
|
- **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.
|
|
123
|
-
- **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'
|
|
125
|
+
- **Trusted-provider allowlist.** `--family` only accepts frameworks on `TRUSTED_REVIEWER_FRAMEWORKS` (`codex-cli`, `gemini-cli`, `claude-code` — 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'`; a trusted-but-config-disabled family (the `claude-code` clean-door family on the fleet) is refused with `reason: 'no-supported-framework'` (trusted-egress ≠ enabled). The `claude-code` clean-door call is additionally hardened to codex-door parity for the untrusted spec text (empty allowed-tools, `--strict-mcp-config`, neutral scratch cwd, stdin prompt, env allowlist) — a spec under review is untrusted inbound text.
|
|
124
126
|
|
|
125
127
|
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**.
|
|
126
128
|
|
|
@@ -125,9 +125,33 @@ function readRepoFile(rel) {
|
|
|
125
125
|
return fs.readFileSync(abs, 'utf-8');
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Read the minimal reviewer config the module needs (REVIEWER-DOOR-REWIRING
|
|
130
|
+
* §1.5): the developmentAgent gate flag + the `specConverge.reviewers` block, so
|
|
131
|
+
* the Anthropic clean-door family resolves live-on-dev / dark-fleet. Best-effort:
|
|
132
|
+
* a missing/unparseable `.instar/config.json` ⇒ `{}` ⇒ fleet-dark (byte-identical
|
|
133
|
+
* `[codex, gemini]`). `.instar/config.json` is machine-local (no config
|
|
134
|
+
* replication in instar) — enabling the family is a per-machine edit.
|
|
135
|
+
*/
|
|
136
|
+
function loadReviewerConfig() {
|
|
137
|
+
try {
|
|
138
|
+
const cfgPath = path.join(ROOT, '.instar', 'config.json');
|
|
139
|
+
if (!fs.existsSync(cfgPath)) return {};
|
|
140
|
+
const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf-8'));
|
|
141
|
+
const out = {};
|
|
142
|
+
if (typeof cfg.developmentAgent === 'boolean') out.developmentAgent = cfg.developmentAgent;
|
|
143
|
+
if (cfg.specConverge && typeof cfg.specConverge === 'object') out.specConverge = cfg.specConverge;
|
|
144
|
+
return out;
|
|
145
|
+
} catch {
|
|
146
|
+
return {};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
128
150
|
async function main() {
|
|
129
151
|
const { spec, context, detectOnly, hashOnly, family, stateDir, timeoutMs } = parseArgs();
|
|
130
152
|
const mod = await loadModule();
|
|
153
|
+
// Config-gate the Anthropic clean-door family (§1.5). Absent config ⇒ fleet-dark.
|
|
154
|
+
const reviewerConfig = loadReviewerConfig();
|
|
131
155
|
|
|
132
156
|
// ── --hash-only: the delta-gating hash of the spec's reviewable body ──
|
|
133
157
|
if (hashOnly) {
|
|
@@ -139,9 +163,9 @@ async function main() {
|
|
|
139
163
|
|
|
140
164
|
// ── --detect-only: report ALL available families (Piece 3) ──
|
|
141
165
|
if (detectOnly) {
|
|
142
|
-
const all = mod.detectAllCrossModelReviewers();
|
|
166
|
+
const all = mod.detectAllCrossModelReviewers({}, reviewerConfig);
|
|
143
167
|
// Back-compat: keep the old single-framework fields (first-match shape).
|
|
144
|
-
const first = mod.detectCrossModelReviewer();
|
|
168
|
+
const first = mod.detectCrossModelReviewer({}, reviewerConfig);
|
|
145
169
|
const report = {
|
|
146
170
|
available: all.length > 0,
|
|
147
171
|
frameworks: all,
|
|
@@ -152,10 +176,11 @@ async function main() {
|
|
|
152
176
|
// Record the activation observation into the durable standing-framework
|
|
153
177
|
// baseline when a state dir was provided. A record failure is surfaced in
|
|
154
178
|
// the JSON (fail-loud), never silently swallowed — a missing baseline
|
|
155
|
-
// would quietly weaken the externals-mandatory check.
|
|
179
|
+
// would quietly weaken the externals-mandatory check. Iterate the ACTIVE
|
|
180
|
+
// set so a config-disabled claude family is not recorded as present.
|
|
156
181
|
if (stateDir) {
|
|
157
182
|
const frameworks = {};
|
|
158
|
-
for (const entry of mod.
|
|
183
|
+
for (const entry of mod.resolveActiveReviewerFrameworks(reviewerConfig)) {
|
|
159
184
|
frameworks[entry.id] = all.some((d) => d.framework === entry.id);
|
|
160
185
|
}
|
|
161
186
|
try {
|
|
@@ -186,7 +211,10 @@ async function main() {
|
|
|
186
211
|
);
|
|
187
212
|
process.exit(0);
|
|
188
213
|
}
|
|
189
|
-
|
|
214
|
+
// Config gate (§1.5): a trusted-but-disabled family (the claude clean-door
|
|
215
|
+
// family on the fleet) is refused here — trusted-egress ≠ enabled.
|
|
216
|
+
const active = mod.resolveActiveReviewerFrameworks(reviewerConfig);
|
|
217
|
+
familyEntry = active.find((f) => f.id === family) ?? null;
|
|
190
218
|
if (!familyEntry) {
|
|
191
219
|
process.stdout.write(
|
|
192
220
|
JSON.stringify({
|
|
@@ -199,7 +227,7 @@ async function main() {
|
|
|
199
227
|
}
|
|
200
228
|
}
|
|
201
229
|
|
|
202
|
-
const detection = familyEntry ? familyEntry.detect() : mod.detectCrossModelReviewer();
|
|
230
|
+
const detection = familyEntry ? familyEntry.detect() : mod.detectCrossModelReviewer({}, reviewerConfig);
|
|
203
231
|
|
|
204
232
|
// Unavailable → print the unavailable flag, exit 0. Never block.
|
|
205
233
|
if (!detection.available) {
|
|
@@ -227,9 +255,11 @@ async function main() {
|
|
|
227
255
|
promptText: assembled.promptText,
|
|
228
256
|
timeoutMs: Number.isFinite(timeoutMs) ? timeoutMs : mod.REVIEW_TIMEOUT_MS,
|
|
229
257
|
detectionOverride: detection,
|
|
258
|
+
reviewerConfig,
|
|
230
259
|
})
|
|
231
260
|
: await mod.runCrossModelReview({
|
|
232
261
|
assembled,
|
|
262
|
+
config: reviewerConfig,
|
|
233
263
|
...(Number.isFinite(timeoutMs) ? { timeoutMs } : {}),
|
|
234
264
|
});
|
|
235
265
|
|