instar 1.3.336 → 1.3.338

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.
@@ -0,0 +1,79 @@
1
+ /**
2
+ * OwnerSuspectBreaker — the per-peer circuit breaker behind the SessionRouter's
3
+ * `markOwnerSuspect` hook ("No Unbounded Loops" / P19).
4
+ *
5
+ * The router's forward path already had the SHAPE of a breaker: on delivery
6
+ * retry exhaustion it calls `markOwnerSuspect(owner)` before re-placing the
7
+ * message. But the hook was NEVER WIRED in production (the dep is optional and
8
+ * no implementation existed) — "constructed but inert". The consequence: every
9
+ * session owned by a slow-or-dead peer independently re-paid the full retry
10
+ * tax (3 attempts × backoff ≈ 4.5s+) per message, because `isMachineAlive`
11
+ * reads only capacity heartbeats, which a slow-but-alive peer keeps passing.
12
+ *
13
+ * This class is the wiring's missing half. Half-open TTL semantics:
14
+ *
15
+ * markSuspect(peer) — start/extend a suspect window (default 30s). The
16
+ * FIRST mark of an episode logs once; an episode
17
+ * sustained past signalAfterMs raises ONE degradation
18
+ * signal (per-peer FailureEpisodeLatch — P19 cond. 4).
19
+ * isSuspect(peer) — true inside the window. The composed isMachineAlive
20
+ * then short-circuits dispatches for ALL of that
21
+ * peer's sessions straight to the existing failover
22
+ * re-place path — no per-message retry tax repaid.
23
+ * recordSuccess(peer) — a delivery reached the peer: window cleared,
24
+ * recovery logged once, latch re-armed.
25
+ *
26
+ * After the TTL expires the breaker is HALF-OPEN: the next message tries the
27
+ * peer for real (paying one retry cycle); success clears, failure re-marks.
28
+ * The peer is never written off permanently — the TTL is the backoff, the
29
+ * suspect state is the breaker, the per-message retry config is the cap.
30
+ *
31
+ * Deliberately POLICY-NEUTRAL: what happens to messages while a peer is
32
+ * suspect (today: the router's existing re-place path) is the wiring's choice
33
+ * — the queue-vs-replace stability policy is a separate operator decision
34
+ * <!-- tracked: CMT-1109 -->. Pure: injectable clock, per-peer bounded state.
35
+ */
36
+ export interface OwnerSuspectBreakerOpts {
37
+ /** Suspect window per mark (the half-open backoff). Default 30s. */
38
+ suspectTtlMs?: number;
39
+ /** Sustained-suspicion threshold for the one-per-episode degradation signal. Default 10min. */
40
+ signalAfterMs?: number;
41
+ now?: () => number;
42
+ logger?: (msg: string) => void;
43
+ /** One-per-episode sustained-suspicion sink (wired to DegradationReporter). */
44
+ reportSustained?: (info: {
45
+ machineId: string;
46
+ suspectForMs: number;
47
+ marks: number;
48
+ }) => void;
49
+ }
50
+ export declare class OwnerSuspectBreaker {
51
+ private readonly ttlMs;
52
+ private readonly now;
53
+ private readonly opts;
54
+ /** Per-peer suspect-window end (ms epoch). Deleted on success. */
55
+ private suspectUntil;
56
+ /** Per-peer episode accounting (created on first mark, deleted on success). */
57
+ private episodes;
58
+ constructor(opts?: OwnerSuspectBreakerOpts);
59
+ private log;
60
+ /** Delivery retries to this peer exhausted — open its suspect window.
61
+ *
62
+ * ABSOLUTE per-episode TTL: a mark that arrives while a window is ALREADY open
63
+ * does NOT push the window end forward. Otherwise a steady message stream
64
+ * arriving faster than the TTL would re-extend the window on every dispatch
65
+ * (each suspect dispatch re-enters dispatchOne's dead-owner branch, which
66
+ * re-calls markOwnerSuspect), so `isSuspect` would never go false at the
67
+ * moment a message arrives — the half-open re-probe (the ONLY path that ever
68
+ * re-attempts delivery and thus the ONLY path that can clear suspicion) would
69
+ * never be reached, leaving a fully-RECOVERED peer suspect forever and
70
+ * force-failing-over all its sessions on every message. The episode latch
71
+ * still records each mark (sustained-suspicion accounting), but the window
72
+ * end is fixed at the first mark of each TTL period. */
73
+ markSuspect(machineId: string): void;
74
+ /** Inside an open suspect window? (Half-open after the TTL — callers re-probe.) */
75
+ isSuspect(machineId: string): boolean;
76
+ /** A delivery reached the peer — close the episode and re-arm. */
77
+ recordSuccess(machineId: string): void;
78
+ }
79
+ //# sourceMappingURL=OwnerSuspectBreaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OwnerSuspectBreaker.d.ts","sourceRoot":"","sources":["../../src/core/OwnerSuspectBreaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAIH,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+FAA+F;IAC/F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,+EAA+E;IAC/E,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC9F;AAKD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,kEAAkE;IAClE,OAAO,CAAC,YAAY,CAA6B;IACjD,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,CAA0C;gBAE9C,IAAI,GAAE,uBAA4B;IAM9C,OAAO,CAAC,GAAG;IAIX;;;;;;;;;;;;4DAYwD;IACxD,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAsBpC,mFAAmF;IACnF,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAKrC,kEAAkE;IAClE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CASvC"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * OwnerSuspectBreaker — the per-peer circuit breaker behind the SessionRouter's
3
+ * `markOwnerSuspect` hook ("No Unbounded Loops" / P19).
4
+ *
5
+ * The router's forward path already had the SHAPE of a breaker: on delivery
6
+ * retry exhaustion it calls `markOwnerSuspect(owner)` before re-placing the
7
+ * message. But the hook was NEVER WIRED in production (the dep is optional and
8
+ * no implementation existed) — "constructed but inert". The consequence: every
9
+ * session owned by a slow-or-dead peer independently re-paid the full retry
10
+ * tax (3 attempts × backoff ≈ 4.5s+) per message, because `isMachineAlive`
11
+ * reads only capacity heartbeats, which a slow-but-alive peer keeps passing.
12
+ *
13
+ * This class is the wiring's missing half. Half-open TTL semantics:
14
+ *
15
+ * markSuspect(peer) — start/extend a suspect window (default 30s). The
16
+ * FIRST mark of an episode logs once; an episode
17
+ * sustained past signalAfterMs raises ONE degradation
18
+ * signal (per-peer FailureEpisodeLatch — P19 cond. 4).
19
+ * isSuspect(peer) — true inside the window. The composed isMachineAlive
20
+ * then short-circuits dispatches for ALL of that
21
+ * peer's sessions straight to the existing failover
22
+ * re-place path — no per-message retry tax repaid.
23
+ * recordSuccess(peer) — a delivery reached the peer: window cleared,
24
+ * recovery logged once, latch re-armed.
25
+ *
26
+ * After the TTL expires the breaker is HALF-OPEN: the next message tries the
27
+ * peer for real (paying one retry cycle); success clears, failure re-marks.
28
+ * The peer is never written off permanently — the TTL is the backoff, the
29
+ * suspect state is the breaker, the per-message retry config is the cap.
30
+ *
31
+ * Deliberately POLICY-NEUTRAL: what happens to messages while a peer is
32
+ * suspect (today: the router's existing re-place path) is the wiring's choice
33
+ * — the queue-vs-replace stability policy is a separate operator decision
34
+ * <!-- tracked: CMT-1109 -->. Pure: injectable clock, per-peer bounded state.
35
+ */
36
+ import { FailureEpisodeLatch } from './FailureEpisodeLatch.js';
37
+ const DEFAULT_SUSPECT_TTL_MS = 30_000;
38
+ const DEFAULT_SIGNAL_AFTER_MS = 10 * 60_000;
39
+ export class OwnerSuspectBreaker {
40
+ ttlMs;
41
+ now;
42
+ opts;
43
+ /** Per-peer suspect-window end (ms epoch). Deleted on success. */
44
+ suspectUntil = new Map();
45
+ /** Per-peer episode accounting (created on first mark, deleted on success). */
46
+ episodes = new Map();
47
+ constructor(opts = {}) {
48
+ this.opts = opts;
49
+ this.ttlMs = opts.suspectTtlMs ?? DEFAULT_SUSPECT_TTL_MS;
50
+ this.now = opts.now ?? Date.now;
51
+ }
52
+ log(m) {
53
+ this.opts.logger?.(`[owner-suspect] ${m}`);
54
+ }
55
+ /** Delivery retries to this peer exhausted — open its suspect window.
56
+ *
57
+ * ABSOLUTE per-episode TTL: a mark that arrives while a window is ALREADY open
58
+ * does NOT push the window end forward. Otherwise a steady message stream
59
+ * arriving faster than the TTL would re-extend the window on every dispatch
60
+ * (each suspect dispatch re-enters dispatchOne's dead-owner branch, which
61
+ * re-calls markOwnerSuspect), so `isSuspect` would never go false at the
62
+ * moment a message arrives — the half-open re-probe (the ONLY path that ever
63
+ * re-attempts delivery and thus the ONLY path that can clear suspicion) would
64
+ * never be reached, leaving a fully-RECOVERED peer suspect forever and
65
+ * force-failing-over all its sessions on every message. The episode latch
66
+ * still records each mark (sustained-suspicion accounting), but the window
67
+ * end is fixed at the first mark of each TTL period. */
68
+ markSuspect(machineId) {
69
+ if (!this.isSuspect(machineId)) {
70
+ this.suspectUntil.set(machineId, this.now() + this.ttlMs);
71
+ }
72
+ let latch = this.episodes.get(machineId);
73
+ if (!latch) {
74
+ latch = new FailureEpisodeLatch({
75
+ signalAfterMs: this.opts.signalAfterMs ?? DEFAULT_SIGNAL_AFTER_MS,
76
+ now: this.now,
77
+ });
78
+ this.episodes.set(machineId, latch);
79
+ }
80
+ const f = latch.recordFailure();
81
+ if (f.firstOfEpisode) {
82
+ this.log(`owner ${machineId} SUSPECT (delivery retries exhausted) — short-circuiting its sessions' dispatches for ${Math.round(this.ttlMs / 1000)}s windows until a delivery succeeds`);
83
+ }
84
+ if (f.shouldSignal) {
85
+ this.log(`owner ${machineId} suspect for ${Math.round(f.failingForMs / 60_000)}min (${f.failures} marks) — signaling once; half-open re-probes continue`);
86
+ this.opts.reportSustained?.({ machineId, suspectForMs: f.failingForMs, marks: f.failures });
87
+ }
88
+ }
89
+ /** Inside an open suspect window? (Half-open after the TTL — callers re-probe.) */
90
+ isSuspect(machineId) {
91
+ const until = this.suspectUntil.get(machineId);
92
+ return until !== undefined && this.now() < until;
93
+ }
94
+ /** A delivery reached the peer — close the episode and re-arm. */
95
+ recordSuccess(machineId) {
96
+ this.suspectUntil.delete(machineId);
97
+ const latch = this.episodes.get(machineId);
98
+ if (latch) {
99
+ const s = latch.recordSuccess();
100
+ if (s.recovered)
101
+ this.log(`owner ${machineId} recovered after ${s.failures} suspect mark(s)`);
102
+ this.episodes.delete(machineId);
103
+ }
104
+ }
105
+ }
106
+ //# sourceMappingURL=OwnerSuspectBreaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OwnerSuspectBreaker.js","sourceRoot":"","sources":["../../src/core/OwnerSuspectBreaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAa/D,MAAM,sBAAsB,GAAG,MAAM,CAAC;AACtC,MAAM,uBAAuB,GAAG,EAAE,GAAG,MAAM,CAAC;AAE5C,MAAM,OAAO,mBAAmB;IACb,KAAK,CAAS;IACd,GAAG,CAAe;IAClB,IAAI,CAA0B;IAC/C,kEAAkE;IAC1D,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IACjD,+EAA+E;IACvE,QAAQ,GAAG,IAAI,GAAG,EAA+B,CAAC;IAE1D,YAAY,OAAgC,EAAE;QAC5C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY,IAAI,sBAAsB,CAAC;QACzD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IAClC,CAAC;IAEO,GAAG,CAAC,CAAS;QACnB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;;;;;;;;4DAYwD;IACxD,WAAW,CAAC,SAAiB;QAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,IAAI,mBAAmB,CAAC;gBAC9B,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,uBAAuB;gBACjE,GAAG,EAAE,IAAI,CAAC,GAAG;aACd,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACtC,CAAC;QACD,MAAM,CAAC,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC;QAChC,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC;YACrB,IAAI,CAAC,GAAG,CAAC,SAAS,SAAS,yFAAyF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,qCAAqC,CAAC,CAAC;QAC1L,CAAC;QACD,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,CAAC,SAAS,SAAS,gBAAgB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,wDAAwD,CAAC,CAAC;YAC1J,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC;IAED,mFAAmF;IACnF,SAAS,CAAC,SAAiB;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/C,OAAO,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;IACnD,CAAC;IAED,kEAAkE;IAClE,aAAa,CAAC,SAAiB;QAC7B,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,SAAS;gBAAE,IAAI,CAAC,GAAG,CAAC,SAAS,SAAS,oBAAoB,CAAC,CAAC,QAAQ,kBAAkB,CAAC,CAAC;YAC9F,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}
@@ -47,6 +47,16 @@ import { detectCodexPath, detectTmuxPath } from './Config.js';
47
47
  import { DegradationReporter } from '../monitoring/DegradationReporter.js';
48
48
  import { MigratorStepEngine, } from './MigratorStepEngine.js';
49
49
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
50
+ /**
51
+ * CLAUDE.md note for the second wedge-signature family (2026-06-05 EXO
52
+ * incident) + the API fresh-respawn lever. Appended to NEW installs as part of
53
+ * the Stuck-Context Recovery section, and patched onto agents that already
54
+ * have the section. Marker for idempotency: 'AUP-rejection wedge'.
55
+ */
56
+ const AUP_WEDGE_CLAUDE_MD_NOTE = `
57
+ - **AUP-rejection wedge (second signature, 2026-06-05):** a transcript that accumulates content tripping the API's Usage Policy classifier (e.g. literal red-team / prompt-injection test payloads from security-harness work) gets EVERY reply rejected with \`API Error: … appears to violate our Usage Policy\` — same permanent death, same fresh-respawn recovery. The sentinel requires the signature on MORE THAN ONE line (the loop always repeats; a benign one-off rejection doesn't). Prevention: keep literal adversarial payloads in files on disk and reference them by path — never paste them into a conversation.
58
+ - **Fresh respawn via API:** \`POST /sessions/refresh\` with \`{"sessionName":"<tmux-name>","fresh":true,"reason":"…"}\` kills + respawns WITHOUT \`--resume\` (clears the topic's resume UUID first). Use it when a transcript is poisoned — a normal refresh would re-wedge.
59
+ `;
50
60
  export class PostUpdateMigrator {
51
61
  config;
52
62
  /**
@@ -3234,9 +3244,10 @@ A secret you give me on one machine — a Telegram token, an API key, a GitHub P
3234
3244
  result.upgraded.push('CLAUDE.md: added secret-sync push-opt-in safety line');
3235
3245
  }
3236
3246
  // ContextWedgeSentinel — the 4th silently-stopped sentinel. Tells the agent
3237
- // about the thinking-block-400 wedge + that auto-recovery is opt-in. Without
3238
- // it, an agent asked "why did my session keep failing instantly / what is
3239
- // the thinking-block error?" has no grounded answer. Idempotent via marker.
3247
+ // about the transcript fast-fail wedges (thinking-block 400 + AUP-rejection
3248
+ // loop) + that auto-recovery is opt-in. Without it, an agent asked "why did
3249
+ // my session keep failing instantly / what is the thinking-block error?"
3250
+ // has no grounded answer. Idempotent via marker.
3240
3251
  if (!content.includes('ContextWedgeSentinel') && !content.includes('Stuck-Context Recovery (thinking-block wedge)')) {
3241
3252
  const section = `
3242
3253
  ## Stuck-Context Recovery (thinking-block wedge)
@@ -3248,13 +3259,22 @@ A nudge can't fix this (re-engaging re-sends the corrupted turn). Recovery is a
3248
3259
  - **Detection + audit are default-ON housekeeping** — every transition (detected / recovered / dry-run / false-alarm / escalated) lands in \`logs/sentinel-events.jsonl\`; the user sees nothing.
3249
3260
  - **Auto-recovery is OPT-IN** (it kills + respawns a session). It rides the Graduated Feature Rollout track and ships dark. Turn it on in \`.instar/config.json\`: \`{"monitoring": {"contextWedgeSentinel": {"autoRecovery": {"enabled": true, "dryRun": false}}}}\` (use \`dryRun: true\` first to log what it WOULD respawn). When OFF, a confirmed wedge escalates (gated by \`sentinelTelegramEscalation\`) so you can restart it yourself.
3250
3261
  - If a user asks "why did my session keep failing / get stuck on a thinking error?" — read \`logs/sentinel-events.jsonl\` (filter \`context-wedge\`) and explain the above. Spec: \`docs/specs/context-wedge-sentinel.md\`.
3251
- `;
3262
+ ${AUP_WEDGE_CLAUDE_MD_NOTE}`;
3252
3263
  content += '\n' + section;
3253
3264
  patched = true;
3254
3265
  result.upgraded.push('CLAUDE.md: added Stuck-Context Recovery section');
3255
3266
  }
3267
+ else if (content.includes('ContextWedgeSentinel') && !content.includes('AUP-rejection wedge')) {
3268
+ // Agents that already got the Stuck-Context section predate the second
3269
+ // signature family (the 2026-06-05 EXO AUP-rejection incident). Append
3270
+ // the note so they know about it + the API fresh-respawn lever.
3271
+ // Idempotent via the 'AUP-rejection wedge' marker.
3272
+ content += '\n' + AUP_WEDGE_CLAUDE_MD_NOTE;
3273
+ patched = true;
3274
+ result.upgraded.push('CLAUDE.md: added AUP-rejection wedge + fresh-respawn API note');
3275
+ }
3256
3276
  else {
3257
- result.skipped.push('CLAUDE.md: Stuck-Context Recovery section already present');
3277
+ result.skipped.push('CLAUDE.md: Stuck-Context Recovery section already current');
3258
3278
  }
3259
3279
  // Reap-log (UNIFIED-SESSION-LIFECYCLE §P4) — tells the agent the durable
3260
3280
  // "why did my session vanish?" answer exists and where to read it. Without