Build Log
Owner Loop Audit, Hardening Charge, and §1 Terminal-State Discipline
September 2, 2026
Audited every real Owner Loop request across MedinaCHF and canvas-2, drafted and Council-reviewed a hardening Charge covering terminal-state discipline, evidence-trail completeness, and universal acceptance gating, then built and shipped §1 to MedinaCHF's real production DB — canvas-1 through canvas-4's schema push is a real, still-open item blocked on DB-owner credential access.
Timeline
What shipped
forgekit-os/charges/owner-loop-hardening-2026-09-02-charge.md — the finalized, Council-reviewed Charge covering §1 (terminal-state discipline), §2 (evidence-trail completeness), §3 (universal acceptance gating), §4 (owner-level acceptance test)
products/medinaCHF/lib/db/schema.ts — four-class lifecycle model: added humanNotifiedAt, promotionBlockedReason, promotionBlockedAt columns; removed 'human_notified' as a dispatch_status value
experiments/canvas-1/lib/db/schema.ts, canvas-2/lib/db/schema.ts, canvas-3/lib/db/schema.ts, canvas-4/lib/db/schema.ts — identical schema mirror of the same fix
products/medinaCHF/components/coordinator/AdminIntentPanel.tsx — updated the optimistic-UI object literal for the 3 new schema fields (tsc fix)
forgekit-os/scripts/dispatch-owner-loop-requests.mjs — fixed the notify-then-write race: lifecycle transition to 'awaiting_coordinator' now happens BEFORE the notification side effect, not after; human_notified_at is now evidence-only, set only on confirmed delivery
forgekit-os/scripts/record-promotion-outcome.mjs — new script; separates promote-actor-state.sh's git-mechanics job from Owner Loop lifecycle semantics; writes dispatch_status='promotion_blocked' for any non-clean-promote outcome using domain language, not implementation language
.github/workflows/actor-spawn.yml — new always-run finalization step invoking record-promotion-outcome.mjs after the promote step, regardless of its exit code
MedinaCHF's real production admin_intents table — schema pushed via drizzle-kit push, independently verified via a direct information_schema query against the real production Neon branch (ep-morning-mountain-ayi12ecg)
.github/workflows/owner-loop-hardening-schema-push-temp.yml — a temporary, one-off workflow to push the same 3 columns to canvas-1/2/3/4's real production DBs using existing CANVAS_N_OWNER_LOOP_DATABASE_URL secrets; found and fixed 2 real bugs in it this session (a /tmp module-resolution failure, and a neon()-vs-Pool DDL-permission-error-swallowing issue) but the underlying credential is the dispatcher's least-privilege role, which correctly lacks ALTER TABLE privilege — the push is still blocked on a real DB-owner credential as of this write-up
“we've been making changes to canvas2 3 and 4. it must be there somewhere”