agentplane 0.2.12 → 0.2.14
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 +4 -0
- package/assets/AGENTS.md +17 -0
- package/dist/cli/command-guide.js +1 -1
- package/dist/cli/run-cli/command-catalog.js +4 -4
- package/dist/cli/run-cli/commands/config.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/config.js +17 -38
- package/dist/cli/run-cli/commands/core.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/core.js +100 -71
- package/dist/cli/run-cli/commands/ide.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/ide.js +3 -9
- package/dist/cli/run-cli/commands/init/ui.d.ts +3 -0
- package/dist/cli/run-cli/commands/init/ui.d.ts.map +1 -0
- package/dist/cli/run-cli/commands/init/ui.js +38 -0
- package/dist/cli/run-cli/commands/init/write-config.d.ts +13 -0
- package/dist/cli/run-cli/commands/init/write-config.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-config.js +1 -0
- package/dist/cli/run-cli/commands/init/write-gitignore.d.ts +2 -1
- package/dist/cli/run-cli/commands/init/write-gitignore.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-gitignore.js +19 -6
- package/dist/cli/run-cli/commands/init.d.ts +3 -0
- package/dist/cli/run-cli/commands/init.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init.js +114 -9
- package/dist/cli/run-cli/commands/wrap-command.d.ts +6 -0
- package/dist/cli/run-cli/commands/wrap-command.d.ts.map +1 -0
- package/dist/cli/run-cli/commands/wrap-command.js +17 -0
- package/dist/cli/run-cli.d.ts.map +1 -1
- package/dist/cli/run-cli.js +5 -3
- package/dist/commands/doctor.command.d.ts +2 -7
- package/dist/commands/doctor.command.d.ts.map +1 -1
- package/dist/commands/doctor.command.js +2 -137
- package/dist/commands/doctor.run.d.ts +4 -0
- package/dist/commands/doctor.run.d.ts.map +1 -0
- package/dist/commands/doctor.run.js +174 -0
- package/dist/commands/doctor.spec.d.ts +7 -0
- package/dist/commands/doctor.spec.d.ts.map +1 -0
- package/dist/commands/doctor.spec.js +20 -0
- package/dist/commands/recipes/install.command.d.ts +2 -11
- package/dist/commands/recipes/install.command.d.ts.map +1 -1
- package/dist/commands/recipes/install.command.js +2 -161
- package/dist/commands/recipes/install.run.d.ts +4 -0
- package/dist/commands/recipes/install.run.d.ts.map +1 -0
- package/dist/commands/recipes/install.run.js +23 -0
- package/dist/commands/recipes/install.spec.d.ts +11 -0
- package/dist/commands/recipes/install.spec.d.ts.map +1 -0
- package/dist/commands/recipes/install.spec.js +140 -0
- package/dist/commands/shared/git-context.d.ts +3 -0
- package/dist/commands/shared/git-context.d.ts.map +1 -1
- package/dist/commands/shared/git-context.js +10 -0
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +34 -2
- package/dist/commands/task/set-status.d.ts.map +1 -1
- package/dist/commands/task/set-status.js +10 -0
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +23 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,6 +24,9 @@ agentplane init
|
|
|
24
24
|
agentplane quickstart
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
`agentplane init` is human-oriented: interactive onboarding includes workflow/backend selection,
|
|
28
|
+
execution profile selection (`conservative|balanced|aggressive`), approval toggles, and optional recipes.
|
|
29
|
+
|
|
27
30
|
Create your first task and run the workflow:
|
|
28
31
|
|
|
29
32
|
```bash
|
|
@@ -45,6 +48,7 @@ npx agentplane quickstart
|
|
|
45
48
|
- `AGENTS.md` is created if missing and defines the policy/guardrails.
|
|
46
49
|
- Built-in agent definitions are copied into `.agentplane/agents/`.
|
|
47
50
|
- Optional recipes can install additional agents when you run `agentplane recipes install ...`.
|
|
51
|
+
- `.agentplane/config.json` stores execution defaults under `execution` (profile, reasoning effort, tool budget, safety gates).
|
|
48
52
|
|
|
49
53
|
## Upgrade review reports
|
|
50
54
|
|
package/assets/AGENTS.md
CHANGED
|
@@ -107,6 +107,23 @@ Outside-repo includes (non-exhaustive):
|
|
|
107
107
|
- modifying keychains, ssh keys, credential stores
|
|
108
108
|
- any tool that mutates outside-repo state
|
|
109
109
|
|
|
110
|
+
## Execution Profile
|
|
111
|
+
|
|
112
|
+
`execution` settings in `.agentplane/config.json` define operational behavior defaults for agents:
|
|
113
|
+
|
|
114
|
+
- `profile`: `conservative` / `balanced` / `aggressive`
|
|
115
|
+
- `reasoning_effort`: `low` / `medium` / `high`
|
|
116
|
+
- `tool_budget`: `{ discovery, implementation, verification }`
|
|
117
|
+
- `stop_conditions`: conditions that force a stop/re-plan/escalation
|
|
118
|
+
- `handoff_conditions`: conditions that trigger handoff to another role
|
|
119
|
+
- `unsafe_actions_requiring_explicit_user_ok`: actions that require explicit user confirmation
|
|
120
|
+
|
|
121
|
+
Scope and precedence:
|
|
122
|
+
|
|
123
|
+
- These settings tune execution style only (autonomy, effort, budget, stop/handoff heuristics).
|
|
124
|
+
- They MUST NOT override role authority boundaries, source-of-truth order, approval gates, or hard invariants defined in this `AGENTS.md`.
|
|
125
|
+
- If `execution` config conflicts with policy, `AGENTS.md` policy wins.
|
|
126
|
+
|
|
110
127
|
## Framework Upgrade / Prompt Merge
|
|
111
128
|
|
|
112
129
|
`agentplane upgrade` is responsible for mechanical upgrades and safe merges. When an upgrade run indicates a potential semantic conflict (for example, both local and incoming changes exist relative to a baseline, or a baseline is missing but files differ), treat the result as requiring a meaning-level review.
|
|
@@ -244,7 +244,7 @@ export function renderQuickstart() {
|
|
|
244
244
|
"## Global flags",
|
|
245
245
|
"",
|
|
246
246
|
"- `--root <path>`: treat <path> as project root",
|
|
247
|
-
"- `--json`: emit JSON-formatted errors",
|
|
247
|
+
"- `--json-errors`: emit JSON-formatted errors",
|
|
248
248
|
"- `--help` / `-h`: show help",
|
|
249
249
|
"- `--version`: show version",
|
|
250
250
|
"- `--no-update-check`: skip checking npm for a newer CLI version",
|
|
@@ -34,7 +34,7 @@ import { workStartSpec } from "../../commands/branch/work-start.command.js";
|
|
|
34
34
|
import { branchBaseClearSpec, branchBaseExplainSpec, branchBaseGetSpec, branchBaseSetSpec, branchBaseSpec, } from "../../commands/branch/base.command.js";
|
|
35
35
|
import { branchStatusSpec } from "../../commands/branch/status.command.js";
|
|
36
36
|
import { branchRemoveSpec } from "../../commands/branch/remove.command.js";
|
|
37
|
-
import { recipesInstallSpec } from "../../commands/recipes/install.
|
|
37
|
+
import { recipesInstallSpec } from "../../commands/recipes/install.spec.js";
|
|
38
38
|
import { recipesListSpec } from "../../commands/recipes/list.command.js";
|
|
39
39
|
import { recipesListRemoteSpec } from "../../commands/recipes/list-remote.command.js";
|
|
40
40
|
import { recipesInfoSpec } from "../../commands/recipes/info.command.js";
|
|
@@ -58,7 +58,7 @@ import { blockSpec } from "../../commands/block.spec.js";
|
|
|
58
58
|
import { verifySpec } from "../../commands/verify.spec.js";
|
|
59
59
|
import { finishSpec } from "../../commands/finish.spec.js";
|
|
60
60
|
import { readySpec } from "../../commands/ready.command.js";
|
|
61
|
-
import { doctorSpec } from "../../commands/doctor.
|
|
61
|
+
import { doctorSpec } from "../../commands/doctor.spec.js";
|
|
62
62
|
import { docsCliSpec } from "../../commands/docs/cli.command.js";
|
|
63
63
|
import { hooksSpec } from "../../commands/hooks/hooks.command.js";
|
|
64
64
|
import { hooksInstallSpec } from "../../commands/hooks/install.command.js";
|
|
@@ -147,7 +147,7 @@ export const COMMANDS = [
|
|
|
147
147
|
needsConfig: true,
|
|
148
148
|
needsTaskContext: false,
|
|
149
149
|
}),
|
|
150
|
-
entry(doctorSpec, () => import("../../commands/doctor.
|
|
150
|
+
entry(doctorSpec, () => import("../../commands/doctor.run.js").then((m) => m.runDoctor), {
|
|
151
151
|
needsProject: true,
|
|
152
152
|
needsConfig: false,
|
|
153
153
|
needsTaskContext: false,
|
|
@@ -189,7 +189,7 @@ export const COMMANDS = [
|
|
|
189
189
|
entry(recipesExplainSpec, () => import("../../commands/recipes/explain.command.js").then((m) => m.runRecipesExplain)),
|
|
190
190
|
entry(recipesRemoveSpec, () => import("../../commands/recipes/remove.command.js").then((m) => m.runRecipesRemove)),
|
|
191
191
|
entry(recipesCachePruneSpec, () => import("../../commands/recipes/cache-prune.command.js").then((m) => m.runRecipesCachePrune)),
|
|
192
|
-
entry(recipesInstallSpec, () => import("../../commands/recipes/install.
|
|
192
|
+
entry(recipesInstallSpec, () => import("../../commands/recipes/install.run.js").then((m) => m.runRecipesInstall)),
|
|
193
193
|
entry(scenarioSpec, () => import("../../commands/scenario/scenario.command.js").then((m) => m.runScenario)),
|
|
194
194
|
entry(scenarioListSpec, () => import("../../commands/scenario/list.command.js").then((m) => m.runScenarioList)),
|
|
195
195
|
entry(scenarioInfoSpec, () => import("../../commands/scenario/info.command.js").then((m) => m.runScenarioInfo)),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/cli/run-cli/commands/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/cli/run-cli/commands/config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGrD,KAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAE9C,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,gBAAgB,CAMxD,CAAC;AAcF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAExF;AAED,KAAK,eAAe,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,eAAe,CAgBtD,CAAC;AA6BF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,CAAC,eAAe,CAAC,CAStF;AAED,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAE3C,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,aAAa,CAMlD,CAAC;AAcF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,CAAC,aAAa,CAAC,CAElF;AAED,KAAK,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,aAAa,CAgBlD,CAAC;AA0BF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,CAAC,aAAa,CAAC,CAQlF"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { saveConfig, setByDottedKey } from "@agentplaneorg/core";
|
|
3
|
-
import { mapCoreError } from "../../error-map.js";
|
|
4
3
|
import { usageError } from "../../spec/errors.js";
|
|
5
|
-
import {
|
|
4
|
+
import { wrapCommand } from "./wrap-command.js";
|
|
6
5
|
export const configShowSpec = {
|
|
7
6
|
id: ["config", "show"],
|
|
8
7
|
group: "Config",
|
|
@@ -11,16 +10,11 @@ export const configShowSpec = {
|
|
|
11
10
|
parse: () => ({}),
|
|
12
11
|
};
|
|
13
12
|
async function cmdConfigShow(opts) {
|
|
14
|
-
|
|
13
|
+
return wrapCommand({ command: "config show", rootOverride: opts.rootOverride }, async () => {
|
|
15
14
|
const loaded = await opts.deps.getLoadedConfig("config show");
|
|
16
15
|
process.stdout.write(`${JSON.stringify(loaded.raw, null, 2)}\n`);
|
|
17
16
|
return 0;
|
|
18
|
-
}
|
|
19
|
-
catch (err) {
|
|
20
|
-
if (err instanceof CliError)
|
|
21
|
-
throw err;
|
|
22
|
-
throw mapCoreError(err, { command: "config show", root: opts.rootOverride ?? null });
|
|
23
|
-
}
|
|
17
|
+
});
|
|
24
18
|
}
|
|
25
19
|
export function makeRunConfigShowHandler(deps) {
|
|
26
20
|
return (ctx) => cmdConfigShow({ cwd: ctx.cwd, rootOverride: ctx.rootOverride, deps });
|
|
@@ -43,7 +37,11 @@ export const configSetSpec = {
|
|
|
43
37
|
parse: (raw) => ({ key: String(raw.args.key ?? ""), value: String(raw.args.value ?? "") }),
|
|
44
38
|
};
|
|
45
39
|
async function cmdConfigSet(opts) {
|
|
46
|
-
|
|
40
|
+
return wrapCommand({
|
|
41
|
+
command: "config set",
|
|
42
|
+
rootOverride: opts.rootOverride,
|
|
43
|
+
context: { key: opts.key },
|
|
44
|
+
}, async () => {
|
|
47
45
|
const resolved = await opts.deps.getResolvedProject("config set");
|
|
48
46
|
const loaded = await opts.deps.getLoadedConfig("config set");
|
|
49
47
|
const raw = { ...loaded.raw };
|
|
@@ -51,16 +49,7 @@ async function cmdConfigSet(opts) {
|
|
|
51
49
|
await saveConfig(resolved.agentplaneDir, raw);
|
|
52
50
|
process.stdout.write(`${path.relative(resolved.gitRoot, path.join(resolved.agentplaneDir, "config.json"))}\n`);
|
|
53
51
|
return 0;
|
|
54
|
-
}
|
|
55
|
-
catch (err) {
|
|
56
|
-
if (err instanceof CliError)
|
|
57
|
-
throw err;
|
|
58
|
-
throw mapCoreError(err, {
|
|
59
|
-
command: "config set",
|
|
60
|
-
key: opts.key,
|
|
61
|
-
root: opts.rootOverride ?? null,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
52
|
+
});
|
|
64
53
|
}
|
|
65
54
|
export function makeRunConfigSetHandler(deps) {
|
|
66
55
|
return (ctx, p) => cmdConfigSet({
|
|
@@ -79,16 +68,11 @@ export const modeGetSpec = {
|
|
|
79
68
|
parse: () => ({}),
|
|
80
69
|
};
|
|
81
70
|
async function cmdModeGet(opts) {
|
|
82
|
-
|
|
71
|
+
return wrapCommand({ command: "mode get", rootOverride: opts.rootOverride }, async () => {
|
|
83
72
|
const loaded = await opts.deps.getLoadedConfig("mode get");
|
|
84
73
|
process.stdout.write(`${loaded.config.workflow_mode}\n`);
|
|
85
74
|
return 0;
|
|
86
|
-
}
|
|
87
|
-
catch (err) {
|
|
88
|
-
if (err instanceof CliError)
|
|
89
|
-
throw err;
|
|
90
|
-
throw mapCoreError(err, { command: "mode get", root: opts.rootOverride ?? null });
|
|
91
|
-
}
|
|
75
|
+
});
|
|
92
76
|
}
|
|
93
77
|
export function makeRunModeGetHandler(deps) {
|
|
94
78
|
return (ctx) => cmdModeGet({ cwd: ctx.cwd, rootOverride: ctx.rootOverride, deps });
|
|
@@ -111,7 +95,11 @@ export const modeSetSpec = {
|
|
|
111
95
|
},
|
|
112
96
|
};
|
|
113
97
|
async function cmdModeSet(opts) {
|
|
114
|
-
|
|
98
|
+
return wrapCommand({
|
|
99
|
+
command: "mode set",
|
|
100
|
+
rootOverride: opts.rootOverride,
|
|
101
|
+
context: { mode: opts.mode },
|
|
102
|
+
}, async () => {
|
|
115
103
|
const resolved = await opts.deps.getResolvedProject("mode set");
|
|
116
104
|
const loaded = await opts.deps.getLoadedConfig("mode set");
|
|
117
105
|
const raw = { ...loaded.raw };
|
|
@@ -119,16 +107,7 @@ async function cmdModeSet(opts) {
|
|
|
119
107
|
await saveConfig(resolved.agentplaneDir, raw);
|
|
120
108
|
process.stdout.write(`${opts.mode}\n`);
|
|
121
109
|
return 0;
|
|
122
|
-
}
|
|
123
|
-
catch (err) {
|
|
124
|
-
if (err instanceof CliError)
|
|
125
|
-
throw err;
|
|
126
|
-
throw mapCoreError(err, {
|
|
127
|
-
command: "mode set",
|
|
128
|
-
root: opts.rootOverride ?? null,
|
|
129
|
-
mode: opts.mode,
|
|
130
|
-
});
|
|
131
|
-
}
|
|
110
|
+
});
|
|
132
111
|
}
|
|
133
112
|
export function makeRunModeSetHandler(deps) {
|
|
134
113
|
return (ctx, p) => cmdModeSet({
|
|
@@ -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":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAIrD,KAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAE9C,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,gBAAgB,CAOxD,CAAC;AASF,eAAO,MAAM,aAAa,EAAE,cAAc,CAAC,gBAAgB,CAE1D,CAAC;AAEF,KAAK,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC,eAAO,MAAM,QAAQ,EAAE,WAAW,CAAC,UAAU,CAO5C,CAAC;AAkMF,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,13 +1,13 @@
|
|
|
1
1
|
import { readdir, readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { resolveProject } from "@agentplaneorg/core";
|
|
4
|
-
import { mapCoreError } from "../../error-map.js";
|
|
5
4
|
import { fileExists } from "../../fs-utils.js";
|
|
6
5
|
import { CliError } from "../../../shared/errors.js";
|
|
7
6
|
import { dedupeStrings } from "../../../shared/strings.js";
|
|
8
7
|
import { usageError } from "../../spec/errors.js";
|
|
9
8
|
import { listRoles, renderQuickstart, renderRole } from "../../command-guide.js";
|
|
10
9
|
import { toStringList } from "../../spec/parse-utils.js";
|
|
10
|
+
import { wrapCommand } from "./wrap-command.js";
|
|
11
11
|
export const quickstartSpec = {
|
|
12
12
|
id: ["quickstart"],
|
|
13
13
|
group: "Core",
|
|
@@ -16,20 +16,14 @@ export const quickstartSpec = {
|
|
|
16
16
|
examples: [{ cmd: "agentplane quickstart", why: "Show quickstart." }],
|
|
17
17
|
parse: () => ({}),
|
|
18
18
|
};
|
|
19
|
-
function cmdQuickstart(opts) {
|
|
20
|
-
|
|
19
|
+
async function cmdQuickstart(opts) {
|
|
20
|
+
return wrapCommand({ command: "quickstart", rootOverride: opts.rootOverride }, () => {
|
|
21
21
|
process.stdout.write(`${renderQuickstart()}\n`);
|
|
22
22
|
return 0;
|
|
23
|
-
}
|
|
24
|
-
catch (err) {
|
|
25
|
-
if (err instanceof CliError)
|
|
26
|
-
throw err;
|
|
27
|
-
throw mapCoreError(err, { command: "quickstart", root: opts.rootOverride ?? null });
|
|
28
|
-
}
|
|
23
|
+
});
|
|
29
24
|
}
|
|
30
25
|
export const runQuickstart = (ctx) => {
|
|
31
|
-
cmdQuickstart({ cwd: ctx.cwd, rootOverride: ctx.rootOverride });
|
|
32
|
-
return Promise.resolve(0);
|
|
26
|
+
return cmdQuickstart({ cwd: ctx.cwd, rootOverride: ctx.rootOverride });
|
|
33
27
|
};
|
|
34
28
|
export const roleSpec = {
|
|
35
29
|
id: ["role"],
|
|
@@ -39,6 +33,27 @@ export const roleSpec = {
|
|
|
39
33
|
examples: [{ cmd: "agentplane role ORCHESTRATOR", why: "Show ORCHESTRATOR guide." }],
|
|
40
34
|
parse: (raw) => ({ role: String(raw.args.role ?? "") }),
|
|
41
35
|
};
|
|
36
|
+
function parseAgentProfileJson(filePath, text) {
|
|
37
|
+
let parsed;
|
|
38
|
+
try {
|
|
39
|
+
parsed = JSON.parse(text);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
throw new CliError({
|
|
43
|
+
exitCode: 3,
|
|
44
|
+
code: "E_VALIDATION",
|
|
45
|
+
message: `Invalid agent profile JSON: ${filePath} (malformed JSON)`,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
49
|
+
throw new CliError({
|
|
50
|
+
exitCode: 3,
|
|
51
|
+
code: "E_VALIDATION",
|
|
52
|
+
message: `Invalid agent profile JSON: ${filePath} (expected object)`,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return parsed;
|
|
56
|
+
}
|
|
42
57
|
function normalizeRoleId(roleRaw) {
|
|
43
58
|
return roleRaw.trim().toUpperCase();
|
|
44
59
|
}
|
|
@@ -87,7 +102,7 @@ async function readAgentProfile(opts) {
|
|
|
87
102
|
return null;
|
|
88
103
|
const filename = `${foundId}.json`;
|
|
89
104
|
const filePath = path.join(listing.agentplaneDir, "agents", filename);
|
|
90
|
-
const raw =
|
|
105
|
+
const raw = parseAgentProfileJson(filePath, await readFile(filePath, "utf8"));
|
|
91
106
|
return { agentplaneDir: listing.agentplaneDir, filename, profile: raw };
|
|
92
107
|
}
|
|
93
108
|
function renderAgentProfileBlock(opts) {
|
|
@@ -112,7 +127,7 @@ function renderAgentProfileBlock(opts) {
|
|
|
112
127
|
return lines.join("\n").trimEnd();
|
|
113
128
|
}
|
|
114
129
|
async function cmdRole(opts) {
|
|
115
|
-
|
|
130
|
+
return wrapCommand({ command: "role", rootOverride: opts.rootOverride }, async () => {
|
|
116
131
|
const roleRaw = opts.role.trim();
|
|
117
132
|
if (!roleRaw) {
|
|
118
133
|
throw usageError({
|
|
@@ -170,12 +185,7 @@ async function cmdRole(opts) {
|
|
|
170
185
|
});
|
|
171
186
|
process.stdout.write(`${block}\n`);
|
|
172
187
|
return 0;
|
|
173
|
-
}
|
|
174
|
-
catch (err) {
|
|
175
|
-
if (err instanceof CliError)
|
|
176
|
-
throw err;
|
|
177
|
-
throw mapCoreError(err, { command: "role", root: opts.rootOverride ?? null });
|
|
178
|
-
}
|
|
188
|
+
});
|
|
179
189
|
}
|
|
180
190
|
export const runRole = (ctx, p) => {
|
|
181
191
|
return cmdRole({ cwd: ctx.cwd, rootOverride: ctx.rootOverride, role: p.role });
|
|
@@ -188,64 +198,83 @@ export const agentsSpec = {
|
|
|
188
198
|
parse: () => ({}),
|
|
189
199
|
};
|
|
190
200
|
export function makeRunAgentsHandler(deps) {
|
|
191
|
-
return async (ctx) => {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
+
return async (ctx) => wrapCommand({ command: "agents", rootOverride: ctx.rootOverride }, async () => {
|
|
202
|
+
const resolved = await deps.getResolvedProject("agents");
|
|
203
|
+
const agentsDir = path.join(resolved.agentplaneDir, "agents");
|
|
204
|
+
if (!(await fileExists(agentsDir))) {
|
|
205
|
+
throw new CliError({
|
|
206
|
+
exitCode: 2,
|
|
207
|
+
code: "E_USAGE",
|
|
208
|
+
message: `Agents directory not found: ${agentsDir} (run \`agentplane init\`)`,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
const entriesRaw = await readdir(agentsDir);
|
|
212
|
+
const entries = entriesRaw.filter((name) => name.endsWith(".json")).toSorted();
|
|
213
|
+
if (entries.length === 0) {
|
|
214
|
+
throw new CliError({
|
|
215
|
+
exitCode: 2,
|
|
216
|
+
code: "E_USAGE",
|
|
217
|
+
message: `No agent definitions found under ${agentsDir} (expected *.json)`,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
const rows = [];
|
|
221
|
+
const seen = new Set();
|
|
222
|
+
const duplicates = [];
|
|
223
|
+
const mismatches = [];
|
|
224
|
+
for (const entry of entries) {
|
|
225
|
+
const canonicalId = entry.replace(/\.json$/i, "");
|
|
226
|
+
const filePath = path.join(agentsDir, entry);
|
|
227
|
+
const raw = parseAgentProfileJson(filePath, await readFile(filePath, "utf8"));
|
|
228
|
+
const rawId = typeof raw.id === "string" ? raw.id : "";
|
|
229
|
+
const rawRole = typeof raw.role === "string" ? raw.role : "";
|
|
230
|
+
const normalizedRawId = rawId.trim();
|
|
231
|
+
const role = rawRole.trim() || "-";
|
|
232
|
+
if (seen.has(canonicalId)) {
|
|
233
|
+
duplicates.push(canonicalId);
|
|
201
234
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (entries.length === 0) {
|
|
205
|
-
throw new CliError({
|
|
206
|
-
exitCode: 2,
|
|
207
|
-
code: "E_USAGE",
|
|
208
|
-
message: `No agent definitions found under ${agentsDir} (expected *.json)`,
|
|
209
|
-
});
|
|
235
|
+
else {
|
|
236
|
+
seen.add(canonicalId);
|
|
210
237
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
seen.add(agentId);
|
|
226
|
-
}
|
|
227
|
-
rows.push([agentId, role, entry]);
|
|
238
|
+
if (normalizedRawId.length > 0 && normalizedRawId !== canonicalId) {
|
|
239
|
+
mismatches.push({ filename: entry, canonicalId, rawId: normalizedRawId });
|
|
240
|
+
}
|
|
241
|
+
rows.push({ canonicalId, role, filename: entry, rawId: normalizedRawId });
|
|
242
|
+
}
|
|
243
|
+
const showRawIdColumn = mismatches.length > 0;
|
|
244
|
+
const widthId = Math.max(...rows.map((row) => row.canonicalId.length), "ID".length);
|
|
245
|
+
const widthFile = Math.max(...rows.map((row) => row.filename.length), "FILE".length);
|
|
246
|
+
if (showRawIdColumn) {
|
|
247
|
+
const widthRawId = Math.max(...rows.map((row) => row.rawId.length), "RAW_ID".length);
|
|
248
|
+
process.stdout.write(`${"ID".padEnd(widthId)} ${"FILE".padEnd(widthFile)} ${"RAW_ID".padEnd(widthRawId)} ROLE\n`);
|
|
249
|
+
process.stdout.write(`${"-".repeat(widthId)} ${"-".repeat(widthFile)} ${"-".repeat(widthRawId)} ----\n`);
|
|
250
|
+
for (const row of rows) {
|
|
251
|
+
process.stdout.write(`${row.canonicalId.padEnd(widthId)} ${row.filename.padEnd(widthFile)} ${row.rawId.padEnd(widthRawId)} ${row.role}\n`);
|
|
228
252
|
}
|
|
229
|
-
|
|
230
|
-
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
231
255
|
process.stdout.write(`${"ID".padEnd(widthId)} ${"FILE".padEnd(widthFile)} ROLE\n`);
|
|
232
256
|
process.stdout.write(`${"-".repeat(widthId)} ${"-".repeat(widthFile)} ----\n`);
|
|
233
|
-
for (const
|
|
234
|
-
process.stdout.write(`${
|
|
235
|
-
}
|
|
236
|
-
if (duplicates.length > 0) {
|
|
237
|
-
throw new CliError({
|
|
238
|
-
exitCode: 2,
|
|
239
|
-
code: "E_USAGE",
|
|
240
|
-
message: `Duplicate agent ids: ${dedupeStrings(duplicates).toSorted().join(", ")}`,
|
|
241
|
-
});
|
|
257
|
+
for (const row of rows) {
|
|
258
|
+
process.stdout.write(`${row.canonicalId.padEnd(widthId)} ${row.filename.padEnd(widthFile)} ${row.role}\n`);
|
|
242
259
|
}
|
|
243
|
-
return 0;
|
|
244
260
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
261
|
+
if (duplicates.length > 0) {
|
|
262
|
+
throw new CliError({
|
|
263
|
+
exitCode: 2,
|
|
264
|
+
code: "E_USAGE",
|
|
265
|
+
message: `Duplicate canonical agent ids: ${dedupeStrings(duplicates).toSorted().join(", ")}`,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
if (mismatches.length > 0) {
|
|
269
|
+
const details = mismatches
|
|
270
|
+
.map((m) => `${m.filename}: raw id "${m.rawId}" != canonical "${m.canonicalId}"`)
|
|
271
|
+
.join("; ");
|
|
272
|
+
throw new CliError({
|
|
273
|
+
exitCode: 2,
|
|
274
|
+
code: "E_USAGE",
|
|
275
|
+
message: `Agent profile id mismatch: ${details}`,
|
|
276
|
+
});
|
|
249
277
|
}
|
|
250
|
-
|
|
278
|
+
return 0;
|
|
279
|
+
});
|
|
251
280
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ide.d.ts","sourceRoot":"","sources":["../../../../src/cli/run-cli/commands/ide.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ide.d.ts","sourceRoot":"","sources":["../../../../src/cli/run-cli/commands/ide.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGrD,KAAK,aAAa,GAAG;IAAE,GAAG,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAA;CAAE,CAAC;AAErD,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,aAAa,CAkBlD,CAAC;AAEF,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5B,IAAI,EAAE,OAAO,CAAC;CACf,GAAG,OAAO,CAAC,MAAM,CAAC,CAwClB;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,CAAC,aAAa,CAAC,CAElF"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { mkdir, readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { mapCoreError } from "../../error-map.js";
|
|
4
3
|
import { writeTextIfChanged } from "../../../shared/write-if-changed.js";
|
|
5
|
-
import {
|
|
4
|
+
import { wrapCommand } from "./wrap-command.js";
|
|
6
5
|
export const ideSyncSpec = {
|
|
7
6
|
id: ["ide", "sync"],
|
|
8
7
|
group: "IDE",
|
|
@@ -23,7 +22,7 @@ export const ideSyncSpec = {
|
|
|
23
22
|
parse: (raw) => ({ ide: raw.opts.ide }),
|
|
24
23
|
};
|
|
25
24
|
export async function cmdIdeSync(opts) {
|
|
26
|
-
|
|
25
|
+
return wrapCommand({ command: "ide sync", rootOverride: opts.rootOverride }, async () => {
|
|
27
26
|
const resolved = await opts.deps.getResolvedProject("ide sync");
|
|
28
27
|
const agentsPath = path.join(resolved.gitRoot, "AGENTS.md");
|
|
29
28
|
const agentsText = await readFile(agentsPath, "utf8");
|
|
@@ -56,12 +55,7 @@ export async function cmdIdeSync(opts) {
|
|
|
56
55
|
process.stdout.write(`${path.relative(resolved.gitRoot, windsurfPath)}\n`);
|
|
57
56
|
}
|
|
58
57
|
return 0;
|
|
59
|
-
}
|
|
60
|
-
catch (err) {
|
|
61
|
-
if (err instanceof CliError)
|
|
62
|
-
throw err;
|
|
63
|
-
throw mapCoreError(err, { command: "ide sync", root: opts.rootOverride ?? null });
|
|
64
|
-
}
|
|
58
|
+
});
|
|
65
59
|
}
|
|
66
60
|
export function makeRunIdeSyncHandler(deps) {
|
|
67
61
|
return (ctx, p) => cmdIdeSync({ cwd: ctx.cwd, rootOverride: ctx.rootOverride, ide: p.ide, deps });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/ui.ts"],"names":[],"mappings":"AAsBA,wBAAgB,iBAAiB,IAAI,MAAM,CAa1C;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAG5E"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
function useColor() {
|
|
2
|
+
return process.stdout.isTTY === true && (process.env.TERM ?? "dumb") !== "dumb";
|
|
3
|
+
}
|
|
4
|
+
function color(text, code) {
|
|
5
|
+
if (!useColor())
|
|
6
|
+
return text;
|
|
7
|
+
return `\u001B[${code}m${text}\u001B[0m`;
|
|
8
|
+
}
|
|
9
|
+
function padLine(line, width) {
|
|
10
|
+
if (line.length >= width)
|
|
11
|
+
return line;
|
|
12
|
+
return `${line}${" ".repeat(width - line.length)}`;
|
|
13
|
+
}
|
|
14
|
+
function box(lines) {
|
|
15
|
+
const width = Math.max(...lines.map((line) => line.length), 0);
|
|
16
|
+
const top = `┌${"─".repeat(width + 2)}┐`;
|
|
17
|
+
const body = lines.map((line) => `│ ${padLine(line, width)} │`);
|
|
18
|
+
const bottom = `└${"─".repeat(width + 2)}┘`;
|
|
19
|
+
return [top, ...body, bottom].join("\n");
|
|
20
|
+
}
|
|
21
|
+
export function renderInitWelcome() {
|
|
22
|
+
const logo = [
|
|
23
|
+
" ___ ____ ____ _ _ _____ ",
|
|
24
|
+
" / _ | / __// __// | / / ___/ ",
|
|
25
|
+
" / __ |/ _/ / _/ / |/ / /__ ",
|
|
26
|
+
String.raw `/_/ |_|\__/ /___//_/|_/\___/ `,
|
|
27
|
+
" agent/plane ",
|
|
28
|
+
].map((line) => color(line, "36"));
|
|
29
|
+
const intro = [
|
|
30
|
+
color("Bootstrap an agent-first workflow in this repository.", "1"),
|
|
31
|
+
"This interactive setup runs once; daily work is executed by agents.",
|
|
32
|
+
];
|
|
33
|
+
return `${logo.join("\n")}\n\n${box(intro)}\n`;
|
|
34
|
+
}
|
|
35
|
+
export function renderInitSection(title, description) {
|
|
36
|
+
const header = color(`[${title}]`, "33");
|
|
37
|
+
return `${header}\n${description}\n`;
|
|
38
|
+
}
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
export type InitExecutionConfig = {
|
|
2
|
+
profile: "conservative" | "balanced" | "aggressive";
|
|
3
|
+
reasoning_effort: "low" | "medium" | "high";
|
|
4
|
+
tool_budget: {
|
|
5
|
+
discovery: number;
|
|
6
|
+
implementation: number;
|
|
7
|
+
verification: number;
|
|
8
|
+
};
|
|
9
|
+
stop_conditions: string[];
|
|
10
|
+
handoff_conditions: string[];
|
|
11
|
+
unsafe_actions_requiring_explicit_user_ok: string[];
|
|
12
|
+
};
|
|
1
13
|
export declare function ensureAgentplaneDirs(agentplaneDir: string): Promise<void>;
|
|
2
14
|
export declare function writeInitConfig(opts: {
|
|
3
15
|
agentplaneDir: string;
|
|
@@ -7,6 +19,7 @@ export declare function writeInitConfig(opts: {
|
|
|
7
19
|
requirePlanApproval: boolean;
|
|
8
20
|
requireNetworkApproval: boolean;
|
|
9
21
|
requireVerifyApproval: boolean;
|
|
22
|
+
execution: InitExecutionConfig;
|
|
10
23
|
}): Promise<void>;
|
|
11
24
|
export declare function writeBackendStubs(opts: {
|
|
12
25
|
localBackendPath: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-config.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/write-config.ts"],"names":[],"mappings":"AAOA,wBAAsB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/E;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,GAAG,WAAW,CAAC;IACjC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,sBAAsB,EAAE,OAAO,CAAC;IAChC,qBAAqB,EAAE,OAAO,CAAC;CAChC,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"write-config.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/write-config.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,cAAc,GAAG,UAAU,GAAG,YAAY,CAAC;IACpD,gBAAgB,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC5C,WAAW,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,yCAAyC,EAAE,MAAM,EAAE,CAAC;CACrD,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/E;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,GAAG,WAAW,CAAC;IACjC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,sBAAsB,EAAE,OAAO,CAAC;IAChC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,SAAS,EAAE,mBAAmB,CAAC;CAChC,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBhB"}
|
|
@@ -17,6 +17,7 @@ export async function writeInitConfig(opts) {
|
|
|
17
17
|
setByDottedKey(rawConfig, "agents.approvals.require_plan", String(opts.requirePlanApproval));
|
|
18
18
|
setByDottedKey(rawConfig, "agents.approvals.require_network", String(opts.requireNetworkApproval));
|
|
19
19
|
setByDottedKey(rawConfig, "agents.approvals.require_verify", String(opts.requireVerifyApproval));
|
|
20
|
+
setByDottedKey(rawConfig, "execution", JSON.stringify(opts.execution));
|
|
20
21
|
await saveConfig(opts.agentplaneDir, rawConfig);
|
|
21
22
|
}
|
|
22
23
|
export async function writeBackendStubs(opts) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-gitignore.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/write-gitignore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"write-gitignore.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/write-gitignore.ts"],"names":[],"mappings":"AAgCA,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,uBAAuB,EAAE,OAAO,CAAC;CAClC,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBhB"}
|
|
@@ -12,14 +12,27 @@ async function readTextIfExists(filePath) {
|
|
|
12
12
|
throw err;
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
const RUNTIME_IGNORE_LINES = [
|
|
16
|
+
"# agentplane: ignore runtime/transient workspace artifacts",
|
|
17
|
+
".agentplane/worktrees",
|
|
18
|
+
".agentplane/cache",
|
|
19
|
+
".agentplane/recipes-cache",
|
|
20
|
+
".agentplane/.upgrade",
|
|
21
|
+
".agentplane/.release",
|
|
22
|
+
".agentplane/upgrade",
|
|
23
|
+
".agentplane/tasks.json",
|
|
24
|
+
];
|
|
25
|
+
const AGENT_PROMPT_IGNORE_LINES = [
|
|
26
|
+
"# agentplane: ignore local agent prompts/templates",
|
|
27
|
+
"AGENTS.md",
|
|
28
|
+
".agentplane/agents/",
|
|
29
|
+
];
|
|
30
|
+
export async function ensureInitGitignore(opts) {
|
|
16
31
|
const gitignorePath = path.join(opts.gitRoot, ".gitignore");
|
|
17
32
|
const existing = (await readTextIfExists(gitignorePath)) ?? "";
|
|
18
|
-
const ensuredLines =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
".agentplane/agents/",
|
|
22
|
-
];
|
|
33
|
+
const ensuredLines = opts.includeAgentPromptFiles
|
|
34
|
+
? [...RUNTIME_IGNORE_LINES, ...AGENT_PROMPT_IGNORE_LINES]
|
|
35
|
+
: [...RUNTIME_IGNORE_LINES];
|
|
23
36
|
const existingLines = existing.split(/\r?\n/);
|
|
24
37
|
const existingSet = new Set(existingLines.map((line) => line.trimEnd()));
|
|
25
38
|
const missing = ensuredLines.filter((line) => !existingSet.has(line));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CommandHandler, CommandSpec } from "../../spec/spec.js";
|
|
2
|
+
type ExecutionProfile = "conservative" | "balanced" | "aggressive";
|
|
2
3
|
type InitFlags = {
|
|
3
4
|
ide?: "codex" | "cursor" | "windsurf";
|
|
4
5
|
workflow?: "direct" | "branch_pr";
|
|
@@ -8,6 +9,8 @@ type InitFlags = {
|
|
|
8
9
|
requirePlanApproval?: boolean;
|
|
9
10
|
requireNetworkApproval?: boolean;
|
|
10
11
|
requireVerifyApproval?: boolean;
|
|
12
|
+
executionProfile?: ExecutionProfile;
|
|
13
|
+
strictUnsafeConfirm?: boolean;
|
|
11
14
|
recipes?: string[];
|
|
12
15
|
force?: boolean;
|
|
13
16
|
backup?: boolean;
|