agentplane 0.3.5 → 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/README.md +103 -75
- package/assets/AGENTS.md +4 -2
- package/bin/dist-guard.js +13 -3
- package/bin/runtime-watch.d.ts +1 -0
- package/bin/runtime-watch.js +22 -5
- package/bin/stale-dist-policy.js +9 -2
- package/dist/.build-manifest.json +251 -821
- 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-backend.test-helpers.d.ts +4 -0
- package/dist/backends/task-backend.test-helpers.d.ts.map +1 -0
- package/dist/backends/task-backend.test-helpers.js +33 -0
- package/dist/backends/task-index.d.ts.map +1 -1
- package/dist/backends/task-index.js +1 -0
- package/dist/cli/bootstrap-guide.d.ts.map +1 -1
- package/dist/cli/bootstrap-guide.js +1 -0
- package/dist/cli/command-guide.d.ts.map +1 -1
- package/dist/cli/command-guide.js +3 -2
- package/dist/cli/reason-codes.d.ts.map +1 -1
- package/dist/cli/reason-codes.js +30 -0
- package/dist/cli/run-cli/command-catalog/core.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/core.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/core.js +137 -0
- package/dist/cli/run-cli/command-catalog/lifecycle.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/lifecycle.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/lifecycle.js +52 -0
- package/dist/cli/run-cli/command-catalog/project.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/project.js +80 -0
- package/dist/cli/run-cli/command-catalog/shared.d.ts +19 -0
- package/dist/cli/run-cli/command-catalog/shared.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/shared.js +9 -0
- package/dist/cli/run-cli/command-catalog/task.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/task.js +85 -0
- package/dist/cli/run-cli/command-catalog.d.ts +3 -18
- package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog.js +8 -337
- package/dist/cli/run-cli/commands/ide.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/ide.js +64 -2
- package/dist/cli/run-cli/commands/init/ui.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/ui.js +33 -13
- 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.core.pr-flow.test-helpers.d.ts +3 -0
- package/dist/cli/run-cli.core.pr-flow.test-helpers.d.ts.map +1 -0
- package/dist/cli/run-cli.core.pr-flow.test-helpers.js +41 -0
- package/dist/cli/run-cli.core.tasks.test-helpers.d.ts +2 -0
- package/dist/cli/run-cli.core.tasks.test-helpers.d.ts.map +1 -0
- package/dist/cli/run-cli.core.tasks.test-helpers.js +6 -0
- package/dist/cli/run-cli.test-helpers.d.ts +3 -0
- package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
- package/dist/cli/run-cli.test-helpers.js +140 -6
- 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 +31 -7
- package/dist/commands/doctor/runtime.d.ts.map +1 -1
- package/dist/commands/doctor/runtime.js +3 -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 +9 -0
- package/dist/commands/guard/impl/allow.d.ts.map +1 -1
- package/dist/commands/guard/impl/allow.js +26 -10
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +146 -18
- package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
- package/dist/commands/guard/impl/comment-commit.js +2 -0
- package/dist/commands/hooks/index.d.ts.map +1 -1
- package/dist/commands/hooks/index.js +8 -35
- package/dist/commands/recipes/impl/apply.d.ts +4 -0
- package/dist/commands/recipes/impl/apply.d.ts.map +1 -1
- package/dist/commands/recipes/impl/apply.js +34 -0
- package/dist/commands/recipes/impl/commands/explain.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/explain.js +70 -11
- package/dist/commands/recipes/impl/commands/info.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/info.js +24 -12
- package/dist/commands/recipes/impl/commands/install.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/install.js +32 -36
- package/dist/commands/recipes/impl/commands/list.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/list.js +7 -4
- package/dist/commands/recipes/impl/commands/remove.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/remove.js +9 -11
- package/dist/commands/recipes/impl/constants.d.ts +2 -0
- package/dist/commands/recipes/impl/constants.d.ts.map +1 -1
- package/dist/commands/recipes/impl/constants.js +2 -0
- package/dist/commands/recipes/impl/manifest.d.ts.map +1 -1
- package/dist/commands/recipes/impl/manifest.js +219 -23
- package/dist/commands/recipes/impl/normalize.d.ts +3 -0
- package/dist/commands/recipes/impl/normalize.d.ts.map +1 -1
- package/dist/commands/recipes/impl/normalize.js +28 -24
- package/dist/commands/recipes/impl/paths.d.ts +9 -0
- package/dist/commands/recipes/impl/paths.d.ts.map +1 -1
- package/dist/commands/recipes/impl/paths.js +10 -1
- package/dist/commands/recipes/impl/project-installed-recipes.d.ts +7 -0
- package/dist/commands/recipes/impl/project-installed-recipes.d.ts.map +1 -0
- package/dist/commands/recipes/impl/project-installed-recipes.js +102 -0
- package/dist/commands/recipes/impl/resolver.d.ts +20 -0
- package/dist/commands/recipes/impl/resolver.d.ts.map +1 -0
- package/dist/commands/recipes/impl/resolver.js +220 -0
- package/dist/commands/recipes/impl/scenario.d.ts.map +1 -1
- package/dist/commands/recipes/impl/scenario.js +40 -11
- package/dist/commands/recipes/impl/types.d.ts +145 -16
- package/dist/commands/recipes/impl/types.d.ts.map +1 -1
- package/dist/commands/recipes/install.spec.d.ts.map +1 -1
- package/dist/commands/recipes/install.spec.js +3 -2
- package/dist/commands/recipes.d.ts +6 -4
- package/dist/commands/recipes.d.ts.map +1 -1
- package/dist/commands/recipes.js +5 -3
- package/dist/commands/recipes.test-helpers.d.ts +185 -0
- package/dist/commands/recipes.test-helpers.d.ts.map +1 -0
- package/dist/commands/recipes.test-helpers.js +339 -0
- package/dist/commands/scenario/impl/commands.d.ts.map +1 -1
- package/dist/commands/scenario/impl/commands.js +192 -336
- package/dist/commands/scenario/info.command.d.ts.map +1 -1
- package/dist/commands/scenario/info.command.js +7 -2
- package/dist/commands/scenario/list.command.js +2 -2
- package/dist/commands/scenario/run.command.d.ts.map +1 -1
- package/dist/commands/scenario/run.command.js +7 -2
- package/dist/commands/shared/reconcile-check.d.ts.map +1 -1
- package/dist/commands/shared/reconcile-check.js +77 -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 +92 -2
- package/dist/commands/shared/task-store.d.ts.map +1 -1
- package/dist/commands/shared/task-store.js +405 -43
- package/dist/commands/task/block.d.ts.map +1 -1
- package/dist/commands/task/block.js +84 -46
- package/dist/commands/task/close-duplicate.d.ts.map +1 -1
- package/dist/commands/task/close-duplicate.js +12 -37
- package/dist/commands/task/close-noop.d.ts.map +1 -1
- package/dist/commands/task/close-noop.js +12 -30
- package/dist/commands/task/close-shared.d.ts +14 -0
- package/dist/commands/task/close-shared.d.ts.map +1 -0
- package/dist/commands/task/close-shared.js +73 -0
- package/dist/commands/task/comment.d.ts.map +1 -1
- package/dist/commands/task/comment.js +34 -21
- 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-set.command.d.ts +2 -1
- package/dist/commands/task/doc-set.command.d.ts.map +1 -1
- package/dist/commands/task/doc-set.command.js +36 -4
- package/dist/commands/task/doc-template.d.ts.map +1 -1
- package/dist/commands/task/doc-template.js +2 -7
- package/dist/commands/task/doc.command.js +1 -1
- package/dist/commands/task/doc.d.ts +2 -1
- package/dist/commands/task/doc.d.ts.map +1 -1
- package/dist/commands/task/doc.js +139 -76
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +142 -80
- 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 +128 -43
- package/dist/commands/task/new.d.ts.map +1 -1
- package/dist/commands/task/new.js +3 -1
- package/dist/commands/task/plan-set.command.js +1 -1
- package/dist/commands/task/plan.command.d.ts +8 -0
- package/dist/commands/task/plan.command.d.ts.map +1 -0
- package/dist/commands/task/plan.command.js +37 -0
- package/dist/commands/task/plan.d.ts.map +1 -1
- package/dist/commands/task/plan.js +198 -101
- package/dist/commands/task/set-status.command.d.ts.map +1 -1
- package/dist/commands/task/set-status.command.js +1 -1
- package/dist/commands/task/set-status.d.ts.map +1 -1
- package/dist/commands/task/set-status.js +115 -35
- 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.d.ts +1 -0
- package/dist/commands/task/shared/docs.d.ts.map +1 -1
- package/dist/commands/task/shared/docs.js +8 -1
- package/dist/commands/task/shared/transitions.d.ts +17 -2
- package/dist/commands/task/shared/transitions.d.ts.map +1 -1
- package/dist/commands/task/shared/transitions.js +20 -13
- package/dist/commands/task/shared.d.ts +3 -3
- package/dist/commands/task/shared.d.ts.map +1 -1
- package/dist/commands/task/shared.js +3 -3
- package/dist/commands/task/start.d.ts.map +1 -1
- package/dist/commands/task/start.js +101 -71
- package/dist/commands/task/task.command.d.ts +8 -0
- package/dist/commands/task/task.command.d.ts.map +1 -0
- package/dist/commands/task/task.command.js +71 -0
- package/dist/commands/task/verify-command-shared.d.ts +16 -0
- package/dist/commands/task/verify-command-shared.d.ts.map +1 -0
- package/dist/commands/task/verify-command-shared.js +53 -0
- package/dist/commands/task/verify-ok.command.d.ts +2 -6
- package/dist/commands/task/verify-ok.command.d.ts.map +1 -1
- package/dist/commands/task/verify-ok.command.js +8 -50
- package/dist/commands/task/verify-record.d.ts.map +1 -1
- package/dist/commands/task/verify-record.js +124 -145
- package/dist/commands/task/verify-rework.command.d.ts +2 -6
- package/dist/commands/task/verify-rework.command.d.ts.map +1 -1
- package/dist/commands/task/verify-rework.command.js +8 -50
- 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/commands/verify.spec.d.ts.map +1 -1
- package/dist/commands/verify.spec.js +3 -12
- package/dist/policy/rules/allowlist.d.ts.map +1 -1
- package/dist/policy/rules/allowlist.js +16 -4
- package/dist/policy/rules/protected-paths.d.ts.map +1 -1
- package/dist/policy/rules/protected-paths.js +6 -1
- package/dist/ports/task-backend-port.d.ts +2 -2
- package/dist/ports/task-backend-port.d.ts.map +1 -1
- package/dist/shared/agent-emoji.d.ts.map +1 -1
- package/dist/shared/protected-paths.d.ts +17 -0
- package/dist/shared/protected-paths.d.ts.map +1 -1
- package/dist/shared/protected-paths.js +59 -10
- package/dist/shared/repo-cli-version.d.ts.map +1 -1
- package/dist/shared/repo-cli-version.js +9 -3
- package/package.json +2 -2
|
@@ -6,7 +6,7 @@ import { backendNotSupportedMessage } from "../../cli/output.js";
|
|
|
6
6
|
import { CliError } from "../../shared/errors.js";
|
|
7
7
|
import { loadCommandContext, loadTaskFromContext, } from "../shared/task-backend.js";
|
|
8
8
|
import { backendIsLocalFileBackend, getTaskStore } from "../shared/task-store.js";
|
|
9
|
-
import { ensureAgentFilledRequiredDocSections, extractDocSection, extractTaskObservationSection, isVerifyStepsFilled, nowIso, normalizeTaskDocVersion, taskObservationSectionName, requiresVerifyStepsByPrimary, toStringArray, } from "./shared.js";
|
|
9
|
+
import { decodeEscapedTaskTextNewlines, ensureAgentFilledRequiredDocSections, extractDocSection, extractTaskObservationSection, isVerifyStepsFilled, nowIso, normalizeTaskDocVersion, taskObservationSectionName, requiresVerifyStepsByPrimary, toStringArray, } from "./shared.js";
|
|
10
10
|
async function loadPlanTask(opts) {
|
|
11
11
|
const ctx = opts.ctx ??
|
|
12
12
|
(await loadCommandContext({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null }));
|
|
@@ -28,6 +28,68 @@ async function loadPlanTask(opts) {
|
|
|
28
28
|
function normalizeForComparison(text) {
|
|
29
29
|
return text.replaceAll("\r\n", "\n").trim();
|
|
30
30
|
}
|
|
31
|
+
function buildPlanDocUpdate(opts) {
|
|
32
|
+
const baseDoc = ensureDocSections(opts.currentDocRaw ?? "", opts.requiredSections);
|
|
33
|
+
const currentPlan = extractDocSection(baseDoc, "Plan") ?? "";
|
|
34
|
+
const planChanged = normalizeForComparison(currentPlan) !== normalizeForComparison(opts.text);
|
|
35
|
+
const nextDoc = ensureDocSections(setMarkdownSection(baseDoc, "Plan", opts.text), opts.requiredSections);
|
|
36
|
+
return {
|
|
37
|
+
currentPlan,
|
|
38
|
+
nextPlan: extractDocSection(nextDoc, "Plan") ?? "",
|
|
39
|
+
planChanged,
|
|
40
|
+
docChanged: nextDoc !== baseDoc,
|
|
41
|
+
nextDoc,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function assertPlanSectionPresent(taskId, doc, action) {
|
|
45
|
+
const plan = extractDocSection(doc, "Plan");
|
|
46
|
+
if (!plan || plan.trim().length === 0) {
|
|
47
|
+
throw new CliError({
|
|
48
|
+
exitCode: 3,
|
|
49
|
+
code: "E_VALIDATION",
|
|
50
|
+
message: `${taskId}: cannot ${action} plan: ## Plan section is missing or empty`,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function assertPlanCanBeApproved(opts) {
|
|
55
|
+
assertPlanSectionPresent(opts.task.id, opts.doc, "approve");
|
|
56
|
+
ensureAgentFilledRequiredDocSections({
|
|
57
|
+
task: opts.task,
|
|
58
|
+
config: opts.config,
|
|
59
|
+
doc: opts.doc,
|
|
60
|
+
action: "approve plan",
|
|
61
|
+
});
|
|
62
|
+
const enforceVerifySteps = opts.config.tasks.verify.enforce_on_plan_approve !== false;
|
|
63
|
+
if (!enforceVerifySteps)
|
|
64
|
+
return;
|
|
65
|
+
const tags = toStringArray(opts.task.tags);
|
|
66
|
+
const spikeTag = (opts.config.tasks.verify.spike_tag ?? "spike").trim().toLowerCase();
|
|
67
|
+
const verifyRequired = requiresVerifyStepsByPrimary(tags, opts.config);
|
|
68
|
+
const isSpike = tags.some((tag) => tag.trim().toLowerCase() === spikeTag);
|
|
69
|
+
if (verifyRequired || isSpike) {
|
|
70
|
+
const verifySteps = extractDocSection(opts.doc, "Verify Steps");
|
|
71
|
+
if (!isVerifyStepsFilled(verifySteps)) {
|
|
72
|
+
throw new CliError({
|
|
73
|
+
exitCode: 3,
|
|
74
|
+
code: "E_VALIDATION",
|
|
75
|
+
message: `${opts.task.id}: cannot approve plan: ## Verify Steps section is missing/empty/unfilled ` +
|
|
76
|
+
"(fill it before approving plan)",
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!isSpike)
|
|
81
|
+
return;
|
|
82
|
+
const observationSection = taskObservationSectionName(normalizeTaskDocVersion(opts.task.doc_version));
|
|
83
|
+
const observation = extractTaskObservationSection(opts.doc, normalizeTaskDocVersion(opts.task.doc_version));
|
|
84
|
+
if (!observation || observation.trim().length === 0) {
|
|
85
|
+
throw new CliError({
|
|
86
|
+
exitCode: 3,
|
|
87
|
+
code: "E_VALIDATION",
|
|
88
|
+
message: `${opts.task.id}: cannot approve plan for spike: ## ${observationSection} section is missing or empty ` +
|
|
89
|
+
"(include Findings/Decision/Next Steps)",
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
31
93
|
export async function cmdTaskPlanSet(opts) {
|
|
32
94
|
try {
|
|
33
95
|
const { ctx, backend, task, useStore, store } = await loadPlanTask({
|
|
@@ -60,6 +122,9 @@ export async function cmdTaskPlanSet(opts) {
|
|
|
60
122
|
updatedBy = trimmed;
|
|
61
123
|
}
|
|
62
124
|
let text = opts.text ?? "";
|
|
125
|
+
if (hasText) {
|
|
126
|
+
text = decodeEscapedTaskTextNewlines(text);
|
|
127
|
+
}
|
|
63
128
|
if (hasFile) {
|
|
64
129
|
try {
|
|
65
130
|
text = await readFile(path.resolve(opts.cwd, opts.file ?? ""), "utf8");
|
|
@@ -68,28 +133,80 @@ export async function cmdTaskPlanSet(opts) {
|
|
|
68
133
|
throw mapCoreError(err, { command: "task plan set", filePath: opts.file ?? "" });
|
|
69
134
|
}
|
|
70
135
|
}
|
|
71
|
-
const existingDoc = useStore
|
|
72
|
-
? String(task.doc ?? "")
|
|
73
|
-
: (typeof task.doc === "string" ? task.doc : "") || (await backend.getTaskDoc(task.id));
|
|
74
|
-
const baseDoc = ensureDocSections(existingDoc ?? "", config.tasks.doc.required_sections);
|
|
75
|
-
const currentPlan = extractDocSection(baseDoc, "Plan") ?? "";
|
|
76
|
-
const planChanged = normalizeForComparison(currentPlan) !== normalizeForComparison(text);
|
|
77
|
-
const nextDoc = ensureDocSections(setMarkdownSection(baseDoc, "Plan", text), config.tasks.doc.required_sections);
|
|
78
|
-
const docChanged = nextDoc !== baseDoc;
|
|
79
136
|
const readmePath = path.join(resolved.gitRoot, config.paths.workflow_dir, task.id, "README.md");
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
137
|
+
if (useStore) {
|
|
138
|
+
let expectedCurrentPlan;
|
|
139
|
+
await store.patch(opts.taskId, (current) => {
|
|
140
|
+
const { currentPlan, nextPlan, planChanged, docChanged } = buildPlanDocUpdate({
|
|
141
|
+
currentDocRaw: String(current.doc ?? ""),
|
|
142
|
+
text,
|
|
143
|
+
requiredSections: config.tasks.doc.required_sections,
|
|
144
|
+
});
|
|
145
|
+
if (!planChanged && !docChanged && !updatedBy)
|
|
146
|
+
return null;
|
|
147
|
+
if (!docChanged) {
|
|
148
|
+
return {
|
|
149
|
+
...(planChanged
|
|
150
|
+
? {
|
|
151
|
+
task: {
|
|
152
|
+
plan_approval: {
|
|
153
|
+
state: "pending",
|
|
154
|
+
updated_at: null,
|
|
155
|
+
updated_by: null,
|
|
156
|
+
note: null,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
}
|
|
160
|
+
: {}),
|
|
161
|
+
...(updatedBy ? { docMeta: { touch: true, updatedBy } } : {}),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
expectedCurrentPlan ??= currentPlan;
|
|
165
|
+
return {
|
|
166
|
+
doc: {
|
|
167
|
+
kind: "set-section",
|
|
168
|
+
section: "Plan",
|
|
169
|
+
text: nextPlan,
|
|
170
|
+
requiredSections: config.tasks.doc.required_sections,
|
|
171
|
+
expectedCurrentText: expectedCurrentPlan,
|
|
172
|
+
},
|
|
173
|
+
...(planChanged
|
|
174
|
+
? {
|
|
175
|
+
task: {
|
|
176
|
+
plan_approval: {
|
|
177
|
+
state: "pending",
|
|
178
|
+
updated_at: null,
|
|
179
|
+
updated_by: null,
|
|
180
|
+
note: null,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
}
|
|
184
|
+
: {}),
|
|
185
|
+
...(updatedBy ? { docMeta: { updatedBy } } : {}),
|
|
186
|
+
};
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
const existingDoc = (typeof task.doc === "string" ? task.doc : "") || (await backend.getTaskDoc(task.id));
|
|
191
|
+
const { planChanged, docChanged, nextDoc } = buildPlanDocUpdate({
|
|
192
|
+
currentDocRaw: existingDoc,
|
|
193
|
+
text,
|
|
194
|
+
requiredSections: config.tasks.doc.required_sections,
|
|
195
|
+
});
|
|
196
|
+
if (!planChanged && !docChanged && !updatedBy) {
|
|
197
|
+
process.stdout.write(`${readmePath}\n`);
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
200
|
+
const nextTask = {
|
|
201
|
+
...task,
|
|
202
|
+
doc: nextDoc,
|
|
203
|
+
...(planChanged
|
|
204
|
+
? { plan_approval: { state: "pending", updated_at: null, updated_by: null, note: null } }
|
|
205
|
+
: {}),
|
|
206
|
+
...(updatedBy ? { doc_updated_by: updatedBy } : {}),
|
|
207
|
+
};
|
|
208
|
+
await backend.writeTask(nextTask);
|
|
83
209
|
}
|
|
84
|
-
const nextTask = {
|
|
85
|
-
...task,
|
|
86
|
-
doc: nextDoc,
|
|
87
|
-
...(planChanged
|
|
88
|
-
? { plan_approval: { state: "pending", updated_at: null, updated_by: null, note: null } }
|
|
89
|
-
: {}),
|
|
90
|
-
...(updatedBy ? { doc_updated_by: updatedBy } : {}),
|
|
91
|
-
};
|
|
92
|
-
await (useStore ? store.update(opts.taskId, () => nextTask) : backend.writeTask(nextTask));
|
|
93
210
|
process.stdout.write(`${readmePath}\n`);
|
|
94
211
|
return 0;
|
|
95
212
|
}
|
|
@@ -117,64 +234,36 @@ export async function cmdTaskPlanApprove(opts) {
|
|
|
117
234
|
});
|
|
118
235
|
}
|
|
119
236
|
const note = typeof opts.note === "string" ? opts.note.trim() : "";
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
message: `${task.id}: cannot approve plan: ## Verify Steps section is missing/empty/unfilled ` +
|
|
151
|
-
"(fill it before approving plan)",
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
if (isSpike) {
|
|
156
|
-
const observationSection = taskObservationSectionName(normalizeTaskDocVersion(task.doc_version));
|
|
157
|
-
const observation = extractTaskObservationSection(baseDoc, normalizeTaskDocVersion(task.doc_version));
|
|
158
|
-
if (!observation || observation.trim().length === 0) {
|
|
159
|
-
throw new CliError({
|
|
160
|
-
exitCode: 3,
|
|
161
|
-
code: "E_VALIDATION",
|
|
162
|
-
message: `${task.id}: cannot approve plan for spike: ## ${observationSection} section is missing or empty ` +
|
|
163
|
-
"(include Findings/Decision/Next Steps)",
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
const nextTask = {
|
|
169
|
-
...task,
|
|
170
|
-
plan_approval: {
|
|
171
|
-
state: "approved",
|
|
172
|
-
updated_at: nowIso(),
|
|
173
|
-
updated_by: by,
|
|
174
|
-
note: note || null,
|
|
175
|
-
},
|
|
176
|
-
};
|
|
177
|
-
await (useStore ? store.update(opts.taskId, () => nextTask) : backend.writeTask(nextTask));
|
|
237
|
+
const approvedAt = nowIso();
|
|
238
|
+
await (useStore
|
|
239
|
+
? store.patch(opts.taskId, (current) => {
|
|
240
|
+
const currentDoc = ensureDocSections(String(current.doc ?? ""), config.tasks.doc.required_sections);
|
|
241
|
+
assertPlanCanBeApproved({ task: current, config, doc: currentDoc });
|
|
242
|
+
return {
|
|
243
|
+
task: {
|
|
244
|
+
plan_approval: {
|
|
245
|
+
state: "approved",
|
|
246
|
+
updated_at: approvedAt,
|
|
247
|
+
updated_by: by,
|
|
248
|
+
note: note || null,
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
})
|
|
253
|
+
: (async () => {
|
|
254
|
+
const existingDoc = (typeof task.doc === "string" ? task.doc : "") || (await backend.getTaskDoc(task.id));
|
|
255
|
+
const baseDoc = ensureDocSections(existingDoc ?? "", config.tasks.doc.required_sections);
|
|
256
|
+
assertPlanCanBeApproved({ task, config, doc: baseDoc });
|
|
257
|
+
await backend.writeTask({
|
|
258
|
+
...task,
|
|
259
|
+
plan_approval: {
|
|
260
|
+
state: "approved",
|
|
261
|
+
updated_at: approvedAt,
|
|
262
|
+
updated_by: by,
|
|
263
|
+
note: note || null,
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
})());
|
|
178
267
|
return 0;
|
|
179
268
|
}
|
|
180
269
|
catch (err) {
|
|
@@ -208,28 +297,36 @@ export async function cmdTaskPlanReject(opts) {
|
|
|
208
297
|
message: "Invalid value for --note: empty.",
|
|
209
298
|
});
|
|
210
299
|
}
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
300
|
+
const rejectedAt = nowIso();
|
|
301
|
+
await (useStore
|
|
302
|
+
? store.patch(opts.taskId, (current) => {
|
|
303
|
+
const currentDoc = ensureDocSections(String(current.doc ?? ""), config.tasks.doc.required_sections);
|
|
304
|
+
assertPlanSectionPresent(current.id, currentDoc, "reject");
|
|
305
|
+
return {
|
|
306
|
+
task: {
|
|
307
|
+
plan_approval: {
|
|
308
|
+
state: "rejected",
|
|
309
|
+
updated_at: rejectedAt,
|
|
310
|
+
updated_by: by,
|
|
311
|
+
note: note || null,
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
})
|
|
316
|
+
: (async () => {
|
|
317
|
+
const existingDoc = (typeof task.doc === "string" ? task.doc : "") || (await backend.getTaskDoc(task.id));
|
|
318
|
+
const baseDoc = ensureDocSections(existingDoc ?? "", config.tasks.doc.required_sections);
|
|
319
|
+
assertPlanSectionPresent(task.id, baseDoc, "reject");
|
|
320
|
+
await backend.writeTask({
|
|
321
|
+
...task,
|
|
322
|
+
plan_approval: {
|
|
323
|
+
state: "rejected",
|
|
324
|
+
updated_at: rejectedAt,
|
|
325
|
+
updated_by: by,
|
|
326
|
+
note: note || null,
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
})());
|
|
233
330
|
return 0;
|
|
234
331
|
}
|
|
235
332
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set-status.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/set-status.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAOtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhE,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,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,mBAAmB,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,mBAAmB,
|
|
1
|
+
{"version":3,"file":"set-status.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/set-status.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAOtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhE,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,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,mBAAmB,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,mBAAmB,CA0K9D,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IAC5E,KAAK,UAAU,EAAE,GAAG,mBAAmB,KAAG,OAAO,CAAC,MAAM,CAAC,CAsBxE"}
|
|
@@ -71,7 +71,7 @@ export const taskSetStatusSpec = {
|
|
|
71
71
|
kind: "boolean",
|
|
72
72
|
name: "commit-allow-tasks",
|
|
73
73
|
default: true,
|
|
74
|
-
description: "Allow
|
|
74
|
+
description: "Allow the tasks export snapshot plus artifacts under the active task subtree when commit-from-comment is used.",
|
|
75
75
|
},
|
|
76
76
|
{
|
|
77
77
|
kind: "boolean",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set-status.d.ts","sourceRoot":"","sources":["../../../src/commands/task/set-status.ts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"set-status.d.ts","sourceRoot":"","sources":["../../../src/commands/task/set-status.ts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AA2BnC,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,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,mBAAmB,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2OlB"}
|
|
@@ -5,8 +5,8 @@ import { CliError } from "../../shared/errors.js";
|
|
|
5
5
|
import { commitFromComment } from "../guard/index.js";
|
|
6
6
|
import { ensureActionApproved } from "../shared/approval-requirements.js";
|
|
7
7
|
import { loadCommandContext, loadTaskFromContext, resolveDocUpdatedBy, } from "../shared/task-backend.js";
|
|
8
|
-
import { backendIsLocalFileBackend, getTaskStore } from "../shared/task-store.js";
|
|
9
|
-
import { appendTaskEvent, defaultCommitEmojiForStatus, ensureCommentCommitAllowed, ensureStatusTransitionAllowed, normalizeTaskDocVersion, normalizeTaskStatus, nowIso, readCommitInfo, resolveTaskDependencyState, resolvePrimaryTag, toStringArray, } from "./shared.js";
|
|
8
|
+
import { appendTaskCommentIntent, appendTaskEventIntent, backendIsLocalFileBackend, getTaskStore, mutateTaskStore, setTaskFieldsIntent, touchTaskDocMetaIntent, } from "../shared/task-store.js";
|
|
9
|
+
import { appendTaskEvent, dependencyWarningMessages, defaultCommitEmojiForStatus, ensureCommentCommitAllowed, resolveCommentCommitWarning, ensureStatusTransitionAllowed, normalizeTaskDocVersion, normalizeTaskStatus, nowIso, readCommitInfo, resolveTaskDependencyState, resolvePrimaryTag, toStringArray, } from "./shared.js";
|
|
10
10
|
export async function cmdTaskSetStatus(opts) {
|
|
11
11
|
const nextStatus = normalizeTaskStatus(opts.status);
|
|
12
12
|
if (nextStatus === "DONE" && !opts.force) {
|
|
@@ -42,38 +42,40 @@ export async function cmdTaskSetStatus(opts) {
|
|
|
42
42
|
? await store.get(opts.taskId)
|
|
43
43
|
: await loadTaskFromContext({ ctx, taskId: opts.taskId });
|
|
44
44
|
const currentStatus = String(task.status || "TODO").toUpperCase();
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
45
|
+
if (!useStore) {
|
|
46
|
+
ensureStatusTransitionAllowed({
|
|
47
|
+
currentStatus,
|
|
48
|
+
nextStatus,
|
|
49
|
+
force: opts.force,
|
|
50
|
+
});
|
|
51
|
+
if (!opts.force && (nextStatus === "DOING" || nextStatus === "DONE")) {
|
|
52
|
+
const dep = await resolveTaskDependencyState(task, ctx.taskBackend);
|
|
53
|
+
if (dep.missing.length > 0 || dep.incomplete.length > 0) {
|
|
54
|
+
if (!opts.quiet) {
|
|
55
|
+
if (dep.missing.length > 0) {
|
|
56
|
+
process.stderr.write(`${warnMessage(`missing deps: ${dep.missing.join(", ")}`)}\n`);
|
|
57
|
+
}
|
|
58
|
+
if (dep.incomplete.length > 0) {
|
|
59
|
+
process.stderr.write(`${warnMessage(`incomplete deps: ${dep.incomplete.join(", ")}`)}\n`);
|
|
60
|
+
}
|
|
59
61
|
}
|
|
62
|
+
throw new CliError({
|
|
63
|
+
exitCode: 2,
|
|
64
|
+
code: "E_USAGE",
|
|
65
|
+
message: `Task is not ready: ${task.id} (use --force to override)`,
|
|
66
|
+
});
|
|
60
67
|
}
|
|
61
|
-
throw new CliError({
|
|
62
|
-
exitCode: 2,
|
|
63
|
-
code: "E_USAGE",
|
|
64
|
-
message: `Task is not ready: ${task.id} (use --force to override)`,
|
|
65
|
-
});
|
|
66
68
|
}
|
|
69
|
+
ensureCommentCommitAllowed({
|
|
70
|
+
enabled: opts.commitFromComment,
|
|
71
|
+
config,
|
|
72
|
+
action: "task set-status",
|
|
73
|
+
confirmed: opts.confirmStatusCommit,
|
|
74
|
+
quiet: opts.quiet,
|
|
75
|
+
statusFrom: currentStatus,
|
|
76
|
+
statusTo: nextStatus,
|
|
77
|
+
});
|
|
67
78
|
}
|
|
68
|
-
ensureCommentCommitAllowed({
|
|
69
|
-
enabled: opts.commitFromComment,
|
|
70
|
-
config,
|
|
71
|
-
action: "task set-status",
|
|
72
|
-
confirmed: opts.confirmStatusCommit,
|
|
73
|
-
quiet: opts.quiet,
|
|
74
|
-
statusFrom: currentStatus,
|
|
75
|
-
statusTo: nextStatus,
|
|
76
|
-
});
|
|
77
79
|
const existingComments = Array.isArray(task.comments)
|
|
78
80
|
? task.comments.filter((item) => !!item && typeof item.author === "string" && typeof item.body === "string")
|
|
79
81
|
: [];
|
|
@@ -87,6 +89,13 @@ export async function cmdTaskSetStatus(opts) {
|
|
|
87
89
|
}
|
|
88
90
|
const at = nowIso();
|
|
89
91
|
const eventAuthor = resolveDocUpdatedBy(task, opts.author);
|
|
92
|
+
const commitInfo = opts.commit ? await readCommitInfo(resolved.gitRoot, opts.commit) : null;
|
|
93
|
+
const nextCommit = opts.commit
|
|
94
|
+
? { hash: commitInfo.hash, message: commitInfo.message }
|
|
95
|
+
: undefined;
|
|
96
|
+
let currentStatusForCommit = currentStatus;
|
|
97
|
+
let primaryTagForCommit = resolvePrimaryTag(toStringArray(task.tags), ctx).primary;
|
|
98
|
+
let deferredWarnings = [];
|
|
90
99
|
const next = {
|
|
91
100
|
...task,
|
|
92
101
|
status: nextStatus,
|
|
@@ -104,10 +113,81 @@ export async function cmdTaskSetStatus(opts) {
|
|
|
104
113
|
doc_updated_by: eventAuthor,
|
|
105
114
|
};
|
|
106
115
|
if (opts.commit) {
|
|
107
|
-
|
|
108
|
-
|
|
116
|
+
next.commit = nextCommit;
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
await (useStore
|
|
120
|
+
? mutateTaskStore(store, opts.taskId, async (current) => {
|
|
121
|
+
deferredWarnings = [];
|
|
122
|
+
const currentStatus = String(current.status || "TODO").toUpperCase();
|
|
123
|
+
currentStatusForCommit = currentStatus;
|
|
124
|
+
primaryTagForCommit = resolvePrimaryTag(toStringArray(current.tags), ctx).primary;
|
|
125
|
+
ensureStatusTransitionAllowed({
|
|
126
|
+
currentStatus,
|
|
127
|
+
nextStatus,
|
|
128
|
+
force: opts.force,
|
|
129
|
+
});
|
|
130
|
+
if (!opts.force && (nextStatus === "DOING" || nextStatus === "DONE")) {
|
|
131
|
+
const dep = await resolveTaskDependencyState(current, ctx.taskBackend);
|
|
132
|
+
deferredWarnings = [...deferredWarnings, ...dependencyWarningMessages(dep)];
|
|
133
|
+
if (dep.missing.length > 0 || dep.incomplete.length > 0) {
|
|
134
|
+
throw new CliError({
|
|
135
|
+
exitCode: 2,
|
|
136
|
+
code: "E_USAGE",
|
|
137
|
+
message: `Task is not ready: ${current.id} (use --force to override)`,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const commitWarning = resolveCommentCommitWarning({
|
|
142
|
+
enabled: opts.commitFromComment,
|
|
143
|
+
config,
|
|
144
|
+
action: "task set-status",
|
|
145
|
+
confirmed: opts.confirmStatusCommit,
|
|
146
|
+
quiet: opts.quiet,
|
|
147
|
+
statusFrom: currentStatus,
|
|
148
|
+
statusTo: nextStatus,
|
|
149
|
+
});
|
|
150
|
+
if (commitWarning)
|
|
151
|
+
deferredWarnings.push(commitWarning);
|
|
152
|
+
const currentEventAuthor = resolveDocUpdatedBy(current, opts.author);
|
|
153
|
+
const intents = [
|
|
154
|
+
setTaskFieldsIntent({
|
|
155
|
+
status: nextStatus,
|
|
156
|
+
...(nextCommit ? { commit: nextCommit } : {}),
|
|
157
|
+
}),
|
|
158
|
+
appendTaskEventIntent({
|
|
159
|
+
type: "status",
|
|
160
|
+
at,
|
|
161
|
+
author: currentEventAuthor,
|
|
162
|
+
from: currentStatus,
|
|
163
|
+
to: nextStatus,
|
|
164
|
+
note: commentBody,
|
|
165
|
+
}),
|
|
166
|
+
touchTaskDocMetaIntent({
|
|
167
|
+
updatedBy: currentEventAuthor,
|
|
168
|
+
version: normalizeTaskDocVersion(current.doc_version),
|
|
169
|
+
}),
|
|
170
|
+
];
|
|
171
|
+
if (commentBody) {
|
|
172
|
+
intents.splice(1, 0, appendTaskCommentIntent({ author: opts.author, body: commentBody }));
|
|
173
|
+
}
|
|
174
|
+
return intents;
|
|
175
|
+
})
|
|
176
|
+
: ctx.taskBackend.writeTask(next));
|
|
177
|
+
}
|
|
178
|
+
catch (err) {
|
|
179
|
+
if (err instanceof CliError && !opts.quiet) {
|
|
180
|
+
for (const warning of new Set(deferredWarnings)) {
|
|
181
|
+
process.stderr.write(`${warnMessage(warning)}\n`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
throw err;
|
|
185
|
+
}
|
|
186
|
+
if (!opts.quiet) {
|
|
187
|
+
for (const warning of new Set(deferredWarnings)) {
|
|
188
|
+
process.stderr.write(`${warnMessage(warning)}\n`);
|
|
189
|
+
}
|
|
109
190
|
}
|
|
110
|
-
await (useStore ? store.update(opts.taskId, () => next) : ctx.taskBackend.writeTask(next));
|
|
111
191
|
// tasks.json is export-only; generated via `agentplane task export`.
|
|
112
192
|
if (opts.commitFromComment) {
|
|
113
193
|
if (!opts.body) {
|
|
@@ -122,9 +202,9 @@ export async function cmdTaskSetStatus(opts) {
|
|
|
122
202
|
cwd: opts.cwd,
|
|
123
203
|
rootOverride: opts.rootOverride,
|
|
124
204
|
taskId: opts.taskId,
|
|
125
|
-
primaryTag:
|
|
205
|
+
primaryTag: primaryTagForCommit,
|
|
126
206
|
author: opts.author,
|
|
127
|
-
statusFrom:
|
|
207
|
+
statusFrom: currentStatusForCommit,
|
|
128
208
|
statusTo: nextStatus,
|
|
129
209
|
commentBody: opts.body,
|
|
130
210
|
formattedComment: formatCommentBodyForCommit(opts.body, config),
|
|
@@ -10,6 +10,7 @@ export declare function ensureTaskDependsOnGraphIsAcyclic(opts: {
|
|
|
10
10
|
dependsOn: string[];
|
|
11
11
|
}): Promise<void>;
|
|
12
12
|
export declare function resolveTaskDependencyState(task: TaskData, backend: Pick<TaskBackend, "getTask" | "getTasks">): Promise<DependencyState>;
|
|
13
|
+
export declare function dependencyWarningMessages(dep: DependencyState): string[];
|
|
13
14
|
export declare function buildDependencyState(tasks: TaskData[]): Map<string, DependencyState>;
|
|
14
15
|
export declare function formatTaskLine(task: TaskData, depState?: DependencyState): string;
|
|
15
16
|
//# sourceMappingURL=dependencies.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../../../src/commands/task/shared/dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAK/E,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAkCF,wBAAsB,iCAAiC,CAAC,IAAI,EAAE;IAC5D,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BhB;AAED,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,UAAU,CAAC,GACjD,OAAO,CAAC,eAAe,CAAC,CAuB1B;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAqBpF;AAgBD,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,eAAe,GAAG,MAAM,CAejF"}
|
|
1
|
+
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../../../src/commands/task/shared/dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAK/E,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAkCF,wBAAsB,iCAAiC,CAAC,IAAI,EAAE;IAC5D,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BhB;AAED,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,UAAU,CAAC,GACjD,OAAO,CAAC,eAAe,CAAC,CAuB1B;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,EAAE,CASxE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAqBpF;AAgBD,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,eAAe,GAAG,MAAM,CAejF"}
|
|
@@ -83,6 +83,16 @@ export async function resolveTaskDependencyState(task, backend) {
|
|
|
83
83
|
}
|
|
84
84
|
return { dependsOn, missing, incomplete };
|
|
85
85
|
}
|
|
86
|
+
export function dependencyWarningMessages(dep) {
|
|
87
|
+
const warnings = [];
|
|
88
|
+
if (dep.missing.length > 0) {
|
|
89
|
+
warnings.push(`missing deps: ${dep.missing.join(", ")}`);
|
|
90
|
+
}
|
|
91
|
+
if (dep.incomplete.length > 0) {
|
|
92
|
+
warnings.push(`incomplete deps: ${dep.incomplete.join(", ")}`);
|
|
93
|
+
}
|
|
94
|
+
return warnings;
|
|
95
|
+
}
|
|
86
96
|
export function buildDependencyState(tasks) {
|
|
87
97
|
const byId = new Map(tasks.map((task) => [task.id, task]));
|
|
88
98
|
const state = new Map();
|
|
@@ -5,6 +5,7 @@ export declare const VERIFY_STEPS_PLACEHOLDER = "<!-- TODO: REPLACE WITH TASK-SP
|
|
|
5
5
|
export declare const VERIFICATION_RESULTS_BEGIN = "<!-- BEGIN VERIFICATION RESULTS -->";
|
|
6
6
|
export declare const VERIFICATION_RESULTS_END = "<!-- END VERIFICATION RESULTS -->";
|
|
7
7
|
export type TaskDocVersion = 2 | 3;
|
|
8
|
+
export declare function decodeEscapedTaskTextNewlines(text: string): string;
|
|
8
9
|
export declare function extractDocSection(doc: string, sectionName: string): string | null;
|
|
9
10
|
export declare function isVerifyStepsFilled(sectionText: string | null): boolean;
|
|
10
11
|
export declare function normalizeTaskDocVersion(value: unknown, fallback?: TaskDocVersion): TaskDocVersion;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../../../src/commands/task/shared/docs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAI5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAElE,wBAAgB,MAAM,IAAI,MAAM,CAE/B;AAED,eAAO,MAAM,wBAAwB,+DACyB,CAAC;AAC/D,eAAO,MAAM,0BAA0B,wCAAwC,CAAC;AAChF,eAAO,MAAM,wBAAwB,sCAAsC,CAAC;AAC5E,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,CAAC,CAAC;AAEnC,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBjF;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAKvE;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,QAAQ,GAAE,cAAkB,GAC3B,cAAc,CAEhB;AAED,wBAAgB,kCAAkC,CAChD,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,OAAO,EAAE,cAAc,GACtB,MAAM,CAyCR;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,GAAG,UAAU,CAExF;AAED,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAIjG;AAMD,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAKtE;AAED,wBAAgB,oCAAoC,CAAC,IAAI,EAAE;IACzD,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC3B,MAAM,EAAE,gBAAgB,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CA6BP"}
|
|
1
|
+
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../../../src/commands/task/shared/docs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAI5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAElE,wBAAgB,MAAM,IAAI,MAAM,CAE/B;AAED,eAAO,MAAM,wBAAwB,+DACyB,CAAC;AAC/D,eAAO,MAAM,0BAA0B,wCAAwC,CAAC;AAChF,eAAO,MAAM,wBAAwB,sCAAsC,CAAC;AAC5E,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,CAAC,CAAC;AAEnC,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlE;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBjF;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAKvE;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,QAAQ,GAAE,cAAkB,GAC3B,cAAc,CAEhB;AAED,wBAAgB,kCAAkC,CAChD,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,OAAO,EAAE,cAAc,GACtB,MAAM,CAyCR;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,GAAG,UAAU,CAExF;AAED,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAIjG;AAMD,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAKtE;AAED,wBAAgB,oCAAoC,CAAC,IAAI,EAAE;IACzD,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC3B,MAAM,EAAE,gBAAgB,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CA6BP"}
|
|
@@ -6,6 +6,13 @@ export function nowIso() {
|
|
|
6
6
|
export const VERIFY_STEPS_PLACEHOLDER = "<!-- TODO: REPLACE WITH TASK-SPECIFIC ACCEPTANCE STEPS -->";
|
|
7
7
|
export const VERIFICATION_RESULTS_BEGIN = "<!-- BEGIN VERIFICATION RESULTS -->";
|
|
8
8
|
export const VERIFICATION_RESULTS_END = "<!-- END VERIFICATION RESULTS -->";
|
|
9
|
+
export function decodeEscapedTaskTextNewlines(text) {
|
|
10
|
+
const normalized = text.replaceAll("\r\n", "\n");
|
|
11
|
+
if (!normalized.includes(String.raw `\n`) && !normalized.includes(String.raw `\r\n`)) {
|
|
12
|
+
return normalized;
|
|
13
|
+
}
|
|
14
|
+
return normalized.replaceAll(String.raw `\r\n`, "\n").replaceAll(String.raw `\n`, "\n");
|
|
15
|
+
}
|
|
9
16
|
export function extractDocSection(doc, sectionName) {
|
|
10
17
|
const lines = doc.replaceAll("\r\n", "\n").split("\n");
|
|
11
18
|
let capturing = false;
|
|
@@ -33,7 +40,7 @@ export function isVerifyStepsFilled(sectionText) {
|
|
|
33
40
|
return false;
|
|
34
41
|
return true;
|
|
35
42
|
}
|
|
36
|
-
export function normalizeTaskDocVersion(value, fallback =
|
|
43
|
+
export function normalizeTaskDocVersion(value, fallback = 3) {
|
|
37
44
|
return value === 3 ? 3 : value === 2 ? 2 : fallback;
|
|
38
45
|
}
|
|
39
46
|
export function normalizeVerificationSectionLayout(sectionText, version) {
|