# Architecture

## Overview

`pi-wakeup` follows a flat Domain DAG: `index.ts` composes the extension, while cohesive `/lib` domains own schedule state, singleton ownership, timer delivery, footer status, file watching, and pi-facing surfaces.

The decomposition is intentionally coarse enough to avoid file proliferation. A file should exist because it owns an independent behavior surface, not because a helper category can be named.

## Runtime Flow

1. `/wakeup-start` acquires `@llblab/pi-wakeup` in `~/.pi/agent/locks.json`
2. The runtime normalizes `WAKEUP.md`, rebuilds delivery timers, starts the file watcher, and updates the footer
3. `wakeup schedule` inserts a stable indexed `[ ]` entry and asks the active runtime to resync timers
4. When the delivery timer fires, `delivery` marks one pending task `[~]` and sends `⏰ Wakeup` as a follow-up
5. `wakeup done` marks current `[~]` tasks done; if pending work remains, timers rebuild for the next task
6. When all entries are done, normalization resets `WAKEUP.md` to the empty template while preserving the next index

## Domain Map

- `index.ts`: Composition root only; namespace-imports local domains and wires pi hooks/tools/commands
- `lib/paths.ts`: Agent directory, `WAKEUP.md`, and `locks.json` path resolution
- `lib/time.ts`: UTC/local timestamp formatting, duration formatting, and timezone labels
- `lib/schedule.ts`: Schedule input parsing, entry line parsing, status conversion, template normalization, next-index tracking, entry insertion, and completion mutation
- `lib/storage.ts`: `WAKEUP.md` filesystem load/write wrapper around schedule normalization
- `lib/locks.ts`: `locks.json` read/write, `@llblab/pi-wakeup` key persistence, process liveness, own/external/stale detection, acquisition, status lines, and mutation guards
- `lib/delivery.ts`: Pending-entry timer selection, fired-task `[~]` transition, timer cleanup, and follow-up message body construction
- `lib/watcher.ts`: `WAKEUP.md` watcher lifecycle, debounce, ownership checks, and reload routing
- `lib/status.ts`: Footer `wakeup off/on/[hh:mm:ss]` rendering and stale-context-safe status interval cleanup
- `lib/reports.ts`: `wakeup check` output, actionable schedule detection, and startup notice formatting
- `lib/runtime.ts`: High-level coordinator that composes storage, locks, delivery, watcher, status, reports, and session start/stop flows
- `lib/commands.ts`: `/wakeup-start` and `/wakeup-stop` command registration plus takeover prompts
- `lib/tools.ts`: Plain JSON schema, LLM-facing guidance, and execution dispatch for the `wakeup` tool

## Import Direction

```text
index
  ├── commands ── locks, runtime types
  ├── runtime ── delivery, locks, paths, reports, schedule, status, storage, time, watcher
  └── tools ── schedule

reports ── locks, schedule, time
storage ── paths types, schedule
delivery ── locks types, schedule
watcher ── locks types, paths
status ── locks types, time
schedule ── time
```

No `/lib` domain imports `index.ts`. The invariant test suite guards this graph for cycles, namespace entrypoint imports, and source responsibility headers.

## Validation Surface

- `npm run check`: Imports `index.ts` with Node type stripping and no runtime `typebox` dependency
- `npm test`: Runs domain and architecture invariant tests
- `npm run pack:dry`: Verifies package contents include `index.ts`, `/lib`, README, context files, and `/docs`

## Related

- [locks.md](./locks.md) — Shared singleton lock standard
- [../AGENTS.md](../AGENTS.md) — Durable project protocol and conventions
