Every Python file and executable in tooling/ assigned to one of 15 domains, with the ambiguous cases carrying their reasoning. The per-domain port tickets are written from this rather than guessed, so their boundaries do not have to be renegotiated halfway through a 160-file move. Three things counting turned up that reading would not have. The Blender carve-out is 35 files, not the 13 visible at top level — 22 more are inside garment-fit/, which turns out to be a payload directory wearing a domain's name. The epic said 35 and an earlier survey of mine said 14; the epic was right. That is not cosmetic: `character` is a far smaller domain than directory sizes imply, and a port ticket written from the listing would have been wrong about both it and the carve-out. The "28 singleton prefixes" were an artefact of splitting filenames on the first token, which scattered coherent families — sculpt-star-map, tune-star-map-topology and generate-star-map* are one group counted as three orphans. Counting families instead, the genuinely ambiguous set is small enough to enumerate with reasons. And tooling/db/ is misnamed: it holds the audio/image/Trellis connectors and wiki_sync, while the actual database work is in economy-db/. Naming a domain after that directory would have carried the misnomer forward. Judgment calls settled with reasons, since each sets a precedent. Registries stay data rather than becoming verbs nobody would type. Gate tests do not become a `test` domain implying a runner that does not exist. pql-migrate is provenance — archived, not deleted and not importable. `pr` is a domain the epic omitted, kept out of `dev` so dev does not become the drawer everything ambiguous goes into. And `atlas` is overloaded across three unrelated places — map data, terrain quality analysis, and systems.db index tables — which stay with their owners rather than being collected into a domain whose only common thread is a noun. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.2 KiB
The domain map (T-1271, D-263)
Every Python file and every executable in tooling/, assigned to a domain
before anything moves. This is the artefact the per-domain port tickets are
written from — without it their boundaries would be guesses, renegotiated
halfway through the move.
Status: map only. Nothing here has moved yet except check client-version,
which shipped in T-1262 as the reference implementation.
What the survey changed
Two corrections to the T-1250 description, both found by counting rather than reading:
- Three Rust crates, not one.
econ-sim,line-previewerandtest-clientare all Cargo projects with zero.pyfiles. None is renamed and none moves; a hyphen only matters for something Python must import. - The "28 singleton prefixes" were an artefact of my own measurement.
Splitting filenames on the first token scattered coherent families:
sculpt-star-map,tune-star-map-topologyandgenerate-star-map*are one group, not three orphans. Counting families instead of prefixes, the genuinely ambiguous set is small and is listed under Judgment calls below.
And two found while reading the tree:
garment-fit/is mostly a Blender payload directory. 22 of its 23 files areblender_author_*.py, leaving one real module. So the Blender carve-out is 35 files, not the 13 visible at top level — the T-1250 description was right about 35 and an intermediate survey of mine was wrong, because it counted only the top level. The consequence is not cosmetic:characteris a much smaller domain than the directory sizes imply, and the carve-out is much larger.tooling/db/is misnamed. It holds the audio/image/Trellis connectors andwiki_sync.py— the actual database work is ineconomy-db/. Naming a domaindbafter that directory would carry the misnomer forward, so its contents split betweenassetsandwikiinstead.
Domains
| domain | what it is | sources |
|---|---|---|
check |
repo consistency gates the push hook runs | check-client-version ✅, check-canvas-version, check-systems-db-stamp, check-fact-ids, check-dataflow-graph.py |
validate |
content and schema validation | validate-content, validate-checklist, validate-ron |
atlas |
the Atlas map data surface | atlas, atlas-check, atlas-names, atlas-commit-and-sync, atlas-systems-done, atlas-update-field, atlas-verify, atlas-flatness |
starmap |
the star map and its renders | generate-star-map.py, generate-star-map-data.py, generate-star-map-svg.py, sculpt-star-map.py, tune-star-map-topology.py, star-map-seed.json |
planet |
planetary generation and its guards | planet-gen/ (30 files) |
db |
the economics DB pipeline | economy-db/ (17 files), schema_version.py |
wiki |
wiki sync and content maintenance | wiki/, db/wiki_sync.py, db/populate_gttr_hook.py, db/backfill_cultural_corridor.py, assign-astro-ids.py, fill-missing-globes.py, migrate-s-to-gj.py, patch-core-sector.py, process-wiki-system-changes |
assets |
connectors to the tower-of-joy generators | db/audio_*.py, db/audio-*, db/image_connector.py, db/trellis_connector.py, db/common.py, trellis-batch.sh, synth_ui_sounds.py |
character |
bodies, garments, GLB handling | garment-fit/make_logo.py, garment-qa/analyze_captures.py, convert_outfit.py, glb_strip_utility_nodes.py, inspect_glb.py, check_hair_symmetry.py, check_icosphere.py, render_quaternius_test.py, setup_clothing_metadata.py — note this is far smaller than garment-fit/'s file count suggests; 22 of its 23 files are Blender payloads and belong to the carve-out |
visual |
screenshot and render comparison | visual-diff, visual-thumbnail, visual-blank-check |
godot |
Godot parse and cold-start checks | godot-parse-sweep, godot-cold-parse |
generate |
content generators not owned elsewhere | generate-brands, generate-corporations, generate-character-manifest, generate_corp_stubs.py |
dev |
developer environment and workflow | install-rust, install-godot, worktree-setup, perf-baseline, clerk-review |
pr |
the PR/review loop | tea-comment, pr-watchlist-diff, pql-board-html |
blender |
carve-out — payloads run by Blender | 35 blender_*.py (13 top-level + 22 in garment-fit/), blender wrapper → tooling/scripts/blender/ |
Judgment calls, with reasons
Each of these sets a precedent, so the reasoning matters more than the answer.
Registries stay module-level data, not commands. canvas_sources.py and
generator_sources.py are lists of paths consumed by gates — nothing types them.
They move beside the domain that reads them (check and db respectively) as
plain modules, not verbs. Making them commands would put something in
reach --help that answers no question a person has.
schema_version.py belongs to db, and check imports it. It is consumed
by the economics importer and by the stamp gate. Shared, but not equally
owned: the importer defines the version, the gate reads it. It goes where it is
defined, and the cross-domain import is legitimate — that is what a service
layer is for.
test_*.py files do NOT become a domain. They are gate tests run by
make test-tooling, not commands anyone types. reach test … would imply a
test runner that does not exist. They stay standalone scripts.
pql-migrate/ is provenance, not tooling. One-shot scripts from a completed
migration, already documented as such in .claude/rules/project-structure.md.
They are not live tools and must not become verbs. Move to tooling/archive/,
excluded from package discovery — deleting them would destroy migration
provenance, and keeping them importable would imply they still run.
pr is a domain the epic did not list. tea-comment and pr-watchlist-diff
are the PR/review loop, which is neither dev (environment setup) nor anything
else on the original list. Folding them into dev would make dev the drawer
everything ambiguous goes into — which is how core/ rots, and the same
argument applies here.
atlas is overloaded, and the port must not merge the three uses. The word
appears in three unrelated places: the top-level atlas-* executables (the map
data surface), planet-gen/atlas_*.py (atlas_cohesion_audit,
atlas_common, atlas_quality_analysis — quality analysis of generated
terrain), and economy-db/atlas.py (the atlas index tables in systems.db).
These are three concerns sharing a noun, not one domain in three places. Each
stays with its owner — atlas, planet and db respectively — and the port
should resist the pull to collect them, which would produce a domain whose only
common thread is a word.
economy-db/errors.py predates core/errors.py and is not the same thing.
Domain-local error types are fine; what must not happen is a silent merge, or a
second ReachError with different semantics. Reconcile explicitly when db is
ported.
character rather than garment. D-263's sketch says garment, but the
files cover bodies, hair, GLB utilities and Quaternius imports as well as
clothing. Naming it for one of its five concerns would leave the other four
looking misfiled.
Not moving
| what | why |
|---|---|
econ-sim/, line-previewer/, test-client/ |
Rust crates. Excluded from package discovery; hyphens are harmless. |
scripts/blender/ (after T-1273) |
Run under Blender's bundled Python; cannot import tooling.core. Excluded from the conformance scope for the same reason. |
archive/ (was pql-migrate/) |
Completed-migration provenance. |
test_*.py |
Gate tests, not commands. |
Naming, applied on the way in
- Modules
snake_case:check-dataflow-graph.py→dataflow_graph.py. - Verbs
kebab-case:reach check dataflow-graph. - No prefix-as-namespace. The domain directory supplies what the
blender_,atlas-andcheck-prefixes were doing by hand.atlas-verifybecomesreach atlas verify, notreach atlas atlas-verify. - Layering is a vocabulary, not a quota. A domain with only a router and a
service gets exactly those two files. Empty
schemas.pyanddependencies.pyare worse than absent ones — they suggest a shape the domain does not have.