Repository navigation
chore(skills): harden sweep.py and close gaps in the rules - #1210
Merged
Merged
Conversation
The lint named a test as missing until its file was staged, since it read test declarations from the tracked list while reading paths from the list that holds untracked files too. A rule naming a new test drew exit 1 from a run the curating skill asks for after every edit. Both now read the one list, so an ignored or deleted file still declares nothing.
appendTypeIDs reads every TypeID under an operation by reflection, so a position that names a type without using it would become a GraphQL reachability root, and the check on field arguments would stay silent on that type. The tests that fail on a new position ask for it to be classified, which says nothing about this reader. The new test fills every kind and compares what the reader takes with ir.TypeEdges. It keeps no list, so a position left out of the graph reaches it unaided. A position only an operation holds is no field of a kind and stays out of its reach, which the new rule states.
classify-ir-fields lists what a new field meets, but a new named string type meets identityClasses, which it does not name. The test finds out, while a change sized from the rule does not. The rule is about fields and at its word cap, so this is a rule of its own beside it.
A mutant of a helper in a _test.go file can be seen only by its own directory's tests and by archtest, which reads test files as text, so a whole-module run per survivor repeats what those two settle. That holds for export_test.go too: another package importing the package does not compile it. A review whose gate pass took CI's run also need not repeat it to conclude.
The message rule required every pushed body to stand on main because the default squash pastes them all, but merges set their own body and a pushed branch is never rewritten, so a body a later commit made stale could never be fixed and a review could not tell whether to report it. A new rule holds a body when it is pushed, and the body that lands at merge. CLAUDE.md measured the appended number as three digits. Numbers are four digits now, so a title its command passed at 72 landed at 73. It now counts the number the PR will get, as the push checklist does.
Added directly under the hand lists bullet, the goldens bullet sat against that bullet's last line, which #1238 rewrites, so the two conflicted on nothing but position. One bullet down, they merge. A shorter values bullet keeps the body within its cap once #1219 lands too, which together with this branch's additions it would pass.
The rule said to stop before a golden write when an earlier assertion failed, which a runner can follow and still rewrite a golden from regressed output: an assertion after the write has not run yet, and a parallel subtest runs only after its parent returns, so at the guard nothing has failed. The rule now states what a run does, and its Probe plants a regression that changes the golden, since one that leaves the document alone keeps the golden with or without a guard. It is a rule of its own, as the rule it came from was over its word cap with this added.
The generated shapes left out many references to one wide component, and the Probe read instructions alone, so a product of references and a component's size passed them. The rule adds the shape, grown in both dimensions together, since doubling either alone reads as linear: output grew 2.00 times with references and 1.95 with entries, against 3.89 with both. The Probe reads output bytes too.
Rule 6.16 takes cmp for slices and maps and bars reflect.DeepEqual, which assert.Equal calls, while the tree writes assert.Equal on them about twice as often as it calls cmp.Diff, so a review could not tell a breach from the house spelling. The rule's reason is unexported fields, and on a value with none the two agree, on nil against empty, order and NaN alike, while assert.Equal labels both sides of a failure. This records a departure for such a value rather than a row awaiting the conversion of every call, and CLAUDE.md says the same.
Outside a checkout the lint printed the git command that failed, which names no problem. It now says the tree is read from git and how to get one. It does not fall back to walking the disk: a copy of .claude alone holds no module, so every path check there would be a false finding, while git init in a full copy already lints clean.
Each of these reached a review of #1233, #1235 or #1238 as something the reviewer had to work out alone. build-guards-see-later-writes is new: a guard on how a value is built also matches what undoes the build, since one passed a later write, a later append argument and an elided literal in turn. one-mutant-per-verdict says a plant removing a call removes it, as one discarding its error still runs it. mutation-survivor-scope says an arm's removal alone does not make it equivalent. test-only-fix-reverts-by-hand is new: the revert that keeps test files is empty for a fix in test code, which read as a pass. no-network-through-a-logging-proxy is new, with a row in the claim table. An empty log says nothing about a loopback address or a client whose Transport sets no Proxy, and the rule says so. plant-in-an-unpacked-copy and review-without-origin are new, for a repository that must stay unwritten or has no origin. The copy takes a commit, since git init alone leaves status and diff HEAD nothing to compare.
A word cap is shared across open PRs. Two branches each under a skill's body cap merged with no conflict at 512 words against 500, which neither a conflict check nor the tests show, so the second to land would fail the lint on nothing in its own change.
The lint reads the tree from git by design, and exit 2 outside a checkout is the "cannot run" its docstring defines, so #1251 was closed as not planned. Saying more on that path answers nothing anyone asked for, so this takes the message back out.
A sweep of two builds at one version had no test, so reporting every spec as a stamp change passed. Nothing pinned two pairs of versions in one run or a stamp that is not UTF-8 either. The killed-compile test raced a one-second limit against an interpreter starting, which its neighbour's comment rules out, and it failed on a loaded machine. It now raises the timeout itself, and also covers a side that wrote nothing, which the library may leave as None. missing_ok was dead under suppress(OSError), and the summary now says how many of the specs a stamp change covers.
cmp calls an Equal method and assert.Equal does not, and the two part on a NaN when a slice is compared with itself, so "agree on NaN" claimed too much and the departure reached a value it should not. No type here declares Equal, which the Probe now shows. The count it cites is of a literal slice or map, not of every assert.Equal, so it says that.
Two rules said "above" of a neighbour, which a move leaves pointing at nothing, and one Probe's "that test" could mean either of two. Each now names what it means. The rest is rewrapping, bar one Why reworded.
This was referenced Nov 1, 2026
The title rule said a PR lands under its title, but the repository's squash setting lands a branch with one commit of its own under that commit's subject, and a merge of main is no second commit. #1232's 61-character title landed as a 73-character subject that way. CONTRIBUTING.md already said so for Dependabot; CLAUDE.md, the shipping skill and its message rule did not. The push checklist now measures each subject as it would land.
merge-main-first read as every plant after every merge, which on one PR came to about 3.5 hours for a merge that changed no lowering. A verdict now outlives a merge that left its file and its killing test alone. Planting through go test -overlay writes no tree and runs in parallel, but only the compiler sees it. A plant caught by reading sources, such as a //nolint line or a new TypeKind, passes through an overlay and fails on disk, so the rule says to re-plant such a survivor. Equivalence is a claim about every input, and a green suite answers only for the inputs it holds: deleting a guard in allOf's election passed go test ./... while one order of a two-conjunct allOf lowered to any and the other to integer.
source-scanners-match-every-form gains every import of a path and a range clause's assignment, and its Probe a plant nested in another, each replayed against the child-command rule at the parent of its fix. Pass 1 says a green head behind a moved main gets no exception. A widened field's readers get a rule of their own, since a grep of the field and its old values finds nothing to change when a reader leaned on an old value unsaid. rules-the-tree-still-breaks names rule 6.24, and the IR skill's hand lists line says what its reference gives, which is a list per kind of field and not a test.
load_tree reads declared test names only from files ending in _test.go, and nothing held that: reading every .go file passed the suite, while a skill could then name a function no test file declares. A non-test file declaring one now sits in the fixture.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This resolves the
skills:issues filed up to #1257 in one change, and #1230, adocs:issue on the same title budget the shipping rules state. Later ones, from #1262 on, stay open for a change of their own. Most of it is rule text. Four parts change behaviour:sweep.py,skills_lint.py, and two new tests.#1152, #1155, #1185, #1198 and #1206 mention a skill but are about code, so they stay open. #1251 was closed as not planned, because the lint needs a checkout by design, so this PR leaves the lint's exit outside one as it was.
sweep.py. Two problems came from the same code, so they are fixed together.OUTDIR/runs/<n>/. If those writes fail, the sweep carries on and says how many were not kept, because nothing it compares is on disk.IRVersionbump listed every spec that compiled. The version a document opens with is now set aside before comparing: the summary prints it once, a spec that differs in nothing else isstampinresults.tsv, and the listed specs are the ones that moved. A sweep with only stamp changes exits 0.The direction in the issue was to delete each pair once it agreed. Holding output in memory goes further, because a compile writing to a full disk fails on its own write, which reads as a difference between the builds rather than a crash. On a full disk the old script recorded
morphic: write ir document: write /dev/stdout: no space left on devicebeside documents cut short, before it stopped.A run now also clears
OUTDIR/runs, since rewriting only the specs that differ would leave an earlier run's pairs under numbers that can name another spec. An OUTDIR that cannot be made exits 2 with a message rather than a traceback, and aresults.tsvthat fails partway is removed rather than left to read as a sweep of fewer specs. An emptyirVersioncounts as a version, so it still shows as a difference.skills_lint.py. The lint named a test as missing until its file was staged, so a rule naming a new test drew exit 1 from a run the curating skill asks for after every edit. It read test declarations from the tracked list and paths from the list that holds untracked files too. Both now read the one list, so an ignored or deleted file still declares nothing.Review and merge against a stacked base. The review setup built the tree it reviews by merging
mainalone, so a stacked PR could pass on a tree that does not compile once it meets its base. The setup now readsbaseRefNameand merges that branch first. The same gap is closed at each other site: the gate pass, the new-commits pass,recheck-against-final-tree, the push checklist's conflict line, and a newmerge-the-base-firstrule. That rule is separate because adding this tomerge-main-firsttook it past the word cap.New or widened rules
trial-merge-open-prsnow covers a change to what every file of a kind must hold, such as a golden, and runs that kind's tests on each merged tree. The review's process pass points at it.trial-merge-happenedis new beside it: a trial merged fromFETCH_HEADin a new worktree fails, and its tests then pass on the branch alone.trial-merge-lints-the-skillsis new: a word cap is shared across open PRs, and this PR and feat(ir)!: settle doc references, promotion records and names #1219 merged with no conflict at 512 words against 500. This PR's additions to that skill are now short enough that the two come to 487 on today'smain.widened-field-valuesis new: when a lowering writes a value a field never held, read what the documents assume of the old values, and bump for the change of meaning, which no test sees. fix!: lower file bodies, enums, unions and streams as declared #1191's own 0.23.0 entry lists such a widening. The changing-the-IR description, its "What changes with it" list and the OpenAPI skill's traps all reach it, since nothing would otherwise have sent a reader there.widened-field-consumersis its second half, as a grep of the field and its old values finds nothing where a reader leaned on the old value unsaid.cost-claims-per-armis new: a cost through a function that switches on kind is measured per arm and quoted as a range. The issue allowed measuring only the arm that reads hardest. The rule asks for every arm, naming any left out, because the same reference opens by saying that reading the code does not find a cost.limitation-searched-on-what-it-namesis new: each limitation a body states is searched on the tool or behaviour it names, since a search on the construct can miss the issue tracking it.limitation-stated-where-it-livesandtracker-on-what-a-rule-settlesboth point at it.new-id-namespaceis new: a new entry in a compiler'sNamespacesrewrites every golden document, where a version bump rewrites none, and needs a spec that mints it, since the compiler's tests hold the list to its corpus. The issue did not name that second part; a plant showed it.rebuild-lost-plantsis new, inmutation.md: a plant set nobody kept is rebuilt from the conditions the change adds rather than carried over, and run once before merge even after a comments-only merge. The review's code pass points at it.verdict-outlives-unchanged-filesis new, beside it: a plant at hand keeps its verdict across a merge that left its file and the test that killed it alone, somerge-main-firstno longer reads as every plant after every merge. The issue's comment proposed the file alone, and said why that falls short: a merge can remove the test.overlay-reaches-the-compiler-aloneis new:go test -overlayplants without writing the tree, as that comment proposed, but it reaches only the compiler. A//nolintline and a newTypeKindeach pass through an overlay and fail on disk, becauseinternal/archtestandinternal/declsread the sources at run time, so the rule says to re-plant such a survivor.equivalent-means-every-inputis new: a survivor is recorded as equivalent only with the reason no input can observe it, after compiling inputs across the construct's domain, since a green suite answers for the inputs it holds.classify-named-stringsis new, besideclassify-ir-fields: a named string type needs anidentityClassesentry. It is a rule of its own becauseclassify-ir-fieldsis about fields.mention-is-no-useis new: aTypeIDposition that names a type without using it stays out ofir.TypeEdgesand of each reader that takes the class as a use. The issue asked for it to stay out of every reflective reader, which would be wrong for one resolving references, since a mention can dangle.body-lands-at-mergeis new: a commit body could stand onmainwhen pushed, and a later commit making it stale is no finding, since a pushed branch is never rewritten and merges set their own body. A merge keeping the default paste edits a stale body out.commit-and-pr-message-formno longer claims the default squash decides what lands.finish-checks-before-the-goldenis new, split fromtests-fail-fast-and-legibly: no assertion follows a golden write, and one that may start a parallel subtest runs inside a serialt.Run, since a guard ahead of the write sees neither failing. Its Probe plants a regression that changes the golden, as one that leaves the document alone keeps the golden with or without a guard.deep-generated-shapesadds many$refs to one wide component, and reads output bytes beside instructions. The issue asked for the shape and the bytes; this also grows both dimensions together, since doubling either alone reads as linear.bound-the-productnames references as a dimension.build-guards-see-later-writesis new: a check on how a value is built also matches a later write that resets it, the forbidden value in each argument of anappend, and a literal with an elided type.source-scanners-match-every-formgains every import of a path and arangeclause's assignment, and its Probe a plant nested in another.test-only-fix-reverts-by-handis new: the revert that keeps test files is empty for a fix in test code, which read as a pass.no-network-through-a-logging-proxyis new, with a row in the claim table. It states what the proxy cannot see, since a request to a loopback address and a client whoseTransportsets noProxyboth leave the log empty.plant-in-an-unpacked-copyandreview-without-originare new, for a repository that must stay unwritten or has noorigin. The issue saidgit initforstatusanddiff; the copy also takes a commit, sincegit initalone leaves them nothing to compare.moved-proseis new, besidemoved-comments: it covers text that moved word for word and went stale when its neighbour did not move, a citation that outlived its passage, and a rewrapped line that opens with block markup.Found while making this change, so no issue tracks them
count-on-one-threadis new: an instruction count over a compile is taken underGOMAXPROCS=1 GOGC=off. Followinginstructions-not-wall-clockas written, the same two builds read +2.73% and then -2.08%; pinned, they read +2.06% with each side's range under 1%.trial-merge-happenedis new, as above: a loop here reported three green trial merges that had never happened.pr-claims-match-evidencenow holds a match count to the matches read, and a body edit to a push that has landed. A body here ran ahead of a commit the lint had refused, and a count of matching diagnostics turned out to hold ordinary spec text.closing-keywordssays to read the field seconds after a save. It listed one of this PR's issues straight after opening.Corrected rules
rules-the-tree-still-breaksnow names rules 6.15 and 6.24, and no longer implies its list is complete. test: most test doubles carry no stub, spy, fake or mock prefix #1279 tracks 6.24, as no issue did.redundant-guardasks whether removing a guard changes any outcome. A guard whose removal changes none is deleted, where the old text told a review to pin something no test could fail on.CLAUDE.md's sentence on guards stays as it is: it already gives this answer, and the rule now agrees with it.better-than-mainno longer sends every output change to a Breaking section, whichmorphic-shipping-prsties to a!in the title.mutation-survivor-scopeno longer asks for a whole-module run for a helper in a_test.gofile, where its directory and./internal/archtestsettle it. This departs from the issue twice. Its own directory is not enough, since archtest reads test files as text. Andexport_test.gosymbols are not an exception: another package importing the package does not compile that file.go test ./...too, as it already does formake gate. Pass 1 says a head behind a movedmaingets no such exception.one-mutant-per-verdictsays a plant removing a call removes it, as one discarding its error still runs it, andmutation-survivor-scopesays an arm's removal alone does not make it equivalent.CLAUDE.mdcounts the appended number at the number the PR will get. It fixed the width at three digits, so a title its command passed at 72 landed at 73.CLAUDE.mdand the shipping skill said a PR lands under its title. A branch with one commit of its own lands under that commit's subject, asCONTRIBUTING.mdalready said and test(ir/irverify): make the sort test reach its Path tiebreak #1232 shows, so every commit subject now counts the number, and the push checklist measures each as it would land.A departure to weigh. #1246 left two ways to settle
assert.Equalagainst rule 6.16, which takescmpfor slices and maps and barsreflect.DeepEqual, whichassert.Equalcalls.assert-equal-on-plain-valuesrecords a departure for a value holding no unexported field, andCLAUDE.mdsays the same; a value holding one keepscmp.Diff. The rule's reason is unexported fields. On a plain value the two agree on nil against empty, on order and on a NaN in separate values, andcmpparts fromassert.Equalin two probed cases: it calls anEqualmethod, so the departure leaves out a value declaring one, which no type here does, and it refuses a NaN in a slice compared with itself. The tree compares a literal slice or map withassert.Equalabout twice as often as it callscmp.Diff. The alternative is a row inrules-the-tree-still-breaksand an issue to convert the calls.New checks.
TestAppendTypeIDs_ReadsWhatTheTypeGraphReadsfills every kind and holdsappendTypeIDs, which reads everyTypeIDunder an operation by reflection, toir.TypeEdges. A position that only mentions a type would otherwise become a GraphQL reachability root, and the check on field arguments would go silent on that type, with nothing saying so: the tests that fail on a new position ask for it to be classified, which says nothing about this reader. The test keeps no list, so it passes on #1219'sDocRefposition with no edit.TestDocuments_OpenNoLineWithAPlusrefuses a line opening with+outside a fence, across the repository's documents and.claude/skills, which a walk of the root leaves out. No document writes a list that way, so such a line is a sum a reflow left at the start of a line, and GitHub renders the rest of the paragraph as a list.Limitations
TestAppendTypeIDs_ReadsWhatTheTypeGraphReadsreaches a type definition's fields. A position only an operation holds is no field of a kind, so nothing holds the reader to it: such a field added toir.Operationleavesgo test ./passgreen, whichmention-is-no-usestates.TestDocuments_OpenNoLineWithAPlusholds the plus marker alone. Every other marker has real lists to tell it from, somoved-proseleaves those to a Probe that prints candidates to read.trial-merge-open-prssays. A base that merges cleanly but breaks the build is caught bymerge-the-base-firstand the review setup, not by the checklist.sweep.pyholds each spec's output in memory for as long as it is compared, so-jbounds what it holds.A tracker search on each of these (
appendTypeIDs,TypeEdges,reflective reader,list marker,markdown block markup,merge-tree,push checklist,sweep memory,sweep.py) returned only issues this PR closes or ones on other subjects, so no issue tracks them.Closes #1184
Closes #1186
Closes #1189
Closes #1193
Closes #1196
Closes #1197
Closes #1203
Closes #1204
Closes #1205
Closes #1208
Closes #1209
Closes #1213
Closes #1216
Closes #1223
Closes #1224
Closes #1225
Closes #1230
Closes #1236
Closes #1237
Closes #1242
Closes #1243
Closes #1246
Closes #1252
Closes #1253
Closes #1254
Closes #1255
Closes #1256
Closes #1257
Test plan
Sweep behaviour, on real builds of
cmd/morphicat this head'ssweep.py:2c2404beagainst20017d99, overtestdataand a corpus of real specs, 2,170 specs in all. The old script lists 2,075 and this one 174, with 1,901 markedstamp. An independent comparison of the old script's kept outputs, as JSON withirVersionremoved, agrees with every one of the 2,170 verdicts.46125b1bagainstbd874baa, overtestdataalone, 215 specs.results.tsvis byte-identical to the old script's, each of the 212 kept pairs matches its bytes, and the printed rows match. The one printed change is the header, which no longer names an outputs directory.results.tsv. This one finishes all 2,170 specs and reports the pairs it could not keep, 112 and 113 in those attempts, and none of its verdicts differ from a run with room.python3.14 -m unittest discoverpasses for both script directories, eight concurrent runs of the sweep's suite included, and 36 runs of its command-line tests, twelve at a time on a loaded machine. 32 mutants ofsweep.pyare each killed by a test, and a comment-only control survives.Evidence the rules cite, replayed rather than quoted:
0611ef9bpassesgo vet ./internal/archtestalone and fails once merged withd707412d. On a local remote holding that stack, withmainat20017d99, the old setup stops on four conflicts with the head alone, where the failure cannot show. The new one merges the base first, which is the merge that fails, and then stops on the conflicts withmain, leaving that tree to review.21854da9andba2f961cmerge with no conflict, andTestConformancefails on the merge.46125b1b, replacing the getter with a field read panicsTestAllOf_BoolBranchContributesNoRequiredNames, and deleting the neighbouringbs == nilguard panics the same test atunmergedBranchKeys.e67594b2against20017d99, instructions retired underGOMAXPROCS=1 GOGC=off, three alternating runs a side on 65,000-member specs I generated:doubleadds about 34%,int64about 2% anduuidunder 1%, with each side's range far narrower than the gap ondouble. That is the spread the rule describes; the figures in its Why are the ones its citation pins.The rest:
DocRefguard fromappendTypeIDson a trial merge with feat(ir)!: settle doc references, promotion records and names #1219 failsTestAppendTypeIDs_ReadsWhatTheTypeGraphReads, which passes there unedited. Adding a struct holding aTypeIDtoir.Docs, asmention-is-no-use's Probe says, fails it until the reader skips the struct. Three mutants of the test redden it, its guard against comparing nothing among them.load_treeeach reddentest_skills_lint.py, and a comment-only control survives.KindPrimitivechanged in(*Primitive).MarshalJSONToat707849c8,TestConformance/scalar-formatunder-updatefails and still rewrites its golden, from an assertion after the write. test: witness common formats and pin what the suite left unheld #1192 moved that assertion ahead of the guard, so the same plant at this head fails and leaves the golden alone. A guard in a test holding a parallel subtest readsFailedfalse, and true once the subtest sits inside a serialt.Run.curl -xrequest and a plantedhttp.Get, and logs nothing for a loopback address or a client with its ownTransport, which still dials out.statusand one change indiff HEADafter a plant, and both fetches ofreview-without-originwork in a newgit initwith no remote.fix-must-move-a-goldenprints 0 bytes against test(compilers/openapi): keep the external order oracle offline #1235's test-only fix at7d31114f.t.Helper()from a helper inpass/validate_payloads_test.gopassesgo test ./passand failsTestTestHelpers_StartWithHelper, and a test in another package namingpass.AppendTypeIDsdoes not compile.irfailsTestIdentityClasses_AreAllClassified, and so does an entry for a type no longer declared.printf '%s (#%s)' "<title>" "$N" | wc -cmeasures the 65-character title from docs: the title budget assumes three-digit PR numbers, which are now four #1230 at 73 with its real number, where the old command read 72.unresolvedto theauthentry ofids.Namespaceschanges all 129 golden documents at this head by one hunk each, against the 128 skills: morphic-changing-the-ir does not say a new ID namespace rewrites every golden #1213 measured, and theuniq -cline innew-id-namespace's Probe prints only that entry's lines.TestNamespaces_DeclaredAreExactlyWhatTheCorpusUsesfails on the plant.namesMedia's check onmime.ParseMediaType's error at2c2404befails no test across 40 packages, while a control mutant of the same function failsTestDecodeOptions_Refusals.content entryandseveral content entriesmiss cli: --explain doesn't list the Unmodeled entries kept at a coordinate #693, andexplain Unmodeledfinds it.TestDocuments_OpenNoLineWithAPlusfails ondocs/emitters/emit/printing.mdas it stood at612b11bd, and on a+line planted in a skill and indocs/architecture.md. Four mutants of the check each reddenTestPlusLines_ReportsAMarkerOutsideAFence.moved-proseawk Probe, run as the rule prints it, flags a planted reflow of each marker (===,---,>,-,1.,#) and leaves a real list alone. It prints four candidates overdocs/at this head.SKILL.mdblocks print them, work on this PR. The checklist now prints eleven of this branch's earlier subjects, past the cap once the number is counted. They are pushed and stay as they are: a branch of several commits lands under its title, which is 66 characters with its number.deda5731, 240 of the 241 with several commits of their own landed under their titles. Each of the four with one commit whose subject differs from the title landed under that subject: refactor(compilers/openapi): lift the core's leaf methods out #197, refactor(compilers/openapi): free component and response lowering #216, and fix(engine)!: keep compiler diagnostics and exit on spec problems #335 and test(ir/irverify): make the sort test reach its Path tiebreak #1232, which have a merge ofmainbeside the commit.source-scanners-match-every-formgains, replayed on test: give every covered child its own coverage directory #1233's child-command rule: a row for a named import beside a blank one fails at15a7e663, and one forcmd.Envas a range value atc6b9992c. Stopping the walk at a match in eachEnvbranch, or at any selector, passes ate3bd3168and fails atd2042a66, which added the nested rows.electat fix(compilers/openapi)!: lower allOf by what its conjuncts say #1269's68ac67d1:{format: int32}then{type: integer}lowers throught/prim/any, and the swapped order throught/prim/integer. With the guard the two agree.appendTypeIDsthroughgo test -overlayfails its test and leaves the tree clean. A//nolintline and a newTypeKindthrough an overlay passTestSuppressions_NoDirectiveStandsInTheSourceandTestTypeDef_HandWrittenKindListsAreComplete, and fail them on disk.git grep -n -E 'Content\.File|File' e1aa55c0 -- docs/emitters/refine docs/emitters/plan/operations.mdprints nothing, the casewidened-field-consumerscovers.skills_lint.pyandgo test ./internal/archtestpass on this head.41b7143b, this head before its last merge ofmain, with fix!: lower file bodies, enums, unions and streams as declared #1191 (b8f1b7f3), test(archtest): widen what two style checks see #1199 (e5d2ed23), fix(compilers/openapi): keep a keyword at every schema outcome #1217 (57591e6a), feat(ir)!: settle doc references, promotion records and names #1219 (d643a686), fix!: keep a security requirement naming no scheme #1226 (1c9e1ace), feat(compilers/openapi): read each document's schema identifiers #1227 (a7affa3f), feat(ir)!: type the secrecy and stability a document states #1229 (346c6b67), test: give every covered child its own coverage directory #1233 (d2042a66), test(compilers/openapi): keep the external order oracle offline #1235 (7a69f281), fix(compilers/openapi)!: lower allOf by what its conjuncts say #1269 (32417e90), fix(compilers/openapi): report allOf conjuncts sharing no value #1277 (e80229c1) and fix(compilers/openapi): treat a restated union branch as bare #1278 (afb4a4f0), each confirmed to hold the PR's head.skills_lint.py,go test ./pass -run TestAppendTypeIDsandgo test ./internal/archtest -run TestDocumentspass on all twelve. fix!: lower file bodies, enums, unions and streams as declared #1191 then landed at that head, with no file in common with this PR. fix(compilers/openapi): keep a keyword at every schema outcome #1217, feat(ir)!: settle doc references, promotion records and names #1219, fix!: keep a security requirement naming no scheme #1226, feat(compilers/openapi): read each document's schema identifiers #1227, feat(ir)!: type the secrecy and stability a document states #1229 and fix(compilers/openapi)!: lower allOf by what its conjuncts say #1269 conflict withmainalone since, in the same files with this head as without it. test(ir/irverify): refuse an integerFields entry for no field #1238 landed while this was under review. It rewrote the hand lists sentence inmorphic-changing-the-ir/SKILL.md, whose stale-entry clause it made false, so the merge ofmainkeeps its shorter sentence with this PR's correction to it.5a1b146b, which holdsmain.