instar 1.3.60 → 1.3.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +44 -2
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +26 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/InitiativeTracker.d.ts +10 -0
- package/dist/core/InitiativeTracker.d.ts.map +1 -1
- package/dist/core/InitiativeTracker.js +18 -0
- package/dist/core/InitiativeTracker.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +23 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionRefresh.d.ts +10 -0
- package/dist/core/SessionRefresh.d.ts.map +1 -1
- package/dist/core/SessionRefresh.js +12 -2
- package/dist/core/SessionRefresh.js.map +1 -1
- package/dist/core/types.d.ts +62 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/CiFailurePoller.d.ts +69 -0
- package/dist/monitoring/CiFailurePoller.d.ts.map +1 -0
- package/dist/monitoring/CiFailurePoller.js +167 -0
- package/dist/monitoring/CiFailurePoller.js.map +1 -0
- package/dist/monitoring/ContextWedgeSentinel.d.ts +118 -0
- package/dist/monitoring/ContextWedgeSentinel.d.ts.map +1 -0
- package/dist/monitoring/ContextWedgeSentinel.js +238 -0
- package/dist/monitoring/ContextWedgeSentinel.js.map +1 -0
- package/dist/monitoring/FailureAnalyzer.d.ts.map +1 -1
- package/dist/monitoring/FailureAnalyzer.js +10 -1
- package/dist/monitoring/FailureAnalyzer.js.map +1 -1
- package/dist/monitoring/FailureAttributionEngine.d.ts.map +1 -1
- package/dist/monitoring/FailureAttributionEngine.js +2 -1
- package/dist/monitoring/FailureAttributionEngine.js.map +1 -1
- package/dist/monitoring/FailureLedger.d.ts +14 -1
- package/dist/monitoring/FailureLedger.d.ts.map +1 -1
- package/dist/monitoring/FailureLedger.js +43 -4
- package/dist/monitoring/FailureLedger.js.map +1 -1
- package/dist/monitoring/SentinelNotifier.d.ts +1 -1
- package/dist/monitoring/SentinelNotifier.d.ts.map +1 -1
- package/dist/monitoring/SentinelNotifier.js.map +1 -1
- package/dist/monitoring/sentinelWiring.d.ts +23 -0
- package/dist/monitoring/sentinelWiring.d.ts.map +1 -1
- package/dist/monitoring/sentinelWiring.js +36 -0
- package/dist/monitoring/sentinelWiring.js.map +1 -1
- package/dist/server/AgentServer.d.ts +1 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +52 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +19 -19
- package/upgrades/1.3.61.md +32 -0
- package/upgrades/1.3.62.md +89 -0
- package/upgrades/side-effects/context-wedge-sentinel.md +69 -0
- package/upgrades/side-effects/failure-learning-ingestion-sources.md +59 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CiFailurePoller — Ingestion-sources spec §3.1.
|
|
3
|
+
*
|
|
4
|
+
* Periodically lists recent CI runs via `gh` and files the failed ones into the
|
|
5
|
+
* FailureLedger. Read-only against GitHub; never mutates a repo. Fail-open: any
|
|
6
|
+
* error (gh missing/unauthed/rate-limited/non-JSON) logs and skips the tick.
|
|
7
|
+
*
|
|
8
|
+
* Safety (spec §3.1/§4.1):
|
|
9
|
+
* - `gh` is invoked arg-array only (never a shell string); `repo` parsed from
|
|
10
|
+
* the git remote is validated against a strict owner/name regex before use.
|
|
11
|
+
* - Attribution is exact-OID (headSha → InitiativeTracker.findByMergeCommit),
|
|
12
|
+
* never a branch-name substring match. Unmapped → inferred / noFeatureLink.
|
|
13
|
+
* - Loop self-exclusion (§4.3): a run mapped to a `failure-learning-loop`-origin
|
|
14
|
+
* initiative is skipped (don't ingest the loop's own fix-PR failures).
|
|
15
|
+
* - Flaky guard (§3.1): per head SHA, only the LATEST run is considered; if a
|
|
16
|
+
* later run for that SHA succeeded, the failure is treated as recovered and
|
|
17
|
+
* skipped (not filed as a process failure).
|
|
18
|
+
* - Per-tick write cap (§5) bounds the ledger writes per poll.
|
|
19
|
+
* - Lease-gated (§5): runs only on the fenced-lease holder so a fleet polls
|
|
20
|
+
* GitHub once, not once per machine.
|
|
21
|
+
*
|
|
22
|
+
* filedBy is the constant `source:ci` (§5) so CI failures share one analyzer
|
|
23
|
+
* "session" identity → they can never alone satisfy the diversity gate.
|
|
24
|
+
*/
|
|
25
|
+
import { execFileSync } from 'node:child_process';
|
|
26
|
+
const REPO_RE = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
|
|
27
|
+
/** Deterministic CI job-name → FailureCategory (fixed allow-list, never raw name). */
|
|
28
|
+
export function ciCategoryFromName(name) {
|
|
29
|
+
const n = (name || '').toLowerCase();
|
|
30
|
+
if (/\b(test|spec|vitest|jest|e2e|unit|integration)\b/.test(n))
|
|
31
|
+
return 'test-failure';
|
|
32
|
+
if (/\b(build|compile|tsc|lint|type.?check|bundle)\b/.test(n))
|
|
33
|
+
return 'build-failure';
|
|
34
|
+
return 'unknown';
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Keep only genuine current failures: group runs by head SHA, take the LATEST
|
|
38
|
+
* by createdAt per SHA, and return those whose latest conclusion is 'failure'.
|
|
39
|
+
* A SHA whose latest run succeeded (a re-run recovery) is dropped (flaky guard).
|
|
40
|
+
*/
|
|
41
|
+
export function currentFailures(runs) {
|
|
42
|
+
const latestBySha = new Map();
|
|
43
|
+
for (const r of runs) {
|
|
44
|
+
const sha = r.headSha;
|
|
45
|
+
if (!sha)
|
|
46
|
+
continue;
|
|
47
|
+
const prev = latestBySha.get(sha);
|
|
48
|
+
if (!prev || String(r.createdAt || '') > String(prev.createdAt || ''))
|
|
49
|
+
latestBySha.set(sha, r);
|
|
50
|
+
}
|
|
51
|
+
return [...latestBySha.values()].filter((r) => r.conclusion === 'failure');
|
|
52
|
+
}
|
|
53
|
+
export class CiFailurePoller {
|
|
54
|
+
ledger;
|
|
55
|
+
resolveByMergeCommit;
|
|
56
|
+
resolveRepo;
|
|
57
|
+
runGh;
|
|
58
|
+
isLeaseHolder;
|
|
59
|
+
intervalMs;
|
|
60
|
+
maxRunsPerTick;
|
|
61
|
+
ghLimit;
|
|
62
|
+
onError;
|
|
63
|
+
timer = null;
|
|
64
|
+
running = false;
|
|
65
|
+
constructor(opts) {
|
|
66
|
+
this.ledger = opts.ledger;
|
|
67
|
+
this.resolveByMergeCommit = opts.resolveByMergeCommit;
|
|
68
|
+
this.resolveRepo = opts.resolveRepo;
|
|
69
|
+
this.runGh =
|
|
70
|
+
opts.runGh ??
|
|
71
|
+
((args) => execFileSync('gh', args, { encoding: 'utf-8', timeout: 15000, stdio: ['pipe', 'pipe', 'pipe'] }));
|
|
72
|
+
this.isLeaseHolder = opts.isLeaseHolder ?? (() => true);
|
|
73
|
+
this.intervalMs = opts.intervalMs && opts.intervalMs > 0 ? opts.intervalMs : 6 * 60 * 60 * 1000;
|
|
74
|
+
this.maxRunsPerTick = opts.maxRunsPerTick && opts.maxRunsPerTick > 0 ? opts.maxRunsPerTick : 50;
|
|
75
|
+
this.ghLimit = opts.ghLimit && opts.ghLimit > 0 ? opts.ghLimit : 50;
|
|
76
|
+
this.onError = opts.onError ?? ((err) => console.warn('[ci-failure-poller]', err));
|
|
77
|
+
}
|
|
78
|
+
start() {
|
|
79
|
+
if (this.timer)
|
|
80
|
+
return;
|
|
81
|
+
queueMicrotask(() => this.tick());
|
|
82
|
+
this.timer = setInterval(() => this.tick(), this.intervalMs);
|
|
83
|
+
if (typeof this.timer.unref === 'function')
|
|
84
|
+
this.timer.unref();
|
|
85
|
+
}
|
|
86
|
+
stop() {
|
|
87
|
+
if (this.timer) {
|
|
88
|
+
clearInterval(this.timer);
|
|
89
|
+
this.timer = null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** One poll. Public for tests. Fail-open throughout. Returns # records filed. */
|
|
93
|
+
tick() {
|
|
94
|
+
if (this.running)
|
|
95
|
+
return 0;
|
|
96
|
+
this.running = true;
|
|
97
|
+
let filed = 0;
|
|
98
|
+
try {
|
|
99
|
+
if (!this.isLeaseHolder())
|
|
100
|
+
return 0;
|
|
101
|
+
const repo = this.resolveRepo();
|
|
102
|
+
if (!repo || !REPO_RE.test(repo))
|
|
103
|
+
return 0; // no repo / untrusted remote → skip
|
|
104
|
+
const raw = this.runGh([
|
|
105
|
+
'run', 'list', '--repo', repo, '--limit', String(this.ghLimit),
|
|
106
|
+
'--json', 'databaseId,conclusion,status,headBranch,headSha,name,createdAt',
|
|
107
|
+
]);
|
|
108
|
+
const runs = JSON.parse(raw);
|
|
109
|
+
if (!Array.isArray(runs))
|
|
110
|
+
return 0;
|
|
111
|
+
const failures = currentFailures(runs).slice(0, this.maxRunsPerTick);
|
|
112
|
+
for (const run of failures) {
|
|
113
|
+
try {
|
|
114
|
+
const headSha = run.headSha;
|
|
115
|
+
const mapped = this.resolveByMergeCommit(headSha);
|
|
116
|
+
if (mapped && mapped.origin === 'failure-learning-loop')
|
|
117
|
+
continue; // loop self-exclusion (§4.3)
|
|
118
|
+
const category = ciCategoryFromName(run.name);
|
|
119
|
+
const conclusion = String(run.conclusion);
|
|
120
|
+
const jobName = String(run.name || 'CI');
|
|
121
|
+
const rec = this.ledger.open({
|
|
122
|
+
source: 'ci',
|
|
123
|
+
severity: 'medium',
|
|
124
|
+
category,
|
|
125
|
+
summary: `CI ${jobName} ${conclusion}`,
|
|
126
|
+
detail: {
|
|
127
|
+
redacted: `${jobName}: ${conclusion}`,
|
|
128
|
+
full: scrubSecrets(`run ${run.databaseId ?? '?'} on ${run.headBranch ?? '?'} (${headSha}) — ${conclusion}`),
|
|
129
|
+
},
|
|
130
|
+
causeCommitOid: headSha,
|
|
131
|
+
initiativeId: mapped?.id,
|
|
132
|
+
projectId: mapped?.projectId,
|
|
133
|
+
specPath: mapped?.specPath,
|
|
134
|
+
filedBy: 'source:ci',
|
|
135
|
+
attribution: mapped ? 'automatic' : 'inferred',
|
|
136
|
+
attributionConfidence: mapped ? 0.9 : 0.2,
|
|
137
|
+
});
|
|
138
|
+
if (rec)
|
|
139
|
+
filed += 1;
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
this.onError(err); // per-run fail-open; keep going
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
this.onError(err); // whole-tick fail-open
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
this.running = false;
|
|
151
|
+
}
|
|
152
|
+
return filed;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Best-effort secret scrub before a value is stored as detail.full (spec §5).
|
|
157
|
+
* Redacts common token shapes; detail.full never crosses HTTP, but it is written
|
|
158
|
+
* to logs + sqlite, so this keeps obvious secrets out of that internal zone.
|
|
159
|
+
*/
|
|
160
|
+
export function scrubSecrets(text) {
|
|
161
|
+
return String(text)
|
|
162
|
+
.replace(/gh[pousr]_[A-Za-z0-9]{20,}/g, 'gh***_REDACTED')
|
|
163
|
+
.replace(/\b(sk|pk|rk)-[A-Za-z0-9]{16,}/g, '$1-REDACTED')
|
|
164
|
+
.replace(/\b[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{20,}\b/g, 'JWT_REDACTED')
|
|
165
|
+
.replace(/((?:token|secret|password|api[_-]?key)["'=:\s]+)[A-Za-z0-9._-]{12,}/gi, '$1REDACTED');
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=CiFailurePoller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CiFailurePoller.js","sourceRoot":"","sources":["../../src/monitoring/CiFailurePoller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ContextWedgeSentinel — detects Claude Code's "thinking/redacted_thinking
|
|
3
|
+
* blocks in the latest assistant message cannot be modified" 400 wedge and
|
|
4
|
+
* recovers via a FRESH respawn.
|
|
5
|
+
*
|
|
6
|
+
* The failure (diagnosed 2026-05-28): a tool call is cancelled inside a
|
|
7
|
+
* parallel tool batch while extended thinking is on. Claude Code cancels every
|
|
8
|
+
* sibling call, and that cancellation corrupts the thinking block on the latest
|
|
9
|
+
* assistant turn. The Anthropic API then rejects EVERY resume of that session
|
|
10
|
+
* with `400 ... thinking blocks in the latest assistant message cannot be
|
|
11
|
+
* modified`. The session fast-fails instantly on every inbound message ("Cooked
|
|
12
|
+
* for 0s"); it is permanently dead yet still emitting output, so neither the
|
|
13
|
+
* silence sentinel (output never goes quiet) nor the socket sentinel (no
|
|
14
|
+
* disconnect string) catches it.
|
|
15
|
+
*
|
|
16
|
+
* Critical difference from the other silently-stopped sentinels: a send-keys
|
|
17
|
+
* nudge CANNOT recover this — re-engaging just re-sends the corrupted turn and
|
|
18
|
+
* hits the same 400. The only recovery is a clean respawn that does NOT
|
|
19
|
+
* `--resume` the corrupted transcript. That is the injected `recoverFn`
|
|
20
|
+
* (wired to SessionRefresh fresh-mode, which clears the topic's resume UUID
|
|
21
|
+
* before respawning).
|
|
22
|
+
*
|
|
23
|
+
* Because recovery is destructive (kills + respawns a session), detection is
|
|
24
|
+
* gated by a CONFIRM WINDOW: the signature must still be the non-progressing
|
|
25
|
+
* session tail after `confirmWindowMs` before a wedge is confirmed. This is the
|
|
26
|
+
* defense against false-positives — most importantly a session merely
|
|
27
|
+
* *discussing* this very error (its tail keeps changing as it works, so the
|
|
28
|
+
* signature does not persist as the tail). And the destructive recovery itself
|
|
29
|
+
* is opt-in (autoRecovery, default off) and rides the Graduated Feature Rollout
|
|
30
|
+
* track; in the default detect-only mode the sentinel only audits + escalates.
|
|
31
|
+
*
|
|
32
|
+
* Spec: docs/specs/context-wedge-sentinel.md (companion to silently-stopped-trio.md)
|
|
33
|
+
*
|
|
34
|
+
* Signal-vs-authority: the regex + confirm-window are detectors. The recoverFn
|
|
35
|
+
* is a bounded recovery primitive (SessionRefresh rate-guards respawns). User-
|
|
36
|
+
* facing escalation routes through the existing MessagingToneGate via the
|
|
37
|
+
* SentinelNotifier path. No new blocking authority.
|
|
38
|
+
*/
|
|
39
|
+
import { EventEmitter } from 'node:events';
|
|
40
|
+
export type ContextWedgeStatus = 'detected' | 'confirming' | 'recovered' | 'escalated';
|
|
41
|
+
/** Outcome of a recovery attempt, returned by the injected recoverFn. */
|
|
42
|
+
export type WedgeRecoveryOutcome = 'respawned' | 'dry-run' | 'detect-only' | 'failed';
|
|
43
|
+
export interface ContextWedgeState {
|
|
44
|
+
sessionName: string;
|
|
45
|
+
detectedAt: number;
|
|
46
|
+
status: ContextWedgeStatus;
|
|
47
|
+
}
|
|
48
|
+
export interface ContextWedgeSentinelDeps {
|
|
49
|
+
/** Peek at the session's most recent tmux output (may be empty). */
|
|
50
|
+
getRecentOutput: (sessionName: string) => string;
|
|
51
|
+
/**
|
|
52
|
+
* Attempt recovery of a confirmed wedge. The wiring decides policy
|
|
53
|
+
* (detect-only / dry-run / live respawn) and reports back via the outcome.
|
|
54
|
+
* Never throws on the expected failure modes; rejection is treated as 'failed'.
|
|
55
|
+
*/
|
|
56
|
+
recoverFn: (sessionName: string) => Promise<WedgeRecoveryOutcome>;
|
|
57
|
+
/** Route a user-facing escalation; server.ts owns topic routing + tone gate. */
|
|
58
|
+
notifyFn: (sessionName: string, text: string) => Promise<void>;
|
|
59
|
+
/** List the session names to scan each tick. Without it the sentinel is
|
|
60
|
+
* event-driven only (caller invokes scanSession/report). */
|
|
61
|
+
listSessionNames?: () => string[];
|
|
62
|
+
/** Override Date.now (tests). */
|
|
63
|
+
now?: () => number;
|
|
64
|
+
/** Override timer setters (tests). */
|
|
65
|
+
setTimer?: (fn: () => void, ms: number) => ReturnType<typeof setTimeout>;
|
|
66
|
+
clearTimer?: (handle: ReturnType<typeof setTimeout>) => void;
|
|
67
|
+
}
|
|
68
|
+
export interface ContextWedgeSentinelConfig {
|
|
69
|
+
enabled?: boolean;
|
|
70
|
+
/** How often the self-driving loop scans every session (ms). Default 20s. */
|
|
71
|
+
tickIntervalMs?: number;
|
|
72
|
+
/** How long the signature must persist as the non-progressing tail before the
|
|
73
|
+
* wedge is confirmed (ms). Default 45s. */
|
|
74
|
+
confirmWindowMs?: number;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Patterns for the thinking-block 400. Intentionally anchored on the unusual,
|
|
78
|
+
* API-specific phrase — natural prose almost never contains it, and the
|
|
79
|
+
* confirm-window + opt-in recovery cover the one case that does (a session
|
|
80
|
+
* discussing this very bug).
|
|
81
|
+
*/
|
|
82
|
+
export declare const CONTEXT_WEDGE_PATTERNS: readonly RegExp[];
|
|
83
|
+
/** Detector — true if `text` contains the thinking-block-400 signature. */
|
|
84
|
+
export declare function detectContextWedge(text: string): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Tail detector — is the signature present within the last `tailLines`
|
|
87
|
+
* non-empty lines of the capture? A genuinely wedged session shows the error as
|
|
88
|
+
* its live tail; a session that merely mentioned the error earlier and then
|
|
89
|
+
* kept working has scrolled it out of the tail.
|
|
90
|
+
*/
|
|
91
|
+
export declare function signatureIsTail(text: string, tailLines?: number): boolean;
|
|
92
|
+
export declare class ContextWedgeSentinel extends EventEmitter {
|
|
93
|
+
private readonly deps;
|
|
94
|
+
private readonly cfg;
|
|
95
|
+
private readonly states;
|
|
96
|
+
private readonly timers;
|
|
97
|
+
private tickHandle;
|
|
98
|
+
constructor(deps: ContextWedgeSentinelDeps, cfg?: ContextWedgeSentinelConfig);
|
|
99
|
+
/** Begin the self-driving scan loop. No-op without listSessionNames. */
|
|
100
|
+
start(): void;
|
|
101
|
+
stop(): void;
|
|
102
|
+
/** One scan pass over every tracked session. */
|
|
103
|
+
tick(): void;
|
|
104
|
+
/** Scan one session for the wedge signature. */
|
|
105
|
+
scanSession(sessionName: string): void;
|
|
106
|
+
/** Public entry: report a detected (not yet confirmed) wedge. Idempotent. */
|
|
107
|
+
report(sessionName: string): void;
|
|
108
|
+
isRecoveryActive(sessionName: string): boolean;
|
|
109
|
+
listActive(): ContextWedgeState[];
|
|
110
|
+
clear(sessionName: string): void;
|
|
111
|
+
shutdown(): void;
|
|
112
|
+
private confirm;
|
|
113
|
+
private escalate;
|
|
114
|
+
private notify;
|
|
115
|
+
private setTimer;
|
|
116
|
+
private clearTimer;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=ContextWedgeSentinel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContextWedgeSentinel.d.ts","sourceRoot":"","sources":["../../src/monitoring/ContextWedgeSentinel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,kBAAkB,GAC1B,UAAU,GACV,YAAY,GACZ,WAAW,GACX,WAAW,CAAC;AAEhB,yEAAyE;AACzE,MAAM,MAAM,oBAAoB,GAC5B,WAAW,GACX,SAAS,GACT,aAAa,GACb,QAAQ,CAAC;AAEb,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,CAAC;IACjD;;;;OAIG;IACH,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAClE,gFAAgF;IAChF,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D;iEAC6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;IAClC,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;IACzE,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,CAAC;CAC9D;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;gDAC4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAQD;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAGnD,CAAC;AAEF,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMxD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,SAAK,GAAG,OAAO,CAKrE;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IAMxC,OAAO,CAAC,QAAQ,CAAC,IAAI;IALjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuC;IAC3D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoD;IAC3E,OAAO,CAAC,UAAU,CAA+C;gBAEpC,IAAI,EAAE,wBAAwB,EAAE,GAAG,GAAE,0BAA+B;IAKjG,wEAAwE;IACxE,KAAK,IAAI,IAAI;IAOb,IAAI,IAAI,IAAI;IAQZ,gDAAgD;IAChD,IAAI,IAAI,IAAI;IAMZ,gDAAgD;IAChD,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAUtC,6EAA6E;IAC7E,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAkBjC,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAK9C,UAAU,IAAI,iBAAiB,EAAE;IAIjC,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAOhC,QAAQ,IAAI,IAAI;YAQF,OAAO;IA2CrB,OAAO,CAAC,QAAQ;YAaF,MAAM;IAQpB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,UAAU;CAGnB"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ContextWedgeSentinel — detects Claude Code's "thinking/redacted_thinking
|
|
3
|
+
* blocks in the latest assistant message cannot be modified" 400 wedge and
|
|
4
|
+
* recovers via a FRESH respawn.
|
|
5
|
+
*
|
|
6
|
+
* The failure (diagnosed 2026-05-28): a tool call is cancelled inside a
|
|
7
|
+
* parallel tool batch while extended thinking is on. Claude Code cancels every
|
|
8
|
+
* sibling call, and that cancellation corrupts the thinking block on the latest
|
|
9
|
+
* assistant turn. The Anthropic API then rejects EVERY resume of that session
|
|
10
|
+
* with `400 ... thinking blocks in the latest assistant message cannot be
|
|
11
|
+
* modified`. The session fast-fails instantly on every inbound message ("Cooked
|
|
12
|
+
* for 0s"); it is permanently dead yet still emitting output, so neither the
|
|
13
|
+
* silence sentinel (output never goes quiet) nor the socket sentinel (no
|
|
14
|
+
* disconnect string) catches it.
|
|
15
|
+
*
|
|
16
|
+
* Critical difference from the other silently-stopped sentinels: a send-keys
|
|
17
|
+
* nudge CANNOT recover this — re-engaging just re-sends the corrupted turn and
|
|
18
|
+
* hits the same 400. The only recovery is a clean respawn that does NOT
|
|
19
|
+
* `--resume` the corrupted transcript. That is the injected `recoverFn`
|
|
20
|
+
* (wired to SessionRefresh fresh-mode, which clears the topic's resume UUID
|
|
21
|
+
* before respawning).
|
|
22
|
+
*
|
|
23
|
+
* Because recovery is destructive (kills + respawns a session), detection is
|
|
24
|
+
* gated by a CONFIRM WINDOW: the signature must still be the non-progressing
|
|
25
|
+
* session tail after `confirmWindowMs` before a wedge is confirmed. This is the
|
|
26
|
+
* defense against false-positives — most importantly a session merely
|
|
27
|
+
* *discussing* this very error (its tail keeps changing as it works, so the
|
|
28
|
+
* signature does not persist as the tail). And the destructive recovery itself
|
|
29
|
+
* is opt-in (autoRecovery, default off) and rides the Graduated Feature Rollout
|
|
30
|
+
* track; in the default detect-only mode the sentinel only audits + escalates.
|
|
31
|
+
*
|
|
32
|
+
* Spec: docs/specs/context-wedge-sentinel.md (companion to silently-stopped-trio.md)
|
|
33
|
+
*
|
|
34
|
+
* Signal-vs-authority: the regex + confirm-window are detectors. The recoverFn
|
|
35
|
+
* is a bounded recovery primitive (SessionRefresh rate-guards respawns). User-
|
|
36
|
+
* facing escalation routes through the existing MessagingToneGate via the
|
|
37
|
+
* SentinelNotifier path. No new blocking authority.
|
|
38
|
+
*/
|
|
39
|
+
import { EventEmitter } from 'node:events';
|
|
40
|
+
const DEFAULT_CONFIG = {
|
|
41
|
+
enabled: true,
|
|
42
|
+
tickIntervalMs: 20_000,
|
|
43
|
+
confirmWindowMs: 45_000,
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Patterns for the thinking-block 400. Intentionally anchored on the unusual,
|
|
47
|
+
* API-specific phrase — natural prose almost never contains it, and the
|
|
48
|
+
* confirm-window + opt-in recovery cover the one case that does (a session
|
|
49
|
+
* discussing this very bug).
|
|
50
|
+
*/
|
|
51
|
+
export const CONTEXT_WEDGE_PATTERNS = [
|
|
52
|
+
/blocks in the latest assistant message cannot be modified/i,
|
|
53
|
+
/`?(?:thinking|redacted_thinking)`?\s+blocks.{0,80}cannot be modified/i,
|
|
54
|
+
];
|
|
55
|
+
/** Detector — true if `text` contains the thinking-block-400 signature. */
|
|
56
|
+
export function detectContextWedge(text) {
|
|
57
|
+
if (!text)
|
|
58
|
+
return false;
|
|
59
|
+
for (const pat of CONTEXT_WEDGE_PATTERNS) {
|
|
60
|
+
if (pat.test(text))
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Tail detector — is the signature present within the last `tailLines`
|
|
67
|
+
* non-empty lines of the capture? A genuinely wedged session shows the error as
|
|
68
|
+
* its live tail; a session that merely mentioned the error earlier and then
|
|
69
|
+
* kept working has scrolled it out of the tail.
|
|
70
|
+
*/
|
|
71
|
+
export function signatureIsTail(text, tailLines = 10) {
|
|
72
|
+
if (!text)
|
|
73
|
+
return false;
|
|
74
|
+
const lines = text.split('\n').map(l => l.trim()).filter(Boolean);
|
|
75
|
+
const tail = lines.slice(-tailLines).join('\n');
|
|
76
|
+
return detectContextWedge(tail);
|
|
77
|
+
}
|
|
78
|
+
export class ContextWedgeSentinel extends EventEmitter {
|
|
79
|
+
deps;
|
|
80
|
+
cfg;
|
|
81
|
+
states = new Map();
|
|
82
|
+
timers = new Map();
|
|
83
|
+
tickHandle = null;
|
|
84
|
+
constructor(deps, cfg = {}) {
|
|
85
|
+
super();
|
|
86
|
+
this.deps = deps;
|
|
87
|
+
this.cfg = { ...DEFAULT_CONFIG, ...cfg };
|
|
88
|
+
}
|
|
89
|
+
/** Begin the self-driving scan loop. No-op without listSessionNames. */
|
|
90
|
+
start() {
|
|
91
|
+
if (!this.cfg.enabled || this.tickHandle)
|
|
92
|
+
return;
|
|
93
|
+
if (!this.deps.listSessionNames)
|
|
94
|
+
return;
|
|
95
|
+
this.tickHandle = setInterval(() => this.tick(), this.cfg.tickIntervalMs);
|
|
96
|
+
if (typeof this.tickHandle.unref === 'function')
|
|
97
|
+
this.tickHandle.unref();
|
|
98
|
+
}
|
|
99
|
+
stop() {
|
|
100
|
+
if (this.tickHandle) {
|
|
101
|
+
clearInterval(this.tickHandle);
|
|
102
|
+
this.tickHandle = null;
|
|
103
|
+
}
|
|
104
|
+
this.shutdown();
|
|
105
|
+
}
|
|
106
|
+
/** One scan pass over every tracked session. */
|
|
107
|
+
tick() {
|
|
108
|
+
if (!this.cfg.enabled)
|
|
109
|
+
return;
|
|
110
|
+
const names = this.deps.listSessionNames?.() ?? [];
|
|
111
|
+
for (const name of names)
|
|
112
|
+
this.scanSession(name);
|
|
113
|
+
}
|
|
114
|
+
/** Scan one session for the wedge signature. */
|
|
115
|
+
scanSession(sessionName) {
|
|
116
|
+
if (!this.cfg.enabled)
|
|
117
|
+
return;
|
|
118
|
+
if (this.states.has(sessionName))
|
|
119
|
+
return; // already handling
|
|
120
|
+
const output = this.deps.getRecentOutput(sessionName);
|
|
121
|
+
// Require the signature to be the live TAIL, not merely present somewhere in
|
|
122
|
+
// the scrollback — the discriminator against a session discussing the bug.
|
|
123
|
+
if (!signatureIsTail(output))
|
|
124
|
+
return;
|
|
125
|
+
this.report(sessionName);
|
|
126
|
+
}
|
|
127
|
+
/** Public entry: report a detected (not yet confirmed) wedge. Idempotent. */
|
|
128
|
+
report(sessionName) {
|
|
129
|
+
if (!this.cfg.enabled)
|
|
130
|
+
return;
|
|
131
|
+
if (this.states.has(sessionName))
|
|
132
|
+
return;
|
|
133
|
+
const now = (this.deps.now ?? Date.now)();
|
|
134
|
+
const state = {
|
|
135
|
+
sessionName,
|
|
136
|
+
detectedAt: now,
|
|
137
|
+
status: 'detected',
|
|
138
|
+
};
|
|
139
|
+
this.states.set(sessionName, state);
|
|
140
|
+
this.emit('detected', { sessionName });
|
|
141
|
+
// Enter the confirm window before any destructive action.
|
|
142
|
+
state.status = 'confirming';
|
|
143
|
+
const handle = this.setTimer(() => void this.confirm(sessionName), this.cfg.confirmWindowMs);
|
|
144
|
+
this.timers.set(sessionName, handle);
|
|
145
|
+
}
|
|
146
|
+
isRecoveryActive(sessionName) {
|
|
147
|
+
const s = this.states.get(sessionName);
|
|
148
|
+
return !!s && s.status !== 'recovered' && s.status !== 'escalated';
|
|
149
|
+
}
|
|
150
|
+
listActive() {
|
|
151
|
+
return Array.from(this.states.values());
|
|
152
|
+
}
|
|
153
|
+
clear(sessionName) {
|
|
154
|
+
const t = this.timers.get(sessionName);
|
|
155
|
+
if (t)
|
|
156
|
+
this.clearTimer(t);
|
|
157
|
+
this.timers.delete(sessionName);
|
|
158
|
+
this.states.delete(sessionName);
|
|
159
|
+
}
|
|
160
|
+
shutdown() {
|
|
161
|
+
for (const t of this.timers.values())
|
|
162
|
+
this.clearTimer(t);
|
|
163
|
+
this.timers.clear();
|
|
164
|
+
this.states.clear();
|
|
165
|
+
}
|
|
166
|
+
// ── Confirm + recover ────────────────────────────────────────────────
|
|
167
|
+
async confirm(sessionName) {
|
|
168
|
+
const state = this.states.get(sessionName);
|
|
169
|
+
if (!state)
|
|
170
|
+
return;
|
|
171
|
+
const output = this.deps.getRecentOutput(sessionName);
|
|
172
|
+
// Confirmation gate: the signature must STILL be the tail. If it scrolled
|
|
173
|
+
// out (the session progressed past the error), this was not a wedge — a
|
|
174
|
+
// false alarm (e.g. a session that quoted the error then kept working).
|
|
175
|
+
if (!signatureIsTail(output)) {
|
|
176
|
+
this.emit('false-alarm', { sessionName });
|
|
177
|
+
this.clear(sessionName);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
// Confirmed wedge → hand to the recovery policy.
|
|
181
|
+
let outcome = 'failed';
|
|
182
|
+
try {
|
|
183
|
+
outcome = await this.deps.recoverFn(sessionName);
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
this.emit('recovery-error', { sessionName, err });
|
|
187
|
+
outcome = 'failed';
|
|
188
|
+
}
|
|
189
|
+
switch (outcome) {
|
|
190
|
+
case 'respawned':
|
|
191
|
+
state.status = 'recovered';
|
|
192
|
+
this.emit('recovered', { sessionName });
|
|
193
|
+
this.clear(sessionName);
|
|
194
|
+
return;
|
|
195
|
+
case 'dry-run':
|
|
196
|
+
// Housekeeping only — would-have-respawned. Keep state so we don't
|
|
197
|
+
// re-confirm the same wedge every tick; the dry-run log is the signal.
|
|
198
|
+
state.status = 'escalated';
|
|
199
|
+
this.emit('dry-run', { sessionName });
|
|
200
|
+
return;
|
|
201
|
+
case 'detect-only':
|
|
202
|
+
case 'failed':
|
|
203
|
+
default:
|
|
204
|
+
this.escalate(sessionName, outcome);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
escalate(sessionName, outcome) {
|
|
209
|
+
const state = this.states.get(sessionName);
|
|
210
|
+
if (!state)
|
|
211
|
+
return;
|
|
212
|
+
state.status = 'escalated';
|
|
213
|
+
const detail = outcome === 'failed'
|
|
214
|
+
? `${friendlyName(sessionName)} is wedged on a stuck-context error and my respawn attempt did not clear it. Want me to dig in?`
|
|
215
|
+
: `${friendlyName(sessionName)} is wedged on a stuck-context error (it can only be fixed by a fresh restart, which is currently off). Want me to restart it?`;
|
|
216
|
+
void this.notify(sessionName, detail);
|
|
217
|
+
this.emit('escalated', { sessionName, outcome });
|
|
218
|
+
// Keep state so a subsequent scan doesn't re-report the same wedge.
|
|
219
|
+
}
|
|
220
|
+
async notify(sessionName, text) {
|
|
221
|
+
try {
|
|
222
|
+
await this.deps.notifyFn(sessionName, text);
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
this.emit('notify-error', { sessionName, err });
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
setTimer(fn, ms) {
|
|
229
|
+
return (this.deps.setTimer ?? setTimeout)(fn, ms);
|
|
230
|
+
}
|
|
231
|
+
clearTimer(handle) {
|
|
232
|
+
(this.deps.clearTimer ?? clearTimeout)(handle);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function friendlyName(sessionName) {
|
|
236
|
+
return sessionName.replace(/^ai\.instar\./, '').replace(/-server$/, '').replace(/-lifeline$/, '');
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=ContextWedgeSentinel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContextWedgeSentinel.js","sourceRoot":"","sources":["../../src/monitoring/ContextWedgeSentinel.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FailureAnalyzer.d.ts","sourceRoot":"","sources":["../../src/monitoring/FailureAnalyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,aAAa,EAAkC,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEvG,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,uBAAuB,EAAE,MAAM,CAAC;IAChC,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,aAAa,EAAE,aAI3B,CAAC;
|
|
1
|
+
{"version":3,"file":"FailureAnalyzer.d.ts","sourceRoot":"","sources":["../../src/monitoring/FailureAnalyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,aAAa,EAAkC,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEvG,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,uBAAuB,EAAE,MAAM,CAAC;IAChC,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,aAAa,EAAE,aAI3B,CAAC;AAkBF,MAAM,WAAW,aAAa;IAC5B,kBAAkB,EAAE,aAAa,EAAE,CAAC;IACpC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAiB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAA7C,MAAM,EAAE,aAAa,EAAmB,KAAK,GAAE,aAA6B;IAEzG;;;;OAIG;IACH,OAAO,IAAI,aAAa;CAoDzB"}
|
|
@@ -11,6 +11,11 @@ const RECOMMENDATION_BY_CATEGORY = {
|
|
|
11
11
|
logic: 'Recurring logic failures — strengthen the both-sides-of-the-boundary test requirement in the spec review.',
|
|
12
12
|
migration: 'Recurring migration failures — add a migration-parity check (existing-agent path) to the review checklist.',
|
|
13
13
|
'test-gap': 'Recurring test-gap failures — require the 3-tier test set (incl. the production storage path) before merge.',
|
|
14
|
+
// Ingestion-sources spec §7: required because this is a total Record<FailureCategory,…>
|
|
15
|
+
// — widening the enum without these entries fails tsc. (A totality test locks this.)
|
|
16
|
+
'build-failure': 'Recurring build failures — check the build config / dependency or lint rule that keeps breaking, and add a pre-merge build gate for it.',
|
|
17
|
+
'test-failure': 'Recurring test failures — require the 3-tier test set before merge and stabilize the flaky path before it lands.',
|
|
18
|
+
regression: 'Recurring regressions — a shipped feature keeps breaking; add a regression guard (a test pinning the behavior) for this path.',
|
|
14
19
|
unknown: 'Recurring uncategorized failures — improve the failure-categorization step so these become actionable.',
|
|
15
20
|
};
|
|
16
21
|
export class FailureAnalyzer {
|
|
@@ -31,9 +36,13 @@ export class FailureAnalyzer {
|
|
|
31
36
|
: undefined;
|
|
32
37
|
// Only attributed records feed a process-change recommendation (§4.3): a
|
|
33
38
|
// guess (`inferred`) is excluded until confirmed.
|
|
39
|
+
// Ingestion-sources spec §6.1 (implements parent §4.4 M6, specified-but-unbuilt):
|
|
40
|
+
// `resolved` records (incl. those a revert closes) are excluded from active-rate
|
|
41
|
+
// clustering — a fixed/reverted failure must not keep driving a recommendation.
|
|
42
|
+
// `reopened` stays IN (it is active again); only `resolved` is excluded.
|
|
34
43
|
const records = this.ledger
|
|
35
44
|
.list({ sinceMs, limit: 1000 })
|
|
36
|
-
.filter((r) => r.attribution === 'automatic' || r.attribution === 'one-tap');
|
|
45
|
+
.filter((r) => (r.attribution === 'automatic' || r.attribution === 'one-tap') && r.status !== 'resolved');
|
|
37
46
|
const byCategory = new Map();
|
|
38
47
|
for (const r of records) {
|
|
39
48
|
const arr = byCategory.get(r.category) ?? [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FailureAnalyzer.js","sourceRoot":"","sources":["../../src/monitoring/FailureAnalyzer.ts"],"names":[],"mappings":"AA+BA,MAAM,CAAC,MAAM,aAAa,GAAkB;IAC1C,UAAU,EAAE,CAAC;IACb,mBAAmB,EAAE,CAAC;IACtB,uBAAuB,EAAE,CAAC;CAC3B,CAAC;AAEF,oFAAoF;AACpF,MAAM,0BAA0B,GAAoC;IAClE,WAAW,EAAE,oIAAoI;IACjJ,cAAc,EAAE,wGAAwG;IACxH,MAAM,EAAE,sJAAsJ;IAC9J,KAAK,EAAE,2GAA2G;IAClH,SAAS,EAAE,4GAA4G;IACvH,UAAU,EAAE,6GAA6G;IACzH,OAAO,EAAE,wGAAwG;CAClH,CAAC;AAQF,MAAM,OAAO,eAAe;IACG;IAAwC;IAArE,YAA6B,MAAqB,EAAmB,QAAuB,aAAa;QAA5E,WAAM,GAAN,MAAM,CAAe;QAAmB,UAAK,GAAL,KAAK,CAA+B;IAAG,CAAC;IAE7G;;;;OAIG;IACH,OAAO;QACL,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC;YAChE,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,SAAS;YAChD,CAAC,CAAC,SAAS,CAAC;QACd,yEAAyE;QACzE,kDAAkD;QAClD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM;aACxB,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;aAC9B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,IAAI,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"FailureAnalyzer.js","sourceRoot":"","sources":["../../src/monitoring/FailureAnalyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FailureAttributionEngine.d.ts","sourceRoot":"","sources":["../../src/monitoring/FailureAttributionEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE3E,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,oFAAoF;IACpF,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,cAAc,GAAG,IAAI,CAAC;IACrD,mEAAmE;IACnE,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,eAAe,CAAC;IAC7B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAKD,qBAAa,wBAAwB;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,eAAe;IAElD,8DAA8D;IAC9D,MAAM,CAAC,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc;IAS3D,8FAA8F;IAC9F,OAAO,CAAC,MAAM,CAAC,IAAI;IAInB;;;;;OAKG;IACH,qBAAqB,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG,kBAAkB;IAoD9F;;;;OAIG;IACH,sBAAsB,CAAC,KAAK,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3E;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,kBAAkB,CAAA;KAAE,GACzC;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAmBjC,6EAA6E;IAC7E,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,eAAe;
|
|
1
|
+
{"version":3,"file":"FailureAttributionEngine.d.ts","sourceRoot":"","sources":["../../src/monitoring/FailureAttributionEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE3E,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,oFAAoF;IACpF,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,cAAc,GAAG,IAAI,CAAC;IACrD,mEAAmE;IACnE,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,eAAe,CAAC;IAC7B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAKD,qBAAa,wBAAwB;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,eAAe;IAElD,8DAA8D;IAC9D,MAAM,CAAC,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc;IAS3D,8FAA8F;IAC9F,OAAO,CAAC,MAAM,CAAC,IAAI;IAInB;;;;;OAKG;IACH,qBAAqB,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG,kBAAkB;IAoD9F;;;;OAIG;IACH,sBAAsB,CAAC,KAAK,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3E;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,kBAAkB,CAAA;KAAE,GACzC;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAmBjC,6EAA6E;IAC7E,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,eAAe;CAOlE"}
|
|
@@ -98,7 +98,8 @@ export class FailureAttributionEngine {
|
|
|
98
98
|
/** Pick a category enum value defensively — never trust free text (§4.4). */
|
|
99
99
|
static coerceCategory(value) {
|
|
100
100
|
const allowed = [
|
|
101
|
-
'concurrency', 'config-parse', 'wiring', 'logic', 'migration', 'test-gap',
|
|
101
|
+
'concurrency', 'config-parse', 'wiring', 'logic', 'migration', 'test-gap',
|
|
102
|
+
'build-failure', 'test-failure', 'regression', 'unknown',
|
|
102
103
|
];
|
|
103
104
|
return allowed.includes(value) ? value : 'unknown';
|
|
104
105
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FailureAttributionEngine.js","sourceRoot":"","sources":["../../src/monitoring/FailureAttributionEngine.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"FailureAttributionEngine.js","sourceRoot":"","sources":["../../src/monitoring/FailureAttributionEngine.ts"],"names":[],"mappings":"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"}
|