Skip to content

records: land opencv, nothing outstanding - #52

Merged
jeffdaily merged 11 commits into
mainfrom
port/opencv
Aug 20, 2026
Merged

records: land opencv, nothing outstanding#52
jeffdaily merged 11 commits into
mainfrom
port/opencv

Conversation

@jeffdaily

Copy link
Copy Markdown
Collaborator

Lands the completed control-plane records for opencv.

Records-only, under projects/opencv/.

Part of the misplaced-branch sweep.

🤖 Generated with Claude Code

jeffdaily and others added 11 commits August 10, 2026 21:57
* flow: stage maintainer-requested fixes off open upstream PRs

Once an upstream PR is open, its head branch (moat-port) is upstream-visible:
any push lands in front of the maintainer before review, revalidation, or a
person's approval. The colmap #4635 maintainer round nearly shipped an
unreviewed fix this way. This closes the hole:

- fixes stage on moat-fix-<pr#> (moatlib fix-branch); head_sha tracks the
  staging tip so revalidate/pr-gate derivation is unchanged; new published_sha
  records what the open PR shows
- a person approves the delta on a fork review PR (upstream.py --fix-review);
  a body section headed '## Upstream reply' is approved with it
- upstream.py --merge-fix --apply re-checks the live approval and all gates,
  fast-forwards moat-port to exactly the approved tip, posts the approved
  reply, deletes the staging branch, and records it -- the second
  pre-authorized upstream write, same contract as --publish --apply
- enforcement: a fork-clone pre-push hook (moatlib protect-fork, installed by
  orient), a check.py 'published' gate, and a HEAD-MOVED report in the
  --dry-run reconciler (a maintainer push is reviewed and recommended on,
  never auto-absorbed)

Docs: AGENTS.md, moat-checkup skill, porter/reviewer/validator roles,
CONTRIBUTING.md, VISUAL.md. Schema regenerated; README table regenerated.
Verified with a synthetic project and local bare fork: hook refusal/bypass,
gate detection, fix-branch backfill, fix-ready refusals, report paths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* flow: make the fix-flow enforcement hold where the records live

Review of the staged fix flow found the enforcement layer passing in the
configuration MOAT actually runs in, and the merge path leaving residue a
person then has to untangle. Fixes, in the order they bite:

- the fork pre-push hook read projects/<name>/status.json as a PATH, but an
  in-flight project's folder lives on port/<name> and is absent from every
  checkout standing anywhere else. json.load then raised, the state read as
  empty, and the hook exited 0 -- so it allowed exactly the push it exists to
  refuse. Verified on the gfx1151 host: projects/colmap/status.json is absent
  while projects/colmap/src is present, and colmap #4635 is the round this
  flow is meant to run first. The hook now asks `moatlib.py pr-state <name>`
  (project_record, so it resolves from whichever ref holds the record) and
  REFUSES when the state cannot be read: a guard that cannot tell must not be
  the reason an unreviewed commit reaches a maintainer. It reads the ref
  updates first, so only a push to the PR branch pays for the lookup, and
  --refresh re-fetches so another host's `set-pr-open` cannot be missed.
- protect-fork now returns a level and sends "a NON-moat pre-push hook is
  installed; not touching it" to stderr, which orient no longer discards. An
  unprotected clone that looks exactly like a protected one is the failure
  mode being guarded against.
- the 'published' gate compared the clone's LOCAL port branch to
  published_sha. --merge-fix pushes a sha to the fork and moves no local ref,
  so the host that performed the approved merge failed this gate on every
  subsequent push (install_hooks' pre-push runs check.py --fast, which
  includes it), and any host that had not fetched since a merge failed it too.
  It now asks the only question a clone can answer -- is it AHEAD of the
  published tip, which is the actual precursor to an unapproved push. Behind
  is a stale fetch and passes silently; diverged is reported as a rewrite.
  do_merge_fix also fast-forwards the clone's own branch afterwards.
- fix-branch was unreachable for most projects it applies to: 30 of the 53
  open-PR records are trunk-resident with no port/<name>, so save_record
  raised "check out main", which rule 1 forbids and orient refuses -- and
  belongs_on_branch only flips once head_sha moves, which cannot happen until
  the round is recorded. It now re-homes the folder onto port/<name> first
  (ensure_port_branch): the fix round IS the event that means "in flight
  again", so it is what breaks the circle.
- record_writable_here is the same question asked in advance, and both
  --fix-review and --merge-fix now pre-flight it. Discovering an unwritable
  record AFTER the upstream PR has moved is the worst state this flow can
  produce; --merge-fix reports HELD instead.
- do_merge_fix records the merge BEFORE deleting the staging branch. A failed
  delete leaves a spare branch; a failed record after a delete left a moved
  PR, a published_sha naming the old tip, and a fix block pointing at a branch
  that no longer existed -- which --dry-run then reports as a maintainer push.
  set-fix-merged is exposed for that recovery (it records, it authorises
  nothing).
- open_fix_review_pr no longer lets set_fix_review_pr raise past a created PR:
  the URL was lost, the round still read as needing a review PR, and the next
  run would open a second one.
- the delta jargon scan treated any parsed compare as complete. `compare` caps
  at 250 commits and 300 files and omits `patch` on large ones, so a truncated
  answer read as clean on the last check before in-house vocabulary reaches a
  stranger's repository. It now scans from the fork clone when one holds both
  commits, and raises on a truncated API answer.
- fix_branch backfilled published_sha from head_sha unverified, though that
  value becomes the merge-time ancestry baseline AND the baseline --dry-run
  calls a maintainer push. It now confirms against the live PR head and
  refuses when they disagree, which is the HEAD-MOVED case.
- the '## Upstream reply' section ran to the end of the body, so a trailing
  '## Notes' written for our own eyes would have been posted verbatim
  upstream. It now ends at the next ## heading, skipping fenced blocks.
- poll() compared shas with != while everything else uses same_commit; an
  abbreviated published_sha would have reported a maintainer push every sweep.

set_fix_review_pr and set_fix_merged also switched from load_status to
project_record, so a port branch's copy of somebody else's folder cannot be
edited and written back over the real record.

Verified: the hook refuses/allows correctly across 6 cases against a local
bare fork, including the branch-resident record that defeated v1 and the
unreadable-state refusal (v1 allowed both); 27 logic checks over the reply
extraction, compare truncation, local delta scan, residency helpers; 7 over
the published gate's ahead/behind/diverged/stale-object paths; 8 over the
branch sync. Full check.py green apart from the pre-existing gh-shim PATH
artifact on this host.

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The gfx1151 host is back in service, so the selector offered kaldi's windows
gate to it: `next-task windows-gfx1151` returned kaldi/port-ready/validator.
That is a build that cannot succeed. kaldi's ROCm path is gated on the host OS,
not on the GPU -- src/configure's configure_rocm() exits 1 unless uname is Linux
and uname -m is x86_64, before any arch is consulted -- and windows-gfx1101 and
windows-gfx1201 already say so in their blocked_reason.

The gfx1151 record that said it too was removed with the other 132 records of an
intention to validate on a machine we no longer had. Removing it was right; an
absent record means "no host has worked this platform" and the selector defaults
it correctly. But the arch that has recorded nothing is exactly the arch most
likely to discover it cannot run the project at all, and set_blocked indexed
straight into obj["platforms"][platform] and raised KeyError. The one way to
record the finding was the one case it could not handle.

So blocking creates the row, the way a stage transition already does. Clearing
does not: writing a row that says "not blocked" would put back an intention to
validate somewhere, which is fleet state, so --clear on an arch with no record
says there is nothing to clear rather than inventing one to unset.

kaldi's windows-gfx1151 block is recorded with the configure line that proves
it, verified against the fork rather than copied from the sibling archs. The
README regeneration that follows also picks up colmap and HEonGPU moving from
validated to revalidate, which their advanced heads already implied.

Test Plan:

```
python3 utils/moatlib.py set-blocked kaldi windows-gfx1151 "..."   # was KeyError
python3 utils/moatlib.py set-blocked kaldi linux-gfx942 --clear    # nothing to clear
python3 utils/moatlib.py validate kaldi
python3 utils/moatlib.py next-task windows-gfx1151                 # no longer kaldi
python3 utils/check.py
```

Authored with Claude (Opus 5) as the AI assistant.
The branch had independently applied both trunk commits -- the fix-flow work and the set-blocked fix -- under different shas, so utils/ conflicted as the same content twice rather than as a disagreement: check.py, upstream.py and reviewer.md are byte-identical to main@b29761d and moatlib.py to main@beacaaa. The trunk is strictly newer in every case, adding the reviewing work lock on top, so the trunk's copy wins and the branch loses nothing.

projects/kaldi/status.json conflicted for the same reason and resolves the same way: the branch carries its own copy of the windows-gfx1151 block, and the trunk's copy additionally carries the published_sha backfill. The branch's own projects/opencv/ records are untouched.
@jeffdaily
jeffdaily merged commit 4203b8f into main Aug 20, 2026
1 check passed
@jeffdaily
jeffdaily deleted the port/opencv branch August 20, 2026 17:11
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.

1 participant