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

vercelBot commented Jul 24, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJul 24, 2026 1:14pm

Request Review

@github-actionsgithub-actionsBot 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 freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

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

@os-zhuang