instar 1.3.680 → 1.3.682

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 (33) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +32 -11
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  5. package/dist/core/PostUpdateMigrator.js +25 -1
  6. package/dist/core/PostUpdateMigrator.js.map +1 -1
  7. package/dist/core/types.d.ts +3 -0
  8. package/dist/core/types.d.ts.map +1 -1
  9. package/dist/core/types.js.map +1 -1
  10. package/dist/messaging/ColdStartFallbackReply.d.ts +68 -0
  11. package/dist/messaging/ColdStartFallbackReply.d.ts.map +1 -0
  12. package/dist/messaging/ColdStartFallbackReply.js +91 -0
  13. package/dist/messaging/ColdStartFallbackReply.js.map +1 -0
  14. package/dist/monitoring/AgentWorktreeReaper.d.ts +8 -0
  15. package/dist/monitoring/AgentWorktreeReaper.d.ts.map +1 -1
  16. package/dist/monitoring/AgentWorktreeReaper.js +1 -0
  17. package/dist/monitoring/AgentWorktreeReaper.js.map +1 -1
  18. package/dist/monitoring/agentWorktreeGit.d.ts +26 -0
  19. package/dist/monitoring/agentWorktreeGit.d.ts.map +1 -1
  20. package/dist/monitoring/agentWorktreeGit.js +83 -1
  21. package/dist/monitoring/agentWorktreeGit.js.map +1 -1
  22. package/dist/scaffold/templates.d.ts.map +1 -1
  23. package/dist/scaffold/templates.js +7 -0
  24. package/dist/scaffold/templates.js.map +1 -1
  25. package/package.json +1 -1
  26. package/src/data/builtin-manifest.json +19 -19
  27. package/src/scaffold/templates.ts +7 -0
  28. package/upgrades/1.3.681.md +43 -0
  29. package/upgrades/1.3.682.md +55 -0
  30. package/upgrades/coldstart-lifeline-fallback.eli16.md +49 -0
  31. package/upgrades/reaper-squash-merge-aware.eli16.md +43 -0
  32. package/upgrades/side-effects/coldstart-lifeline-fallback.md +85 -0
  33. package/upgrades/side-effects/reaper-squash-merge-aware.md +75 -0
@@ -0,0 +1,49 @@
1
+ # Cold-Start Lifeline Fallback — ELI16 overview
2
+
3
+ ## The problem in plain words
4
+
5
+ When you send a message to one of your agent's topics, the agent has to *start a
6
+ session* to read and answer it. Usually that just works. But sometimes it can't
7
+ start one right then — maybe too many sessions are already running (a hard limit),
8
+ maybe the machine is low on memory or under heavy load, or maybe the startup hit an
9
+ unexpected error.
10
+
11
+ Before this change, when that happened you'd either get silence, or a bare, unhelpful
12
+ line like "Having trouble starting a session right now." Worse, one version told you
13
+ to "increase maxSessions in your config" — asking *you* to go edit a settings file.
14
+ That's backwards: the agent is the thing with the tools to free up resources and fix
15
+ the problem. You shouldn't have to.
16
+
17
+ ## What this change does
18
+
19
+ Now, when the agent genuinely can't start (or restart) a session for a topic, you get
20
+ ONE clear, friendly reply that does three things:
21
+
22
+ 1. **Says WHY in plain English** — "I'm already running the maximum number of sessions
23
+ at once," or "the machine is under resource pressure right now," or an honest
24
+ "unexpected start-up error." No jargon, no config keys.
25
+ 2. **Points you to your Lifeline topic** — the one topic that's guaranteed to always be
26
+ reachable. That's the place to go when a normal topic is stuck.
27
+ 3. **Hands you a ready-to-paste message** — a pre-written line you can copy straight
28
+ into the Lifeline that describes exactly what failed, so the agent can diagnose and
29
+ free resources fast. You don't have to explain anything yourself.
30
+
31
+ If the failing topic *is* your Lifeline, it doesn't tell you to go elsewhere — it says
32
+ you're already in the right place and it'll start freeing resources. If you have no
33
+ Lifeline configured, it still tells you why and reassures you that your message isn't
34
+ lost — just resend once things settle.
35
+
36
+ ## Why it's built this way
37
+
38
+ This is the "G1" half of a constitutional standard called **"The Agent Is Always
39
+ Reachable."** The core idea: the agent must never go silently unreachable, because the
40
+ agent itself is the solution — it holds the tools to diagnose and free resources, so it
41
+ has to stay reachable to use them. The reply is sent on a *deterministic* delivery path
42
+ (a direct send), never through the smart message-review gate, because that gate could
43
+ itself fail under the very resource pressure we're trying to report.
44
+
45
+ It's an always-on safety floor with no on/off switch — the standard forbids hiding
46
+ reachability behind a flag. Under the hood it's a small, well-tested message builder
47
+ wired into the two places a session-start can fail (a fresh spawn and a restart), plus
48
+ a CLAUDE.md note so any agent can explain "why did I get a go-to-lifeline message?" if
49
+ you ask.
@@ -0,0 +1,43 @@
1
+ # Squash-merge-aware worktree reaper — ELI16 overview
2
+
3
+ ## The problem in plain words
4
+
5
+ When the agent works on a change, it makes a "worktree" — a full copy of the codebase
6
+ in its own folder — so different jobs don't trip over each other. Each one is hundreds
7
+ of megabytes. After the change is merged and shipped, that folder is dead weight: the
8
+ work is safely in the main branch, so the copy can be deleted.
9
+
10
+ A background cleaner (the "reaper") is supposed to delete those finished folders. But it
11
+ had a blind spot. To decide "is this branch's work already in main?", it compared the
12
+ branch's commits to main commit-by-commit (using a git trick called patch-id). That
13
+ works when a branch is merged normally — but this project **squash-merges**: it mashes
14
+ all of a branch's commits into ONE new commit on main. That single squashed commit has a
15
+ different fingerprint than the original commits, so the reaper couldn't recognize the
16
+ work as merged. It played it safe and **kept the folder forever**.
17
+
18
+ Result: merged-but-unrecognized folders piled up — on this machine, hundreds of them,
19
+ over 100 GB of disk. That bloat is part of what made the machine slow and, eventually,
20
+ contributed to a crash.
21
+
22
+ ## What this change does
23
+
24
+ The reaper now has a second way to tell a branch is merged: it asks GitHub. Once per
25
+ cleanup sweep it fetches the list of **merged pull requests** and the exact commit each
26
+ one merged. If a folder's branch has a merged PR, AND the folder is sitting on exactly
27
+ that same commit, the reaper knows the work is in main and the folder is safe to delete.
28
+
29
+ Two safety rules make this trustworthy:
30
+ - **Exact-commit match.** If you added new commits to the branch AFTER its PR merged,
31
+ the folder's commit won't match the merged one, so it's still KEPT — new work is never
32
+ thrown away.
33
+ - **Fail-safe.** If GitHub can't be reached (offline, not logged in, not a GitHub repo),
34
+ the reaper simply falls back to the old commit-by-commit check and keeps the folder.
35
+ It never deletes on a guess.
36
+
37
+ It's still off by default and runs in dry-run first (it tells you what it WOULD delete
38
+ before it deletes anything), and there's an off-switch (`githubMergeCheck: false`) to
39
+ turn off the GitHub call entirely. The GitHub lookup is just ONE call per sweep, cached,
40
+ so it's cheap.
41
+
42
+ The net effect: when you turn the reaper on, it can finally reclaim the squash-merged
43
+ folders that were stuck forever — recovering the disk that was quietly disappearing.
@@ -0,0 +1,85 @@
1
+ # Side-Effects Review — Cold-Start Lifeline Fallback (G1)
2
+
3
+ **Version / slug:** `coldstart-lifeline-fallback`
4
+ **Date:** `2026-06-26`
5
+ **Author:** `echo`
6
+ **Tier:** 1 (enhances an EXISTING always-on user-notice on the inbound cold-start
7
+ failure path; reuses the already-merged "Agent Is Always Reachable" standard #1288;
8
+ no new authority, no new gate, no protocol/security change)
9
+
10
+ ## Summary of the change
11
+
12
+ G1 (the user-facing arm) of the constitutional standard **"The Agent Is Always
13
+ Reachable"** corollary (2), *no silent resource rejection*. When a user messages a
14
+ topic and the system genuinely cannot start (cold spawn) OR restart a session for it,
15
+ the existing catch already sent a generic notice — but it (a) did not point to the
16
+ Lifeline, (b) did not hand a copy-paste debug message, and (c) leaked dev jargon
17
+ ("increase maxSessions in your config"). This change extracts a pure, unit-tested
18
+ message builder (`src/messaging/ColdStartFallbackReply.ts`) that classifies WHY the
19
+ start failed (`session-limit` / `resource-pressure` / `start-failure`) and composes a
20
+ plain-English reply with the Lifeline pointer + a pre-written copy-paste debug block,
21
+ and wires it into BOTH inbound failure paths in `src/commands/server.ts`. Migration
22
+ parity: a `migrateClaudeMd` section (existing agents) + a `generateClaudeMd` template
23
+ section (new agents) so any agent can explain the behavior. Files:
24
+ `src/messaging/ColdStartFallbackReply.ts` (new), `src/commands/server.ts` (two catch
25
+ sites), `src/core/PostUpdateMigrator.ts` (CLAUDE.md section), `src/scaffold/templates.ts`
26
+ (template section), plus three test files (logic, wiring-integrity, migration).
27
+
28
+ ## Decision-point inventory
29
+
30
+ - The two inbound failure catches (`onTopicMessage` cold-spawn `.catch` and restart
31
+ `.catch`) — **pass-through**. They already FIRED a notice; this only changes the
32
+ *content* of the message (and replaces the string-match branch with the classifier).
33
+ No control-flow change: still one `telegram.sendToTopic(topicId, …)` on failure.
34
+
35
+ ## 1. Over-block
36
+
37
+ **No block/allow surface — not applicable.** The change produces a user-facing message
38
+ on an already-failing path; it never blocks, delays, or rejects any session, message,
39
+ or spawn. The spawn/restart decision is entirely unchanged (the failure already
40
+ happened by the time the builder runs).
41
+
42
+ ## 2. Under-block
43
+
44
+ **Not applicable** — no gate. The closest "miss" is a misclassified reason word, which
45
+ only changes the wording (the notice still fires and still points to the Lifeline). The
46
+ classifier is a SIGNAL (help text), not authority — both sides of each classification
47
+ branch are unit-tested.
48
+
49
+ ## 3. Level-of-abstraction fit
50
+
51
+ Correct layer. The failure reason (the thrown error) and the delivery primitive
52
+ (`telegram.sendToTopic`, `telegram.getLifelineTopicId`) are both already in scope at the
53
+ catch site; composing the message there — via a pure builder that has no I/O — is the
54
+ right level. The builder is isolated in `src/messaging/` so it is unit-testable without
55
+ standing up the server.
56
+
57
+ ## 4. Signal vs authority compliance
58
+
59
+ The reply is **pure signal** — a help message on a deterministic delivery path. It
60
+ carries zero blocking authority: it cannot hold, delay, or release a session. The
61
+ session's fate is decided entirely by the unchanged `SessionManager.spawnSession`
62
+ throw. This is the signal-vs-authority split the principle demands.
63
+
64
+ ## 5. Interactions
65
+
66
+ - **Deterministic path (deliberate):** delivery is the direct `sendToTopic`, NOT the
67
+ LLM tone gate — per the standard, the notice must not be blockable by the very
68
+ pressure it reports (a tone gate failing closed under load would swallow it).
69
+ - **Double-fire:** unchanged. The existing `spawningTopics` guard + the single `.catch`
70
+ still fire at most one notice per failed attempt.
71
+ - **Same-topic-is-lifeline:** handled — when the failing topic IS the Lifeline, the
72
+ message does not tell the user to go elsewhere (tested).
73
+ - **No-lifeline-configured:** degrades to "why + honest retry guidance" (tested).
74
+
75
+ ## 6. External surfaces
76
+
77
+ - **User:** the agent's own Telegram topic — same `sendToTopic` primitive, same
78
+ topic, same priority as the message it replaces. No new external call shape.
79
+ - **No new config, route, hook, or credential.** Always-on (the standard forbids
80
+ dark-shipping reachability); the only "surface" change is better message text.
81
+
82
+ ## 7. Rollback
83
+
84
+ Pure code + docs. Reverting the commit restores the prior generic notice. No state
85
+ migration to undo (the CLAUDE.md section is idempotent and additive).
@@ -0,0 +1,75 @@
1
+ # Side-Effects Review — Squash-merge-aware worktree reaper
2
+
3
+ **Version / slug:** `reaper-squash-merge-aware`
4
+ **Date:** `2026-06-26`
5
+ **Author:** `echo`
6
+ **Tier:** 1 — enhances an EXISTING merged-detection on the AgentWorktreeReaper (which
7
+ ships OFF + dry-run by default). Adds a fail-safe, conservative network SIGNAL + a config
8
+ off-switch. No new authority, no new gate, no new route. The reaper's safety contract
9
+ ("NEVER delete unmerged work") is strengthened, not weakened.
10
+
11
+ ## Summary of the change
12
+
13
+ The reaper's merged-check used `git cherry` (patch-id equivalence) ONLY, which the code
14
+ itself documents cannot detect MULTI-commit squash-merges — the disk-accumulation root
15
+ cause (squash-merged worktrees kept forever; ~118GB/290 observed). Added a SECOND,
16
+ conservative signal: `fetchMergedPrHeadOids()` does ONE `gh pr list --state merged`
17
+ call per sweep (cached 60s) → a `headRefName→headRefOid` map; `isMerged` treats a
18
+ worktree as merged only when its branch has a merged PR whose head OID EXACTLY matches
19
+ the worktree HEAD. Files: `agentWorktreeGit.ts` (the fetcher + the cached map + the
20
+ enhanced `isMerged`), `AgentWorktreeReaper.ts` (config field `githubMergeCheck`,
21
+ default true), `types.ts` (config type), `server.ts` (plumb the flag),
22
+ `PostUpdateMigrator.ts` (awareness). Tests: 9 new (`fetchMergedPrHeadOids` parse/fail-safe,
23
+ `isMerged` PR-map both sides + oid-mismatch keep + disabled-no-call).
24
+
25
+ ## 1. Over-block (over-KEEP)
26
+
27
+ Possible: a genuinely-merged worktree is still KEPT (e.g. gh offline, PR list older than
28
+ `--limit 500`, branch renamed). This is the SAFE direction — a kept worktree wastes disk
29
+ but loses nothing. Fully acceptable; it is exactly today's behavior on any gh failure.
30
+
31
+ ## 2. Under-block (the deletion-safety risk — the one that matters)
32
+
33
+ The hard rule is NEVER delete unmerged work. The new signal can only ADD a "merged"
34
+ verdict, so the question is: can it false-positive? Guards: (a) it requires an actual
35
+ MERGED PR for the branch (authoritative — the content is in main); (b) it requires the
36
+ worktree HEAD to EXACTLY equal the PR's merged head OID, so a branch with commits added
37
+ AFTER the merge (unmerged work on top) is KEPT (tested); (c) the upstream `isClean` gate
38
+ still independently blocks any uncommitted/untracked changes; (d) fail-safe to cherry-only
39
+ on any gh error. A reused branch name resolves to the NEWEST merged PR, and the exact-OID
40
+ match still gates deletion. Both sides tested.
41
+
42
+ ## 3. Level-of-abstraction fit
43
+
44
+ Correct layer — the change lives entirely in the deps factory (`makeAgentWorktreeReaperDeps`);
45
+ the pure classifier (`AgentWorktreeReaper.evaluate`) is untouched and stays fake-testable.
46
+ The gh call is lazy (only when `git cherry` says unmerged) and cached (one call per sweep).
47
+
48
+ ## 4. Signal vs authority compliance
49
+
50
+ The merged-PR map is a SIGNAL consumed by the existing deterministic reaper gate-chain;
51
+ it has no block/allow surface of its own. It can only contribute a conservative "merged"
52
+ input, which the existing in-use/clean/blast-radius/breaker gates still sit in front of.
53
+
54
+ ## 5. Interactions
55
+
56
+ - **`isClean` ordering:** unchanged — `isMerged` (now with the gh path) is still only
57
+ reached AFTER the cheap protect-gates (in-use, dirty) clear, so no extra gh calls on
58
+ dirty/active worktrees.
59
+ - **Caching:** 60s TTL map + the existing 10s cwd cache — one sweep = one gh call.
60
+ - **Blast radius:** unchanged `maxReapsPerPass` (default 20) still caps deletions/sweep.
61
+ - **Breaker:** unchanged per-path removal-failure breaker still applies.
62
+
63
+ ## 6. External surfaces
64
+
65
+ - **New external call:** `gh pr list` (read-only) against the repo's GitHub. Requires gh
66
+ installed + authed; absent → fail-safe KEEP. No write, no new credential (uses the
67
+ ambient gh auth). Off-switch: `agentWorktreeReaper.githubMergeCheck: false`.
68
+ - No new route, no user-facing message, no config migration required (the field defaults
69
+ true via `?? true`, so existing agents get the behavior on the dist update).
70
+
71
+ ## 7. Rollback
72
+
73
+ Pure code + one config flag. `githubMergeCheck: false` restores cherry-only at runtime;
74
+ reverting the commit removes the path entirely. The reaper's OFF+dry-run default means no
75
+ agent reaps anything until explicitly enabled and reviewed.