greprag 5.44.2 → 5.45.0

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 (42) hide show
  1. package/dist/commands/collision-check.d.ts +113 -0
  2. package/dist/commands/collision-check.js +266 -0
  3. package/dist/commands/collision-check.js.map +1 -0
  4. package/dist/commands/coordinate-gate.d.ts +73 -0
  5. package/dist/commands/coordinate-gate.js +108 -0
  6. package/dist/commands/coordinate-gate.js.map +1 -0
  7. package/dist/commands/corpus/refresh.js +1 -1
  8. package/dist/commands/corpus/refresh.js.map +1 -1
  9. package/dist/commands/inbox-drain.d.ts +49 -0
  10. package/dist/commands/inbox-drain.js +163 -0
  11. package/dist/commands/inbox-drain.js.map +1 -0
  12. package/dist/commands/inbox-poll.d.ts +47 -0
  13. package/dist/commands/inbox-poll.js +261 -0
  14. package/dist/commands/inbox-poll.js.map +1 -0
  15. package/dist/commands/inbox-watch.js +3 -0
  16. package/dist/commands/inbox-watch.js.map +1 -1
  17. package/dist/commands/ingress-trigger.d.ts +67 -0
  18. package/dist/commands/ingress-trigger.js +103 -0
  19. package/dist/commands/ingress-trigger.js.map +1 -0
  20. package/dist/commands/init.js +41 -0
  21. package/dist/commands/init.js.map +1 -1
  22. package/dist/commands/poll-registry.d.ts +56 -0
  23. package/dist/commands/poll-registry.js +261 -0
  24. package/dist/commands/poll-registry.js.map +1 -0
  25. package/dist/commands/state-trigger.d.ts +66 -0
  26. package/dist/commands/state-trigger.js +305 -0
  27. package/dist/commands/state-trigger.js.map +1 -0
  28. package/dist/fix-trigger.d.ts +25 -5
  29. package/dist/fix-trigger.js +35 -11
  30. package/dist/fix-trigger.js.map +1 -1
  31. package/dist/guard.d.ts +13 -0
  32. package/dist/guard.js +58 -3
  33. package/dist/guard.js.map +1 -1
  34. package/dist/hook.js +226 -4
  35. package/dist/hook.js.map +1 -1
  36. package/dist/index.js +76 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/session-id.d.ts +12 -0
  39. package/dist/session-id.js +17 -0
  40. package/dist/session-id.js.map +1 -1
  41. package/package.json +1 -1
  42. package/skill/greprag/SKILL.md +4 -0
@@ -0,0 +1,261 @@
1
+ "use strict";
2
+ /** Poll registry — local pidfile tracking for the asyncRewake idle-liveness
3
+ * polls (`greprag inbox poll`), kept in its OWN namespace `~/.greprag/polls/`
4
+ * so it NEVER touches the Monitor watcher's `~/.greprag/watchers/` registry.
5
+ *
6
+ * WHY SEPARATE: `notify`'s `isLocallyArmed` reads the watcher registry to decide
7
+ * whether to inject the Monitor arm directive. If a poll registered there, the
8
+ * Monitor arm would go silent and the poll would REPLACE Monitor instead of
9
+ * running ALONGSIDE it. The two liveness mechanisms must be independent until a
10
+ * deliberate cutover. adr: adr/monitor-resilience.md
11
+ *
12
+ * The cleanup model mirrors the SHIPPED watcher count-cap (and reuses its pure
13
+ * `capSurplusVerdict`): per session, keep the K freshest LIVE polls, reap only
14
+ * the surplus, never below K. No death-judgment — a count + a floor — so it can
15
+ * never false-kill the live poll. Reload-orphans (if asyncRewake does not adopt
16
+ * a process across reload) are bounded here AND self-clean via the poll's own
17
+ * max-lifetime ceiling. */
18
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ var desc = Object.getOwnPropertyDescriptor(m, k);
21
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
22
+ desc = { enumerable: true, get: function() { return m[k]; } };
23
+ }
24
+ Object.defineProperty(o, k2, desc);
25
+ }) : (function(o, m, k, k2) {
26
+ if (k2 === undefined) k2 = k;
27
+ o[k2] = m[k];
28
+ }));
29
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
30
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
31
+ }) : function(o, v) {
32
+ o["default"] = v;
33
+ });
34
+ var __importStar = (this && this.__importStar) || (function () {
35
+ var ownKeys = function(o) {
36
+ ownKeys = Object.getOwnPropertyNames || function (o) {
37
+ var ar = [];
38
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
39
+ return ar;
40
+ };
41
+ return ownKeys(o);
42
+ };
43
+ return function (mod) {
44
+ if (mod && mod.__esModule) return mod;
45
+ var result = {};
46
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
47
+ __setModuleDefault(result, mod);
48
+ return result;
49
+ };
50
+ })();
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ exports.DEFAULT_POLL_CAP = void 0;
53
+ exports.registerPoll = registerPoll;
54
+ exports.deregisterPoll = deregisterPoll;
55
+ exports.isPollArmed = isPollArmed;
56
+ exports.listLivePolls = listLivePolls;
57
+ exports.readPollCursor = readPollCursor;
58
+ exports.writePollCursor = writePollCursor;
59
+ exports.clearPollCursor = clearPollCursor;
60
+ exports.reapSurplusPolls = reapSurplusPolls;
61
+ const fs = __importStar(require("fs"));
62
+ const path = __importStar(require("path"));
63
+ const child_process_1 = require("child_process");
64
+ const watcher_registry_1 = require("./watcher-registry");
65
+ const POLL_DIRNAME = 'polls';
66
+ /** Default per-session poll floor: keep this many freshest live polls, reap the
67
+ * surplus, never below it. K=2 = the live one + one margin (a reload overlap). */
68
+ exports.DEFAULT_POLL_CAP = 2;
69
+ function grepragHome() {
70
+ const home = process.env.HOME || process.env.USERPROFILE || '';
71
+ return home ? path.join(home, '.greprag') : null;
72
+ }
73
+ function pollsDir() {
74
+ const h = grepragHome();
75
+ return h ? path.join(h, POLL_DIRNAME) : null;
76
+ }
77
+ function pollfilePath(short) {
78
+ const dir = pollsDir();
79
+ return dir ? path.join(dir, `${short}.json`) : null;
80
+ }
81
+ /** True iff `pid` is a live process. `process.kill(pid, 0)` probes existence
82
+ * without signalling; EPERM = exists (another user), ESRCH = gone. */
83
+ function pidAlive(pid) {
84
+ if (!Number.isFinite(pid) || pid <= 0)
85
+ return false;
86
+ try {
87
+ process.kill(pid, 0);
88
+ return true;
89
+ }
90
+ catch (e) {
91
+ return e?.code === 'EPERM';
92
+ }
93
+ }
94
+ function readPollEntries(short) {
95
+ try {
96
+ const p = pollfilePath(short);
97
+ if (!p)
98
+ return [];
99
+ const parsed = JSON.parse(fs.readFileSync(p, 'utf-8'));
100
+ const arr = Array.isArray(parsed) ? parsed : [parsed];
101
+ return arr.filter((r) => !!r && typeof r.pid === 'number');
102
+ }
103
+ catch {
104
+ return [];
105
+ }
106
+ }
107
+ function writePollEntries(short, entries) {
108
+ try {
109
+ const dir = pollsDir();
110
+ if (!dir)
111
+ return;
112
+ fs.mkdirSync(dir, { recursive: true });
113
+ const p = path.join(dir, `${short}.json`);
114
+ if (entries.length === 0) {
115
+ fs.rmSync(p, { force: true });
116
+ return;
117
+ }
118
+ fs.writeFileSync(p, JSON.stringify(entries));
119
+ }
120
+ catch { /* best-effort — a failed write only means a re-arm, never a crash */ }
121
+ }
122
+ function allShorts() {
123
+ try {
124
+ const dir = pollsDir();
125
+ if (!dir || !fs.existsSync(dir))
126
+ return [];
127
+ return fs.readdirSync(dir).filter(f => f.endsWith('.json')).map(f => f.slice(0, -5));
128
+ }
129
+ catch {
130
+ return [];
131
+ }
132
+ }
133
+ /** APPEND this poll's entry (pruning dead entries as it goes). Best-effort. */
134
+ function registerPoll(short, pid) {
135
+ const entries = readPollEntries(short).filter(r => r.pid !== pid && pidAlive(r.pid));
136
+ entries.push({ short, pid, startedAt: Date.now() });
137
+ writePollEntries(short, entries);
138
+ }
139
+ /** Remove THIS poll's entry (on the poll's own exit — message-wake or ceiling). */
140
+ function deregisterPoll(short, pid) {
141
+ writePollEntries(short, readPollEntries(short).filter(r => r.pid !== pid));
142
+ }
143
+ /** Does this session have ANY live poll right now? The re-arm gate: a gated arm
144
+ * (PostToolUse / UserPromptSubmit) skips when true so per-tool fires don't pile
145
+ * up; SessionStart never gates (it always arms a fresh, reload-adopted poll).
146
+ * Sweeps dead entries as it reads. */
147
+ function isPollArmed(short) {
148
+ const entries = readPollEntries(short);
149
+ const alive = entries.filter(r => pidAlive(r.pid));
150
+ if (alive.length !== entries.length)
151
+ writePollEntries(short, alive);
152
+ return alive.length > 0;
153
+ }
154
+ /** Every live poll on this machine, freshest first. */
155
+ function listLivePolls() {
156
+ const out = [];
157
+ for (const short of allShorts()) {
158
+ const entries = readPollEntries(short);
159
+ const alive = entries.filter(r => pidAlive(r.pid));
160
+ if (alive.length !== entries.length)
161
+ writePollEntries(short, alive);
162
+ out.push(...alive);
163
+ }
164
+ return out.sort((a, b) => (b.startedAt || 0) - (a.startedAt || 0));
165
+ }
166
+ // ---- Cursor (gap-recovery so the long-poll never loses a message) ----------
167
+ // Each poll resumes the SSE stream from the last id it persisted (`?since=`),
168
+ // so a message that arrives between one poll exiting and the next arming is
169
+ // REPLAYED, not lost. The cursor is per-session, shared across poll invocations.
170
+ function cursorPath(short) {
171
+ const dir = pollsDir();
172
+ return dir ? path.join(dir, `${short}.cursor`) : null;
173
+ }
174
+ /** Last message id this session's polls have seen, or null (first poll → live
175
+ * tail only; no replay of pre-existing history). */
176
+ function readPollCursor(short) {
177
+ try {
178
+ const p = cursorPath(short);
179
+ if (!p)
180
+ return null;
181
+ const v = fs.readFileSync(p, 'utf-8').trim();
182
+ return v || null;
183
+ }
184
+ catch {
185
+ return null;
186
+ }
187
+ }
188
+ function writePollCursor(short, id) {
189
+ try {
190
+ const dir = pollsDir();
191
+ if (!dir || !id)
192
+ return;
193
+ fs.mkdirSync(dir, { recursive: true });
194
+ fs.writeFileSync(path.join(dir, `${short}.cursor`), id);
195
+ }
196
+ catch { /* best-effort — at worst one message is re-delivered */ }
197
+ }
198
+ /** Drop the cursor (→ next poll live-tails from now). Called when the server
199
+ * rejects the stored `since` (the message it points to was pruned/deleted): a
200
+ * stale cursor would otherwise 4xx forever, permanently wedging delivery for
201
+ * this session. Clearing it trades replay of the gap for restored liveness. */
202
+ function clearPollCursor(short) {
203
+ try {
204
+ const p = cursorPath(short);
205
+ if (p)
206
+ fs.rmSync(p, { force: true });
207
+ }
208
+ catch { /* best-effort */ }
209
+ }
210
+ /** Count-cap every session's polls: keep the K freshest LIVE polls, kill only the
211
+ * surplus, never below K. Snapshot-free (per-session file reads + pidAlive); a
212
+ * `taskkill` only on genuine surplus. Run at SessionStart (recap hook) and via
213
+ * `greprag inbox poll-reap`. Reuses the watcher's pure `capSurplusVerdict` — the
214
+ * same liveness-safety guarantee, applied to the poll namespace.
215
+ * adr: adr/monitor-resilience.md */
216
+ function reapSurplusPolls(K = exports.DEFAULT_POLL_CAP) {
217
+ let scanned = 0;
218
+ let surplus = 0;
219
+ const killed = [];
220
+ for (const short of allShorts()) {
221
+ const alive = readPollEntries(short).filter(r => pidAlive(r.pid));
222
+ scanned += alive.length;
223
+ const { keep, kill } = (0, watcher_registry_1.capSurplusVerdict)(alive, K);
224
+ if (kill.length === 0) {
225
+ writePollEntries(short, alive);
226
+ continue;
227
+ }
228
+ surplus += kill.length;
229
+ const survivors = keep.slice();
230
+ for (const w of kill) {
231
+ if (killProcess(w.pid))
232
+ killed.push(w.pid);
233
+ else
234
+ survivors.push(w); // kill failed → keep tracking, retry next pass
235
+ }
236
+ writePollEntries(short, survivors);
237
+ }
238
+ return { scanned, surplus, killed };
239
+ }
240
+ /** Force-kill a poll process. A poll has no children (single SSE process), so a
241
+ * plain kill suffices — but `taskkill /T` is used on Windows for symmetry with
242
+ * the watcher and to catch any incidental child. */
243
+ function killProcess(pid) {
244
+ try {
245
+ if (process.platform === 'win32') {
246
+ (0, child_process_1.execFileSync)('taskkill.exe', ['/PID', String(pid), '/T', '/F'], // proc-allow: poll count-cap surplus kill, mirrors watcher-registry
247
+ { timeout: 5_000, stdio: 'ignore', windowsHide: true });
248
+ }
249
+ else {
250
+ try {
251
+ process.kill(pid, 'SIGKILL');
252
+ }
253
+ catch { /* already gone */ }
254
+ }
255
+ return true;
256
+ }
257
+ catch {
258
+ return false;
259
+ }
260
+ }
261
+ //# sourceMappingURL=poll-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"poll-registry.js","sourceRoot":"","sources":["../../src/commands/poll-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /** state-trigger — Adapter A of the ingress-trigger bridge (the LOCAL half).
2
+ *
3
+ * A Stop / UserPromptSubmit hook computes the cheap DETERMINISTIC state values
4
+ * (stress level, turn count, keyword-seen) from the transcript — NO LLM, NO
5
+ * network — and stashes them in the matchset cache under `stateValues` (see
6
+ * guard.writeStateValues). A `source:"state"` condition clause then reads them on
7
+ * the PreToolUse hot path in microseconds, still local, still fail-open. This is
8
+ * what lets stress migrate from an offline-only backtest signal to a registered,
9
+ * live-firing matchset rule. docs/ingress-trigger-bridge.md, docs/stress-trigger.md
10
+ *
11
+ * STRESS PORT: a faithful TypeScript port of scripts/stress-tune2.py's windowed
12
+ * behavioral composite (the validated winner — AUC 0.835 full / 0.794
13
+ * behavioral-only on 1,069 real turns). Features rep / retry / seqrep / err /
14
+ * churn are streamed over the trailing window exactly as the Python maintains its
15
+ * deques, and the FINAL turn's vector is the live stress reading. Weights +
16
+ * level thresholds are PINNED from that backtest and re-tunable via the script;
17
+ * this module never re-derives them. docs/stress-trigger.md
18
+ */
19
+ /** Per-turn behavioral summary — the same fields scripts/stress-backtest.py's
20
+ * parse_turns produces (prose_words, tool_targets, errors, n_tools, writes). */
21
+ export interface TurnSummary {
22
+ proseWords: number;
23
+ toolTargets: string[];
24
+ errors: number;
25
+ nTools: number;
26
+ writes: string[];
27
+ }
28
+ /** Stress level enum, encoded numerically so the `state` DSL can threshold it
29
+ * with gte/lte (0 calm · 1 elevated · 2 high). */
30
+ export declare const STRESS_CALM = 0;
31
+ export declare const STRESS_ELEVATED = 1;
32
+ export declare const STRESS_HIGH = 2;
33
+ /** Parse the transcript into per-turn summaries. Returns the TRAILING `maxTurns`
34
+ * turns (enough for every short-memory deque) plus the total real-user turn
35
+ * count. Bounded memory: older turns are dropped as they fall out of the window.
36
+ * Best-effort: a missing/corrupt transcript → empty. */
37
+ export declare function parseTurns(transcriptPath: string | undefined, maxTurns?: number): {
38
+ turns: TurnSummary[];
39
+ totalTurns: number;
40
+ };
41
+ export interface StressResult {
42
+ score: number;
43
+ level: number;
44
+ }
45
+ /** Stream the windowed behavioral features over the turns and score the FINAL
46
+ * one — the live stress reading. Faithful port of stress-tune2.py
47
+ * features_and_labels (rep / retry / seqrep / err / churn), scored with the
48
+ * pinned weight vector and mapped to a 0/1/2 level. Pure. */
49
+ export declare function computeStress(turns: TurnSummary[]): StressResult;
50
+ /** Scan the most recent user prompt for each watched keyword (case-insensitive
51
+ * substring), returning `keyword:<term>` → true for every hit. The Stop hook
52
+ * collects the watched terms from the cached rules so this stays driven by the
53
+ * matchset, never a hardcoded list. Pure. */
54
+ export declare function scanKeywords(latestPrompt: string, keywords: string[]): Record<string, boolean>;
55
+ export interface StateValuesOptions {
56
+ /** Watched keyword terms (collected from `keyword:<term>` state clauses in the
57
+ * cached rules). The latest user prompt is scanned for each. */
58
+ keywords?: string[];
59
+ /** The latest user prompt text (from the hook payload, not a store query — the
60
+ * un-Stop-ped turn isn't in the store yet). Used only for keyword scan. */
61
+ latestPrompt?: string;
62
+ maxTurns?: number;
63
+ }
64
+ /** Compute the full stateValues bag for one Stop/UserPromptSubmit fire. Pure
65
+ * given the transcript contents; never throws (parse failures → calm/zero). */
66
+ export declare function computeStateValues(transcriptPath: string | undefined, opts?: StateValuesOptions): Record<string, unknown>;
@@ -0,0 +1,305 @@
1
+ "use strict";
2
+ /** state-trigger — Adapter A of the ingress-trigger bridge (the LOCAL half).
3
+ *
4
+ * A Stop / UserPromptSubmit hook computes the cheap DETERMINISTIC state values
5
+ * (stress level, turn count, keyword-seen) from the transcript — NO LLM, NO
6
+ * network — and stashes them in the matchset cache under `stateValues` (see
7
+ * guard.writeStateValues). A `source:"state"` condition clause then reads them on
8
+ * the PreToolUse hot path in microseconds, still local, still fail-open. This is
9
+ * what lets stress migrate from an offline-only backtest signal to a registered,
10
+ * live-firing matchset rule. docs/ingress-trigger-bridge.md, docs/stress-trigger.md
11
+ *
12
+ * STRESS PORT: a faithful TypeScript port of scripts/stress-tune2.py's windowed
13
+ * behavioral composite (the validated winner — AUC 0.835 full / 0.794
14
+ * behavioral-only on 1,069 real turns). Features rep / retry / seqrep / err /
15
+ * churn are streamed over the trailing window exactly as the Python maintains its
16
+ * deques, and the FINAL turn's vector is the live stress reading. Weights +
17
+ * level thresholds are PINNED from that backtest and re-tunable via the script;
18
+ * this module never re-derives them. docs/stress-trigger.md
19
+ */
20
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ var desc = Object.getOwnPropertyDescriptor(m, k);
23
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
24
+ desc = { enumerable: true, get: function() { return m[k]; } };
25
+ }
26
+ Object.defineProperty(o, k2, desc);
27
+ }) : (function(o, m, k, k2) {
28
+ if (k2 === undefined) k2 = k;
29
+ o[k2] = m[k];
30
+ }));
31
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
32
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
33
+ }) : function(o, v) {
34
+ o["default"] = v;
35
+ });
36
+ var __importStar = (this && this.__importStar) || (function () {
37
+ var ownKeys = function(o) {
38
+ ownKeys = Object.getOwnPropertyNames || function (o) {
39
+ var ar = [];
40
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
41
+ return ar;
42
+ };
43
+ return ownKeys(o);
44
+ };
45
+ return function (mod) {
46
+ if (mod && mod.__esModule) return mod;
47
+ var result = {};
48
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
49
+ __setModuleDefault(result, mod);
50
+ return result;
51
+ };
52
+ })();
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ exports.STRESS_HIGH = exports.STRESS_ELEVATED = exports.STRESS_CALM = void 0;
55
+ exports.parseTurns = parseTurns;
56
+ exports.computeStress = computeStress;
57
+ exports.scanKeywords = scanKeywords;
58
+ exports.computeStateValues = computeStateValues;
59
+ const fs = __importStar(require("fs"));
60
+ /** Stress level enum, encoded numerically so the `state` DSL can threshold it
61
+ * with gte/lte (0 calm · 1 elevated · 2 high). */
62
+ exports.STRESS_CALM = 0;
63
+ exports.STRESS_ELEVATED = 1;
64
+ exports.STRESS_HIGH = 2;
65
+ /** PINNED weight vector (rep, retry, seqrep, err, churn), from the stress-tune2
66
+ * backtest narrative: same-TARGET repetition (rep) + errors (err) are the sharp
67
+ * signals; churn + retry corroborate. seqrep (tool-NAME trigram repetition) is
68
+ * deliberately the WEAKEST — it saturates on any sustained tool use (six Reads in
69
+ * a row repeats the (Read,Read,Read) trigram), so a heavy weight would flag
70
+ * ordinary work as stress. Re-tune via scripts/stress-tune2.py, never inline. */
71
+ const STRESS_WEIGHTS = { rep: 0.75, retry: 0.5, seqrep: 0.25, err: 0.75, churn: 0.5 };
72
+ /** PINNED level thresholds on the composite score: tuned so seqrep ALONE (≈0.25)
73
+ * can't reach elevated — it takes real repetition/errors/churn. Same provenance. */
74
+ const STRESS_ELEVATED_AT = 0.6;
75
+ const STRESS_HIGH_AT = 1.1;
76
+ const WINDOW = 4; // recent-turn window (W in stress-tune2.py)
77
+ const SEEN_MAX = 12;
78
+ const NAMESEQ_MAX = 9;
79
+ const TRIGRAM_MAX = 20;
80
+ const ERROR_RE = /\b(error|failed|exception|traceback|exit code [1-9]|not found|no such)\b/i;
81
+ // ---------- Transcript → turns ----------------------------------------------
82
+ function blocks(rec) {
83
+ const msg = (rec.message || {});
84
+ const c = msg.content;
85
+ if (Array.isArray(c))
86
+ return c;
87
+ if (typeof c === 'string')
88
+ return [{ type: 'text', text: c }];
89
+ return [];
90
+ }
91
+ function isRealUser(rec) {
92
+ if (rec.type !== 'user')
93
+ return false;
94
+ for (const b of blocks(rec)) {
95
+ if (b && b.type === 'tool_result')
96
+ return false;
97
+ }
98
+ return true;
99
+ }
100
+ function toolTargetKey(b) {
101
+ const name = b.name || '';
102
+ const inp = (b.input || {});
103
+ let key = (inp.command ?? inp.file_path ?? inp.pattern ?? inp.path);
104
+ if (typeof key !== 'string') {
105
+ try {
106
+ key = JSON.stringify(inp).slice(0, 120);
107
+ }
108
+ catch {
109
+ key = '';
110
+ }
111
+ }
112
+ return `${name}:${key}`;
113
+ }
114
+ function resultIsError(b) {
115
+ if (b.is_error === true)
116
+ return true;
117
+ const c = b.content;
118
+ let txt = '';
119
+ if (typeof c === 'string')
120
+ txt = c;
121
+ else if (c) {
122
+ try {
123
+ txt = JSON.stringify(c);
124
+ }
125
+ catch {
126
+ txt = '';
127
+ }
128
+ }
129
+ return ERROR_RE.test(txt);
130
+ }
131
+ /** Parse the transcript into per-turn summaries. Returns the TRAILING `maxTurns`
132
+ * turns (enough for every short-memory deque) plus the total real-user turn
133
+ * count. Bounded memory: older turns are dropped as they fall out of the window.
134
+ * Best-effort: a missing/corrupt transcript → empty. */
135
+ function parseTurns(transcriptPath, maxTurns = 40) {
136
+ if (!transcriptPath)
137
+ return { turns: [], totalTurns: 0 };
138
+ let lines;
139
+ try {
140
+ lines = fs.readFileSync(transcriptPath, 'utf-8').split('\n');
141
+ }
142
+ catch {
143
+ return { turns: [], totalTurns: 0 };
144
+ }
145
+ const turns = [];
146
+ let total = 0;
147
+ let cur = null;
148
+ const flush = () => {
149
+ if (cur) {
150
+ turns.push(cur);
151
+ if (turns.length > maxTurns)
152
+ turns.shift();
153
+ }
154
+ cur = null;
155
+ };
156
+ for (const line of lines) {
157
+ const trimmed = line.trim();
158
+ if (!trimmed)
159
+ continue;
160
+ let rec;
161
+ try {
162
+ rec = JSON.parse(trimmed);
163
+ }
164
+ catch {
165
+ continue;
166
+ }
167
+ if (isRealUser(rec)) {
168
+ flush();
169
+ total++;
170
+ cur = { proseWords: 0, toolTargets: [], errors: 0, nTools: 0, writes: [] };
171
+ continue;
172
+ }
173
+ if (!cur)
174
+ continue; // pre-first-prompt noise
175
+ if (rec.type === 'assistant') {
176
+ for (const b of blocks(rec)) {
177
+ if (!b)
178
+ continue;
179
+ if (b.type === 'text') {
180
+ cur.proseWords += String(b.text || '').split(/\s+/).filter(Boolean).length;
181
+ }
182
+ else if (b.type === 'tool_use') {
183
+ cur.nTools++;
184
+ cur.toolTargets.push(toolTargetKey(b));
185
+ if (b.name === 'Edit' || b.name === 'Write') {
186
+ const fp = (b.input || {}).file_path;
187
+ if (typeof fp === 'string' && fp)
188
+ cur.writes.push(fp);
189
+ }
190
+ }
191
+ }
192
+ }
193
+ else if (rec.type === 'user') { // tool_result records
194
+ for (const b of blocks(rec)) {
195
+ if (b && b.type === 'tool_result' && resultIsError(b))
196
+ cur.errors++;
197
+ }
198
+ }
199
+ }
200
+ flush();
201
+ return { turns, totalTurns: total };
202
+ }
203
+ /** Stream the windowed behavioral features over the turns and score the FINAL
204
+ * one — the live stress reading. Faithful port of stress-tune2.py
205
+ * features_and_labels (rep / retry / seqrep / err / churn), scored with the
206
+ * pinned weight vector and mapped to a 0/1/2 level. Pure. */
207
+ function computeStress(turns) {
208
+ if (turns.length === 0)
209
+ return { score: 0, level: exports.STRESS_CALM };
210
+ const seen = [];
211
+ const recent = [];
212
+ const nameSeq = [];
213
+ const trigrams = [];
214
+ let prevTargets = new Set();
215
+ let last = { rep: 0, retry: 0, seqrep: 0, err: 0, churn: 0 };
216
+ const pushCap = (arr, v, cap) => {
217
+ arr.push(v);
218
+ if (arr.length > cap)
219
+ arr.shift();
220
+ };
221
+ for (const t of turns) {
222
+ recent.push(t);
223
+ if (recent.length > WINDOW)
224
+ recent.shift();
225
+ const tools = recent.reduce((s, x) => s + x.nTools, 0);
226
+ const errs = recent.reduce((s, x) => s + x.errors, 0);
227
+ const curTargets = new Set(t.toolTargets);
228
+ const rep = t.toolTargets.length
229
+ ? t.toolTargets.filter(tg => seen.includes(tg)).length / t.toolTargets.length : 0;
230
+ let retry = 0;
231
+ for (const tg of curTargets) {
232
+ if (prevTargets.has(tg)) {
233
+ retry = 1;
234
+ break;
235
+ }
236
+ }
237
+ for (const tg of t.toolTargets)
238
+ pushCap(seen, tg, SEEN_MAX);
239
+ let hits = 0, tot = 0;
240
+ for (const tg of t.toolTargets) {
241
+ const nm = tg.split(':', 1)[0];
242
+ pushCap(nameSeq, nm, NAMESEQ_MAX);
243
+ if (nameSeq.length >= 3) {
244
+ const tri = nameSeq.slice(-3).join('');
245
+ tot++;
246
+ if (trigrams.includes(tri))
247
+ hits++;
248
+ pushCap(trigrams, tri, TRIGRAM_MAX);
249
+ }
250
+ }
251
+ const seqrep = tot ? hits / tot : 0;
252
+ const err = tools ? errs / tools : 0;
253
+ const wcount = new Map();
254
+ for (const x of recent) {
255
+ for (const fp of new Set(x.writes))
256
+ wcount.set(fp, (wcount.get(fp) || 0) + 1);
257
+ }
258
+ let churn = 0;
259
+ for (const v of wcount.values()) {
260
+ if (v >= 3) {
261
+ churn = 1;
262
+ break;
263
+ }
264
+ }
265
+ last = { rep, retry, seqrep, err, churn };
266
+ prevTargets = curTargets;
267
+ }
268
+ const score = STRESS_WEIGHTS.rep * last.rep + STRESS_WEIGHTS.retry * last.retry +
269
+ STRESS_WEIGHTS.seqrep * last.seqrep + STRESS_WEIGHTS.err * last.err +
270
+ STRESS_WEIGHTS.churn * last.churn;
271
+ const level = score >= STRESS_HIGH_AT ? exports.STRESS_HIGH
272
+ : score >= STRESS_ELEVATED_AT ? exports.STRESS_ELEVATED : exports.STRESS_CALM;
273
+ return { score: Math.round(score * 1000) / 1000, level };
274
+ }
275
+ // ---------- Keyword scan -----------------------------------------------------
276
+ /** Scan the most recent user prompt for each watched keyword (case-insensitive
277
+ * substring), returning `keyword:<term>` → true for every hit. The Stop hook
278
+ * collects the watched terms from the cached rules so this stays driven by the
279
+ * matchset, never a hardcoded list. Pure. */
280
+ function scanKeywords(latestPrompt, keywords) {
281
+ const out = {};
282
+ const hay = (latestPrompt || '').toLowerCase();
283
+ for (const kw of keywords) {
284
+ if (!kw)
285
+ continue;
286
+ out[`keyword:${kw}`] = hay.includes(kw.toLowerCase());
287
+ }
288
+ return out;
289
+ }
290
+ /** Compute the full stateValues bag for one Stop/UserPromptSubmit fire. Pure
291
+ * given the transcript contents; never throws (parse failures → calm/zero). */
292
+ function computeStateValues(transcriptPath, opts = {}) {
293
+ const { turns, totalTurns } = parseTurns(transcriptPath, opts.maxTurns ?? 40);
294
+ const stress = computeStress(turns);
295
+ const values = {
296
+ stress: stress.level,
297
+ stressScore: stress.score,
298
+ turnCount: totalTurns,
299
+ };
300
+ if (opts.keywords && opts.keywords.length) {
301
+ Object.assign(values, scanKeywords(opts.latestPrompt || '', opts.keywords));
302
+ }
303
+ return values;
304
+ }
305
+ //# sourceMappingURL=state-trigger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-trigger.js","sourceRoot":"","sources":["../../src/commands/state-trigger.ts"],"names":[],"mappings":"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"}