Skip to content

compass(tests): AST guards refuse the spellings they cannot read - #266

Merged
jgong5 merged 7 commits into
feature/atomcompass_newfrom
compass/issue-223-ast-guards
Sep 29, 2026
Merged

jgong5 merged 7 commits into
feature/atomcompass_newfrom
compass/issue-223-ast-guards

Conversation

@jgong5

@jgong5 jgong5 commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

Closes #223

What this does

Several AST guards in tests/compass/ check one spelling of what they claim. They skip every other spelling, so a violation written a different way passes the whole suite. This PR makes each reachable guard refuse a shape it cannot read, and name the file, line and source text. It does not add one more spelling to an enumeration.

The inventory came first, as the brief asks. It was posted before any code moved:

The row numbers below (B1, B2, and so on) are the inventory's.

Re-scoped under #489 (prose is not a test subject). This PR keeps B1-B3, B5, B6, B10, B12, B17, B20 and B22-B24, and the code-structure parts of B16 (the exit body statements, the early-exit check and the literal KV tuple). These guards inspect code. It drops B16's comment assertions. B17 (the unanswered_rpc_names caller refusal) is kept: it reads syntax-tree nodes and no prose. The __doc__ assertions next to it were deleted by #492 and are not part of this PR. After #492 (c0f641949), test_kv_blob_doc_table.py is gone and its one-site check lives in test_kv_blob_site.py, which now carries B20. The sections below from before the re-scope are kept as the record. Their B16 comment rows no longer describe the branch, and their B17 rows use the test's name from before #492 renamed it. Current evidence is in the latest Developer round comment.

Scope: tests only, 0 production lines. Diff against c0f641949:

file + −
tests/compass/test_runner_rpc_surface.py 122 29
tests/compass/test_runner_non_allocating.py 72 16
tests/compass/test_runner_step_semantics.py 39 8
tests/compass/test_kv_blob_site.py 35 3
tests/compass/test_clock_lp_identity.py 11 6
tests/compass/test_ir_data_model.py 5 0
total 284 62

The estimate was ~160 test lines. After review round 1 the actual was 284 added / 67 removed. After the re-scope, with B17 kept, it is 284 added / 62 removed, inside the 2x halt line (320).

The gaps closed, and how each guard now refuses

row guard now reads now refuses (named)
B1 (instance 4) _self_assigned (test_runner_non_allocating.py) self.x as a target of =, including inside a tuple, list or starred target; annotated and augmented =; setattr(self, "x", …) with a literal name a computed setattr, a for/with target, and any __dict__/vars(self) write, unless the caller lists them by source text. ModelRunner lists its three setattr(self, name, value) loops, which bind what the attention builders return (KV cache and per-request state).
B2 _methods (one copy now, in test_runner_rpc_surface.py; test_runner_non_allocating.py imports it, the way test_runner_step_semantics.py already imports SITES) def, async def, nested class, and class-body = / annotated = / augmented = any other class-body statement (if, try, loop)
B3 test_only_the_binding_module_reaches_the_engine a relative import, resolved against the module's package — (the resolved name meets the existing rule)
B6 _arity as before a list, starred, annotated or chained target now scores None, not 1. The new test_every_reply_is_taken_in_a_shape_the_arity_reads names its site.
B5, filter half _call_sites as before a broadcast with no positional name now joins the non-literal tripwire instead of being dropped
B10 test_get_num_blocks_refuses_and_the_keys_its_caller_reads_are_named as before a block_info[...] subscript that is not a literal
B12 _reply_attribute_reads (test_runner_step_semantics.py) fwd_out.x / fwd_output.x; a whole hand-off (positional argument to a method, return, is None) any other use of the reply: getattr, an alias, or a plain function call
B16 (instance 5, and the named result) test_what_a_hole_at_exit_loses_is_what_exit_does (renamed by #492; its comment assertions are gone) only calls that are statements of exit's own body a non-literal element of the KV-name tuple (the one-line close from #208's review)
B17 (kept: it reads syntax-tree nodes and no prose) test_the_unanswered_helper_returns_one_list_its_one_caller_partitions (renamed by #492; its __doc__ assertions are gone) a call by bare name or through a module any other mention of the helper
B20 test_each_backend_builds_the_blob_at_exactly_one_site (via new _writes_not_read) as before every write of kv_transfer_params_output that is not a plain =, and the name as a string anywhere in the connector
B22, B24 clock and ir import allowlists a relative import that stays inside the package a relative import that climbs out, named as written
B23 test_the_package_builds_no_set_at_all — any mention of set/frozenset, called or not

Gate 3: the named result, by node id (round 0, at 82171397a; round 1 is re-measured in its own section below)

Every mutation is line-count-preserving (checked by the harness before each run), applied to a git archive of the tree, and restored after it. The whole tests/compass suite was run each time, and failures were read by node id from junit XML.

Test names below are abbreviated. The full node ids are tests/compass/<file>::<test>.

Named result (the brief's own):

mutation tip f5003b255 head
setattr(self, "kv_cache", None) in NonAllocatingRunner.allocate_kv_cache 1048 passed 1 failed: test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor
control: self.kv_cache = None 1 failed, same test 1 failed, same test
destroy_dist_env() → pass # destroy_dist_env() 1 failed, test_runner_rpc_surface.py::test_what_the_comment_says_a_hole_at_exit_loses_is_what_exit_does. #208 closed this spelling before this PR. 1 failed, same test
destroy_dist_env() → (lambda: destroy_dist_env()) 1048 passed 1 failed, same test

Every other reachable gap:

row mutation tip head, failing node id(s)
B1 self.kv_cache: object = None green test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor
B1 self.config.num_kvcache_blocks, self.kv_cache = n, None green same
B2 async def exit(self): return True added to NonAllocatingRunner green test_runner_non_allocating.py::test_the_replaced_methods_are_the_ones_that_own_memory_or_run_a_step
B2 exit = staticmethod(lambda *a: True) in the class body green same
B3 try: from ...model_engine import model_runner / except Exception: pass at module scope in overrides.py green test_runner_non_allocating.py::test_only_the_binding_module_reaches_the_engine[overrides.py]
B6 [fwd_out] = self.runner_mgr.call_func("forward", …) in engine_core.py green test_runner_rpc_surface.py::test_every_reply_is_taken_in_a_shape_the_arity_reads, …::test_forward_refuses_and_its_reply_is_one_object_read_for_nine_attributes
B10 _kv = block_info[KV_KEY] in engine_core.py green test_runner_rpc_surface.py::test_get_num_blocks_refuses_and_the_keys_its_caller_reads_are_named
B12 _t = getattr(fwd_output, "tenth", None) in scheduler.py green test_runner_step_semantics.py::test_the_reply_answers_every_attribute_atom_reads_off_one
B16 a sixth KV-tuple element "draft" + "_kv_cache" in ModelRunner.exit green test_runner_rpc_surface.py::test_what_the_comment_says_a_hole_at_exit_loses_is_what_exit_does
B16 (lambda: torch.cuda.empty_cache()) in exit green same
B17 _all = lambda overrides: overrides.unanswered_rpc_names(object) in runner/step_output.py green test_runner_rpc_surface.py::test_the_unanswered_helper_describes_its_whole_return_and_not_one_half
B20 a second blob site setattr(seq, "kv_transfer_params_output", {}) in moriio_connector.py green test_kv_blob_doc_table.py::test_each_backend_builds_the_blob_at_exactly_one_site[moriio]
B20 a second blob site seq.kv_transfer_params_output: dict = {} green same
B22 from ..backends import Tier in clock/registry.py green test_clock_lp_identity.py::test_the_package_imports_only_the_standard_library_it_names[registry.py]
B23 _ordered = frozenset.union in clock/registry.py green test_clock_lp_identity.py::test_the_package_builds_no_set_at_all[registry.py]
B24 from ..backends import Tier in ir/graph.py green test_ir_data_model.py::test_the_package_imports_only_the_standard_library_it_names[graph.py]

Covered-by-a-neighbour rows, re-run on both sides as controls. Each has the same result at tip and head, except where this PR adds a second, correct name:

  • B5. call_func(func_name="exit") fails 3 at tip and 4 at head; the addition is test_both_filters_in_the_derivation_drop_nothing. A keyword-named, unwaited flush_pp_send site fails 2 at tip (test_sync_inventory) and 3 at head, with the same addition.
  • B13. An async def reading fwd_out.tenth fails 2 on both sides.
  • B19. A bare all_reduce outside the guard fails 1 on both sides, test_sync_inventory.py::test_every_scanned_site_is_classified.
  • B20/B21. A second, non-dict blob site fails 4 on both sides.
  • B6. A list-target capture_cudagraph site fails 1 at tip, where it is red only because it scores 1. At head it fails 2, adding test_every_reply_is_taken_in_a_shape_the_arity_reads.

Gate 1: ATOM's suite, unmodified, as a delta (round 0; the round-1 gate on the merged tree is in the review round 1 section)

Both runs were on node 18 in xiaobizh_n18_cpu:

  • Each tree was staged with git archive + docker cp into my own root, /tmp/i223gates/<label>/ATOM. Nothing was written into the shared mount.
  • Each was gated with its own scripts/compass/gate_cpu.sh.
  • The .compass-commit and .compass-changed stamps were written from the same rev-parse.
  • atom.__file__ was asserted under the staged root and printed before any count.
  • Each run was bounded by timeout -k 10 2400, run one at a time, never piped, and read from its log file. Node ids came from --junitxml.
tree stamp atom.__file__ passed / skipped / xfailed failed GATE_CPU_RC
control 175739f87 (the current integration tip) /tmp/i223gates/ctl3/ATOM/atom/__init__.py 5107 / 149 / 3, 405 s 0 0
branch 82171397a (the round-0 head) /tmp/i223gates/br4/ATOM/atom/__init__.py 5108 / 149 / 3, 414 s 0 0

Both runs printed gate: 29 files excluded + tests/plugin and gpu: not required (.compass-changed stamp), and both printed their GATE_CPU_RC line, so neither hung.

The node-id delta, from junit XML (5259 → 5260 ids):

  • added (1): tests/compass/test_runner_rpc_surface.py::test_every_reply_is_taken_in_a_shape_the_arity_reads
  • removed: none

The flaky TestTheRegionIsNotCopiedPerChunk did not fail on either side. The same pair measured one tip earlier, at f5003b255/1955aa708, gave 5056 → 5057 passed with the same single added id and GATE_CPU_RC=0 on both.

git merge-tree --write-tree 175739f87 82171397a → 03e9e1f809b7c0e278d7bbb1d9370a39d398a243, rc=0. This equals the head's own tree, so it merges clean.

Lint over the six edited files (black 26.5.1 --target-version py312, ruff 0.16.7): BLACK_RC=0, RUFF_RC=0.

Review round 1 (82171397a → 176cac3d4)

The review's seven findings are each fixed by making the guard refuse, not by adding one more spelling.

Commits:

  • 0364f226d: F1–F6, plus the file named in the _self_assigned and _methods messages.
  • 176cac3d4: F7. Its hunk did not apply in 0364f226d, because black had already rewrapped the line the edit anchored on. The battery caught this: the F7 mutation was still green at 0364f226d.
finding now
F1 _self_assigned Only setattr(self, "<literal>", v) is read as a call binding. Every other mention of setattr, __setattr__, __dict__ or vars in the class is refused.
F2 _writes_not_read Any mention of setattr, __setattr__, __dict__ or vars in a connector is refused. There are none today.
F3 _methods The refusal is moved out of import into test_every_class_body_the_method_sets_are_read_from_is_read. An Expr is read only as a docstring.
F4 _arity A Call parent scores None, not 1.
F5 reply hand-offs The reply may be handed whole only to HANDED_TO = ("postprocess", "send_tokens"). Any other hand-off is refused.
F6 exit The only return or raise allowed in exit are the opening guard's and the closing return True.
F7 helper callers An import unanswered_rpc_names as <x> is refused. A plain import is neutral.

Pins. Node 18, xiaobizh_n18_cpu.

  • The reviewer's harness, mut.py, was run unchanged except for one added spelling (N10).
  • Tip 77d203b86 and head 176cac3d4 were each staged by git archive + docker exec -i, and md5 matched on both ends.
  • atom.__file__ was asserted under each root.
  • The whole tests/compass suite ran per mutation, and results were read from junit XML.
  • The head has 1153 cases, not the tip's 1155, because its base predates the newest spec tests.
  • All results below are tests/compass/… node ids.
id mutation tip head 176cac3d4, failing node id(s)
null one docstring word in overrides.py 1155 passed 1153 passed
M1 setattr(self, "kv_cache", None) 1155 passed test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor
M2 (lambda: destroy_dist_env()) 1155 passed test_runner_rpc_surface.py::test_what_the_comment_says_a_hole_at_exit_loses_is_what_exit_does
M3 self.kv_cache: object = None 1155 passed test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor
M3b tuple target 1155 passed same
M4 if False: from ...model_engine import model_runner 1155 passed test_runner_non_allocating.py::test_only_the_binding_module_reaches_the_engine[overrides.py]
M5 sixth KV element "draft" + "_kv_cache" 1155 passed test_runner_rpc_surface.py::test_what_the_comment_says_a_hole_at_exit_loses_is_what_exit_does
M6 getattr(fwd_output, "tenth", None) 1155 passed test_runner_step_semantics.py::test_the_reply_answers_every_attribute_atom_reads_off_one
F1 (N1) self.__setattr__("kv_cache", None) 1155 passed test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor
F1 (N1b) super().__setattr__("kv_cache", None) 1155 passed same
F1 (N10) __import__("builtins").setattr(self, "kv_cache", None) 1155 passed same
F2 (N3) setattr(seq, "kv_transfer_params" + "_output", …) 1155 passed test_kv_blob_doc_table.py::test_each_backend_builds_the_blob_at_exactly_one_site[moriio]
F3 (N9) class-body if False: pass 1155 passed test_runner_rpc_surface.py::test_every_class_body_the_method_sets_are_read_from_is_read. Named; no collection error (rc=1, 1153 cases ran).
F3 (N7) class-body vars().update(exit=…) 1155 passed the same, plus test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor
F4 (N8) fwd_out, _extra = tuple(call_func("forward", …)) 1155 passed test_runner_rpc_surface.py::test_every_reply_is_taken_in_a_shape_the_arity_reads, test_runner_rpc_surface.py::test_forward_refuses_and_its_reply_is_one_object_read_for_nine_attributes
F5 (N5) self._peek(fwd_output) with _peek reading getattr(o, "tenth", None) 1155 passed test_runner_step_semantics.py::test_the_reply_answers_every_attribute_atom_reads_off_one
F6 (N6) self.still_running = False; return True 1155 passed test_runner_rpc_surface.py::test_what_the_comment_says_a_hole_at_exit_loses_is_what_exit_does
F7 (N4) from … import unanswered_rpc_names as u 1155 passed test_runner_rpc_surface.py::test_the_unanswered_helper_describes_its_whole_return_and_not_one_half

Gate on the tree that will land. git merge-tree --write-tree ff9617f30 176cac3d4 → 1849f16602541a399c8bce0acb57cd027baaeabc, rc=0. ff9617f30 is the integration tip when the gate ran.

  • How it was run: staged by git archive into my own root. .compass-commit is the merged hash, and .compass-changed is the six test files. atom.__file__ = /tmp/i223r2/merged3/ATOM/atom/__init__.py. Bounded by timeout -k 10 2400, unpiped.
  • Result: 5122 passed, 149 skipped, 3 xfailed, 0 failed, GATE_CPU_RC=0.

Control gate on the tip ff9617f30, run the same way (atom.__file__ = /tmp/i223r2/ctl/ATOM/atom/__init__.py):

  • Result: 5120 passed, 149 skipped, 3 xfailed, 0 failed, GATE_CPU_RC=0.
  • Delta: +2 passed. Node ids go from 5272 to 5274.
    • Added: tests/compass/test_runner_rpc_surface.py::test_every_reply_is_taken_in_a_shape_the_arity_reads and tests/compass/test_runner_rpc_surface.py::test_every_class_body_the_method_sets_are_read_from_is_read.
    • Removed: none.
  • Neither test_stream_marker_properties.py timing class failed on either side.

Not split out. Everything fits inside the 2x line, so nothing is proposed for a follow-up. If one had been needed, F5 would have been first: HANDED_TO is a named allowlist of two callees, the same data-flow class as the other items recorded as undone.

What surprised me

  1. Half of the brief's named result had already closed. compass(runner): correct the fourth spelling of the park claim, and pin the exit break #208 added {"destroy_dist_env", "torch.cuda.empty_cache"} <= calls, so the pass spelling was red at fa5180b62. But that set was built from every call anywhere in exit's walk, so wrapping the call in a lambda left it silent. That is the fifth instance's family: the guard counted a call it never checked was made.
  2. Five apparent gaps were already covered by a neighbour: B5, B13, B18, B19 and B21's value filter. Four of those are covered by test_sync_inventory, which classifies call sites by form. I measured rather than assumed, and I recorded these instead of fixing them.
  3. The null control caught my own defect. In one intermediate head, _writes_not_read compared node id()s across two separate ast.parse calls, so every connector looked unread and the null mutation went red. That was fixed before this head.
  4. A refusal at collection time hides the names. Early drafts raised inside _arity and inside the blob reader. SITES is computed at import and test_kv_remote_prefill.py parametrizes at collection, so the refusal became rc=2 collection errors across three modules and no test ran. The refusals now live in named tests instead: _arity scores None, and the blob refusal sits in the one-site test. test_kv_remote_prefill.py is left as it was. Correction after review round 1: at 82171397a this was true only of _arity and the blob reader. _methods still asserted at import, so one class-body if False: pass gave rc=2 across three modules. It now records into UNREAD_CLASS_BODY and a named test asserts that list is empty (F3, in the review round 1 section).
  5. ModelRunner already binds through three computed setattrs (the KV builder loops) that _self_assigned never read. They are not ring holders, but nothing said so; the call site now lists them.
  6. One mutation first went red for the wrong reason. getattr(fwd_output, "tenth") without a default raised at run time in the driven scheduler, giving 13 step-semantics failures. It was re-run with a default so that only the guard could redden.

Left undone, with the reason

gap why
B7, B14, B28 (glob walks in test_runner_rpc_surface.py, test_runner_step_semantics.py, test_memory_readings.py) Unreachable today. atom/compass/runner/, atom/model_engine/ and atom/compass/memory/ have no subdirectory. This is #218's shape.
Dynamic imports (__import__, importlib.import_module, exec) in B3, B22, B24, B25 Not closable at the AST level. The module can be reached through sys.modules, builtins, getattr or exec with any string, so no finite refusal exists.
Keys-view set operations (a.keys() | b.keys()) in B23 Needs types, not syntax.
Data-flow aliasing (out = func(); a, b = out) in B18 A binding analysis, not a spelling.
B5's wait_out read as False when it is not a literal Covered: test_sync_inventory classifies the site by its form.
B21's non-dict filter in test_kv_remote_prefill.py Covered by B20, which reddens by name. Routing it through the refusing reader made it a collection error (surprise 4), so the file is untouched.
B27 (test_spec_schema.py) Belongs to #212 (landed) and #218. Inventory only.
The three hard-typed "twelve"s from #208's review Prose counts, not an AST spelling gap. They belong with the prose-drift guards.
Text/regex guards, such as test_kv_simulated_connector.py's clock-name scan and test_memory_compare.py's design-reference scan (landed with #176 after the inventory) Not AST guards, so outside this sweep.

Overlaps, for the restacker

No design-doc references in code, test names, comments or emitted data.

🤖 Generated with Claude Code

…read

Several guards in tests/compass enumerate one spelling of what they
check and skip every other one, so a violation written another way
passes the whole suite. Each fix below makes the guard refuse the
shape it cannot read, naming the file, line and source, instead of
enumerating one more spelling.

- _self_assigned reads every binding of self.x that states its name
  (=, tuple and list targets, annotated and augmented =, and setattr
  with a literal name). A computed setattr, a for/with target or a
  __dict__/vars write has to be listed by its source text, or the
  guard refuses. ModelRunner lists its three builder setattrs.
- _methods reads def, async def and class-body assignments, and
  refuses any other statement that could bind a name. It exists once,
  in test_runner_rpc_surface.py, and test_runner_non_allocating.py
  imports it.
- The runner, clock and ir import guards resolve a relative import.
  One that climbs out of the package is now read as what it imports.
- _arity scores a list, starred, annotated or chained target as None
  instead of as a use of the whole reply, and a new test names every
  such site. A broadcast with no positional name joins the
  non-literal tripwire.
- The exit test counts only calls that are statements of exit's own
  body, and refuses a tuple element that is not a literal.
- The get_num_blocks key test refuses a block_info subscript that is
  not a literal. The unanswered_rpc_names caller check counts a call
  through a module and refuses any other mention.
- The clock set guard refuses any mention of set or frozenset, called
  or not.
- The one-site blob test refuses every write of
  kv_transfer_params_output that is not a plain assignment.
- _reply_attribute_reads refuses a use of the forward reply that is
  neither an attribute read nor a whole hand-off.

Closes #223

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
read.add(id(t))
elif (
isinstance(n, ast.Call)
and ast.unparse(n.func) in ("setattr", "object.__setattr__", "vars")

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.

F1. Blocking, principle 6 (refuse rather than fall back). The call half of _self_assigned is still an enumeration. It matches three exact callee strings (setattr, object.__setattr__, vars) and skips every other spelling of the same write. So the brief's own instance-4 claim is still held by nothing, one spelling over.

Measured on node 18 (xiaobizh_n18_cpu):

  • a git archive of 82171397a, with atom.__file__ asserted under the staged root;
  • the whole tests/compass suite;
  • line-count-preserving edits, restored afterwards.
mutation, appended to overrides.py:246 (allocate_kv_cache) head 82171397a
; setattr(self, "kv_cache", None) (control) 1 failed: tests/compass/test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor
; self.__setattr__("kv_cache", None) 1152 passed, rc=0
; super().__setattr__("kv_cache", None) 1152 passed, rc=0

The null control (one word changed in an overrides.py docstring) gives 1152 passed.

The ctx=Store half is a real refusal. The call half should be one too. The simplest fix follows your own B23 change: refuse any mention of setattr, __setattr__, __dict__ or vars in the class that this helper has not read, instead of matching three callee strings. builtins.setattr(...) is the next spelling after the two above.

This is also an inventory miss. B1's "does not see" column lists setattr, AnnAssign, AugAssign, tuple targets, for/with and __dict__/vars, but not the dunder-method spellings. Both are silent at the tip as well.

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.

F1: fixed in 0364f226d. The call half no longer matches callee strings. _self_assigned now reads exactly one call spelling as a binding: setattr(self, "<literal>", v). Every other mention of setattr, __setattr__, __dict__ or vars anywhere in the class is refused, however it is reached, by file, line and source text (the enclosing call's text when the mention is a callee). The ModelRunner allowlist is unchanged: the same three setattr(self, name, value), and nothing else newly refused there.

Measured on node 18 over the whole tests/compass suite: tip 77d203b86, head 176cac3d4.

mutation tip head
self.__setattr__("kv_cache", None) 1155 passed 1 failed: tests/compass/test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor
super().__setattr__("kv_cache", None) 1155 passed 1 failed: same test
__import__("builtins").setattr(self, "kv_cache", None) 1155 passed 1 failed: same test

The null control gives 1153 passed at head.

Comment thread tests/compass/test_kv_blob_doc_table.py Outdated
and not isinstance(n.ctx, ast.Load)
and id(n) not in read
)
or (isinstance(n, ast.Constant) and n.value == BLOB_ATTR)

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.

F2. Blocking, principle 6. This is the same family as the _self_assigned comment. The string check refuses the name only when it appears as a single literal, so a setattr with a computed name is a second blob site that nothing sees:

mutation, moriio_connector.py:997 (the } closing the blob dict) head 82171397a
}; setattr(seq, "kv_transfer_params" + "_output", seq.kv_transfer_params_output) 1152 passed, rc=0

The fix is to refuse any setattr, __setattr__ or __dict__ in the connector module whose name argument is not exactly this literal, or simply any setattr in the module at all. Neither connector contains setattr or __dict__ today (grepped at head), so the wider refusal fires on 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.

F2: fixed in 0364f226d, using the wider refusal you suggested. _writes_not_read now also refuses any mention of setattr, __setattr__, __dict__ or vars in the connector module, whatever name it builds. Neither connector has one, and the null control is green.

}; setattr(seq, "kv_transfer_params" + "_output", seq.kv_transfer_params_output):

  • tip 77d203b86: 1155 passed;
  • head 176cac3d4: 1 failed, tests/compass/test_kv_blob_doc_table.py::test_each_backend_builds_the_blob_at_exactly_one_site[moriio].

for target in n.targets if isinstance(n, ast.Assign) else [n.target]:
names |= {t.id for t in ast.walk(target) if isinstance(t, ast.Name)}
else:
assert isinstance(n, (ast.Expr, ast.Pass)), (

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.

F3. Blocking, principle 6, and it contradicts this PR's own design claim (principle 8). The dev record's surprise 4 says the refusals were moved out of import and collection time into named tests. This one was not moved:

  • _methods asserts.
  • It runs at module import, building BASE, RAPID, MIXIN and EXTENSION_CLASSES (:228-238).
  • Those cover ATOM's own ModelRunner and RapidServeModelRunner, and every class in the three atom/rollout/ files.
  • test_runner_non_allocating.py now imports _methods from this module, and test_runner_step_semantics.py imports SITES from it.
mutation head 82171397a
if False: pass as a class-body line of NonAllocatingRunner (overrides.py:209, a blank line) rc=2: 3 collection errors, 0 tests ran, in tests/compass/test_runner_non_allocating.py, tests/compass/test_runner_rpc_surface.py and tests/compass/test_runner_step_semantics.py

The text is NonAllocatingRunner:209 binds names in a form not read here: if False:. It gives the class and line, but no file and no test id.

An upstream if TYPE_CHECKING: or try: in any class body in those ATOM files would take all three modules down the same way. The fix is to have _methods return the statements it could not read alongside the names, and have one named test assert that list is empty. That is the pattern _arity and test_every_reply_is_taken_in_a_shape_the_arity_reads already use in this PR.

A second, smaller point on the same line. ast.Expr is allowed unconditionally, so an expression statement that binds a name passes silently:

mutation, same class body head
vars().update(exit=staticmethod(lambda *a: True)) 1152 passed, rc=0

On Python 3.12.3 in the same container, class C: vars().update(exit=...) does bind C.exit. I checked it with "exit" in C.__dict__, which gives True. Allowing only a docstring (an ast.Expr whose value is a str constant) closes this. B2's inventory row lists async def and class-body assignment but not this spelling.

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.

F3: both halves fixed.

  • Collection-time refusal (0364f226d). _methods no longer asserts. It appends every class-body statement it cannot read to UNREAD_CLASS_BODY, as file:line: source, and the new named test test_every_class_body_the_method_sets_are_read_from_is_read asserts that list is empty. That is the same pattern as _arity. You were right that the dev record claimed this had already been done at 82171397a. It had not: surprise 4 only moved _arity and the blob reader. The PR body is corrected.
  • Expression statements. An ast.Expr is now accepted only as a docstring, meaning a str constant.

Tip 77d203b86 vs head 176cac3d4:

mutation (NonAllocatingRunner class body) tip head
if False: pass 1155 passed 1 failed, no collection error: tests/compass/test_runner_rpc_surface.py::test_every_class_body_the_method_sets_are_read_from_is_read
vars().update(exit=staticmethod(lambda *a: True)) 1155 passed 2 failed: the test above, plus tests/compass/test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor (the new vars mention refusal from F1)

The refusal messages now carry the file as well: _classes stamps each node with its file.

target = parent.targets[0]
return len(target.elts) if isinstance(target, ast.Tuple) else 1
return 1
if isinstance(parent, (ast.Return, ast.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.

F4. Blocking (a one-line fix), principle 6. ast.Call is scored 1 ("used whole"), but no broadcast site in today's tree has a Call parent. I listed all 40 non-Compass sites at head: every parent is an Assign or an Expr, apart from the one Return at engine_core.py:749. So this line guesses an answer for a shape the tree does not contain, and the guess hides an unpack:

mutation, engine_core.py:1264 head 82171397a
fwd_out, _extra = tuple(self.runner_mgr.call_func("forward", scheduled_batch, wait_out=True)) 1152 passed, rc=0

The forward reply is unpacked into two names, and every arity test stays green. Dropping ast.Call from this tuple, so that it scores None, fires on nothing today and lets test_every_reply_is_taken_in_a_shape_the_arity_reads name the site.

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.

F4: fixed in 0364f226d. A Call parent now scores None, and the docstring no longer lists "passed on as an argument" as a use of the whole reply. It fires on nothing today.

fwd_out, _extra = tuple(self.runner_mgr.call_func("forward", ...)) at engine_core.py:1264:

  • tip: 1155 passed;
  • head 176cac3d4: 2 failed,
    • tests/compass/test_runner_rpc_surface.py::test_every_reply_is_taken_in_a_shape_the_arity_reads
    • tests/compass/test_runner_rpc_surface.py::test_forward_refuses_and_its_reply_is_one_object_read_for_nine_attributes

isinstance(up, ast.Return)
or ast.unparse(up) == f"{node.id} is None"
or (
isinstance(up, ast.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.

F5. Blocking (a small fix), principle 6. A reply "passed positionally to a method" is accepted as reading nothing. But the callee reads it under its own parameter name, which this walk never sees. That is an alias through a call, and the docstring says aliases are refused.

mutation, scheduler.py head 82171397a
def _peek(self, o): return getattr(o, "tenth", None) on the blank line before Scheduler.postprocess (:2355), plus ; self._peek(fwd_output) appended to :2435 1152 passed, rc=0

Today the tree hands the reply to exactly two methods:

  • self.scheduler.postprocess(..., fwd_out, ...) at engine_core.py:1276. Its parameter is named fwd_output, so its reads are seen.
  • self.pp_transport.send_tokens(fwd_out) at pp_engine_core.py:385, which only pickles it.

Name those two callees as the accepted hand-offs, as _self_assigned names its three setattrs, and refuse any other method. That keeps this a refusal.

A minor point: ast.unparse(up) == f"{node.id} is None" only matches when the reply is the left operand, so None is fwd_out would be refused. That is harmless, since it fails closed.

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.

F5: fixed in 0364f226d, as you suggested. HANDED_TO = ("postprocess", "send_tokens") names the two methods the tree hands the reply to, with the reason for each. A hand-off to any other function or method is refused by file, line and source text.

Your _peek mutation (the helper def plus ; self._peek(fwd_output)):

  • tip: 1155 passed;
  • head 176cac3d4: 1 failed, tests/compass/test_runner_step_semantics.py::test_the_reply_answers_every_attribute_atom_reads_off_one.

I left None is fwd_out failing closed, as you noted.

# nested def is one `exit` may never make.
calls = {
ast.unparse(n.value.func)
for n in body.body

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.

F6. Blocking, principle 6. This is the brief's named result, one spelling over. Reading only the statements of exit's own body closes the lambda wrapper. But a statement of the body is not necessarily one that exit reaches, and an early return before it is the destroy_dist_env() no-op the brief names:

mutation, model_runner.py:1041 tip 5acb025e1 head 82171397a
self.still_running = False; return True 1155 passed 1152 passed, rc=0

destroy_dist_env() and torch.cuda.empty_cache() are both still statements of the body, and neither runs.

The fix is to refuse any Return or Raise among body.body, and any compound statement containing one, other than two:

  • the leading if not self.still_running: return guard;
  • the final return True.

That fires on nothing today. B16's inventory row did not list this spelling.

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.

F6: fixed in 0364f226d. The exit test now takes every Return and Raise anywhere in exit, and requires that sorted list to be exactly ["return", "return True"]: the opening guard's return and the closing one. It also requires that the last statement is return True. This fires on nothing today.

self.still_running = False; return True:

  • tip 77d203b86: 1155 passed;
  • head 176cac3d4: 1 failed, tests/compass/test_runner_rpc_surface.py::test_what_the_comment_says_a_hole_at_exit_loses_is_what_exit_does.

tree = ast.parse(f.read_text())
called = {id(n.func) for n in ast.walk(tree) if isinstance(n, ast.Call)}
for n in ast.walk(tree):
if "unanswered_rpc_names" not in (

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.

F7. Blocking (a one-line fix), principle 6. "Any other mention of the helper is refused", but an aliased import is a mention this loop does not read. The name sits on an ast.alias (.name), which neither id nor attr reaches, and the call is then made through the alias:

mutation, atom/compass/runner/step_output.py:60 (a blank line after import numpy as np) head 82171397a
def _all(): from atom.compass.runner.overrides import unanswered_rpc_names as u; return u(object) 1152 passed, rc=0

To fix it, also read ast.alias nodes whose .name is the helper, and refuse one with an asname. A plain asname=None import, like the one at atom/compass/runner/model_runner.py:12, has to stay neutral, or the fix refuses today's tree. B17's inventory row lists a call through an attribute but not this spelling, and it is silent at the tip too.

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.

F7: fixed, in 176cac3d4. I had written this hunk for 0364f226d, but it did not apply, because black had already rewrapped the line it anchored on. The battery at 0364f226d still showed your mutation green. It went red only after the separate commit.

Now an ast.alias whose .name is the helper is refused when it has an asname. It is neutral without one, so the plain import at atom/compass/runner/model_runner.py:12 still passes.

Your def _all(): from ... import unanswered_rpc_names as u; return u(object):

  • tip 77d203b86: 1155 passed;
  • head 0364f226d: 1153 passed, the missed hunk;
  • head 176cac3d4: 1 failed, tests/compass/test_runner_rpc_surface.py::test_the_unanswered_helper_describes_its_whole_return_and_not_one_half.

@jgong5

jgong5 commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

This review is agent-authored: the first review of PR #266 (issue #223, the AST-guard sweep).

Verdict: REQUEST_CHANGES at head 82171397a7254c91055aa872a8a48b0ab9063d9a.

Blocking: seven gaps are reachable at this head in guards this PR says it closed. Each is measured, each is a small fix, and each has an inline comment:

  • five places where a "refusal" is still an enumeration or a benign fallback: F1, F2, F4, F5, F7;
  • the brief's own named no-op, one spelling over: F6;
  • one refusal that still fires at collection time, which the dev record says was moved out: F3.

Not blocking: the overlap note for #178 (§6), and two refusal messages that give the class but not the file.

What is solid, so the next cycle does not redo it:

  • All six brief reproductions hold: green on the tip and red by name at head.
  • The null control is clean.
  • The three glob walks really are over flat directories.
  • The computed setattr allowlist in ModelRunner is honest.
  • There are no design-doc references.
  • The merged tree gates at exactly the tip's count plus 1.

Read first: the eight design principles in atom/compass/design/README.md and atom/compass/AI_DEV_RULES.md. Every finding cites its principle number.

How this was measured

  • Where: node 18, xiaobizh_n18_cpu.
  • Trees: git archive of the tip 5acb025e1 and the head 82171397a, piped into docker exec -i under my own /tmp/pr266rev/<side>/ATOM. Nothing was written into the shared mount. The tarball md5 matched on both ends.
  • Imports: PYTHONPATH was set to the staged root, and atom.__file__ was asserted under it before every run. Each run printed it, for example /tmp/pr266rev/head/ATOM/atom/__init__.py.
  • Mutations: each one is line-count-preserving, and the harness asserts that the anchor is unique and the line count unchanged. Each is applied, the whole tests/compass suite is run under timeout -k 10 1800, and the file is then restored. Failures are read by node id from --junitxml.
  • Null control (one word changed in an overrides.py docstring): tip 1155 passed, head 1152 passed, both rc=0. Head has 3 fewer tests than the tip because it predates compass(spec): explain refuses an unknown term as ADDRESSING and an absent one as TOTALITY #264's spec tests.

1. The brief's gaps, reproduced

# mutation tip 5acb025e1 head 82171397a, failing node id
M1 ; setattr(self, "kv_cache", None) appended to overrides.py:246 1155 passed 1 failed: tests/compass/test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor
M2 destroy_dist_env() → (lambda: destroy_dist_env()) in ModelRunner.exit 1155 passed 1 failed: tests/compass/test_runner_rpc_surface.py::test_what_the_comment_says_a_hole_at_exit_loses_is_what_exit_does
M3 ; self.kv_cache: object = None (annotated) 1155 passed 1 failed: tests/compass/test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor
M3b self.config.num_kvcache_blocks, self.kv_cache = num_kvcache_blocks, None (tuple target) 1155 passed 1 failed: same test as M3
M4 if False: from ...model_engine import model_runner at module scope in overrides.py (climbing relative import) 1155 passed 1 failed: tests/compass/test_runner_non_allocating.py::test_only_the_binding_module_reaches_the_engine[overrides.py]
M5 sixth KV element "draft" + "_kv_cache" in exit's tuple 1155 passed 1 failed: tests/compass/test_runner_rpc_surface.py::test_what_the_comment_says_a_hole_at_exit_loses_is_what_exit_does
M6 ; _t = getattr(fwd_output, "tenth", None) at scheduler.py:2435 1155 passed 1 failed: tests/compass/test_runner_step_semantics.py::test_the_reply_answers_every_attribute_atom_reads_off_one

Each head failure is exactly one test, and it is the guard named for that row. None comes from a line-drift guard.

2. Independent inventory (principle 7)

I wrote my own list of unseen spellings for seven guards before comparing with the inventory. For each spelling, I ran it as a mutation of the head tree and then the whole suite:

inline guard spelling head in the inventory?
F1 B1 _self_assigned self.__setattr__("kv_cache", None) 1152 passed no. B1 lists setattr, __dict__ and vars, but not the dunder-method call.
F1 B1 super().__setattr__("kv_cache", None) 1152 passed no
F2 B20 _writes_not_read setattr(seq, "kv_transfer_params" + "_output", ...) 1152 passed inventoried as setattr, but the fix refuses only a literal name
F3 B2 _methods vars().update(exit=staticmethod(lambda *a: True)) in the class body. It does bind: "exit" in C.__dict__ gives True on Python 3.12.3. 1152 passed no
F4 B6 _arity fwd_out, _extra = tuple(call_func("forward", ...)) 1152 passed new: the fix scores a Call parent as 1
F5 B12 _reply_attribute_reads a hand-off to a method that reads the reply under another parameter name 1152 passed new: the fix accepts any positional method hand-off
F6 B16, the exit test self.still_running = False; return True (early return) 1152 passed (tip 1155) no. B16 lists the wrapped call and the non-literal element only.
F7 B17, the helper's callers from ... import unanswered_rpc_names as u; ... u(object) 1152 passed no. B17 lists a call through an attribute only.

The spellings marked "no" were all reachable when the inventory was taken, because each is at least as silent at the tip. The inventory missed four reachable gaps: F1, F3's vars() half, F6 and F7. F2, F4 and F5 are gaps in the new refusals themselves.

3. Refuse or enumerate (principle 6)

Refusals that are real, and fire on nothing today.

  • Real refusals:
    • B10, the non-literal block_info[...] subscript: it names the file, line and text.
    • B12, getattr or a plain alias of the reply: file, line and text.
    • B16's KV tuple: line and text.
    • B17's non-call mention: file, line and text.
    • B20's literal name: file, line and source.
    • B22 and B24, the climbing relative import: named as written.
    • B23, any mention of set: name and line.
    • _self_assigned's ctx=Store half: class, line and text, with an exact-equality allowlist that also refuses a stale entry.
  • Fire on nothing: the null runs are green on both sides, and the merged-tree gate below has 0 failed.

Enumerations and fallbacks that will fail open on the next spelling. Each is measured in §2 and has an inline comment:

  • F1: the setattr call match is a list of three callee strings.
  • F2: the blob refusal matches only a literal string.
  • F4: _arity scores a Call parent as "used whole", although no such site exists among today's 40.
  • F5: "handed on to a method" is treated as reading nothing.
  • F6: "a statement of the body" is treated as "a call exit makes".
  • F7: ast.alias is not read.

A refusal in the wrong place, F3. _methods asserts at import, while BASE, RAPID, MIXIN and EXTENSION_CLASSES are built over ATOM's own runner and rollout classes. A harmless class-body if False: pass in NonAllocatingRunner gives rc=2, 3 collection errors and 0 tests run, across test_runner_non_allocating.py, test_runner_rpc_surface.py and test_runner_step_semantics.py. The dev record's design change 1 (surprise 4) says exactly this had been moved into named tests.

Messages (not blocking).

  • _self_assigned and _methods give the class and line but not the file.
  • test_every_reply_is_taken_in_a_shape_the_arity_reads gives the file and line but not the source text.

4. The computed-setattr bindings in ModelRunner

These are handled honestly. They are allowlisted by exact source text, ["setattr(self, name, value)"] * 3, and each has a reason. The reason is accurate: model_runner.py:1922, :1932 and :1943 bind whatever allocate_kv_cache_tensors (main and Eagle3 draft) and allocate_per_req_cache return. Those are the KV and per-request tensors, not the forward_vars ring.

The comparison is exact equality, so a fourth such setattr refuses, and so does removing one. One residual, which is not blocking: moving one of the three to another method stays green, because the list holds text, not location.

5. Recorded, not closed

  • The glob walks. At the tip 5acb025e1, atom/compass/runner/ (4 .py), atom/model_engine/ (24) and atom/compass/memory/ (5) each have 0 subdirectories, so B7, B14 and B28 really are unreachable today.
  • Dynamic imports, keys-view set operations and data-flow aliasing are fairly recorded as out of reach of syntax.

One caveat: the method hand-off in F5 is the same data-flow class. The PR accepts it rather than refusing it, and it can be refused by name, because the tree has only two such callees (postprocess and send_tokens).

6. Overlaps (not blocking, but the body should say this)

I measured this with git merge-tree --write-tree against the current PR heads.

7. Design-doc references

None. I grepped the diff's added lines for D<n>, P0.<n>, T<n>, W<n>.<n>, principle <n>, Gate <n>, #<nn>, design/ and doc filenames, and got no hits.

Gate: the tree that will land

git merge-tree --write-tree 5acb025e12ece608284987c32ec9e594c339dbf0 82171397a7254c91055aa872a8a48b0ab9063d9a → 02fca93d7c873eaf9c96dada2c69bcb606df7d29, rc=0.

The tip moved since the developer's measurement, so this is not the developer's 03e9e1f80. #264 touched only atom/compass/spec/explain.py, test_spec_schema.py and test_spec_verbs.py, which are disjoint from this PR.

How the gate was run:

  • One gate, on node 18 xiaobizh_n18_cpu.
  • Staged from git archive 02fca93d7 with docker exec -i into /tmp/pr266rev/merged/ATOM. The md5 d395100a… matched on both ends.
  • The tree's own scripts/compass/gate_cpu.sh.
  • .compass-commit = the merged tree hash, and .compass-changed = git diff --name-only 5acb025e1 02fca93d7 (the six test files).
  • atom.__file__ = /tmp/pr266rev/merged/ATOM/atom/__init__.py.
  • timeout -k 10 3000, unpiped, with output to a log file.
tree gate header passed / skipped / xfailed failed GATE_CPU_RC
merged 02fca93d7 commit: 02fca93d7 (stamp), gate: 29 files excluded + tests/plugin, gpu: not required (.compass-changed stamp) 5112 / 149 / 3, 164 s 0 0

The expected count was the tip's 5111 plus 1, so this matches exactly. The junit output has 5264 cases, and tests/compass/test_runner_rpc_surface.py::test_every_reply_is_taken_in_a_shape_the_arity_reads is present. Neither test_stream_marker_properties.py timing class failed, so no re-run was needed.

What the next cycle should watch

Every one of F1 to F7 needs only a small change. Re-run the eight §2 spellings, plus builtins.setattr(self, "kv_cache", None), as the acceptance battery for the fix. Also re-run N9 (if False: pass in a class body) and expect a named failure, not rc=2.

jgong5 and others added 2 commits September 23, 2026 06:48
Each of the seven guards the review drove red now refuses what it cannot
read instead of matching one more spelling.

- _self_assigned: any mention of setattr, __setattr__, __dict__ or vars
  in the class that is not a setattr(self, "<literal>", ...) it read is
  refused, however it is reached (self.__setattr__, super().__setattr__,
  builtins.setattr).
- _writes_not_read: any mention of setattr, __setattr__, __dict__ or
  vars in a connector is refused; neither connector has one.
- _methods no longer asserts at import. It records a class-body
  statement it cannot read -- anything but a def, a class, an
  assignment, a docstring or pass -- and a named test lists them. An
  expression such as vars().update(...) is one of those.
- _arity scores a reply passed to another call as None, not 1.
- The forward-reply walk accepts a whole hand-off only to postprocess
  and send_tokens, the two methods the tree hands it to.
- The exit test refuses any return or raise in exit other than the
  opening guard's and the closing return True.
- The unanswered_rpc_names caller check refuses an import of it under
  another name.
- The class-body and self-binding refusals name the file.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The previous commit meant to make the caller check refuse an import of
the helper under another name, but that hunk did not apply, and an
import-as caller still passed. The check now refuses it. This commit
also rewraps two docstrings.

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

jgong5 commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

Developer round 1: all seven findings (F1–F7) and both non-blocking notes are addressed. The new head is 176cac3d4f504cf14d7e7bc0e569a205a2258d47. The two commits (0364f226d, 176cac3d4) sit on top of 82171397a, with no force-push. Each inline thread has its own reply, with node ids from both sides.

What changed: each guard now refuses the shapes it cannot read, rather than matching one more spelling.

  • F1 and F2 refuse any mention of setattr, __setattr__, __dict__ or vars.
  • F3 records a class-body statement it cannot read and fails a named test, test_every_class_body_the_method_sets_are_read_from_is_read. There is no collection error any more, and an Expr is read only as a docstring.
  • F4 scores a Call parent None.
  • F5 names its two hand-offs, postprocess and send_tokens, and refuses the rest.
  • F6 allows only the opening guard's return and the closing return True.
  • F7 refuses import … as.
  • Both refusal messages now name the file.
  • The PR body now records the compass: MEM-2 -- size the KV pool with ATOM's own arithmetic over substituted readings #178 conflict in test_only_the_binding_module_reaches_the_engine, and corrects surprise 4.

Pins. I ran your mut.py unchanged, adding only N10 (__import__("builtins").setattr(self, "kv_cache", None)). The whole tests/compass suite ran each time, on node 18, from git archive staging, with atom.__file__ asserted.

  • Tip 77d203b86: all 19 mutations and the null control gave 1155 passed.
  • Head 176cac3d4:
    • The null control gave 1153 passed. The base predates the newest spec tests, so the head has 2 fewer cases.
    • M1–M6, N1, N1b, N3, N4, N5, N6, N8 and N10 are each red in exactly the guard named for them.
    • N7 is red in two guards. N9 is red by name, with rc=1 and 1153 cases run.
  • The full table with node ids is in the PR body, under "Review round 1".

Gate on the tree that will land. git merge-tree --write-tree ff9617f30 176cac3d4 → 1849f16602541a399c8bce0acb57cd027baaeabc, rc=0.

tree passed / skipped / xfailed failed GATE_CPU_RC
merged 1849f1660 5122 / 149 / 3 0 0
control, tip ff9617f30 5120 / 149 / 3 0 0

The node-id delta is +2, the two named tests test_every_reply_is_taken_in_a_shape_the_arity_reads and test_every_class_body_the_method_sets_are_read_from_is_read, with none removed. No test_stream_marker_properties.py timing class failed.

Size. The PR is 284 test lines added and 67 removed (this round +92 / −40). That is 1.78x the ~160-line estimate, inside the 2x line. Production lines: 0.

One process defect, named: the F7 hunk silently failed to apply in 0364f226d, because black had already rewrapped its anchor line. The battery caught it (the F7 mutation was still green at 0364f226d), and 176cac3d4 fixes it.

There are no blocking issues on my side. Ready for re-review.

}
if id(n) not in read
and (
(_on_self(n) and isinstance(n.ctx, ast.Store))

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.

G1 (cycle 2). Blocking, principle 6. The ctx=Store half reads a write only when its base is exactly self, and skips a write on any other base without refusing it. A write through the type binds an attribute that every instance reads:

mutation, appended to overrides.py:246 tip ff9617f30 head 176cac3d4
; type(self).kv_cache = None 1164 passed 1153 passed, rc=0

self.__class__.kv_cache = None takes the same route: its base is self.__class__, not self, and __class__ is not in _WRITERS.

A generic "refuse every Store not on self" rule would hit 36 legitimate seq., config. and batch. stores in ModelRunner, which I measured at head. In NonAllocatingRunner the same count is 0, and it has 0 chains through __class__. So the refusal can be scoped to the overrides call: refuse any attribute store not rooted at self, and any chain through __class__. That fires on nothing today. This spelling was silent at the tip too, and neither inventory listed it.

module importing this one from collecting.
"""
names = set()
for n in node.body:

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.

G2 (cycle 2). Blocking, principle 6. The body is now a real refusal: F3's if False: pass is a named failure, rc=1 with 1153 cases run. But _methods reads only node.body. The class's bases, decorator_list and keywords are not read and not recorded, and each of them can bind a name that the worker's getattr finds:

mutation tip ff9617f30 head 176cac3d4
class NonAllocatingRunner(type("_M", (), {"exit": lambda *a: True})): (overrides.py:179) 1164 passed 1153 passed, rc=0
@lambda c: type(c.__name__, (c,), {"exit": lambda *a: True}) on the blank line overrides.py:178 1164 passed 1153 passed, rc=0

In both cases the composed runner answers exit from the overrides, while test_the_replaced_methods_are_the_ones_that_own_memory_or_run_a_step still reads six methods.

NonAllocatingRunner has no bases, decorators or keywords today. The fix is to append any of them to UNREAD_CLASS_BODY when _methods reads the mixin, which fires on nothing. For ModelRunner and RapidServeModelRunner, whose bases are known, list them by text instead.

or ast.unparse(up) == f"{node.id} is None"
or (
getattr(up, "func", None) is not None
and getattr(up.func, "attr", None) in HANDED_TO

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.

G3 (cycle 2). Blocking, principle 6. This is the narrowed residue of F5, and it is partly my own suggestion, so I am flagging that for the stop rule. HANDED_TO is matched on the bare method name, on any receiver, and nothing checks either stated reason: that postprocess reads the reply as fwd_output, or that send_tokens reads nothing.

mutation tip ff9617f30 head 176cac3d4
; _t = getattr(out, "tenth", None) appended to atom/distributed/pp_transport.py:141, inside send_tokens, which is outside the model_engine walk 1164 passed 1153 passed, rc=0
appended to engine_core.py:1264: ; type("_P", (), {"postprocess": staticmethod(lambda o: getattr(o, "tenth", None))}).postprocess(fwd_out) 1164 passed 1153 passed, rc=0

postprocess is also a method name on ModelRunner (model_runner.py:3068) and on LLMEngine (llm_engine.py:766, whose parameter is reqs). So a hand-off to either of those would be accepted too.

To make this a refusal:

  1. Key the list on the call's text, self.scheduler.postprocess and self.pp_transport.send_tokens.
  2. Hold each reason: every def postprocess that a listed call can reach names the parameter fwd_output, and send_tokens's parameter appears only inside pickle.dumps(...).

# And nothing leaves `exit` between them: its only ways out are the guard
# that opens it and the `return True` that closes it.
exits = sorted(
ast.unparse(n) for n in ast.walk(body) if isinstance(n, (ast.Return, ast.Raise))

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.

G4 (cycle 2). Blocking, principle 6. This is still the brief's named no-op. Return and Raise are the two exits this enumerates, so two other ways to leave exit before destroy_dist_env() pass:

mutation, model_runner.py:1041 tip ff9617f30 head 176cac3d4
self.still_running = False; assert self.still_running 1164 passed 1153 passed, rc=0
self.still_running = False; (yield) (turns exit into a generator, so no line of it runs when it is called) 1164 passed 1153 passed, rc=0

The refusal that does not depend on listing exit forms is to compare body.body's statements before destroy_dist_env() by source text against the two that are there today: the if not self.still_running: return guard and self.still_running = False. Also refuse any Yield, YieldFrom or Await anywhere in exit. Both fire on nothing today.

def _self_assigned(node):
"""Every `self.x = ...` in *node*, as (name, the source of its value).
# Every name through which an attribute can be written without an assignment.
_WRITERS = ("setattr", "__setattr__", "__dict__", "vars")

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.

G5 (cycle 2). Not blocking, principle 6 and principle 8 (on the docstring's claim). F1, F2 and F7 now refuse every identifier spelling of the writers and of the helper; N10 __import__("builtins").setattr is red. A name looked up as data still passes:

mutation head 176cac3d4
; __builtins__["setattr"](self, "kv_cache", None) (overrides.py:246) 1153 passed
}; __builtins__["setattr"](seq, "kv_transfer_params" + "_output", …) (moriio_connector.py:997) 1153 passed
def _all(): from atom.compass.runner import overrides as o; return getattr(o, "unanswered_rpc_names")(object) (step_output.py:60) 1153 passed

Two cheap changes:

  • Refuse a literal-string mention of the watched names ("setattr", "__setattr__", "__dict__", "vars", "unanswered_rpc_names"), as _writes_not_read already does for BLOB_ATTR. That closes all three rows. None of the three scopes contains such a string today; measure that first.
  • Record the residue. A name built at run time ("set" + "attr") is the same class as the dynamic imports this PR already records as out of reach. Record it there, and drop "however it is reached" from _self_assigned's docstring, because that overclaims.

@jgong5

jgong5 commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

This review is agent-authored: cycle 2 of the review of PR #266 (issue #223). It covers the delta 82171397a..176cac3d4 only.

Verdict: REQUEST_CHANGES at head 176cac3d4f504cf14d7e7bc0e569a205a2258d47.

All seven round-1 findings are fixed and verified. F1 to F7, M1 to M6, N10, and F3's collection error are each red by name at head, and F3 is now rc=1 with every test run.

Blocking: G1 to G4, four new gaps. Each is structural, not data-level, and each is green at head (1153 passed). All were silent at the tip too, so neither the inventory nor my round-1 list found them.

  • G1: a store through type(self).
  • G2: a class base or decorator that injects exit.
  • G3: the hand-off list matched on method name only, with its "reads nothing" reason held by nothing. This is the narrowed residue of F5, and partly my own suggestion; see the note on the stop rule below.
  • G4: assert or yield in exit, the brief's named no-op.

Not blocking: G5, a name looked up as a string. Refuse the literal form, and record the computed form beside the dynamic imports.

The merged-tree gate is clean at +2.

Read first: the eight design principles in atom/compass/design/README.md and atom/compass/AI_DEV_RULES.md. Every finding cites its principle number.

How this was measured

Battery, at head 176cac3d4

Round-1 set: every mutation is red by name. Each row fails exactly the named guard(s).

id spelling failing node id(s)
M1 setattr(self, "kv_cache", None) tests/compass/test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor
M3, M3b annotated binding; tuple-target binding same test
N1, N1b self.__setattr__(...), super().__setattr__(...) same test
N10 __import__("builtins").setattr(self, "kv_cache", None) same test
M2, M5 lambda-wrapped destroy_dist_env; non-constant sixth KV name tests/compass/test_runner_rpc_surface.py::test_what_the_comment_says_a_hole_at_exit_loses_is_what_exit_does
N6 early return True in exit same test
M4 climbing relative import in overrides.py tests/compass/test_runner_non_allocating.py::test_only_the_binding_module_reaches_the_engine[overrides.py]
M6 getattr(fwd_output, "tenth", None) tests/compass/test_runner_step_semantics.py::test_the_reply_answers_every_attribute_atom_reads_off_one
N5 self._peek(fwd_output) hand-off same test
N3 computed-name setattr blob site tests/compass/test_kv_blob_doc_table.py::test_each_backend_builds_the_blob_at_exactly_one_site[moriio]
N4 import unanswered_rpc_names as u tests/compass/test_runner_rpc_surface.py::test_the_unanswered_helper_describes_its_whole_return_and_not_one_half
N7 vars().update(exit=...) in the class body 2 failed: …test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor, …test_runner_rpc_surface.py::test_every_class_body_the_method_sets_are_read_from_is_read
N8 fwd_out, _extra = tuple(call_func("forward", …)) 2 failed: …test_runner_rpc_surface.py::test_every_reply_is_taken_in_a_shape_the_arity_reads, …::test_forward_refuses_and_its_reply_is_one_object_read_for_nine_attributes
N9 (F3) if False: pass in the class body rc=1, 1153 cases ran, 1 failed: tests/compass/test_runner_rpc_surface.py::test_every_class_body_the_method_sets_are_read_from_is_read. There is no collection error.

New spellings, one or more per guard. Each was run on both sides.

id guard spelling tip ff9617f30 head
N11 F1 _self_assigned type(self).kv_cache = None 1164 passed 1153 passed. G1
N12 F1 __builtins__["setattr"](self, "kv_cache", None) 1164 passed 1153 passed. G5
N13 F2 _writes_not_read __builtins__["setattr"](seq, "kv_transfer_params" + "_output", …) 1164 passed 1153 passed. G5
N14 F3 _methods base class type("_M", (), {"exit": …}) 1164 passed 1153 passed. G2
N21 F3 class decorator returning a subclass with exit 1164 passed 1153 passed. G2
N20 F4 _arity fwd_out = (_w := call_func("forward", …)) n/a red: the same 2 tests as N8
N15 F5 hand-off a read of out.tenth inside send_tokens (pp_transport.py:141) 1164 passed 1153 passed. G3
N16 F5 ….postprocess(fwd_out) on an unrelated object 1164 passed 1153 passed. G3
N17 F6 exit self.still_running = False; assert self.still_running 1164 passed 1153 passed. G4
N18 F6 self.still_running = False; (yield) 1164 passed 1153 passed. G4
N19 F7 helper callers getattr(overrides, "unanswered_rpc_names")(object) 1164 passed 1153 passed. G5

Refuse or enumerate, per fix (principle 6)

fix ruling evidence
F1 _self_assigned The call half is now a refusal at the identifier level. Any setattr, __setattr__, __dict__ or vars mention, however it is called, is refused (N1, N1b, N10). The store half is still selective: a store on any base other than exactly self is skipped, not refused (G1). A name looked up as a string escapes (G5). N11 green; N12 green
F2 blob writes The same identifier-level refusal, and the same string-lookup residue (G5). N3 red; N13 green
F3 _methods The body is a refusal: anything not read is recorded and named, and there is no collection error any more. But the class header is not read at all: bases and decorators (G2). N9 named; N14 and N21 green
F4 _arity A refusal. The default is None, so an unforeseen parent (a walrus) is named. N20 red
F5 hand-off An allowlist that fails open (G3). It matches postprocess or send_tokens on any receiver, and nothing holds its two stated reasons. N15 and N16 green
F6 exit An enumeration of two exit forms, Return and Raise. Assert and Yield leave just as early (G4). N17 and N18 green
F7 helper callers Adds one more spelling (asname). A string lookup escapes (G5). N4 red; N19 green

On the stop rule, in AI_DEV_RULES.md: G3 is the narrowed residue of F5, and its shape (name the two callees) was my own round-1 suggestion. If the coordinator counts it as F5 surviving, the rule applies. G1, G2, G4 and G5 are new: each was silent at the tip and absent from both inventories.

Other delta items

Gate: the tree that will land

The tip is still ff9617f3052c93067a2f56a663ef2cea5add4c28. git merge-tree --write-tree ff9617f30 176cac3d4 → 1849f16602541a399c8bce0acb57cd027baaeabc, rc=0, which matches the developer's hash.

How the gate was run:

  • One gate on node 18.
  • Staged with git archive + docker exec -i; md5 4dad6579… on both ends.
  • The tree's own scripts/compass/gate_cpu.sh.
  • .compass-commit = the merged tree hash, and .compass-changed = the six test files.
  • atom.__file__ = /tmp/pr266r2/merged/ATOM/atom/__init__.py.
  • timeout -k 10 3000, unpiped.
tree header passed / skipped / xfailed failed GATE_CPU_RC
merged 1849f1660 commit: 1849f1660 (stamp), 29 files excluded + tests/plugin, gpu: not required (.compass-changed stamp) 5122 / 149 / 3, 161 s 0 0

This matches the developer's 5122, which is their control of 5120 + 2. The junit output has 5274 cases, and both new ids are present: test_every_reply_is_taken_in_a_shape_the_arity_reads and test_every_class_body_the_method_sets_are_read_from_is_read. No test_stream_marker_properties.py timing class failed.

Next cycle

G1 to G4 are each a few lines, and each fires on nothing today. The acceptance battery is N11 to N21 above. For G5, either refuse the literal-string forms (N12, N13, N19) or record them beside the dynamic imports and drop "however it is reached".

@jgong5 jgong5 added the need human Automation stopped; needs owner judgement. Agents apply when escalating, only the owner removes. label Sep 23, 2026
@jgong5

jgong5 commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

Halted under the review-loop stop rule: labelled need human.

Why. Cycle 2 (#266 (comment)) verified that all seven cycle-1 findings F1–F7 are closed. It then found four new blocking gaps, G1–G4, by trying one more spelling per guard. G3 is the remainder of F5, whose hand-off fix is an allowlist that fails open. So F5 has survived two cycles, and the rule halts the loop.

What the pattern says. Each round closes the spellings the reviewer named, and the next round finds the next spelling:

  • G1: a write through type(self);
  • G2: a base class or decorator that adds exit;
  • G3: a read inside send_tokens, or postprocess on an unrelated object;
  • G4: an assert or yield in exit.

The rules call a loop that cannot converge a mis-cut task.

Proposal for the owner (not acted on):

  1. Land what is verified. Cycle 2 confirms F1–F7 and M1–M6 are all red by name at 176cac3d4. The merged tree gates at 5122 / 149 / 3, GATE_CPU_RC=0.
  2. File G1–G5 as a follow-up task, cut per guard. Its brief should require each guard to refuse any shape it cannot read, rather than enumerate spellings. For exit, that means refusing any statement that is not an allowed call, instead of listing Return and Raise.

Or decide that this PR carries G1–G4 before landing.

Either way, this needs your call. No agent will act on #266 until the label is removed.

jgong5 added a commit that referenced this pull request Sep 24, 2026
…s tests (#410)

This applies 11 of the 12 findings from the ponytail-audit of
atom/compass/clock/ and its tests, posted on #406.

Production code, identity.py, lookahead.py and registry.py (-63/+10):
- removes LookaheadMatrix.tightest, .serializing, .links and __len__;
- removes LinkClass.scale_seconds and .label;
- tightens the helpers the audit flagged.
Nothing outside the edited files calls any removed member, at the tip or
at any held clock head (#59, #63, #67, #75, #91, #96, #266). The only
clock name those heads use after a merge is
TRAFFIC_TO_ENGINE_FLOOR_SECONDS, which is kept.

Tests (-76/+4) lose 7 that pinned removed members or repeated a kept
test. Mutants confirm the kept tests still pin inbound order and the
cross-process total order.

Skipped: F7b, removing LpRegistry.__contains__. `[] in registry` keeps
raising TypeError rather than silently returning False (principle 6).

The audit's differential probe (39,252 lines) is byte-identical apart
from the 4 lines it tagged in advance. LinkClass values changed:
LinkClass("traffic_to_engine") now returns the member. That is an exact
lookup of the member's own value, not a fallback. Unknown values still
raise, and declare() still refuses a str.

The held clock chain picks up new textual conflicts in these five
files. Nearly all of them resolve to the integration side. #63's import
block at test_clock_lp_identity.py:47 needs a hand merge. The owner
ruled that this lands without holding for that chain.

Gate (node 18, CPU tier, merged tree on 60186b8): 5273 passed,
155 skipped, 3 xfailed, GATE_CPU_RC=0. That is -7 against the tip,
exactly the removed tests.

Closes #406

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

Base update of held PR #266, owner-authorized on 2026-09-24 ("yes, file
the rules change and include #266"). The PR keeps its need human label;
this merge only brings in the integration tip and resolves its conflicts.

Resolved files:

- tests/compass/test_runner_non_allocating.py,
  test_only_the_binding_module_reaches_the_engine: kept the tip's
  docstring, which explains the atom.compass.memory exemption (#178),
  and applied this PR's relative-import resolution of `imported` under
  it. The tip's startswith(("atom.compass.runner", "atom.compass.memory"))
  exemption now reads the resolved set. No module under
  atom/compass/runner/ has a relative import today, so the resolution
  changes no verdict on the tip's tree.

- tests/compass/test_runner_rpc_surface.py,
  test_get_num_blocks_refuses_and_the_keys_its_caller_reads_are_named:
  kept the tip's repo-relative `REPO / site.file` (#407) and this PR's
  `subscripts = [...]` list with its non-literal-key refusal.

Everything else merged clean. The merged tree's diff against the tip
matches this PR's own diff against its old merge base 175739f
line for line: the same 6 files, +284/-67.

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

jgong5 commented Sep 24, 2026

Copy link
Copy Markdown
Owner Author

Base update (owner-authorized, 2026-09-24)

The owner authorized this on 2026-09-24: "yes, file the rules change and include #266". It covers the base update only. The need human label stays. Nothing was undrafted, reviewed or landed, and nothing changed beyond resolving this merge.

Heads

  • Old head: 176cac3d4f504cf14d7e7bc0e569a205a2258d47
  • New head: a86d05363e62a9a38f3ae9a5c84eceb335ab5911, a single merge commit with parents 176cac3d4 and 3a3267a84, which is the freshly fetched fork/feature/atomcompass_new.
  • Pushed as a fast-forward (176cac3d4..a86d05363). There was no rebase, amend or force-push.

Resolved files. There were two conflicts, one hunk each. Everything else merged clean.

file hunk resolution
tests/compass/test_runner_non_allocating.py test_only_the_binding_module_reaches_the_engine: docstring and imported Kept the tip's docstring (#178's atom.compass.memory exemption paragraph). Under it, applied this PR's relative-import resolution of imported. The tip's startswith(("atom.compass.runner", "atom.compass.memory")) now reads the resolved set. No module under atom/compass/runner/ has a relative import today, so this changes no verdict on the tip's tree.
tests/compass/test_runner_rpc_surface.py top of test_get_num_blocks_refuses_and_the_keys_its_caller_reads_are_named Kept the tip's repo-relative REPO / site.file (#407) and this PR's subscripts = [...] with its non-literal-key refusal.

No tip change was dropped. In each hunk, the lines the tip changed and the lines this PR changed are disjoint, and both sides' changes are kept.

Lint on the two resolved files (black 26.5.1 --target-version py312, ruff 0.16.7): BLACK_RC=0, RUFF_RC=0.

Gate. Node 18, xiaobizh_n18_cpu, one gate at a time, each tree with its own scripts/compass/gate_cpu.sh.

  • Each tree was staged by git archive plus docker exec -i into /tmp/u266gates/<tree>, with the tarball md5 matching on both ends. Nothing was written into the shared mount.
  • The stamps were written from the same sha as the archive.
  • atom.__file__ was asserted under each staged root.
  • Every run was bounded by timeout -k 10 3000, unpiped, with node ids read from --junitxml.
tree commit: stamp .compass-changed passed / skipped / xfailed failed GATE_CPU_RC junit ids
new head a86d05363 6 test files vs tip 5280 / 155 / 3 0 0 5438
tip (control) 3a3267a84 empty 5278 / 155 / 3 0 0 5436
old head 176cac3d4 6 test files vs 175739f87 5109 / 149 / 3 0 0 5261

Node-id delta

Failure classification: there are none to classify. There were 0 failures and 0 errors at the new head, the tip and the old head. Neither test_stream_marker_properties.py timing class and test_gc_utils.py::test_freezing_twice_is_additive_and_harmless failed on any side, so nothing needed a re-run and no fix commit was needed.

No blocking issues from this update. The PR stays held under need human, pending the owner's ruling on the proposal above.

@jgong5

jgong5 commented Sep 24, 2026

Copy link
Copy Markdown
Owner Author

Base-update resolution review

This review is agent-authored. It covers only the conflict resolutions in merge commit a86d05363e62a9a38f3ae9a5c84eceb335ab5911, which merges tip 3a3267a84 into old head 176cac3d4. It is not a review of #266's own content and makes no change to the need human label. At posting time the PR head is a86d05363.

Verdict: SOUND. Both conflict hunks keep every change from both sides. No tip change is dropped anywhere in the merged tree. There are no findings, so there are no inline comments.

1. Remerge diff (git show --remerge-diff a86d05363)

Only two files conflicted. Both are resolved as the union of the two sides:

2. Equality check, reproduced independently

  • The merge base of 176cac3d4 and 3a3267a84 is 175739f87 (the only base).

  • git diff 3a3267a84 a86d05363 and git diff 175739f87 176cac3d4 both show 6 files, +284/−67.

  • Compared as sequences, the changed lines (diff --git headers plus every +/- line) are identical: diff rc 0.

  • The full diffs are not byte-identical once index lines and hunk line numbers are stripped. They differ in exactly three context lines, and each one is tip content that shows up as context in the merged diff:

    So "line for line identical" holds for the changes. It does not hold for context, and the context differences are exactly the tip's changes being kept, which supports the claim rather than weakening it.

  • Every file outside those 6 is byte-identical to the tip in the merged tree.

3. Tests on node 18 (xiaobizh_n18_cpu)

Setup: a git archive of a86d05363, md5 b511bc21… matching on both ends, staged at a private path. atom.__file__ resolves under the staged root. Every run is bounded by timeout -k 10.

run expectation result
both resolved files, unmodified pass 103 passed, rc 0. This matches the 103 ids these two files have in the developer's new-head gate (tip: 101).
probe module from ..memory import EAGER_SOURCE resolved to atom.compass.memory, exempted 1 passed
probe from ...model_engine import model_runner resolved and refused failed: {'atom.model_engine'} == set()
mutation: drop "atom.compass.memory" from the #178 exemption, with the ..memory probe in place refused 2 failed: [overrides.py] (absolute import) and [zz_probe.py] (relative import), both {'atom.compass.memory'}
mutation: restore #266's pre-merge ENGINE / site.file red FileNotFoundError …/atom/model_engine/atom/model_engine/engine_core.py

So #266's relative-import resolution feeds the #178 exemption: a relative import of the exempted package is exempted, and removing the exemption refuses it. Taking #266's side of the rpc conflict would have been red, which is why the tip's REPO had to be kept.

Not a finding: from .. import memory resolves to atom.compass and is refused. The absolute form from atom.compass import memory is refused the same way at the tip, because _import_time_imports records node.module. The behaviour is consistent across the two forms and fails safe. It is not introduced by this merge.

4. Gate (logs read, not re-run)

The logs are complete. Each has its commit: stamp, its summary line and its GATE_CPU_RC.

tree stamp result
new head a86d05363 5280 passed, 155 skipped, 3 xfailed; GATE_CPU_RC=0; 5438 ids
tip 3a3267a84 5278 passed, 155 skipped, 3 xfailed; rc 0; 5436 ids
old head 176cac3d4 5109 passed, 149 skipped; rc 0; 5261 ids

Information only: the integration branch has since moved to 168c58309, so the PR is behind it again.

@jgong5

jgong5 commented Sep 29, 2026

Copy link
Copy Markdown
Owner Author

Re-scoped under the owner's ruling in #489 (prose is not a test subject). Keep B1-B3, B5, B6, B10, B12, B20 and B22-B24, which harden the tests that inspect code structure. Drop B16's comment assertions and B17 (unanswered_rpc_names.__doc__), because they harden tests of prose. The need human label stays for the owner to remove.

@jgong5 jgong5 removed the need human Automation stopped; needs owner judgement. Agents apply when escalating, only the owner removes. label Sep 29, 2026
@jgong5

jgong5 commented Sep 29, 2026

Copy link
Copy Markdown
Owner Author

The need human label is removed. This PR is claimable once #490 lands. #490 deletes tests from test_kv_blob_doc_table.py, test_runner_non_allocating.py and test_runner_rpc_surface.py, which are three of this PR's six files. The developer then merges the fresh integration tip into this branch, keeping both sides, and applies the re-scope in the comment above: keep B1-B3, B5, B6, B10, B12, B20 and B22-B24; drop B16's comment assertions and B17.

jgong5 and others added 2 commits September 29, 2026 03:49
…st-guards

Conflicts, resolved:
- tests/compass/test_kv_blob_doc_table.py: deleted upstream, its one-site
  structure check kept as tests/compass/test_kv_blob_site.py. The file is
  deleted here too, and this branch's `_writes_not_read` refusal and the
  `_blob_site` docstring that points at it are carried onto the kept test.
- tests/compass/test_runner_rpc_surface.py, exit test (renamed upstream to
  test_what_a_hole_at_exit_loses_is_what_exit_does): kept this branch's
  early-exit check; the three comment assertions upstream deleted stay
  deleted.
- tests/compass/test_runner_rpc_surface.py, unanswered-helper test (renamed
  upstream to test_the_unanswered_helper_returns_one_list_its_one_caller_partitions):
  kept this branch's caller refusal on the kept callers check; the docstring
  assertions upstream deleted stay deleted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The re-scope keeps the guards that inspect code structure and drops the
ones that hardened tests of prose. The caller refusal in
test_the_unanswered_helper_returns_one_list_its_one_caller_partitions was
added to harden a test of `unanswered_rpc_names.__doc__`; that test is
back to the integration branch's form. The exit test's comment assertions
went with the merge, where the upstream deletion won.

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

jgong5 commented Sep 29, 2026

Copy link
Copy Markdown
Owner Author

Developer round: merge of #492, re-scope applied

Head: 051fc93ca239bff6f10cd68ca94afbab11148eb8. It has two new commits on top of a86d05363, and it was pushed as a fast-forward (no force-push, rebase or amend).

Merge resolutions (git show --remerge-diff 0f7e86ea0)

file conflict resolution
tests/compass/test_kv_blob_doc_table.py modify/delete: #492 deleted it, and kept its one-site check as tests/compass/test_kv_blob_site.py The file is deleted. B20 (_writes_not_read, the refusal at the top of test_each_backend_builds_the_blob_at_exactly_one_site, and the _blob_site docstring that points at it) is carried onto test_kv_blob_site.py. Everything else this branch had in the deleted file went with it.
tests/compass/test_runner_rpc_surface.py test_what_a_hole_at_exit_loses_is_what_exit_does (renamed by #492) Kept this branch's early-exit check (the only Return/Raise in exit are return and return True, and the last statement is return True). The three ... in comment assertions stay deleted, because #492's deletion wins. The body-statement call set and the literal KV-tuple refusal merged cleanly.
tests/compass/test_runner_rpc_surface.py test_the_unanswered_helper_returns_one_list_its_one_caller_partitions (renamed by #492) In the merge, I kept this branch's caller refusal on the kept callers check, and the docstring assertions stay deleted. The next commit then drops it (below).
tests/compass/test_runner_non_allocating.py none (auto-merged) This branch's _self_assigned, the _methods import and the relative-import resolution sit on #492's kept tests. _self_assigned's ModelRunner call site is now in test_exactly_two_attributes_of_the_runner_hold_the_ring, which #492 renamed.

Dropped (051fc93ca)

  • B17: test_the_unanswered_helper_returns_one_list_its_one_caller_partitions is back to the integration branch's form.
  • B16's comment assertions were dropped in the merge.
  • No other line in the diff reads a docstring or comment to assert its text. _is_docstring in _methods only skips a class docstring and asserts nothing about it.

Mutation evidence, per kept B-item

Method. Node 18, xiaobizh_n18_cpu.

  • Trees. Two git archive trees, the control c0f641949 (the guards before hardening) and the head 051fc93ca, were staged under /tmp/pr266gates/mut/. The production code in the two is identical.
  • Each mutation is one line-count-preserving edit of production source. Before applying it, the harness checks the line's content and that the line count is unchanged. After each run it restores the file and checks the md5.
  • Each run is the whole tests/compass suite on each side, with PYTHONPATH set to that root. Node ids and assertions come from junit.
  • Null control (one docstring word in overrides.py): control 1257 tests, 0 failed; head 1259 tests, 0 failed.

Results. Every row below is green on the control (1257 tests, 0 failed) and red on the head in exactly the named test, and in no other test (1259 tests), unless the row says otherwise. Node ids are tests/compass/<file>::<test>.

item mutation (file) head: failing node id assertion
B1 ; setattr(self, "kv_cache", None) in NonAllocatingRunner.allocate_kv_cache (overrides.py) test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor assert {'_token_stre...ing', 'model'} == {...} (kv_cache is now in the bound set)
B1 ; self.kv_cache: object = None same same
B1 self.config.num_kvcache_blocks, self.kv_cache = num_kvcache_blocks, None same same
B1 ; self.__setattr__("kv_cache", None) same NonAllocatingRunner binds attributes on self in a form not read here: overrides.py:437: self.__setattr__('kv_cache', None)
B2 async def exit(self): return True in the NonAllocatingRunner body test_runner_non_allocating.py::test_the_replaced_methods_are_the_ones_that_own_memory_or_run_a_step assert {...} == {...} (exit is now in the method set)
B2 if False: pass in the NonAllocatingRunner body test_runner_rpc_surface.py::test_every_class_body_the_method_sets_are_read_from_is_read class bodies not read: ['overrides.py:240: if False:', ...]. rc=1, not a collection error.
B3 if False: from ...model_engine import model_runner at module scope in overrides.py test_runner_non_allocating.py::test_only_the_binding_module_reaches_the_engine[overrides.py] assert {'atom.model_engine'} == set()
B5 ; _ = False and self.runner_mgr.call_func(func_name="exit") in engine_core.py test_runner_rpc_surface.py::test_both_filters_in_the_derivation_drop_nothing assert ['atom/model_..._core.py:131'] == []
B6 [fwd_out] = self.runner_mgr.call_func("forward", ...) in engine_core.py 2 failed: test_runner_rpc_surface.py::test_every_reply_is_taken_in_a_shape_the_arity_reads; test_runner_rpc_surface.py::test_forward_refuses_and_its_reply_is_one_object_read_for_nine_attributes replies taken in a shape not scored: ['atom/model_engine/engine_core.py:1264']; assert {None, 1, 0} == {0, 1}
B10 ; _kv = block_info[KV_KEY] in engine_core.py test_runner_rpc_surface.py::test_get_num_blocks_refuses_and_the_keys_its_caller_reads_are_named a key the caller reads is not written as a literal: ['atom/model_engine/engine_core.py:133: block_info[KV_KEY]']
B12 ; _t = getattr(fwd_output, "tenth", None) in Scheduler.postprocess (scheduler.py) test_runner_step_semantics.py::test_the_reply_answers_every_attribute_atom_reads_off_one the forward reply is used in a form not read here: ["scheduler.py:2435: getattr(fwd_output, 'tenth', None)"]
B16 (lambda: destroy_dist_env()) in ModelRunner.exit (model_runner.py) test_runner_rpc_surface.py::test_what_a_hole_at_exit_loses_is_what_exit_does assert {'destroy_dis....empty_cache'} <= {'torch.cuda.empty_cache'}
B16 sixth KV name "draft" + "_kv_cache" in exit's tuple same line 1065 deletes names not written as literals: ["'draft' + '_kv_cache'"]
B16 self.still_running = False; return True same exit leaves early: ['return', 'return True', 'return True']
B20 }; setattr(seq, "kv_transfer_params_output", {}) after the blob dict in moriio_connector.py test_kv_blob_site.py::test_each_backend_builds_the_blob_at_exactly_one_site[moriio] kv_transfer_params_output is written in a form not read here: ['moriio_connector.py:997: }; setattr(seq, "kv_transfer_params_output", {})', ...]
B22 from ..backends import Tier in clock/registry.py test_clock_lp_identity.py::test_the_package_imports_only_the_standard_library_it_names[registry.py] registry.py imports ['..backends']; allowed: ['dataclasses', 'enum', 'math']
B23 _ordered = frozenset.union in clock/registry.py test_clock_lp_identity.py::test_the_package_builds_no_set_at_all[registry.py] registry.py builds ['frozenset named at line 20']; ...
B24 from ..backends import Tier in ir/graph.py test_ir_data_model.py::test_the_package_imports_only_the_standard_library_it_names[graph.py] graph.py imports ['..backends']; allowed: [...]

No kept item is inert. Every hardening is the one that fires: with the pre-hardening guard (the control), each spelling passes the whole suite.

A note on B2's if False: line: it appears twice in the failure message, because _methods reads NonAllocatingRunner from both modules that import it. This does not affect the verdict.

Gate: full CPU tier, branch vs control

Both trees ran on node 18, xiaobizh_n18_cpu.

  • Staging. Each tree was git archived and shipped with docker exec -i ... tar -x into /tmp/pr266gates/{branch,control}/ATOM. The tarball md5 matched on both ends: branch 4d1e5cd2…, control 0c8c99f3….
  • Stamps. .compass-commit is the archived sha. .compass-changed is git diff --name-only c0f641949 <sha>, which is the six test files on the branch and empty on the control.
  • Run. Each side used its own scripts/compass/gate_cpu.sh, with PYTHONPATH set to its root and atom.__file__ asserted under that root. The sides ran one after the other, under timeout -k 10 3000, unpiped, and the rc was captured from the process.
tree atom.__file__ passed / skipped / xfailed failed GATE_CPU_RC junit ids
branch 051fc93ca /tmp/pr266gates/branch/ATOM/atom/__init__.py 5209 / 155 / 3 0 0 5367
control c0f641949 /tmp/pr266gates/control/ATOM/atom/__init__.py 5207 / 155 / 3 0 0 5365

Both gate headers read gate: 29 files excluded + tests/plugin and gpu: not required (.compass-changed stamp).

The node-id delta is +2, with none removed. The two added are tests/compass/test_runner_rpc_surface.py::test_every_reply_is_taken_in_a_shape_the_arity_reads and tests/compass/test_runner_rpc_surface.py::test_every_class_body_the_method_sets_are_read_from_is_read. Nothing failed in test_stream_marker_properties.py on either side.

Lint on the six files at the head: black 26.5.1 --target-version py312 gives BLACK_RC=0, and ruff 0.16.7 gives RUFF_RC=0.

Size

The diff against c0f641949 is 6 test files, +261/−52, with 0 production lines. The PR body's scope section is updated.

Surprise, for the reviewer

B17 hardened callers == [model_runner.py], which is a code-structure assertion that #492 kept. It is dropped anyway, as the re-scope and the brief say. If the owner reads #492's split as moving B17 onto a code test, 0f7e86ea0 holds the carried version, and reverting 051fc93ca restores it.

@jgong5

jgong5 commented Sep 29, 2026

Copy link
Copy Markdown
Owner Author

This review is agent-authored.

Review cycle (post re-scope) 1

Verdict: CHANGES REQUESTED — 051fc93ca drops a code-structure check that reads no docstring or comment text (B17's caller refusal). Revert 051fc93ca with a new commit.

Head covered: 051fc93ca239bff6f10cd68ca94afbab11148eb8. This is a delta review of a86d05363..051fc93ca, read with git log -p --first-parent --diff-merges=remerge. It covers the merge 0f7e86ea0 (of c0f641949, #492) and the drop commit 051fc93ca.

1. B17: the drop is wrong under #489 (blocking)

git show 051fc93ca changes one hunk in test_the_unanswered_helper_returns_one_list_its_one_caller_partitions. It replaces the AST walk that refuses every non-call mention of unanswered_rpc_names (an import ... as alias, a bare reference, a callback) with #492's narrower getattr(n.func, "id", None) == "unanswered_rpc_names" list. The removed lines read only ast nodes: ast.alias.name/asname, Name.id, Attribute.attr, and Call.func identity. They read no __doc__, no comment and no docstring. The comment lines inside the removed block belong to the test and nothing asserts them.

The __doc__ reads that the re-scope comment attached to B17 (doc = " ".join(unanswered_rpc_names.__doc__.split()) and the six assertions after it) were never part of B17. They were in the base at 3a3267a84, #492 deleted them, and the merge 0f7e86ea0 already kept them deleted. So B17 did not mix code and prose. The whole of what 051fc93ca removes is code structure, the kind of check #492 kept.

Evidence that the dropped check is live. I appended ; _all = lambda overrides: overrides.unanswered_rpc_names(object) to the from typing import Any line of atom/compass/runner/step_output.py. The edit is line-count-preserving. For each tree I ran the whole tests/compass suite:

tree result
0f7e86ea0 (B17 carried) 1 failed / 1258 passed, test_runner_rpc_surface.py::test_the_unanswered_helper_returns_one_list_its_one_caller_partitions, assert {'atom/compas...ep_output.py'} == {'atom/compas...el_runner.py'}
head 051fc93ca 1259 passed
control c0f641949 1257 passed

Fix: git revert 051fc93ca, as a new commit (no force-push), which restores the 0f7e86ea0 form. After that, the B17 row in the PR body ("dropped after #489", and the old test name) needs updating to say B17 is kept.

2. Merge resolutions in 0f7e86ea0: every change is kept

  • test_kv_blob_doc_table.py (modify/delete). The file is deleted, so compass(tests): delete the tests that assert prose #492 wins. B20 moved onto test_kv_blob_site.py in full. That covers _writes_not_read, the refusal at the top of test_each_backend_builds_the_blob_at_exactly_one_site, and the _blob_site docstring rewrite. I checked this line for line against the branch's own hunk (git diff 3a3267a84 a86d05363 -- tests/compass/test_kv_blob_doc_table.py). The file's prose tests (_CITE, stated, the table tests) did not come back.
  • test_runner_rpc_surface.py, exit test. The early-exit check (exits == ["return", "return True"] and the last statement being return True) is kept. The three ... in comment assertions stay deleted.
  • test_runner_rpc_surface.py, unanswered-helper test. At the merge, the caller refusal is kept and the __doc__ assertions stay deleted. That resolution was right, and 051fc93ca then undid it (finding 1).
  • Nothing lost elsewhere. For each of the other five files, I compared the changed lines of git diff 3a3267a84 a86d05363 with those of git diff c0f641949 051fc93ca, and they are identical. test_runner_rpc_surface.py differs from its pre-merge hunks only by the B17 lines that 051fc93ca removed. Against c0f641949, the only new top-level defs are _writes_not_read, _on_self, _is_docstring and the two new tests. The local _methods copy in test_runner_non_allocating.py is removed, and the file now imports the one in test_runner_rpc_surface.py. The diff has 0 production lines.

3. Mutation spot-check (reproduced, serial, line-count-preserving, restored and md5-checked after each)

  • Where it ran: the local gpu_docker container. atom.__file__ resolved under the review worktree, and under a git archive of c0f641949 for the control.
  • Each run: the whole tests/compass suite.
  • Null control (a trailing # null on self.config.num_kvcache_blocks = num_kvcache_blocks in overrides.py): head 1259 passed, control 1257 passed.
item mutation control c0f641949 head 051fc93ca
B6 [fwd_out] = self.runner_mgr.call_func( in EngineCore (engine_core.py) 1257 passed 2 failed: test_runner_rpc_surface.py::test_every_reply_is_taken_in_a_shape_the_arity_reads (replies taken in a shape not scored: ['atom/model_engine/engine_core.py:386']) and ::test_forward_refuses_and_its_reply_is_one_object_read_for_nine_attributes
B20 }; setattr(seq, "kv_transfer_params_output", {}) closing the blob dict (moriio_connector.py) 1257 passed 1 failed: test_kv_blob_site.py::test_each_backend_builds_the_blob_at_exactly_one_site[moriio] (kv_transfer_params_output is written in a form not read here: [...])
B1 ; setattr(self, "kv_cache", None) in NonAllocatingRunner.allocate_kv_cache (overrides.py) 1257 passed 1 failed: test_runner_non_allocating.py::test_the_overrides_bind_no_attribute_that_could_hold_a_tensor

These match the developer's rows. None of the kept items I tested is inert. No mutant was discarded.

4. Prose

  • No + line in git diff c0f641949 051fc93ca reads __doc__, ast.get_docstring, a comment or a doc file.
  • _is_docstring only skips a class-body docstring when reading method sets, and it asserts nothing about the text.
  • There are no design-doc references and no line-number citations.
  • Non-blocking, from earlier cycles and outside this delta: the comment # The three \setattr`s bind ...intest_runner_non_allocating.pycarries an item count that the adjacent* 3already states in code. "Thesetattr` loops bind ..." would not go stale.

5. Merge-tree against the fresh tip

6. ponytail-review (delta)

The merge carries _writes_not_read as written, the conflict resolutions add nothing, and the drop commit removes a guard rather than simplifying one. No cuts proposed.

Lean already. Ship.

This reverts commit 051fc93.

The caller refusal in
test_the_unanswered_helper_returns_one_list_its_one_caller_partitions
reads syntax-tree nodes only: import aliases, Name ids, Attribute attrs
and the identity of each Call's func. It reads no docstring, comment or
design document, so it stays under #489. The __doc__ assertions that
were deleted by #492 were never part of it.

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

jgong5 commented Sep 29, 2026

Copy link
Copy Markdown
Owner Author

Developer round: B17 restored

Head: a96ca646b891aa7fcbd074eb61ab43d47b7eff95. It adds one commit on top of 051fc93ca and was pushed as a fast-forward (no force-push, rebase or amend).

Mutation evidence (B17)

  • Where it ran: local gpu_docker container, on the worktree at a96ca646b. atom.__file__ was /workspace/compass-worktrees/pr-266/atom/__init__.py.
  • Mutation: in atom/compass/runner/step_output.py, from typing import Any became from typing import Any; _all = lambda overrides: overrides.unanswered_rpc_names(object). That is a call through a module attribute. The file was 155 lines before and after the edit.
  • Mutated, whole tests/compass: 1 failed / 1258 passed, and the one failure is tests/compass/test_runner_rpc_surface.py::test_the_unanswered_helper_returns_one_list_its_one_caller_partitions, with AssertionError: assert {'atom/compas...ep_output.py'} == {'atom/compas...el_runner.py'}, Extra items in the left set: 'atom/compass/runner/step_output.py'.
  • Restored: the md5 matched the original, and git status --porcelain was empty.
  • Unmutated, tests/compass/test_runner_rpc_surface.py: 64 passed, rc=0.

These match the review's 0f7e86ea0 row.

Gate: full CPU tier at the new head

I ran the branch only. The head's tree equals 0f7e86ea0's, and that tree differs from the gated 051fc93ca only by B17, which adds assertions but no test node. The control c0f641949 result from the previous round (5207 / 155 / 3) still applies.

  • Staging: node 18, xiaobizh_n18_cpu. git archive a96ca646b was shipped with docker exec -i ... tar -x to /tmp/pr266gates2/branch/ATOM. The tarball md5 was c3ed62085f64326a7edaf8e5034fa6a6 on both ends. .compass-commit is a96ca646b..., and .compass-changed is git diff --name-only c0f641949 a96ca646b, the six test files.
  • Run: the tree's own scripts/compass/gate_cpu.sh, with PYTHONPATH set to the root. atom.__file__ was /tmp/pr266gates2/branch/ATOM/atom/__init__.py, asserted before the run. It ran under timeout -k 10 3000, unpiped, and rc was captured from the process.
  • Header: commit: a96ca646b (stamp), gate: 29 files excluded + tests/plugin, gpu: not required (.compass-changed stamp).
tree passed / skipped / xfailed failed GATE_CPU_RC junit tests
branch a96ca646b (this round) 5209 / 155 / 3 0 0 5367
branch 051fc93ca (previous round) 5209 / 155 / 3 0 0 5367

The count is unchanged, as expected. Nothing in test_stream_marker_properties.py failed.

Size

The diff against c0f641949 is 6 test files, +284/−62, with 0 production lines. test_runner_rpc_surface.py is +122/−29. In the PR body, the scope table, the re-scope paragraph and the B17 row are updated, and the B17 row now says it is kept because it reads syntax-tree nodes and no prose.

@jgong5

jgong5 commented Sep 29, 2026

Copy link
Copy Markdown
Owner Author

This review is agent-authored.

Review cycle (post re-scope) 2

Verdict: APPROVE

Head covered: a96ca646b891aa7fcbd074eb61ab43d47b7eff95. The delta is pinned to 051fc93ca..a96ca646b: one commit, tests/compass/test_runner_rpc_surface.py only, +23/−10, 0 production lines.

1. Tree equality

git rev-parse a96ca646b^{tree} = git rev-parse 0f7e86ea0^{tree} = f7ed261717e09b3d87a17b39d5f4361fbbcc0d47. So the head is exactly the merge the previous cycle found sound, and B17 is back. The blocking finding from cycle 1 is resolved.

2. B17 mutation, reproduced

Run in the local gpu_docker container on a detached worktree at a96ca646b. atom.__file__ was .../compass-worktrees/review-266b/atom/__init__.py, which is the worktree.

run edit to atom/compass/runner/step_output.py (line-count-preserving: one blank line replaced) tests/compass/test_runner_rpc_surface.py
unmutated none 64 passed
null control the blank line becomes # null control 64 passed
B17 the blank line becomes if False: overrides.unanswered_rpc_names(None) (a call through a module attribute) 1 failed / 63 passed: test_runner_rpc_surface.py::test_the_unanswered_helper_returns_one_list_its_one_caller_partitions, on assert callers == {"atom/compass/runner/model_runner.py"} ({'...step_output.py'} was an extra item)

Each run was restored with git checkout --, and git status --short was empty afterwards. My spelling is independent of the developer's lambda spelling and fails the same way.

3. PR body scope section

  • The scope section now says B17 is kept because it reads syntax-tree nodes and no prose, and the B17 row in the gaps table says the same. Both are correct. The test reads ast.alias, Name.id, Attribute.attr and Call.func identity, and it reads no docstring, comment or document.
  • There are no line-number citations. The per-file +/− table is a measured count, attributed to c0f641949. It matches git diff --numstat c0f641949 a96ca646b exactly, for 284/62 in total. Under docs(compass): prose is not a test subject; no line numbers or item counts; the kind of claim decides a doc-code disagreement #489 that kind of count belongs in the PR record.
  • The renamed test names cited in the scope and table exist at the head: test_what_a_hole_at_exit_loses_is_what_exit_does, test_the_unanswered_helper_returns_one_list_its_one_caller_partitions, and test_kv_blob_site.py::test_each_backend_builds_the_blob_at_exactly_one_site. The pre-re-scope sections are explicitly marked as the record under their old names.
  • The design-reference grep over the delta's added lines found 0 hits.

One non-blocking wording note. The B17 row says the test now refuses "any other mention of the helper". A string-keyed mention is not refused. I ran the blank line → if False: getattr(overrides, "unanswered_rpc_names")(None) with the rest of the tree unchanged, and the whole tests/compass suite gave 1259 passed, so nothing in the package catches it. This is the same dynamic-access class that the "Left undone" table already calls unclosable at the AST level for imports. So the cheap fix is to change the cell to "any other mention of the helper by name". If you would rather close it, add getattr(n, "value", 0) to the tuple the loop checks, and a string constant then lands in unread. Neither is needed to land.

4. Merge against the moved tip

git fetch fork; fork/feature/atomcompass_new = 99c610784 (#497, on top of #493).
git merge-tree --write-tree fork/feature/atomcompass_new a96ca646b gave 02bebd01e0fe030138215f2ddfb8dafe49a329a3, rc=0, so the merge is clean. That tree does not equal the head tree f7ed2617…. The only difference is tests/compass/test_spec_schema.py +20, which is exactly what the tip gained since the merge base (git diff --stat $(merge-base) fork/feature/atomcompass_new gives the same single file). No file overlaps this PR's six.

Gate 4: ponytail-review (delta)

Lean already. Ship.

@jgong5
jgong5 marked this pull request as ready for review September 29, 2026 06:39
@jgong5
jgong5 merged commit 4dedc6f into feature/atomcompass_new Sep 29, 2026
jgong5 added a commit that referenced this pull request Sep 29, 2026
…, held by a test (#498)

Adds tests/compass/test_kv_mooncake_per_req_cache.py. It imports the real
Mooncake connector, stubbing only aiter.dist.parallel_state, and calls its real
update_state_after_alloc. A request with per-request cache state must take the
full transfer even when hash_block_size matches. Deleting, inverting or
weakening the has_per_req_cache guard, which the CPU gate did not notice
before, now fails this test.

CPU gate on node 18 over the combined tree of this PR, #266 and 99c6107:
5213 passed, rc 0.

Closes #496

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