Build Log · July 20, 2026

Alloy — Product/Workpiece/Arc Vertical Slice

Corrected the Product/Workpiece/Arc identity model through two review rounds, then built and proved a real end-to-end entry path (Workpieces → Product → Workpiece → Orient → Charge) — stopping honestly before Ignite, which needs its own dedicated rebuild.

  • Alloy
  • Architecture
  • Schema
design review rounds before build
3

design review rounds before build

design docs written
6

design docs written

files in the vertical-slice commit
32

files in the vertical-slice commit

real bugs caught by review before/after commit
3

real bugs caught by review before/after commit

Timeline

  1. Start

    Home page System State/Open Items real-data rewrite

    Earlier in the same session — real Forge Energy/Pressure/Mechanisms/Network wiring

  2. +2h

    Workpiece grouping investigation

    Zeb noticed Recent Workpieces looked like noise — traced to workpiece_id acting as both product AND workpiece identity

  3. +3h

    Product/Workpiece/Arc model proposed, then corrected twice

    First pass conflated Product and Workpiece; Zeb's review corrected concurrency, completion-condition timing, and the product registry design

  4. +4h

    Six design docs locked

    workpiece-model, schema-delta, migration-plan, screen-flow, product-registry-manifest, vscode-to-alloy-mapping

  5. +6h

    Vertical slice built solo overnight

    Schema migration, product registry sync, 5 new pages, Orient/Charge dual-mode

  6. +7h

    Zeb's review found 8 real issues

    Sync coupled to page render, migration mechanism unverified, lint not actually clean, concurrency mislabeled, unassigned Workpieces invisible, legacy classification scope creep, oversized commit, no live walkthrough

  7. +8h

    Full correction pass

    All 8 items addressed; found and fixed a live bug (os-engine/website hidden) during the correction; commit history rewritten into 3 coherent commits

  8. +9h

    Live click-through by Zeb

    Confirmed Workpieces → Alloy → Workpiece → Orient → Charge works; surfaced 3 more real gaps (Orient/Charge nav, delete Workpiece, prototype visual match)

  9. +9.5h

    Nav + delete shipped, visual-hardening plan written

    Session closed pending retro

What shipped

  • products/alloy/lib/db/schema.ts — new products table (kind/status enums), workpieces.productId + completionCondition + completionConditionDeferredReason, workpieceStatusEnum extended (draft/active/paused/completed/archived) with legacy 'banked' value PRESERVED not dropped

  • products/alloy/drizzle/migrations/0002_gifted_absorbing_man.sql — additive-only migration (CREATE TYPE, ALTER TYPE ADD VALUE, ADD COLUMN — zero DROPs), applied via drizzle-kit push, verified against real pre-existing rows (4 workpieces, 1 arc) before writing

  • forgekit-os/product-registry.json + forgekit-os/scripts/verify-product-registry.mjs — explicit 18-entry product/experiment/os manifest, NOT parsed from PROJECT_INDEX.md (verified that file omits Alloy itself, ForgeKit OS, and 4 real experiment folders), with validation + drift-report functions

  • products/alloy/lib/products-sync.ts + scripts/sync-products.mjs — idempotent DB sync from the manifest, wired as an explicit `npm run sync:products` command (NOT coupled to page render — corrected after review)

  • products/alloy/app/workpieces/page.tsx — rebuilt as a Product-grouped landing page (real DB Workpieces + legacy session history via lib/workpiece-classification.ts + an Unassigned Workpieces holding view for pre-model rows)

  • products/alloy/app/workpieces/[productId]/page.tsx — new Product workspace screen

  • products/alloy/app/workpieces/[productId]/[workpieceId]/page.tsx — new Workpiece detail screen (Start/Continue Session, completion condition, Arc history, delete)

  • products/alloy/app/orient/page.tsx — real per-Arc Orient mode (?arc=) added alongside the existing global dashboard mode; assembles Product/Workpiece identity, previous Arc's Bank summary, carried-forward return conditions

  • products/alloy/app/charge/page.tsx + ChargeContractPanel.tsx — Charge rewritten to session-scoped fields with inherited (read-only) Workpiece context, a completion-condition gate before finalizing, and Orient<->Charge back/forward navigation

  • products/alloy/lib/actions.ts — createWorkpiece (Product required, lightweight), startArc (session-entry dedup, NOT a concurrency model — resumes any existing open Arc rather than double-opening), setWorkpieceCompletionCondition, deleteWorkpiece (real cascading delete via existing FK onDelete:'cascade' chain), bankArc fixed to stop writing workpieces.status='banked'

  • products/alloy/components/DeleteWorkpieceControl.tsx — type-the-title-to-confirm destructive-action UI

  • 6 design docs in products/alloy/docs/ — workpiece-model, workpiece-schema-delta, workpiece-migration-plan, workpiece-screen-flow, product-registry-manifest, vscode-to-alloy-mapping — plus a 7th, visual-hardening-plan.md, scoping the next session's prototype-visual-matching pass

  • Home page (earlier in this session): SystemStatePanel/SystemOpenItemsPanel rewired to real Forge Energy/Pressure/Mechanisms/Network/spin/reuse data, new /health-engine page, Recent Workpieces/Forge Arcs/Active Workpiece restyled to a consistent icon-badge visual language

  • 3 stale workpiece_id session JSONs corrected (alloy-orient-screen-build, arcade-cartridge-grammar, duplication-sweep-followthrough) + _SCHEMA.md's workpiece_id section rewritten to require deriving the value from real touched paths

“The next Ignite session should begin from a trusted doorway, not from a foyer whose light switches have only been typechecked.”
— Zeb, in review, on why typecheck/build passing isn't the same as a verified product experience