This is the record of an abcd-managed repository

abcdBetav0.16.2 · 2026-11-06

Development record

A status branch moves without a preflight receipt

adrproposedadr-2610150729333337

Context

itd-2609151838312703 has sessions post announcements to the shared remote. They post from any account, any machine and hosted cloud sessions. Each announcement is an empty-tree commit on the person's own branch, abcd-status/<forge username in lower case>.

Three constraints were already locked:

  • The push hook needs a receipt. .githooks/pre-push refuses any push whose new commit carries no preflight receipt.
  • Cloud sessions have no receipt. A hosted cloud session cannot mint one, because it cannot pass preflight there (itd-2610120738075547).
  • The cloud proxy accepts branches only. It refuses every ref that is not a branch, so a hidden ref namespace is out (itd-2609091034175565 decision 10).

The hook already admits one family of commits that change no file: reservations, under adr-2610031352212697. It does so with one row of its receipt-less table and the reservation_shape check.

Decision

The push hook's receipt-less table gains a second row: the prefix abcd-status/, checked by the same reservation_shape check that reservations pass. That check admits only a fast-forward of commits that change no file. Every other push under the prefix is gated as any branch is: one that changes a file, rewrites the branch or deletes it.

Rewrites and deletions are blocked on the forge too. A ruleset on refs/heads/abcd-status/** blocks deletion and non-fast-forward pushes, with no bypass. Its mirror is kept in .abcd/work/rulesets/, and the person applies it from that mirror, as every ruleset there is applied (brief invariant 10; corrected 2026-10-22, iss-2610222040438015: no apply verb exists for rulesets).

Announcements are fetched only by verbs whose documented meaning is that fetch: abcd announce, abcd status and the land step (brief invariant 7, adr-38). The prompt hook renders the last fetch from disk.

Invariants 7 and 10 gain clauses naming these verbs and the branch, written in the change that builds them.

Alternatives Considered

  • A receipt for every announcement. Rejected: a cloud session cannot mint one, so it could never announce.
  • A hidden ref namespace (refs/abcd/status/*) outside the branch list. Rejected:
    • the cloud proxy refuses it;
    • the forge's rulesets cannot protect it;
    • the forge's activity record, which verifies senders, covers branches.
  • A second, announcement-specific shape check that parses trailers in shell. Rejected: it would be a second parser beside the Go reader, which breaks one-canonical-primitive. The reader already flags an announcement it cannot parse (itd-2609151838312703 C11).
  • The chosen option: a second row reusing reservation_shape. It admits nothing the reservation row does not already admit: commits that change no file.

Consequences

  • Easier: a cloud session, or any session without a receipt, can announce. The trust boundary is unchanged, because a push the row admits changes no file a gate would read.
  • Harder: status branches can never be deleted. Their history is permanent and public, which the product thinker accepted (itd-2609151838312703 decision 19). They grow by one branch per person, never per session.
  • The hook is a local-only check. The receipt-less row guards only a push made through the committed hooks. A hosted cloud session runs no hook: its clone has no core.hooksPath and no .git/hooks/pre-push (the cloud probe of 2026-10-15). There the guards are the server's ruleset on refs/heads/abcd-status/**, which refuses deletion and non-fast-forward pushes, and abcd's own reader, which shows a status commit whose tree is not the empty tree as doubtful, with that reason, and never renders it (itd-2609151838312703 C11).
  • Nothing on the forge refuses a status push that changes a file. GitHub's push rulesets, which restrict file paths, are offered for private and internal repositories only, and they target no branch: a push rule applies to every push to the repository and its fork network, so none can be scoped to abcd-status/. Branch rulesets govern creating, updating and deleting a branch, never which files a push changes (checked on 2026-10-15 against GitHub's ruleset documentation). So a cloud push that changes a file on a status branch lands, and the reader is the guard against it.
  • The ruleset is required, not optional. Without the hook in the cloud it is the only refusal of a deletion or a rewrite there. Its mirror is .abcd/work/rulesets/status-protection.json.
  • New obligations:
    • apply the ruleset, and keep the mirror and the live ruleset in step;
    • add the invariant clauses in the building change.

Frontmatter

idadr-2610150729333337
typeadr
statusproposed
date2026-10-15

References4

mentions3