From 3e5917cbccca9fe72f5d14c28b4c0c281ea0a46b Mon Sep 17 00:00:00 2001 From: "Alex H. Raber" Date: Mon, 25 May 2026 23:00:58 -0700 Subject: [PATCH 1/2] feat: implement non-interactive initialization with --proof flag - Add `--proof` flag to `decapod init` to bypass all interactive prompts. - Automatically target the current directory and use defaults when `--proof` is set. - Update agent entrypoint templates (AGENTS.md, etc.) to use `decapod init --proof` for smart bootstrapping. - Update documentation and payload examples to reflect the non-interactive standard. - Add test case to verify `--proof` behavior in `tests/init_config_behavior.rs`. --- .decapod/README.md | 2 +- AGENTS.md | 2 +- CLAUDE.md | 2 +- CODEX.md | 2 +- GEMINI.md | 2 +- README.md | 6 +++--- docs/agent/payload-examples.md | 2 +- docs/book/src/quickstart.md | 4 ++-- src/cli.rs | 6 ++++++ src/core/assets.rs | 6 +++--- src/lib.rs | 8 ++++++-- tests/init_config_behavior.rs | 21 +++++++++++++++++++++ 12 files changed, 47 insertions(+), 16 deletions(-) diff --git a/.decapod/README.md b/.decapod/README.md index fe3b803f..0844cf49 100644 --- a/.decapod/README.md +++ b/.decapod/README.md @@ -14,7 +14,7 @@ It keeps Decapod-owned state, generated artifacts, and isolated workspaces separ ## Quick Start -1. `decapod init` +1. `decapod init --proof` 2. `decapod validate` 3. `decapod rpc --op constitution.get --params '{"section":"core/DECAPOD"}'` 4. `decapod session acquire` diff --git a/AGENTS.md b/AGENTS.md index 28839ad5..b6ffd6a5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,7 +14,7 @@ This is a Decapod-managed repository. **Strict Dependency: You are strictly boun ```bash # Smart bootstrap: only install/init if a newer version is available -(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init) +(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init --proof) decapod docs ingest && decapod validate && decapod session acquire decapod rpc --op agent.init decapod workspace status diff --git a/CLAUDE.md b/CLAUDE.md index bc404a7e..c01521f7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -22,7 +22,7 @@ See `AGENTS.md` for the universal contract. ```bash # Smart bootstrap: only install/init if a newer version is available -(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init) +(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init --proof) decapod docs ingest && decapod validate && decapod session acquire decapod rpc --op agent.init decapod workspace status diff --git a/CODEX.md b/CODEX.md index 1171a28e..eac5e620 100644 --- a/CODEX.md +++ b/CODEX.md @@ -22,7 +22,7 @@ See `AGENTS.md` for the universal contract. ```bash # Smart bootstrap: only install/init if a newer version is available -(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init) +(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init --proof) decapod docs ingest && decapod validate && decapod session acquire decapod rpc --op agent.init decapod workspace status diff --git a/GEMINI.md b/GEMINI.md index 99ed55d6..f06ef812 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -22,7 +22,7 @@ See `AGENTS.md` for the universal contract. ```bash # Smart bootstrap: only install/init if a newer version is available -(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init) +(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init --proof) decapod docs ingest && decapod validate && decapod session acquire decapod rpc --op agent.init decapod workspace status diff --git a/README.md b/README.md index 8799258a..47488bb0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

🦀

- cargo install decapod && decapod init + cargo install decapod && decapod init --proof

@@ -36,10 +36,10 @@ Decapod provides comprehensive documentation for both human operators and AI age ```bash cargo install decapod -decapod init +decapod init --proof ``` -`decapod init` creates `.decapod/`, a local folder your agent uses to remember intent, rules, context, specs, and proof. +`decapod init --proof` creates `.decapod/`, a local folder your agent uses to remember intent, rules, context, specs, and proof. Your **conversational** workflow does not change. You keep working through your agent; Decapod gives the agent the missing control plane. Intent is captured, scope is bounded, context is shaped, protected areas are respected, work is isolated, and completion is proven against the project’s rules and the Decapod constitution. diff --git a/docs/agent/payload-examples.md b/docs/agent/payload-examples.md index 0da154c9..79899c71 100644 --- a/docs/agent/payload-examples.md +++ b/docs/agent/payload-examples.md @@ -52,7 +52,7 @@ Efficiently install and initialize Decapod only when updates are available. ### Version-Aware Installation ```bash # Checks crates.io and installs/refreshes only if a newer version exists -(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init) +(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init --proof) ``` ## Subsystem Queries diff --git a/docs/book/src/quickstart.md b/docs/book/src/quickstart.md index 4513b650..3082ec2d 100644 --- a/docs/book/src/quickstart.md +++ b/docs/book/src/quickstart.md @@ -12,10 +12,10 @@ cargo install decapod ## 2. Initialization -Initialize your repository. This creates the `.decapod/` directory and scaffolds the initial agent entrypoints (`AGENTS.md`, etc.). +Initialize your repository. This creates the `.decapod/` directory and scaffolds the initial agent entrypoints (`AGENTS.md`, etc.). Use the `--proof` flag for non-interactive agent-driven setup. ```bash -decapod init +decapod init --proof ``` ## 3. Orientation diff --git a/src/cli.rs b/src/cli.rs index 3a41953e..6861562a 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -115,6 +115,9 @@ pub(crate) struct InitGroupCli { /// Force creation of all 4 entrypoint files (AGENTS.md, CLAUDE.md, GEMINI.md, CODEX.md). #[clap(long)] pub all: bool, + /// Support non-interactive agent initialization for proof-gated flows. + #[clap(long)] + pub proof: bool, /// Create only CLAUDE.md entrypoint file. #[clap(long)] pub claude: bool, @@ -188,6 +191,9 @@ pub(crate) struct InitWithCli { /// Force creation of all 4 entrypoint files (AGENTS.md, CLAUDE.md, GEMINI.md, CODEX.md). #[clap(long)] pub all: bool, + /// Support non-interactive agent initialization for proof-gated flows. + #[clap(long)] + pub proof: bool, /// Create only CLAUDE.md entrypoint file. #[clap(long)] pub claude: bool, diff --git a/src/core/assets.rs b/src/core/assets.rs index 5dfc40bb..f6050b97 100644 --- a/src/core/assets.rs +++ b/src/core/assets.rs @@ -247,7 +247,7 @@ See `AGENTS.md` for the universal contract. ```bash # Smart bootstrap: only install/init if a newer version is available -(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init) +(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init --proof) decapod docs ingest && decapod validate && decapod session acquire decapod rpc --op agent.init decapod workspace status @@ -311,7 +311,7 @@ This is a Decapod-managed repository. **Strict Dependency: You are strictly boun ```bash # Smart bootstrap: only install/init if a newer version is available -(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init) +(decapod capabilities --format json | grep -q '"is_latest":true') || (cargo install decapod && decapod init --proof) decapod docs ingest && decapod validate && decapod session acquire decapod rpc --op agent.init decapod workspace status @@ -416,7 +416,7 @@ It keeps Decapod-owned state, generated artifacts, and isolated workspaces separ ## Quick Start -1. `decapod init` +1. `decapod init --proof` 2. `decapod validate` 3. `decapod rpc --op constitution.get --params '{"section":"core/DECAPOD"}'` 4. `decapod session acquire` diff --git a/src/lib.rs b/src/lib.rs index a656badb..31b51553 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1300,6 +1300,7 @@ fn init_with_from_config( dir: Some(target_dir), project_dir: None, force, + proof: false, dry_run, all: all_entrypoints, claude: has("CLAUDE.md"), @@ -1622,6 +1623,8 @@ pub fn run() -> Result<(), error::DecapodError> { )? } else if let Some(dir) = init_group.dir.as_ref() { resolve_existing_init_dir(dir)? + } else if init_group.proof { + resolve_existing_init_dir(¤t_dir)? } else if io::stdin().is_terminal() { prompt_init_target_dir(¤t_dir)? } else { @@ -1679,7 +1682,7 @@ pub fn run() -> Result<(), error::DecapodError> { } with } else { - let diagram_style = if io::stdin().is_terminal() { + let diagram_style = if io::stdin().is_terminal() && !init_group.proof { prompt_diagram_style(init_group.diagram_style)? } else { init_group.diagram_style @@ -1688,6 +1691,7 @@ pub fn run() -> Result<(), error::DecapodError> { dir: Some(target), project_dir: None, force: init_group.force, + proof: init_group.proof, dry_run: init_group.dry_run, all: init_group.all, claude: init_group.claude, @@ -1732,7 +1736,7 @@ pub fn run() -> Result<(), error::DecapodError> { // Only do full TUI experience if not refreshing an existing project let is_refresh = init_target.join(".decapod").exists(); - if base_init_invocation && io::stdin().is_terminal() && !is_refresh { + if base_init_invocation && io::stdin().is_terminal() && !is_refresh && !init_with.proof { enrich_repo_context_interactive(&mut repo_ctx)?; } let target_dir = run_init_apply(&init_with, ¤t_dir, &repo_ctx)?; diff --git a/tests/init_config_behavior.rs b/tests/init_config_behavior.rs index 151a4ea7..cb0d94f2 100644 --- a/tests/init_config_behavior.rs +++ b/tests/init_config_behavior.rs @@ -150,6 +150,27 @@ fn init_uses_existing_config_for_noninteractive_defaults() { ); } +#[test] +fn init_with_proof_bypasses_interaction_and_initializes_cwd() { + let tmp = tempdir().expect("tempdir"); + // Ensure it's a git repo so init works correctly + let _ = std::process::Command::new("git") + .arg("init") + .current_dir(tmp.path()) + .output() + .expect("git init"); + + let out = run_decapod(tmp.path(), &["init", "--proof"]); + assert!( + out.status.success(), + "decapod init --proof failed: {}", + String::from_utf8_lossy(&out.stderr) + ); + + assert!(tmp.path().join(".decapod").is_dir()); + assert!(tmp.path().join("AGENTS.md").is_file()); +} + #[test] fn init_with_accepts_noninteractive_spec_seed_flags() { let tmp = tempdir().expect("tempdir"); From ca99535b36323a38acbba0ee2c345a1aa5885102 Mon Sep 17 00:00:00 2001 From: "Alex H. Raber" Date: Mon, 25 May 2026 23:09:19 -0700 Subject: [PATCH 2/2] style: run cargo fmt --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 31b51553..8a428d64 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1736,7 +1736,8 @@ pub fn run() -> Result<(), error::DecapodError> { // Only do full TUI experience if not refreshing an existing project let is_refresh = init_target.join(".decapod").exists(); - if base_init_invocation && io::stdin().is_terminal() && !is_refresh && !init_with.proof { + if base_init_invocation && io::stdin().is_terminal() && !is_refresh && !init_with.proof + { enrich_repo_context_interactive(&mut repo_ctx)?; } let target_dir = run_init_apply(&init_with, ¤t_dir, &repo_ctx)?;