Skip to content

claw: ledger_union.t27 + claw-batch job -- fold port PRs into one merge-commit batch (Closes #10398) - #10485

Merged
gHashTag merged 8 commits into
masterfrom
claude/claw-batch-10398-6d9344
Oct 18, 2026
Merged

gHashTag merged 8 commits into
masterfrom
claude/claw-batch-10398-6d9344

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Lane 5 of the TRI CLAW queue epic #10393.

Every port PR appends to docs/reports/t27b_expectations.json, so any two of them conflict in git. #10098 folded 66 of them by hand with a shell loop and a Python union in a scratch folder. This PR moves that into CI, with the union written in t27.

What lands

  • specs/claw/ledger_union.t27 (module ClawLedgerUnion) is the merge rule as law. Its three public functions are lowered to gen/c/claw/ledger_union.c.
    • ledger_union takes base, theirs and ours, keyed by path. The result is ours plus what theirs added over base, sorted by path bytes. A key two sides hold with different values is refused, never picked:
      • theirs adding a path ours added with another verdict;
      • theirs changing or removing a base entry that ours does not match;
      • theirs changing the header or footer.
    • A side that is not in the ledger's shape is refused too (one entry per line, commas, strictly ascending paths, no backslash), so the result is never a guess.
    • marker_lines counts git conflict-marker lines.
    • pr_scope decides whether a PR's file list stays inside specs/port, its own seal (read through the seal's spec_path field) and the ledger.
  • A claw-batch job in the existing .github/workflows/gate-topology.yml. No new workflow file. It runs only on workflow_dispatch with the new prs input (N:headsha ...).
    • It mints a TRI CLAW App token with only contents write + pull_requests write (FR-004).
    • For each PR in order, it leaves the PR out, and names it, when:
      • the PR is not open into master;
      • its head moved since it was named;
      • it changes a file outside the scope;
      • its ledger lines are refused by the union.
    • It merges each remaining head with --no-ff onto claw/batch-<run>. A ledger-only conflict is resolved by the lowered union. A conflict in any other file stops the batch there (FR-002).
    • Before pushing it checks every changed file for zero conflict-marker lines, and that the ledger parses (jq) and is in the ledger shape.
    • It opens the batch PR as a draft with no-auto-merge, so issue-gate.yml does not squash it. It then marks it ready and enables a merge-commit auto-merge (FR-003). The body carries Refs #N for each folded PR's closing issue.
  • spec-guards.yml: ledger_union.c joins the gen-c freshness step.
  • scripts/gen_w387_lean.py is deleted. It is an unreferenced wave generator, removed so this diff shrinks the foreign line count, as the foreign-budget gate requires. Following the precedent of claw: sarif_feed -- a spec that does not parse becomes a code-scanning alert on the pull request (Closes #10356) #10358 and claw: suggest_feed -- a spec that t27c fmt would reformat becomes a suggestion review on the PR (Closes #10365) #10373.

Evidence (Railway lab, nothing on the Mac)

  • t27c seal --save: tests 25/25 pass and 0 are vacuous (test-report). The seal is .trinity/seals/claw_ClawLedgerUnion.json.
  • The tests include a replay of the real port(trios-chat): land 66 open CR-CHAT-03/04/07 port PRs in one merge (Refs #8884) #10098 conflict on PR spec(port): port the proposal validation guard (Refs #8883) #9945, plus negative controls:
    • both sides adding a path with different verdicts;
    • theirs changing or removing an entry;
    • header drift;
    • unsorted, duplicate or misshaped sides;
    • overflow;
    • scope refusals.
  • The harness extracted verbatim from the job YAML was run on the three real ledger blobs of batch merge 9ce20d7d6:
  • Mutation runs (tri mutate spec, three rounds): 62 survivors, then 24, then 18. The final run had 266 mutants: 229 killed, 18 survived, 16 hung (endless loops the mutant itself caused), 3 unviable. The tests killed two real gaps, and two unreachable guards were removed. Each of the 18 survivors is an equivalent mutant:
    • lu_key_end 148 (i <= e): both exits return e.
    • 168, 364, 408, 443 (s <= n): at s == n the line is empty and s steps past n, so no extra work happens.
    • 173 (hs < 12 changed to 11 or 10): lu_at's own bound refuses the same short headers.
    • 174 (hs or hs + 1 as the bound): the bound only guards s + pn, which is hs - 1 either way.
    • 268 (pb <= fb[1]): the extra phantom base entry has an empty key that no side holds, so nothing is emitted.
    • 328, 330 (and changed to or): when the presence flags differ, lu_cmp of an empty range is nonzero, so the flag ends the same.
    • 390, 391 (bounds of the .. scan, x[i-1]): a scoped path ends in .t27 and follows a tab, so the extra bytes never form ...
    • 410 (e >= s + 1 or e > s): on a one-byte line x[s+1] is the newline, not a tab.

Not verified

  • A real batch of at least 5 PRs, the issue's second success criterion, can only run after this lands. The job reads its own definition from master, and it needs the CLAW_APP_PRIVATE_KEY secret and the CLAW_APP_ID variable.
  • A dispatch of this workflow shares its concurrency group with any other manual dispatch on master, so two concurrent dispatches cancel each other. Dispatch batches one at a time.

Inherited reds, not from this PR

claw-sarif, Corpus ratchet, Verilog widths, t27b-native-*, withdrawn-live are red on master too.

Closes #10398

🤖 Generated with Claude Code

gHashTag and others added 6 commits October 18, 2026 21:28
…w (WIP, Refs #10398)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r union (WIP, Refs #10398)

Drops scripts/gen_w387_lean.py, an unreferenced wave generator, so the
foreign line count shrinks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… removed (WIP, Refs #10398)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gen/c/claw/ledger_union.c is t27c gen-c of specs/claw/ledger_union.t27; the
seal records 24 passing tests, 0 vacuous, run on the Railway lab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ards (Refs #10398)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…0398)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag enabled auto-merge (squash) October 18, 2026 14:29
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 14:29:50 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 49
PRs with All Checks Green 1
READY 0
FAILING 49
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 49 + 0 + 0 = 49, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=fad12492937a != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

gHashTag and others added 2 commits October 18, 2026 21:35
…kipping it (Refs #10398)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shell: jobs 92 -> 93, run: steps 324 -> 325, runner-shell steps 303 -> 304 --
the new claw-batch job in gate-topology.yml is one job with one run: step.
quiet: named-a-path-but-not-quiet 220 -> 233 -- that step names the ledger,
the union harness and its temp files; quiet shapes stay 33, since the marker
check no longer skips a missing file. Blessed on the Railway lab with
tri census pin --bless.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag merged commit 1032954 into master Oct 18, 2026
32 of 34 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 14:45:01 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 50
PRs with All Checks Green 0
READY 0
FAILING 50
PENDING 0
NO CHECKS YET 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=fad12492937a != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

gHashTag added a commit that referenced this pull request Oct 18, 2026
… passes (Refs #10385)

Both specs reached master in #10485 and #10484 without ledger lines, so the ratchet reported them UNLISTED.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 18, 2026
…token_floor uses it (Closes #10385) (#10388)

* t27f: frame shards as a generic spec, frame_shard.t27 (Closes #10385)

The shard partition and the TF_SHARD/TF_SHARDS reader, with the reel
length as a parameter, so any renderer opts in with three lines in its
main instead of copying them. token_floor.t27 switches to it in its
owner's render(wide) rewrite. Lab: test report 5/5, 0 vacuous; sealed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* t27f: token_floor takes its shards from frame_shard.t27; t27b ledger names frame_shard (Closes #10385)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* t27f: reseal token_floor after the frame_shard swap (Refs #10385)

Lab: t27c test-report token_floor 32/32, frame_shard 5/5, 0 vacuous; frame_shard seal verifies unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* t27f: reseal token_floor_mux, whose closure holds token_floor's hash (Refs #10385)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* t27b ledger: list ledger_union.t27 and t27mcp/service.t27, which t27b passes (Refs #10385)

Both specs reached master in #10485 and #10484 without ledger lines, so the ratchet reported them UNLISTED.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* t27f: reseal token_floor_mux after merging master (Refs #10385)

Master's mux seal recorded the token_floor hash from before the frame_shard swap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* t27b ledger: list model_route, lesson_reel and reel_topics as CI's t27b run saw them (Refs #10385)

model_route.t27 and reel_topics.t27 pass. lesson_reel.t27 is blocked on type [N]T, like frame_shard, so max_not_pass goes from 133 to 134.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

claw: @tri-claw batch -- the ledger union in t27 and one merge-commit PR for many port PRs

1 participant