People/<you>/Promotions/, with
frontmatter naming the target-path, the source note, and a mode:
create (default), append, or patch — see modes
below. New knowledge — decisions in Company/Decisions/, standing
processes in Company/Playbook/ — uses the default mode: create and
targets a fresh file. Curated running files like Company/Memory.md stay
maintained by the admin; an agent updates an existing shared page only
through append or patch, never by targeting it with create._meta/, because a personal agent has no write
access to _meta/. That is deliberate: the agent can propose, never
publish.1brain promotions sweep --master /srv/brain/master
pending/ is a clean, provenance-stamped
candidate. For a mode: patch draft, sweep also stamps base-hash — a
sha256 of the target file as it stood at this moment — into the
queued promotion; that hash is what approval re-checks before it writes.123brain promotions list --master /srv/brain/master brain promotions approve p-1 --master /srv/brain/master --approver admin brain promotions reject p-2 --master /srv/brain/master --reason "belongs in the sales playbook, not Company"
promoted-by, approved-by, source, date). The approver
must be entitled to approve this promotion — an admin, or a lead of
the team whose space it targets (see Who approves) — a
blank name, an unknown one, or an ineligible colleague is refused, so
approved-by always points at someone entitled to publish. Rejections
move to rejected/ with the reason — a training signal for what this
company considers shareable.Brain
Promotions — so the moment a note crossed from private to shared is in
history alongside every ingest and write-back, whether the decision came
from the CLI or the dashboard.brain dashboard exposes this same gate as a live surface: the Promotions tab renders each pending item with its destination, a warning naming exactly who will be able to read it, a mode badge, and its full body — or, for a patch, a live diff against the current target — with Approve / Reject (reason required) and Sweep drafts actions wired to these same primitives. You pick who you are from a dropdown scoped to whoever is entitled to approve that item — admins for anything, plus that team's leads for a Teams/<team>/ item (remembered for next time) — rather than typing a name, so approvals can't carry a typo or name someone who isn't entitled to approve. It never bypasses the human gate — it is the human gate, with a nicer view.target-path. So approve re-validates the target at the moment it publishes — a hand-edited path that tries to escape the master root, or one that names a private space or a bare space root, is refused. Validation at draft time is not trusted to still hold at approve time.| Mode | Target must be | On mismatch |
create (default) | absent | refused — an approval can never silently overwrite a curated file like Company/Memory.md |
append | present | refused if the target is missing — nothing to append to |
patch | present and unchanged since sweep | refused if the target's sha256 no longer matches the base-hash sweep stamped on it |
create and append each refuse the one target state that would let them do damage — create can't overwrite, append can't invent a page from nothing. patch goes further because it replaces the whole file: at sweep time, brain promotions sweep hashes the target and stores that sha256 as base-hash on the queued promotion; at approval, approve re-hashes the live target and refuses to write if it no longer matches. This is deliberately honest about what the hash does and doesn't cover: it guards the pending→approve window (however long that queue sits), but a master edit landing between the agent drafting its patch and the sweep that stamps the hash isn't caught by it — the hash is taken from whatever the target looked like at sweep time, not when the agent read it. That's why approval is never just the hash check: brain promotions show <id> (and the dashboard's Promotions card) renders a live unified diff of the proposed body against the current target, computed fresh at review time, so the approver's own eyes are the second check.create or append mismatch, edit the pending file's target-path (or its mode) and approve again. This is how the Company/Intel/ wiki updates an existing page: the agent promotes with mode: append for an additive note, or mode: patch carrying the complete revised page, instead of drafting a separate addendum file.approve call, the dashboard's API, and the CLI all refuse a blank approver, one that isn't in the org roster, and one not entitled to approve that target (see Who approves). The rule lives in a single function — may_approve in brain/promotions.py, the promotions counterpart to may_decide for shares — so the surfaces cannot drift apart. However an approval arrives, the approved-by line resolves to a real person entitled to publish.| Target | Approver |
Teams/<team>/… | anyone with role: lead on that team, or an admin |
Company/… (the shared space) | an admin, at the dashboard or brain promotions approve |
Clients/<name>/… (entity spaces) | an admin |
may_approve in brain/promotions.py, the promotions counterpart to may_decide for shares — and every surface calls it.People/<lead>/Shares.md, listing each pending promotion into a team they lead — with what would be published: the body for create/append, a live unified diff for patch, capped at 4 KB with a notice pointing at brain promotions show <id> when truncated. Each item states who would be able to read it once approved, the same audience the dashboard card warns about.spaces.yaml say the lead cannot read the target space — an exact rule shadowing the Teams/* wildcard, say — the item is left out entirely. Nothing is rendered into a vault that the space's own permissions keep it out of; those promotions are decided at the dashboard. The lead (or their agent, recording a decision the lead made) writes:123456People/<lead>/PromotionApprovals/<promo-id>.md --- decision: approve # or: reject reason: required when rejecting owner: <lead> ---
brain cycle applies it — re-checking eligibility server-side, refusing with an Inbox note when the promotion is already decided, targets a team the decider doesn't lead, or a rejection is missing its reason. A forged owner: is treated as tampering. Every applied decision is archived with via: delegated, committed under the decider's identity, and surfaced by brain doctor for 30 days.approve() itself refuses any delegated decision on a shared-space target, so a pending file edited between the two still cannot publish company-wide. The seam is scoped to team spaces so it never bypasses the human gate.People/<you>/Shares.md
into their slice listing everything still pending and the most recent
decisions from the last 30 days, including rejections with their reasons. It is a generated
file (like AGENTS.md): write-back ignores edits to it and the next cycle
regenerates it from the queue, so the status a person sees is always the
queue's truth — visible in chat (their agent reads it) and in the dashboard
(it is an ordinary note in Query and the graph).Shares.md is a pull surface: it is always current, but nothing tells anyone to open it. A person learns a decision is waiting on them only if they look, and an admin only if they open the dashboard. Two ready-made cron jobs close that loop — a per-person nudge that reports what is waiting and records the decision its human gives, and an admin queue nudge that reports depth and age without deciding anything. Both print nothing when nothing is pending — so nothing is delivered — and neither adds authority: the seam and its server-side eligibility re-check are unchanged.Shares.md isn't only about promotions, despite the name — it's the one status page for everything a person owns or has requested that moves through a human gate. Alongside the promotions status above, it carries a generated Space shares section: that person's own pending share requests (things they've asked to grant on a space they own) plus approvals, rejections, and revocations from the last 30 days, capped at 20. Same generation rule applies — it's regenerated from _meta/shares/ truth on every compile, not editable in place. Recipients and team leads may also see an Awaiting your decision section listing share requests they're eligible to decide themselves — see the routing table in Sharing a space.brain shares for the share-request queue.