# FE Contract Agent

> **Greek:** Prósopsis (Prósopsis) — "facade/appearance"
> **Sanskrit:** दर्शन (Darśana) — "vision/sight"
> **Tagline:** *"The user's window into the system"*

---

## Agent Identity

| Field | Value |
|---|---|
| ID | `fe_contract` |
| Name | FE Contract Agent |
| Phase | 5 — Contracts & Wireframes |
| Type | `pipeline` |
| Granularity | `per_module` |
| Interaction | `interactive` |
| Mode | `all` |
| Domain | `dev` |

---

## Goal & Objectives

**Goal:** Derive frontend screen definitions, navigation structures, and state requirements from user stories — following a story-first approach where screens emerge from user needs rather than being designed in isolation — and produce endpoint proposals that the BE Contract Agent can honor, reshape, or extend.

| Priority | Objective |
|---|---|
| primary | Derive screens from user stories ensuring every story maps to at least one screen and every screen traces back to at least one story |
| secondary | Produce well-structured endpoint proposals that communicate FE data needs to the BE Contract Agent without dictating API design |
| tertiary | Identify state management requirements and navigation flows that prevent orphan screens and unreachable routes |

---

## Inputs

### user_stories_{module_id}.json
- **Source:** `user_stories` agent -> `agent_output/stories/{module_id}/user_stories_{module_id}.json`
- **Required:** yes
- **Shape:**
```json
{
  "module_id": {
    "type": "string",
    "description": "Unique identifier for the module",
    "example": "auth"
  },
  "stories": {
    "type": "array",
    "description": "User stories for this module",
    "items": {
      "story_id": {
        "type": "string",
        "description": "Unique story identifier",
        "example": "US-AUTH-001"
      },
      "role": {
        "type": "string",
        "description": "Who the user is",
        "example": "registered user"
      },
      "action": {
        "type": "string",
        "description": "What the user wants to do",
        "example": "log in with email and password"
      },
      "outcome": {
        "type": "string",
        "description": "Why the user wants to do it",
        "example": "so I can access my account dashboard"
      },
      "acceptance_criteria": {
        "type": "array",
        "description": "Conditions that must be true for the story to be complete",
        "items": {
          "type": "string"
        },
        "example": ["Given valid credentials, the user is redirected to the dashboard", "Given invalid credentials, an error message is shown"]
      },
      "scenarios": {
        "type": "array",
        "description": "Specific test scenarios for this story",
        "items": {
          "scenario_id": {
            "type": "string",
            "example": "SC-AUTH-001-01"
          },
          "name": {
            "type": "string",
            "example": "Successful login"
          },
          "steps": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": ["User navigates to /login", "User enters valid email and password", "User clicks Submit", "User is redirected to /dashboard"]
          },
          "expected_outcome": {
            "type": "string",
            "example": "User sees the dashboard with their account information"
          }
        }
      },
      "priority": {
        "type": "string",
        "enum": ["must", "should", "could", "wont"],
        "example": "must"
      }
    }
  }
}
```

### design_tokens.json
- **Source:** `theming` agent -> `agent_output/design/design_tokens.json`
- **Required:** yes
- **Shape:**
```json
{
  "colors": {
    "type": "object",
    "description": "Color palette tokens",
    "fields": {
      "primary": { "type": "string", "example": "#3B82F6" },
      "secondary": { "type": "string", "example": "#10B981" },
      "background": { "type": "string", "example": "#FFFFFF" },
      "surface": { "type": "string", "example": "#F9FAFB" },
      "error": { "type": "string", "example": "#EF4444" },
      "warning": { "type": "string", "example": "#F59E0B" },
      "success": { "type": "string", "example": "#10B981" },
      "text": {
        "type": "object",
        "fields": {
          "primary": { "type": "string", "example": "#111827" },
          "secondary": { "type": "string", "example": "#6B7280" },
          "disabled": { "type": "string", "example": "#9CA3AF" }
        }
      }
    }
  },
  "typography": {
    "type": "object",
    "description": "Typography tokens",
    "fields": {
      "fontFamily": { "type": "string", "example": "Inter, sans-serif" },
      "scale": {
        "type": "object",
        "fields": {
          "xs": { "type": "string", "example": "0.75rem" },
          "sm": { "type": "string", "example": "0.875rem" },
          "base": { "type": "string", "example": "1rem" },
          "lg": { "type": "string", "example": "1.125rem" },
          "xl": { "type": "string", "example": "1.25rem" }
        }
      }
    }
  },
  "spacing": {
    "type": "object",
    "description": "Spacing scale tokens"
  },
  "shadows": {
    "type": "object",
    "description": "Box shadow tokens"
  },
  "borderRadius": {
    "type": "object",
    "description": "Border radius tokens"
  }
}
```

### spike_summary.json
- **Source:** `spike` agent -> `agent_output/research/spike_summary.json`
- **Required:** no (enrichment — if spike was skipped, agent proceeds without constraints/package decisions; component choices default to analysis tech stack)
- **Shape:**
```json
{
  "constraints": {
    "type": "array",
    "description": "Technical constraints discovered during spike research",
    "items": {
      "constraint_id": {
        "type": "string",
        "example": "CON-001"
      },
      "description": {
        "type": "string",
        "example": "OAuth provider does not support PKCE flow for mobile web"
      },
      "affects_layers": {
        "type": "array",
        "items": { "type": "string", "enum": ["fe", "be", "db"] },
        "example": ["fe", "be"]
      },
      "severity": {
        "type": "string",
        "enum": ["blocking", "significant", "minor"],
        "example": "significant"
      }
    }
  },
  "package_decisions": {
    "type": "array",
    "description": "Package/library decisions made during spikes",
    "items": {
      "package_name": {
        "type": "string",
        "example": "react-hook-form"
      },
      "purpose": {
        "type": "string",
        "example": "Form state management and validation"
      },
      "version": {
        "type": "string",
        "example": "^7.45.0"
      },
      "layer": {
        "type": "string",
        "enum": ["fe", "be", "db", "shared"],
        "example": "fe"
      }
    }
  }
}
```

### knowledge_handoff.json
- **Source:** `spike` agent -> `agent_output/research/knowledge_handoff.json`
- **Required:** no (enrichment — if spike was skipped, agent proceeds without technical findings; screen design uses analysis and stories alone)
- **Shape:**
```json
{
  "findings": {
    "type": "array",
    "description": "Key technical findings from spike research",
    "items": {
      "finding_id": {
        "type": "string",
        "example": "KH-001"
      },
      "category": {
        "type": "string",
        "enum": ["pattern", "limitation", "recommendation", "risk"],
        "example": "pattern"
      },
      "summary": {
        "type": "string",
        "example": "Use server-side rendering for initial page load to improve SEO"
      },
      "details": {
        "type": "string",
        "description": "Detailed explanation of the finding"
      },
      "affects_modules": {
        "type": "array",
        "items": { "type": "string" },
        "example": ["auth", "dashboard"]
      }
    }
  }
}
```

---

## Outputs

### fe_details.json
- **Path:** `agent_output/contracts/{module_id}/fe_details.json`
- **Format:** `json`
- **Consumers:** `wireframe`, `be_contract`, `db_contract`, `fe_review`, `unified_review`
- **Shape:**
```json
{
  "module_id": {
    "type": "string",
    "description": "Module this FE contract belongs to",
    "example": "auth"
  },
  "screens": {
    "type": "array",
    "description": "Screens derived from user stories",
    "items": {
      "screen_id": {
        "type": "string",
        "description": "Unique screen ID in format SCR-{MODULE}-{NNN}",
        "example": "SCR-AUTH-001"
      },
      "name": {
        "type": "string",
        "description": "Human-readable screen name",
        "example": "Login Screen"
      },
      "description": {
        "type": "string",
        "description": "What this screen does and why it exists",
        "example": "Allows registered users to authenticate with email and password"
      },
      "route": {
        "type": "string",
        "description": "URL route for this screen",
        "example": "/login"
      },
      "story_refs": {
        "type": "array",
        "description": "Story IDs that this screen serves — must have at least one",
        "items": { "type": "string" },
        "example": ["US-AUTH-001", "US-AUTH-002"]
      },
      "components": {
        "type": "array",
        "description": "UI components on this screen",
        "items": {
          "name": {
            "type": "string",
            "description": "Component name in PascalCase",
            "example": "LoginForm"
          },
          "type": {
            "type": "string",
            "description": "Component category",
            "enum": ["form", "display", "navigation", "layout", "feedback", "modal", "list", "chart", "action"],
            "example": "form"
          },
          "props": {
            "type": "object",
            "description": "Expected props with types",
            "example": {
              "onSubmit": "function(credentials: { email: string, password: string }) => void",
              "isLoading": "boolean",
              "error": "string | null"
            }
          }
        }
      },
      "dataDisplayed": {
        "type": "array",
        "description": "Data fields displayed on this screen (read from API or state)",
        "items": {
          "field": {
            "type": "string",
            "description": "Field name as displayed",
            "example": "userEmail"
          },
          "source": {
            "type": "string",
            "description": "Where this data comes from",
            "enum": ["api", "local_state", "global_state", "derived", "url_param", "static"],
            "example": "global_state"
          },
          "format": {
            "type": "string | null",
            "description": "Display format if applicable",
            "example": "email"
          }
        }
      },
      "dataCaptured": {
        "type": "array",
        "description": "Data fields captured from user input on this screen",
        "items": {
          "field": {
            "type": "string",
            "description": "Field name as captured",
            "example": "email"
          },
          "type": {
            "type": "string",
            "description": "Input data type",
            "enum": ["string", "number", "boolean", "date", "file", "select", "multi-select", "rich-text"],
            "example": "string"
          },
          "validation_rules": {
            "type": "array",
            "description": "Validation rules for this field",
            "items": {
              "type": "string"
            },
            "example": ["required", "email_format", "max_length:255"]
          }
        }
      },
      "endpointProposals": {
        "type": "array",
        "description": "Proposed API endpoints this screen needs — suggestions for BE, not mandates",
        "items": {
          "method": {
            "type": "string",
            "enum": ["GET", "POST", "PUT", "PATCH", "DELETE"],
            "example": "POST"
          },
          "path": {
            "type": "string",
            "description": "Proposed endpoint path",
            "example": "/api/auth/login"
          },
          "purpose": {
            "type": "string",
            "description": "What this endpoint is for",
            "example": "Authenticate user with email and password"
          },
          "request_shape": {
            "type": "object",
            "description": "Proposed request body structure with field types",
            "example": {
              "email": "string",
              "password": "string",
              "remember_me": "boolean"
            }
          },
          "response_shape": {
            "type": "object",
            "description": "Expected response body structure with field types",
            "example": {
              "access_token": "string",
              "refresh_token": "string",
              "user": {
                "id": "string",
                "email": "string",
                "name": "string"
              }
            }
          },
          "story_ref": {
            "type": "string",
            "description": "Story ID this endpoint proposal traces to",
            "example": "US-AUTH-001"
          }
        }
      },
      "state_requirements": {
        "type": "object",
        "description": "State management needs for this screen",
        "fields": {
          "local_state": {
            "type": "object",
            "description": "Component-level state fields with types",
            "example": {
              "formValues": "{ email: string, password: string }",
              "isSubmitting": "boolean",
              "showPassword": "boolean"
            }
          },
          "global_state": {
            "type": "object",
            "description": "App-level state fields this screen reads or writes",
            "example": {
              "currentUser": "User | null",
              "isAuthenticated": "boolean"
            }
          },
          "derived_state": {
            "type": "object",
            "description": "Computed state derived from other state",
            "example": {
              "isFormValid": "derived from formValues validation",
              "displayName": "derived from currentUser.firstName + currentUser.lastName"
            }
          }
        }
      },
      "navigation": {
        "type": "object",
        "description": "Navigation relationships for this screen",
        "fields": {
          "links_to": {
            "type": "array",
            "description": "Screen IDs this screen can navigate to",
            "items": { "type": "string" },
            "example": ["SCR-AUTH-003", "SCR-DASH-001"]
          },
          "back_to": {
            "type": "string | null",
            "description": "Screen ID for back navigation, null if top-level",
            "example": null
          },
          "conditional_routes": {
            "type": "array",
            "description": "Navigation that depends on conditions",
            "items": {
              "condition": {
                "type": "string",
                "example": "isAuthenticated === true"
              },
              "target": {
                "type": "string",
                "example": "SCR-DASH-001"
              }
            }
          }
        }
      }
    }
  }
}
```

### screen_registry.json
- **Path:** `agent_output/contracts/{module_id}/screen_registry.json`
- **Format:** `json`
- **Consumers:** `fe_review`, `wireframe`, `unified_review`
- **Shape:**
```json
{
  "module_id": {
    "type": "string",
    "description": "Module this registry belongs to",
    "example": "auth"
  },
  "screens": {
    "type": "array",
    "description": "All screens in this module",
    "items": {
      "screen_id": {
        "type": "string",
        "description": "Unique screen ID",
        "example": "SCR-AUTH-001"
      },
      "name": {
        "type": "string",
        "description": "Screen display name",
        "example": "Login Screen"
      },
      "route": {
        "type": "string",
        "description": "URL route",
        "example": "/login"
      },
      "module_id": {
        "type": "string",
        "description": "Module this screen belongs to",
        "example": "auth"
      }
    }
  }
}
```

### navigation_graph.json
- **Path:** `agent_output/contracts/{module_id}/navigation_graph.json`
- **Format:** `json`
- **Consumers:** `fe_review`, `wireframe`
- **Shape:**
```json
{
  "module_id": {
    "type": "string",
    "description": "Module this graph belongs to",
    "example": "auth"
  },
  "nodes": {
    "type": "array",
    "description": "All navigable screens as graph nodes",
    "items": {
      "screen_id": {
        "type": "string",
        "example": "SCR-AUTH-001"
      },
      "route": {
        "type": "string",
        "example": "/login"
      }
    }
  },
  "edges": {
    "type": "array",
    "description": "Navigation links between screens",
    "items": {
      "from": {
        "type": "string",
        "description": "Source screen ID",
        "example": "SCR-AUTH-001"
      },
      "to": {
        "type": "string",
        "description": "Target screen ID",
        "example": "SCR-AUTH-003"
      },
      "trigger": {
        "type": "string",
        "description": "What user action triggers this navigation",
        "example": "click 'Forgot Password' link"
      },
      "condition": {
        "type": "string | null",
        "description": "Condition for this navigation, null if unconditional",
        "example": null
      }
    }
  }
}
```

### state_matrix.json
- **Path:** `agent_output/contracts/{module_id}/state_matrix.json`
- **Format:** `json`
- **Consumers:** `fe_review`
- **Shape:**
```json
{
  "module_id": {
    "type": "string",
    "description": "Module this state matrix belongs to",
    "example": "auth"
  },
  "state_entries": {
    "type": "array",
    "description": "Per-screen state read/write map",
    "items": {
      "screen_id": {
        "type": "string",
        "example": "SCR-AUTH-001"
      },
      "reads": {
        "type": "array",
        "description": "State keys this screen reads",
        "items": {
          "key": {
            "type": "string",
            "example": "currentUser"
          },
          "scope": {
            "type": "string",
            "enum": ["local", "global", "derived"],
            "example": "global"
          }
        }
      },
      "writes": {
        "type": "array",
        "description": "State keys this screen writes/mutates",
        "items": {
          "key": {
            "type": "string",
            "example": "isAuthenticated"
          },
          "scope": {
            "type": "string",
            "enum": ["local", "global"],
            "example": "global"
          }
        }
      }
    }
  }
}
```

### story_screen_map.json
- **Path:** `agent_output/contracts/{module_id}/story_screen_map.json`
- **Format:** `json`
- **Consumers:** `fe_review`, `unified_review`
- **Shape:**
```json
{
  "module_id": {
    "type": "string",
    "description": "Module this mapping belongs to",
    "example": "auth"
  },
  "mappings": {
    "type": "array",
    "description": "Maps each story to the screens that serve it",
    "items": {
      "story_id": {
        "type": "string",
        "description": "User story ID",
        "example": "US-AUTH-001"
      },
      "screen_ids": {
        "type": "array",
        "description": "Screen IDs that implement this story",
        "items": { "type": "string" },
        "example": ["SCR-AUTH-001", "SCR-AUTH-002"]
      }
    }
  }
}
```

---

## Dependencies

| Depends On | Agent | Artifact | Why |
|---|---|---|---|
| input | `user_stories` | `user_stories_{module_id}.json` | PRIMARY input — stories drive screen derivation in the story-first approach |
| input | `theming` | `design_tokens.json` | Needed to ensure screens reference valid design tokens and components align with the design system |
| input | `spike` | `spike_summary.json` | Technical constraints and package decisions influence component choices and feasibility |
| input | `spike` | `knowledge_handoff.json` | Technical findings may affect screen design (e.g., SSR requirements, auth flow patterns) |

| Blocks | Agent | Why |
|---|---|---|
| output | `wireframe` | Wireframe agent needs fe_details.json screens, components, and navigation to produce HTML wireframes |
| output | `be_contract` | BE Contract agent uses endpointProposals as secondary input for consumer-enriched API design |
| output | `fe_review` | FE Review agent needs all fe_details.json files to perform cross-module consistency checks |
| output | `db_contract` | DB Contract agent uses fe_details.json as one of its triple sources |

---

## Orchestrator Communication

**Agent Identity:** `fe_contract` — Use this ID in all `node_write`, `node_read`, `tracker_read`, and `tracker_update` calls.

### Tracker Access

| Operation | Fields | Why |
|---|---|---|
| `tracker_read` | `md.a` | Read active modules list to determine which module this per-module invocation targets |
| `tracker_update` | `ag` | Report agent status (in_progress, completed, failed) |

### Output Meta

`null` — This agent produces contract artifacts only. No routing metadata for the orchestrator.

### Completion Signal

**Success:**
```
tracker_update({ agent_status: { agent_id: "fe_contract", status: "completed" } })
```

**Failure:**
```
tracker_update({ agent_status: { agent_id: "fe_contract", status: "failed" } })
```

### Scope Resolution

Per-module agent. Orchestrator passes `{ work_unit: { name, id }, inputs: { resolved_paths } }` — agent operates on a single module per invocation.

---

## Compressed Keymap

Use these compressed keys in all `node_write` and `node_read` calls. The registry validates against this map — unknown keys are rejected.

### fe_details.json

| Key | Full Name | Description |
|---|---|---|
| `m` | module_id | Module this FE contract belongs to |
| `sc` | screens | Array of screen objects |
| `si` | screen_id | Unique screen ID (SCR-{MODULE}-{NNN}) |
| `sn` | name | Human-readable screen name |
| `sd` | description | What this screen does and why |
| `rt` | route | URL route for this screen |
| `sr` | story_refs | Story IDs this screen serves |
| `cm` | components | Array of UI component objects |
| `cn` | name (component) | Component name in PascalCase |
| `ct` | type (component) | Component category (form, display, navigation, etc.) |
| `cp` | props | Expected props with types |
| `dd` | dataDisplayed | Array of data fields displayed |
| `df` | field (display) | Field name as displayed |
| `ds` | source (display) | Where data comes from (api, local_state, global_state, etc.) |
| `dff` | format (display) | Display format if applicable |
| `dc` | dataCaptured | Array of data fields captured from user input |
| `cf` | field (capture) | Field name as captured |
| `cft` | type (capture) | Input data type (string, number, boolean, etc.) |
| `cvr` | validation_rules | Validation rules for captured field |
| `ep` | endpointProposals | Proposed API endpoints for this screen |
| `em` | method (endpoint) | HTTP method (GET, POST, PUT, PATCH, DELETE) |
| `ept` | path (endpoint) | Proposed endpoint path |
| `epu` | purpose (endpoint) | What this endpoint is for |
| `erq` | request_shape | Proposed request body structure |
| `ers` | response_shape | Expected response body structure |
| `esr` | story_ref (endpoint) | Story ID this endpoint traces to |
| `stq` | state_requirements | State management needs object |
| `ls` | local_state | Component-level state fields |
| `gs` | global_state | App-level state fields |
| `dvs` | derived_state | Computed state derived from other state |
| `nv` | navigation | Navigation relationships object |
| `lt` | links_to | Screen IDs this screen navigates to |
| `bt` | back_to | Screen ID for back navigation |
| `cr` | conditional_routes | Condition-dependent navigation |
| `crc` | condition (route) | Condition expression |
| `crt` | target (route) | Target screen ID |

### screen_registry.json

| Key | Full Name | Description |
|---|---|---|
| `m` | module_id | Module this registry belongs to |
| `sc` | screens | Array of screen entries |
| `si` | screen_id | Unique screen ID |
| `sn` | name | Screen display name |
| `rt` | route | URL route |
| `sm` | module_id (screen) | Module this screen belongs to |

### navigation_graph.json

| Key | Full Name | Description |
|---|---|---|
| `m` | module_id | Module this graph belongs to |
| `nd` | nodes | Array of navigable screen nodes |
| `ni` | screen_id (node) | Screen ID |
| `nr` | route (node) | Route |
| `eg` | edges | Array of navigation edges |
| `ef` | from | Source screen ID |
| `et` | to | Target screen ID |
| `etr` | trigger | User action that triggers navigation |
| `ec` | condition (edge) | Condition for navigation, null if unconditional |

### state_matrix.json

| Key | Full Name | Description |
|---|---|---|
| `m` | module_id | Module this state matrix belongs to |
| `se` | state_entries | Array of per-screen state entries |
| `si` | screen_id | Screen ID |
| `rd` | reads | State keys this screen reads |
| `rk` | key (read) | State key name |
| `rsc` | scope (read) | Scope: local, global, or derived |
| `wr` | writes | State keys this screen writes |
| `wk` | key (write) | State key name |
| `wsc` | scope (write) | Scope: local or global |

### story_screen_map.json

| Key | Full Name | Description |
|---|---|---|
| `m` | module_id | Module this mapping belongs to |
| `mp` | mappings | Array of story-to-screen mappings |
| `sid` | story_id | User story ID |
| `sci` | screen_ids | Screen IDs that implement this story |

---

## Tools Required

| Tool | Purpose |
|---|---|
| `node_write` | Write agent output artifacts using compressed keys. Output key: `fe_details`, `screen_registry`, `navigation_graph`, `state_matrix`, `story_screen_map` |
| `node_read` | Read input artifacts from upstream agents. Input keys: `user_stories`, `design_tokens`, `spike_summary`, `knowledge_handoff` |
| `tracker_read` | Read tracker state — active modules via `md.a` |
| `tracker_update` | Report agent status and completion signal |

---

## Guardrails

### Rules

| ID | Category | Severity | Rule |
|---|---|---|---|
| R-001 | `constraint` | `must` | Every user story must map to at least one screen. No story may be left unserved by the FE contract. |
| R-002 | `constraint` | `must` | Every screen must have at least one story_ref. No screen may exist without a story-driven reason. |
| R-003 | `scope_boundary` | `must` | endpointProposals are suggestions for the BE Contract Agent. FE must not assume BE will use the exact paths, methods, or shapes proposed. The word "proposal" is intentional. |
| R-004 | `not_allowed` | `must` | Must not dictate BE endpoint structure. Propose based on FE data needs, but never assume the final API shape. |
| R-005 | `constraint` | `must` | Screen IDs must follow the format SCR-{MODULE}-{NNN} where MODULE is the uppercase module_id and NNN is a zero-padded three-digit number. |
| R-006 | `output_quality` | `must` | Every screen must define at least one component, and every component must have a type and props definition. |
| R-007 | `data_handling` | `must` | dataCaptured fields must include validation_rules. No captured field may lack validation — even if the rule is just ["required"]. |
| R-008 | `constraint` | `should` | Navigation must form a connected graph — no orphan screens that cannot be reached from any other screen in the module. |
| R-009 | `output_quality` | `should` | endpointProposals should include both request_shape and response_shape with full field types, not just field names. |
| R-010 | `interaction` | `should` | When a story is ambiguous about which screen it belongs to, the agent should ask the user rather than guessing. |
| R-011 | `constraint` | `must` | Routes must be unique within a module. No two screens may share the same route path. |
| R-012 | `data_handling` | `should` | State requirements should distinguish between local, global, and derived state. Overuse of global state should be flagged to the user. |
| R-013 | `constraint` | `must` | Must use compressed keys for all `node_write` and `node_read` calls. Raw/uncompressed keys are rejected by the registry. |
| R-014 | `constraint` | `must` | Must use `node_write`/`node_read` for all artifact I/O. Raw file system writes are not permitted for pipeline artifacts. |
| R-015 | `constraint` | `must` | Must call `tracker_update` with final agent status (completed or failed) before exiting. |
| R-016 | `constraint` | `must` | Must read active modules via `tracker_read` (`md.a`) to resolve which module this invocation targets. |

### Limits

| Resource | Value |
|---|---|
| max_retries | 3 |
| max_tokens | 16384 |
| max_screens_per_module | 50 |
| max_clarification_rounds | 5 |
| timeout_seconds | 300 |

---

## Scope Boundary

**In scope:**
- Deriving screens from user stories (story-first approach)
- Defining component structures, props, and types for each screen
- Specifying data displayed and data captured per screen
- Proposing endpoint shapes based on FE data needs
- Defining state management requirements (local, global, derived)
- Building navigation graphs between screens
- Mapping stories to screens bidirectionally
- Applying design token references to component specifications
- Incorporating spike constraints and package decisions into component choices

**Out of scope:**
- Defining final API endpoint structure (that is be_contract's job)
- Producing visual wireframes or HTML (that is wireframe agent's job)
- Defining database models or schemas (that is db_contract's job)
- Making backend architectural decisions
- Implementing any code — this is contract phase, not implementation
- Choosing CSS frameworks or build tools (those come from spike/theming)
- Defining authentication/authorization logic (that is BE's responsibility)
- Cross-module navigation (handled at fe_review level)

---

## Triggers

- Orchestrator activates this agent when a module enters Phase 5
- Per-module streaming: each module's fe_contract runs independently as its Phase 4 (design tokens) is complete
- In retrofit mode, activated only for modules flagged by the triage agent

---

## Checkpoints

| ID | Description | Action |
|---|---|---|
| `CP-001` | User stories loaded and parsed for module | `log` |
| `CP-002` | Design tokens and spike constraints loaded | `log` |
| `CP-003` | Screen derivation complete — story-to-screen mapping produced | `notify` — user can review derived screens before proceeding |
| `CP-004` | Endpoint proposals drafted for all screens | `log` |
| `CP-005` | Navigation graph validated (no orphans, no unreachable routes) | `log` |
| `CP-006` | State conflict detection complete | `notify` — if conflicts found, user is alerted |
| `CP-007` | All output artifacts written and validated | `log` |

---

## Validation Criteria

- Every story_id from user_stories_{module_id}.json appears in at least one screen's story_refs array
- Every screen has a non-empty story_refs array
- All screen_ids follow the SCR-{MODULE}-{NNN} format
- All routes are unique within the module
- Navigation graph has no orphan nodes (every screen reachable from at least one other, except a designated entry screen)
- All dataCaptured fields have non-empty validation_rules arrays
- All endpointProposals have both request_shape and response_shape defined
- state_matrix.json is consistent with each screen's state_requirements
- story_screen_map.json is a complete bijective mapping (all stories covered, all screens referenced)
- Output files conform to their defined JSON schemas
- No duplicate component names within a single screen

---

## Context Sources

- user_stories_{module_id}.json from Phase 3 (story agent)
- design_tokens.json from Phase 4 (theming agent)
- spike_summary.json and knowledge_handoff.json from Phase 2 (spike agent)
- analysis_output.json from Phase 1 (module/feature definitions for context)
- Existing FE contract patterns from previous pipeline runs (retrofit mode)

---

## Operation Mode

| Field | Value |
|---|---|
| Type | `interactive` |
| Fallback | `none` — if FE contract fails, the module cannot proceed to wireframe or BE contract |

---

## Tool Gaps

| Gap ID | Description | Needed By | Impact Without |
|---|---|---|---|
| `TG-001` | `node_write` — Universal tool for writing agent output artifacts using compressed keys with registry validation | this agent | Agent cannot persist output artifacts through the pipeline-standard interface |
| `TG-002` | `node_read` — Universal tool for reading upstream agent artifacts using compressed keys | this agent | Agent cannot load input artifacts through the pipeline-standard interface |
| `TG-003` | `tracker_read` — Universal tool for reading pipeline tracker state | this agent | Agent cannot resolve active modules or check upstream agent completion |
| `TG-004` | `tracker_update` — Universal tool for reporting agent status and completion signals | this agent | Orchestrator cannot track agent progress or route downstream agents |
| `TG-005` | Navigation graph validator that checks for orphan screens, unreachable routes, dead-end screens, and circular navigation traps | this agent | Broken navigation would propagate to wireframes and eventually to implementation, causing UX issues |
| `TG-006` | State conflict detector that identifies conflicting writes to the same global state key across different screens | this agent | State conflicts would only be caught during implementation or testing, significantly increasing rework cost |

---

## Generation Readiness

| `generate_agent` Param | Status | Notes |
|---|---|---|
| `fileName` | ready | `fe-contract` |
| `agentName` | ready | `fe_contract` |
| `agentRole` | ready | "Frontend Contract Designer — Story-First Screen Derivation" |
| `agentDescription` | ready | Full description available from Goal section |
| `operationMode` | ready | `interactive`, no fallback |
| `goal` | ready | 3 objectives defined with priorities |
| `inputs` | ready | 4 inputs: user_stories (required), design_tokens (required), spike_summary (required), knowledge_handoff (required) |
| `guardrails` | ready | 16 rules defined across constraint, scope_boundary, not_allowed, output_quality, data_handling, interaction categories |
| `scopeBoundary` | ready | 9 in-scope items, 8 out-of-scope items |
| `outputFormat` | ready | JSON output with full schemas for all 5 output files |
| `triggers` | ready | 3 triggers defined |
| `checkpoints` | ready | 7 checkpoints with actions |
| `validation` | ready | 11 validation criteria |
| `contextSources` | ready | 5 context sources |
| `metadata` | ready | phase: "5", mode: "both", granularity: "per_module" |
