Resume from disk: read STATE.md first — it always says what's done, what's in flight, and what's next. Decisions live in docs/DECISIONS.md.
The product name, tagline, and version live ONLY in product.json at the repo root. Never hardcode the name in code. Docs/manifests may use the name in prose, but anything generated (CLI banner, --version, asset text) must read product.json. scripts/finalize.sh performs renames by updating product.json and regenerating derived references.
- Python ≥3.12 (dev box: 3.14), managed by uv (
pyproject.toml,uv run,uv sync). - Core library in
src/<pkg>/; umbrella CLI entry inpyproject.toml [project.scripts]. - All external binaries are called through the single adapter layer
src/<pkg>/adapters.py— neversubprocessdirectly from command modules. Adapters do capability detection. - Repo root doubles as a Claude Code plugin marketplace:
.claude-plugin/marketplace.json+plugins/<name>/.
- Python: type hints on public functions,
pathlib.Pathover strings, no global state, f-strings, stdlibargparse-free — we use the CLI framework chosen in Phase 2 (see docs/ARCHITECTURE.md). - Every CLI command MUST have: working
--help,--jsonflag when output is data, ≥1 test, graceful degradation when an optional binary is missing (actionable message + install hint, exit code 3 — never a traceback, never a silent no-op). - No stubs/TODO/placeholder code in shipped commands. Cut and document in
docs/FEATURES.mdinstead. - Wrap, don't rewrite: prefer proven libraries/binaries via the adapter layer; attribute in docs/LICENSES section.
0success1general/unexpected error (message to stderr, no traceback unless--debug)2bad usage/arguments (argparse-style)3missing optional dependency (message names the binary + install hint)4input file not found / unreadable / unsupported type5operation produced no result (e.g., search with no hits when--fail-empty)
uv run pytestfrom repo root runs everything. Fixtures intests/fixtures/(generated bytests/fixtures/generate.py; never hand-edit binaries).- Tests that need an optional binary must skip (with reason) when it's absent, not fail.
Subagents: read your spec in specs/, respect your write boundary exactly, and report: files touched, tests written+run (with real output), deviations from spec, open issues. Claims are verified by execution — write tests that actually run.
- Branch
main. Commits at phase gatesphase(N): ...and waveswave(N): .... - Never commit generated junk (see .gitignore); fixtures ARE committed once generated.