Skip to content

fix(distcheck): stop the node flow's integration guard restating a retired layout - #999

Merged
thekevinscott merged 2 commits into
mainfrom
claude/tackle-996-7xngyz
Aug 20, 2026
Merged

thekevinscott merged 2 commits into
mainfrom
claude/tackle-996-7xngyz

Conversation

@thekevinbot

Copy link
Copy Markdown
Collaborator

Fixes #996

Problem

internals/distcheck/tests/integration/node_flow_test.py builds its skip guard from two identifiers #739 deleted (bundled-cli-<slug> and Platform.bin_name), so the attribute lookup blows up before the skip it feeds:

E   AttributeError: 'Platform' object has no attribute 'bin_name'
internals/distcheck/tests/integration/node_flow_test.py:28: AttributeError

Reproduced verbatim on main before touching anything. The node flow's only real-subprocess coverage has not executed since #739.

Change

The root cause is that the guard restates the gate's prerequisite instead of asking for it. So rather than re-deriving the current layout in a second place (which is the same drift again, one rename later), gate.py exports the path:

  • staged_addon_path(ts_pkg, host) — the one build prerequisite, used by run() and by the integration guard. A layout change now moves one expression, and gate_test.py pins that run()'s prerequisite is the helper's output.
  • node_flow_test.py guards on staged_addon_path(_TS, host); npm/pnpm guard kept.
  • gate.py docstring and README.md:34 corrected from the retired @dirsql/cli-<slug> / resolve-binary.ts wording to @dirsql/lib-<slug> / loadNativeCore().

On the issue's open question for item (3) — a docstring-only edit to src/ tripping colocated-test's co-change sub-check: taken as the "land it alongside a gate_test.py change that earns its own keep" branch. The new assertion is not ceremony for the gate; nothing previously tied run()'s prerequisite to anything a caller could reference, which is what let the drift happen.

Validation

Raise → skip → pass transition observed directly, as #996 asks:

state result
before AttributeError: 'Platform' object has no attribute 'bin_name' (hard red)
after, no pnpm build SKIPPED [1] staged addon absent (pnpm build in packages/ts)
after, with pnpm build 1 passed — real npm pack / pnpm pack / npm install / dirsql --version

Gate runs and the full local command list are in a comment below.

E2E Verification

N/A - repo tooling only — no change under packages/*/src, packages/ts/napi, or packages/rust. No attestation receipt is owed (internals/distcheck is in no e2e scope).

  • Ran e2e suites locally for every affected SDK — N/A, no SDK affected
  • Python SDK e2e: N/A
  • TypeScript SDK e2e: N/A
  • Rust core e2e (if applicable): N/A
  • packages/python/e2e-attestations/<branch>.json receipt written if packages/python changed — not changed
  • packages/ts/e2e-attestations/<branch>.json receipt written if packages/ts changed — not changed
  • Command(s) run: N/A
  • Result summary: N/A

Changelog / Migrations

  • Changelog fragment — not required: internals/ is not a changelog root (_ROOTS = ("packages", "plugins") in changelog_gate/decide.py), and nothing published changes.
  • Migration fragment — not required: repo tooling, no public API.

PARITY.md unaffected — no SDK public API touched.


Generated by Claude Code

claude added 2 commits August 20, 2026 21:00
`node_flow_test.py`'s skip guard restates the staged-artifact layout instead
of asking the gate, and the layout it restates was deleted in #739 -- so the
guard raises `AttributeError: 'Platform' object has no attribute 'bin_name'`
before it can skip, and the node flow's only real-subprocess coverage has not
run since.

Assert the contract that removes the restating: `run()`'s prerequisite is
exactly `staged_addon_path()`'s output. `staged_addon_path` does not exist
yet, so this collection-errors.

Refs #996
…uires

The node flow's integration guard restated the staged-artifact layout, and
#739 deleted the layout it restated -- `bundled-cli-<slug>` and
`Platform.bin_name` -- so it raised `AttributeError` before reaching the skip
it feeds. Re-deriving the current layout in a second place would be the same
drift again, one rename later, so export the path instead:
`staged_addon_path()` is the flow's one build prerequisite, and `run()` and
the guard both call it.

Also correct the two places still describing the retired standalone-CLI
sub-package: `gate.py`'s module docstring and README's `node` bullet now say
`@dirsql/lib-<slug>` / `loadNativeCore()`, matching what `run()` packs.

Fixes #996

Copy link
Copy Markdown
Collaborator Author

Validation transcript

Red/green. The RED commit (8db8b13) was pushed alone and CI was observed red for the right reason — run 32417247161, both coverage jobs:

distcheck/node_flow/gate_test.py:12: in <module>
    from distcheck.node_flow.gate import (
E   ImportError: cannot import name 'staged_addon_path' from 'distcheck.node_flow.gate'

Static checks and Unit mutation — changed lines passed on that same run, so nothing unrelated was failing. GREEN is cc768a1.

The raise → skip → pass transition, observed directly as #996 asks (uv run python -m pytest tests/integration/node_flow_test.py -q -rs in internals/distcheck):

# before the fix
E   AttributeError: 'Platform' object has no attribute 'bin_name'
internals/distcheck/tests/integration/node_flow_test.py:28: AttributeError

# after the fix, build/ moved aside
SKIPPED [1] tests/integration/node_flow_test.py:28: staged addon absent (pnpm build in packages/ts)
1 skipped in 0.01s

# after the fix, addon staged by `pnpm build`
1 passed in 2.95s

pnpm build staged the addon at packages/ts/build/linux-x64-gnu/dirsql.linux-x64-gnu.node — exactly what staged_addon_path returns, which is the point of routing both callers through it.

The command #996 names as a hard red for anyone running it now comes back clean:

$ uv run python -m pytest src tests -q
67 passed, 1 skipped in 2.76s

(the one skip is python_flow_test.py on absent maturin — the correct post-#993 behavior).

Manual exercise of the user-visible entry point, per AGENTS.md:

$ uv run --project internals/distcheck dirsql-distcheck node
node packaging distcheck: OK          # exit 0

That is the real npm pack / pnpm pack / npm install / dirsql --version path, no mocks.

Gates run locally (all clean): unit colocated-test 0 · unit lint 0 · integration lint 0 · unit coverage 100% (floor 100) · unit mutation --base origin/main 0 survivors.

Why mutation reports "0 mutant(s) tested" on this diff

That is a real zero, not a misfire. The added lines are a docstring, return os.path.join(...), and an assignment from a call — none of which cosmic-ray's core operators (numbers, comparisons, booleans, side-effect statements) can mutate. Confirmed the engine is live by running it unscoped over the package, which finds 184 mutants; all 184 are in *_test.py files and none in source. They are pre-existing and whole-tree, which is exactly why CI scopes this gate to the PR diff.

Two invocation notes for whoever runs these next, both of which cost time here:

  • unit lint / integration lint reject --base (error: unexpected argument '--base' found) — pass only --language / --config.
  • unit mutation must run from the repo root with a repo-relative source path. Run from inside internals/distcheck with a bare src, it silently reports 0 mutant(s) tested because the changed-file paths never match the scan root — a false pass that looks identical to a real one.

One thing found and deliberately not folded in

Platform.exe in node_flow/platforms.py is a vestige of the same #739 change: packages/ts/src/platforms.ts, which that dataclass documents itself as mirroring, has no exe field at all, and nothing in internals/distcheck reads it outside its own tests (platforms_test.py lines 30/42/65). One of those tests already carries a comment noting the .exe suffix belonged to the retired standalone binary.

Left alone: #996 scopes itself to items 1–4, removing it touches a second module pair, and a prior pass evidently looked straight at it and chose to keep it. Flagging rather than filing, since whether the mirror should track platforms.ts field-for-field is a maintainer call.


Generated by Claude Code

@thekevinscott
thekevinscott merged commit 3180e9a into main Aug 20, 2026
8 checks passed
@thekevinscott
thekevinscott deleted the claude/tackle-996-7xngyz branch August 20, 2026 21:40
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.

distcheck: node flow's @dirsql/cli-<slug> prerequisite left behind by #739 (integration test raises, stale gate docstring + README)

3 participants