agentplane 0.2.19 → 0.2.21
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/assets/AGENTS.md +4 -3
- package/bin/agentplane.js +24 -0
- package/dist/backends/task-backend/load.d.ts +2 -0
- package/dist/backends/task-backend/load.d.ts.map +1 -1
- package/dist/backends/task-backend/load.js +38 -18
- package/dist/cli/command-guide.d.ts.map +1 -1
- package/dist/cli/command-guide.js +12 -11
- 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/command-catalog.js +12 -1
- package/dist/cli/run-cli/commands/core.d.ts +9 -1
- package/dist/cli/run-cli/commands/core.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/core.js +268 -8
- package/dist/cli/run-cli/commands/init/write-config.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-config.js +2 -0
- package/dist/cli/run-cli/commands/init/write-gitignore.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-gitignore.js +3 -18
- package/dist/cli/run-cli/commands/init.d.ts +1 -0
- package/dist/cli/run-cli/commands/init.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init.js +55 -30
- package/dist/cli/run-cli.d.ts.map +1 -1
- package/dist/cli/run-cli.js +85 -14
- package/dist/commands/commit.command.d.ts.map +1 -1
- package/dist/commands/commit.command.js +2 -0
- package/dist/commands/commit.spec.d.ts +2 -0
- package/dist/commands/commit.spec.d.ts.map +1 -1
- package/dist/commands/commit.spec.js +26 -0
- package/dist/commands/doctor.run.d.ts.map +1 -1
- package/dist/commands/doctor.run.js +15 -6
- package/dist/commands/finish.run.d.ts.map +1 -1
- package/dist/commands/finish.run.js +2 -0
- package/dist/commands/finish.spec.d.ts +2 -0
- package/dist/commands/finish.spec.d.ts.map +1 -1
- package/dist/commands/finish.spec.js +36 -0
- package/dist/commands/guard/impl/allow.d.ts.map +1 -1
- package/dist/commands/guard/impl/allow.js +33 -7
- package/dist/commands/guard/impl/commands.d.ts +2 -0
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +24 -4
- package/dist/commands/guard/impl/comment-commit.d.ts +1 -0
- package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
- package/dist/commands/guard/impl/comment-commit.js +16 -24
- package/dist/commands/release/apply.command.d.ts.map +1 -1
- package/dist/commands/release/apply.command.js +51 -3
- package/dist/commands/release/plan.command.d.ts.map +1 -1
- package/dist/commands/release/plan.command.js +25 -1
- package/dist/commands/shared/task-backend.d.ts +3 -0
- package/dist/commands/shared/task-backend.d.ts.map +1 -1
- package/dist/commands/shared/task-backend.js +4 -1
- package/dist/commands/task/block.d.ts.map +1 -1
- package/dist/commands/task/block.js +12 -9
- package/dist/commands/task/close-duplicate.command.d.ts +14 -0
- package/dist/commands/task/close-duplicate.command.d.ts.map +1 -0
- package/dist/commands/task/close-duplicate.command.js +102 -0
- package/dist/commands/task/close-duplicate.d.ts +14 -0
- package/dist/commands/task/close-duplicate.d.ts.map +1 -0
- package/dist/commands/task/close-duplicate.js +90 -0
- package/dist/commands/task/close-noop.command.d.ts +14 -0
- package/dist/commands/task/close-noop.command.d.ts.map +1 -0
- package/dist/commands/task/close-noop.command.js +77 -0
- package/dist/commands/task/close-noop.d.ts +13 -0
- package/dist/commands/task/close-noop.d.ts.map +1 -0
- package/dist/commands/task/close-noop.js +77 -0
- package/dist/commands/task/finish.d.ts +2 -0
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +52 -10
- package/dist/commands/task/index.d.ts +3 -0
- package/dist/commands/task/index.d.ts.map +1 -1
- package/dist/commands/task/index.js +3 -0
- package/dist/commands/task/new.d.ts.map +1 -1
- package/dist/commands/task/new.js +34 -6
- package/dist/commands/task/new.spec.js +1 -1
- package/dist/commands/task/plan.d.ts.map +1 -1
- package/dist/commands/task/plan.js +2 -3
- package/dist/commands/task/set-status.d.ts.map +1 -1
- package/dist/commands/task/set-status.js +12 -9
- package/dist/commands/task/shared.d.ts +19 -0
- package/dist/commands/task/shared.d.ts.map +1 -1
- package/dist/commands/task/shared.js +137 -0
- package/dist/commands/task/start-ready.command.d.ts +14 -0
- package/dist/commands/task/start-ready.command.d.ts.map +1 -0
- package/dist/commands/task/start-ready.command.js +77 -0
- package/dist/commands/task/start-ready.d.ts +13 -0
- package/dist/commands/task/start-ready.d.ts.map +1 -0
- package/dist/commands/task/start-ready.js +46 -0
- package/dist/commands/task/start.d.ts.map +1 -1
- package/dist/commands/task/start.js +13 -11
- package/dist/commands/task/update.command.d.ts +1 -0
- package/dist/commands/task/update.command.d.ts.map +1 -1
- package/dist/commands/task/update.command.js +8 -0
- package/dist/commands/task/update.d.ts +1 -0
- package/dist/commands/task/update.d.ts.map +1 -1
- package/dist/commands/task/update.js +19 -3
- package/dist/shared/errors.d.ts +9 -1
- package/dist/shared/errors.d.ts.map +1 -1
- package/dist/shared/errors.js +3 -1
- package/dist/shared/runtime-artifacts.d.ts +3 -0
- package/dist/shared/runtime-artifacts.d.ts.map +1 -0
- package/dist/shared/runtime-artifacts.js +18 -0
- package/dist/usecases/context/resolve-context.d.ts +3 -0
- package/dist/usecases/context/resolve-context.d.ts.map +1 -1
- package/dist/usecases/context/resolve-context.js +6 -1
- package/package.json +2 -2
package/assets/AGENTS.md
CHANGED
|
@@ -425,7 +425,7 @@ If config sets `agents.approvals.require_plan=true`:
|
|
|
425
425
|
- `## Verify Steps` is the **ex-ante verification contract**: instructions and pass criteria addressed to the verifier.
|
|
426
426
|
- `## Verification` is the **ex-post verification log**: append-only entries written by `agentplane verify ...`.
|
|
427
427
|
- Do not hand-edit `## Verification` entries. Treat them as audit records.
|
|
428
|
-
- For tasks with verify-required tags (default: `code`, `
|
|
428
|
+
- For tasks with verify-required primary tags (default: `code`, `data`, `ops`) and for `spike`, `agentplane task plan approve`
|
|
429
429
|
will block until `## Verify Steps` is filled (the placeholder `<!-- TODO: FILL VERIFY STEPS -->` is treated as empty).
|
|
430
430
|
- Use `agentplane task verify-show <task-id>` to print the current `## Verify Steps` to stdout.
|
|
431
431
|
|
|
@@ -471,8 +471,9 @@ Use comment-driven flags (where supported by agentplane), e.g.:
|
|
|
471
471
|
|
|
472
472
|
In this mode:
|
|
473
473
|
|
|
474
|
-
- agentplane builds the commit subject as `<emoji> <suffix> <
|
|
475
|
-
-
|
|
474
|
+
- agentplane builds the commit subject as `<emoji> <suffix> <primary>: <status>` for major transitions only.
|
|
475
|
+
- major transitions for status/comment-driven commits: `TODO->DOING`, `DOING->BLOCKED`, `BLOCKED->DOING`, `DOING->DONE`.
|
|
476
|
+
- agentplane adds a short structured commit body (`Task` / `Primary` / `Status` / `Comment`) automatically for comment-driven commits.
|
|
476
477
|
|
|
477
478
|
## Commit subject format (enforced)
|
|
478
479
|
|
package/bin/agentplane.js
CHANGED
|
@@ -12,6 +12,29 @@ async function exists(p) {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
async function maybeWarnGlobalBinaryInRepoCheckout() {
|
|
16
|
+
const cwd = process.cwd();
|
|
17
|
+
const repoCli = path.join(cwd, "packages", "agentplane", "src", "cli.ts");
|
|
18
|
+
const repoBin = path.join(cwd, "packages", "agentplane", "bin", "agentplane.js");
|
|
19
|
+
if (!(await exists(repoCli)) || !(await exists(repoBin))) return;
|
|
20
|
+
|
|
21
|
+
const thisBin = fileURLToPath(import.meta.url);
|
|
22
|
+
const normalizedThis = path.resolve(thisBin);
|
|
23
|
+
const normalizedRepo = path.resolve(repoBin);
|
|
24
|
+
if (normalizedThis === normalizedRepo) return;
|
|
25
|
+
|
|
26
|
+
process.stderr.write(
|
|
27
|
+
"warning: running global agentplane binary inside repository checkout.\n" +
|
|
28
|
+
"using global binary: " +
|
|
29
|
+
normalizedThis +
|
|
30
|
+
"\n" +
|
|
31
|
+
"expected local binary: " +
|
|
32
|
+
normalizedRepo +
|
|
33
|
+
"\n" +
|
|
34
|
+
"tip: run `node packages/agentplane/bin/agentplane.js ...` for repo-local changes.\n",
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
15
38
|
function isTestLikePath(absPath) {
|
|
16
39
|
// The repo build does not emit test files to dist. If we treat test mtimes as
|
|
17
40
|
// "src is newer than dist", we can block normal commits that only change tests.
|
|
@@ -106,5 +129,6 @@ async function assertDistUpToDate() {
|
|
|
106
129
|
return true;
|
|
107
130
|
}
|
|
108
131
|
|
|
132
|
+
await maybeWarnGlobalBinaryInRepoCheckout();
|
|
109
133
|
const ok = await assertDistUpToDate();
|
|
110
134
|
if (ok) await import("../dist/cli.js");
|
|
@@ -3,6 +3,8 @@ import { type TaskBackend } from "./shared.js";
|
|
|
3
3
|
export declare function loadTaskBackend(opts: {
|
|
4
4
|
cwd: string;
|
|
5
5
|
rootOverride?: string | null;
|
|
6
|
+
resolvedProject?: ResolvedProject;
|
|
7
|
+
config?: AgentplaneConfig;
|
|
6
8
|
}): Promise<{
|
|
7
9
|
backend: TaskBackend;
|
|
8
10
|
backendId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../../src/backends/task-backend/load.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAC;AAO7B,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../../src/backends/task-backend/load.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAC;AAO7B,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAuF7D,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B,GAAG,OAAO,CAAC;IACV,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,eAAe,CAAC;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC,CAUD"}
|
|
@@ -18,6 +18,37 @@ async function loadBackendConfig(configPath) {
|
|
|
18
18
|
throw err;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
+
async function instantiateTaskBackend(opts) {
|
|
22
|
+
const backendConfigPath = path.join(opts.resolved.gitRoot, opts.config.tasks_backend.config_path);
|
|
23
|
+
const backendConfig = await loadBackendConfig(backendConfigPath);
|
|
24
|
+
const normalized = normalizeBackendConfig(backendConfig);
|
|
25
|
+
const backendId = normalized.id;
|
|
26
|
+
const settings = normalized.settings;
|
|
27
|
+
if (backendId === "redmine") {
|
|
28
|
+
await loadDotEnv(opts.resolved.gitRoot);
|
|
29
|
+
const cacheDirRaw = resolveMaybeRelative(opts.resolved.gitRoot, settings.cache_dir);
|
|
30
|
+
const cacheDir = cacheDirRaw ?? path.join(opts.resolved.gitRoot, opts.config.paths.workflow_dir);
|
|
31
|
+
const cache = cacheDir ? new LocalBackend({ dir: cacheDir }) : null;
|
|
32
|
+
const redmine = new RedmineBackend(settings, { cache });
|
|
33
|
+
return {
|
|
34
|
+
backend: redmine,
|
|
35
|
+
backendId,
|
|
36
|
+
resolved: opts.resolved,
|
|
37
|
+
config: opts.config,
|
|
38
|
+
backendConfigPath,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const localDir = resolveMaybeRelative(opts.resolved.gitRoot, settings.dir) ??
|
|
42
|
+
path.join(opts.resolved.gitRoot, opts.config.paths.workflow_dir);
|
|
43
|
+
const local = new LocalBackend({ dir: localDir });
|
|
44
|
+
return {
|
|
45
|
+
backend: local,
|
|
46
|
+
backendId: "local",
|
|
47
|
+
resolved: opts.resolved,
|
|
48
|
+
config: opts.config,
|
|
49
|
+
backendConfigPath,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
21
52
|
function resolveMaybeRelative(root, input) {
|
|
22
53
|
if (!input)
|
|
23
54
|
return null;
|
|
@@ -36,23 +67,12 @@ function normalizeBackendConfig(raw) {
|
|
|
36
67
|
return { id, version, settings };
|
|
37
68
|
}
|
|
38
69
|
export async function loadTaskBackend(opts) {
|
|
39
|
-
const resolved =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const normalized = normalizeBackendConfig(backendConfig);
|
|
44
|
-
const backendId = normalized.id;
|
|
45
|
-
const settings = normalized.settings;
|
|
46
|
-
if (backendId === "redmine") {
|
|
47
|
-
await loadDotEnv(resolved.gitRoot);
|
|
48
|
-
const cacheDirRaw = resolveMaybeRelative(resolved.gitRoot, settings.cache_dir);
|
|
49
|
-
const cacheDir = cacheDirRaw ?? path.join(resolved.gitRoot, loaded.config.paths.workflow_dir);
|
|
50
|
-
const cache = cacheDir ? new LocalBackend({ dir: cacheDir }) : null;
|
|
51
|
-
const redmine = new RedmineBackend(settings, { cache });
|
|
52
|
-
return { backend: redmine, backendId, resolved, config: loaded.config, backendConfigPath };
|
|
70
|
+
const resolved = opts.resolvedProject ??
|
|
71
|
+
(await resolveProject({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null }));
|
|
72
|
+
if (opts.config) {
|
|
73
|
+
return await instantiateTaskBackend({ resolved, config: opts.config });
|
|
53
74
|
}
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return { backend: local, backendId: "local", resolved, config: loaded.config, backendConfigPath };
|
|
75
|
+
const loadedConfig = await loadConfig(resolved.agentplaneDir);
|
|
76
|
+
const config = loadedConfig.config;
|
|
77
|
+
return await instantiateTaskBackend({ resolved, config });
|
|
58
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-guide.d.ts","sourceRoot":"","sources":["../../src/cli/command-guide.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"command-guide.d.ts","sourceRoot":"","sources":["../../src/cli/command-guide.ts"],"names":[],"mappings":"AAgMA,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAEpC;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CA8EzC"}
|
|
@@ -57,11 +57,11 @@ const CHEAT_SHEET_ROWS = [
|
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
operation: "INTEGRATOR: finish task(s)",
|
|
60
|
-
command: '`agentplane finish <task-id> [<task-id> ...] --commit <git-rev> --author INTEGRATOR --body "Verified: ..." [--result "<one line>"]`',
|
|
60
|
+
command: '`agentplane finish <task-id> [<task-id> ...] --commit <git-rev> --author INTEGRATOR --body "Verified: ..." [--result "<one line>"] [--close-commit] [--close-unstage-others]`',
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
63
|
operation: "INTEGRATOR: commit closure",
|
|
64
|
-
command: "`agentplane commit <task-id> --close`",
|
|
64
|
+
command: "Preferred: `agentplane finish <task-id> --close-commit` (single command). Legacy/manual: `agentplane commit <task-id> --close [--check-only] [--unstage-others]` / duplicate no-op close: `agentplane task close-duplicate <task-id> --of <canonical-task-id> --author <ROLE>`",
|
|
65
65
|
},
|
|
66
66
|
];
|
|
67
67
|
const ROLE_GUIDES = [
|
|
@@ -82,7 +82,7 @@ const ROLE_GUIDES = [
|
|
|
82
82
|
'- Update tasks: `agentplane task update <task-id> --title "..." --description "..." --priority med --owner <ROLE> --depends-on <task-id>`',
|
|
83
83
|
"- Scaffold artifacts: `agentplane task scaffold <task-id>`",
|
|
84
84
|
'- Plan lifecycle: `agentplane task plan set <task-id> --text "..." --updated-by <ROLE>` -> `agentplane task plan approve <task-id> --by <id>`',
|
|
85
|
-
"- Verify Steps discipline: if a task
|
|
85
|
+
"- Verify Steps discipline: if a task primary tag is verify-required (default: code/data/ops), fill `## Verify Steps` before plan approval.",
|
|
86
86
|
'- Task docs (when planning needs it): `agentplane task doc set <task-id> --section Summary --text "..."`',
|
|
87
87
|
],
|
|
88
88
|
},
|
|
@@ -95,7 +95,7 @@ const ROLE_GUIDES = [
|
|
|
95
95
|
"- Verify Steps: `agentplane task verify-show <task-id>` (use as the verification contract before recording results).",
|
|
96
96
|
'- Verify: `agentplane verify <task-id> --ok|--rework --by <ROLE> --note "..."`',
|
|
97
97
|
'- PR artifacts (branch_pr): `agentplane pr open <task-id> --branch task/<task-id>/<slug> --author <ROLE>` / `agentplane pr update <task-id>` / `agentplane pr note <task-id> --author <ROLE> --body "..."`',
|
|
98
|
-
'- Commit: `agentplane guard commit <task-id> -m "<emoji> <suffix> <scope>: <summary>"` / `agentplane commit <task-id> -m "<emoji> <suffix> <scope>: <summary>" --allow <path-prefix>` / close: `agentplane
|
|
98
|
+
'- Commit: `agentplane guard commit <task-id> -m "<emoji> <suffix> <scope>: <summary>"` / `agentplane commit <task-id> -m "<emoji> <suffix> <scope>: <summary>" --allow <path-prefix>` / preferred close path: `agentplane finish <task-id> --close-commit [--close-unstage-others]`',
|
|
99
99
|
],
|
|
100
100
|
},
|
|
101
101
|
{
|
|
@@ -107,7 +107,7 @@ const ROLE_GUIDES = [
|
|
|
107
107
|
"- Verify Steps: `agentplane task verify-show <task-id>` (treat as the verification contract).",
|
|
108
108
|
'- Verify: `agentplane verify <task-id> --ok|--rework --by <ROLE> --note "..."`',
|
|
109
109
|
'- PR artifacts (branch_pr): `agentplane pr open <task-id> --branch task/<task-id>/<slug> --author <ROLE>` / `agentplane pr update <task-id>` / `agentplane pr note <task-id> --author <ROLE> --body "..."`',
|
|
110
|
-
'- Commit: `agentplane guard commit <task-id> -m "<emoji> <suffix> <scope>: <summary>"` / `agentplane commit <task-id> -m "<emoji> <suffix> <scope>: <summary>" --allow <path-prefix>` / close: `agentplane
|
|
110
|
+
'- Commit: `agentplane guard commit <task-id> -m "<emoji> <suffix> <scope>: <summary>"` / `agentplane commit <task-id> -m "<emoji> <suffix> <scope>: <summary>" --allow <path-prefix>` / preferred close path: `agentplane finish <task-id> --close-commit [--close-unstage-others]`',
|
|
111
111
|
],
|
|
112
112
|
},
|
|
113
113
|
{
|
|
@@ -115,7 +115,7 @@ const ROLE_GUIDES = [
|
|
|
115
115
|
lines: [
|
|
116
116
|
'- Task docs: `agentplane task doc set <task-id> --section Summary --text "..."` (repeat per section or use `--file`)',
|
|
117
117
|
'- PR notes: `agentplane pr note <task-id> --author DOCS --body "..."`',
|
|
118
|
-
'- Commit: `agentplane guard commit <task-id> -m "<emoji> <suffix> <scope>: <summary>"` / `agentplane commit <task-id> -m "<emoji> <suffix> <scope>: <summary>" --allow <path-prefix>` / close: `agentplane
|
|
118
|
+
'- Commit: `agentplane guard commit <task-id> -m "<emoji> <suffix> <scope>: <summary>"` / `agentplane commit <task-id> -m "<emoji> <suffix> <scope>: <summary>" --allow <path-prefix>` / preferred close path: `agentplane finish <task-id> --close-commit [--close-unstage-others]`',
|
|
119
119
|
],
|
|
120
120
|
},
|
|
121
121
|
{
|
|
@@ -128,8 +128,8 @@ const ROLE_GUIDES = [
|
|
|
128
128
|
{
|
|
129
129
|
role: "INTEGRATOR",
|
|
130
130
|
lines: [
|
|
131
|
-
'- branch_pr: `agentplane pr check <task-id>` -> `agentplane integrate <task-id> --branch task/<task-id>/<slug> --merge-strategy squash --run-verify` -> `agentplane finish <task-id> --commit <git-rev> --author INTEGRATOR --body "Verified: ..."`',
|
|
132
|
-
'- direct: task owner uses `agentplane finish <task-id> --commit <git-rev> --author <OWNER> --body "Verified: ..."` after the implementation commit',
|
|
131
|
+
'- branch_pr: `agentplane pr check <task-id>` -> `agentplane integrate <task-id> --branch task/<task-id>/<slug> --merge-strategy squash --run-verify` -> `agentplane finish <task-id> --commit <git-rev> --author INTEGRATOR --body "Verified: ..." --close-commit`',
|
|
132
|
+
'- direct: task owner uses `agentplane finish <task-id> --commit <git-rev> --author <OWNER> --body "Verified: ..." --close-commit` after the implementation commit',
|
|
133
133
|
"- Optional cleanup: `agentplane cleanup merged --yes`",
|
|
134
134
|
],
|
|
135
135
|
},
|
|
@@ -205,7 +205,7 @@ export function renderQuickstart() {
|
|
|
205
205
|
'- `agentplane task new --title "..." --description "..." --priority med --owner CODER --tag <tag>`',
|
|
206
206
|
'- `agentplane start <task-id> --author <ROLE> --body "Start: ..."`',
|
|
207
207
|
'- `agentplane verify <task-id> --ok|--rework --by <ROLE> --note "..."`',
|
|
208
|
-
'- `agentplane finish <task-id> --author <ROLE> --body "Verified: ..."`',
|
|
208
|
+
'- `agentplane finish <task-id> --author <ROLE> --body "Verified: ..." --commit <git-rev> --close-commit`',
|
|
209
209
|
"",
|
|
210
210
|
"## Branch workflow (branch_pr)",
|
|
211
211
|
"",
|
|
@@ -233,7 +233,7 @@ export function renderQuickstart() {
|
|
|
233
233
|
"",
|
|
234
234
|
"- Show the current config: `agentplane config show`",
|
|
235
235
|
"- Set a value by dotted key: `agentplane config set workflow_mode branch_pr`",
|
|
236
|
-
'- Set JSON values (lists/objects): `agentplane config set tasks.verify.
|
|
236
|
+
'- Set JSON values (lists/objects): `agentplane config set tasks.verify.require_steps_for_primary \'["code","data","ops"]\'`',
|
|
237
237
|
"",
|
|
238
238
|
"## Role/phase command guide (when to use what)",
|
|
239
239
|
"",
|
|
@@ -258,6 +258,7 @@ export function renderQuickstart() {
|
|
|
258
258
|
"",
|
|
259
259
|
"Notes:",
|
|
260
260
|
"- `suffix` is the task ID segment after the last dash.",
|
|
261
|
-
"- When using comment-driven flags, the subject is auto-built as `<emoji> <suffix> <
|
|
261
|
+
"- When using comment-driven flags, the subject is auto-built as `<emoji> <suffix> <primary>: <status>` and only for major transitions (TODO->DOING, DOING->BLOCKED, BLOCKED->DOING, DOING->DONE).",
|
|
262
|
+
"- Comment-driven commit bodies are structured: `Task`, `Primary`, `Status`, `Comment`.",
|
|
262
263
|
].join("\n");
|
|
263
264
|
}
|
|
@@ -15,5 +15,5 @@ export type CommandEntry = {
|
|
|
15
15
|
needsConfig: boolean;
|
|
16
16
|
needsTaskContext: boolean;
|
|
17
17
|
};
|
|
18
|
-
export declare const COMMANDS: readonly [CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry];
|
|
18
|
+
export declare const COMMANDS: readonly [CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry, CommandEntry];
|
|
19
19
|
//# sourceMappingURL=command-catalog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-catalog.d.ts","sourceRoot":"","sources":["../../../src/cli/run-cli/command-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"command-catalog.d.ts","sourceRoot":"","sources":["../../../src/cli/run-cli/command-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAoGvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEzE,MAAM,MAAM,OAAO,GAAG;IACpB,MAAM,EAAE,CAAC,sBAAsB,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IACpE,kBAAkB,EAAE,CAAC,sBAAsB,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IACjF,eAAe,EAAE,CAAC,sBAAsB,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3E,kBAAkB,EAAE,MAAM,SAAS,QAAQ,EAAE,CAAC;CAC/C,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1D,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CAAC;AAgBF,eAAO,MAAM,QAAQ,iyCA2ZuB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { initSpec } from "./commands/init.js";
|
|
2
|
-
import { agentsSpec, quickstartSpec, roleSpec } from "./commands/core.js";
|
|
2
|
+
import { agentsSpec, preflightSpec, quickstartSpec, roleSpec } from "./commands/core.js";
|
|
3
3
|
import { configSetSpec, configShowSpec, modeGetSpec, modeSetSpec } from "./commands/config.js";
|
|
4
4
|
import { ideSyncSpec } from "./commands/ide.js";
|
|
5
5
|
import { taskNewSpec } from "../../commands/task/new.spec.js";
|
|
@@ -22,6 +22,9 @@ import { taskLintSpec } from "../../commands/task/lint.command.js";
|
|
|
22
22
|
import { taskMigrateSpec } from "../../commands/task/migrate.command.js";
|
|
23
23
|
import { taskMigrateDocSpec } from "../../commands/task/migrate-doc.command.js";
|
|
24
24
|
import { taskDeriveSpec } from "../../commands/task/derive.command.js";
|
|
25
|
+
import { taskCloseDuplicateSpec } from "../../commands/task/close-duplicate.command.js";
|
|
26
|
+
import { taskCloseNoopSpec } from "../../commands/task/close-noop.command.js";
|
|
27
|
+
import { taskStartReadySpec } from "../../commands/task/start-ready.command.js";
|
|
25
28
|
import { taskPlanSetSpec } from "../../commands/task/plan-set.command.js";
|
|
26
29
|
import { taskPlanApproveSpec } from "../../commands/task/plan-approve.command.js";
|
|
27
30
|
import { taskPlanRejectSpec } from "../../commands/task/plan-reject.command.js";
|
|
@@ -112,6 +115,11 @@ export const COMMANDS = [
|
|
|
112
115
|
needsConfig: false,
|
|
113
116
|
needsTaskContext: false,
|
|
114
117
|
}),
|
|
118
|
+
entry(preflightSpec, () => import("./commands/core.js").then((m) => m.runPreflight), {
|
|
119
|
+
needsProject: false,
|
|
120
|
+
needsConfig: false,
|
|
121
|
+
needsTaskContext: false,
|
|
122
|
+
}),
|
|
115
123
|
entry(roleSpec, () => import("./commands/core.js").then((m) => m.runRole), {
|
|
116
124
|
needsProject: false,
|
|
117
125
|
needsConfig: false,
|
|
@@ -158,6 +166,9 @@ export const COMMANDS = [
|
|
|
158
166
|
entry(taskShowSpec, (deps) => import("../../commands/task/show.run.js").then((m) => m.makeRunTaskShowHandler(deps.getCtx))),
|
|
159
167
|
entry(taskNewSpec, (deps) => import("../../commands/task/new.command.js").then((m) => m.makeRunTaskNewHandler(deps.getCtx))),
|
|
160
168
|
entry(taskDeriveSpec, (deps) => import("../../commands/task/derive.command.js").then((m) => m.makeRunTaskDeriveHandler(deps.getCtx))),
|
|
169
|
+
entry(taskCloseDuplicateSpec, (deps) => import("../../commands/task/close-duplicate.command.js").then((m) => m.makeRunTaskCloseDuplicateHandler(deps.getCtx))),
|
|
170
|
+
entry(taskStartReadySpec, (deps) => import("../../commands/task/start-ready.command.js").then((m) => m.makeRunTaskStartReadyHandler(deps.getCtx))),
|
|
171
|
+
entry(taskCloseNoopSpec, (deps) => import("../../commands/task/close-noop.command.js").then((m) => m.makeRunTaskCloseNoopHandler(deps.getCtx))),
|
|
161
172
|
entry(taskAddSpec, (deps) => import("../../commands/task/add.command.js").then((m) => m.makeRunTaskAddHandler(deps.getCtx))),
|
|
162
173
|
entry(taskUpdateSpec, (deps) => import("../../commands/task/update.command.js").then((m) => m.makeRunTaskUpdateHandler(deps.getCtx))),
|
|
163
174
|
entry(taskCommentSpec, (deps) => import("../../commands/task/comment.command.js").then((m) => m.makeRunTaskCommentHandler(deps.getCtx))),
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import type { CommandHandler, CommandSpec } from "../../spec/spec.js";
|
|
2
2
|
import type { RunDeps } from "../command-catalog.js";
|
|
3
|
-
type QuickstartParsed =
|
|
3
|
+
type QuickstartParsed = {
|
|
4
|
+
json: boolean;
|
|
5
|
+
};
|
|
4
6
|
export declare const quickstartSpec: CommandSpec<QuickstartParsed>;
|
|
5
7
|
export declare const runQuickstart: CommandHandler<QuickstartParsed>;
|
|
8
|
+
type PreflightParsed = {
|
|
9
|
+
json: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare const preflightSpec: CommandSpec<PreflightParsed>;
|
|
12
|
+
export declare const runPreflight: CommandHandler<PreflightParsed>;
|
|
6
13
|
type RoleParsed = {
|
|
7
14
|
role: string;
|
|
15
|
+
json: boolean;
|
|
8
16
|
};
|
|
9
17
|
export declare const roleSpec: CommandSpec<RoleParsed>;
|
|
10
18
|
export declare const runRole: CommandHandler<RoleParsed>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../../src/cli/run-cli/commands/core.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../../src/cli/run-cli/commands/core.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAIrD,KAAK,gBAAgB,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAE1C,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,gBAAgB,CAcxD,CAAC;AA6BF,eAAO,MAAM,aAAa,EAAE,cAAc,CAAC,gBAAgB,CAE1D,CAAC;AAEF,KAAK,eAAe,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AA0LzC,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,eAAe,CAgBtD,CAAC;AAsCF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,eAAe,CAExD,CAAC;AAEF,KAAK,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAElD,eAAO,MAAM,QAAQ,EAAE,WAAW,CAAC,UAAU,CAe5C,CAAC;AAoOF,eAAO,MAAM,OAAO,EAAE,cAAc,CAAC,UAAU,CAE9C,CAAC;AAEF,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAE1C,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC,YAAY,CAMhD,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,CAAC,YAAY,CAAC,CA0FhF"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { readdir, readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { resolveProject } from "@agentplaneorg/core";
|
|
3
|
+
import { loadConfig, resolveProject } from "@agentplaneorg/core";
|
|
4
|
+
import { loadTaskBackend } from "../../../backends/task-backend.js";
|
|
5
|
+
import { GitContext } from "../../../commands/shared/git-context.js";
|
|
6
|
+
import { gitCurrentBranch } from "../../../commands/shared/git-ops.js";
|
|
4
7
|
import { fileExists } from "../../fs-utils.js";
|
|
5
8
|
import { CliError } from "../../../shared/errors.js";
|
|
6
9
|
import { dedupeStrings } from "../../../shared/strings.js";
|
|
@@ -12,26 +15,256 @@ export const quickstartSpec = {
|
|
|
12
15
|
id: ["quickstart"],
|
|
13
16
|
group: "Core",
|
|
14
17
|
summary: "Print CLI quickstart and command cheat sheet.",
|
|
15
|
-
options: [
|
|
18
|
+
options: [
|
|
19
|
+
{
|
|
20
|
+
kind: "boolean",
|
|
21
|
+
name: "json",
|
|
22
|
+
default: false,
|
|
23
|
+
description: "Emit compact machine-readable output for agent runtimes.",
|
|
24
|
+
},
|
|
25
|
+
],
|
|
16
26
|
examples: [{ cmd: "agentplane quickstart", why: "Show quickstart." }],
|
|
17
|
-
parse: () => ({}),
|
|
27
|
+
parse: (raw) => ({ json: raw.opts.json === true }),
|
|
18
28
|
};
|
|
19
29
|
async function cmdQuickstart(opts) {
|
|
20
30
|
return wrapCommand({ command: "quickstart", rootOverride: opts.rootOverride }, () => {
|
|
21
|
-
|
|
31
|
+
const text = renderQuickstart();
|
|
32
|
+
if (opts.json) {
|
|
33
|
+
const lines = text
|
|
34
|
+
.split("\n")
|
|
35
|
+
.map((line) => line.trim())
|
|
36
|
+
.filter((line) => line.length > 0);
|
|
37
|
+
const payload = {
|
|
38
|
+
source_of_truth: {
|
|
39
|
+
workflow_policy: "AGENTS.md",
|
|
40
|
+
cli_syntax: "quickstart/role output",
|
|
41
|
+
},
|
|
42
|
+
lines,
|
|
43
|
+
};
|
|
44
|
+
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
process.stdout.write(`${text}\n`);
|
|
22
48
|
return 0;
|
|
23
49
|
});
|
|
24
50
|
}
|
|
25
|
-
export const runQuickstart = (ctx) => {
|
|
26
|
-
return cmdQuickstart({ cwd: ctx.cwd, rootOverride: ctx.rootOverride });
|
|
51
|
+
export const runQuickstart = (ctx, p) => {
|
|
52
|
+
return cmdQuickstart({ cwd: ctx.cwd, rootOverride: ctx.rootOverride, json: p.json });
|
|
53
|
+
};
|
|
54
|
+
function compactError(err) {
|
|
55
|
+
if (err instanceof Error) {
|
|
56
|
+
const first = (err.message ?? "").split("\n", 1)[0] ?? "";
|
|
57
|
+
return first.trim() || err.name;
|
|
58
|
+
}
|
|
59
|
+
return String(err);
|
|
60
|
+
}
|
|
61
|
+
function probeYesNo(probe) {
|
|
62
|
+
return probe.ok ? "yes" : "no";
|
|
63
|
+
}
|
|
64
|
+
function probeValueOrUnknown(probe) {
|
|
65
|
+
return probe.ok && probe.value !== undefined ? String(probe.value) : "unknown";
|
|
66
|
+
}
|
|
67
|
+
function inferWorkflowMode(config) {
|
|
68
|
+
if (!config)
|
|
69
|
+
return "unknown";
|
|
70
|
+
return config.workflow_mode === "direct" || config.workflow_mode === "branch_pr"
|
|
71
|
+
? config.workflow_mode
|
|
72
|
+
: "unknown";
|
|
73
|
+
}
|
|
74
|
+
function inferApprovals(config) {
|
|
75
|
+
if (!config) {
|
|
76
|
+
return {
|
|
77
|
+
require_plan: "unknown",
|
|
78
|
+
require_verify: "unknown",
|
|
79
|
+
require_network: "unknown",
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const approvals = config.agents?.approvals;
|
|
83
|
+
if (!approvals) {
|
|
84
|
+
return {
|
|
85
|
+
require_plan: "unknown",
|
|
86
|
+
require_verify: "unknown",
|
|
87
|
+
require_network: "unknown",
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
require_plan: approvals.require_plan,
|
|
92
|
+
require_verify: approvals.require_verify,
|
|
93
|
+
require_network: approvals.require_network,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async function buildPreflightReport(opts) {
|
|
97
|
+
const nextActions = [];
|
|
98
|
+
const quickstartText = renderQuickstart();
|
|
99
|
+
const quickstartLoaded = {
|
|
100
|
+
ok: quickstartText.trim().length > 0,
|
|
101
|
+
error: quickstartText.trim().length > 0 ? undefined : "quickstart renderer returned empty output",
|
|
102
|
+
};
|
|
103
|
+
let resolved = null;
|
|
104
|
+
try {
|
|
105
|
+
resolved = await resolveProject({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null });
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
nextActions.push({
|
|
109
|
+
command: "agentplane init",
|
|
110
|
+
reason: `project not resolved (${compactError(err)})`,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
let config = null;
|
|
114
|
+
let configLoaded = { ok: false, error: "project not resolved" };
|
|
115
|
+
if (resolved) {
|
|
116
|
+
try {
|
|
117
|
+
const loaded = await loadConfig(resolved.agentplaneDir);
|
|
118
|
+
config = loaded.config;
|
|
119
|
+
configLoaded = { ok: true };
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
const message = compactError(err);
|
|
123
|
+
configLoaded = { ok: false, error: message };
|
|
124
|
+
nextActions.push({
|
|
125
|
+
command: "agentplane config show",
|
|
126
|
+
reason: `config failed validation (${message})`,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
let taskListLoaded = {
|
|
131
|
+
ok: false,
|
|
132
|
+
error: "project not resolved",
|
|
133
|
+
};
|
|
134
|
+
if (resolved) {
|
|
135
|
+
try {
|
|
136
|
+
const loaded = await loadTaskBackend({
|
|
137
|
+
cwd: opts.cwd,
|
|
138
|
+
rootOverride: opts.rootOverride ?? null,
|
|
139
|
+
});
|
|
140
|
+
const tasks = await loaded.backend.listTasks();
|
|
141
|
+
taskListLoaded = { ok: true, count: tasks.length };
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
const message = compactError(err);
|
|
145
|
+
taskListLoaded = { ok: false, error: message };
|
|
146
|
+
nextActions.push({
|
|
147
|
+
command: "agentplane task list",
|
|
148
|
+
reason: `task backend unavailable (${message})`,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
let workingTree = {
|
|
153
|
+
ok: false,
|
|
154
|
+
error: "project not resolved",
|
|
155
|
+
};
|
|
156
|
+
let branch = {
|
|
157
|
+
ok: false,
|
|
158
|
+
error: "project not resolved",
|
|
159
|
+
};
|
|
160
|
+
if (resolved) {
|
|
161
|
+
try {
|
|
162
|
+
const git = new GitContext({ gitRoot: resolved.gitRoot });
|
|
163
|
+
const [staged, unstagedTracked] = await Promise.all([
|
|
164
|
+
git.statusStagedPaths(),
|
|
165
|
+
git.statusUnstagedTrackedPaths(),
|
|
166
|
+
]);
|
|
167
|
+
workingTree = { ok: true, value: staged.length === 0 && unstagedTracked.length === 0 };
|
|
168
|
+
if (!workingTree.value) {
|
|
169
|
+
nextActions.push({
|
|
170
|
+
command: "git status --short --untracked-files=no",
|
|
171
|
+
reason: "tracked changes detected",
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
const message = compactError(err);
|
|
177
|
+
workingTree = { ok: false, error: message };
|
|
178
|
+
nextActions.push({
|
|
179
|
+
command: "git status --short --untracked-files=no",
|
|
180
|
+
reason: `cannot inspect git status (${message})`,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
const current = await gitCurrentBranch(resolved.gitRoot);
|
|
185
|
+
branch = { ok: true, value: current };
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
branch = { ok: false, error: compactError(err) };
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
project_detected: resolved !== null,
|
|
193
|
+
config_loaded: configLoaded,
|
|
194
|
+
quickstart_loaded: quickstartLoaded,
|
|
195
|
+
task_list_loaded: taskListLoaded,
|
|
196
|
+
working_tree_clean_tracked: workingTree,
|
|
197
|
+
current_branch: branch,
|
|
198
|
+
workflow_mode: inferWorkflowMode(config),
|
|
199
|
+
approvals: inferApprovals(config),
|
|
200
|
+
outside_repo_needed: false,
|
|
201
|
+
next_actions: nextActions,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
export const preflightSpec = {
|
|
205
|
+
id: ["preflight"],
|
|
206
|
+
group: "Core",
|
|
207
|
+
summary: "Run aggregated preflight checks and print a deterministic readiness report.",
|
|
208
|
+
options: [
|
|
209
|
+
{
|
|
210
|
+
kind: "boolean",
|
|
211
|
+
name: "json",
|
|
212
|
+
default: false,
|
|
213
|
+
description: "Emit machine-readable JSON report.",
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
examples: [
|
|
217
|
+
{ cmd: "agentplane preflight --json", why: "Produce one-shot agent-readable preflight." },
|
|
218
|
+
],
|
|
219
|
+
parse: (raw) => ({ json: raw.opts.json === true }),
|
|
220
|
+
};
|
|
221
|
+
async function cmdPreflight(opts) {
|
|
222
|
+
return wrapCommand({ command: "preflight", rootOverride: opts.rootOverride }, async () => {
|
|
223
|
+
const report = await buildPreflightReport({ cwd: opts.cwd, rootOverride: opts.rootOverride });
|
|
224
|
+
if (opts.json) {
|
|
225
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
226
|
+
return 0;
|
|
227
|
+
}
|
|
228
|
+
process.stdout.write("Preflight Summary\n");
|
|
229
|
+
process.stdout.write(`- project detected: ${report.project_detected ? "yes" : "no"}\n`);
|
|
230
|
+
process.stdout.write(`- config loaded: ${probeYesNo(report.config_loaded)}\n`);
|
|
231
|
+
process.stdout.write(`- quickstart loaded: ${probeYesNo(report.quickstart_loaded)}\n`);
|
|
232
|
+
process.stdout.write(`- task list loaded: ${probeYesNo(report.task_list_loaded)}\n`);
|
|
233
|
+
process.stdout.write(`- working tree clean (tracked-only): ${probeValueOrUnknown(report.working_tree_clean_tracked)}\n`);
|
|
234
|
+
process.stdout.write(`- current git branch: ${probeValueOrUnknown(report.current_branch)}\n`);
|
|
235
|
+
process.stdout.write(`- workflow_mode: ${report.workflow_mode}\n`);
|
|
236
|
+
process.stdout.write("- approval gates:\n");
|
|
237
|
+
process.stdout.write(` - require_plan: ${String(report.approvals.require_plan)}\n`);
|
|
238
|
+
process.stdout.write(` - require_verify: ${String(report.approvals.require_verify)}\n`);
|
|
239
|
+
process.stdout.write(` - require_network: ${String(report.approvals.require_network)}\n`);
|
|
240
|
+
process.stdout.write("- outside-repo: not needed\n");
|
|
241
|
+
if (report.next_actions.length > 0) {
|
|
242
|
+
process.stdout.write("Next actions:\n");
|
|
243
|
+
for (const action of report.next_actions) {
|
|
244
|
+
process.stdout.write(`- ${action.command}: ${action.reason}\n`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return 0;
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
export const runPreflight = (ctx, p) => {
|
|
251
|
+
return cmdPreflight({ cwd: ctx.cwd, rootOverride: ctx.rootOverride, json: p.json });
|
|
27
252
|
};
|
|
28
253
|
export const roleSpec = {
|
|
29
254
|
id: ["role"],
|
|
30
255
|
group: "Core",
|
|
31
256
|
summary: "Show role-specific workflow guidance.",
|
|
32
257
|
args: [{ name: "role", required: true, valueHint: "<role>" }],
|
|
258
|
+
options: [
|
|
259
|
+
{
|
|
260
|
+
kind: "boolean",
|
|
261
|
+
name: "json",
|
|
262
|
+
default: false,
|
|
263
|
+
description: "Emit compact machine-readable role payload.",
|
|
264
|
+
},
|
|
265
|
+
],
|
|
33
266
|
examples: [{ cmd: "agentplane role ORCHESTRATOR", why: "Show ORCHESTRATOR guide." }],
|
|
34
|
-
parse: (raw) => ({ role: String(raw.args.role ?? "") }),
|
|
267
|
+
parse: (raw) => ({ role: String(raw.args.role ?? ""), json: raw.opts.json === true }),
|
|
35
268
|
};
|
|
36
269
|
function parseAgentProfileJson(filePath, text) {
|
|
37
270
|
let parsed;
|
|
@@ -159,6 +392,23 @@ async function cmdRole(opts) {
|
|
|
159
392
|
});
|
|
160
393
|
}
|
|
161
394
|
if (guide) {
|
|
395
|
+
if (opts.json) {
|
|
396
|
+
const payload = {
|
|
397
|
+
role: normalizedRole,
|
|
398
|
+
builtin_guide: guide
|
|
399
|
+
.split("\n")
|
|
400
|
+
.map((line) => line.trim())
|
|
401
|
+
.filter((line) => line.length > 0),
|
|
402
|
+
};
|
|
403
|
+
if (agentProfile) {
|
|
404
|
+
payload.agent_profile = {
|
|
405
|
+
filename: agentProfile.filename,
|
|
406
|
+
profile: agentProfile.profile,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
410
|
+
return 0;
|
|
411
|
+
}
|
|
162
412
|
process.stdout.write(`${guide}\n`);
|
|
163
413
|
if (agentProfile) {
|
|
164
414
|
const block = renderAgentProfileBlock({
|
|
@@ -183,12 +433,22 @@ async function cmdRole(opts) {
|
|
|
183
433
|
roleId: normalizedRole,
|
|
184
434
|
profile: agentProfile.profile,
|
|
185
435
|
});
|
|
436
|
+
if (opts.json) {
|
|
437
|
+
process.stdout.write(`${JSON.stringify({
|
|
438
|
+
role: normalizedRole,
|
|
439
|
+
agent_profile: {
|
|
440
|
+
filename: agentProfile.filename,
|
|
441
|
+
profile: agentProfile.profile,
|
|
442
|
+
},
|
|
443
|
+
}, null, 2)}\n`);
|
|
444
|
+
return 0;
|
|
445
|
+
}
|
|
186
446
|
process.stdout.write(`${block}\n`);
|
|
187
447
|
return 0;
|
|
188
448
|
});
|
|
189
449
|
}
|
|
190
450
|
export const runRole = (ctx, p) => {
|
|
191
|
-
return cmdRole({ cwd: ctx.cwd, rootOverride: ctx.rootOverride, role: p.role });
|
|
451
|
+
return cmdRole({ cwd: ctx.cwd, rootOverride: ctx.rootOverride, role: p.role, json: p.json });
|
|
192
452
|
};
|
|
193
453
|
export const agentsSpec = {
|
|
194
454
|
id: ["agents"],
|