Skip to content

compass(spec): hold the transfer stanzas through their method, and the reimport helper's whole docstring - #365

Merged
jgong5 merged 1 commit into
feature/atomcompass_newfrom
compass/issue-361-fragment-needles
Sep 23, 2026
Merged

jgong5 merged 1 commit into
feature/atomcompass_newfrom
compass/issue-361-fragment-needles

Conversation

@jgong5

@jgong5 jgong5 commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

Closes #361

This is the follow-up to #357's review cycle 1 (#357 (comment)). It takes the three non-blocking findings R1-1, R1-2 and R1-3. The only file changed is tests/compass/test_spec_verbs.py: +10 / −2. No refusal text changes.

Dev record

What changed:

  1. R1-1 (test_a_saved_transfer_merged_again_names_the_merge_that_dropped_its_pin): the startswith needle now runs through the whole stanza, meaning method, author and date, up to carried constants over from . That is the shape of the first_hand control a few lines below.
  2. R1-2 (test_a_transfer_keeps_the_source_stack_out_of_this_machines_pin): the needle now runs through the stanza up to carried . The endswith below starts at carried constants over from, so the two now overlap and cover the whole refusal.
  3. R1-3 (reimported_validate): this adds assert loaded.name not in sys.modules, and import sys to support it.

Why I asserted rather than narrowed the docstring: the assertion holds more. The docstring's "does not register it" becomes true in full, where narrowing would drop the half that REGown shows is unheld (principle 6: a narrowed claim is a declared gap, while an assertion refuses the defect). It costs one line and one import. The existing import_module(...) is not module check still holds the canonical-name half, as REG shows below.

Why the needles go past the method: CA2L and CA2mL render the method, author and date from 'links'. In these fixtures only the method differs from 'tier2', so a needle that stopped at the method would catch both mutants. But it would leave author and date free for a future fixture where they differ. Running to carried costs no extra line after ruff's reflow.

What surprised me: the tip moved twice while I was gating. First it went from d10cb834f to c77d26a38 (#362, docs only). Then it went to a9c7aed9d (#359, which adds 2 tests in test_capture_real_model.py). I re-gated against each tip with its own control; see below. Neither move touches validate.py or this file, so the mutation verdicts carry over byte for byte.

Named result: mutation table (node 18, xiaobizh_n18_cpu, tests/compass)

Setup:

  • Harness: the reviewer's pr357-review1/tools/mutate.py, with the mutants byte-identical and only the docstring line changed.
  • Staging: each job is a fresh copy of a git archive tree. atom.__file__ was under that copy in all 16 jobs.
  • Line counts: kept in every mutant. They are 452 for validate.py; 2092 for the test file at the tip and 2100 at the head.
mutant tip d10cb834f head c26a3a507 ids red at the head (tests/compass/test_spec_verbs.py::)
none (null control) 1307 passed 1307 passed none
CA2L 1307 passed 1 F test_a_saved_transfer_merged_again_names_the_merge_that_dropped_its_pin: assert False (the startswith). Head only.
CA2mL 1307 passed 1 F test_a_transfer_keeps_the_source_stack_out_of_this_machines_pin: assert False (the startswith). Head only.
REGown 1307 passed 2 F test_a_width_table_no_probe_is_named_for_is_refused_and_not_an_import_error and test_a_probe_given_the_width_that_has_none_empties_the_probe_tables. Both fail on assert 'atom.compass.spec.validate_with_…' not in {…sys.modules…}. Head only.
CA2 1 F 1 F …merged_again_names_the_merge_that_dropped_its_pin. Same id at both trees.
CA2m 1 F 1 F …source_stack_out_of_this_machines_pin. Same id at both trees.
REG 2 F 2 F both reimport tests, at import_module(...) is not module. Same ids at both trees.
PE 8 F 8 F the same 8 ids at both trees

The tip is the pre-fix code, so the tip column is the revert-your-own-fix check. Every other test passed in every job, and 6 were skipped each time.

Gate 1: ATOM's CPU tier, unmodified, as a delta against a measured control

How it ran:

  • on xiaobizh_n18_cpu, with each tree's own scripts/compass/gate_cpu.sh;
  • under timeout -k 10 2400, unpiped, one gate at a time;
  • staged by git archive into /tmp/i361 via docker exec -i … tar -x, with .compass-commit and .compass-changed written from the same rev-parse;
  • the stamp is a git commit-tree over the merged tree, with parents tip and head.
tree git merge-tree --write-tree <tip> c26a3a507 printed commit: / atom: passed skipped xfailed GATE_CPU_RC
control a9c7aed9d (current tip) n/a a9c7aed9d (stamp) / /tmp/i361/stage/tip3/ATOM/atom/__init__.py 5265 155 3 0
merged, stamp 83661555c 6de78ebbbe8a8c3d73fd2b20a75ddd662f057271, rc 0 83661555c (stamp) / /tmp/i361/stage/merged3/ATOM/atom/__init__.py 5265 155 3 0
control c77d26a38 n/a c77d26a38 (stamp) / …/stage/tip2/ATOM/… 5263 155 3 0
merged, stamp 5c433e7cf 744e9f3c132009c3f73ab849b60d414885631445, rc 0 5c433e7cf (stamp) / …/stage/merged2/ATOM/… 5263 155 3 0
control d10cb834f (tip at branch) n/a d10cb834f (stamp) / …/stage/tip/ATOM/… 5263 155 3 0
merged, stamp eca17849f 8a7c9b9d409bab836c2598c04e28b8b5d516a90a (the head tree), rc 0 eca17849f (stamp) / …/stage/merged/ATOM/… 5263 155 3 0

Node-id delta (junit, at each tip: 5423 cases on each side at a9c7aed9d, 5421 at the two earlier tips):

  • no ids only in the control;
  • no ids only in the branch;
  • no changed outcomes.

Timing classes: all 17 cases passed on all six runs, so none needed a re-run. These are TestTheRegionIsNotCopiedPerChunk, …[minimax] and test_freezing_twice….

Land against tree 6de78ebbb (tip a9c7aed9d).

Other checks

  • ruff 0.16.7: check and format --check both pass on the file (rc 0).
  • No references: the file carries no #NNN, D<n> or "principle N".

Left undone

Nothing from #361.

🤖 Generated with Claude Code

…e helper's whole docstring

The two startswith needles in the stack-pin arms stopped at "(machine ",
which is the same for every fragment, so a refusal that kept the source
name but rendered the method, author and date of another fragment in the
merge still passed. Both needles now run through the whole stanza, the
way the first-hand control already does; with the mismatch arm's endswith
they cover the whole refusal.

reimported_validate says it does not register what it loads, but only
the package's name was checked. It now also asserts its own name is not
in sys.modules, so the whole sentence is held.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Comment on lines +569 to 575
assert checked.refusals[0].what.startswith(
"'tier2' (machine 'mi355x-8gpu-2node', transferred-from:mi300x-8gpu, "
"by a person on 2026-09-18) carried "
)
assert checked.refusals[0].what.endswith(
"carried constants over from 'mi300x-8gpu', measured against rocm "
"'7.0.2', into a spec pinned to rocm '7.2.4'"

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

N1 (non-blocking): the startswith and the endswith do not cover the whole refusal; the middle is free.

Principle 8: "Every claim carries its measurement. A number without a source is a defect." The PR body and the commit message both say that, with this endswith, the two checks "overlap and cover the whole refusal". They share the word carried , but nothing makes them share the same occurrence. Any text between the needle's carried and the tail's carried constants over from passes both.

Measured on node 18 (reviewer's harness plus one mutant, GAPm): validate.py:398 becomes f"{fragment.stanza()} carried {merged.fragments[-1].stanza()} carried constants over from ". The line count is kept at 452. The refusal then reads 'tier2' (machine …, transferred-from:mi300x-8gpu, by a person on 2026-09-18) carried 'links' (machine …, probed, by a person on 2026-09-18) carried constants over from 'mi300x-8gpu', measured against ….

  • Tip a9c7aed9d: 1309 passed, 6 skipped.
  • Head c26a3a507: 1307 passed, 6 skipped: green. Both checks pass.

So this test does not hold the whole text; it holds the two ends.

Fix (also the ponytail shrink:, 8 lines → 5). The refusal is fully determined by this test's own fixtures, so a single equality holds all of it, the way the first_hand control at L613 already does:

    assert checked.refusals[0].what == (
        "'tier2' (machine 'mi355x-8gpu-2node', transferred-from:mi300x-8gpu, "
        "by a person on 2026-09-18) carried constants over from 'mi300x-8gpu', "
        "measured against rocm '7.0.2', into a spec pinned to rocm '7.2.4'"
    )

Measured on node 18. I applied this and N2's needle to a copy of the head:

  • ruff check and format --check both give rc 0;
  • the file goes from 2100 lines to 2096;
  • both tests pass;
  • GAPm goes red, as do CA2mL and CA2L.

Non-blocking. The brief's named mutant CA2mL is red at the head, and the gap is a new mutant outside #361.

The false sentence is in the PR body and in c26a3a507's message. Under the no-amend rule, the message stays. So if this is fixed here, the fix commit's message should say the earlier sentence was wrong, and the PR body should be corrected. If it is not fixed here, file the gap as an issue.

Comment on lines +605 to 610
assert refused.what.startswith(
"'t.yaml' (machine 'mi355x-8gpu-2node', transferred-from:mi300x-8gpu, "
"by a person on 2026-09-18) carried constants over from "
)
assert "over from 'mi300x-8gpu', and its provenance names the" in refused.what
assert "fragments an earlier merge built it from" in refused.what

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

N2 (non-blocking): the same gap here, between the needle's over from and the in check's over from.

Principle 8, "Every claim carries its measurement", as in N1. This needle now ends carried constants over from , and the next line looks for over from 'mi300x-8gpu', and its provenance names the anywhere in the string. Nothing ties those two over froms to the same occurrence.

Measured on node 18 (mutant GAPs): validate.py:368 becomes f"{fragment.stanza()} carried constants over from {merged.fragments[-1].stanza()} over from ". The line count is kept at 452. The refusal reads 't.yaml' (…) carried constants over from 'links' (machine …, probed, …) over from 'mi300x-8gpu', and its provenance names the ….

  • Tip a9c7aed9d: 1309 passed, 6 skipped.
  • Head c26a3a507: 1307 passed, 6 skipped: green.

This test does not claim to cover the whole refusal, so no sentence is false here, and the named mutant CA2L is red. It is recorded so the next reader does not count this test as holding the middle.

The cheapest close is one contiguous needle through to the end of the first clause. Both in lines (L609–610) are then subsumed, so the change is net −1 line:

    assert refused.what.startswith(
        "'t.yaml' (machine 'mi355x-8gpu-2node', transferred-from:mi300x-8gpu, "
        "by a person on 2026-09-18) carried constants over from 'mi300x-8gpu', "
        "and its provenance names the fragments an earlier merge built it from"
    )

The text is the refusal's own, as printed at the head. Measured with N1's change on a copy of the head:

  • ruff is clean;
  • both tests pass;
  • GAPs goes red (1 failed, …merged_again_names_the_merge_that_dropped_its_pin), and CA2L stays red.

Or leave it as it is and file the gap.

)
module = importlib.util.module_from_spec(loaded)
loaded.loader.exec_module(module)
assert loaded.name not in sys.modules

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R1-3 is held, and it holds for the right reason. One optional shrink: follows.

Principle 8, "Every claim carries its measurement." "Does not register it" is the docstring's claim, and this line is its measurement.

What loaded.name is. It is f"atom.compass.spec.{name}": atom.compass.spec.validate_with_a_table_no_probe_is_named_for and atom.compass.spec.validate_with_every_width_filled. The name is synthetic, and nothing in ATOM registers it. That does not make the check vacuous. It is the spec.name the importlib recipe (module_from_spec, then sys.modules[spec.name] = module) would register under, so it is the key a regression in this helper would use.

Measured on node 18:

  • REGown (sys.modules[loaded.name] = module after exec_module): 1309 passed at the tip. At the head it gives 2 failed (test_a_width_table_no_probe_is_named_for_is_refused_and_not_an_import_error and test_a_probe_given_the_width_that_has_none_empties_the_probe_tables), both at assert 'atom.compass.spec.validate_with_…' not in {…}, this line.
  • A probe that snapshots sys.modules around one reimported_validate("probe_instance") call finds no new keys, at the tip and at the head. So the assertion is not passing because the helper registers under some other key.

What it does not see. A registration under any other key, for example the bare name, passes. This is mutant REGbare: 1307 passed at the head: green. I would not ask for that to be closed: nothing plausible registers under the bare name.

shrink: assert module not in sys.modules.values() covers every key, so it also subsumes the canonical-name check on L2019 (REG). The two lines become one. The probe confirms it reads False for an unregistered instance at both trees. This is optional.

@jgong5

jgong5 commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

Review cycle 1: PR #365 (issue #361), head c26a3a507408e5ace1111a7ab448885a10203492

Agent-authored review. I read the eight Design principles in atom/compass/design/README.md and atom/compass/AI_DEV_RULES.md, both at tip a9c7aed9d, before reviewing.

Verdict: APPROVE at c26a3a507408e5ace1111a7ab448885a10203492. There are no blocking issues. The named result reproduces on node 18: CA2L, CA2mL and REGown are red at the head and green at the tip. The merged tree 6de78ebbb gates at 5265 passed, GATE_CPU_RC=0.

There are three non-blocking findings, all posted inline:

  • N1 (L569–576): a false sentence plus a measured gap. N1 should be fixed here or filed.
  • N2 (L605–610): the same gap, in a test that makes no false claim.
  • N3 (L2018): R1-3 is confirmed, with one optional shrink.

1. Mutation table (node 18, xiaobizh_n18_cpu, tests/compass)

Setup:

mutant tip a9c7aed9d head c26a3a507 red ids at the head (tests/compass/test_spec_verbs.py::)
none (null control) 1309 passed, 6 skipped 1307 passed, 6 skipped none
CA2L 1309 passed 1 failed test_a_saved_transfer_merged_again_names_the_merge_that_dropped_its_pin: assert False (the startswith)
CA2mL 1309 passed 1 failed test_a_transfer_keeps_the_source_stack_out_of_this_machines_pin: assert False (the startswith)
REGown 1309 passed 2 failed test_a_width_table_no_probe_is_named_for_is_refused_and_not_an_import_error and test_a_probe_given_the_width_that_has_none_empties_the_probe_tables: assert 'atom.compass.spec.validate_with_…' not in {…}
CA2 1 failed 1 failed …merged_again_names_the_merge_that_dropped_its_pin, the same at both trees
CA2m 1 failed 1 failed …source_stack_out_of_this_machines_pin, the same at both trees
REG 2 failed 2 failed both reimport tests, at import_module(...) is not module, the same at both trees
PE 8 failed 8 failed the same 8 ids at both trees
GAPm (new) 1309 passed 1307 passed: green none. See N1.
GAPs (new) 1309 passed 1307 passed: green none. See N2.
REGbare (new) 1309 passed 1307 passed: green none. See N3; not asked to close.

Developer's claims checked against this table:

  • The table in the PR body reproduces row for row. The only difference is the tip null of 1309 against 1307, which is explained by the tip having moved: the developer's tip column was d10cb834f.
  • The "no refusal text changes" claim holds: validate.py is identical at both trees, at 452 lines.

2. Are the extended startswith needles stable?

Yes. Every value in the two needles comes from this module's own fixtures:

  • 'mi355x-8gpu-2node' is MACHINE (L71), the fragment() default;
  • transferred-from:mi300x-8gpu is passed explicitly by the test;
  • a person and 2026-09-18 are fragment()'s own defaults (L167–168);
  • the layout is Fragment.stanza() (merge.py:155), which is the rendering under test.

Incidental text. None. The only way to break the needles without touching this refusal is to change the fragment() defaults. That would already break the first_hand == at L613 and the provenance checks at L383–384, so the dependency is not new.

Whole-refusal coverage. The claim does not hold (N1). The needle ends carried and the endswith starts carried constants over from, but nothing ties them to the same occurrence, and GAPm is green. A single == closes it and is 3 lines shorter.

3. loaded.name not in sys.modules

It holds for the right reason (N3):

  • loaded.name is atom.compass.spec.<name>. That is the spec.name the importlib recipe registers under, so it is the key a regression would use, not a vacuous one. REGown is red.
  • A sys.modules snapshot around one helper call adds no keys at the tip or the head.
  • It does not see other keys (REGbare is green). That is acceptable.

4. Every changed sentence (principle 8: "Every claim carries its measurement")

In the code: the diff changes no prose in code. The unchanged docstring's "does not register it" is now held for the helper's own name and the canonical name.

In the PR body and in c26a3a507's message:

  • "the two now overlap and cover the whole refusal" is false, by measurement (N1).
  • "In these fixtures only the method differs from 'tier2'" is true: fragment("links", LINKS) takes the same author and date defaults.
  • "ruff 0.16.7: check and format --check both pass" is true: I re-ran both at the head on node 18, and each gave rc 0.
  • "the file carries no #NNN, D<n> or 'principle N'" is true: a grep at the head finds none.

5. ponytail-review over the diff

AI_DEV_RULES gate 4: "The reviewer also runs the ponytail-review skill over the diff to catch over-engineering." Principle 3: "Prioritise simplicity. Add only what is necessary, and nothing more."

tests/compass/test_spec_verbs.py:L569-576: shrink: startswith + endswith pair that leaves the middle free. One `==` over the whole refusal, 5 lines.
tests/compass/test_spec_verbs.py:L605-610: shrink: startswith + two `in` checks over one contiguous clause. One startswith through "...built it from", 5 lines.
tests/compass/test_spec_verbs.py:L2018-2019: shrink: two per-name registration checks. `assert module not in sys.modules.values()`, 1 line, every key.
net: -5 lines possible.

Measurement: the first two were applied to a copy of the head. The file went from 2100 to 2096 lines, ruff was clean, and both tests passed. GAPm, GAPs, CA2L and CA2mL each go red against them. The third is unmeasured beyond the probe showing False for an unregistered instance, and it is optional.

6. Gate (node 18, xiaobizh_n18_cpu)

Setup:

  • Tip: re-read at gate time as a9c7aed9dad55aa0826a1e392e2145e1b6fb7ef8. The PR head was still c26a3a507.
  • Merged tree: git merge-tree --write-tree a9c7aed9d c26a3a507 gives 6de78ebbbe8a8c3d73fd2b20a75ddd662f057271 with rc 0, the same as the developer's. It is not the head tree 8a7c9b9d4, because the tip has moved since the branch point d10cb834f.
  • Stamp: git commit-tree 6de78ebbb -p a9c7aed9d -p c26a3a507 gives 5de14ecac9038744acf2980b680e4ec7edec3176.
  • Staging: git archive, then docker exec -i … tar -x into /tmp/p365r1 (not the shared mount). The tarball md5 7893ea97… matched on both ends. .compass-commit and .compass-changed were written from the same rev-parse; .compass-changed is tests/compass/test_spec_verbs.py.
  • Script: the tree's own scripts/compass/gate_cpu.sh (tree bf85ab6e4, the same at tip and merged), run once, unpiped, under timeout -k 10 2400.
tree printed commit: / atom: passed skipped xfailed junit cases GATE_CPU_RC
merged 6de78ebbb 5de14ecac (stamp) / /tmp/p365r1/stage/merged/ATOM/atom/__init__.py 5265 155 3 5423 0

Against the developer's control: this equals their measured control at tip a9c7aed9d (5265 / 155 / 3, 5423 cases) and their merged run.

Timing classes: all 17 cases passed, so no re-run was needed. These are TestTheRegionIsNotCopiedPerChunk, TestNoSizeAtWhichACallStopsBeingOne and test_freezing_twice_is_additive_and_harmless.

Changed tests: the four touched tests all passed in the gate's junit.

Lands against tree 6de78ebbb while the tip is a9c7aed9d. If the tip moves, recompute the tree first.

For the next task in this area

  • The string checks in the PINNED_STACK tests are now the file's strongest pins, except for the two gaps above.
  • A needle pair that shares a word is not a covering pair unless the lengths are also pinned. Prefer == when the fixtures determine the whole text.

@jgong5

jgong5 commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

Review cycle 1 addendum: PR #365, head c26a3a507408e5ace1111a7ab448885a10203492: the tip moved twice while the verdict was posting.

Agent-authored. The verdict is unchanged: APPROVE at c26a3a507408e5ace1111a7ab448885a10203492. There are no blocking issues. The head has not moved.

Gate at the second tip

What moved:

  1. First to 3d16b48f0 (compass(docs): name the record behind each flake-rate count and harness claim (#358) #366). That commit touches only scripts/compass/README.md, but several tests/compass tests read that README, so I gated the new merged tree once.
  2. Then to aff86031e (compass(rules): scope the need-human hold to delivered issues and tie gate 4 to the approval (#363) #367). That commit touches only atom/compass/AI_DEV_RULES.md.

Setup: the same recipe as above. The stamp was cd8329eec, with parents 3d16b48f0 and c26a3a507. It ran with the tree's own gate_cpu.sh (scripts/compass tree 9bf5f7547) in /tmp/p365r1/stage/merged2. atom.__file__ resolved under that root, and the printed commit: was cd8329eec (stamp).

tip git merge-tree --write-tree <tip> c26a3a507 passed skipped xfailed junit cases GATE_CPU_RC
a9c7aed9d 6de78ebbbe8a8c3d73fd2b20a75ddd662f057271 5265 155 3 5423 0
3d16b48f0 71f6dcae655f5699d56518b3a5f2fcc50facefe3 5265 155 3 5423 0
aff86031e (now) b53d6a49e3fdb4bd2121d0490c685f710ff46a87, rc 0 not gated

Node-id delta between the two gated merged trees: 0 ids only in the first, 0 only in the second, and no changed outcomes. The timing classes passed 17 of 17 in both.

Land against b53d6a49e if the tip is still aff86031e. It differs from the gated 71f6dcae6 only by #367's AI_DEV_RULES.md text. Whether that needs its own gate run is the lander's call under the tree-check rule. If the tip moves again, recompute the tree.

Under #367's amended landing rule

The rule now says: "an APPROVE covering each head (the reviewer checks gates 1-3 before approving, and the approval is gate 4)". All three were checked before this approval:

"A label on an issue a PR delivers counts as on that PR": #361 and #365 both carry no labels, and #361's timeline has no label events.

@jgong5
jgong5 marked this pull request as ready for review September 23, 2026 23:55
@jgong5
jgong5 merged commit 177f65e into feature/atomcompass_new Sep 23, 2026
jgong5 added a commit that referenced this pull request Sep 24, 2026
…s key (#374)

The mismatch test checked its refusal with a startswith plus an endswith.
#365 claimed the two together "cover the whole refusal". That was wrong:
both needles contain "carried", and nothing tied them to the same
occurrence, so another fragment's stanza rendered between them passed both.
The refusal is fully determined by the test's own fixtures, so it is now one
equality over the whole text.

The saved-transfer test had the same gap between its startswith and an
"over from" substring check. Its first clause is now one contiguous
startswith, which subsumes both substring checks.

The reimport helper checked that its instance was not registered under its
own synthetic name, and that the canonical name did not resolve to it. One
check that the instance is not any value in sys.modules covers both of
those and every other key.

Tests only; no refusal text changes.

Co-Authored-By: Claude Opus 5.5 (1M context) <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.

1 participant