@tea-agent/loop-agent 0.10.0 → 0.12.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 +91 -24
- package/README.md +84 -12
- package/dist/application/dag/args.js +1 -12
- package/dist/application/dag/generate-task-dag.js +38 -2
- package/dist/application/dag/run-dag.js +11 -27
- package/dist/application/dag/validate-dag.js +13 -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 +547 -95
- 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 +488 -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 +29 -12
- package/dist/task/delegate.js +9 -21
- package/dist/task/runtime.js +1 -2
- package/dist/worker/cli.js +32 -3
- 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/event-history.js +216 -0
- package/dist/worker/observability/read-model.js +338 -83
- package/dist/worker/observe/paths.js +17 -0
- package/dist/worker/observe/routes.js +165 -21
- package/dist/worker/observe/server.js +59 -1
- package/dist/worker/observe/static/api.js +27 -0
- package/dist/worker/observe/static/app.js +120 -2317
- package/dist/worker/observe/static/constants.js +148 -0
- package/dist/worker/observe/static/copy.js +67 -0
- package/dist/worker/observe/static/dag-helpers.js +172 -0
- package/dist/worker/observe/static/dag-model.js +72 -0
- package/dist/worker/observe/static/dom.js +61 -0
- package/dist/worker/observe/static/format-pool.js +67 -0
- package/dist/worker/observe/static/format.js +292 -0
- package/dist/worker/observe/static/index.html +300 -82
- package/dist/worker/observe/static/kpi.js +94 -0
- package/dist/worker/observe/static/relations.js +128 -0
- package/dist/worker/observe/static/router.js +85 -0
- package/dist/worker/observe/static/run-processing.js +148 -0
- package/dist/worker/observe/static/shell-chrome.js +68 -0
- package/dist/worker/observe/static/state.js +253 -0
- package/dist/worker/observe/static/styles.css +1720 -495
- package/dist/worker/observe/static/views/batch.js +226 -0
- package/dist/worker/observe/static/views/dag-graph.js +172 -0
- package/dist/worker/observe/static/views/dag-inspector.js +477 -0
- package/dist/worker/observe/static/views/dag.js +362 -0
- package/dist/worker/observe/static/views/dashboard.js +442 -0
- package/dist/worker/observe/static/views/failures.js +143 -0
- package/dist/worker/observe/static/views/feature.js +453 -0
- package/dist/worker/observe/static/views/pool.js +347 -0
- package/dist/worker/observe/static/views/run.js +453 -0
- package/dist/worker/observe/static/views/session-timeline.js +205 -0
- package/dist/worker/observe/static/views/shell.js +7 -0
- package/dist/worker/observe/static/views/task.js +260 -0
- package/dist/worker/observe/static/views/timeline.js +163 -0
- 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/controller-identity.js +104 -0
- 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 +797 -27
- package/dist/workflows/dag/node-execution.js +183 -35
- package/dist/workflows/dag/repair-artifact.js +91 -0
- package/dist/workflows/dag/report.js +50 -0
- package/dist/workflows/dag/retry-policy.js +138 -0
- package/dist/workflows/dag/runner.js +77 -17
- package/dist/workflows/dag/runtime-contract.js +87 -0
- 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 +529 -0
- package/dist/workflows/dag/types.js +86 -10
- package/dist/workflows/dag/validate.js +73 -12
- 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 +28 -3
- package/docs/architecture/README.md +26 -0
- package/docs/architecture/dag-execution.md +140 -0
- package/docs/architecture/evolution.md +53 -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 +43 -21
- package/docs/development-principles.md +2 -2
- package/docs/exec-plans/active/README.md +1 -3
- package/docs/exec-plans/completed/README.md +23 -0
- package/docs/feature-workflow.md +78 -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 +50 -1
- package/docs/reports/README.md +90 -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 +23 -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 +70 -3
- package/docs/templates/agent-dag.supervised-implementation.json +9 -8
- package/docs/templates/backend-test-dag.generate-pytest.prompt.md +139 -0
- package/docs/templates/backend-test-dag.json +276 -0
- package/docs/templates/backend-test-dag.retrospect.prompt.md +125 -0
- package/docs/templates/backend-test-dag.review-cases.prompt.md +81 -0
- 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 +14 -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 +36 -20
- 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/loop-agent/references/verification-and-failure-handling.md +6 -0
- 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,7 +1,9 @@
|
|
|
1
1
|
import { DEFAULT_DAG_EXECUTOR_MODELS, ENV_VAR_NAME_PATTERN, } from "./types.js";
|
|
2
2
|
import { resolveShellCommands } from "../../executors/shell-executor.js";
|
|
3
3
|
import { pathMatchesPattern } from "../../shared/git-progress.js";
|
|
4
|
+
import { resolveRepairTaskForGate } from "./repair-artifact.js";
|
|
4
5
|
import { topoSortToRanks } from "./topo.js";
|
|
6
|
+
import { isSafeReadOnlyPiRetryCandidate } from "./retry-policy.js";
|
|
5
7
|
const GOVERNANCE_WARNING_TYPES = new Set([
|
|
6
8
|
"read-only-missing-artifacts-forbidden",
|
|
7
9
|
"read-only-prompt-mentions-artifact-writes",
|
|
@@ -176,14 +178,65 @@ function validateRepairArtifactGateConfig(task, spec, issues) {
|
|
|
176
178
|
});
|
|
177
179
|
}
|
|
178
180
|
const upstream = spec.tasks.find((candidate) => candidate.id === repairArtifactGate.fromNodeId);
|
|
179
|
-
if (
|
|
180
|
-
return;
|
|
181
|
-
if (upstream.executor === "shell") {
|
|
181
|
+
if (upstream && upstream.executor === "shell") {
|
|
182
182
|
issues.push({
|
|
183
183
|
type: "invalid-repair-artifact-gate-config",
|
|
184
184
|
message: `task ${task.id} shell.repairArtifactGate.fromNodeId "${repairArtifactGate.fromNodeId}" must reference a non-shell upstream artifact node`,
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
|
+
const resolution = resolveRepairTaskForGate({
|
|
188
|
+
tasks: spec.tasks,
|
|
189
|
+
gateTask: task,
|
|
190
|
+
});
|
|
191
|
+
if (!resolution.ok) {
|
|
192
|
+
issues.push({
|
|
193
|
+
type: "invalid-repair-artifact-gate-config",
|
|
194
|
+
message: `task ${task.id} ${resolution.reason}`,
|
|
195
|
+
});
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const hardVerifyCandidates = spec.tasks.filter((candidate) => candidate.depends_on.includes(resolution.repairTask.id) &&
|
|
199
|
+
candidate.executor === "shell" &&
|
|
200
|
+
candidate.role === "verifier" &&
|
|
201
|
+
candidate.shell?.verifyEvidence?.phase === "final" &&
|
|
202
|
+
candidate.shell.verifyEvidence.quota === "full" &&
|
|
203
|
+
candidate.shell.verifyEvidence.finalFullRequired === true);
|
|
204
|
+
if (hardVerifyCandidates.length !== 1) {
|
|
205
|
+
issues.push({
|
|
206
|
+
type: "invalid-repair-artifact-gate-config",
|
|
207
|
+
message: hardVerifyCandidates.length === 0
|
|
208
|
+
? `task ${task.id} repair node "${resolution.repairTask.id}" must have one direct downstream final/full hard verification shell node with finalFullRequired=true`
|
|
209
|
+
: `task ${task.id} repair node "${resolution.repairTask.id}" has multiple hard verification shell nodes (${hardVerifyCandidates.map((candidate) => candidate.id).join(", ")})`,
|
|
210
|
+
});
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const hardVerify = hardVerifyCandidates[0];
|
|
214
|
+
const descendantIds = new Set();
|
|
215
|
+
const queue = [hardVerify.id];
|
|
216
|
+
while (queue.length > 0) {
|
|
217
|
+
const parentId = queue.shift();
|
|
218
|
+
for (const candidate of spec.tasks) {
|
|
219
|
+
if (candidate.depends_on.includes(parentId) &&
|
|
220
|
+
!descendantIds.has(candidate.id)) {
|
|
221
|
+
descendantIds.add(candidate.id);
|
|
222
|
+
queue.push(candidate.id);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const reviewCandidates = spec.tasks.filter((candidate) => descendantIds.has(candidate.id) &&
|
|
227
|
+
candidate.executor === "pi" &&
|
|
228
|
+
candidate.role === "reviewer" &&
|
|
229
|
+
!candidate.decisionGate?.enabled &&
|
|
230
|
+
candidate.writePolicy === "read-only" &&
|
|
231
|
+
(candidate.outputContract?.includes("VERDICT:") ?? false));
|
|
232
|
+
if (reviewCandidates.length !== 1) {
|
|
233
|
+
issues.push({
|
|
234
|
+
type: "invalid-repair-artifact-gate-config",
|
|
235
|
+
message: reviewCandidates.length === 0
|
|
236
|
+
? `task ${task.id} hard verification node "${hardVerify.id}" must reach one read-only Pi reviewer with a VERDICT output contract`
|
|
237
|
+
: `task ${task.id} hard verification node "${hardVerify.id}" has multiple Pi reviewer nodes (${reviewCandidates.map((candidate) => candidate.id).join(", ")})`,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
187
240
|
}
|
|
188
241
|
function validateShellVerdictGateGovernance(task, commands, issues) {
|
|
189
242
|
if (task.executor !== "shell") {
|
|
@@ -229,7 +282,7 @@ function writeSetEntriesOverlap(a, b) {
|
|
|
229
282
|
pathMatchesPattern(probeB, a)));
|
|
230
283
|
}
|
|
231
284
|
function shouldValidateWritePolicy(spec, task) {
|
|
232
|
-
return (spec.version
|
|
285
|
+
return (spec.version >= 2 ||
|
|
233
286
|
task.writePolicy !== undefined ||
|
|
234
287
|
task.writeSet !== undefined);
|
|
235
288
|
}
|
|
@@ -319,20 +372,17 @@ function validateSameRankWriteSetConflicts(spec, ranks, issues) {
|
|
|
319
372
|
}
|
|
320
373
|
}
|
|
321
374
|
}
|
|
322
|
-
function
|
|
323
|
-
return
|
|
324
|
-
(task?.executor === "pi" && task.toolProfile === "write"));
|
|
375
|
+
function isAgentTask(task) {
|
|
376
|
+
return task?.executor === "pi";
|
|
325
377
|
}
|
|
326
378
|
function validateSameRankAgentAttributionRisks(spec, ranks, issues) {
|
|
327
379
|
const taskById = new Map(spec.tasks.map((task) => [task.id, task]));
|
|
328
380
|
for (const rank of ranks) {
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
.filter(isWriteGuardedAgentTask);
|
|
332
|
-
const hasExclusiveWriter = guardedTasks.some((task) => resolveWritePolicy(task, spec) === "exclusive");
|
|
381
|
+
const agentTasks = rank.map((id) => taskById.get(id)).filter(isAgentTask);
|
|
382
|
+
const hasExclusiveWriter = agentTasks.some((task) => resolveWritePolicy(task, spec) === "exclusive");
|
|
333
383
|
if (!hasExclusiveWriter)
|
|
334
384
|
continue;
|
|
335
|
-
for (const task of
|
|
385
|
+
for (const task of agentTasks) {
|
|
336
386
|
const policy = resolveWritePolicy(task, spec) ?? "read-only";
|
|
337
387
|
if (policy === "read-only" || policy === "none") {
|
|
338
388
|
issues.push({
|
|
@@ -417,6 +467,16 @@ function validateStaticTaskConfig(task, issues) {
|
|
|
417
467
|
});
|
|
418
468
|
}
|
|
419
469
|
}
|
|
470
|
+
function validateRetryPolicyTaskConfig(task, issues) {
|
|
471
|
+
if (task.retryPolicy === undefined)
|
|
472
|
+
return;
|
|
473
|
+
if (!isSafeReadOnlyPiRetryCandidate(task)) {
|
|
474
|
+
issues.push({
|
|
475
|
+
type: "invalid-retry-policy",
|
|
476
|
+
message: `task ${task.id} declares retryPolicy but is not a safe read-only non-dynamic Pi node; retry is only allowed for read-only/none Pi planner/scout/reviewer/verifier/closeout nodes without write, supervisor, or dynamic capabilities`,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
}
|
|
420
480
|
function validateDecisionGateTaskConfig(task, issues) {
|
|
421
481
|
if (!task.decisionGate?.enabled) {
|
|
422
482
|
return;
|
|
@@ -515,6 +575,7 @@ export function validateDagSpec(spec) {
|
|
|
515
575
|
validateShellTaskConfig(task, spec, issues);
|
|
516
576
|
validateStaticTaskConfig(task, issues);
|
|
517
577
|
validateDecisionGateTaskConfig(task, issues);
|
|
578
|
+
validateRetryPolicyTaskConfig(task, issues);
|
|
518
579
|
}
|
|
519
580
|
validateSameRankWriteSetConflicts(spec, ranks, issues);
|
|
520
581
|
validateSameRankAgentAttributionRisks(spec, ranks, issues);
|
|
@@ -64,8 +64,6 @@ export async function runLoopDagAction(repoRoot, taskId, options = {}) {
|
|
|
64
64
|
if (options.maxConcurrent !== undefined) {
|
|
65
65
|
runArgs.push("--max-concurrent", String(options.maxConcurrent));
|
|
66
66
|
}
|
|
67
|
-
if (options.noCursor)
|
|
68
|
-
runArgs.push("--no-cursor");
|
|
69
67
|
const runSummary = asRecord(await runner("run-dag", runArgs), "run-dag");
|
|
70
68
|
runId = stringField(runSummary, "runId", "run-dag");
|
|
71
69
|
const report = await runner("dag-report", [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { repoRelativePath, toPosixPath } from "../../../shared/path-refs.js";
|
|
3
3
|
import { workflowReportSchema } from "../../dynamic/artifacts.js";
|
|
4
|
-
import { normalizePattern } from "../policy/
|
|
4
|
+
import { normalizePattern } from "../policy/path-patterns.js";
|
|
5
5
|
export const SUMMARY_LIMIT = 1200;
|
|
6
6
|
export function truncateSummary(text) {
|
|
7
7
|
const normalized = text.trim();
|
|
@@ -7,21 +7,17 @@ import { validateDagUseCase } from "../../application/dag/validate-dag.js";
|
|
|
7
7
|
import { formatDagReportHandoffMarkdown, formatDagReportMarkdown, } from "../dag/report.js";
|
|
8
8
|
import { loadTaskConfig } from "../../task/runtime.js";
|
|
9
9
|
import { appendLoopEvent } from "./events.js";
|
|
10
|
-
import { appendLoopRound
|
|
10
|
+
import { appendLoopRound } from "./rounds.js";
|
|
11
11
|
import { rewriteLoopContext } from "./context.js";
|
|
12
12
|
import { loadLoopState } from "./state.js";
|
|
13
13
|
import { drainLoopSignals, pendingLoopSignals, readLoopSignals, } from "./signals.js";
|
|
14
14
|
import { decideNextLoopAutoAction, } from "./policy/auto-policy.js";
|
|
15
|
-
import { validateLoopCursorFixPolicy } from "./policy/cursor-fix-policy.js";
|
|
16
15
|
import { configureLoopDagDefaultRunner, } from "./actions/dag-action.js";
|
|
17
16
|
import { readLatestPiReviewRecord } from "./actions/pi-review.js";
|
|
18
17
|
import { runLoopWorkflowGateSignalAction, } from "./actions/workflow-action.js";
|
|
19
|
-
import { hasDagRound } from "./actions/shared.js";
|
|
20
18
|
export { decideNextLoopAutoAction } from "./policy/auto-policy.js";
|
|
21
|
-
export { validateLoopCursorFixPolicy } from "./policy/cursor-fix-policy.js";
|
|
22
19
|
export { resolveLoopShellVerifyCommands, runLoopShellVerification } from "./actions/shell-verify.js";
|
|
23
20
|
export { buildLoopPiReviewPrompt, runLoopPiReview, } from "./actions/pi-review.js";
|
|
24
|
-
export { buildLoopCursorFixPrompt, runLoopCursorFix } from "./actions/cursor-fix.js";
|
|
25
21
|
export { runLoopDagAction } from "./actions/dag-action.js";
|
|
26
22
|
export { runLoopWorkflowAction, runLoopWorkflowGateSignalAction, } from "./actions/workflow-action.js";
|
|
27
23
|
async function defaultDagCommandRunner(repoRoot, command, args) {
|
|
@@ -58,6 +54,17 @@ async function defaultDagCommandRunner(repoRoot, command, args) {
|
|
|
58
54
|
configureLoopDagDefaultRunner(defaultDagCommandRunner);
|
|
59
55
|
async function defaultAutoActionRunner(input) {
|
|
60
56
|
if (isLoopActionName(input.action)) {
|
|
57
|
+
if (input.action === "dag") {
|
|
58
|
+
await runLoopAction({
|
|
59
|
+
action: "dag",
|
|
60
|
+
repoRoot: input.repoRoot,
|
|
61
|
+
taskId: input.taskId,
|
|
62
|
+
options: {
|
|
63
|
+
mode: input.dagMode ?? "review",
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
61
68
|
await runLoopAction({
|
|
62
69
|
action: input.action,
|
|
63
70
|
repoRoot: input.repoRoot,
|
|
@@ -81,7 +88,6 @@ async function defaultAutoActionRunner(input) {
|
|
|
81
88
|
function isLoopActionName(action) {
|
|
82
89
|
return (action === "shell-verify" ||
|
|
83
90
|
action === "pi-review" ||
|
|
84
|
-
action === "cursor-fix" ||
|
|
85
91
|
action === "dag" ||
|
|
86
92
|
action === "workflow");
|
|
87
93
|
}
|
|
@@ -117,33 +123,10 @@ export async function runLoopAuto(repoRoot, taskId, options = {}) {
|
|
|
117
123
|
}
|
|
118
124
|
continue;
|
|
119
125
|
}
|
|
120
|
-
const hasApprovalSignal = pendingLoopSignals(signals).some((signal) => signal.type === "approval");
|
|
121
|
-
const policyAllowsCursorFix = taskConfig.loopAutoWritePolicy === "enabled" ||
|
|
122
|
-
(taskConfig.loopAutoWritePolicy === "approval-required" &&
|
|
123
|
-
(Boolean(options.allowCursorFix) || hasApprovalSignal));
|
|
124
|
-
let cursorFixPolicyError;
|
|
125
|
-
if (policyAllowsCursorFix &&
|
|
126
|
-
state.lastAction === "pi-review" &&
|
|
127
|
-
latestPiReview?.structured.recommendedAction === "implement_fix") {
|
|
128
|
-
try {
|
|
129
|
-
const rounds = await readLoopRounds(repoRoot, taskId);
|
|
130
|
-
validateLoopCursorFixPolicy({
|
|
131
|
-
allowedPaths: taskConfig.allowedPaths,
|
|
132
|
-
forbiddenPaths: taskConfig.forbiddenPaths,
|
|
133
|
-
complexity: taskConfig.complexity,
|
|
134
|
-
dagFallbackReason: taskConfig.dagFallbackReason ?? "",
|
|
135
|
-
hasDagRound: hasDagRound(rounds),
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
catch (error) {
|
|
139
|
-
cursorFixPolicyError = error instanceof Error ? error.message : String(error);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
126
|
const next = decideNextLoopAutoAction(state, signals, {
|
|
143
|
-
|
|
144
|
-
|
|
127
|
+
loopAutoExecutionPolicy: taskConfig.loopAutoExecutionPolicy,
|
|
128
|
+
approvalGranted: options.approvalGranted,
|
|
145
129
|
latestPiReview: latestPiReview?.structured,
|
|
146
|
-
cursorFixPolicyError,
|
|
147
130
|
});
|
|
148
131
|
actions.push(next);
|
|
149
132
|
await appendLoopEvent(repoRoot, taskId, {
|
|
@@ -194,7 +194,7 @@ export const LOOP_BENCHMARK_FIXTURE_SAMPLES = [
|
|
|
194
194
|
regressionPause: false,
|
|
195
195
|
changedPaths: 1,
|
|
196
196
|
repairPasses: 1,
|
|
197
|
-
}, ["./test/loop-workflow.test.ts"], "Approval or enabled policy triggers bounded
|
|
197
|
+
}, ["./test/loop-workflow.test.ts"], "Approval or enabled policy triggers bounded DAG execute."),
|
|
198
198
|
result("3-pass-convergence+quota", {
|
|
199
199
|
pass: true,
|
|
200
200
|
fullVerifyPass: true,
|
|
@@ -5,4 +5,4 @@ export { rewriteLoopContext } from "./context.js";
|
|
|
5
5
|
export { appendLoopSignal, drainLoopSignals, parseLoopSignalType, pendingLoopSignals, readLoopSignals, } from "./signals.js";
|
|
6
6
|
export { appendLoopEvent, readLoopEvents } from "./events.js";
|
|
7
7
|
export { generateLoopCloseout } from "./closeout.js";
|
|
8
|
-
export { buildLoopPiReviewPrompt,
|
|
8
|
+
export { buildLoopPiReviewPrompt, decideNextLoopAutoAction, resolveLoopShellVerifyCommands, runLoopAuto, runLoopDagAction, runLoopPiReview, runLoopShellVerification, runLoopWorkflowGateSignalAction, runLoopWorkflowAction, } from "./actions.js";
|
|
@@ -55,28 +55,34 @@ export function decideNextLoopAutoAction(state, signals = [], options = {}) {
|
|
|
55
55
|
}
|
|
56
56
|
if (state.lastAction === "pi-review") {
|
|
57
57
|
if (options.latestPiReview?.recommendedAction === "implement_fix") {
|
|
58
|
-
const policy = options.
|
|
58
|
+
const policy = options.loopAutoExecutionPolicy ?? "off";
|
|
59
59
|
const approvalSignal = pendingSignals.find((signal) => signal.type === "approval");
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
(Boolean(options.allowCursorFix) || Boolean(approvalSignal)));
|
|
63
|
-
if (options.cursorFixPolicyError) {
|
|
60
|
+
const approved = Boolean(options.approvalGranted) || Boolean(approvalSignal);
|
|
61
|
+
if (policy === "off") {
|
|
64
62
|
return {
|
|
65
|
-
action: "
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
action: "dag",
|
|
64
|
+
dagMode: "review",
|
|
65
|
+
reason: `pi-review recommended implement_fix; loopAutoExecutionPolicy=off (DAG review only)`,
|
|
66
|
+
decision: "continue",
|
|
68
67
|
};
|
|
69
68
|
}
|
|
70
|
-
if (
|
|
69
|
+
if (policy === "approval-required" && !approved) {
|
|
71
70
|
return {
|
|
72
|
-
action: "
|
|
73
|
-
reason: `pi-review recommended implement_fix;
|
|
74
|
-
decision: "
|
|
71
|
+
action: "pause",
|
|
72
|
+
reason: `pi-review recommended implement_fix; loopAutoExecutionPolicy=approval-required without approval`,
|
|
73
|
+
decision: "pause",
|
|
75
74
|
};
|
|
76
75
|
}
|
|
76
|
+
return {
|
|
77
|
+
action: "dag",
|
|
78
|
+
dagMode: "execute",
|
|
79
|
+
reason: `pi-review recommended implement_fix; loopAutoExecutionPolicy=${policy}`,
|
|
80
|
+
decision: "continue",
|
|
81
|
+
};
|
|
77
82
|
}
|
|
78
83
|
return {
|
|
79
84
|
action: "dag",
|
|
85
|
+
dagMode: "review",
|
|
80
86
|
reason: "read-only review produced next action; generate a governed DAG review packet",
|
|
81
87
|
decision: "continue",
|
|
82
88
|
};
|
|
@@ -85,19 +91,21 @@ export function decideNextLoopAutoAction(state, signals = [], options = {}) {
|
|
|
85
91
|
if (approvalSignal) {
|
|
86
92
|
return {
|
|
87
93
|
action: "dag",
|
|
94
|
+
dagMode: "review",
|
|
88
95
|
reason: `approval signal received; generate next governed DAG packet: ${approvalSignal.message}`,
|
|
89
96
|
decision: "continue",
|
|
90
97
|
};
|
|
91
98
|
}
|
|
92
|
-
if (state.lastAction === "
|
|
99
|
+
if (state.lastAction === "dag") {
|
|
93
100
|
return {
|
|
94
101
|
action: "shell-verify",
|
|
95
|
-
reason:
|
|
102
|
+
reason: "dag round must be followed by deterministic shell verification",
|
|
96
103
|
decision: "continue",
|
|
97
104
|
};
|
|
98
105
|
}
|
|
99
106
|
return {
|
|
100
107
|
action: "dag",
|
|
108
|
+
dagMode: "review",
|
|
101
109
|
reason: "default to DAG governed review packet for the next bounded round",
|
|
102
110
|
decision: "continue",
|
|
103
111
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
}
|
package/docs/README.md
CHANGED
|
@@ -4,27 +4,40 @@
|
|
|
4
4
|
|
|
5
5
|
顶层 `AGENTS.md` 是操作地图。长期知识应落在此处:决策、契约、计划、验证证据、调试笔记和可复用流程规则应记录在 `docs/` 下,而不是只留在聊天里。
|
|
6
6
|
|
|
7
|
+
**索引职责**:本文件只索引**核心契约、方法论、产物目录入口与模板**。单篇 progress / report / completed plan 的全量列表分别由对应子目录 `README.md` 维护,避免三处精选榜漂移。
|
|
8
|
+
|
|
9
|
+
站上用法文档在 `../website/docs/`;双树收敛见 `../skills/loop-agent/references/docs-converge.md`。
|
|
10
|
+
|
|
7
11
|
## 核心文档
|
|
8
12
|
|
|
13
|
+
- `design/2026-07-14-loop-agent-self-update-notifier.md` — loop-agent CLI 自更新提醒设计与实现依据
|
|
9
14
|
- `development-principles.md` — 仓库开发原则
|
|
10
15
|
- `architecture/runtime-boundaries.md` — runtime 层边界与依赖方向
|
|
16
|
+
- `architecture/README.md` — 架构文档目录索引与阅读路径
|
|
17
|
+
- `architecture/system-overview.md` — loop-agent / agent-worker / 治理层 / 外部系统全景
|
|
18
|
+
- `architecture/dag-execution.md` — Agent DAG 主调用链、rank 调度、executor、skill snapshot、生命周期
|
|
19
|
+
- `architecture/worker-and-feature.md` — agent-worker 子进程边界、controller identity、Task Pool、Feature 与 Observe
|
|
20
|
+
- `architecture/facts-and-state.md` — harness 事实与状态、canonical/derived、可写/只读边界
|
|
21
|
+
- `architecture/evolution.md` — 当前已实现能力 vs 第 3–6 月未来方向
|
|
11
22
|
- `feature-workflow.md` — 有边界的功能工作流
|
|
12
23
|
- `verification-matrix.md` — 验证命令选择
|
|
13
24
|
- `production-readiness.md` — Production Readiness v0.1 范围、证据与 DAG hardening 标准
|
|
14
25
|
- `loop-agent-harness.md` — runtime 与 command surface 概览
|
|
15
|
-
- `exec-plans/completed/2026-07-11-m2-01-feature-review-model.md` — 第二月 Feature read model 与 `feature review` 已完成实施合同
|
|
16
|
-
- `exec-plans/completed/2026-07-12-m2-02-feature-run-orchestration.md` — 第二月 Feature run 薄编排已完成实施合同
|
|
17
|
-
- `exec-plans/completed/2026-07-12-m2-03-follow-up-tracer-bullet.md` — 第二月 ProductBug Follow-up tracer bullet 已完成合同
|
|
18
|
-
- `exec-plans/completed/2026-07-12-m2-04-follow-up-hardening.md` — 第二月 Follow-up 全分类与事务故障注入已完成合同
|
|
19
|
-
- `exec-plans/completed/2026-07-12-m2-05-git-transaction.md` — 第二月显式授权 Git checkpoint 与失败恢复已完成合同
|
|
20
|
-
- `exec-plans/completed/2026-07-12-m2-06-delivery-closeout-preview.md` — 第二月 Delivery、Acceptance Coverage 与 Closeout preview 已完成合同
|
|
21
|
-
- `exec-plans/completed/2026-07-12-m2-07-feature-decision-metrics.md` — 第二月 Feature 决策体验与 metrics 已完成合同
|
|
22
|
-
- `exec-plans/completed/2026-07-12-m2-08-closeout-dogfood-release.md` — 第二月 Closeout apply、真实 dogfood 与发布证据已完成合同
|
|
23
26
|
- `agent-dag-runner.md` — Agent DAG runner 指南
|
|
24
|
-
- `
|
|
25
|
-
- `
|
|
27
|
+
- `agent-dag-recovery-playbook.md` — DAG 失败分类、recovery action 与 operator 处置手册
|
|
28
|
+
- `cursor-prompt-sidecar.md` — `cursor-prompt` one-shot sidecar 用法(非受治理 writer)
|
|
26
29
|
- `init-surface.manifest.json` — npm 包范围、目标项目初始化投影与 `init check-update` surface 分类的机器校验契约
|
|
27
30
|
|
|
31
|
+
## 近期完成合同(入口)
|
|
32
|
+
|
|
33
|
+
完整列表见 `exec-plans/completed/README.md`。近期高频入口:
|
|
34
|
+
|
|
35
|
+
- `exec-plans/completed/2026-07-14-website-docs-ia-and-converge.md` — Website IA、双树边界与 docs-converge
|
|
36
|
+
- `exec-plans/completed/2026-07-13-versioned-self-hosting-bootstrap.md` — 版本化自举与 candidate canary
|
|
37
|
+
- `exec-plans/completed/2026-07-12-pi-only-agent-runtime.md` — Pi-only 受治理 runtime
|
|
38
|
+
- `exec-plans/completed/2026-07-12-observe-warm-console-redesign.md` — Observe 暖白运行控制台
|
|
39
|
+
- `exec-plans/completed/2026-07-12-m2-08-closeout-dogfood-release.md` — 第二月 Closeout 与 dogfood 收口(M2-01~08 见 completed 索引)
|
|
40
|
+
|
|
28
41
|
## 设计思想来源
|
|
29
42
|
|
|
30
43
|
- `../website/docs/practices/` — Anthropic 长时运行 agent harness、OpenAI Codex harness engineering、腾讯端到端 Harness Engineering 与社区 agent harness 实践资料。当前仓库的“人类掌舵、智能体执行”、仓库即记录系统、小步增量、结构化 handoff 和 shell verification 纪律均受这些实践启发;权威执行规则仍以本目录治理文档、根目录 AGENTS.md、harness.json、skills 目录和脚本检查为准。
|
|
@@ -37,34 +50,19 @@
|
|
|
37
50
|
|
|
38
51
|
## 产物目录
|
|
39
52
|
|
|
40
|
-
- `design/README.md` —
|
|
53
|
+
- `design/README.md` — 设计草稿、契约映射与路线图(含 design/dynamic-workflow-dag-engine-roadmap.md)
|
|
41
54
|
- `exec-plans/active/README.md` — 进行中的执行计划
|
|
42
|
-
- `exec-plans/completed/README.md` —
|
|
43
|
-
- `progress/README.md` —
|
|
44
|
-
- `reports/README.md` —
|
|
45
|
-
- `
|
|
46
|
-
- `reports/2026-07-11-observe-dag-visualization.md` — Observe DAG edges、SVG 图形化、交互与真实 Chrome smoke 验证证据
|
|
47
|
-
- `reports/2026-07-11-0.7.5-init-evolution-review.md` — 0.7.5 package/version 变化对目标项目初始化 surface 的影响审查
|
|
48
|
-
- `reports/2026-07-11-command-performance-audit.md` — 命令并发、验证、Observe 和子进程输出的性能审计
|
|
49
|
-
- `reports/2026-07-11-command-performance-followups.md` — Observe 快照复用、输出缓冲和 reference index 遍历优化的验证记录
|
|
50
|
-
- `reports/2026-07-11-observe-terminal-dag-kpi.md` — 终态 DAG 被误计为活跃数的修复记录
|
|
51
|
-
- `reports/2026-07-12-observe-warm-console-redesign.md` — 暖白运行控制台视觉重构与桌面验证记录
|
|
52
|
-
- `reports/2026-07-12-dag-state-reconciliation.md` — DAG 实际状态判定、安全收口命令与历史失联运行处理记录
|
|
53
|
-
- `reports/2026-07-12-dag-state-reconciliation-init-evolution-review.md` — DAG 状态收口能力对初始化 surface 的影响审查
|
|
54
|
-
- `reports/2026-07-12-observe-dag-node-model.md` — Dashboard DAG 节点模型显示与历史运行兼容修复记录
|
|
55
|
-
- `reports/2026-07-12-observe-dag-node-model-init-evolution-review.md` — 节点模型持久化与 Observe 投影对初始化 surface 的影响审查
|
|
56
|
-
- `reports/2026-07-12-dag-output-language.md` — Agent DAG 默认中文输出与可配置语言规则实现记录
|
|
57
|
-
- `reports/2026-07-12-dag-output-language-init-evolution-review.md` — DAG 输出语言配置对初始化 surface 的影响审查
|
|
58
|
-
- `reports/2026-07-12-init-evolution-strict-report-range.md` — 严格 init 演化校验拒绝无关历史报告的修复与验证证据
|
|
59
|
-
- `reports/2026-07-12-dag-liveness-recovery.md` — DAG runner 心跳、孤儿运行诊断与 Observe 活跃筛选的修复记录
|
|
60
|
-
- `reports/2026-07-12-dag-liveness-init-evolution-review.md` — DAG 活性元数据对初始化投影和旧项目兼容性的审查
|
|
61
|
-
- `decisions/README.md` — 架构决策
|
|
55
|
+
- `exec-plans/completed/README.md` — 已完成的执行计划(全量)
|
|
56
|
+
- `progress/README.md` — 进度交接日志(全量)
|
|
57
|
+
- `reports/README.md` — 验证与审计报告(全量);活能力摘要见 `reports/current-capability-summary.md`
|
|
58
|
+
- `decisions/README.md` — 架构决策(ADR 0001–0003)
|
|
62
59
|
- `skills/README.md` — repo-local skill registry and vetting notes
|
|
63
60
|
- `templates/` — 可复用的规划、报告与 DAG 模板
|
|
64
61
|
|
|
65
62
|
## 仓库 Skills
|
|
66
63
|
|
|
67
64
|
- `../skills/loop-agent/` — loop-agent 自身的 skill 指令与参考资料
|
|
65
|
+
- `../skills/agent-worker/` — Feature Packet / Task Pool / versioned self-hosting 的可选 outer-loop operator skill;不进入默认 DAG role skills
|
|
68
66
|
- 每个额外 skill 在仓库根 `../skills/` 下使用独立子目录;这些本地副本由 DAG 模板引用,维护不依赖外部 agent skill 目录
|
|
69
67
|
|
|
70
68
|
## 模板
|
|
@@ -75,8 +73,8 @@
|
|
|
75
73
|
- `templates/exec-plan.md` — 非平凡工作的执行计划
|
|
76
74
|
- `templates/progress-log.md` — 进度与交接日志
|
|
77
75
|
- `templates/qa-report.md` — 验证与 QA 证据
|
|
78
|
-
- `templates/worker-dogfood-setup.md` —
|
|
79
|
-
- `templates/worker-dogfood-evidence.md` — BE/FE/QA
|
|
76
|
+
- `templates/worker-dogfood-setup.md` — 发布 controller identity 固定、真实 Worker sample、candidate canary 与 retry 纪律
|
|
77
|
+
- `templates/worker-dogfood-evidence.md` — controller fingerprint、skill snapshot、canary、BE/FE/QA、Observe 与 failure evidence 模板
|
|
80
78
|
- `templates/harness.schema.json` — `harness.json` 的 IDE JSON Schema,随初始化投影到目标项目
|
|
81
79
|
- `templates/interactive-ui-round2-experiment.md` — interactive UI prompt/model A/B/C 对照实验与统一指标模板
|
|
82
80
|
- `templates/product-line/` — 可投影的 Feature/Task/QA/Links 产品线包;配合 `agent-worker task validate-feature` 做 docs CI
|
|
@@ -89,9 +87,14 @@
|
|
|
89
87
|
文档变更后运行:
|
|
90
88
|
|
|
91
89
|
```bash
|
|
90
|
+
node bin/loop-agent.js docs audit --repo-root .
|
|
91
|
+
bash scripts/check-doc-index.sh
|
|
92
|
+
bash scripts/check-doc-links.sh
|
|
92
93
|
bash scripts/check-repo.sh
|
|
93
94
|
```
|
|
94
95
|
|
|
96
|
+
涉及 `website/docs/` 时再跑 `npm run docs:build`,并按 `skills/loop-agent/references/docs-converge.md` 同步 `overview/roadmap.md` 等站上活页。
|
|
97
|
+
|
|
95
98
|
Windows 上通过 Git Bash 或已配置的兼容 Bash 运行脚本。实际文件操作使用平台原生路径;`/` 仅用于 repo 引用、JSON/Markdown 证据引用和 glob 约定。
|
|
96
99
|
|
|
97
100
|
完整本地门禁:
|
package/docs/agent-dag-runner.md
CHANGED
|
@@ -17,15 +17,40 @@ loop-agent run-dag --dag <temp-dir>/<task-id>-dag.json --cwd .
|
|
|
17
17
|
- `static`:确定性生成的 artifacts 或 notes
|
|
18
18
|
- `shell`:验证与文件系统检查
|
|
19
19
|
- `pi`:规划、review、诊断;节点设 `toolProfile: "write"` 时有界写入
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
## Retry (read-only Pi nodes)
|
|
22
|
+
|
|
23
|
+
planner/scout/reviewer/verifier/closeout 角色的只读 Pi 节点可声明 opt-in `retryPolicy`,用于在同一 run 内有界重试模型连接中断、provider 限流、临时不可用或请求 timeout。生成器会为这些安全节点自动声明默认策略:总尝试次数 3(手工配置上限 5),指数退避,单次等待上限 30s。
|
|
24
|
+
|
|
25
|
+
- 仅以下原始失败分类默认可重试:`timeout`、`network`、`rate-limit`、`unavailable`。
|
|
26
|
+
- `quota`、`auth`、`invalid-output`、`write-guard`、`decision-envelope` 与未知失败不重试。`quota` 不是 rate limit,不会被自动重试。
|
|
27
|
+
- 资格由确定性 helper 判断:仅 `writePolicy=read-only|none`(或 Pi 默认只读)的 planner/scout/reviewer/verifier/closeout 可用。supervisor、implementer、writer(`toolProfile=write` 或 `writePolicy=exclusive`)、docs-only、dynamic、shell、static 与 decision-gate 节点一律不重试,DAG validation 会拒绝其策略。
|
|
28
|
+
- 每次 attempt 写入独立不可变证据(`<node-id>/attempt-<n>.json`,run-relative path),最终 node record 的 `attempts` 字段引用完整 attempt 历史;后一次成功不会覆盖前一次失败证据。
|
|
29
|
+
- 重试期间复用同一 run、controller identity、skill snapshot、prompt、model 与上游输入。节点终态的 `durationMs`、`tokensUsed`、`parsedEvents` 聚合全部 attempts;退避等待会刷新 `lastActivityAt`,避免被误判为 node-quiet。当前退避会占用该节点所在的并发槽。
|
|
30
|
+
|
|
31
|
+
示例:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"retryPolicy": {
|
|
36
|
+
"maxAttempts": 3,
|
|
37
|
+
"backoff": "exponential",
|
|
38
|
+
"initialDelayMs": 2000,
|
|
39
|
+
"maxDelayMs": 30000,
|
|
40
|
+
"retryCategories": ["timeout", "network", "rate-limit", "unavailable"]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
未声明 `retryPolicy` 的历史 DAG 行为不变(单次执行、无 `attempts` 字段,也不新增 attempt artifact)。
|
|
21
46
|
|
|
22
47
|
## Skills
|
|
23
48
|
|
|
24
|
-
DAG spec 可声明 `defaults.skills`、`skillsByRole` 与节点级 `skills`。Runner
|
|
49
|
+
DAG spec 可声明 `defaults.skills`、`skillsByRole` 与节点级 `skills`。Runner 优先从目标项目 `.agents/skills/<skill-name>/SKILL.md` 解析本地指令,再回退到包内 `skills/`,并在各节点 `skills.json` artifact 中记录解析元数据。
|
|
25
50
|
|
|
26
51
|
执行前可用 `dag validate --strict-skills` 做 opt-in skill audit;该门禁会在 missing/error/truncated skill 或 unresolved reference 出现时失败。默认 role skill 应来自 `docs/skills/vetted-skill-registry.md` 中记录的 repo-local wrapper。
|
|
27
52
|
|
|
28
|
-
`loop-agent` skill 位于 `skills/loop-agent/SKILL.md
|
|
53
|
+
目标项目的 `loop-agent` skill 位于 `.agents/skills/loop-agent/SKILL.md`。loop-agent 源仓库和 npm 包内置版本仍位于 `skills/loop-agent/SKILL.md`;遗留根路径 `skill/SKILL.md` 仅为旧 worktree 保留兼容 fallback。
|
|
29
54
|
|
|
30
55
|
## Artifacts
|
|
31
56
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# 架构文档索引
|
|
2
|
+
|
|
3
|
+
本目录是 loop-agent 维护者架构文档入口。每篇文档回答一个具体问题,不重复 `runtime-boundaries.md` 的依赖方向表与 governance-hook 表;遇到契约级事实请回到该文件。
|
|
4
|
+
|
|
5
|
+
## 阅读路径
|
|
6
|
+
|
|
7
|
+
建议按以下顺序阅读——先全景,再主路径,再边界/事实,最后路线:
|
|
8
|
+
|
|
9
|
+
1. `runtime-boundaries.md` — runtime 层边界、依赖方向与治理 hook 的机器校验契约(**先读,是其他文档的边界真源**)。
|
|
10
|
+
2. `system-overview.md` — loop-agent / agent-worker / 治理层 / 外部系统的全景关系。
|
|
11
|
+
3. `dag-execution.md` — Agent DAG 主调用链、rank 调度、executor、skill snapshot、生命周期。
|
|
12
|
+
4. `worker-and-feature.md` — agent-worker 子进程边界、controller identity、Task Pool、Feature 与 Observe。
|
|
13
|
+
5. `facts-and-state.md` — `.harness/` 各根目录、canonical facts、derived read models 与不可变规则。
|
|
14
|
+
6. `evolution.md` — 当前已实现能力 vs 第 3–6 月未来方向(明确标注规划/未实现)。
|
|
15
|
+
|
|
16
|
+
## 事实与规划的区分
|
|
17
|
+
|
|
18
|
+
- **当前事实源**:`src/` 源码、发布 CLI、`docs/exec-plans/completed/`、`docs/reports/current-capability-summary.md`、ADR 0001–0003。
|
|
19
|
+
- **规划/设计输入**:`docs/design/`(含 `dynamic-workflow-dag-engine-roadmap.md`、`六个月规划.md`)。这些文件已带 2026-07-14 校准条;凡未兑现的 phase 段落是设计输入,**不是**已实现证明。
|
|
20
|
+
- 凡本目录文档描述未来能力,一律使用「规划 / 未实现 / 前瞻」标签。
|
|
21
|
+
|
|
22
|
+
## 与其他文档的分工
|
|
23
|
+
|
|
24
|
+
- 本目录不复制 `runtime-boundaries.md` 的 import 方向表、governance-hook 表与版本化自举边界表,只交叉引用。
|
|
25
|
+
- 用法与操作说明在 `website/docs/`(使用者双树),不在本目录重复。
|
|
26
|
+
- 本目录文档随发布包发布(npm `files` 显式条目 + `docs/init-surface.manifest.json` `packageRequired`),但 **不**投影到目标项目 init surface;目标项目 init 仍只投影语言无关的 `runtime-boundaries.md`。
|