Add prototype/openapi/validate/resume commands, wire edge-failure matrix into UX, enforce traceability + validation gates, mandate C4/C5 belief-runtime verification. Rework 038-dashboard-scenario-model artifacts: applicability, structured edge cases, 24-class UX state matrix, interactive HTML prototype, standardized OpenAPI 3.1 (7 ops), full RTM with coverage gate, 56-task backlog, and PASS validation report.
10 KiB
description, handoffs
| description | handoffs | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Generate a feature-local interactive HTML prototype from UX contracts, producing specs/<feature>/prototype/index.html plus a prototype manifest and state-coverage report. No production source mutation. |
|
User Input
$ARGUMENTS
You MUST consider the user input before proceeding (if not empty).
Applicability
This command is applicable ONLY when the feature has a UI surface. For backend-only features, skip gracefully with: "No UI surface detected — prototype not applicable. Proceed to /speckit.openapi or /speckit.plan."
Decision gate: If FEATURE_DIR/contracts/ux/ exists (from /speckit.ux), generate the full prototype. If only ux_reference.md exists, generate a lightweight prototype from the reference. If neither exists, skip.
Principle
You are generating a read-only, interactive HTML artifact that validates UX contract states against actual browser behavior. The prototype is a design verification tool, not production code. It proves that every declared @UX_STATE can be reached, that @UX_FEEDBACK mechanisms work, and that @UX_RECOVERY paths are traversable — all without touching frontend/src/.
Outline
Phase 0: Pre-Flight
- Setup: Run
.specify/scripts/bash/check-prerequisites.sh --json --paths-onlyfrom repo root. ParseFEATURE_DIR. - Verify applicability: Check for
FEATURE_DIR/contracts/ux/orFEATURE_DIR/ux_reference.md. If neither exists and no UI surface is indicated, report skip and exit. - Load context:
FEATURE_DIR/spec.md— user stories and acceptance criteriaFEATURE_DIR/ux_reference.md— interaction referenceFEATURE_DIR/contracts/ux/screen-models.md— model inventory (if exists)FEATURE_DIR/contracts/ux/api-ux.md— API shapes for realistic mock data (if exists)FEATURE_DIR/contracts/ux/<screen>-ux.md— per-screen UX contracts (if exists).opencode/skills/semantics-svelte/SKILL.md— §VI canonical FSM template, §VII design tokensfrontend/src/lib/ui/— existing design-system atom inventory (Button, Card, Input, Select, Badge, PageHeader, Skeleton, EmptyState, Pagination, etc.)frontend/src/lib/components/— existing composite widget inventoryfrontend/src/lib/ui/index.ts— design token exports (colors, spacing, typography)
Phase 1: Extract Representational States
From the loaded UX contracts and reference docs, build the representative state inventory:
For each screen identified in the feature:
- Mandatory states (from UX contracts or inferred):
idle— before any user actionloading— during async operationloaded— data visible, readyempty— no data (first use or filtered)error— failure state with recovery
- Story-specific states (from per-screen UX contracts):
- Every distinct
@UX_STATEdeclared in contracts - Every
@UX_FEEDBACKmechanism (toast, inline error, modal) - Every
@UX_RECOVERYpath (retry, cancel, navigate away)
- Every distinct
- Edge states (from Phase 2 of
/speckit.ux):- Stale data with refresh indicator
- Partial data (some loaded, some failed)
- Background update notification
- Rate-limited with countdown
- Network offline with reconnection
State coverage requirement: Every @UX_STATE declared in UX contracts MUST be represented. Every declared @UX_RECOVERY path MUST be reachable from its error state. Output a state coverage table in the manifest showing contract → prototype mapping.
Phase 2: Build Static Prototype
Create specs/<feature>/prototype/index.html:
Mandatory structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>[Feature] — Interactive Prototype</title>
<style>
/* Embedded styles — no external deps */
/* Use Tailwind-like utility classes matching design tokens */
/* Responsive: mobile-first with breakpoints at 640px, 768px, 1024px */
</style>
</head>
<body>
<!-- State Switcher (top bar, always visible) -->
<nav class="prototype-state-switcher">...</nav>
<!-- Screen content — one <section> per screen -->
<main>
<section id="screen-1" class="prototype-screen">...</section>
</main>
<script>
// Inline JavaScript for state switching
// No frameworks, no build step, no external deps
// All states toggleable via the state switcher
</script>
</body>
</html>
Rules:
- Single file:
index.htmlis self-contained. All CSS and JS are inline. No external dependencies by default. - Use existing design tokens: If
frontend/src/lib/ui/index.tsexports color/typography tokens, translate them to CSS custom properties. If the design system uses Tailwind, use Tailwind utility class names (but inlined as raw CSS since no build step). Match the existingButton.svelte,Card.svelte,Input.svelte,Badge.svelte,Skeleton.svelte,EmptyState.sveltevisual language. - No production source mutation: The prototype lives in
specs/<feature>/prototype/. It NEVER writes tofrontend/src/. - Accessibility: All interactive elements MUST have: appropriate ARIA roles,
aria-liveregions for dynamic content, keyboard navigation (Tab/Enter/Space), focus management, minimum 44×44px touch targets on mobile, andalttext for images/icons. - Responsive: Mobile-first CSS with breakpoints at 640px (sm), 768px (md), 1024px (lg). Test on both viewports via the state switcher's viewport toggle.
- State switcher: A fixed toolbar at the top of the prototype that allows:
- Switching between screens (if multiple)
- Toggling between states for each screen
- Toggling viewport size (desktop 1280px / mobile 375px)
- Shows CURRENT state name, can trigger transitions (loading → loaded, loaded → error, etc.)
- Realistic mock data: Use data shapes from
api-ux.mdto populate loaded states with plausible content. Empty states show realistic empty-state components. Error states show realistic error messages.
Phase 3: Generate Prototype Manifest
Create specs/<feature>/prototype/manifest.md:
#region Std.Opencode.PrototypeManifest [C:3] [TYPE ADR] [SEMANTICS prototype,manifest,[DOMAIN]]
@defgroup Prototype Interactive HTML prototype manifest for [FEATURE].
## Prototype Metadata
- **Feature**: [feature name]
- **Source contracts**: contracts/ux/
- **Screens represented**: N
- **Total states**: N
- **Accessibility validations**: keyboard nav, ARIA roles, touch targets, focus management
- **Responsive breakpoints**: 375px (mobile), 1280px (desktop)
## State Coverage
| Screen | @UX_STATE Contract | Prototype State | Reachable? | Recovery Path |
|--------|-------------------|-----------------|------------|---------------|
| Dashboard | idle | idle (default) | ✅ | — |
| Dashboard | loading | loading (3s auto) | ✅ | — |
| Dashboard | loaded | loaded (with mock data) | ✅ | — |
| Dashboard | empty | empty (no data mock) | ✅ | — |
| Dashboard | error | error (network fail) | ✅ | retry button → loading |
| Dashboard | stale | stale (cached + indicator) | ✅ | refresh button |
## Screen ↔ Story Traceability
| Prototype Screen | User Story | UX Contract | Acceptance Criteria Verified |
|-----------------|------------|-------------|------------------------------|
| /dashboard | US1: View Dashboards | DashboardUx | AC1: list loads, AC2: empty state |
| /migration | US2: Migrate Items | MigrationUx | AC1: step wizard, AC2: error recovery |
## Validation Results
- [ ] All @UX_STATE contracts reachable via state switcher
- [ ] All @UX_RECOVERY paths traversable
- [ ] Keyboard navigation: Tab order verified
- [ ] Touch targets: ≥44×44px on mobile viewport
- [ ] ARIA: live regions for loading/error states
- [ ] No broken links or dead-end states
- [ ] Responsive layout: mobile viewport does not overflow
## Design System Reuse
| Element | Source | Prototype Mapping |
|---------|--------|-------------------|
| Button | $lib/ui/Button.svelte | CSS .btn-primary, .btn-secondary |
| Card | $lib/ui/Card.svelte | CSS .card |
| Badge | $lib/ui/Badge.svelte | CSS .badge + variant classes |
| Skeleton | $lib/ui/Skeleton.svelte | CSS .skeleton + animate-pulse |
| EmptyState | $lib/ui/EmptyState.svelte | CSS .empty-state |
| PageHeader | $lib/ui/PageHeader.svelte | CSS .page-header |
| Input | $lib/ui/Input.svelte | CSS .input-field |
| Select | $lib/ui/Select.svelte | CSS .select-field |
#endregion Std.Opencode.PrototypeManifest
Phase 4: Browser Validation
Open specs/<feature>/prototype/index.html in the browser and validate:
- State coverage: Cycle through every state via the state switcher. Confirm each declared
@UX_STATEis visually represented. - Recovery paths: From each error state, verify the recovery action leads to the correct next state (retry → loading, dismiss → idle, etc.).
- Keyboard navigation: Tab through all interactive elements. Confirm focus rings are visible. Confirm Enter/Space activate buttons and links.
- Responsive: Toggle viewport size. Confirm layout adapts without overflow or broken alignment.
- Accessibility snapshot: Use browser DevTools accessibility tree to confirm ARIA roles and labels are correct.
Record results in manifest.md under "Validation Results".
Phase 5: Report
Report:
- Prototype path:
specs/<feature>/prototype/index.html - Manifest path:
specs/<feature>/prototype/manifest.md - Screens represented: N
- Total states: N
- State coverage: N/N contracts reachable (100% required)
- Recovery paths: N/N traversable
- Accessibility: keyboard nav ✅/❌, ARIA ✅/❌, touch targets ✅/❌
- Recommended next command:
/speckit.openapi(if API surface) or/speckit.plan