Skip to content

The writer set for a contended authority: given a path, print who is currently writing it - #10263

Merged
gunbai-bot[bot] merged 2 commits into
mainfrom
session/quick-cat-355
Sep 3, 2026
Merged

gunbai-bot[bot] merged 2 commits into
mainfrom
session/quick-cat-355

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor

Run against dag/gunbc/instruments/, this query returns 8 open pull requests — including itself. A population that contains the observer is enumerated, not curated.

What it answers

Given one path, who is currently writing it — every open pull request whose diff against its own merge base touches that path.

gunbc run --source-root dag --source-root src/v2 \
  --entry dag/gunbc/instruments/path_writer_set_instrument.dag \
  --function writers --arg repo=gunb-ai/gunbc --arg path=<path>

A subject ending in / asks about a subtree; anything else names one file. The report prints which rule it used.

Measured live (2026-09-03, gunb-ai/gunbc, 55 open PRs, 0 unobserved)

subject	.github/workflows/witnesses.yml
match_rule	exact path equality — the subject names one file (end the subject with `/` to ask about a subtree)
diff_scope	every changed path, rename detection disabled — a branch renaming or deleting the subject is a writer of it
pull_requests	55
unobserved	0
writers	4
writer	#10261	app/gunbai-bot	session/deep-bear-318	Split required CI measurement, publication, and adjudication	284c8550…
  touches	.github/workflows/witnesses.yml
writer	#9981	briansrls	root2b/quality-floor	ROOT-2B: the evaluation-budget quality floor…	1920f5ff…
  touches	.github/workflows/witnesses.yml
writer	#9725	app/gunbai-bot	session/snappy-koi-879	FLOOR-ROUTE-GAP-SELF-HOST…	8b8358c3…
  touches	.github/workflows/witnesses.yml
writer	#9693	app/gunbai-bot	session/smart-wren-406	FABRIC-CI-1 / FCI-1…	68d34759…
  touches	.github/workflows/witnesses.yml

Both live runs exit 0. dag/gunbc/cross_pr_contradiction.dag returns writers 0 and says no open pull request touches … in words.

Why it is worth asking

Authorities here are single by construction (DESIGN §3), which makes them contention points: one file is where a concept lives, so every lane touching that concept edits that file. A lane about to restructure a module cannot see, from its own branch, that three other branches are already rewriting it. The conflict is created at authoring time and discovered at merge time, by whoever lands second — and the rework is paid in full every time.

Why this is not a widening of gunbc.cross_pr_contradiction

That instrument reads the same population to ask whether two branches move one roster identity in opposite directions, and states in its own header that a same-direction overlap index is out of scope: 45 of the 53 multi-PR keys its hand run found were same-direction and would have buried the one row that mattered. That ruling is correct for a scan over the whole corpus, and it is exactly why this is a query — the subject is supplied by the asker, so there is no population to bury a finding in. The two share the observation vocabulary (PrDiffUnobservedCause is imported, not re-coined) and share nothing else.

Rename detection is off — the one new extdeps operation

diff.renames defaults to true, so a pure rename prints only the destination path. Measured: over git mv a.txt b.txt, git diff --name-only HEAD~1 HEAD prints b.txt alone; --no-renames prints a.txt and b.txt. The branch renaming or deleting the contended authority is precisely the writer a lane most needs to know about, so extdeps.git.git gains DiffNameOnlyNoRenames beside DiffNameOnly, and the scope travels on the report's own row.

Empty is not absent (DESIGN §5)

This query's most common true answer is "nobody", so an instrument rendering "I could not read this pull request" as "this pull request touches nothing" would produce the answer an asker is most likely to accept without checking, from an observation never made. Four states, four spellings: unread, empty-by-derivation, empty-corroborated-by-the-forge, diff-refused. The completeness verdict is bound to the exit status, and the no open pull request touches X sentence is reachable only over a fully-read population.

PrDiffUnobservedCause gains a DiffRefused arm rather than being forked — git.Core.Diff declares no exit status so the contradiction instrument cannot produce it, and DiffNameOnlyNoRenames can. One vocabulary, one set of consequences; that module gains a total arm it does not construct, which is the cost of one authority and smaller than the cost of two.

Rung

mitigatable, and the ceiling is reached rather than stalled below: what is being prevented is two people choosing to edit one file, which is not a state a compiler can refuse. It reports — it closes, comments, rebases and merges nothing, and the only forge operation called anywhere is the readonly ListOpenJson.

Evidence

13 witnesses in dag/test/claim/path_writer_set_witness_test.dag, all green, with two planted mutations run as discriminating REDs:

mutation reddens positive controls
ExactPath => starts_with an_exact_subject_does_not_match_a_longer_path (1) other 12 stay green
report_is_complete => true the 4 completeness witnesses 9 stay green, incl. a_derived_empty_branch_leaves_the_report_complete

The 27 cross_pr_contradiction witnesses stay green over the added arm. Whole-corpus v1_src_dag_parse: 4620 files parse-clean.

What it costs to run — and a finding that is not about this PR

Requirements: network, an ordinary gh token (no special access — the only forge operation anywhere in the module is the readonly ListOpenJson), and a local clone, because diffs are read from the local object store and every branch head is compared against the oid GitHub reports — a stale ref refuses that PR by name rather than reading a different branch state.

The two figures are deliberately separated, because they have different owners:

One timed end-to-end run (--arg path=dag/gunbc/instruments/, 55 open PRs, 8 writers, exit 0 — the run is quoted in full below):

measured
the query's own work 12.3 s — 167 git/gh calls across 55 open PRs: one fetch-prune, one gh pr list, then resolve + merge-base + name-only-diff per PR at ~30–40 ms each
gunbc run resolving the whole .dag corpus before evaluating anything ~101 s (113 s total wall minus the 12.3 s above)
total 113 s

So the answer to "can a lane run this before landing?" is no — and the reason has nothing to do with what this PR builds. Twelve seconds of actual work sits behind ~101 s of entry resolve, and that resolve is paid by every .dag entry point, so it blocks every cheap-check-before-landing idea, not just this one. It is a finding about the substrate's entry cost and is being dispatched as its own item; it is recorded here so the follow-up is denominated correctly rather than read as a property of this instrument.

The incident this was built for, answered with the instrument

Two managers issued contradictory instructions to the same worker about dag/gunbc/recurring_failure_mode.dag inside one hour, because neither could enumerate who was writing it. The estimate at the time was five commits from lanes they did not know existed. The actual standing writer set, in one command:

subject               dag/gunbc/recurring_failure_mode.dag
total_pull_requests   55
total_unobserved      0
total_writers         15

#10256 #10252 #10251 #10248 #10236 #10206 #10204 #10197 #10193 #10183 #10028 #9981 #9913 #9785 #9725 — each printed with author, branch, head oid and matched path. Three times the estimate, on a file that had been actively coordinated all afternoon.

unobserved 0 is the load-bearing half of that output: fifteen writers over a partially-read population would be a lower bound printed as an answer, and the run exits nonzero in that case so a script cannot mistake one for the other.

The directory-prefix rule, demonstrated on the directory this instrument lives in

The timed run above used dag/gunbc/instruments/ as its subject. Eight open pull requests are writing that directory — including this one, which the query enumerates as a contender in its own answer:

subject	dag/gunbc/instruments/
match_rule	directory prefix — the subject ends with `/`, so every changed path beneath it counts
total_pull_requests	55
total_unobserved	0
total_writers	8
writer	#10263	…	session/quick-cat-355	The writer set for a contended authority…
  touches	dag/gunbc/instruments/path_writer_set_instrument.dag
writer	#10259	…	session/gentle-crane-57	Bound the 500ms ceiling against a between-run envelope…
  touches	dag/gunbc/instruments/floor_cost_distribution_instrument.dag
writer	#10256	…	work/step0-census-calibration	Calibrate the reference-occurrence census…
  touches	dag/gunbc/instruments/reference_occurrence_binding_census.dag
writer	#10245	…	session/jolly-stag-534	Give v2.std.fn_index fn_arrow_decl_facts_live a caller-named subject…
  touches	dag/gunbc/instruments/rust_stage0_gates.dag
writer	#10210	…	session/crisp-ram-568	A right-censored bound could inhabit the field consumers read as an exact cost…
  touches	dag/gunbc/instruments/floor_cost_distribution_instrument.dag
writer	#10197	…	session/zesty-gull-732	gunbc.rung_drop rows serialize as multi-kilobyte single-line blobs…
  touches	dag/gunbc/instruments/ci_gates.dag
writer	#9785	…	session/still-swift-363	first(): construct the Optional std.algebra declares…
  touches	dag/gunbc/instruments/dag_compile_clean_shard_totality.dag
writer	#9693	…	session/smart-wren-406	FABRIC-CI-1 / FCI-1: bind exact Work to a durable converged-cell reservation
  touches	dag/gunbc/instruments/fabric_control_plane_live_probe.dag

#10259 and #10210 are two different lanes editing the same file — floor_cost_distribution_instrument.dag — which is the shape the query exists to surface before rather than after the fact.

The summary row is unmiscountable by construction

The obvious way to count this report's answer is grep -c '^writer'. In the first cut of the renderer the summary read writers<TAB>8 above rows spelled writer<TAB>#10263… — both match ^writer, so that command returned nine for eight writers, silently, by counting the header as a datum. unobserved carried the identical collision against its own per-PR rows. This is not hypothetical: it is how I first misreported this instrument's own output while the tool printed the correct number throughout.

A header note telling readers to mind the summary row would be a rule, and a rule is not a firing mechanism — the shape is. So the summary keys are total_writers / total_unobserved / total_pull_requests, chosen until the naive command is correct rather than warned about: grep -c '^writer' and grep -c '^unobserved' now yield exactly the row counts they look like they yield. The miscount is not detected, it is unwritable.

writer_set_row_keys_do_not_collide_with_summary_keys is the executing evidence, asserted over a report carrying both kinds of row, and it goes red on any future summary key that reintroduces the prefix.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AinEdiYkU1u4HYnS6DUP78

…open-PR writing it

This repository's authorities are single by construction (DESIGN §3), which
makes them contention points: one file is where a concept lives, so every lane
touching that concept edits that file. A lane about to restructure a module
cannot see, from its own branch, that three other branches are already
rewriting it -- the conflict is created at authoring time and discovered at
merge time, by whoever lands second. The displaced cost is the rework the later
lane pays, in full, every time.

  gunbc run --source-root dag --source-root src/v2 \
    --entry dag/gunbc/instruments/path_writer_set_instrument.dag \
    --function writers --arg repo=gunb-ai/gunbc --arg path=<path>

A subject ending in `/` asks about a subtree; anything else names one file, and
the report prints which rule it used.

MEASURED LIVE (2026-09-03, gunb-ai/gunbc, 55 open pull requests, 0 unobserved):
`.github/workflows/witnesses.yml` has four writers -- #10261, #9981, #9725,
#9693 -- each printed with its branch, author, head oid and matched paths;
`dag/gunbc/cross_pr_contradiction.dag` has none, and says so in words.

WHY IT IS NOT A WIDENING OF `gunbc.cross_pr_contradiction`. That instrument
reads the same population to ask whether two branches move one roster IDENTITY
in opposite directions, and states in its own header that a same-direction
overlap index is out of scope for it: 45 of the 53 multi-PR keys its hand run
found were same-direction and would have buried the one row that mattered. That
ruling is correct for a SCAN over the whole corpus, and it is exactly why this
is a QUERY -- the subject is supplied by the asker, so there is no population to
bury a finding in.

RENAME DETECTION IS OFF, AND THAT IS THE ONE NEW EXTDEPS OPERATION.
`diff.renames` defaults to true, so a pure rename prints only the DESTINATION
path -- measured: over `git mv a.txt b.txt`, `git diff --name-only HEAD~1 HEAD`
prints `b.txt` alone while `--no-renames` prints both. The branch renaming or
deleting the contended authority is precisely the writer a lane most needs to
know about, so `extdeps.git.git` gains `DiffNameOnlyNoRenames` beside
`DiffNameOnly` and the scope value travels on the report's own row.

EMPTY IS NOT ABSENT (DESIGN §5). This query's most common true answer is
"nobody", so an instrument rendering "I could not read this pull request" as
"this pull request touches nothing" would produce the answer an asker is most
likely to accept without checking, from an observation never made. An unread
branch, a branch empty by derivation, a branch the forge corroborates as empty,
and a diff that refused are four states with four spellings; the completeness
verdict is bound to the exit status, and the "no open pull request touches X"
sentence is reachable only when the population was fully read.

`PrDiffUnobservedCause` gains a `DiffRefused` arm rather than being forked:
`git.Core.Diff` declares no exit status so the contradiction instrument cannot
produce it, and `DiffNameOnlyNoRenames` can. One vocabulary, one set of
consequences.

RUNG: mitigatable, and the ceiling is REACHED rather than stalled below -- what
is being prevented is two people choosing to edit one file, which is not a
state a compiler can refuse. The instrument reports; it closes, comments,
rebases and merges nothing, and the only forge operation it calls is the
readonly `ListOpenJson`.

EVIDENCE. 13 witnesses in dag/test/claim/path_writer_set_witness_test.dag, all
green, with two planted mutations run as discriminating REDs:
`ExactPath => starts_with` reddens exactly `an_exact_subject_does_not_match_a_
longer_path` and nothing else; `report_is_complete => true` reddens exactly the
four completeness witnesses while every positive control stays green. The 27
`cross_pr_contradiction` witnesses stay green over the added arm.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AinEdiYkU1u4HYnS6DUP78
@gunbai-bot

gunbai-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Thanks — taking the DiffPathScope nit as a note rather than a change, and recording why here so the next reader hits the answer at the same place the question arises.

The single-variant scope coproduct is not a one-off shape: gunbc.cross_pr_contradiction declares type DiffFileScope = | EveryFileInDiff for exactly the same job, and its header states the reason — an index computed over a filtered subset is blind to everything outside the filter, and the filter is precisely what an author reaches for when extraction gets awkward. Making the scope a value that travels with every report means narrowing it later requires adding a variant, which no reader can miss.

The load-bearing part is the printed diff_scope row, not the arity of the type. A writer set taken with rename detection on is a materially different observation, and the row is what stops a report taken one way being quoted as the other. Collapsing the coproduct to a bare string constant would keep the row but move the decision out of the type system, which is the wrong direction; collapsing it away entirely would drop the row. So the row stays, and if a second scope never materializes the candidate for collapse is real but is a corpus-wide call about that idiom (both instances), not a local one about this module.

No change pushed: CI on d2b70b7 is mid-flight and restarting the required floor for an annotation sentence is not a trade worth making.

— sent from quick-cat-355

…, and the witness that keeps it so

THE DEFECT WAS IN THE OUTPUT FORMAT, NOT ONLY IN THE READER. The obvious way
to count this report's answer is `grep -c '^writer'`. The summary read
`writers<TAB>8` above rows spelled `writer<TAB>#10263...`, so both matched
`^writer` and that command returned NINE FOR EIGHT WRITERS -- silently,
by counting the header as a datum. `unobserved` carried the identical
collision against its own per-pull-request rows.

It is not hypothetical. It is how this instrument's own author first
misreported its output to a manager, while the tool printed the correct number
throughout: the source was right and the reader was the defect, and the format
invited it.

A header note telling readers to mind the summary row would be a rule, and a
rule is not a firing mechanism -- the shape is. So the summary keys become
`total_pull_requests` / `total_unobserved` / `total_writers`, chosen until THE
NAIVE COMMAND IS CORRECT rather than merely warned about: `grep -c '^writer'`
and `grep -c '^unobserved'` now yield exactly the row counts they look like
they yield. The miscount is not detected, it is unwritable -- 4b's move from
validation to construction, applied to an output format.

EVIDENCE. `writer_set_row_keys_do_not_collide_with_summary_keys` asserts the
property directly over a report carrying BOTH a writer row and an unobserved
row, which is the only shape where the collision is visible. Planted RED:
restoring the summary key to `writers` reddens exactly that witness and leaves
the other 13 green. 14 witnesses green on the repair.

Reported by neat-swift-219 on the message where I gave them the wrong count.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AinEdiYkU1u4HYnS6DUP78
@gunbai-bot
gunbai-bot Bot merged commit 3e15609 into main Sep 3, 2026
7 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/quick-cat-355 branch September 3, 2026 19:26
@briansrls
briansrls restored the session/quick-cat-355 branch September 3, 2026 19:34
Sign up for free to 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.

0 participants