agentplane 0.1.2 → 0.1.3
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 +75 -2
- package/assets/AGENTS.md +3 -0
- package/dist/command-guide.d.ts.map +1 -1
- package/dist/command-guide.js +1 -0
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +6 -5
- package/dist/run-cli.d.ts.map +1 -1
- package/dist/run-cli.js +256 -24
- package/dist/run-cli.test-helpers.d.ts.map +1 -1
- package/dist/run-cli.test-helpers.js +8 -0
- package/dist/task-backend.d.ts.map +1 -1
- package/dist/task-backend.js +57 -5
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
# agentplane
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/agentplane)
|
|
4
|
+
[](https://www.npmjs.com/package/agentplane)
|
|
5
|
+
[](https://github.com/basilisk-labs/agentplane/blob/main/LICENSE)
|
|
6
|
+
[](https://github.com/basilisk-labs/agentplane/blob/main/docs/user/prerequisites.mdx)
|
|
7
|
+
|
|
8
|
+
Agent Plane is an offline-first CLI for running policy-driven agent workflows inside real repositories.
|
|
9
|
+
It turns "AI magic" into a predictable process with approvals, role boundaries, and audit-friendly artifacts.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- Policy-first execution with explicit approvals and guardrails.
|
|
14
|
+
- Role-based workflows for teams: ORCHESTRATOR, PLANNER, CREATOR, INTEGRATOR, etc.
|
|
15
|
+
- Two workflow modes: `direct` (single checkout) and `branch_pr` (worktrees + integration).
|
|
16
|
+
- Task tracking, verification, and exports baked in.
|
|
17
|
+
- Recipes for repeatable setup and automation.
|
|
4
18
|
|
|
5
19
|
## Install
|
|
6
20
|
|
|
@@ -8,12 +22,71 @@ AgentPlane is an offline-first CLI for managing agent workflows (tasks, guardrai
|
|
|
8
22
|
npm install -g agentplane
|
|
9
23
|
```
|
|
10
24
|
|
|
25
|
+
Or run without installing:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx agentplane --help
|
|
29
|
+
```
|
|
30
|
+
|
|
11
31
|
## Requirements
|
|
12
32
|
|
|
13
33
|
- Node.js >= 20
|
|
14
34
|
|
|
15
|
-
##
|
|
35
|
+
## Quickstart
|
|
36
|
+
|
|
37
|
+
Initialize a repository:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx agentplane init
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
See the built-in quickstart guide:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx agentplane quickstart
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Switch workflow mode if you need a structured team flow:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npx agentplane config set workflow_mode branch_pr
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Common Commands
|
|
16
56
|
|
|
17
57
|
```bash
|
|
18
58
|
agentplane --help
|
|
59
|
+
agentplane quickstart
|
|
60
|
+
agentplane config show
|
|
61
|
+
agentplane task list
|
|
62
|
+
agentplane task new --title "..." --description "..." --priority med --owner ORCHESTRATOR --tag docs
|
|
63
|
+
agentplane verify <task-id>
|
|
64
|
+
agentplane finish <task-id>
|
|
65
|
+
agentplane recipes list
|
|
19
66
|
```
|
|
67
|
+
|
|
68
|
+
## Docs and Guides
|
|
69
|
+
|
|
70
|
+
- Documentation index: https://github.com/basilisk-labs/agentplane/tree/main/docs
|
|
71
|
+
- Workflow overview: https://github.com/basilisk-labs/agentplane/blob/main/docs/user/workflow.mdx
|
|
72
|
+
- CLI commands: https://github.com/basilisk-labs/agentplane/blob/main/docs/user/commands.mdx
|
|
73
|
+
- Project layout: https://github.com/basilisk-labs/agentplane/blob/main/docs/developer/project-layout.mdx
|
|
74
|
+
- Recipes: https://github.com/basilisk-labs/agentplane/tree/main/agentplane-recipes
|
|
75
|
+
|
|
76
|
+
## How it works
|
|
77
|
+
|
|
78
|
+
Agent Plane expects a repository policy file (`AGENTS.md`) plus a project config (`.agentplane/config.json`).
|
|
79
|
+
Together, they define role boundaries, approval gates, and the execution pipeline:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
Preflight -> Plan -> Approval -> Tasks -> Verify -> Finish -> Export
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Support
|
|
86
|
+
|
|
87
|
+
- Issues: https://github.com/basilisk-labs/agentplane/issues
|
|
88
|
+
- Contributing: https://github.com/basilisk-labs/agentplane/blob/main/CONTRIBUTING.md
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
MIT
|
package/assets/AGENTS.md
CHANGED
|
@@ -163,6 +163,7 @@ Every task must have these sections in its README or task doc:
|
|
|
163
163
|
|
|
164
164
|
## Updating task docs
|
|
165
165
|
|
|
166
|
+
- Workflow/task artifacts (task READMEs, PR artifacts, task exports) must be updated via `agentplane` commands, not manual edits.
|
|
166
167
|
- Task README updates must be done via `agentplane task doc set ...`
|
|
167
168
|
- Manual edits to `.agentplane/tasks/<task-id>/README.md` are prohibited.
|
|
168
169
|
|
|
@@ -170,6 +171,8 @@ Every task must have these sections in its README or task doc:
|
|
|
170
171
|
|
|
171
172
|
# COMMIT WORKFLOW
|
|
172
173
|
|
|
174
|
+
- Commits and pushes must go through `agentplane` commands (no direct `git commit`/`git push`). If a push is needed but no `agentplane` command exists, ask for guidance.
|
|
175
|
+
|
|
173
176
|
## Commit message semantics (canonical)
|
|
174
177
|
|
|
175
178
|
There are two supported modes:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-guide.d.ts","sourceRoot":"","sources":["../src/command-guide.ts"],"names":[],"mappings":"AA4KA,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAEpC;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"command-guide.d.ts","sourceRoot":"","sources":["../src/command-guide.ts"],"names":[],"mappings":"AA4KA,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAEpC;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CA4EzC"}
|
package/dist/command-guide.js
CHANGED
|
@@ -228,6 +228,7 @@ export function renderQuickstart() {
|
|
|
228
228
|
"- `--json`: emit JSON-formatted errors",
|
|
229
229
|
"- `--help` / `-h`: show help",
|
|
230
230
|
"- `--version`: show version",
|
|
231
|
+
"- `--no-update-check`: skip checking npm for a newer CLI version",
|
|
231
232
|
"",
|
|
232
233
|
"Notes:",
|
|
233
234
|
"- `.env` at the repo root is loaded automatically (without overwriting existing environment variables).",
|
package/dist/help.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,IAAI,MAAM,CA4HnC"}
|
package/dist/help.js
CHANGED
|
@@ -3,15 +3,16 @@ export function renderHelp() {
|
|
|
3
3
|
"agentplane (v1 prototype)",
|
|
4
4
|
"",
|
|
5
5
|
"Usage:",
|
|
6
|
-
" agentplane [--root <path>] [--json] <namespace> <command> [options]",
|
|
7
|
-
" agentplane [--root <path>] [--json] <command> [options]",
|
|
6
|
+
" agentplane [--root <path>] [--json] [--no-update-check] <namespace> <command> [options]",
|
|
7
|
+
" agentplane [--root <path>] [--json] [--no-update-check] <command> [options]",
|
|
8
8
|
"",
|
|
9
9
|
"Core namespaces (implemented in this prototype): config, mode, task, ide, recipes, backend",
|
|
10
10
|
"",
|
|
11
11
|
"Flags:",
|
|
12
|
-
" --help, -h
|
|
13
|
-
" --version
|
|
14
|
-
" --root <path>
|
|
12
|
+
" --help, -h Show help",
|
|
13
|
+
" --version Show version",
|
|
14
|
+
" --root <path> Treat <path> as project root",
|
|
15
|
+
" --no-update-check Skip checking npm for a newer CLI version",
|
|
15
16
|
"",
|
|
16
17
|
"Quickstart commands:",
|
|
17
18
|
" agentplane quickstart",
|
package/dist/run-cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-cli.d.ts","sourceRoot":"","sources":["../src/run-cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-cli.d.ts","sourceRoot":"","sources":["../src/run-cli.ts"],"names":[],"mappings":"AAo8QA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4/D5D"}
|
package/dist/run-cli.js
CHANGED
|
@@ -30,6 +30,7 @@ function gitEnv() {
|
|
|
30
30
|
function parseGlobalArgs(argv) {
|
|
31
31
|
let help = false;
|
|
32
32
|
let version = false;
|
|
33
|
+
let noUpdateCheck = false;
|
|
33
34
|
let jsonErrors = false;
|
|
34
35
|
let root;
|
|
35
36
|
const rest = [];
|
|
@@ -45,6 +46,10 @@ function parseGlobalArgs(argv) {
|
|
|
45
46
|
version = true;
|
|
46
47
|
continue;
|
|
47
48
|
}
|
|
49
|
+
if (arg === "--no-update-check") {
|
|
50
|
+
noUpdateCheck = true;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
48
53
|
if (arg === "--json") {
|
|
49
54
|
jsonErrors = true;
|
|
50
55
|
continue;
|
|
@@ -63,7 +68,7 @@ function parseGlobalArgs(argv) {
|
|
|
63
68
|
}
|
|
64
69
|
rest.push(arg);
|
|
65
70
|
}
|
|
66
|
-
return { globals: { help, version, root, jsonErrors }, rest };
|
|
71
|
+
return { globals: { help, version, noUpdateCheck, root, jsonErrors }, rest };
|
|
67
72
|
}
|
|
68
73
|
function writeError(err, jsonErrors) {
|
|
69
74
|
const hint = renderErrorHint(err);
|
|
@@ -157,6 +162,79 @@ function usageMessage(usage, example) {
|
|
|
157
162
|
function backendNotSupportedMessage(feature) {
|
|
158
163
|
return `Backend does not support ${feature}`;
|
|
159
164
|
}
|
|
165
|
+
const UPDATE_CHECK_PACKAGE = "agentplane";
|
|
166
|
+
const UPDATE_CHECK_URL = `https://registry.npmjs.org/${UPDATE_CHECK_PACKAGE}/latest`;
|
|
167
|
+
const UPDATE_CHECK_TIMEOUT_MS = 1500;
|
|
168
|
+
function parseVersionParts(version) {
|
|
169
|
+
const cleaned = version.trim().replace(/^v/i, "").split("+")[0] ?? "";
|
|
170
|
+
const [mainRaw, prereleaseRaw] = cleaned.split("-", 2);
|
|
171
|
+
const main = (mainRaw ?? "")
|
|
172
|
+
.split(".")
|
|
173
|
+
.filter((part) => part.length > 0)
|
|
174
|
+
.map((part) => {
|
|
175
|
+
const parsed = Number.parseInt(part, 10);
|
|
176
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
177
|
+
});
|
|
178
|
+
return { main, prerelease: prereleaseRaw ? prereleaseRaw.trim() : null };
|
|
179
|
+
}
|
|
180
|
+
function compareVersions(left, right) {
|
|
181
|
+
const a = parseVersionParts(left);
|
|
182
|
+
const b = parseVersionParts(right);
|
|
183
|
+
const length = Math.max(a.main.length, b.main.length);
|
|
184
|
+
for (let i = 0; i < length; i++) {
|
|
185
|
+
const partA = a.main[i] ?? 0;
|
|
186
|
+
const partB = b.main[i] ?? 0;
|
|
187
|
+
if (partA !== partB)
|
|
188
|
+
return partA > partB ? 1 : -1;
|
|
189
|
+
}
|
|
190
|
+
if (a.prerelease === b.prerelease)
|
|
191
|
+
return 0;
|
|
192
|
+
if (a.prerelease === null)
|
|
193
|
+
return 1;
|
|
194
|
+
if (b.prerelease === null)
|
|
195
|
+
return -1;
|
|
196
|
+
return a.prerelease.localeCompare(b.prerelease);
|
|
197
|
+
}
|
|
198
|
+
function isTruthyEnv(value) {
|
|
199
|
+
if (!value)
|
|
200
|
+
return false;
|
|
201
|
+
const normalized = value.trim().toLowerCase();
|
|
202
|
+
return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
|
|
203
|
+
}
|
|
204
|
+
async function fetchLatestNpmVersion() {
|
|
205
|
+
const controller = new AbortController();
|
|
206
|
+
const timeout = setTimeout(() => controller.abort(), UPDATE_CHECK_TIMEOUT_MS);
|
|
207
|
+
try {
|
|
208
|
+
const res = await fetch(UPDATE_CHECK_URL, {
|
|
209
|
+
headers: { "User-Agent": "agentplane" },
|
|
210
|
+
signal: controller.signal,
|
|
211
|
+
});
|
|
212
|
+
if (!res.ok)
|
|
213
|
+
return null;
|
|
214
|
+
const data = (await res.json());
|
|
215
|
+
const version = typeof data.version === "string" ? data.version.trim() : "";
|
|
216
|
+
return version.length > 0 ? version : null;
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
finally {
|
|
222
|
+
clearTimeout(timeout);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
async function maybeWarnOnUpdate(opts) {
|
|
226
|
+
if (opts.skip || opts.jsonErrors)
|
|
227
|
+
return;
|
|
228
|
+
if (isTruthyEnv(process.env.AGENTPLANE_NO_UPDATE_CHECK))
|
|
229
|
+
return;
|
|
230
|
+
const latest = await fetchLatestNpmVersion();
|
|
231
|
+
if (!latest)
|
|
232
|
+
return;
|
|
233
|
+
if (compareVersions(latest, opts.currentVersion) <= 0)
|
|
234
|
+
return;
|
|
235
|
+
const message = `Update available: ${UPDATE_CHECK_PACKAGE} ${opts.currentVersion} → ${latest}. Run: npm i -g ${UPDATE_CHECK_PACKAGE}@latest`;
|
|
236
|
+
process.stderr.write(`${warnMessage(message)}\n`);
|
|
237
|
+
}
|
|
160
238
|
function workflowModeMessage(actual, expected) {
|
|
161
239
|
return `Invalid workflow_mode: ${actual ?? "unknown"} (expected ${expected})`;
|
|
162
240
|
}
|
|
@@ -359,7 +437,7 @@ const BRANCH_STATUS_USAGE_EXAMPLE = "agentplane branch status --base main";
|
|
|
359
437
|
const BRANCH_REMOVE_USAGE = "Usage: agentplane branch remove [--branch <name>] [--worktree <path>] [--force] [--quiet]";
|
|
360
438
|
const BRANCH_REMOVE_USAGE_EXAMPLE = "agentplane branch remove --branch task/20260203-F1Q8AB --worktree .agentplane/worktrees/task";
|
|
361
439
|
const UPGRADE_USAGE = "Usage: agentplane upgrade [--tag <tag>] [--dry-run] [--no-backup] [--source <repo-url>] [--bundle <path|url>] [--checksum <path|url>]";
|
|
362
|
-
const UPGRADE_USAGE_EXAMPLE = "agentplane upgrade --tag v0.1.
|
|
440
|
+
const UPGRADE_USAGE_EXAMPLE = "agentplane upgrade --tag v0.1.3 --dry-run";
|
|
363
441
|
const INIT_USAGE = "Usage: agentplane init --ide <...> --workflow <...> --hooks <...> --require-plan-approval <...> --require-network-approval <...> [--recipes <...>] [--yes] [--force|--backup]";
|
|
364
442
|
const INIT_USAGE_EXAMPLE = "agentplane init --ide codex --workflow direct --hooks false --require-plan-approval true --require-network-approval true --yes";
|
|
365
443
|
const CONFIG_SET_USAGE = "Usage: agentplane config set <key> <value>";
|
|
@@ -1485,6 +1563,7 @@ async function cmdInit(opts) {
|
|
|
1485
1563
|
let recipes = flags.recipes ?? defaults.recipes;
|
|
1486
1564
|
let requirePlanApproval = flags.requirePlanApproval ?? defaults.requirePlanApproval;
|
|
1487
1565
|
let requireNetworkApproval = flags.requireNetworkApproval ?? defaults.requireNetworkApproval;
|
|
1566
|
+
const isInteractive = process.stdin.isTTY && !flags.yes;
|
|
1488
1567
|
if (!process.stdin.isTTY &&
|
|
1489
1568
|
!flags.yes &&
|
|
1490
1569
|
(!flags.workflow ||
|
|
@@ -1497,7 +1576,7 @@ async function cmdInit(opts) {
|
|
|
1497
1576
|
message: usageMessage(INIT_USAGE, INIT_USAGE_EXAMPLE),
|
|
1498
1577
|
});
|
|
1499
1578
|
}
|
|
1500
|
-
if (
|
|
1579
|
+
if (isInteractive) {
|
|
1501
1580
|
ide = flags.ide ?? defaults.ide;
|
|
1502
1581
|
if (!flags.workflow) {
|
|
1503
1582
|
const choice = await promptChoice("Select workflow mode", ["direct", "branch_pr"], workflow);
|
|
@@ -1534,7 +1613,9 @@ async function cmdInit(opts) {
|
|
|
1534
1613
|
validateBundledRecipesSelection(recipes);
|
|
1535
1614
|
try {
|
|
1536
1615
|
const initRoot = path.resolve(opts.rootOverride ?? opts.cwd);
|
|
1537
|
-
|
|
1616
|
+
const existingGitRoot = await findGitRoot(initRoot);
|
|
1617
|
+
const gitRootExisted = Boolean(existingGitRoot);
|
|
1618
|
+
let gitRoot = existingGitRoot;
|
|
1538
1619
|
const baseBranchFallback = defaultConfig().base_branch;
|
|
1539
1620
|
if (!gitRoot) {
|
|
1540
1621
|
await gitInitRepo(initRoot, baseBranchFallback);
|
|
@@ -1544,7 +1625,13 @@ async function cmdInit(opts) {
|
|
|
1544
1625
|
cwd: gitRoot,
|
|
1545
1626
|
rootOverride: gitRoot,
|
|
1546
1627
|
});
|
|
1547
|
-
|
|
1628
|
+
let initBaseBranch = await resolveInitBaseBranch(resolved.gitRoot, baseBranchFallback);
|
|
1629
|
+
if (isInteractive && workflow === "branch_pr" && gitRootExisted) {
|
|
1630
|
+
initBaseBranch = await promptInitBaseBranch({
|
|
1631
|
+
gitRoot: resolved.gitRoot,
|
|
1632
|
+
fallback: initBaseBranch,
|
|
1633
|
+
});
|
|
1634
|
+
}
|
|
1548
1635
|
const configPath = path.join(resolved.agentplaneDir, "config.json");
|
|
1549
1636
|
const backendPath = path.join(resolved.agentplaneDir, "backends", "local", "backend.json");
|
|
1550
1637
|
const initDirs = [
|
|
@@ -1658,6 +1745,7 @@ async function cmdInit(opts) {
|
|
|
1658
1745
|
baseBranch: initBaseBranch,
|
|
1659
1746
|
installPaths,
|
|
1660
1747
|
version: getVersion(),
|
|
1748
|
+
skipHooks: hooks,
|
|
1661
1749
|
});
|
|
1662
1750
|
process.stdout.write(`${path.relative(resolved.gitRoot, resolved.agentplaneDir)}\n`);
|
|
1663
1751
|
return 0;
|
|
@@ -4472,8 +4560,12 @@ async function gitAddPaths(cwd, paths) {
|
|
|
4472
4560
|
return;
|
|
4473
4561
|
await execFileAsync("git", ["add", "--", ...paths], { cwd, env: gitEnv() });
|
|
4474
4562
|
}
|
|
4475
|
-
async function gitCommit(cwd, message) {
|
|
4476
|
-
|
|
4563
|
+
async function gitCommit(cwd, message, opts) {
|
|
4564
|
+
const args = ["commit", "-m", message];
|
|
4565
|
+
if (opts?.skipHooks)
|
|
4566
|
+
args.push("--no-verify");
|
|
4567
|
+
const env = opts?.env ? { ...gitEnv(), ...opts.env } : gitEnv();
|
|
4568
|
+
await execFileAsync("git", args, { cwd, env });
|
|
4477
4569
|
}
|
|
4478
4570
|
async function resolveInitBaseBranch(gitRoot, fallback) {
|
|
4479
4571
|
let current = null;
|
|
@@ -4495,6 +4587,47 @@ async function resolveInitBaseBranch(gitRoot, fallback) {
|
|
|
4495
4587
|
}
|
|
4496
4588
|
return fallback;
|
|
4497
4589
|
}
|
|
4590
|
+
async function promptInitBaseBranch(opts) {
|
|
4591
|
+
const branches = await gitListBranches(opts.gitRoot);
|
|
4592
|
+
let current = null;
|
|
4593
|
+
try {
|
|
4594
|
+
current = await gitCurrentBranch(opts.gitRoot);
|
|
4595
|
+
}
|
|
4596
|
+
catch {
|
|
4597
|
+
current = null;
|
|
4598
|
+
}
|
|
4599
|
+
const promptNewBranch = async (hasBranches) => {
|
|
4600
|
+
const raw = await promptInput(`Enter new base branch name (default ${opts.fallback}): `);
|
|
4601
|
+
const candidate = raw.trim() || opts.fallback;
|
|
4602
|
+
if (!candidate) {
|
|
4603
|
+
throw new CliError({
|
|
4604
|
+
exitCode: 2,
|
|
4605
|
+
code: "E_USAGE",
|
|
4606
|
+
message: "Base branch name cannot be empty",
|
|
4607
|
+
});
|
|
4608
|
+
}
|
|
4609
|
+
if (await gitBranchExists(opts.gitRoot, candidate))
|
|
4610
|
+
return candidate;
|
|
4611
|
+
try {
|
|
4612
|
+
await execFileAsync("git", hasBranches ? ["branch", candidate] : ["checkout", "-q", "-b", candidate], { cwd: opts.gitRoot, env: gitEnv() });
|
|
4613
|
+
}
|
|
4614
|
+
catch (err) {
|
|
4615
|
+
const message = err instanceof Error ? err.message : `Failed to create branch ${candidate}`;
|
|
4616
|
+
throw new CliError({ exitCode: 5, code: "E_GIT", message });
|
|
4617
|
+
}
|
|
4618
|
+
return candidate;
|
|
4619
|
+
};
|
|
4620
|
+
if (branches.length === 0) {
|
|
4621
|
+
return await promptNewBranch(false);
|
|
4622
|
+
}
|
|
4623
|
+
const createLabel = "Create new branch";
|
|
4624
|
+
const defaultChoice = current && branches.includes(current) ? current : (branches[0] ?? opts.fallback);
|
|
4625
|
+
const choice = await promptChoice("Select base branch", [...branches, createLabel], defaultChoice);
|
|
4626
|
+
if (choice === createLabel) {
|
|
4627
|
+
return await promptNewBranch(true);
|
|
4628
|
+
}
|
|
4629
|
+
return choice;
|
|
4630
|
+
}
|
|
4498
4631
|
async function ensureInitCommit(opts) {
|
|
4499
4632
|
const stagedBefore = await gitStagedPaths(opts.gitRoot);
|
|
4500
4633
|
if (stagedBefore.length > 0) {
|
|
@@ -4515,7 +4648,7 @@ async function ensureInitCommit(opts) {
|
|
|
4515
4648
|
if (staged.length === 0)
|
|
4516
4649
|
return;
|
|
4517
4650
|
const message = `chore: install agentplane ${opts.version}`;
|
|
4518
|
-
await gitCommit(opts.gitRoot, message);
|
|
4651
|
+
await gitCommit(opts.gitRoot, message, { skipHooks: opts.skipHooks });
|
|
4519
4652
|
}
|
|
4520
4653
|
function toGitPath(filePath) {
|
|
4521
4654
|
return filePath.split(path.sep).join("/");
|
|
@@ -6935,26 +7068,111 @@ function setMarkdownSection(body, section, text) {
|
|
|
6935
7068
|
const out = [...lines.slice(0, start + 1), ...replacement, ...lines.slice(nextHeading)];
|
|
6936
7069
|
return `${out.join("\n")}\n`;
|
|
6937
7070
|
}
|
|
7071
|
+
function normalizeDocSectionName(section) {
|
|
7072
|
+
return section.trim().replaceAll(/\s+/g, " ").toLowerCase();
|
|
7073
|
+
}
|
|
7074
|
+
function splitCombinedHeadingLines(doc) {
|
|
7075
|
+
const lines = doc.replaceAll("\r\n", "\n").split("\n");
|
|
7076
|
+
const out = [];
|
|
7077
|
+
let inFence = false;
|
|
7078
|
+
for (const line of lines) {
|
|
7079
|
+
const trimmed = line.trimStart();
|
|
7080
|
+
if (trimmed.startsWith("```")) {
|
|
7081
|
+
inFence = !inFence;
|
|
7082
|
+
out.push(line);
|
|
7083
|
+
continue;
|
|
7084
|
+
}
|
|
7085
|
+
if (!inFence && line.includes("## ")) {
|
|
7086
|
+
const matches = [...line.matchAll(/##\s+/g)];
|
|
7087
|
+
if (matches.length > 1 && matches[0]?.index === 0) {
|
|
7088
|
+
let start = 0;
|
|
7089
|
+
for (let i = 1; i < matches.length; i += 1) {
|
|
7090
|
+
const idx = matches[i]?.index ?? 0;
|
|
7091
|
+
const chunk = line.slice(start, idx).trimEnd();
|
|
7092
|
+
if (chunk)
|
|
7093
|
+
out.push(chunk);
|
|
7094
|
+
start = idx;
|
|
7095
|
+
}
|
|
7096
|
+
const last = line.slice(start).trimEnd();
|
|
7097
|
+
if (last)
|
|
7098
|
+
out.push(last);
|
|
7099
|
+
continue;
|
|
7100
|
+
}
|
|
7101
|
+
}
|
|
7102
|
+
out.push(line);
|
|
7103
|
+
}
|
|
7104
|
+
return out;
|
|
7105
|
+
}
|
|
7106
|
+
function normalizeDocSections(doc, required) {
|
|
7107
|
+
const lines = splitCombinedHeadingLines(doc);
|
|
7108
|
+
const sections = new Map();
|
|
7109
|
+
const order = [];
|
|
7110
|
+
const pendingSeparator = new Set();
|
|
7111
|
+
let currentKey = null;
|
|
7112
|
+
for (const line of lines) {
|
|
7113
|
+
const match = /^##\s+(.*)$/.exec(line.trim());
|
|
7114
|
+
if (match) {
|
|
7115
|
+
const title = match[1]?.trim() ?? "";
|
|
7116
|
+
const key = normalizeDocSectionName(title);
|
|
7117
|
+
if (key) {
|
|
7118
|
+
const existing = sections.get(key);
|
|
7119
|
+
if (existing) {
|
|
7120
|
+
if (existing.lines.some((entry) => entry.trim() !== "")) {
|
|
7121
|
+
pendingSeparator.add(key);
|
|
7122
|
+
}
|
|
7123
|
+
}
|
|
7124
|
+
else {
|
|
7125
|
+
sections.set(key, { title, lines: [] });
|
|
7126
|
+
order.push(key);
|
|
7127
|
+
}
|
|
7128
|
+
currentKey = key;
|
|
7129
|
+
continue;
|
|
7130
|
+
}
|
|
7131
|
+
}
|
|
7132
|
+
if (currentKey) {
|
|
7133
|
+
const entry = sections.get(currentKey);
|
|
7134
|
+
if (!entry)
|
|
7135
|
+
continue;
|
|
7136
|
+
if (pendingSeparator.has(currentKey) && line.trim() !== "") {
|
|
7137
|
+
entry.lines.push("");
|
|
7138
|
+
pendingSeparator.delete(currentKey);
|
|
7139
|
+
}
|
|
7140
|
+
entry.lines.push(line);
|
|
7141
|
+
}
|
|
7142
|
+
}
|
|
7143
|
+
const out = [];
|
|
7144
|
+
const seen = new Set(order);
|
|
7145
|
+
for (const key of order) {
|
|
7146
|
+
const section = sections.get(key);
|
|
7147
|
+
if (!section)
|
|
7148
|
+
continue;
|
|
7149
|
+
out.push(`## ${section.title}`);
|
|
7150
|
+
if (section.lines.length > 0) {
|
|
7151
|
+
out.push(...section.lines);
|
|
7152
|
+
}
|
|
7153
|
+
else {
|
|
7154
|
+
out.push("");
|
|
7155
|
+
}
|
|
7156
|
+
out.push("");
|
|
7157
|
+
}
|
|
7158
|
+
for (const requiredSection of required) {
|
|
7159
|
+
const requiredKey = normalizeDocSectionName(requiredSection);
|
|
7160
|
+
if (seen.has(requiredKey))
|
|
7161
|
+
continue;
|
|
7162
|
+
out.push(`## ${requiredSection}`, "", "");
|
|
7163
|
+
}
|
|
7164
|
+
return `${out.join("\n").trimEnd()}\n`;
|
|
7165
|
+
}
|
|
6938
7166
|
function ensureDocSections(doc, required) {
|
|
6939
7167
|
const trimmed = doc.trim();
|
|
6940
7168
|
if (!trimmed) {
|
|
6941
7169
|
const blocks = required.map((section) => `## ${section}\n`);
|
|
6942
7170
|
return `${blocks.join("\n").trimEnd()}\n`;
|
|
6943
7171
|
}
|
|
6944
|
-
|
|
6945
|
-
for (const section of required) {
|
|
6946
|
-
const needle = `## ${section}`;
|
|
6947
|
-
if (!out.split("\n").some((line) => line.trim() === needle)) {
|
|
6948
|
-
out = `${out.trimEnd()}\n\n${needle}\n`;
|
|
6949
|
-
}
|
|
6950
|
-
}
|
|
6951
|
-
return out.endsWith("\n") ? out : `${out}\n`;
|
|
6952
|
-
}
|
|
6953
|
-
function normalizeDocSectionName(section) {
|
|
6954
|
-
return section.trim().replaceAll(/\s+/g, " ").toLowerCase();
|
|
7172
|
+
return normalizeDocSections(doc, required);
|
|
6955
7173
|
}
|
|
6956
7174
|
function parseDocSections(doc) {
|
|
6957
|
-
const lines = doc
|
|
7175
|
+
const lines = splitCombinedHeadingLines(doc);
|
|
6958
7176
|
const sections = new Map();
|
|
6959
7177
|
const order = [];
|
|
6960
7178
|
let currentKey = null;
|
|
@@ -7098,9 +7316,17 @@ async function cmdTaskDocSet(opts) {
|
|
|
7098
7316
|
message: usageMessage(TASK_DOC_SET_USAGE, TASK_DOC_SET_USAGE_EXAMPLE),
|
|
7099
7317
|
});
|
|
7100
7318
|
}
|
|
7101
|
-
|
|
7102
|
-
if (updatedBy
|
|
7103
|
-
|
|
7319
|
+
let updatedBy;
|
|
7320
|
+
if (flags.updatedBy !== undefined) {
|
|
7321
|
+
const trimmed = flags.updatedBy.trim();
|
|
7322
|
+
if (trimmed.length === 0) {
|
|
7323
|
+
throw new CliError({
|
|
7324
|
+
exitCode: 2,
|
|
7325
|
+
code: "E_USAGE",
|
|
7326
|
+
message: "--updated-by must be non-empty",
|
|
7327
|
+
});
|
|
7328
|
+
}
|
|
7329
|
+
updatedBy = trimmed;
|
|
7104
7330
|
}
|
|
7105
7331
|
let text = flags.text ?? "";
|
|
7106
7332
|
if (hasFile) {
|
|
@@ -7164,7 +7390,8 @@ async function cmdTaskDocSet(opts) {
|
|
|
7164
7390
|
}
|
|
7165
7391
|
}
|
|
7166
7392
|
const nextDoc = setMarkdownSection(baseDoc, flags.section, nextText);
|
|
7167
|
-
|
|
7393
|
+
const normalized = ensureDocSections(nextDoc, config.tasks.doc.required_sections);
|
|
7394
|
+
await backend.setTaskDoc(opts.taskId, normalized, updatedBy);
|
|
7168
7395
|
}
|
|
7169
7396
|
const tasksDir = path.join(resolved.gitRoot, config.paths.workflow_dir);
|
|
7170
7397
|
process.stdout.write(`${path.join(tasksDir, opts.taskId, "README.md")}\n`);
|
|
@@ -7234,6 +7461,11 @@ export async function runCli(argv) {
|
|
|
7234
7461
|
return 0;
|
|
7235
7462
|
}
|
|
7236
7463
|
await maybeLoadDotEnv({ cwd: process.cwd(), rootOverride: globals.root });
|
|
7464
|
+
await maybeWarnOnUpdate({
|
|
7465
|
+
currentVersion: getVersion(),
|
|
7466
|
+
skip: globals.noUpdateCheck,
|
|
7467
|
+
jsonErrors: globals.jsonErrors,
|
|
7468
|
+
});
|
|
7237
7469
|
const [namespace, command, ...args] = rest;
|
|
7238
7470
|
if (namespace === "init") {
|
|
7239
7471
|
const initArgs = command ? [command, ...args] : [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-cli.test-helpers.d.ts","sourceRoot":"","sources":["../src/run-cli.test-helpers.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"run-cli.test-helpers.d.ts","sourceRoot":"","sources":["../src/run-cli.test-helpers.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAkCpD,wBAAgB,sBAAsB,IAAI,IAAI,CAsB7C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAEjD;AAED,wBAAgB,YAAY;;;;EAgC3B;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAKrD;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAEjD;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKpE;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,IAAI,CAAC,CAKhE;AAED,wBAAsB,mBAAmB,CAAC,IAAI,CAAC,EAAE;IAC/C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CA+FtE;AAED,wBAAsB,+BAA+B,CAAC,IAAI,EAAE;IAC1D,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBlB;AAED,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAiBD;AAED,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAI7E;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlE;AAED,wBAAgB,WAAW,IAAI,MAAM,CAAC,UAAU,CAS/C;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYpF;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG5E;AAED,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIzE"}
|
|
@@ -9,6 +9,7 @@ import { defaultConfig } from "@agentplaneorg/core";
|
|
|
9
9
|
const execFileAsync = promisify(execFile);
|
|
10
10
|
let agentplaneHome = null;
|
|
11
11
|
const originalAgentplaneHome = process.env.AGENTPLANE_HOME;
|
|
12
|
+
const originalNoUpdateCheck = process.env.AGENTPLANE_NO_UPDATE_CHECK;
|
|
12
13
|
const recipeArchiveCache = new Map();
|
|
13
14
|
let gitTemplateRoot = null;
|
|
14
15
|
let gitTemplatePromise = null;
|
|
@@ -31,6 +32,7 @@ export function registerAgentplaneHome() {
|
|
|
31
32
|
beforeAll(async () => {
|
|
32
33
|
agentplaneHome = await mkdtemp(path.join(os.tmpdir(), "agentplane-home-"));
|
|
33
34
|
process.env.AGENTPLANE_HOME = agentplaneHome;
|
|
35
|
+
process.env.AGENTPLANE_NO_UPDATE_CHECK = "1";
|
|
34
36
|
});
|
|
35
37
|
afterAll(async () => {
|
|
36
38
|
if (agentplaneHome) {
|
|
@@ -42,6 +44,12 @@ export function registerAgentplaneHome() {
|
|
|
42
44
|
else {
|
|
43
45
|
process.env.AGENTPLANE_HOME = originalAgentplaneHome;
|
|
44
46
|
}
|
|
47
|
+
if (originalNoUpdateCheck === undefined) {
|
|
48
|
+
delete process.env.AGENTPLANE_NO_UPDATE_CHECK;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
process.env.AGENTPLANE_NO_UPDATE_CHECK = originalNoUpdateCheck;
|
|
52
|
+
}
|
|
45
53
|
});
|
|
46
54
|
}
|
|
47
55
|
export function getAgentplaneHome() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-backend.d.ts","sourceRoot":"","sources":["../src/task-backend.ts"],"names":[],"mappings":"AAIA,OAAO,EAOL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"task-backend.d.ts","sourceRoot":"","sources":["../src/task-backend.ts"],"names":[],"mappings":"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"}
|
package/dist/task-backend.js
CHANGED
|
@@ -6,6 +6,7 @@ import { loadDotEnv } from "./env.js";
|
|
|
6
6
|
const ID_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
7
7
|
const TASK_ID_RE = new RegExp(String.raw `^\d{12}-[${ID_ALPHABET}]{4,}$`);
|
|
8
8
|
const DOC_SECTION_HEADER = "## Summary";
|
|
9
|
+
const DOC_SECTION_HEADER_RE = /^##\s+Summary(?:\s|$|#)/;
|
|
9
10
|
const AUTO_SUMMARY_HEADER = "## Changes Summary (auto)";
|
|
10
11
|
const DEFAULT_DOC_UPDATED_BY = "agentplane";
|
|
11
12
|
const DOC_VERSION = 2;
|
|
@@ -49,19 +50,70 @@ function ensureDocMetadata(task, updatedBy) {
|
|
|
49
50
|
task.doc_updated_at = nowIso();
|
|
50
51
|
task.doc_updated_by = updatedBy ?? DEFAULT_DOC_UPDATED_BY;
|
|
51
52
|
}
|
|
53
|
+
function lastCommentAuthor(comments) {
|
|
54
|
+
if (!Array.isArray(comments))
|
|
55
|
+
return null;
|
|
56
|
+
const entries = comments;
|
|
57
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
58
|
+
const entry = entries[i];
|
|
59
|
+
if (!isRecord(entry))
|
|
60
|
+
continue;
|
|
61
|
+
const author = entry.author;
|
|
62
|
+
if (typeof author === "string") {
|
|
63
|
+
const trimmed = author.trim();
|
|
64
|
+
if (trimmed)
|
|
65
|
+
return trimmed;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
function resolveDocUpdatedByFromFrontmatter(frontmatter, updatedBy, fallback) {
|
|
71
|
+
if (updatedBy !== undefined) {
|
|
72
|
+
const trimmed = updatedBy.trim();
|
|
73
|
+
return trimmed.length > 0 ? trimmed : fallback;
|
|
74
|
+
}
|
|
75
|
+
const author = lastCommentAuthor(frontmatter.comments);
|
|
76
|
+
if (author)
|
|
77
|
+
return author;
|
|
78
|
+
const existing = frontmatter.doc_updated_by;
|
|
79
|
+
if (typeof existing === "string") {
|
|
80
|
+
const trimmed = existing.trim();
|
|
81
|
+
if (trimmed)
|
|
82
|
+
return trimmed;
|
|
83
|
+
}
|
|
84
|
+
return fallback;
|
|
85
|
+
}
|
|
86
|
+
function resolveDocUpdatedByFromTask(task, fallback) {
|
|
87
|
+
const author = lastCommentAuthor(task.comments);
|
|
88
|
+
if (author)
|
|
89
|
+
return author;
|
|
90
|
+
const existing = task.doc_updated_by;
|
|
91
|
+
if (typeof existing === "string") {
|
|
92
|
+
const trimmed = existing.trim();
|
|
93
|
+
if (trimmed)
|
|
94
|
+
return trimmed;
|
|
95
|
+
}
|
|
96
|
+
return fallback;
|
|
97
|
+
}
|
|
98
|
+
function isDocSectionHeader(line) {
|
|
99
|
+
return DOC_SECTION_HEADER_RE.test(line.trim());
|
|
100
|
+
}
|
|
52
101
|
export function extractTaskDoc(body) {
|
|
53
102
|
if (!body)
|
|
54
103
|
return "";
|
|
55
104
|
const lines = body.split("\n");
|
|
56
105
|
let startIdx = null;
|
|
57
106
|
for (const [idx, line] of lines.entries()) {
|
|
58
|
-
if (line
|
|
107
|
+
if (isDocSectionHeader(line)) {
|
|
59
108
|
startIdx = idx;
|
|
60
109
|
break;
|
|
61
110
|
}
|
|
62
111
|
}
|
|
63
112
|
if (startIdx === null)
|
|
64
113
|
return "";
|
|
114
|
+
if (lines[startIdx]?.trim() !== DOC_SECTION_HEADER) {
|
|
115
|
+
lines[startIdx] = DOC_SECTION_HEADER;
|
|
116
|
+
}
|
|
65
117
|
let endIdx = lines.length;
|
|
66
118
|
for (let idx = startIdx + 1; idx < lines.length; idx++) {
|
|
67
119
|
if (lines[idx]?.trim() === AUTO_SUMMARY_HEADER) {
|
|
@@ -77,7 +129,7 @@ export function mergeTaskDoc(body, doc) {
|
|
|
77
129
|
const lines = body ? body.split("\n") : [];
|
|
78
130
|
let prefixIdx = null;
|
|
79
131
|
for (const [idx, line] of lines.entries()) {
|
|
80
|
-
if (line
|
|
132
|
+
if (isDocSectionHeader(line)) {
|
|
81
133
|
prefixIdx = idx;
|
|
82
134
|
break;
|
|
83
135
|
}
|
|
@@ -383,7 +435,7 @@ export class LocalBackend {
|
|
|
383
435
|
if (docChanged(existingDoc, docText)) {
|
|
384
436
|
payload.doc_version = DOC_VERSION;
|
|
385
437
|
payload.doc_updated_at = nowIso();
|
|
386
|
-
payload.doc_updated_by = this.updatedBy;
|
|
438
|
+
payload.doc_updated_by = resolveDocUpdatedByFromTask(task, this.updatedBy);
|
|
387
439
|
}
|
|
388
440
|
}
|
|
389
441
|
if (payload.doc_version !== DOC_VERSION) {
|
|
@@ -409,7 +461,7 @@ export class LocalBackend {
|
|
|
409
461
|
if (docChanged(extractTaskDoc(parsed.body), docText) || !frontmatter.doc_updated_at) {
|
|
410
462
|
frontmatter.doc_version = DOC_VERSION;
|
|
411
463
|
frontmatter.doc_updated_at = nowIso();
|
|
412
|
-
frontmatter.doc_updated_by = updatedBy
|
|
464
|
+
frontmatter.doc_updated_by = resolveDocUpdatedByFromFrontmatter(frontmatter, updatedBy, this.updatedBy);
|
|
413
465
|
}
|
|
414
466
|
if (frontmatter.doc_version !== DOC_VERSION) {
|
|
415
467
|
frontmatter.doc_version = DOC_VERSION;
|
|
@@ -424,7 +476,7 @@ export class LocalBackend {
|
|
|
424
476
|
const frontmatter = { ...parsed.frontmatter };
|
|
425
477
|
frontmatter.doc_version = DOC_VERSION;
|
|
426
478
|
frontmatter.doc_updated_at = nowIso();
|
|
427
|
-
frontmatter.doc_updated_by = updatedBy
|
|
479
|
+
frontmatter.doc_updated_by = resolveDocUpdatedByFromFrontmatter(frontmatter, updatedBy, this.updatedBy);
|
|
428
480
|
const next = renderTaskReadme(frontmatter, parsed.body || "");
|
|
429
481
|
await writeFile(readme, next.endsWith("\n") ? next : `${next}\n`, "utf8");
|
|
430
482
|
}
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentplane",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Agent Plane CLI for task workflows, recipes, and project automation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentplane",
|
|
@@ -54,6 +54,6 @@
|
|
|
54
54
|
"prepublishOnly": "npm run prepack"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@agentplaneorg/core": "0.1.
|
|
57
|
+
"@agentplaneorg/core": "0.1.3"
|
|
58
58
|
}
|
|
59
59
|
}
|