Remaining Work — local-node roadmap (post Phase 5)
Status: historical record — roadmap notes from the modeld refactor; build/test recipes here predate the current Makefile targets (see
CONTRIBUTING.md).
Status note (this session): the codebase was replaced with the completed
modeldrefactor and the following landed + verified: daemon wiring (cmd/modeld now importsmodeld/llama/llamasession), manifest token-range population, the common benchmark harness (runtime/benchreport+ real llama driver), the OpenVINO in-flight cancel test, and model-native llama tool calls (llama.cpp common chat template path, tools across the transport, output parser).Build/test recipe for the tagged llama path:
make build-modeld-llama test-llamacpp-direct-cpu, thenCGO_ENABLED=1 CGO_CPPFLAGS="-I$PWD/tmp/ref/llama.cpp/common -I$PWD/tmp/ref/llama.cpp/vendor -I$PWD/.llamacpp-runtime/cpu/include" CGO_LDFLAGS="-L$PWD/.llamacpp-runtime/cpu/lib -Wl,--disable-new-dtags -Wl,-rpath,$PWD/.llamacpp-runtime/cpu/lib -Wl,-rpath-link,$PWD/.llamacpp-runtime/cpu/lib -l:libcommon.a -l:libllama.so -l:libggml.so -l:libggml-base.so -l:libggml-cpu.so -lstdc++ -lm -ldl -lpthread" go test -tags 'llamanode llamacpp_direct' ./modeld/llama/...OpenVINO: model at.openvino/models/qwen-coder-0.5b-int4; flags resolved from the.openvino/venvlikeMakefile.openvino(make -f Makefile.openvino test-s1-5).
Update (2026-06-18): landed + verified (pure-Go build/vet/tests green) —
make build-modeldwired: CGO flags via sharedmk/openvino-flags.mk+mk/llama-flags.mk;make deps-modeldreproduces deps. Parallelism capped (-p) to avoid OOM.- modeld single-backend made coherent:
cmd/modeldregistry picks one backend (CONTENOX_MODELD_BACKEND/ preference); the owner lease + gRPC health advertise it;modeldprobe.Status.Backend+modeldconn.Backend()let the runtime detect the daemon’s mode and gate each provider’sSessionAvailable().- Typed transport handle:
transport.OpenSessionRequestnow carries{ModelName, Type, Digest, Path}(was a rawModelIDpath); modeld validatesTypeagainst its served backend (transport.ErrBackendMismatch).- Both local backends registered:
contenox initregistersllamaANDopenvinoat per-type dirs~/.contenox/models/<type>/;openvinois a first-class backend type (validation +runtimestatedispatch).- OpenVINO IR
model pull(handover Step 7): curated-ovregistry entries + multi-file HF-Hub HTTP fetch intomodels/openvino/<name>/.- #6 below: eviction + class foundation done (admission policy deferred to #7).
The remaining tracks are independent unless noted. Each lists where to work and how.
#6 Semantic cache admission/eviction (PARTIALLY DONE 2026-06-18)
Goal: replace plain-LRU with the coding-aware priority from
local-coding-node-goals.md (highest: system/tool schemas/repo instructions … low:
stale logs/old turns). Pin core segments for the workspace session; admit volatile
suffix material only when likely reused.
DONE — eviction + class foundation:
- Bounded session cache (
runtime/modelrepo/warmcache.go, genericWarmCache[S]): idle-TTL reap + resident cap + LRU, never evicting a mid-turn session, closing evicted sessions so modeld releases the model. Both providers’ previously-unboundedsessionCachein{llama,openvino}/client.gonow share it. This fixed the model-switch leak (every distinct model used to stay resident in modeld until OOM). Verified inwarmcache_test.go. - Cache-class types (
runtime/contextasm/segments.go):CacheClass(task_pinned/repo_map/volatile),SegmentKind.CacheClass(),MoreEvictableThan;ManifestSegmentcarriesCacheClass+Invalidation(manifest.go), populated byAssembleManifest(additive; byte hashes unchanged).
DEFERRED to #7 (no producer yet): the budget-aware admission policy —
AdmitSegments(segs, tokenBudget) dropping highest-evictable classes first to fit
the window — plus its wiring into the chat assembler. Nothing produces the rich
segment kinds (KindRepoMap/KindDiff/KindTerminal) today; the chat providers
use a coarse role-based stable/volatile split. The #7 T3 planner is the producer;
only then can the policy be exercised + benched (benchreport hit_rate vs LRU).
Done: Snapshot/restore wiring
L0 live snapshot round-trip is wired through transport.Session and the gRPC
transport, with modeld/llama/llamasession restoring into a fresh llama.cpp
context and matching the original greedy continuation on a tiny GGUF.
The session snapshot uses full llama.cpp context state (llama_state_get_data /
llama_state_set_data) through modeld/llama/llamacppshim/direct.go, not only
llama_state_seq_*, because sequence state restores KV memory but not the last
logits buffer needed for exact next-token equality.
Remaining optional work: add file save/load wrappers if benchmark output should
avoid moving large state blobs through Go, and fill the snapshot_save /
snapshot_restore fields in benchreport.Report.
#7 T3 context planner + coding-context eval gate (large; needs GPU for latency)
Goal: prove “effective 200k” is real — the planner selects/cites/edits across more text than the hot window holds.
Where (new): a planner package, PlanTurn(workspace, task) -> []contextasm.Segment
(repo map, symbol graph, pins, retrieval, summaries, diff/test/log budgeter) feeding the
existing EnsurePrefix/PrefillSuffix/Decode.
Hints: the segment/manifest plumbing is done (contextasm), so the planner only
emits []Segment with cache classes (ties into #6). Build the eval harness for the gate
tasks in local-coding-node-goals.md (“Coding-context eval gate”: cross-file bug
localization, edit-A-from-B/C, trace failing test, large refactor, architecture Q with
citations); record pinned/retrieved/summarized/cached/missed/cited per task. Latency
go/no-go needs the budget GPU; correctness/selection can be evaluated on CPU + tiny model.
#4 OpenVINO capability gaps (model-gated — need extra models to verify here)
Done: deterministic in-flight cancel test (modeld/openvino/ovsession/genai_test.go);
OpenVINO is now a first-class registrable backend type (2026-06-18) — contenox init registers it, backendservice validation accepts it, runtimestate dispatches
it, and contenox model pull fetches curated IR models (see handover Step 7).
Embedding transport/provider wiring is done: profiles opt in with can_embed,
runtime calls modeldconn.Embed, and modeld runs OpenVINO GenAI
TextEmbeddingPipeline as a stateless request. System verification passed with
.openvino/models/bge-small-ov. Stream/tool history parity is done: modeld
receives assistant tool_calls and tool-result IDs in chat-template rendering,
and tool-enabled streams emit a final parsed ToolCalls parcel.
Streaming incremental reasoning is also wired: DecodeConfig.ParserProtocols
reaches OpenVINO GenAI, native incremental parsers split reasoning_content
into StreamChunk.Thinking, and the runtime only displays it when WithThink
requests a visible level. Verified with
.openvino/models/deepseek-r1-distill-qwen-1.5b-int4-ov.
Remaining:
- VLLMParserWrapper — formalize: either a Python parser-object bridge or keep the
explicit native-bridge error, documented (per
modeld/openvino/s2-7-protocol-registry.md). - Per-model-family profiles — ship
contenox-openvino.jsonfiles declaring the right tool/reasoning protocol per shipped model. - Idle session GC — the runtime side is now handled (#6): the bounded
modelrepo.WarmCachereaps idle/over-cap sessions andClose()s them, so modeld releases the model. Still worth confirming the daemon side frees promptly onClose(lifecycle is viaOpenSession/Closesince the in-process pool was removed).
Hint: to verify locally, make -f Makefile.openvino model downloads the chat model;
set CONTENOX_OPENVINO_EMBED_MODEL to a BGE OpenVINO IR and
CONTENOX_OPENVINO_REASONING_MODEL to an official DeepSeek/Phi reasoning IR with
openvino_tokenizer.xml.
Done: tool-result history
Tool results in multi-turn history (role:"tool" messages, assistant messages
with tool_calls) now flow through the message→segment mapping and modeld
reconstruction. The llama backend renders them via llama.cpp’s common chat
template layer, so the same upstream path handles tool definitions, assistant
tool calls, tool result IDs, and model-specific template handlers.
Done: Contenox-owned llama.cpp shim
The live llama path now runs on modeld/llama/llamacppshim behind the
llamacpp_direct build tag. The old llama_unsafe_abi spike and
modeld/llama/llamaabi package are retired. Remaining work on this track is
GPU/runtime certification, snapshot transport, and benchmark reporting, not
replacement of the binding itself.