agentplane 0.3.1 → 0.3.2

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 CHANGED
@@ -17,7 +17,7 @@ Detailed procedures live in canonical modules from `## CANONICAL DOCS`.
17
17
  - Repository type: user project initialized with `agentplane`.
18
18
  - Gateway role: keep this file compact and deterministic; move scenario-specific details to policy modules.
19
19
  - CLI rule: use `agentplane` from `PATH`; if unavailable, stop and request installation guidance (do not invent repo-local entrypoints).
20
- - Startup shortcut: run `## COMMANDS -> Preflight`, then apply `## LOAD RULES` before any mutation.
20
+ - Startup shortcut: run `## COMMANDS -> Preflight`, then read `docs/user/agent-bootstrap.generated.mdx`, then apply `## LOAD RULES` before any mutation.
21
21
 
22
22
  ---
23
23
 
@@ -28,7 +28,7 @@ Priority order (highest first):
28
28
  1. Enforcement: CI, tests, linters, hooks, CLI validations.
29
29
  2. Policy gateway: `AGENTS.md`.
30
30
  3. Canonical policy modules from `## CANONICAL DOCS`.
31
- 4. CLI guidance: `agentplane quickstart`, `agentplane role <ROLE>`, `.agentplane/config.json`.
31
+ 4. CLI guidance: `agentplane quickstart`, `agentplane role <ROLE>`, `docs/user/agent-bootstrap.generated.mdx`, `.agentplane/config.json`.
32
32
  5. Reference examples from `## REFERENCE EXAMPLES`.
33
33
 
34
34
  Conflict rule:
@@ -66,7 +66,7 @@ agentplane task plan set <task-id> --text "..." --updated-by <ROLE>
66
66
  agentplane task plan approve <task-id> --by ORCHESTRATOR
67
67
  agentplane task start-ready <task-id> --author <ROLE> --body "Start: ..."
68
68
  agentplane verify <task-id> --ok|--rework --by <ROLE> --note "..."
69
- agentplane finish <task-id> --author <ROLE> --body "Verified: ..." --result "..." --commit <git-rev> --close-commit
69
+ agentplane finish <task-id> --author <ROLE> --body "Verified: ..." --result "..." --commit <git-rev>
70
70
  ```
71
71
 
72
72
  ### Verification
@@ -83,6 +83,7 @@ node .agentplane/policy/check-routing.mjs
83
83
  ## TOOLING
84
84
 
85
85
  - Use `## COMMANDS` as the canonical command source.
86
+ - Use `docs/user/agent-bootstrap.generated.mdx` as the canonical startup path for agent onboarding.
86
87
  - For policy changes, routing validation MUST pass via `node .agentplane/policy/check-routing.mjs`.
87
88
 
88
89
  ---
@@ -23,7 +23,7 @@ agentplane task plan set <task-id> --text "..." --updated-by <ROLE>
23
23
  agentplane task plan approve <task-id> --by ORCHESTRATOR
24
24
  agentplane task start-ready <task-id> --author <ROLE> --body "Start: ..."
25
25
  agentplane verify <task-id> --ok|--rework --by <ROLE> --note "..."
26
- agentplane finish <task-id> --author <ROLE> --body "Verified: ..." --result "..." --commit <git-rev> --close-commit
26
+ agentplane finish <task-id> --author <ROLE> --body "Verified: ..." --result "..." --commit <git-rev>
27
27
  ```
28
28
 
29
29
  ## ERROR RECOVERY
@@ -41,6 +41,7 @@ If any step fails:
41
41
  - MUST NOT perform mutating actions before explicit user approval.
42
42
  - Task documentation updates MAY be batched within one turn before approval.
43
43
  - MUST run `task plan approve` then `task start-ready` as `Step 1 -> wait -> Step 2` (never parallel).
44
+ - In direct mode, `finish` auto-creates the deterministic close commit by default; use `--no-close-commit` only for explicit manual handling.
44
45
  - MUST stop and request re-approval on material drift.
45
46
  - Do not use worktrees in direct mode.
46
47
  - Do not perform `branch_pr`-only operations.
package/bin/agentplane.js CHANGED
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ import { spawnSync } from "node:child_process";
2
3
  import path from "node:path";
3
4
  import { stat } from "node:fs/promises";
4
5
  import { fileURLToPath } from "node:url";
5
6
  import { distExists, isPackageBuildFresh } from "./dist-guard.js";
7
+ import { resolveFrameworkBinaryContext } from "./runtime-context.js";
6
8
 
7
9
  async function exists(p) {
8
10
  try {
@@ -14,15 +16,12 @@ async function exists(p) {
14
16
  }
15
17
 
16
18
  async function maybeWarnGlobalBinaryInRepoCheckout() {
17
- const cwd = process.cwd();
18
- const repoCli = path.join(cwd, "packages", "agentplane", "src", "cli.ts");
19
- const repoBin = path.join(cwd, "packages", "agentplane", "bin", "agentplane.js");
20
- if (!(await exists(repoCli)) || !(await exists(repoBin))) return;
21
-
22
19
  const thisBin = fileURLToPath(import.meta.url);
20
+ const context = resolveFrameworkBinaryContext({ cwd: process.cwd(), thisBin });
21
+ if (!context.inFrameworkCheckout || context.isRepoLocalBinary) return;
22
+
23
23
  const normalizedThis = path.resolve(thisBin);
24
- const normalizedRepo = path.resolve(repoBin);
25
- if (normalizedThis === normalizedRepo) return;
24
+ const normalizedRepo = path.resolve(context.checkout.repoBin);
26
25
 
27
26
  process.stderr.write(
28
27
  "warning: running global agentplane binary inside repository checkout.\n" +
@@ -36,6 +35,53 @@ async function maybeWarnGlobalBinaryInRepoCheckout() {
36
35
  );
37
36
  }
38
37
 
38
+ function shouldUseGlobalBinaryInFramework() {
39
+ return (process.env.AGENTPLANE_USE_GLOBAL_IN_FRAMEWORK ?? "").trim() === "1";
40
+ }
41
+
42
+ function isRepoLocalHandoffInvocation() {
43
+ return (process.env.AGENTPLANE_REPO_LOCAL_HANDOFF ?? "").trim() === "1";
44
+ }
45
+
46
+ function handoffToRepoLocalBinary(context) {
47
+ const repoBin = context.checkout?.repoBin;
48
+ if (!repoBin) return false;
49
+
50
+ process.stderr.write(
51
+ `info: detected framework checkout; delegating to repo-local binary: ${repoBin}\n`,
52
+ );
53
+
54
+ const result = spawnSync(process.execPath, [repoBin, ...process.argv.slice(2)], {
55
+ cwd: process.cwd(),
56
+ stdio: "inherit",
57
+ env: {
58
+ ...process.env,
59
+ AGENTPLANE_REPO_LOCAL_HANDOFF: "1",
60
+ },
61
+ });
62
+
63
+ if (result.error) {
64
+ process.stderr.write(`error: failed to launch repo-local binary: ${result.error.message}\n`);
65
+ process.exitCode = 2;
66
+ return true;
67
+ }
68
+
69
+ process.exitCode = result.status ?? (result.signal ? 1 : 0);
70
+ return true;
71
+ }
72
+
73
+ function maybeHandoffToRepoLocalBinary() {
74
+ if (shouldUseGlobalBinaryInFramework() || isRepoLocalHandoffInvocation()) return false;
75
+
76
+ const context = resolveFrameworkBinaryContext({
77
+ cwd: process.cwd(),
78
+ thisBin: fileURLToPath(import.meta.url),
79
+ });
80
+ if (!context.inFrameworkCheckout || context.isRepoLocalBinary) return false;
81
+
82
+ return handoffToRepoLocalBinary(context);
83
+ }
84
+
39
85
  function isHooksRunCommitMsgInvocation(argv) {
40
86
  const args = argv.slice(2).map((value) => String(value ?? "").trim());
41
87
  for (let i = 0; i < args.length; i += 1) {
@@ -119,6 +165,8 @@ async function assertDistUpToDate() {
119
165
  return true;
120
166
  }
121
167
 
122
- await maybeWarnGlobalBinaryInRepoCheckout();
123
- const ok = isHooksRunCommitMsgInvocation(process.argv) ? true : await assertDistUpToDate();
124
- if (ok) await import("../dist/cli.js");
168
+ if (!maybeHandoffToRepoLocalBinary()) {
169
+ await maybeWarnGlobalBinaryInRepoCheckout();
170
+ const ok = isHooksRunCommitMsgInvocation(process.argv) ? true : await assertDistUpToDate();
171
+ if (ok) await import("../dist/cli.js");
172
+ }
@@ -0,0 +1,20 @@
1
+ export type FrameworkCheckout = {
2
+ repoRoot: string;
3
+ packageRoot: string;
4
+ repoBin: string;
5
+ repoCli: string;
6
+ };
7
+
8
+ export type FrameworkBinaryContext = {
9
+ inFrameworkCheckout: boolean;
10
+ isRepoLocalBinary: boolean;
11
+ checkout: FrameworkCheckout | null;
12
+ thisBin: string;
13
+ };
14
+
15
+ export function findFrameworkCheckout(startDir: string): FrameworkCheckout | null;
16
+
17
+ export function resolveFrameworkBinaryContext(options: {
18
+ cwd: string;
19
+ thisBin: string;
20
+ }): FrameworkBinaryContext;
@@ -0,0 +1,81 @@
1
+ import { existsSync } from "node:fs";
2
+ import path from "node:path";
3
+
4
+ /**
5
+ * @typedef {{
6
+ * repoRoot: string;
7
+ * packageRoot: string;
8
+ * repoBin: string;
9
+ * repoCli: string;
10
+ * }} FrameworkCheckout
11
+ */
12
+
13
+ /**
14
+ * @typedef {{
15
+ * cwd: string;
16
+ * thisBin: string;
17
+ * }} FrameworkBinaryContextOptions
18
+ */
19
+
20
+ /**
21
+ * @typedef {{
22
+ * inFrameworkCheckout: boolean;
23
+ * isRepoLocalBinary: boolean;
24
+ * checkout: FrameworkCheckout | null;
25
+ * thisBin: string;
26
+ * }} FrameworkBinaryContext
27
+ */
28
+
29
+ function fileExists(p) {
30
+ return existsSync(p);
31
+ }
32
+
33
+ /**
34
+ * @param {string} startDir
35
+ * @returns {FrameworkCheckout | null}
36
+ */
37
+ export function findFrameworkCheckout(startDir) {
38
+ let dir = path.resolve(startDir);
39
+ for (;;) {
40
+ const packageRoot = path.join(dir, "packages", "agentplane");
41
+ const repoBin = path.join(packageRoot, "bin", "agentplane.js");
42
+ const repoCli = path.join(packageRoot, "src", "cli.ts");
43
+ if (fileExists(repoBin) && fileExists(repoCli)) {
44
+ return {
45
+ repoRoot: dir,
46
+ packageRoot,
47
+ repoBin,
48
+ repoCli,
49
+ };
50
+ }
51
+
52
+ const parent = path.dirname(dir);
53
+ if (parent === dir) return null;
54
+ dir = parent;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * @param {FrameworkBinaryContextOptions} options
60
+ * @returns {FrameworkBinaryContext}
61
+ */
62
+ export function resolveFrameworkBinaryContext(options) {
63
+ const cwd = path.resolve(options.cwd);
64
+ const thisBin = path.resolve(options.thisBin);
65
+ const checkout = findFrameworkCheckout(cwd);
66
+ if (!checkout) {
67
+ return {
68
+ inFrameworkCheckout: false,
69
+ isRepoLocalBinary: false,
70
+ checkout: null,
71
+ thisBin,
72
+ };
73
+ }
74
+
75
+ return {
76
+ inFrameworkCheckout: true,
77
+ isRepoLocalBinary: path.resolve(checkout.repoBin) === thisBin,
78
+ checkout,
79
+ thisBin,
80
+ };
81
+ }
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "schema_version": 1,
3
3
  "package_dir": "/home/runner/work/agentplane/agentplane/packages/agentplane",
4
- "generated_at": "2026-03-06T15:25:37.651Z",
5
- "git_head": "1be96fc47916b76925f9bc59ce7d24176216a87f",
6
- "src_cli_mtime_ms": 1772810682734.0005,
4
+ "generated_at": "2026-03-07T17:34:46.688Z",
5
+ "git_head": "8ffbebd27d5fa6dcf906b1781f8fe2d0030c6c98",
6
+ "src_cli_mtime_ms": 1772904835121.3193,
7
7
  "src_index_mtime_ms": null,
8
- "dist_cli_mtime_ms": 1772810737168.81,
8
+ "dist_cli_mtime_ms": 1772904886214.584,
9
9
  "dist_index_mtime_ms": null,
10
- "tsbuildinfo_mtime_ms": 1772810737234.8098
10
+ "tsbuildinfo_mtime_ms": 1772904886278.5845
11
11
  }
@@ -0,0 +1,18 @@
1
+ export declare const AGENT_BOOTSTRAP_DOC_PATH = "docs/user/agent-bootstrap.generated.mdx";
2
+ export type BootstrapSection = {
3
+ heading: string;
4
+ summary: string;
5
+ commands: readonly string[];
6
+ notes?: readonly string[];
7
+ };
8
+ export declare const BOOTSTRAP_PREFLIGHT_COMMANDS: readonly ["agentplane config show", "agentplane quickstart", "agentplane task list", "git status --short --untracked-files=no", "git rev-parse --abbrev-ref HEAD"];
9
+ export declare const BOOTSTRAP_TASK_PREP_COMMANDS: string[];
10
+ export declare const BOOTSTRAP_TASK_LIFECYCLE_COMMANDS: readonly [...string[], "agentplane task start-ready <task-id> --author <ROLE> --body \"Start: ...\"", "agentplane verify <task-id> --ok|--rework --by <ROLE> --note \"...\"", "agentplane finish <task-id> --author <ROLE> --body \"Verified: ...\" --result \"...\" --commit <git-rev>"];
11
+ export declare const BOOTSTRAP_VERIFY_AND_FINISH_COMMANDS: readonly ["agentplane task verify-show <task-id>", "agentplane verify <task-id> --ok|--rework --by <ROLE> --note \"...\"", "agentplane finish <task-id> --author <ROLE> --body \"Verified: ...\" --result \"...\" --commit <git-rev>"];
12
+ export declare const BOOTSTRAP_VERIFICATION_COMMANDS: readonly ["agentplane task verify-show <task-id>", "agentplane verify <task-id> --ok|--rework --by <ROLE> --note \"...\"", "agentplane doctor", "node .agentplane/policy/check-routing.mjs"];
13
+ export declare const BOOTSTRAP_RECOVERY_COMMANDS: readonly ["agentplane doctor", "agentplane upgrade --dry-run", "agentplane upgrade"];
14
+ export declare const BOOTSTRAP_SECTIONS: readonly BootstrapSection[];
15
+ export declare function renderBootstrapReferenceLine(): string;
16
+ export declare function renderBootstrapSectionLines(sections: readonly BootstrapSection[]): string[];
17
+ export declare function renderBootstrapDoc(): string;
18
+ //# sourceMappingURL=bootstrap-guide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap-guide.d.ts","sourceRoot":"","sources":["../../src/cli/bootstrap-guide.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,wBAAwB,4CAA4C,CAAC;AAElF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,4BAA4B,oKAM/B,CAAC;AAEX,eAAO,MAAM,4BAA4B,UAIxC,CAAC;AAEF,eAAO,MAAM,iCAAiC,2RAKpC,CAAC;AAEX,eAAO,MAAM,oCAAoC,wOAIvC,CAAC;AAEX,eAAO,MAAM,+BAA+B,8LAKlC,CAAC;AAEX,eAAO,MAAM,2BAA2B,sFAI9B,CAAC;AAEX,eAAO,MAAM,kBAAkB,EAAE,SAAS,gBAAgB,EA+ChD,CAAC;AAEX,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,EAAE,CAiB3F;AAMD,wBAAgB,kBAAkB,IAAI,MAAM,CA0B3C"}
@@ -0,0 +1,132 @@
1
+ import { COMMAND_SNIPPETS } from "./command-snippets.js";
2
+ export const AGENT_BOOTSTRAP_DOC_PATH = "docs/user/agent-bootstrap.generated.mdx";
3
+ export const BOOTSTRAP_PREFLIGHT_COMMANDS = [
4
+ "agentplane config show",
5
+ "agentplane quickstart",
6
+ "agentplane task list",
7
+ "git status --short --untracked-files=no",
8
+ "git rev-parse --abbrev-ref HEAD",
9
+ ];
10
+ export const BOOTSTRAP_TASK_PREP_COMMANDS = [
11
+ COMMAND_SNIPPETS.core.taskNew,
12
+ 'agentplane task plan set <task-id> --text "..." --updated-by <ROLE>',
13
+ "agentplane task plan approve <task-id> --by ORCHESTRATOR",
14
+ ];
15
+ export const BOOTSTRAP_TASK_LIFECYCLE_COMMANDS = [
16
+ ...BOOTSTRAP_TASK_PREP_COMMANDS,
17
+ COMMAND_SNIPPETS.core.startTask,
18
+ COMMAND_SNIPPETS.core.verifyTask,
19
+ 'agentplane finish <task-id> --author <ROLE> --body "Verified: ..." --result "..." --commit <git-rev>',
20
+ ];
21
+ export const BOOTSTRAP_VERIFY_AND_FINISH_COMMANDS = [
22
+ "agentplane task verify-show <task-id>",
23
+ COMMAND_SNIPPETS.core.verifyTask,
24
+ 'agentplane finish <task-id> --author <ROLE> --body "Verified: ..." --result "..." --commit <git-rev>',
25
+ ];
26
+ export const BOOTSTRAP_VERIFICATION_COMMANDS = [
27
+ "agentplane task verify-show <task-id>",
28
+ COMMAND_SNIPPETS.core.verifyTask,
29
+ "agentplane doctor",
30
+ "node .agentplane/policy/check-routing.mjs",
31
+ ];
32
+ export const BOOTSTRAP_RECOVERY_COMMANDS = [
33
+ "agentplane doctor",
34
+ "agentplane upgrade --dry-run",
35
+ "agentplane upgrade",
36
+ ];
37
+ export const BOOTSTRAP_SECTIONS = [
38
+ {
39
+ heading: "1. Preflight",
40
+ summary: "Establish workflow mode, current branch, current task state, and tracked working-tree state.",
41
+ commands: BOOTSTRAP_PREFLIGHT_COMMANDS,
42
+ notes: [
43
+ "Run this before any mutation.",
44
+ "If the project is not initialized, stop and use `agentplane init` first.",
45
+ ],
46
+ },
47
+ {
48
+ heading: "2. Prepare executable task scope",
49
+ summary: "Work only through executable task ids. Create the task, fill plan/docs, then approve the plan.",
50
+ commands: BOOTSTRAP_TASK_PREP_COMMANDS,
51
+ notes: [
52
+ "Use `task doc set` to fill required README sections before approval.",
53
+ "For dependent tasks, wait until upstream tasks are DONE before `task start-ready`.",
54
+ ],
55
+ },
56
+ {
57
+ heading: "3. Start work deterministically",
58
+ summary: "Move the task to DOING only after plan approval succeeds.",
59
+ commands: [COMMAND_SNIPPETS.core.startTask],
60
+ notes: ["`task plan approve` and `task start-ready` must run sequentially, never in parallel."],
61
+ },
62
+ {
63
+ heading: "4. Verify and finish",
64
+ summary: "Treat Verify Steps as the contract, then record verification and close with traceable metadata.",
65
+ commands: BOOTSTRAP_VERIFY_AND_FINISH_COMMANDS,
66
+ notes: [
67
+ "In `direct`, `finish` creates the deterministic close commit by default.",
68
+ "Use `--no-close-commit` only for explicit manual close handling.",
69
+ ],
70
+ },
71
+ {
72
+ heading: "5. Recover mixed or broken state",
73
+ summary: "Use diagnostics before manual repair, especially after framework upgrades or partial edits.",
74
+ commands: BOOTSTRAP_RECOVERY_COMMANDS,
75
+ notes: [
76
+ "Run `doctor` before touching managed policy files by hand.",
77
+ "`upgrade` applies the managed framework files from the installed CLI bundle.",
78
+ ],
79
+ },
80
+ ];
81
+ export function renderBootstrapReferenceLine() {
82
+ return `Canonical bootstrap doc: \`${AGENT_BOOTSTRAP_DOC_PATH}\`.`;
83
+ }
84
+ export function renderBootstrapSectionLines(sections) {
85
+ const lines = [];
86
+ for (const section of sections) {
87
+ lines.push(`## ${section.heading}`, "", section.summary, "");
88
+ for (const command of section.commands) {
89
+ lines.push(`- \`${command}\``);
90
+ }
91
+ if (section.notes && section.notes.length > 0) {
92
+ lines.push("");
93
+ for (const note of section.notes) {
94
+ lines.push(`- ${note}`);
95
+ }
96
+ }
97
+ lines.push("");
98
+ }
99
+ if (lines.at(-1) === "")
100
+ lines.pop();
101
+ return lines;
102
+ }
103
+ function renderCommandBlock(commands) {
104
+ return ["```bash", ...commands, "```"];
105
+ }
106
+ export function renderBootstrapDoc() {
107
+ const lines = [
108
+ "---",
109
+ 'title: "Agent bootstrap"',
110
+ 'description: "The shortest canonical startup path for agent work in an Agent Plane repository."',
111
+ "---",
112
+ "",
113
+ "This page is generated from `packages/agentplane/src/cli/bootstrap-guide.ts`.",
114
+ "",
115
+ "Use it as the single startup path for agents. `AGENTS.md`, `agentplane quickstart`, and `agentplane role <ROLE>` should point here instead of restating lifecycle prose.",
116
+ "",
117
+ "## Copy-paste start block",
118
+ "",
119
+ ...renderCommandBlock(BOOTSTRAP_PREFLIGHT_COMMANDS),
120
+ "",
121
+ "After preflight, continue with the smallest task flow that matches your mode and role.",
122
+ "",
123
+ ...renderBootstrapSectionLines(BOOTSTRAP_SECTIONS),
124
+ "",
125
+ "## Direct vs branch_pr",
126
+ "",
127
+ "- `direct`: work in the current checkout and finish the task yourself.",
128
+ "- `branch_pr`: start a task branch/worktree, maintain PR artifacts, and let INTEGRATOR close on base.",
129
+ "",
130
+ ];
131
+ return `${lines.join("\n")}\n`;
132
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"command-guide.d.ts","sourceRoot":"","sources":["../../src/cli/command-guide.ts"],"names":[],"mappings":"AA0MA,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAEpC;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CA6FzC"}
1
+ {"version":3,"file":"command-guide.d.ts","sourceRoot":"","sources":["../../src/cli/command-guide.ts"],"names":[],"mappings":"AA+GA,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAEpC;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAsCzC"}
@@ -1,183 +1,103 @@
1
1
  import { COMMAND_SNIPPETS } from "./command-snippets.js";
2
- const CHEAT_SHEET_ROWS = [
3
- {
4
- operation: "PLANNER: list/show tasks",
5
- command: "`agentplane task list` / `agentplane task show <task-id>`",
6
- },
7
- {
8
- operation: "PLANNER: set/approve/reject plan",
9
- command: '`agentplane task plan set <task-id> --text "..." --updated-by <id>` / `agentplane task plan approve <task-id> --by <id> --note "OK"`',
10
- },
11
- {
12
- operation: "PLANNER: create task (auto ID)",
13
- command: '`agentplane task new --title "..." --description "..." --priority med --owner CODER --tag <tag> [--depends-on <task-id|json>]`',
14
- },
15
- {
16
- operation: "PLANNER: add/update task",
17
- command: "`agentplane task add <task-id> ...` / `agentplane task update <task-id> ...`",
18
- },
19
- {
20
- operation: "PLANNER: backfill/repair scaffold",
21
- command: "`agentplane task scaffold <task-id>` (backfill/import/manual repair only)",
22
- },
23
- {
24
- operation: "PLANNER: derive implementation from spike",
25
- command: '`agentplane task derive <spike-id> --title "..." --description "..." --priority med --owner CODER --tag code`',
26
- },
27
- {
28
- operation: "Config: show/set",
29
- command: "`agentplane config show` / `agentplane config set <key> <value>`",
30
- },
31
- {
32
- operation: "CODER/TESTER/DOCS: start checkout (branch_pr)",
33
- command: "`agentplane work start <task-id> --agent <ROLE> --slug <slug> --worktree`",
34
- },
35
- {
36
- operation: "CODER/TESTER: start task deterministically",
37
- command: '`agentplane task start-ready <task-id> --author <ROLE> --body "Start: ..."` (run after successful `task plan approve`; do not run in parallel)',
38
- },
39
- {
40
- operation: "CODER/TESTER/DOCS: update PR artifacts",
41
- command: "`agentplane pr update <task-id>`",
42
- },
43
- {
44
- operation: "CODER/TESTER/DOCS/REVIEWER: add handoff note",
45
- command: '`agentplane pr note <task-id> --author <ROLE> --body "..."`',
46
- },
47
- {
48
- operation: "CODER/TESTER: verify task",
49
- command: '`agentplane verify <task-id> --ok|--rework --by <id> --note "..."` (record-only; appends to README)',
50
- },
51
- {
52
- operation: "CODER/TESTER: print Verify Steps",
53
- command: "`agentplane task verify-show <task-id>`",
54
- },
55
- {
56
- operation: "REVIEWER: check PR artifacts",
57
- command: "`agentplane pr check <task-id>`",
58
- },
59
- {
60
- operation: "INTEGRATOR: integrate task",
61
- command: "`agentplane integrate <task-id> --branch task/<task-id>/<slug> --merge-strategy squash --run-verify`",
62
- },
63
- {
64
- operation: "INTEGRATOR: finish task(s)",
65
- command: '`agentplane finish <task-id> [<task-id> ...] --commit <git-rev> --author INTEGRATOR --body "Verified: ..." [--result "<one line>"] [--close-commit] [--close-unstage-others]`',
66
- },
67
- {
68
- operation: "INTEGRATOR: commit closure",
69
- command: "Preferred: `agentplane finish <task-id> --close-commit` (single command). Legacy/manual: `agentplane commit <task-id> --close [--check-only] [--unstage-others]` / duplicate no-op close: `agentplane task close-duplicate <task-id> --of <canonical-task-id> --author <ROLE>`",
70
- },
71
- ];
2
+ import { AGENT_BOOTSTRAP_DOC_PATH, BOOTSTRAP_SECTIONS, renderBootstrapReferenceLine, } from "./bootstrap-guide.js";
3
+ function renderBootstrapOverview() {
4
+ const lines = [];
5
+ for (const section of BOOTSTRAP_SECTIONS) {
6
+ lines.push(`## ${section.heading}`, "", section.summary, "");
7
+ for (const command of section.commands) {
8
+ lines.push(`- \`${command}\``);
9
+ }
10
+ lines.push("");
11
+ }
12
+ if (lines.at(-1) === "")
13
+ lines.pop();
14
+ return lines;
15
+ }
72
16
  const ROLE_GUIDES = [
73
17
  {
74
18
  role: "ORCHESTRATOR",
75
19
  lines: [
76
- "- Plan intake: `agentplane task list` / `agentplane task show <task-id>`",
77
- "- After plan approval: ask PLANNER to create executable tasks directly from the approved task graph.",
78
- "- If task graph has exactly one work item, create exactly one executable task.",
79
- "- Two-stage verification: `## Verify Steps` is the ex-ante contract; `agentplane verify ...` appends an ex-post entry into `## Verification`.",
20
+ `- Shared bootstrap path: \`${COMMAND_SNIPPETS.core.quickstart}\` -> \`${AGENT_BOOTSTRAP_DOC_PATH}\`.`,
21
+ "- Owns preflight, plan summaries, approvals, and scope checkpoints.",
22
+ "- Does not create non-executable tasks or bypass lifecycle guardrails.",
80
23
  ],
81
24
  },
82
25
  {
83
26
  role: "PLANNER",
84
27
  lines: [
85
- '- TODO scan: `agentplane task list` / `agentplane task search "..."` / `agentplane task next`',
86
- '- Create tasks: `agentplane task new --title "..." --description "..." --priority med --owner <ROLE> --depends-on "[]" --tag <tag>` (tags are required; use `task add` only for imported IDs)',
87
- '- Update tasks: `agentplane task update <task-id> --title "..." --description "..." --priority med --owner <ROLE> --depends-on <task-id>`',
88
- "- `task new` auto-seeds README sections; use `task scaffold` only for backfill/import/manual repair.",
89
- '- Plan lifecycle: `agentplane task plan set <task-id> --text "..." --updated-by <ROLE>` -> `agentplane task plan approve <task-id> --by <id>`',
90
- "- Verify Steps discipline: if a task primary tag is verify-required (default: code/data/ops), fill `## Verify Steps` before plan approval.",
91
- "- Doc quality gate: `task plan approve` and `finish` fail when required agent-filled sections (`Summary/Scope/Plan/Risks/Rollback Plan`, per config) are empty/TODO placeholders.",
92
- '- Task docs (when planning needs it): `agentplane task doc set <task-id> --section Summary --text "..."`; if `--text`/`--file` contains multiple known headings, the command applies it as one batched full-doc update.',
28
+ `- Shared bootstrap path: \`${COMMAND_SNIPPETS.core.quickstart}\` -> \`${AGENT_BOOTSTRAP_DOC_PATH}\`.`,
29
+ '- Create executable tasks with `agentplane task new --title "..." --description "..." --priority med --owner <ROLE> --tag <tag>`.',
30
+ '- Fill docs with `agentplane task doc set <task-id> --section <name> --text "..."` and set plan text with `agentplane task plan set <task-id> --text "..." --updated-by <ROLE>`.',
31
+ "- Approve plan only after required sections and Verify Steps are ready.",
93
32
  ],
94
33
  },
95
34
  {
96
35
  role: "CODER",
97
36
  lines: [
98
- "- direct mode: single-stream in the current checkout; `agentplane work start <task-id> --agent <ROLE> --slug <slug>` records the active task and keeps the current branch (no task branches). Use `task doc set` / `task plan set` for normal docs updates; batched doc updates are allowed before approval.",
99
- "- branch_pr: `agentplane work start <task-id> --agent <ROLE> --slug <slug> --worktree`",
100
- '- Start status (deterministic): `agentplane task start-ready <task-id> --author <ROLE> --body "Start: ..."` (after `task plan approve`, sequential only).',
101
- '- Other status updates: `agentplane block <task-id> --author <ROLE> --body "Blocked: ..."`',
102
- "- Verify Steps: `agentplane task verify-show <task-id>` (use as the verification contract before recording results).",
103
- '- Verify: `agentplane verify <task-id> --ok|--rework --by <ROLE> --note "..."`',
104
- '- PR artifacts (branch_pr): `agentplane pr open <task-id> --branch task/<task-id>/<slug> --author <ROLE>` / `agentplane pr update <task-id>` / `agentplane pr note <task-id> --author <ROLE> --body "..."`',
105
- '- Commit: `agentplane guard commit <task-id> -m "<emoji> <suffix> <scope>: <summary>"` / `agentplane commit <task-id> -m "<emoji> <suffix> <scope>: <summary>" --allow <path-prefix>` / preferred close path: `agentplane finish <task-id> --close-commit [--close-unstage-others]`',
37
+ `- Shared bootstrap path: \`${COMMAND_SNIPPETS.core.quickstart}\` -> \`${AGENT_BOOTSTRAP_DOC_PATH}\`.`,
38
+ "- direct: stay in the current checkout; branch_pr: start a task branch/worktree first.",
39
+ `- Start deterministically with \`${COMMAND_SNIPPETS.core.startTask}\` after plan approval.`,
40
+ '- Treat `agentplane task verify-show <task-id>` as the verification contract, then record `agentplane verify <task-id> --ok|--rework --by <ROLE> --note "..."`.',
41
+ `- Preferred direct close path: \`${COMMAND_SNIPPETS.core.finishTask}\` with \`--result "..." \`; add \`--no-close-commit\` only for explicit manual close handling.`,
106
42
  ],
107
43
  },
108
44
  {
109
45
  role: "TESTER",
110
46
  lines: [
111
- "- direct mode: single-stream in the current checkout; `agentplane work start <task-id> --agent <ROLE> --slug <slug>` records the active task and keeps the current branch (no task branches). Use `task doc set` / `task plan set` for normal docs updates; batched doc updates are allowed before approval.",
112
- "- branch_pr: `agentplane work start <task-id> --agent <ROLE> --slug <slug> --worktree`",
113
- '- Start status (deterministic): `agentplane task start-ready <task-id> --author <ROLE> --body "Start: ..."` (after `task plan approve`, sequential only).',
114
- '- Other status updates: `agentplane block <task-id> --author <ROLE> --body "Blocked: ..."`',
115
- "- Verify Steps: `agentplane task verify-show <task-id>` (treat as the verification contract).",
116
- '- Verify: `agentplane verify <task-id> --ok|--rework --by <ROLE> --note "..."`',
117
- '- PR artifacts (branch_pr): `agentplane pr open <task-id> --branch task/<task-id>/<slug> --author <ROLE>` / `agentplane pr update <task-id>` / `agentplane pr note <task-id> --author <ROLE> --body "..."`',
118
- '- Commit: `agentplane guard commit <task-id> -m "<emoji> <suffix> <scope>: <summary>"` / `agentplane commit <task-id> -m "<emoji> <suffix> <scope>: <summary>" --allow <path-prefix>` / preferred close path: `agentplane finish <task-id> --close-commit [--close-unstage-others]`',
47
+ `- Shared bootstrap path: \`${COMMAND_SNIPPETS.core.quickstart}\` -> \`${AGENT_BOOTSTRAP_DOC_PATH}\`.`,
48
+ "- Start only after plan approval and explicit Verify Steps exist.",
49
+ '- Use `agentplane task verify-show <task-id>` before running checks, then record `agentplane verify <task-id> --ok|--rework --by <ROLE> --note "..."`.',
50
+ `- In direct mode, close with \`${COMMAND_SNIPPETS.core.finishTask}\` plus \`--result "..." \` when you own final verification.`,
119
51
  ],
120
52
  },
121
53
  {
122
54
  role: "DOCS",
123
55
  lines: [
124
- '- Task docs: `agentplane task doc set <task-id> --section Summary --text "..."` (repeat per section, or send one multi-heading full-doc payload via `--text`/`--file`)',
125
- '- PR notes: `agentplane pr note <task-id> --author DOCS --body "..."`',
126
- '- Commit: `agentplane guard commit <task-id> -m "<emoji> <suffix> <scope>: <summary>"` / `agentplane commit <task-id> -m "<emoji> <suffix> <scope>: <summary>" --allow <path-prefix>` / preferred close path: `agentplane finish <task-id> --close-commit [--close-unstage-others]`',
56
+ `- Shared bootstrap path: \`${COMMAND_SNIPPETS.core.quickstart}\` -> \`${AGENT_BOOTSTRAP_DOC_PATH}\`.`,
57
+ '- Keep task docs and user docs aligned with runtime behavior via `agentplane task doc set <task-id> --section <name> --text "..."`.',
58
+ "- For implementation tasks, verify generated/help surfaces after changing CLI-facing text.",
127
59
  ],
128
60
  },
129
61
  {
130
62
  role: "REVIEWER",
131
63
  lines: [
132
- "- Review artifacts: `agentplane pr check <task-id>` / `agentplane task show <task-id>`",
133
- '- Handoff notes: `agentplane pr note <task-id> --author REVIEWER --body "..."`',
64
+ `- Shared bootstrap path: \`${COMMAND_SNIPPETS.core.quickstart}\` -> \`${AGENT_BOOTSTRAP_DOC_PATH}\`.`,
65
+ "- Review artifacts with `agentplane task show <task-id>` and `agentplane pr check <task-id>` when relevant.",
66
+ "- Focus on regressions, lifecycle drift, and missing verification evidence.",
134
67
  ],
135
68
  },
136
69
  {
137
70
  role: "INTEGRATOR",
138
71
  lines: [
139
- '- branch_pr: `agentplane pr check <task-id>` -> `agentplane integrate <task-id> --branch task/<task-id>/<slug> --merge-strategy squash --run-verify` -> `agentplane finish <task-id> --commit <git-rev> --author INTEGRATOR --body "Verified: ..." --close-commit`',
140
- '- direct: task owner uses `agentplane finish <task-id> --commit <git-rev> --author <OWNER> --body "Verified: ..." --close-commit` after the implementation commit',
141
- "- Optional cleanup: `agentplane cleanup merged --yes`",
72
+ `- Shared bootstrap path: \`${COMMAND_SNIPPETS.core.quickstart}\` -> \`${AGENT_BOOTSTRAP_DOC_PATH}\`.`,
73
+ '- branch_pr: `agentplane pr check <task-id>` -> `agentplane integrate <task-id> --branch task/<task-id>/<slug> --merge-strategy squash --run-verify` -> `agentplane finish <task-id> --commit <git-rev> --author INTEGRATOR --body "Verified: ..." --result "..." --close-commit`.',
74
+ `- direct: the task owner normally closes with \`${COMMAND_SNIPPETS.core.finishTask}\` plus \`--result "..." \`.`,
142
75
  ],
143
76
  },
144
77
  {
145
78
  role: "CREATOR",
146
79
  lines: [
147
- '- Task bookkeeping: `agentplane task update <task-id> ...` / `agentplane task start-ready <task-id> --author CREATOR --body "Start: ..."`',
148
- '- Commits: `agentplane guard commit <task-id> -m "<emoji> <suffix> <scope>: <summary>"` / `agentplane commit <task-id> -m "<emoji> <suffix> <scope>: <summary>" --allow <path-prefix>`',
80
+ `- Shared bootstrap path: \`${COMMAND_SNIPPETS.core.quickstart}\` -> \`${AGENT_BOOTSTRAP_DOC_PATH}\`.`,
81
+ `- Use \`${COMMAND_SNIPPETS.core.startTask}\` only when the new-agent creation task is approved and ready.`,
82
+ "- Keep commits scoped to the created agent artifacts and task docs.",
149
83
  ],
150
84
  },
151
85
  {
152
86
  role: "REDMINE",
153
87
  lines: [
154
- `- Sync before/after updates: \`${COMMAND_SNIPPETS.sync.pullRedmineExplicit}\` / \`${COMMAND_SNIPPETS.sync.pushRedmineExplicitWithYes}\``,
155
- "- Then use normal task/doc commands (`agentplane task list` / `agentplane task show` / `agentplane task update` / `agentplane task doc set`) as needed.",
88
+ `- Shared bootstrap path: \`${COMMAND_SNIPPETS.core.quickstart}\` -> \`${AGENT_BOOTSTRAP_DOC_PATH}\`.`,
89
+ `- Sync explicitly with \`${COMMAND_SNIPPETS.sync.pullRedmineExplicit}\` / \`${COMMAND_SNIPPETS.sync.pushRedmineExplicitWithYes}\`.`,
90
+ "- After sync, follow the same task/bootstrap lifecycle as local backends.",
156
91
  ],
157
92
  },
158
93
  {
159
94
  role: "UPDATER",
160
95
  lines: [
161
- '- Read-only audit: `agentplane task list` / `agentplane task show` / `agentplane task search "..."` / `agentplane task next` (no write commands).',
96
+ `- Shared bootstrap path: \`${COMMAND_SNIPPETS.core.quickstart}\` -> \`${AGENT_BOOTSTRAP_DOC_PATH}\`.`,
97
+ "- Read-only role: inspect state, do not mutate task or workflow artifacts.",
162
98
  ],
163
99
  },
164
100
  ];
165
- function renderCheatSheet(rows) {
166
- const lines = ["Operation | Command", "--- | ---"];
167
- for (const row of rows) {
168
- lines.push(`${row.operation} | ${row.command}`);
169
- }
170
- return lines;
171
- }
172
- function renderRoleSection() {
173
- const lines = [];
174
- for (const guide of ROLE_GUIDES) {
175
- lines.push(`### ${guide.role}`, ...guide.lines, "");
176
- }
177
- if (lines.at(-1) === "")
178
- lines.pop();
179
- return lines;
180
- }
181
101
  export function listRoles() {
182
102
  return ROLE_GUIDES.map((guide) => guide.role);
183
103
  }
@@ -195,84 +115,30 @@ export function renderQuickstart() {
195
115
  return [
196
116
  "# agentplane quickstart",
197
117
  "",
198
- "The policy gateway file (AGENTS.md or CLAUDE.md) is the source of truth for workflow/process policy; quickstart and role output are the source of truth for CLI syntax and artifacts.",
118
+ "The policy gateway file (AGENTS.md or CLAUDE.md) is the source of truth for workflow/process policy. CLI syntax lives in quickstart and `agentplane role <ROLE>`.",
199
119
  "Do not edit `.agentplane/tasks.json` by hand.",
120
+ "If the repository is not initialized yet, stop and run `agentplane init` first.",
200
121
  "",
201
- "- See your policy gateway file (AGENTS.md or CLAUDE.md) for canonical workflow policy and approval gates.",
202
- "",
203
- "## Project setup",
122
+ renderBootstrapReferenceLine(),
204
123
  "",
205
- "- `agentplane init` (bootstrap `.agentplane/`)",
206
- "- `agentplane config show` / `agentplane config set <key> <value>`",
207
- "- `agentplane mode get` / `agentplane mode set <direct|branch_pr>`",
208
- "- `agentplane ide sync` (regenerate IDE entrypoints)",
124
+ ...renderBootstrapOverview(),
209
125
  "",
210
- "## Daily task workflow",
126
+ "## Role-specific deltas",
211
127
  "",
212
- `- \`${COMMAND_SNIPPETS.core.taskList}\` / \`${COMMAND_SNIPPETS.core.taskShow}\``,
213
- `- \`${COMMAND_SNIPPETS.core.taskNew}\``,
214
- `- \`${COMMAND_SNIPPETS.core.startTask}\``,
215
- `- \`${COMMAND_SNIPPETS.core.verifyTask}\``,
216
- `- \`${COMMAND_SNIPPETS.core.finishTask}\``,
128
+ `- Use \`${COMMAND_SNIPPETS.core.role}\` for role-specific constraints after you understand the shared bootstrap path.`,
129
+ "- Role output should add deltas, not replace the canonical bootstrap flow.",
217
130
  "",
218
- "## Harness engeneering loop",
219
- "",
220
- "- Constrain: policy + workflow contract first.",
221
- "- Execute: small explicit transitions.",
222
- "- Observe: structured artifacts and diagnostics.",
223
- "- Recover: deterministic fallback before manual repair.",
224
- "",
225
- "## Branch workflow (branch_pr)",
131
+ "## Branch workflow extras",
226
132
  "",
227
133
  "- `agentplane work start <task-id> --agent <ROLE> --slug <slug> --worktree`",
228
134
  "- `agentplane pr open <task-id>` / `agentplane pr update <task-id>` / `agentplane pr check <task-id>`",
229
135
  "- `agentplane integrate <task-id> --branch task/<task-id>/<slug> --run-verify`",
230
136
  "",
231
- "## Workflow operations (core)",
232
- "- `agentplane workflow debug`",
233
- "- `agentplane workflow sync`",
234
- "- `agentplane workflow land`",
235
- "",
236
- "## Recipes and scenarios (extensions)",
237
- "",
238
- "- `agentplane recipes list`",
239
- "- `agentplane recipes list --tag <tag>`",
240
- "- `agentplane recipes explain <id>`",
241
- "- `agentplane scenario list`",
242
- "- `agentplane scenario run <recipe:scenario>`",
243
- "",
244
137
  "## More guidance",
245
138
  "",
246
- `- \`${COMMAND_SNIPPETS.core.quickstart}\` and \`${COMMAND_SNIPPETS.core.role}\` show command guidance.`,
247
- "",
248
- "## Agent cheat sheet",
249
- "",
250
- ...renderCheatSheet(CHEAT_SHEET_ROWS),
251
- "",
252
- "## Config management",
253
- "",
254
- "- Show the current config: `agentplane config show`",
255
- "- Set a value by dotted key: `agentplane config set workflow_mode branch_pr`",
256
- '- Set JSON values (lists/objects): `agentplane config set tasks.verify.require_steps_for_primary \'["code","data","ops"]\'`',
257
- "",
258
- "## Role/phase command guide (when to use what)",
259
- "",
260
- "Use `agentplane role <ROLE>` to print a single block from this section.",
261
- "",
262
- ...renderRoleSection(),
263
- "",
264
- "## Global flags",
265
- "",
266
- "- `--root <path>`: treat <path> as project root",
267
- "- `--output <text|json>`: force global CLI output mode (`json` is agent-oriented envelope mode)",
268
- "- `--json-errors`: emit JSON-formatted errors",
269
- "- `--help` / `-h`: show help",
270
- "- `--version`: show version",
271
- "- `--no-update-check`: skip checking npm for a newer CLI version",
272
- "",
273
- "Notes:",
274
- "- `AGENTPLANE_OUTPUT=json` enables global JSON output mode for agent runtimes.",
275
- "- `.env` at the repo root is loaded automatically (without overwriting existing environment variables).",
139
+ "- `agentplane help <command>` for command-level flags and examples.",
140
+ `- \`${COMMAND_SNIPPETS.core.role}\` for role-specific deltas.`,
141
+ `- \`${AGENT_BOOTSTRAP_DOC_PATH}\` for the canonical startup path in repository docs.`,
276
142
  "",
277
143
  "## Commit message format",
278
144
  "",
@@ -2,10 +2,10 @@ export declare const COMMAND_SNIPPETS: {
2
2
  readonly core: {
3
3
  readonly taskList: "agentplane task list";
4
4
  readonly taskShow: "agentplane task show <task-id>";
5
- readonly taskNew: "agentplane task new --title \"...\" --description \"...\" --priority med --owner CODER --tag <tag>";
5
+ readonly taskNew: "agentplane task new --title \"...\" --description \"...\" --priority med --owner <ROLE> --tag <tag>";
6
6
  readonly startTask: "agentplane task start-ready <task-id> --author <ROLE> --body \"Start: ...\"";
7
7
  readonly verifyTask: "agentplane verify <task-id> --ok|--rework --by <ROLE> --note \"...\"";
8
- readonly finishTask: "agentplane finish <task-id> --author <ROLE> --body \"Verified: ...\" --commit <git-rev> --close-commit";
8
+ readonly finishTask: "agentplane finish <task-id> --author <ROLE> --body \"Verified: ...\" --commit <git-rev>";
9
9
  readonly quickstart: "agentplane quickstart";
10
10
  readonly role: "agentplane role <ROLE>";
11
11
  };
@@ -2,10 +2,10 @@ export const COMMAND_SNIPPETS = {
2
2
  core: {
3
3
  taskList: "agentplane task list",
4
4
  taskShow: "agentplane task show <task-id>",
5
- taskNew: 'agentplane task new --title "..." --description "..." --priority med --owner CODER --tag <tag>',
5
+ taskNew: 'agentplane task new --title "..." --description "..." --priority med --owner <ROLE> --tag <tag>',
6
6
  startTask: 'agentplane task start-ready <task-id> --author <ROLE> --body "Start: ..."',
7
7
  verifyTask: 'agentplane verify <task-id> --ok|--rework --by <ROLE> --note "..."',
8
- finishTask: 'agentplane finish <task-id> --author <ROLE> --body "Verified: ..." --commit <git-rev> --close-commit',
8
+ finishTask: 'agentplane finish <task-id> --author <ROLE> --body "Verified: ..." --commit <git-rev>',
9
9
  quickstart: "agentplane quickstart",
10
10
  role: "agentplane role <ROLE>",
11
11
  },
@@ -15,7 +15,7 @@ import { wrapCommand } from "./wrap-command.js";
15
15
  export const quickstartSpec = {
16
16
  id: ["quickstart"],
17
17
  group: "Core",
18
- summary: "Print CLI quickstart and command cheat sheet.",
18
+ summary: "Print the canonical agent bootstrap path and startup guidance.",
19
19
  options: [
20
20
  {
21
21
  kind: "boolean",
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.run.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.run.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAM1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAyUrD,eAAO,MAAM,SAAS,EAAE,cAAc,CAAC,YAAY,CAmDlD,CAAC"}
1
+ {"version":3,"file":"doctor.run.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.run.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAM1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAoXrD,eAAO,MAAM,SAAS,EAAE,cAAc,CAAC,YAAY,CAmDlD,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
3
4
  import { resolveProject } from "@agentplaneorg/core";
4
5
  import { warnMessage, successMessage } from "../cli/output.js";
5
6
  import { RUNTIME_GITIGNORE_LINES } from "../shared/runtime-artifacts.js";
@@ -57,6 +58,29 @@ async function isDirectory(absPath) {
57
58
  return false;
58
59
  }
59
60
  }
61
+ async function listMissingManagedPolicyFiles(repoRoot) {
62
+ const manifestPath = fileURLToPath(new URL("../../assets/framework.manifest.json", import.meta.url));
63
+ let parsed = {};
64
+ try {
65
+ parsed = JSON.parse(await fs.readFile(manifestPath, "utf8"));
66
+ }
67
+ catch {
68
+ return [];
69
+ }
70
+ const relPaths = Array.isArray(parsed.files)
71
+ ? parsed.files
72
+ .filter((entry) => entry?.required === true && typeof entry.path === "string")
73
+ .map((entry) => String(entry.path).replaceAll("\\", "/").trim())
74
+ .filter((relPath) => relPath.startsWith(".agentplane/policy/"))
75
+ : [];
76
+ const missing = [];
77
+ for (const relPath of relPaths) {
78
+ if (!(await pathExists(path.join(repoRoot, relPath)))) {
79
+ missing.push(relPath);
80
+ }
81
+ }
82
+ return missing.toSorted();
83
+ }
60
84
  async function checkWorkspace(repoRoot) {
61
85
  const problems = [];
62
86
  const requiredFiles = [path.join(repoRoot, ".agentplane", "config.json")];
@@ -72,6 +96,19 @@ async function checkWorkspace(repoRoot) {
72
96
  if (!(await pathExists(gateway.absPath))) {
73
97
  problems.push("Missing required policy gateway file: AGENTS.md or CLAUDE.md");
74
98
  }
99
+ if (await pathExists(gateway.absPath)) {
100
+ const missingManagedPolicy = await listMissingManagedPolicyFiles(repoRoot);
101
+ if (missingManagedPolicy.length > 0) {
102
+ const listed = missingManagedPolicy.slice(0, 8).join(", ");
103
+ const more = missingManagedPolicy.length > 8 ? ` (+${missingManagedPolicy.length - 8} more)` : "";
104
+ problems.push("Managed policy tree is incomplete for the current framework gateway. " +
105
+ `Missing required files: ${listed}${more}. ` +
106
+ "This often means AGENTS.md/CLAUDE.md was updated manually or the repo was upgraded " +
107
+ "with an older agentplane CLI. Recovery: update or reinstall agentplane, then run " +
108
+ "`agentplane upgrade --yes` (or `agentplane upgrade --remote --yes`). " +
109
+ "See `docs/help/legacy-upgrade-recovery.mdx` for the shortest recovery path.");
110
+ }
111
+ }
75
112
  const agentsDir = path.join(repoRoot, ".agentplane", "agents");
76
113
  if (!(await isDirectory(agentsDir))) {
77
114
  problems.push("Missing required directory: .agentplane/agents");
@@ -1 +1 @@
1
- {"version":3,"file":"finish.run.d.ts","sourceRoot":"","sources":["../../src/commands/finish.run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEjE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IACrE,KAAK,UAAU,EAAE,GAAG,YAAY,KAAG,OAAO,CAAC,MAAM,CAAC,CAsCjE"}
1
+ {"version":3,"file":"finish.run.d.ts","sourceRoot":"","sources":["../../src/commands/finish.run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEjE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IACrE,KAAK,UAAU,EAAE,GAAG,YAAY,KAAG,OAAO,CAAC,MAAM,CAAC,CAuCjE"}
@@ -36,6 +36,7 @@ export function makeRunFinishHandler(getCtx) {
36
36
  statusCommitRequireClean: p.statusCommitRequireClean,
37
37
  confirmStatusCommit: p.confirmStatusCommit,
38
38
  closeCommit: p.closeCommit,
39
+ noCloseCommit: p.noCloseCommit,
39
40
  closeUnstageOthers: p.closeUnstageOthers,
40
41
  quiet: p.quiet,
41
42
  });
@@ -22,6 +22,7 @@ export type FinishParsed = {
22
22
  statusCommitRequireClean: boolean;
23
23
  confirmStatusCommit: boolean;
24
24
  closeCommit: boolean;
25
+ noCloseCommit: boolean;
25
26
  closeUnstageOthers: boolean;
26
27
  quiet: boolean;
27
28
  };
@@ -1 +1 @@
1
- {"version":3,"file":"finish.spec.d.ts","sourceRoot":"","sources":["../../src/commands/finish.spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AASvD,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,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,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;IAClC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC,YAAY,CAsShD,CAAC"}
1
+ {"version":3,"file":"finish.spec.d.ts","sourceRoot":"","sources":["../../src/commands/finish.spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AASvD,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,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,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;IAClC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC,YAAY,CA6ThD,CAAC"}
@@ -145,6 +145,12 @@ export const finishSpec = {
145
145
  default: false,
146
146
  description: "After finishing, run a deterministic close commit for the task README (single-task only).",
147
147
  },
148
+ {
149
+ kind: "boolean",
150
+ name: "no-close-commit",
151
+ default: false,
152
+ description: "Disable the default deterministic close commit in direct mode (single-task only).",
153
+ },
148
154
  {
149
155
  kind: "boolean",
150
156
  name: "close-unstage-others",
@@ -228,12 +234,26 @@ export const finishSpec = {
228
234
  message: "--close-commit requires exactly one task id",
229
235
  });
230
236
  }
231
- if (raw.opts["close-commit"] === true &&
237
+ if (raw.opts["no-close-commit"] === true && taskIds.length !== 1) {
238
+ throw usageError({
239
+ spec: finishSpec,
240
+ command: "finish",
241
+ message: "--no-close-commit requires exactly one task id",
242
+ });
243
+ }
244
+ if (raw.opts["close-commit"] === true && raw.opts["no-close-commit"] === true) {
245
+ throw usageError({
246
+ spec: finishSpec,
247
+ command: "finish",
248
+ message: "--close-commit and --no-close-commit are mutually exclusive",
249
+ });
250
+ }
251
+ if ((raw.opts["close-commit"] === true || raw.opts["no-close-commit"] === true) &&
232
252
  (raw.opts["commit-from-comment"] === true || raw.opts["status-commit"] === true)) {
233
253
  throw usageError({
234
254
  spec: finishSpec,
235
255
  command: "finish",
236
- message: "--close-commit cannot be combined with --commit-from-comment/--status-commit",
256
+ message: "--close-commit/--no-close-commit cannot be combined with --commit-from-comment/--status-commit",
237
257
  });
238
258
  }
239
259
  if (raw.opts["close-unstage-others"] === true && raw.opts["close-commit"] !== true) {
@@ -279,6 +299,7 @@ export const finishSpec = {
279
299
  statusCommitRequireClean: raw.opts["status-commit-require-clean"] === true,
280
300
  confirmStatusCommit: raw.opts["confirm-status-commit"] === true,
281
301
  closeCommit: raw.opts["close-commit"] === true,
302
+ noCloseCommit: raw.opts["no-close-commit"] === true,
282
303
  closeUnstageOthers: raw.opts["close-unstage-others"] === true,
283
304
  quiet: raw.opts.quiet === true,
284
305
  }),
@@ -6,6 +6,7 @@ export type ReleaseApplyFlags = {
6
6
  remote: string;
7
7
  };
8
8
  export type ReleaseApplyParsed = ReleaseApplyFlags;
9
+ export declare function pushReleaseRefs(gitRoot: string, remote: string, tag: string): Promise<void>;
9
10
  export declare const releaseApplySpec: CommandSpec<ReleaseApplyParsed>;
10
11
  export declare const runReleaseApply: CommandHandler<ReleaseApplyParsed>;
11
12
  //# sourceMappingURL=apply.command.d.ts.map
@@ -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;AA4VnD,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,kBAAkB,CAiF5D,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,kBAAkB,CAoL9D,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;AA4VnD,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASjG;AAED,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,kBAAkB,CAiF5D,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,kBAAkB,CAgL9D,CAAC"}
@@ -285,6 +285,16 @@ async function writeReleaseApplyReport(gitRoot, report) {
285
285
  await writeFile(latestPath, text, "utf8");
286
286
  return reportPath;
287
287
  }
288
+ export async function pushReleaseRefs(gitRoot, remote, tag) {
289
+ await execFileAsync("git", ["push", "--no-verify", remote, "HEAD"], {
290
+ cwd: gitRoot,
291
+ env: gitEnv(),
292
+ });
293
+ await execFileAsync("git", ["push", "--no-verify", remote, tag], {
294
+ cwd: gitRoot,
295
+ env: gitEnv(),
296
+ });
297
+ }
288
298
  export const releaseApplySpec = {
289
299
  id: ["release", "apply"],
290
300
  group: "Release",
@@ -497,11 +507,7 @@ export const runReleaseApply = async (ctx, flags) => {
497
507
  await execFileAsync("git", ["tag", plan.nextTag], { cwd: gitRoot, env: gitEnv() });
498
508
  process.stdout.write(`Release tag created: ${plan.nextTag}\n`);
499
509
  if (flags.push) {
500
- await execFileAsync("git", ["push", flags.remote, "HEAD"], { cwd: gitRoot, env: gitEnv() });
501
- await execFileAsync("git", ["push", flags.remote, plan.nextTag], {
502
- cwd: gitRoot,
503
- env: gitEnv(),
504
- });
510
+ await pushReleaseRefs(gitRoot, flags.remote, plan.nextTag);
505
511
  process.stdout.write(`Pushed: ${flags.remote} HEAD + ${plan.nextTag}\n`);
506
512
  }
507
513
  else {
@@ -25,6 +25,7 @@ export declare function cmdFinish(opts: {
25
25
  statusCommitRequireClean: boolean;
26
26
  confirmStatusCommit: boolean;
27
27
  closeCommit?: boolean;
28
+ noCloseCommit?: boolean;
28
29
  closeUnstageOthers?: boolean;
29
30
  quiet: boolean;
30
31
  }): Promise<number>;
@@ -1 +1 @@
1
- {"version":3,"file":"finish.d.ts","sourceRoot":"","sources":["../../../src/commands/task/finish.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAoCnC,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,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,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;IAClC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsWlB"}
1
+ {"version":3,"file":"finish.d.ts","sourceRoot":"","sources":["../../../src/commands/task/finish.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAoCnC,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,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,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;IAClC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsXlB"}
@@ -51,18 +51,25 @@ export async function cmdFinish(opts) {
51
51
  message: "--commit-from-comment/--status-commit requires exactly one task id",
52
52
  });
53
53
  }
54
- if (opts.closeCommit && opts.taskIds.length !== 1) {
54
+ if ((opts.closeCommit || opts.noCloseCommit) && opts.taskIds.length !== 1) {
55
55
  throw new CliError({
56
56
  exitCode: 2,
57
57
  code: "E_USAGE",
58
- message: "--close-commit requires exactly one task id",
58
+ message: "--close-commit/--no-close-commit requires exactly one task id",
59
59
  });
60
60
  }
61
- if (opts.closeCommit && (opts.commitFromComment || opts.statusCommit)) {
61
+ if (opts.closeCommit && opts.noCloseCommit) {
62
62
  throw new CliError({
63
63
  exitCode: 2,
64
64
  code: "E_USAGE",
65
- message: "--close-commit cannot be combined with --commit-from-comment/--status-commit",
65
+ message: "--close-commit and --no-close-commit are mutually exclusive",
66
+ });
67
+ }
68
+ if ((opts.closeCommit || opts.noCloseCommit) && (opts.commitFromComment || opts.statusCommit)) {
69
+ throw new CliError({
70
+ exitCode: 2,
71
+ code: "E_USAGE",
72
+ message: "--close-commit/--no-close-commit cannot be combined with --commit-from-comment/--status-commit",
66
73
  });
67
74
  }
68
75
  const primaryTaskId = opts.taskIds[0] ?? "";
@@ -107,6 +114,12 @@ export async function cmdFinish(opts) {
107
114
  : await readHeadCommit(gitRoot);
108
115
  const useStore = backendIsLocalFileBackend(ctx);
109
116
  const store = useStore ? getTaskStore(ctx) : null;
117
+ const defaultDirectCloseCommit = ctx.config.workflow_mode === "direct" &&
118
+ useStore &&
119
+ opts.taskIds.length === 1 &&
120
+ !opts.commitFromComment &&
121
+ !statusCommitRequested;
122
+ const shouldCloseCommit = opts.closeCommit === true || (defaultDirectCloseCommit && opts.noCloseCommit !== true);
110
123
  const metaTaskId = opts.taskIds.length === 1 ? (opts.taskIds[0] ?? "") : "";
111
124
  const wantMeta = typeof opts.result === "string" || typeof opts.risk === "string" || opts.breaking === true;
112
125
  if (wantMeta && opts.taskIds.length !== 1) {
@@ -308,7 +321,7 @@ export async function cmdFinish(opts) {
308
321
  config: ctx.config,
309
322
  });
310
323
  }
311
- if (opts.closeCommit && primaryTaskId) {
324
+ if (shouldCloseCommit && primaryTaskId) {
312
325
  await cmdCommit({
313
326
  ctx,
314
327
  cwd: opts.cwd,
@@ -326,7 +339,7 @@ export async function cmdFinish(opts) {
326
339
  allowCI: false,
327
340
  requireClean: true,
328
341
  quiet: opts.quiet,
329
- closeUnstageOthers: opts.closeUnstageOthers === true,
342
+ closeUnstageOthers: opts.closeCommit === true && opts.closeUnstageOthers === true,
330
343
  closeCheckOnly: false,
331
344
  });
332
345
  }
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade.command.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEnE,MAAM,MAAM,aAAa,GAAG,YAAY,CAAC;AAEzC,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,aAAa,CA2JlD,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,aAAa,CACsB,CAAC"}
1
+ {"version":3,"file":"upgrade.command.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEnE,MAAM,MAAM,aAAa,GAAG,YAAY,CAAC;AAEzC,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,aAAa,CA8JlD,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,aAAa,CACsB,CAAC"}
@@ -4,19 +4,19 @@ export const upgradeSpec = {
4
4
  id: ["upgrade"],
5
5
  group: "Setup",
6
6
  summary: "Upgrade the local agentplane framework bundle in the repo.",
7
- description: "Upgrades the local agentplane framework bundle in the repo using a strict manifest of managed files. By default, upgrade generates an agent-assisted plan from the locally installed agentplane package assets (no network) and does not modify files. Use --auto to apply changes and create a dedicated upgrade commit. Use --remote to fetch a GitHub release bundle; network access is gated by config approvals.",
7
+ description: "Upgrades the local agentplane framework bundle in the repo using a strict manifest of managed files. By default, upgrade applies the bundled managed files from the locally installed agentplane package assets (no network) and creates a dedicated upgrade commit. Use --dry-run to preview changes without writing files, or --agent to generate a review plan instead of applying. Use --remote to fetch a GitHub release bundle; network access is gated by config approvals.",
8
8
  options: [
9
9
  {
10
10
  kind: "boolean",
11
11
  name: "agent",
12
12
  default: false,
13
- description: "Generate an agent-assisted upgrade plan (no files are modified). This is the default mode.",
13
+ description: "Generate an agent-assisted upgrade plan instead of applying managed files.",
14
14
  },
15
15
  {
16
16
  kind: "boolean",
17
17
  name: "auto",
18
18
  default: false,
19
- description: "Apply the upgrade automatically (writes managed files) and create a dedicated upgrade commit.",
19
+ description: "Apply the upgrade automatically (same behavior as the default mode; useful for explicit scripts).",
20
20
  },
21
21
  {
22
22
  kind: "boolean",
@@ -97,11 +97,15 @@ export const upgradeSpec = {
97
97
  examples: [
98
98
  {
99
99
  cmd: "agentplane upgrade",
100
- why: "Generate an agent-assisted plan using locally installed assets (no network).",
100
+ why: "Apply managed files from the installed CLI assets and create an upgrade commit.",
101
101
  },
102
102
  {
103
- cmd: "agentplane upgrade --auto",
104
- why: "Apply the upgrade automatically (writes managed files).",
103
+ cmd: "agentplane upgrade --dry-run",
104
+ why: "Preview managed-file changes without modifying the repo.",
105
+ },
106
+ {
107
+ cmd: "agentplane upgrade --agent",
108
+ why: "Generate an agent-assisted upgrade plan instead of applying files.",
105
109
  },
106
110
  {
107
111
  cmd: "agentplane upgrade --remote --tag v0.1.9 --dry-run",
@@ -115,7 +119,7 @@ export const upgradeSpec = {
115
119
  parse: (raw) => {
116
120
  const noBackup = raw.opts["no-backup"] === true;
117
121
  return {
118
- mode: raw.opts.auto === true ? "auto" : "agent",
122
+ mode: raw.opts.agent === true ? "agent" : "auto",
119
123
  remote: raw.opts.remote === true,
120
124
  allowTarball: raw.opts["allow-tarball"] === true,
121
125
  source: raw.opts.source,
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"AAqCA,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,oBAAoB,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAiGF,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,MAAM,GAAG;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CACnB,CAWA;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE;IACtD,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB,GACG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAqB1C;AAUD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CAgBT;AAmRD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,YAAY,CAAC;CACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6oBlB"}
1
+ {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"AAqCA,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,oBAAoB,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AA6GF,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,MAAM,GAAG;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CACnB,CAWA;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE;IACtD,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB,GACG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAqB1C;AAUD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CAgBT;AAmRD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,YAAY,CAAC;CACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CAupBlB"}
@@ -17,6 +17,17 @@ const DEFAULT_UPGRADE_ASSET = "agentplane-upgrade.tar.gz";
17
17
  const DEFAULT_UPGRADE_CHECKSUM_ASSET = "agentplane-upgrade.tar.gz.sha256";
18
18
  const UPGRADE_DOWNLOAD_TIMEOUT_MS = 60_000;
19
19
  const UPGRADE_RELEASE_METADATA_TIMEOUT_MS = 15_000;
20
+ function describeUpgradeSource(opts) {
21
+ if (opts.bundleLayout === "local_assets")
22
+ return "local installed agentplane CLI assets";
23
+ if (opts.bundleLayout === "repo_tarball")
24
+ return "GitHub repo tarball fallback";
25
+ if (opts.hasExplicitBundle)
26
+ return "explicit upgrade bundle";
27
+ if (opts.useRemote)
28
+ return "GitHub release bundle";
29
+ return "upgrade bundle";
30
+ }
20
31
  async function safeRemovePath(targetPath) {
21
32
  try {
22
33
  await rm(targetPath, { recursive: true, force: true });
@@ -537,6 +548,14 @@ export async function cmdUpgradeParsed(opts) {
537
548
  ? fileURLToPath(new URL("../../assets/framework.manifest.json", import.meta.url))
538
549
  : path.join(bundleRoot, "framework.manifest.json");
539
550
  const manifest = await loadFrameworkManifestFromPath(manifestPath);
551
+ const modeLabel = flags.dryRun ? "dry-run" : flags.mode === "agent" ? "review" : "apply";
552
+ process.stdout.write(`Upgrade source: ${describeUpgradeSource({
553
+ bundleLayout,
554
+ hasExplicitBundle: hasBundle,
555
+ useRemote,
556
+ })}\n` +
557
+ `Upgrade version: ${upgradeVersionLabel}\n` +
558
+ `Upgrade mode: ${modeLabel}\n`);
540
559
  const additions = [];
541
560
  const updates = [];
542
561
  const skipped = [];
@@ -777,7 +796,7 @@ export async function cmdUpgradeParsed(opts) {
777
796
  await mkdir(runDir, { recursive: true });
778
797
  const managedFiles = manifest.files.map((f) => f.path.replaceAll("\\", "/").trim());
779
798
  const planMd = `# agentplane upgrade plan (${runId})\n\n` +
780
- `Mode: agent-assisted (no files modified)\n\n` +
799
+ `Mode: agent-assisted review (no files modified)\n\n` +
781
800
  `## Summary\n\n` +
782
801
  `- additions: ${additions.length}\n` +
783
802
  `- updates: ${updates.length}\n` +
@@ -798,7 +817,7 @@ export async function cmdUpgradeParsed(opts) {
798
817
  `\n` +
799
818
  `## Next steps\n\n` +
800
819
  `1. Review the proposed changes list.\n` +
801
- `2. Apply changes manually or re-run with \`agentplane upgrade --auto\` to apply managed files.\n` +
820
+ `2. Apply changes manually or re-run without \`--agent\` to apply managed files.\n` +
802
821
  `3. Run \`agentplane doctor\` (or \`agentplane doctor --fix\`) and ensure checks pass.\n`;
803
822
  const constraintsMd = `# Upgrade constraints\n\n` +
804
823
  `This upgrade is restricted to framework-managed files only.\n\n` +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentplane",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Agent Plane CLI for task workflows, recipes, and project automation.",
5
5
  "keywords": [
6
6
  "agentplane",
@@ -55,7 +55,7 @@
55
55
  "prepublishOnly": "node ../../scripts/enforce-github-publish.mjs && npm run prepack"
56
56
  },
57
57
  "dependencies": {
58
- "@agentplaneorg/core": "0.3.1",
58
+ "@agentplaneorg/core": "0.3.2",
59
59
  "yauzl": "^2.10.0"
60
60
  },
61
61
  "devDependencies": {