@nexus-cortex/core 4.108.11 → 4.108.13

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.
@@ -6,7 +6,7 @@
6
6
  * detector remains as the fast path for byte-identical spam.)
7
7
  */
8
8
  import { type ToolOutcome } from './toolOutcome.js';
9
- export type LadderAction = 'none' | 'remind' | 'diversify' | 'break';
9
+ export type LadderAction = 'none' | 'remind' | 'diversify' | 'break' | 'poll_steer';
10
10
  export interface LadderResult {
11
11
  action: LadderAction;
12
12
  /** Consecutive not-ok observations for this (tool, approach). */
@@ -14,6 +14,12 @@ export interface LadderResult {
14
14
  family?: string;
15
15
  /** Which lens produced a 'neardup' result: 'hash' (approachHash equality) or 'similarity' (HB-LOOP-NEARDUP). */
16
16
  trigger?: 'hash' | 'similarity';
17
+ /** R135 HB-POLL-LOOP: set on a 'poll_steer' result — the probe identity and the consecutive poll streak. */
18
+ poll?: {
19
+ probe: string;
20
+ waits: number;
21
+ waitSec?: number;
22
+ };
17
23
  }
18
24
  export interface LoopLadderThresholds {
19
25
  remindAt?: number;
@@ -40,14 +46,22 @@ export declare class LoopLadder {
40
46
  private readonly recentKeys;
41
47
  private readonly nearDupNudged;
42
48
  private readonly lastChunk;
49
+ private lastPollKey;
50
+ private pollStreak;
51
+ private pollWaitSum;
52
+ private pollWaitN;
53
+ private readonly lastProbe;
43
54
  constructor(thresholds?: LoopLadderThresholds);
44
- /** HB-LOOP-NEARDUP: windowed similarity count for an executing tool's normalized text. */
55
+ /** HB-LOOP-NEARDUP: windowed similarity count for an executing tool's normalized text. R136: script identity
56
+ * dominates wrapper shape — entries whose identity differs are skipped before the text comparison. */
45
57
  private observeSimilar;
46
58
  /** 14b: outcome-agnostic windowed near-dup check. Returns a result when the
47
59
  * same normalized approach recurs >= nudgeAt (diversify, once per key) or
48
60
  * >= 2x nudgeAt (break) within the sliding window. */
49
61
  private observeNearDup;
50
- observe(toolName: string, outcome: Pick<ToolOutcome, 'status' | 'approachHash' | 'family' | 'approachText' | 'chunkRead'>): LadderResult;
62
+ /** R135: true when this observation is a poll (a wait + read-only probe, or a bare probe repeating the tool's previous probe). */
63
+ private notePoll;
64
+ observe(toolName: string, outcome: Pick<ToolOutcome, 'status' | 'approachHash' | 'family' | 'approachText' | 'chunkRead' | 'commandIdentity' | 'poll'>): LadderResult;
51
65
  }
52
66
  /**
53
67
  * Format the tool-result signal text for a ladder escalation. `null` for
@@ -90,17 +104,21 @@ export declare class ExactRepeatTracker {
90
104
  private resultStreak;
91
105
  /** A poll was observed and its result has not been reported yet (noteResult never called). */
92
106
  private pendingResult;
107
+ /** R135b: the current key is poll-shaped — a POLL_TOOL_NAMES tool, or a Bash poll-and-wait (observe hint). */
108
+ private lastIsPoll;
93
109
  /** Returns the CONSECUTIVE occurrence count for this exact call. For poll tools
94
110
  * (POLL_TOOL_NAMES) the count is the trailing run of byte-identical stalled results + 1 —
95
111
  * a live process or changing output never accumulates (falls back to the raw consecutive
96
112
  * count when results were never reported via noteResult). */
97
- observe(toolName: string, inputHash: string): number;
98
- /** Report the RESULT of the most recently observed call (poll tools only; other keys are ignored). */
113
+ observe(toolName: string, inputHash: string, opts?: {
114
+ isPoll?: boolean;
115
+ }): number;
116
+ /** Report the RESULT of the most recently observed call (poll-shaped keys only; other keys are ignored). */
99
117
  noteResult(toolName: string, inputHash: string, content: string, metadata?: Record<string, unknown>): void;
100
118
  }
101
- /** Orchestrator glue (both tool loops): feed a batch's results back to the tracker. Non-poll
102
- * tools are ignored inside noteResult; the inputHash must be the same JSON.stringify(input)
103
- * the observe() call used. */
119
+ /** Orchestrator glue (both tool loops): feed a batch's results back to the tracker. Non-poll keys
120
+ * (neither a POLL_TOOL_NAMES tool nor a Bash poll hinted at observe) are ignored inside noteResult;
121
+ * the inputHash must be the same JSON.stringify(input) the observe() call used. */
104
122
  export declare function notePollResults(tracker: ExactRepeatTracker, toolUseBlocks: ReadonlyArray<{
105
123
  id: string;
106
124
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"loopLadder.d.ts","sourceRoot":"","sources":["../../src/training/loopLadder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC;AAErE,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gHAAgH;IAChH,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;CACjC;AAID,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAOD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyD;IAQhF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;IACtC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,UAAU,CAAS;IAM3B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAOxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6C;IACvE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IAInD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;gBAE9C,UAAU,GAAE,oBAAyB;IAuBjD,0FAA0F;IAC1F,OAAO,CAAC,cAAc;IActB;;2DAEuD;IACvD,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,cAAc,GAAG,QAAQ,GAAG,cAAc,GAAG,WAAW,CAAC,GAAG,YAAY;CA+CzI;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CA2CxF;AAED;;;;;;;;;;;;;GAaG;AACH;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAA6C,CAAC;AAE9F;;sBAEsB;AACtB,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAIlH;AASD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,KAAK,CAAK;IAElB,OAAO,CAAC,cAAc,CAAuB;IAC7C,6FAA6F;IAC7F,OAAO,CAAC,YAAY,CAAK;IACzB,8FAA8F;IAC9F,OAAO,CAAC,aAAa,CAAS;IAE9B;;;kEAG8D;IAC9D,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAiBpD,sGAAsG;IACtG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAa3G;AAED;;+BAE+B;AAC/B,wBAAgB,eAAe,CAC7B,OAAO,EAAE,kBAAkB,EAC3B,aAAa,EAAE,aAAa,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,EAC1E,WAAW,EAAE,aAAa,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,GAC1H,IAAI,CAON"}
1
+ {"version":3,"file":"loopLadder.d.ts","sourceRoot":"","sources":["../../src/training/loopLadder.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,8 @@
7
7
  */
8
8
  import { diceSimilarity } from './toolOutcome.js';
9
9
  import { isChunkProgression } from './chunkReadProgression.js';
10
- const RANK = { none: 0, remind: 1, diversify: 2, break: 3 };
10
+ import { commandIdentityDiffers, commandIdentityDigest } from './commandIdentity.js';
11
+ const RANK = { none: 0, remind: 1, diversify: 2, break: 3, poll_steer: 1 };
11
12
  function envInt(name, fallback) {
12
13
  const v = parseInt(process.env[name] ?? '', 10);
13
14
  return Number.isNaN(v) || v <= 0 ? fallback : v;
@@ -45,6 +46,8 @@ export class LoopLadder {
45
46
  // 7; no PASSING session did (max 6 = healthy test iteration). Diversify at NEARDUP_SIM_AT (7), break at 2×.
46
47
  nearDupSim;
47
48
  nearDupSimAt;
49
+ // R136 HB-NEARDUP-SCRIPT-SHAPE: each entry carries the command identity (script paths / inline body);
50
+ // a DIFFERENT identity is never a near-duplicate no matter how similar the shared shell wrapper is.
48
51
  recentSim = [];
49
52
  simNudged = new Set();
50
53
  recentKeys = [];
@@ -53,6 +56,17 @@ export class LoopLadder {
53
56
  // gets a range-suffixed key (a NEW approach for the hash lens, poll guard and failure ladder) and
54
57
  // skips the similarity lens; an identical/overlapping/backwards range keeps the plain hash key.
55
58
  lastChunk = new Map();
59
+ // R135 HB-POLL-LOOP (2026-09-13): an OK poll-and-wait (sleep N; read-only probe — classifyToolOutcome's
60
+ // outcome.poll) is monitoring, not a stuck approach. It feeds NEITHER near-dup lens NOR the failure
61
+ // ladder; consecutive same-probe polls are counted here and answered with a 'poll_steer' nudge at the
62
+ // 3rd (then every 10th): move the wait into a background job + BashOutput. A bare read-only probe that
63
+ // immediately repeats the previous probe of the same tool is a poll too. Failing polls (curl exit 7)
64
+ // still climb the failure ladder as before. The old CORTEX_POLL_GUARD busy-wait remind is untouched.
65
+ lastPollKey = null;
66
+ pollStreak = 0;
67
+ pollWaitSum = 0;
68
+ pollWaitN = 0;
69
+ lastProbe = new Map();
56
70
  constructor(thresholds = {}) {
57
71
  this.remindAt = thresholds.remindAt ?? envInt('LOOP_REMIND_AT', 2);
58
72
  this.diversifyAt = thresholds.diversifyAt ?? envInt('LOOP_DIVERSIFY_AT', 4);
@@ -75,12 +89,13 @@ export class LoopLadder {
75
89
  const sim = parseFloat(process.env.NEARDUP_SIM ?? '');
76
90
  this.nearDupSim = Number.isFinite(sim) && sim > 0 && sim <= 1 ? sim : 0.9;
77
91
  }
78
- /** HB-LOOP-NEARDUP: windowed similarity count for an executing tool's normalized text. */
79
- observeSimilar(toolName, text) {
92
+ /** HB-LOOP-NEARDUP: windowed similarity count for an executing tool's normalized text. R136: script identity
93
+ * dominates wrapper shape — entries whose identity differs are skipped before the text comparison. */
94
+ observeSimilar(toolName, text, identity) {
80
95
  if (!this.nearDupEnabled || !text)
81
96
  return null;
82
- const count = 1 + this.recentSim.filter((e) => e.tool === toolName && (e.text === text || diceSimilarity(e.text, text) >= this.nearDupSim)).length;
83
- this.recentSim.push({ tool: toolName, text });
97
+ const count = 1 + this.recentSim.filter((e) => e.tool === toolName && !commandIdentityDiffers(e.identity, identity, this.nearDupSim) && (e.text === text || diceSimilarity(e.text, text) >= this.nearDupSim)).length;
98
+ this.recentSim.push({ tool: toolName, text, ...(identity ? { identity } : {}) });
84
99
  if (this.recentSim.length > this.nearDupWindow)
85
100
  this.recentSim.shift();
86
101
  if (count >= this.nearDupSimAt * 2)
@@ -111,8 +126,23 @@ export class LoopLadder {
111
126
  }
112
127
  return null;
113
128
  }
129
+ /** R135: true when this observation is a poll (a wait + read-only probe, or a bare probe repeating the tool's previous probe). */
130
+ notePoll(toolName, poll) {
131
+ const probe = poll?.probe;
132
+ const bareRepeat = !!poll && !poll.isPoll && !!probe && this.lastProbe.get(toolName) === probe;
133
+ if (probe)
134
+ this.lastProbe.set(toolName, probe);
135
+ else
136
+ this.lastProbe.delete(toolName);
137
+ return !!poll && (poll.isPoll || bareRepeat);
138
+ }
114
139
  observe(toolName, outcome) {
115
140
  let key = `${toolName}\n${outcome.approachHash}`;
141
+ // R136b: script identity (executed file / inline body) is part of the approach for the hash lens and the
142
+ // failure ladder — different scripts under one wrapper are different approaches; no identity = plain key.
143
+ const ident = commandIdentityDigest(outcome.commandIdentity);
144
+ if (ident)
145
+ key += `\n@${ident}`;
116
146
  let progression = false;
117
147
  if (outcome.chunkRead) {
118
148
  const chunkKey = `${toolName}\n${outcome.chunkRead.file}`;
@@ -121,8 +151,35 @@ export class LoopLadder {
121
151
  if (progression)
122
152
  key += `\n${outcome.chunkRead.start}-${outcome.chunkRead.end}`;
123
153
  }
154
+ const isPoll = this.notePoll(toolName, outcome.poll);
155
+ if (isPoll && outcome.status === 'ok') {
156
+ this.counts.delete(key); // an ok still resets the failure rung of this approach
157
+ const pkey = `${toolName}\n${outcome.poll.probe}`;
158
+ if (pkey === this.lastPollKey)
159
+ this.pollStreak += 1;
160
+ else {
161
+ this.lastPollKey = pkey;
162
+ this.pollStreak = 1;
163
+ this.pollWaitSum = 0;
164
+ this.pollWaitN = 0;
165
+ }
166
+ if (typeof outcome.poll.waitSec === 'number') {
167
+ this.pollWaitSum += outcome.poll.waitSec;
168
+ this.pollWaitN += 1;
169
+ }
170
+ if (this.pollStreak === 3 || (this.pollStreak > 3 && this.pollStreak % 10 === 0)) {
171
+ return {
172
+ action: 'poll_steer', count: this.pollStreak, family: 'poll',
173
+ poll: { probe: outcome.poll.probe, waits: this.pollStreak, ...(this.pollWaitN ? { waitSec: Math.round(this.pollWaitSum / this.pollWaitN) } : {}) },
174
+ };
175
+ }
176
+ return { action: 'none', count: 0 };
177
+ }
178
+ // A non-poll call of the same tool ends the consecutive streak (a failing poll keeps it).
179
+ if (!isPoll && this.lastPollKey?.startsWith(`${toolName}\n`))
180
+ this.lastPollKey = null;
124
181
  const hashDup = this.observeNearDup(key);
125
- const simDup = this.observeSimilar(toolName, progression ? undefined : outcome.approachText);
182
+ const simDup = this.observeSimilar(toolName, progression ? undefined : outcome.approachText, outcome.commandIdentity);
126
183
  // the more severe of the two near-dup lenses
127
184
  const nearDup = hashDup && simDup ? (RANK[simDup.action] >= RANK[hashDup.action] ? simDup : hashDup) : (simDup ?? hashDup);
128
185
  if (outcome.status === 'ok') {
@@ -172,6 +229,14 @@ export class LoopLadder {
172
229
  * already cover the remind rung; the ladder speaks only when it must.
173
230
  */
174
231
  export function formatLadderSignal(toolName, result) {
232
+ // R135 HB-POLL-LOOP: a poll-and-wait streak — steer the wait off the turn; the executor stays available.
233
+ if (result.action === 'poll_steer') {
234
+ const p = result.poll;
235
+ const waits = p?.waitSec !== undefined ? `${p.waits} waits of ~${p.waitSec} s on ${p.probe}` : `${p?.waits ?? result.count} repeats of ${p?.probe ?? toolName}`;
236
+ return (`<system-reminder>\nPolling pattern detected (${waits}). Move the wait off the turn: launch the probe loop with ` +
237
+ `run_in_background (or \`persistentSession\`) and read it with BashOutput when you need it; keep any foreground wait <= 60 s. ` +
238
+ `${toolName} stays available.\n</system-reminder>`);
239
+ }
175
240
  // Poll guard (run3 busy-wait class): a remind with family 'poll' is a
176
241
  // SUCCEEDING-repeat nudge, not a failure escalation — inject its own text.
177
242
  if (result.action === 'remind' && result.family === 'poll') {
@@ -254,11 +319,13 @@ export class ExactRepeatTracker {
254
319
  resultStreak = 0;
255
320
  /** A poll was observed and its result has not been reported yet (noteResult never called). */
256
321
  pendingResult = false;
322
+ /** R135b: the current key is poll-shaped — a POLL_TOOL_NAMES tool, or a Bash poll-and-wait (observe hint). */
323
+ lastIsPoll = false;
257
324
  /** Returns the CONSECUTIVE occurrence count for this exact call. For poll tools
258
325
  * (POLL_TOOL_NAMES) the count is the trailing run of byte-identical stalled results + 1 —
259
326
  * a live process or changing output never accumulates (falls back to the raw consecutive
260
327
  * count when results were never reported via noteResult). */
261
- observe(toolName, inputHash) {
328
+ observe(toolName, inputHash, opts) {
262
329
  const key = `${toolName}\u0000${inputHash}`;
263
330
  if (key === this.lastKey) {
264
331
  this.count += 1;
@@ -270,17 +337,18 @@ export class ExactRepeatTracker {
270
337
  this.resultStreak = 0;
271
338
  this.pendingResult = false;
272
339
  }
273
- if (!POLL_TOOL_NAMES.has(toolName))
340
+ // R135b HB-POLL-LOOP: a Bash poll-and-wait (outcome.poll.isPoll, hinted by the caller) gets the same
341
+ // result-aware count as BashOutput — identical polls with CHANGING results are progress, not a repeat.
342
+ this.lastIsPoll = POLL_TOOL_NAMES.has(toolName) || opts?.isPoll === true;
343
+ if (!this.lastIsPoll)
274
344
  return this.count;
275
345
  const effective = this.count > 1 && this.pendingResult ? this.count : this.resultStreak + 1;
276
346
  this.pendingResult = true;
277
347
  return effective;
278
348
  }
279
- /** Report the RESULT of the most recently observed call (poll tools only; other keys are ignored). */
349
+ /** Report the RESULT of the most recently observed call (poll-shaped keys only; other keys are ignored). */
280
350
  noteResult(toolName, inputHash, content, metadata) {
281
- if (!POLL_TOOL_NAMES.has(toolName))
282
- return;
283
- if (`${toolName}\u0000${inputHash}` !== this.lastKey)
351
+ if (`${toolName}\u0000${inputHash}` !== this.lastKey || !this.lastIsPoll)
284
352
  return;
285
353
  this.pendingResult = false;
286
354
  if (isPollResultRunning(toolName, content, metadata)) {
@@ -293,13 +361,13 @@ export class ExactRepeatTracker {
293
361
  this.lastResultHash = h;
294
362
  }
295
363
  }
296
- /** Orchestrator glue (both tool loops): feed a batch's results back to the tracker. Non-poll
297
- * tools are ignored inside noteResult; the inputHash must be the same JSON.stringify(input)
298
- * the observe() call used. */
364
+ /** Orchestrator glue (both tool loops): feed a batch's results back to the tracker. Non-poll keys
365
+ * (neither a POLL_TOOL_NAMES tool nor a Bash poll hinted at observe) are ignored inside noteResult;
366
+ * the inputHash must be the same JSON.stringify(input) the observe() call used. */
299
367
  export function notePollResults(tracker, toolUseBlocks, toolResults) {
300
368
  const inputById = new Map(toolUseBlocks.map((b) => [b.id, b.input]));
301
369
  for (const tr of toolResults) {
302
- if (!POLL_TOOL_NAMES.has(tr.tool_name))
370
+ if (!POLL_TOOL_NAMES.has(tr.tool_name) && tr.tool_name !== 'Bash')
303
371
  continue;
304
372
  if (!inputById.has(tr.tool_use_id))
305
373
  continue;
@@ -1 +1 @@
1
- {"version":3,"file":"loopLadder.js","sourceRoot":"","sources":["../../src/training/loopLadder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loopLadder.js","sourceRoot":"","sources":["../../src/training/loopLadder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface PollPattern {
2
+ /** A wait combined with a read-only probe (and nothing else). */
3
+ isPoll: boolean;
4
+ /** Total foreground wait in seconds when known (sum of sleeps; the per-iteration sleep of a loop). */
5
+ waitSec?: number;
6
+ /** Stable identity of the probe (`curl localhost:5000/api/v1/config`, `tail /tmp/train.log`, …); set for
7
+ * bare read-only probes too so an immediate repeat can be recognized as a poll. */
8
+ probe?: string;
9
+ }
10
+ /**
11
+ * Recognize a poll-and-wait command. `isPoll` requires at least one wait AND at least one read-only probe
12
+ * and NO unsafe segment; `probe` is the identity of the first probe (set for bare probes too).
13
+ */
14
+ export declare function detectPollPattern(command: string): PollPattern;
15
+ //# sourceMappingURL=pollPattern.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pollPattern.d.ts","sourceRoot":"","sources":["../../src/training/pollPattern.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB,sGAAsG;IACtG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;wFACoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmLD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAc9D"}
@@ -0,0 +1,287 @@
1
+ /**
2
+ * pollPattern — R135 HB-POLL-LOOP (2026-09-13).
3
+ *
4
+ * Terminal-Bench 4.0 ctr-optimization (a 48-sim-hour task, 1 sim hour = 6 real minutes): the model had to
5
+ * observe an eval window hours later and polled with `sleep 115; curl -s …/config | python3 -c "…print(…)"`
6
+ * variants. The near-dup similarity lens scored every poll as a repeat: loop_escalation diversify x3 →
7
+ * loop_tool_block neardup-similarity x3 (redirect Read/Write/Edit) → "Bash is disabled" → the model routed
8
+ * around via CreateArtifactTool oneshot x14 and finalized WITHOUT observing its eval window.
9
+ *
10
+ * ONE pure helper: recognize a POLL — a WAIT (`sleep N`, `timeout N` wrapping a wait, `until`/`while … sleep`
11
+ * loop) combined with a READ-ONLY probe (curl/wget/http GET, cat/tail/ls/stat/ps/pgrep/docker ps|logs/
12
+ * kubectl get/systemctl status/nc -z/ss/netstat/test -f, `python3 -c` bodies that only GET and print). A
13
+ * bare read-only probe with NO wait is reported with its probe identity (isPoll=false) so the ladder can
14
+ * treat an immediate repeat of the same probe as a poll. CONSERVATIVE: any write verb (POST/PUT/DELETE,
15
+ * `-d`, a `>` redirect outside /tmp, rm/mv/cp, git commit/push, installs, build/test runners, scripts that
16
+ * are not obviously probes) or anything unrecognized → NOT a poll.
17
+ */
18
+ import { splitSegments } from './commandIdentity.js';
19
+ const LOOP_KEYWORDS = /^(until|while|done|do|then|else|elif|fi|if|for|in)\b\s*|^!\s*/;
20
+ const WRAPPERS = new Set(['time', 'nice', 'nohup', 'stdbuf', 'command', 'env', 'sudo']);
21
+ const NEUTRAL_HEADS = new Set(['cd', 'echo', 'printf', 'true', ':', 'export', 'set', 'date', 'pwd', 'sync']);
22
+ // Read-only probe heads (first token). Verbs of multi-verb tools are checked separately below.
23
+ const PROBE_HEADS = new Set([
24
+ 'cat', 'tail', 'head', 'ls', 'stat', 'wc', 'ps', 'pgrep', 'ss', 'netstat', 'lsof', 'df', 'du', 'free', 'uptime',
25
+ 'test', '[', '[[', 'grep', 'egrep', 'fgrep', 'rg', 'jq', 'nvidia-smi', 'top', 'nc', 'ncat', 'ping', 'dig', 'nslookup',
26
+ 'journalctl', 'id', 'whoami', 'hostname', 'file', 'find', 'md5sum', 'sha256sum', 'sqlite3',
27
+ ]);
28
+ const STATUS_HEADS = new Set(['tail', 'cat', 'ps', 'pgrep', 'ss', 'netstat', 'nc', 'ncat', 'lsof', 'nvidia-smi', 'top', 'journalctl', 'ping', 'df', 'free', 'uptime']);
29
+ const VERB_TOOLS = {
30
+ docker: new Set(['ps', 'logs', 'inspect', 'stats', 'top', 'port', 'images', 'version', 'info']),
31
+ kubectl: new Set(['get', 'describe', 'logs', 'top', 'version']),
32
+ systemctl: new Set(['status', 'is-active', 'is-enabled', 'is-failed', 'show', 'list-units']),
33
+ git: new Set(['status', 'log', 'diff', 'show', 'branch', 'rev-parse']),
34
+ podman: new Set(['ps', 'logs', 'inspect', 'stats']),
35
+ 'docker-compose': new Set(['ps', 'logs']),
36
+ };
37
+ const CURL_WRITE_FLAGS = /^(-d|--data(-\w+)?|-F|--form|-T|--upload-file|--json)$/;
38
+ const WGET_WRITE_FLAGS = /^(--post-data|--post-file|--method|--body-data|--body-file)/;
39
+ const URL_RE = /(?:https?:\/\/[^\s'"|;&)]+|\b(?:localhost|127\.0\.0\.1|0\.0\.0\.0)(?::\d+)?(?:\/[^\s'"|;&)]*)?)/;
40
+ const PY_WRITE_RE = /\b(requests\.(post|put|delete|patch)|urllib\.request\.Request\([^)]*data=|urlopen\([^)]*data=|method\s*=\s*['"](POST|PUT|DELETE|PATCH)|open\([^)]*['"][wax][b+]*['"]|\.write\(|json\.dump\(|subprocess|os\.system|os\.(remove|unlink|rename|makedirs|mkdir)|shutil\.|Popen|pickle\.dump\()/;
41
+ const PY_PROBE_RE = /\b(print\(|requests\.(get|head)\(|urlopen\(|sys\.stdin|json\.load\()/;
42
+ /** `sleep 115` → 115, `sleep 2m` → 120, `sleep 1.5` → 1.5; undefined when not a literal. */
43
+ function parseSeconds(tok) {
44
+ if (!tok)
45
+ return undefined;
46
+ const m = /^(\d+(?:\.\d+)?)([smhd]?)$/.exec(tok);
47
+ if (!m)
48
+ return undefined;
49
+ const n = parseFloat(m[1]);
50
+ const mult = { '': 1, s: 1, m: 60, h: 3600, d: 86400 }[m[2]];
51
+ return n * mult;
52
+ }
53
+ /** Whitespace tokenizer keeping quoted spans (unquoted text) as one token. */
54
+ function tokenize(seg) {
55
+ const toks = [];
56
+ let cur = '';
57
+ let inTok = false;
58
+ let quote = null;
59
+ for (let i = 0; i < seg.length; i++) {
60
+ const ch = seg[i];
61
+ if (quote) {
62
+ if (ch === quote) {
63
+ quote = null;
64
+ continue;
65
+ }
66
+ if (ch === '\\' && quote === '"' && i + 1 < seg.length) {
67
+ cur += seg[++i];
68
+ continue;
69
+ }
70
+ cur += ch;
71
+ continue;
72
+ }
73
+ if (ch === '"' || ch === "'") {
74
+ quote = ch;
75
+ inTok = true;
76
+ continue;
77
+ }
78
+ if (ch === '\\' && i + 1 < seg.length) {
79
+ cur += seg[++i];
80
+ inTok = true;
81
+ continue;
82
+ }
83
+ if (/\s/.test(ch)) {
84
+ if (inTok) {
85
+ toks.push(cur);
86
+ cur = '';
87
+ inTok = false;
88
+ }
89
+ continue;
90
+ }
91
+ cur += ch;
92
+ inTok = true;
93
+ }
94
+ if (inTok)
95
+ toks.push(cur);
96
+ return toks;
97
+ }
98
+ /** A `>`/`>>` redirect to anything but /dev/null or /tmp is a write. Returns the segment with redirects stripped, or null. */
99
+ function stripRedirects(seg) {
100
+ let unsafe = false;
101
+ const out = seg.replace(/(?:\d*|&)>{1,2}\s*([^\s;|&]+)/g, (_m, target) => {
102
+ if (target === '/dev/null' || target === '&1' || target === '&2' || target.startsWith('/tmp/'))
103
+ return ' ';
104
+ unsafe = true;
105
+ return ' ';
106
+ }).replace(/<\s*[^\s;|&]+/g, ' ');
107
+ return unsafe ? null : out;
108
+ }
109
+ function outputTargetOk(target) {
110
+ return !!target && (target === '-' || target === '/dev/null' || target.startsWith('/tmp/'));
111
+ }
112
+ function probeId(head, args) {
113
+ const url = URL_RE.exec(args.join(' '))?.[0];
114
+ if (url)
115
+ return `${head} ${url.replace(/^https?:\/\//, '')}`;
116
+ const target = args.find((a) => !a.startsWith('-'));
117
+ return target ? `${head} ${target}` : head;
118
+ }
119
+ function classifyCurl(args) {
120
+ for (let i = 0; i < args.length; i++) {
121
+ const a = args[i];
122
+ if (CURL_WRITE_FLAGS.test(a))
123
+ return { kind: 'unsafe' };
124
+ if (a === '-X' || a === '--request') {
125
+ if (!/^(GET|HEAD)$/i.test(args[i + 1] ?? ''))
126
+ return { kind: 'unsafe' };
127
+ i++;
128
+ continue;
129
+ }
130
+ if (/^(-X|--request=)/.test(a) && !/^(-X|--request=)(GET|HEAD)$/i.test(a))
131
+ return { kind: 'unsafe' };
132
+ if (a === '-o' || a === '--output') {
133
+ if (!outputTargetOk(args[i + 1]))
134
+ return { kind: 'unsafe' };
135
+ i++;
136
+ continue;
137
+ }
138
+ if (a === '-O' || a === '--remote-name')
139
+ return { kind: 'unsafe' };
140
+ }
141
+ return { kind: 'probe', probe: probeId('curl', args), status: true };
142
+ }
143
+ function classifyWget(args) {
144
+ let stdout = false;
145
+ for (let i = 0; i < args.length; i++) {
146
+ const a = args[i];
147
+ if (WGET_WRITE_FLAGS.test(a))
148
+ return { kind: 'unsafe' };
149
+ if (a === '--spider')
150
+ stdout = true;
151
+ if (a === '-O' || a === '--output-document') {
152
+ if (!outputTargetOk(args[i + 1]))
153
+ return { kind: 'unsafe' };
154
+ stdout = true;
155
+ i++;
156
+ continue;
157
+ }
158
+ if (/^-q?O-$/.test(a) || /^--output-document=/.test(a)) {
159
+ if (a.endsWith('-') || outputTargetOk(a.split('=')[1]))
160
+ stdout = true;
161
+ else
162
+ return { kind: 'unsafe' };
163
+ }
164
+ }
165
+ return stdout ? { kind: 'probe', probe: probeId('wget', args), status: true } : { kind: 'unsafe' }; // a plain wget downloads a file into cwd
166
+ }
167
+ function classifyHttpie(args) {
168
+ const method = /^[A-Z]+$/.test(args[0] ?? '') ? args[0] : 'GET';
169
+ if (!/^(GET|HEAD)$/.test(method))
170
+ return { kind: 'unsafe' };
171
+ if (args.some((a) => /^[\w-]+(:=|=)(?!=)/.test(a) && !a.includes(':')))
172
+ return { kind: 'unsafe' }; // request items = an implicit POST
173
+ return { kind: 'probe', probe: probeId('http', args), status: true };
174
+ }
175
+ /** `python3 -c BODY`: a probe only when the body GETs/prints and never writes. */
176
+ function classifyPythonInline(body) {
177
+ if (PY_WRITE_RE.test(body))
178
+ return { kind: 'unsafe' };
179
+ const sleep = /time\.sleep\(\s*(\d+(?:\.\d+)?)\s*\)/.exec(body);
180
+ if (!PY_PROBE_RE.test(body)) {
181
+ return sleep && /^\s*import\s+time\s*;?\s*time\.sleep\([^)]*\)\s*$/.test(body) ? { kind: 'wait', waitSec: parseFloat(sleep[1]) } : { kind: 'unsafe' };
182
+ }
183
+ const url = URL_RE.exec(body)?.[0];
184
+ return { kind: 'probe', probe: url ? `python3 ${url.replace(/^https?:\/\//, '')}` : 'python3 -c probe', ...(sleep ? { waitSec: parseFloat(sleep[1]) } : {}) };
185
+ }
186
+ function classifySegment(raw) {
187
+ let bare = raw.trim();
188
+ if (/^for\s+\w+\s+in\b/.test(bare))
189
+ return { kind: 'neutral' }; // `for i in 1 2 3` header (the body segments are classified on their own)
190
+ for (let prev = ''; prev !== bare;) {
191
+ prev = bare;
192
+ bare = bare.replace(LOOP_KEYWORDS, '').trim();
193
+ }
194
+ const stripped = stripRedirects(bare);
195
+ if (stripped === null)
196
+ return { kind: 'unsafe' };
197
+ let toks = tokenize(stripped.trim());
198
+ while (toks.length && /^[A-Za-z_]\w*=/.test(toks[0]))
199
+ toks = toks.slice(1); // VAR=x prefix
200
+ if (toks.length === 0)
201
+ return { kind: 'neutral' };
202
+ let head = toks[0];
203
+ // Wrappers: `timeout N cmd` is a wait only when cmd is itself a wait / blocking probe; other wrappers are transparent.
204
+ let timeoutSec;
205
+ for (;;) {
206
+ if (head === 'timeout') {
207
+ let j = 1;
208
+ while (toks[j]?.startsWith('-'))
209
+ j += /^(-s|--signal|-k|--kill-after)$/.test(toks[j]) ? 2 : 1;
210
+ timeoutSec = parseSeconds(toks[j]);
211
+ toks = toks.slice(j + 1);
212
+ head = toks[0] ?? '';
213
+ continue;
214
+ }
215
+ if (WRAPPERS.has(head)) {
216
+ toks = toks.slice(1);
217
+ while (toks[0]?.startsWith('-'))
218
+ toks = toks.slice(1);
219
+ head = toks[0] ?? '';
220
+ continue;
221
+ }
222
+ break;
223
+ }
224
+ if (!head)
225
+ return { kind: 'neutral' };
226
+ const args = toks.slice(1);
227
+ if (head === 'sleep')
228
+ return { kind: 'wait', waitSec: parseSeconds(args[0]) };
229
+ if (/^(bash|sh|zsh|dash)$/.test(head) && args[0] === '-c' && args[1]) {
230
+ const inner = detectPollPattern(args[1]);
231
+ if (inner.isPoll)
232
+ return { kind: 'probe', probe: inner.probe, waitSec: inner.waitSec ?? timeoutSec, status: true };
233
+ return { kind: 'unsafe' };
234
+ }
235
+ if (/^(python[\d.]*|pypy[\d]*)$/.test(head)) {
236
+ const c = args.indexOf('-c');
237
+ return c >= 0 && args[c + 1] ? classifyPythonInline(args[c + 1]) : { kind: 'unsafe' };
238
+ }
239
+ if (head === 'curl')
240
+ return classifyCurl(args);
241
+ if (head === 'wget')
242
+ return classifyWget(args);
243
+ if (head === 'http' || head === 'https' || head === 'xh')
244
+ return classifyHttpie(args);
245
+ if (NEUTRAL_HEADS.has(head))
246
+ return { kind: 'neutral' };
247
+ const verbs = VERB_TOOLS[head];
248
+ if (verbs)
249
+ return verbs.has(args[0] ?? '') ? { kind: 'probe', probe: probeId(`${head} ${args[0]}`, args.slice(1)), status: head !== 'git' } : { kind: 'unsafe' };
250
+ if (PROBE_HEADS.has(head)) {
251
+ if (head === 'sqlite3' && !args.some((a) => /^\s*select\b/i.test(a)))
252
+ return { kind: 'unsafe' };
253
+ if ((head === 'nc' || head === 'ncat') && !args.includes('-z'))
254
+ return { kind: 'unsafe' };
255
+ if (head === 'find' && args.some((a) => /^-(delete|exec|execdir|ok)$/.test(a)))
256
+ return { kind: 'unsafe' };
257
+ if (head === 'grep' && args.includes('-r') && args.length > 8)
258
+ return { kind: 'unsafe' }; // a scan, not a status probe
259
+ const blocking = head === 'tail' && args.some((a) => /^-[a-zA-Z]*[fF]/.test(a));
260
+ return { kind: 'probe', probe: probeId(head, args), status: STATUS_HEADS.has(head), ...(blocking && timeoutSec ? { waitSec: timeoutSec } : {}) };
261
+ }
262
+ return { kind: 'unsafe' };
263
+ }
264
+ /**
265
+ * Recognize a poll-and-wait command. `isPoll` requires at least one wait AND at least one read-only probe
266
+ * and NO unsafe segment; `probe` is the identity of the first probe (set for bare probes too).
267
+ */
268
+ export function detectPollPattern(command) {
269
+ const cmd = String(command ?? '').trim();
270
+ if (!cmd)
271
+ return { isPoll: false };
272
+ const loop = /\b(until|while)\b[\s\S]*\bdo\b[\s\S]*\bdone\b/.test(cmd);
273
+ const segs = splitSegments(cmd).map(classifySegment);
274
+ if (segs.some((s) => s.kind === 'unsafe'))
275
+ return { isPoll: false };
276
+ const probes = segs.filter((s) => s.kind === 'probe');
277
+ const probe = probes[0]?.probe;
278
+ const waits = segs.filter((s) => s.kind === 'wait' || s.waitSec !== undefined);
279
+ if (probes.length === 0)
280
+ return { isPoll: false };
281
+ if (waits.length === 0 && !loop)
282
+ return { isPoll: false, ...(probes[0].status ? { probe } : {}) }; // bare status probe: identity only
283
+ const known = waits.map((w) => w.waitSec).filter((n) => typeof n === 'number' && Number.isFinite(n));
284
+ const waitSec = known.length ? (loop ? Math.max(...known) : known.reduce((a, b) => a + b, 0)) : undefined;
285
+ return { isPoll: true, ...(waitSec !== undefined ? { waitSec } : {}), probe };
286
+ }
287
+ //# sourceMappingURL=pollPattern.js.map