| """Schema for the process state machine (SPEC §2). |
| |
| A flow is a namespaced set of Step nodes. Each Step is curated, cited data — not |
| generated — which is what makes the roadmap hallucination-proof. Steps may be |
| ordinary process steps or conditional sub-flows (``is_subflow: true``). |
| """ |
| from __future__ import annotations |
|
|
| from typing import List, Optional |
|
|
| from pydantic import BaseModel, Field |
|
|
|
|
| class RequiredForm(BaseModel): |
| form_id: str = Field(..., description="Catalog code/ID, or 'verify-against-source'.") |
| name: str |
| must_contain: List[str] = Field(default_factory=list) |
| source: str |
| verify: bool = Field( |
| False, description="True if the ID/details still need human verification." |
| ) |
|
|
|
|
| class Deadline(BaseModel): |
| description: str |
| basis: str = "" |
| citation: str = "" |
| verify: bool = False |
|
|
|
|
| class Transition(BaseModel): |
| to: str |
| when: Optional[str] = Field( |
| None, description="Condition label; None = default/next transition." |
| ) |
| label: Optional[str] = None |
|
|
|
|
| class HelpTrigger(BaseModel): |
| when: str |
| to: str |
|
|
|
|
| class Step(BaseModel): |
| id: str |
| title: str |
| summary: str |
| is_subflow: bool = False |
| trigger: Optional[str] = None |
| preconditions: List[str] = Field(default_factory=list) |
| required_actions: List[str] = Field(default_factory=list) |
| required_forms: List[RequiredForm] = Field(default_factory=list) |
| deadlines: List[Deadline] = Field(default_factory=list) |
| who_to_contact: Optional[str] = None |
| citations: List[str] = Field(default_factory=list) |
| transitions: List[Transition] = Field(default_factory=list) |
| help_triggers: List[HelpTrigger] = Field(default_factory=list) |
| verify: bool = Field( |
| False, description="Step-level flag: some specifics need verification." |
| ) |
|
|
|
|
| class Flow(BaseModel): |
| id: str |
| namespace: str |
| title: str |
| description: str |
| jurisdiction: str |
| start: str |
| citations: List[str] = Field(default_factory=list) |
| steps: List[Step] |
|
|
| def step_map(self) -> dict: |
| return {s.id: s for s in self.steps} |
|
|
| def main_line(self) -> List[Step]: |
| """The non-subflow steps, in declared order (the linear spine).""" |
| return [s for s in self.steps if not s.is_subflow] |
|
|
| def subflows(self) -> List[Step]: |
| return [s for s in self.steps if s.is_subflow] |
|
|