@tokenfactory/acc-runner 0.14.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -238,6 +238,35 @@ remain uncovered by its budget/backoff. The client is the sanctioned path
238
238
  for any future **direct** REST call (`fetch` against `api.github.com`) the
239
239
  runner adds.
240
240
 
241
+ ## Conflict-resolution integrity guardrail (v0.57, T-57-2)
242
+
243
+ When a Claude/worktree task whose job is to **resolve a merge conflict**
244
+ finishes, the runner does not trust the agent's self-reported gate results.
245
+ Before the resolution is pushed, `src/runtime/resolution-integrity.ts`
246
+ re-verifies it from the runner's own vantage point. The invariant —
247
+ **a conflict resolution is shippable only if all three hold**:
248
+
249
+ 1. **Zero conflict markers** remain in any tracked file
250
+ (`<<<<<<<` / `=======` / `>>>>>>>`).
251
+ 2. **`pnpm typecheck` passes** (or the task's `typecheck_cmd`).
252
+ 3. **No version regression**: if a `package.json` `"version"` changed in the
253
+ resolution it must move **forward** (semver-greater than the base ref,
254
+ never backward) **and** `CHANGELOG.md` must carry a matching entry for the
255
+ new version.
256
+
257
+ On ANY failure the resolution is **rejected**: the runner does not push and
258
+ does not mark the task resolved. The task transitions to `failed` (so it is
259
+ reworked, not merged broken), an `append_task_event` of kind
260
+ `resolution_integrity_failed` records the offending assertion(s), and a
261
+ `conflict.integrity_rejected` activity event surfaces it to the operator. A
262
+ guardrail that itself errors **fails closed** (rejects). The check is a no-op
263
+ for every non-conflict task — it is gated by `isConflictResolutionTask`.
264
+
265
+ This exists because v0.55–v0.56 agent resolutions repeatedly shipped broken
266
+ merges that were still marked "resolved": stale-variable splices
267
+ (task-runner.ts), duplicate declarations (health.ts), and a silently dropped
268
+ version bump (#496 reverted `package.json` 0.14.0 → 0.13.0).
269
+
241
270
  ## Security notes
242
271
 
243
272
  - The CLI never reads or writes your git, gh, or Anthropic credentials.
@@ -1,20 +1,48 @@
1
1
  /**
2
- * v0.48: classify a non-zero claude CLI exit into one of four categories
2
+ * v0.48: classify a non-zero claude CLI exit into one of five categories
3
3
  * so the watch loop can distinguish machine-level failures (which should
4
4
  * quarantine the runner) from genuine task errors (which count toward the
5
- * task's retry budget).
5
+ * task's retry budget) and from a spent capacity window (which should
6
+ * PAUSE, not quarantine).
6
7
  *
7
- * The four classes:
8
- * usage_limit — Claude/Anthropic plan limit or rate limit reached.
8
+ * The six classes:
9
+ * capacity_exhausted — Claude/Anthropic session or usage limit reached
10
+ * (api_error_status 429 + a "resets <time>" message).
11
+ * A NEW v0.56 (T-56-1) retryable-infra class: capacity is
12
+ * a resource, not a failure. NEVER task_error and NEVER
13
+ * quarantine — the runner pauses claiming until the stated
14
+ * reset time (or a default backoff) then resumes with a
15
+ * single probe. Root cause of the 2026-06-05 brownout.
16
+ * claude_unavailable — A NEW v0.63 (T-63-1) retryable-infra class: claude
17
+ * exited fast with NO output AND no env/auth/usage signal —
18
+ * the silent instant-empty fingerprint. Pre-v0.63 the pd36
19
+ * heuristic called this env_broken and (after 2 in a row)
20
+ * quarantined the runner; but a brief/silent claude window
21
+ * (a usage blip that exits without a 429, or a momentary API
22
+ * hiccup) presents identically. Silence alone cannot tell
23
+ * "broken host" from "claude momentarily down", so this class
24
+ * is RETRYABLE (pause + backoff + retry, like
25
+ * capacity_exhausted) and NEVER quarantines on its own. The
26
+ * task-runner's `claude --version` health probe is the
27
+ * authoritative tiebreaker: if the probe fails, the host is
28
+ * genuinely broken and the exit is upgraded to env_broken.
29
+ * Root cause of the live T-63-1 self-quarantine incident.
30
+ * usage_limit — A hard Claude/Anthropic plan limit that will NOT reset
31
+ * on its own soon (out of credits, monthly spend cap,
32
+ * quota exhausted). Quarantine is still the right response
33
+ * — an operator has to top up or wait out the billing cycle.
9
34
  * auth_expired — API key invalid or session expired on the user's machine.
10
35
  * env_broken — Host-side environment failure (dyld, missing binary, OOM).
11
36
  * Root cause of the pd36 claim-and-fail storm (INCIDENT_2026-06-02).
12
37
  * task_error — Everything else; genuine task-level failure.
13
38
  *
14
- * Only task_error counts toward a task's retry budget. The other three
15
- * trigger runner quarantine in watch.ts.
39
+ * Only task_error counts toward a task's retry budget. usage_limit /
40
+ * auth_expired / env_broken trigger runner quarantine in watch.ts;
41
+ * capacity_exhausted and claude_unavailable trigger the pause/resume path
42
+ * instead (capacity until a reset time, claude_unavailable with an
43
+ * exponential backoff).
16
44
  */
17
- export type ClaudeExitClass = "usage_limit" | "auth_expired" | "env_broken" | "task_error";
45
+ export type ClaudeExitClass = "capacity_exhausted" | "claude_unavailable" | "usage_limit" | "auth_expired" | "env_broken" | "task_error";
18
46
  export interface ClassifiedExit {
19
47
  exitCode: number | null;
20
48
  class: ClaudeExitClass;
@@ -24,15 +52,45 @@ export interface ClassifiedExit {
24
52
  * fast-exit/empty-output heuristic (the pd36 fingerprint), not from a
25
53
  * definitive signal (exit 127, a matched dyld/OOM/usage/auth pattern).
26
54
  *
27
- * The distinction matters for quarantine policy: a definitive
28
- * env_broken benches the runner immediately, but a lone heuristic hit
29
- * is too weak to bench a healthy machine (v0.52 incident (d) — ONE
30
- * 249ms empty exit quarantined a working box). The task-runner retries
31
- * the spawn once and only treats TWO consecutive heuristic hits as a
32
- * real env_broken. Absent/false on every non-heuristic classification.
55
+ * v0.63 T-63-1: the heuristic now yields `claude_unavailable` (retryable),
56
+ * NOT `env_broken` (quarantine). A lone instant-empty exit was always too
57
+ * weak to bench a healthy machine (v0.52 incident (d) — ONE 249ms empty
58
+ * exit quarantined a working box); the live T-63-1 incident proved that
59
+ * even TWO in a row can be a transient/silent claude window rather than a
60
+ * broken host. The task-runner still retries the spawn once, but a
61
+ * confirmed instant-empty streak now routes to pause + backoff + retry and
62
+ * only escalates to env_broken (quarantine) when a `claude --version`
63
+ * health probe ALSO fails. Absent/false on every non-heuristic
64
+ * classification.
33
65
  */
34
66
  heuristic?: boolean;
35
67
  }
68
+ /**
69
+ * v0.56 (T-56-1): pull `api_error_status` out of claude's
70
+ * `--output-format=json` envelope. On a session/usage limit the CLI exits
71
+ * 1 with a JSON object carrying `{ "is_error": true, "api_error_status":
72
+ * 429, "result": "You've hit your session limit - resets 3:20pm
73
+ * (Asia/Calcutta)" }`. Returns the numeric status when present, else null.
74
+ * Kept self-contained (a local parse, no cost-pricing import) so the
75
+ * classifier stays a pure (strings) → class function for unit tests.
76
+ */
77
+ export declare function parseApiErrorStatus(stdout: string): number | null;
78
+ /**
79
+ * v0.56 (T-56-1): parse the reset time Claude states when it pauses a
80
+ * session ("...resets 3:20pm (Asia/Calcutta)") into an absolute epoch
81
+ * (ms). The runner schedules its capacity resume off this so it wakes
82
+ * exactly when the window reopens rather than guessing a fixed backoff.
83
+ *
84
+ * - 12h ("3:20pm") and 24h ("15:20") clock forms are both accepted.
85
+ * - A parenthetical IANA zone ("(Asia/Calcutta)") is honoured; without
86
+ * one the time is read in the runner's local zone.
87
+ * - The soonest FUTURE occurrence wins: a stated time already past today
88
+ * rolls to tomorrow.
89
+ *
90
+ * Returns null when no reset time is present or the zone is unparseable —
91
+ * the caller then falls back to a default backoff.
92
+ */
93
+ export declare function extractResetTime(text: string, now?: number): number | null;
36
94
  /**
37
95
  * Classify a non-zero claude exit.
38
96
  *
@@ -1 +1 @@
1
- {"version":3,"file":"failure-classifier.d.ts","sourceRoot":"","sources":["../src/failure-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,MAAM,eAAe,GACvB,aAAa,GACb,cAAc,GACd,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,eAAe,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA0DD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,cAAc,CA8DhB"}
1
+ {"version":3,"file":"failure-classifier.d.ts","sourceRoot":"","sources":["../src/failure-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,MAAM,MAAM,eAAe,GACvB,oBAAoB,GACpB,oBAAoB,GACpB,aAAa,GACb,cAAc,GACd,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,eAAe,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA0ED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYjE;AA2DD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,GAAG,IAAI,CAiCtF;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,cAAc,CAqFhB"}
@@ -1,19 +1,62 @@
1
1
  /**
2
- * v0.48: classify a non-zero claude CLI exit into one of four categories
2
+ * v0.48: classify a non-zero claude CLI exit into one of five categories
3
3
  * so the watch loop can distinguish machine-level failures (which should
4
4
  * quarantine the runner) from genuine task errors (which count toward the
5
- * task's retry budget).
5
+ * task's retry budget) and from a spent capacity window (which should
6
+ * PAUSE, not quarantine).
6
7
  *
7
- * The four classes:
8
- * usage_limit — Claude/Anthropic plan limit or rate limit reached.
8
+ * The six classes:
9
+ * capacity_exhausted — Claude/Anthropic session or usage limit reached
10
+ * (api_error_status 429 + a "resets <time>" message).
11
+ * A NEW v0.56 (T-56-1) retryable-infra class: capacity is
12
+ * a resource, not a failure. NEVER task_error and NEVER
13
+ * quarantine — the runner pauses claiming until the stated
14
+ * reset time (or a default backoff) then resumes with a
15
+ * single probe. Root cause of the 2026-06-05 brownout.
16
+ * claude_unavailable — A NEW v0.63 (T-63-1) retryable-infra class: claude
17
+ * exited fast with NO output AND no env/auth/usage signal —
18
+ * the silent instant-empty fingerprint. Pre-v0.63 the pd36
19
+ * heuristic called this env_broken and (after 2 in a row)
20
+ * quarantined the runner; but a brief/silent claude window
21
+ * (a usage blip that exits without a 429, or a momentary API
22
+ * hiccup) presents identically. Silence alone cannot tell
23
+ * "broken host" from "claude momentarily down", so this class
24
+ * is RETRYABLE (pause + backoff + retry, like
25
+ * capacity_exhausted) and NEVER quarantines on its own. The
26
+ * task-runner's `claude --version` health probe is the
27
+ * authoritative tiebreaker: if the probe fails, the host is
28
+ * genuinely broken and the exit is upgraded to env_broken.
29
+ * Root cause of the live T-63-1 self-quarantine incident.
30
+ * usage_limit — A hard Claude/Anthropic plan limit that will NOT reset
31
+ * on its own soon (out of credits, monthly spend cap,
32
+ * quota exhausted). Quarantine is still the right response
33
+ * — an operator has to top up or wait out the billing cycle.
9
34
  * auth_expired — API key invalid or session expired on the user's machine.
10
35
  * env_broken — Host-side environment failure (dyld, missing binary, OOM).
11
36
  * Root cause of the pd36 claim-and-fail storm (INCIDENT_2026-06-02).
12
37
  * task_error — Everything else; genuine task-level failure.
13
38
  *
14
- * Only task_error counts toward a task's retry budget. The other three
15
- * trigger runner quarantine in watch.ts.
39
+ * Only task_error counts toward a task's retry budget. usage_limit /
40
+ * auth_expired / env_broken trigger runner quarantine in watch.ts;
41
+ * capacity_exhausted and claude_unavailable trigger the pause/resume path
42
+ * instead (capacity until a reset time, claude_unavailable with an
43
+ * exponential backoff).
16
44
  */
45
+ // v0.56 (T-56-1): signatures of a SPENT-BUT-RECOVERABLE capacity window —
46
+ // the session/usage limit Claude resets on a clock (vs. usage_limit below,
47
+ // which is a hard billing wall). These must stay disjoint from the
48
+ // usage_limit patterns so the live 2026-06-05 signature
49
+ // ("You've hit your session limit - resets 3:20pm (Asia/Calcutta)")
50
+ // routes to pause, while "out of credits" / "monthly spend limit" still
51
+ // route to quarantine. The authoritative signal is api_error_status 429 in
52
+ // the result JSON; these message patterns are the fallback when the runner
53
+ // only has plain text (older claude, or the JSON envelope was not emitted).
54
+ const CAPACITY_PATTERNS = [
55
+ /hit your (?:session|usage|account) limit/i,
56
+ /session limit/i,
57
+ /(?:session|usage|account|limit).*resets?\b/i,
58
+ /resets?\s+(?:at\s+)?\d{1,2}(?::\d{2})?\s*(?:am|pm)/i,
59
+ ];
17
60
  const USAGE_LIMIT_PATTERNS = [
18
61
  /usage limit/i,
19
62
  /you have reached the maximum number of tokens/i,
@@ -65,6 +108,129 @@ const FAST_EXIT_MAX_OUTPUT_BYTES = 100;
65
108
  function matchesAny(text, patterns) {
66
109
  return patterns.some((p) => p.test(text));
67
110
  }
111
+ /**
112
+ * v0.56 (T-56-1): pull `api_error_status` out of claude's
113
+ * `--output-format=json` envelope. On a session/usage limit the CLI exits
114
+ * 1 with a JSON object carrying `{ "is_error": true, "api_error_status":
115
+ * 429, "result": "You've hit your session limit - resets 3:20pm
116
+ * (Asia/Calcutta)" }`. Returns the numeric status when present, else null.
117
+ * Kept self-contained (a local parse, no cost-pricing import) so the
118
+ * classifier stays a pure (strings) → class function for unit tests.
119
+ */
120
+ export function parseApiErrorStatus(stdout) {
121
+ const trimmed = stdout.trim();
122
+ if (!trimmed.startsWith("{"))
123
+ return null;
124
+ try {
125
+ const parsed = JSON.parse(trimmed);
126
+ const status = parsed?.api_error_status;
127
+ if (typeof status === "number")
128
+ return status;
129
+ if (typeof status === "string" && /^\d+$/.test(status))
130
+ return Number(status);
131
+ return null;
132
+ }
133
+ catch {
134
+ return null;
135
+ }
136
+ }
137
+ const RESET_TIME_RE = /resets?\s+(?:at\s+|by\s+)?(\d{1,2})(?::(\d{2}))?\s*(am|pm)?\s*(?:\(([^)]+)\))?/i;
138
+ function tzDateParts(instant, tz) {
139
+ const dtf = new Intl.DateTimeFormat("en-US", {
140
+ timeZone: tz,
141
+ year: "numeric",
142
+ month: "2-digit",
143
+ day: "2-digit",
144
+ hour: "2-digit",
145
+ minute: "2-digit",
146
+ second: "2-digit",
147
+ hour12: false,
148
+ });
149
+ const map = {};
150
+ for (const p of dtf.formatToParts(instant)) {
151
+ if (p.type !== "literal")
152
+ map[p.type] = p.value;
153
+ }
154
+ // Intl can emit "24" for midnight in hour12:false mode; normalise to 0.
155
+ const hour = Number(map.hour) === 24 ? 0 : Number(map.hour);
156
+ return {
157
+ year: Number(map.year),
158
+ month: Number(map.month),
159
+ day: Number(map.day),
160
+ hour,
161
+ minute: Number(map.minute),
162
+ second: Number(map.second),
163
+ };
164
+ }
165
+ /** Offset (ms) of `tz` relative to UTC at the given instant (east = positive). */
166
+ function zoneOffsetMs(instant, tz) {
167
+ const p = tzDateParts(instant, tz);
168
+ const asUtc = Date.UTC(p.year, p.month - 1, p.day, p.hour, p.minute, p.second);
169
+ return asUtc - instant;
170
+ }
171
+ /** Resolve a wall-clock Y-M-D H:M in `tz` to a UTC epoch (one DST refinement). */
172
+ function wallClockToUtc(year, month, day, hour, minute, tz) {
173
+ const guess = Date.UTC(year, month - 1, day, hour, minute, 0);
174
+ let instant = guess - zoneOffsetMs(guess, tz);
175
+ const off2 = zoneOffsetMs(instant, tz);
176
+ const refined = guess - off2;
177
+ if (refined !== instant)
178
+ instant = refined;
179
+ return instant;
180
+ }
181
+ /**
182
+ * v0.56 (T-56-1): parse the reset time Claude states when it pauses a
183
+ * session ("...resets 3:20pm (Asia/Calcutta)") into an absolute epoch
184
+ * (ms). The runner schedules its capacity resume off this so it wakes
185
+ * exactly when the window reopens rather than guessing a fixed backoff.
186
+ *
187
+ * - 12h ("3:20pm") and 24h ("15:20") clock forms are both accepted.
188
+ * - A parenthetical IANA zone ("(Asia/Calcutta)") is honoured; without
189
+ * one the time is read in the runner's local zone.
190
+ * - The soonest FUTURE occurrence wins: a stated time already past today
191
+ * rolls to tomorrow.
192
+ *
193
+ * Returns null when no reset time is present or the zone is unparseable —
194
+ * the caller then falls back to a default backoff.
195
+ */
196
+ export function extractResetTime(text, now = Date.now()) {
197
+ if (!text)
198
+ return null;
199
+ const m = RESET_TIME_RE.exec(text);
200
+ if (!m)
201
+ return null;
202
+ let hour = Number(m[1]);
203
+ const minute = m[2] ? Number(m[2]) : 0;
204
+ const ampm = m[3]?.toLowerCase();
205
+ const tz = m[4]?.trim();
206
+ if (Number.isNaN(hour) || hour > 23 || minute > 59)
207
+ return null;
208
+ if (ampm === "pm" && hour < 12)
209
+ hour += 12;
210
+ if (ampm === "am" && hour === 12)
211
+ hour = 0;
212
+ try {
213
+ if (tz) {
214
+ const today = tzDateParts(now, tz);
215
+ let instant = wallClockToUtc(today.year, today.month, today.day, hour, minute, tz);
216
+ if (instant <= now) {
217
+ const tomorrow = tzDateParts(now + 24 * 3_600_000, tz);
218
+ instant = wallClockToUtc(tomorrow.year, tomorrow.month, tomorrow.day, hour, minute, tz);
219
+ }
220
+ return instant;
221
+ }
222
+ const local = new Date(now);
223
+ local.setHours(hour, minute, 0, 0);
224
+ let instant = local.getTime();
225
+ if (instant <= now)
226
+ instant += 24 * 3_600_000;
227
+ return instant;
228
+ }
229
+ catch {
230
+ // Unknown/garbled IANA zone — let the caller apply its default backoff.
231
+ return null;
232
+ }
233
+ }
68
234
  /**
69
235
  * Classify a non-zero claude exit.
70
236
  *
@@ -84,6 +250,18 @@ export function classifyClaudeExit(exitCode, stderr, stdout, durationMs) {
84
250
  };
85
251
  }
86
252
  const combined = `${stderr}\n${stdout}`;
253
+ // v0.56 (T-56-1): capacity check FIRST so the recoverable session/usage
254
+ // window routes to pause, not quarantine. Authoritative signal is the
255
+ // result JSON's api_error_status 429; the message patterns are the
256
+ // plain-text fallback. Disjoint from USAGE_LIMIT_PATTERNS below, which
257
+ // stay quarantine-worthy (hard billing walls).
258
+ if (parseApiErrorStatus(stdout) === 429 || matchesAny(combined, CAPACITY_PATTERNS)) {
259
+ return {
260
+ exitCode,
261
+ class: "capacity_exhausted",
262
+ detail: "Claude session/usage capacity reached (429) — runner will pause until reset",
263
+ };
264
+ }
87
265
  if (matchesAny(combined, USAGE_LIMIT_PATTERNS)) {
88
266
  return {
89
267
  exitCode,
@@ -105,21 +283,31 @@ export function classifyClaudeExit(exitCode, stderr, stdout, durationMs) {
105
283
  detail: "host environment error detected in process output",
106
284
  };
107
285
  }
108
- // pd36 heuristic: exit almost immediately with near-empty output.
109
- // A real task failure always produces at least some stdout (the model's
110
- // preamble + any partial work). Pure silence + fast exit points to a
111
- // broken shared library or missing dependency on the runner machine.
286
+ // pd36 fingerprint: exit almost immediately with near-empty output, and
287
+ // none of the definitive signals above matched (no exit 127, no dyld/OOM,
288
+ // no usage/auth/capacity pattern). A real task failure always produces at
289
+ // least some stdout (the model's preamble + any partial work). Pure silence
290
+ // + fast exit is genuinely ambiguous: it can be a broken host (missing lib,
291
+ // bad PATH) OR a transient/silent claude window (a usage blip that exits
292
+ // without a 429, a momentary API hiccup).
293
+ //
294
+ // v0.63 T-63-1: classify this BARE silent instant-empty exit as the
295
+ // retryable `claude_unavailable`, NOT `env_broken`. Quarantining on silence
296
+ // alone benched a healthy runner in the live T-63-1 incident (claude -p
297
+ // worked seconds later in the same shell). The task-runner pauses + backs
298
+ // off + retries on this class, and only upgrades it to env_broken (the
299
+ // quarantine cause) when a `claude --version` health probe ALSO fails —
300
+ // that probe being the authoritative "is the binary/host actually broken?"
301
+ // tiebreaker. `heuristic: true` is preserved so the runner still applies
302
+ // the retry-once tune before pausing.
112
303
  if (durationMs !== undefined &&
113
304
  durationMs < FAST_EXIT_MS &&
114
305
  stderr.trim().length === 0 &&
115
306
  stdout.trim().length < FAST_EXIT_MAX_OUTPUT_BYTES) {
116
307
  return {
117
308
  exitCode,
118
- class: "env_broken",
119
- detail: `claude exited ${exitCode ?? "signal"} in ${durationMs}ms with empty output (env_broken heuristic)`,
120
- // v0.53 T-53-4: flag the heuristic origin so the task-runner applies
121
- // the "retry once, quarantine only on 2 consecutive" tune rather than
122
- // benching the machine on a single instant-empty blip.
309
+ class: "claude_unavailable",
310
+ detail: `claude exited ${exitCode ?? "signal"} in ${durationMs}ms with empty output (silent instant-empty — claude momentarily unavailable, retrying)`,
123
311
  heuristic: true,
124
312
  };
125
313
  }
@@ -1 +1 @@
1
- {"version":3,"file":"failure-classifier.js","sourceRoot":"","sources":["../src/failure-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA2BH,MAAM,oBAAoB,GAAa;IACrC,cAAc;IACd,gDAAgD;IAChD,sBAAsB;IACtB,iBAAiB;IACjB,sBAAsB;IACtB,aAAa;IACb,iBAAiB;IACjB,sBAAsB;IACtB,oCAAoC;CACrC,CAAC;AAEF,MAAM,qBAAqB,GAAa;IACtC,kBAAkB;IAClB,yBAAyB;IACzB,oBAAoB;IACpB,eAAe;IACf,0CAA0C;IAC1C,mBAAmB;IACnB,yCAAyC;IACzC,oBAAoB;IACpB,uBAAuB;IACvB,gBAAgB;CACjB,CAAC;AAEF,yEAAyE;AACzE,4EAA4E;AAC5E,2EAA2E;AAC3E,MAAM,mBAAmB,GAAa;IACpC,8BAA8B;IAC9B,qBAAqB;IACrB,kBAAkB;IAClB,oCAAoC;IACpC,QAAQ;IACR,aAAa;IACb,qBAAqB;IACrB,SAAS;IACT,eAAe;IACf,oBAAoB;IACpB,4BAA4B;IAC5B,0BAA0B;IAC1B,WAAW;IACX,SAAS;IACT,6BAA6B;CAC9B,CAAC;AAEF,kEAAkE;AAClE,sEAAsE;AACtE,4EAA4E;AAC5E,MAAM,YAAY,GAAG,KAAK,CAAC;AAC3B,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAEvC,SAAS,UAAU,CAAC,IAAY,EAAE,QAAkB;IAClD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAAuB,EACvB,MAAc,EACd,MAAc,EACd,UAAmB;IAEnB,mEAAmE;IACnE,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;QACrB,OAAO;YACL,QAAQ;YACR,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,4CAA4C;SACrD,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,MAAM,KAAK,MAAM,EAAE,CAAC;IAExC,IAAI,UAAU,CAAC,QAAQ,EAAE,oBAAoB,CAAC,EAAE,CAAC;QAC/C,OAAO;YACL,QAAQ;YACR,KAAK,EAAE,aAAa;YACpB,MAAM,EAAE,wCAAwC;SACjD,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,CAAC,QAAQ,EAAE,qBAAqB,CAAC,EAAE,CAAC;QAChD,OAAO;YACL,QAAQ;YACR,KAAK,EAAE,cAAc;YACrB,MAAM,EAAE,6DAA6D;SACtE,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,CAAC,QAAQ,EAAE,mBAAmB,CAAC,EAAE,CAAC;QAC9C,OAAO;YACL,QAAQ;YACR,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,mDAAmD;SAC5D,CAAC;IACJ,CAAC;IAED,kEAAkE;IAClE,wEAAwE;IACxE,qEAAqE;IACrE,qEAAqE;IACrE,IACE,UAAU,KAAK,SAAS;QACxB,UAAU,GAAG,YAAY;QACzB,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAC1B,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,0BAA0B,EACjD,CAAC;QACD,OAAO;YACL,QAAQ;YACR,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,iBAAiB,QAAQ,IAAI,QAAQ,OAAO,UAAU,6CAA6C;YAC3G,qEAAqE;YACrE,sEAAsE;YACtE,uDAAuD;YACvD,SAAS,EAAE,IAAI;SAChB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ;QACR,KAAK,EAAE,YAAY;QACnB,MAAM,EAAE,iBAAiB,QAAQ,IAAI,QAAQ,uBAAuB;KACrE,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"failure-classifier.js","sourceRoot":"","sources":["../src/failure-classifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ export type IntegrityAssertion = "conflict_markers" | "typecheck" | "version_regression" | "changelog_missing";
2
+ export interface IntegrityFailure {
3
+ assertion: IntegrityAssertion;
4
+ /** Human-readable, log-safe (no secrets) explanation of the failure. */
5
+ detail: string;
6
+ /** Offending tracked files, when the assertion is file-scoped. */
7
+ files?: string[];
8
+ }
9
+ export interface ResolutionIntegrityResult {
10
+ ok: boolean;
11
+ /** Assertions that actually ran (version checks skip when nothing changed). */
12
+ checked: IntegrityAssertion[];
13
+ failures: IntegrityFailure[];
14
+ }
15
+ /** A package.json / CHANGELOG.md pair to version-check, relative to workdir. */
16
+ export interface VersionTarget {
17
+ packageJsonPath: string;
18
+ changelogPath: string;
19
+ }
20
+ export interface AssertResolutionOptions {
21
+ /**
22
+ * Base ref the resolution should not regress against (e.g. the integration
23
+ * branch). When omitted, or when the base file can't be read, the version
24
+ * assertion is skipped — never false-failed.
25
+ */
26
+ baseRef?: string;
27
+ /** Typecheck command (defaults to `pnpm typecheck`). */
28
+ typecheckCmd?: string;
29
+ /**
30
+ * package.json / CHANGELOG.md pairs to version-check. Defaults to the repo
31
+ * root pair. The runner passes the acc-runner package pair (the #496 site).
32
+ */
33
+ versionTargets?: VersionTarget[];
34
+ }
35
+ export interface ResolutionIntegrityDeps {
36
+ /** Tracked files still carrying a conflict marker. Default: `git grep`. */
37
+ findConflictMarkers?: (workdir: string) => Promise<string[]>;
38
+ /** Run the typecheck command. Default: spawn `pnpm typecheck` in workdir. */
39
+ runTypecheck?: (workdir: string, cmd: string) => Promise<{
40
+ ok: boolean;
41
+ output: string;
42
+ }>;
43
+ /** Resolved (post-resolution, on-disk) version for a target, or null. */
44
+ readResolvedVersion?: (workdir: string, target: VersionTarget) => Promise<string | null>;
45
+ /** Base-ref version for a target, or null when unreadable (→ skip check). */
46
+ readBaseVersion?: (workdir: string, baseRef: string, target: VersionTarget) => Promise<string | null>;
47
+ /** CHANGELOG.md text for a target, or null when absent. */
48
+ readChangelog?: (workdir: string, target: VersionTarget) => Promise<string | null>;
49
+ }
50
+ /**
51
+ * Conflict-marker line shape: 7 of the same marker char at the start of a
52
+ * line. `<<<<<<<` and `>>>>>>>` are unambiguous; the `=======` divider is
53
+ * matched only as a whole line so a 7-equals markdown rule plus trailing text
54
+ * does not trip it.
55
+ */
56
+ export declare const CONFLICT_MARKER_RE: RegExp;
57
+ export declare function textHasConflictMarker(text: string): boolean;
58
+ /** Semver compare (a-b sign); tolerant of pre-release/build suffixes. */
59
+ export declare function cmpSemver(a: string, b: string): number;
60
+ /**
61
+ * True when `changelog` carries an entry for `version`. The version must
62
+ * appear bounded by non-version characters so 0.14.0 does not match inside
63
+ * 0.14.00 or 10.14.0.
64
+ */
65
+ export declare function changelogMentionsVersion(changelog: string, version: string): boolean;
66
+ export declare const DEFAULT_VERSION_TARGET: VersionTarget;
67
+ /**
68
+ * Assert that a conflict resolution in `workdir` is shippable. Returns a
69
+ * structured result; `ok === false` means the caller MUST reject the
70
+ * resolution (do not push, do not mark resolved).
71
+ */
72
+ export declare function assertResolutionIntegrity(workdir: string, opts?: AssertResolutionOptions, deps?: ResolutionIntegrityDeps): Promise<ResolutionIntegrityResult>;
73
+ /**
74
+ * True when a task that reaches the worktree/push path is a conflict
75
+ * resolution and must clear the integrity guardrail. `conflict_resolution`
76
+ * task types are handled mechanically upstream and never reach the push path,
77
+ * so the live signal here is the title an operator/manager files when the
78
+ * mechanical resolver bails and a Claude session takes over the merge.
79
+ */
80
+ export declare function isConflictResolutionTask(task: {
81
+ type?: string | null;
82
+ title?: string | null;
83
+ }): boolean;
84
+ /** One-line, log-safe summary of which assertions failed. */
85
+ export declare function summariseFailures(failures: IntegrityFailure[]): string;
86
+ //# sourceMappingURL=resolution-integrity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolution-integrity.d.ts","sourceRoot":"","sources":["../../src/runtime/resolution-integrity.ts"],"names":[],"mappings":"AAsCA,MAAM,MAAM,kBAAkB,GAC1B,kBAAkB,GAClB,WAAW,GACX,oBAAoB,GACpB,mBAAmB,CAAC;AAExB,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,kBAAkB,CAAC;IAC9B,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,OAAO,CAAC;IACZ,+EAA+E;IAC/E,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAED,gFAAgF;AAChF,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,2EAA2E;IAC3E,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7D,6EAA6E;IAC7E,YAAY,CAAC,EAAE,CACb,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,KACR,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,CACpB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,KAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5B,6EAA6E;IAC7E,eAAe,CAAC,EAAE,CAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,KAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5B,2DAA2D;IAC3D,aAAa,CAAC,EAAE,CACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,KAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC7B;AAMD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,QAAsC,CAAC;AAEtE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAQtD;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAGT;AAED,eAAO,MAAM,sBAAsB,EAAE,aAGpC,CAAC;AAqGF;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,uBAA4B,EAClC,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,yBAAyB,CAAC,CAgFpC;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC7C,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,GAAG,OAAO,CAIV;AAED,6DAA6D;AAC7D,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAEtE"}