Skip to content

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

Description

@os-zhuang

Summary

The showcase seeds 4 of 5 projects and 9 of 10 tasks are silently rejected on every boot. The running app has exactly one project and one task. Nothing in the boot log says so.

The platform is behaving correctly — this is a self-contradictory fixture plus a surfacing gap.

Root cause

showcase_project declares its own FSM entry gate (#3165):

// project.object.tsevents: ['insert','update'],initialStates: ['planned'],// "without it a project could be born already completed"

The project seed in the same repo creates 5 projects with status:

Projectseeded statuslegal on insert?
Website Relaunchactive✗ rejected
Data Platformactive✗ rejected
Compliance Auditon_hold✗ rejected
Mobile Appplanned✓ survives
Legacy Sunsetcompleted✗ rejected

Seeds deliberately run validation — SeedLoaderService.SEED_OPTIONS = { isSystem: true, skipTriggers: true }, commented "Lifecycle HOOKS (derived/default fields, validation) still run." So the gate fires and correctly rejects the four.

showcase_task.project is a master-detail to project, and 9 of the 10 seeded tasks point at the three projects that were never created. Only App wireframesMobile App survives.

showcase_project_membership (references team + project) lands 0 of 3 for the same reason.

Evidence

Built artifact is correct — the loss is at load time:

dist/objectstack.json: showcase_project records=5 showcase_task records=10
sqlite dev.db: showcase_project 1 row showcase_task 1 row
showcase_project_membership 0 rows (3 declared)

knex debug on a wiped DB shows exactly one single-row insert per table:

insert into `showcase_project` (…) values (?, …) returning * ← 1 statement
insert into `showcase_task` (…) values (?, …) returning * ← 1 statement
insert into `showcase_account` (…) select ? … union all select ? ← batched, 14 rows ✓

Impact

The showcase's own seed docstring says it is "sized to feed every view: every Kanban column is populated, tasks carry due/start/end/created dates (calendar, gantt, timeline) and a work location (map)". None of that is true at runtime:

  • Chart Gallery — "One widget per chart family… honest visual coverage" — renders 14 charts on a single data point. Total Tasks 1, every bar/pie/funnel/radar/treemap/sankey degenerate, both month-bucketed trend lines a single point.
  • Kanban: 1 card in 1 column (5 columns were intended).
  • Gantt / timeline / calendar / map: one item each.
  • Project list: 1 row of 5; no status or health variety, so the health-progression FSM demo has nothing to show either.
  • This also blocks v16.0 browser test checklist — exercise every 16.0 feature in the running app #3358 §3 "Report drill-through range" — there is no meaningful date bucket to drill.

Silent failure

SeedLoader does record each rejection (this.logger.warn('[SeedLoader] …'), and buildResult carries the errors), but not one [SeedLoader] line reaches os dev output — I ran with OS_LOG_LEVEL=debug LOG_LEVEL=debug DEBUG=* (19k lines of knex tracing) and grepped case-insensitively: zero hits. The boot banner's only seed mention is seeded on empty DB · dev only.

So a fixture can lose 90% of its rows with no signal at all. Even if the fixture below is fixed, a boot-time summary of seed inserts/rejections would have caught this immediately — and would catch the next one.

Options for the fixture

  1. Two-phase seed (respects and demonstrates the FSM). Insert all 5 as planned, then walk them to their target status via mode: 'update' datasets. The transition map allows planned→active and active→{on_hold, completed}, so it needs two update passes (a single pass cannot do the 2-hop jumps). Needs confirmation that ordering between multiple datasets on the same object is deterministic.
  2. Seed everything as planned. One-line fix, but the project list loses all status/health variety and several demos flatten.
  3. Widen initialStates. Cheapest, but it deletes the point of enhancement: state_machine 校验规则在 INSERT 上是 no-op —— 无法强制记录的初始状态(declared ≠ enforced) #3165 — "a project could be born already completed" is exactly what the gate exists to prevent.

I'd take (1) if same-object dataset ordering is guaranteed, otherwise (2) plus a follow-up. Flagging rather than picking, since it's a showcase-design call.

Found during the #3358 v16 browser sweep (§3).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions