diff --git a/AGENTS.md b/AGENTS.md index e999faa..5bea5e1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,6 +2,16 @@ Instructions for AI agents (and humans) working in this repository. English only. +> **Portable dev rules live in the global agent-tools skills:** +> github.com/alex-mextner/agent-tools (`skills/universal/` + `skills/by-type/cli`). +> They cover the stack-agnostic discipline this file used to spell out at length — atomic +> commits, push-regularly, AI review before commit, dead-code investigation, visual-proof +> cycle, GAN critic loop, and the CLI-shaped skills `self-registering-commands`, +> `lazy-heavy-imports`, `structured-exit-codes`, `help-docs-sync`, `idempotent-bootstrap`. +> This file keeps only what is **specific to `3d-cli`**: its command-authoring contract, +> the OpenSCAD/render/section toolchain, the proof bar for fit-camera/match work, the exact +> test gate, and the project's command surface. Read both. + ## What this is `3d` is a scriptable, AI-assisted CLI for the whole 3D FDM lifecycle — modeling, @@ -13,6 +23,9 @@ in `lib/*.py` and run through `cli.pyrun`. ## Adding a command (the command-authoring contract) +> The patterns behind this contract are the global skills `cli/self-registering-commands`, +> `cli/lazy-heavy-imports`, `cli/structured-exit-codes`. Below is `3d-cli`'s concrete instance. + A command is ONE module `lib/commands/.py` that defines a module-level `COMMAND`: ```python @@ -198,12 +211,17 @@ install command, graceful degrade — never a silent false PASS. `cli/env.py` is for tool discovery + the OS/install table.) ### Help text sync +> Generic rule: global skill `cli/help-docs-sync`. Project specifics: + Help text must be in sync between `lib/commands/.py` (the `--help` USAGE string) and `docs/commands/.md` (the doc fragment). Every flag/option must have a concrete example in both places. When a command's surface changes, both files must be updated in the same commit. ### First-run bootstrap +> Generic rule: global skill `cli/idempotent-bootstrap` (idempotent, non-fatal if offline). +> Project specifics: + On ANY `3d` invocation, if `~/.config/3d-cli/.bootstrapped` is absent, the dispatcher auto-installs the OpenSCAD libraries (BOSL2, NopSCADlib) into the repo `libs/` ONCE, quietly (one-line notice), then touches the marker. It is **idempotent** and **non-fatal @@ -213,62 +231,22 @@ subprocess) so `include ` resolves with no manual step. ## Commit discipline (mandatory, every change) -1. **Atomic commits** — one logical change each. Message form: `: ` - (e.g. `render: compute --view camera from bounding box`). No "update"/"fix" vagueness. -2. **Before every commit** run multi-model review in parallel, then iterate. Use the - shared read-only review runner as `review` on `$PATH`; install/update it from - `https://github.com/alex-mextner/review-cli` when missing: - ```bash - review -m codex -m gemini -m oc:fireworks/accounts/fireworks/routers/kimi-k2p6-turbo - ``` - Equivalent comma-separated form: - ```bash - review -m codex,gemini,oc:fireworks/accounts/fireworks/routers/kimi-k2p6-turbo - ``` - To force a narrower review question, pass an explicit prompt: - ```bash - review -m codex -m gemini -m oc:fireworks/accounts/fireworks/routers/kimi-k2p6-turbo --prompt "Review the current uncommitted diff for bugs, regressions, security issues, and missing tests. Return only actionable findings." - ``` - Optional extra reviewers run in addition to the baseline when available: - ```bash - review -m codex -m gemini -m oc:fireworks/accounts/fireworks/routers/kimi-k2p6-turbo -m claude-p -m oc:deepseek/deepseek-reasoner - ``` - Run this before staging. If changes are already staged, run the same command with - `--staged`; if both staged and unstaged changes exist, review both diffs separately. - `review` supports repeated or comma-separated `-m` values, runs reviewers in parallel, - and has a per-review timeout (`--timeout`, default 1200s). Backends are read-only by - design; keep the exact backend mechanics in the `review-cli` README - (`https://github.com/alex-mextner/review-cli`) rather than duplicating them here. Do - not print, paste into logs, or commit provider API keys. If `review` is unavailable, - install/update it from `https://github.com/alex-mextner/review-cli`, ensure it is on - `$PATH`, or fall back to equivalent direct read-only reviewer commands. The fallback - path must still attempt Codex plus the best available independent non-Codex reviewer: - ```bash - timeout 1200 codex exec review --uncommitted - gemini -p "Review the current uncommitted diff for bugs, regressions, security issues, and missing tests. Return only actionable findings." - # If Gemini CLI is unavailable or blocked by location/tier, use Gemini API directly: - git diff --no-ext-diff | timeout 300 uv run --with google-genai python -c 'import os, sys; from google import genai; diff = sys.stdin.read(); base = "Review the current uncommitted diff for bugs, regressions, security issues, and missing tests. Return only actionable findings."; print(genai.Client().models.generate_content(model=os.environ.get("GEMINI_MODEL", "gemini-2.5-flash"), contents=base + "\n\n" + diff).text)' - ``` - The staged/unstaged split applies to fallback commands too; use - `git diff --cached --no-ext-diff` for staged Gemini API fallback review. - Gemini CLI must already be configured. The direct Gemini API fallback requires - `GEMINI_API_KEY` or `GOOGLE_API_KEY` in the environment; never print either value. - The API fallback defaults to `gemini-2.5-flash` for parity with the current `review` - backend and speed; override with `GEMINI_MODEL` when a different Gemini model is - required. - READ every finding, fix the real issues, and run another review iteration after fixes. The minimum - acceptable pre-commit bar is Codex plus at least one independent non-Codex reviewer - from a different provider or model family; a second Codex run does not count. If a - configured reviewer is down, replace it with the best available independent model - first. Only when no independent non-Codex reviewer is available may the work fall below - that bar, and the provider-wide blocker must be recorded; do not silently treat - single-review work as fully reviewed. -3. **Push regularly — do NOT let work sit only on your local machine.** This project works - directly on `main` (that is where all history lives — no feature-branch dance). After each - commit or small batch, push: `git push origin main`. Pushing often means the work survives a - crash and is always visible. Never end a working session with unpushed commits — finish with - local `main` level with `origin/main`. -4. Don't mix unrelated changes in one commit. +> Generic rules in global skills `atomic-commits`, `ai-review-before-commit`, +> `push-regularly`. The project-specific deltas: + +1. **Atomic commits** — message form `: ` (e.g. + `render: compute --view camera from bounding box`). No "update"/"fix" vagueness; don't + mix unrelated changes. +2. **Before every commit** run multi-model review (see `ai-review-before-commit` for the + mechanics, and the `review` CLI / `review-cli` README for backends). The minimum bar for + THIS repo: Codex plus at least one independent non-Codex reviewer from a different + provider/model family — a second Codex run does not count. A typical invocation: + `review -m codex,gemini,oc:fireworks/accounts/fireworks/routers/kimi-k2p6-turbo` + (add `--staged` for staged-only diffs). Read every finding, fix the real issues, re-review. + If no independent non-Codex reviewer is available, record the provider-wide blocker; never + silently treat single-review work as fully reviewed. +3. **Push regularly.** This project works directly on `main` (no feature-branch dance) — after + each commit or small batch, `git push origin main`. Never end a session with unpushed commits. Co-Authored-By trailer on commits: `Co-Authored-By: Claude Opus 4.8 (1M context) `