Voyage · EventFarm Parity Roadmap
The story corpus describes user journeys; this page describes our progress through them. Each closed factory cycle leaves behind a closure markdown, an artifact bundle, and an updated parity matrix entry. Each in-flight or queued cycle has a brief that names what it intends to close. Demoted predicates and surfaced bugs name themselves so the next cycle has a clear target.
Last updated: 2026-04-29 ·
Cycles closed since 2026-04-29 morning: 3 (EF-074 tightening, W1 mailing, EF-073 EFx Poll) ·
Source matrix: voyage/docs/parity/eventfarm-capability-matrix.md ·
Evidence: all test results
100 EventFarm capabilities, status as of the last factory cycle. Counts are deployed-runtime-validated.
Newest first. Pre/post numbers are passed-probe counts under strict predicates against the deployed surface. The Ratchet pattern: declare → measure → diff → close → re-measure → tighten.
Net-new attendee voting surface and station display surface, built to spec. Reuses the EF-074 visualizer-spec-workflow socket plumbing, snapshot/delta protocol, and tally semantics. Organizer admin (question setup, pause, free-text moderation) intentionally deferred — needs admin auth/action wiring.
poll-5k-load — F88 evidence has 206 missing/dropped acks under strict zero-drop predicateworkers/events doesn't yet expose /v1/live/events/{eventId}/polls/{pollId}/votes — idempotency proven via harness transport interception, real endpoint shape is follow-upd79a1b2 · 75f0559 · adff28b (aperture) · 3a89f34 (voyage)
Mailing-queue-ops Deliverable 3 closed: 99/100 → 100/100 within five-minute SLO. Root cause: duplicate-invocation race between request-side waitUntil fast path and Cloudflare Queue consumer; missing stale-sending reconciler. Fix shipped both paths (defense in depth).
queued_count=0; D1 showed 31 recipient + 31 outbox rows; mailing row remained sending with zero counterssending rows from recipient/outbox evidencefb6f884 · 976279c · 5323e4b (voyage)
Three demoted predicates from Cycle 1 got strict-predicate teeth. Result: zero probes flipped green — instead, three real client-side bugs were surfaced as honest failures. The Ratchet doing its job: replacing demotion-by-skip with demotion-by-failure-with-evidence.
visualizer-ws-adapter.mjs for delta injection — out-of-order, foreign-eventload-harness-wrapper.mjs wraps F88 substrate as a story-runner predicateea76be3 · abcc49c · 81a98ce · 8fb3542 (aperture) · 593905b (voyage)
First end-to-end execution of the Ratchet on a real EF row. Net-new visualizer-spec-workflow component built to spec, deployed alongside the legacy visualizer, then runtime-probed by the story harness. Old visualizer-workflow.tsx retained as reference until the 24-hour verification window completes.
2eae434f serving visualizer.vxge-aperture.porivo.com/poll-results45f6de2 · 18b543d · 411ca63 (aperture) · 585d955 (voyage)
Currently no cycle dispatched. Add an entry here when dispatch-codex.sh is fired and the run dir's status is RUNNING.
— none —
Ready to dispatch when an operator is at the keyboard. Briefs at ~/voyage-ef-parity/factories/.
Address the three real bugs the EF-074 tightening cycle surfaced. Each is a discrete client-side fix in visualizer-spec-workflow.tsx; the harness adapters are ready to re-verify under strict predicates.
visualizer-spec-workflow.tsx release pathCloses the organizer-admin lanes deferred from both EF-073 and EF-074: organizer-pause-mid-poll, free-text moderation, question-type setup, start/pause/close CTAs. Needs admin auth/action wiring before any of these predicates can flip green.
organizer-pause-mid-poll, free-text-moderation, organizer-side question-type-single-multi-free-textTwo more EFx rows in the same trunk (efx-station-shell). EF-077 needs native NFC hardware proof to fully close; EF-078 has a sponsor-mobile-app gap. Both can be partially closed using the EF-073 net-new pattern — attendee/station-side first, hardware/native-side later.
Tracked in docs/planning/wave-j-ii-roadmap.md. W3 blocked on Stripe token/account access. W4 blocked on Gate 7 fleet provisioning. W5 (50k VM driver), W6 (operating history), W7 (pen test), W8 (SOC 2 + DSR + PCI) are all sequenced after W3/W4.
Strict predicates flushed these out. Each is a documented gap with a known target cycle. None of them existed in the pre-Ratchet view of the world.
Adapter holds seq N, injects N+2 first, then releases N. Visualizer reverts to the seq-N tally instead of converging on the strictly-ordered final state. Expected: snapshot-replace semantics, or queue-and-replay. Actual: latest-wins.
Adapter injects a delta whose envelope eventId is foreign. The visualizer's WebSocket message handler doesn't filter by event id, so the foreign delta updates local state. Server-side DO boundary holds; client-side filter missing.
Existing F88 5k-concurrent evidence has 206 ack misses despite p99 of 512ms (under the 1500ms story threshold). Strict zero-drop predicate fails. Latency is fine; reliability is not. Substrate-level, not client.
Story expects POST /v1/live/events/{eventId}/polls/{pollId}/votes. Existing live votes are /v1/live/sessions/:sessionId/votes with vote_id dedupe. Idempotency proven via harness transport interception this cycle, but real endpoint shape is follow-up.
Generic ui-progress-bar value-state assertions, ui-data-table handler/state fixtures, and ui-status-pill fixture labels don't map cleanly to display-only EFx instances. Stays demoted rather than force-passed.
Cross-cycle observations. These shape how we run the next factory.
Three cycles in a row (EF-074 build, EF-074 tighten, EF-073 build) all closed end-to-end with the same shape: declare → measure → diff → close → re-measure → tighten. Each leaves a closure markdown, an artifact bundle, pre/post JSONL, and a matrix re-stamp. The pattern is now repeatable; subsequent EFx rows arrive with significantly less per-cycle setup overhead.
EF-074 Cycle 1 demoted 5 predicates with documented blockers. Cycle 2 closed 3 of them (out-of-order, cross-station, n-concurrent) by building the named infrastructure (visualizer-ws-adapter.mjs, load-harness-wrapper.mjs). Result: zero probes flipped green numerically, but three real bugs got surfaced as strict failures instead of soft skips. The demotion ledger is paying compound interest.
EF-074 Cycle 1 chose net-new build over incremental refactor of the existing visualizer-workflow.tsx. Reasoning held up: the existing component had zero spec'd data-test attributes, no tier-3 inheritance points, no display-only marker. Net-new also produced a clean reuse boundary (socket plumbing, snapshot/delta, module-switch FSM) that EF-073 inherited directly — Cycle 1 of EF-073 reused the EF-074 hooks instead of reinventing them.
Every passOrFail() in these cycles requires more than 2xx. idempotent-vote requires the server-side tally to count exactly one. cross-station-isolation requires zero local tally mutation. color-contrast requires minRatio: 7 (distance-viewing target, not the default 4.5). Lax predicates were how the legacy mailing flow showed 99/100 looking like a pass — strict predicates surface the gap.
voyage, not voyage-aperture
Lesson from the W1 mailing factory. The platform repo (voyage) owns workers, shared packages, and the parity matrix. voyage-aperture owns the tenant deployment surface — React tenant-shell, story corpus, harness, tenant-specific configs, deploy scripts. The W1 mailing brief incorrectly named voyage-aperture as the worker home; the factory ignored that and committed correctly. Future briefs should target both repos when worker code + matrix re-stamp + closure docs all need updates.
W1 closed the stuck-sending edge with two layers: (1) hardened the duplicate-invocation race in the request-side fast path, and (2) added a notifications-cron reconciler that rebuilds counters for stale sending rows from recipient/outbox evidence. Either alone would have closed the observed case; together they cover the class of bug. Operational fixes earn their second layer.
CreateProcess Rejected stalls
Three cycles dispatched serially today, all completed cleanly via dispatch-codex.sh with gpt-5.5 + high reasoning + sandbox bypass. The CreateProcess Rejected 0% CPU stall pattern (cpu_time=0s, stdout_age >60s) was not observed today. Continue serializing until that mode is understood.
EF-074 Cycle 1's harness commit pushed to origin (aa13a25) before local polish landed (45f6de2 — same parent, 22 more lines of delta-injection gating + hex/srgb color parsing). Resolved with a merge commit preserving the local superset. Pattern to watch: factory-pushed commit + local polish on the same surface during the same session.
Hand-maintained for now. Future automation possible from the underlying data sources.
After each completed factory:
pnpm exec node apps/stories-pages/scripts/publish-findings.mjs to copy new JSONL/proof artifacts into the published findings directory./findings?run=...&probe=... row when available.voyage/docs/parity/eventfarm-capability-matrix.md.voyage-aperture-stories; UI deploys still happen from their own app/project.Data sources: matrix at voyage/docs/parity/eventfarm-capability-matrix.md · findings at apps/stories-pages/public/findings/ · closure markdowns at voyage-aperture/docs/parity-factory/ and voyage/docs/parity-factory/ · briefs at ~/voyage-ef-parity/factories/ · artifact bundles at voyage-aperture/artifacts/parity-factory/.