e7ecce2859
Three tangled defects, fixed together because each one hid the others. DefaultActMatcher matched an exact English prefix and internal/tool.Matcher delegated straight to it, so no Russian utterance could reach a tool: 55 of the 69 lines in models/seeds/act.txt routed to IntentAct and fell to proposeGap. Tools now carry spoken aliases from deploy/mavend.json, matched as exact leading tokens, longest phrase first. Config data, not a stem pattern in code. The comment claiming "the production matcher is fuzzy" was false and is gone. Seven lines were exact duplicates inside models/seeds/query.txt, each one a second identical vector double-weighting its region. "как дела у сервера" carried both a query and a system label. It leaves system.txt, because replySystem's stats arm answers "системная статистика пока не подключена." and always did. The mode inventory records that shape as act.tool.hoststats rather than a system mode. Fixture unchanged at 69/91, and it cannot see any of this: no host-stat case and no Russian act in it. TestActMatcherAliases is the coverage. docs/evals/2026-08-06-russian-acts-reach-tools.md has the numbers. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0117tgnmbgZpHVV3XSNw8Qua
242 lines
10 KiB
JSON
242 lines
10 KiB
JSON
{
|
|
"db_path": "/var/lib/maven/maven.db.enc",
|
|
"db_tmpfs": "/dev/shm/maven-plain.db",
|
|
"db_key_env": "MAVEN_DB_KEY",
|
|
"socket_path": "/run/maven/mavend.sock",
|
|
"state_dir": "/var/lib/maven",
|
|
|
|
"//disabled_rules": [
|
|
"Nudge rules that are not wired at all. Names come from loop.DefaultRules:",
|
|
"water, meal, break, service_down, netdata_critical.",
|
|
"service_down is back on: mavpoll now writes one fact per kuma monitor",
|
|
"(service_down:<name>), so the nudge names the service and pausing a monitor",
|
|
"in kuma silences that monitor. It is also edge-triggered, so a service that",
|
|
"stays down is one nudge, not one every fifteen minutes."
|
|
],
|
|
"disabled_rules": [],
|
|
|
|
"phraser": {
|
|
"model_path": "/opt/maven/models/llm/qwen3/Qwen3-1.7B-UD-Q4_K_XL.gguf",
|
|
"bin_path": "llama-server",
|
|
"n_gpu_layers": 99,
|
|
"n_ctx": 4096,
|
|
"cache_ram_mib": 512,
|
|
"timeout": "60s",
|
|
"llm_nudges": false
|
|
},
|
|
|
|
"telegram": {
|
|
"bot_token": "${TELEGRAM_BOT_TOKEN}",
|
|
"chat_id": "${TELEGRAM_CHAT_ID}",
|
|
|
|
"//proxy": [
|
|
"api.telegram.org is not reachable directly from this box, so every send",
|
|
"timed out. The relay is the x-ui socks inbound on the host, port 10808;",
|
|
"192.168.240.1 is the maven_default bridge gateway, which is how a",
|
|
"container addresses the host. mavend is on that network.",
|
|
"This needs a matching ufw rule or the container's SYN is dropped:",
|
|
" ufw allow from 192.168.240.0/20 to any port 10808 proto tcp"
|
|
],
|
|
"proxy": "socks5://192.168.240.1:10808"
|
|
},
|
|
|
|
"//workstation": [
|
|
"The big model on the desk PC (workpc, 7900 GRE 16GB), fronted by",
|
|
"mavgpud on port 8080. It runs gemma-4-12b and it is preferred over the",
|
|
"resident Qwen3-1.7B for routing and replies whenever the card is free.",
|
|
"The machine is never assumed up: it sleeps, and the card is often held by",
|
|
"a CPT run, in which case mavgpud answers 503 and Maven falls back to the",
|
|
"resident model without saying so. Deleting this block restores exactly",
|
|
"the behaviour homesrv had before it existed.",
|
|
"Addressed by LAN address, not container name: mavgpud runs on another",
|
|
"machine and there is no shared docker network to name it on."
|
|
],
|
|
"workstation": {
|
|
"url": "http://192.168.1.105:8080",
|
|
"probe": "15s",
|
|
"timeout": "90s"
|
|
},
|
|
|
|
"//search": [
|
|
"The live web, searched after his own notes and before Kiwix. Only the",
|
|
"query string leaves the box — never a note, a fact, the persona block or",
|
|
"the history — and a question about him never reaches here at all.",
|
|
"The instance must have `json` in search.formats (settings.yml); a stock",
|
|
"SearXNG answers 403 to format=json and every search then fails. It is",
|
|
"addressed by container name, so it needs the same maven_default",
|
|
"attachment kiwix has, and it must listen on 9563: 8080 is taken several",
|
|
"times over on this box. No instance reachable ⇒ she falls through to the",
|
|
"ZIMs and never says the search failed."
|
|
],
|
|
"search": {
|
|
"url": "http://searxng:9563",
|
|
"max_results": 4,
|
|
"snippet_runes": 1500,
|
|
"language": "auto",
|
|
"timeout": "8s"
|
|
},
|
|
|
|
"//kiwix": [
|
|
"The offline encyclopedia, searched after his own notes and before anything",
|
|
"on the network. kiwix-server publishes 8034 on loopback only, so a container",
|
|
"cannot reach it by address; it is attached to the maven_default network",
|
|
"instead and addressed by container name. That attachment is imperative and",
|
|
"does not survive recreating the kiwix stack — make it declarative there:",
|
|
" networks: [default, maven_default] # maven_default: external: true",
|
|
"The book is the catalog name from the /content/... href in",
|
|
"/catalog/v2/entries, not the display title. Others on the box:",
|
|
"ifixit_en_all_2025-06, devdocs_en_ansible_2025-10."
|
|
],
|
|
"kiwix": {
|
|
"url": "http://kiwix-server:8080",
|
|
"book": "wikipedia_en_all_maxi_2026-02",
|
|
"book_ru": "wikipedia_ru_all_maxi_2026-02",
|
|
"max_results": 5,
|
|
"snippet_runes": 1500
|
|
},
|
|
|
|
"//morning_routines": [
|
|
"The daily checklist (Vikunja #280). Each item is done when its fact_key",
|
|
"gets a non-voided fact inside the window, so 'выпил воды' closes water and",
|
|
"nothing has to be ticked by hand. nudge_at fires once, at the end of the",
|
|
"window, and only for what is still open. Weekdays empty = every day."
|
|
],
|
|
"morning_routines": [
|
|
{
|
|
"name": "утро",
|
|
"window_start": "08:00",
|
|
"window_end": "11:00",
|
|
"nudge_at": "10:30",
|
|
"severity": 1,
|
|
"items": [
|
|
{ "key": "medicine", "fact_key": "medicine", "label": "лекарство" },
|
|
{ "key": "water", "fact_key": "water", "label": "вода" },
|
|
{ "key": "pets", "fact_key": "pets", "label": "покормить кота" }
|
|
]
|
|
}
|
|
],
|
|
|
|
"//feeds": [
|
|
"RSS reading (Vikunja #258). Every item lands as a note with source",
|
|
"rss:<name>, which is also what puts entries in the intake journal that",
|
|
"/events reads. Only the feed URL leaves the box.",
|
|
"This is a starting pair, not a curated set — trim or extend it."
|
|
],
|
|
"feeds": {
|
|
"poll_interval": "30m",
|
|
"max_items": 5,
|
|
"max_age": "24h",
|
|
"sources": [
|
|
{ "name": "lwn", "url": "https://lwn.net/headlines/newrss", "category": "технологии" },
|
|
{ "name": "archlinux", "url": "https://archlinux.org/feeds/news/", "category": "технологии" }
|
|
]
|
|
},
|
|
|
|
"//crawl": [
|
|
"Reading a web page (Vikunja #259). on_demand answers 'посмотри <URL>'.",
|
|
"No allow_hosts, so any public host he names is readable; private",
|
|
"addresses are refused unconditionally by internal/webfetch and do not",
|
|
"need listing. Setting allow_hosts here would also narrow on-demand,",
|
|
"which is the point of leaving it empty."
|
|
],
|
|
"crawl": {
|
|
"on_demand": true,
|
|
"timeout": "10s",
|
|
"max_runes": 4000
|
|
},
|
|
|
|
"digest": {
|
|
"enabled": true,
|
|
"window": "30m",
|
|
"max_items": 5,
|
|
"severity_ceiling": 2
|
|
},
|
|
|
|
"pattern_proposals": {
|
|
"notify": false,
|
|
"cooldown": "24h"
|
|
},
|
|
|
|
"mcp": {
|
|
"timeout": "15s",
|
|
"servers": [
|
|
{
|
|
"name": "vikunja",
|
|
"url": "http://192.168.1.104:9100/mcp",
|
|
"allow_private": true,
|
|
"allow_tools": ["list_projects", "list_tasks", "get_task_details", "create_task"],
|
|
"max_tools": 6,
|
|
"enabled": false
|
|
}
|
|
]
|
|
},
|
|
|
|
"smarthome": {
|
|
"provider": "homeassistant",
|
|
"url": "http://192.168.1.50:8123",
|
|
"token": "${HA_TOKEN}",
|
|
"domains": ["light", "switch", "sensor"],
|
|
"max_entities": 40,
|
|
"timeout": "10s",
|
|
"refresh": "15m",
|
|
"enabled": false
|
|
},
|
|
|
|
"netscan": {
|
|
"subnets": ["192.168.1.0/24"],
|
|
"ports": [22, 80, 443, 8080],
|
|
"timeout": "400ms",
|
|
"rate": 100,
|
|
"max_hosts": 256,
|
|
"enabled": true
|
|
},
|
|
|
|
"nexus": { "url": "http://nexus:9740" },
|
|
"praxis": { "url": "http://praxis:8989" },
|
|
"hexis": { "url": "http://hexis:9741" },
|
|
|
|
"voice": {
|
|
"enabled": true,
|
|
"bind": "0.0.0.0:9100",
|
|
"lang": "ru",
|
|
"stt": { "socket": "/run/maven/stt.sock", "lang": "ru" },
|
|
"tts": { "socket": "/run/maven/tts.sock", "lang": "ru" },
|
|
"embedder": {
|
|
"model_path": "/opt/maven/models/embedder/multilingual-e5-small/model_quantized.onnx",
|
|
"tokenizer_path": "/opt/maven/models/embedder/multilingual-e5-small/tokenizer.json",
|
|
"lib_path": "/opt/maven/lib/libonnxruntime.so"
|
|
},
|
|
"llm_router": true,
|
|
"query_min_score": 0.55,
|
|
"query_min_margin": 0.008,
|
|
"clarify_max_attempts": 3,
|
|
"tool_timeout": "30s",
|
|
"tools": [
|
|
{ "name": "status", "cmd": ["systemctl", "status"], "scope": "homelab", "destructive": false,
|
|
"aliases": ["статус", "покажи статус", "проверь статус"] },
|
|
{ "name": "ps", "cmd": ["docker", "ps"], "scope": "homelab", "destructive": false,
|
|
"aliases": ["статус докера", "лог докера", "покажи запущенные контейнеры", "покажи контейнеры", "список контейнеров", "что запущено"] },
|
|
{ "name": "uptime", "cmd": ["uptime"], "scope": "homelab", "destructive": false,
|
|
"aliases": ["покажи uptime", "аптайм", "как работает сервер", "сколько работает сервер"] },
|
|
{ "name": "disk", "cmd": ["df", "-h"], "scope": "homelab", "destructive": false,
|
|
"aliases": ["сколько места на диске", "сколько свободного места на диске", "место на диске", "покажи диск"] },
|
|
{ "name": "memory", "cmd": ["free", "-h"], "scope": "homelab", "destructive": false,
|
|
"aliases": ["свободная память", "сколько оперативной памяти свободно", "покажи память"] },
|
|
{ "name": "logs", "cmd": ["journalctl", "-n", "50", "-u"], "scope": "homelab", "destructive": false,
|
|
"aliases": ["покажи логи", "логи", "лог"] },
|
|
{ "name": "restart", "cmd": ["systemctl", "restart"], "scope": "homelab", "destructive": true,
|
|
"aliases": ["перезапусти", "перезагрузи", "рестарт"] },
|
|
{ "name": "stop", "cmd": ["systemctl", "stop"], "scope": "homelab", "destructive": true,
|
|
"aliases": ["останови", "останови сервис"] },
|
|
{ "name": "start", "cmd": ["systemctl", "start"], "scope": "homelab", "destructive": true,
|
|
"aliases": ["запусти", "запусти сервис"] },
|
|
{ "name": "docker-restart", "cmd": ["docker", "restart"], "scope": "homelab", "destructive": true,
|
|
"aliases": ["перезапусти контейнер", "перезагрузи контейнер"] },
|
|
{ "name": "docker-stop", "cmd": ["docker", "stop"], "scope": "homelab", "destructive": true,
|
|
"aliases": ["останови контейнер"] },
|
|
{ "name": "reboot", "cmd": ["systemctl", "reboot"], "scope": "homelab", "destructive": true,
|
|
"aliases": ["перезагрузи сервер", "перезагрузи хост"] }
|
|
]
|
|
}
|
|
}
|