Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/user/setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ If `.git` does not exist in that folder, `init` creates a new git repository the
`agentplane init` now starts with a setup profile:

- `prod` (default): compact flow with essential prompts only (typically setup profile + backend).
- `prod-strict`: compact flow with stricter defaults (hooks on, strict unsafe confirmations).
- `dev`: full questionnaire (workflow, hooks, approvals, execution profile, recipes).
- `dev-safe`: full questionnaire with stricter unsafe-action confirmations by default.

Use `--setup-profile dev` to force full prompts.
Use `--setup-profile dev` (or `dev-safe`) to force full prompts.

Non-interactive setup is available through flags:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,18 @@ describe("runCli", () => {
}
});

it("init accepts setup-profile strict variants", async () => {
const root1 = await mkGitRepoRoot();
await configureGitUser(root1);
let code = await runCli(["init", "--yes", "--setup-profile", "prod-strict", "--root", root1]);
expect(code).toBe(0);

const root2 = await mkGitRepoRoot();
await configureGitUser(root2);
code = await runCli(["init", "--yes", "--setup-profile", "dev-safe", "--root", root2]);
expect(code).toBe(0);
});
Comment on lines +901 to +911
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Test coverage for new presets looks good.

The test correctly validates that prod-strict and dev-safe are accepted by the CLI. Consider adding assertions to verify that preset-specific defaults (e.g., defaultHooks: true for prod-strict, defaultStrictUnsafeConfirm: true for both strict variants) are actually applied in the resulting config.

,

💡 Optional: Verify preset defaults are applied
   it("init accepts setup-profile strict variants", async () => {
     const root1 = await mkGitRepoRoot();
     await configureGitUser(root1);
     let code = await runCli(["init", "--yes", "--setup-profile", "prod-strict", "--root", root1]);
     expect(code).toBe(0);
+    // Verify prod-strict applies defaultStrictUnsafeConfirm: true
+    const config1 = JSON.parse(await readFile(path.join(root1, ".agentplane", "config.json"), "utf8"));
+    expect(config1.execution?.strict_unsafe_confirm).toBe(true);
 
     const root2 = await mkGitRepoRoot();
     await configureGitUser(root2);
     code = await runCli(["init", "--yes", "--setup-profile", "dev-safe", "--root", root2]);
     expect(code).toBe(0);
+    // Verify dev-safe applies defaultStrictUnsafeConfirm: true
+    const config2 = JSON.parse(await readFile(path.join(root2, ".agentplane", "config.json"), "utf8"));
+    expect(config2.execution?.strict_unsafe_confirm).toBe(true);
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it("init accepts setup-profile strict variants", async () => {
const root1 = await mkGitRepoRoot();
await configureGitUser(root1);
let code = await runCli(["init", "--yes", "--setup-profile", "prod-strict", "--root", root1]);
expect(code).toBe(0);
const root2 = await mkGitRepoRoot();
await configureGitUser(root2);
code = await runCli(["init", "--yes", "--setup-profile", "dev-safe", "--root", root2]);
expect(code).toBe(0);
});
it("init accepts setup-profile strict variants", async () => {
const root1 = await mkGitRepoRoot();
await configureGitUser(root1);
let code = await runCli(["init", "--yes", "--setup-profile", "prod-strict", "--root", root1]);
expect(code).toBe(0);
// Verify prod-strict applies defaultStrictUnsafeConfirm: true
const config1 = JSON.parse(await readFile(path.join(root1, ".agentplane", "config.json"), "utf8"));
expect(config1.execution?.strict_unsafe_confirm).toBe(true);
const root2 = await mkGitRepoRoot();
await configureGitUser(root2);
code = await runCli(["init", "--yes", "--setup-profile", "dev-safe", "--root", root2]);
expect(code).toBe(0);
// Verify dev-safe applies defaultStrictUnsafeConfirm: true
const config2 = JSON.parse(await readFile(path.join(root2, ".agentplane", "config.json"), "utf8"));
expect(config2.execution?.strict_unsafe_confirm).toBe(true);
});
🤖 Prompt for AI Agents
In `@packages/agentplane/src/cli/run-cli.core.init-upgrade-backend.test.ts` around
lines 901 - 911, Add assertions after each successful runCli invocation in the
test "init accepts setup-profile strict variants" to verify that preset-specific
defaults were applied: for the prod-strict run (after runCli with
"--setup-profile", "prod-strict") read the generated configuration (use the same
helper used elsewhere in tests to load repo config or parse the config file in
the repo root created by mkGitRepoRoot) and assert that defaultHooks === true
and defaultStrictUnsafeConfirm === true; for the dev-safe run load that run's
generated config and assert defaultStrictUnsafeConfirm === true (and any other
dev-safe-specific defaults expected). Reference the existing helpers
mkGitRepoRoot, configureGitUser, and runCli to locate where to plug in the
config-load and expect(...) assertions.


it("init rejects invalid --workflow values", async () => {
const root = await mkGitRepoRoot();
const io = captureStdIO();
Expand Down
10 changes: 5 additions & 5 deletions packages/agentplane/src/cli/run-cli/commands/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { ensureInitRedmineEnvTemplate } from "./init/write-env.js";
import { renderInitSection, renderInitWelcome } from "./init/ui.js";

type InitFlags = {
setupProfile?: "prod" | "dev";
setupProfile?: SetupProfilePreset;
ide?: "codex" | "cursor" | "windsurf";
workflow?: "direct" | "branch_pr";
backend?: "local" | "redmine";
Expand Down Expand Up @@ -119,10 +119,10 @@ export const initSpec: CommandSpec<InitParsed> = {
{
kind: "string",
name: "setup-profile",
valueHint: "<prod|dev>",
choices: ["prod", "dev"],
valueHint: "<prod|prod-strict|dev|dev-safe>",
choices: ["prod", "prod-strict", "dev", "dev-safe"],
description:
"Interactive preset. prod is the default and asks only essential questions; dev asks the full setup questionnaire.",
"Interactive preset. prod is default; prod-strict enables stricter defaults, dev asks the full questionnaire, and dev-safe adds stricter unsafe-action confirmations.",
},
{
kind: "string",
Expand Down Expand Up @@ -334,7 +334,7 @@ async function cmdInit(opts: {
let requireVerifyApproval = flags.requireVerifyApproval ?? defaults.requireVerifyApproval;
let executionProfile = flags.executionProfile ?? defaults.executionProfile;
let strictUnsafeConfirm = flags.strictUnsafeConfirm ?? defaults.strictUnsafeConfirm;
let setupProfile: "prod" | "dev" = flags.setupProfile ?? "prod";
let setupProfile: "prod" | "dev" = setupProfilePresets[flags.setupProfile ?? "prod"].mode;
let setupProfilePreset: SetupProfilePreset = flags.setupProfile ?? "prod";
const isInteractive = process.stdin.isTTY && !flags.yes;

Expand Down