agentplane 0.3.4 → 0.3.6

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 (217) hide show
  1. package/README.md +103 -75
  2. package/assets/AGENTS.md +4 -2
  3. package/bin/dist-guard.js +13 -3
  4. package/bin/runtime-watch.d.ts +1 -0
  5. package/bin/runtime-watch.js +22 -5
  6. package/bin/stale-dist-policy.js +9 -2
  7. package/dist/.build-manifest.json +220 -790
  8. package/dist/adapters/task-backend/task-backend-adapter.d.ts +1 -1
  9. package/dist/adapters/task-backend/task-backend-adapter.d.ts.map +1 -1
  10. package/dist/adapters/task-backend/task-backend-adapter.js +5 -2
  11. package/dist/backends/task-backend/local-backend.d.ts +13 -0
  12. package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
  13. package/dist/backends/task-backend/local-backend.js +17 -0
  14. package/dist/backends/task-backend/redmine-backend.d.ts +18 -0
  15. package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
  16. package/dist/backends/task-backend/redmine-backend.js +35 -25
  17. package/dist/backends/task-backend/shared/types.d.ts +20 -0
  18. package/dist/backends/task-backend/shared/types.d.ts.map +1 -1
  19. package/dist/backends/task-backend/shared.d.ts +1 -1
  20. package/dist/backends/task-backend/shared.d.ts.map +1 -1
  21. package/dist/backends/task-backend.d.ts +1 -1
  22. package/dist/backends/task-backend.d.ts.map +1 -1
  23. package/dist/backends/task-backend.test-helpers.d.ts +4 -0
  24. package/dist/backends/task-backend.test-helpers.d.ts.map +1 -0
  25. package/dist/backends/task-backend.test-helpers.js +33 -0
  26. package/dist/cli/bootstrap-guide.d.ts.map +1 -1
  27. package/dist/cli/bootstrap-guide.js +1 -0
  28. package/dist/cli/command-guide.d.ts.map +1 -1
  29. package/dist/cli/command-guide.js +3 -2
  30. package/dist/cli/reason-codes.d.ts.map +1 -1
  31. package/dist/cli/reason-codes.js +30 -0
  32. package/dist/cli/run-cli/command-catalog/core.d.ts +3 -0
  33. package/dist/cli/run-cli/command-catalog/core.d.ts.map +1 -0
  34. package/dist/cli/run-cli/command-catalog/core.js +137 -0
  35. package/dist/cli/run-cli/command-catalog/lifecycle.d.ts +3 -0
  36. package/dist/cli/run-cli/command-catalog/lifecycle.d.ts.map +1 -0
  37. package/dist/cli/run-cli/command-catalog/lifecycle.js +52 -0
  38. package/dist/cli/run-cli/command-catalog/project.d.ts +3 -0
  39. package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -0
  40. package/dist/cli/run-cli/command-catalog/project.js +78 -0
  41. package/dist/cli/run-cli/command-catalog/shared.d.ts +19 -0
  42. package/dist/cli/run-cli/command-catalog/shared.d.ts.map +1 -0
  43. package/dist/cli/run-cli/command-catalog/shared.js +9 -0
  44. package/dist/cli/run-cli/command-catalog/task.d.ts +3 -0
  45. package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -0
  46. package/dist/cli/run-cli/command-catalog/task.js +85 -0
  47. package/dist/cli/run-cli/command-catalog.d.ts +3 -18
  48. package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
  49. package/dist/cli/run-cli/command-catalog.js +8 -337
  50. package/dist/cli/run-cli/commands/ide.d.ts.map +1 -1
  51. package/dist/cli/run-cli/commands/ide.js +64 -2
  52. package/dist/cli/run-cli/commands/init/ui.d.ts.map +1 -1
  53. package/dist/cli/run-cli/commands/init/ui.js +33 -13
  54. package/dist/cli/run-cli.core.pr-flow.test-helpers.d.ts +3 -0
  55. package/dist/cli/run-cli.core.pr-flow.test-helpers.d.ts.map +1 -0
  56. package/dist/cli/run-cli.core.pr-flow.test-helpers.js +41 -0
  57. package/dist/cli/run-cli.core.tasks.test-helpers.d.ts +2 -0
  58. package/dist/cli/run-cli.core.tasks.test-helpers.d.ts.map +1 -0
  59. package/dist/cli/run-cli.core.tasks.test-helpers.js +6 -0
  60. package/dist/cli/run-cli.test-helpers.d.ts +3 -0
  61. package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
  62. package/dist/cli/run-cli.test-helpers.js +138 -6
  63. package/dist/commands/commit.spec.d.ts.map +1 -1
  64. package/dist/commands/commit.spec.js +2 -2
  65. package/dist/commands/doctor/runtime.d.ts.map +1 -1
  66. package/dist/commands/doctor/runtime.js +3 -6
  67. package/dist/commands/doctor/workspace.d.ts +4 -1
  68. package/dist/commands/doctor/workspace.d.ts.map +1 -1
  69. package/dist/commands/doctor/workspace.js +87 -4
  70. package/dist/commands/doctor.run.d.ts.map +1 -1
  71. package/dist/commands/doctor.run.js +8 -1
  72. package/dist/commands/guard/commit.command.js +1 -1
  73. package/dist/commands/guard/impl/allow.d.ts +5 -0
  74. package/dist/commands/guard/impl/allow.d.ts.map +1 -1
  75. package/dist/commands/guard/impl/allow.js +15 -10
  76. package/dist/commands/guard/impl/commands.d.ts.map +1 -1
  77. package/dist/commands/guard/impl/commands.js +137 -18
  78. package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
  79. package/dist/commands/guard/impl/comment-commit.js +2 -0
  80. package/dist/commands/hooks/index.d.ts.map +1 -1
  81. package/dist/commands/hooks/index.js +8 -35
  82. package/dist/commands/recipes/impl/apply.d.ts +4 -0
  83. package/dist/commands/recipes/impl/apply.d.ts.map +1 -1
  84. package/dist/commands/recipes/impl/apply.js +34 -0
  85. package/dist/commands/recipes/impl/commands/explain.d.ts.map +1 -1
  86. package/dist/commands/recipes/impl/commands/explain.js +70 -11
  87. package/dist/commands/recipes/impl/commands/info.d.ts.map +1 -1
  88. package/dist/commands/recipes/impl/commands/info.js +24 -12
  89. package/dist/commands/recipes/impl/commands/install.d.ts.map +1 -1
  90. package/dist/commands/recipes/impl/commands/install.js +32 -36
  91. package/dist/commands/recipes/impl/commands/list.d.ts.map +1 -1
  92. package/dist/commands/recipes/impl/commands/list.js +7 -4
  93. package/dist/commands/recipes/impl/commands/remove.d.ts.map +1 -1
  94. package/dist/commands/recipes/impl/commands/remove.js +9 -11
  95. package/dist/commands/recipes/impl/constants.d.ts +2 -0
  96. package/dist/commands/recipes/impl/constants.d.ts.map +1 -1
  97. package/dist/commands/recipes/impl/constants.js +2 -0
  98. package/dist/commands/recipes/impl/manifest.d.ts.map +1 -1
  99. package/dist/commands/recipes/impl/manifest.js +219 -23
  100. package/dist/commands/recipes/impl/normalize.d.ts +3 -0
  101. package/dist/commands/recipes/impl/normalize.d.ts.map +1 -1
  102. package/dist/commands/recipes/impl/normalize.js +28 -24
  103. package/dist/commands/recipes/impl/paths.d.ts +9 -0
  104. package/dist/commands/recipes/impl/paths.d.ts.map +1 -1
  105. package/dist/commands/recipes/impl/paths.js +10 -1
  106. package/dist/commands/recipes/impl/project-installed-recipes.d.ts +7 -0
  107. package/dist/commands/recipes/impl/project-installed-recipes.d.ts.map +1 -0
  108. package/dist/commands/recipes/impl/project-installed-recipes.js +102 -0
  109. package/dist/commands/recipes/impl/resolver.d.ts +20 -0
  110. package/dist/commands/recipes/impl/resolver.d.ts.map +1 -0
  111. package/dist/commands/recipes/impl/resolver.js +220 -0
  112. package/dist/commands/recipes/impl/scenario.d.ts.map +1 -1
  113. package/dist/commands/recipes/impl/scenario.js +40 -11
  114. package/dist/commands/recipes/impl/types.d.ts +145 -16
  115. package/dist/commands/recipes/impl/types.d.ts.map +1 -1
  116. package/dist/commands/recipes/install.spec.d.ts.map +1 -1
  117. package/dist/commands/recipes/install.spec.js +3 -2
  118. package/dist/commands/recipes.d.ts +6 -4
  119. package/dist/commands/recipes.d.ts.map +1 -1
  120. package/dist/commands/recipes.js +5 -3
  121. package/dist/commands/recipes.test-helpers.d.ts +185 -0
  122. package/dist/commands/recipes.test-helpers.d.ts.map +1 -0
  123. package/dist/commands/recipes.test-helpers.js +339 -0
  124. package/dist/commands/scenario/impl/commands.d.ts.map +1 -1
  125. package/dist/commands/scenario/impl/commands.js +192 -336
  126. package/dist/commands/scenario/info.command.d.ts.map +1 -1
  127. package/dist/commands/scenario/info.command.js +7 -2
  128. package/dist/commands/scenario/list.command.js +2 -2
  129. package/dist/commands/scenario/run.command.d.ts.map +1 -1
  130. package/dist/commands/scenario/run.command.js +7 -2
  131. package/dist/commands/shared/git-context.d.ts +1 -0
  132. package/dist/commands/shared/git-context.d.ts.map +1 -1
  133. package/dist/commands/shared/git-context.js +4 -0
  134. package/dist/commands/shared/reconcile-check.d.ts.map +1 -1
  135. package/dist/commands/shared/reconcile-check.js +77 -2
  136. package/dist/commands/shared/task-backend.d.ts +5 -0
  137. package/dist/commands/shared/task-backend.d.ts.map +1 -1
  138. package/dist/commands/shared/task-backend.js +24 -0
  139. package/dist/commands/shared/task-store.d.ts +32 -1
  140. package/dist/commands/shared/task-store.d.ts.map +1 -1
  141. package/dist/commands/shared/task-store.js +166 -42
  142. package/dist/commands/task/block.d.ts.map +1 -1
  143. package/dist/commands/task/block.js +46 -29
  144. package/dist/commands/task/close-duplicate.d.ts.map +1 -1
  145. package/dist/commands/task/close-duplicate.js +12 -37
  146. package/dist/commands/task/close-noop.d.ts.map +1 -1
  147. package/dist/commands/task/close-noop.js +12 -30
  148. package/dist/commands/task/close-shared.d.ts +14 -0
  149. package/dist/commands/task/close-shared.d.ts.map +1 -0
  150. package/dist/commands/task/close-shared.js +76 -0
  151. package/dist/commands/task/comment.d.ts.map +1 -1
  152. package/dist/commands/task/comment.js +35 -17
  153. package/dist/commands/task/doc-set.command.d.ts +2 -1
  154. package/dist/commands/task/doc-set.command.d.ts.map +1 -1
  155. package/dist/commands/task/doc-set.command.js +36 -4
  156. package/dist/commands/task/doc-template.d.ts.map +1 -1
  157. package/dist/commands/task/doc-template.js +2 -7
  158. package/dist/commands/task/doc.command.js +1 -1
  159. package/dist/commands/task/doc.d.ts +2 -1
  160. package/dist/commands/task/doc.d.ts.map +1 -1
  161. package/dist/commands/task/doc.js +123 -71
  162. package/dist/commands/task/export.d.ts.map +1 -1
  163. package/dist/commands/task/export.js +4 -4
  164. package/dist/commands/task/finish.d.ts.map +1 -1
  165. package/dist/commands/task/finish.js +141 -78
  166. package/dist/commands/task/migrate-doc.d.ts.map +1 -1
  167. package/dist/commands/task/migrate-doc.js +15 -11
  168. package/dist/commands/task/plan-set.command.js +1 -1
  169. package/dist/commands/task/plan.command.d.ts +8 -0
  170. package/dist/commands/task/plan.command.d.ts.map +1 -0
  171. package/dist/commands/task/plan.command.js +37 -0
  172. package/dist/commands/task/plan.d.ts.map +1 -1
  173. package/dist/commands/task/plan.js +190 -93
  174. package/dist/commands/task/set-status.command.d.ts.map +1 -1
  175. package/dist/commands/task/set-status.command.js +1 -1
  176. package/dist/commands/task/set-status.d.ts.map +1 -1
  177. package/dist/commands/task/set-status.js +40 -3
  178. package/dist/commands/task/shared/docs.d.ts +1 -0
  179. package/dist/commands/task/shared/docs.d.ts.map +1 -1
  180. package/dist/commands/task/shared/docs.js +7 -0
  181. package/dist/commands/task/shared/transitions.d.ts +0 -2
  182. package/dist/commands/task/shared/transitions.d.ts.map +1 -1
  183. package/dist/commands/task/shared/transitions.js +0 -6
  184. package/dist/commands/task/shared.d.ts +2 -2
  185. package/dist/commands/task/shared.d.ts.map +1 -1
  186. package/dist/commands/task/shared.js +2 -2
  187. package/dist/commands/task/start.d.ts.map +1 -1
  188. package/dist/commands/task/start.js +88 -63
  189. package/dist/commands/task/task.command.d.ts +8 -0
  190. package/dist/commands/task/task.command.d.ts.map +1 -0
  191. package/dist/commands/task/task.command.js +71 -0
  192. package/dist/commands/task/verify-command-shared.d.ts +16 -0
  193. package/dist/commands/task/verify-command-shared.d.ts.map +1 -0
  194. package/dist/commands/task/verify-command-shared.js +53 -0
  195. package/dist/commands/task/verify-ok.command.d.ts +2 -6
  196. package/dist/commands/task/verify-ok.command.d.ts.map +1 -1
  197. package/dist/commands/task/verify-ok.command.js +8 -50
  198. package/dist/commands/task/verify-record.d.ts.map +1 -1
  199. package/dist/commands/task/verify-record.js +119 -140
  200. package/dist/commands/task/verify-rework.command.d.ts +2 -6
  201. package/dist/commands/task/verify-rework.command.d.ts.map +1 -1
  202. package/dist/commands/task/verify-rework.command.js +8 -50
  203. package/dist/commands/verify.spec.d.ts.map +1 -1
  204. package/dist/commands/verify.spec.js +3 -12
  205. package/dist/policy/rules/allowlist.d.ts.map +1 -1
  206. package/dist/policy/rules/allowlist.js +13 -4
  207. package/dist/policy/rules/protected-paths.d.ts.map +1 -1
  208. package/dist/policy/rules/protected-paths.js +6 -1
  209. package/dist/ports/task-backend-port.d.ts +1 -1
  210. package/dist/ports/task-backend-port.d.ts.map +1 -1
  211. package/dist/shared/agent-emoji.d.ts.map +1 -1
  212. package/dist/shared/protected-paths.d.ts +7 -0
  213. package/dist/shared/protected-paths.d.ts.map +1 -1
  214. package/dist/shared/protected-paths.js +26 -10
  215. package/dist/shared/repo-cli-version.d.ts.map +1 -1
  216. package/dist/shared/repo-cli-version.js +9 -3
  217. package/package.json +2 -2
@@ -1,15 +1,30 @@
1
1
  import { mapCoreError } from "../../../cli/error-map.js";
2
- import { successMessage } from "../../../cli/output.js";
2
+ import { infoMessage, successMessage } from "../../../cli/output.js";
3
+ import { stripAnsi } from "../../../cli/shared/ansi.js";
3
4
  import { withDiagnosticContext } from "../../../shared/diagnostics.js";
4
5
  import { CliError } from "../../../shared/errors.js";
5
6
  import { loadCommandContext } from "../../shared/task-backend.js";
6
7
  import { loadTaskFromContext } from "../../shared/task-backend.js";
7
8
  import { execFileAsync, gitEnv } from "../../shared/git.js";
8
9
  import { ensureReconciledBeforeMutation } from "../../shared/reconcile-check.js";
9
- import { suggestAllowPrefixes } from "./allow.js";
10
+ import { stageAllowlist, suggestAllowPrefixes } from "./allow.js";
10
11
  import { buildCloseCommitMessage, taskReadmePathForTask } from "./close-message.js";
11
12
  import { buildGitCommitEnv } from "./env.js";
12
13
  import { guardCommitCheck } from "./policy.js";
14
+ const COMMIT_FAILURE_SIGNAL_PATTERNS = [
15
+ /Code style issues found/i,
16
+ /Run Prettier with --write/i,
17
+ /\bESLint\b/i,
18
+ /\b[0-9]+\s+problems?\b/i,
19
+ /\berror\b/i,
20
+ /\bfailed\b/i,
21
+ /✖/,
22
+ ];
23
+ const FORMATTER_SIGNAL_PATTERNS = [
24
+ /Code style issues found/i,
25
+ /Run Prettier with --write/i,
26
+ ];
27
+ const ESLINT_SIGNAL_PATTERNS = [/\bESLint\b/i, /\b[0-9]+\s+problems?\b/i];
13
28
  function readText(value) {
14
29
  if (typeof value === "string")
15
30
  return value;
@@ -21,16 +36,103 @@ function summarizeOutput(raw) {
21
36
  const lines = raw
22
37
  .replaceAll("\r\n", "\n")
23
38
  .split("\n")
24
- .map((line) => line.trimEnd())
39
+ .map((line) => stripAnsi(line).trimEnd())
25
40
  .filter((line) => line.trim().length > 0)
26
41
  .map((line) => (line.length > 180 ? `${line.slice(0, 180)} [truncated]` : line));
27
42
  if (lines.length <= 12)
28
43
  return lines;
29
- const head = lines.slice(0, 6);
30
- const tail = lines.slice(-6);
31
- return [...head, `[${lines.length - 12} lines omitted]`, ...tail];
44
+ const selected = new Set();
45
+ for (let index = 0; index < Math.min(6, lines.length); index += 1) {
46
+ selected.add(index);
47
+ }
48
+ for (let index = Math.max(lines.length - 6, 0); index < lines.length; index += 1) {
49
+ selected.add(index);
50
+ }
51
+ for (const [index, line] of lines.entries()) {
52
+ if (selected.has(index))
53
+ continue;
54
+ if (COMMIT_FAILURE_SIGNAL_PATTERNS.some((pattern) => pattern.test(line))) {
55
+ selected.add(index);
56
+ }
57
+ }
58
+ const ordered = [...selected].toSorted((a, b) => a - b);
59
+ const summary = [];
60
+ let previous = -1;
61
+ for (const index of ordered) {
62
+ if (previous >= 0 && index - previous > 1) {
63
+ summary.push(`[${index - previous - 1} lines omitted]`);
64
+ }
65
+ summary.push(lines[index] ?? "");
66
+ previous = index;
67
+ }
68
+ return summary;
69
+ }
70
+ function detectCommitFailureSignal(output) {
71
+ if (FORMATTER_SIGNAL_PATTERNS.some((pattern) => pattern.test(output))) {
72
+ return "formatter";
73
+ }
74
+ if (ESLINT_SIGNAL_PATTERNS.some((pattern) => pattern.test(output))) {
75
+ return "eslint";
76
+ }
77
+ return null;
78
+ }
79
+ function commitFailureDiagnostic(phase, output) {
80
+ const signal = detectCommitFailureSignal(output);
81
+ if (signal === "formatter") {
82
+ return {
83
+ state: phase === "close_commit"
84
+ ? "git rejected the generated close commit"
85
+ : "git rejected the requested task-scoped commit",
86
+ likelyCause: phase === "close_commit"
87
+ ? "a formatting check in the pre-commit path rejected the deterministic close commit after the task README was staged"
88
+ : "a formatting check in the pre-commit path rejected the staged task-scoped commit",
89
+ nextAction: {
90
+ command: "bun run format",
91
+ reason: "apply formatter fixes before retrying the commit flow",
92
+ reasonCode: "git_pre_commit_format",
93
+ },
94
+ };
95
+ }
96
+ if (signal === "eslint") {
97
+ return {
98
+ state: phase === "close_commit"
99
+ ? "git rejected the generated close commit"
100
+ : "git rejected the requested task-scoped commit",
101
+ likelyCause: phase === "close_commit"
102
+ ? "a lint check in the pre-commit path rejected the deterministic close commit after the task README was staged"
103
+ : "a lint check in the pre-commit path rejected the staged task-scoped commit",
104
+ nextAction: {
105
+ command: "bun run lint:core",
106
+ reason: "rerun lint and fix the reported error before retrying the commit flow",
107
+ reasonCode: "git_pre_commit_lint",
108
+ },
109
+ };
110
+ }
111
+ if (phase === "close_commit") {
112
+ return {
113
+ state: "git rejected the generated close commit",
114
+ likelyCause: "a hook or commit policy blocked the deterministic task close commit after the task README was staged",
115
+ nextAction: {
116
+ command: "git status --short --untracked-files=no",
117
+ reason: "inspect the staged close-commit payload before fixing the hook or policy failure",
118
+ reasonCode: "git_close_commit_blocked",
119
+ },
120
+ };
121
+ }
122
+ return {
123
+ state: "git rejected the requested task-scoped commit",
124
+ likelyCause: "a hook or commit policy blocked the staged changes after guard validation passed",
125
+ nextAction: {
126
+ command: "git status --short --untracked-files=no",
127
+ reason: "inspect the staged task-scoped payload before fixing the hook or policy failure",
128
+ reasonCode: "git_task_commit_blocked",
129
+ },
130
+ };
32
131
  }
33
- function asCommitFailure(err) {
132
+ function hasExplicitCommitScope(opts) {
133
+ return opts.allow.some((prefix) => prefix.trim().length > 0) || opts.allowTasks;
134
+ }
135
+ function asCommitFailure(err, phase) {
34
136
  if (err instanceof Error) {
35
137
  const e = err;
36
138
  const cmd = typeof e.cmd === "string" ? e.cmd : "";
@@ -51,15 +153,7 @@ function asCommitFailure(err) {
51
153
  exitCode: 5,
52
154
  code: "E_GIT",
53
155
  message: lines.join("\n"),
54
- context: withDiagnosticContext({ command: "commit" }, {
55
- state: "git rejected the generated close commit",
56
- likelyCause: "a hook or commit policy blocked the deterministic task close commit after the task README was staged",
57
- nextAction: {
58
- command: "git status --short --untracked-files=no",
59
- reason: "inspect the staged close-commit payload before fixing the hook or policy failure",
60
- reasonCode: "git_close_commit_blocked",
61
- },
62
- }),
156
+ context: withDiagnosticContext({ command: "commit" }, commitFailureDiagnostic(phase, output)),
63
157
  });
64
158
  }
65
159
  return null;
@@ -235,6 +329,31 @@ export async function cmdCommit(opts) {
235
329
  });
236
330
  }
237
331
  await ensureReconciledBeforeMutation({ ctx, command: "commit" });
332
+ let autoStaged = [];
333
+ const staged = await ctx.git.statusStagedPaths();
334
+ if (staged.length === 0) {
335
+ if (!hasExplicitCommitScope(opts)) {
336
+ throw new CliError({
337
+ exitCode: 2,
338
+ code: "E_USAGE",
339
+ message: "No staged files and no commit allowlist. Pass --allow <path-prefix>, use --allow-tasks for active task artifacts, or stage files manually.",
340
+ });
341
+ }
342
+ autoStaged = await stageAllowlist({
343
+ ctx,
344
+ allow: opts.allow,
345
+ allowTasks: opts.allowTasks,
346
+ tasksPath: ctx.config.paths.tasks_path,
347
+ workflowDir: ctx.config.paths.workflow_dir,
348
+ taskId: opts.taskId,
349
+ allowTaskOnly: true,
350
+ emptyAllowMessage: "No staged files and no commit allowlist. Pass --allow <path-prefix>, use --allow-tasks for active task artifacts, or stage files manually.",
351
+ noMatchMessage: "No changed files matched the commit allowlist (adjust --allow / --allow-tasks or stage files manually).",
352
+ });
353
+ if (!opts.quiet) {
354
+ process.stdout.write(`${infoMessage(`commit auto-staged ${autoStaged.length} path(s) from allowlist`)}\n`);
355
+ }
356
+ }
238
357
  await guardCommitCheck({
239
358
  ctx,
240
359
  cwd: opts.cwd,
@@ -263,14 +382,14 @@ export async function cmdCommit(opts) {
263
382
  await ctx.git.commit({ message: opts.message, env });
264
383
  if (!opts.quiet) {
265
384
  const { hash, subject } = await ctx.git.headHashSubject();
266
- process.stdout.write(`${successMessage("committed", `${hash?.slice(0, 12) ?? ""} ${subject ?? ""}`.trim())}\n`);
385
+ process.stdout.write(`${successMessage("committed", `${hash?.slice(0, 12) ?? ""} ${subject ?? ""}`.trim(), autoStaged.length > 0 ? `staged=${autoStaged.join(", ")}` : undefined)}\n`);
267
386
  }
268
387
  return 0;
269
388
  }
270
389
  catch (err) {
271
390
  if (err instanceof CliError)
272
391
  throw err;
273
- const commitFailure = asCommitFailure(err);
392
+ const commitFailure = asCommitFailure(err, opts.close ? "close_commit" : "task_commit");
274
393
  if (commitFailure)
275
394
  throw commitFailure;
276
395
  throw mapCoreError(err, { command: "commit", root: opts.rootOverride ?? null });
@@ -1 +1 @@
1
- {"version":3,"file":"comment-commit.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/comment-commit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAQ/E,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAiEvF,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,gBAAgB,CAAC;CAC1B,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAyF/D"}
1
+ {"version":3,"file":"comment-commit.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/comment-commit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAQ/E,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAiEvF,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,gBAAgB,CAAC;CAC1B,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA2F/D"}
@@ -68,6 +68,8 @@ export async function commitFromComment(opts) {
68
68
  allow: allowPrefixes,
69
69
  allowTasks: opts.allowTasks,
70
70
  tasksPath: opts.config.paths.tasks_path,
71
+ workflowDir: opts.config.paths.workflow_dir,
72
+ taskId: opts.taskId,
71
73
  });
72
74
  const message = deriveCommitMessageFromComment({
73
75
  taskId: opts.taskId,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/hooks/index.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,UAAU,mDAAoD,CAAC;AA8G5E,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmClB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BlB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA8HlB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/hooks/index.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,UAAU,mDAAoD,CAAC;AA8G5E,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmClB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BlB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsGlB"}
@@ -5,13 +5,11 @@ import { evaluatePolicy } from "../../policy/evaluate.js";
5
5
  import { mapBackendError, mapCoreError } from "../../cli/error-map.js";
6
6
  import { fileExists } from "../../cli/fs-utils.js";
7
7
  import { infoMessage, successMessage } from "../../cli/output.js";
8
- import { resolveCommitEmojiForAgent } from "../../shared/agent-emoji.js";
9
8
  import { CliError } from "../../shared/errors.js";
10
9
  import { GitContext } from "../shared/git-context.js";
11
10
  import { throwIfPolicyDenied } from "../shared/policy-deny.js";
12
11
  import { gitCurrentBranch, gitRevParse } from "../shared/git-ops.js";
13
12
  import { isPathWithin } from "../shared/path.js";
14
- import { readDirectWorkLock } from "../../shared/direct-work-lock.js";
15
13
  const HOOK_MARKER = "agentplane-hook";
16
14
  const SHIM_MARKER = "agentplane-hook-shim";
17
15
  export const HOOK_NAMES = ["commit-msg", "pre-commit", "pre-push"];
@@ -201,40 +199,15 @@ export async function cmdHooksRun(opts) {
201
199
  const loaded = await loadConfig(resolved.agentplaneDir);
202
200
  const taskId = (process.env.AGENTPLANE_TASK_ID ?? "").trim();
203
201
  const statusTo = (process.env.AGENTPLANE_STATUS_TO ?? "").trim().toUpperCase();
204
- const agentsDirAbs = path.join(resolved.gitRoot, loaded.config.paths.agents_dir);
205
- let agentId = (process.env.AGENTPLANE_AGENT_ID ?? "").trim();
206
- if (!agentId && loaded.config.workflow_mode === "direct" && taskId) {
207
- const lock = await readDirectWorkLock(resolved.agentplaneDir);
208
- const lockAgent = lock?.agent?.trim() ?? "";
209
- if (lock?.task_id === taskId && lockAgent)
210
- agentId = lockAgent;
211
- }
212
202
  const emoji = subject.split(/\s+/).find(Boolean) ?? "";
213
- if (taskId) {
214
- if (statusTo === "DONE") {
215
- if (emoji !== "✅") {
216
- throw new CliError({
217
- exitCode: 5,
218
- code: "E_GIT",
219
- message: "Finish commits must use a checkmark emoji.\n" +
220
- "Expected:\n" +
221
- " ✅ <TASK_SUFFIX> <scope>: <summary>",
222
- });
223
- }
224
- }
225
- else if (agentId) {
226
- const expectedEmoji = await resolveCommitEmojiForAgent({ agentsDirAbs, agentId });
227
- if (emoji !== expectedEmoji) {
228
- throw new CliError({
229
- exitCode: 5,
230
- code: "E_GIT",
231
- message: "Commit emoji does not match the executor agent policy.\n" +
232
- `executor_agent=${agentId}\n` +
233
- "Expected:\n" +
234
- ` ${expectedEmoji} <TASK_SUFFIX> <scope>: <summary>`,
235
- });
236
- }
237
- }
203
+ if (taskId && statusTo === "DONE" && emoji !== "✅") {
204
+ throw new CliError({
205
+ exitCode: 5,
206
+ code: "E_GIT",
207
+ message: "Finish commits must use a checkmark emoji.\n" +
208
+ "Expected:\n" +
209
+ " <TASK_SUFFIX> <scope>: <summary>",
210
+ });
238
211
  }
239
212
  const res = evaluatePolicy({
240
213
  action: "hook_commit_msg",
@@ -3,6 +3,10 @@ export declare function moveRecipeDir(opts: {
3
3
  from: string;
4
4
  to: string;
5
5
  }): Promise<void>;
6
+ export declare function validateRecipeAssets(opts: {
7
+ manifest: RecipeManifest;
8
+ recipeDir: string;
9
+ }): Promise<void>;
6
10
  export declare function applyRecipeAgents(opts: {
7
11
  manifest: RecipeManifest;
8
12
  recipeDir: string;
@@ -1 +1 @@
1
- {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../../src/commands/recipes/impl/apply.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAErE,wBAAsB,aAAa,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAarF;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,kBAAkB,CAAC;CAChC,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDhB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BhB"}
1
+ {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../../src/commands/recipes/impl/apply.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAErE,wBAAsB,aAAa,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAarF;AAkBD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BhB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,kBAAkB,CAAC;CAChC,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDhB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BhB"}
@@ -24,6 +24,40 @@ export async function moveRecipeDir(opts) {
24
24
  throw err;
25
25
  }
26
26
  }
27
+ async function readRecipeJsonObject(recipeDir, relativePath, label) {
28
+ const sourcePath = path.join(recipeDir, relativePath);
29
+ if (!(await fileExists(sourcePath))) {
30
+ throw new Error(missingFileMessage(label, relativePath));
31
+ }
32
+ const raw = JSON.parse(await readFile(sourcePath, "utf8"));
33
+ if (!isRecord(raw)) {
34
+ throw new Error(invalidFieldMessage(label, "JSON object", relativePath));
35
+ }
36
+ }
37
+ export async function validateRecipeAssets(opts) {
38
+ for (const skill of opts.manifest.skills ?? []) {
39
+ await readRecipeJsonObject(opts.recipeDir, skill.file, "recipe skill file");
40
+ }
41
+ for (const agent of opts.manifest.agents ?? []) {
42
+ await readRecipeJsonObject(opts.recipeDir, agent.file, "recipe agent file");
43
+ }
44
+ for (const tool of opts.manifest.tools ?? []) {
45
+ const entrypointPath = path.join(opts.recipeDir, tool.entrypoint);
46
+ if (!(await fileExists(entrypointPath))) {
47
+ throw new Error(missingFileMessage("recipe tool entrypoint", tool.entrypoint));
48
+ }
49
+ }
50
+ for (const scenario of opts.manifest.scenarios ?? []) {
51
+ const sourcePath = path.join(opts.recipeDir, scenario.file);
52
+ if (!(await fileExists(sourcePath))) {
53
+ throw new Error(missingFileMessage("recipe scenario file", scenario.file));
54
+ }
55
+ const definition = await readScenarioDefinition(sourcePath);
56
+ if (definition.id !== scenario.id) {
57
+ throw new Error(invalidFieldMessage("recipe scenario file", `scenario.id=${scenario.id}`, scenario.file));
58
+ }
59
+ }
60
+ }
27
61
  export async function applyRecipeAgents(opts) {
28
62
  const agents = opts.manifest.agents ?? [];
29
63
  if (agents.length === 0)
@@ -1 +1 @@
1
- {"version":3,"file":"explain.d.ts","sourceRoot":"","sources":["../../../../../src/commands/recipes/impl/commands/explain.ts"],"names":[],"mappings":"AASA,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,MAAM,CAAC,CAmFlB"}
1
+ {"version":3,"file":"explain.d.ts","sourceRoot":"","sources":["../../../../../src/commands/recipes/impl/commands/explain.ts"],"names":[],"mappings":"AAWA,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,MAAM,CAAC,CAqIlB"}
@@ -1,13 +1,18 @@
1
+ import { resolveProject } from "@agentplaneorg/core";
1
2
  import { mapCoreError } from "../../../../cli/error-map.js";
2
3
  import { exitCodeForError } from "../../../../cli/exit-codes.js";
3
4
  import { CliError } from "../../../../shared/errors.js";
4
5
  import { collectRecipeScenarioDetails } from "../scenario.js";
5
6
  import { formatJsonBlock } from "../format.js";
6
- import { readInstalledRecipesFile } from "../installed-recipes.js";
7
- import { resolveInstalledRecipeDir, resolveInstalledRecipesPath } from "../paths.js";
7
+ import { readProjectInstalledRecipes } from "../project-installed-recipes.js";
8
+ import { resolveProjectInstalledRecipeDir } from "../paths.js";
8
9
  export async function cmdRecipeExplainParsed(opts) {
9
10
  try {
10
- const installed = await readInstalledRecipesFile(resolveInstalledRecipesPath());
11
+ const resolved = await resolveProject({
12
+ cwd: opts.cwd,
13
+ rootOverride: opts.rootOverride ?? null,
14
+ });
15
+ const installed = await readProjectInstalledRecipes(resolved);
11
16
  const entry = installed.recipes.find((recipe) => recipe.id === opts.id);
12
17
  if (!entry) {
13
18
  throw new CliError({
@@ -17,7 +22,7 @@ export async function cmdRecipeExplainParsed(opts) {
17
22
  });
18
23
  }
19
24
  const manifest = entry.manifest;
20
- const recipeDir = resolveInstalledRecipeDir(entry);
25
+ const recipeDir = resolveProjectInstalledRecipeDir(resolved, entry.id);
21
26
  const scenarioDetails = await collectRecipeScenarioDetails(recipeDir, manifest);
22
27
  process.stdout.write(`Recipe: ${manifest.id}@${manifest.version}\n`);
23
28
  process.stdout.write(`Name: ${manifest.name}\n`);
@@ -26,35 +31,59 @@ export async function cmdRecipeExplainParsed(opts) {
26
31
  if (manifest.tags && manifest.tags.length > 0) {
27
32
  process.stdout.write(`Tags: ${manifest.tags.join(", ")}\n`);
28
33
  }
34
+ if (manifest.compatibility) {
35
+ const payload = formatJsonBlock(manifest.compatibility, " ");
36
+ if (payload)
37
+ process.stdout.write(`Compatibility:\n${payload}\n`);
38
+ }
39
+ const skills = manifest.skills ?? [];
29
40
  const agents = manifest.agents ?? [];
30
41
  const tools = manifest.tools ?? [];
42
+ if (skills.length > 0) {
43
+ process.stdout.write("Skills:\n");
44
+ for (const skill of skills) {
45
+ process.stdout.write(` - ${skill.id} - ${skill.summary}\n`);
46
+ }
47
+ }
31
48
  if (agents.length > 0) {
32
49
  process.stdout.write("Agents:\n");
33
50
  for (const agent of agents) {
34
- const label = agent?.id ?? "unknown";
35
- const summary = agent?.summary ? ` - ${agent.summary}` : "";
36
- process.stdout.write(` - ${label}${summary}\n`);
51
+ process.stdout.write(` - ${agent.display_name} (${agent.id}) - ${agent.summary} [role=${agent.role}]\n`);
37
52
  }
38
53
  }
39
54
  if (tools.length > 0) {
40
55
  process.stdout.write("Tools:\n");
41
56
  for (const tool of tools) {
42
- const label = tool?.id ?? "unknown";
43
- const summary = tool?.summary ? ` - ${tool.summary}` : "";
44
- process.stdout.write(` - ${label}${summary}\n`);
57
+ process.stdout.write(` - ${tool.id} - ${tool.summary}\n`);
45
58
  }
46
59
  }
47
60
  if (scenarioDetails.length > 0) {
48
61
  process.stdout.write("Scenarios:\n");
49
62
  for (const scenario of scenarioDetails) {
63
+ const title = scenario.name ? `${scenario.name} (${scenario.id})` : scenario.id;
50
64
  const summary = scenario.summary ? ` - ${scenario.summary}` : "";
51
- process.stdout.write(` - ${scenario.id}${summary}\n`);
65
+ process.stdout.write(` - ${title}${summary}\n`);
52
66
  if (scenario.description) {
53
67
  process.stdout.write(` Description: ${scenario.description}\n`);
54
68
  }
55
69
  if (scenario.goal) {
56
70
  process.stdout.write(` Goal: ${scenario.goal}\n`);
57
71
  }
72
+ if (scenario.use_when && scenario.use_when.length > 0) {
73
+ const payload = formatJsonBlock(scenario.use_when, " ");
74
+ if (payload)
75
+ process.stdout.write(` Use when:\n${payload}\n`);
76
+ }
77
+ if (scenario.avoid_when && scenario.avoid_when.length > 0) {
78
+ const payload = formatJsonBlock(scenario.avoid_when, " ");
79
+ if (payload)
80
+ process.stdout.write(` Avoid when:\n${payload}\n`);
81
+ }
82
+ if (scenario.required_inputs && scenario.required_inputs.length > 0) {
83
+ const payload = formatJsonBlock(scenario.required_inputs, " ");
84
+ if (payload)
85
+ process.stdout.write(` Required inputs:\n${payload}\n`);
86
+ }
58
87
  if (scenario.inputs !== undefined) {
59
88
  const payload = formatJsonBlock(scenario.inputs, " ");
60
89
  if (payload)
@@ -65,6 +94,36 @@ export async function cmdRecipeExplainParsed(opts) {
65
94
  if (payload)
66
95
  process.stdout.write(` Outputs:\n${payload}\n`);
67
96
  }
97
+ if (scenario.permissions && scenario.permissions.length > 0) {
98
+ const payload = formatJsonBlock(scenario.permissions, " ");
99
+ if (payload)
100
+ process.stdout.write(` Permissions:\n${payload}\n`);
101
+ }
102
+ if (scenario.artifacts && scenario.artifacts.length > 0) {
103
+ const payload = formatJsonBlock(scenario.artifacts, " ");
104
+ if (payload)
105
+ process.stdout.write(` Artifacts:\n${payload}\n`);
106
+ }
107
+ if (scenario.agents_involved && scenario.agents_involved.length > 0) {
108
+ const payload = formatJsonBlock(scenario.agents_involved, " ");
109
+ if (payload)
110
+ process.stdout.write(` Agents involved:\n${payload}\n`);
111
+ }
112
+ if (scenario.skills_used && scenario.skills_used.length > 0) {
113
+ const payload = formatJsonBlock(scenario.skills_used, " ");
114
+ if (payload)
115
+ process.stdout.write(` Skills used:\n${payload}\n`);
116
+ }
117
+ if (scenario.tools_used && scenario.tools_used.length > 0) {
118
+ const payload = formatJsonBlock(scenario.tools_used, " ");
119
+ if (payload)
120
+ process.stdout.write(` Tools used:\n${payload}\n`);
121
+ }
122
+ if (scenario.run_profile) {
123
+ const payload = formatJsonBlock(scenario.run_profile, " ");
124
+ if (payload)
125
+ process.stdout.write(` Run profile:\n${payload}\n`);
126
+ }
68
127
  if (scenario.steps && scenario.steps.length > 0) {
69
128
  process.stdout.write(" Steps:\n");
70
129
  let stepIndex = 1;
@@ -1 +1 @@
1
- {"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../../../../src/commands/recipes/impl/commands/info.ts"],"names":[],"mappings":"AAOA,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,MAAM,CAAC,CAsDlB"}
1
+ {"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../../../../src/commands/recipes/impl/commands/info.ts"],"names":[],"mappings":"AASA,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,MAAM,CAAC,CAkElB"}
@@ -1,11 +1,16 @@
1
+ import { resolveProject } from "@agentplaneorg/core";
1
2
  import { mapCoreError } from "../../../../cli/error-map.js";
2
3
  import { exitCodeForError } from "../../../../cli/exit-codes.js";
3
4
  import { CliError } from "../../../../shared/errors.js";
4
- import { readInstalledRecipesFile } from "../installed-recipes.js";
5
- import { resolveInstalledRecipesPath } from "../paths.js";
5
+ import { formatJsonBlock } from "../format.js";
6
+ import { readProjectInstalledRecipes } from "../project-installed-recipes.js";
6
7
  export async function cmdRecipeInfoParsed(opts) {
7
8
  try {
8
- const installed = await readInstalledRecipesFile(resolveInstalledRecipesPath());
9
+ const resolved = await resolveProject({
10
+ cwd: opts.cwd,
11
+ rootOverride: opts.rootOverride ?? null,
12
+ });
13
+ const installed = await readProjectInstalledRecipes(resolved);
9
14
  const entry = installed.recipes.find((recipe) => recipe.id === opts.id);
10
15
  if (!entry) {
11
16
  throw new CliError({
@@ -22,31 +27,38 @@ export async function cmdRecipeInfoParsed(opts) {
22
27
  if (manifest.tags && manifest.tags.length > 0) {
23
28
  process.stdout.write(`Tags: ${manifest.tags.join(", ")}\n`);
24
29
  }
30
+ if (manifest.compatibility) {
31
+ const payload = formatJsonBlock(manifest.compatibility, " ");
32
+ if (payload)
33
+ process.stdout.write(`Compatibility:\n${payload}\n`);
34
+ }
35
+ const skills = manifest.skills ?? [];
25
36
  const agents = manifest.agents ?? [];
26
37
  const tools = manifest.tools ?? [];
27
38
  const scenarios = manifest.scenarios ?? [];
39
+ if (skills.length > 0) {
40
+ process.stdout.write("Skills:\n");
41
+ for (const skill of skills) {
42
+ process.stdout.write(` - ${skill.id} - ${skill.summary}\n`);
43
+ }
44
+ }
28
45
  if (agents.length > 0) {
29
46
  process.stdout.write("Agents:\n");
30
47
  for (const agent of agents) {
31
- const label = agent?.id ?? "unknown";
32
- const summary = agent?.summary ? ` - ${agent.summary}` : "";
33
- process.stdout.write(` - ${label}${summary}\n`);
48
+ const label = `${agent.display_name} (${agent.id})`;
49
+ process.stdout.write(` - ${label} - ${agent.summary}\n`);
34
50
  }
35
51
  }
36
52
  if (tools.length > 0) {
37
53
  process.stdout.write("Tools:\n");
38
54
  for (const tool of tools) {
39
- const label = tool?.id ?? "unknown";
40
- const summary = tool?.summary ? ` - ${tool.summary}` : "";
41
- process.stdout.write(` - ${label}${summary}\n`);
55
+ process.stdout.write(` - ${tool.id} - ${tool.summary}\n`);
42
56
  }
43
57
  }
44
58
  if (scenarios.length > 0) {
45
59
  process.stdout.write("Scenarios:\n");
46
60
  for (const scenario of scenarios) {
47
- const label = scenario?.id ?? "unknown";
48
- const summary = scenario?.summary ? ` - ${scenario.summary}` : "";
49
- process.stdout.write(` - ${label}${summary}\n`);
61
+ process.stdout.write(` - ${scenario.name} (${scenario.id}) - ${scenario.summary} [mode=${scenario.run_profile.mode}]\n`);
50
62
  }
51
63
  }
52
64
  return 0;
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../../../src/commands/recipes/impl/commands/install.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAM3E,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,kBAAkB,CAAC;IAC/B,GAAG,EAAE,OAAO,CAAC;CACd,GAAG,OAAO,CAAC,MAAM,CAAC,CA6NlB"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../../../src/commands/recipes/impl/commands/install.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAM3E,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,kBAAkB,CAAC;IAC/B,GAAG,EAAE,OAAO,CAAC;CACd,GAAG,OAAO,CAAC,MAAM,CAAC,CA4NlB"}