From bdd925a9b08d50d3a0fac0cbf3d250bce7546117 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 18:46:53 +0700 Subject: [PATCH 1/2] skills: t27o -- Sonnet for every role, the merge route when auto-merge refuses, t27b ledger rows, types-ratchet names, merge-base dupe test, sandbox traps, the issue-shape gate warning (Closes #11022) Co-Authored-By: Claude Sonnet 5.5 --- .claude/skills/t27o/SKILL.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.claude/skills/t27o/SKILL.md b/.claude/skills/t27o/SKILL.md index 7eef635b86..7e633234e6 100644 --- a/.claude/skills/t27o/SKILL.md +++ b/.claude/skills/t27o/SKILL.md @@ -60,11 +60,12 @@ 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. Opus plans and reviews, Sonnet implements (`specs/claw/model_route.t27`). 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 ` (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); `cargo check -p tri`. 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`). 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. +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 ` (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 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 `, check `git diff HEAD -- ` is empty, push with `--force-with-lease=:`; auto-merge survives a force push. -7. Edit the ledger row last; add a trap here when it cost more than one try. +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. +8. Edit the epic ledger row last; add a trap here when it cost more than one try. ## Hand-written glue must net to zero @@ -91,4 +92,7 @@ PR #10538 failed it with +9 / -0 at 1e20cfb34. - Building `tri` on master: when `Cargo.lock` pins a crate the sandbox cannot write into `~/.cargo`, clone the registry (`cp -c -R ~/.cargo/registry $TMPDIR/cargo-home/registry`, an APFS clone that costs no space), `CARGO_HOME=$TMPDIR/cargo-home cargo fetch`, and build with that `CARGO_HOME`. Give each lane its own `ZIG_LOCAL_CACHE_DIR`: two lanes sharing one get `BLOCKED ... FileNotFound`. - zsh: `echo "$json"` expands `\n` inside JSON strings, so write API responses to a file and parse the file; `echo =====` runs `=` expansion; text with backticks goes through a quoted heredoc, never into a double-quoted argument (it runs the command). - gen-rust's `use` splice matches words inside string literals and can pull a whole module into the generated file (#10824): after regenerating, look at the gen file's size. +- A trailing `&` inside a `run_in_background` Bash call dies at once (`nice(5) failed`): run the command itself in the background. `rc=$?` after `| tail` is tail's exit code, not the tool's. +- The sandbox cannot delete `.git/worktrees/` (`git worktree remove` and `prune` fail on the admin entry, the directory itself goes): remove only your own entry through the Terminal tab, `rm -rf /Users/playom/t27/.git/worktrees/`. It cannot write `~/.claude/projects` from Bash either (use the Edit tool for memory files). +- The issue-shape gate (`.github/workflows/needs-boundary.yml`) closed 185 issues on 2026-10-18/19, 128 of them wrongly (it judged a queued run's event payload; fixed by #11008). An issue "closed as not planned" with the label `shape-refused` proves nothing: compile `gen/c/policy/issue_shape.c` as the workflow does and run the issue's current body through it before accepting the close (#11007). - Each lane worktree costs about 320 MB; remove finished ones (`git worktree remove --force`) and keep 8 GB free. From ad7b2ec4974b3154d4642fe2e4f544721d0a0bf6 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 18:50:00 +0700 Subject: [PATCH 2/2] skills: t27o -- no developer home path in the worktree-entry line; derive it from git rev-parse --git-common-dir (Closes #11022) The first commit of this PR named the maintainer's home directory and turned `scan` red (tools/check_devhome_paths.py), the trap of #10646. Co-Authored-By: Claude Sonnet 5.5 --- .claude/skills/t27o/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.claude/skills/t27o/SKILL.md b/.claude/skills/t27o/SKILL.md index 7e633234e6..c004ff5fd0 100644 --- a/.claude/skills/t27o/SKILL.md +++ b/.claude/skills/t27o/SKILL.md @@ -93,6 +93,6 @@ PR #10538 failed it with +9 / -0 at 1e20cfb34. - zsh: `echo "$json"` expands `\n` inside JSON strings, so write API responses to a file and parse the file; `echo =====` runs `=` expansion; text with backticks goes through a quoted heredoc, never into a double-quoted argument (it runs the command). - gen-rust's `use` splice matches words inside string literals and can pull a whole module into the generated file (#10824): after regenerating, look at the gen file's size. - A trailing `&` inside a `run_in_background` Bash call dies at once (`nice(5) failed`): run the command itself in the background. `rc=$?` after `| tail` is tail's exit code, not the tool's. -- The sandbox cannot delete `.git/worktrees/` (`git worktree remove` and `prune` fail on the admin entry, the directory itself goes): remove only your own entry through the Terminal tab, `rm -rf /Users/playom/t27/.git/worktrees/`. It cannot write `~/.claude/projects` from Bash either (use the Edit tool for memory files). +- The sandbox cannot delete `.git/worktrees/` (`git worktree remove` and `prune` fail on the admin entry, the directory itself goes): remove only your own entry through the Terminal tab, `rm -rf "$(git rev-parse --git-common-dir)/worktrees/"`. It cannot write `~/.claude/projects` from Bash either (use the Edit tool for memory files). - The issue-shape gate (`.github/workflows/needs-boundary.yml`) closed 185 issues on 2026-10-18/19, 128 of them wrongly (it judged a queued run's event payload; fixed by #11008). An issue "closed as not planned" with the label `shape-refused` proves nothing: compile `gen/c/policy/issue_shape.c` as the workflow does and run the issue's current body through it before accepting the close (#11007). - Each lane worktree costs about 320 MB; remove finished ones (`git worktree remove --force`) and keep 8 GB free.