instar 1.3.744 → 1.3.746
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/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +13 -3
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/monitoring/delivery-failure-sentinel/recovery-policy.d.ts +7 -0
- package/dist/monitoring/delivery-failure-sentinel/recovery-policy.d.ts.map +1 -1
- package/dist/monitoring/delivery-failure-sentinel/recovery-policy.js +47 -0
- package/dist/monitoring/delivery-failure-sentinel/recovery-policy.js.map +1 -1
- package/dist/server/routes.d.ts +23 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +112 -16
- package/dist/server/routes.js.map +1 -1
- package/package.json +4 -2
- package/scripts/lint-model-registry-freshness.mjs +192 -0
- package/scripts/model-registry-freshness.manifest.json +104 -0
- package/src/data/builtin-manifest.json +65 -65
- package/src/templates/scripts/slack-reply.sh +30 -0
- package/src/templates/scripts/telegram-reply.sh +50 -5
- package/upgrades/1.3.745.md +19 -0
- package/upgrades/1.3.746.md +43 -0
- package/upgrades/side-effects/model-registry-freshness-guard.md +53 -0
- package/upgrades/side-effects/slack-outbound-robustness-r8m1-arm-b-adapter-timeout.md +76 -0
- package/upgrades/side-effects/slack-outbound-robustness-r8m1-recovery-policy.md +110 -0
- package/upgrades/side-effects/slack-outbound-robustness-slack-delivery-id.md +83 -0
- package/upgrades/side-effects/slack-outbound-robustness-slack-forward-refusal.md +74 -0
- package/upgrades/side-effects/slack-outbound-robustness-telegram-prepost-mint.md +81 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "instar",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.746",
|
|
4
4
|
"description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -28,9 +28,11 @@
|
|
|
28
28
|
"test:contract": "node scripts/run-contract-tests.js",
|
|
29
29
|
"test:contract:raw": "vitest run --config vitest.contract.config.ts",
|
|
30
30
|
"test:all": "vitest run && vitest run --config vitest.integration.config.ts && vitest run --config vitest.e2e.config.ts",
|
|
31
|
-
"lint": "tsc --noEmit && node scripts/lint-no-direct-destructive.js && node scripts/lint-no-direct-llm-http.js && node scripts/lint-no-direct-url-log.js && node scripts/lint-no-unfunneled-topic-creation.js && node scripts/lint-no-unfunneled-headless-launch.js && node scripts/lint-no-unbounded-llm-spawn.js && node scripts/lint-no-unfunneled-credential-write.js && node scripts/lint-state-registry.js && node scripts/lint-store-retention-declared.js && node scripts/lint-no-wholefile-sync-read.js && node scripts/lint-cas-emit-placement.js && node scripts/lint-journal-actuation-ban.js && node scripts/lint-no-blocking-process-scans.js && node scripts/lint-sync-subprocess-chokepoint.js && node scripts/lint-dev-agent-dark-gate.js && node scripts/lint-guard-manifest.js && node scripts/lint-llm-attribution.js && node scripts/lint-no-mainthread-cartographer-walk.js && node scripts/lint-scrape-fixture-realness.js && node scripts/check-codex-rule1-drift.js && node scripts/lint-routing-registry-freshness.js && node scripts/lint-no-opus-claude-cli-gating.js",
|
|
31
|
+
"lint": "tsc --noEmit && node scripts/lint-no-direct-destructive.js && node scripts/lint-no-direct-llm-http.js && node scripts/lint-no-direct-url-log.js && node scripts/lint-no-unfunneled-topic-creation.js && node scripts/lint-no-unfunneled-headless-launch.js && node scripts/lint-no-unbounded-llm-spawn.js && node scripts/lint-no-unfunneled-credential-write.js && node scripts/lint-state-registry.js && node scripts/lint-store-retention-declared.js && node scripts/lint-no-wholefile-sync-read.js && node scripts/lint-cas-emit-placement.js && node scripts/lint-journal-actuation-ban.js && node scripts/lint-no-blocking-process-scans.js && node scripts/lint-sync-subprocess-chokepoint.js && node scripts/lint-dev-agent-dark-gate.js && node scripts/lint-guard-manifest.js && node scripts/lint-llm-attribution.js && node scripts/lint-no-mainthread-cartographer-walk.js && node scripts/lint-scrape-fixture-realness.js && node scripts/check-codex-rule1-drift.js && node scripts/lint-routing-registry-freshness.js && node scripts/lint-no-opus-claude-cli-gating.js && node scripts/lint-model-registry-freshness.mjs",
|
|
32
32
|
"lint:routing-registry": "node scripts/lint-routing-registry-freshness.js",
|
|
33
33
|
"lint:no-opus-claude-cli-gating": "node scripts/lint-no-opus-claude-cli-gating.js",
|
|
34
|
+
"lint:model-freshness": "node scripts/lint-model-registry-freshness.mjs",
|
|
35
|
+
"lint:model-freshness:strict": "INSTAR_MODEL_FRESHNESS_STRICT=1 node scripts/lint-model-registry-freshness.mjs",
|
|
34
36
|
"lint:no-unbounded-llm-spawn": "node scripts/lint-no-unbounded-llm-spawn.js",
|
|
35
37
|
"lint:no-unbounded-llm-spawn:staged": "node scripts/lint-no-unbounded-llm-spawn.js --staged",
|
|
36
38
|
"lint:destructive": "node scripts/lint-no-direct-destructive.js",
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* lint-model-registry-freshness.mjs — the model-registry FRESHNESS ratchet.
|
|
4
|
+
*
|
|
5
|
+
* THE PROBLEM (2026-07-03, operator directive): Instar's per-provider "capable/
|
|
6
|
+
* latest/frontier" model pins rot SILENTLY. Nothing forces anyone to re-check
|
|
7
|
+
* that (e.g.) the gemini `capable` tier still points at a current model — so
|
|
8
|
+
* `gemini-2.5-pro` kept routing spec-review/converge work long after
|
|
9
|
+
* Gemini 3-class shipped. A stale pin is invisible until it degrades output.
|
|
10
|
+
*
|
|
11
|
+
* THE GUARD (model-id-AGNOSTIC by construction): a deterministic check with
|
|
12
|
+
* TWO teeth, both driven by scripts/model-registry-freshness.manifest.json —
|
|
13
|
+
* the single human-edit surface:
|
|
14
|
+
*
|
|
15
|
+
* TOOTH 1 — STALENESS. `lastReviewedAt` must be within `stalenessWindowDays`
|
|
16
|
+
* of today. An un-reviewed list ages out and fails LOUDLY, forcing a
|
|
17
|
+
* periodic "is each pin still frontier?" review + a date bump. This is the
|
|
18
|
+
* anti-rot mechanism: it fails even if no id ever changes.
|
|
19
|
+
*
|
|
20
|
+
* TOOTH 2 — DRIFT. Every pinned capable/latest model id (extracted live from
|
|
21
|
+
* the real source files via each pin's regex) must be a member of that
|
|
22
|
+
* door's `frontierAllowlist` (the CURRENT_FRONTIER_MODELS set). A pin that
|
|
23
|
+
* names a model not in the maintained allowlist fails — either the pin is
|
|
24
|
+
* stale, or the allowlist wasn't updated. To go green a human must reconcile
|
|
25
|
+
* the two, which IS the review.
|
|
26
|
+
*
|
|
27
|
+
* Plus: `flaggedStale[]` entries (known-stale-pending-operator-confirmation) are
|
|
28
|
+
* always printed as WARN lines and, under strict enforcement, count as findings.
|
|
29
|
+
*
|
|
30
|
+
* The guard NEVER hard-codes what the "right" model id is — it only asserts the
|
|
31
|
+
* pins and the allowlist agree and that the review is fresh. Swapping to a new
|
|
32
|
+
* frontier id is a manifest edit (allowlist + date), never a code change here.
|
|
33
|
+
*
|
|
34
|
+
* ENFORCEMENT (dark/reversible): manifest `enforcement` field —
|
|
35
|
+
* "report" (default) — prints findings, ALWAYS exits 0 (non-gating). Safe to
|
|
36
|
+
* wire into CI today while the current list is known-stale: it stays VISIBLE
|
|
37
|
+
* in the lint log without breaking the build.
|
|
38
|
+
* "strict" — exits 1 on any finding (staleness, drift, or a flaggedStale row).
|
|
39
|
+
* Flip here once the flagged door swaps are operator-confirmed + applied.
|
|
40
|
+
* Env INSTAR_MODEL_FRESHNESS_STRICT=1 forces strict for a one-off run.
|
|
41
|
+
*
|
|
42
|
+
* Exit codes:
|
|
43
|
+
* 0 — no findings, OR findings under "report" enforcement (non-gating).
|
|
44
|
+
* 1 — findings under "strict" enforcement, or a manifest/parse error.
|
|
45
|
+
*
|
|
46
|
+
* Usage:
|
|
47
|
+
* node scripts/lint-model-registry-freshness.mjs # honor manifest enforcement
|
|
48
|
+
* INSTAR_MODEL_FRESHNESS_STRICT=1 node scripts/lint-model-registry-freshness.mjs
|
|
49
|
+
*
|
|
50
|
+
* Test overrides:
|
|
51
|
+
* INSTAR_MODEL_FRESHNESS_MANIFEST=<path> # point at a fixture manifest
|
|
52
|
+
* INSTAR_MODEL_FRESHNESS_ROOT=<path> # resolve pin files under this root
|
|
53
|
+
* INSTAR_MODEL_FRESHNESS_NOW=<ISO date> # inject the clock (staleness tests)
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
import fs from 'node:fs';
|
|
57
|
+
import path from 'node:path';
|
|
58
|
+
import { fileURLToPath } from 'node:url';
|
|
59
|
+
|
|
60
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
61
|
+
const REPO_ROOT = process.env.INSTAR_MODEL_FRESHNESS_ROOT
|
|
62
|
+
? path.resolve(process.env.INSTAR_MODEL_FRESHNESS_ROOT)
|
|
63
|
+
: path.resolve(__dirname, '..');
|
|
64
|
+
const MANIFEST_PATH = process.env.INSTAR_MODEL_FRESHNESS_MANIFEST
|
|
65
|
+
? path.resolve(process.env.INSTAR_MODEL_FRESHNESS_MANIFEST)
|
|
66
|
+
: path.join(__dirname, 'model-registry-freshness.manifest.json');
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Run the freshness check. Pure over its inputs (manifest + files under root +
|
|
70
|
+
* the injected clock), so the unit test drives it directly with fixtures.
|
|
71
|
+
* @returns {{ findings: string[], warnings: string[], info: string[], strict: boolean, error: string|null }}
|
|
72
|
+
*/
|
|
73
|
+
export function checkModelRegistryFreshness({
|
|
74
|
+
manifestPath = MANIFEST_PATH,
|
|
75
|
+
repoRoot = REPO_ROOT,
|
|
76
|
+
now = process.env.INSTAR_MODEL_FRESHNESS_NOW
|
|
77
|
+
? new Date(process.env.INSTAR_MODEL_FRESHNESS_NOW)
|
|
78
|
+
: new Date(),
|
|
79
|
+
forceStrict = process.env.INSTAR_MODEL_FRESHNESS_STRICT === '1',
|
|
80
|
+
} = {}) {
|
|
81
|
+
const findings = [];
|
|
82
|
+
const warnings = [];
|
|
83
|
+
const info = [];
|
|
84
|
+
|
|
85
|
+
let manifest;
|
|
86
|
+
try {
|
|
87
|
+
manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
88
|
+
} catch (e) {
|
|
89
|
+
return { findings: [], warnings: [], info: [], strict: true, error: `cannot read/parse manifest ${manifestPath}: ${e.message}` };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const strict = forceStrict || manifest.enforcement === 'strict';
|
|
93
|
+
|
|
94
|
+
// --- TOOTH 1: staleness ---
|
|
95
|
+
const reviewedRaw = manifest.lastReviewedAt;
|
|
96
|
+
const reviewed = reviewedRaw ? new Date(reviewedRaw) : null;
|
|
97
|
+
const windowDays = Number(manifest.stalenessWindowDays);
|
|
98
|
+
if (!reviewed || Number.isNaN(reviewed.getTime())) {
|
|
99
|
+
findings.push(`STALENESS: manifest.lastReviewedAt is missing or unparseable (got ${JSON.stringify(reviewedRaw)}).`);
|
|
100
|
+
} else if (!Number.isFinite(windowDays) || windowDays <= 0) {
|
|
101
|
+
findings.push(`STALENESS: manifest.stalenessWindowDays is missing or invalid (got ${JSON.stringify(manifest.stalenessWindowDays)}).`);
|
|
102
|
+
} else {
|
|
103
|
+
const ageDays = Math.floor((now.getTime() - reviewed.getTime()) / 86_400_000);
|
|
104
|
+
if (ageDays > windowDays) {
|
|
105
|
+
findings.push(
|
|
106
|
+
`STALENESS: model registry last reviewed ${reviewedRaw} (${ageDays}d ago) exceeds the ${windowDays}d window. ` +
|
|
107
|
+
`Re-review each capable/latest pin against current frontier, update frontierAllowlist if a model has moved, then bump lastReviewedAt.`
|
|
108
|
+
);
|
|
109
|
+
} else {
|
|
110
|
+
info.push(`Staleness OK: reviewed ${reviewedRaw} (${ageDays}d ago, window ${windowDays}d).`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// --- TOOTH 2: drift (pin id must be in its door's frontier allowlist) ---
|
|
115
|
+
const allowlist = manifest.frontierAllowlist || {};
|
|
116
|
+
for (const pin of manifest.pins || []) {
|
|
117
|
+
const abs = path.join(repoRoot, pin.file);
|
|
118
|
+
let src;
|
|
119
|
+
try {
|
|
120
|
+
src = fs.readFileSync(abs, 'utf8');
|
|
121
|
+
} catch {
|
|
122
|
+
findings.push(`DRIFT: pin '${pin.id}' references ${pin.file} which is missing under ${repoRoot} (a pin site moved or was deleted — re-anchor it).`);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
let re;
|
|
126
|
+
try {
|
|
127
|
+
re = new RegExp(pin.regex);
|
|
128
|
+
} catch (e) {
|
|
129
|
+
findings.push(`DRIFT: pin '${pin.id}' has an invalid regex (${e.message}).`);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const m = src.match(re);
|
|
133
|
+
if (!m) {
|
|
134
|
+
findings.push(`DRIFT: pin '${pin.id}' pattern did not match in ${pin.file} (the pinned site changed shape — re-anchor the regex).`);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
// All capture groups are candidate model ids (e.g. default + escalated).
|
|
138
|
+
const ids = m.slice(1).filter(Boolean);
|
|
139
|
+
const doorAllow = allowlist[pin.door] || [];
|
|
140
|
+
for (const id of ids) {
|
|
141
|
+
if (!doorAllow.includes(id)) {
|
|
142
|
+
findings.push(
|
|
143
|
+
`DRIFT: pin '${pin.id}' (${pin.door}) pins '${id}' in ${pin.file}, which is NOT in frontierAllowlist['${pin.door}'] = [${doorAllow.join(', ')}]. ` +
|
|
144
|
+
`Either the pin is stale or the allowlist wasn't updated — reconcile the two (operator-confirm the frontier id).`
|
|
145
|
+
);
|
|
146
|
+
} else {
|
|
147
|
+
info.push(`Drift OK: ${pin.door} '${pin.id}' -> '${id}' (in allowlist).`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// --- flaggedStale (known-stale-pending-confirmation): always WARN; strict counts them ---
|
|
153
|
+
for (const f of manifest.flaggedStale || []) {
|
|
154
|
+
const line =
|
|
155
|
+
`FLAGGED-STALE: ${f.door} pin '${f.pin}' currently '${f.currentId}' -> suspected frontier '${f.suspectedFrontier}'. ` +
|
|
156
|
+
`${f.evidence || ''} ${f.note || ''}`.trim();
|
|
157
|
+
warnings.push(line);
|
|
158
|
+
if (strict) findings.push(line);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return { findings, warnings, info, strict, error: null };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// --- CLI entry ---
|
|
165
|
+
const isMain = process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
|
|
166
|
+
if (isMain) {
|
|
167
|
+
const res = checkModelRegistryFreshness();
|
|
168
|
+
const B = '\x1b[1m', R = '\x1b[0m', Y = '\x1b[33m', RED = '\x1b[31m', G = '\x1b[32m';
|
|
169
|
+
console.log(`${B}[lint-model-registry-freshness]${R} enforcement=${res.strict ? 'strict' : 'report'}`);
|
|
170
|
+
|
|
171
|
+
if (res.error) {
|
|
172
|
+
console.error(`${RED}ERROR:${R} ${res.error}`);
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
for (const i of res.info) console.log(` ${G}ok${R} ${i}`);
|
|
176
|
+
for (const w of res.warnings) console.log(` ${Y}warn${R} ${w}`);
|
|
177
|
+
for (const f of res.findings) console.log(` ${RED}FIND${R} ${f}`);
|
|
178
|
+
|
|
179
|
+
if (res.findings.length === 0) {
|
|
180
|
+
console.log(`${G}PASS${R} — model registry pins fresh and in-allowlist.`);
|
|
181
|
+
process.exit(0);
|
|
182
|
+
}
|
|
183
|
+
if (res.strict) {
|
|
184
|
+
console.error(`${RED}FAIL${R} — ${res.findings.length} finding(s) under strict enforcement.`);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
console.log(
|
|
188
|
+
`${Y}REPORT-ONLY${R} — ${res.findings.length} finding(s) surfaced but NOT gating (manifest enforcement="report"). ` +
|
|
189
|
+
`Resolve them, then flip enforcement to "strict".`
|
|
190
|
+
);
|
|
191
|
+
process.exit(0);
|
|
192
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Frontier-model allowlist + staleness gate for Instar's per-provider 'capable/latest' model pins. This file is the SINGLE human-edit surface that keeps the model registry from silently rotting. See docs/LLM-ROUTING-REGISTRY.md and scripts/lint-model-registry-freshness.mjs. Two teeth: (1) STALENESS — lastReviewedAt must be within stalenessWindowDays; (2) DRIFT — every pinned capable model id must be a member of frontierAllowlist[door]. To pass the check a human must confirm each capable pin is genuinely current frontier AND bump lastReviewedAt. An un-reviewed list fails loudly.",
|
|
3
|
+
"lastReviewedAt": "2026-07-03",
|
|
4
|
+
"stalenessWindowDays": 45,
|
|
5
|
+
"enforcement": "report",
|
|
6
|
+
"$enforcementNote": "'report' = non-gating (prints findings, always exits 0) — the dark/reversible default while the current list is known-stale. Flip to 'strict' (exits 1 on any finding) ONLY after the flaggedStale door swaps below are operator-confirmed and applied. Env INSTAR_MODEL_FRESHNESS_STRICT=1 forces strict for a one-off run.",
|
|
7
|
+
"doors": {
|
|
8
|
+
"claude-code": {
|
|
9
|
+
"accessMethod": "Claude Code CLI (subscription/OAuth)",
|
|
10
|
+
"status": "alive",
|
|
11
|
+
"note": "Primary door. Tier aliases opus/sonnet/haiku auto-resolve to latest and do NOT rot; only concrete claude-*-N ids below are pinned."
|
|
12
|
+
},
|
|
13
|
+
"anthropic-headless": {
|
|
14
|
+
"accessMethod": "claude -p one-shot (Agent SDK credit pot)",
|
|
15
|
+
"status": "alive",
|
|
16
|
+
"note": "Background/internal calls. Billing shifts to interactive pool after 2026-06-15 per subscriptionPath."
|
|
17
|
+
},
|
|
18
|
+
"codex-cli": {
|
|
19
|
+
"accessMethod": "codex exec (ChatGPT account)",
|
|
20
|
+
"status": "referenced-not-installed",
|
|
21
|
+
"note": "codex CLI is NOT installed on this machine (which codex -> not found), yet componentFrameworks routes job/Usher/TopicIntentExtractor to it -> those fall back at runtime. Door-liveness gap flagged to operator."
|
|
22
|
+
},
|
|
23
|
+
"gemini-cli": {
|
|
24
|
+
"accessMethod": "gemini -m <model> (Homebrew formula, OAuth)",
|
|
25
|
+
"status": "alive-but-deprecated-formula",
|
|
26
|
+
"note": "Homebrew gemini-cli formula DEPRECATED (upstream-unsupported, disabled 2026-12-18). CLI v0.25.2 still runs. Default model still gemini-2.5-pro; CLI already knows gemini-3-pro-preview / gemini-3-flash-preview. Migrate off the deprecated formula (npm @google/gemini-cli, or an OpenRouter/pi door)."
|
|
27
|
+
},
|
|
28
|
+
"pi-cli": {
|
|
29
|
+
"accessMethod": "pi --model <provider>/<id> (multi-provider: openai-codex, openrouter, ...)",
|
|
30
|
+
"status": "alive",
|
|
31
|
+
"note": "Multi-provider consolidation door. Can reach OpenRouter (one door to many frontier models; vault key metered_openrouter_bench present). pi policy DENIES anthropic/claude via openrouter passthrough by default to protect subscription billing."
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"frontierAllowlist": {
|
|
35
|
+
"$comment": "CURRENT_FRONTIER_MODELS — the set of model ids considered acceptable-current for each door. A pinned capable model NOT in its door's list fails the DRIFT tooth. Add a new frontier id here (operator-confirmed) at the same time you update the pin.",
|
|
36
|
+
"claude-code": [
|
|
37
|
+
"claude-opus-4-8",
|
|
38
|
+
"claude-fable-5"
|
|
39
|
+
],
|
|
40
|
+
"anthropic-headless": [
|
|
41
|
+
"claude-opus-4-6",
|
|
42
|
+
"claude-sonnet-4-6",
|
|
43
|
+
"claude-haiku-4-5"
|
|
44
|
+
],
|
|
45
|
+
"codex-cli": [
|
|
46
|
+
"gpt-5.5"
|
|
47
|
+
],
|
|
48
|
+
"gemini-cli": [
|
|
49
|
+
"gemini-2.5-pro"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
"pins": [
|
|
53
|
+
{
|
|
54
|
+
"id": "gemini-capable-tier",
|
|
55
|
+
"door": "gemini-cli",
|
|
56
|
+
"tier": "capable",
|
|
57
|
+
"file": "src/providers/adapters/gemini-cli/models.ts",
|
|
58
|
+
"regex": "capable:\\s*'((?:claude|gpt|gemini)-[^']+)'",
|
|
59
|
+
"note": "TIER_TO_MODEL.capable in the gemini adapter."
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"id": "codex-capable-tier",
|
|
63
|
+
"door": "codex-cli",
|
|
64
|
+
"tier": "capable",
|
|
65
|
+
"file": "src/providers/adapters/openai-codex/models.ts",
|
|
66
|
+
"regex": "capable:\\s*'((?:claude|gpt|gemini)-[^']+)'",
|
|
67
|
+
"note": "TIER_TO_MODEL.capable in the codex adapter."
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id": "anthropic-headless-capable-tier",
|
|
71
|
+
"door": "anthropic-headless",
|
|
72
|
+
"tier": "capable",
|
|
73
|
+
"file": "src/providers/adapters/anthropic-headless/models.ts",
|
|
74
|
+
"regex": "capable:\\s*'((?:claude|gpt|gemini)-[^']+)'",
|
|
75
|
+
"note": "TIER_TO_MODEL.capable in the anthropic-headless adapter."
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "claude-tier-escalation-default-escalated",
|
|
79
|
+
"door": "claude-code",
|
|
80
|
+
"tier": "capable",
|
|
81
|
+
"file": "src/core/ModelTierEscalation.ts",
|
|
82
|
+
"regex": "'claude-code':\\s*\\{\\s*default:\\s*'([^']+)',\\s*escalated:\\s*'([^']+)'",
|
|
83
|
+
"note": "DEFAULT_TIER_ESCALATION.frameworks['claude-code'] default + escalated ids."
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
"flaggedStale": [
|
|
87
|
+
{
|
|
88
|
+
"door": "gemini-cli",
|
|
89
|
+
"pin": "gemini-capable-tier",
|
|
90
|
+
"currentId": "gemini-2.5-pro",
|
|
91
|
+
"suspectedFrontier": "gemini-3-pro-preview",
|
|
92
|
+
"evidence": "gemini CLI v0.25.2 accepts gemini-3-pro-preview / gemini-3-flash-preview (in gemini-cli-core known-models); operator referenced 'Gemini 3-class'. Homebrew formula also deprecated (disabled 2026-12-18).",
|
|
93
|
+
"note": "OPERATOR TO CONFIRM exact frontier id before the pin+allowlist are updated. Also present at src/core/frameworkSessionLaunch.ts, src/commands/route.ts (KNOWN_MODELS), src/server/routes.ts."
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"door": "codex-cli",
|
|
97
|
+
"pin": "codex-capable-tier",
|
|
98
|
+
"currentId": "gpt-5.5",
|
|
99
|
+
"suspectedFrontier": "gpt-5.6 (Sol) — UNVERIFIED",
|
|
100
|
+
"evidence": "codex CLI NOT installed on this machine, so newer accepted ids could NOT be probed. Operator referenced 'GPT-5.6 Sol'.",
|
|
101
|
+
"note": "OPERATOR TO CONFIRM. Cannot verify from a live probe (codex door not installed)."
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|