state-model

review

visual tier

Draft Stonk State Model Review

Alignment review for the proposed logical domain model attached to the promoted first-pick-speed user-flow branch. This page is pre-approval: it previews the canonical files that will be written only after compiled approval YAML is returned.

Alignment date: 2026-07-02 · Command: $state-model draft-stonk · Alignment page: alignment/state-model-draft-stonk.html

Decision Boundary

This review asks whether the synthesized model is ready to become the branch-scoped state model for branches[first-pick-speed]. If approved later, the agent will write:

Not written yet: canonical domain model, model-tree manifest, glossary additions, and flow-tree model refs.

Source Evidence

ArtifactStatusRole In Synthesis
design/flow-tree-draft-stonk.yamlApproved flow rootBranch anchor and route guard; route remains unchanged.
design/user-flow-draft-stonk.mdApproved flow mapSurface, state, decision, and failure-path evidence.
design/_working/state-model-draft-stonk-brief.mdShared contextScope, assumptions, framework order, and cross-framework facts.
event-modeling.mdComplete intermediateTimeline of commands, events, and read models.
domain-model.mdComplete intermediateDDD aggregate, entities, value objects, policies, and invariants.
state-machine.mdComplete intermediateLifecycle states, transitions, and UI-state mappings.
data-model.mdComplete intermediateLogical ERD, attributes, relationships, and cardinality.
contract-map.mdComplete intermediateLogical command/query request, response, and error shapes.

Model Overview

Aggregate Root

DraftSession is the consistency boundary for first-pick speed. It owns participants, turns, picks, taken stock choices, current validation result, draft events, trust boundary, and data label.

Primary Proof Point

The model optimizes the path from start intent to first valid stock pick, then carries enough board continuation to show bot-pick handoff and next-turn readiness.

Guardrails

TrustBoundaryPolicy, DataLabelPolicy, PickValidationPolicy, and TurnOwnershipPolicy keep the draft framed as a game, not trading, advice, prizes, brokerage, or live market truth.

Extension Posture

Later promoted branches should extend this substrate for equal-dollar standings, concept explanation, and replay/share/invite instead of replacing it.

State And Entity Diagrams

DraftSession aggregate root Participant Turn Pick StockUniverse StockChoice ValidationResult TrustBoundary + DataLabel DraftEvent
not_startedStart surface ready.
startingQuick draft command accepted.
active_waiting_for_first_pickStock chooser ready.
validating_first_pickPick attempt pending.
first_pick_recordedGame pick recorded.
in_progressBoard continuation and bot handoff.

Proposed Domain Model Document

Proposed target path after approval: design/domain-model-draft-stonk.md.

# Draft Stonk Domain Model

> Topic: `draft-stonk`
> Branch scope: `first-pick-speed`
> Status: Proposed for alignment review. Write canonical only after approval.
> Source frameworks: event-modeling, domain-model, state-machine, data-model, contract-map.

## Scope

This model attaches the first logical domain/state/contract substrate to `branches[first-pick-speed]` in `design/flow-tree-draft-stonk.yaml`. It models the first visit through first valid stock pick and the compact draft-board continuation needed to show turn state and bot handoff.

The model is logical only. It does not decide storage engines, database schema, endpoints, URLs, authentication, migrations, indexes, deployment, production market-data providers, analytics transport, legal wording, or production recovery depth.

## Ubiquitous Language Glossary

- Social fantasy stock draft: a no-money, no-prize game where users make stock picks as fantasy selections.
- Market take: a user's opinion about a stock or market story, converted into a game pick.
- Quick draft: the short draft loop that starts without account, payment, brokerage, or league setup.
- Draft session: the bounded game instance that owns participants, turns, picks, taken stocks, events, trust boundary, and data labels.
- Stock universe: the recognizable set of stock choices available for the draft.
- Stock choice: a selectable game item representing a company/ticker inside the stock universe.
- Pick: a fantasy-game selection record, never a trade, order, position, recommendation, or investment action.
- Bot pick: a simple system participant's game pick from remaining available stock choices.
- Turn: one participant's opportunity to make a game pick.
- Validation result: the allowed, blocked, or error outcome from a pick attempt with a recovery action.
- Trust boundary: the domain policy that keeps the experience in no-money, no-prize, no-brokerage, no-advice game framing.
- Data label: visible local/mock/delayed/prototype-only data posture shown where stock information could be mistaken for live investing information.

## Entities And Value Objects

### DraftSession

- Kind: aggregate-root.
- Identity: `draft_id`.
- Attributes: `status`, `started_at`, `entry_context`, `stock_universe_id`, `stock_universe_label`, `active_turn_id`, `participants[]`, `turns[]`, `picks[]`, `taken_stock_choice_ids[]`, `current_validation_result`, `trust_boundary`, `data_label`, `remaining_slots`, `events[]`.
- Relationships: owns many `Participant`, `Turn`, `Pick`, and `DraftEvent`; references one `StockUniverse`; embeds one `TrustBoundary`; embeds or carries one `DataLabel`; has zero or one current `ValidationResult`.
- Lifecycle: `draft-session-lifecycle`.
- Flow bindings: `surface:start-and-concept` writes; `surface:stock-chooser` writes; `surface:draft-board` displays; `branches[first-pick-speed]` transitions.

### Participant

- Kind: entity owned by `DraftSession`.
- Identity: `participant_id`.
- Attributes: `display_name`, `actor_type: user|bot`, `draft_order_slot`, `is_current_player`, `status`.
- Relationships: belongs to one `DraftSession`; has zero or many `Turn`; has zero or many `Pick`.
- Flow bindings: `surface:draft-board` reads and displays.

### Turn

- Kind: entity owned by `DraftSession`.
- Identity: `turn_id`.
- Attributes: `sequence`, `round`, `active_participant_id`, `actor_type`, `state`, `started_at`, `completed_at`.
- Relationships: belongs to one `DraftSession`; references one active `Participant`; produces zero or one `Pick`.
- Lifecycle: `turn-lifecycle`.
- Flow bindings: `surface:stock-chooser` reads/writes; `surface:draft-board` transitions/displays.

### Pick

- Kind: entity owned by `DraftSession`.
- Identity: `pick_id`.
- Attributes: `sequence`, `round`, `actor`, `participant_id`, `stock_choice_id`, `stock_display_name`, `ticker`, `source_turn_id`, `recorded_at`, `data_label`.
- Relationships: belongs to one `DraftSession`; belongs to one `Participant`; references one `StockChoice`; completes one `Turn`.
- Flow bindings: `branches[first-pick-speed]` transitions; `surface:stock-chooser` writes; `surface:draft-board` displays; `shape:draft_event` triggers.

### StockUniverse

- Kind: entity.
- Identity: `stock_universe_id`.
- Attributes: `label`, `scope`, `data_label`, `available_count`, `search_supported_by`.
- Relationships: contains many `StockChoice`; referenced by many draft sessions over time.
- Flow bindings: `surface:stock-chooser` reads/displays.

### StockChoice

- Kind: entity.
- Identity: `stock_choice_id`.
- Attributes: `ticker`, `company_name`, `recognizable_label`, `availability_state`, `taken_by_pick_id`, `data_label`.
- Relationships: belongs to one `StockUniverse`; may be referenced by many picks globally; may be referenced by zero or one pick within a single `DraftSession`.
- Lifecycle: `stock-choice-availability-lifecycle`.
- Flow bindings: `surface:stock-chooser` reads/displays; `shape:validation_result` writes.

### ValidationResult

- Kind: value-object.
- Identity: none required; `attempt_sequence` may identify review instances inside a draft session.
- Attributes: `status: none|pending|allowed|blocked|error`, `reason`, `message`, `next_action`, `stock_choice_id`, `turn_id`, `attempt_sequence`, `data_label`.
- Relationships: produced by `DraftSession` validation; references optional attempted `StockChoice` and active `Turn`.
- Lifecycle: `validation-result-lifecycle`.
- Flow bindings: `shape:validation_result` writes; `surface:stock-chooser` displays.

### TrustBoundary

- Kind: value-object / policy descriptor.
- Attributes: `no_money`, `no_prizes`, `no_brokerage`, `no_advice`, `for_entertainment`, `language_guardrails`.
- Relationships: embedded in `DraftSession`; read by trust-boundary policy for commands, messages, read models, and later share/replay copy.
- Flow bindings: `surface:start-and-concept`, `surface:stock-chooser`, and `surface:draft-board` display.

### DataLabel

- Kind: value-object.
- Attributes: `source_posture: local|mock|delayed|prototype-only`, `display_label`, `confidence`, `explanation`.
- Relationships: carried by `StockUniverse`, `StockChoice`, `DraftSession`, `Pick`, `ValidationResult`, and first-pick read models.
- Flow bindings: `surface:stock-chooser`, `shape:validation_result`, and `surface:draft-board` display.

### DraftEvent

- Kind: value-object / audit record.
- Identity: `sequence` within `DraftSession`.
- Attributes: `draft_id`, `sequence`, `actor`, `event`, `occurred_at`, `metadata`.
- Relationships: belongs to one `DraftSession`; may reference participant, turn, pick, or stock choice in logical metadata.
- Flow bindings: `shape:draft_event` writes/triggers.

## State Machines

### draft-session-lifecycle

States:

- `not_started` maps to start surface ready/empty.
- `starting` maps to start action loading/disabled.
- `active_waiting_for_first_pick` maps to stock chooser ready.
- `validating_first_pick` maps to selected row pending validation.
- `first_pick_recorded` maps to first-pick success transition.
- `in_progress` maps to draft board active with turn indicator and pick feed.
- `interrupted` maps to restart/resume copy for local-state interruption.
- `completed` maps to draft completion transition for the later standings branch.

Transitions:

- `not_started` -- `StartQuickDraft` --> `starting`.
- `starting` -- `QuickDraftStarted` --> `active_waiting_for_first_pick`.
- `active_waiting_for_first_pick` -- `MakeStockPick` --> `validating_first_pick`.
- `validating_first_pick` -- `FirstPickRecorded` --> `first_pick_recorded`.
- `validating_first_pick` -- `StockPickBlocked|StockPickErrored` --> `active_waiting_for_first_pick`.
- `first_pick_recorded` -- `TurnAdvanced` --> `in_progress`.
- `in_progress` -- `LocalStateUnavailable` --> `interrupted`.
- `interrupted` -- `RestartQuickDraft` --> `starting`.
- `in_progress` -- `DraftSlotsFilled` --> `completed`.

### turn-lifecycle

States: `user_turn_ready`, `user_pick_validating`, `user_turn_blocked`, `user_turn_completed`, `bot_turn_pending`, `bot_turn_completed`, `turn_sequence_complete`.

Transitions: user pick request starts validation; blocked or errored validation returns the user to recovery; first pick completes user turn; turn advancement moves to bot turn; bot pick completion either returns to user turn or ends the turn sequence.

### stock-choice-availability-lifecycle

States: `unknown`, `available`, `selected_pending_validation`, `taken`, `unavailable`, `not_found`, `data_unavailable`.

Transitions: browse/search resolves available or not-found choices; pick attempt moves to pending validation; recorded pick marks taken; blocked or data-unavailable outcomes surface recovery.

### validation-result-lifecycle

States: `none`, `pending`, `allowed`, `blocked_duplicate_pick`, `blocked_stock_not_found`, `blocked_stock_unavailable`, `blocked_not_users_turn`, `error_data_unavailable`.

Transitions: validation request creates pending; allowed records the pick; blocked/error states show recovery; choosing another stock clears the current result.

### draft-board-continuation-lifecycle

States: `board_not_ready`, `showing_first_pick`, `bot_pick_pending`, `showing_bot_pick`, `awaiting_next_user_pick`, `ready_for_standings_extension`.

Transitions: first pick reveals the board, bot continuation records a bot pick, next turn readiness appears, and full compact draft hands off to standings.

## Events

- `QuickDraftStarted`
- `StockUniverseViewed`
- `StockSearchSubmitted`
- `StockPickValidationRequested`
- `FirstPickRecorded`
- `StockPickBlocked`
- `StockPickErrored`
- `TurnAdvanced`
- `BotPickQueued`
- `BotPickRecorded`
- `ValidationRecoverySelected`
- `LocalStateUnavailable`
- `RestartQuickDraft`
- `DraftSlotsFilled`

## Commands

- `StartQuickDraft`
- `MakeStockPick`
- `ChooseAnotherStock`
- `AdvanceTurnAfterFirstPick`
- `RecordBotPickContinuation`
- `RestartQuickDraft`

## Read Models

- `DraftStartSummary`: start action, concept frame, trust boundary, optional invite context.
- `StockChooserList`: ticker/company rows, availability, taken status, data label, disabled reasons.
- `StockSearchResults`: matching choices, no-results state, browse fallback.
- `ValidationResultView`: pending, allowed, blocked, or error state with recovery action.
- `DraftBoardPreview`: pick feed, participants, active turn, bot state, taken stocks, remaining slots, trust/data labels.

## Policies

- `PickValidationPolicy`: allow a pick only when the draft is active, the actor owns the active turn, the stock choice belongs to the current universe, and it is not taken or unavailable.
- `TurnOwnershipPolicy`: user picks are accepted only on user-owned turns; bot turns disable user picking and select from remaining available choices.
- `TrustBoundaryPolicy`: preserve game framing; avoid trade, buy, sell, profit, cash prize, entry fee, brokerage, portfolio advice, and recommendation language.
- `DataLabelPolicy`: surface local/mock/delayed/prototype-only posture anywhere stock data, validation, board, or later standings could be mistaken for live investing.

## Logical Contracts

### StartQuickDraft

Request: `entry_context`, `start_mode`, `stock_universe_hint`, `trust_boundary_acknowledged`.

Response: `DraftSession`, participants, initial turn, trust boundary, data label, current read model, `QuickDraftStarted`.

Error shape: `start_unavailable|stock_universe_unavailable|trust_boundary_unavailable`, user-visible message, next action, optional data label.

### GetDraftStartSummary

Query response: quick-draft frame, start availability, trust boundary, data label, optional invite context.

### BrowseStockUniverse

Query response: stock universe label, stock choice list, availability state, data labels, empty/fallback copy.

### SearchStockUniverse

Query response: query, matching choices, no-results state, browse fallback, data label, `StockSearchSubmitted` event.

### MakeStockPick

Request: draft, participant, turn, stock choice, selection context.

Allowed response: `ValidationResult.allowed`, `Pick`, updated `DraftSession`, completed `Turn`, `DraftBoardPreview`, `StockPickValidationRequested`, `FirstPickRecorded`.

Blocked/recoverable response: domain-level `ValidationResult` with reason `duplicate_pick|stock_not_found|stock_unavailable|not_users_turn|data_unavailable`, current session/turn state, and recovery next action. These are not transport failures.

### ChooseAnotherStock

Command response: clear current recoverable `ValidationResult`, preserve draft session and user turn, return `StockChooserList`.

### GetDraftBoardPreview

Query response: `DraftSession`, participants, turn state, pick feed, taken stock choices, remaining slots, trust boundary, data label.

### AdvanceTurnAfterFirstPick

Command response: updated session and next turn, `DraftBoardPreview`, `TurnAdvanced`, optional `BotPickQueued`.

### RecordBotPickContinuation

Command response: bot `Pick`, bot turn completion, updated session, board preview, `BotPickRecorded`, optional `TurnAdvanced`.

## Evidence And Flow-Binding Matrix

| Model element | Evidence | Flow bindings |
|---|---|---|
| DraftSession | All five framework intermediates | start writes; stock chooser writes; board displays; first-pick branch transitions |
| StockChoice | Event/domain/data/contract passes | stock chooser reads/displays; validation result writes |
| Pick | Event/domain/state/data/contract passes | first-pick branch transitions; chooser writes; board displays |
| ValidationResult | All five framework intermediates | validation shape writes; chooser displays |
| TrustBoundary | Flow map, positioning, domain/data/contract passes | start, chooser, and board display |
| DataLabel | Flow map, journey, event/data/contract passes | chooser, validation, board display |
| DraftBoardPreview | Event/state/data/contract passes | board displays and transitions |
| PickValidationPolicy | Domain/state/contract passes | chooser writes; validation result writes |

## Assumptions And Confidence

- High confidence: `DraftSession` as aggregate root, `Pick` as fantasy-game record, duplicate prevention scoped to one draft session, `ValidationResult` as domain value object, and trust/data policies as first-class model concerns.
- Medium confidence: exact compact draft slot count, bot selection basis, interruption recovery depth, and whether `TrustBoundary` needs version identity before production.
- Deliberately deferred: production persistence, real endpoints, auth, invite identity, market-data providers, freshness guarantees, analytics transport, legal-review wording, and deployment.

## Physical-Concern Deferrals To `$spec-interview`

- Storage engines, tables/documents, migrations, indexes, query optimization, cache strategy, local persistence durability, and recovery depth.
- Endpoint, URL, transport, routing, API style, network retry, and command/query delivery.
- Authentication, account identity, invite identity, participant recovery, and production session recovery.
- Production market-data providers, licensing, live/delayed provider choices, freshness guarantees, fallback feeds, and data retention.
- Analytics instrumentation names, event transport, privacy policy, audit retention, and legal-review wording.

Proposed Model Tree Manifest

Proposed target path after approval: design/model-tree-draft-stonk.yaml.

schema_version: v0.5
mode: flat
topic: draft-stonk
status: proposed
flow_tree_ref: design/flow-tree-draft-stonk.yaml
branch_ref: branches[first-pick-speed]
source_artifacts:
  - design/flow-tree-draft-stonk.yaml
  - design/user-flow-draft-stonk.md
  - design/_working/state-model-draft-stonk-brief.md
  - design/state-model-draft-stonk/event-modeling.md
  - design/state-model-draft-stonk/domain-model.md
  - design/state-model-draft-stonk/state-machine.md
  - design/state-model-draft-stonk/data-model.md
  - design/state-model-draft-stonk/contract-map.md
frameworks:
  - id: event-modeling
    status: synthesized
    source: design/state-model-draft-stonk/event-modeling.md
  - id: domain-model
    status: synthesized
    source: design/state-model-draft-stonk/domain-model.md
  - id: state-machine
    status: synthesized
    source: design/state-model-draft-stonk/state-machine.md
  - id: data-model
    status: synthesized
    source: design/state-model-draft-stonk/data-model.md
  - id: contract-map
    status: synthesized
    source: design/state-model-draft-stonk/contract-map.md
entities:
  - id: draft-session
    name: DraftSession
    kind: aggregate-root
    lifecycle_ref: draft-session-lifecycle
    attributes: [draft_id, status, started_at, entry_context, stock_universe_id, stock_universe_label, active_turn_id, participants, turns, picks, taken_stock_choice_ids, current_validation_result, trust_boundary, data_label, remaining_slots, events]
    relationships:
      - {to: participant, cardinality: 1-to-many, relationship: owns}
      - {to: turn, cardinality: 1-to-many, relationship: owns}
      - {to: pick, cardinality: 0-to-many, relationship: records}
      - {to: stock-universe, cardinality: many-to-1, relationship: uses}
      - {to: validation-result, cardinality: 0-or-1-current, relationship: has_current}
      - {to: draft-event, cardinality: 0-to-many, relationship: emits}
    flow_bindings:
      - {flow_node_ref: surface:start-and-concept, access: writes}
      - {flow_node_ref: surface:stock-chooser, access: writes}
      - {flow_node_ref: surface:draft-board, access: displays}
      - {flow_node_ref: branches[first-pick-speed], access: transitions}
  - id: participant
    name: Participant
    kind: entity
    attributes: [participant_id, display_name, actor_type, draft_order_slot, is_current_player, status]
    relationships:
      - {to: draft-session, cardinality: many-to-1, relationship: belongs_to}
      - {to: pick, cardinality: 0-to-many, relationship: makes}
      - {to: turn, cardinality: 0-to-many, relationship: owns}
    flow_bindings:
      - {flow_node_ref: surface:draft-board, access: reads}
      - {flow_node_ref: surface:draft-board, access: displays}
  - id: turn
    name: Turn
    kind: entity
    lifecycle_ref: turn-lifecycle
    attributes: [turn_id, sequence, round, active_participant_id, actor_type, state, started_at, completed_at]
    relationships:
      - {to: draft-session, cardinality: many-to-1, relationship: belongs_to}
      - {to: participant, cardinality: many-to-1, relationship: active_participant}
      - {to: pick, cardinality: 0-or-1, relationship: produces}
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: reads}
      - {flow_node_ref: surface:stock-chooser, access: writes}
      - {flow_node_ref: surface:draft-board, access: transitions}
      - {flow_node_ref: surface:draft-board, access: displays}
  - id: pick
    name: Pick
    kind: entity
    attributes: [pick_id, sequence, round, actor, participant_id, stock_choice_id, stock_display_name, ticker, source_turn_id, recorded_at, data_label]
    relationships:
      - {to: draft-session, cardinality: many-to-1, relationship: belongs_to}
      - {to: participant, cardinality: many-to-1, relationship: belongs_to}
      - {to: stock-choice, cardinality: many-to-1, relationship: references}
      - {to: turn, cardinality: 1-to-1, relationship: completes}
    flow_bindings:
      - {flow_node_ref: branches[first-pick-speed], access: transitions}
      - {flow_node_ref: surface:stock-chooser, access: writes}
      - {flow_node_ref: surface:draft-board, access: displays}
      - {flow_node_ref: shape:draft_event, access: triggers}
  - id: stock-universe
    name: StockUniverse
    kind: entity
    attributes: [stock_universe_id, label, scope, data_label, available_count, search_supported_by]
    relationships:
      - {to: stock-choice, cardinality: 1-to-many, relationship: contains}
      - {to: draft-session, cardinality: 1-to-many, relationship: used_by}
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: reads}
      - {flow_node_ref: surface:stock-chooser, access: displays}
  - id: stock-choice
    name: StockChoice
    kind: entity
    lifecycle_ref: stock-choice-availability-lifecycle
    attributes: [stock_choice_id, ticker, company_name, recognizable_label, availability_state, taken_by_pick_id, data_label]
    relationships:
      - {to: stock-universe, cardinality: many-to-1, relationship: belongs_to}
      - {to: pick, cardinality: 0-to-many-globally-0-or-1-per-session, relationship: selected_by}
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: reads}
      - {flow_node_ref: surface:stock-chooser, access: displays}
      - {flow_node_ref: shape:validation_result, access: writes}
  - id: validation-result
    name: ValidationResult
    kind: value-object
    lifecycle_ref: validation-result-lifecycle
    attributes: [status, reason, message, next_action, stock_choice_id, turn_id, attempt_sequence, data_label]
    relationships:
      - {to: draft-session, cardinality: many-over-attempts, relationship: produced_by}
      - {to: stock-choice, cardinality: 0-or-1, relationship: attempted_choice}
      - {to: turn, cardinality: 0-or-1, relationship: attempted_turn}
    flow_bindings:
      - {flow_node_ref: shape:validation_result, access: writes}
      - {flow_node_ref: surface:stock-chooser, access: displays}
  - id: trust-boundary
    name: TrustBoundary
    kind: value-object
    attributes: [no_money, no_prizes, no_brokerage, no_advice, for_entertainment, language_guardrails]
    flow_bindings:
      - {flow_node_ref: surface:start-and-concept, access: displays}
      - {flow_node_ref: surface:stock-chooser, access: displays}
      - {flow_node_ref: surface:draft-board, access: displays}
  - id: data-label
    name: DataLabel
    kind: value-object
    attributes: [source_posture, display_label, confidence, explanation]
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: displays}
      - {flow_node_ref: shape:validation_result, access: displays}
      - {flow_node_ref: surface:draft-board, access: displays}
  - id: draft-event
    name: DraftEvent
    kind: value-object
    attributes: [draft_id, sequence, actor, event, occurred_at, metadata]
    flow_bindings:
      - {flow_node_ref: shape:draft_event, access: writes}
      - {flow_node_ref: shape:draft_event, access: triggers}
state_machines:
  - id: draft-session-lifecycle
    subject: DraftSession
    states:
      - {id: not_started, maps_to_ui_state: start surface ready}
      - {id: starting, maps_to_ui_state: start action loading}
      - {id: active_waiting_for_first_pick, maps_to_ui_state: stock chooser ready}
      - {id: validating_first_pick, maps_to_ui_state: validation pending}
      - {id: first_pick_recorded, maps_to_ui_state: first-pick success transition}
      - {id: in_progress, maps_to_ui_state: draft board active}
      - {id: interrupted, maps_to_ui_state: interrupted draft recovery}
      - {id: completed, maps_to_ui_state: draft completion transition}
    transitions:
      - {from: not_started, event: StartQuickDraft, to: starting, guard: trust boundary can display, action: create logical draft session}
      - {from: starting, event: QuickDraftStarted, to: active_waiting_for_first_pick, guard: initial turn and stock universe available, action: display stock chooser}
      - {from: active_waiting_for_first_pick, event: MakeStockPick, to: validating_first_pick, guard: active user turn and selected choice, action: request validation}
      - {from: validating_first_pick, event: FirstPickRecorded, to: first_pick_recorded, guard: pick allowed, action: record pick and mark stock taken}
      - {from: validating_first_pick, event: StockPickBlocked, to: active_waiting_for_first_pick, guard: validation blocked, action: show recovery}
      - {from: validating_first_pick, event: StockPickErrored, to: active_waiting_for_first_pick, guard: data unavailable, action: show recovery}
      - {from: first_pick_recorded, event: TurnAdvanced, to: in_progress, guard: next turn derivable, action: update draft-board preview}
    flow_bindings:
      - {flow_node_ref: branches[first-pick-speed], access: transitions}
      - {flow_node_ref: surface:stock-chooser, access: displays}
      - {flow_node_ref: surface:draft-board, access: transitions}
  - id: turn-lifecycle
    subject: Turn
    states:
      - {id: user_turn_ready, maps_to_ui_state: pick controls enabled}
      - {id: user_pick_validating, maps_to_ui_state: pick controls disabled pending validation}
      - {id: user_turn_blocked, maps_to_ui_state: blocked or error message}
      - {id: user_turn_completed, maps_to_ui_state: pick feed receives user pick}
      - {id: bot_turn_pending, maps_to_ui_state: bot picking indicator}
      - {id: bot_turn_completed, maps_to_ui_state: bot pick appears in feed}
      - {id: turn_sequence_complete, maps_to_ui_state: draft completion transition}
    transitions:
      - {from: user_turn_ready, event: MakeStockPick, to: user_pick_validating, guard: selected choice and user turn, action: create validation attempt}
      - {from: user_pick_validating, event: StockPickBlocked, to: user_turn_blocked, guard: validation blocked, action: preserve turn and show recovery}
      - {from: user_turn_blocked, event: ChooseAnotherStock, to: user_turn_ready, guard: recoverable, action: clear validation result}
      - {from: user_pick_validating, event: FirstPickRecorded, to: user_turn_completed, guard: pick allowed, action: record pick}
      - {from: user_turn_completed, event: TurnAdvanced, to: bot_turn_pending, guard: next turn is bot-owned, action: disable user picking}
      - {from: bot_turn_pending, event: BotPickRecorded, to: bot_turn_completed, guard: available stock choices remain, action: record bot pick}
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: writes}
      - {flow_node_ref: surface:draft-board, access: displays}
  - id: stock-choice-availability-lifecycle
    subject: StockChoice
    states:
      - {id: unknown, maps_to_ui_state: empty search or unloaded list}
      - {id: available, maps_to_ui_state: enabled stock row}
      - {id: selected_pending_validation, maps_to_ui_state: selected row pending}
      - {id: taken, maps_to_ui_state: disabled taken row}
      - {id: unavailable, maps_to_ui_state: disabled unavailable row}
      - {id: not_found, maps_to_ui_state: no-results state}
      - {id: data_unavailable, maps_to_ui_state: data error recovery}
    transitions:
      - {from: unknown, event: BrowseStockUniverse, to: available, guard: choice in universe, action: show choice}
      - {from: unknown, event: SearchStockUniverse, to: not_found, guard: no match, action: show no-results}
      - {from: available, event: MakeStockPick, to: selected_pending_validation, guard: user owns turn, action: begin validation}
      - {from: selected_pending_validation, event: FirstPickRecorded, to: taken, guard: pick recorded, action: mark taken}
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: displays}
      - {flow_node_ref: shape:validation_result, access: writes}
  - id: validation-result-lifecycle
    subject: ValidationResult
    states:
      - {id: none, maps_to_ui_state: clean chooser state}
      - {id: pending, maps_to_ui_state: inline pending state}
      - {id: allowed, maps_to_ui_state: success transition}
      - {id: blocked_duplicate_pick, maps_to_ui_state: duplicate-pick message}
      - {id: blocked_stock_not_found, maps_to_ui_state: no-results message}
      - {id: blocked_stock_unavailable, maps_to_ui_state: unavailable message}
      - {id: blocked_not_users_turn, maps_to_ui_state: turn warning}
      - {id: error_data_unavailable, maps_to_ui_state: data-label recovery}
    transitions:
      - {from: none, event: StockPickValidationRequested, to: pending, guard: pick submitted, action: create pending result}
      - {from: pending, event: FirstPickRecorded, to: allowed, guard: pick allowed, action: record pick}
      - {from: pending, event: StockPickBlocked, to: blocked_duplicate_pick, guard: duplicate stock, action: show choose-another recovery}
      - {from: pending, event: StockPickErrored, to: error_data_unavailable, guard: data unavailable, action: show retry/browse/restart recovery}
    flow_bindings:
      - {flow_node_ref: shape:validation_result, access: writes}
      - {flow_node_ref: surface:stock-chooser, access: displays}
events:
  - id: quick-draft-started
    name: QuickDraftStarted
    flow_bindings:
      - {flow_node_ref: surface:start-and-concept, access: writes}
      - {flow_node_ref: shape:draft_event, access: triggers}
  - id: stock-universe-viewed
    name: StockUniverseViewed
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: displays}
  - id: stock-search-submitted
    name: StockSearchSubmitted
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: reads}
      - {flow_node_ref: shape:draft_event, access: triggers}
  - id: stock-pick-validation-requested
    name: StockPickValidationRequested
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: writes}
      - {flow_node_ref: shape:validation_result, access: writes}
  - id: first-pick-recorded
    name: FirstPickRecorded
    flow_bindings:
      - {flow_node_ref: branches[first-pick-speed], access: transitions}
      - {flow_node_ref: surface:draft-board, access: displays}
      - {flow_node_ref: shape:draft_event, access: triggers}
  - id: stock-pick-blocked
    name: StockPickBlocked
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: displays}
      - {flow_node_ref: shape:validation_result, access: writes}
  - id: turn-advanced
    name: TurnAdvanced
    flow_bindings:
      - {flow_node_ref: surface:draft-board, access: transitions}
  - id: bot-pick-recorded
    name: BotPickRecorded
    flow_bindings:
      - {flow_node_ref: surface:draft-board, access: displays}
      - {flow_node_ref: shape:draft_event, access: triggers}
commands:
  - id: start-quick-draft
    name: StartQuickDraft
    flow_bindings:
      - {flow_node_ref: surface:start-and-concept, access: writes}
      - {flow_node_ref: shape:draft_event, access: triggers}
  - id: make-stock-pick
    name: MakeStockPick
    flow_bindings:
      - {flow_node_ref: branches[first-pick-speed], access: transitions}
      - {flow_node_ref: surface:stock-chooser, access: writes}
      - {flow_node_ref: shape:validation_result, access: writes}
  - id: choose-another-stock
    name: ChooseAnotherStock
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: reads}
      - {flow_node_ref: surface:stock-chooser, access: displays}
  - id: advance-turn-after-first-pick
    name: AdvanceTurnAfterFirstPick
    flow_bindings:
      - {flow_node_ref: surface:draft-board, access: transitions}
      - {flow_node_ref: surface:draft-board, access: displays}
  - id: record-bot-pick-continuation
    name: RecordBotPickContinuation
    flow_bindings:
      - {flow_node_ref: surface:draft-board, access: writes}
      - {flow_node_ref: shape:draft_event, access: triggers}
read_models:
  - id: draft-start-summary
    name: DraftStartSummary
    flow_bindings:
      - {flow_node_ref: surface:start-and-concept, access: displays}
  - id: stock-chooser-list
    name: StockChooserList
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: displays}
  - id: stock-search-results
    name: StockSearchResults
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: displays}
  - id: validation-result-view
    name: ValidationResultView
    flow_bindings:
      - {flow_node_ref: shape:validation_result, access: writes}
      - {flow_node_ref: surface:stock-chooser, access: displays}
  - id: draft-board-preview
    name: DraftBoardPreview
    flow_bindings:
      - {flow_node_ref: surface:draft-board, access: displays}
policies:
  - id: pick-validation-policy
    name: PickValidationPolicy
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: writes}
      - {flow_node_ref: shape:validation_result, access: writes}
  - id: turn-ownership-policy
    name: TurnOwnershipPolicy
    flow_bindings:
      - {flow_node_ref: surface:draft-board, access: transitions}
  - id: trust-boundary-policy
    name: TrustBoundaryPolicy
    flow_bindings:
      - {flow_node_ref: surface:start-and-concept, access: displays}
      - {flow_node_ref: surface:stock-chooser, access: displays}
      - {flow_node_ref: surface:draft-board, access: displays}
  - id: data-label-policy
    name: DataLabelPolicy
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: displays}
      - {flow_node_ref: shape:validation_result, access: displays}
contracts:
  - id: start-quick-draft-contract
    name: StartQuickDraft
    kind: command
    request_shape: [entry_context, start_mode, stock_universe_hint, trust_boundary_acknowledged]
    response_shape: [draft_session, participants, current_read_model, events]
    error_shape: [start_unavailable, stock_universe_unavailable, trust_boundary_unavailable]
    flow_bindings:
      - {flow_node_ref: surface:start-and-concept, access: writes}
  - id: make-stock-pick-contract
    name: MakeStockPick
    kind: command
    request_shape: [draft_id, participant_id, turn_id, stock_choice_id, selection_context]
    response_shape: [validation_result, pick, draft_session, turn, read_models, events]
    error_shape: [missing_draft_id, missing_participant_id, missing_turn_id, missing_stock_choice_id, invalid_contract_shape]
    flow_bindings:
      - {flow_node_ref: branches[first-pick-speed], access: transitions}
      - {flow_node_ref: surface:stock-chooser, access: writes}
      - {flow_node_ref: shape:validation_result, access: writes}
  - id: browse-stock-universe-contract
    name: BrowseStockUniverse
    kind: query
    request_shape: [draft_id, filter, availability_scope]
    response_shape: [stock_universe, stock_choices, data_label]
    error_shape: [stock_universe_unavailable]
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: reads}
      - {flow_node_ref: surface:stock-chooser, access: displays}
  - id: search-stock-universe-contract
    name: SearchStockUniverse
    kind: query
    request_shape: [draft_id, query]
    response_shape: [query, results, no_results_state, data_label]
    error_shape: [invalid_query, stock_universe_unavailable]
    flow_bindings:
      - {flow_node_ref: surface:stock-chooser, access: reads}
      - {flow_node_ref: surface:stock-chooser, access: displays}
  - id: get-draft-board-preview-contract
    name: GetDraftBoardPreview
    kind: query
    request_shape: [draft_id]
    response_shape: [draft_session, participants, active_turn, pick_feed, taken_stock_choices, trust_boundary, data_label]
    error_shape: [draft_not_found, draft_interrupted]
    flow_bindings:
      - {flow_node_ref: surface:draft-board, access: displays}

Flow-Binding Matrix

Flow NodeModel ElementsAccess
branches[first-pick-speed]DraftSession, Pick, FirstPickRecorded, MakeStockPick, draft-session-lifecycletransitions
surface:start-and-conceptDraftSession, TrustBoundary, StartQuickDraft, DraftStartSummary, QuickDraftStartedwrites, displays, triggers
surface:stock-chooserStockUniverse, StockChoice, Turn, ValidationResult, StockChooserList, StockSearchResults, MakeStockPickreads, writes, displays
surface:draft-boardDraftSession, Participant, Turn, Pick, DraftBoardPreview, TurnAdvanced, BotPickRecordedreads, writes, displays, transitions
shape:validation_resultValidationResult, ValidationResultView, PickValidationPolicy, StockPickBlocked, StockPickErroredwrites, displays
shape:draft_eventDraftEvent, QuickDraftStarted, FirstPickRecorded, BotPickRecorded, StartQuickDraftwrites, triggers

Deferrals And Confidence

High Confidence

  • DraftSession as aggregate root.
  • Pick as fantasy-game record, not trade/order/position.
  • Duplicate prevention scoped to one draft session.
  • ValidationResult as a domain value object.
  • TrustBoundary and DataLabel as first-class policy/value concerns.

Medium Confidence

  • Exact compact draft slot count.
  • Bot selection basis.
  • Interruption recovery depth.
  • Whether trust-boundary versions become identities in production.

Strict Deferrals

Storage, endpoints, auth, production data providers, analytics transport, legal wording, deployment, indexes, migrations, and production recovery belong to $spec-interview.

Route Guard

The flow-tree route remains user-flow-map, ux-variations, ui-interview, logic-wiring, consolidate-prototypes, spec-interview. The model tree stores flow bindings; the flow tree receives only refs after approval.

Review Gates

Approve Proposed Domain Model?

Approve Proposed Model Tree Manifest?

Approve Flow-Tree Attachment After Canonical Write?

Approve Glossary Additions?

Confirm Physical Concerns Are Deferred?

Section Feedback

Optional feedback can be compiled even before every required gate is answered.

Compile Responses

Use this after reviewing. The YAML routes back to $state-model draft-stonk.