# v1.12.0 — Story Loader (2026-05-21)

The first release of the **Complete Context System** roadmap.
After this milestone, OpenLife's runtime is no longer blind to the
project it runs inside: every story and epic under
`docs/stories/<epic-id>/` is read, parsed, indexed, and queryable
via four surfaces (CLI, HTTP, core↔agent bridge, Telegram).

## What landed

### `src/orchestrator/story/` — the registry

| File              | Role                                                  |
|-------------------|-------------------------------------------------------|
| `StorySchema.ts`  | `Story`, `Epic`, `StoryStatus`, `AcceptanceCriterion` |
| `StoryParser.ts`  | Bolded-field markdown → typed `Story`/`Epic`          |
| `StoryRegistry.ts`| Filesystem scanner + in-memory index                  |
| `StoryLifecycle.ts`| `Draft → Ready → InProgress → InReview → Done` guard |
| `StoryWriter.ts`  | Atomic `**Status:**` update + changelog append        |

The parser handles the convention actually used in the corpus:

```
**StoryId:** `3.3`
**Epic:**    `epic-multi-host-installer` (v1.1)
**Status:**  InReview
**Severity:** P1
**Cluster:** install-flow
**Depends on:** Story 3.1, Story 3.2
```

Acceptance criteria are parsed from `- [ ]` / `- [x]` checkboxes.
Change-log entries are parsed from the trailing `## Change Log`
section.

### `openlife story <verb>` — CLI surface

```
openlife story list [--epic <id>] [--status <s>] [--cluster <c>]
openlife story show <id>
openlife story validate <id>
openlife story transition <id> <to-status> [--role <r>] [--note <n>]
openlife story epics
```

All subcommands lazy-import the registry so `openlife --help` stays
fast.

### Gateway HTTP endpoints

All behind the existing `bridgeAuth` (Basic Auth via
gateway-manifest token):

- `GET  /api/v1/stories?epic=&status=&cluster=`
- `GET  /api/v1/stories/:id`
- `GET  /api/v1/epics`
- `GET  /api/v1/epics/:id`
- `POST /api/v1/stories/:id/transition` body `{ to, role?, note? }`

### Bridge CLI proxy

```
openlife bridge story list [--epic <id>] [--status <s>]
openlife bridge story show <id>
openlife bridge story transition <id> <to>
openlife bridge story epics
```

These call the daemon via `httpJsonRequest`, reusing the same
manifest-auth pattern as `bridge push`.

### Telegram

- `/core story <id>` — pretty-printed story summary
- `/core stories` — full list

### Tests

| Test                       | What it asserts                                    |
|----------------------------|----------------------------------------------------|
| `test_story_parser.ts`     | All 18 real story files + 2 epic files parse OK    |
| `test_story_registry.ts`   | Multi-root scanning, filter, dependency lookup     |
| `test_story_lifecycle.ts`  | Full state-machine matrix + role gating            |

Wired into `npm run test:all`; also available individually via
`test:story-parser`, `test:story-registry`, `test:story-lifecycle`,
or the `test:story` aggregator.

## Migration notes

- **No story files were modified.** The parser reads the existing
  format byte-for-byte; the corpus stays human-authored.
- **No new dependencies.** The implementation uses only Node
  built-ins plus the existing `AtomicWriter` utility.
- **No breaking changes** to existing CLI / HTTP / Telegram
  surfaces. The story commands are additive.

## What's next

- **v1.13** — Codebase RAG (Ollama-default embeddings + sqlite-vec
  store + `openlife index {build,update,query}`).
- **v1.14** — Codebase Graph (tree-sitter) + Context Composer +
  per-CLI tier router (`OPENLIFE_INFERENCE_MODE=cli-only` default;
  `openlife provider setup` zero-config wizard).
