agentplane 0.3.12 → 0.3.13

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 (180) hide show
  1. package/assets/RUNNER.md +1 -1
  2. package/assets/agents/ORCHESTRATOR.json +1 -1
  3. package/assets/codex-plugin/assets/header.png +0 -0
  4. package/assets/codex-plugin/assets/icon.svg +1 -0
  5. package/assets/codex-plugin/assets/logo.svg +1 -0
  6. package/assets/codex-plugin/skills/agentplane/SKILL.md +35 -0
  7. package/assets/policy/governance.md +4 -2
  8. package/assets/policy/incidents.md +3 -20
  9. package/assets/policy/workflow.release.md +5 -2
  10. package/dist/.build-manifest.json +203 -113
  11. package/dist/cli/exit-codes.d.ts.map +1 -1
  12. package/dist/cli/exit-codes.js +1 -0
  13. package/dist/cli/reason-codes.d.ts +1 -1
  14. package/dist/cli/reason-codes.d.ts.map +1 -1
  15. package/dist/cli/reason-codes.js +12 -0
  16. package/dist/cli/run-cli/command-catalog/core.d.ts +1 -1
  17. package/dist/cli/run-cli/command-catalog/core.d.ts.map +1 -1
  18. package/dist/cli/run-cli/command-catalog/core.js +16 -0
  19. package/dist/cli/run-cli/command-catalog/project.d.ts +1 -1
  20. package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -1
  21. package/dist/cli/run-cli/command-catalog/project.js +21 -3
  22. package/dist/cli/run-cli/command-catalog.d.ts +1 -1
  23. package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
  24. package/dist/cli/run-cli/commands/codex.d.ts +14 -0
  25. package/dist/cli/run-cli/commands/codex.d.ts.map +1 -0
  26. package/dist/cli/run-cli/commands/codex.js +100 -0
  27. package/dist/cli/run-cli/commands/core.d.ts +1 -0
  28. package/dist/cli/run-cli/commands/core.d.ts.map +1 -1
  29. package/dist/cli/run-cli/commands/core.js +1 -0
  30. package/dist/cli/run-cli/commands/init/recipes.d.ts +9 -1
  31. package/dist/cli/run-cli/commands/init/recipes.d.ts.map +1 -1
  32. package/dist/cli/run-cli/commands/init/recipes.js +32 -22
  33. package/dist/cli/run-cli/commands/init.d.ts.map +1 -1
  34. package/dist/cli/run-cli/commands/init.js +26 -21
  35. package/dist/cli/run-cli/error-guidance.js +20 -0
  36. package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
  37. package/dist/cli/run-cli.test-helpers.js +22 -19
  38. package/dist/commands/codex/plugin-install.d.ts +26 -0
  39. package/dist/commands/codex/plugin-install.d.ts.map +1 -0
  40. package/dist/commands/codex/plugin-install.js +209 -0
  41. package/dist/commands/pr/integrate/cmd.d.ts.map +1 -1
  42. package/dist/commands/pr/integrate/cmd.js +81 -5
  43. package/dist/commands/pr/integrate/internal/prepare.d.ts.map +1 -1
  44. package/dist/commands/pr/integrate/internal/prepare.js +38 -7
  45. package/dist/commands/pr/internal/auto-commit.d.ts.map +1 -1
  46. package/dist/commands/pr/internal/auto-commit.js +11 -6
  47. package/dist/commands/pr/internal/sync.d.ts.map +1 -1
  48. package/dist/commands/pr/internal/sync.js +5 -1
  49. package/dist/commands/pr/open.d.ts.map +1 -1
  50. package/dist/commands/pr/open.js +46 -8
  51. package/dist/commands/recipes/active.command.d.ts +7 -0
  52. package/dist/commands/recipes/active.command.d.ts.map +1 -0
  53. package/dist/commands/recipes/active.command.js +12 -0
  54. package/dist/commands/recipes/add.command.d.ts +8 -0
  55. package/dist/commands/recipes/add.command.d.ts.map +1 -0
  56. package/dist/commands/recipes/add.command.js +33 -0
  57. package/dist/commands/recipes/detach.command.d.ts +7 -0
  58. package/dist/commands/recipes/detach.command.d.ts.map +1 -0
  59. package/dist/commands/recipes/detach.command.js +19 -0
  60. package/dist/commands/recipes/disable.command.d.ts +7 -0
  61. package/dist/commands/recipes/disable.command.d.ts.map +1 -0
  62. package/dist/commands/recipes/disable.command.js +10 -0
  63. package/dist/commands/recipes/enable.command.d.ts +7 -0
  64. package/dist/commands/recipes/enable.command.d.ts.map +1 -0
  65. package/dist/commands/recipes/enable.command.js +10 -0
  66. package/dist/commands/recipes/explain-active.command.d.ts +5 -0
  67. package/dist/commands/recipes/explain-active.command.d.ts.map +1 -0
  68. package/dist/commands/recipes/explain-active.command.js +11 -0
  69. package/dist/commands/recipes/explain.command.d.ts.map +1 -1
  70. package/dist/commands/recipes/explain.command.js +4 -2
  71. package/dist/commands/recipes/impl/apply.d.ts.map +1 -1
  72. package/dist/commands/recipes/impl/apply.js +33 -14
  73. package/dist/commands/recipes/impl/commands/active.d.ts +6 -0
  74. package/dist/commands/recipes/impl/commands/active.d.ts.map +1 -0
  75. package/dist/commands/recipes/impl/commands/active.js +46 -0
  76. package/dist/commands/recipes/impl/commands/add.d.ts +7 -0
  77. package/dist/commands/recipes/impl/commands/add.d.ts.map +1 -0
  78. package/dist/commands/recipes/impl/commands/add.js +100 -0
  79. package/dist/commands/recipes/impl/commands/detach.d.ts +6 -0
  80. package/dist/commands/recipes/impl/commands/detach.d.ts.map +1 -0
  81. package/dist/commands/recipes/impl/commands/detach.js +85 -0
  82. package/dist/commands/recipes/impl/commands/disable.d.ts +6 -0
  83. package/dist/commands/recipes/impl/commands/disable.d.ts.map +1 -0
  84. package/dist/commands/recipes/impl/commands/disable.js +21 -0
  85. package/dist/commands/recipes/impl/commands/enable.d.ts +6 -0
  86. package/dist/commands/recipes/impl/commands/enable.d.ts.map +1 -0
  87. package/dist/commands/recipes/impl/commands/enable.js +39 -0
  88. package/dist/commands/recipes/impl/commands/explain-active.d.ts +5 -0
  89. package/dist/commands/recipes/impl/commands/explain-active.d.ts.map +1 -0
  90. package/dist/commands/recipes/impl/commands/explain-active.js +20 -0
  91. package/dist/commands/recipes/impl/commands/explain.d.ts.map +1 -1
  92. package/dist/commands/recipes/impl/commands/explain.js +40 -3
  93. package/dist/commands/recipes/impl/commands/info.d.ts.map +1 -1
  94. package/dist/commands/recipes/impl/commands/info.js +21 -8
  95. package/dist/commands/recipes/impl/commands/install.d.ts.map +1 -1
  96. package/dist/commands/recipes/impl/commands/install.js +32 -29
  97. package/dist/commands/recipes/impl/commands/list.d.ts.map +1 -1
  98. package/dist/commands/recipes/impl/commands/list.js +11 -11
  99. package/dist/commands/recipes/impl/commands/remove.d.ts.map +1 -1
  100. package/dist/commands/recipes/impl/commands/remove.js +5 -0
  101. package/dist/commands/recipes/impl/commands/update.d.ts +7 -0
  102. package/dist/commands/recipes/impl/commands/update.d.ts.map +1 -0
  103. package/dist/commands/recipes/impl/commands/update.js +93 -0
  104. package/dist/commands/recipes/impl/commands.d.ts +7 -0
  105. package/dist/commands/recipes/impl/commands.d.ts.map +1 -1
  106. package/dist/commands/recipes/impl/commands.js +7 -0
  107. package/dist/commands/recipes/impl/constants.d.ts +1 -14
  108. package/dist/commands/recipes/impl/constants.d.ts.map +1 -1
  109. package/dist/commands/recipes/impl/constants.js +1 -18
  110. package/dist/commands/recipes/impl/manifest.d.ts +2 -2
  111. package/dist/commands/recipes/impl/manifest.d.ts.map +1 -1
  112. package/dist/commands/recipes/impl/manifest.js +4 -226
  113. package/dist/commands/recipes/impl/overlay-project.d.ts +32 -0
  114. package/dist/commands/recipes/impl/overlay-project.d.ts.map +1 -0
  115. package/dist/commands/recipes/impl/overlay-project.js +282 -0
  116. package/dist/commands/recipes/impl/paths.d.ts +20 -2
  117. package/dist/commands/recipes/impl/paths.d.ts.map +1 -1
  118. package/dist/commands/recipes/impl/paths.js +23 -5
  119. package/dist/commands/recipes/impl/project-installed-recipes.d.ts +2 -4
  120. package/dist/commands/recipes/impl/project-installed-recipes.d.ts.map +1 -1
  121. package/dist/commands/recipes/impl/project-installed-recipes.js +30 -74
  122. package/dist/commands/recipes/impl/project-recipe-state.d.ts +18 -0
  123. package/dist/commands/recipes/impl/project-recipe-state.d.ts.map +1 -0
  124. package/dist/commands/recipes/impl/project-recipe-state.js +94 -0
  125. package/dist/commands/recipes/impl/project-registry.d.ts +20 -0
  126. package/dist/commands/recipes/impl/project-registry.d.ts.map +1 -0
  127. package/dist/commands/recipes/impl/project-registry.js +104 -0
  128. package/dist/commands/recipes/impl/resolver.d.ts.map +1 -1
  129. package/dist/commands/recipes/impl/resolver.js +5 -3
  130. package/dist/commands/recipes/impl/types.d.ts +1 -240
  131. package/dist/commands/recipes/impl/types.d.ts.map +1 -1
  132. package/dist/commands/recipes/info.command.js +2 -2
  133. package/dist/commands/recipes/install.spec.js +4 -4
  134. package/dist/commands/recipes/list.command.js +4 -4
  135. package/dist/commands/recipes/remove.command.js +2 -2
  136. package/dist/commands/recipes/update.command.d.ts +8 -0
  137. package/dist/commands/recipes/update.command.d.ts.map +1 -0
  138. package/dist/commands/recipes/update.command.js +35 -0
  139. package/dist/commands/recipes.d.ts +7 -4
  140. package/dist/commands/recipes.d.ts.map +1 -1
  141. package/dist/commands/recipes.js +6 -3
  142. package/dist/commands/recipes.test-helpers.d.ts +3 -3
  143. package/dist/commands/recipes.test-helpers.d.ts.map +1 -1
  144. package/dist/commands/recipes.test-helpers.js +105 -15
  145. package/dist/commands/scenario/execute.command.js +4 -4
  146. package/dist/commands/scenario/impl/commands.js +4 -4
  147. package/dist/commands/scenario/info.command.js +4 -4
  148. package/dist/commands/scenario/list.command.js +3 -3
  149. package/dist/commands/scenario/run.command.js +5 -5
  150. package/dist/commands/scenario/scenario.command.js +7 -7
  151. package/dist/commands/shared/task-handoff.d.ts +2 -1
  152. package/dist/commands/shared/task-handoff.d.ts.map +1 -1
  153. package/dist/commands/shared/task-handoff.js +15 -0
  154. package/dist/commands/task/handoff-show.command.d.ts.map +1 -1
  155. package/dist/commands/task/handoff-show.command.js +24 -0
  156. package/dist/runner/context/base-prompts.d.ts +2 -1
  157. package/dist/runner/context/base-prompts.d.ts.map +1 -1
  158. package/dist/runner/context/base-prompts.js +109 -13
  159. package/dist/runner/context/recipe-context.d.ts.map +1 -1
  160. package/dist/runner/context/recipe-context.js +40 -8
  161. package/dist/runner/types.d.ts +4 -0
  162. package/dist/runner/types.d.ts.map +1 -1
  163. package/dist/runner/usecases/task-run.d.ts.map +1 -1
  164. package/dist/runner/usecases/task-run.js +2 -1
  165. package/dist/runtime/behavior/resolve.d.ts +2 -1
  166. package/dist/runtime/behavior/resolve.d.ts.map +1 -1
  167. package/dist/runtime/behavior/resolve.js +25 -5
  168. package/dist/runtime/behavior/types.d.ts +1 -0
  169. package/dist/runtime/behavior/types.d.ts.map +1 -1
  170. package/dist/runtime/capabilities/recipe.d.ts +2 -1
  171. package/dist/runtime/capabilities/recipe.d.ts.map +1 -1
  172. package/dist/runtime/capabilities/recipe.js +88 -28
  173. package/dist/shared/errors.d.ts +1 -1
  174. package/dist/shared/errors.d.ts.map +1 -1
  175. package/dist/shared/runtime-source.d.ts.map +1 -1
  176. package/dist/shared/runtime-source.js +8 -3
  177. package/package.json +3 -2
  178. package/dist/cli/recipes-bundled.d.ts +0 -10
  179. package/dist/cli/recipes-bundled.d.ts.map +0 -1
  180. package/dist/cli/recipes-bundled.js +0 -36
@@ -308,7 +308,7 @@ export async function writeConfig(root, config) {
308
308
  export async function resetAgentplaneHomeRecipes() {
309
309
  if (!agentplaneHome)
310
310
  return;
311
- await rm(path.join(agentplaneHome, "recipes"), { recursive: true, force: true });
311
+ await rm(path.join(agentplaneHome, "recipes-store"), { recursive: true, force: true });
312
312
  await rm(path.join(agentplaneHome, "recipes.json"), { force: true });
313
313
  await rm(path.join(agentplaneHome, "recipes-index.json"), { force: true });
314
314
  }
@@ -349,8 +349,7 @@ export async function createRecipeArchive(opts) {
349
349
  {
350
350
  id: "RECIPE_SKILL",
351
351
  summary: "Recipe analysis skill",
352
- kind: "agent-skill",
353
- file: "skills/analysis.json",
352
+ file: "skills/analysis.md",
354
353
  },
355
354
  ],
356
355
  agents: [
@@ -361,7 +360,7 @@ export async function createRecipeArchive(opts) {
361
360
  summary: "Recipe agent",
362
361
  skills: ["RECIPE_SKILL"],
363
362
  tools: ["RECIPE_TOOL"],
364
- file: "agents/recipe.json",
363
+ file: "agents/recipe.md",
365
364
  },
366
365
  ],
367
366
  tools: [
@@ -395,18 +394,23 @@ export async function createRecipeArchive(opts) {
395
394
  await writeFile(path.join(recipeDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
396
395
  const agentsDir = path.join(recipeDir, "agents");
397
396
  await mkdir(agentsDir, { recursive: true });
398
- await writeFile(path.join(agentsDir, "recipe.json"), JSON.stringify({
399
- id: "RECIPE_AGENT",
400
- role: "Recipe agent",
401
- description: "Example agent installed from a recipe.",
402
- }, null, 2), "utf8");
397
+ await writeFile(path.join(agentsDir, "recipe.md"), [
398
+ "# Recipe Agent",
399
+ "",
400
+ "Role: executor",
401
+ "",
402
+ "Instructions:",
403
+ "- Use recipe local policy.",
404
+ "- Materialize the declared scenario artifacts.",
405
+ ].join("\n"), "utf8");
403
406
  const skillsDir = path.join(recipeDir, "skills");
404
407
  await mkdir(skillsDir, { recursive: true });
405
- await writeFile(path.join(skillsDir, "analysis.json"), JSON.stringify({
406
- id: "RECIPE_SKILL",
407
- summary: "Recipe analysis skill",
408
- kind: "agent-skill",
409
- }, null, 2), "utf8");
408
+ await writeFile(path.join(skillsDir, "analysis.md"), [
409
+ "# Recipe Skill",
410
+ "",
411
+ "- Inspect the generated bundle before acting.",
412
+ "- Keep recipe-owned artifacts inside the declared output paths.",
413
+ ].join("\n"), "utf8");
410
414
  const toolsDir = path.join(recipeDir, "tools");
411
415
  await mkdir(toolsDir, { recursive: true });
412
416
  await writeFile(path.join(toolsDir, "run.js"), [
@@ -496,8 +500,7 @@ export async function createUnsafeRecipeArchive(opts) {
496
500
  {
497
501
  id: "RECIPE_SKILL",
498
502
  summary: "Recipe skill",
499
- kind: "agent-skill",
500
- file: "skills/recipe.json",
503
+ file: "skills/recipe.md",
501
504
  },
502
505
  ],
503
506
  agents: [
@@ -508,7 +511,7 @@ export async function createUnsafeRecipeArchive(opts) {
508
511
  summary: "Recipe agent",
509
512
  skills: ["RECIPE_SKILL"],
510
513
  tools: ["RECIPE_TOOL"],
511
- file: "agents/recipe.json",
514
+ file: "agents/recipe.md",
512
515
  },
513
516
  ],
514
517
  tools: [
@@ -535,10 +538,10 @@ export async function createUnsafeRecipeArchive(opts) {
535
538
  await writeFile(path.join(recipeDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
536
539
  const agentsDir = path.join(recipeDir, "agents");
537
540
  await mkdir(agentsDir, { recursive: true });
538
- await writeFile(path.join(agentsDir, "recipe.json"), JSON.stringify({ id: "RECIPE_AGENT", role: "Recipe agent" }, null, 2), "utf8");
541
+ await writeFile(path.join(agentsDir, "recipe.md"), "# Recipe Agent\n\nFollow the unsafe archive validation path.\n", "utf8");
539
542
  const skillsDir = path.join(recipeDir, "skills");
540
543
  await mkdir(skillsDir, { recursive: true });
541
- await writeFile(path.join(skillsDir, "recipe.json"), JSON.stringify({ id: "RECIPE_SKILL" }), "utf8");
544
+ await writeFile(path.join(skillsDir, "recipe.md"), "# Recipe Skill\n\nInspect archive contents before materialization.\n", "utf8");
542
545
  const toolsDir = path.join(recipeDir, "tools");
543
546
  await mkdir(toolsDir, { recursive: true });
544
547
  await writeFile(path.join(toolsDir, "run.sh"), "#!/usr/bin/env bash\n", "utf8");
@@ -0,0 +1,26 @@
1
+ export declare const AGENTPLANE_CODEX_HOME_ENV = "AGENTPLANE_CODEX_HOME";
2
+ export type CodexPluginInstallScope = "user" | "repo";
3
+ export type CodexPluginInstallResult = {
4
+ scope: CodexPluginInstallScope;
5
+ installRoot: string;
6
+ pluginRoot: string;
7
+ manifestPath: string;
8
+ marketplacePath: string;
9
+ copiedAssets: string[];
10
+ };
11
+ type JsonObject = Record<string, unknown>;
12
+ export declare function buildCodexPluginManifest(version?: string): JsonObject;
13
+ export declare function resolveCodexInstallRoot(opts: {
14
+ scope: CodexPluginInstallScope;
15
+ repoRoot?: string;
16
+ env?: NodeJS.ProcessEnv;
17
+ }): string;
18
+ export declare function resolveCodexPluginRoot(installRoot: string): string;
19
+ export declare function resolveCodexMarketplacePath(installRoot: string): string;
20
+ export declare function installBundledCodexPlugin(opts: {
21
+ scope: CodexPluginInstallScope;
22
+ installRoot: string;
23
+ version?: string;
24
+ }): Promise<CodexPluginInstallResult>;
25
+ export {};
26
+ //# sourceMappingURL=plugin-install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-install.d.ts","sourceRoot":"","sources":["../../../src/commands/codex/plugin-install.ts"],"names":[],"mappings":"AAoCA,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AAEjE,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,MAAM,CAAC;AAEtD,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,uBAAuB,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AAEF,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAwG1C,wBAAgB,wBAAwB,CAAC,OAAO,SAAe,GAAG,UAAU,CA8B3E;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,KAAK,EAAE,uBAAuB,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB,GAAG,MAAM,CAiBT;AAED,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE;IACpD,KAAK,EAAE,uBAAuB,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAyCpC"}
@@ -0,0 +1,209 @@
1
+ import { copyFile, mkdir, readFile } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { CliError } from "../../shared/errors.js";
6
+ import { getVersion } from "../../meta/version.js";
7
+ import { writeJsonStableIfChanged, writeTextIfChanged } from "../../shared/write-if-changed.js";
8
+ const PLUGIN_NAME = "agentplane";
9
+ const DEFAULT_MARKETPLACE_NAME = "agentplane-local-marketplace";
10
+ const DEFAULT_MARKETPLACE_DISPLAY_NAME = "AgentPlane Local Plugins";
11
+ const ASSET_ROOT_URL = new URL("../../../assets/codex-plugin/", import.meta.url);
12
+ const TEXT_ASSETS = [
13
+ {
14
+ source: new URL("skills/agentplane/SKILL.md", ASSET_ROOT_URL),
15
+ relativePath: "skills/agentplane/SKILL.md",
16
+ },
17
+ ];
18
+ const BINARY_ASSETS = [
19
+ {
20
+ source: new URL("assets/icon.svg", ASSET_ROOT_URL),
21
+ relativePath: "assets/icon.svg",
22
+ },
23
+ {
24
+ source: new URL("assets/logo.svg", ASSET_ROOT_URL),
25
+ relativePath: "assets/logo.svg",
26
+ },
27
+ {
28
+ source: new URL("assets/header.png", ASSET_ROOT_URL),
29
+ relativePath: "assets/header.png",
30
+ },
31
+ ];
32
+ export const AGENTPLANE_CODEX_HOME_ENV = "AGENTPLANE_CODEX_HOME";
33
+ function isJsonObject(value) {
34
+ return typeof value === "object" && value !== null && !Array.isArray(value);
35
+ }
36
+ function invalidMarketplaceError(message) {
37
+ return new CliError({
38
+ exitCode: 3,
39
+ code: "E_VALIDATION",
40
+ message,
41
+ });
42
+ }
43
+ async function readTextIfExists(filePath) {
44
+ try {
45
+ return await readFile(filePath, "utf8");
46
+ }
47
+ catch (err) {
48
+ const code = err?.code;
49
+ if (code === "ENOENT")
50
+ return null;
51
+ throw err;
52
+ }
53
+ }
54
+ function defaultMarketplaceDocument() {
55
+ return {
56
+ name: DEFAULT_MARKETPLACE_NAME,
57
+ interface: {
58
+ displayName: DEFAULT_MARKETPLACE_DISPLAY_NAME,
59
+ },
60
+ plugins: [],
61
+ };
62
+ }
63
+ function parseMarketplaceDocument(text) {
64
+ if (text === null)
65
+ return defaultMarketplaceDocument();
66
+ let parsed;
67
+ try {
68
+ parsed = JSON.parse(text);
69
+ }
70
+ catch (err) {
71
+ throw invalidMarketplaceError(`Invalid Codex marketplace JSON: ${err instanceof Error ? err.message : "unknown parse error"}`);
72
+ }
73
+ if (!isJsonObject(parsed)) {
74
+ throw invalidMarketplaceError("Invalid Codex marketplace JSON: expected a top-level object.");
75
+ }
76
+ if ("plugins" in parsed && !Array.isArray(parsed.plugins)) {
77
+ throw invalidMarketplaceError("Invalid Codex marketplace JSON: `plugins` must be an array.");
78
+ }
79
+ if ("interface" in parsed && parsed.interface !== undefined && !isJsonObject(parsed.interface)) {
80
+ throw invalidMarketplaceError("Invalid Codex marketplace JSON: `interface` must be an object when present.");
81
+ }
82
+ return parsed;
83
+ }
84
+ function marketplaceEntry() {
85
+ return {
86
+ name: PLUGIN_NAME,
87
+ source: {
88
+ source: "local",
89
+ path: `./plugins/${PLUGIN_NAME}`,
90
+ },
91
+ policy: {
92
+ installation: "AVAILABLE",
93
+ authentication: "ON_INSTALL",
94
+ },
95
+ category: "Productivity",
96
+ };
97
+ }
98
+ function upsertMarketplaceDocument(text) {
99
+ const document = parseMarketplaceDocument(text);
100
+ const interfaceObject = isJsonObject(document.interface) ? { ...document.interface } : {};
101
+ if (typeof document.name !== "string" || document.name.trim().length === 0) {
102
+ document.name = DEFAULT_MARKETPLACE_NAME;
103
+ }
104
+ if (typeof interfaceObject.displayName !== "string" ||
105
+ interfaceObject.displayName.trim().length === 0) {
106
+ interfaceObject.displayName = DEFAULT_MARKETPLACE_DISPLAY_NAME;
107
+ }
108
+ const plugins = Array.isArray(document.plugins) ? document.plugins : [];
109
+ const nextEntry = marketplaceEntry();
110
+ const existingIndex = plugins.findIndex((entry) => isJsonObject(entry) && entry.name === PLUGIN_NAME);
111
+ if (existingIndex === -1) {
112
+ plugins.push(nextEntry);
113
+ }
114
+ else {
115
+ plugins.splice(existingIndex, 1, nextEntry);
116
+ }
117
+ return {
118
+ ...document,
119
+ interface: interfaceObject,
120
+ plugins,
121
+ };
122
+ }
123
+ export function buildCodexPluginManifest(version = getVersion()) {
124
+ return {
125
+ name: PLUGIN_NAME,
126
+ version,
127
+ description: "Bundle AgentPlane workflow guidance for the Codex plugins UI.",
128
+ homepage: "https://github.com/basilisk-labs/agentplane",
129
+ repository: "https://github.com/basilisk-labs/agentplane",
130
+ license: "MIT",
131
+ keywords: ["agentplane", "codex", "workflow", "tasks", "git"],
132
+ skills: "./skills/",
133
+ interface: {
134
+ displayName: "AgentPlane",
135
+ shortDescription: "Governed git-native workflow guidance for Codex",
136
+ longDescription: "Install AgentPlane into Codex through a local marketplace and give Codex explicit task, planning, verification, and branch_pr workflow guidance.",
137
+ developerName: "basilisk-labs",
138
+ category: "Productivity",
139
+ capabilities: ["Read", "Write"],
140
+ websiteURL: "https://github.com/basilisk-labs/agentplane",
141
+ defaultPrompt: [
142
+ "Use AgentPlane to initialize a governed workflow in this repository.",
143
+ "Use AgentPlane to create a task, approve the plan, and start work in branch_pr mode.",
144
+ "Use AgentPlane to verify the active task and record evidence before finish.",
145
+ ],
146
+ brandColor: "#111827",
147
+ composerIcon: "./assets/icon.svg",
148
+ logo: "./assets/logo.svg",
149
+ screenshots: ["./assets/header.png"],
150
+ },
151
+ };
152
+ }
153
+ export function resolveCodexInstallRoot(opts) {
154
+ if (opts.scope === "repo") {
155
+ const repoRoot = opts.repoRoot?.trim();
156
+ if (!repoRoot) {
157
+ throw new CliError({
158
+ exitCode: 2,
159
+ code: "E_USAGE",
160
+ message: "Repo scope requires a resolved repository root.",
161
+ });
162
+ }
163
+ return path.resolve(repoRoot);
164
+ }
165
+ const env = opts.env ?? process.env;
166
+ const overridden = env[AGENTPLANE_CODEX_HOME_ENV]?.trim();
167
+ if (overridden)
168
+ return path.resolve(overridden);
169
+ return os.homedir();
170
+ }
171
+ export function resolveCodexPluginRoot(installRoot) {
172
+ return path.join(installRoot, "plugins", PLUGIN_NAME);
173
+ }
174
+ export function resolveCodexMarketplacePath(installRoot) {
175
+ return path.join(installRoot, ".agents", "plugins", "marketplace.json");
176
+ }
177
+ export async function installBundledCodexPlugin(opts) {
178
+ const installRoot = path.resolve(opts.installRoot);
179
+ const pluginRoot = resolveCodexPluginRoot(installRoot);
180
+ const manifestPath = path.join(pluginRoot, ".codex-plugin", "plugin.json");
181
+ const marketplacePath = resolveCodexMarketplacePath(installRoot);
182
+ await mkdir(path.dirname(manifestPath), { recursive: true });
183
+ await mkdir(path.dirname(marketplacePath), { recursive: true });
184
+ await writeJsonStableIfChanged(manifestPath, buildCodexPluginManifest(opts.version ?? getVersion()));
185
+ const copiedAssets = [];
186
+ for (const asset of TEXT_ASSETS) {
187
+ const targetPath = path.join(pluginRoot, asset.relativePath);
188
+ await mkdir(path.dirname(targetPath), { recursive: true });
189
+ const contents = await readFile(asset.source, "utf8");
190
+ await writeTextIfChanged(targetPath, contents);
191
+ copiedAssets.push(targetPath);
192
+ }
193
+ for (const asset of BINARY_ASSETS) {
194
+ const targetPath = path.join(pluginRoot, asset.relativePath);
195
+ await mkdir(path.dirname(targetPath), { recursive: true });
196
+ await copyFile(fileURLToPath(asset.source), targetPath);
197
+ copiedAssets.push(targetPath);
198
+ }
199
+ const nextMarketplace = upsertMarketplaceDocument(await readTextIfExists(marketplacePath));
200
+ await writeJsonStableIfChanged(marketplacePath, nextMarketplace);
201
+ return {
202
+ scope: opts.scope,
203
+ installRoot,
204
+ pluginRoot,
205
+ manifestPath,
206
+ marketplacePath,
207
+ copiedAssets,
208
+ };
209
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"cmd.d.ts","sourceRoot":"","sources":["../../../../src/commands/pr/integrate/cmd.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAUnE,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACvC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA+OlB"}
1
+ {"version":3,"file":"cmd.d.ts","sourceRoot":"","sources":["../../../../src/commands/pr/integrate/cmd.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AA0EnE,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACvC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6QlB"}
@@ -2,11 +2,13 @@ import path from "node:path";
2
2
  import { mapBackendError } from "../../../cli/error-map.js";
3
3
  import { exitCodeForError } from "../../../cli/exit-codes.js";
4
4
  import { createCliEmitter } from "../../../cli/output.js";
5
+ import { withDiagnosticContext } from "../../../shared/diagnostics.js";
5
6
  import { CliError } from "../../../shared/errors.js";
6
7
  import { cleanupIntegratedBranch } from "./internal/cleanup.js";
7
8
  import { renderPostIntegrateBootstrapFailureGuidance, renderPostIntegrateBootstrapGuidance, shouldRecommendPostIntegrateBootstrap, } from "./internal/bootstrap-guidance.js";
8
9
  import { execFileAsync, gitEnv } from "../../shared/git.js";
9
10
  import { gitRevParse } from "../../shared/git-ops.js";
11
+ import { buildTaskHandoffArtifact, resolveTaskHandoffPaths, writeTaskHandoff, } from "../../shared/task-handoff.js";
10
12
  import { finalizeIntegrate } from "./internal/finalize.js";
11
13
  import { runMergeCommit, runRebaseFastForward, runSquashMerge } from "./internal/merge.js";
12
14
  import { maybeRunPreIntegrateBootstrap } from "./internal/pre-integrate-bootstrap.js";
@@ -14,6 +16,54 @@ import { maybeRunPostIntegrateBootstrap } from "./internal/post-integrate-bootst
14
16
  import { prepareIntegrate } from "./internal/prepare.js";
15
17
  import { resolveWorktreeForIntegrate } from "./internal/worktree.js";
16
18
  import { runVerifyCommands } from "./verify.js";
19
+ async function recordProtectedBaseIntegrateHandoff(opts) {
20
+ const paths = resolveTaskHandoffPaths({
21
+ git_root: opts.ctx.resolvedProject.gitRoot,
22
+ workflow_dir: opts.ctx.config.paths.workflow_dir,
23
+ task_id: opts.taskId,
24
+ });
25
+ const handoffShowCommand = `agentplane task handoff show ${opts.taskId}`;
26
+ const prLabel = typeof opts.prNumber === "number" && opts.prNumber > 0
27
+ ? `GitHub PR #${opts.prNumber}`
28
+ : `the GitHub PR for branch ${opts.branch}`;
29
+ const prUrl = opts.prUrl?.trim() ?? "";
30
+ const prMetaPath = path.join(opts.ctx.config.paths.workflow_dir, opts.taskId, "pr", "meta.json");
31
+ const taskReadmePath = path.join(opts.ctx.config.paths.workflow_dir, opts.taskId, "README.md");
32
+ await writeTaskHandoff({
33
+ paths,
34
+ handoff: buildTaskHandoffArtifact({
35
+ task_id: opts.taskId,
36
+ created_at: new Date().toISOString(),
37
+ from_role: "INTEGRATOR",
38
+ reason: `Protected base ${opts.base} requires GitHub pull-request merges.`,
39
+ note: prUrl.length > 0
40
+ ? `Merge ${prLabel}: ${prUrl}. After GitHub merge, wait for Task Hosted Close, then pull ${opts.base}.`
41
+ : `Merge ${prLabel} on GitHub. After GitHub merge, wait for Task Hosted Close, then pull ${opts.base}.`,
42
+ branch: opts.branch,
43
+ base_branch: opts.base,
44
+ head_sha: opts.branchHeadSha,
45
+ workspace_root: opts.ctx.resolvedProject.gitRoot,
46
+ pr_branch: opts.branch,
47
+ route: {
48
+ kind: "protected_base_integrate",
49
+ status: "awaiting_github_merge",
50
+ local_mutation: "not_performed",
51
+ finalize_via: "github_pr_merge_then_hosted_close",
52
+ pr_number: opts.prNumber,
53
+ pr_url: prUrl.length > 0 ? prUrl : null,
54
+ handoff_show_command: handoffShowCommand,
55
+ base_pull_command: "git pull --ff-only",
56
+ },
57
+ next_actions: [
58
+ handoffShowCommand,
59
+ prUrl.length > 0 ? `Merge ${prLabel}: ${prUrl}` : `Merge ${prLabel} on GitHub`,
60
+ `Wait for Task Hosted Close to finish`,
61
+ `git pull --ff-only`,
62
+ ],
63
+ evidence_paths: [taskReadmePath, prMetaPath],
64
+ }),
65
+ });
66
+ }
17
67
  export async function cmdIntegrate(opts) {
18
68
  let tempWorktreePath = null;
19
69
  let createdTempWorktree = false;
@@ -41,14 +91,40 @@ export async function cmdIntegrate(opts) {
41
91
  return 0;
42
92
  }
43
93
  if (protectedBaseRequiresPrMerge) {
44
- const prHint = typeof metaSource.pr_number === "number" && metaSource.pr_number > 0
45
- ? `GitHub PR #${metaSource.pr_number}`
46
- : `the GitHub PR for branch ${branch}`;
94
+ const prNumber = typeof metaSource.pr_number === "number" && metaSource.pr_number > 0
95
+ ? metaSource.pr_number
96
+ : null;
97
+ const prUrl = typeof metaSource.pr_url === "string" ? metaSource.pr_url : null;
98
+ const prHint = prNumber === null ? `the GitHub PR for branch ${branch}` : `GitHub PR #${prNumber}`;
99
+ await recordProtectedBaseIntegrateHandoff({
100
+ ctx: prepared.ctx,
101
+ taskId: task.id,
102
+ branch,
103
+ base,
104
+ branchHeadSha,
105
+ prNumber,
106
+ prUrl,
107
+ });
47
108
  throw new CliError({
48
- exitCode: exitCodeForError("E_GIT"),
49
- code: "E_GIT",
109
+ exitCode: exitCodeForError("E_HANDOFF"),
110
+ code: "E_HANDOFF",
50
111
  message: `Base branch ${base} requires GitHub pull-request merges; integrate will not mutate it locally. ` +
51
112
  `Merge ${prHint} on GitHub, let Task Hosted Close finish the closure tail, then pull ${base}.`,
113
+ context: withDiagnosticContext({
114
+ task_id: task.id,
115
+ branch,
116
+ base_branch: base,
117
+ reason_code: "protected_base_integrate_handoff",
118
+ }, {
119
+ state: `protected-base integrate routed to GitHub merge handoff for ${task.id}`,
120
+ likelyCause: `base branch ${base} is protected by a GitHub pull-request merge policy, so local integrate must stop before mutating ${base}`,
121
+ hint: "Inspect the persisted handoff artifact for the canonical finalize route, then merge the PR on GitHub and let Task Hosted Close finish the close tail.",
122
+ nextAction: {
123
+ command: `agentplane task handoff show ${task.id}`,
124
+ reason: "inspect the persisted protected-base finalize route before continuing",
125
+ reasonCode: "protected_base_integrate_handoff",
126
+ },
127
+ }),
52
128
  });
53
129
  }
54
130
  const wt = await resolveWorktreeForIntegrate({
@@ -1 +1 @@
1
- {"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../../../../../src/commands/pr/integrate/internal/prepare.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAUrE,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,iCAAiC,CAAC;AAWzC,OAAO,EAAgC,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAIvF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,cAAc,CAAC;IACpB,QAAQ,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAC5C,YAAY,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,EAAE,QAAQ,CAAC;IAEf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,4BAA4B,EAAE,OAAO,CAAC;IAEtC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IAEtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IAEb,aAAa,EAAE,MAAM,CAAC;IAEtB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;CACpB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgP7B"}
1
+ {"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../../../../../src/commands/pr/integrate/internal/prepare.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAWrE,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,iCAAiC,CAAC;AAWzC,OAAO,EAAgC,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAIvF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,cAAc,CAAC;IACpB,QAAQ,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAC5C,YAAY,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,EAAE,QAAQ,CAAC;IAEf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,4BAA4B,EAAE,OAAO,CAAC;IAEtC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IAEtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IAEb,aAAa,EAAE,MAAM,CAAC;IAEtB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;CACpB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAqR7B"}
@@ -4,6 +4,7 @@ import { resolveBaseBranch } from "@agentplaneorg/core";
4
4
  import { fileExists } from "../../../../cli/fs-utils.js";
5
5
  import { exitCodeForError } from "../../../../cli/exit-codes.js";
6
6
  import { unknownEntityMessage, workflowModeMessage } from "../../../../cli/output.js";
7
+ import { withDiagnosticContext } from "../../../../shared/diagnostics.js";
7
8
  import { CliError } from "../../../../shared/errors.js";
8
9
  import { ensureGitClean } from "../../../guard/index.js";
9
10
  import { gitDiffNames } from "../../../shared/git-diff.js";
@@ -52,13 +53,6 @@ export async function prepareIntegrate(opts) {
52
53
  });
53
54
  }
54
55
  const currentBranch = await gitCurrentBranch(resolved.gitRoot);
55
- if (currentBranch !== baseBranch) {
56
- throw new CliError({
57
- exitCode: exitCodeForError("E_GIT"),
58
- code: "E_GIT",
59
- message: `integrate must run on base branch ${baseBranch} (current: ${currentBranch})`,
60
- });
61
- }
62
56
  const { prDir, metaPath, diffstatPath, verifyLogPath } = await resolvePrPaths({
63
57
  ctx,
64
58
  cwd: opts.cwd,
@@ -92,6 +86,43 @@ export async function prepareIntegrate(opts) {
92
86
  message: unknownEntityMessage("branch", branch),
93
87
  });
94
88
  }
89
+ if (currentBranch !== baseBranch) {
90
+ if (currentBranch === branch) {
91
+ const baseWorktreePath = await findWorktreeForBranch(resolved.gitRoot, baseBranch);
92
+ const rerunCommand = baseWorktreePath && baseWorktreePath.trim().length > 0
93
+ ? `agentplane integrate ${opts.taskId} --branch ${branch} --root ${baseWorktreePath}`
94
+ : `git checkout ${baseBranch} && agentplane integrate ${opts.taskId} --branch ${branch}`;
95
+ throw new CliError({
96
+ exitCode: exitCodeForError("E_GIT"),
97
+ code: "E_GIT",
98
+ message: `integrate must run from the ${baseBranch} base checkout, not from task branch ${branch}. ` +
99
+ `Rerun it against the base checkout after leaving this task worktree.`,
100
+ context: withDiagnosticContext({
101
+ command: "integrate",
102
+ task_id: opts.taskId,
103
+ branch,
104
+ base_branch: baseBranch,
105
+ current_branch: currentBranch,
106
+ ...(baseWorktreePath ? { base_worktree_path: baseWorktreePath } : {}),
107
+ reason_code: "integrate_base_checkout_required",
108
+ }, {
109
+ state: `integrate was invoked from task branch ${branch} instead of base branch ${baseBranch}`,
110
+ likelyCause: "the operator is inside the task worktree, but branch_pr integrate is only valid from the registered base checkout",
111
+ hint: "Use the base checkout/worktree for the resolved base branch, not the task branch worktree, when running integrate.",
112
+ nextAction: {
113
+ command: rerunCommand,
114
+ reason: "rerun integrate against the base checkout route",
115
+ reasonCode: "integrate_base_checkout_required",
116
+ },
117
+ }),
118
+ });
119
+ }
120
+ throw new CliError({
121
+ exitCode: exitCodeForError("E_GIT"),
122
+ code: "E_GIT",
123
+ message: `integrate must run on base branch ${baseBranch} (current: ${currentBranch})`,
124
+ });
125
+ }
95
126
  await ensureCommittedPrArtifactsOnBranch({
96
127
  resolved,
97
128
  prDir,
@@ -1 +1 @@
1
- {"version":3,"file":"auto-commit.d.ts","sourceRoot":"","sources":["../../../../src/commands/pr/internal/auto-commit.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AA6BnE,wBAAsB,8BAA8B,CAAC,IAAI,EAAE;IACzD,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,OAAO,CAAC,CA8CnB"}
1
+ {"version":3,"file":"auto-commit.d.ts","sourceRoot":"","sources":["../../../../src/commands/pr/internal/auto-commit.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAiCnE,wBAAsB,8BAA8B,CAAC,IAAI,EAAE;IACzD,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,OAAO,CAAC,CA8CnB"}
@@ -7,8 +7,13 @@ import { gitCurrentBranch } from "../../shared/git-ops.js";
7
7
  function taskPrDirPrefix(workflowDir, taskId) {
8
8
  return `${toGitPath(path.join(workflowDir, taskId, "pr"))}/`;
9
9
  }
10
- function isTaskPrArtifactPath(opts) {
11
- return toGitPath(opts.relPath).startsWith(taskPrDirPrefix(opts.workflowDir, opts.taskId));
10
+ function taskReadmePath(workflowDir, taskId) {
11
+ return toGitPath(path.join(workflowDir, taskId, "README.md"));
12
+ }
13
+ function isTaskPacketPath(opts) {
14
+ const normalized = toGitPath(opts.relPath);
15
+ return (normalized === taskReadmePath(opts.workflowDir, opts.taskId) ||
16
+ normalized.startsWith(taskPrDirPrefix(opts.workflowDir, opts.taskId)));
12
17
  }
13
18
  async function readCachedPaths(gitRoot) {
14
19
  const { stdout } = await execFileAsync("git", ["diff", "--cached", "--name-only", "--relative"], {
@@ -31,22 +36,22 @@ export async function maybeAutoCommitTaskPrArtifacts(opts) {
31
36
  if (!currentBranch || currentBranch !== opts.branch.trim())
32
37
  return false;
33
38
  const changedPaths = await opts.ctx.git.statusChangedPaths();
34
- const prArtifactPaths = changedPaths.filter((relPath) => isTaskPrArtifactPath({
39
+ const taskPacketPaths = changedPaths.filter((relPath) => isTaskPacketPath({
35
40
  workflowDir: opts.ctx.config.paths.workflow_dir,
36
41
  taskId: opts.taskId,
37
42
  relPath,
38
43
  }));
39
- if (prArtifactPaths.length === 0)
44
+ if (taskPacketPaths.length === 0)
40
45
  return false;
41
46
  const cachedPaths = await readCachedPaths(opts.ctx.resolvedProject.gitRoot);
42
- if (cachedPaths.some((relPath) => !isTaskPrArtifactPath({
47
+ if (cachedPaths.some((relPath) => !isTaskPacketPath({
43
48
  workflowDir: opts.ctx.config.paths.workflow_dir,
44
49
  taskId: opts.taskId,
45
50
  relPath,
46
51
  }))) {
47
52
  return false;
48
53
  }
49
- await opts.ctx.git.stage(prArtifactPaths);
54
+ await opts.ctx.git.stage(taskPacketPaths);
50
55
  await opts.ctx.git.commit({
51
56
  message: taskPrArtifactRefreshMessage(opts.taskId),
52
57
  env: buildGitCommitEnv({
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../../src/commands/pr/internal/sync.ts"],"names":[],"mappings":"AAqBA,OAAO,EAML,KAAK,MAAM,EACZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,8BAA8B,CAAC;AAoFtC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,CAAC;AAEhD,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,iBAAiB,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC/D,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAySF,KAAK,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;AAmCpC,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAClD,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/B,GAAG,IAAI,CAAC,CAmDR;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,YAAY,CAAC;CAC3B,GAAG,OAAO,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B,CAAC,CA4TD"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../../src/commands/pr/internal/sync.ts"],"names":[],"mappings":"AAqBA,OAAO,EAML,KAAK,MAAM,EACZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,8BAA8B,CAAC;AAoFtC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,CAAC;AAEhD,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,iBAAiB,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC/D,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AA6SF,KAAK,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;AAmCpC,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAClD,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/B,GAAG,IAAI,CAAC,CAmDR;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,YAAY,CAAC;CAC3B,GAAG,OAAO,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B,CAAC,CA4TD"}
@@ -282,9 +282,13 @@ async function computePrDiffstat(opts) {
282
282
  gitRoot: opts.gitRoot,
283
283
  baseBranch: opts.baseBranch,
284
284
  });
285
+ const taskDir = path.dirname(opts.prDir);
285
286
  try {
286
287
  return await gitDiffStat(opts.gitRoot, diffBaseRef, opts.branch, {
287
- excludePaths: [path.relative(opts.gitRoot, opts.prDir)],
288
+ excludePaths: [
289
+ path.relative(opts.gitRoot, opts.prDir),
290
+ path.relative(opts.gitRoot, path.join(taskDir, "README.md")),
291
+ ],
288
292
  });
289
293
  }
290
294
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../../src/commands/pr/open.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAkBpF,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2ClB"}
1
+ {"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../../src/commands/pr/open.ts"],"names":[],"mappings":"AAQA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAuCpF,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgElB"}