Switch the os-vault rebuild hook to Unsloth 9B V4 on llama.cpp #1576
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
rule-proposal
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#1576
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The os-vault rebuild hook runs Ollama
qwen3.5:9b. Jared decided that Unsloth Qwen3.5-9B on llama.cpp is the default (ruling 23: config V4). A rebuild with the old model replaces the re-extraction results. The hook starts this rebuild when a stamp is older than 7 days. The hook also starts it in each session when no stamp and no lock exist.Observed
plugins/os-vault/hooks/session_start.pyhardcodes--backend ollama. On 2026-11-05 at 12:53 the hook started a rebuild on Ollama, and session 47ffa777 stopped it. The rebuild gate regex misses the outputstill hollowandstill truncated. #1556 covers the gate of the eval, with no numeric limit.Reproduce
n/a: a rebuild takes over one hour on the GPU.
Approach
The hook runs the V4 config on llama.cpp and re-extracts only changed notes. llm-stack has no CLI and no process control, so os-vault owns a small readiness script and the router unit file.
Required work:
plugins/os-vault/config.yamlis the one place that names the choice. Replaceollama_modelwithgraphify_backend: llamacpp-qwen35,graphify_model: qwen3.5-9b(the id graphify sends to the router), andllm_model: qwen3-5-9b(the llm-stack catalog name). RemoveGRAPHIFY_OLLAMA_NUM_CTX,GRAPHIFY_OLLAMA_KEEP_ALIVE, andOLLAMA_BASE_URL. SetGRAPHIFY_MAX_OUTPUT_TOKENS=10000,GRAPHIFY_MAX_RETRY_DEPTH=1,GRAPHIFY_MAX_RETRIES=0,GRAPHIFY_API_TIMEOUT=900,LLAMACPP_KEY=local. KeepGRAPHIFY_DISABLE_THINKING. check: presentllamacpp-qwen35inplugins/os-vault/config.yamlhooks/config.pyreads the three new keys and loses its fallback model copy. A missing key loads as an empty value;mainstarts no rebuild and logs the reason. check: absentqwen3.5:9binplugins/os-vault/hooks/config.pyllm-stack docs/research/llamacpp-router-spike.md. The unit runsllama serve --host 127.0.0.1 --port 8087 --models-preset <preset> --models-max 1 --sleep-idle-seconds 30. The hook does not start or stop the service. check: present--sleep-idle-secondsinplugins/os-vault/llama-router/llama-router.service/home/jared/.cache/huggingface/hub/models--unsloth--Qwen3.5-9B-GGUF/snapshots/3885219b6810b007914f3a7950a8d1b469d598a5/Qwen3.5-9B-UD-Q4_K_XL.gguf. check: presentqwen3.5-9binplugins/os-vault/llama-router/preset.iniplugins/os-vault/bin/vault-model-ready, a Ruby script, andplugins/os-vault/Gemfilewithgem 'llm-stack'by path in the same form asplugins/os-adr/Gemfile. It takes the catalog name, callsLLM.models.find(name, provider: "llamacpp"), exits 0 whenready?is true, and otherwise printsreasonand exits 1._REBUILD_SCRIPTcalls it asruby "$READY_SCRIPT" "$LLM_MODEL", so a test can place arubyshim on PATH. check: presentLLM.models.findinplugins/os-vault/bin/vault-model-readyplugins/os-vault/hooks/changed_notes.py, run with$GRAPHIFY_PYTHONasstub_markdown_pages.pyis. It callsgraphify.detect.detect_incremental(root, manifest_path=<root>/graphify-out/manifest.json, kind="semantic"). The default manifest path is relative to the working directory, so the script must pass the path. Exit 0 whennew_totalis above 0, exit 1 when it is 0, and any other exit on error. check: presentdetect_incrementalinplugins/os-vault/hooks/changed_notes.py_REBUILD_SCRIPTrunschanged_notes.pyfirst. With changes: runvault-model-ready; if it fails, the run fails. Then rungraphify extract "$VAULT_PATH" --backend "$BACKEND" --model "$MODEL" --token-budget 4000 --max-concurrency 1 --allow-partial, thengraphify cluster-onlywith the same--backendand--model. With no changes: skip readiness, extract, and cluster-only. In both cases run the stub step and the twographify update --forceruns. Extract stays incremental and never uses--force. check: present--allow-partialinplugins/os-vault/hooks/session_start.pystill hollowandstill truncatedto the failure check next tochunk N/M failed. check: presentstill truncatedinplugins/os-vault/hooks/session_start.pyllamacpp-qwen35indocs/implementation-status/os-vault.mdGRAPHIFY_OLLAMA_NUM_CTXinplugins/os-vault/README.mdollama_modelinplugins/os-vault/tests/harness.shollama_modelinplugins/os-vault/tests/generate-fixtures.shAcceptance criteria
--backend llamacpp-qwen35 --model qwen3.5-9b --allow-partial, and no argument names ollama.still holloworstill truncated, when the rebuild ends, then it writes no stamp and it writes the failed marker.graphify_model, when the hook runs, then it starts no rebuild and logs the reason.--forceto extract.After merge
The orchestrator does these by hand, because they sit outside the repo. They are not gates of this pipeline.
~/.config/systemd/user, enable it, and confirm that port 8087 answers.base_urlin~/.graphify/providers.jsonto port 8087, because 8089 was the eval logging proxy. Update~/Documents/SecondBrain/howto/running-qwen35-9b-gguf-behind-graphify-with-llama-cpp.mdto match.POST /models/unload.Owner sketch
_REBUILD_SCRIPTowns the run steps.config.yamlowns the choice.changed_notes.pyowns the question "did a note change", andvault-model-readyowns the question "can the model run". Both are thin scripts with no new domain object.plugins/os-vault/tests/test_session_start_rebuild.py is retired. The pipeline deleted it from the worktree at open, so the Retired tests section is gone: the reroute check refuses an entry whose file no longer exists. The new tests replace it.
Out of scope
onboard-projectskill still passes--backend ollama(SKILL.md:45-51,86).eval/graph-extraction/bin/run_extract.shstays on Ollama.Blocking edges
None. jared/llm-stack#22 and #23 are closed, and both are on main.
Origin
~/.cache/graphify/vault-rebuild.lockas a hold, which ends 2026-11-06 12:55.--backend ollamainplugins/os-vault/hooks/session_start.py← DESIGNVERDICT: CREATE
Date limit: the stamp was written 2026-11-05, so it passes 7 days on 2026-11-12. The hook then starts a rebuild on Ollama
qwen3.5:9bunless this ticket ships. The V4 full run also showed that extract needs--allow-partialwhenever it replaces older notes, or the shrink guard refuses the save.Blocked by jared/llm-stack#22. The 2026-11-12 date in the earlier comment is not a real limit: any vault note write deletes the stamp, and each run is incremental. Jared, 2026-11-06: no full rebuild until the setup is proven; incremental updates continue.
Ticket revised for jared/llm-stack#23. llm-stack run is dropped: the router runs as a systemd user service on port 8087, and the unit is not installed yet. Revised: item 3, item 4, criteria 2 and 4, blocking edges. Readiness: LLM.models.find("qwen3-5-9b", provider: "llamacpp").ready?. Note: a sleeping model keeps 122 MiB of VRAM until POST /models/unload. Router spike evidence: llm-stack docs/research/llamacpp-router-spike.md.
Resumed. jared/llm-stack#22 and #23 are closed and on main (b7af097, 4b3d459). The revised body matches the shipped interface: LLM.models.find with provider llamacpp, port 8087, no llm-stack run. Removed the waiting label.
Work started on branch ticket-1576.
Follow-up dropped by ticket-skeptic (depth-1 limit): reroute intake re-runs missing_retired_tests after Implementation::Open has already deleted the retired files (ticket_shape.rb:103, open.rb:58). Any reroute of a ticket with a Retired tests section is refused.
Resolution
Done: The os-vault rebuild hook now runs Unsloth Qwen3.5-9B V4 through llamacpp-qwen35 on changed notes only. No changed notes means no router request. vault-model-ready gates extract. changed_notes.py fails the run on any error or a missing manifest or graph, so it cannot start a full re-extraction. The failure scan covers hollow, truncated, and incomplete output. The router runs as llama-router.service on port 8087, and providers.json and the howto point at it.
Evidence: main
d02eb380(39eacd90,df4f36e7). pytest plugins/os-vault/tests: 35 passed. rubocop clean. Each required-work check verified by a script. One opus design audit: 9 of 10 findings fixed or answered by code, finding 10 answered with no change. Live run at 2026-11-06 15:22 through the real hook: 50 s, 3 re-extracted, 339 unchanged, 0 chunks failed, stamp written, no failed marker, /api/ps empty on Ollama. The model slept about 30 s after the last request: 146 MiB VRAM, service active. Hand-finished through the escalation procedure because the diff-test gate cannot run pytest. AC 2, the no-change branch, is proved by tests, not by a live run.Follow-ups: #1625 diff-test gate for pytest targets. #1626 onboard-project and reorganize skill text. Dropped by ticket-skeptic and noted: reroute retired-tests refusal (comment on #1576); harness.sh repair (comment on #1527).