instar 1.3.811 → 1.3.813

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.
Files changed (41) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +4 -0
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/core/CodexCliIntelligenceProvider.d.ts +1 -0
  5. package/dist/core/CodexCliIntelligenceProvider.d.ts.map +1 -1
  6. package/dist/core/CodexCliIntelligenceProvider.js +25 -4
  7. package/dist/core/CodexCliIntelligenceProvider.js.map +1 -1
  8. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  9. package/dist/core/PostUpdateMigrator.js +6 -0
  10. package/dist/core/PostUpdateMigrator.js.map +1 -1
  11. package/dist/core/types.d.ts +3 -1
  12. package/dist/core/types.d.ts.map +1 -1
  13. package/dist/core/types.js.map +1 -1
  14. package/dist/monitoring/QuotaCollector.d.ts +10 -4
  15. package/dist/monitoring/QuotaCollector.d.ts.map +1 -1
  16. package/dist/monitoring/QuotaCollector.js +71 -2
  17. package/dist/monitoring/QuotaCollector.js.map +1 -1
  18. package/dist/monitoring/QuotaTracker.d.ts +2 -0
  19. package/dist/monitoring/QuotaTracker.d.ts.map +1 -1
  20. package/dist/monitoring/QuotaTracker.js +25 -5
  21. package/dist/monitoring/QuotaTracker.js.map +1 -1
  22. package/dist/providers/adapters/openai-codex/models.d.ts +7 -0
  23. package/dist/providers/adapters/openai-codex/models.d.ts.map +1 -1
  24. package/dist/providers/adapters/openai-codex/models.js +12 -8
  25. package/dist/providers/adapters/openai-codex/models.js.map +1 -1
  26. package/dist/providers/adapters/openai-codex/observability/eventNormalizer.d.ts +1 -0
  27. package/dist/providers/adapters/openai-codex/observability/eventNormalizer.d.ts.map +1 -1
  28. package/dist/providers/adapters/openai-codex/observability/eventNormalizer.js +10 -4
  29. package/dist/providers/adapters/openai-codex/observability/eventNormalizer.js.map +1 -1
  30. package/dist/scaffold/templates.d.ts.map +1 -1
  31. package/dist/scaffold/templates.js +1 -0
  32. package/dist/scaffold/templates.js.map +1 -1
  33. package/package.json +1 -1
  34. package/src/data/builtin-manifest.json +19 -19
  35. package/src/scaffold/templates.ts +1 -0
  36. package/upgrades/1.3.812.md +23 -0
  37. package/upgrades/1.3.813.md +23 -0
  38. package/upgrades/eli16/codex-model-retirement-fallback.md +21 -0
  39. package/upgrades/eli16/codex-quota-load-shed.md +21 -0
  40. package/upgrades/side-effects/codex-model-retirement-fallback.md +77 -0
  41. package/upgrades/side-effects/codex-quota-load-shed.md +91 -0
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-07-11T02:35:23.065Z",
5
- "instarVersion": "1.3.811",
4
+ "generatedAt": "2026-07-11T03:54:14.492Z",
5
+ "instarVersion": "1.3.813",
6
6
  "entryCount": 202,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -11,7 +11,7 @@
11
11
  "domain": "identity",
12
12
  "sourcePath": "src/core/PostUpdateMigrator.ts",
13
13
  "installedPath": ".instar/hooks/instar/session-start.sh",
14
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
14
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
15
15
  "since": "2025-01-01"
16
16
  },
17
17
  "hook:dangerous-command-guard": {
@@ -20,7 +20,7 @@
20
20
  "domain": "safety",
21
21
  "sourcePath": "src/core/PostUpdateMigrator.ts",
22
22
  "installedPath": ".instar/hooks/instar/dangerous-command-guard.sh",
23
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
23
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
24
24
  "since": "2025-01-01"
25
25
  },
26
26
  "hook:grounding-before-messaging": {
@@ -29,7 +29,7 @@
29
29
  "domain": "safety",
30
30
  "sourcePath": "src/core/PostUpdateMigrator.ts",
31
31
  "installedPath": ".instar/hooks/instar/grounding-before-messaging.sh",
32
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
32
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
33
33
  "since": "2025-01-01"
34
34
  },
35
35
  "hook:compaction-recovery": {
@@ -38,7 +38,7 @@
38
38
  "domain": "identity",
39
39
  "sourcePath": "src/core/PostUpdateMigrator.ts",
40
40
  "installedPath": ".instar/hooks/instar/compaction-recovery.sh",
41
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
41
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
42
42
  "since": "2025-01-01"
43
43
  },
44
44
  "hook:external-operation-gate": {
@@ -47,7 +47,7 @@
47
47
  "domain": "safety",
48
48
  "sourcePath": "src/core/PostUpdateMigrator.ts",
49
49
  "installedPath": ".instar/hooks/instar/external-operation-gate.js",
50
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
50
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
51
51
  "since": "2025-01-01"
52
52
  },
53
53
  "hook:deferral-detector": {
@@ -56,7 +56,7 @@
56
56
  "domain": "safety",
57
57
  "sourcePath": "src/core/PostUpdateMigrator.ts",
58
58
  "installedPath": ".instar/hooks/instar/deferral-detector.js",
59
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
59
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
60
60
  "since": "2025-01-01"
61
61
  },
62
62
  "hook:self-stop-guard": {
@@ -65,7 +65,7 @@
65
65
  "domain": "coherence",
66
66
  "sourcePath": "src/core/PostUpdateMigrator.ts",
67
67
  "installedPath": ".instar/hooks/instar/self-stop-guard.js",
68
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
68
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
69
69
  "since": "2025-01-01"
70
70
  },
71
71
  "hook:post-action-reflection": {
@@ -74,7 +74,7 @@
74
74
  "domain": "evolution",
75
75
  "sourcePath": "src/core/PostUpdateMigrator.ts",
76
76
  "installedPath": ".instar/hooks/instar/post-action-reflection.js",
77
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
77
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
78
78
  "since": "2025-01-01"
79
79
  },
80
80
  "hook:external-communication-guard": {
@@ -83,7 +83,7 @@
83
83
  "domain": "safety",
84
84
  "sourcePath": "src/core/PostUpdateMigrator.ts",
85
85
  "installedPath": ".instar/hooks/instar/external-communication-guard.js",
86
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
86
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
87
87
  "since": "2025-01-01"
88
88
  },
89
89
  "hook:scope-coherence-collector": {
@@ -92,7 +92,7 @@
92
92
  "domain": "coherence",
93
93
  "sourcePath": "src/core/PostUpdateMigrator.ts",
94
94
  "installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
95
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
95
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
96
96
  "since": "2025-01-01"
97
97
  },
98
98
  "hook:scope-coherence-checkpoint": {
@@ -101,7 +101,7 @@
101
101
  "domain": "coherence",
102
102
  "sourcePath": "src/core/PostUpdateMigrator.ts",
103
103
  "installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
104
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
104
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
105
105
  "since": "2025-01-01"
106
106
  },
107
107
  "hook:free-text-guard": {
@@ -110,7 +110,7 @@
110
110
  "domain": "safety",
111
111
  "sourcePath": "src/core/PostUpdateMigrator.ts",
112
112
  "installedPath": ".instar/hooks/instar/free-text-guard.sh",
113
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
113
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
114
114
  "since": "2025-01-01"
115
115
  },
116
116
  "hook:claim-intercept": {
@@ -119,7 +119,7 @@
119
119
  "domain": "coherence",
120
120
  "sourcePath": "src/core/PostUpdateMigrator.ts",
121
121
  "installedPath": ".instar/hooks/instar/claim-intercept.js",
122
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
122
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
123
123
  "since": "2025-01-01"
124
124
  },
125
125
  "hook:claim-intercept-response": {
@@ -128,7 +128,7 @@
128
128
  "domain": "coherence",
129
129
  "sourcePath": "src/core/PostUpdateMigrator.ts",
130
130
  "installedPath": ".instar/hooks/instar/claim-intercept-response.js",
131
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
131
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
132
132
  "since": "2025-01-01"
133
133
  },
134
134
  "hook:stop-gate-router": {
@@ -137,7 +137,7 @@
137
137
  "domain": "safety",
138
138
  "sourcePath": "src/core/PostUpdateMigrator.ts",
139
139
  "installedPath": ".instar/hooks/instar/stop-gate-router.js",
140
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
140
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
141
141
  "since": "2025-01-01"
142
142
  },
143
143
  "hook:auto-approve-permissions": {
@@ -146,7 +146,7 @@
146
146
  "domain": "safety",
147
147
  "sourcePath": "src/core/PostUpdateMigrator.ts",
148
148
  "installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
149
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
149
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
150
150
  "since": "2025-01-01"
151
151
  },
152
152
  "job:health-check": {
@@ -1562,7 +1562,7 @@
1562
1562
  "type": "subsystem",
1563
1563
  "domain": "updates",
1564
1564
  "sourcePath": "src/core/PostUpdateMigrator.ts",
1565
- "contentHash": "e2bc1b5eef5aa582ecae8f26c0c82e699a3b01fcc7883b297b57ad8f64230c8c",
1565
+ "contentHash": "c56abb8d920e024e09f5d88beb426798c57ca6d55aa1221912977afa4ffdce18",
1566
1566
  "since": "2025-01-01"
1567
1567
  },
1568
1568
  "subsystem:scheduler": {
@@ -863,6 +863,7 @@ I declare owner/blockedOn at commitment creation; a later state change goes thro
863
863
  - **Quota across ALL my machines** (pool-scope read) — \`GET /subscription-pool?scope=pool\` fans out to every ONLINE peer's plain pool, tags each account with the machine holding it (\`machineId\`/\`machineNickname\`/\`remote:true\`), and merges into ONE dark-peer-tolerant object \`{ enabled, accounts:[...], pool:{ selfMachineId, peersQueried, peersOk, failed }, scope:'pool' }\`. A down/slow/unauth peer is a classified \`pool.failed\` row (normalized reason — never a peer URL or token), never a silent omission and never a 500. Per-machine seat is meaningful, so the SAME account on two machines stays individually visible (never coalesced). Single-machine → the plain self-only view tagged \`scope:'pool'\`. Use this when the operator asks "how much quota is left across ALL my machines?".
864
864
  - **Continuity guarantee** — a long session that hits its account's quota resumes on another eligible account (conversation preserved via \`--resume\`), never dies. Manual lever: \`POST /subscription-pool/swap\` \`{"sessionName":"...","exhaustedAccountId":"..."}\`. Auto-swap on rate-limit ships OFF (opt-in via \`subscriptionPool.autoSwapOnRateLimit\` — it moves a live session, real authority).
865
865
  - **Codex quota is first-class in the pool:** Codex accounts read the real 5-hour + weekly windows from their latest rollout instead of appearing permanently empty. Placement and every reactive/proactive swap are framework-safe: a Codex session can use only Codex accounts, and a Claude session only Claude accounts.
866
+ - **Solo Codex load shedding is fail-safe:** the global quota brake also consumes those rollout windows when no subscription pool is present. A walled account stops new jobs/sessions, a healthy account runs normally, and a missing, stale, unreadable, or incomplete Codex reading sheds rather than repeatedly spawning into an unknown wall. Claude keeps its existing OAuth-authoritative / JSONL-degraded behavior.
866
867
  - **Pre-limit (proactive) swap** — beyond the reactive swap above, I can move a session OFF an account BEFORE it walls, at a lag-aware measured threshold (default 80% — the polled reading trails real usage, so the swap completes with margin). It also covers the UNTAGGED interactive session (resolves its account from the default login), so the session you talk to doesn't wedge at the wall. Opt-in via \`subscriptionPool.proactiveSwap.enabled\` (same authority as auto-swap, earlier trigger). Status: \`GET /subscription-pool/proactive-swap\`; run a pass now: \`POST /subscription-pool/proactive-swap/check\`.
867
868
  - **Anti-thrash brakes + in-flight work protection on swaps** — the proactive swap carries brakes so it can never ping-pong sessions between hot accounts (the 2026-07-02 thrash day): when EVERY account is hot it STAYS PUT (\`all-hot\` refusal — one reactive rescue beats N pointless kills), a just-swapped session dwells ~45 min before it can be moved again (restart-safe via \`state/swap-ledger.jsonl\`), and a swap only executes onto a target that is MATERIALLY cooler on a fresh quota reading (never onto an unmeasured/stale account). A session mid-turn or carrying live subagents is never killed by an optimization — the swap DEFERS until the work lands (a forced/reactive kill carries a mitigation note enumerating interrupted subagents + re-injecting the last unanswered message). Brakes ship dry-run first (\`subscriptionPool.proactiveSwap.antiThrash.dryRun\`); the work gate's \`subscriptionPool.swapContinuity.enabled\` is restart-required (§7.1). "Why didn't my session swap?" → \`GET /subscription-pool/proactive-swap\` \`brakes\`/\`deferrals\` blocks name the refusal; "why did my refresh get a session-busy error?" → the work gate refused to kill in-flight work — wait, or re-issue with \`force:true\`.
868
869
  - **Enroll a new account from your phone** — \`POST /subscription-pool/enroll\` \`{"id","label","provider","framework","configHome"}\` starts a login and returns a public code/URL (never a token); \`GET /subscription-pool/pending-logins\` is the surface; expired codes are auto-reissued. Mark done with \`POST /subscription-pool/enroll/:id/complete\`.
@@ -0,0 +1,23 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Internal Codex calls now recover automatically when OpenAI retires their selected model from the ChatGPT-account Codex surface.
9
+
10
+ ## What to Tell Your User
11
+
12
+ A Codex model retirement no longer silently breaks classifications, gates, tone checks, and commitment checks fleet-wide. Instar retries that exact failure once on a known-good safe model while leaving every other error unchanged.
13
+
14
+ ## Summary of New Capabilities
15
+
16
+ - Exact unsupported-model classification for the ChatGPT-account retirement response.
17
+ - One bounded retry on the live-verified `gpt-5.4-mini` floor.
18
+ - No fallback for rate limits, authentication failures, unrelated 400s, timeouts, or network failures.
19
+ - Equivalent recovery in structured and legacy Codex execution modes.
20
+
21
+ ## Evidence
22
+
23
+ Boundary unit tests cover retirement recovery, non-retry error classes, and bounded fallback failure. Structured exec-path coverage proves the real spawn path retries with the safe model and succeeds. Full lint, build, and three-tier tests gate release.
@@ -0,0 +1,23 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Solo Codex agents now feed real rollout quota windows into the global job/session load-shed brake.
9
+
10
+ ## What to Tell Your User
11
+
12
+ A solo Codex agent stops starting work when its five-hour or weekly account window is exhausted. Missing, stale, unreadable, or incomplete Codex quota data now pauses new work conservatively instead of failing open into an unknown wall.
13
+
14
+ ## Summary of New Capabilities
15
+
16
+ - Authoritative `codex-rollout` quota state for the global brake.
17
+ - Healthy Codex windows allow work; exhausted windows shed it.
18
+ - Missing or invalid Codex readings persist explicit uncertainty and fail safe.
19
+ - Existing Claude OAuth-authoritative and JSONL-degraded behavior remains unchanged.
20
+
21
+ ## Evidence
22
+
23
+ Scoped unit coverage exercises both sides of the gate and every uncertainty boundary. Collector-to-manager integration proves persisted wall shedding and replacement of prior healthy headroom when the reader disappears. Full lint, build, and CI matrix gate release.
@@ -0,0 +1,21 @@
1
+ # ELI16 — Codex model retirements self-heal
2
+
3
+ ## What Changed
4
+
5
+ OpenAI can remove a model from the ChatGPT-account Codex surface without changing Instar. Previously, every small internal Codex judgment call using that model would begin failing until a person found the incident and manually changed the tier map. Instar now recognizes Codex's specific model-retirement response and retries that one call once with a live-verified safe model.
6
+
7
+ ## What to Tell Your User
8
+
9
+ A retired Codex model should no longer take down classifications, gates, tone checks, or commitment checks across the fleet. The recovery is intentionally narrow: it does not swap models for rate limits, login problems, network failures, or unrelated bad requests, so those real problems remain visible instead of being hidden behind a retry.
10
+
11
+ ## Summary of New Capabilities
12
+
13
+ - Classify Codex's exact ChatGPT-account “model not supported” response as an unsupported-model signal rather than generic authentication failure.
14
+ - Retry once on `gpt-5.4-mini`, the designated live-verified safe floor and a member of Instar's known Codex model registry.
15
+ - Preserve the original failure behavior for 429s, authentication errors, unrelated 400s, timeouts, and network failures.
16
+ - Stop after the fallback attempt and surface its error if it also fails; there is no recursive or unbounded retry path.
17
+ - Apply the same recovery to both the default structured exec path and the legacy plain-output kill-switch path.
18
+
19
+ ## Evidence
20
+
21
+ Unit coverage proves both sides of the classification boundary, the exact two-model attempt sequence, fallback failure surfacing, and non-retry behavior for neighboring errors. Exec-path coverage drives the real structured spawn helper through retirement and recovery. Existing provider, event-normalizer, lint, build, and three-tier suites remain the release gates.
@@ -0,0 +1,21 @@
1
+ # ELI16 — Solo Codex agents stop spawning into a quota wall
2
+
3
+ ## What Changed
4
+
5
+ Instar’s global quota brake already protected Claude and Gemini work, and the subscription pool already understood Codex quota. But a Codex agent with only one account had no producer feeding those real Codex windows into the global brake. When that account was exhausted—or when its quota reading disappeared—the agent could keep starting work that could not succeed.
6
+
7
+ ## What to Tell Your User
8
+
9
+ Solo Codex agents now read the same authoritative five-hour and weekly rollout windows already used by the subscription pool. Healthy headroom allows work normally. A full window stops new jobs and sessions. If the Codex reading is missing, stale, unreadable, or incomplete, the Codex brake fails safe and pauses new work instead of repeatedly spending attempts against an unknown wall.
10
+
11
+ ## Summary of New Capabilities
12
+
13
+ - Start the existing quota collector for Codex agents instead of skipping every non-Claude framework.
14
+ - Convert the existing rollout reader’s primary and secondary windows into the shared quota-state shape with `codex-rollout` provenance.
15
+ - Treat Codex rollout data as authoritative at the same load-shed decision layer as provider-native capacity signals.
16
+ - Persist explicit uncertainty when a previously healthy reading disappears, preventing stale headroom from silently keeping the gate open.
17
+ - Preserve Claude semantics: OAuth remains authoritative, JSONL remains bounded-degraded, and missing Claude data retains its existing behavior.
18
+
19
+ ## Evidence
20
+
21
+ Focused unit tests cover healthy, exhausted, missing, unreadable, and first-boot Codex states plus explicit Claude regression boundaries. Integration coverage drives collector through QuotaManager into the persisted quota file and proves both wall shedding and healthy-to-unknown fail-safe replacement.
@@ -0,0 +1,77 @@
1
+ # Side-Effects Review — Codex model-retirement fallback
2
+
3
+ **Version / slug:** `codex-model-retirement-fallback`
4
+ **Date:** 2026-07-10
5
+ **Author:** Instar-codey
6
+ **Second-pass reviewer:** not required
7
+
8
+ ## Summary of the change
9
+
10
+ `eventNormalizer.ts` now emits the existing `unsupported` error kind for Codex's exact ChatGPT-account model-retirement response. `CodexCliIntelligenceProvider` consumes that classified signal and retries once using the explicit `gpt-5.4-mini` safe-floor constant, after verifying it remains in `KNOWN_CODEX_MODEL_IDS`. Both structured and legacy exec modes use the same bounded authority.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - Codex upstream-error classification — modify — distinguish the model-retirement response from generic authentication errors.
15
+ - Internal Codex retry authority — add — permit one safe-floor retry only for the classified retirement signal.
16
+
17
+ ## 1. Over-block
18
+
19
+ No legitimate request is blocked. A successful first attempt is unchanged. Failures outside the exact retirement signature continue surfacing exactly as before. A caller already using the fallback floor is never retried, preventing a same-model duplicate call.
20
+
21
+ ## 2. Under-block
22
+
23
+ If OpenAI changes the retirement wording, the new response will surface rather than trigger recovery; this is deliberately fail-loud. The fallback model can itself be retired, in which case its error surfaces after the single retry. API-key-only model availability is not inferred from generic errors.
24
+
25
+ ## 3. Level-of-abstraction fit
26
+
27
+ The event normalizer owns provider-native error classification. The intelligence provider owns bounded execution recovery and already controls both spawn modes. The retry consumes the shared classified signal rather than creating a second raw-stderr policy. The known-model registry remains the authority for acceptable Codex model identities.
28
+
29
+ ## 4. Signal vs authority compliance
30
+
31
+ Required reference: [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
32
+
33
+ - [x] No — the brittle provider-signature detector produces the structured `unsupported` signal; the provider's narrowly enumerated recovery policy consumes it.
34
+
35
+ This is also a constrained protocol invariant, not conversational judgment. The detector cannot retry anything itself. The authority requires the exact classified condition, a different requested model, and a known registry member before acting.
36
+
37
+ ## 5. Interactions
38
+
39
+ - **Shadowing:** retirement classification runs before generic auth classification so the recoverable condition is no longer swallowed by the broader category.
40
+ - **Double-fire:** `evaluate()` owns the only retry. The mode-specific execution methods do not recurse and do not contain fallback logic.
41
+ - **Races:** there is no shared mutable retry state; the attempt bound is lexical to one evaluation.
42
+ - **Feedback loops:** the fallback invocation bypasses the outer catch, so a second retirement response surfaces instead of feeding back into another retry.
43
+ - **Observability:** `onModel` receives the original model and then the fallback model. Existing usage callbacks still reflect any structured usage that Codex emitted per attempt.
44
+
45
+ ## 6. External surfaces
46
+
47
+ Codex-backed agents gain automatic continuity for internal judgment calls during a model retirement. No endpoint, configuration, database, credential, user notice, external network integration, generated URL, or operator action is added. Other error types remain externally visible as failures.
48
+
49
+ ## 6b. Operator-surface quality
50
+
51
+ No operator surface — not applicable.
52
+
53
+ ## 7. Multi-machine posture
54
+
55
+ **Replicated by code rollout.** The fallback policy has no mutable state; every updated machine applies the same constant, classifier, registry check, and attempt bound independently. It emits no user-facing notice, holds no durable state, does not interact with topic transfer, and generates no URLs.
56
+
57
+ ## 8. Rollback cost
58
+
59
+ Pure code rollback and patch release. No state migration or agent repair is required. During rollback propagation, a newly retired model would again fail loudly rather than corrupt state or silently choose arbitrary models.
60
+
61
+ ## Conclusion
62
+
63
+ The recovery is intentionally smaller than a generic retry policy: one exact classified provider response, one registry-checked safe floor, one additional attempt. Boundary tests preserve visibility for neighboring errors and prove the fallback cannot loop. Clear to ship after full gates and CI.
64
+
65
+ ## Second-pass review
66
+
67
+ Not required by the instar-dev high-risk list: this changes an internal provider error-recovery path, not messaging, session lifecycle, dispatch, compaction, trust, coherence, or a sentinel/guard/gate/watchdog.
68
+
69
+ ## Evidence pointers
70
+
71
+ - `tests/unit/CodexCliIntelligenceProvider.test.ts`
72
+ - `tests/unit/codex-cli-provider-execjson.test.ts`
73
+ - `tests/unit/providers/adapters/openai-codex/observability/eventNormalizer.test.ts`
74
+
75
+ ## Class-Closure Declaration
76
+
77
+ No agent-authored-artifact defect and no self-triggered controller — not applicable.
@@ -0,0 +1,91 @@
1
+ # Side-Effects Review — Codex quota load-shed parity
2
+
3
+ **Version / slug:** `codex-quota-load-shed`
4
+ **Date:** 2026-07-10
5
+ **Author:** Instar-codey
6
+ **Second-pass reviewer:** framework_guard_review
7
+
8
+ ## Summary of the change
9
+
10
+ Boot now constructs `QuotaCollector` for `codex-cli`, using the existing rollout reader. The collector maps complete primary/secondary windows to shared `QuotaState`, persists explicit `quotaUnknown` when collection is missing or broken, and attributes both as `codex-rollout`. `QuotaTracker` treats complete Codex readings as authoritative and Codex uncertainty as fail-safe denial while preserving Claude semantics.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - Framework collector construction — modify — Codex gains a real quota producer; Claude construction is unchanged.
15
+ - Codex rollout mapping — add — provider windows become shared quota state.
16
+ - Solo-agent quota authority — modify — complete Codex state gates normally; Codex uncertainty sheds.
17
+ - Existing-agent awareness migration — add — all framework templates learn the new safety posture.
18
+
19
+ ## 1. Over-block
20
+
21
+ A Codex agent with no readable complete rollout pauses new jobs/sessions, including first boot before its first quota-bearing turn. This is intentional fail-safe behavior requested for a framework where unknown capacity may already be a hard wall. Existing live sessions are not killed. Claude missing data remains fail-open. Gemini's provider-native capacity signal is now explicitly authoritative; at the normal 100% wall behavior is unchanged, while an implausible >100% provider value now sheds all priorities instead of entering bounded-degraded mode—the safe direction for a native capacity signal.
22
+
23
+ ## 2. Under-block
24
+
25
+ The newest persisted rollout can lag actual provider consumption until Codex emits another rate-limit-bearing event. Thresholds therefore remain the existing brake thresholds, not a prediction system. If quota tracking is disabled entirely, this subsystem remains intentionally absent. A complete but old snapshot is rejected by the tracker’s existing staleness bound and then follows Codex fail-safe denial.
26
+
27
+ ## 3. Level-of-abstraction fit
28
+
29
+ The existing Codex rollout reader owns provider-log parsing. `QuotaCollector` owns normalization and persistence into the shared state shape. `QuotaTracker` remains the single job/session spawn authority. No second parser or parallel spawn gate is introduced.
30
+
31
+ ## 4. Signal vs authority compliance
32
+
33
+ Required reference: [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
34
+
35
+ - [x] No — the rollout reader and collector produce structured provider signals consumed by the existing quota authority.
36
+
37
+ Quota exhaustion and missing-data posture are constrained operational invariants, not conversational judgments. The tracker already owns this deterministic authority; the change supplies the missing Codex provenance and framework-specific uncertainty rule.
38
+
39
+ ## 5. Interactions
40
+
41
+ - **Shadowing:** the Codex collector replaces the previous explicit “no framework usage meter” skip only for `codex-cli`.
42
+ - **Double-fire:** a solo Codex agent has one `QuotaManager` and one collector. Subscription-pool polling writes account metadata, not this global quota file.
43
+ - **Races:** `QuotaTracker.updateState` retains its atomic temp-write/rename. Failed collection writes explicit uncertainty so a prior cached healthy state cannot survive invisibly.
44
+ - **Feedback loops:** shedding prevents new spawns; it does not start retries, migrations, or swaps. The next successful scheduled collection overwrites uncertainty and reopens the gate from real headroom.
45
+ - **Gemini scope:** `gemini-cli-capacity` joins the explicit authoritative-source set. A regression test locks its real-wall and over-wall behavior so this additive safety choice is deliberate rather than a silent ride-along.
46
+
47
+ ## 6. External surfaces
48
+
49
+ Codex agents may pause new background jobs and session spawns when capacity is exhausted or unknown. The existing quota-state file gains additive `codex-rollout` and `quotaUnknown` values. No endpoint, credential, network call, URL, or operator action is added; rollout reads are local and read-only.
50
+
51
+ ## 6b. Operator-surface quality
52
+
53
+ No operator surface — not applicable.
54
+
55
+ ## 7. Multi-machine posture
56
+
57
+ **Machine-local by design.** A rollout describes the Codex account/config home available on that machine, and the global spawn brake controls that machine’s work. Subscription-pool quota continues its separate replicated metadata path. This feature emits no direct user notice, holds only the existing per-machine quota-state file, does not strand topic state, and generates no URLs.
58
+
59
+ ## 8. Rollback cost
60
+
61
+ Pure code and additive-state rollback. Older readers ignore the extra fields/source at runtime only after code rollback; deleting the optional quota-state file is not required because the collector will replace it. No database migration or credential repair exists.
62
+
63
+ ## Conclusion
64
+
65
+ The change closes the last solo-Codex fail-open path at the existing choke point. The design deliberately persists uncertainty rather than letting yesterday’s healthy headroom survive a broken reader. Claude authority/degradation behavior is explicitly regression-tested. Clear to ship after scoped gates and authoritative CI.
66
+
67
+ ## Second-pass review
68
+
69
+ **Reviewer:** framework_guard_review
70
+
71
+ **First independent read: concern.** A corrupt quota-state file could return previously healthy cached Codex state, and a complete rollout without a valid capture timestamp was being stamped fresh. Both would let uncertainty masquerade as headroom.
72
+
73
+ **Resolution:** Codex now clears cached state on corrupt/stale file reads while Claude preserves last-known-good behavior. Collector authority additionally requires a finite capture timestamp no older than the configured freshness window and no more than five minutes in the future; otherwise it persists `quotaUnknown`. Adversarial unit tests cover cached-healthy → corrupt and missing-timestamp → deny. Revised concurrence recorded below.
74
+
75
+ **Final independent read: concur.** Fail-safe cache and timestamp handling are correct, Claude behavior is preserved, boot wiring is sound, and the reviewer’s focused suite passed 75/75.
76
+
77
+ **CI follow-up:** The intentional framework-specific corrupt-file catch is classified inline with the repository's narrow `@silent-fallback-ok` annotation. This changes no runtime behavior; it makes the already-reviewed fail-safe fallback explicit to the no-silent-fallbacks enforcement test.
78
+
79
+ **E2E clock follow-up:** The live Codex pool fixture now injects a fixed clock matching its recorded rollout. Its five-hour reset timestamp had crossed during CI, so the real poller correctly zeroed that expired window while the assertion still expected the pre-reset value. Freezing the fixture clock removes the wall-clock time bomb without changing production expiry behavior.
80
+
81
+ ## Evidence pointers
82
+
83
+ - `tests/unit/codex-quota-load-shed.test.ts`
84
+ - `tests/unit/quota-tracker.test.ts`
85
+ - `tests/unit/quota-tracker-pool-aware.test.ts`
86
+ - `tests/unit/quota-collector.test.ts`
87
+ - `tests/integration/codex-quota-load-shed.integration.test.ts`
88
+
89
+ ## Class-Closure Declaration
90
+
91
+ No agent-authored-artifact defect and no self-triggered controller — not applicable.