|
|
|
|
@ -8,7 +8,7 @@ tags:
|
|
|
|
|
|
|
|
|
|
# Hephaestus — Design Document
|
|
|
|
|
|
|
|
|
|
> **Status:** Living design record. This is the **rationale + decision-history** document. For the clean, implementation-facing spec the next session builds from, see **[[tech-spec]]**. Sections marked **❓ OPEN** are unresolved; **🔒 DECIDED** are settled.
|
|
|
|
|
> **Status:** Living design record. This is the **rationale + decision-history** document. For the clean, implementation-facing spec the next session builds from, see **[[v1-prototype-tech-spec]]**. Sections marked **❓ OPEN** are unresolved; **🔒 DECIDED** are settled.
|
|
|
|
|
|
|
|
|
|
## 1. Purpose & Vision
|
|
|
|
|
|
|
|
|
|
@ -63,7 +63,7 @@ Today these are loosely coupled by fragile cross-links (`todoist://<task-id>` in
|
|
|
|
|
### 3.1 Identity
|
|
|
|
|
|
|
|
|
|
- 🔒 **DECIDED — ULID for content nodes** (`doc`/`task`/`project`), sortable and sync-safe, with a human-facing `slug`/`alias` layer so `[[wiki-links]]` can be written by name. The ZK's timestamp-IDs (`1722897441-MWFE`) are ULID-like already; a future migration can map them.
|
|
|
|
|
- 🔒 **DECIDED — deterministic ids for key-unique kinds.** Random ULIDs *diverge* when two offline replicas independently create the *same logical singleton* (today's `journal`, a `tag` by name) — duplicates that never merge. So `journal` ids derive deterministically from `(owner, ISO-date)` and `tag` ids from `(owner, normalized-name)`; independent creation then yields the *same* id and the CRDT/op-log coalesce them (two partial daily notes even merge). `project` stays a random ULID (deliberately created, renameable, tiny stable set). Tag rename = retag (no in-place key change); the normalization function is a fixed, versioned constant. See [[tech-spec]] §4.5.
|
|
|
|
|
- 🔒 **DECIDED — deterministic ids for key-unique kinds.** Random ULIDs *diverge* when two offline replicas independently create the *same logical singleton* (today's `journal`, a `tag` by name) — duplicates that never merge. So `journal` ids derive deterministically from `(owner, ISO-date)` and `tag` ids from `(owner, normalized-name)`; independent creation then yields the *same* id and the CRDT/op-log coalesce them (two partial daily notes even merge). `project` stays a random ULID (deliberately created, renameable, tiny stable set). Tag rename = retag (no in-place key change); the normalization function is a fixed, versioned constant. See [[v1-prototype-tech-spec]] §4.5.
|
|
|
|
|
|
|
|
|
|
### 3.2 Scalar task attributes vs. links
|
|
|
|
|
|
|
|
|
|
@ -81,7 +81,7 @@ A **recurring task** carries an **RFC-5545 RRULE** and acts as a recurring **def
|
|
|
|
|
- A recurring task is a **single node**. On completion: (1) append the finished occurrence to the per-task **log** (§6.4), (2) reset the body's checkboxes to unchecked (a body-CRDT edit), (3) advance the do-date to **the next RRULE instance strictly after `now`**, *skipping* missed occurrences. So a fresh, all-`outstanding` checklist each occurrence; **completion never carries forward**; a missed daily routine is **one** gently-overdue item, not a pile.
|
|
|
|
|
- History is narrative (the log), matching "narrative > list" (§6.1). RRULE expansion stays **lazy** — only "next instance after now" is ever computed, never the series (§6.6).
|
|
|
|
|
|
|
|
|
|
**Why not occurrence-instances?** The rejected alternative (a fresh node per occurrence) was attractive for queryable per-occurrence history, but under Fork A each occurrence would need its own body — hence its own node — turning every daily recurrence into a new node-pair: exactly the explosion §6.6 forbids. No v1 query needs occurrence rows (the ranking reads the single node's do-date), and adherence/streak stats can be reconstructed from the log later. See [[tech-spec]] §4.4.
|
|
|
|
|
**Why not occurrence-instances?** The rejected alternative (a fresh node per occurrence) was attractive for queryable per-occurrence history, but under Fork A each occurrence would need its own body — hence its own node — turning every daily recurrence into a new node-pair: exactly the explosion §6.6 forbids. No v1 query needs occurrence rows (the ranking reads the single node's do-date), and adherence/streak stats can be reconstructed from the log later. See [[v1-prototype-tech-spec]] §4.4.
|
|
|
|
|
|
|
|
|
|
## 4. Architecture
|
|
|
|
|
|
|
|
|
|
@ -92,9 +92,9 @@ Layers, top to bottom:
|
|
|
|
|
- **Surfaces (thin clients) — a three-surface model (revised 2026-06 after the §6.2.1 Todoist study; supersedes the earlier "nvim is *the* primary surface" framing).** Tasks and knowledge pull in different interaction directions, so each surface plays to its strength rather than one trying to do everything:
|
|
|
|
|
- **`heph.nvim` — the primary *context / knowledge-base* surface.** The full "org-mode"-style experience (markdown buffers backed by `doc` nodes; wiki-links, journaling, the canonical-context doc, per-task log, checklists). The explicit **successor to obsidian.nvim** (telescope picker, follow `[[wiki-links]]` on `<Enter>`, dailies, multi-state checkboxes); must reach that parity (§6.5). It surfaces tasks for **navigation/reading and context**, not as the primary place to *edit* structured task fields.
|
|
|
|
|
- **`heph` CLI — capture/scripting + the complete daemon API.** Every structured task field is a flag (`-a red --do tomorrow --late fri --recur weekly --project Maintenance`), which is exactly what command-line flags are good at and dissolves the "how do I edit N structured fields" problem. The CLI implements the *entire* API (admin, sync, conflicts, export) so it is also the scripting/automation surface.
|
|
|
|
|
- **`heph-tui` — the primary *task agenda / triage* surface (planned, [[tech-spec]] §8.1).** The §6.2.1 study shows the dominant task activity is *interactive triage of a large set* (daily orange reconfirm, blue keep/drop review, browse-by-project) — work that is awkward as either CLI flags or nvim buffers. A terminal UI owns that, and **launches into nvim** for a task's context (and nvim launches back). Not yet built.
|
|
|
|
|
- **`heph-tui` — the primary *task agenda / triage* surface (planned, [[v1-prototype-tech-spec]] §8.1).** The §6.2.1 study shows the dominant task activity is *interactive triage of a large set* (daily orange reconfirm, blue keep/drop review, browse-by-project) — work that is awkward as either CLI flags or nvim buffers. A terminal UI owns that, and **launches into nvim** for a task's context (and nvim launches back). Not yet built.
|
|
|
|
|
- The **web UI** is the occasional hub-served surface. A later iOS/Watch client talks to the hub directly.
|
|
|
|
|
- 🔒 **Single binary, three modes.** One Rust binary runs as `local` / `server` / `client` ([[tech-spec]] §3.1); the `heph` CLI shares the same command surface. Mode is two orthogonal axes (backend + inbound listener) plus an optional `hub_url` that makes any `local` instance a syncing **spoke** — the everyday device is `local` + `hub_url`, the hub is `server`, `client` is the online-only convenience.
|
|
|
|
|
- 🔒 **Single binary, three modes.** One Rust binary runs as `local` / `server` / `client` ([[v1-prototype-tech-spec]] §3.1); the `heph` CLI shares the same command surface. Mode is two orthogonal axes (backend + inbound listener) plus an optional `hub_url` that makes any `local` instance a syncing **spoke** — the everyday device is `local` + `hub_url`, the hub is `server`, `client` is the online-only convenience.
|
|
|
|
|
- **Per-device daemon (`hephd`):** owns the local SQLite handle, the CRDT/op-log state, and background sync. All local surfaces connect to it over a local socket. This is what makes multi-surface access concurrent and safe on one SQLite file, and gives one place to run background sync.
|
|
|
|
|
- 🔒 **Lifecycle = an explicit OS service; surfaces are connect-only (decided 2026-06).** Since the daemon is shared across surfaces (CLI, TUI, nvim), no single surface owns it — so none auto-spawns it (an earlier nvim "managed daemon" that spawned + killed-on-exit was removed: a surface-owned daemon can't be shared, and "when do we stop it?" has no good answer). Instead it runs as a launchd agent (macOS) / systemd user service (Linux), managed by **`heph daemon start/stop/restart/status`** ([[run-the-daemon]]). Surfaces only connect, and tell you to run `heph daemon start` if nothing is serving the socket.
|
|
|
|
|
- **Core crate (Rust lib):** data model, query engine, markdown parsing + wiki-link extraction, and sync logic. Linked by both `hephd` and the hub server.
|
|
|
|
|
@ -252,7 +252,7 @@ The owner's old rule — "avoid ncurses and interactive UIs; write atomic code a
|
|
|
|
|
|
|
|
|
|
**heph's default "what is next?" (Tactical blank-slate)** therefore ≈ Top of Mind (Red first — by *consequence*, then Orange) **+** White items whose do-date has arrived, scoped to the current project/context, **with Blue hidden**. Concise, honest, light.
|
|
|
|
|
|
|
|
|
|
> 🔒 **DECIDED ranking mechanics ([[tech-spec]] §7):** `do_date` is a *boolean candidacy filter only* (null ⇒ "now"), **never** an urgency input; **`late_on` is the sole urgency signal** (a global "now a problem" top tier); within a band, FIFO by `created_at` — **age never becomes urgency**. The order is expressed as a reorderable named-dimension list so it can be retuned without touching the engine.
|
|
|
|
|
> 🔒 **DECIDED ranking mechanics ([[v1-prototype-tech-spec]] §7):** `do_date` is a *boolean candidacy filter only* (null ⇒ "now"), **never** an urgency input; **`late_on` is the sole urgency signal** (a global "now a problem" top tier); within a band, FIFO by `created_at` — **age never becomes urgency**. The order is expressed as a reorderable named-dimension list so it can be retuned without touching the engine.
|
|
|
|
|
|
|
|
|
|
### 6.2.1 Todoist study (2026-06): empirical confirmation + new requirements
|
|
|
|
|
|
|
|
|
|
@ -261,7 +261,7 @@ The owner's old rule — "avoid ncurses and interactive UIs; write atomic code a
|
|
|
|
|
**Confirms the model:**
|
|
|
|
|
|
|
|
|
|
- **Projects = contexts, used heavily and hierarchically.** 34 projects organized into top-level life-areas (`Life`, `Work`, `Coding`, `Camano`, `Culture`) → sub-projects (`Child`, `Blumeops`, `Daily Routine`, `Maintenance`, `Movies`…). The *hierarchy* is new information (§6.2 listed projects flat).
|
|
|
|
|
- **Huge backlog, tiny hot set.** Priority split p1=2, p2=8, p4(default)=229, p3=148 — i.e. the genuinely "hot" set is ~10, the rest is white/blue backlog. The dominant *activity* is therefore **triage of a large set**, not editing single tasks — a direct argument for an interactive agenda surface (§4, [[tech-spec]] §8.1).
|
|
|
|
|
- **Huge backlog, tiny hot set.** Priority split p1=2, p2=8, p4(default)=229, p3=148 — i.e. the genuinely "hot" set is ~10, the rest is white/blue backlog. The dominant *activity* is therefore **triage of a large set**, not editing single tasks — a direct argument for an interactive agenda surface (§4, [[v1-prototype-tech-spec]] §8.1).
|
|
|
|
|
- **Do-date, not due-date — validated to the hilt.** **Zero** Todoist *deadlines* are used; only 107/387 carry a due (do) date. `late_on` will be genuinely rare.
|
|
|
|
|
- **Recurring checklists are real** ("Prep For Day", every day @ 07:00, 6 children) — exactly the §3.3 reset-each-occurrence mechanism.
|
|
|
|
|
- **Daily rituals exist as tasks**: "Excess Tasks to On Deck" (= the blue keep/drop review), "Coordinate with Allison", "Check Personal Email" (= orange reconfirm). The §6.2 working-set rituals are alive in the data; the TUI should make them first-class filters.
|
|
|
|
|
@ -274,7 +274,7 @@ The owner's old rule — "avoid ncurses and interactive UIs; write atomic code a
|
|
|
|
|
- **Natural-language recurrence** — 95/107 dated tasks recur, expressed as `every 3 days`, `every 6 months`, `every workday`, `every April 15`, `every other wed`. heph stores RFC-5545 RRULE; capture should accept the common NL forms and compile them (the easy subset; time-of-day like "at 08:00" deferred — heph's `do_date` is date-grained for ranking).
|
|
|
|
|
- **Tags are noise** — 7 labels, **5 task-uses across 387**. Confidently **defer** a tag surface; it is not load-bearing.
|
|
|
|
|
|
|
|
|
|
**The saved filters, verbatim (the basis for heph's filter views, [[tech-spec]] §8.2):**
|
|
|
|
|
**The saved filters, verbatim (the basis for heph's filter views, [[v1-prototype-tech-spec]] §8.2):**
|
|
|
|
|
|
|
|
|
|
| Filter | Todoist query |
|
|
|
|
|
|---|---|
|
|
|
|
|
@ -285,13 +285,13 @@ The owner's old rule — "avoid ncurses and interactive UIs; write atomic code a
|
|
|
|
|
| Chores | `(today \| overdue \| no date) & (#Chores \| #Camano Chores)` |
|
|
|
|
|
| On Deck | `p3 & (no date \| overdue \| today)` |
|
|
|
|
|
|
|
|
|
|
These define both the **agenda slices** heph must offer ([[tech-spec]] §8.2) and, by what "Tasks" *excludes* (`##Culture` = Movies/Books/Theater; `#Camano Info`), which contexts are **not tasks at all**.
|
|
|
|
|
These define both the **agenda slices** heph must offer ([[v1-prototype-tech-spec]] §8.2) and, by what "Tasks" *excludes* (`##Culture` = Movies/Books/Theater; `#Camano Info`), which contexts are **not tasks at all**.
|
|
|
|
|
|
|
|
|
|
**Reference contexts → wiki, not tasks (decided 2026-06).** The `##Culture` subtree (Movies/Books/Theater) and `#Camano Info` are reference lists (films to watch, books to read, contractor phone numbers), deliberately excluded from every task filter. In heph they belong as **`doc` pages**, not committed tasks — otherwise they flood "what is next?". On the initial Todoist import these 5 projects (~59 items) were reclassified into one wiki list-doc each and the task/project nodes tombstoned. (A useful general principle: a "task" that never appears in any of your filters is probably a note.)
|
|
|
|
|
|
|
|
|
|
**Future direction (noted 2026-06, not scheduled):**
|
|
|
|
|
|
|
|
|
|
- **Chores as a first-class feature.** Chores want **different do-date / recurrence semantics** from regular tasks (the every-N-days "do it again sometime after" rhythm, tuned-down urgency). Rather than model them as a `#Chores` *project* you scope to, make "chore" a **first-class task property** (kind/flag) with its own scheduling rules — which retires the `#Chores` / `#Camano Chores` projects (and the Camano split) entirely. The interim `Chores` filter view ([[tech-spec]] §8.2) is project-scoped until then.
|
|
|
|
|
- **Chores as a first-class feature.** Chores want **different do-date / recurrence semantics** from regular tasks (the every-N-days "do it again sometime after" rhythm, tuned-down urgency). Rather than model them as a `#Chores` *project* you scope to, make "chore" a **first-class task property** (kind/flag) with its own scheduling rules — which retires the `#Chores` / `#Camano Chores` projects (and the Camano split) entirely. The interim `Chores` filter view ([[v1-prototype-tech-spec]] §8.2) is project-scoped until then.
|
|
|
|
|
- **Drop the `Schedule` filter.** Schedule was Todoist's timed-routine view (`!no time`); heph's `do_date` is date-grained, so it is **omitted** (not approximated). It's entangled with the chores rework (timed routines), so reconsider both together if/when time-of-day lands on tasks.
|
|
|
|
|
|
|
|
|
|
### 6.3 Two kinds of task: commitments vs. context items
|
|
|
|
|
@ -306,7 +306,7 @@ These define both the **agenda slices** heph must offer ([[tech-spec]] §8.2) an
|
|
|
|
|
|
|
|
|
|
#### Editing surface for context items — *deliberately deferred to the prototype*
|
|
|
|
|
|
|
|
|
|
> 🔑 **DECIDED — Fork A "index" backend (the affordance is still trialed both ways).** The stored source of truth is the `doc` **body markdown**: context items are `- [ ]` lines in it, and a context item's checked state *is* the `[ ]`/`[x]`. They are **not** synced nodes — each replica derives a **local index** from its converged CRDT body, so they converge for free (no divergent ULIDs across offline edits — the original sync trap). Identity is pinned only at **promotion**, which mints a real committed `task` node and rewrites the source line into a link to it. This collapses the hardest sync problem into "the body CRDT already converges" and matches this section's "ephemeral, low-stakes identity" intent. **What's still trialed both ways is purely the nvim *affordance*** (Option A checkboxes-in-body vs. Option B command-driven capture) — the backend is shared, so ergonomics can be judged in the prototype. See [[tech-spec]] §4.3, §5.
|
|
|
|
|
> 🔑 **DECIDED — Fork A "index" backend (the affordance is still trialed both ways).** The stored source of truth is the `doc` **body markdown**: context items are `- [ ]` lines in it, and a context item's checked state *is* the `[ ]`/`[x]`. They are **not** synced nodes — each replica derives a **local index** from its converged CRDT body, so they converge for free (no divergent ULIDs across offline edits — the original sync trap). Identity is pinned only at **promotion**, which mints a real committed `task` node and rewrites the source line into a link to it. This collapses the hardest sync problem into "the body CRDT already converges" and matches this section's "ephemeral, low-stakes identity" intent. **What's still trialed both ways is purely the nvim *affordance*** (Option A checkboxes-in-body vs. Option B command-driven capture) — the backend is shared, so ergonomics can be judged in the prototype. See [[v1-prototype-tech-spec]] §4.3, §5.
|
|
|
|
|
|
|
|
|
|
- **Option A — checkboxes in the body, derived on save.** Edit the task's canonical context doc as plain markdown; `- [ ]` lines are materialized into context-item state on `:w` (`BufWritePost`), reusing the wiki-link extraction machinery. **No real-time scanning needed** (debounced live updates are optional polish). Remote CRDT edits are *pushed* from the daemon to reconcile an open buffer. Item identity is low-stakes (reword = tombstone-old + add-new) since items are ephemeral; identity is pinned only at **promotion**. Most "personal org-mode"-native; millisecond capture = "type a line."
|
|
|
|
|
- **Option B — command-driven capture, rendered.** Capture via a leader chord + `vim.ui.input` (no raw checkbox typing); the new item is still written as a `- [ ]` line into the body-backed store (Fork A), then **rendered** inline via virtual text/extmarks or a transient **floating window** (avoids the disliked persistent cutaway). Heavier capture; more UI to build; promotion identical.
|
|
|
|
|
@ -410,7 +410,7 @@ Reuse the established blumeops patterns (🔒 confirmed by repo conventions):
|
|
|
|
|
1. **CRDT library** for body merge: `yrs` (leaning) vs `automerge`; bespoke op-log/HLC for scalar fields either way.
|
|
|
|
|
2. **Hub network transport** (tech-spec §6.1): `axum` HTTP/JSON (leaning) vs gRPC; sync propagation cadence (push vs periodic pull); **device-id provisioning** (how a spoke mints its `origin` id and registers with the hub).
|
|
|
|
|
|
|
|
|
|
*Resolved in the second-pass review (2026-05-31), now folded into [[tech-spec]]:*
|
|
|
|
|
*Resolved in the second-pass review (2026-05-31), now folded into [[v1-prototype-tech-spec]]:*
|
|
|
|
|
|
|
|
|
|
3. ✅ **Recurrence → roll-forward in place** (§3.3) — occurrence-instances rejected (would explode into a node-per-occurrence under Fork A); advance to the next RRULE instance after `now`, skipping misses.
|
|
|
|
|
4. ✅ **Context items → Fork A "index" backend** (§6.3) — body markdown is the source of truth; context items are a local derived index, not synced nodes; identity at promotion. The nvim *affordance* (A vs B) is still trialed in-prototype.
|
|
|
|
|
@ -430,10 +430,10 @@ Reuse the established blumeops patterns (🔒 confirmed by repo conventions):
|
|
|
|
|
|
|
|
|
|
## 10. Roadmap (provisional)
|
|
|
|
|
|
|
|
|
|
- **Phase 0 — Design** (this document + [[tech-spec]]): done enough to build.
|
|
|
|
|
- **Phase 0 — Design** (this document + [[v1-prototype-tech-spec]]): done enough to build.
|
|
|
|
|
- **Phase 1 — v1 prototype (a single C1 effort, deliberately — a one-shot test of delivering a high-complexity prototype from the spec; built in TDD slices):** `heph-core` (model, schema, extraction, recurrence, "what is next", `Store` trait, op-log/HLC/CRDT merge) → `hephd` **local mode** → **server + client modes (+ lock handoff)** → **offline sync + conflict queue** → **OIDC/Authentik auth + per-user isolation** → `heph.nvim` + `heph` CLI. Local-only works standalone; runnable client/server + offline sync on the tailnet. The build order doubles as the cross-session resume tracker (next un-green slice = where to resume). C2/Mikado is *not* used: it sequences prerequisites against existing code under test, and this is greenfield delivery from a complete spec; follow-up C1s or a C2 refactor come later as needed.
|
|
|
|
|
|
|
|
|
|
**Phase 1 progress** (branch `feature/v1-prototype`, PR #1; 102 tests green as of 2026-06-01 — see [[tech-spec]] §14 for the per-area tracker):
|
|
|
|
|
**Phase 1 progress** (branch `feature/v1-prototype`, PR #1; 102 tests green as of 2026-06-01 — see [[v1-prototype-tech-spec]] §14 for the per-area tracker):
|
|
|
|
|
- [x] `heph-core` library — schema/`Store`/`LocalStore`, extraction, tasks/links/canonical-context + wiki-link materialization, "what is next?" ranking, recurrence roll-forward + per-task logs.
|
|
|
|
|
- [x] `hephd` **local mode** — file lock + JSON-RPC over a unix socket (tokio blocking pool); `heph` CLI + `export`.
|
|
|
|
|
- [x] Local query surface — `list`, `health`, `journal`, `search` (FTS5).
|
|
|
|
|
@ -447,7 +447,7 @@ Reuse the established blumeops patterns (🔒 confirmed by repo conventions):
|
|
|
|
|
|
|
|
|
|
> The handoff target for the next context session. Items here are **proposals to ratify**; once ratified, a fresh session can build directly from this.
|
|
|
|
|
|
|
|
|
|
> **The canonical, implementation-ready scope/stack/schema/API now live in [[tech-spec]].** This section keeps the *intent* and the kickoff process; defer to the spec for details (and update the spec when decisions change).
|
|
|
|
|
> **The canonical, implementation-ready scope/stack/schema/API now live in [[v1-prototype-tech-spec]].** This section keeps the *intent* and the kickoff process; defer to the spec for details (and update the spec when decisions change).
|
|
|
|
|
|
|
|
|
|
### 11.1 Scope — *local-to-distributed via a targetable backend* (ratified)
|
|
|
|
|
|
|
|
|
|
@ -464,7 +464,7 @@ Core: `rusqlite` (bundled) + migrations · `tokio` + JSON-RPC/unix-socket (local
|
|
|
|
|
|
|
|
|
|
### 11.3 First-session kickoff checklist
|
|
|
|
|
|
|
|
|
|
1. `mise run ai-docs`; read **[[tech-spec]]** (the build spec) and this doc's §3/§6 for rationale.
|
|
|
|
|
1. `mise run ai-docs`; read **[[v1-prototype-tech-spec]]** (the build spec) and this doc's §3/§6 for rationale.
|
|
|
|
|
2. **Classify as a single C1** (deliberate — a one-shot test of delivering this high-complexity prototype from the spec; C2/Mikado is for sequencing prerequisites against *existing* code, not greenfield delivery). Single long-lived feature branch + early draft PR, docs-first, push as you go ([[agent-change-process]]). The §11.1 build order is the resume tracker; the hairy slices (sync/CRDT) may spin off follow-up C1s rather than blocking the prototype.
|
|
|
|
|
3. Scaffold the cargo workspace + `heph.nvim` skeleton; **fill the AGENTS.md Project Structure section** (last template TODO).
|
|
|
|
|
4. Build outward in testable slices (TDD, tech-spec §2/§9): `heph-core` (schema, model, extraction, recurrence, "what is next", `Store` trait, **op-log/HLC/CRDT merge**) → `hephd` **local mode** (LocalStore + lock + local RPC) → **server + client modes** (network endpoint, RemoteStore, lock handoff) → **sync + conflict queue** → **OIDC auth** → `heph.nvim` + `heph` CLI.
|
|
|
|
|
@ -472,6 +472,6 @@ Core: `rusqlite` (bundled) + migrations · `tokio` + JSON-RPC/unix-socket (local
|
|
|
|
|
|
|
|
|
|
## Related
|
|
|
|
|
|
|
|
|
|
- [[tech-spec]] — clean implementation-facing technical specification distilled from this document
|
|
|
|
|
- [[v1-prototype-tech-spec]] — clean implementation-facing technical specification distilled from this document
|
|
|
|
|
- [[ai-assistance-guide]] — conventions for AI agents in this repo
|
|
|
|
|
- [[agent-change-process]] — C0/C1/C2 change methodology
|
|
|
|
|
|