@tea-agent/loop-agent 0.24.11-beta.0 → 0.25.1
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 +53 -4
- package/README.md +4 -4
- package/dist/application/dag/generate-task-dag.js +25 -8
- package/dist/commands/dag-init-hybrid.js +3 -2
- package/dist/commands/delegate.js +11 -11
- package/dist/commands/init.js +29 -14
- package/dist/commands/instructions.js +1 -2
- package/dist/executors/dag-pi-executor.js +74 -13
- package/dist/executors/pi-executor.js +25 -7
- package/dist/executors/pi-prompt-transport.js +198 -0
- package/dist/executors/pi-sdk-executor.js +1 -1
- package/dist/executors/process-tree.js +33 -0
- package/dist/executors/shell-executor.js +362 -24
- package/dist/executors/shell-verification.js +4 -2
- package/dist/infrastructure/harness/task-store.js +31 -0
- package/dist/shared/operator/capabilities.js +6 -0
- package/dist/task/read-model.js +3 -7
- package/dist/task/runtime.js +12 -3
- package/dist/verification/maven/cache.js +142 -0
- package/dist/verification/maven/index.js +120 -0
- package/dist/verification/maven/plan-commands.js +421 -0
- package/dist/verification/maven/pom-static.js +136 -0
- package/dist/verification/maven/scope-resolve.js +153 -0
- package/dist/verification/maven/stale.js +130 -0
- package/dist/verification/maven/types.js +23 -0
- package/dist/verification/maven/workspace-graph.js +322 -0
- package/dist/worker/cli.js +236 -21
- package/dist/worker/delivery/final-verification.js +12 -0
- package/dist/worker/delivery/git-transaction.js +32 -7
- package/dist/worker/delivery/package.js +9 -5
- package/dist/worker/delivery/verification-bundle.js +26 -5
- package/dist/worker/feature/advance.js +301 -0
- package/dist/worker/feature/doctor.js +223 -0
- package/dist/worker/feature/next-action.js +11 -3
- package/dist/worker/feature/scaffold.js +798 -0
- package/dist/worker/observe/dag-run-artifacts.js +90 -0
- package/dist/worker/observe/node-input.js +444 -0
- package/dist/worker/observe/routes.js +17 -0
- package/dist/worker/observe/static/api.js +9 -0
- package/dist/worker/observe/static/constants.js +9 -0
- package/dist/worker/observe/static/state.js +14 -0
- package/dist/worker/observe/static/styles.css +74 -0
- package/dist/worker/observe/static/views/dag-inspector.js +371 -15
- package/dist/worker/outcomes/projector.js +5 -1
- package/dist/worker/run-task/run-task.js +18 -2
- package/dist/worker/runner/run-ready.js +41 -1
- package/dist/workflows/dag/backend-test-markdown-workflow.js +300 -9
- package/dist/workflows/dag/backend-test-result-contract.js +103 -0
- package/dist/workflows/dag/failure-category.js +5 -1
- package/dist/workflows/dag/frontend-implementation-contract.js +4 -0
- package/dist/workflows/dag/frontend-prewrite-gate.js +0 -17
- package/dist/workflows/dag/frontend-test-result-contract.js +106 -41
- package/dist/workflows/dag/init-hybrid.js +224 -39
- package/dist/workflows/dag/node-execution.js +3 -2
- package/dist/workflows/dag/reconcile-run.js +24 -0
- package/dist/workflows/dag/types.js +57 -0
- package/dist/workflows/dag/validate.js +19 -2
- package/dist/workflows/loop/actions/dag-action.js +2 -1
- package/docs/architecture/dag-execution.md +5 -1
- package/docs/architecture/runtime-boundaries.md +11 -1
- package/docs/architecture/worker-and-feature.md +2 -0
- package/docs/init-surface.manifest.json +3 -0
- package/docs/templates/backend-test-dag.json +3 -3
- package/docs/templates/product-line/README.md +17 -1
- package/docs/templates/product-line/feature-scaffold-batch.example.yaml +31 -0
- package/docs/templates/product-line/scaffold-samples/README.md +36 -0
- package/docs/templates/product-line/scaffold-samples/backend-only/acceptance.yaml +13 -0
- package/docs/templates/product-line/scaffold-samples/backend-only/design.md +14 -0
- package/docs/templates/product-line/scaffold-samples/backend-only/feature.yaml +3 -0
- package/docs/templates/product-line/scaffold-samples/backend-only/requirement.md +6 -0
- package/docs/templates/product-line/scaffold-samples/backend-only/tasks/BE-IMPL-001.yaml +83 -0
- package/docs/templates/product-line/scaffold-samples/backend-only/tasks/task-graph.yaml +14 -0
- package/docs/templates/product-line/scaffold-samples/fe-with-api/acceptance.yaml +15 -0
- package/docs/templates/product-line/scaffold-samples/fe-with-api/design.md +18 -0
- package/docs/templates/product-line/scaffold-samples/fe-with-api/feature.yaml +3 -0
- package/docs/templates/product-line/scaffold-samples/fe-with-api/requirement.md +6 -0
- package/docs/templates/product-line/scaffold-samples/fe-with-api/tasks/BE-IMPL-001.yaml +84 -0
- package/docs/templates/product-line/scaffold-samples/fe-with-api/tasks/CONTRACT-001.yaml +84 -0
- package/docs/templates/product-line/scaffold-samples/fe-with-api/tasks/FE-IMPL-001.yaml +86 -0
- package/docs/templates/product-line/scaffold-samples/fe-with-api/tasks/task-graph.yaml +40 -0
- package/docs/templates/product-line/scaffold-samples/frontend-only/acceptance.yaml +13 -0
- package/docs/templates/product-line/scaffold-samples/frontend-only/design.md +14 -0
- package/docs/templates/product-line/scaffold-samples/frontend-only/feature.yaml +3 -0
- package/docs/templates/product-line/scaffold-samples/frontend-only/requirement.md +6 -0
- package/docs/templates/product-line/scaffold-samples/frontend-only/tasks/FE-IMPL-001.yaml +85 -0
- package/docs/templates/product-line/scaffold-samples/frontend-only/tasks/task-graph.yaml +14 -0
- package/examples/l5-report-coms-process-definition.html +322 -0
- package/package.json +1 -1
- package/skills/agent-worker/references/agent-worker-operator.md +84 -0
- package/skills/frontend-implementation/references/node-contracts.md +2 -2
- package/skills/loop-agent/SKILL.md +14 -16
- package/skills/loop-agent/references/command-reference.md +33 -12
- package/skills/loop-agent/references/harness-policy.md +28 -6
- package/skills/loop-agent/references/hybrid-dag.md +8 -7
- package/skills/loop-agent/references/post-implementation-and-patterns.md +19 -9
- package/skills/loop-agent/references/source-and-plan-practice.md +161 -0
- package/skills/loop-agent/references/task-workflow.md +13 -5
|
@@ -280,6 +280,37 @@ export const dagBackendTestPipelineSchema = z.enum([
|
|
|
280
280
|
"markdown-traceability",
|
|
281
281
|
"markdown-execute-html",
|
|
282
282
|
]);
|
|
283
|
+
export const dagFrontendTestEvidenceValidationSchema = z.object({}).strict();
|
|
284
|
+
export const dagMavenWorkspaceManifestSchema = z.object({
|
|
285
|
+
files: z.array(z.object({
|
|
286
|
+
path: z.string(),
|
|
287
|
+
size: z.number(),
|
|
288
|
+
mtimeMs: z.number(),
|
|
289
|
+
})),
|
|
290
|
+
directories: z.array(z.object({
|
|
291
|
+
path: z.string(),
|
|
292
|
+
entryNames: z.array(z.string()),
|
|
293
|
+
})),
|
|
294
|
+
});
|
|
295
|
+
export const dagMavenVerificationPlanSchema = z.object({
|
|
296
|
+
schemaVersion: z.number().int().positive(),
|
|
297
|
+
plannerVersion: z.string().min(1),
|
|
298
|
+
fingerprint: z.string().min(1),
|
|
299
|
+
inputDigest: z.string().min(1),
|
|
300
|
+
targets: z.array(z.object({
|
|
301
|
+
pomPath: z.string().min(1),
|
|
302
|
+
artifactId: z.string().min(1),
|
|
303
|
+
reactorRootPomPath: z.string().min(1).optional(),
|
|
304
|
+
moduleCoordinate: z.string().min(1).optional(),
|
|
305
|
+
})),
|
|
306
|
+
commandDigests: z.array(z.string()),
|
|
307
|
+
plannedCommands: z.array(z.object({
|
|
308
|
+
label: z.string(),
|
|
309
|
+
args: z.array(z.string()),
|
|
310
|
+
})),
|
|
311
|
+
workspaceManifest: dagMavenWorkspaceManifestSchema.optional(),
|
|
312
|
+
shellCommandDigests: z.array(z.string()).optional(),
|
|
313
|
+
});
|
|
283
314
|
export const dagShellConfigSchema = z.object({
|
|
284
315
|
commands: z.array(z.string()).default([]),
|
|
285
316
|
preset: dagShellPresetSchema.optional(),
|
|
@@ -293,7 +324,19 @@ export const dagShellConfigSchema = z.object({
|
|
|
293
324
|
frontendLintBaseline: dagFrontendLintBaselineSchema.optional(),
|
|
294
325
|
frontendVerificationBundle: dagFrontendVerificationBundleSchema.optional(),
|
|
295
326
|
frontendReviewContext: dagFrontendReviewContextSchema.optional(),
|
|
327
|
+
frontendTestEvidenceValidation: dagFrontendTestEvidenceValidationSchema.optional(),
|
|
296
328
|
backendTestPipeline: dagBackendTestPipelineSchema.optional(),
|
|
329
|
+
/** JaCoCo coverage collection for backend-test (Java services). When set, node 7 dumps coverage over TCP from a JaCoCo tcpserver agent and feeds it to the L-5 dashboard. */
|
|
330
|
+
jacocoCoverage: z.object({
|
|
331
|
+
/** JaCoCo tcpserver endpoint, e.g. "host:6300". */
|
|
332
|
+
endpoint: z.string().min(1),
|
|
333
|
+
/** Absolute path to jacococli.jar on this machine, used to convert .exec → jacoco.xml. */
|
|
334
|
+
cliJarPath: z.string().min(1),
|
|
335
|
+
/** Business package filter passed to JaCoCo includes, e.g. "com.example.*". Defaults to "*". */
|
|
336
|
+
includes: z.string().min(1).optional().default("*"),
|
|
337
|
+
/** TCP connect timeout in ms. Defaults to 5000. */
|
|
338
|
+
connectTimeoutMs: z.number().int().positive().optional().default(5000),
|
|
339
|
+
}).strict().optional(),
|
|
297
340
|
verifyEvidence: dagShellVerifyEvidenceSchema.optional(),
|
|
298
341
|
repairArtifactGate: dagRepairArtifactGateSchema.optional(),
|
|
299
342
|
/** fail (default): any nonzero command fails the node. record: finish node FINISHED with failure facts for downstream assess/repair. */
|
|
@@ -301,6 +344,8 @@ export const dagShellConfigSchema = z.object({
|
|
|
301
344
|
envAllowlist: z.array(z.string()).optional(),
|
|
302
345
|
timeoutMs: z.number().optional(),
|
|
303
346
|
cwd: z.string().optional(),
|
|
347
|
+
/** Frozen Maven verification plan; shell executor re-checks fingerprint before running. */
|
|
348
|
+
mavenVerificationPlan: dagMavenVerificationPlanSchema.optional(),
|
|
304
349
|
});
|
|
305
350
|
export const dagStaticConfigSchema = z.object({
|
|
306
351
|
resultMarkdown: z.string().min(1),
|
|
@@ -408,6 +453,11 @@ export const dagDecisionGateSchema = z.object({
|
|
|
408
453
|
schemaVersion: z.literal(1).optional(),
|
|
409
454
|
mode: dagDecisionGateModeSchema.optional().default("record-only"),
|
|
410
455
|
});
|
|
456
|
+
export const dagWriterOutcomePolicySchema = z
|
|
457
|
+
.object({
|
|
458
|
+
type: z.literal("implementation-outcome-v1"),
|
|
459
|
+
})
|
|
460
|
+
.strict();
|
|
411
461
|
export const dagConvergenceSpecSchema = z
|
|
412
462
|
.object({
|
|
413
463
|
enabled: z.boolean().optional().default(false),
|
|
@@ -465,6 +515,13 @@ export const dagTaskSchema = z.object({
|
|
|
465
515
|
* on safe read-only Pi nodes before the node becomes ERROR.
|
|
466
516
|
*/
|
|
467
517
|
outputProtocol: dagOutputProtocolSchema.optional(),
|
|
518
|
+
/**
|
|
519
|
+
* Fail-closed outcome/diff consistency contract for bounded Pi writers.
|
|
520
|
+
* The writer must begin with IMPLEMENTATION_OUTCOME: changed,
|
|
521
|
+
* already-satisfied, or blocked; the executor checks it against the
|
|
522
|
+
* run-attributed diff.
|
|
523
|
+
*/
|
|
524
|
+
writerOutcomePolicy: dagWriterOutcomePolicySchema.optional(),
|
|
468
525
|
/**
|
|
469
526
|
* Explicit opt-in for the deterministic project governance context resolver
|
|
470
527
|
* (AGENTS.md chain + referenced code standards). Only tasks that set this
|
|
@@ -461,10 +461,11 @@ function validateShellTaskConfig(task, spec, issues) {
|
|
|
461
461
|
!shell.backendTestPipeline &&
|
|
462
462
|
!shell.frontendPrewriteGate &&
|
|
463
463
|
!shell.frontendVerificationBundle &&
|
|
464
|
-
!shell.frontendReviewContext
|
|
464
|
+
!shell.frontendReviewContext &&
|
|
465
|
+
!shell.frontendTestEvidenceValidation) {
|
|
465
466
|
issues.push({
|
|
466
467
|
type: "missing-shell-commands",
|
|
467
|
-
message: `shell task ${task.id} requires
|
|
468
|
+
message: `shell task ${task.id} requires a supported shell operation or non-empty shell.commands`,
|
|
468
469
|
});
|
|
469
470
|
}
|
|
470
471
|
if (commands.some((command) => command.trim().length === 0)) {
|
|
@@ -603,6 +604,21 @@ function validateOutputProtocolTaskConfig(task, issues) {
|
|
|
603
604
|
});
|
|
604
605
|
}
|
|
605
606
|
}
|
|
607
|
+
function validateWriterOutcomePolicyTaskConfig(task, issues) {
|
|
608
|
+
if (task.writerOutcomePolicy === undefined)
|
|
609
|
+
return;
|
|
610
|
+
const isBoundedPiWriter = task.executor === "pi" &&
|
|
611
|
+
task.toolProfile === "write" &&
|
|
612
|
+
task.role === "implementer" &&
|
|
613
|
+
task.writePolicy === "exclusive" &&
|
|
614
|
+
(task.writeSet?.length ?? 0) > 0;
|
|
615
|
+
if (!isBoundedPiWriter) {
|
|
616
|
+
issues.push({
|
|
617
|
+
type: "invalid-writer-outcome-policy",
|
|
618
|
+
message: `task ${task.id} declares writerOutcomePolicy but is not a bounded exclusive Pi implementer writer`,
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
}
|
|
606
622
|
function validateDecisionGateTaskConfig(task, issues) {
|
|
607
623
|
if (!task.decisionGate?.enabled) {
|
|
608
624
|
return;
|
|
@@ -757,6 +773,7 @@ export function validateDagSpec(spec) {
|
|
|
757
773
|
validateDecisionGateTaskConfig(task, issues);
|
|
758
774
|
validateRetryPolicyTaskConfig(task, issues);
|
|
759
775
|
validateOutputProtocolTaskConfig(task, issues);
|
|
776
|
+
validateWriterOutcomePolicyTaskConfig(task, issues);
|
|
760
777
|
validateProjectGovernanceTaskConfig(task, spec, issues);
|
|
761
778
|
validateFailureAwareDependsOn(task, spec, issues);
|
|
762
779
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { mkdir } from "node:fs/promises";
|
|
3
3
|
import { writeLoopDagRecord } from "../../../infrastructure/harness/loop-action-store.js";
|
|
4
|
+
import { getTaskPaths } from "../../../task/runtime.js";
|
|
4
5
|
import { getLoopPaths } from "../paths.js";
|
|
5
6
|
import { appendLoopRound } from "../rounds.js";
|
|
6
7
|
import { rewriteLoopContext } from "../context.js";
|
|
@@ -26,7 +27,7 @@ export async function runLoopDagAction(repoRoot, taskId, options = {}) {
|
|
|
26
27
|
await mkdir(dagEvidenceDir, { recursive: true });
|
|
27
28
|
const dagPath = options.dagPath
|
|
28
29
|
? path.resolve(repoRoot, options.dagPath)
|
|
29
|
-
:
|
|
30
|
+
: getTaskPaths(repoRoot, taskId).dagDraftPath;
|
|
30
31
|
const runner = options.runner ?? resolveDefaultRunner(repoRoot);
|
|
31
32
|
let generated = {};
|
|
32
33
|
if (!options.dagPath) {
|
|
@@ -128,7 +128,7 @@ decision envelope 中的 **model verdict**(`decision` / `riskLevel` 等解析
|
|
|
128
128
|
|
|
129
129
|
- **pause → approve → resume**:`dag approve` 在 paused run 写 `human-approval.json`,将状态改回 `running` 并把目录迁回 `active/`;随后 `resumeDagRun`(`runner.ts`)要求 active lifecycle + approval artifact,并用 `prepareSkillSnapshotForContinuation` 复用 run-owned snapshot。
|
|
130
130
|
- **completed 写入**:只有 runner 在终态 `persistState({ allowCompletedFactsWrite: true })`(`runner.ts`)才能写 completed 目录;该 flag 经 `completed-facts-guard.ts` 校验。
|
|
131
|
-
- **显式 recovery mutation**:`dag reconcile-run`(`src/commands/dag-reconcile-run.ts`,命令层)默认仅检查;只有给出 `--action supersede|abandon` + reason,且 liveness 证明 runner 已停止时,才在原 lifecycle 写 reconciliation/state 并迁移到 `completed
|
|
131
|
+
- **显式 recovery mutation**:`dag reconcile-run`(`src/commands/dag-reconcile-run.ts`,命令层)默认仅检查;只有给出 `--action supersede|abandon` + reason,且 liveness 证明 runner 已停止时,才在原 lifecycle 写 reconciliation/state 并迁移到 `completed/`。仍为 `RUNNING` 的节点保持失败语义,但以 `reconciledAt - startedAt` 补齐节点和当前 attempt 的耗时,原始状态继续冻结在 `reconciliation.json`。它不是修改既有 completed history 的通用入口。Observe / status / doctor 始终只读。
|
|
132
132
|
- **status 枚举**:`DagRunState.status`;`TERMINAL_RUN_STATUSES` 判终态;`isTerminalDagRunStatus` 工具函数。
|
|
133
133
|
|
|
134
134
|
## convergence(可选、supervised)
|
|
@@ -142,6 +142,10 @@ decision envelope 中的 **model verdict**(`decision` / `riskLevel` 等解析
|
|
|
142
142
|
|
|
143
143
|
完成声明的权威是 shell command 的新鲜 exit code 与归档输出。验证命令执行在 `src/executors/shell-executor.ts`,环境与 preset helper 在 `src/executors/shell-verification.ts`;DAG authoring 写入的 `task.shell.verifyEvidence` 元数据由 `src/workflows/dag/node-execution.ts` 复制到 `node.verifyEvidence`。model verdict、Observe 或报告都不能替代这些 shell facts。
|
|
144
144
|
|
|
145
|
+
supervised 的 `soft-verify-shell` 只运行聚焦命令,明确排除无参数的 `npm test`、`npm run test` 与 `scripts/ci.sh` 等 full-suite 入口;`hard-verify-shell` 保留一次完整 final 集合。task 与 adapter 命令合并时会解包可证明安全的单命令 `bash -lc` wrapper,并以规范化 cwd、argv、env、timeout 做语义去重;`verifyEvidence.commandCount/commandLabels/commandTexts` 必须对应去重后实际执行的命令。
|
|
146
|
+
|
|
147
|
+
Pi SDK 正常路径继续在内存中传递 system prompt;只有 CLI fallback / `cli-only` 才通过权限收紧的系统临时文件传给 `--append-system-prompt`,归档命令只保存占位符。transport 解析并记录真实 temp root,持有 prompt 文件句柄,并冻结 temp root、随机私有目录、固定文件名三层 identity;收口时先用句柄清空正文,三层 identity 均匹配才精确 `unlink` 文件并非递归 `rmdir` 空目录。未知 sibling、symlink/junction 或 identity 漂移都会拒绝扩大删除范围。shell 与 Pi 子进程以独立进程组启动;超时在 Windows 使用 tree termination、在 POSIX 对进程组发信号,防止 npm/Vitest/tsx 后代在节点结束后继续持有 IPC 或临时文件。
|
|
148
|
+
|
|
145
149
|
## Dynamic Workflow
|
|
146
150
|
|
|
147
151
|
Dynamic Workflow 是 DAG runtime 上方的逻辑编排/编译层,**不**重写 runner:
|
|
@@ -18,6 +18,9 @@ Application layer (src/application/,逐步引入)
|
|
|
18
18
|
Workflow runtime (src/workflows/)
|
|
19
19
|
└─ DAG / Dynamic / Loop 核心执行规则;不应依赖 commands
|
|
20
20
|
|
|
21
|
+
Verification planners (src/verification/)
|
|
22
|
+
└─ 生成期/执行期验证规划(如 Maven workspace 静态图与冻结计划);纯库模块,不跑 CLI
|
|
23
|
+
|
|
21
24
|
Executors (src/executors/)
|
|
22
25
|
└─ Pi / Shell / Static 等受治理外部工具适配;不应依赖 commands 或 CLI formatting
|
|
23
26
|
|
|
@@ -66,11 +69,18 @@ Governance (scripts/check-*.sh, src/governance/)
|
|
|
66
69
|
- **允许依赖**:`src/executors/**`、`src/task/**`、`src/records/**`、`src/shared/**`、application use-case(目标态)。
|
|
67
70
|
- **禁止**:`import` 来自 `src/commands/**`(见下方过渡例外)。
|
|
68
71
|
|
|
72
|
+
### Verification planners
|
|
73
|
+
|
|
74
|
+
- **位置**:`src/verification/**`(当前含 `src/verification/maven/**`)
|
|
75
|
+
- **职责**:在 DAG 生成阶段与 `verify-shell` 执行前,对任务作用域驱动的验证命令做静态规划与冻结计划复核(例如 Maven Workspace Graph、`-f/-pl/-am` 重写、`.harness/cache/` 图缓存、`verification-plan-stale`)。
|
|
76
|
+
- **允许依赖**:`src/adapters/types`(`VerifyCommand`)、Node 标准库;由 `src/workflows/dag/**` 与 `src/executors/shell-executor.ts` 调用。
|
|
77
|
+
- **禁止**:执行 Maven/npm 等外部 goal 做发现;依赖 `src/commands/**` 或 CLI;把独立 POM 拼成伪 reactor;按 first-match/深度/字典序/启动 cwd 选择目标。
|
|
78
|
+
|
|
69
79
|
### Executors
|
|
70
80
|
|
|
71
81
|
- **位置**:`src/executors/**`
|
|
72
82
|
- **职责**:封装 Pi SDK、shell 执行、static 输出与 write guard。受治理 Agent runtime 只有 Pi。
|
|
73
|
-
- **允许依赖**:`src/shared
|
|
83
|
+
- **允许依赖**:`src/shared/**`、`src/verification/**`(执行前计划复核)、外部 SDK(不含 `@cursor/sdk`)。
|
|
74
84
|
- **禁止**:依赖 `src/commands/**`、CLI 输出格式,或 import `src/sidecars/**` / `@cursor/sdk`。
|
|
75
85
|
|
|
76
86
|
### Sidecars
|
|
@@ -88,6 +88,8 @@ controller identity 与 DAG skill snapshot 是两个不同冻结层(前者跨
|
|
|
88
88
|
| 入口 | 职责 |
|
|
89
89
|
| --- | --- |
|
|
90
90
|
| `agent-worker feature verify-final` | **唯一** canonical writer:Feature Verification Bundle、`qa-pass.json`、`final-verification.json` |
|
|
91
|
+
| `agent-worker feature advance` | 编排 verify-final → delivery → closeout preview[/apply](ADR 0007 运维入口) |
|
|
92
|
+
| `agent-worker feature doctor` | 只读诊断证据/Pool/dirty worktree;建议下一步命令 |
|
|
91
93
|
| Feature Packet `FINAL-VERIFY-*`(若保留) | 可选 **local smoke recipe**(样本 `verify:final` / reports);Task Done ≠ Final Verification Record |
|
|
92
94
|
| `feature delivery` | 重验 verify-final 证据;省略路径时默认 `.harness/task-pool/evidence/<featureId>/{qa-pass,final-verification}.json` |
|
|
93
95
|
| `feature closeout` | 只认 Delivery manifest + Final Verification Record 链 |
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"skills/agent-worker/references/agent-worker-operator.md",
|
|
56
56
|
"skills/loop-agent/SKILL.md",
|
|
57
57
|
"skills/loop-agent/references/command-reference.md",
|
|
58
|
+
"skills/loop-agent/references/source-and-plan-practice.md",
|
|
58
59
|
"skills/loop-agent/references/docs-converge.md",
|
|
59
60
|
"skills/ai-engineering-context/SKILL.md",
|
|
60
61
|
"skills/verification-before-completion/SKILL.md",
|
|
@@ -133,6 +134,7 @@
|
|
|
133
134
|
".agents/skills/agent-worker/references/agent-worker-operator.md",
|
|
134
135
|
".agents/skills/loop-agent/SKILL.md",
|
|
135
136
|
".agents/skills/loop-agent/references/command-reference.md",
|
|
137
|
+
".agents/skills/loop-agent/references/source-and-plan-practice.md",
|
|
136
138
|
".agents/skills/loop-agent/references/docs-converge.md",
|
|
137
139
|
".agents/skills/ai-engineering-context/SKILL.md",
|
|
138
140
|
".agents/skills/verification-before-completion/SKILL.md",
|
|
@@ -212,6 +214,7 @@
|
|
|
212
214
|
".agents/skills/agent-worker/references/agent-worker-operator.md": "copied",
|
|
213
215
|
".agents/skills/loop-agent/SKILL.md": "copied",
|
|
214
216
|
".agents/skills/loop-agent/references/command-reference.md": "copied",
|
|
217
|
+
".agents/skills/loop-agent/references/source-and-plan-practice.md": "copied",
|
|
215
218
|
".agents/skills/loop-agent/references/docs-converge.md": "copied",
|
|
216
219
|
".agents/skills/ai-engineering-context/SKILL.md": "copied",
|
|
217
220
|
".agents/skills/verification-before-completion/SKILL.md": "copied",
|
|
@@ -250,7 +250,7 @@
|
|
|
250
250
|
".harness/dag-runs/**",
|
|
251
251
|
"artifacts/**"
|
|
252
252
|
],
|
|
253
|
-
"outputContract": "One scoped pytest execution over Markdown-mapped scripts producing a valid pytest-html report with per-case captured output, self-contained reports/backend-test.html
|
|
253
|
+
"outputContract": "One scoped pytest execution over Markdown-mapped scripts producing a valid pytest-html report with per-case captured output, self-contained reports/backend-test.html, reports/backend-test.md, reports/backend-test-facts.md, a deterministic self-contained reports/backend-test-l5-dashboard.html (machine-computed L-5 metrics, no JSON), and an optional contracts/code-coverage-v1.json when jacocoCoverage is configured (JaCoCo TCP dump → jacoco.xml → parsed; failure-safe); exit 0/1 with valid evidence continues.",
|
|
254
254
|
"subtask_prompt": "Resolve the final Markdown Automation Notes/自动化映射 to a unique, safe set of testcase/**/test_*.py targets and execute only those scripts exactly once. Prefer the deterministic module one-to-one path when a mapped script is missing but the module stem file exists. Generate a native pytest-html self-contained report, then render the primary self-contained Chinese HTML report from the same pytest-html plus final Markdown case metadata without rerun. Keep 测试结论, quality status, failure overview, and a polished per-case result card with concise scenario, automation test name, result, duration, and redacted bounded HTTP request parameters/response results for both passed and failed cases. Do not render a technical/execution evidence section in HTML; retain auditable paths and hashes in facts.",
|
|
255
255
|
"shell": {
|
|
256
256
|
"commands": [
|
|
@@ -283,8 +283,8 @@
|
|
|
283
283
|
".harness/dag-runs/**",
|
|
284
284
|
"artifacts/**"
|
|
285
285
|
],
|
|
286
|
-
"outputContract": "Final Markdown report and L-5 conclusion under docs/test-reports/**; no JSON.",
|
|
287
|
-
"subtask_prompt": "Generate the final Markdown report from upstream facts and run-owned environment, advisory case-validation, advisory traceability, pytest-html and HTML evidence. Do not emit JSON.\n\nUse this exact human-facing section order: 测试结论 → 执行概览 → 质量校验 → 失败分析 → 风险与建议 → 证据与 L-5. Put the decision and key numbers first, use compact tables/bullets, and keep headings concise. Do not paste entire upstream reports, duplicate per-case tables already present in facts, or repeat the same evidence in multiple sections; link to paths/hashes and quote only the findings needed for the conclusion.\n\nAlways state the exact PASS/FAIL status and findings from nodes 4 and 6. Their FAIL status does not block pytest, but it must remain visible as a quality/traceability risk and must never be rewritten as PASS.\n\nInclude environment, case quality/review, automation mapping, exact pytest facts, failure classification/analysis, risks, regression recommendations, evidence paths/hashes, coverage availability, and L-5 READY/NOT READY.\n\nNever override Shell/pytest-html facts. L-5 requires pass=100%, AC=100%, automation>=90%, line>=80%, branch>=70%, skipped=0 and no blocking Critical risk.\n\nWrite only under docs/test-reports/**."
|
|
286
|
+
"outputContract": "Final Markdown report and L-5 conclusion under docs/test-reports/**; the deterministic L-5 dashboard at reports/backend-test-l5-dashboard.html is the authoritative visualization and must be linked, not re-rendered; no JSON.",
|
|
287
|
+
"subtask_prompt": "Generate the final Markdown report from upstream facts and run-owned environment, advisory case-validation, advisory traceability, pytest-html and HTML evidence. Do not emit JSON.\n\nUse this exact human-facing section order: 测试结论 → 执行概览 → 质量校验 → 失败分析 → 风险与建议 → 证据与 L-5. Put the decision and key numbers first, use compact tables/bullets, and keep headings concise. Do not paste entire upstream reports, duplicate per-case tables already present in facts, or repeat the same evidence in multiple sections; link to paths/hashes and quote only the findings needed for the conclusion.\n\nThe L-5 metrics and visualization are already produced deterministically by node 7 at reports/backend-test-l5-dashboard.html (rendered from computeL5ReportMetrics). Link to that dashboard as the authoritative L-5 view; do not recompute pass/AC/automation/coverage numbers or re-render an HTML dashboard yourself. Quote its L-5 decision verbatim.\n\nAlways state the exact PASS/FAIL status and findings from nodes 4 and 6. Their FAIL status does not block pytest, but it must remain visible as a quality/traceability risk and must never be rewritten as PASS.\n\nInclude environment, case quality/review, automation mapping, exact pytest facts, failure classification/analysis, risks, regression recommendations, evidence paths/hashes, coverage availability, and L-5 READY/NOT READY.\n\nNever override Shell/pytest-html facts. L-5 requires pass=100%, AC=100%, automation>=90%, line>=80%, branch>=70%, skipped=0 and no blocking Critical risk.\n\nWrite only under docs/test-reports/**."
|
|
288
288
|
}
|
|
289
289
|
],
|
|
290
290
|
"sourceBinding": {
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
# Product-line feature packet
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**推荐入口(确定性脚手架):**
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
agent-worker feature scaffold --repo . --template backend-only \
|
|
7
|
+
--feature-id F-2026-010 --title "..." \
|
|
8
|
+
--be-path services/example/** \
|
|
9
|
+
--verify-command "npm run typecheck" --verify-command "npm test"
|
|
10
|
+
agent-worker task validate-feature features/F-2026-010
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
批量示例见 [`feature-scaffold-batch.example.yaml`](feature-scaffold-batch.example.yaml)。
|
|
14
|
+
|
|
15
|
+
**生成快照(可读、防漂移,非 dogfood)**见 [`scaffold-samples/`](scaffold-samples/):`backend-only` / `frontend-only` / `fe-with-api`。刷新:`node --import tsx/esm scripts/generate-scaffold-samples.mjs`;校验:同脚本 `--check` 或 `bash scripts/check-scaffold-samples.sh`。
|
|
16
|
+
|
|
17
|
+
操作说明以 skill 包内 `skills/agent-worker/references/agent-worker-operator.md` § Feature Packet Scaffold 为准(不依赖 website 是否随包)。
|
|
18
|
+
|
|
19
|
+
也可手工复制本目录占位文件,替换 angle-bracket placeholders,保持 IDs 稳定,然后运行:
|
|
4
20
|
|
|
5
21
|
```bash
|
|
6
22
|
agent-worker task validate-feature <feature-dir>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Example batch for: agent-worker feature scaffold --batch <this-file> --repo <repo>
|
|
2
|
+
# Every feature_id must be explicit (v1 does not auto-allocate IDs).
|
|
3
|
+
# Any invalid row fails the whole batch with zero writes.
|
|
4
|
+
|
|
5
|
+
features:
|
|
6
|
+
- feature_id: F-2026-010
|
|
7
|
+
title: Banner 拉取欢迎语
|
|
8
|
+
template: fe-with-api
|
|
9
|
+
description: 前端 Banner 调用薄 API 展示欢迎语
|
|
10
|
+
fe_paths:
|
|
11
|
+
- apps/web/src/welcome/**
|
|
12
|
+
be_paths:
|
|
13
|
+
- services/welcome/**
|
|
14
|
+
verify_commands:
|
|
15
|
+
- npm run typecheck
|
|
16
|
+
- npm test
|
|
17
|
+
acceptance:
|
|
18
|
+
- id: AC-001
|
|
19
|
+
title: 页面展示非空 message
|
|
20
|
+
given: 欢迎语接口可用
|
|
21
|
+
when: 用户打开页面
|
|
22
|
+
then: 页面展示非空 message
|
|
23
|
+
|
|
24
|
+
- feature_id: F-2026-011
|
|
25
|
+
title: 设置页主题切换
|
|
26
|
+
template: frontend-only
|
|
27
|
+
fe_paths:
|
|
28
|
+
- apps/web/src/settings/theme/**
|
|
29
|
+
verify_commands:
|
|
30
|
+
- npm run typecheck
|
|
31
|
+
- npm test
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Scaffold samples (generated snapshots)
|
|
2
|
+
|
|
3
|
+
> **身份**:由 `agent-worker feature scaffold` **同一套 typed builders** 生成的只读快照,供人阅读与防漂移对照。
|
|
4
|
+
> **不是** 运行中的 dogfood Feature,**不是** 默认模板源(生成器仍以 `src/worker/feature/scaffold.ts` 为准)。
|
|
5
|
+
> **不要** 复制进 `features/` 当业务 Feature;日常请直接跑 `feature scaffold`。
|
|
6
|
+
|
|
7
|
+
## 目录
|
|
8
|
+
|
|
9
|
+
| 子目录 | 模板 | 快照 feature_id |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| `backend-only/` | pure backend | `F-2099-901` |
|
|
12
|
+
| `frontend-only/` | pure frontend | `F-2099-902` |
|
|
13
|
+
| `fe-with-api/` | contract + BE + FE | `F-2099-903` |
|
|
14
|
+
|
|
15
|
+
ID 使用 `F-2099-*` 号段,避免与 `features/F-2026-*` dogfood 混淆。
|
|
16
|
+
|
|
17
|
+
## 刷新 / 校验
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# 按当前 scaffold 实现重写本目录
|
|
21
|
+
node --import tsx/esm scripts/generate-scaffold-samples.mjs
|
|
22
|
+
|
|
23
|
+
# CI / 本地:快照必须与当前 builder 一致
|
|
24
|
+
node --import tsx/esm scripts/generate-scaffold-samples.mjs --check
|
|
25
|
+
npx vitest run test/worker/feature/scaffold-samples.test.ts
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`scripts/check-repo.sh` 会调用 `--check`。若你改了 scaffold 模板语义,请先 generate 再提交快照。
|
|
29
|
+
|
|
30
|
+
## 与真实 Packet 的关系
|
|
31
|
+
|
|
32
|
+
| 路径 | 用途 |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| 本目录 | 文档可读快照 + 漂移门禁 |
|
|
35
|
+
| `features/F-2026-*` | 仓库内真实 / dogfood Feature |
|
|
36
|
+
| 用户目标仓 `features/F-YYYY-NNN/` | `feature scaffold --repo <target>` 写入处 |
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
feature_id: F-2099-901
|
|
3
|
+
acceptance:
|
|
4
|
+
- id: AC-001
|
|
5
|
+
title: Scaffold sample — backend-only
|
|
6
|
+
priority: must
|
|
7
|
+
type: behavior
|
|
8
|
+
given: 需求与路径边界已冻结
|
|
9
|
+
when: Feature Packet 内实现任务完成
|
|
10
|
+
then: 验收目标达成且 verify.commands 通过
|
|
11
|
+
verification:
|
|
12
|
+
expected_task_refs:
|
|
13
|
+
- BE-IMPL-001
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Design — Scaffold sample — backend-only
|
|
2
|
+
|
|
3
|
+
## Goals
|
|
4
|
+
|
|
5
|
+
Generated snapshot for docs/templates/product-line/scaffold-samples. Not a live dogfood Feature.
|
|
6
|
+
|
|
7
|
+
## Paths
|
|
8
|
+
|
|
9
|
+
- Backend allowed paths:
|
|
10
|
+
- `services/sample-backend/**`
|
|
11
|
+
|
|
12
|
+
## Artifacts
|
|
13
|
+
|
|
14
|
+
- `BE-IMPL-001` produces `backend-impl`
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
id: BE-IMPL-001
|
|
3
|
+
feature_id: F-2099-901
|
|
4
|
+
title: Scaffold sample — backend-only — 后端实现
|
|
5
|
+
description: Generated snapshot for
|
|
6
|
+
docs/templates/product-line/scaffold-samples. Not a live dogfood Feature.
|
|
7
|
+
repo:
|
|
8
|
+
name: loop-agent
|
|
9
|
+
path_ref: .
|
|
10
|
+
default_branch: main
|
|
11
|
+
type: backend-feature
|
|
12
|
+
priority: P2
|
|
13
|
+
risk_level: medium
|
|
14
|
+
depends_on: []
|
|
15
|
+
source_docs:
|
|
16
|
+
requirement: ../requirement.md
|
|
17
|
+
acceptance: ../acceptance.yaml
|
|
18
|
+
design: ../design.md
|
|
19
|
+
acceptance_refs:
|
|
20
|
+
- AC-001
|
|
21
|
+
scope:
|
|
22
|
+
goals:
|
|
23
|
+
- 实现后端变更并满足验收
|
|
24
|
+
non_goals:
|
|
25
|
+
- 不扩展到模板外的 Task 节点(无 BE-TEST/FE-TEST/FINAL-VERIFY)
|
|
26
|
+
assumptions:
|
|
27
|
+
- verify.commands 由 scaffold 调用方显式提供
|
|
28
|
+
open_questions: []
|
|
29
|
+
constraints:
|
|
30
|
+
allowed_paths:
|
|
31
|
+
- services/sample-backend/**
|
|
32
|
+
- docs/progress/F-2099-901/be/status.md
|
|
33
|
+
- docs/progress/F-2099-901/be/**
|
|
34
|
+
forbidden_paths:
|
|
35
|
+
- config/prod/**
|
|
36
|
+
- .env
|
|
37
|
+
- .env.*
|
|
38
|
+
- secrets/**
|
|
39
|
+
- apps/**
|
|
40
|
+
hard_constraints:
|
|
41
|
+
- 不读取生产密钥
|
|
42
|
+
- 不绕过 scaffold 冻结的 depends/produces/consumes
|
|
43
|
+
execution:
|
|
44
|
+
workflow: agent-dag
|
|
45
|
+
verify:
|
|
46
|
+
preset: standard
|
|
47
|
+
mode: serial
|
|
48
|
+
quota: full
|
|
49
|
+
commands:
|
|
50
|
+
- id: verify-1
|
|
51
|
+
label: npm run typecheck
|
|
52
|
+
command: npm run typecheck
|
|
53
|
+
required: true
|
|
54
|
+
timeout_ms: 300000
|
|
55
|
+
- id: verify-2
|
|
56
|
+
label: npm test
|
|
57
|
+
command: npm test
|
|
58
|
+
required: true
|
|
59
|
+
timeout_ms: 300000
|
|
60
|
+
worker:
|
|
61
|
+
execution_mode: generate-validate-run
|
|
62
|
+
max_attempts: 1
|
|
63
|
+
timeout_ms: 7200000
|
|
64
|
+
require_clean_worktree: true
|
|
65
|
+
require_human_review: true
|
|
66
|
+
create_worktree: false
|
|
67
|
+
loop_agent:
|
|
68
|
+
profile_policy: mapped
|
|
69
|
+
strict_models: true
|
|
70
|
+
strict_governance: true
|
|
71
|
+
max_concurrent: 1
|
|
72
|
+
outputs:
|
|
73
|
+
required:
|
|
74
|
+
- dag_json
|
|
75
|
+
- dag_validate_json
|
|
76
|
+
- run_record
|
|
77
|
+
- dag_report_json
|
|
78
|
+
- shell_verification
|
|
79
|
+
- closeout_or_failure_handoff
|
|
80
|
+
failure_policy:
|
|
81
|
+
failed_run_promote: false
|
|
82
|
+
generate_closeout_draft: true
|
|
83
|
+
create_followup_task: true
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
feature_id: F-2099-901
|
|
3
|
+
nodes:
|
|
4
|
+
- id: BE-IMPL-001
|
|
5
|
+
task: BE-IMPL-001.yaml
|
|
6
|
+
type: backend-feature
|
|
7
|
+
depends_on: []
|
|
8
|
+
produces:
|
|
9
|
+
- kind: backend-impl
|
|
10
|
+
schemaId: backend-impl-v1
|
|
11
|
+
path: services/sample-backend
|
|
12
|
+
parallel_policy:
|
|
13
|
+
max_parallel_tasks: 1
|
|
14
|
+
disallow_same_file_parallel_writes: true
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
feature_id: F-2099-903
|
|
3
|
+
acceptance:
|
|
4
|
+
- id: AC-001
|
|
5
|
+
title: Scaffold sample — fe-with-api
|
|
6
|
+
priority: must
|
|
7
|
+
type: behavior
|
|
8
|
+
given: 需求与路径边界已冻结
|
|
9
|
+
when: Feature Packet 内实现任务完成
|
|
10
|
+
then: 验收目标达成且 verify.commands 通过
|
|
11
|
+
verification:
|
|
12
|
+
expected_task_refs:
|
|
13
|
+
- CONTRACT-001
|
|
14
|
+
- BE-IMPL-001
|
|
15
|
+
- FE-IMPL-001
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Design — Scaffold sample — fe-with-api
|
|
2
|
+
|
|
3
|
+
## Goals
|
|
4
|
+
|
|
5
|
+
Generated snapshot for docs/templates/product-line/scaffold-samples. Not a live dogfood Feature.
|
|
6
|
+
|
|
7
|
+
## Paths
|
|
8
|
+
|
|
9
|
+
- Backend allowed paths:
|
|
10
|
+
- `services/sample-api/**`
|
|
11
|
+
- Frontend allowed paths:
|
|
12
|
+
- `apps/web/src/sample-api/**`
|
|
13
|
+
- Contract path: `docs/contracts/F-2099-903/api.md`
|
|
14
|
+
|
|
15
|
+
## Artifacts
|
|
16
|
+
|
|
17
|
+
- `CONTRACT-001` produces `api-contract`
|
|
18
|
+
- `BE-IMPL-001` / `FE-IMPL-001` consume `api-contract` (only formal consumers)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
id: BE-IMPL-001
|
|
3
|
+
feature_id: F-2099-903
|
|
4
|
+
title: Scaffold sample — fe-with-api — 后端实现
|
|
5
|
+
description: Generated snapshot for
|
|
6
|
+
docs/templates/product-line/scaffold-samples. Not a live dogfood Feature.
|
|
7
|
+
repo:
|
|
8
|
+
name: loop-agent
|
|
9
|
+
path_ref: .
|
|
10
|
+
default_branch: main
|
|
11
|
+
type: backend-feature
|
|
12
|
+
priority: P2
|
|
13
|
+
risk_level: medium
|
|
14
|
+
depends_on:
|
|
15
|
+
- CONTRACT-001
|
|
16
|
+
source_docs:
|
|
17
|
+
requirement: ../requirement.md
|
|
18
|
+
acceptance: ../acceptance.yaml
|
|
19
|
+
design: ../design.md
|
|
20
|
+
acceptance_refs:
|
|
21
|
+
- AC-001
|
|
22
|
+
scope:
|
|
23
|
+
goals:
|
|
24
|
+
- 按契约实现后端
|
|
25
|
+
non_goals:
|
|
26
|
+
- 不扩展到模板外的 Task 节点(无 BE-TEST/FE-TEST/FINAL-VERIFY)
|
|
27
|
+
assumptions:
|
|
28
|
+
- verify.commands 由 scaffold 调用方显式提供
|
|
29
|
+
open_questions: []
|
|
30
|
+
constraints:
|
|
31
|
+
allowed_paths:
|
|
32
|
+
- services/sample-api/**
|
|
33
|
+
- docs/progress/F-2099-903/be/status.md
|
|
34
|
+
- docs/progress/F-2099-903/be/**
|
|
35
|
+
forbidden_paths:
|
|
36
|
+
- config/prod/**
|
|
37
|
+
- .env
|
|
38
|
+
- .env.*
|
|
39
|
+
- secrets/**
|
|
40
|
+
- apps/**
|
|
41
|
+
hard_constraints:
|
|
42
|
+
- 不读取生产密钥
|
|
43
|
+
- 不绕过 scaffold 冻结的 depends/produces/consumes
|
|
44
|
+
execution:
|
|
45
|
+
workflow: agent-dag
|
|
46
|
+
verify:
|
|
47
|
+
preset: standard
|
|
48
|
+
mode: serial
|
|
49
|
+
quota: full
|
|
50
|
+
commands:
|
|
51
|
+
- id: verify-1
|
|
52
|
+
label: npm run typecheck
|
|
53
|
+
command: npm run typecheck
|
|
54
|
+
required: true
|
|
55
|
+
timeout_ms: 300000
|
|
56
|
+
- id: verify-2
|
|
57
|
+
label: npm test
|
|
58
|
+
command: npm test
|
|
59
|
+
required: true
|
|
60
|
+
timeout_ms: 300000
|
|
61
|
+
worker:
|
|
62
|
+
execution_mode: generate-validate-run
|
|
63
|
+
max_attempts: 1
|
|
64
|
+
timeout_ms: 7200000
|
|
65
|
+
require_clean_worktree: true
|
|
66
|
+
require_human_review: true
|
|
67
|
+
create_worktree: false
|
|
68
|
+
loop_agent:
|
|
69
|
+
profile_policy: mapped
|
|
70
|
+
strict_models: true
|
|
71
|
+
strict_governance: true
|
|
72
|
+
max_concurrent: 1
|
|
73
|
+
outputs:
|
|
74
|
+
required:
|
|
75
|
+
- dag_json
|
|
76
|
+
- dag_validate_json
|
|
77
|
+
- run_record
|
|
78
|
+
- dag_report_json
|
|
79
|
+
- shell_verification
|
|
80
|
+
- closeout_or_failure_handoff
|
|
81
|
+
failure_policy:
|
|
82
|
+
failed_run_promote: false
|
|
83
|
+
generate_closeout_draft: true
|
|
84
|
+
create_followup_task: true
|