Skip to content

fix(showcase): seed all five projects through the FSM + surface seed outcomes in the boot banner (#3415)#3435

Merged
os-zhuang merged 1 commit into
mainfrom
fix/3415-seed-vs-fsm
Jul 24, 2026
Merged

fix(showcase): seed all five projects through the FSM + surface seed outcomes in the boot banner (#3415)#3435
os-zhuang merged 1 commit into
mainfrom
fix/3415-seed-vs-fsm

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #3415 — both halves: the self-contradictory fixture AND the surfacing gap that let it ship silently.

Fixture: walk the FSM instead of violating it

project_status_flow gates inserts to initialStates: ['planned']; the seed wrote terminal statuses directly, so 4/5 projects, 9/10 tasks (master-detail), 3/3 memberships were rejected on every boot. Now the seed runs in three phases (same-object datasets execute in declaration order — stable topological sort):

  1. Phase 1 — enter: all five projects insert as planned, explicitly (seed inserts do not apply select defaults — the Accounts seed documents this), with mode: 'ignore' so replays leave walked rows untouched.
  2. Phase 2 — activate: planned → active for the four that move on.
  3. Phase 3 — settle: active → on_hold (Compliance Audit) and active → completed (Legacy Sunset).

The walk doubles as a live demo of the state machine the seed used to violate. A new completed → active reopen transition (a real PM affordance — cancelled could already be revived via planned) keeps the replay walk legal instead of dead-ending; initialStates is untouched, so the #3165 entry gate is exactly as strong as before.

Surfacing: a Seeds line in the boot banner

SeedLoader's own logs are double-swallowed (info < default warn level, and serve's boot-quiet stdout window). Following the seededAdmin/automation-summary precedent: AppPlugin stashes per-boot counters on the kernel (seed-summary service, accumulating across apps), serve reads them back after restoreOutput(), and the banner prints:

  • clean: Seeds: 130 inserted · 6 updated (dim)
  • dropped rows: ⚠ Seeds: 114 inserted · 30 REJECTED — run with OS_LOG_LEVEL=info to see each reason (yellow)

That yellow line is literally what the old fixture prints under this banner — it could never have shipped broken with the line in place.

Verification

  • Fresh boot (wiped SQLite): 5 projects across four statuses (active×2 / on_hold / completed / planned), 10 tasks, 3 memberships; banner Seeds: 130 inserted · 6 updated — the 6 updates are exactly the FSM walk. Before the fix on the same runtime: 1/1/0 and ⚠ 114 inserted · 30 REJECTED.
  • Replay boot: walked statuses preserved, zero rejections (3 inserted · 123 updated · 10 skipped).
  • New gates, proven red first: seed.test.ts statically replays every FSM-gated object's seed phases — two rounds, fresh boot AND replay — against initialStates/transitions (red on the old fixture and red without the reopen edge); format.seed-summary.test.ts covers the banner contract (3 cases). @objectstack/runtime and @objectstack/cli suites pass.

Known pre-existing follow-up

#3434mode: 'insert' datasets (memberships) duplicate on every replay boot (3→6). Masked until now because the rows never inserted at all; needs composite externalId or an explicit key, filed separately.

Console UI assets aren't present in a fresh worktree (objectui:refresh artifact), so browser-level kanban verification ran on DB counts + the earlier dogfood evidence that the board renders correctly the moment status-matched rows exist; this PR touches no renderer code.

🤖 Generated with Claude Code

…ed outcomes in the boot banner (#3415)

The project seed wrote terminal statuses directly on insert, but
project_status_flow gates inserts to initialStates: ['planned'] — so 4/5
projects, 9/10 master-detail tasks and 3/3 memberships were rejected on
every boot, silently: SeedLoader's logs sit under the default warn level
AND inside serve's boot-quiet stdout window.

Fixture: seed projects in three phases. Phase 1 inserts all five as
'planned' (explicitly — seed inserts do not apply select defaults) with
mode 'ignore' so replays leave walked rows untouched; phases 2-3 then walk
them along legal transitions (planned→active→on_hold/completed), doubling
as a live FSM demo. A new 'completed → active' reopen transition (a real
PM affordance — cancelled could already be revived) keeps the walk legal
on replay. Fresh boot: 5 projects across four statuses, 10 tasks, 3
memberships, zero rejections; replay preserves walked states.

Surfacing: AppPlugin stashes per-boot seed counters on the kernel
('seed-summary'); the serve banner prints 'Seeds: X inserted · Y updated
· Z skipped', escalating to a yellow '⚠ … N REJECTED' line when rows
dropped — before the fix that line read '114 inserted · 30 REJECTED',
after it reads '130 inserted · 6 updated'.

Gates: seed.test.ts now statically replays every FSM-gated object's seed
phases (two rounds — fresh boot AND replay) against initialStates and
transitions; format.seed-summary.test.ts covers the banner contract. Both
proven red against the old fixture / a dead-end terminal state.

Known pre-existing follow-up (#3434): mode:'insert' datasets (memberships)
duplicate on every replay boot — masked until now because the rows never
inserted at all.

Closes #3415

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 24, 2026 1:14pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jul 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/cli, @objectstack/runtime.

30 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/skills-reference.mdx (via packages/cli)
  • content/docs/api/client-sdk.mdx (via @objectstack/cli)
  • content/docs/api/data-flow.mdx (via @objectstack/cli)
  • content/docs/api/environment-routing.mdx (via @objectstack/cli)
  • content/docs/api/error-catalog.mdx (via @objectstack/cli)
  • content/docs/api/index.mdx (via @objectstack/runtime)
  • content/docs/api/wire-format.mdx (via @objectstack/runtime)
  • content/docs/automation/hook-bodies.mdx (via packages/cli, @objectstack/runtime)
  • content/docs/concepts/north-star.mdx (via packages/runtime)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/runtime)
  • content/docs/deployment/backup-restore.mdx (via @objectstack/cli)
  • content/docs/deployment/cli.mdx (via @objectstack/cli)
  • content/docs/deployment/index.mdx (via @objectstack/runtime)
  • content/docs/deployment/production-readiness.mdx (via @objectstack/runtime)
  • content/docs/deployment/self-hosting.mdx (via @objectstack/cli)
  • content/docs/deployment/single-project-mode.mdx (via @objectstack/runtime)
  • content/docs/deployment/vercel.mdx (via @objectstack/runtime)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/cli, @objectstack/runtime)
  • content/docs/kernel/runtime-services/data-service.mdx (via packages/cli)
  • content/docs/kernel/runtime-services/index.mdx (via packages/cli)
  • content/docs/permissions/authentication.mdx (via @objectstack/cli, @objectstack/runtime)
  • content/docs/permissions/authorization.mdx (via packages/runtime)
  • content/docs/plugins/packages.mdx (via @objectstack/cli, @objectstack/runtime)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/cli)
  • content/docs/protocol/kernel/realtime-protocol.mdx (via @objectstack/cli)
  • content/docs/releases/implementation-status.mdx (via @objectstack/cli, @objectstack/runtime)
  • content/docs/releases/v16.mdx (via @objectstack/cli)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

showcase: 4/5 projects and 9/10 tasks are silently rejected on every boot (FSM initialStates vs seed data)

1 participant