@bluewombat/runtime 0.11.0 → 0.11.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/README.md +84 -7
- package/SPECS.md +55 -9
- package/dist/cli.js +63 -0
- package/dist/cli.js.map +1 -1
- package/dist/config/load-config.d.ts.map +1 -1
- package/dist/config/load-config.js +2 -1
- package/dist/config/load-config.js.map +1 -1
- package/dist/config/types.d.ts +7 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/loop/authority.d.ts +2 -0
- package/dist/loop/authority.d.ts.map +1 -1
- package/dist/loop/authority.js +11 -1
- package/dist/loop/authority.js.map +1 -1
- package/dist/loop/deliveries.d.ts.map +1 -1
- package/dist/loop/deliveries.js +19 -0
- package/dist/loop/deliveries.js.map +1 -1
- package/dist/loop/features.d.ts +14 -0
- package/dist/loop/features.d.ts.map +1 -1
- package/dist/loop/features.js +78 -35
- package/dist/loop/features.js.map +1 -1
- package/dist/loop/journal.d.ts +7 -0
- package/dist/loop/journal.d.ts.map +1 -1
- package/dist/loop/journal.js +23 -1
- package/dist/loop/journal.js.map +1 -1
- package/dist/loop/lock.d.ts +2 -0
- package/dist/loop/lock.d.ts.map +1 -1
- package/dist/loop/lock.js +10 -0
- package/dist/loop/lock.js.map +1 -1
- package/dist/loop/run-slot.d.ts +14 -0
- package/dist/loop/run-slot.d.ts.map +1 -1
- package/dist/loop/run-slot.js +53 -5
- package/dist/loop/run-slot.js.map +1 -1
- package/dist/loop/streams.js +2 -2
- package/dist/loop/streams.js.map +1 -1
- package/dist/loop/tick.d.ts.map +1 -1
- package/dist/loop/tick.js +2 -1
- package/dist/loop/tick.js.map +1 -1
- package/dist/loop/transformers.d.ts.map +1 -1
- package/dist/loop/transformers.js +5 -3
- package/dist/loop/transformers.js.map +1 -1
- package/dist/operator/dash-model.d.ts +65 -0
- package/dist/operator/dash-model.d.ts.map +1 -0
- package/dist/operator/dash-model.js +209 -0
- package/dist/operator/dash-model.js.map +1 -0
- package/dist/operator/dash-view.d.ts +16 -0
- package/dist/operator/dash-view.d.ts.map +1 -0
- package/dist/operator/dash-view.js +226 -0
- package/dist/operator/dash-view.js.map +1 -0
- package/dist/operator/dash.d.ts +34 -0
- package/dist/operator/dash.d.ts.map +1 -0
- package/dist/operator/dash.js +141 -0
- package/dist/operator/dash.js.map +1 -0
- package/dist/operator/doctor.d.ts.map +1 -1
- package/dist/operator/doctor.js +44 -1
- package/dist/operator/doctor.js.map +1 -1
- package/dist/operator/incident-dossier.d.ts +4 -4
- package/dist/operator/incident-dossier.d.ts.map +1 -1
- package/dist/operator/incident-dossier.js +14 -18
- package/dist/operator/incident-dossier.js.map +1 -1
- package/dist/operator/incident-system.d.ts +13 -4
- package/dist/operator/incident-system.d.ts.map +1 -1
- package/dist/operator/incident-system.js +68 -6
- package/dist/operator/incident-system.js.map +1 -1
- package/dist/operator/install.d.ts +9 -0
- package/dist/operator/install.d.ts.map +1 -0
- package/dist/operator/install.js +14 -0
- package/dist/operator/install.js.map +1 -0
- package/dist/operator/supervise/act.d.ts +37 -0
- package/dist/operator/supervise/act.d.ts.map +1 -0
- package/dist/operator/supervise/act.js +354 -0
- package/dist/operator/supervise/act.js.map +1 -0
- package/dist/operator/supervise/config.d.ts +74 -0
- package/dist/operator/supervise/config.d.ts.map +1 -0
- package/dist/operator/supervise/config.js +175 -0
- package/dist/operator/supervise/config.js.map +1 -0
- package/dist/operator/supervise/council.d.ts +45 -0
- package/dist/operator/supervise/council.d.ts.map +1 -0
- package/dist/operator/supervise/council.js +97 -0
- package/dist/operator/supervise/council.js.map +1 -0
- package/dist/operator/supervise/decision.d.ts +46 -0
- package/dist/operator/supervise/decision.d.ts.map +1 -0
- package/dist/operator/supervise/decision.js +137 -0
- package/dist/operator/supervise/decision.js.map +1 -0
- package/dist/operator/supervise/exec.d.ts +28 -0
- package/dist/operator/supervise/exec.d.ts.map +1 -0
- package/dist/operator/supervise/exec.js +47 -0
- package/dist/operator/supervise/exec.js.map +1 -0
- package/dist/operator/supervise/memory.d.ts +33 -0
- package/dist/operator/supervise/memory.d.ts.map +1 -0
- package/dist/operator/supervise/memory.js +73 -0
- package/dist/operator/supervise/memory.js.map +1 -0
- package/dist/operator/supervise/observe.d.ts +47 -0
- package/dist/operator/supervise/observe.d.ts.map +1 -0
- package/dist/operator/supervise/observe.js +73 -0
- package/dist/operator/supervise/observe.js.map +1 -0
- package/dist/operator/supervise/prompts.d.ts +60 -0
- package/dist/operator/supervise/prompts.d.ts.map +1 -0
- package/dist/operator/supervise/prompts.js +338 -0
- package/dist/operator/supervise/prompts.js.map +1 -0
- package/dist/operator/supervise/review.d.ts +24 -0
- package/dist/operator/supervise/review.d.ts.map +1 -0
- package/dist/operator/supervise/review.js +51 -0
- package/dist/operator/supervise/review.js.map +1 -0
- package/dist/operator/supervise/supervise.d.ts +26 -0
- package/dist/operator/supervise/supervise.d.ts.map +1 -0
- package/dist/operator/supervise/supervise.js +484 -0
- package/dist/operator/supervise/supervise.js.map +1 -0
- package/package.json +14 -14
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export declare const SUPERVISOR_FILENAME = "mason.supervisor.yaml";
|
|
2
|
+
/** A command with a ceiling. `{name}` in a word is filled by the supervisor. */
|
|
3
|
+
export type CommandSpec = {
|
|
4
|
+
cmd: string[];
|
|
5
|
+
timeoutMs: number;
|
|
6
|
+
};
|
|
7
|
+
/** A repository the supervisor may change, and how a change reaches its line. */
|
|
8
|
+
export type FixTarget = {
|
|
9
|
+
name: string;
|
|
10
|
+
/** A checkout of the repository. The supervisor never edits it: it works in its own worktrees. */
|
|
11
|
+
repo: string;
|
|
12
|
+
base: string;
|
|
13
|
+
remote: string;
|
|
14
|
+
/** Run in the worktree after the agent. A change that does not pass is not offered. */
|
|
15
|
+
checks: CommandSpec[];
|
|
16
|
+
/** Offer the branch. Receives `{branch}` `{title}` `{bodyFile}`. Prints the pull request's reference. */
|
|
17
|
+
open: CommandSpec;
|
|
18
|
+
/**
|
|
19
|
+
* Fold the offer without a person. Off unless the Project turns it on: by default the offer waits
|
|
20
|
+
* for a person to read and merge it, and nothing that depends on it moves until then.
|
|
21
|
+
*/
|
|
22
|
+
autoMerge: boolean;
|
|
23
|
+
/** Fold the offer. Receives `{pr}`. Used only when `autoMerge` is on. */
|
|
24
|
+
merge: CommandSpec;
|
|
25
|
+
/** Whether the offer is folded yet. Receives `{pr}`. Exit 0 means folded. */
|
|
26
|
+
merged: CommandSpec;
|
|
27
|
+
/** After the fold: release, upgrade, restart. Receives `{branch}` `{title}`. */
|
|
28
|
+
after: CommandSpec[];
|
|
29
|
+
/** Paths the agent's change may not touch (prefixes). */
|
|
30
|
+
deny: string[];
|
|
31
|
+
/**
|
|
32
|
+
* Where the repository writes down what it must be: the rules every member reads before it reasons
|
|
33
|
+
* about a change, relative to `repo`. The first one is expected to route to the others.
|
|
34
|
+
*/
|
|
35
|
+
rules: string[];
|
|
36
|
+
};
|
|
37
|
+
export type SupervisorConfig = {
|
|
38
|
+
configDir: string;
|
|
39
|
+
/** Where the supervisor keeps its own files, under Host's home. */
|
|
40
|
+
dir: string;
|
|
41
|
+
pollIntervalMs: number;
|
|
42
|
+
/** Journal silent this long with work active is a stall. */
|
|
43
|
+
stallAfterMs: number;
|
|
44
|
+
/** An escalation younger than this is left to a person who may already be on it. 0: act at once. */
|
|
45
|
+
settleMs: number;
|
|
46
|
+
/** After acting, the same finding seen again is left this long to take effect. */
|
|
47
|
+
cooldownMs: number;
|
|
48
|
+
diskMinBytes: number;
|
|
49
|
+
/** Attempts per finding before it is handed to a person. */
|
|
50
|
+
maxAttempts: number;
|
|
51
|
+
/** An agent per role. `{promptFile}` and `{prompt}` are filled. */
|
|
52
|
+
agents: Record<string, CommandSpec>;
|
|
53
|
+
worker: {
|
|
54
|
+
start?: CommandSpec;
|
|
55
|
+
};
|
|
56
|
+
/** Takes a resume signal to the tracker. Receives `{key}` `{number}`. */
|
|
57
|
+
resume?: CommandSpec;
|
|
58
|
+
diskCleanup: CommandSpec[];
|
|
59
|
+
/** Tell a person. Receives `{subject}` `{file}`. Optional: the page is written either way. */
|
|
60
|
+
notify?: CommandSpec;
|
|
61
|
+
targets: FixTarget[];
|
|
62
|
+
};
|
|
63
|
+
export declare const ROLES: readonly ["rootcause", "remedy", "skeptic", "arbiter", "reformatter", "fixer", "reviewer"];
|
|
64
|
+
export type Role = (typeof ROLES)[number];
|
|
65
|
+
export type LoadedConfig = {
|
|
66
|
+
ok: true;
|
|
67
|
+
config: SupervisorConfig;
|
|
68
|
+
} | {
|
|
69
|
+
ok: false;
|
|
70
|
+
reason: string;
|
|
71
|
+
};
|
|
72
|
+
export declare function findSupervisorConfig(from: string): string | undefined;
|
|
73
|
+
export declare function loadSupervisorConfig(path: string, home: string): LoadedConfig;
|
|
74
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/operator/supervise/config.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,0BAA+B,CAAC;AAEhE,gFAAgF;AAChF,MAAM,MAAM,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D,iFAAiF;AACjF,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,kGAAkG;IAClG,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,yGAAyG;IACzG,IAAI,EAAE,WAAW,CAAC;IAClB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,KAAK,EAAE,WAAW,CAAC;IACnB,6EAA6E;IAC7E,MAAM,EAAE,WAAW,CAAC;IACpB,gFAAgF;IAChF,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,yDAAyD;IACzD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;OAGG;IACH,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,oGAAoG;IACpG,QAAQ,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;IAChC,yEAAyE;IACzE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B,8FAA8F;IAC9F,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,KAAK,4FAQR,CAAC;AACX,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1C,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAgBlG,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAarE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAiB7E"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { PRODUCT } from "@bluewombat/manager-kit";
|
|
4
|
+
import { parse as parseYaml } from "yaml";
|
|
5
|
+
export const SUPERVISOR_FILENAME = `${PRODUCT}.supervisor.yaml`;
|
|
6
|
+
export const ROLES = [
|
|
7
|
+
"rootcause",
|
|
8
|
+
"remedy",
|
|
9
|
+
"skeptic",
|
|
10
|
+
"arbiter",
|
|
11
|
+
"reformatter",
|
|
12
|
+
"fixer",
|
|
13
|
+
"reviewer",
|
|
14
|
+
];
|
|
15
|
+
const DEFAULT_AGENT_MS = 20 * 60_000;
|
|
16
|
+
/**
|
|
17
|
+
* Claude Code, headless. The analysts read and do not write; the fixer works in
|
|
18
|
+
* a worktree of its own and may. The prompt comes before `--add-dir`, which takes
|
|
19
|
+
* every value after it and would swallow the prompt as a directory.
|
|
20
|
+
*/
|
|
21
|
+
function claude(mode, model) {
|
|
22
|
+
return {
|
|
23
|
+
cmd: ["claude", "-p", "{prompt}", "--model", model, "--permission-mode", mode, "{addDirArgs}"],
|
|
24
|
+
timeoutMs: DEFAULT_AGENT_MS,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function findSupervisorConfig(from) {
|
|
28
|
+
let dir = resolve(from);
|
|
29
|
+
for (;;) {
|
|
30
|
+
const candidate = join(dir, SUPERVISOR_FILENAME);
|
|
31
|
+
if (existsSync(candidate)) {
|
|
32
|
+
return candidate;
|
|
33
|
+
}
|
|
34
|
+
const parent = dirname(dir);
|
|
35
|
+
if (parent === dir) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
dir = parent;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function loadSupervisorConfig(path, home) {
|
|
42
|
+
let raw;
|
|
43
|
+
try {
|
|
44
|
+
raw = parseYaml(readFileSync(path, "utf8"));
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return { ok: false, reason: `${path}: ${error instanceof Error ? error.message : error}` };
|
|
48
|
+
}
|
|
49
|
+
const object = (raw ?? {});
|
|
50
|
+
if (typeof object !== "object" || Array.isArray(object)) {
|
|
51
|
+
return { ok: false, reason: `${path} must be a YAML mapping.` };
|
|
52
|
+
}
|
|
53
|
+
const configDir = dirname(path);
|
|
54
|
+
try {
|
|
55
|
+
return { ok: true, config: build(object, configDir, home) };
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
return { ok: false, reason: `${path}: ${error instanceof Error ? error.message : error}` };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function build(o, configDir, home) {
|
|
62
|
+
const agents = {
|
|
63
|
+
rootcause: claude("plan", "opus"),
|
|
64
|
+
remedy: claude("plan", "opus"),
|
|
65
|
+
skeptic: claude("plan", "opus"),
|
|
66
|
+
arbiter: claude("plan", "opus"),
|
|
67
|
+
reformatter: claude("plan", "haiku"),
|
|
68
|
+
fixer: claude("bypassPermissions", "opus"),
|
|
69
|
+
reviewer: claude("plan", "opus"),
|
|
70
|
+
};
|
|
71
|
+
for (const [role, value] of Object.entries(map(o.agents, "agents"))) {
|
|
72
|
+
if (!ROLES.includes(role)) {
|
|
73
|
+
throw new Error(`agents.${role}: no such role (${ROLES.join(", ")}).`);
|
|
74
|
+
}
|
|
75
|
+
agents[role] = command(value, `agents.${role}`, DEFAULT_AGENT_MS);
|
|
76
|
+
}
|
|
77
|
+
const worker = map(o.worker, "worker");
|
|
78
|
+
const targets = Object.entries(map(o.targets, "targets")).map(([name, value]) => target(name, map(value, `targets.${name}`), configDir));
|
|
79
|
+
return {
|
|
80
|
+
configDir,
|
|
81
|
+
dir: resolve(configDir, text(o.dir) ?? join(home, "supervisor")),
|
|
82
|
+
pollIntervalMs: num(o.pollIntervalMs, "pollIntervalMs", 15_000),
|
|
83
|
+
stallAfterMs: num(o.stallAfterMs, "stallAfterMs", 20 * 60_000),
|
|
84
|
+
settleMs: num(o.settleMs, "settleMs", 0),
|
|
85
|
+
cooldownMs: num(o.cooldownMs, "cooldownMs", 5 * 60_000),
|
|
86
|
+
diskMinBytes: num(o.diskMinBytes, "diskMinBytes", 3 * 1024 ** 3),
|
|
87
|
+
maxAttempts: num(o.maxAttempts, "maxAttempts", 3),
|
|
88
|
+
agents,
|
|
89
|
+
worker: worker.start === undefined ? {} : { start: command(worker.start, "worker.start", 30_000) },
|
|
90
|
+
...(o.resume === undefined ? {} : { resume: command(o.resume, "resume", 60_000) }),
|
|
91
|
+
diskCleanup: list(o.diskCleanup, "diskCleanup").map((c, i) => command(c, `diskCleanup[${i}]`, 10 * 60_000)),
|
|
92
|
+
...(o.notify === undefined ? {} : { notify: command(o.notify, "notify", 60_000) }),
|
|
93
|
+
targets,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function target(name, o, configDir) {
|
|
97
|
+
const where = `targets.${name}`;
|
|
98
|
+
const repo = text(o.repo);
|
|
99
|
+
if (repo === undefined) {
|
|
100
|
+
throw new Error(`${where}.repo is required.`);
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
name,
|
|
104
|
+
repo: resolve(configDir, repo),
|
|
105
|
+
base: text(o.base) ?? "main",
|
|
106
|
+
remote: text(o.remote) ?? "origin",
|
|
107
|
+
checks: list(o.checks, `${where}.checks`).map((c, i) => command(c, `${where}.checks[${i}]`, 30 * 60_000)),
|
|
108
|
+
open: command(o.open ?? {
|
|
109
|
+
cmd: [
|
|
110
|
+
"gh",
|
|
111
|
+
"pr",
|
|
112
|
+
"create",
|
|
113
|
+
"--head",
|
|
114
|
+
"{branch}",
|
|
115
|
+
"--title",
|
|
116
|
+
"{title}",
|
|
117
|
+
"--body-file",
|
|
118
|
+
"{bodyFile}",
|
|
119
|
+
],
|
|
120
|
+
}, `${where}.open`, 120_000),
|
|
121
|
+
autoMerge: o.autoMerge === true,
|
|
122
|
+
merge: command(o.merge ?? { cmd: ["gh", "pr", "merge", "{pr}", "--squash", "--auto"] }, `${where}.merge`, 120_000),
|
|
123
|
+
merged: command(o.merged ?? {
|
|
124
|
+
cmd: [
|
|
125
|
+
"sh",
|
|
126
|
+
"-c",
|
|
127
|
+
'test "$(gh pr view "$1" --json state -q .state)" = MERGED',
|
|
128
|
+
"sh",
|
|
129
|
+
"{pr}",
|
|
130
|
+
],
|
|
131
|
+
}, `${where}.merged`, 60_000),
|
|
132
|
+
after: list(o.after, `${where}.after`).map((c, i) => command(c, `${where}.after[${i}]`, 30 * 60_000)),
|
|
133
|
+
deny: list(o.deny, `${where}.deny`).map((d) => String(d)),
|
|
134
|
+
rules: o.rules === undefined ? ["AGENTS.md"] : list(o.rules, `${where}.rules`).map(String),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function command(value, where, fallbackMs) {
|
|
138
|
+
const o = Array.isArray(value) ? { cmd: value } : map(value, where);
|
|
139
|
+
const cmd = o.cmd;
|
|
140
|
+
if (!Array.isArray(cmd) || cmd.length === 0 || cmd.some((w) => typeof w !== "string")) {
|
|
141
|
+
throw new Error(`${where}.cmd must be a non-empty list of strings.`);
|
|
142
|
+
}
|
|
143
|
+
return { cmd: cmd, timeoutMs: num(o.timeoutMs, `${where}.timeoutMs`, fallbackMs) };
|
|
144
|
+
}
|
|
145
|
+
function map(value, where) {
|
|
146
|
+
if (value === undefined || value === null) {
|
|
147
|
+
return {};
|
|
148
|
+
}
|
|
149
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
150
|
+
throw new Error(`${where} must be a mapping.`);
|
|
151
|
+
}
|
|
152
|
+
return value;
|
|
153
|
+
}
|
|
154
|
+
function list(value, where) {
|
|
155
|
+
if (value === undefined || value === null) {
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
if (!Array.isArray(value)) {
|
|
159
|
+
throw new Error(`${where} must be a list.`);
|
|
160
|
+
}
|
|
161
|
+
return value;
|
|
162
|
+
}
|
|
163
|
+
function text(value) {
|
|
164
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
165
|
+
}
|
|
166
|
+
function num(value, where, fallback) {
|
|
167
|
+
if (value === undefined) {
|
|
168
|
+
return fallback;
|
|
169
|
+
}
|
|
170
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
171
|
+
throw new Error(`${where} must be a number of zero or more.`);
|
|
172
|
+
}
|
|
173
|
+
return value;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/operator/supervise/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { SupervisorConfig } from "./config.js";
|
|
2
|
+
import { type Decision } from "./decision.js";
|
|
3
|
+
import { type Exec } from "./exec.js";
|
|
4
|
+
import { type Brief } from "./prompts.js";
|
|
5
|
+
export type Deliberation = {
|
|
6
|
+
ok: true;
|
|
7
|
+
decision: Decision;
|
|
8
|
+
reports: Record<string, string>;
|
|
9
|
+
} | {
|
|
10
|
+
ok: false;
|
|
11
|
+
reason: string;
|
|
12
|
+
reports: Record<string, string>;
|
|
13
|
+
};
|
|
14
|
+
export type AgentRunInput = {
|
|
15
|
+
config: SupervisorConfig;
|
|
16
|
+
exec: Exec;
|
|
17
|
+
role: string;
|
|
18
|
+
prompt: string;
|
|
19
|
+
/** Where the prompt and the answer are filed. */
|
|
20
|
+
dir: string;
|
|
21
|
+
cwd: string;
|
|
22
|
+
addDirs: string[];
|
|
23
|
+
};
|
|
24
|
+
/** One agent, once: its prompt written down, its answer kept. */
|
|
25
|
+
export declare function runAgent(input: AgentRunInput): Promise<{
|
|
26
|
+
ok: boolean;
|
|
27
|
+
text: string;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* Three members read the same stop from different seats; an arbiter decides.
|
|
31
|
+
*
|
|
32
|
+
* The members run together and apart: none sees another's answer, so they
|
|
33
|
+
* cannot settle on the first idea. The arbiter sees all three and the code.
|
|
34
|
+
* A member that fails does not stop the others; fewer than two answers is no
|
|
35
|
+
* council. An arbiter whose answer is refused for its shape has it corrected by a small
|
|
36
|
+
* agent from its own text; one that fails is asked again as before.
|
|
37
|
+
*/
|
|
38
|
+
export declare function deliberate(input: {
|
|
39
|
+
config: SupervisorConfig;
|
|
40
|
+
exec: Exec;
|
|
41
|
+
brief: Brief;
|
|
42
|
+
dir: string;
|
|
43
|
+
cwd: string;
|
|
44
|
+
}): Promise<Deliberation>;
|
|
45
|
+
//# sourceMappingURL=council.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"council.d.ts","sourceRoot":"","sources":["../../../src/operator/supervise/council.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,KAAK,QAAQ,EAA2B,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,KAAK,IAAI,EAA0C,MAAM,WAAW,CAAC;AAC9E,OAAO,EAEL,KAAK,KAAK,EAKX,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACjE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC;AAWnE,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,iEAAiE;AACjE,wBAAsB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAoB3F;AAWD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE;IACtC,MAAM,EAAE,gBAAgB,CAAC;IACzB,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,OAAO,CAAC,YAAY,CAAC,CAqDxB"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { lastJson, parseDecision } from "./decision.js";
|
|
4
|
+
import { fill, succeeded, tail } from "./exec.js";
|
|
5
|
+
import { arbiterPrompt, formPrompt, remedyPrompt, rootcausePrompt, skepticPrompt, } from "./prompts.js";
|
|
6
|
+
const ANALYSTS = [
|
|
7
|
+
["rootcause", rootcausePrompt],
|
|
8
|
+
["remedy", remedyPrompt],
|
|
9
|
+
["skeptic", skepticPrompt],
|
|
10
|
+
];
|
|
11
|
+
/** Cap what one member's report adds to the arbiter's page. */
|
|
12
|
+
const REPORT_CHARS = 30_000;
|
|
13
|
+
/** One agent, once: its prompt written down, its answer kept. */
|
|
14
|
+
export async function runAgent(input) {
|
|
15
|
+
mkdirSync(input.dir, { recursive: true });
|
|
16
|
+
const promptFile = join(input.dir, `${input.role}.prompt.md`);
|
|
17
|
+
writeFileSync(promptFile, input.prompt);
|
|
18
|
+
const spec = input.config.agents[input.role];
|
|
19
|
+
if (spec === undefined) {
|
|
20
|
+
return { ok: false, text: `no agent configured for ${input.role}` };
|
|
21
|
+
}
|
|
22
|
+
const result = await input.exec(fill(spec.cmd, { prompt: input.prompt, promptFile }, { addDirArgs: input.addDirs.flatMap((dir) => ["--add-dir", dir]) }), { cwd: input.cwd, timeoutMs: spec.timeoutMs });
|
|
23
|
+
const ok = succeeded(result) || answeredBeforeCeiling(result);
|
|
24
|
+
const text = ok ? result.stdout : tail(result);
|
|
25
|
+
writeFileSync(join(input.dir, `${input.role}.out.md`), text);
|
|
26
|
+
return { ok, text };
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Every role ends its answer with a JSON block. An agent cut at its ceiling
|
|
30
|
+
* after writing one finished its work: the answer is kept, not counted as lost.
|
|
31
|
+
*/
|
|
32
|
+
function answeredBeforeCeiling(result) {
|
|
33
|
+
const value = result.atCeiling === true ? lastJson(result.stdout) : undefined;
|
|
34
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Three members read the same stop from different seats; an arbiter decides.
|
|
38
|
+
*
|
|
39
|
+
* The members run together and apart: none sees another's answer, so they
|
|
40
|
+
* cannot settle on the first idea. The arbiter sees all three and the code.
|
|
41
|
+
* A member that fails does not stop the others; fewer than two answers is no
|
|
42
|
+
* council. An arbiter whose answer is refused for its shape has it corrected by a small
|
|
43
|
+
* agent from its own text; one that fails is asked again as before.
|
|
44
|
+
*/
|
|
45
|
+
export async function deliberate(input) {
|
|
46
|
+
const addDirs = [...new Set([...input.brief.codeRoots, input.brief.ledgerRoot])];
|
|
47
|
+
const base = { config: input.config, exec: input.exec, dir: input.dir, cwd: input.cwd, addDirs };
|
|
48
|
+
const answers = await Promise.all(ANALYSTS.map(async ([role, prompt]) => ({
|
|
49
|
+
role,
|
|
50
|
+
...(await runAgent({ ...base, role, prompt: prompt(input.brief) })),
|
|
51
|
+
})));
|
|
52
|
+
const reports = {};
|
|
53
|
+
for (const answer of answers) {
|
|
54
|
+
if (answer.ok) {
|
|
55
|
+
reports[answer.role] = answer.text.slice(-REPORT_CHARS);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (Object.keys(reports).length < 2) {
|
|
59
|
+
return {
|
|
60
|
+
ok: false,
|
|
61
|
+
reason: `only ${Object.keys(reports).length} of ${ANALYSTS.length} members answered: ${answers
|
|
62
|
+
.filter((a) => !a.ok)
|
|
63
|
+
.map((a) => `${a.role}: ${a.text.slice(0, 200)}`)
|
|
64
|
+
.join(" | ")}`,
|
|
65
|
+
reports,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const targets = input.config.targets.map((target) => target.name);
|
|
69
|
+
const prompt = arbiterPrompt(input.brief, reports);
|
|
70
|
+
let reason = "";
|
|
71
|
+
for (let round = 0; round < 2; round++) {
|
|
72
|
+
const arbiter = await runAgent({ ...base, role: "arbiter", prompt });
|
|
73
|
+
if (!arbiter.ok) {
|
|
74
|
+
reason = `the arbiter failed: ${arbiter.text.slice(0, 300)}`;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const parsed = parseDecision(arbiter.text, targets);
|
|
78
|
+
if (parsed.ok) {
|
|
79
|
+
return { ok: true, decision: parsed.decision, reports };
|
|
80
|
+
}
|
|
81
|
+
reason = `the arbiter's answer was refused: ${parsed.reason}`;
|
|
82
|
+
const corrected = await runAgent({
|
|
83
|
+
...base,
|
|
84
|
+
role: "reformatter",
|
|
85
|
+
prompt: formPrompt(arbiter.text, parsed.reason),
|
|
86
|
+
addDirs: [],
|
|
87
|
+
});
|
|
88
|
+
const again = corrected.ok ? parseDecision(corrected.text, targets) : undefined;
|
|
89
|
+
if (again?.ok) {
|
|
90
|
+
return { ok: true, decision: again.decision, reports };
|
|
91
|
+
}
|
|
92
|
+
reason = `the arbiter's answer was refused: ${again === undefined ? parsed.reason : again.reason}`;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
return { ok: false, reason, reports };
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=council.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"council.js","sourceRoot":"","sources":["../../../src/operator/supervise/council.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAiB,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAA8B,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EACL,aAAa,EAEb,UAAU,EACV,YAAY,EACZ,eAAe,EACf,aAAa,GACd,MAAM,cAAc,CAAC;AAMtB,MAAM,QAAQ,GAAG;IACf,CAAC,WAAW,EAAE,eAAe,CAAC;IAC9B,CAAC,QAAQ,EAAE,YAAY,CAAC;IACxB,CAAC,SAAS,EAAE,aAAa,CAAC;CAClB,CAAC;AAEX,+DAA+D;AAC/D,MAAM,YAAY,GAAG,MAAM,CAAC;AAa5B,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAoB;IACjD,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,IAAI,YAAY,CAAC,CAAC;IAC9D,aAAa,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,2BAA2B,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;IACtE,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAC7B,IAAI,CACF,IAAI,CAAC,GAAG,EACR,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,EACpC,EAAE,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,EAAE,CACnE,EACD,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAC9C,CAAC;IACF,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/C,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,IAAI,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC;IAC7D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,SAAS,qBAAqB,CAAC,MAAkB;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAMhC;IACC,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACjF,MAAM,IAAI,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC;IACjG,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACtC,IAAI;QACJ,GAAG,CAAC,MAAM,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;KACpE,CAAC,CAAC,CACJ,CAAC;IACF,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,QAAQ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,OAAO,QAAQ,CAAC,MAAM,sBAAsB,OAAO;iBAC3F,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;iBACpB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;iBAChD,IAAI,CAAC,KAAK,CAAC,EAAE;YAChB,OAAO;SACR,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,GAAG,uBAAuB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;YAC7D,SAAS;QACX,CAAC;QACD,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACpD,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;QAC1D,CAAC;QACD,MAAM,GAAG,qCAAqC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9D,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC;YAC/B,GAAG,IAAI;YACP,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC;YAC/C,OAAO,EAAE,EAAE;SACZ,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChF,IAAI,KAAK,EAAE,EAAE,EAAE,CAAC;YACd,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;QACzD,CAAC;QACD,MAAM,GAAG,qCAAqC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACnG,MAAM;IACR,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export declare const UNBLOCK_KINDS: readonly ["resume", "restart", "cancel", "start-worker", "restart-worker", "cleanup-disk"];
|
|
2
|
+
export type UnblockKind = (typeof UNBLOCK_KINDS)[number];
|
|
3
|
+
/** What puts the run back in motion, now or once the fixes have landed. */
|
|
4
|
+
export type Unblock = {
|
|
5
|
+
do: UnblockKind;
|
|
6
|
+
key?: string;
|
|
7
|
+
reason: string;
|
|
8
|
+
};
|
|
9
|
+
/** A change to a repository the supervisor was given, so that this does not happen again. */
|
|
10
|
+
export type Fix = {
|
|
11
|
+
target: string;
|
|
12
|
+
title: string;
|
|
13
|
+
/** The result to reach and what proves it, inside the rules. Not the design: the fixer designs. */
|
|
14
|
+
instruction: string;
|
|
15
|
+
/** The rules and accepted decisions the change touches, and why it conforms to each. */
|
|
16
|
+
conformity: string;
|
|
17
|
+
/**
|
|
18
|
+
* Set when no change can reach the result without revisiting an accepted decision or rule: which one.
|
|
19
|
+
* Such a fix is not made; a person decides.
|
|
20
|
+
*/
|
|
21
|
+
revises?: string;
|
|
22
|
+
};
|
|
23
|
+
export type Decision = {
|
|
24
|
+
summary: string;
|
|
25
|
+
cause: string;
|
|
26
|
+
/** `file:line`, a log line, a command and what it printed. Nothing that was not seen. */
|
|
27
|
+
evidence: string[];
|
|
28
|
+
confidence: "high" | "medium" | "low";
|
|
29
|
+
/** The unblock needs the fixes first (the same stop would come straight back). */
|
|
30
|
+
unblockAfterFixes: boolean;
|
|
31
|
+
unblock: Unblock[];
|
|
32
|
+
fixes: Fix[];
|
|
33
|
+
/** Set when no one but a person can go on: what only they can decide. */
|
|
34
|
+
needsHuman?: string;
|
|
35
|
+
};
|
|
36
|
+
export type Parsed = {
|
|
37
|
+
ok: true;
|
|
38
|
+
decision: Decision;
|
|
39
|
+
} | {
|
|
40
|
+
ok: false;
|
|
41
|
+
reason: string;
|
|
42
|
+
};
|
|
43
|
+
/** The last JSON object an agent printed: in a ```json fence, else the last balanced braces. */
|
|
44
|
+
export declare function lastJson(output: string): unknown;
|
|
45
|
+
export declare function parseDecision(output: string, targets: readonly string[]): Parsed;
|
|
46
|
+
//# sourceMappingURL=decision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../../../src/operator/supervise/decision.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,4FAOhB,CAAC;AACX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,2EAA2E;AAC3E,MAAM,MAAM,OAAO,GAAG;IAAE,EAAE,EAAE,WAAW,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,6FAA6F;AAC7F,MAAM,MAAM,GAAG,GAAG;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,mGAAmG;IACnG,WAAW,EAAE,MAAM,CAAC;IACpB,wFAAwF;IACxF,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,kFAAkF;IAClF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,KAAK,EAAE,GAAG,EAAE,CAAC;IACb,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAItF,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAqBhD;AAUD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CA2GhF"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
export const UNBLOCK_KINDS = [
|
|
2
|
+
"resume",
|
|
3
|
+
"restart",
|
|
4
|
+
"cancel",
|
|
5
|
+
"start-worker",
|
|
6
|
+
"restart-worker",
|
|
7
|
+
"cleanup-disk",
|
|
8
|
+
];
|
|
9
|
+
const NEEDS_KEY = ["resume", "restart", "cancel"];
|
|
10
|
+
/** The last JSON object an agent printed: in a ```json fence, else the last balanced braces. */
|
|
11
|
+
export function lastJson(output) {
|
|
12
|
+
const fenced = [...output.matchAll(/```json\s*([\s\S]*?)```/g)].map((m) => m[1] ?? "");
|
|
13
|
+
for (const body of fenced.reverse()) {
|
|
14
|
+
const value = tryParse(body);
|
|
15
|
+
if (value !== undefined) {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
for (let end = output.lastIndexOf("}"); end >= 0; end = output.lastIndexOf("}", end - 1)) {
|
|
20
|
+
for (let start = output.lastIndexOf("{", end); start >= 0; start = output.lastIndexOf("{", start - 1)) {
|
|
21
|
+
const value = tryParse(output.slice(start, end + 1));
|
|
22
|
+
if (value !== undefined) {
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
function tryParse(body) {
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(body);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function parseDecision(output, targets) {
|
|
38
|
+
const value = lastJson(output);
|
|
39
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
40
|
+
return { ok: false, reason: "no JSON object in the arbiter's answer" };
|
|
41
|
+
}
|
|
42
|
+
const o = value;
|
|
43
|
+
const problems = [];
|
|
44
|
+
const str = (name) => {
|
|
45
|
+
const v = o[name];
|
|
46
|
+
if (typeof v !== "string" || v.trim().length === 0) {
|
|
47
|
+
problems.push(`${name} must be a non-empty string`);
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
return v;
|
|
51
|
+
};
|
|
52
|
+
const summary = str("summary");
|
|
53
|
+
const cause = str("cause");
|
|
54
|
+
const evidence = Array.isArray(o.evidence) ? o.evidence.map(String) : [];
|
|
55
|
+
if (evidence.length === 0) {
|
|
56
|
+
problems.push("evidence must name what was seen");
|
|
57
|
+
}
|
|
58
|
+
const confidence = o.confidence;
|
|
59
|
+
if (confidence !== "high" && confidence !== "medium" && confidence !== "low") {
|
|
60
|
+
problems.push("confidence must be high, medium or low");
|
|
61
|
+
}
|
|
62
|
+
const unblock = [];
|
|
63
|
+
for (const raw of Array.isArray(o.unblock) ? o.unblock : []) {
|
|
64
|
+
const u = (raw ?? {});
|
|
65
|
+
const kind = UNBLOCK_KINDS.find((k) => k === u.do);
|
|
66
|
+
if (kind === undefined) {
|
|
67
|
+
problems.push(`unblock.do ${JSON.stringify(u.do)} is not one of ${UNBLOCK_KINDS.join(", ")}`);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (NEEDS_KEY.includes(kind) && typeof u.key !== "string") {
|
|
71
|
+
problems.push(`unblock ${kind} needs a key`);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
unblock.push({
|
|
75
|
+
do: kind,
|
|
76
|
+
...(typeof u.key === "string" ? { key: u.key } : {}),
|
|
77
|
+
reason: typeof u.reason === "string" ? u.reason : "",
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
const fixes = [];
|
|
81
|
+
for (const raw of Array.isArray(o.fixes) ? o.fixes : []) {
|
|
82
|
+
const f = (raw ?? {});
|
|
83
|
+
if (typeof f.target !== "string" || !targets.includes(f.target)) {
|
|
84
|
+
problems.push(`fix.target ${JSON.stringify(f.target)} is not one of ${targets.join(", ") || "(none configured)"}`);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (typeof f.title !== "string" ||
|
|
88
|
+
typeof f.instruction !== "string" ||
|
|
89
|
+
f.instruction.length < 20) {
|
|
90
|
+
problems.push("a fix needs a title and an instruction a stranger could carry out");
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (typeof f.conformity !== "string" || f.conformity.trim().length < 20) {
|
|
94
|
+
problems.push("a fix needs its conformity: the rules and accepted decisions it touches, and why it conforms");
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
fixes.push({
|
|
98
|
+
target: f.target,
|
|
99
|
+
title: f.title,
|
|
100
|
+
instruction: f.instruction,
|
|
101
|
+
conformity: f.conformity,
|
|
102
|
+
...(typeof f.revises === "string" && f.revises.trim().length > 0
|
|
103
|
+
? { revises: f.revises }
|
|
104
|
+
: {}),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
const asked = typeof o.needsHuman === "string" && o.needsHuman.length > 0 ? o.needsHuman : undefined;
|
|
108
|
+
if (asked !== undefined && unblock.length > 0) {
|
|
109
|
+
problems.push("needsHuman and unblock contradict: a stop for a person is not resumed");
|
|
110
|
+
}
|
|
111
|
+
// A change that would revisit an accepted decision is a product choice, not the supervisor's.
|
|
112
|
+
const revising = fixes.filter((fix) => fix.revises !== undefined);
|
|
113
|
+
const needsHuman = asked ??
|
|
114
|
+
(revising.length === 0
|
|
115
|
+
? undefined
|
|
116
|
+
: `A person must decide: ${revising.map((fix) => `"${fix.title}" would revise ${fix.revises}`).join("; ")}.`);
|
|
117
|
+
if (o.unblockAfterFixes === true && unblock.length === 0) {
|
|
118
|
+
problems.push("unblockAfterFixes is true but there is nothing to unblock");
|
|
119
|
+
}
|
|
120
|
+
if (problems.length > 0) {
|
|
121
|
+
return { ok: false, reason: problems.join("; ") };
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
ok: true,
|
|
125
|
+
decision: {
|
|
126
|
+
summary,
|
|
127
|
+
cause,
|
|
128
|
+
evidence,
|
|
129
|
+
confidence: confidence,
|
|
130
|
+
unblockAfterFixes: o.unblockAfterFixes === true,
|
|
131
|
+
unblock,
|
|
132
|
+
fixes,
|
|
133
|
+
...(needsHuman === undefined ? {} : { needsHuman }),
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=decision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision.js","sourceRoot":"","sources":["../../../src/operator/supervise/decision.ts"],"names":[],"mappings":"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"}
|