instar 1.3.399 → 1.3.401

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/dashboard/index.html +48 -18
  2. package/dist/commands/server.d.ts.map +1 -1
  3. package/dist/commands/server.js +73 -5
  4. package/dist/commands/server.js.map +1 -1
  5. package/dist/core/QuotaAwareScheduler.d.ts +96 -0
  6. package/dist/core/QuotaAwareScheduler.d.ts.map +1 -0
  7. package/dist/core/QuotaAwareScheduler.js +134 -0
  8. package/dist/core/QuotaAwareScheduler.js.map +1 -0
  9. package/dist/core/SessionManager.d.ts +6 -0
  10. package/dist/core/SessionManager.d.ts.map +1 -1
  11. package/dist/core/SessionManager.js +6 -0
  12. package/dist/core/SessionManager.js.map +1 -1
  13. package/dist/core/SessionRefresh.d.ts +18 -1
  14. package/dist/core/SessionRefresh.d.ts.map +1 -1
  15. package/dist/core/SessionRefresh.js +4 -1
  16. package/dist/core/SessionRefresh.js.map +1 -1
  17. package/dist/core/frameworkSessionLaunch.d.ts +10 -0
  18. package/dist/core/frameworkSessionLaunch.d.ts.map +1 -1
  19. package/dist/core/frameworkSessionLaunch.js +10 -6
  20. package/dist/core/frameworkSessionLaunch.js.map +1 -1
  21. package/dist/core/types.d.ts +18 -0
  22. package/dist/core/types.d.ts.map +1 -1
  23. package/dist/core/types.js.map +1 -1
  24. package/dist/scaffold/templates.d.ts.map +1 -1
  25. package/dist/scaffold/templates.js +1 -0
  26. package/dist/scaffold/templates.js.map +1 -1
  27. package/dist/server/AgentServer.d.ts +1 -0
  28. package/dist/server/AgentServer.d.ts.map +1 -1
  29. package/dist/server/AgentServer.js +1 -0
  30. package/dist/server/AgentServer.js.map +1 -1
  31. package/dist/server/routes.d.ts +2 -0
  32. package/dist/server/routes.d.ts.map +1 -1
  33. package/dist/server/routes.js +26 -0
  34. package/dist/server/routes.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/data/builtin-manifest.json +48 -48
  37. package/src/scaffold/templates.ts +1 -0
  38. package/upgrades/1.3.400.md +55 -0
  39. package/upgrades/1.3.401.md +30 -0
  40. package/upgrades/side-effects/dashboard-stream-phase3-ui.md +58 -0
  41. package/upgrades/side-effects/subscription-auth-scheduler.md +90 -0
@@ -0,0 +1,90 @@
1
+ # Side-Effects Review — QuotaAwareScheduler + continuity guarantee (P1.3)
2
+
3
+ ## Scope of change
4
+
5
+ - `src/core/QuotaAwareScheduler.ts` (new) — account selection + the swap-and-resume guarantee.
6
+ - `src/core/SessionRefresh.ts` — RefreshOptions gains optional `configHome`/`accountId`; the respawner gains an optional 4th `accountSwap` arg.
7
+ - `src/core/SessionManager.ts` — `spawnInteractiveSession` options gain optional `configHome` (→ `CLAUDE_CONFIG_DIR` via the launch builder) + `subscriptionAccountId` (→ session record).
8
+ - `src/core/frameworkSessionLaunch.ts` — `InteractiveLaunchOptions.configHome` → `CLAUDE_CONFIG_DIR` env (claude-code builder).
9
+ - `src/core/types.ts` — `Session.subscriptionAccountId?`; `InstarConfig.subscriptionPool?{swapSoftThresholdPct,autoSwapOnRateLimit}`.
10
+ - `src/commands/server.ts` — wires the scheduler (refreshFn=SessionRefresh, onNoAlternate=Attention), the DARK rate-limit auto-trigger, and threads `accountSwap` through `respawnSessionForTopic` → `spawnSessionForTopic`.
11
+ - `src/server/routes.ts` + `AgentServer.ts` — `POST /subscription-pool/swap` + RouteContext plumbing.
12
+ - tests (unit + e2e) + api.md.
13
+
14
+ ## The load-bearing concern: surgery on the session-restart path
15
+
16
+ This is the highest-authority change in the standard. The restart path
17
+ (SessionRefresh → respawn → spawn) is what every conversation — including the
18
+ agent's ability to reply to the operator — depends on. The safety design:
19
+
20
+ - **Additive-optional everywhere.** Every new parameter (`configHome`,
21
+ `accountId`, `accountSwap`) is optional and defaults to today's behaviour.
22
+ When no swap is requested — i.e. every existing restart, recovery, and spawn —
23
+ the code path is byte-for-byte unchanged. Confirmed: the existing
24
+ SessionRefresh suite passes after a one-line assertion update (the respawner
25
+ now receives a trailing `undefined` 4th arg; behaviour identical).
26
+ - **The swap preserves the conversation.** `claude --resume <uuid>` is agnostic
27
+ to `CLAUDE_CONFIG_DIR`, so resuming under a different account carries the full
28
+ conversation (verified: the launch builder applies BOTH `--resume` and the new
29
+ `CLAUDE_CONFIG_DIR` together). TopicResumeMap persists the uuid across the kill,
30
+ independent of account.
31
+
32
+ ## Authority / autonomy analysis
33
+
34
+ - **Auto-swap of live sessions ships DARK** behind
35
+ `config.subscriptionPool.autoSwapOnRateLimit` (default off). Only when the
36
+ operator enables it does a rate-limit escalation drive an automatic swap. The
37
+ manual `POST /subscription-pool/swap` route + the selection logic are always
38
+ available but never fire on their own.
39
+ - **Tier-2, operator-approved.** This change has real authority (restarts live
40
+ sessions, changes spawn env). The driving spec
41
+ (`subscription-auth-p1.3-scheduler.md`) is converged + `approved: true` by
42
+ Justin (Telegram topic 20905, 2026-06-07).
43
+ - **Honest no-op.** When a session hits a wall with no eligible alternate, the
44
+ scheduler does NOT restart it (nowhere to go) — it raises ONE deduped HIGH
45
+ Attention item and leaves the existing rate-limit back-off as the floor. No
46
+ false "swapped" claim (verified by test).
47
+
48
+ ## Failure modes considered
49
+
50
+ - No alternate account → honest report + Attention, session untouched (back-off floor).
51
+ - refreshFn (SessionRefresh) reports failure → surfaced as `refresh-failed`, not a false success.
52
+ - Account over the soft threshold / rate-limited / disabled → excluded from selection.
53
+ - Single-account pool → no alternate ever → effectively a no-op (the common case today).
54
+ - Rate-limit-event session not pool-managed (no `subscriptionAccountId`) → skipped, existing back-off unchanged.
55
+
56
+ ## Blast radius
57
+
58
+ Contained by the additive-optional design + the dark auto-trigger. With no
59
+ accounts enrolled and the flag off (the default), this code never executes a swap
60
+ — existing behaviour is wholly unchanged. The risk surface is the new swap path,
61
+ which is exercised only by the manual route or the explicitly-enabled auto-trigger.
62
+
63
+ ## Framework generality
64
+
65
+ The launch-abstraction change (`InteractiveLaunchOptions.configHome`) is
66
+ framework-agnostic in SHAPE but intentionally Claude-specific in EFFECT for now:
67
+
68
+ - The `configHome` option is read ONLY by the claude-code builder (→
69
+ `CLAUDE_CONFIG_DIR`). The codex-cli, gemini-cli, and pi-cli builders ignore it
70
+ entirely — passing it is a no-op for them, so non-Claude launches are
71
+ byte-for-byte unchanged. This is correct because per-account login isolation is
72
+ framework-specific: codex uses its own auth/config (a different env + login
73
+ flow), gemini likewise. There is no single cross-framework "config home" knob.
74
+ - This matches the standard's deliberate scope (Justin's decision 3: Claude-first).
75
+ The account-swap account-selection logic (QuotaAwareScheduler) is itself
76
+ framework-agnostic — it operates on pool accounts regardless of provider — and
77
+ the scheduler only filters to `claude-code`/`anthropic` accounts where the swap
78
+ mechanism is actually implemented today. Extending the swap mechanism to
79
+ codex-cli / gemini-cli (their own per-account config) is future work, not a
80
+ Claude-specific assumption baked into the abstraction: the option + the
81
+ scheduler are ready for it; only the per-builder env injection is Claude-only.
82
+ - Per the constitution's "Framework-Agnostic — and Framework-Optimizing": the
83
+ abstraction stays neutral (the option exists for all), the optimization is
84
+ per-framework (Claude gets CLAUDE_CONFIG_DIR; others get their own when built).
85
+
86
+ ## Migration / parity
87
+
88
+ `Session.subscriptionAccountId` + `InstarConfig.subscriptionPool` are additive-
89
+ optional (no migration needed). New route stays under the already-classified
90
+ `/subscription-pool` INTERNAL prefix (no CapabilityIndex change). Ships via dist.