agentplane 0.1.6 → 0.1.8

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 (138) hide show
  1. package/assets/AGENTS.md +1 -1
  2. package/assets/agents/ORCHESTRATOR.json +1 -1
  3. package/assets/agents/UPGRADER.json +1 -1
  4. package/dist/backends/task-backend.d.ts +16 -0
  5. package/dist/backends/task-backend.d.ts.map +1 -1
  6. package/dist/backends/task-backend.js +44 -0
  7. package/dist/backends/task-index.d.ts.map +1 -1
  8. package/dist/backends/task-index.js +3 -6
  9. package/dist/cli/command-guide.d.ts.map +1 -1
  10. package/dist/cli/command-guide.js +4 -4
  11. package/dist/cli/help.d.ts.map +1 -1
  12. package/dist/cli/help.js +7 -5
  13. package/dist/cli/run-cli.d.ts.map +1 -1
  14. package/dist/cli/run-cli.js +39 -78
  15. package/dist/commands/backend.d.ts.map +1 -1
  16. package/dist/commands/backend.js +17 -2
  17. package/dist/commands/branch/index.d.ts +60 -0
  18. package/dist/commands/branch/index.d.ts.map +1 -0
  19. package/dist/commands/branch/index.js +513 -0
  20. package/dist/commands/guard/index.d.ts +67 -0
  21. package/dist/commands/guard/index.d.ts.map +1 -0
  22. package/dist/commands/guard/index.js +367 -0
  23. package/dist/commands/hooks/index.d.ts +18 -0
  24. package/dist/commands/hooks/index.d.ts.map +1 -0
  25. package/dist/commands/hooks/index.js +290 -0
  26. package/dist/commands/pr/index.d.ts +46 -0
  27. package/dist/commands/pr/index.d.ts.map +1 -0
  28. package/dist/commands/pr/index.js +857 -0
  29. package/dist/commands/recipes.d.ts.map +1 -1
  30. package/dist/commands/recipes.js +67 -23
  31. package/dist/commands/shared/git-diff.d.ts +9 -0
  32. package/dist/commands/shared/git-diff.d.ts.map +1 -0
  33. package/dist/commands/shared/git-diff.js +41 -0
  34. package/dist/commands/shared/git-ops.d.ts +24 -0
  35. package/dist/commands/shared/git-ops.d.ts.map +1 -0
  36. package/dist/commands/shared/git-ops.js +181 -0
  37. package/dist/commands/shared/git-worktree.d.ts +8 -0
  38. package/dist/commands/shared/git-worktree.d.ts.map +1 -0
  39. package/dist/commands/shared/git-worktree.js +48 -0
  40. package/dist/commands/shared/git.d.ts +4 -0
  41. package/dist/commands/shared/git.d.ts.map +1 -0
  42. package/dist/commands/shared/git.js +14 -0
  43. package/dist/commands/shared/network-approval.d.ts +8 -0
  44. package/dist/commands/shared/network-approval.d.ts.map +1 -0
  45. package/dist/commands/shared/network-approval.js +25 -0
  46. package/dist/commands/shared/path.d.ts +3 -0
  47. package/dist/commands/shared/path.d.ts.map +1 -0
  48. package/dist/commands/shared/path.js +14 -0
  49. package/dist/commands/shared/pr-meta.d.ts +21 -0
  50. package/dist/commands/shared/pr-meta.d.ts.map +1 -0
  51. package/dist/commands/shared/pr-meta.js +72 -0
  52. package/dist/commands/shared/task-backend.d.ts +15 -0
  53. package/dist/commands/shared/task-backend.d.ts.map +1 -0
  54. package/dist/commands/shared/task-backend.js +61 -0
  55. package/dist/commands/task/add.d.ts +8 -0
  56. package/dist/commands/task/add.d.ts.map +1 -0
  57. package/dist/commands/task/add.js +164 -0
  58. package/dist/commands/task/block.d.ts +19 -0
  59. package/dist/commands/task/block.d.ts.map +1 -0
  60. package/dist/commands/task/block.js +86 -0
  61. package/dist/commands/task/comment.d.ts +8 -0
  62. package/dist/commands/task/comment.d.ts.map +1 -0
  63. package/dist/commands/task/comment.js +29 -0
  64. package/dist/commands/task/doc.d.ts +17 -0
  65. package/dist/commands/task/doc.d.ts.map +1 -0
  66. package/dist/commands/task/doc.js +220 -0
  67. package/dist/commands/task/export.d.ts +5 -0
  68. package/dist/commands/task/export.d.ts.map +1 -0
  69. package/dist/commands/task/export.js +27 -0
  70. package/dist/commands/task/finish.d.ts +27 -0
  71. package/dist/commands/task/finish.d.ts.map +1 -0
  72. package/dist/commands/task/finish.js +132 -0
  73. package/dist/commands/task/index.d.ts +26 -0
  74. package/dist/commands/task/index.d.ts.map +1 -0
  75. package/dist/commands/task/index.js +25 -0
  76. package/dist/commands/task/lint.d.ts +5 -0
  77. package/dist/commands/task/lint.d.ts.map +1 -0
  78. package/dist/commands/task/lint.js +22 -0
  79. package/dist/commands/task/list.d.ts +11 -0
  80. package/dist/commands/task/list.d.ts.map +1 -0
  81. package/dist/commands/task/list.js +54 -0
  82. package/dist/commands/task/migrate-doc.d.ts +8 -0
  83. package/dist/commands/task/migrate-doc.d.ts.map +1 -0
  84. package/dist/commands/task/migrate-doc.js +147 -0
  85. package/dist/commands/task/migrate.d.ts +6 -0
  86. package/dist/commands/task/migrate.d.ts.map +1 -0
  87. package/dist/commands/task/migrate.js +70 -0
  88. package/dist/commands/task/new.d.ts +8 -0
  89. package/dist/commands/task/new.d.ts.map +1 -0
  90. package/dist/commands/task/new.js +117 -0
  91. package/dist/commands/task/next.d.ts +6 -0
  92. package/dist/commands/task/next.d.ts.map +1 -0
  93. package/dist/commands/task/next.js +45 -0
  94. package/dist/commands/task/normalize.d.ts +6 -0
  95. package/dist/commands/task/normalize.d.ts.map +1 -0
  96. package/dist/commands/task/normalize.js +46 -0
  97. package/dist/commands/task/plan.d.ts +14 -0
  98. package/dist/commands/task/plan.d.ts.map +1 -0
  99. package/dist/commands/task/plan.js +217 -0
  100. package/dist/commands/task/ready.d.ts +6 -0
  101. package/dist/commands/task/ready.d.ts.map +1 -0
  102. package/dist/commands/task/ready.js +57 -0
  103. package/dist/commands/task/scaffold.d.ts +8 -0
  104. package/dist/commands/task/scaffold.d.ts.map +1 -0
  105. package/dist/commands/task/scaffold.js +142 -0
  106. package/dist/commands/task/scrub.d.ts +8 -0
  107. package/dist/commands/task/scrub.d.ts.map +1 -0
  108. package/dist/commands/task/scrub.js +121 -0
  109. package/dist/commands/task/search.d.ts +7 -0
  110. package/dist/commands/task/search.d.ts.map +1 -0
  111. package/dist/commands/task/search.js +79 -0
  112. package/dist/commands/task/set-status.d.ts +19 -0
  113. package/dist/commands/task/set-status.d.ts.map +1 -0
  114. package/dist/commands/task/set-status.js +123 -0
  115. package/dist/commands/task/shared.d.ts +48 -0
  116. package/dist/commands/task/shared.d.ts.map +1 -0
  117. package/dist/commands/task/shared.js +312 -0
  118. package/dist/commands/task/show.d.ts +6 -0
  119. package/dist/commands/task/show.d.ts.map +1 -0
  120. package/dist/commands/task/show.js +35 -0
  121. package/dist/commands/task/start.d.ts +19 -0
  122. package/dist/commands/task/start.d.ts.map +1 -0
  123. package/dist/commands/task/start.js +110 -0
  124. package/dist/commands/task/update.d.ts +8 -0
  125. package/dist/commands/task/update.d.ts.map +1 -0
  126. package/dist/commands/task/update.js +144 -0
  127. package/dist/commands/task/verify-record.d.ts +16 -0
  128. package/dist/commands/task/verify-record.d.ts.map +1 -0
  129. package/dist/commands/task/verify-record.js +277 -0
  130. package/dist/commands/task/verify.d.ts +2 -0
  131. package/dist/commands/task/verify.d.ts.map +1 -0
  132. package/dist/commands/task/verify.js +1 -0
  133. package/dist/commands/upgrade.d.ts.map +1 -1
  134. package/dist/commands/upgrade.js +17 -2
  135. package/dist/commands/workflow.d.ts +5 -364
  136. package/dist/commands/workflow.d.ts.map +1 -1
  137. package/dist/commands/workflow.js +6 -4617
  138. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/path.ts"],"names":[],"mappings":"AAGA,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM3E;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAGvE"}
@@ -0,0 +1,14 @@
1
+ import { realpath } from "node:fs/promises";
2
+ import path from "node:path";
3
+ export async function resolvePathFallback(filePath) {
4
+ try {
5
+ return await realpath(filePath);
6
+ }
7
+ catch {
8
+ return path.resolve(filePath);
9
+ }
10
+ }
11
+ export function isPathWithin(parent, candidate) {
12
+ const rel = path.relative(parent, candidate);
13
+ return rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel));
14
+ }
@@ -0,0 +1,21 @@
1
+ export type PrMeta = {
2
+ schema_version: 1;
3
+ task_id: string;
4
+ branch?: string;
5
+ created_at: string;
6
+ updated_at: string;
7
+ last_verified_sha: string | null;
8
+ last_verified_at: string | null;
9
+ verify?: {
10
+ status?: "pass" | "fail" | "skipped";
11
+ command?: string;
12
+ };
13
+ };
14
+ export declare function parsePrMeta(raw: string, taskId: string): PrMeta;
15
+ export declare function extractLastVerifiedSha(logText: string): string | null;
16
+ export declare function appendVerifyLog(logPath: string, header: string, content: string): Promise<void>;
17
+ export declare function runShellCommand(command: string, cwd: string): Promise<{
18
+ code: number;
19
+ output: string;
20
+ }>;
21
+ //# sourceMappingURL=pr-meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr-meta.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/pr-meta.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,MAAM,GAAG;IACnB,cAAc,EAAE,CAAC,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrE,CAAC;AAEF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAc/D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQrE;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAoBD"}
@@ -0,0 +1,72 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { execFileAsync } from "./git.js";
4
+ function isRecord(value) {
5
+ return !!value && typeof value === "object" && !Array.isArray(value);
6
+ }
7
+ function isIsoDate(value) {
8
+ return typeof value === "string" && !Number.isNaN(Date.parse(value));
9
+ }
10
+ export function parsePrMeta(raw, taskId) {
11
+ let parsed;
12
+ try {
13
+ parsed = JSON.parse(raw);
14
+ }
15
+ catch (err) {
16
+ const message = err instanceof Error ? err.message : String(err);
17
+ throw new Error(`JSON Parse error: ${message}`);
18
+ }
19
+ if (!isRecord(parsed))
20
+ throw new Error("pr/meta.json must be an object");
21
+ if (parsed.schema_version !== 1)
22
+ throw new Error("pr/meta.json schema_version must be 1");
23
+ if (parsed.task_id !== taskId)
24
+ throw new Error("pr/meta.json task_id mismatch");
25
+ if (!isIsoDate(parsed.created_at))
26
+ throw new Error("pr/meta.json created_at must be ISO");
27
+ if (!isIsoDate(parsed.updated_at))
28
+ throw new Error("pr/meta.json updated_at must be ISO");
29
+ return parsed;
30
+ }
31
+ export function extractLastVerifiedSha(logText) {
32
+ const regex = /verified_sha=([0-9a-f]{7,40})/gi;
33
+ let match = null;
34
+ let last = null;
35
+ while ((match = regex.exec(logText))) {
36
+ last = match[1] ?? null;
37
+ }
38
+ return last;
39
+ }
40
+ export async function appendVerifyLog(logPath, header, content) {
41
+ await mkdir(path.dirname(logPath), { recursive: true });
42
+ const lines = [header.trimEnd()];
43
+ if (content)
44
+ lines.push(content.trimEnd());
45
+ lines.push("");
46
+ await writeFile(logPath, `${lines.join("\n")}\n`, { flag: "a" });
47
+ }
48
+ export async function runShellCommand(command, cwd) {
49
+ try {
50
+ const { stdout, stderr } = await execFileAsync("sh", ["-lc", command], {
51
+ cwd,
52
+ env: process.env,
53
+ maxBuffer: 10 * 1024 * 1024,
54
+ });
55
+ let output = "";
56
+ if (stdout)
57
+ output += stdout;
58
+ if (stderr)
59
+ output += (output && !output.endsWith("\n") ? "\n" : "") + stderr;
60
+ return { code: 0, output };
61
+ }
62
+ catch (err) {
63
+ const error = err;
64
+ let output = "";
65
+ if (error.stdout)
66
+ output += String(error.stdout);
67
+ if (error.stderr)
68
+ output += (output && !output.endsWith("\n") ? "\n" : "") + String(error.stderr);
69
+ const code = typeof error.code === "number" ? error.code : 1;
70
+ return { code, output };
71
+ }
72
+ }
@@ -0,0 +1,15 @@
1
+ import { loadTaskBackend, type TaskData } from "../../backends/task-backend.js";
2
+ export declare function resolveDocUpdatedBy(task: TaskData, author?: string): string;
3
+ export declare function taskDataToFrontmatter(task: TaskData): Record<string, unknown>;
4
+ export declare function loadBackendTask(opts: {
5
+ cwd: string;
6
+ rootOverride?: string | null;
7
+ taskId: string;
8
+ }): Promise<{
9
+ backend: Awaited<ReturnType<typeof loadTaskBackend>>["backend"];
10
+ backendId: string;
11
+ resolved: Awaited<ReturnType<typeof loadTaskBackend>>["resolved"];
12
+ config: Awaited<ReturnType<typeof loadTaskBackend>>["config"];
13
+ task: TaskData;
14
+ }>;
15
+ //# sourceMappingURL=task-backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-backend.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/task-backend.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAShF,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,CAyB7E;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC;IACV,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAClE,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC9D,IAAI,EAAE,QAAQ,CAAC;CAChB,CAAC,CAgBD"}
@@ -0,0 +1,61 @@
1
+ import path from "node:path";
2
+ import { CliError } from "../../shared/errors.js";
3
+ import { loadTaskBackend } from "../../backends/task-backend.js";
4
+ function normalizeDocUpdatedBy(value) {
5
+ const trimmed = value?.trim() ?? "";
6
+ if (!trimmed)
7
+ return "";
8
+ if (trimmed.toLowerCase() === "agentplane")
9
+ return "";
10
+ return trimmed;
11
+ }
12
+ export function resolveDocUpdatedBy(task, author) {
13
+ const fromAuthor = normalizeDocUpdatedBy(author);
14
+ if (fromAuthor)
15
+ return fromAuthor;
16
+ const fromTask = normalizeDocUpdatedBy(typeof task.doc_updated_by === "string" ? task.doc_updated_by : undefined);
17
+ if (fromTask)
18
+ return fromTask;
19
+ return normalizeDocUpdatedBy(typeof task.owner === "string" ? task.owner : undefined);
20
+ }
21
+ export function taskDataToFrontmatter(task) {
22
+ const planApproval = task.plan_approval ??
23
+ { state: "pending", updated_at: null, updated_by: null, note: null };
24
+ const verification = task.verification ??
25
+ { state: "pending", updated_at: null, updated_by: null, note: null };
26
+ return {
27
+ id: task.id,
28
+ title: task.title,
29
+ status: task.status,
30
+ priority: task.priority,
31
+ owner: task.owner,
32
+ depends_on: task.depends_on ?? [],
33
+ tags: task.tags ?? [],
34
+ verify: task.verify ?? [],
35
+ plan_approval: planApproval,
36
+ verification,
37
+ commit: task.commit ?? null,
38
+ comments: task.comments ?? [],
39
+ doc_version: task.doc_version,
40
+ doc_updated_at: task.doc_updated_at,
41
+ doc_updated_by: task.doc_updated_by,
42
+ description: task.description ?? "",
43
+ };
44
+ }
45
+ export async function loadBackendTask(opts) {
46
+ const { backend, backendId, resolved, config } = await loadTaskBackend({
47
+ cwd: opts.cwd,
48
+ rootOverride: opts.rootOverride ?? null,
49
+ });
50
+ const task = await backend.getTask(opts.taskId);
51
+ if (!task) {
52
+ const tasksDir = path.join(resolved.gitRoot, config.paths.workflow_dir);
53
+ const readmePath = path.join(tasksDir, opts.taskId, "README.md");
54
+ throw new CliError({
55
+ exitCode: 4,
56
+ code: "E_IO",
57
+ message: `ENOENT: no such file or directory, open '${readmePath}'`,
58
+ });
59
+ }
60
+ return { backend, backendId, resolved, config, task };
61
+ }
@@ -0,0 +1,8 @@
1
+ export declare const TASK_ADD_USAGE = "Usage: agentplane task add <task-id> [<task-id> ...] --title <text> --description <text> --priority <low|normal|med|high> --owner <id> --tag <tag> [--tag <tag>...]";
2
+ export declare const TASK_ADD_USAGE_EXAMPLE = "agentplane task add 202602030608-F1Q8AB --title \"...\" --description \"...\" --priority med --owner CODER --tag cli";
3
+ export declare function cmdTaskAdd(opts: {
4
+ cwd: string;
5
+ rootOverride?: string;
6
+ args: string[];
7
+ }): Promise<number>;
8
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../src/commands/task/add.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,cAAc,wKAC4I,CAAC;AACxK,eAAO,MAAM,sBAAsB,yHACiF,CAAC;AAgGrH,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgFlB"}
@@ -0,0 +1,164 @@
1
+ import { loadTaskBackend } from "../../backends/task-backend.js";
2
+ import { mapBackendError } from "../../cli/error-map.js";
3
+ import { missingValueMessage, usageMessage } from "../../cli/output.js";
4
+ import { CliError } from "../../shared/errors.js";
5
+ import { dedupeStrings, normalizeDependsOnInput, normalizeTaskStatus, nowIso, requiresVerify, } from "./shared.js";
6
+ export const TASK_ADD_USAGE = "Usage: agentplane task add <task-id> [<task-id> ...] --title <text> --description <text> --priority <low|normal|med|high> --owner <id> --tag <tag> [--tag <tag>...]";
7
+ export const TASK_ADD_USAGE_EXAMPLE = 'agentplane task add 202602030608-F1Q8AB --title "..." --description "..." --priority med --owner CODER --tag cli';
8
+ function parseTaskAddFlags(args) {
9
+ const out = {
10
+ taskIds: [],
11
+ title: "",
12
+ description: "",
13
+ status: "TODO",
14
+ priority: "",
15
+ owner: "",
16
+ tags: [],
17
+ dependsOn: [],
18
+ verify: [],
19
+ };
20
+ for (let i = 0; i < args.length; i++) {
21
+ const arg = args[i];
22
+ if (!arg)
23
+ continue;
24
+ if (!arg.startsWith("--")) {
25
+ out.taskIds.push(arg);
26
+ continue;
27
+ }
28
+ const next = args[i + 1];
29
+ if (arg === "--replace-tags" || arg === "--replace-depends-on" || arg === "--replace-verify") {
30
+ throw new CliError({
31
+ exitCode: 2,
32
+ code: "E_USAGE",
33
+ message: usageMessage(TASK_ADD_USAGE, TASK_ADD_USAGE_EXAMPLE),
34
+ });
35
+ }
36
+ if (!next) {
37
+ throw new CliError({ exitCode: 2, code: "E_USAGE", message: missingValueMessage(arg) });
38
+ }
39
+ switch (arg) {
40
+ case "--title": {
41
+ out.title = next;
42
+ break;
43
+ }
44
+ case "--description": {
45
+ out.description = next;
46
+ break;
47
+ }
48
+ case "--status": {
49
+ out.status = next;
50
+ break;
51
+ }
52
+ case "--priority": {
53
+ out.priority = next;
54
+ break;
55
+ }
56
+ case "--owner": {
57
+ out.owner = next;
58
+ break;
59
+ }
60
+ case "--tag": {
61
+ out.tags.push(next);
62
+ break;
63
+ }
64
+ case "--depends-on": {
65
+ out.dependsOn.push(...normalizeDependsOnInput(next));
66
+ break;
67
+ }
68
+ case "--verify": {
69
+ out.verify.push(next);
70
+ break;
71
+ }
72
+ case "--comment-author": {
73
+ out.commentAuthor = next;
74
+ break;
75
+ }
76
+ case "--comment-body": {
77
+ out.commentBody = next;
78
+ break;
79
+ }
80
+ default: {
81
+ throw new CliError({ exitCode: 2, code: "E_USAGE", message: `Unknown flag: ${arg}` });
82
+ }
83
+ }
84
+ i++;
85
+ }
86
+ return out;
87
+ }
88
+ export async function cmdTaskAdd(opts) {
89
+ const flags = parseTaskAddFlags(opts.args);
90
+ if (flags.taskIds.length === 0 ||
91
+ !flags.title ||
92
+ !flags.description ||
93
+ !flags.priority ||
94
+ !flags.owner ||
95
+ flags.tags.length === 0) {
96
+ throw new CliError({
97
+ exitCode: 2,
98
+ code: "E_USAGE",
99
+ message: usageMessage(TASK_ADD_USAGE, TASK_ADD_USAGE_EXAMPLE),
100
+ });
101
+ }
102
+ try {
103
+ const { backend, config } = await loadTaskBackend({
104
+ cwd: opts.cwd,
105
+ rootOverride: opts.rootOverride ?? null,
106
+ });
107
+ const status = normalizeTaskStatus(flags.status);
108
+ const existing = await backend.listTasks();
109
+ const existingIds = new Set(existing.map((task) => task.id));
110
+ for (const taskId of flags.taskIds) {
111
+ if (existingIds.has(taskId)) {
112
+ throw new CliError({
113
+ exitCode: 2,
114
+ code: "E_USAGE",
115
+ message: `Task already exists: ${taskId}`,
116
+ });
117
+ }
118
+ }
119
+ const tags = dedupeStrings(flags.tags);
120
+ const dependsOn = dedupeStrings(flags.dependsOn);
121
+ const verify = dedupeStrings(flags.verify);
122
+ const docUpdatedBy = (flags.commentAuthor ?? "").trim() || flags.owner;
123
+ if (requiresVerify(tags, config.tasks.verify.required_tags) && verify.length === 0) {
124
+ throw new CliError({
125
+ exitCode: 2,
126
+ code: "E_USAGE",
127
+ message: "verify commands are required for tasks with code/backend/frontend tags",
128
+ });
129
+ }
130
+ const tasks = flags.taskIds.map((taskId) => ({
131
+ id: taskId,
132
+ title: flags.title,
133
+ description: flags.description,
134
+ status,
135
+ priority: flags.priority,
136
+ owner: flags.owner,
137
+ tags,
138
+ depends_on: dependsOn,
139
+ verify,
140
+ comments: flags.commentAuthor && flags.commentBody
141
+ ? [{ author: flags.commentAuthor, body: flags.commentBody }]
142
+ : [],
143
+ doc_version: 2,
144
+ doc_updated_at: nowIso(),
145
+ doc_updated_by: docUpdatedBy,
146
+ id_source: "explicit",
147
+ }));
148
+ if (backend.writeTasks) {
149
+ await backend.writeTasks(tasks);
150
+ }
151
+ else {
152
+ for (const task of tasks) {
153
+ await backend.writeTask(task);
154
+ }
155
+ }
156
+ for (const task of tasks) {
157
+ process.stdout.write(`${task.id}\n`);
158
+ }
159
+ return 0;
160
+ }
161
+ catch (err) {
162
+ throw mapBackendError(err, { command: "task add", root: opts.rootOverride ?? null });
163
+ }
164
+ }
@@ -0,0 +1,19 @@
1
+ export declare const BLOCK_USAGE = "Usage: agentplane block <task-id> --author <id> --body <text> [flags]";
2
+ export declare const BLOCK_USAGE_EXAMPLE = "agentplane block 202602030608-F1Q8AB --author CODER --body \"Blocked: ...\"";
3
+ export declare function cmdBlock(opts: {
4
+ cwd: string;
5
+ rootOverride?: string;
6
+ taskId: string;
7
+ author: string;
8
+ body: string;
9
+ commitFromComment: boolean;
10
+ commitEmoji?: string;
11
+ commitAllow: string[];
12
+ commitAutoAllow: boolean;
13
+ commitAllowTasks: boolean;
14
+ commitRequireClean: boolean;
15
+ confirmStatusCommit: boolean;
16
+ force: boolean;
17
+ quiet: boolean;
18
+ }): Promise<number>;
19
+ //# sourceMappingURL=block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block.d.ts","sourceRoot":"","sources":["../../../src/commands/task/block.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,WAAW,0EAA0E,CAAC;AACnG,eAAO,MAAM,mBAAmB,gFAC6C,CAAC;AAE9E,wBAAsB,QAAQ,CAAC,IAAI,EAAE;IACnC,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,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqFlB"}
@@ -0,0 +1,86 @@
1
+ import { loadConfig, resolveProject } from "@agentplaneorg/core";
2
+ import { mapBackendError } from "../../cli/error-map.js";
3
+ import { successMessage } from "../../cli/output.js";
4
+ import { formatCommentBodyForCommit } from "../../shared/comment-format.js";
5
+ import { CliError } from "../../shared/errors.js";
6
+ import { commitFromComment } from "../guard/index.js";
7
+ import { loadBackendTask } from "../shared/task-backend.js";
8
+ import { defaultCommitEmojiForStatus, enforceStatusCommitPolicy, isTransitionAllowed, nowIso, requireStructuredComment, } from "./shared.js";
9
+ export const BLOCK_USAGE = "Usage: agentplane block <task-id> --author <id> --body <text> [flags]";
10
+ export const BLOCK_USAGE_EXAMPLE = 'agentplane block 202602030608-F1Q8AB --author CODER --body "Blocked: ..."';
11
+ export async function cmdBlock(opts) {
12
+ try {
13
+ const resolved = await resolveProject({
14
+ cwd: opts.cwd,
15
+ rootOverride: opts.rootOverride ?? null,
16
+ });
17
+ const loaded = await loadConfig(resolved.agentplaneDir);
18
+ if (opts.commitFromComment) {
19
+ enforceStatusCommitPolicy({
20
+ policy: loaded.config.status_commit_policy,
21
+ action: "block",
22
+ confirmed: opts.confirmStatusCommit,
23
+ quiet: opts.quiet,
24
+ });
25
+ }
26
+ const { prefix, min_chars: minChars } = loaded.config.tasks.comments.blocked;
27
+ requireStructuredComment(opts.body, prefix, minChars);
28
+ const { backend, task } = await loadBackendTask({
29
+ cwd: opts.cwd,
30
+ rootOverride: opts.rootOverride,
31
+ taskId: opts.taskId,
32
+ });
33
+ const currentStatus = String(task.status || "TODO").toUpperCase();
34
+ if (!opts.force && !isTransitionAllowed(currentStatus, "BLOCKED")) {
35
+ throw new CliError({
36
+ exitCode: 2,
37
+ code: "E_USAGE",
38
+ message: `Refusing status transition ${currentStatus} -> BLOCKED (use --force to override)`,
39
+ });
40
+ }
41
+ const formattedComment = opts.commitFromComment
42
+ ? formatCommentBodyForCommit(opts.body, loaded.config)
43
+ : null;
44
+ const commentBody = formattedComment ?? opts.body;
45
+ const existingComments = Array.isArray(task.comments)
46
+ ? task.comments.filter((item) => !!item && typeof item.author === "string" && typeof item.body === "string")
47
+ : [];
48
+ const commentsValue = [...existingComments, { author: opts.author, body: commentBody }];
49
+ const nextTask = {
50
+ ...task,
51
+ status: "BLOCKED",
52
+ comments: commentsValue,
53
+ doc_version: 2,
54
+ doc_updated_at: nowIso(),
55
+ doc_updated_by: opts.author,
56
+ };
57
+ await backend.writeTask(nextTask);
58
+ let commitInfo = null;
59
+ if (opts.commitFromComment) {
60
+ commitInfo = await commitFromComment({
61
+ cwd: opts.cwd,
62
+ rootOverride: opts.rootOverride,
63
+ taskId: opts.taskId,
64
+ commentBody: opts.body,
65
+ formattedComment,
66
+ emoji: opts.commitEmoji ?? defaultCommitEmojiForStatus("BLOCKED"),
67
+ allow: opts.commitAllow,
68
+ autoAllow: opts.commitAutoAllow || opts.commitAllow.length === 0,
69
+ allowTasks: opts.commitAllowTasks,
70
+ requireClean: opts.commitRequireClean,
71
+ quiet: opts.quiet,
72
+ config: loaded.config,
73
+ });
74
+ }
75
+ if (!opts.quiet) {
76
+ const suffix = commitInfo ? ` (commit=${commitInfo.hash.slice(0, 12)})` : "";
77
+ process.stdout.write(`${successMessage("blocked", `${opts.taskId}${suffix}`)}\n`);
78
+ }
79
+ return 0;
80
+ }
81
+ catch (err) {
82
+ if (err instanceof CliError)
83
+ throw err;
84
+ throw mapBackendError(err, { command: "block", root: opts.rootOverride ?? null });
85
+ }
86
+ }
@@ -0,0 +1,8 @@
1
+ export declare function cmdTaskComment(opts: {
2
+ cwd: string;
3
+ rootOverride?: string;
4
+ taskId: string;
5
+ author: string;
6
+ body: string;
7
+ }): Promise<number>;
8
+ //# sourceMappingURL=comment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment.d.ts","sourceRoot":"","sources":["../../../src/commands/task/comment.ts"],"names":[],"mappings":"AAOA,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,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;CACd,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BlB"}
@@ -0,0 +1,29 @@
1
+ import { mapBackendError } from "../../cli/error-map.js";
2
+ import { successMessage } from "../../cli/output.js";
3
+ import { loadBackendTask } from "../shared/task-backend.js";
4
+ import { nowIso } from "./shared.js";
5
+ export async function cmdTaskComment(opts) {
6
+ try {
7
+ const { backend, task } = await loadBackendTask({
8
+ cwd: opts.cwd,
9
+ rootOverride: opts.rootOverride ?? null,
10
+ taskId: opts.taskId,
11
+ });
12
+ const existing = Array.isArray(task.comments)
13
+ ? task.comments.filter((item) => !!item && typeof item.author === "string" && typeof item.body === "string")
14
+ : [];
15
+ const next = {
16
+ ...task,
17
+ comments: [...existing, { author: opts.author, body: opts.body }],
18
+ doc_version: 2,
19
+ doc_updated_at: nowIso(),
20
+ doc_updated_by: opts.author,
21
+ };
22
+ await backend.writeTask(next);
23
+ process.stdout.write(`${successMessage("commented", opts.taskId)}\n`);
24
+ return 0;
25
+ }
26
+ catch (err) {
27
+ throw mapBackendError(err, { command: "task comment", root: opts.rootOverride ?? null });
28
+ }
29
+ }
@@ -0,0 +1,17 @@
1
+ export declare const TASK_DOC_SET_USAGE = "Usage: agentplane task doc set <task-id> --section <name> (--text <text> | --file <path>)";
2
+ export declare const TASK_DOC_SET_USAGE_EXAMPLE = "agentplane task doc set 202602030608-F1Q8AB --section Summary --text \"...\"";
3
+ export declare const TASK_DOC_SHOW_USAGE = "Usage: agentplane task doc show <task-id> [--section <name>] [--quiet]";
4
+ export declare const TASK_DOC_SHOW_USAGE_EXAMPLE = "agentplane task doc show 202602030608-F1Q8AB --section Summary";
5
+ export declare function cmdTaskDocSet(opts: {
6
+ cwd: string;
7
+ rootOverride?: string;
8
+ taskId: string;
9
+ args: string[];
10
+ }): Promise<number>;
11
+ export declare function cmdTaskDocShow(opts: {
12
+ cwd: string;
13
+ rootOverride?: string;
14
+ taskId: string;
15
+ args: string[];
16
+ }): Promise<number>;
17
+ //# sourceMappingURL=doc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc.d.ts","sourceRoot":"","sources":["../../../src/commands/task/doc.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,kBAAkB,8FAC8D,CAAC;AAC9F,eAAO,MAAM,0BAA0B,iFACuC,CAAC;AAC/E,eAAO,MAAM,mBAAmB,2EAC0C,CAAC;AAC3E,eAAO,MAAM,2BAA2B,mEAC0B,CAAC;AAgFnE,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoGlB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyClB"}