Skip to content

The Whole-Unit Read Is Scoped to Carriage, and the Evidence Says It Should Be Scoped to Text Shape #1437

Closed as not planned

Description

@ptr727

Evidence from PR #1435 that the whole-unit read is scoped to the wrong property, and a measurement that
separates the two candidate causes.

What happened

GOVERNANCE.md "Communicating with the User" is carried, so every change to it owed a whole-unit
adversarial read. It got eighteen. repo-config/README.md is not carried, so it owed none, and it got
diff-scoped reviews instead.

The Labels section of that uncarried file was then broken four times in a row, each time by a fix
to the previous break:

  1. decision moved out of the four mutually exclusive triage classes and made a marker. The invariant
    sentence seven lines above still said an issue carries exactly one of them.
  2. The marker paragraph said it "sits beside one of the four", making a class mandatory, which left the
    pure parked question GOVERNANCE.md names with no legal label set.
  3. The invariant gained the exemption. The marker paragraph had by then introduced "class" as the noun
    for the four, colliding with the sentence one blank line below it, which uses "class" for the
    review-finding labels introduced and pre-existing.
  4. Two more in the same paragraph: a pronoun binding that made an issue mark every question rather than
    the marker marking one, and "has a session present at handoff" reading "present" as an adjective,
    which collides with that rule's own presence vocabulary and turns an obligation into a precondition.

Each fix was verified. Each verification was scoped to the sentence that changed. The first read of the
section as one whole text found three of the four, immediately.

The measurement

Across this branch, the surfaces that carried the same rule:

Surface Maintained how Times it drifted
Three generated agent-conduct copies build_dist.py fills them from the source 0
GOVERNANCE.md "Communicating with the User" Hand-written, whole-unit read owed on every change Defects found and fixed in-branch, none shipped
docs/fleet-map.md Hand-written, no whole-unit read owed 2
repo-config/README.md Hand-written, no whole-unit read owed 4
README.md Hand-written, no whole-unit read owed 1
AGENTS.md Hand-written, whole-unit read owed 1, caught by the read

The generated copies never drifted, which is #1317's argument. The hand-written surfaces that owed a
whole-unit read had their defects caught in-branch. The hand-written surfaces that owed none drifted
seven times between them and were caught only by a reviewer or by a whole-tree diff pass
, which is a
weaker net and a later one.

What this suggests

The rule in GOVERNANCE.md "Verification Discipline" scopes the whole-unit read to carried content,
and the reason it gives is that a carrier reads the unit whole and cannot fix what it finds. That reason
is real. But the evidence here is that the whole-unit read is not actually a remedy for carriage. It is a
remedy for a multi-sentence text edited one sentence at a time, which is a property of the text and
not of who reads it. Carriage is one situation where that hurts. An eight-sentence section in an uncarried
file is another, and it drifted more, not less.

Two things worth deciding:

  1. Whether the whole-unit read's trigger should be the shape of the text rather than its carriage, for
    example any section a change edits that exceeds some size, whatever file it sits in.
  2. Whether canonical_review.py should be able to record a pass over a unit in an uncarried file, since
    today the ledger's unit set comes from the carry manifest and there is nowhere to record such a pass
    even if one is run.

Filed rather than acted on, since changing what the gate covers is a fleet-wide decision. The immediate
cost is bounded: the four breaks above were all caught before merge.

Activity

  1. ptr727 commented on Nov 1, 2026

    @ptr727
    OwnerAuthor

    Decision needed (decision triage, 2026-11-01)

    Question: Now that #1649 replaced the per-push carried-content gate with a weekly sweep, should scripts/canonical_review.py's unit set (from spec/files.json) take in sections of uncarried hub docs, or should the whole-unit read be triggered by the shape of the text?

    Options, recommended first:

    1. Decline both and close (recommended): Sweep the Carried-Content Read Weekly Instead of Gating Every Push #1649 removed the per-change trigger this issue argued about; the carriage rationale ("a carrier ... cannot fix what it finds") does not apply to uncarried hub text the hub fixes anytime; the local diff pass already reads full files; all four breaks were caught before merge; and widening the sweep goes against Review rounds are spent debating prose in comments instead of fixing code #1631's choice to spend less here. No work in flight.
    2. Edit the local-strict-review brief: Have the diff pass read each edited level-two section whole and check its internal invariants in any file, targeting the actual failure (sentence-at-a-time edits) at edit time with no ledger change. Skill edit plus a build_dist.py regeneration. No work in flight.
    3. Add uncarried units to the sweep ledger: A declared set of extra units (for example repo-config/README.md sections) the engine records and sweeps, closing point 2 as asked but growing the ledger and weekly backlog. No work in flight.

    Evidence: 91e0fd2 (#1649) implements #1631 item 1: "Nothing refuses a push or a pull request over a carried unit any more". canonical_review.py:28 MANIFEST = "spec/files.json". local-strict-review SKILL.md:35: the diff pass "reads the full content of every file the diff ... touch[es]" (since 41ddcf4, #1065, before #1435, so full-file context alone did not prevent the breaks, the case for option 2). SKILL.md:109: "No change owes this pass".

    Blocks: none

  2. added
    decisionA question waiting on the maintainer, alone or beside whatever else the issue carries
    on Nov 1, 2026
  3. ptr727 commented on Nov 1, 2026

    @ptr727
    OwnerAuthor

    Maintainer answer (decision triage, 2026-11-01): Option 1: decline both and close. #1649 removed the per-change trigger, and uncarried hub text is fixable by the hub at any time.

  4. removed
    decisionA question waiting on the maintainer, alone or beside whatever else the issue carries
    on Nov 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions