agentplane 0.2.26 → 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.
Files changed (97) hide show
  1. package/README.md +3 -1
  2. package/assets/AGENTS.md +124 -526
  3. package/assets/agents/UPGRADER.json +10 -9
  4. package/assets/framework.manifest.json +112 -7
  5. package/assets/policy/check-routing.mjs +180 -0
  6. package/assets/policy/dod.code.md +25 -0
  7. package/assets/policy/dod.core.md +32 -0
  8. package/assets/policy/dod.docs.md +32 -0
  9. package/assets/policy/examples/migration-note.md +6 -0
  10. package/assets/policy/examples/pr-note.md +16 -0
  11. package/assets/policy/examples/unit-test-pattern.md +19 -0
  12. package/assets/policy/governance.md +37 -0
  13. package/assets/policy/incidents.md +36 -0
  14. package/assets/policy/security.must.md +7 -0
  15. package/assets/policy/workflow.branch_pr.md +34 -0
  16. package/assets/policy/workflow.direct.md +47 -0
  17. package/assets/policy/workflow.md +9 -0
  18. package/assets/policy/workflow.release.md +31 -0
  19. package/assets/policy/workflow.upgrade.md +20 -0
  20. package/bin/agentplane.js +88 -87
  21. package/bin/dist-guard.js +124 -0
  22. package/bin/runtime-context.d.ts +20 -0
  23. package/bin/runtime-context.js +81 -0
  24. package/dist/.build-manifest.json +5 -5
  25. package/dist/agents/agents-template.d.ts +7 -0
  26. package/dist/agents/agents-template.d.ts.map +1 -1
  27. package/dist/agents/agents-template.js +41 -2
  28. package/dist/cli/bootstrap-guide.d.ts +18 -0
  29. package/dist/cli/bootstrap-guide.d.ts.map +1 -0
  30. package/dist/cli/bootstrap-guide.js +132 -0
  31. package/dist/cli/command-guide.d.ts.map +1 -1
  32. package/dist/cli/command-guide.js +58 -183
  33. package/dist/cli/command-snippets.d.ts +3 -3
  34. package/dist/cli/command-snippets.js +3 -3
  35. package/dist/cli/run-cli/commands/core.js +3 -3
  36. package/dist/cli/run-cli/commands/ide.d.ts.map +1 -1
  37. package/dist/cli/run-cli/commands/ide.js +8 -3
  38. package/dist/cli/run-cli/commands/init/ui.d.ts.map +1 -1
  39. package/dist/cli/run-cli/commands/init/ui.js +1 -2
  40. package/dist/cli/run-cli/commands/init/write-agents.d.ts +2 -0
  41. package/dist/cli/run-cli/commands/init/write-agents.d.ts.map +1 -1
  42. package/dist/cli/run-cli/commands/init/write-agents.js +24 -5
  43. package/dist/cli/run-cli/commands/init/write-workflow.d.ts +5 -0
  44. package/dist/cli/run-cli/commands/init/write-workflow.d.ts.map +1 -1
  45. package/dist/cli/run-cli/commands/init/write-workflow.js +6 -0
  46. package/dist/cli/run-cli/commands/init.d.ts +2 -0
  47. package/dist/cli/run-cli/commands/init.d.ts.map +1 -1
  48. package/dist/cli/run-cli/commands/init.js +47 -19
  49. package/dist/cli/run-cli.d.ts.map +1 -1
  50. package/dist/cli/run-cli.js +125 -7
  51. package/dist/commands/doctor.run.d.ts.map +1 -1
  52. package/dist/commands/doctor.run.js +48 -6
  53. package/dist/commands/finish.run.d.ts.map +1 -1
  54. package/dist/commands/finish.run.js +1 -0
  55. package/dist/commands/finish.spec.d.ts +1 -0
  56. package/dist/commands/finish.spec.d.ts.map +1 -1
  57. package/dist/commands/finish.spec.js +23 -2
  58. package/dist/commands/release/apply.command.d.ts +1 -0
  59. package/dist/commands/release/apply.command.d.ts.map +1 -1
  60. package/dist/commands/release/apply.command.js +20 -9
  61. package/dist/commands/release/plan.command.d.ts.map +1 -1
  62. package/dist/commands/release/plan.command.js +9 -3
  63. package/dist/commands/task/add.d.ts.map +1 -1
  64. package/dist/commands/task/add.js +32 -0
  65. package/dist/commands/task/doc.command.d.ts.map +1 -1
  66. package/dist/commands/task/doc.command.js +1 -0
  67. package/dist/commands/task/finish.d.ts +1 -0
  68. package/dist/commands/task/finish.d.ts.map +1 -1
  69. package/dist/commands/task/finish.js +28 -7
  70. package/dist/commands/task/new.d.ts.map +1 -1
  71. package/dist/commands/task/new.js +41 -4
  72. package/dist/commands/task/plan.d.ts.map +1 -1
  73. package/dist/commands/task/plan.js +7 -1
  74. package/dist/commands/task/shared.d.ts +7 -0
  75. package/dist/commands/task/shared.d.ts.map +1 -1
  76. package/dist/commands/task/shared.js +37 -0
  77. package/dist/commands/task/start-ready.js +1 -1
  78. package/dist/commands/upgrade.command.d.ts.map +1 -1
  79. package/dist/commands/upgrade.command.js +11 -7
  80. package/dist/commands/upgrade.d.ts.map +1 -1
  81. package/dist/commands/upgrade.js +284 -296
  82. package/dist/commands/workflow-build.command.d.ts.map +1 -1
  83. package/dist/commands/workflow-build.command.js +7 -0
  84. package/dist/commands/workflow-playbook.command.d.ts.map +1 -1
  85. package/dist/commands/workflow-playbook.command.js +0 -1
  86. package/dist/shared/policy-gateway.d.ts +15 -0
  87. package/dist/shared/policy-gateway.d.ts.map +1 -0
  88. package/dist/shared/policy-gateway.js +49 -0
  89. package/dist/shared/protected-paths.d.ts.map +1 -1
  90. package/dist/shared/protected-paths.js +1 -0
  91. package/dist/shared/runtime-artifacts.d.ts +2 -2
  92. package/dist/shared/runtime-artifacts.d.ts.map +1 -1
  93. package/dist/shared/runtime-artifacts.js +4 -0
  94. package/dist/workflow-runtime/build.d.ts +1 -1
  95. package/dist/workflow-runtime/build.d.ts.map +1 -1
  96. package/dist/workflow-runtime/build.js +14 -2
  97. package/package.json +2 -2
@@ -0,0 +1,31 @@
1
+ # Workflow: release
2
+
3
+ Use this module when task touches release/version/publish flows.
4
+
5
+ ## Required sequence
6
+
7
+ 1. CHECKPOINT A: confirm clean tracked tree and approved scope.
8
+ 2. CHECKPOINT B: generate release plan and freeze version/tag target.
9
+ 3. Generate release notes with complete human-readable coverage of all task-level changes.
10
+ 4. Run release prepublish checks.
11
+ 5. CHECKPOINT C: apply release and push/tag only after all gates pass.
12
+ 6. Record release evidence (commands, outputs, resulting version/tag).
13
+
14
+ ## Command contract
15
+
16
+ ```bash
17
+ git status --short --untracked-files=no
18
+ agentplane task plan set <task-id> --text "Release plan: version=<v>, tag=<t>, scope=<...>" --updated-by <ROLE>
19
+ agentplane task plan approve <task-id> --by ORCHESTRATOR
20
+ agentplane release plan --patch
21
+ agentplane release apply --push --yes
22
+ agentplane verify <task-id> --ok|--rework --by <ROLE> --note "Release checks: ..."
23
+ agentplane finish <task-id> --author <ROLE> --body "Verified: release" --result "Release <v> published" --commit <git-rev> --close-commit
24
+ ```
25
+
26
+ ## Constraints
27
+
28
+ - MUST NOT perform irreversible release actions before explicit approval.
29
+ - MUST NOT skip parity/version checks.
30
+ - MUST NOT bypass required notes validation.
31
+ - MUST stop and request re-approval if release scope/tag/version changes.
@@ -0,0 +1,20 @@
1
+ # Workflow: upgrade
2
+
3
+ Use this module when task runs `agentplane upgrade` or touches `.agentplane/.upgrade/**`.
4
+
5
+ ## Required sequence
6
+
7
+ 1. Run upgrade command and capture run directory.
8
+ 2. Read upgrade review report:
9
+ - agent mode: `.agentplane/.upgrade/agent/<runId>/review.json`
10
+ - auto mode: `.agentplane/.upgrade/last-review.json`
11
+ 3. Apply upgrade as replace-all for managed files (`agentplane upgrade --auto`), excluding task data paths.
12
+ 4. For `.agentplane/policy/incidents.md`, keep existing local content and append incoming policy content (never replace non-empty local incidents file).
13
+ 5. Ensure the upgrade produced a dedicated upgrade commit with version in commit message.
14
+ 6. Verify policy/agent consistency and routing checks.
15
+ 7. Record run path and reviewed files in task notes.
16
+
17
+ ## Minimum verification
18
+
19
+ - `node .agentplane/policy/check-routing.mjs`
20
+ - `agentplane agents`
package/bin/agentplane.js CHANGED
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { execFileSync } from "node:child_process";
2
+ import { spawnSync } from "node:child_process";
3
3
  import path from "node:path";
4
- import { readFile, stat } from "node:fs/promises";
4
+ import { stat } from "node:fs/promises";
5
5
  import { fileURLToPath } from "node:url";
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,88 +35,65 @@ async function maybeWarnGlobalBinaryInRepoCheckout() {
36
35
  );
37
36
  }
38
37
 
39
- async function readJsonIfExists(p) {
40
- let raw = "";
41
- try {
42
- raw = await readFile(p, "utf8");
43
- } catch {
44
- return null;
45
- }
46
- try {
47
- return JSON.parse(raw);
48
- } catch {
49
- return null;
50
- }
38
+ function shouldUseGlobalBinaryInFramework() {
39
+ return (process.env.AGENTPLANE_USE_GLOBAL_IN_FRAMEWORK ?? "").trim() === "1";
51
40
  }
52
41
 
53
- function resolveGitHead(cwd) {
54
- try {
55
- return execFileSync("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8" }).trim() || null;
56
- } catch {
57
- return null;
58
- }
42
+ function isRepoLocalHandoffInvocation() {
43
+ return (process.env.AGENTPLANE_REPO_LOCAL_HANDOFF ?? "").trim() === "1";
59
44
  }
60
45
 
61
- function hasSrcChanges(cwd) {
62
- try {
63
- const out = execFileSync(
64
- "git",
65
- ["status", "--porcelain", "--untracked-files=all", "--", "src"],
66
- {
67
- cwd,
68
- encoding: "utf8",
69
- },
70
- );
71
- return out.trim().length > 0;
72
- } catch {
73
- return false;
74
- }
75
- }
46
+ function handoffToRepoLocalBinary(context) {
47
+ const repoBin = context.checkout?.repoBin;
48
+ if (!repoBin) return false;
76
49
 
77
- async function fileMtimeMs(p) {
78
- try {
79
- const s = await stat(p);
80
- if (!s.isFile()) return null;
81
- return s.mtimeMs;
82
- } catch {
83
- return null;
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;
84
67
  }
68
+
69
+ process.exitCode = result.status ?? (result.signal ? 1 : 0);
70
+ return true;
85
71
  }
86
72
 
87
- async function isPackageBuildFresh(packageRoot) {
88
- const manifestPath = path.join(packageRoot, "dist", ".build-manifest.json");
89
- const manifest = await readJsonIfExists(manifestPath);
90
- if (!manifest || manifest.schema_version !== 1) {
91
- return { ok: false, reason: "manifest_missing" };
92
- }
73
+ function maybeHandoffToRepoLocalBinary() {
74
+ if (shouldUseGlobalBinaryInFramework() || isRepoLocalHandoffInvocation()) return false;
93
75
 
94
- const currentHead = resolveGitHead(packageRoot);
95
- if (manifest.git_head && currentHead && manifest.git_head !== currentHead) {
96
- return { ok: false, reason: "git_head_changed" };
97
- }
76
+ const context = resolveFrameworkBinaryContext({
77
+ cwd: process.cwd(),
78
+ thisBin: fileURLToPath(import.meta.url),
79
+ });
80
+ if (!context.inFrameworkCheckout || context.isRepoLocalBinary) return false;
98
81
 
99
- if (hasSrcChanges(packageRoot)) {
100
- return { ok: false, reason: "src_dirty" };
101
- }
82
+ return handoffToRepoLocalBinary(context);
83
+ }
102
84
 
103
- const srcCliMtimeMs = await fileMtimeMs(path.join(packageRoot, "src", "cli.ts"));
104
- const srcIndexMtimeMs = await fileMtimeMs(path.join(packageRoot, "src", "index.ts"));
105
- if (
106
- typeof manifest.src_cli_mtime_ms === "number" &&
107
- typeof srcCliMtimeMs === "number" &&
108
- srcCliMtimeMs > manifest.src_cli_mtime_ms
109
- ) {
110
- return { ok: false, reason: "src_cli_newer_than_manifest" };
111
- }
112
- if (
113
- typeof manifest.src_index_mtime_ms === "number" &&
114
- typeof srcIndexMtimeMs === "number" &&
115
- srcIndexMtimeMs > manifest.src_index_mtime_ms
116
- ) {
117
- return { ok: false, reason: "src_index_newer_than_manifest" };
85
+ function isHooksRunCommitMsgInvocation(argv) {
86
+ const args = argv.slice(2).map((value) => String(value ?? "").trim());
87
+ for (let i = 0; i < args.length; i += 1) {
88
+ if (args[i] !== "hooks") continue;
89
+ return args[i + 1] === "run" && args[i + 2] === "commit-msg";
118
90
  }
91
+ return false;
92
+ }
119
93
 
120
- return { ok: true, reason: "fresh" };
94
+ function isPathInside(baseDir, targetPath) {
95
+ const rel = path.relative(path.resolve(baseDir), path.resolve(targetPath));
96
+ return rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel));
121
97
  }
122
98
 
123
99
  async function assertDistUpToDate() {
@@ -127,8 +103,7 @@ async function assertDistUpToDate() {
127
103
  if (!inRepo) return true;
128
104
 
129
105
  const allowStale = (process.env.AGENTPLANE_DEV_ALLOW_STALE_DIST ?? "").trim() === "1";
130
- const agentplaneDistDir = path.join(agentplaneRoot, "dist");
131
- if (!(await exists(agentplaneDistDir))) {
106
+ if (!(await distExists(agentplaneRoot))) {
132
107
  process.stderr.write(
133
108
  "error: agentplane dist is missing for this repo checkout.\n" +
134
109
  "Fix:\n" +
@@ -141,16 +116,40 @@ async function assertDistUpToDate() {
141
116
 
142
117
  const repoRoot = path.resolve(agentplaneRoot, "..", "..");
143
118
  const coreRoot = path.join(repoRoot, "packages", "core");
144
- const checks = [{ name: "agentplane", root: agentplaneRoot }];
145
- if (await exists(path.join(coreRoot, "src"))) checks.push({ name: "core", root: coreRoot });
119
+ const checks = [
120
+ {
121
+ name: "agentplane",
122
+ root: agentplaneRoot,
123
+ watchedPaths: ["src", "bin/agentplane.js", "bin/dist-guard.js"],
124
+ },
125
+ ];
126
+ if (await exists(path.join(coreRoot, "src")))
127
+ checks.push({ name: "core", root: coreRoot, watchedPaths: ["src"] });
146
128
 
147
129
  const staleReasons = [];
148
130
  for (const check of checks) {
149
- const result = await isPackageBuildFresh(check.root);
150
- if (!result.ok) staleReasons.push(`${check.name}:${result.reason}`);
131
+ const result = await isPackageBuildFresh(check.root, { watchedPaths: check.watchedPaths });
132
+ if (!result.ok) {
133
+ const detail =
134
+ Array.isArray(result.changedPaths) && result.changedPaths.length > 0
135
+ ? `(${result.changedPaths.slice(0, 5).join(", ")}${result.changedPaths.length > 5 ? ", ..." : ""})`
136
+ : "";
137
+ staleReasons.push(`${check.name}:${result.reason}${detail}`);
138
+ }
151
139
  }
152
140
 
153
141
  if (staleReasons.length > 0 && !allowStale) {
142
+ const runningInsideCheckout = isPathInside(repoRoot, process.cwd());
143
+ if (!runningInsideCheckout) {
144
+ process.stderr.write(
145
+ "warning: linked development binary has a stale build, but current working directory is outside the agentplane checkout.\n" +
146
+ "proceeding with existing dist output.\n" +
147
+ `detected: ${staleReasons.join(", ")}\n` +
148
+ "tip: rebuild (`bun run --filter=@agentplaneorg/core build && bun run --filter=agentplane build`) or reinstall from npm for stable global usage.\n",
149
+ );
150
+ return true;
151
+ }
152
+
154
153
  process.stderr.write(
155
154
  "error: refusing to run a stale repo build (manifest/git quick-check failed).\n" +
156
155
  "Fix:\n" +
@@ -166,6 +165,8 @@ async function assertDistUpToDate() {
166
165
  return true;
167
166
  }
168
167
 
169
- await maybeWarnGlobalBinaryInRepoCheckout();
170
- const ok = await assertDistUpToDate();
171
- 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,124 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import path from "node:path";
3
+ import { readFile, stat } from "node:fs/promises";
4
+
5
+ async function exists(p) {
6
+ try {
7
+ await stat(p);
8
+ return true;
9
+ } catch {
10
+ return false;
11
+ }
12
+ }
13
+
14
+ async function readJsonIfExists(p) {
15
+ let raw = "";
16
+ try {
17
+ raw = await readFile(p, "utf8");
18
+ } catch {
19
+ return null;
20
+ }
21
+ try {
22
+ return JSON.parse(raw);
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+
28
+ function resolveGitHead(cwd) {
29
+ try {
30
+ return execFileSync("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8" }).trim() || null;
31
+ } catch {
32
+ return null;
33
+ }
34
+ }
35
+
36
+ function listGitPaths(cwd, args) {
37
+ try {
38
+ const out = execFileSync("git", args, { cwd, encoding: "utf8" });
39
+ return out
40
+ .split(/\r?\n/u)
41
+ .map((line) => line.trim())
42
+ .filter(Boolean);
43
+ } catch {
44
+ return [];
45
+ }
46
+ }
47
+
48
+ function uniqueSorted(values) {
49
+ return [...new Set(values)].toSorted((a, b) => a.localeCompare(b));
50
+ }
51
+
52
+ function workingTreeChangedPaths(cwd, watchedPaths) {
53
+ const lines = listGitPaths(cwd, [
54
+ "status",
55
+ "--porcelain",
56
+ "--untracked-files=all",
57
+ "--",
58
+ ...watchedPaths,
59
+ ]);
60
+ return uniqueSorted(lines.map((line) => line.slice(3).trim()).filter(Boolean));
61
+ }
62
+
63
+ function committedChangedPathsSince(cwd, fromGitHead, watchedPaths) {
64
+ if (!fromGitHead) return [];
65
+ return uniqueSorted(
66
+ listGitPaths(cwd, ["diff", "--name-only", `${fromGitHead}..HEAD`, "--", ...watchedPaths]),
67
+ );
68
+ }
69
+
70
+ async function fileMtimeMs(p) {
71
+ try {
72
+ const s = await stat(p);
73
+ if (!s.isFile()) return null;
74
+ return s.mtimeMs;
75
+ } catch {
76
+ return null;
77
+ }
78
+ }
79
+
80
+ export async function isPackageBuildFresh(packageRoot, options = {}) {
81
+ const watchedPaths = options.watchedPaths ?? ["src"];
82
+ const manifestPath = path.join(packageRoot, "dist", ".build-manifest.json");
83
+ const manifest = await readJsonIfExists(manifestPath);
84
+ if (!manifest || manifest.schema_version !== 1) {
85
+ return { ok: false, reason: "manifest_missing", changedPaths: [] };
86
+ }
87
+
88
+ const currentHead = resolveGitHead(packageRoot);
89
+ const changedPaths = uniqueSorted([
90
+ ...committedChangedPathsSince(packageRoot, manifest.git_head, watchedPaths),
91
+ ...workingTreeChangedPaths(packageRoot, watchedPaths),
92
+ ]);
93
+
94
+ if (changedPaths.length > 0) {
95
+ return { ok: false, reason: "watched_paths_changed", changedPaths };
96
+ }
97
+
98
+ const srcCliMtimeMs = await fileMtimeMs(path.join(packageRoot, "src", "cli.ts"));
99
+ const srcIndexMtimeMs = await fileMtimeMs(path.join(packageRoot, "src", "index.ts"));
100
+ if (
101
+ typeof manifest.src_cli_mtime_ms === "number" &&
102
+ typeof srcCliMtimeMs === "number" &&
103
+ srcCliMtimeMs > manifest.src_cli_mtime_ms
104
+ ) {
105
+ return { ok: false, reason: "src_cli_newer_than_manifest", changedPaths: [] };
106
+ }
107
+ if (
108
+ typeof manifest.src_index_mtime_ms === "number" &&
109
+ typeof srcIndexMtimeMs === "number" &&
110
+ srcIndexMtimeMs > manifest.src_index_mtime_ms
111
+ ) {
112
+ return { ok: false, reason: "src_index_newer_than_manifest", changedPaths: [] };
113
+ }
114
+
115
+ if (manifest.git_head && currentHead && manifest.git_head !== currentHead) {
116
+ return { ok: true, reason: "fresh_after_non_runtime_head_change", changedPaths: [] };
117
+ }
118
+
119
+ return { ok: true, reason: "fresh", changedPaths: [] };
120
+ }
121
+
122
+ export async function distExists(packageRoot) {
123
+ return await exists(path.join(packageRoot, "dist"));
124
+ }
@@ -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-05T13:42:04.968Z",
5
- "git_head": "7fdf3f088d7d98748b9ef5db06f5bef3766b534d",
6
- "src_cli_mtime_ms": 1772718067546.3232,
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": 1772718124490.9443,
8
+ "dist_cli_mtime_ms": 1772904886214.584,
9
9
  "dist_index_mtime_ms": null,
10
- "tsbuildinfo_mtime_ms": 1772718124554.9443
10
+ "tsbuildinfo_mtime_ms": 1772904886278.5845
11
11
  }
@@ -1,10 +1,17 @@
1
+ import { type PolicyGatewayFlavor } from "../shared/policy-gateway.js";
1
2
  export type WorkflowMode = "direct" | "branch_pr";
2
3
  type AgentTemplate = {
3
4
  fileName: string;
4
5
  contents: string;
5
6
  };
7
+ export type PolicyTemplate = {
8
+ relativePath: string;
9
+ contents: string;
10
+ };
6
11
  export declare function loadAgentsTemplate(): Promise<string>;
7
12
  export declare function loadAgentTemplates(): Promise<AgentTemplate[]>;
13
+ export declare function loadPolicyTemplates(): Promise<PolicyTemplate[]>;
8
14
  export declare function filterAgentsByWorkflow(template: string, workflow: WorkflowMode): string;
15
+ export declare function loadPolicyGatewayTemplate(flavor: PolicyGatewayFlavor): Promise<string>;
9
16
  export {};
10
17
  //# sourceMappingURL=agents-template.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agents-template.d.ts","sourceRoot":"","sources":["../../src/agents/agents-template.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,WAAW,CAAC;AAElD,KAAK,aAAa,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAwC5D,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAG1D;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAanE;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,MAAM,CASvF"}
1
+ {"version":3,"file":"agents-template.d.ts","sourceRoot":"","sources":["../../src/agents/agents-template.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,6BAA6B,CAAC;AAUrC,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,WAAW,CAAC;AAElD,KAAK,aAAa,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAC5D,MAAM,MAAM,cAAc,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAwCxE,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAE1D;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAanE;AAsBD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAerE;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,MAAM,CASvF;AAED,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAI5F"}
@@ -1,8 +1,10 @@
1
1
  import { readdir, readFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
+ import { policyGatewayFileName, renderPolicyGatewayTemplateText, } from "../shared/policy-gateway.js";
4
5
  const AGENTS_TEMPLATE_URL = new URL("../../assets/AGENTS.md", import.meta.url);
5
6
  const AGENTS_DIR_URL = new URL("../../assets/agents/", import.meta.url);
7
+ const POLICY_DIR_URL = new URL("../../assets/policy/", import.meta.url);
6
8
  const HEADING_RE = /^(#+)\s+(.*)$/;
7
9
  function ensureTrailingNewline(text) {
8
10
  return text.endsWith("\n") ? text : `${text}\n`;
@@ -41,8 +43,7 @@ function removeSections(lines, titles) {
41
43
  return lines.filter((_line, index) => !shouldRemove.has(index));
42
44
  }
43
45
  export async function loadAgentsTemplate() {
44
- const text = await readFile(AGENTS_TEMPLATE_URL, "utf8");
45
- return ensureTrailingNewline(text.trimEnd());
46
+ return loadPolicyGatewayTemplate("codex");
46
47
  }
47
48
  export async function loadAgentTemplates() {
48
49
  const dirPath = fileURLToPath(AGENTS_DIR_URL);
@@ -56,6 +57,39 @@ export async function loadAgentTemplates() {
56
57
  }
57
58
  return templates;
58
59
  }
60
+ async function listFilesRecursive(dirPath, relPrefix = "") {
61
+ const entries = await readdir(dirPath, { withFileTypes: true });
62
+ const sorted = entries.toSorted((a, b) => a.name.localeCompare(b.name));
63
+ const files = [];
64
+ for (const entry of sorted) {
65
+ // Ignore editor/OS hidden metadata files.
66
+ if (entry.name.startsWith("."))
67
+ continue;
68
+ const absPath = path.join(dirPath, entry.name);
69
+ const relPath = relPrefix ? `${relPrefix}/${entry.name}` : entry.name;
70
+ if (entry.isDirectory()) {
71
+ files.push(...(await listFilesRecursive(absPath, relPath)));
72
+ continue;
73
+ }
74
+ if (entry.isFile())
75
+ files.push(relPath);
76
+ }
77
+ return files;
78
+ }
79
+ export async function loadPolicyTemplates() {
80
+ const dirPath = fileURLToPath(POLICY_DIR_URL);
81
+ const relFiles = await listFilesRecursive(dirPath);
82
+ const templates = [];
83
+ for (const relFile of relFiles) {
84
+ const filePath = path.join(dirPath, relFile);
85
+ const contents = await readFile(filePath, "utf8");
86
+ templates.push({
87
+ relativePath: relFile.replaceAll("\\", "/"),
88
+ contents: ensureTrailingNewline(contents.trimEnd()),
89
+ });
90
+ }
91
+ return templates;
92
+ }
59
93
  export function filterAgentsByWorkflow(template, workflow) {
60
94
  const lines = template.replaceAll("\r\n", "\n").split("\n");
61
95
  const removeTitles = workflow === "direct"
@@ -64,3 +98,8 @@ export function filterAgentsByWorkflow(template, workflow) {
64
98
  const filtered = removeSections(lines, removeTitles);
65
99
  return ensureTrailingNewline(filtered.join("\n").trimEnd());
66
100
  }
101
+ export async function loadPolicyGatewayTemplate(flavor) {
102
+ const text = await readFile(AGENTS_TEMPLATE_URL, "utf8");
103
+ const rendered = renderPolicyGatewayTemplateText(text, policyGatewayFileName(flavor));
104
+ return ensureTrailingNewline(rendered.trimEnd());
105
+ }
@@ -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"}