instar 1.2.81 → 1.2.83

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 (53) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +110 -11
  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 +23 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/PostUpdateMigrator.d.ts +7 -0
  8. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  9. package/dist/core/PostUpdateMigrator.js +59 -75
  10. package/dist/core/PostUpdateMigrator.js.map +1 -1
  11. package/dist/core/SessionManager.d.ts +43 -0
  12. package/dist/core/SessionManager.d.ts.map +1 -1
  13. package/dist/core/SessionManager.js +123 -24
  14. package/dist/core/SessionManager.js.map +1 -1
  15. package/dist/core/types.d.ts +26 -0
  16. package/dist/core/types.d.ts.map +1 -1
  17. package/dist/core/types.js.map +1 -1
  18. package/dist/monitoring/SessionReaper.d.ts +153 -0
  19. package/dist/monitoring/SessionReaper.d.ts.map +1 -0
  20. package/dist/monitoring/SessionReaper.js +376 -0
  21. package/dist/monitoring/SessionReaper.js.map +1 -0
  22. package/dist/monitoring/TokenLedger.d.ts +12 -0
  23. package/dist/monitoring/TokenLedger.d.ts.map +1 -1
  24. package/dist/monitoring/TokenLedger.js +22 -0
  25. package/dist/monitoring/TokenLedger.js.map +1 -1
  26. package/dist/monitoring/transcriptProber.d.ts +44 -0
  27. package/dist/monitoring/transcriptProber.d.ts.map +1 -0
  28. package/dist/monitoring/transcriptProber.js +57 -0
  29. package/dist/monitoring/transcriptProber.js.map +1 -0
  30. package/dist/scaffold/templates.d.ts.map +1 -1
  31. package/dist/scaffold/templates.js +21 -0
  32. package/dist/scaffold/templates.js.map +1 -1
  33. package/dist/server/AgentServer.d.ts +3 -0
  34. package/dist/server/AgentServer.d.ts.map +1 -1
  35. package/dist/server/AgentServer.js +1 -0
  36. package/dist/server/AgentServer.js.map +1 -1
  37. package/dist/server/routes.d.ts +3 -0
  38. package/dist/server/routes.d.ts.map +1 -1
  39. package/dist/server/routes.js +108 -0
  40. package/dist/server/routes.js.map +1 -1
  41. package/dist/threadline/CollaborationSurfacer.d.ts +67 -18
  42. package/dist/threadline/CollaborationSurfacer.d.ts.map +1 -1
  43. package/dist/threadline/CollaborationSurfacer.js +132 -37
  44. package/dist/threadline/CollaborationSurfacer.js.map +1 -1
  45. package/package.json +1 -1
  46. package/src/data/builtin-manifest.json +63 -63
  47. package/src/scaffold/templates.ts +21 -0
  48. package/upgrades/1.2.81.md +13 -0
  49. package/upgrades/1.2.82.md +26 -0
  50. package/upgrades/1.2.83.md +26 -0
  51. package/upgrades/side-effects/1.2.81.md +127 -0
  52. package/upgrades/side-effects/session-reaper.md +42 -0
  53. package/upgrades/side-effects/threadline-notification-routing.md +46 -0
@@ -0,0 +1,26 @@
1
+ # Upgrade Guide — NEXT
2
+
3
+ <!-- bump: minor -->
4
+ <!-- Valid values: patch, minor, major -->
5
+ <!-- patch = bug fixes, refactors, test additions, doc updates -->
6
+ <!-- minor = new features, new APIs, new capabilities (backwards-compatible) -->
7
+ <!-- major = breaking changes to existing APIs or behavior -->
8
+
9
+ ## What Changed
10
+
11
+ **SessionReaper — pressure-aware cleanup of idle-but-alive sessions.** A new monitor that reaps sessions sitting idle at a ready prompt (holding memory) — but ONLY when the machine is under memory pressure, and it NEVER reaps a session that might be working. It requires *positive* proof of idleness (turn complete + at a ready prompt + screen byte-static across several checks + no running process + no transcript growth) and KEEPs on any ambiguity. Ships **OFF + dry-run by default** — the only monitor that kills on a heuristic, so it stays dark until an operator validates the dry-run log and opts in. Closes the gap behind the 2026-05-25 fleet pileup (idle sessions accumulated until the machine starved and cross-agent messaging silently failed because agents could no longer spawn).
12
+
13
+ New read-only endpoint `GET /sessions/reaper` shows the live pressure tier and, per session, the verdict + the exact gate that kept it. `SessionManager` gains a single-writer `terminateSession()` so the existing idle-kill and the reaper can never double-kill. The zombie-kill recovery veto now also defers to the socket + silence sentinels.
14
+
15
+ ## What to Tell Your User
16
+
17
+ - **Idle sessions get cleaned up under memory pressure — safely.** When your machine fills up with idle agent sessions, this sweeps them so new sessions (and incoming cross-agent messages) don't get refused. It will never reap a session that's actually working. It's off by default; ask me to turn it on after we watch its dry-run log.
18
+ - **You won't notice anything unless you enable it.** No behavior change on update.
19
+
20
+ ## Summary of New Capabilities
21
+
22
+ | Capability | How to Use |
23
+ |-----------|-----------|
24
+ | SessionReaper (idle-session cleanup under pressure) | `monitoring.sessionReaper.enabled:true` (leave `dryRun:true` first). Off by default. |
25
+ | Reaper observability | `GET /sessions/reaper` — pressure tier + per-session verdict + keptBy |
26
+ | Single-writer session termination | `SessionManager.terminateSession()` — idle-kill + reaper share one CAS kill path |
@@ -0,0 +1,127 @@
1
+ # Side-Effects Review — Free-text guard template resolution
2
+
3
+ **Version / slug:** `free-text-guard-template-resolution`
4
+ **Date:** `2026-05-25`
5
+ **Author:** `instar-codey`
6
+ **Second-pass reviewer:** `Echo`
7
+
8
+ ## Summary of the change
9
+
10
+ This change fixes how the post-update migrator finds built-in template files.
11
+ The free-text guard hook was looking only in the compiled-template layout, but
12
+ published packages ship that hook in the source-template layout. The migrator
13
+ now has one shared template loader for hook, script, and playbook templates. The
14
+ free-text guard and existing similar readers use that loader.
15
+
16
+ ## Decision-point inventory
17
+
18
+ This change does not add, remove, or modify any block/allow decision. It changes
19
+ file lookup for a static built-in template. The free-text guard's own behavior is
20
+ passed through unchanged.
21
+
22
+ - `free-text-guard.sh` — pass-through — installed from the packaged template;
23
+ its blocking rules are not changed.
24
+ - `PostUpdateMigrator` template lookup — modified — uses shared lookup instead
25
+ of repeated one-off path checks.
26
+
27
+ ---
28
+
29
+ ## 1. Over-block
30
+
31
+ No new block/allow surface. Over-block is not applicable to the template lookup
32
+ change. The free-text guard may still block exactly the same inputs it blocked
33
+ before; this patch only controls whether the hook is installed.
34
+
35
+ ---
36
+
37
+ ## 2. Under-block
38
+
39
+ This does not change what the guard detects. The remaining failure mode is
40
+ package-shape drift: if a future publish stops shipping both supported template
41
+ locations, the migrator will fail clearly for the required free-text guard and
42
+ skip or fall back for callers that already had softer behavior. The new package
43
+ shape test covers the current published layout.
44
+
45
+ ---
46
+
47
+ ## 3. Level-of-abstraction fit
48
+
49
+ The fix belongs in the migrator because the bug is runtime asset resolution, not
50
+ guard policy. A shared helper is the right layer: it keeps package-layout
51
+ knowledge in one place and lets each caller decide whether a missing template is
52
+ fatal, skippable, or eligible for fallback.
53
+
54
+ ---
55
+
56
+ ## 4. Signal vs authority compliance
57
+
58
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
59
+
60
+ - [x] No — this change has no block/allow surface.
61
+
62
+ The change does not introduce a detector or an authority. It does not decide
63
+ whether a message, action, or user request should be blocked. It only locates a
64
+ static template file so existing migration behavior can install the existing
65
+ hook.
66
+
67
+ ---
68
+
69
+ ## 5. Interactions
70
+
71
+ - **Shadowing:** no existing decision path is shadowed. Existing template
72
+ readers now share one lookup helper.
73
+ - **Double-fire:** no duplicate installer is added. The same migration still
74
+ writes the same built-in hook once.
75
+ - **Races:** no shared persistent state is added. File reads are local and
76
+ synchronous, matching the previous migrator style.
77
+ - **Feedback loops:** none. The resolver does not feed runtime decisions or
78
+ telemetry.
79
+
80
+ ---
81
+
82
+ ## 6. External surfaces
83
+
84
+ Existing agents see the external effect on update: the free-text guard hook can
85
+ be installed again from the package we actually publish. The hook content and
86
+ runtime behavior do not change. There is no new user-facing command, API,
87
+ database field, or external service dependency.
88
+
89
+ ---
90
+
91
+ ## 7. Rollback cost
92
+
93
+ Rollback is a normal patch revert. The change writes no new persistent state and
94
+ does not migrate data. If it misbehaves, revert the shared resolver refactor and
95
+ ship a patch. Agents that already received the hook do not need repair because
96
+ the hook content itself is unchanged.
97
+
98
+ ---
99
+
100
+ ## Conclusion
101
+
102
+ The review found no new decision authority and no new block/allow behavior. The
103
+ main production risk is future package layout drift, and the integration test now
104
+ checks the packed package shape and runs the compiled migrator from that shape.
105
+ This is clear to ship once CI is green.
106
+
107
+ ---
108
+
109
+ ## Second-pass review (if required)
110
+
111
+ **Reviewer:** Echo
112
+ **Independent read of the artifact: concur**
113
+
114
+ Echo reviewed the diagnosis and implementation direction during the Threadline
115
+ collaboration and signed off on the root cause, shared resolver approach, and
116
+ packed-package smoke as the evidence needed before normal CI.
117
+
118
+ ---
119
+
120
+ ## Evidence pointers
121
+
122
+ - Approved spec: `docs/specs/FREE-TEXT-GUARD-TEMPLATE-RESOLUTION-SPEC.md`
123
+ - Plain-language spec overview:
124
+ `docs/specs/FREE-TEXT-GUARD-TEMPLATE-RESOLUTION-SPEC.eli16.md`
125
+ - Focused tests: 6 passing.
126
+ - Build and lint: passing.
127
+ - Packed package smoke: passing.
@@ -0,0 +1,42 @@
1
+ # Side-Effects Review — SessionReaper
2
+
3
+ Spec: `docs/specs/SESSION-REAPER-SPEC.md` (v2 CONVERGED + ratified). Build branch `build/session-reaper`.
4
+
5
+ ## What changes for a deployed agent
6
+
7
+ - A new monitor (`SessionReaper`) is constructed and started at server boot. **Default OFF + dry-run** (`monitoring.sessionReaper.enabled:false, dryRun:true`), so deployed agents get **no behavior change** until an operator opts in. New config block arrives via the standard `ConfigDefaults`/`applyDefaults` migration; operator-set values are never overwritten.
8
+ - New read-only endpoint `GET /sessions/reaper` (503 when unwired, 200 snapshot otherwise).
9
+ - `SessionManager` gains `terminateSession()` (single-writer CAS), `isRelayLeaseActive()`, and `markReaping/clearReaping/isReaping`. The existing idle-kill now funnels through `terminateSession` and skips reaping-leased sessions; `killSession` shares the CAS guard and now sets `endedReason` (its event emissions are unchanged — still no `sessionComplete`).
10
+ - The zombie-kill recovery veto (`activeRecoveryChecker`) is recomposed to include the socket + silence sentinels (previously compaction + rate-limit only) — a strict superset; nothing is dropped.
11
+
12
+ ## Over/under-block analysis (the hard requirement)
13
+
14
+ The reaper must never reap a working session. Safety rests on positive evidence, not absence of activity:
15
+ - **Under-block (fails to reap a genuinely idle session):** acceptable — the existing 15m/4h idle-kill still runs; the reaper is additive pressure relief.
16
+ - **Over-block (reaps a working session):** the failure that matters. Mitigations: (1) requires a *positive* turn-complete idle-prompt signal; (2) render-stasis — pane byte-identical across all confirm ticks; (3) process + transcript must be quiet, and any *unresolvable* signal (no `claudeSessionId`, Codex/missing/rotated transcript, uninspectable process) forces KEEP, never "quiet"; (4) hysteresis; (5) two-phase reap with a final-grace re-check that aborts on any frame change; (6) Normal pressure tier reaps nothing; (7) bounded per-tick/per-hour budget; (8) auto-disable to dry-run on any ambiguous/failed reap; (9) ships OFF + dry-run.
17
+
18
+ ## Level-of-abstraction / signal-vs-authority
19
+
20
+ Signals carry confidence and only *recommend*; kill authority sits behind the budget + dry-run + single-writer `terminateSession` CAS + auto-disable. The reaper computes a verdict; it does not own an unbounded kill.
21
+
22
+ ## Interactions
23
+
24
+ - Composes with (does not fight) existing watchdogs: gate G defers to any recovery-in-flight (now incl. socket/silence); disjoint from OrphanProcessReaper (untracked procs) and SessionWatchdog (active-but-stuck); shares the single-writer kill path with the idle-kill so no double-kill / double-event.
25
+ - Pressure source is freemem-tiered for v1 (advisory; macOS under-reports). Crucially, an over-eager pressure tier can only reap a *genuinely-idle* session sooner — it cannot cause a working session to be reaped, because the classifier protects working sessions independent of tier.
26
+
27
+ ## Rollback
28
+
29
+ Set `monitoring.sessionReaper.enabled:false` (the default) — fully inert. No data migration; `endedReason` is additive/optional. Revert the branch to remove code; no persisted state needs cleanup beyond an optional `state/session-reaper.json` (absent unless restart-durability is later wired).
30
+
31
+ ## Tests
32
+
33
+ 3-tier: unit (transcript prober, terminateSession CAS, classifier incl. every false-reap vector, config/migration), integration (`/sessions/reaper` + dry-run), e2e (feature-alive + dangerous cases). Wiring-integrity guards the construct→start→pass chain. Live test-as-self on a real in-flight build + a real Codex session precedes merge.
34
+
35
+ ## Phase-3 review fixes (post multi-agent code review)
36
+
37
+ Independent review confirmed NO blocker to the hard requirement (cannot reap a working session) and surfaced safety-net hardening, all applied:
38
+ - **Reaping-lease leak:** when a matured reap is budget/tier-gated, the reaping lease is now released — previously it could permanently disable the fast idle-kill for that session.
39
+ - **Protected-list wiring:** gate A now reads `SessionManager.getProtectedSessions()` (the resolved list including the `<project>-server` default) rather than the raw config field, preventing spurious auto-disable when the server session goes idle.
40
+ - **Robustness:** `tick()` and `snapshot()` treat a throwing protect-signal as KEEP — never reap on a failed evaluation, and the `/sessions/reaper` route never 500s.
41
+ - **`killSession` contract preserved:** unconditional pane kill retained (only the in-flight guard added; no terminal-status early-return).
42
+ - **Known v1 gap (documented, not a false-reap vector):** the optional `mainProcessActive` CPU/IO-delta signal is not wired in v1; render-stasis is the real-time liveness channel that covers in-process work. Promoting `mainProcessActive` is a tracked enhancement, validated during the dry-run rollout.
@@ -0,0 +1,46 @@
1
+ # Side-Effects Review — Threadline notification routing (CMT-519)
2
+
3
+ **Version / slug:** `threadline-notification-routing`
4
+ **Date:** 2026-05-25
5
+ **Author:** Echo
6
+ **Second-pass reviewer:** (pending — required; touches messaging routing + a structural redirect "guard")
7
+
8
+ ## Summary of the change
9
+
10
+ Threadline notifications no longer spawn a Telegram topic per event. `CollaborationSurfacer` gains a `notify()` entry (status/housekeeping → the single SILENT "Threadline" hub, never the parent topic), record-shaped surface state (with a legacy `string[]` read-migration) + bind helpers (`mostRecentUnbound`, `markBound`, `noteInHub`). The loop-gate (`src/commands/server.ts` ~7167) routes through `notify()` instead of `createAttentionItem`. `POST /attention` redirects threadline-class items to the hub. A new `POST /threadline/hub/bind` promotes ("open this") / binds ("tie this to X") a surfaced conversation to a topic — authoritatively setting `boundTopicId` + the commitment's `topicId`. Template + migration teach agents the hub + "open this" behavior. Decision points: the `/attention` reroute (routing, not block/allow), the loop-gate notice destination, the bind mutation.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - `POST /attention` threadline-class redirect — **add** — reroutes threadline/inter-agent/spawn items to the silent hub instead of a per-event topic.
15
+ - Loop-gate wind-down destination (`server.ts`) — **modify** — `createAttentionItem` → `collaborationSurfacer.notify()` (hub, not parent, not per-event topic).
16
+ - `POST /threadline/hub/bind` — **add** — authoritative thread→topic bind.
17
+ - CollaborationSurfacer status vs first-contact surfacing — **modify** — adds the status lane (`notify`) alongside the existing parentless first-contact lane (`surface`).
18
+
19
+ ## 1. Over-block
20
+ No block/allow surface — these are routing/delivery decisions, not gates. The `/attention` redirect could mis-route a *legitimate general* item if its title coincidentally matches `threadline|inter-agent|spawn|relay` — mitigated by the category-first check (`/^(threadline|inter-agent|relay|spawn)/i` on category) plus content sniff only on distinctive phrases (`spawn-storm`, `spawn to receive`, `cannot spawn`, `inter-agent`, `\bthreadline\b`). A generic "spawn a new worker" general item would NOT match (no category prefix, no distinctive phrase). Worst case the item lands in the hub instead of its own topic — recoverable, not lost.
21
+
22
+ ## 2. Under-block
23
+ A threadline alert posted via `/attention` with a *non-threadline category AND no distinctive phrase* would still get its own topic. Acceptable: the in-code threadline emitters (loop-gate) now route correctly; the redirect is a backstop for ad-hoc posts. The `TelegramBridge.mirrorInbound` per-thread topic path is intentionally excluded as a deliberate opt-in feature (default-off — the operator turned it on knowingly), not a notification the routing fix should override.
24
+
25
+ ## 3. Level-of-abstraction fit
26
+ Correct: extended `CollaborationSurfacer` (already the hub owner) rather than a parallel router (convergence Q1). Status notices use a delivery sink (`notify`); real reply *content* still flows via the existing `TopicLinkageHandler` parent-topic path (one emitter per topic — avoids the double-notify the reviewer flagged, H2). The bind endpoint composes existing primitives (`ConversationStore.mutate`, `findOrCreateForumTopic`, `commitmentTracker.mutate`).
27
+
28
+ ## 4. Signal vs authority compliance
29
+ No new blocking authority. The `/attention` redirect is a router (reroute + 201, never a hard block). `notify()`/`surface()` are delivery sinks. The bind endpoint mutates state on explicit operator action. Per `docs/signal-vs-authority.md`: detectors/sinks, not gates.
30
+
31
+ ## 5. Interactions
32
+ - **No double-surface:** status (`notify`) → hub only; content (replies) → parent topic via TopicLinkageHandler only. The loop-gate path `return`s after notify, so it never also hits surface(). `surface()` (parentless first-contact) and `notify()` (status) are distinct lanes; a single inbound triggers at most one.
33
+ - **Bind vs first-write-wins:** `hub/bind` is authoritative — it overrides `captureOriginOnSend`'s anti-poisoning refusal by directly setting `boundTopicId` + the commitment `topicId` (operator intent > heuristic).
34
+ - **Legacy state migration** is read-time + idempotent; new record-shape round-trips.
35
+
36
+ ## 6. External surfaces
37
+ New `transport`-free; new route `POST /threadline/hub/bind` (503 when telegram/conversationStore absent). Hub stays silent (`{silent:true}`) — no new buzzing. Template/migration change is agent-facing (Agent Awareness Standard) + idempotent (Migration Parity).
38
+
39
+ ## 7. Rollback cost
40
+ Localized: CollaborationSurfacer (additive methods + schema with back-compat read), one server.ts callsite, two routes.ts additions, template + migration. Clean `git revert`. The surface-state schema change is forward+backward tolerant (load() reads both shapes); no data migration needed. New agents get the template via `generateClaudeMd`; existing via `migrateClaudeMd` (idempotent).
41
+
42
+ ## Second-pass review
43
+
44
+ **Concur with the review** (independent reviewer, 2026-05-25). Verified all six checks against the diff: (1) the loop-gate `budgetExhausted && collaborationSurfacer` guard is sound (surfacer is `telegram ? new ... : undefined`), and the dropped `createAttentionItem` had no `/ack` consumer — nothing operational lost; (2) `load()` migration round-trips all three shapes (records / legacy string[] / dedicatedTopicId-only) with no loss of `dedicatedTopicId`; (3) the `/attention` redirect runs after `checkOutboundMessage`, matches only category-prefix `^(threadline|inter-agent|relay|spawn)` OR distinctive body tokens (8 realistic inputs tested — "CI failed", "relay race", "Spawning a new initiative" correctly do NOT match), else falls through; (4) `hub/bind` 503/404/409/200 paths correct, authoritative bind sets `boundTopicId` + commitment `topicId` via existing CAS-safe mutates, null-safe field access, all awaits correct, tsc clean; (5) migration content-sniff marker exactly matches the template heading — idempotent; (6) no double-surface — the `budgetExhausted` path `notify()`s then `return`s before `surface()`, and `surface()` early-returns on `hasParentTopic`; mutually exclusive per inbound.
45
+
46
+ Reviewer's one non-blocking gap — the new HTTP routes lacked Tier 2/3 coverage — has been **addressed**: added `tests/integration/threadline/hub-bind-routes.test.ts` (6 tests: 503/400/404/409/200-open/200-tie, asserting `boundTopicId` is set through the real `createRoutes` pipeline). The `/attention` redirect's match logic is covered by the reviewer's verified 8-input analysis + live test-as-self.