ForgeKitFORGEKIT

Build Log

Alloy: Quench Ticket 3 — the crack concept (schema + query + action, no UI yet)

July 26, 2026

Built the real 'crack' concept for Quench — a two-event lifecycle (crack_discovered / crack_resolved) following the exact getActiveProposedStrike precedent, plus its query and server-action layer. Scoped correctly to schema/plumbing only, per the original 6-ticket plan — the Cracks & Routing UI panel is Ticket 5's job, not this one's.

AlloyQuenchCrackSchema
2
new arc_events types (crack_discovered, crack_resolved)
6
resolution routes defined
339/341
real tests passing (2 pre-existing, unrelated)

Timeline

Start
Resumed the original 6-ticket Quench plan at Ticket 3, per Zeb's 'keep developing ticket 3'
Bootstrap Arc's criteria-authoring work committed first, cleanly separating the two Arcs' diffs
+10m
Grep confirmed zero existing 'crack' references anywhere
Genuinely new concept, not an extension of anything
+20m
Designed as a two-event lifecycle, not one mutable event
Followed getActiveProposedStrike's exact established precedent (propose/resolve as separate append-only event types) rather than criterion_verified's simpler latest-wins shape — a crack has a real decision (the route) to make, not just a status to report
+35m
Schema pushed and independently DB-verified
Hit the same known drizzle-kit self-referencing-FK bug as Ticket 2; verified crack_discovered/crack_resolved live via direct pg_enum query, not trusted from db:push exit code
+50m
listCracksForArc query + recordCrack/resolveCrack actions built
Server-side validation of severity/route enums and required fields, since payload is JSONB and the DB can't enforce it
End
tsc clean, 339/341 tests passing (2 pre-existing unrelated), no UI built — correctly deferred to Ticket 5

What shipped

products/alloy/lib/db/schema.ts — crack_discovered and crack_resolved values added to arcEventTypeEnum, additive-only, DB-verified live

products/alloy/lib/db/queries.ts — CRACK_SEVERITIES/CrackSeverity, CRACK_ROUTES/CrackRoute, CrackDiscoveredPayload/CrackResolvedPayload types, Crack interface, listCracksForArc (derives unresolved-vs-resolved the same way getActiveProposedStrike derives active-vs-resolved)

products/alloy/lib/actions.ts — recordCrack (discover) and resolveCrack (route + resolution) server actions, both server-validating their enums/required fields since payload is JSONB