A logical plan tree, cost model, and pull-based executor that drives the lower layers. After this phase, a Recall request transforms into a plan: EmbedCue → IndexSearch(filtered) → MetadataFetch → Score → Sort → Trim.
- Phase 5 complete (
brain-embedexists). brain-storage,brain-metadata,brain-indexare usable handles.
spec/12_query_optimizer/00_purpose.mdspec/12_query_optimizer/01_planner.mdspec/12_query_optimizer/01_planner.mdspec/12_query_optimizer/02_per_op_planning.mdspec/12_query_optimizer/02_per_op_planning.mdspec/12_query_optimizer/02_per_op_planning.mdspec/12_query_optimizer/02_per_op_planning.mdspec/12_query_optimizer/03_cost_estimation.mdspec/12_query_optimizer/04_executor.md
crates/brain-plannerexportsPlan,PlanNode,Executor,Context(the bag of handles passed down).- Tag:
phase-6-complete.
Reads: spec/12_query_optimizer/01_planner.md
Writes: crates/brain-planner/src/plan.rs
What to build:
- Each operator:
EmbedText,IndexSearch,MetadataFetch,EdgeTraverse,FilterByAgent,Score,Sort,Trim,WalAppend,ArenaWrite, etc. - Each variant carries its parameters.
Reads: spec/12_query_optimizer/03_cost_estimation.md
Writes: crates/brain-planner/src/cost.rs
Done when: Per-node cost = f(estimated cardinality, op cost coefficient). Total plan cost is sum of nodes. Tested with known shapes.
Reads: spec/12_query_optimizer/02_per_op_planning.md
Writes: crates/brain-planner/src/recall.rs
Done when: Recall request → plan tree per spec. Supports: cue text, filters (agent, context, kind, salience, time), K, with/without text body.
Reads: spec/12_query_optimizer/02_per_op_planning.md
Writes: crates/brain-planner/src/encode.rs
Done when: Encode request → plan: Embed → AllocSlot → ArenaWrite → MetadataWrite → IndexInsert → WalAppend (with WAL-before-ack semantics).
Reads: spec/12_query_optimizer/02_per_op_planning.md
Writes: crates/brain-planner/src/plan_reason.rs
Done when: Both queries become traversal plans with depth bounds and edge-kind filters.
Reads: spec/12_query_optimizer/02_per_op_planning.md
Writes: crates/brain-planner/src/forget.rs
Done when: Soft and hard forget plans differ as spec'd; force_reclaim flag respected.
Reads: spec/12_query_optimizer/04_executor.md
Writes: crates/brain-planner/src/executor.rs
What to build:
- Pull-based iterator model.
- Each
PlanNodehasexecute(self, ctx: &Context) -> impl Iterator<Item = Row>(or async equivalent). Contextcarries&Wal,&Arena,&MetadataDb,&HnswIndex,&Embedder. Done when: Recall plan executes end-to-end with faked storage; results match expected ordering.
Reads: spec/12_query_optimizer/01_planner.md
Writes: extend plan.rs
What to build: impl Debug for Plan with a tree pretty-printer (similar to EXPLAIN in SQL).
Done when: Plans round-trip through Debug readably; useful for diagnostics.
- All sub-tasks complete.
-
cargo test -p brain-plannergreen (101 tests passing in the Linux dev container). - Each operation type has at least one end-to-end planner test (recall/encode/forget end-to-end via the executor; PLAN + REASON planner shape tests; the dispatch smoke test exercises three ops through one fixture).
- Tag
phase-6-complete.
Phase 6 ships single-shard, single-memory planning + execution. Cross-shard fan-out and bulk / filter targets need a wire bump and land later (Phase 12 sharding for cross-shard, future wire schema for bulk / filter).
PLAN and REASON ship the planner side only — plan_path and plan_reason build full plans with depth bounds, edge-kind filters, and cost estimates, but execute(Plan|Reason) returns ExecError::Unsupported("…— Phase 7"). Bidirectional-BFS edge traversal needs the cognitive-ops scaffolding that lands with Phase 7 alongside LINK / UNLINK.
The WriterHandle trait introduced in 6.4 is the design slot the real channel-fed group-commit writer (spec §02/08 §10) plugs into in Phase 8 / Phase 9. Phase 6 ships test-only FakeWriterHandle impls that drive the test MetadataDb + SharedHnsw synchronously without WAL — enough to exercise the interface but not the durability story.
The 6.8 plan inspection ships as Display (not Debug) — the derive-generated Debug is preserved for test panic messages. Phase 9's ADMIN_EXPLAIN_PLAN opcode just wraps format!("{plan}").