instar 1.3.665 → 1.3.666
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/server.d.ts.map +1 -1
- package/dist/commands/server.js +52 -0
- package/dist/commands/server.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +9 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionManager.d.ts +9 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +31 -0
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/paneTail.d.ts +9 -0
- package/dist/core/paneTail.d.ts.map +1 -1
- package/dist/core/paneTail.js +12 -0
- package/dist/core/paneTail.js.map +1 -1
- package/dist/core/types.d.ts +11 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/PermissionPromptAutoResolver.d.ts +215 -0
- package/dist/monitoring/PermissionPromptAutoResolver.d.ts.map +1 -0
- package/dist/monitoring/PermissionPromptAutoResolver.js +475 -0
- package/dist/monitoring/PermissionPromptAutoResolver.js.map +1 -0
- package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
- package/dist/monitoring/PresenceProxy.js +18 -0
- package/dist/monitoring/PresenceProxy.js.map +1 -1
- package/dist/monitoring/StuckSignatureClassifier.d.ts +1 -1
- package/dist/monitoring/StuckSignatureClassifier.d.ts.map +1 -1
- package/dist/monitoring/StuckSignatureClassifier.js +24 -0
- package/dist/monitoring/StuckSignatureClassifier.js.map +1 -1
- package/dist/monitoring/guardManifest.d.ts.map +1 -1
- package/dist/monitoring/guardManifest.js +15 -0
- package/dist/monitoring/guardManifest.js.map +1 -1
- package/dist/monitoring/guardPosture.d.ts.map +1 -1
- package/dist/monitoring/guardPosture.js +19 -0
- package/dist/monitoring/guardPosture.js.map +1 -1
- package/package.json +1 -1
- package/scripts/lint-guard-manifest.js +1 -0
- package/src/data/builtin-manifest.json +20 -20
- package/upgrades/1.3.666.md +131 -0
- package/upgrades/1.3.665.md +0 -68
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-06-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-06-25T23:12:52.494Z",
|
|
5
|
+
"instarVersion": "1.3.666",
|
|
6
6
|
"entryCount": 202,
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
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": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
150
150
|
"since": "2025-01-01"
|
|
151
151
|
},
|
|
152
152
|
"job:health-check": {
|
|
@@ -1538,7 +1538,7 @@
|
|
|
1538
1538
|
"type": "subsystem",
|
|
1539
1539
|
"domain": "sessions",
|
|
1540
1540
|
"sourcePath": "src/core/SessionManager.ts",
|
|
1541
|
-
"contentHash": "
|
|
1541
|
+
"contentHash": "07c12341d721732f00a07e617140a0b4c6a3ad89d0c450c78a79f052d835be1e",
|
|
1542
1542
|
"since": "2025-01-01"
|
|
1543
1543
|
},
|
|
1544
1544
|
"subsystem:auto-updater": {
|
|
@@ -1562,7 +1562,7 @@
|
|
|
1562
1562
|
"type": "subsystem",
|
|
1563
1563
|
"domain": "updates",
|
|
1564
1564
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
1565
|
-
"contentHash": "
|
|
1565
|
+
"contentHash": "3f5b94f3892478477e6048a95a3b4b565c4b4050b803ad777356843b249c8889",
|
|
1566
1566
|
"since": "2025-01-01"
|
|
1567
1567
|
},
|
|
1568
1568
|
"subsystem:scheduler": {
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
An Instar session could be silently, permanently wedged by an agent-framework approval
|
|
9
|
+
prompt it cannot answer. Claude Code 2.1.176-177 added a hardcoded Bash safety prompt —
|
|
10
|
+
`cd <dir> && <cmd>` combined with a redirect/pipe pops "Do you want to proceed? ❯ 1. Yes
|
|
11
|
+
/ 2. No / Esc to cancel" — that runs BEFORE all permission rules and PermissionRequest
|
|
12
|
+
hooks, so `--dangerously-skip-permissions` and `permissions.allow` cannot suppress it.
|
|
13
|
+
A remote-driven session (Telegram/dashboard) cannot press a terminal key, so it freezes
|
|
14
|
+
while still *looking* busy (PresenceProxy could even report "actively working"). The
|
|
15
|
+
empirically-confirmed reason it bit the fleet: the existing PromptGate/AutoApprover
|
|
16
|
+
pipeline was persisted `enabled:false` on deployed agents (a stale-`false` config wins
|
|
17
|
+
over a newer `true` default), so nothing answered the prompt.
|
|
18
|
+
|
|
19
|
+
- **New `src/monitoring/PermissionPromptAutoResolver.ts`** — an always-on, deterministic,
|
|
20
|
+
zero-LLM safety floor driven once per monitoring tick. It detects a live, focused
|
|
21
|
+
approval menu in a session's tmux tail and sends the approve keystroke itself.
|
|
22
|
+
- **Layer 2 (auto-answer):** requires ≥2 distinct registered prose patterns AND a live
|
|
23
|
+
glyph-led `❯`-cursor-on-an-approve-option line at the genuine bottom of the tail
|
|
24
|
+
while not generating; sends **`Enter`** only (confirm the highlighted "Yes"), with a
|
|
25
|
+
re-capture-before-send check. Because a text capture cannot *perfectly* distinguish a
|
|
26
|
+
real TUI selector from displayed content containing the same characters, this is
|
|
27
|
+
bar-raising mitigation (stated honestly), bounded by Enter-only (a false match is a
|
|
28
|
+
benign empty submit), a per-episode `MAX_ATTEMPTS=3` (reset-on-clear so distinct
|
|
29
|
+
prompts are independent), and a terminal defect.
|
|
30
|
+
- **Layer 3 (broad detector):** a prose-agnostic `detectPersistingMenu` surfaces ANY
|
|
31
|
+
persisting glyph-led menu the auto-answer declines (cursor-not-on-approve, or a future
|
|
32
|
+
prompt whose wording drifts) as a single deduped Attention defect — so nothing is ever
|
|
33
|
+
silently stranded, and it doubles as the prompt-string drift detector.
|
|
34
|
+
- **`src/core/paneTail.ts`** gains a pure `leadGlyphsOf(line)` helper so the detector can
|
|
35
|
+
test for the `❯` selector glyph (U+276F) specifically.
|
|
36
|
+
- **`StuckSignatureClassifier`** gains an `approval-prompt-waiting` kind; **`PresenceProxy`**
|
|
37
|
+
never surfaces it as a user message (the sole user-facing surface is the terminal
|
|
38
|
+
defect), killing the false "actively working" report for a prompt-wedged session.
|
|
39
|
+
- **The floor is unconditional — no persisted `enabled:true` to rot to `false`** (the
|
|
40
|
+
exact trap that caused the bug). The only opt-out is `monitoring.permissionPromptAutoResolver.emergencyDisable`
|
|
41
|
+
(absent ⇒ on). A computed guard-posture key (`guardPosture.ts`) + a runtime
|
|
42
|
+
`guardStatus()` + a `GUARD_MANIFEST` entry make a disabled floor a visible incident in
|
|
43
|
+
`GET /guards`.
|
|
44
|
+
- Existing wedged sessions recover automatically: the server restart that deploys the
|
|
45
|
+
update restarts the monitor loop, which auto-clears any session currently parked on the
|
|
46
|
+
prompt. No new setting, no manual step.
|
|
47
|
+
|
|
48
|
+
The resolver answers a UI-flow prompt only; it never widens what commands are allowed
|
|
49
|
+
(the destructive `dangerous-command-guard` denylist remains an independent guard). The
|
|
50
|
+
auto-approve is accepted under the operator full-machine-access trust model. Converged
|
|
51
|
+
through 6 spec-review rounds (6 internal reviewers + codex/gemini cross-model).
|
|
52
|
+
|
|
53
|
+
CMT-1785: the idle-error detector that decides "did this paused session stall on a transient API
|
|
54
|
+
error (nudge it) or stop normally (leave it)?" is migrated from a brittle bare-substring scan to a
|
|
55
|
+
tail-gated, frame-discriminated SIGNAL.
|
|
56
|
+
|
|
57
|
+
- New pure modules `src/core/paneTail.ts` (shared `liveTail`/`stripLineLead`/`wasGlyphLed` — ONE
|
|
58
|
+
definition of "the live tail", extracted so it is no longer copied per consumer) and
|
|
59
|
+
`src/core/IdleErrorClassifier.ts` (`classifyIdleError`).
|
|
60
|
+
- The old gate `TERMINAL_ERROR_PATTERNS.some(p => recentOutput.includes(p))` (a bare `.includes()`
|
|
61
|
+
over the whole capture) is replaced by `classifyIdleError`, which fires only when a terminal-error
|
|
62
|
+
token sits in the live tail (last 20 non-empty lines) on a Claude-EMITTED error frame — a two-tier
|
|
63
|
+
begins-with rule: **Tier A** the line begins with `API Error:`; **Tier B** the line is glyph-led
|
|
64
|
+
(`⏺`/`⎿`/…) and begins with one of the 11 patterns. The match set is a strict subset of the old
|
|
65
|
+
buffer-wide match, so the change can only SUPPRESS spurious fires, never add one.
|
|
66
|
+
- The idle-error capture is widened 30→45 rows (`RATE_LIMIT_SETTLED_CAPTURE_LINES`): Claude Code's
|
|
67
|
+
input box + footer render 15-25 rows BELOW the error, so a 30-row capture could miss it entirely.
|
|
68
|
+
- `StuckSignatureClassifier` is migrated onto the shared `liveTail` (behavior-preserving via
|
|
69
|
+
`.join('\n')`; its existing test corpus is the characterization guard).
|
|
70
|
+
- A once-per-idle-episode structured record (`{event:'idle-error-classify', result:'fired'|'suppressed', …}`)
|
|
71
|
+
lands in `logs/server.log` so a wave of suppressions on genuine errors (the under-fire risk) is
|
|
72
|
+
observable. Cleared in both the re-arm block and `sessionComplete` (no leak on the death path).
|
|
73
|
+
|
|
74
|
+
The signal still feeds the existing `apiErrorAtIdle` → `rateLimitSentinel` recovery actuator and gains
|
|
75
|
+
no blocking authority (Signal vs Authority).
|
|
76
|
+
|
|
77
|
+
## What to Tell Your User
|
|
78
|
+
|
|
79
|
+
Your agent will no longer get silently stuck on a pop-up it can't answer. A recent
|
|
80
|
+
update to the coding tool added a safety pop-up ("Do you want to proceed? Yes / No") that
|
|
81
|
+
freezes the session, because nobody can press a key on it from your phone — and there's no
|
|
82
|
+
setting to turn it off. Now a small always-on layer answers that pop-up itself, only ever
|
|
83
|
+
pressing the harmless "Yes", and it's built into the code with no on/off switch that could
|
|
84
|
+
get stuck "off" (a stuck-off setting is exactly what caused the freeze). If it ever hits a
|
|
85
|
+
pop-up it genuinely can't clear (say a future version changes the wording), it stops and
|
|
86
|
+
sends you one "please take a look" notice instead of freezing silently. Nothing for you to
|
|
87
|
+
do; your agent just stays reachable.
|
|
88
|
+
|
|
89
|
+
Nothing you need to do. Under the hood, the agent got more reliable at telling a session that genuinely
|
|
90
|
+
stalled on an API error (which it nudges back to life) apart from one that's merely *showing* an old or
|
|
91
|
+
quoted error on screen. The old check was a blunt text search that sometimes kicked off a needless
|
|
92
|
+
recovery on a healthy session, and — more importantly — sometimes read too little of the screen and
|
|
93
|
+
missed a real stall. The new check looks at the live bottom of the screen, reads enough of it to clear
|
|
94
|
+
the input box, and only counts a line the tool actually emitted as an error. Net: fewer false recoveries
|
|
95
|
+
AND fewer missed real ones, so paused sessions get the right treatment faster. No new setting; behavior
|
|
96
|
+
is otherwise unchanged, and it's a one-line revert if ever needed.
|
|
97
|
+
|
|
98
|
+
## Summary of New Capabilities
|
|
99
|
+
|
|
100
|
+
- An always-on safety floor that auto-answers an un-answerable framework approval prompt,
|
|
101
|
+
so a remote-driven session is never silently wedged.
|
|
102
|
+
- Honest, bounded detection (live glyph-led menu, Enter-only, re-capture, attempt cap) +
|
|
103
|
+
a prose-agnostic backstop so a drifted/unrecognized prompt surfaces rather than strands.
|
|
104
|
+
- Visible in `GET /guards` (`on-confirmed`); an audit trail at
|
|
105
|
+
`logs/permission-prompt-resolver.jsonl` (matched-pattern names only, never raw tail);
|
|
106
|
+
emergency opt-out via `monitoring.permissionPromptAutoResolver.emergencyDisable`.
|
|
107
|
+
|
|
108
|
+
- `paneTail` + `IdleErrorClassifier` — a precise, tail-gated, frame-discriminated idle-error signal
|
|
109
|
+
replacing the bare buffer-wide substring scan; widened capture (45 rows) so the input-box chrome can
|
|
110
|
+
no longer hide a real error; structured once-per-episode observability of fired-vs-suppressed
|
|
111
|
+
decisions. Internal robustness improvement to session-stall recovery; no user-facing surface to
|
|
112
|
+
configure.
|
|
113
|
+
|
|
114
|
+
## Evidence
|
|
115
|
+
|
|
116
|
+
- `tests/unit/IdleErrorClassifier.test.ts` (28) — both sides of every boundary, pinned to REAL captured
|
|
117
|
+
render fixtures: fires on `⏺ API Error:` / ` ⎿ API Error:` / glyph-led network tokens / wrapped
|
|
118
|
+
errors; suppresses stale-scrollback, prose mentions, quoted source literals (the self-collision case),
|
|
119
|
+
a tool's own `Error: …ECONNREFUSED`; the 45-vs-30 input-box-chrome capture test; parametrized over all
|
|
120
|
+
11 patterns; bounded audit fields; paneTail helpers.
|
|
121
|
+
- `tests/integration/idle-error-classifier-production-wiring.test.ts` (7) — the REAL exported
|
|
122
|
+
`TERMINAL_ERROR_PATTERNS` produce correct decisions on real panes; the SessionManager call-site is
|
|
123
|
+
wired to the classifier, the 45-row capture, the dual once-per-episode clears, and the structured record.
|
|
124
|
+
- `tests/e2e/idle-error-classifier-lifecycle.test.ts` (2) — the real SessionManager constructs and the
|
|
125
|
+
`apiErrorAtIdle` recovery handoff is attachable; the production-pattern live decision is correct.
|
|
126
|
+
- `tests/unit/monitoring/StuckSignatureClassifier.test.ts` (13) — unchanged, the characterization guard
|
|
127
|
+
proving the shared-`liveTail` migration is behavior-preserving.
|
|
128
|
+
- `npm run build` + `tsc --noEmit` clean; full unit suite green.
|
|
129
|
+
- Driven by the converged + approved spec; convergence report at
|
|
130
|
+
`docs/specs/reports/idle-error-tailgate-corroboration-convergence.md` (4 rounds; the review caught a
|
|
131
|
+
CRITICAL under-fire-on-the-common-error-form flaw before any code).
|
package/upgrades/1.3.665.md
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
# Upgrade Guide — vNEXT
|
|
2
|
-
|
|
3
|
-
<!-- assembled-by: assemble-next-md -->
|
|
4
|
-
<!-- bump: patch -->
|
|
5
|
-
|
|
6
|
-
## What Changed
|
|
7
|
-
|
|
8
|
-
CMT-1785: the idle-error detector that decides "did this paused session stall on a transient API
|
|
9
|
-
error (nudge it) or stop normally (leave it)?" is migrated from a brittle bare-substring scan to a
|
|
10
|
-
tail-gated, frame-discriminated SIGNAL.
|
|
11
|
-
|
|
12
|
-
- New pure modules `src/core/paneTail.ts` (shared `liveTail`/`stripLineLead`/`wasGlyphLed` — ONE
|
|
13
|
-
definition of "the live tail", extracted so it is no longer copied per consumer) and
|
|
14
|
-
`src/core/IdleErrorClassifier.ts` (`classifyIdleError`).
|
|
15
|
-
- The old gate `TERMINAL_ERROR_PATTERNS.some(p => recentOutput.includes(p))` (a bare `.includes()`
|
|
16
|
-
over the whole capture) is replaced by `classifyIdleError`, which fires only when a terminal-error
|
|
17
|
-
token sits in the live tail (last 20 non-empty lines) on a Claude-EMITTED error frame — a two-tier
|
|
18
|
-
begins-with rule: **Tier A** the line begins with `API Error:`; **Tier B** the line is glyph-led
|
|
19
|
-
(`⏺`/`⎿`/…) and begins with one of the 11 patterns. The match set is a strict subset of the old
|
|
20
|
-
buffer-wide match, so the change can only SUPPRESS spurious fires, never add one.
|
|
21
|
-
- The idle-error capture is widened 30→45 rows (`RATE_LIMIT_SETTLED_CAPTURE_LINES`): Claude Code's
|
|
22
|
-
input box + footer render 15-25 rows BELOW the error, so a 30-row capture could miss it entirely.
|
|
23
|
-
- `StuckSignatureClassifier` is migrated onto the shared `liveTail` (behavior-preserving via
|
|
24
|
-
`.join('\n')`; its existing test corpus is the characterization guard).
|
|
25
|
-
- A once-per-idle-episode structured record (`{event:'idle-error-classify', result:'fired'|'suppressed', …}`)
|
|
26
|
-
lands in `logs/server.log` so a wave of suppressions on genuine errors (the under-fire risk) is
|
|
27
|
-
observable. Cleared in both the re-arm block and `sessionComplete` (no leak on the death path).
|
|
28
|
-
|
|
29
|
-
The signal still feeds the existing `apiErrorAtIdle` → `rateLimitSentinel` recovery actuator and gains
|
|
30
|
-
no blocking authority (Signal vs Authority).
|
|
31
|
-
|
|
32
|
-
## What to Tell Your User
|
|
33
|
-
|
|
34
|
-
Nothing you need to do. Under the hood, the agent got more reliable at telling a session that genuinely
|
|
35
|
-
stalled on an API error (which it nudges back to life) apart from one that's merely *showing* an old or
|
|
36
|
-
quoted error on screen. The old check was a blunt text search that sometimes kicked off a needless
|
|
37
|
-
recovery on a healthy session, and — more importantly — sometimes read too little of the screen and
|
|
38
|
-
missed a real stall. The new check looks at the live bottom of the screen, reads enough of it to clear
|
|
39
|
-
the input box, and only counts a line the tool actually emitted as an error. Net: fewer false recoveries
|
|
40
|
-
AND fewer missed real ones, so paused sessions get the right treatment faster. No new setting; behavior
|
|
41
|
-
is otherwise unchanged, and it's a one-line revert if ever needed.
|
|
42
|
-
|
|
43
|
-
## Summary of New Capabilities
|
|
44
|
-
|
|
45
|
-
- `paneTail` + `IdleErrorClassifier` — a precise, tail-gated, frame-discriminated idle-error signal
|
|
46
|
-
replacing the bare buffer-wide substring scan; widened capture (45 rows) so the input-box chrome can
|
|
47
|
-
no longer hide a real error; structured once-per-episode observability of fired-vs-suppressed
|
|
48
|
-
decisions. Internal robustness improvement to session-stall recovery; no user-facing surface to
|
|
49
|
-
configure.
|
|
50
|
-
|
|
51
|
-
## Evidence
|
|
52
|
-
|
|
53
|
-
- `tests/unit/IdleErrorClassifier.test.ts` (28) — both sides of every boundary, pinned to REAL captured
|
|
54
|
-
render fixtures: fires on `⏺ API Error:` / ` ⎿ API Error:` / glyph-led network tokens / wrapped
|
|
55
|
-
errors; suppresses stale-scrollback, prose mentions, quoted source literals (the self-collision case),
|
|
56
|
-
a tool's own `Error: …ECONNREFUSED`; the 45-vs-30 input-box-chrome capture test; parametrized over all
|
|
57
|
-
11 patterns; bounded audit fields; paneTail helpers.
|
|
58
|
-
- `tests/integration/idle-error-classifier-production-wiring.test.ts` (7) — the REAL exported
|
|
59
|
-
`TERMINAL_ERROR_PATTERNS` produce correct decisions on real panes; the SessionManager call-site is
|
|
60
|
-
wired to the classifier, the 45-row capture, the dual once-per-episode clears, and the structured record.
|
|
61
|
-
- `tests/e2e/idle-error-classifier-lifecycle.test.ts` (2) — the real SessionManager constructs and the
|
|
62
|
-
`apiErrorAtIdle` recovery handoff is attachable; the production-pattern live decision is correct.
|
|
63
|
-
- `tests/unit/monitoring/StuckSignatureClassifier.test.ts` (13) — unchanged, the characterization guard
|
|
64
|
-
proving the shared-`liveTail` migration is behavior-preserving.
|
|
65
|
-
- `npm run build` + `tsc --noEmit` clean; full unit suite green.
|
|
66
|
-
- Driven by the converged + approved spec; convergence report at
|
|
67
|
-
`docs/specs/reports/idle-error-tailgate-corroboration-convergence.md` (4 rounds; the review caught a
|
|
68
|
-
CRITICAL under-fire-on-the-common-error-form flaw before any code).
|