Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

v0.4 closure & roadmap review: what shipped, what slipped back, what comes next

FieldValue
Date finalised2026-06-02
AuthorRômulo Febasi <romulo@febasi.com.br> (analysis assisted by Claude Code)
ScopePost-mortem read of the v0.4.0 release (2026-05-27): what landed, what architectural debt re-grew, what the README failed to advertise, and the prioritised next-three-actions before v0.5 code starts.
Statusaccepted: input to the v0.5 brief and to the README §Status refresh (commit b37a418)
InputsRepository walk on 2026-06-02; find src/ -name '*.rs' | xargs wc -l; cross-read of ADR-015 vs current file sizes; CHANGELOG.md from the auto-generated v0.4.0 section; live gh issue list --milestone "v0.5 Semantic layer"; live gh issue list --milestone "v1.0 Stable".
Out of scopeThe v0.5 brief itself (separate document, same day). Code changes: only audit + recommendation.

Executive summary

v0.4 shipped 18/18 tickets in two weeks (12 core + 6 stretch), four releases in that window, zero rollback. The product moved from “auditable AI second brain” to “auditable AI second brain with cross-editor LSP + portable identity v2 + real MCP sampling”. For a solo project that is delivery above the curve.

But the ride exposed three honest items that need to be flagged before v0.5 code begins: (1) src/mcp/server.rs regrew to 844 lines, breaking the red-tier threshold of the very ADR-015 that v0.4 wrote to contain it: SYN-150 split the file, then SYN-136 (replay_proposal) and SYN-138 (reindex) brought ~300 lines of new handlers back in. (2) the README §Status only listed v0.1 + v0.2 until 2026-06-02: three releases were invisible to anyone landing on the repo, including the entire LSP companion that is the most differentiated single artefact of v0.4. (3) v0.5’s GitHub milestone has 11 issues but no brief: v0.4 worked because it had one; starting v0.5 code without one is committing to architectural decisions inside the largest backend module rewrite of the project so far.

1. Context and premisses

  • v0.4.0 tagged + pushed 2026-05-27 03:31; mirror release synchronised 12 s later (run 26489555101). Cross-platform assets present for aarch64 + x86_64 macOS, aarch64 + x86_64 Linux GNU, x86_64 Windows MSVC. Smoke test of the public mirror binary on the author’s laptop (aarch64-apple-darwin) confirms 15 MCP tools advertised including reindex and replay_proposal.
  • 121 unit tests pass on the full feature matrix (mcp lsp mcp_tasks); zero clippy warnings under -D warnings; cargo doc clean.
  • v0.5 milestone holds 11 issues (SYN-80..SYN-89 + SYN-93b network freshness) filed during the original v0.5 planning sprint in 2026-05-24.
  • v1.0 milestone holds 10 issues (SYN-100..SYN-109).
  • No code changes are being proposed in this document, the changes that matter (re-split, brief, benchmark spike) are recorded as ticket sketches for the v0.5 brief that ships next to this file.

2. Architectural read: file by file

2.1 Red tier (>800 lines per ADR-015): one file

PathLinesNotes
src/mcp/server.rs844Carries 15 #[tool] handlers + ServerHandler impl + resource/prompt routing. SYN-150 reduced it from ~1380 → ~550 on 2026-05-25; SYN-136 added replay_proposal (~120 lines including the sampling builder), SYN-138 added reindex with the tasks progress callback shim (~80 lines), SYN-140 added the Redactable wiring at the call sites (~10 lines), plus the docstring expansion. Net: back to red tier two weeks after the split.

What this means: ADR-015’s playbook (split when red, target < 500) was followed once and then quietly disregarded by every subsequent MCP feature. The pattern is recurring because #[tool_router] in rmcp 1.7 mandates one impl block: every tool handler has to land in the same file, so the attractor pulls every new MCP feature back here. The split that holds long term is not a second pass of the same kind (extracting helpers) but a dispatcher pattern: keep #[tool] shims thin (3–8 lines each) and move all logic to core::mcp::* use case modules outside the macro’s reach.

2.2 Yellow tier (500–800 lines): five files

PathLinesTrajectory
src/core/identity/mod.rs650Stable. Concentrated crypto + bundle serde + canonical JSON. experience.rs already extracted. Split if v0.5 adds curriculum endorsements: otherwise leave it.
src/cli/at.rs620Grew 280 lines in v0.4 (SYN-141 list/info/graph + SYN-142 sandbox wiring). Candidate for cli/at/{mod,search,show,list,info,graph}.rs split.
src/cli/audit.rs611list/show/prune/stale/verify/replay. Six subcommands in one file. Candidate for cli/audit/{listing,verify,replay,stale,prune}.rs split.
src/cli/ws.rs577Grew with syn ws clone (SYN-143). Still coherent. Don’t pre-emptively split.
src/registry/mod.rs562Schema + queries + cache + freshness coexist. Stable; defer split until v0.6.

2.3 Green tier (< 500): everything else

Notably core/at.rs (the SYN-142 sandbox builder, 339 lines) and lsp/server.rs (437 lines) landed well within the green tier. The trait Redactable (SYN-140) reduced what would have been ~60 lines of duplication across three call sites into one trait + two impls. These are the v0.4 wins that the file-size scoreboard rewards.

3. Surface-level adoption gaps

GapImpactEffort to close
README §Status frozen at v0.1+v0.2 until 2026-06-02Three releases invisible to the repo landing page; LSP companion (highest-leverage v0.4 single-feature) buried in the docs table✅ closed in b37a418 (commit before this doc)
No section “Editor integration” near top of READMEThe cross-editor LSP differentiator is the kind of thing visitors discover only by reading every line~1 h: add a short H2 with three editor logos + syn lsp --help snippet
No badges in README header (release, MSRV, license, CI)Reduces credibility signal at first glance~30 min
No demo asciinema / GIF for syn lsp and syn cv exportThese are the v0.4 features that show well in motion and don’t show well in text~2 h
Install path is cargo install only (no Homebrew, no curl pipe, no npm)macOS first-time users are the largest single platform-bucket for Claude Code adoption, the highest-leverage friction pointSYN-101 (curl pipe) ~1 day; SYN-102 (Homebrew tap) ~2 days. Both filed under v1.0 but the cost of moving them earlier is zero.
No GitHub Pages docs siteREADME is ~150 lines and growing; new contributors land and don’t know where to startSYN-109 v1.0 ticket: antecipar para v0.5

4. Strategic bets that v0.5 is choosing without a brief

There are at least four decisions baked into the v0.5 milestone issues (SYN-80..SYN-89) that were not load-bearing-discussed before they were opened on 2026-05-24:

  1. Embedding backend. ADR-008’s slot says “chosen default embedding backend after benchmark” but no benchmark was run before the issues were filed. Three real candidates: Ollama-as-runner (forces external dep), fastembed-rs (ONNX Runtime under the hood, ships small models), pure candle (HuggingFace’s Rust framework, no ONNX dependency). The trade-off: local-first vs perf vs binary size, needs a 1-day spike with numbers before SYN-83 starts.
  2. Vector storage choice. SYN-81 says “sqlite-vec via load_extension”. sqlite-vec is real, recent, used in production. But the combination of rusqlite bundled + load_extension has known ABI gotchas (Alex Garcia documents them explicitly). If sqlite-vec fails the spike, the fallback is lance (full vector DB) or a hand-rolled flat / HNSW index: both larger architectural decisions than the issue title implies.
  3. Hybrid ranking algorithm. SYN-86 says “reciprocal rank fusion”. RRF is the cold-start default (Elastic, Qdrant, Weaviate, OpenSearch ship it). But 2026 papers show convex combination (`α * dense + (1-α)
    • bm25`) outperforming RRF with as little as ~40 labelled relevance pairs. For a personal second-brain workspace that pair set is self-collectable. RRF is right for v0.5 ship; convex combination is the next-step polish.
  4. Search target. Is syn search hybrid by default, or vector-only behind --semantic? SYN-87 reads “vector-only mode” which suggests the second; SYN-86 reads “hybrid” which suggests the first. The two tickets are inconsistent. The brief needs to pick one.

5. Recommendation: the next three actions, ordered

#ActionEffortWhy it goes first
1Write the v0.5 brief: docs/researchs/YYYY-MM-DD-v0.5-…: with the 4 strategic decisions above answered with reasons and a benchmark spike for the embedding backend2 days (1 day brief, 1 day spike)v0.4 worked because the brief did the load-bearing thinking; v0.5 touches the largest single new module (vector index) and the biggest external choice (embedding backend): committing without a brief is committing to commit-driven design
2File SYN-151: re-split mcp/server.rs to the dispatcher pattern (thin #[tool] shims, logic in core::mcp::*) before any v0.5 MCP feature lands½ dayADR-015’s red tier exists for this exact file. Every new MCP feature in v0.5 (semantic_search per SYN-88, reindex_vectors) lands here. Pay now or pay 3× later.
3Visibility polish: README §Editor integration section + Homebrew tap (antecipate SYN-102) + asciinema demo of syn lsp1–2 daysv0.4’s most differentiated single feature (cross-editor LSP) was undiscoverable until 2026-06-02. Polish converts what’s already built; it does not gate v0.5.

6. Risk register

RiskSeverityMitigation
mcp/server.rs regrows again after the v0.5 dispatcher refactor because the macro contract still wants a single impl blockMediumDocument the dispatcher pattern in ADR-015 §Playbook so it survives the next contributor; add a CI lint that fails on mcp/server.rs > 600 lines
Embedding backend choice (Ollama vs fastembed vs candle) gets locked by accident through the first PR rather than by ADRHighThe v0.5 brief MUST close the open decision before SYN-83 is started. ADR-008 must land first.
Visibility polish slips because v0.5 code feels more urgentLow–MediumMake item #3 above explicitly a v0.4.1-bucket so it can ship independently of the v0.5 milestone
tower-lsp-server (v0.4 dep, ADR-018) goes inactive like its upstream didLowThe fork was active 2025-12; the LSP backend is ~440 lines; documented as portable to hand-rolled JSON-RPC in extremis
v1.0 milestone has 10 issues but no plan for the x-ai-* schema freeze that v0.4 just expanded (SYN-137 added x-ai-history)MediumFile a v1.0 ticket “SEMVER policy for the x-ai-* namespace”: SYN-104 covers frontmatter broadly but the AI provenance subset needs its own decision

7. Open decisions for the v0.5 brief to close

  1. Which embedding backend: Ollama (~700 MB binary + ~280 MB model = ~1 GB footprint, external dep) vs fastembed-rs (~10 MB crate + ~33 MB BGE-small quantised, embedded inference via ONNX Runtime) vs pure candle (no ONNX, more flexibility, slower per-query)? Bias from the owner: local-first, no Ollama. Brief must show the trade-off with numbers.
  2. Vector storage: sqlite-vec (lean, in-process, recent), lance (full vector DB, heavier), or hand-rolled flat / HNSW? Spike before committing.
  3. Hybrid ranking: RRF (cold-start safe) or convex combination (better with labelled data: does a single-user workspace have those?).
  4. Default mode for syn search: hybrid by default, vector-only behind --semantic flag, or the inverse?
  5. Insertion-time vs query-time enrichment. The owner explicitly stated 2026-06-02: “ao invés de usar puramente um LLM para isso, é organizar e processar esses dados no momento que estamos inserindo eles”. This is a business rule (BR-13 candidate) and changes the v0.5 architecture meaningfully: entity linking happens on syn project add, not on syn search. The brief codifies this.
  6. Adoption polish: does it ship as a hot-fix v0.4.1 cycle, parallel to v0.5, or after v0.5?

8. References

  • ADR-015: modular files policy (yellow 500–800 / red 800+), the threshold mcp/server.rs just crossed.
  • ADR-018: tower-lsp-server 0.23 fork rationale.
  • v0.4 brief: docs/researchs/2026-05-25-v0.4-refinement-and-extensibility.md.
  • CHANGELOG.md §0.4.0: list of 15 features merged in the cycle.
  • README §Status: refreshed in b37a418 on 2026-06-02; this doc is the reasoning trail behind that refresh.