Turns a one-line brief into a code-checked floor plan, and the plan into a tender document two panel manufacturers can quote against.
A brief becomes a dimensioned plan with elevations, a semantic BIM and an IFC export, checked against the in-force residential code for its jurisdiction. From there the geometry becomes a provider-neutral panel specification: wall runs, rough openings, roof planes and a required R-value — never a thickness, a core or a brand, because naming any of those hands the job to one supplier by definition.
The kit is structural insulated panels. It was WikiHouse Skylark until the block library stopped matching what the generator produced — Skylark ships roof blocks at 0 and 42 degrees, and six of seven roof styles here are neither.
The browser app remains the review surface: a gallery of generated and traced plans, each opening as a customer-facing product page with repair, export and debug tools available but not default.
- PROJECT_STATUS.md is the current handoff: active architecture, target plans, current blockers, metrics, cleanup stance, and next work.
- OPERATING_PRINCIPLES.md captures the relevant engineering principles for this repo: lossless paired artifacts, boundary validation, browser QA, bug-shape audits, and semantic/presentation separation.
- Browse paired Den-style plan candidates with bed/bath, square-footage, level, roof, and readiness filters.
- Show gallery cards with plan thumbnail, elevation preview, status, and Design / Presentation / Brochure quality chips.
- Open a product detail page with clean BIM/Product 3D as the primary canvas.
- Keep Compare, Overlay, and Semantic review views for source/render/JSON evidence.
- Keep the old component/review rail hidden behind explicit
Review Tools. - Generate scoped GPT repair prompts for blocked artifacts and apply RFC 6902 JSON Patch repairs through validation.
- Export stable product packets while keeping Manufacturing and IFC readiness separate from Design/Brochure quality.
The app is not the generator and should not repair layouts silently. Generation and visual reasoning happen through GPT image+JSON handoffs. Local code validates, scopes, applies, rolls back, renders, and exports.
The active app has one browser-passing review artifact and two blocked review artifacts. Promotion still does not mean the whole product goal is done:
outpost-medium/proposal-paired-v11currently passes desktop and laptop brochure QA after scoped source-anchor, fixture, and wall primitive repairs.a-frame-bunk/proposal-paired-v1is still blocked under strict Brochure QA. A scoped bed-span patch and fixture-body profile sweep improved the score and cleared the fixture-specific blocker, but broader drawing-language drift remains. A source-image crop overlay experiment was rejected as too fragile and too heavy for product output.a-frame-22/proposal-paired-v10remains the hardest source/render drift case. Fixture-body profile tuning improved fixture drift, but door, fixture, ladder, dashed-void, and broader primitive drawing-language drift are still real blockers.
Do not call a plan brochure-ready from manifest status or validation chips alone. A release candidate needs Design Quality, Presentation Quality, Brochure Quality, and browser screenshots to agree.
- Open
/to browse the product gallery. - Filter plans by bedrooms, baths, square footage, levels, roof type, or readiness status.
- Open a plan for Product 3D, Compare, Overlay, and Semantic review.
- If the plan is blocked, use
Repair Promptfrom the card orRepair With GPTfrom the detail page. - Send the scoped prompt to GPT and request JSON Patch only.
- Evaluate the returned patch with
npm run repair:evaluate; it applies, rerenders, recomputes drift, and rolls back if the patch is worse. - Re-run
npm run qa:brochureonly when you need a full browser evidence packet. - Export the brochure packet only when Design, Presentation, and Brochure quality pass.
Optional local API handoff:
cp .env.example .env.local
# Fill OPENAI_API_KEY and OPENAI_REPAIR_MODEL in .env.local.
npm run repair:queue -- --out artifacts/brochure-qa/next-repair-prompts-all.md --bundle-dir artifacts/brochure-qa/repair-bundles-all --zip --all
npm run repair:gpt -- --bundle artifacts/brochure-qa/repair-bundles-all/a-frame-22-proposal-paired-v10-semantic-rebuild --model "$OPENAI_REPAIR_MODEL" --yes
npm run repair:evaluate -- --bundle artifacts/brochure-qa/repair-bundles-all/a-frame-22-proposal-paired-v10-semantic-rebuild --patch artifacts/brochure-qa/repair-bundles-all/a-frame-22-proposal-paired-v10-semantic-rebuild/patch.json
npm run qa:brochurerepair:gpt reads OPENAI_API_KEY from the shell or .env.local, attaches the bundle's visual evidence locally, writes patch.json, and runs repair:apply --dry-run for scope validation. It never exposes provider keys to browser code.
Manual ChatGPT handoff:
npm run repair:queue -- --out artifacts/brochure-qa/next-repair-prompts-all.md --bundle-dir artifacts/brochure-qa/repair-bundles-all --zip --all
# Upload one zip from artifacts/brochure-qa/repair-bundles-all to ChatGPT and save the returned JSON Patch text as response.txt.
npm run repair:ingest -- --bundle artifacts/brochure-qa/repair-bundles-all/a-frame-22-proposal-paired-v10-semantic-rebuild --response response.txt
npm run repair:evaluate -- --bundle artifacts/brochure-qa/repair-bundles-all/a-frame-22-proposal-paired-v10-semantic-rebuild --patch artifacts/brochure-qa/repair-bundles-all/a-frame-22-proposal-paired-v10-semantic-rebuild/patch.json
npm run qa:brochureTo run the same loop explicitly without installing cron:
npm run repair:loop -- --url http://127.0.0.1:3001 --iterations 1
npm run repair:loop -- --url http://127.0.0.1:3001 --iterations 3 --model "$OPENAI_REPAIR_MODEL" --yesWithout --yes, repair:loop refreshes browser QA, regenerates uploadable repair bundles, and prints the next exact handoff. With --yes, it requires OPENAI_API_KEY, requests a scoped patch, applies it through the validator, reruns browser QA, and rolls back unless the target plan either loses blockers or improves visual-drift score.
The source of truth is no longer a floorplan alone. A brochure-ready candidate should be a paired architectural artifact:
- GPT proposal floorplan image
- deterministic semantic floorplan JSON
- deterministic floorplan render
- front and side elevation images or elevation traces
- semantic roof/elevation JSON
The roof/elevation block must be anchored to the same footprint, wall graph, openings, and floor levels as the plan. The app may render a provisional roof from roofStyle, but a plan is not roof-complete until JSON contains explicit roof planes/elevations:
roof.styleroof.ridgeDirectionroof.ridgeLineroof.eaveHeightFtroof.ridgeHeightFtroof.pitchDegroof.overhangFtroof.planes[].polygon3delevations[].facadeWallIdselevations[].openingselevations[].outline
Validation must catch a roof/elevation that changes footprint width/depth, moves wall openings, invents a different facade, or renders a 3D roof from generic style instead of paired roof geometry.
Render themes are separate from geometry. The same semantic plan can be drawn as a review model, a Den brochure plan, a soft furnished floorplan, a white A-frame cutaway, or a construction-kit view without changing rooms, walls, fixtures, roof, or elevations.
Theme data may specify materials, wall colors, background, lighting, cutaway mode, fixture detail, furniture style, labels, and camera presets. Theme data must never move geometry or make a blocked plan pass validation.
The default theme is product-presentation. Debug guides, anchors, source traces, grids, and legacy component-kit geometry must stay behind explicit Debug/Review mode.
dev-compiler image-loop -> symlink -> public/data/den-image-loop
proposal-manifest.json -> paired artifact selection and promotion state
paired-generation-queue -> next GPT repair/regeneration targets
library/components -> retained component metadata with no legacy home defaults
Legacy SpatialIR home defaults, static home JSON, and old canonical seed paths are intentionally excluded from app selection.
Legacy generator/analyzer files from the pre-paired SpatialIR loop have been removed from the active foundation. The paired smoke check guards that they do not silently return.
- Next.js 16 App Router
- React Three Fiber + drei for optional 3D review
- Tailwind CSS 4
- TypeScript
npm run dev # dev server at localhost:3000
npm run build # production/static build
npx tsc --noEmit # typecheck
npm run paired:smoke # paired data/default-selection smoke check
npm run qa:brochure # browser QA: gallery, repair, product views, compare/overlay, export packet
npm run repair:queue # print next scoped GPT repair prompt for each blocked QA packet
npm run repair:queue -- --bundle-dir artifacts/brochure-qa/repair-bundles-all --all # create uploadable GPT repair folders with prompt + evidence images
npm run repair:queue -- --bundle-dir artifacts/brochure-qa/repair-bundles-all --zip --all # also create one uploadable zip per repair bundle
npm run repair:gpt -- --bundle artifacts/brochure-qa/repair-bundles-all/a-frame-22-proposal-paired-v10-semantic-rebuild --model "$OPENAI_REPAIR_MODEL" --yes # optional local OpenAI handoff, writes patch.json
npm run repair:loop -- --url http://127.0.0.1:3001 --iterations 1 # explicit QA -> bundle -> handoff loop, no cron
npm run repair:ingest -- --bundle artifacts/brochure-qa/repair-bundles-all/a-frame-22-proposal-paired-v10-semantic-rebuild --response response.txt # extract/validate patch.json from copied ChatGPT output
npm run repair:ingest -- --bundle artifacts/brochure-qa/repair-bundles-all/a-frame-22-proposal-paired-v10-semantic-rebuild --latest-download # use newest likely ChatGPT patch from ~/Downloads
npm run repair:doctor # report API/model/bundle/session/QA readiness and print the next repair commands
npm run archive:stale # move manifest-archived paired sidecars/backups/debug traces out of active folders
npm run goal:audit # strict completion audit for the Drafted-style product goal
npm run repair:prompt -- --packet artifacts/brochure-qa/a-frame-bunk-brochure-repair-packet.json --layer "level frames"
npm run repair:evaluate -- --bundle artifacts/brochure-qa/repair-bundles-all/a-frame-22-proposal-paired-v10-walls --patch patch.json # apply, render, drift-check, and rollback if worse
npm run repair:apply -- --packet artifacts/brochure-qa/a-frame-bunk-brochure-repair-packet.json --layer "level frames" --patch patch.json # raw scope-only apply for debuggingartifacts/brochure-qa/repair-bundles-all is the active repair-bundle directory. Older one-layer bundle output was archived and should be regenerated rather than reused.
npm run image:paired:queue
npm run image:paired:accept -- <planId> <proposalId> <imagePath> <pairedJsonPath>
npm run image:paired:accept -- <planId> <proposalId> <imagePath> <pairedJsonPath> --review-passed