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.
Files changed (39) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +52 -0
  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 +9 -0
  6. package/dist/core/PostUpdateMigrator.js.map +1 -1
  7. package/dist/core/SessionManager.d.ts +9 -0
  8. package/dist/core/SessionManager.d.ts.map +1 -1
  9. package/dist/core/SessionManager.js +31 -0
  10. package/dist/core/SessionManager.js.map +1 -1
  11. package/dist/core/paneTail.d.ts +9 -0
  12. package/dist/core/paneTail.d.ts.map +1 -1
  13. package/dist/core/paneTail.js +12 -0
  14. package/dist/core/paneTail.js.map +1 -1
  15. package/dist/core/types.d.ts +11 -0
  16. package/dist/core/types.d.ts.map +1 -1
  17. package/dist/core/types.js.map +1 -1
  18. package/dist/monitoring/PermissionPromptAutoResolver.d.ts +215 -0
  19. package/dist/monitoring/PermissionPromptAutoResolver.d.ts.map +1 -0
  20. package/dist/monitoring/PermissionPromptAutoResolver.js +475 -0
  21. package/dist/monitoring/PermissionPromptAutoResolver.js.map +1 -0
  22. package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
  23. package/dist/monitoring/PresenceProxy.js +18 -0
  24. package/dist/monitoring/PresenceProxy.js.map +1 -1
  25. package/dist/monitoring/StuckSignatureClassifier.d.ts +1 -1
  26. package/dist/monitoring/StuckSignatureClassifier.d.ts.map +1 -1
  27. package/dist/monitoring/StuckSignatureClassifier.js +24 -0
  28. package/dist/monitoring/StuckSignatureClassifier.js.map +1 -1
  29. package/dist/monitoring/guardManifest.d.ts.map +1 -1
  30. package/dist/monitoring/guardManifest.js +15 -0
  31. package/dist/monitoring/guardManifest.js.map +1 -1
  32. package/dist/monitoring/guardPosture.d.ts.map +1 -1
  33. package/dist/monitoring/guardPosture.js +19 -0
  34. package/dist/monitoring/guardPosture.js.map +1 -1
  35. package/package.json +1 -1
  36. package/scripts/lint-guard-manifest.js +1 -0
  37. package/src/data/builtin-manifest.json +20 -20
  38. package/upgrades/1.3.666.md +131 -0
  39. package/upgrades/1.3.665.md +0 -68
@@ -0,0 +1,215 @@
1
+ /**
2
+ * PermissionPromptAutoResolver — the always-on, unconditional SAFETY FLOOR that
3
+ * keeps Instar from being silently wedged on an agent-framework approval prompt.
4
+ *
5
+ * Spec: docs/specs/framework-permission-prompt-robustness.md
6
+ * Convergence: docs/specs/reports/framework-permission-prompt-robustness-convergence.md
7
+ *
8
+ * The bug it closes (Claude Code 2.1.176–177): a hardcoded Bash safety classifier
9
+ * pauses a session on a terminal Y/N approval prompt (e.g. "Compound command
10
+ * contains cd with output redirection — manual approval required … Do you want to
11
+ * proceed? ❯ 1. Yes / 2. No"). It runs BEFORE all permission rules and hooks, so
12
+ * `--dangerously-skip-permissions` cannot pre-answer it. A remote agent (Telegram /
13
+ * dashboard) cannot press a terminal key, so the session freezes forever while still
14
+ * LOOKING busy — a third liveness state every existing watcher mis-reads.
15
+ *
16
+ * The operator directive that governs the design: a low-level command/tool approval
17
+ * prompt is NEVER a user decision — the agent runs operator-owned sessions with full
18
+ * machine access. So a prompt-parked session is a DEFECT to auto-clear and detect,
19
+ * never a "waiting for operator" state.
20
+ *
21
+ * TWO PURE DETECTORS + a stateful driver:
22
+ * - Layer 2 (`detectApprovalPrompt`, LOAD-BEARING): matches a registered approval
23
+ * signature with the ❯ selector cursor sitting on an approve option, at the
24
+ * genuine bottom of a non-generating pane → the driver sends `Enter` (confirm the
25
+ * highlighted default). Bar-raising MITIGATION, not closure — a text capture
26
+ * cannot perfectly tell TUI chrome from displayed content, so the residual is
27
+ * bounded by Enter-only + re-capture-before-send + a per-episode attempt cap + a
28
+ * terminal defect.
29
+ * - Layer 3 (`detectPersistingMenu`, prose-AGNOSTIC observability): matches ANY
30
+ * persisting glyph-led numbered menu the resolver did NOT auto-clear (❯-not-on-
31
+ * approve, prose-drift, an open non-approval picker) → after a persistence
32
+ * threshold it raises the SAME terminal defect. This is what makes "never
33
+ * silently stranded" TRUE for the cases Layer 2 declines, and doubles as the
34
+ * prompt-string drift detector.
35
+ *
36
+ * Signal-vs-authority: the detectors are pure. The ONLY actuation is `sendKey(…,
37
+ * 'Enter')` (a benign empty submit on a false match) and `raiseDefect` (an Attention
38
+ * item). No new blocking authority. All I/O is injected (DI), so the detectors +
39
+ * state machine are fully unit-testable.
40
+ *
41
+ * Privacy: the audit logs only the STATIC registry pattern NAMES and a one-way
42
+ * fingerprint — never the raw tail. Layer 3's dedup key is a one-way digest of the
43
+ * option labels — the labels themselves are never logged.
44
+ */
45
+ /** Per-episode consecutive un-cleared sends before Layer 2 declares Terminal. */
46
+ export declare const MAX_ATTEMPTS = 3;
47
+ /** Layer-3 consecutive matched ticks before the persisting-menu Terminal defect. */
48
+ export declare const LAYER3_PERSIST_TICKS = 4;
49
+ /** Per-entry staleness TTL — neither state map can grow with uptime (Bounded Accumulation). */
50
+ export declare const STATE_TTL_MS: number;
51
+ /**
52
+ * One non-empty line of a captured tail, split into the lead-STRIPPED content
53
+ * (`text`, via `stripLineLead`) and the separated leading run (`leadGlyphs`, via
54
+ * `leadGlyphsOf`). `text` lets anchored regexes match the real first token; the
55
+ * separated `leadGlyphs` lets the detector test for the ❯ selector cursor
56
+ * specifically (not merely "some glyph", which `wasGlyphLed` answers).
57
+ */
58
+ export interface PaneTailLine {
59
+ text: string;
60
+ leadGlyphs: string;
61
+ }
62
+ /**
63
+ * Split a raw tmux tail capture into `PaneTailLine`s — dropping whitespace-only
64
+ * lines (like `liveTail`), mapping each remaining RAW line → its lead-stripped
65
+ * `text` + its `leadGlyphs`. Pure.
66
+ */
67
+ export declare function toPaneTailLines(rawTail: string): PaneTailLine[];
68
+ /** A single registered prose pattern carrying its stable symbolic name. */
69
+ export interface ProsePattern {
70
+ name: string;
71
+ pattern: RegExp;
72
+ }
73
+ /** The registered signature for one framework. */
74
+ export interface ApprovalSignature {
75
+ prosePatterns: ProsePattern[];
76
+ /** Anchored at the start of the post-`N.` option label — an APPROVE verb. */
77
+ approveLabels: RegExp;
78
+ }
79
+ /**
80
+ * Approval-prompt signatures, keyed by framework. Only `claude-code` is VERIFIED at
81
+ * ship; codex/gemini entries are deliberately OMITTED — off until a live prompt is
82
+ * characterized (Decision 10). The resolver tries EVERY registered signature each
83
+ * tick (it does not depend on a session's framework field, undefined on legacy
84
+ * records); a Claude prompt won't match a Codex pattern, so trying all is safe.
85
+ *
86
+ * `matchedPatternNames` (what the audit + fingerprint use) are these STATIC `name`s —
87
+ * never matched tail text — so neither artifact can ever carry pane-derived bytes.
88
+ */
89
+ export declare const APPROVAL_PROMPT_SIGNATURES: Record<string, ApprovalSignature>;
90
+ /** A Layer-2 match — an answerable, focused approval menu. */
91
+ export interface ApprovalMatch {
92
+ framework: string;
93
+ /** The STATIC registry names that matched, sorted. Never tail text. */
94
+ matchedPatternNames: string[];
95
+ /** The only key the resolver ever sends. */
96
+ approveKey: 'Enter';
97
+ /** hash(framework + sorted matchedPatternNames) — invariant across redraws,
98
+ * carries NO tail-derived bytes. */
99
+ stableFingerprint: string;
100
+ }
101
+ /** A Layer-3 match — a persisting glyph-led menu the resolver will NOT auto-answer. */
102
+ export interface MenuMatch {
103
+ /** The sorted texts of the numbered option lines (consumed ONLY as hash input). */
104
+ optionLabels: string[];
105
+ }
106
+ /**
107
+ * Pure Layer-2 detector. Returns a match ONLY when ALL hold:
108
+ * 1. ≥2 DISTINCT named prose patterns from the framework's registry matched;
109
+ * 2. a line whose `leadGlyphs` contains ❯ AND whose `text` is `N.` followed by an
110
+ * approve label (the selector cursor is ON an approve option);
111
+ * 3. the menu is at the genuine bottom (no idle input box below, option line within
112
+ * the bottom window) AND the session is not generating.
113
+ *
114
+ * Honest residual (spec security#1): a tmux text capture cannot perfectly prove a
115
+ * `❯ 1. Yes` is TUI chrome vs displayed content. Requirements 1–3 substantially raise
116
+ * the bar; the residual is bounded by the Enter-only keystroke + re-capture + attempt
117
+ * cap + Terminal defect in the driver, never by this detector pretending closure.
118
+ */
119
+ export declare function detectApprovalPrompt(tail: PaneTailLine[], framework: string, isGenerating: boolean): ApprovalMatch | null;
120
+ /**
121
+ * Pure Layer-3 detector. Prose-agnostic by design (so it catches drift): matches
122
+ * purely on STRUCTURE — (i) a glyph-led numbered option line, (ii) a generic
123
+ * blocking affordance (`Esc to cancel` / `Do you want to proceed` / ≥2 numbered
124
+ * options), (iii) genuine bottom, (iv) not generating. Deliberately matches the
125
+ * cases Layer 2 declines (❯ not on an approve option, prose-drift) AS WELL AS a
126
+ * genuinely open non-approval picker (an accepted, benign surface — something IS
127
+ * waiting for input the agent cannot self-answer, worth one notice).
128
+ */
129
+ export declare function detectPersistingMenu(tail: PaneTailLine[], isGenerating: boolean): MenuMatch | null;
130
+ /** A Terminal defect raised to the Attention surface (the wiring owns dedup). */
131
+ export interface ResolverDefect {
132
+ sessionName: string;
133
+ layer: 'layer2' | 'layer3';
134
+ /** sessionName + fingerprint (Layer 2) OR sessionName + menuStructureKey (Layer 3). */
135
+ dedupKey: string;
136
+ fingerprint?: string;
137
+ menuStructureKey?: string;
138
+ /** STATIC names only (Layer 2). */
139
+ matchedPatternNames?: string[];
140
+ reason: string;
141
+ }
142
+ /** The outcome of one Layer-2 action, recorded in the audit. */
143
+ export type ResolverOutcome = 'answered' | 'retried' | 'cleared' | 'persisted-terminal' | 'send-failed' | 'race-aborted';
144
+ /** One audit row. NEVER carries raw tail — only the static matched-pattern names. */
145
+ export interface ResolverAuditRow {
146
+ ts: number;
147
+ sessionName: string;
148
+ framework: string;
149
+ matchedPatternNames: string[];
150
+ keySent: 'Enter' | null;
151
+ fingerprint: string;
152
+ attempt: number;
153
+ outcome: ResolverOutcome;
154
+ }
155
+ export interface PermissionPromptResolverDeps {
156
+ /** Send a keystroke to the session's pane. Returns/resolves false on failure. */
157
+ sendKey: (session: string, key: string) => boolean | Promise<boolean>;
158
+ /** Re-capture the live tail for the race-guard. Null/throw → race-aborted. */
159
+ reCaptureTail: (session: string) => Promise<PaneTailLine[] | null>;
160
+ /** Is the session generating right now? (e.g. looksGeneratingNow on the tail.) */
161
+ isGenerating: (rawOrTail: string) => boolean;
162
+ /** Raise the Terminal Attention defect (the wiring dedups + age-escalates). */
163
+ raiseDefect: (args: ResolverDefect) => void;
164
+ /** Append one audit row (size-bounded JSONL in the wiring). Must not throw up. */
165
+ appendAudit: (row: ResolverAuditRow) => void;
166
+ /** Clock (tests). */
167
+ now: () => number;
168
+ /** The emergency off-switch (absent ⇒ false ⇒ floor ON). */
169
+ emergencyDisabled: () => boolean;
170
+ }
171
+ export declare class PermissionPromptAutoResolver {
172
+ private readonly deps;
173
+ /** Layer-2 episode state, keyed (session, stableFingerprint). */
174
+ private readonly episodes;
175
+ /** Layer-3 persistence state, keyed (session, menuStructureKey). */
176
+ private readonly persistMenus;
177
+ /** Last evaluate/sweep wall-clock — the GuardRegistry liveness read. */
178
+ private lastTickAt;
179
+ constructor(deps: PermissionPromptResolverDeps);
180
+ /**
181
+ * Per-candidate tick logic for one running session. Captures nothing of its own —
182
+ * the caller passes the already-in-hand fuller tail. Layer 2 owns a tick it
183
+ * matched (returns before Layer 3), so the two can never double-raise one wedge.
184
+ */
185
+ evaluate(session: string, fullTail: PaneTailLine[]): Promise<void>;
186
+ /**
187
+ * Evict every state entry for `session` EXCEPT the one active this tick (the
188
+ * reset-on-clear rule). An evicted Layer-2 entry that had un-cleared sends and was
189
+ * not already terminal audits `cleared` (the episode's prompt was answered/gone).
190
+ */
191
+ private reconcileSession;
192
+ private handleLayer2;
193
+ private handleLayer3;
194
+ /**
195
+ * Evict BOTH maps' entries for sessions no longer running, and any entry older
196
+ * than the per-entry TTL (stale lastTick). Neither map can grow with uptime.
197
+ * Called each tick.
198
+ */
199
+ sweep(runningSessions: Set<string>): void;
200
+ /** Cheap, no-I/O runtime liveness read for the GuardRegistry (GET /guards). */
201
+ guardStatus(): {
202
+ enabled: boolean;
203
+ lastTickAt: number;
204
+ };
205
+ /** Current live state-map sizes (both are provably bounded by the eviction triple). */
206
+ stateSizes(): {
207
+ episodes: number;
208
+ persistMenus: number;
209
+ };
210
+ private l2Key;
211
+ private l3Key;
212
+ private menuStructureKey;
213
+ private audit;
214
+ }
215
+ //# sourceMappingURL=PermissionPromptAutoResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PermissionPromptAutoResolver.d.ts","sourceRoot":"","sources":["../../src/monitoring/PermissionPromptAutoResolver.ts"],"names":[],"mappings":"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"}