agentplane 0.3.3 → 0.3.5

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 (65) hide show
  1. package/assets/AGENTS.md +3 -3
  2. package/assets/agents/CODER.json +10 -7
  3. package/assets/agents/CREATOR.json +8 -6
  4. package/assets/agents/DOCS.json +8 -5
  5. package/assets/agents/INTEGRATOR.json +8 -5
  6. package/assets/agents/ORCHESTRATOR.json +7 -6
  7. package/assets/agents/PLANNER.json +8 -6
  8. package/assets/agents/REDMINE.json +6 -3
  9. package/assets/agents/REVIEWER.json +8 -6
  10. package/assets/agents/TESTER.json +6 -4
  11. package/assets/agents/UPDATER.json +6 -4
  12. package/assets/agents/UPGRADER.json +7 -6
  13. package/dist/.build-manifest.json +89 -74
  14. package/dist/adapters/task-backend/task-backend-adapter.d.ts +1 -1
  15. package/dist/adapters/task-backend/task-backend-adapter.d.ts.map +1 -1
  16. package/dist/adapters/task-backend/task-backend-adapter.js +5 -2
  17. package/dist/backends/task-backend/local-backend.d.ts +13 -0
  18. package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
  19. package/dist/backends/task-backend/local-backend.js +17 -0
  20. package/dist/backends/task-backend/redmine-backend.d.ts +18 -0
  21. package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
  22. package/dist/backends/task-backend/redmine-backend.js +35 -25
  23. package/dist/backends/task-backend/shared/types.d.ts +20 -0
  24. package/dist/backends/task-backend/shared/types.d.ts.map +1 -1
  25. package/dist/backends/task-backend/shared.d.ts +1 -1
  26. package/dist/backends/task-backend/shared.d.ts.map +1 -1
  27. package/dist/backends/task-backend.d.ts +1 -1
  28. package/dist/backends/task-backend.d.ts.map +1 -1
  29. package/dist/cli/bootstrap-guide.d.ts +1 -0
  30. package/dist/cli/bootstrap-guide.d.ts.map +1 -1
  31. package/dist/cli/bootstrap-guide.js +3 -2
  32. package/dist/cli/command-guide.d.ts +14 -1
  33. package/dist/cli/command-guide.d.ts.map +1 -1
  34. package/dist/cli/command-guide.js +50 -19
  35. package/dist/cli/run-cli/commands/core.d.ts.map +1 -1
  36. package/dist/cli/run-cli/commands/core.js +37 -29
  37. package/dist/cli/run-cli/commands/init/write-workflow.d.ts.map +1 -1
  38. package/dist/cli/run-cli/commands/init/write-workflow.js +6 -55
  39. package/dist/commands/doctor/workspace.d.ts +4 -1
  40. package/dist/commands/doctor/workspace.d.ts.map +1 -1
  41. package/dist/commands/doctor/workspace.js +87 -4
  42. package/dist/commands/doctor.run.d.ts.map +1 -1
  43. package/dist/commands/doctor.run.js +8 -1
  44. package/dist/commands/shared/git-context.d.ts +1 -0
  45. package/dist/commands/shared/git-context.d.ts.map +1 -1
  46. package/dist/commands/shared/git-context.js +4 -0
  47. package/dist/commands/shared/task-backend.d.ts +5 -0
  48. package/dist/commands/shared/task-backend.d.ts.map +1 -1
  49. package/dist/commands/shared/task-backend.js +24 -0
  50. package/dist/commands/task/export.d.ts.map +1 -1
  51. package/dist/commands/task/export.js +4 -4
  52. package/dist/commands/task/finish.d.ts.map +1 -1
  53. package/dist/commands/task/finish.js +3 -2
  54. package/dist/commands/task/migrate-doc.d.ts.map +1 -1
  55. package/dist/commands/task/migrate-doc.js +13 -3
  56. package/dist/commands/upgrade.d.ts.map +1 -1
  57. package/dist/commands/upgrade.js +22 -1
  58. package/dist/commands/workflow-build.command.d.ts.map +1 -1
  59. package/dist/commands/workflow-build.command.js +9 -15
  60. package/dist/ports/task-backend-port.d.ts +1 -1
  61. package/dist/ports/task-backend-port.d.ts.map +1 -1
  62. package/dist/shared/workflow-artifacts.d.ts +37 -0
  63. package/dist/shared/workflow-artifacts.d.ts.map +1 -0
  64. package/dist/shared/workflow-artifacts.js +97 -0
  65. package/package.json +2 -2
@@ -3,6 +3,8 @@ import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { renderDiagnosticFinding } from "../../shared/diagnostics.js";
5
5
  import { resolvePolicyGatewayForRepo } from "../../shared/policy-gateway.js";
6
+ import { GitContext } from "../shared/git-context.js";
7
+ import { listTaskProjection } from "../shared/task-backend.js";
6
8
  async function pathExists(absPath) {
7
9
  try {
8
10
  await fs.access(absPath);
@@ -44,7 +46,14 @@ async function listMissingManagedPolicyFiles(repoRoot) {
44
46
  }
45
47
  return missing.toSorted();
46
48
  }
47
- async function checkTaskReadmeMigrationState(repoRoot) {
49
+ function taskDataToSnapshot(task) {
50
+ return {
51
+ id: task.id,
52
+ status: task.status,
53
+ doc_version: task.doc_version,
54
+ };
55
+ }
56
+ async function readTaskDocSnapshotsFromTasksJson(repoRoot) {
48
57
  const tasksPath = path.join(repoRoot, ".agentplane", "tasks.json");
49
58
  let raw = "";
50
59
  try {
@@ -60,7 +69,22 @@ async function checkTaskReadmeMigrationState(repoRoot) {
60
69
  catch {
61
70
  return [];
62
71
  }
63
- const tasks = Array.isArray(parsed.tasks) ? parsed.tasks : [];
72
+ return Array.isArray(parsed.tasks) ? parsed.tasks : [];
73
+ }
74
+ async function readTaskDocSnapshotsFromProjection(ctx) {
75
+ if (!ctx)
76
+ return null;
77
+ try {
78
+ const tasks = await listTaskProjection(ctx);
79
+ if (tasks === null)
80
+ return null;
81
+ return tasks.map((task) => taskDataToSnapshot(task));
82
+ }
83
+ catch {
84
+ return null;
85
+ }
86
+ }
87
+ function buildTaskReadmeMigrationFindings(tasks) {
64
88
  if (tasks.length === 0)
65
89
  return [];
66
90
  const legacy = tasks.filter((task) => task.doc_version !== 3);
@@ -114,7 +138,66 @@ async function checkTaskReadmeMigrationState(repoRoot) {
114
138
  }),
115
139
  ];
116
140
  }
117
- export async function checkWorkspace(repoRoot) {
141
+ async function checkTaskReadmeMigrationState(repoRoot, ctx) {
142
+ const projectionTasks = await readTaskDocSnapshotsFromProjection(ctx);
143
+ const tasks = projectionTasks && projectionTasks.length > 0
144
+ ? projectionTasks
145
+ : await readTaskDocSnapshotsFromTasksJson(repoRoot);
146
+ return buildTaskReadmeMigrationFindings(tasks);
147
+ }
148
+ async function readUntrackedPaths(repoRoot, ctx) {
149
+ try {
150
+ const git = ctx?.git ?? new GitContext({ gitRoot: repoRoot });
151
+ return new Set(await git.statusUntrackedPaths());
152
+ }
153
+ catch {
154
+ return new Set();
155
+ }
156
+ }
157
+ async function checkDoneTaskReadmeArchiveDrift(repoRoot, ctx) {
158
+ const projectionTasks = await readTaskDocSnapshotsFromProjection(ctx);
159
+ const tasks = projectionTasks && projectionTasks.length > 0
160
+ ? projectionTasks
161
+ : await readTaskDocSnapshotsFromTasksJson(repoRoot);
162
+ if (tasks.length === 0)
163
+ return [];
164
+ const workflowDir = (ctx?.config.paths.workflow_dir ?? ".agentplane/tasks").replaceAll("\\", "/");
165
+ const untracked = await readUntrackedPaths(repoRoot, ctx);
166
+ if (untracked.size === 0)
167
+ return [];
168
+ const affected = tasks
169
+ .filter((task) => {
170
+ const status = typeof task.status === "string" ? task.status.trim().toUpperCase() : "";
171
+ const taskId = typeof task.id === "string" ? task.id.trim() : "";
172
+ if (status !== "DONE" || !taskId)
173
+ return false;
174
+ return untracked.has(`${workflowDir}/${taskId}/README.md`);
175
+ })
176
+ .map((task) => String(task.id))
177
+ .toSorted();
178
+ if (affected.length === 0)
179
+ return [];
180
+ const examples = affected.slice(0, 5).join(", ");
181
+ const stagedCommand = `git add ${affected
182
+ .map((taskId) => `${workflowDir}/${taskId}/README.md`)
183
+ .join(" ")}`;
184
+ return [
185
+ renderDiagnosticFinding({
186
+ severity: "WARN",
187
+ state: "DONE task archive README files exist on disk but are missing from the git index",
188
+ likelyCause: "task metadata reached DONE state, but the human-readable task README archive never landed in a tracked close commit",
189
+ nextAction: {
190
+ command: stagedCommand,
191
+ reason: "stage the missing archived task README files and commit them before continuing",
192
+ },
193
+ details: [
194
+ `Affected DONE tasks: ${affected.length}`,
195
+ examples ? `Examples: ${examples}` : "Examples unavailable.",
196
+ ],
197
+ }),
198
+ ];
199
+ }
200
+ export async function checkWorkspace(repoRoot, opts) {
118
201
  const problems = [];
119
202
  const requiredFiles = [path.join(repoRoot, ".agentplane", "config.json")];
120
203
  for (const filePath of requiredFiles) {
@@ -160,6 +243,6 @@ export async function checkWorkspace(repoRoot) {
160
243
  if (!hasJson) {
161
244
  problems.push("No agent profiles found in .agentplane/agents (*.json expected).");
162
245
  }
163
- problems.push(...(await checkTaskReadmeMigrationState(repoRoot)));
246
+ problems.push(...(await checkTaskReadmeMigrationState(repoRoot, opts?.ctx)), ...(await checkDoneTaskReadmeArchiveDrift(repoRoot, opts?.ctx)));
164
247
  return problems;
165
248
  }
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.run.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.run.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAYrD,eAAO,MAAM,SAAS,EAAE,cAAc,CAAC,YAAY,CAuDlD,CAAC"}
1
+ {"version":3,"file":"doctor.run.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.run.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAarD,eAAO,MAAM,SAAS,EAAE,cAAc,CAAC,YAAY,CA6DlD,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { loadConfig, resolveProject } from "@agentplaneorg/core";
2
2
  import { warnMessage, successMessage } from "../cli/output.js";
3
+ import { loadCommandContext } from "./shared/task-backend.js";
3
4
  import { checkDoneTaskCommitInvariants } from "./doctor/archive.js";
4
5
  import { safeFixGitignore, safeFixTaskIndex } from "./doctor/fixes.js";
5
6
  import { checkLayering } from "./doctor/layering.js";
@@ -11,9 +12,15 @@ export const runDoctor = async (ctx, p) => {
11
12
  const resolved = await resolveProject({ cwd: ctx.cwd, rootOverride: ctx.rootOverride ?? null });
12
13
  const repoRoot = resolved.gitRoot;
13
14
  const loadedConfig = await loadConfig(resolved.agentplaneDir);
15
+ const commandCtx = await loadCommandContext({
16
+ cwd: ctx.cwd,
17
+ rootOverride: ctx.rootOverride ?? null,
18
+ resolvedProject: resolved,
19
+ config: loadedConfig.config,
20
+ });
14
21
  const runChecks = async () => {
15
22
  let checks = [
16
- ...(await checkWorkspace(repoRoot)),
23
+ ...(await checkWorkspace(repoRoot, { ctx: commandCtx })),
17
24
  ...checkRuntimeSourceFacts(ctx.cwd, loadedConfig.config),
18
25
  ...(await checkDoneTaskCommitInvariants(repoRoot, { fullArchive: p.archiveFull })),
19
26
  ];
@@ -7,6 +7,7 @@ export declare class GitContext {
7
7
  private statusPorcelainZ;
8
8
  statusChangedPaths(): Promise<string[]>;
9
9
  statusStagedPaths(): Promise<string[]>;
10
+ statusUntrackedPaths(): Promise<string[]>;
10
11
  statusUnstagedTrackedPaths(): Promise<string[]>;
11
12
  headCommit(): Promise<string>;
12
13
  stage(paths: string[]): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"git-context.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/git-context.ts"],"names":[],"mappings":"AAyEA,qBAAa,UAAU;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,IAAI,CAGL;gBAEK,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE;YAIvB,gBAAgB;IAmBxB,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKvC,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKtC,0BAA0B,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKrD,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAWvB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWrC,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxF,iBAAiB,CAAC,IAAI,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWpE,eAAe,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAWpE"}
1
+ {"version":3,"file":"git-context.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/git-context.ts"],"names":[],"mappings":"AAyEA,qBAAa,UAAU;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,IAAI,CAGL;gBAEK,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE;YAIvB,gBAAgB;IAmBxB,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKvC,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKtC,oBAAoB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKzC,0BAA0B,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKrD,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAWvB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWrC,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxF,iBAAiB,CAAC,IAAI,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWpE,eAAe,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAWpE"}
@@ -87,6 +87,10 @@ export class GitContext {
87
87
  const status = await this.statusPorcelainZ();
88
88
  return status.stagedPaths;
89
89
  }
90
+ async statusUntrackedPaths() {
91
+ const status = await this.statusPorcelainZ();
92
+ return status.untrackedPaths;
93
+ }
90
94
  async statusUnstagedTrackedPaths() {
91
95
  const status = await this.statusPorcelainZ();
92
96
  return status.unstagedTrackedPaths;
@@ -44,4 +44,9 @@ export declare function loadBackendTask(opts: {
44
44
  task: TaskData;
45
45
  }>;
46
46
  export declare function listTasksMemo(ctx: CommandContext): Promise<TaskData[]>;
47
+ export declare function listTaskProjection(ctx: CommandContext): Promise<TaskData[] | null>;
48
+ export declare function exportTaskProjectionSnapshot(opts: {
49
+ ctx: CommandContext;
50
+ outputPath: string;
51
+ }): Promise<void>;
47
52
  //# sourceMappingURL=task-backend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"task-backend.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/task-backend.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG7E,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,eAAe,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IACzE,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC9D,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,UAAU,CAAC;IAEhB,IAAI,EAAE,WAAW,CAAC;IAGlB,QAAQ,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAC5C,OAAO,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;CACxC,CAAC;AASF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ3E;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA+B7E;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B,GAAG,OAAO,CAAC,cAAc,CAAC,CAmB1B;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAepB;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC;IACV,OAAO,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAC5C,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjC,IAAI,EAAE,QAAQ,CAAC;CAChB,CAAC,CAaD;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAG5E"}
1
+ {"version":3,"file":"task-backend.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/task-backend.ts"],"names":[],"mappings":"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"}
@@ -99,3 +99,27 @@ export async function listTasksMemo(ctx) {
99
99
  ctx.memo.taskList ??= ctx.taskBackend.listTasks();
100
100
  return await ctx.memo.taskList;
101
101
  }
102
+ export async function listTaskProjection(ctx) {
103
+ if (ctx.taskBackend.listProjectionTasks) {
104
+ return await ctx.taskBackend.listProjectionTasks();
105
+ }
106
+ if (ctx.taskBackend.capabilities.reads_from_projection_by_default) {
107
+ return await listTasksMemo(ctx);
108
+ }
109
+ return null;
110
+ }
111
+ export async function exportTaskProjectionSnapshot(opts) {
112
+ if (opts.ctx.taskBackend.exportProjectionSnapshot) {
113
+ await opts.ctx.taskBackend.exportProjectionSnapshot(opts.outputPath);
114
+ return;
115
+ }
116
+ if (opts.ctx.taskBackend.exportTasksJson) {
117
+ await opts.ctx.taskBackend.exportTasksJson(opts.outputPath);
118
+ return;
119
+ }
120
+ throw new CliError({
121
+ exitCode: 3,
122
+ code: "E_VALIDATION",
123
+ message: "Configured backend does not support exporting a task snapshot",
124
+ });
125
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../src/commands/task/export.ts"],"names":[],"mappings":"AAKA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEpF,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBlB"}
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../src/commands/task/export.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAEnC,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBlB"}
@@ -2,20 +2,20 @@ import path from "node:path";
2
2
  import { mapBackendError } from "../../cli/error-map.js";
3
3
  import { backendNotSupportedMessage } from "../../cli/output.js";
4
4
  import { CliError } from "../../shared/errors.js";
5
- import { loadCommandContext } from "../shared/task-backend.js";
5
+ import { exportTaskProjectionSnapshot, loadCommandContext, } from "../shared/task-backend.js";
6
6
  export async function cmdTaskExport(opts) {
7
7
  try {
8
8
  const ctx = opts.ctx ??
9
9
  (await loadCommandContext({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null }));
10
10
  const outPath = path.join(ctx.resolvedProject.gitRoot, ctx.config.paths.tasks_path);
11
- if (!ctx.taskBackend.exportTasksJson) {
11
+ if (!ctx.taskBackend.exportProjectionSnapshot && !ctx.taskBackend.exportTasksJson) {
12
12
  throw new CliError({
13
13
  exitCode: 3,
14
14
  code: "E_VALIDATION",
15
- message: backendNotSupportedMessage("exportTasksJson()"),
15
+ message: backendNotSupportedMessage("exportProjectionSnapshot()"),
16
16
  });
17
17
  }
18
- await ctx.taskBackend.exportTasksJson(outPath);
18
+ await exportTaskProjectionSnapshot({ ctx, outputPath: outPath });
19
19
  process.stdout.write(`${path.relative(ctx.resolvedProject.gitRoot, outPath)}\n`);
20
20
  return 0;
21
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"finish.d.ts","sourceRoot":"","sources":["../../../src/commands/task/finish.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAqCnC,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;IAClC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2XlB"}
1
+ {"version":3,"file":"finish.d.ts","sourceRoot":"","sources":["../../../src/commands/task/finish.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAqCnC,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;IAClC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4XlB"}
@@ -114,8 +114,9 @@ export async function cmdFinish(opts) {
114
114
  : await readHeadCommit(gitRoot);
115
115
  const useStore = backendIsLocalFileBackend(ctx);
116
116
  const store = useStore ? getTaskStore(ctx) : null;
117
+ const backendWritesTaskReadmes = ctx.taskBackend.capabilities.writes_task_readmes === true;
117
118
  const defaultDirectCloseCommit = ctx.config.workflow_mode === "direct" &&
118
- useStore &&
119
+ backendWritesTaskReadmes &&
119
120
  opts.taskIds.length === 1 &&
120
121
  !opts.commitFromComment &&
121
122
  !statusCommitRequested;
@@ -275,7 +276,7 @@ export async function cmdFinish(opts) {
275
276
  await (useStore
276
277
  ? store.update(primaryTaskId, () => updatedAfterCommit)
277
278
  : ctx.taskBackend.writeTask(updatedAfterCommit));
278
- if (useStore) {
279
+ if (backendWritesTaskReadmes) {
279
280
  const workflowReadmeRelPath = path.join(ctx.config.paths.workflow_dir, primaryTaskId, "README.md");
280
281
  await ctx.git.stage([workflowReadmeRelPath]);
281
282
  const env = buildGitCommitEnv({
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-doc.d.ts","sourceRoot":"","sources":["../../../src/commands/task/migrate-doc.ts"],"names":[],"mappings":"AAkSA,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,GAAG,OAAO,CAAC,MAAM,CAAC,CAwClB"}
1
+ {"version":3,"file":"migrate-doc.d.ts","sourceRoot":"","sources":["../../../src/commands/task/migrate-doc.ts"],"names":[],"mappings":"AAiSA,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqDlB"}
@@ -6,11 +6,11 @@ import { exitCodeForError } from "../../cli/exit-codes.js";
6
6
  import { fileExists, getPathKind } from "../../cli/fs-utils.js";
7
7
  import { successMessage } from "../../cli/output.js";
8
8
  import { CliError } from "../../shared/errors.js";
9
+ import { exportTaskProjectionSnapshot, loadCommandContext } from "../shared/task-backend.js";
9
10
  import { extractDocSection, extractTaskObservationSection, normalizeTaskDocVersion, normalizeVerificationSectionLayout, } from "./shared/docs.js";
10
11
  import { defaultTaskDocV3 } from "./doc-template.js";
11
12
  const V3_CANONICAL_ORDER = [
12
13
  "Summary",
13
- "Context",
14
14
  "Scope",
15
15
  "Plan",
16
16
  "Verify Steps",
@@ -98,8 +98,6 @@ function migrateDocToV3(opts) {
98
98
  const currentText = firstSectionText(currentSections, title);
99
99
  const defaultText = firstSectionText(defaultSections, title) ?? "";
100
100
  let nextText = currentText ?? defaultText;
101
- if (title === "Context" && !(currentText ?? "").trim())
102
- continue;
103
101
  if (title === "Verification") {
104
102
  nextText = normalizeVerificationSectionLayout(currentText ?? defaultText, 3);
105
103
  }
@@ -242,6 +240,12 @@ export async function cmdTaskMigrateDoc(opts) {
242
240
  rootOverride: opts.rootOverride ?? null,
243
241
  });
244
242
  const loaded = await loadConfig(resolved.agentplaneDir);
243
+ const ctx = await loadCommandContext({
244
+ cwd: opts.cwd,
245
+ rootOverride: opts.rootOverride ?? null,
246
+ resolvedProject: resolved,
247
+ config: loaded.config,
248
+ });
245
249
  const tasksDir = path.join(resolved.gitRoot, loaded.config.paths.workflow_dir);
246
250
  const readmePaths = await resolveReadmePaths({ tasksDir, params });
247
251
  if (!params.all) {
@@ -262,6 +266,12 @@ export async function cmdTaskMigrateDoc(opts) {
262
266
  if (res.changed)
263
267
  changed += 1;
264
268
  }
269
+ // Refresh the local export snapshot so doctor and other snapshot-based checks
270
+ // immediately observe the migrated README contract without a separate task export.
271
+ if (ctx.taskBackend.exportProjectionSnapshot || ctx.taskBackend.exportTasksJson) {
272
+ const outPath = path.join(resolved.gitRoot, loaded.config.paths.tasks_path);
273
+ await exportTaskProjectionSnapshot({ ctx, outputPath: outPath });
274
+ }
265
275
  if (!params.quiet) {
266
276
  process.stdout.write(`${successMessage("migrated task docs", undefined, `changed=${changed}`)}\n`);
267
277
  }
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"AA2CA,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAuMF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,YAAY,CAAC;CACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4gBlB;AAED,OAAO,EACL,kCAAkC,EAClC,qBAAqB,EACrB,iCAAiC,GAClC,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"AA4CA,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAuMF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,YAAY,CAAC;CACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsiBlB;AAED,OAAO,EACL,kCAAkC,EAClC,qBAAqB,EACrB,iCAAiC,GAClC,MAAM,qBAAqB,CAAC"}
@@ -10,6 +10,7 @@ import { extractArchive } from "../cli/archive.js";
10
10
  import { exitCodeForError } from "../cli/exit-codes.js";
11
11
  import { warnMessage } from "../cli/output.js";
12
12
  import { CliError } from "../shared/errors.js";
13
+ import { ensureWorkflowArtifacts } from "../shared/workflow-artifacts.js";
13
14
  import { ensureNetworkApproved } from "./shared/network-approval.js";
14
15
  import { getVersion } from "../meta/version.js";
15
16
  import { applyManagedFiles, cleanupAutoUpgradeArtifacts, createUpgradeCommit, ensureCleanTrackedTreeForUpgrade, persistUpgradeState, } from "./upgrade/apply.js";
@@ -638,8 +639,25 @@ export async function cmdUpgradeParsed(opts) {
638
639
  updates: updates.length,
639
640
  skipped: skipped.length,
640
641
  });
642
+ const orchestratorProfilePath = path.join(resolved.agentplaneDir, "agents", "ORCHESTRATOR.json");
643
+ const workflowArtifacts = (await fileExists(orchestratorProfilePath))
644
+ ? await ensureWorkflowArtifacts({
645
+ gitRoot: resolved.gitRoot,
646
+ workflowMode: loaded.config.workflow_mode,
647
+ approvals: {
648
+ requirePlanApproval: loaded.config.agents?.approvals?.require_plan ?? true,
649
+ requireVerifyApproval: loaded.config.agents?.approvals?.require_verify ?? true,
650
+ requireNetworkApproval: loaded.config.agents?.approvals?.require_network ?? true,
651
+ },
652
+ })
653
+ : { installPaths: [], commitPaths: [], changedPaths: [] };
641
654
  const commitPaths = [
642
- ...new Set([...additions, ...updates, ...(shouldMutateConfig ? [CONFIG_REL_PATH] : [])]),
655
+ ...new Set([
656
+ ...additions,
657
+ ...updates,
658
+ ...workflowArtifacts.commitPaths,
659
+ ...(shouldMutateConfig ? [CONFIG_REL_PATH] : []),
660
+ ]),
643
661
  ];
644
662
  const commit = await createUpgradeCommit({
645
663
  gitRoot: resolved.gitRoot,
@@ -653,6 +671,9 @@ export async function cmdUpgradeParsed(opts) {
653
671
  });
654
672
  await cleanupAutoUpgradeArtifacts({ upgradeStateDir, createdBackups });
655
673
  process.stdout.write(`Upgrade applied: ${additions.length} add, ${updates.length} update, ${skipped.length} unchanged\n`);
674
+ if (workflowArtifacts.changedPaths.length > 0) {
675
+ process.stdout.write(`Workflow artifacts refreshed: ${workflowArtifacts.commitPaths.join(", ")}\n`);
676
+ }
656
677
  if (commit) {
657
678
  process.stdout.write(`Upgrade commit: ${commit.hash.slice(0, 12)} ${commit.subject}\n`);
658
679
  }
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-build.command.d.ts","sourceRoot":"","sources":["../../src/commands/workflow-build.command.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAWvE,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,mBAAmB,CAgC9D,CAAC;AAWF,eAAO,MAAM,gBAAgB,EAAE,cAAc,CAAC,mBAAmB,CA2EhE,CAAC"}
1
+ {"version":3,"file":"workflow-build.command.d.ts","sourceRoot":"","sources":["../../src/commands/workflow-build.command.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAYvE,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,mBAAmB,CAgC9D,CAAC;AAWF,eAAO,MAAM,gBAAgB,EAAE,cAAc,CAAC,mBAAmB,CAoEhE,CAAC"}
@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { loadConfig, resolveProject } from "@agentplaneorg/core";
4
4
  import { successMessage, warnMessage } from "../cli/output.js";
5
+ import { buildWorkflowRuntimeContext } from "../shared/workflow-artifacts.js";
5
6
  import { DEFAULT_WORKFLOW_TEMPLATE, buildWorkflowFromTemplates, diagnosticsSummary, publishWorkflowCandidate, resolveWorkflowPaths, validateWorkflowText, } from "../workflow-runtime/index.js";
6
7
  export const workflowBuildSpec = {
7
8
  id: ["workflow", "build"],
@@ -50,22 +51,15 @@ export const runWorkflowBuild = async (ctx, flags) => {
50
51
  const configLoaded = await loadConfig(resolved.agentplaneDir);
51
52
  const workflowPaths = resolveWorkflowPaths(resolved.gitRoot);
52
53
  const configApprovals = configLoaded.config.agents?.approvals;
53
- const runtimeContext = {
54
- workflow: {
55
- mode: configLoaded.config.workflow_mode,
56
- version: 1,
57
- approvals: {
58
- require_plan: configApprovals?.require_plan ?? true,
59
- require_verify: configApprovals?.require_verify ?? true,
60
- require_network: configApprovals?.require_network ?? true,
61
- },
54
+ const runtimeContext = buildWorkflowRuntimeContext({
55
+ gitRoot: resolved.gitRoot,
56
+ workflowMode: configLoaded.config.workflow_mode,
57
+ approvals: {
58
+ requirePlanApproval: configApprovals?.require_plan ?? true,
59
+ requireVerifyApproval: configApprovals?.require_verify ?? true,
60
+ requireNetworkApproval: configApprovals?.require_network ?? true,
62
61
  },
63
- runtime: {
64
- repo_name: path.basename(resolved.gitRoot),
65
- repo_root: resolved.gitRoot,
66
- timestamp: new Date().toISOString(),
67
- },
68
- };
62
+ });
69
63
  const overrideTemplate = await maybeReadOverride(workflowPaths);
70
64
  const built = buildWorkflowFromTemplates({
71
65
  baseTemplate: DEFAULT_WORKFLOW_TEMPLATE,
@@ -3,6 +3,6 @@ export type TaskBackendPort = {
3
3
  listTasks(): Promise<TaskData[]>;
4
4
  getTask(id: string): Promise<TaskData | null>;
5
5
  writeTask(task: TaskData): Promise<void>;
6
- exportTasksJson(path: string): Promise<void>;
6
+ exportProjectionSnapshot(path: string): Promise<void>;
7
7
  };
8
8
  //# sourceMappingURL=task-backend-port.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"task-backend-port.d.ts","sourceRoot":"","sources":["../../src/ports/task-backend-port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAC9C,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C,CAAC"}
1
+ {"version":3,"file":"task-backend-port.d.ts","sourceRoot":"","sources":["../../src/ports/task-backend-port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAC9C,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD,CAAC"}
@@ -0,0 +1,37 @@
1
+ export type WorkflowArtifactApprovals = {
2
+ requirePlanApproval: boolean;
3
+ requireVerifyApproval: boolean;
4
+ requireNetworkApproval: boolean;
5
+ };
6
+ export declare function buildWorkflowRuntimeContext(opts: {
7
+ gitRoot: string;
8
+ workflowMode: "direct" | "branch_pr";
9
+ approvals: WorkflowArtifactApprovals;
10
+ timestamp?: string;
11
+ }): {
12
+ workflow: {
13
+ mode: "direct" | "branch_pr";
14
+ version: number;
15
+ approvals: {
16
+ require_plan: boolean;
17
+ require_verify: boolean;
18
+ require_network: boolean;
19
+ };
20
+ };
21
+ runtime: {
22
+ repo_name: string;
23
+ repo_root: string;
24
+ timestamp: string;
25
+ };
26
+ };
27
+ export declare function ensureWorkflowArtifacts(opts: {
28
+ gitRoot: string;
29
+ workflowMode: "direct" | "branch_pr";
30
+ approvals: WorkflowArtifactApprovals;
31
+ projectOverrideTemplate?: string;
32
+ }): Promise<{
33
+ installPaths: string[];
34
+ commitPaths: string[];
35
+ changedPaths: string[];
36
+ }>;
37
+ //# sourceMappingURL=workflow-artifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-artifacts.d.ts","sourceRoot":"","sources":["../../src/shared/workflow-artifacts.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,yBAAyB,GAAG;IACtC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,sBAAsB,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,QAAQ,GAAG,WAAW,CAAC;IACrC,SAAS,EAAE,yBAAyB,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;;;;;;;;;;;;;;;EAiBA;AAUD,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,QAAQ,GAAG,WAAW,CAAC;IACrC,SAAS,EAAE,yBAAyB,CAAC;IACrC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC,GAAG,OAAO,CAAC;IAAE,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAwErF"}
@@ -0,0 +1,97 @@
1
+ import path from "node:path";
2
+ import { readFile } from "node:fs/promises";
3
+ import { DEFAULT_WORKFLOW_TEMPLATE, buildWorkflowFromTemplates, diagnosticsSummary, publishWorkflowCandidate, resolveWorkflowPaths, } from "../workflow-runtime/index.js";
4
+ import { CliError } from "./errors.js";
5
+ export function buildWorkflowRuntimeContext(opts) {
6
+ return {
7
+ workflow: {
8
+ mode: opts.workflowMode,
9
+ version: 1,
10
+ approvals: {
11
+ require_plan: opts.approvals.requirePlanApproval,
12
+ require_verify: opts.approvals.requireVerifyApproval,
13
+ require_network: opts.approvals.requireNetworkApproval,
14
+ },
15
+ },
16
+ runtime: {
17
+ repo_name: path.basename(opts.gitRoot) || "repo",
18
+ repo_root: opts.gitRoot,
19
+ timestamp: opts.timestamp ?? new Date().toISOString(),
20
+ },
21
+ };
22
+ }
23
+ async function readIfPresent(absPath) {
24
+ try {
25
+ return await readFile(absPath, "utf8");
26
+ }
27
+ catch {
28
+ return null;
29
+ }
30
+ }
31
+ export async function ensureWorkflowArtifacts(opts) {
32
+ const workflowPaths = resolveWorkflowPaths(opts.gitRoot);
33
+ const [beforeWorkflow, beforeLastKnownGood, beforeLegacyWorkflow] = await Promise.all([
34
+ readIfPresent(workflowPaths.workflowPath),
35
+ readIfPresent(workflowPaths.lastKnownGoodPath),
36
+ workflowPaths.legacyWorkflowPath === workflowPaths.workflowPath
37
+ ? Promise.resolve(null)
38
+ : readIfPresent(workflowPaths.legacyWorkflowPath),
39
+ ]);
40
+ const built = buildWorkflowFromTemplates({
41
+ baseTemplate: DEFAULT_WORKFLOW_TEMPLATE,
42
+ projectOverrideTemplate: opts.projectOverrideTemplate,
43
+ runtimeContext: buildWorkflowRuntimeContext({
44
+ gitRoot: opts.gitRoot,
45
+ workflowMode: opts.workflowMode,
46
+ approvals: opts.approvals,
47
+ }),
48
+ });
49
+ if (built.diagnostics.some((diagnostic) => diagnostic.severity === "ERROR")) {
50
+ throw new CliError({
51
+ exitCode: 3,
52
+ code: "E_VALIDATION",
53
+ message: `Failed to generate WORKFLOW.md: ${diagnosticsSummary(built.diagnostics)}`,
54
+ context: {
55
+ diagnostics: built.diagnostics.map((diagnostic) => ({
56
+ severity: diagnostic.severity,
57
+ code: diagnostic.code,
58
+ path: diagnostic.path,
59
+ message: diagnostic.message,
60
+ })),
61
+ },
62
+ });
63
+ }
64
+ const published = await publishWorkflowCandidate(opts.gitRoot, built.text);
65
+ if (!published.ok) {
66
+ throw new CliError({
67
+ exitCode: 3,
68
+ code: "E_VALIDATION",
69
+ message: `Failed to publish WORKFLOW.md: ${diagnosticsSummary(published.diagnostics)}`,
70
+ context: {
71
+ diagnostics: published.diagnostics.map((diagnostic) => ({
72
+ severity: diagnostic.severity,
73
+ code: diagnostic.code,
74
+ path: diagnostic.path,
75
+ message: diagnostic.message,
76
+ })),
77
+ },
78
+ });
79
+ }
80
+ const changedPaths = [];
81
+ if (beforeWorkflow !== built.text)
82
+ changedPaths.push(workflowPaths.workflowPath);
83
+ if (beforeLastKnownGood !== built.text)
84
+ changedPaths.push(workflowPaths.lastKnownGoodPath);
85
+ if (workflowPaths.legacyWorkflowPath !== workflowPaths.workflowPath &&
86
+ beforeLegacyWorkflow !== null) {
87
+ changedPaths.push(workflowPaths.legacyWorkflowPath);
88
+ }
89
+ const commitPaths = [
90
+ ...new Set(changedPaths.map((absPath) => path.relative(opts.gitRoot, absPath))),
91
+ ];
92
+ return {
93
+ installPaths: [workflowPaths.workflowPath, workflowPaths.lastKnownGoodPath],
94
+ commitPaths,
95
+ changedPaths,
96
+ };
97
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentplane",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "Agent Plane CLI for task workflows, recipes, and project automation.",
5
5
  "keywords": [
6
6
  "agentplane",
@@ -55,7 +55,7 @@
55
55
  "prepublishOnly": "node ../../scripts/enforce-github-publish.mjs && npm run prepack"
56
56
  },
57
57
  "dependencies": {
58
- "@agentplaneorg/core": "0.3.3",
58
+ "@agentplaneorg/core": "0.3.5",
59
59
  "yauzl": "^2.10.0"
60
60
  },
61
61
  "devDependencies": {