agentplane 0.3.10 → 0.3.12

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 (271) hide show
  1. package/assets/AGENTS.md +2 -2
  2. package/assets/agents/CODER.json +4 -0
  3. package/assets/agents/CREATOR.json +1 -0
  4. package/assets/agents/DOCS.json +2 -1
  5. package/assets/agents/INTEGRATOR.json +2 -1
  6. package/assets/agents/ORCHESTRATOR.json +2 -0
  7. package/assets/agents/PLANNER.json +3 -1
  8. package/assets/agents/REVIEWER.json +1 -0
  9. package/assets/agents/TESTER.json +2 -2
  10. package/assets/agents/UPDATER.json +1 -0
  11. package/assets/agents/UPGRADER.json +1 -1
  12. package/assets/policy/governance.md +3 -4
  13. package/assets/policy/incidents.md +20 -88
  14. package/assets/policy/workflow.branch_pr.md +1 -1
  15. package/assets/policy/workflow.direct.md +2 -2
  16. package/bin/agentplane.js +114 -4
  17. package/bin/runtime-watch.js +1 -0
  18. package/bin/stale-dist-policy.d.ts +1 -1
  19. package/bin/stale-dist-policy.js +19 -1
  20. package/dist/.build-manifest.json +251 -166
  21. package/dist/cli/bootstrap-guide.d.ts.map +1 -1
  22. package/dist/cli/bootstrap-guide.js +3 -2
  23. package/dist/cli/command-guide.d.ts.map +1 -1
  24. package/dist/cli/command-guide.js +2 -1
  25. package/dist/cli/command-invocations.d.ts.map +1 -1
  26. package/dist/cli/command-invocations.js +4 -1
  27. package/dist/cli/run-cli/command-catalog/core.d.ts +1 -1
  28. package/dist/cli/run-cli/command-catalog/core.d.ts.map +1 -1
  29. package/dist/cli/run-cli/command-catalog/core.js +6 -1
  30. package/dist/cli/run-cli/command-catalog/project.d.ts +1 -1
  31. package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -1
  32. package/dist/cli/run-cli/command-catalog/project.js +3 -1
  33. package/dist/cli/run-cli/command-catalog/task.d.ts +1 -1
  34. package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -1
  35. package/dist/cli/run-cli/command-catalog/task.js +10 -0
  36. package/dist/cli/run-cli/command-catalog.d.ts +1 -1
  37. package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
  38. package/dist/cli/run-cli/commands/core/preflight.d.ts.map +1 -1
  39. package/dist/cli/run-cli/commands/core/preflight.js +44 -1
  40. package/dist/cli/run-cli.test-helpers.d.ts +1 -0
  41. package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
  42. package/dist/cli/run-cli.test-helpers.js +26 -0
  43. package/dist/commands/branch/cleanup-merged.d.ts +3 -0
  44. package/dist/commands/branch/cleanup-merged.d.ts.map +1 -1
  45. package/dist/commands/branch/cleanup-merged.js +149 -36
  46. package/dist/commands/branch/work-start.d.ts.map +1 -1
  47. package/dist/commands/branch/work-start.js +137 -1
  48. package/dist/commands/cleanup/merged.command.d.ts +2 -0
  49. package/dist/commands/cleanup/merged.command.d.ts.map +1 -1
  50. package/dist/commands/cleanup/merged.command.js +24 -0
  51. package/dist/commands/doctor/branch-pr.d.ts +4 -0
  52. package/dist/commands/doctor/branch-pr.d.ts.map +1 -0
  53. package/dist/commands/doctor/branch-pr.js +96 -0
  54. package/dist/commands/doctor/fixes.d.ts +5 -0
  55. package/dist/commands/doctor/fixes.d.ts.map +1 -1
  56. package/dist/commands/doctor/fixes.js +70 -0
  57. package/dist/commands/doctor.run.d.ts.map +1 -1
  58. package/dist/commands/doctor.run.js +6 -1
  59. package/dist/commands/finish.run.d.ts.map +1 -1
  60. package/dist/commands/finish.run.js +11 -0
  61. package/dist/commands/finish.spec.d.ts +11 -0
  62. package/dist/commands/finish.spec.d.ts.map +1 -1
  63. package/dist/commands/finish.spec.js +51 -0
  64. package/dist/commands/guard/impl/close-message.d.ts.map +1 -1
  65. package/dist/commands/guard/impl/close-message.js +23 -6
  66. package/dist/commands/guard/impl/commands.d.ts +1 -0
  67. package/dist/commands/guard/impl/commands.d.ts.map +1 -1
  68. package/dist/commands/guard/impl/commands.js +94 -2
  69. package/dist/commands/guard/impl/env.d.ts +1 -0
  70. package/dist/commands/guard/impl/env.d.ts.map +1 -1
  71. package/dist/commands/guard/impl/env.js +1 -0
  72. package/dist/commands/hooks/index.d.ts +1 -1
  73. package/dist/commands/hooks/index.d.ts.map +1 -1
  74. package/dist/commands/hooks/index.js +139 -6
  75. package/dist/commands/incidents/collect.command.d.ts.map +1 -1
  76. package/dist/commands/incidents/collect.command.js +12 -7
  77. package/dist/commands/incidents/incidents.command.js +1 -1
  78. package/dist/commands/incidents/shared.d.ts +34 -0
  79. package/dist/commands/incidents/shared.d.ts.map +1 -1
  80. package/dist/commands/incidents/shared.js +166 -12
  81. package/dist/commands/pr/check.d.ts.map +1 -1
  82. package/dist/commands/pr/check.js +241 -135
  83. package/dist/commands/pr/close-superseded.d.ts +9 -0
  84. package/dist/commands/pr/close-superseded.d.ts.map +1 -0
  85. package/dist/commands/pr/close-superseded.js +129 -0
  86. package/dist/commands/pr/close.d.ts +11 -0
  87. package/dist/commands/pr/close.d.ts.map +1 -0
  88. package/dist/commands/pr/close.js +116 -0
  89. package/dist/commands/pr/index.d.ts +2 -0
  90. package/dist/commands/pr/index.d.ts.map +1 -1
  91. package/dist/commands/pr/index.js +2 -0
  92. package/dist/commands/pr/integrate/artifacts.d.ts +7 -0
  93. package/dist/commands/pr/integrate/artifacts.d.ts.map +1 -1
  94. package/dist/commands/pr/integrate/artifacts.js +66 -1
  95. package/dist/commands/pr/integrate/cmd.d.ts.map +1 -1
  96. package/dist/commands/pr/integrate/cmd.js +43 -2
  97. package/dist/commands/pr/integrate/internal/bootstrap-guidance.d.ts +8 -0
  98. package/dist/commands/pr/integrate/internal/bootstrap-guidance.d.ts.map +1 -0
  99. package/dist/commands/pr/integrate/internal/bootstrap-guidance.js +59 -0
  100. package/dist/commands/pr/integrate/internal/cleanup.d.ts +1 -11
  101. package/dist/commands/pr/integrate/internal/cleanup.d.ts.map +1 -1
  102. package/dist/commands/pr/integrate/internal/cleanup.js +1 -46
  103. package/dist/commands/pr/integrate/internal/finalize.d.ts.map +1 -1
  104. package/dist/commands/pr/integrate/internal/finalize.js +43 -12
  105. package/dist/commands/pr/integrate/internal/github-protection.d.ts +5 -0
  106. package/dist/commands/pr/integrate/internal/github-protection.d.ts.map +1 -0
  107. package/dist/commands/pr/integrate/internal/github-protection.js +13 -0
  108. package/dist/commands/pr/integrate/internal/merge.d.ts.map +1 -1
  109. package/dist/commands/pr/integrate/internal/merge.js +36 -13
  110. package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.d.ts +13 -0
  111. package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.d.ts.map +1 -0
  112. package/dist/commands/pr/integrate/internal/post-integrate-bootstrap.js +25 -0
  113. package/dist/commands/pr/integrate/internal/pre-integrate-bootstrap.d.ts +15 -0
  114. package/dist/commands/pr/integrate/internal/pre-integrate-bootstrap.d.ts.map +1 -0
  115. package/dist/commands/pr/integrate/internal/pre-integrate-bootstrap.js +35 -0
  116. package/dist/commands/pr/integrate/internal/prepare.d.ts +4 -2
  117. package/dist/commands/pr/integrate/internal/prepare.d.ts.map +1 -1
  118. package/dist/commands/pr/integrate/internal/prepare.js +109 -38
  119. package/dist/commands/pr/internal/auto-commit.d.ts +7 -0
  120. package/dist/commands/pr/internal/auto-commit.d.ts.map +1 -0
  121. package/dist/commands/pr/internal/auto-commit.js +64 -0
  122. package/dist/commands/pr/internal/freshness.d.ts +21 -0
  123. package/dist/commands/pr/internal/freshness.d.ts.map +1 -0
  124. package/dist/commands/pr/internal/freshness.js +52 -0
  125. package/dist/commands/pr/internal/gh-api.d.ts +6 -0
  126. package/dist/commands/pr/internal/gh-api.d.ts.map +1 -0
  127. package/dist/commands/pr/internal/gh-api.js +80 -0
  128. package/dist/commands/pr/internal/pr-paths.d.ts +10 -0
  129. package/dist/commands/pr/internal/pr-paths.d.ts.map +1 -1
  130. package/dist/commands/pr/internal/pr-paths.js +10 -0
  131. package/dist/commands/pr/internal/review-template.d.ts.map +1 -1
  132. package/dist/commands/pr/internal/review-template.js +37 -4
  133. package/dist/commands/pr/internal/sync.d.ts +9 -0
  134. package/dist/commands/pr/internal/sync.d.ts.map +1 -1
  135. package/dist/commands/pr/internal/sync.js +531 -124
  136. package/dist/commands/pr/open.d.ts +1 -0
  137. package/dist/commands/pr/open.d.ts.map +1 -1
  138. package/dist/commands/pr/open.js +24 -2
  139. package/dist/commands/pr/pr.command.d.ts +15 -0
  140. package/dist/commands/pr/pr.command.d.ts.map +1 -1
  141. package/dist/commands/pr/pr.command.js +118 -2
  142. package/dist/commands/pr/update.d.ts.map +1 -1
  143. package/dist/commands/pr/update.js +71 -2
  144. package/dist/commands/release/apply.command.d.ts +3 -1
  145. package/dist/commands/release/apply.command.d.ts.map +1 -1
  146. package/dist/commands/release/apply.command.js +356 -34
  147. package/dist/commands/release/apply.mutation.d.ts.map +1 -1
  148. package/dist/commands/release/apply.mutation.js +1 -0
  149. package/dist/commands/release/apply.preflight.d.ts.map +1 -1
  150. package/dist/commands/release/apply.preflight.js +1 -1
  151. package/dist/commands/release/apply.reporting.d.ts +1 -0
  152. package/dist/commands/release/apply.reporting.d.ts.map +1 -1
  153. package/dist/commands/release/apply.reporting.js +12 -8
  154. package/dist/commands/release/apply.types.d.ts +13 -0
  155. package/dist/commands/release/apply.types.d.ts.map +1 -1
  156. package/dist/commands/release/plan.command.d.ts.map +1 -1
  157. package/dist/commands/release/plan.command.js +48 -0
  158. package/dist/commands/shared/gh-transport.d.ts +16 -0
  159. package/dist/commands/shared/gh-transport.d.ts.map +1 -0
  160. package/dist/commands/shared/gh-transport.js +71 -0
  161. package/dist/commands/shared/git-diff.d.ts +3 -1
  162. package/dist/commands/shared/git-diff.d.ts.map +1 -1
  163. package/dist/commands/shared/git-diff.js +10 -2
  164. package/dist/commands/shared/git-ops.d.ts +1 -0
  165. package/dist/commands/shared/git-ops.d.ts.map +1 -1
  166. package/dist/commands/shared/git-ops.js +15 -0
  167. package/dist/commands/shared/git-worktree.d.ts +2 -0
  168. package/dist/commands/shared/git-worktree.d.ts.map +1 -1
  169. package/dist/commands/shared/git-worktree.js +22 -2
  170. package/dist/commands/shared/merged-branch-cleanup.d.ts +12 -0
  171. package/dist/commands/shared/merged-branch-cleanup.d.ts.map +1 -0
  172. package/dist/commands/shared/merged-branch-cleanup.js +46 -0
  173. package/dist/commands/shared/post-commit-pr-artifacts.d.ts +9 -0
  174. package/dist/commands/shared/post-commit-pr-artifacts.d.ts.map +1 -0
  175. package/dist/commands/shared/post-commit-pr-artifacts.js +57 -0
  176. package/dist/commands/shared/pr-meta.d.ts +20 -0
  177. package/dist/commands/shared/pr-meta.d.ts.map +1 -1
  178. package/dist/commands/shared/pr-meta.js +125 -0
  179. package/dist/commands/shared/task-backend.d.ts +7 -0
  180. package/dist/commands/shared/task-backend.d.ts.map +1 -1
  181. package/dist/commands/shared/task-backend.js +71 -27
  182. package/dist/commands/shared/task-local-freshness.d.ts +2 -0
  183. package/dist/commands/shared/task-local-freshness.d.ts.map +1 -1
  184. package/dist/commands/shared/task-local-freshness.js +7 -1
  185. package/dist/commands/task/close-duplicate.d.ts.map +1 -1
  186. package/dist/commands/task/close-duplicate.js +34 -1
  187. package/dist/commands/task/derive.js +1 -1
  188. package/dist/commands/task/doc-template.d.ts.map +1 -1
  189. package/dist/commands/task/doc-template.js +7 -11
  190. package/dist/commands/task/findings-add.command.d.ts +20 -0
  191. package/dist/commands/task/findings-add.command.d.ts.map +1 -0
  192. package/dist/commands/task/findings-add.command.js +165 -0
  193. package/dist/commands/task/findings.command.d.ts +7 -0
  194. package/dist/commands/task/findings.command.d.ts.map +1 -0
  195. package/dist/commands/task/findings.command.js +20 -0
  196. package/dist/commands/task/findings.d.ts +63 -0
  197. package/dist/commands/task/findings.d.ts.map +1 -0
  198. package/dist/commands/task/findings.js +188 -0
  199. package/dist/commands/task/finish-shared.d.ts +2 -0
  200. package/dist/commands/task/finish-shared.d.ts.map +1 -1
  201. package/dist/commands/task/finish-shared.js +56 -1
  202. package/dist/commands/task/finish.d.ts +10 -0
  203. package/dist/commands/task/finish.d.ts.map +1 -1
  204. package/dist/commands/task/finish.js +125 -6
  205. package/dist/commands/task/hosted-close-pr.command.d.ts +11 -0
  206. package/dist/commands/task/hosted-close-pr.command.d.ts.map +1 -0
  207. package/dist/commands/task/hosted-close-pr.command.js +449 -0
  208. package/dist/commands/task/hosted-close.command.d.ts.map +1 -1
  209. package/dist/commands/task/hosted-close.command.js +234 -19
  210. package/dist/commands/task/hosted-merge-sync.d.ts +41 -0
  211. package/dist/commands/task/hosted-merge-sync.d.ts.map +1 -1
  212. package/dist/commands/task/hosted-merge-sync.js +291 -17
  213. package/dist/commands/task/index.d.ts +1 -0
  214. package/dist/commands/task/index.d.ts.map +1 -1
  215. package/dist/commands/task/index.js +1 -0
  216. package/dist/commands/task/new.d.ts +1 -0
  217. package/dist/commands/task/new.d.ts.map +1 -1
  218. package/dist/commands/task/new.js +71 -1
  219. package/dist/commands/task/new.spec.d.ts.map +1 -1
  220. package/dist/commands/task/new.spec.js +7 -0
  221. package/dist/commands/task/normalize.command.d.ts +2 -0
  222. package/dist/commands/task/normalize.command.d.ts.map +1 -1
  223. package/dist/commands/task/normalize.command.js +45 -0
  224. package/dist/commands/task/normalize.d.ts +2 -0
  225. package/dist/commands/task/normalize.d.ts.map +1 -1
  226. package/dist/commands/task/normalize.js +85 -8
  227. package/dist/commands/task/plan.d.ts.map +1 -1
  228. package/dist/commands/task/plan.js +7 -10
  229. package/dist/commands/task/shared/docs.d.ts +6 -0
  230. package/dist/commands/task/shared/docs.d.ts.map +1 -1
  231. package/dist/commands/task/shared/docs.js +14 -0
  232. package/dist/commands/task/shared/transitions.d.ts.map +1 -1
  233. package/dist/commands/task/shared/transitions.js +11 -1
  234. package/dist/commands/task/shared.d.ts +1 -1
  235. package/dist/commands/task/shared.d.ts.map +1 -1
  236. package/dist/commands/task/shared.js +1 -1
  237. package/dist/commands/task/start.d.ts.map +1 -1
  238. package/dist/commands/task/start.js +7 -10
  239. package/dist/commands/task/task.command.d.ts.map +1 -1
  240. package/dist/commands/task/task.command.js +4 -0
  241. package/dist/commands/task/verify-command-shared.d.ts +19 -0
  242. package/dist/commands/task/verify-command-shared.d.ts.map +1 -1
  243. package/dist/commands/task/verify-command-shared.js +152 -1
  244. package/dist/commands/task/verify-ok.command.d.ts.map +1 -1
  245. package/dist/commands/task/verify-ok.command.js +15 -2
  246. package/dist/commands/task/verify-record.d.ts +36 -0
  247. package/dist/commands/task/verify-record.d.ts.map +1 -1
  248. package/dist/commands/task/verify-record.js +166 -11
  249. package/dist/commands/task/verify-rework.command.d.ts.map +1 -1
  250. package/dist/commands/task/verify-rework.command.js +15 -2
  251. package/dist/commands/task/verify-show.command.d.ts +1 -1
  252. package/dist/commands/task/verify-show.command.d.ts.map +1 -1
  253. package/dist/commands/task/verify-show.command.js +28 -1
  254. package/dist/commands/verify.run.d.ts.map +1 -1
  255. package/dist/commands/verify.run.js +12 -0
  256. package/dist/commands/verify.spec.d.ts +2 -6
  257. package/dist/commands/verify.spec.d.ts.map +1 -1
  258. package/dist/commands/verify.spec.js +30 -3
  259. package/dist/runtime/incidents/index.d.ts +1 -1
  260. package/dist/runtime/incidents/index.d.ts.map +1 -1
  261. package/dist/runtime/incidents/resolve.d.ts.map +1 -1
  262. package/dist/runtime/incidents/resolve.js +319 -73
  263. package/dist/runtime/incidents/types.d.ts +14 -2
  264. package/dist/runtime/incidents/types.d.ts.map +1 -1
  265. package/dist/shared/env.d.ts +1 -0
  266. package/dist/shared/env.d.ts.map +1 -1
  267. package/dist/shared/env.js +22 -1
  268. package/dist/shared/protected-paths.d.ts +1 -1
  269. package/dist/shared/protected-paths.d.ts.map +1 -1
  270. package/dist/shared/protected-paths.js +4 -0
  271. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
1
  import path from "node:path";
2
- import { loadConfig, resolveProject } from "@agentplaneorg/core";
2
+ import { extractTaskSuffix, loadConfig, resolveBaseBranch, resolveProject, } from "@agentplaneorg/core";
3
3
  import { createCliEmitter } from "../../cli/output.js";
4
4
  import { exitCodeForError } from "../../cli/exit-codes.js";
5
5
  import { usageError } from "../../cli/spec/errors.js";
@@ -7,12 +7,14 @@ import { withDiagnosticContext } from "../../shared/diagnostics.js";
7
7
  import { CliError } from "../../shared/errors.js";
8
8
  import { execFileAsync, gitEnv } from "../shared/git.js";
9
9
  import { GitContext } from "../shared/git-context.js";
10
+ import { gitCurrentBranch } from "../shared/git-ops.js";
11
+ import { parseTaskIdFromBranch } from "../shared/git-worktree.js";
10
12
  import { ensureActionApproved } from "../shared/approval-requirements.js";
11
13
  import { ensureNetworkApproved } from "../shared/network-approval.js";
12
14
  import { runOperatorPipeline } from "../shared/operator-pipeline.js";
13
15
  import { cleanHookEnv, maybePersistExpectedCliVersion, maybeRefreshGeneratedReference, maybeUpdateBunLockfile, replaceAgentplanePackageMetadata, replacePackageVersionInFile, } from "./apply.mutation.js";
14
16
  import { ensureCleanTrackedTree, ensureNpmVersionsAvailable, ensureRemoteExists, ensureRemoteTagDoesNotExist, ensureTagDoesNotExist, fileExists, loadReleasePlan, readCoreDependencyVersion, readPackageVersion, runReleasePrepublishGate, validateReleaseNotes, } from "./apply.preflight.js";
15
- import { pushReleaseRefs, writeReleaseApplyReport } from "./apply.reporting.js";
17
+ import { pushReleaseCandidateBranch, pushReleaseRefs, writeReleaseApplyReport, } from "./apply.reporting.js";
16
18
  const output = createCliEmitter();
17
19
  async function resolveReleasePlanInputs(opts) {
18
20
  const { planDir, plan, minBullets } = await loadReleasePlan({
@@ -84,18 +86,21 @@ async function ensureReleasePlanMatchesRepoState(opts) {
84
86
  }
85
87
  async function runPushPreflight(opts) {
86
88
  const loaded = await loadConfig(opts.agentplaneDir);
89
+ const pushReason = opts.route.kind === "release_candidate"
90
+ ? `${opts.commandLabel} will push current branch ${opts.route.current_branch} to ${opts.remote} as a release candidate for ${opts.nextTag}; final publication remains gated on merge to ${opts.route.base_branch}`
91
+ : `${opts.commandLabel} will push HEAD and ${opts.nextTag} to ${opts.remote}`;
87
92
  await ensureNetworkApproved({
88
- action: "release_apply",
93
+ action: opts.route.kind === "release_candidate" ? "release_candidate" : "release_apply",
89
94
  config: loaded.config,
90
95
  yes: opts.yes,
91
- reason: "release apply --push validates npm version availability and pushes over network",
96
+ reason: `${opts.commandLabel} validates npm version availability and pushes over network`,
92
97
  interactive: Boolean(process.stdin.isTTY),
93
98
  });
94
99
  await ensureActionApproved({
95
100
  action: "git_push",
96
101
  config: loaded.config,
97
102
  yes: opts.yes,
98
- reason: `release apply --push will push HEAD and ${opts.nextTag} to ${opts.remote}`,
103
+ reason: pushReason,
99
104
  interactive: Boolean(process.stdin.isTTY),
100
105
  });
101
106
  await ensureRemoteExists(opts.gitRoot, opts.remote);
@@ -104,6 +109,140 @@ async function runPushPreflight(opts) {
104
109
  await runReleasePrepublishGate(opts.gitRoot);
105
110
  return true;
106
111
  }
112
+ async function resolveDirectReleaseRoute(opts) {
113
+ const loaded = await loadConfig(opts.agentplaneDir);
114
+ const workflowMode = loaded.config.workflow_mode;
115
+ const currentBranch = await gitCurrentBranch(opts.gitRoot);
116
+ if (workflowMode !== "branch_pr") {
117
+ return {
118
+ kind: "direct_release",
119
+ workflow_mode: workflowMode,
120
+ current_branch: currentBranch,
121
+ base_branch: null,
122
+ };
123
+ }
124
+ const baseBranch = await resolveBaseBranch({
125
+ cwd: opts.cwd,
126
+ rootOverride: opts.rootOverride ?? null,
127
+ mode: workflowMode,
128
+ });
129
+ if (!baseBranch) {
130
+ throw new CliError({
131
+ exitCode: exitCodeForError("E_VALIDATION"),
132
+ code: "E_VALIDATION",
133
+ message: "Release apply in branch_pr mode requires a resolved base branch.\n" +
134
+ "Pin it with `agentplane branch base set <branch>` or configure origin/HEAD before rerunning.",
135
+ context: withDiagnosticContext({ command: "release apply" }, {
136
+ state: "branch_pr release routing could not resolve the protected base branch",
137
+ likelyCause: "the release flow needs to know whether this checkout is the protected base branch or a task branch before deciding if it should create or push a release tag",
138
+ nextAction: {
139
+ command: "agentplane branch base set <branch>",
140
+ reason: "pin the protected base branch so release commands can choose between the direct route and the release-candidate route",
141
+ reasonCode: "release_branch_pr_base_unresolved",
142
+ },
143
+ }),
144
+ });
145
+ }
146
+ if (currentBranch !== baseBranch) {
147
+ throw new CliError({
148
+ exitCode: exitCodeForError("E_VALIDATION"),
149
+ code: "E_VALIDATION",
150
+ message: "release apply is not available on branch_pr task branches.\n" +
151
+ "Use `agentplane release candidate` to prepare and optionally push the release candidate branch.",
152
+ context: withDiagnosticContext({ command: "release apply" }, {
153
+ state: "release apply was invoked from a branch_pr candidate branch",
154
+ likelyCause: "branch_pr repositories must prepare release candidates on dedicated non-base branches and publish only after merge into the protected base branch",
155
+ nextAction: {
156
+ command: "agentplane release candidate",
157
+ reason: "prepare the release candidate on the current branch instead of treating it as a direct publish route",
158
+ reasonCode: "release_apply_branch_pr_candidate_requires_explicit_route",
159
+ },
160
+ }),
161
+ });
162
+ }
163
+ throw new CliError({
164
+ exitCode: exitCodeForError("E_VALIDATION"),
165
+ code: "E_VALIDATION",
166
+ message: "release apply is not available in branch_pr mode.\n" +
167
+ "Prepare the release candidate on a dedicated branch, merge it into the protected base branch, then let hosted publish run from main.",
168
+ context: withDiagnosticContext({ command: "release apply" }, {
169
+ state: "release apply was invoked from a branch_pr base checkout",
170
+ likelyCause: "branch_pr repositories publish from the merged base branch, so local direct release apply should not act as the publication route",
171
+ nextAction: {
172
+ command: "agentplane release candidate",
173
+ reason: "run the explicit release-candidate route from a dedicated non-base branch/worktree before merging to the protected base branch",
174
+ reasonCode: "release_apply_branch_pr_base_requires_candidate_route",
175
+ },
176
+ }),
177
+ });
178
+ }
179
+ async function resolveReleaseCandidateRoute(opts) {
180
+ const loaded = await loadConfig(opts.agentplaneDir);
181
+ const workflowMode = loaded.config.workflow_mode;
182
+ const currentBranch = await gitCurrentBranch(opts.gitRoot);
183
+ if (workflowMode !== "branch_pr") {
184
+ throw new CliError({
185
+ exitCode: exitCodeForError("E_VALIDATION"),
186
+ code: "E_VALIDATION",
187
+ message: "release candidate is only available when workflow_mode=branch_pr.\n" +
188
+ "Use `agentplane release apply` for direct-mode releases.",
189
+ context: withDiagnosticContext({ command: "release candidate" }, {
190
+ state: "release candidate was invoked outside branch_pr mode",
191
+ likelyCause: "direct-mode repositories have no protected-base candidate route, so release preparation and publication stay on the direct release path",
192
+ nextAction: {
193
+ command: "agentplane release apply",
194
+ reason: "use the direct release route when the repository workflow mode is not branch_pr",
195
+ reasonCode: "release_candidate_requires_branch_pr_mode",
196
+ },
197
+ }),
198
+ });
199
+ }
200
+ const baseBranch = await resolveBaseBranch({
201
+ cwd: opts.cwd,
202
+ rootOverride: opts.rootOverride ?? null,
203
+ mode: workflowMode,
204
+ });
205
+ if (!baseBranch) {
206
+ throw new CliError({
207
+ exitCode: exitCodeForError("E_VALIDATION"),
208
+ code: "E_VALIDATION",
209
+ message: "Release candidate routing in branch_pr mode requires a resolved base branch.\n" +
210
+ "Pin it with `agentplane branch base set <branch>` or configure origin/HEAD before rerunning.",
211
+ context: withDiagnosticContext({ command: "release candidate" }, {
212
+ state: "branch_pr release-candidate routing could not resolve the protected base branch",
213
+ likelyCause: "the candidate route must know which protected branch will eventually receive and publish the release candidate",
214
+ nextAction: {
215
+ command: "agentplane branch base set <branch>",
216
+ reason: "pin the protected base branch so release candidate routing can target the correct merge branch",
217
+ reasonCode: "release_candidate_base_unresolved",
218
+ },
219
+ }),
220
+ });
221
+ }
222
+ if (currentBranch === baseBranch) {
223
+ throw new CliError({
224
+ exitCode: exitCodeForError("E_VALIDATION"),
225
+ code: "E_VALIDATION",
226
+ message: "release candidate must run from a dedicated non-base branch/worktree in branch_pr mode.\n" +
227
+ `Current branch ${currentBranch} is the protected base branch ${baseBranch}.`,
228
+ context: withDiagnosticContext({ command: "release candidate" }, {
229
+ state: "release candidate was invoked from the protected base branch",
230
+ likelyCause: "branch_pr release candidates must be prepared on a dedicated branch so the hosted PR becomes the promotion boundary into the protected base branch",
231
+ nextAction: {
232
+ command: "agentplane work start <task-id> --agent CODER --slug <slug> --worktree",
233
+ reason: "create or switch to a dedicated release-candidate branch/worktree before preparing the candidate",
234
+ reasonCode: "release_candidate_requires_non_base_branch",
235
+ },
236
+ }),
237
+ });
238
+ }
239
+ return {
240
+ kind: "release_candidate",
241
+ workflow_mode: workflowMode,
242
+ current_branch: currentBranch,
243
+ base_branch: baseBranch,
244
+ };
245
+ }
107
246
  async function applyReleaseMutation(opts) {
108
247
  let releaseCommit = null;
109
248
  await Promise.all([
@@ -133,7 +272,12 @@ async function applyReleaseMutation(opts) {
133
272
  output.line("No changes to commit.");
134
273
  return { releaseCommit };
135
274
  }
136
- const subject = `✨ release: ${opts.nextTag}`;
275
+ const taskId = opts.route.kind === "release_candidate"
276
+ ? parseTaskIdFromBranch(opts.taskBranchPrefix, opts.route.current_branch)
277
+ : null;
278
+ const subject = taskId
279
+ ? `✨ ${extractTaskSuffix(taskId)} release: publish ${opts.nextTag}`
280
+ : `✨ release: publish ${opts.nextTag}`;
137
281
  await opts.git.commit({ message: subject, env: cleanHookEnv() });
138
282
  const { stdout: headHash } = await execFileAsync("git", ["rev-parse", "HEAD"], {
139
283
  cwd: opts.gitRoot,
@@ -143,14 +287,32 @@ async function applyReleaseMutation(opts) {
143
287
  return { releaseCommit };
144
288
  }
145
289
  async function finalizeReleaseApply(opts) {
146
- await execFileAsync("git", ["tag", opts.plan.nextTag], {
147
- cwd: opts.gitRoot,
148
- env: gitEnv(),
149
- });
150
- output.line(`Release tag created: ${opts.plan.nextTag}`);
290
+ const tagCreated = opts.route.kind === "direct_release";
291
+ const pushedRefs = [];
292
+ if (tagCreated) {
293
+ await execFileAsync("git", ["tag", opts.plan.nextTag], {
294
+ cwd: opts.gitRoot,
295
+ env: gitEnv(),
296
+ });
297
+ output.line(`Release tag created: ${opts.plan.nextTag}`);
298
+ }
299
+ else {
300
+ output.line(`Release candidate prepared on ${opts.route.current_branch}; skipped local tag creation for ${opts.plan.nextTag} because final publication is deferred until merge to ${opts.route.base_branch}.`);
301
+ }
151
302
  if (opts.push) {
152
- await pushReleaseRefs(opts.gitRoot, opts.remote, opts.plan.nextTag);
153
- output.line(`Pushed: ${opts.remote} HEAD + ${opts.plan.nextTag}`);
303
+ if (opts.route.kind === "release_candidate") {
304
+ await pushReleaseCandidateBranch(opts.gitRoot, opts.remote);
305
+ pushedRefs.push("HEAD");
306
+ output.line(`Pushed: ${opts.remote} ${opts.route.current_branch} (release candidate branch only; no tag pushed)`);
307
+ }
308
+ else {
309
+ await pushReleaseRefs(opts.gitRoot, opts.remote, opts.plan.nextTag);
310
+ pushedRefs.push("HEAD", opts.plan.nextTag);
311
+ output.line(`Pushed: ${opts.remote} HEAD + ${opts.plan.nextTag}`);
312
+ }
313
+ }
314
+ else if (opts.route.kind === "release_candidate") {
315
+ output.line(`Next: git push <remote> HEAD # merge ${opts.route.current_branch} into ${opts.route.base_branch} before publishing ${opts.plan.nextTag}`);
154
316
  }
155
317
  else {
156
318
  output.line(`Next: git push <remote> HEAD && git push <remote> ${opts.plan.nextTag}`);
@@ -171,7 +333,18 @@ async function finalizeReleaseApply(opts) {
171
333
  npm_version_available_checked: opts.npmVersionChecked,
172
334
  },
173
335
  commit: opts.releaseCommit,
174
- push: { requested: opts.push, remote: opts.remote, performed: opts.push },
336
+ route: opts.route,
337
+ tag: {
338
+ name: opts.plan.nextTag,
339
+ created: tagCreated,
340
+ pushed: tagCreated && opts.push,
341
+ },
342
+ push: {
343
+ requested: opts.push,
344
+ remote: opts.remote,
345
+ performed: pushedRefs.length > 0,
346
+ refs: pushedRefs,
347
+ },
175
348
  });
176
349
  output.line(`Release report: ${path.relative(opts.gitRoot, reportPath)}`);
177
350
  return 0;
@@ -179,8 +352,8 @@ async function finalizeReleaseApply(opts) {
179
352
  export const releaseApplySpec = {
180
353
  id: ["release", "apply"],
181
354
  group: "Release",
182
- summary: "Apply a prepared release: bump versions, validate notes, commit, and tag.",
183
- description: "Applies a release plan generated by `agentplane release plan`. This command does not author release notes; it expects a DOCS agent to have written docs/releases/vX.Y.Z.md. By default it applies a patch bump; minor/major bumps require explicit approval.",
355
+ summary: "Apply a prepared direct-mode release: bump versions, validate notes, commit, and tag.",
356
+ description: "Applies a release plan generated by `agentplane release plan` on the direct release route. This command does not author release notes; it expects a DOCS agent to have written docs/releases/vX.Y.Z.md. In branch_pr repositories, use `agentplane release candidate` on a dedicated non-base branch instead.",
184
357
  options: [
185
358
  {
186
359
  kind: "string",
@@ -192,8 +365,8 @@ export const releaseApplySpec = {
192
365
  kind: "boolean",
193
366
  name: "push",
194
367
  default: false,
195
- description: "Mandatory for real releases: push commit and tag so GitHub publish workflow can publish to npm " +
196
- "(requires --yes). Local tests can skip with AGENTPLANE_RELEASE_DRY_RUN=1.",
368
+ description: "Optional direct-push mode: push the release commit and tag immediately " +
369
+ "(requires --yes). This is for the direct release route only.",
197
370
  },
198
371
  {
199
372
  kind: "string",
@@ -217,13 +390,6 @@ export const releaseApplySpec = {
217
390
  };
218
391
  },
219
392
  validate: (p) => {
220
- if (!p.push && process.env.AGENTPLANE_RELEASE_DRY_RUN !== "1") {
221
- throw usageError({
222
- spec: releaseApplySpec,
223
- command: "release apply",
224
- message: "Release publish is mandatory. Run `agentplane release apply --push --yes`.",
225
- });
226
- }
227
393
  if (p.push && p.yes !== true) {
228
394
  throw usageError({
229
395
  spec: releaseApplySpec,
@@ -242,7 +408,7 @@ export const releaseApplySpec = {
242
408
  examples: [
243
409
  {
244
410
  cmd: "agentplane release apply",
245
- why: "Apply the latest release plan (expects docs/releases/vX.Y.Z.md to exist).",
411
+ why: "Apply the latest release plan locally (expects docs/releases/vX.Y.Z.md to exist).",
246
412
  },
247
413
  {
248
414
  cmd: "agentplane release apply --plan .agentplane/.release/plan/<runId>",
@@ -254,14 +420,71 @@ export const releaseApplySpec = {
254
420
  },
255
421
  ],
256
422
  };
423
+ const releaseCandidateOptions = [
424
+ {
425
+ kind: "string",
426
+ name: "plan",
427
+ valueHint: "<path>",
428
+ description: "Path to a release plan directory (defaults to the latest under .agentplane/.release/plan/).",
429
+ },
430
+ {
431
+ kind: "boolean",
432
+ name: "push",
433
+ default: false,
434
+ description: "Optional candidate-push mode: push only the release candidate branch for hosted review and merge (requires --yes). The release tag is not created or pushed here.",
435
+ },
436
+ {
437
+ kind: "string",
438
+ name: "remote",
439
+ valueHint: "<name>",
440
+ description: "Git remote to push to (default: origin).",
441
+ },
442
+ {
443
+ kind: "boolean",
444
+ name: "yes",
445
+ default: false,
446
+ description: "Approve minor/major bumps and allow pushing. Patch bumps can be applied without this flag.",
447
+ },
448
+ ];
449
+ export const releaseCandidateSpec = {
450
+ id: ["release", "candidate"],
451
+ group: "Release",
452
+ summary: "Prepare a branch_pr release candidate: bump versions, validate notes, commit, and optionally push the candidate branch.",
453
+ description: "Prepares a release candidate from a generated release plan on a dedicated non-base branch in branch_pr mode. This command creates the candidate commit but intentionally does not create or push the release tag; final publication remains gated on merge to the protected base branch and hosted publish from main.",
454
+ options: releaseCandidateOptions,
455
+ parse: releaseApplySpec.parse,
456
+ validate: (p) => {
457
+ if (p.push && p.yes !== true) {
458
+ throw usageError({
459
+ spec: releaseCandidateSpec,
460
+ command: "release candidate",
461
+ message: "Option --push requires explicit approval. Re-run with --yes.",
462
+ });
463
+ }
464
+ if (!p.remote.trim()) {
465
+ throw usageError({
466
+ spec: releaseCandidateSpec,
467
+ command: "release candidate",
468
+ message: "Option --remote must be non-empty.",
469
+ });
470
+ }
471
+ },
472
+ examples: [
473
+ {
474
+ cmd: "agentplane release candidate",
475
+ why: "Prepare the latest release plan on the current branch_pr candidate branch.",
476
+ },
477
+ {
478
+ cmd: "agentplane release candidate --plan .agentplane/.release/plan/<runId>",
479
+ why: "Prepare a specific release plan on the current candidate branch.",
480
+ },
481
+ {
482
+ cmd: "agentplane release candidate --push --yes",
483
+ why: "Prepare and push only the release candidate branch for hosted review and merge.",
484
+ },
485
+ ],
486
+ };
257
487
  export const runReleaseApply = async (ctx, flags) => {
258
- if (!flags.push && process.env.AGENTPLANE_RELEASE_DRY_RUN !== "1") {
259
- throw usageError({
260
- spec: releaseApplySpec,
261
- command: "release apply",
262
- message: "Release publish is mandatory. Run `agentplane release apply --push --yes`.",
263
- });
264
- }
265
488
  return await runOperatorPipeline({
266
489
  init: async () => {
267
490
  const resolved = await resolveProject({
@@ -273,12 +496,20 @@ export const runReleaseApply = async (ctx, flags) => {
273
496
  gitRoot,
274
497
  planOverride: flags.plan,
275
498
  });
499
+ const loaded = await loadConfig(resolved.agentplaneDir);
276
500
  return {
277
501
  resolved,
278
502
  gitRoot,
279
503
  planDir,
280
504
  plan,
281
505
  notesPath,
506
+ taskBranchPrefix: loaded.config.branch.task_prefix,
507
+ route: await resolveDirectReleaseRoute({
508
+ cwd: ctx.cwd,
509
+ rootOverride: ctx.rootOverride ?? null,
510
+ gitRoot,
511
+ agentplaneDir: resolved.agentplaneDir,
512
+ }),
282
513
  corePkgPath: path.join(gitRoot, "packages", "core", "package.json"),
283
514
  agentplanePkgPath: path.join(gitRoot, "packages", "agentplane", "package.json"),
284
515
  npmVersionChecked: false,
@@ -305,7 +536,95 @@ export const runReleaseApply = async (ctx, flags) => {
305
536
  remote: flags.remote,
306
537
  nextTag: state.plan.nextTag,
307
538
  nextVersion: state.plan.nextVersion,
539
+ route: state.route,
540
+ yes: flags.yes,
541
+ commandLabel: "release apply --push",
542
+ });
543
+ }
544
+ },
545
+ execute: async (state) => {
546
+ const git = new GitContext({ gitRoot: state.gitRoot });
547
+ return await applyReleaseMutation({
548
+ agentplaneDir: state.resolved.agentplaneDir,
549
+ gitRoot: state.gitRoot,
550
+ git,
551
+ notesPath: state.notesPath,
552
+ corePkgPath: state.corePkgPath,
553
+ agentplanePkgPath: state.agentplanePkgPath,
554
+ nextTag: state.plan.nextTag,
555
+ nextVersion: state.plan.nextVersion,
556
+ route: state.route,
557
+ taskBranchPrefix: state.taskBranchPrefix,
558
+ });
559
+ },
560
+ finalize: async (state, mutation) => await finalizeReleaseApply({
561
+ gitRoot: state.gitRoot,
562
+ planDir: state.planDir,
563
+ notesPath: state.notesPath,
564
+ plan: state.plan,
565
+ npmVersionChecked: state.npmVersionChecked,
566
+ releaseCommit: mutation.releaseCommit,
567
+ route: state.route,
568
+ push: flags.push,
569
+ remote: flags.remote,
570
+ }),
571
+ });
572
+ };
573
+ export const runReleaseCandidate = async (ctx, flags) => {
574
+ return await runOperatorPipeline({
575
+ init: async () => {
576
+ const resolved = await resolveProject({
577
+ cwd: ctx.cwd,
578
+ rootOverride: ctx.rootOverride ?? null,
579
+ });
580
+ const gitRoot = resolved.gitRoot;
581
+ const { planDir, plan, notesPath } = await resolveReleasePlanInputs({
582
+ gitRoot,
583
+ planOverride: flags.plan,
584
+ });
585
+ const loaded = await loadConfig(resolved.agentplaneDir);
586
+ return {
587
+ resolved,
588
+ gitRoot,
589
+ planDir,
590
+ plan,
591
+ notesPath,
592
+ taskBranchPrefix: loaded.config.branch.task_prefix,
593
+ route: await resolveReleaseCandidateRoute({
594
+ cwd: ctx.cwd,
595
+ rootOverride: ctx.rootOverride ?? null,
596
+ gitRoot,
597
+ agentplaneDir: resolved.agentplaneDir,
598
+ }),
599
+ corePkgPath: path.join(gitRoot, "packages", "core", "package.json"),
600
+ agentplanePkgPath: path.join(gitRoot, "packages", "agentplane", "package.json"),
601
+ npmVersionChecked: false,
602
+ };
603
+ },
604
+ preflight: async (state) => {
605
+ if ((state.plan.bump === "minor" || state.plan.bump === "major") && flags.yes !== true) {
606
+ throw usageError({
607
+ spec: releaseCandidateSpec,
608
+ command: "release candidate",
609
+ message: `Bump '${state.plan.bump}' requires explicit approval. Re-run with --yes.`,
610
+ });
611
+ }
612
+ await ensureReleasePlanMatchesRepoState({
613
+ gitRoot: state.gitRoot,
614
+ plan: state.plan,
615
+ corePkgPath: state.corePkgPath,
616
+ agentplanePkgPath: state.agentplanePkgPath,
617
+ });
618
+ if (flags.push) {
619
+ state.npmVersionChecked = await runPushPreflight({
620
+ agentplaneDir: state.resolved.agentplaneDir,
621
+ gitRoot: state.gitRoot,
622
+ remote: flags.remote,
623
+ nextTag: state.plan.nextTag,
624
+ nextVersion: state.plan.nextVersion,
625
+ route: state.route,
308
626
  yes: flags.yes,
627
+ commandLabel: "release candidate --push",
309
628
  });
310
629
  }
311
630
  },
@@ -320,6 +639,8 @@ export const runReleaseApply = async (ctx, flags) => {
320
639
  agentplanePkgPath: state.agentplanePkgPath,
321
640
  nextTag: state.plan.nextTag,
322
641
  nextVersion: state.plan.nextVersion,
642
+ route: state.route,
643
+ taskBranchPrefix: state.taskBranchPrefix,
323
644
  });
324
645
  },
325
646
  finalize: async (state, mutation) => await finalizeReleaseApply({
@@ -329,9 +650,10 @@ export const runReleaseApply = async (ctx, flags) => {
329
650
  plan: state.plan,
330
651
  npmVersionChecked: state.npmVersionChecked,
331
652
  releaseCommit: mutation.releaseCommit,
653
+ route: state.route,
332
654
  push: flags.push,
333
655
  remote: flags.remote,
334
656
  }),
335
657
  });
336
658
  };
337
- export { pushReleaseRefs } from "./apply.reporting.js";
659
+ export { pushReleaseCandidateBranch, pushReleaseRefs } from "./apply.reporting.js";
@@ -1 +1 @@
1
- {"version":3,"file":"apply.mutation.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.mutation.ts"],"names":[],"mappings":"AASA,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,wBAAsB,gCAAgC,CACpD,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAC1C,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,wBAAsB,8BAA8B,CAClD,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAC1C,OAAO,CAAC,OAAO,CAAC,CAyBlB;AAED,wBAAsB,8BAA8B,CAClD,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED,wBAAgB,YAAY,IAAI,MAAM,CAAC,UAAU,CAMhD"}
1
+ {"version":3,"file":"apply.mutation.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.mutation.ts"],"names":[],"mappings":"AASA,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,wBAAsB,gCAAgC,CACpD,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAC1C,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,wBAAsB,8BAA8B,CAClD,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAC1C,OAAO,CAAC,OAAO,CAAC,CAyBlB;AAED,wBAAsB,8BAA8B,CAClD,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED,wBAAgB,YAAY,IAAI,MAAM,CAAC,UAAU,CAOhD"}
@@ -103,5 +103,6 @@ export function cleanHookEnv() {
103
103
  delete env.AGENTPLANE_TASK_ID;
104
104
  delete env.AGENTPLANE_STATUS_TO;
105
105
  delete env.AGENTPLANE_AGENT_ID;
106
+ env.AGENTPLANE_ALLOW_CONFIG = "1";
106
107
  return env;
107
108
  }
@@ -1 +1 @@
1
- {"version":3,"file":"apply.preflight.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.preflight.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEvE,wBAAsB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO5D;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAE3D;AAaD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAuBjE;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBxE;AAED,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW7E;AAED,wBAAsB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBpF;AAED,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB/F;AAED,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC3E;AAED,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BvF;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BvF;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC,CAyDf;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmChG;AAED,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C7E;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC;IAC/F,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAwBD"}
1
+ {"version":3,"file":"apply.preflight.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.preflight.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEvE,wBAAsB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO5D;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAE3D;AAaD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAuBjE;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBxE;AAED,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW7E;AAED,wBAAsB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBpF;AAED,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB/F;AAED,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgC3E;AAED,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BvF;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BvF;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC,CAyDf;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmChG;AAED,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C7E;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC;IAC/F,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAwBD"}
@@ -140,7 +140,7 @@ export async function ensureCleanTrackedTree(gitRoot) {
140
140
  likelyCause: "the release flow needs to create one deterministic version-bump commit and tag, but tracked edits already exist in the workspace",
141
141
  nextAction: {
142
142
  command: "git status --short --untracked-files=no",
143
- reason: "inspect or clear tracked changes before rerunning `agentplane release apply --push --yes`",
143
+ reason: "inspect or clear tracked changes before rerunning `agentplane release apply`",
144
144
  reasonCode: "release_dirty_tree",
145
145
  },
146
146
  }),
@@ -1,4 +1,5 @@
1
1
  import type { ReleaseApplyReport } from "./apply.types.js";
2
2
  export declare function writeReleaseApplyReport(gitRoot: string, report: ReleaseApplyReport): Promise<string>;
3
3
  export declare function pushReleaseRefs(gitRoot: string, remote: string, tag: string): Promise<void>;
4
+ export declare function pushReleaseCandidateBranch(gitRoot: string, remote: string): Promise<void>;
4
5
  //# sourceMappingURL=apply.reporting.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"apply.reporting.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.reporting.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASjG"}
1
+ {"version":3,"file":"apply.reporting.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.reporting.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAe3D,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjG;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/F"}
@@ -1,6 +1,14 @@
1
1
  import { mkdir, writeFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { execFileAsync, gitEnv } from "../shared/git.js";
4
+ async function pushRefspecsNoVerify(gitRoot, remote, refspecs) {
5
+ for (const refspec of refspecs) {
6
+ await execFileAsync("git", ["push", "--no-verify", remote, refspec], {
7
+ cwd: gitRoot,
8
+ env: gitEnv(),
9
+ });
10
+ }
11
+ }
4
12
  export async function writeReleaseApplyReport(gitRoot, report) {
5
13
  const runId = new Date().toISOString().replaceAll(":", "-").replaceAll(".", "-");
6
14
  const dir = path.join(gitRoot, ".agentplane", ".release", "apply");
@@ -13,12 +21,8 @@ export async function writeReleaseApplyReport(gitRoot, report) {
13
21
  return reportPath;
14
22
  }
15
23
  export async function pushReleaseRefs(gitRoot, remote, tag) {
16
- await execFileAsync("git", ["push", "--no-verify", remote, "HEAD"], {
17
- cwd: gitRoot,
18
- env: gitEnv(),
19
- });
20
- await execFileAsync("git", ["push", "--no-verify", remote, tag], {
21
- cwd: gitRoot,
22
- env: gitEnv(),
23
- });
24
+ await pushRefspecsNoVerify(gitRoot, remote, ["HEAD", tag]);
25
+ }
26
+ export async function pushReleaseCandidateBranch(gitRoot, remote) {
27
+ await pushRefspecsNoVerify(gitRoot, remote, ["HEAD"]);
24
28
  }
@@ -13,6 +13,12 @@ export type ReleaseVersionPlan = {
13
13
  nextVersion: string;
14
14
  bump: BumpKind;
15
15
  };
16
+ export type ReleaseApplyRoute = {
17
+ kind: "direct_release" | "release_candidate";
18
+ workflow_mode: "direct" | "branch_pr";
19
+ current_branch: string;
20
+ base_branch: string | null;
21
+ };
16
22
  export type PlanChange = {
17
23
  hash: string;
18
24
  authorDateIso: string;
@@ -37,10 +43,17 @@ export type ReleaseApplyReport = {
37
43
  hash: string;
38
44
  subject: string;
39
45
  } | null;
46
+ route: ReleaseApplyRoute;
47
+ tag: {
48
+ name: string;
49
+ created: boolean;
50
+ pushed: boolean;
51
+ };
40
52
  push: {
41
53
  requested: boolean;
42
54
  remote: string;
43
55
  performed: boolean;
56
+ refs: string[];
44
57
  };
45
58
  };
46
59
  //# sourceMappingURL=apply.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"apply.types.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAEnD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,QAAQ,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE;QACN,kBAAkB,EAAE,IAAI,CAAC;QACzB,UAAU,EAAE,IAAI,CAAC;QACjB,eAAe,EAAE,IAAI,CAAC;QACtB,6BAA6B,EAAE,OAAO,CAAC;KACxC,CAAC;IACF,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,IAAI,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;CAClE,CAAC"}
1
+ {"version":3,"file":"apply.types.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAEnD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,QAAQ,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;IAC7C,aAAa,EAAE,QAAQ,GAAG,WAAW,CAAC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE;QACN,kBAAkB,EAAE,IAAI,CAAC;QACzB,UAAU,EAAE,IAAI,CAAC;QACjB,eAAe,EAAE,IAAI,CAAC;QACtB,6BAA6B,EAAE,OAAO,CAAC;KACxC,CAAC;IACF,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,KAAK,EAAE,iBAAiB,CAAC;IACzB,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IACzD,IAAI,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAClF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"plan.command.d.ts","sourceRoot":"","sources":["../../../src/commands/release/plan.command.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAO1E,KAAK,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAE5C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;AA4IjD,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,iBAAiB,CA4E1D,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,iBAAiB,CAqE5D,CAAC"}
1
+ {"version":3,"file":"plan.command.d.ts","sourceRoot":"","sources":["../../../src/commands/release/plan.command.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAO1E,KAAK,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAE5C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;AAkLjD,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,iBAAiB,CA4E1D,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,iBAAiB,CAiF5D,CAAC"}