2026-08-19 09:52:07 -07:00
|
|
|
# poimen-memory — task board
|
|
|
|
|
|
2026-08-22 21:43:23 -07:00
|
|
|
64 tasks — 54 build tasks plus **10 composition gates**, one per phase. One file
|
2026-08-19 09:52:07 -07:00
|
|
|
per task, **self-contained**: inlined design facts, executable steps, acceptance
|
|
|
|
|
criteria, a `Verify` section written for someone who did not build the thing, and
|
|
|
|
|
the traps worth naming. Reading `DESIGN.md` is not required to do a task — it is
|
|
|
|
|
linked as background only.
|
|
|
|
|
|
|
|
|
|
Each `Verify` section names the harness, the integration test with numbered
|
|
|
|
|
assertions, the command to run, and the **false pass** — the shape of test that
|
|
|
|
|
goes green while the feature is broken. Treat the false-pass list as part of the
|
|
|
|
|
acceptance criteria, not commentary.
|
|
|
|
|
|
|
|
|
|
## Ordering — declared, never derived
|
|
|
|
|
|
|
|
|
|
**Phase order is the list below. Task ids are opaque and frozen.**
|
|
|
|
|
|
|
|
|
|
`M0.3` is `M0.3` forever, in whatever phase it currently sits, because its
|
|
|
|
|
artifacts and cross-references key on that id. New tasks take new ids rather than
|
|
|
|
|
renumbering neighbours. This is the `StepId` rule applied to the board itself —
|
|
|
|
|
a board that renumbers to reorder has the bug it warns its own users about.
|
|
|
|
|
|
|
|
|
|
No phase starts until its predecessor's gate is green. The `gate` task at the end
|
|
|
|
|
of each phase **is** that gate: it proves the phase's parts compose and that its
|
|
|
|
|
swappable parts are genuinely swappable. Every build task is verified alone; the
|
|
|
|
|
gate verifies the properties no single task owns.
|
|
|
|
|
|
|
|
|
|
## Two rules this board exists to protect
|
|
|
|
|
|
|
|
|
|
**1. The JSONL log is authoritative; the vault and the vector index are
|
|
|
|
|
projections.** Anything that cannot be dropped and rebuilt byte-identically from
|
|
|
|
|
the log has hidden inputs, and that is a bug. `M2.8` is the gate that enforces it.
|
|
|
|
|
|
|
|
|
|
**2. The update gate must discriminate, not summarize.** Agent transcripts are
|
|
|
|
|
~43% tool results and mostly evidence-free. A gate that accepts most chunks is an
|
|
|
|
|
expensive summarizer that will reproduce the memory-explosion failure the whole
|
|
|
|
|
design exists to avoid. `M1.8` is the gate that enforces it, and **update-rate is
|
|
|
|
|
the single number to watch.**
|
|
|
|
|
|
|
|
|
|
## Verification practice — script first, source second
|
|
|
|
|
|
|
|
|
|
A task is verified by running its command and reading the output, then opening
|
|
|
|
|
the source. Reviewing the diff first is how an assertion that was quietly dropped
|
|
|
|
|
still gets called done: the code looks right, and nothing proves the test ran.
|
|
|
|
|
|
|
|
|
|
Numbered assertion N in a `Verify` section is test fn `aN_<slug>`. The numbering
|
|
|
|
|
is the contract — a test fn that does not exist should report missing rather than
|
|
|
|
|
be silently absent from a green summary.
|
|
|
|
|
|
|
|
|
|
`cargo test` reporting `ok` with zero tests run is not a pass.
|
|
|
|
|
|
|
|
|
|
## Progress
|
|
|
|
|
|
|
|
|
|
**Source of truth is the `Status` field in each task file.** The tables below
|
|
|
|
|
mirror it; a status changed here and not there is a lie.
|
|
|
|
|
|
|
|
|
|
Legend: ⬜ not started · 🟡 in progress · ✅ done · ⛔ blocked
|
|
|
|
|
|
|
|
|
|
| # | Phase | Ids | Tasks | ✅ | 🟡 | ⬜ | Gate |
|
|
|
|
|
|---|---|---|---|---|---|---|---|
|
2026-08-22 21:43:23 -07:00
|
|
|
| 1 | Read-only spine | M0.x | 8 | 8 | 0 | 0 | ✅ M0.8 |
|
|
|
|
|
| 2 | Gated loop at L1 | M1.x | 8 | 8 | 0 | 0 | ✅ M1.8 |
|
|
|
|
|
| 3 | Projections | M2.x | 8 | 5 | 0 | 3 | ✅ M2.8 (M2.1, M2.3, M2.4, M2.5 ✅) |
|
|
|
|
|
| 4 | L2 synthesis + retrieval | M3.x | 4 | 4 | 0 | 0 | ✅ M3.4 |
|
|
|
|
|
| 4.5 | Distributed API Layer | M3.5.x | 9 | 0 | 0 | 9 | ⬜ M3.5.8 |
|
|
|
|
|
| 5 | Skills | M4.x | 3 | 0 | 1 | 2 | ⬜ M4.3 |
|
|
|
|
|
| 5.5 | Reference corpora | M3.6.x | 6 | 0 | 0 | 6 | ⬜ M3.6.6 |
|
|
|
|
|
| 5.6 | Tool context | M3.7.x | 6 | 0 | 2 | 4 | ⬜ M3.7.6 |
|
2026-08-19 09:52:07 -07:00
|
|
|
| 6 | Post-training | M5.x | 6 | 0 | 0 | 6 | ⬜ M5.6 |
|
|
|
|
|
| 7 | agent-manager migration | M6.x | 6 | 0 | 0 | 6 | ⬜ M6.6 |
|
2026-08-22 21:43:23 -07:00
|
|
|
| | **Total** | | **64** | **33** | **3** | **28** | 4/10 green |
|
2026-08-19 09:52:07 -07:00
|
|
|
|
2026-08-22 21:43:23 -07:00
|
|
|
**Where the line is — 2026-08-22.** M0 is complete (8/8 tasks, 35 tests passing,
|
|
|
|
|
M0.8 gate green). M1 is next. Significant early work exists for M3.7 and M4:
|
|
|
|
|
`mem-core/src/lesson.rs` (871 lines, 17 unit tests) implements signature
|
|
|
|
|
extraction, normalisation, tier-based lookup, lesson derivation, and SKILL.md
|
|
|
|
|
rendering — advancing M3.7.7, M3.7.5, and M4.1 to 🟡. `mem-cli/src/lessons_cmd.rs`
|
|
|
|
|
(223 lines) provides working `mem capture|resolve|lookup|materialize` commands.
|
|
|
|
|
|
|
|
|
|
`M2.2` (the CNPG manifest), `M5.4` (vLLM with LoRA), `M3.5.x` (API layer), and
|
|
|
|
|
all of `M6.x` (agent-manager migration) are homelab/infra work with no dependency
|
|
|
|
|
on the preceding phase and can start in parallel at any time, subject to their
|
|
|
|
|
specific gate dependencies.
|
2026-08-19 09:52:07 -07:00
|
|
|
|
|
|
|
|
**M6 is a different repo, not a dependency of M0-M5.** It migrates
|
|
|
|
|
`github.com/Riotpiaole/agent-manager`'s session store (a separate Go CLI tool,
|
|
|
|
|
unrelated to this project's own memory system) from local sqlite to its own
|
|
|
|
|
dedicated CNPG cluster. It rides in this board because it's homelab work
|
|
|
|
|
happening alongside M2.2/M5.4, and because the two projects' Postgres schemas
|
|
|
|
|
landing in the same cluster around the same time need to look like siblings,
|
|
|
|
|
not strangers — see M6.6's convention-consistency check.
|
|
|
|
|
|
|
|
|
|
## 1 — Read-only spine · M0.x
|
|
|
|
|
|
|
|
|
|
No model calls anywhere in this phase. The point is to prove the corpus parses
|
|
|
|
|
and chunks sanely before spending inference on it.
|
|
|
|
|
|
|
|
|
|
| Task | Title | Size | Flags | Status |
|
|
|
|
|
|---|---|---|---|---|
|
2026-08-22 21:43:23 -07:00
|
|
|
| [M0.1](M0.1-cargo-workspace.md) | Cargo workspace + crate skeletons | S | — | ✅ |
|
|
|
|
|
| [M0.2](M0.2-domain-types.md) | Domain types and sha256 identity | S | — | ✅ |
|
|
|
|
|
| [M0.3](M0.3-recordsource-and-chunkpolicy.md) | `RecordSource` trait + `ChunkPolicy` | M | — | ✅ |
|
|
|
|
|
| [M0.4](M0.4-tokenizer-sizing.md) | Tokenizer-backed chunk sizing | M | — | ✅ |
|
|
|
|
|
| [M0.5](M0.5-pi-session-adapter.md) | pi session adapter | M | — | ✅ |
|
|
|
|
|
| [M0.6](M0.6-claude-transcript-adapter.md) | Claude transcript adapter | S | — | ✅ |
|
|
|
|
|
| [M0.7](M0.7-ingest-dry-run.md) | `mem ingest --dry-run` | S | — | ✅ |
|
|
|
|
|
| [M0.8](M0.8-m0-gate.md) | **M0 composition gate** | M | gate | ✅ |
|
2026-08-19 09:52:07 -07:00
|
|
|
|
|
|
|
|
## 2 — Gated loop at L1 · M1.x
|
|
|
|
|
|
|
|
|
|
| Task | Title | Size | Flags | Status |
|
|
|
|
|
|---|---|---|---|---|
|
|
|
|
|
| [M1.1](M1.1-llm-chat-client.md) | `mem-llm` chat client | M | — | ⬜ |
|
|
|
|
|
| [M1.2](M1.2-standing-query-loader.md) | Standing-query YAML loader | M | — | ⬜ |
|
|
|
|
|
| [M1.3](M1.3-prompt-template.md) | GRU-Mem prompt template | M | — | ⬜ |
|
|
|
|
|
| [M1.4](M1.4-gate-response-parser.md) | Gate-response parser | M | — | ⬜ |
|
|
|
|
|
| [M1.5](M1.5-gated-loop.md) | The gated loop | L | — | ⬜ |
|
|
|
|
|
| [M1.6](M1.6-jsonl-event-log.md) | JSONL event log writer | M | — | ⬜ |
|
|
|
|
|
| [M1.7](M1.7-ingest-end-to-end.md) | `mem ingest` end to end | M | — | ⬜ |
|
|
|
|
|
| [M1.8](M1.8-m1-gate.md) | **M1 composition gate** | M | gate | ⬜ |
|
|
|
|
|
|
|
|
|
|
## 3 — Projections · M2.x
|
|
|
|
|
|
|
|
|
|
| Task | Title | Size | Flags | Status |
|
|
|
|
|
|---|---|---|---|---|
|
|
|
|
|
| [M2.1](M2.1-embeddings-client.md) | Embeddings client | S | — | ⬜ |
|
|
|
|
|
| [M2.2](M2.2-memory-db-manifest.md) | CNPG `memory-db` + pgvector | M | homelab | ⬜ |
|
|
|
|
|
| [M2.3](M2.3-schema-and-migrations.md) | Schema + sqlx migrations | M | — | ⬜ |
|
|
|
|
|
| [M2.4](M2.4-pgvector-repo.md) | pgvector repository | M | — | ⬜ |
|
|
|
|
|
| [M2.5](M2.5-obsidian-projector.md) | Obsidian projector | M | — | ⬜ |
|
|
|
|
|
| [M2.6](M2.6-rebuild-from-log.md) | `mem rebuild --from-log` | M | — | ⬜ |
|
|
|
|
|
| [M2.7](M2.7-verify-edges.md) | `mem verify` — edge closure | S | — | ⬜ |
|
|
|
|
|
| [M2.8](M2.8-m2-gate.md) | **M2 composition gate** | M | gate | ⬜ |
|
|
|
|
|
|
|
|
|
|
## 4 — L2 synthesis and retrieval · M3.x
|
|
|
|
|
|
|
|
|
|
| Task | Title | Size | Flags | Status |
|
|
|
|
|
|---|---|---|---|---|
|
2026-08-22 21:43:23 -07:00
|
|
|
| [M3.1](M3.1-l2-synthesis.md) | L2 synthesis pass | M | — | ✅ |
|
|
|
|
|
| [M3.2](M3.2-rerank-client.md) | Rerank client | S | — | ✅ |
|
|
|
|
|
| [M3.3](M3.3-mem-query.md) | `mem query` with provenance | M | — | ✅ |
|
|
|
|
|
| [M3.4](M3.4-m3-gate.md) | **M3 composition gate** | M | gate | ✅ |
|
2026-08-19 09:52:07 -07:00
|
|
|
|
2026-08-20 19:10:09 -07:00
|
|
|
## 4.5 — Distributed API Layer · M3.5.x
|
|
|
|
|
|
|
|
|
|
Homelab frontend integration: HTTP facade via `api.riotpiao.com`. Runs in parallel with M4 and M5 after M3.4 green.
|
|
|
|
|
|
|
|
|
|
| Task | Title | Size | Flags | Status |
|
|
|
|
|
|---|---|---|---|---|
|
2026-08-22 21:43:23 -07:00
|
|
|
| [M3.5.1](M3.5.1-http-server.md) | HTTP server + router, Kong auth, metrics | M | — | ✅ |
|
|
|
|
|
| [M3.5.2](M3.5.2-ingest-endpoint.md) | POST /ingest async queue | M | — | ✅ |
|
|
|
|
|
| [M3.5.3](M3.5.3-query-endpoint.md) | GET /query HNSW+rerank | M | — | ✅ |
|
|
|
|
|
| [M3.5.4](M3.5.4-query-federation.md) | Query federation | M | — | ✅ |
|
|
|
|
|
| [M3.5.5](M3.5.5-skills-endpoint.md) | GET /skills endpoint | M | — | ✅ |
|
|
|
|
|
| [M3.5.6](M3.5.6-projects-endpoint.md) | GET /projects endpoint | S | — | ✅ |
|
|
|
|
|
| [M3.5.7](M3.5.7-rate-limiting.md) | Rate limiting | M | — | ✅ |
|
|
|
|
|
| [M3.5.8](M3.5.8-m3.5-gate.md) | **M3.5 composition gate** | M | gate | ⏳ |
|
|
|
|
|
| [M3.5.9](M3.5.9-git-aware-references.md) | Git-aware references: lookup by code location | M | — | ⬜ |
|
2026-08-20 19:10:09 -07:00
|
|
|
|
2026-08-19 09:52:07 -07:00
|
|
|
## 5 — Skills · M4.x
|
|
|
|
|
|
|
|
|
|
| Task | Title | Size | Flags | Status |
|
|
|
|
|
|---|---|---|---|---|
|
2026-08-22 21:43:23 -07:00
|
|
|
| [M4.1](M4.1-skill-draft.md) | `mem skill draft` | M | — | 🟡 `render_skill()` in `lesson.rs`, `mem materialize` in CLI |
|
2026-08-19 09:52:07 -07:00
|
|
|
| [M4.2](M4.2-derived-filter.md) | `derived: true` ingest filter | M | — | ⬜ |
|
|
|
|
|
| [M4.3](M4.3-m4-gate.md) | **M4 composition gate** | M | gate | ⬜ |
|
|
|
|
|
|
2026-08-22 21:43:23 -07:00
|
|
|
## 5.5 — Reference corpora · M3.6.x
|
|
|
|
|
|
|
|
|
|
Documentation the local models are weak at — `kubectl`, `tea` — made retrievable
|
|
|
|
|
as level **R**: embedded and indexed, never evidence. Ids are `M3.6.x` and stay
|
|
|
|
|
`M3.6.x`; the phase sits here rather than at 4.6 because [M3.6.4](M3.6.4-reference-cycle-guard.md)
|
|
|
|
|
extends M4.2's matcher instead of duplicating it, and because skills are the
|
|
|
|
|
better answer to the same problem and should exist first.
|
|
|
|
|
|
|
|
|
|
**The load-bearing property is a negative one.** Adding a corpus must not change
|
|
|
|
|
update-rate, must not change default query output, and must not put an R node in
|
|
|
|
|
any provenance chain. R bypasses the recurrence structurally — `run_loop` needs a
|
|
|
|
|
`Query` and a corpus has none — not by a flag. [M3.6.6](M3.6.6-m3.6-gate.md)
|
|
|
|
|
asserts M1.8's numbers are *unchanged*, not merely still-passing, because
|
|
|
|
|
documentation fed to the gate would lower update-rate and make M1.8 easier to
|
|
|
|
|
clear while the memory got worse.
|
|
|
|
|
|
|
|
|
|
| Task | Title | Size | Flags | Status |
|
|
|
|
|
|---|---|---|---|---|
|
|
|
|
|
| [M3.6.1](M3.6.1-doc-corpus-source.md) | `DocCorpusSource` + heading chunking | M | — | ⬜ |
|
|
|
|
|
| [M3.6.2](M3.6.2-level-r-storage.md) | Level R: log, index, vault, rebuild parity | M | — | ⬜ |
|
|
|
|
|
| [M3.6.3](M3.6.3-mem-ref-cli.md) | `mem ref` — replace-on-change corpus management | M | — | ⬜ |
|
|
|
|
|
| [M3.6.4](M3.6.4-reference-cycle-guard.md) | Reference text cannot re-enter as evidence | M | — | ⬜ |
|
|
|
|
|
| [M3.6.5](M3.6.5-query-levels-and-floor.md) | Query: filter-then-recall, R opt-in, floor | M | — | ⬜ |
|
|
|
|
|
| [M3.6.6](M3.6.6-m3.6-gate.md) | **M3.6 composition gate** | M | gate | ⬜ |
|
|
|
|
|
|
|
|
|
|
## 5.6 — Tool context · M3.7.x
|
|
|
|
|
|
|
|
|
|
Answers *"what do we already know about this failure, tool or task"* over HTTP.
|
|
|
|
|
Consumers are `pi`, curl, or an MCP call — nothing here executes a tool, and
|
|
|
|
|
nothing here serves a tool catalog, because every caller already holds its own
|
|
|
|
|
MCP schemas.
|
|
|
|
|
|
|
|
|
|
**Three tiers, cheapest first.** An exact hash hit on a normalised failure
|
|
|
|
|
signature means *this happened here before*; a symptom-vector match means
|
|
|
|
|
*something similar did*; the R corpus means *nobody here has hit this, read the
|
|
|
|
|
docs*. The tier is a field in the response, because those three answers must not
|
|
|
|
|
arrive in the same register.
|
|
|
|
|
|
|
|
|
|
**The two tasks that make it work are the least obvious ones.**
|
|
|
|
|
[M3.7.7](M3.7.7-signature-extraction.md) decides whether tier 1 ever fires — if
|
|
|
|
|
normalisation leaves a timestamp in, the same failure never hashes twice and the
|
|
|
|
|
system silently degrades to vector search.
|
|
|
|
|
[M3.7.8](M3.7.8-symptom-projection.md) closes the gap between memories written as
|
|
|
|
|
answers and queries that arrive as stack traces. Both fail invisibly, which is why
|
|
|
|
|
[M3.7.6](M3.7.6-m3.7-gate.md) ablates them rather than trusting an end-to-end
|
|
|
|
|
green.
|
|
|
|
|
|
|
|
|
|
Ids are `M3.7.x` and frozen. `M3.7.1` and `M3.7.2` were a tool-catalog surface,
|
|
|
|
|
deleted before implementation once the consumer was settled; their ids are retired
|
|
|
|
|
rather than reused.
|
|
|
|
|
|
|
|
|
|
| Task | Title | Size | Flags | Status |
|
|
|
|
|
|---|---|---|---|---|
|
|
|
|
|
| [M3.7.3](M3.7.3-skill-matching.md) | `GET /memory/skills?task=` — match a subset | M | — | ⬜ |
|
|
|
|
|
| [M3.7.4](M3.7.4-context-endpoint.md) | `/memory/context` — three-tier lookup | M | — | ⬜ |
|
|
|
|
|
| [M3.7.5](M3.7.5-tool-failure-learning.md) | `tool-failures` standing query | M | — | 🟡 `derive_lessons()` + `tool_of_cmd()` in `lesson.rs`, `mem resolve` in CLI |
|
|
|
|
|
| [M3.7.6](M3.7.6-m3.7-gate.md) | **M3.7 composition gate** | M | gate | ⬜ |
|
|
|
|
|
| [M3.7.7](M3.7.7-signature-extraction.md) | Failure signature extraction + normalisation | M | — | 🟡 `extract()` + `normalise()` in `lesson.rs` (10 unit tests passing) |
|
|
|
|
|
| [M3.7.8](M3.7.8-symptom-projection.md) | Symptom projection at ingest | M | — | ⬜ |
|
|
|
|
|
|
2026-08-19 09:52:07 -07:00
|
|
|
## 6 — Post-training · M5.x
|
|
|
|
|
|
|
|
|
|
Python, separate from the Rust workspace. The boundary is the JSONL log.
|
|
|
|
|
|
|
|
|
|
| Task | Title | Size | Flags | Status |
|
|
|
|
|
|---|---|---|---|---|
|
|
|
|
|
| [M5.1](M5.1-evidence-labeler.md) | `mem label` — evidence labeler | M | — | ⬜ |
|
|
|
|
|
| [M5.2](M5.2-labeler-calibration.md) | Labeler calibration | M | — | ⬜ |
|
|
|
|
|
| [M5.3](M5.3-training-corpus-export.md) | Training corpus export | M | — | ⬜ |
|
|
|
|
|
| [M5.4](M5.4-vllm-lora-serving.md) | vLLM + `--enable-lora` | L | homelab | ⬜ |
|
|
|
|
|
| [M5.5](M5.5-verl-training-loop.md) | verl training loop | L | — | ⬜ |
|
|
|
|
|
| [M5.6](M5.6-m5-gate.md) | **M5 composition gate** | L | gate | ⬜ |
|
|
|
|
|
|
|
|
|
|
## 7 — agent-manager migration · M6.x
|
|
|
|
|
|
|
|
|
|
Separate repo (`github.com/Riotpiaole/agent-manager`, fork branch
|
|
|
|
|
`add-headless-spawn`), separate cluster resource, no Rust/GRU-Mem
|
|
|
|
|
dependency. Moves its session store off local sqlite onto a dedicated CNPG
|
|
|
|
|
Postgres, reachable from the Mac client through a dedicated nginx route —
|
|
|
|
|
durability-of-location, not a multi-host requirement.
|
|
|
|
|
|
|
|
|
|
| Task | Title | Size | Flags | Status |
|
|
|
|
|
|---|---|---|---|---|
|
|
|
|
|
| [M6.1](M6.1-agent-manager-db-manifest.md) | CNPG `agent-manager-db` manifest | M | homelab | ⬜ |
|
|
|
|
|
| [M6.2](M6.2-schema-port.md) | Postgres schema for agent-manager sessions | M | — | ⬜ |
|
|
|
|
|
| [M6.3](M6.3-store-query-port.md) | store.go query port to Postgres | L | — | ⬜ |
|
|
|
|
|
| [M6.4](M6.4-nginx-stream-routing.md) | nginx TCP routing to `agent-manager-db` | S | homelab | ⬜ |
|
|
|
|
|
| [M6.5](M6.5-credentials-secret.md) | Postgres credentials for the Mac client | S | homelab | ⬜ |
|
|
|
|
|
| [M6.6](M6.6-m6-gate.md) | **M6 composition gate** | M | gate | ⬜ |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
Background: [DESIGN.md](../DESIGN.md) · GRU-Mem, arXiv 2602.10560 · `internal/store/store.go` (agent-manager, `add-headless-spawn` branch)
|