harness-engineering-agent 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -60
- package/dist/agent/harness-agent-capabilities.d.ts +4 -0
- package/dist/agent/harness-agent-capabilities.d.ts.map +1 -0
- package/dist/agent/harness-agent-capabilities.js +4 -0
- package/dist/agent/harness-agent-capabilities.js.map +1 -0
- package/dist/agent/harness-agent-capability-builders.d.ts +11 -0
- package/dist/agent/harness-agent-capability-builders.d.ts.map +1 -0
- package/dist/agent/harness-agent-capability-builders.js +57 -0
- package/dist/agent/harness-agent-capability-builders.js.map +1 -0
- package/dist/agent/harness-agent-capability-data.d.ts +3 -0
- package/dist/agent/harness-agent-capability-data.d.ts.map +1 -0
- package/dist/agent/harness-agent-capability-data.js +23 -0
- package/dist/agent/harness-agent-capability-data.js.map +1 -0
- package/dist/agent/harness-agent-capability-types.d.ts +50 -0
- package/dist/agent/harness-agent-capability-types.d.ts.map +1 -0
- package/dist/agent/harness-agent-capability-types.js +3 -0
- package/dist/agent/harness-agent-capability-types.js.map +1 -0
- package/dist/agent/harness-role-capability-directory-data.d.ts +3 -0
- package/dist/agent/harness-role-capability-directory-data.d.ts.map +1 -0
- package/dist/agent/harness-role-capability-directory-data.js +208 -0
- package/dist/agent/harness-role-capability-directory-data.js.map +1 -0
- package/dist/agent/harness-role-capability-directory.d.ts +43 -0
- package/dist/agent/harness-role-capability-directory.d.ts.map +1 -0
- package/dist/agent/harness-role-capability-directory.js +57 -0
- package/dist/agent/harness-role-capability-directory.js.map +1 -0
- package/dist/agent/index.d.ts +7 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +6 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/config/config-defaults.d.ts +22 -0
- package/dist/config/config-defaults.d.ts.map +1 -1
- package/dist/config/config-defaults.js +22 -0
- package/dist/config/config-defaults.js.map +1 -1
- package/dist/config/config-merge.d.ts.map +1 -1
- package/dist/config/config-merge.js +30 -0
- package/dist/config/config-merge.js.map +1 -1
- package/dist/config/config-schema.d.ts +59 -0
- package/dist/config/config-schema.d.ts.map +1 -1
- package/dist/config/config-schema.js +18 -1
- package/dist/config/config-schema.js.map +1 -1
- package/dist/config/config-types.d.ts +5 -1
- package/dist/config/config-types.d.ts.map +1 -1
- package/dist/config/harness-config.d.ts +2 -1
- package/dist/config/harness-config.d.ts.map +1 -1
- package/dist/config/harness-config.js +1 -0
- package/dist/config/harness-config.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/opencode-compatibility.d.ts +37 -0
- package/dist/config/opencode-compatibility.d.ts.map +1 -0
- package/dist/config/opencode-compatibility.js +99 -0
- package/dist/config/opencode-compatibility.js.map +1 -0
- package/dist/controller/agent-output.d.ts +1 -1
- package/dist/controller/agent-output.d.ts.map +1 -1
- package/dist/controller/agent-output.js +18 -1
- package/dist/controller/agent-output.js.map +1 -1
- package/dist/controller/agent-session-types.d.ts +56 -0
- package/dist/controller/agent-session-types.d.ts.map +1 -0
- package/dist/controller/agent-session-types.js +2 -0
- package/dist/controller/agent-session-types.js.map +1 -0
- package/dist/controller/agent-session-utils.d.ts +52 -0
- package/dist/controller/agent-session-utils.d.ts.map +1 -0
- package/dist/controller/agent-session-utils.js +118 -0
- package/dist/controller/agent-session-utils.js.map +1 -0
- package/dist/controller/agent-session.d.ts +2 -55
- package/dist/controller/agent-session.d.ts.map +1 -1
- package/dist/controller/agent-session.js +82 -129
- package/dist/controller/agent-session.js.map +1 -1
- package/dist/controller/contracts.d.ts +3 -2
- package/dist/controller/contracts.d.ts.map +1 -1
- package/dist/controller/contracts.js.map +1 -1
- package/dist/controller/evidence-factory.js +7 -1
- package/dist/controller/evidence-factory.js.map +1 -1
- package/dist/controller/failure-analysis.d.ts +12 -0
- package/dist/controller/failure-analysis.d.ts.map +1 -1
- package/dist/controller/failure-analysis.js +41 -0
- package/dist/controller/failure-analysis.js.map +1 -1
- package/dist/controller/failure-analyzer-schemas.d.ts +87 -0
- package/dist/controller/failure-analyzer-schemas.d.ts.map +1 -0
- package/dist/controller/failure-analyzer-schemas.js +117 -0
- package/dist/controller/failure-analyzer-schemas.js.map +1 -0
- package/dist/controller/graph-validator.js +18 -4
- package/dist/controller/graph-validator.js.map +1 -1
- package/dist/controller/index.d.ts +7 -2
- package/dist/controller/index.d.ts.map +1 -1
- package/dist/controller/index.js +4 -1
- package/dist/controller/index.js.map +1 -1
- package/dist/controller/repair-loop.d.ts +1 -1
- package/dist/controller/repair-loop.d.ts.map +1 -1
- package/dist/controller/repair-loop.js +28 -0
- package/dist/controller/repair-loop.js.map +1 -1
- package/dist/controller/report-factory.d.ts.map +1 -1
- package/dist/controller/report-factory.js +49 -21
- package/dist/controller/report-factory.js.map +1 -1
- package/dist/controller/role-prompts.d.ts +2 -1
- package/dist/controller/role-prompts.d.ts.map +1 -1
- package/dist/controller/role-prompts.js +3 -9
- package/dist/controller/role-prompts.js.map +1 -1
- package/dist/controller/run-acceptance.d.ts +17 -0
- package/dist/controller/run-acceptance.d.ts.map +1 -0
- package/dist/controller/run-acceptance.js +179 -0
- package/dist/controller/run-acceptance.js.map +1 -0
- package/dist/controller/run-controller.d.ts.map +1 -1
- package/dist/controller/run-controller.js +244 -22
- package/dist/controller/run-controller.js.map +1 -1
- package/dist/controller/session-tool-authorization.d.ts +14 -0
- package/dist/controller/session-tool-authorization.d.ts.map +1 -0
- package/dist/controller/session-tool-authorization.js +88 -0
- package/dist/controller/session-tool-authorization.js.map +1 -0
- package/dist/controller/task-agent-output.d.ts +13 -2
- package/dist/controller/task-agent-output.d.ts.map +1 -1
- package/dist/controller/task-agent-output.js +58 -1
- package/dist/controller/task-agent-output.js.map +1 -1
- package/dist/controller/task-agent-schemas.d.ts +745 -26
- package/dist/controller/task-agent-schemas.d.ts.map +1 -1
- package/dist/controller/task-agent-schemas.js +70 -21
- package/dist/controller/task-agent-schemas.js.map +1 -1
- package/dist/controller/task-executor.d.ts +1 -1
- package/dist/controller/task-executor.d.ts.map +1 -1
- package/dist/controller/task-executor.js +269 -105
- package/dist/controller/task-executor.js.map +1 -1
- package/dist/doctor/cli.d.ts +3 -0
- package/dist/doctor/cli.d.ts.map +1 -0
- package/dist/doctor/cli.js +10 -0
- package/dist/doctor/cli.js.map +1 -0
- package/dist/doctor/index.d.ts +7 -0
- package/dist/doctor/index.d.ts.map +1 -0
- package/dist/doctor/index.js +16 -0
- package/dist/doctor/index.js.map +1 -0
- package/dist/doctor/local-mcp-probe.d.ts +3 -0
- package/dist/doctor/local-mcp-probe.d.ts.map +1 -0
- package/dist/doctor/local-mcp-probe.js +151 -0
- package/dist/doctor/local-mcp-probe.js.map +1 -0
- package/dist/doctor/opencode-config.d.ts +43 -0
- package/dist/doctor/opencode-config.d.ts.map +1 -0
- package/dist/doctor/opencode-config.js +103 -0
- package/dist/doctor/opencode-config.js.map +1 -0
- package/dist/doctor/run-harness-doctor.d.ts +23 -0
- package/dist/doctor/run-harness-doctor.d.ts.map +1 -0
- package/dist/doctor/run-harness-doctor.js +176 -0
- package/dist/doctor/run-harness-doctor.js.map +1 -0
- package/dist/doctor/types.d.ts +69 -0
- package/dist/doctor/types.d.ts.map +1 -0
- package/dist/doctor/types.js +8 -0
- package/dist/doctor/types.js.map +1 -0
- package/dist/domain/acceptance-criteria.d.ts +9 -0
- package/dist/domain/acceptance-criteria.d.ts.map +1 -0
- package/dist/domain/acceptance-criteria.js +38 -0
- package/dist/domain/acceptance-criteria.js.map +1 -0
- package/dist/domain/context-package.d.ts +43 -0
- package/dist/domain/context-package.d.ts.map +1 -0
- package/dist/domain/context-package.js +54 -0
- package/dist/domain/context-package.js.map +1 -0
- package/dist/domain/evidence.d.ts +1 -0
- package/dist/domain/evidence.d.ts.map +1 -1
- package/dist/domain/evidence.js +1 -2
- package/dist/domain/evidence.js.map +1 -1
- package/dist/domain/index.d.ts +14 -4
- package/dist/domain/index.d.ts.map +1 -1
- package/dist/domain/index.js +7 -2
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/plan-artifacts.d.ts +170 -0
- package/dist/domain/plan-artifacts.d.ts.map +1 -0
- package/dist/domain/plan-artifacts.js +187 -0
- package/dist/domain/plan-artifacts.js.map +1 -0
- package/dist/domain/project-context.d.ts +10 -0
- package/dist/domain/project-context.d.ts.map +1 -0
- package/dist/domain/project-context.js +11 -0
- package/dist/domain/project-context.js.map +1 -0
- package/dist/domain/report.d.ts +608 -11
- package/dist/domain/report.d.ts.map +1 -1
- package/dist/domain/report.js +6 -4
- package/dist/domain/report.js.map +1 -1
- package/dist/domain/requirement.d.ts +22 -2
- package/dist/domain/requirement.d.ts.map +1 -1
- package/dist/domain/requirement.js +26 -3
- package/dist/domain/requirement.js.map +1 -1
- package/dist/domain/run-acceptance.d.ts +33 -0
- package/dist/domain/run-acceptance.d.ts.map +1 -0
- package/dist/domain/run-acceptance.js +29 -0
- package/dist/domain/run-acceptance.js.map +1 -0
- package/dist/domain/run.d.ts +596 -7
- package/dist/domain/run.d.ts.map +1 -1
- package/dist/domain/run.js +58 -0
- package/dist/domain/run.js.map +1 -1
- package/dist/domain/shared.d.ts +40 -2
- package/dist/domain/shared.d.ts.map +1 -1
- package/dist/domain/shared.js +26 -0
- package/dist/domain/shared.js.map +1 -1
- package/dist/domain/task-review.d.ts +57 -0
- package/dist/domain/task-review.d.ts.map +1 -0
- package/dist/domain/task-review.js +63 -0
- package/dist/domain/task-review.js.map +1 -0
- package/dist/domain/task.d.ts +24 -2
- package/dist/domain/task.d.ts.map +1 -1
- package/dist/domain/task.js +20 -12
- package/dist/domain/task.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/plugin/create-harness-plugin.d.ts +4 -28
- package/dist/plugin/create-harness-plugin.d.ts.map +1 -1
- package/dist/plugin/create-harness-plugin.js +33 -166
- package/dist/plugin/create-harness-plugin.js.map +1 -1
- package/dist/plugin/harness-agent-config.d.ts +7 -0
- package/dist/plugin/harness-agent-config.d.ts.map +1 -1
- package/dist/plugin/harness-agent-config.js +72 -118
- package/dist/plugin/harness-agent-config.js.map +1 -1
- package/dist/plugin/harness-chat-protocol.d.ts.map +1 -1
- package/dist/plugin/harness-chat-protocol.js +29 -6
- package/dist/plugin/harness-chat-protocol.js.map +1 -1
- package/dist/plugin/harness-plugin-identifiers.d.ts +5 -0
- package/dist/plugin/harness-plugin-identifiers.d.ts.map +1 -0
- package/dist/plugin/harness-plugin-identifiers.js +24 -0
- package/dist/plugin/harness-plugin-identifiers.js.map +1 -0
- package/dist/plugin/harness-plugin-runtime.d.ts +64 -0
- package/dist/plugin/harness-plugin-runtime.d.ts.map +1 -0
- package/dist/plugin/harness-plugin-runtime.js +125 -0
- package/dist/plugin/harness-plugin-runtime.js.map +1 -0
- package/dist/plugin/harness-plugin-scheduler.d.ts +16 -0
- package/dist/plugin/harness-plugin-scheduler.d.ts.map +1 -0
- package/dist/plugin/harness-plugin-scheduler.js +51 -0
- package/dist/plugin/harness-plugin-scheduler.js.map +1 -0
- package/dist/plugin/harness-requirement.d.ts +1 -1
- package/dist/plugin/harness-requirement.d.ts.map +1 -1
- package/dist/plugin/harness-requirement.js +2 -3
- package/dist/plugin/harness-requirement.js.map +1 -1
- package/dist/session/contracts.d.ts +9 -0
- package/dist/session/contracts.d.ts.map +1 -1
- package/dist/session/contracts.js.map +1 -1
- package/dist/session/fake-session-adapter.d.ts.map +1 -1
- package/dist/session/fake-session-adapter.js +1 -0
- package/dist/session/fake-session-adapter.js.map +1 -1
- package/dist/session/index.d.ts +1 -1
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js.map +1 -1
- package/dist/session/opencode-session-adapter.d.ts +2 -1
- package/dist/session/opencode-session-adapter.d.ts.map +1 -1
- package/dist/session/opencode-session-adapter.js +7 -2
- package/dist/session/opencode-session-adapter.js.map +1 -1
- package/dist/session/opencode-session-prompts.d.ts +2 -10
- package/dist/session/opencode-session-prompts.d.ts.map +1 -1
- package/dist/session/opencode-session-prompts.js +7 -9
- package/dist/session/opencode-session-prompts.js.map +1 -1
- package/dist/store/run-event.d.ts +596 -7
- package/dist/store/run-event.d.ts.map +1 -1
- package/dist/tools/harness-research-tools.d.ts +22 -0
- package/dist/tools/harness-research-tools.d.ts.map +1 -1
- package/dist/tools/harness-research-tools.js +173 -64
- package/dist/tools/harness-research-tools.js.map +1 -1
- package/dist/tools/harness-tool-capabilities.d.ts +342 -0
- package/dist/tools/harness-tool-capabilities.d.ts.map +1 -0
- package/dist/tools/harness-tool-capabilities.js +170 -0
- package/dist/tools/harness-tool-capabilities.js.map +1 -0
- package/dist/verification/command-policy.d.ts.map +1 -1
- package/dist/verification/command-policy.js +2 -2
- package/dist/verification/command-policy.js.map +1 -1
- package/dist/workspace/collect-project-context.d.ts +3 -0
- package/dist/workspace/collect-project-context.d.ts.map +1 -0
- package/dist/workspace/collect-project-context.js +92 -0
- package/dist/workspace/collect-project-context.js.map +1 -0
- package/dist/workspace/index.d.ts +1 -0
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/index.js +1 -0
- package/dist/workspace/index.js.map +1 -1
- package/package.json +6 -1
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { AgentResultSchema } from "../domain/index.js";
|
|
2
|
+
import { normalizeVerificationCommand } from "../verification/command-policy.js";
|
|
2
3
|
import { VerificationExecutionStatus } from "../verification/index.js";
|
|
3
4
|
import { createGitWorkspaceAdapter, createGitWorktreeAdapter } from "../workspace/index.js";
|
|
4
5
|
import { createEvidence } from "./evidence-factory.js";
|
|
5
6
|
import { resolveFailureAnalysis } from "./failure-analysis.js";
|
|
6
|
-
import {
|
|
7
|
+
import { createContextGapFailure, createImplementationFailure, createMergeConflictFailure, createModelFailure, createScopeDriftFailure, createVerificationEnvironmentFailure, } from "./failure-factory.js";
|
|
7
8
|
import { orderTasks } from "./graph-validator.js";
|
|
8
9
|
import { runRepairLoop } from "./repair-loop.js";
|
|
10
|
+
import { finalizeRunAcceptance } from "./run-acceptance.js";
|
|
9
11
|
import { consumeBudget, parsePlannedRun, RunBudgetExceededError, withParts, withPlannedStatus, withTask, } from "./run-state.js";
|
|
10
|
-
import {
|
|
12
|
+
import { readFailureAnalyzerOutput, readTaskReviewOutput, readWorkerOutput, } from "./task-agent-output.js";
|
|
11
13
|
import { isAllowedPath } from "./task-paths.js";
|
|
12
14
|
import { persistTaskFailed, persistTaskRetry } from "./task-retry.js";
|
|
13
15
|
import { createWorktreeScheduler } from "./worktree-scheduler.js";
|
|
@@ -29,11 +31,99 @@ export const createTaskExecutor = (input) => {
|
|
|
29
31
|
case "failed":
|
|
30
32
|
case "completed":
|
|
31
33
|
case "evidence_gap":
|
|
34
|
+
case "blocked":
|
|
32
35
|
return parsePlannedRun(latest);
|
|
33
36
|
default:
|
|
34
37
|
return assertNever(latest);
|
|
35
38
|
}
|
|
36
39
|
};
|
|
40
|
+
const runDiagnosticProbe = async (params) => {
|
|
41
|
+
try {
|
|
42
|
+
normalizeVerificationCommand({
|
|
43
|
+
workspaceRoot: input.options.workingDirectory,
|
|
44
|
+
command: params.probe.verificationCommand,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (!(error instanceof Error)) {
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
kind: "failed",
|
|
53
|
+
failure: createImplementationFailure({
|
|
54
|
+
failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-diagnostic-probe-policy`),
|
|
55
|
+
runId: params.run.runId,
|
|
56
|
+
taskId: params.task.taskId,
|
|
57
|
+
summary: "Failure analyzer proposed an invalid diagnostic probe.",
|
|
58
|
+
detail: error.message,
|
|
59
|
+
recoveryPlan: "Reject the probe and require a minimal read-only verification command.",
|
|
60
|
+
}),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
await input.writer.persist(withPlannedStatus(params.run, "verifying"), input.writer.createEvent(params.run.runId, "task.diagnostic.probe.started", {
|
|
64
|
+
taskId: params.task.taskId,
|
|
65
|
+
attempt: params.attempt,
|
|
66
|
+
commandName: params.probe.verificationCommand.name,
|
|
67
|
+
}));
|
|
68
|
+
let verificationResult;
|
|
69
|
+
try {
|
|
70
|
+
verificationResult = await input.options.verificationRunner.run({
|
|
71
|
+
verificationCommands: [params.probe.verificationCommand],
|
|
72
|
+
defaultWorkingDirectory: input.options.workingDirectory,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (!(error instanceof Error)) {
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
kind: "failed",
|
|
81
|
+
failure: createVerificationEnvironmentFailure({
|
|
82
|
+
failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-diagnostic-probe-environment`),
|
|
83
|
+
runId: params.run.runId,
|
|
84
|
+
taskId: params.task.taskId,
|
|
85
|
+
commandName: params.probe.verificationCommand.name,
|
|
86
|
+
detail: error.message,
|
|
87
|
+
}),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (verificationResult.records.length === 0) {
|
|
91
|
+
return {
|
|
92
|
+
kind: "failed",
|
|
93
|
+
failure: createContextGapFailure({
|
|
94
|
+
failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-diagnostic-probe-empty`),
|
|
95
|
+
runId: params.run.runId,
|
|
96
|
+
taskId: params.task.taskId,
|
|
97
|
+
relatedEvidenceIds: [],
|
|
98
|
+
summary: "Diagnostic probe produced no verification records.",
|
|
99
|
+
detail: params.probe.summary,
|
|
100
|
+
recoveryPlan: "Capture a real read-only verification record before confirming the root cause.",
|
|
101
|
+
missingContext: ["diagnostic-probe-record"],
|
|
102
|
+
}),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const evidence = verificationResult.records.map((record, index) => createEvidence({
|
|
106
|
+
ids: input.options.ids,
|
|
107
|
+
runId: params.run.runId,
|
|
108
|
+
task: params.task,
|
|
109
|
+
record,
|
|
110
|
+
label: `${params.task.taskId}-${params.attempt}-diagnostic-probe-${index}`,
|
|
111
|
+
kind: "verification",
|
|
112
|
+
summary: `diagnostic-probe:${record.command.name}`,
|
|
113
|
+
}));
|
|
114
|
+
const nextRun = withParts(params.run, {
|
|
115
|
+
evidence: [...params.run.evidence, ...evidence],
|
|
116
|
+
failures: params.run.failures,
|
|
117
|
+
agentResults: params.run.agentResults,
|
|
118
|
+
workspace: params.run.workspace,
|
|
119
|
+
});
|
|
120
|
+
await input.writer.persist(withPlannedStatus(nextRun, "executing"), input.writer.createEvent(params.run.runId, "task.diagnostic.probe.completed", {
|
|
121
|
+
taskId: params.task.taskId,
|
|
122
|
+
attempt: params.attempt,
|
|
123
|
+
evidenceIds: evidence.map((item) => item.evidenceId),
|
|
124
|
+
}));
|
|
125
|
+
return { kind: "approved", evidence };
|
|
126
|
+
};
|
|
37
127
|
const analyzeFailure = async (params) => {
|
|
38
128
|
const analysisResult = await readFailureAnalyzerOutput({
|
|
39
129
|
input,
|
|
@@ -70,6 +160,50 @@ export const createTaskExecutor = (input) => {
|
|
|
70
160
|
evidence: params.evidence,
|
|
71
161
|
analysis: analysisResult.output,
|
|
72
162
|
});
|
|
163
|
+
if (analysisResult.output.action === "probe") {
|
|
164
|
+
const probeResult = await runDiagnosticProbe({
|
|
165
|
+
run: params.run,
|
|
166
|
+
task: params.task,
|
|
167
|
+
attempt: params.attempt,
|
|
168
|
+
probe: analysisResult.output.diagnosticProbe,
|
|
169
|
+
});
|
|
170
|
+
if (probeResult.kind === "failed") {
|
|
171
|
+
const failedRun = withParts(withTask(params.run, { ...params.task, status: "failed" }), {
|
|
172
|
+
evidence: params.run.evidence,
|
|
173
|
+
failures: [
|
|
174
|
+
...params.run.failures,
|
|
175
|
+
params.failure,
|
|
176
|
+
resolution.failure,
|
|
177
|
+
probeResult.failure,
|
|
178
|
+
],
|
|
179
|
+
agentResults: [...params.run.agentResults, resolution.result],
|
|
180
|
+
workspace: params.run.workspace,
|
|
181
|
+
});
|
|
182
|
+
await input.writer.persist(withPlannedStatus(failedRun, "failed"), input.writer.createEvent(params.run.runId, "task.failed", {
|
|
183
|
+
taskId: params.task.taskId,
|
|
184
|
+
attempt: params.attempt,
|
|
185
|
+
failureId: probeResult.failure.failureId,
|
|
186
|
+
}));
|
|
187
|
+
return {
|
|
188
|
+
run: withPlannedStatus(failedRun, "failed"),
|
|
189
|
+
repairRequested: false,
|
|
190
|
+
failure: probeResult.failure,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
const probeRun = withParts(params.run, {
|
|
194
|
+
evidence: [...params.run.evidence, ...probeResult.evidence],
|
|
195
|
+
failures: params.run.failures,
|
|
196
|
+
agentResults: params.run.agentResults,
|
|
197
|
+
workspace: params.run.workspace,
|
|
198
|
+
});
|
|
199
|
+
return analyzeFailure({
|
|
200
|
+
run: probeRun,
|
|
201
|
+
task: params.task,
|
|
202
|
+
attempt: params.attempt,
|
|
203
|
+
failure: params.failure,
|
|
204
|
+
evidence: [...params.evidence, ...probeResult.evidence],
|
|
205
|
+
});
|
|
206
|
+
}
|
|
73
207
|
const nextTask = { ...params.task, status: resolution.taskStatus };
|
|
74
208
|
const nextRun = withParts(withTask(params.run, nextTask), {
|
|
75
209
|
evidence: params.run.evidence,
|
|
@@ -84,13 +218,14 @@ export const createTaskExecutor = (input) => {
|
|
|
84
218
|
failure: resolution.failure,
|
|
85
219
|
};
|
|
86
220
|
};
|
|
87
|
-
const
|
|
88
|
-
const verifierOutput = await
|
|
221
|
+
const reviewTask = async (params) => {
|
|
222
|
+
const verifierOutput = await readTaskReviewOutput({
|
|
89
223
|
input,
|
|
90
224
|
run: params.run,
|
|
91
225
|
task: params.task,
|
|
92
226
|
attempt: params.attempt,
|
|
93
227
|
evidence: params.evidence,
|
|
228
|
+
changedPaths: params.changedPaths,
|
|
94
229
|
});
|
|
95
230
|
if (verifierOutput.kind === "failed") {
|
|
96
231
|
const resolution = await analyzeFailure({
|
|
@@ -102,38 +237,6 @@ export const createTaskExecutor = (input) => {
|
|
|
102
237
|
});
|
|
103
238
|
return resolution.run;
|
|
104
239
|
}
|
|
105
|
-
if (verifierOutput.output.status !== "passed") {
|
|
106
|
-
const verifierFailure = verifierOutput.output.status === "evidence_gap"
|
|
107
|
-
? createContextGapFailure({
|
|
108
|
-
failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-verifier-evidence-gap`),
|
|
109
|
-
runId: params.run.runId,
|
|
110
|
-
taskId: params.task.taskId,
|
|
111
|
-
relatedEvidenceIds: params.evidence.map((item) => item.evidenceId),
|
|
112
|
-
summary: verifierOutput.output.summary,
|
|
113
|
-
detail: verifierOutput.output.missingEvidenceKinds.join(", "),
|
|
114
|
-
recoveryPlan: "Collect the missing verification evidence before retrying.",
|
|
115
|
-
missingContext: verifierOutput.output.missingEvidenceKinds,
|
|
116
|
-
})
|
|
117
|
-
: createImplementationFailure({
|
|
118
|
-
failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-verifier`),
|
|
119
|
-
runId: params.run.runId,
|
|
120
|
-
taskId: params.task.taskId,
|
|
121
|
-
...(params.evidence[0] === undefined
|
|
122
|
-
? {}
|
|
123
|
-
: { failingEvidenceId: params.evidence[0].evidenceId }),
|
|
124
|
-
summary: verifierOutput.output.summary,
|
|
125
|
-
detail: verifierOutput.output.status,
|
|
126
|
-
recoveryPlan: "Retry the task with fresh evidence.",
|
|
127
|
-
});
|
|
128
|
-
const resolution = await analyzeFailure({
|
|
129
|
-
run: params.run,
|
|
130
|
-
task: params.task,
|
|
131
|
-
attempt: params.attempt,
|
|
132
|
-
failure: verifierFailure,
|
|
133
|
-
evidence: params.evidence,
|
|
134
|
-
});
|
|
135
|
-
return resolution.run;
|
|
136
|
-
}
|
|
137
240
|
const workerResult = AgentResultSchema.parse({
|
|
138
241
|
schemaVersion: "1.0.0",
|
|
139
242
|
resultId: input.options.ids.createAgentResultId(`worker-${params.task.taskId}-${params.attempt}`),
|
|
@@ -147,7 +250,7 @@ export const createTaskExecutor = (input) => {
|
|
|
147
250
|
});
|
|
148
251
|
const verifierResult = AgentResultSchema.parse({
|
|
149
252
|
schemaVersion: "1.0.0",
|
|
150
|
-
resultId: input.options.ids.createAgentResultId(`
|
|
253
|
+
resultId: input.options.ids.createAgentResultId(`task-review-${params.task.taskId}-${params.attempt}`),
|
|
151
254
|
runId: params.run.runId,
|
|
152
255
|
taskId: params.task.taskId,
|
|
153
256
|
role: "verifier",
|
|
@@ -156,71 +259,58 @@ export const createTaskExecutor = (input) => {
|
|
|
156
259
|
evidenceIds: params.evidence.map((item) => item.evidenceId),
|
|
157
260
|
changedPaths: [],
|
|
158
261
|
});
|
|
159
|
-
const
|
|
262
|
+
const reviewedRun = withParts(params.run, {
|
|
160
263
|
evidence: params.run.evidence,
|
|
161
264
|
failures: params.run.failures,
|
|
162
265
|
agentResults: [...params.run.agentResults, workerResult, verifierResult],
|
|
163
266
|
workspace: params.run.workspace,
|
|
164
267
|
});
|
|
165
|
-
const
|
|
166
|
-
|
|
268
|
+
const runWithTaskReview = parsePlannedRun({
|
|
269
|
+
...reviewedRun,
|
|
270
|
+
taskReviews: [...reviewedRun.taskReviews, verifierOutput.output.taskReview],
|
|
271
|
+
});
|
|
272
|
+
const reviewing = withPlannedStatus(runWithTaskReview, "verifying");
|
|
273
|
+
await input.writer.persist(reviewing, input.writer.createEvent(params.run.runId, "task.review.started", {
|
|
167
274
|
taskId: params.task.taskId,
|
|
168
275
|
attempt: params.attempt,
|
|
169
276
|
}));
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
run: accepting,
|
|
173
|
-
task: params.task,
|
|
174
|
-
attempt: params.attempt,
|
|
175
|
-
evidence: params.evidence,
|
|
176
|
-
});
|
|
177
|
-
if (acceptanceOutput.kind === "failed") {
|
|
178
|
-
const resolution = await analyzeFailure({
|
|
179
|
-
run: accepting,
|
|
180
|
-
task: params.task,
|
|
181
|
-
attempt: params.attempt,
|
|
182
|
-
failure: acceptanceOutput.failure,
|
|
183
|
-
evidence: params.evidence,
|
|
184
|
-
});
|
|
185
|
-
return resolution.run;
|
|
186
|
-
}
|
|
187
|
-
if (acceptanceOutput.output.status !== "accepted") {
|
|
188
|
-
const acceptanceFailure = acceptanceOutput.output.status === "evidence_gap"
|
|
277
|
+
if (verifierOutput.output.status !== "passed") {
|
|
278
|
+
const taskReviewFailure = verifierOutput.output.status === "evidence_gap"
|
|
189
279
|
? createContextGapFailure({
|
|
190
|
-
failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-
|
|
280
|
+
failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-task-review-evidence-gap`),
|
|
191
281
|
runId: params.run.runId,
|
|
192
282
|
taskId: params.task.taskId,
|
|
193
283
|
relatedEvidenceIds: params.evidence.map((item) => item.evidenceId),
|
|
194
|
-
summary:
|
|
195
|
-
detail:
|
|
196
|
-
recoveryPlan: "Collect the missing
|
|
197
|
-
missingContext:
|
|
284
|
+
summary: verifierOutput.output.summary,
|
|
285
|
+
detail: verifierOutput.output.missingEvidenceKinds.join(", "),
|
|
286
|
+
recoveryPlan: "Collect the missing task review evidence before completing.",
|
|
287
|
+
missingContext: verifierOutput.output.missingEvidenceKinds,
|
|
198
288
|
})
|
|
199
289
|
: params.evidence[0] === undefined
|
|
200
290
|
? createContextGapFailure({
|
|
201
|
-
failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-
|
|
291
|
+
failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-task-review-missing-evidence`),
|
|
202
292
|
runId: params.run.runId,
|
|
203
293
|
taskId: params.task.taskId,
|
|
204
294
|
relatedEvidenceIds: [],
|
|
205
|
-
summary:
|
|
206
|
-
detail: "
|
|
207
|
-
recoveryPlan: "Capture real deterministic evidence before processing
|
|
208
|
-
missingContext: ["
|
|
295
|
+
summary: verifierOutput.output.summary,
|
|
296
|
+
detail: "TaskReview reported failed but no deterministic evidence exists.",
|
|
297
|
+
recoveryPlan: "Capture real deterministic evidence before processing task review failure.",
|
|
298
|
+
missingContext: ["task-review-evidence"],
|
|
209
299
|
})
|
|
210
|
-
:
|
|
211
|
-
failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-
|
|
300
|
+
: createImplementationFailure({
|
|
301
|
+
failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-task-review`),
|
|
212
302
|
runId: params.run.runId,
|
|
213
303
|
taskId: params.task.taskId,
|
|
214
304
|
failingEvidenceId: params.evidence[0].evidenceId,
|
|
215
|
-
summary:
|
|
216
|
-
detail:
|
|
217
|
-
recoveryPlan: "Address the
|
|
305
|
+
summary: verifierOutput.output.summary,
|
|
306
|
+
detail: verifierOutput.output.taskReview?.summary ?? verifierOutput.output.status,
|
|
307
|
+
recoveryPlan: "Address the task review findings before completing the task.",
|
|
218
308
|
});
|
|
219
309
|
const resolution = await analyzeFailure({
|
|
220
|
-
run:
|
|
310
|
+
run: reviewing,
|
|
221
311
|
task: params.task,
|
|
222
312
|
attempt: params.attempt,
|
|
223
|
-
failure:
|
|
313
|
+
failure: taskReviewFailure,
|
|
224
314
|
evidence: params.evidence,
|
|
225
315
|
});
|
|
226
316
|
return resolution.run;
|
|
@@ -233,22 +323,11 @@ export const createTaskExecutor = (input) => {
|
|
|
233
323
|
...params.evidence.map((item) => item.evidenceId),
|
|
234
324
|
],
|
|
235
325
|
};
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
role: "acceptance",
|
|
242
|
-
status: "completed",
|
|
243
|
-
summary: acceptanceOutput.output.summary,
|
|
244
|
-
evidenceIds: params.evidence.map((item) => item.evidenceId),
|
|
245
|
-
changedPaths: [],
|
|
246
|
-
});
|
|
247
|
-
const currentRun = withPlannedStatus(withParts(withTask(accepting, completedTask), {
|
|
248
|
-
evidence: accepting.evidence,
|
|
249
|
-
failures: accepting.failures,
|
|
250
|
-
agentResults: [...accepting.agentResults, acceptanceResult],
|
|
251
|
-
workspace: accepting.workspace,
|
|
326
|
+
const currentRun = withPlannedStatus(withParts(withTask(reviewing, completedTask), {
|
|
327
|
+
evidence: reviewing.evidence,
|
|
328
|
+
failures: reviewing.failures,
|
|
329
|
+
agentResults: reviewing.agentResults,
|
|
330
|
+
workspace: reviewing.workspace,
|
|
252
331
|
}), "executing");
|
|
253
332
|
await input.writer.persist(currentRun, input.writer.createEvent(params.run.runId, "task.completed", {
|
|
254
333
|
taskId: params.task.taskId,
|
|
@@ -284,7 +363,7 @@ export const createTaskExecutor = (input) => {
|
|
|
284
363
|
if (repaired.kind === "terminal") {
|
|
285
364
|
return repaired.run;
|
|
286
365
|
}
|
|
287
|
-
return
|
|
366
|
+
return reviewTask({
|
|
288
367
|
run: repaired.run,
|
|
289
368
|
task: params.task,
|
|
290
369
|
attempt: params.attempt,
|
|
@@ -356,12 +435,16 @@ export const createTaskExecutor = (input) => {
|
|
|
356
435
|
taskId: task.taskId,
|
|
357
436
|
attempt,
|
|
358
437
|
}));
|
|
438
|
+
const taskVerificationCommands = task.verificationPlan.filter((command) => command.scope !== "integration");
|
|
359
439
|
let verificationResult;
|
|
360
440
|
try {
|
|
361
|
-
verificationResult =
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
441
|
+
verificationResult =
|
|
442
|
+
taskVerificationCommands.length === 0
|
|
443
|
+
? { records: [], stoppedEarly: false }
|
|
444
|
+
: await input.options.verificationRunner.run({
|
|
445
|
+
verificationCommands: taskVerificationCommands,
|
|
446
|
+
defaultWorkingDirectory: executionCwd,
|
|
447
|
+
});
|
|
365
448
|
}
|
|
366
449
|
catch (error) {
|
|
367
450
|
if (!(error instanceof Error)) {
|
|
@@ -371,7 +454,7 @@ export const createTaskExecutor = (input) => {
|
|
|
371
454
|
failureId: input.options.ids.createFailureId(`${task.taskId}-${attempt}-verification-environment`),
|
|
372
455
|
runId: run.runId,
|
|
373
456
|
taskId: task.taskId,
|
|
374
|
-
commandName:
|
|
457
|
+
commandName: taskVerificationCommands[0]?.name ?? "verification",
|
|
375
458
|
detail: error.message,
|
|
376
459
|
});
|
|
377
460
|
}
|
|
@@ -449,7 +532,7 @@ export const createTaskExecutor = (input) => {
|
|
|
449
532
|
});
|
|
450
533
|
}
|
|
451
534
|
}
|
|
452
|
-
else if (verificationResult.records.length === 0) {
|
|
535
|
+
else if (verificationResult.records.length === 0 && taskVerificationCommands.length > 0) {
|
|
453
536
|
lastFailure = createContextGapFailure({
|
|
454
537
|
failureId: input.options.ids.createFailureId(`${task.taskId}-${attempt}-verification-empty`),
|
|
455
538
|
runId: run.runId,
|
|
@@ -488,7 +571,7 @@ export const createTaskExecutor = (input) => {
|
|
|
488
571
|
record,
|
|
489
572
|
label: `${task.taskId}-${attempt}-${index}`,
|
|
490
573
|
changedPaths: workerOutput.output.changedPaths,
|
|
491
|
-
acceptanceCriterionIds:
|
|
574
|
+
acceptanceCriterionIds: [],
|
|
492
575
|
}));
|
|
493
576
|
currentRun = withParts(currentRun, {
|
|
494
577
|
evidence: [...currentRun.evidence, ...evidence],
|
|
@@ -528,12 +611,15 @@ export const createTaskExecutor = (input) => {
|
|
|
528
611
|
}
|
|
529
612
|
}
|
|
530
613
|
else {
|
|
531
|
-
const
|
|
614
|
+
const reconciledChangedPaths = currentRun.workspace.git.mode === "git"
|
|
615
|
+
? currentRun.workspace.git.harnessChangedPaths.filter((path) => task.allowedPaths.some((allowedPath) => path === allowedPath || path.startsWith(`${allowedPath}/`)))
|
|
616
|
+
: workerOutput.output.changedPaths;
|
|
617
|
+
const finalized = await reviewTask({
|
|
532
618
|
run: currentRun,
|
|
533
619
|
task,
|
|
534
620
|
attempt,
|
|
535
621
|
evidence,
|
|
536
|
-
changedPaths:
|
|
622
|
+
changedPaths: reconciledChangedPaths,
|
|
537
623
|
});
|
|
538
624
|
if (finalized.status !== "executing") {
|
|
539
625
|
return finalized;
|
|
@@ -596,10 +682,89 @@ export const createTaskExecutor = (input) => {
|
|
|
596
682
|
return currentRun;
|
|
597
683
|
}
|
|
598
684
|
}
|
|
599
|
-
|
|
600
|
-
|
|
685
|
+
currentRun = await runIntegrationVerification(currentRun);
|
|
686
|
+
const runAcceptanceResult = await finalizeRunAcceptance({
|
|
687
|
+
options: input.options,
|
|
688
|
+
runtime: input.runtime,
|
|
689
|
+
run: currentRun,
|
|
690
|
+
});
|
|
691
|
+
const completed = withPlannedStatus(withParts(parsePlannedRun({
|
|
692
|
+
...currentRun,
|
|
693
|
+
runAcceptance: runAcceptanceResult.runAcceptance,
|
|
694
|
+
}), {
|
|
695
|
+
evidence: currentRun.evidence,
|
|
696
|
+
failures: runAcceptanceResult.failure === undefined
|
|
697
|
+
? currentRun.failures
|
|
698
|
+
: [...currentRun.failures, runAcceptanceResult.failure],
|
|
699
|
+
agentResults: runAcceptanceResult.agentResult === undefined
|
|
700
|
+
? currentRun.agentResults
|
|
701
|
+
: [...currentRun.agentResults, runAcceptanceResult.agentResult],
|
|
702
|
+
workspace: currentRun.workspace,
|
|
703
|
+
}), runAcceptanceResult.status);
|
|
704
|
+
await input.writer.persist(completed, input.writer.createEvent(completed.runId, "run.completed", { status: completed.status }));
|
|
601
705
|
return completed;
|
|
602
706
|
};
|
|
707
|
+
const runIntegrationVerification = async (run) => {
|
|
708
|
+
const commands = run.taskGraph.tasks.flatMap((task) => task.verificationPlan.filter((command) => command.scope === "integration"));
|
|
709
|
+
if (commands.length === 0)
|
|
710
|
+
return run;
|
|
711
|
+
const task = run.taskGraph.tasks.at(-1);
|
|
712
|
+
if (task === undefined)
|
|
713
|
+
return run;
|
|
714
|
+
try {
|
|
715
|
+
const result = await input.options.verificationRunner.run({
|
|
716
|
+
verificationCommands: commands,
|
|
717
|
+
defaultWorkingDirectory: input.options.workingDirectory,
|
|
718
|
+
});
|
|
719
|
+
if (result.records.length === 0 ||
|
|
720
|
+
result.records.some((record) => record.status !== VerificationExecutionStatus.passed)) {
|
|
721
|
+
return persistIntegrationVerificationFailure(run, task, "integration verification failed");
|
|
722
|
+
}
|
|
723
|
+
const evidence = result.records.map((record, index) => createEvidence({
|
|
724
|
+
ids: input.options.ids,
|
|
725
|
+
runId: run.runId,
|
|
726
|
+
task,
|
|
727
|
+
record,
|
|
728
|
+
label: `integration-${task.taskId}-${index}`,
|
|
729
|
+
changedPaths: [],
|
|
730
|
+
acceptanceCriterionIds: [],
|
|
731
|
+
}));
|
|
732
|
+
const verified = withParts(run, {
|
|
733
|
+
evidence: [...run.evidence, ...evidence],
|
|
734
|
+
failures: run.failures,
|
|
735
|
+
agentResults: run.agentResults,
|
|
736
|
+
workspace: run.workspace,
|
|
737
|
+
});
|
|
738
|
+
await input.writer.persist(verified, input.writer.createEvent(run.runId, "run.integration.verified", {
|
|
739
|
+
evidenceIds: evidence.map((item) => item.evidenceId),
|
|
740
|
+
}));
|
|
741
|
+
return verified;
|
|
742
|
+
}
|
|
743
|
+
catch (error) {
|
|
744
|
+
if (!(error instanceof Error))
|
|
745
|
+
throw error;
|
|
746
|
+
return persistIntegrationVerificationFailure(run, task, error.message);
|
|
747
|
+
}
|
|
748
|
+
};
|
|
749
|
+
const persistIntegrationVerificationFailure = async (run, task, detail) => {
|
|
750
|
+
const failure = createVerificationEnvironmentFailure({
|
|
751
|
+
failureId: input.options.ids.createFailureId(`${run.runId}-integration`),
|
|
752
|
+
runId: run.runId,
|
|
753
|
+
taskId: task.taskId,
|
|
754
|
+
commandName: "integration verification",
|
|
755
|
+
detail,
|
|
756
|
+
});
|
|
757
|
+
const nextRun = withParts(run, {
|
|
758
|
+
evidence: run.evidence,
|
|
759
|
+
failures: [...run.failures, failure],
|
|
760
|
+
agentResults: run.agentResults,
|
|
761
|
+
workspace: run.workspace,
|
|
762
|
+
});
|
|
763
|
+
await input.writer.persist(nextRun, input.writer.createEvent(run.runId, "run.integration.failed", {
|
|
764
|
+
failureId: failure.failureId,
|
|
765
|
+
}));
|
|
766
|
+
return nextRun;
|
|
767
|
+
};
|
|
603
768
|
return { runTasks };
|
|
604
769
|
async function runParallelReadyBatch(run, orderedTasks) {
|
|
605
770
|
if (run.workspace.git.mode !== "git") {
|
|
@@ -782,5 +947,4 @@ const claimTaskAttemptBudget = (run, attempt) => {
|
|
|
782
947
|
}
|
|
783
948
|
return parsePlannedRun(consumeBudget(consumedOverallBudget, "repair"));
|
|
784
949
|
};
|
|
785
|
-
const paramsAcceptanceCriterionIds = (run) => run.requirement.acceptanceCriteria.map((_criterion, index) => `${run.requirement.requirementId}-ac-${index + 1}`);
|
|
786
950
|
//# sourceMappingURL=task-executor.js.map
|