agentplane 0.3.1 → 0.3.3

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 (201) hide show
  1. package/assets/AGENTS.md +5 -4
  2. package/assets/agents/CODER.json +4 -3
  3. package/assets/agents/DOCS.json +1 -1
  4. package/assets/agents/INTEGRATOR.json +1 -1
  5. package/assets/agents/ORCHESTRATOR.json +1 -0
  6. package/assets/agents/PLANNER.json +1 -0
  7. package/assets/agents/TESTER.json +3 -1
  8. package/assets/policy/dod.code.md +2 -2
  9. package/assets/policy/dod.core.md +16 -2
  10. package/assets/policy/dod.docs.md +2 -2
  11. package/assets/policy/incidents.md +44 -1
  12. package/assets/policy/workflow.direct.md +10 -5
  13. package/bin/agentplane.js +116 -18
  14. package/bin/dist-guard.js +78 -10
  15. package/bin/runtime-context.d.ts +23 -0
  16. package/bin/runtime-context.js +94 -0
  17. package/bin/runtime-watch.d.ts +26 -0
  18. package/bin/runtime-watch.js +116 -0
  19. package/bin/stale-dist-policy.d.ts +6 -0
  20. package/bin/stale-dist-policy.js +44 -0
  21. package/dist/.build-manifest.json +2480 -5
  22. package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
  23. package/dist/backends/task-backend/local-backend.js +9 -12
  24. package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
  25. package/dist/backends/task-backend/redmine-backend.js +23 -18
  26. package/dist/backends/task-backend/shared/constants.d.ts +1 -0
  27. package/dist/backends/task-backend/shared/constants.d.ts.map +1 -1
  28. package/dist/backends/task-backend/shared/constants.js +1 -0
  29. package/dist/backends/task-backend/shared/doc.d.ts +1 -0
  30. package/dist/backends/task-backend/shared/doc.d.ts.map +1 -1
  31. package/dist/backends/task-backend/shared/doc.js +4 -1
  32. package/dist/backends/task-backend/shared/export.js +3 -3
  33. package/dist/cli/bootstrap-guide.d.ts +16 -0
  34. package/dist/cli/bootstrap-guide.d.ts.map +1 -0
  35. package/dist/cli/bootstrap-guide.js +112 -0
  36. package/dist/cli/command-guide.d.ts.map +1 -1
  37. package/dist/cli/command-guide.js +62 -203
  38. package/dist/cli/command-snippets.d.ts +2 -2
  39. package/dist/cli/command-snippets.js +2 -2
  40. package/dist/cli/run-cli/catalog.d.ts +7 -0
  41. package/dist/cli/run-cli/catalog.d.ts.map +1 -0
  42. package/dist/cli/run-cli/catalog.js +22 -0
  43. package/dist/cli/run-cli/command-catalog.d.ts +1 -1
  44. package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
  45. package/dist/cli/run-cli/command-catalog.js +11 -0
  46. package/dist/cli/run-cli/commands/core.js +1 -1
  47. package/dist/cli/run-cli/commands/init/write-config.d.ts.map +1 -1
  48. package/dist/cli/run-cli/commands/init/write-config.js +2 -0
  49. package/dist/cli/run-cli/commands/init.js +5 -14
  50. package/dist/cli/run-cli/error-guidance.d.ts +9 -0
  51. package/dist/cli/run-cli/error-guidance.d.ts.map +1 -0
  52. package/dist/cli/run-cli/error-guidance.js +180 -0
  53. package/dist/cli/run-cli/globals.d.ts +22 -0
  54. package/dist/cli/run-cli/globals.d.ts.map +1 -0
  55. package/dist/cli/run-cli/globals.js +197 -0
  56. package/dist/cli/run-cli/update-warning.d.ts +6 -0
  57. package/dist/cli/run-cli/update-warning.d.ts.map +1 -0
  58. package/dist/cli/run-cli/update-warning.js +64 -0
  59. package/dist/cli/run-cli.d.ts.map +1 -1
  60. package/dist/cli/run-cli.js +5 -476
  61. package/dist/cli/spec/docs-render.d.ts.map +1 -1
  62. package/dist/cli/spec/docs-render.js +14 -1
  63. package/dist/commands/doctor/archive.d.ts +4 -0
  64. package/dist/commands/doctor/archive.d.ts.map +1 -0
  65. package/dist/commands/doctor/archive.js +211 -0
  66. package/dist/commands/doctor/fixes.d.ts +9 -0
  67. package/dist/commands/doctor/fixes.d.ts.map +1 -0
  68. package/dist/commands/doctor/fixes.js +40 -0
  69. package/dist/commands/doctor/layering.d.ts +2 -0
  70. package/dist/commands/doctor/layering.d.ts.map +1 -0
  71. package/dist/commands/doctor/layering.js +87 -0
  72. package/dist/commands/doctor/runtime.d.ts +4 -0
  73. package/dist/commands/doctor/runtime.d.ts.map +1 -0
  74. package/dist/commands/doctor/runtime.js +56 -0
  75. package/dist/commands/doctor/workflow.d.ts +6 -0
  76. package/dist/commands/doctor/workflow.d.ts.map +1 -0
  77. package/dist/commands/doctor/workflow.js +62 -0
  78. package/dist/commands/doctor/workspace.d.ts +2 -0
  79. package/dist/commands/doctor/workspace.d.ts.map +1 -0
  80. package/dist/commands/doctor/workspace.js +165 -0
  81. package/dist/commands/doctor.run.d.ts.map +1 -1
  82. package/dist/commands/doctor.run.js +16 -305
  83. package/dist/commands/doctor.spec.d.ts +1 -0
  84. package/dist/commands/doctor.spec.d.ts.map +1 -1
  85. package/dist/commands/doctor.spec.js +15 -1
  86. package/dist/commands/finish.run.d.ts.map +1 -1
  87. package/dist/commands/finish.run.js +1 -0
  88. package/dist/commands/finish.spec.d.ts +1 -0
  89. package/dist/commands/finish.spec.d.ts.map +1 -1
  90. package/dist/commands/finish.spec.js +23 -2
  91. package/dist/commands/guard/impl/commands.d.ts.map +1 -1
  92. package/dist/commands/guard/impl/commands.js +19 -0
  93. package/dist/commands/release/apply.command.d.ts +2 -7
  94. package/dist/commands/release/apply.command.d.ts.map +1 -1
  95. package/dist/commands/release/apply.command.js +159 -382
  96. package/dist/commands/release/apply.mutation.d.ts +7 -0
  97. package/dist/commands/release/apply.mutation.d.ts.map +1 -0
  98. package/dist/commands/release/apply.mutation.js +107 -0
  99. package/dist/commands/release/apply.preflight.d.ts +25 -0
  100. package/dist/commands/release/apply.preflight.d.ts.map +1 -0
  101. package/dist/commands/release/apply.preflight.js +338 -0
  102. package/dist/commands/release/apply.reporting.d.ts +4 -0
  103. package/dist/commands/release/apply.reporting.d.ts.map +1 -0
  104. package/dist/commands/release/apply.reporting.js +24 -0
  105. package/dist/commands/release/apply.types.d.ts +46 -0
  106. package/dist/commands/release/apply.types.d.ts.map +1 -0
  107. package/dist/commands/release/apply.types.js +1 -0
  108. package/dist/commands/runtime.command.d.ts +28 -0
  109. package/dist/commands/runtime.command.d.ts.map +1 -0
  110. package/dist/commands/runtime.command.js +169 -0
  111. package/dist/commands/shared/task-store.d.ts.map +1 -1
  112. package/dist/commands/shared/task-store.js +7 -3
  113. package/dist/commands/task/add.d.ts.map +1 -1
  114. package/dist/commands/task/add.js +3 -33
  115. package/dist/commands/task/block.d.ts.map +1 -1
  116. package/dist/commands/task/block.js +2 -2
  117. package/dist/commands/task/close-duplicate.d.ts.map +1 -1
  118. package/dist/commands/task/close-duplicate.js +2 -2
  119. package/dist/commands/task/close-noop.d.ts.map +1 -1
  120. package/dist/commands/task/close-noop.js +2 -2
  121. package/dist/commands/task/comment.js +2 -2
  122. package/dist/commands/task/derive.d.ts.map +1 -1
  123. package/dist/commands/task/derive.js +3 -3
  124. package/dist/commands/task/doc-template.d.ts +10 -0
  125. package/dist/commands/task/doc-template.d.ts.map +1 -0
  126. package/dist/commands/task/doc-template.js +104 -0
  127. package/dist/commands/task/doc.d.ts.map +1 -1
  128. package/dist/commands/task/doc.js +36 -1
  129. package/dist/commands/task/finish.d.ts +1 -0
  130. package/dist/commands/task/finish.d.ts.map +1 -1
  131. package/dist/commands/task/finish.js +26 -10
  132. package/dist/commands/task/migrate-doc.command.d.ts.map +1 -1
  133. package/dist/commands/task/migrate-doc.command.js +5 -1
  134. package/dist/commands/task/migrate-doc.d.ts.map +1 -1
  135. package/dist/commands/task/migrate-doc.js +136 -2
  136. package/dist/commands/task/new.d.ts.map +1 -1
  137. package/dist/commands/task/new.js +4 -110
  138. package/dist/commands/task/new.spec.js +3 -3
  139. package/dist/commands/task/plan.d.ts.map +1 -1
  140. package/dist/commands/task/plan.js +5 -4
  141. package/dist/commands/task/scaffold.d.ts.map +1 -1
  142. package/dist/commands/task/scaffold.js +7 -52
  143. package/dist/commands/task/set-status.d.ts.map +1 -1
  144. package/dist/commands/task/set-status.js +2 -2
  145. package/dist/commands/task/shared/dependencies.d.ts +15 -0
  146. package/dist/commands/task/shared/dependencies.d.ts.map +1 -0
  147. package/dist/commands/task/shared/dependencies.js +143 -0
  148. package/dist/commands/task/shared/docs.d.ts +21 -0
  149. package/dist/commands/task/shared/docs.d.ts.map +1 -0
  150. package/dist/commands/task/shared/docs.js +121 -0
  151. package/dist/commands/task/shared/listing.d.ts +20 -0
  152. package/dist/commands/task/shared/listing.d.ts.map +1 -0
  153. package/dist/commands/task/shared/listing.js +127 -0
  154. package/dist/commands/task/shared/tags.d.ts +24 -0
  155. package/dist/commands/task/shared/tags.d.ts.map +1 -0
  156. package/dist/commands/task/shared/tags.js +177 -0
  157. package/dist/commands/task/shared/transitions.d.ts +42 -0
  158. package/dist/commands/task/shared/transitions.d.ts.map +1 -0
  159. package/dist/commands/task/shared/transitions.js +175 -0
  160. package/dist/commands/task/shared.d.ts +5 -106
  161. package/dist/commands/task/shared.d.ts.map +1 -1
  162. package/dist/commands/task/shared.js +5 -681
  163. package/dist/commands/task/start.d.ts.map +1 -1
  164. package/dist/commands/task/start.js +7 -5
  165. package/dist/commands/task/verify-record.d.ts.map +1 -1
  166. package/dist/commands/task/verify-record.js +9 -25
  167. package/dist/commands/task/verify-show.command.d.ts.map +1 -1
  168. package/dist/commands/task/verify-show.command.js +5 -1
  169. package/dist/commands/upgrade/apply.d.ts +44 -0
  170. package/dist/commands/upgrade/apply.d.ts.map +1 -0
  171. package/dist/commands/upgrade/apply.js +180 -0
  172. package/dist/commands/upgrade/report.d.ts +21 -0
  173. package/dist/commands/upgrade/report.d.ts.map +1 -0
  174. package/dist/commands/upgrade/report.js +81 -0
  175. package/dist/commands/upgrade/source.d.ts +35 -0
  176. package/dist/commands/upgrade/source.d.ts.map +1 -0
  177. package/dist/commands/upgrade/source.js +109 -0
  178. package/dist/commands/upgrade/types.d.ts +31 -0
  179. package/dist/commands/upgrade/types.d.ts.map +1 -0
  180. package/dist/commands/upgrade/types.js +1 -0
  181. package/dist/commands/upgrade.command.d.ts.map +1 -1
  182. package/dist/commands/upgrade.command.js +11 -7
  183. package/dist/commands/upgrade.d.ts +1 -35
  184. package/dist/commands/upgrade.d.ts.map +1 -1
  185. package/dist/commands/upgrade.js +54 -320
  186. package/dist/shared/diagnostics.d.ts +23 -0
  187. package/dist/shared/diagnostics.d.ts.map +1 -0
  188. package/dist/shared/diagnostics.js +57 -0
  189. package/dist/shared/errors.d.ts +2 -0
  190. package/dist/shared/errors.d.ts.map +1 -1
  191. package/dist/shared/errors.js +2 -0
  192. package/dist/shared/repo-cli-version.d.ts +13 -0
  193. package/dist/shared/repo-cli-version.d.ts.map +1 -0
  194. package/dist/shared/repo-cli-version.js +63 -0
  195. package/dist/shared/runtime-source.d.ts +33 -0
  196. package/dist/shared/runtime-source.d.ts.map +1 -0
  197. package/dist/shared/runtime-source.js +156 -0
  198. package/dist/shared/version-compare.d.ts +7 -0
  199. package/dist/shared/version-compare.d.ts.map +1 -0
  200. package/dist/shared/version-compare.js +30 -0
  201. package/package.json +2 -2
@@ -7,7 +7,7 @@ import { ensureActionApproved } from "../shared/approval-requirements.js";
7
7
  import { loadCommandContext, loadTaskFromContext, } from "../shared/task-backend.js";
8
8
  import { backendIsLocalFileBackend, getTaskStore } from "../shared/task-store.js";
9
9
  import { readDirectWorkLock } from "../../shared/direct-work-lock.js";
10
- import { appendTaskEvent, ensurePlanApprovedIfRequired, ensureCommentCommitAllowed, ensureStatusTransitionAllowed, defaultCommitEmojiForAgentId, extractDocSection, isVerifyStepsFilled, nowIso, requiresVerifyStepsByPrimary, requireStructuredComment, resolveTaskDependencyState, resolvePrimaryTag, toStringArray, } from "./shared.js";
10
+ import { appendTaskEvent, ensurePlanApprovedIfRequired, ensureCommentCommitAllowed, ensureStatusTransitionAllowed, extractTaskObservationSection, defaultCommitEmojiForAgentId, extractDocSection, isVerifyStepsFilled, normalizeTaskDocVersion, nowIso, requiresVerifyStepsByPrimary, requireStructuredComment, resolveTaskDependencyState, resolvePrimaryTag, taskObservationSectionName, toStringArray, } from "./shared.js";
11
11
  export async function cmdStart(opts) {
12
12
  try {
13
13
  const ctx = opts.ctx ??
@@ -47,12 +47,14 @@ export async function cmdStart(opts) {
47
47
  }
48
48
  }
49
49
  if (isSpike) {
50
- const notes = extractDocSection(doc, "Notes");
51
- if (!notes || notes.trim().length === 0) {
50
+ const docVersion = normalizeTaskDocVersion(task.doc_version);
51
+ const observationSection = taskObservationSectionName(docVersion);
52
+ const observation = extractTaskObservationSection(doc, docVersion);
53
+ if (!observation || observation.trim().length === 0) {
52
54
  throw new CliError({
53
55
  exitCode: 3,
54
56
  code: "E_VALIDATION",
55
- message: `${task.id}: cannot start spike: ## Notes section is missing or empty ` +
57
+ message: `${task.id}: cannot start spike: ## ${observationSection} section is missing or empty ` +
56
58
  "(include Findings/Decision/Next Steps)",
57
59
  });
58
60
  }
@@ -117,7 +119,7 @@ export async function cmdStart(opts) {
117
119
  to: "DOING",
118
120
  note: commentBody,
119
121
  }),
120
- doc_version: 2,
122
+ doc_version: normalizeTaskDocVersion(task.doc_version),
121
123
  doc_updated_at: at,
122
124
  doc_updated_by: opts.author,
123
125
  };
@@ -1 +1 @@
1
- {"version":3,"file":"verify-record.d.ts","sourceRoot":"","sources":["../../../src/commands/task/verify-record.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAKnC,KAAK,WAAW,GAAG,IAAI,GAAG,cAAc,CAAC;AAkKzC,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,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;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4ClB;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,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;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4ClB;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4ClB"}
1
+ {"version":3,"file":"verify-record.d.ts","sourceRoot":"","sources":["../../../src/commands/task/verify-record.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAanC,KAAK,WAAW,GAAG,IAAI,GAAG,cAAc,CAAC;AAgJzC,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,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;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4ClB;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,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;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4ClB;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4ClB"}
@@ -8,28 +8,11 @@ import { CliError } from "../../shared/errors.js";
8
8
  import { ensureReconciledBeforeMutation } from "../shared/reconcile-check.js";
9
9
  import { loadCommandContext, loadTaskFromContext, } from "../shared/task-backend.js";
10
10
  import { backendIsLocalFileBackend, getTaskStore } from "../shared/task-store.js";
11
- import { appendTaskEvent, extractDocSection, nowIso } from "./shared.js";
12
- const RESULTS_BEGIN = "<!-- BEGIN VERIFICATION RESULTS -->";
13
- const RESULTS_END = "<!-- END VERIFICATION RESULTS -->";
14
- function ensureVerificationResultsMarkers(sectionText) {
15
- const normalized = sectionText.replaceAll("\r\n", "\n").trimEnd();
16
- if (!normalized) {
17
- return ["### Plan", "", "", "### Results", "", "", RESULTS_BEGIN, RESULTS_END].join("\n");
18
- }
19
- const hasBegin = normalized.includes(RESULTS_BEGIN);
20
- const hasEnd = normalized.includes(RESULTS_END);
21
- if (hasBegin && hasEnd)
22
- return normalized;
23
- const out = [normalized];
24
- if (!normalized.endsWith("\n"))
25
- out.push("");
26
- out.push("", RESULTS_BEGIN, RESULTS_END);
27
- return out.join("\n").trimEnd();
28
- }
29
- function appendBetweenMarkers(sectionText, entryText) {
30
- const ensured = ensureVerificationResultsMarkers(sectionText);
31
- const beginIdx = ensured.indexOf(RESULTS_BEGIN);
32
- const endIdx = ensured.indexOf(RESULTS_END);
11
+ import { appendTaskEvent, extractDocSection, normalizeTaskDocVersion, normalizeVerificationSectionLayout, nowIso, VERIFICATION_RESULTS_BEGIN, VERIFICATION_RESULTS_END, } from "./shared.js";
12
+ function appendBetweenMarkers(sectionText, entryText, version) {
13
+ const ensured = normalizeVerificationSectionLayout(sectionText, version);
14
+ const beginIdx = ensured.indexOf(VERIFICATION_RESULTS_BEGIN);
15
+ const endIdx = ensured.indexOf(VERIFICATION_RESULTS_END);
33
16
  if (beginIdx === -1 || endIdx === -1 || endIdx <= beginIdx) {
34
17
  throw new Error("Verification results markers are malformed");
35
18
  }
@@ -38,7 +21,7 @@ function appendBetweenMarkers(sectionText, entryText) {
38
21
  const entry = entryText.trimEnd();
39
22
  const parts = [
40
23
  beforeEnd,
41
- ...(beforeEnd.endsWith(RESULTS_BEGIN) ? [] : [""]),
24
+ ...(beforeEnd.endsWith(VERIFICATION_RESULTS_BEGIN) ? [] : [""]),
42
25
  entry,
43
26
  "",
44
27
  afterEnd,
@@ -94,8 +77,9 @@ async function recordVerificationResult(opts) {
94
77
  const verifyStepsHash = verifySteps
95
78
  ? sha256Hex(verifySteps.replaceAll("\r\n", "\n").trim())
96
79
  : null;
80
+ const docVersion = normalizeTaskDocVersion(task.doc_version);
97
81
  const verifyStepsRef = [
98
- `doc_version=${String(task.doc_version ?? "missing")}`,
82
+ `doc_version=${String(docVersion)}`,
99
83
  `doc_updated_at=${String(task.doc_updated_at ?? "missing")}`,
100
84
  `excerpt_hash=sha256:${verifyStepsHash ?? "missing"}`,
101
85
  ].join(", ");
@@ -108,7 +92,7 @@ async function recordVerificationResult(opts) {
108
92
  details: opts.details ?? null,
109
93
  verifyStepsRef,
110
94
  });
111
- const nextVerification = appendBetweenMarkers(verificationSection, entry);
95
+ const nextVerification = appendBetweenMarkers(verificationSection, entry, docVersion);
112
96
  const nextDoc = ensureDocSections(setMarkdownSection(baseDoc, "Verification", nextVerification), config.tasks.doc.required_sections);
113
97
  const nextTask = {
114
98
  ...task,
@@ -1 +1 @@
1
- {"version":3,"file":"verify-show.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/verify-show.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhE,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,oBAAoB,CAyBhE,CAAC;AAEF,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IAC7E,KAAK,UAAU,EAAE,GAAG,oBAAoB,KAAG,OAAO,CAAC,MAAM,CAAC,CAUzE"}
1
+ {"version":3,"file":"verify-show.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/verify-show.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhE,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,oBAAoB,CA6BhE,CAAC;AAEF,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IAC7E,KAAK,UAAU,EAAE,GAAG,oBAAoB,KAAG,OAAO,CAAC,MAAM,CAAC,CAUzE"}
@@ -2,7 +2,7 @@ import { cmdTaskDocShow } from "./doc.js";
2
2
  export const taskVerifyShowSpec = {
3
3
  id: ["task", "verify-show"],
4
4
  group: "Task",
5
- summary: 'Print the task Verify Steps section (alias for task doc show --section "Verify Steps").',
5
+ summary: 'Print the task Verify Steps acceptance contract (alias for task doc show --section "Verify Steps").',
6
6
  args: [{ name: "task-id", required: true, valueHint: "<task-id>" }],
7
7
  options: [
8
8
  {
@@ -19,6 +19,10 @@ export const taskVerifyShowSpec = {
19
19
  why: "Print Verify Steps without erroring when missing.",
20
20
  },
21
21
  ],
22
+ notes: [
23
+ "`## Verify Steps` is the ex-ante acceptance contract for the verifier.",
24
+ "Verification results are recorded later in `## Verification` via `agentplane verify ...`.",
25
+ ],
22
26
  parse: (raw) => ({
23
27
  taskId: String(raw.args["task-id"]),
24
28
  quiet: raw.opts.quiet === true,
@@ -0,0 +1,44 @@
1
+ import type { UpgradeReviewRecord } from "./types.js";
2
+ export declare function cleanupAutoUpgradeArtifacts(opts: {
3
+ upgradeStateDir: string;
4
+ createdBackups: string[];
5
+ }): Promise<void>;
6
+ export declare function ensureCleanTrackedTreeForUpgrade(gitRoot: string): Promise<void>;
7
+ export declare function createUpgradeCommit(opts: {
8
+ gitRoot: string;
9
+ paths: string[];
10
+ versionLabel: string;
11
+ source: "local_assets" | "upgrade_bundle" | "repo_tarball";
12
+ additions: number;
13
+ updates: number;
14
+ unchanged: number;
15
+ incidentsAppendedCount: number;
16
+ }): Promise<{
17
+ hash: string;
18
+ subject: string;
19
+ } | null>;
20
+ export declare function applyManagedFiles(opts: {
21
+ gitRoot: string;
22
+ additions: string[];
23
+ updates: string[];
24
+ backup: boolean;
25
+ fileContents: Map<string, Buffer>;
26
+ baselineDir: string;
27
+ createdBackups: string[];
28
+ toBaselineKey: (rel: string) => string | null;
29
+ }): Promise<void>;
30
+ export declare function persistUpgradeState(opts: {
31
+ agentplaneDir: string;
32
+ rawConfig: Record<string, unknown>;
33
+ normalizedSourceToPersist: string | null;
34
+ expectedCliVersionToPersist: string | null;
35
+ hasManagedMutations: boolean;
36
+ statePath: string;
37
+ upgradeStateDir: string;
38
+ source: "local_assets" | "upgrade_bundle" | "repo_tarball";
39
+ reviewRecords: UpgradeReviewRecord[];
40
+ additions: number;
41
+ updates: number;
42
+ skipped: number;
43
+ }): Promise<boolean>;
44
+ //# sourceMappingURL=apply.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/commands/upgrade/apply.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAUtD,wBAAsB,2BAA2B,CAAC,IAAI,EAAE;IACtD,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,GAAG,OAAO,CAAC,IAAI,CAAC,CAKhB;AAED,wBAAsB,gCAAgC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BrF;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,cAAc,GAAG,gBAAgB,GAAG,cAAc,CAAC;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,EAAE,MAAM,CAAC;CAChC,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAoEpD;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CAC/C,GAAG,OAAO,CAAC,IAAI,CAAC,CA2ChB;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,yBAAyB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,mBAAmB,EAAE,OAAO,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,cAAc,GAAG,gBAAgB,GAAG,cAAc,CAAC;IAC3D,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,OAAO,CAAC,CA4CnB"}
@@ -0,0 +1,180 @@
1
+ import { lstat, mkdir, readlink, rm, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { saveConfig, setByDottedKey } from "@agentplaneorg/core";
4
+ import { backupPath, fileExists } from "../../cli/fs-utils.js";
5
+ import { exitCodeForError } from "../../cli/exit-codes.js";
6
+ import { withDiagnosticContext } from "../../shared/diagnostics.js";
7
+ import { CliError } from "../../shared/errors.js";
8
+ import { execFileAsync, gitEnv } from "../shared/git.js";
9
+ async function safeRemovePath(targetPath) {
10
+ try {
11
+ await rm(targetPath, { recursive: true, force: true });
12
+ }
13
+ catch {
14
+ // best-effort cleanup
15
+ }
16
+ }
17
+ export async function cleanupAutoUpgradeArtifacts(opts) {
18
+ for (const backupPath of opts.createdBackups) {
19
+ await safeRemovePath(backupPath);
20
+ }
21
+ await safeRemovePath(path.join(opts.upgradeStateDir, "agent"));
22
+ }
23
+ export async function ensureCleanTrackedTreeForUpgrade(gitRoot) {
24
+ const { stdout } = await execFileAsync("git", ["status", "--short", "--untracked-files=no"], {
25
+ cwd: gitRoot,
26
+ env: gitEnv(),
27
+ maxBuffer: 10 * 1024 * 1024,
28
+ });
29
+ const dirty = String(stdout ?? "")
30
+ .split(/\r?\n/u)
31
+ .map((line) => line.trimEnd())
32
+ .filter((line) => line.length > 0);
33
+ if (dirty.length === 0)
34
+ return;
35
+ throw new CliError({
36
+ exitCode: exitCodeForError("E_GIT"),
37
+ code: "E_GIT",
38
+ message: "Upgrade --auto requires a clean tracked working tree.\n" +
39
+ `Found tracked changes:\n${dirty.map((line) => ` ${line}`).join("\n")}`,
40
+ context: withDiagnosticContext({ command: "upgrade" }, {
41
+ state: "managed upgrade cannot apply over tracked local edits",
42
+ likelyCause: "auto-apply upgrade is about to replace framework-managed files, but the repository already has tracked modifications",
43
+ nextAction: {
44
+ command: "git status --short --untracked-files=no",
45
+ reason: "inspect or clear tracked changes before rerunning `agentplane upgrade --yes`",
46
+ reasonCode: "upgrade_dirty_tree",
47
+ },
48
+ }),
49
+ });
50
+ }
51
+ export async function createUpgradeCommit(opts) {
52
+ const uniquePaths = [...new Set(opts.paths.filter(Boolean))];
53
+ if (uniquePaths.length === 0)
54
+ return null;
55
+ await execFileAsync("git", ["add", "--", ...uniquePaths], {
56
+ cwd: opts.gitRoot,
57
+ env: gitEnv(),
58
+ maxBuffer: 10 * 1024 * 1024,
59
+ });
60
+ const { stdout: stagedOut } = await execFileAsync("git", ["diff", "--cached", "--name-only", "-z"], {
61
+ cwd: opts.gitRoot,
62
+ env: gitEnv(),
63
+ encoding: "buffer",
64
+ maxBuffer: 10 * 1024 * 1024,
65
+ });
66
+ const staged = (Buffer.isBuffer(stagedOut) ? stagedOut.toString("utf8") : String(stagedOut ?? ""))
67
+ .split("\0")
68
+ .map((entry) => entry.trim())
69
+ .some(Boolean);
70
+ if (!staged)
71
+ return null;
72
+ const subject = `⬆️ upgrade: apply framework ${opts.versionLabel}`;
73
+ const body = `Upgrade-Version: ${opts.versionLabel}\n` +
74
+ `Source: ${opts.source}\n` +
75
+ `Managed-Changes: add=${opts.additions}, update=${opts.updates}, unchanged=${opts.unchanged}\n` +
76
+ `Incidents-Appended: ${opts.incidentsAppendedCount}\n`;
77
+ try {
78
+ await execFileAsync("git", ["commit", "-m", subject, "-m", body], {
79
+ cwd: opts.gitRoot,
80
+ env: gitEnv(),
81
+ maxBuffer: 10 * 1024 * 1024,
82
+ });
83
+ }
84
+ catch (err) {
85
+ const details = err?.stderr ?? "";
86
+ throw new CliError({
87
+ exitCode: exitCodeForError("E_GIT"),
88
+ code: "E_GIT",
89
+ message: "Upgrade applied but failed to create the upgrade commit.\n" +
90
+ "Fix commit policy/hook issues and commit the staged upgrade files as a dedicated upgrade commit.\n" +
91
+ (String(details).trim() ? `Details:\n${String(details).trim()}` : ""),
92
+ context: withDiagnosticContext({ command: "upgrade" }, {
93
+ state: "managed files were updated, but the upgrade commit was blocked",
94
+ likelyCause: "the generated upgrade commit hit a git hook or commit policy failure after the framework files were already staged",
95
+ nextAction: {
96
+ command: `git commit -m "⬆️ upgrade: apply framework ${opts.versionLabel}"`,
97
+ reason: "record the already-staged framework changes as one dedicated upgrade commit after fixing the blocking hook or policy",
98
+ reasonCode: "upgrade_commit_blocked",
99
+ },
100
+ }),
101
+ });
102
+ }
103
+ const { stdout: hashOut } = await execFileAsync("git", ["rev-parse", "HEAD"], {
104
+ cwd: opts.gitRoot,
105
+ env: gitEnv(),
106
+ });
107
+ return { hash: String(hashOut ?? "").trim(), subject };
108
+ }
109
+ export async function applyManagedFiles(opts) {
110
+ for (const rel of [...opts.additions, ...opts.updates]) {
111
+ const destPath = path.join(opts.gitRoot, rel);
112
+ if (opts.backup && (await fileExists(destPath))) {
113
+ const backup = await backupPath(destPath);
114
+ opts.createdBackups.push(backup);
115
+ }
116
+ await mkdir(path.dirname(destPath), { recursive: true });
117
+ const data = opts.fileContents.get(rel);
118
+ if (data) {
119
+ if (rel === "AGENTS.md" || rel === "CLAUDE.md") {
120
+ try {
121
+ const st = await lstat(destPath);
122
+ if (st.isSymbolicLink()) {
123
+ const linkTarget = await readlink(destPath);
124
+ const targetAbs = path.resolve(path.dirname(destPath), linkTarget);
125
+ const relFromRoot = path.relative(opts.gitRoot, targetAbs);
126
+ if (relFromRoot.startsWith("..") || path.isAbsolute(relFromRoot)) {
127
+ throw new CliError({
128
+ exitCode: exitCodeForError("E_VALIDATION"),
129
+ code: "E_VALIDATION",
130
+ message: `Refusing to overwrite symlinked ${rel} target outside repo: ${linkTarget}. ` +
131
+ "Replace the symlink with a regular file and retry.",
132
+ });
133
+ }
134
+ }
135
+ }
136
+ catch (err) {
137
+ const code = err?.code;
138
+ if (code !== "ENOENT")
139
+ throw err;
140
+ }
141
+ }
142
+ await writeFile(destPath, data);
143
+ }
144
+ const baselineKey = opts.toBaselineKey(rel);
145
+ if (baselineKey && data) {
146
+ const baselinePath = path.join(opts.baselineDir, baselineKey);
147
+ await mkdir(path.dirname(baselinePath), { recursive: true });
148
+ await writeFile(baselinePath, data);
149
+ }
150
+ }
151
+ }
152
+ export async function persistUpgradeState(opts) {
153
+ const hasSourceMigration = opts.normalizedSourceToPersist !== null;
154
+ const shouldMutateConfig = opts.hasManagedMutations || hasSourceMigration;
155
+ if (shouldMutateConfig) {
156
+ const raw = { ...opts.rawConfig };
157
+ if (opts.normalizedSourceToPersist) {
158
+ setByDottedKey(raw, "framework.source", opts.normalizedSourceToPersist);
159
+ }
160
+ setByDottedKey(raw, "framework.last_update", new Date().toISOString());
161
+ if (opts.expectedCliVersionToPersist) {
162
+ setByDottedKey(raw, "framework.cli.expected_version", opts.expectedCliVersionToPersist);
163
+ }
164
+ await saveConfig(opts.agentplaneDir, raw);
165
+ }
166
+ await writeFile(opts.statePath, JSON.stringify({
167
+ applied_at: new Date().toISOString(),
168
+ source: opts.source,
169
+ updated: { add: opts.additions, update: opts.updates, unchanged: opts.skipped },
170
+ }, null, 2) + "\n", "utf8");
171
+ await writeFile(path.join(opts.upgradeStateDir, "last-review.json"), JSON.stringify({
172
+ generated_at: new Date().toISOString(),
173
+ counts: {
174
+ total: opts.reviewRecords.length,
175
+ needsSemanticReview: opts.reviewRecords.filter((r) => r.needsSemanticReview).length,
176
+ },
177
+ files: opts.reviewRecords,
178
+ }, null, 2) + "\n", "utf8");
179
+ return shouldMutateConfig;
180
+ }
@@ -0,0 +1,21 @@
1
+ import type { FrameworkManifest, UpgradeReviewRecord } from "./types.js";
2
+ export declare function printUpgradeDryRun(opts: {
3
+ additions: string[];
4
+ updates: string[];
5
+ skipped: string[];
6
+ merged: string[];
7
+ }): void;
8
+ export declare function writeUpgradeAgentReview(opts: {
9
+ gitRoot: string;
10
+ runRoot: string;
11
+ manifest: FrameworkManifest;
12
+ additions: string[];
13
+ updates: string[];
14
+ skipped: string[];
15
+ merged: string[];
16
+ reviewRecords: UpgradeReviewRecord[];
17
+ }): Promise<{
18
+ relRunDir: string;
19
+ needsReviewCount: number;
20
+ }>;
21
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/commands/upgrade/report.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEzE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,GAAG,IAAI,CAQP;AAED,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,EAAE,mBAAmB,EAAE,CAAC;CACtC,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAAC,CA2F3D"}
@@ -0,0 +1,81 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ export function printUpgradeDryRun(opts) {
4
+ process.stdout.write(`Upgrade dry-run: ${opts.additions.length} add, ${opts.updates.length} update, ${opts.skipped.length} unchanged\n`);
5
+ for (const rel of opts.additions)
6
+ process.stdout.write(`ADD ${rel}\n`);
7
+ for (const rel of opts.updates)
8
+ process.stdout.write(`UPDATE ${rel}\n`);
9
+ for (const rel of opts.skipped)
10
+ process.stdout.write(`SKIP ${rel}\n`);
11
+ for (const rel of opts.merged)
12
+ process.stdout.write(`MERGE ${rel}\n`);
13
+ }
14
+ export async function writeUpgradeAgentReview(opts) {
15
+ const runId = new Date().toISOString().replaceAll(":", "-").replaceAll(".", "-");
16
+ const runDir = path.join(opts.runRoot, runId);
17
+ await mkdir(runDir, { recursive: true });
18
+ const managedFiles = opts.manifest.files.map((f) => f.path.replaceAll("\\", "/").trim());
19
+ const needsReviewCount = opts.reviewRecords.filter((r) => r.needsSemanticReview).length;
20
+ const planMd = `# agentplane upgrade plan (${runId})\n\n` +
21
+ `Mode: agent-assisted review (no files modified)\n\n` +
22
+ `## Summary\n\n` +
23
+ `- additions: ${opts.additions.length}\n` +
24
+ `- updates: ${opts.updates.length}\n` +
25
+ `- unchanged: ${opts.skipped.length}\n` +
26
+ `- merged (auto-safe transforms already applied to incoming): ${opts.merged.length}\n\n` +
27
+ `## Managed files (manifest)\n\n` +
28
+ managedFiles.map((p) => `- ${p}`).join("\n") +
29
+ `\n\n` +
30
+ `## Proposed changes\n\n` +
31
+ opts.additions.map((p) => `- ADD ${p}`).join("\n") +
32
+ (opts.additions.length > 0 ? "\n" : "") +
33
+ opts.updates.map((p) => `- UPDATE ${p}`).join("\n") +
34
+ (opts.updates.length > 0 ? "\n" : "") +
35
+ opts.merged.map((p) => `- MERGE ${p}`).join("\n") +
36
+ (opts.merged.length > 0 ? "\n" : "") +
37
+ opts.skipped.map((p) => `- SKIP ${p}`).join("\n") +
38
+ (opts.skipped.length > 0 ? "\n" : "") +
39
+ `\n` +
40
+ `## Next steps\n\n` +
41
+ `1. Review the proposed changes list.\n` +
42
+ `2. Apply changes manually or re-run without \`--agent\` to apply managed files.\n` +
43
+ `3. Run \`agentplane doctor\` (or \`agentplane doctor --fix\`) and ensure checks pass.\n`;
44
+ const constraintsMd = `# Upgrade constraints\n\n` +
45
+ `This upgrade is restricted to framework-managed files only.\n\n` +
46
+ `## Must not touch\n\n` +
47
+ `- .agentplane/tasks/** (task data)\n` +
48
+ `- .agentplane/tasks.json (export snapshot)\n` +
49
+ `- .agentplane/backends/** (backend configuration)\n` +
50
+ `- .agentplane/config.json (project config)\n` +
51
+ `- .git/**\n\n` +
52
+ `## Notes\n\n` +
53
+ `- The upgrade bundle is validated against framework.manifest.json.\n` +
54
+ `- The policy gateway file at workspace root is AGENTS.md or CLAUDE.md.\n`;
55
+ const reportMd = `# Upgrade report (${runId})\n\n` +
56
+ `## Actions taken\n\n` +
57
+ `- [ ] Reviewed plan.md\n` +
58
+ `- [ ] Applied changes (manual or --auto)\n` +
59
+ `- [ ] Ran doctor\n` +
60
+ `- [ ] Ran tests / lint\n\n` +
61
+ `## Notes\n\n` +
62
+ `- \n`;
63
+ await writeFile(path.join(runDir, "plan.md"), planMd, "utf8");
64
+ await writeFile(path.join(runDir, "constraints.md"), constraintsMd, "utf8");
65
+ await writeFile(path.join(runDir, "report.md"), reportMd, "utf8");
66
+ await writeFile(path.join(runDir, "files.json"), JSON.stringify({
67
+ additions: opts.additions,
68
+ updates: opts.updates,
69
+ skipped: opts.skipped,
70
+ merged: opts.merged,
71
+ }, null, 2) + "\n", "utf8");
72
+ await writeFile(path.join(runDir, "review.json"), JSON.stringify({
73
+ generated_at: new Date().toISOString(),
74
+ counts: {
75
+ total: opts.reviewRecords.length,
76
+ needsSemanticReview: needsReviewCount,
77
+ },
78
+ files: opts.reviewRecords,
79
+ }, null, 2) + "\n", "utf8");
80
+ return { relRunDir: path.relative(opts.gitRoot, runDir), needsReviewCount };
81
+ }
@@ -0,0 +1,35 @@
1
+ import type { FrameworkManifest, GitHubRelease } from "./types.js";
2
+ export declare function describeUpgradeSource(opts: {
3
+ bundleLayout: "local_assets" | "upgrade_bundle" | "repo_tarball";
4
+ hasExplicitBundle: boolean;
5
+ useRemote: boolean;
6
+ }): string;
7
+ export declare function loadFrameworkManifestFromPath(manifestPath: string): Promise<FrameworkManifest>;
8
+ export declare function normalizeFrameworkSourceForUpgrade(source: string): {
9
+ source: string;
10
+ owner: string;
11
+ repo: string;
12
+ migrated: boolean;
13
+ };
14
+ export declare function resolveUpgradeDownloadFromRelease(opts: {
15
+ release: GitHubRelease;
16
+ owner: string;
17
+ repo: string;
18
+ assetName: string;
19
+ checksumName: string;
20
+ }): {
21
+ kind: "assets";
22
+ bundleUrl: string;
23
+ checksumUrl: string;
24
+ } | {
25
+ kind: "tarball";
26
+ tarballUrl: string;
27
+ };
28
+ export declare function resolveRepoTarballUrl(opts: {
29
+ release: GitHubRelease;
30
+ owner: string;
31
+ repo: string;
32
+ explicitTag?: string;
33
+ }): string;
34
+ export declare function resolveUpgradeRoot(extractedDir: string): Promise<string>;
35
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../../src/commands/upgrade/source.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEnE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,YAAY,EAAE,cAAc,GAAG,gBAAgB,GAAG,cAAc,CAAC;IACjE,iBAAiB,EAAE,OAAO,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;CACpB,GAAG,MAAM,CAMT;AAED,wBAAsB,6BAA6B,CACjD,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAW5B;AAmBD,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,MAAM,GAAG;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CACnB,CAWA;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE;IACtD,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB,GACG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAqB1C;AAQD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CAgBT;AAED,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ9E"}
@@ -0,0 +1,109 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { invalidFieldMessage, invalidValueMessage, requiredFieldMessage, } from "../../cli/output.js";
4
+ import { exitCodeForError } from "../../cli/exit-codes.js";
5
+ import { CliError } from "../../shared/errors.js";
6
+ export function describeUpgradeSource(opts) {
7
+ if (opts.bundleLayout === "local_assets")
8
+ return "local installed agentplane CLI assets";
9
+ if (opts.bundleLayout === "repo_tarball")
10
+ return "GitHub repo tarball fallback";
11
+ if (opts.hasExplicitBundle)
12
+ return "explicit upgrade bundle";
13
+ if (opts.useRemote)
14
+ return "GitHub release bundle";
15
+ return "upgrade bundle";
16
+ }
17
+ export async function loadFrameworkManifestFromPath(manifestPath) {
18
+ const text = await readFile(manifestPath, "utf8");
19
+ const parsed = JSON.parse(text);
20
+ if (parsed?.schema_version !== 1 || !Array.isArray(parsed?.files)) {
21
+ throw new CliError({
22
+ exitCode: 3,
23
+ code: "E_VALIDATION",
24
+ message: "Invalid framework.manifest.json (expected schema_version=1 and files array).",
25
+ });
26
+ }
27
+ return parsed;
28
+ }
29
+ function parseGitHubRepo(source) {
30
+ const trimmed = source.trim();
31
+ if (!trimmed)
32
+ throw new Error(requiredFieldMessage("config.framework.source"));
33
+ if (!trimmed.includes("github.com")) {
34
+ throw new Error(invalidFieldMessage("config.framework.source", "GitHub URL"));
35
+ }
36
+ try {
37
+ const url = new URL(trimmed);
38
+ const parts = url.pathname.replaceAll(".git", "").split("/").filter(Boolean);
39
+ if (parts.length < 2)
40
+ throw new Error(invalidValueMessage("GitHub repo URL", trimmed, "owner/repo"));
41
+ return { owner: parts[0], repo: parts[1] };
42
+ }
43
+ catch {
44
+ throw new Error(invalidValueMessage("GitHub repo URL", trimmed, "owner/repo"));
45
+ }
46
+ }
47
+ export function normalizeFrameworkSourceForUpgrade(source) {
48
+ const { owner, repo } = parseGitHubRepo(source);
49
+ if (owner === "basilisk-labs" && repo === "agent-plane") {
50
+ return {
51
+ source: `https://github.com/${owner}/agentplane`,
52
+ owner,
53
+ repo: "agentplane",
54
+ migrated: true,
55
+ };
56
+ }
57
+ return { source: `https://github.com/${owner}/${repo}`, owner, repo, migrated: false };
58
+ }
59
+ export function resolveUpgradeDownloadFromRelease(opts) {
60
+ const assets = Array.isArray(opts.release.assets) ? opts.release.assets : [];
61
+ const asset = assets.find((a) => a?.name === opts.assetName);
62
+ const checksumAsset = assets.find((a) => a?.name === opts.checksumName);
63
+ if (asset?.browser_download_url && checksumAsset?.browser_download_url) {
64
+ return {
65
+ kind: "assets",
66
+ bundleUrl: asset.browser_download_url,
67
+ checksumUrl: checksumAsset.browser_download_url,
68
+ };
69
+ }
70
+ const tarballUrl = typeof opts.release.tarball_url === "string" ? opts.release.tarball_url : "";
71
+ if (!tarballUrl) {
72
+ throw new CliError({
73
+ exitCode: exitCodeForError("E_NETWORK"),
74
+ code: "E_NETWORK",
75
+ message: `Upgrade assets not found in ${opts.owner}/${opts.repo} release`,
76
+ });
77
+ }
78
+ return { kind: "tarball", tarballUrl };
79
+ }
80
+ function buildCodeloadTarGzUrl(opts) {
81
+ const tag = opts.tag.trim();
82
+ if (!tag)
83
+ throw new Error("tag is required");
84
+ return `https://codeload.github.com/${opts.owner}/${opts.repo}/tar.gz/${encodeURIComponent(tag)}`;
85
+ }
86
+ export function resolveRepoTarballUrl(opts) {
87
+ const tag = (typeof opts.explicitTag === "string" && opts.explicitTag.trim()) ||
88
+ (typeof opts.release.tag_name === "string" && opts.release.tag_name.trim()) ||
89
+ "";
90
+ if (tag)
91
+ return buildCodeloadTarGzUrl({ owner: opts.owner, repo: opts.repo, tag });
92
+ const tarballUrl = typeof opts.release.tarball_url === "string" ? opts.release.tarball_url : "";
93
+ if (tarballUrl)
94
+ return tarballUrl;
95
+ throw new CliError({
96
+ exitCode: exitCodeForError("E_NETWORK"),
97
+ code: "E_NETWORK",
98
+ message: "GitHub release did not provide tag_name or tarball_url; cannot fall back to repo tarball.",
99
+ });
100
+ }
101
+ export async function resolveUpgradeRoot(extractedDir) {
102
+ const entries = await readdir(extractedDir, { withFileTypes: true });
103
+ const dirs = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
104
+ const files = entries.filter((entry) => entry.isFile()).map((entry) => entry.name);
105
+ if (files.length === 0 && dirs.length === 1) {
106
+ return path.join(extractedDir, dirs[0]);
107
+ }
108
+ return extractedDir;
109
+ }
@@ -0,0 +1,31 @@
1
+ export type GitHubRelease = {
2
+ tag_name?: string;
3
+ assets?: {
4
+ name?: string;
5
+ browser_download_url?: string;
6
+ }[];
7
+ tarball_url?: string;
8
+ };
9
+ export type FrameworkManifest = {
10
+ schema_version: 1;
11
+ files: FrameworkManifestEntry[];
12
+ };
13
+ export type FrameworkManifestEntry = {
14
+ path: string;
15
+ source_path?: string;
16
+ type: "markdown" | "json" | "text";
17
+ merge_strategy: "agents_policy_markdown" | "agent_json_3way" | "agent_json_merge";
18
+ required?: boolean;
19
+ };
20
+ export type UpgradeReviewRecord = {
21
+ relPath: string;
22
+ mergeStrategy: FrameworkManifestEntry["merge_strategy"];
23
+ hasBaseline: boolean;
24
+ changedCurrentVsBaseline: boolean | null;
25
+ changedIncomingVsBaseline: boolean | null;
26
+ currentDiffersFromIncoming: boolean;
27
+ needsSemanticReview: boolean;
28
+ mergeApplied: boolean;
29
+ mergePath: "none" | "markdownOverrides" | "3way" | "incomingWins" | "incomingWinsFallback" | "parseFailed" | "incidentsAppend";
30
+ };
31
+ //# sourceMappingURL=types.d.ts.map