@tea-agent/loop-agent 0.10.0 → 0.11.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/AGENTS.md +10 -2
- package/CHANGELOG.md +67 -25
- package/README.md +82 -11
- package/dist/application/dag/args.js +1 -12
- package/dist/application/dag/generate-task-dag.js +23 -2
- package/dist/application/dag/run-dag.js +1 -27
- package/dist/application/dag/validate-dag.js +2 -2
- package/dist/application/loop/run-action.js +0 -4
- package/dist/cli/command-definitions.js +44 -16
- package/dist/cli/program.js +40 -23
- package/dist/cli/update/notifier.js +117 -0
- package/dist/cli/update/npm-client.js +151 -0
- package/dist/cli/update/policy.js +58 -0
- package/dist/cli/update/state.js +68 -0
- package/dist/cli.js +33 -0
- package/dist/commands/cursor-prompt.js +42 -82
- package/dist/commands/dag-approve.js +36 -0
- package/dist/commands/delegate.js +75 -77
- package/dist/commands/doctor.js +0 -18
- package/dist/commands/init.js +476 -91
- package/dist/commands/instructions.js +7 -10
- package/dist/commands/loop.js +4 -20
- package/dist/commands/plan.js +50 -0
- package/dist/executors/config-core.js +0 -51
- package/dist/executors/dag-pi-executor.js +1 -1
- package/dist/executors/dag.js +0 -1
- package/dist/executors/index.js +0 -2
- package/dist/executors/model-routing.js +9 -9
- package/dist/executors/shell-executor.js +1 -1
- package/dist/governance/checks.js +6 -3
- package/dist/governance/exec-plans.js +545 -0
- package/dist/governance/manifest-types.js +24 -2
- package/dist/infrastructure/harness/loop-action-store.js +0 -3
- package/dist/records/harvest.js +2 -23
- package/dist/records/one-shot-runs.js +1 -1
- package/dist/shared/artifacts-core.js +24 -5
- package/dist/shared/output-truncation.js +37 -0
- package/dist/shared/package-metadata.js +353 -0
- package/dist/{executors/cursor-executor.js → sidecars/cursor-prompt/executor.js} +2 -42
- package/dist/sidecars/cursor-prompt/index.js +3 -0
- package/dist/sidecars/cursor-prompt/stream.js +121 -0
- package/dist/task/config-types.js +28 -12
- package/dist/task/delegate.js +9 -21
- package/dist/task/runtime.js +1 -2
- package/dist/worker/cli.js +29 -2
- package/dist/worker/delivery/final-verification.js +47 -11
- package/dist/worker/delivery/package.js +63 -10
- package/dist/worker/feature/run.js +60 -8
- package/dist/worker/loop-agent/loop-agent-client.js +329 -126
- package/dist/worker/observability/read-model.js +27 -1
- package/dist/worker/observe/static/app.js +326 -45
- package/dist/worker/observe/static/index.html +1 -1
- package/dist/worker/observe/static/styles.css +5 -4
- package/dist/worker/preflight.js +49 -1
- package/dist/worker/run-task/run-task.js +22 -12
- package/dist/worker/runner/run-ready.js +76 -12
- package/dist/worker/task-spec/schema.js +0 -1
- package/dist/workflows/dag/convergence/controller.js +1 -1
- package/dist/workflows/dag/executor-registry.js +0 -2
- package/dist/workflows/dag/init-hybrid.js +402 -25
- package/dist/workflows/dag/node-execution.js +61 -7
- package/dist/workflows/dag/runner.js +45 -17
- package/dist/workflows/dag/scheduler.js +7 -2
- package/dist/workflows/dag/sdd-embedded.js +128 -0
- package/dist/workflows/dag/skill-instructions.js +5 -4
- package/dist/workflows/dag/skill-snapshot.js +527 -0
- package/dist/workflows/dag/types.js +42 -9
- package/dist/workflows/dag/validate.js +5 -8
- package/dist/workflows/loop/actions/dag-action.js +0 -2
- package/dist/workflows/loop/actions/shared.js +1 -1
- package/dist/workflows/loop/actions.js +14 -31
- package/dist/workflows/loop/benchmark.js +1 -1
- package/dist/workflows/loop/index.js +1 -1
- package/dist/workflows/loop/policy/auto-policy.js +22 -14
- package/dist/workflows/loop/policy/path-patterns.js +13 -0
- package/docs/README.md +36 -33
- package/docs/agent-dag-recovery-playbook.md +1 -1
- package/docs/agent-dag-runner.md +2 -2
- package/docs/architecture/README.md +26 -0
- package/docs/architecture/dag-execution.md +134 -0
- package/docs/architecture/evolution.md +52 -0
- package/docs/architecture/facts-and-state.md +58 -0
- package/docs/architecture/runtime-boundaries.md +45 -17
- package/docs/architecture/system-overview.md +93 -0
- package/docs/architecture/worker-and-feature.md +81 -0
- package/docs/cursor-prompt-sidecar.md +36 -0
- package/docs/decisions/README.md +13 -1
- package/docs/design/README.md +42 -21
- package/docs/development-principles.md +2 -2
- package/docs/exec-plans/active/README.md +2 -2
- package/docs/exec-plans/completed/README.md +12 -0
- package/docs/feature-workflow.md +50 -4
- package/docs/harness-methodology-debugging.md +1 -1
- package/docs/harness-methodology-tdd.md +3 -3
- package/docs/init-surface.manifest.json +60 -25
- package/docs/loop-agent-harness.md +28 -4
- package/docs/progress/README.md +32 -1
- package/docs/reports/README.md +84 -18
- package/docs/skills/README.md +2 -1
- package/docs/skills/vetted-skill-registry.md +2 -1
- package/docs/templates/agent-dag-report.schema.json +6 -6
- package/docs/templates/agent-dag.base.json +0 -5
- package/docs/templates/agent-dag.final-verification.json +0 -5
- package/docs/templates/agent-dag.schema.json +1 -2
- package/docs/templates/agent-dag.supervised-implementation.json +1 -6
- package/docs/templates/frontend-design-contract.md +33 -0
- package/docs/templates/frontend-task-constraints.md +25 -0
- package/docs/templates/frontend-task-requirement.md +61 -0
- package/docs/templates/harness.schema.json +10 -12
- package/docs/templates/hybrid-dag.json +1 -6
- package/docs/templates/interactive-ui-round2-experiment.md +1 -1
- package/docs/templates/product-line/task.yaml +0 -1
- package/docs/templates/project-start-checklist.md +2 -2
- package/docs/templates/worker-dogfood-evidence.md +28 -0
- package/docs/templates/worker-dogfood-setup.md +20 -0
- package/docs/verification-matrix.md +10 -0
- package/examples/decision-gate-agent-dag.json +87 -33
- package/examples/example-dag.json +0 -5
- package/examples/hybrid-loop-agent-dag.json +0 -5
- package/harness.json +7 -15
- package/package.json +22 -46
- package/scripts/check-product-line-docs.sh +10 -7
- package/skills/agent-worker/SKILL.md +37 -0
- package/skills/agent-worker/references/agent-worker-operator.md +43 -0
- package/skills/frontend-design-review/SKILL.md +59 -0
- package/skills/frontend-design-review/references/review-checklist.md +37 -0
- package/skills/frontend-implementation/SKILL.md +51 -0
- package/skills/frontend-implementation/references/code-standards.md +34 -0
- package/skills/frontend-implementation/references/design-spec.md +46 -0
- package/skills/frontend-implementation/references/node-contracts.md +32 -0
- package/skills/frontend-review/SKILL.md +53 -0
- package/skills/frontend-review/references/review-findings.md +42 -0
- package/skills/frontend-verification/SKILL.md +40 -0
- package/skills/frontend-verification/references/verification-checklist.md +56 -0
- package/skills/grill-me/SKILL.md +10 -0
- package/skills/grill-with-docs/SKILL.md +88 -0
- package/skills/grill-with-docs/adr-format.md +47 -0
- package/skills/grill-with-docs/context-format.md +60 -0
- package/skills/loop-agent/SKILL.md +11 -9
- package/skills/loop-agent/references/command-reference.md +13 -15
- package/skills/loop-agent/references/docs-converge.md +126 -0
- package/skills/loop-agent/references/harness-policy.md +7 -7
- package/skills/loop-agent/references/hybrid-dag.md +15 -18
- package/skills/loop-agent/references/long-running-loop.md +4 -6
- package/skills/loop-agent/references/multi-worktree.md +6 -6
- package/skills/loop-agent/references/orchestrator-and-interventions.md +3 -3
- package/skills/loop-agent/references/pi-subagent-assisted-mode.md +14 -11
- package/skills/loop-agent/references/task-workflow.md +1 -1
- package/skills/using-git-worktrees/SKILL.md +215 -0
- package/dist/commands/cursor-worker.js +0 -43
- package/dist/cursor-worker-entry.js +0 -8
- package/dist/executors/cursor-artifacts.js +0 -33
- package/dist/executors/cursor-execution-log.js +0 -81
- package/dist/executors/cursor-executor-artifacts.js +0 -134
- package/dist/executors/cursor-run.js +0 -115
- package/dist/executors/cursor-tool.js +0 -94
- package/dist/executors/cursor-worker-client.js +0 -223
- package/dist/executors/cursor-worker-protocol.js +0 -18
- package/dist/executors/cursor-worker-server.js +0 -54
- package/dist/executors/cursor-worker.js +0 -3
- package/dist/executors/cursor.js +0 -6
- package/dist/executors/dag-cursor-executor.js +0 -87
- package/dist/workflows/loop/actions/cursor-fix.js +0 -191
- package/dist/workflows/loop/policy/cursor-fix-policy.js +0 -31
- package/docs/cursor-executor-usage.md +0 -25
- package/docs/dynamic-workflow-dag-engine-roadmap.md +0 -1749
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { ensureDagNodeArtifactDir } from "../infrastructure/harness/artifact-store.js";
|
|
3
|
-
import { executeCursorTask } from "./cursor-executor.js";
|
|
4
|
-
import { writeCursorExecutorArtifacts } from "./cursor-executor-artifacts.js";
|
|
5
|
-
import { buildCursorExecutionLogRecord, persistCursorExecutionLog, } from "./cursor-execution-log.js";
|
|
6
|
-
import { readGitStatusPorcelain, runPostRunWriteGuard, } from "./shell-write-guard.js";
|
|
7
|
-
export async function executeDagCursorNode(input, meta) {
|
|
8
|
-
const started = Date.now();
|
|
9
|
-
let beforeStatus;
|
|
10
|
-
try {
|
|
11
|
-
beforeStatus = await readGitStatusPorcelain(input.cwd);
|
|
12
|
-
}
|
|
13
|
-
catch {
|
|
14
|
-
// Non-git cwd: skip write guard (documented limitation).
|
|
15
|
-
beforeStatus = undefined;
|
|
16
|
-
}
|
|
17
|
-
const artifactDir = await ensureDagNodeArtifactDir(meta.runDir, input.task.id);
|
|
18
|
-
const result = await executeCursorTask({
|
|
19
|
-
task: input.prompt,
|
|
20
|
-
cwd: input.cwd,
|
|
21
|
-
model: input.model,
|
|
22
|
-
useWorker: true,
|
|
23
|
-
artifactDir,
|
|
24
|
-
});
|
|
25
|
-
const executionContext = {
|
|
26
|
-
channel: "dag",
|
|
27
|
-
cwd: input.cwd,
|
|
28
|
-
dagRunId: meta.runId,
|
|
29
|
-
dagNodeId: input.task.id,
|
|
30
|
-
};
|
|
31
|
-
await persistCursorExecutionLog(meta.runDir, buildCursorExecutionLogRecord({
|
|
32
|
-
context: executionContext,
|
|
33
|
-
model: input.model,
|
|
34
|
-
prompt: input.prompt,
|
|
35
|
-
result,
|
|
36
|
-
}));
|
|
37
|
-
await writeCursorExecutorArtifacts(path.join(meta.runDir, input.task.id), {
|
|
38
|
-
prompt: input.prompt,
|
|
39
|
-
model: input.model,
|
|
40
|
-
context: executionContext,
|
|
41
|
-
result,
|
|
42
|
-
});
|
|
43
|
-
let writeGuardOk = true;
|
|
44
|
-
let writeGuardViolations = [];
|
|
45
|
-
if (beforeStatus !== undefined) {
|
|
46
|
-
try {
|
|
47
|
-
const guard = await runPostRunWriteGuard({
|
|
48
|
-
rootCwd: input.cwd,
|
|
49
|
-
beforeStatus,
|
|
50
|
-
writePolicy: input.task.writePolicy,
|
|
51
|
-
writeSet: input.task.writeSet,
|
|
52
|
-
allowedPaths: input.task.allowedPaths,
|
|
53
|
-
forbiddenPaths: input.task.forbiddenPaths,
|
|
54
|
-
concurrentSiblingWriteSets: meta.concurrentSiblingWriteSets,
|
|
55
|
-
});
|
|
56
|
-
writeGuardOk = guard.ok;
|
|
57
|
-
writeGuardViolations = guard.violations;
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
writeGuardOk = false;
|
|
61
|
-
writeGuardViolations = ["write guard failed: git status unavailable"];
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
const ok = result.ok && writeGuardOk;
|
|
65
|
-
const stderrParts = [result.stderr];
|
|
66
|
-
if (!writeGuardOk) {
|
|
67
|
-
stderrParts.push(`write guard failed: ${writeGuardViolations.join(", ")}`);
|
|
68
|
-
if (meta.writeGuardAttribution === "best-effort") {
|
|
69
|
-
stderrParts.push("write guard note: concurrent rank writers use best-effort per-node attribution; keep same-rank writeSet entries disjoint");
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
const executionResult = {
|
|
73
|
-
ok,
|
|
74
|
-
stdout: result.stdout,
|
|
75
|
-
stderr: stderrParts.filter(Boolean).join("\n\n"),
|
|
76
|
-
failureCategory: !result.ok
|
|
77
|
-
? result.failureCategory
|
|
78
|
-
: !writeGuardOk
|
|
79
|
-
? "write-guard"
|
|
80
|
-
: result.failureCategory,
|
|
81
|
-
durationMs: result.durationMs ?? Date.now() - started,
|
|
82
|
-
};
|
|
83
|
-
if (result.tokensUsed !== undefined) {
|
|
84
|
-
executionResult.tokensUsed = result.tokensUsed;
|
|
85
|
-
}
|
|
86
|
-
return executionResult;
|
|
87
|
-
}
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { DEFAULT_CURSOR_MODEL, DEFAULT_CURSOR_TIMEOUT_MS, executeCursorTask, } from "../../../executors/cursor-executor.js";
|
|
4
|
-
import { pathsChangedDuringRun, readGitStatusPorcelain, snapshotGitStatusPorcelain, validateShellWriteGuard, } from "../../../executors/shell-write-guard.js";
|
|
5
|
-
import { computeRunDir, persistCursorRunLog } from "../../../records/one-shot-runs.js";
|
|
6
|
-
import { writeLoopCursorFixRecord } from "../../../infrastructure/harness/loop-action-store.js";
|
|
7
|
-
import { loadTaskConfig } from "../../../task/runtime.js";
|
|
8
|
-
import { getLoopPaths } from "../paths.js";
|
|
9
|
-
import { appendLoopRound } from "../rounds.js";
|
|
10
|
-
import { rewriteLoopContext } from "../context.js";
|
|
11
|
-
import { readLoopRounds } from "../rounds.js";
|
|
12
|
-
import { validateLoopCursorFixPolicy } from "../policy/cursor-fix-policy.js";
|
|
13
|
-
import { filterLoopOwnedChangedPaths, hasDagRound, relativeRef } from "./shared.js";
|
|
14
|
-
import { readLatestPiReviewRecord } from "./pi-review.js";
|
|
15
|
-
function extractChangedPaths(result) {
|
|
16
|
-
const raw = result.details?.changedPaths;
|
|
17
|
-
if (!Array.isArray(raw))
|
|
18
|
-
return undefined;
|
|
19
|
-
return raw.filter((value) => typeof value === "string");
|
|
20
|
-
}
|
|
21
|
-
export async function buildLoopCursorFixPrompt(repoRoot, taskId) {
|
|
22
|
-
const paths = getLoopPaths(repoRoot, taskId);
|
|
23
|
-
const [objective, context] = await Promise.all([
|
|
24
|
-
readFile(paths.objectivePath, "utf-8"),
|
|
25
|
-
readFile(paths.contextPath, "utf-8"),
|
|
26
|
-
]);
|
|
27
|
-
const config = await loadTaskConfig(repoRoot, taskId);
|
|
28
|
-
const rounds = await readLoopRounds(repoRoot, taskId);
|
|
29
|
-
const latestReview = await readLatestPiReviewRecord(repoRoot, taskId);
|
|
30
|
-
validateLoopCursorFixPolicy({
|
|
31
|
-
allowedPaths: config.allowedPaths,
|
|
32
|
-
forbiddenPaths: config.forbiddenPaths,
|
|
33
|
-
complexity: config.complexity,
|
|
34
|
-
dagFallbackReason: config.dagFallbackReason ?? "",
|
|
35
|
-
hasDagRound: hasDagRound(rounds),
|
|
36
|
-
});
|
|
37
|
-
return [
|
|
38
|
-
`Task id: ${taskId}`,
|
|
39
|
-
"Exact objective: implement the next bounded fix described by the loop context.",
|
|
40
|
-
"",
|
|
41
|
-
"Allowed paths:",
|
|
42
|
-
...config.allowedPaths.map((entry) => `- ${entry}`),
|
|
43
|
-
"",
|
|
44
|
-
"Forbidden paths:",
|
|
45
|
-
...(config.forbiddenPaths.length > 0
|
|
46
|
-
? config.forbiddenPaths.map((entry) => `- ${entry}`)
|
|
47
|
-
: ["- none"]),
|
|
48
|
-
"",
|
|
49
|
-
"Hard constraints:",
|
|
50
|
-
"- Preserve unrelated files and user work.",
|
|
51
|
-
"- Do not touch forbidden paths.",
|
|
52
|
-
"- Do not mark the loop complete; shell verification or review must follow.",
|
|
53
|
-
"",
|
|
54
|
-
"Expected verification:",
|
|
55
|
-
"- Run the verification commands listed in the task constraints after the fix, or explain why they were not run.",
|
|
56
|
-
"",
|
|
57
|
-
"<latest_pi_review>",
|
|
58
|
-
latestReview
|
|
59
|
-
? [
|
|
60
|
-
`recommendedAction: ${latestReview.structured.recommendedAction}`,
|
|
61
|
-
`rootCause: ${latestReview.structured.rootCause}`,
|
|
62
|
-
`fixScope: ${latestReview.structured.fixScope.join(", ")}`,
|
|
63
|
-
`invariant: ${latestReview.structured.invariant ?? "unknown"}`,
|
|
64
|
-
].join("\n")
|
|
65
|
-
: "No structured Pi review record found.",
|
|
66
|
-
"</latest_pi_review>",
|
|
67
|
-
"",
|
|
68
|
-
"<objective>",
|
|
69
|
-
objective.trim(),
|
|
70
|
-
"</objective>",
|
|
71
|
-
"",
|
|
72
|
-
"<context>",
|
|
73
|
-
context.trim(),
|
|
74
|
-
"</context>",
|
|
75
|
-
].join("\n");
|
|
76
|
-
}
|
|
77
|
-
async function defaultCursorFixExecutor(input) {
|
|
78
|
-
return executeCursorTask({
|
|
79
|
-
task: input.prompt,
|
|
80
|
-
cwd: input.cwd,
|
|
81
|
-
model: input.model,
|
|
82
|
-
timeoutMs: input.timeoutMs,
|
|
83
|
-
runDir: input.runDir,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
export async function runLoopCursorFix(repoRoot, taskId, options = {}) {
|
|
87
|
-
const config = await loadTaskConfig(repoRoot, taskId);
|
|
88
|
-
const rounds = await readLoopRounds(repoRoot, taskId);
|
|
89
|
-
validateLoopCursorFixPolicy({
|
|
90
|
-
allowedPaths: config.allowedPaths,
|
|
91
|
-
forbiddenPaths: config.forbiddenPaths,
|
|
92
|
-
complexity: config.complexity,
|
|
93
|
-
dagFallbackReason: config.dagFallbackReason ?? "",
|
|
94
|
-
hasDagRound: hasDagRound(rounds),
|
|
95
|
-
});
|
|
96
|
-
const model = options.model ?? config.cursorModel ?? DEFAULT_CURSOR_MODEL;
|
|
97
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_CURSOR_TIMEOUT_MS;
|
|
98
|
-
const cwd = options.cwd ? path.resolve(repoRoot, options.cwd) : repoRoot;
|
|
99
|
-
const executor = options.executor ?? defaultCursorFixExecutor;
|
|
100
|
-
const round = rounds.length + 1;
|
|
101
|
-
const latestReview = await readLatestPiReviewRecord(repoRoot, taskId);
|
|
102
|
-
const prompt = await buildLoopCursorFixPrompt(repoRoot, taskId);
|
|
103
|
-
const runDir = (await computeRunDir(repoRoot, `${taskId} cursor-fix r${round}`)) ?? undefined;
|
|
104
|
-
const beforeStatus = await readGitStatusPorcelain(repoRoot).catch(() => "");
|
|
105
|
-
const result = await executor({ prompt, cwd, model, timeoutMs, runDir });
|
|
106
|
-
const explicitChangedPaths = extractChangedPaths(result);
|
|
107
|
-
let changedPaths = explicitChangedPaths
|
|
108
|
-
? filterLoopOwnedChangedPaths(explicitChangedPaths, repoRoot, runDir)
|
|
109
|
-
: undefined;
|
|
110
|
-
const guard = explicitChangedPaths
|
|
111
|
-
? validateShellWriteGuard({
|
|
112
|
-
changedPaths: changedPaths ?? [],
|
|
113
|
-
writePolicy: "exclusive",
|
|
114
|
-
writeSet: config.allowedPaths,
|
|
115
|
-
forbiddenPaths: config.forbiddenPaths,
|
|
116
|
-
})
|
|
117
|
-
: await (async () => {
|
|
118
|
-
const afterStatus = await readGitStatusPorcelain(repoRoot).catch(() => "");
|
|
119
|
-
changedPaths = filterLoopOwnedChangedPaths(pathsChangedDuringRun(snapshotGitStatusPorcelain(beforeStatus), snapshotGitStatusPorcelain(afterStatus)), repoRoot, runDir);
|
|
120
|
-
return validateShellWriteGuard({
|
|
121
|
-
changedPaths,
|
|
122
|
-
writePolicy: "exclusive",
|
|
123
|
-
writeSet: config.allowedPaths,
|
|
124
|
-
forbiddenPaths: config.forbiddenPaths,
|
|
125
|
-
});
|
|
126
|
-
})();
|
|
127
|
-
const finalResult = guard.ok
|
|
128
|
-
? result
|
|
129
|
-
: {
|
|
130
|
-
...result,
|
|
131
|
-
ok: false,
|
|
132
|
-
status: "failed",
|
|
133
|
-
failureCategory: "path-violation",
|
|
134
|
-
stderr: [
|
|
135
|
-
result.stderr,
|
|
136
|
-
`loop cursor-fix path violations: ${guard.violations.join(", ")}`,
|
|
137
|
-
]
|
|
138
|
-
.filter(Boolean)
|
|
139
|
-
.join("\n"),
|
|
140
|
-
};
|
|
141
|
-
const persisted = await persistCursorRunLog(repoRoot, {
|
|
142
|
-
task: prompt,
|
|
143
|
-
model,
|
|
144
|
-
channel: "tool",
|
|
145
|
-
cwd,
|
|
146
|
-
result: finalResult,
|
|
147
|
-
taskId,
|
|
148
|
-
runDir,
|
|
149
|
-
});
|
|
150
|
-
const runRef = persisted?.logPath
|
|
151
|
-
? relativeRef(repoRoot, persisted.logPath)
|
|
152
|
-
: "";
|
|
153
|
-
const paths = getLoopPaths(repoRoot, taskId);
|
|
154
|
-
const record = {
|
|
155
|
-
schemaVersion: 1,
|
|
156
|
-
taskId,
|
|
157
|
-
round,
|
|
158
|
-
action: "cursor-fix",
|
|
159
|
-
ok: finalResult.ok,
|
|
160
|
-
model,
|
|
161
|
-
runRef,
|
|
162
|
-
allowedPaths: config.allowedPaths,
|
|
163
|
-
forbiddenPaths: config.forbiddenPaths,
|
|
164
|
-
changedPaths: changedPaths ?? [],
|
|
165
|
-
writeGuardViolations: guard.violations,
|
|
166
|
-
fixScope: latestReview?.structured.fixScope ?? [],
|
|
167
|
-
rootCause: latestReview?.structured.rootCause ?? "",
|
|
168
|
-
invariant: latestReview?.structured.invariant ?? "",
|
|
169
|
-
expectedNextVerification: "loop shell-verify or required task verification commands",
|
|
170
|
-
recordedAt: new Date().toISOString(),
|
|
171
|
-
};
|
|
172
|
-
const recordPath = path.join(paths.reviewDir, `round-${round}-cursor-fix.json`);
|
|
173
|
-
await writeLoopCursorFixRecord(repoRoot, taskId, round, record);
|
|
174
|
-
await appendLoopRound(repoRoot, taskId, {
|
|
175
|
-
action: "cursor-fix",
|
|
176
|
-
refs: [runRef, relativeRef(repoRoot, recordPath)].filter(Boolean),
|
|
177
|
-
result: finalResult.ok ? "cursor fix completed" : "cursor fix failed",
|
|
178
|
-
verification: finalResult.ok
|
|
179
|
-
? "cursor-fix completed; shell verification still required"
|
|
180
|
-
: `cursor-fix failed: ${finalResult.failureCategory}`,
|
|
181
|
-
lesson: finalResult.ok
|
|
182
|
-
? "cursor-fix changed only allowed paths; completion remains gated by verification"
|
|
183
|
-
: finalResult.stderr || finalResult.stdout || "cursor-fix failed",
|
|
184
|
-
next: "run shell verification for the cursor fix",
|
|
185
|
-
decision: "continue",
|
|
186
|
-
failureCategory: finalResult.ok ? undefined : finalResult.failureCategory,
|
|
187
|
-
completedCriteria: finalResult.ok ? ["cursor bounded fix action executed"] : [],
|
|
188
|
-
});
|
|
189
|
-
await rewriteLoopContext(repoRoot, taskId);
|
|
190
|
-
return record;
|
|
191
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { pathMatchesPattern } from "../../../shared/git-progress.js";
|
|
2
|
-
export function normalizePattern(pattern) {
|
|
3
|
-
return pattern.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/\*\*$/, "");
|
|
4
|
-
}
|
|
5
|
-
export function patternsOverlap(allowed, forbidden) {
|
|
6
|
-
const a = normalizePattern(allowed);
|
|
7
|
-
const f = normalizePattern(forbidden);
|
|
8
|
-
return (a === f ||
|
|
9
|
-
a.startsWith(`${f}/`) ||
|
|
10
|
-
f.startsWith(`${a}/`) ||
|
|
11
|
-
pathMatchesPattern(a, forbidden) ||
|
|
12
|
-
pathMatchesPattern(f, allowed));
|
|
13
|
-
}
|
|
14
|
-
export function validateLoopCursorFixPolicy(input) {
|
|
15
|
-
if (input.allowedPaths.length === 0) {
|
|
16
|
-
throw new Error("loop cursor-fix requires non-empty task allowedPaths");
|
|
17
|
-
}
|
|
18
|
-
for (const allowed of input.allowedPaths) {
|
|
19
|
-
for (const forbidden of input.forbiddenPaths) {
|
|
20
|
-
if (patternsOverlap(allowed, forbidden)) {
|
|
21
|
-
throw new Error(`loop cursor-fix allowed/forbidden paths overlap: ${allowed} vs ${forbidden}`);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
if (input.complexity !== undefined &&
|
|
26
|
-
input.complexity !== "small" &&
|
|
27
|
-
!input.hasDagRound &&
|
|
28
|
-
!input.dagFallbackReason?.trim()) {
|
|
29
|
-
throw new Error("loop cursor-fix for medium/large tasks requires a prior loop dag round or task dagFallbackReason");
|
|
30
|
-
}
|
|
31
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# Cursor Executor 用法
|
|
2
|
-
|
|
3
|
-
Cursor 用于有界写实现。每个 Cursor 写任务必须显式定义 scope。
|
|
4
|
-
|
|
5
|
-
## Prompt 必填字段
|
|
6
|
-
|
|
7
|
-
- task id
|
|
8
|
-
- objective
|
|
9
|
-
- allowed paths
|
|
10
|
-
- forbidden paths
|
|
11
|
-
- constraints
|
|
12
|
-
- expected verification
|
|
13
|
-
- 保留无关变更的指令
|
|
14
|
-
|
|
15
|
-
## One-Shot Helper
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
loop-agent cursor-prompt \
|
|
19
|
-
--cwd . \
|
|
20
|
-
--timeout 1800000 \
|
|
21
|
-
--model composer-2.5 \
|
|
22
|
-
"<bounded task prompt>"
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Cursor 返回后,主会话必须检查 diff 并运行相关验证命令。
|