|
1 | 1 | # CLAUDE.md |
2 | 2 |
|
3 | 3 | **[AGENTS.md](./AGENTS.md) is the source of truth for working in this repo — read it.** |
4 | | -Its Prime Directives are binding. Do not rely on this file alone; the four rules that |
5 | | -must never be missed are inlined here because missing any one of them wastes or corrupts |
6 | | -other agents' work. |
| 4 | +Its Prime Directives are binding: each of the four rules that must never be missed is |
| 5 | +inlined below as one sentence, its enforcing hook, and a pointer to the AGENTS.md heading. |
7 | 6 |
|
8 | 7 | ## ⛔ Claim the issue before you write any code |
9 | 8 |
|
10 | | -Assign the issue to yourself (`gh issue edit <n> --add-assignee @me`, or `issue_write` with |
11 | | -`assignees`) as the **first action of the task** — before the worktree, before the first read. |
12 | | -Several agents work this repo at once and an unassigned issue reads as an open invitation: two |
13 | | -that start on it burn the same hours twice, then race to land conflicting shapes. Already |
14 | | -assigned to someone else? It is taken — pick another or ask; never reassign it. File findings |
15 | | -unassigned when only recording; assign at the moment you start. |
16 | | - |
17 | | -All agents share one GitHub identity, so the assignee field can't tell you whether a claim |
18 | | -is **yours** — a claim is assign **plus a claim comment with your session ID and branch** |
19 | | -(`claude/issue-<n>-<slug>`), and before writing code you must re-read the comments: an |
20 | | -earlier claim with a different session ID means it's taken, whatever the assignee says. |
21 | | -(Skipping that read is how one issue got implemented twice in one morning.) |
| 9 | +Claim it **before any other action**: assign yourself *and* comment your session ID and |
| 10 | +branch — the shared identity makes the assignee field no proof, so re-read the comments. |
| 11 | +No hook enforces this one. Full rule: AGENTS.md → **Multi-agent working discipline**, its |
| 12 | +paragraph **Claim the issue BEFORE you write any code.** |
22 | 13 |
|
23 | 14 | ## ⛔ Worktree-first — before your FIRST file edit (AGENTS.md Prime Directive #11) |
24 | 15 |
|
25 | | -This repo — **and every sibling repo you touch (`objectui`, `cloud`)** — is edited by |
26 | | -**multiple agents at once**. The shared primary checkout has its HEAD switched and its |
27 | | -tree reset *under you*, silently clobbering uncommitted work. **A feature branch on the |
28 | | -shared checkout is NOT enough** — it still gets switched under you. You MUST be in a |
29 | | -**dedicated per-task worktree**: |
30 | | - |
31 | | -``` |
32 | | -git fetch origin main && git worktree add --no-track ../<repo>-<task> -b <branch> origin/main && cd ../<repo>-<task> && pnpm install |
33 | | -``` |
34 | | - |
35 | | -Then make all edits there. This applies **per repo**: if a task spans `framework` and |
36 | | -`objectui`, create a worktree in *each*. Two PreToolUse hooks enforce this, and both check |
37 | | -the target file's **own** repo (so sibling repos are covered): `guard-main-checkout.sh` |
38 | | -blocks `Edit`/`Write`/`NotebookEdit`, and `guard-main-checkout-bash.sh` blocks the same |
39 | | -write as a **Bash** command (`>`/`>>`, `sed -i`, `perl -i`, `tee`, `cp`, `mv`, `rm`, |
40 | | -`touch`) — reads are never blocked, and anything it cannot parse confidently is allowed |
41 | | -through, so the rule still outranks the hook. Non-task exception (both hooks, one switch): |
42 | | -`OS_ALLOW_MAIN_EDITS=1`. Follow the rule because it's correct, not because the hook fires. |
| 16 | +Never edit a shared primary checkout — this repo's or any sibling repo's (`objectui`, |
| 17 | +`cloud`); its HEAD and tree move under you. One dedicated worktree per task, per repo. |
| 18 | +Hooks in `.claude/hooks/`: `guard-main-checkout.sh` (Edit/Write/NotebookEdit) and |
| 19 | +`guard-main-checkout-bash.sh` (the same writes as Bash); override `OS_ALLOW_MAIN_EDITS=1`. |
| 20 | +Full rule: AGENTS.md → **Prime Directives**, directive 11. |
43 | 21 |
|
44 | 22 | ## ⛔ Never `git stash` — the stash stack is NOT covered by worktree isolation |
45 | 23 |
|
46 | | -`git stash` keeps its stack in `refs/stash` inside the **common `.git` directory**, so |
47 | | -**every worktree of the repo shares one LIFO stack**. ⚠️ It is one CASE, not an exception: |
48 | | -a worktree isolates your checkout and exactly four ref namespaces (`HEAD`, `refs/bisect`, |
49 | | -`refs/worktree`, `refs/rewritten`) and nothing else — `refs/remotes/*` is shared too, so a |
50 | | -sibling's fetch moves *your* `origin/main` (AGENTS.md §9 carries the full rule). Two agents |
51 | | -stashing in their own worktrees push and pop the *same* stack — your `pop` restores what |
52 | | -the other agent pushed a moment earlier, and your own changes stay on the stack for them to |
53 | | -take. `pop` reports **success**; the only symptom is someone else's files appearing in your |
54 | | -`git status`, and a following `git add -A` merges their work into your PR. Not |
55 | | -hypothetical: it happened between two parallel agents mid reverse-verification and cost |
56 | | -both of them their in-flight changes, recoverable only as unreachable commits. |
57 | | - |
58 | | -Use one of these instead — no shared state, all inside your own worktree: |
59 | | - |
60 | | -``` |
61 | | -git diff > /tmp/wip.patch && git checkout -- <paths> # then: git apply /tmp/wip.patch |
62 | | -git commit -am wip # then: git reset --soft HEAD~1 |
63 | | -git worktree add ../objectstack-<task>-cmp <ref> # a second tree to compare against |
64 | | -``` |
65 | | - |
66 | | -A PreToolUse hook (`.claude/hooks/guard-shared-stash.sh`) enforces this — it blocks the |
67 | | -`Bash` commands that push/pop/drop/clear the stack, and allows the forms that cannot take |
68 | | -another agent's entry: `git stash list`/`show`/`create`, and `git stash apply <sha>` / |
69 | | -`store <sha>` pinned to a **literal hex object id** (never `stash@{N}` — that is a |
70 | | -*position* in a stack you don't own). Deliberate exception: `OS_ALLOW_STASH=1`. Changing |
71 | | -the hook? Re-run `.claude/hooks/guard-shared-stash.selftest.sh`. |
| 24 | +`refs/stash` lives in the common `.git` dir, so all worktrees share one LIFO stack: your |
| 25 | +`pop` takes another agent's entry and reports **success** — use a patch or a wip commit. |
| 26 | +Hook `guard-shared-stash.sh` enforces it (override `OS_ALLOW_STASH=1`; re-run its |
| 27 | +`.selftest.sh` if you change it). Full rule: AGENTS.md → **Multi-agent working discipline**. |
72 | 28 |
|
73 | 29 | ## ⛔ Never edit `content/docs/releases/` in a code PR |
74 | 30 |
|
75 | | -Release notes are written **centrally, at release time** — not accreted one PR at a time. |
76 | | -Every code/feature/retirement PR appending its own row to the current |
77 | | -`releases/v<major>.mdx` turns that file into the single hottest merge-conflict magnet in |
78 | | -the repo (with ~18 merges to `main` in a working day, the same table conflicts over and |
79 | | -over, and each resolution risks dropping someone else's row). Your PR's inputs to the |
80 | | -release notes are the **changeset** (`.changeset/*.md` — one file per change, never |
81 | | -conflicts) and, for spec removals, the ADR-0087 registries; the release process compiles |
82 | | -them. If a releases page has a factual error, file an issue or make it a dedicated |
83 | | -docs-only PR — never a rider on code changes. |
| 31 | +Release notes are written **centrally, at release time**, never accreted a row per PR; a |
| 32 | +factual error there is a dedicated docs-only PR or an issue, never a rider on code changes. |
| 33 | +No hook: your PR's input to them is its **changeset** (`.changeset/*.md`). Full rule: |
| 34 | +AGENTS.md → **Documentation Guardrails**, its `content/docs/releases/` row. |
84 | 35 |
|
85 | | -See **AGENTS.md** for the full playbook: branch hygiene, the dev stack, PR flow, and the |
86 | | -rest of the Prime Directives. |
| 36 | +See **AGENTS.md** for the rest: branch hygiene, the dev stack, PR flow, the Prime Directives. |
0 commit comments