From bb329e3294a945b3f3281a849735b8893c1917ed Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Wed, 2 Sep 2026 18:19:51 +0200 Subject: [PATCH] =?UTF-8?q?chore(meta):=20T-1287=20through=20T-1290=20?= =?UTF-8?q?=E2=80=94=20the=20manifest=20bug=20and=20the=20remaining=20port?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit T-1287 records the generator/artifact divergence the push gate caught: 'make manifest' silently drops the style and logo_capable fields T-1089 added to the schema but never taught the generator to emit. T-1288/1289/1290 give the port epic its remaining work-list — planet-gen (30 files), economy-db as 'ledger' (17), and the wiki/assets/character tail (~26). ledger blocks on the hyphen sweep because its sys.path bootstrap only exists because economy-db cannot be imported; the tail blocks on the Blender carve-out because 22 of garment-fit's 23 files must never import the package. Co-Authored-By: Claude Opus 5 --- .pql/changelog/ticket_deps/2026-09.sql | 2 + .pql/changelog/ticket_history/2026-09.sql | 88 ++++++++++++++++++++++ .pql/changelog/ticket_idmap/2026-09.sql | 3 + .pql/changelog/tickets/2026-09.sql | 91 +++++++++++++++++++++++ 4 files changed, 184 insertions(+) create mode 100644 .pql/changelog/ticket_deps/2026-09.sql diff --git a/.pql/changelog/ticket_deps/2026-09.sql b/.pql/changelog/ticket_deps/2026-09.sql new file mode 100644 index 000000000..24afca96f --- /dev/null +++ b/.pql/changelog/ticket_deps/2026-09.sql @@ -0,0 +1,2 @@ +INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G5FZCVZXH6M00C57EXMZD0SG', '06G65T2N1WAT491WY8SV736J3G', '2026-09-02 16:19:43.328', '2026-09-02 16:19:43.328', NULL, '5ce8ab5d4936aef2df0ca4b5153e2d40', 2) ON CONFLICT(blocker_record_id, blocked_record_id) DO UPDATE SET updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= ticket_deps.updated_at; +INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G5FZDN9YBP0MZ021N3TJCFXM', '06G65TC359QGCVBEPXHJ4N0MRG', '2026-09-02 16:19:43.349', '2026-09-02 16:19:43.349', NULL, '66d337f0362c0ecf64a4c4065a97d485', 2) ON CONFLICT(blocker_record_id, blocked_record_id) DO UPDATE SET updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= ticket_deps.updated_at; diff --git a/.pql/changelog/ticket_history/2026-09.sql b/.pql/changelog/ticket_history/2026-09.sql index abd1cc77f..733e634b7 100644 --- a/.pql/changelog/ticket_history/2026-09.sql +++ b/.pql/changelog/ticket_history/2026-09.sql @@ -155,3 +155,91 @@ identical values costs whoever hits it real time. Acceptance: `reach generate character-manifest` on a clean tree leaves manifest.json byte-identical, and the T-1089 test still passes after it runs.', NULL, '2026-09-02 15:54:41', '2026-09-02 15:54:41.911', '2026-09-02 15:54:41.911', NULL, '1a36359b2986139da3157d2429351f74', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65NSJ4RG6SJ12TQE78S6TKR', 'description', NULL, 'The largest single port left: `tooling/planet-gen/` (30 Python files) becomes +`reach atlas planet `, the third rung of the spatial ladder (D-243), per +the nesting the domain map fixed in T-1271 — `planet` is NOT a top-level domain, +it lives under `atlas` because atlas coordinates world-location generation. + +BEFORE MOVING ANYTHING, check `__file__`-relative roots. Five ports so far have +hit this and it fails SILENTLY: a script that computed `Path(__file__).parent.parent` +as the repo root resolves somewhere else once it lives two directories deeper, +and the usual symptom is a gate that reports "nothing to check, OK" and exits 0. +`validate-checklist` did exactly that. Grep for `__file__` first and convert to +`config.repo_root()` / `config.path(...)` as part of the move, not after. + +WATCH the ones that are already gated: +- `test_sim_determinism.py` and `test_oasis_ring_scaling.py` are run by + `make test-tooling` and must keep working — they are tests, not verbs. Decide + whether they move with the domain or stay as test scripts, and update the + Makefile either way. +- Anything registered in `tooling/canvas_sources.py` (the canvas-generation + version gate, T-1242) — moving a path there without updating the registry + breaks `make check-canvas-version`, which has no override. +- `import_heightmaps` / `import_province_boundaries` are one-time build imports, + deliberately NOT stamped (`.claude/rules/asset-pipeline.md`). Do not fold them + into the regen path while porting. + +Standard port acceptance as on T-1281/T-1286: output parity (exit codes match +exactly, no fact lost, failures name a remedy), every command carries `@command`, +nothing prints but `console`, no `subprocess` outside `core/process`.', NULL, '2026-09-02 16:16:24', '2026-09-02 16:16:24.021', '2026-09-02 16:16:24.021', NULL, 'e657bda60a8641aab38e714d9611a9f8', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65T2N1WAT491WY8SV736J3G', 'description', NULL, '`tooling/economy-db/` (17 files) + `schema_version.py` become `reach ledger`. + +The name is deliberate and is the user''s call (D-263 amendment): reach verbs +mirror the game''s implant-app presentation patterns. `ledger` is the player-facing +component that will aggregate economics — browse markets, wealth, transactions — +the way `atlas` aggregates topography. The tooling verb takes the same name so the +CLI and the UI do not diverge into two vocabularies for one subject. + +THIS IS THE HIGHEST-RISK PORT IN THE EPIC and the reason E5 (T-1252) exists as a +separate epic: `import_economics` is the SOLE generator of `server/data/systems.db`, +and its meta stamp is computed over a source-file registry. Two things bite: + +1. `tooling/generator_sources.py` lists every stamped path. Moving a file without + updating the registry either breaks the import (missing path) or silently + changes the SHA. T-1286 already had to swap the retired `generate-brands` + wrapper for `core/process.py` there and regen. Expect the same. +2. `economy-db` is hyphenated, so it is NOT importable as a package. `brands.py` + currently bootstraps `sys.path` with REPO_ROOT to reach `tooling.core` — see + the comment there. That bootstrap should DISAPPEAR in this port, not be + copied; it exists only because the directory could not be imported. Overlaps + T-1272 (hyphen sweep) — do them together or in that order. + +Every port of this domain ends with `make regen-db` + `reach check systems-db-stamp` ++ a commit of `server/data/systems.db`. `generated_brands.toml` must come back +byte-identical; if it does not, the port changed generator behaviour and that is +a bug, not a regen. + +Standard port acceptance as on T-1281/T-1286.', NULL, '2026-09-02 16:17:43', '2026-09-02 16:17:43.245', '2026-09-02 16:17:43.245', NULL, '08c8880187594a4dead79878792f2a9a', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65TC359QGCVBEPXHJ4N0MRG', 'description', NULL, 'The tail of the tree — three domains, ~26 files, batched because none of them +entangles with the spatial ladder or the systems.db stamp. + +`reach wiki` — `tooling/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`. +READ `Skill(wiki)` FIRST. The wiki has two ownership models running in opposite +directions and these tools sit on the seam: `star-systems/` (93% of the wiki) is +OUTPUT generated FROM systems.db by `wiki_sync.py`, while the flat categories are +INPUT. A verb that writes to the wrong side is silently reverted on the next sync. +Several of these are one-shot migrations (`migrate-s-to-gj`, `patch-core-sector`) — +decide per file whether it is a live verb or provenance bound for `tooling/archive/`, +the same call T-1271 made for `pql-migrate/`. + +`reach assets` — `db/audio_*.py`, `db/audio-*`, `db/image_connector.py`, +`db/trellis_connector.py`, `db/common.py`, `trellis-batch.sh`, `synth_ui_sounds.py`. +These call tower-of-joy over the network (Stable Audio :11500, Trellis :11510, by +IP per `.claude/rules/local-services.md`). Endpoints live in `tooling/db/config.json` +— that config must keep working or move deliberately, not incidentally. Network +failure is the normal case here, so `ReachError` messages need to distinguish +"the box is off" from "the request was wrong"; `missing_fix=` and `fix=` both matter. + +`reach character` — `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`. +Much smaller than `garment-fit/`''s 23 files suggest — 22 of them are Blender +payloads that belong to the carve-out (T-1273) and MUST NOT import the package. +Do T-1273 first or the boundary will blur. + +Standard port acceptance as on T-1281/T-1286. Check `__file__`-relative roots +before moving anything — five silent failures so far.', NULL, '2026-09-02 16:19:29', '2026-09-02 16:19:29.675', '2026-09-02 16:19:29.675', NULL, '24b375349147ca97fec304c70086e503', 2) ON CONFLICT(hash) DO NOTHING; diff --git a/.pql/changelog/ticket_idmap/2026-09.sql b/.pql/changelog/ticket_idmap/2026-09.sql index 5c57f34fa..9f7d2558d 100644 --- a/.pql/changelog/ticket_idmap/2026-09.sql +++ b/.pql/changelog/ticket_idmap/2026-09.sql @@ -2,3 +2,6 @@ INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_ INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G642RKW8PNW7AP9BY9203SPG', 'T-1285', '2026-09-02 12:14:48.290', '2026-09-02 12:14:48.290', NULL, '020f491d1ae8fbde83d2aae0f8325011', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= ticket_idmap.updated_at; INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G64ASTXBBHMWMBQSVPM9MK1W', 'T-1286', '2026-09-02 12:49:55.434', '2026-09-02 12:49:55.434', NULL, '7c65442cc261176c9c472fdbd635cc91', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= ticket_idmap.updated_at; INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65N2W393K7A4B8JA8FGP22R', 'T-1287', '2026-09-02 15:54:39.514', '2026-09-02 15:54:39.514', NULL, 'de690eafa611669d722b0ffb850a1d7b', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= ticket_idmap.updated_at; +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65NSJ4RG6SJ12TQE78S6TKR', 'T-1288', '2026-09-02 15:57:45.383', '2026-09-02 15:57:45.383', NULL, 'db4b46dbe9d6484c4d618bcbc0c3d04d', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= ticket_idmap.updated_at; +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65T2N1WAT491WY8SV736J3G', 'T-1289', '2026-09-02 16:16:28.431', '2026-09-02 16:16:28.431', NULL, '976a8d383d0581caafca5a4bc2e0fb61', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= ticket_idmap.updated_at; +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65TC359QGCVBEPXHJ4N0MRG', 'T-1290', '2026-09-02 16:17:45.770', '2026-09-02 16:17:45.770', NULL, '748d7ed02f4821a7ee5059a76d2fd3fe', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= ticket_idmap.updated_at; diff --git a/.pql/changelog/tickets/2026-09.sql b/.pql/changelog/tickets/2026-09.sql index c124d16d1..ccfb3310d 100644 --- a/.pql/changelog/tickets/2026-09.sql +++ b/.pql/changelog/tickets/2026-09.sql @@ -265,3 +265,94 @@ identical values costs whoever hits it real time. Acceptance: `reach generate character-manifest` on a clean tree leaves manifest.json byte-identical, and the T-1089 test still passes after it runs.', 'backlog', 'medium', NULL, 'client', NULL, '2026-09-02 15:54:39.514', '2026-09-02 15:54:41.911', NULL, '2f6393f44525977bfeba1200e8f79561', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= tickets.updated_at; +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65NSJ4RG6SJ12TQE78S6TKR', 'task', '06G1S3D0M1TQW0GMFBBPQZG3ZM', 'Port atlas planet — the 30-file planet-gen tree', NULL, 'backlog', 'high', NULL, 'tooling', 'D-263', '2026-09-02 15:57:45.382', '2026-09-02 15:57:45.382', NULL, '7a42eb5aacc05e9d7405ca9d0b6be2de', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= tickets.updated_at; +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65NSJ4RG6SJ12TQE78S6TKR', 'task', '06G1S3D0M1TQW0GMFBBPQZG3ZM', 'Port atlas planet — the 30-file planet-gen tree', 'The largest single port left: `tooling/planet-gen/` (30 Python files) becomes +`reach atlas planet `, the third rung of the spatial ladder (D-243), per +the nesting the domain map fixed in T-1271 — `planet` is NOT a top-level domain, +it lives under `atlas` because atlas coordinates world-location generation. + +BEFORE MOVING ANYTHING, check `__file__`-relative roots. Five ports so far have +hit this and it fails SILENTLY: a script that computed `Path(__file__).parent.parent` +as the repo root resolves somewhere else once it lives two directories deeper, +and the usual symptom is a gate that reports "nothing to check, OK" and exits 0. +`validate-checklist` did exactly that. Grep for `__file__` first and convert to +`config.repo_root()` / `config.path(...)` as part of the move, not after. + +WATCH the ones that are already gated: +- `test_sim_determinism.py` and `test_oasis_ring_scaling.py` are run by + `make test-tooling` and must keep working — they are tests, not verbs. Decide + whether they move with the domain or stay as test scripts, and update the + Makefile either way. +- Anything registered in `tooling/canvas_sources.py` (the canvas-generation + version gate, T-1242) — moving a path there without updating the registry + breaks `make check-canvas-version`, which has no override. +- `import_heightmaps` / `import_province_boundaries` are one-time build imports, + deliberately NOT stamped (`.claude/rules/asset-pipeline.md`). Do not fold them + into the regen path while porting. + +Standard port acceptance as on T-1281/T-1286: output parity (exit codes match +exactly, no fact lost, failures name a remedy), every command carries `@command`, +nothing prints but `console`, no `subprocess` outside `core/process`.', 'backlog', 'high', NULL, 'tooling', 'D-263', '2026-09-02 15:57:45.382', '2026-09-02 16:16:24.021', NULL, 'db4db84afdd8a5308a231f7e006dd20c', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= tickets.updated_at; +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65T2N1WAT491WY8SV736J3G', 'task', '06G1S3D0M1TQW0GMFBBPQZG3ZM', 'Port ledger — the economics pipeline under its UI name', NULL, 'backlog', 'high', NULL, 'tooling', 'D-263', '2026-09-02 16:16:28.431', '2026-09-02 16:16:28.431', NULL, '968ceeb5217fa8298109db1a339f42bb', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= tickets.updated_at; +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65T2N1WAT491WY8SV736J3G', 'task', '06G1S3D0M1TQW0GMFBBPQZG3ZM', 'Port ledger — the economics pipeline under its UI name', '`tooling/economy-db/` (17 files) + `schema_version.py` become `reach ledger`. + +The name is deliberate and is the user''s call (D-263 amendment): reach verbs +mirror the game''s implant-app presentation patterns. `ledger` is the player-facing +component that will aggregate economics — browse markets, wealth, transactions — +the way `atlas` aggregates topography. The tooling verb takes the same name so the +CLI and the UI do not diverge into two vocabularies for one subject. + +THIS IS THE HIGHEST-RISK PORT IN THE EPIC and the reason E5 (T-1252) exists as a +separate epic: `import_economics` is the SOLE generator of `server/data/systems.db`, +and its meta stamp is computed over a source-file registry. Two things bite: + +1. `tooling/generator_sources.py` lists every stamped path. Moving a file without + updating the registry either breaks the import (missing path) or silently + changes the SHA. T-1286 already had to swap the retired `generate-brands` + wrapper for `core/process.py` there and regen. Expect the same. +2. `economy-db` is hyphenated, so it is NOT importable as a package. `brands.py` + currently bootstraps `sys.path` with REPO_ROOT to reach `tooling.core` — see + the comment there. That bootstrap should DISAPPEAR in this port, not be + copied; it exists only because the directory could not be imported. Overlaps + T-1272 (hyphen sweep) — do them together or in that order. + +Every port of this domain ends with `make regen-db` + `reach check systems-db-stamp` ++ a commit of `server/data/systems.db`. `generated_brands.toml` must come back +byte-identical; if it does not, the port changed generator behaviour and that is +a bug, not a regen. + +Standard port acceptance as on T-1281/T-1286.', 'backlog', 'high', NULL, 'tooling', 'D-263', '2026-09-02 16:16:28.431', '2026-09-02 16:17:43.245', NULL, '94584fec950483d71790b876fd6acbc2', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= tickets.updated_at; +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65TC359QGCVBEPXHJ4N0MRG', 'task', '06G1S3D0M1TQW0GMFBBPQZG3ZM', 'Port wiki, assets and character — the three small remaining domains', NULL, 'backlog', 'medium', NULL, 'tooling', 'D-263', '2026-09-02 16:17:45.770', '2026-09-02 16:17:45.770', NULL, 'd210eaa362a8570a09d1ac111343d402', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= tickets.updated_at; +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06G65TC359QGCVBEPXHJ4N0MRG', 'task', '06G1S3D0M1TQW0GMFBBPQZG3ZM', 'Port wiki, assets and character — the three small remaining domains', 'The tail of the tree — three domains, ~26 files, batched because none of them +entangles with the spatial ladder or the systems.db stamp. + +`reach wiki` — `tooling/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`. +READ `Skill(wiki)` FIRST. The wiki has two ownership models running in opposite +directions and these tools sit on the seam: `star-systems/` (93% of the wiki) is +OUTPUT generated FROM systems.db by `wiki_sync.py`, while the flat categories are +INPUT. A verb that writes to the wrong side is silently reverted on the next sync. +Several of these are one-shot migrations (`migrate-s-to-gj`, `patch-core-sector`) — +decide per file whether it is a live verb or provenance bound for `tooling/archive/`, +the same call T-1271 made for `pql-migrate/`. + +`reach assets` — `db/audio_*.py`, `db/audio-*`, `db/image_connector.py`, +`db/trellis_connector.py`, `db/common.py`, `trellis-batch.sh`, `synth_ui_sounds.py`. +These call tower-of-joy over the network (Stable Audio :11500, Trellis :11510, by +IP per `.claude/rules/local-services.md`). Endpoints live in `tooling/db/config.json` +— that config must keep working or move deliberately, not incidentally. Network +failure is the normal case here, so `ReachError` messages need to distinguish +"the box is off" from "the request was wrong"; `missing_fix=` and `fix=` both matter. + +`reach character` — `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`. +Much smaller than `garment-fit/`''s 23 files suggest — 22 of them are Blender +payloads that belong to the carve-out (T-1273) and MUST NOT import the package. +Do T-1273 first or the boundary will blur. + +Standard port acceptance as on T-1281/T-1286. Check `__file__`-relative roots +before moving anything — five silent failures so far.', 'backlog', 'medium', NULL, 'tooling', 'D-263', '2026-09-02 16:17:45.770', '2026-09-02 16:19:29.675', NULL, '8b7c1faf88c3c056d1d8690ec23e0d4b', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at >= tickets.updated_at;