@mcoda/codali 0.1.134 → 0.1.135-codali.4
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 +42 -0
- package/ORCHESTRATION.md +387 -0
- package/README.md +103 -1
- package/config/alternate-local.example.json +49 -0
- package/config/docdex-runtime.json +21 -0
- package/config/orchestration.schema.json +548 -0
- package/config/raijin-suku.example.json +172 -0
- package/config/terminal-long-scenarios.v1.json +70 -0
- package/dist/agents/RoleResolution.d.ts.map +1 -1
- package/dist/agents/RoleResolution.js +4 -4
- package/dist/api/CodaliApi.d.ts +16 -0
- package/dist/api/CodaliApi.d.ts.map +1 -1
- package/dist/api/CodaliApi.js +39 -10
- package/dist/cli/AskCommand.d.ts +3 -0
- package/dist/cli/AskCommand.d.ts.map +1 -1
- package/dist/cli/AskCommand.js +76 -13
- package/dist/cli/RunCommand.d.ts +4 -0
- package/dist/cli/RunCommand.d.ts.map +1 -1
- package/dist/cli/RunCommand.js +110 -24
- package/dist/cli/TerminalCommand.d.ts +35 -0
- package/dist/cli/TerminalCommand.d.ts.map +1 -0
- package/dist/cli/TerminalCommand.js +616 -0
- package/dist/cli/TerminalCredentials.d.ts +3 -0
- package/dist/cli/TerminalCredentials.d.ts.map +1 -0
- package/dist/cli/TerminalCredentials.js +89 -0
- package/dist/cli/TerminalInput.d.ts +24 -0
- package/dist/cli/TerminalInput.d.ts.map +1 -0
- package/dist/cli/TerminalInput.js +98 -0
- package/dist/cli/TerminalText.d.ts +10 -0
- package/dist/cli/TerminalText.d.ts.map +1 -0
- package/dist/cli/TerminalText.js +53 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +33 -4
- package/dist/cognitive/ConfiguredPipeline.d.ts +34 -0
- package/dist/cognitive/ConfiguredPipeline.d.ts.map +1 -0
- package/dist/cognitive/ConfiguredPipeline.js +50 -0
- package/dist/cognitive/ValidationRunner.d.ts +4 -0
- package/dist/cognitive/ValidationRunner.d.ts.map +1 -1
- package/dist/cognitive/ValidationRunner.js +18 -41
- package/dist/config/NodeOrchestration.d.ts +21 -0
- package/dist/config/NodeOrchestration.d.ts.map +1 -0
- package/dist/config/NodeOrchestration.js +54 -0
- package/dist/config/OrchestrationConfig.d.ts +100 -0
- package/dist/config/OrchestrationConfig.d.ts.map +1 -0
- package/dist/config/OrchestrationConfig.js +245 -0
- package/dist/connectors/mcp/McpClient.d.ts +3 -1
- package/dist/connectors/mcp/McpClient.d.ts.map +1 -1
- package/dist/connectors/mcp/McpClient.js +3 -2
- package/dist/connectors/mcp/McpServerRegistry.d.ts +2 -2
- package/dist/connectors/mcp/McpServerRegistry.d.ts.map +1 -1
- package/dist/connectors/mcp/McpServerRegistry.js +39 -16
- package/dist/connectors/mcp/McpToolAdapter.js +2 -2
- package/dist/connectors/media/ConfiguredMediaTools.d.ts +6 -0
- package/dist/connectors/media/ConfiguredMediaTools.d.ts.map +1 -0
- package/dist/connectors/media/ConfiguredMediaTools.js +41 -0
- package/dist/connectors/media/ImageGenerationTool.js +3 -3
- package/dist/connectors/media/MediaArtifactReceipt.d.ts +5 -0
- package/dist/connectors/media/MediaArtifactReceipt.d.ts.map +1 -0
- package/dist/connectors/media/MediaArtifactReceipt.js +65 -0
- package/dist/connectors/media/MediaJobStore.d.ts +68 -0
- package/dist/connectors/media/MediaJobStore.d.ts.map +1 -0
- package/dist/connectors/media/MediaJobStore.js +199 -0
- package/dist/connectors/media/MediaJobWorker.d.ts +2 -0
- package/dist/connectors/media/MediaJobWorker.d.ts.map +1 -0
- package/dist/connectors/media/MediaJobWorker.js +65 -0
- package/dist/connectors/media/RemoteMediaJob.d.ts +6 -0
- package/dist/connectors/media/RemoteMediaJob.d.ts.map +1 -0
- package/dist/connectors/media/RemoteMediaJob.js +80 -0
- package/dist/docdex/DocdexClient.d.ts +18 -1
- package/dist/docdex/DocdexClient.d.ts.map +1 -1
- package/dist/docdex/DocdexClient.js +135 -19
- package/dist/docdex/ManagedDocdex.d.ts +29 -0
- package/dist/docdex/ManagedDocdex.d.ts.map +1 -0
- package/dist/docdex/ManagedDocdex.js +215 -0
- package/dist/docdex/ManagedRuntime.d.ts +28 -0
- package/dist/docdex/ManagedRuntime.d.ts.map +1 -0
- package/dist/docdex/ManagedRuntime.js +212 -0
- package/dist/eval/EvaluationProcess.d.ts +13 -0
- package/dist/eval/EvaluationProcess.d.ts.map +1 -0
- package/dist/eval/EvaluationProcess.js +76 -0
- package/dist/eval/LongWorkflowJourney.d.ts +34 -0
- package/dist/eval/LongWorkflowJourney.d.ts.map +1 -0
- package/dist/eval/LongWorkflowJourney.js +243 -0
- package/dist/eval/PlanningCorpus.d.ts +45 -0
- package/dist/eval/PlanningCorpus.d.ts.map +1 -0
- package/dist/eval/PlanningCorpus.js +189 -0
- package/dist/eval/PlanningCorpusRunner.d.ts +13 -0
- package/dist/eval/PlanningCorpusRunner.d.ts.map +1 -0
- package/dist/eval/PlanningCorpusRunner.js +89 -0
- package/dist/eval/TerminalCorpusRunner.d.ts +36 -0
- package/dist/eval/TerminalCorpusRunner.d.ts.map +1 -0
- package/dist/eval/TerminalCorpusRunner.js +222 -0
- package/dist/eval/TerminalTaskCorpus.d.ts +26 -0
- package/dist/eval/TerminalTaskCorpus.d.ts.map +1 -0
- package/dist/eval/TerminalTaskCorpus.js +105 -0
- package/dist/eval/TerminalWorkflowCorpus.d.ts +11 -0
- package/dist/eval/TerminalWorkflowCorpus.d.ts.map +1 -0
- package/dist/eval/TerminalWorkflowCorpus.js +116 -0
- package/dist/eval/fixtures/TerminalRecoveryJourney.d.ts +4 -0
- package/dist/eval/fixtures/TerminalRecoveryJourney.d.ts.map +1 -0
- package/dist/eval/fixtures/TerminalRecoveryJourney.js +132 -0
- package/dist/gateway/CodaliGateway.d.ts +2 -0
- package/dist/gateway/CodaliGateway.d.ts.map +1 -1
- package/dist/gateway/CodaliGateway.js +11 -1
- package/dist/gateway/ConfiguredGateway.d.ts +23 -0
- package/dist/gateway/ConfiguredGateway.d.ts.map +1 -0
- package/dist/gateway/ConfiguredGateway.js +44 -0
- package/dist/gateway/GatewayTracer.d.ts +1 -1
- package/dist/gateway/GatewayTracer.d.ts.map +1 -1
- package/dist/gateway/GatewayTracer.js +2 -27
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/permissions/PermissionGate.d.ts +44 -0
- package/dist/permissions/PermissionGate.d.ts.map +1 -0
- package/dist/permissions/PermissionGate.js +97 -0
- package/dist/providers/ConfiguredEmbeddings.d.ts +43 -0
- package/dist/providers/ConfiguredEmbeddings.d.ts.map +1 -0
- package/dist/providers/ConfiguredEmbeddings.js +87 -0
- package/dist/providers/ConfiguredModelScope.d.ts +69 -0
- package/dist/providers/ConfiguredModelScope.d.ts.map +1 -0
- package/dist/providers/ConfiguredModelScope.js +113 -0
- package/dist/providers/ConfiguredProvider.d.ts +79 -0
- package/dist/providers/ConfiguredProvider.d.ts.map +1 -0
- package/dist/providers/ConfiguredProvider.js +238 -0
- package/dist/providers/ModelServiceError.d.ts +10 -0
- package/dist/providers/ModelServiceError.d.ts.map +1 -0
- package/dist/providers/ModelServiceError.js +45 -0
- package/dist/providers/MswarmWorkerProvider.d.ts.map +1 -1
- package/dist/providers/MswarmWorkerProvider.js +4 -0
- package/dist/providers/OpenAiCompatibleProvider.d.ts.map +1 -1
- package/dist/providers/OpenAiCompatibleProvider.js +91 -50
- package/dist/providers/ProviderTypes.d.ts +12 -0
- package/dist/providers/ProviderTypes.d.ts.map +1 -1
- package/dist/runtime/CodaliJobRuntime.d.ts +6 -0
- package/dist/runtime/CodaliJobRuntime.d.ts.map +1 -1
- package/dist/runtime/CodaliJobRuntime.js +36 -1
- package/dist/runtime/CodaliRuntime.d.ts +28 -0
- package/dist/runtime/CodaliRuntime.d.ts.map +1 -1
- package/dist/runtime/CodaliRuntime.js +69 -1
- package/dist/runtime/CompletionReport.d.ts +5 -0
- package/dist/runtime/CompletionReport.d.ts.map +1 -0
- package/dist/runtime/CompletionReport.js +12 -0
- package/dist/runtime/ProgressTracker.d.ts +17 -0
- package/dist/runtime/ProgressTracker.d.ts.map +1 -0
- package/dist/runtime/ProgressTracker.js +27 -0
- package/dist/runtime/RequestedTestEvidence.d.ts +12 -0
- package/dist/runtime/RequestedTestEvidence.d.ts.map +1 -0
- package/dist/runtime/RequestedTestEvidence.js +16 -0
- package/dist/runtime/RequiredRetrieval.d.ts +13 -0
- package/dist/runtime/RequiredRetrieval.d.ts.map +1 -0
- package/dist/runtime/RequiredRetrieval.js +25 -0
- package/dist/runtime/ReviewSource.d.ts +6 -0
- package/dist/runtime/ReviewSource.d.ts.map +1 -0
- package/dist/runtime/ReviewSource.js +38 -0
- package/dist/runtime/Runner.d.ts +7 -0
- package/dist/runtime/Runner.d.ts.map +1 -1
- package/dist/runtime/Runner.js +215 -171
- package/dist/runtime/SecretRedaction.d.ts +11 -0
- package/dist/runtime/SecretRedaction.d.ts.map +1 -0
- package/dist/runtime/SecretRedaction.js +85 -0
- package/dist/runtime/SessionController.d.ts +148 -0
- package/dist/runtime/SessionController.d.ts.map +1 -0
- package/dist/runtime/SessionController.js +1357 -0
- package/dist/runtime/StructuralEvidence.d.ts +22 -0
- package/dist/runtime/StructuralEvidence.d.ts.map +1 -0
- package/dist/runtime/StructuralEvidence.js +87 -0
- package/dist/runtime/TaskReviewContext.d.ts +34 -0
- package/dist/runtime/TaskReviewContext.d.ts.map +1 -0
- package/dist/runtime/TaskReviewContext.js +34 -0
- package/dist/runtime/ValidationOutput.d.ts +5 -0
- package/dist/runtime/ValidationOutput.d.ts.map +1 -0
- package/dist/runtime/ValidationOutput.js +32 -0
- package/dist/runtime/VerificationCommand.d.ts +5 -0
- package/dist/runtime/VerificationCommand.d.ts.map +1 -0
- package/dist/runtime/VerificationCommand.js +76 -0
- package/dist/runtime/WorkStatusPage.d.ts +15 -0
- package/dist/runtime/WorkStatusPage.d.ts.map +1 -0
- package/dist/runtime/WorkStatusPage.js +58 -0
- package/dist/runtime/WorkspaceLedger.d.ts +13 -0
- package/dist/runtime/WorkspaceLedger.d.ts.map +1 -0
- package/dist/runtime/WorkspaceLedger.js +145 -0
- package/dist/runtime/WorkspaceLock.d.ts.map +1 -1
- package/dist/runtime/WorkspaceLock.js +20 -17
- package/dist/runtime/WorkspaceSnapshot.d.ts +13 -0
- package/dist/runtime/WorkspaceSnapshot.d.ts.map +1 -0
- package/dist/runtime/WorkspaceSnapshot.js +88 -0
- package/dist/session/AtomicState.d.ts +13 -0
- package/dist/session/AtomicState.d.ts.map +1 -0
- package/dist/session/AtomicState.js +123 -0
- package/dist/session/SessionStoragePath.d.ts +15 -0
- package/dist/session/SessionStoragePath.d.ts.map +1 -0
- package/dist/session/SessionStoragePath.js +89 -0
- package/dist/session/SessionStore.d.ts +9 -0
- package/dist/session/SessionStore.d.ts.map +1 -1
- package/dist/session/SessionStore.js +181 -47
- package/dist/session/WorkState.d.ts +23 -0
- package/dist/session/WorkState.d.ts.map +1 -0
- package/dist/session/WorkState.js +367 -0
- package/dist/session/WorkTypes.d.ts +94 -0
- package/dist/session/WorkTypes.d.ts.map +1 -0
- package/dist/session/WorkTypes.js +1 -0
- package/dist/tools/ToolRegistry.d.ts +2 -0
- package/dist/tools/ToolRegistry.d.ts.map +1 -1
- package/dist/tools/ToolRegistry.js +12 -2
- package/dist/tools/ToolTypes.d.ts +16 -0
- package/dist/tools/ToolTypes.d.ts.map +1 -1
- package/dist/tools/docdex/DocdexTools.d.ts +2 -0
- package/dist/tools/docdex/DocdexTools.d.ts.map +1 -1
- package/dist/tools/docdex/DocdexTools.js +17 -2
- package/dist/tools/filesystem/FileTools.d.ts.map +1 -1
- package/dist/tools/filesystem/FileTools.js +30 -10
- package/dist/tools/shell/AsyncProcess.d.ts +19 -0
- package/dist/tools/shell/AsyncProcess.d.ts.map +1 -0
- package/dist/tools/shell/AsyncProcess.js +94 -0
- package/dist/tools/shell/DarwinRuntimeLibraries.d.ts +13 -0
- package/dist/tools/shell/DarwinRuntimeLibraries.d.ts.map +1 -0
- package/dist/tools/shell/DarwinRuntimeLibraries.js +130 -0
- package/dist/tools/shell/HostToolchain.d.ts +19 -0
- package/dist/tools/shell/HostToolchain.d.ts.map +1 -0
- package/dist/tools/shell/HostToolchain.js +266 -0
- package/dist/tools/shell/IsolatedExecutor.d.ts +15 -0
- package/dist/tools/shell/IsolatedExecutor.d.ts.map +1 -0
- package/dist/tools/shell/IsolatedExecutor.js +138 -0
- package/dist/tools/shell/ShellTool.d.ts.map +1 -1
- package/dist/tools/shell/ShellTool.js +9 -29
- package/dist/tools/shell/ShellWorkingDirectory.d.ts +3 -0
- package/dist/tools/shell/ShellWorkingDirectory.d.ts.map +1 -0
- package/dist/tools/shell/ShellWorkingDirectory.js +30 -0
- package/package.json +27 -24
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const timestamp = () => new Date().toISOString();
|
|
4
|
+
const assert = (value, message) => { if (!value)
|
|
5
|
+
throw new Error(message); };
|
|
6
|
+
const unique = (values, label) => {
|
|
7
|
+
assert(values.every(v => typeof v === "string" && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,119}$/.test(v)), `Invalid ${label} id`);
|
|
8
|
+
assert(new Set(values).size === values.length, `Duplicate ${label} id`);
|
|
9
|
+
};
|
|
10
|
+
const taskDependencies = (state, task) => {
|
|
11
|
+
const phase = state.phases?.find(p => p.id === task.phaseId);
|
|
12
|
+
return [...new Set([...task.dependsOn, ...state.tasks.filter(t => t.phaseId && phase?.dependsOn.includes(t.phaseId)).map(t => t.id)])];
|
|
13
|
+
};
|
|
14
|
+
const dependenciesVerified = (state, task) => taskDependencies(state, task).every(id => state.tasks.find(t => t.id === id)?.status === "verified");
|
|
15
|
+
const reopenTask = (task) => {
|
|
16
|
+
task.status = "planned";
|
|
17
|
+
task.evidenceIds = [];
|
|
18
|
+
task.attemptId = undefined;
|
|
19
|
+
task.leaseExpiresAt = undefined;
|
|
20
|
+
};
|
|
21
|
+
export const createWorkState = (objective, requirements) => {
|
|
22
|
+
assert(objective.trim(), "Objective is required");
|
|
23
|
+
const at = timestamp();
|
|
24
|
+
const criteria = requirements ?? [{ id: "R1", description: objective, required: true }];
|
|
25
|
+
const state = {
|
|
26
|
+
schemaVersion: 1, revision: 1, goalRevision: 1, goalId: randomUUID(), originalObjective: objective,
|
|
27
|
+
objective, requirements: criteria, constraints: [], nonGoals: [], decisions: [], evidence: [], checkpoints: [], amendments: [],
|
|
28
|
+
createdAt: at, updatedAt: at, status: "active", phases: [], planRevision: 1, planHistory: [],
|
|
29
|
+
tasks: [{ id: "T1", title: objective, requirementIds: criteria.map(c => c.id), dependsOn: [], allowedPaths: [], status: "ready", evidenceIds: [] }],
|
|
30
|
+
};
|
|
31
|
+
validateWorkState(state);
|
|
32
|
+
return state;
|
|
33
|
+
};
|
|
34
|
+
export const validateWorkState = (state) => {
|
|
35
|
+
assert(state.schemaVersion === 1 && Number.isSafeInteger(state.revision) && state.revision > 0 && Number.isSafeInteger(state.goalRevision) && state.goalRevision > 0, "Unsupported/invalid work-state revision");
|
|
36
|
+
assert(typeof state.objective === "string" && state.objective.trim() && typeof state.originalObjective === "string" && state.originalObjective.trim(), "Missing work objective");
|
|
37
|
+
assert(["active", "blocked", "cancelled", "completed"].includes(state.status), "Invalid goal status");
|
|
38
|
+
for (const key of ["requirements", "tasks", "decisions", "evidence", "checkpoints", "amendments", "constraints", "nonGoals"])
|
|
39
|
+
assert(Array.isArray(state[key]), `Invalid ${key}`);
|
|
40
|
+
unique(state.requirements.map(r => r.id), "requirement");
|
|
41
|
+
unique(state.tasks.map(t => t.id), "task");
|
|
42
|
+
unique(state.decisions.map(d => d.id), "decision");
|
|
43
|
+
unique(state.evidence.map(e => e.id), "evidence");
|
|
44
|
+
assert(state.requirements.length > 0, "At least one acceptance criterion is required");
|
|
45
|
+
const tasks = new Map(state.tasks.map(t => [t.id, t]));
|
|
46
|
+
const requirements = new Set(state.requirements.map(r => r.id));
|
|
47
|
+
const evidence = new Map(state.evidence.map(e => [e.id, e]));
|
|
48
|
+
const phases = state.phases ?? [];
|
|
49
|
+
assert(Array.isArray(phases) && (state.planRevision === undefined || Number.isSafeInteger(state.planRevision) && state.planRevision > 0), "Invalid plan revision/phases");
|
|
50
|
+
unique(phases.map(p => p.id), "phase");
|
|
51
|
+
for (const phase of phases) {
|
|
52
|
+
assert(typeof phase.title === "string" && phase.title.trim(), `Phase ${phase.id}: missing title`);
|
|
53
|
+
assert(Array.isArray(phase.dependsOn) && phase.dependsOn.every(id => id !== phase.id && phases.some(p => p.id === id)), `Phase ${phase.id}: missing/self dependency`);
|
|
54
|
+
assert(Array.isArray(phase.exitRequirementIds) && phase.exitRequirementIds.length > 0 && phase.exitRequirementIds.every(id => requirements.has(id)), `Phase ${phase.id}: invalid exit criteria`);
|
|
55
|
+
assert(state.tasks.some(t => t.phaseId === phase.id), `Phase ${phase.id}: no tasks`);
|
|
56
|
+
assert(phase.exitRequirementIds.every(id => state.tasks.some(t => t.phaseId === phase.id && t.requirementIds.includes(id))), `Phase ${phase.id}: uncovered exit criterion`);
|
|
57
|
+
}
|
|
58
|
+
for (const r of state.requirements)
|
|
59
|
+
assert(typeof r.description === "string" && r.description.trim() && typeof r.required === "boolean", "Invalid acceptance criterion");
|
|
60
|
+
for (const task of state.tasks) {
|
|
61
|
+
assert(typeof task.title === "string" && task.title.trim(), `Task ${task.id}: missing title`);
|
|
62
|
+
assert(["planned", "ready", "running", "review_pending", "verified", "blocked", "cancelled", "superseded"].includes(task.status), `Task ${task.id}: invalid status`);
|
|
63
|
+
assert(Array.isArray(task.dependsOn) && Array.isArray(task.requirementIds) && Array.isArray(task.allowedPaths) && Array.isArray(task.evidenceIds), `Task ${task.id}: invalid arrays`);
|
|
64
|
+
assert(task.requirementIds.length > 0 && task.requirementIds.every(r => requirements.has(r)), `Task ${task.id}: unknown/missing requirement`);
|
|
65
|
+
assert(task.dependsOn.every(id => tasks.has(id) && id !== task.id), `Task ${task.id}: missing/self dependency`);
|
|
66
|
+
assert(!task.phaseId || phases.some(p => p.id === task.phaseId), `Task ${task.id}: unknown phase`);
|
|
67
|
+
for (const file of task.allowedPaths)
|
|
68
|
+
assert(typeof file === "string" && !path.isAbsolute(file) && !file.split(/[\\/]/).includes(".."), `Task ${task.id}: invalid path`);
|
|
69
|
+
assert(task.evidenceIds.every(id => evidence.get(id)?.taskId === task.id), `Task ${task.id}: invalid evidence reference`);
|
|
70
|
+
}
|
|
71
|
+
const visited = new Set();
|
|
72
|
+
const visiting = new Set();
|
|
73
|
+
const visit = (id) => {
|
|
74
|
+
assert(!visiting.has(id), `Task dependency cycle at ${id}`);
|
|
75
|
+
if (visited.has(id))
|
|
76
|
+
return;
|
|
77
|
+
visiting.add(id);
|
|
78
|
+
const task = tasks.get(id);
|
|
79
|
+
const phase = phases.find(p => p.id === task.phaseId);
|
|
80
|
+
const dependencies = [...task.dependsOn, ...state.tasks.filter(t => t.phaseId && phase?.dependsOn.includes(t.phaseId)).map(t => t.id)];
|
|
81
|
+
for (const dep of dependencies)
|
|
82
|
+
visit(dep);
|
|
83
|
+
visiting.delete(id);
|
|
84
|
+
visited.add(id);
|
|
85
|
+
};
|
|
86
|
+
for (const task of state.tasks)
|
|
87
|
+
visit(task.id);
|
|
88
|
+
for (const criterion of state.requirements.filter(r => r.required)) {
|
|
89
|
+
assert(state.tasks.some(t => !["cancelled", "superseded"].includes(t.status) && t.requirementIds.includes(criterion.id)), `Uncovered requirement: ${criterion.id}. Link this existing ID in task.requirementIds rather than inventing a replacement. Put whole-request R1 on the final integration task.`);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
export const refreshReadyTasks = (state) => {
|
|
93
|
+
for (const task of state.tasks)
|
|
94
|
+
if (task.status === "planned" || task.status === "ready") {
|
|
95
|
+
task.status = dependenciesVerified(state, task) ? "ready" : "planned";
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
export const replaceWorkPlan = (state, tasks, phases = state.phases ?? [], reason = "Task plan refined") => {
|
|
99
|
+
assert(!state.tasks.some(t => ["running", "review_pending"].includes(t.status)), "Finish the current attempt or call work_release with its taskId and attemptId before replacing the plan");
|
|
100
|
+
const existing = new Map(state.tasks.map(t => [t.id, t]));
|
|
101
|
+
const next = tasks.map(t => {
|
|
102
|
+
const old = existing.get(t.id);
|
|
103
|
+
if (old?.status === "verified") {
|
|
104
|
+
assert(JSON.stringify([old.title, old.requirementIds, old.dependsOn, old.allowedPaths, old.phaseId]) === JSON.stringify([t.title, t.requirementIds, t.dependsOn, t.allowedPaths, t.phaseId]), `Cannot silently rewrite verified task ${t.id}`);
|
|
105
|
+
return old;
|
|
106
|
+
}
|
|
107
|
+
return { ...t, status: "planned", evidenceIds: [] };
|
|
108
|
+
});
|
|
109
|
+
for (const old of state.tasks.filter(t => t.status === "verified"))
|
|
110
|
+
assert(next.some(t => t.id === old.id), `Cannot remove verified task ${old.id}`);
|
|
111
|
+
const candidate = { ...state, tasks: next, phases };
|
|
112
|
+
validateWorkState(candidate);
|
|
113
|
+
const phaseContract = (all, id) => {
|
|
114
|
+
const selected = new Map();
|
|
115
|
+
const add = (phaseId) => {
|
|
116
|
+
const phase = all.find(p => p.id === phaseId);
|
|
117
|
+
if (!phase || selected.has(phaseId))
|
|
118
|
+
return;
|
|
119
|
+
selected.set(phaseId, phase);
|
|
120
|
+
phase.dependsOn.forEach(add);
|
|
121
|
+
};
|
|
122
|
+
if (id)
|
|
123
|
+
add(id);
|
|
124
|
+
return [...selected.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
125
|
+
};
|
|
126
|
+
for (const task of next.filter(t => t.status === "verified")) {
|
|
127
|
+
assert(JSON.stringify(phaseContract(state.phases ?? [], task.phaseId)) === JSON.stringify(phaseContract(phases, task.phaseId)), `Cannot silently rewrite the phase contract of verified task ${task.id}`);
|
|
128
|
+
assert(dependenciesVerified(candidate, task), `Verified task ${task.id} has an unverified prerequisite in the revised plan`);
|
|
129
|
+
}
|
|
130
|
+
state.planHistory ?? (state.planHistory = []);
|
|
131
|
+
state.planHistory.push({ revision: state.planRevision ?? 1, goalRevision: state.goalRevision, at: timestamp(), reason, tasks: structuredClone(state.tasks), phases: structuredClone(state.phases ?? []) });
|
|
132
|
+
state.planRevision = (state.planRevision ?? 1) + 1;
|
|
133
|
+
state.tasks = next;
|
|
134
|
+
state.phases = structuredClone(phases);
|
|
135
|
+
refreshReadyTasks(state);
|
|
136
|
+
};
|
|
137
|
+
/** Update named contracts while retaining every unmentioned task and phase. */
|
|
138
|
+
export const updateWorkPlan = (state, updates, phaseUpdates = [], reason = "Task plan updated") => {
|
|
139
|
+
unique(updates.map(task => task.id), "task update");
|
|
140
|
+
unique(phaseUpdates.map(phase => phase.id), "phase update");
|
|
141
|
+
const tasks = new Map(state.tasks.map(task => [task.id, task]));
|
|
142
|
+
const phases = new Map((state.phases ?? []).map(phase => [phase.id, phase]));
|
|
143
|
+
for (const task of updates)
|
|
144
|
+
tasks.set(task.id, { ...task, status: "planned", evidenceIds: [] });
|
|
145
|
+
for (const phase of phaseUpdates)
|
|
146
|
+
phases.set(phase.id, phase);
|
|
147
|
+
// Reuse the same coverage, verified-contract, dependency and lease fences.
|
|
148
|
+
const candidate = structuredClone(state);
|
|
149
|
+
replaceWorkPlan(candidate, [...tasks.values()], [...phases.values()], reason);
|
|
150
|
+
const updatedIds = new Set(updates.map(task => task.id));
|
|
151
|
+
candidate.tasks = candidate.tasks.map(task => {
|
|
152
|
+
const old = state.tasks.find(previous => previous.id === task.id);
|
|
153
|
+
return old && !updatedIds.has(task.id) && ["blocked", "cancelled", "superseded"].includes(old.status) ? structuredClone(old) : task;
|
|
154
|
+
});
|
|
155
|
+
validateWorkState(candidate);
|
|
156
|
+
refreshReadyTasks(candidate);
|
|
157
|
+
Object.assign(state, candidate);
|
|
158
|
+
};
|
|
159
|
+
export const claimWorkTask = (state, taskId, leaseMs = 300000) => {
|
|
160
|
+
assert(state.status === "active", "Goal is not active");
|
|
161
|
+
refreshReadyTasks(state);
|
|
162
|
+
const task = state.tasks.find(t => t.id === taskId);
|
|
163
|
+
assert(task?.status === "ready", "Task is not ready");
|
|
164
|
+
assert(!state.tasks.some(t => ["running", "review_pending"].includes(t.status)), "A task already owns this workspace");
|
|
165
|
+
assert(Number.isFinite(leaseMs) && leaseMs > 0, "Invalid lease");
|
|
166
|
+
task.status = "running";
|
|
167
|
+
task.attemptId = randomUUID();
|
|
168
|
+
task.goalRevision = state.goalRevision;
|
|
169
|
+
task.planRevision = state.planRevision ?? 1;
|
|
170
|
+
task.leaseExpiresAt = new Date(Date.now() + leaseMs).toISOString();
|
|
171
|
+
return task;
|
|
172
|
+
};
|
|
173
|
+
export const releaseWorkTask = (state, taskId, attemptId, note) => {
|
|
174
|
+
const task = state.tasks.find(t => t.id === taskId);
|
|
175
|
+
assert(task && ["running", "review_pending"].includes(task.status) && task.attemptId === attemptId, "Cannot release a stale or inactive task attempt");
|
|
176
|
+
assert(note.trim(), "Explain why the attempt is released and what changes next");
|
|
177
|
+
state.checkpoints.push({ id: randomUUID(), at: timestamp(), goalRevision: state.goalRevision,
|
|
178
|
+
activeTaskId: taskId, note: `Released attempt ${attemptId}: ${note}`, uncertainInvocationIds: [] });
|
|
179
|
+
reopenTask(task);
|
|
180
|
+
refreshReadyTasks(state);
|
|
181
|
+
};
|
|
182
|
+
/** Withdraw a disproven verification and fence all dependent attempts without rewriting the plan. */
|
|
183
|
+
export const reopenVerifiedTask = (state, taskId, reason) => {
|
|
184
|
+
const task = state.tasks.find(t => t.id === taskId);
|
|
185
|
+
assert(state.status === "active" && task?.status === "verified", "Only a verified task in an active goal can be reopened");
|
|
186
|
+
assert(reason.trim(), "Explain the new evidence that disproves this verification");
|
|
187
|
+
const affected = new Set([taskId]);
|
|
188
|
+
let changed = true;
|
|
189
|
+
while (changed) {
|
|
190
|
+
changed = false;
|
|
191
|
+
for (const candidate of state.tasks)
|
|
192
|
+
if (!affected.has(candidate.id) && !["cancelled", "superseded"].includes(candidate.status)
|
|
193
|
+
&& taskDependencies(state, candidate).some(id => affected.has(id))) {
|
|
194
|
+
affected.add(candidate.id);
|
|
195
|
+
changed = true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
for (const candidate of state.tasks)
|
|
199
|
+
if (affected.has(candidate.id))
|
|
200
|
+
reopenTask(candidate);
|
|
201
|
+
state.checkpoints.push({ id: randomUUID(), at: timestamp(), goalRevision: state.goalRevision,
|
|
202
|
+
activeTaskId: taskId, note: `Reopened verified task ${taskId}; invalidated ${[...affected].join(", ")}: ${reason}`, uncertainInvocationIds: [] });
|
|
203
|
+
refreshReadyTasks(state);
|
|
204
|
+
return [...affected];
|
|
205
|
+
};
|
|
206
|
+
export const assertWorkAttempt = (state, taskId, attemptId) => {
|
|
207
|
+
const task = state.tasks.find(t => t.id === taskId);
|
|
208
|
+
assert(state.status === "active" && task && ["running", "review_pending"].includes(task.status) && task.attemptId === attemptId && task.goalRevision === state.goalRevision, "Stale task attempt or goal revision");
|
|
209
|
+
assert(Date.parse(task.leaseExpiresAt ?? "") > Date.now(), "Task lease expired; reconcile before retrying");
|
|
210
|
+
assert(task.planRevision === undefined || task.planRevision === (state.planRevision ?? 1), "Stale plan revision");
|
|
211
|
+
assert(dependenciesVerified(state, task), "Task prerequisite was invalidated; reconcile before continuing");
|
|
212
|
+
return task;
|
|
213
|
+
};
|
|
214
|
+
export const recordWorkEvidence = (state, taskId, attemptId, evidence) => {
|
|
215
|
+
const task = assertWorkAttempt(state, taskId, attemptId);
|
|
216
|
+
assert(evidence.taskId === taskId && evidence.criterionIds.length > 0 && evidence.criterionIds.every(id => task.requirementIds.includes(id)), "Evidence does not match the task criteria");
|
|
217
|
+
assert(evidence.kind !== "tool" || evidence.invocationId, "Tool evidence requires an invocation receipt");
|
|
218
|
+
const previous = state.evidence.find(e => e.id === evidence.id);
|
|
219
|
+
if (previous) {
|
|
220
|
+
assert(JSON.stringify(previous) === JSON.stringify(evidence), "Conflicting evidence id");
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
state.evidence.push(evidence);
|
|
224
|
+
task.evidenceIds.push(evidence.id);
|
|
225
|
+
task.status = "review_pending";
|
|
226
|
+
};
|
|
227
|
+
export const verifyWorkTask = (state, taskId, attemptId, currentHashes) => {
|
|
228
|
+
const task = assertWorkAttempt(state, taskId, attemptId);
|
|
229
|
+
const applicable = state.evidence.filter(e => task.evidenceIds.includes(e.id) && e.ok && Object.entries(e.inputHashes).every(([file, hash]) => currentHashes[file] === hash));
|
|
230
|
+
for (const requirement of task.requirementIds)
|
|
231
|
+
assert(applicable.some(e => e.criterionIds.includes(requirement)), `Unverified/stale criterion: ${requirement}`);
|
|
232
|
+
task.status = "verified";
|
|
233
|
+
refreshReadyTasks(state);
|
|
234
|
+
};
|
|
235
|
+
/** Reopen stale proofs and their dependent tasks without discarding audit history. */
|
|
236
|
+
export const refreshStaleEvidence = (state, currentHashes) => {
|
|
237
|
+
const reopened = [];
|
|
238
|
+
let changed = true;
|
|
239
|
+
while (changed) {
|
|
240
|
+
changed = false;
|
|
241
|
+
for (const task of state.tasks.filter(t => ["verified", "running", "review_pending"].includes(t.status))) {
|
|
242
|
+
const proofs = state.evidence.filter(e => task.evidenceIds.includes(e.id) && e.ok && Object.entries(e.inputHashes).every(([file, hash]) => currentHashes[file] === hash));
|
|
243
|
+
if ((task.status !== "verified" || task.requirementIds.every(id => proofs.some(e => e.criterionIds.includes(id)))) && dependenciesVerified(state, task))
|
|
244
|
+
continue;
|
|
245
|
+
reopenTask(task);
|
|
246
|
+
reopened.push(task.id);
|
|
247
|
+
changed = true;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (reopened.length && state.status === "completed")
|
|
251
|
+
state.status = "active";
|
|
252
|
+
refreshReadyTasks(state);
|
|
253
|
+
return reopened;
|
|
254
|
+
};
|
|
255
|
+
export const amendWorkGoal = (state, objective, reason) => {
|
|
256
|
+
assert(objective.trim() && reason.trim(), "Goal amendment needs an objective and reason");
|
|
257
|
+
state.amendments.push({ revision: state.goalRevision, at: timestamp(), reason, previousObjective: state.objective });
|
|
258
|
+
state.goalRevision += 1;
|
|
259
|
+
state.objective = objective;
|
|
260
|
+
state.status = "active";
|
|
261
|
+
const criterionId = `steering-${state.goalRevision}`;
|
|
262
|
+
state.requirements.push({ id: criterionId, description: reason, required: true });
|
|
263
|
+
state.tasks.push({ id: criterionId, title: reason, requirementIds: [criterionId], dependsOn: [], allowedPaths: [], status: "planned", evidenceIds: [] });
|
|
264
|
+
for (const task of state.tasks)
|
|
265
|
+
if (!["cancelled", "superseded"].includes(task.status)) {
|
|
266
|
+
task.status = "planned";
|
|
267
|
+
task.attemptId = undefined;
|
|
268
|
+
task.leaseExpiresAt = undefined;
|
|
269
|
+
task.evidenceIds = [];
|
|
270
|
+
}
|
|
271
|
+
refreshReadyTasks(state);
|
|
272
|
+
};
|
|
273
|
+
export const recordDecision = (state, decision) => {
|
|
274
|
+
assert(decision.title.trim() && decision.rationale.trim(), "Decision requires a title and rationale");
|
|
275
|
+
assert(!state.decisions.some(d => d.id === decision.id), "Decision id already exists");
|
|
276
|
+
if (decision.supersedes)
|
|
277
|
+
assert(state.decisions.some(d => d.id === decision.supersedes), "Superseded decision does not exist");
|
|
278
|
+
if (decision.supersedes)
|
|
279
|
+
assert(!state.decisions.some(d => d.supersedes === decision.supersedes), "Decision was already superseded; supersede its current replacement");
|
|
280
|
+
state.decisions.push(decision);
|
|
281
|
+
if (decision.supersedes) {
|
|
282
|
+
const previous = state.decisions.find(d => d.id === decision.supersedes);
|
|
283
|
+
const affected = [...previous.paths, ...decision.paths];
|
|
284
|
+
const invalidated = new Set();
|
|
285
|
+
for (const task of state.tasks)
|
|
286
|
+
if (["verified", "running", "review_pending"].includes(task.status) && (!affected.length || !task.allowedPaths.length || task.allowedPaths.some(scope => affected.some(file => scope === "." || file === scope || file.startsWith(`${scope}/`) || scope.startsWith(`${file}/`))))) {
|
|
287
|
+
reopenTask(task);
|
|
288
|
+
invalidated.add(task.id);
|
|
289
|
+
}
|
|
290
|
+
let changed = true;
|
|
291
|
+
while (changed) {
|
|
292
|
+
changed = false;
|
|
293
|
+
for (const task of state.tasks)
|
|
294
|
+
if (!invalidated.has(task.id) && !["cancelled", "superseded"].includes(task.status) && taskDependencies(state, task).some(id => invalidated.has(id))) {
|
|
295
|
+
reopenTask(task);
|
|
296
|
+
invalidated.add(task.id);
|
|
297
|
+
changed = true;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (invalidated.size && state.status === "completed")
|
|
301
|
+
state.status = "active";
|
|
302
|
+
refreshReadyTasks(state);
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
export const completeWorkGoal = (state, currentHashes, uncertainInvocationIds = []) => {
|
|
306
|
+
validateWorkState(state);
|
|
307
|
+
assert(state.status === "active" && uncertainInvocationIds.length === 0, "Goal cannot complete with unresolved side effects");
|
|
308
|
+
assert(state.tasks.every(t => ["verified", "cancelled", "superseded"].includes(t.status)), "Required task work remains");
|
|
309
|
+
for (const criterion of state.requirements.filter(r => r.required)) {
|
|
310
|
+
const tasks = state.tasks.filter(t => t.requirementIds.includes(criterion.id) && t.status === "verified");
|
|
311
|
+
assert(tasks.length > 0 && tasks.every(t => state.evidence.some(e => t.evidenceIds.includes(e.id) && e.ok && e.criterionIds.includes(criterion.id) && Object.entries(e.inputHashes).every(([file, hash]) => currentHashes[file] === hash))), `Unverified/stale criterion: ${criterion.id}`);
|
|
312
|
+
}
|
|
313
|
+
state.status = "completed";
|
|
314
|
+
};
|
|
315
|
+
export const workContext = (state) => JSON.stringify({
|
|
316
|
+
goalId: state.goalId, goalRevision: state.goalRevision, planRevision: state.planRevision ?? 1, phases: state.phases ?? [], objective: state.objective,
|
|
317
|
+
originalObjective: state.originalObjective, requirements: state.requirements, constraints: state.constraints,
|
|
318
|
+
nonGoals: state.nonGoals, tasks: state.tasks.map(t => ({ id: t.id, title: t.title, phaseId: t.phaseId, status: t.status, dependsOn: t.dependsOn, requirementIds: t.requirementIds, allowedPaths: t.allowedPaths, attemptId: t.attemptId, blocker: t.blocker })),
|
|
319
|
+
decisions: state.decisions, checkpoint: state.checkpoints.at(-1),
|
|
320
|
+
});
|
|
321
|
+
/** Keep the active contract intact while paging unrelated backlog out of context. */
|
|
322
|
+
export const activeWorkContext = (state, maxChars) => {
|
|
323
|
+
const full = workContext(state);
|
|
324
|
+
if (full.length <= maxChars)
|
|
325
|
+
return full;
|
|
326
|
+
const active = state.tasks.find(t => ["running", "review_pending"].includes(t.status)) ?? state.tasks.find(t => t.status === "ready");
|
|
327
|
+
const requiredIds = new Set(active?.requirementIds ?? []);
|
|
328
|
+
const superseded = new Set(state.decisions.map(d => d.supersedes).filter(Boolean));
|
|
329
|
+
const relevant = (paths) => !active || !paths.length || !active.allowedPaths.length || paths.some(file => active.allowedPaths.some(scope => scope === "." || file === scope || file.startsWith(`${scope}/`) || scope.startsWith(`${file}/`)));
|
|
330
|
+
const currentDecisions = state.decisions.filter(d => !superseded.has(d.id) && relevant(d.paths));
|
|
331
|
+
const view = {
|
|
332
|
+
goalId: state.goalId, goalRevision: state.goalRevision, planRevision: state.planRevision ?? 1,
|
|
333
|
+
objective: state.objective, originalObjective: state.originalObjective, constraints: state.constraints, nonGoals: state.nonGoals,
|
|
334
|
+
activeTask: active,
|
|
335
|
+
requirements: state.requirements.filter(r => requiredIds.has(r.id)),
|
|
336
|
+
decisions: currentDecisions,
|
|
337
|
+
phases: state.phases?.filter(p => p.id === active?.phaseId),
|
|
338
|
+
prerequisiteTasks: active ? taskDependencies(state, active).map(id => {
|
|
339
|
+
const task = state.tasks.find(t => t.id === id);
|
|
340
|
+
return { id, title: task.title, status: task.status };
|
|
341
|
+
}) : [],
|
|
342
|
+
taskCounts: Object.fromEntries([...new Set(state.tasks.map(t => t.status))].map(status => [status, state.tasks.filter(t => t.status === status).length])),
|
|
343
|
+
totalRequirements: state.requirements.length,
|
|
344
|
+
otherRequirements: [],
|
|
345
|
+
nextTasks: [],
|
|
346
|
+
contextPartial: true,
|
|
347
|
+
continuation: "The complete goal and backlog remain canonical in storage. Use work_status with offset/limit or taskIds/requirementIds to retrieve omitted records. Claiming a task loads its full criteria and relevant decisions. Completion still checks every required criterion.",
|
|
348
|
+
};
|
|
349
|
+
const encode = () => JSON.stringify(view);
|
|
350
|
+
if (encode().length > maxChars)
|
|
351
|
+
throw new Error("Active goal, constraints, architecture decisions and criteria exceed the context reservation; use a larger compatible model context or split the active task");
|
|
352
|
+
for (const requirement of state.requirements.filter(r => !requiredIds.has(r.id))) {
|
|
353
|
+
view.otherRequirements.push(requirement);
|
|
354
|
+
if (encode().length > maxChars) {
|
|
355
|
+
view.otherRequirements.pop();
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
for (const task of state.tasks.filter(t => t.id !== active?.id && !["verified", "cancelled", "superseded"].includes(t.status))) {
|
|
360
|
+
view.nextTasks.push({ id: task.id, title: task.title, status: task.status });
|
|
361
|
+
if (encode().length > maxChars) {
|
|
362
|
+
view.nextTasks.pop();
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return encode();
|
|
367
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { ProjectTaskAttachment } from "@mcoda/shared";
|
|
2
|
+
export type WorkTaskStatus = "planned" | "ready" | "running" | "review_pending" | "verified" | "blocked" | "cancelled" | "superseded";
|
|
3
|
+
export interface Requirement {
|
|
4
|
+
id: string;
|
|
5
|
+
description: string;
|
|
6
|
+
required: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface WorkTask {
|
|
9
|
+
id: string;
|
|
10
|
+
title: string;
|
|
11
|
+
requirementIds: string[];
|
|
12
|
+
dependsOn: string[];
|
|
13
|
+
allowedPaths: string[];
|
|
14
|
+
status: WorkTaskStatus;
|
|
15
|
+
evidenceIds: string[];
|
|
16
|
+
attemptId?: string;
|
|
17
|
+
goalRevision?: number;
|
|
18
|
+
leaseExpiresAt?: string;
|
|
19
|
+
blocker?: string;
|
|
20
|
+
phaseId?: string;
|
|
21
|
+
planRevision?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface WorkPhase {
|
|
24
|
+
id: string;
|
|
25
|
+
title: string;
|
|
26
|
+
dependsOn: string[];
|
|
27
|
+
exitRequirementIds: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface PlanRevision {
|
|
30
|
+
revision: number;
|
|
31
|
+
goalRevision: number;
|
|
32
|
+
at: string;
|
|
33
|
+
reason: string;
|
|
34
|
+
tasks: WorkTask[];
|
|
35
|
+
phases: WorkPhase[];
|
|
36
|
+
}
|
|
37
|
+
export interface DecisionRecord {
|
|
38
|
+
id: string;
|
|
39
|
+
title: string;
|
|
40
|
+
rationale: string;
|
|
41
|
+
alternatives: string[];
|
|
42
|
+
paths: string[];
|
|
43
|
+
supersedes?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface EvidenceReceipt {
|
|
46
|
+
id: string;
|
|
47
|
+
taskId: string;
|
|
48
|
+
criterionIds: string[];
|
|
49
|
+
kind: "tool" | "review" | "human";
|
|
50
|
+
ok: boolean;
|
|
51
|
+
summary: string;
|
|
52
|
+
invocationId?: string;
|
|
53
|
+
inputHashes: Record<string, string>;
|
|
54
|
+
at: string;
|
|
55
|
+
}
|
|
56
|
+
export interface WorkCheckpoint {
|
|
57
|
+
id: string;
|
|
58
|
+
at: string;
|
|
59
|
+
goalRevision: number;
|
|
60
|
+
note: string;
|
|
61
|
+
activeTaskId?: string;
|
|
62
|
+
uncertainInvocationIds: string[];
|
|
63
|
+
}
|
|
64
|
+
export interface GoalAmendment {
|
|
65
|
+
revision: number;
|
|
66
|
+
at: string;
|
|
67
|
+
reason: string;
|
|
68
|
+
previousObjective: string;
|
|
69
|
+
}
|
|
70
|
+
export interface WorkState {
|
|
71
|
+
projectTask?: ProjectTaskAttachment;
|
|
72
|
+
schemaVersion: 1;
|
|
73
|
+
revision: number;
|
|
74
|
+
goalRevision: number;
|
|
75
|
+
goalId: string;
|
|
76
|
+
originalObjective: string;
|
|
77
|
+
objective: string;
|
|
78
|
+
requirements: Requirement[];
|
|
79
|
+
constraints: string[];
|
|
80
|
+
nonGoals: string[];
|
|
81
|
+
tasks: WorkTask[];
|
|
82
|
+
/** Optional on older v1 records; absence means the initial flat plan. */
|
|
83
|
+
phases?: WorkPhase[];
|
|
84
|
+
planRevision?: number;
|
|
85
|
+
planHistory?: PlanRevision[];
|
|
86
|
+
decisions: DecisionRecord[];
|
|
87
|
+
evidence: EvidenceReceipt[];
|
|
88
|
+
checkpoints: WorkCheckpoint[];
|
|
89
|
+
amendments: GoalAmendment[];
|
|
90
|
+
createdAt: string;
|
|
91
|
+
updatedAt: string;
|
|
92
|
+
status: "active" | "blocked" | "cancelled" | "completed";
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=WorkTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkTypes.d.ts","sourceRoot":"","sources":["../../src/session/WorkTypes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE3D,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,gBAAgB,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,YAAY,CAAC;AAEtI,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,MAAM,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,aAAa,EAAE,CAAC,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,yEAAyE;IACzE,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;IAC7B,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;CAC1D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -12,6 +12,8 @@ export declare class ToolRegistry {
|
|
|
12
12
|
private tools;
|
|
13
13
|
register(tool: ToolDefinition): void;
|
|
14
14
|
list(): ToolDefinition[];
|
|
15
|
+
/** Trusted host lifecycle operation; never exposed as an agent tool. */
|
|
16
|
+
unregister(name: string): void;
|
|
15
17
|
describe(): Array<Pick<ToolDefinition, "name" | "description" | "inputSchema">>;
|
|
16
18
|
/**
|
|
17
19
|
* Model-facing view of the registry, optionally narrowed to a set of tool
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolRegistry.d.ts","sourceRoot":"","sources":["../../src/tools/ToolRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EAGnB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAE1B,MAAM,gBAAgB,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,cAAc,KAAG,cAOvD,CAAC;AA4HH,eAAO,MAAM,qBAAqB,GAChC,OAAO,OAAO,EACd,QAAQ,oBAAoB,GAAG,SAAS,KACvC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAwBrC,CAAC;AAyLF,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAqC;IAElD,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAOpC,IAAI,IAAI,cAAc,EAAE;IAIxB,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,aAAa,GAAG,aAAa,CAAC,CAAC;IAQ/E;;;;OAIG;IACH,OAAO,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,EAAE;IAOpD,2EAA2E;IAC3E,YAAY,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,GAAG,CAAC,cAAc,EAAE,cAAc,EAAE,CAAC;IAaxE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"ToolRegistry.d.ts","sourceRoot":"","sources":["../../src/tools/ToolRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EAGnB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAE1B,MAAM,gBAAgB,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,cAAc,KAAG,cAOvD,CAAC;AA4HH,eAAO,MAAM,qBAAqB,GAChC,OAAO,OAAO,EACd,QAAQ,oBAAoB,GAAG,SAAS,KACvC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAwBrC,CAAC;AAyLF,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAqC;IAElD,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAOpC,IAAI,IAAI,cAAc,EAAE;IAIxB,wEAAwE;IACxE,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAE9B,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,aAAa,GAAG,aAAa,CAAC,CAAC;IAQ/E;;;;OAIG;IACH,OAAO,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,EAAE;IAOpD,2EAA2E;IAC3E,YAAY,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,GAAG,CAAC,cAAc,EAAE,cAAc,EAAE,CAAC;IAaxE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAgD/F"}
|
|
@@ -339,6 +339,8 @@ export class ToolRegistry {
|
|
|
339
339
|
list() {
|
|
340
340
|
return Array.from(this.tools.values());
|
|
341
341
|
}
|
|
342
|
+
/** Trusted host lifecycle operation; never exposed as an agent tool. */
|
|
343
|
+
unregister(name) { this.tools.delete(name); }
|
|
342
344
|
describe() {
|
|
343
345
|
return this.list().map((tool) => ({
|
|
344
346
|
name: tool.name,
|
|
@@ -396,16 +398,24 @@ export class ToolRegistry {
|
|
|
396
398
|
if (validationError) {
|
|
397
399
|
return { ok: false, output: "", error: validationError };
|
|
398
400
|
}
|
|
401
|
+
let execution;
|
|
399
402
|
try {
|
|
403
|
+
context.signal?.throwIfAborted();
|
|
404
|
+
await context.beforeTool?.(toolDescriptorFor(tool), sanitized.value);
|
|
405
|
+
context.signal?.throwIfAborted();
|
|
400
406
|
const result = await tool.handler(sanitized.value, context);
|
|
401
|
-
|
|
407
|
+
execution = { ok: true, output: result.output, data: result.data };
|
|
402
408
|
}
|
|
403
409
|
catch (error) {
|
|
404
|
-
|
|
410
|
+
execution = {
|
|
405
411
|
ok: false,
|
|
406
412
|
output: "",
|
|
407
413
|
error: normalizeExecutionError(error),
|
|
408
414
|
};
|
|
409
415
|
}
|
|
416
|
+
// Persistence failures must stop the run, not silently acknowledge a side effect.
|
|
417
|
+
await context.afterTool?.(toolDescriptorFor(tool), sanitized.value, execution);
|
|
418
|
+
context.signal?.throwIfAborted();
|
|
419
|
+
return execution;
|
|
410
420
|
}
|
|
411
421
|
}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
export interface ToolContext {
|
|
2
|
+
signal?: AbortSignal;
|
|
3
|
+
onOutput?: (stream: "stdout" | "stderr", chunk: string) => void;
|
|
4
|
+
beforeTool?: (tool: ToolDescriptor, args: unknown) => Promise<void>;
|
|
5
|
+
afterTool?: (tool: ToolDescriptor, args: unknown, result: ToolExecutionResult) => Promise<void>;
|
|
6
|
+
checkPath?: (resolvedPath: string, action: "read" | "write") => Promise<void>;
|
|
7
|
+
shellTimeoutMs?: number;
|
|
8
|
+
shellMaxOutputBytes?: number;
|
|
9
|
+
/** Process cwd inside workspaceRoot; does not change root-relative write scopes. */
|
|
10
|
+
shellWorkingDirectory?: string;
|
|
11
|
+
/** Optional trusted executor wrapper, applied after permission evaluation. */
|
|
12
|
+
shellExecutor?: (command: string, args: string[], context: ToolContext) => Promise<ToolHandlerResult>;
|
|
2
13
|
workspaceRoot: string;
|
|
3
14
|
runId?: string;
|
|
4
15
|
recordTouchedFile?: (path: string) => void;
|
|
@@ -55,6 +66,11 @@ export interface ToolHandlerResult {
|
|
|
55
66
|
export interface ToolExecutionResult extends ToolHandlerResult {
|
|
56
67
|
ok: boolean;
|
|
57
68
|
error?: ToolError;
|
|
69
|
+
/** Set by the host's afterTool hook; retained outside output truncation. */
|
|
70
|
+
invocationReceipt?: {
|
|
71
|
+
id: string;
|
|
72
|
+
reference: string;
|
|
73
|
+
};
|
|
58
74
|
}
|
|
59
75
|
export type ToolHandler = (args: unknown, context: ToolContext) => Promise<ToolHandlerResult>;
|
|
60
76
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolTypes.d.ts","sourceRoot":"","sources":["../../src/tools/ToolTypes.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ToolTypes.d.ts","sourceRoot":"","sources":["../../src/tools/ToolTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,6 +35,8 @@ export type RelevanceJudge = (input: {
|
|
|
35
35
|
}) => Promise<boolean>;
|
|
36
36
|
export interface DocdexToolOptions {
|
|
37
37
|
judgeRelevance?: RelevanceJudge;
|
|
38
|
+
/** Terminal clients authorize web research as a separate operation. */
|
|
39
|
+
allowSearchWebFallback?: boolean;
|
|
38
40
|
}
|
|
39
41
|
export declare const createDocdexTools: (client: DocdexClient, options?: DocdexToolOptions) => ToolDefinition[];
|
|
40
42
|
//# sourceMappingURL=DocdexTools.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocdexTools.d.ts","sourceRoot":"","sources":["../../../src/tools/docdex/DocdexTools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"DocdexTools.d.ts","sourceRoot":"","sources":["../../../src/tools/docdex/DocdexTools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAwFjE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,MAAM,GAAG,SAAS,EACzB,gBAAgB,MAAM,KACrB,MAAM,GAAG,SAWX,CAAC;AAwCF,0CAA0C;AAC1C,eAAO,MAAM,uBAAuB,QAAO,IAG1C,CAAC;AA0DF,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAO3D,CAAC;AAoHF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEvB,MAAM,WAAW,iBAAiB;IAChC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,uEAAuE;IACvE,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,YAAY,EACpB,UAAS,iBAAsB,KAC9B,cAAc,EAAiG,CAAC"}
|
|
@@ -14,6 +14,7 @@ const DOCDEX_WRITE_TOOLS = new Set([
|
|
|
14
14
|
"docdex_memory_save",
|
|
15
15
|
"docdex_save_preference",
|
|
16
16
|
"docdex_delegate",
|
|
17
|
+
"docdex_diary_write",
|
|
17
18
|
]);
|
|
18
19
|
/**
|
|
19
20
|
* Docdex is one capability from the orchestrator's point of view, except web
|
|
@@ -313,7 +314,21 @@ const withDocdexMetadata = (tools) => tools.map((tool) => ({
|
|
|
313
314
|
readOnly: tool.readOnly ?? !DOCDEX_WRITE_TOOLS.has(tool.name),
|
|
314
315
|
capability: tool.capability ?? docdexCapabilityFor(tool.name),
|
|
315
316
|
}));
|
|
316
|
-
export const createDocdexTools = (client, options = {}) => withDocdexMetadata(docdexToolDefinitions(client, options));
|
|
317
|
+
export const createDocdexTools = (client, options = {}) => withDocdexMetadata([...docdexToolDefinitions(client, options), ...continuityTools(client)]);
|
|
318
|
+
const continuityTools = (client) => {
|
|
319
|
+
const single = (name, description, key, call) => ({
|
|
320
|
+
name, description, inputSchema: { type: "object", properties: { [key]: { type: "string", minLength: 1, maxLength: 12000 } }, required: [key], additionalProperties: false },
|
|
321
|
+
handler: async (args) => toOutput(await call(args[key])),
|
|
322
|
+
});
|
|
323
|
+
return [
|
|
324
|
+
single("docdex_wakeup", "Read bounded continuity context for this repository and agent. Canonical goal and authorization remain authoritative.", "query", query => client.wakeup(query)),
|
|
325
|
+
single("docdex_conversation_search", "Find source-linked prior conversation records in this repository.", "query", query => client.conversationSearch(query)),
|
|
326
|
+
single("docdex_conversation_read", "Read a prior repository conversation by its returned session ID.", "sessionId", id => client.conversationRead(id)),
|
|
327
|
+
single("docdex_kg_query", "Inspect temporal knowledge-graph facts and provenance for this repository.", "query", query => client.knowledgeQuery(query)),
|
|
328
|
+
single("docdex_diary_write", "Save a concise durable handoff with the current goal, observed outcome and next action. Requires memory-write permission.", "content", content => client.diaryWrite(content)),
|
|
329
|
+
{ name: "docdex_diary_read", description: "Read the agent's recent durable repository handoffs.", inputSchema: { type: "object", properties: {}, additionalProperties: false }, handler: async () => toOutput(await client.diaryRead()) },
|
|
330
|
+
];
|
|
331
|
+
};
|
|
317
332
|
const docdexToolDefinitions = (client, options) => [
|
|
318
333
|
{
|
|
319
334
|
name: "docdex_health",
|
|
@@ -377,7 +392,7 @@ const docdexToolDefinitions = (client, options) => [
|
|
|
377
392
|
}
|
|
378
393
|
}
|
|
379
394
|
const webQuery = normalizeWebQuery(query);
|
|
380
|
-
if (!localAnswers && webQuery && !webResearchBlocked()) {
|
|
395
|
+
if (options.allowSearchWebFallback !== false && !localAnswers && webQuery && !webResearchBlocked()) {
|
|
381
396
|
try {
|
|
382
397
|
const web = await client.search(webQuery, { limit, forceWeb: true });
|
|
383
398
|
if (hasWebFindings(web)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileTools.d.ts","sourceRoot":"","sources":["../../../src/tools/filesystem/FileTools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"FileTools.d.ts","sourceRoot":"","sources":["../../../src/tools/filesystem/FileTools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA8EnE,eAAO,MAAM,eAAe,QAAO,cAAc,EAkGhD,CAAC"}
|