docs(confidence-engine): define v0.60 investigation storage contract
This commit is contained in:
@@ -178,6 +178,72 @@ Reconstruct CU when canonical meaning or eligible evidence set changes — NOT w
|
||||
- The `≤5` processing bound observed during development was an experimental apparatus constraint, NOT a product requirement. Six Open Questions surfacing is legitimate product output, not a formulation defect.
|
||||
- Evidence discipline: what proves useful in live experimentation must be captured at provenance level, not as test diary entries that become operational constraints.
|
||||
|
||||
## v0.60 — Multi-Investigation Storage Contract Decision
|
||||
|
||||
Completed on branch `feature/multi-investigation-storage-v0.60`. Bounded architecture/contract decision task following v0.60 audit. Zero production changes. Documentation-only decision checkpoint.
|
||||
|
||||
### 1. Contract ownership
|
||||
|
||||
**Decision:** `lib/storage/investigation-storage.js` is the application-facing persistence boundary. It defines the contract whose semantics (not just signatures) are immutable across provider implementations. Consumers import only from this module.
|
||||
|
||||
`lib/storage/providers/local-storage.js` remains one concrete provider implementation behind the contract, not an application import target.
|
||||
|
||||
**Invariant:** No consumer imports `providers/local-storage` directly.
|
||||
|
||||
### 2. Durable Investigation identity
|
||||
|
||||
**Decision:** Canonical Investigation carries a durable `id` field.
|
||||
|
||||
| Property | Value |
|
||||
|---|---|
|
||||
| ID allocation owner | Application (not storage contract) |
|
||||
| Allocation timing | On create new, before any persistence call |
|
||||
| Mutable after creation | NO |
|
||||
| Route `[id]` represents same identity | YES — direct round-trip: app sets → route reads → storage uses |
|
||||
|
||||
### 3. Minimum contract operations
|
||||
|
||||
Five semantic operations. No speculative additions.
|
||||
|
||||
| # | Operation | Input | Output | Product use |
|
||||
|---|---|---|---|---|
|
||||
| 1 | `listInvestigations()` | — | `InvestigationSummary[]` (lightweight) | Portfolio renders index/list |
|
||||
| 2 | `loadInvestigation(id)` | durable ID string | `Investigation \| null` | Investigation/Report page hydration |
|
||||
| 3 | `createEmptyInvestigation()` | — | `{ id: string }` | "+ Create new investigation" |
|
||||
| 4 | `saveInvestigation(id, investigation)` | ID + full snapshot | void | Autosave, Report generation, all writes |
|
||||
| 5 | `restartInvestigation(id)` | durable Investigation ID | void (reasoning state cleared) | "Restart this investigation" |
|
||||
|
||||
**Explicitly rejected:** search, pagination, sorting, sync, merge, transactions, history, report versions, sharing, permissions, accounts. No existing product behaviour requires them.
|
||||
|
||||
### 4. Portfolio listing returns lightweight metadata
|
||||
|
||||
`listInvestigations()` returns summaries, not full snapshots. Minimum information:
|
||||
- `id` — navigation target
|
||||
- `scenario` (or title framing) — card text
|
||||
- `updatedAt` — freshness display
|
||||
- `investigationRevision` — revision metadata
|
||||
- Report existence and `generatedFromRevision` — "Current" / "Update available" indicator
|
||||
|
||||
Full Investigation loads separately via `loadInvestigation(id)` on navigation.
|
||||
|
||||
### 5. Restart = reset reasoning state, NOT remove
|
||||
|
||||
Restart clears reasoning state (findings, questions, report) within the Investigation but preserves the Investigation's durable identity and container. The Investigation remains visible in Portfolio listing as a named item with cleared state.
|
||||
|
||||
A separate "Delete investigation" UI is not required by current MVP. Contract-level `removeInvestigation(id)` is acceptable for future use but has no product owner yet.
|
||||
|
||||
### 6. Create new investigation flow
|
||||
|
||||
User clicks "+ Create new investigation" → app allocates durable ID (crypto.randomUUID or equivalent, library choice deferred) → persist an empty Investigation under that ID immediately → navigate to `/investigations/{id}` → existing Investigations untouched. Empty Investigation is persisted on creation so it appears in Portfolio; user can return later or abandon with container remaining visible.
|
||||
|
||||
### 7. localStorage ≠ contract
|
||||
|
||||
The storage contract accepts/returns domain-level Investigation objects keyed by `id`. How each provider maps those to its storage mechanism is implementation detail. Contract does not dictate key scheme, row schema, or collection structure.
|
||||
|
||||
### 8. Synchronization separate
|
||||
|
||||
Storage contract = persistence only. Not synchronization. No sync-specific fields (syncStatus, remoteId, dirtyFlags, lastSyncedAt) belong in the Investigation shape during this increment. Decisions here do not prevent future sync — the Investigation object carries its own durable ID sufficient for identity resolution.
|
||||
|
||||
## Next restart point
|
||||
|
||||
Consult `docs/design-evolution/README.md` for progressive loading of product reasoning and provenance chronology; load the relevant chapter only when a specific historical question requires it.
|
||||
|
||||
Reference in New Issue
Block a user