instar 1.3.466 → 1.3.468

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 (60) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +11 -1
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +6 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/CartographerTree.d.ts +124 -0
  8. package/dist/core/CartographerTree.d.ts.map +1 -0
  9. package/dist/core/CartographerTree.js +360 -0
  10. package/dist/core/CartographerTree.js.map +1 -0
  11. package/dist/core/EnrollmentWizard.d.ts +18 -1
  12. package/dist/core/EnrollmentWizard.d.ts.map +1 -1
  13. package/dist/core/EnrollmentWizard.js +22 -2
  14. package/dist/core/EnrollmentWizard.js.map +1 -1
  15. package/dist/core/PostUpdateMigrator.d.ts +20 -0
  16. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  17. package/dist/core/PostUpdateMigrator.js +61 -0
  18. package/dist/core/PostUpdateMigrator.js.map +1 -1
  19. package/dist/core/ProactiveSwapMonitor.d.ts.map +1 -1
  20. package/dist/core/ProactiveSwapMonitor.js +7 -0
  21. package/dist/core/ProactiveSwapMonitor.js.map +1 -1
  22. package/dist/core/ProjectMapper.d.ts.map +1 -1
  23. package/dist/core/ProjectMapper.js +3 -5
  24. package/dist/core/ProjectMapper.js.map +1 -1
  25. package/dist/core/SessionManager.d.ts +10 -0
  26. package/dist/core/SessionManager.d.ts.map +1 -1
  27. package/dist/core/SessionManager.js +28 -0
  28. package/dist/core/SessionManager.js.map +1 -1
  29. package/dist/core/SessionRefresh.d.ts.map +1 -1
  30. package/dist/core/SessionRefresh.js +13 -0
  31. package/dist/core/SessionRefresh.js.map +1 -1
  32. package/dist/core/ensureInteractiveReady.d.ts +58 -0
  33. package/dist/core/ensureInteractiveReady.d.ts.map +1 -0
  34. package/dist/core/ensureInteractiveReady.js +114 -0
  35. package/dist/core/ensureInteractiveReady.js.map +1 -0
  36. package/dist/core/skipDirs.d.ts +9 -0
  37. package/dist/core/skipDirs.d.ts.map +1 -0
  38. package/dist/core/skipDirs.js +13 -0
  39. package/dist/core/skipDirs.js.map +1 -0
  40. package/dist/scaffold/templates.d.ts.map +1 -1
  41. package/dist/scaffold/templates.js +1 -0
  42. package/dist/scaffold/templates.js.map +1 -1
  43. package/dist/server/AgentServer.d.ts +1 -0
  44. package/dist/server/AgentServer.d.ts.map +1 -1
  45. package/dist/server/AgentServer.js +1 -0
  46. package/dist/server/AgentServer.js.map +1 -1
  47. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  48. package/dist/server/CapabilityIndex.js +16 -0
  49. package/dist/server/CapabilityIndex.js.map +1 -1
  50. package/dist/server/routes.d.ts +2 -0
  51. package/dist/server/routes.d.ts.map +1 -1
  52. package/dist/server/routes.js +58 -0
  53. package/dist/server/routes.js.map +1 -1
  54. package/package.json +1 -1
  55. package/src/data/builtin-manifest.json +66 -66
  56. package/src/scaffold/templates.ts +1 -0
  57. package/upgrades/1.3.467.md +80 -0
  58. package/upgrades/1.3.468.md +25 -0
  59. package/upgrades/side-effects/cartographer-doc-tree-schema.md +82 -0
  60. package/upgrades/side-effects/onboarding-safe-pinswap.md +49 -0
@@ -0,0 +1,80 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Fixes the 2026-06-09 incident where subscription-pool **pinning** and **account
9
+ swap** relaunched interactive sessions into pool-account config homes that were
10
+ enrolled via headless `claude auth login` — homes with valid OAuth tokens but
11
+ WITHOUT the interactive first-launch onboarding flags. Every relaunched session
12
+ wedged on Claude Code's onboarding screens (OAuth-authorize browser-tab spam +
13
+ the Bypass-Permissions accept screen); ~8 live sessions froze at once until the
14
+ operator logged in manually.
15
+
16
+ New util `ensureInteractiveReady(configHome)` idempotently seeds the three
17
+ local trust-acknowledgement flags (`hasCompletedOnboarding`,
18
+ `bypassPermissionsModeAccepted`, `hasTrustDialogAccepted`) in
19
+ `<configHome>/.claude.json`, preserving every other key and **never touching
20
+ `oauthAccount`/tokens** (an unparseable file is refused, not rewritten; writes
21
+ are atomic). It is fail-safe by contract — a launch can never crash on it.
22
+
23
+ Called everywhere a session can enter a pool home, so the wedge is impossible
24
+ by construction:
25
+
26
+ 1. **Enrollment** — `EnrollmentWizard.complete()` seeds a freshly-enrolled
27
+ claude-code home immediately.
28
+ 2. **Pinned launches** — both SessionManager pin lanes (headless +
29
+ interactive-reroute) and the interactive account-swap lane seed before
30
+ setting `CLAUDE_CONFIG_DIR`.
31
+ 3. **Swaps** — `SessionRefresh` seeds the target home BEFORE the kill+respawn.
32
+ 4. **Existing homes** — a `PostUpdateMigrator` sweep seeds every claude-code
33
+ pool account's existing home once on update (stale entries skipped, never
34
+ created).
35
+
36
+ ## What to Tell Your User
37
+
38
+ If I run on a pool of Claude accounts, moving my sessions between accounts
39
+ (when one hits its weekly limit) used to be able to freeze them on Claude's
40
+ "first launch" welcome screens — the account was logged in, but nobody had
41
+ ever clicked through the one-time setup dialogs for that account's config
42
+ folder. That's fixed at every layer now: new accounts are made
43
+ interactive-ready the moment they're enrolled, every launch double-checks, and
44
+ existing accounts get fixed automatically on this update. Account swaps should
45
+ now be invisible — same conversation, different account, no frozen sessions
46
+ and no browser-tab spam.
47
+
48
+ ## Summary of New Capabilities
49
+
50
+ | Capability | How to Use |
51
+ |-----------|-----------|
52
+ | Pool config homes are onboarding-safe by construction (enrollment + every pinned/swapped launch) | automatic — no config |
53
+ | Existing pool homes seeded once on update | automatic — PostUpdateMigrator sweep |
54
+ | `ensureInteractiveReady(configHome)` util for any future launch lane | `src/core/ensureInteractiveReady.ts` |
55
+
56
+ ## Evidence
57
+
58
+ Live state at the incident (this machine): `sagemind-justin` and `sagemind-dawn`
59
+ homes were fully headless (no flags), `justin-gmail` had onboarded=true but
60
+ bypass=false — exactly the homes whose sessions wedged; the two complete homes'
61
+ sessions were unaffected. The OAuth tokens were present in every case.
62
+
63
+ After the change:
64
+ - `tests/unit/ensure-interactive-ready.test.ts` — 14 cases: missing-file
65
+ create, partial merge, flag-false reseed, idempotency (mtime-stable second
66
+ call), oauthAccount/token preservation, tilde expansion, unparseable/
67
+ non-object refusal with bytes preserved, unreadable fail-safe,
68
+ requireExistingHome both sides.
69
+ - `tests/unit/PostUpdateMigrator-subscriptionPoolInteractiveReady.test.ts` — 8
70
+ cases incl. one-bad-home-never-aborts-the-sweep and full-migrate() wiring.
71
+ - `tests/unit/SessionRefresh.test.ts` — flags land BEFORE the respawner fires
72
+ (ordering pinned), fresh swaps too, no-swap untouched, fail-safe.
73
+ - `tests/integration/subscription-pin-sessions.test.ts` — both launch lanes
74
+ land the flags on disk through the real SessionManager.
75
+ - `tests/integration/subscription-enrollment-interactive-ready.test.ts` +
76
+ `tests/e2e/subscription-enrollment-lifecycle.test.ts` — full HTTP
77
+ enroll→complete leaves the home interactive-ready, credentials
78
+ byte-identical.
79
+ - `npm run lint` (tsc + all custom lints) clean; subscription/quota regression
80
+ suites green.
@@ -0,0 +1,25 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: minor -->
5
+
6
+ ## What Changed
7
+
8
+ Introduces the **Cartographer doc-tree** — the substrate of the cartographer-conformance project. A new `CartographerTree` core module builds a hierarchical semantic map of the codebase: one node per directory and source file, each carrying a plain-English summary and a git-object-id fingerprint. Staleness is derived from a single batched `git ls-tree` (not a per-node git spawn), so the tree can report exactly which summaries have drifted from the code they describe — at near-zero cost.
9
+
10
+ Four read-only routes are added, all behind a dark-by-default `cartographer.enabled` gate (the feature is inert — routes 503 — until explicitly turned on): GET /cartographer/tree, /cartographer/node, /cartographer/stale, and /cartographer/health. Node-store filenames are collision-free sha256 slugs; the path lookup validates against traversal. The shared directory skip-set was extracted from ProjectMapper into a single skipDirs module that both now import. Destructive filesystem pruning of stale node files is funneled through SafeFsExecutor.
11
+
12
+ This is spec #1 of a multi-round project; later rounds add summary authoring, a freshness sweep, and conformance auditing. It changes no existing behavior — a fresh agent gets the feature off.
13
+
14
+ ## What to Tell Your User
15
+
16
+ - **A living map of your codebase (groundwork)**: "I'm building a self-maintaining map of this project — a tree of plain-English summaries, one per folder and file, that can tell when a summary has fallen behind the code it describes. This first piece is the foundation, and it's turned off by default for now. I'll let you know when the rest is ready to switch on."
17
+
18
+ ## Summary of New Capabilities
19
+
20
+ | Capability | How to Use |
21
+ |-----------|-----------|
22
+ | Codebase doc-tree map | GET /cartographer/tree (opt-in; off by default) |
23
+ | Per-node summary lookup | GET /cartographer/node?path=… |
24
+ | Stale-summary detection | GET /cartographer/stale |
25
+ | Feature health / liveness | GET /cartographer/health |
@@ -0,0 +1,82 @@
1
+ # Side-Effects Review — Cartographer Doc-Tree Schema (spec #1)
2
+
3
+ **Version / slug:** `cartographer-doc-tree-schema`
4
+ **Date:** `2026-06-09`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `external Gemini cross-model (convergence round 2) — no material findings`
7
+
8
+ ## Summary of the change
9
+
10
+ Adds the substrate of the `cartographer-conformance` project: a new
11
+ `CartographerTree` core module (hierarchical semantic doc-tree of the codebase,
12
+ per-node git-object-id staleness derived from ONE batched `git ls-tree`), a shared
13
+ `skipDirs.ts` (extracted from `ProjectMapper`, which now imports it), four
14
+ read-only HTTP routes `GET /cartographer/{tree,node,stale,health}` gated behind a
15
+ dark-by-default `cartographer.enabled` config, the config default + CLAUDE.md
16
+ template/migration (Migration Parity + Agent Awareness), and 3-tier tests.
17
+
18
+ ## Decision-point inventory
19
+
20
+ One gate: the routes return **503** when `cartographer.enabled` is false (or the
21
+ context holds no tree). No block/allow logic beyond the enable gate and the
22
+ `/cartographer/node?path=` validation (reject leading `/` or a `..` segment → 400).
23
+
24
+ ## 1. Over-block
25
+ The `?path=` validation rejects only traversal-shaped inputs (`/`-prefixed or
26
+ containing a `..` segment) and unknown nodes (404). Legitimate repo-relative paths
27
+ pass. The leaf-selection default (source extensions, excluding `*.test.*`) omits
28
+ non-source files from leaf nodes by design; directories always get a node, so no
29
+ directory is "over-blocked" out of the map.
30
+
31
+ ## 2. Under-block
32
+ Staleness compares committed git oids by default, so uncommitted working-tree
33
+ edits are not flagged unless the opt-in dirty mode is used — intentional (committed
34
+ state is deterministic across machines). Summaries are stored verbatim and
35
+ semantically unverified; the map never asserts a summary is *true* — downstream
36
+ specs (#3/#5) must re-ground against code. The map only covers what `scaffold()`
37
+ walks (skip-set + maxDepth bounded).
38
+
39
+ ## 3. Level-of-abstraction fit
40
+ Right layer. `CartographerTree` is a `src/core` data-structure module like
41
+ `ProjectMapper`; routes mount via the existing `createRoutes` context pattern; the
42
+ gate + instantiation live beside `projectMapper` in `server.ts`; the config default
43
+ rides the existing `applyDefaults` migration path (no bespoke migrator). The
44
+ skip-set is one shared export, not duplicated.
45
+
46
+ ## 4. Blast radius / reversibility
47
+ Self-contained and dark by default — a fresh agent gets `cartographer.enabled:
48
+ false`, so the feature is inert (routes 503) until explicitly enabled. The only
49
+ change to existing code paths is `ProjectMapper` importing `DEFAULT_SKIP_DIRS` from
50
+ the new shared module (identical set; covered by ProjectMapper's existing tests,
51
+ which stay green). Removing the feature is deleting the module + routes; no schema
52
+ migration to undo. State lives under `.instar/cartographer/` (gitignored).
53
+
54
+ ## 5. State / migration / multi-machine
55
+ New runtime state dir `.instar/cartographer/` (per-machine, gitignored, never
56
+ committed). Config default flows to existing agents via `migrateConfig` →
57
+ `applyDefaults` (existence-checked, idempotent). CLAUDE.md awareness flows via a
58
+ content-sniffed `migrateClaudeMd` block (idempotent). No cross-machine sync surface
59
+ — the tree is a local derived index, regenerable by `scaffold()` on any machine.
60
+
61
+ ## 6. Security / abuse
62
+ `?path=` never builds a filesystem path — it indexes the in-memory node store; the
63
+ on-disk node filename is a sha256 slug, collision-free and not derived from request
64
+ input. All git access is read-only via `SafeGitExecutor.readSync` (arg-form, no
65
+ shell interpolation). Routes are Bearer-auth'd like all instar routes; writes have
66
+ no open route (in-process only). Summaries served as JSON (consumers escape before
67
+ any HTML render). `scaffold()` is bounded by maxDepth + a symlink-loop guard
68
+ (visited realpaths) so a pathological repo cannot hang it. The one destructive fs
69
+ path — pruning stale node files in `rewriteAll()` — is funneled through
70
+ `SafeFsExecutor.safeUnlinkSync` (operation-tagged `cartographer-prune-stale-node`,
71
+ source-tree-guarded with the agent-runtime-state carveout for `.instar/`), never a
72
+ raw `fs.unlinkSync`, so the destructive-fs lint and audit trail both cover it.
73
+
74
+ ## 7. Observability / failure modes
75
+ `GET /cartographer/health` exposes node/authored/stale counts (the Tier-3 "alive"
76
+ surface). Absent git/HEAD degrades to "no current oids" → nodes read as
77
+ `never-authored`/`path-gone` rather than crashing (try/caught, `@silent-fallback-ok`).
78
+ `setSummary`'s node-then-index write is non-transactional: a crash between the two
79
+ leaves the index one version behind that node — a benign lag, self-healed by the
80
+ next `setSummary`/`scaffold`, never corruption. Tests cover all of: 14 unit + 8
81
+ integration (route contract) + 2 e2e (alive lifecycle), all green; `tsc --noEmit`
82
+ clean; ProjectMapper's existing tests stay green after the skip-set extraction.
@@ -0,0 +1,49 @@
1
+ # Side-Effects Review — onboarding-safe config homes for subscription pin/swap
2
+
3
+ **Version / slug:** `onboarding-safe-pinswap`
4
+ **Date:** `2026-06-09`
5
+ **Author:** `echo (Fable 5 build session)`
6
+ **Second-pass reviewer:** `self-review under the Tier-1 lite lane; every write path to .claude.json walked below`
7
+
8
+ ## Summary of the change
9
+
10
+ 2026-06-09 incident (topic 20905): pin/swap relaunched ~8 interactive sessions into pool-account config homes created by headless `claude auth login` — tokens present, interactive first-launch flags absent — so every one wedged on the onboarding screens. New util `ensureInteractiveReady(configHome)` idempotently seeds `hasCompletedOnboarding` / `bypassPermissionsModeAccepted` / `hasTrustDialogAccepted` in `<configHome>/.claude.json`, called at enrollment completion (EnrollmentWizard), defensively at every pinned/swapped launch (SessionManager headless-pin, interactive-reroute-pin, interactive configHome lanes; SessionRefresh before the swap respawn), and once for existing homes via a PostUpdateMigrator sweep.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - `src/core/ensureInteractiveReady.ts` — NEW — the only writer. Sets exactly the three flags; preserves every other key; refuses unparseable/non-object files (never clobbers a file that may hold salvageable credentials); atomic tmp+rename write; never throws (fail-safe contract); `requireExistingHome` gate for the migration sweep.
15
+ - `SessionManager.ensurePinnedHomeInteractiveReady` — NEW private helper — log-and-continue on failure; called in the headless pin lane, the interactive-reroute pin lane, and `spawnInteractiveSession` when `options.configHome` is set (claude-code only).
16
+ - `SessionRefresh.refreshSession` — seeds the target home whenever `accountSwap.configHome` is present (fresh and resume swaps both relaunch interactively), BEFORE the respawner fires.
17
+ - `EnrollmentWizard.complete()` — seeds for claude-code logins with a configHome; injectable `ensureReady` seam (default = real util). A seeding failure never blocks completion.
18
+ - `PostUpdateMigrator.migrateSubscriptionPoolInteractiveReady` — one-time sweep over `SubscriptionPool.list()` claude-code accounts; `requireExistingHome:true` so a stale registry entry never litters $HOME; per-home failures reported in `result.errors`, never abort the sweep.
19
+ - `ProactiveSwapMonitor` — comment-only TODO for active-session-only gating (secondary incident finding, deferred to a follow-up).
20
+
21
+ ## Could this corrupt credentials? (the load-bearing question)
22
+
23
+ The util never touches `oauthAccount` or any token field — it sets three booleans on the parsed object and writes the rest back. Unparseable or non-object files are REFUSED, not rewritten (bytes preserved exactly — pinned by unit tests). Writes are atomic (tmp+rename) so a crash mid-write cannot truncate `.claude.json`. The Monroe homes (`~/.claude`, `~/.claude-monroe`) are not in any subscription pool registry and no new code path enumerates $HOME — only registry/launch-provided configHome values are ever touched.
24
+
25
+ ## Could the seeding itself break a launch?
26
+
27
+ No — fail-safe by contract: every failure lane returns `{patched:false, reason}`; callers log and proceed. Worst case is byte-identical to the pre-fix behavior (the onboarding wedge), never a dead spawn/refresh path. Pinned-spawn behavior when the resolver returns null, and refreshes without an account swap, are unchanged (covered by existing + new tests).
28
+
29
+ ## Framework generality
30
+
31
+ Seeding is gated to claude-code everywhere: the SessionManager lanes only run for claude-code launches, EnrollmentWizard checks `login.framework === 'claude-code'`, and the migrator filters `framework === 'claude-code'`. codex-cli / gemini-cli / pi-cli homes are never touched — `.claude.json` onboarding flags are a Claude Code concept by construction.
32
+
33
+ ## Over-permit
34
+
35
+ The three flags are local trust acknowledgements (the operator manually accepted the same dialogs during incident recovery — this reproduces that state for pool homes). `bypassPermissionsModeAccepted` does not ENABLE bypass mode; it records that the mode's accept-screen was answered, which is precisely what an unattended relaunch cannot do itself. No trust scope widens beyond what every pre-incident pool home already required to function.
36
+
37
+ ## Migration parity
38
+
39
+ Handled IN this change: existing agents get the sweep via `PostUpdateMigrator.migrate()` on update; new enrollments are seeded at completion; every launch re-ensures defensively (triple coverage). No CLAUDE.md/template surface changes — the feature is structural (Structure > Willpower), not agent-invoked.
40
+
41
+ ## Token/cost impact
42
+
43
+ None. One stat + one small JSON read per pinned/swapped launch (write only when flags are missing — i.e., at most once per home). No LLM calls, no new polling.
44
+
45
+ ## Test coverage
46
+
47
+ - Unit: `tests/unit/ensure-interactive-ready.test.ts` (14 — both sides of every boundary), `PostUpdateMigrator-subscriptionPoolInteractiveReady.test.ts` (8), `SessionRefresh.test.ts` (+4 ordering/fail-safe), `enrollment-wizard.test.ts` (+4 seam/wiring).
48
+ - Integration: `subscription-pin-sessions.test.ts` (+2 — both launch lanes land the flags on disk), `subscription-enrollment-interactive-ready.test.ts` (2 — full HTTP enroll→complete seeds flags, codex untouched).
49
+ - E2E: `subscription-enrollment-lifecycle.test.ts` (+1 feature-alive — real server, headless-state home becomes interactive-ready with credentials byte-identical).