| 1 | # π€ suite |
| 2 | |
| 3 | The shared repository of the Oficina suite. See `README.md` for what it |
| 4 | holds. This file is binding. Where it disagrees with a general skill, this |
| 5 | file wins. |
| 6 | |
| 7 | --- |
| 8 | |
| 9 | ## The one rule |
| 10 | |
| 11 | > **Cite, never restate.** |
| 12 | |
| 13 | This repository exists because five app specs each restated one contract |
| 14 | in their own words and the copies drifted. A rule that lives here is |
| 15 | stated here once. An app spec names the ruling number and the commit it |
| 16 | read; it does not paraphrase. A paraphrase in an app spec is a bug in that |
| 17 | spec, fixed by replacing it with a citation. |
| 18 | |
| 19 | The same rule binds this repository in the other direction: the home's |
| 20 | calls 1 to 6 belong to the home spec and are cited here, not restated. |
| 21 | |
| 22 | --- |
| 23 | |
| 24 | ## Authorship |
| 25 | |
| 26 | - Every ruling carries who made it and when. "This session" is a valid |
| 27 | author and is marked as such so a reader can tell a ruling from a |
| 28 | proposal. |
| 29 | - A design here is not approved until a review pass by the |
| 30 | highest-capability model available, recorded by name in the status |
| 31 | block. The author of a draft cannot be its reviewer. |
| 32 | - Rejected alternatives are recorded beside the ruling that rejected |
| 33 | them, so nobody proposes them again in good faith without seeing why. |
| 34 | |
| 35 | ## The contract module |
| 36 | |
| 37 | - Additive only. A removed field is a new major version. |
| 38 | - No rastrillo dependency. The module is types, fixtures and a thin |
| 39 | client, so the pin chain from an app is one deep. |
| 40 | - Fixtures are the interface. A fixture is added with the first client |
| 41 | that needs it and corrected by the second implementation, never |
| 42 | designed from two specs at once. |
| 43 | - Every constant carries its reason in a comment: a cap, a deadline, a |
| 44 | TTL. |
| 45 | |
| 46 | ## Discussions |
| 47 | |
| 48 | Cross-repository requests go through `amadan discuss` on the repository |
| 49 | whose text must change. A request asks for a boundary to be recorded, not |
| 50 | for a ruling to be reversed, and says which of the two it is. |
| 51 | |
| 52 | ## The checkout on disk can lie |
| 53 | |
| 54 | `amadan branch merge` lands a branch on the **remote**. It does not touch |
| 55 | any working checkout, including this repository's own. So a session that |
| 56 | merges its work and then walks away leaves the repository on disk showing |
| 57 | the state before the merge β and the next reader, human or session, sees |
| 58 | that state with nothing on screen saying it is behind. |
| 59 | |
| 60 | **Two rules follow.** |
| 61 | |
| 62 | **Fetch before you read a spec you did not just write**, in this repository |
| 63 | or a sibling. A grep of a stale checkout is not evidence, and it is |
| 64 | confident in exactly the same way a fresh one is. |
| 65 | |
| 66 | **Fast-forward the shared checkout after you merge.** Your worktree is not |
| 67 | where anybody else looks. |
| 68 | |
| 69 | This is written down because it happened, at length, on 2026-09-05. Every |
| 70 | merge of the doctrine and the contract module went to the remote through |
| 71 | `amadan branch merge`, and the shared checkout sat on the initial commit |
| 72 | with an empty `docs/superpowers/specs/` for the whole session. A peer |
| 73 | session on `oficina/home` spent an entire coordination pass reading a |
| 74 | *worktree* rather than a commit, and only knew to flag it because three |
| 75 | commits it was given for one revision failed to line up. Had they lined up, |
| 76 | it would have cited a working tree and neither of us would have known. |
| 77 | |
| 78 | The failure to guard against is not that empty directory β that one is |
| 79 | loud. It is the quiet version: a session reading a file that is merely a |
| 80 | few commits behind, citing it with a commit hash that resolves, and being |
| 81 | wrong about the text. Suite gate 9 checks that a citation's revision |
| 82 | belongs to its commit; nothing checks that the reader read the commit. |
| 83 | |
| 84 | ## Work in a worktree, and catch main up first |
| 85 | |
| 86 | Take a worktree for the work. Do not work in the shared checkout. |
| 87 | |
| 88 | git -C <repo> fetch origin |
| 89 | git -C <repo> worktree add ../<repo>-<task> -b <branch> origin/main |
| 90 | |
| 91 | Both halves matter, for different reasons. |
| 92 | |
| 93 | **The worktree**, because several sessions share this machine and some |
| 94 | share this repository, and a checkout has one HEAD, one index and one |
| 95 | working tree between all of them. A branch switch under somebody else's |
| 96 | uncommitted work destroys it with nothing on screen to say so, and two |
| 97 | sessions editing the same paths disagree quietly instead of conflicting |
| 98 | loudly. A worktree gives the work its own HEAD and its own files, and |
| 99 | costs a directory. |
| 100 | |
| 101 | **From `origin/main`, after a fetch** β not from whatever the checkout |
| 102 | happens to be sitting on. A branch cut from a stale main is a merge |
| 103 | conflict scheduled for later, against files somebody else has renamed in |
| 104 | the meantime. A branch cut from another task's branch is worse: it |
| 105 | carries that task's commits into yours, where they are reviewed as |
| 106 | though you wrote them, and the two can only be separated by hand. |
| 107 | |
| 108 | Remove it when the work has landed β `git worktree remove` β so that |
| 109 | `git worktree list` keeps saying something true. |
| 110 | |
| 111 | Written down because of 2026-09-17, in `meet`. The shared checkout was |
| 112 | sitting on one task's branch while holding a *different* task's feature |
| 113 | uncommitted on disk β some four hundred lines, a new migration among |
| 114 | them β put there by a session nobody else knew was working in that tree. |
| 115 | Two other sessions were meanwhile coordinating over the same checkout by |
| 116 | asking each other not to touch it, which is the arrangement a worktree |
| 117 | makes unnecessary. Nothing was lost. Nothing about the arrangement would |
| 118 | have said so if it had been, and by then the same feature existed twice, |
| 119 | once on each side of a rename, because the two sessions had branched |
| 120 | from different starting points. |
| 121 | |