/** * GUCDI — LCR plan compiler (pure). The deterministic spine of the whole-app * `vibe` redesign: instead of generating one mock per story, vibe first compiles * ALL specs into a single coherent plan for one clickable LCR app — * - the unified DATA MODEL (every story's `data_contract.entities` merged into * one schema, with cross-story field conflicts surfaced) → the data adaptor's * spine (a Drizzle/SQLite schema is generated from this); * - the ROUTE / PERSONA map (from each story's `persona` + `surfaces`) → the * app's navigation, every surface reachable; * - per-story COVERAGE (which stories contribute a surface vs are backend-only). * * No LLM: this is aggregation over the specs. The schema/seed/surface GENERATION * passes (LLM) hang off this plan. See docs/plans/vibe-whole-mock-lcr.md. */ /** The slice of a spec the planner needs (kept minimal so the core stays pure + * unit-testable independent of the full Spec type). */ export interface PlanSpecInput { storyId: string; entities: { name: string; fields: { name: string; type: string; }[]; relations?: string[]; }[]; actors?: { name: string; }[]; persona?: { id: string; chrome?: string; }; surfaces?: { route: string; persona?: string; home?: boolean; states?: string[]; }[]; /** The product theme this story belongs to (groups EPSS scenarios across * personas). Falls back to a label derived from the PRD anchor. */ epic?: string; title?: string; /** Given/When/Then strings — the EPSS *scenarios* (When) + *states* (Given). */ acceptanceScenarios?: string[]; } export interface PlanField { name: string; type: string; fromStories: string[]; } export interface PlanEntity { name: string; fields: PlanField[]; relations: string[]; fromStories: string[]; } /** Same entity+field declared with divergent types across stories — the thing * that silently breaks a hand-merged schema; we surface it for resolution. */ export interface FieldConflict { entity: string; field: string; types: { type: string; stories: string[]; }[]; } export interface PlanPersona { id: string; chrome?: string; fromStories: string[]; } export interface PlanSurface { route: string; persona: string; storyId: string; home: boolean; states: string[]; } export interface PlanStory { storyId: string; entities: string[]; personas: string[]; routes: string[]; hasSurface: boolean; } /** One EPSS test case: a semantic Scenario (the "When") under an Epic + Persona, * reached in a given State (the "Given"), happening at `route`. NOT a URL — the * route is just where it happens. Built from a story's acceptance_scenarios. */ export interface EpssScenario { epic: string; persona: string; /** the action / journey — the acceptance scenario's "When". */ scenario: string; /** the precondition — the "Given". */ state: string; /** expected outcome — the "Then" (shown as a hint). */ then: string; route: string; storyId: string; } export interface LcrPlan { entities: PlanEntity[]; conflicts: FieldConflict[]; personas: PlanPersona[]; surfaces: PlanSurface[]; stories: PlanStory[]; /** The EPSS test matrix — semantic scenarios (from acceptance_scenarios), * grouped downstream into epic ▸ persona ▸ scenario ▸ state. */ epss: EpssScenario[]; /** stories that declare no surface — either a UI gap or a legitimately * backend-only story (the planner can't tell; it reports). */ uncoveredStories: string[]; } /** Compile the whole-app plan from the spec set. Deterministic. */ export declare function compileLcrPlan(specs: PlanSpecInput[]): LcrPlan; /** Parse a "Given … When … Then …" acceptance scenario into its three clauses. * Given = the precondition (EPSS State), When = the action (Scenario), Then = * the expected outcome. Returns null if it isn't Gherkin-shaped. */ export declare function parseGwt(s: string): { given: string; when: string; then: string; } | null; //# sourceMappingURL=lcr-plan.d.ts.map