Files
sift/AGENTS.md
T
kyleandClaude Opus 5.5 103ec3d05a P6 during the run: split the runner task (02 core, 03 workers); guard.PreCheck as an owner commit; AGENTS.md: write code into files early
Task 02 (the whole runner) ended at 21:08 with no file and no commit: Ornith wrote the
implementation out in its reply (~700 lines), OpenCode compacted the session, and the model
then emitted a malformed tool call. It had also looked for the given test at a wrong path
("_files/…" relative to the plan: my ambiguity).

- 02-runner → 02-runner-core (types, Submit, Status, Touch, Cancel; no goroutines) and
  03-runner-workers; the given test split to match (runner_core_test.go gains three tests:
  queued storage, cancel while queued, Status never moves the lease); later tasks renumbered
  04-09 and every cross-reference checked.
- Copy paths spelled from the repo root.
- guard.PreCheck (+ its test) is committed here by the owner: the old task 05 told the
  implementer to edit internal/guard/, which AGENTS.md forbids. My contradiction.
- AGENTS.md rule 6: write code into files early, in small steps.
Both runner test files compile against a panic-only skeleton (the core file also alone) and
fail there on panic: todo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 21:14:08 -07:00

103 lines
5.6 KiB
Markdown

# AGENTS.md
sift is the fleet's fetch and search service for LLM agents: it fetches a URL through an SSRF
guard, cleans the result (HTML → Markdown, JSON, text, and from P5a PDF), optionally digests it
with a small model, and serves Hermes agents through a Firecrawl-compatible API. It is written in
Go and runs on orion under a hardened systemd unit. You are implementing it one task at a time.
## How you work
1. The owner gives you one task file, `docs/plans/<plan>/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 other task files, `docs/PLAN.md` or other phase docs 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.
5. Work only from files inside this repository. Never read another checkout, and never search the
file system for code. If you are stuck, stop as in point 4.
6. **Write code into files early and in small steps.** Start each new file with its types and
signatures, make it compile, then fill in one function at a time and run the tests as you go.
Never write a whole implementation out in your reply before putting it in a file: a long
session is compacted, and what was only in the reply is lost (P6 task 02, 2026-09-26).
## Files you must never edit
- `docs/plans/`, `docs/PLAN.md`, `docs/P*.md`, `AGENTS.md`, `tools/run-plan.sh`
- `internal/guard/` and `internal/auth/` — the SSRF guard and the key store are the security
boundary; no task changes them.
- `go.mod`, `go.sum`, `vendor/` — every dependency is already vendored. Never add a module and
never run `go get` or `go mod tidy`/`vendor`; the build is offline.
- `nix/` and `flake.nix`, unless the task names the exact change.
- Anything a task told you to copy from `docs/plans/**/_files/` — tests, fixtures,
`internal/pdftest` — in this plan **or any earlier one**. If a copied test fails, your code is
wrong. If a copied test can no longer be right because the task changes what it tested, that
is the owner's error: stop and report it.
## Code rules
- Go 1.26 (`go.mod`). Standard library plus what is already in `vendor/`.
- No **new** source file over 400 lines. Do not grow `internal/api/api.go`: new API code goes in
the new file the task names.
- Library code (`internal/...`) never panics on input: no `panic`, no indexing that can go out of
range on data from a file, a request, a PDF or a peer. Check lengths. `main` may exit with a
message.
- Errors are values: return them, wrap with `fmt.Errorf("...: %w", err)`. A check that cannot do
its job fails; it does not return "ok".
- **Never log, print or store a request or response body, a document's text or its title.** Log
lines carry caller, host, sizes, counts, durations and outcomes. For a restricted caller
(`PermitRestricted`) use the existing helpers (`logHost`, `restrictedLog`, `logErr`): they
already blank what must not be written.
- Anything read from the network, a child process or a file is bounded (`io.LimitReader`,
deadlines).
- Exported names, field names and JSON tags are exactly as the task gives them; the tests compile
against them.
- Comments say why, not what. `gofmt` decides layout.
## Lessons from earlier work (crossbar, same owner, same process)
- A type assertion on a value from outside your package uses the two-value form and handles
`false`.
- When a rule says "every" or "everywhere", finish by listing each place it applies and checking
them one by one.
- Never end a turn by describing what you are about to do. Do it, then report.
- Work only inside this repository. Scratch programs under `/tmp` or anywhere else are refused by
the sandbox, and **a refused tool call is not a reason to end the turn**: write the experiment
as a `_test.go` file inside the repository (delete it before committing), or reason it out.
- Never change when production code releases, flushes or records something just to make a given
test's timing pass. If a given test seems to check a value before the code could settle it,
that is the owner's bug: stop and report it.
## The gate
`make gate` must pass before a task is done:
```
make gate # gofmt check, go vet, go test -race ./..., staticcheck if installed
```
It runs offline against `vendor/`. Run `gofmt -w` on the files you touched first. `go test
./internal/<pkg>/` runs one package.
## 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, a short body if useful, then the
`Co-Authored-By:` trailer line the owner's prompt gives you, exactly, as the last line.
- A message with more than one line goes in `.state/commit-msg.txt` (inside the repository and
ignored by git; `/tmp` is refused) and is committed with `git commit -F .state/commit-msg.txt`.
## The implementer log
Before you commit, add one row to the table in `docs/implementer-log.md` and include the file in
the commit:
`| <plan>/<task> | <date> | done or stopped | <sessions> | gate pass/fail | deviations | what you did |`
Be honest: the log is how the owner judges the process. A deviation you log is a finding; one
you hide is a defect.