Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .claude/skills/t27o/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ For a `.zig` file there is no rustc oracle: the converted spec carries the file'
1. Read the ledger comment on #10522; `CronList` (delete duplicates after a restart); list running subagents. A lane a row calls running is not started again. The analog loop keeps its own ledger on #10486 and owns #10509 and `specs/analog/`: never start work there.
2. Anomalies before new work: open PRs of the epic that are red, conflicting or stale; a lane that reported done with no PR (`git ls-remote origin | grep t27o`); a seal that no longer verifies.
3. Sonnet 5.5 plans, implements and reviews (`specs/claw/model_route.t27`, #10929, owner 2026-10-19); Opus only after two failed attempts or on the owner's word. Two lanes at most from this loop while the analog loop runs on the same 8 GB Mac; one lane at a time edits `rust_convert.t27`.
4. Review before auto-merge, on the PR head: `t27b test` and once `t27c test-report` (vacuous 0) on every touched spec; `t27c seal --verify`; regenerate each gen file and compare byte for byte; `python3 -I tools/dupe_scan.py` and `--like <spec>` (bodies -- `t27c dupes --name` only finds names; #10801 passed the name check with 13 copied bodies); the own-language budget compiled from the merge base (below); `python3 -I tools/check_devhome_paths.py` (#10646 brought nine `/Users/...` test literals); `tri types ratchet` when the diff declares a struct or enum (a fixture type named `Gate` clashed with crm-sellers' `Gate`: the types ratchet counts a second definition of a name as a conflict, so name fixture types uniquely); `cargo check -p tri`. A red is inherited only if the PR's failures are a subset of master's: run `dupe_scan` on the PR head AND on its merge base and `comm -23` the findings (against current master the base drift shows up as false extras). A spec that `use`s `rust_convert.t27` (spice, zig) carries it in its seal closure: re-seal it when rust_convert changes.
4. The local gate is `tri pr preflight --quick` (#11207; `tri pr preflight` adds the corpus ratchet, about 11 minutes): check, tests with vacuity, seal, types, dupes against the base, ledger rows, census, the own-language budget and the home-path scan; exit 0 all passed, 1 a rule failed, 2 evidence unreadable (never a pass). It does not run `check_seal_currency.py`, `check_seal_coverage.py` or the cargo tests: run those after an emitter or spec change. Review before auto-merge, on the PR head: `t27b test` and once `t27c test-report` (vacuous 0) on every touched spec; `t27c seal --verify`; regenerate each gen file and compare byte for byte; `python3 -I tools/dupe_scan.py` and `--like <spec>` (bodies -- `t27c dupes --name` only finds names; #10801 passed the name check with 13 copied bodies); the own-language budget compiled from the merge base (below); `python3 -I tools/check_devhome_paths.py` (#10646 brought nine `/Users/...` test literals); `tri types ratchet` when the diff declares a struct or enum (a fixture type named `Gate` clashed with crm-sellers' `Gate`: the types ratchet counts a second definition of a name as a conflict, so name fixture types uniquely); `cargo check -p tri`. A red is inherited only if the PR's failures are a subset of master's: run `dupe_scan` on the PR head AND on its merge base and `comm -23` the findings (against current master the base drift shows up as false extras). A spec that `use`s `rust_convert.t27` (spice, zig) carries it in its seal closure: re-seal it when rust_convert changes.
5. Merge only green, then auto-merge (GraphQL `enablePullRequestAutoMerge`). It refuses with "in unstable status" while a NON-required check is red; when the four required checks (validate, check-linked-issue, parse-ratchet, own-language) are green and every red is master's, merge with `PUT /repos/gHashTag/t27/pulls/N/merge` and `{"merge_method":"squash","sha":"<the head you reviewed>"}` (the sha makes a late push fail the merge instead of slipping in). Turning auto-merge off does not hold a PR -- any actor with the token can re-arm it (#10801 merged five minutes after it was switched off). To hold a PR, convert it to a draft (`convertPullRequestToDraft`); `markPullRequestReadyForReview` when it may go.
6. Stacked PRs and squash merges: after the base merges, `git rebase --onto origin/master <old base tip>`, check `git diff <reviewed head> HEAD -- <converter files>` is empty, push with `--force-with-lease=<branch>:<old sha>`; auto-merge survives a force push.
7. A t27b change that makes ledger-blocked specs pass, or moves a blocker, edits `docs/reports/t27b_expectations.json` in the same PR (the rows and `max_not_pass` recounted; precedents #10862, #10999). The steward applies UNEXPECTED PASS and UNLISTED from a master run itself but refuses MOVED; a new spec's UNLISTED row is the steward's.
Expand All @@ -82,6 +82,17 @@ This is the gate CI runs, compiled from the base revision. Most "never used" ite

PR #10538 failed it with +9 / -0 at 1e20cfb34.

## Day-two lessons (2026-10-19/20)

- Measure before you write a rule, and write it only above a stated threshold. Lane A5 (`Vec` parameters, ceiling 1 fn) and lane A6 (iterator chains, 17 to 32 fns) each saved a pull request by posting the table first and closing the issue as not planned.
- The Rust converted share is flat (9.93% to 9.88%): the bound is what t27 cannot say (heap, strings, closures, tuples), not missing converter rules. Conversion deletes about 1% of hand-written lines (#11149, #11159, #11168); the RFC `docs/now/2026-10-20-heap-free-collections-rfc.md` says build no construct yet (bar: a pilot rate of 15 in 100, best measured 1.3).
- An emitter fix moves the output of every spec it touches, and each needs its seal re-saved after reading the change. Run `python3 tools/check_seal_currency.py` and `python3 tools/check_seal_coverage.py` locally before pushing (#11192 lost an hour to 16 stale seals), diff the output over all tracked specs, and never call a seal "already stale on master" without reading master's CI.
- Say whether a count is of items or of fns, and over which sweep: 6,180 refused items over 16,057 fns was reported as 38.5%; the fns-only share is 30.8%.
- A lane cleans only its own named scratch directory, never a glob in `$TMPDIR` or the shared scratchpad (one wiped 29 files of other lanes).
- Free disk follows swap and load, not files: measure with `df` and the load, keep lanes to one job at a time, and delete a profile you do not need (`target-tri/debug` was 2.5 GB).
- A PR-body edit re-queues the required `check-linked-issue`: finish the body before the final CI wait. Merge a docs-only PR only after the checks that exist have completed.
- The first golden port (#11157) is the recipe for deleting hand Rust: issue, `tri t27o`, review the spec, keep the hand tests, gen-rust into `bootstrap/gen/rust/` (`git add -f`), delete the file, mount it from the parent `mod.rs`, then the real crate's `cargo check --all-targets` and tests, and a side-by-side run of old and new (756 million comparisons, 0 disagreements).

## Traps met on this Mac

- `.claude/skills/**` is not writable from the session's own worktree in the sandbox; a checkout that touches it half-applies (index changed, file unchanged). Work in a separate worktree: `git worktree add --no-track -b <branch> $TMPDIR/t27o-loop/wt-x origin/master`, then `git -C $TMPDIR/t27o-loop/wt-x config --worktree core.hooksPath .githooks`.
Expand Down
Loading