ForgeKitFORGEKIT

Build Log

Alloy — Product/Workpiece/Arc Vertical Slice

July 20, 2026

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.

AlloyArchitectureSchema
3
design review rounds before build
6
design docs written
32
files in the vertical-slice commit
3
real bugs caught by review before/after commit

Timeline

Start
Home page System State/Open Items real-data rewrite
Earlier in the same session — real Forge Energy/Pressure/Mechanisms/Network wiring
+2h
Workpiece grouping investigation
Zeb noticed Recent Workpieces looked like noise — traced to workpiece_id acting as both product AND workpiece identity
+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
+4h
Six design docs locked
workpiece-model, schema-delta, migration-plan, screen-flow, product-registry-manifest, vscode-to-alloy-mapping
+6h
Vertical slice built solo overnight
Schema migration, product registry sync, 5 new pages, Orient/Charge dual-mode
+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
+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
+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.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
Alloy — Product/Workpiece/Arc Vertical Slice — July 20, 2026 · ForgeKit