agentplane 0.2.18 → 0.2.21
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.
- package/assets/AGENTS.md +4 -3
- package/bin/agentplane.js +24 -0
- package/dist/backends/task-backend/load.d.ts +2 -0
- package/dist/backends/task-backend/load.d.ts.map +1 -1
- package/dist/backends/task-backend/load.js +38 -18
- package/dist/cli/command-guide.d.ts.map +1 -1
- package/dist/cli/command-guide.js +12 -11
- package/dist/cli/run-cli/command-catalog.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog.js +12 -1
- package/dist/cli/run-cli/commands/core.d.ts +9 -1
- package/dist/cli/run-cli/commands/core.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/core.js +268 -8
- package/dist/cli/run-cli/commands/init/write-config.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-config.js +2 -0
- package/dist/cli/run-cli/commands/init/write-gitignore.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-gitignore.js +3 -18
- package/dist/cli/run-cli/commands/init.d.ts +1 -0
- package/dist/cli/run-cli/commands/init.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init.js +55 -30
- package/dist/cli/run-cli.d.ts.map +1 -1
- package/dist/cli/run-cli.js +85 -14
- package/dist/commands/commit.command.d.ts.map +1 -1
- package/dist/commands/commit.command.js +2 -0
- package/dist/commands/commit.spec.d.ts +2 -0
- package/dist/commands/commit.spec.d.ts.map +1 -1
- package/dist/commands/commit.spec.js +26 -0
- package/dist/commands/doctor.run.d.ts.map +1 -1
- package/dist/commands/doctor.run.js +15 -6
- package/dist/commands/finish.run.d.ts.map +1 -1
- package/dist/commands/finish.run.js +2 -0
- package/dist/commands/finish.spec.d.ts +2 -0
- package/dist/commands/finish.spec.d.ts.map +1 -1
- package/dist/commands/finish.spec.js +36 -0
- package/dist/commands/guard/impl/allow.d.ts.map +1 -1
- package/dist/commands/guard/impl/allow.js +33 -7
- package/dist/commands/guard/impl/commands.d.ts +2 -0
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +24 -4
- package/dist/commands/guard/impl/comment-commit.d.ts +1 -0
- package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
- package/dist/commands/guard/impl/comment-commit.js +16 -24
- package/dist/commands/release/apply.command.d.ts.map +1 -1
- package/dist/commands/release/apply.command.js +79 -3
- package/dist/commands/release/plan.command.d.ts.map +1 -1
- package/dist/commands/release/plan.command.js +25 -1
- package/dist/commands/shared/task-backend.d.ts +3 -0
- package/dist/commands/shared/task-backend.d.ts.map +1 -1
- package/dist/commands/shared/task-backend.js +4 -1
- package/dist/commands/task/block.d.ts.map +1 -1
- package/dist/commands/task/block.js +12 -9
- package/dist/commands/task/close-duplicate.command.d.ts +14 -0
- package/dist/commands/task/close-duplicate.command.d.ts.map +1 -0
- package/dist/commands/task/close-duplicate.command.js +102 -0
- package/dist/commands/task/close-duplicate.d.ts +14 -0
- package/dist/commands/task/close-duplicate.d.ts.map +1 -0
- package/dist/commands/task/close-duplicate.js +90 -0
- package/dist/commands/task/close-noop.command.d.ts +14 -0
- package/dist/commands/task/close-noop.command.d.ts.map +1 -0
- package/dist/commands/task/close-noop.command.js +77 -0
- package/dist/commands/task/close-noop.d.ts +13 -0
- package/dist/commands/task/close-noop.d.ts.map +1 -0
- package/dist/commands/task/close-noop.js +77 -0
- package/dist/commands/task/finish.d.ts +2 -0
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +52 -10
- package/dist/commands/task/index.d.ts +3 -0
- package/dist/commands/task/index.d.ts.map +1 -1
- package/dist/commands/task/index.js +3 -0
- package/dist/commands/task/new.d.ts.map +1 -1
- package/dist/commands/task/new.js +34 -6
- package/dist/commands/task/new.spec.js +1 -1
- package/dist/commands/task/plan.d.ts.map +1 -1
- package/dist/commands/task/plan.js +2 -3
- package/dist/commands/task/set-status.d.ts.map +1 -1
- package/dist/commands/task/set-status.js +12 -9
- package/dist/commands/task/shared.d.ts +19 -0
- package/dist/commands/task/shared.d.ts.map +1 -1
- package/dist/commands/task/shared.js +137 -0
- package/dist/commands/task/start-ready.command.d.ts +14 -0
- package/dist/commands/task/start-ready.command.d.ts.map +1 -0
- package/dist/commands/task/start-ready.command.js +77 -0
- package/dist/commands/task/start-ready.d.ts +13 -0
- package/dist/commands/task/start-ready.d.ts.map +1 -0
- package/dist/commands/task/start-ready.js +46 -0
- package/dist/commands/task/start.d.ts.map +1 -1
- package/dist/commands/task/start.js +13 -11
- package/dist/commands/task/update.command.d.ts +1 -0
- package/dist/commands/task/update.command.d.ts.map +1 -1
- package/dist/commands/task/update.command.js +8 -0
- package/dist/commands/task/update.d.ts +1 -0
- package/dist/commands/task/update.d.ts.map +1 -1
- package/dist/commands/task/update.js +19 -3
- package/dist/shared/errors.d.ts +9 -1
- package/dist/shared/errors.d.ts.map +1 -1
- package/dist/shared/errors.js +3 -1
- package/dist/shared/runtime-artifacts.d.ts +3 -0
- package/dist/shared/runtime-artifacts.d.ts.map +1 -0
- package/dist/shared/runtime-artifacts.js +18 -0
- package/dist/usecases/context/resolve-context.d.ts +3 -0
- package/dist/usecases/context/resolve-context.d.ts.map +1 -1
- package/dist/usecases/context/resolve-context.js +6 -1
- package/package.json +5 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/commands.ts"],"names":[],"mappings":"AAGA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/commands.ts"],"names":[],"mappings":"AAGA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAOvF,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAyDxE,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBlB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBlB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAS9E;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB,EAAE,OAAO,CAAC;IAC5B,cAAc,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyJlB"}
|
|
@@ -3,6 +3,7 @@ import { successMessage } from "../../../cli/output.js";
|
|
|
3
3
|
import { CliError } from "../../../shared/errors.js";
|
|
4
4
|
import { loadCommandContext } from "../../shared/task-backend.js";
|
|
5
5
|
import { loadTaskFromContext } from "../../shared/task-backend.js";
|
|
6
|
+
import { execFileAsync, gitEnv } from "../../shared/git.js";
|
|
6
7
|
import { suggestAllowPrefixes } from "./allow.js";
|
|
7
8
|
import { buildCloseCommitMessage, taskReadmePathForTask } from "./close-message.js";
|
|
8
9
|
import { buildGitCommitEnv } from "./env.js";
|
|
@@ -126,13 +127,22 @@ export async function cmdCommit(opts) {
|
|
|
126
127
|
if (opts.close) {
|
|
127
128
|
const ctx = opts.ctx ??
|
|
128
129
|
(await loadCommandContext({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null }));
|
|
129
|
-
// Make the close commit deterministic:
|
|
130
|
-
|
|
131
|
-
if (staged.length > 0) {
|
|
130
|
+
// Make the close commit deterministic: start from a clean index unless --unstage-others is used.
|
|
131
|
+
let staged = await ctx.git.statusStagedPaths();
|
|
132
|
+
if (staged.length > 0 && opts.closeUnstageOthers) {
|
|
133
|
+
if (!opts.closeCheckOnly) {
|
|
134
|
+
await execFileAsync("git", ["restore", "--staged", "--", "."], {
|
|
135
|
+
cwd: ctx.resolvedProject.gitRoot,
|
|
136
|
+
env: gitEnv(),
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
staged = opts.closeCheckOnly ? staged : await ctx.git.statusStagedPaths();
|
|
140
|
+
}
|
|
141
|
+
if (staged.length > 0 && !opts.closeUnstageOthers) {
|
|
132
142
|
throw new CliError({
|
|
133
143
|
exitCode: 5,
|
|
134
144
|
code: "E_GIT",
|
|
135
|
-
message: "Staged files exist (close commit requires an empty index)",
|
|
145
|
+
message: "Staged files exist (close commit requires an empty index; rerun with --unstage-others to auto-unstage).",
|
|
136
146
|
});
|
|
137
147
|
}
|
|
138
148
|
const task = await loadTaskFromContext({ ctx, taskId: opts.taskId });
|
|
@@ -145,6 +155,16 @@ export async function cmdCommit(opts) {
|
|
|
145
155
|
const readmeRel = readmeAbs.startsWith(ctx.resolvedProject.gitRoot)
|
|
146
156
|
? readmeAbs.slice(ctx.resolvedProject.gitRoot.length + 1)
|
|
147
157
|
: readmeAbs;
|
|
158
|
+
if (opts.closeCheckOnly) {
|
|
159
|
+
if (!opts.quiet) {
|
|
160
|
+
const stagedCount = staged.length;
|
|
161
|
+
const suffix = stagedCount > 0 && opts.closeUnstageOthers
|
|
162
|
+
? `; would unstage ${stagedCount} path(s)`
|
|
163
|
+
: "";
|
|
164
|
+
process.stdout.write(`${successMessage("close preflight", opts.taskId, `subject=${msg.subject}${suffix}`)}\n`);
|
|
165
|
+
}
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
148
168
|
await ctx.git.stage([readmeRel]);
|
|
149
169
|
// Close commits should not require manual --allow flags:
|
|
150
170
|
// the command stages exactly one task README under workflow_dir.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comment-commit.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/comment-commit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAS/E,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"comment-commit.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/comment-commit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAS/E,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAiEvF,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,gBAAgB,CAAC;CAC1B,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA+F/D"}
|
|
@@ -8,24 +8,6 @@ import { buildGitCommitEnv } from "./env.js";
|
|
|
8
8
|
import { stageAllowlist, suggestAllowPrefixes } from "./allow.js";
|
|
9
9
|
import { guardCommitCheck } from "./policy.js";
|
|
10
10
|
function deriveCommitMessageFromComment(opts) {
|
|
11
|
-
const raw = (opts.formattedComment ?? formatCommentBodyForCommit(opts.body, opts.config))
|
|
12
|
-
.trim()
|
|
13
|
-
.replaceAll(/\s+/g, " ");
|
|
14
|
-
if (!raw) {
|
|
15
|
-
throw new CliError({
|
|
16
|
-
exitCode: 2,
|
|
17
|
-
code: "E_USAGE",
|
|
18
|
-
message: "Comment body is required to build a commit message from the task comment",
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
const summary = raw.replace(/^(start|blocked|verified):\s*/i, "").trim();
|
|
22
|
-
if (!summary) {
|
|
23
|
-
throw new CliError({
|
|
24
|
-
exitCode: 2,
|
|
25
|
-
code: "E_USAGE",
|
|
26
|
-
message: "Comment body is required to build a commit message from the task comment",
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
11
|
const prefix = opts.emoji.trim();
|
|
30
12
|
if (!prefix) {
|
|
31
13
|
throw new CliError({
|
|
@@ -42,15 +24,25 @@ function deriveCommitMessageFromComment(opts) {
|
|
|
42
24
|
message: invalidValueMessage("task id", opts.taskId, "valid task id"),
|
|
43
25
|
});
|
|
44
26
|
}
|
|
45
|
-
|
|
27
|
+
const primary = opts.primaryTag.trim().toLowerCase();
|
|
28
|
+
if (!primary) {
|
|
29
|
+
throw new CliError({
|
|
30
|
+
exitCode: 2,
|
|
31
|
+
code: "E_USAGE",
|
|
32
|
+
message: "Primary tag is required when deriving commit messages from task comments",
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const status = (opts.statusTo?.trim().toLowerCase() ?? "status-transition").replaceAll(/\s+/g, "-");
|
|
36
|
+
return `${prefix} ${suffix} ${primary}: ${status}`;
|
|
46
37
|
}
|
|
47
38
|
function deriveCommitBodyFromComment(opts) {
|
|
48
39
|
const lines = [
|
|
49
40
|
`Task: ${opts.taskId}`,
|
|
41
|
+
`Primary: ${opts.primaryTag}`,
|
|
50
42
|
...(opts.executorAgent ? [`Agent: ${opts.executorAgent}`] : []),
|
|
51
43
|
...(opts.author ? [`Author: ${opts.author}`] : []),
|
|
52
|
-
...(opts.
|
|
53
|
-
`Comment: ${normalizeCommentBodyForCommit(opts.formattedComment
|
|
44
|
+
...(opts.statusTo ? [`Status: ${opts.statusTo}`] : []),
|
|
45
|
+
`Comment: ${normalizeCommentBodyForCommit(opts.formattedComment ?? opts.commentBody)}`,
|
|
54
46
|
];
|
|
55
47
|
return lines.join("\n").trimEnd();
|
|
56
48
|
}
|
|
@@ -88,14 +80,14 @@ export async function commitFromComment(opts) {
|
|
|
88
80
|
});
|
|
89
81
|
const message = deriveCommitMessageFromComment({
|
|
90
82
|
taskId: opts.taskId,
|
|
91
|
-
|
|
83
|
+
primaryTag: opts.primaryTag,
|
|
84
|
+
statusTo: opts.statusTo,
|
|
92
85
|
emoji: opts.emoji,
|
|
93
|
-
formattedComment: opts.formattedComment,
|
|
94
|
-
config: opts.config,
|
|
95
86
|
});
|
|
96
87
|
const formattedComment = opts.formattedComment ?? formatCommentBodyForCommit(opts.commentBody, opts.config);
|
|
97
88
|
const body = deriveCommitBodyFromComment({
|
|
98
89
|
taskId: opts.taskId,
|
|
90
|
+
primaryTag: opts.primaryTag,
|
|
99
91
|
executorAgent: opts.executorAgent,
|
|
100
92
|
author: opts.author,
|
|
101
93
|
statusFrom: opts.statusFrom,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.command.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.command.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAU1E,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;
|
|
1
|
+
{"version":3,"file":"apply.command.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.command.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAU1E,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;AAsVnD,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,kBAAkB,CAwE5D,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,kBAAkB,CAuK9D,CAAC"}
|
|
@@ -82,6 +82,20 @@ async function readPackageVersion(pkgJsonPath) {
|
|
|
82
82
|
}
|
|
83
83
|
return version;
|
|
84
84
|
}
|
|
85
|
+
async function readCoreDependencyVersion(pkgJsonPath) {
|
|
86
|
+
const raw = JSON.parse(await readFile(pkgJsonPath, "utf8"));
|
|
87
|
+
const value = raw.dependencies?.["@agentplaneorg/core"];
|
|
88
|
+
const version = typeof value === "string" ? value.trim() : "";
|
|
89
|
+
if (!version) {
|
|
90
|
+
throw new CliError({
|
|
91
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
92
|
+
code: "E_VALIDATION",
|
|
93
|
+
message: `Missing dependency @agentplaneorg/core in ${pkgJsonPath}. ` +
|
|
94
|
+
"Release parity requires packages/agentplane to pin @agentplaneorg/core to the same version.",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return version;
|
|
98
|
+
}
|
|
85
99
|
async function replacePackageVersionInFile(pkgJsonPath, nextVersion) {
|
|
86
100
|
const text = await readFile(pkgJsonPath, "utf8");
|
|
87
101
|
const replaced = text.replace(/"version"\s*:\s*"[^"]*"/u, `"version": "${nextVersion}"`);
|
|
@@ -94,6 +108,27 @@ async function replacePackageVersionInFile(pkgJsonPath, nextVersion) {
|
|
|
94
108
|
}
|
|
95
109
|
await writeFile(pkgJsonPath, replaced, "utf8");
|
|
96
110
|
}
|
|
111
|
+
async function replaceAgentplanePackageMetadata(pkgJsonPath, nextVersion) {
|
|
112
|
+
const text = await readFile(pkgJsonPath, "utf8");
|
|
113
|
+
const withVersion = text.replace(/"version"\s*:\s*"[^"]*"/u, `"version": "${nextVersion}"`);
|
|
114
|
+
if (withVersion === text) {
|
|
115
|
+
throw new CliError({
|
|
116
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
117
|
+
code: "E_VALIDATION",
|
|
118
|
+
message: `Failed to update version in ${pkgJsonPath} (missing "version" field).`,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const withDependency = withVersion.replace(/("@agentplaneorg\/core"\s*:\s*")[^"]*(")/u, `$1${nextVersion}$2`);
|
|
122
|
+
if (withDependency === withVersion) {
|
|
123
|
+
throw new CliError({
|
|
124
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
125
|
+
code: "E_VALIDATION",
|
|
126
|
+
message: `Failed to update @agentplaneorg/core dependency in ${pkgJsonPath}. ` +
|
|
127
|
+
"Ensure packages/agentplane/package.json declares this dependency.",
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
await writeFile(pkgJsonPath, withDependency, "utf8");
|
|
131
|
+
}
|
|
97
132
|
function cleanHookEnv() {
|
|
98
133
|
const env = { ...gitEnv() };
|
|
99
134
|
delete env.AGENTPLANE_TASK_ID;
|
|
@@ -212,6 +247,33 @@ async function ensureNpmVersionsAvailable(gitRoot, version) {
|
|
|
212
247
|
});
|
|
213
248
|
}
|
|
214
249
|
}
|
|
250
|
+
async function runReleasePrepublishGate(gitRoot) {
|
|
251
|
+
try {
|
|
252
|
+
await execFileAsync("bun", ["run", "release:prepublish"], {
|
|
253
|
+
cwd: gitRoot,
|
|
254
|
+
env: {
|
|
255
|
+
...process.env,
|
|
256
|
+
GIT_AUTHOR_NAME: process.env.GIT_AUTHOR_NAME ?? "agentplane-release",
|
|
257
|
+
GIT_AUTHOR_EMAIL: process.env.GIT_AUTHOR_EMAIL ?? "agentplane-release@example.com",
|
|
258
|
+
GIT_COMMITTER_NAME: process.env.GIT_COMMITTER_NAME ?? "agentplane-release",
|
|
259
|
+
GIT_COMMITTER_EMAIL: process.env.GIT_COMMITTER_EMAIL ?? "agentplane-release@example.com",
|
|
260
|
+
},
|
|
261
|
+
maxBuffer: 200 * 1024 * 1024,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
catch (err) {
|
|
265
|
+
const details = String(err?.stderr ??
|
|
266
|
+
err?.stdout ??
|
|
267
|
+
err?.message ??
|
|
268
|
+
"").trim();
|
|
269
|
+
throw new CliError({
|
|
270
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
271
|
+
code: "E_VALIDATION",
|
|
272
|
+
message: "Release prepublish gate failed. `agentplane release apply --push` requires a successful local `bun run release:prepublish` run before pushing the release tag." +
|
|
273
|
+
(details ? `\n\n${details}` : ""),
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
215
277
|
async function writeReleaseApplyReport(gitRoot, report) {
|
|
216
278
|
const runId = new Date().toISOString().replaceAll(":", "-").replaceAll(".", "-");
|
|
217
279
|
const dir = path.join(gitRoot, ".agentplane", ".release", "apply");
|
|
@@ -332,9 +394,10 @@ export const runReleaseApply = async (ctx, flags) => {
|
|
|
332
394
|
await validateReleaseNotes(notesPath);
|
|
333
395
|
const corePkgPath = path.join(gitRoot, "packages", "core", "package.json");
|
|
334
396
|
const agentplanePkgPath = path.join(gitRoot, "packages", "agentplane", "package.json");
|
|
335
|
-
const [coreVersion, agentplaneVersion] = await Promise.all([
|
|
397
|
+
const [coreVersion, agentplaneVersion, coreDependencyVersion] = await Promise.all([
|
|
336
398
|
readPackageVersion(corePkgPath),
|
|
337
399
|
readPackageVersion(agentplanePkgPath),
|
|
400
|
+
readCoreDependencyVersion(agentplanePkgPath),
|
|
338
401
|
]);
|
|
339
402
|
if (coreVersion !== agentplaneVersion) {
|
|
340
403
|
throw new CliError({
|
|
@@ -344,6 +407,15 @@ export const runReleaseApply = async (ctx, flags) => {
|
|
|
344
407
|
`packages/core=${coreVersion} packages/agentplane=${agentplaneVersion}`,
|
|
345
408
|
});
|
|
346
409
|
}
|
|
410
|
+
if (coreDependencyVersion !== coreVersion) {
|
|
411
|
+
throw new CliError({
|
|
412
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
413
|
+
code: "E_VALIDATION",
|
|
414
|
+
message: "Release dependency parity check failed before apply. " +
|
|
415
|
+
`packages/agentplane dependency @agentplaneorg/core=${coreDependencyVersion} ` +
|
|
416
|
+
`must match packages/core version ${coreVersion}.`,
|
|
417
|
+
});
|
|
418
|
+
}
|
|
347
419
|
const git = new GitContext({ gitRoot });
|
|
348
420
|
await ensureCleanTrackedTree(gitRoot);
|
|
349
421
|
await ensureTagDoesNotExist(gitRoot, plan.nextTag);
|
|
@@ -356,6 +428,7 @@ export const runReleaseApply = async (ctx, flags) => {
|
|
|
356
428
|
reason: "release apply --push validates npm version availability and pushes over network",
|
|
357
429
|
interactive: Boolean(process.stdin.isTTY),
|
|
358
430
|
});
|
|
431
|
+
await runReleasePrepublishGate(gitRoot);
|
|
359
432
|
await ensureNpmVersionsAvailable(gitRoot, plan.nextVersion);
|
|
360
433
|
npmVersionChecked = true;
|
|
361
434
|
}
|
|
@@ -363,10 +436,13 @@ export const runReleaseApply = async (ctx, flags) => {
|
|
|
363
436
|
if (coreVersion === plan.prevVersion) {
|
|
364
437
|
await Promise.all([
|
|
365
438
|
replacePackageVersionInFile(corePkgPath, plan.nextVersion),
|
|
366
|
-
|
|
439
|
+
replaceAgentplanePackageMetadata(agentplanePkgPath, plan.nextVersion),
|
|
367
440
|
]);
|
|
368
441
|
}
|
|
369
|
-
else if (coreVersion
|
|
442
|
+
else if (coreVersion === plan.nextVersion) {
|
|
443
|
+
await replaceAgentplanePackageMetadata(agentplanePkgPath, plan.nextVersion);
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
370
446
|
throw new CliError({
|
|
371
447
|
exitCode: exitCodeForError("E_VALIDATION"),
|
|
372
448
|
code: "E_VALIDATION",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.command.d.ts","sourceRoot":"","sources":["../../../src/commands/release/plan.command.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAM1E,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;
|
|
1
|
+
{"version":3,"file":"plan.command.d.ts","sourceRoot":"","sources":["../../../src/commands/release/plan.command.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAM1E,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;AAqIjD,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,iBAAiB,CA4E1D,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,iBAAiB,CAoE5D,CAAC"}
|
|
@@ -43,6 +43,20 @@ async function readPackageVersion(pkgJsonPath) {
|
|
|
43
43
|
}
|
|
44
44
|
return version;
|
|
45
45
|
}
|
|
46
|
+
async function readCoreDependencyVersion(pkgJsonPath) {
|
|
47
|
+
const raw = JSON.parse(await readFile(pkgJsonPath, "utf8"));
|
|
48
|
+
const value = raw.dependencies?.["@agentplaneorg/core"];
|
|
49
|
+
const version = typeof value === "string" ? value.trim() : "";
|
|
50
|
+
if (!version) {
|
|
51
|
+
throw new CliError({
|
|
52
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
53
|
+
code: "E_VALIDATION",
|
|
54
|
+
message: `Missing dependency @agentplaneorg/core in ${pkgJsonPath}. ` +
|
|
55
|
+
"Release planning requires packages/agentplane to pin @agentplaneorg/core to the same version.",
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return version;
|
|
59
|
+
}
|
|
46
60
|
async function getLatestSemverTag(gitRoot) {
|
|
47
61
|
try {
|
|
48
62
|
const { stdout } = await execFileAsync("git", ["describe", "--tags", "--abbrev=0", "--match", "v[0-9]*.[0-9]*.[0-9]*"], { cwd: gitRoot, env: gitEnv() });
|
|
@@ -176,9 +190,10 @@ export const runReleasePlan = async (ctx, flags) => {
|
|
|
176
190
|
const gitRoot = resolved.gitRoot;
|
|
177
191
|
const corePkgPath = path.join(gitRoot, "packages", "core", "package.json");
|
|
178
192
|
const agentplanePkgPath = path.join(gitRoot, "packages", "agentplane", "package.json");
|
|
179
|
-
const [coreVersion, agentplaneVersion] = await Promise.all([
|
|
193
|
+
const [coreVersion, agentplaneVersion, coreDependencyVersion] = await Promise.all([
|
|
180
194
|
readPackageVersion(corePkgPath),
|
|
181
195
|
readPackageVersion(agentplanePkgPath),
|
|
196
|
+
readCoreDependencyVersion(agentplanePkgPath),
|
|
182
197
|
]);
|
|
183
198
|
if (coreVersion !== agentplaneVersion) {
|
|
184
199
|
throw new CliError({
|
|
@@ -188,6 +203,15 @@ export const runReleasePlan = async (ctx, flags) => {
|
|
|
188
203
|
`packages/core=${coreVersion} packages/agentplane=${agentplaneVersion}`,
|
|
189
204
|
});
|
|
190
205
|
}
|
|
206
|
+
if (coreDependencyVersion !== coreVersion) {
|
|
207
|
+
throw new CliError({
|
|
208
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
209
|
+
code: "E_VALIDATION",
|
|
210
|
+
message: "Release dependency parity check failed before planning. " +
|
|
211
|
+
`packages/agentplane dependency @agentplaneorg/core=${coreDependencyVersion} ` +
|
|
212
|
+
`must match packages/core version ${coreVersion}.`,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
191
215
|
const prevTag = flags.since ?? (await getLatestSemverTag(gitRoot));
|
|
192
216
|
const nextVersion = bumpVersion(coreVersion, flags.bump);
|
|
193
217
|
const nextTag = `v${nextVersion}`;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AgentplaneConfig, ResolvedProject } from "@agentplaneorg/core";
|
|
1
2
|
import { loadTaskBackend, type TaskData } from "../../backends/task-backend.js";
|
|
2
3
|
import { GitContext } from "./git-context.js";
|
|
3
4
|
export type CommandMemo = {
|
|
@@ -22,6 +23,8 @@ export declare function taskDataToFrontmatter(task: TaskData): Record<string, un
|
|
|
22
23
|
export declare function loadCommandContext(opts: {
|
|
23
24
|
cwd: string;
|
|
24
25
|
rootOverride?: string | null;
|
|
26
|
+
resolvedProject?: ResolvedProject;
|
|
27
|
+
config?: AgentplaneConfig;
|
|
25
28
|
}): Promise<CommandContext>;
|
|
26
29
|
export declare function loadTaskFromContext(opts: {
|
|
27
30
|
ctx: CommandContext;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-backend.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/task-backend.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"task-backend.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/task-backend.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG7E,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,eAAe,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IACzE,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC9D,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,UAAU,CAAC;IAEhB,IAAI,EAAE,WAAW,CAAC;IAGlB,QAAQ,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAC5C,OAAO,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;CACxC,CAAC;AASF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ3E;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA+B7E;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B,GAAG,OAAO,CAAC,cAAc,CAAC,CAmB1B;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAepB;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC;IACV,OAAO,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAC5C,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjC,IAAI,EAAE,QAAQ,CAAC;CAChB,CAAC,CAaD;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAG5E"}
|
|
@@ -50,10 +50,13 @@ export function taskDataToFrontmatter(task) {
|
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
52
|
export async function loadCommandContext(opts) {
|
|
53
|
-
const
|
|
53
|
+
const backendLoaded = await loadTaskBackend({
|
|
54
54
|
cwd: opts.cwd,
|
|
55
55
|
rootOverride: opts.rootOverride ?? null,
|
|
56
|
+
resolvedProject: opts.resolvedProject,
|
|
57
|
+
config: opts.config,
|
|
56
58
|
});
|
|
59
|
+
const { backend, backendId, backendConfigPath, resolved, config } = backendLoaded;
|
|
57
60
|
return {
|
|
58
61
|
resolvedProject: resolved,
|
|
59
62
|
config,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block.d.ts","sourceRoot":"","sources":["../../../src/commands/task/block.ts"],"names":[],"mappings":"AAQA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"block.d.ts","sourceRoot":"","sources":["../../../src/commands/task/block.ts"],"names":[],"mappings":"AAQA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAgBnC,wBAAsB,QAAQ,CAAC,IAAI,EAAE;IACnC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmIlB"}
|
|
@@ -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, defaultCommitEmojiForAgentId, enforceStatusCommitPolicy, isTransitionAllowed, nowIso, requireStructuredComment, } from "./shared.js";
|
|
10
|
+
import { appendTaskEvent, defaultCommitEmojiForAgentId, enforceStatusCommitPolicy, isTransitionAllowed, nowIso, requireStructuredComment, resolvePrimaryTag, toStringArray, } from "./shared.js";
|
|
11
11
|
export async function cmdBlock(opts) {
|
|
12
12
|
try {
|
|
13
13
|
const ctx = opts.ctx ??
|
|
@@ -20,14 +20,6 @@ export async function cmdBlock(opts) {
|
|
|
20
20
|
reason: "block --force",
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
|
-
if (opts.commitFromComment) {
|
|
24
|
-
enforceStatusCommitPolicy({
|
|
25
|
-
policy: ctx.config.status_commit_policy,
|
|
26
|
-
action: "block",
|
|
27
|
-
confirmed: opts.confirmStatusCommit,
|
|
28
|
-
quiet: opts.quiet,
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
23
|
const { prefix, min_chars: minChars } = ctx.config.tasks.comments.blocked;
|
|
32
24
|
requireStructuredComment(opts.body, prefix, minChars);
|
|
33
25
|
const useStore = backendIsLocalFileBackend(ctx);
|
|
@@ -43,6 +35,16 @@ export async function cmdBlock(opts) {
|
|
|
43
35
|
message: `Refusing status transition ${currentStatus} -> BLOCKED (use --force to override)`,
|
|
44
36
|
});
|
|
45
37
|
}
|
|
38
|
+
if (opts.commitFromComment) {
|
|
39
|
+
enforceStatusCommitPolicy({
|
|
40
|
+
policy: ctx.config.status_commit_policy,
|
|
41
|
+
action: "block",
|
|
42
|
+
confirmed: opts.confirmStatusCommit,
|
|
43
|
+
quiet: opts.quiet,
|
|
44
|
+
statusFrom: currentStatus,
|
|
45
|
+
statusTo: "BLOCKED",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
46
48
|
const formattedComment = opts.commitFromComment
|
|
47
49
|
? formatCommentBodyForCommit(opts.body, ctx.config)
|
|
48
50
|
: null;
|
|
@@ -94,6 +96,7 @@ export async function cmdBlock(opts) {
|
|
|
94
96
|
cwd: opts.cwd,
|
|
95
97
|
rootOverride: opts.rootOverride,
|
|
96
98
|
taskId: opts.taskId,
|
|
99
|
+
primaryTag: resolvePrimaryTag(toStringArray(task.tags), ctx).primary,
|
|
97
100
|
executorAgent,
|
|
98
101
|
author: opts.author,
|
|
99
102
|
statusFrom: currentStatus,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CommandCtx, CommandSpec } from "../../cli/spec/spec.js";
|
|
2
|
+
import type { CommandContext } from "../shared/task-backend.js";
|
|
3
|
+
export type TaskCloseDuplicateParsed = {
|
|
4
|
+
taskId: string;
|
|
5
|
+
duplicateOf: string;
|
|
6
|
+
author: string;
|
|
7
|
+
note?: string;
|
|
8
|
+
force: boolean;
|
|
9
|
+
yes: boolean;
|
|
10
|
+
quiet: boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare const taskCloseDuplicateSpec: CommandSpec<TaskCloseDuplicateParsed>;
|
|
13
|
+
export declare function makeRunTaskCloseDuplicateHandler(getCtx: (cmd: string) => Promise<CommandContext>): (ctx: CommandCtx, p: TaskCloseDuplicateParsed) => Promise<number>;
|
|
14
|
+
//# sourceMappingURL=close-duplicate.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"close-duplicate.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/close-duplicate.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAEtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAGhE,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,wBAAwB,CAmFxE,CAAC;AAEF,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IACjF,KAAK,UAAU,EAAE,GAAG,wBAAwB,KAAG,OAAO,CAAC,MAAM,CAAC,CAc7E"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { usageError } from "../../cli/spec/errors.js";
|
|
2
|
+
import { cmdTaskCloseDuplicate } from "./close-duplicate.js";
|
|
3
|
+
export const taskCloseDuplicateSpec = {
|
|
4
|
+
id: ["task", "close-duplicate"],
|
|
5
|
+
group: "Task",
|
|
6
|
+
summary: "Close a task as a duplicate of another task with no-op bookkeeping metadata.",
|
|
7
|
+
args: [{ name: "task-id", required: true, valueHint: "<task-id>" }],
|
|
8
|
+
options: [
|
|
9
|
+
{
|
|
10
|
+
kind: "string",
|
|
11
|
+
name: "of",
|
|
12
|
+
valueHint: "<task-id>",
|
|
13
|
+
required: true,
|
|
14
|
+
description: "Canonical task id that this task duplicates.",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
kind: "string",
|
|
18
|
+
name: "author",
|
|
19
|
+
valueHint: "<id>",
|
|
20
|
+
required: true,
|
|
21
|
+
description: "Comment author id (e.g. ORCHESTRATOR).",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
kind: "string",
|
|
25
|
+
name: "note",
|
|
26
|
+
valueHint: "<text>",
|
|
27
|
+
description: "Optional short reason appended to the closure comment.",
|
|
28
|
+
},
|
|
29
|
+
{ kind: "boolean", name: "force", default: false, description: "Force closure despite gates." },
|
|
30
|
+
{
|
|
31
|
+
kind: "boolean",
|
|
32
|
+
name: "yes",
|
|
33
|
+
default: false,
|
|
34
|
+
description: "Auto-approve force-action approval checks when required.",
|
|
35
|
+
},
|
|
36
|
+
{ kind: "boolean", name: "quiet", default: false, description: "Suppress output." },
|
|
37
|
+
],
|
|
38
|
+
examples: [
|
|
39
|
+
{
|
|
40
|
+
cmd: "agentplane task close-duplicate 202602120845-VKGC27 --of 202602120845-RWJ8K3 --author ORCHESTRATOR",
|
|
41
|
+
why: "Close accidental duplicate task in one command.",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
validateRaw: (raw) => {
|
|
45
|
+
const taskId = typeof raw.args["task-id"] === "string" ? raw.args["task-id"].trim() : "";
|
|
46
|
+
const of = typeof raw.opts.of === "string" ? raw.opts.of.trim() : "";
|
|
47
|
+
const author = typeof raw.opts.author === "string" ? raw.opts.author.trim() : "";
|
|
48
|
+
const note = raw.opts.note;
|
|
49
|
+
if (!taskId) {
|
|
50
|
+
throw usageError({
|
|
51
|
+
spec: taskCloseDuplicateSpec,
|
|
52
|
+
message: "Invalid value for task-id: empty.",
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (!of) {
|
|
56
|
+
throw usageError({ spec: taskCloseDuplicateSpec, message: "Invalid value for --of: empty." });
|
|
57
|
+
}
|
|
58
|
+
if (!author) {
|
|
59
|
+
throw usageError({
|
|
60
|
+
spec: taskCloseDuplicateSpec,
|
|
61
|
+
message: "Invalid value for --author: empty.",
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (typeof note === "string" && note.trim().length === 0) {
|
|
65
|
+
throw usageError({
|
|
66
|
+
spec: taskCloseDuplicateSpec,
|
|
67
|
+
message: "Invalid value for --note: empty.",
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (taskId === of) {
|
|
71
|
+
throw usageError({
|
|
72
|
+
spec: taskCloseDuplicateSpec,
|
|
73
|
+
message: "Duplicate target must differ from task-id.",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
parse: (raw) => ({
|
|
78
|
+
taskId: String(raw.args["task-id"]),
|
|
79
|
+
duplicateOf: String(raw.opts.of),
|
|
80
|
+
author: String(raw.opts.author),
|
|
81
|
+
note: typeof raw.opts.note === "string" ? raw.opts.note : undefined,
|
|
82
|
+
force: raw.opts.force === true,
|
|
83
|
+
yes: raw.opts.yes === true,
|
|
84
|
+
quiet: raw.opts.quiet === true,
|
|
85
|
+
}),
|
|
86
|
+
};
|
|
87
|
+
export function makeRunTaskCloseDuplicateHandler(getCtx) {
|
|
88
|
+
return async (ctx, p) => {
|
|
89
|
+
return await cmdTaskCloseDuplicate({
|
|
90
|
+
ctx: await getCtx("task close-duplicate"),
|
|
91
|
+
cwd: ctx.cwd,
|
|
92
|
+
rootOverride: ctx.rootOverride,
|
|
93
|
+
taskId: p.taskId,
|
|
94
|
+
duplicateOf: p.duplicateOf,
|
|
95
|
+
author: p.author,
|
|
96
|
+
note: p.note,
|
|
97
|
+
force: p.force,
|
|
98
|
+
yes: p.yes,
|
|
99
|
+
quiet: p.quiet,
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type CommandContext } from "../shared/task-backend.js";
|
|
2
|
+
export declare function cmdTaskCloseDuplicate(opts: {
|
|
3
|
+
ctx: CommandContext;
|
|
4
|
+
cwd: string;
|
|
5
|
+
rootOverride?: string;
|
|
6
|
+
taskId: string;
|
|
7
|
+
duplicateOf: string;
|
|
8
|
+
author: string;
|
|
9
|
+
note?: string;
|
|
10
|
+
force: boolean;
|
|
11
|
+
yes: boolean;
|
|
12
|
+
quiet: boolean;
|
|
13
|
+
}): Promise<number>;
|
|
14
|
+
//# sourceMappingURL=close-duplicate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"close-duplicate.d.ts","sourceRoot":"","sources":["../../../src/commands/task/close-duplicate.ts"],"names":[],"mappings":"AAIA,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIrF,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,GAAG,EAAE,cAAc,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAuFlB"}
|