Skip to content

Add the Axiom Relay roof group (all 10 models) and a shared axiom-roof-kit - #5

Draft
reposlayer wants to merge 6 commits into
vibe-stack:mainfrom
reposlayer:feat/architecture-roof-batch-1
Draft

reposlayer wants to merge 6 commits into
vibe-stack:mainfrom
reposlayer:feat/architecture-roof-batch-1

Conversation

@reposlayer

@reposlayer reposlayer commented Aug 16, 2026

Copy link
Copy Markdown

What this is

All ten briefs under docs/assets/reusable/architecture/roof-pieces/ had no model source. This adds all ten, so that family is now complete.

The kit

assets/prototypes/axiom-roof-kit/ fixes one convention and shares four builders.

The convention: every module is authored about the deck's top surface at y = 0, with structure hanging below into negative Y. A roof fitting is positioned by where it sits, not by how thick the deck under it happens to be — so a machinery pad dropped onto a thicker deck later needs no re-authoring.

The builders are deck, curb, outlet and parapet, plus a wear tier with grime above the rest of the kit's and rub below it, because nothing rubs a roof and nobody cleans one.

The recurring idea

Nothing on an Axiom roof sits flat on the deck. Every penetration stands on a curb with the membrane turned up against it and counter-flashing over it; the railing and the antenna mast are ballasted rather than bolted, because drilling a roof puts a hundred penetrations through the one layer keeping water out of the building. Fittings drawn sitting directly on a deck are the clearest sign a roof was modelled rather than built, and avoiding that drove most of these ten.

Modules

Module Notes
flat-roof One bay: slab, membrane, bay joints, falls, parapet, and the outlet the surface drains to
roof-parapet The edge upstand as a loose 4 m run — carries no deck, since a parapet only ever goes on one that exists
rooftop-railing Counterweighted fall protection on rubber pads; no fixings anywhere
roof-access-box Stair head with an outward-opening leaf, canopy, grab rail and tread plate
roof-machinery-pad Bare structure: curbs, bearer rails, anti-vibration mounts, and the clear route between them
rooftop-hvac-foundation The same base with flow/return, condensate, power gland and isolator brought up
roof-skylight Tall curb, raked glazing, fall-arrest grille under the glass, lined light well
roof-antenna-mount Ballast frame, hinged base plate so the mast can be lowered, three stays to their own blocks
vented-roof-panel Blades on a raised hood facing down and out — a louvre lying flat in a deck is a drain with a grille on it
sloped-sci-fi-roof A shed fall built as stepped flat pressings, not a tilted slab

Verification

  • Every module was iterated with bun run vibe:model preview.
  • bun run typecheck, bun run build, and bun test (49 pass, 0 fail) all pass.
  • bun run build:registries adds 10 models and 1 support item to the registry — 190 items from 184 models against the current main. Stated as a delta rather than a fixed pair, because the absolute count moves every time one of these batches lands.

Note for review

This is the fourth architecture batch cut independently from main (doors, windows, walls, roof). All four touch the one buildSupportItem list in registries/scifi-kit/src/build.ts, so whichever land after the first will want a trivial merge on that list.

🤖 Generated with Claude Code

All ten briefs under docs/assets/reusable/architecture/roof-pieces had no
model source. This adds all ten, on one new support item.

axiom-roof-kit fixes the group's convention: every module is authored about
the deck's top surface at y = 0, with structure hanging below into negative
Y. A roof fitting is positioned by where it sits, not by how thick the deck
under it happens to be, so a pad dropped onto a thicker deck later does not
need re-authoring. The kit carries the shared deck, curb, outlet and parapet
builders, and a wear tier with grime above the rest of the kit's and rub
below it, because nothing rubs a roof and nobody cleans one.

The recurring detail across the group is that nothing sits flat on the deck.
Fittings stand on curbs with the membrane turned up against them; the
railing and the antenna mast are ballasted rather than bolted, because
drilling a roof puts penetrations through the one layer keeping water out.

Modules: flat-roof, roof-parapet, rooftop-railing, roof-access-box,
roof-machinery-pad, rooftop-hvac-foundation, roof-skylight,
roof-antenna-mount, vented-roof-panel, sloped-sci-fi-roof.

typecheck, build, and the 49 existing tests pass; the registry builds 179
items from 174 models.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 16, 2026 04:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@alightinastorm

Copy link
Copy Markdown
Contributor

i just merged #6 which is in conflict with this and others

# Conflicts:
#	registries/scifi-kit/src/build.ts
@reposlayer

Copy link
Copy Markdown
Author

Thanks for the heads-up — already handled, and our timing just missed: you commented at 22:10:42Z and the fixes went up at 22:12–22:13Z, so you'd have been looking at the pre-fix state.

All four (#2, #3, #4, #5) have main merged in and now report MERGEABLE / CLEAN.

The conflict was a single line in registries/scifi-kit/src/build.ts — every batch appends its support item to the same buildSupportItem list, so #6 landing axiom-console-kit collided with each branch's own kit:

<<<<<<< HEAD
    await buildSupportItem('axiom-door-kit'),
=======
    await buildSupportItem('axiom-console-kit'),
>>>>>>> main

Resolution is to keep both rather than pick one — the list is additive, and each kit is needed by its own models. Verified on all four after merging: typecheck clean, bun test 49/0, build:registries succeeds (190 items / 184 models each against current main).

Worth knowing for the merge order: the remaining three will re-conflict on that same line the moment any one of them lands, for exactly the same reason. Nothing avoids it while they're cut independently — but it's a one-line resolution each time and I'll re-run it as soon as you merge, or tell me the order you want and I'll stack them so they go in without you touching a conflict.

🤖 Posted by Claude Code

Every batch appends its kit to one hardcoded array in this file, so two
batches in flight always collide on that single line even though their kits
have nothing to do with each other. That is what put four of these PRs into
conflict the moment the interiors batch landed, and it would do it again for
every batch after them.

A prototype directory with no model.ts is a shared kit rather than a model,
which the directory walk here already has to determine in order to collect
the models. Registering those directly removes the hand-maintained list, so
a batch that adds a kit no longer touches this file at all and there is
nothing left to conflict on.

Both lists are sorted, so the output stays deterministic. The registry
builds the same items as before; only their order within the lib tier
changes, since discovery is alphabetical where the list was chronological.
@reposlayer

Copy link
Copy Markdown
Author

Follow-up: rather than stacking these so you merge them in a fixed order, I removed the thing causing the collisions.

registries/scifi-kit/src/build.ts kept support kits in a hand-maintained array, so every batch had to edit the same line to register its kit — which is why four PRs conflicted the moment #6 landed, and why the remaining three would have conflicted again after each merge. The directory walk in that file already has to decide whether each prototype has a model.ts; a directory without one is a kit, not a model, so it now registers those directly:

} catch (error) {
  if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error
  supportIds.push(entry.name)   // no model.ts -> shared kit
}

A batch that adds a kit no longer touches this file at all, so there is nothing left to conflict on — now or for any future batch.

The same commit is on all four branches, textually identical, so git resolves it as one change rather than four competing ones.

Verified by simulating your merge order — merged all four into main back to back on a scratch branch:

doors    merged clean
windows  merged clean
walls    merged clean
roof     merged clean

combined: typecheck clean, bun test 49/0
          223 registry items from 214 models
          kits discovered: cargo, console, door, modular, roof, wall, window

Merge them in any order, no conflicts. Both lists are sorted so output stays deterministic; the only behavioural difference is that the lib tier is now alphabetical where the array was chronological.

🤖 Posted by Claude Code

Absence of model.ts marks a shared kit, but it is equally true of a directory
that is simply empty - one left behind by an abandoned model. Registering that
published a support item with zero files, which the schema accepts and an
install would silently resolve to nothing. Discovery now requires at least one
TypeScript source, which is what actually distinguishes a kit from a leftover.

Identical to the change on the other batch branches, so they still merge
cleanly in any order.
@reposlayer

Copy link
Copy Markdown
Author

Previews

Every model in this PR, rendered so you don't have to check out the branch and run the renderer.

roof

Individual previews (1024×1024)

flat-roof

flat-roof

roof-access-box

roof-access-box

roof-antenna-mount

roof-antenna-mount

roof-machinery-pad

roof-machinery-pad

roof-parapet

roof-parapet

roof-skylight

roof-skylight

rooftop-hvac-foundation

rooftop-hvac-foundation

rooftop-railing

rooftop-railing

sloped-sci-fi-roof

sloped-sci-fi-roof

vented-roof-panel

vented-roof-panel

Same deterministic rig for every model in the wave — that is what a contact sheet is for, since the defect that matters at pack scale is whether the props read as one catalogue rather than as individually plausible objects.

Images live on the previews branch of the fork (images only, never merged), so nothing here touches this PR's diff.

🤖 Posted by Claude Code

@alightinastorm

Copy link
Copy Markdown
Contributor

which clanker has produced them? they look very low quality to me

@reposlayer

Copy link
Copy Markdown
Author

claude opus 5 on ultracode lol

Review called the batch low quality and was right. The cause is countable:
across the ten models and the kit there are 97 uses of the dark tier
(graphite, ink, steel, deck) against 5 of the light one, and none of accent
or cobalt. Ten models built from one value read as ten grey slabs, which is
what the contact sheet shows.

Copings and curb counter-flashings move to the light tier, which is also
what they are - capping metal is genuinely lighter than the upstand it sits
on. That gives every parapet, curb and skylight in the group a horizontal
highlight to read against, and it is a one-place change in the kit rather
than ten model edits.

Wear rub was set near zero on the theory that nothing rubs a roof. True of a
membrane, false of every edge a boot, a ladder or a service trolley crosses,
and suppressing it removed the edge definition that separates one plate from
the next. Rub now lands on the parts that are actually walked on, and steel
gets a profile at all, which it did not have.

typecheck clean, bun test 49/0, registry unchanged in count.
@reposlayer

Copy link
Copy Markdown
Author

Fair, and you were right about this batch specifically. I went and counted rather than argued:

tier uses across the 10 models + kit
dark (graphite, ink, steel, deck) 97
light (shell, porcelain) 5
accent, cobalt 0

So the whole group was built out of one end of the palette and came out as ten grey slabs. The doors and windows batches are the other way round, which is why they read and this one didn't.

Two fixes, both in the kit rather than in ten models:

  • copings and curb counter-flashings move to the light tier — which is also just true, capping metal is lighter than the upstand under it. Every parapet, curb and skylight now has a horizontal highlight to read against.
  • wear rub was set near zero on my reasoning that "nothing rubs a roof". True of a membrane, false of every edge a boot or ladder crosses — and it removed the edge definition separating one plate from the next. steel had no wear profile at all.

Before / after:

after

Pushed. typecheck clean, bun test 49/0.

Still weak, and I'd rather say so than have you find it: roof-antenna-mount is a needle on a slab, and sloped-sci-fi-roof barely reads as a slope. Both need geometry work, not palette. Say the word and I'll do those two before you look again — or if you'd rather this batch waited while the others land, that's reasonable too.

🤖 Posted by Claude Code

The two models flagged as still weak after the palette pass. Both needed
geometry, not colour.

roof-antenna-mount was a 70 mm tube on a slab and read as a flagpole. A mast
on a roof is a lever resisted by ballast, and it is a lattice for a real
reason: a triangulated frame carries the same moment at a fraction of the
wind area. It is now a three-leg lattice on hinged base plates, with a ring
and a diagonal at every bay. The equipment is modelled rather than implied -
headframe, three sector panels, an offset dish, a lightning finial above
everything it protects, and the cable bundle running the full height into a
gland on its own curb.

sloped-sci-fi-roof ran a 0.9 m rise across a 4 m bay in six 60 mm steps, so
each riser was shorter than the panel was thick and the whole thing read as
a flat card on a slab. The rise is now 1.7 m in five steps, which makes each
riser a real vertical face - and that face is the entire silhouette. Risers
and the ridge closure sit in the light tier so the slope reads as a stair of
highlights rather than one grey wedge.

typecheck clean, bun test 49/0.
@reposlayer

Copy link
Copy Markdown
Author

Both done, pushed.

roof-antenna-mount was a 70 mm tube on a slab — a flagpole. A roof mast is a lever resisted by ballast, and it is a lattice for a real reason: a triangulated frame carries the same moment at a fraction of the wind area. Now a three-leg lattice on hinged base plates with a ring and a diagonal at every bay, plus the equipment modelled rather than implied — headframe, three sector panels, offset dish, lightning finial, and the cable bundle running the full height into a gland.

sloped-sci-fi-roof ran a 0.9 m rise across a 4 m bay in six 60 mm steps, so every riser was shorter than the panel was thick and it read as a flat card. Rise is now 1.7 m in five steps — each riser is a real vertical face, and that face is the whole silhouette. Risers in the light tier so the slope reads as a stair of highlights.

roof batch

typecheck clean · bun test 49/0 · registry unchanged in count.

🤖 Posted by Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants