diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e3d598..8027d51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,8 @@ CHANGELOG entry. ### Added +- **`atomic-agents init` wizard PR 2 of 2: researcher + writer templates + Add-to-it recovery merge + 8 polish items** ([#94](https://github.com/dep0we/atomic-agents-stack/issues/94) -- init-wizard arc **PR 2 of 2**, arc closer). Operators now have three starter templates instead of one: `advisor` (general-purpose, Cautious autonomy), `researcher` (curiosity-first investigator with research integrity layer 1 ON, raw/ source intake, $1.50/day cost cap for multi-source synthesis, Cautious preset), and `writer` (voice-first content agent with Sonnet primary + Haiku fallback, drafts/ + revisions/ write paths, Cautious preset). Each template declares its operating mode explicitly per spec/01 (advisor and writer reactive; researcher hybrid for sustained multi-session investigations). The advisor template gains an `## Operating mode` section so all three templates conform to spec/01's mode-declaration requirement. Re-running `atomic-agents init` on an existing agent now offers a third recovery branch: **Add to it** (in addition to Overwrite and Cancel). The collision prompt in `_check_collision` offers three options: overwrite, add_to_it, cancel. Choosing add_to_it triggers section detection via the ATX h2 state machine (`_extract_h2_headers`, `_detect_sections`): code fences, HTML comments, and YAML frontmatter are skipped to avoid false positives; setext-style headings (underline) fail closed. Detection failure routes the operator back to overwrite/cancel via a plain-English message. On detection success, `_compute_merged_content` performs a file-level section-aware merge for every file in `TEMPLATE_SECTION_SCHEMA[template_name]`: the preamble before the first h2 is preserved verbatim; orphan h2 sections (operator-authored, not in schema) are preserved verbatim in their original position; schema h2 sections merge with operator preamble + existing h3 subsections preserved in order + new template h3 subsections appended at end. A unified diff preview (`_render_diff_preview`) is shown with CRLF and UTF-8 BOM normalization so Windows-originating vaults do not show every line as changed; if zero files changed the preview exits early with "up to date" and skips the Confirm prompt. On confirmation, each file is committed via `_io.atomic_write` (tmp + fsync + rename) directly into `agent_dir` in sorted relpath order -- no staging directory. A mid-commit KeyboardInterrupt prints a summary of written vs pending files before re-raising so the operator knows exactly what landed. Operator-authored memory notes (under `memory/` except `INDEX.md`), journal entries, log files, and raw documents are never touched; schema-owned scaffolding files (`memory/INDEX.md`, `wiki/INDEX.md`) ARE rewritten because they are template-owned routing/structure files. Missing template-owned files trigger a backfill path (label `[new file]` in the diff preview). 8 polish items from PR 1 adversarial review land in this PR: `DEFAULT_AGENTS_ROOT` is now lazy-computed in `get_agents_root()` so test monkeypatches of `HOME` work correctly; `_doctor_handoff` splits its try/except around `run_doctor` and `render_human` so a render-phase failure surfaces the exit code rather than masquerading as inconclusive; `_from_template` gains a symmetric length check before the regex match so a too-long name produces the correct error message; `_test_call` extracts an `_types(mod, *names)` helper for the exception catalog so the dispatch reads cleanly and tolerates missing SDK installs; `_translate_oserror` adds a specific message for `errno.ENOENT` ("the folder disappeared between collision check and overwrite") so operators get actionable guidance instead of a generic write failure; `_walk_traversable` converts from recursion to iterative deque with a `MAX_TEMPLATE_DEPTH=16` cap to defend future deep template trees; backup and staging directory timestamps now include microseconds (`%Y%m%dT%H%M%S_%fZ`) so two simultaneous overwrites within the same second produce distinct names; the persona-backend warning prints a credential-redacted URL via a new `redact_url_credentials` helper (drops `user:pass@` from netloc while keeping scheme + host + path visible, fixing the original advisor-warning pattern that hid the host entirely). PR 1 adversarial Round 2 deferred a `KeyboardInterrupt` cleanup gap (the existing `except Exception` did not catch KeyboardInterrupt because it inherits from BaseException, not Exception); PR 2 restructures all wizard cleanup paths to `except BaseException` with explicit `KeyboardInterrupt` re-raise after cleanup, plus an outermost handler in `run_init` that prints `"Canceled."` and returns exit code 130 (when KI lands mid-`_commit_merges`, the per-commit summary already printed the written vs pending file list). `--from-template ` and `--list-templates` are now fully CI-friendly: the non-TTY guard and the API key pre-flight both carve out these paths (per amended spec/35 MUST 2, 7, and 11), so a CI build can scaffold an agent without an interactive terminal and without the operator setting `ANTHROPIC_API_KEY` at build time (doctor catches the missing key later at first run). `_cmd_list_templates` enumerates all three templates with one-line descriptions. The action class glosses in spec/28 amend to explicitly classify web search HTTP GETs as `read_only` (they do not change external state), so researcher templates use the same Cautious preset as advisor without paying judge_required overhead on every search query. spec/35 grows to 15 normative MUSTs with MUST 5 updated to distinguish operator-authored data files from schema-owned scaffolding files (memory/INDEX.md and wiki/INDEX.md are template-owned and ARE rewritten; operator notes, journal, log, raw are not) and a new MUST 15 documenting the section-detection algorithm and file-level merge contract. New constants in `atomic_agents/init/constants.py`: `TEMPLATE_PRESET_DEFAULTS` per-template preset map, `TEMPLATE_SECTION_SCHEMA` per-template per-file h2 header schema (the source of truth that Add-to-it section detection validates against), `MAX_TEMPLATE_DEPTH`, three new MSG_ constants for the new recovery flow paths, and the `redact_url_credentials` helper. New `atomic_agents/init/templates/researcher/` (7 files, 360 LOC) and `atomic_agents/init/templates/writer/` (7 files, 352 LOC) trees use the same 12 locked template variables as advisor with template-specific section schemas. 59 net new tests across `test_init_cli.py` (--list-templates enumerates 3; researcher and writer choices accepted; unknown still rejected), `test_init_wizard.py` (section detection state machine; Add-to-it dispatch + detection; detection-failure fallback to cancel; file-level merge success + failure + KI-safe; _split_sections/_join_sections round-trip; _compute_merged_content preamble preservation + orphan h2 position + h3 preservation; CRLF + BOM normalization; all 8 polish items; per-template preset dispatch), `test_init_templates.py` (researcher + writer schema conformance; structural conformance per spec/01; ALL template variables used; zero em dashes per template; Operating mode sections present), and `test_init_smoke.py` (researcher and writer e2e happy paths; --from-template works without API key per the P3 carve-out). Test suite: 2939 + 50 skipped to 3051 collected, zero regressions. Pre-impl prep (4 parallel subagents) caught 13 SEVERE + 15 HIGH + 17 MEDIUM + 13 LOW = 58 findings across the brief BEFORE any code shipped (exceeding PR 1 of #94's 53 findings in a smaller scope), including 6 SEVERE locks emerged from cross-corroboration (known_templates not expanded with cli.py choices, `_default_template_vars` hardcoding the advisor preset for all templates, Operating mode section missing from IDENTITY.md across all templates, KeyboardInterrupt bypassing the cleanup block, TEMPLATE_SECTION_SCHEMA values not locked in the brief, spec/35 MUST 5 + MUST 15 text not drafted in the brief). Three architectural decisions surfaced via AskUserQuestion gates: web search action class (locked to read_only with spec/28 amendment), writer template model default (Sonnet primary + Haiku fallback with Opus upgrade path documented inline), and --from-template carve-out from MUST 7 (no API key required for scaffold; CI-friendly end-to-end). With PR 2 of the arc landing, Issue #94 closes: the half-day home-user deploy is now an under-10-minute first-run experience with three starter shapes plus a non-destructive recovery flow for re-running on existing agents. + - **`atomic-agents init` wizard** ([#94](https://github.com/dep0we/atomic-agents-stack/issues/94) -- init-wizard arc **PR 1 of 2**). Operators can now run `atomic-agents init ` and have a callable home-user agent in under 10 minutes, including time spent thinking about what the agent should be. The wizard walks seven structured questions (name, mission, scope in/out, autonomy, voice, communication preferences, hard refusals), composes `persona/{IDENTITY,SOUL,USER}.md` + `tools.md` + `model.md` + `memory/INDEX.md` + `wiki/INDEX.md` deterministically from the answers, creates empty `journal/` and `log/` directories, and ends with a `doctor` health check on the new agent followed by an opt-in test call against the configured LLM. `--from-template advisor` skips the interview and scaffolds a Caldwell-shaped starter agent in under 30 seconds. `--list-templates` enumerates available templates. Re-running `init` on an existing agent name offers Overwrite (atomic backup+restore: rename existing to `.bak.`, write fresh, rmtree backup on success, restore on failure) or Cancel (default; pressing Enter is a no-op exit). The wizard refuses non-interactive terminals on the interactive Q&A path with a plain-English pointer to `--from-template`; `--from-template ` and `--list-templates` work in CI without a terminal. The opt-in test call catches `anthropic.RateLimitError`, `anthropic.AuthenticationError`, `anthropic.APIConnectionError` / `httpx.ConnectError`, `AtomicAgentsError`, and generic `Exception` with operator-friendly messages; every exception path exits status 0 (the scaffold succeeded; the call is best-effort). The wizard warns before any file write when `ATOMIC_AGENTS_PERSONA_BACKEND_URL` is set non-empty (the case where wizard output diverges from PersonaBackend's view); decline exits 0 with zero files written. ANTHROPIC_API_KEY pre-flight uses `_llm._get_key` directly so operators with the key in macOS Keychain or `~/.config/atomic_agents/keys.json` are not false-negatived. Closes the half-day deploy: the brief's seven pain points compress from approximately 4-5 hours total to approximately 5-10 minutes, with `mcp.md` configuration (pain 5) the only one explicitly deferred (`doctor` skips cleanly when absent). `rich` adopted as the canonical operator-facing CLI rendering library (documented in spec/35 as the rendering primitive future arcs migrate `doctor`, `bundle`, and `corpus` output to). spec/35 ships with 14 normative MUSTs that the implementation honors and that the adversarial review army verifies. New `atomic_agents/init/` package with `wizard.py` (the interactive flow), `constants.py` (the single source of truth for action class vocabulary, template variable names, error messages, reserved names, and the `agent_name` regex), and `templates/advisor/` (seven `.md` files using `string.Template` `${var}` substitution via `safe_substitute`). cli.py edits are bounded to one lazy import (inside `_cmd_init`, matching the existing pattern at `_cmd_doctor` and `_cmd_persona`), one `sub.add_parser("init", ...)` block with arguments, one dispatch case in the doctor/persona/corpus early branch, plus two Usage / Subcommands docstring lines. 50 net new tests across 5 files (`test_init_cli.py` argparse + dispatch, `test_init_wizard.py` Q1-Q7 + Q4 preset/customize + non-TTY + persona-backend warning + collision recovery + OSError translation + template substitution + agents_root single-resolution, `test_init_templates.py` advisor structure + locked variable conformance, `test_init_smoke.py` end-to-end with mocked LLM, `test_init_wheel_install.py` opt-in wheel build + install verification gated by `RUN_WHEEL_INSTALL_TESTS=1`). Test suite: 2889 + 48 skipped to 2939 + 50 skipped, zero regressions. Pre-impl prep (4 parallel subagents) caught 8 SEVERE + 21 HIGH + 16 MEDIUM + 8 LOW findings across the brief BEFORE any code shipped, including the Q4 action-class vocabulary mismatch (the brief used shorthand `audit`/`judge` where spec/28 defines `allow_with_audit`/`judge_required`), the hatchling force-include misconfiguration (templates auto-include via existing `packages = ["atomic_agents"]`; the brief's "add a force-include line" was a no-op or build break), the pre-flight resolver chain incompleteness (Keychain and `keys.json` operators got false-negative on env-var-only check), the USER.md "Things to avoid" section missing (Q7 originally routed only to tools.md; now renders to both with surface-appropriate phrasing per the persona-vs-enforcement separation), and the overwrite atomicity gap (`rm -rf` then write is not crash-safe; backup+restore preserves operator work). - **CorpusBackend wiring + per-runner kwargs + delegate threading + doctor + IRON RULE regression suite** ([#65](https://github.com/dep0we/atomic-agents-stack/issues/65) -- CorpusBackend arc **PR 3 of 4**). The wiring PR turns the Protocol scaffolded in PR 1 and the SQLite impl shipped in PR 2 into something single-host operators can pin via one env var. `ATOMIC_AGENTS_CORPUS_BACKEND=sqlite` now resolves to `SQLiteCorpusBackend` with a sensible default db at `/.corpus.db` and `agent_scope=` (mirroring the `AgentProfileBackend` and `ToolRegistryBackend` precedent). `ATOMIC_AGENTS_CORPUS_BACKEND_URL` overrides the default path; both `filesystem://...` and `sqlite:///path?agent_scope=...` URLs route through their respective factories. `AtomicAgent` gains a `corpus_backend` constructor kwarg + class-level annotation; resolution defaults via `get_default_corpus_backend(self.agent_root)` when not supplied. `_corpus_backend_was_explicit` flag tracking on `self` (mirrors PersonaBackend D-ER-2 at `agent.py:431`) drives explicit-only threading at `delegate()`: default-resolved backends do NOT leak the coordinator's `agent_root` into delegates because corpus is per-agent semantic context, not fleet-scoped. Per-runner kwargs land on `OutcomeRunner` (threads through to the internal `AtomicAgent` at `outcome.py:255`), `EvalRunner` (threads at `eval.py:363`), and `DreamRunner` (stored as `self._corpus_backend` for API parity; no internal `AtomicAgent` construction site in v1 -- documented in the runner). `doctor.check_corpus_backend` lands as the 12th `check_*_backend` in `doctor.py` with PASS/WARN/FAIL ladder: PASS on healthy filesystem or sqlite construction + successful stats probes on both wiki and raw corpora; WARN on the page-count cliff (any corpus exceeding ~1000 pages on a backend that advertises `supports_full_text_search=False`, with the hint `"Set ATOMIC_AGENTS_CORPUS_BACKEND=sqlite for indexed query performance. Filesystem keyword grep at this scale can take seconds per query."`); WARN on operator-implicit URL configuration (URL set, backend id unset; surfaces the implicit-default resolution path rather than forcing operators to debug which backend is active); FAIL on construction error or stats() probe failure, with URL credential redaction through the existing `_redact_for_error_message` helper. Capability snapshot in the FAIL/WARN detail dicts includes `backend_id`, `supports_full_text_search`, `supports_semantic_search`, `supports_versioning`, `embedding_provider`, `wiki_page_count`, `raw_page_count`. Call-site migration at `agent.py:2937-2939` (the wiki/INDEX.md read in `_load_indexes`) routes through `corpus_backend.render_index_summary(corpus="wiki")` when configured; `bundle.py:_render_memory_breakpoint` (line 494) gains a `corpus_backend: CorpusBackend | None = None` parameter threaded all three levels (`render_bundle` -> `_render_sections` -> `_render_memory_breakpoint`). A new shared helper `_render_wiki_index_section(label, path, content)` produces the canonical `## {label}\n`{path}`\n\n{content}` bundle format used by both the Protocol path and the legacy fallback, guaranteeing byte-identical output between paths (IRON RULE assertion 4). `bundle.py:_source_paths` migration deferred to v1.1 (filesystem-only function; SQLite has no equivalent path to track for staleness; follow-up issue filed at PR 4). `cli.py:_cmd_corpus` swaps the hardcoded `FilesystemCorpusBackend(agent_root)` for `get_default_corpus_backend(agent_root)` so operators who pin via env var see consistent behavior between runtime and CLI (closes a CLI-vs-runtime drift). **IRON RULE 5-assertion regression suite** lands at `tests/test_corpus_migration_regression.py`: agent.py None-fallback byte-identity, agent.py explicit-backend Protocol-vs-direct agreement, bundle.py None fallback, bundle.py explicit-backend agreement, plus the OSError soft-degrade behavior for the legacy path. The 9 wiki-touching tests previously created empty wiki dirs and never asserted on INDEX content; 2 load-bearing ones in `tests/test_agent_cascade_integration.py` (`test_cascade_assembled_prompt_contains_all_layers` and `test_cascade_assembled_prompt_order_matches_spec_06`) gain a real wiki/INDEX.md fixture + content assertions + section-ordering assertions, closing the silent-corruption risk class flagged by the prep pass. 35 net new tests across 4 new files (`test_corpus_composition.py` flag tracking + delegate threading, `test_corpus_migration_regression.py` IRON RULE, `test_corpus_wiring.py` env var + runner kwargs + CLI activation, `test_corpus_doctor.py` PASS/WARN/FAIL ladder + page-count cliff + URL redaction) plus 2 augmented existing integration tests and 2 new bundle tests (3-level threading + `_source_paths` v1.1 deferral guard). Test suite: 2853 -> 2888 + 48 skipped, zero regressions. Pre-impl prep (4 parallel subagents) caught 4 SEVERE + 11 HIGH + 9 MEDIUM + 8 LOW findings pre-code, including the SQLite-branch-missing-in-get_default_corpus_backend gap that the PR 1 scaffolding left as a documented TODO. Round 1 adversarial review caught 10 additional findings + 2 pre-landing review findings; 8 high-confidence findings applied as fixes folded into the PR (see the Round 1 fix bullet below). diff --git a/atomic_agents/_platform.py b/atomic_agents/_platform.py index 10ab02a..2de1e5f 100644 --- a/atomic_agents/_platform.py +++ b/atomic_agents/_platform.py @@ -7,20 +7,23 @@ import os from pathlib import Path +# Module-level constant kept for backward compat with any external imports. +# get_agents_root() does NOT reference this constant; it computes fresh on +# each call so test monkeypatches of HOME work correctly. New code should +# call get_agents_root() rather than referencing this constant directly. DEFAULT_AGENTS_ROOT = (Path.home() / "docs" / "agents").expanduser().resolve() def get_agents_root() -> Path: - """Resolve the agents-root directory. + """Resolve the agents root from env var or default to ~/docs/agents. - Order: ATOMIC_AGENTS_ROOT env var → default ~/docs/agents. - - Operators with a custom vault location override via the env var. + Reads HOME and ATOMIC_AGENTS_ROOT on EVERY call (not at import time) so + tests that monkeypatch HOME after framework import see the correct value. """ env_val = os.environ.get("ATOMIC_AGENTS_ROOT") if env_val: return Path(env_val).expanduser().resolve() - return DEFAULT_AGENTS_ROOT + return (Path.home() / "docs" / "agents").expanduser().resolve() def get_agent_root(agent_name: str, agents_root: Path | None = None) -> Path: diff --git a/atomic_agents/cli.py b/atomic_agents/cli.py index 199be67..c5a1893 100644 --- a/atomic_agents/cli.py +++ b/atomic_agents/cli.py @@ -395,8 +395,8 @@ def main(argv: list[str] | None = None) -> int: "--from-template", dest="from_template", default=None, - choices=["advisor"], - help="skip Q&A; scaffold from a starter template", + choices=["advisor", "researcher", "writer"], + help="skip Q&A; scaffold from a starter template (advisor, researcher, or writer)", ) init_cmd.add_argument( "--list-templates", diff --git a/atomic_agents/init/constants.py b/atomic_agents/init/constants.py index ba0a220..b304383 100644 --- a/atomic_agents/init/constants.py +++ b/atomic_agents/init/constants.py @@ -81,6 +81,201 @@ }, } +# Per-template autonomy preset defaults. Used by _default_template_vars in wizard.py +# when --from-template is invoked without going through the interactive Q&A. +# All three templates default to Cautious per the design decisions: +# - advisor: Cautious is the home-user-safe default per PR 1 +# - researcher: Cautious because web search APIs are classified read_only +# (spec/28 amended in PR 2), so the rare outbound action (email a summary) +# correctly escalates rather than going through judge_required overhead +# - writer: Cautious because publishing is a high-stakes external action that +# the operator must approve per draft +TEMPLATE_PRESET_DEFAULTS: Final[dict[str, str]] = { + "advisor": PRESET_CAUTIOUS, + "researcher": PRESET_CAUTIOUS, + "writer": PRESET_CAUTIOUS, +} + +# Section schema for Add-to-it recovery merge per spec/35 MUST 15. +# Maps template name -> file relpath -> ordered list of exact h2 header strings. +# The wizard's section-detection state machine compares an existing file's +# extracted h2 headers against this schema. When they match, the wizard +# offers Add-to-it. When they don't match, the wizard fails closed and +# offers Overwrite or Cancel only. +TEMPLATE_SECTION_SCHEMA: Final[dict[str, dict[str, list[str]]]] = { + "advisor": { + "persona/IDENTITY.md": [ + "Who I am", + "Mission", + "Scope", + "Operating doctrine", + "Operating mode", + "Autonomy ladder", + "What I'm NOT (the bright lines)", + ], + "persona/SOUL.md": [ + "Voice", + "Posture", + "Evolution discipline", + "Things I have learned about this operator", + ], + "persona/USER.md": [ + "Role and context", + "Communication preferences", + "Things to avoid", + "Supporting professionals (when to recommend outside help)", + ], + "tools.md": [ + "Read paths", + "Write paths (own folder ONLY)", + "External APIs", + "Hard NOs (absolute, no exceptions)", + "Soft NOs (require explicit operator override)", + "Read budget", + "Tool failure behavior", + ], + "model.md": [ + "Default model", + "Fallback", + "Token budget", + "Prompt caching strategy", + "Cost guardrail", + "Research integrity", + ], + "memory/INDEX.md": [ + "Critical Feedback", + "Locked Decisions", + "User Profile", + "Active Projects", + "Reference", + "Recently Promoted to Persona", + "Archive (superseded)", + ], + "wiki/INDEX.md": [ + "Background and context", + "Reference material", + "How wiki pages cite sources", + ], + }, + "researcher": { + "persona/IDENTITY.md": [ + "Who I am", + "Mission", + "Scope", + "Operating doctrine", + "Operating mode", + "Research integrity", + "Autonomy ladder", + "What I'm NOT (the bright lines)", + ], + "persona/SOUL.md": [ + "Voice", + "Posture", + "Evolution discipline", + "Things I have learned about this operator", + ], + "persona/USER.md": [ + "Role and context", + "Communication preferences", + "Things to avoid", + "Supporting professionals (when to recommend outside help)", + ], + "tools.md": [ + "Read paths", + "Write paths (own folder ONLY)", + "External APIs", + "Hard NOs (absolute, no exceptions)", + "Soft NOs (require explicit operator override)", + "Read budget", + "Tool failure behavior", + ], + "model.md": [ + "Default model", + "Fallback", + "Token budget", + "Prompt caching strategy", + "Cost guardrail", + "Research integrity", + ], + "memory/INDEX.md": [ + "Critical Feedback", + "Research Conclusions", + "User Profile", + "Active Investigations", + "Reference", + "Recently Promoted to Persona", + "Archive (superseded)", + ], + "wiki/INDEX.md": [ + "Source citations", + "Pending distillation", + "Background and context", + "Reference material", + "How wiki pages cite sources", + ], + }, + "writer": { + "persona/IDENTITY.md": [ + "Who I am", + "Mission", + "Scope", + "Operating doctrine", + "Operating mode", + "Autonomy ladder", + "What I'm NOT (the bright lines)", + ], + "persona/SOUL.md": [ + "Voice", + "Posture", + "Evolution discipline", + "Things I have learned about this operator", + ], + "persona/USER.md": [ + "Role and context", + "Communication preferences", + "Things to avoid", + "Revision and consistency preferences", + "Supporting professionals (when to recommend outside help)", + ], + "tools.md": [ + "Read paths", + "Write paths (own folder ONLY)", + "External APIs", + "Hard NOs (absolute, no exceptions)", + "Soft NOs (require explicit operator override)", + "Read budget", + "Tool failure behavior", + ], + "model.md": [ + "Default model", + "Fallback", + "Token budget", + "Prompt caching strategy", + "Cost guardrail", + "Research integrity", + ], + "memory/INDEX.md": [ + "Critical Feedback", + "Locked Decisions", + "User Profile", + "Active Projects", + "Reference", + "Recently Promoted to Persona", + "Archive (superseded)", + ], + "wiki/INDEX.md": [ + "Background and context", + "Reference material", + "How wiki pages cite sources", + ], + }, +} + +# Maximum directory depth the template walk will traverse. Defensive cap +# against future template trees that ship deeply nested structures. +# Current advisor template is 3 levels deep (templates//persona/IDENTITY.md). +MAX_TEMPLATE_DEPTH: Final[int] = 16 + # --------------------------------------------------------------------------- # agent_name validation # --------------------------------------------------------------------------- @@ -143,8 +338,9 @@ MSG_NO_TTY: Final = ( "This command needs an interactive terminal. For non-interactive use, run " - "`atomic-agents init --from-template advisor` to scaffold a Caldwell-shaped " - "agent. See `atomic-agents init --list-templates` for other options." + "`atomic-agents init --from-template