@tea-agent/loop-agent 0.35.4-beta.0 → 0.36.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 +4 -2
- package/CHANGELOG.md +55 -7
- package/dist/application/task-lifecycle/advance.js +1 -0
- package/dist/application/task-lifecycle/observe.js +15 -0
- package/dist/application/task-lifecycle/plan-transitions.js +15 -0
- package/dist/build-stamp.json +3 -3
- package/dist/commands/init-upgrade.js +351 -19
- package/dist/commands/init.js +14 -67
- package/dist/commands/run-dag-progress.js +14 -0
- package/dist/commands/task-advance.js +33 -3
- package/dist/executors/dag-pi-executor.js +3 -1
- package/dist/shared/operator/capabilities.js +125 -11
- package/dist/task/source-prepare/completeness.js +17 -0
- package/dist/task/source-prepare/parse-intent.js +15 -1
- package/dist/worker/console/chat/artifact-card.js +8 -1
- package/dist/worker/console/chat/chat-event-store.js +61 -0
- package/dist/worker/console/chat/human-gate-card.js +9 -1
- package/dist/worker/console/chat/operation-card.js +71 -2
- package/dist/worker/console/chat/pi-runtime.js +69 -30
- package/dist/worker/console/chat/routes.js +27 -4
- package/dist/worker/console/chat/semantic-activity.js +465 -0
- package/dist/worker/console/chat/turn-process.js +31 -12
- package/dist/worker/console/operation-run-facts.js +190 -0
- package/dist/worker/console/operation-runner.js +107 -6
- package/dist/worker/console/operation-wait.js +314 -0
- package/dist/worker/console/operator-actions.js +153 -2
- package/dist/worker/console/static/assets/index-2OeZODxk.js +57 -0
- package/dist/worker/console/static/assets/index-DVJlUL8X.css +1 -0
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/activity-journey.js +125 -0
- package/dist/worker/console/static-src/operator-chat/activity-rail-presentation.js +73 -0
- package/dist/worker/console/static-src/operator-chat/activity-references.js +20 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +69 -31
- package/dist/worker/console/static-src/operator-chat/slash-palette-layout.js +24 -0
- package/dist/worker/console/static-src/operator-chat/slash-palette-nav.js +141 -0
- package/dist/worker/console/static-src/operator-chat/spatial-overlay.js +2 -1
- package/dist/worker/console/static-src/operator-chat/useActivityRailTransition.js +59 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +16 -5
- package/dist/worker/console/static-src/operator-chat/useComposer.js +30 -7
- package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +7 -3
- package/dist/worker/observe/static/operator-chrome.js +1 -1
- package/dist/workflows/dag/failure-routing.js +4 -9
- package/dist/workflows/dag/init-hybrid.js +74 -2
- package/dist/workflows/dag/lifecycle.js +0 -4
- package/dist/workflows/dag/report.js +0 -6
- package/docs/README.md +3 -3
- package/docs/architecture/evolution.md +102 -67
- package/docs/templates/frontend-task-constraints.md +7 -13
- package/docs/templates/init-managed-agents.md +5 -2
- package/harness.json +2 -2
- package/package.json +1 -1
- package/skills/loop-agent/SKILL.md +1 -0
- package/skills/loop-agent/references/command-reference.md +2 -0
- package/dist/worker/console/static/assets/index-DRqZiQ7J.css +0 -1
- package/dist/worker/console/static/assets/index-DuVLjCIT.js +0 -57
|
@@ -730,6 +730,7 @@ function resolveImplementPaths(taskConfig, options = {}) {
|
|
|
730
730
|
const allowed = [...taskConfig.allowedPaths];
|
|
731
731
|
const forbidden = mergeForbiddenPaths(taskConfig);
|
|
732
732
|
const repoRoot = options.repoRoot;
|
|
733
|
+
let companions = [];
|
|
733
734
|
// Only consult the catalog when writer paths can touch docs/* so non-docs
|
|
734
735
|
// temp fixtures without a catalog keep working; docs writers still fail closed.
|
|
735
736
|
const mayNeedDocIndex = allowed.some((entry) => {
|
|
@@ -742,6 +743,7 @@ function resolveImplementPaths(taskConfig, options = {}) {
|
|
|
742
743
|
paths: allowed,
|
|
743
744
|
forbiddenPaths: forbidden,
|
|
744
745
|
});
|
|
746
|
+
companions = closure.companions;
|
|
745
747
|
const explicitAllowedPaths = new Set(allowed.map((entry) => entry.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+$/, "")));
|
|
746
748
|
const missingCompanions = closure.companions.filter((companion) => !explicitAllowedPaths.has(companion));
|
|
747
749
|
if (missingCompanions.length > 0) {
|
|
@@ -751,11 +753,13 @@ function resolveImplementPaths(taskConfig, options = {}) {
|
|
|
751
753
|
return {
|
|
752
754
|
allowedPaths: allowed,
|
|
753
755
|
writeSet: [...allowed],
|
|
756
|
+
docIndexCompanions: companions,
|
|
754
757
|
};
|
|
755
758
|
}
|
|
756
759
|
return {
|
|
757
760
|
allowedPaths: ["**"],
|
|
758
761
|
writeSet: [IMPLEMENT_WRITESET_PLACEHOLDER],
|
|
762
|
+
docIndexCompanions: [],
|
|
759
763
|
};
|
|
760
764
|
}
|
|
761
765
|
function shellQuote(value) {
|
|
@@ -1802,6 +1806,15 @@ export function buildStandardHybridDagFromTask(sources) {
|
|
|
1802
1806
|
subtask_prompt: [
|
|
1803
1807
|
"Implement the approved plan with minimal focused changes.",
|
|
1804
1808
|
"Stay within writeSet. Do not write root artifacts/** unless artifacts paths are explicitly declared in writeSet.",
|
|
1809
|
+
"Apply changes by calling the write/edit tools so files change on disk. Do not paste the new code in your response instead of writing it: the runner verifies the working-tree diff mechanically, and a response-only change is an empty diff that fails this node.",
|
|
1810
|
+
"Edit existing files with the structured edit/write tools. NEVER rewrite Markdown (or any file with quoting/backticks/indentation-sensitive content) via bash sed/awk/echo redirection: escaping mistakes silently corrupt the file and self-repair loops burn the run. If a bash text-substitution already damaged a file, restore the damaged region with the edit tool against the original content instead of stacking more substitutions.",
|
|
1811
|
+
"The plan node already designed the changes — that design is your input, not your output. Your job is to write those changes into the files in writeSet. The task is not done until the files on disk contain the changes.",
|
|
1812
|
+
"If the task only adds tests/docs that use existing code as-is, forbidden implementation paths (e.g. src/**) do not block you: you never need to write them. Write the tests/docs and report changed.",
|
|
1813
|
+
...(implementPaths.docIndexCompanions.length > 0
|
|
1814
|
+
? [
|
|
1815
|
+
`Doc index sync is MANDATORY: ${implementPaths.docIndexCompanions.join(", ")} are catalog index files for this writeSet. When you add, rename, or remove any indexed file, you MUST also update ${implementPaths.docIndexCompanions.join(" and ")} in the same run (append or fix the matching index entry following the existing line style). Verification runs check-doc-index and fails the run when a new file is missing from the index. Skipping this sync is not "minimal change" — it is an incomplete delivery.`,
|
|
1816
|
+
]
|
|
1817
|
+
: []),
|
|
1805
1818
|
writerDeliveryContract(taskConfig),
|
|
1806
1819
|
sourceContext,
|
|
1807
1820
|
]
|
|
@@ -2565,7 +2578,7 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
2565
2578
|
allowedPaths: readOnlyPaths,
|
|
2566
2579
|
forbiddenPaths,
|
|
2567
2580
|
skills: FRONTEND_IMPLEMENTATION_SKILLS,
|
|
2568
|
-
outputContract: "Markdown implementation plan with Requirement Coverage, Implementation Steps, Target Files, UI State Handling, Styling / Component Strategy, Interaction Notes, Mock / API Strategy, Dependency Policy, Verification Plan, Real Integration Gap, and Residual Risks, ending with exactly ONE fenced json object (
|
|
2581
|
+
outputContract: "Markdown implementation plan with Requirement Coverage, Implementation Steps, Target Files, UI State Handling, Styling / Component Strategy, Interaction Notes, Mock / API Strategy, Dependency Policy, Verification Plan, Real Integration Gap, and Residual Risks, ending with exactly ONE fenced json object (```json ... ```) conforming to frontend-implementation-contract-v1. This fenced block is the single authoritative implementation contract the prewrite gate materializes; it must appear exactly once and must not contain or be followed by any raw JSON or extra fenced block. No file writes.",
|
|
2569
2582
|
subtask_prompt: [
|
|
2570
2583
|
"Based on frontend-contract-pi, frontend-scout-pi, task sources, and the generation-time Mock capability evidence, return a minimal frontend implementation plan.",
|
|
2571
2584
|
"Select the Mock / API strategy inside the plan and structured contract. Carry endpoint/fixture mapping, explicit activation, production-default-off rule, verification commands, and Real Integration Gap into both outputs.",
|
|
@@ -2623,7 +2636,7 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
2623
2636
|
allowedPaths: readOnlyPaths,
|
|
2624
2637
|
forbiddenPaths,
|
|
2625
2638
|
skills: FRONTEND_IMPLEMENTATION_SKILLS,
|
|
2626
|
-
outputContract: "When the initial design review requests revision, return a complete Markdown revision plan followed by exactly ONE fenced json object (
|
|
2639
|
+
outputContract: "When the initial design review requests revision, return a complete Markdown revision plan followed by exactly ONE fenced json object (```json ... ```) conforming to frontend-implementation-contract-v1. This fenced block is the single authoritative implementation contract the prewrite gate materializes; it must appear exactly once and must not contain or be followed by any raw JSON or extra fenced block. Do NOT include multiple fenced JSON blocks; only the single authoritative contract JSON block is accepted. No file writes.",
|
|
2627
2640
|
subtask_prompt: [
|
|
2628
2641
|
"Consume frontend-plan-pi (original plan) and frontend-design-review-pi (first design review findings).",
|
|
2629
2642
|
"This node runs only when frontend-design-review-pi emitted VERDICT: request-revision. Produce a complete revised implementation plan that addresses every Required Plan Correction from the design findings.",
|
|
@@ -2770,6 +2783,12 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
2770
2783
|
"frontend-prewrite-gate-shell confirmed the effective plan/review, requirement coverage, Mock policy, and contract. Stay within writeSet and preserve unrelated files.",
|
|
2771
2784
|
"For native, browser-intercept, or request-adapter, implement contract-aligned fixtures/states and a dev/test-only activation boundary in this same writer. For not-needed, do not add Mock files or a framework and state the positive reason.",
|
|
2772
2785
|
"Do not write root artifacts/** unless explicitly included in writeSet. Do not claim Browser/visual verification.",
|
|
2786
|
+
"Edit existing files with the structured edit/write tools. NEVER rewrite Markdown (or any file with quoting/backticks/indentation-sensitive content) via bash sed/awk/echo redirection: escaping mistakes silently corrupt the file and self-repair loops burn the run.",
|
|
2787
|
+
...(implementPaths.docIndexCompanions.length > 0
|
|
2788
|
+
? [
|
|
2789
|
+
`Doc index sync is MANDATORY: ${implementPaths.docIndexCompanions.join(", ")} are catalog index files for this writeSet. When you add, rename, or remove any indexed file, you MUST also update ${implementPaths.docIndexCompanions.join(" and ")} in the same run (append or fix the matching index entry following the existing line style). Verification runs check-doc-index and fails the run when a new file is missing from the index.`,
|
|
2790
|
+
]
|
|
2791
|
+
: []),
|
|
2773
2792
|
writerDeliveryContract(taskConfig),
|
|
2774
2793
|
]
|
|
2775
2794
|
.filter((value) => Boolean(value))
|
|
@@ -2825,6 +2844,11 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
2825
2844
|
"The repair assessment and canonical implementation contract are complete inputs for this phase. Do not re-open task sources, OpenSpec, AI workspace, plan/revision, or design-review prose, and do not repeat repository-wide discovery.",
|
|
2826
2845
|
"Do not change lint/type/test config, do not add .skip/.only, do not comment out real requests, do not default-enable Mock, do not add dependencies.",
|
|
2827
2846
|
"Do not re-plan requirements or expand allowed paths. Browser/visual remain not-run.",
|
|
2847
|
+
...(implementPaths.docIndexCompanions.length > 0
|
|
2848
|
+
? [
|
|
2849
|
+
`Doc index sync is MANDATORY: ${implementPaths.docIndexCompanions.join(", ")} are catalog index files for this writeSet. When your repair adds, renames, or removes any indexed file, update ${implementPaths.docIndexCompanions.join(" and ")} in the same run; verification runs check-doc-index and fails the run on a missing index entry.`,
|
|
2850
|
+
]
|
|
2851
|
+
: []),
|
|
2828
2852
|
writerDeliveryContract(taskConfig),
|
|
2829
2853
|
]
|
|
2830
2854
|
.filter((value) => Boolean(value))
|
|
@@ -4714,6 +4738,53 @@ function buildMultiPerspectiveReviewNodes(input) {
|
|
|
4714
4738
|
].join("\n\n"),
|
|
4715
4739
|
}));
|
|
4716
4740
|
const reviewIds = reviewNodes.map((n) => n.id);
|
|
4741
|
+
if (input.structuredVerdictGate) {
|
|
4742
|
+
const aggregateNodeId = `${input.nodePrefix}aggregate-pi`;
|
|
4743
|
+
const aggregateNode = {
|
|
4744
|
+
id: aggregateNodeId,
|
|
4745
|
+
depends_on: reviewIds,
|
|
4746
|
+
role: "reviewer",
|
|
4747
|
+
executor: "pi",
|
|
4748
|
+
complexity: "HIGH",
|
|
4749
|
+
writePolicy: "read-only",
|
|
4750
|
+
allowedPaths: input.allowedPaths,
|
|
4751
|
+
forbiddenPaths: commonForbiddenPaths(input.sources),
|
|
4752
|
+
outputContract: "Plain Markdown; first non-empty line is exactly VERDICT: pass only when every upstream perspective emitted VERDICT: pass, otherwise VERDICT: request-revision. No file writes.",
|
|
4753
|
+
subtask_prompt: [
|
|
4754
|
+
`Aggregate ${input.gateLabel} without changing any review finding.`,
|
|
4755
|
+
`Inspect every upstream result: ${reviewIds.join(", ")}.`,
|
|
4756
|
+
"First non-empty line must be exactly VERDICT: pass only when every upstream first verdict is VERDICT: pass; otherwise use VERDICT: request-revision.",
|
|
4757
|
+
"List each upstream node and its observed verdict as evidence. Do not invent or override a missing/request-revision verdict.",
|
|
4758
|
+
"Read-only: do not modify files.",
|
|
4759
|
+
].join("\n\n"),
|
|
4760
|
+
};
|
|
4761
|
+
const gateNode = {
|
|
4762
|
+
id: input.gateId,
|
|
4763
|
+
depends_on: [aggregateNodeId],
|
|
4764
|
+
role: "verifier",
|
|
4765
|
+
executor: "shell",
|
|
4766
|
+
complexity: "LOW",
|
|
4767
|
+
writePolicy: "read-only",
|
|
4768
|
+
allowedPaths: commonReadOnlyPaths(input.sources),
|
|
4769
|
+
forbiddenPaths: commonForbiddenPaths(input.sources),
|
|
4770
|
+
outputContract: `Structured verdict gate: exit 0 only when ${aggregateNodeId} emits VERDICT: pass.`,
|
|
4771
|
+
subtask_prompt: `Structured gate for ${input.gateLabel}: all perspectives must pass before downstream apply/promote.`,
|
|
4772
|
+
shell: {
|
|
4773
|
+
commands: [],
|
|
4774
|
+
verdictGate: {
|
|
4775
|
+
fromNodeId: aggregateNodeId,
|
|
4776
|
+
accept: ["pass"],
|
|
4777
|
+
routingAccept: ["request-revision"],
|
|
4778
|
+
source: "verdict-line",
|
|
4779
|
+
lineMode: "first-verdict-line",
|
|
4780
|
+
label: input.gateLabel,
|
|
4781
|
+
},
|
|
4782
|
+
cwd: ".",
|
|
4783
|
+
timeoutMs: 60000,
|
|
4784
|
+
},
|
|
4785
|
+
};
|
|
4786
|
+
return [...reviewNodes, aggregateNode, gateNode];
|
|
4787
|
+
}
|
|
4717
4788
|
const aggregateScript = buildMultiPerspectiveReviewAggregateScript(reviewIds, input.gateLabel);
|
|
4718
4789
|
const gateNode = {
|
|
4719
4790
|
id: input.gateId,
|
|
@@ -4973,6 +5044,7 @@ function buildKnowledgeSyncMultiReviewNodes(sources, featureId) {
|
|
|
4973
5044
|
`Primary draft path: ${knowledgeSyncDraftRelPath(featureId)}.`,
|
|
4974
5045
|
"Apply is blocked until all perspectives pass. Do not approve fabricated verification pass.",
|
|
4975
5046
|
],
|
|
5047
|
+
structuredVerdictGate: true,
|
|
4976
5048
|
});
|
|
4977
5049
|
}
|
|
4978
5050
|
function buildKnowledgeSyncApplyNode(sources, featureId) {
|
|
@@ -743,7 +743,6 @@ function findDoctorFailureNode(state) {
|
|
|
743
743
|
nodeId: state.pausedByNodeId,
|
|
744
744
|
status: node?.status,
|
|
745
745
|
rawFailureCategory: node?.failureCategory,
|
|
746
|
-
skippedReason: node?.skippedReason,
|
|
747
746
|
};
|
|
748
747
|
}
|
|
749
748
|
const errorEntry = Object.entries(state.nodes).find(([, node]) => node.status === "ERROR");
|
|
@@ -759,7 +758,6 @@ function findDoctorFailureNode(state) {
|
|
|
759
758
|
nodeId: selected[0],
|
|
760
759
|
status: selected[1].status,
|
|
761
760
|
rawFailureCategory: selected[1].failureCategory,
|
|
762
|
-
skippedReason: selected[1].skippedReason,
|
|
763
761
|
};
|
|
764
762
|
}
|
|
765
763
|
async function readRunOwnedBackendTestClassification(runDir) {
|
|
@@ -788,7 +786,6 @@ async function resolveDoctorFailureRouting(input) {
|
|
|
788
786
|
normalizedFailureCategory: "unknown",
|
|
789
787
|
nodeId: input.nodeId,
|
|
790
788
|
productLineFailureCategory: classifiedCategory,
|
|
791
|
-
skippedReason: input.skippedReason,
|
|
792
789
|
});
|
|
793
790
|
}
|
|
794
791
|
return routeDagFailure(input);
|
|
@@ -810,7 +807,6 @@ async function formatDagDoctorMarkdown(repoRoot, runId) {
|
|
|
810
807
|
rawFailureCategory,
|
|
811
808
|
normalizedFailureCategory: normalizedCategory,
|
|
812
809
|
nodeId: failure.nodeId,
|
|
813
|
-
skippedReason: failure.skippedReason,
|
|
814
810
|
});
|
|
815
811
|
const evidence = failure.nodeId
|
|
816
812
|
? path.join(located.runDir, failure.nodeId, "result.summary.md")
|
|
@@ -441,7 +441,6 @@ export async function buildDagRunReportEntry(input) {
|
|
|
441
441
|
normalizedFailureCategory,
|
|
442
442
|
nodeId,
|
|
443
443
|
executor: node.executor,
|
|
444
|
-
skippedReason: node.skippedReason,
|
|
445
444
|
});
|
|
446
445
|
const followUp = node.status === "ERROR" || node.status === "SKIPPED"
|
|
447
446
|
? recommendFollowUpForFailureCategory(node.failureCategory)
|
|
@@ -506,7 +505,6 @@ export async function buildDagRunReportEntry(input) {
|
|
|
506
505
|
normalizedFailureCategory: normalizeDagFailureCategory(pausedNode.failureCategory, pausedNode.status),
|
|
507
506
|
failureCategory: pausedNode.failureCategory,
|
|
508
507
|
nodeId: input.state.pausedByNodeId,
|
|
509
|
-
skippedReason: pausedNode.skippedReason,
|
|
510
508
|
}
|
|
511
509
|
: firstActionableNode
|
|
512
510
|
? {
|
|
@@ -515,7 +513,6 @@ export async function buildDagRunReportEntry(input) {
|
|
|
515
513
|
normalizeDagFailureCategory(firstActionableNode.failureCategory, firstActionableNode.status),
|
|
516
514
|
failureCategory: firstActionableNode.failureCategory,
|
|
517
515
|
nodeId: firstActionableNode.nodeId,
|
|
518
|
-
skippedReason: input.state.nodes[firstActionableNode.nodeId]?.skippedReason,
|
|
519
516
|
}
|
|
520
517
|
: {
|
|
521
518
|
status: input.state.status,
|
|
@@ -532,9 +529,6 @@ export async function buildDagRunReportEntry(input) {
|
|
|
532
529
|
rawFailureCategory: runRecoverySource.failureCategory,
|
|
533
530
|
normalizedFailureCategory: runRecoverySource.normalizedFailureCategory,
|
|
534
531
|
nodeId: "nodeId" in runRecoverySource ? runRecoverySource.nodeId : undefined,
|
|
535
|
-
skippedReason: "skippedReason" in runRecoverySource
|
|
536
|
-
? runRecoverySource.skippedReason
|
|
537
|
-
: undefined,
|
|
538
532
|
});
|
|
539
533
|
const runFollowUp = input.state.status === "failed" ||
|
|
540
534
|
input.state.status === "partial_failed"
|
package/docs/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`docs/` 是 loop-agent 源仓的治理文档根目录。新读者不需要先浏览所有文件,先按任务选择入口,再由目录 README 或 `docs/document-catalog.json` 判断文档身份。
|
|
4
4
|
|
|
5
|
-
**维护日:2026-
|
|
5
|
+
**维护日:2026-08-16** — 对齐 `@tea-agent/loop-agent@0.35.3`。版本事实以根 `CHANGELOG.md` 与 `package.json` 为准;能力短摘要见 `reports/current-capability-summary.md`。
|
|
6
6
|
|
|
7
7
|
## 我现在要做什么?
|
|
8
8
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
| --- | --- | --- |
|
|
11
11
|
| 理解当前能力与边界 | `reports/current-capability-summary.md` | `architecture/README.md`、`website/docs/overview/roadmap.md` |
|
|
12
12
|
| 开始一个受治理功能变更 | `governance/feature-workflow.md` | `governance/verification-matrix.md`、`templates/exec-plan.md` |
|
|
13
|
-
| 跑或恢复 Agent DAG | `runtime/agent-dag-runner.md` | `runtime/agent-dag-recovery-playbook.md`、`runtime/loop-agent-harness.md
|
|
13
|
+
| 跑或恢复 Agent DAG | `runtime/agent-dag-runner.md` | `runtime/agent-dag-recovery-playbook.md`、`runtime/loop-agent-harness.md`;Operator Chat Phase 1/P0 的 meaningful wait 与安全 terminal summary 已实现,Phase 2/3 仍见 active design |
|
|
14
14
|
| 判断架构边界 | `architecture/README.md` | `architecture/runtime-boundaries.md` |
|
|
15
15
|
| 查设计输入而非实现证明 | `design/README.md` | 对应设计文档;视觉参考见 `design/visual-references/README.md`,归档设计见 `design/archive/README.md` |
|
|
16
16
|
| 接手进行中任务 | `exec-plans/active/README.md` | 对应 active plan,再读 `progress/README.md` |
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
| 选择 taskKind、治理 profile 和 Agent DAG 路径 | `governance/feature-workflow.md` |
|
|
27
27
|
| 选择快速、标准或完整验证命令 | `governance/verification-matrix.md` |
|
|
28
28
|
| 理解 CLI、runtime 和初始化能力边界 | `runtime/loop-agent-harness.md` |
|
|
29
|
-
| 运行 DAG、查看报告或处理失败 | `runtime/agent-dag-runner.md`、`runtime/agent-dag-recovery-playbook.md` |
|
|
29
|
+
| 运行 DAG、查看报告或处理失败 | `runtime/agent-dag-runner.md`、`runtime/agent-dag-recovery-playbook.md`;Operator Chat P0 closeout 见 `reports/feature/2026-08-14-operator-chat-dag-recovery-p0.md` |
|
|
30
30
|
| 按 TDD、验证和调试纪律推进修复 | `governance/harness-methodology-tdd.md`、`governance/harness-methodology-verification.md`、`governance/harness-methodology-debugging.md` |
|
|
31
31
|
| 执行真实 backend-test provider 验证 | `runtime/backend-test-live-campaign.md` |
|
|
32
32
|
| 判断单任务 loop-agent Production Readiness | `operations/production-readiness.md` |
|
|
@@ -1,73 +1,108 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 架构演进:当前内核与未来边界
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
本文区分 `loop-agent` 当前已实现架构和第 3–6 月前瞻。当前事实以代码、`CHANGELOG.md`、`docs/reports/current-capability-summary.md` 与 completed/active plans 为准;路线以 `docs/design/active/六个月规划.md` 为准。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
对照版本:`@tea-agent/loop-agent@0.35.3`(2026-08-16)。
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 当前架构
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
```text
|
|
10
|
+
Skills / AGENTS
|
|
11
|
+
↓
|
|
12
|
+
loop-agent CLI → application use cases → workflow runtime → Pi/Shell/Static executors
|
|
13
|
+
↓ ↓
|
|
14
|
+
task source / contracts run-owned facts / artifacts / receipts
|
|
15
|
+
|
|
16
|
+
agent-worker CLI / Console
|
|
17
|
+
↓ frozen published controller subprocess
|
|
18
|
+
loop-agent CLI
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 已实现能力
|
|
22
|
+
|
|
23
|
+
| 域 | 当前事实 | 权威入口 |
|
|
10
24
|
| --- | --- | --- |
|
|
11
|
-
|
|
|
12
|
-
|
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
25
|
+
| 标准生命周期 | `task advance` 是唯一标准 mutation 入口;`task status` 只读;run 级 `dag` 命令保留为 advanced recovery/forensic | ADR 0008、`docs/governance/feature-workflow.md` |
|
|
26
|
+
| DAG kernel | Contract/Scout/Plan/Implement/Verify/Closeout;dynamic workflow、pause/resume、doctor/report/rerun/reconcile | `dag-execution.md`、`agent-dag-runner.md` |
|
|
27
|
+
| 写入与契约 | Pi-only writer、Task Contract、DagSpec v4 binding、writeSet review、writer admission、write guard | ADR 0001、`runtime-boundaries.md` |
|
|
28
|
+
| 专用 taskKind | `frontend-implementation`、`backend-test`、`frontend-test`、knowledge 路径;显式 taskKind 贯穿 intake→task→DAG | `CHANGELOG.md [0.35.0]`–`[0.35.3]` |
|
|
29
|
+
| Backend test | map-shard、execution readiness、generated-output conflict、collection/pytest 结构化失败、恢复加固 | completed plans、`CHANGELOG.md [0.30.0]`–`[0.31.1]` |
|
|
30
|
+
| Frontend implementation | canonical prewrite result、两层 writer gate、统一 writer helper、rollback journal、child recovery、root manifest | completed `2026-08-13-frontend-implementation-dag-optimization.md` |
|
|
31
|
+
| Frontend test | lean 默认 DAG、case map、evidence/quality report;安全边界 hard gate,内容质量 advisory | completed `2026-08-07-frontend-test-dag-lean-nodes.md` |
|
|
32
|
+
| Worker / Feature | TaskSpec、feature-scoped Task Pool、Ready Planner、Outcome、Verification Bundle、Delivery/Closeout | `worker-and-feature.md`、current capability summary |
|
|
33
|
+
| Worker readiness baseline | Attempt identity、immutable owner、lineage/revision、task-scoped lease、controller protocol、acceptance、reconcile | Agent Worker PR v1 Phase 1–7 / `0.32.0` |
|
|
34
|
+
| Operator Surface | 裸 `agent-worker console`;Operate、`/inspect/`、Operator Chat、recovery CTA、intake bridge | ADR 0005、0011–0013 |
|
|
35
|
+
| 自举与验证 | controller identity、skill snapshot、deterministic/live canary、verified tarball、`verify:tree` receipt | `runtime-boundaries.md`、verification matrix |
|
|
36
|
+
|
|
37
|
+
### 当前不变量
|
|
38
|
+
|
|
39
|
+
- `loop-agent` 拥有 repo-local DAG kernel;`agent-worker` 通过冻结的已发布 CLI 子进程执行,不复制内核。
|
|
40
|
+
- 受治理 Agent writer 只有 Pi;`cursor-prompt` 只是显式 one-shot sidecar。
|
|
41
|
+
- shell verification / Final Verification 是完成权威;模型 verdict 与 UI projection 不是。
|
|
42
|
+
- Console 是本地 loopback 控制面;canonical mutation 仍经 sibling CLI/application contract。
|
|
43
|
+
- controller identity 和 run-owned skill snapshot 分属不同冻结层,不能互相替代。
|
|
44
|
+
- recovery 必须保留原始终态并生成显式 reconciliation/continuation 事实。
|
|
45
|
+
|
|
46
|
+
完整 import 与 runtime 依赖规则见 `runtime-boundaries.md`,本文不复制其机器校验表。
|
|
47
|
+
|
|
48
|
+
## 当前尚未 Ready
|
|
49
|
+
|
|
50
|
+
| 项目 | 状态 |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| Agent Worker PR v1 Phase 8 | `NOT_READY`:burn-in、live Closeout、C4/C7 crash 未收口;live Pi canary 已验证 |
|
|
53
|
+
| Fullstack release train | I40 Delivery/Closeout live;FC-B orphan recovery failed,overall=partial |
|
|
54
|
+
| Operator Chat primary session | 主体能力已发布;event recovery / dogfood 门槛仍 open |
|
|
55
|
+
| frontend-test | formal V7 smoke 与独立成功率报告 open |
|
|
56
|
+
| backend-test | 真实 provider 五路径 smoke blocked-external |
|
|
57
|
+
|
|
58
|
+
## 下一阶段目标架构
|
|
59
|
+
|
|
60
|
+
未来能力不直接塞入当前 runtime,而是增加两个外层边界:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
Organization Control Plane
|
|
64
|
+
Feature Graph / Queue / Policy / Approval / Remote Adapters
|
|
65
|
+
↓ assignment + lease
|
|
66
|
+
Isolated Execution Plane
|
|
67
|
+
Workspace Manager / published loop-agent / repo-local agent-worker projection
|
|
68
|
+
↓ immutable refs + receipts
|
|
69
|
+
Evidence & Trust Plane
|
|
70
|
+
Artifact Manifest / Git & CI Receipts / Audit / Metrics / SLO
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 演进顺序
|
|
74
|
+
|
|
75
|
+
| 阶段 | 新边界 | 不能破坏的旧边界 |
|
|
45
76
|
| --- | --- | --- |
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
77
|
+
| 远程交付 | Git/PR/CI adapter、head-bound receipt、approval | repo-local writer gate 与 verification authority |
|
|
78
|
+
| 隔离 Worker | workspace lease、fencing、credential/network policy、artifact projection | frozen controller 与 DAG run facts |
|
|
79
|
+
| 跨仓库 Feature | repo-qualified TaskRef、contract hash、saga/compensation | 每仓库独立 Task/PR/CI/terminal state |
|
|
80
|
+
| 生产治理 | versioned policy、audit、SLO、semi-auto lane | owner opt-in、可撤销授权、fail-closed |
|
|
81
|
+
|
|
82
|
+
### 未来合同
|
|
83
|
+
|
|
84
|
+
- `AssignmentEnvelope`
|
|
85
|
+
- `WorkspaceLease`
|
|
86
|
+
- `ControllerAttestation`
|
|
87
|
+
- `GitMutationReceipt`
|
|
88
|
+
- `CiRunReceipt`
|
|
89
|
+
- `ArtifactManifest`
|
|
90
|
+
- `PolicyDecision`
|
|
91
|
+
- `FeatureCloseout`
|
|
92
|
+
|
|
93
|
+
这些对象必须先有 schema、fixture、verifier、失败语义和 ADR,再接真实 provider。
|
|
94
|
+
|
|
95
|
+
## 仍属前瞻、禁止写成已交付
|
|
96
|
+
|
|
97
|
+
- 自动远程 push / PR / CI / merge。
|
|
98
|
+
- 线上队列、容器 Worker Pool、多租户与跨 region 调度。
|
|
99
|
+
- 组织级凭据代理、策略服务与审计服务。
|
|
100
|
+
- 跨仓库原子交付;目标模型是 saga 与补偿,不是伪全局事务。
|
|
101
|
+
- Eval Lab auto-promote、默认自动 merge、自动发布或 RSI Level 1。
|
|
102
|
+
|
|
103
|
+
## 文档演进规则
|
|
104
|
+
|
|
105
|
+
1. 新能力先由代码、测试、live campaign、completed plan 或正式报告证明。
|
|
106
|
+
2. 证明成立后更新 current capability summary 和本页“当前架构”。
|
|
107
|
+
3. 未证明部分只保留在 active design/exec-plan,不能通过修改措辞升级状态。
|
|
108
|
+
4. 使用者短索引同步到 `website/docs/overview/roadmap.md`,避免复制长版本流水账。
|
|
@@ -18,19 +18,13 @@ TODO
|
|
|
18
18
|
|
|
19
19
|
## Mock 约束(数据型任务)
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
- **既有 Mock service root、handler/fixture/bootstrap**:TODO
|
|
29
|
-
- **既有 browser/e2e interception 或 request adapter/DI seam**:TODO
|
|
30
|
-
- **production 禁用边界**:TODO
|
|
31
|
-
- **真实请求默认路径与 Mock 显式启用方式**:TODO
|
|
32
|
-
- **`task.json.frontendMock.policy`**:`auto | required | disabled`(规范强制 Mock 用 `required`)
|
|
33
|
-
- **被拦截时怎么修**:`mock-strategy-outside-allowed` / `no authorized Mock verification commands` 是**生成期契约问题,不是 plan 问题**——补 `frontendMock.verifyCommands`(或 `policy: "required"` + 命令)后**重新生成 DAG** 再跑,plan-revision 无法修复它。
|
|
21
|
+
- Mock/API/schema 规范路径:TODO
|
|
22
|
+
- 既有 Mock service root、handler/fixture/bootstrap:TODO
|
|
23
|
+
- 既有 browser/e2e interception 或 request adapter/DI seam:TODO
|
|
24
|
+
- 启动、健康检查和专项验证命令:TODO
|
|
25
|
+
- production 禁用边界:TODO
|
|
26
|
+
- 真实请求默认路径与 Mock 显式启用方式:TODO
|
|
27
|
+
- `task.json.frontendMock.policy`:`auto | required | disabled`
|
|
34
28
|
|
|
35
29
|
## allowedPaths
|
|
36
30
|
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
| **允许** | 已发布 `loop-agent` / `agent-worker` CLI;只读 status/doctor/report/inspect/observe;准备 `source/*` 与 `task.json` 边界;human gate;shell 验证与 handoff。 |
|
|
34
34
|
| **禁止** | 绕过 CLI 用宿主 Edit/Write/ApplyPatch 直接改业务实现;CLI/DAG 失败后「救火改文件」;用聊天自述代替 shell 验证。 |
|
|
35
35
|
| **失败时** | 先 `dag report` / `dag doctor`;优先 `dag rerun --from-node` 安全子图续跑;仅契约/源真变或 plan 不合格时同 task 重 advance / `dag rerun-task`;paused 用 approve→`dag resume`。 |
|
|
36
|
-
| **实现写入** | 业务代码 **只** 经受治理 DAG writer(`implement-pi` / `repair-pi`)经 `task advance`(批准 writeSet gate
|
|
36
|
+
| **实现写入** | 业务代码 **只** 经受治理 DAG writer(`implement-pi` / `repair-pi`)经 `task advance`(批准 writeSet gate 后长跑)由 Console operation 后台持有;主会话**不得**在前台 Bash 直接执行 `task advance --approve-gate`,不得把长跑命令管道到 `tail`/`head`,不得自行拼接 `nohup` / `Start-Process` / `start`。 |
|
|
37
|
+
| **契约漂移** | 直接编辑 `source/需求.md` / `执行约束.md` 后契约会进入 `externally-modified`,此时 advance/dagRunTask 拒用新内容(DIRTY_SOURCE / hash 不一致)。合法收编路径:`task contract adopt --task <id> --expected-revision <n> --expected-observed-hash <hash> --request-id <id> --request-payload-sha256 <sha>`(hash 从 `task status --json` 的 `contract.observedCanonicalHash` 取);或改 PRD 后重新 importPrd 走完整重投影。禁止手工改 `lifecycle.json` / `.transactions/` 绕过。 |
|
|
37
38
|
|
|
38
39
|
**永远不要**:`loop-agent` / `agent-worker` 失败 ⇒ 主会话直接改仓库实现;也勿因 provider 抖动或只读节点失败**新建无关 task-id**。
|
|
39
40
|
|
|
@@ -109,6 +110,8 @@ loop-agent task status <task-id> --json
|
|
|
109
110
|
# 有 plan 时收尾:loop-agent plan complete <plan-id> --summary "..."
|
|
110
111
|
```
|
|
111
112
|
|
|
113
|
+
长跑 DAG 采用 `prepareDagExecution → runDag → operationId` 异步 operation 路径(`--approve-gate` 不在前台 Bash 中同步等待);监督退避 60 → 90 → 120 → 180 秒,状态变化后重置为 60 秒,疑似 stall 用 30–60 秒复查。
|
|
114
|
+
|
|
112
115
|
`--verify` 命令应取项目 `AGENTS.md` / `__LOOP_AGENT_GOVERNANCE_ROOT__/verification-matrix.md` 登记的验证命令(不要假定 `npm run typecheck` 存在);`--verify` 可选,省略时自动从 package.json scripts 或既有 managed `task.json.verifyCommands` 推导建议。
|
|
113
116
|
|
|
114
117
|
`source/需求.md` 与 `source/执行约束.md` 仍必需(M8/M9),但默认由 `task advance --prd` 投影生成,而不是主会话手写。`plan create` 不是 `task advance` 的硬依赖。写入前同步 `task.json.allowedPaths` / `task.json.forbiddenPaths` 并审查 writer `writeSet`。高级任意 DagSpec 才用 `dag validate|execute|report`,不进入标准 happy path。
|
|
@@ -139,7 +142,7 @@ live run 先用 `loop-agent dag status --run-id <run-id>` 看 lifecycle 与 live
|
|
|
139
142
|
|
|
140
143
|
**失败默认恢复序**:`dag report`/`dag doctor` → 优先 `dag rerun --from-node <node> --plan` 再带 `--plan-hash`(provider 抖动、plan/review/verify 安全下游;writer/decision/fingerprint 不合格勿硬跑)→ paused:approve→`dag resume` → 契约/源真变或 R1 不合格:同 task `task advance` / `dag rerun-task`(禁无理由新建 task-id)→ Worker-owned:`agent-worker task retry`。
|
|
141
144
|
|
|
142
|
-
Operator 须监控 live run 至终态(FINISHED / FAILED / partial_failed)或 Decision Gate 需要 approve
|
|
145
|
+
Operator 须监控 live run 至终态(FINISHED / FAILED / partial_failed)或 Decision Gate 需要 approve;监督退避 60 → 90 → 120 → 180 秒(状态变化后重置 60 秒,疑似 stall 用 30–60 秒复查),长跑 DAG 由 Console operation 后台持有(`prepareDagExecution → runDag → operationId`),禁止前台 Bash 直接 `task advance --approve-gate`、禁止管道 `tail`/`head`、禁止自行拼接 `nohup` / `Start-Process` / `start`;可在节点/rank 变化、verify/closeout、stall 或需 approve 时简短汇报(告知非请求确认)。判活须组合 runner heartbeat、session events 与 `dag doctor` liveness/provider meaningful progress(heartbeat alone ≠ progress)。bounded writer 运行期间不得并发修改工作区(write guard / write-guard 会把越界 diff 错误归因到 writer);只读 status/doctor/report 与 approve/reject/resume 仍允许。恢复:report/doctor → **优先** `dag rerun --from-node` → 必要时 rerun-task/同 task advance → shell verify。**禁止**把主会话直接 Edit 业务代码当作恢复手段。
|
|
143
146
|
|
|
144
147
|
### 运行态与验证
|
|
145
148
|
|
package/harness.json
CHANGED
|
@@ -79,9 +79,9 @@
|
|
|
79
79
|
},
|
|
80
80
|
"executors": {
|
|
81
81
|
"pi": {
|
|
82
|
-
"description": "Pi 负责规划、评审、诊断;当 DAG toolProfile=write
|
|
82
|
+
"description": "Pi 负责规划、评审、诊断;当 DAG toolProfile=write 时也可做有界写入。模型按复杂度三档配置,支持 provider/model 字符串或带 thinking 的对象;斜杠前为 Pi provider,后为 modelId,勿只写裸 modelId。",
|
|
83
83
|
"LOW": "wizard-local/minimax-m3",
|
|
84
|
-
"MED": "wizard-local/
|
|
84
|
+
"MED": "wizard-local/grok-4.6",
|
|
85
85
|
"HIGH": "wizard-local/gpt-5.6-sol"
|
|
86
86
|
}
|
|
87
87
|
}
|
package/package.json
CHANGED
|
@@ -24,6 +24,7 @@ references:
|
|
|
24
24
|
## 初始化升级路由
|
|
25
25
|
|
|
26
26
|
- 写入型「**loop-agent初始化更新**」「loop-agent 初始化更新」「更新 loop-agent 初始化内容」「升级后对齐」统一运行 `loop-agent init upgrade --repo-root . --json`;处理 controller 返回的单文件 `allowedPaths`,以同一 run `--continue` 推进至终态,不停在中间状态。
|
|
27
|
+
- 升级可能因 gitignore 迁移评估暂停:若 `.agents/` 存在已跟踪内容,需先审查是否有应团队共享的自定义内容;存在 staged 变更或 git 查询失败时需先解决 blocker,再重跑评估。建议的 `git rm -r --cached --ignore-unmatch` 只修改 index、保留工作区文件,且由用户执行而非 controller。
|
|
27
28
|
- 「检查初始化更新」「初始化更新校验」「只检查,不要修改」仅运行 `loop-agent init check-update --repo-root . --markdown`,不得创建 run 或写入。
|
|
28
29
|
- facts 位于 `.harness/init-upgrades/<run-id>/`;禁止业务源码和宽泛 glob。默认管理项目 `.opencode/plugins/`、`.pi/extensions/`、`.pi/settings.json`;Pi trust 后加载,默认不读写 `~/.pi/agent/settings.json`。
|
|
29
30
|
|
|
@@ -152,6 +152,8 @@ fresh init 将精确引用写到 `executors.pi.LOW/MED/HIGH`。fresh `loop-agent
|
|
|
152
152
|
|
|
153
153
|
`init upgrade` 是写入型升级入口:首次运行冻结 controller identity、检查 npm latest、扫描 surface、自动执行安全动作,并把 run facts 持久化到 `.harness/init-upgrades/<run-id>/`。`--status` 与 `--report` 严格只读;`--continue` 会重新核验 identity、当前 hash 与不变量。版本选择、无法判定冲突、凭据、破坏性删除或 active writer 才进入 human decision。普通语义冲突返回具体单文件 `allowedPaths` merge task,主会话必须合并后继续,不能把 `needs-model-merge` 作为完成。默认管理项目级 OpenCode/Pi recovery 与 `.pi/settings.json` nested merge,保留显式 disabled,Pi trust 后才加载;默认不读写 `~/.pi/agent/settings.json`。旧 `init reconcile` 保留为兼容低层诊断。
|
|
154
154
|
|
|
155
|
+
升级在 managed block 收敛后生成只读 gitignore 迁移评估(`.harness/init-upgrades/<run-id>/gitignore-migration.json`):inventory 已跟踪的 `.harness/**` 与 `.agents/**`,建议 index-only 命令 `git rm -r --cached --ignore-unmatch .harness` / `.agents`(只改 index、保留工作区文件;`scripts/**` 与 `ai_workspace/loop-agent/**` 永不出现)。`.agents` 已跟踪内容会触发 human-decision 暂停等待审查;非 Git 仓库、git 查询失败或存在 staged 条目时 `status: blocked` 且无命令建议。controller 不自动修改 Git index。
|
|
156
|
+
|
|
155
157
|
### 查看或复制内置示例
|
|
156
158
|
|
|
157
159
|
```bash
|