kb: batch from 2026-07-30 parallel run (#181 #183 #189 #192 #164 #128 #219)

Work produced by the /kb driver on 2026-07-30. Each change is recorded on its
Kanboard task; all remain Done-unverified or parked pending alvis's decisions.

#183 agap-mcp/src/gitea.js
  askpassScript() and giteaWikiWrite()'s wiki checkout both used
  /tmp/agap-mcp-wiki, so writing the askpass helper made the dir non-empty and
  git clone always failed. gitea_wiki_write had likely never succeeded in
  production. Askpass moved to its own dir.

#181 agap-mcp/src/server.js
  Initialise registeredToolCount at module load so /health reports the real
  count immediately instead of 0 until the first MCP request.

#189 kanboard/backup.sh, seafile/backup.sh, vaultwarden/backup.sh,
     users-backup.sh, openai/backup-{hindsight-adolf,llm-dbs}.sh
  Remove the dead *.ts Zabbix trapper pushes (never landed). users-backup.sh
  also pointed at localhost:81 instead of 192.168.1.4:81 and pushed a date
  string into a numeric item. Freshness monitoring now rides the .age items.

#192 RESTORE-RUNBOOK.md, {kanboard,seafile,vaultwarden}/restore.sh
  Restore path for the three services, verified in throwaway containers.
  Note: this work found Seafile backups have carried an empty ccnet_db.sql
  since 2026-07-07 -- filed as kb#222, not fixed here.

#164 openai/litellm-config.yaml
  Metered `judge` (anthropic/claude-haiku-4-5) entry removed per alvis's
  2026-07-30 decision. ANTHROPIC_API_KEY was never wired, so it could not spend.

#128 openai/agent_registry.py
  litellm_key_spec() now also grants the routing-mode aliases, gated by the
  same _reachable_tiers() check as raw grants, so a small-tier agent cannot
  acquire automatic routing that resolves to tier-large.

#219 openai/migrate-adolf-state.sh
  Migration script only; inert until run. Copies (never moves) the
  openai_adolf-state volume to /mnt/ssd/dbs/adolf, verifying a full sha256
  manifest before declaring success. Tested against a throwaway volume.

Deliberately NOT included, both awaiting alvis:
  agap-mcp/docker-compose.yml -- kb#174's contested BW_EMAIL revert (parked).
  openai/docker-compose.yml   -- kb#219's bind-mount switch; the target dirs
                                 under /mnt/ssd/dbs/adolf do not exist yet, so
                                 committing it would let a later `compose up`
                                 recreate Adolf against empty paths.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Y5QPagv4iun1ghpwM96Ff
This commit is contained in:
2026-07-30 15:06:09 +00:00
parent 4a9ae75912
commit a27bae828a
15 changed files with 666 additions and 110 deletions

View File

@@ -210,6 +210,33 @@ def litellm_key_spec(registry, agent_id, model_registry=None):
if name not in models:
models.append(name)
# kb#128 gap (flagged 2026-07-26, closed 2026-07-30): the raw litellm_
# model_names above (e.g. "ollama/gemma3:4b") are the BACKING deployments
# for openai/litellm-config.yaml's alias model_names -- tier-small/
# tier-large (alvis's "tier" routing mode) and auto_router/
# complexity_router (alvis's "automatic" routing mode). Without granting
# the aliases too, a provisioned key could reach a model directly but not
# by tier or through the router, so "all three routing modes exercisable"
# (kb#128 acceptance) wasn't actually true per-agent. Gate exactly like
# the raw grants above -- reachable tiers, not a separate allow-list --
# so an agent's routing-mode access never exceeds its direct-model access:
# - "small" reachable -> tier-small (mirrors the always-granted small
# pool; every agent with a backbone gets at least this).
# - "large" reachable -> tier-large, PLUS auto_router/complexity_router.
# Both routers' pools include tier-large in their upper bands (COMPLEX/
# REASONING, or the semantic "complex reasoning" route), so granting
# them to a small-only (sandboxed) agent would let automatic routing
# escalate it past its trust class -- exactly the asymmetry
# _reachable_tiers()/kb#147 exists to prevent. A small-only agent gets
# neither router: it can still call tier-small directly.
reachable = _reachable_tiers(a.get("preferred_tier"))
if "small" in reachable and "tier-small" not in models:
models.append("tier-small")
if "large" in reachable:
for alias in ("tier-large", "auto_router", "complexity_router"):
if alias not in models:
models.append(alias)
classes = registry.get("trust_classes", {})
cls = classes.get(a["trust_class"], {})
return {