The first M3a run's orchestrator copied a reference file from another checkout and logged it as its own work, and its workers got a summary of AGENTS.md instead of the file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
107 lines
6.0 KiB
Markdown
107 lines
6.0 KiB
Markdown
# AGENTS.md
|
|
|
|
Boxmaker is a personal agent harness in Rust: a Cargo workspace of small daemons that talk over
|
|
Unix sockets. You are implementing it one task at a time.
|
|
|
|
## How you work
|
|
|
|
1. The owner gives you one task file, `docs/plans/M<n>/NN-name.md`. Read it fully. Do that task and
|
|
nothing else. Do not start the next task.
|
|
2. Do the steps in order. Where a step shows a command and its expected output, run it and compare.
|
|
3. Do not read `docs/design.md` or other plans unless the task tells you to. The task file quotes
|
|
what you need.
|
|
4. If something in the task is impossible, contradictory, or fails twice in the same way, **stop**.
|
|
Do not improvise, do not change a test, do not weaken a check. Add your row to
|
|
`docs/implementer-log.md` with status `stopped`, say what you tried and what happened, commit
|
|
only that file, and tell the owner.
|
|
A later session that finishes the task adds a new `done` row; it never edits the `stopped`
|
|
row, because the record of the stop is part of the log.
|
|
5. Work only from files inside this repository. Never read another checkout or worktree (such as
|
|
`~/src/boxmaker-ref`), and never search the file system for code (`find /`, `locate`). If you
|
|
are stuck, stop as in point 4; copying code from elsewhere is not finishing the task.
|
|
6. If you hand a task to another agent, tell it to read `AGENTS.md` and the task file itself. Do
|
|
not pass on your own summary of either. Log what the agent did, as it did it.
|
|
|
|
## Files you must never edit
|
|
|
|
- `docs/design.md`, `docs/decisions.md`, `docs/inference-contract.md`, `docs/specs/`, `docs/plans/`
|
|
- Anything a task told you to copy from `docs/plans/**/files/`: tests, fixtures, `Makefile`,
|
|
`deny.toml`, `scripts/test-gate-scripts.sh`. If a copied test fails, your code is wrong.
|
|
- `AGENTS.md`, `CLAUDE.md`
|
|
|
|
## Code rules
|
|
|
|
- Rust stable, edition 2024, `rust-version = "1.95"`. No `unsafe`. No async runtime.
|
|
- No dependency that the task file does not name. All external dependencies are declared in the
|
|
root `Cargo.toml` under `[workspace.dependencies]`, used with `name.workspace = true`, and have a
|
|
row in `docs/dependencies.md`.
|
|
- `proto` depends on no workspace crate. Every other crate depends on `proto` only, never on
|
|
another role crate.
|
|
- No source file over 500 lines.
|
|
- Library code never panics on input: no `unwrap`, `expect`, `panic!`, indexing that can go out of
|
|
bounds, or `as` casts that can lose data on untrusted values. Tests may use them.
|
|
- Errors are plain enums that implement `std::fmt::Display` and `std::error::Error`. No `anyhow`,
|
|
no `thiserror`.
|
|
- Do not silence a lint with `#[allow(...)]` unless the task says so. Fix the code.
|
|
- Keep struct fields and enum variants in the order the task gives. The order is the wire format.
|
|
- Formats we define (config, grants, IPC messages, log records) reject unknown fields. Formats
|
|
another program defines (the inference server's JSON, later Mattermost's) ignore them: those
|
|
programs send fields we do not use and add more over time. Each task says which kind it handles.
|
|
- Everything read from a socket is bounded, and a number that came from a peer is never used to
|
|
index, allocate or cast without a check.
|
|
- Comments say why, not what. Match the amount of commenting you see in the task's examples.
|
|
|
|
## Lessons from earlier reviews
|
|
|
|
These come from defects found in review. The evidence is in `docs/implementer-lessons.md`.
|
|
|
|
- When a rule says "every" or "everywhere", finish by listing each place it could apply (every
|
|
struct and enum in the file, every script, every branch) and check them one by one. An example
|
|
in a task shows one place; the rule covers all of them.
|
|
- A check must fail when it cannot do its job: missing input, unreadable file, a tool that errors.
|
|
Never throw errors away with `2>/dev/null`, `|| true` or an ignored `Result`.
|
|
- Report every problem you find, not only the first.
|
|
- Log every attempt, including one you abandon.
|
|
- Never end a turn by describing what you are about to do. Do it, then report.
|
|
- If a tool you were told to use does not exist, stop and say so. Do not invent a command in its
|
|
place.
|
|
- A `read` returns as soon as it has any data to give and blocks only when it has none.
|
|
- A rule about one path applies to every path that does the same thing, including early returns
|
|
and error paths the task did not walk through.
|
|
- A file that exists but cannot be read is an error. Only a missing file may count as absent.
|
|
|
|
## The gate
|
|
|
|
`make gate` must print `gate: ok` before a task is done. It runs offline: rustfmt, clippy with
|
|
warnings denied, all tests, cargo-deny, and the scripts in `scripts/`. Run `cargo fmt --all` before
|
|
the gate; rustfmt decides the order of `mod` and `use` lines, not you. After you add a dependency,
|
|
run `cargo build` once so that `Cargo.lock` is updated, then run the gate.
|
|
|
|
Useful while working: `cargo test -p <crate> --test <file>` runs one test file, and
|
|
`cargo test -p <crate> <name>` runs tests whose name contains `<name>`.
|
|
|
|
## Git
|
|
|
|
- Work on the branch the task names. One task is one commit.
|
|
- Stage only the paths the task lists: `git add <path> ...`. Never `git add -A` or `git add .`.
|
|
- Never push, amend, rebase, reset, or switch to another branch.
|
|
- Commit message: the subject line the task gives, a blank line, then this trailer:
|
|
`Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)`
|
|
|
|
## The implementer log
|
|
|
|
Before you commit, add one row to the table in `docs/implementer-log.md` and include the file in
|
|
the commit. Be honest: the log is how the owner judges the process, and a wrong row is worse than a
|
|
bad one.
|
|
|
|
| Column | What to write |
|
|
|---|---|
|
|
| Task | The task file name, for example `M1/03-proto-wire` |
|
|
| Date | Today's date, `YYYY-MM-DD` |
|
|
| Status | `done` or `stopped` |
|
|
| Gate runs | How many times you ran `make gate` |
|
|
| First gate | `pass` or `fail` for the first run |
|
|
| Deviations | Anything you did that the task did not say, or `none` |
|
|
| Notes | Problems you hit and how you solved them, in one or two sentences |
|
|
| Model | Write `?`. The owner fills this in. |
|