Skip to content

Retire the scope-floor cluster and release the one it blocked - #595

Closed
ptr727 wants to merge 1 commit into
developfrom
chore/retire-the-scope-floor-cluster
Closed

Retire the scope-floor cluster and release the one it blocked#595
ptr727 wants to merge 1 commit into
developfrom
chore/retire-the-scope-floor-cluster

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Why

TODO.md step 9 says a cluster heading is deleted when its pull request merges. #594 merged as c8687c5, carrying "The Prose Gate Scope Floor" whole, so the entry now describes work the tree already holds. Left in place it would be selected again.

What changed

The shipped cluster is deleted, not annotated. It filed no issue, so nothing moves to "Verified Complete, Awaiting Close" and the deletion is the whole of its bookkeeping. Every one of its Settled bullets is now either implemented in scripts/prose_lint.py or recorded in #594's description, so nothing researched is lost.

"The Representative-Data Path Check" goes from blocked to ready. It waited on exactly that floor, on the stated reasoning that gating a path shape is worth having only once the gate can prove it read something. The dependency is recorded as a Settled bullet rather than dropped, so a later reader sees why the block lifted instead of finding a state change with no cause.

Its Checked anchor is rewritten against the tree, per step 4, which says to re-verify by reading the surface the anchor names rather than by re-reading the issue. Verified on develop at c8687c5: GOVERNANCE.md states the rule at its "Representative Data in Agent-Authored Text" heading, and none of the gate's nine rules reads a path shape.

What deliberately did not change

The entry's one Open question survives untouched, whether a home path in an operational repo's runbook is a finding, since it may be the literal path an operator types. That is a scoping decision with fleet reach, and step 3's bar for a ready cluster is that the open question is answerable by the session doing the work, not that it is already answered.

Verification

  • python3 scripts/prose_lint.py TODO.md clean.
  • markdownlint-cli2 and editorconfig-checker clean, CRLF preserved.
  • python3 spec/validate.py clean.
  • Every link reference still defined and every definition still cited, checked mechanically. prose-lint stays referenced by other clusters, so no definition is orphaned by the deletion.

🤖 Generated with Claude Code

Selection step 9 applied to c8687c5. The cluster it carried filed no issue,
so nothing moves to "Verified Complete, Awaiting Close" and the deletion is
the whole of the bookkeeping for it.
"The Representative-Data Path Check" waited on exactly that floor, on the
reasoning that gating a path shape is worth having only once the gate can
prove it read something, so its state goes to ready and the dependency is
recorded as settled rather than dropped silently. Its freshness anchor is
rewritten against the tree rather than against the issue, per step 4: the
rule is stated in GOVERNANCE.md and none of the gate's nine rules reads a
path shape.
Its one open question survives untouched, whether a home path in an
operational repo's runbook is a finding, since that is a scoping decision
with fleet reach rather than something this commit settles.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CopilotAI lite review requested due to automatic review settings August 7, 2026 00:52

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the repository backlog bookkeeping in TODO.md to reflect that the previously-tracked “Prose Gate Scope Floor” cluster has shipped (per #594), and to unblock/advance the dependent “Representative-Data Path Check” cluster accordingly.

Changes:

  • Delete the shipped “The Prose Gate Scope Floor” work cluster from TODO.md rather than annotating it.
  • Move “The Representative-Data Path Check” from blocked to ready, recording that its dependency has been met.
  • Refresh the “Checked” anchor for the representative-data entry to develop at c8687c5 on 2026-08-06 and add a Settled bullet capturing why the state changed.

ptr727 added a commit that referenced this pull request Aug 7, 2026
## Why
`GOVERNANCE.md` "Representative Data in Agent-Authored Text" says
agent-authored text illustrates with constructed data rather than data
observed in the maintainer's environment, and says in the same breath
that no pattern closes it. This gates the half a pattern can reach.
It is introduced as that half deliberately. The leak that motivated the
rule was name-shaped and sat in a pull request comment, which no
committed-file linter reads, so a check mistaken for the answer is what
stops anyone looking at the exposure the rule actually exists for.
Carries the `TODO.md` cluster "The Representative-Data Path Check",
which #595 released from `blocked` once the scope floor shipped in #594.
## The shapes were measured, not assumed
The backlog recorded four shapes, `/home/<name>`, `/Users/<name>`,
`C:\Users\<name>`, and a bare drive letter. Run against this repository,
**a bare drive letter matched 11 files and named a path in none of
them.**
An escaped newline after any word ending in a letter and a colon reads
as a drive letter, so a YAML fixture is full of them:
| Matched text | What it actually is |
| --- | --- |
| `e:\n needs` | `jobs:\n needs` inside a test fixture string |
| `s:\n a` | `jobs:\n a:` inside a test fixture string |
| `C:\tmp` (8 hits) | a temp path in fixtures for the string-literal
rule |
That shape is dropped. The one kept is a drive letter followed by
`Users`, which matches nothing in the tree today. This is narrower than
the committed prose, which says "an absolute home path or a drive
letter", so the narrowing is stated here rather than left for a reader
to discover.
## The exemption is built, not listed
A wrong exemption hands out a work list that damages correct documents,
and this rule has two self-referential problems that a file-name
allowlist would solve badly and briefly.
**The rule's own wording quotes the shapes it forbids.** Requiring a
real user segment solves it by construction: the documentation
placeholder is not a valid account name, so it describes the shape
without matching it. No exemption names `GOVERNANCE.md`, and none goes
stale when the text moves.
| Probe | Verdict |
| --- | --- |
| `C:\Users\<name>` in documentation | no match |
| `/home/<name>` in documentation | no match |
| `/home/vscode/.ssh` | exempt, container account |
| a real absolute home path | **flagged** |
**Container accounts are exempt by name.** Every home path in this
repository, all 15, is `/home/vscode` from the devcontainer snippets and
the doc describing them. Without that exemption the rule would open with
15 findings and no true positive among them.
**The gate reads its own source**, so the bait paths in the tests are
assembled from parts and a case asserts that neither `prose_lint.py` nor
its test file carries a literal. That is the approach the file already
takes for non-ASCII, which it writes as escapes for exactly this reason.
## Operational repositories are exempt, and told so
An operational repository's runbook carries the literal path an operator
types. That is the repository's own content rather than an agent quoting
an environment it observed, which is the distinction the rule is about.
The model is read from what the repository carries rather than from the
hub registry, which a downstream checkout cannot see: `spec/files.json`
declares `repo-config/operational/develop.json` for the operational
model and `repo-config/develop.json` for the release one. The hub
carries both, being the template for each, so it reads as release rather
than exempting itself from a rule it authors.
**The skip is announced on stderr**, because a rule that silently stops
running reads as a rule that passed, which is the same failure #594
closed on the other side.
## Scope note
Unlike every other prose rule, this one reads fenced blocks and
configuration values rather than stripped prose. A transcript pasted
from a terminal and a bind mount naming a real home are the exposure in
its most consequential forms, and neither is a sentence.
## Verification
- `python3 scripts/test_prose_lint.py` - 188 pass, up from 173. Of the
14 new cases, 10 fail against `develop` and 4 pass against both, holding
the must-not-fire direction.
- `python3 scripts/prose_lint.py . --check home-path` - clean across the
tracked tree.
- `python3 scripts/prose_lint.py . --summary` - 557 violations across 45
files, the #519 backlog figure unchanged, with `home-path` contributing
none. Adding a rule to `DEFAULT_RULES` did not move the number.
- `python3 spec/validate.py`, `python3 spec/audit.py --selftest`,
`python3 scripts/repo_gate.py` - clean.
- The blocking CI prose run - clean.
## Correction: this branch carries the TODO bookkeeping too
An earlier revision of this description said the `TODO.md` edits were
held back to avoid conflicting with #595. **That was wrong.** This
branch was cut from #595's branch rather than from `develop`, so it
already contained that commit, and the description claimed an absence a
reader could disprove from the diff.
The review then caught the real consequence: the cluster entry still
promised a bare drive letter after the implementation dropped that
shape. Correcting the bullet was the smaller half of the answer, since
this is the pull request that ships the cluster, so `c6fca9e` applies
step 9 and deletes it rather than leaving a corrected description of
finished work. The disproved claim is recorded here and in the commit
message, alongside the measurement that disproved it.
**This makes #595 redundant**, since every line of it is already in this
branch. Closing it as superseded is the maintainer's call rather than
something this branch does.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Closing as superseded by #596, which carries every line of this branch.

What happened. This branch was pushed, and the branch for #596 was then cut from it rather than from develop, so #596 contained this commit from the moment it opened. That was a mistake in how the branch was created, not a decision to stack. It reached develop in the squash 8e10a2c along with the rest of #596.

Why this is closed rather than merged. The pull request is now CONFLICTING, and the conflict is a delete-versus-modify on TODO.md where only one resolution is correct:

Resolving it by keeping this branch's text would re-add 18 lines describing finished work, and would restore a claim the corpus disproved: a bare drive letter matched 11 files in this repository and named a path in none of them, since an escaped newline after any word ending in a letter and a colon reads as one. Resolving it the other way produces a tree byte-identical to develop, which is the proof there is nothing left here to merge.

Nothing is lost. The scope-floor cluster deletion and the release of the cluster it blocked are both on develop, and this page keeps the commit and its message.

@ptr727ptr727 closed this Aug 7, 2026
ptr727 added a commit that referenced this pull request Aug 8, 2026
Closes#607.
## What was wrong
A Copilot review body states how many of the pull request's changed
files it read, and nothing parsed that line. A round that read part of
the diff carries the correct `commit.oid`, raises no inline threads, and
reports "generated no comments", so it is the clean pass byte for byte
in everything the loop checks, and `status` printed `review_on_head=yes`
over it and exited `0`.
Measured over **332 Copilot review bodies** on this repository, five
rounds across three pull requests reported reading fewer files than were
changed, and all three merged. #592 is the sharpest: three changed
files, one never read, across *both* rounds, both reporting no comments.
## What changed, and why it is wider than the issue asked
Partial coverage is the third instance of a shape this script already
answers twice, and the generalization is the point. Every reader here
keys on a structural marker, so a marker that changes spelling is a
section the reader stops finding and reports as absent. All three
failures on record have that shape:
| Drift | Result |
| --- | --- |
| Suppressed heading reworded | `suppressed=0` over a body carrying
findings |
| Suppressed section moved inside another wrapper | `suppressed=0` again
|
| Coverage line never parsed | a partial round reported as a covered
head |
Each was found by the maintainer after it had landed, rather than by the
gate. So the digest now vets the reviewer's output as a whole and
**fails closed**:
- `coverage=full` / `PARTIAL` / `unstated`, with exit **42** on a
partial round.
- `shapes=ok` / `UNRECOGNIZED`, with exit **43** on any heading,
`<summary>`, metadata label, coverage wording or reviewer login the
script has no vetted spelling for. It outranks 42, because a reader that
does not understand the output cannot be believed about what it read of
the diff.
The `43` message states the remedy in two parts: **file an issue on the
repository hosting the reader**, quoting the body the shape came from,
and **the merge decision is the maintainer's**. An unrecognized shape
does not say the pull request is bad, only that nothing here can vouch
for the review of it.
## The inventory is measured, not imagined
With fenced blocks dropped and text reduced to ASCII, all 332 bodies
reduce to **7 headings, 6 `<summary>` texts and 3 metadata labels**, and
every body carries at least one. Counts normalize to `(N)` and the
verdict headings' colored circle is dropped before comparing, since both
change on every review without the section changing, and dropping the
emoji is also what keeps the source inside the charset rule.
Two exemptions, both required by the corpus:
- **A body stating no coverage** reads as `unstated`, never as pass or
failure. 28 of the 332 are an overview and a change list, that shape is
current and interleaves with the counted one, and one pull request
carries both across its two rounds. Failing on it would cry wolf on
about one review in twelve.
- **A refusal** is exempt, being a bare paragraph by design and already
classified. The exemption is the pattern rather than a carve-out, so a
refusal reworded stops being exempt and blocks, which is the refusal
check's own failure mode caught one rewording later.
The quietest reading is the reviewer **login**: a rename leaves every
filter here matching nothing, so a review that landed reads as
`rounds=0` and a wait polls out its timeout against it.
## Evidence
Both readers were swept over the full corpus before this was written,
and over it again after:
- Shape inventory: **0** items raised across all 332 bodies, and **0**
across every review and comment author on those 120 pull requests
(`copilot-pull-request-reviewer` and `ptr727`).
- Coverage: `full 299 / unstated 28 / partial 5`, the five being exactly
#476 (x2), #479 and #592 (x2).
- Live: #592 reports `coverage=PARTIAL shapes=ok` and exits `42`. #595,
#604 and #606 report `shapes=ok` and exit `0`.
166 tests pass, up from 132. The two fixtures the issue named as
unasserted filler are promoted to assertions, and a case reads the
vetted coverage spellings out of the runbook and hands them to the
script's own parser, so the pair fails in both directions on drift. The
old fixtures crafted review bodies with no heading, which no real body
has, so they were made realistic rather than the check loosened.
## Also carried
- `.github/copilot-instructions.md` - the verify step checked
`commit.oid` only, which is what this shows to be insufficient, plus a
new section stating that an unrecognized shape blocks and earns an
issue.
- `GOVERNANCE.md` - merge-gate precondition 4, and the "all four
preconditions" restatement swept to five.
- `scripts/README.md` - both readings.
- `TODO.md` - a `measure` cluster to survey whether GitHub publishes
anything structured about a Copilot review, since this whole design
rests on prose being the only surface. Introspection says it is:
`PullRequestReview` exposes `body`, `bodyText` and `bodyHTML` and no
field naming a finding or a file count, and the only Copilot-named
GraphQL types configure review-on-push in a ruleset.
## The accepted cost
The shape scan reads every round rather than the head's, so once Copilot
changes format, every open pull request blocks at once until the
inventory is updated. That is deliberate and the maintainer's call: it
is well balanced against a reviewer silently missing a raised finding.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@ptr727