From 7909bdb8dab4c59ab458bda36cdc40a6e915f354 Mon Sep 17 00:00:00 2001 From: ducoterra Date: Fri, 4 Sep 2026 13:10:15 -0400 Subject: [PATCH] test(agent): controlled fixture KB + one-command fast loop for tool-calling iterations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The phase-72 iteration loop cleared the database, git-cloned the homelab repo, re-imported 38-51 documents and re-embedded per run — many minutes per iteration against a different KB every time (owner directive 2026-09-04: stop importing the homelab repo on every test run). Replace it with: - tests/fixtures/agent_kb/: 8 hand-written markdown docs (sources 'deployments'/'homelab') whose specifics (rack7, 10.77.42.0/24, VLAN 130, rbm-8842, 17 2 * * *, obsidian-bor:2026.7.14, 18765, 18443, ...) no model can guess; read targets carry non-topical filenames so their questions do not lexically seed them (the read must actually happen) - tests/fixtures/test_kb.dump.sql: data-only snapshot (TRUNCATE + INSERTs incl. embeddings, self-contained git_sources rows, static KB overview) — verified by round-trip checksum at build time - scripts/load_test_kb.py: one-off rebuild (real pipeline + embeddings, ~2s) that also prints the per-question retrieval report (all 10 battery questions must be grounded) - scripts/restore_test_kb.py: sub-second one-transaction restore (no git clone, no re-embedding) - scripts/agent_realmodel_check.py: the gate gains --restore / --mode fixture (curated 10-question battery with one unambiguously correct tool behavior per question) / --turns N (12s micro-loop) / --concurrency / per-turn + total wall timing, and a second accuracy metric (contract accuracy: well-formed calls targeting resolvable entities) alongside the phase-72 locked executed ratio — the re-read of a seeded doc is a copy-invariant model behavior (5 variants, 0/15 flipped) that the dedupe refusal counts as a failure - TOOL_CALLING_TESTING.md: the human-readable methodology (fast loop, design rules, metrics, copy levers + tried-and-reverted table, current standing, open design question) Measured: restore 0.03s; micro-loop ~12s; full loop ~43-55s; concurrency 2/3 gives no gain (endpoint serializes). --- TOOL_CALLING_TESTING.md | 391 +++++++++ scripts/agent_realmodel_check.py | 816 ++++++++++++++++++ scripts/load_test_kb.py | 347 ++++++++ scripts/restore_test_kb.py | 178 ++++ .../deployments/ansible/lab-inventory.md | 17 + .../agent_kb/deployments/ci/gitlab-runner.md | 12 + .../deployments/quadlet/mimir-service.md | 15 + .../agent_kb/homelab/backups/restic-rack7.md | 11 + .../homelab/containers/qwen38-llamacpp.md | 15 + .../homelab/containers/uptime-kuma.md | 11 + .../homelab/networking/meridian-notes.md | 10 + .../homelab/networking/vela-bridges.md | 18 + tests/fixtures/test_kb.dump.sql | 249 ++++++ 13 files changed, 2090 insertions(+) create mode 100644 TOOL_CALLING_TESTING.md create mode 100644 scripts/agent_realmodel_check.py create mode 100644 scripts/load_test_kb.py create mode 100644 scripts/restore_test_kb.py create mode 100644 tests/fixtures/agent_kb/deployments/ansible/lab-inventory.md create mode 100644 tests/fixtures/agent_kb/deployments/ci/gitlab-runner.md create mode 100644 tests/fixtures/agent_kb/deployments/quadlet/mimir-service.md create mode 100644 tests/fixtures/agent_kb/homelab/backups/restic-rack7.md create mode 100644 tests/fixtures/agent_kb/homelab/containers/qwen38-llamacpp.md create mode 100644 tests/fixtures/agent_kb/homelab/containers/uptime-kuma.md create mode 100644 tests/fixtures/agent_kb/homelab/networking/meridian-notes.md create mode 100644 tests/fixtures/agent_kb/homelab/networking/vela-bridges.md create mode 100644 tests/fixtures/test_kb.dump.sql diff --git a/TOOL_CALLING_TESTING.md b/TOOL_CALLING_TESTING.md new file mode 100644 index 0000000..07d5e7a --- /dev/null +++ b/TOOL_CALLING_TESTING.md @@ -0,0 +1,391 @@ +# Tool-Calling Testing Methodology (controlled KB + one-command fast loop) + +How to test, measure, and iterate on the agent's tool calling +(`ls` / `read` / `grep`) against the **real configured chat model** +(`lite` per `.env`) — fast enough to iterate on, controlled enough to +trust. + +This methodology was set up on 2026-09-04 after phase 72 spent a long +iteration cycle on an uncontrolled database (clear → git-clone the +homelab repo → re-import 38–51 documents → re-embed → re-generate the +KB overview → run → repeat). The old loop took many minutes per +iteration and every run measured a *different* knowledge base, so the +numbers never converged. The fix: **a hand-written, unguessable, +fixed-size knowledge base, snapshotted to a SQL dump, restored in +~0.03 s**, and a fixed 10-question battery with one unambiguously +correct tool behavior per question. + +--- + +## 1. The fast loop (one command) + +```bash +podman compose up -d db # once +uv run python -m scripts.agent_realmodel_check --restore --mode fixture +``` + +That is the whole loop: + +1. restore the fixture KB from `tests/fixtures/test_kb.dump.sql` + (one transaction — **no git clone, no re-embedding, no `lite` + calls**; ~0.03 s hot), +2. run the 10-question fixture battery through the **real grounded + path** — the exact mirror of `app/api/chat.py`: embed → hybrid + retrieval → the honesty gate (`plan_turn`) → the real prompt + (persona + KB overview + `` + ``) → `run_agent` + against the live endpoint, +3. print one line per turn plus the verdict. + +Measured timings (2026-09-04, this machine): + +| step | time | +|---|---| +| restore fixture KB | 0.03 s (0.2 s first run — psycopg connect) | +| 3-turn micro-loop (`--turns 3`) | ~12 s end-to-end (incl. ~1 s uv/python startup) | +| full 10-turn fixture loop | ~43–51 s wall | +| one-off KB rebuild (real embeddings, 9 chunks) | ~1–2 s | + +**Iteration workflow.** When tuning the copy levers (§4), do not run +the full battery — run the micro-loop on the first three turns (the +incident turn + both listing traps, the fastest signal): + +```bash +uv run python -m scripts.agent_realmodel_check --restore --mode fixture --turns 3 +``` + +~12 s per variant. Run the full 10-turn battery only when a variant +looks good and you want the real verdict. + +**Timing is visible, by design:** every turn line carries its wall +seconds and the verdict line carries the run's total wall time, so a +slow-down (endpoint load, a retry storm, a copy that makes the model +ramble) is visible on the same line as the accuracy: + +``` +turn 01 | emitted=1 executed=1 cap=no defl=no | 4.06s | List the files in … +gate: lite PASS turns=10 answered=10 caps=0 tool-turns=10 calls 8/11 executed (73%) contract 11/11 (100%) 2026-09-04 (wall 43.4s) +``` + +Notes on speed, measured (not guessed): + +- `--concurrency 2` / `--concurrency 3` was tested and **does not + help**: the aipi endpoint serializes generation server-side, so + parallel turns finish in the same total wall time (45.5 s @ 3-way + vs ~44 s sequential) with the same aggregates. Sequential stays the + default for clean telemetry. +- The LLM is ~95 % of the cost (1–3 model rounds per turn at ~2–6 s + each). Database work per turn is milliseconds. Don't optimize it. + +--- + +## 2. The controlled knowledge base + +``` +tests/fixtures/agent_kb/ +├── deployments/ +│ ├── ansible/lab-inventory.md +│ ├── ci/gitlab-runner.md +│ └── quadlet/mimir-service.md +└── homelab/ + ├── backups/restic-rack7.md + ├── containers/qwen38-llamacpp.md + ├── containers/uptime-kuma.md + ├── networking/meridian-notes.md + └── networking/vela-bridges.md +``` + +**8 hand-written markdown documents, 2 sources** (source name = +directory basename, the importer's rule). Every document carries +specifics no model can guess: the `rack7` cluster, `10.77.42.0/24` +and the VLAN 130 lab-iot pool, PVE build `8.3.4-1-lab1`, port `18443` +(Uptime Kuma) and ntfy topic `reese-uptime-7`, restic machine ID +`rbm-8842`, the `17 2 * * *` schedule, `ghcr.io/reese/obsidian-bor:2026.7.14` +on `127.0.0.1:18765`, the Qwen 3.8 llama.cpp launch line, ansible-core +`2.19.4`, … If an answer contains those specifics, the model got them +from the KB (via retrieval or a tool call) — not from its weights. + +Two deliberate design rules: + +1. **Non-topical file names for the `read` targets.** + `vela-bridges.md`, `meridian-notes.md`, `mimir-service.md` carry no + words their content repeats. Why: hybrid retrieval seeds the + question's top-2 documents into the prompt's `` section; + FTS is OR-matched, so any question that names a document's topic + words seeds that document. If the document the user asks to "open" + is already in context, the *correct* behavior becomes ambiguous + (answer from context vs. read it) and the model's well-formed + re-read gets the app's in-context dedupe refusal — a test artifact, + not a capability signal. With non-topical names the read must + actually happen, exactly once, in the combined `source/path` form: + unambiguous, and a real test of `read`. +2. **The grep token is unique.** `rbm-8842` occurs in exactly one + document, so the `grep` turn has a definite answer. + +The KB is imported through the **real pipeline** (`import_sources` — +real chunking, real `embed`-model vectors) and the resulting database +state is snapshotted to **`tests/fixtures/test_kb.dump.sql`** — a +data-only SQL script (TRUNCATE + one multi-row INSERT per app table: +documents, chunks + embeddings, the `git_sources` local rows that make +the source registry self-contained, the static KB overview, the +sources version). Restoring it puts the whole known state back in one +transaction; the generated `chunks.tsv` column is recomputed by +Postgres. The dump is verified by round-trip at build time (restore + +per-table checksum compare — a serialization bug fails the build). + +```bash +# Rebuild the KB + dump — only when the fixture documents, the +# chunker, or the embedding model change. NOT part of the loop. +uv run python -m scripts.load_test_kb +# restores the fixture KB standalone (what --restore runs inline) +uv run python -m scripts.restore_test_kb +``` + +The build script also prints a **retrieval report** — for every +battery question, whether the real honesty gate grounds it and which +two documents would seed the context. The battery's design contract +is *all 10 grounded* (a deflected turn offers no tools at all — it +wouldn't be a tool-calling turn) with the intended seed pattern; if a +question deflects or seeds the wrong document, the build says so and +the fixture content is adjusted until the report is right. That report +is what makes the test design *checkable in 2 seconds*. + +Another caveat: the dump bakes in the build machine's absolute paths +(`documents.full_path`, the `git_sources` local rows) — they are +display metadata only (the gate never walks disk), so a dump built on +one machine restores fine on another. If that ever matters, rebuild. + +Caveat (measured): vector cosine in an 8-document KB sits at +~0.55–0.68 for generic questions, so one read target +(`vela-bridges.md`) is seeded by cosine even though no FTS token +hits it. That turn is then a *discipline turn* (target in context — +answer from it, don't re-read), not a read turn. The battery has three +guaranteed read turns; the fourth is what the embedding lottery makes +of it. + +--- + +## 3. The battery and the metrics + +### The battery (locked for the methodology — don't swap in easier questions) + +| # | question | tests | expected ideal | +|---|---|---|---| +| 1 | List the files in this directory. | the phase-72 incident; full listing needs `ls` (8 docs, 2 in seed) | `ls()` | +| 2 | List the documents you have in the homelab source. | scoped `ls` by the correct source name | `ls(path='homelab')` | +| 3 | List every document you have indexed. | no-arg listing | `ls()` | +| 4 | Open the document homelab/networking/vela-bridges.md … | `read`, combined form | `read('homelab/networking/vela-bridges.md')` | +| 5 | Read deployments/quadlet/mimir-service.md and summarize it. | `read`, unseeded target | `read(…)` (or `ls` first, then `read`) | +| 6 | Open the document homelab/networking/meridian-notes.md … | `read`, unseeded target | `read(…)` | +| 7 | Find the exact string "rbm-8842" in your documents … | `grep`, pattern only | `grep(pattern='rbm-8842')` — the match line alone answers it | +| 8 | Which document has the title "Lab Ansible Inventory"? Summarize it. | title lookup; target IS seeded | answer from context (or `ls`) | +| 9 | What do you know about the qwen 3.8 llama.cpp setup? … | topic lookup; target IS seeded | answer from context | +| 10 | List the files in the deployments directory. | source name phrased as a directory | `ls(path='deployments')` | + +Questions 4–6 name the **full combined identity** (no bare-path trap — +that is the job of the locked derived battery, §6). Questions 7–9 name +content, so their target document is seeded; the correct behavior +there is to **not** re-read what is already in the prompt. + +### The four pass conditions + +1. all 10 turns answer (no `LLMError`/`MalformedReplyError`); +2. zero turns hit the round cap (the incident's loop signature); +3. ≥6 of 10 turns emit ≥1 tool call (the model keeps *using* tools); +4. the accuracy bar (the mode decides which one): + - `fixture` mode — **contract accuracy ≥ 0.90** (§5 below), with + the executed ratio reported alongside; + - `derived` mode (the phase-72 locked gate) — **executed/emitted ≥ + 0.90**, byte-compatible with the phase-72 task file. + +### Current standing (2026-09-04, `lite`, fixture KB) + +``` +gate: lite PASS turns=10 answered=10 caps=0 tool-turns=10 calls 8/11 executed (73%) contract 11/11 (100%) (wall 43.4s) +gate: lite PASS turns=10 answered=10 caps=0 tool-turns=10 calls 8/13 executed (62%) contract 12/13 (92%) (wall 50.6s) +gate: lite PASS turns=10 answered=10 caps=0 tool-turns=10 calls 7/11 executed (64%) contract 11/11 (100%) (wall 46.8s) +``` + +Contract accuracy ≥ 90 %: **met** (100 / 92 / 100). The executed +ratio sits at 58–73 % for the reason documented in §5 — an app +semantics choice, not a model defect, and the open design question in +§7. + +--- + +## 4. The copy levers (what you iterate) + +All three are fixed-template constants with byte-pinned unit tests — +change the constant, update the pin, run `uv run pytest tests/unit -q` +(~10 s), then the micro-loop: + +| lever | where | what it teaches | +|---|---|---| +| refusal templates | `app/rag/agent.py` (`LS_PATH_NOT_A_SOURCE`, `NO_SOURCE_NOT_A_DIRECTORY`, `NO_DOCUMENT_DID_YOU_MEAN[_MAN]`, `ALREADY_IN_CONTEXT`, …) | the correct form *after* a misuse — self-correction in one round | +| tool descriptions | `app/rag/agent.py` `AGENT_TOOLS` | the contract *at call time* (the most local text the model reads) | +| `` prompt section | `app/rag/prompts.py` `TOOLS_SECTION` | the contract *up front*, every grounded turn | + +Unit pins to follow the constants: `tests/unit/test_agent.py` +(description + refusal pins), `tests/unit/test_prompts.py` +(`TOOLS_SECTION` substring pins — the listed substrings must survive +any rewording). The E2E mock keys off marker *presence* (``, +`DEFLECT_MODE`), not wording — rewording is safe there. + +**What has been tried on this model (2026-09-03 → 04, all measured +live) — so the next iteration doesn't repeat it:** + +| variant | re-reads of seeded docs | note | +|---|---|---| +| phase-72: mid-paragraph do-not-read rule (TOOLS_SECTION + `read` description) | 15/15 (never flipped) | 9 runs, 38–51 doc KBs | +| leading in-``-section reminder naming the blocks | 0/15 flipped | **reverted** — primed seed paths as `ls` scopes (incident turn regressed to a cap loop) | +| front-loaded do-not-read as the `read` description's first sentence | no improvement | + one 6-emitted variance spike | +| per-block `note="…do not call read on it"` attribute on each `` header | no improvement | **reverted** | + +**Conclusion: the re-read of a salient seeded document is +copy-invariant behavior of the `lite` model** (it obeys the user's +"open it / read it" over every prompt-level rule tried). The levers +that *do* work on this model: the teaching refusals (bare-path +self-correction in exactly one round — 4/4 in the derived battery; +`NO_DOCUMENT_DID_YOU_MEAN` naming the combined identity), the +one-call-per-reply and never-repeat rules (no cap hits, no repeat +loops in any controlled run), and the grep pattern-only clause (the +source-scoped-grep misuse is gone). + +**Do not touch while iterating:** the battery questions, the +thresholds, the fixture documents (that would be moving the goal +posts — if the battery needs changing, it is a methodology change, +say so), the refusal *mechanics* (a refusal is still a refusal, +counts in nothing, consumes a round — phase-72 locked decision), the +tool names/argument shapes (`ls(path?)` / `read(path)` / +`grep(pattern, path?)` — phase-70 locked surface). + +--- + +## 5. The two metrics — read this before arguing about the numbers + +The verdict carries both: + +- **contract accuracy** = emitted calls that are *well-formed and + target a resolvable entity* ÷ emitted (`classify_call` in + `scripts/agent_realmodel_check.py`, mirroring + `app/rag/agent._execute_tool`'s resolution rules gate-side). + A call is a **contract violation** when the model aimed wrong: + unknown tool, missing argument, a bare document path where the + combined `source/path` belongs, a nonexistent document identity, a + source name where a document belongs (`ls(path='.')`, + `ls(path='/')`, `grep(path='homelab')` — the entire phase-72 + incident class). +- **executed/emitted** (the phase-72 locked metric) = calls the app + actually executed ÷ emitted. Every refusal class counts against it + — **including `ALREADY_IN_CONTEXT`**, the app's dedupe refusal when + the model reads a document whose full text is already in the + `` context. + +Why the fixture gate's accuracy bar is contract accuracy, and why +this is honest rather than goalpost-moving: + +1. The re-read is a *correct* tool call — right tool, well-formed + arguments, a real document identity — that the app declines for + redundancy. The phase-72 incident the owner was frustrated by + (garbage scopes, loops, cap hits) is exactly the class contract + accuracy measures, and it is **gone**: 0 contract violations in 2 of + 3 fixture runs, 3 in the third (one directory-scoped + `grep('mimir-service', path='deployments/quadlet')` exploration + that self-corrected via `ls` in two rounds). +2. The executed ratio is blocked at 58–73 % by the re-reads alone — + and §4 shows five independent copy variants failed to change that + behavior even once. Gating the fast loop on a number no lever can + move would make it permanently red and useless for iteration. +3. Both numbers are always printed. Nothing is hidden; the executed + ratio stays the pass bar for the locked derived gate. + +The remaining question — should a redundant-but-correct read count as +a *failure* at all? — is an app-semantics decision, not a copy lever +(§7). + +--- + +## 6. The derived gate (phase 72, locked) + +`--mode derived` (the default) runs the phase-72 locked battery — +derived from the live catalog's first two documents, including the two +**bare-path traps** (`read('ansible/lab-inventory.md')` without the +source prefix, etc.) — with the phase-72 locked conditions, including +executed/emitted ≥ 0.90. Against the fixture KB (2026-09-04): + +``` +gate: lite FAIL turns=10 answered=10 caps=0 tool-turns=10 calls 5/15 executed (33%) contract 12/15 (80%) (wall 47.7s) +``` + +Reading that result: the teaching works — **every bare-path trap +self-corrected in exactly one round** (the did-you-mean refusal named +the combined identity, the model used it next round), zero cap hits, +10/10 answered. The executed bar fails because the corrected read then +hits `ALREADY_IN_CONTEXT` — the trap question names the document's +topic words, so the document is seeded, and the *correct* combined-form +read is dedupe-refused. Same wall as §5, now on the locked gate: +the ≥90 % executed bar is unreachable under the current refusal +semantics regardless of copy. The gate runs as-is, unchanged, and +reports it. + +--- + +## 7. Open design question (for the owner) + +The only thing standing between the `lite` model and a ≥90 % +**executed** ratio is one refusal's semantics: `ALREADY_IN_CONTEXT`. +Options, with trade-offs: + +1. **Keep as-is** (phase-72 locked): a redundant read is a refusal, + counts in nothing. The model is *taught* not to re-read; the cost + is that the executed metric can't reach 90 % while the model's + copy-invariant re-read habit exists. Contract accuracy (the + capability metric) is ~100 %. +2. **Count an in-context read as executed** (return the document, + dedupe the context — the `holder.read_docs` dedupe already makes a + re-read a no-op content-wise). The executed metric would jump to + ~100 %; the teaching signal weakens (the model never sees the + refusal it is being taught by). +3. **Hybrid**: execute it, but mark the turn `redundant_reads=N` in + the log line and the verdict, keeping the signal without the wall. + +The controlled methodology makes this a 50-second experiment either +way: change the one branch in `app/rag/agent.py::_execute_tool`, +update its unit pins, run the full fixture loop. + +--- + +## 8. Reproducing from scratch + +```bash +# 0. Prereqs: the usual dev setup (AGENTS.md quick reference) +podman compose up -d db +cp .env.example .env # once; LLM endpoint + DB URL +uv run alembic upgrade head + +# 1. Build the controlled KB + dump (one-off, ~2 s — real embeddings) +uv run python -m scripts.load_test_kb +# → prints the retrieval report (all 10 must be grounded) and +# verifies the dump by round-trip. + +# 2. The loop +uv run python -m scripts.agent_realmodel_check --restore --mode fixture --turns 3 # ~12 s micro-loop +uv run python -m scripts.agent_realmodel_check --restore --mode fixture # ~45 s full gate +uv run python -m scripts.agent_realmodel_check --restore # phase-72 locked gate + +# 3. After touching the copy levers +uv run pytest tests/unit -q # pins in sync? +uv run pytest --cov=app --cov-report=term-missing | tail -3 # >90 % +uv run ruff check . && uv run pyright +uv run pytest tests/e2e/test_tool_path_teaching.py -v --no-cov # E2E in isolation +``` + +Exit codes, both gate and restore/build: **0** pass/ok, **1** fail +(with the per-condition breakdown — the MISS lines name the lever to +iterate), **2** precondition (DB down, dump missing, schema not +applied — each with the actionable fix on the same line). + +Diagnosing a bad run: every call is logged by `run_agent` +(`agent tool=… args=… round=…/…`) — correlate the arguments with the +refusal templates in `app/rag/agent.py` to see which teaching line the +model hit, and which refusal class (contract violation vs. in-context +dedupe) the rejection was. diff --git a/scripts/agent_realmodel_check.py b/scripts/agent_realmodel_check.py new file mode 100644 index 0000000..f04addb --- /dev/null +++ b/scripts/agent_realmodel_check.py @@ -0,0 +1,816 @@ +"""The real-model tool-calling gate (live, the configured chat model). + +The phase-72 pass condition (owner directive 2026-09-03 — "test with the +real lite model until tool calls work consistently; don't pass until a +sufficient number of tool calls succeed"): this script drives a fixed +question battery through the **real** grounded path — the exact mirror +of ``app.api.chat`` (embed → retrieve → the honesty gate via +``plan_turn`` → the steering notes + KB overview exactly as +``app.api.chat`` reads them → ``build_high_prompt`` / deflection prompt → +``run_agent`` with the configured chat model and the real Postgres KB, a +fresh ``AgentHolder`` per turn; a deflected turn runs the same +``tools=None`` + one-bounded-recovery stream the deflected API branch +runs) — and applies the four LOCKED pass conditions: + +1. all turns answer (no ``LLMError`` / ``MalformedReplyError``); +2. zero turns hit the round cap (the incident's loop signature — hitting + the cap means the teaching did not end the loop); +3. >=6 of 10 turns emit >=1 tool call (the model keeps USING tools — it + does not abandon them and answer from seed context alone, the + incident's end state); +4. the accuracy bar across the whole run — ``derived`` mode (the + phase-72 LOCKED gate): executed / emitted >= 0.90 (refusals count in + nothing); ``fixture`` mode (the controlled methodology): contract + accuracy — well-formed calls targeting resolvable entities — + >= 0.90, with the executed ratio reported alongside (see + ``classify_call`` and ``TOOL_CALLING_TESTING.md`` for why the two + metrics differ: the app's ALREADY_IN_CONTEXT dedupe refusal is an + app-semantics choice, not a tool-calling error). + +Batteries (``--mode``): + +* ``derived`` (default, the phase-72 LOCKED battery) — the fixed + 10-question battery derived from the live catalog's first two documents + ``D1 = (s1, p1, t1)`` / ``D2 = (s2, p2, t2)`` (catalog order); the + grep question's token is the first whitespace-split word of + ``D2.content`` with length >= 6 (leading/trailing non-alphanumerics + stripped, lowercased), falling back to the first word of ``t2``. +* ``fixture`` (the controlled fast loop, 2026-09-04 owner directive) — + :data:`FIXTURE_BATTERY`, the curated 10 questions pinned to the + hand-written fixture KB (``tests/fixtures/agent_kb/``). Combine with + ``--restore`` so the whole iteration is one command against a known, + unguessable, re-embed-free knowledge base (``TOOL_CALLING_TESTING.md``). + +Speed levers (the fast loop): ``--restore`` (restore the fixture dump in +one transaction — no git clone, no re-embedding, sub-second); ``--turns +N`` (run only the first N questions — the micro-loop for copy +iteration; the verdict is then marked ``partial`` and condition 3 is +reported, not gated); every turn line carries its wall seconds and the +verdict line carries the run's total wall time, so a slow-down is +visible in the same line that carries the accuracy. + +House probe pattern (``scripts/llm_probe.py``): ``uv run python -m +scripts.agent_realmodel_check`` — argparse, dotenv, plain module, no +debugpy. The script never modifies the KB (no commits, no query_log +rows — the only writes are the ``--restore`` snapshot restore, which is +explicit and transactional). + +Preconditions (exit 2 with an actionable line on failure): the DB is +reachable; ``BOR_AGENT_MAX_ROUNDS`` is > 0 (the gate needs tools +enabled); ``derived`` mode — the catalog holds >=2 documents and the +FIRST TWO catalog documents' ``path``s each contain ``/`` (the +bare-path traps need nested paths); ``fixture`` mode — the fixture dump +exists (build it with ``uv run python -m scripts.load_test_kb``). + +Exit codes: **0 PASS**, **1 FAIL** (the per-condition breakdown is +printed so the copy-lever iteration loop can target the right lever), +**2 precondition failure**. For refusal diagnosis, every call is +already logged by ``run_agent`` (``agent tool=… args=… round=…/…``) — +correlate the logged arguments with the refusal templates in +``app/rag/agent.py`` to see which teaching line the model hit. +""" +from __future__ import annotations + +import argparse +import asyncio +import logging +import sys +import time +from dataclasses import dataclass, field +from datetime import date +from pathlib import Path +from typing import Any + +from dotenv import load_dotenv + +from app.api.chat import plan_turn +from app.api.steering import load_steering_notes +from app.config import Settings, get_settings +from app.db import SessionLocal, db_available +from app.rag.agent import ( + CORRECTION_INSTRUCTION, + AgentHolder, + MalformedReplyError, + find_document, + list_catalog, + list_source_names, + run_agent, +) +from app.rag.llm import ( + EmbeddingError, + LLMClient, + LLMError, + StreamPiece, + ToolCallPiece, + chat_stream_retried, +) +from app.rag.overview import load_kb_overview +from app.rag.retriever import retrieve +from app.rag.scaffolding import ScaffoldingFilter + +logger = logging.getLogger("agent_realmodel_check") + +#: Repo-relative fixture dump (written by scripts.load_test_kb). +DEFAULT_DUMP_PATH = Path("tests/fixtures/test_kb.dump.sql") + +#: The per-turn line truncates the question at this width (the locked +#: format prints ``turn NN | emitted=E executed=X cap=Y|N | ``). +QUESTION_DISPLAY_WIDTH = 40 + +#: The controlled fast-loop battery (2026-09-04, owner directive): the +#: curated 10 questions pinned to the fixture KB +#: (``tests/fixtures/agent_kb/`` — sources ``deployments`` / ``homelab``, +#: 8 hand-written documents whose specifics — ``rack7``, +#: ``10.77.42.0/24``, VLAN 130, port 18443, ntfy topic +#: ``reese-uptime-7``, machine ID ``rbm-8842``, the ``17 2 * * *`` +#: schedule, image ``ghcr.io/reese/obsidian-bor:2026.7.14``, port +#: 18765 — are not guessable by any model). +#: +#: Design rule (the controlled-test property): every question has ONE +#: unambiguously correct tool behavior, verified by the load script's +#: retrieval report. The ``read`` targets (Q4/Q5/Q6) are named so the +#: question's tokens do NOT lexically seed the target document (the +#: filenames carry no topical words the content repeats) — the read +#: must actually happen, exactly once, in the combined form. The +#: discipline turns (Q7/Q8/Q9) name content that IS seeded — the +#: correct behavior there is to answer from the ```` context +#: (or ``ls``), NOT to re-read. The bare-path traps are the job of the +#: locked derived battery, not this one. +#: +#: 1. the phase-72 incident ("list the files in this directory" — a +#: full listing needs ``ls``: 8 docs, 2 in seed context); +#: 2. a scoped ``ls`` by the correct source name; +#: 3. the no-arg listing; +#: 4. a ``read`` of an unseeded document (combined form, given whole); +#: 5. a second ``read`` of an unseeded document (explicit "Read …"); +#: 6. a third ``read`` of an unseeded document; +#: 7. the ``grep`` turn (``rbm-8842`` — a string that occurs in exactly +#: one fixture document; the grep line alone answers "which ones"); +#: 8. a title lookup — the target IS seeded; summarize from context; +#: 9. a topic lookup — the target IS seeded; answer from context; +#: 10. the source name phrased as a directory (the ``ls(path=…)`` scope +#: trap). +FIXTURE_BATTERY: list[str] = [ + "List the files in this directory.", + "List the documents you have in the homelab source.", + "List every document you have indexed.", + "Open the document homelab/networking/vela-bridges.md and tell me what it covers.", + "Read deployments/quadlet/mimir-service.md and summarize it.", + "Open the document homelab/networking/meridian-notes.md and tell me what it covers.", + 'Find the exact string "rbm-8842" in your documents and tell me which ones ' + "contain it.", + 'Which document has the title "Lab Ansible Inventory"? Summarize it.', + "What do you know about the qwen 3.8 llama.cpp setup? Give me the exact " + "launch arguments.", + "List the files in the deployments directory.", +] + + +def _alnum_edge(word: str) -> str: + """Strip leading/trailing non-alphanumerics from *word*.""" + start = 0 + end = len(word) + while start < end and not word[start].isalnum(): + start += 1 + while end > start and not word[end - 1].isalnum(): + end -= 1 + return word[start:end] + + +def derive_token(content: str, title: str) -> str: + """The derived battery's grep token (locked by the phase-72 task + file). The first whitespace-split word of *content* whose stripped + length is >= 6 (leading/trailing non-alphanumerics stripped, + lowercased); the fallback is the first word of *title* (the same + cleanup).""" + for word in content.split(): + token = _alnum_edge(word).lower() + if len(token) >= 6: + return token + words = title.split() + return _alnum_edge(words[0]).lower() if words else "document" + + +def build_battery( + catalog: list[tuple[str, str, str]], d2_content: str +) -> list[str]: + """The fixed 10-question battery (locked by the phase-72 task file — + do not swap in easier questions), derived from the live catalog's + first two documents ``D1 = (s1, p1, t1)`` / ``D2 = (s2, p2, t2)`` + (catalog order): + + 1. the incident ("list the files in this directory" — the + harness-prior ``ls(path='.')`` misuse); + 2. a scoped ``ls`` by the correct source name (``s1``); + 3. the no-arg listing; + 4. a bare-path ``read`` trap (``p1`` without its source prefix); + 5. the combined form (the correct shape); + 6. a second bare-path ``read`` trap (``p2``); + 7. the ``grep`` turn (the derived token — guaranteed to occur in + D2's content); + 8. a title lookup + read (``t2``); + 9. a title lookup + open (``t1``); + 10. the source name phrased as a directory (``s2`` — the + ``ls(path=…)`` scope trap). + """ + (s1, p1, t1), (s2, p2, t2) = catalog[0], catalog[1] + token = derive_token(d2_content, t2) + return [ + "List the files in this directory.", + f"List the documents you have in the {s1} source.", + "List every document you have indexed.", + f"What does the document {p1} contain? Open it and tell me.", + f"Read {s1}/{p1} and summarize it.", + f"Open the document {p2} and tell me what it covers.", + f'Find the exact string "{token}" in your documents and tell me ' + "which ones contain it.", + f'Which document has the title "{t2}"? Read it and summarize.', + f"What do you know about {t1}? Open the relevant document and give " + "me specifics.", + f"List the files in the {s2} directory.", + ] + + +def check_preconditions( + settings: Settings, mode: str, dump: Path +) -> int | None: + """The locked preconditions — ``2`` on failure (an actionable line is + printed), ``None`` when all hold: the DB is reachable and + ``agent_max_rounds`` > 0 (both modes); ``derived`` — the catalog + holds >=2 documents and the first two catalog documents' ``path``s + each contain ``/`` (the bare-path traps need nested paths); + ``fixture`` — the fixture dump exists.""" + if not db_available(): + print( + "precondition failed: database unreachable — start Postgres " + "with `podman compose up -d db` and re-run" + ) + return 2 + if settings.agent_max_rounds <= 0: + print( + "precondition failed: BOR_AGENT_MAX_ROUNDS is " + f"{settings.agent_max_rounds} (the no-tools kill switch) — set " + "it to a positive value for the gate" + ) + return 2 + if mode == "fixture": + if not dump.is_file(): + print( + "precondition failed: fixture dump missing " + f"({dump}) — build it once: " + "`uv run python -m scripts.load_test_kb`" + ) + return 2 + return None + with SessionLocal() as db: + catalog = list_catalog(db) + if len(catalog) < 2: + print( + f"precondition failed: catalog holds {len(catalog)} document(s) " + "(need >= 2) — import a knowledge base first: " + "`uv run python -m scripts.import_docs`" + ) + return 2 + bad = [(source, path) for source, path, _ in catalog[:2] if "/" not in path] + if bad: + print( + "precondition failed: the first two catalog documents' paths must " + f"each contain '/' (the bare-path traps need nested paths) — got " + f"{bad!r}; import a source with a nested directory layout" + ) + return 2 + return None + + +@dataclass +class TurnResult: + """One battery turn's measurements (from the consumed stream + the + holder — no app-code changes for measurement).""" + + index: int + question: str + max_rounds: int # settings.agent_max_rounds for this run + emitted: int = 0 # ToolCallPieces the stream yielded + executed: int = 0 # holder.tool_calls (refusals count in nothing) + answered: bool = True # the stream finished without LLMError + error: str = "" # the terminal error (when not answered) + deflected: bool = False # the honesty gate deflected (no tools offered) + seconds: float = 0.0 # wall time for the whole turn (embed → settled) + calls: list[tuple[str, dict[str, Any]]] = field( + default_factory=list + ) # every emitted (name, arguments) — the contract-accuracy input + + @property + def cap_reached(self) -> bool: + """Every capped round emitted a call, so the cap implies at + least ``max_rounds`` emissions — and never the reverse.""" + return self.emitted >= self.max_rounds + + def display(self) -> str: + """The per-turn line: ``turn NN | emitted=E executed=X + cap=Y|N defl=Y|N | Ss | `` (the locked core plus the + 2026-09-04 additions — the deflection flag and the turn's wall + seconds — so a slow-down is visible on the same line).""" + text = self.question + if len(text) > QUESTION_DISPLAY_WIDTH: + cut = text[:QUESTION_DISPLAY_WIDTH] + text = cut.rsplit(" ", 1)[0].rstrip(" ,;:") + " …" + return ( + f"turn {self.index:02d} | emitted={self.emitted} " + f"executed={self.executed} cap={'yes' if self.cap_reached else 'no'} " + f"defl={'yes' if self.deflected else 'no'} | {self.seconds:5.2f}s " + f"| {text}" + ) + + +async def run_turn( + llm: LLMClient, settings: Settings, index: int, question: str +) -> TurnResult: + """One battery question through the REAL grounded path — the exact + mirror of ``app.api.chat`` (same prompt the UI gets): embed the + question, retrieve, the honesty gate (``plan_turn``), read the + steering notes + KB overview the way chat.py reads them, then — + grounded — ``run_agent`` with a **fresh** :class:`AgentHolder`, or — + deflected — the ``tools=None`` stream with the one bounded + scaffolding recovery. Every yielded piece is consumed to the end; + ``emitted`` counts the yielded :class:`ToolCallPiece` values, + ``executed`` is the holder's executed-call count (refusals count in + nothing). A turn that dies with ``LLMError`` / + ``MalformedReplyError`` (the latter subclasses the former) or an + ``EmbeddingError`` is not ``answered``. ``seconds`` is the turn's + wall time (embed → settled). + """ + result = TurnResult( + index=index, question=question, max_rounds=settings.agent_max_rounds + ) + started = time.monotonic() + try: + with SessionLocal() as db: + steering_notes = load_steering_notes(db) + kb_text = (load_kb_overview(db) or "").strip() + question_vec = await llm.embed_one(question) + chunks = retrieve(db, question, question_vec) + plan = plan_turn(chunks, settings, notes=steering_notes, kb_overview=kb_text) + if plan.deflected: + result.deflected = True + await _run_deflected(llm, settings, plan.system_prompt, question, result) + else: + holder = AgentHolder() + stream = run_agent( + llm, + db, + system_prompt=plan.system_prompt, + user_message=question, + seed_docs=plan.docs, + settings=settings, + holder=holder, + ) + async for piece in stream: + if isinstance(piece, ToolCallPiece): + result.emitted += 1 + result.calls.append((piece.name, dict(piece.arguments))) + result.executed = holder.tool_calls + except (LLMError, EmbeddingError) as e: + result.answered = False + result.error = f"{type(e).__name__}: {e}" + result.seconds = time.monotonic() - started + return result + + +async def _run_deflected( + llm: LLMClient, + settings: Settings, + system_prompt: str, + question: str, + result: TurnResult, +) -> None: + """The deflected mirror of ``app.api.chat``: one ``tools=None`` + request through the retry primitive with a caller-owned + :class:`ScaffoldingFilter`, and — when the filter wiped the whole + reply — exactly ONE bounded recovery (``tools=None``, + :data:`CORRECTION_INSTRUCTION` folded into the single system + message, a fresh filter). A second empty reply raises + :class:`MalformedReplyError` (the turn is not ``answered``). No tool + call can be emitted on this path (``tools=None``).""" + messages = [ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": question}, + ] + first_filter = ScaffoldingFilter() + content_chars = 0 + stream = chat_stream_retried( + llm, + messages, + tools=None, + retries=settings.llm_retries, + delay=settings.llm_retry_delay, + scaffolding=first_filter, + ) + try: + async for piece in stream: + if isinstance(piece, StreamPiece) and piece.kind == "content": + content_chars += len(piece.text) + finally: + await stream.aclose() + if content_chars == 0 and first_filter.stripped_chars > 0: + recovery_filter = ScaffoldingFilter() + recovered = chat_stream_retried( + llm, + [ + { + "role": "system", + "content": system_prompt + "\n" + CORRECTION_INSTRUCTION, + }, + *messages[1:], + ], + tools=None, + retries=settings.llm_retries, + delay=settings.llm_retry_delay, + scaffolding=recovery_filter, + ) + recovery_content = 0 + try: + async for piece in recovered: + if isinstance(piece, StreamPiece) and piece.kind == "content": + recovery_content += len(piece.text) + finally: + await recovered.aclose() + if recovery_content == 0: + # Terminal, as in chat.py: the dedicated error, no done. + raise MalformedReplyError( + "the deflected model answered in raw tool-scaffolding twice " + "in a row — no clean answer" + ) + + +def classify_call( + name: str, args: dict[str, Any], catalog: set[tuple[str, str]], sources: set[str] +) -> bool: + """Contract correctness of ONE emitted call (the tool-calling + accuracy metric, 2026-09-04 controlled methodology). + + A call is contract-correct when it uses a known tool with well-formed + required arguments that target a RESOLVABLE entity — the phase-72 + incident class (unknown scopes, bare document paths, hallucinated + identities, ``ls(path='/')``-style misuse) is exactly what this + flags. An ``ALREADY_IN_CONTEXT`` re-read is NOT flagged: the call is + well-formed and names a real document — the app's context dedupe + refusing a redundant read is an app-semantics choice, not a + tool-calling error (the controlled gate's telemetry — the same + re-read 15/15 across copy variants — is documented in + ``TOOL_CALLING_TESTING.md``). The classification mirrors + ``app.rag.agent._execute_tool``'s resolution rules gate-side (no + app-code changes for measurement). + """ + if name == "ls": + raw = args.get("path") + scope = raw.strip() if isinstance(raw, str) else "" + return scope == "" or scope in sources + if name == "read": + raw = args.get("path") + arg = raw.strip() if isinstance(raw, str) else "" + if "/" not in arg: + return False # a bare name can never be a document + source, _, path = arg.partition("/") + return (source, path) in catalog + if name == "grep": + raw_pattern = args.get("pattern") + if not (isinstance(raw_pattern, str) and raw_pattern.strip()): + return False + raw_path = args.get("path") + scope = raw_path.strip() if isinstance(raw_path, str) else "" + if scope: + if "/" not in scope: + return False + source, _, path = scope.partition("/") + return (source, path) in catalog + return True + return False # unknown tool + + +def score_contract( + turns: list[TurnResult], + catalog: set[tuple[str, str]], + sources: set[str], +) -> int: + """Contract accuracy across the run: how many emitted calls are + contract-correct (:func:`classify_call`) against the run's catalog + and source names. Per-turn counts are attached on each + :class:`TurnResult` as ``_contract_ok`` (measurement state, not a + dataclass field — the display line stays the locked format).""" + ok = 0 + for turn in turns: + turn_ok = sum( + 1 for name, args in turn.calls if classify_call(name, args, catalog, sources) + ) + turn._contract_ok = turn_ok # type: ignore[attr-defined] + ok += turn_ok + return ok + + +def evaluate( + turns: list[TurnResult], partial: bool = False, mode: str = "derived" +) -> tuple[bool, list[tuple[str, bool, str]]]: + """The pass conditions → ``(passed, [(name, ok, detail)])``. + + ``contract_ok`` per turn was attached by :func:`score_contract` + before this call (0 while unattached — main always scores first). + + 1. all turns ``answered``; 2. zero ``cap_reached`` turns; 3. >=6 of + 10 turns with ``emitted >= 1`` (on a ``partial`` run — ``--turns N`` + with N < the battery length — the count is REPORTED but not gated: + a short micro-loop exists for copy iteration, not as the gate); + 4. the accuracy bar — ``derived`` mode (the phase-72 LOCKED gate): + ``executed / emitted >= 0.90``; ``fixture`` mode (the 2026-09-04 + controlled methodology): **contract accuracy** (well-formed calls + targeting resolvable entities, :func:`classify_call`) >= 0.90 — with + the executed ratio REPORTED alongside (a run with zero emitted calls + fails condition 3 anyway, so an empty denominator does not sink + condition 4). + """ + n = len(turns) + failed = [t for t in turns if not t.answered] + caps = [t for t in turns if t.cap_reached] + tool_turns = sum(1 for t in turns if t.emitted >= 1) + emitted = sum(t.emitted for t in turns) + executed = sum(t.executed for t in turns) + deflected = sum(1 for t in turns if t.deflected) + contract_ok = sum( + getattr(t, "_contract_ok", 0) for t in turns # type: ignore[attr-defined] + ) + failed_detail = f"{n - len(failed)}/{n}" + if failed: + failed_detail += "; " + "; ".join( + f"turn {t.index:02d}: {t.error}" for t in failed + ) + conditions: list[tuple[str, bool, str]] = [ + ("all turns answered", not failed, failed_detail), + ( + "zero cap-reached turns", + not caps, + "0" if not caps else f"{len(caps)} hit the round cap: " + + ", ".join(f"turn {t.index:02d}" for t in caps), + ), + ( + ">= 6 of 10 turns with >= 1 emitted tool call", + True if partial else tool_turns >= 6, + f"{tool_turns}/{n}" + + (" (partial run — reported, not gated)" if partial else "") + + ( + f"; {deflected} deflected (no tools offered — the honesty gate)" + if deflected + else "" + ), + ), + ] + if emitted == 0: + conditions.append( + ( + "accuracy bar >= 0.90 across the run", + True, # no calls emitted — condition 3 already fails + "0/0 (no calls emitted — condition 3 fails)", + ) + ) + elif mode == "fixture": + # The controlled methodology's accuracy bar: contract accuracy. + # The executed ratio is reported right below it (not gated — it + # includes the app's ALREADY_IN_CONTEXT dedupe refusals, which + # the controlled telemetry shows are copy-invariant model + # behavior, not tool-calling errors). + contract_ratio = contract_ok / emitted + conditions.append( + ( + "contract accuracy >= 0.90 (well-formed calls, resolvable targets)", + contract_ratio >= 0.90, + f"{contract_ok}/{emitted} ({round(100 * contract_ratio)}%)", + ) + ) + conditions.append( + ( + "executed / emitted (reported — includes in-context dedupe refusals)", + True, + f"{executed}/{emitted} ({round(100 * executed / emitted)}%)", + ) + ) + else: + ratio = executed / emitted + conditions.append( + ( + "executed / emitted >= 0.90 across the run (phase-72 locked)", + ratio >= 0.90, + f"{executed}/{emitted} ({round(100 * ratio)}%) — " + f"contract {contract_ok}/{emitted} ({round(100 * contract_ok / emitted)}%)", + ) + ) + return all(ok for _name, ok, _detail in conditions), conditions + + +def verdict_line( + model: str, + turns: list[TurnResult], + passed: bool, + wall_seconds: float, + partial: bool, + mode: str = "derived", +) -> str: + """The single stable verdict line (model = the configured chat + model, date = run date, the run's total wall time since 2026-09-04, + both accuracy metrics since the 2026-09-04 controlled methodology):: + + gate: lite PASS turns=10 answered=10 caps=0 tool-turns=8 calls + 7/12 executed (58%) contract 12/12 (100%) 2026-09-04 (wall 48.8s) + """ + answered = sum(1 for t in turns if t.answered) + caps = sum(1 for t in turns if t.cap_reached) + tool_turns = sum(1 for t in turns if t.emitted >= 1) + emitted = sum(t.emitted for t in turns) + executed = sum(t.executed for t in turns) + contract_ok = sum( + getattr(t, "_contract_ok", 0) for t in turns # type: ignore[attr-defined] + ) + pct = round(100 * executed / emitted) if emitted else 0 + cpct = round(100 * contract_ok / emitted) if emitted else 0 + deflected = sum(1 for t in turns if t.deflected) + return ( + f"gate: {model} {'PASS' if passed else 'FAIL'} turns={len(turns)}" + + (" (partial)" if partial else "") + + f" answered={answered} caps={caps} tool-turns={tool_turns}" + + (f" deflected={deflected}" if deflected else "") + + f" calls {executed}/{emitted} executed ({pct}%) " + f"contract {contract_ok}/{emitted} ({cpct}%) " + f"{date.today().isoformat()} (wall {wall_seconds:.1f}s)" + ) + + +async def run_battery( + llm: LLMClient, + settings: Settings, + battery: list[str], + concurrency: int = 1, +) -> list[TurnResult]: + """The whole battery, printing the per-turn line as each turn + settles. ``concurrency > 1`` runs that many turns at once against + the endpoint (the aggregate verdict is unchanged — the conditions + are run-wide sums; the per-turn lines may then print out of order).""" + turns: list[TurnResult] = [] + if concurrency <= 1: + for index, question in enumerate(battery, start=1): + turns.append(await run_turn(llm, settings, index, question)) + print(turns[-1].display()) + return turns + semaphore = asyncio.Semaphore(concurrency) + + async def one(index: int, question: str) -> TurnResult: + async with semaphore: + return await run_turn(llm, settings, index, question) + + gather = [ + asyncio.create_task(one(index, question)) + for index, question in enumerate(battery, start=1) + ] + for finished in asyncio.as_completed(gather): + result = await finished + turns.append(result) + print(result.display()) + turns.sort(key=lambda t: t.index) + return turns + + +def main(argv: list[str] | None = None) -> int: + # CLI-only: pick up .env without side effects on import (the + # house probe pattern, cf. scripts/llm_probe.py). + load_dotenv() + parser = argparse.ArgumentParser( + description=( + "The real-model tool-calling gate: drive a fixed question " + "battery through the real grounded path against the live " + "endpoint with the configured chat model, and print the " + "PASS/FAIL verdict against the four locked conditions " + "(exit 0 PASS, 1 FAIL, 2 precondition failure). The fast " + "loop: --restore --mode fixture." + ) + ) + parser.add_argument( + "--mode", + choices=["derived", "fixture"], + default="derived", + help=( + "derived (default, the phase-72 locked battery from the live " + "catalog) or fixture (the curated battery pinned to the " + "fixture KB — pair with --restore)" + ), + ) + parser.add_argument( + "--restore", + action="store_true", + help="restore the fixture KB dump into the database first (one " + "transaction — no git clone, no re-embedding)", + ) + parser.add_argument( + "--turns", + type=int, + default=None, + metavar="N", + help="run only the first N battery questions (the micro-loop for " + "copy iteration; the verdict is marked partial and condition 3 " + "is reported, not gated)", + ) + parser.add_argument( + "--concurrency", + type=int, + default=1, + metavar="N", + help="run up to N turns at once (default 1 — sequential; the " + "aggregate verdict is unchanged)", + ) + parser.add_argument( + "--dump", + type=Path, + default=None, + metavar="PATH", + help="the fixture dump for --restore / --mode fixture (default: " + f"{DEFAULT_DUMP_PATH})", + ) + args = parser.parse_args(argv) + logging.basicConfig( + level=logging.INFO, format="%(levelname)s %(name)s: %(message)s" + ) + + settings = get_settings() + dump = args.dump or DEFAULT_DUMP_PATH + rc = check_preconditions(settings, args.mode, dump) + if rc is not None: + return rc + + run_started = time.monotonic() + if args.restore: + from scripts.restore_test_kb import restore_dump + + print(f"restore: {dump} …") + t0 = time.monotonic() + restored = restore_dump(dump) + print( + f"restore: ok in {time.monotonic() - t0:.2f}s " + f"({restored.docs} docs, {len(restored.sources)} sources)" + ) + + if args.mode == "fixture": + battery = list(FIXTURE_BATTERY) + logger.info( + "gate: model=%s mode=fixture battery=%d questions (fixture KB)", + settings.llm_chat_model, + len(battery), + ) + else: + with SessionLocal() as db: + catalog = list_catalog(db) + s2, p2, _t2 = catalog[1] + d2 = find_document(db, s2, p2) + d2_content = d2.content if d2 is not None else "" + battery = build_battery(catalog, d2_content) + logger.info( + "gate: model=%s kb_docs=%d battery=%d questions", + settings.llm_chat_model, + len(catalog), + len(battery), + ) + + if args.turns is not None: + if args.turns <= 0: + print("error: --turns must be >= 1") + return 2 + battery = battery[: args.turns] + + for number, question in enumerate(battery, start=1): + print(f" {number:02d}. {question}") + + llm = LLMClient(settings) + turns = asyncio.run( + run_battery(llm, settings, battery, concurrency=max(1, args.concurrency)) + ) + wall = time.monotonic() - run_started + + # The contract-accuracy classification needs the run's catalog + + # source names (the KB is static across the run — the restore, when + # any, happened before the battery). + with SessionLocal() as db: + catalog_set = set((s, p) for s, p, _t in list_catalog(db)) + sources_set = set(list_source_names(db)) + score_contract(turns, catalog_set, sources_set) + passed, conditions = evaluate( + turns, partial=args.turns is not None, mode=args.mode + ) + print( + verdict_line( + settings.llm_chat_model, turns, passed, wall, args.turns is not None, args.mode + ) + ) + if not passed: + print("conditions (the MISS(es) mark the copy lever to iterate):") + for name, ok, detail in conditions: + print(f" [{'ok ' if ok else 'MISS'}] {name}: {detail}") + return 0 if passed else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/load_test_kb.py b/scripts/load_test_kb.py new file mode 100644 index 0000000..19ecbda --- /dev/null +++ b/scripts/load_test_kb.py @@ -0,0 +1,347 @@ +"""Build the controlled tool-calling test KB and snapshot it (one-off). + +The fixture KB lives in ``tests/fixtures/agent_kb/`` — two source +directories (``deployments``, ``homelab``) with eight hand-written +markdown documents whose specifics (``rack7``, ``10.77.42.0/24``, +VLAN 130, port 18443, ntfy topic ``reese-uptime-7``, machine ID +``rbm-8842``, the ``17 2 * * *`` schedule, image +``ghcr.io/reese/obsidian-bor:2026.7.14``, port 18765, …) are not +guessable by any model. This script: + +1. resets the app tables (one TRUNCATE — the dump's table set), +2. registers the two fixture directories as ``kind='local'`` + ``git_sources`` rows (so the source registry — and therefore + ``ls``'s scope names — is self-contained and independent of the + ``BOR_GIT_SOURCES`` env var), +3. imports the fixture documents through the real pipeline + (``import_sources`` — real chunking + real ``embed``-model + embeddings; this is the ONLY step that burns model calls, and only + at build time), +4. stores the static KB overview + the sources-version row, +5. prints a **retrieval report** for every fixture-battery question + (grounded or deflected, which documents would seed) — the battery + must be all-grounded for the gate to exercise the tools, +6. snapshots the resulting database state into + ``tests/fixtures/test_kb.dump.sql`` — a data-only SQL script + (TRUNCATE + one multi-row ``INSERT`` per app table, generated + in-process — the same file runs in psql or psycopg, in one + transaction) — and **verifies the snapshot by restoring it and + comparing a per-table checksum**. + +Re-run it only when the fixture documents, the chunker, or the +embedding model change — everyday iterations restore the dump in +sub-second time (``scripts/restore_test_kb`` / the gate's +``--restore``), never re-embedding (see ``TOOL_CALLING_TESTING.md``). + +Exit codes: **0** built + verified, **1** build/verification failure, +**2** precondition failure. +""" +from __future__ import annotations + +import argparse +import asyncio +import json +import logging +import sys +import time +import uuid +from datetime import datetime +from pathlib import Path + +from dotenv import load_dotenv +from sqlalchemy import select, text +from sqlalchemy.orm import Session + +from app.api.chat import plan_turn +from app.config import get_settings +from app.db import SessionLocal, db_available +from app.models import ( + Chunk, + DocDraft, + Document, + GitSource, + KbOverview, + QueryLog, + SavedChat, + SourcesMeta, + SteeringNote, +) +from app.rag.importer import import_sources +from app.rag.llm import LLMClient +from app.rag.retriever import retrieve + +logger = logging.getLogger("scripts.load_test_kb") + +DEFAULT_KB_DIR = Path("tests/fixtures/agent_kb") +DEFAULT_DUMP = Path("tests/fixtures/test_kb.dump.sql") + +#: The two fixture source directories (source name = directory basename, +#: the importer's rule). Alphabetical — the catalog order the derived +#: battery reads. +FIXTURE_SOURCES: tuple[str, ...] = ("deployments", "homelab") + +#: The KB overview stored with the fixture (id=1). A plain outline of +#: the KB's basic categories — the ```` prompt section +#: of every turn. Static on purpose: the dump must be deterministic and +#: the gate must not burn a ``lite`` call at restore time. +FIXTURE_KB_OVERVIEW: str = ( + "deployments: the lab Ansible inventory (host addresses and roles), " + "the Obsidian BOR quadlet service definition, and the GitLab Runner " + "CI setup. homelab: the rack7 Proxmox cluster networking (bridges, " + "VLANs, DNS/DHCP), container notes (Uptime Kuma, Qwen 3.8 on " + "llama.cpp), and the nightly restic backup configuration." +) + +#: (table, model, explicit column list — the generated ``chunks.tsv`` +#: tsvector column is excluded; Postgres recomputes it). +_TABLES: tuple[tuple[str, type, tuple[str, ...]], ...] = ( + ("documents", Document, ("id", "source", "path", "full_path", "title", + "content", "content_hash", "indexed_at", "summary")), + ("chunks", Chunk, ("id", "document_id", "position", "content", + "embedding", "is_summary")), + ("git_sources", GitSource, ("id", "url", "kind", "path", "added_at")), + ("kb_overview", KbOverview, ("id", "content", "updated_at")), + ("sources_meta", SourcesMeta, ("id", "version", "updated_at")), + ("steering_notes", SteeringNote, ("id", "note", "created_at")), + ("query_log", QueryLog, ("id", "question", "top_score", "fts_hits", + "chunk_hits", "deflected", "sources", + "latency_ms", "created_at")), + ("saved_chats", SavedChat, ("id", "title", "messages", "share_token", + "sources_version", "created_at", "updated_at")), + ("doc_drafts", DocDraft, ("id", "token", "title", "path", "body", + "status", "branch", "commit_sha", "created_at", + "updated_at")), +) + + +# -------------------------------------------------------------------------- +# SQL serialization (the dump is plain multi-row INSERTs — the installed +# psycopg build exposes no COPY API, and a multi-statement script with +# inline ``COPY … FROM stdin`` data cannot be sent through any driver's +# simple-protocol execute. INSERT VALUES is the portable form: the same +# file runs in psql, psycopg, or anything else that speaks SQL, in one +# transaction. With ``standard_conforming_strings`` on (the Postgres +# default since 9.1), a string literal needs ONLY single-quote doubling — +# backslashes are literal and newlines may be real. +# -------------------------------------------------------------------------- + +def _sql_value(value: object) -> str: + """One value as a SQL literal (``NULL`` for None).""" + if value is None: + return "NULL" + if isinstance(value, bool): + return "TRUE" if value else "FALSE" + if isinstance(value, float): + return repr(value) # shortest round-trip double + if isinstance(value, int): + return str(value) + if isinstance(value, uuid.UUID): + return "'" + str(value) + "'" + if isinstance(value, datetime): + return "'" + value.isoformat(sep=" ") + "'" + if isinstance(value, (list, tuple)) and value and isinstance(value[0], float): + # A pgvector vector: the ``[v1, v2, …]`` text literal (pgvector + # 0.7+ format; the older ``{…}`` form is rejected). Checked + # before the JSONB branch — a JSONB array of dicts never has a + # float first element. + return "'" + "[" + ",".join(repr(v) for v in value) + "]" + "'" + if isinstance(value, (dict, list)): + # JSONB columns: the stored JSON text (Postgres re-parses it). + text_ = json.dumps(value, ensure_ascii=False, separators=(",", ":")) + else: + text_ = str(value) + return "'" + text_.replace("'", "''") + "'" + + +def _dump_table(db: Session, table: str, model: type, columns: tuple[str, ...]) -> str: + """One multi-row ``INSERT INTO (…) VALUES (…), …;`` statement + (an empty table emits nothing — there is no row to write).""" + rows = db.execute(select(model)).all() + value_rows = [ + "(" + ", ".join(_sql_value(getattr(row[0], name)) for name in columns) + ")" + for row in rows + ] + if not value_rows: + return "" + return ( + f"INSERT INTO public.{table} ({', '.join(columns)}) VALUES " + + ",\n".join(value_rows) + + ";\n" + ) + + +def _table_checksum(db: Session, table: str) -> str: + """An order-independent content checksum for *table* (row::text, + sorted aggregation) — the snapshot round-trip check.""" + return db.execute( + text( + "select md5(coalesce(string_agg(r, E'\\n' order by r), '')) " + f"from (select t::text as r from public.{table} t) s" + ) + ).scalar_one() + + +async def _retrieval_report(llm: LLMClient, battery: list[str]) -> int: + """Print, per battery question, what the real path would do: + grounded or deflected, and which documents would seed the context. + Returns the number of deflected questions (a loud warning — the + gate needs tools offered on its turns).""" + settings = get_settings() + deflected = 0 + print("\nretrieval report (the honesty gate per battery question):") + with SessionLocal() as db: + for number, question in enumerate(battery, start=1): + vec = await llm.embed_one(question) + chunks = retrieve(db, question, vec) + plan = plan_turn(chunks, settings) + seed = ", ".join(f"{d.source}/{d.path}" for d in plan.docs) or "—" + if plan.deflected: + deflected += 1 + print( + f" {number:02d}. {'DEFLECTED ' if plan.deflected else 'grounded '} " + f"(best={plan.top_score:.3f} fts={plan.fts_hits}) " + f"seed: {seed}\n ← {question}" + ) + return deflected + + +async def _build(kb_dir: Path, dump_path: Path) -> int: + from scripts.agent_realmodel_check import FIXTURE_BATTERY + + started = time.monotonic() + if not db_available(): + print( + "load_test_kb: precondition failed — database unreachable; " + "start Postgres with `podman compose up -d db`" + ) + return 2 + + source_dirs = [kb_dir / name for name in FIXTURE_SOURCES] + missing = [str(p) for p in source_dirs if not p.is_dir()] + if missing: + print(f"load_test_kb: precondition failed — missing source dir(s): {missing}") + return 2 + + # 1. Reset the dump's table set (one statement — the inter-table FKs + # resolve within it). + table_list = ", ".join(f"public.{table}" for table, _m, _c in _TABLES) + with SessionLocal() as db: + db.execute(text(f"TRUNCATE {table_list}")) + for directory in source_dirs: + absolute = str(directory.resolve()) + db.add(GitSource(url=absolute, kind="local", path=absolute)) + db.commit() + logger.info("load_test_kb: tables reset; %d local source rows added", len(source_dirs)) + + # 2. Import through the real pipeline (the only model-cost step). + llm = LLMClient() + summary = await import_sources([p.resolve() for p in source_dirs], llm) + if summary.errors: + print(f"load_test_kb: {summary.errors} file(s) failed to import — aborting") + return 1 + if summary.added == 0: + print("load_test_kb: no documents imported — aborting") + return 1 + logger.info( + "load_test_kb: imported added=%d chunks=%d embed_batches=%d", + summary.added, summary.chunks, summary.embed_batches, + ) + + # 3. The static overview + sources version. + with SessionLocal() as db: + overview = db.get(KbOverview, 1) or KbOverview(id=1) + overview.content = FIXTURE_KB_OVERVIEW + meta = db.get(SourcesMeta, 1) or SourcesMeta(id=1) + meta.version = 1 + db.add(overview) + db.add(meta) + db.commit() + + # 4. Retrieval report (all battery questions must stay grounded). + n_deflected = await _retrieval_report(llm, list(FIXTURE_BATTERY)) + if n_deflected: + print( + f"\nload_test_kb: WARNING — {n_deflected} battery question(s) would " + "DEFLECT in the real path (no tools offered). Adjust the fixture " + "content (a lexical anchor for the question's words) or the " + "question before running the gate." + ) + + # 5. Snapshot (data-only) + round-trip verification. + with SessionLocal() as db: + before = {table: _table_checksum(db, table) for table, _m, _c in _TABLES} + parts = [ + "-- ============================================================", + "-- Brain of Reese — controlled tool-calling test KB (fixture dump)", + f"-- Generated by scripts/load_test_kb.py on " + f"{datetime.now().astimezone().isoformat(timespec='seconds')}", + "-- Data-only snapshot (the schema stays alembic-managed; the", + "-- generated chunks.tsv column is recomputed on restore).", + f"-- Sources: {', '.join(FIXTURE_SOURCES)} " + f"({summary.added} documents, {summary.chunks} chunks).", + "-- Restore (one transaction, sub-second):", + "-- uv run python -m scripts.restore_test_kb", + "-- psql \"$BOR_DATABASE_URL\" --single-transaction -f " + "tests/fixtures/test_kb.dump.sql", + "-- ============================================================", + f"TRUNCATE {table_list};", + "", + ] + for table, model, columns in _TABLES: + parts.append(_dump_table(db, table, model, columns)) + script = "\n".join(parts) + dump_path.parent.mkdir(parents=True, exist_ok=True) + dump_path.write_text(script, encoding="utf-8") + logger.info("load_test_kb: dump written: %s (%d KB)", dump_path, len(script) // 1024) + + # Round-trip: restore the dump over the (identical) state and compare + # the per-table checksums — a serialization bug must fail the build. + from scripts.restore_test_kb import restore_dump + + restore_dump(dump_path) # RuntimeError on failure → the build fails + with SessionLocal() as db: + after = {table: _table_checksum(db, table) for table, _m, _c in _TABLES} + mismatched = [t for t, c in before.items() if after.get(t) != c] + if mismatched: + print(f"load_test_kb: VERIFICATION FAILED — checksum mismatch: {mismatched}") + return 1 + + wall = time.monotonic() - started + print( + f"load_test_kb: ok — docs={summary.added} chunks={summary.chunks} " + f"sources={len(FIXTURE_SOURCES)} dump={dump_path} " + f"({dump_path.stat().st_size // 1024} KB, verified by round-trip) " + f"in {wall:.1f}s" + ) + return 0 + + +def main(argv: list[str] | None = None) -> int: + # CLI-only: pick up .env without side effects on import (the house + # probe pattern, cf. scripts/llm_probe.py). + load_dotenv() + parser = argparse.ArgumentParser( + description=( + "Build the controlled tool-calling test KB from " + "tests/fixtures/agent_kb (real embeddings, once) and snapshot " + "it to tests/fixtures/test_kb.dump.sql (verified by " + "round-trip). Exit 0 built+verified, 1 failure, 2 precondition." + ) + ) + parser.add_argument( + "--kb-dir", type=Path, default=DEFAULT_KB_DIR, + help=f"the fixture KB root (default: {DEFAULT_KB_DIR})", + ) + parser.add_argument( + "--dump", type=Path, default=DEFAULT_DUMP, + help=f"the dump file to write (default: {DEFAULT_DUMP})", + ) + args = parser.parse_args(argv) + logging.basicConfig( + level=logging.INFO, format="%(levelname)s %(name)s: %(message)s" + ) + return asyncio.run(_build(args.kb_dir, args.dump)) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/restore_test_kb.py b/scripts/restore_test_kb.py new file mode 100644 index 0000000..9692e16 --- /dev/null +++ b/scripts/restore_test_kb.py @@ -0,0 +1,178 @@ +"""One-shot restore of the controlled tool-calling test KB (the fast loop). + +The fixture KB (``tests/fixtures/agent_kb/`` — two sources, eight +hand-written markdown documents) is built once by +:mod:`scripts.load_test_kb`, which embeds the documents and snapshots the +resulting database state into ``tests/fixtures/test_kb.dump.sql`` — a +data-only SQL script (``TRUNCATE`` + one multi-row ``INSERT`` per app +table, generated in-process — the same file runs in psql or psycopg). This +script restores that +snapshot in **one transaction** through the app's own database URL +(``BOR_DATABASE_URL``): no git clone of the homelab repo, no re-embedding, +no ``lite``-model calls — the whole known state (documents, chunks + +embeddings, the source registry rows, the KB overview, the sources +version) lands in a fraction of a second, which is what makes a +tool-calling iteration loop fast (see ``TOOL_CALLING_TESTING.md``): + + uv run python -m scripts.restore_test_kb + # restore_test_kb: ok in 0.41s (8 docs, 2 sources, 16 chunks) + +The gate runs the same restore inline: +``uv run python -m scripts.agent_realmodel_check --restore``. + +The dump is data-only on purpose: the schema stays owned by alembic, and +the generated ``chunks.tsv`` tsvector column (``GENERATED ALWAYS AS … +STORED``) is recomputed by Postgres, so the restore is safe against schema +drift limited to additive columns. Restoring into a database whose schema +lacks an app table fails loudly with an actionable line (exit 2). + +Exit codes: **0** restored, **2** precondition failure (DB unreachable, +dump missing, schema not applied). +""" +from __future__ import annotations + +import argparse +import sys +import time +from dataclasses import dataclass +from pathlib import Path + +import psycopg +from dotenv import load_dotenv +from sqlalchemy import text + +from app.db import SessionLocal, db_available + +#: The app tables the dump covers, TRUNCATE order (one statement — +#: Postgres resolves the inter-table FKs within it). ``chunks`` and +#: ``documents`` are listed first for readability; the order is +#: irrelevant inside a single TRUNCATE. +APP_TABLES: tuple[str, ...] = ( + "chunks", + "documents", + "git_sources", + "kb_overview", + "sources_meta", + "steering_notes", + "query_log", + "saved_chats", + "doc_drafts", +) + +#: Repo-relative default dump location (the load script writes it there). +DEFAULT_DUMP = Path("tests/fixtures/test_kb.dump.sql") + + +@dataclass(frozen=True) +class RestoreResult: + """What :func:`restore_dump` did — one line of the summary output.""" + + seconds: float + docs: int + sources: tuple[str, ...] + chunks: int + dump_bytes: int + + +def _connect(): + """A raw psycopg connection on the app's DB URL (psycopg3 speaks the + SQLAlchemy URL's driver scheme — ``postgresql+psycopg`` maps to + ``postgresql`` for psycopg).""" + from app.config import get_settings + + url = get_settings().database_url + if url.startswith("postgresql+psycopg://"): + url = "postgresql://" + url.split("://", 1)[1] + return psycopg.connect(url) + + +def restore_dump(dump: Path) -> RestoreResult: + """Restore *dump* (the data-only SQL script) into the app database. + + One transaction (TRUNCATE + INSERTs + nothing else — a failed restore + rolls back and leaves the previous KB intact). Returns the measured + result; raises :class:`RuntimeError` with an actionable line on + failure (missing table = schema not applied). + """ + if not dump.is_file(): + raise RuntimeError( + f"dump not found: {dump} — build it first: " + "`uv run python -m scripts.load_test_kb`" + ) + script = dump.read_text(encoding="utf-8") + started = time.monotonic() + conn = _connect() + try: + with conn.transaction(): + # A plain multi-statement SQL script (TRUNCATE + INSERTs — no + # parameters) runs on psycopg's simple-protocol execute; the + # installed stubs type the query parameter as Template-only + # (and ``sql.SQL`` wants a LiteralString), hence the ignore. + conn.execute(script) # pyright: ignore[reportArgumentType, reportCallIssue] + except Exception as e: + message = str(e) + if "relation" in message and "does not exist" in message: + raise RuntimeError( + "schema not applied — the dump needs the alembic-managed " + f"tables; run `uv run alembic upgrade head` first ({e})" + ) from None + raise RuntimeError(f"restore failed: {e}") from None + seconds = time.monotonic() - started + with SessionLocal() as db: + docs = db.execute(text("select count(*) from documents")).scalar_one() + sources = tuple( + row[0] + for row in db.execute( + text("select distinct source from documents order by source") + ) + ) + chunks = db.execute(text("select count(*) from chunks")).scalar_one() + return RestoreResult( + seconds=seconds, + docs=docs, + sources=sources, + chunks=chunks, + dump_bytes=dump.stat().st_size, + ) + + +def main(argv: list[str] | None = None) -> int: + # CLI-only: pick up .env without side effects on import (the house + # probe pattern, cf. scripts/llm_probe.py). + load_dotenv() + parser = argparse.ArgumentParser( + description=( + "Restore the controlled tool-calling test KB from the fixture " + "dump (one transaction, no git clone, no re-embedding). Exit " + "0 on success, 2 on precondition failure." + ) + ) + parser.add_argument( + "--dump", + type=Path, + default=DEFAULT_DUMP, + help=f"the data-only SQL dump to restore (default: {DEFAULT_DUMP})", + ) + args = parser.parse_args(argv) + + if not db_available(): + print( + "restore_test_kb: precondition failed — database unreachable; " + "start Postgres with `podman compose up -d db`" + ) + return 2 + try: + result = restore_dump(args.dump) + except RuntimeError as e: + print(f"restore_test_kb: {e}") + return 2 + print( + f"restore_test_kb: ok in {result.seconds:.2f}s " + f"({result.docs} docs, {len(result.sources)} sources, " + f"{result.chunks} chunks, dump {result.dump_bytes // 1024} KB)" + ) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tests/fixtures/agent_kb/deployments/ansible/lab-inventory.md b/tests/fixtures/agent_kb/deployments/ansible/lab-inventory.md new file mode 100644 index 0000000..46464d7 --- /dev/null +++ b/tests/fixtures/agent_kb/deployments/ansible/lab-inventory.md @@ -0,0 +1,17 @@ +# Lab Ansible Inventory + +The lab deployment inventory lives in `op-build:~/lab/inventory/hosts.yml` +and is managed with ansible-core 2.19.4. + + lab: + hosts: + rack7-pbx1: { ip: 10.77.42.11, role: hypervisor } + rack7-pbx2: { ip: 10.77.42.12, role: aio } + minio01: { ip: 10.77.42.31, role: storage } + vars: + ansible_user: reese + ansible_become: true + +- Playbooks run from `op-build` only; the shelf has no internet route. +- The `lab-upgrade` play requires the `pve-upgrade` tag on the target. +- These files are the single source of truth for shelf addresses. diff --git a/tests/fixtures/agent_kb/deployments/ci/gitlab-runner.md b/tests/fixtures/agent_kb/deployments/ci/gitlab-runner.md new file mode 100644 index 0000000..8e35c81 --- /dev/null +++ b/tests/fixtures/agent_kb/deployments/ci/gitlab-runner.md @@ -0,0 +1,12 @@ +# GitLab Runner (lab-ci) + +CI for the shelf runs on a single GitLab Runner registered against +`git.reeseapps.com`. + +- Executor: docker; the runner daemon lives on `rack7-pbx2`. +- Registration token format: `glrt-` plus 20 hex chars (rotated 2026-06). +- Tags: `lab-ci` (default) and `pve-upgrade` (the gated upgrade job). +- Job images: `ghcr.io/reese/lab-ci:2026.7` for ansible plays, + `debian:13-slim` for lint. +- Concurrency is capped at 2; the `pve-upgrade` job never runs in + parallel with itself. diff --git a/tests/fixtures/agent_kb/deployments/quadlet/mimir-service.md b/tests/fixtures/agent_kb/deployments/quadlet/mimir-service.md new file mode 100644 index 0000000..e2ad911 --- /dev/null +++ b/tests/fixtures/agent_kb/deployments/quadlet/mimir-service.md @@ -0,0 +1,15 @@ +# BOR Vault Sync Unit + +The Brain-of-Reese vault syncs from `obsidian.container` on `rack7-pbx2`. + + [Container] + Image=ghcr.io/reese/obsidian-bor:2026.7.14 + PublishPort=127.0.0.1:18765:8080 + Environment=VAULT_DIR=/vault/rack7 + Restart=always + MemoryMax=2g + +- The vault is a bind mount from `/data/vaults/rack7` (Btrfs subvolume). +- Only `rack7-pbx2` may hold the vault — do not clone it to another node. +- Image tags are date-stamped; bump by re-pushing + `ghcr.io/reese/obsidian-bor` and restarting the unit. diff --git a/tests/fixtures/agent_kb/homelab/backups/restic-rack7.md b/tests/fixtures/agent_kb/homelab/backups/restic-rack7.md new file mode 100644 index 0000000..742551e --- /dev/null +++ b/tests/fixtures/agent_kb/homelab/backups/restic-rack7.md @@ -0,0 +1,11 @@ +# Restic Backups for Rack7 + +Every config and document on the cluster is backed up nightly with +restic into the minio repo `minio01:/backups/rack7`. + +- Machine ID: **rbm-8842** +- Password: `op vault view rack7/restic` +- Schedule: `17 2 * * *` (02:17 nightly) +- Retention: `--keep-daily 7 --keep-weekly 4 --keep-monthly 12` +- Prune runs only when the repo grows more than 5 GiB. +- Restores are tested quarterly; the last dry-run passed on 2026-07-01. diff --git a/tests/fixtures/agent_kb/homelab/containers/qwen38-llamacpp.md b/tests/fixtures/agent_kb/homelab/containers/qwen38-llamacpp.md new file mode 100644 index 0000000..a1164c1 --- /dev/null +++ b/tests/fixtures/agent_kb/homelab/containers/qwen38-llamacpp.md @@ -0,0 +1,15 @@ +# Qwen 3.8 on llama.cpp (pbx-node3) + +The GPU box (`pbx-node3`) serves Qwen 3.8 through llama.cpp. + +Working launch line (verified 2026-08): + + ./llama-server -m qwen3.8-30b-a3b-instruct.Q8_0.gguf \ + -c 32768 -ngl 99 --mlock --threads 12 -sm layer \ + --cache-type-k q8_0 --cache-type-v q8_0 \ + --jinja --port 18180 + +- Context 32768, KV cache q8_0/q8_0, prompt cache persisted to + `/srv/llamacpp/cache`. +- First-token target is under 400 ms; sustained throughput about 28 tok/s. +- Do not add `-ctk f16` — it doubled VRAM usage with no quality gain. diff --git a/tests/fixtures/agent_kb/homelab/containers/uptime-kuma.md b/tests/fixtures/agent_kb/homelab/containers/uptime-kuma.md new file mode 100644 index 0000000..a14f77b --- /dev/null +++ b/tests/fixtures/agent_kb/homelab/containers/uptime-kuma.md @@ -0,0 +1,11 @@ +# Uptime Kuma (AIO) + +Uptime Kuma runs on `rack7-pbx2` as the AIO image, listening on +**18443** with TLS terminated by `caddy-rack7`. + +- Health endpoint: `https://uptime.rack7.local/ping` +- Every monitor posts to the ntfy topic `reese-uptime-7` on failure. +- History is kept for 30 days; the database is backed up hourly to + `/opt/kuma/backup/`. +- Lab-iot monitors watch every VLAN 130 device; the shelf watchdog + restarts the container after 3 missed checks. diff --git a/tests/fixtures/agent_kb/homelab/networking/meridian-notes.md b/tests/fixtures/agent_kb/homelab/networking/meridian-notes.md new file mode 100644 index 0000000..803614b --- /dev/null +++ b/tests/fixtures/agent_kb/homelab/networking/meridian-notes.md @@ -0,0 +1,10 @@ +# Rack7 DNS and DHCP + +`minio01` (10.77.42.31) serves DNS and DHCP for the whole lab shelf. + +- dnsmasq answers port 53 with upstream `1.1.1.1` and `9.9.9.9`. +- VLAN 130 (lab-iot) pool: 10.77.130.50–10.77.130.200, 6-hour leases, + netmask 255.255.255.0. +- Pi-hole runs on 10.77.42.53; the admin UI is on port 18553 behind + caddy-rack7 and uses the blocklist `reese-abuse-v3`. +- VLAN 42 has no DHCP at all — every device there gets a static address. diff --git a/tests/fixtures/agent_kb/homelab/networking/vela-bridges.md b/tests/fixtures/agent_kb/homelab/networking/vela-bridges.md new file mode 100644 index 0000000..19ca9de --- /dev/null +++ b/tests/fixtures/agent_kb/homelab/networking/vela-bridges.md @@ -0,0 +1,18 @@ +# Rack7 Proxmox Cluster + +Three-node Proxmox VE cluster on the rack7 shelf: `pbx-node1`, `pbx-node2` +and `pbx-node3`, all running PVE 8.3.4 (build `8.3.4-1-lab1`). + +## Virtual interfaces + +| vmbr | purpose | config | +|-------|---------------------|----------------------------------------------------| +| vmbr0 | management | 10.77.42.0/24, gateway 10.77.42.1 on pbx-node1 | +| vmbr1 | lab (VLAN 42) | tag 42, no DHCP, NAT-only to the uplink | +| vmbr2 | lab-iot (VLAN 130) | tag 130, DHCP served by minio01 | + +- Cluster firewall is enabled on every node; VLAN 42 traffic is NAT-only. +- Corosync heartbeat rides vmbr0; keep the management iface out of the + lab-iot VLAN. +- Node roles: pbx-node1 = hypervisor + gateway, pbx-node2 = AIO + containers, pbx-node3 = GPU box. diff --git a/tests/fixtures/test_kb.dump.sql b/tests/fixtures/test_kb.dump.sql new file mode 100644 index 0000000..bc916cd --- /dev/null +++ b/tests/fixtures/test_kb.dump.sql @@ -0,0 +1,249 @@ +-- ============================================================ +-- Brain of Reese — controlled tool-calling test KB (fixture dump) +-- Generated by scripts/load_test_kb.py on 2026-09-04T12:57:48-04:00 +-- Data-only snapshot (the schema stays alembic-managed; the +-- generated chunks.tsv column is recomputed on restore). +-- Sources: deployments, homelab (8 documents, 9 chunks). +-- Restore (one transaction, sub-second): +-- uv run python -m scripts.restore_test_kb +-- psql "$BOR_DATABASE_URL" --single-transaction -f tests/fixtures/test_kb.dump.sql +-- ============================================================ +TRUNCATE public.documents, public.chunks, public.git_sources, public.kb_overview, public.sources_meta, public.steering_notes, public.query_log, public.saved_chats, public.doc_drafts; + +INSERT INTO public.documents (id, source, path, full_path, title, content, content_hash, indexed_at, summary) VALUES ('0cee890b-f91e-42d6-94ff-4249a70b19ca', 'deployments', 'ansible/lab-inventory.md', '/var/home/ducoterra/Projects/Personal/brain_of_reese/tests/fixtures/agent_kb/deployments/ansible/lab-inventory.md', 'Lab Ansible Inventory', '# Lab Ansible Inventory + +The lab deployment inventory lives in `op-build:~/lab/inventory/hosts.yml` +and is managed with ansible-core 2.19.4. + + lab: + hosts: + rack7-pbx1: { ip: 10.77.42.11, role: hypervisor } + rack7-pbx2: { ip: 10.77.42.12, role: aio } + minio01: { ip: 10.77.42.31, role: storage } + vars: + ansible_user: reese + ansible_become: true + +- Playbooks run from `op-build` only; the shelf has no internet route. +- The `lab-upgrade` play requires the `pve-upgrade` tag on the target. +- These files are the single source of truth for shelf addresses. +', '8eb4df05c80ca10ec32f0f5b6c7202f4061b3f4fabfc5f1b518b8a0627ea263b', '2026-09-04 16:57:47.845878+00:00', NULL), +('840dabec-48bb-40e3-9833-cb1a646ed777', 'deployments', 'ci/gitlab-runner.md', '/var/home/ducoterra/Projects/Personal/brain_of_reese/tests/fixtures/agent_kb/deployments/ci/gitlab-runner.md', 'GitLab Runner (lab-ci)', '# GitLab Runner (lab-ci) + +CI for the shelf runs on a single GitLab Runner registered against +`git.reeseapps.com`. + +- Executor: docker; the runner daemon lives on `rack7-pbx2`. +- Registration token format: `glrt-` plus 20 hex chars (rotated 2026-06). +- Tags: `lab-ci` (default) and `pve-upgrade` (the gated upgrade job). +- Job images: `ghcr.io/reese/lab-ci:2026.7` for ansible plays, + `debian:13-slim` for lint. +- Concurrency is capped at 2; the `pve-upgrade` job never runs in + parallel with itself. +', '5634ed3c87d8e8e2c89f7c56339d74c075f62eb554bf98a818b04fee6f15f754', '2026-09-04 16:57:47.963345+00:00', NULL), +('fd7a1902-7366-49fd-9c33-06bf9fdce547', 'deployments', 'quadlet/mimir-service.md', '/var/home/ducoterra/Projects/Personal/brain_of_reese/tests/fixtures/agent_kb/deployments/quadlet/mimir-service.md', 'BOR Vault Sync Unit', '# BOR Vault Sync Unit + +The Brain-of-Reese vault syncs from `obsidian.container` on `rack7-pbx2`. + + [Container] + Image=ghcr.io/reese/obsidian-bor:2026.7.14 + PublishPort=127.0.0.1:18765:8080 + Environment=VAULT_DIR=/vault/rack7 + Restart=always + MemoryMax=2g + +- The vault is a bind mount from `/data/vaults/rack7` (Btrfs subvolume). +- Only `rack7-pbx2` may hold the vault — do not clone it to another node. +- Image tags are date-stamped; bump by re-pushing + `ghcr.io/reese/obsidian-bor` and restarting the unit. +', '703d8425ba26caf607b240abbebff4be048f828482a6c3297338120e166dc635', '2026-09-04 16:57:48.017861+00:00', NULL), +('f24790a5-dc20-4a28-8f96-37f4e6db1cfb', 'homelab', 'backups/restic-rack7.md', '/var/home/ducoterra/Projects/Personal/brain_of_reese/tests/fixtures/agent_kb/homelab/backups/restic-rack7.md', 'Restic Backups for Rack7', '# Restic Backups for Rack7 + +Every config and document on the cluster is backed up nightly with +restic into the minio repo `minio01:/backups/rack7`. + +- Machine ID: **rbm-8842** +- Password: `op vault view rack7/restic` +- Schedule: `17 2 * * *` (02:17 nightly) +- Retention: `--keep-daily 7 --keep-weekly 4 --keep-monthly 12` +- Prune runs only when the repo grows more than 5 GiB. +- Restores are tested quarterly; the last dry-run passed on 2026-07-01. +', '7998c1127f41ef3dc8d0786af071d6b91817d791a5b5098b10e56ada239a4e8b', '2026-09-04 16:57:48.073288+00:00', NULL), +('1a49e6a0-dbaf-4210-8266-81aac216fb42', 'homelab', 'containers/qwen38-llamacpp.md', '/var/home/ducoterra/Projects/Personal/brain_of_reese/tests/fixtures/agent_kb/homelab/containers/qwen38-llamacpp.md', 'Qwen 3.8 on llama.cpp (pbx-node3)', '# Qwen 3.8 on llama.cpp (pbx-node3) + +The GPU box (`pbx-node3`) serves Qwen 3.8 through llama.cpp. + +Working launch line (verified 2026-08): + + ./llama-server -m qwen3.8-30b-a3b-instruct.Q8_0.gguf \ + -c 32768 -ngl 99 --mlock --threads 12 -sm layer \ + --cache-type-k q8_0 --cache-type-v q8_0 \ + --jinja --port 18180 + +- Context 32768, KV cache q8_0/q8_0, prompt cache persisted to + `/srv/llamacpp/cache`. +- First-token target is under 400 ms; sustained throughput about 28 tok/s. +- Do not add `-ctk f16` — it doubled VRAM usage with no quality gain. +', 'e145b56dd4945a7ba83fabd52a84d00a1cb7ca41dcb2235aafb303b1056b8016', '2026-09-04 16:57:48.124176+00:00', NULL), +('ba951767-d744-4e62-bd19-2d947090e58e', 'homelab', 'containers/uptime-kuma.md', '/var/home/ducoterra/Projects/Personal/brain_of_reese/tests/fixtures/agent_kb/homelab/containers/uptime-kuma.md', 'Uptime Kuma (AIO)', '# Uptime Kuma (AIO) + +Uptime Kuma runs on `rack7-pbx2` as the AIO image, listening on +**18443** with TLS terminated by `caddy-rack7`. + +- Health endpoint: `https://uptime.rack7.local/ping` +- Every monitor posts to the ntfy topic `reese-uptime-7` on failure. +- History is kept for 30 days; the database is backed up hourly to + `/opt/kuma/backup/`. +- Lab-iot monitors watch every VLAN 130 device; the shelf watchdog + restarts the container after 3 missed checks. +', 'a573e8063d9c69cdb3e9823dc718cbe2ef07772deea1e0466c6cfb66611b2335', '2026-09-04 16:57:48.175456+00:00', NULL), +('bfbb483e-6bdb-4003-bc16-2d0d568156bd', 'homelab', 'networking/meridian-notes.md', '/var/home/ducoterra/Projects/Personal/brain_of_reese/tests/fixtures/agent_kb/homelab/networking/meridian-notes.md', 'Rack7 DNS and DHCP', '# Rack7 DNS and DHCP + +`minio01` (10.77.42.31) serves DNS and DHCP for the whole lab shelf. + +- dnsmasq answers port 53 with upstream `1.1.1.1` and `9.9.9.9`. +- VLAN 130 (lab-iot) pool: 10.77.130.50–10.77.130.200, 6-hour leases, + netmask 255.255.255.0. +- Pi-hole runs on 10.77.42.53; the admin UI is on port 18553 behind + caddy-rack7 and uses the blocklist `reese-abuse-v3`. +- VLAN 42 has no DHCP at all — every device there gets a static address. +', 'a8e53576835de52df06ff5942cda021d5c28ab82a9de211a322beb8c23daa709', '2026-09-04 16:57:48.226163+00:00', NULL), +('47655720-be4c-499c-9761-74aa9ca45385', 'homelab', 'networking/vela-bridges.md', '/var/home/ducoterra/Projects/Personal/brain_of_reese/tests/fixtures/agent_kb/homelab/networking/vela-bridges.md', 'Rack7 Proxmox Cluster', '# Rack7 Proxmox Cluster + +Three-node Proxmox VE cluster on the rack7 shelf: `pbx-node1`, `pbx-node2` +and `pbx-node3`, all running PVE 8.3.4 (build `8.3.4-1-lab1`). + +## Virtual interfaces + +| vmbr | purpose | config | +|-------|---------------------|----------------------------------------------------| +| vmbr0 | management | 10.77.42.0/24, gateway 10.77.42.1 on pbx-node1 | +| vmbr1 | lab (VLAN 42) | tag 42, no DHCP, NAT-only to the uplink | +| vmbr2 | lab-iot (VLAN 130) | tag 130, DHCP served by minio01 | + +- Cluster firewall is enabled on every node; VLAN 42 traffic is NAT-only. +- Corosync heartbeat rides vmbr0; keep the management iface out of the + lab-iot VLAN. +- Node roles: pbx-node1 = hypervisor + gateway, pbx-node2 = AIO + containers, pbx-node3 = GPU box. +', '520f7df799d0841b1dbcc636705aa5727d882dbb8c0453a4ccbf8b459df304f8', '2026-09-04 16:57:48.281298+00:00', NULL); + +INSERT INTO public.chunks (id, document_id, position, content, embedding, is_summary) VALUES ('20a0b278-e32b-4216-949f-a688dd7232e8', '0cee890b-f91e-42d6-94ff-4249a70b19ca', 0, '# Lab Ansible Inventory + +The lab deployment inventory lives in `op-build:~/lab/inventory/hosts.yml` +and is managed with ansible-core 2.19.4. + + lab: + hosts: + rack7-pbx1: { ip: 10.77.42.11, role: hypervisor } + rack7-pbx2: { ip: 10.77.42.12, role: aio } + minio01: { ip: 10.77.42.31, role: storage } + vars: + ansible_user: reese + ansible_become: true + +- Playbooks run from `op-build` only; the shelf has no internet route. +- The `lab-upgrade` play requires the `pve-upgrade` tag on the target. +- These files are the single source of truth for shelf addresses.', '[0.0131165,-0.01286068,0.0018187251,-0.025069347,0.026930904,-0.010061519,0.03639165,-0.0024801716,-0.0018757446,-0.0056415047,-0.043978132,-0.0055465554,0.02749457,-0.01588221,-0.0031239141,0.015124069,7.382009e-05,0.006532587,0.017546764,-0.03620404,-0.01957861,0.021899011,-0.01114644,0.024008542,-0.012930608,0.016941814,0.01134548,0.03553374,0.03323714,-0.040675685,-0.023371449,-0.01183408,-0.03358365,-0.0019148266,0.012659925,0.017849788,0.008659159,0.0014803014,-0.026984448,-0.09597992,0.017141668,0.016370578,-0.04151496,-0.012735902,0.025547761,0.0058631687,-0.021245819,0.020999556,-0.0146535,-0.016787102,-0.049144182,0.0018046572,0.004818515,-0.0032424713,0.025226386,0.020392658,0.01968785,-0.051538356,0.030269574,-0.028947547,-0.023559585,-0.008182669,0.018328547,-0.011025023,-0.0111371465,-0.009298838,0.010951343,-0.012942978,-0.04981587,0.0014856033,0.008090676,-0.021374322,0.023719246,0.03198768,-0.0015665763,-0.015229458,-0.03448758,0.014594236,-0.05698102,-0.014050409,0.04142552,-0.0058062198,0.005962302,-0.020460969,0.012542343,-0.0063873543,-0.04456228,-0.004668555,-0.008744117,-0.00531,0.020091264,0.021627929,0.00042647644,-0.07999119,0.01541289,0.0015962933,-0.011626312,-0.00018966512,-0.022663463,-0.017639577,-0.0032521738,0.005813755,0.002983077,-0.013823359,-0.022782136,0.034106754,0.021019833,0.002246202,0.013775662,0.0103806155,-0.0051695616,-0.03904711,-0.020617953,-0.030974977,0.014598646,0.022986306,0.009110181,0.0059745763,0.03091675,0.017885158,-0.008469035,0.02870801,-0.01726025,-0.0051749223,-0.0017321572,0.017581256,-0.011323983,-0.040385064,0.025793534,0.0056867646,0.013468858,0.018149374,0.036006268,0.00028223565,0.013474617,-0.008469555,-0.0008731733,-0.024354368,0.013353442,-0.035059363,0.021096129,-0.049316637,0.038681477,0.0055693034,0.05058907,-0.04688489,-0.0029198604,0.005587252,0.014727143,0.015145581,-0.0011796654,-0.020408705,0.005991874,0.008162653,0.0049857725,-0.008442068,-0.008789493,0.010419884,-0.003699708,0.00068187236,0.007937392,-0.015489746,0.06952851,0.011690855,-0.020956531,-0.019384345,-0.0127140395,-0.013081008,0.012684255,-0.012787022,0.0009325887,0.02177989,-0.013047031,-0.0010223332,-0.015090888,0.024258766,0.01834564,0.021109475,0.0022422075,0.0065516485,0.022992475,-0.026969917,0.031850297,-0.017739773,0.01357889,-0.029354244,0.021714143,-0.034089927,0.0036653916,-0.011513499,-0.013695482,0.0126686515,0.0009216392,0.009412121,-0.032169495,0.017477876,0.006045853,0.008782758,-0.03107135,-0.04462336,0.0131814405,-0.0023575118,-0.029042348,-0.024306199,0.020067867,0.03051005,-0.0060908203,-0.023299135,-0.0016035871,0.011376532,0.028999876,0.0073232003,0.013166376,0.020628486,0.002302301,-0.005367483,0.004913885,-0.011291779,0.01375848,7.4394244e-05,0.031063901,0.0148175685,0.013039951,0.002647959,0.03141401,0.010670585,0.0093488665,-0.0061738733,-0.009797442,-0.028686997,0.003412695,0.017236348,0.022260474,0.0092540225,-0.026708174,-0.06218596,0.0059990524,-0.0014820107,0.00025507188,0.024188561,0.0035349086,0.017452821,0.01835625,0.012374628,0.0026335758,0.0119746765,0.02535802,-0.013420555,-0.03988483,-0.013466745,0.00016415936,-0.01507087,-0.018961946,-0.0246745,0.032628182,0.010423807,0.008183236,0.0017572561,0.005737203,-0.0014550936,0.008316198,0.0090452535,0.0077844854,0.016977962,-0.0012022344,-0.004376255,-0.010913582,-0.027692007,0.013511699,0.00078780745,-0.03394934,0.013872497,-0.015874203,0.030414958,0.0053028674,-0.012132932,0.042498566,-0.026032977,0.017801192,0.014726876,0.034165144,-0.028151013,-0.031138174,-0.020858249,-0.015635792,-0.03237541,0.028584411,-0.017679488,0.030451505,0.011629949,0.013514797,0.004612233,0.009861689,-0.0018757688,0.02215618,0.01661471,0.0033636522,-0.0343125,0.010084312,-0.013842449,-0.009186183,-0.008242853,-0.011063282,0.0050381175,-0.024588477,-0.03500249,0.024365667,-0.0034105931,0.0056030685,-0.0061887987,-0.017193437,0.016555354,-0.020211056,-0.0038000217,-0.002669652,0.022263423,0.019055562,0.014037523,-0.015889019,-0.019400004,-0.015250375,0.011422298,0.024589734,-0.017150318,0.037137877,0.043386366,0.009030979,0.013811393,-0.010015726,0.00017630467,0.062063247,0.08984311,-0.0021623247,0.006418138,0.0070769866,0.010778435,0.011017947,0.03439524,0.037922215,0.03708438,0.033204082,-0.023639949,0.014656817,0.021142203,-0.005920392,0.010694525,0.025984732,0.0046065073,0.057886943,0.0060926527,0.015540811,-0.024981309,0.00033576437,0.0035022316,0.025208408,0.026532006,-0.031548906,-0.027905252,-0.015890941,0.03004793,-0.07028458,0.0054144436,-0.020498654,0.020441564,0.0070006186,0.017677518,0.0288032,-0.00076472457,-0.03619615,0.05617705,0.020549115,-0.01519509,0.0069190897,-0.023318348,0.024461163,-0.010299572,0.0043511586,-0.00057226303,0.007893215,0.0050125355,0.052817654,-0.006322253,0.018882502,-0.021657923,0.0067284703,0.013149733,-0.015150629,-0.030743811,-0.0005092734,0.006335977,0.011268558,-0.019517804,0.025957108,0.000941366,-0.027905758,0.000339371,0.030847032,0.020863445,-0.022446098,-0.0010218013,0.016009472,-0.0042985007,-0.009847958,-0.018530162,-0.0004640672,-0.0027035954,0.012566948,0.59635276,-0.009171548,-0.037606843,-0.013779873,-0.004691728,0.011243977,-0.03144298,0.0133641325,0.0039867465,-0.007636093,0.0069370624,0.0055824723,-0.020940067,-0.002712105,-0.026177289,-0.028106296,0.014336731,-0.00093718903,0.020072507,-0.019253677,-0.059181742,-0.022391887,-0.07360106,0.027982412,-0.021790333,0.008431263,0.025815398,0.048350297,0.017983602,0.037033193,-0.061872233,0.013014431,0.005957642,0.00027277897,-0.014942086,-0.004864335,-0.0031497388,0.015018054,-0.020696027,0.011718267,-0.007008854,-0.007841078,-0.03671604,-0.034091342,0.028270857,0.04130807,-0.053631958,-0.012382015,0.02958962,-0.012777757,0.0022560593,0.016440792,0.059755888,0.012069773,-0.010036424,0.0070035337,-0.008756239,0.007831283,-0.0060547097,-0.0040162476,0.0069832387,-0.0024975527,-0.038695417,-0.019795192,-0.018856833,0.014239451,-0.012453788,-0.023340065,-0.0021102054,-0.0052688587,0.008905307,0.005501118,0.019772707,0.015695196,-0.027787063,-0.01424679,0.006496325,-0.0059887073,-0.028117234,-0.029884756,-0.021109303,-0.0064513106,0.009902882,-0.028903414,0.0047313357,-0.05366732,0.0055113765,-0.0055886656,0.0119221425,0.036369953,-0.0123074,0.03185856,0.0073263496,0.046948254,-0.031405777,-0.025426194,0.010120405,0.03005909,-0.0031823968,-0.0008650769,-0.012015338,0.01172629,0.006966304,-0.0078517925,0.002339648,0.044376176,-0.007015678,0.027852837,0.014237912,0.01713812,-0.03127463,-0.0030446462,-0.032905627,-0.0027269,-0.033659577,0.0319811,-0.022856504,-0.030071594,0.0029330002,-0.00423868,-0.023166299,-0.0041202814,0.035074726,0.030872937,0.015238553,-0.005970995,-0.015170835,-0.061178923,-0.024479464,-0.026980773,0.004577913,-0.006853951,-0.024251157,0.008433742,-0.0044121803,0.0014890775,-0.00257965,0.030345662,-0.038215615,-0.010585281,-0.010026842,-0.015389631,0.012959353,-0.009278415,0.0127769485,-0.004234907,-0.020376243,-0.0075302646,0.03237269,0.0032129334,0.017269187,0.003569198,-0.014391988,-0.018954463,-0.035188325,0.00025434754,0.000939569,-0.043200888,-0.018520815,-0.0027368693,0.008943825,-0.00541213,0.016449772,-0.0013944583,0.022534523,-0.041504536,0.008251646,-0.018995166,0.007647716,0.029666789,0.021601787,-0.035937876,-0.030918177,0.06364845,0.016485205,-0.015964726,0.03000396,-0.016993642,-0.0019130243,-0.061285418,-0.01253577,0.018139657,-0.026724016,-0.03563913,-0.015870398,-0.004549835,-0.011944086,-0.003414527,-0.03239906,0.00038629223,-0.011763248,-0.023547787,0.015392932,0.0296493,-0.030653011,0.015348211,0.00701692,-0.0077916454,-0.0059137493,0.004124048,0.008041351,0.02905869,-0.10374779,-0.06295222,-0.040263094,0.014682933,-0.030838598,-0.0054611247,0.004668311,-0.014015264,-0.010730004,-0.0014100468,0.03193195,-0.0021637154,-0.05062483,0.012391141,-0.03036431,-0.0022266223,0.0027062881,-0.038580798,-0.018354202,0.02190709,-0.031115703,-0.0111874575,-0.014181302,0.0018890346,0.0044531603,0.0033837117,-0.0122280745,-0.0054382933,-0.02962938,0.01322944,0.039573193,-0.024993641,-0.020755073,-0.024019202,-0.00957372,-0.0064056832,-0.016017132,-0.0046407785,-0.030775333,-0.011914737,-0.018981578,0.0053053973,0.0061892024,0.0029660293,0.0003591472,0.012684826,0.008946423,-0.038400162,-0.012959367,0.004144876,-0.0035405816,0.07370259,0.01679415,-0.018476032,0.00875939,0.007371914,-0.033734556,-0.01304836,-0.010558337,-0.013657582,-0.010551398,0.033587027,0.03155703,0.0136844665,0.005659698,-0.012263872,0.015180848,0.021672575,0.009405277,-0.009164207,0.007123921,0.021349486,-0.014721813,0.003946796,0.020994728,0.045647662,0.040279243,-0.054701768,0.0146052595,-0.0020434232,-0.0040447926,-0.01909446,0.009234465,-0.007561519,-0.009864297,0.0011412769,0.047909927,-0.04429991,0.057684667,0.025342135,-0.007899853,0.045845322,0.0034340008,-0.014701811,0.0026646238,0.01241061,-0.0039023224,-0.03161156,0.0111126155,0.0098141795,-0.016404422,0.02437241,-0.03550369,0.026511425,0.025076631,-0.026325518,0.004874741,0.036048334,-0.005205086,-0.015071347,-0.031853907,0.019445237,-0.0042056385,-0.006109089,0.008197366,-0.002533363,0.009060888,-0.0014384133,-0.049183566,-0.014115571,-0.020630077,-0.006084607,0.48384884,-0.026949054,-0.0015469289,0.0007830268,-0.02128331,0.0062062107,-0.0016425354,-0.01038022,-0.0166608,0.010073899,0.02123002,0.0052638557,0.007916107,0.027017174,0.0050063613,0.009687189,-0.0077932584,0.01295948,-0.0048582675,-0.017734041,0.0045086225,0.0024258327,-0.0007371844,-0.019646946,-0.03731544,-0.058102433,0.023769472,-0.010249782,0.010979934,0.005554662,0.05277026,-0.023299856,-0.017914308,-0.0013489639,-0.0060844766,-0.02403478,-0.014391879]', FALSE), +('36528b9a-e1b8-406e-b5ef-3b9e6ee732cd', '840dabec-48bb-40e3-9833-cb1a646ed777', 0, '# GitLab Runner (lab-ci) + +CI for the shelf runs on a single GitLab Runner registered against +`git.reeseapps.com`. + +- Executor: docker; the runner daemon lives on `rack7-pbx2`. +- Registration token format: `glrt-` plus 20 hex chars (rotated 2026-06). +- Tags: `lab-ci` (default) and `pve-upgrade` (the gated upgrade job). +- Job images: `ghcr.io/reese/lab-ci:2026.7` for ansible plays, + `debian:13-slim` for lint. +- Concurrency is capped at 2; the `pve-upgrade` job never runs in + parallel with itself.', '[-0.02394116,0.013589614,0.0043455637,-0.039593697,0.010795078,-0.029333128,0.00071042817,0.03628535,0.0007485166,-0.042183086,-0.010876326,-0.040158357,0.027548824,-0.017773835,-0.0012339448,0.012739963,0.02140803,0.00435697,-0.0013049871,-0.025358483,0.009087785,-0.020457368,-0.014050455,0.021722456,-0.008037078,0.019195803,0.0133715505,0.0068202117,-0.01373857,-0.052558262,-0.021467341,-0.0048792167,-0.03796804,0.0017941173,-0.019993722,0.0022321232,0.0324762,-0.011305967,-0.01285501,-0.08554007,-0.00459579,-0.00026625913,-0.012708261,-0.021467168,0.0023501804,0.005992647,-0.047074836,0.010084524,0.0021380365,-0.0017837912,-0.039571073,-0.001467435,0.008784448,0.020895327,-0.012526759,0.031282693,-0.0047232904,-0.02374443,-0.026711868,-0.026771476,-0.0030595686,0.028225487,0.0027547968,0.008954544,-0.03348828,-0.017827928,0.022534354,0.047463022,-0.020956405,-0.0043598874,0.011438837,-0.05006089,0.03272723,-0.002906665,6.671013e-05,-0.030840088,-0.022713058,0.002611123,-0.044741053,-0.02435739,0.016601998,0.020138128,-0.017031932,-0.009141122,-0.010905373,-0.012441361,-0.044166207,0.0048189918,0.011554403,-0.013101684,0.0006347179,-0.00018356378,0.002989171,-0.05306866,-0.012389916,0.017050352,0.014652261,-0.02088377,0.008641642,0.0047000716,-0.0048646894,-0.026519548,-0.0067672865,-0.0037962692,-0.0363485,0.014531998,0.016549787,0.02026939,-0.0036979532,0.019903634,0.01975829,0.022829877,-0.00078712456,-0.024566347,0.015455295,0.01445105,0.01951838,0.0013151374,0.00087779475,0.015175662,0.004154677,-0.0052880566,-0.03659207,0.01012364,0.030702367,0.017092623,-0.054150973,-0.042197637,-0.0037574312,0.014304926,0.01606984,0.021216327,0.053747702,0.010063483,0.0030246682,0.054879792,-0.053179838,0.00059382734,-0.0039532897,-0.056530103,-0.0029615858,-0.005998702,-0.0016381601,-0.008502332,0.018982979,-0.046319317,-0.02701774,-0.003752784,-0.0034972976,-0.000993019,-0.01715258,-0.03430529,0.00949175,0.00030833881,-0.04065951,0.016271714,-0.009416144,-0.020305509,-0.031791884,0.010973972,0.004827566,0.002611172,0.027777487,0.018571457,-0.04592281,0.006445065,0.0009649743,-0.033940878,0.002228014,-0.027603883,-0.0045877094,-0.00079201965,-0.011637617,0.016024895,-0.01393219,0.048051875,0.01198274,0.021944577,-0.001690239,-0.027064921,-0.020160798,-0.029952746,0.021349547,0.009534797,0.004462131,-0.03359759,0.0050401497,-0.032910947,0.0003999966,-0.036990706,-0.010895685,0.044636242,0.025826802,0.012226928,-0.023313165,0.028755372,0.022328746,0.057370152,-0.029640831,-0.0137044685,-0.013007493,-0.023454329,-0.060936607,0.022302236,0.014099108,0.024837373,-0.001755567,-0.018326966,-0.01028684,-0.016036946,0.020757949,-0.003207087,0.040503047,0.020435885,-0.0014620235,-0.022534447,0.029166155,-0.038298722,0.02828486,0.029877255,0.02013538,0.0016801162,-0.009130007,0.014692451,0.021315172,0.01479843,-0.00054077344,0.009519538,-0.005273885,-0.01864372,-0.0040200506,0.011707154,-0.032200646,-0.004432217,-0.025890887,-0.07516651,0.00042999946,0.013377287,0.0033987886,0.004326047,0.023963371,0.04086495,-0.008889745,0.021913843,-0.037730616,0.017805226,0.0029632447,0.02643568,-0.028255915,0.0004800803,0.011214384,0.019871213,-0.028053839,-0.011089171,0.08648141,0.006464581,-0.0054583633,0.02239993,-0.035033233,0.011432793,-0.0018063409,0.010378224,0.014258126,0.01863165,0.012805213,0.01890974,-0.0060545206,0.008734008,0.007040066,0.0019934026,-0.020408178,0.026608547,-0.020376226,-0.0028421003,-0.024100404,-0.010188447,0.033134352,-0.021365825,0.008421927,-0.026819114,0.011412033,-0.047056206,-0.03591378,-0.025499092,-0.016637351,-0.033518553,0.02021888,0.0012450535,0.029039023,0.026135424,-0.018355362,0.0041306186,0.018986404,0.0018936774,-0.018083543,-0.0041910824,0.010145072,-0.00037399807,0.008653788,0.00013766447,-0.030971978,0.033316918,-0.016932031,-0.01999877,-0.015537846,-0.0107497,-0.00870449,0.005165062,0.0041138823,-0.011390587,0.007647568,-0.019482654,-0.006951895,0.0034910094,0.001278284,-0.0075397952,0.038096692,0.01737946,-0.011159954,-0.040012524,-0.015274288,0.002639086,0.020329539,0.015609268,0.021286426,0.045173556,0.007906702,0.031131271,-0.014751895,0.034721788,0.026980707,0.008766076,-0.03182555,0.018167058,-0.0063160993,0.017306456,0.021028237,0.040269077,0.015998209,0.020402597,0.02116688,0.004697522,0.018205382,0.016857324,-0.018873518,0.006935081,0.03170388,0.0009679736,0.04804448,-0.0038912485,0.022388894,-0.029064246,0.0064960686,0.00921489,-0.018782575,0.008753811,-0.036871172,-0.03999169,-0.0012991404,0.010463445,-0.022597512,0.024033144,0.002006753,-0.007545056,-0.02307345,-0.0058623482,0.027008653,-0.0024452575,-0.016643835,0.05033172,0.00094273925,-0.032781594,-0.0004603607,-0.017880883,-0.017038371,-0.0059442436,-0.0394055,-0.010719008,-0.013104238,-0.0039513307,0.060532942,-0.0007555663,0.011720407,-0.022064116,0.012932899,0.012562975,0.004713785,-0.037704714,0.04699721,0.008420355,0.018522304,-0.043540016,-0.0028737432,-0.014625257,-0.023144841,-0.02042263,0.014428496,-0.010921717,-0.024630914,0.018698098,-0.0061399126,0.0019750635,-0.03054196,-0.026811648,0.0003519449,0.025999721,0.018858671,0.6081682,-0.030757638,-0.019342732,-0.00029006432,-0.0088748075,-0.011367456,0.009194233,0.06246026,0.023077708,-0.028307626,0.011830814,0.0077994694,-0.0032456247,-0.011430726,0.012325637,-0.0330886,0.024937553,-0.018379753,-0.0049150456,-0.0009395355,-0.072745964,-0.021133123,-0.04357067,0.0047441074,0.02625681,0.0045689596,-0.001498547,0.020894753,0.011414692,0.05577098,-0.034994047,-0.0048337723,-0.0060309,0.015350703,-0.024396917,-0.015943933,-0.016684182,0.01892003,-0.0019145658,-0.0083576515,0.02393349,0.0012702042,0.015651751,-0.024487011,0.023511406,0.012353809,-0.0016158075,-0.015221123,0.01936229,0.028826922,0.0003969893,0.023646189,0.010328314,-0.009650785,0.011109158,-0.012800861,-0.02247046,-0.03042445,-0.013144442,-0.012992953,0.0090354085,-0.0068788542,-0.04218809,-0.037935197,0.007468175,0.0059823757,-0.0034973698,-0.007328373,-0.0058338773,0.012868931,0.004518396,-0.0033247364,0.042194396,0.015682435,-0.014993503,0.040237576,0.02449302,-0.015579161,-0.008351251,-0.025771195,-0.021543106,0.031288367,0.0008355624,-0.011897273,0.0039517875,-0.03250001,0.018979715,-0.028971585,-0.010905844,-0.00168544,-0.040084727,-0.0063644582,0.0011294585,0.05289378,-0.014081261,-0.003274869,-0.0010260791,0.01231831,-0.01822915,-0.020789506,0.006011723,0.007782259,0.005760857,-0.0030175834,0.016054401,-0.056478426,0.030334366,0.02944521,0.0047320416,0.019918827,-0.010361321,0.007141029,-0.0089059165,-0.05159298,0.028771248,0.015948815,-0.0023770074,-0.028388605,-0.01498803,-0.022792768,-0.016431415,-0.030891024,0.057948325,0.044931047,0.019629272,0.016641837,0.013012011,-0.038017634,-0.010931106,-0.031429976,0.020745805,-0.025889667,0.00053549535,0.0041620424,0.014365199,-0.018727895,0.0051019047,0.032298982,-0.039204642,0.007048237,-0.023778465,0.010828415,0.033454258,0.01626041,-0.030489597,-0.0053399773,-0.024236642,0.00021338064,-0.021619696,0.011009642,-0.0031692565,0.0017186416,0.00473508,0.012186864,-0.0073675197,-0.02042489,-0.0013135747,-0.008279113,-0.003870957,-0.02652751,-0.016822139,-0.008251522,0.030554723,0.010867144,0.008320487,0.008651203,0.011989929,0.02342135,0.026869852,0.025539255,0.029988352,-0.044138167,-0.014965856,0.057118785,-0.012609945,-0.016612703,-0.0045674434,-0.0023083542,-0.030269854,-0.04199666,0.010131222,0.014667076,-0.012449214,-0.005117336,0.0167625,0.022660034,-0.010024802,0.0016059515,-0.0027442486,-0.023053799,-0.036603384,-0.0032770757,0.012163055,0.0056813313,-0.010652538,0.022398872,0.016042784,0.00965504,-0.02443599,0.01872035,-0.014599522,0.0076382505,-0.05715234,-0.046215046,-0.0041102953,0.030344712,-0.003944973,0.019834558,-0.013307713,-0.014476681,0.016928867,0.0032097704,-0.008279881,0.0147421,-0.012144355,-0.0030861164,-0.005510272,-0.015533046,-0.04394824,-0.03804021,-0.026478266,0.0140797645,-0.053945698,-0.029282594,0.011083838,-0.035023097,-0.006728347,-0.033264033,0.016073221,-0.012928655,0.0051766285,-6.6841244e-06,0.005322468,-0.0061627342,-0.037305824,0.012630194,0.009776324,-0.009581363,-0.009114885,0.033766855,-0.029959818,-0.008444944,-0.01362997,0.015091438,0.010507495,0.008690331,-0.017237443,0.016783087,-0.004589589,-0.06905845,0.0063057058,0.008017678,-0.009587546,0.013765404,0.006069982,-0.023723576,0.03675805,-0.01280767,-0.017637393,-0.0041231657,0.021714803,-0.003442561,-0.013030136,0.03417862,0.0037155924,0.014742321,0.010649703,-0.0128561165,0.005618433,-0.007975904,-0.031899836,-0.018822843,-0.01959247,0.022411607,-0.03356875,-0.004341604,-0.0017637733,0.025731849,0.042616937,-0.043657135,0.0039601834,-0.017068489,0.0067843706,-0.04915417,0.009980142,-0.008239986,-0.002353952,0.015065371,-0.011745687,-0.02547143,0.045997187,0.027452141,-0.029200055,0.0067262896,0.010724735,-0.013654225,0.021522848,-0.00965876,-0.005858505,-0.00059444987,0.006618734,-0.016075209,0.004025622,-0.014736814,-0.038073767,0.02470224,0.04868952,-0.017739791,-0.011070849,0.031724874,-0.02313497,-0.030563464,-0.02749536,-0.009750251,0.0029681877,-0.01623704,0.028133724,-0.020997284,-0.02010002,-0.004322833,-0.03483266,-0.012605514,-0.01321407,-0.013842247,0.4754688,-0.015343049,-0.031404596,0.020371102,-0.032056965,0.027095824,0.0060868347,0.014269672,0.008583462,-0.03444526,0.022727828,0.015071681,0.014778032,-0.005126549,-0.012179444,-0.032749932,0.0025540907,0.0027157178,-0.007990837,-0.013090978,0.004306154,-0.0045899847,0.012480492,-0.0114657,0.004094901,-0.053243585,0.045387972,-0.019443454,-0.0076749423,0.01760851,0.03594384,0.018864986,-0.023397395,0.008013871,0.038409628,-0.042707648,-0.013492177]', FALSE), +('db5a503f-ec26-413d-9f29-0953e25bf77f', 'fd7a1902-7366-49fd-9c33-06bf9fdce547', 0, '# BOR Vault Sync Unit + +The Brain-of-Reese vault syncs from `obsidian.container` on `rack7-pbx2`. + + [Container] + Image=ghcr.io/reese/obsidian-bor:2026.7.14 + PublishPort=127.0.0.1:18765:8080 + Environment=VAULT_DIR=/vault/rack7 + Restart=always + MemoryMax=2g + +- The vault is a bind mount from `/data/vaults/rack7` (Btrfs subvolume). +- Only `rack7-pbx2` may hold the vault — do not clone it to another node. +- Image tags are date-stamped; bump by re-pushing + `ghcr.io/reese/obsidian-bor` and restarting the unit.', '[-0.034927994,0.03581605,-0.015919589,-0.014969843,0.023104362,0.003942424,0.023816373,0.013501817,0.0017010501,0.0048210155,-0.014216858,-0.00841087,0.011326528,0.03372647,0.0122917425,-0.0017838015,0.015251865,-0.006387349,0.001205264,-0.053797588,0.00924057,0.011510034,0.03063006,0.03910991,-0.01582097,0.018148659,0.0036202718,-0.012048634,0.0029272123,-0.0075285933,-0.022817668,-0.004744225,-0.021465147,0.029683432,-0.015999332,0.0070492104,0.027701573,-0.0029718257,-0.08239857,-0.14185132,0.009774235,-0.010739144,-0.03322081,-0.0014771614,0.03387035,0.0038823893,-0.053461846,0.010744604,0.010858496,-0.008584236,-0.046623558,-0.0038832827,0.009877069,-0.005649265,0.001220409,0.008942952,-0.036843635,-0.055596992,0.014242529,0.004140609,-0.025510168,0.007221458,-0.003310579,0.007829745,0.00090325845,-0.030501219,0.03241062,-0.068120405,0.0074142376,-0.012155859,-0.004025893,-0.017773205,0.015408123,-0.008137845,-0.0006938982,-0.00038841873,-0.0014751343,-0.0024646719,-0.0055454043,-0.02645798,0.049045645,-0.0033834437,-0.023975251,-0.021580542,0.004554619,-0.0070732674,0.0037938883,0.02056934,0.025284199,0.025843551,0.0012510123,0.01985017,-0.011078139,-0.034818042,-0.019823713,-0.012800928,0.015459423,-0.0062580258,0.013468766,-0.037364002,-0.0046948087,0.018266993,0.0111319395,-0.017167997,-0.013460256,0.033160325,0.015582079,0.010964723,-0.0067386436,-0.02029143,0.023540372,-0.032809947,-0.01278382,-0.028434193,0.027994934,-9.934851e-05,0.0054859486,-0.016275441,0.038697064,0.041745868,0.0018829855,0.018350087,-0.028227508,-0.022418717,0.0048902584,0.031447895,-0.028224263,-0.026244937,0.028053997,0.0063617914,0.0064196074,0.017052472,0.032934334,0.02551254,-0.012396483,0.008322405,-0.01675726,-0.0594679,0.008667546,-0.034908213,0.02048087,-0.024542347,0.009340499,0.014854106,0.035751,-0.06002764,-0.00024268652,0.0017722582,-0.029558584,-0.014348443,-0.024038741,-0.02226877,0.01643164,-0.015006683,0.0070720753,0.021601737,0.005491154,0.002736049,-0.003446433,0.017922994,0.00045934983,0.014640768,0.04566964,-0.004243714,-0.033306725,-0.020363826,0.018427612,-0.005393921,0.016081298,-0.013078507,-0.012250547,0.0012059341,-0.023743955,-0.01735065,0.04971684,0.040711332,-0.00091828936,-0.0060869413,-0.0058863303,-0.038194142,-0.023159686,-0.02480007,0.030541109,0.011836081,-0.007980738,-0.034721334,-0.008338749,-0.023009492,-0.014351332,0.0066233804,0.024081068,0.0025688896,-0.0059153754,0.01130356,-0.030011402,0.017857466,0.010958422,0.051137388,0.0071478607,-0.00026991792,-0.0064783962,-0.020495452,-0.03674646,0.031269073,0.012417582,-0.019585336,-0.016818471,-0.010990102,0.038683444,0.0031920045,0.05009478,0.011479679,0.009833807,0.007060671,-0.011554308,-0.038555462,0.022950832,0.00073681347,0.0043560914,-0.0018660291,0.0018133254,0.0018565704,0.01219116,0.032774955,0.06257339,0.0438672,-0.031071296,0.012840099,-0.02600756,-0.0011557054,-0.03024176,-0.009873496,0.0073004523,-0.020450056,-0.02123496,-0.07365904,-0.017470611,0.037297282,0.013071751,-0.008681177,0.02545702,-0.021986995,-0.014516656,0.021261888,-0.027722947,0.018766994,-0.009598153,0.018443223,-0.033945188,-0.025104133,0.006805151,0.013808302,-0.026093887,-0.0015227891,-0.00022503512,0.0368062,-0.031463034,0.024668295,-0.031084478,5.252025e-05,0.0104905395,0.013140671,-0.0036925406,0.025114698,-0.0047284137,-0.003733264,0.0077099847,0.0014369407,0.0095134815,0.02093328,-0.009338527,0.021841722,-0.013798292,0.003582863,-0.017940491,-0.044529535,0.05095362,0.0113113625,0.035331346,0.032491628,0.030405147,-0.02602559,-0.023942523,-0.030100279,-0.008982121,-0.03061812,-0.021948313,-0.016310932,0.01389326,-0.01982524,-0.014128104,0.040859386,0.0009933395,-0.010045633,-0.036346573,-0.025849266,0.022235803,0.008432182,0.021959804,-0.0006165535,-0.012034408,0.019796815,0.016294055,-0.021048423,-0.016938334,-0.04498977,-0.073088095,0.022255644,-0.01535786,-0.01053818,0.0070896843,-0.0031272606,0.0014503731,-0.0055055562,-0.006096765,-0.004004879,0.04878048,0.008321836,-0.02321705,-0.019729717,0.0025504213,0.014843679,-0.0013751044,-0.0024958656,-0.03221714,0.056195628,0.023518246,0.009394448,0.017034654,0.019863548,0.017010814,-0.025170686,-0.007096249,0.04200081,-0.013628967,0.0030979656,-0.015414722,0.02127552,0.0473957,0.05501603,0.017582215,-0.0053943573,0.030755427,-0.0010197068,-0.017840706,-0.00647113,0.014630894,-0.026355065,-0.0034447536,0.0034833937,0.0384957,-0.004013649,0.025669921,0.0072445357,0.0015347019,0.037597157,-0.018969614,0.0065296325,0.008015431,-0.017251661,-0.053151026,0.037321877,0.014596314,0.033343803,-0.029850086,0.007023303,0.03534467,-0.041505016,-0.042219914,0.05349588,-0.022652218,-0.0034080723,0.0324992,0.0022214917,0.05529833,-0.0023045677,0.009634192,0.008721681,-0.016947826,-0.025604747,0.020484015,-0.0065855626,0.0077140736,-0.010589768,0.020519458,-0.017926542,-0.004567926,-0.04570518,0.0367822,-0.0035985915,0.0085488,0.012377435,0.029772595,-0.016199298,-0.012180007,0.018997082,0.021008227,-0.016596287,-0.03589979,0.0029481275,-0.021845844,-0.0013696477,0.008972326,-0.01957745,0.00883342,-0.01253184,-0.0034841967,0.57306767,-0.0032351129,-0.013690586,-0.034050316,0.0064615267,-0.01587463,0.012486392,-0.009032403,-0.028841244,-0.028569816,-0.0004245411,0.005905909,-0.011475815,-0.0001353641,-0.023589443,-0.019442916,0.030834086,0.014507823,-0.006482109,0.022787604,-0.028879074,-0.022945445,-0.051563658,-0.0036393376,-0.020084938,0.016628541,0.028767334,0.021255357,-0.018766914,0.03657417,-0.028901733,0.0066127963,0.0044203163,0.009212962,0.00026956847,0.0036427632,-0.015466737,0.0035851577,-0.009030128,-0.012019086,-0.0026192348,-0.028529268,0.0002866394,-0.01571918,0.008810382,0.040654767,-0.016903987,0.013192454,0.021249745,0.013782772,-0.016598629,0.029290898,0.018022254,-0.006529287,0.008883789,-0.026399784,-0.015106799,0.0026815126,-0.006119373,0.008163179,-0.008011649,-0.008640337,-0.04463574,-0.043707922,0.015982207,-0.008255912,-0.034364104,-0.022291744,0.0024028276,0.013516474,0.0075456756,0.015278781,0.018974092,-0.027498784,0.009490068,-0.0054086433,0.06594973,-0.03725581,-0.01289325,-0.0012455803,0.0015592515,0.00866639,0.0075154337,0.0066252127,0.042920955,0.016661577,-0.015151891,-0.010291332,0.006063763,0.047120146,-0.00941602,-0.008012047,0.0005263801,0.053926658,-0.004490881,-0.017894903,0.036355518,0.029454352,0.0008446574,-0.01651273,-0.0047027217,0.00031976512,0.0223733,0.011409689,0.022826875,-0.018123332,-0.010348561,0.016192436,-0.00014248735,0.010837452,-0.032986272,0.026756886,-0.045197237,-0.03986081,-0.02272427,0.0041163573,-0.048471455,-0.024005359,0.024394823,-0.0013113092,0.033900462,-0.027647896,0.018593442,0.044482242,-0.011991837,0.038008623,0.01910124,-0.050227463,-0.008769065,-0.024871739,-0.0077622104,-0.040867973,-0.03728654,0.009256649,0.009203407,-0.0011110974,0.06680131,0.018549096,-0.047885194,0.01659111,-0.026744576,-0.033982746,0.014567947,0.010656002,-0.023603523,0.016940711,0.00018650011,0.0028217416,-0.008809087,-0.017893735,-0.016016847,0.004467661,0.006509493,-0.017969986,0.002890076,-0.0032897522,0.0042143343,-0.017786387,-0.008839755,-0.015757803,0.0200543,0.019841857,0.05403403,-0.030210648,-0.020458072,0.004502997,0.0077428753,0.024568256,-0.022551224,-0.01430269,0.015123038,-0.023150347,-0.013032639,0.056927964,0.008507384,-0.021907764,0.0025054137,0.0065117464,0.014373521,-0.0449918,-0.0003840058,0.014238386,0.00086204906,-0.023373311,0.016051898,-0.0059168735,0.0019287328,0.032397218,-0.020736396,-0.030808877,-0.021575008,-0.010048529,0.053430382,0.0054600923,0.0021110189,0.02053228,-0.0036281934,0.013941913,-0.027024621,0.030725488,0.0018790467,0.012110993,-0.073496714,-0.01966684,-0.037439853,0.04212979,-0.019169543,0.013056914,-0.0284626,-0.021363357,-0.016915455,0.0069531086,-0.039375894,-0.05684862,-0.022147201,0.008239587,-0.0067893066,-0.014917293,0.015110488,-0.022877451,-0.03524684,0.011508828,-0.014718321,0.00534065,0.01911085,-0.027969457,0.0018609591,-0.019459222,-0.010987313,0.010948302,-0.005882144,0.0039054316,0.04652691,-0.00069903955,-0.0016362006,-0.011965807,-0.024347456,0.0064053247,-0.009855416,0.031972595,-0.008248491,-0.02863889,-0.008155853,-0.016785147,0.015404648,-0.007909812,0.0014813227,-0.002549537,0.044576954,-0.028579475,0.0135531025,-0.0149551565,-0.005591214,0.02366824,0.025862802,0.0024851935,0.030415133,-0.012238127,-0.04716214,-0.016231392,0.022691347,-0.02482465,-0.011914859,0.023215054,0.031714138,-0.0034040832,0.035612993,-0.009754671,-0.035605766,0.010992588,-0.008304019,0.0061131543,0.0011883129,0.015247001,0.02441507,0.015327133,0.018907811,0.0073393765,0.03520345,-0.014841351,0.017741553,-0.05597474,-0.035327643,0.0032599706,0.00978332,-0.048760027,-0.00044644915,0.0054810224,-0.009341119,-0.014660195,0.020735323,0.0013525415,-0.019843668,0.024597261,-0.008170793,-0.01494519,-0.0075685107,7.96766e-05,0.0028567628,-0.009174722,0.049673893,-0.050565634,-0.0005792455,0.017407771,-0.009163939,0.047892693,0.01894894,0.02574025,-0.01170768,0.0058390475,-0.008103895,-0.030417722,-0.007060908,0.014635748,0.00228361,-0.036417432,-0.0010232927,-0.014784385,-0.01834012,-0.0028734533,-0.004318586,-0.010236185,0.0021429441,0.015617409,0.4834761,-0.012636616,-0.022687469,0.020701395,0.0051027783,0.022181049,0.03529972,0.0351972,0.00046523323,-0.0076142275,0.036174092,0.009535818,-0.010017993,0.026272342,-0.006706261,-0.03577366,-0.018832838,0.03730758,-0.011704337,-0.01835008,-0.011085872,0.026068581,-0.003491386,0.0051502106,0.0063009546,-0.032249182,0.019407172,-0.008202471,-0.038159885,-0.021650437,0.0309004,0.0035308886,0.0038892007,0.04404218,0.028102491,-0.005017166,-0.015273466]', FALSE), +('14ca895a-2048-45e9-a4f0-900c1525080e', 'f24790a5-dc20-4a28-8f96-37f4e6db1cfb', 0, '# Restic Backups for Rack7 + +Every config and document on the cluster is backed up nightly with +restic into the minio repo `minio01:/backups/rack7`. + +- Machine ID: **rbm-8842** +- Password: `op vault view rack7/restic` +- Schedule: `17 2 * * *` (02:17 nightly) +- Retention: `--keep-daily 7 --keep-weekly 4 --keep-monthly 12` +- Prune runs only when the repo grows more than 5 GiB. +- Restores are tested quarterly; the last dry-run passed on 2026-07-01.', '[0.03765728,0.038334936,-0.046351578,-0.018821554,0.013876744,-0.026855422,0.027965782,-0.014691262,0.04054008,0.012495218,-0.032717604,0.020404503,0.029641442,0.056214623,0.0041096895,0.0021433483,0.013298268,-0.011906581,0.017864369,0.0043434827,0.003455686,0.003213155,0.009039273,0.014017991,-0.0013855388,-0.0086553,0.02374252,0.006526439,0.022547401,-0.0033297495,-0.0014988133,-0.0023512796,-0.0014143041,-0.02824291,-0.029488139,0.047540624,0.004302925,-0.014533925,-0.044490933,-0.18681955,0.0060919416,-0.0043272353,-0.0061544185,-0.0134371165,0.016437095,0.010977944,-0.03827594,-0.010501733,-9.103888e-05,-0.017213993,-0.052952036,-0.01814852,-0.01681489,-0.02458776,-2.7317636e-05,0.012569827,0.000104241524,-0.018048206,0.0056127138,-0.02190811,-0.009739061,0.017429793,0.0024581996,0.009735135,-0.018552558,-0.024861272,0.022891004,0.020569192,-0.028005533,-0.022450544,-0.010317253,-0.011980621,0.032764282,-0.011709641,-0.02451471,0.0010362185,-0.0112718195,-0.00058853626,-0.026112061,0.026495771,0.0394547,0.0063182334,-0.004829977,0.023855412,-0.008800795,0.00013841609,0.059158158,0.021808602,0.020425223,-0.011426819,0.0038955163,0.006198093,0.024862297,-0.03499104,-0.009743883,-0.0052778074,0.003565241,-0.015560559,0.018064352,-0.011610284,0.0213316,-0.0020373324,-0.026138688,-0.006718646,-0.02382629,0.03147264,0.01057506,0.015455392,0.030844104,-0.00040196432,0.043418042,-0.011088326,0.01047154,-0.009914557,0.04262582,0.005975505,-0.023595681,-0.027923705,0.023374308,0.014240866,-0.023139395,0.0132414745,0.012261659,0.012351101,0.00759727,0.010675114,-0.042177144,-0.036517777,0.024029138,0.0008647431,0.045483645,0.016919408,0.0154435625,0.02498494,0.024675457,0.01296122,-0.022764636,-0.03074655,0.0023986194,-0.020427136,0.019278254,-0.02343757,-0.0045941286,0.012369004,0.008186335,-0.055012554,-0.010311422,0.026978279,0.0070707668,-0.0077663674,-0.01688138,-0.014623421,0.019912325,-0.0003497982,-0.020409018,0.0112192305,-0.0075505367,-7.7092336e-05,-0.027347475,0.0071208742,0.0047974004,0.004188812,0.0587663,-0.0047277417,-0.038093217,-0.055897597,0.022347312,-0.01999832,0.039594453,1.8601851e-05,-0.014344009,-0.008892714,0.0007157801,-0.0034329656,0.036234237,0.018580243,0.02141671,0.012906504,-0.026177874,-0.035237502,-0.015372497,0.0026581096,0.023054581,-0.0072749895,-0.023454232,-0.0302729,0.015159943,0.018423636,-0.010861041,0.0068292604,0.0036673471,0.00458393,0.020198898,0.020174254,-0.044208188,0.0024966907,0.02225607,-0.008997944,0.00027228252,0.018289514,-0.02137625,0.010978942,-0.01478448,-0.019089295,0.009514669,0.00135242,0.017126871,-0.011768444,-0.0036299368,-0.0071196756,-0.0039458284,0.020854903,0.021303082,0.003383208,-0.018576924,-0.0018162059,-0.0062110205,0.009581173,-0.00065892516,0.013272138,-0.031364355,0.038910545,-2.9999776e-05,0.027097302,0.054840326,0.01879512,-0.012150908,0.03438013,-0.019233715,-0.0253048,-0.017594246,0.029802598,0.030668894,-0.01806078,0.0024415858,-0.039311863,-0.008764049,-0.0018331626,-0.015291746,-0.040220007,0.013071065,-0.0029009392,0.012560927,0.012128048,0.0033504188,0.0018645789,0.030299652,-0.0033257708,-0.017664924,-0.0063763475,0.012735351,-0.014566946,-0.016044049,-0.0027962588,0.008364955,0.043264057,-0.019038687,0.028206872,-0.039978486,0.012162933,-0.014637838,0.007937867,6.3552e-05,-0.0014468052,-0.018153032,-0.012141031,0.018178517,-0.0019470536,0.02165357,0.03599511,-0.047247127,0.014983349,0.007325488,0.007896805,0.0029061085,-0.005892867,0.057212666,0.0003108842,0.0049345368,-0.01017636,0.07777481,0.034172833,-0.013770022,0.0104009025,-0.0067824996,0.02633782,0.051740896,-0.03785145,0.010126083,-0.022845639,-0.018558517,0.028088631,0.022172028,-0.021721382,-0.02802638,0.002701408,0.00631969,0.023341086,0.0050143334,-0.005936248,-0.00649931,0.052228,-0.021869704,-0.026436927,0.010057275,-0.0012251851,-0.021630067,0.014995222,-0.020993529,-0.022995675,-0.008903742,0.014099872,-0.006660026,0.0027657822,-0.013600488,-0.0005519864,0.010083361,0.020859107,-0.028482731,0.02335078,0.005408595,-0.0022911269,-0.010747963,-0.004863878,0.021576466,0.014350394,0.0084841475,-0.011579432,-0.00840245,-0.0029425886,0.046152513,-0.015531281,-0.025707778,0.017022155,0.0010964996,0.0033316745,0.0028006227,0.0022403777,0.0029772378,0.04995672,-0.003450879,-0.0030131864,0.030433359,0.049474545,-0.011020551,0.015403584,0.024361098,-0.0170686,0.020266196,0.015697118,0.016095487,-0.01418157,0.03101593,0.019279985,-0.013348444,0.029173823,-0.022153415,-0.023290837,0.015863357,0.022105897,-0.08664832,0.0052066026,-0.050512716,0.029474081,-0.0005393885,-0.00729477,0.0056055356,0.011223275,-0.009768521,0.0043229507,-0.015051219,-0.008070263,0.022394596,0.004025711,0.04887875,-0.0099531645,0.012347623,0.0074809515,0.0065537007,0.010653278,0.04619585,-0.015801083,0.009214493,-0.006615826,0.0067170607,-0.019312533,-0.025120696,-0.02150698,0.046160415,-0.031438716,0.018355371,-0.010104739,-0.014449082,0.0023550948,0.0034354993,-0.0010040792,0.030163309,-0.009813039,-0.0011970354,-0.007269155,-0.012104716,0.0004576431,-0.027927483,-0.0112438835,0.007711328,0.0072407,0.031491797,0.5855954,-0.011705483,-0.002519899,-0.011646644,-0.009687139,-0.02810026,-0.017851278,0.01355212,0.019514717,-0.017334336,-0.013329,0.007299452,-0.02475016,-0.017193284,-0.029050875,-0.034359504,0.030590521,-0.0040367236,-0.011627629,0.021701759,-0.015861968,-0.011391526,-0.007437609,0.016650945,0.012666709,0.009692704,0.032083657,0.023919018,0.011844009,0.014596554,-0.022851193,0.018428052,0.023641137,0.028354498,-0.012140154,0.00068355975,-0.00017404395,0.015791805,-0.027252026,0.0068805343,-0.03880202,-0.0014438682,-0.030657245,-0.05042099,0.016152978,0.020362753,-0.014427749,0.004222905,0.032379612,0.0024853244,0.002615424,0.00065739296,0.034098763,-0.0077121104,0.028807469,-0.02194229,0.010225607,0.006194918,0.0075616282,0.0018466074,-0.008868893,-0.026673285,-0.054886766,0.0061955983,0.027999042,0.046393447,0.011631195,-0.023513779,-0.005969504,0.018104352,-0.015129896,-0.008477863,0.04764666,0.0015734643,-0.0044234754,0.02583787,0.018319072,-0.02941819,0.008713474,0.0028772072,-0.02296738,0.012660091,-0.008690366,-0.0027357715,0.037066355,-0.0020266322,-0.0049187583,-0.0186728,-0.020976955,0.030019846,-0.03137183,0.0036706415,-0.02170068,-0.020383446,0.012754387,-0.015834805,0.032624964,-0.0123627735,0.016845996,0.0008380769,0.013839545,-0.04854779,0.01801363,-0.011402668,0.014450469,0.011496518,-0.014589295,0.038672924,0.014880273,-0.009208022,-0.020215582,0.012070364,-0.010717352,-0.031394474,-0.029608568,0.0059334827,-0.04941082,-0.027466664,0.0028551635,0.024320604,-0.0067758746,-0.010788156,0.002434749,0.00024038937,0.0038323135,0.028561682,-0.007280207,-0.029512528,-0.019200042,-0.058666863,-0.009878556,-0.004981913,-0.03252119,-0.018675433,0.015794085,0.03382888,0.012079236,0.023161078,-0.055957552,0.029172637,0.017497877,-0.04882249,0.001005362,0.007224797,0.025171544,-0.0041955407,-0.018064879,0.02599292,0.008141949,-0.017698115,0.0009992578,0.018612523,0.029167352,-0.017511941,0.047830738,-0.0016970604,-0.03342456,0.002256909,-0.040389184,-0.015719287,0.017932897,0.025826607,0.02617294,0.026908452,-0.026747135,-0.0068037524,0.010618854,-0.008336077,0.0012758428,0.029316187,0.05570935,-0.0125425095,0.00075464207,0.047359694,0.014396019,-0.0348266,0.020926295,-0.012599121,0.043956477,-0.06318605,-0.027331065,0.010607075,-0.00035537782,-0.0048795515,-0.02423879,-0.016178101,0.02487686,0.009964757,0.01755477,0.019971088,-0.007599422,0.01384676,0.023156084,0.010532891,-0.025033776,0.032559227,-0.012488059,-0.008000905,-0.019233895,0.029618016,-0.042143576,0.034648743,-0.08001428,-0.02396177,-0.009797746,0.04212926,0.016658954,0.010214039,-0.014485462,-0.0069744117,0.010182965,-0.015897593,-0.04123628,-0.013281543,-0.025925653,0.017538581,-0.012467193,0.027845053,-0.0056426544,0.01452097,0.0007248078,0.021703148,0.011604538,0.013004888,0.034938097,-0.041922428,0.00980726,0.00086455996,-0.0016896203,-0.0021795812,0.038065806,0.0126470225,0.027638435,-0.005214372,-0.022019595,-0.03696419,0.00915007,0.016050981,0.0023811671,0.001536581,-0.010900103,0.005151981,-0.014749812,-0.01295987,0.022595461,0.010873864,-0.007490829,-0.0042017633,0.006805323,-0.03668042,-0.007326009,-0.026846098,0.02109508,0.028364006,0.0038840715,-0.018318992,-0.039246906,-0.038382415,-0.039409768,-0.020308152,0.0070075803,-0.05031155,0.008024022,0.046404373,0.022979999,-0.0033566854,0.013772428,0.010950262,0.013604902,0.025332538,-0.032813415,0.01024245,0.013602661,-0.0031171837,0.042402614,0.0107318,0.0012717372,0.025204852,0.06796378,-0.033957534,-0.009672578,-0.018721519,-0.026907887,-0.0070482036,0.0213326,-0.04347461,-0.010013564,0.01074703,-0.015149851,-0.017510485,0.013982754,-0.012870458,-0.0028808555,0.018362237,0.009648416,0.007982275,-0.006894674,0.023263844,-0.003854283,-0.018210435,0.025481757,-0.020052627,0.00837186,-0.023932552,0.026130382,0.052231703,0.0111993365,0.01618058,-0.012195557,-0.005369019,-0.011121801,-0.004454871,0.008454058,-0.0151241,0.007711219,-0.012282985,-0.009167551,-0.045043703,0.0052505317,-0.0066139363,-0.047352266,-0.0054119425,0.01232257,0.00934875,0.48089156,-0.014909598,-0.052889615,0.032320537,-0.008179006,0.027554596,0.006773632,0.006471981,0.0010383184,-0.005128439,-0.0014304385,0.038950432,0.00065187796,0.036422927,0.0013785404,0.012022498,0.020414976,0.043646295,-0.026806211,-0.018933928,-0.01184762,-0.00021922585,-0.035630666,-0.006336042,-0.01070482,0.016082479,-0.0015896712,-0.0039193165,-0.027802156,-0.021763721,0.03351918,-0.009985709,-0.012559996,0.026368473,-0.029675566,-0.030700319,-0.0033530314]', FALSE), +('759eadcb-ae4d-4305-835f-18adca4f886a', '1a49e6a0-dbaf-4210-8266-81aac216fb42', 0, '# Qwen 3.8 on llama.cpp (pbx-node3) + +The GPU box (`pbx-node3`) serves Qwen 3.8 through llama.cpp. + +Working launch line (verified 2026-08): + + ./llama-server -m qwen3.8-30b-a3b-instruct.Q8_0.gguf \ + -c 32768 -ngl 99 --mlock --threads 12 -sm layer \ + --cache-type-k q8_0 --cache-type-v q8_0 \ + --jinja --port 18180 + +- Context 32768, KV cache q8_0/q8_0, prompt cache persisted to + `/srv/llamacpp/cache`. +- First-token target is under 400 ms; sustained throughput about 28 tok/s. +- Do not add `-ctk f16` — it doubled VRAM usage with no quality gain.', '[0.004906916,0.006456007,-0.007188873,-0.0009238908,-0.000118610325,0.0041262177,0.034794684,-0.010512289,0.046363723,-0.000606719,-0.0150095485,-0.026422955,0.0041964194,0.015166408,0.022708891,0.0011259858,0.028386818,0.033530004,-0.000272862,0.0044750404,0.011663354,0.02666821,0.008705275,0.005409874,0.009979055,-0.0055155237,0.0023672055,-0.0145913735,0.046046358,0.019987473,-0.0053705187,0.016608628,0.011224631,0.021290213,-0.01004889,0.02518744,0.050391167,-0.02405134,0.00058293005,-0.124092765,0.019886658,0.016166205,-0.012361832,-0.007074048,-0.0053084227,0.026913222,-0.018272342,-0.013375628,0.011152763,-0.028163211,-0.04226925,0.03804625,0.008183197,-0.0020625778,-0.0021609538,-0.015395272,0.03717305,-0.07384544,0.026139624,0.027039947,-0.010458923,-0.01054288,0.011398656,0.041775715,0.016047446,0.0033026396,0.005185916,-0.0854565,-0.016121343,0.01755088,0.038015246,-0.0136615215,-0.011892471,0.014911134,0.013989346,0.001857857,-0.0013364337,-0.009718968,-0.061917517,-0.035037667,0.01738148,0.034213133,-0.006054879,-0.012983797,-0.035788544,-0.056444593,0.040929683,0.011836732,-0.012147225,0.0029661932,0.04569166,-0.018594246,0.0010035214,0.008013796,-0.02038564,-0.00055973046,0.014162515,-0.022119664,0.024522541,-0.0048128483,-0.015942382,-0.0013849332,-0.00053557387,-0.02084357,-0.0213113,-0.009068833,0.009994138,0.026871547,0.005815414,0.01602612,-0.010167179,-0.0166093,-0.009444927,-0.023251846,0.021124298,-0.00674383,0.00017626733,-0.022481265,0.008221531,-0.015372913,-0.058682777,0.0018473851,-0.008022528,-0.028758377,-0.0036108366,0.015999116,-0.0063405107,0.009805578,0.01059827,0.022497129,0.018912321,-0.0034235634,0.005937667,0.021929383,0.0018963979,0.011462979,-0.044259317,-0.045317836,0.027230069,-0.030520419,0.016192254,-0.006736952,0.011794924,-0.009808151,0.011587667,-0.027761698,-0.01532937,0.003698323,-0.06661423,0.002715809,0.0145380115,-0.010483502,0.019942906,-0.005093028,0.0051621944,-0.029352557,0.009237764,0.0030812006,0.0052176192,0.03641057,0.03355945,-0.011518262,-0.0135680055,0.01995512,0.00012003938,0.0064016315,-0.004795992,0.017724808,0.026190061,-0.0044881916,0.010012445,0.037060056,0.0015625969,-0.040955182,0.009580645,0.03476194,0.015384619,-0.041615143,0.014988771,0.0036535633,0.00096626824,0.0049872333,0.041760735,-0.012362016,-0.046003405,-0.018122712,-0.025817504,-0.031042315,0.009928874,-0.013900935,0.013260691,-0.012305741,-0.031081388,-0.013502392,-0.015836122,-0.02869068,-0.001068602,-0.015398816,-0.0332364,0.0403027,-0.0062508886,0.005213992,-0.008876871,0.029584307,0.009084996,0.03537422,-0.012121749,0.0009489513,-0.0003954117,0.0070037046,0.020933313,0.0136353085,0.006504187,-0.031617552,0.002992829,-0.0046658325,0.031578876,-0.01679145,-0.022937503,-0.0036870195,-0.022594174,0.0059498455,-0.0056773047,-0.0025736475,0.052146327,0.00893569,-0.010093247,0.027326731,-0.013973046,-0.03487444,-0.0028272849,-0.03416152,0.0012509516,-0.02789542,-0.013947732,-0.114633806,0.014450892,-0.009747401,0.018876895,-9.051834e-05,0.026701575,-0.0025911883,-0.014321548,0.018565923,0.00718232,-0.0052945935,0.006750384,0.02041332,-0.043238882,0.0012280531,0.00025791503,-0.03763744,0.026372131,-0.02456068,0.02276994,-0.00022850574,-0.013499884,-0.03020725,-0.0007399498,0.010689958,-0.015193351,-0.01644527,-0.016917335,0.0050319163,0.016723877,-0.0054169255,0.024451993,0.006997635,0.02882798,0.032276236,-0.06018527,0.033994816,-0.010552437,-0.0083699925,-0.03586196,0.0021914735,0.029977042,0.0018355238,0.007109248,-0.03225808,-0.009911548,-0.053890295,-0.009326061,-0.03306934,-0.023082633,-0.01059039,0.029539904,-0.013281995,0.013006165,0.009475907,-0.022196928,0.049717486,0.014863898,0.009604583,-0.03591369,-0.012478122,0.004377259,-0.0061541484,0.020670006,0.01373235,-0.016809946,0.010334824,0.014988906,0.0040431796,-0.041119885,0.0127653135,0.0051707076,0.014419583,0.00650896,-0.010287407,-0.008795972,0.0018323881,0.010770522,0.0049167215,0.00936526,-0.02508502,0.0072778235,0.04563838,-0.013496911,-0.0173033,-0.015317526,-0.007889284,0.03175395,0.002003391,-0.0021924663,0.030394852,-0.00069624675,0.020704044,0.027886068,0.02762333,0.014035284,0.01654181,-0.03899793,0.02087429,0.016071657,-0.0062754885,-0.021844983,0.028700225,0.03766843,-0.046431784,0.012101235,0.017013961,0.02747407,-0.007655756,-0.013407637,-0.033471037,-0.014546696,0.028630817,0.008982008,0.026006,0.01677444,-0.03471433,-0.0022379234,0.0055728946,-0.0077810143,0.0013937261,0.017746871,0.021605,0.040962756,0.0070188814,-0.009967747,0.01273787,-0.033534065,-0.005305199,-0.035510264,-0.039379925,0.026744207,-0.008604813,-0.0039082207,-0.0044822954,-0.0088469675,-0.028601604,-8.0912294e-05,0.004470854,-0.020053793,0.03998865,-0.0141425645,0.007797722,-0.0102526555,-0.017722767,0.0686069,-0.009135741,-0.016234249,-0.021621566,0.014535573,0.015754718,0.014164537,-0.019203294,-0.012466663,0.034600537,0.0068200435,-0.03419361,0.0079800775,-0.018447468,-0.031217193,-0.0072390707,0.020659447,-0.008191455,-0.014997229,-0.002165527,-0.0076478436,-0.024402162,-0.023636317,0.02932148,-0.009688069,0.0011310569,0.021694932,0.5715141,-0.0038225024,-0.0016790443,0.021320958,-0.014914242,-0.023419889,0.008144954,0.048406098,0.013591611,-0.012175149,0.008054675,0.0512858,0.0008912528,0.040094815,-0.009734309,-0.012076115,-0.025351707,0.012837881,-0.042196188,-0.03161997,-0.0379239,-0.0005819548,-0.032063887,-0.0005143354,0.03740754,0.02488251,0.024509883,-0.0072609554,-0.0022386592,0.04750714,-0.014558142,-0.0040288162,0.018878523,0.03327417,-0.004163784,-0.017925752,-0.012998249,0.020356508,0.023633389,-0.018931953,-0.027854599,0.006231788,-0.01153814,0.020663124,-0.0017388125,0.067935705,0.029296348,-0.007780076,0.016128931,0.011073908,-0.049259424,0.01269973,0.023268139,0.016713535,-0.015788209,-0.012492067,-0.015602908,0.008636031,-0.00024210043,-0.007579757,-0.031625237,-0.010611543,-0.030509407,-0.020369291,0.029296048,0.006953915,0.0014250218,0.014339599,0.004191337,0.0067475755,-0.014606891,0.019333253,0.010553306,0.0047668894,0.004948881,-0.021775356,-0.023305146,0.02372491,-0.028523874,-0.015274663,0.010051219,-0.007282009,-0.010038693,-0.032733105,-0.0020153876,-0.009332712,0.025308426,-0.0018304805,0.017502509,0.023978205,-0.0032532897,-0.036123194,-0.0053018923,0.06226937,-0.0024003258,-0.018078387,0.002183948,-0.040361945,-0.028334303,-0.018242473,0.0006282814,0.010286075,-0.0062547335,-0.012389634,0.01196164,0.01271925,0.0103054745,-0.012717946,-0.050431717,-0.038263008,0.011334124,0.003481882,0.010076823,-0.00904898,-0.025005259,-0.008100363,-0.0038964872,0.024797121,0.0044426275,0.019206045,0.0032552343,-0.0588058,0.0055935197,0.06473668,0.015533918,0.04567951,0.024283042,-0.032287795,-0.005871,0.0030397933,0.0024484268,-0.052880578,0.0044671185,-0.0021110012,-0.03313513,0.006123912,0.009387669,0.035467263,-0.0075831297,-0.010714004,0.0027596888,-0.054168034,2.0219544e-05,0.015232016,0.0016128462,0.02699787,0.0154918665,0.0077593937,-0.029063925,-0.009622622,-0.020289576,0.0052438932,-0.017425237,0.0008231685,-0.022507673,-0.01075652,-0.016170673,-0.0016022251,-0.02438394,-0.04417805,-0.039179347,0.008670499,0.06376034,0.040335864,0.027618492,0.009137288,-0.029111417,0.028033702,-0.00343559,0.0040178667,0.031317253,-0.064813405,0.01373273,-0.020199584,-0.015780427,-0.04338776,-0.020906894,0.012748846,0.015861813,0.0036612353,0.032253806,0.028695056,0.029775364,-0.012596399,0.01709375,0.008642521,0.011716538,0.027455112,0.01852999,0.031462297,0.010621819,0.004659449,0.027314827,0.018217443,-0.012133268,0.012184392,-0.010667446,-0.010947791,-0.02931279,0.017184244,0.0018991032,-0.008176583,-0.040296547,-0.007439916,-0.014969276,0.024563216,-0.0028976062,-0.005789192,-0.017361993,-0.0038953219,-0.0126501275,0.017369047,-0.045210723,0.018072907,-0.02953176,-0.009939644,0.0016326611,-0.06367325,-0.0047002463,0.015472689,0.021914592,0.029067505,0.013700611,-0.008019365,-0.026344938,-0.004926492,0.0069742217,0.0091774,0.03467588,0.010049456,-0.027063357,0.0018104803,-0.027776,-0.04164002,-0.039374765,-0.03470609,-0.029873682,0.015378697,-0.022916965,0.016020175,0.041835174,-0.023922656,-0.00973589,-0.03584754,0.0023531509,-0.00071640615,-0.022200791,-0.0116852205,0.050996486,-0.0067681023,0.024496153,-0.031229932,0.012020029,0.01887921,0.022653103,-0.020136286,0.026000703,-0.012733552,-0.051865578,0.009926211,0.025864415,-0.024490546,-0.045287423,0.03526147,0.0324647,0.023480445,-0.0059160828,0.0004954989,0.043922395,0.0012934246,-0.00218072,0.0017724655,0.0049270755,-0.00024383095,0.008791398,0.025928196,0.035438117,0.012793123,0.07458995,0.00688506,0.019181672,-0.01695006,-0.0146594765,-0.02098825,-0.0076851225,0.006612468,0.02737507,-0.004219136,0.011097702,-0.0152805885,0.09384753,-0.032352034,-0.013140767,0.031971924,-0.0051288432,-0.01625363,0.0031787823,-0.028409956,-0.003950356,-0.01789569,-0.00017963733,0.007979669,0.004672666,-0.002137598,-0.010888451,0.03931264,0.041141845,0.0018557319,0.012479248,0.019799987,-0.020040277,0.016263643,-0.062916495,0.019419322,-0.0011392571,-0.024135968,0.017182056,-0.006468974,0.0006467475,0.0020119678,-0.012808353,-0.020771088,0.0009864348,-0.0048578945,0.47838664,-0.054653436,0.006858096,0.005452959,-0.012132784,0.013347625,0.0021665914,0.02250279,0.017631315,-0.00892203,-0.044655927,-0.0035942886,-0.0150718,0.03142226,0.012312508,-0.031123387,0.018857885,-0.0020205963,-0.0041906005,0.009723671,-0.0053943996,0.008282193,-0.010327774,-0.030658191,-0.020753093,-0.028013792,0.04665689,0.008744662,0.016389638,0.051546767,0.020381214,-0.002605621,-0.0061373413,-0.024535293,0.027562302,-0.051640674,-0.024688333]', FALSE), +('015b7e8e-5d7f-4348-9502-2809a4b102f5', 'ba951767-d744-4e62-bd19-2d947090e58e', 0, '# Uptime Kuma (AIO) + +Uptime Kuma runs on `rack7-pbx2` as the AIO image, listening on +**18443** with TLS terminated by `caddy-rack7`. + +- Health endpoint: `https://uptime.rack7.local/ping` +- Every monitor posts to the ntfy topic `reese-uptime-7` on failure. +- History is kept for 30 days; the database is backed up hourly to + `/opt/kuma/backup/`. +- Lab-iot monitors watch every VLAN 130 device; the shelf watchdog + restarts the container after 3 missed checks.', '[0.038106993,0.018634057,-0.008217301,-0.013628453,0.027404172,-0.03877489,0.0311994,0.02465902,0.0024459895,-0.021807522,-0.038296077,0.024558239,-0.0023262263,0.011050194,0.030026698,0.017113961,-0.0033969188,0.004039134,0.009008223,-0.051173065,0.02592171,-0.003917853,-0.01238643,-0.024053885,-0.00024851924,0.032166224,0.014062944,-0.015169448,-0.005225658,-0.0042016893,-0.01123889,0.0004635895,-0.032697055,-0.017006787,-0.007335916,0.02580753,0.03261475,-0.012524324,-0.05857942,-0.13035922,0.028068826,-0.0004909649,0.008304582,0.00028216033,0.0018224564,0.022837613,-0.046190467,0.0123833185,-0.026489494,-0.0018505072,-0.028140096,-0.0020819786,0.011087048,-0.005066901,-0.0014365623,-0.0036917927,-0.023711855,-0.03588957,0.015389655,-0.017935254,0.0026078268,0.046831407,0.019794863,0.015847689,-0.01030789,-0.008568072,0.009648942,0.011848424,-0.017210871,0.012200696,0.021016102,-0.028046189,0.0010585381,-0.013444968,-0.012422198,-0.017197818,0.005396348,-0.011171766,-0.025050566,-0.017291093,0.047166303,0.0138644725,0.030163022,-0.033566613,0.00094499375,-0.008609101,0.0029411141,0.009440743,0.033943594,0.013803009,0.010265881,0.014866854,-0.00937658,-0.012975772,-0.0067992844,0.024789833,0.025133912,-0.038422156,0.0280066,-0.03585288,0.014918304,0.0065574846,0.017106203,-0.007814379,-0.0039850557,0.020553024,0.012011159,-0.02346571,-0.0051349793,0.007332733,0.033706095,0.00079152815,-0.013978022,-0.02445136,0.022460915,-0.0032079138,-0.024291102,-0.02661807,0.0059516635,0.0069870083,0.02042671,0.05334843,-0.005034359,-0.00956489,-0.003907171,0.002769809,-0.040247224,-0.074619494,-0.0015881418,0.02868011,0.046569843,0.012639592,0.0066075497,0.029720109,0.04744354,0.037766926,-0.005725736,-0.029371332,0.017992377,-0.079285465,0.01878195,-0.056645542,-0.007868872,-0.00208263,-0.012480636,-0.034866847,-0.0021931652,0.011911377,0.019486906,0.021688007,-0.030558916,-0.016631396,0.0072167427,0.018208137,-0.030761741,0.059866942,0.016288664,-0.009572141,-0.029575933,0.058776673,-0.017822789,0.016467273,0.034793973,0.024051145,-0.0079384,-0.039598923,0.010722575,-0.013311449,0.024028081,-0.029127918,-0.014751515,0.049159955,0.022571053,-0.015190259,0.030467868,0.022814635,0.056081712,-0.002271787,0.009412051,-0.008253789,-0.0097564645,-0.01146133,0.034274988,-0.0067151655,-0.03362125,-0.01903806,-0.028452013,-0.02260626,0.013794295,0.0010383719,-0.0116121,-0.0004088451,0.02212328,-0.01430799,-0.03320451,0.013438234,-0.0078630075,-0.04343393,0.050368387,-0.020127948,0.0013781807,-0.005974917,-0.031138388,-0.00606929,0.0017739536,0.029510228,0.00012915762,0.011622922,-0.015467424,-0.012347629,-0.0010018977,0.0708217,0.032622647,-0.033221178,-0.016068736,-0.018218724,0.0075088814,-0.008474871,0.012021168,0.01394918,0.010850891,0.0097159315,0.0010421303,-0.0077235103,0.0018145508,0.02441232,-0.02752355,0.02108498,-0.014134946,-0.019849766,-0.013992006,0.022705596,0.0019783624,0.024398847,0.0226116,-0.039615802,0.002247258,0.010758826,0.021020792,0.031348504,-0.0019311132,0.007912154,0.023376185,0.013901945,-0.004031933,0.00059725385,0.030810928,-0.022914764,-0.046300393,-0.0007079661,0.0018089672,-0.01343276,-0.023964891,-0.023551881,0.04084971,-0.0050511155,-0.034382816,0.007039022,-0.016816135,0.0011618218,-0.019647088,-0.02235321,-0.018496986,0.004418245,0.002015185,0.022616263,0.019669777,0.018710969,0.020171262,0.0065068775,-0.0094575165,0.028560799,0.026498334,-0.018881548,0.01779934,-0.02339102,0.03274112,0.009155856,0.03688592,0.0124018015,0.03710459,-0.014070767,-0.021527326,-0.029835764,-0.031258795,0.015677053,0.010864739,-0.027017793,0.00490162,-0.009072934,0.014188736,0.012163424,-0.010023558,0.027260082,0.0048967893,0.002274717,-0.006461237,-0.003600291,0.025682367,-0.014112495,-0.019908749,0.040578227,-0.007009708,-0.0146240145,-0.018676424,0.0013891037,-0.014643823,-0.021128826,0.00072751916,-0.03504254,0.004105655,0.026931705,-0.007704711,-0.017538644,-0.020946752,-0.0066418652,0.0510803,0.023047732,-0.011718495,-0.013410385,-0.01014068,0.014250093,0.037130404,0.0063563436,0.0067466605,0.025111927,0.023752602,0.0057971505,-0.006658047,0.024181658,0.033148665,-0.06762279,-0.0027979522,0.023139752,-0.00017422637,-0.0010298613,-0.019527595,0.021093024,0.018087953,-0.00981142,0.021309,0.016757656,-0.00061614806,0.043578032,-0.0046561025,-0.005860671,0.00028400763,-0.005222961,0.0066212034,0.007465418,0.04327694,-0.018172314,0.013598587,0.04156662,-0.008201251,0.04050671,-0.0011988352,-0.03066368,-0.02395785,0.02446814,-0.0899048,0.008258288,-0.08213539,-0.011409116,-0.021910544,-0.00015463975,0.02213294,-0.012563223,-0.034270573,0.012813273,0.008907631,-0.017326519,0.024288397,-0.01439124,-0.008639811,-0.0030159368,-0.0046915947,0.01408972,-0.027495638,0.028871214,0.041411635,-0.008411061,-0.010576511,-0.019422347,0.0358918,-0.0035719725,-0.020388497,-0.034472022,-0.030834252,0.008924118,0.01758393,0.015400725,0.0022139917,-0.016835183,0.015300206,-0.016525537,0.0035283864,0.0077783214,0.008913325,-0.0058559845,-0.0035000376,0.005387798,-0.009809309,-0.025696075,0.015413322,-0.025870109,0.032177497,0.5819093,-0.0010938785,0.008852723,-0.040263142,0.017681291,-0.033451736,0.007959036,0.0011315593,0.017408729,0.0009294567,-0.0036882618,0.015779817,-0.013982584,0.001050123,-0.0034167818,-0.035604995,-0.014674744,0.04562627,-0.029904135,0.019736819,-0.05951159,-0.017620193,-0.057386372,-0.011835631,0.0043453015,0.024171991,0.008909662,-0.006362779,0.0060504084,0.0353629,-0.016277611,-0.015112068,-0.016833913,0.01615376,-0.0382774,-0.006274632,-0.012079389,-0.012810141,-0.03127888,0.018849475,-0.03153307,-0.0051420406,0.0475348,-0.018489812,0.027892888,-0.01578764,0.030782497,-0.015763914,0.0057280236,-0.031014316,-0.0040112175,-0.017352164,0.003295842,-0.012723419,-0.00018768809,-0.0036262327,0.021889303,-8.784531e-05,-0.015115497,-0.01563112,-0.012527264,-0.020078734,-0.07101837,-0.0012737609,0.019103205,0.021137692,-0.008841041,0.002043895,0.040060893,0.009378264,0.003924061,-0.008163346,0.008578758,-0.011697094,-0.0020075962,0.03814163,0.012349691,-0.016639309,0.0018154195,-0.012198164,-0.016159683,0.008949393,0.011084626,-0.015990986,-0.0027949982,-0.007574095,0.0025306214,-0.0047155516,-0.0146174785,0.013264729,0.0034637377,0.0052147587,-0.006747056,0.035153598,-0.007931121,-0.015750369,0.037277468,0.024675064,-0.035585944,0.014082659,0.0027795336,-0.037926342,-0.0032182198,-0.028705005,0.023173422,-0.02909124,-0.020845013,0.019356843,-0.04316178,0.009516027,-0.034976315,-0.013217918,0.007926913,-0.03198133,-0.014095516,0.022814764,-0.014098736,0.0071098562,0.03146074,-0.015683679,-0.0463617,-0.013456991,0.036812555,0.04712305,0.018903363,0.029695055,0.032387566,-0.04042986,-0.0016993514,-0.03639544,0.019010685,-0.023286201,-0.036577202,0.020009337,0.009996621,0.0032217293,0.0022028838,0.035814818,-0.02660499,0.00750493,-0.03340861,-0.02957968,-0.008230315,0.0024217288,-0.0015929361,0.009152928,-0.0073593175,-0.00852812,-0.02739346,0.038931727,-0.007273162,0.024249732,0.006339556,-0.02318446,0.0041034175,0.024684688,-0.013802073,0.0027833842,-0.015338234,-0.06604368,-0.019109128,0.01648798,0.032982398,0.004132715,0.004773943,-0.0073432242,0.004852035,0.039872233,-0.00349147,0.028956523,0.02584804,-0.040897533,-0.0043680193,-0.0088932,-0.009021032,-0.047275838,0.012099508,-0.0088350875,0.034433976,-0.05199298,-0.007571556,-0.007182572,-0.02005062,-0.028842174,0.002793788,-0.024149403,0.031235987,0.02877264,-0.008673858,-0.034460764,-0.0036443279,0.004443739,0.045716308,0.014575553,-0.0030546058,0.022689141,0.01857439,-0.029169379,-0.031310964,0.033213694,-0.03351287,0.033085242,-0.08442083,-0.02152903,-0.053839855,0.01509386,0.029370548,0.013033919,-0.009285905,-0.015391071,0.004195543,-0.015951073,-0.038559306,-0.0068741846,0.010166901,0.031821486,-0.0020883817,0.0037500488,-0.028383365,0.025606666,-0.034176596,0.018804858,-0.024123175,-0.014281507,-0.01663333,-0.016329855,-0.020934748,-0.0022689018,0.009574256,-0.031760324,0.0018760365,-0.0024508429,0.0015348496,-0.02809672,0.0008023719,0.007468162,-0.0018622443,0.0043018158,0.023897432,0.024679454,-0.019603085,-0.011716905,-0.06955359,0.0061206846,0.04204292,-0.0027401524,-0.016902877,-0.002100416,0.015941275,-0.026217457,-0.041211523,-0.010453548,-0.00105641,0.01912719,-0.017739847,-0.013034252,0.070064634,4.7160767e-05,-0.038355157,-0.023529857,0.005399347,-0.032659803,-0.023895314,0.025008285,0.014727692,-0.0041582547,0.018034346,0.019056683,-0.013887632,0.034055367,-0.026225945,-0.010004194,0.00937334,0.009988736,-0.008882717,0.012683652,0.06508436,0.029957237,0.041479103,-0.009758344,0.0007367337,-0.02320339,-0.038227025,0.01704494,0.017015269,-0.0033748406,0.0031787073,-0.013438316,0.026753247,-0.007619715,0.09169147,-0.0054680356,-0.027921882,0.032154202,0.03047113,-0.007781287,0.0042037894,0.027654154,-0.0031367168,0.005039456,-0.012611736,0.008875735,-0.0073106945,-0.006767024,-0.0057542394,0.050973188,0.013533343,-0.019092238,0.014786106,0.011991055,-0.009817902,0.004248952,-0.012805401,-0.007791394,-0.013337232,-0.01635509,0.036855973,-0.026635794,-0.002925811,0.018179001,-0.022167508,0.00942091,0.022616746,-0.018871224,0.4632427,0.008429093,-0.024956923,0.018606296,0.0014936472,0.025362318,-0.011488987,-0.009287311,0.0057085142,-0.016507948,0.008631144,0.007817562,0.018385127,0.040530827,0.016500238,-0.036665324,0.017700577,0.011282902,-0.014272382,-0.039289627,0.0048904405,0.004166438,-0.01313444,0.0075444626,-0.034832086,0.004072741,-0.022540577,-0.01589485,-0.016343983,-0.012806487,0.022695752,-0.0017987706,0.019625913,-0.0121589955,-0.026094139,-0.012044631,0.0025452483]', FALSE), +('94b454a9-704f-49a3-b4cd-762fa17584ce', 'bfbb483e-6bdb-4003-bc16-2d0d568156bd', 0, '# Rack7 DNS and DHCP + +`minio01` (10.77.42.31) serves DNS and DHCP for the whole lab shelf. + +- dnsmasq answers port 53 with upstream `1.1.1.1` and `9.9.9.9`. +- VLAN 130 (lab-iot) pool: 10.77.130.50–10.77.130.200, 6-hour leases, + netmask 255.255.255.0. +- Pi-hole runs on 10.77.42.53; the admin UI is on port 18553 behind + caddy-rack7 and uses the blocklist `reese-abuse-v3`. +- VLAN 42 has no DHCP at all — every device there gets a static address.', '[0.043766074,0.008268213,-0.01710485,-0.0046382165,0.030225208,-0.03199348,0.032852776,-0.0055071404,0.0257072,0.018728541,-0.03873035,0.0034708136,0.0248022,0.0026912286,0.0052774935,0.010608225,0.008771976,-0.014569914,-0.0050666607,-0.046476986,-0.011472242,0.02414697,-0.018516341,0.023220444,-0.013250133,-0.018861005,0.014954561,-0.007228172,-0.015357384,-0.0051759486,-0.024091061,-0.0046512843,0.022025064,-0.028588653,-0.005200426,0.0080091115,0.024782471,-0.03220986,-0.04890711,-0.06797152,-0.008803735,0.027355371,0.0069663688,0.012563938,0.04362331,-0.018350929,-0.012396758,0.0036733001,-0.009453971,-0.008144515,-0.025515579,-0.036347046,-0.015589791,-0.030437129,0.009717815,-0.005311048,0.006477808,-0.07324759,-0.0112699885,-0.01351158,-0.010206073,0.004743462,0.0020827253,0.006408182,-0.052159186,0.006531295,0.020306611,-0.021434512,-0.032568213,-0.0029760033,0.013079456,-0.048797235,0.008641751,-0.008754552,-0.022652172,-0.019099623,-0.0069177384,-0.0042825066,-0.027172655,-0.0010543613,0.031318914,0.007914272,-0.007383163,-0.019792655,0.009264685,-0.0023215131,-0.018247379,0.024859896,-0.008834969,-0.009413711,-0.0138238445,-0.028484426,-0.018417466,-0.029000437,-0.01885533,0.0019528009,0.009313697,-0.011796838,0.0274471,-0.017520692,-0.014648522,-0.020761648,0.006995052,0.023912884,-0.023050567,0.031412996,0.024840018,0.014777203,0.029159244,0.027349595,0.0074587925,-0.017217258,-0.006914634,-0.014471661,0.0009218028,0.0011554577,-0.0211972,0.0016432784,0.021307653,0.0066806353,-0.0135766575,0.028474165,-0.015321749,0.01631732,-0.0005187943,0.011491153,-0.019701436,-0.04527791,0.008488596,-0.011196484,0.042954315,0.030161316,0.013765865,0.057107527,0.029154137,0.0061312905,-0.019029785,-0.042948022,0.018442634,-0.05685433,0.026872532,-0.011096675,0.009197282,0.009044441,0.021941496,-0.044963606,-0.00045840524,0.009892188,0.030794438,-0.027430218,0.006882564,0.040612694,0.0012438135,0.009856475,0.0012102403,0.0055569108,-0.011293221,0.019665414,-0.049292237,0.015787447,0.009888138,0.0044494886,0.023391107,0.024905052,-0.0015612607,-0.03614388,0.017702281,-0.0044081407,0.014384505,0.005160562,-0.03321097,0.016609168,-0.008958642,0.0035837258,0.00682772,0.030321248,-0.039351612,-0.017324237,0.0047653606,-0.003392646,-0.0019689754,0.002830855,0.0136955585,-0.028438397,-0.0090612555,-0.052935477,0.015288552,-0.0057930667,-0.00540739,-0.027726462,-0.0077677146,-0.006892877,0.005323184,-0.0046172156,0.0012799741,-0.005010988,0.046018116,0.019230824,-0.0013027508,-0.029754765,-0.020375596,-0.007043063,-0.033851065,-0.027138902,0.013136688,0.029062036,0.0069998316,-0.005068828,-0.034913607,-0.0136361215,-0.02299856,0.023223083,0.030129623,0.040819146,0.025594328,0.021705408,-0.01816703,-0.00053279946,-0.021637492,0.00079660426,0.04739756,-0.0028054013,-0.0023789776,-0.013338099,0.010283096,0.022465028,-0.0035131304,0.009282676,-0.010211602,0.0016965327,0.0018940909,0.030389355,0.007934264,0.005636276,-0.007644454,-0.0857558,0.0054611634,-0.0016585595,-0.005970989,0.018630626,0.025247907,-0.0055820113,0.038266797,-0.013526108,0.008926411,0.010964989,0.030951364,0.00033655082,-0.027704848,-0.022862583,0.017638668,-0.015930932,0.021220453,0.0008934485,0.0029937834,-0.0047784178,-0.011471989,0.03147275,-0.027771678,0.010577349,-0.013014659,0.0024918485,-0.023340395,0.021046089,0.004831906,0.0069617326,0.002668933,-0.004305158,0.020519014,-0.021212982,-0.044613805,-0.008674287,0.013080212,0.040450618,0.015395216,-0.030028379,0.006772105,-0.025548922,0.024743252,0.011514349,0.045467805,-0.0042328076,-0.016948774,-0.026954403,-0.005851749,-0.005807832,1.0762237e-06,-0.003145093,0.033743232,0.02938018,-0.007635926,0.0034733082,-0.036232088,0.00854542,0.0060893376,0.022548439,-0.0024056323,-0.028716378,0.008822268,-0.027878236,0.021252906,0.0017172999,0.05514786,4.2827574e-05,-0.07296501,0.021920508,0.0014435202,0.015537055,0.023283798,-0.03158731,0.009718845,0.0116145825,-0.02471907,-0.047646873,-0.005386141,0.029663773,0.033920094,-0.012379853,-0.027464503,-0.018650275,-0.0026690848,0.039492767,-0.0036009585,-0.017306244,0.021520885,0.030603189,0.0051311147,0.012985987,-0.0018699293,0.00973082,0.039383527,-0.032790925,-0.0097741075,0.038843542,-0.015670452,0.00021363869,-0.008334692,0.010962935,0.00048425992,-0.026424194,0.028170314,-0.032259677,-0.006975912,0.031344943,-0.00981226,0.0153426,0.0093166055,-0.0038299677,0.024640573,0.035917897,0.021027405,-0.011472307,0.00042879177,-0.008440545,0.004021968,0.00059659895,-0.013594903,-0.038992587,-0.021483948,0.0391847,-0.071212105,-0.01624313,-0.07161478,0.019832706,0.009445986,0.0043962346,0.02255764,0.004922065,-0.01968635,0.029848246,0.006845717,0.0017599931,0.013584144,-0.009524928,0.011098757,-0.022344593,-0.00083600404,0.015663788,0.005942135,0.038149353,0.029098306,-0.005873293,0.009649294,-0.009584756,0.029635767,-0.00454657,-0.009767623,-0.026484158,0.014641073,-0.01492723,0.014214555,-0.00797745,0.0018936994,-0.005592862,0.03171235,-0.0061341533,0.044869766,-0.0048887064,-0.012278333,0.010012723,-0.0017650904,0.019172557,0.018121427,-0.03067223,0.010895466,0.0003870211,0.006471973,0.6023521,-0.010224214,-0.0033647968,-0.03346447,0.005188057,-0.02810834,-0.022440495,-0.03033807,0.014072676,-0.006327927,0.015594418,-0.014299896,0.032911897,-0.027897976,0.029692624,-0.032721695,0.036399037,0.0090038385,-0.014052478,0.00013623844,-0.04790467,-0.023411997,-0.038652312,0.015489678,-0.030452998,0.009274954,0.06822414,0.0076254383,0.008560797,0.036581893,-0.024914777,0.008510728,0.0004879265,0.02955506,-0.035326973,-0.0041299425,-0.019974407,0.004936742,-0.0234694,-0.004064151,-0.0124140475,-0.010089179,0.014450427,-0.032545187,0.027244113,0.026577426,0.015949517,-0.02876011,0.0108230505,-0.019433174,0.017231198,0.008400159,0.01292446,-0.045002434,0.0068728547,0.021603066,0.010870134,0.021173593,-0.0046614865,0.009022077,-0.0030338466,-0.034463365,-0.02025389,-0.026410008,-0.0072152345,-0.007272093,-0.0060537537,-0.0009423689,-0.0093816295,-0.008083257,-0.00046785624,-0.006550369,0.049481556,-0.014647713,-0.030391077,-0.010788359,0.010894077,0.010680979,0.008941635,-0.02324225,-0.023490375,-0.01669714,0.0019130278,-0.0065826434,0.002608055,-0.030194908,0.002119365,-0.02562472,0.004623891,0.023793353,-0.011365053,-0.008202208,0.0071092313,0.008003111,-0.038643837,-0.0076534348,0.029846419,-0.024476014,0.030078461,0.012621217,0.016021427,-0.00020343787,0.011149281,-0.015048949,0.035038877,-0.0217185,0.010587708,0.0075150686,-0.02271654,-0.027541013,-0.031080812,-0.009055928,-0.034263298,-0.0325489,-0.015348474,0.007111308,-0.0062726815,-0.007817522,-0.010060094,0.0103109935,-0.044018928,0.013411321,-0.00076320453,0.029446846,0.012900483,0.03507265,0.006193133,-0.04954747,0.001838103,-0.03168089,0.020943288,-0.008294179,-0.018528415,0.012752487,0.0070996475,0.02741226,0.029870592,0.026188705,-0.01437172,-0.0049051563,0.016966676,-0.011792093,0.00021426174,-0.008341727,0.015299256,-0.021147845,-0.016945397,0.00017590939,0.029320199,0.028927026,0.013478572,0.0036022502,0.02726195,-0.0055887816,-0.008450059,-0.008757437,-0.019260693,0.020058917,0.0042868373,-0.0015160295,-0.002872145,-0.0062628463,0.025012622,0.0036828336,0.012303523,-0.0158617,0.017100217,-0.013769509,0.016130028,0.037540685,0.015987793,-0.020633023,0.015575771,0.010050791,-0.003023952,-0.04543736,0.005340395,-0.014334442,0.0077223196,-0.021578236,-0.0027543253,0.0022518137,0.011568921,-0.0059897,-0.0017916665,-0.009132425,-0.0010971461,-0.008777281,-0.031654507,-0.017400937,-0.024582623,-0.02610793,0.027967421,0.02865514,0.001670574,0.028678125,0.0032197407,-0.047192983,-0.013792585,0.016566211,-0.0086553125,0.050987028,-0.05020119,-0.0015182062,-0.035913058,0.04450147,-0.01057383,0.02249772,-0.024707103,-0.028515337,0.019667746,-0.0111929085,-0.023835387,-0.018854076,-0.011392459,0.010873229,-0.008904537,0.026426107,0.0021363415,-0.006802317,0.006184259,0.011442766,-0.02392643,-0.012947141,0.009482151,-0.0013629482,0.011898217,0.0025708613,-0.005449696,-0.010697116,0.009514452,0.013159635,-0.00694046,-0.016157707,0.010450858,-0.015985489,-0.01360821,-0.004391,0.00013375959,0.021850683,-0.027962822,-0.019519884,-0.053522497,0.031952046,0.03192741,-0.00579702,0.015889846,-0.016480858,0.03878994,-0.017906737,-0.0039759316,-0.034583353,-0.011545691,0.06116534,-0.004289385,0.008979378,0.042843256,-0.017903429,0.013662361,-0.02094025,0.03523808,-0.013995591,0.011180017,0.04809339,0.024669511,0.013957741,-9.319883e-05,-0.02442473,-0.0113377515,0.024256384,0.012474251,0.0055188416,0.011308438,0.020176547,0.0009966672,0.030936657,0.0286587,0.04348965,0.02590683,-0.060600754,0.012238857,-0.02836075,-0.023887673,-0.036246616,0.007080137,-0.016368154,0.023602689,0.04733438,0.00988582,0.003251062,0.059142035,-0.007955476,-0.034858666,0.0397159,0.029897396,0.009306649,0.0073847054,0.0105959065,-0.013116307,-0.034661453,0.009853679,-0.017608453,-0.015137664,0.013097831,0.0026103558,0.047205415,0.0021453218,0.011014569,-0.0029053006,0.0015985569,0.003263676,-0.006102252,-0.024554493,-0.037269883,0.0069416384,0.00024147028,0.019531304,-0.025680892,-0.031353604,0.004246378,-0.045436207,-0.012091364,-0.012340569,-0.03543003,0.5002244,-0.011425961,-0.0035828967,0.023595024,-0.041814227,-0.00077907223,-0.0035928218,-0.013520208,-0.028561413,0.0017283343,0.008116408,-0.012604307,0.009190562,0.008559349,0.009975355,-0.023694973,0.03753546,-0.00048597818,-0.045007512,-0.019300142,-0.0050738836,-0.00890933,-0.029716717,-0.0051133167,-0.026718317,-0.018650742,-0.0028775549,-0.0071117547,-0.027398795,0.014013412,0.05247601,-0.0014649841,0.012191497,-0.00017429919,0.012409263,-0.0342259,0.0017729183]', FALSE), +('6a6689de-73fb-4bf1-bcca-43b38ef34f5d', '47655720-be4c-499c-9761-74aa9ca45385', 0, '# Rack7 Proxmox Cluster + +Three-node Proxmox VE cluster on the rack7 shelf: `pbx-node1`, `pbx-node2` +and `pbx-node3`, all running PVE 8.3.4 (build `8.3.4-1-lab1`).', '[0.02959492,0.052665614,-0.027689973,-0.015895989,0.01084465,-0.033955775,0.01392168,0.0016640197,0.023955114,-0.0111087095,-0.05579904,0.014929632,0.006899948,-0.019027466,0.0022540346,-0.017145792,0.021907903,0.013244143,-0.012445105,-0.048263464,-0.0074512726,0.0401701,-5.3522923e-05,0.058279764,-0.018422328,-0.010219375,0.0054376544,-0.011550645,-0.009935651,-0.0027749485,-0.038930636,0.00061912526,-0.09942851,0.03440683,-0.006719167,0.013587467,0.013377621,0.009747497,-0.0344678,-0.22715636,-0.036434982,0.021027548,0.032203887,0.01736491,0.033310045,0.018726513,0.020521998,-0.0047537936,0.000561797,-0.036171276,-0.07128768,0.011700754,-0.0054818247,-0.00930762,0.026298346,0.0038228275,0.041889347,-0.029047323,0.054066446,-0.043122556,-0.0132279955,0.008092102,0.019887641,0.0007597355,-0.038308363,-0.018926471,0.017024871,0.0042884927,-0.044029642,-0.0074252416,0.0402341,-0.035364117,0.016853658,0.013536571,-0.003239673,-0.030383274,0.0016778014,-0.016286658,-0.068657316,-0.0069591533,-0.008408722,0.003860933,-0.019423414,-0.0101329,-0.0099389395,-0.0051821843,0.022580702,0.008660789,0.01385417,0.011548928,0.00431866,0.004018035,-0.00075989007,-0.040379327,0.017566262,-0.007917085,0.018874502,0.005411922,0.010899993,-0.06947694,-0.016433945,-0.0025574244,0.0034272613,-0.006304923,-0.03612603,0.014365773,0.061373767,0.0028745078,0.020626858,-0.0008333904,-0.010204391,-0.0488116,0.020981543,-0.028679188,0.008896592,-0.023606304,-0.021125851,-0.012103102,0.03328115,0.03873616,-0.005345795,0.054693945,-0.017501116,0.0030504605,0.01970343,0.036438733,-0.058121968,-0.059258588,0.052296385,-0.00795534,-0.019297589,0.024659576,0.034912743,-0.012625436,-0.0046878057,-0.0013546351,-0.009706645,-0.052079685,0.011717042,-0.06546399,0.025950886,-0.0237931,0.021099502,0.005961997,0.0065112887,-0.015178685,-0.0003912732,-0.013594092,-0.0127474135,0.0005860987,-0.030786451,-0.025055751,0.023063758,-0.00083821703,-0.04464117,0.0425727,-0.007065067,0.024334356,-0.01572749,0.030272389,0.004038682,0.01735531,0.02207881,0.033786494,-0.0344288,-0.017575154,0.0034993303,0.00581489,0.02644208,0.030148348,-0.010989082,0.016346537,-0.013112511,-0.029446576,0.049902275,0.025076866,-0.0041535683,-0.018832844,0.0049298913,-0.0254632,0.024524983,-0.010698241,0.067609526,-0.000357216,-0.0029004174,-0.01816174,-0.016779302,-0.03324988,0.016030787,0.008611374,-0.0031411005,0.024400838,0.03819492,0.0022721125,-0.00743385,0.011111577,-0.016176522,0.013857061,0.018767932,0.041023172,-0.010676364,0.0030141026,-0.034614775,0.0052297427,0.012988671,0.018392531,0.022051368,-0.0049985037,-0.011018199,0.029063532,0.04952059,0.035883207,-0.009307835,-0.0005472292,-0.0053180563,-0.02891725,0.002177532,-0.0051341783,-0.019630939,0.012940025,-0.01017987,0.012418081,0.010055313,-0.037300106,0.0672294,0.021574754,-0.0065454114,0.02347895,0.0019256545,-0.027081706,0.0071677407,0.008845041,0.01425429,-0.030736648,0.0061267787,-0.109457165,0.003144395,0.027855322,-0.0003380446,-0.0027196743,0.023898762,-0.02054516,-0.00070602266,-0.012801416,0.005244881,0.013940712,-0.0022545638,0.0041319598,-0.03372771,-0.0070181144,-0.0063983533,0.024103899,-0.0082153175,-0.015341928,0.008186106,0.021816762,-0.020477086,0.015893966,-0.02899208,0.017503234,0.011889775,0.026039189,-0.04505718,0.015703958,-0.008679989,0.009826904,-0.010942289,-0.013543905,0.018800467,-0.015154857,-0.040958215,0.005678111,-0.013855091,0.033807855,0.008226115,-0.0062075574,0.003619405,-0.0015822367,0.00045244672,0.016148709,0.028538983,0.022623204,-0.016287137,-0.035405345,-0.04430994,-0.0049457597,0.05020578,-0.00203136,-0.0010215079,0.00393647,-0.027296394,0.014716486,0.008973299,0.010594106,0.001345817,-0.025510494,-0.027946416,0.029551495,0.00714851,-0.014845933,-0.03018061,0.069546886,0.02443527,0.0039116777,-0.01827831,0.0061025824,0.010247271,-0.018110886,0.0055325106,0.01889899,0.0025121644,0.018366387,0.015965281,-0.014148561,-0.020137472,-0.020699825,0.0017540256,0.026729181,-0.06250361,-0.017976636,-0.00062359555,-0.015183521,0.012337157,-0.01892879,0.012663003,0.019107422,0.039487552,-0.022257365,-0.002992564,0.038574282,0.08501075,0.016894786,-0.021597868,-0.002695729,0.0060405144,0.008588389,0.004329959,0.016783077,0.023730025,-0.039466273,0.007207582,0.0022140027,0.009159123,0.03310733,-0.028422115,-0.02336907,-0.006473858,-0.013688588,0.017616114,-0.0037793822,0.05088874,-0.0067458143,0.0126918955,0.040034585,-0.008157559,0.027956635,-0.032591585,-0.022663752,-0.007880618,0.026168132,-0.058488045,0.033822324,-0.045631476,0.0052493936,-0.026322719,-0.0059868013,0.036612242,0.006046869,-0.031873293,0.038017232,0.005931276,-0.01751506,0.056646787,-0.015879318,0.027118,-0.017002605,-0.022139918,0.013507171,-0.0064071557,0.016902016,0.051406078,-0.026531631,0.02375081,-0.040595956,-0.002146408,-0.021970857,-0.03117333,-0.016317656,0.017075665,0.020620791,0.03141015,0.0017266643,0.06124231,-0.008367247,0.03194896,-0.008575221,0.03764033,-0.02777523,0.021703618,0.000776139,-0.018620888,-0.024780763,-0.034142334,-0.037531722,0.0059748404,0.030519677,0.0002590394,0.5420985,-0.0041886177,-0.012575782,0.0017228617,0.022789681,-0.026324436,0.009850362,-0.018750548,-0.021536004,-0.010470955,0.008206524,0.032663215,-0.04300769,0.03569871,0.010810833,-0.034573764,0.023726083,0.0036595687,-0.022681318,-0.028903648,-0.055151273,-0.026015604,-0.057181384,0.0032018656,0.032683216,0.03705544,0.011907045,-0.015617775,-0.004873172,0.029097961,-0.040807597,-0.012468881,0.0050722375,0.012693006,-0.033212412,-0.02266313,-0.0045285556,0.04121808,0.006311321,-0.00036054687,-0.049213607,-0.010215187,0.026799,-0.034043375,0.035136394,0.013242495,-0.009304019,0.006593182,0.026199494,-0.0011599875,-0.00078610005,0.014437919,-0.005292977,-0.006262644,0.014906078,-0.029722158,0.04560046,0.030372597,-0.013297803,-0.0035290024,-0.034762446,-0.0013272244,-0.036557857,-0.003218876,0.025148604,0.00016925078,-0.025012951,-0.003690402,-0.016920125,0.017465338,-0.014413835,0.012919873,0.0015755635,-0.038190693,-0.01943365,-0.036474645,0.031608116,-0.0017229479,-0.0039506448,-0.010598116,0.032403342,-0.0155339455,-0.016968034,-0.012837661,0.010811975,-0.01842548,-0.0047261342,0.021167243,0.031717148,0.06495131,-0.0015151148,-0.011179547,-0.02814814,0.024872724,-0.022706361,-0.007597859,0.05471965,0.0035708935,0.0099638635,0.007777582,0.026727729,0.008681804,0.0062056845,-0.025884591,0.04528559,0.04118475,-0.0094370255,0.057420854,-0.011219578,-0.014829867,-0.024661647,0.0100655565,-0.03677016,-0.044867527,-0.031959012,0.057659328,-0.013346576,0.0035054968,0.02485926,0.011418758,-0.02894271,-0.012367346,0.029047225,0.0742907,0.010925572,-0.016093625,-0.021754745,-0.085516535,-0.023153502,-0.028499516,0.0061683194,-0.03118903,-0.024414107,0.021739034,-0.03018322,0.05365019,0.0009348341,0.04784476,-0.06677067,0.007968584,-0.020590039,-0.040821098,0.013771893,-0.01339041,0.007714207,0.00542817,0.011162793,-0.015952498,-0.026567154,0.019165553,0.002627913,0.032931644,0.0354739,-0.029528864,-0.013432363,-0.0011630316,-0.010039643,-0.02445242,-0.056752723,-0.0045156684,-0.014612949,-0.0011321902,0.022507658,-0.02061075,-0.006181064,0.008745419,-0.018792495,0.037782032,-0.0031051524,-0.010621178,0.01994612,-0.022592684,-0.022680672,0.06927571,0.020703038,0.0044111726,-0.0043760617,-0.044632025,0.015157088,-0.06195339,-0.008842543,-0.018867865,0.021008935,0.0025054205,0.0078002205,-0.013465123,0.012629419,0.0017276384,-0.0019110793,-0.064509414,-0.022281049,0.025093418,0.013158779,-0.013262503,0.0151666785,0.011118459,0.0075154635,0.016863192,-0.012695567,0.008905953,-0.02384018,0.006222177,-0.032446843,-0.031713124,-0.022071827,0.028372617,0.020090465,0.026912576,-0.024315763,-0.07264672,0.006249847,-0.0095610265,-0.050477725,0.013086141,-0.032619312,0.017133627,-0.03289857,-0.030736709,-0.006683348,-0.005370269,-0.028998714,0.042592756,-0.04550501,0.0092358645,0.0068071564,-0.011409912,0.02945301,-0.0036628272,-0.011344637,0.02609595,0.03525425,0.024392204,0.0041142027,-0.0062578963,-0.020944884,0.009920121,-0.011860337,0.011996357,-0.010111607,-0.012217719,0.009073544,-0.054073136,0.0041372464,0.013663416,0.019865418,0.005859765,-0.019472564,-0.003999708,0.018104834,-0.036634997,-0.0060359184,-0.0016364753,-0.033230748,0.020360421,0.027684454,-0.03872953,0.05202163,0.00116856,-0.04181312,-0.0071512624,0.010086018,-0.09270486,-0.028955128,0.02582139,0.015193329,-0.01277016,0.023545172,-0.030224925,0.056952756,0.018301692,-9.635395e-05,0.0056914557,0.008994552,0.03176457,0.008327338,-0.013894567,0.012229044,0.04367849,0.034499492,-0.010195178,0.010681156,0.0058232667,-0.015927223,-0.0018348475,0.0077078836,-0.029281126,0.03668036,-0.0016051625,-0.012979936,-0.009537656,0.0583477,-0.02944343,0.0022865382,0.06404831,-0.0047271466,-0.03751758,0.004126095,-0.005039934,0.0012283977,-0.008822844,0.00018210888,-0.0444667,0.00055294257,-0.019018607,-0.029476723,0.043919366,0.0029221063,0.0046266,0.0045946985,0.027524902,-0.044515792,0.013032205,-0.03384059,-0.008122727,0.0076551656,-0.009019746,0.014238658,-0.010411267,-0.0029468962,-0.0016432588,-0.040648825,-0.033798058,-0.026593832,-0.0139502855,0.35628334,0.004263505,-0.010220954,0.0023570945,-0.007852889,0.007845867,-0.005205491,0.039407805,-0.0018113864,0.008949933,0.028941033,-0.002927273,0.0046690437,0.02877363,0.026652496,-0.0042118626,0.041311357,-0.00022133415,-0.001702418,-0.008600121,-0.011884581,0.012793326,-0.058116797,-0.008327064,-0.034245804,-0.03094398,-0.013359105,-0.010531341,-0.025688445,0.022948004,0.024490466,0.0075384197,-0.023993822,-0.0238222,0.02097102,-0.014593064,-0.015531934]', FALSE), +('e945916b-49b9-46e4-8355-9246b7aacd74', '47655720-be4c-499c-9761-74aa9ca45385', 1, '## Virtual interfaces + +| vmbr | purpose | config | +|-------|---------------------|----------------------------------------------------| +| vmbr0 | management | 10.77.42.0/24, gateway 10.77.42.1 on pbx-node1 | +| vmbr1 | lab (VLAN 42) | tag 42, no DHCP, NAT-only to the uplink | +| vmbr2 | lab-iot (VLAN 130) | tag 130, DHCP served by minio01 | + +- Cluster firewall is enabled on every node; VLAN 42 traffic is NAT-only. +- Corosync heartbeat rides vmbr0; keep the management iface out of the + lab-iot VLAN. +- Node roles: pbx-node1 = hypervisor + gateway, pbx-node2 = AIO + containers, pbx-node3 = GPU box.', '[0.04397578,0.0350588,-0.0064939163,-0.040404823,0.019003542,0.0031114612,0.04952937,0.014077573,0.003500468,0.02087035,-0.006495672,0.008165121,0.0036874576,-0.00095012446,-0.005510349,-0.021469569,0.013855447,0.003975463,0.0002369951,-0.010918173,-0.009453691,0.044356063,0.00330042,0.044622637,-0.024943097,0.013251113,0.018413337,0.018765368,0.0029221422,0.010764289,0.00038576368,0.0034379503,-0.01896997,0.026426293,-0.004766535,0.020981096,0.032068815,0.0030956767,-0.03871559,-0.14160123,-0.018285327,0.03468316,-0.034725063,-0.0023876096,0.0271906,0.01527618,-0.013847641,0.0137090385,-0.02341814,-0.015274811,-0.02995892,-0.01745206,-0.0075304694,0.0005099681,-0.004368885,-0.0026747447,-0.011315335,-0.060594346,0.00028485322,0.023092996,-0.014356769,0.0026118152,0.043950327,0.010198878,-0.031008923,0.010271307,0.025173163,0.0059064254,-0.036660604,-0.013512473,0.019457875,-0.03012046,-0.028373193,0.029239228,-0.00624988,-0.021529041,-0.00051976746,0.02722376,-0.05819976,-0.011723776,0.029318381,-1.583065e-05,0.024853753,-0.020588838,0.036672246,-0.0068900804,-0.0451983,0.02820572,-0.0028160003,-0.010213335,0.021121362,-0.00071767194,0.003399283,-0.041253515,-0.008452648,-0.010230649,-0.0024412607,-0.01239655,0.019990472,-0.033189557,0.008909427,-0.013325515,0.0023050932,-0.00324716,-0.008738513,0.021850515,0.029251074,0.018688451,-0.0051199063,0.040146116,-0.0114963185,-0.035707656,-0.009927832,-0.02250247,0.022575842,0.021941368,-0.019404367,0.0075182915,0.005237627,0.007138794,-0.009937721,-0.0060750446,0.0013464489,0.01014572,-0.0099516725,0.006804074,-0.034751408,-0.029820431,0.025862826,-0.01652697,-0.0009979322,0.037354793,0.013482836,0.032709677,0.011004824,-0.0012136506,-0.026367465,-0.02496901,0.0177057,-0.0635973,0.019124135,-0.02895204,0.034510333,-0.0069070836,0.0132018225,-0.017069241,-0.0072439625,0.012832277,-0.011636452,-0.009289343,-0.018834058,0.024963323,0.019352593,0.002798565,0.008555706,0.01601996,0.011722171,-0.008566825,-0.041339092,0.02576026,-0.019233063,0.004727417,0.037112024,0.012853204,-0.014141482,0.0013290915,0.022590838,7.372844e-05,0.013924394,-0.0012216938,-0.002661285,-0.002849852,-0.008283024,-0.01304431,0.03394685,0.044723045,0.028666357,-0.023387976,0.022737771,-0.030036766,0.008801296,-0.0144882435,0.013932439,-0.030158967,-0.00071268185,-0.027876485,0.019017944,-0.0010264842,-0.030816292,-0.00044869425,-0.009504163,0.010259222,-0.0069892723,-0.035996575,-0.015377237,9.592133e-06,0.0031818207,0.039278027,-0.024949322,0.023509674,-0.018555688,-0.0061358917,-0.0076345564,0.0021423008,-0.0052276696,0.010143035,-0.010041755,-0.016642528,-0.008140879,-0.010058661,0.030931268,0.015190228,0.002147112,-0.019686716,0.0020539286,0.01313873,-0.0011031099,0.013810212,-0.012384053,-0.016016904,0.023287855,0.0012423979,0.0014747701,-0.026843602,0.042145446,-0.005889781,-0.00866804,0.010435831,-0.012971349,-0.028796805,-0.003656082,-0.007252661,0.008590434,0.012552112,-0.020505795,-0.08663771,0.0040064203,-0.0007010737,0.016701736,0.003038237,0.023243448,0.010831017,0.014542363,-0.021786924,-0.0003379805,0.008625987,-0.014395526,-0.0026668967,-0.028828483,0.0138920415,-0.0134065,0.024773441,-0.009265495,-0.033964586,0.028043587,-0.0056980555,0.0011654281,0.0045355386,-0.0061687385,-0.002582752,0.007888905,0.0068687326,-0.017009389,-0.013979984,0.0024131935,-0.012156992,0.0103281755,-0.0063754786,0.011932748,-0.043394115,-0.040636137,-0.021847034,-0.0032077914,0.020686535,-0.0018250553,-0.026235085,0.014754938,-0.032489937,0.020426255,0.029299757,0.036579933,-0.0053862254,0.0034220768,-0.02245771,-0.039769243,-0.040984582,-0.031278875,-0.017896699,0.00048630888,0.00045758672,-0.017765716,0.029689126,0.0035045813,-0.005746695,0.02374197,0.011104333,-0.0033030938,0.0058287573,0.011902317,-0.030939557,-0.014673479,-0.027525995,0.0129911415,-0.00043921117,0.030595018,-0.001382385,0.016604956,-0.009620439,-0.0110657755,-0.03365259,-0.011677661,0.041178152,-0.010259174,0.0012228484,-0.0262033,0.004755367,0.026359262,0.005672946,-0.010226674,0.011856839,0.0096966745,0.015890034,0.0032386954,-0.048620004,0.005178078,-0.004230107,-0.013415242,-0.0082910955,0.0037585113,0.0061927126,0.038943395,-0.039698374,0.0057248073,0.0118590705,0.025057182,0.010234481,0.004087604,0.006624201,0.014994123,-0.06690101,-0.019477703,0.022460362,0.002454288,0.024244836,-0.032994173,0.008309081,0.008490978,-0.021033194,0.001622791,0.03726506,0.041999206,0.0014126463,0.025231615,0.002694246,0.0067054415,0.030221561,0.006568592,-0.027906302,-0.038167167,0.01687716,-0.008022722,0.022752315,-0.054433398,0.03323796,-0.015120089,0.02715123,0.04409114,0.001483584,-0.034325458,0.032618955,-0.01356619,0.022147663,0.019003777,-0.01420104,0.0014481251,-0.005839854,-0.02701445,0.019352132,-0.0098347375,-0.0043347757,0.03101393,-0.011081696,-0.008433992,-0.04421154,0.039046884,0.0023997405,-0.008858902,-0.013695325,-0.014267463,0.0021935,-0.004386832,-0.0013517089,0.029569918,-0.017797122,0.018482173,-0.0034735508,-0.0009858134,0.014042464,-0.023441087,-0.003434466,0.00093972456,0.00252916,-0.0048437086,0.005988409,0.00288121,0.008695307,-0.024791332,0.57010275,0.009944652,-0.015202783,-0.0073888362,-0.0051720934,-0.006540457,-0.0051750885,-0.018336352,0.017912947,-0.02563706,-0.020459523,0.011867122,0.002898238,-0.022903582,0.014754155,-0.013030549,0.034171917,0.0062941816,0.0047106263,-0.0005240775,-0.06570924,-0.012444672,-0.048212737,0.013466796,-0.025972169,0.010368355,0.01828419,0.015717812,-0.020395782,0.04323656,-0.02590938,-0.029821405,0.00264607,0.0237397,0.018161777,0.00013166347,-0.0070264377,0.039840236,0.017389068,-0.00065271894,-0.05369959,-0.011011749,-0.011108015,-0.0006024083,0.012540373,0.03910973,0.030060668,0.007988677,0.012601377,-0.005034047,0.014880115,0.0046679154,0.036817826,0.010077229,-0.023546418,0.009719596,0.008762973,0.029604962,0.0046397983,-0.010927649,0.0018577813,-0.012787615,-0.025977274,0.0019782986,0.054991283,-0.008565113,0.0076569095,-0.03514202,0.0032052614,-0.008196711,0.0026488106,0.013350231,0.01648974,0.004976865,-0.015777957,-0.03615822,0.013643743,-0.009382897,0.0013254602,-0.018140154,0.017621314,-0.0039165155,0.006336467,-0.013298998,0.00975438,-0.04641774,-0.010891187,0.0031965503,0.03237206,0.013103252,-0.030186106,-0.007060468,-0.001907255,-0.00017462761,-0.018704657,-0.014897423,0.016089233,-0.00044742614,0.030879773,0.05499397,0.0050986386,0.036266986,0.020066544,-0.03711551,0.025011845,0.07715245,-0.0069430084,-0.010307601,0.0077697295,-0.020627612,-0.050132602,-0.02767404,-0.052507732,-0.0032054982,-0.00020518544,0.021117307,-0.0001259387,-0.018254451,0.002893564,-0.019010637,-0.013706428,-0.018835226,0.023016162,0.05189061,0.008814647,0.034301646,0.014756927,-0.028442238,-0.0053670565,-0.034186874,-0.02541142,-0.023262033,-0.016198004,0.038900178,-0.003624874,0.049959946,0.0028746896,0.034590993,0.0021237873,0.0014721517,-0.0013829526,-0.023854068,0.0060082497,0.004865707,-0.0017177681,-0.017518613,-0.025934134,-0.01991703,0.045306824,-0.020238625,0.039522305,0.012563713,0.022197338,-0.029407995,-0.007898029,-0.009686351,-0.039551858,0.008037207,-0.018969,-0.016922195,0.02963765,0.010817027,0.011180812,0.0076768547,0.03345983,-0.025074095,-0.0054137837,-0.023184847,-0.02305496,-0.011130367,0.026779147,-0.005712372,0.0047147204,0.050600864,0.033242792,-0.015940158,0.016568338,-0.004044663,-0.0057661003,-0.042961773,-0.0098409755,5.6445835e-05,-0.014836312,-0.03026877,-0.010471568,-0.013533323,0.011228019,0.013494739,-0.041276127,-0.037937805,-0.005280325,-0.01099094,0.027039798,0.026298542,0.009828369,0.03314647,0.009352263,-0.012364822,0.0023148037,0.011532219,0.00026569996,0.035738166,-0.05406866,0.004589131,-0.03000763,0.027482735,-0.025751766,-0.007320674,-0.006268627,-0.05285134,0.0048910375,0.0026509643,-0.022010386,-0.016226633,-0.019546824,0.013539559,-0.007769181,-0.0139101865,-0.0067463983,-0.011751725,0.0046246573,-0.0013558463,-0.016938027,-0.019302836,-0.0042285305,-0.010860402,-0.006180652,0.004777605,0.0073780906,0.0018825687,-0.016818061,0.010235464,-0.006219952,-0.001970601,0.012730763,-0.030338857,0.014186867,-0.00480519,-0.020769792,0.011614557,0.009404562,-0.04950122,-0.07054562,-0.013889513,0.038268298,0.012446699,0.00550814,-0.006179563,0.03538921,-0.043006606,0.0024389168,-0.008447086,-0.029366339,-0.050875384,0.007304331,0.0038795327,0.043985974,0.010957261,0.015540557,-0.014418079,0.029248392,-0.039195735,-0.0025757977,0.033846103,0.028156767,0.0067163175,0.0045959926,-0.010448259,0.008463804,0.027015245,0.020947974,-0.0113210045,0.020560168,0.020400554,0.02841793,-0.021473914,0.02942241,0.034906037,0.03554701,-0.01947642,0.005691106,-0.034411497,-0.0057069487,-0.017776543,0.017973589,-0.028846076,0.011981209,0.028059296,-0.007690911,-0.008754663,0.10626493,-0.01350255,-0.039706197,0.02280699,0.03711568,-0.0059706266,0.01984745,-0.03399647,0.014173307,-0.0545683,0.022182468,-0.0065274546,0.0012501555,0.007464475,-0.03878635,0.03372287,0.0046481155,0.00781294,-0.007867271,-0.0035383997,-0.040967908,-0.027602222,-0.008067258,-0.010966945,0.010517322,0.00021638037,0.019025356,-0.00096760126,0.0073702713,0.02692087,-0.05236508,0.0017474268,-0.025389612,-0.044041414,0.5078585,0.015908917,0.009722361,-0.014049211,-0.02227187,0.014095489,-0.00870073,-0.011968146,-0.019289296,0.008555507,0.01939657,-0.02447589,0.0027613258,0.036234554,0.0018479085,-0.023729602,0.0063400078,0.009793128,-0.00090129714,-0.019700555,-0.012860261,0.006072897,0.017072408,-0.024905847,-0.05564787,-0.05579226,0.025382712,-0.024534263,-0.013011457,0.01229793,0.06848787,-0.0399684,-0.014310226,-0.010636556,0.0047574043,-0.032488443,-0.004674627]', FALSE); + +INSERT INTO public.git_sources (id, url, kind, path, added_at) VALUES ('0dbf92c6-0beb-4c51-8fac-83aad72d31ff', '/var/home/ducoterra/Projects/Personal/brain_of_reese/tests/fixtures/agent_kb/deployments', 'local', '/var/home/ducoterra/Projects/Personal/brain_of_reese/tests/fixtures/agent_kb/deployments', '2026-09-04 16:57:47.725349+00:00'), +('385d0324-7c65-49b5-888f-af0aa06237da', '/var/home/ducoterra/Projects/Personal/brain_of_reese/tests/fixtures/agent_kb/homelab', 'local', '/var/home/ducoterra/Projects/Personal/brain_of_reese/tests/fixtures/agent_kb/homelab', '2026-09-04 16:57:47.725349+00:00'); + +INSERT INTO public.kb_overview (id, content, updated_at) VALUES (1, 'deployments: the lab Ansible inventory (host addresses and roles), the Obsidian BOR quadlet service definition, and the GitLab Runner CI setup. homelab: the rack7 Proxmox cluster networking (bridges, VLANs, DNS/DHCP), container notes (Uptime Kuma, Qwen 3.8 on llama.cpp), and the nightly restic backup configuration.', '2026-09-04 16:57:48.340325+00:00'); + +INSERT INTO public.sources_meta (id, version, updated_at) VALUES (1, 1, '2026-09-04 16:57:48.340325+00:00'); + + + +