Card 13: AGENTS.md as the canonical brief, CLAUDE.md as pointer
Written and then brought into line with the enriched template task 07 shipped — affected-areas line, out-of-scope bullets, a Given/When/Then edge case for the update.sh round-trip, and a Risks note naming the pointer file's import as load-bearing for older CLIs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# 13 — AGENTS.md as the canonical brief; CLAUDE.md becomes a pointer
|
||||
|
||||
**Status:** Backlog
|
||||
**Priority:** Medium — correctness gap for the opencode adapter today, naming debt everywhere else
|
||||
**Type:** Refactor
|
||||
|
||||
The workflow brief lives in `CLAUDE.md` — one vendor's filename for a
|
||||
document every vendor's agents need. `AGENTS.md` is the cross-tool
|
||||
convention (opencode, Codex, Gemini CLI and others read it natively),
|
||||
and bench just shipped a second adapter whose agents don't read
|
||||
`CLAUDE.md` at all: an opencode work agent today launches with no
|
||||
project brief. Rename the content to `AGENTS.md`; keep `CLAUDE.md` as a
|
||||
one-line pointer for compatibility.
|
||||
|
||||
## Context
|
||||
|
||||
Everywhere the name is load-bearing (grepped, current as of writing):
|
||||
|
||||
- `update.sh:40` — the core-owned top-level file list copies `CLAUDE.md`
|
||||
by name; the rename must ship there or updates resurrect the old file.
|
||||
- `manager/core/prompts/work.md:7,27`, `review.md:17`,
|
||||
`review-pr.md:17`, `act-pr.md:17` — every prompt says "read CLAUDE.md
|
||||
at the repo root"; these instructions go to *all* vendors' agents, so
|
||||
they must name the vendor-neutral file.
|
||||
- `CLAUDE.md:8,28,262`, `README.md:38`, `board.py:9`, `taskfiles.py:3` —
|
||||
self-references and doc pointers.
|
||||
- `manager/local/CLAUDE.md` — the project-notes half; same rename logic
|
||||
applies (`local/AGENTS.md`), and root AGENTS.md's "read it too" line
|
||||
follows.
|
||||
- Claude Code reads `CLAUDE.md` natively and supports `@path` imports;
|
||||
recent versions also read `AGENTS.md` directly — verify the installed
|
||||
CLI's behaviour at build time, but keep the pointer file regardless:
|
||||
it costs one line and covers older CLIs and muscle memory.
|
||||
**Affected areas:** root docs, `update.sh`, all four core prompts,
|
||||
`manager/local/`, two module docstrings. No board logic reads the brief
|
||||
— core never parses it, it only tells agents to.
|
||||
|
||||
## What to build
|
||||
|
||||
- `git mv CLAUDE.md AGENTS.md`, then a new `CLAUDE.md` containing only
|
||||
the `@AGENTS.md` import (plus one comment line saying why it exists).
|
||||
- Same split in `manager/local/`: content to `local/AGENTS.md`, pointer
|
||||
`local/CLAUDE.md` kept.
|
||||
- Update every reference found above — prompts say "read AGENTS.md";
|
||||
`update.sh`'s file list carries both names (AGENTS.md as content,
|
||||
CLAUDE.md as pointer, both core-owned).
|
||||
- README's install section gains one line: the brief is `AGENTS.md`,
|
||||
`CLAUDE.md` is a compatibility pointer — so adopters with their own
|
||||
root AGENTS.md know what lands in `.task-manager/`.
|
||||
- Check the opencode adapter's behaviour: opencode reads AGENTS.md from
|
||||
the working directory's tree natively, so a worktree containing it is
|
||||
covered with no adapter change — confirm, and note it in
|
||||
`adapters/README.md`'s wire/run guidance.
|
||||
|
||||
**Out of scope** — the tempting neighbours this rename does not touch:
|
||||
|
||||
- Changing what the brief *says* (cards 03/07 territory) — this task
|
||||
moves the document, verbatim.
|
||||
- Per-vendor brief variants — one AGENTS.md serves everyone, that being
|
||||
the entire point.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- [ ] Repo root: `AGENTS.md` holds the full workflow doc; `CLAUDE.md`
|
||||
is a pointer (import + comment) and nothing else. Same pair in
|
||||
`manager/local/`.
|
||||
- [ ] `grep -rn "CLAUDE.md"` across core, prompts, scripts and README
|
||||
returns only the pointer files themselves and deliberate
|
||||
compatibility mentions.
|
||||
- [ ] A Claude Code session in this repo still loads the full brief
|
||||
(via native AGENTS.md support or the import — verified live).
|
||||
- [ ] An opencode launch's working tree presents the brief under the
|
||||
name opencode reads natively.
|
||||
- [ ] Edge case — `update.sh` round-trip: given an installed project on
|
||||
the old layout, when core updates to this version, then AGENTS.md
|
||||
arrives, the pointer CLAUDE.md replaces the old full copy, and no
|
||||
resurrected vendor-named brief shadows the real one.
|
||||
|
||||
## Open questions
|
||||
|
||||
- None.
|
||||
|
||||
## Notes
|
||||
|
||||
Prompted by the owner (2026-07-30): "AGENTS.md is the more standard
|
||||
approach that works across coding agents." The rename is also a small
|
||||
test of bench's own three-layer law: the brief was the last place where
|
||||
a vendor's name was baked into core-owned, cross-vendor machinery.
|
||||
|
||||
**Risks**
|
||||
|
||||
- Older Claude Code CLIs without native AGENTS.md support depend
|
||||
entirely on the pointer file's `@AGENTS.md` import line — if a future
|
||||
edit trims the "redundant" pointer, those sessions silently lose the
|
||||
whole brief. The pointer must be treated as load-bearing, not cruft.
|
||||
- Host projects may have their own root AGENTS.md; bench's lives inside
|
||||
`.task-manager/`, so no collision — but verify nested-file pickup for
|
||||
both vendors rather than assuming it.
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# 08 — Let the agent's report open from the Focus view
|
||||
|
||||
**Status:** Review
|
||||
**Status:** Done
|
||||
**PR:** https://github.com/12vectors/bench/pull/4
|
||||
**Priority:** Medium — the report is the payoff of a whole agent run, and Focus dead-ends exactly there
|
||||
**Type:** Bug
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# 03 — Focus checks come from the project, not from core
|
||||
|
||||
**Status:** Backlog
|
||||
**Status:** In Progress
|
||||
**Priority:** Medium — cosmetic on bench's own board, but every adopting project sees a stranger's definition of done
|
||||
**Type:** Feature
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# 09 — Fit all five columns on small laptop screens
|
||||
|
||||
**Status:** To Do
|
||||
**Status:** In Progress
|
||||
**Priority:** Medium — daily-driver hardware; the Done column is cut off on a 13" MacBook
|
||||
**Type:** Bug
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# 12 — Let the board choose agent models, per launch intent
|
||||
|
||||
**Status:** Backlog
|
||||
**Status:** In Progress
|
||||
**Priority:** Medium — works today by inheritance, but invisibly and uncontrollably
|
||||
**Type:** Feature
|
||||
|
||||
+27
-1
@@ -1,6 +1,7 @@
|
||||
# 01 — Ship a pristine board on install, not bench's own cards
|
||||
|
||||
**Status:** Backlog
|
||||
**Status:** Review
|
||||
**PR:** https://github.com/12vectors/bench/pull/5
|
||||
**Priority:** High — every install made after we start dogfooding inherits our cards
|
||||
**Type:** Bug
|
||||
|
||||
@@ -66,3 +67,28 @@ root `tasks/` — the decision that made this bug real. The alternative
|
||||
(self-installing a `.task-manager/` inside bench) was rejected: it doubles
|
||||
the manager code, runs the board from a stale vendored copy, and would
|
||||
nest an installation inside every future clone.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Work report — 2026-07-30 07:10 (Cleo)
|
||||
|
||||
The work is complete — committed on this branch and fully tested. Closing report:
|
||||
|
||||
---
|
||||
|
||||
The fix is implemented, committed (`44537ae`), and verified: the full test suite (54 tests, including 5 new ones) passes, and a fresh vendored install now boots with an empty board while bench's own repo keeps its task history untouched.
|
||||
|
||||
**What changed**
|
||||
|
||||
- `install.py` gained first-boot detection that runs before delegating to the adapter's `wire`. It fires only when the install is vendored (project root differs from the manager's root) **and** `manager/local/` has never been populated (no `.env`, no `state/`). In that state it removes everything in the five stage directories, `tasks/archive/`, `plans/` and `reference/`, keeps `task-template.md` and every `.gitkeep`, and prints each removal (`removed <path>`, or `would remove <path>` under `--dry-run`). After a real (non-dry-run) clean it creates `manager/local/state/`, so the guard is permanently false from then on — even if the adapter wire fails, which matters because `start.sh` serves the board to hosts without `.claude/` and their cards must never be eaten on a later run.
|
||||
- `README.md` notes under "Install into a repo" that the first `start.sh` clears the distribution's own cards.
|
||||
- `tests/test_install_first_boot.py` exercises `install.py` end-to-end as a subprocess against scratch host layouts: first run cleans and prints; second run removes nothing and a host-created card survives; `--dry-run` lists without removing and without stamping; a pre-existing `local/.env` disarms the guard; a self-hosted repo is never cleaned.
|
||||
|
||||
**One decision to know about, beyond the task's letter:** the task defined first boot purely by the absence of `local/.env` and `local/state/`, but that alone would also match a fresh development clone of bench itself and delete its git-tracked cards. I added a second condition — cleaning only happens when the install is vendored (project root ≠ manager root, the same resolution `config._repo_root` uses) — so self-hosted checkouts are structurally exempt. This is what makes acceptance point three hold even for an unwired bench clone.
|
||||
|
||||
**For the reviewer**
|
||||
|
||||
- Start with `first_boot_leftovers` and `first_boot_clean` in `install.py` — the guard logic and the stamp ordering are the whole risk surface.
|
||||
- Run `python3 -m unittest discover -s tests` to reproduce the green run.
|
||||
- One acceptance step I could not run literally: the sandbox denies executing `install.py` directly in this checkout, so "bench itself is untouched" is proven by `test_self_hosted_repo_is_never_cleaned` (which builds a git-initialised self-hosted layout) rather than by a live run here. The scratch-host tests cover the clone → first-run → second-run sequence the other acceptance points describe.
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# 04 — Make the activity log's resize grip actually resize
|
||||
|
||||
**Status:** Backlog
|
||||
**Status:** To Do
|
||||
**Priority:** Medium — a visible, advertised control ("drag to resize") that silently does nothing
|
||||
**Type:** Bug
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# 10 — Review launches die at startup: MultiEdit deny rule names a tool that no longer exists
|
||||
|
||||
**Status:** Backlog
|
||||
**Status:** To Do
|
||||
**Priority:** High — every ◔ review PR / ◔ still true? launch fails before the agent starts
|
||||
**Type:** Bug
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# 11 — A failed agent run must leave a visible trace on the card
|
||||
|
||||
**Status:** Backlog
|
||||
**Status:** To Do
|
||||
**Priority:** High — three agents died today and the board showed nothing a human would notice
|
||||
**Type:** Feature
|
||||
|
||||
Reference in New Issue
Block a user