Skip to content

Make the two build scripts importable, and read the real prefix lists - #108

Merged
realmarcin merged 1 commit into
mainfrom
fix/importable-pipeline-scripts
Sep 22, 2026
Merged

realmarcin merged 1 commit into
mainfrom
fix/importable-pipeline-scripts

Conversation

@realmarcin

@realmarcin realmarcin commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Closes #97 and #101.

The problem

build_subsets.py resolved every Mech checkout at import — MECHS calls mech_root, which exits when one is missing — then scanned the corpora. build_data.py read both JSON inputs at import and rewrote fleet_data.json. Neither could be imported to look at a constant.

The refactor

Both keep only pure constants at module level. build_subsets grew a prepare() that resolves checkouts and indexes HabitatMech's pages; everything from the scan onward moved into main(). Function bodies are untouched and still refer to the same module-level names, so MECHS, hab_pages and friends are declared empty and filled by prepare() rather than moved into it. build_data grew build() and main().

Importing either is now free and writes nothing.

The payoff: #101 retired, not narrowed

The tests had to recover VOC and PREF from the source text with ast, which cannot see a list rebuilt after its literal. That was the hole #99 closed partly and #101 recorded the rest of. Reading the real objects retires the class:

mutation after the literal source parser real import
VOC, _X = [...], 1 passed FAILED
del VOC[0] passed FAILED
VOC[0] += "X" passed FAILED
VOC += [...] FAILED FAILED
VOC.append(...) FAILED FAILED

literal() and its mutator allowlist are deleted along with the parsing they served.

Verified behaviour-preserving

Ran both scripts before and after the refactor over the same checkouts and compared every output file. assets/fleet and subsets_summary.json match semantically: identical per-Mech scan counts, identical edge weights and by breakdowns, identical term lists in identical order, every term entry equal.

One edge file differs by bytes only, and it is not this refactor:

run A  "by":{...,"CAS":1,"ENVO":1}
run B  "by":{...,"ENVO":1,"CAS":1}

Same length, same content. CAS and ENVO are tied, and Counter.most_common() breaks ties by insertion order, which comes from iterating a set of strings under per-process hash randomization. Filed as #107 — it means a refresh churns committed assets for no reason, and the pipeline cannot be used to verify itself.

No committed data changes here; the verification runs' output was restored.

27 tests and assemble_page.py --check pass.

Review fixes

Rebased over #105, carrying its CITATION filter into main(). From the adversarial review: main() now calls prepare() itself, so importing the module and calling main() resolves the checkouts instead of failing with a KeyError inside scan() (closes #117); the unused import ast is gone (closes #116). Left filed: #118 (unclosed handles and non-atomic writes).

🤖 Generated with Claude Code

`build_subsets.py` resolved every Mech checkout at import — `MECHS` called
`mech_root`, which exits when one is missing — and then scanned. `build_data.py`
read both JSON inputs at import and rewrote fleet_data.json. Neither could be
imported to look at a constant (#97).

Both now keep only the pure constants at module level. `build_subsets` grew a
`prepare()` that resolves the checkouts and indexes HabitatMech's pages, and
everything from the scan onward moved into `main()`; the function bodies are
untouched and still refer to the same module-level names, so `MECHS`,
`hab_pages` and the rest are declared empty and filled by `prepare()` rather
than moved. `build_data` grew `build()` and `main()`, with the same treatment.
Importing either is now free and writes nothing.

That lets the tests read the lists the pipeline actually uses. They had been
recovered from the source text with `ast`, which cannot see a list rebuilt
after its literal — the hole #99 closed partly and #101 recorded the rest of.
Reading the objects retires the class: all five shapes now fail, including the
three the parser could not see.

    VOC, _X = [...], 1     parser: passed   import: FAILED
    del VOC[0]             parser: passed   import: FAILED
    VOC[0] += "X"          parser: passed   import: FAILED
    VOC += [...]           parser: FAILED   import: FAILED
    VOC.append(...)        parser: FAILED   import: FAILED

`literal()` and its mutator allowlist are gone with the parsing they served.

Verified behaviour-preserving by running both scripts before and after the
refactor over the same checkouts and comparing every output file. `assets/fleet`
and `subsets_summary.json` match semantically: identical per-Mech scan counts,
identical edge weights and `by` breakdowns, identical term lists in identical
order, every term entry equal.

One edge file differs by bytes, and it is not this refactor. `CAS` and `ENVO`
are tied at 1 in that edge's `by`, and `Counter.most_common()` breaks ties by
insertion order, which comes from iterating a set of strings under per-process
hash randomization. Filed as #107, since it means a refresh churns committed
assets for no reason and the pipeline cannot be used to verify itself.

No committed data changes here; the runs' output was restored.

Rebased over #105, carrying its CITATION filter into main(). From the review:
main() now calls prepare() itself, so importing the module and calling main()
resolves the checkouts instead of failing with a KeyError inside scan()
(closes #117); the unused `import ast` left behind by literal()'s removal is
gone (closes #116).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@realmarcin
realmarcin force-pushed the fix/importable-pipeline-scripts branch from 0bbe30b to 0c7875f Compare September 22, 2026 07:26
@realmarcin
realmarcin merged commit 26e02a6 into main Sep 22, 2026
1 check passed
@realmarcin
realmarcin deleted the fix/importable-pipeline-scripts branch September 22, 2026 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant