instar 1.3.235 → 1.3.237
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/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +41 -0
- package/dist/commands/server.js.map +1 -1
- package/dist/core/CircuitBreakingIntelligenceProvider.d.ts +1 -1
- package/dist/core/CircuitBreakingIntelligenceProvider.d.ts.map +1 -1
- package/dist/core/CircuitBreakingIntelligenceProvider.js +5 -2
- package/dist/core/CircuitBreakingIntelligenceProvider.js.map +1 -1
- package/dist/core/IntelligenceRouter.d.ts +82 -0
- package/dist/core/IntelligenceRouter.d.ts.map +1 -0
- package/dist/core/IntelligenceRouter.js +108 -0
- package/dist/core/IntelligenceRouter.js.map +1 -0
- package/dist/core/ParallelActivityIndex.d.ts +62 -0
- package/dist/core/ParallelActivityIndex.d.ts.map +1 -0
- package/dist/core/ParallelActivityIndex.js +129 -0
- package/dist/core/ParallelActivityIndex.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +34 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/componentCategories.d.ts +37 -0
- package/dist/core/componentCategories.d.ts.map +1 -0
- package/dist/core/componentCategories.js +84 -0
- package/dist/core/componentCategories.js.map +1 -0
- package/dist/core/intelligenceProviderFactory.d.ts +8 -0
- package/dist/core/intelligenceProviderFactory.d.ts.map +1 -1
- package/dist/core/intelligenceProviderFactory.js +3 -3
- package/dist/core/intelligenceProviderFactory.js.map +1 -1
- package/dist/core/types.d.ts +26 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/GeminiLoopDriver.d.ts +112 -0
- package/dist/monitoring/GeminiLoopDriver.d.ts.map +1 -0
- package/dist/monitoring/GeminiLoopDriver.js +111 -0
- package/dist/monitoring/GeminiLoopDriver.js.map +1 -0
- package/dist/monitoring/ParallelWorkOverlap.d.ts +59 -0
- package/dist/monitoring/ParallelWorkOverlap.d.ts.map +1 -0
- package/dist/monitoring/ParallelWorkOverlap.js +86 -0
- package/dist/monitoring/ParallelWorkOverlap.js.map +1 -0
- package/dist/monitoring/ParallelWorkSentinel.d.ts +59 -0
- package/dist/monitoring/ParallelWorkSentinel.d.ts.map +1 -0
- package/dist/monitoring/ParallelWorkSentinel.js +79 -0
- package/dist/monitoring/ParallelWorkSentinel.js.map +1 -0
- package/dist/providers/adapters/gemini-cli/transport/geminiSpawn.d.ts +14 -0
- package/dist/providers/adapters/gemini-cli/transport/geminiSpawn.d.ts.map +1 -1
- package/dist/providers/adapters/gemini-cli/transport/geminiSpawn.js +16 -0
- package/dist/providers/adapters/gemini-cli/transport/geminiSpawn.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +10 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +1 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +33 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +10 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts +4 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +44 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +64 -64
- package/src/scaffold/templates.ts +10 -0
- package/upgrades/1.3.236.md +53 -0
- package/upgrades/1.3.237.md +82 -0
- package/upgrades/side-effects/gemini-multi-turn-loop-driver.md +56 -0
- package/upgrades/side-effects/parallel-activity-coherence.md +85 -0
- package/upgrades/side-effects/per-component-framework-routing.md +88 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: minor -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
First increment (the pure engine) of the **Gemini multi-turn loop-driver**
|
|
9
|
+
(`need-gem-002`) — the mechanism that will let a Gemini mentee sustain a
|
|
10
|
+
multi-turn task instead of being bounded to one-shots (the #1 program-need from
|
|
11
|
+
the codey-to-gemini apprenticeship retro).
|
|
12
|
+
|
|
13
|
+
A new `GeminiLoopDriver` (`src/monitoring/GeminiLoopDriver.ts`) drives a goal
|
|
14
|
+
across turns. Unlike Claude/codex — which run as persistent hook-capable sessions
|
|
15
|
+
and re-prompt via the autonomous Stop hook — gemini runs as one-shots, so the loop
|
|
16
|
+
is driven EXTERNALLY: turn 1 is a one-shot that establishes a session, and each
|
|
17
|
+
later turn re-spawns gemini with the proven native resume path. Because gemini
|
|
18
|
+
restores the session's context itself, the driver re-prompts with only the next
|
|
19
|
+
instruction — never the accumulated transcript — which is the quota-efficient
|
|
20
|
+
design that respects the subscription-auth / no-overspend rule.
|
|
21
|
+
|
|
22
|
+
The engine is fully dependency-injected (the gemini spawn, an optional budget
|
|
23
|
+
gate, the session-handle capture, sleep, clock), so its loop logic is exercised
|
|
24
|
+
by 14 unit tests with zero real gemini calls and zero quota. It terminates on a
|
|
25
|
+
done-sentinel, a turn cap, a budget-gate halt, a spawn failure, or a
|
|
26
|
+
handle-capture failure (it ABORTS rather than resuming a foreign session). A
|
|
27
|
+
companion transport helper `buildGeminiResumeArgv` adds the `-r <handle>` resume
|
|
28
|
+
argv (keeping the explicit `-m` that bypasses gemini-cli's flaky pre-turn
|
|
29
|
+
model-router classifier).
|
|
30
|
+
|
|
31
|
+
This increment is **dark and unwired**: nothing invokes the engine yet. Lifecycle
|
|
32
|
+
invocation (a budget-gated route + the apprenticeship machinery calling it, the
|
|
33
|
+
real `--list-sessions` handle parser, and a config flag) is the next increment,
|
|
34
|
+
which is where the §6 budget-guardrail defaults are finalized. Spec:
|
|
35
|
+
`docs/specs/gemini-multi-turn-loop-driver.md`.
|
|
36
|
+
|
|
37
|
+
**Your agent can now see what all its hands are doing across topics at once.** A new
|
|
38
|
+
cross-topic Activity Index reads your existing per-topic intent and presents one view:
|
|
39
|
+
every topic, its current focus, high-specificity tags, and whether a session is live on
|
|
40
|
+
it. This is the antidote to self-blindness — starting work in one topic that another topic
|
|
41
|
+
already finished (the exact thing that happened in the resource-tracking workstream, where
|
|
42
|
+
one topic re-specced CPU work another had already shipped).
|
|
43
|
+
|
|
44
|
+
Crucially, this does NOT add a new store. The design review found that the per-topic focus
|
|
45
|
+
data already exists (the Topic-Intent layer, updated structurally on every turn), so this is
|
|
46
|
+
a thin read-aggregator over it — no duplication, no new write path to remember.
|
|
47
|
+
|
|
48
|
+
This is Phase A (the read surface). The proactive overlap councilor — a sentinel that
|
|
49
|
+
notices "two of your topics are working on the same thing" and tells you — is Phase B and
|
|
50
|
+
ships separately (and dark, because a false-positive nudge is worse than silence).
|
|
51
|
+
|
|
52
|
+
## What to Tell Your User
|
|
53
|
+
|
|
54
|
+
Nothing is live to announce yet. This is internal groundwork — a tested engine
|
|
55
|
+
that, once wired up in a following change, will let the Gemini agent work through
|
|
56
|
+
a multi-step task on its own (on subscription login, never an API key) instead of
|
|
57
|
+
stopping after one reply. It ships turned off and disconnected, so it changes
|
|
58
|
+
nothing about how I work today. I will only surface it as a real capability once
|
|
59
|
+
it is wired, budget-guarded, and verified.
|
|
60
|
+
|
|
61
|
+
Your agent is now less likely to duplicate work across different conversations. It can list
|
|
62
|
+
what each of its topics is working on in one place, so before it starts something big it can
|
|
63
|
+
notice another topic already has it covered. Nothing to configure; it reads data the agent
|
|
64
|
+
already keeps.
|
|
65
|
+
|
|
66
|
+
## Summary of New Capabilities
|
|
67
|
+
|
|
68
|
+
- `GET /parallel-work/activities` — read-only cross-topic index: per topic, its current focus,
|
|
69
|
+
high-specificity tags, freshness, and whether a session is live on it.
|
|
70
|
+
- A specificity-aware tag extractor that ignores generic boilerplate (so two topics that both
|
|
71
|
+
say "fix the test" don't look like the same work) and keeps genuine shared entities.
|
|
72
|
+
|
|
73
|
+
## Evidence
|
|
74
|
+
|
|
75
|
+
- Converged spec (2-reviewer adversarial + integration pass that RESHAPED the design — from a
|
|
76
|
+
new store to a thin index over the existing Topic-Intent layer, with a distinct
|
|
77
|
+
/parallel-work prefix to avoid the existing Coherence-Gate naming collision):
|
|
78
|
+
docs/specs/parallel-activity-coherence.md.
|
|
79
|
+
- All three test tiers green: 7 unit (extractTags specificity boundary incl. cpu vs
|
|
80
|
+
cpu-sampling; focus derivation goal>decision>purpose; empty-dir ⇒ []), 2 integration
|
|
81
|
+
(200/503), 3 e2e (feature-alive on the real AgentServer init path + Bearer-auth + read-only).
|
|
82
|
+
tsc clean.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Side-Effects Review — Gemini multi-turn loop-driver (engine increment)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `gemini-multi-turn-loop-driver`
|
|
4
|
+
**Date:** `2026-06-04`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required` (dark + unwired engine increment; the
|
|
7
|
+
spendable surface — the invoking route/wiring — is a separate later increment
|
|
8
|
+
that will carry its own review)
|
|
9
|
+
|
|
10
|
+
## Summary of the change
|
|
11
|
+
|
|
12
|
+
Adds `GeminiLoopDriver` (`src/monitoring/GeminiLoopDriver.ts`), a dependency-
|
|
13
|
+
injected engine that drives a gemini task across turns via the native
|
|
14
|
+
`gemini -r <handle>` resume path (turn 1 one-shot establishes the session; later
|
|
15
|
+
turns resume by a stable handle, re-prompting with only the next instruction so
|
|
16
|
+
no transcript is re-sent). Adds the `buildGeminiResumeArgv` transport helper. The
|
|
17
|
+
engine is NOT invoked anywhere yet (dark + unwired); only its 14 unit tests
|
|
18
|
+
exercise it.
|
|
19
|
+
|
|
20
|
+
## Decision-point inventory
|
|
21
|
+
|
|
22
|
+
The engine makes five terminal decisions per run: done-sentinel detected,
|
|
23
|
+
turn-cap reached, budget-gate closed, spawn failure (non-zero exit), and
|
|
24
|
+
handle-capture failure. Each is covered both-sides in the unit suite.
|
|
25
|
+
|
|
26
|
+
## 1. Over-block
|
|
27
|
+
|
|
28
|
+
**What legitimate inputs does this change reject?** Nothing in production today —
|
|
29
|
+
the engine is unwired, so no caller is gated by it. Within a run: a closed budget
|
|
30
|
+
gate halts before spawning (intended — that IS the overspend guard), and a
|
|
31
|
+
`null` handle-capture aborts the loop after turn 1 rather than resuming (intended
|
|
32
|
+
— resuming `latest` could hijack a foreign session; aborting is the safe choice).
|
|
33
|
+
The `maxTurns` clamp floors at 1, so a 0/negative cap still runs exactly one turn
|
|
34
|
+
rather than zero or infinite.
|
|
35
|
+
|
|
36
|
+
## 2. Under-block
|
|
37
|
+
|
|
38
|
+
**What does this still miss?** The engine does not itself enforce a token budget —
|
|
39
|
+
it delegates to the injected `budgetGate`, which is wired to the real
|
|
40
|
+
QuotaTracker only in the (later) invocation increment; an integrator that injects
|
|
41
|
+
a permissive gate gets no budget protection. It does not detect a wedged turn
|
|
42
|
+
mid-spawn (it relies on the injected spawn's own timeout, which the real
|
|
43
|
+
`spawnGeminiAndWait` provides). It does not yet verify the empirically-noted 3+
|
|
44
|
+
turn resume-accumulation (a live-verify gate recorded in the spec before any
|
|
45
|
+
enable). Completion relies on the mentee emitting the sentinel OR (later) a judge;
|
|
46
|
+
a mentee that finishes silently without the sentinel runs to the turn cap.
|
|
47
|
+
|
|
48
|
+
## 3. Level-of-abstraction fit
|
|
49
|
+
|
|
50
|
+
**Right layer?** Yes. The engine sits in `src/monitoring/` beside the other
|
|
51
|
+
driver/lifecycle components and depends only on the gemini transport's pure argv
|
|
52
|
+
builders (`buildGeminiOneShotArgv` / `buildGeminiResumeArgv`); all I/O is
|
|
53
|
+
injected, so the subscription-auth guarantee stays in the transport
|
|
54
|
+
(`buildGeminiChildEnv` strips billing env) and is reused, not re-implemented. The
|
|
55
|
+
resume argv helper lives in the transport module next to the one-shot builder,
|
|
56
|
+
keeping the gemini-cli invocation surface in one place.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Side-Effects Review — Parallel-Work Awareness, Phase A core (cross-topic index)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `parallel-activity-coherence`
|
|
4
|
+
**Date:** `2026-06-03`
|
|
5
|
+
**Author:** `Echo (instar-dev agent)`
|
|
6
|
+
**Tier:** `2` (new capability; converged + approved spec: docs/specs/parallel-activity-coherence.md)
|
|
7
|
+
**Second-pass reviewer:** `not required (the converged spec carries a 2-reviewer adversarial+integration pass that reshaped it)`
|
|
8
|
+
|
|
9
|
+
## Summary of the change
|
|
10
|
+
Phase A CORE of the Parallel-Work Awareness feature: `ParallelActivityIndex` — a thin
|
|
11
|
+
CROSS-topic read aggregator over the EXISTING Topic-Intent Layer. It does NOT add a new
|
|
12
|
+
per-topic store (convergence: that would duplicate `TopicIntentStore`); it only READS the
|
|
13
|
+
existing per-topic intent files and presents the cross-topic view ("all my topics + what
|
|
14
|
+
each is working on") that genuinely did not exist. Plus `extractTags` — high-specificity
|
|
15
|
+
token extraction (drops generic boilerplate so two "fix the test" topics don't false-match).
|
|
16
|
+
|
|
17
|
+
New:
|
|
18
|
+
- `src/core/ParallelActivityIndex.ts` — enumerate `{stateDir}/topic-intent/*.json`; per
|
|
19
|
+
topic derive `focus` (latest goal > latest decision > purpose), `tags` (high-specificity
|
|
20
|
+
tokens), `refCount`, `updatedAt`, `running`. Read-only; an injectable `getRefs` seam for
|
|
21
|
+
testability (production uses the real `TopicIntentStore.getRefsAtOrAbove`).
|
|
22
|
+
- `tests/unit/parallel-activity-index.test.ts` — 7 tests.
|
|
23
|
+
|
|
24
|
+
Phase A is now COMPLETE: `GET /parallel-work/activities` route + CapabilityIndex entry
|
|
25
|
+
(`parallelWork`, prefixes `['/parallel-work']`) + server wiring (constructed in AgentServer
|
|
26
|
+
in its OWN try/catch, injected into routeCtx, `running` enriched from the live session list)
|
|
27
|
+
+ integration/e2e tests + CLAUDE.md template + migrateClaudeMd agent-awareness. The overlap
|
|
28
|
+
ParallelWorkSentinel is Phase B (ships dark), a separate PR.
|
|
29
|
+
|
|
30
|
+
## Phase B (overlap sentinel core — added to this PR)
|
|
31
|
+
- `src/monitoring/ParallelWorkOverlap.ts` — the PURE cross-topic overlap detector: activity
|
|
32
|
+
gate (only recently-worked topics), IDF/specificity weighting over the already-boilerplate-
|
|
33
|
+
filtered tags, ≥1 shared high-specificity tag required, self-exclusion, signature = sorted
|
|
34
|
+
shared-tag set, + `signatureChangedMaterially` (hysteresis) and `pairKey`. No I/O, no real
|
|
35
|
+
time (injected nowMs) ⇒ exhaustively unit-tested (11 tests).
|
|
36
|
+
- `src/monitoring/ParallelWorkSentinel.ts` — the stateful councilor: `tick(nowMs)` reads the
|
|
37
|
+
activities, runs the detector, and emits ONE `overlap` nudge per genuinely-fresh overlap.
|
|
38
|
+
Containment: PAIR-KEYED cooldown (survives focus edits), signature hysteresis (no re-nag on
|
|
39
|
+
a one-token tweak), audit sink for every transition. SIGNAL-ONLY (emits an event; never
|
|
40
|
+
gates/mutates). 6 tests. The cadence + lease-gating + server wiring + config (ships dark) +
|
|
41
|
+
the nudge→Telegram/sentinel-events routing are the remaining wiring on this branch.
|
|
42
|
+
|
|
43
|
+
## Decision-point inventory
|
|
44
|
+
- `ParallelActivityIndex` read aggregation — **add** — pure read over existing state; no
|
|
45
|
+
block/allow surface, no mutation.
|
|
46
|
+
- `ParallelWorkOverlap` / `ParallelWorkSentinel` — **add** — pure detector + a signal-only
|
|
47
|
+
EventEmitter; no block/allow surface, no mutation. The nudge informs; the agent decides.
|
|
48
|
+
|
|
49
|
+
## 1./2. Over/Under-block
|
|
50
|
+
No block/allow surface. Signal-only observability over existing data.
|
|
51
|
+
|
|
52
|
+
## 3. Level-of-abstraction fit
|
|
53
|
+
Correct — it reads the Topic-Intent layer (the right source for "what each topic intends")
|
|
54
|
+
and presents a cross-topic view; it does not re-implement intent capture or storage.
|
|
55
|
+
|
|
56
|
+
## 4. Signal vs authority
|
|
57
|
+
**Reference:** docs/signal-vs-authority.md. [x] No block/allow surface. A read aggregator.
|
|
58
|
+
|
|
59
|
+
## 5. Interactions
|
|
60
|
+
- **No new store / no new write path** — reuses `TopicIntentStore` (which already has the
|
|
61
|
+
structural per-turn write path via TopicIntentCapture). No duplication, no second decay engine.
|
|
62
|
+
- **False-positive containment starts here:** `extractTags` strips generic boilerplate +
|
|
63
|
+
requires specificity (compound/identifier tokens, or rare ≥4-char words), so the Phase B
|
|
64
|
+
overlap comparison rests on genuine shared entities, not coincidental generic words.
|
|
65
|
+
- **Robustness:** missing intent dir ⇒ empty list; a corrupt/again topic file ⇒ that topic
|
|
66
|
+
contributes no refs (swallowed), never throws.
|
|
67
|
+
|
|
68
|
+
## 6. External surfaces
|
|
69
|
+
- (Remaining) `GET /parallel-work/activities` + CapabilityIndex classification (the #727
|
|
70
|
+
lesson). No persistent state of its own (reads existing topic-intent files). Config flag
|
|
71
|
+
(`monitoring.parallelWorkSentinel`) lands with the sentinel (Phase B), ships dark.
|
|
72
|
+
|
|
73
|
+
## 7. Rollback cost
|
|
74
|
+
Pure additive read code. Revert ⇒ gone, no state, no migration.
|
|
75
|
+
|
|
76
|
+
## Conclusion
|
|
77
|
+
Phase A core complete + unit-tested (7 tests, tsc clean): the cross-topic index over the
|
|
78
|
+
existing Topic-Intent layer + specificity-aware tag extraction. Non-duplicative (the
|
|
79
|
+
convergence-mandated reshape). Route + wiring + integration/e2e + agent-awareness follow on
|
|
80
|
+
this branch; the overlap ParallelWorkSentinel is Phase B (ships dark).
|
|
81
|
+
|
|
82
|
+
## Evidence pointers
|
|
83
|
+
- `tsc --noEmit` clean; `vitest run tests/unit/parallel-activity-index.test.ts` → 7/7
|
|
84
|
+
(extractTags specificity boundary incl. the cpu vs cpu-sampling case; focus derivation
|
|
85
|
+
goal>decision>purpose; tags; running/nickname; empty-dir ⇒ []).
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Side-Effects Review — Per-component framework routing (B1)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `per-component-framework-routing`
|
|
4
|
+
**Date:** `2026-06-03`
|
|
5
|
+
**Author:** `Echo (instar-dev agent)`
|
|
6
|
+
**Tier:** `2` (new capability; converged + approved spec: docs/specs/per-component-framework-routing.md)
|
|
7
|
+
**Second-pass reviewer:** `not required (the converged spec already carries a 2-reviewer adversarial+integration pass)`
|
|
8
|
+
|
|
9
|
+
## Summary of the change
|
|
10
|
+
Adds an `IntelligenceRouter` at the single LLM funnel so different internal components
|
|
11
|
+
(sentinels, gates, …) can be routed to different agentic frameworks (e.g. all sentinels on
|
|
12
|
+
Codex while the agent stays on Claude), to move that LLM chatter off the Claude rate-limit
|
|
13
|
+
budget. ABSENT-by-default config ⇒ byte-identical to today.
|
|
14
|
+
|
|
15
|
+
New / changed:
|
|
16
|
+
- `src/core/componentCategories.ts` (NEW) — component-name → category registry + resolver.
|
|
17
|
+
- `src/core/IntelligenceRouter.ts` (NEW) — funnel-level, per-call, per-framework routing with
|
|
18
|
+
per-framework circuit breakers and circuit-aware fallback.
|
|
19
|
+
- `src/core/intelligenceProviderFactory.ts` — additive `breaker?` option threaded to the wrap
|
|
20
|
+
calls (lets the router give each framework its OWN breaker).
|
|
21
|
+
- `src/core/CircuitBreakingIntelligenceProvider.ts` — `wrapIntelligenceWithCircuitBreaker`
|
|
22
|
+
gains an optional `breaker` param (default unchanged = global singleton).
|
|
23
|
+
- `src/core/types.ts` — additive `attribution.category?` on IntelligenceOptions; additive
|
|
24
|
+
`sessions.componentFrameworks?` config (TYPE-ONLY — NOT added to ConfigDefaults).
|
|
25
|
+
- `src/commands/server.ts` — wrap the shared provider in the router in its OWN try/catch.
|
|
26
|
+
- `tests/unit/intelligence-router.test.ts` (NEW) — 11 tests.
|
|
27
|
+
|
|
28
|
+
## Decision-point inventory
|
|
29
|
+
- `IntelligenceRouter.evaluate` routing — **add** — chooses WHICH framework answers; no
|
|
30
|
+
block/allow authority (providers are signal). The one safety branch is fallback (D4).
|
|
31
|
+
- `wrapIntelligenceWithCircuitBreaker` / factory `breaker?` — **modify (additive)** — default
|
|
32
|
+
path unchanged; only the router passes a distinct breaker.
|
|
33
|
+
|
|
34
|
+
## 1. Over-block / 2. Under-block
|
|
35
|
+
No block/allow surface — providers are SIGNAL. The router cannot block a running agent; the
|
|
36
|
+
worst it does is degrade-and-report (D4). Unconfigured, it is a transparent passthrough.
|
|
37
|
+
|
|
38
|
+
## 3. Level-of-abstraction fit
|
|
39
|
+
Correct — the router sits at the existing `CircuitBreakingIntelligenceProvider` funnel (the
|
|
40
|
+
one chokepoint every `.evaluate()` already passes), so it covers ALL callers (including the
|
|
41
|
+
config-path and inline-closure ones) without editing 38 call sites — Structure > Willpower.
|
|
42
|
+
|
|
43
|
+
## 4. Signal vs authority compliance
|
|
44
|
+
**Reference:** docs/signal-vs-authority.md. [x] No block/allow surface of its own. Routing
|
|
45
|
+
changes which model answers; it adds no gate. The per-framework breakers are the existing
|
|
46
|
+
breaker authority, now correctly ISOLATED per framework (a Claude trip no longer pauses Codex)
|
|
47
|
+
— a correctness improvement, not a new authority.
|
|
48
|
+
|
|
49
|
+
## 5. Interactions
|
|
50
|
+
- **Breaker isolation:** each non-default framework gets a distinct `new LlmCircuitBreaker()`
|
|
51
|
+
(proven by unit test — a routed call reaches a different provider instance than the default).
|
|
52
|
+
The default framework keeps the global singleton, so status/health surfaces are unchanged for
|
|
53
|
+
it. (Per-framework breaker states are additionally surfaced via GET /intelligence/routing —
|
|
54
|
+
part 2 of B1, see "Remaining".)
|
|
55
|
+
- **Fallback (D4):** binary-missing → degrade to default + DegradationReporter (no silent
|
|
56
|
+
fallback — composes with Task-1's re-armed gate); rate-limited → LlmCircuitOpenError
|
|
57
|
+
propagates and the caller swallows it into its heuristic (NO herd onto Claude).
|
|
58
|
+
- **Cascade-503:** the router is built in its OWN try/catch in server boot; a build failure
|
|
59
|
+
leaves the raw provider, never 503s the server.
|
|
60
|
+
- **Config:** type-only; NOT in ConfigDefaults (applyDefaults deep-merge would otherwise inject
|
|
61
|
+
it everywhere and break absent-equals-unchanged).
|
|
62
|
+
|
|
63
|
+
## 6. External surfaces
|
|
64
|
+
- (Remaining in this PR) `GET /intelligence/routing` read-only surface + its CapabilityIndex
|
|
65
|
+
classification (the #727 lesson). No persistent state. Config: `sessions.componentFrameworks`
|
|
66
|
+
(opt-in, absent by default).
|
|
67
|
+
|
|
68
|
+
## 7. Rollback cost
|
|
69
|
+
Pure additive + opt-in. Remove `componentFrameworks` (or revert) → every call routes to the
|
|
70
|
+
single shared provider exactly as today. No state, no migration.
|
|
71
|
+
|
|
72
|
+
## Conclusion
|
|
73
|
+
B1 complete across all three test tiers (tsc clean): per-call funnel resolution,
|
|
74
|
+
per-framework breaker isolation, circuit-aware fallback, live-config (hot), the category
|
|
75
|
+
registry, factory breaker-threading, config type, server wiring, the `GET /intelligence/routing`
|
|
76
|
+
read surface (+ CapabilityIndex INTERNAL_PREFIXES classification — the #727 lesson),
|
|
77
|
+
CLAUDE.md agent-awareness (template + migrateClaudeMd for existing agents). Tests: 11 unit
|
|
78
|
+
(`intelligence-router.test.ts`) + 3 integration (`intelligence-routing-routes.test.ts`,
|
|
79
|
+
200/503) + 3 e2e (`intelligence-routing-lifecycle.test.ts`, feature-alive on the real
|
|
80
|
+
AgentServer init path + Bearer-auth + read-only). The design was converged (2-reviewer
|
|
81
|
+
adversarial+integration) which corrected the breaker-isolation and resolution-point design
|
|
82
|
+
before any code — see the spec's Convergence Report. B2 (gates/reflectors + per-framework
|
|
83
|
+
spend accounting + dashboard view) is a deliberate follow-up.
|
|
84
|
+
|
|
85
|
+
## Evidence pointers
|
|
86
|
+
- `tsc --noEmit` clean.
|
|
87
|
+
- `vitest run tests/unit/intelligence-router.test.ts` → 11/11 pass (resolution precedence,
|
|
88
|
+
dispatch, per-framework instance isolation, fallback both modes, live-config hot, for() surface).
|