instar 1.3.207 → 1.3.208
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.
- package/dist/commands/init.js +4 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +23 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +119 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/types.d.ts +10 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/sentinelWiring.d.ts +13 -0
- package/dist/monitoring/sentinelWiring.d.ts.map +1 -1
- package/dist/monitoring/sentinelWiring.js +44 -1
- package/dist/monitoring/sentinelWiring.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +19 -19
- package/upgrades/1.3.208.md +54 -0
- package/upgrades/side-effects/spinner-immune-liveness.md +122 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-06-02T21:
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-06-02T21:56:02.195Z",
|
|
5
|
+
"instarVersion": "1.3.208",
|
|
6
6
|
"entryCount": 195,
|
|
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": "
|
|
14
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
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": "
|
|
23
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
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": "
|
|
32
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
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": "
|
|
41
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
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": "
|
|
50
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
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": "
|
|
59
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
60
60
|
"since": "2025-01-01"
|
|
61
61
|
},
|
|
62
62
|
"hook:self-stop-guard": {
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"domain": "coherence",
|
|
66
66
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
67
67
|
"installedPath": ".instar/hooks/instar/self-stop-guard.js",
|
|
68
|
-
"contentHash": "
|
|
68
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
69
69
|
"since": "2025-01-01"
|
|
70
70
|
},
|
|
71
71
|
"hook:post-action-reflection": {
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"domain": "evolution",
|
|
75
75
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
76
76
|
"installedPath": ".instar/hooks/instar/post-action-reflection.js",
|
|
77
|
-
"contentHash": "
|
|
77
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
78
78
|
"since": "2025-01-01"
|
|
79
79
|
},
|
|
80
80
|
"hook:external-communication-guard": {
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"domain": "safety",
|
|
84
84
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
85
85
|
"installedPath": ".instar/hooks/instar/external-communication-guard.js",
|
|
86
|
-
"contentHash": "
|
|
86
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
87
87
|
"since": "2025-01-01"
|
|
88
88
|
},
|
|
89
89
|
"hook:scope-coherence-collector": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"domain": "coherence",
|
|
93
93
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
94
94
|
"installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
|
|
95
|
-
"contentHash": "
|
|
95
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
96
96
|
"since": "2025-01-01"
|
|
97
97
|
},
|
|
98
98
|
"hook:scope-coherence-checkpoint": {
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"domain": "coherence",
|
|
102
102
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
103
103
|
"installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
|
|
104
|
-
"contentHash": "
|
|
104
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
105
105
|
"since": "2025-01-01"
|
|
106
106
|
},
|
|
107
107
|
"hook:free-text-guard": {
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"domain": "safety",
|
|
111
111
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
112
112
|
"installedPath": ".instar/hooks/instar/free-text-guard.sh",
|
|
113
|
-
"contentHash": "
|
|
113
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
114
114
|
"since": "2025-01-01"
|
|
115
115
|
},
|
|
116
116
|
"hook:claim-intercept": {
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"domain": "coherence",
|
|
120
120
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
121
121
|
"installedPath": ".instar/hooks/instar/claim-intercept.js",
|
|
122
|
-
"contentHash": "
|
|
122
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
123
123
|
"since": "2025-01-01"
|
|
124
124
|
},
|
|
125
125
|
"hook:claim-intercept-response": {
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"domain": "coherence",
|
|
129
129
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
130
130
|
"installedPath": ".instar/hooks/instar/claim-intercept-response.js",
|
|
131
|
-
"contentHash": "
|
|
131
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
132
132
|
"since": "2025-01-01"
|
|
133
133
|
},
|
|
134
134
|
"hook:stop-gate-router": {
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"domain": "safety",
|
|
138
138
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
139
139
|
"installedPath": ".instar/hooks/instar/stop-gate-router.js",
|
|
140
|
-
"contentHash": "
|
|
140
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
141
141
|
"since": "2025-01-01"
|
|
142
142
|
},
|
|
143
143
|
"hook:auto-approve-permissions": {
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"domain": "safety",
|
|
147
147
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
148
148
|
"installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
|
|
149
|
-
"contentHash": "
|
|
149
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
150
150
|
"since": "2025-01-01"
|
|
151
151
|
},
|
|
152
152
|
"job:health-check": {
|
|
@@ -1506,7 +1506,7 @@
|
|
|
1506
1506
|
"type": "subsystem",
|
|
1507
1507
|
"domain": "updates",
|
|
1508
1508
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
1509
|
-
"contentHash": "
|
|
1509
|
+
"contentHash": "623bae8fdc8451b34fca0ac1d83fb255d3e8c449d8bf923b0997357b383a0173",
|
|
1510
1510
|
"since": "2025-01-01"
|
|
1511
1511
|
},
|
|
1512
1512
|
"subsystem:scheduler": {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
`OutputActivityTracker` (the per-session change-detector that feeds
|
|
9
|
+
`ActiveWorkSilenceSentinel`) now hashes a **spinner-immune** view of the captured
|
|
10
|
+
pane. The host's "working" spinner (e.g. Claude's `✻ Sautéed for 26m 16s ·
|
|
11
|
+
(esc to interrupt)`) ticks its elapsed-time counter every second, so the previous
|
|
12
|
+
raw hash changed on every poll even when the turn had produced no real output for
|
|
13
|
+
many minutes. That kept the session's `lastChangeAt` perpetually fresh and blinded
|
|
14
|
+
the silence sentinel to a stalled-but-spinning turn — the cause of a ~26-minute
|
|
15
|
+
unrecovered API-stall where a wedged session looked fully alive. A new
|
|
16
|
+
`stripVolatileStatus` removes the volatile status region (the rotating glyph, the
|
|
17
|
+
elapsed-time and token/context counters, and the `esc to interrupt` footer) before
|
|
18
|
+
hashing, so only REAL scrollback changes refresh the activity timestamp. A
|
|
19
|
+
stalled-but-spinning turn now correctly accrues idle time and becomes eligible for
|
|
20
|
+
the sentinel's gentle nudge.
|
|
21
|
+
|
|
22
|
+
This is safe: the silence sentinel's nudge is a non-destructive `Enter` keystroke,
|
|
23
|
+
so a false-positive on a genuinely long turn is harmless. The only destructive
|
|
24
|
+
recovery (Ctrl-C) lives in `SocketDisconnectSentinel`, which fires only on a
|
|
25
|
+
positive connection-error marker — unchanged.
|
|
26
|
+
|
|
27
|
+
## What to Tell Your User
|
|
28
|
+
|
|
29
|
+
- **Better stuck-session detection**: "If one of my sessions ever freezes mid-task
|
|
30
|
+
while still showing a 'working' spinner, I can now actually notice it and try to
|
|
31
|
+
wake it, instead of being fooled into thinking it's busy because the spinner's
|
|
32
|
+
clock keeps ticking. It's a gentle nudge only — it never interrupts real work."
|
|
33
|
+
|
|
34
|
+
## Summary of New Capabilities
|
|
35
|
+
|
|
36
|
+
| Capability | How to Use |
|
|
37
|
+
|-----------|-----------|
|
|
38
|
+
| Spinner-immune stall detection | Automatic (ActiveWorkSilenceSentinel) |
|
|
39
|
+
|
|
40
|
+
## Evidence
|
|
41
|
+
|
|
42
|
+
- **Live before:** 2026-06-02, a session hung ~26 min on an Anthropic API socket
|
|
43
|
+
drop while showing `Sautéed for 26m 16s`; `ActiveWorkSilenceSentinel` never fired
|
|
44
|
+
(it flagged a *different* session idle at a static prompt in the same window), and
|
|
45
|
+
the turn only re-engaged when an inbound user message arrived. Confirmed in
|
|
46
|
+
`logs/server.log` + `logs/sentinel-events.jsonl`.
|
|
47
|
+
- **After (code path):** `tests/unit/spinner-immune-liveness.test.ts` drives
|
|
48
|
+
`OutputActivityTracker` with ticking-spinner-only frames and asserts `lastOutputAt`
|
|
49
|
+
HOLDS across them (idle accrues) while genuine new output still advances it; plus
|
|
50
|
+
`stripVolatileStatus` unit cases for Claude/codex spinner shapes and a guard that
|
|
51
|
+
benign content (e.g. "completed in 5s") is not over-stripped.
|
|
52
|
+
- **Cross-model reviewed** by the codex-based agent (task #63): confirmed the silence
|
|
53
|
+
nudge is `Enter`-only (non-destructive), which is why the spinner-immune hash alone
|
|
54
|
+
is sufficient and safe.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Side-Effects Review — spinner-immune liveness signal
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `spinner-immune-liveness`
|
|
4
|
+
**Date:** `2026-06-02`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `instar-codey (codex) — cross-model review completed; verdict incorporated`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
`src/monitoring/sentinelWiring.ts`: `OutputActivityTracker.snapshot()` now hashes
|
|
11
|
+
`stripVolatileStatus(output, framework)` instead of the raw pane. `stripVolatileStatus`
|
|
12
|
+
strips the host's animated working-status region (Braille spinner glyphs, the
|
|
13
|
+
`Nm Ns` / `(Ns` elapsed timers, token/context counters, and the `esc to interrupt`
|
|
14
|
+
footer line) so only real scrollback changes refresh `lastChangeAt`. Fixes the
|
|
15
|
+
silence sentinel being permanently blinded by the spinner's ticking clock.
|
|
16
|
+
|
|
17
|
+
## Decision-point inventory
|
|
18
|
+
|
|
19
|
+
- `OutputActivityTracker: did this frame change?` (sentinelWiring.ts:~215) — **modify**
|
|
20
|
+
— the hashed input is now spinner-normalized. The downstream "observed-change
|
|
21
|
+
requirement" + `looksActivelyWorking` + silence-threshold logic are unchanged.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 1. Over-block
|
|
26
|
+
|
|
27
|
+
**No block/allow surface — over-block not applicable.** The change cannot reject or
|
|
28
|
+
block anything. The only effect is that the silence sentinel correctly recognizes a
|
|
29
|
+
stalled-but-spinning turn as idle (rather than perpetually "active") and may issue
|
|
30
|
+
its existing non-destructive `Enter` nudge.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 2. Under-block
|
|
35
|
+
|
|
36
|
+
**What does it still miss?** It strips a conservative, anchored set of volatile
|
|
37
|
+
tokens; an exotic future spinner format could still leak a changing token into the
|
|
38
|
+
hash (degrading gracefully back to the old "always active" behavior for that host —
|
|
39
|
+
no worse than today). It does not change the silence THRESHOLD; a true stall is
|
|
40
|
+
detected at the existing ~16-min mark.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 3. Level-of-abstraction fit
|
|
45
|
+
|
|
46
|
+
Correct layer — a normalization at the change-detector's input boundary, reusing the
|
|
47
|
+
existing per-framework `getActivitySignal` patterns rather than inventing new ones.
|
|
48
|
+
It feeds the existing smart silence sentinel; it does not add a parallel detector or
|
|
49
|
+
hold any authority.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 4. Signal vs authority compliance
|
|
54
|
+
|
|
55
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
56
|
+
|
|
57
|
+
- [x] No — this change produces a signal (a fresher/stale activity timestamp)
|
|
58
|
+
consumed by the existing `ActiveWorkSilenceSentinel`, which owns the (non-destructive)
|
|
59
|
+
recovery decision.
|
|
60
|
+
|
|
61
|
+
The cross-model review (Codey) specifically affirmed the signal-vs-authority shape:
|
|
62
|
+
absence-of-activity must NOT authorize destructive recovery; here it only authorizes a
|
|
63
|
+
non-destructive `Enter` nudge, and the destructive Ctrl-C path (SocketDisconnectSentinel)
|
|
64
|
+
remains gated on a POSITIVE error-string marker. No change weakens that.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 5. Interactions
|
|
69
|
+
|
|
70
|
+
- **Shadowing:** none — same single hash site; downstream logic unchanged.
|
|
71
|
+
- **Double-fire:** none — `SocketDisconnectSentinel` (error-string → Ctrl-C) and
|
|
72
|
+
`ActiveWorkSilenceSentinel` (silence → Enter) remain independent; this only un-blinds
|
|
73
|
+
the latter.
|
|
74
|
+
- **Races:** none — pure synchronous string transform inside the existing snapshot tick.
|
|
75
|
+
- **Feedback loops:** the Enter nudge could, on a genuinely-long generation, submit a
|
|
76
|
+
stray blank line; the pane is mid-turn (spinner present) so it is queued/ignored, not
|
|
77
|
+
destructive. Verified the nudge is `sendKey(session, 'Enter')` (sentinelWiring.ts:255),
|
|
78
|
+
not Ctrl-C.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 6. External surfaces
|
|
83
|
+
|
|
84
|
+
- Persistent state: none.
|
|
85
|
+
- External systems: none.
|
|
86
|
+
- Behavior visible to operators: a stalled-but-spinning session now appears in
|
|
87
|
+
`logs/sentinel-events.jsonl` as detected/nudged where before it was invisible. The
|
|
88
|
+
Telegram escalation default (off) is unchanged.
|
|
89
|
+
- Runtime: one extra string transform per session per silence tick — negligible.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 7. Rollback cost
|
|
94
|
+
|
|
95
|
+
Pure code change — revert `stripVolatileStatus` + restore `cheapHash(output)`, ship a
|
|
96
|
+
patch. No persistent state, no migration, no user-visible regression (it would simply
|
|
97
|
+
return to the prior "spinner fools the detector" behavior).
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Conclusion
|
|
102
|
+
|
|
103
|
+
The cross-model review materially improved this change: it began as a multi-state
|
|
104
|
+
process-activity gate to protect long generations from a *destructive* Ctrl-C, but the
|
|
105
|
+
reviewer's grounded catch — the silence nudge is `Enter`-only, not Ctrl-C — collapsed it
|
|
106
|
+
to a single safe normalization, with the destructive path already correctly gated on a
|
|
107
|
+
positive error marker elsewhere. Clear to ship as a Tier-1 monitoring reliability fix.
|
|
108
|
+
|
|
109
|
+
## Second-pass review (if required)
|
|
110
|
+
|
|
111
|
+
**Reviewer:** instar-codey (codex)
|
|
112
|
+
**Independent read: concur (after the implementation correction).** The reviewer's
|
|
113
|
+
verdict drove the final design: do not let absence-of-activity authorize destructive
|
|
114
|
+
recovery (already satisfied — the silence path is non-destructive `Enter`; Ctrl-C stays
|
|
115
|
+
behind the SocketDisconnectSentinel error marker). No residual concern on the shipped
|
|
116
|
+
shape.
|
|
117
|
+
|
|
118
|
+
## Evidence pointers
|
|
119
|
+
|
|
120
|
+
- `tests/unit/spinner-immune-liveness.test.ts` — 7 tests (normalizer + tracker behavior).
|
|
121
|
+
- `src/monitoring/sentinelWiring.ts:255` — nudge is `sendKey(session, 'Enter')`.
|
|
122
|
+
- Origin incident: `logs/server.log` + `logs/sentinel-events.jsonl`, 2026-06-02 26-min stall.
|