# Projects Module — Codex (per FVW v8 §22)

**Module ID:** `oscar.projects`
**Per FVW v8 v0.10.0 §22:** C1-C9 contract items.
**Status:** Constitutional (per §37 latent doctrine, locally ratified).

---

## C1 — Behaviour Inventory

| File | Purpose |
|---|---|
| `app/src/data/models/Project.ts` | Project type, state, project_type, lifecycle |
| `app/src/projects/ProjectsContext.tsx` | React context for current project + project list |
| `app/src/views/Projects.tsx` | Projects dashboard (grid of project cards) |
| `app/src/App.tsx` (modified) | Wraps with ProjectsProvider; /projects route |

## C2 — State Machine (per §37.5)

```
draft → active → paused → archived → deleted
  ↑                    ↓
  └────────────────────┘
```

Transitions:
- `draft → active` (operator creates project)
- `active → paused` (operator pauses)
- `paused → active` (operator resumes)
- `active → archived` (operator archives)
- `archived → deleted` (operator deletes)
- `deleted` is terminal

## C3 — Side Effect List

- IDB write via `projectsRepo` (every create/setState)
- localStorage: `oscar:current-project-id` (current project tracking)
- DOM updates (project card grid, current project highlight)

## C4 — Input Validation Contract

- Project name: non-empty, ≤ 200 chars
- Project type: must be one of `tree | media | social | charity | home | admin`
- Project state: must be one of the 5 lifecycle states

## C5 — Failure Modes

- IDB quota exceeded → caught, reports error
- Default project missing → created on first mount (migration v2→v3)
- Network: none (localStorage only)

## C6 — User Simulation List

1. Open /projects → see "My First Survey" (default)
2. Click "+ New project" → modal appears
3. Type "Test Project", select "tree", click Create → new card appears
4. Click new project card → becomes "Current project"
5. Reload page → current project persists (localStorage)
6. Create project of type "media" → second card
7. Verify cards show different state badges
8. Verify each card shows artefact counts

## C7 — Reproducibility Test

Deterministic: same project data → same rendering.

## C8 — Shape Matrix (per §30)

Per-surface × per-mode × per-chip × per-state:

| Surface | Modes | Chips | States |
|---|---|---|---|
| Projects dashboard | view | new-project, switch, set-state | draft, active, paused, archived, deleted |
| Project card | view | click-to-switch | (5) |
| New project modal | create | submit, cancel | (form state) |

## C9 — State Shape Inventory

### C9.1 localStorage
- `oscar:current-project-id` (which project is active)

### C9.2 In-memory
- `current: Project | null` (ProjectsContext)
- `all: Project[]` (ProjectsContext)
- `counts: Record<projectId, artefact counts>` (ProjectsView local)

### C9.3 IDB
- `projects` store (new in C1; schema bump 2 → 3)

### C9.4 Migration v2 → v3
- On first launch, if `projects` store is empty, create `default` project
- Existing artefacts (without `project_id`) get `project_id = "default"` (handled per-view)

---

## END OF PROJECTS CODEX
