@mobrienv/autoloop-harness 0.7.4 → 0.9.1
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/acceptance.d.ts +31 -0
- package/dist/acceptance.js +69 -0
- package/dist/acceptance.js.map +1 -0
- package/dist/ask.d.ts +16 -0
- package/dist/ask.js +47 -0
- package/dist/ask.js.map +1 -0
- package/dist/backend/types.d.ts +16 -0
- package/dist/backend/types.js +17 -0
- package/dist/backend/types.js.map +1 -0
- package/dist/circuit-breaker.d.ts +27 -0
- package/dist/circuit-breaker.js +41 -0
- package/dist/circuit-breaker.js.map +1 -0
- package/dist/completion-lint.d.ts +29 -0
- package/dist/completion-lint.js +51 -0
- package/dist/completion-lint.js.map +1 -0
- package/dist/config-helpers.d.ts +10 -2
- package/dist/config-helpers.js +272 -30
- package/dist/config-helpers.js.map +1 -1
- package/dist/control/acp-adapter.d.ts +12 -0
- package/dist/control/acp-adapter.js +54 -0
- package/dist/control/acp-adapter.js.map +1 -0
- package/dist/control/adapter.d.ts +12 -0
- package/dist/control/adapter.js +2 -0
- package/dist/control/adapter.js.map +1 -0
- package/dist/control/capabilities.d.ts +9 -0
- package/dist/control/capabilities.js +27 -0
- package/dist/control/capabilities.js.map +1 -0
- package/dist/control/claude-sdk-adapter.d.ts +15 -0
- package/dist/control/claude-sdk-adapter.js +79 -0
- package/dist/control/claude-sdk-adapter.js.map +1 -0
- package/dist/control/command-adapter.d.ts +19 -0
- package/dist/control/command-adapter.js +57 -0
- package/dist/control/command-adapter.js.map +1 -0
- package/dist/control/dispatch.d.ts +14 -0
- package/dist/control/dispatch.js +55 -0
- package/dist/control/dispatch.js.map +1 -0
- package/dist/control/index.d.ts +11 -0
- package/dist/control/index.js +9 -0
- package/dist/control/index.js.map +1 -0
- package/dist/control/kiro-adapter.d.ts +2 -0
- package/dist/control/kiro-adapter.js +2 -0
- package/dist/control/kiro-adapter.js.map +1 -0
- package/dist/control/paths.d.ts +19 -0
- package/dist/control/paths.js +40 -0
- package/dist/control/paths.js.map +1 -0
- package/dist/control/pi-adapter.d.ts +15 -0
- package/dist/control/pi-adapter.js +76 -0
- package/dist/control/pi-adapter.js.map +1 -0
- package/dist/control/queue.d.ts +14 -0
- package/dist/control/queue.js +82 -0
- package/dist/control/queue.js.map +1 -0
- package/dist/control/render.d.ts +10 -0
- package/dist/control/render.js +53 -0
- package/dist/control/render.js.map +1 -0
- package/dist/control/types.d.ts +56 -0
- package/dist/control/types.js +9 -0
- package/dist/control/types.js.map +1 -0
- package/dist/display.d.ts +9 -2
- package/dist/display.js +37 -1
- package/dist/display.js.map +1 -1
- package/dist/emit.d.ts +27 -0
- package/dist/emit.js +327 -6
- package/dist/emit.js.map +1 -1
- package/dist/events.d.ts +36 -3
- package/dist/fanout-runner.d.ts +25 -0
- package/dist/fanout-runner.js +54 -0
- package/dist/fanout-runner.js.map +1 -0
- package/dist/file-mod-audit.d.ts +29 -0
- package/dist/file-mod-audit.js +63 -0
- package/dist/file-mod-audit.js.map +1 -0
- package/dist/git-diff.d.ts +19 -0
- package/dist/git-diff.js +74 -0
- package/dist/git-diff.js.map +1 -0
- package/dist/guards.d.ts +37 -0
- package/dist/guards.js +78 -0
- package/dist/guards.js.map +1 -0
- package/dist/hooks.d.ts +78 -0
- package/dist/hooks.js +239 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +15 -2
- package/dist/index.js +359 -26
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +45 -0
- package/dist/intent.js +127 -0
- package/dist/intent.js.map +1 -0
- package/dist/iteration-diff.d.ts +32 -0
- package/dist/iteration-diff.js +92 -0
- package/dist/iteration-diff.js.map +1 -0
- package/dist/iteration.d.ts +20 -0
- package/dist/iteration.js +551 -30
- package/dist/iteration.js.map +1 -1
- package/dist/metareview.d.ts +9 -1
- package/dist/metareview.js +158 -34
- package/dist/metareview.js.map +1 -1
- package/dist/notify.d.ts +22 -0
- package/dist/notify.js +110 -0
- package/dist/notify.js.map +1 -0
- package/dist/parallel.d.ts +17 -0
- package/dist/parallel.js +38 -6
- package/dist/parallel.js.map +1 -1
- package/dist/postconditions.d.ts +25 -0
- package/dist/postconditions.js +107 -0
- package/dist/postconditions.js.map +1 -0
- package/dist/postfire-verify.d.ts +31 -0
- package/dist/postfire-verify.js +64 -0
- package/dist/postfire-verify.js.map +1 -0
- package/dist/premature-quit.d.ts +25 -0
- package/dist/premature-quit.js +54 -0
- package/dist/premature-quit.js.map +1 -0
- package/dist/progress.d.ts +20 -0
- package/dist/progress.js +56 -0
- package/dist/progress.js.map +1 -0
- package/dist/prompt.d.ts +4 -0
- package/dist/prompt.js +42 -2
- package/dist/prompt.js.map +1 -1
- package/dist/provisional.d.ts +42 -0
- package/dist/provisional.js +92 -0
- package/dist/provisional.js.map +1 -0
- package/dist/registry-bridge.js +32 -1
- package/dist/registry-bridge.js.map +1 -1
- package/dist/resume.d.ts +61 -0
- package/dist/resume.js +226 -0
- package/dist/resume.js.map +1 -0
- package/dist/scratchpad.js +27 -8
- package/dist/scratchpad.js.map +1 -1
- package/dist/stage.d.ts +21 -0
- package/dist/stage.js +131 -0
- package/dist/stage.js.map +1 -0
- package/dist/stop.d.ts +32 -2
- package/dist/stop.js +169 -0
- package/dist/stop.js.map +1 -1
- package/dist/suspend-state.d.ts +32 -0
- package/dist/suspend-state.js +104 -0
- package/dist/suspend-state.js.map +1 -0
- package/dist/tamper.d.ts +21 -0
- package/dist/tamper.js +88 -0
- package/dist/tamper.js.map +1 -0
- package/dist/types.d.ts +294 -3
- package/dist/types.js +91 -1
- package/dist/types.js.map +1 -1
- package/dist/wave/finalize-wave.d.ts +15 -5
- package/dist/wave/finalize-wave.js +56 -2
- package/dist/wave/finalize-wave.js.map +1 -1
- package/dist/wave/launch-branches.d.ts +23 -2
- package/dist/wave/launch-branches.js +58 -3
- package/dist/wave/launch-branches.js.map +1 -1
- package/dist/wave/stage-branch-runner.d.ts +12 -0
- package/dist/wave/stage-branch-runner.js +130 -0
- package/dist/wave/stage-branch-runner.js.map +1 -0
- package/dist/wave/types.d.ts +40 -2
- package/dist/wave.d.ts +32 -1
- package/dist/wave.js +163 -34
- package/dist/wave.js.map +1 -1
- package/package.json +131 -3
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { LoopContext } from "./types.js";
|
|
2
|
+
export interface AcceptanceFailure {
|
|
3
|
+
command: string;
|
|
4
|
+
exitCode: number;
|
|
5
|
+
timedOut: boolean;
|
|
6
|
+
tail: string;
|
|
7
|
+
}
|
|
8
|
+
export interface AcceptanceResult {
|
|
9
|
+
/** False when no verify commands are configured (gate is a no-op). */
|
|
10
|
+
ran: boolean;
|
|
11
|
+
/** True when the gate ran and every command exited 0. */
|
|
12
|
+
passed: boolean;
|
|
13
|
+
failures: AcceptanceFailure[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Run the out-of-band acceptance gate for a done-claim. The HARNESS executes
|
|
17
|
+
* each `verifyCmds` entry in a clean shell rooted at the work dir — never the
|
|
18
|
+
* agent's session — so the pass/fail status is captured harness-side and cannot
|
|
19
|
+
* be faked by a prompt. Returns `passed: true` (and `ran: false`) when no
|
|
20
|
+
* commands are configured, preserving prior completion behavior.
|
|
21
|
+
*
|
|
22
|
+
* Every command's exit code and output tail is journaled as a verification
|
|
23
|
+
* artifact regardless of outcome.
|
|
24
|
+
*/
|
|
25
|
+
export declare function runAcceptanceGate(loop: LoopContext, iteration: number): AcceptanceResult;
|
|
26
|
+
/**
|
|
27
|
+
* Re-inject a failed acceptance gate's output as operator guidance so the next
|
|
28
|
+
* iteration's prompt carries the concrete failure instead of completing. This
|
|
29
|
+
* is the "do not complete; fix it" path of a deterministic gate.
|
|
30
|
+
*/
|
|
31
|
+
export declare function reinjectAcceptanceFailure(loop: LoopContext, iteration: number, result: AcceptanceResult): void;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { jsonBool, jsonField, jsonFieldRaw } from "@mobrienv/autoloop-core";
|
|
3
|
+
import { appendEvent, appendOperatorEvent, } from "@mobrienv/autoloop-core/journal";
|
|
4
|
+
import { lastNChars } from "./display.js";
|
|
5
|
+
const TAIL_CHARS = 2000;
|
|
6
|
+
/**
|
|
7
|
+
* Run the out-of-band acceptance gate for a done-claim. The HARNESS executes
|
|
8
|
+
* each `verifyCmds` entry in a clean shell rooted at the work dir — never the
|
|
9
|
+
* agent's session — so the pass/fail status is captured harness-side and cannot
|
|
10
|
+
* be faked by a prompt. Returns `passed: true` (and `ran: false`) when no
|
|
11
|
+
* commands are configured, preserving prior completion behavior.
|
|
12
|
+
*
|
|
13
|
+
* Every command's exit code and output tail is journaled as a verification
|
|
14
|
+
* artifact regardless of outcome.
|
|
15
|
+
*/
|
|
16
|
+
export function runAcceptanceGate(loop, iteration) {
|
|
17
|
+
const commands = loop.acceptance.verifyCmds;
|
|
18
|
+
const iter = String(iteration);
|
|
19
|
+
if (commands.length === 0) {
|
|
20
|
+
return { ran: false, passed: true, failures: [] };
|
|
21
|
+
}
|
|
22
|
+
appendEvent(loop.paths.journalFile, loop.runtime.runId, iter, "acceptance.start", jsonField("count", String(commands.length)));
|
|
23
|
+
const failures = [];
|
|
24
|
+
for (const command of commands) {
|
|
25
|
+
const res = spawnSync(command, {
|
|
26
|
+
shell: "/bin/sh",
|
|
27
|
+
cwd: loop.paths.workDir,
|
|
28
|
+
encoding: "utf-8",
|
|
29
|
+
timeout: loop.acceptance.timeoutMs,
|
|
30
|
+
maxBuffer: 50 * 1024 * 1024,
|
|
31
|
+
});
|
|
32
|
+
const timedOut = res.signal === "SIGTERM" ||
|
|
33
|
+
res.error?.code === "ETIMEDOUT";
|
|
34
|
+
const exitCode = timedOut ? 124 : (res.status ?? 1);
|
|
35
|
+
const tail = lastNChars(`${res.stdout ?? ""}${res.stderr ?? ""}`, TAIL_CHARS);
|
|
36
|
+
appendEvent(loop.paths.journalFile, loop.runtime.runId, iter, "acceptance.command", jsonField("command", command) +
|
|
37
|
+
", " +
|
|
38
|
+
jsonField("exit_code", String(exitCode)) +
|
|
39
|
+
", " +
|
|
40
|
+
jsonFieldRaw("timed_out", jsonBool(timedOut)) +
|
|
41
|
+
", " +
|
|
42
|
+
jsonField("output_tail", tail));
|
|
43
|
+
if (exitCode !== 0) {
|
|
44
|
+
failures.push({ command, exitCode, timedOut, tail });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const passed = failures.length === 0;
|
|
48
|
+
appendEvent(loop.paths.journalFile, loop.runtime.runId, iter, "acceptance.result", jsonFieldRaw("passed", jsonBool(passed)) +
|
|
49
|
+
", " +
|
|
50
|
+
jsonField("failed", String(failures.length)) +
|
|
51
|
+
", " +
|
|
52
|
+
jsonField("total", String(commands.length)));
|
|
53
|
+
return { ran: true, passed, failures };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Re-inject a failed acceptance gate's output as operator guidance so the next
|
|
57
|
+
* iteration's prompt carries the concrete failure instead of completing. This
|
|
58
|
+
* is the "do not complete; fix it" path of a deterministic gate.
|
|
59
|
+
*/
|
|
60
|
+
export function reinjectAcceptanceFailure(loop, iteration, result) {
|
|
61
|
+
const detail = result.failures
|
|
62
|
+
.map((f) => `- \`${f.command}\` exited ${f.exitCode}${f.timedOut ? " (timed out)" : ""}:\n${f.tail}`)
|
|
63
|
+
.join("\n\n");
|
|
64
|
+
const message = "Completion was blocked: the harness acceptance gate failed. " +
|
|
65
|
+
"Do not announce completion until every verify command passes. " +
|
|
66
|
+
`Failing command(s):\n\n${detail}`;
|
|
67
|
+
appendOperatorEvent(loop.paths.journalFile, loop.runtime.runId, String(iteration), "operator.guidance", message);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=acceptance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acceptance.js","sourceRoot":"","sources":["../src/acceptance.ts"],"names":[],"mappings":"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"}
|
package/dist/ask.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface AwaitResponseOptions {
|
|
2
|
+
/** Run state dir (loop.paths.stateDir) — control requests live under it. */
|
|
3
|
+
stateDir: string;
|
|
4
|
+
runId: string;
|
|
5
|
+
questionId: string;
|
|
6
|
+
timeoutMs: number;
|
|
7
|
+
pollMs?: number;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Block until a `respond` control request matching `questionId` appears, the
|
|
12
|
+
* timeout elapses, or the run is aborted. Returns the answer string, or `null`
|
|
13
|
+
* on timeout/abort. `questionId` is unique per ask, so any pre-existing respond
|
|
14
|
+
* requests for other questions are naturally ignored.
|
|
15
|
+
*/
|
|
16
|
+
export declare function awaitHumanResponse(opts: AwaitResponseOptions): Promise<string | null>;
|
package/dist/ask.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Blocking human-in-the-loop: pause the loop until an operator responds.
|
|
2
|
+
//
|
|
3
|
+
// autoloop is turn-based, so HITL maps cleanly to *between-iteration* blocking:
|
|
4
|
+
// an agent emits the reserved ask event, the harness journals `ask.pending` and
|
|
5
|
+
// blocks here until a matching `respond` control request arrives (the same
|
|
6
|
+
// channel `autoloop control respond` writes to) or the timeout elapses, then
|
|
7
|
+
// injects the answer into the next prompt as guidance. This lets an external
|
|
8
|
+
// supervisor (e.g. ralph relaying a Telegram reply) drive HITL over the
|
|
9
|
+
// subprocess engine without a mid-turn hook.
|
|
10
|
+
import { appendStatus, readRequests } from "./control/queue.js";
|
|
11
|
+
function sleep(ms) {
|
|
12
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Block until a `respond` control request matching `questionId` appears, the
|
|
16
|
+
* timeout elapses, or the run is aborted. Returns the answer string, or `null`
|
|
17
|
+
* on timeout/abort. `questionId` is unique per ask, so any pre-existing respond
|
|
18
|
+
* requests for other questions are naturally ignored.
|
|
19
|
+
*/
|
|
20
|
+
export async function awaitHumanResponse(opts) {
|
|
21
|
+
const pollMs = opts.pollMs && opts.pollMs > 0 ? opts.pollMs : 500;
|
|
22
|
+
const deadline = Date.now() + Math.max(0, opts.timeoutMs);
|
|
23
|
+
for (;;) {
|
|
24
|
+
if (opts.signal?.aborted)
|
|
25
|
+
return null;
|
|
26
|
+
const match = readRequests(opts.stateDir).find((r) => r.verb === "respond" &&
|
|
27
|
+
r.runId === opts.runId &&
|
|
28
|
+
r.payload.questionId === opts.questionId);
|
|
29
|
+
if (match) {
|
|
30
|
+
// Ack so the consumed response does not linger as a pending request.
|
|
31
|
+
appendStatus(opts.stateDir, {
|
|
32
|
+
id: match.id,
|
|
33
|
+
runId: match.runId,
|
|
34
|
+
verb: "respond",
|
|
35
|
+
state: "applied",
|
|
36
|
+
at: new Date().toISOString(),
|
|
37
|
+
detail: "delivered to human-ask",
|
|
38
|
+
});
|
|
39
|
+
return match.payload.answer;
|
|
40
|
+
}
|
|
41
|
+
const remaining = deadline - Date.now();
|
|
42
|
+
if (remaining <= 0)
|
|
43
|
+
return null;
|
|
44
|
+
await sleep(Math.min(pollMs, remaining));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=ask.js.map
|
package/dist/ask.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask.js","sourceRoot":"","sources":["../src/ask.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,2EAA2E;AAC3E,6EAA6E;AAC7E,6EAA6E;AAC7E,wEAAwE;AACxE,6CAA6C;AAE7C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGhE,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAYD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAA0B;IAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC;IAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAE1D,SAAS,CAAC;QACR,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,OAAO,IAAI,CAAC;QAEtC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC5C,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI,KAAK,SAAS;YACpB,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK;YACrB,CAAC,CAAC,OAA0B,CAAC,UAAU,KAAK,IAAI,CAAC,UAAU,CAC/D,CAAC;QACF,IAAI,KAAK,EAAE,CAAC;YACV,qEAAqE;YACrE,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE;gBAC1B,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,SAAS;gBAChB,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC5B,MAAM,EAAE,wBAAwB;aACjC,CAAC,CAAC;YACH,OAAQ,KAAK,CAAC,OAA0B,CAAC,MAAM,CAAC;QAClD,CAAC;QAED,MAAM,SAAS,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACxC,IAAI,SAAS,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAChC,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LoopContext } from "../types.js";
|
|
2
|
+
export interface ResolvedIterationBackend {
|
|
3
|
+
kind: string;
|
|
4
|
+
provider: string;
|
|
5
|
+
command: string;
|
|
6
|
+
args: string[];
|
|
7
|
+
promptMode: string;
|
|
8
|
+
timeoutMs: number;
|
|
9
|
+
trustAllTools: boolean;
|
|
10
|
+
agent: string;
|
|
11
|
+
model: string;
|
|
12
|
+
profile: string;
|
|
13
|
+
disallowedTools: string[];
|
|
14
|
+
usageFrom: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function resolvedFromLoopBackend(loop: LoopContext): ResolvedIterationBackend;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function resolvedFromLoopBackend(loop) {
|
|
2
|
+
return {
|
|
3
|
+
kind: loop.backend.kind,
|
|
4
|
+
provider: loop.backend.provider,
|
|
5
|
+
command: loop.backend.command,
|
|
6
|
+
args: [...loop.backend.args],
|
|
7
|
+
promptMode: loop.backend.promptMode,
|
|
8
|
+
timeoutMs: loop.backend.timeoutMs,
|
|
9
|
+
trustAllTools: loop.backend.trustAllTools,
|
|
10
|
+
agent: loop.backend.agent,
|
|
11
|
+
model: loop.backend.model,
|
|
12
|
+
profile: loop.backend.profile ?? "",
|
|
13
|
+
disallowedTools: [...(loop.backend.disallowedTools ?? [])],
|
|
14
|
+
usageFrom: loop.backend.usageFrom ?? "",
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/backend/types.ts"],"names":[],"mappings":"AAiBA,MAAM,UAAU,uBAAuB,CACrC,IAAiB;IAEjB,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;QACvB,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;QAC/B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;QAC7B,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QAC5B,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU;QACnC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;QACjC,aAAa,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa;QACzC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;QACzB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;QACzB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE;QACnC,eAAe,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;QAC1D,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE;KACxC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { BackendErrorClass } from "@mobrienv/autoloop-backends";
|
|
2
|
+
import type { StopReason } from "./types.js";
|
|
3
|
+
export interface CircuitDecision {
|
|
4
|
+
/** `pause`: back off and retry the run; `stop`: terminate with `reason`. */
|
|
5
|
+
action: "pause" | "stop";
|
|
6
|
+
/**
|
|
7
|
+
* Typed stop reason to journal (also used as the pause's error class).
|
|
8
|
+
* Narrowed to the subset of `StopReason` this classifier can produce.
|
|
9
|
+
*/
|
|
10
|
+
reason: Extract<StopReason, "auth_failed" | "quota_exhausted" | "rate_limited" | "transient_error" | "backend_failed">;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Circuit-breaker policy for a classified backend error. Non-retryable classes
|
|
14
|
+
* (auth/quota) stop immediately with a typed reason. Retryable classes
|
|
15
|
+
* (rate-limit/transient) pause-and-retry rather than fast-failing, until the
|
|
16
|
+
* breaker opens after `maxPauses` pauses — then they stop with the typed reason
|
|
17
|
+
* instead of being laundered into a confident verdict or a generic failure.
|
|
18
|
+
*/
|
|
19
|
+
export declare function circuitDecision(errorClass: BackendErrorClass, transientPauseCount: number, maxPauses: number): CircuitDecision;
|
|
20
|
+
/** How many transient pauses this run has already taken (breaker memory). */
|
|
21
|
+
export declare function countTransientPauses(runLines: string[]): number;
|
|
22
|
+
/**
|
|
23
|
+
* Exponential backoff for the retry ladder: `base * 2^(attempt-1)`, clamped to
|
|
24
|
+
* `cap` and never negative. `attempt` is 1-indexed (the first retry waits
|
|
25
|
+
* `base`). A `base` of 0 disables the wait entirely (used in tests).
|
|
26
|
+
*/
|
|
27
|
+
export declare function backoffDelayMs(attempt: number, baseMs: number, capMs: number): number;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { extractTopic } from "@mobrienv/autoloop-core/journal";
|
|
2
|
+
/**
|
|
3
|
+
* Circuit-breaker policy for a classified backend error. Non-retryable classes
|
|
4
|
+
* (auth/quota) stop immediately with a typed reason. Retryable classes
|
|
5
|
+
* (rate-limit/transient) pause-and-retry rather than fast-failing, until the
|
|
6
|
+
* breaker opens after `maxPauses` pauses — then they stop with the typed reason
|
|
7
|
+
* instead of being laundered into a confident verdict or a generic failure.
|
|
8
|
+
*/
|
|
9
|
+
export function circuitDecision(errorClass, transientPauseCount, maxPauses) {
|
|
10
|
+
switch (errorClass) {
|
|
11
|
+
case "auth_failed":
|
|
12
|
+
return { action: "stop", reason: "auth_failed" };
|
|
13
|
+
case "quota_exhausted":
|
|
14
|
+
return { action: "stop", reason: "quota_exhausted" };
|
|
15
|
+
case "rate_limited":
|
|
16
|
+
case "transient_error":
|
|
17
|
+
return transientPauseCount >= maxPauses
|
|
18
|
+
? { action: "stop", reason: errorClass }
|
|
19
|
+
: { action: "pause", reason: errorClass };
|
|
20
|
+
default:
|
|
21
|
+
// An unclassified failure is a plain backend failure.
|
|
22
|
+
return { action: "stop", reason: "backend_failed" };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** How many transient pauses this run has already taken (breaker memory). */
|
|
26
|
+
export function countTransientPauses(runLines) {
|
|
27
|
+
return runLines.filter((l) => extractTopic(l) === "backend.transient").length;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Exponential backoff for the retry ladder: `base * 2^(attempt-1)`, clamped to
|
|
31
|
+
* `cap` and never negative. `attempt` is 1-indexed (the first retry waits
|
|
32
|
+
* `base`). A `base` of 0 disables the wait entirely (used in tests).
|
|
33
|
+
*/
|
|
34
|
+
export function backoffDelayMs(attempt, baseMs, capMs) {
|
|
35
|
+
if (baseMs <= 0)
|
|
36
|
+
return 0;
|
|
37
|
+
const n = Math.max(1, Math.floor(attempt));
|
|
38
|
+
const delay = baseMs * 2 ** (n - 1);
|
|
39
|
+
return Math.min(Math.max(0, capMs), delay);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=circuit-breaker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../src/circuit-breaker.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAoB/D;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,UAA6B,EAC7B,mBAA2B,EAC3B,SAAiB;IAEjB,QAAQ,UAAU,EAAE,CAAC;QACnB,KAAK,aAAa;YAChB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;QACnD,KAAK,iBAAiB;YACpB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;QACvD,KAAK,cAAc,CAAC;QACpB,KAAK,iBAAiB;YACpB,OAAO,mBAAmB,IAAI,SAAS;gBACrC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE;gBACxC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAC9C;YACE,sDAAsD;YACtD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACxD,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,oBAAoB,CAAC,QAAkB;IACrD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,mBAAmB,CAAC,CAAC,MAAM,CAAC;AAChF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAe,EACf,MAAc,EACd,KAAa;IAEb,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface CompletionContractInput {
|
|
2
|
+
/** Completion promise string (stdout fallback). */
|
|
3
|
+
promise: string;
|
|
4
|
+
/** Completion event topic. */
|
|
5
|
+
event: string;
|
|
6
|
+
/** Required-evidence events that must precede completion. */
|
|
7
|
+
requiredEvents: string[];
|
|
8
|
+
/** Out-of-band acceptance verify commands. */
|
|
9
|
+
verifyCmds: string[];
|
|
10
|
+
/** Intent-binding acceptance criteria (may bind `text :: cmd` checks). */
|
|
11
|
+
criteria: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface ContractLintFinding {
|
|
14
|
+
level: "warn" | "info";
|
|
15
|
+
rule: string;
|
|
16
|
+
message: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Does the contract have ANY deterministic, harness-checkable completion
|
|
20
|
+
* condition (verify command, required event, or a criterion-bound check)? If
|
|
21
|
+
* not, completion is self-asserted with nothing to falsify it.
|
|
22
|
+
*/
|
|
23
|
+
export declare function hasDeterministicCheck(c: CompletionContractInput): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Lint a completion contract for falsifiability and triviality BEFORE a run
|
|
26
|
+
* burns iterations on a bad stop condition. Returns [] for a well-formed
|
|
27
|
+
* contract; warnings for trivial/un-falsifiable ones.
|
|
28
|
+
*/
|
|
29
|
+
export declare function lintCompletionContract(c: CompletionContractInput): ContractLintFinding[];
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { parseCriterion } from "./intent.js";
|
|
2
|
+
// Trivial promise strings an agent can satisfy incidentally.
|
|
3
|
+
const TRIVIAL_PROMISE = /^(done|ok|okay|complete|completed|finished|yes|true|success)$/i;
|
|
4
|
+
/**
|
|
5
|
+
* Does the contract have ANY deterministic, harness-checkable completion
|
|
6
|
+
* condition (verify command, required event, or a criterion-bound check)? If
|
|
7
|
+
* not, completion is self-asserted with nothing to falsify it.
|
|
8
|
+
*/
|
|
9
|
+
export function hasDeterministicCheck(c) {
|
|
10
|
+
if (c.verifyCmds.length > 0)
|
|
11
|
+
return true;
|
|
12
|
+
if (c.requiredEvents.length > 0)
|
|
13
|
+
return true;
|
|
14
|
+
return c.criteria.some((line) => parseCriterion(line).check !== undefined);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Lint a completion contract for falsifiability and triviality BEFORE a run
|
|
18
|
+
* burns iterations on a bad stop condition. Returns [] for a well-formed
|
|
19
|
+
* contract; warnings for trivial/un-falsifiable ones.
|
|
20
|
+
*/
|
|
21
|
+
export function lintCompletionContract(c) {
|
|
22
|
+
const findings = [];
|
|
23
|
+
const deterministic = hasDeterministicCheck(c);
|
|
24
|
+
if (!deterministic) {
|
|
25
|
+
findings.push({
|
|
26
|
+
level: "warn",
|
|
27
|
+
rule: "unfalsifiable_completion",
|
|
28
|
+
message: "Completion has no deterministic check — the agent can satisfy it without proof. Add acceptance.verify_cmds, event_loop.required_events, or a criterion-bound check (`text :: cmd`).",
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
// A trivial promise is only a real hazard when nothing else gates completion
|
|
32
|
+
// (otherwise the deterministic check backs it up).
|
|
33
|
+
if (c.promise && !deterministic && TRIVIAL_PROMISE.test(c.promise.trim())) {
|
|
34
|
+
findings.push({
|
|
35
|
+
level: "warn",
|
|
36
|
+
rule: "trivial_promise",
|
|
37
|
+
message: `Completion promise "${c.promise}" is trivially printable; the agent can emit it without doing the work. Use a distinctive promise plus a deterministic check.`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// Criteria present but all advisory — they won't gate completion.
|
|
41
|
+
if (c.criteria.length > 0 &&
|
|
42
|
+
!c.criteria.some((line) => parseCriterion(line).check !== undefined)) {
|
|
43
|
+
findings.push({
|
|
44
|
+
level: "info",
|
|
45
|
+
rule: "advisory_criteria_only",
|
|
46
|
+
message: "Acceptance criteria are advisory only (no `::` checks); they are recorded but do not gate completion. Bind a check to enforce them.",
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return findings;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=completion-lint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion-lint.js","sourceRoot":"","sources":["../src/completion-lint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAqB7C,6DAA6D;AAC7D,MAAM,eAAe,GACnB,gEAAgE,CAAC;AAEnE;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,CAA0B;IAC9D,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,CAAC,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;AAC7E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,CAA0B;IAE1B,MAAM,QAAQ,GAA0B,EAAE,CAAC;IAC3C,MAAM,aAAa,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAE/C,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC;YACZ,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,0BAA0B;YAChC,OAAO,EACL,qLAAqL;SACxL,CAAC,CAAC;IACL,CAAC;IAED,6EAA6E;IAC7E,mDAAmD;IACnD,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,aAAa,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC1E,QAAQ,CAAC,IAAI,CAAC;YACZ,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,uBAAuB,CAAC,CAAC,OAAO,+HAA+H;SACzK,CAAC,CAAC;IACL,CAAC;IAED,kEAAkE;IAClE,IACE,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QACrB,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,EACpE,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC;YACZ,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EACL,qIAAqI;SACxI,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/dist/config-helpers.d.ts
CHANGED
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
import * as config from "@mobrienv/autoloop-core/config";
|
|
2
2
|
import * as topo from "@mobrienv/autoloop-core/topology";
|
|
3
3
|
import type { LoopContext, RunOptions } from "./types.js";
|
|
4
|
-
export
|
|
4
|
+
export interface ResolvePromptOptions {
|
|
5
|
+
workDir?: string;
|
|
6
|
+
stateDir?: string;
|
|
7
|
+
baseStateDir?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function resolvePrompt(projectDir: string, cfg: config.Config, override: string | null, options?: ResolvePromptOptions): string;
|
|
5
10
|
export declare function resolveReviewPrompt(projectDir: string, cfg: config.Config): string;
|
|
6
11
|
export declare function readOptionalProjectFile(projectDir: string, relativePath: string): string;
|
|
7
12
|
export declare function resolveReviewEvery(cfg: config.Config, topoData: topo.Topology): number;
|
|
8
13
|
export declare function truthySetting(value: string): boolean;
|
|
9
14
|
export declare function ensureLayout(stateDir: string): void;
|
|
10
15
|
export declare function installRuntimeTools(loop: LoopContext): void;
|
|
11
|
-
export declare function resolveProcessKind(kind: string, command: string
|
|
16
|
+
export declare function resolveProcessKind(kind: string, command: string, opts?: {
|
|
17
|
+
hasCustomArgs?: boolean;
|
|
18
|
+
}): string;
|
|
12
19
|
export declare function normalizePromptMode(value: string): string;
|
|
13
20
|
export declare function configListWithFallback(cfg: config.Config, key: string, fallback: string[]): string[];
|
|
14
21
|
export declare function injectClaudePermissions(command: string, args: string[]): string[];
|
|
15
22
|
export declare function processStringOverride(override: Record<string, unknown>, key: string, fallback: string): string;
|
|
16
23
|
export declare function processListOverride(override: Record<string, unknown>, key: string, fallback: string[]): string[];
|
|
17
24
|
export declare function processIntOverride(override: Record<string, unknown>, key: string, fallback: number): number;
|
|
25
|
+
export declare function processBoolOverride(override: Record<string, unknown>, key: string, fallback: boolean): boolean;
|
|
18
26
|
export declare function claudeBackend(command: string): boolean;
|
|
19
27
|
export declare function nextRunId(path: string, cfg: config.Config): string;
|
|
20
28
|
export declare function iterationFieldForRun(journalFile: string, runId: string, iteration: string, topic: string, field: string): string;
|