Find a file
oskar f14ad410a0 fix(gmail-header-backfill): compat32 fallback + missing_file stat — 8-bit Date header crashed json.dumps mid-slice, losing 4999 rows
Diagnosis of the 5008 header-less envelopes after the full 225 030-row run
(read-only, on PIHA, 2026-07-14):

- 4999 = one contiguous block at ORDER BY id positions 70001-74999: the
  --offset 70000 slice died mid-run. Root cause reproduced: a Date: header
  with raw 8-bit bytes makes compat32 .get() return email.header.Header
  (not str), and json.dumps([headers]) — which sat OUTSIDE the per-row
  try/except — raised TypeError and killed the process, silently losing
  the rest of the slice.
- 9 = genuine typed-parse failures: 7x RFC 2047 encoded-word decoding to
  CR/LF inside a display name (ValueError in headerregistry), 1x RFC 5322
  group syntax in To: ("unlisted-recipients:;"), 1x CPython
  _header_value_parser bug on a malformed display name (fixed upstream,
  present on PIHA's 3.11).
- 0 missing .eml files.

Fixes:

- date_raw: str() + surrogate sanitization on the compat32 value — the
  crash cause, now also covered by a regression test.
- json.dumps moved inside the per-row try: a non-serializable value counts
  as that row's parse_error instead of crashing the slice.
- parse_headers_fallback(): on typed-parse failure retry with a pure
  compat32 parse — getaddresses over raw header text, raw-string values,
  same §4.1 entity shape. Counted separately as parsed_fallback (labeled
  subset of updated), logged per row with the original typed error.
- missing_file counter + skip.missing_file info log (id, expected path);
  run_complete now balances: scanned = updated + already_has_headers +
  parse_errors + read_errors + missing_file. Non-zero missing_file also
  fails the exit code.

Verified: 43/43 pytest locally (3.13) and on PIHA (3.11); read-only dry
runs on PIHA — all 9 parse failures recover via fallback, the lost slice
completes scanned=5000 updated=4999 already_has_headers=1 with zero errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 19:35:30 +02:00
.claude/skills docs: session 2026-06-11 — lustro ssh shipping fix + ha-diag-agent piha + backlog/flota-bomba 2026-06-11 14:18:00 +02:00
backups/zigbee Add Zigbee coordinator backup 2026-05-14 18:24:26 +02:00
docs docs(infra): monitoring coverage recon — co biega vs co monitorowane + plan domknięcia 2026-07-14 19:25:51 +02:00
dotfiles add shared zshrc 2026-05-10 20:52:44 +02:00
hosts fix(node-agent): PIHA — group_add gid 123 (docker) so agent can read /var/run/docker.sock (was PermissionError, agent blind to containers) 2026-07-13 20:02:20 +02:00
inventory feat(gokapi): config publicznego file-share na VPS (share.okit.pl, E2E, Tailscale-bind za npm@VPS, disk-protection) — do deployu 2026-07-09 17:29:28 +02:00
jobs fix(gmail-header-backfill): compat32 fallback + missing_file stat — 8-bit Date header crashed json.dumps mid-slice, losing 4999 rows 2026-07-14 19:35:30 +02:00
packages/kb-mail feat(kb-postgres): migration 002_chunks.sql — document_chunk table 2026-07-13 21:13:13 +02:00
scripts fix(observer): checkpoint by timestamp not lexical path — lexically-smaller-but-newer events were silently skipped forever (poisoned node) 2026-07-14 15:55:38 +02:00
services fix(observer): checkpoint by timestamp not lexical path — lexically-smaller-but-newer events were silently skipped forever (poisoned node) 2026-07-14 15:55:38 +02:00
.codex Document current homelab state 2026-04-15 17:37:25 +02:00
.gitignore fix(piha): capabilities — realny RAM/NVMe + gitignore build dirs 2026-06-25 17:07:11 +02:00
CLAUDE.md docs(kb): etap 1 fundament done + session log 2026-06-17 2026-06-19 20:02:25 +02:00
codex_context Add session context state 2026-04-20 22:10:39 +02:00
codex_context.yaml add shared context lock 2026-05-05 17:25:50 +02:00
deploy_agent.py Add deploy escalation output 2026-04-22 22:08:26 +02:00
ollama_client.py Initial shared homelab agent workspace 2026-05-03 19:37:40 +02:00
README.md docs: add planner-agent docs and session summary 2026-05-27 2026-05-27 22:35:59 +02:00
start-aider.sh Initial shared homelab agent workspace 2026-05-03 19:37:40 +02:00
start-codex.sh Initial shared homelab agent workspace 2026-05-03 19:37:40 +02:00
sync-context.sh add shared context lock 2026-05-05 17:25:50 +02:00
tech-debt.md docs(tech-debt): cleanup artefaktow paste-error w ~oskar (SOLARIA, niski prio) 2026-06-24 17:13:51 +02:00
update-context.md Initial shared homelab agent workspace 2026-05-03 19:37:40 +02:00

Homelab Codex

GitOps-lite orchestration for a distributed homelab environment.

Architecture

The homelab consists of several nodes connected via a Tailscale internal mesh.

Host Role Description
SATURN Primary Node Development, orchestration, and git source of truth (commit node).
SOLARIA Compute Node GPU, inference, and heavy compute workloads.
PIHA Infra Node Core infrastructure services, automation, and monitoring.
VPS Edge Node Public ingress, reverse proxy, and edge services.

Agent System

The homelab uses a multi-agent orchestration model with human-in-the-loop for destructive actions:

Agent Node Role
stability-agent all nodes Per-node watchdog — monitors Docker, disk, Tailscale, MQTT; emits events
node-agent all nodes Publishes container health events to Redis pub/sub
observer VPS Synthesizes world state from events into /opt/homelab/world/*.json
supervisor VPS Detects drift between desired and actual state; writes pending actions
planner-agent SOLARIA LLM-powered diagnosis — listens to Redis, proposes remediation actions
executor VPS Executes actions only after operator approval
operator-ui + telegram-bot VPS / PIHA Operator reviews and approves/rejects pending actions

Action approval flow: pending/ → operator approves → approved/ → executor runs.

Repository Structure

Getting Started

  1. Standardization: Follow the Infrastructure Standards.
  2. Deployment: See Deployment Conventions for how to roll out changes.
  3. SATURN: Remember that SATURN is the only node where commits should be made.

Documentation Index


Note: This repository documents the state of the homelab. Runtime state lives outside the repository in /opt/homelab.