@tea-agent/loop-agent 0.36.3-beta.0 → 0.37.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/CHANGELOG.md +56 -55
- package/dist/build-stamp.json +3 -3
- package/dist/task/contract/project.js +4 -0
- package/dist/task/source-prepare/completeness.js +36 -0
- package/dist/task/source-prepare/parse-intent.js +67 -11
- package/dist/task/source-prepare/prepare.js +102 -5
- package/dist/worker/console/chat/chat-event-store.js +91 -0
- package/dist/worker/console/chat/pi-runtime.js +25 -0
- package/dist/worker/console/chat/routes.js +7 -2
- package/dist/worker/console/chat/semantic-activity.js +7 -1
- package/dist/worker/console/chat/session-store.js +6 -1
- package/dist/worker/console/chat/turn-process.js +119 -12
- package/dist/worker/console/operator-actions.js +18 -1
- package/dist/worker/console/static/assets/abnfDiagram-N423BO3Z-DSvF6RXQ.js +1 -0
- package/dist/worker/console/static/assets/arc-DuI4ogtJ.js +1 -0
- package/dist/worker/console/static/assets/architectureDiagram-T3A2C74G-DdBbgD4y.js +36 -0
- package/dist/worker/console/static/assets/blockDiagram-VBNYF7ZC-xQC2HELm.js +132 -0
- package/dist/worker/console/static/assets/c4Diagram-5PPSVZJV-DPMSgwIZ.js +10 -0
- package/dist/worker/console/static/assets/channel-DLVz9TYW.js +1 -0
- package/dist/worker/console/static/assets/chunk-2GRJ4B5K-WTEKTxin.js +1 -0
- package/dist/worker/console/static/assets/chunk-2Q5K7J3B-B6vZ0Pv_.js +1 -0
- package/dist/worker/console/static/assets/chunk-5RXB4S5H-BrerNAix.js +231 -0
- package/dist/worker/console/static/assets/chunk-5VM5RSS4-D_ch2aaI.js +15 -0
- package/dist/worker/console/static/assets/chunk-6Q2QTUOP-VvfacNrq.js +88 -0
- package/dist/worker/console/static/assets/chunk-GF5L2VYU-B-uGFIg2.js +206 -0
- package/dist/worker/console/static/assets/chunk-JWPE2WC7-BlysCtod.js +1 -0
- package/dist/worker/console/static/assets/chunk-KBJHAD2P-BjAUAfcT.js +1 -0
- package/dist/worker/console/static/assets/chunk-RYQCIY6F-BeZnBmb-.js +1 -0
- package/dist/worker/console/static/assets/chunk-XXDRQBXY-Bbfe3UJG.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BeAuGcO9.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BeAuGcO9.js +1 -0
- package/dist/worker/console/static/assets/cose-bilkent-JH36ORCC-BKJQnYVM.js +1 -0
- package/dist/worker/console/static/assets/cynefin-VYW2F7L2-B1wtI3hU.js +166 -0
- package/dist/worker/console/static/assets/cynefinDiagram-MW4NZA55-DCF6DBSu.js +62 -0
- package/dist/worker/console/static/assets/cytoscape.esm-yzknjiTM.js +321 -0
- package/dist/worker/console/static/assets/dagre-VZM6K2ZE-BJyNGRlP.js +4 -0
- package/dist/worker/console/static/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/worker/console/static/assets/diagram-7IWD3JNH-B7j1-VsZ.js +30 -0
- package/dist/worker/console/static/assets/diagram-B4RE2ZJO-BREJ140a.js +3 -0
- package/dist/worker/console/static/assets/diagram-LBJQPF4R-CDPHmHGH.js +24 -0
- package/dist/worker/console/static/assets/diagram-Q27KOJAE-BtZLrez1.js +24 -0
- package/dist/worker/console/static/assets/diagram-UB23O5K3-mzybu8oU.js +41 -0
- package/dist/worker/console/static/assets/ebnfDiagram-BXEA7PRR-Dk3I2uO6.js +1 -0
- package/dist/worker/console/static/assets/erDiagram-JOGREHBK-BT97u_tQ.js +85 -0
- package/dist/worker/console/static/assets/flowDiagram-UKHOOZJN-CMOtYzui.js +156 -0
- package/dist/worker/console/static/assets/ganttDiagram-PKOTCBZU-DiNydkuY.js +292 -0
- package/dist/worker/console/static/assets/gitGraphDiagram-DS77QQ5N-Cwt6fLkl.js +106 -0
- package/dist/worker/console/static/assets/graph-DOmOIIwC.js +1 -0
- package/dist/worker/console/static/assets/index-DQxiso1w.js +325 -0
- package/dist/worker/console/static/assets/index-_j0Hzo69.css +1 -0
- package/dist/worker/console/static/assets/infoDiagram-6WML65LV-AsGIGKKB.js +2 -0
- package/dist/worker/console/static/assets/init-Gi6I4Gst.js +1 -0
- package/dist/worker/console/static/assets/ishikawaDiagram-WSZJBQD7-BL8ITZh3.js +70 -0
- package/dist/worker/console/static/assets/journeyDiagram-NVQOT4AX-VPKAUX8M.js +139 -0
- package/dist/worker/console/static/assets/kanban-definition-27J2QSJJ-BL56hfGp.js +89 -0
- package/dist/worker/console/static/assets/layout-D-LzfAck.js +1 -0
- package/dist/worker/console/static/assets/linear-BmSG3nIZ.js +1 -0
- package/dist/worker/console/static/assets/map-DxJ2ADlA.js +1 -0
- package/dist/worker/console/static/assets/mermaid.core-DWGK9kwP.js +308 -0
- package/dist/worker/console/static/assets/mindmap-definition-FAOFIHXS--vvKLjo0.js +96 -0
- package/dist/worker/console/static/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/worker/console/static/assets/pegDiagram-VL7TDLO6-B41mxb2-.js +1 -0
- package/dist/worker/console/static/assets/pieDiagram-7S7Q4E2Y-DTlu77sw.js +39 -0
- package/dist/worker/console/static/assets/quadrantDiagram-CIZ2JOQS-Bk5A7alv.js +7 -0
- package/dist/worker/console/static/assets/railroadDiagram-AXF67PYL-Csf9jzQy.js +1 -0
- package/dist/worker/console/static/assets/requirementDiagram-LRYGKXZP-CeptoSNx.js +84 -0
- package/dist/worker/console/static/assets/sankeyDiagram-W5VNT64P-A-DLCLer.js +40 -0
- package/dist/worker/console/static/assets/sequenceDiagram-SI44F4Z6-22VbPdOI.js +162 -0
- package/dist/worker/console/static/assets/sizeCapture-X5ZJPWSS-DWvAyBC9.js +1 -0
- package/dist/worker/console/static/assets/stateDiagram-OKZ733FA-qICZ75yT.js +1 -0
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DzKvfHTX.js +1 -0
- package/dist/worker/console/static/assets/swimlanes-SLNWSIFB-xi7lcMyp.js +2 -0
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Cxqr_qM1.js +8 -0
- package/dist/worker/console/static/assets/timeline-definition-Z64GVDOM-Bu6Nl6O2.js +120 -0
- package/dist/worker/console/static/assets/vennDiagram-T6HMQDX7-BzMz4Bn9.js +34 -0
- package/dist/worker/console/static/assets/wardleyDiagram-T6FBY63Y-CxaJnzc5.js +78 -0
- package/dist/worker/console/static/assets/xychartDiagram-ELKLHX3M-5JK-omQK.js +7 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_AMS-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Main-Bold.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Main-Italic.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Main-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Math-Italic.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Script-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Size1-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Size2-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Size3-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Size4-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +25 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +37 -2
- package/dist/worker/observe/static/operator-chrome.js +4 -2
- package/dist/workflows/dag/failure-routing.js +4 -9
- package/dist/workflows/dag/init-hybrid.js +2 -47
- package/dist/workflows/dag/lifecycle.js +0 -4
- package/dist/workflows/dag/node-execution.js +6 -16
- package/dist/workflows/dag/report.js +0 -6
- package/dist/workflows/dag/retry-policy.js +0 -11
- package/dist/workflows/dag/runner.js +19 -3
- package/dist/workflows/dag/types.js +0 -2
- package/dist/workflows/dag/validate.js +2 -7
- package/docs/templates/frontend-task-constraints.md +7 -13
- package/package.json +6 -1
- package/skills/loop-agent/references/command-reference.md +1 -0
- package/dist/worker/console/static/assets/index-D83DYAFG.css +0 -1
- package/dist/worker/console/static/assets/index-IXm7oYjL.js +0 -59
|
@@ -44,9 +44,7 @@ function routeToProductLine(input) {
|
|
|
44
44
|
case "decision-envelope":
|
|
45
45
|
return "NeedsHuman";
|
|
46
46
|
case "skipped":
|
|
47
|
-
return
|
|
48
|
-
? "ContractMismatch"
|
|
49
|
-
: "DependencyFailure";
|
|
47
|
+
return "DependencyFailure";
|
|
50
48
|
case "shell-command":
|
|
51
49
|
if (/\b(ENOENT|PATH|command not found|No such file|not found in PATH|bash: .*: No such file)\b/i.test(raw)) {
|
|
52
50
|
return "EnvFailure";
|
|
@@ -92,12 +90,9 @@ export function routeDagFailure(input) {
|
|
|
92
90
|
if (!productLineFailureCategory)
|
|
93
91
|
return {};
|
|
94
92
|
const recommendedFollowUp = productLineFailureCategory === "ContractMismatch" &&
|
|
95
|
-
input.
|
|
96
|
-
? "
|
|
97
|
-
: productLineFailureCategory
|
|
98
|
-
isFrontendDesignGateNode(input.nodeId ?? "")
|
|
99
|
-
? "frontend-plan-revision-and-rerun"
|
|
100
|
-
: FOLLOW_UP_BY_PRODUCT_LINE[productLineFailureCategory];
|
|
93
|
+
isFrontendDesignGateNode(input.nodeId ?? "")
|
|
94
|
+
? "frontend-plan-revision-and-rerun"
|
|
95
|
+
: FOLLOW_UP_BY_PRODUCT_LINE[productLineFailureCategory];
|
|
101
96
|
return {
|
|
102
97
|
productLineFailureCategory,
|
|
103
98
|
recommendedFollowUp,
|
|
@@ -9,7 +9,7 @@ import { planMavenVerification, } from "../../verification/maven/index.js";
|
|
|
9
9
|
import { pathMatchesPattern } from "../../shared/git-progress.js";
|
|
10
10
|
import { BASELINE_FORBIDDEN_PATHS } from "./governance-constants.js";
|
|
11
11
|
import { buildDecisionEnvelopePromptContract } from "./decision-envelope.js";
|
|
12
|
-
import { DEFAULT_READ_ONLY_PI_RETRY_POLICY,
|
|
12
|
+
import { DEFAULT_READ_ONLY_PI_RETRY_POLICY, PROTOCOL_AWARE_PI_RETRY_POLICY, STRUCTURED_REQUIRED_PI_RETRY_POLICY, BACKEND_TEST_WRITER_COMPLETENESS_RETRY_POLICY, WRITER_TRANSPORT_RETRY_POLICY, isSafeReadOnlyPiRetryCandidate, isWriterTransportRetryCandidate, } from "./retry-policy.js";
|
|
13
13
|
import { REVIEW_JSON_VERDICT_OUTPUT_PROTOCOL, REVIEW_VERDICT_OUTPUT_PROTOCOL, } from "./output-protocol.js";
|
|
14
14
|
import { resolveAdapter } from "../../adapters/index.js";
|
|
15
15
|
import { loadHarnessManifest } from "../../governance/harness.js";
|
|
@@ -558,39 +558,6 @@ export function hasApiDependency(sources) {
|
|
|
558
558
|
.some((clause) => !negationPatterns.some((pattern) => pattern.test(clause)) &&
|
|
559
559
|
dependencyPatterns.some((pattern) => pattern.test(clause)));
|
|
560
560
|
}
|
|
561
|
-
/**
|
|
562
|
-
* Generation-time heuristic: does the task source mention interface/API/Mock
|
|
563
|
-
* needs anywhere (requirement or constraints)?
|
|
564
|
-
*
|
|
565
|
-
* Mirrors hasApiDependency's clause-level negation filtering so explicit
|
|
566
|
-
* "not involved / not implementing" clauses and out-of-scope sections do not
|
|
567
|
-
* become positive evidence. Used to emit a machine-visible advisory when auto
|
|
568
|
-
* mode narrows Mock to not-needed despite the source mentioning such needs.
|
|
569
|
-
*/
|
|
570
|
-
export function frontendSourceMentionsMock(sources) {
|
|
571
|
-
const text = [sources.requirementMarkdown, sources.constraintMarkdown]
|
|
572
|
-
.filter((entry) => typeof entry === "string" && entry.trim().length > 0)
|
|
573
|
-
.map((entry) => normalizeTaskRequirementText(entry).replace(/`[^`\n]*`/g, " "))
|
|
574
|
-
.join("\n");
|
|
575
|
-
const signalPatterns = [
|
|
576
|
-
/mock/i,
|
|
577
|
-
/模拟服务/,
|
|
578
|
-
/接口桩/,
|
|
579
|
-
/\bmsw\b/i,
|
|
580
|
-
/(?<![A-Za-z0-9_])API(?![A-Za-z0-9_])/i,
|
|
581
|
-
/接口/,
|
|
582
|
-
];
|
|
583
|
-
const negationPatterns = [
|
|
584
|
-
/(?:不涉及|无需|不需要|不依赖|不调用|不请求|不实现|没有|禁止|不得).{0,16}(?:接口|后端|服务端|远程数据|异步数据|API|mock|模拟|桩)/i,
|
|
585
|
-
/\b(?:no|without|does\s+not|do\s+not|must\s+not)\b.{0,24}\b(?:api|endpoint|request|backend|server|mock)\b/i,
|
|
586
|
-
];
|
|
587
|
-
return text
|
|
588
|
-
.split(/[。!?!?;;,,\r\n]+/)
|
|
589
|
-
.map((clause) => clause.trim())
|
|
590
|
-
.filter(Boolean)
|
|
591
|
-
.some((clause) => !negationPatterns.some((pattern) => pattern.test(clause)) &&
|
|
592
|
-
signalPatterns.some((pattern) => pattern.test(clause)));
|
|
593
|
-
}
|
|
594
561
|
/**
|
|
595
562
|
* Resolve frontend Mock mode from capability seed, task config, and interface dependency analysis.
|
|
596
563
|
*
|
|
@@ -2144,7 +2111,6 @@ function resolveFrontendMockContextBlock(sources) {
|
|
|
2144
2111
|
parts.push("Generation-time evidence does not require Mock. The assessment must still use contract/scout evidence: select not-needed when Mock is intentionally skipped, or select a safe Mock strategy if project evidence supports one.");
|
|
2145
2112
|
if (frontendMockStrategyMustBeNotNeeded(sources)) {
|
|
2146
2113
|
parts.push('Auto mode has no confirmed project Mock capability or no deterministic Mock verification command. The structured contract must set mockApi.strategy to "not-needed". Do not add Mock files or dependencies; keep the real request path as default and record any unproved backend behavior as Real Integration Gap.');
|
|
2147
|
-
parts.push('HARD CONSTRAINT (frozen at generation time): this DAG allows only mockApi.strategy "not-needed"; the prewrite gate rejects any other strategy. If project governance (openspec / ai_workspace / decision records, e.g. a DEC rule requiring native) demands Mock-backed verification, that is a generation-time contract gap, not a plan-revision defect: declare frontendMock.verifyCommands (or policy: "required") in task.json and regenerate the DAG. Do not emit any mockApi.strategy outside the allowlist and do not add Mock files or dependencies within this run.');
|
|
2148
2114
|
}
|
|
2149
2115
|
}
|
|
2150
2116
|
if (mode === "blocked") {
|
|
@@ -2543,11 +2509,6 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
2543
2509
|
`- Behavior command source: ${behaviorVerifyEvidence.commandSource}`,
|
|
2544
2510
|
...behaviorVerifyEvidence.commandLabels.map((command) => ` - ${JSON.stringify(command)}`),
|
|
2545
2511
|
].join("\n");
|
|
2546
|
-
const advisories = [];
|
|
2547
|
-
if (frontendSourceMentionsMock(frontendSources) &&
|
|
2548
|
-
frontendMockStrategyMustBeNotNeeded(frontendSources)) {
|
|
2549
|
-
advisories.push("auto 模式已将 Mock 策略收窄为 not-needed:任务源提到接口/API/Mock 需求,但仓库无确认 Mock 能力或无确定性 Mock 验证命令。若项目规范要求 Mock,请声明 frontendMock.verifyCommands 或 policy:required 后重新生成 DAG。");
|
|
2550
|
-
}
|
|
2551
2512
|
const spec = {
|
|
2552
2513
|
version: 3,
|
|
2553
2514
|
title: `Frontend implementation DAG: ${taskConfig.title}`,
|
|
@@ -2562,7 +2523,6 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
2562
2523
|
skillsByRole: FRONTEND_SKILLS_BY_ROLE,
|
|
2563
2524
|
executorModels: sources.executorModelMatrix ?? DEFAULT_DAG_EXECUTOR_MODELS,
|
|
2564
2525
|
verifyStrategy: resolveDagVerifyStrategy(taskConfig),
|
|
2565
|
-
advisories: advisories.length > 0 ? advisories : undefined,
|
|
2566
2526
|
tasks: [
|
|
2567
2527
|
{
|
|
2568
2528
|
id: "frontend-contract-pi",
|
|
@@ -2657,7 +2617,6 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
2657
2617
|
"Read-only: do not modify repository files.",
|
|
2658
2618
|
fixedVerificationContext,
|
|
2659
2619
|
sourceContext,
|
|
2660
|
-
mockContextBlock,
|
|
2661
2620
|
].join("\n\n"),
|
|
2662
2621
|
},
|
|
2663
2622
|
{
|
|
@@ -2692,7 +2651,6 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
2692
2651
|
fixedVerificationContext,
|
|
2693
2652
|
sourceContext,
|
|
2694
2653
|
frontendContractSchemaBlock,
|
|
2695
|
-
mockContextBlock,
|
|
2696
2654
|
].join("\n\n"),
|
|
2697
2655
|
},
|
|
2698
2656
|
{
|
|
@@ -2723,7 +2681,6 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
2723
2681
|
"Read-only: do not modify repository files.",
|
|
2724
2682
|
fixedVerificationContext,
|
|
2725
2683
|
sourceContext,
|
|
2726
|
-
mockContextBlock,
|
|
2727
2684
|
].join("\n\n"),
|
|
2728
2685
|
},
|
|
2729
2686
|
{
|
|
@@ -5826,9 +5783,7 @@ function applyDefaultReadOnlyRetryPolicy(spec) {
|
|
|
5826
5783
|
if (isSafeReadOnlyPiRetryCandidate(task)) {
|
|
5827
5784
|
task.retryPolicy = task.outputProtocol
|
|
5828
5785
|
? PROTOCOL_AWARE_PI_RETRY_POLICY
|
|
5829
|
-
:
|
|
5830
|
-
? PLANNER_OUTPUT_LIMIT_RETRY_POLICY
|
|
5831
|
-
: DEFAULT_READ_ONLY_PI_RETRY_POLICY;
|
|
5786
|
+
: DEFAULT_READ_ONLY_PI_RETRY_POLICY;
|
|
5832
5787
|
continue;
|
|
5833
5788
|
}
|
|
5834
5789
|
if (isWriterTransportRetryCandidate(task)) {
|
|
@@ -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")
|
|
@@ -216,28 +216,18 @@ function buildAttemptPrompt(task, basePrompt, attemptNumber, previousFailureCate
|
|
|
216
216
|
"</retry_instruction>",
|
|
217
217
|
].join("\n");
|
|
218
218
|
}
|
|
219
|
-
if (
|
|
219
|
+
if (task.outputMode !== "structured-required" ||
|
|
220
|
+
previousFailureCategory !== "output-too-large") {
|
|
220
221
|
return basePrompt;
|
|
221
222
|
}
|
|
222
|
-
if (task.outputMode === "structured-required") {
|
|
223
|
-
return [
|
|
224
|
-
basePrompt,
|
|
225
|
-
"",
|
|
226
|
-
"<retry_instruction>",
|
|
227
|
-
"Previous attempt exceeded the structured output size limit.",
|
|
228
|
-
"Return only the compact structured artifact required by this node's output contract.",
|
|
229
|
-
"Do not include explanatory prose, duplicated upstream context, long evidence excerpts, or additional markdown sections.",
|
|
230
|
-
"If a fenced JSON object is required, output exactly one fenced json block and nothing else.",
|
|
231
|
-
"</retry_instruction>",
|
|
232
|
-
].join("\n");
|
|
233
|
-
}
|
|
234
223
|
return [
|
|
235
224
|
basePrompt,
|
|
236
225
|
"",
|
|
237
226
|
"<retry_instruction>",
|
|
238
|
-
"Previous attempt exceeded the output size limit.",
|
|
239
|
-
"Return
|
|
240
|
-
"
|
|
227
|
+
"Previous attempt exceeded the structured output size limit.",
|
|
228
|
+
"Return only the compact structured artifact required by this node's output contract.",
|
|
229
|
+
"Do not include explanatory prose, duplicated upstream context, long evidence excerpts, or additional markdown sections.",
|
|
230
|
+
"If a fenced JSON object is required, output exactly one fenced json block and nothing else.",
|
|
241
231
|
"</retry_instruction>",
|
|
242
232
|
].join("\n");
|
|
243
233
|
}
|
|
@@ -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"
|
|
@@ -118,17 +118,6 @@ export const STRUCTURED_REQUIRED_PI_RETRY_POLICY = {
|
|
|
118
118
|
...DEFAULT_READ_ONLY_PI_RETRY_POLICY,
|
|
119
119
|
retryCategories: [...STRUCTURED_REQUIRED_DAG_RETRY_CATEGORIES],
|
|
120
120
|
};
|
|
121
|
-
/**
|
|
122
|
-
* Planner read-only nodes (standard DAG contract-pi / plan-pi) may retry with
|
|
123
|
-
* a compact-output instruction when the model produced an oversized assistant
|
|
124
|
-
* response. Only `output-too-large` is added on top of the default set;
|
|
125
|
-
* report/review and other read-only roles keep the default set so they do not
|
|
126
|
-
* silently learn new output semantics.
|
|
127
|
-
*/
|
|
128
|
-
export const PLANNER_OUTPUT_LIMIT_RETRY_POLICY = {
|
|
129
|
-
...DEFAULT_READ_ONLY_PI_RETRY_POLICY,
|
|
130
|
-
retryCategories: [...DEFAULT_DAG_RETRY_CATEGORIES, STRUCTURED_OUTPUT_RETRY_CATEGORY],
|
|
131
|
-
};
|
|
132
121
|
/**
|
|
133
122
|
* Default retry for reviewer / recovery nodes that declare outputProtocol.
|
|
134
123
|
* Includes protocol-invalid so missing VERDICT lines are corrected in-node.
|
|
@@ -115,6 +115,22 @@ export async function buildDagRunId(spec, options) {
|
|
|
115
115
|
const existing = await listExistingDagRunIds(options.cwd);
|
|
116
116
|
return collisionSafeDagRunId(baseId, existing, now);
|
|
117
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Append a human-readable round label to a run title when the runId carries
|
|
120
|
+
* a `-rN` collision suffix (2026-08-16): the sidebar / Inspect list showed
|
|
121
|
+
* identical titles for reruns and only the id hinted at the round.
|
|
122
|
+
*/
|
|
123
|
+
export function titleWithRoundLabel(title, runId) {
|
|
124
|
+
const match = /-r(\d{1,2})$/.exec(runId);
|
|
125
|
+
if (!match)
|
|
126
|
+
return title;
|
|
127
|
+
const round = Number.parseInt(match[1], 10);
|
|
128
|
+
if (!Number.isFinite(round) || round < 2)
|
|
129
|
+
return title;
|
|
130
|
+
// Never stack labels on reruns of reruns.
|
|
131
|
+
const base = title.replace(/\s*(第\s*\d+\s*轮)$/u, "");
|
|
132
|
+
return `${base}(第 ${round} 轮)`;
|
|
133
|
+
}
|
|
118
134
|
export function createInitialRunState(spec, opts, ranks, runId = opts.runId ?? "dag") {
|
|
119
135
|
const nodes = {};
|
|
120
136
|
for (const task of spec.tasks) {
|
|
@@ -136,7 +152,7 @@ export function createInitialRunState(spec, opts, ranks, runId = opts.runId ?? "
|
|
|
136
152
|
: "execute";
|
|
137
153
|
const state = {
|
|
138
154
|
version: 1,
|
|
139
|
-
title: spec.title,
|
|
155
|
+
title: titleWithRoundLabel(spec.title, runId),
|
|
140
156
|
runId,
|
|
141
157
|
cwd: opts.cwd,
|
|
142
158
|
startedAt: new Date().toISOString(),
|
|
@@ -263,7 +279,7 @@ export async function runDag(spec, opts) {
|
|
|
263
279
|
}
|
|
264
280
|
if (opts.dryRun || opts.initOnly) {
|
|
265
281
|
return {
|
|
266
|
-
title:
|
|
282
|
+
title: state.title,
|
|
267
283
|
runId: state.runId,
|
|
268
284
|
status: state.status,
|
|
269
285
|
ranks,
|
|
@@ -717,7 +733,7 @@ async function executeDagCheckpoint(input) {
|
|
|
717
733
|
await writeBudgetLedgerArtifacts(runDir, state.budgetLedger);
|
|
718
734
|
await persistState({ allowCompletedFactsWrite: true });
|
|
719
735
|
return {
|
|
720
|
-
title:
|
|
736
|
+
title: state.title,
|
|
721
737
|
runId: state.runId,
|
|
722
738
|
status: state.status,
|
|
723
739
|
ranks,
|
|
@@ -822,8 +822,6 @@ export const dagSpecSchema = z
|
|
|
822
822
|
defaults: dagDefaultsSchema,
|
|
823
823
|
skillsByRole: z.record(z.string(), z.array(z.string())).optional(),
|
|
824
824
|
executorModels: dagExecutorModelsSchema.optional(),
|
|
825
|
-
/** Generation-time advisories surfaced as machine-visible warnings. */
|
|
826
|
-
advisories: z.array(z.string()).optional(),
|
|
827
825
|
tasks: z.array(dagTaskSchema).min(1),
|
|
828
826
|
})
|
|
829
827
|
.superRefine((spec, ctx) => {
|
|
@@ -14,7 +14,6 @@ const GOVERNANCE_WARNING_TYPES = new Set([
|
|
|
14
14
|
"shell-verdict-gate-multi-command-state",
|
|
15
15
|
"shell-verdict-gate-handwritten-inline",
|
|
16
16
|
"orphan-writer-source-binding",
|
|
17
|
-
"advisory",
|
|
18
17
|
]);
|
|
19
18
|
const ROOT_ARTIFACT_PATH_PROBES = [
|
|
20
19
|
"artifacts/修改记录.md",
|
|
@@ -33,11 +32,10 @@ export function collectGovernanceWarnings(issues) {
|
|
|
33
32
|
return issues.filter(isGovernanceWarning);
|
|
34
33
|
}
|
|
35
34
|
function collectBlockingIssues(issues, options = {}) {
|
|
36
|
-
const nonAdvisory = issues.filter((issue) => issue.type !== "advisory");
|
|
37
35
|
if (options.strictGovernance) {
|
|
38
|
-
return
|
|
36
|
+
return [...issues];
|
|
39
37
|
}
|
|
40
|
-
return
|
|
38
|
+
return issues.filter((issue) => !isGovernanceWarning(issue));
|
|
41
39
|
}
|
|
42
40
|
function normalizePath(value) {
|
|
43
41
|
return value.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
@@ -958,9 +956,6 @@ export function validateDagSpec(spec) {
|
|
|
958
956
|
validateSameRankWriteSetConflicts(spec, ranks, issues);
|
|
959
957
|
validateSameRankAgentAttributionRisks(spec, ranks, issues);
|
|
960
958
|
validateWriterSourceBinding(spec, issues);
|
|
961
|
-
for (const advisory of spec.advisories ?? []) {
|
|
962
|
-
issues.push({ type: "advisory", message: advisory });
|
|
963
|
-
}
|
|
964
959
|
return issues;
|
|
965
960
|
}
|
|
966
961
|
function validateProjectGovernanceTaskConfig(task, spec, issues) {
|
|
@@ -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
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tea-agent/loop-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"loop-agent": "bin/loop-agent.js",
|
|
@@ -65,6 +65,11 @@
|
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"commander": "^12.1.0",
|
|
68
|
+
"katex": "^0.16.47",
|
|
69
|
+
"mermaid": "^11.16.1",
|
|
70
|
+
"rehype-highlight": "^7.0.2",
|
|
71
|
+
"rehype-katex": "^7.0.1",
|
|
72
|
+
"remark-math": "^6.0.0",
|
|
68
73
|
"semver": "^7.8.5",
|
|
69
74
|
"yaml": "^2.9.0",
|
|
70
75
|
"zod": "^3.25.76"
|
|
@@ -325,6 +325,7 @@ loop-agent dag request-interrupt --run-id <run-id> --request-id <id> --target-op
|
|
|
325
325
|
loop-agent dag rerun --run-id <run-id> --from-node <node-id> --plan [--json] # 从节点重跑资格预检(不执行)
|
|
326
326
|
loop-agent dag rerun --run-id <run-id> --from-node <node-id> --plan-hash <sha256> --request-id <key> --reason "..." [--json] # 安全子图 continuation
|
|
327
327
|
loop-agent dag rerun-task --run-id <run-id> --reason "..." --request-id <key> [--profile auto] [--task-id <id>] [--json] # standalone 完整任务重跑
|
|
328
|
+
loop-agent dag request-interrupt --run-id <run-id> --request-id <key> --target-operation-id <op-id> --reason-code <code> --reason "..." --expected-runner-pid <pid> --expected-runner-hostname <host> --expected-runner-started-at <ts> --expected-controller-fingerprint <fingerprint> # 协作式中止:经 Human Gate 登记 interrupt.json,runner 等当前节点安全收敛后再停调度,不直接 SIGKILL
|
|
328
329
|
loop-agent dag reconcile-tasks --glob '<pattern>' # 仅报告的 task/run/artifact/verify drift audit
|
|
329
330
|
loop-agent dag final-verification <task-id> # 生成 closeout DAG,closeout artifact 后再 final verify
|
|
330
331
|
loop-agent dag decision inspect --run-id <run-id> [--node-id <node-id>] # dry-run envelope 重解析;除 run 缺失外 exit 0
|