Skip to content

compass(design): the stack pin warns by default, refuses under strict=True or on a transfer or merge - #278

Merged
jgong5 merged 1 commit into
feature/atomcompass_newfrom
compass/issue-277-stack-pin-wording
Sep 23, 2026
Merged

jgong5 merged 1 commit into
feature/atomcompass_newfrom
compass/issue-277-stack-pin-wording

Conversation

@jgong5

@jgong5 jgong5 commented Sep 23, 2026

Copy link
Copy Markdown
Owner

Closes #277

Ruling source: #275 (comment), item 4.

Named result: every changed sentence, before and after

Every sentence in atom/compass/design/*.md about the stack pin's default now says: warns by default, refuses under validate(strict=True), and refuses on a transfer or merge across stacks. Three sentences changed, 10 insertions and 6 deletions across three files.

Doc 03, runtime-constants assumption (03_memory_and_kv_model.md, was line 358)

  • Before: "made enforceable by software_pinned_to (doc 05 D25 rule 3), which refuses silently reusing a spec across a stack change."
  • After: "made enforceable by software_pinned_to (doc 05 D25 rule 3): reusing a spec across a stack change warns by default (check_stack) and refuses under validate(strict=True), and moving constants across stacks, by a transfer or a merge, always refuses."

Doc 05, D25 rule 3 (05_machine_spec_and_probes.md, line 177)

  • Before: "A stack mismatch warns loudly."
  • After: "A stack mismatch warns loudly by default and refuses under validate(strict=True); constants moved across stacks, by a transfer or a merge, always refuse."

Doc 07 (07_calibration_toolchain.md, line 688)

  • Before: "...which is why doc 05's schema carries software_pinned_to and why a mismatch warns loudly."
  • After: "...which is why doc 05's schema carries software_pinned_to and why a mismatch warns loudly by default, refusing under validate(strict=True) or when a transfer or merge moves constants across stacks."

Backing code at ba51cd440

Claim Function File:line
Warns by default MachineSpec.check_stack: collects each differing component and calls warnings.warn(..., StackMismatch). It returns the differences and raises nothing. atom/compass/spec/machine.py:302-339; StackMismatch(UserWarning) at atom/compass/spec/rules.py:95
Refuses under strict=True validate(..., strict=False): the default is False. check_stack runs only when observed_stack is given. On differences with strict it appends SpecRefusal(Rule.PINNED_STACK, ...). atom/compass/spec/validate.py:369-409; Rule.PINNED_STACK at atom/compass/spec/rules.py:60
Transfer refuses unconditionally validate._transfers: for each transfer fragment, it refuses with Rule.PINNED_STACK when the fragment declares no stack, or when a declared component differs from the resolved pin. validate calls it for any Merge subject, whatever strict is. atom/compass/spec/validate.py:334-366, call at :410-411
Merge refuses unconditionally merge._conflict: two non-transfer fragments disagreeing on a device.software_pinned_to.* field raise SpecRefusal(Rule.PINNED_STACK, ...). Transfer fragments' pins are skipped at merge (merge.py:285), so a transfer mismatch is caught by _transfers, not here. atom/compass/spec/merge.py:194-213, reached via claim at :271-274

The module docstrings agree: validate.py:104-107 says it "warns and names both versions, and refuses only when the caller asks for that", and machine.py:45 says the same.

Checked and left unchanged

  • 05_machine_spec_and_probes.md:308-309 (validate refuses on): "(warn, or refuse under a strict flag)" and "a transfer fragment whose source spec pinned a different stack". Both are already exact.
  • 05_machine_spec_and_probes.md:215 and doc 03's "made enforceable" say that the transfer assumption is enforced. That is true, because a transfer across stacks refuses.
  • 05_machine_spec_and_probes.md:281: a transfer carries both pins "so a later mismatch is visible". This understates _transfers, which refuses rather than only showing the mismatch. It describes what the probe stamps, not the default behaviour, so it is out of this issue's file-set wording. Flagged for the reviewer.
  • README.md:284: "Artifacts are keyed, digested and fingerprinted; a stack or source change refuses". This is about artifact keys and digests in general, not the software_pinned_to check, so it is outside this issue's scope. Flagged for the reviewer in case they read it as covering the machine spec.

Gate 1: ATOM's suite, unmodified, as a delta (node 18, xiaobizh_n18_cpu)

Both trees were staged with git archive + docker exec -i tar -x under /tmp/i277gates/{control,branch}/ATOM, with .compass-commit/.compass-changed stamps. The file-content digests matched on both ends. Each run used the tree's own scripts/compass/gate_cpu.sh under timeout -k 10 3000, with PYTHONPATH set to its root. The staging has been removed.

Side Commit atom.__file__ Result GATE_CPU_RC
control ba51cd440 /tmp/i277gates/control/ATOM/atom/__init__.py 5122 passed, 149 skipped, 3 xfailed 0
branch 2540d9a0a /tmp/i277gates/branch/ATOM/atom/__init__.py 5122 passed, 149 skipped, 3 xfailed 0

Delta: 0. There were no flakes, so nothing was re-run.

git merge-tree --write-tree ba51cd440 2540d9a0a gives f59cee848561e637696a4b2109ff719e41575560, with no conflicts.

Dev record

  • The docs are prose only. No code changed, and no doc references were added to code.
  • Transfer fragments' pins are excluded from the merge-conflict check. So "by a transfer or a merge" names two separate refusal sites, not one. The doc text says "a transfer or a merge" and leaves the mechanism to doc 05.

🤖 Generated with Claude Code

…s under strict, transfer or merge

Doc 03 said software_pinned_to "refuses silently reusing a spec across a
stack change". The code warns by default (check_stack, StackMismatch),
refuses under validate(strict=True) with Rule.PINNED_STACK, and refuses
unconditionally when constants move across stacks, by a transfer
(validate._transfers) or a merge (merge._conflict). Doc 03, doc 05 rule 3
and doc 07 now say all three.

Closes #277

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
one startup on a second card type.
`software_pinned_to` (doc `05` D25 rule 3): reusing a spec across a stack change warns by
default (`check_stack`) and refuses under `validate(strict=True)`, and moving constants
across stacks, by a transfer or a merge, always refuses. Still untested across dies;

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 review comment (Claude), reviewer for #277.

Non-blocking, principle 8 (every claim carries its measurement): "always refuses" is true about strict but not about every way a transfer gets validated.

I ran it on node 18 against the merged tree 17d6577da (tip e9d31f4bc + this head). The setup is the test_spec_verbs fixtures, with a transfer fragment pinned to rocm 7.0.2 merged into a spec pinned to 7.2.4:

  • validate(<the Merge>) returns ok=False with PINNED_STACK for all four combinations of strict in {False, True} and observed_stack in {None, matching}. So the refusal does not depend on strict, which is the contrast this sentence draws.
  • validate(<that Merge>.document, strict=True, observed_stack=<matching>) returns ok=True with 0 refusals. The "whether a transferred constant came from a spec pinned to this stack" check is listed in not_asked. That is by design: merge keeps the source pin out of the document (merge.py, the transferred_from skip in merge()), and test_the_transfer_condition_names_itself_as_unaskable_of_a_document pins it.

So a reader of doc 03 alone would expect a saved cross-stack spec to be refused wherever it is checked, and it is not. This is milder than the wording #277 fixes, because the document path names the question as unasked instead of clearing silently. Suggested wording: "...moving constants across stacks, by a transfer or a merge, refuses whatever strict says". Doc 05 can carry the Merge-versus-document detail. The same "always" appears at 05_machine_spec_and_probes.md:179. 07:689-690 avoids the word and is fine as written.

context plus libraries. A stack mismatch warns loudly.
context plus libraries. A stack mismatch warns loudly by default and refuses under
`validate(strict=True)`; constants moved across stacks, by a transfer or a merge,
always refuse.

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 review comment (Claude).

Non-blocking, principle 8. This is the same "always" as the comment on 03_memory_and_kv_model.md:360. The transfer refusal comes from validate._transfers and is reached only when the Merge itself is validated. On the saved document, validate returns ok=True and lists the transfer check under not_asked (measured on node 18). "Regardless of strict" is exact. "Always" is not quite exact.

@jgong5

jgong5 commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

Agent-authored review (Claude), first review of #278 for #277. I read the eight design principles and AI_DEV_RULES.md first.

Verdict: APPROVE, head 2540d9a0a0f895bc3b1af57a163dead7df9716f4. There are no blocking issues. Two inline notes are non-blocking: the word "always" at 03:360 and 05:179. Folding them in is optional.

1. Every new claim, run on the merged tree (principle 8)

I ran each claim on node 18 (xiaobizh_n18_cpu), on merged tree 17d6577da (= git merge-tree --write-tree e9d31f4bc 2540d9a0a). atom.__file__ resolved to /tmp/r278gates/merged/ATOM/atom/__init__.py. The fixtures are tests/compass/test_spec_verbs.py's. The pin is rocm 7.2.4.

Claim in the diff Code Observed
warns by default (check_stack) MachineSpec.check_stack, spec/machine.py observed 7.3.0: returned (('rocm','7.2.4','7.3.0'),), raised nothing, one StackMismatch warning naming both versions
refuses under validate(strict=True) validate, spec/validate.py strict=False: ok=True, 0 refusals, warned. strict=True: ok=False, [PINNED_STACK], warned
transfer across stacks refuses validate._transfers transfer pinned to 7.0.2 into a 7.2.4 spec: validate(Merge) gives ok=False [PINNED_STACK] for all four of strict in {F,T} x observed_stack in {None, matching}. A transfer with no pin: ok=False [PINNED_STACK]
merge across stacks refuses merge._conflict two non-transfer fragments pinned to 7.2.4 / 7.3.0: merge() raised SpecRefusal, rule PINNED_STACK

All three edited sentences match the code. On the same tree, validate(<that Merge>.document, strict=True, observed_stack=<matching>) is ok=True, and the transfer check appears under not_asked. That is the basis of the inline note on "always": the refusal does not depend on strict, but it is only reached when the Merge is validated. This is non-blocking, because the document path names the question as unasked and does not report it clear.

2. Completeness: the two lines left on purpose

I grepped atom/compass/design/*.md at the merged tree for software_pinned|stack pin|stack mismatch|stack change|check_stack|PINNED_STACK|across stack|pinned to|stack or source. Two lines were left unchanged on purpose. My ruling on each:

  • 05:283 (the table row for transfer --from <spec>, "...so a later mismatch is visible"): accurate but understated, and non-blocking. Not required in this PR. Measured above, a mismatched transfer is refused by validate whatever strict says, which is more than "visible". A transfer that carries no pin is refused too. The row describes the output of a probe that does not exist yet (no transferred-from emitter outside spec/ at the tip). It is not a sentence about the pin's default, which is the file set compass(design): doc 03 says the stack pin refuses by default; it warns #277 names. It is also the opposite error from compass(design): doc 03 says the stack pin refuses by default; it warns #277's: compass(design): doc 03 says the stack pin refuses by default; it warns #277's wording overstated the refusal, and this row understates it. A one-word change to "...so a later mismatch is refused" would make the row exact, if the developer wants to fold it in. This line is outside the diff hunks, so it has no inline comment.
  • README.md:284 ("Artifacts are keyed, digested and fingerprinted; a stack or source change refuses"): accurate, no fix. It describes the artifact-store fingerprint layer, not software_pinned_to. artifacts/fingerprints.py refuses by default (OnMismatch.REFUSE) and warns only under the explicit OnMismatch.WARN. artifacts/matrix.py gives machine_spec's runtime-constants row the SOFTWARE_STACK axis. So "refuses" is the right default for that mechanism. Two mechanisms touch a spec with opposite defaults: the store refuses on a stale fingerprint, and check_stack warns on the running stack. That is a fact of the code, not an error in either sentence.

05:310-311 ("warn, or refuse under a strict flag"; "a transfer fragment whose source spec pinned a different stack") and 05:215-218 ("enforced by software_pinned_to") are also exact. The developer's reading of them is right.

3. Scope

git diff --name-only e9d31f4bc 17d6577da lists only the three .md files. No code changed, and no doc reference was added to code.

4. Gate: the tree that will land

The tip is e9d31f4bc (#275 landed after the developer's control ba51cd440). git merge-tree --write-tree e9d31f4bc 2540d9a0a gives 17d6577dafbfe1e02dbe76e2af3357fcc198d964, with no conflicts.

The tree was staged with git archive and docker exec -i ... tar -x to /tmp/r278gates/merged/ATOM, a path of my own, not the shared mount. The .compass-commit and .compass-changed stamps were written, and the tar md5 e5e4b176... matched on both ends. I ran the tree's own scripts/compass/gate_cpu.sh under timeout -k 10 3000. The gate printed commit: 17d6577da (stamp) and gpu: not required.

Tree Result GATE_CPU_RC
merged 17d6577da 5123 passed, 149 skipped, 3 xfailed 0

This equals the tip's expected 5123 (the developer's 5122 on ba51cd440, plus the one test #275 added), so the delta is 0. No flakes occurred, so nothing was re-run. The staging is removed.

Next for this area

If the transfer probe in 05's Tier 4 table is ever built, its row and doc 03's sentence should say that the transfer refusal is reached by validating the merge, not the saved document.

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