coding-agent-harness 1.0.5 → 1.0.6

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 (260) hide show
  1. package/CONTRIBUTING.md +2 -2
  2. package/README.md +63 -3
  3. package/README.zh-CN.md +52 -3
  4. package/SKILL.md +43 -43
  5. package/dist/build-dist.mjs +189 -0
  6. package/dist/check-dist-observation.mjs +428 -0
  7. package/dist/check-harness.mjs +489 -0
  8. package/dist/check-import-graph.mjs +511 -0
  9. package/dist/check-runtime-emit.mjs +304 -0
  10. package/dist/check-type-boundaries.mjs +139 -0
  11. package/dist/commands/dashboard-command.mjs +80 -0
  12. package/dist/commands/migration-command.mjs +152 -0
  13. package/dist/commands/preset-command.mjs +91 -0
  14. package/dist/commands/task-command.mjs +324 -0
  15. package/dist/harness.mjs +304 -0
  16. package/dist/lib/capability-registry.mjs +643 -0
  17. package/dist/lib/check-module-parallel.mjs +227 -0
  18. package/dist/lib/check-profiles.mjs +414 -0
  19. package/dist/lib/check-task-contracts.mjs +54 -0
  20. package/dist/lib/core-shared.mjs +254 -0
  21. package/dist/lib/dashboard-data.mjs +608 -0
  22. package/dist/lib/dashboard-workbench.mjs +334 -0
  23. package/dist/lib/dashboard-writer.mjs +200 -0
  24. package/dist/lib/git-status-summary.mjs +45 -0
  25. package/dist/lib/governance-index-generator.mjs +236 -0
  26. package/dist/lib/governance-sync.mjs +617 -0
  27. package/dist/lib/governance-table-boundary.mjs +161 -0
  28. package/{scripts → dist}/lib/harness-core.mjs +2 -0
  29. package/dist/lib/harness-paths.mjs +338 -0
  30. package/dist/lib/lesson-maintenance.mjs +139 -0
  31. package/dist/lib/markdown-utils.mjs +193 -0
  32. package/dist/lib/migration-planner.mjs +439 -0
  33. package/dist/lib/migration-support.mjs +317 -0
  34. package/dist/lib/phase-kind.mjs +46 -0
  35. package/dist/lib/preset-audit-contracts.mjs +40 -0
  36. package/dist/lib/preset-engine.mjs +516 -0
  37. package/dist/lib/preset-registry.mjs +831 -0
  38. package/dist/lib/preset-resource-contracts.mjs +83 -0
  39. package/dist/lib/review-confirm-git-gate.mjs +244 -0
  40. package/dist/lib/status-builder.mjs +87 -0
  41. package/{scripts → dist}/lib/status-dashboard-renderer.mjs +44 -46
  42. package/dist/lib/structure-migration.mjs +404 -0
  43. package/dist/lib/subagent-authorization-audit.mjs +198 -0
  44. package/dist/lib/task-audit-metadata.mjs +376 -0
  45. package/dist/lib/task-audit-migration.mjs +355 -0
  46. package/dist/lib/task-completion-consistency.mjs +29 -0
  47. package/dist/lib/task-index.mjs +133 -0
  48. package/dist/lib/task-lesson-candidates.mjs +239 -0
  49. package/dist/lib/task-lesson-sedimentation.mjs +300 -0
  50. package/dist/lib/task-lifecycle/create-task-helpers.mjs +84 -0
  51. package/dist/lib/task-lifecycle/phase-sync.mjs +82 -0
  52. package/dist/lib/task-lifecycle/review-confirm.mjs +93 -0
  53. package/dist/lib/task-lifecycle/review-gates.mjs +62 -0
  54. package/dist/lib/task-lifecycle/review-submission.mjs +52 -0
  55. package/dist/lib/task-lifecycle/scaffold-provenance.mjs +54 -0
  56. package/dist/lib/task-lifecycle/template-files.mjs +52 -0
  57. package/dist/lib/task-lifecycle/text-utils.mjs +26 -0
  58. package/dist/lib/task-lifecycle.mjs +611 -0
  59. package/dist/lib/task-metadata.mjs +116 -0
  60. package/dist/lib/task-review-model.mjs +474 -0
  61. package/dist/lib/task-scanner.mjs +439 -0
  62. package/dist/lib/task-tombstone-commands.mjs +125 -0
  63. package/dist/postinstall.mjs +14 -0
  64. package/dist/run-built-tests.mjs +84 -0
  65. package/docs-release/README.md +1 -0
  66. package/docs-release/architecture/overview.md +12 -12
  67. package/docs-release/architecture/overview.zh-CN.md +12 -12
  68. package/docs-release/architecture/system-explainer/01-system-overview.md +15 -14
  69. package/docs-release/architecture/system-explainer/02-module-dependency.md +8 -8
  70. package/docs-release/architecture/system-explainer/03-task-lifecycle.md +3 -3
  71. package/docs-release/architecture/system-explainer/04-check-and-governance.md +9 -7
  72. package/docs-release/architecture/system-explainer/05-data-flow.md +5 -5
  73. package/docs-release/architecture/system-explainer/06-preset-and-migration.md +1 -4
  74. package/docs-release/architecture/system-explainer/en-US/01-system-overview.md +15 -14
  75. package/docs-release/architecture/system-explainer/en-US/02-module-dependency.md +8 -8
  76. package/docs-release/architecture/system-explainer/en-US/03-task-lifecycle.md +3 -3
  77. package/docs-release/architecture/system-explainer/en-US/04-check-and-governance.md +10 -8
  78. package/docs-release/architecture/system-explainer/en-US/05-data-flow.md +5 -5
  79. package/docs-release/architecture/system-explainer/en-US/06-preset-and-migration.md +1 -4
  80. package/docs-release/guides/agent-installation.en-US.md +14 -8
  81. package/docs-release/guides/agent-installation.md +14 -8
  82. package/docs-release/guides/contributing.md +3 -3
  83. package/docs-release/guides/contributing.zh-CN.md +3 -3
  84. package/docs-release/guides/document-audience-and-surfaces.en-US.md +10 -10
  85. package/docs-release/guides/document-audience-and-surfaces.md +10 -10
  86. package/docs-release/guides/legacy-migration-agent-prompt.md +25 -2
  87. package/docs-release/guides/legacy-migration-agent-prompt.zh-CN.md +25 -2
  88. package/docs-release/guides/migration-playbook.en-US.md +63 -1
  89. package/docs-release/guides/migration-playbook.md +59 -1
  90. package/docs-release/guides/parent-control-repository-pattern.en-US.md +25 -25
  91. package/docs-release/guides/parent-control-repository-pattern.md +25 -25
  92. package/docs-release/guides/preset-development.md +2 -2
  93. package/docs-release/guides/repository-operating-models.en-US.md +21 -21
  94. package/docs-release/guides/repository-operating-models.md +21 -21
  95. package/docs-release/guides/task-state-machine.en-US.md +5 -5
  96. package/docs-release/guides/task-state-machine.md +5 -5
  97. package/docs-release/guides/typescript-runtime-migration-closeout.md +96 -0
  98. package/examples/minimal-project/AGENTS.md +2 -2
  99. package/examples/minimal-project/coding-agent-harness/harness.yaml +14 -0
  100. package/examples/minimal-project/coding-agent-harness/planning/tasks/demo-task/progress.md +11 -0
  101. package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/review.md +1 -1
  102. package/package.json +20 -12
  103. package/presets/legacy-migration/preset.yaml +5 -5
  104. package/presets/legacy-migration/templates/execution_strategy.append.md +1 -1
  105. package/presets/lesson-sedimentation/preset.yaml +3 -3
  106. package/presets/module/preset.yaml +2 -2
  107. package/presets/module/templates/execution_strategy.append.md +1 -1
  108. package/presets/module/templates/task_plan.append.md +3 -3
  109. package/presets/standard-task/preset.yaml +2 -2
  110. package/references/adversarial-review-standard.md +2 -2
  111. package/references/agents-md-pattern.md +14 -14
  112. package/references/cadence-ledger.md +1 -1
  113. package/references/ci-cd-standard.md +1 -1
  114. package/references/delivery-operating-model-standard.md +4 -4
  115. package/references/docs-directory-standard.md +65 -159
  116. package/references/external-source-intake-standard.md +10 -10
  117. package/references/harness-ledger.md +5 -5
  118. package/references/legacy-12-phase-bootstrap.md +2 -2
  119. package/references/lessons-governance.md +15 -15
  120. package/references/long-running-task-standard.md +6 -6
  121. package/references/module-parallel-standard.md +34 -34
  122. package/references/planning-loop.md +6 -6
  123. package/references/project-onboarding-audit.md +4 -4
  124. package/references/regression-system.md +2 -2
  125. package/references/repo-governance-standard.md +4 -4
  126. package/references/review-routing-standard.md +1 -1
  127. package/references/ssot-governance.md +19 -19
  128. package/references/taskr-gap-analysis.md +5 -5
  129. package/references/walkthrough-closeout.md +14 -14
  130. package/references/worktree-parallel.md +3 -3
  131. package/skills/preset-creator/references/complex-task-skeleton/task_plan.md +1 -1
  132. package/skills/preset-creator/references/preset-package-skeleton.md +5 -5
  133. package/templates/AGENTS.md.template +26 -26
  134. package/templates/architecture/README.md +4 -4
  135. package/templates/architecture/service-catalog.md +2 -2
  136. package/templates/architecture/services/service-template.md +1 -1
  137. package/templates/dashboard/assets/app-src/20-overview.js +11 -5
  138. package/templates/dashboard/assets/app-src/40-modules.js +1 -1
  139. package/templates/dashboard/assets/app.js +12 -6
  140. package/templates/dashboard/assets/i18n.js +4 -2
  141. package/templates/development/README.md +10 -10
  142. package/templates/development/cross-repo-debugging.md +3 -3
  143. package/templates/development/external-context/service-template.md +2 -2
  144. package/templates/development/external-source-packs/README.md +4 -4
  145. package/templates/integrations/README.md +4 -4
  146. package/templates/integrations/api-contract.md +2 -2
  147. package/templates/integrations/event-contract.md +2 -2
  148. package/templates/integrations/third-party/vendor-template.md +2 -2
  149. package/templates/integrations/webhook-contract.md +2 -2
  150. package/templates/ledger/Harness-Ledger.md +1 -1
  151. package/templates/planning/INDEX.md +1 -0
  152. package/templates/planning/module_session_prompt.md +1 -1
  153. package/templates/planning/task_plan.md +1 -1
  154. package/templates/planning/walkthrough.md +47 -0
  155. package/templates/reference/docs-library-standard.md +8 -8
  156. package/templates/reference/external-source-intake-standard.md +15 -15
  157. package/templates/reference/repo-governance-standard.md +1 -1
  158. package/templates/ssot/Module-Registry.md +1 -1
  159. package/templates/walkthrough/walkthrough-template.md +2 -2
  160. package/templates-zh-CN/AGENTS.md.template +26 -26
  161. package/templates-zh-CN/CLAUDE.md.template +1 -1
  162. package/templates-zh-CN/architecture/README.md +4 -4
  163. package/templates-zh-CN/architecture/service-catalog.md +2 -2
  164. package/templates-zh-CN/architecture/services/service-template.md +1 -1
  165. package/templates-zh-CN/development/README.md +10 -10
  166. package/templates-zh-CN/development/cross-repo-debugging.md +3 -3
  167. package/templates-zh-CN/development/external-context/service-template.md +2 -2
  168. package/templates-zh-CN/development/external-source-packs/README.md +4 -4
  169. package/templates-zh-CN/integrations/README.md +4 -4
  170. package/templates-zh-CN/integrations/api-contract.md +2 -2
  171. package/templates-zh-CN/integrations/event-contract.md +2 -2
  172. package/templates-zh-CN/integrations/third-party/vendor-template.md +2 -2
  173. package/templates-zh-CN/integrations/webhook-contract.md +2 -2
  174. package/templates-zh-CN/ledger/Harness-Ledger.md +1 -1
  175. package/templates-zh-CN/lessons/lesson-arch-process-change.md +1 -1
  176. package/templates-zh-CN/lessons/lesson-new-doc.md +3 -3
  177. package/templates-zh-CN/lessons/lesson-ref-change.md +4 -4
  178. package/templates-zh-CN/planning/module_session_prompt.md +11 -11
  179. package/templates-zh-CN/planning/walkthrough.md +47 -0
  180. package/templates-zh-CN/reference/adversarial-review-standard.md +2 -2
  181. package/templates-zh-CN/reference/delivery-operating-model-standard.md +3 -3
  182. package/templates-zh-CN/reference/docs-library-standard.md +28 -28
  183. package/templates-zh-CN/reference/execution-workflow-standard.md +1 -1
  184. package/templates-zh-CN/reference/external-source-intake-standard.md +16 -16
  185. package/templates-zh-CN/reference/harness-ledger-standard.md +6 -6
  186. package/templates-zh-CN/reference/regression-ssot-governance.md +2 -2
  187. package/templates-zh-CN/reference/repo-governance-standard.md +1 -1
  188. package/templates-zh-CN/reference/review-routing-standard.md +1 -1
  189. package/templates-zh-CN/reference/walkthrough-standard.md +7 -7
  190. package/templates-zh-CN/reference/worktree-standard.md +1 -1
  191. package/templates-zh-CN/regression/Cadence-Ledger.md +2 -2
  192. package/templates-zh-CN/ssot/Delivery-SSoT.md +3 -3
  193. package/templates-zh-CN/ssot/Module-Registry.md +3 -3
  194. package/templates-zh-CN/ssot/Regression-SSoT.md +2 -2
  195. package/templates-zh-CN/walkthrough/walkthrough-template.md +5 -5
  196. package/tsconfig.dist.json +16 -0
  197. package/tsconfig.json +25 -0
  198. package/tsconfig.runtime.json +24 -0
  199. package/examples/minimal-project/.harness-capabilities.json +0 -8
  200. package/examples/minimal-project/docs/09-PLANNING/TASKS/demo-task/progress.md +0 -11
  201. package/scripts/check-harness.mjs +0 -508
  202. package/scripts/commands/dashboard-command.mjs +0 -67
  203. package/scripts/commands/migration-command.mjs +0 -126
  204. package/scripts/commands/preset-command.mjs +0 -73
  205. package/scripts/commands/task-command.mjs +0 -328
  206. package/scripts/harness.mjs +0 -291
  207. package/scripts/lib/capability-registry.mjs +0 -587
  208. package/scripts/lib/check-module-parallel.mjs +0 -230
  209. package/scripts/lib/check-profiles.mjs +0 -372
  210. package/scripts/lib/check-task-contracts.mjs +0 -55
  211. package/scripts/lib/core-shared.mjs +0 -249
  212. package/scripts/lib/dashboard-data.mjs +0 -520
  213. package/scripts/lib/dashboard-workbench.mjs +0 -336
  214. package/scripts/lib/dashboard-writer.mjs +0 -202
  215. package/scripts/lib/git-status-summary.mjs +0 -46
  216. package/scripts/lib/governance-index-generator.mjs +0 -174
  217. package/scripts/lib/governance-sync.mjs +0 -611
  218. package/scripts/lib/governance-table-boundary.mjs +0 -175
  219. package/scripts/lib/lesson-maintenance.mjs +0 -152
  220. package/scripts/lib/markdown-utils.mjs +0 -191
  221. package/scripts/lib/migration-planner.mjs +0 -476
  222. package/scripts/lib/migration-support.mjs +0 -312
  223. package/scripts/lib/phase-kind.mjs +0 -50
  224. package/scripts/lib/preset-audit-contracts.mjs +0 -37
  225. package/scripts/lib/preset-engine.mjs +0 -494
  226. package/scripts/lib/preset-registry.mjs +0 -776
  227. package/scripts/lib/preset-resource-contracts.mjs +0 -83
  228. package/scripts/lib/review-confirm-git-gate.mjs +0 -248
  229. package/scripts/lib/status-builder.mjs +0 -88
  230. package/scripts/lib/subagent-authorization-audit.mjs +0 -196
  231. package/scripts/lib/task-audit-metadata.mjs +0 -385
  232. package/scripts/lib/task-audit-migration.mjs +0 -350
  233. package/scripts/lib/task-completion-consistency.mjs +0 -26
  234. package/scripts/lib/task-index.mjs +0 -93
  235. package/scripts/lib/task-lesson-candidates.mjs +0 -242
  236. package/scripts/lib/task-lesson-sedimentation.mjs +0 -326
  237. package/scripts/lib/task-lifecycle/create-task-helpers.mjs +0 -67
  238. package/scripts/lib/task-lifecycle/phase-sync.mjs +0 -88
  239. package/scripts/lib/task-lifecycle/review-confirm.mjs +0 -112
  240. package/scripts/lib/task-lifecycle/review-gates.mjs +0 -73
  241. package/scripts/lib/task-lifecycle/review-submission.mjs +0 -63
  242. package/scripts/lib/task-lifecycle/scaffold-provenance.mjs +0 -49
  243. package/scripts/lib/task-lifecycle/template-files.mjs +0 -53
  244. package/scripts/lib/task-lifecycle/text-utils.mjs +0 -24
  245. package/scripts/lib/task-lifecycle.mjs +0 -616
  246. package/scripts/lib/task-metadata.mjs +0 -118
  247. package/scripts/lib/task-review-model.mjs +0 -455
  248. package/scripts/lib/task-scanner.mjs +0 -503
  249. package/scripts/lib/task-tombstone-commands.mjs +0 -140
  250. package/scripts/postinstall.mjs +0 -14
  251. package/templates/walkthrough/Closeout-SSoT.md +0 -43
  252. package/templates-zh-CN/walkthrough/Closeout-SSoT.md +0 -42
  253. /package/examples/minimal-project/{docs → coding-agent-harness/governance/generated}/Harness-Ledger.md +0 -0
  254. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/INDEX.md +0 -0
  255. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/brief.md +0 -0
  256. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/execution_strategy.md +0 -0
  257. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/findings.md +0 -0
  258. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/lesson_candidates.md +0 -0
  259. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/task_plan.md +0 -0
  260. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/visual_map.md +0 -0
@@ -0,0 +1,516 @@
1
+ // @ts-nocheck
2
+ // Preset task rendering stays behavior-first until preset/session domain types are modeled.
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import crypto from "node:crypto";
6
+ import { spawnSync } from "node:child_process";
7
+ import { readJsonSafe, repoRoot, taskContractMarker, toPosix, visualMapFile } from "./core-shared.mjs";
8
+ import { verifyMigrationSession } from "./migration-planner.mjs";
9
+ import { buildPresetAudit, renderPresetTemplate } from "./preset-registry.mjs";
10
+ import { legacyPath, legacyPlanningRoot, legacyTaskRoot, v2HarnessRoot, } from "./harness-paths.mjs";
11
+ export function resolvePresetInputs(preset, { cliArgs = [], fromSession = "", targetInput = "" } = {}) {
12
+ const inputs = {};
13
+ let targetFromInput = "";
14
+ for (const [name, declaration] of Object.entries(preset.inputs || {})) {
15
+ const rawValue = inputValue(declaration, { cliArgs, fromSession });
16
+ if ((rawValue == null || rawValue === "") && declaration.required) {
17
+ throw new Error(`Missing required preset input ${declaration.flag || name}`);
18
+ }
19
+ if (declaration.type === "flag") {
20
+ inputs[name] = rawValue === true;
21
+ continue;
22
+ }
23
+ if (declaration.type === "json-file") {
24
+ if (rawValue == null || rawValue === "") {
25
+ inputs[name] = null;
26
+ continue;
27
+ }
28
+ const filePath = path.resolve(String(rawValue));
29
+ if (!fs.existsSync(filePath))
30
+ throw new Error(`Preset input file not found for ${declaration.flag || name}: ${rawValue}`);
31
+ let readError = null;
32
+ const value = readJsonSafe(filePath, null, { onError: (error) => { readError = error; } });
33
+ if (value === null)
34
+ throw new Error(`Invalid preset JSON input ${declaration.flag || name}: ${readError?.message || "unknown parse error"}`);
35
+ if (declaration.validateOperation && value.operation !== declaration.validateOperation) {
36
+ throw new Error(`${preset.id} preset requires ${declaration.flag || name} operation ${declaration.validateOperation}`);
37
+ }
38
+ if (declaration.rejectPlanOnly && value.planOnly)
39
+ throw new Error(`${preset.id} preset cannot use plan-only session evidence`);
40
+ if (declaration.requireTarget && (!value.target || !fs.existsSync(value.target)))
41
+ throw new Error(`Preset input target missing: ${value.target || "(none)"}`);
42
+ if (declaration.targetFromSession)
43
+ targetFromInput = value.target || targetFromInput;
44
+ inputs[name] = { ...value, sourcePath: filePath };
45
+ continue;
46
+ }
47
+ inputs[name] = rawValue == null || rawValue === "" ? declaration.default || "" : String(rawValue);
48
+ }
49
+ return {
50
+ inputs,
51
+ targetInput: targetFromInput || targetInput,
52
+ };
53
+ }
54
+ export function evaluateTemplateValues(preset, resolvedInputs, { taskId = "", taskTitle = "", moduleKey = "" } = {}) {
55
+ const computed = computedValues(preset, resolvedInputs);
56
+ const base = {
57
+ inputs: resolvedInputs,
58
+ computed,
59
+ preset: {
60
+ id: preset.id,
61
+ version: String(preset.version),
62
+ source: preset.source,
63
+ },
64
+ task: {
65
+ id: taskId,
66
+ title: taskTitle,
67
+ moduleKey,
68
+ kind: preset.task?.kind || "general",
69
+ },
70
+ };
71
+ const values = {
72
+ preset: preset.id,
73
+ presetVersion: String(preset.version),
74
+ kind: preset.task?.kind || "general",
75
+ ...computed,
76
+ };
77
+ for (const [name, declaration] of Object.entries(preset.templateValues || {})) {
78
+ if (Object.prototype.hasOwnProperty.call(declaration, "from")) {
79
+ values[name] = getPath(base, declaration.from);
80
+ }
81
+ else if (Object.prototype.hasOwnProperty.call(declaration, "value")) {
82
+ values[name] = declaration.value;
83
+ }
84
+ else if (Object.prototype.hasOwnProperty.call(declaration, "default")) {
85
+ values[name] = declaration.default;
86
+ }
87
+ }
88
+ return values;
89
+ }
90
+ export function buildPresetContext(preset, { target, taskDir, taskId, taskTitle, resolvedInputs, evaluatedValues }) {
91
+ const taskRelativeDir = toPosix(path.relative(target.projectRoot, taskDir));
92
+ const evidenceBundle = presetEvidenceBundle(preset, { target, taskDir, evaluatedValues });
93
+ const audit = buildPresetAudit(preset, {
94
+ taskId,
95
+ targetRoot: target.projectRoot,
96
+ entrypoint: "newTask",
97
+ });
98
+ const context = {
99
+ kind: evaluatedValues.kind || preset.task?.kind || "general",
100
+ preset: preset.id,
101
+ presetVersion: String(preset.version),
102
+ presetPackage: preset,
103
+ audit,
104
+ resolvedInputs,
105
+ taskId,
106
+ taskTitle,
107
+ taskRelativeDir,
108
+ values: {
109
+ ...evaluatedValues,
110
+ evidenceBundle,
111
+ },
112
+ migrationTargetLevel: evaluatedValues.migrationTargetLevel || "",
113
+ migrationAchievedLevel: evaluatedValues.migrationAchievedLevel || "",
114
+ evidenceBundle,
115
+ };
116
+ context.evidenceFiles = generateEvidenceFiles(preset, { target, taskDir, context });
117
+ const resources = generateResourceFiles(preset, { context });
118
+ context.resourceFiles = resources.files;
119
+ context.resourceIndexRows = resources.indexRows;
120
+ return context;
121
+ }
122
+ export function renderPresetTaskTemplate(destination, content, presetContext) {
123
+ if (!presetContext)
124
+ return content;
125
+ let next = String(content);
126
+ if (destination === "task_plan.md" || destination === "task_plan") {
127
+ next = renderPresetMetadata(next, presetContext);
128
+ }
129
+ const templateKey = {
130
+ task_plan: "taskPlanAppend",
131
+ "task_plan.md": "taskPlanAppend",
132
+ execution_strategy: "executionStrategyAppend",
133
+ "execution_strategy.md": "executionStrategyAppend",
134
+ findings: "findingsSeed",
135
+ "findings.md": "findingsSeed",
136
+ review: "reviewSeed",
137
+ "review.md": "reviewSeed",
138
+ [visualMapFile]: "visualMapAppend",
139
+ }[destination];
140
+ const templatePath = presetContext.presetPackage?.newTaskTemplates?.[templateKey];
141
+ if (templatePath) {
142
+ next = `${next.trimEnd()}\n\n${renderPresetTemplate(presetContext.presetPackage, templatePath, presetContext.values).trimEnd()}\n`;
143
+ }
144
+ if (destination === "task_plan.md" || destination === "task_plan") {
145
+ next = appendPresetRequiredReads(next, presetContext);
146
+ }
147
+ return next;
148
+ }
149
+ export function renderPresetResourceIndex(content, kind, rows) {
150
+ if (!rows.length)
151
+ return content;
152
+ const renderedRows = rows.map((row) => kind === "references"
153
+ ? `| ${markdownTableCell(row.id)} | ${markdownTableCell(row.type || "preset")} | ${markdownTableCell(row.path)} | ${markdownTableCell(row.summary)} | ${markdownTableCell(row.usedBy || "coordinator")} |`
154
+ : `| ${markdownTableCell(row.id)} | ${markdownTableCell(row.type || "preset")} | ${markdownTableCell(row.path)} | ${markdownTableCell(row.summary)} | ${markdownTableCell(row.producedBy || "preset")} |`);
155
+ const base = String(content || "").trim() ? String(content || "") : presetIndexSkeleton(kind);
156
+ const lines = base.trimEnd().split(/\r?\n/);
157
+ const separatorIndex = lines.findIndex((line) => /^\|\s*---/.test(line));
158
+ if (separatorIndex >= 0) {
159
+ lines.splice(separatorIndex + 1, 0, ...renderedRows);
160
+ return `${lines.join("\n")}\n`;
161
+ }
162
+ return `${String(content || "").trimEnd()}\n${renderedRows.join("\n")}\n`;
163
+ }
164
+ export function assertPresetWriteScope(preset, relativePath) {
165
+ const normalized = toPosix(path.normalize(relativePath));
166
+ if (normalized.startsWith("../") || path.isAbsolute(normalized)) {
167
+ throw new Error(`Preset write scope violation for ${relativePath}`);
168
+ }
169
+ if (!preset.writeScopes.some((scope) => normalizedPresetScopes(scope.path).some((candidate) => matchesScope(candidate, normalized)))) {
170
+ throw new Error(`Preset write scope violation for ${normalized}`);
171
+ }
172
+ }
173
+ function normalizedPresetScopes(scopePath) {
174
+ const scope = toPosix(path.normalize(String(scopePath || "")));
175
+ const taskRoot = legacyPath(legacyTaskRoot);
176
+ const planningRoot = legacyPath(legacyPlanningRoot);
177
+ const scopes = [scope];
178
+ if (scope.startsWith(taskRoot))
179
+ scopes.push(`${v2HarnessRoot}/planning/tasks${scope.slice(taskRoot.length)}`);
180
+ else if (scope.startsWith(planningRoot))
181
+ scopes.push(`${v2HarnessRoot}/planning${scope.slice(planningRoot.length)}`);
182
+ return scopes;
183
+ }
184
+ function inputValue(declaration, { cliArgs, fromSession }) {
185
+ if (declaration.flag === "--from-session" && fromSession)
186
+ return fromSession;
187
+ if (!declaration.flag)
188
+ return declaration.default;
189
+ const index = cliArgs.indexOf(declaration.flag);
190
+ if (index < 0)
191
+ return declaration.default;
192
+ if (declaration.type === "flag")
193
+ return true;
194
+ const value = cliArgs[index + 1];
195
+ if (!value || value.startsWith("--"))
196
+ return "";
197
+ return value;
198
+ }
199
+ function computedValues(preset, inputs) {
200
+ const values = {};
201
+ const migrationSession = Object.values(inputs).find((value) => value && typeof value === "object" && value.operation === "migrate-run");
202
+ if (migrationSession) {
203
+ values.migrationTargetLevel = preset.task?.migrationTargetLevel || "migration-baseline";
204
+ values.migrationAchievedLevel = migrationSession.strictDeferred ? "migration-deferred" : migrationSession.result === "complete" ? "migration-full-cutover" : "migration-baseline";
205
+ values.strictDeferred = migrationSession.strictDeferred ? "yes" : "no";
206
+ values.fullCutoverClaimAllowed = values.migrationAchievedLevel === "migration-full-cutover" ? "yes" : "no";
207
+ values.warnings = migrationSession.plan?.summary?.warnings || 0;
208
+ values.taskActions = migrationSession.plan?.summary?.taskActions || 0;
209
+ values.legacyResiduals = migrationSession.plan?.summary?.legacyResiduals || 0;
210
+ values.generatedAt = migrationSession.generatedAt || "";
211
+ }
212
+ return values;
213
+ }
214
+ function presetEvidenceBundle(preset, { target, taskDir, evaluatedValues }) {
215
+ const bundleDir = String(preset.evidence?.bundleDir || "artifacts/preset").trim();
216
+ const stampSource = evaluatedValues.generatedAt || new Date().toISOString();
217
+ const stamp = String(stampSource).replace(/[^0-9A-Za-z-]+/g, "-").replace(/-+$/g, "");
218
+ const relativeTaskDir = toPosix(path.relative(target.projectRoot, taskDir));
219
+ return toPosix(path.join(relativeTaskDir, bundleDir, stamp || "generated"));
220
+ }
221
+ function generateEvidenceFiles(preset, { target, context }) {
222
+ const files = [];
223
+ const add = (relativePath, source, content) => {
224
+ assertPresetWriteScope(preset, relativePath);
225
+ files.push({ relativePath, source, content });
226
+ };
227
+ const evidenceFiles = preset.evidence?.files || {};
228
+ for (const [name, declaration] of Object.entries(evidenceFiles)) {
229
+ addEvidenceFile({ name, declaration, preset, target, context, add });
230
+ }
231
+ for (const name of preset.audit.evidenceFiles || []) {
232
+ if (files.some((file) => path.basename(file.relativePath) === name))
233
+ continue;
234
+ addAuditFile({ name, preset, context, add });
235
+ }
236
+ return files;
237
+ }
238
+ function generateResourceFiles(preset, { context }) {
239
+ const files = [];
240
+ const indexRows = { references: [], artifacts: [] };
241
+ const add = (relativePath, source, content) => {
242
+ assertPresetWriteScope(preset, relativePath);
243
+ files.push({ relativePath, source, content });
244
+ };
245
+ for (const resource of Object.values(preset.resources?.references || {})) {
246
+ const relativePath = toPosix(path.join(context.taskRelativeDir, resource.path));
247
+ add(relativePath, resource.source || resource.template, renderResourceContent(preset, resource, context));
248
+ indexRows.references.push(renderReferenceIndexRow(resource, relativePath, context.values));
249
+ }
250
+ for (const resource of Object.values(preset.resources?.artifacts || {})) {
251
+ const relativePath = toPosix(path.join(context.taskRelativeDir, resource.path));
252
+ add(relativePath, resource.source || resource.template, renderResourceContent(preset, resource, context));
253
+ indexRows.artifacts.push(renderArtifactIndexRow(resource, relativePath, context.values));
254
+ }
255
+ return { files, indexRows };
256
+ }
257
+ function renderResourceContent(preset, resource, context) {
258
+ if (resource.template)
259
+ return renderPresetTemplate(preset, resource.template, context.values);
260
+ return fs.readFileSync(path.join(preset.directory, resource.source), "utf8");
261
+ }
262
+ function renderReferenceIndexRow(resource, relativePath, values) {
263
+ return {
264
+ id: resource.index.id,
265
+ type: renderInline(resource.index.type, values),
266
+ path: `TARGET:${relativePath}`,
267
+ summary: renderInline(resource.index.summary, values),
268
+ usedBy: renderInline(resource.index.usedBy, values),
269
+ };
270
+ }
271
+ function renderArtifactIndexRow(resource, relativePath, values) {
272
+ return {
273
+ id: resource.index.id,
274
+ type: renderInline(resource.index.type, values),
275
+ path: `TARGET:${relativePath}`,
276
+ summary: renderInline(resource.index.summary, values),
277
+ producedBy: renderInline(resource.index.producedBy || "preset", values),
278
+ };
279
+ }
280
+ function appendPresetRequiredReads(content, context) {
281
+ const requiredReads = context.presetPackage?.context?.requiredReads || [];
282
+ if (!requiredReads.length)
283
+ return content;
284
+ const rowsById = new Map((context.resourceIndexRows?.references || []).map((row) => [row.id, row]));
285
+ const rows = requiredReads.map((id) => {
286
+ const row = rowsById.get(id);
287
+ return `| ${markdownTableCell(id)} | ${markdownTableCell(row?.path || "references/INDEX.md")} | ${markdownTableCell(row?.summary || "Preset-provided reference")} |`;
288
+ });
289
+ return `${content.trimEnd()}\n\n## Preset Required Reads\n\nOpen \`references/INDEX.md\`, then read these preset-provided references before implementation.\n\n| Reference | Path | Why |\n| --- | --- | --- |\n${rows.join("\n")}\n`;
290
+ }
291
+ function addEvidenceFile({ name, declaration, preset, target, context, add }) {
292
+ const fileName = declaration.path || `${name}.txt`;
293
+ const relativePath = toPosix(path.join(context.evidenceBundle, fileName));
294
+ const type = declaration.type || "text";
295
+ if (type === "input-json") {
296
+ add(relativePath, declaration.value || "input-json", `${JSON.stringify(getPath({ inputs: context.resolvedInputs }, declaration.value || ""), null, 2)}\n`);
297
+ }
298
+ else if (type === "json") {
299
+ add(relativePath, declaration.value || "json", `${JSON.stringify(getPath({ inputs: context.resolvedInputs, values: context.values }, declaration.value || ""), null, 2)}\n`);
300
+ }
301
+ else if (type === "text") {
302
+ add(relativePath, declaration.value || "text", `${String(getPath({ inputs: context.resolvedInputs, values: context.values }, declaration.value || "") || "").trim()}\n`);
303
+ }
304
+ else if (type === "migration-verify") {
305
+ const session = migrationSession(context);
306
+ add(relativePath, "migrate-verify", `${JSON.stringify(verifyMigrationSession(session.sourcePath, { fullCutover: false }), null, 2)}\n`);
307
+ }
308
+ else if (type === "migration-ledger") {
309
+ const session = migrationSession(context);
310
+ const verifyResult = verifyMigrationSession(session.sourcePath, { fullCutover: false });
311
+ add(relativePath, "preset-ledger", `${JSON.stringify(migrationLedger({ session, preset, verifyResult }), null, 2)}\n`);
312
+ }
313
+ else if (type === "preset-manifest") {
314
+ add(relativePath, "preset.yaml", `${JSON.stringify(presetManifestSnapshot(preset), null, 2)}\n`);
315
+ }
316
+ else if (type === "preset-audit") {
317
+ add(relativePath, "preset-audit", `${JSON.stringify(context.audit, null, 2)}\n`);
318
+ }
319
+ else if (type === "write-scope") {
320
+ add(relativePath, "preset.yaml", `${JSON.stringify({ preset: preset.id, scopes: preset.writeScopes, entrypointScopes: context.audit.writeScopes }, null, 2)}\n`);
321
+ }
322
+ else if (type === "dashboard-hash") {
323
+ add(relativePath, "dashboard", `${dashboardHash(migrationSession(context).dashboard?.indexPath || "")}\n`);
324
+ }
325
+ else if (type === "target-git-status") {
326
+ add(relativePath, "session.git.after", `${JSON.stringify(migrationSession(context).git?.after || {}, null, 2)}\n`);
327
+ }
328
+ else if (type === "target-commit") {
329
+ add(relativePath, "git", `${targetCommit(target.projectRoot)}\n`);
330
+ }
331
+ else if (type === "harness-version") {
332
+ add(relativePath, "package.json", `${packageVersion()}\n`);
333
+ }
334
+ else if (type === "generated-at") {
335
+ add(relativePath, "generated", `${new Date().toISOString()}\n`);
336
+ }
337
+ else {
338
+ throw new Error(`Unsupported preset evidence type: ${type}`);
339
+ }
340
+ }
341
+ function addAuditFile({ name, preset, context, add }) {
342
+ const relativePath = toPosix(path.join(context.evidenceBundle, name));
343
+ if (name === "preset-manifest.json") {
344
+ add(relativePath, "preset.yaml", `${JSON.stringify(presetManifestSnapshot(preset), null, 2)}\n`);
345
+ }
346
+ else if (name === "preset-audit.json") {
347
+ add(relativePath, "preset-audit", `${JSON.stringify(context.audit, null, 2)}\n`);
348
+ }
349
+ else if (name === "write-scope.json") {
350
+ add(relativePath, "preset.yaml", `${JSON.stringify({ preset: preset.id, scopes: preset.writeScopes, entrypointScopes: context.audit.writeScopes }, null, 2)}\n`);
351
+ }
352
+ else {
353
+ add(relativePath, "preset-audit", `${JSON.stringify({ preset: preset.id, generatedAt: new Date().toISOString() }, null, 2)}\n`);
354
+ }
355
+ }
356
+ function renderPresetMetadata(content, context) {
357
+ const metadata = [
358
+ context.kind && context.kind !== "general" ? `Task Kind: ${context.kind}` : "",
359
+ `Task Preset: ${context.preset}`,
360
+ `Preset Version: ${context.presetVersion}`,
361
+ context.migrationTargetLevel ? `Migration Target Level: ${context.migrationTargetLevel}` : "",
362
+ context.migrationAchievedLevel ? `Migration Achieved Level: ${context.migrationAchievedLevel}` : "",
363
+ context.evidenceBundle ? `Evidence Bundle: ${context.evidenceBundle}` : "",
364
+ ...declaredMetadataLines(context),
365
+ ].filter(Boolean).join("\n");
366
+ let next = String(content).replace(new RegExp(`^(${escapeRegExp(taskContractMarker)}\\s*)$`, "im"), `$1\n${metadata}`);
367
+ const outcome = context.presetPackage.task?.defaultOutcome || "";
368
+ if (outcome) {
369
+ next = next
370
+ .replace("[State the outcome this task must deliver in one sentence.]", outcome)
371
+ .replace("[用一句话说明本任务完成后应达到的状态。]", outcome);
372
+ }
373
+ return next;
374
+ }
375
+ function declaredMetadataLines(context) {
376
+ const base = {
377
+ inputs: context.resolvedInputs || {},
378
+ values: context.values || {},
379
+ preset: {
380
+ id: context.preset,
381
+ version: context.presetVersion,
382
+ },
383
+ task: {
384
+ id: context.taskId,
385
+ title: context.taskTitle,
386
+ kind: context.kind,
387
+ },
388
+ };
389
+ return Object.entries(context.presetPackage?.metadata || {}).map(([name, declaration]) => {
390
+ const label = declaration.label || name;
391
+ let value = "";
392
+ if (Object.prototype.hasOwnProperty.call(declaration, "from")) {
393
+ value = getPath(base, declaration.from);
394
+ }
395
+ else if (Object.prototype.hasOwnProperty.call(declaration, "value")) {
396
+ value = declaration.value;
397
+ }
398
+ else if (Object.prototype.hasOwnProperty.call(declaration, "default")) {
399
+ value = declaration.default;
400
+ }
401
+ return value == null || value === "" ? "" : `${label}: ${value}`;
402
+ });
403
+ }
404
+ function migrationSession(context) {
405
+ const session = Object.values(context.resolvedInputs || {}).find((value) => value && typeof value === "object" && value.operation === "migrate-run");
406
+ if (!session)
407
+ throw new Error("Preset evidence requires migrate-run session input");
408
+ return session;
409
+ }
410
+ function migrationLedger({ session, preset, verifyResult }) {
411
+ const summary = session.plan?.summary || {};
412
+ return {
413
+ schemaVersion: "legacy-migration-ledger/v2",
414
+ preset: preset.id,
415
+ presetVersion: preset.version,
416
+ staticDashboardRole: "evidence-snapshot",
417
+ workbenchRole: "human-confirmation-control-plane",
418
+ phases: [
419
+ { id: "baseline", state: verifyResult.status === "pass" ? "done" : "blocked", evidence: ["session.json", "migrate-plan.json", "normal-check.json", "strict-check.json", "migrate-verify.json"] },
420
+ {
421
+ id: "mechanical-scaffold",
422
+ state: "planned",
423
+ automationAllowed: true,
424
+ outputPolicy: "May add missing task contract files and placeholders, but must not mark semantic reconstruction complete.",
425
+ counters: {
426
+ taskActions: Number(summary.taskActions || 0),
427
+ reviewSchemaGaps: Number(summary.reviewSchemaGaps || 0),
428
+ legacyReferenceGaps: Number(summary.legacyReferenceGaps || 0),
429
+ },
430
+ },
431
+ {
432
+ id: "semantic-reconstruction",
433
+ state: "planned",
434
+ automationAllowed: false,
435
+ evidenceLedgerRequired: true,
436
+ requiredEvidenceSources: ["task_plan.md", "progress.md", "review.md", "walkthrough", "Harness-Ledger", "git"],
437
+ completionRule: "Each task needs explicit evidenceSources and reviewState before semantic completion.",
438
+ },
439
+ { id: "cutover-review", state: "planned", humanConfirmationRequired: true, workbenchQueueRequired: true, staticDashboardRole: "evidence-snapshot" },
440
+ ],
441
+ counters: {
442
+ warnings: Number(summary.warnings || 0),
443
+ taskActions: Number(summary.taskActions || 0),
444
+ reviewSchemaGaps: Number(summary.reviewSchemaGaps || 0),
445
+ legacyReferenceGaps: Number(summary.legacyReferenceGaps || 0),
446
+ legacyResiduals: Number(summary.legacyResiduals || 0),
447
+ fullCutoverEligible: summary.fullCutoverEligible === true,
448
+ },
449
+ queue: [],
450
+ };
451
+ }
452
+ function presetManifestSnapshot(preset) {
453
+ return {
454
+ id: preset.id,
455
+ version: preset.version,
456
+ manifestPath: preset.manifestRelativePath,
457
+ manifestSha256: preset.manifestSha256,
458
+ compatibleBudgets: preset.compatibleBudgets,
459
+ entrypoints: preset.entrypoints,
460
+ audit: preset.audit,
461
+ writeScopes: preset.writeScopes,
462
+ inputs: preset.inputs,
463
+ templateValues: preset.templateValues,
464
+ metadata: preset.metadata,
465
+ resources: preset.resources,
466
+ context: preset.context,
467
+ };
468
+ }
469
+ function matchesScope(scope, relativePath) {
470
+ const normalizedScope = toPosix(String(scope || ""));
471
+ if (normalizedScope.endsWith("/**")) {
472
+ const prefix = normalizedScope.slice(0, -3);
473
+ return relativePath === prefix || relativePath.startsWith(`${prefix}/`);
474
+ }
475
+ return relativePath === normalizedScope;
476
+ }
477
+ function dashboardHash(indexPath) {
478
+ if (!indexPath || !fs.existsSync(indexPath))
479
+ return "missing";
480
+ return `sha256:${crypto.createHash("sha256").update(fs.readFileSync(indexPath)).digest("hex")}`;
481
+ }
482
+ function targetCommit(projectRoot) {
483
+ const result = spawnSync("git", ["-C", projectRoot, "rev-parse", "HEAD"], { encoding: "utf8" });
484
+ return result.status === 0 ? result.stdout.trim() : "n/a";
485
+ }
486
+ function packageVersion() {
487
+ try {
488
+ return readJsonSafe(path.join(repoRoot, "package.json"), {}).version || "unknown";
489
+ }
490
+ catch {
491
+ return "unknown";
492
+ }
493
+ }
494
+ function getPath(values, key) {
495
+ if (!key)
496
+ return values;
497
+ return String(key).split(".").reduce((cursor, part) => (cursor && Object.prototype.hasOwnProperty.call(cursor, part) ? cursor[part] : undefined), values);
498
+ }
499
+ function renderInline(value, values) {
500
+ return String(value || "").replace(/\{\{\s*([A-Za-z0-9_.-]+)\s*\}\}/g, (_match, key) => {
501
+ const result = getPath(values, key);
502
+ return result == null ? "" : String(result);
503
+ });
504
+ }
505
+ function markdownTableCell(value) {
506
+ return String(value || "").replace(/\r?\n/g, " ").replaceAll("|", "&#124;").trim();
507
+ }
508
+ function presetIndexSkeleton(kind) {
509
+ if (kind === "references") {
510
+ return "# References Index\n\n| ID | Type | Path | Summary | Used By |\n| --- | --- | --- | --- | --- |\n";
511
+ }
512
+ return "# Artifacts Index\n\n| ID | Type | Path | Summary | Produced By |\n| --- | --- | --- | --- | --- |\n";
513
+ }
514
+ function escapeRegExp(value) {
515
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
516
+ }