blob: 7c25b479ef88b8ac164e638914800ad0efb39ef6 [file] [view]
<!-- SPDX-License-Identifier: Apache-2.0
https://www.apache.org/licenses/LICENSE-2.0 -->
# AGENTS — spec-loop operational context
This file is the **operational** context for the spec-loop only:
build/validate commands, the repository map, and the branch rules. It is
loaded by the loop's prompts in addition to the repository-wide
[`/AGENTS.md`](../../AGENTS.md), which still governs everything (commit
trailers, placeholder convention, privacy/security posture). Where the
two overlap, the repo-wide `AGENTS.md` wins.
## Repository map (what the loop edits)
This repo has no `src/` tree. Work lands in one of:
- `.claude/skills/<name>/SKILL.md` — agent-readable skills (Markdown +
YAML frontmatter; required keys `name`, `description`, `license`).
- `tools/<tool>/` — deterministic Python tools (`uv`, hatchling,
`src/` + `tests/`, `dependencies = []` where possible).
- `docs/` — human-facing documentation. `docs/rfcs/` is the **separate**
governance layer — the loop never edits it.
- `tools/spec-loop/specs/` — the specs this loop consumes.
## Validation commands (the build "backpressure" step)
Run the spec's own **Validation** block first. General checks:
```bash
# Validate skill definitions (frontmatter, links, placeholders)
uv run --project tools/skill-and-tool-validator --group dev skill-and-tool-validate
# Validate the compact inventory helper
uv run --project tools/spec-inventory --group dev pytest tools/spec-inventory/tests
# A skill's behavioural eval suite (every skill must have one)
uv run --project tools/skill-evals skill-eval tools/skill-evals/evals/<skill-name>/
# A tool's own tests (substitute the tool path)
uv run --project tools/<tool> --group dev pytest
# Shell scripts
bash -n <script>.sh && shellcheck <script>.sh
```
There is no repo-wide test runner; validate the specific surface the
spec touches. If a work item adds or changes a **skill**, it must also
add/extend that skill's eval suite under
`tools/skill-evals/evals/<skill-name>/` (per `/AGENTS.md` § Reusable
skills — a skill without an eval suite is incomplete). If a work item
adds a **tool**, that tool ships its own tests. Both must pass before
commit.
## Branch rules (the user's constraint: one branch per fix/feature)
- **Never commit feature work to the integration branch.** Build mode
branches `<slug>` off the integration branch (`$SPEC_LOOP_BASE`,
default: `main`) first.
- **One spec per branch, one branch per PR.** Do not bundle specs.
- A feature branch edits only **its own** spec's `status:` (→ `done`) —
not sibling specs and not `IMPLEMENTATION_PLAN.md` (avoids cross-branch
conflicts; the plan is reconciled by a later `plan` pass).
- The **`update`** beat (specs fell behind code others contributed)
branches `sync-specs-<timestamp>` and edits `specs/` **only** — it
documents reality, it never changes a skill, tool, or doc outside the
spec dir. The runner, not the prompt, owns `.last-sync`.
- The runner feeds each iteration **both** the open PRs and the local
work-item branches as in-flight work. Because the loop never pushes, a
built-but-un-pushed item exists only as a local branch with no PR, so the
local-branch list (not just open PRs) is what prevents the loop from
rebuilding the same item every iteration.
## Hard limits (governance — do not cross)
- **No push, no PR.** `git push` and `gh pr create` are in the `ask`
list of `.claude/settings.json`. The loop stops at a local commit and
prints the human-run commands. Opening the PR is the human's click.
- **No `.claude/settings.json` edits** (it is in the `deny` list).
- **No new network/filesystem allowances.** Run inside the existing
sandbox.
## Commits
- Imperative subject describing the user-visible change.
- Trailer `Generated-by: <agent> (<model>)`, where `<agent>` and `<model>`
are the actual agent and model you are running as (e.g. `Claude (Opus
4.8)`, `OpenCode (Big Pickle)`) — do not hardcode either. **Never**
`Co-Authored-By` with an agent (repo-wide `AGENTS.md` § Commit and PR
conventions).
- One commit per build iteration (the change + its spec `status` flip).