M4 iteration 2: portable modules and the Mockingbird re-carve - #49
Merged
Conversation
…not just the first (#M4) every_shipped_module_resolves_in_its_slot_test picked one target per module via list.find, so a module with several targets on this hull (the upcoming multi-slot cabin) would have all but its first placement silently unverified. Iterate every mockingbird target instead.
…(#M4) `lookup_modules` only resolved the one slot id named in a loadout entry; the rest of a multi-slot target's `slots` were never checked against the hull, so `check_bounds`'s digit lookup silently dropped a bad id instead of erroring. Resolve every id in the target's `slots` up front, reusing the existing `slot_not_on_hull:<id>` reason string.
…lines (#M4) Her five slots become ten, and they now name ROOMS rather than the shapes a particular fit happened to draw: a cockpit, five identical 1x2 cabins, the crew commons, the payload bay, engineering and the hold. Corridors, both stairwells, the aft junction, the whole mezzanine and the hull skin stay fixed hull. Two regions that were hard-coded interior — the mess cabin at (4, 10-11) and engineering at (5-7, 18-19) — are stripped back to bare shell so their modules supply what is in them. Everywhere a divider now has slot tiles on both sides the hull hands the whole wall to the module (the Mockingbird already drew none of those, so this is a rule the re-carve establishes rather than a diff). `payload_passenger`, `commons_crew` and `engineering_stock` replace the four modules whose regions no longer exist; `cockpit_stock` and both hold modules keep their slot ids and their content. Two hull numbers move so nothing downstream does. Her dry mass drops 96.0 -> 73.0 because the default modules grew 24.0 -> 47.0: the fit still totals 128.0, so her flight numbers are untouched. Her reactor grows 10 -> 18 power because the same interior is now billed as ten modules instead of five (17 with the Consol patch fitted) — one spare, exactly the headroom she had before. The cabin document that fills the five cabin slots lands in the next commit, so the golden deck comparison is red at this commit by construction. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…s (#M4) `rijay.cabin.standard` carries five targets on the Mockingbird — `cabin_fore_a`, `cabin_fore_b`, `cabin_mess`, `cabin_engineer` and `cabin_aft_stbd` — and the default loadout installs it in all five. One concept, one document, however many places it fits; the id is namespaced `rijay.` rather than `mockingbird.` because the Sparrow and the Finch add targets to this same file rather than each growing a cabin file of their own. Every target is still hand-drawn against its own origin: the three forward cabins put the door and window on the same walls, the engineer's cabin flips north-south, and the aft starboard cabin mirrors east-west. That is the point — the doors line up because a human drew them lining up, not because anything matched shapes at runtime. `module.schema.json` learns the `targets` spelling, minimally, so the new document validates; Task 5 owns the full schema and documentation pass. Both suites green: 336 Gleam tests, harness 29 passed / 2 deselected, with `default_loadout_reproduces_the_authored_deck_test` reproducing her frozen pre-M4 deck tile for tile. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… (#M4) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Mirror branch A's exclusion onto branch B so hull+slot+targets is genuinely rejected (the schema's typo-catching purpose otherwise misses a half-finished migration to targets that leaves stale flat fields the decoder silently ignores). Also fix docs/modules.md's Mockingbird slot summary: the hold slot lives on the Lower deck, not a "Hold" deck. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… drop dead Slot (#M4) A content bug (a module document's targets naming a slot id off the hull) was reported through slot_not_on_hull, the player-refusal channel — give it its own target_slot_not_on_hull:<module id> reason and update the three vocabulary lists plus the covering test. Also: cover the schema's oneOf/not construct with a live positive/negative test, close the targets+stray-slot schema gap symmetric with hull, align docs/modules.md's both-spellings tone with the schema's rejection, narrow lookup_modules's fitted tuple to #(Module, Target) now that nothing reads the Slot element, and fix a stray hyphenated "iteration-2a" in deckplan-format.md.
… (#M4) The schema oneOf test proved `oneOf` was live but never `not`: its negative case carried both `hull` and `slot`, so it matched BOTH branches and the exactly-one rule refused it whether or not the `not` clauses did anything. Adds `targets` beside a lone stray `slot` — the shape a half-finished migration leaves behind — which matches branch 1 alone unless `not` is live. Renames the test accordingly, and moves the both-spellings clause in docs/modules.md next to the sentence it qualifies rather than after the "neither" case. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
One module document can now serve many
(hull, slot)placements, a module can claim several adjacent slots, and the Mockingbird is re-carved so her rooms are slots — five standard cabins served by a singlerijay.cabin.standarddocument, a central payload bay, a crew commons, and a modular engine room.Nothing about the authored-overlay bet changes. Every target is still drawn by hand against one specific hull's coordinates, which is what guarantees its doors line up. What changed is file organisation: one document per concept instead of one per placement. Free placement stays refused, and the validator still does no geometry.
This restores what
docs/modules.mdoriginally specified and that iteration 1 simplified away, so the Sparrow and Finch can be authored once, against final rules.What landed
34be4ec18d33fctargets5d46056301373d6f15216ecdec33rijay.cabin.standardserving all five cabinsb068b9f0a4920181642690f74346The ten slots
cockpit(4 tiles) ·cabin_fore_a(2) ·cabin_fore_b(2) ·crew_commons(12) ·cabin_mess(2) ·payload(45) ·cabin_engineer(2) ·engineering(6) ·cabin_aft_stbd(2) ·hold(74)Fixed hull: the cockpit passage, the x8 corridor, the aft junction, both stairwells, the whole Mezzanine with its
Qports, and the skin. Where a divider now has slot tiles on both sides — the aft passenger cabin partitions, the wall between the large common and those cabins — it left the hull and moved into the payload module. Those walls are movable now.Verification
server/test/fixtures/mockingbird_authored.jsonanddefault_loadout_reproduces_the_authored_deck_testwere the arbiter throughout and are untouched — zero deletions inmockingbird_test.gleam.tools/slotmap.pyrenders the ten regions at exactly the planned tile counts, and the bare-hull render confirms the payload interior is genuinely open where the modules now own it.Two forced number changes
The plan's own module masses and tag figures required these; both were verified against the unchanged part documents.
96.0 → 73.0— modules went 24.0 → 47.0, so the resolved total stays 128.0 and her flight numbers are unchanged.10 → 18— modules now draw 17 with the Consol patch, 18 with the stock engine, preserving the pre-M4 headroom of 1 and 0 respectively.Known follow-up (not a blocker)
tag_deficit:poweris unreachable through shipped content now: every slot has one candidate module excepthold, whose two both draw 1. The rule is still enforced and unit-tested; what is missing is a shipped demonstration, which is whysim_test's refused-refit case retargeted totag_deficit:engine. Iteration 3's refit catalog brings alternatives that can overdraw, at which point that test can go back topower. Worth noting she sits at exactly zero headroom with the stock engine, so the first catalog addition forces a reactor decision.Vocabulary change
module_wrong_hullandmodule_wrong_slotare gone, replaced bymodule_not_drawn_for_slot. A typo in a module document'sslotsreports astarget_slot_not_on_hull:<module id>— a content error naming the file at fault — kept distinct from the player-facingslot_not_on_hull:<slot id>refusal.🤖 Generated with Claude Code