Skip to content
Open
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
90 changes: 34 additions & 56 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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/<name>.py` that defines a module-level `COMMAND`:

```python
Expand Down Expand Up @@ -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/<name>.py` (the `--help` USAGE string)
and `docs/commands/<name>.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
Expand All @@ -213,62 +231,22 @@ subprocess) so `include <BOSL2/std.scad>` resolves with no manual step.

## Commit discipline (mandatory, every change)

1. **Atomic commits** — one logical change each. Message form: `<area>: <what changed>`
(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 `<area>: <what changed>` (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) <noreply@anthropic.com>`

Expand Down
Loading