chore(meta): close the two harness tickets, file the gaps they exposed
T-1222 and T-1223 shipped today but were still sitting in backlog. Closed, with what actually landed recorded on each — including that T-1223's title premise was wrong: godot-cold-parse does not miss client/tests specifically, it only ever sees the startup path, so the fix was a new tool rather than a widened filter. Three gaps opened after the reconciliation pass and had no ticket: T-1230 — re-enable test_character_visual_sprint28 and fix the per-test compositor rebuild that made it 37% of the client suite. Skipping it bought 39s; the skip must not become permanent, and the ticket says so with the deadline (Phase 5 player rendering) and the better fix to prefer. T-1231 — the enclosed-settlement and Sol GeneratorScope rulings still exist only in a scratchlog under /tmp with no D-record behind them. Qatux flagged this and correctly refused to invent the governance itself. T-1232 — scene_helper.gd turns out to have no importers at all, which is why its five-month parse breakage cost nothing. Delete or adopt: user's call. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3211,3 +3211,24 @@ non-reproducible in isolation / module-scoped / --lib-only runs, and absent on
|
||||
a clean full-suite rerun). No golden fixtures changed.', NULL, '2026-07-26 13:23:55', '2026-07-26 13:23:55.540', '2026-07-26 13:23:55.540', NULL, '8af7979612b90a17bce6b8bafca84fb4', 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 ('06FSWCYA60VHFK44J09WW78FY0', 'status', 'in_progress', 'review', NULL, '2026-07-26 13:23:59', '2026-07-26 13:23:59.369', '2026-07-26 13:23:59.369', NULL, 'ed0a9656e3b0ada543a2f58e17eda9f5', 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 ('06FSP3GEJYTA966BSSR9354YC4', 'status', 'review', 'done', NULL, '2026-07-26 13:24:15', '2026-07-26 13:24:15.122', '2026-07-26 13:24:15.122', NULL, '37112750b5d1aeec9384cb9a1f5544ae', 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 ('06FT0V9F4MNF4FZ44KJMKTXJ0G', 'description', 'Bit the team during the 2026-07-26 pair session and should be fixed BEFORE the larger D-258/scale-constant work lands, since that work will touch a lot of test files and this bug actively masks failures during exactly that kind of change. tests/run-godot currently reports ''Tests passed'' when a gdUnit4 suite fails to parse entirely (e.g. a syntax error in a test file) -- the harness sees a run with total: 0 tests and treats zero-failures-because-zero-tests as green, rather than treating ''a suite that should have contributed tests contributed none'' as a hard failure. Fix: total: 0 for a suite that was expected to run must be a FAIL, not a silent pass-through. Needs a regression test: intentionally break a test file''s parse and assert the harness reports failure, not success.', 'Bit the team during the 2026-07-26 pair session and should be fixed BEFORE the larger D-258/scale-constant work lands, since that work will touch a lot of test files and this bug actively masks failures during exactly that kind of change. tests/run-godot currently reports ''Tests passed'' when a gdUnit4 suite fails to parse entirely (e.g. a syntax error in a test file) -- the harness sees a run with total: 0 tests and treats zero-failures-because-zero-tests as green, rather than treating ''a suite that should have contributed tests contributed none'' as a hard failure. Fix: total: 0 for a suite that was expected to run must be a FAIL, not a silent pass-through. Needs a regression test: intentionally break a test file''s parse and assert the harness reports failure, not success.
|
||||
|
||||
FIXED 2026-07-27 (commits b2ef73256, 263a98f3e). Three bugs, not one. (1) load_error/no_tests guards added: a suite that fails to LOAD, or a run that executes zero tests, are now harness failures with a harness_error JSON field and exit 2 -- the exit code cannot inherit gdUnit4''s, which returns 0 in both states. Verified by injecting each failure, including the case that actually bit: one broken file among many, where total stays large and failed stays zero. (2) DOUBLE COUNT: the parser matched gdUnit4''s per-suite ''Statistics:'' lines AND the ''Overall Summary:'' line that already sums them, so every total was exactly 2x -- the real suite is 1830 tests, not 3660. (3) ANSI escapes sit between summary fields, so patterns on the raw log fell through to a weaker fallback that could not see skips and reported a fully-skipped suite as 26 FAILED. All parsing now runs on a de-ANSI''d copy; skipped is parsed, surfaced, and excluded from passed.', NULL, '2026-07-26 23:12:10', '2026-07-26 23:12:10.402', '2026-07-26 23:12:10.402', NULL, '8e0f23f4bb55fbe300530ed5a6b6b062', 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 ('06FT0V9Y08S6XNMB04JJTGQP44', 'description', 'Companion bug to the tests/run-godot false-green (sibling ticket) -- both bit the team in the same 2026-07-26 pair session, and together they mean a broken test file can pass BOTH the cold-parse gate and the test run with no signal anywhere. tooling/godot-cold-parse currently scans production/source directories but does not include client/tests/ in its parse-check sweep, so a syntax error introduced in a test file is invisible to the cold-parse gate (which would have caught it) AND to the test run (which reports total: 0 as green per the sibling ticket). Fix: extend godot-cold-parse''s scan set to include client/tests/. Do this ticket and its sibling FIRST, ahead of the D-258/scale-constant work (T-1211/T-1218), since that work touches a large volume of test files and needs both gates trustworthy going in.', 'Companion bug to the tests/run-godot false-green (sibling ticket) -- both bit the team in the same 2026-07-26 pair session, and together they mean a broken test file can pass BOTH the cold-parse gate and the test run with no signal anywhere. tooling/godot-cold-parse currently scans production/source directories but does not include client/tests/ in its parse-check sweep, so a syntax error introduced in a test file is invisible to the cold-parse gate (which would have caught it) AND to the test run (which reports total: 0 as green per the sibling ticket). Fix: extend godot-cold-parse''s scan set to include client/tests/. Do this ticket and its sibling FIRST, ahead of the D-258/scale-constant work (T-1211/T-1218), since that work touches a large volume of test files and needs both gates trustworthy going in.
|
||||
|
||||
FIXED 2026-07-27 (commits a005e4840, bf1976613) -- but the premise in this title is TOO NARROW. godot-cold-parse does not miss client/tests/ specifically; it only ever sees scripts on the STARTUP path (autoloads + main scene chain). Verified by breaking a non-startup UI script (step_canvas_legend.gd) and a test file in turn: it reported ''clean'', exit 0, for both. It also filters ''Cannot infer the type'', which had hidden a genuinely unparseable file for five months. Fix shipped as a NEW tool rather than a widened filter: tooling/godot-parse-sweep + client/tools/parse_sweep.gd open all 226 project scripts and fail on any that do not parse. Enforced in the pre-push hook AHEAD of the test suite, so a parse failure costs ~4s instead of ~135s (the hook never ran cold-parse at all, so nothing previously enforced this). The two-part split is forced: no Godot API reports GDScript parse failure reliably -- CACHE_MODE_IGNORE segfaults the engine on a broken script, GDScript.new()+reload() false-positived 150 of 226 healthy scripts, and plain load() returns non-null for a broken one. The engine''s stderr is the only honest signal. First run found client/tests/util/scene_helper.gd unparseable since 2026-02-25.', NULL, '2026-07-26 23:12:22', '2026-07-26 23:12:22.665', '2026-07-26 23:12:22.665', NULL, '19ea43b7aa92622eb2f334c1a56e72cf', 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 ('06FT0V9F4MNF4FZ44KJMKTXJ0G', 'status', 'backlog', 'done', NULL, '2026-07-26 23:12:26', '2026-07-26 23:12:26.266', '2026-07-26 23:12:26.266', NULL, '7f56e47d4c4b49a457c29853fc678013', 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 ('06FT0V9Y08S6XNMB04JJTGQP44', 'status', 'backlog', 'done', NULL, '2026-07-26 23:12:26', '2026-07-26 23:12:26.269', '2026-07-26 23:12:26.269', NULL, 'dffd6923b5e046dec68a4a3ef06a8629', 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 ('06FT1CZSETZPGX9F5747TDBA7W', 'description', 'GAP FLAGGED BY QATUX during the 2026-07-26/27 reconciliation, and it is real: two substantive design rulings from the pair session exist ONLY in a scratchlog under /tmp, with no governance record backing them. D-258 covers rung-0.5; neither of these is in it. (A) ENCLOSED SETTLEMENTS. Non-breathable worlds get enclosed settlements -- point locations on the Atlas, interiors deferred to a separate generator, handled like embedded stations. Rationale: D-220''s density model is physically inapplicable to a pressure vessel, not merely mistuned (it measures people per km2 of footprint driven by utility cost per metre of street; run airless it yields 1,500 ppl/km2 of open-air streets in vacuum). The handoff mechanism already exists: D-166''s door boundary contract -- a dome''s airlock IS that door. Branch on an explicit property, NOT the atmosphere string (leaves room for enclosed settlements on breathable worlds: hostile-biome research posts, undersea, arcologies). Jeroen ruled folds into enclosed; by the same logic and must too, making the rule a single condition -- open-air requires atmosphere == ''standard'', everything else enclosed. NULL atmosphere defaults to enclosed (fails safe). Split: 231 open / 38 enclosed across 269 in-bounds populated bodies. Atmosphere keeps its full range for the SURFACE-EXPEDITION layer (Jeroen: ''surface expeditions will play differently'') -- the binary collapse applies only to settlement layout. (B) SOL GENERATOR SCOPE. See T-1219..T-1221 for the implementation; the DESIGN has no record: the GeneratorScope enum shape (Procedural | Authored { deepest_rung }), the DLC gate being a DEPTH rather than a boolean, no new wire status because ''viewable at Global, no deeper'' IS the existing rung-liveness path, and the ruling that Sol art is an authored DATA CANVAS rather than a finished image (rides the existing wire, no new client draw path, same map-art function as all 269 procedural bodies). Claim ids with {"id":"D-259","domain":"architecture","title":"..."} before writing.', 'GAP FLAGGED BY QATUX during the 2026-07-26/27 reconciliation, and it is real: two substantive design rulings from the pair session exist ONLY in a scratchlog under /tmp, with no governance record backing them. D-258 covers rung-0.5; neither of these is in it.
|
||||
|
||||
(A) ENCLOSED SETTLEMENTS. Non-breathable worlds get enclosed settlements -- point locations on the Atlas, interiors deferred to a separate generator, handled like embedded stations. Rationale: D-220''s density model is physically inapplicable to a pressure vessel, not merely mistuned (it measures people per km2 of footprint driven by utility cost per metre of street; run airless it yields 1,500 ppl/km2 of open-air streets in vacuum). The handoff mechanism already exists -- D-166''s door boundary contract, where a dome''s airlock IS that door. Branch on an explicit ''enclosed'' PROPERTY, not on the atmosphere string, which leaves room for enclosed settlements on breathable worlds (hostile-biome research posts, undersea, arcologies) with no second code path.
|
||||
|
||||
Jeroen ruled that ''thin'' folds into enclosed. By the same logic ''thick'' (Venus-like) and ''reducing'' (toxic) must too -- neither is open-air -- which collapses the rule to a single condition: open-air requires atmosphere == standard, everything else is enclosed. NULL atmosphere defaults to enclosed, which fails safe (an enclosed settlement on a breathable world is merely conservative; an open one in vacuum is absurd). Split: 231 open / 38 enclosed across 269 in-bounds populated bodies. NOTE the thick/reducing extension is the lead''s inference from Jeroen''s thin ruling, not his words -- confirm before writing.
|
||||
|
||||
Atmosphere keeps its full expressive range for the SURFACE-EXPEDITION layer (Jeroen: ''surface expeditions will play differently'' -- thin gives suit + dust storms + weather; none gives hard vacuum, no weather, extreme swings, radiation). The binary collapse applies ONLY to settlement layout. Record that, so the collapse is not later mistaken for atmosphere being unimportant.
|
||||
|
||||
(B) SOL GENERATOR SCOPE. T-1219..T-1221 carry the implementation; the DESIGN has no record. Needs capturing: the GeneratorScope enum shape (Procedural | Authored with a deepest_rung), the DLC gate being a DEPTH rather than a boolean (a Sol expansion deepens the ladder by changing one value), the absence of any new wire status because ''viewable at Global, no deeper'' IS the existing rung-liveness path rather than an error to report, and the ruling that Sol art is an authored DATA CANVAS rather than a finished image -- it rides the existing wire untouched, needs no new client draw path, and goes through the same map-art function as all 269 procedural bodies. The framing Jeroen accepted: you are not looking at a photograph of Earth, you are looking at your implant rendering Earth in the same visual language it renders everything else.
|
||||
|
||||
Also record that Sol bodies carry dangling terrain_reference rows pointing at heightmaps deliberately never baked (import_heightmaps.py explicitly excludes Sol), so a real Earth or Mars DEM dropped at that exact path would silently start generating a procedural homeworld with no gate to stop it.
|
||||
|
||||
Claim ids with ''pql decisions claim D architecture ...'' before writing.', NULL, '2026-07-26 23:13:40', '2026-07-26 23:13:40.114', '2026-07-26 23:13:40.114', NULL, '7c7563a0fa9899b39ec05877ab33b0cb', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
|
||||
@@ -143,3 +143,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 ('06FT0VDA5Q7JZFXG7XYWFR6M3C', 'T-1227', '2026-07-26 21:56:09.390', '2026-07-26 21:56:09.390', NULL, 'f2917021939a93d921bbbc34111fba71', 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 OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
|
||||
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FT0VDJPQWHQZ73WRB7KM56QW', 'T-1228', '2026-07-26 21:56:11.573', '2026-07-26 21:56:11.573', NULL, 'c380e75611d0835950ecbed7ca75f862', 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 OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
|
||||
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FT0VERS6AKQHB30Y1RSRW1FM', 'T-1229', '2026-07-26 21:56:21.321', '2026-07-26 21:56:21.321', NULL, 'bad1b79b90c5e25a8bace4e4dfc383d8', 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 OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
|
||||
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FT1CXPZ8HH73P67G6R98NV6M', 'T-1230', '2026-07-26 23:12:40.186', '2026-07-26 23:12:40.186', NULL, 'e915b5b01c1970246c33217b337b6d7e', 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 OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
|
||||
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FT1CZSETZPGX9F5747TDBA7W', 'T-1231', '2026-07-26 23:12:57.211', '2026-07-26 23:12:57.211', NULL, '54cbe170611367610549c31882930676', 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 OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
|
||||
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FT1D64MS28Z2BGV4Z771JRQG', 'T-1232', '2026-07-26 23:13:49.222', '2026-07-26 23:13:49.222', NULL, 'c5a8956d41c58cd2a29decf840ebdc77', 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 OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
|
||||
|
||||
@@ -5496,3 +5496,31 @@ INSERT INTO tickets (record_id, type, parent_record_id, title, description, stat
|
||||
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 ('06FT0VDA5Q7JZFXG7XYWFR6M3C', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'step_canvas_viewer.gd is 1,133 lines against the 1,000-line gdlint cap', 'Pre-existing lint-cap violation, made worse by the 2026-07-26 pair session''s fetch-overlay wiring work (still net additive to a file already over cap). Split step_canvas_viewer.gd so it comes back under the 1,000-line gdlint limit -- likely candidate: extract the fetch-overlay wiring / cache-store plumbing into a separate component now that step_canvas_fetch_overlay.gd exists as a dedicated node, reducing what step_canvas_viewer.gd itself needs to own directly. Verify gdlint passes clean after the split and that the viewer test suite (92/92 as of this session) stays green.', 'backlog', 'low', NULL, NULL, NULL, '2026-07-26 21:56:09.390', '2026-07-26 21:56:09.390', NULL, '268d5f4b86aa39d08661b88b50fee029', 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 OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
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 ('06FT0VDJPQWHQZ73WRB7KM56QW', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Remove unreferenced DISPLAY_RATIO_SHALLOW constant', 'DISPLAY_RATIO_SHALLOW (step_canvas_transport.gd) is unreferenced since the display-ratio band went uniform at 2x2 across every rung (D-255 2026-07-26 amendment, item 4 -- superseding the old ''1x1 ideal to >=5x5 acceptable'' banded model). Delete the dead constant and confirm no remaining references (grep the client tree, not just the transport file, in case a test or a comment still cites it).', 'backlog', 'low', NULL, NULL, NULL, '2026-07-26 21:56:11.573', '2026-07-26 21:56:11.573', NULL, '3f03f56deae9c61866af0da2759c7d30', 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 OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
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 ('06FT0VERS6AKQHB30Y1RSRW1FM', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Regenerate Atlas visual-capture goldens (defer until rung-0.5 + scale-constant work lands)', 'DEFERRED BY DESIGN -- do not start this until BOTH T-1211 (D-258 rung-0.5 epic) and T-1218 (scale-constant change) have landed, so goldens are regenerated once rather than twice. Two independent reasons goldens are already known-stale from the 2026-07-26 pair session alone, before rung-0.5/scale-constants even land: (1) the extent inversion + uniform 2x2 display ratio changed every rung''s canvas size and sampling, so atlas_*_District / atlas_*_Global visual-capture goldens (tests/visual.json via _setup_atlas_golden_shot) no longer match; (2) existing disk-cache entries hold 1x1-sized canvases from before the 2x2 gridunit change -- these age out naturally via the cache key (a different extent is a different cache key, per D-227''s version-tag/eviction discipline), so NO manual purge is needed there, but the goldens themselves still need hand regeneration since they are golden-image fixtures, not cache entries. Run make fixtures-gauntlet + the tests/run-visual golden regeneration flow once rung-0.5 and the scale constants are both live, then do a full eyeball pass, not just a pixel-diff, since both the data source (rung 0.5) and the metre constants (district/region) will have changed underneath the images in the same window. See governance/decisions/architecture.md#d-258 and the pair-session scratchlog 2026-07-26 backfile checklist.', 'backlog', 'medium', NULL, NULL, 'D-258', '2026-07-26 21:56:21.321', '2026-07-26 21:56:21.321', NULL, '61b17c35456103cc1663077c9710f96b', 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 OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
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 ('06FT0V9F4MNF4FZ44KJMKTXJ0G', 'bug', '06FBPPMZNNEV052DBYYY3A897C', 'tests/run-godot reports false PASS when a suite fails to parse (total: 0)', 'Bit the team during the 2026-07-26 pair session and should be fixed BEFORE the larger D-258/scale-constant work lands, since that work will touch a lot of test files and this bug actively masks failures during exactly that kind of change. tests/run-godot currently reports ''Tests passed'' when a gdUnit4 suite fails to parse entirely (e.g. a syntax error in a test file) -- the harness sees a run with total: 0 tests and treats zero-failures-because-zero-tests as green, rather than treating ''a suite that should have contributed tests contributed none'' as a hard failure. Fix: total: 0 for a suite that was expected to run must be a FAIL, not a silent pass-through. Needs a regression test: intentionally break a test file''s parse and assert the harness reports failure, not success.
|
||||
|
||||
FIXED 2026-07-27 (commits b2ef73256, 263a98f3e). Three bugs, not one. (1) load_error/no_tests guards added: a suite that fails to LOAD, or a run that executes zero tests, are now harness failures with a harness_error JSON field and exit 2 -- the exit code cannot inherit gdUnit4''s, which returns 0 in both states. Verified by injecting each failure, including the case that actually bit: one broken file among many, where total stays large and failed stays zero. (2) DOUBLE COUNT: the parser matched gdUnit4''s per-suite ''Statistics:'' lines AND the ''Overall Summary:'' line that already sums them, so every total was exactly 2x -- the real suite is 1830 tests, not 3660. (3) ANSI escapes sit between summary fields, so patterns on the raw log fell through to a weaker fallback that could not see skips and reported a fully-skipped suite as 26 FAILED. All parsing now runs on a de-ANSI''d copy; skipped is parsed, surfaced, and excluded from passed.', 'backlog', 'high', NULL, NULL, NULL, '2026-07-26 21:55:37.893', '2026-07-26 23:12:10.402', NULL, '2d81d19695b6b5f32442af48101585ca', 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 OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
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 ('06FT0V9Y08S6XNMB04JJTGQP44', 'bug', '06FBPPMZNNEV052DBYYY3A897C', 'tooling/godot-cold-parse does not cover client/tests/, so a broken test file reads clean twice over', 'Companion bug to the tests/run-godot false-green (sibling ticket) -- both bit the team in the same 2026-07-26 pair session, and together they mean a broken test file can pass BOTH the cold-parse gate and the test run with no signal anywhere. tooling/godot-cold-parse currently scans production/source directories but does not include client/tests/ in its parse-check sweep, so a syntax error introduced in a test file is invisible to the cold-parse gate (which would have caught it) AND to the test run (which reports total: 0 as green per the sibling ticket). Fix: extend godot-cold-parse''s scan set to include client/tests/. Do this ticket and its sibling FIRST, ahead of the D-258/scale-constant work (T-1211/T-1218), since that work touches a large volume of test files and needs both gates trustworthy going in.
|
||||
|
||||
FIXED 2026-07-27 (commits a005e4840, bf1976613) -- but the premise in this title is TOO NARROW. godot-cold-parse does not miss client/tests/ specifically; it only ever sees scripts on the STARTUP path (autoloads + main scene chain). Verified by breaking a non-startup UI script (step_canvas_legend.gd) and a test file in turn: it reported ''clean'', exit 0, for both. It also filters ''Cannot infer the type'', which had hidden a genuinely unparseable file for five months. Fix shipped as a NEW tool rather than a widened filter: tooling/godot-parse-sweep + client/tools/parse_sweep.gd open all 226 project scripts and fail on any that do not parse. Enforced in the pre-push hook AHEAD of the test suite, so a parse failure costs ~4s instead of ~135s (the hook never ran cold-parse at all, so nothing previously enforced this). The two-part split is forced: no Godot API reports GDScript parse failure reliably -- CACHE_MODE_IGNORE segfaults the engine on a broken script, GDScript.new()+reload() false-positived 150 of 226 healthy scripts, and plain load() returns non-null for a broken one. The engine''s stderr is the only honest signal. First run found client/tests/util/scene_helper.gd unparseable since 2026-02-25.', 'backlog', 'high', NULL, NULL, NULL, '2026-07-26 21:55:41.698', '2026-07-26 23:12:22.665', NULL, '8f2ac9a25583f0301b89a375c394b50d', 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 OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
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 ('06FT0V9F4MNF4FZ44KJMKTXJ0G', 'bug', '06FBPPMZNNEV052DBYYY3A897C', 'tests/run-godot reports false PASS when a suite fails to parse (total: 0)', 'Bit the team during the 2026-07-26 pair session and should be fixed BEFORE the larger D-258/scale-constant work lands, since that work will touch a lot of test files and this bug actively masks failures during exactly that kind of change. tests/run-godot currently reports ''Tests passed'' when a gdUnit4 suite fails to parse entirely (e.g. a syntax error in a test file) -- the harness sees a run with total: 0 tests and treats zero-failures-because-zero-tests as green, rather than treating ''a suite that should have contributed tests contributed none'' as a hard failure. Fix: total: 0 for a suite that was expected to run must be a FAIL, not a silent pass-through. Needs a regression test: intentionally break a test file''s parse and assert the harness reports failure, not success.
|
||||
|
||||
FIXED 2026-07-27 (commits b2ef73256, 263a98f3e). Three bugs, not one. (1) load_error/no_tests guards added: a suite that fails to LOAD, or a run that executes zero tests, are now harness failures with a harness_error JSON field and exit 2 -- the exit code cannot inherit gdUnit4''s, which returns 0 in both states. Verified by injecting each failure, including the case that actually bit: one broken file among many, where total stays large and failed stays zero. (2) DOUBLE COUNT: the parser matched gdUnit4''s per-suite ''Statistics:'' lines AND the ''Overall Summary:'' line that already sums them, so every total was exactly 2x -- the real suite is 1830 tests, not 3660. (3) ANSI escapes sit between summary fields, so patterns on the raw log fell through to a weaker fallback that could not see skips and reported a fully-skipped suite as 26 FAILED. All parsing now runs on a de-ANSI''d copy; skipped is parsed, surfaced, and excluded from passed.', 'done', 'high', NULL, NULL, NULL, '2026-07-26 21:55:37.893', '2026-07-26 23:12:26.261', NULL, 'e0076aba35093efb329ac20bea78997e', 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 OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
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 ('06FT0V9Y08S6XNMB04JJTGQP44', 'bug', '06FBPPMZNNEV052DBYYY3A897C', 'tooling/godot-cold-parse does not cover client/tests/, so a broken test file reads clean twice over', 'Companion bug to the tests/run-godot false-green (sibling ticket) -- both bit the team in the same 2026-07-26 pair session, and together they mean a broken test file can pass BOTH the cold-parse gate and the test run with no signal anywhere. tooling/godot-cold-parse currently scans production/source directories but does not include client/tests/ in its parse-check sweep, so a syntax error introduced in a test file is invisible to the cold-parse gate (which would have caught it) AND to the test run (which reports total: 0 as green per the sibling ticket). Fix: extend godot-cold-parse''s scan set to include client/tests/. Do this ticket and its sibling FIRST, ahead of the D-258/scale-constant work (T-1211/T-1218), since that work touches a large volume of test files and needs both gates trustworthy going in.
|
||||
|
||||
FIXED 2026-07-27 (commits a005e4840, bf1976613) -- but the premise in this title is TOO NARROW. godot-cold-parse does not miss client/tests/ specifically; it only ever sees scripts on the STARTUP path (autoloads + main scene chain). Verified by breaking a non-startup UI script (step_canvas_legend.gd) and a test file in turn: it reported ''clean'', exit 0, for both. It also filters ''Cannot infer the type'', which had hidden a genuinely unparseable file for five months. Fix shipped as a NEW tool rather than a widened filter: tooling/godot-parse-sweep + client/tools/parse_sweep.gd open all 226 project scripts and fail on any that do not parse. Enforced in the pre-push hook AHEAD of the test suite, so a parse failure costs ~4s instead of ~135s (the hook never ran cold-parse at all, so nothing previously enforced this). The two-part split is forced: no Godot API reports GDScript parse failure reliably -- CACHE_MODE_IGNORE segfaults the engine on a broken script, GDScript.new()+reload() false-positived 150 of 226 healthy scripts, and plain load() returns non-null for a broken one. The engine''s stderr is the only honest signal. First run found client/tests/util/scene_helper.gd unparseable since 2026-02-25.', 'done', 'high', NULL, NULL, NULL, '2026-07-26 21:55:41.698', '2026-07-26 23:12:26.269', NULL, '7b2d5b71e7c49d5f02a77fde39dd7a5f', 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 OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
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 ('06FT1CXPZ8HH73P67G6R98NV6M', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Re-enable test_character_visual_sprint28 and fix its per-test compositor rebuild', 'SKIPPED 2026-07-27 (commit 791600dd2) via gdUnit4 __is_skipped, on Jeroen''s call, because 3D character representation is not under active work and this one suite was 37% of the whole client run. Client suite went 135s -> 96s from this file alone. Measured across all 86 suites: this suite 50.0s / 26 tests (~1.9s each); all suites 127.1s / 1830 tests; the other 78 suites ~33s / 1804 tests. The cost is asset loading PER TEST -- every test instantiates a fresh CharacterVisual Node3D and loads the skeleton .glb plus body/skin-tone assets. Two things to do here, in order: (1) fix the cause -- build the compositor once per suite (before()) or cache the loaded resources, instead of rebuilding per test; (2) delete the _init() in the suite to re-enable. Nothing else was changed: every test is intact and was passing when skipped. MUST be re-enabled no later than Phase 5 player rendering, when this code is live again. Prefer fixing the setup over leaving it skipped for cost -- a permanently skipped suite is dead coverage that will rot silently. Note run-godot now surfaces skipped as its own JSON field and excludes it from passed, so the 26 stay visible in every run.', 'backlog', 'medium', NULL, 'client', NULL, '2026-07-26 23:12:40.186', '2026-07-26 23:12:40.186', NULL, '2a4d9262945c68441387e624b5fc920c', 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 OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
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 ('06FT1CZSETZPGX9F5747TDBA7W', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Record the Sol GeneratorScope + enclosed-settlement rulings as D-records', 'GAP FLAGGED BY QATUX during the 2026-07-26/27 reconciliation, and it is real: two substantive design rulings from the pair session exist ONLY in a scratchlog under /tmp, with no governance record backing them. D-258 covers rung-0.5; neither of these is in it. (A) ENCLOSED SETTLEMENTS. Non-breathable worlds get enclosed settlements -- point locations on the Atlas, interiors deferred to a separate generator, handled like embedded stations. Rationale: D-220''s density model is physically inapplicable to a pressure vessel, not merely mistuned (it measures people per km2 of footprint driven by utility cost per metre of street; run airless it yields 1,500 ppl/km2 of open-air streets in vacuum). The handoff mechanism already exists: D-166''s door boundary contract -- a dome''s airlock IS that door. Branch on an explicit property, NOT the atmosphere string (leaves room for enclosed settlements on breathable worlds: hostile-biome research posts, undersea, arcologies). Jeroen ruled folds into enclosed; by the same logic and must too, making the rule a single condition -- open-air requires atmosphere == ''standard'', everything else enclosed. NULL atmosphere defaults to enclosed (fails safe). Split: 231 open / 38 enclosed across 269 in-bounds populated bodies. Atmosphere keeps its full range for the SURFACE-EXPEDITION layer (Jeroen: ''surface expeditions will play differently'') -- the binary collapse applies only to settlement layout. (B) SOL GENERATOR SCOPE. See T-1219..T-1221 for the implementation; the DESIGN has no record: the GeneratorScope enum shape (Procedural | Authored { deepest_rung }), the DLC gate being a DEPTH rather than a boolean, no new wire status because ''viewable at Global, no deeper'' IS the existing rung-liveness path, and the ruling that Sol art is an authored DATA CANVAS rather than a finished image (rides the existing wire, no new client draw path, same map-art function as all 269 procedural bodies). Claim ids with {"id":"D-259","domain":"architecture","title":"..."} before writing.', 'backlog', 'high', NULL, 'server', NULL, '2026-07-26 23:12:57.206', '2026-07-26 23:12:57.206', NULL, '218dafced176867270e66a8962e4d62f', 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 OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
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 ('06FT1CZSETZPGX9F5747TDBA7W', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Record the Sol GeneratorScope + enclosed-settlement rulings as D-records', 'GAP FLAGGED BY QATUX during the 2026-07-26/27 reconciliation, and it is real: two substantive design rulings from the pair session exist ONLY in a scratchlog under /tmp, with no governance record backing them. D-258 covers rung-0.5; neither of these is in it.
|
||||
|
||||
(A) ENCLOSED SETTLEMENTS. Non-breathable worlds get enclosed settlements -- point locations on the Atlas, interiors deferred to a separate generator, handled like embedded stations. Rationale: D-220''s density model is physically inapplicable to a pressure vessel, not merely mistuned (it measures people per km2 of footprint driven by utility cost per metre of street; run airless it yields 1,500 ppl/km2 of open-air streets in vacuum). The handoff mechanism already exists -- D-166''s door boundary contract, where a dome''s airlock IS that door. Branch on an explicit ''enclosed'' PROPERTY, not on the atmosphere string, which leaves room for enclosed settlements on breathable worlds (hostile-biome research posts, undersea, arcologies) with no second code path.
|
||||
|
||||
Jeroen ruled that ''thin'' folds into enclosed. By the same logic ''thick'' (Venus-like) and ''reducing'' (toxic) must too -- neither is open-air -- which collapses the rule to a single condition: open-air requires atmosphere == standard, everything else is enclosed. NULL atmosphere defaults to enclosed, which fails safe (an enclosed settlement on a breathable world is merely conservative; an open one in vacuum is absurd). Split: 231 open / 38 enclosed across 269 in-bounds populated bodies. NOTE the thick/reducing extension is the lead''s inference from Jeroen''s thin ruling, not his words -- confirm before writing.
|
||||
|
||||
Atmosphere keeps its full expressive range for the SURFACE-EXPEDITION layer (Jeroen: ''surface expeditions will play differently'' -- thin gives suit + dust storms + weather; none gives hard vacuum, no weather, extreme swings, radiation). The binary collapse applies ONLY to settlement layout. Record that, so the collapse is not later mistaken for atmosphere being unimportant.
|
||||
|
||||
(B) SOL GENERATOR SCOPE. T-1219..T-1221 carry the implementation; the DESIGN has no record. Needs capturing: the GeneratorScope enum shape (Procedural | Authored with a deepest_rung), the DLC gate being a DEPTH rather than a boolean (a Sol expansion deepens the ladder by changing one value), the absence of any new wire status because ''viewable at Global, no deeper'' IS the existing rung-liveness path rather than an error to report, and the ruling that Sol art is an authored DATA CANVAS rather than a finished image -- it rides the existing wire untouched, needs no new client draw path, and goes through the same map-art function as all 269 procedural bodies. The framing Jeroen accepted: you are not looking at a photograph of Earth, you are looking at your implant rendering Earth in the same visual language it renders everything else.
|
||||
|
||||
Also record that Sol bodies carry dangling terrain_reference rows pointing at heightmaps deliberately never baked (import_heightmaps.py explicitly excludes Sol), so a real Earth or Mars DEM dropped at that exact path would silently start generating a procedural homeworld with no gate to stop it.
|
||||
|
||||
Claim ids with ''pql decisions claim D architecture ...'' before writing.', 'backlog', 'high', NULL, 'server', NULL, '2026-07-26 23:12:57.206', '2026-07-26 23:13:40.114', NULL, '53a08ddb97ea73677337c7a50dd1cc05', 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 OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
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 ('06FT1D64MS28Z2BGV4Z771JRQG', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'client/tests/util/scene_helper.gd has no importers -- dead test utility', 'Found by the new parse sweep on 2026-07-27. This helper had not PARSED since 2026-02-25 -- five months -- because a lambda used ''func(a := null, ...)'', and := cannot infer a type from null. Fixed in commit a005e4840 with explicit '': Variant'' params. But the reason it went unnoticed for five months is that NOTHING IMPORTS IT: a grep across client/tests/ returns zero consumers. So the blast radius of the breakage was zero, and the file is dead code. Decide: delete it, or adopt it (it wraps signal-emission monitoring for scene tests, which several suites currently hand-roll). Not deleted unilaterally -- deleting code is the user''s call. Low priority; it is inert either way now that it parses.', 'backlog', 'low', NULL, 'client', NULL, '2026-07-26 23:13:49.222', '2026-07-26 23:13:49.222', NULL, '336371298ea7b847684b5e093ef1b299', 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 OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
|
||||
Reference in New Issue
Block a user