onboarding a project¶
a project is a namespace: a github repo that receives approved specs as PRs.
every spec belongs to exactly one, via namespace: owner/repo frontmatter or
the board's default. only repos on the operator-controlled allowlist take
part in the PR flow; specs pointing anywhere else get a red namespace chip
and never open PRs.

prerequisites¶
- a github repo to hold the specs. features can live in other repos (see
implementation-reposbelow). - the board's service token (
GITHUB_TOKEN) needs contents read/write and pull requests read/write on the repo. - spec authors have write access on the repo and log in to the editor via github. login asks for no repo permissions, so spec PRs open under the board's service token rather than the author.
steps¶
- commit
.specs/roles.ymlto the repo's default branch:
approvers: [octocat, hubot] # GitHub logins allowed to approve
approvals-required: 2 # quorum; default 1, explicit 0 disables it
implementation-repos: [owner/app] # scanned for "implements #N"; default: this repo
commit-prefix: spec # PR/commit type; "" for a bare title
areas: [api, design, client] # optional allowlist; also enables tag routing
specs-dir: specs # dir specs land in; "." for the repo apex
a spec picks its area with area: api in the note frontmatter and lands
as specs/<area>/NNN-<slug>.md (specs/NNN-<slug>.md without one). any
area routes by default; declare areas to restrict the set and to let a
matching note tag route as fallback.
-
protect the default branch and add a CODEOWNERS rule for
specs/**(*in a repo-mode specs repo, see below). board approvals are cooperative workflow; the merge review on the spec PR is the enforceable gate. don't skip this and expect the board to be your security boundary. -
add the repo to the board's
NAMESPACESenv (comma-separated) and roll the deployment. to make it the default for specs with no namespace, also setDEFAULT_NAMESPACEon the board andCMD_SPEC_DEFAULT_NAMESPACEon the editor; the two must match. -
verify with
curl https://<board-host>/api/namespaces:repo,push, androlesshould bepass(protectionstaysunknownwhen the token can't read branch protection, which is fine),poller.staleshould befalse.
roles.yml semantics¶
- approvers come only from this file, never from the editable note; the note
records
approved-bybut the roster and quorum are repo-controlled. approvals-requiredis clamped to the approver count. malformed values fall back to 1; an explicit 0 turns quorum off.- unresolved comment threads block approval regardless of quorum.
areas(legacy key:categories): optional. without it, anyarea:frontmatter routes as its slug and tags never route. with it, an unlisted area is ignored and the first note tag matching the list is the fallback. spec numbering (NNN) is per directory, and the area is pinned when the PR opens, so later frontmatter or tag edits never re-path an existing PR.implementation-repos: repos scanned forimplementscommits. omit when features land in the spec repo itself.specs-dir: where specs land..(or"") publishes at the repo apex:<area>/NNN-<slug>.md, nospecs/dir. any other value is a subdir, nesting allowed (docs/specs). changing it orphans already-published specs: they stay where they are, and numbering starts over in the new dir.
repo mode¶
a repo that holds nothing but specs can commit roles.yml at the repo root
instead of .specs/roles.yml. that flips the specs-dir default to the
apex; set specs-dir explicitly to override in either direction. with the
apex layout, point CODEOWNERS at * instead of specs/**.