@tea-agent/loop-agent 0.1.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.
Files changed (264) hide show
  1. package/AGENTS.md +121 -0
  2. package/CHANGELOG.md +37 -0
  3. package/README.md +144 -0
  4. package/bin/loop-agent.js +21 -0
  5. package/dist/adapters/aimax.js +91 -0
  6. package/dist/adapters/context.js +32 -0
  7. package/dist/adapters/index.js +28 -0
  8. package/dist/adapters/loop-agent.js +98 -0
  9. package/dist/adapters/types.js +1 -0
  10. package/dist/cli/catalog.js +259 -0
  11. package/dist/cli/help.js +55 -0
  12. package/dist/cli/index.js +3 -0
  13. package/dist/cli/program.js +505 -0
  14. package/dist/cli.js +12 -0
  15. package/dist/commands/closeout.js +13 -0
  16. package/dist/commands/coverage-audit.js +14 -0
  17. package/dist/commands/cursor-prompt.js +222 -0
  18. package/dist/commands/cursor-worker.js +43 -0
  19. package/dist/commands/dag-approve.js +102 -0
  20. package/dist/commands/dag-final-verification.js +76 -0
  21. package/dist/commands/dag-init-hybrid.js +56 -0
  22. package/dist/commands/dag-reconcile-tasks.js +51 -0
  23. package/dist/commands/dag-reject.js +91 -0
  24. package/dist/commands/dag-report.js +177 -0
  25. package/dist/commands/dag-resume.js +34 -0
  26. package/dist/commands/dag-run-task.js +470 -0
  27. package/dist/commands/dag-validate.js +186 -0
  28. package/dist/commands/dag-workflow-compile.js +91 -0
  29. package/dist/commands/dag-workflow-plan.js +130 -0
  30. package/dist/commands/dag-workflow-validate.js +66 -0
  31. package/dist/commands/delegate.js +132 -0
  32. package/dist/commands/docs-archive.js +5 -0
  33. package/dist/commands/docs-audit.js +5 -0
  34. package/dist/commands/doctor.js +50 -0
  35. package/dist/commands/goal.js +92 -0
  36. package/dist/commands/handoff-check.js +5 -0
  37. package/dist/commands/harvest.js +44 -0
  38. package/dist/commands/inspect.js +11 -0
  39. package/dist/commands/instructions.js +195 -0
  40. package/dist/commands/knowledge.js +64 -0
  41. package/dist/commands/loop-benchmark.js +72 -0
  42. package/dist/commands/loop.js +241 -0
  43. package/dist/commands/new-task.js +5 -0
  44. package/dist/commands/pi-prompt.js +181 -0
  45. package/dist/commands/pi-reuse-benchmark.js +153 -0
  46. package/dist/commands/plan-list.js +5 -0
  47. package/dist/commands/promote-run.js +29 -0
  48. package/dist/commands/reference-index.js +16 -0
  49. package/dist/commands/run-dag.js +184 -0
  50. package/dist/commands/spine.js +38 -0
  51. package/dist/commands/stats.js +84 -0
  52. package/dist/commands/status.js +56 -0
  53. package/dist/commands/study-init.js +192 -0
  54. package/dist/commands/workflow.js +259 -0
  55. package/dist/commands/worktree-create.js +31 -0
  56. package/dist/commands/worktree-list.js +5 -0
  57. package/dist/commands/worktree-remove.js +26 -0
  58. package/dist/cursor-worker-entry.js +8 -0
  59. package/dist/executors/config-core.js +55 -0
  60. package/dist/executors/config.js +2 -0
  61. package/dist/executors/cursor-artifacts.js +33 -0
  62. package/dist/executors/cursor-execution-log.js +81 -0
  63. package/dist/executors/cursor-executor-artifacts.js +135 -0
  64. package/dist/executors/cursor-executor.js +468 -0
  65. package/dist/executors/cursor-run.js +115 -0
  66. package/dist/executors/cursor-tool.js +94 -0
  67. package/dist/executors/cursor-worker-client.js +213 -0
  68. package/dist/executors/cursor-worker-protocol.js +18 -0
  69. package/dist/executors/cursor-worker-server.js +54 -0
  70. package/dist/executors/cursor-worker.js +3 -0
  71. package/dist/executors/cursor.js +6 -0
  72. package/dist/executors/dag-cursor-executor.js +88 -0
  73. package/dist/executors/dag-pi-executor.js +322 -0
  74. package/dist/executors/dag-static-executor.js +45 -0
  75. package/dist/executors/dag.js +4 -0
  76. package/dist/executors/index.js +8 -0
  77. package/dist/executors/model-routing.js +60 -0
  78. package/dist/executors/pi-event-serializer.js +43 -0
  79. package/dist/executors/pi-executor.js +606 -0
  80. package/dist/executors/pi-reuse-benchmark.js +316 -0
  81. package/dist/executors/pi-runtime-reuse.js +29 -0
  82. package/dist/executors/pi-sdk-executor.js +255 -0
  83. package/dist/executors/pi-sdk.js +1 -0
  84. package/dist/executors/pi.js +3 -0
  85. package/dist/executors/shell-executor.js +300 -0
  86. package/dist/executors/shell-presets.js +47 -0
  87. package/dist/executors/shell-verification.js +251 -0
  88. package/dist/executors/shell-write-guard.js +126 -0
  89. package/dist/executors/shell.js +3 -0
  90. package/dist/executors/static.js +1 -0
  91. package/dist/governance/checks.js +434 -0
  92. package/dist/governance/harness.js +9 -0
  93. package/dist/governance/index.js +3 -0
  94. package/dist/governance/manifest-types.js +128 -0
  95. package/dist/governance/manifest.js +2 -0
  96. package/dist/governance/path-guard.js +69 -0
  97. package/dist/governance/path-guards.js +2 -0
  98. package/dist/governance/profiles.js +3 -0
  99. package/dist/governance/requirement-coverage.js +425 -0
  100. package/dist/governance/skill-safety.js +135 -0
  101. package/dist/governance/spine-audit.js +152 -0
  102. package/dist/records/closeout.js +2 -0
  103. package/dist/records/harvest.js +236 -0
  104. package/dist/records/index.js +3 -0
  105. package/dist/records/one-shot-runs.js +421 -0
  106. package/dist/records/promotion.js +199 -0
  107. package/dist/shared/artifacts-core.js +88 -0
  108. package/dist/shared/artifacts.js +2 -0
  109. package/dist/shared/context-files.js +32 -0
  110. package/dist/shared/context.js +2 -0
  111. package/dist/shared/copy-dir.js +17 -0
  112. package/dist/shared/git-progress.js +165 -0
  113. package/dist/shared/index.js +5 -0
  114. package/dist/shared/logger.js +23 -0
  115. package/dist/shared/one-shot-prompt-args.js +98 -0
  116. package/dist/shared/path-refs.js +31 -0
  117. package/dist/shared/prompts.js +26 -0
  118. package/dist/shared/reference-context.js +238 -0
  119. package/dist/shared/timeout-policy.js +19 -0
  120. package/dist/shared/timeout.js +1 -0
  121. package/dist/shared/types.js +5 -0
  122. package/dist/task/config-types.js +97 -0
  123. package/dist/task/config.js +2 -0
  124. package/dist/task/delegate.js +220 -0
  125. package/dist/task/goal-audit.js +51 -0
  126. package/dist/task/goal-policy.js +8 -0
  127. package/dist/task/goal.js +3 -0
  128. package/dist/task/ids.js +1 -0
  129. package/dist/task/index.js +9 -0
  130. package/dist/task/lifecycle.js +1 -0
  131. package/dist/task/paths.js +1 -0
  132. package/dist/task/read-model.js +149 -0
  133. package/dist/task/runtime.js +699 -0
  134. package/dist/task/source-state.js +1 -0
  135. package/dist/task/state.js +55 -0
  136. package/dist/task/subagent-guidance.js +1 -0
  137. package/dist/task/workflow-state-types.js +92 -0
  138. package/dist/task/worktree-cleanup.js +140 -0
  139. package/dist/task/worktree.js +171 -0
  140. package/dist/workflows/dag/authoring.js +8 -0
  141. package/dist/workflows/dag/authority-surface.js +138 -0
  142. package/dist/workflows/dag/canvas-observer.js +474 -0
  143. package/dist/workflows/dag/decision-envelope.js +502 -0
  144. package/dist/workflows/dag/decision-evidence.js +153 -0
  145. package/dist/workflows/dag/decision-gates.js +1 -0
  146. package/dist/workflows/dag/executor-registry.js +25 -0
  147. package/dist/workflows/dag/facts.js +4 -0
  148. package/dist/workflows/dag/failure-category.js +111 -0
  149. package/dist/workflows/dag/final-verification.js +180 -0
  150. package/dist/workflows/dag/governance-constants.js +5 -0
  151. package/dist/workflows/dag/governance-profile.js +405 -0
  152. package/dist/workflows/dag/index.js +6 -0
  153. package/dist/workflows/dag/init-hybrid.js +855 -0
  154. package/dist/workflows/dag/knowledge-curator.js +162 -0
  155. package/dist/workflows/dag/lifecycle.js +484 -0
  156. package/dist/workflows/dag/prompt-source.js +88 -0
  157. package/dist/workflows/dag/prompt.js +130 -0
  158. package/dist/workflows/dag/reconcile-tasks.js +404 -0
  159. package/dist/workflows/dag/recovery-recommendation.js +226 -0
  160. package/dist/workflows/dag/repair-artifact.js +136 -0
  161. package/dist/workflows/dag/report.js +1019 -0
  162. package/dist/workflows/dag/runner.js +1677 -0
  163. package/dist/workflows/dag/runtime.js +5 -0
  164. package/dist/workflows/dag/skill-instructions.js +471 -0
  165. package/dist/workflows/dag/skills.js +41 -0
  166. package/dist/workflows/dag/spec.js +3 -0
  167. package/dist/workflows/dag/topo.js +30 -0
  168. package/dist/workflows/dag/types.js +275 -0
  169. package/dist/workflows/dag/upstream-artifacts.js +95 -0
  170. package/dist/workflows/dag/validate.js +527 -0
  171. package/dist/workflows/dynamic/artifacts.js +65 -0
  172. package/dist/workflows/dynamic/compile.js +360 -0
  173. package/dist/workflows/dynamic/compileTypes.js +1 -0
  174. package/dist/workflows/dynamic/errors.js +5 -0
  175. package/dist/workflows/dynamic/index.js +7 -0
  176. package/dist/workflows/dynamic/profiles.js +156 -0
  177. package/dist/workflows/dynamic/spec.js +114 -0
  178. package/dist/workflows/dynamic/validate.js +275 -0
  179. package/dist/workflows/loop/actions.js +1334 -0
  180. package/dist/workflows/loop/benchmark.js +510 -0
  181. package/dist/workflows/loop/closeout.js +134 -0
  182. package/dist/workflows/loop/context.js +48 -0
  183. package/dist/workflows/loop/events.js +25 -0
  184. package/dist/workflows/loop/hash.js +32 -0
  185. package/dist/workflows/loop/index.js +8 -0
  186. package/dist/workflows/loop/paths.js +17 -0
  187. package/dist/workflows/loop/rounds.js +81 -0
  188. package/dist/workflows/loop/signals.js +55 -0
  189. package/dist/workflows/loop/state.js +116 -0
  190. package/dist/workflows/loop/templates.js +54 -0
  191. package/dist/workflows/loop/types.js +28 -0
  192. package/docs/README.md +62 -0
  193. package/docs/agent-dag-recovery-playbook.md +158 -0
  194. package/docs/agent-dag-runner.md +40 -0
  195. package/docs/cursor-executor-usage.md +25 -0
  196. package/docs/decisions/README.md +3 -0
  197. package/docs/design/README.md +36 -0
  198. package/docs/development-principles.md +71 -0
  199. package/docs/dynamic-workflow-dag-engine-roadmap.md +1749 -0
  200. package/docs/exec-plans/README.md +6 -0
  201. package/docs/exec-plans/active/README.md +5 -0
  202. package/docs/exec-plans/completed/README.md +5 -0
  203. package/docs/feature-workflow.md +184 -0
  204. package/docs/harness-methodology-debugging.md +153 -0
  205. package/docs/harness-methodology-tdd.md +130 -0
  206. package/docs/harness-methodology-verification.md +27 -0
  207. package/docs/loop-agent-harness.md +42 -0
  208. package/docs/progress/README.md +3 -0
  209. package/docs/reports/README.md +3 -0
  210. package/docs/templates/adr.md +60 -0
  211. package/docs/templates/agent-dag-authority-surface-audit.prompt.md +94 -0
  212. package/docs/templates/agent-dag-decision-envelope.schema.json +213 -0
  213. package/docs/templates/agent-dag-decision-gate-dogfood-report.md +117 -0
  214. package/docs/templates/agent-dag-decision-gate.prompt.md +246 -0
  215. package/docs/templates/agent-dag-process-supervisor.prompt.md +98 -0
  216. package/docs/templates/agent-dag-report.schema.json +423 -0
  217. package/docs/templates/agent-dag-review-verdict.prompt.md +68 -0
  218. package/docs/templates/agent-dag.base.json +195 -0
  219. package/docs/templates/agent-dag.final-verification.json +190 -0
  220. package/docs/templates/agent-dag.schema.json +316 -0
  221. package/docs/templates/agent-dag.supervised-implementation.json +500 -0
  222. package/docs/templates/exec-plan.md +64 -0
  223. package/docs/templates/feature-spec.md +53 -0
  224. package/docs/templates/hybrid-dag.json +193 -0
  225. package/docs/templates/progress-log.md +17 -0
  226. package/docs/templates/project-start-checklist.md +9 -0
  227. package/docs/templates/qa-report.md +42 -0
  228. package/docs/templates/sprint-contract.md +29 -0
  229. package/docs/verification-matrix.md +30 -0
  230. package/examples/decision-gate-agent-dag.json +123 -0
  231. package/examples/example-dag.json +51 -0
  232. package/examples/hybrid-loop-agent-dag.json +194 -0
  233. package/harness.json +92 -0
  234. package/package.json +61 -0
  235. package/skills/ai-engineering-context/SKILL.md +48 -0
  236. package/skills/loop-agent/SKILL.md +260 -0
  237. package/skills/loop-agent/references/README.md +63 -0
  238. package/skills/loop-agent/references/command-reference.md +315 -0
  239. package/skills/loop-agent/references/harness-policy.md +258 -0
  240. package/skills/loop-agent/references/hybrid-dag.md +216 -0
  241. package/skills/loop-agent/references/learned/README.md +21 -0
  242. package/skills/loop-agent/references/model-routing.md +36 -0
  243. package/skills/loop-agent/references/multi-worktree.md +54 -0
  244. package/skills/loop-agent/references/one-shot-runs.md +85 -0
  245. package/skills/loop-agent/references/orchestrator-and-interventions.md +169 -0
  246. package/skills/loop-agent/references/pi-prompt.md +23 -0
  247. package/skills/loop-agent/references/pi-subagent-assisted-mode.md +83 -0
  248. package/skills/loop-agent/references/post-implementation-and-patterns.md +44 -0
  249. package/skills/loop-agent/references/task-workflow.md +84 -0
  250. package/skills/loop-agent/references/verification-and-failure-handling.md +74 -0
  251. package/skills/requesting-code-review/SKILL.md +101 -0
  252. package/skills/requesting-code-review/code-reviewer.md +168 -0
  253. package/skills/systematic-debugging/CREATION-LOG.md +119 -0
  254. package/skills/systematic-debugging/SKILL.md +296 -0
  255. package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  256. package/skills/systematic-debugging/condition-based-waiting.md +115 -0
  257. package/skills/systematic-debugging/defense-in-depth.md +122 -0
  258. package/skills/systematic-debugging/find-polluter.sh +63 -0
  259. package/skills/systematic-debugging/root-cause-tracing.md +169 -0
  260. package/skills/systematic-debugging/test-academic.md +14 -0
  261. package/skills/systematic-debugging/test-pressure-1.md +58 -0
  262. package/skills/systematic-debugging/test-pressure-2.md +68 -0
  263. package/skills/systematic-debugging/test-pressure-3.md +69 -0
  264. package/skills/verification-before-completion/SKILL.md +154 -0
@@ -0,0 +1,111 @@
1
+ import { z } from "zod";
2
+ export const dagNormalizedFailureCategorySchema = z.enum([
3
+ "success",
4
+ "validation",
5
+ "executor",
6
+ "write-guard",
7
+ "timeout",
8
+ "auth",
9
+ "human-required",
10
+ "human-rejected",
11
+ "shell-command",
12
+ "static-error",
13
+ "decision-envelope",
14
+ "skipped",
15
+ "unknown",
16
+ ]);
17
+ export const DAG_NORMALIZED_FAILURE_CATEGORIES = dagNormalizedFailureCategorySchema.options;
18
+ const RAW_TO_NORMALIZED = {
19
+ success: "success",
20
+ "write-guard": "write-guard",
21
+ timeout: "timeout",
22
+ "missing-api-key": "auth",
23
+ auth: "auth",
24
+ "human-rejected": "human-rejected",
25
+ "human-required": "human-required",
26
+ "decision-envelope-invalid": "decision-envelope",
27
+ "nonzero-exit": "shell-command",
28
+ "spawn-error": "shell-command",
29
+ "static-error": "static-error",
30
+ "invalid-output": "validation",
31
+ "path-violation": "validation",
32
+ "empty-output": "validation",
33
+ "verify-failure": "validation",
34
+ "test-failure": "validation",
35
+ network: "executor",
36
+ quota: "executor",
37
+ "rate-limit": "executor",
38
+ unavailable: "executor",
39
+ unknown: "unknown",
40
+ };
41
+ function isFinishedStatus(status) {
42
+ return status === "FINISHED" || status === "finished";
43
+ }
44
+ function isInProgressStatus(status) {
45
+ return (status === "PENDING" ||
46
+ status === "RUNNING" ||
47
+ status === "pending" ||
48
+ status === "running");
49
+ }
50
+ function isFailureStatus(status) {
51
+ return (status === "ERROR" ||
52
+ status === "failed" ||
53
+ status === "partial_failed");
54
+ }
55
+ function mapRawCategory(raw) {
56
+ const direct = RAW_TO_NORMALIZED[raw];
57
+ if (direct)
58
+ return direct;
59
+ const lower = raw.toLowerCase();
60
+ if (lower.includes("timeout"))
61
+ return "timeout";
62
+ if (lower.includes("validation") || lower.includes("invalid"))
63
+ return "validation";
64
+ if (lower.includes("auth") || lower.includes("api-key"))
65
+ return "auth";
66
+ if (lower.includes("write-guard") || lower.includes("write_guard"))
67
+ return "write-guard";
68
+ if (lower.includes("decision-envelope") || lower.includes("decision_envelope"))
69
+ return "decision-envelope";
70
+ if (lower.includes("human-rejected"))
71
+ return "human-rejected";
72
+ if (lower.includes("human-required"))
73
+ return "human-required";
74
+ if (lower.includes("static-error"))
75
+ return "static-error";
76
+ if (lower.includes("nonzero-exit") ||
77
+ lower.includes("spawn-error") ||
78
+ lower.includes("shell"))
79
+ return "shell-command";
80
+ return undefined;
81
+ }
82
+ export function isDagFailureCategory(value) {
83
+ return DAG_NORMALIZED_FAILURE_CATEGORIES.includes(value);
84
+ }
85
+ export function normalizeDagFailureCategory(raw, status) {
86
+ if (status === "SKIPPED") {
87
+ return "skipped";
88
+ }
89
+ if (raw !== undefined) {
90
+ const mapped = mapRawCategory(raw);
91
+ if (mapped) {
92
+ if (mapped === "success") {
93
+ return isFinishedStatus(status) ? "success" : "unknown";
94
+ }
95
+ return mapped;
96
+ }
97
+ }
98
+ if (raw === undefined && isFinishedStatus(status)) {
99
+ return "success";
100
+ }
101
+ if (isInProgressStatus(status)) {
102
+ return "unknown";
103
+ }
104
+ if (isFailureStatus(status)) {
105
+ return "unknown";
106
+ }
107
+ if (raw === "success" && isFinishedStatus(status)) {
108
+ return "success";
109
+ }
110
+ return "unknown";
111
+ }
@@ -0,0 +1,180 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { DEFAULT_DAG_EXECUTOR_MODELS } from './types.js';
5
+ import { parseDagSpec } from './types.js';
6
+ import { loadHarnessManifest } from '../../governance/harness.js';
7
+ import { loadTaskConfig } from '../../task/runtime.js';
8
+ import { resolveCliPath } from '../../shared/path-refs.js';
9
+ const DEFAULT_OUTPUT_DIR = os.tmpdir();
10
+ export function defaultFinalVerificationDagOutputPath(taskId) {
11
+ return path.join(DEFAULT_OUTPUT_DIR, `${taskId}-final-verification-dag.json`);
12
+ }
13
+ export async function initFinalVerificationDagFromTask(repoRoot, taskId, options = {}) {
14
+ const spec = await buildFinalVerificationDagFromTask(repoRoot, taskId, options);
15
+ const outputPath = resolveCliPath(options.outputPath ?? defaultFinalVerificationDagOutputPath(taskId));
16
+ await writeFile(outputPath, `${JSON.stringify(spec, null, 2)}\n`, 'utf-8');
17
+ return {
18
+ taskId,
19
+ outputPath,
20
+ nodeIds: spec.tasks.map((task) => task.id),
21
+ taskCount: spec.tasks.length,
22
+ };
23
+ }
24
+ export async function buildFinalVerificationDagFromTask(repoRoot, taskId, options = {}) {
25
+ const [taskConfig, manifest] = await Promise.all([
26
+ loadTaskConfig(repoRoot, taskId),
27
+ loadHarnessManifest(repoRoot),
28
+ ]);
29
+ const taskGlob = options.taskGlob ?? taskId;
30
+ const closeoutPath = options.closeoutPath ?? path.join(os.tmpdir(), `${taskId}-closeout-report.md`);
31
+ const checkRepo = manifest.scripts.checkRepo ?? 'scripts/check-repo.sh';
32
+ const finalVerifyCommands = [`HARNESS_ALLOW_ACTIVE_DAG_RUNS=1 bash ${checkRepo}`];
33
+ const hasChangesetSignal = taskDeclaresReleaseImpact(taskConfig);
34
+ const tasks = [
35
+ shellTask({
36
+ id: 'task-state-reconcile-shell',
37
+ depends_on: [],
38
+ outputContract: 'Markdown task state/artifact/DAG/verification drift report.',
39
+ commands: [
40
+ `npm run dev -- dag reconcile-tasks --glob ${JSON.stringify(taskGlob)} --markdown`,
41
+ ],
42
+ }),
43
+ shellTask({
44
+ id: 'requirement-coverage-shell',
45
+ depends_on: [],
46
+ outputContract: 'Markdown requirement coverage audit for the closeout task.',
47
+ commands: [
48
+ `npm run dev -- handoff coverage ${JSON.stringify(taskId)} --markdown`,
49
+ ],
50
+ }),
51
+ shellTask({
52
+ id: 'static-invariant-shell',
53
+ depends_on: [],
54
+ outputContract: 'Task-scoped static invariant scan derived only from task source/config constraints.',
55
+ commands: [
56
+ [
57
+ 'node',
58
+ '-e',
59
+ JSON.stringify([
60
+ "const fs=require('fs');",
61
+ `const task=${JSON.stringify(taskId)};`,
62
+ "const cfg=JSON.parse(fs.readFileSync(`.harness/tasks/${task}/task.json`,'utf8'));",
63
+ "const forbidden=cfg.forbiddenPaths||[];",
64
+ "const hard=cfg.hardConstraints||[];",
65
+ "console.log(`# Static invariant scan for ${task}`);",
66
+ "console.log(`forbiddenPaths=${forbidden.length}`);",
67
+ "console.log(`hardConstraints=${hard.length}`);",
68
+ "if (forbidden.some((entry)=>String(entry).includes('harness.json'))) console.log('invariant: harness.json remains forbidden by task source');",
69
+ "console.log('No global shellPolicy or host wrapper policy was introduced by this scan.');",
70
+ ].join('')),
71
+ ].join(' '),
72
+ ],
73
+ }),
74
+ shellTask({
75
+ id: 'changeset-impact-shell',
76
+ depends_on: [],
77
+ outputContract: 'Changeset impact audit, or explicit skip reason when the repo/task has no release signal.',
78
+ commands: [
79
+ hasChangesetSignal
80
+ ? 'test -d .changeset || test -f .changeset/config.json || { echo "changeset impact declared by task but no .changeset metadata found"; exit 1; }; echo "changeset impact metadata present"'
81
+ : 'if test -d .changeset || test -f .changeset/config.json; then echo "changeset metadata present; review release notes before final verify"; else echo "SKIP: no changesets directory/config and task declares no release impact"; fi',
82
+ ],
83
+ }),
84
+ shellTask({
85
+ id: 'closeout-artifact-shell',
86
+ depends_on: [
87
+ 'task-state-reconcile-shell',
88
+ 'requirement-coverage-shell',
89
+ 'static-invariant-shell',
90
+ 'changeset-impact-shell',
91
+ ],
92
+ writePolicy: 'none',
93
+ outputContract: 'Writes a derived closeout artifact outside completed run facts, before final verification.',
94
+ commands: [
95
+ `mkdir -p ${JSON.stringify(path.dirname(closeoutPath))}`,
96
+ `printf '%s\\n' '# Final Verification Closeout' '' 'task: ${taskId}' 'generated before final verification; do not treat as verify evidence' > ${JSON.stringify(closeoutPath)}`,
97
+ `test -s ${JSON.stringify(closeoutPath)}`,
98
+ ],
99
+ }),
100
+ shellTask({
101
+ id: 'final-verify-shell',
102
+ depends_on: ['closeout-artifact-shell'],
103
+ outputContract: 'Final verification evidence captured after closeout artifact exists.',
104
+ commands: finalVerifyCommands,
105
+ }),
106
+ {
107
+ id: 'closeout-summary-pi',
108
+ depends_on: ['final-verify-shell'],
109
+ executor: 'pi',
110
+ role: 'closeout',
111
+ complexity: 'LOW',
112
+ writePolicy: 'read-only',
113
+ allowedPaths: [],
114
+ forbiddenPaths: ['.harness/**', '.harness/dag-runs/**', 'artifacts/**'],
115
+ outputContract: 'Plain Markdown summary of reconcile, coverage, invariant, changeset, closeout artifact, and final verification results. No file writes.',
116
+ subtask_prompt: [
117
+ `Summarize final verification DAG results for task ${taskId}.`,
118
+ `The closeout artifact path is ${closeoutPath}.`,
119
+ 'Do not write files. Do not claim final verification passed unless final-verify-shell succeeded.',
120
+ ].join('\n'),
121
+ },
122
+ ];
123
+ return parseDagSpec({
124
+ version: 2,
125
+ title: `Final Verification DAG: ${taskConfig.title || taskId}`,
126
+ objective: `Run deterministic closeout gates for ${taskId} with final verification after closeout artifact creation.`,
127
+ successCriteria: [
128
+ 'task-state-reconcile-shell runs before closeout artifact creation',
129
+ 'requirement-coverage-shell audits source requirements',
130
+ 'static-invariant-shell uses task-scoped constraints only',
131
+ 'changeset-impact-shell skips with an explicit reason when no changesets/release impact exists',
132
+ 'closeout-artifact-shell runs before final-verify-shell',
133
+ 'final-verify-shell uses repo manifest verification commands without host-specific wrappers',
134
+ ],
135
+ globalConstraints: [
136
+ 'Do not implement Project Policy Gate',
137
+ 'Do not add rtk or host-specific shell wrappers as loop-agent built-ins',
138
+ 'Do not mutate .harness/dag-runs/completed facts',
139
+ 'Final verification must run after closeout artifact creation',
140
+ ],
141
+ defaults: {
142
+ executor: 'shell',
143
+ contextProfile: 'slim',
144
+ writePolicy: 'read-only',
145
+ skills: ['ai-engineering-context'],
146
+ },
147
+ executorModels: DEFAULT_DAG_EXECUTOR_MODELS,
148
+ skillsByRole: {
149
+ verifier: ['verification-before-completion'],
150
+ closeout: ['loop-agent', 'verification-before-completion'],
151
+ },
152
+ tasks,
153
+ });
154
+ }
155
+ function shellTask(input) {
156
+ return {
157
+ id: input.id,
158
+ depends_on: input.depends_on,
159
+ executor: 'shell',
160
+ role: 'verifier',
161
+ complexity: 'LOW',
162
+ writePolicy: input.writePolicy ?? 'read-only',
163
+ allowedPaths: [],
164
+ forbiddenPaths: ['.harness/dag-runs/completed/**', 'artifacts/**'],
165
+ shell: {
166
+ commands: input.commands,
167
+ timeoutMs: 600_000,
168
+ },
169
+ outputContract: input.outputContract,
170
+ subtask_prompt: input.outputContract,
171
+ };
172
+ }
173
+ function taskDeclaresReleaseImpact(taskConfig) {
174
+ const haystack = [
175
+ taskConfig.notes ?? '',
176
+ ...(taskConfig.hardConstraints ?? []),
177
+ ...(taskConfig.sourceFiles ?? []),
178
+ ].join('\n');
179
+ return /changeset|release|publish|version/i.test(haystack);
180
+ }
@@ -0,0 +1,5 @@
1
+ export const BASELINE_FORBIDDEN_PATHS = [
2
+ ".harness/**",
3
+ ".harness/dag-runs/**",
4
+ "artifacts/**",
5
+ ];