intentdna 1.9.0 → 1.9.3
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +227 -87
- package/dist/cli/commands/run-lifecycle.d.ts +61 -11
- package/dist/cli/commands/run-lifecycle.js +184 -50
- package/dist/cli/commands/run-observer.d.ts +15 -0
- package/dist/cli/commands/run-observer.js +210 -0
- package/dist/cli/commands/run.d.ts +16 -20
- package/dist/cli/commands/run.js +461 -659
- package/dist/cli/commands/sync.js +16 -12
- package/dist/cli/index.js +14 -5
- package/dist/compiler/compile.d.ts +1 -0
- package/dist/compiler/compile.js +1 -1
- package/dist/compiler/controller.d.ts +16 -0
- package/dist/compiler/controller.js +693 -0
- package/dist/compiler/input-resolver.d.ts +2 -0
- package/dist/compiler/input-resolver.js +22 -6
- package/dist/hooks/cli.d.ts +45 -0
- package/dist/hooks/cli.js +263 -31
- package/dist/hooks/host-event.d.ts +57 -0
- package/dist/hooks/host-event.js +187 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/protocol.d.ts +7 -0
- package/dist/hooks/schema.d.ts +1 -0
- package/dist/hooks/schema.js +89 -1
- package/dist/hooks/state.d.ts +23 -1
- package/dist/hooks/state.js +9 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/tools-run.d.ts +4 -0
- package/dist/mcp/tools-run.js +419 -0
- package/dist/mcp/tools-state.d.ts +1 -1
- package/dist/mcp/tools-state.js +13 -241
- package/dist/runtime/artifact-store.d.ts +146 -0
- package/dist/runtime/artifact-store.js +1436 -0
- package/dist/runtime/canonical-attempt-outcome.d.ts +12 -0
- package/dist/runtime/canonical-attempt-outcome.js +195 -0
- package/dist/runtime/canonical-json.d.ts +10 -0
- package/dist/runtime/canonical-json.js +105 -0
- package/dist/runtime/canonical-run-application.d.ts +93 -0
- package/dist/runtime/canonical-run-application.js +229 -0
- package/dist/runtime/canonical-run-service.d.ts +454 -0
- package/dist/runtime/canonical-run-service.js +4760 -0
- package/dist/runtime/canonical-runtime-composition.d.ts +22 -0
- package/dist/runtime/canonical-runtime-composition.js +34 -0
- package/dist/runtime/canonical-runtime-projection.d.ts +3 -0
- package/dist/runtime/canonical-runtime-projection.js +4 -0
- package/dist/runtime/canonical-target-compiler.d.ts +46 -0
- package/dist/runtime/canonical-target-compiler.js +514 -0
- package/dist/runtime/claude-agent-identity.d.ts +2 -0
- package/dist/runtime/claude-agent-identity.js +21 -0
- package/dist/runtime/executable-run-plan.d.ts +328 -0
- package/dist/runtime/executable-run-plan.js +1485 -0
- package/dist/runtime/execution-authority.d.ts +83 -0
- package/dist/runtime/execution-authority.js +98 -0
- package/dist/runtime/handoff-resolver.js +4 -1
- package/dist/runtime/harness-pull-adapter.d.ts +146 -0
- package/dist/runtime/harness-pull-adapter.js +315 -0
- package/dist/runtime/index.d.ts +39 -14
- package/dist/runtime/index.js +29 -7
- package/dist/runtime/local-execution-authority.d.ts +194 -0
- package/dist/runtime/local-execution-authority.js +2897 -0
- package/dist/runtime/local-execution-reconciliation.d.ts +20 -0
- package/dist/runtime/local-execution-reconciliation.js +107 -0
- package/dist/runtime/local-execution-supervisor-script.d.ts +7 -0
- package/dist/runtime/local-execution-supervisor-script.js +793 -0
- package/dist/runtime/local-provider-sandbox.d.ts +42 -0
- package/dist/runtime/local-provider-sandbox.js +154 -0
- package/dist/runtime/local-verifier-execution.d.ts +24 -0
- package/dist/runtime/local-verifier-execution.js +290 -0
- package/dist/runtime/local-windows-execution-supervisor-script.d.ts +6 -0
- package/dist/runtime/local-windows-execution-supervisor-script.js +788 -0
- package/dist/runtime/plan-store.d.ts +30 -0
- package/dist/runtime/plan-store.js +231 -0
- package/dist/runtime/process-tree.d.ts +9 -0
- package/dist/runtime/process-tree.js +97 -24
- package/dist/runtime/providers/codex.js +2 -2
- package/dist/runtime/push-driver.d.ts +184 -0
- package/dist/runtime/push-driver.js +1002 -0
- package/dist/runtime/result-store.d.ts +34 -3
- package/dist/runtime/result-store.js +1073 -2
- package/dist/runtime/run-binding.d.ts +68 -0
- package/dist/runtime/run-binding.js +278 -0
- package/dist/runtime/run-contracts.d.ts +575 -0
- package/dist/runtime/run-contracts.js +58 -7
- package/dist/runtime/run-controller.d.ts +1 -6
- package/dist/runtime/run-controller.js +0 -41
- package/dist/runtime/run-store.d.ts +85 -7
- package/dist/runtime/run-store.js +2528 -186
- package/dist/runtime/skill-adapter.d.ts +18 -7
- package/dist/runtime/skill-adapter.js +100 -742
- package/dist/runtime/structured-output-validator.d.ts +44 -0
- package/dist/runtime/structured-output-validator.js +171 -0
- package/dist/runtime/verifier-command-binding.d.ts +22 -0
- package/dist/runtime/verifier-command-binding.js +162 -0
- package/dist/runtime/verifier.d.ts +46 -6
- package/dist/runtime/verifier.js +355 -53
- package/dist/runtime/windows-job-keeper.d.ts +47 -0
- package/dist/runtime/windows-job-keeper.js +231 -0
- package/dist/runtime/worker-executor.d.ts +17 -1
- package/dist/runtime/worker-executor.js +26 -5
- package/dist/runtime/workflow-plan-adapter.d.ts +19 -0
- package/dist/runtime/workflow-plan-adapter.js +502 -6
- package/dist/runtime/workflow-runtime-manifest.d.ts +1 -0
- package/dist/runtime/workflow-runtime-manifest.js +5 -0
- package/dist/runtime/workspace-isolation.d.ts +29 -2
- package/dist/runtime/workspace-isolation.js +488 -11
- package/dist/runtime/workspace-observation.d.ts +44 -0
- package/dist/runtime/workspace-observation.js +216 -0
- package/dist/schema/controller-registry.d.ts +0 -7
- package/dist/schema/controller-registry.js +0 -8
- package/dist/schema/types.d.ts +84 -10
- package/dist/schema/types.js +2 -0
- package/dist/schema/validate.js +151 -1
- package/dist/schema/validators/controllers.d.ts +1 -1
- package/dist/schema/validators/controllers.js +126 -41
- package/dist/schema/workflow-authoring-contract.js +2 -0
- package/dist/schema/yaml-parser.js +1 -1
- package/dist/templates/flutter-rewrite-new.dna.yaml +1 -0
- package/dist/templates/flutter-rewrite.dna.yaml +87 -60
- package/dist/templates/safe-refactoring.dna.yaml +1 -0
- package/native/windows-job-keeper/README.md +80 -0
- package/native/windows-job-keeper/bin/aarch64/intentdna-windows-job-keeper.exe +0 -0
- package/native/windows-job-keeper/bin/x86_64/intentdna-windows-job-keeper.exe +0 -0
- package/native/windows-job-keeper/keeper.c +979 -0
- package/native/windows-job-keeper/manifest.json +33 -0
- package/package.json +6 -2
- package/scripts/build-windows-job-keeper.mjs +172 -0
- package/scripts/verify-windows-job-keeper.mjs +184 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { resolvePostCheckCommand } from "../compiler/compile.js";
|
|
2
|
+
import { EXECUTABLE_RUN_PLAN_SCHEMA_VERSION, deriveWorkerRuntimeInputNames, parseExecutableRunPlanPayload, } from "./executable-run-plan.js";
|
|
1
3
|
const DEFAULT_RETRYABLE_OUTCOMES = [
|
|
2
4
|
"non_zero_exit",
|
|
3
5
|
"malformed_result",
|
|
@@ -114,15 +116,20 @@ function collectConstraints(step, role, variables) {
|
|
|
114
116
|
for (const checkpoint of step.checkpoints ?? []) {
|
|
115
117
|
constraints.push(checkpointText(checkpoint, variables));
|
|
116
118
|
}
|
|
117
|
-
|
|
119
|
+
const bindings = Object.entries(step.canonical_handoff_path_bindings ?? {});
|
|
120
|
+
return constraints.map((constraint) => bindings.reduce((rendered, [path, replacement]) => rendered.replaceAll(path, replacement), constraint));
|
|
118
121
|
}
|
|
119
122
|
function createOutputContract(step, variables) {
|
|
120
123
|
const outputs = (step.handoff?.produces ?? []).map((artifact) => ({
|
|
121
124
|
name: artifactIdentity(artifact, variables, step.id),
|
|
122
125
|
kind: outputKind(artifact.type),
|
|
126
|
+
artifact_kind: artifact.type,
|
|
123
127
|
required: artifact.required !== false,
|
|
124
128
|
description: substitute(artifact.description, variables),
|
|
125
|
-
|
|
129
|
+
relative_path_template: artifact.path === undefined
|
|
130
|
+
? null
|
|
131
|
+
: substitute(artifact.path, variables),
|
|
132
|
+
schema_ref: artifact.schema_ref ?? null,
|
|
126
133
|
}));
|
|
127
134
|
const names = new Set();
|
|
128
135
|
for (const output of outputs) {
|
|
@@ -133,6 +140,34 @@ function createOutputContract(step, variables) {
|
|
|
133
140
|
}
|
|
134
141
|
return outputs;
|
|
135
142
|
}
|
|
143
|
+
function createHandoffInputContract(step, variables) {
|
|
144
|
+
return (step.handoff?.consumes ?? []).map((artifact) => ({
|
|
145
|
+
name: artifactIdentity(artifact, variables, step.id),
|
|
146
|
+
source: artifact.from ? "handoff" : "external",
|
|
147
|
+
mode: handoffMode(artifact.type),
|
|
148
|
+
artifact_kind: artifact.type,
|
|
149
|
+
required: artifact.required !== false,
|
|
150
|
+
description: substitute(artifact.description, variables),
|
|
151
|
+
relative_path_template: artifact.path === undefined
|
|
152
|
+
? null
|
|
153
|
+
: substitute(artifact.path, variables),
|
|
154
|
+
schema_ref: artifact.schema_ref ?? null,
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
157
|
+
function workerResponseContract(role) {
|
|
158
|
+
if (role.output_schema === undefined)
|
|
159
|
+
return { kind: "none" };
|
|
160
|
+
if (typeof role.output_schema === "string") {
|
|
161
|
+
return { kind: "named", schema_ref: role.output_schema };
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
kind: "document",
|
|
165
|
+
relative_path_template: role.output_schema.path ?? null,
|
|
166
|
+
required_sections: role.output_schema.required_sections ?? [],
|
|
167
|
+
format: (role.output_schema.format ?? null),
|
|
168
|
+
converter_command: role.output_schema.converter ?? null,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
136
171
|
function findSourceOutput(sourceStep, outputName, variables) {
|
|
137
172
|
const matches = (sourceStep.handoff?.produces ?? []).filter((artifact) => artifactIdentity(artifact, variables, sourceStep.id) === outputName);
|
|
138
173
|
if (matches.length !== 1) {
|
|
@@ -155,8 +190,8 @@ function createHandoffs(step, stepById, variables) {
|
|
|
155
190
|
const inputName = artifactIdentity(artifact, variables, step.id);
|
|
156
191
|
const sourceArtifact = findSourceOutput(sourceStep, inputName, variables);
|
|
157
192
|
const mode = handoffMode(artifact.type);
|
|
158
|
-
if (
|
|
159
|
-
throw new WorkflowPlanAdapterError("invalid_handoff", `handoff '${inputName}' changes
|
|
193
|
+
if (sourceArtifact.type !== artifact.type) {
|
|
194
|
+
throw new WorkflowPlanAdapterError("invalid_handoff", `handoff '${inputName}' changes artifact kind between '${sourceStep.id}' and '${step.id}'`, step.id);
|
|
160
195
|
}
|
|
161
196
|
const base = {
|
|
162
197
|
binding_id: `${step.id}:${inputName}`,
|
|
@@ -172,10 +207,14 @@ function createHandoffs(step, stepById, variables) {
|
|
|
172
207
|
declarations.push({ ...base, mode, selection: null });
|
|
173
208
|
}
|
|
174
209
|
else if (mode === "structured") {
|
|
175
|
-
declarations.push({ ...base, mode, schema_ref: null });
|
|
210
|
+
declarations.push({ ...base, mode, schema_ref: artifact.schema_ref ?? null });
|
|
176
211
|
}
|
|
177
212
|
else {
|
|
178
|
-
declarations.push({
|
|
213
|
+
declarations.push({
|
|
214
|
+
...base,
|
|
215
|
+
mode,
|
|
216
|
+
artifact_kind: artifact.type,
|
|
217
|
+
});
|
|
179
218
|
}
|
|
180
219
|
}
|
|
181
220
|
const bindingIds = new Set();
|
|
@@ -225,6 +264,7 @@ function renderBinding(binding) {
|
|
|
225
264
|
prefix,
|
|
226
265
|
` Reference kind: ${binding.reference.kind}`,
|
|
227
266
|
` Reference value: ${binding.reference.value}`,
|
|
267
|
+
` Artifact id: ${binding.reference.artifact_id ?? "legacy-unavailable"}`,
|
|
228
268
|
];
|
|
229
269
|
}
|
|
230
270
|
if (binding.mode === "quote") {
|
|
@@ -434,7 +474,10 @@ export function adaptWorkflowPlan(plan, options) {
|
|
|
434
474
|
constraints: collectConstraints(step, role, variables),
|
|
435
475
|
handoffs,
|
|
436
476
|
external_inputs,
|
|
477
|
+
handoff_inputs: createHandoffInputContract(step, variables),
|
|
478
|
+
runtime_input_names: [],
|
|
437
479
|
outputs: createOutputContract(step, variables),
|
|
480
|
+
response_contract: workerResponseContract(role),
|
|
438
481
|
isolation: isolationForStep(plan.parallel_groups, step.id),
|
|
439
482
|
retry: retryPolicy(plan, step, options, workflowLoop !== null),
|
|
440
483
|
};
|
|
@@ -481,3 +524,456 @@ export function adaptWorkflowPlan(plan, options) {
|
|
|
481
524
|
},
|
|
482
525
|
}));
|
|
483
526
|
}
|
|
527
|
+
const EXECUTABLE_WORKFLOW_RETRY_SEGMENT_ID = "retry:workflow";
|
|
528
|
+
const SUCCEEDED_TERMINAL_NODE_ID = "terminal:succeeded";
|
|
529
|
+
const FAILED_TERMINAL_NODE_ID = "terminal:failed";
|
|
530
|
+
const CANCELLED_TERMINAL_NODE_ID = "terminal:cancelled";
|
|
531
|
+
function workerNodeId(stepId) {
|
|
532
|
+
return `worker:${stepId}`;
|
|
533
|
+
}
|
|
534
|
+
function gateNodeId(stepId) {
|
|
535
|
+
return `gate:${stepId}`;
|
|
536
|
+
}
|
|
537
|
+
function gatePassRouteId(stepId) {
|
|
538
|
+
return `route:gate:${stepId}:pass`;
|
|
539
|
+
}
|
|
540
|
+
function gateFailRouteId(stepId) {
|
|
541
|
+
return `route:gate:${stepId}:fail`;
|
|
542
|
+
}
|
|
543
|
+
function completionVerifier(stepId, completion, index) {
|
|
544
|
+
const verifier_id = `verifier:${stepId}:completion:${index}`;
|
|
545
|
+
if (completion.file_exists !== undefined) {
|
|
546
|
+
return {
|
|
547
|
+
verifier_id,
|
|
548
|
+
subject_node_id: workerNodeId(stepId),
|
|
549
|
+
kind: "artifact_exists",
|
|
550
|
+
relative_path_template: completion.file_exists,
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
if (completion.file_not_empty !== undefined) {
|
|
554
|
+
return {
|
|
555
|
+
verifier_id,
|
|
556
|
+
subject_node_id: workerNodeId(stepId),
|
|
557
|
+
kind: "artifact_non_empty",
|
|
558
|
+
relative_path_template: completion.file_not_empty,
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
if (completion.file_contains !== undefined) {
|
|
562
|
+
return {
|
|
563
|
+
verifier_id,
|
|
564
|
+
subject_node_id: workerNodeId(stepId),
|
|
565
|
+
kind: "artifact_contains",
|
|
566
|
+
relative_path_template: completion.file_contains.path,
|
|
567
|
+
pattern: completion.file_contains.pattern,
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
if (completion.evaluator_result !== undefined) {
|
|
571
|
+
return {
|
|
572
|
+
verifier_id,
|
|
573
|
+
subject_node_id: workerNodeId(stepId),
|
|
574
|
+
kind: "evaluator_result",
|
|
575
|
+
relative_path_template: completion.evaluator_result.path,
|
|
576
|
+
require_score: completion.evaluator_result.require_score === true,
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
return {
|
|
580
|
+
verifier_id,
|
|
581
|
+
subject_node_id: workerNodeId(stepId),
|
|
582
|
+
kind: "command",
|
|
583
|
+
command: completion.command_success ?? "",
|
|
584
|
+
relative_working_directory: ".",
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
function checkpointVerifier(stepId, checkpoint, index) {
|
|
588
|
+
return {
|
|
589
|
+
verifier_id: `verifier:${stepId}:checkpoint:${index}`,
|
|
590
|
+
subject_node_id: workerNodeId(stepId),
|
|
591
|
+
kind: "checkpoint",
|
|
592
|
+
assertion: checkpoint.assert,
|
|
593
|
+
command: checkpoint.command ?? null,
|
|
594
|
+
message: checkpoint.message,
|
|
595
|
+
action: checkpoint.action ?? "block",
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
function rolePostCheckVerifier(stepId, postCheck, index) {
|
|
599
|
+
return {
|
|
600
|
+
verifier_id: `verifier:${stepId}:post-check:${index}`,
|
|
601
|
+
subject_node_id: workerNodeId(stepId),
|
|
602
|
+
kind: "checkpoint",
|
|
603
|
+
assertion: `role_post_check_${index}`,
|
|
604
|
+
command: resolvePostCheckCommand(postCheck),
|
|
605
|
+
message: `Post-check failed: ${postCheck}`,
|
|
606
|
+
action: "warn",
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
function executableVerifiersForStep(step, role) {
|
|
610
|
+
return [
|
|
611
|
+
...(step.completion ?? []).map((completion, index) => (completionVerifier(step.id, completion, index))),
|
|
612
|
+
...(step.checkpoints ?? []).map((checkpoint, index) => (checkpointVerifier(step.id, checkpoint, index))),
|
|
613
|
+
...(role.post_checks ?? []).map((postCheck, index) => (rolePostCheckVerifier(step.id, postCheck, index))),
|
|
614
|
+
];
|
|
615
|
+
}
|
|
616
|
+
function renderExecutableHandoffInput(handoff) {
|
|
617
|
+
const prefix = `- ${handoff.input_name} (${handoff.mode}, ${handoff.required ? "required" : "optional"}): ${handoff.description}`;
|
|
618
|
+
if (handoff.mode === "reference") {
|
|
619
|
+
if (handoff.artifact_kind === "git_commit") {
|
|
620
|
+
return [
|
|
621
|
+
prefix,
|
|
622
|
+
` Commit id: {{handoff.${handoff.binding_id}.commit_oid}}`,
|
|
623
|
+
` Artifact id: {{handoff.${handoff.binding_id}.artifact_id}}`,
|
|
624
|
+
];
|
|
625
|
+
}
|
|
626
|
+
return [
|
|
627
|
+
prefix,
|
|
628
|
+
` Materialized path: {{handoff.${handoff.binding_id}.materialized_path}}`,
|
|
629
|
+
` Artifact id: {{handoff.${handoff.binding_id}.artifact_id}}`,
|
|
630
|
+
];
|
|
631
|
+
}
|
|
632
|
+
if (handoff.mode === "quote") {
|
|
633
|
+
return [prefix, ` Exact text: {{handoff.${handoff.binding_id}.exact_text}}`];
|
|
634
|
+
}
|
|
635
|
+
if (handoff.mode === "structured") {
|
|
636
|
+
return [prefix, ` JSON value: {{handoff.${handoff.binding_id}.json}}`];
|
|
637
|
+
}
|
|
638
|
+
return [prefix];
|
|
639
|
+
}
|
|
640
|
+
function renderResponseContract(contract) {
|
|
641
|
+
if (contract.kind === "none")
|
|
642
|
+
return [];
|
|
643
|
+
if (contract.kind === "named") {
|
|
644
|
+
return ["## Response Contract", `- Schema: ${contract.schema_ref}`, ""];
|
|
645
|
+
}
|
|
646
|
+
const lines = ["## Response Contract"];
|
|
647
|
+
if (contract.relative_path_template !== null) {
|
|
648
|
+
lines.push(`- Output path: ${contract.relative_path_template}`);
|
|
649
|
+
}
|
|
650
|
+
if (contract.format !== null)
|
|
651
|
+
lines.push(`- Final format: ${contract.format}`);
|
|
652
|
+
for (const section of contract.required_sections) {
|
|
653
|
+
lines.push(`- Required section: ## ${section}`);
|
|
654
|
+
}
|
|
655
|
+
return [...lines, ""];
|
|
656
|
+
}
|
|
657
|
+
function executableStandalonePrompt(plan, adapted) {
|
|
658
|
+
const { step, role, constraints, handoffs, external_inputs: externalInputs, outputs } = adapted;
|
|
659
|
+
const lines = [
|
|
660
|
+
`# ${plan.name}: ${step.id}`,
|
|
661
|
+
"",
|
|
662
|
+
"You are executing one standalone workflow Step in an independent session.",
|
|
663
|
+
"Use only the task, constraints, and declared inputs below. Do not rely on or request previous conversation history.",
|
|
664
|
+
"Complete only this Step and stop after returning its declared result.",
|
|
665
|
+
"",
|
|
666
|
+
"## Role",
|
|
667
|
+
`${step.role}: ${role.description}`,
|
|
668
|
+
"",
|
|
669
|
+
"## Task",
|
|
670
|
+
step.prompt ?? step.description,
|
|
671
|
+
"",
|
|
672
|
+
"## Constraints",
|
|
673
|
+
...(constraints.length > 0
|
|
674
|
+
? constraints.map((constraint) => `- ${constraint}`)
|
|
675
|
+
: ["- No additional current-Step constraints are declared."]),
|
|
676
|
+
"",
|
|
677
|
+
"## Inputs",
|
|
678
|
+
];
|
|
679
|
+
if (handoffs.length === 0 && externalInputs.length === 0) {
|
|
680
|
+
lines.push("- None. This Step has no declared upstream delivery.");
|
|
681
|
+
}
|
|
682
|
+
else {
|
|
683
|
+
for (const handoff of handoffs)
|
|
684
|
+
lines.push(...renderExecutableHandoffInput(handoff));
|
|
685
|
+
for (const artifact of externalInputs) {
|
|
686
|
+
lines.push(...renderExternalInput(artifact, {}, step.id));
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
lines.push("", "## Outputs", ...renderOutputProtocol(outputs), "", ...renderResponseContract(adapted.response_contract));
|
|
690
|
+
if (role.success_criteria?.length) {
|
|
691
|
+
lines.push("## Success Criteria", ...role.success_criteria.map((criterion) => `- ${criterion}`), "");
|
|
692
|
+
}
|
|
693
|
+
if (role.failure_modes?.length) {
|
|
694
|
+
lines.push("## Failure Modes To Avoid", ...role.failure_modes.map((failure) => `- ${failure}`), "");
|
|
695
|
+
}
|
|
696
|
+
return lines.join("\n");
|
|
697
|
+
}
|
|
698
|
+
function executableHandoffs(adapted) {
|
|
699
|
+
return adapted.flatMap((entry) => entry.handoffs.flatMap((handoff) => {
|
|
700
|
+
if (handoff.mode === "none")
|
|
701
|
+
return [];
|
|
702
|
+
const input = entry.handoff_inputs.find((candidate) => candidate.name === handoff.input_name);
|
|
703
|
+
if (!input || input.source !== "handoff") {
|
|
704
|
+
throw new WorkflowPlanAdapterError("invalid_handoff", `step '${entry.step.id}' is missing typed input '${handoff.input_name}'`, entry.step.id);
|
|
705
|
+
}
|
|
706
|
+
return [{
|
|
707
|
+
handoff_id: handoff.binding_id,
|
|
708
|
+
from_node_id: workerNodeId(handoff.source.step_id),
|
|
709
|
+
output_name: handoff.source.output_name,
|
|
710
|
+
to_node_id: workerNodeId(entry.step.id),
|
|
711
|
+
input_name: handoff.input_name,
|
|
712
|
+
mode: handoff.mode,
|
|
713
|
+
artifact_kind: input.artifact_kind,
|
|
714
|
+
required: handoff.required,
|
|
715
|
+
schema_ref: handoff.mode === "structured" ? handoff.schema_ref : null,
|
|
716
|
+
}];
|
|
717
|
+
}));
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Compile a WorkflowPlan into the immutable, provider-neutral plan payload.
|
|
721
|
+
* The legacy closure-based adapter above remains unchanged until the S8 cutover.
|
|
722
|
+
*/
|
|
723
|
+
export function adaptWorkflowPlanToExecutableRunPlan(plan, options) {
|
|
724
|
+
if (!options.target_key) {
|
|
725
|
+
throw new WorkflowPlanAdapterError("invalid_plan", "target_key must be non-empty");
|
|
726
|
+
}
|
|
727
|
+
const cancellationGrace = options.cancellation_grace_ms ?? 5_000;
|
|
728
|
+
requireNonNegativeInteger(cancellationGrace, "cancellation_grace_ms");
|
|
729
|
+
if (options.timeout_ms !== undefined && options.timeout_ms !== null) {
|
|
730
|
+
requireNonNegativeInteger(options.timeout_ms, "timeout_ms");
|
|
731
|
+
}
|
|
732
|
+
const adapterOptions = {
|
|
733
|
+
roles: options.roles,
|
|
734
|
+
variables: {},
|
|
735
|
+
working_directory: ".",
|
|
736
|
+
timeout_ms: options.timeout_ms,
|
|
737
|
+
cancellation_grace_ms: cancellationGrace,
|
|
738
|
+
retry_initial_delay_ms: options.retry_initial_delay_ms,
|
|
739
|
+
retry_max_delay_ms: options.retry_max_delay_ms,
|
|
740
|
+
retryable_outcomes: options.retryable_outcomes,
|
|
741
|
+
};
|
|
742
|
+
const workflowLoop = validatePlanRouting(plan, adapterOptions);
|
|
743
|
+
for (const step of plan.steps) {
|
|
744
|
+
if (workflowLoop === null && step.run_if !== null) {
|
|
745
|
+
throw new WorkflowPlanAdapterError("unsupported_routing", `step '${step.id}' uses run_if without a typed retry segment`, step.id);
|
|
746
|
+
}
|
|
747
|
+
if (step.blocked_items_path !== undefined) {
|
|
748
|
+
throw new WorkflowPlanAdapterError("unsupported_routing", `step '${step.id}' uses failure routing not represented by the executable plan`, step.id);
|
|
749
|
+
}
|
|
750
|
+
if (step.on_fail === "retry_with_feedback"
|
|
751
|
+
&& (step.max_attempts === undefined || step.max_attempts < 2)) {
|
|
752
|
+
throw new WorkflowPlanAdapterError("invalid_plan", `step '${step.id}' retry_with_feedback requires max_attempts of at least 2`, step.id);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
const stepById = new Map(plan.steps.map((step) => [step.id, step]));
|
|
756
|
+
const adapted = plan.steps.map((step) => {
|
|
757
|
+
const role = options.roles[step.role];
|
|
758
|
+
if (!role) {
|
|
759
|
+
throw new WorkflowPlanAdapterError("missing_role", `step '${step.id}' references missing role '${step.role}'`, step.id);
|
|
760
|
+
}
|
|
761
|
+
const { handoffs, external_inputs } = createHandoffs(step, stepById, {});
|
|
762
|
+
return {
|
|
763
|
+
step,
|
|
764
|
+
role,
|
|
765
|
+
constraints: [
|
|
766
|
+
...(options.global_constraints ?? []),
|
|
767
|
+
...collectConstraints(step, role, {}),
|
|
768
|
+
],
|
|
769
|
+
handoffs,
|
|
770
|
+
external_inputs,
|
|
771
|
+
handoff_inputs: createHandoffInputContract(step, {}),
|
|
772
|
+
runtime_input_names: [],
|
|
773
|
+
outputs: createOutputContract(step, {}),
|
|
774
|
+
response_contract: workerResponseContract(role),
|
|
775
|
+
isolation: isolationForStep(plan.parallel_groups, step.id),
|
|
776
|
+
retry: retryPolicy(plan, step, adapterOptions, workflowLoop !== null),
|
|
777
|
+
};
|
|
778
|
+
});
|
|
779
|
+
const verifiersByStep = new Map(adapted.map((entry) => [
|
|
780
|
+
entry.step.id,
|
|
781
|
+
executableVerifiersForStep(entry.step, entry.role),
|
|
782
|
+
]));
|
|
783
|
+
const handoffPlan = executableHandoffs(adapted);
|
|
784
|
+
const effectiveNodeId = (stepId) => ((verifiersByStep.get(stepId)?.length ?? 0) > 0
|
|
785
|
+
? gateNodeId(stepId)
|
|
786
|
+
: workerNodeId(stepId));
|
|
787
|
+
const dependenciesByStep = new Map(adapted.map((entry) => [
|
|
788
|
+
entry.step.id,
|
|
789
|
+
addHandoffDependencies(entry.step, entry.handoffs).map(effectiveNodeId),
|
|
790
|
+
]));
|
|
791
|
+
const dependentSteps = new Map();
|
|
792
|
+
for (const entry of adapted) {
|
|
793
|
+
for (const dependency of addHandoffDependencies(entry.step, entry.handoffs)) {
|
|
794
|
+
const dependents = dependentSteps.get(dependency) ?? [];
|
|
795
|
+
dependents.push(entry.step.id);
|
|
796
|
+
dependentSteps.set(dependency, dependents);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
const workerNodes = adapted.map((entry) => {
|
|
800
|
+
const worker = {
|
|
801
|
+
kind: "worker",
|
|
802
|
+
node_id: workerNodeId(entry.step.id),
|
|
803
|
+
depends_on: dependenciesByStep.get(entry.step.id) ?? [],
|
|
804
|
+
role: entry.step.role,
|
|
805
|
+
packet_template: {
|
|
806
|
+
standalone_prompt: executableStandalonePrompt(plan, entry),
|
|
807
|
+
constraints: entry.constraints,
|
|
808
|
+
runtime_input_names: [],
|
|
809
|
+
handoff_inputs: entry.handoff_inputs,
|
|
810
|
+
output_contract: entry.outputs,
|
|
811
|
+
response_contract: entry.response_contract,
|
|
812
|
+
},
|
|
813
|
+
workspace: {
|
|
814
|
+
isolation: entry.isolation,
|
|
815
|
+
relative_working_directory: ".",
|
|
816
|
+
read_only: entry.step.enforce?.read_only === true,
|
|
817
|
+
readable_path_templates: entry.role.scope?.read ?? ["**/*"],
|
|
818
|
+
writable_path_templates: entry.step.enforce?.read_only === true
|
|
819
|
+
? []
|
|
820
|
+
: [
|
|
821
|
+
...(entry.role.scope?.write ?? []),
|
|
822
|
+
...(entry.step.enforce?.additional_write_paths ?? []),
|
|
823
|
+
],
|
|
824
|
+
scope_relaxation: entry.step.enforce?.relax_after_iteration === undefined
|
|
825
|
+
? null
|
|
826
|
+
: {
|
|
827
|
+
from_iteration: entry.step.enforce.relax_after_iteration,
|
|
828
|
+
effect: "disable_path_scope",
|
|
829
|
+
},
|
|
830
|
+
},
|
|
831
|
+
tool_policy: {
|
|
832
|
+
allow: entry.role.tool_permissions?.allow ?? null,
|
|
833
|
+
deny: entry.role.tool_permissions?.deny ?? [],
|
|
834
|
+
},
|
|
835
|
+
attempt_policy: {
|
|
836
|
+
timeout_ms: options.timeout_ms ?? null,
|
|
837
|
+
cancellation_grace_ms: cancellationGrace,
|
|
838
|
+
max_attempts: entry.retry.max_attempts,
|
|
839
|
+
backoff: entry.retry.backoff,
|
|
840
|
+
initial_delay_ms: entry.retry.initial_delay_ms,
|
|
841
|
+
max_delay_ms: entry.retry.max_delay_ms,
|
|
842
|
+
retryable_outcomes: entry.retry.retryable_outcomes.filter((outcome) => outcome !== "success"),
|
|
843
|
+
retry_segment_id: workflowLoop?.step_ids.includes(entry.step.id)
|
|
844
|
+
? EXECUTABLE_WORKFLOW_RETRY_SEGMENT_ID
|
|
845
|
+
: null,
|
|
846
|
+
},
|
|
847
|
+
};
|
|
848
|
+
return {
|
|
849
|
+
...worker,
|
|
850
|
+
packet_template: {
|
|
851
|
+
...worker.packet_template,
|
|
852
|
+
runtime_input_names: deriveWorkerRuntimeInputNames(worker, verifiersByStep.get(entry.step.id) ?? [], handoffPlan),
|
|
853
|
+
},
|
|
854
|
+
};
|
|
855
|
+
});
|
|
856
|
+
const routes = [];
|
|
857
|
+
const gateNodes = adapted.flatMap((entry) => {
|
|
858
|
+
const verifiers = verifiersByStep.get(entry.step.id) ?? [];
|
|
859
|
+
if (verifiers.length === 0)
|
|
860
|
+
return [];
|
|
861
|
+
const passTargets = dependentSteps.get(entry.step.id)?.map(workerNodeId)
|
|
862
|
+
?? [SUCCEEDED_TERMINAL_NODE_ID];
|
|
863
|
+
routes.push(...passTargets.map((toNodeId, index) => ({
|
|
864
|
+
route_id: index === 0
|
|
865
|
+
? gatePassRouteId(entry.step.id)
|
|
866
|
+
: `${gatePassRouteId(entry.step.id)}:${index}`,
|
|
867
|
+
from_node_id: gateNodeId(entry.step.id),
|
|
868
|
+
to_node_id: toNodeId,
|
|
869
|
+
condition: {
|
|
870
|
+
kind: "gate",
|
|
871
|
+
gate_node_id: gateNodeId(entry.step.id),
|
|
872
|
+
outcome: "pass",
|
|
873
|
+
},
|
|
874
|
+
})), {
|
|
875
|
+
route_id: gateFailRouteId(entry.step.id),
|
|
876
|
+
from_node_id: gateNodeId(entry.step.id),
|
|
877
|
+
to_node_id: FAILED_TERMINAL_NODE_ID,
|
|
878
|
+
condition: {
|
|
879
|
+
kind: "gate",
|
|
880
|
+
gate_node_id: gateNodeId(entry.step.id),
|
|
881
|
+
outcome: "fail",
|
|
882
|
+
},
|
|
883
|
+
});
|
|
884
|
+
return [{
|
|
885
|
+
kind: "gate",
|
|
886
|
+
node_id: gateNodeId(entry.step.id),
|
|
887
|
+
depends_on: [workerNodeId(entry.step.id)],
|
|
888
|
+
verifier_ids: verifiers.map((verifier) => verifier.verifier_id),
|
|
889
|
+
pass_route_ids: passTargets.map((_target, index) => (index === 0
|
|
890
|
+
? gatePassRouteId(entry.step.id)
|
|
891
|
+
: `${gatePassRouteId(entry.step.id)}:${index}`)),
|
|
892
|
+
fail_route_id: gateFailRouteId(entry.step.id),
|
|
893
|
+
}];
|
|
894
|
+
});
|
|
895
|
+
const leafNodeIds = adapted
|
|
896
|
+
.filter((entry) => (dependentSteps.get(entry.step.id)?.length ?? 0) === 0)
|
|
897
|
+
.map((entry) => effectiveNodeId(entry.step.id));
|
|
898
|
+
const retrySegments = workflowLoop === null ? [] : [{
|
|
899
|
+
retry_segment_id: EXECUTABLE_WORKFLOW_RETRY_SEGMENT_ID,
|
|
900
|
+
node_ids: workflowLoop.step_ids.flatMap((stepId) => [
|
|
901
|
+
workerNodeId(stepId),
|
|
902
|
+
...((verifiersByStep.get(stepId)?.length ?? 0) > 0 ? [gateNodeId(stepId)] : []),
|
|
903
|
+
]),
|
|
904
|
+
retry_from_node_id: workerNodeId(workflowLoop.retry_from),
|
|
905
|
+
max_rounds: workflowLoop.max_retries + 1,
|
|
906
|
+
backoff: workflowLoop.backoff,
|
|
907
|
+
initial_delay_ms: workflowLoop.initial_delay_ms,
|
|
908
|
+
max_delay_ms: workflowLoop.max_delay_ms,
|
|
909
|
+
retryable_outcomes: DEFAULT_RETRYABLE_OUTCOMES,
|
|
910
|
+
}];
|
|
911
|
+
const writablePaths = adapted.flatMap((entry) => (entry.step.enforce?.read_only === true
|
|
912
|
+
? []
|
|
913
|
+
: [
|
|
914
|
+
...(entry.role.scope?.write ?? []),
|
|
915
|
+
...(entry.step.enforce?.additional_write_paths ?? []),
|
|
916
|
+
]));
|
|
917
|
+
const readablePaths = adapted.flatMap((entry) => entry.role.scope?.read ?? ["**/*"]);
|
|
918
|
+
const allowNetwork = options.allow_network ?? true;
|
|
919
|
+
const payload = {
|
|
920
|
+
schema_version: EXECUTABLE_RUN_PLAN_SCHEMA_VERSION,
|
|
921
|
+
target: { kind: "workflow", key: options.target_key },
|
|
922
|
+
input_contract: {
|
|
923
|
+
...options.input_contract,
|
|
924
|
+
inputs: options.input_contract.inputs.filter((input) => workerNodes.some((worker) => worker.packet_template.runtime_input_names.includes(input.name))),
|
|
925
|
+
},
|
|
926
|
+
nodes: [
|
|
927
|
+
...workerNodes,
|
|
928
|
+
...gateNodes,
|
|
929
|
+
{
|
|
930
|
+
kind: "terminal",
|
|
931
|
+
node_id: SUCCEEDED_TERMINAL_NODE_ID,
|
|
932
|
+
depends_on: leafNodeIds,
|
|
933
|
+
terminal_id: "succeeded",
|
|
934
|
+
},
|
|
935
|
+
{
|
|
936
|
+
kind: "terminal",
|
|
937
|
+
node_id: FAILED_TERMINAL_NODE_ID,
|
|
938
|
+
depends_on: [],
|
|
939
|
+
terminal_id: "failed",
|
|
940
|
+
},
|
|
941
|
+
{
|
|
942
|
+
kind: "terminal",
|
|
943
|
+
node_id: CANCELLED_TERMINAL_NODE_ID,
|
|
944
|
+
depends_on: [],
|
|
945
|
+
terminal_id: "cancelled",
|
|
946
|
+
},
|
|
947
|
+
],
|
|
948
|
+
routes,
|
|
949
|
+
retry_segments: retrySegments,
|
|
950
|
+
terminals: [
|
|
951
|
+
{ terminal_id: "succeeded", status: "succeeded", reason_code: "workflow_completed" },
|
|
952
|
+
{ terminal_id: "failed", status: "failed", reason_code: "workflow_failed" },
|
|
953
|
+
{ terminal_id: "cancelled", status: "cancelled", reason_code: "run_cancelled" },
|
|
954
|
+
],
|
|
955
|
+
verifier_plan: [...verifiersByStep.values()].flat(),
|
|
956
|
+
handoff_plan: handoffPlan,
|
|
957
|
+
workspace_policy: {
|
|
958
|
+
default_isolation: adapted.some((entry) => entry.isolation === "worktree")
|
|
959
|
+
? "worktree"
|
|
960
|
+
: "none",
|
|
961
|
+
relative_workspace_root: ".",
|
|
962
|
+
allow_network: allowNetwork,
|
|
963
|
+
readable_path_templates: [...new Set(readablePaths)],
|
|
964
|
+
writable_path_templates: [...new Set(writablePaths)],
|
|
965
|
+
},
|
|
966
|
+
required_capabilities: {
|
|
967
|
+
worktree_isolation: adapted.some((entry) => entry.isolation === "worktree"),
|
|
968
|
+
parallelism: plan.parallel_groups.some((group) => group.step_ids.length > 1),
|
|
969
|
+
cancellation: false,
|
|
970
|
+
hook_identity: false,
|
|
971
|
+
caller_attestation: plan.steps.some((step) => step.canonical_requires_attested_independent_submit === true),
|
|
972
|
+
human_interaction: false,
|
|
973
|
+
direct_structured_submission: true,
|
|
974
|
+
network_policy_enforcement: !allowNetwork,
|
|
975
|
+
},
|
|
976
|
+
source_provenance: options.source_provenance,
|
|
977
|
+
};
|
|
978
|
+
return parseExecutableRunPlanPayload(payload);
|
|
979
|
+
}
|
|
@@ -39,6 +39,7 @@ export declare function createWorkflowRuntimeManifest(options: {
|
|
|
39
39
|
resolvedVariables: Record<string, string>;
|
|
40
40
|
workflowAsset?: string;
|
|
41
41
|
additionalTemplateVariableRefs?: string[];
|
|
42
|
+
runtimeInputRefs?: string[];
|
|
42
43
|
additionalRuntimeValues?: unknown;
|
|
43
44
|
}>;
|
|
44
45
|
compiledAt: string;
|
|
@@ -116,12 +116,16 @@ export function createWorkflowRuntimeManifest(options) {
|
|
|
116
116
|
.filter((name) => !WORKFLOW_RUNTIME_INPUT_VARIABLE_NAMES.has(name))
|
|
117
117
|
.filter((name) => Object.prototype.hasOwnProperty.call(planVariables, name))
|
|
118
118
|
.map((name) => [name, planVariables[name]]));
|
|
119
|
+
const explicitRuntimeInputRefs = item.runtimeInputRefs ?? [];
|
|
120
|
+
const explicitRuntimeInputs = new Set(explicitRuntimeInputRefs);
|
|
119
121
|
const undefinedVariableRefs = templateVariableRefs.filter((name) => !WORKFLOW_RUNTIME_INPUT_VARIABLE_NAMES.has(name) &&
|
|
122
|
+
!explicitRuntimeInputs.has(name) &&
|
|
120
123
|
!Object.prototype.hasOwnProperty.call(planVariables, name));
|
|
121
124
|
if (undefinedVariableRefs.length > 0) {
|
|
122
125
|
throw new Error(`Workflow ${workflow} references undefined template variable(s): ${undefinedVariableRefs.join(", ")}. Declare them in DNA variables or use $ARGUMENTS/task_id for runtime input.`);
|
|
123
126
|
}
|
|
124
127
|
const runtimeInputRefs = templateVariableRefs.filter((name) => WORKFLOW_RUNTIME_INPUT_VARIABLE_NAMES.has(name) ||
|
|
128
|
+
explicitRuntimeInputs.has(name) ||
|
|
125
129
|
!Object.prototype.hasOwnProperty.call(planVariables, name));
|
|
126
130
|
const requiresArguments = workflowUsesArguments(plan, planVariables) ||
|
|
127
131
|
valueUsesArguments(item.additionalRuntimeValues, planVariables) ||
|
|
@@ -132,6 +136,7 @@ export function createWorkflowRuntimeManifest(options) {
|
|
|
132
136
|
template_variable_refs: templateVariableRefs,
|
|
133
137
|
runtime_input_refs: [
|
|
134
138
|
...(requiresArguments ? ["ARGUMENTS"] : []),
|
|
139
|
+
...explicitRuntimeInputRefs,
|
|
135
140
|
...runtimeInputRefs.filter((name) => name !== "ARGUMENTS"),
|
|
136
141
|
].filter((name, index, names) => names.indexOf(name) === index).sort(),
|
|
137
142
|
requires_arguments: requiresArguments,
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
* commit, and leaves preservation or cleanup to an explicit Controller decision.
|
|
6
6
|
* Team naming, CLI parsing, generated shell, and automatic rollback are excluded.
|
|
7
7
|
*/
|
|
8
|
-
import type { AttemptId, RunId, StepId } from "./run-contracts.js";
|
|
8
|
+
import type { AttemptId, CanonicalWorkspaceAllocation, CanonicalWorkspacePlan, RunId, StepId } from "./run-contracts.js";
|
|
9
|
+
import type { AllocateAttemptWorkspaceRequest, AttemptWorkspaceAuthorityPort, CommittedWorkspaceAuthorityRequest, WorkspaceMutationAuthority } from "./canonical-run-service.js";
|
|
9
10
|
export type WorkspaceIsolation = "none" | "worktree";
|
|
10
|
-
export type WorkspaceIsolationErrorCode = "invalid_request" | "not_git_repository" | "git_command_failed" | "path_conflict" | "branch_conflict" | "workspace_mismatch" | "unsafe_cleanup_target";
|
|
11
|
+
export type WorkspaceIsolationErrorCode = "invalid_request" | "not_git_repository" | "git_command_failed" | "path_conflict" | "branch_conflict" | "workspace_mismatch" | "workspace_conflict" | "unsafe_cleanup_target";
|
|
11
12
|
export declare class WorkspaceIsolationError extends Error {
|
|
12
13
|
readonly code: WorkspaceIsolationErrorCode;
|
|
13
14
|
constructor(code: WorkspaceIsolationErrorCode, message: string);
|
|
@@ -95,8 +96,34 @@ export type WorkspaceLifecycleResult = {
|
|
|
95
96
|
readonly working_directory: string;
|
|
96
97
|
readonly branch_deleted: boolean;
|
|
97
98
|
};
|
|
99
|
+
/**
|
|
100
|
+
* Resolve an existing directory below a committed workspace without following
|
|
101
|
+
* symbolic-link components. This is suitable for verifier/process cwd values.
|
|
102
|
+
*/
|
|
103
|
+
export declare function canonicalWorkspaceDirectory(workspaceRoot: string, relativeDirectory: string, label?: string): Promise<string>;
|
|
98
104
|
export declare function planAttemptWorkspace(request: AttemptWorkspaceRequest): AttemptWorkspacePlan;
|
|
99
105
|
export declare function allocateAttemptWorkspace(plan: AttemptWorkspacePlan): AttemptWorkspaceAllocation;
|
|
106
|
+
export interface LocalAttemptWorkspaceAuthorityOptions {
|
|
107
|
+
readonly lock_root?: string;
|
|
108
|
+
readonly lock_wait_ms?: number;
|
|
109
|
+
readonly lock_stale_ms?: number;
|
|
110
|
+
readonly lock_retry_ms?: number;
|
|
111
|
+
readonly lock_heartbeat_ms?: number;
|
|
112
|
+
}
|
|
113
|
+
export declare class LocalAttemptWorkspaceAuthority implements AttemptWorkspaceAuthorityPort {
|
|
114
|
+
private readonly lockRoot;
|
|
115
|
+
private readonly lockWaitMs;
|
|
116
|
+
private readonly lockStaleMs;
|
|
117
|
+
private readonly lockRetryMs;
|
|
118
|
+
private readonly lockHeartbeatMs;
|
|
119
|
+
constructor(options?: LocalAttemptWorkspaceAuthorityOptions);
|
|
120
|
+
plan(request: AllocateAttemptWorkspaceRequest): Promise<CanonicalWorkspacePlan>;
|
|
121
|
+
ensureWithExclusiveAuthority<T>(plan: CanonicalWorkspacePlan, operation: (allocation: CanonicalWorkspaceAllocation) => Promise<T>): Promise<T>;
|
|
122
|
+
withExclusiveMutationAuthority<T>(request: CommittedWorkspaceAuthorityRequest, operation: (authority: WorkspaceMutationAuthority) => Promise<T>): Promise<T>;
|
|
123
|
+
private nextFencingEpoch;
|
|
124
|
+
private assertCommittedAllocation;
|
|
125
|
+
private withLock;
|
|
126
|
+
}
|
|
100
127
|
export declare function inspectAttemptWorkspace(workspace: AttemptWorkspaceAllocation): WorkspaceInspection;
|
|
101
128
|
export declare function applyWorkspaceLifecycleDecision(workspace: AttemptWorkspaceAllocation, decision: WorkspaceLifecycleDecision): WorkspaceLifecycleResult;
|
|
102
129
|
export declare function defaultWorktreeRoot(repositoryRoot: string): string;
|