@tokenfactory/acc-runner 0.38.3 → 0.40.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.
@@ -0,0 +1,66 @@
1
+ import type { ClaudeExitClass } from "../failure-classifier.js";
2
+ /**
3
+ * Failure classes that OPEN the chat circuit. These mirror the batch lane's
4
+ * "machine-level, not task-level" split: a spent/broken CREDENTIAL or a broken
5
+ * HOST is a `claude_exit_1`-class fault the runner cannot serve chat through, so
6
+ * it stops claiming chat turns. Recoverable-capacity classes
7
+ * (`capacity_exhausted`, `subscription_exhausted`, transient `claude_unavailable`)
8
+ * are NOT here — those merely requeue the turn; capacity is a resource, not a
9
+ * fault, and quarantining chat on a resettable window would needlessly bench it.
10
+ */
11
+ export declare const CHAT_CIRCUIT_TRIP_CLASSES: readonly ClaudeExitClass[];
12
+ /** True when `cls` is a chat-circuit-opening (`claude_exit_1`-class) failure. */
13
+ export declare function isChatCircuitTripClass(cls: ClaudeExitClass): boolean;
14
+ /**
15
+ * Persisted chat-circuit sentinel. Shape mirrors QuarantineState but is a
16
+ * DISTINCT file so the two fault domains stay independent; `turnId` /
17
+ * `conversationId` replace the batch `taskId` so `doctor` can show which chat
18
+ * turn tripped the breaker.
19
+ */
20
+ export interface ChatCircuitState {
21
+ cause: ClaudeExitClass;
22
+ trippedAt: string;
23
+ turnId: string;
24
+ conversationId: string;
25
+ detail: string;
26
+ }
27
+ /** Path to the chat-circuit sentinel (per-runner via the shared cacheDir()). */
28
+ export declare function chatCircuitFile(): string;
29
+ /** Current tripped state, or null when the chat circuit is closed. */
30
+ export declare function getChatCircuit(): Promise<ChatCircuitState | null>;
31
+ /** Write the chat-circuit sentinel (opens the circuit). Creates parent dirs. */
32
+ export declare function setChatCircuit(state: ChatCircuitState): Promise<void>;
33
+ /** Remove the chat-circuit sentinel (closes the circuit). Safe when closed. */
34
+ export declare function clearChatCircuit(): Promise<void>;
35
+ /**
36
+ * In-memory chat circuit breaker. Loaded from the sentinel at boot so a runner
37
+ * that restarts while its chat credential is still broken stays open until an
38
+ * operator clears it. `trip()` is idempotent — a second concurrent chat-turn
39
+ * failure never overwrites the first cause or re-persists — so racing failures
40
+ * on two in-flight turns open the circuit exactly once.
41
+ */
42
+ export declare class ChatCircuitBreaker {
43
+ private open;
44
+ private state;
45
+ /** Hydrate the in-memory flag from the on-disk sentinel (call once at boot). */
46
+ load(): Promise<void>;
47
+ /** True while the chat circuit is open (runner must not claim chat turns). */
48
+ isOpen(): boolean;
49
+ /** The cause + provenance of the open circuit, or null when closed. */
50
+ current(): ChatCircuitState | null;
51
+ /**
52
+ * Open the circuit for a `claude_exit_1`-class chat failure. Idempotent: a
53
+ * no-op (returns false) when already open, so two concurrent turn failures
54
+ * trip it once. Returns true when this call opened it.
55
+ */
56
+ trip(args: {
57
+ cause: ClaudeExitClass;
58
+ turnId: string;
59
+ conversationId: string;
60
+ detail: string;
61
+ now?: () => number;
62
+ }): Promise<boolean>;
63
+ /** Close the circuit (operator resolved the underlying issue). */
64
+ reset(): Promise<void>;
65
+ }
66
+ //# sourceMappingURL=chat-circuit-breaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-circuit-breaker.d.ts","sourceRoot":"","sources":["../../src/runtime/chat-circuit-breaker.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS,eAAe,EAI/D,CAAC;AAEF,iFAAiF;AACjF,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAEpE;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,eAAe,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,gFAAgF;AAChF,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,sEAAsE;AACtE,wBAAsB,cAAc,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAQvE;AAED,gFAAgF;AAChF,wBAAsB,cAAc,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3E;AAED,+EAA+E;AAC/E,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMtD;AAED;;;;;;GAMG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,KAAK,CAAiC;IAE9C,gFAAgF;IAC1E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,8EAA8E;IAC9E,MAAM,IAAI,OAAO;IAIjB,uEAAuE;IACvE,OAAO,IAAI,gBAAgB,GAAG,IAAI;IAIlC;;;;OAIG;IACG,IAAI,CAAC,IAAI,EAAE;QACf,KAAK,EAAE,eAAe,CAAC;QACvB,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,EAAE,MAAM,CAAC;QACvB,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBpB,kEAAkE;IAC5D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK7B"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * CC-1B (TURN-LANE): the runner's CHAT-CAPABILITY circuit breaker.
3
+ *
4
+ * The batch lane's whole-runner quarantine (runtime/quarantine.ts) benches the
5
+ * ENTIRE runner — no task, no review, no chat — when the host/binary is broken.
6
+ * The chat lane needs a NARROWER fault domain: a `claude_exit_1`-class failure
7
+ * that surfaces while serving a chat turn must stop the runner claiming further
8
+ * CHAT turns (and requeue the in-flight one so another companion can finish it),
9
+ * WITHOUT benching the code/review lanes — a flaky chat credential should never
10
+ * starve the fleet's build throughput. This module is that scoped breaker.
11
+ *
12
+ * It deliberately REUSES the quarantine.ts recipe (a JSON sentinel under the
13
+ * shared cacheDir, an in-memory flag loaded from it at boot, a `ClaudeExitClass`
14
+ * cause) rather than inventing a new persistence shape — the two are siblings,
15
+ * one per fault domain. The sentinel filename differs (`chat-quarantine.json`)
16
+ * so the chat breaker and the whole-runner quarantine never clobber each other.
17
+ *
18
+ * Tripping the breaker is a CIRCUIT-OPEN, not a task failure: the turn that
19
+ * tripped it is REQUEUED (not burned) so it survives on another companion, and
20
+ * an operator clears the breaker (`acc-runner chat-circuit clear`, or deleting
21
+ * the file) once the underlying credential/host issue is fixed. `acc-runner
22
+ * doctor` surfaces the tripped state and its cause alongside the quarantine.
23
+ */
24
+ import fs from "node:fs/promises";
25
+ import path from "node:path";
26
+ import { cacheDir } from "./cache-dir.js";
27
+ /**
28
+ * Failure classes that OPEN the chat circuit. These mirror the batch lane's
29
+ * "machine-level, not task-level" split: a spent/broken CREDENTIAL or a broken
30
+ * HOST is a `claude_exit_1`-class fault the runner cannot serve chat through, so
31
+ * it stops claiming chat turns. Recoverable-capacity classes
32
+ * (`capacity_exhausted`, `subscription_exhausted`, transient `claude_unavailable`)
33
+ * are NOT here — those merely requeue the turn; capacity is a resource, not a
34
+ * fault, and quarantining chat on a resettable window would needlessly bench it.
35
+ */
36
+ export const CHAT_CIRCUIT_TRIP_CLASSES = [
37
+ "auth_expired",
38
+ "env_broken",
39
+ "usage_limit",
40
+ ];
41
+ /** True when `cls` is a chat-circuit-opening (`claude_exit_1`-class) failure. */
42
+ export function isChatCircuitTripClass(cls) {
43
+ return CHAT_CIRCUIT_TRIP_CLASSES.includes(cls);
44
+ }
45
+ /** Path to the chat-circuit sentinel (per-runner via the shared cacheDir()). */
46
+ export function chatCircuitFile() {
47
+ return path.join(cacheDir(), "chat-quarantine.json");
48
+ }
49
+ /** Current tripped state, or null when the chat circuit is closed. */
50
+ export async function getChatCircuit() {
51
+ try {
52
+ const raw = await fs.readFile(chatCircuitFile(), "utf8");
53
+ return JSON.parse(raw);
54
+ }
55
+ catch (err) {
56
+ if (err.code === "ENOENT")
57
+ return null;
58
+ throw err;
59
+ }
60
+ }
61
+ /** Write the chat-circuit sentinel (opens the circuit). Creates parent dirs. */
62
+ export async function setChatCircuit(state) {
63
+ const file = chatCircuitFile();
64
+ await fs.mkdir(path.dirname(file), { recursive: true });
65
+ await fs.writeFile(file, JSON.stringify(state, null, 2), "utf8");
66
+ }
67
+ /** Remove the chat-circuit sentinel (closes the circuit). Safe when closed. */
68
+ export async function clearChatCircuit() {
69
+ try {
70
+ await fs.unlink(chatCircuitFile());
71
+ }
72
+ catch (err) {
73
+ if (err.code !== "ENOENT")
74
+ throw err;
75
+ }
76
+ }
77
+ /**
78
+ * In-memory chat circuit breaker. Loaded from the sentinel at boot so a runner
79
+ * that restarts while its chat credential is still broken stays open until an
80
+ * operator clears it. `trip()` is idempotent — a second concurrent chat-turn
81
+ * failure never overwrites the first cause or re-persists — so racing failures
82
+ * on two in-flight turns open the circuit exactly once.
83
+ */
84
+ export class ChatCircuitBreaker {
85
+ open = false;
86
+ state = null;
87
+ /** Hydrate the in-memory flag from the on-disk sentinel (call once at boot). */
88
+ async load() {
89
+ this.state = await getChatCircuit();
90
+ this.open = this.state !== null;
91
+ }
92
+ /** True while the chat circuit is open (runner must not claim chat turns). */
93
+ isOpen() {
94
+ return this.open;
95
+ }
96
+ /** The cause + provenance of the open circuit, or null when closed. */
97
+ current() {
98
+ return this.state;
99
+ }
100
+ /**
101
+ * Open the circuit for a `claude_exit_1`-class chat failure. Idempotent: a
102
+ * no-op (returns false) when already open, so two concurrent turn failures
103
+ * trip it once. Returns true when this call opened it.
104
+ */
105
+ async trip(args) {
106
+ if (this.open)
107
+ return false;
108
+ const now = args.now ?? Date.now;
109
+ const state = {
110
+ cause: args.cause,
111
+ trippedAt: new Date(now()).toISOString(),
112
+ turnId: args.turnId,
113
+ conversationId: args.conversationId,
114
+ detail: args.detail,
115
+ };
116
+ this.open = true;
117
+ this.state = state;
118
+ await setChatCircuit(state);
119
+ return true;
120
+ }
121
+ /** Close the circuit (operator resolved the underlying issue). */
122
+ async reset() {
123
+ this.open = false;
124
+ this.state = null;
125
+ await clearChatCircuit();
126
+ }
127
+ }
128
+ //# sourceMappingURL=chat-circuit-breaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-circuit-breaker.js","sourceRoot":"","sources":["../../src/runtime/chat-circuit-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAA+B;IACnE,cAAc;IACd,YAAY;IACZ,aAAa;CACd,CAAC;AAEF,iFAAiF;AACjF,MAAM,UAAU,sBAAsB,CAAC,GAAoB;IACzD,OAAO,yBAAyB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACjD,CAAC;AAgBD,gFAAgF;AAChF,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,sBAAsB,CAAC,CAAC;AACvD,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,MAAM,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAqB,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAClE,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAuB;IAC1D,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACnE,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,GAAG,CAAC;IAClE,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,kBAAkB;IACrB,IAAI,GAAG,KAAK,CAAC;IACb,KAAK,GAA4B,IAAI,CAAC;IAE9C,gFAAgF;IAChF,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC;IAClC,CAAC;IAED,8EAA8E;IAC9E,MAAM;QACJ,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,uEAAuE;IACvE,OAAO;QACL,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,IAAI,CAAC,IAMV;QACC,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;QACjC,MAAM,KAAK,GAAqB;YAC9B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE;YACxC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,MAAM,gBAAgB,EAAE,CAAC;IAC3B,CAAC;CACF"}
package/dist/types.d.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  export { PROTOCOL_VERSION } from "./pkg-version.js";
9
9
  export declare const RUNNER_KEYCHAIN_SERVICE: "acc-runner";
10
10
  export type { MessagingState, RunnerProtocol } from "./messaging.js";
11
+ import type { ConcurrencySource } from "./config.js";
11
12
  export interface DeviceCodeResponse {
12
13
  device_code: string;
13
14
  user_code: string;
@@ -148,6 +149,13 @@ export interface RunnerCaps {
148
149
  * can compute executor slots = concurrency − reserve without guessing.
149
150
  */
150
151
  reserved_review_slots?: number;
152
+ /**
153
+ * RUNCFG-1: where the advertised `concurrency` came from — "server" (operator
154
+ * set acc.runners.desired_concurrency), "env" (ACC_RUNNER_CONCURRENCY), or
155
+ * "default" (compiled). Published so a misconfig ("advertised 5, operator set
156
+ * 50") is visible in the caps and the Runners UI. Additive/optional.
157
+ */
158
+ concurrency_source?: ConcurrencySource;
151
159
  }
152
160
  export interface StoredSession {
153
161
  access_token: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/watch.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { RealtimeChannel } from "@supabase/supabase-js";
2
- import { type RunnerConfig } from "./config.js";
2
+ import { type ConcurrencySource, type RunnerConfig } from "./config.js";
3
3
  export { resolveConcurrencyLimit, resolveReservedReviewSlots } from "./config.js";
4
4
  import { type TokenProvider } from "./token-provider.js";
5
5
  import { type RunnerSupabaseClient } from "./supabase.js";
@@ -288,6 +288,32 @@ interface WatchState {
288
288
  * 1). Clamped away on a single-slot runner — see computeTaskClaimLimit.
289
289
  */
290
290
  reservedReviewSlots: number;
291
+ /**
292
+ * RUNCFG-1: the env-or-default concurrency base (before any server override).
293
+ * `concurrencyLimit` above is the LIVE effective ceiling and may be raised or
294
+ * lowered by an operator's acc.runners.desired_concurrency on any heartbeat;
295
+ * this base is what the runner falls back to when the server override is
296
+ * cleared (set back to NULL). Captured once at startup.
297
+ */
298
+ baseConcurrency: number;
299
+ baseReservedReviewSlots: number;
300
+ /** RUNCFG-1: whether ACC_RUNNER_CONCURRENCY was explicitly set (env vs default). */
301
+ concurrencyEnvExplicit: boolean;
302
+ /**
303
+ * RUNCFG-1: where the LIVE `concurrencyLimit` currently comes from
304
+ * (server|env|default). Published into caps.concurrency_source via
305
+ * runner_pull_concurrency and logged on every change so a "runner advertised
306
+ * 5 while operator set 50" misconfig is visible.
307
+ */
308
+ concurrencySource: ConcurrencySource;
309
+ /**
310
+ * RUNCFG-1: single-flight + change tracking for the caps republish. The
311
+ * runner only writes caps.concurrency* when its effective value actually
312
+ * changes (or on the first heartbeat) — steady-state pulls pass NULL so the
313
+ * heartbeat path is a read, not a per-tick caps UPDATE. `false` until the
314
+ * first successful publish.
315
+ */
316
+ concurrencyCapsPublished: boolean;
291
317
  /**
292
318
  * RVU-2 (FU-RVU2R): claim-pause-before-review-pause. Set true when a review
293
319
  * signals capacity pressure (ReviewerOutcome.capacity_degraded) so pump()
@@ -1 +1 @@
1
- {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"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"}
package/dist/watch.js CHANGED
@@ -26,7 +26,7 @@
26
26
  * arms a clean self-termination after n minutes without work.
27
27
  */
28
28
  import chalk from "chalk";
29
- import { applyBootstrapConfig, loadConfig, supabaseConfigSource, resolveRunnerConcurrency, } from "./config.js";
29
+ import { applyBootstrapConfig, concurrencyEnvExplicit, loadConfig, resolveEffectiveConcurrency, supabaseConfigSource, resolveRunnerConcurrency, } from "./config.js";
30
30
  // CONC-1: these resolvers moved to config.ts so login.ts
31
31
  // can share them without a login→watch import cycle. Re-exported here so
32
32
  // existing tests that import them from `../src/watch.js` keep resolving.
@@ -1186,6 +1186,14 @@ export async function watchCommand(options = {}) {
1186
1186
  // them once guarantees no drift between what the runner runs and advertises.
1187
1187
  concurrencyLimit,
1188
1188
  reservedReviewSlots,
1189
+ // RUNCFG-1: the env/default base the live ceiling falls back to when the
1190
+ // server override is cleared, plus the initial source label. An operator's
1191
+ // desired_concurrency overrides `concurrencyLimit` live (applyServerConcurrency).
1192
+ baseConcurrency: concurrencyLimit,
1193
+ baseReservedReviewSlots: reservedReviewSlots,
1194
+ concurrencyEnvExplicit: concurrencyEnvExplicit(),
1195
+ concurrencySource: concurrencyEnvExplicit() ? "env" : "default",
1196
+ concurrencyCapsPublished: false,
1189
1197
  // RVU-2 (FU-RVU2R): claim-pause starts off; set under review capacity pressure.
1190
1198
  capacityClaimPaused: false,
1191
1199
  queue: [],
@@ -1353,6 +1361,11 @@ export async function watchCommand(options = {}) {
1353
1361
  p_id: state.session.runner_id,
1354
1362
  p_version: PACKAGE_VERSION,
1355
1363
  });
1364
+ // RUNCFG-1: pull + apply any server-set concurrency at startup (and publish
1365
+ // the effective ceiling + source into caps) so a runner that boots with an
1366
+ // operator override already in place honours it from the first tick, not only
1367
+ // after the first scheduled heartbeat.
1368
+ await syncConcurrency(state, taskRunnerFactory);
1356
1369
  console.log(chalk.gray(`Runner ${state.session.runner_id} is online. Ctrl-C to stop.`));
1357
1370
  const stop = async () => {
1358
1371
  if (state.stopped)
@@ -1469,6 +1482,88 @@ export async function watchCommand(options = {}) {
1469
1482
  runningCount: () => state.running.size,
1470
1483
  };
1471
1484
  }
1485
+ /**
1486
+ * RUNCFG-1: apply the operator's server-set concurrency to the LIVE watch-loop
1487
+ * ceiling, precedence server-set > env > default. Idempotent: a no-change row
1488
+ * is a no-op. On a real change it updates the ceiling in place (no restart), so
1489
+ * pump() picks up the new limit on its next pass — a GROW immediately fills the
1490
+ * freed slots; a SHRINK applies as in-flight tasks free their slots (running
1491
+ * tasks are never interrupted). Marks caps for republish so the server-side
1492
+ * runnerReviewSlots() and the UI see the new effective value + source.
1493
+ */
1494
+ function applyServerConcurrency(state, row, factory) {
1495
+ const eff = resolveEffectiveConcurrency({
1496
+ serverConcurrency: row?.desired_concurrency ?? null,
1497
+ serverReserve: row?.desired_reserved_review_slots ?? null,
1498
+ envConcurrency: state.baseConcurrency,
1499
+ envReserve: state.baseReservedReviewSlots,
1500
+ envExplicit: state.concurrencyEnvExplicit,
1501
+ });
1502
+ if (eff.concurrency === state.concurrencyLimit &&
1503
+ eff.reservedReviewSlots === state.reservedReviewSlots &&
1504
+ eff.source === state.concurrencySource) {
1505
+ return false;
1506
+ }
1507
+ const prevLimit = state.concurrencyLimit;
1508
+ const prevSource = state.concurrencySource;
1509
+ console.log(chalk.cyan(`[acc-runner] concurrency ${prevLimit}→${eff.concurrency} ` +
1510
+ `(reserve ${state.reservedReviewSlots}→${eff.reservedReviewSlots}, ` +
1511
+ `source ${prevSource}→${eff.source}) — applied live, no restart`));
1512
+ state.concurrencyLimit = eff.concurrency;
1513
+ state.reservedReviewSlots = eff.reservedReviewSlots;
1514
+ state.concurrencySource = eff.source;
1515
+ // Republish the new effective value + source into caps on the next heartbeat.
1516
+ state.concurrencyCapsPublished = false;
1517
+ void (async () => {
1518
+ try {
1519
+ await state.supabase.rpc("log_activity", {
1520
+ p_verb: "runner.concurrency_applied",
1521
+ p_target_id: state.session.runner_id,
1522
+ p_payload: {
1523
+ concurrency: eff.concurrency,
1524
+ reserved_review_slots: eff.reservedReviewSlots,
1525
+ source: eff.source,
1526
+ version: PACKAGE_VERSION,
1527
+ },
1528
+ p_target_type: "runner",
1529
+ });
1530
+ }
1531
+ catch { /* best-effort breadcrumb */ }
1532
+ })();
1533
+ // GROW: new slots are available now — pump to fill them. SHRINK needs no
1534
+ // action; pump already stops launching once running.size >= the new limit.
1535
+ if (eff.concurrency > prevLimit)
1536
+ void pump(state, factory);
1537
+ return true;
1538
+ }
1539
+ /**
1540
+ * RUNCFG-1: one concurrency sync round-trip, folded into the heartbeat cadence.
1541
+ * Reads acc.runners.desired_* (so applyServerConcurrency can retune the live
1542
+ * ceiling within one heartbeat) and — only when the effective value is stale in
1543
+ * caps (first sync or after a change) — publishes the runner's effective
1544
+ * ceiling + source so the server never writes a per-tick caps UPDATE in steady
1545
+ * state. Best-effort: an error just skips this round (the next heartbeat retries)
1546
+ * and never disturbs the heartbeat-failure ladder.
1547
+ */
1548
+ async function syncConcurrency(state, factory) {
1549
+ const publish = !state.concurrencyCapsPublished;
1550
+ const { data, error } = await state.supabase.rpc("runner_pull_concurrency", {
1551
+ p_id: state.session.runner_id,
1552
+ p_effective: publish ? state.concurrencyLimit : null,
1553
+ p_reserve: publish ? state.reservedReviewSlots : null,
1554
+ p_source: publish ? state.concurrencySource : null,
1555
+ });
1556
+ if (error) {
1557
+ // A pre-0260 server 404s this RPC — non-fatal, exactly like
1558
+ // set_runner_capabilities / set_runner_repos on an older deploy. The runner
1559
+ // keeps its env/default ceiling.
1560
+ return;
1561
+ }
1562
+ if (publish)
1563
+ state.concurrencyCapsPublished = true;
1564
+ const row = (Array.isArray(data) ? data[0] : data);
1565
+ applyServerConcurrency(state, row, factory);
1566
+ }
1472
1567
  function scheduleHeartbeat(state, taskRunnerFactory, baseMs) {
1473
1568
  if (state.stopped)
1474
1569
  return;
@@ -1481,6 +1576,11 @@ function scheduleHeartbeat(state, taskRunnerFactory, baseMs) {
1481
1576
  });
1482
1577
  if (!error) {
1483
1578
  state.heartbeatFailures = 0;
1579
+ // RUNCFG-1: pull the operator's server-set concurrency and apply it to
1580
+ // the live ceiling within this heartbeat. Runs only on a healthy
1581
+ // heartbeat (a network/auth failure would fail this RPC too). Awaited so
1582
+ // a test's forced heartbeat sees the ceiling settled before it asserts.
1583
+ await syncConcurrency(state, taskRunnerFactory);
1484
1584
  }
1485
1585
  else {
1486
1586
  state.heartbeatFailures += 1;