Files
Maven/deploy/mavend.json
claude bec7362b7b config: clear three of 472's five QA blockers (V-459)
morning_routines, feeds, crawl.on_demand and netscan.enabled in
deploy/mavend.json; -ambient-token on mavweb, interpolated from a gitignored
/.env. All verified on the box: the dispatcher builds the morning plan,
/api/ambient answers 401/201, the crawler reads a named page, netscan finds 3
devices, and /events fills with scan:lan and ambient:notif.

Filed 482 (ambient reads a notification's wall clock as UTC). Corrected 479:
both capabilities work once configured, so it is not a routing defect.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NJYcaBiuny9UGSpFweQVQ1
2026-08-02 15:52:56 +04:00

211 lines
8.0 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 off because it cannot say WHICH service — mavpoll folds the",
"whole kuma gauge into one boolean, so the nudge is always the generic 'a",
"service on homesrv is down'. Nothing to act on, every fifteen minutes.",
"Turn it back on once Vikunja #444 lands a fact per monitor."
],
"disabled_rules": ["service_down"],
"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,
"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"
},
"//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",
"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 },
{ "name": "ps", "cmd": ["docker", "ps"], "scope": "homelab", "destructive": false },
{ "name": "uptime", "cmd": ["uptime"], "scope": "homelab", "destructive": false },
{ "name": "disk", "cmd": ["df", "-h"], "scope": "homelab", "destructive": false },
{ "name": "memory", "cmd": ["free", "-h"], "scope": "homelab", "destructive": false },
{ "name": "logs", "cmd": ["journalctl", "-n", "50", "-u"], "scope": "homelab", "destructive": false },
{ "name": "restart", "cmd": ["systemctl", "restart"], "scope": "homelab", "destructive": true },
{ "name": "stop", "cmd": ["systemctl", "stop"], "scope": "homelab", "destructive": true },
{ "name": "start", "cmd": ["systemctl", "start"], "scope": "homelab", "destructive": true },
{ "name": "docker-restart", "cmd": ["docker", "restart"], "scope": "homelab", "destructive": true },
{ "name": "docker-stop", "cmd": ["docker", "stop"], "scope": "homelab", "destructive": true },
{ "name": "reboot", "cmd": ["systemctl", "reboot"], "scope": "homelab", "destructive": true }
]
}
}