agentplane 0.3.5 → 0.3.7

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 (256) hide show
  1. package/README.md +103 -75
  2. package/assets/AGENTS.md +4 -2
  3. package/bin/dist-guard.js +13 -3
  4. package/bin/runtime-watch.d.ts +1 -0
  5. package/bin/runtime-watch.js +22 -5
  6. package/bin/stale-dist-policy.js +9 -2
  7. package/dist/.build-manifest.json +251 -821
  8. package/dist/adapters/task-backend/task-backend-adapter.d.ts +2 -2
  9. package/dist/adapters/task-backend/task-backend-adapter.d.ts.map +1 -1
  10. package/dist/adapters/task-backend/task-backend-adapter.js +2 -2
  11. package/dist/backends/task-backend/local-backend.d.ts +7 -5
  12. package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
  13. package/dist/backends/task-backend/local-backend.js +79 -7
  14. package/dist/backends/task-backend/redmine/env.d.ts +1 -1
  15. package/dist/backends/task-backend/redmine/env.d.ts.map +1 -1
  16. package/dist/backends/task-backend/redmine/env.js +3 -0
  17. package/dist/backends/task-backend/redmine/inspect.d.ts +11 -0
  18. package/dist/backends/task-backend/redmine/inspect.d.ts.map +1 -0
  19. package/dist/backends/task-backend/redmine/inspect.js +75 -0
  20. package/dist/backends/task-backend/redmine/mapping.d.ts.map +1 -1
  21. package/dist/backends/task-backend/redmine/mapping.js +21 -2
  22. package/dist/backends/task-backend/redmine/state.d.ts +17 -0
  23. package/dist/backends/task-backend/redmine/state.d.ts.map +1 -0
  24. package/dist/backends/task-backend/redmine/state.js +95 -0
  25. package/dist/backends/task-backend/redmine-backend.d.ts +10 -16
  26. package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
  27. package/dist/backends/task-backend/redmine-backend.js +205 -15
  28. package/dist/backends/task-backend/shared/constants.d.ts +1 -1
  29. package/dist/backends/task-backend/shared/constants.js +1 -1
  30. package/dist/backends/task-backend/shared/record.d.ts.map +1 -1
  31. package/dist/backends/task-backend/shared/record.js +20 -1
  32. package/dist/backends/task-backend/shared/types.d.ts +42 -4
  33. package/dist/backends/task-backend/shared/types.d.ts.map +1 -1
  34. package/dist/backends/task-backend/shared.d.ts +1 -1
  35. package/dist/backends/task-backend/shared.d.ts.map +1 -1
  36. package/dist/backends/task-backend.d.ts +1 -1
  37. package/dist/backends/task-backend.d.ts.map +1 -1
  38. package/dist/backends/task-backend.test-helpers.d.ts +4 -0
  39. package/dist/backends/task-backend.test-helpers.d.ts.map +1 -0
  40. package/dist/backends/task-backend.test-helpers.js +33 -0
  41. package/dist/backends/task-index.d.ts.map +1 -1
  42. package/dist/backends/task-index.js +1 -0
  43. package/dist/cli/bootstrap-guide.d.ts.map +1 -1
  44. package/dist/cli/bootstrap-guide.js +1 -0
  45. package/dist/cli/command-guide.d.ts.map +1 -1
  46. package/dist/cli/command-guide.js +3 -2
  47. package/dist/cli/reason-codes.d.ts.map +1 -1
  48. package/dist/cli/reason-codes.js +30 -0
  49. package/dist/cli/run-cli/command-catalog/core.d.ts +3 -0
  50. package/dist/cli/run-cli/command-catalog/core.d.ts.map +1 -0
  51. package/dist/cli/run-cli/command-catalog/core.js +137 -0
  52. package/dist/cli/run-cli/command-catalog/lifecycle.d.ts +3 -0
  53. package/dist/cli/run-cli/command-catalog/lifecycle.d.ts.map +1 -0
  54. package/dist/cli/run-cli/command-catalog/lifecycle.js +52 -0
  55. package/dist/cli/run-cli/command-catalog/project.d.ts +3 -0
  56. package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -0
  57. package/dist/cli/run-cli/command-catalog/project.js +80 -0
  58. package/dist/cli/run-cli/command-catalog/shared.d.ts +19 -0
  59. package/dist/cli/run-cli/command-catalog/shared.d.ts.map +1 -0
  60. package/dist/cli/run-cli/command-catalog/shared.js +9 -0
  61. package/dist/cli/run-cli/command-catalog/task.d.ts +3 -0
  62. package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -0
  63. package/dist/cli/run-cli/command-catalog/task.js +85 -0
  64. package/dist/cli/run-cli/command-catalog.d.ts +3 -18
  65. package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
  66. package/dist/cli/run-cli/command-catalog.js +8 -337
  67. package/dist/cli/run-cli/commands/ide.d.ts.map +1 -1
  68. package/dist/cli/run-cli/commands/ide.js +64 -2
  69. package/dist/cli/run-cli/commands/init/ui.d.ts.map +1 -1
  70. package/dist/cli/run-cli/commands/init/ui.js +33 -13
  71. package/dist/cli/run-cli/commands/init/write-env.d.ts.map +1 -1
  72. package/dist/cli/run-cli/commands/init/write-env.js +12 -0
  73. package/dist/cli/run-cli.core.pr-flow.test-helpers.d.ts +3 -0
  74. package/dist/cli/run-cli.core.pr-flow.test-helpers.d.ts.map +1 -0
  75. package/dist/cli/run-cli.core.pr-flow.test-helpers.js +41 -0
  76. package/dist/cli/run-cli.core.tasks.test-helpers.d.ts +2 -0
  77. package/dist/cli/run-cli.core.tasks.test-helpers.d.ts.map +1 -0
  78. package/dist/cli/run-cli.core.tasks.test-helpers.js +6 -0
  79. package/dist/cli/run-cli.test-helpers.d.ts +3 -0
  80. package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
  81. package/dist/cli/run-cli.test-helpers.js +140 -6
  82. package/dist/commands/backend/sync.command.d.ts +5 -1
  83. package/dist/commands/backend/sync.command.d.ts.map +1 -1
  84. package/dist/commands/backend/sync.command.js +67 -3
  85. package/dist/commands/backend.d.ts +22 -0
  86. package/dist/commands/backend.d.ts.map +1 -1
  87. package/dist/commands/backend.js +110 -1
  88. package/dist/commands/commit.spec.d.ts.map +1 -1
  89. package/dist/commands/commit.spec.js +31 -7
  90. package/dist/commands/doctor/runtime.d.ts.map +1 -1
  91. package/dist/commands/doctor/runtime.js +3 -6
  92. package/dist/commands/doctor/workspace.d.ts +8 -0
  93. package/dist/commands/doctor/workspace.d.ts.map +1 -1
  94. package/dist/commands/doctor/workspace.js +127 -3
  95. package/dist/commands/guard/commit.command.d.ts.map +1 -1
  96. package/dist/commands/guard/commit.command.js +30 -6
  97. package/dist/commands/guard/impl/allow.d.ts +9 -0
  98. package/dist/commands/guard/impl/allow.d.ts.map +1 -1
  99. package/dist/commands/guard/impl/allow.js +26 -10
  100. package/dist/commands/guard/impl/commands.d.ts.map +1 -1
  101. package/dist/commands/guard/impl/commands.js +146 -18
  102. package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
  103. package/dist/commands/guard/impl/comment-commit.js +2 -0
  104. package/dist/commands/hooks/index.d.ts.map +1 -1
  105. package/dist/commands/hooks/index.js +8 -35
  106. package/dist/commands/recipes/impl/apply.d.ts +4 -0
  107. package/dist/commands/recipes/impl/apply.d.ts.map +1 -1
  108. package/dist/commands/recipes/impl/apply.js +34 -0
  109. package/dist/commands/recipes/impl/commands/explain.d.ts.map +1 -1
  110. package/dist/commands/recipes/impl/commands/explain.js +70 -11
  111. package/dist/commands/recipes/impl/commands/info.d.ts.map +1 -1
  112. package/dist/commands/recipes/impl/commands/info.js +24 -12
  113. package/dist/commands/recipes/impl/commands/install.d.ts.map +1 -1
  114. package/dist/commands/recipes/impl/commands/install.js +32 -36
  115. package/dist/commands/recipes/impl/commands/list.d.ts.map +1 -1
  116. package/dist/commands/recipes/impl/commands/list.js +7 -4
  117. package/dist/commands/recipes/impl/commands/remove.d.ts.map +1 -1
  118. package/dist/commands/recipes/impl/commands/remove.js +9 -11
  119. package/dist/commands/recipes/impl/constants.d.ts +2 -0
  120. package/dist/commands/recipes/impl/constants.d.ts.map +1 -1
  121. package/dist/commands/recipes/impl/constants.js +2 -0
  122. package/dist/commands/recipes/impl/manifest.d.ts.map +1 -1
  123. package/dist/commands/recipes/impl/manifest.js +219 -23
  124. package/dist/commands/recipes/impl/normalize.d.ts +3 -0
  125. package/dist/commands/recipes/impl/normalize.d.ts.map +1 -1
  126. package/dist/commands/recipes/impl/normalize.js +28 -24
  127. package/dist/commands/recipes/impl/paths.d.ts +9 -0
  128. package/dist/commands/recipes/impl/paths.d.ts.map +1 -1
  129. package/dist/commands/recipes/impl/paths.js +10 -1
  130. package/dist/commands/recipes/impl/project-installed-recipes.d.ts +7 -0
  131. package/dist/commands/recipes/impl/project-installed-recipes.d.ts.map +1 -0
  132. package/dist/commands/recipes/impl/project-installed-recipes.js +102 -0
  133. package/dist/commands/recipes/impl/resolver.d.ts +20 -0
  134. package/dist/commands/recipes/impl/resolver.d.ts.map +1 -0
  135. package/dist/commands/recipes/impl/resolver.js +220 -0
  136. package/dist/commands/recipes/impl/scenario.d.ts.map +1 -1
  137. package/dist/commands/recipes/impl/scenario.js +40 -11
  138. package/dist/commands/recipes/impl/types.d.ts +145 -16
  139. package/dist/commands/recipes/impl/types.d.ts.map +1 -1
  140. package/dist/commands/recipes/install.spec.d.ts.map +1 -1
  141. package/dist/commands/recipes/install.spec.js +3 -2
  142. package/dist/commands/recipes.d.ts +6 -4
  143. package/dist/commands/recipes.d.ts.map +1 -1
  144. package/dist/commands/recipes.js +5 -3
  145. package/dist/commands/recipes.test-helpers.d.ts +185 -0
  146. package/dist/commands/recipes.test-helpers.d.ts.map +1 -0
  147. package/dist/commands/recipes.test-helpers.js +339 -0
  148. package/dist/commands/scenario/impl/commands.d.ts.map +1 -1
  149. package/dist/commands/scenario/impl/commands.js +192 -336
  150. package/dist/commands/scenario/info.command.d.ts.map +1 -1
  151. package/dist/commands/scenario/info.command.js +7 -2
  152. package/dist/commands/scenario/list.command.js +2 -2
  153. package/dist/commands/scenario/run.command.d.ts.map +1 -1
  154. package/dist/commands/scenario/run.command.js +7 -2
  155. package/dist/commands/shared/reconcile-check.d.ts.map +1 -1
  156. package/dist/commands/shared/reconcile-check.js +77 -2
  157. package/dist/commands/shared/task-backend.d.ts +1 -1
  158. package/dist/commands/shared/task-backend.d.ts.map +1 -1
  159. package/dist/commands/shared/task-backend.js +9 -0
  160. package/dist/commands/shared/task-store.d.ts +92 -2
  161. package/dist/commands/shared/task-store.d.ts.map +1 -1
  162. package/dist/commands/shared/task-store.js +405 -43
  163. package/dist/commands/task/block.d.ts.map +1 -1
  164. package/dist/commands/task/block.js +84 -46
  165. package/dist/commands/task/close-duplicate.d.ts.map +1 -1
  166. package/dist/commands/task/close-duplicate.js +12 -37
  167. package/dist/commands/task/close-noop.d.ts.map +1 -1
  168. package/dist/commands/task/close-noop.js +12 -30
  169. package/dist/commands/task/close-shared.d.ts +14 -0
  170. package/dist/commands/task/close-shared.d.ts.map +1 -0
  171. package/dist/commands/task/close-shared.js +73 -0
  172. package/dist/commands/task/comment.d.ts.map +1 -1
  173. package/dist/commands/task/comment.js +34 -21
  174. package/dist/commands/task/derive.command.d.ts +1 -0
  175. package/dist/commands/task/derive.command.d.ts.map +1 -1
  176. package/dist/commands/task/derive.command.js +15 -2
  177. package/dist/commands/task/derive.d.ts +1 -0
  178. package/dist/commands/task/derive.d.ts.map +1 -1
  179. package/dist/commands/task/derive.js +27 -4
  180. package/dist/commands/task/doc-set.command.d.ts +2 -1
  181. package/dist/commands/task/doc-set.command.d.ts.map +1 -1
  182. package/dist/commands/task/doc-set.command.js +36 -4
  183. package/dist/commands/task/doc-template.d.ts.map +1 -1
  184. package/dist/commands/task/doc-template.js +2 -7
  185. package/dist/commands/task/doc.command.js +1 -1
  186. package/dist/commands/task/doc.d.ts +2 -1
  187. package/dist/commands/task/doc.d.ts.map +1 -1
  188. package/dist/commands/task/doc.js +139 -76
  189. package/dist/commands/task/finish.d.ts.map +1 -1
  190. package/dist/commands/task/finish.js +142 -80
  191. package/dist/commands/task/migrate-doc.d.ts +15 -0
  192. package/dist/commands/task/migrate-doc.d.ts.map +1 -1
  193. package/dist/commands/task/migrate-doc.js +128 -43
  194. package/dist/commands/task/new.d.ts.map +1 -1
  195. package/dist/commands/task/new.js +3 -1
  196. package/dist/commands/task/plan-set.command.js +1 -1
  197. package/dist/commands/task/plan.command.d.ts +8 -0
  198. package/dist/commands/task/plan.command.d.ts.map +1 -0
  199. package/dist/commands/task/plan.command.js +37 -0
  200. package/dist/commands/task/plan.d.ts.map +1 -1
  201. package/dist/commands/task/plan.js +198 -101
  202. package/dist/commands/task/set-status.command.d.ts.map +1 -1
  203. package/dist/commands/task/set-status.command.js +1 -1
  204. package/dist/commands/task/set-status.d.ts.map +1 -1
  205. package/dist/commands/task/set-status.js +115 -35
  206. package/dist/commands/task/shared/dependencies.d.ts +1 -0
  207. package/dist/commands/task/shared/dependencies.d.ts.map +1 -1
  208. package/dist/commands/task/shared/dependencies.js +10 -0
  209. package/dist/commands/task/shared/docs.d.ts +1 -0
  210. package/dist/commands/task/shared/docs.d.ts.map +1 -1
  211. package/dist/commands/task/shared/docs.js +8 -1
  212. package/dist/commands/task/shared/transitions.d.ts +17 -2
  213. package/dist/commands/task/shared/transitions.d.ts.map +1 -1
  214. package/dist/commands/task/shared/transitions.js +20 -13
  215. package/dist/commands/task/shared.d.ts +3 -3
  216. package/dist/commands/task/shared.d.ts.map +1 -1
  217. package/dist/commands/task/shared.js +3 -3
  218. package/dist/commands/task/start.d.ts.map +1 -1
  219. package/dist/commands/task/start.js +101 -71
  220. package/dist/commands/task/task.command.d.ts +8 -0
  221. package/dist/commands/task/task.command.d.ts.map +1 -0
  222. package/dist/commands/task/task.command.js +71 -0
  223. package/dist/commands/task/verify-command-shared.d.ts +16 -0
  224. package/dist/commands/task/verify-command-shared.d.ts.map +1 -0
  225. package/dist/commands/task/verify-command-shared.js +53 -0
  226. package/dist/commands/task/verify-ok.command.d.ts +2 -6
  227. package/dist/commands/task/verify-ok.command.d.ts.map +1 -1
  228. package/dist/commands/task/verify-ok.command.js +8 -50
  229. package/dist/commands/task/verify-record.d.ts.map +1 -1
  230. package/dist/commands/task/verify-record.js +124 -145
  231. package/dist/commands/task/verify-rework.command.d.ts +2 -6
  232. package/dist/commands/task/verify-rework.command.d.ts.map +1 -1
  233. package/dist/commands/task/verify-rework.command.js +8 -50
  234. package/dist/commands/upgrade/apply.d.ts +2 -0
  235. package/dist/commands/upgrade/apply.d.ts.map +1 -1
  236. package/dist/commands/upgrade/apply.js +33 -1
  237. package/dist/commands/upgrade.command.d.ts.map +1 -1
  238. package/dist/commands/upgrade.command.js +25 -0
  239. package/dist/commands/upgrade.d.ts +1 -0
  240. package/dist/commands/upgrade.d.ts.map +1 -1
  241. package/dist/commands/upgrade.js +34 -0
  242. package/dist/commands/verify.spec.d.ts.map +1 -1
  243. package/dist/commands/verify.spec.js +3 -12
  244. package/dist/policy/rules/allowlist.d.ts.map +1 -1
  245. package/dist/policy/rules/allowlist.js +16 -4
  246. package/dist/policy/rules/protected-paths.d.ts.map +1 -1
  247. package/dist/policy/rules/protected-paths.js +6 -1
  248. package/dist/ports/task-backend-port.d.ts +2 -2
  249. package/dist/ports/task-backend-port.d.ts.map +1 -1
  250. package/dist/shared/agent-emoji.d.ts.map +1 -1
  251. package/dist/shared/protected-paths.d.ts +17 -0
  252. package/dist/shared/protected-paths.d.ts.map +1 -1
  253. package/dist/shared/protected-paths.js +59 -10
  254. package/dist/shared/repo-cli-version.d.ts.map +1 -1
  255. package/dist/shared/repo-cli-version.js +9 -3
  256. package/package.json +2 -2
@@ -1,13 +1,14 @@
1
1
  import { readdir, readFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { atomicWriteFile, ensureDocSections, extractTaskDoc, loadConfig, mergeTaskDoc, normalizeTaskDoc, parseTaskReadme, renderTaskReadme, resolveProject, setMarkdownSection, } from "@agentplaneorg/core";
3
+ import { atomicWriteFile, ensureDocSections, extractTaskDoc, loadConfig, mergeTaskDoc, normalizeTaskDoc, parseTaskReadme, renderTaskDocFromSections, renderTaskReadme, resolveProject, setMarkdownSection, taskDocToSectionMap, } from "@agentplaneorg/core";
4
4
  import { mapCoreError } from "../../cli/error-map.js";
5
5
  import { exitCodeForError } from "../../cli/exit-codes.js";
6
6
  import { fileExists, getPathKind } from "../../cli/fs-utils.js";
7
7
  import { successMessage } from "../../cli/output.js";
8
8
  import { CliError } from "../../shared/errors.js";
9
- import { exportTaskProjectionSnapshot, loadCommandContext } from "../shared/task-backend.js";
10
- import { extractDocSection, extractTaskObservationSection, normalizeTaskDocVersion, normalizeVerificationSectionLayout, } from "./shared/docs.js";
9
+ import { execFileAsync, gitEnv } from "../shared/git.js";
10
+ import { exportTaskProjectionSnapshot, loadCommandContext, } from "../shared/task-backend.js";
11
+ import { extractDocSection, extractTaskObservationSection, decodeEscapedTaskTextNewlines, normalizeTaskDocVersion, normalizeVerificationSectionLayout, } from "./shared/docs.js";
11
12
  import { defaultTaskDocV3 } from "./doc-template.js";
12
13
  const V3_CANONICAL_ORDER = [
13
14
  "Summary",
@@ -22,6 +23,21 @@ const HUMAN_TEXT_SECTIONS = new Set(["summary", "context", "scope", "plan", "fin
22
23
  function isRecord(value) {
23
24
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
24
25
  }
26
+ function normalizeRevision(value) {
27
+ return Number.isInteger(value) && typeof value === "number" && value > 0 ? value : null;
28
+ }
29
+ function normalizeCanonicalSections(value) {
30
+ if (!isRecord(value))
31
+ return null;
32
+ const out = {};
33
+ for (const [title, text] of Object.entries(value)) {
34
+ const normalizedTitle = title.trim();
35
+ if (!normalizedTitle || typeof text !== "string")
36
+ continue;
37
+ out[normalizedTitle] = text.replaceAll("\r\n", "\n").trimEnd();
38
+ }
39
+ return Object.keys(out).length > 0 ? out : null;
40
+ }
25
41
  function normalizeSectionKey(section) {
26
42
  return section.trim().replaceAll(/\s+/g, " ").toLowerCase();
27
43
  }
@@ -61,13 +77,7 @@ function renderMarkdownSections(sections) {
61
77
  function normalizeLiteralNewlinesInHumanSection(title, text) {
62
78
  if (!HUMAN_TEXT_SECTIONS.has(normalizeSectionKey(title)))
63
79
  return text.trimEnd();
64
- let next = text.replaceAll("\r\n", "\n");
65
- const escapedDoubleNewline = next.includes(String.raw `\n\n`) || next.includes(String.raw `\r\n\r\n`);
66
- const escapedNewlineMatches = next.match(/\\n/g) ?? [];
67
- if (escapedDoubleNewline || escapedNewlineMatches.length >= 2) {
68
- next = next.replaceAll(String.raw `\r\n`, "\n").replaceAll(String.raw `\n`, "\n");
69
- }
70
- return next.trimEnd();
80
+ return decodeEscapedTaskTextNewlines(text).trimEnd();
71
81
  }
72
82
  function firstSectionText(sections, title) {
73
83
  const target = normalizeSectionKey(title);
@@ -183,9 +193,12 @@ async function migrateTaskReadmeDoc(opts) {
183
193
  ensurePlanApprovalFrontmatter(frontmatter);
184
194
  ensureVerificationFrontmatter(frontmatter);
185
195
  normalizeFrontmatterNoteTimestamps(frontmatter);
196
+ const canonicalSections = normalizeCanonicalSections(frontmatter.sections);
186
197
  const required = opts.config.tasks.doc.required_sections;
187
198
  const extracted = extractTaskDoc(parsed.body);
188
- const baseDoc = extracted || parsed.body;
199
+ const baseDoc = canonicalSections === null
200
+ ? extracted || parsed.body
201
+ : renderTaskDocFromSections(canonicalSections);
189
202
  let nextDoc = normalizeTaskDoc(ensureDocSections(baseDoc, required));
190
203
  const docVersion = normalizeTaskDocVersion(frontmatter.doc_version);
191
204
  if (docVersion === 2) {
@@ -208,6 +221,8 @@ async function migrateTaskReadmeDoc(opts) {
208
221
  }
209
222
  }
210
223
  const nextBody = extracted ? mergeTaskDoc(parsed.body, nextDoc) : nextDoc;
224
+ frontmatter.sections = taskDocToSectionMap(nextDoc);
225
+ frontmatter.revision = normalizeRevision(frontmatter.revision) ?? 1;
211
226
  const rendered = renderTaskReadme(frontmatter, nextBody);
212
227
  const next = rendered.endsWith("\n") ? rendered : `${rendered}\n`;
213
228
  if (next === original)
@@ -232,48 +247,118 @@ async function resolveReadmePaths(opts) {
232
247
  }
233
248
  return out;
234
249
  }
235
- export async function cmdTaskMigrateDoc(opts) {
236
- const params = { all: opts.all, quiet: opts.quiet, taskIds: opts.taskIds };
250
+ async function exportProjectionSnapshotIfChanged(opts) {
251
+ if (!(opts.ctx.taskBackend.exportProjectionSnapshot || opts.ctx.taskBackend.exportTasksJson)) {
252
+ return [];
253
+ }
254
+ const relOutputPath = opts.tasksPath.replaceAll("\\", "/");
255
+ const outputPath = path.join(opts.resolvedGitRoot, relOutputPath);
256
+ let before = null;
257
+ try {
258
+ before = await readFile(outputPath, "utf8");
259
+ }
260
+ catch {
261
+ before = null;
262
+ }
263
+ await exportTaskProjectionSnapshot({ ctx: opts.ctx, outputPath });
264
+ let after = null;
265
+ try {
266
+ after = await readFile(outputPath, "utf8");
267
+ }
268
+ catch {
269
+ after = null;
270
+ }
271
+ if (before === after)
272
+ return [];
273
+ return (await canStageGitPath(opts.resolvedGitRoot, relOutputPath)) ? [relOutputPath] : [];
274
+ }
275
+ async function canStageGitPath(gitRoot, relPath) {
237
276
  try {
238
- const resolved = await resolveProject({
277
+ await execFileAsync("git", ["ls-files", "--error-unmatch", "--", relPath], {
278
+ cwd: gitRoot,
279
+ env: gitEnv(),
280
+ });
281
+ return true;
282
+ }
283
+ catch {
284
+ // Continue below: untracked paths may still be stageable when they are not ignored.
285
+ }
286
+ try {
287
+ await execFileAsync("git", ["check-ignore", "--quiet", "--", relPath], {
288
+ cwd: gitRoot,
289
+ env: gitEnv(),
290
+ });
291
+ return false;
292
+ }
293
+ catch {
294
+ return true;
295
+ }
296
+ }
297
+ export async function migrateTaskDocsInWorkspace(opts) {
298
+ const resolved = opts.resolvedProject ??
299
+ (await resolveProject({
239
300
  cwd: opts.cwd,
240
301
  rootOverride: opts.rootOverride ?? null,
241
- });
242
- const loaded = await loadConfig(resolved.agentplaneDir);
243
- const ctx = await loadCommandContext({
302
+ }));
303
+ let config = opts.config;
304
+ if (!config) {
305
+ const loadedConfig = await loadConfig(resolved.agentplaneDir);
306
+ config = loadedConfig.config;
307
+ }
308
+ const ctx = opts.ctx ??
309
+ (await loadCommandContext({
244
310
  cwd: opts.cwd,
245
311
  rootOverride: opts.rootOverride ?? null,
246
312
  resolvedProject: resolved,
247
- config: loaded.config,
248
- });
249
- const tasksDir = path.join(resolved.gitRoot, loaded.config.paths.workflow_dir);
250
- const readmePaths = await resolveReadmePaths({ tasksDir, params });
251
- if (!params.all) {
252
- for (const readmePath of readmePaths) {
253
- if (!(await fileExists(readmePath))) {
254
- const taskId = path.basename(path.dirname(readmePath));
255
- throw new CliError({
256
- exitCode: exitCodeForError("E_IO"),
257
- code: "E_IO",
258
- message: `Task README not found: ${taskId}`,
259
- });
260
- }
261
- }
262
- }
263
- let changed = 0;
313
+ config,
314
+ }));
315
+ const params = { all: opts.all, quiet: false, taskIds: opts.taskIds };
316
+ const tasksDir = path.join(resolved.gitRoot, config.paths.workflow_dir);
317
+ const readmePaths = await resolveReadmePaths({ tasksDir, params });
318
+ if (!opts.all) {
264
319
  for (const readmePath of readmePaths) {
265
- const res = await migrateTaskReadmeDoc({ readmePath, config: loaded.config });
266
- if (res.changed)
267
- changed += 1;
320
+ if (!(await fileExists(readmePath))) {
321
+ const taskId = path.basename(path.dirname(readmePath));
322
+ throw new CliError({
323
+ exitCode: exitCodeForError("E_IO"),
324
+ code: "E_IO",
325
+ message: `Task README not found: ${taskId}`,
326
+ });
327
+ }
268
328
  }
269
- // Refresh the local export snapshot so doctor and other snapshot-based checks
270
- // immediately observe the migrated README contract without a separate task export.
271
- if (ctx.taskBackend.exportProjectionSnapshot || ctx.taskBackend.exportTasksJson) {
272
- const outPath = path.join(resolved.gitRoot, loaded.config.paths.tasks_path);
273
- await exportTaskProjectionSnapshot({ ctx, outputPath: outPath });
329
+ }
330
+ let changed = 0;
331
+ const changedPaths = [];
332
+ for (const readmePath of readmePaths) {
333
+ const res = await migrateTaskReadmeDoc({ readmePath, config });
334
+ if (!res.changed)
335
+ continue;
336
+ changed += 1;
337
+ const relReadmePath = path.relative(resolved.gitRoot, readmePath).replaceAll("\\", "/");
338
+ if (await canStageGitPath(resolved.gitRoot, relReadmePath)) {
339
+ changedPaths.push(relReadmePath);
274
340
  }
341
+ }
342
+ if (changed > 0) {
343
+ changedPaths.push(...(await exportProjectionSnapshotIfChanged({
344
+ ctx,
345
+ resolvedGitRoot: resolved.gitRoot,
346
+ tasksPath: config.paths.tasks_path,
347
+ })));
348
+ }
349
+ return { changed, changedPaths: [...new Set(changedPaths)] };
350
+ }
351
+ export async function cmdTaskMigrateDoc(opts) {
352
+ const params = { all: opts.all, quiet: opts.quiet, taskIds: opts.taskIds };
353
+ try {
354
+ const result = await migrateTaskDocsInWorkspace({
355
+ cwd: opts.cwd,
356
+ rootOverride: opts.rootOverride ?? null,
357
+ all: params.all,
358
+ taskIds: params.taskIds,
359
+ });
275
360
  if (!params.quiet) {
276
- process.stdout.write(`${successMessage("migrated task docs", undefined, `changed=${changed}`)}\n`);
361
+ process.stdout.write(`${successMessage("migrated task docs", undefined, `changed=${result.changed}`)}\n`);
277
362
  }
278
363
  return 0;
279
364
  }
@@ -1 +1 @@
1
- {"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/commands/task/new.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAcpF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IAC5C,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAmDF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,aAAa,CAAC;CACvB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgFlB"}
1
+ {"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/commands/task/new.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAcpF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IAC5C,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAmDF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,aAAa,CAAC;CACvB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmFlB"}
@@ -1,4 +1,4 @@
1
- import { setMarkdownSection } from "@agentplaneorg/core";
1
+ import { setMarkdownSection, taskDocToSectionMap } from "@agentplaneorg/core";
2
2
  import { mapBackendError } from "../../cli/error-map.js";
3
3
  import { backendNotSupportedMessage, warnMessage } from "../../cli/output.js";
4
4
  import { CliError } from "../../shared/errors.js";
@@ -73,6 +73,7 @@ export async function runTaskNewParsed(opts) {
73
73
  status: "TODO",
74
74
  priority: p.priority,
75
75
  owner: p.owner,
76
+ revision: 1,
76
77
  tags: p.tags,
77
78
  depends_on: p.dependsOn,
78
79
  verify: p.verify,
@@ -107,6 +108,7 @@ export async function runTaskNewParsed(opts) {
107
108
  if (hasSpike && hasImplementationTags) {
108
109
  process.stderr.write(`${warnMessage("spike is combined with a primary tag that requires verify steps; consider splitting spike vs implementation tasks")}\n`);
109
110
  }
111
+ task.sections = taskDocToSectionMap(task.doc ?? "");
110
112
  await ctx.taskBackend.writeTask(task);
111
113
  process.stdout.write(`${taskId}\n`);
112
114
  return 0;
@@ -10,7 +10,7 @@ export const taskPlanSetSpec = {
10
10
  kind: "string",
11
11
  name: "text",
12
12
  valueHint: "<text>",
13
- description: "Plan text to write into the task README Plan section.",
13
+ description: String.raw `Plan text to write into the task README Plan section. Literal escaped newlines (\n) are normalized for inline text.`,
14
14
  },
15
15
  {
16
16
  kind: "string",
@@ -0,0 +1,8 @@
1
+ import type { CommandHandler, CommandSpec } from "../../cli/spec/spec.js";
2
+ type TaskPlanGroupParsed = {
3
+ cmd: string[];
4
+ };
5
+ export declare const taskPlanSpec: CommandSpec<TaskPlanGroupParsed>;
6
+ export declare const runTaskPlan: CommandHandler<TaskPlanGroupParsed>;
7
+ export {};
8
+ //# sourceMappingURL=plan.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/plan.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAItF,KAAK,mBAAmB,GAAG;IAAE,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAI7C,eAAO,MAAM,YAAY,EAAE,WAAW,CAAC,mBAAmB,CAqBzD,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,cAAc,CAAC,mBAAmB,CAW3D,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { usageError } from "../../cli/spec/errors.js";
2
+ import { suggestOne } from "../../cli/spec/suggest.js";
3
+ const TASK_PLAN_SUBCOMMANDS = ["set", "approve", "reject"];
4
+ export const taskPlanSpec = {
5
+ id: ["task", "plan"],
6
+ group: "Task",
7
+ summary: "Task plan commands (set/approve/reject).",
8
+ synopsis: ["agentplane task plan <set|approve|reject> [args] [options]"],
9
+ args: [{ name: "cmd", required: false, variadic: true, valueHint: "<subcommand>" }],
10
+ examples: [
11
+ {
12
+ cmd: 'agentplane task plan set <task-id> --text "..." --updated-by ORCHESTRATOR',
13
+ why: "Write or replace the task plan.",
14
+ },
15
+ {
16
+ cmd: "agentplane task plan approve <task-id> --by ORCHESTRATOR",
17
+ why: "Approve the current task plan.",
18
+ },
19
+ {
20
+ cmd: 'agentplane task plan reject <task-id> --by ORCHESTRATOR --note "..."',
21
+ why: "Reject the current task plan with a note.",
22
+ },
23
+ ],
24
+ parse: (raw) => ({ cmd: (raw.args.cmd ?? []) }),
25
+ };
26
+ export const runTaskPlan = (_ctx, p) => {
27
+ const input = p.cmd.join(" ");
28
+ const suggestion = suggestOne(input, [...TASK_PLAN_SUBCOMMANDS]);
29
+ const suffix = suggestion ? ` Did you mean: ${suggestion}?` : "";
30
+ const message = p.cmd.length === 0 ? "Missing subcommand." : `Unknown subcommand: ${p.cmd[0]}.`;
31
+ throw usageError({
32
+ spec: taskPlanSpec,
33
+ command: "task plan",
34
+ message: `${message}${suffix}`,
35
+ context: { command: "task plan" },
36
+ });
37
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/commands/task/plan.ts"],"names":[],"mappings":"AASA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAuDnC,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6ElB;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,MAAM,CAAC,CA4FlB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,MAAM,CAAC,CAuDlB"}
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/commands/task/plan.ts"],"names":[],"mappings":"AASA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAkJnC,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,MAAM,CAAC,CA8HlB;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,MAAM,CAAC,CA2DlB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,MAAM,CAAC,CAkElB"}