instar 1.3.755 → 1.3.756

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.755",
3
+ "version": "1.3.756",
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",
@@ -19,10 +19,21 @@
19
19
  *
20
20
  * TOOTH 2 — DRIFT. Every pinned capable/latest model id (extracted live from
21
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.
22
+ * door's DERIVED frontier set (spec §1.4, docs/specs/DOORWAY-MODEL-KNOWLEDGE-
23
+ * REGISTRY-SPEC.md): the ids in `doors[door].topModels[]` carrying
24
+ * `frontier: true`. `topModels` is the ONE hand-edited structure; the
25
+ * frontier set is a *view* of it and cannot diverge by construction (this
26
+ * supersedes the old hand-maintained `frontierAllowlist` — a second list is
27
+ * exactly the rot this guard fights). A pin that names a model not in the
28
+ * derived set fails — either the pin is stale, or `topModels` wasn't updated.
29
+ * To go green a human must reconcile the two, which IS the review.
30
+ *
31
+ * BACKWARD-COMPAT (un-enriched manifests): a door with a literal
32
+ * `frontierAllowlist[door]` and NO `topModels` is read from the literal list
33
+ * EXACTLY as before (no behavior change). A door with BOTH a literal
34
+ * `frontierAllowlist[door]` AND `topModels` emits a TRANSITION finding
35
+ * ("migrated to derived — delete the literal") so the old hand-list can't
36
+ * silently linger and re-rot; the derived set is authoritative there.
26
37
  *
27
38
  * Plus: `flaggedStale[]` entries (known-stale-pending-operator-confirmation) are
28
39
  * always printed as WARN lines and, under strict enforcement, count as findings.
@@ -65,6 +76,42 @@ const MANIFEST_PATH = process.env.INSTAR_MODEL_FRESHNESS_MANIFEST
65
76
  ? path.resolve(process.env.INSTAR_MODEL_FRESHNESS_MANIFEST)
66
77
  : path.join(__dirname, 'model-registry-freshness.manifest.json');
67
78
 
79
+ /**
80
+ * Compute a door's effective frontier set — the ONE source of truth (spec §1.4).
81
+ *
82
+ * DERIVED (schema v2): `doors[door].topModels` present (an array) → the set is
83
+ * the ids of entries with `frontier === true`. `topModels` is the only
84
+ * hand-edited structure; the frontier set is a view of it (cannot diverge).
85
+ * LITERAL (backward-compat): no `topModels` for the door but a literal
86
+ * `frontierAllowlist[door]` present → use it verbatim (un-enriched manifest,
87
+ * today's exact behavior).
88
+ * NONE: neither present → empty set (a pin on that door drifts, as before).
89
+ *
90
+ * `transition` is true when a door carries BOTH a literal `frontierAllowlist[door]`
91
+ * AND `topModels` — the derived set is authoritative and a transition finding is
92
+ * raised so the stale literal can't linger.
93
+ *
94
+ * @param {Record<string, any>} manifest
95
+ * @param {string} door
96
+ * @returns {{ set: string[], source: 'derived'|'literal'|'none', transition: boolean }}
97
+ */
98
+ export function frontierSetForDoor(manifest, door) {
99
+ const doorEntry = (manifest && manifest.doors && manifest.doors[door]) || null;
100
+ const topModels = doorEntry && Array.isArray(doorEntry.topModels) ? doorEntry.topModels : null;
101
+ const literal =
102
+ manifest && manifest.frontierAllowlist && Array.isArray(manifest.frontierAllowlist[door])
103
+ ? manifest.frontierAllowlist[door]
104
+ : null;
105
+ if (topModels) {
106
+ const set = topModels
107
+ .filter((m) => m && m.frontier === true && typeof m.id === 'string')
108
+ .map((m) => m.id);
109
+ return { set, source: 'derived', transition: literal !== null };
110
+ }
111
+ if (literal) return { set: literal, source: 'literal', transition: false };
112
+ return { set: [], source: 'none', transition: false };
113
+ }
114
+
68
115
  /**
69
116
  * Run the freshness check. Pure over its inputs (manifest + files under root +
70
117
  * the injected clock), so the unit test drives it directly with fixtures.
@@ -111,8 +158,23 @@ export function checkModelRegistryFreshness({
111
158
  }
112
159
  }
113
160
 
114
- // --- TOOTH 2: drift (pin id must be in its door's frontier allowlist) ---
115
- const allowlist = manifest.frontierAllowlist || {};
161
+ // --- TRANSITION: a door carrying BOTH a literal frontierAllowlist entry AND
162
+ // topModels has migrated to the derived set — flag the lingering literal so
163
+ // it can't silently re-rot (spec §1.4). Deduped per door, independent of pins.
164
+ const doorsObj = manifest.doors || {};
165
+ const litAllow = manifest.frontierAllowlist || {};
166
+ for (const door of Object.keys(doorsObj)) {
167
+ const entry = doorsObj[door];
168
+ if (entry && Array.isArray(entry.topModels) && Array.isArray(litAllow[door])) {
169
+ findings.push(
170
+ `TRANSITION: door '${door}' has BOTH a literal frontierAllowlist['${door}'] and topModels[] — ` +
171
+ `it migrated to the DERIVED frontier set (§1.4; the derived set is now authoritative). ` +
172
+ `Delete the literal frontierAllowlist['${door}'] so the old hand-maintained list can't silently linger and re-rot.`
173
+ );
174
+ }
175
+ }
176
+
177
+ // --- TOOTH 2: drift (pin id must be in its door's DERIVED frontier set) ---
116
178
  for (const pin of manifest.pins || []) {
117
179
  const abs = path.join(repoRoot, pin.file);
118
180
  let src;
@@ -136,15 +198,19 @@ export function checkModelRegistryFreshness({
136
198
  }
137
199
  // All capture groups are candidate model ids (e.g. default + escalated).
138
200
  const ids = m.slice(1).filter(Boolean);
139
- const doorAllow = allowlist[pin.door] || [];
201
+ const { set: doorFrontier, source } = frontierSetForDoor(manifest, pin.door);
202
+ const setLabel =
203
+ source === 'literal'
204
+ ? `frontierAllowlist['${pin.door}']`
205
+ : `the derived frontier set for '${pin.door}' (doors['${pin.door}'].topModels[frontier=true])`;
140
206
  for (const id of ids) {
141
- if (!doorAllow.includes(id)) {
207
+ if (!doorFrontier.includes(id)) {
142
208
  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).`
209
+ `DRIFT: pin '${pin.id}' (${pin.door}) pins '${id}' in ${pin.file}, which is NOT in ${setLabel} = [${doorFrontier.join(', ')}]. ` +
210
+ `Either the pin is stale or the frontier set wasn't updated — reconcile the two (operator-confirm the frontier id).`
145
211
  );
146
212
  } else {
147
- info.push(`Drift OK: ${pin.door} '${pin.id}' -> '${id}' (in allowlist).`);
213
+ info.push(`Drift OK: ${pin.door} '${pin.id}' -> '${id}' (in ${source === 'literal' ? 'allowlist' : 'derived frontier set'}).`);
148
214
  }
149
215
  }
150
216
  }
@@ -1,54 +1,59 @@
1
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.",
2
+ "$comment": "Doorway/Model Knowledge Registry — canonical/reviewed layer + staleness/drift 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, docs/specs/DOORWAY-MODEL-KNOWLEDGE-REGISTRY-SPEC.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 its door's DERIVED frontier set (the ids in doors[door].topModels[] carrying frontier:true — see §1.4 of the spec). topModels is the ONE hand-edited source of truth; the frontier set is a view of it and cannot diverge by construction. 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
+ "registrySchemaVersion": 2,
4
+ "$schemaNote": "registrySchemaVersion 2 = the enriched Doorway/Model Knowledge Registry. Rollout increment 1 (spec §Rollout step 1): the per-door topModels[] frontier-derivation layer + the derived-frontier lint (report mode). The live scan-state (.instar/state/doorway-scan.json), the deterministic prober, the per-door probe{} block, candidateDoorways[], the scan job, and GET /doorways are LATER increments (spec §Rollout steps 2-3) and are NOT part of this schema version's consumers yet.",
3
5
  "lastReviewedAt": "2026-07-03",
4
6
  "stalenessWindowDays": 45,
5
7
  "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.",
8
+ "$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 AND the standard is ratified (spec §Rollout step 5). Env INSTAR_MODEL_FRESHNESS_STRICT=1 forces strict for a one-off run.",
7
9
  "doors": {
8
10
  "claude-code": {
11
+ "name": "Claude Code CLI",
9
12
  "accessMethod": "Claude Code CLI (subscription/OAuth)",
10
13
  "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."
14
+ "topModels": [
15
+ { "id": "claude-opus-4-8", "role": "capable-anthropic", "frontier": true, "pricing": null, "verifiedAt": "carried-over-from-allowlist" },
16
+ { "id": "claude-fable-5", "role": "ultra-anthropic", "frontier": true, "pricing": null, "verifiedAt": "carried-over-from-allowlist" }
17
+ ],
18
+ "note": "Primary door. Tier aliases opus/sonnet/haiku auto-resolve to latest and do NOT rot; only concrete claude-*-N ids in topModels are pinned. topModels seeded 1:1 from the reviewed frontierAllowlist (spec D4 carry-over); the first enabled scan re-verifies."
12
19
  },
13
20
  "anthropic-headless": {
21
+ "name": "Anthropic headless (claude -p)",
14
22
  "accessMethod": "claude -p one-shot (Agent SDK credit pot)",
15
23
  "status": "alive",
16
- "note": "Background/internal calls. Billing shifts to interactive pool after 2026-06-15 per subscriptionPath."
24
+ "topModels": [
25
+ { "id": "claude-opus-4-8", "role": "capable-anthropic", "frontier": true, "pricing": null, "verifiedAt": "carried-over-from-allowlist" },
26
+ { "id": "claude-sonnet-4-6", "role": "balanced-anthropic", "frontier": true, "pricing": null, "verifiedAt": "carried-over-from-allowlist" },
27
+ { "id": "claude-haiku-4-5", "role": "fast-anthropic", "frontier": true, "pricing": null, "verifiedAt": "carried-over-from-allowlist" }
28
+ ],
29
+ "note": "Background/internal calls. Billing shifts to interactive pool after 2026-06-15 per subscriptionPath. topModels seeded from the reviewed frontierAllowlist (spec D4 carry-over)."
17
30
  },
18
31
  "codex-cli": {
32
+ "name": "Codex CLI",
19
33
  "accessMethod": "codex exec (ChatGPT account)",
20
34
  "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."
35
+ "topModels": [
36
+ { "id": "gpt-5.5", "role": "capable-openai", "frontier": true, "pricing": null, "verifiedAt": "carried-over-from-allowlist" }
37
+ ],
38
+ "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. topModels seeded from the reviewed frontierAllowlist (spec D4 carry-over)."
22
39
  },
23
40
  "gemini-cli": {
41
+ "name": "Gemini CLI",
24
42
  "accessMethod": "gemini -m <model> (Homebrew formula, OAuth)",
25
43
  "status": "alive-but-deprecated-formula",
26
- "note": "Homebrew gemini-cli formula DEPRECATED (upstream-unsupported, disabled 2026-12-18). CLI v0.25.2 still runs. capable tier now pinned to gemini-3.1-pro-preview (verified reachable 2026-07-03 via the gemini CLI / OpenRouter / paid Gemini key); gemini-2.5-pro remains a recognized/spawnable model + capacity fallback. Migrate off the deprecated formula (npm @google/gemini-cli, or an OpenRouter/pi door)."
44
+ "topModels": [
45
+ { "id": "gemini-3.1-pro-preview", "role": "capable-google", "frontier": true, "pricing": null, "verifiedAt": "carried-over-from-allowlist" }
46
+ ],
47
+ "note": "Homebrew gemini-cli formula DEPRECATED (upstream-unsupported, disabled 2026-12-18). CLI v0.25.2 still runs. capable tier now pinned to gemini-3.1-pro-preview (verified reachable 2026-07-03 via the gemini CLI / OpenRouter / paid Gemini key); gemini-2.5-pro remains a recognized/spawnable model + capacity fallback (NOT frontier). Migrate off the deprecated formula (npm @google/gemini-cli, or an OpenRouter/pi door). topModels seeded from the reviewed frontierAllowlist (spec D4 carry-over)."
27
48
  },
28
49
  "pi-cli": {
50
+ "name": "pi CLI",
29
51
  "accessMethod": "pi --model <provider>/<id> (multi-provider: openai-codex, openrouter, ...)",
30
52
  "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."
53
+ "topModels": [],
54
+ "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. No pin references this door yet, so topModels is empty (no frontier set to derive); the first enabled scan enumerates observed models for operator classification."
32
55
  }
33
56
  },
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-8",
42
- "claude-sonnet-4-6",
43
- "claude-haiku-4-5"
44
- ],
45
- "codex-cli": [
46
- "gpt-5.5"
47
- ],
48
- "gemini-cli": [
49
- "gemini-3.1-pro-preview"
50
- ]
51
- },
52
57
  "pins": [
53
58
  {
54
59
  "id": "gemini-capable-tier",
@@ -83,6 +88,7 @@
83
88
  "note": "DEFAULT_TIER_ESCALATION.frameworks['claude-code'] default + escalated ids."
84
89
  }
85
90
  ],
86
- "$flaggedStaleNote": "Both prior flagged pins RESOLVED (operator-confirmed 2026-07-03): gemini capable swapped gemini-2.5-pro -> gemini-3.1-pro-preview (pin + allowlist 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.",
87
- "flaggedStale": []
88
- }
91
+ "$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.",
92
+ "flaggedStale": [],
93
+ "$frontierAllowlistNote": "The hand-maintained frontierAllowlist{} was SUPERSEDED by derivation (spec §1.4): the frontier set for each door is now the ids in doors[door].topModels[] carrying frontier:true. This removes a second hand-maintained list (the rot this registry fights). The lint keeps a backward-compat path: a door with a literal frontierAllowlist[door] and NO topModels behaves exactly as before; a door with BOTH emits a transition finding so the old hand-list can't silently linger."
94
+ }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-07-04T18:02:08.942Z",
5
- "instarVersion": "1.3.755",
4
+ "generatedAt": "2026-07-04T18:27:11.948Z",
5
+ "instarVersion": "1.3.756",
6
6
  "entryCount": 202,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -0,0 +1,27 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Doorway/Model Knowledge Registry — rollout increment 1 (the foundational, dark/inert, backward-compatible piece of `docs/specs/DOORWAY-MODEL-KNOWLEDGE-REGISTRY-SPEC.md`):
9
+
10
+ - **Enriched the canonical registry** (`scripts/model-registry-freshness.manifest.json`, now `registrySchemaVersion: 2`): every door carries a `topModels[]` list — the exact model id, a role label, a `frontier` flag, `pricing` (null on carry-over), and `verifiedAt`. Seeded 1:1 from the already-reviewed `frontierAllowlist` (spec D4 carry-over: `verifiedAt:"carried-over-from-allowlist"`), so no new research/operator round-trip was needed to land it.
11
+ - **Made the frontier set DERIVED, not hand-maintained** (spec §1.4): the freshness lint's DRIFT tooth (`scripts/lint-model-registry-freshness.mjs`) now checks each pin against the ids in `doors[door].topModels[]` carrying `frontier:true` — a *view* of the one hand-edited structure — instead of the separate `frontierAllowlist{}` (now removed). This eliminates the second hand-maintained list that was itself a rot vector. Backward-compatible: a door with a literal `frontierAllowlist` and no `topModels` behaves exactly as before; a door with BOTH emits a non-gating `TRANSITION` finding so the stale literal can't silently linger.
12
+
13
+ The lint stays in non-gating `report` mode. No runtime code (`src/`), route, job, config default, hook, or agent-installed file changes in this increment — the deterministic prober, live scan-state, `GET /doorways`, the scan job, and the config knob are later rollout increments and are NOT in this PR.
14
+
15
+ ## What to Tell Your User
16
+
17
+ None — internal change (no user-facing surface).
18
+
19
+ ## Summary of New Capabilities
20
+
21
+ None — internal change (no user-facing surface).
22
+
23
+ ## Evidence
24
+
25
+ - `node scripts/lint-model-registry-freshness.mjs` → PASS against the enriched shipped manifest (all pins resolve via the derived frontier set; staleness OK).
26
+ - `tests/unit/model-registry-freshness.test.ts` → 20/20 pass (11 pre-existing + 9 new: derived-frontier drift both sides, `frontier:false` exclusion, the transition finding, old-shape backward-compat, and direct `frontierSetForDoor` unit coverage). The shipped-manifest self-consistency test passes via the derived path.
27
+ - Deferred items (spec §Deferred DF1-DF6) filed as tracked follow-ups: `docs/specs/reports/DOORWAY-MODEL-KNOWLEDGE-REGISTRY-followups.md` + `<!-- tracked: 29723 -->` markers in the spec body (owner topic 29723).
@@ -0,0 +1,89 @@
1
+ # Side-Effects Review — Doorway/Model Knowledge Registry, increment 1 (enriched manifest + derived-frontier lint)
2
+
3
+ **Version / slug:** `doorway-model-registry-inc1`
4
+ **Date:** `2026-07-04`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required` (no messaging/session-lifecycle/gate/sentinel/watchdog surface — see §4/§5)
7
+
8
+ ## Summary of the change
9
+
10
+ First rollout increment of `DOORWAY-MODEL-KNOWLEDGE-REGISTRY-SPEC.md` (§Rollout step 1), landed dark/inert and backward-compatible. Two source artifacts change:
11
+
12
+ 1. **`scripts/model-registry-freshness.manifest.json`** — enriched into the canonical Doorway/Model Knowledge Registry (`registrySchemaVersion: 2`). Each door gains a `topModels[]` array (exact model id + `role` + `frontier` flag + `pricing:null` + `verifiedAt`), seeded **1:1 from the reviewed `frontierAllowlist`** per spec D4 (`verifiedAt:"carried-over-from-allowlist"`, `frontier:true`, pricing null). The hand-maintained `frontierAllowlist{}` is removed (superseded by derivation).
13
+ 2. **`scripts/lint-model-registry-freshness.mjs`** — the DRIFT tooth (TOOTH 2) now checks each pin against a **derived** frontier set (`doors[door].topModels[] where frontier===true`) via a new exported `frontierSetForDoor()` helper, instead of the literal `frontierAllowlist`. Backward-compat is preserved: a door with a literal allowlist and NO `topModels` uses the literal list exactly as before; a door with BOTH emits a `TRANSITION` finding so the stale literal can't linger.
14
+
15
+ Plus the spec docs (spec + ELI16 + convergence report + a follow-ups tracking stub) and the unit test extension. The prober, scan-state, `GET /doorways` route, config knob, CLAUDE.md block, and the scan job are all LATER increments (§Rollout steps 2-3) and are explicitly NOT in this PR.
16
+
17
+ The lint stays in `enforcement: "report"` (non-gating; always exits 0). No runtime behavior changes: no code under `src/` is touched, no route, no job, no config default.
18
+
19
+ ## Decision-point inventory
20
+
21
+ - `TOOTH 2 (DRIFT) in lint-model-registry-freshness.mjs` — **modify** — the drift check's frontier set is now derived from `topModels[frontier=true]` rather than the literal `frontierAllowlist`. Same decision (is each pin's id in its door's frontier set?), new one-source-of-truth input. Model-id-agnostic and non-gating under `report`.
22
+ - `TRANSITION finding` — **add** — a new non-gating (under report) finding class flagging a door that carries both a literal allowlist and `topModels`. Purely a maintainer nudge to delete the stale literal.
23
+ - No runtime decision point (message/dispatch/session/gate) is touched.
24
+
25
+ ---
26
+
27
+ ## 1. Over-block
28
+
29
+ No block/allow surface at runtime — over-block not applicable. The lint is a build-time CI signal. In `report` mode it always exits 0 (never blocks a build). The only "block" it could ever produce is a CI failure under `strict` enforcement, which is unchanged in this increment (`enforcement: "report"`). A false DRIFT/TRANSITION finding under a future `strict` flip would over-block a build, but: (a) strict is not enabled here, and (b) the derivation is a faithful superset-preserving projection of the prior allowlist (verified: the shipped manifest lints clean).
30
+
31
+ ---
32
+
33
+ ## 2. Under-block
34
+
35
+ No block/allow surface — under-block not applicable in the runtime sense. As a freshness ratchet, the increment could "under-catch" only in the same ways the pre-existing lint could: a pin whose regex no longer matches, or a door with neither `topModels` nor a literal allowlist (derived set empty → any pin on it drifts, same as before). The derivation does not weaken TOOTH 1 (staleness) or the regex-anchored pin extraction. It strictly removes a second hand-maintained list (a rot vector), so it under-catches strictly less than before, not more.
36
+
37
+ ---
38
+
39
+ ## 3. Level-of-abstraction fit
40
+
41
+ Correct layer. This is a deterministic, model-id-agnostic build-time consistency lint (a detector/signal), not a runtime authority. The change keeps it there: `frontierSetForDoor()` is a pure function over the manifest; the derivation removes a duplicated data structure so the frontier set is a *view* of `topModels` and cannot diverge by construction (one-source-of-truth). It does not reach up into a smart gate nor down into a runtime primitive — the manifest/lint pair is exactly the right home for "is our model map internally consistent and fresh?".
42
+
43
+ ---
44
+
45
+ ## 4. Signal vs authority compliance
46
+
47
+ **Required reference:** `docs/signal-vs-authority.md`
48
+
49
+ - [x] **No — this change produces a signal consumed by an existing smart gate / CI.** The lint prints findings; CI (and a human) consume them. Its authority knob (`report` vs `strict`) is unchanged and stays in non-gating `report`. The change refines the *input* to an existing deterministic check (derived set vs literal list) and adds a non-gating maintainer finding. No new brittle blocking authority over agent behavior, messages, or dispatch is introduced. The derivation is exact/deterministic, not brittle inference.
50
+
51
+ ---
52
+
53
+ ## 5. Interactions
54
+
55
+ - **Shadowing:** none. The only reader of this manifest is `lint-model-registry-freshness.mjs` and its test (confirmed by grep across `src/`, `scripts/`, `tests/`). No `src/` code reads `frontierAllowlist` or `topModels`, so removing the literal allowlist shadows nothing.
56
+ - **Double-fire:** none. No new scheduled/event actor. The TRANSITION finding is deduped per-door (independent of the pins loop).
57
+ - **Races:** none. Pure file read at lint time; no shared mutable state.
58
+ - **Feedback loops:** none. The lint reads the manifest and prints; it never writes the manifest or any state.
59
+
60
+ ---
61
+
62
+ ## 6. External surfaces
63
+
64
+ - Other agents on the same machine: none — source-only change, no runtime surface.
65
+ - Install base: the manifest + lint ship as instar **source**; they are present only on source-carrying (maintainer/dev/fixture) agents and are absent on pure end-user agents (not scaffolded). No agent-installed file (`.claude/`, `.instar/`, CLAUDE.md template, job template, hook) changes in this increment, so no `PostUpdateMigrator` migration is needed (that arrives with increments 2-3: config knob, CLAUDE.md block, job, PreToolUse guard).
66
+ - External systems (Telegram/Slack/GitHub/Cloudflare): none.
67
+ - Persistent state: none written. No new state file in this increment (the live scan-state `.instar/state/doorway-scan.json` is increment 2).
68
+ - Timing/runtime: none.
69
+ - **Operator surface (Mobile-Complete Operator Actions):** no operator-facing actions added or touched — the only human-facing artifact is CI lint output. Not applicable.
70
+
71
+ ## 6b. Operator-surface quality
72
+
73
+ No operator surface — not applicable. No dashboard renderer, approval page, or grant/revoke/secret-drop form is touched.
74
+
75
+ ---
76
+
77
+ ## 7. Multi-machine posture (Cross-Machine Coherence)
78
+
79
+ **machine-local BY DESIGN — no, actually: replicated-by-git-tracking (identical on every machine).** The canonical registry (`scripts/model-registry-freshness.manifest.json`) and the lint are **git-tracked instar source**, so they are byte-identical on every machine by construction — there is no per-machine divergence, no replication path to build, and no merge concern. (The *live/observed* per-machine scan-state that IS machine-local by design is a later increment — §1.3 of the spec — and is out of scope here.) This increment emits no user-facing notices (no one-voice gating needed), holds no durable runtime state (nothing to strand on topic transfer), and generates no URLs.
80
+
81
+ ---
82
+
83
+ ## 8. Rollback cost
84
+
85
+ Pure source/data change — **revert and ship a patch**, zero runtime blast radius.
86
+ - Hot-fix: `git revert` the manifest + lint change; the lint returns to reading the literal `frontierAllowlist`. Because the change is backward-compatible in both directions (the reverted lint reads a literal allowlist; the enriched manifest with `topModels` and no `frontierAllowlist` would, under the OLD lint, treat every door's allowlist as empty → DRIFT findings — but only non-gating under `report`), a clean revert restores BOTH files together, so there is no split-brain window.
87
+ - Data migration: none — no persistent state produced.
88
+ - Agent state repair: none — existing agents pull the source on update; nothing to reset.
89
+ - User visibility: none — no user-visible surface; the lint runs in CI only, and stays non-gating (`report`).