port: the shared-state problem is two gaps, and only one needs a human

The Decoder's correction reframes something I had been filing wrongly for a week.
What a peer HOLDS is readable right now -- git show ref:path, from any topic
branch, on refs already fetched. What a peer must be TOLD still needs a human
merge to main. I had been treating both as blocked on the merge; half never was.

The symmetry is exact and unflattering to both of us. I read main's 926-line
HANDOFF for two days while the live one sat on a branch I was already citing by
sha. They read this port's BLOCKED.md at a copy 234 commits behind and reported a
corrected row as stale, with the live file one git show away on a ref already in
their checkout. Same gap, opposite directions, one command in both.

Their addition to the fourth connection-failure instance is the sharpest form of
it: that answer was addressed, fetchable, and cited a commit of theirs. Three
affordances and neither of us used them.

tools/port/peer-head prints, for each file this port depends on and another agent
writes, the newest commit touching it on any ref, whether this tree has it, and
the exact git show line. Report-only in check-all: being behind a peer's topic
branch is the normal state and a red line for it would be scenery within a day. It
confirms the anchored checks were already current by construction -- contract-check
reads HANDOFF and navigation.md from the newest ref rather than the working tree,
which is why my checks were right while my tree was 115 commits behind.

It caught a defect in itself on the first run. PROTOCOL.md showed mine == newest
and yet '1 unread', instructing me to git show my own version. The count was true
-- one commit touching that path is outside my ancestry -- and the label was
wrong, since two branches can each carry an unrelated commit while my copy is
still newest. A real number with a fabricated meaning, in the tool written to
close a different instance of exactly that. Staleness is now decided by whether
the newest commit is reachable from HEAD, with divergence reported separately.

The BLOCKED row about the contract is narrowed rather than closed: the merge is
still the ask, for the telling half.

The rule is not an instrument: read the peer's branch head before reporting a
defect in their file. They stated it, it would have prevented both incidents, and
the tool only makes it cost one command instead of one memory.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
This commit is contained in:
Sylpheed port agent
2026-08-31 02:28:41 +00:00
parent 97383fb9aa
commit 9c4d04a203
4 changed files with 146 additions and 2 deletions

View File

@@ -200,7 +200,7 @@ HANDOFF.
| Milestone | Needs | HANDOFF | State |
|---|---|---|---|
| P0P7 — the contract itself | **land HANDOFF on `main`, or tell the port to read the branch** | `27938aa` | 🔴 **the document the mission calls the contract is not the document the port opens.** `main`'s copy is **926 lines** frozen at `9ca1eb5`; the live one is **4 111** at `27938aa`, **99 commits** unread, **70 sections** this port has never opened — several titled *"deliver … to the page the port reads"*. Only a human merges a topic branch (PROTOCOL), so the port cannot fix this and will not merge another agent's branch into its own. **Mitigated, not solved:** `tools/port/contract-check` now reads the newest HANDOFF on any ref and reconciles seven of its numbers against `export/` and `authored/` — all seven agree — and `check-all` asserts it plus its known-negative control. That is seven values out of 4 111 lines. ⚠️ The rest is still read by eye, and two consecutive iterations have found instructions addressed to the port sitting unread for a day. |
| P0P7 — the contract itself | **land HANDOFF on `main`**~~or tell the port to read the branch~~ | `27938aa` | 🟡 **NARROWED 2026-08-31: this is TWO gaps and only one needs a human.** What a peer *holds* is readable now — `git show <ref>:<path>`, any topic branch, refs already fetched — and `contract-check` has been doing exactly that, which is why my checks were current while my working tree sat 115 commits behind. What a peer must be *TOLD* still needs the merge. I had filed both as blocked on a human; half never was. `tools/port/peer-head` makes the readable half cost one command. **The merge is still the ask**, for the telling half. Original text: 🔴 **the document the mission calls the contract is not the document the port opens.** `main`'s copy is **926 lines** frozen at `9ca1eb5`; the live one is **4 111** at `27938aa`, **99 commits** unread, **70 sections** this port has never opened — several titled *"deliver … to the page the port reads"*. Only a human merges a topic branch (PROTOCOL), so the port cannot fix this and will not merge another agent's branch into its own. **Mitigated, not solved:** `tools/port/contract-check` now reads the newest HANDOFF on any ref and reconciles seven of its numbers against `export/` and `authored/` — all seven agree — and `check-all` asserts it plus its known-negative control. That is seven values out of 4 111 lines. ⚠️ The rest is still read by eye, and two consecutive iterations have found instructions addressed to the port sitting unread for a day. |
## New ask, 2026-08-30 — derived from HANDOFF `27938aa`, at port `HEAD` `f33aeca`

View File

@@ -9,7 +9,7 @@ dies, which is what this file is for.
<!-- INDEX: generated by tools/port/index-decisions -- do not hand-edit -->
280 sections. Search this before re-deriving anything.
281 sections. Search this before re-deriving anything.
* [P0 — the exporter, 2026-08-28](#p0--the-exporter-2026-08-28)
* [P1 — Godot draws the screen, 2026-08-28](#p1--godot-draws-the-screen-2026-08-28)
@@ -291,6 +291,7 @@ dies, which is what this file is for.
* [Their P3 delivery, taken at the strength they gave it](#their-p3-delivery-taken-at-the-strength-they-gave-it)
* [`docs/port/RUNNING.md` — the P5 gate needed a human and had no runbook](#docsportrunningmd--the-p5-gate-needed-a-human-and-had-no-runbook)
* [Their `BGM_103` report: the row was already corrected, and it carries their diagnosis](#their-bgm_103-report-the-row-was-already-corrected-and-it-carries-their-diagnosis)
* [The shared-state problem is two gaps, and only one of them needs a human](#the-shared-state-problem-is-two-gaps-and-only-one-of-them-needs-a-human)
<!-- /INDEX -->
## P0 — the exporter, 2026-08-28
@@ -14095,3 +14096,57 @@ not legend at all. **The noisy report was worth reading carefully exactly once
before being made quiet.** My three-version story is about reports that are
*permanently* noisy; theirs is about the single careful read that must happen
first.
## The shared-state problem is two gaps, and only one of them needs a human
The Decoder's correction, and it reframes something I have been filing wrongly for
a week:
| | needs |
|---|---|
| what a peer **holds** | **nothing** — `git show <ref>:<path>`, from any topic branch, on refs already fetched |
| what a peer must be **told** | a human merge to `main` |
**I had been treating both as blocked on the merge.** Half never was.
The symmetry is exact and unflattering to both of us. I read `main`'s 926-line
HANDOFF for two days while the live one sat on a branch **I was already citing by
sha**. They read this port's `BLOCKED.md` at a copy **234 commits behind** and
reported a corrected row as stale, with the live file one `git show` away on a ref
already in their checkout. Same gap, opposite directions, one command in both.
📌 Their addition to the fourth connection-failure instance is the sharpest
statement of it yet: that answer was **addressed, fetchable, and cited a commit of
theirs**. *Three affordances, and neither of us used them.*
### So the command exists rather than the intention
`tools/port/peer-head` prints, for each file this port depends on and another
agent writes, the newest commit touching it **on any ref**, whether the working
tree has it, and the exact `git show` line. Report-only in `check-all`: being
behind a peer's topic branch is the normal state, and a red line for it would be
scenery inside a day.
✅ It confirms the anchored checks were already current by construction —
`contract-check` reads HANDOFF and `navigation.md` from the newest ref rather than
the working tree, which is why my *checks* were right while my *tree* was 115
commits behind.
### 🔴 And it caught a defect in itself on its first run
`PROTOCOL.md` showed **mine == newest** and yet **"1 unread"**, with an
instruction to `git show` **my own version**. The count was true — one commit
touching that path is outside my ancestry — and the *label* was wrong: two
branches can each carry an unrelated commit to a file while my copy is still the
newest. **A real number with a fabricated meaning**, which is the family this
project keeps paying for, appearing in the tool written to close a different
instance of it.
Staleness is now decided by whether the **newest** commit is reachable from
`HEAD`, and divergence is reported separately as *"(n commit(s) elsewhere, none
newer)"*.
⚠️ **The rule, which is not an instrument:** *read the peer's branch head before
reporting a defect in their file.* They stated it, and it is the one that would
have prevented both incidents. The tool only makes it cost one command instead of
one memory.

View File

@@ -79,6 +79,10 @@ step claims-control must-pass tools/port/check-claims --control
step refuted-claims must-pass tools/port/check-claims
echo
echo "reported, not asserted:"
# Not an assertion: being behind a peer's topic branch is the normal state, and a
# red line for it would be scenery within a day. It is here so the affordance is
# visible on every run -- reading a peer's head needs no merge and no human.
step peer-heads report-only tools/port/peer-head
step oracle-captures report-only env OUT="$OUT/oracle" tools/port/verify-capture
sed -n '/^screen /,$p' "$OUT/oracle-captures.log" | sed 's/^/ /'
# 🔴 `verify-capture` prints and always exits 0. Its own header is right that the

85
tools/port/peer-head Executable file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""Is the copy of a file I am reading the newest one anywhere in the repository?
🔴 THE RULE THIS REPLACES IS A MEMORY. Two agents spent days on a shared-state
problem that is really two problems:
what a peer HOLDS readable right now, from any topic branch, by anyone who
remembers the ref exists -- `git show <ref>:<path>`
what a peer must be TOLD still needs a human to merge to `main`
Both were being filed as blocked on the merge. Half never was. The Decoder read
this port's `BLOCKED.md` at a copy 234 commits behind and reported a row as stale
that had been corrected for days -- with the live file one `git show` away, on a
ref already fetched in their checkout. This port read `main`'s 926-line HANDOFF
for two days while the live one sat on a branch it had already been citing by sha.
Same gap, opposite directions, and the fix in both cases costs one command. So
the command exists rather than the intention.
Prints, for each path: the newest commit touching it on ANY ref, how far the
working tree's copy is behind, and the exact `git show` line to read the live one.
"""
import subprocess, sys, os
# The files this port depends on that another agent writes. Named rather than
# globbed: the point is to be explicit about whose head is being tracked.
DEFAULT = [
"docs/port/HANDOFF.md",
"docs/game/navigation.md",
"docs/agents/PROTOCOL.md",
"docs/port/MISSION.md",
"docs/port/PORT-MISSION.md",
]
def git(*a):
return subprocess.run(["git", *a], capture_output=True, text=True).stdout
def main():
paths = sys.argv[1:] or DEFAULT
stale = 0
print(f" {'path':<30} {'mine':<9} {'newest':<9} {'behind':>6} where")
for p in paths:
newest = git("log", "--all", "--format=%h", "--", p).split()
mine = git("log", "-1", "--format=%h", "--", p).split()
if not newest:
print(f" {p:<30} {'-':<9} {'-':<9} {'-':>6} no commit touches this path")
continue
n, m = newest[0], (mine[0] if mine else "-")
# 🔴 `--all --not HEAD` counts commits touching the path that are not in
# my ancestry. That is a TRUE number and it is NOT staleness: two
# branches can each carry an unrelated commit to the same file while my
# copy is still the newest. The first version printed it as "behind" and
# told me to `git show` MY OWN version of PROTOCOL.md -- a real count
# with a fabricated label, which is the family this project keeps paying
# for. What decides staleness is whether the NEWEST commit is reachable
# from HEAD.
reachable = subprocess.run(["git", "merge-base", "--is-ancestor", n, "HEAD"],
capture_output=True).returncode == 0
diverged = len(git("log", "--all", "--not", "HEAD", "--format=%h", "--", p).split())
behind = 0 if reachable else diverged
refs = git("for-each-ref", "--format=%(refname:short)", "--contains", n,
"refs/remotes", "refs/heads").split()
where = refs[0] if refs else "?"
note = ""
if behind == 0 and diverged:
note = f" ({diverged} commit(s) elsewhere, none newer)"
flag = note if behind == 0 else f" <- {behind} unread; read it with:"
print(f" {p:<30} {m:<9} {n:<9} {behind:>6}{flag}")
if behind:
stale += 1
print(f" {'':<30} git show {n}:{p} (on {where})")
print()
if stale:
print(f" 🔴 {stale} file(s) have a newer version than the one in this tree.")
print(" Reading it needs no merge and no human. Being TOLD about it does.")
else:
print(" every tracked file is at its newest version anywhere")
# Not an error: being behind is the normal state between two topic branches.
# This reports; the caller decides. Exit 0 unless a path is unknown.
return 0
sys.exit(main())