agentplane 0.3.6 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.build-manifest.json +106 -96
- package/dist/adapters/task-backend/task-backend-adapter.d.ts +2 -2
- package/dist/adapters/task-backend/task-backend-adapter.d.ts.map +1 -1
- package/dist/adapters/task-backend/task-backend-adapter.js +2 -2
- package/dist/backends/task-backend/local-backend.d.ts +7 -5
- package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/local-backend.js +79 -7
- package/dist/backends/task-backend/redmine/env.d.ts +1 -1
- package/dist/backends/task-backend/redmine/env.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine/env.js +3 -0
- package/dist/backends/task-backend/redmine/inspect.d.ts +11 -0
- package/dist/backends/task-backend/redmine/inspect.d.ts.map +1 -0
- package/dist/backends/task-backend/redmine/inspect.js +75 -0
- package/dist/backends/task-backend/redmine/mapping.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine/mapping.js +21 -2
- package/dist/backends/task-backend/redmine/state.d.ts +17 -0
- package/dist/backends/task-backend/redmine/state.d.ts.map +1 -0
- package/dist/backends/task-backend/redmine/state.js +95 -0
- package/dist/backends/task-backend/redmine-backend.d.ts +10 -16
- package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine-backend.js +205 -15
- package/dist/backends/task-backend/shared/constants.d.ts +1 -1
- package/dist/backends/task-backend/shared/constants.js +1 -1
- package/dist/backends/task-backend/shared/record.d.ts.map +1 -1
- package/dist/backends/task-backend/shared/record.js +20 -1
- package/dist/backends/task-backend/shared/types.d.ts +42 -4
- package/dist/backends/task-backend/shared/types.d.ts.map +1 -1
- package/dist/backends/task-backend/shared.d.ts +1 -1
- package/dist/backends/task-backend/shared.d.ts.map +1 -1
- package/dist/backends/task-backend.d.ts +1 -1
- package/dist/backends/task-backend.d.ts.map +1 -1
- package/dist/backends/task-index.d.ts.map +1 -1
- package/dist/backends/task-index.js +1 -0
- package/dist/cli/run-cli/command-catalog/project.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/project.js +3 -1
- package/dist/cli/run-cli/command-catalog.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-env.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-env.js +12 -0
- package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
- package/dist/cli/run-cli.test-helpers.js +2 -0
- package/dist/commands/backend/sync.command.d.ts +5 -1
- package/dist/commands/backend/sync.command.d.ts.map +1 -1
- package/dist/commands/backend/sync.command.js +67 -3
- package/dist/commands/backend.d.ts +22 -0
- package/dist/commands/backend.d.ts.map +1 -1
- package/dist/commands/backend.js +110 -1
- package/dist/commands/commit.spec.d.ts.map +1 -1
- package/dist/commands/commit.spec.js +30 -6
- package/dist/commands/doctor/workspace.d.ts +8 -0
- package/dist/commands/doctor/workspace.d.ts.map +1 -1
- package/dist/commands/doctor/workspace.js +127 -3
- package/dist/commands/guard/commit.command.d.ts.map +1 -1
- package/dist/commands/guard/commit.command.js +30 -6
- package/dist/commands/guard/impl/allow.d.ts +4 -0
- package/dist/commands/guard/impl/allow.d.ts.map +1 -1
- package/dist/commands/guard/impl/allow.js +14 -3
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +11 -2
- package/dist/commands/shared/task-backend.d.ts +1 -1
- package/dist/commands/shared/task-backend.d.ts.map +1 -1
- package/dist/commands/shared/task-backend.js +9 -0
- package/dist/commands/shared/task-store.d.ts +61 -2
- package/dist/commands/shared/task-store.d.ts.map +1 -1
- package/dist/commands/shared/task-store.js +298 -60
- package/dist/commands/task/block.d.ts.map +1 -1
- package/dist/commands/task/block.js +58 -37
- package/dist/commands/task/close-shared.d.ts.map +1 -1
- package/dist/commands/task/close-shared.js +17 -20
- package/dist/commands/task/comment.d.ts.map +1 -1
- package/dist/commands/task/comment.js +14 -19
- package/dist/commands/task/derive.command.d.ts +1 -0
- package/dist/commands/task/derive.command.d.ts.map +1 -1
- package/dist/commands/task/derive.command.js +15 -2
- package/dist/commands/task/derive.d.ts +1 -0
- package/dist/commands/task/derive.d.ts.map +1 -1
- package/dist/commands/task/derive.js +27 -4
- package/dist/commands/task/doc.d.ts.map +1 -1
- package/dist/commands/task/doc.js +16 -5
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +41 -41
- package/dist/commands/task/migrate-doc.d.ts +15 -0
- package/dist/commands/task/migrate-doc.d.ts.map +1 -1
- package/dist/commands/task/migrate-doc.js +126 -35
- package/dist/commands/task/new.d.ts.map +1 -1
- package/dist/commands/task/new.js +3 -1
- package/dist/commands/task/plan.js +28 -28
- package/dist/commands/task/set-status.d.ts.map +1 -1
- package/dist/commands/task/set-status.js +104 -61
- package/dist/commands/task/shared/dependencies.d.ts +1 -0
- package/dist/commands/task/shared/dependencies.d.ts.map +1 -1
- package/dist/commands/task/shared/dependencies.js +10 -0
- package/dist/commands/task/shared/docs.js +1 -1
- package/dist/commands/task/shared/transitions.d.ts +17 -0
- package/dist/commands/task/shared/transitions.d.ts.map +1 -1
- package/dist/commands/task/shared/transitions.js +20 -7
- package/dist/commands/task/shared.d.ts +2 -2
- package/dist/commands/task/shared.d.ts.map +1 -1
- package/dist/commands/task/shared.js +2 -2
- package/dist/commands/task/start.d.ts.map +1 -1
- package/dist/commands/task/start.js +33 -28
- package/dist/commands/task/verify-record.d.ts.map +1 -1
- package/dist/commands/task/verify-record.js +32 -32
- package/dist/commands/upgrade/apply.d.ts +2 -0
- package/dist/commands/upgrade/apply.d.ts.map +1 -1
- package/dist/commands/upgrade/apply.js +33 -1
- package/dist/commands/upgrade.command.d.ts.map +1 -1
- package/dist/commands/upgrade.command.js +25 -0
- package/dist/commands/upgrade.d.ts +1 -0
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +34 -0
- package/dist/policy/rules/allowlist.d.ts.map +1 -1
- package/dist/policy/rules/allowlist.js +12 -9
- package/dist/ports/task-backend-port.d.ts +2 -2
- package/dist/ports/task-backend-port.d.ts.map +1 -1
- package/dist/shared/protected-paths.d.ts +10 -0
- package/dist/shared/protected-paths.d.ts.map +1 -1
- package/dist/shared/protected-paths.js +33 -0
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mapBackendError } from "../../cli/error-map.js";
|
|
2
2
|
import { successMessage } from "../../cli/output.js";
|
|
3
3
|
import { loadCommandContext, loadTaskFromContext, } from "../shared/task-backend.js";
|
|
4
|
-
import { backendIsLocalFileBackend, getTaskStore } from "../shared/task-store.js";
|
|
4
|
+
import { appendTaskCommentIntent, appendTaskEventIntent, backendIsLocalFileBackend, getTaskStore, touchTaskDocMetaIntent, } from "../shared/task-store.js";
|
|
5
5
|
import { appendTaskEvent, normalizeTaskDocVersion, nowIso } from "./shared.js";
|
|
6
6
|
export async function cmdTaskComment(opts) {
|
|
7
7
|
try {
|
|
@@ -9,27 +9,22 @@ export async function cmdTaskComment(opts) {
|
|
|
9
9
|
(await loadCommandContext({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null }));
|
|
10
10
|
const useStore = backendIsLocalFileBackend(ctx);
|
|
11
11
|
const store = useStore ? getTaskStore(ctx) : null;
|
|
12
|
-
const task = useStore
|
|
13
|
-
? await store.get(opts.taskId)
|
|
14
|
-
: await loadTaskFromContext({ ctx, taskId: opts.taskId });
|
|
12
|
+
const task = useStore ? null : await loadTaskFromContext({ ctx, taskId: opts.taskId });
|
|
15
13
|
const at = nowIso();
|
|
16
14
|
await (useStore
|
|
17
|
-
? store.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
],
|
|
27
|
-
docMeta: {
|
|
28
|
-
touch: true,
|
|
15
|
+
? store.mutate(opts.taskId, (current) => [
|
|
16
|
+
appendTaskCommentIntent({ author: opts.author, body: opts.body }),
|
|
17
|
+
appendTaskEventIntent({
|
|
18
|
+
type: "comment",
|
|
19
|
+
at,
|
|
20
|
+
author: opts.author,
|
|
21
|
+
body: opts.body,
|
|
22
|
+
}),
|
|
23
|
+
touchTaskDocMetaIntent({
|
|
29
24
|
updatedBy: opts.author,
|
|
30
|
-
version: normalizeTaskDocVersion(
|
|
31
|
-
},
|
|
32
|
-
|
|
25
|
+
version: normalizeTaskDocVersion(current.doc_version),
|
|
26
|
+
}),
|
|
27
|
+
])
|
|
33
28
|
: ctx.taskBackend.writeTask({
|
|
34
29
|
...task,
|
|
35
30
|
comments: [
|
|
@@ -7,6 +7,7 @@ export type TaskDeriveParsed = {
|
|
|
7
7
|
owner: string;
|
|
8
8
|
priority: "low" | "normal" | "med" | "high";
|
|
9
9
|
tags: string[];
|
|
10
|
+
verify: string[];
|
|
10
11
|
};
|
|
11
12
|
export declare const taskDeriveSpec: CommandSpec<TaskDeriveParsed>;
|
|
12
13
|
export declare function makeRunTaskDeriveHandler(getCtx: (cmd: string) => Promise<CommandContext>): (ctx: CommandCtx, p: TaskDeriveParsed) => Promise<number>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derive.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/derive.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IAC5C,IAAI,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"derive.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/derive.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IAC5C,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,gBAAgB,CAiFxD,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IACzE,KAAK,UAAU,EAAE,GAAG,gBAAgB,KAAG,OAAO,CAAC,MAAM,CAAC,CAcrE"}
|
|
@@ -45,13 +45,24 @@ export const taskDeriveSpec = {
|
|
|
45
45
|
minCount: 1,
|
|
46
46
|
description: "Repeatable. Adds a tag (must provide at least one).",
|
|
47
47
|
},
|
|
48
|
+
{
|
|
49
|
+
kind: "string",
|
|
50
|
+
name: "verify",
|
|
51
|
+
valueHint: "<command>",
|
|
52
|
+
repeatable: true,
|
|
53
|
+
description: "Repeatable. Verification commands/checks to run for this task.",
|
|
54
|
+
},
|
|
48
55
|
],
|
|
49
56
|
examples: [
|
|
50
57
|
{
|
|
51
|
-
cmd: 'agentplane task derive 202602070101-ABCD --title "Implement X" --description "Do the thing" --owner CODER --tag code',
|
|
52
|
-
why: "Create an implementation task derived from a spike.",
|
|
58
|
+
cmd: 'agentplane task derive 202602070101-ABCD --title "Implement X" --description "Do the thing" --owner CODER --tag code --verify "bun test"',
|
|
59
|
+
why: "Create an implementation task derived from a spike with seeded verify steps.",
|
|
53
60
|
},
|
|
54
61
|
],
|
|
62
|
+
notes: [
|
|
63
|
+
"Derived tasks default to doc_version=3 and seed the README v3 section contract automatically.",
|
|
64
|
+
"For verify-required primary tags, this command seeds a default ## Verify Steps acceptance contract in README.",
|
|
65
|
+
],
|
|
55
66
|
validateRaw: (raw) => {
|
|
56
67
|
const tags = toStringList(raw.opts.tag);
|
|
57
68
|
if (tags.some((t) => t.trim() === "")) {
|
|
@@ -69,6 +80,7 @@ export const taskDeriveSpec = {
|
|
|
69
80
|
owner: raw.opts.owner,
|
|
70
81
|
priority: raw.opts.priority ?? "med",
|
|
71
82
|
tags: toStringList(raw.opts.tag),
|
|
83
|
+
verify: (raw.opts.verify ?? []),
|
|
72
84
|
}),
|
|
73
85
|
};
|
|
74
86
|
export function makeRunTaskDeriveHandler(getCtx) {
|
|
@@ -83,6 +95,7 @@ export function makeRunTaskDeriveHandler(getCtx) {
|
|
|
83
95
|
owner: p.owner,
|
|
84
96
|
priority: p.priority,
|
|
85
97
|
tags: p.tags,
|
|
98
|
+
verify: p.verify,
|
|
86
99
|
});
|
|
87
100
|
};
|
|
88
101
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derive.d.ts","sourceRoot":"","sources":["../../../src/commands/task/derive.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"derive.d.ts","sourceRoot":"","sources":["../../../src/commands/task/derive.ts"],"names":[],"mappings":"AAKA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAuBpF,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IAC5C,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsGlB"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { setMarkdownSection, taskDocToSectionMap } from "@agentplaneorg/core";
|
|
1
2
|
import { mapBackendError } from "../../cli/error-map.js";
|
|
2
|
-
import { unknownEntityMessage } from "../../cli/output.js";
|
|
3
|
+
import { unknownEntityMessage, warnMessage } from "../../cli/output.js";
|
|
3
4
|
import { CliError } from "../../shared/errors.js";
|
|
4
5
|
import { loadCommandContext } from "../shared/task-backend.js";
|
|
5
|
-
import {
|
|
6
|
+
import { buildDefaultVerifyStepsSection, defaultTaskDocV3, TASK_DOC_VERSION_V3, } from "./doc-template.js";
|
|
7
|
+
import { extractTaskObservationSection, normalizeTaskDocVersion, nowIso, requiresVerifyStepsByPrimary, resolvePrimaryTag, toStringArray, warnIfUnknownOwner, } from "./shared.js";
|
|
6
8
|
function normalizeOneLine(text, maxChars) {
|
|
7
9
|
const normalized = text.trim().replaceAll(/\s+/g, " ");
|
|
8
10
|
if (normalized.length <= maxChars)
|
|
@@ -45,6 +47,25 @@ export async function cmdTaskDerive(opts) {
|
|
|
45
47
|
description = `${description} (derived from spike ${opts.spikeId})`;
|
|
46
48
|
if (excerpt)
|
|
47
49
|
description = `${description} [spike_notes: ${excerpt}]`;
|
|
50
|
+
let doc = defaultTaskDocV3({ title: opts.title, description });
|
|
51
|
+
const spikeTag = (ctx.config.tasks.verify.spike_tag ?? "spike").trim().toLowerCase();
|
|
52
|
+
const primary = resolvePrimaryTag(opts.tags, ctx);
|
|
53
|
+
if (primary.usedFallback) {
|
|
54
|
+
process.stderr.write(`${warnMessage(`primary tag not found in task tags; using fallback primary=${primary.primary}`)}\n`);
|
|
55
|
+
}
|
|
56
|
+
const requiresVerifySteps = requiresVerifyStepsByPrimary(opts.tags, ctx.config);
|
|
57
|
+
await warnIfUnknownOwner(ctx, opts.owner);
|
|
58
|
+
if (requiresVerifySteps) {
|
|
59
|
+
doc = setMarkdownSection(doc, "Verify Steps", buildDefaultVerifyStepsSection({
|
|
60
|
+
primary: primary.primary,
|
|
61
|
+
verifyCommands: opts.verify,
|
|
62
|
+
}));
|
|
63
|
+
process.stderr.write(`${warnMessage("task requires Verify Steps by primary tag; seeded a default ## Verify Steps section in README (review and refine before approval/start)")}\n`);
|
|
64
|
+
}
|
|
65
|
+
const hasSpike = opts.tags.some((tag) => tag.trim().toLowerCase() === spikeTag);
|
|
66
|
+
if (hasSpike && requiresVerifySteps) {
|
|
67
|
+
process.stderr.write(`${warnMessage("spike is combined with a primary tag that requires verify steps; consider splitting spike vs implementation tasks")}\n`);
|
|
68
|
+
}
|
|
48
69
|
const at = nowIso();
|
|
49
70
|
await ctx.taskBackend.writeTask({
|
|
50
71
|
id: taskId,
|
|
@@ -55,9 +76,11 @@ export async function cmdTaskDerive(opts) {
|
|
|
55
76
|
owner: opts.owner,
|
|
56
77
|
tags: opts.tags,
|
|
57
78
|
depends_on: [opts.spikeId],
|
|
58
|
-
verify:
|
|
79
|
+
verify: opts.verify,
|
|
59
80
|
comments: [],
|
|
60
|
-
|
|
81
|
+
doc,
|
|
82
|
+
sections: taskDocToSectionMap(doc),
|
|
83
|
+
doc_version: TASK_DOC_VERSION_V3,
|
|
61
84
|
doc_updated_at: at,
|
|
62
85
|
doc_updated_by: opts.owner,
|
|
63
86
|
id_source: "generated",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doc.d.ts","sourceRoot":"","sources":["../../../src/commands/task/doc.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doc.d.ts","sourceRoot":"","sources":["../../../src/commands/task/doc.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AA6CpF,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgLlB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyDlB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { normalizeDocSectionName, normalizeTaskDoc, parseDocSections, renderTaskDocFromSections, setMarkdownSection, taskDocToSectionMap, ensureDocSections, } from "@agentplaneorg/core";
|
|
4
4
|
import { mapBackendError, mapCoreError } from "../../cli/error-map.js";
|
|
5
5
|
import { infoMessage, unknownEntityMessage, backendNotSupportedMessage, warnMessage, } from "../../cli/output.js";
|
|
6
6
|
import { CliError } from "../../shared/errors.js";
|
|
@@ -222,19 +222,30 @@ export async function cmdTaskDocShow(opts) {
|
|
|
222
222
|
const useStore = backendIsLocalFileBackend(ctx);
|
|
223
223
|
const storeTask = useStore ? await getTaskStore(ctx).get(opts.taskId) : null;
|
|
224
224
|
const doc = useStore
|
|
225
|
-
?
|
|
225
|
+
? storeTask?.sections && Object.keys(storeTask.sections).length > 0
|
|
226
|
+
? renderTaskDocFromSections(storeTask.sections)
|
|
227
|
+
: String(storeTask?.doc ?? "")
|
|
226
228
|
: ((await backend.getTaskDoc(opts.taskId)) ?? "");
|
|
229
|
+
const canonicalSections = new Map();
|
|
230
|
+
for (const [title, text] of Object.entries(useStore && storeTask?.sections && Object.keys(storeTask.sections).length > 0
|
|
231
|
+
? storeTask.sections
|
|
232
|
+
: taskDocToSectionMap(doc))) {
|
|
233
|
+
canonicalSections.set(normalizeDocSectionName(title), {
|
|
234
|
+
title,
|
|
235
|
+
lines: String(text ?? "").split("\n"),
|
|
236
|
+
});
|
|
237
|
+
}
|
|
227
238
|
if (opts.section) {
|
|
228
239
|
const sectionKey = normalizeDocSectionName(opts.section);
|
|
229
|
-
const
|
|
230
|
-
const entry = sections.get(sectionKey);
|
|
240
|
+
const entry = canonicalSections.get(sectionKey);
|
|
231
241
|
const content = entry?.lines ?? [];
|
|
232
|
-
if (content.length > 0) {
|
|
242
|
+
if (content.some((line) => line.trim().length > 0)) {
|
|
233
243
|
process.stdout.write(`${content.join("\n").trimEnd()}\n`);
|
|
234
244
|
return 0;
|
|
235
245
|
}
|
|
236
246
|
if (!opts.quiet) {
|
|
237
247
|
process.stdout.write(`${infoMessage(`section has no content: ${opts.section}`)}\n`);
|
|
248
|
+
return 0;
|
|
238
249
|
}
|
|
239
250
|
return 0;
|
|
240
251
|
}
|
|
@@ -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;
|
|
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;AAgGnC,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,CA8YlB"}
|
|
@@ -9,7 +9,7 @@ import { buildGitCommitEnv, cmdCommit, commitFromComment } from "../guard/index.
|
|
|
9
9
|
import { ensureActionApproved } from "../shared/approval-requirements.js";
|
|
10
10
|
import { ensureReconciledBeforeMutation } from "../shared/reconcile-check.js";
|
|
11
11
|
import { loadCommandContext, loadTaskFromContext, } from "../shared/task-backend.js";
|
|
12
|
-
import { backendIsLocalFileBackend, getTaskStore } from "../shared/task-store.js";
|
|
12
|
+
import { appendTaskCommentIntent, appendTaskEventIntent, backendIsLocalFileBackend, getTaskStore, mutateTaskStore, setTaskFieldsIntent, touchTaskDocMetaIntent, } from "../shared/task-store.js";
|
|
13
13
|
import { readDirectWorkLock } from "../../shared/direct-work-lock.js";
|
|
14
14
|
import { appendTaskEvent, defaultCommitEmojiForStatus, enforceStatusCommitPolicy, ensureAgentFilledRequiredDocSections, ensureVerificationSatisfiedIfRequired, normalizeTaskDocVersion, nowIso, readCommitInfo, readHeadCommit, requireStructuredComment, resolvePrimaryTag, toStringArray, } from "./shared.js";
|
|
15
15
|
async function clearDirectWorkLockIfMatches(opts) {
|
|
@@ -175,24 +175,24 @@ export async function cmdFinish(opts) {
|
|
|
175
175
|
let primaryTag = null;
|
|
176
176
|
for (const taskId of opts.taskIds) {
|
|
177
177
|
const task = useStore ? await store.get(taskId) : await loadTaskFromContext({ ctx, taskId });
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
(opts.commitFromComment || statusCommitRequested)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
178
|
+
if (!useStore) {
|
|
179
|
+
assertTaskCanFinish({
|
|
180
|
+
task,
|
|
181
|
+
config: ctx.config,
|
|
182
|
+
taskCount: opts.taskIds.length,
|
|
183
|
+
isMetaTask: taskId === metaTaskId,
|
|
184
|
+
resultProvided,
|
|
185
|
+
resultSummary,
|
|
186
|
+
force: opts.force,
|
|
187
|
+
});
|
|
188
|
+
if (taskId === primaryTaskId && (opts.commitFromComment || statusCommitRequested)) {
|
|
189
|
+
primaryStatusFrom = String(task.status || "TODO").toUpperCase();
|
|
190
|
+
primaryTag = resolvePrimaryTag(toStringArray(task.tags), ctx).primary;
|
|
191
|
+
}
|
|
192
192
|
}
|
|
193
193
|
const at = nowIso();
|
|
194
194
|
if (useStore) {
|
|
195
|
-
await store
|
|
195
|
+
await mutateTaskStore(store, taskId, (current) => {
|
|
196
196
|
assertTaskCanFinish({
|
|
197
197
|
task: current,
|
|
198
198
|
config: ctx.config,
|
|
@@ -203,31 +203,32 @@ export async function cmdFinish(opts) {
|
|
|
203
203
|
force: opts.force,
|
|
204
204
|
});
|
|
205
205
|
const currentStatus = String(current.status || "TODO").toUpperCase();
|
|
206
|
-
|
|
207
|
-
|
|
206
|
+
if (taskId === primaryTaskId && (opts.commitFromComment || statusCommitRequested)) {
|
|
207
|
+
primaryStatusFrom = currentStatus;
|
|
208
|
+
primaryTag = resolvePrimaryTag(toStringArray(current.tags), ctx).primary;
|
|
209
|
+
}
|
|
210
|
+
return [
|
|
211
|
+
setTaskFieldsIntent({
|
|
208
212
|
status: "DONE",
|
|
209
213
|
commit: { hash: commitInfo.hash, message: commitInfo.message },
|
|
210
214
|
...(taskId === metaTaskId && resultSummary ? { result_summary: resultSummary } : {}),
|
|
211
215
|
...(taskId === metaTaskId && riskLevel ? { risk_level: riskLevel } : {}),
|
|
212
216
|
...(taskId === metaTaskId && breaking ? { breaking: true } : {}),
|
|
213
|
-
},
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
],
|
|
225
|
-
docMeta: {
|
|
226
|
-
touch: true,
|
|
217
|
+
}),
|
|
218
|
+
appendTaskCommentIntent({ author: opts.author, body: opts.body }),
|
|
219
|
+
appendTaskEventIntent({
|
|
220
|
+
type: "status",
|
|
221
|
+
at,
|
|
222
|
+
author: opts.author,
|
|
223
|
+
from: currentStatus,
|
|
224
|
+
to: "DONE",
|
|
225
|
+
note: opts.body,
|
|
226
|
+
}),
|
|
227
|
+
touchTaskDocMetaIntent({
|
|
227
228
|
updatedBy: opts.author,
|
|
228
229
|
version: normalizeTaskDocVersion(current.doc_version),
|
|
229
|
-
},
|
|
230
|
-
|
|
230
|
+
}),
|
|
231
|
+
];
|
|
231
232
|
});
|
|
232
233
|
}
|
|
233
234
|
else {
|
|
@@ -314,16 +315,15 @@ export async function cmdFinish(opts) {
|
|
|
314
315
|
// Refresh task commit metadata to this hash and amend the same commit in local mode so
|
|
315
316
|
// "task done" metadata does not require a manual follow-up close commit.
|
|
316
317
|
await (useStore
|
|
317
|
-
? store
|
|
318
|
-
|
|
318
|
+
? mutateTaskStore(store, primaryTaskId, (current) => [
|
|
319
|
+
setTaskFieldsIntent({
|
|
319
320
|
commit: { hash: committed.hash, message: committed.message },
|
|
320
|
-
},
|
|
321
|
-
|
|
322
|
-
touch: true,
|
|
321
|
+
}),
|
|
322
|
+
touchTaskDocMetaIntent({
|
|
323
323
|
updatedBy: opts.author,
|
|
324
324
|
version: normalizeTaskDocVersion(current.doc_version),
|
|
325
|
-
},
|
|
326
|
-
|
|
325
|
+
}),
|
|
326
|
+
])
|
|
327
327
|
: (async () => {
|
|
328
328
|
const taskAfterCommit = await loadTaskFromContext({ ctx, taskId: primaryTaskId });
|
|
329
329
|
const updatedAfterCommit = {
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
import { resolveProject, type AgentplaneConfig } from "@agentplaneorg/core";
|
|
2
|
+
import { type CommandContext } from "../shared/task-backend.js";
|
|
3
|
+
export type TaskDocMigrationResult = {
|
|
4
|
+
changed: number;
|
|
5
|
+
changedPaths: string[];
|
|
6
|
+
};
|
|
7
|
+
export declare function migrateTaskDocsInWorkspace(opts: {
|
|
8
|
+
cwd: string;
|
|
9
|
+
rootOverride?: string | null;
|
|
10
|
+
all: boolean;
|
|
11
|
+
taskIds: string[];
|
|
12
|
+
resolvedProject?: Awaited<ReturnType<typeof resolveProject>>;
|
|
13
|
+
config?: AgentplaneConfig;
|
|
14
|
+
ctx?: CommandContext;
|
|
15
|
+
}): Promise<TaskDocMigrationResult>;
|
|
1
16
|
export declare function cmdTaskMigrateDoc(opts: {
|
|
2
17
|
cwd: string;
|
|
3
18
|
rootOverride?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-doc.d.ts","sourceRoot":"","sources":["../../../src/commands/task/migrate-doc.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"migrate-doc.d.ts","sourceRoot":"","sources":["../../../src/commands/task/migrate-doc.ts"],"names":[],"mappings":"AAGA,OAAO,EAUL,cAAc,EAGd,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAanC,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AA+TF,wBAAsB,0BAA0B,CAAC,IAAI,EAAE;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC;IAC7D,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,GAAG,CAAC,EAAE,cAAc,CAAC;CACtB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA4DlC;AAED,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,CAoBlB"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { readdir, readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { atomicWriteFile, ensureDocSections, extractTaskDoc, loadConfig, mergeTaskDoc, normalizeTaskDoc, parseTaskReadme, renderTaskReadme, resolveProject, setMarkdownSection, } from "@agentplaneorg/core";
|
|
3
|
+
import { atomicWriteFile, ensureDocSections, extractTaskDoc, loadConfig, mergeTaskDoc, normalizeTaskDoc, parseTaskReadme, renderTaskDocFromSections, renderTaskReadme, resolveProject, setMarkdownSection, taskDocToSectionMap, } from "@agentplaneorg/core";
|
|
4
4
|
import { mapCoreError } from "../../cli/error-map.js";
|
|
5
5
|
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 {
|
|
9
|
+
import { execFileAsync, gitEnv } from "../shared/git.js";
|
|
10
|
+
import { exportTaskProjectionSnapshot, loadCommandContext, } from "../shared/task-backend.js";
|
|
10
11
|
import { extractDocSection, extractTaskObservationSection, decodeEscapedTaskTextNewlines, normalizeTaskDocVersion, normalizeVerificationSectionLayout, } from "./shared/docs.js";
|
|
11
12
|
import { defaultTaskDocV3 } from "./doc-template.js";
|
|
12
13
|
const V3_CANONICAL_ORDER = [
|
|
@@ -22,6 +23,21 @@ const HUMAN_TEXT_SECTIONS = new Set(["summary", "context", "scope", "plan", "fin
|
|
|
22
23
|
function isRecord(value) {
|
|
23
24
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
24
25
|
}
|
|
26
|
+
function normalizeRevision(value) {
|
|
27
|
+
return Number.isInteger(value) && typeof value === "number" && value > 0 ? value : null;
|
|
28
|
+
}
|
|
29
|
+
function normalizeCanonicalSections(value) {
|
|
30
|
+
if (!isRecord(value))
|
|
31
|
+
return null;
|
|
32
|
+
const out = {};
|
|
33
|
+
for (const [title, text] of Object.entries(value)) {
|
|
34
|
+
const normalizedTitle = title.trim();
|
|
35
|
+
if (!normalizedTitle || typeof text !== "string")
|
|
36
|
+
continue;
|
|
37
|
+
out[normalizedTitle] = text.replaceAll("\r\n", "\n").trimEnd();
|
|
38
|
+
}
|
|
39
|
+
return Object.keys(out).length > 0 ? out : null;
|
|
40
|
+
}
|
|
25
41
|
function normalizeSectionKey(section) {
|
|
26
42
|
return section.trim().replaceAll(/\s+/g, " ").toLowerCase();
|
|
27
43
|
}
|
|
@@ -177,9 +193,12 @@ async function migrateTaskReadmeDoc(opts) {
|
|
|
177
193
|
ensurePlanApprovalFrontmatter(frontmatter);
|
|
178
194
|
ensureVerificationFrontmatter(frontmatter);
|
|
179
195
|
normalizeFrontmatterNoteTimestamps(frontmatter);
|
|
196
|
+
const canonicalSections = normalizeCanonicalSections(frontmatter.sections);
|
|
180
197
|
const required = opts.config.tasks.doc.required_sections;
|
|
181
198
|
const extracted = extractTaskDoc(parsed.body);
|
|
182
|
-
const baseDoc =
|
|
199
|
+
const baseDoc = canonicalSections === null
|
|
200
|
+
? extracted || parsed.body
|
|
201
|
+
: renderTaskDocFromSections(canonicalSections);
|
|
183
202
|
let nextDoc = normalizeTaskDoc(ensureDocSections(baseDoc, required));
|
|
184
203
|
const docVersion = normalizeTaskDocVersion(frontmatter.doc_version);
|
|
185
204
|
if (docVersion === 2) {
|
|
@@ -202,6 +221,8 @@ async function migrateTaskReadmeDoc(opts) {
|
|
|
202
221
|
}
|
|
203
222
|
}
|
|
204
223
|
const nextBody = extracted ? mergeTaskDoc(parsed.body, nextDoc) : nextDoc;
|
|
224
|
+
frontmatter.sections = taskDocToSectionMap(nextDoc);
|
|
225
|
+
frontmatter.revision = normalizeRevision(frontmatter.revision) ?? 1;
|
|
205
226
|
const rendered = renderTaskReadme(frontmatter, nextBody);
|
|
206
227
|
const next = rendered.endsWith("\n") ? rendered : `${rendered}\n`;
|
|
207
228
|
if (next === original)
|
|
@@ -226,48 +247,118 @@ async function resolveReadmePaths(opts) {
|
|
|
226
247
|
}
|
|
227
248
|
return out;
|
|
228
249
|
}
|
|
229
|
-
|
|
230
|
-
|
|
250
|
+
async function exportProjectionSnapshotIfChanged(opts) {
|
|
251
|
+
if (!(opts.ctx.taskBackend.exportProjectionSnapshot || opts.ctx.taskBackend.exportTasksJson)) {
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
const relOutputPath = opts.tasksPath.replaceAll("\\", "/");
|
|
255
|
+
const outputPath = path.join(opts.resolvedGitRoot, relOutputPath);
|
|
256
|
+
let before = null;
|
|
257
|
+
try {
|
|
258
|
+
before = await readFile(outputPath, "utf8");
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
before = null;
|
|
262
|
+
}
|
|
263
|
+
await exportTaskProjectionSnapshot({ ctx: opts.ctx, outputPath });
|
|
264
|
+
let after = null;
|
|
231
265
|
try {
|
|
232
|
-
|
|
266
|
+
after = await readFile(outputPath, "utf8");
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
after = null;
|
|
270
|
+
}
|
|
271
|
+
if (before === after)
|
|
272
|
+
return [];
|
|
273
|
+
return (await canStageGitPath(opts.resolvedGitRoot, relOutputPath)) ? [relOutputPath] : [];
|
|
274
|
+
}
|
|
275
|
+
async function canStageGitPath(gitRoot, relPath) {
|
|
276
|
+
try {
|
|
277
|
+
await execFileAsync("git", ["ls-files", "--error-unmatch", "--", relPath], {
|
|
278
|
+
cwd: gitRoot,
|
|
279
|
+
env: gitEnv(),
|
|
280
|
+
});
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
// Continue below: untracked paths may still be stageable when they are not ignored.
|
|
285
|
+
}
|
|
286
|
+
try {
|
|
287
|
+
await execFileAsync("git", ["check-ignore", "--quiet", "--", relPath], {
|
|
288
|
+
cwd: gitRoot,
|
|
289
|
+
env: gitEnv(),
|
|
290
|
+
});
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
export async function migrateTaskDocsInWorkspace(opts) {
|
|
298
|
+
const resolved = opts.resolvedProject ??
|
|
299
|
+
(await resolveProject({
|
|
233
300
|
cwd: opts.cwd,
|
|
234
301
|
rootOverride: opts.rootOverride ?? null,
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
|
|
302
|
+
}));
|
|
303
|
+
let config = opts.config;
|
|
304
|
+
if (!config) {
|
|
305
|
+
const loadedConfig = await loadConfig(resolved.agentplaneDir);
|
|
306
|
+
config = loadedConfig.config;
|
|
307
|
+
}
|
|
308
|
+
const ctx = opts.ctx ??
|
|
309
|
+
(await loadCommandContext({
|
|
238
310
|
cwd: opts.cwd,
|
|
239
311
|
rootOverride: opts.rootOverride ?? null,
|
|
240
312
|
resolvedProject: resolved,
|
|
241
|
-
config
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
if (!(await fileExists(readmePath))) {
|
|
248
|
-
const taskId = path.basename(path.dirname(readmePath));
|
|
249
|
-
throw new CliError({
|
|
250
|
-
exitCode: exitCodeForError("E_IO"),
|
|
251
|
-
code: "E_IO",
|
|
252
|
-
message: `Task README not found: ${taskId}`,
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
let changed = 0;
|
|
313
|
+
config,
|
|
314
|
+
}));
|
|
315
|
+
const params = { all: opts.all, quiet: false, taskIds: opts.taskIds };
|
|
316
|
+
const tasksDir = path.join(resolved.gitRoot, config.paths.workflow_dir);
|
|
317
|
+
const readmePaths = await resolveReadmePaths({ tasksDir, params });
|
|
318
|
+
if (!opts.all) {
|
|
258
319
|
for (const readmePath of readmePaths) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
320
|
+
if (!(await fileExists(readmePath))) {
|
|
321
|
+
const taskId = path.basename(path.dirname(readmePath));
|
|
322
|
+
throw new CliError({
|
|
323
|
+
exitCode: exitCodeForError("E_IO"),
|
|
324
|
+
code: "E_IO",
|
|
325
|
+
message: `Task README not found: ${taskId}`,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
262
328
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
329
|
+
}
|
|
330
|
+
let changed = 0;
|
|
331
|
+
const changedPaths = [];
|
|
332
|
+
for (const readmePath of readmePaths) {
|
|
333
|
+
const res = await migrateTaskReadmeDoc({ readmePath, config });
|
|
334
|
+
if (!res.changed)
|
|
335
|
+
continue;
|
|
336
|
+
changed += 1;
|
|
337
|
+
const relReadmePath = path.relative(resolved.gitRoot, readmePath).replaceAll("\\", "/");
|
|
338
|
+
if (await canStageGitPath(resolved.gitRoot, relReadmePath)) {
|
|
339
|
+
changedPaths.push(relReadmePath);
|
|
268
340
|
}
|
|
341
|
+
}
|
|
342
|
+
if (changed > 0) {
|
|
343
|
+
changedPaths.push(...(await exportProjectionSnapshotIfChanged({
|
|
344
|
+
ctx,
|
|
345
|
+
resolvedGitRoot: resolved.gitRoot,
|
|
346
|
+
tasksPath: config.paths.tasks_path,
|
|
347
|
+
})));
|
|
348
|
+
}
|
|
349
|
+
return { changed, changedPaths: [...new Set(changedPaths)] };
|
|
350
|
+
}
|
|
351
|
+
export async function cmdTaskMigrateDoc(opts) {
|
|
352
|
+
const params = { all: opts.all, quiet: opts.quiet, taskIds: opts.taskIds };
|
|
353
|
+
try {
|
|
354
|
+
const result = await migrateTaskDocsInWorkspace({
|
|
355
|
+
cwd: opts.cwd,
|
|
356
|
+
rootOverride: opts.rootOverride ?? null,
|
|
357
|
+
all: params.all,
|
|
358
|
+
taskIds: params.taskIds,
|
|
359
|
+
});
|
|
269
360
|
if (!params.quiet) {
|
|
270
|
-
process.stdout.write(`${successMessage("migrated task docs", undefined, `changed=${changed}`)}\n`);
|
|
361
|
+
process.stdout.write(`${successMessage("migrated task docs", undefined, `changed=${result.changed}`)}\n`);
|
|
271
362
|
}
|
|
272
363
|
return 0;
|
|
273
364
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/commands/task/new.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAcpF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IAC5C,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAmDF,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,aAAa,CAAC;CACvB,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/commands/task/new.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAcpF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IAC5C,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAmDF,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,aAAa,CAAC;CACvB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmFlB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { setMarkdownSection } from "@agentplaneorg/core";
|
|
1
|
+
import { setMarkdownSection, taskDocToSectionMap } from "@agentplaneorg/core";
|
|
2
2
|
import { mapBackendError } from "../../cli/error-map.js";
|
|
3
3
|
import { backendNotSupportedMessage, warnMessage } from "../../cli/output.js";
|
|
4
4
|
import { CliError } from "../../shared/errors.js";
|
|
@@ -73,6 +73,7 @@ export async function runTaskNewParsed(opts) {
|
|
|
73
73
|
status: "TODO",
|
|
74
74
|
priority: p.priority,
|
|
75
75
|
owner: p.owner,
|
|
76
|
+
revision: 1,
|
|
76
77
|
tags: p.tags,
|
|
77
78
|
depends_on: p.dependsOn,
|
|
78
79
|
verify: p.verify,
|
|
@@ -107,6 +108,7 @@ export async function runTaskNewParsed(opts) {
|
|
|
107
108
|
if (hasSpike && hasImplementationTags) {
|
|
108
109
|
process.stderr.write(`${warnMessage("spike is combined with a primary tag that requires verify steps; consider splitting spike vs implementation tasks")}\n`);
|
|
109
110
|
}
|
|
111
|
+
task.sections = taskDocToSectionMap(task.doc ?? "");
|
|
110
112
|
await ctx.taskBackend.writeTask(task);
|
|
111
113
|
process.stdout.write(`${taskId}\n`);
|
|
112
114
|
return 0;
|