coding-agent-harness 1.0.8 → 1.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 (232) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/CONTRIBUTING.md +8 -4
  3. package/README.md +12 -2
  4. package/README.zh-CN.md +10 -2
  5. package/SKILL.md +14 -3
  6. package/dist/build-dist.mjs +19 -6
  7. package/dist/check-dist-observation.mjs +57 -29
  8. package/dist/check-harness.mjs +0 -1
  9. package/dist/check-import-graph.mjs +44 -27
  10. package/dist/check-lite-forbidden-surfaces.mjs +121 -0
  11. package/dist/check-no-ts-nocheck.mjs +7 -7
  12. package/dist/check-runtime-emit.mjs +10 -3
  13. package/dist/check-type-boundaries.mjs +51 -9
  14. package/dist/commands/dashboard-command.mjs +52 -14
  15. package/dist/commands/migration-command.mjs +18 -8
  16. package/dist/commands/module-command.mjs +142 -0
  17. package/dist/commands/preset-command.mjs +51 -12
  18. package/dist/commands/registry.mjs +483 -0
  19. package/dist/commands/task-command.mjs +109 -52
  20. package/dist/harness.mjs +6 -304
  21. package/dist/lib/capability-registry.mjs +229 -53
  22. package/dist/lib/check-module-parallel.mjs +1 -6
  23. package/dist/lib/check-profiles.mjs +39 -46
  24. package/dist/lib/check-task-contracts.mjs +6 -4
  25. package/dist/lib/command-registry.mjs +248 -0
  26. package/dist/lib/core-shared.mjs +78 -3
  27. package/dist/lib/dashboard-data.mjs +203 -22
  28. package/dist/lib/dashboard-workbench.mjs +245 -21
  29. package/dist/lib/dashboard-writer.mjs +4 -1
  30. package/dist/lib/git-status-summary.mjs +0 -1
  31. package/dist/lib/governance-index-generator.mjs +7 -5
  32. package/dist/lib/governance-sync.mjs +46 -121
  33. package/dist/lib/governance-table-boundary.mjs +1 -14
  34. package/dist/lib/harness-core.mjs +4 -1
  35. package/dist/lib/harness-paths.mjs +115 -1
  36. package/dist/lib/impact-classifier.mjs +420 -0
  37. package/dist/lib/lesson-maintenance.mjs +1 -2
  38. package/dist/lib/markdown-utils.mjs +50 -1
  39. package/dist/lib/migration-planner.mjs +31 -16
  40. package/dist/lib/migration-support.mjs +5 -4
  41. package/dist/lib/module-registry.mjs +296 -0
  42. package/dist/lib/preset-audit-contracts.mjs +24 -1
  43. package/dist/lib/preset-engine.mjs +67 -29
  44. package/dist/lib/preset-registry.mjs +361 -71
  45. package/dist/lib/preset-runner.mjs +292 -26
  46. package/dist/lib/review-confirm-git-gate.mjs +73 -19
  47. package/dist/lib/status-builder.mjs +23 -8
  48. package/dist/lib/structure-migration.mjs +6 -4
  49. package/dist/lib/subagent-authorization-audit.mjs +8 -2
  50. package/dist/lib/task-archive-eligibility.mjs +65 -0
  51. package/dist/lib/task-audit-metadata.mjs +25 -11
  52. package/dist/lib/task-audit-migration.mjs +21 -14
  53. package/dist/lib/task-discovery-contract.mjs +32 -0
  54. package/dist/lib/task-index.mjs +3 -2
  55. package/dist/lib/task-lesson-candidates.mjs +1 -2
  56. package/dist/lib/task-lesson-sedimentation.mjs +310 -9
  57. package/dist/lib/task-lifecycle/create-task-helpers.mjs +6 -3
  58. package/dist/lib/task-lifecycle/phase-sync.mjs +0 -1
  59. package/dist/lib/task-lifecycle/preset-interop.mjs +16 -0
  60. package/dist/lib/task-lifecycle/review-confirm.mjs +34 -2
  61. package/dist/lib/task-lifecycle/review-gates.mjs +12 -5
  62. package/dist/lib/task-lifecycle/review-submission.mjs +1 -2
  63. package/dist/lib/task-lifecycle/scaffold-provenance.mjs +0 -1
  64. package/dist/lib/task-lifecycle/template-files.mjs +2 -5
  65. package/dist/lib/task-lifecycle.mjs +116 -160
  66. package/dist/lib/task-metadata.mjs +10 -5
  67. package/dist/lib/task-preset-contract-drift.mjs +45 -0
  68. package/dist/lib/task-repository.mjs +192 -0
  69. package/dist/lib/task-review-model.mjs +36 -17
  70. package/dist/lib/task-scanner.mjs +74 -23
  71. package/dist/lib/task-template-materials.mjs +131 -0
  72. package/dist/lib/task-tombstone-commands.mjs +186 -29
  73. package/dist/lib/types/check-profiles.js +1 -0
  74. package/dist/lib/types/impact.js +1 -0
  75. package/dist/lib/types/preset.js +1 -0
  76. package/dist/lib/types/task-lifecycle.js +1 -0
  77. package/dist/lib/types/task-scanner.js +1 -0
  78. package/dist/postinstall.mjs +2 -2
  79. package/dist/run-built-tests.mjs +10 -3
  80. package/docs-release/README.md +1 -0
  81. package/docs-release/architecture/document-contract-kernel/README.md +150 -0
  82. package/docs-release/architecture/document-contract-kernel/products/full-skill-overlay.md +29 -0
  83. package/docs-release/architecture/document-contract-kernel/products/lite-forbidden-surfaces.txt +26 -0
  84. package/docs-release/architecture/document-contract-kernel/products/lite-skill-overlay.md +37 -0
  85. package/docs-release/architecture/overview.md +2 -2
  86. package/docs-release/architecture/overview.zh-CN.md +2 -2
  87. package/docs-release/architecture/system-explainer/01-system-overview.md +11 -7
  88. package/docs-release/architecture/system-explainer/02-module-dependency.md +4 -4
  89. package/docs-release/architecture/system-explainer/03-task-lifecycle.md +17 -12
  90. package/docs-release/architecture/system-explainer/05-data-flow.md +6 -6
  91. package/docs-release/architecture/system-explainer/06-preset-and-migration.md +2 -2
  92. package/docs-release/architecture/system-explainer/README.md +1 -1
  93. package/docs-release/architecture/system-explainer/en-US/01-system-overview.md +12 -8
  94. package/docs-release/architecture/system-explainer/en-US/02-module-dependency.md +5 -5
  95. package/docs-release/architecture/system-explainer/en-US/03-task-lifecycle.md +19 -11
  96. package/docs-release/architecture/system-explainer/en-US/05-data-flow.md +5 -5
  97. package/docs-release/architecture/system-explainer/en-US/06-preset-and-migration.md +2 -2
  98. package/docs-release/architecture/system-explainer/en-US/README.md +1 -1
  99. package/docs-release/guides/agent-installation.en-US.md +4 -6
  100. package/docs-release/guides/agent-installation.md +11 -8
  101. package/docs-release/guides/contributing.md +10 -3
  102. package/docs-release/guides/contributing.zh-CN.md +10 -3
  103. package/docs-release/guides/legacy-migration-agent-prompt.md +1 -1
  104. package/docs-release/guides/legacy-migration-agent-prompt.zh-CN.md +1 -1
  105. package/docs-release/guides/migration-playbook.en-US.md +9 -6
  106. package/docs-release/guides/migration-playbook.md +9 -6
  107. package/docs-release/guides/preset-development.md +68 -2
  108. package/docs-release/guides/task-state-machine.en-US.md +8 -8
  109. package/docs-release/guides/task-state-machine.md +7 -7
  110. package/docs-release/guides/typescript-runtime-migration-closeout.md +17 -13
  111. package/package.json +16 -12
  112. package/postinstall.mjs +37 -0
  113. package/presets/legacy-migration/preset.yaml +5 -5
  114. package/presets/legacy-migration/templates/execution_strategy.append.md +1 -1
  115. package/presets/lesson-sedimentation/preset.yaml +3 -3
  116. package/presets/module/preset.yaml +2 -2
  117. package/presets/module/templates/execution_strategy.append.md +1 -1
  118. package/presets/module/templates/task_plan.append.md +3 -3
  119. package/presets/release-closeout/checks/check-release-package.mjs +6 -1
  120. package/presets/release-closeout/preset.yaml +9 -9
  121. package/presets/release-closeout/scripts/generate-release-package.mjs +387 -25
  122. package/presets/release-closeout/templates/task_plan.append.md +5 -5
  123. package/presets/standard-task/preset.yaml +2 -2
  124. package/references/agents-md-pattern.md +23 -17
  125. package/references/lessons-governance.md +2 -2
  126. package/references/module-parallel-standard.md +3 -6
  127. package/references/ssot-governance.md +2 -2
  128. package/references/taskr-gap-analysis.md +3 -3
  129. package/run-dist.mjs +34 -0
  130. package/skills/preset-creator/SKILL.md +40 -8
  131. package/skills/preset-creator/references/complex-task-skeleton/brief.md +32 -8
  132. package/skills/preset-creator/references/preset-package-skeleton.md +15 -5
  133. package/skills/preset-creator/references/structure-aware-paths.md +112 -0
  134. package/templates/AGENTS.md.template +28 -26
  135. package/templates/architecture/README.md +2 -2
  136. package/templates/architecture/service-catalog.md +2 -2
  137. package/templates/architecture/services/service-template.md +1 -1
  138. package/templates/dashboard/assets/app-src/00-state.js +5 -1
  139. package/templates/dashboard/assets/app-src/10-router.js +7 -0
  140. package/templates/dashboard/assets/app-src/20-overview.js +8 -8
  141. package/templates/dashboard/assets/app-src/30-tasks.js +132 -40
  142. package/templates/dashboard/assets/app-src/32-task-swimlane.js +314 -0
  143. package/templates/dashboard/assets/app-src/35-task-detail.js +35 -5
  144. package/templates/dashboard/assets/app-src/40-modules.js +257 -41
  145. package/templates/dashboard/assets/app-src/45-review.js +127 -1
  146. package/templates/dashboard/assets/app-src/90-bindings.js +185 -2
  147. package/templates/dashboard/assets/app.css +928 -53
  148. package/templates/dashboard/assets/app.css.manifest.json +2 -0
  149. package/templates/dashboard/assets/app.js +1071 -98
  150. package/templates/dashboard/assets/app.manifest.json +1 -0
  151. package/templates/dashboard/assets/css-src/00-foundation.css +12 -6
  152. package/templates/dashboard/assets/css-src/10-panels-flow.css +2 -2
  153. package/templates/dashboard/assets/css-src/30-task-index.css +21 -13
  154. package/templates/dashboard/assets/css-src/31-archive.css +94 -0
  155. package/templates/dashboard/assets/css-src/32-task-swimlane.css +487 -0
  156. package/templates/dashboard/assets/css-src/35-review-workspace.css +78 -0
  157. package/templates/dashboard/assets/css-src/40-detail-modules-migration.css +191 -14
  158. package/templates/dashboard/assets/css-src/50-responsive-overrides.css +23 -0
  159. package/templates/dashboard/assets/i18n.js +166 -2
  160. package/templates/development/README.md +9 -9
  161. package/templates/development/cross-repo-debugging.md +3 -3
  162. package/templates/development/external-context/service-template.md +1 -1
  163. package/templates/development/external-source-packs/README.md +2 -2
  164. package/templates/integrations/README.md +4 -4
  165. package/templates/integrations/api-contract.md +1 -1
  166. package/templates/integrations/event-contract.md +1 -1
  167. package/templates/integrations/third-party/vendor-template.md +1 -1
  168. package/templates/integrations/webhook-contract.md +1 -1
  169. package/templates/ledger/Harness-Ledger.md +1 -1
  170. package/templates/modules/module_brief.md +50 -0
  171. package/templates/modules/module_plan.md +49 -0
  172. package/templates/modules/registry_view.md +9 -0
  173. package/templates/modules/session_prompt_pack.md +55 -0
  174. package/templates/planning/brief.md +32 -8
  175. package/templates/planning/module_brief.md +28 -3
  176. package/templates/planning/module_plan.md +26 -11
  177. package/templates/planning/module_session_prompt.md +11 -2
  178. package/templates/planning/optional/slices/_slice-template/brief.md +28 -0
  179. package/templates/planning/review.md +1 -1
  180. package/templates/planning/visual_map.md +1 -1
  181. package/templates/reference/docs-library-standard.md +7 -7
  182. package/templates/reference/execution-workflow-standard.md +13 -0
  183. package/templates/reference/external-source-intake-standard.md +10 -10
  184. package/templates/reference/repo-governance-standard.md +1 -1
  185. package/templates/reference/review-routing-standard.md +4 -0
  186. package/templates/ssot/Module-Registry.md +4 -38
  187. package/templates/walkthrough/walkthrough-template.md +1 -1
  188. package/templates-zh-CN/AGENTS.md.template +27 -25
  189. package/templates-zh-CN/CLAUDE.md.template +1 -1
  190. package/templates-zh-CN/architecture/README.md +2 -2
  191. package/templates-zh-CN/architecture/service-catalog.md +2 -2
  192. package/templates-zh-CN/architecture/services/service-template.md +1 -1
  193. package/templates-zh-CN/development/README.md +9 -9
  194. package/templates-zh-CN/development/cross-repo-debugging.md +3 -3
  195. package/templates-zh-CN/development/external-context/service-template.md +1 -1
  196. package/templates-zh-CN/development/external-source-packs/README.md +2 -2
  197. package/templates-zh-CN/integrations/README.md +4 -4
  198. package/templates-zh-CN/integrations/api-contract.md +1 -1
  199. package/templates-zh-CN/integrations/event-contract.md +1 -1
  200. package/templates-zh-CN/integrations/third-party/vendor-template.md +1 -1
  201. package/templates-zh-CN/integrations/webhook-contract.md +1 -1
  202. package/templates-zh-CN/ledger/Harness-Ledger.md +1 -1
  203. package/templates-zh-CN/lessons/lesson-arch-process-change.md +1 -1
  204. package/templates-zh-CN/lessons/lesson-new-doc.md +3 -3
  205. package/templates-zh-CN/lessons/lesson-ref-change.md +4 -4
  206. package/templates-zh-CN/modules/module_brief.md +47 -0
  207. package/templates-zh-CN/modules/module_plan.md +48 -0
  208. package/templates-zh-CN/modules/registry_view.md +9 -0
  209. package/templates-zh-CN/modules/session_prompt_pack.md +50 -0
  210. package/templates-zh-CN/planning/INDEX.md +1 -0
  211. package/templates-zh-CN/planning/brief.md +26 -7
  212. package/templates-zh-CN/planning/module_brief.md +24 -2
  213. package/templates-zh-CN/planning/module_plan.md +35 -29
  214. package/templates-zh-CN/planning/module_session_prompt.md +15 -11
  215. package/templates-zh-CN/planning/optional/slices/_slice-template/brief.md +28 -11
  216. package/templates-zh-CN/planning/review.md +1 -1
  217. package/templates-zh-CN/reference/adversarial-review-standard.md +1 -1
  218. package/templates-zh-CN/reference/delivery-operating-model-standard.md +3 -3
  219. package/templates-zh-CN/reference/docs-library-standard.md +27 -27
  220. package/templates-zh-CN/reference/execution-workflow-standard.md +12 -2
  221. package/templates-zh-CN/reference/external-source-intake-standard.md +10 -10
  222. package/templates-zh-CN/reference/harness-ledger-standard.md +3 -3
  223. package/templates-zh-CN/reference/regression-ssot-governance.md +2 -2
  224. package/templates-zh-CN/reference/repo-governance-standard.md +1 -1
  225. package/templates-zh-CN/reference/review-routing-standard.md +3 -0
  226. package/templates-zh-CN/reference/walkthrough-standard.md +2 -2
  227. package/templates-zh-CN/reference/worktree-standard.md +1 -1
  228. package/templates-zh-CN/regression/Cadence-Ledger.md +2 -2
  229. package/templates-zh-CN/ssot/Delivery-SSoT.md +2 -2
  230. package/templates-zh-CN/ssot/Module-Registry.md +5 -44
  231. package/templates-zh-CN/ssot/Regression-SSoT.md +2 -2
  232. package/templates-zh-CN/walkthrough/walkthrough-template.md +4 -4
@@ -1,22 +1,27 @@
1
- // @ts-nocheck
2
1
  import fs from "node:fs";
3
2
  import path from "node:path";
4
3
  import { normalizeTarget, nowTimestamp, readFileSafe, toPosix, datePrefix, } from "./core-shared.mjs";
4
+ import { removeHeadingSectionOutsideFences } from "./markdown-utils.mjs";
5
5
  import { collectTasks } from "./task-scanner.mjs";
6
+ import { resolveTaskDirectory } from "./task-lifecycle.mjs";
7
+ import { taskIdFromDirectory } from "./harness-paths.mjs";
8
+ import { assessArchiveEligibility, normalizeArchiveActor } from "./task-archive-eligibility.mjs";
9
+ import { normalizeReviewBoolean } from "./task-review-model.mjs";
6
10
  import { beginGovernanceSync, commitGovernanceSync, releaseGovernanceSync, } from "./governance-sync.mjs";
7
- export function supersedeTask(targetInput, oldRef, { by = "", reason = "" } = {}) {
11
+ export function supersedeTask(targetInput, oldRef, { by = "", reason = "", deletedBy = "", confirm = "", allowOpenFindings = false } = {}) {
8
12
  if (!by)
9
13
  throw new Error("task-supersede requires --by <new-task-id>");
10
14
  const target = normalizeTarget(targetInput);
11
15
  const oldTask = resolveTask(target, oldRef);
12
16
  const newTask = resolveTask(target, by);
17
+ assertSoftDeleteEligible(oldTask, { reason, deletedBy, confirm, allowOpenFindings, action: "task-supersede" });
13
18
  const governanceContext = beginGovernanceSync(target, { operation: `task-supersede ${oldTask.id}` });
14
19
  try {
15
20
  writeTombstone(target, oldTask, {
16
21
  State: "superseded",
17
22
  "Superseded By": newTask.id,
18
23
  Reason: reason || "superseded",
19
- Operator: "coordinator",
24
+ Operator: normalizeTombstoneActor(deletedBy) || "coordinator",
20
25
  Timestamp: nowTimestamp(),
21
26
  "Reopen Eligible": "yes",
22
27
  "Archive Eligible": "no",
@@ -32,16 +37,43 @@ export function supersedeTask(targetInput, oldRef, { by = "", reason = "" } = {}
32
37
  releaseGovernanceSync(governanceContext);
33
38
  }
34
39
  }
35
- export function softDeleteTask(targetInput, taskRef, { reason = "" } = {}) {
40
+ export function softDeleteTask(targetInput, taskRef, options = {}) {
41
+ return deleteTask(targetInput, taskRef, { ...options, hard: false });
42
+ }
43
+ export function deleteTask(targetInput, taskRef, { hard = false, reason = "", deletedBy = "", confirm = "", allowOpenFindings = false } = {}) {
36
44
  const target = normalizeTarget(targetInput);
37
45
  const task = resolveTask(target, taskRef);
38
- return writeDeletionState(target, task, "soft-deleted", reason || "soft-delete", "task-delete --soft");
46
+ if (!hard) {
47
+ assertSoftDeleteEligible(task, { reason, deletedBy, confirm, allowOpenFindings, action: "task-delete" });
48
+ return writeDeletionState(target, task, "soft-deleted", reason || "soft-delete", "task-delete --soft", {
49
+ Operator: normalizeTombstoneActor(deletedBy) || "coordinator",
50
+ });
51
+ }
52
+ assertHardDeleteEligible(target, task, { reason, deletedBy, confirm });
53
+ const taskDir = path.join(target.projectRoot, task.path.replace(/^TARGET:/, ""));
54
+ const allowedPaths = collectTaskDirectoryFiles(taskDir).map((file) => toPosix(path.relative(target.projectRoot, file)));
55
+ const governanceContext = beginGovernanceSync(target, { operation: `task-delete --hard ${task.id}` });
56
+ try {
57
+ fs.rmSync(taskDir, { recursive: true, force: true });
58
+ const commit = commitGovernanceSync(governanceContext, allowedPaths, {
59
+ message: `chore(harness): hard delete task ${task.id}`,
60
+ });
61
+ return { taskId: task.id, deletionState: "hard-deleted", reason, governance: { commit } };
62
+ }
63
+ finally {
64
+ releaseGovernanceSync(governanceContext);
65
+ }
39
66
  }
40
- export function archiveTask(targetInput, taskRef, { reason = "" } = {}) {
67
+ export function archiveTask(targetInput, taskRef, { reason = "", archivedBy = "", archiveFields = {} } = {}) {
41
68
  const target = normalizeTarget(targetInput);
42
69
  const task = resolveTask(target, taskRef);
43
- assertArchiveEligible(task);
44
- return writeDeletionState(target, task, "archived", reason || "archive", "task-archive");
70
+ const archiveAudit = assertArchiveEligible(task, { archivedBy });
71
+ const normalizedArchiveFields = normalizeArchiveFields(archiveFields);
72
+ assertNoReservedArchiveFields(normalizedArchiveFields);
73
+ return writeDeletionState(target, task, "archived", reason || "archive", "task-archive", {
74
+ ...normalizedArchiveFields,
75
+ ...archiveAudit,
76
+ });
45
77
  }
46
78
  export function reopenTask(targetInput, taskRef, { reason = "" } = {}) {
47
79
  const target = normalizeTarget(targetInput);
@@ -50,7 +82,7 @@ export function reopenTask(targetInput, taskRef, { reason = "" } = {}) {
50
82
  try {
51
83
  const taskPlanPath = path.join(target.projectRoot, task.taskPlanPath.replace(/^TARGET:/, ""));
52
84
  const content = readFileSafe(taskPlanPath);
53
- const next = content.replace(/\n##\s*(?:Task Tombstone|任务墓碑)\s*$[\s\S]*?(?=^##\s+|(?![\s\S]))/im, "");
85
+ const next = removeHeadingSectionOutsideFences(content, /^##\s*(?:Task Tombstone|任务墓碑)\s*$/i);
54
86
  fs.writeFileSync(taskPlanPath, next.endsWith("\n") ? next : `${next}\n`);
55
87
  appendProgress(target, task, "task-reopen", reason || "reopened");
56
88
  const commit = commitGovernanceSync(governanceContext, taskPaths(target, task), {
@@ -62,7 +94,8 @@ export function reopenTask(targetInput, taskRef, { reason = "" } = {}) {
62
94
  releaseGovernanceSync(governanceContext);
63
95
  }
64
96
  }
65
- function writeDeletionState(target, task, deletionState, reason, action) {
97
+ function writeDeletionState(target, task, deletionState, reason, action, archiveFields = {}) {
98
+ const normalizedArchiveFields = normalizeArchiveFields(archiveFields);
66
99
  const governanceContext = beginGovernanceSync(target, { operation: `${action} ${task.id}` });
67
100
  try {
68
101
  writeTombstone(target, task, {
@@ -72,6 +105,7 @@ function writeDeletionState(target, task, deletionState, reason, action) {
72
105
  Timestamp: nowTimestamp(),
73
106
  "Reopen Eligible": "yes",
74
107
  "Archive Eligible": deletionState === "archived" ? "yes" : "no",
108
+ ...normalizedArchiveFields,
75
109
  });
76
110
  appendProgress(target, task, action, reason);
77
111
  const commit = commitGovernanceSync(governanceContext, taskPaths(target, task), {
@@ -91,33 +125,121 @@ function contextFor(_target, context) {
91
125
  }
92
126
  function resolveTask(target, ref) {
93
127
  const normalized = String(ref || "").trim();
94
- const matches = collectTasks(target).filter((task) => {
95
- const bare = datePrefix.test(task.shortId) ? task.shortId.replace(datePrefix, "") : task.shortId;
96
- return task.id === normalized || task.shortId === normalized || task.id.endsWith(`/${normalized}`) || bare === normalized;
97
- });
98
- if (matches.length === 1)
99
- return matches[0];
100
- if (matches.length > 1)
101
- throw new Error(`Ambiguous task reference: ${ref}`);
128
+ const resolvedTarget = target;
129
+ const taskDir = resolveTaskDirectory(resolvedTarget, normalized);
130
+ const taskId = taskIdFromDirectory(resolvedTarget.harness, taskDir);
131
+ const task = collectTasks(target).find((candidate) => candidate.id === taskId);
132
+ if (task)
133
+ return task;
102
134
  throw new Error(`Task not found: ${ref}`);
103
135
  }
104
- function assertArchiveEligible(task) {
105
- if (task.state === "blocked" || (task.taskQueues || []).includes("blocked")) {
106
- throw new Error("blocked tasks cannot be archived without an explicit human waiver");
107
- }
108
- const blockingRisks = (task.risks || []).filter((risk) => risk.open !== "no" && (risk.blocksRelease === "yes" || ["P0", "P1", "P2"].includes(risk.severity)));
109
- if (blockingRisks.length)
110
- throw new Error("tasks with open blocking review findings cannot be archived without an explicit human waiver");
111
- if (task.materialsReady === false && task.reviewStatus !== "confirmed") {
112
- throw new Error("tasks with incomplete closeout materials cannot be archived without an explicit human waiver");
113
- }
136
+ function assertArchiveEligible(task, { archivedBy = "" } = {}) {
137
+ const result = assessArchiveEligibility(task, { archivedBy, now: nowTimestamp() });
138
+ if (!result.eligible)
139
+ throw new Error(result.reason);
140
+ return result.auditFields;
114
141
  }
115
142
  function writeTombstone(target, task, fields) {
116
143
  const taskPlanPath = path.join(target.projectRoot, task.taskPlanPath.replace(/^TARGET:/, ""));
117
- const content = readFileSafe(taskPlanPath).replace(/\n##\s*(?:Task Tombstone|任务墓碑)\s*$[\s\S]*?(?=^##\s+|(?![\s\S]))/im, "");
144
+ const content = removeHeadingSectionOutsideFences(readFileSafe(taskPlanPath), /^##\s*(?:Task Tombstone|任务墓碑)\s*$/i);
118
145
  const block = ["", "## Task Tombstone", "", "| Field | Value |", "| --- | --- |", ...Object.entries(fields).map(([key, value]) => `| ${key} | ${escapeCell(value)} |`), ""].join("\n");
119
146
  fs.writeFileSync(taskPlanPath, `${content.trimEnd()}\n${block}`);
120
147
  }
148
+ function assertSoftDeleteEligible(task, { reason = "", deletedBy = "", confirm = "", allowOpenFindings = false, action = "task-delete" } = {}) {
149
+ const risky = isRiskyMutationTask(task);
150
+ const hasOpenFindings = !isDraftState(task.state) && hasOpenBlockingFindings(task);
151
+ if (!risky && !hasOpenFindings)
152
+ return;
153
+ const missing = [];
154
+ if (!String(reason || "").trim())
155
+ missing.push("--reason");
156
+ if (!normalizeTombstoneActor(deletedBy))
157
+ missing.push("--deleted-by");
158
+ if (String(confirm || "").trim() !== task.id)
159
+ missing.push(`--confirm ${task.id}`);
160
+ if (hasOpenFindings && !allowOpenFindings)
161
+ missing.push("--allow-open-findings");
162
+ if (missing.length) {
163
+ throw new Error(`${action} would hide a risky task; required: ${missing.join(", ")}`);
164
+ }
165
+ }
166
+ export function assertHardDeleteEligible(target, task, { reason = "", deletedBy = "", confirm = "" } = {}) {
167
+ const missing = [];
168
+ if (!String(reason || "").trim())
169
+ missing.push("--reason");
170
+ if (!normalizeTombstoneActor(deletedBy))
171
+ missing.push("--deleted-by");
172
+ if (String(confirm || "").trim() !== task.id)
173
+ missing.push(`--confirm ${task.id}`);
174
+ if (missing.length)
175
+ throw new Error(`task-delete --hard requires accountable safe draft confirmation: ${missing.join(", ")}`);
176
+ const blockers = [];
177
+ if (!isDraftState(task.state))
178
+ blockers.push(`state:${task.state}`);
179
+ if (task.deletionState !== "active")
180
+ blockers.push(`deletionState:${task.deletionState}`);
181
+ if (isRiskyMutationTask(task))
182
+ blockers.push("task has lifecycle, review, evidence, or closeout history");
183
+ if (!isDraftState(task.state) && hasOpenBlockingFindings(task))
184
+ blockers.push("task has open blocking findings");
185
+ const taskDir = path.join(target.projectRoot, task.path.replace(/^TARGET:/, ""));
186
+ const disallowedFiles = collectTaskDirectoryFiles(taskDir).filter((file) => !isSafeDraftFile(taskDir, file));
187
+ if (disallowedFiles.length)
188
+ blockers.push(`non-scaffold files: ${disallowedFiles.map((file) => toPosix(path.relative(taskDir, file))).join(", ")}`);
189
+ if (blockers.length)
190
+ throw new Error(`task-delete --hard only supports safe draft tasks; ${blockers.join("; ")}`);
191
+ }
192
+ function isRiskyMutationTask(task) {
193
+ return !isDraftState(task.state) ||
194
+ Boolean(task.reviewSubmitted) ||
195
+ task.reviewStatus === "confirmed" ||
196
+ Boolean(task.reviewConfirmation?.confirmed) ||
197
+ task.materialsReady === true && !isDraftState(task.state) ||
198
+ (task.evidence || []).length > 0 ||
199
+ (task.taskQueues || []).some((queue) => ["blocked", "review", "confirmed", "finalized", "lessons"].includes(queue));
200
+ }
201
+ function isDraftState(state) {
202
+ const normalized = String(state || "").trim().toLowerCase().replaceAll("-", "_").replace(/\s+/g, "_");
203
+ return ["planned", "not_started"].includes(normalized);
204
+ }
205
+ function hasOpenBlockingFindings(task) {
206
+ return (task.risks || []).some((risk) => normalizeReviewBoolean(risk.open) !== "no" && (normalizeReviewBoolean(risk.blocksRelease) === "yes" || ["P0", "P1", "P2"].includes(String(risk.severity))));
207
+ }
208
+ function normalizeTombstoneActor(value) {
209
+ return normalizeArchiveActor(value);
210
+ }
211
+ function collectTaskDirectoryFiles(taskDir) {
212
+ if (!fs.existsSync(taskDir))
213
+ return [];
214
+ const files = [];
215
+ const visit = (dir) => {
216
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
217
+ const full = path.join(dir, entry.name);
218
+ if (entry.isDirectory())
219
+ visit(full);
220
+ else if (entry.isFile())
221
+ files.push(full);
222
+ }
223
+ };
224
+ visit(taskDir);
225
+ return files.sort();
226
+ }
227
+ function isSafeDraftFile(taskDir, file) {
228
+ const relative = toPosix(path.relative(taskDir, file));
229
+ return [
230
+ "INDEX.md",
231
+ "brief.md",
232
+ "execution_strategy.md",
233
+ "findings.md",
234
+ "lesson_candidates.md",
235
+ "progress.md",
236
+ "review.md",
237
+ "task_plan.md",
238
+ "visual_map.md",
239
+ "walkthrough.md",
240
+ "long-running-task-contract.md",
241
+ ].includes(relative) || /^artifacts\/INDEX\.md$/.test(relative) || /^references\/INDEX\.md$/.test(relative);
242
+ }
121
243
  function appendSupersedes(target, task, oldId) {
122
244
  const taskPlanPath = path.join(target.projectRoot, task.taskPlanPath.replace(/^TARGET:/, ""));
123
245
  const content = readFileSafe(taskPlanPath);
@@ -135,3 +257,38 @@ function appendProgress(target, task, action, reason) {
135
257
  function escapeCell(value) {
136
258
  return String(value || "").replace(/\r?\n/g, " ").replaceAll("|", "\\|").trim();
137
259
  }
260
+ function normalizeArchiveFields(fields) {
261
+ const entries = Object.entries(fields || {});
262
+ const normalized = {};
263
+ const seen = new Set();
264
+ for (const [rawKey, rawValue] of entries) {
265
+ const key = String(rawKey || "").trim();
266
+ if (!key || /[\r\n|]/.test(key))
267
+ throw new Error(`Invalid archive field key: ${key || "<empty>"}`);
268
+ const normalizedKey = key.toLowerCase();
269
+ if (seen.has(normalizedKey))
270
+ throw new Error(`Duplicate archive field key: ${key}`);
271
+ seen.add(normalizedKey);
272
+ normalized[key] = String(rawValue || "").replace(/\r?\n/g, " ").trim();
273
+ }
274
+ return normalized;
275
+ }
276
+ function assertNoReservedArchiveFields(fields) {
277
+ const reserved = new Set([
278
+ "state",
279
+ "reason",
280
+ "operator",
281
+ "timestamp",
282
+ "reopen eligible",
283
+ "archive eligible",
284
+ "archived by",
285
+ "archived at",
286
+ "review confirmed by",
287
+ "review confirmed at",
288
+ "review confirmation id",
289
+ "review commit sha",
290
+ ]);
291
+ const blocked = Object.keys(fields).filter((key) => reserved.has(key.toLowerCase()));
292
+ if (blocked.length)
293
+ throw new Error(`Reserved archive field cannot be overridden: ${blocked.join(", ")}`);
294
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- // @ts-nocheck
3
2
  import { seedBundledPresets } from "./lib/harness-core.mjs";
4
3
  if (process.env.CODING_AGENT_HARNESS_SKIP_POSTINSTALL === "1")
5
4
  process.exit(0);
@@ -10,5 +9,6 @@ try {
10
9
  console.log(`coding-agent-harness postinstall: ${summary} at ${result.target}`);
11
10
  }
12
11
  catch (error) {
13
- console.warn(`coding-agent-harness postinstall: preset seed skipped (${error.message})`);
12
+ const message = error instanceof Error ? error.message : String(error);
13
+ console.warn(`coding-agent-harness postinstall: preset seed skipped (${message})`);
14
14
  }
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- // @ts-nocheck
3
2
  import fs from "node:fs";
4
3
  import path from "node:path";
5
4
  import { spawnSync } from "node:child_process";
@@ -9,7 +8,9 @@ const outDir = path.join(repoRoot, "tmp", `test-runner-emit-${process.pid}`);
9
8
  const typescriptVersion = "5.9.3";
10
9
  const options = parseArgs(process.argv.slice(2));
11
10
  fs.rmSync(outDir, { recursive: true, force: true });
12
- const emit = spawnSync("npm", ["exec", "--yes", "--package", `typescript@${typescriptVersion}`, "--", "tsc", "-p", "tsconfig.tests.json", "--outDir", outDir, "--noCheck"], {
11
+ const npmArgs = ["exec", "--yes", "--package", `typescript@${typescriptVersion}`, "--", "tsc", "-p", "tsconfig.tests.json", "--outDir", outDir, "--noCheck"];
12
+ const npmCommand = resolveNpmCommand(npmArgs);
13
+ const emit = spawnSync(npmCommand.command, npmCommand.args, {
13
14
  cwd: repoRoot,
14
15
  encoding: "utf8",
15
16
  stdio: "inherit",
@@ -36,7 +37,7 @@ const result = spawnSync(process.execPath, [runner], {
36
37
  if (result.status !== 0)
37
38
  process.exit(result.status || 1);
38
39
  function parseArgs(argv) {
39
- const parsed = { test: undefined };
40
+ const parsed = {};
40
41
  for (let index = 0; index < argv.length; index += 1) {
41
42
  const arg = argv[index];
42
43
  if (arg === "--test") {
@@ -55,6 +56,12 @@ function requireValue(argv, index, option) {
55
56
  throw new Error(`${option} requires a value`);
56
57
  return value;
57
58
  }
59
+ function resolveNpmCommand(npmArgs) {
60
+ const npmExecPath = process.env.npm_execpath;
61
+ if (npmExecPath)
62
+ return { command: process.execPath, args: [npmExecPath, ...npmArgs] };
63
+ return { command: process.platform === "win32" ? "npm.cmd" : "npm", args: npmArgs };
64
+ }
58
65
  function linkPackageResources() {
59
66
  for (const entry of [
60
67
  "package.json",
@@ -56,6 +56,7 @@ Not every document is written for the same reader.
56
56
  ### Architecture / 架构
57
57
 
58
58
  - `architecture/overview.md` / `architecture/overview.zh-CN.md` — public architecture overview, including the CLI, dashboard, task lifecycle, migration rails, review gate, and release package surface. 公开架构总览,覆盖 CLI、Dashboard、任务生命周期、迁移轨道、审查门禁和发布包表面。
59
+ - `architecture/document-contract-kernel/README.md` — shared Document Contract Kernel for Full/Lite Skill semantics, compatibility matrix, change classification, Lite forbidden surfaces, and Lite to Full upgrade mapping.
59
60
 
60
61
  ### Methodology / 方法论
61
62
 
@@ -0,0 +1,150 @@
1
+ # Document Contract Kernel
2
+
3
+ The Document Contract Kernel is the product and Skill contract shared by the
4
+ Full Coding Agent Harness Skill and the future Lite Skill. It defines the stable
5
+ document semantics that both product surfaces must preserve without turning Lite
6
+ into a runtime mode or forcing Full to lower its automation and audit bar.
7
+
8
+ This contract is public source material. Full and Lite Skill text should be
9
+ generated from this shared source plus product overlays. Until a generator is
10
+ introduced, changes to the concepts or compatibility matrix must update this
11
+ file and the product overlays in the same change.
12
+
13
+ ## Kernel Naming Boundary
14
+
15
+ | Name | Layer | Responsibility | Must not do |
16
+ | --- | --- | --- | --- |
17
+ | Document Contract Kernel | Product / Skill contract | Shared document semantics, Lite/Full compatibility matrix, change classification, and upgrade mapping | Implement runtime behavior, read or write files, or define git, markdown, or path utilities |
18
+ | Domain Kernel | Runtime domain | Task identity, policy, state transitions, module ownership, and preset model | Describe Skill installation copy, package manager commands, UI text, or git transport |
19
+ | Infrastructure Kernel | Runtime infrastructure | Filesystem, path, template, markdown, git, date, id, and locale helpers | Own business semantics or product distribution semantics |
20
+
21
+ Always write the full name "Document Contract Kernel" in source and docs. Do not
22
+ shorten it to a generic `kernel/` label; that collides with later runtime
23
+ refactoring work.
24
+
25
+ ## Shared Concepts
26
+
27
+ | Concept | Kernel semantic | Lite expression | Full expression |
28
+ | --- | --- | --- | --- |
29
+ | Agent entry | The first project protocol an agent reads before acting | `AGENTS.md` | `AGENTS.md` plus optional `CLAUDE.md` shim |
30
+ | Project context | Durable project facts, separate from chat memory | `context/architecture`, `context/development`, `context/integrations` | Same directories, with optional source packs and generated indexes |
31
+ | Task package | The smallest reviewable unit of work for one objective | `tasks/<id>/brief.md`, `task_plan.md`, `progress.md`, `walkthrough.md` | `planning/tasks/<id>/` or module task package |
32
+ | Brief | Purpose, scope, and first-read entry for the task | Required | Required |
33
+ | Task plan | Goal, scope, steps, acceptance criteria, and verification intent | Required | Required |
34
+ | Progress evidence | Execution log with evidence references | Required, hand-maintained | Required, may be updated by lifecycle command |
35
+ | Review | Independent review or human confirmation material | Optional | Required for standard and complex work |
36
+ | Visual map | Phase, state, and structure aid | Optional for simple work | Required in CLI-created task packages |
37
+ | Walkthrough | Closeout summary, validation, residual risks, and lesson decision | Required | Required |
38
+ | Regression | The project's important validation surfaces | Simple checklist | Regression SSoT, cadence, and checks |
39
+ | Lessons | Reusable learning from the work | Optional `lessons.md` | Lesson candidates plus promoted lesson details |
40
+
41
+ ## Compatibility Matrix
42
+
43
+ Compatibility matrix version: `document-contract-kernel-v0.5`.
44
+
45
+ | Surface | Lite | Full | Kernel classification |
46
+ | --- | --- | --- | --- |
47
+ | `AGENTS.md` | Required | Required | Shared |
48
+ | `CLAUDE.md` | Optional shim | Optional shim | Shared optional |
49
+ | `context/` | Required | Required | Shared |
50
+ | `brief.md` | Required | Required | Shared |
51
+ | `task_plan.md` | Required | Required | Shared |
52
+ | `progress.md` | Required | Required | Shared |
53
+ | `walkthrough.md` | Required | Required | Shared |
54
+ | `review.md` | Optional | Required for standard and complex work | Shared with profile differences |
55
+ | `visual_map.md` | Optional for simple work | Required in CLI-created task packages | Shared with profile differences |
56
+ | `regression.md` | Simple checklist | Regression SSoT and cadence | Shared with profile differences |
57
+ | `lessons.md` | Optional simple table | Lesson candidates and promoted details | Shared with profile differences |
58
+ | `harness.yaml` | Forbidden | Required | Full-only |
59
+ | Generated ledger | Forbidden | Supported | Full-only |
60
+ | Dashboard / Workbench | Forbidden | Supported | Full-only |
61
+ | Preset | Forbidden | Supported | Full-only |
62
+ | Module Registry | Forbidden | Supported | Full-only |
63
+ | Lifecycle CLI commands | Forbidden | Supported | Full-only |
64
+ | `npm install` / `npx coding-agent-harness` | Forbidden | Allowed with user consent | Full-only |
65
+ | Node.js version requirement | Forbidden | Required by the source package and runtime | Full-only |
66
+
67
+ ## Change Classification
68
+
69
+ Every PR or task that edits Skill, template, or public product docs must be
70
+ classified before implementation.
71
+
72
+ | Change type | Definition | Must sync | Must not do |
73
+ | --- | --- | --- | --- |
74
+ | Kernel change | Changes the base semantics of AGENTS, context, task package, progress, walkthrough, review, regression, or lessons | Lite overlay, Full overlay, and this compatibility matrix | Update only the Full Skill |
75
+ | Full-only change | CLI, Dashboard, Preset, module registry, generated ledger, transaction, migration, or runtime automation | Full Skill, runtime docs, and Full overlay | Leak into Lite source |
76
+ | Lite-only change | Document-only scaffold, lower cognitive load wording, and hand-maintained task material | Lite overlay | Weaken Full audit or automation requirements |
77
+ | Migration bridge | Maps Lite project material into a Full Harness project | Full migration docs and Lite upgrade note | Promise that Lite supports Full surfaces in place |
78
+
79
+ PR checklist:
80
+
81
+ - [ ] Does this change alter the Document Contract Kernel?
82
+ - [ ] If yes, did Lite and Full overlays both change?
83
+ - [ ] If yes, did the compatibility matrix version or content change?
84
+ - [ ] If Full-only, does the Lite forbidden-surface check still pass?
85
+ - [ ] If Lite-only, did Full retain its review, regression, and automation requirements?
86
+
87
+ ## Lite Forbidden Surfaces
88
+
89
+ Lite is a document-only Skill surface. It must not contain product or runtime
90
+ surfaces that imply package installation, CLI operation, dashboard operation,
91
+ preset execution, generated governance, module registry ownership, lifecycle
92
+ commands, or a Node.js runtime requirement.
93
+
94
+ The canonical blocked pattern list is
95
+ `docs-release/architecture/document-contract-kernel/products/lite-forbidden-surfaces.txt`.
96
+ Run the guard with:
97
+
98
+ ```bash
99
+ node scripts/check-lite-forbidden-surfaces.mts
100
+ ```
101
+
102
+ The guard scans Lite product source files only. It intentionally does not scan
103
+ this contract document or the forbidden pattern list, because those files must
104
+ name Full-only surfaces to define the boundary.
105
+
106
+ ## Lite to Full Upgrade Path
107
+
108
+ A Lite project can be used as migration input for Full Harness adoption. Lite
109
+ does not promise that Full runtime adapters can read or update its files in
110
+ place.
111
+
112
+ 1. Read Lite `AGENTS.md`, `context/`, `tasks/`, `regression.md`, and `lessons.md`.
113
+ 2. Create the Full harness manifest and v2 directory structure.
114
+ 3. Map `tasks/<id>/` into Full `planning/tasks/<id>/`.
115
+ 4. If `review.md` or `visual_map.md` is missing, create adoption-needed follow-up
116
+ work or fill it within an approved migration budget.
117
+ 5. Project Lite `regression.md` into Regression SSoT.
118
+ 6. Project Lite `lessons.md` into lesson candidates, not promoted lesson details.
119
+ 7. Run Full migration and check evidence before claiming Full adoption.
120
+
121
+ ## Source, Overlay, Generator Path
122
+
123
+ The maintainable target is shared source plus product overlays:
124
+
125
+ ```text
126
+ docs-release/architecture/document-contract-kernel/
127
+ README.md
128
+ products/
129
+ lite-skill-overlay.md
130
+ full-skill-overlay.md
131
+ lite-forbidden-surfaces.txt
132
+ ```
133
+
134
+ Future generator shape:
135
+
136
+ 1. Render this shared Document Contract Kernel source.
137
+ 2. Apply the Full or Lite product overlay.
138
+ 3. Stamp the compatibility matrix version into the generated Skill.
139
+ 4. Run Lite forbidden-surface checks after Lite render.
140
+ 5. Run Full concept coverage checks after Full render.
141
+
142
+ Generated targets should be:
143
+
144
+ ```text
145
+ SKILL.md
146
+ skills/coding-agent-harness-lite/SKILL.md
147
+ ```
148
+
149
+ The Lite target is not created in Phase 0.5. This phase establishes the public
150
+ contract and drift guard that a later Lite implementation must use.
@@ -0,0 +1,29 @@
1
+ # Full Skill Overlay Source
2
+
3
+ Compatibility matrix version: `document-contract-kernel-v0.5`.
4
+
5
+ The Full Skill keeps all Document Contract Kernel concepts and adds Full-only
6
+ automation, governance, migration, and runtime surfaces. Full must not copy or
7
+ fork the shared task semantics by hand.
8
+
9
+ ## Shared Kernel Dependency
10
+
11
+ Full task packages, context documents, progress evidence, reviews,
12
+ walkthroughs, regression records, and lessons must stay compatible with the
13
+ Document Contract Kernel compatibility matrix.
14
+
15
+ ## Full-only Surfaces
16
+
17
+ Full-only sections may describe package installation, CLI commands, Dashboard,
18
+ Workbench, Preset behavior, generated ledger files, Module Registry, lifecycle
19
+ commands, runtime checks, and source package requirements.
20
+
21
+ These sections must remain explicitly Full-only so later Lite generation can
22
+ exclude them without weakening Full's audit requirements.
23
+
24
+ ## Coverage Rule
25
+
26
+ When a Full Skill edit changes the semantics of AGENTS, context, task package,
27
+ progress evidence, review, walkthrough, regression, or lessons, classify it as a
28
+ Kernel change and update the shared contract plus the Lite overlay in the same
29
+ task.
@@ -0,0 +1,26 @@
1
+ # Lines are regex patterns matched case-insensitively against Lite product source.
2
+ # The guard scans Lite source and generated Lite Skill files, not this list.
3
+ literal:npm install
4
+ regex:\bnpx\s+(?:--yes\s+)?coding-agent-harness\b
5
+ regex:\bharness\s+init\b
6
+ regex:\bharness\s+dev\b
7
+ regex:\bharness\s+check\b
8
+ regex:\bharness\s+(?:new-task|task-start|task-log|task-block|task-review|review-confirm|task-complete|lesson-promote|task-list)\b
9
+ literal:harness.yaml
10
+ literal:Dashboard
11
+ literal:Workbench
12
+ literal:Preset
13
+ literal:preset-creator
14
+ regex:generated\s+ledger
15
+ regex:generated\s+governance
16
+ regex:generated\s+indexes?
17
+ literal:Closeout-Index
18
+ literal:Module-Registry
19
+ literal:Module Registry
20
+ regex:lifecycle\s+CLI\s+commands?
21
+ regex:CLI\s+(?:checks?|commands?|operation|automation)
22
+ literal:Node.js version requirement
23
+ regex:node\s+version\s+requirement
24
+ regex:\bTaskRepository\b
25
+ regex:\bTaskOperations\b
26
+ regex:\bHarnessTransaction\b
@@ -0,0 +1,37 @@
1
+ # Lite Skill Overlay Source
2
+
3
+ Compatibility matrix version: `document-contract-kernel-v0.5`.
4
+
5
+ This source is for a future document-only Lite Skill. Lite keeps the shared
6
+ Document Contract Kernel concepts and removes runtime product surfaces.
7
+
8
+ ## Positioning
9
+
10
+ Lite helps an agent set up and maintain a small project work protocol through
11
+ plain repository documents. It is document-only: the agent reads, writes, and
12
+ reviews project files directly.
13
+
14
+ ## Required Lite Surfaces
15
+
16
+ - `AGENTS.md` as the agent entry protocol.
17
+ - `context/` for stable project facts.
18
+ - `tasks/` for reviewable task packages.
19
+ - `brief.md`, `task_plan.md`, `progress.md`, and `walkthrough.md` in each task.
20
+ - Optional `review.md`, `visual_map.md`, `regression.md`, and `lessons.md` when
21
+ the project needs them.
22
+
23
+ ## Lite Operating Rules
24
+
25
+ - Keep all state human-readable and hand-maintainable.
26
+ - Do not require a project manifest.
27
+ - Do not require machine-produced project state.
28
+ - Treat missing review or visual material as adoption-needed if the project
29
+ later moves to the larger product.
30
+ - Keep upgrade notes short and link back to the compatibility matrix version.
31
+
32
+ ## Upgrade Note
33
+
34
+ If the project later needs the larger Full Coding Agent Harness product, keep the
35
+ Lite documents as migration input. The shared document semantics are preserved so
36
+ an agent can map Lite task packages and context into the Full structure during an
37
+ explicit migration task.
@@ -118,7 +118,7 @@ flowchart LR
118
118
  CLI --> Status["status / check<br/>derive health and failures"]
119
119
  CLI --> Dashboard["dashboard / dev<br/>render human-readable state"]
120
120
  CLI --> Migration["migrate-plan / migrate-run / migrate-verify<br/>legacy project adoption"]
121
- CLI --> Task["new-task / task-* / review-confirm<br/>task lifecycle operations"]
121
+ CLI --> Task["new-task / task-*<br/>task lifecycle operations"]
122
122
  CLI --> UserSkill["install-user / doctor-user<br/>local skill setup"]
123
123
 
124
124
  Status --> Scanner["task scanner + check profiles"]
@@ -168,7 +168,7 @@ stateDiagram-v2
168
168
  active --> in_review: task-review
169
169
  in_review --> review_blocked: open P0-P2 finding
170
170
  review_blocked --> in_review: finding closed or routed
171
- in_review --> closing: review-confirm + task-complete
171
+ in_review --> closing: Workbench confirmation + task-complete
172
172
  closing --> closed: closeout evidence linked
173
173
  closed --> [*]
174
174
  ```
@@ -105,7 +105,7 @@ flowchart LR
105
105
  CLI --> Status["status / check<br/>推导健康状态与失败项"]
106
106
  CLI --> Dashboard["dashboard / dev<br/>渲染可读状态"]
107
107
  CLI --> Migration["migrate-plan / migrate-run / migrate-verify<br/>旧项目迁移"]
108
- CLI --> Task["new-task / task-* / review-confirm<br/>任务生命周期操作"]
108
+ CLI --> Task["new-task / task-*<br/>任务生命周期操作"]
109
109
  CLI --> UserSkill["install-user / doctor-user<br/>本机 Skill 设置"]
110
110
 
111
111
  Status --> Scanner["任务扫描器 + check profiles"]
@@ -153,7 +153,7 @@ stateDiagram-v2
153
153
  active --> in_review: task-review
154
154
  in_review --> review_blocked: 存在 P0-P2 finding
155
155
  review_blocked --> in_review: finding 关闭或路由
156
- in_review --> closing: review-confirm + task-complete
156
+ in_review --> closing: Workbench 人工确认 + task-complete
157
157
  closing --> closed: 收口证据已链接
158
158
  closed --> [*]
159
159
  ```