pi-amq 0.1.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/CHANGELOG.md +66 -0
- package/LICENSE +21 -0
- package/README.md +92 -0
- package/THIRD_PARTY_NOTICES.md +33 -0
- package/dist/extension/guidance.d.ts +25 -0
- package/dist/extension/guidance.d.ts.map +1 -0
- package/dist/extension/guidance.js +121 -0
- package/dist/extension/guidance.js.map +1 -0
- package/dist/extension/guide.d.ts +30 -0
- package/dist/extension/guide.d.ts.map +1 -0
- package/dist/extension/guide.js +128 -0
- package/dist/extension/guide.js.map +1 -0
- package/dist/extension/index.d.ts +4 -0
- package/dist/extension/index.d.ts.map +1 -0
- package/dist/extension/index.js +6 -0
- package/dist/extension/index.js.map +1 -0
- package/dist/extension/runtime.d.ts +48 -0
- package/dist/extension/runtime.d.ts.map +1 -0
- package/dist/extension/runtime.js +1095 -0
- package/dist/extension/runtime.js.map +1 -0
- package/dist/extension/tools.d.ts +12 -0
- package/dist/extension/tools.d.ts.map +1 -0
- package/dist/extension/tools.js +198 -0
- package/dist/extension/tools.js.map +1 -0
- package/dist/extension/worker-runtime.d.ts +34 -0
- package/dist/extension/worker-runtime.d.ts.map +1 -0
- package/dist/extension/worker-runtime.js +974 -0
- package/dist/extension/worker-runtime.js.map +1 -0
- package/dist/extension/worker-tools.d.ts +140 -0
- package/dist/extension/worker-tools.d.ts.map +1 -0
- package/dist/extension/worker-tools.js +217 -0
- package/dist/extension/worker-tools.js.map +1 -0
- package/dist/integration/confirmed-bind-onboarding.d.ts +44 -0
- package/dist/integration/confirmed-bind-onboarding.d.ts.map +1 -0
- package/dist/integration/confirmed-bind-onboarding.js +199 -0
- package/dist/integration/confirmed-bind-onboarding.js.map +1 -0
- package/dist/integration/fleet-view.d.ts +66 -0
- package/dist/integration/fleet-view.d.ts.map +1 -0
- package/dist/integration/fleet-view.js +238 -0
- package/dist/integration/fleet-view.js.map +1 -0
- package/dist/integration/fresh-session-dispatcher.d.ts +66 -0
- package/dist/integration/fresh-session-dispatcher.d.ts.map +1 -0
- package/dist/integration/fresh-session-dispatcher.js +103 -0
- package/dist/integration/fresh-session-dispatcher.js.map +1 -0
- package/dist/integration/launch-preview.d.ts +31 -0
- package/dist/integration/launch-preview.d.ts.map +1 -0
- package/dist/integration/launch-preview.js +325 -0
- package/dist/integration/launch-preview.js.map +1 -0
- package/dist/integration/transport-port.d.ts +39 -0
- package/dist/integration/transport-port.d.ts.map +1 -0
- package/dist/integration/transport-port.js +2 -0
- package/dist/integration/transport-port.js.map +1 -0
- package/dist/integration/worker-completion-notifier.d.ts +22 -0
- package/dist/integration/worker-completion-notifier.d.ts.map +1 -0
- package/dist/integration/worker-completion-notifier.js +81 -0
- package/dist/integration/worker-completion-notifier.js.map +1 -0
- package/dist/transport/amq-cli-adapter.d.ts +41 -0
- package/dist/transport/amq-cli-adapter.d.ts.map +1 -0
- package/dist/transport/amq-cli-adapter.js +291 -0
- package/dist/transport/amq-cli-adapter.js.map +1 -0
- package/dist/transport/amq-message.d.ts +47 -0
- package/dist/transport/amq-message.d.ts.map +1 -0
- package/dist/transport/amq-message.js +173 -0
- package/dist/transport/amq-message.js.map +1 -0
- package/dist/transport/amq-operations.d.ts +105 -0
- package/dist/transport/amq-operations.d.ts.map +1 -0
- package/dist/transport/amq-operations.js +320 -0
- package/dist/transport/amq-operations.js.map +1 -0
- package/dist/transport/atomic-json.d.ts +18 -0
- package/dist/transport/atomic-json.d.ts.map +1 -0
- package/dist/transport/atomic-json.js +90 -0
- package/dist/transport/atomic-json.js.map +1 -0
- package/dist/transport/binding-resolver.d.ts +46 -0
- package/dist/transport/binding-resolver.d.ts.map +1 -0
- package/dist/transport/binding-resolver.js +389 -0
- package/dist/transport/binding-resolver.js.map +1 -0
- package/dist/transport/bridge-journal.d.ts +100 -0
- package/dist/transport/bridge-journal.d.ts.map +1 -0
- package/dist/transport/bridge-journal.js +459 -0
- package/dist/transport/bridge-journal.js.map +1 -0
- package/dist/transport/dlq-retry-audit.d.ts +28 -0
- package/dist/transport/dlq-retry-audit.d.ts.map +1 -0
- package/dist/transport/dlq-retry-audit.js +66 -0
- package/dist/transport/dlq-retry-audit.js.map +1 -0
- package/dist/transport/inbox-pump.d.ts +81 -0
- package/dist/transport/inbox-pump.d.ts.map +1 -0
- package/dist/transport/inbox-pump.js +558 -0
- package/dist/transport/inbox-pump.js.map +1 -0
- package/dist/transport/index.d.ts +12 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +12 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/presence-projector.d.ts +29 -0
- package/dist/transport/presence-projector.d.ts.map +1 -0
- package/dist/transport/presence-projector.js +73 -0
- package/dist/transport/presence-projector.js.map +1 -0
- package/dist/transport/priority-delivery-scheduler.d.ts +85 -0
- package/dist/transport/priority-delivery-scheduler.d.ts.map +1 -0
- package/dist/transport/priority-delivery-scheduler.js +210 -0
- package/dist/transport/priority-delivery-scheduler.js.map +1 -0
- package/dist/transport/receiver-lease.d.ts +102 -0
- package/dist/transport/receiver-lease.d.ts.map +1 -0
- package/dist/transport/receiver-lease.js +778 -0
- package/dist/transport/receiver-lease.js.map +1 -0
- package/dist/transport/runtime-status.d.ts +48 -0
- package/dist/transport/runtime-status.d.ts.map +1 -0
- package/dist/transport/runtime-status.js +71 -0
- package/dist/transport/runtime-status.js.map +1 -0
- package/dist/workflow/atomic-storage.d.ts +12 -0
- package/dist/workflow/atomic-storage.d.ts.map +1 -0
- package/dist/workflow/atomic-storage.js +104 -0
- package/dist/workflow/atomic-storage.js.map +1 -0
- package/dist/workflow/budget.d.ts +18 -0
- package/dist/workflow/budget.d.ts.map +1 -0
- package/dist/workflow/budget.js +74 -0
- package/dist/workflow/budget.js.map +1 -0
- package/dist/workflow/index.d.ts +17 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +17 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/lifecycle-projection.d.ts +18 -0
- package/dist/workflow/lifecycle-projection.d.ts.map +1 -0
- package/dist/workflow/lifecycle-projection.js +22 -0
- package/dist/workflow/lifecycle-projection.js.map +1 -0
- package/dist/workflow/model-fallback.d.ts +2 -0
- package/dist/workflow/model-fallback.d.ts.map +1 -0
- package/dist/workflow/model-fallback.js +17 -0
- package/dist/workflow/model-fallback.js.map +1 -0
- package/dist/workflow/pi-session-fork.d.ts +18 -0
- package/dist/workflow/pi-session-fork.d.ts.map +1 -0
- package/dist/workflow/pi-session-fork.js +80 -0
- package/dist/workflow/pi-session-fork.js.map +1 -0
- package/dist/workflow/run-artifacts.d.ts +5 -0
- package/dist/workflow/run-artifacts.d.ts.map +1 -0
- package/dist/workflow/run-artifacts.js +25 -0
- package/dist/workflow/run-artifacts.js.map +1 -0
- package/dist/workflow/run-cleanup.d.ts +70 -0
- package/dist/workflow/run-cleanup.d.ts.map +1 -0
- package/dist/workflow/run-cleanup.js +222 -0
- package/dist/workflow/run-cleanup.js.map +1 -0
- package/dist/workflow/run-gate.d.ts +43 -0
- package/dist/workflow/run-gate.d.ts.map +1 -0
- package/dist/workflow/run-gate.js +70 -0
- package/dist/workflow/run-gate.js.map +1 -0
- package/dist/workflow/run-store.d.ts +208 -0
- package/dist/workflow/run-store.d.ts.map +1 -0
- package/dist/workflow/run-store.js +2965 -0
- package/dist/workflow/run-store.js.map +1 -0
- package/dist/workflow/spawn-confirmation.d.ts +44 -0
- package/dist/workflow/spawn-confirmation.d.ts.map +1 -0
- package/dist/workflow/spawn-confirmation.js +228 -0
- package/dist/workflow/spawn-confirmation.js.map +1 -0
- package/dist/workflow/system-process-inspector.d.ts +9 -0
- package/dist/workflow/system-process-inspector.d.ts.map +1 -0
- package/dist/workflow/system-process-inspector.js +129 -0
- package/dist/workflow/system-process-inspector.js.map +1 -0
- package/dist/workflow/worker-child-extension.d.ts +3 -0
- package/dist/workflow/worker-child-extension.d.ts.map +1 -0
- package/dist/workflow/worker-child-extension.js +182 -0
- package/dist/workflow/worker-child-extension.js.map +1 -0
- package/dist/workflow/worker-gate.d.ts +74 -0
- package/dist/workflow/worker-gate.d.ts.map +1 -0
- package/dist/workflow/worker-gate.js +165 -0
- package/dist/workflow/worker-gate.js.map +1 -0
- package/dist/workflow/worker-launch.d.ts +65 -0
- package/dist/workflow/worker-launch.d.ts.map +1 -0
- package/dist/workflow/worker-launch.js +338 -0
- package/dist/workflow/worker-launch.js.map +1 -0
- package/dist/workflow/worker-model-catalog.d.ts +36 -0
- package/dist/workflow/worker-model-catalog.d.ts.map +1 -0
- package/dist/workflow/worker-model-catalog.js +105 -0
- package/dist/workflow/worker-model-catalog.js.map +1 -0
- package/dist/workflow/worker-process-supervisor.d.ts +110 -0
- package/dist/workflow/worker-process-supervisor.d.ts.map +1 -0
- package/dist/workflow/worker-process-supervisor.js +1188 -0
- package/dist/workflow/worker-process-supervisor.js.map +1 -0
- package/dist/workflow/worker-prompt-capsule.d.ts +32 -0
- package/dist/workflow/worker-prompt-capsule.d.ts.map +1 -0
- package/dist/workflow/worker-prompt-capsule.js +52 -0
- package/dist/workflow/worker-prompt-capsule.js.map +1 -0
- package/dist/workflow/worker-role-presets.d.ts +38 -0
- package/dist/workflow/worker-role-presets.d.ts.map +1 -0
- package/dist/workflow/worker-role-presets.js +201 -0
- package/dist/workflow/worker-role-presets.js.map +1 -0
- package/dist/workflow/workflow-doctor.d.ts +57 -0
- package/dist/workflow/workflow-doctor.d.ts.map +1 -0
- package/dist/workflow/workflow-doctor.js +289 -0
- package/dist/workflow/workflow-doctor.js.map +1 -0
- package/dist/workflow/workflow-lease.d.ts +125 -0
- package/dist/workflow/workflow-lease.d.ts.map +1 -0
- package/dist/workflow/workflow-lease.js +689 -0
- package/dist/workflow/workflow-lease.js.map +1 -0
- package/dist/workflow/workflow-types.d.ts +335 -0
- package/dist/workflow/workflow-types.d.ts.map +1 -0
- package/dist/workflow/workflow-types.js +11 -0
- package/dist/workflow/workflow-types.js.map +1 -0
- package/dist/workflow/workspace-paths.d.ts +4 -0
- package/dist/workflow/workspace-paths.d.ts.map +1 -0
- package/dist/workflow/workspace-paths.js +22 -0
- package/dist/workflow/workspace-paths.js.map +1 -0
- package/docs/conformance.md +116 -0
- package/docs/demo-transcript.md +34 -0
- package/docs/design.md +1481 -0
- package/docs/operator-guide.md +100 -0
- package/extension/guidance.ts +162 -0
- package/extension/guide.ts +155 -0
- package/extension/index.ts +8 -0
- package/extension/runtime.ts +1224 -0
- package/extension/tools.ts +221 -0
- package/extension/worker-runtime.ts +1150 -0
- package/extension/worker-tools.ts +276 -0
- package/integration/confirmed-bind-onboarding.ts +296 -0
- package/integration/fleet-view.ts +286 -0
- package/integration/fresh-session-dispatcher.ts +166 -0
- package/integration/launch-preview.ts +396 -0
- package/integration/transport-port.ts +29 -0
- package/integration/worker-completion-notifier.ts +98 -0
- package/package.json +55 -0
- package/roles/oracle.md +9 -0
- package/roles/researcher.md +8 -0
- package/roles/reviewer.md +9 -0
- package/roles/scout.md +8 -0
- package/roles/worker.md +10 -0
- package/scripts/demo-two-terminal.sh +59 -0
- package/skills/coordination-patterns/SKILL.md +41 -0
- package/skills/coordination-patterns/references/supervised-worker-fan-out.md +12 -0
- package/skills/coordination-patterns/references/today-mail-team.md +36 -0
- package/transport/amq-cli-adapter.ts +381 -0
- package/transport/amq-message.ts +218 -0
- package/transport/amq-operations.ts +482 -0
- package/transport/atomic-json.ts +115 -0
- package/transport/binding-resolver.ts +565 -0
- package/transport/bridge-journal.ts +588 -0
- package/transport/dlq-retry-audit.ts +97 -0
- package/transport/inbox-pump.ts +729 -0
- package/transport/index.ts +11 -0
- package/transport/presence-projector.ts +104 -0
- package/transport/priority-delivery-scheduler.ts +328 -0
- package/transport/receiver-lease.ts +945 -0
- package/transport/runtime-status.ts +112 -0
- package/workflow/.gitkeep +1 -0
- package/workflow/atomic-storage.ts +120 -0
- package/workflow/budget.ts +90 -0
- package/workflow/index.ts +16 -0
- package/workflow/lifecycle-projection.ts +37 -0
- package/workflow/model-fallback.ts +17 -0
- package/workflow/pi-session-fork.ts +96 -0
- package/workflow/run-artifacts.ts +36 -0
- package/workflow/run-cleanup.ts +315 -0
- package/workflow/run-gate.ts +122 -0
- package/workflow/run-store.ts +3890 -0
- package/workflow/spawn-confirmation.ts +305 -0
- package/workflow/system-process-inspector.ts +142 -0
- package/workflow/worker-child-extension.ts +193 -0
- package/workflow/worker-gate.ts +238 -0
- package/workflow/worker-launch.ts +485 -0
- package/workflow/worker-model-catalog.ts +165 -0
- package/workflow/worker-process-supervisor.ts +1504 -0
- package/workflow/worker-prompt-capsule.ts +81 -0
- package/workflow/worker-role-presets.ts +241 -0
- package/workflow/workflow-doctor.ts +400 -0
- package/workflow/workflow-lease.ts +905 -0
- package/workflow/workflow-types.ts +367 -0
- package/workflow/workspace-paths.ts +32 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { access, mkdir, readFile, rename, rm } from "node:fs/promises";
|
|
2
|
+
import { isAbsolute, dirname, normalize } from "node:path";
|
|
3
|
+
import { SessionManager } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
export function describeCurrentPiSessionFork(source) {
|
|
5
|
+
const sourceSessionFile = source.getSessionFile();
|
|
6
|
+
if (!sourceSessionFile || !isAbsolute(sourceSessionFile)) {
|
|
7
|
+
throw new Error("Fork context requires a persisted absolute parent Pi session file");
|
|
8
|
+
}
|
|
9
|
+
const branchPointId = source.getLeafId();
|
|
10
|
+
if (!branchPointId)
|
|
11
|
+
throw new Error("Fork context requires a current parent session leaf");
|
|
12
|
+
const branch = source.getBranch(branchPointId);
|
|
13
|
+
if (branch.length === 0 || !branch.some((entry) => entry.id === branchPointId)) {
|
|
14
|
+
throw new Error("Fork context branch point is absent from the parent session");
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
sourceSessionFile: normalize(sourceSessionFile),
|
|
18
|
+
branchPointId,
|
|
19
|
+
inheritedEntries: branch.length,
|
|
20
|
+
inheritedBytes: branch.reduce((total, entry) => total + Buffer.byteLength(`${JSON.stringify(entry)}\n`, "utf8"), 0),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export class NodePiSessionForker {
|
|
24
|
+
async fork(input) {
|
|
25
|
+
const sourceSessionFile = absolute(input.sourceSessionFile, "fork source session file");
|
|
26
|
+
const targetSessionFile = absolute(input.targetSessionFile, "fork target session file");
|
|
27
|
+
if (sourceSessionFile === targetSessionFile) {
|
|
28
|
+
throw new Error("Fork target session file must differ from its parent");
|
|
29
|
+
}
|
|
30
|
+
await assertAbsent(targetSessionFile);
|
|
31
|
+
await mkdir(dirname(targetSessionFile), { recursive: true, mode: 0o700 });
|
|
32
|
+
const sourceBefore = await readFile(sourceSessionFile);
|
|
33
|
+
const manager = SessionManager.open(sourceSessionFile, dirname(targetSessionFile));
|
|
34
|
+
if (!manager.getEntry(input.branchPointId)) {
|
|
35
|
+
throw new Error(`Fork branch point ${input.branchPointId} is absent from the parent session`);
|
|
36
|
+
}
|
|
37
|
+
let generated;
|
|
38
|
+
try {
|
|
39
|
+
generated = manager.createBranchedSession(input.branchPointId);
|
|
40
|
+
if (!generated)
|
|
41
|
+
throw new Error("Pi session fork did not produce a persisted child session");
|
|
42
|
+
await access(generated);
|
|
43
|
+
await rename(generated, targetSessionFile);
|
|
44
|
+
generated = undefined;
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
if (generated)
|
|
48
|
+
await rm(generated, { force: true }).catch(() => { });
|
|
49
|
+
}
|
|
50
|
+
const child = SessionManager.open(targetSessionFile, dirname(targetSessionFile));
|
|
51
|
+
if (child.getHeader()?.parentSession !== sourceSessionFile) {
|
|
52
|
+
throw new Error("Fork child session does not record the expected parent session");
|
|
53
|
+
}
|
|
54
|
+
if (!child.getEntry(input.branchPointId)) {
|
|
55
|
+
throw new Error("Fork child session does not contain the requested branch point");
|
|
56
|
+
}
|
|
57
|
+
const sourceAfter = await readFile(sourceSessionFile);
|
|
58
|
+
if (!sourceAfter.equals(sourceBefore)) {
|
|
59
|
+
throw new Error("Forking mutated the parent Pi session file");
|
|
60
|
+
}
|
|
61
|
+
return targetSessionFile;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function absolute(value, label) {
|
|
65
|
+
if (!isAbsolute(value))
|
|
66
|
+
throw new TypeError(`${label} must be absolute`);
|
|
67
|
+
return normalize(value);
|
|
68
|
+
}
|
|
69
|
+
async function assertAbsent(path) {
|
|
70
|
+
try {
|
|
71
|
+
await access(path);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (error.code === "ENOENT")
|
|
75
|
+
return;
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
throw new Error(`Fork target session file already exists: ${path}`);
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=pi-session-fork.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-session-fork.js","sourceRoot":"","sources":["../../workflow/pi-session-fork.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { WorkerRequest } from "./workflow-types.js";
|
|
2
|
+
export declare function runArtifactDirectory(namespaceDirectory: string, requestKey: string): string;
|
|
3
|
+
export declare function ensureRunArtifactDirectory(namespaceDirectory: string, requestKey: string): Promise<string>;
|
|
4
|
+
export declare function withRunArtifactContext(request: WorkerRequest, artifactDirectory: string): WorkerRequest;
|
|
5
|
+
//# sourceMappingURL=run-artifacts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-artifacts.d.ts","sourceRoot":"","sources":["../../workflow/run-artifacts.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,wBAAgB,oBAAoB,CAAC,kBAAkB,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE3F;AAED,wBAAsB,0BAA0B,CAC9C,kBAAkB,EAAE,MAAM,EAC1B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,aAAa,EACtB,iBAAiB,EAAE,MAAM,GACxB,aAAa,CAaf"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import { isAbsolute, join, normalize } from "node:path";
|
|
3
|
+
import { runDirectoryForRequest } from "./run-store.js";
|
|
4
|
+
export function runArtifactDirectory(namespaceDirectory, requestKey) {
|
|
5
|
+
return join(runDirectoryForRequest(namespaceDirectory, requestKey), "artifacts");
|
|
6
|
+
}
|
|
7
|
+
export async function ensureRunArtifactDirectory(namespaceDirectory, requestKey) {
|
|
8
|
+
const directory = runArtifactDirectory(namespaceDirectory, requestKey);
|
|
9
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
10
|
+
return directory;
|
|
11
|
+
}
|
|
12
|
+
export function withRunArtifactContext(request, artifactDirectory) {
|
|
13
|
+
if (!isAbsolute(artifactDirectory)) {
|
|
14
|
+
throw new TypeError("Run artifact directory must be absolute");
|
|
15
|
+
}
|
|
16
|
+
const canonical = normalize(artifactDirectory);
|
|
17
|
+
return {
|
|
18
|
+
...request,
|
|
19
|
+
contextRefs: [
|
|
20
|
+
{ kind: "artifact", value: canonical },
|
|
21
|
+
...request.contextRefs.filter((reference) => reference.kind !== "artifact" || normalize(reference.value) !== canonical),
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=run-artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-artifacts.js","sourceRoot":"","sources":["../../workflow/run-artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAGxD,MAAM,UAAU,oBAAoB,CAAC,kBAA0B,EAAE,UAAkB;IACjF,OAAO,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,EAAE,UAAU,CAAC,EAAE,WAAW,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,kBAA0B,EAC1B,UAAkB;IAElB,MAAM,SAAS,GAAG,oBAAoB,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;IACvE,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACzD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,OAAsB,EACtB,iBAAyB;IAEzB,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,SAAS,GAAG,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC/C,OAAO;QACL,GAAG,OAAO;QACV,WAAW,EAAE;YACX,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE;YACtC,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAC1C,SAAS,CAAC,IAAI,KAAK,UAAU,IAAI,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC;SAC7E;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { WorkflowLeaseManager } from "./workflow-lease.js";
|
|
2
|
+
import type { RunProjectionV2 } from "./workflow-types.js";
|
|
3
|
+
export interface CleanupItem {
|
|
4
|
+
readonly kind: "run" | "worker-session" | "artifact";
|
|
5
|
+
readonly path: string;
|
|
6
|
+
readonly bytes: number;
|
|
7
|
+
}
|
|
8
|
+
export interface CleanupCandidate {
|
|
9
|
+
readonly requestKey: string;
|
|
10
|
+
readonly runId: string;
|
|
11
|
+
readonly updatedAt: string;
|
|
12
|
+
readonly ageMs: number;
|
|
13
|
+
readonly items: readonly CleanupItem[];
|
|
14
|
+
readonly reclaimableBytes: number;
|
|
15
|
+
}
|
|
16
|
+
export interface CleanupSkip {
|
|
17
|
+
readonly requestKey: string;
|
|
18
|
+
readonly runId: string;
|
|
19
|
+
readonly reason: "not-old-enough" | "active-run" | "ambiguous-run" | "active-worker" | "held-session-lease" | "corrupt-session-lease";
|
|
20
|
+
readonly diagnostic: string;
|
|
21
|
+
}
|
|
22
|
+
export interface RunCleanupPlan {
|
|
23
|
+
readonly dryRun: true;
|
|
24
|
+
readonly olderThanMs: number;
|
|
25
|
+
readonly candidates: readonly CleanupCandidate[];
|
|
26
|
+
readonly skipped: readonly CleanupSkip[];
|
|
27
|
+
readonly reclaimableBytes: number;
|
|
28
|
+
}
|
|
29
|
+
export interface RunCleanupResult extends Omit<RunCleanupPlan, "dryRun"> {
|
|
30
|
+
readonly dryRun: false;
|
|
31
|
+
readonly auditEventPath: string | null;
|
|
32
|
+
readonly deletedRunIds: readonly string[];
|
|
33
|
+
}
|
|
34
|
+
interface CleanupRunCatalog {
|
|
35
|
+
listRuns(): Promise<readonly RunProjectionV2[]>;
|
|
36
|
+
}
|
|
37
|
+
interface CleanupLeaseAuthority {
|
|
38
|
+
withCurrentSupervisor<T>(generation: string, operation: () => Promise<T>): Promise<T>;
|
|
39
|
+
inspectWorkerSession(sessionPath: string): ReturnType<WorkflowLeaseManager["inspectWorkerSession"]>;
|
|
40
|
+
}
|
|
41
|
+
export interface WorkflowRunCleanupOptions {
|
|
42
|
+
readonly namespaceDirectory: string;
|
|
43
|
+
readonly store: CleanupRunCatalog;
|
|
44
|
+
readonly leaseManager: CleanupLeaseAuthority;
|
|
45
|
+
readonly supervisorGeneration: string;
|
|
46
|
+
readonly now?: () => Date;
|
|
47
|
+
readonly randomUUID?: () => string;
|
|
48
|
+
readonly removePath?: (path: string) => Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
export declare class CleanupConfirmationError extends Error {
|
|
51
|
+
constructor(message: string);
|
|
52
|
+
}
|
|
53
|
+
export declare class WorkflowRunCleanup {
|
|
54
|
+
#private;
|
|
55
|
+
constructor(options: WorkflowRunCleanupOptions);
|
|
56
|
+
plan(olderThanMs: number): Promise<RunCleanupPlan>;
|
|
57
|
+
execute(input: {
|
|
58
|
+
readonly olderThanMs: number;
|
|
59
|
+
readonly confirmed: boolean;
|
|
60
|
+
}): Promise<RunCleanupResult>;
|
|
61
|
+
}
|
|
62
|
+
export declare function confirmCleanupDeletion(input: {
|
|
63
|
+
readonly dryRun: boolean;
|
|
64
|
+
readonly yes: boolean;
|
|
65
|
+
readonly tui: boolean;
|
|
66
|
+
readonly confirm?: () => Promise<boolean>;
|
|
67
|
+
}): Promise<boolean>;
|
|
68
|
+
export declare function parseCleanupAge(value: string): number;
|
|
69
|
+
export {};
|
|
70
|
+
//# sourceMappingURL=run-cleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-cleanup.d.ts","sourceRoot":"","sources":["../../workflow/run-cleanup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { randomUUID as nodeRandomUUID } from "node:crypto";
|
|
2
|
+
import { lstat, mkdir, readdir, rm } from "node:fs/promises";
|
|
3
|
+
import { isAbsolute, join, normalize, relative, sep } from "node:path";
|
|
4
|
+
import { writeWorkflowJson } from "./atomic-storage.js";
|
|
5
|
+
import { runDirectoryForRequest } from "./run-store.js";
|
|
6
|
+
import { WorkflowLeaseManager } from "./workflow-lease.js";
|
|
7
|
+
export class CleanupConfirmationError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "CleanupConfirmationError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class WorkflowRunCleanup {
|
|
14
|
+
#namespaceDirectory;
|
|
15
|
+
#store;
|
|
16
|
+
#leaseManager;
|
|
17
|
+
#supervisorGeneration;
|
|
18
|
+
#now;
|
|
19
|
+
#randomUUID;
|
|
20
|
+
#removePath;
|
|
21
|
+
constructor(options) {
|
|
22
|
+
if (!isAbsolute(options.namespaceDirectory)) {
|
|
23
|
+
throw new TypeError("Workflow cleanup namespace must be absolute");
|
|
24
|
+
}
|
|
25
|
+
this.#namespaceDirectory = normalize(options.namespaceDirectory);
|
|
26
|
+
this.#store = options.store;
|
|
27
|
+
this.#leaseManager = options.leaseManager;
|
|
28
|
+
this.#supervisorGeneration = requireNonEmpty(options.supervisorGeneration, "workflow supervisor generation");
|
|
29
|
+
this.#now = options.now ?? (() => new Date());
|
|
30
|
+
this.#randomUUID = options.randomUUID ?? nodeRandomUUID;
|
|
31
|
+
this.#removePath = options.removePath ?? (async (path) => {
|
|
32
|
+
assertOwnedPath(this.#namespaceDirectory, path);
|
|
33
|
+
await rm(path, { recursive: true, force: true });
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async plan(olderThanMs) {
|
|
37
|
+
const age = positiveInteger(olderThanMs, "cleanup age");
|
|
38
|
+
const nowMs = this.#now().getTime();
|
|
39
|
+
const candidates = [];
|
|
40
|
+
const skipped = [];
|
|
41
|
+
for (const run of await this.#store.listRuns()) {
|
|
42
|
+
const evaluated = await this.#evaluate(run, age, nowMs);
|
|
43
|
+
if ("reason" in evaluated)
|
|
44
|
+
skipped.push(evaluated);
|
|
45
|
+
else
|
|
46
|
+
candidates.push(evaluated);
|
|
47
|
+
}
|
|
48
|
+
candidates.sort((left, right) => left.runId.localeCompare(right.runId));
|
|
49
|
+
skipped.sort((left, right) => left.runId.localeCompare(right.runId));
|
|
50
|
+
return {
|
|
51
|
+
dryRun: true,
|
|
52
|
+
olderThanMs: age,
|
|
53
|
+
candidates,
|
|
54
|
+
skipped,
|
|
55
|
+
reclaimableBytes: candidates.reduce((sum, candidate) => sum + candidate.reclaimableBytes, 0),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
async execute(input) {
|
|
59
|
+
if (!input.confirmed) {
|
|
60
|
+
throw new CleanupConfirmationError("Workflow cleanup deletion requires explicit confirmation");
|
|
61
|
+
}
|
|
62
|
+
return this.#leaseManager.withCurrentSupervisor(this.#supervisorGeneration, async () => {
|
|
63
|
+
const plan = await this.plan(input.olderThanMs);
|
|
64
|
+
if (plan.candidates.length === 0) {
|
|
65
|
+
return { ...plan, dryRun: false, auditEventPath: null, deletedRunIds: [] };
|
|
66
|
+
}
|
|
67
|
+
const auditEventPath = await this.#recordAudit(plan);
|
|
68
|
+
const deletedRunIds = [];
|
|
69
|
+
for (const candidate of plan.candidates) {
|
|
70
|
+
for (const session of candidate.items.filter((item) => item.kind === "worker-session")) {
|
|
71
|
+
await this.#removePath(session.path);
|
|
72
|
+
}
|
|
73
|
+
const run = candidate.items.find((item) => item.kind === "run");
|
|
74
|
+
if (!run)
|
|
75
|
+
throw new Error(`Cleanup candidate ${candidate.runId} has no run directory`);
|
|
76
|
+
await this.#removePath(run.path);
|
|
77
|
+
deletedRunIds.push(candidate.runId);
|
|
78
|
+
}
|
|
79
|
+
return { ...plan, dryRun: false, auditEventPath, deletedRunIds };
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
async #evaluate(run, olderThanMs, nowMs) {
|
|
83
|
+
const ageMs = Math.max(0, nowMs - Date.parse(run.updatedAt));
|
|
84
|
+
if (ageMs < olderThanMs) {
|
|
85
|
+
return skip(run, "not-old-enough", `run age ${ageMs}ms is below ${olderThanMs}ms`);
|
|
86
|
+
}
|
|
87
|
+
if (run.state === "ambiguous" || run.state === "needs-attention"
|
|
88
|
+
|| run.unresolvedAmbiguities.length > 0) {
|
|
89
|
+
return skip(run, "ambiguous-run", `run state is ${run.state}`);
|
|
90
|
+
}
|
|
91
|
+
if (run.state !== "done" && run.state !== "cancelled") {
|
|
92
|
+
return skip(run, "active-run", `run state is ${run.state}`);
|
|
93
|
+
}
|
|
94
|
+
const attempts = Object.values(run.workers).flatMap((worker) => worker.attempts);
|
|
95
|
+
if (attempts.some(isActiveAttempt)) {
|
|
96
|
+
return skip(run, "active-worker", "at least one worker attempt is active or lacks exit evidence");
|
|
97
|
+
}
|
|
98
|
+
const sessionPaths = [...new Set(attempts.map((attempt) => attempt.session.path))].sort();
|
|
99
|
+
for (const sessionPath of sessionPaths) {
|
|
100
|
+
const lease = await this.#leaseManager.inspectWorkerSession(sessionPath);
|
|
101
|
+
if (lease.kind === "owned") {
|
|
102
|
+
return skip(run, "held-session-lease", `session ${sessionPath} is held by generation ${lease.owner.generation}`);
|
|
103
|
+
}
|
|
104
|
+
if (lease.kind === "corrupt") {
|
|
105
|
+
return skip(run, "corrupt-session-lease", lease.diagnostic);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const runPath = runDirectoryForRequest(this.#namespaceDirectory, run.requestKey);
|
|
109
|
+
const artifactPath = join(runPath, "artifacts");
|
|
110
|
+
const runBytes = await pathBytes(runPath);
|
|
111
|
+
const items = [{ kind: "run", path: runPath, bytes: runBytes }];
|
|
112
|
+
for (const sessionPath of sessionPaths) {
|
|
113
|
+
assertOwnedPath(this.#namespaceDirectory, sessionPath);
|
|
114
|
+
items.push({ kind: "worker-session", path: sessionPath, bytes: await pathBytes(sessionPath) });
|
|
115
|
+
}
|
|
116
|
+
const artifactBytes = await pathBytes(artifactPath);
|
|
117
|
+
if (artifactBytes > 0)
|
|
118
|
+
items.push({ kind: "artifact", path: artifactPath, bytes: artifactBytes });
|
|
119
|
+
return {
|
|
120
|
+
requestKey: run.requestKey,
|
|
121
|
+
runId: run.runId,
|
|
122
|
+
updatedAt: run.updatedAt,
|
|
123
|
+
ageMs,
|
|
124
|
+
items,
|
|
125
|
+
reclaimableBytes: runBytes + items
|
|
126
|
+
.filter((item) => item.kind === "worker-session")
|
|
127
|
+
.reduce((sum, item) => sum + item.bytes, 0),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
async #recordAudit(plan) {
|
|
131
|
+
const directory = join(this.#namespaceDirectory, "cleanup-ledger", "events");
|
|
132
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
133
|
+
const eventId = `cleanup_${requireNonEmpty(this.#randomUUID(), "cleanup event UUID")}`;
|
|
134
|
+
const path = join(directory, `${this.#now().getTime()}.${safePathPart(eventId)}.json`);
|
|
135
|
+
await writeWorkflowJson(path, {
|
|
136
|
+
schema: 1,
|
|
137
|
+
eventId,
|
|
138
|
+
type: "cleanup-started",
|
|
139
|
+
occurredAt: this.#now().toISOString(),
|
|
140
|
+
supervisorGeneration: this.#supervisorGeneration,
|
|
141
|
+
olderThanMs: plan.olderThanMs,
|
|
142
|
+
candidates: plan.candidates,
|
|
143
|
+
reclaimableBytes: plan.reclaimableBytes,
|
|
144
|
+
}, { createOnly: true });
|
|
145
|
+
return path;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
export async function confirmCleanupDeletion(input) {
|
|
149
|
+
if (input.dryRun)
|
|
150
|
+
return false;
|
|
151
|
+
if (input.tui) {
|
|
152
|
+
if (!input.confirm || !await input.confirm()) {
|
|
153
|
+
throw new CleanupConfirmationError("Workflow cleanup was not confirmed; no state changed");
|
|
154
|
+
}
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
if (!input.yes) {
|
|
158
|
+
throw new CleanupConfirmationError("Headless workflow cleanup requires explicit yes=true");
|
|
159
|
+
}
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
export function parseCleanupAge(value) {
|
|
163
|
+
const match = /^(\d+)(ms|s|m|h|d|w)$/.exec(value.trim());
|
|
164
|
+
if (!match)
|
|
165
|
+
throw new TypeError("Cleanup age must use <integer><ms|s|m|h|d|w>");
|
|
166
|
+
const amount = Number(match[1]);
|
|
167
|
+
const multiplier = { ms: 1, s: 1_000, m: 60_000, h: 3_600_000, d: 86_400_000, w: 604_800_000 }[match[2]];
|
|
168
|
+
const result = amount * multiplier;
|
|
169
|
+
return positiveInteger(result, "cleanup age");
|
|
170
|
+
}
|
|
171
|
+
function isActiveAttempt(attempt) {
|
|
172
|
+
return attempt.pidStartEvidence.observedExitAt === null
|
|
173
|
+
|| attempt.pidStartEvidence.exitStatus === null
|
|
174
|
+
|| attempt.state === "pending"
|
|
175
|
+
|| attempt.state === "running"
|
|
176
|
+
|| attempt.state === "blocked"
|
|
177
|
+
|| attempt.state === "ambiguous";
|
|
178
|
+
}
|
|
179
|
+
function skip(run, reason, diagnostic) {
|
|
180
|
+
return { requestKey: run.requestKey, runId: run.runId, reason, diagnostic };
|
|
181
|
+
}
|
|
182
|
+
async function pathBytes(path) {
|
|
183
|
+
let info;
|
|
184
|
+
try {
|
|
185
|
+
info = await lstat(path);
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
if (isNodeError(error) && error.code === "ENOENT")
|
|
189
|
+
return 0;
|
|
190
|
+
throw error;
|
|
191
|
+
}
|
|
192
|
+
if (!info.isDirectory())
|
|
193
|
+
return info.size;
|
|
194
|
+
let total = info.size;
|
|
195
|
+
for (const entry of await readdir(path, { withFileTypes: true })) {
|
|
196
|
+
total += await pathBytes(join(path, entry.name));
|
|
197
|
+
}
|
|
198
|
+
return total;
|
|
199
|
+
}
|
|
200
|
+
function assertOwnedPath(namespaceDirectory, path) {
|
|
201
|
+
const child = relative(namespaceDirectory, normalize(path));
|
|
202
|
+
if (child.length === 0 || child === ".." || child.startsWith(`..${sep}`) || isAbsolute(child)) {
|
|
203
|
+
throw new Error(`Workflow cleanup path escapes its namespace: ${path}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function positiveInteger(value, name) {
|
|
207
|
+
if (!Number.isSafeInteger(value) || value <= 0)
|
|
208
|
+
throw new TypeError(`${name} must be positive`);
|
|
209
|
+
return value;
|
|
210
|
+
}
|
|
211
|
+
function requireNonEmpty(value, name) {
|
|
212
|
+
if (value.length === 0)
|
|
213
|
+
throw new TypeError(`${name} is required`);
|
|
214
|
+
return value;
|
|
215
|
+
}
|
|
216
|
+
function safePathPart(value) {
|
|
217
|
+
return value.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
218
|
+
}
|
|
219
|
+
function isNodeError(error) {
|
|
220
|
+
return error instanceof Error && "code" in error;
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=run-cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-cleanup.js","sourceRoot":"","sources":["../../workflow/run-cleanup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { RUN_STATES, type RunState } from "./workflow-types.js";
|
|
2
|
+
export { RUN_STATES, type RunState };
|
|
3
|
+
export interface RunGateFacts {
|
|
4
|
+
readonly objective: {
|
|
5
|
+
readonly evidenceComplete: boolean;
|
|
6
|
+
readonly verifierPassed: boolean;
|
|
7
|
+
readonly prerequisitesComplete: boolean;
|
|
8
|
+
};
|
|
9
|
+
readonly workers: {
|
|
10
|
+
readonly active: boolean;
|
|
11
|
+
readonly uncertain: boolean;
|
|
12
|
+
readonly detached: boolean;
|
|
13
|
+
};
|
|
14
|
+
readonly cancellation: {
|
|
15
|
+
readonly requested: boolean;
|
|
16
|
+
readonly settled: boolean;
|
|
17
|
+
};
|
|
18
|
+
readonly input: {
|
|
19
|
+
readonly delivered: boolean;
|
|
20
|
+
};
|
|
21
|
+
readonly reconciliation: {
|
|
22
|
+
readonly recorded: boolean;
|
|
23
|
+
readonly uncertaintyCleared: boolean;
|
|
24
|
+
};
|
|
25
|
+
readonly attention: {
|
|
26
|
+
readonly cleared: boolean;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export type RunGateGuard = "objective.evidence.complete" | "objective.verifier.passed" | "objective.prerequisites.complete" | "workers.none_active" | "workers.none_uncertain" | "workers.none_detached" | "cancellation.requested" | "cancellation.settled" | "input.delivered" | "reconciliation.recorded" | "reconciliation.uncertainty_cleared" | "attention.cleared";
|
|
30
|
+
export interface RunTransitionRule {
|
|
31
|
+
readonly from: RunState;
|
|
32
|
+
readonly to: RunState;
|
|
33
|
+
readonly guards: readonly RunGateGuard[];
|
|
34
|
+
}
|
|
35
|
+
export declare const RUN_LEGALITY_TABLE: readonly RunTransitionRule[];
|
|
36
|
+
export declare function evaluateRunTransition(from: RunState, to: RunState, facts: RunGateFacts): {
|
|
37
|
+
readonly allowed: true;
|
|
38
|
+
} | {
|
|
39
|
+
readonly allowed: false;
|
|
40
|
+
readonly reason: "undeclared-transition" | "guard-failed";
|
|
41
|
+
readonly blockers: readonly RunGateGuard[];
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=run-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-gate.d.ts","sourceRoot":"","sources":["../../workflow/run-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAE,CAAC;AAErC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE;QAClB,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;QACnC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;QACjC,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;KACzC,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;QAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;KAC5B,CAAC;IACF,QAAQ,CAAC,YAAY,EAAE;QACrB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;QAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;KAC3B,CAAC;IACF,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAChD,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9F,QAAQ,CAAC,SAAS,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CACnD;AAED,MAAM,MAAM,YAAY,GACpB,6BAA6B,GAC7B,2BAA2B,GAC3B,kCAAkC,GAClC,qBAAqB,GACrB,wBAAwB,GACxB,uBAAuB,GACvB,wBAAwB,GACxB,sBAAsB,GACtB,iBAAiB,GACjB,yBAAyB,GACzB,oCAAoC,GACpC,mBAAmB,CAAC;AAExB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;CAC1C;AAgBD,eAAO,MAAM,kBAAkB,EAAE,SAAS,iBAAiB,EA+BjD,CAAC;AAEX,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,QAAQ,EACd,EAAE,EAAE,QAAQ,EACZ,KAAK,EAAE,YAAY,GAClB;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAC9B,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,uBAAuB,GAAG,cAAc,CAAC;IAC1D,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;CAC5C,CAKA"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { RUN_STATES } from "./workflow-types.js";
|
|
2
|
+
export { RUN_STATES };
|
|
3
|
+
const DONE_GUARDS = [
|
|
4
|
+
"objective.evidence.complete",
|
|
5
|
+
"objective.verifier.passed",
|
|
6
|
+
"objective.prerequisites.complete",
|
|
7
|
+
"workers.none_active",
|
|
8
|
+
"workers.none_uncertain",
|
|
9
|
+
"workers.none_detached",
|
|
10
|
+
];
|
|
11
|
+
const RECONCILED = [
|
|
12
|
+
"reconciliation.recorded",
|
|
13
|
+
"reconciliation.uncertainty_cleared",
|
|
14
|
+
];
|
|
15
|
+
export const RUN_LEGALITY_TABLE = [
|
|
16
|
+
{ from: "open", to: "verifying", guards: [] },
|
|
17
|
+
{ from: "open", to: "blocked", guards: [] },
|
|
18
|
+
{ from: "open", to: "cancel-requested", guards: ["cancellation.requested"] },
|
|
19
|
+
{ from: "open", to: "ambiguous", guards: [] },
|
|
20
|
+
{ from: "open", to: "needs-attention", guards: [] },
|
|
21
|
+
{ from: "verifying", to: "open", guards: [] },
|
|
22
|
+
{ from: "verifying", to: "blocked", guards: [] },
|
|
23
|
+
{ from: "verifying", to: "done", guards: DONE_GUARDS },
|
|
24
|
+
{ from: "verifying", to: "cancel-requested", guards: ["cancellation.requested"] },
|
|
25
|
+
{ from: "verifying", to: "ambiguous", guards: [] },
|
|
26
|
+
{ from: "verifying", to: "needs-attention", guards: [] },
|
|
27
|
+
{ from: "blocked", to: "open", guards: ["input.delivered"] },
|
|
28
|
+
{ from: "blocked", to: "cancel-requested", guards: ["cancellation.requested"] },
|
|
29
|
+
{ from: "blocked", to: "ambiguous", guards: [] },
|
|
30
|
+
{ from: "blocked", to: "needs-attention", guards: [] },
|
|
31
|
+
{ from: "cancel-requested", to: "cancelled", guards: ["cancellation.settled", "workers.none_uncertain"] },
|
|
32
|
+
{ from: "cancel-requested", to: "ambiguous", guards: [] },
|
|
33
|
+
{ from: "cancel-requested", to: "needs-attention", guards: [] },
|
|
34
|
+
{ from: "ambiguous", to: "open", guards: RECONCILED },
|
|
35
|
+
{ from: "ambiguous", to: "verifying", guards: RECONCILED },
|
|
36
|
+
{ from: "ambiguous", to: "blocked", guards: RECONCILED },
|
|
37
|
+
{ from: "ambiguous", to: "cancel-requested", guards: [...RECONCILED, "cancellation.requested"] },
|
|
38
|
+
{ from: "ambiguous", to: "cancelled", guards: [...RECONCILED, "cancellation.settled"] },
|
|
39
|
+
{ from: "ambiguous", to: "done", guards: [...RECONCILED, ...DONE_GUARDS] },
|
|
40
|
+
{ from: "ambiguous", to: "needs-attention", guards: RECONCILED },
|
|
41
|
+
{ from: "needs-attention", to: "open", guards: ["attention.cleared", "workers.none_detached"] },
|
|
42
|
+
{ from: "needs-attention", to: "verifying", guards: ["attention.cleared", "workers.none_detached"] },
|
|
43
|
+
{ from: "needs-attention", to: "blocked", guards: ["attention.cleared"] },
|
|
44
|
+
{ from: "needs-attention", to: "cancel-requested", guards: ["cancellation.requested"] },
|
|
45
|
+
{ from: "needs-attention", to: "ambiguous", guards: [] },
|
|
46
|
+
];
|
|
47
|
+
export function evaluateRunTransition(from, to, facts) {
|
|
48
|
+
const rule = RUN_LEGALITY_TABLE.find((candidate) => candidate.from === from && candidate.to === to);
|
|
49
|
+
if (!rule)
|
|
50
|
+
return { allowed: false, reason: "undeclared-transition", blockers: [] };
|
|
51
|
+
const blockers = rule.guards.filter((guard) => !guardSatisfied(guard, facts));
|
|
52
|
+
return blockers.length === 0 ? { allowed: true } : { allowed: false, reason: "guard-failed", blockers };
|
|
53
|
+
}
|
|
54
|
+
function guardSatisfied(guard, facts) {
|
|
55
|
+
switch (guard) {
|
|
56
|
+
case "objective.evidence.complete": return facts.objective.evidenceComplete;
|
|
57
|
+
case "objective.verifier.passed": return facts.objective.verifierPassed;
|
|
58
|
+
case "objective.prerequisites.complete": return facts.objective.prerequisitesComplete;
|
|
59
|
+
case "workers.none_active": return !facts.workers.active;
|
|
60
|
+
case "workers.none_uncertain": return !facts.workers.uncertain;
|
|
61
|
+
case "workers.none_detached": return !facts.workers.detached;
|
|
62
|
+
case "cancellation.requested": return facts.cancellation.requested;
|
|
63
|
+
case "cancellation.settled": return facts.cancellation.settled;
|
|
64
|
+
case "input.delivered": return facts.input.delivered;
|
|
65
|
+
case "reconciliation.recorded": return facts.reconciliation.recorded;
|
|
66
|
+
case "reconciliation.uncertainty_cleared": return facts.reconciliation.uncertaintyCleared;
|
|
67
|
+
case "attention.cleared": return facts.attention.cleared;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=run-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-gate.js","sourceRoot":"","sources":["../../workflow/run-gate.ts"],"names":[],"mappings":"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"}
|