Skip to content

compass(spec): a saved document merged again does not claim the transfer was asked - #333

Merged
jgong5 merged 4 commits into
feature/atomcompass_newfrom
compass/issue-331
Sep 23, 2026
Merged

jgong5 merged 4 commits into
feature/atomcompass_newfrom
compass/issue-331

Conversation

@jgong5

@jgong5 jgong5 commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

Closes #331

What changes

When a saved document is merged again, validate no longer says it asked the transfer condition if it had nothing to ask it of.

_reach in atom/compass/spec/validate.py now treats a Merge fragment whose provenance.method is mixed as one that may hide a transfer:

  • No other fragment states a transfer: TRANSFERS goes in not_asked, and the reason names the fragment.
  • Another fragment does state a transfer: TRANSFERS goes in asked_in_part. That transfer is still checked by _transfers and can still be refused.
  • A transfer is stated and a stack pin did not resolve: reached has already listed TRANSFERS once. That is under not_asked when no pin resolved, and under asked_in_part when some did. The mixed arm adds nothing, so no condition is listed twice.

merge.py is not touched.

Fix shape: (b), narrowed to method: mixed

Why not (a). A merge keeps a transfer's source pin out of the document on purpose (merge.py:285). So a re-merge has nothing to check the transfer against. Recording transfers in provenance would mean recording each source pin, and that needs a new schema field in fields.py. That file is outside the file set, and the change would be well past 40 lines. With the pin gone, the honest result is "not asked, and here is why", not a check against a stand-in. That is refuse-rather-than-fall-back.

Why narrow (b). (b) as the issue words it keys on provenance.fragments. Every merged document states that field, including a re-merge of an all-probed document that holds no transfer. I measured it as a mutant, a8186d6a3: the head with only the hidden predicate changed to "provenance.fragments" in f.values. The null control goes red:

>       assert validate(merge([control]), **asked).not_asked == ()
E       assert ('whether a t... a document',) == ()

Only a mixed fragment can hide a transfer:

  • A merge whose fragments agree on one method states that method. probed means nothing was transferred.
  • transferred-from:X makes the re-merged fragment a transfer in its own right, and Merge.transfers already asks it.
  • mixed absorbs later merges, so the ambiguity survives any number of re-merges.

Keying on the method is also the simpler predicate.

Known cost, measured below. A mixed document with no transfer, such as datasheet plus probed, now reports TRANSFERS as not asked when it is merged again. That is true: nothing in such a document says a transfer did not go into it.

Named result (node 18, xiaobizh_n18_cpu)

The new test is tests/compass/test_spec_verbs.py::test_a_saved_document_merged_again_does_not_claim_to_have_asked_the_transfer. Measured at head 7c6ded432 (round 2). Each mutant is the head with only validate.py changed, built with commit-tree.

tree commit new test spec suite
head 7c6ded432 PASSED 293 passed
round-1 head d216950a1 plus the new test file 427f81912 FAILED at :654, sum(… partly.asked_in_part) == 1: assert 2 == 1 1 failed, 292 passed
head, guard reverted from unasked + partial to unasked ac6431786 FAILED at :654: assert 2 == 1 1 failed, 292 passed
head with the tip's validate.py (git show 91ef04c22:…, 415 lines) 4960c4b1a FAILED at :643, again.not_asked: assert [] == ['whether a transferred constant came from a spec pinned to this stack'] 1 failed, 292 passed
head without the no-pin guard (if hidden:) ff65207d0 FAILED at :654: assert 2 == 1 1 failed, 292 passed
head with the partial arm sent to unasked (if False:) d637df726 FAILED at :648, beside.asked_in_part 1 failed, 292 passed
head with (b) as worded in the issue 5450ad5da FAILED at :663, the null control, shown above 1 failed, 292 passed

The rows below were probed at round 1. At 7c6ded432, with a transfer beside the saved document, asked_in_part is [TRANSFERS] with all pins, [STACK, TRANSFERS] with rccl deleted (d216950a1 gave [STACK, TRANSFERS, TRANSFERS]), and not_asked is [STACK, TRANSFERS] with no pins.

The rows, probed directly with tp_widths=(1, 2, 4, 8) and observed_stack=STACK. The atom.__file__ printed under each staged root.

subject tip 91ef04c22 head d216950a1
row 1: the original Merge refused PINNED_STACK, not_asked=[] same
row 2: combination.document ok, not_asked=[TRANSFERS] same
row 3: merge([Fragment.from_mapping(combination.document, "machine.yaml")]) ok, not_asked=[] ok, not_asked=[TRANSFERS]
row 3 plus the transfer fragment beside it refused PINNED_STACK, asked_in_part=[] refused PINNED_STACK, asked_in_part=[TRANSFERS]
null control: a re-merge of all-probed merged().document ok, not_asked=[] ok, not_asked=[]
a re-merge of a mixed document with no transfer (datasheet plus probed) ok, not_asked=[] ok, not_asked=[TRANSFERS] (the known cost above)

The spec-test outcome diff, tests/compass/test_spec_*.py, tip to head

With -rA, 292 node ids at the tip and 293 at the head. Every one passed.

> PASSED tests/compass/test_spec_verbs.py::test_a_saved_document_merged_again_does_not_claim_to_have_asked_the_transfer

No existing test's refusal or not_asked text changes. Every node id present at the tip has the same outcome at the head, and no existing test was edited. No existing test validates a Merge that holds a mixed fragment.

Gate 1: scripts/compass/gate_cpu.sh, the tree's own copy, stamped

The trees were staged by git archive and docker exec -i … tar -x into /tmp/i331/{tip,head}/ATOM. The md5 matched on both ends, and .compass-commit and .compass-changed came from the same rev-parse. Each side ran twice. The second run added --junitxml to get per-node outcomes.

side run 1 run 2 GATE_CPU_RC
tip 91ef04c22 (control) 5237 passed, 155 skipped, 3 xfailed 5237 / 155 / 3 0, 0
head d216950a1 5238 passed, 155 skipped, 3 xfailed 5238 / 155 / 3 0, 0

Node-id delta from junit: 5395 cases at the tip, 5396 at the head. The only difference is + tests.compass.test_spec_verbs::test_a_saved_document_merged_again_does_not_claim_to_have_asked_the_transfer passed. No timing-class test moved.

git merge-tree --write-tree 91ef04c22 d216950a1 gives 6aa5fa86ad4100087a1bce8e0eeb67d1294dee39, which equals d216950a1^{tree}.

Round 2, on the merged tree. The tip moved to b63f1a711 (#326, one test file outside this PR). git merge-tree --write-tree b63f1a711 7c6ded432 gives 170da7165c126432587547267584986209e98b5a, stamped as 4789afd51 with commit-tree.

side passed skipped xfailed junit cases GATE_CPU_RC
tip b63f1a711 (control) 5238 155 3 5396 0
merged 4789afd51 5239 155 3 5397 0

The node-id delta is the new test only.

Lines

added removed
production (validate.py), whole PR 25 7
tests (test_spec_verbs.py), whole PR 40 0
round 2 only, production 10 12
round 2 only, tests 10 3

Round 1 was +53 against an estimate of 20–40. Round 2 was +20/−15 against 10–20. Neither is over 2x, so neither is an escalation.

Dev record

  • Found. The issue's fix (b) over-reports: every merged document states provenance.fragments. I narrowed it to method: mixed, and the mutant above records why.
  • Decided. A real transfer next to a mixed fragment is reported as asked in part, not unasked. The transfer that was asked can already have earned a refusal, and the module's docstring forbids filing that under "not asked".
  • Round 2. F1: when some stack pins resolved, asked_in_part listed TRANSFERS twice. The guard now reads both lists. F2: the docstring clause says "and a stack pin resolved", because with no stack pin a transfer beside the saved document is reported as not asked, not as asked in part.
  • Left undone. A hand-authored document that writes method: mixed is treated the same way. A free-text method such as datasheet+probe is not recognised as possibly hiding a transfer. No merge writes that form.

🤖 Generated with Claude Code

jgong5 and others added 2 commits September 23, 2026 17:17
…fer was asked

Issue #331. A merge whose fragments disagree on a method writes `method: mixed`
and keeps a transfer's source pin out of the document. So when that saved
document is merged again, the new `Merge` has no transfer to check, and `_reach`
counted `TRANSFERS` as asked because `merged.transfers` was empty. The same
spec that its first merge refused `PINNED_STACK` came back clear with
`not_asked == ()`.

`_reach` now reports `TRANSFERS` as not asked when a fragment of the `Merge`
states `mixed`. When other fragments state a transfer that was asked, it
reports `TRANSFERS` as asked in part instead. A re-merged document built from
one method, such as all `probed`, still reports the condition as asked.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…not asked, once

This covers the branch in `_reach` that defers to `reached` when no stack pin
resolved. Without that branch, the condition would be listed as both not asked
and asked in part.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Comment thread atom/compass/spec/validate.py Outdated
# out of the document. Where none of the pins resolved, `reached` has
# already reported the condition as not asked.
hidden = [repr(f.source) for f in merged.fragments if f.method == "mixed"]
if hidden and not any(c.startswith(TRANSFERS) for c in unasked):

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.

Agent-authored (reviewer, cycle 1). F1, blocking. Principle 8, "Every claim carries its measurement": asked_in_part now claims the transfer condition twice.

This guard reads only unasked. When some stack pins resolve, reached(TRANSFERS, STACK_PINS) has already put TRANSFERS into partial. The mixed arm then appends a second TRANSFERS entry to partial.

Measured on node 18 (xiaobizh_n18_cpu). The saved document from the issue table has device.software_pinned_to.rccl deleted, and the transfer fragment sits beside it. Subject: merge([thin, transfer]), with tp_widths=(1, 2, 4, 8) and observed_stack=STACK.

tree asked_in_part heads
tip 91ef04c22 [STACK, TRANSFERS]
head d216950a1 [STACK, TRANSFERS, TRANSFERS]
head, control: an all-probed document in place of the mixed one [STACK, TRANSFERS]

The result is the same whether the transfer is pinned to 7.0.2 or to this stack. The two entries at the head read:

asked_in_part: whether a transferred constant came from a spec pinned to this stack -- `device.software_pinned_to.rccl` did not resolve, so it was asked of the rest and not of those
asked_in_part: whether a transferred constant came from a spec pinned to this stack -- method `mixed` in 'machine.yaml' does not say whether a transfer went into it, ...; it was asked of the transfers stated

This is the same defect the guard exists to prevent, one list over. The test's own comment calls that "says so once". Every existing reader of asked_in_part treats it as one entry per condition, for example (in_part,) = checked.asked_in_part at test_spec_verbs.py:696 and :717. The module's count of reach is per condition too. At the tip this input gave one entry; the diff made it two. The verdict is not affected, because the missing required pin already refuses the document with SHAPE.

Fix, in a new commit, with a test line that is red without it: keep one entry per condition. Either guard on both lists, not any(c.startswith(TRANSFERS) for c in (*unasked, *partial)), which drops the mixed reason in this case, or fold the mixed reason into the partial entry reached already wrote. Which one is the developer's call.

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.

Agent-authored (developer, round 2). F1: fixed in db0fedba7.

The guard now checks both lists, as you suggested: not any(c.startswith(TRANSFERS) for c in unasked + partial). When reached has already filed TRANSFERS under asked_in_part, the mixed arm adds nothing, so its reason is dropped in that case.

Test. I added one assertion to the existing test, using your input: the saved document with device.software_pinned_to.rccl deleted, and the transfer beside it.

assert sum(c.startswith(TRANSFERS_ASKED) for c in partly.asked_in_part) == 1

Measured on node 18 (xiaobizh_n18_cpu), spec suite tests/compass/test_spec_*.py:

tree result where it fails
d216950a1 plus the new test (427f81912, commit-tree) 1 failed, 292 passed test_spec_verbs.py:654, assert 2 == 1
new head 7c6ded432 with the guard reverted to unasked (ac6431786, 433 lines, one line changed) 1 failed, 292 passed :654, assert 2 == 1
new head 7c6ded432 293 passed

A direct probe with tp_widths=(1, 2, 4, 8) and observed_stack=STACK gives these asked_in_part heads for this input: tip [STACK, TRANSFERS], d216950a1 [STACK, TRANSFERS, TRANSFERS], 7c6ded432 [STACK, TRANSFERS].

Comment thread atom/compass/spec/validate.py Outdated
to it is one no result can report on.
ask it. Merging the document again does not recover the pin: a merge whose
fragments disagree on a method states `mixed`, so a `Merge` holding the saved
document reports the transfer as not asked too. A `validate` verb over a

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.

Agent-authored (reviewer, cycle 1). F2, blocking. Principle 8, "Every claim carries its measurement": this new sentence is contradicted by the PR's own test.

The sentence is "so a Merge holding the saved document reports the transfer as not asked too". That holds only when no other fragment of the Merge states a transfer. When one does, the diff deliberately files the condition under asked_in_part, and the new test asserts exactly that (beside, test_spec_verbs.py:645-647).

Measured on node 18 at head d216950a1. merge([saved, transfer]) gives not_asked=[] and asked_in_part=[TRANSFERS], and is refused PINNED_STACK.

The fix is one clause, for example: "...reports the transfer as not asked too, or as asked only in part when another fragment states a transfer."

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.

Agent-authored (developer, round 2). F2: fixed in db0fedba7, then made exact in 7c6ded432.

The sentence now reads: "...so a Merge holding the saved document reports the transfer as not asked too, or as asked only in part when another fragment states a transfer and a stack pin resolved."

The "and a stack pin resolved" part came from a probe on node 18. With a transfer beside the saved document and no stack pin, the condition is reported as not_asked, not asked_in_part. Your one-clause wording would have been false in that case. The heads at 7c6ded432:

saved document alone transfer beside it
all pins not_asked=[TRANSFERS] asked_in_part=[TRANSFERS]
rccl deleted not_asked=[TRANSFERS] asked_in_part=[STACK, TRANSFERS]
no pins not_asked=[STACK, TRANSFERS] not_asked=[STACK, TRANSFERS]

Each cell in the "transfer beside it" column is asserted in the test: beside, partly and nowhere.

Comment thread atom/compass/spec/validate.py Outdated
# one, so a saved document merged again does not say whether a
# transfer went into it, and the merge kept that transfer's source pin
# out of the document. Where none of the pins resolved, `reached` has
# already reported the condition as not asked.

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.

Agent-authored (reviewer, cycle 1). F3, non-blocking. Principle 8. "Where none of the pins resolved, reached has already reported the condition as not asked" is true only when merged.transfers is non-empty. That is the only case in which reached is called.

With no transfer and no pins, reached never ran. The mixed arm is then the one that reports the condition, which is the right behaviour. The sentence reads as unconditional, and it says nothing about the partial-pin case in F1. Suggested wording: "Where a transfer is stated and none of the pins resolved, ...".

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.

Agent-authored (developer, round 2). F3: fixed in db0fedba7.

The comment now reads: "Where a transfer is stated and a pin did not resolve, reached has already reported the condition once."

That is the only case in which reached(TRANSFERS, ...) runs and reports anything. With no pins it reports not_asked, and with some pins it reports asked_in_part. The new guard defers to either. This comment also replaces the three lines the ponytail shrink: flagged, so the comment block goes from 5 lines to 2.

Comment thread tests/compass/test_spec_verbs.py Outdated


def test_a_saved_document_merged_again_does_not_claim_to_have_asked_the_transfer():
# Issue #331. The first merge is refused and writes `method: mixed`, which

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.

Agent-authored (reviewer, cycle 1). F4, non-blocking. Two problems with this comment.

  1. Principle 8, wording. "The first merge is refused" is not accurate. merge() succeeds and returns a Merge, and it is validate of that Merge that is refused PINNED_STACK. "Writes method: mixed, which drops the transfer" also runs two separate mechanisms together:

    • merge.py:285 keeps the transfer's source pin out of the document;
    • mixed drops the record that a transfer went in at all.

    Suggested wording: "Validating the first Merge is refused. Its document keeps the transfer's source pin out and says only method: mixed, so ...".

  2. AI_DEV_RULES, "No design-doc references in code ... Say what the code does." "Issue compass(spec): a saved document merged again reports the transfer condition as asked #331." is the only #NNN citation in the spec file set: atom/compass/spec/*.py, tests/compass/test_spec_schema.py and tests/compass/test_spec_verbs.py. At the tip, after compass(spec): say what the code does, not which task or design wrote it #325's clean-up ("say what the code does, not which task or design wrote it"), that file set had none. The rule's list does not name issue numbers explicitly, so this is non-blocking. Dropping the two words costs nothing.

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.

Agent-authored (developer, round 2). F4: fixed in db0fedba7.

I used your wording, and "Issue #331." is gone. The comment now reads:

Validating the first Merge is refused. Its document keeps the transfer's source pin out and says only method: mixed, so a Merge of the saved document has no transfer to ask the condition of. A re-merged all-probed document is the control.

git grep -nE "#[0-9]{3}" 7c6ded432 over atom/compass/spec/*.py, tests/compass/test_spec_schema.py and tests/compass/test_spec_verbs.py finds no match (rc 1).

@jgong5

jgong5 commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

Agent-authored (reviewer, cycle 1). Principles read first: atom/compass/design/README.md (all eight) and atom/compass/AI_DEV_RULES.md at tip 91ef04c22.

Verdict: REQUEST_CHANGES on head d216950a1d8d28e8d503a251981924f772b3f57d.

  • Blocking: F1 and F2, both inline, both a few lines to fix.
    • F1: asked_in_part lists TRANSFERS twice when some stack pins resolve. This is a change from the tip, measured.
    • F2: a new docstring sentence that the PR's own test contradicts.
  • Non-blocking: F3, F4 and the ponytail line.
  • Everything else checks out. That covers the named result, the fix shape, the outcome diff and the gate.

The inline findings are F1 at validate.py:279 (4085525396), F2 at validate.py:57 (4085525694), F3 at validate.py:277 (4085525875) and F4 at test_spec_verbs.py:627 (4085526076). Answer them with new commits, not an amend.

Everything below was run on node 18 in xiaobizh_n18_cpu. The trees were staged with git archive and docker exec -i … tar -x into /tmp/pr333r1, and the md5 matched on both ends. atom.__file__ was printed under each staged root before any result was read.

1. The named result reproduces

  • The new node id is tests/compass/test_spec_verbs.py::test_a_saved_document_merged_again_does_not_claim_to_have_asked_the_transfer.
  • Every mutant is a copy of the head tree with only validate.py changed.
  • "Spec suite" means tests/compass/test_spec_schema.py plus tests/compass/test_spec_verbs.py.
tree validate.py lines spec suite where it fails
head 435 293 passed
head with the tip's validate.py 415 (the tip's own) 1 failed, 292 passed new test, assert [] == ['whether a t...o this stack'], the row-3 assertion
head without the no-pin guard (:279 becomes if hidden:) 435 1 failed, 292 passed new test, assert ('whether a t...fers stated',) == (), i.e. nowhere.asked_in_part == ()
head with :285 if merged.transfers: changed to if False: (mine) 435 1 failed, 292 passed new test, the beside asked_in_part assertion
head keyed on "provenance.fragments" in f.values (the issue's (b); the developer's a8186d6a3) 435 1 failed, 292 passed new test, the null control: assert ('whether a t... a document',) == ()

The table's rows. Each was probed directly with tp_widths=(1, 2, 4, 8) and observed_stack=STACK.

subject tip 91ef04c22 head d216950a1
row 1, the original Merge refused PINNED_STACK, not_asked=[] same
row 2, combination.document ok, not_asked=[TRANSFERS] same
row 3, merge([Fragment.from_mapping(combination.document, "machine.yaml")]) ok, not_asked=[] ok, not_asked=[TRANSFERS]
row 3 with the transfer beside it refused PINNED_STACK, asked_in_part=[] refused PINNED_STACK, asked_in_part=[TRANSFERS]
null control, a re-merge of the all-probed merged().document ok, not_asked=[] ok, not_asked=[]

2. Ruling on the fix shape (principle 6, "Refuse rather than fall back")

Keying on method == "mixed" is sound for every document a merge writes.

  • _provenance (merge.py:248) writes either the one method the fragments share, or mixed.
  • If a transfer went in, there are two cases:
    • Every fragment shared transferred-from:X. The saved document then reads back as a transfer fragment in its own right, and merge.py:285 has dropped its pins. It is refused, not cleared.
    • The methods disagreed. The saved document is mixed.
  • mixed is absorbing: any later merge that includes a mixed fragment is mixed again.

Measured at tip and head:

attack tip head
chain: m2 = merge([saved m1, probed]) mixed, ok, not_asked=[] mixed, ok, not_asked=[TRANSFERS]
chain: m3 = merge([saved m2]) mixed, ok, not_asked=[] mixed, ok, not_asked=[TRANSFERS]
chain: m4 = merge([saved m3, probed]), and merge([saved m2, datasheet]) mixed, ok, not_asked=[] mixed, ok, not_asked=[TRANSFERS]
merge([transfer]) saved, then re-merged with probed tier0/tier1/links refused PINNED_STACK ("without saying which stack") same
the same, with the transfer's source pinned to this stack refused PINNED_STACK ("without saying which stack") same
merge([transfer, links as transferred-from:X]) saved, then re-merged with probed refused PINNED_STACK same
two mixed fragments ok, not_asked=[] ok, not_asked=[TRANSFERS], and the reason names both sources

No path a merge writes hides a transfer under another method string. The residue is a hand-edited method, and the PR body already states it.

The known cost is acceptable. Re-merging a mixed document with no transfer in it (datasheet plus probed) now gives not_asked=[TRANSFERS], where the tip gave []. This is exactly what validate(ds.document) reports at both tip and head, so a re-merge now reaches what the document reaches and no more. ok stays True. Nothing in the document can say a transfer did not go in, so "not asked" is the honest record.

Option (a) is outside the file set as claimed. Asking the condition needs the transfer's source pin. The provenance fields are authored_by, date, method, fragments and notes (fields.py:94-98). The schema is closed (test_an_unknown_key_is_refused_where_it_sits), so a structured source pin needs a new Field in fields.py. A merge.py-only variant could at most mark "a transfer went in" in the method text. That would remove the known cost, but it still could not ask the condition, so the verdict would be the same "not asked".

Out of scope, recorded here and not caused by this PR. A saved transferred-from:X document is refused with "carried constants over … without saying which stack they were measured against". That happens even when the original transfer was pinned to this stack, because it was the merge that dropped the pin, not the author who omitted it. The refusal is correct under principle 6. Its wording blames the author (principle 8). The behaviour is identical at tip and head. The coordinator may want to file it.

3. No existing refusal or not_asked text changed

pytest -rA over tests/compass/test_spec_*.py, tip against head:

  • Tip: 292 node ids, 292 passed, rc 0.
  • Head: 293 node ids, 293 passed, rc 0.
  • Outcome diff: one line, > PASSED tests/compass/test_spec_verbs.py::test_a_saved_document_merged_again_does_not_claim_to_have_asked_the_transfer.

The outcome diff cannot see text, so I measured the text directly. A pytest plugin wrapped validate and recorded every call's ok, refusals (rule, what and remedy), stack_differences, not_asked, asked_in_part and str(), per node id.

  • Tip: 87 calls, 84 of them with a non-empty not_asked.
  • Head: 93 calls, of which 6 are in the new test.
  • The other 87 are byte-identical to the tip's (cmp).
  • Nothing else in atom/compass or tests/compass calls validate.

4. Truth checks (principle 8)

sentence measured
PR body: validate.py +27/−7, code +19/−2; tests +33 true. diff --stat gives 27/7 and 33. Code is :270-288 (19 lines) against the tip's 2-line elif.
PR body: merge.py:285 keeps the source pin out true
PR body: (b) as worded turns the null control red true (mutant above)
PR body: no existing test validates a Merge holding a mixed fragment consistent with the byte-identical validate record
docstring :55-57: "a Merge holding the saved document reports the transfer as not asked too" false when a transfer is beside it. That case gives asked_in_part, which the PR's own beside assertion checks. F2
comment :273-276: mixed is what a merge writes on disagreement, and the pin is kept out true
comment :276-277: "Where none of the pins resolved, reached has already reported…" true only when a transfer is stated. F3
test comment :627: "The first merge is refused and writes method: mixed, which drops the transfer" imprecise: merge() is not refused, and mixed is not what drops the pin. F4
test comments :644 and :649 true (rows above)

F1 is inline on validate.py:279. Some pins resolved, plus a transfer beside a mixed document: tip asked_in_part=[STACK, TRANSFERS], head [STACK, TRANSFERS, TRANSFERS], control [STACK, TRANSFERS].

5. ponytail-review

atom/compass/spec/validate.py L273-275: shrink: the comment restates the docstring sentence the diff added at L55-57 (mixed = fragments disagree; the merge keeps the pin out). Keep only the guard sentence at L276-277.
tests/compass/test_spec_verbs.py: lean; four scenarios plus a control, each asserted once.
net: -3 lines possible.

6. Gate on the merged tree

  • Tip, read again: fork/feature/atomcompass_new was 91ef04c22558ba44b21806c262798aec790cccb0, unmoved.
  • Merged tree: git merge-tree --write-tree 91ef04c22 d216950a1 gives 6aa5fa86ad4100087a1bce8e0eeb67d1294dee39, which equals d216950a1^{tree}.
  • Stamp: git commit-tree produced 9258b14aa28d5e8c61ee6702bd70d95b618ca03e, with parents the tip and the head. Its tree is 6aa5fa86a. .compass-changed holds the two PR files.
  • Gate scripts: the tree's own scripts/compass/gate_cpu.sh. scripts/compass is ba78568c8 at both tip and merged.
  • Printed stamps: the gate printed commit: 9258b14aa (stamp) and atom: /tmp/pr333r1/stage/merged/ATOM/atom/__init__.py.
  • Run: one gate, bounded by timeout -k 10 2400, unpiped, with the load average at 16.
tree passed skipped xfailed junit cases GATE_CPU_RC
merged 9258b14aa (tree 6aa5fa86a) 5238 155 3 5396 0

This matches the developer's head numbers: 5238/155/3 and 5396 cases, against a tip of 5237 and 5395. The new node id is present in the junit. No timing-class test failed, so none needed a re-run.

What the next task in this area should watch

  • The re-read transfer refusal wording in section 2.
  • A future compass spec validate machine.yaml verb will hit exactly this mixed path. Its test should assert not_asked, not only ok.

🤖 Generated with Claude Code

jgong5 and others added 2 commits September 23, 2026 17:51
When some stack pins resolve, `reached` has already filed `TRANSFERS` under
`asked_in_part`. The `mixed` arm checked only `unasked`, so it added a second
`TRANSFERS` entry to `asked_in_part`. The guard now checks both lists, and the
test asserts one entry for a saved document with one stack pin deleted and a
transfer beside it.

The module docstring now also covers the case where another fragment states a
transfer: the condition is then asked only in part. The comment above the guard
no longer repeats the docstring, and it says `reached` has reported the
condition only when a transfer is stated. The test comment says it is
`validate` of the first `Merge` that is refused, not the merge itself, and it
no longer cites the issue number.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n part

With another fragment stating a transfer, a `Merge` holding the saved `mixed`
document reports the transfer condition as asked in part only when a stack pin
resolved. With no stack pin, it reports the condition as not asked at all. The
`nowhere` assertion in the test already checks that case.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@jgong5

jgong5 commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

Agent-authored (developer, round 2). Principles read first: atom/compass/design/README.md (all eight) and atom/compass/AI_DEV_RULES.md at tip b63f1a711.

Developer round 2: new head 7c6ded432c5e11f544e6a4529c2e7a64cd6dee9f. Delta for review: d216950a1..7c6ded432, two new commits, no amend, no force-push.

  • db0fedba7 fixes F1, F2, F3, F4 and the ponytail shrink:.
  • 7c6ded432 makes F2's new docstring clause exact. The reviewer's suggested wording was false with no stack pin, measured below.
  • No blocking issues remain, as far as I know. Each finding has an inline reply.

Findings

finding fix how I checked it
F1, blocking The guard reads unasked + partial, so TRANSFERS is listed once. A new assertion, sum(c.startswith(TRANSFERS_ASKED) for c in partly.asked_in_part) == 1, on the saved document with rccl deleted and the transfer beside it. It is red at d216950a1 and green at 7c6ded432 (table below).
F2, blocking The docstring adds: "or as asked only in part when another fragment states a transfer and a stack pin resolved". A probe over all pins, rccl deleted and no pins, each alone and with a transfer beside it (inline reply). With no pins and a transfer beside it, the result is not_asked, which is why the clause says "and a stack pin resolved".
F3 The comment reads: "Where a transfer is stated and a pin did not resolve, reached has already reported the condition once." reached(TRANSFERS, …) runs only under if merged.transfers:.
F4 Your wording, and "Issue #331." is dropped. git grep -nE "#[0-9]{3}" 7c6ded432 over the spec file set gives rc 1.
ponytail shrink: The comment block is 2 lines, down from 5. Production is +10/−12 this round (below).

Named result (node 18, xiaobizh_n18_cpu)

  • Each tree was staged with git archive and docker exec -i … tar -x into /tmp/i331r2/<name>/ATOM inside the container. The md5 matched on both ends.
  • atom.__file__ was printed under each staged root before any result was read.
  • "Spec suite" means tests/compass/test_spec_*.py. Every failure is in the same node id, tests/compass/test_spec_verbs.py::test_a_saved_document_merged_again_does_not_claim_to_have_asked_the_transfer.
  • Each mutant is 7c6ded432 with only validate.py changed (433 lines, or 415 for the tip's own), built with commit-tree.
tree commit spec suite fails at
d216950a1 plus the new test file 427f81912 1 failed, 292 passed :654, the F1 assertion: assert 2 == 1
new head 7c6ded432 293 passed
new head, F1 guard reverted to unasked ac6431786 1 failed, 292 passed :654, assert 2 == 1
new head with the tip's validate.py 4960c4b1a 1 failed, 292 passed :643, assert [] == ['whether a t...o this stack'] (the row-3 again.not_asked)
new head without the no-pin guard (if hidden:) ff65207d0 1 failed, 292 passed :654, assert 2 == 1. This now fails on the new F1 line, which runs before nowhere. At d216950a1 it failed on nowhere.asked_in_part == ().
new head with the partial arm sent to unasked (the mixed arm's if merged.transfers: becomes if False:) d637df726 1 failed, 292 passed :648, the beside asked_in_part assertion: assert [] == [...]
new head keyed on "provenance.fragments" in f.values 5450ad5da 1 failed, 292 passed :663, the null control: assert ('whether a t... a document',) == ()

Every cycle-1 mutant keeps its verdict.

Spec-suite outcome diff, -rA. The tip b63f1a711 has 292 node ids, all passed. The merged tree has 293, all passed. The diff is one line:

> PASSED tests/compass/test_spec_verbs.py::test_a_saved_document_merged_again_does_not_claim_to_have_asked_the_transfer

F1 added an assertion, not a new node id.

Gate on the merged tree

tree passed skipped xfailed junit cases GATE_CPU_RC
tip b63f1a711 (control) 5238 155 3 5396 0
merged 4789afd51 (tree 170da7165) 5239 155 3 5397 0

Node-id delta from junit: one line, + tests.compass.test_spec_verbs::test_a_saved_document_merged_again_does_not_claim_to_have_asked_the_transfer passed. Every timing-class test passed on the merged tree, so none needed a re-run: TestTheRegionIsNotCopiedPerChunk (4), TestNoSizeAtWhichACallStopsBeingOne::…[minimax] (2) and test_freezing_twice_is_additive_and_harmless.

Lines this round (d216950a1..7c6ded432)

added removed
production (validate.py) 10 (7 docstring, 2 comment, 1 code) 12 (6 docstring, 5 comment, 1 code)
tests (test_spec_verbs.py) 10 (4 comment for F4, 6 for the F1 assertion) 3 (F4 comment)

That is 20 added and 15 removed. The brief estimated 10–20, so this is under 2x.

🤖 Generated with Claude Code

@jgong5

jgong5 commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

Agent-authored (reviewer, cycle 2). Principles read first: atom/compass/design/README.md (all eight) and atom/compass/AI_DEV_RULES.md at tip b63f1a711.

Verdict: APPROVE on head 7c6ded432c5e11f544e6a4529c2e7a64cd6dee9f.

  • No blocking issues. F1 and F2 are fixed, and each fix is held by a test line I saw go red.
  • Non-blocking: none that needs a commit. One reservation is recorded in section 3.
  • Scope: the delta d216950a1..7c6ded432 only. That is 2 commits: validate.py +10/−12 (code +1/−1) and test_spec_verbs.py +10/−3, measured with git diff --numstat.

Everything below ran on node 18 in xiaobizh_n18_cpu.

  • Staging: the trees were staged with git archive and docker exec -i … tar -x into /tmp/pr333r2. The tarball md5 7b6f19b05f18cd4119ab222781ff2c52 matched on both ends.
  • Root check: atom.__file__ was printed under each staged root before any result was read.
  • Spec suite: this means tests/compass/test_spec_schema.py plus tests/compass/test_spec_verbs.py.
  • Failing node id: every red below is in tests/compass/test_spec_verbs.py::test_a_saved_document_merged_again_does_not_claim_to_have_asked_the_transfer.

1. Reproduction (principle 8, "Every claim carries its measurement")

Each mutant is a copy of the head tree with one line of validate.py changed, by an anchored sed. M1 is the exception: it swaps in the tip's whole file. The test file is the head's in every row, md5 836e0be206ee.

tree validate.py lines spec suite fails at
head 7c6ded432 433 293 passed, rc 0
d216950a1 plus the head's test file 435 1 failed, 292 passed :654, assert 2 == 1 (the F1 line)
head, guard back to for c in unasked): 433 1 failed, 292 passed :654, assert 2 == 1
M1: head with the tip's validate.py (the tip's blob 3791a6050 is the same as at 91ef04c22) 415 1 failed, 292 passed :643, assert [] == ['whether a t...o this stack']
M2: head without the pin guard (if hidden:) 433 1 failed, 292 passed :654, assert 2 == 1
M3: head with :283 if merged.transfers: changed to if False: 433 1 failed, 292 passed :648, beside.asked_in_part, assert [] == [...]
M4: head keyed on "provenance.fragments" in f.values 433 1 failed, 292 passed :663, the null control, assert ('whether a t... a document',) == ()

All four cycle-1 mutants are still red. The lines match the developer's table. M2 now fails first at the F1 line (:654), which runs before nowhere (:661), as the developer said.

2. The 3×2 pin-state probe, and the docstring clause

Every call used tp_widths=(1, 2, 4, 8) and observed_stack=STACK. Each cell below is ok, the refusals, the not_asked heads and the asked_in_part heads. I added a third column for a transfer pinned to this stack.

saved mixed document alone transfer rocm 7.0.2 beside it transfer pinned to this stack beside it
all pins ok, not_asked=[TRANSFERS] PINNED_STACK, asked_in_part=[TRANSFERS] (the mixed reason) ok, asked_in_part=[TRANSFERS] (the mixed reason)
rccl deleted SHAPE, not_asked=[TRANSFERS], asked_in_part=[STACK] SHAPE, PINNED_STACK, asked_in_part=[STACK, TRANSFERS] (the rccl reason) SHAPE, asked_in_part=[STACK, TRANSFERS] (the rccl reason)
no pins SHAPE×3, not_asked=[STACK, TRANSFERS] SHAPE×3, not_asked=[STACK, TRANSFERS] (the pin reason) same as the previous cell

The first two columns match the developer's inline reply cell for cell. At d216950a1, the two rccl deleted cells with a transfer gave [STACK, TRANSFERS, TRANSFERS]. At the tip, every "alone" cell omitted TRANSFERS.

The docstring clause is true in both directions. The clause is: "a Merge holding the saved document reports the transfer as not asked too, or as asked only in part when another fragment states a transfer and a stack pin resolved". I checked it as a predicate over a sweep:

  • Pins: all 8 subsets of {rocm, aiter, rccl} deleted.
  • Beside the saved document: no transfer, a 7.0.2 transfer, a this-stack transfer, or a transfer with no pin block.
  • Saved document: mixed, an all-probed control, or two mixed copies.

That is 96 cases. The expected placement follows from the fields alone:

  • A transfer is stated and no pin resolved: not_asked.
  • A transfer is stated and some pins resolved: asked_in_part.
  • A transfer is stated, all pins resolved, and a mixed fragment is present: asked_in_part.
  • No transfer is stated and a mixed fragment is present: not_asked.
  • Anything else: absent.

On top of that, no condition head may appear twice across the two lists.

tree violations / 96 what they are
tip b63f1a711 22 every mixed case that has all pins or no transfer: TRANSFERS is missing (the issue)
d216950a1 36 every partial-pin case with a transfer beside a mixed document: TRANSFERS is listed twice (F1)
head 7c6ded432 0

That includes 0 mismatches of the docstring predicate over the 32 single-mixed cases.

3. The one-line change cannot drop a condition

unasked + partial holds a TRANSFERS entry before the mixed arm only when reached(TRANSFERS, STACK_PINS) wrote one (validate.py:272-273). That happens only under merged.transfers. The merged is None arm is the other branch of the same if. No other condition string starts with TRANSFERS (:130-135). So the guard can only skip a second entry. _unreached returns at most one entry, so the condition is still listed exactly once.

I tried to make it drop one. Every case where TRANSFERS belongs in asked_in_part for a reason other than the mixed guard lists it once at the head:

  • partial pins with any of the three transfer kinds, beside an all-probed document;
  • the same beside one mixed document;
  • the same beside two mixed documents.

This is the sweep above, 0 violations. The all-probed rows pass the same check at the tip and at d216950a1 too.

Accepted with reservation (non-blocking, no action; principle 8, "Every claim carries its measurement"). When pins partly resolve and a transfer is stated beside a mixed document, the one surviving entry is reached's: "device.software_pinned_to.rccl did not resolve, so it was asked of the rest and not of those". The mixed reason is dropped. That is the trade the cycle-1 finding offered, and the developer chose it. The sentence is true, and the category (asked_in_part) is right. A reader just learns one reason for "in part", not both. If a future verb prints these entries to a user, folding the two reasons into one entry is the place to revisit.

4. Truth checks on every reworded sentence (principle 8)

sentence measured
docstring :55-58, "…or as asked only in part when another fragment states a transfer and a stack pin resolved" true, section 2: 32/32 single-mixed cases
comment :274-275, "Where a transfer is stated and a pin did not resolve, reached has already reported the condition once" true. reached(TRANSFERS, …) runs only under merged.transfers (:272), and _unreached returns exactly one entry whenever a read path is absent (:219-231).
test comment :627-630, "Validating the first Merge is refused. Its document keeps the transfer's source pin out and says only method: mixed, so a Merge of the saved document has no transfer to ask the condition of." true. first is refused PINNED_STACK (asserted at :637). The saved document's software_pinned_to is {rocm: 7.2.4, …} and 7.0.2 appears nowhere in it. Its method is 'mixed'. merge([saved]) states no transfer: with no pins, its TRANSFERS entry is the mixed reason and not the pin reason, so reached did not run.
test comment :649, "With some stack pins resolved it was asked in part, and says so once." true (the rccl deleted cell)
PR body, round 2: "reached has already listed TRANSFERS once. That is under not_asked when no pin resolved, and under asked_in_part when some did. The mixed arm adds nothing." true (sweep)
PR body and round-2 comment, "round 2 +20/−15; production +10/−12, tests +10/−3" true (--numstat)
PR body: the mutant table's line numbers :643, :648, :654 and :663 true, section 1
round-2 inline reply to F2: "Each cell in the 'transfer beside it' column is asserted in the test: beside, partly and nowhere" true for the TRANSFERS placement, which is what the clause is about. partly asserts one TRANSFERS in asked_in_part, not the whole [STACK, TRANSFERS]. nowhere asserts one TRANSFERS in not_asked and an empty asked_in_part, not STACK. This is a thread comment and does not land, so no action.

No design-doc or issue references. git grep -nE "#[0-9]{2,}|\bD[0-9]+\b|principle [0-9]|Gate [0-9]|…" over the PR's two files at 7c6ded432 gives rc 1, so the file set is clean.

Ruff. ruff check and ruff format --check on both files give rc 0 at both the tip and the head (ruff 0.16.7).

5. ponytail-review over d216950a1..7c6ded432

atom/compass/spec/validate.py: lean; the delta is one operand (+ partial), a 2-line comment that replaced 5, and one docstring clause F2 required.
tests/compass/test_spec_verbs.py L649-654: lean; one scenario, one assertion, reusing the fixtures already in the test.
Lean already. Ship.

6. Gate on the merged tree (AI_DEV_RULES, "compute the tree that will land")

  • Tip, read again: after a fetch, fork/feature/atomcompass_new is b63f1a711469007dfba903bfba90c50236bf1dd2, unmoved since round 2.
  • Merged tree: git merge-tree --write-tree b63f1a711 7c6ded432 gives 170da7165c126432587547267584986209e98b5a, with no conflict. This is the developer's hash. It is not 7c6ded432^{tree} (6cb437ccb), because it also carries compass(tests): refuse any reply-scan root set but REPLY_SURFACE, and read relative engine imports #326's test file. git diff --stat b63f1a711 <stamp> is the PR's two files, +65/−7.
  • Stamp: git commit-tree gave 9924f2433f6a806a19c4d955974fb24e30aac0b9, with parents the tip and the head, and tree 170da7165. .compass-changed holds the two PR files.
  • Gate script: the tree's own scripts/compass/gate_cpu.sh. scripts/compass is ba78568c8 at both the tip and the merged tree.
  • Printed stamps: the gate printed commit: 9924f2433 (stamp) and atom: /tmp/pr333r2/stage/merged/ATOM/atom/__init__.py. My wrapper had already asserted that atom.__file__ resolves under that root.
  • Run: one gate, bounded by timeout -k 10 2400, unpiped, with load average 10–17.
tree passed skipped xfailed junit tests GATE_CPU_RC
merged 9924f2433 (tree 170da7165) 5239 155 3 5397 (0 failures, 0 errors) 0
  • Against the developer's numbers: this matches their merged run (5239/155/3, 5397 cases, rc 0). Their tip control was 5238, so the difference is +1, the new node id, which is present in my junit.
  • Timing classes: every one passed, so none needed a re-run: TestTheRegionIsNotCopiedPerChunk (4 cases), TestNoSizeAtWhichACallStopsBeingOne (12 cases, both [minimax] cases included) and tests/test_gc_utils.py::test_freezing_twice_is_additive_and_harmless.

What the next task in this area should watch

  • Section 3's reservation: the surviving asked_in_part entry names the pin reason and not the mixed one.
  • Cycle 1's two notes still stand:
    • the wording of the refusal on a re-read transfer;
    • a future compass spec validate machine.yaml verb should assert not_asked, not only ok.

🤖 Generated with Claude Code

@jgong5
jgong5 marked this pull request as ready for review September 23, 2026 18:17
@jgong5
jgong5 merged commit feb1b27 into feature/atomcompass_new Sep 23, 2026
jgong5 added a commit that referenced this pull request Sep 29, 2026
…held by tests (#493)

Adds two behaviour tests to tests/compass/test_spec_schema.py.

One asserts that spec/machine.py::_walk raises the first refusal it meets:
any later refusal fails it. The other asks MachineSpec.runtime_constant for a
width table a fragment lacks, reaching the second read site, and asserts
SpecRefusal with Rule.TOTALITY instead of a bare KeyError.

The reached(STACK, ...) and reached(TRANSFERS, ...) calls in spec/validate.py
needed nothing: tests from #183 and #333 already go red when either is deleted.

Each reinstated defect goes red on its named test (1 failed / 297 passed against
298). CPU gate on node 18 over the combined tree with c0f6419: 5209 passed,
rc 0.

Closes #243
Closes #249

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