For Agents

Living index of themes for this project. Each H2 is a topic; bullets are wikilinks to related notes. Updated by obsidian-documenter when documenting work. Read by historian at bootstrap. Topics kept alphabetical.

Cargo & Workspace Tooling

  • cargo-workspace-dependency-inheritance — ⚠️ cargo remove -p <member> <dep> also prunes the root [workspace.dependencies] entry once no member references it (cargo 1.95.0). Breaks the add → copy up → remove → re-inherit migration path; fails one step later at cargo check with workspace.dependencies` was not defined. Write dep.workspace = true into the member manifest directly instead
  • cargo-tree-verifying-deps-while-build-is-red — 🔧 cargo tree resolves from the manifests and does not compile, so cargo tree -p <crate> --depth 1 confirms dep.workspace = true inheritance while cargo check --workspace is failing on unrelated broken source. Companions that also survive a red build: cargo check -p <unaffected-crate> (root manifest is valid TOML), cargo tree -p <crate> -e features -i <dep> (a feature actually activated), grep -c '^\[\[package\]\]' Cargo.lock before/after (nothing silently pulled in). Cargo has two front ends — resolution and compilation — and a syntax error cannot invalidate a cargo tree result
  • Workspace Layoutedition 2024, resolver 3, two members, all deps inherited from the root block
  • Workspace Dependencies — the seven root deps and the member split, which follows lib-emits / binary-subscribes: packages/app takes tracing-subscriber because it owns the binary, packages/core/project takes chrono + tracing only

Dependency Selection

  • chrono-already-in-tree-via-arrow — ⭐ grep Cargo.lock BEFORE adding a crate. chrono v0.4.45 was already compiled into the build via arrow-array v58.4.0 ← arrow-ipc ← grafeo-engine ← grafeo (feature "arrow-export"), so declaring it directly at the same version added zero crates (149 packages before and after, one entry, no duplicate versions); features = ["serde"] only switched on impls inside a crate already present, serde v1.0.229 being there too. Picking what a heavy dependency already chose is free and semantically correct — grafeo speaks chrono via arrow, so timestamps round-trip with no conversion layer, whereas time or jiff would have added a parallel crate tree AND a type-mismatch boundary at the DB edge

Graph Database (grafeo)

  • grafeo-feature-matrix — the embedded / server / edge split, which is a real fork in the road and invisible on docs.rs. default = ["embedded"] = in-process engine (GQL, vector/text/hybrid indexes, CDC, algorithms, rayon); server adds all query languages + async-storage + triple-store + shacl; edge/browser strips to lpg + gql + regex-lite for wasm
  • Graph Layer — the workspace runs grafeo v0.5.42 on default features — in-process, GQL only, no Cypher/SPARQL/Gremlin/GraphQL/SQL-PGQ
  • chrono-already-in-tree-via-arrow — a consequence of the default feature set worth knowing: arrow-export is in embedded, so any project on default grafeo already has chrono (and serde) in its tree, and chrono is the calendar type grafeo speaks internally via arrow — the right choice for anything crossing the DB boundary
  • 2026-09-07-scope-recommendation-reconciler — ⚠️ the standing recommendation is to REMOVE grafeo. The only job worth building here — a reconciler resolving note code_refs against a code index — needs none of what embedded buys (GQL, vector/text/hybrid indexes, CDC, algorithms); SQLite suffices for 150-300 lines. ⭐ Consequence to weigh: dropping grafeo makes chrono a genuine new dependency rather than a free one, since it arrives transitively via arrow-export — see chrono-already-in-tree-via-arrow. Not decided

Observability & Tracing

  • grafeo-feature-matrix — ⭐ the load-bearing gotcha: grafeo emits no spans or events by default. tracing is opt-in (tracing = ["grafeo-engine/tracing"]), not part of embedded/default — it arrives free with server, and that asymmetry is the trap. Symptom is a silent graph layer inside an otherwise working subscriber, with no error and no warning, which misdirects debugging onto EnvFilter / RUST_LOG / init order. main.rs already has a working tracing_subscriber::fmt(), so only the sending end is compiled out

Project Overview

  • ai-project-brain — entry point. ⛔ Scaffold stage as of 2026-09-07 — workspace and dependencies exist, application code effectively does not

Project Scope & Direction

  • 2026-09-07-scope-recommendation-reconciler — 🔬 narrow the project from “graph database application” to one reconciler, per a day of knowledge-graph research. The reconciler resolves code_refs (repo + path + qualified symbol, replacing bare lib.rs:176) against a current index and marks rot: missing symbol or changed body hash sets status: stale, otherwise verified: today; a Stale notes.base view is the review queue. Runs server-side as a SessionEnd hook or systemd timer, because hooks run where Claude Code runs. Rationale: only one file-to-knowledge edge exists anywhere in the current stack and it is inert data in a dead database, so a rename invalidates zero notes — that gap is a reconciliation job, not a database feature. ⚠️ Not decided; the alternative is to drop the project and trial trace-mcp. Also do not revive the graphtest rustc_driver HIR walker — rust-analyzer scip supersedes it with stable symbols and no nightly pin
  • knowledge-graph-research-2026-09-07 — the vault-level synthesis this project now hangs off: markdown stays the source of truth, two derived disposable graphs, one anchor, one reconciler

Rust Language Traps

  • rust-path-vs-pathbuf-struct-field — ⚠️ std::path::Path cannot be a struct field by value. Path is unsized (it wraps [u8]), so path: Path fails with the size for values of type `[u8]` cannot be known at compile-timean error that never names Path and reads like it is about something else entirely. PathBuf is the owned form; the compiler always reports the innermost type, so a [u8] size error in a struct definition is almost always a Path field