instar 0.28.35 → 0.28.42

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 (82) hide show
  1. package/dashboard/index.html +40 -30
  2. package/dist/commands/server.d.ts.map +1 -1
  3. package/dist/commands/server.js +105 -46
  4. package/dist/commands/server.js.map +1 -1
  5. package/dist/core/CoherenceGate.d.ts +7 -0
  6. package/dist/core/CoherenceGate.d.ts.map +1 -1
  7. package/dist/core/CoherenceGate.js +7 -6
  8. package/dist/core/CoherenceGate.js.map +1 -1
  9. package/dist/core/CoherenceReviewer.d.ts +20 -5
  10. package/dist/core/CoherenceReviewer.d.ts.map +1 -1
  11. package/dist/core/CoherenceReviewer.js +36 -6
  12. package/dist/core/CoherenceReviewer.js.map +1 -1
  13. package/dist/core/OutboundDedupGate.d.ts +56 -0
  14. package/dist/core/OutboundDedupGate.d.ts.map +1 -0
  15. package/dist/core/OutboundDedupGate.js +90 -0
  16. package/dist/core/OutboundDedupGate.js.map +1 -0
  17. package/dist/core/PostUpdateMigrator.d.ts +0 -14
  18. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  19. package/dist/core/PostUpdateMigrator.js +2 -123
  20. package/dist/core/PostUpdateMigrator.js.map +1 -1
  21. package/dist/core/SessionManager.d.ts +9 -0
  22. package/dist/core/SessionManager.d.ts.map +1 -1
  23. package/dist/core/SessionManager.js +18 -0
  24. package/dist/core/SessionManager.js.map +1 -1
  25. package/dist/core/UpdateChecker.d.ts.map +1 -1
  26. package/dist/core/UpdateChecker.js +6 -2
  27. package/dist/core/UpdateChecker.js.map +1 -1
  28. package/dist/core/junk-payload.d.ts +14 -0
  29. package/dist/core/junk-payload.d.ts.map +1 -0
  30. package/dist/core/junk-payload.js +32 -0
  31. package/dist/core/junk-payload.js.map +1 -0
  32. package/dist/monitoring/CompactionSentinel.d.ts +143 -0
  33. package/dist/monitoring/CompactionSentinel.d.ts.map +1 -0
  34. package/dist/monitoring/CompactionSentinel.js +262 -0
  35. package/dist/monitoring/CompactionSentinel.js.map +1 -0
  36. package/dist/monitoring/PresenceProxy.d.ts +0 -40
  37. package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
  38. package/dist/monitoring/PresenceProxy.js +4 -156
  39. package/dist/monitoring/PresenceProxy.js.map +1 -1
  40. package/dist/monitoring/PromptGate.d.ts.map +1 -1
  41. package/dist/monitoring/PromptGate.js +0 -75
  42. package/dist/monitoring/PromptGate.js.map +1 -1
  43. package/dist/threadline/adapters/RESTServer.d.ts +7 -1
  44. package/dist/threadline/adapters/RESTServer.d.ts.map +1 -1
  45. package/dist/threadline/adapters/RESTServer.js +62 -1
  46. package/dist/threadline/adapters/RESTServer.js.map +1 -1
  47. package/dist/threadline/relay/OfflineQueue.js +1 -1
  48. package/dist/threadline/relay/OfflineQueue.js.map +1 -1
  49. package/package.json +1 -1
  50. package/scripts/check-upgrade-guide.js +9 -115
  51. package/scripts/collect-metrics.py +25 -120
  52. package/scripts/upgrade-guide-validator.mjs +221 -0
  53. package/src/data/builtin-manifest.json +18 -18
  54. package/upgrades/0.28.36.md +40 -0
  55. package/upgrades/0.28.37.md +69 -0
  56. package/upgrades/0.28.38.md +41 -0
  57. package/upgrades/0.28.39.md +29 -0
  58. package/upgrades/0.28.40.md +32 -0
  59. package/upgrades/0.28.42.md +25 -0
  60. package/upgrades/NEXT.md +18 -0
  61. package/upgrades/0.28.10.md +0 -19
  62. package/upgrades/0.28.11.md +0 -19
  63. package/upgrades/0.28.13.md +0 -11
  64. package/upgrades/0.28.15.md +0 -11
  65. package/upgrades/0.28.18.md +0 -12
  66. package/upgrades/0.28.20.md +0 -19
  67. package/upgrades/0.28.21.md +0 -23
  68. package/upgrades/0.28.22.md +0 -23
  69. package/upgrades/0.28.23.md +0 -19
  70. package/upgrades/0.28.24.md +0 -18
  71. package/upgrades/0.28.25.md +0 -21
  72. package/upgrades/0.28.26.md +0 -20
  73. package/upgrades/0.28.27.md +0 -20
  74. package/upgrades/0.28.28.md +0 -20
  75. package/upgrades/0.28.30.md +0 -25
  76. package/upgrades/0.28.31.md +0 -38
  77. package/upgrades/0.28.32.md +0 -22
  78. package/upgrades/0.28.33.md +0 -22
  79. package/upgrades/0.28.35.md +0 -37
  80. package/upgrades/0.28.5.md +0 -17
  81. package/upgrades/0.28.7.md +0 -24
  82. package/upgrades/0.28.8.md +0 -21
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-04-15T00:18:56.675Z",
5
- "instarVersion": "0.28.35",
4
+ "generatedAt": "2026-04-15T16:15:05.626Z",
5
+ "instarVersion": "0.28.42",
6
6
  "entryCount": 186,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -11,7 +11,7 @@
11
11
  "domain": "identity",
12
12
  "sourcePath": "src/core/PostUpdateMigrator.ts",
13
13
  "installedPath": ".instar/hooks/instar/session-start.sh",
14
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
14
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
15
15
  "since": "2025-01-01"
16
16
  },
17
17
  "hook:dangerous-command-guard": {
@@ -20,7 +20,7 @@
20
20
  "domain": "safety",
21
21
  "sourcePath": "src/core/PostUpdateMigrator.ts",
22
22
  "installedPath": ".instar/hooks/instar/dangerous-command-guard.sh",
23
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
23
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
24
24
  "since": "2025-01-01"
25
25
  },
26
26
  "hook:grounding-before-messaging": {
@@ -29,7 +29,7 @@
29
29
  "domain": "safety",
30
30
  "sourcePath": "src/core/PostUpdateMigrator.ts",
31
31
  "installedPath": ".instar/hooks/instar/grounding-before-messaging.sh",
32
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
32
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
33
33
  "since": "2025-01-01"
34
34
  },
35
35
  "hook:compaction-recovery": {
@@ -38,7 +38,7 @@
38
38
  "domain": "identity",
39
39
  "sourcePath": "src/core/PostUpdateMigrator.ts",
40
40
  "installedPath": ".instar/hooks/instar/compaction-recovery.sh",
41
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
41
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
42
42
  "since": "2025-01-01"
43
43
  },
44
44
  "hook:external-operation-gate": {
@@ -47,7 +47,7 @@
47
47
  "domain": "safety",
48
48
  "sourcePath": "src/core/PostUpdateMigrator.ts",
49
49
  "installedPath": ".instar/hooks/instar/external-operation-gate.js",
50
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
50
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
51
51
  "since": "2025-01-01"
52
52
  },
53
53
  "hook:deferral-detector": {
@@ -56,7 +56,7 @@
56
56
  "domain": "safety",
57
57
  "sourcePath": "src/core/PostUpdateMigrator.ts",
58
58
  "installedPath": ".instar/hooks/instar/deferral-detector.js",
59
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
59
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
60
60
  "since": "2025-01-01"
61
61
  },
62
62
  "hook:post-action-reflection": {
@@ -65,7 +65,7 @@
65
65
  "domain": "evolution",
66
66
  "sourcePath": "src/core/PostUpdateMigrator.ts",
67
67
  "installedPath": ".instar/hooks/instar/post-action-reflection.js",
68
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
68
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
69
69
  "since": "2025-01-01"
70
70
  },
71
71
  "hook:external-communication-guard": {
@@ -74,7 +74,7 @@
74
74
  "domain": "safety",
75
75
  "sourcePath": "src/core/PostUpdateMigrator.ts",
76
76
  "installedPath": ".instar/hooks/instar/external-communication-guard.js",
77
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
77
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
78
78
  "since": "2025-01-01"
79
79
  },
80
80
  "hook:scope-coherence-collector": {
@@ -83,7 +83,7 @@
83
83
  "domain": "coherence",
84
84
  "sourcePath": "src/core/PostUpdateMigrator.ts",
85
85
  "installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
86
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
86
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
87
87
  "since": "2025-01-01"
88
88
  },
89
89
  "hook:scope-coherence-checkpoint": {
@@ -92,7 +92,7 @@
92
92
  "domain": "coherence",
93
93
  "sourcePath": "src/core/PostUpdateMigrator.ts",
94
94
  "installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
95
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
95
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
96
96
  "since": "2025-01-01"
97
97
  },
98
98
  "hook:free-text-guard": {
@@ -101,7 +101,7 @@
101
101
  "domain": "safety",
102
102
  "sourcePath": "src/core/PostUpdateMigrator.ts",
103
103
  "installedPath": ".instar/hooks/instar/free-text-guard.sh",
104
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
104
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
105
105
  "since": "2025-01-01"
106
106
  },
107
107
  "hook:claim-intercept": {
@@ -110,7 +110,7 @@
110
110
  "domain": "coherence",
111
111
  "sourcePath": "src/core/PostUpdateMigrator.ts",
112
112
  "installedPath": ".instar/hooks/instar/claim-intercept.js",
113
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
113
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
114
114
  "since": "2025-01-01"
115
115
  },
116
116
  "hook:claim-intercept-response": {
@@ -119,7 +119,7 @@
119
119
  "domain": "coherence",
120
120
  "sourcePath": "src/core/PostUpdateMigrator.ts",
121
121
  "installedPath": ".instar/hooks/instar/claim-intercept-response.js",
122
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
122
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
123
123
  "since": "2025-01-01"
124
124
  },
125
125
  "hook:auto-approve-permissions": {
@@ -128,7 +128,7 @@
128
128
  "domain": "safety",
129
129
  "sourcePath": "src/core/PostUpdateMigrator.ts",
130
130
  "installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
131
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
131
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
132
132
  "since": "2025-01-01"
133
133
  },
134
134
  "job:health-check": {
@@ -1408,7 +1408,7 @@
1408
1408
  "type": "subsystem",
1409
1409
  "domain": "sessions",
1410
1410
  "sourcePath": "src/core/SessionManager.ts",
1411
- "contentHash": "4f5316ff9dde6b798dc369308f68399c0c34a43a0d9f61cfdc88fabbc4271f6f",
1411
+ "contentHash": "541adcef56fc133c4b56034eeacf17d27ebc4512dd89b09eced58e427b10df39",
1412
1412
  "since": "2025-01-01"
1413
1413
  },
1414
1414
  "subsystem:auto-updater": {
@@ -1432,7 +1432,7 @@
1432
1432
  "type": "subsystem",
1433
1433
  "domain": "updates",
1434
1434
  "sourcePath": "src/core/PostUpdateMigrator.ts",
1435
- "contentHash": "dd96a76bb76cf753f461dd7b999e3ce527c7cd0f0a5794ec2aff112a9774619a",
1435
+ "contentHash": "ce2a71744732f5e6d5db9534ee06b33bac00a1f898d9dd8292d44705a353deaf",
1436
1436
  "since": "2025-01-01"
1437
1437
  },
1438
1438
  "subsystem:scheduler": {
@@ -0,0 +1,40 @@
1
+ # Upgrade Guide — v0.28.36
2
+
3
+ <!-- bump: patch -->
4
+
5
+ ## What Changed
6
+
7
+ **Compaction-resume now injects a re-orient prompt, not the user's last message.**
8
+
9
+ When a session compacts mid-conversation (via `/compact` or Claude Code's
10
+ auto-compact), its working context is gone. The prior behavior — re-sending the
11
+ user's last message verbatim — assumed the agent still had thread context, which
12
+ by definition it doesn't after compaction. That produced responses that read as
13
+ a second-pass attempt at the same message rather than a real continuation.
14
+
15
+ The compaction-resume helper (`recoverCompactedSession` in `server.ts`) now
16
+ injects a single prompt:
17
+
18
+ please read the previous messages in this topic and continue
19
+
20
+ This lets the agent fetch recent topic/channel history through its own tooling
21
+ and resume coherently. Applies to all three independent triggers:
22
+
23
+ 1. `PreCompact` hook event
24
+ 2. `SessionWatchdog` `compaction-idle` poll
25
+ 3. `POST /internal/compaction-resume` from `compaction-recovery.sh`
26
+
27
+ The Slack path previously still detoured through `TriageOrchestrator`, whose
28
+ `reinject_message` heuristic ignores the passed-in `pendingMessage` and always
29
+ re-sends the last user message from history — defeating the override. Slack now
30
+ bypasses triage and injects directly, matching the Telegram path.
31
+
32
+ ## What to Tell Your User
33
+
34
+ - **Smoother continuity after compaction**: "When my session gets auto-summarized mid-conversation, I'll now pick up by re-reading the recent thread and continuing — instead of replaying your message like nothing happened."
35
+
36
+ ## Summary of New Capabilities
37
+
38
+ | Capability | How to Use |
39
+ |-----------|-----------|
40
+ | Compaction-resume re-orient prompt | Automatic — fires on all three compaction-recovery triggers |
@@ -0,0 +1,69 @@
1
+ # Upgrade Guide — v0.28.37
2
+
3
+ <!-- bump: patch -->
4
+
5
+ ## What Changed
6
+
7
+ **New: `CompactionSentinel` — a dedicated monitor that owns the full post-compaction recovery lifecycle.**
8
+
9
+ Prior to this release, three independent trigger paths (PreCompact hook event, `SessionWatchdog` `compaction-idle` poll, and the `POST /internal/compaction-resume` endpoint called by `compaction-recovery.sh`) all called the `recoverCompactedSession` helper fire-and-forget. If the injection didn't wake the session up — which happens when the Claude process is hung, the injection is silently dropped, or the session is genuinely dead — nobody noticed. The 15-minute idle-prompt zombie-killer in `SessionManager` then raced the recovery window and killed the session, wiping the user's conversation.
10
+
11
+ The `CompactionSentinel` adds:
12
+
13
+ - **Dedupe** — multiple triggers for the same session inside a 1-minute window collapse into a single recovery lifecycle, preventing three overlapping inject attempts from racing each other.
14
+ - **Verification** — after each injection, the sentinel samples the most recently-modified Claude Code JSONL file for this project; growth in size or mtime within a 25s window is taken as proof that Claude actually processed the prompt and emitted output.
15
+ - **Retry** — if verification fails within the window, the sentinel re-injects, up to `maxInjectAttempts` (default 3). It only declares failure after verified exhaustion.
16
+ - **Zombie-kill veto** — `SessionManager` now exposes `setActiveRecoveryChecker`, and the idle-prompt cleanup skips sessions that are in active recovery. When it skips, it also resets the idle clock so we don't re-race the cleanup on the next poll either.
17
+ - **Observability** — every step logs with the `[Sentinel]` prefix. Lifecycle events (`compaction:detected`, `inject-attempted`, `recovered`, `failed`) are emitted with full state payloads so downstream monitors can subscribe.
18
+
19
+ The three trigger paths in `server.ts` now report into the sentinel instead of calling `recoverCompactedSession` directly. The helper is still used — the sentinel takes it as an injected dependency, so topic/channel routing stays in `server.ts` and this class stays focused on the recovery state machine.
20
+
21
+ Wiring detail: `CompactionSentinel` is instantiated next to `SessionWatchdog` in `server.ts` startup. `sessionManager.setActiveRecoveryChecker(session => sentinel.isRecoveryActive(session.tmuxSession))` is registered during the same block. Default config (1m dedupe, 25s verify window, 3 attempts, 10m recovery guard) is production-tuned; override via the config object if needed.
22
+
23
+ ## What to Tell Your User
24
+
25
+ - **More reliable recovery after my session gets auto-summarized**: "When my conversation hits the context limit and gets compressed, I now verify that I actually woke up and responded — not just that a prompt was sent. If the first attempt didn't land, I retry before giving up. And the idle-session cleanup knows to leave me alone while a recovery is in progress, so conversations no longer get wiped out mid-recovery."
26
+
27
+ ## Summary of New Capabilities
28
+
29
+ | Capability | How to Use |
30
+ |-----------|-----------|
31
+ | Compaction recovery verification | automatic (no config change) |
32
+ | Compaction recovery retry | automatic, up to 3 attempts per session |
33
+ | Zombie-kill veto during recovery | automatic via setActiveRecoveryChecker on SessionManager |
34
+ | Lifecycle events for observers | CompactionSentinel emits compaction:detected / inject-attempted / recovered / failed |
35
+
36
+ ## Evidence
37
+
38
+ **Reproduction of the prior failure mode is documented in echo's server.log:**
39
+
40
+ At 2026-04-15T03:21:05Z and 03:26:35Z (pre-0.28.37, old behavior on session "echo-watchdog-issues"):
41
+
42
+ [Watchdog] "echo-watchdog-issues": compaction-idle detected — session compacted and at prompt
43
+
44
+ Followed by silence. No recovery attempt logged. No visibility into what happened next. The old code called recoverCompactedSession() and forgot. On 2026-04-15T01:33Z a different session went through the same sequence, showed a single [CompactionResume] direct re-inject OK line, and then was killed 25 minutes later as a zombie. That is the load-bearing failure this release addresses.
45
+
46
+ **Observed behavior after 0.28.37 was installed and the server restarted at 2026-04-15T03:27:34Z:**
47
+
48
+ Same watchdog trigger, same session, new behavior (within 5s of server startup):
49
+
50
+ [Watchdog] "echo-watchdog-issues": compaction-idle detected — session compacted and at prompt
51
+ [Sentinel] detected compaction on "echo-watchdog-issues" via watchdog-poll; baseline jsonl: none size=n/a
52
+ [Sentinel] inject-attempted on "echo-watchdog-issues" (attempt 1/3, accepted=false)
53
+ [Sentinel] failed "echo-watchdog-issues": recoverFn declined (no pending work or session gone)
54
+
55
+ The sentinel correctly determined there was no pending user message to recover and finalized as "failed" with a clear reason — an outcome that was silently invisible before.
56
+
57
+ **Direct endpoint path verified:**
58
+
59
+ A POST to /internal/compaction-resume with {"sessionName":"synthetic-test-session-xyz"} produced:
60
+
61
+ [Sentinel] detected compaction on "synthetic-test-session-xyz" via recovery-hook; baseline jsonl: none size=n/a
62
+ [Sentinel] inject-attempted on "synthetic-test-session-xyz" (attempt 1/3, accepted=false)
63
+ [Sentinel] failed "synthetic-test-session-xyz": recoverFn declined (no pending work or session gone)
64
+
65
+ **Dedupe verified in production:** three identical POSTs to the endpoint within 3 seconds produced exactly one lifecycle trace, not three. The old behavior would have attempted three injections racing each other.
66
+
67
+ **Unit coverage (14 new tests in tests/unit/CompactionSentinel.test.ts, 100% pass):** detection + recoverFn dispatch; dedupe within window; parallel session independence; verification success via JSONL size growth → recovered emitted with jsonlDelta; retry on no-growth up to maxInjectAttempts; success on later attempt stops the retry; max-attempts exhausted → failed emitted with reason; recoverFn returning false → fast failed without retry; recoverFn throwing → treated as non-acceptance; isRecoveryActive predicate correct across all lifecycle states; JSONL edge cases (no file, mtime-only change); clear/stop cleanup.
68
+
69
+ **What has NOT been verified in production:** a real-compaction positive-path trace (session genuinely compacts, has an unanswered user message, sentinel injects, Claude responds, JSONL grows, recovered emits). That requires either spawning a fresh Claude session and driving /compact through it, or waiting for a natural compaction on a session that happens to have an unanswered message — neither was deterministically triggerable during this autonomous run without disrupting the active user session. The verification logic itself is exercised by the 14 unit tests, and the production traces above confirm the sentinel is wired into all three trigger paths correctly. If a natural positive-path trace shows up during the remaining autonomous-mode time, the next release will reference it here.
@@ -0,0 +1,41 @@
1
+ # Upgrade Guide — v0.28.38
2
+
3
+ <!-- bump: patch -->
4
+
5
+ ## What Changed
6
+
7
+ **Fix: CompactionSentinel targets the exact session's JSONL file by Claude Code session UUID, preventing false positives from sibling sessions.**
8
+
9
+ In 0.28.37 the verification step picked the most-recently-modified jsonl file in the project's `.claude/projects/<hash>/` directory. For projects with multiple concurrent sessions (the common case — a user topic session alongside a job session), a sibling session emitting output during the 25s verify window would look identical to "our session recovered." The sentinel would mistakenly emit `compaction:recovered` and close out, while the actually-stuck session was still asleep.
10
+
11
+ This release threads `getClaudeSessionId(sessionName)` through `CompactionSentinelDeps`. When the Claude Code session UUID is known (populated on the session's first hook event via `Session.claudeSessionId`), the sentinel reads exactly `<uuid>.jsonl` and nothing else. When the UUID isn't known yet — typically for very new sessions or sessions that haven't fired a hook — the sentinel falls back to the previous most-recently-modified behavior.
12
+
13
+ Wiring: `server.ts` passes a resolver that looks up `sessionManager.listRunningSessions()` and returns `session.claudeSessionId` for matching tmux sessions.
14
+
15
+ ## What to Tell Your User
16
+
17
+ - **Recovery verification is now session-accurate**: "When I'm monitoring whether a compaction recovery actually worked, I check the right file — not just the most-recently-touched one. That matters on machines where several sessions are active at once."
18
+
19
+ ## Summary of New Capabilities
20
+
21
+ | Capability | How to Use |
22
+ |-----------|-----------|
23
+ | Session-targeted jsonl verification | automatic when session has claudeSessionId; falls back to previous behavior otherwise |
24
+
25
+ ## Evidence
26
+
27
+ **Reproduction of the failure mode via unit test (tests/unit/CompactionSentinel.test.ts):**
28
+
29
+ The new test "uses claudeSessionId to target the exact jsonl when available" sets up two sibling jsonl files in the temp jsonl root (`abc-123.jsonl` for session s1 and `sibling-session.jsonl` for another session). It then:
30
+
31
+ 1. Reports compaction on s1 — sentinel records baseline from `abc-123.jsonl`.
32
+ 2. Grows `sibling-session.jsonl` to 5000 bytes (simulating the sibling session emitting output).
33
+ 3. Advances past the verify window.
34
+ 4. Asserts `compaction:recovered` is NOT emitted (correctly — the sibling grew, not s1's file).
35
+ 5. Grows `abc-123.jsonl` to 400 bytes.
36
+ 6. Advances past another verify window.
37
+ 7. Asserts `compaction:recovered` IS emitted.
38
+
39
+ Before the fix, step 4 would have failed (sentinel emits recovered on sibling growth). After the fix, it passes. All 15 CompactionSentinel tests pass (14 from 0.28.37 + this new isolation test).
40
+
41
+ **Not reproduced in production** — the fix is preventive. Catching it required reading the code after 0.28.37 was already live, and I chose to ship the fix immediately via unit-test-verified behavior rather than wait for a natural multi-session scenario to expose it. Natural in-production evidence would require two sessions within the same project compacting simultaneously with overlapping recovery windows, which is non-deterministic.
@@ -0,0 +1,29 @@
1
+ # Upgrade Guide — v0.28.39
2
+
3
+ <!-- bump: patch -->
4
+
5
+ ## What Changed
6
+
7
+ **Fix: CompactionSentinel allows re-recovery after a previous recovery finalizes, even within the dedupe window.**
8
+
9
+ The `recentReports` map, used to dedupe overlapping trigger events from the PreCompact hook, watchdog poll, and recovery-hook endpoint, was only cleared by `stop()` and `clear()`. When a recovery finalized (either `recovered` or `failed`) and the session compacted again within the 60-second dedupe window, the second compaction was silently suppressed — same session, fresh compaction event, no recovery attempt.
10
+
11
+ Fix: on finalize, schedule the `recentReports[sessionName]` entry to be deleted alongside the `active[sessionName]` entry (after the keep-window). A second compaction on the same session is now always eligible for a fresh recovery once the first one has finalized and its keep-window elapsed.
12
+
13
+ ## What to Tell Your User
14
+
15
+ - **Back-to-back session recoveries work now**: "If my session goes through compaction twice in quick succession, I recover from the second one the same way I recovered from the first — no silent skipping."
16
+
17
+ ## Summary of New Capabilities
18
+
19
+ | Capability | How to Use |
20
+ |-----------|-----------|
21
+ | Re-recovery after finalize | automatic — no config change |
22
+
23
+ ## Evidence
24
+
25
+ **Reproduction of the failure mode via unit test (tests/unit/CompactionSentinel.test.ts "allows re-recovery after a previous recovery finalizes"):**
26
+
27
+ The test sets up a recovery that succeeds, waits out the 5-second keep-window, then triggers a second compaction on the same session. It asserts that exactly 2 `compaction:detected` events fire (one per compaction). Before the fix: only 1 event fired — the second report was silently suppressed by the `recentReports` timestamp from the first. After the fix: both fire. 16/16 CompactionSentinel tests pass.
28
+
29
+ **Not reproduced in production** — this is a code-audit finding. Triggering it naturally requires two compactions on the same session within a 65-second window (60s dedupe + up to 5s keep-window for a recovered state), which doesn't happen on the current traffic here. The fix is verified against the state machine via the new test; production evidence would require forcing that timing, which is not deterministically reproducible.
@@ -0,0 +1,32 @@
1
+ # Upgrade Guide — v0.28.40
2
+
3
+ <!-- bump: patch -->
4
+
5
+ ## What Changed
6
+
7
+ **Injected recovery prompt now instructs the agent to re-orient on topic history first, inform the user that compaction occurred, and then continue.**
8
+
9
+ The prompt the CompactionSentinel injects after detection was previously:
10
+
11
+ please read the previous messages in this topic and continue
12
+
13
+ That got the agent reading history but left two gaps: (a) the user never learned that a compaction happened — the agent would appear to mysteriously shift tone/awareness with no explanation, and (b) the single-sentence instruction didn't make the re-orient-first ordering explicit, so the agent sometimes replied from a blank slate before reading history.
14
+
15
+ New prompt:
16
+
17
+ Your session just went through context compaction. Read the recent messages in this topic to re-orient, briefly let the user know compaction occurred, then continue where you left off.
18
+
19
+ Three explicit steps in order: orient (read history), acknowledge (tell the user), continue (pick up the thread). The user-facing acknowledgment is explicit — if an invisible context wipe happens, the user should know.
20
+
21
+ Applies to all three recovery trigger paths (PreCompact hook event, watchdog compaction-idle poll, recovery-hook endpoint) via the shared `COMPACTION_RESUME_PROMPT` constant in `server.ts`.
22
+
23
+ ## What to Tell Your User
24
+
25
+ - **You'll know when my context gets compressed now**: "If my conversation hits the context limit and gets auto-summarized mid-thread, I'll briefly tell you that happened when I pick back up — instead of just silently continuing like nothing changed."
26
+
27
+ ## Summary of New Capabilities
28
+
29
+ | Capability | How to Use |
30
+ |-----------|-----------|
31
+ | User notification on compaction recovery | automatic — the agent announces when compaction occurred on its next response |
32
+ | Explicit re-orient-first ordering | automatic — the injected prompt tells the agent to read history before replying |
@@ -0,0 +1,25 @@
1
+ # Upgrade Guide — v0.28.42
2
+
3
+ <!-- bump: patch -->
4
+
5
+ ## What Changed
6
+
7
+ Fixed a silent failure in post-update migration: when Node.js is upgraded in place (e.g., via `brew upgrade node`) while an Instar server is still running, `process.execPath` can point at a binary path that no longer exists on disk. The subsequent spawn fails with ENOENT and post-update migration skips silently, leaving agent configuration stale after auto-updates.
8
+
9
+ `UpdateChecker.postUpdateMigration` now guards `process.execPath` with an `existsSync` check and falls back to `node` on PATH when the resolved exec path has been deleted.
10
+
11
+ ## What to Tell Your User
12
+
13
+ - **More reliable self-updates**: "If your system's Node was upgraded while I was running, my next auto-update will still apply its migrations correctly instead of silently skipping them."
14
+
15
+ ## Summary of New Capabilities
16
+
17
+ | Capability | How to Use |
18
+ |-----------|-----------|
19
+ | Resilient post-update migration across in-place Node upgrades | automatic |
20
+
21
+ ## Evidence
22
+
23
+ Reproduction: Homebrew users who ran `brew upgrade node` between Instar server starts reported repeated `UpdateChecker.postUpdateMigration` degradation events with reason `spawn /opt/homebrew/Cellar/node@22/22.22.2/bin/node ENOENT`. Root cause traced to `src/core/UpdateChecker.ts:282` where `cmd = process.execPath` was spawned unconditionally.
24
+
25
+ Verified fix: Before — `execFile(process.execPath, [shadowCliJs, 'migrate'])` rejects with ENOENT when the Cellar path is gone; degradation reporter fires; migration skipped. After — `fs.existsSync(process.execPath)` returns false, `cmd` falls back to `'node'`, spawn resolves via PATH, migration runs. Unit tests for UpdateChecker (13) continue to pass.
package/upgrades/NEXT.md CHANGED
@@ -33,3 +33,21 @@
33
33
  | Capability | How to Use |
34
34
  |-----------|-----------|
35
35
  | [Capability] | [Endpoint, command, or "automatic"] |
36
+
37
+ ## Evidence
38
+
39
+ <!-- REQUIRED if this release claims to fix a bug. -->
40
+ <!-- Unit tests passing is NOT evidence. Provide ONE of: -->
41
+ <!-- (a) Reproduction steps + observed before/after on a live system. -->
42
+ <!-- Include log excerpts, observed command output, or behavior -->
43
+ <!-- description. Make it specific enough that a future reader can -->
44
+ <!-- re-run it and see the same thing. -->
45
+ <!-- (b) "Not reproducible in dev — [concrete reason]" if the failure -->
46
+ <!-- mode truly can't be exercised locally (race conditions, -->
47
+ <!-- event-driven paths requiring external signals, etc). -->
48
+ <!-- -->
49
+ <!-- If this release doesn't claim a bug fix (pure feature / refactor), -->
50
+ <!-- leave this section blank or delete it — it's only enforced when -->
51
+ <!-- "What Changed" describes a fix. -->
52
+
53
+ [Describe reproduction + verified fix, OR "Not reproducible in dev — [concrete reason]"]
@@ -1,19 +0,0 @@
1
- # Upgrade Guide — v0.28.10
2
-
3
- <!-- bump: patch -->
4
-
5
- ## What Changed
6
-
7
- Job gate checks now retry up to 3 times with a 5-second delay between attempts before recording a skip. Previously, a single gate failure (e.g., health check returning non-zero during a brief server restart) would immediately skip the job. This caused guardian jobs scheduled at minute 0 to consistently miss their windows when the server restarts hourly at the same time.
8
-
9
- The existing `scheduleRetry` mechanism (1min, 5min, 15min escalating retries) remains as a second layer, but the in-gate retry handles the most common case: a health endpoint that's unavailable for a few seconds during restart.
10
-
11
- ## What to Tell Your User
12
-
13
- - **More reliable scheduled jobs**: "Jobs that depend on health checks are now more resilient to brief server restart windows. If you've noticed guardian or monitoring jobs being skipped, they should start running consistently now."
14
-
15
- ## Summary of New Capabilities
16
-
17
- | Capability | How to Use |
18
- |-----------|-----------|
19
- | Gate retry on transient failure | Automatic — no configuration needed |
@@ -1,19 +0,0 @@
1
- # Upgrade Guide — v0.28.11
2
-
3
- <!-- bump: patch -->
4
-
5
- ## What Changed
6
-
7
- The GET /context endpoint now includes the `contextDir` path in its response, making it possible for agents to verify that the server is looking in the same directory where their context files live. This helps diagnose the "0 bytes for all segments" issue that occurs when there's a path mismatch between the server's configured state directory and where hooks/sessions create context files.
8
-
9
- Response format changed from an array of segments to `{ contextDir: string, segments: [...] }`.
10
-
11
- ## What to Tell Your User
12
-
13
- - **Better context diagnostics**: "If your context segments ever show as empty despite files being on disk, the context endpoint now shows the exact directory path the server is checking. This makes it easy to spot path mismatches."
14
-
15
- ## Summary of New Capabilities
16
-
17
- | Capability | How to Use |
18
- |-----------|-----------|
19
- | Context directory path in response | GET /context now returns contextDir alongside segments |
@@ -1,11 +0,0 @@
1
- ## What Changed
2
-
3
- - **Prerequisites installer now auto-installs Homebrew on macOS.** Previously, on a fresh Mac without Homebrew, the installer would bail out and tell the user to install Homebrew manually. Now it offers to install Homebrew non-interactively using the official install script, then proceeds to install tmux via `brew install tmux`.
4
-
5
- ## What to Tell Your User
6
-
7
- Nothing — this is a seamless improvement to the setup experience. Users on fresh Macs will now be prompted to install Homebrew automatically instead of being told to do it themselves.
8
-
9
- ## Summary of New Capabilities
10
-
11
- - `npx instar` on a fresh macOS machine now handles the full dependency chain: Homebrew -> tmux -> Claude CLI, all with interactive prompts and no manual steps required.
@@ -1,11 +0,0 @@
1
- ## What Changed
2
-
3
- - **Fixed Homebrew installer failing on admin accounts.** The previous version used NONINTERACTIVE mode which prevented the sudo password prompt, causing installation to fail even on admin accounts with a misleading "needs to be an Administrator" error. Now stdio is inherited so the user can enter their password when prompted. Timeout also increased to 10 minutes to accommodate Xcode Command Line Tools installation.
4
-
5
- ## What to Tell Your User
6
-
7
- Nothing — this is a fix to the setup experience. Installing on a fresh Mac will now correctly prompt for the password instead of failing silently.
8
-
9
- ## Summary of New Capabilities
10
-
11
- No new capabilities — bug fix to Homebrew auto-install from 0.28.13.
@@ -1,12 +0,0 @@
1
- ## What Changed
2
-
3
- - **GitHub CLI is now a real prerequisite.** Previously the setup wizard only emitted a soft warning when gh was missing, then continued without it — silently disabling cloud-backed agent discovery, GitHub backup sync, CI status checks, and PR/issue management. GitHub CLI is now part of the prerequisites check alongside Node.js, tmux, and Claude CLI, with auto-install support via Homebrew on macOS and apt on Linux. If Homebrew is missing on macOS, the wizard offers to install Homebrew first (same flow as the existing tmux path).
4
-
5
- ## What to Tell Your User
6
-
7
- If you're on a fresh machine, the setup wizard will now offer to install GitHub CLI automatically. After install, I can help you sign in to GitHub so I can sync state across machines and discover any other agents you've set up. Without GitHub CLI, I still work locally but can't back things up to GitHub or find your other agents.
8
-
9
- ## Summary of New Capabilities
10
-
11
- - GitHub CLI added as a fourth prerequisite with auto-install on macOS (Homebrew) and Linux (apt)
12
- - Two-step install flow: if Homebrew is missing on macOS, wizard offers to install it before installing GitHub CLI
@@ -1,19 +0,0 @@
1
- # Upgrade Guide — vNEXT
2
-
3
- <!-- bump: patch -->
4
-
5
- ## What Changed
6
-
7
- - **Setup wizard now offers GitHub sign-in BEFORE asking for an agent name.** Previously, when GitHub CLI was installed but not authenticated (or when the discovery scan ran without GitHub access), the wizard silently moved on to "what should we call your agent?" — even if the user already had agents backed up to GitHub from another machine. Users were creating duplicates instead of restoring. The Entry Point B branches in `setup-wizard/SKILL.md` for `gh_status="auth-needed"` and `gh_status="unavailable"` are now MANDATORY blocking steps with imperative language.
8
- - **GitHub Device-Code Auth Flow documented.** Running `gh auth login --web --git-protocol https` synchronously inside Claude Code's Bash tool blocks on the device-code prompt and the user sees a frozen command with no instructions. The skill now instructs the agent to: run gh auth in the background, poll its output for the device code and URL, present them to the user conversationally, then poll `gh auth status` until the user completes the sign-in. Same flow is referenced from Phase 4 (cloud backup) so there's one canonical pattern.
9
-
10
- ## What to Tell Your User
11
-
12
- If you're setting up a fresh machine and you've used Instar before, the wizard will now offer to sign you in to GitHub first so I can find any agents you've backed up — instead of creating a duplicate. The sign-in itself is also smoother: I'll show you the code to enter at github.com/login/device right in our chat instead of leaving you staring at a stuck terminal.
13
-
14
- ## Summary of New Capabilities
15
-
16
- | Capability | How to Use |
17
- |-----------|-----------|
18
- | Mandatory pre-name GitHub auth offer | Automatic during setup wizard |
19
- | Background device-code auth flow | Automatic during setup wizard |
@@ -1,23 +0,0 @@
1
- # Upgrade Guide — v0.28.21
2
-
3
- <!-- bump: patch -->
4
-
5
- ## What Changed
6
-
7
- - **Threadline delivery honesty**: `/messages/relay-agent` now awaits `ThreadlineRouter` and returns the real outcome (`spawned`, `resumed`, `injected`, `queued`, `error`) instead of always saying `delivered:true`. The `threadline_send` MCP tool surfaces the actual status to callers.
8
- - **First-contact messages no longer dropped**: `ThreadlineRouter` mints a UUID threadId for messages without one, routing them through `spawnNewThread` instead of silently returning `{handled:false}`.
9
- - **Fingerprint-based identity**: Reply waiters rekeyed by threadId (prevents same-name agent collisions). Self-guard compares fingerprints. Ambiguous targets (multiple agents sharing a name) now fail loudly with a fingerprint-qualifier hint.
10
- - **Live-session injection**: `ThreadlineRouter` tries `MessageDelivery.deliverToSession` (tmux send-keys) before falling back to spawn/resume — messages can reach already-running sessions without spawning a new process.
11
-
12
- ## What to Tell Your User
13
-
14
- Agent-to-agent messaging (threadline) has been fixed. Messages between agents now actually reach the recipient's active session, first-contact messages work, and agents with the same name on different machines no longer collide.
15
-
16
- ## Summary of New Capabilities
17
-
18
- | Capability | How to Use |
19
- |-----------|-----------|
20
- | Honest delivery status | `threadline_send` now reports `spawned` / `resumed` / `injected` / `queued` instead of always `delivered` |
21
- | First-contact messaging | Just send — no threadId needed on first message, one is minted automatically |
22
- | Same-name agent disambiguation | Use `name:fpPrefix` format (e.g., `luna:ab12cd34`) when multiple agents share a name |
23
- | Live-session injection | Automatic — messages try injection into running sessions before spawning new ones |
@@ -1,23 +0,0 @@
1
- # Upgrade Guide — v0.28.22
2
-
3
- <!-- bump: patch -->
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
- - Replaced all `execSync` calls in server startup (better-sqlite3 auto-rebuild) with shell-free `execFileSync` using npm's CLI JS directly. Fixes "spawnSync /bin/sh ENOENT" failures in minimal/containerized environments.
12
- - Added `findNpmCli()` helper that locates npm's entry point without requiring a shell.
13
- - Affects `ensureSqliteBindings()` preflight and TopicMemory auto-rebuild fallback.
14
-
15
- ## What to Tell Your User
16
-
17
- - **Better startup reliability**: "Agents running in Docker or minimal Linux environments should no longer see SemanticMemory or TopicMemory degradation at startup. The native module rebuild now works without requiring a system shell."
18
-
19
- ## Summary of New Capabilities
20
-
21
- | Capability | How to Use |
22
- |-----------|-----------|
23
- | Shell-free native module rebuild | Automatic — no user action needed |
@@ -1,19 +0,0 @@
1
- # Upgrade Guide — v0.28.23
2
-
3
- <!-- bump: patch -->
4
-
5
- ## What Changed
6
-
7
- - Replaced all shell-dependent npm calls in server startup (better-sqlite3 auto-rebuild) with shell-free alternatives using npm's CLI JS directly via Node.js. Fixes "spawnSync /bin/sh ENOENT" failures in minimal/containerized environments.
8
- - Added findNpmCli helper that locates npm's entry point without requiring a shell.
9
- - Affects ensureSqliteBindings preflight and TopicMemory auto-rebuild fallback.
10
-
11
- ## What to Tell Your User
12
-
13
- - **Better startup reliability**: "Agents running in Docker or minimal Linux environments should no longer see memory system degradation at startup. The native module rebuild now works without requiring a system shell."
14
-
15
- ## Summary of New Capabilities
16
-
17
- | Capability | How to Use |
18
- |-----------|-----------|
19
- | Shell-free native module rebuild | Automatic — no user action needed |
@@ -1,18 +0,0 @@
1
- # Upgrade Guide — v0.28.24
2
-
3
- <!-- bump: patch -->
4
-
5
- ## What Changed
6
-
7
- - The /semantic/export-memory endpoint no longer overwrites MEMORY.md when SemanticMemory has 0 entities. Previously, an empty export would destroy manually-curated memory content. Now skips the write and returns existing file metadata with a skipped flag.
8
- - MemoryExporter.write() guards against empty-entity overwrites at the class level.
9
-
10
- ## What to Tell Your User
11
-
12
- - **Memory file protection**: "Your MEMORY.md is now safe from accidental overwrites. If the knowledge graph hasn't been populated yet, the export will leave your existing memory file untouched instead of replacing it with an empty template."
13
-
14
- ## Summary of New Capabilities
15
-
16
- | Capability | How to Use |
17
- |-----------|-----------|
18
- | Empty-export guard | Automatic — no user action needed |
@@ -1,21 +0,0 @@
1
- # Upgrade Guide — v0.28.25
2
-
3
- <!-- bump: patch -->
4
-
5
- ## What Changed
6
-
7
- - Fixed dashboard apiFetch to properly pass method, headers, and body options to fetch. Feature toggles and autonomy profile changes now persist instead of silently failing as GET requests.
8
- - Fixed degradation-digest job gate and skill to read from the correct file path (.instar/degradations.json instead of .instar/state/degradation-events.json). The job can now actually run.
9
- - Fixed MemoryExporter to not overwrite existing MEMORY.md when SemanticMemory has 0 entities.
10
-
11
- ## What to Tell Your User
12
-
13
- - **Dashboard feature toggles work now**: "Feature toggles and autonomy profile changes in the dashboard now actually save. Previously they appeared to toggle but silently reverted."
14
- - **Degradation monitoring active**: "The degradation digest job can now run properly. It was blocked by a wrong file path since it was created."
15
-
16
- ## Summary of New Capabilities
17
-
18
- | Capability | How to Use |
19
- |-----------|-----------|
20
- | Working dashboard toggles | Toggle features in the dashboard Features tab |
21
- | Degradation digest job | Automatic — runs every 4 hours when degradation events exist |