Commit Graph
64 Commits
Author SHA1 Message Date
Story Crater Bot 5f954b904d fix: add cube+earthdistance to postInitApplicationSQL, immich needs them for geo queries 2026-08-25 18:50:09 -07:00
Story Crater Bot e614354b11 fix: add postInitApplicationSQL for pgvector, app role isn't superuser
immich-server crash-looped on "permission denied to create extension
vector" - pgvector's control file isn't marked trusted, and CNPG's
app owner role isn't superuser (enableSuperuserAccess: false).
Documents the fix for future cluster rebuilds; the live cluster
already had CREATE EXTENSION run manually via the postgres pod's
local socket.
2026-08-25 18:49:09 -07:00
Story Crater Bot 1729ca854d fix: use img.riotpiao.com instead of immich.riotpiao.com for hostname 2026-08-25 18:46:58 -07:00
Story Crater Bot b42936c272 fix: shrink immich-media to 1400Gi, real disk headroom smaller than assumed
2000Gi didn't schedule - "insufficient storage; tags not fulfilled".
The cp-3 HDD's real usable capacity (~3724GiB) minus paperless-media's
2000Gi and ~231GiB of other apps' default-class replicas that Longhorn
placed here anyway (tags only pull matching volumes in, don't exclude
others when the untagged pool elsewhere is full) only leaves ~1493Gi
of real scheduling headroom. 1400Gi fits with margin.
2026-08-25 18:34:22 -07:00
Story Crater Bot 6a1002958d feat: deploy Immich with Authentik OIDC, rock as admin
Self-hosted photo backup (Google Photos replacement) - raw manifests,
no Helm chart, self-contained under k8s/apps/immich including its own
CNPG Postgres. Media PVC shares the cp-3 HDD 2TB/2TB with
paperless-media.

Postgres is pg18, not this repo's usual 16.2: CNPG's official pgvector
extension image (ghcr.io/cloudnative-pg/pgvector) is only published
for pg18, loaded via CNPG's ImageVolume extension mechanism (operator
1.30.0 / k8s 1.36.1 both support it). Immich auto-manages CREATE
EXTENSION itself at startup.

OIDC via a new "immich_role" Authentik scope mapping (homelab-admins/
immich-admins -> "admin" claim, else "user"), consumed by Immich's
OAuth roleClaim setting which re-syncs isAdmin on every login - more
reliable than Immich's racy first-user-is-admin fallback. Config
composed into an immich-oidc Secret and mounted as IMMICH_CONFIG_FILE,
matching the paperless-oidc pattern. k8s RBAC (immich-operator Role +
oidc:immich-admins binding) mirrors paperless/rbac.yaml.

immich namespace pre-created in k8s/infra/databases/namespaces.yaml
(not just immich's own CreateNamespace=true) since the iam PostSync
job's RoleBinding needs it to exist before wave 8.
2026-08-25 18:21:28 -07:00
Story Crater Bot f8d90efe38 fix: shrink paperless-media to 2TB, split cp-3 HDD with Immich
4TB disk on cp-3 was single-tenant for paperless (3500Gi). Splitting
2TB/2TB with the new Immich media PVC on the same disk/tag. Live PVC
and Longhorn volume already deleted+recreated manually (data was
outdated test uploads only, nightly MinIO backup covers it).
2026-08-25 18:09:23 -07:00
Story Crater Bot 970cce1ed2 fix: use 2.20.15 instead of 3.0.5, direct 2.13->3.0 migration is blocked
paperless-ngx v3 refuses to migrate from anything before v2.20.15
(paperless.E002). 2.20.15 already covers the API version range the
iOS app needs, so it fixes the phone upload issue without the v3
breaking changes.
2026-08-25 17:40:42 -07:00
Story Crater Bot 0ab57d7478 fix: bump paperless-ngx to 3.0.5 for iOS app API version compat
Swift Paperless needs REST API v3-9; server was on 2.13 (v1-5 only),
causing 406 on /api/token/ for all phone uploads. v3 requires
PAPERLESS_DBENGINE explicit instead of inferred from PAPERLESS_DBHOST.
2026-08-25 17:37:41 -07:00
Story Crater Bot f9dd1f2b71 feat: add homelab-wide Authentik RBAC model and k8s OIDC auth wiring
Adds permissions claim + per-service admin groups in Authentik, scoped
Role/RoleBinding per service, public PKCE kubernetes OAuth2 client, and
kube-apiserver OIDC extraArgs. Also fixes paperless OIDC signup permissions
via adapter override and adds CoreDNS rewrite for authentik.riotpiao.com.
2026-08-25 15:03:44 -07:00
Story Crater Bot 1095bab05a fix: disable email verification requirement on paperless OIDC signup
allauth defaulted to ACCOUNT_EMAIL_VERIFICATION=mandatory, and building the confirmation link 500'd with NoReverseMatch on account_confirm_email (paperless-ngx doesn't wire up that view, no SMTP configured either). Authentik already verifies identity via OIDC, so this step is redundant.
2026-08-25 13:05:50 -07:00
Story Crater Bot 499aedb343 fix: disable enableServiceLinks on paperless pod to stop gunicorn crash-loop
Service "paperless" made k8s inject PAPERLESS_PORT=tcp://<ip>:8000 as a legacy Docker-links env var, which paperless-ngx's own entrypoint also reads for gunicorn's bind port - collided, gunicorn crash-looped ("not a valid port number"), and the pod was 1/1 Running with nothing actually listening (nginx saw 502).
2026-08-25 12:26:16 -07:00
Story Crater Bot 98c4391ca8 feat: add paperless-ngx with OIDC, CNPG db, cp-3 HDD media, MinIO backup
Fixes controlplane.tftpl's install.wipe:true (should be false, live CPs already run false) and syncs coredns Corefile back to what's actually deployed (drops an unrolled-out, stale Kong-era rewrite).
2026-08-25 11:11:37 -07:00
Story Crater Bot d3b6ecfb62 Add Temporal worker for production task queue 2026-08-21 16:44:59 -07:00
Story Crater Bot 76d00bcfc3 fix: restore YaRN rope-scaling for reasoning-predictor (GPTQ requant dropped it, checkpoint's own ceiling was 40960 not 131072) 2026-08-21 16:42:39 -07:00
Story Crater Bot 76d5078611 fix: swap reasoning-predictor to Qwen3-32B-GPTQ-Int4, 131072 context (bnb-4bit decode too slow, GPTQ is Volta-native) 2026-08-21 16:39:33 -07:00
Story Crater Bot 93128a104e fix: retire one reasoning-predictor replica, run PP=2 across both V100s (Qwen3.5 MoE swap abandoned, moving to Ollama) 2026-08-21 16:23:07 -07:00
Story Crater Bot c956ac1465 chore: retire TemporalWorker CRD — agent-harness-worker and Forgejo build workflow removed 2026-08-20 23:10:06 -07:00
Story Crater Bot 5167656445 feat: point api.riotpiao.com at the gateway ahead of Kong removal
Kong is being deleted, so the backend cannot stay kong-proxy. Gateway serves
404 on API routes until tasks 2.1/2.2 land.
2026-08-19 23:34:33 -07:00
Story Crater Bot abd0af3ea9 revert: point api.riotpiao.com back at kong-proxy
Gateway pods are ErrImagePull — nodes resolve forgejo.riotpiao.com to a
ClusterIP and time out, so the Service had no endpoints and the host was
returning 503. Kong is still running; this restores it.
2026-08-19 22:56:22 -07:00
Story Crater Bot 98d8276476 feat: cut api.riotpiao.com over to the Go gateway and retire Kong
Ingress api/api now backs onto api-gateway:8080; the kong Application, its
Helm values, plugins and llm-routes are removed. Gateway image v0.0.0 is in
the Forgejo registry and the pull secret is in the api namespace.
2026-08-19 22:51:53 -07:00
Story Crater Bot bd6a21e7e1 coordinator: make gitignore/PLAN.md setup idempotent, run every phase
Old i===0 && !resuming gate meant this only ran on a fresh start -- every
run this session was a resume, so poiman's branch never got the harness
gitignore rules, and portfolio's PLAN.md stayed tracked from before the
rule existed (gitignore doesn't affect already-tracked files). Now checks
and fixes both on every phase instead of once at genesis.
2026-08-19 21:12:33 -07:00
Story Crater Bot 5589bcd56a coordinator: detect+respawn dead pool sessions, bound resolver call
Dead sessions were only caught after a full 10-min stall timeout; now
polled via agent-manager status and respawned (retry once). spawnPi had
no timeout and could hang a repo's whole pipeline forever -- bounded to
5 minutes now.
2026-08-19 20:27:17 -07:00
Story Crater Bot fd7b714f09 reasoning: raise num_cpu_blocks 32->256 for real DRAM KV offload capacity
32 blocks was a ~1GB safety-valve leftover from the num_cpu_blocks=2000
hang incident, not meaningful offload capacity. This model's KV cache is
~32MB/128-token block (64 layers, 8 KV heads x 128 head_dim, fp16) --
256 blocks gives ~8GB of real DRAM offload (32,768 tokens), comfortably
under the pod's 36Gi limit alongside the ~20GB bnb-4bit weights.
2026-08-19 18:42:37 -07:00
Story Crater Bot 6291dd5afb reasoning: swap to dense Qwen3-32B-bnb-4bit for reliable tool calling
DeepSeek-R1-distill's tool_choice=auto narration bug needed a real fix,
not a workaround -- Qwen3's native tool-call format (hermes-compatible
chat template) solves it at the source instead of parsing around it.
Dense Qwen3-32B avoids the MoE arch/quantization pitfalls hit by the two
prior swap attempts (Kimi-distilled Qwen3.6 MoE, AWQ Qwen3-30B-A3B) --
same bnb-4bit path already proven working on this sm70 (V100) node.
2026-08-19 18:40:15 -07:00
Story Crater Bot 648388554d reasoning: revert to DeepSeek-R1-Distill-32B, retire Kimi/Qwen3 swap attempt
Three straight failures on worker-1: Kimi-K2.6-distilled Qwen3.6-35B-A3B
had an unrecognized model type (qwen3_5_moe); the AWQ-4bit fallback needed
compute capability 80+ (marlin INT4 kernels) but this node's GPU is sm70
(V100); on-the-fly bitsandbytes against the full-precision Qwen3-30B-A3B
kept crash-looping. Reverting to the last known-good config (ac1849d) --
tool-call narration bug on judge remains open, to revisit separately.
2026-08-19 18:34:15 -07:00
Story Crater Bot 6ce46b9ad5 reasoning: switch to on-the-fly bnb quant, worker-1 GPU is sm70 (V100)
cpatonn's pre-quantized build failed with a real hardware constraint:
"Quantization scheme not supported for current GPU. Min capability: 80.
Current capability: 70." AWQ/GPTQ/compressed-tensors marlin INT4 kernels
all need sm80+ -- this node's GPU can't run any of them. Only bitsandbytes
or full precision work here. Switching to the official full-precision
Qwen/Qwen3-30B-A3B-Thinking-2507 with --quantization=bitsandbytes
on-the-fly, and bumping the memory limit (36Gi->48Gi, request unchanged)
for the transient bf16-shard staging during load.
2026-08-19 18:30:24 -07:00
Story Crater Bot d3a059a6b4 reasoning: fix quantization flag mismatch (compressed-tensors, not awq_marlin)
cpatonn's "AWQ-4bit" repo is actually quantized via llm-compressor --
config.json declares compressed-tensors. Passing awq_marlin explicitly
conflicted with the checkpoint's own declared format and 400d at
config-validation time.
2026-08-19 18:23:15 -07:00
Story Crater Bot f015e4577b reasoning: fall back to official Qwen3-30B-A3B-Thinking-2507 AWQ-4bit
Kimi-K2.6-distilled Qwen3.6-35B-A3B crashed on boot -- model type
qwen3_5_moe unrecognized by transformers/vLLM 0.11.0, a genuinely
unsupported architecture, not a config issue. Using cpatonn's pre-quantized
AWQ-4bit build of the official Qwen3-30B-A3B-Thinking-2507 instead: native
vLLM support confirmed, no Kimi distillation but Qwen3's own tool-call
format is natively supported (the actual root problem being solved).
Restored max-num-seqs=4 since AWQ-4bit weight footprint leaves more KV
headroom than the bnb attempts did.
2026-08-19 18:20:34 -07:00
Story Crater Bot 1877f94bf6 reasoning: halve max-num-seqs to 2 for Kimi swap's first boot
New model's weight footprint (35B total MoE at on-the-fly bnb-4bit) leaves
less confirmed KV-cache headroom on the 32GB card than the old one had --
reducing concurrent-sequence worst case until real memory use is verified.
2026-08-19 18:14:22 -07:00
Story Crater Bot c5ff86d6dc reasoning: swap DeepSeek-R1-Distill-32B for Kimi-K2.6-distilled Qwen3.6-35B-A3B
R1-family tool_choice=auto is a documented vLLM architecture conflict --
the model narrates fake tool_calls in <think> instead of emitting real
ones, regardless of parser (deepseek_v3 400s, hermes parses but the model
still doesn't call out). Qwen3's native tool-call format sidesteps this.

No pre-quantized AWQ/GPTQ/bnb checkpoint exists for this specific distill
(only GGUF, llama.cpp/Ollama-only) -- using on-the-fly bitsandbytes
quantization against the full bf16 checkpoint instead.
2026-08-19 18:11:45 -07:00
Story Crater Bot 1bf611739b fix(agent-pod): force judge to actually call tools instead of narrating
Observed live: phase-judge (on homelab-reasoning) wrote a full page of
'I should check X, then Y' reasoning, declared VERDICT: PASS, and showed
the touch command as a fenced code block in its own text -- never ran
git diff, never wrote the result file, never touched the sentinel.
Coordinator timed out waiting on a file that was never going to appear.
2026-08-19 17:13:49 -07:00
Story Crater Bot 9fbfce7963 fix(agent-pod): install rust+gcc toolchain, symlink go, drop brave-search skill
poiman is Rust, portfolio is Go -- neither toolchain was reachable from an
interactive kubectl exec session (go's PATH export was local to its own
install script; rust was entirely absent, and cargo needs gcc as a linker
which also wasn't present).

brave-search was just a curl one-liner wrapped in its own skill file --
inlined the same curl command directly into info-collector/investigator's
instructions instead of dispatching to a separate skill for it.
2026-08-19 15:59:11 -07:00
Story Crater Bot ac1849d2a9 fix(llm-serving): bump reasoning memory limit to 36Gi headroom 2026-08-19 15:16:46 -07:00
Story Crater Bot 4eab8271c7 fix(llm-serving): num_cpu_blocks=2000 hung pod startup, drop to 32 2026-08-19 15:09:28 -07:00
Story Crater Bot dd491f6f8b feat(llm-serving): offload reasoning's KV cache to CPU DRAM
vLLM 0.11.0's native OffloadingConnector -- spills KV blocks to CPU RAM on
preemption instead of discarding them, avoiding recompute. Built into vLLM
core, no extra dependency. Bumped memory request/limit (+4Gi/replica) to
give the CPU block pool real room; worker-1 had ~18Gi of request headroom
across both replicas.
2026-08-19 15:02:28 -07:00
Story Crater Bot 5b041df884 fix(agent-pod): committed progress ledger so resume skips done tasks
Resuming the phase branch alone only recovers the code -- the task loop
still walked from the first task, re-verifying every already-done one
through a full planner call before reaching the first task that actually
needed work. .agent-progress is committed (not gitignored) and appended
per completed task, so a resumed run reads it once and skips straight
past known-done tasks with zero LLM calls. Validated locally against a
throwaway repo: second run skipped both tasks instantly (resumed: true)
instead of re-running planner on them.
2026-08-19 13:16:03 -07:00
Story Crater Bot 3ea057d83e fix(agent-pod): group sessions by repo, resume phase branches, fix empty-diff bug
- agent-manager spawn now gets --group repoId, so the TUI clusters
  planner/investigator/implementer/judge under one repo heading instead of
  4 unrelated sessions.
- runPhase was called with phaseBranch where it needed the true baseBranch,
  so every per-task judge review compared phaseBranch...HEAD -- always
  empty, since HEAD is phaseBranch while checked out. Judges only produced
  real verdicts anyway because they fell back to their own git log/show.
- Every restart re-cloned baseBranch fresh and started a new phase branch,
  discarding whatever a prior run had already committed mid-phase. Now:
  fetch+resume an existing phase branch if origin has one, push after every
  task instead of only at phase-end, and delete the phase branch (local +
  origin) once its milestone squash-merges into base.
2026-08-19 11:46:53 -07:00
Story Crater Bot 43c0e1faa2 fix(agent-pod): absolute paths for every sentinel/verdict file, cwd reminder per call
A pooled session's shell cwd drifts as it explores the repo between turns.
Seen live: a repo whose internal workspace dir is one letter off from the
repo's own directory name was enough for the agent to touch its sentinel
one level off from where coordinator watches for it -- coordinator waited
out the full timeout for a file that existed, just in the wrong place.
2026-08-19 11:26:33 -07:00
Story Crater Bot 3a244577e4 fix(agent-pod): fold judgeOnly status check into planner, drop separate judge pre-check 2026-08-19 10:57:21 -07:00
Story Crater Bot 7a0d09cbe0 fix(agent-pod): install python3 and sqlite3 in the container init 2026-08-19 10:46:50 -07:00
Story Crater Bot cb52356d13 fix(agent-pod): sync coordinator.js (slug repoId), tighten compaction, route judge to reasoning model 2026-08-19 10:41:33 -07:00
Story Crater Bot d0cbfac7a4 fix(agent-pod): stateless role pool (/new per reuse), never commit PLAN.md 2026-08-19 07:59:01 -07:00
Story Crater Bot 930374a3b8 feat(agent-pod): persistent per-role agent pool, concurrency moves to repo level
coordinator.js now runs one long-lived planner/investigator/implementer/judge
session per repo (reused across every task via tmux send-keys) instead of a
fresh spawn per task per stage. Tasks within a repo run sequentially against
that pool; concurrency is now REPO_CONCURRENCY (default 3) concurrent repos
via a new --repos flag, not concurrent tasks in one repo's phase.
2026-08-18 21:30:49 -07:00
Story Crater Bot b10d1c3a25 fix(llm-serving): use hermes tool-call parser, not deepseek_v3
deepseek_v3 400s on this checkpoint: "could not locate tool call start/end tokens in the tokenizer". unsloth/DeepSeek-R1-Distill-Qwen-32B is a Qwen2.5 base distilled on R1 reasoning traces -- it kept R1's <think> format but never got DeepSeek-V3's own special tool-call tokens registered in its tokenizer. hermes parses from text patterns instead of special tokens, so it works against the underlying Qwen tokenizer.
2026-08-18 20:56:40 -07:00
Story Crater Bot 4c54674dff fix(llm-serving): enable tool calling on homelab-reasoning
pi sends tool_choice="auto" for every session (Read/Bash/etc.) -- vLLM 400s on that without --enable-auto-tool-choice and a --tool-call-parser. Verified this deployed vLLM v0.11.0's registered parsers directly; deepseek_v3 matches, same family as the deepseek_r1 reasoning-parser already set (this Qwen-base distillation still emits DeepSeek's own tool-call format).
2026-08-18 20:50:21 -07:00
Story Crater Bot 05ff12c117 fix(agent-pod): use process.exitCode not process.exit() in coordinator.js
process.exit() right after console.log() can drop buffered stdout when it's piped (not a TTY) -- exactly kubectl exec's case. Explains the silent empty-output-exit-1 failures. process.exitCode + natural exit lets the event loop drain and flush first.
2026-08-18 19:13:07 -07:00
Story Crater Bot 56b1c96fcf fix(agent-pod): clone deterministically, not through a headless LLM call
git clone is mechanical -- routing it through spawnPi meant a crash gave zero diagnostic output, just a silent exit code. Direct runGit call now, same as commitPending/the squash-merge sequence. Drops the now-unused runStageWithResolver.
2026-08-18 18:57:18 -07:00
Story Crater Bot 26a959215e fix(agent-pod): sync coordinator.js ConfigMap, was stale since auto-discovery landed
The pod's coordinator-src ConfigMap still had the pre-auto-discovery version -- --tasks was required, no task-board parsing, no self-chained stages, no judge model routing. Regenerated from the current source.
2026-08-18 18:42:45 -07:00
Story Crater Bot 193b040de6 feat(agent-pod): implementer and judge learn Playwright for UI verification
Both skills already have Bash in allowed-tools -- no new pi capability needed. For UI/frontend work, implementer screenshots/clicks through the golden path via npx playwright instead of trusting that code compiling means it renders correctly; judge does the same as review evidence, FAILing on visual defects a diff alone wouldn't show. Doesn't apply to non-UI work.
2026-08-18 18:37:46 -07:00
Story Crater Bot 12778d5576 feat(llm-serving): scale ornith to 2 replicas instead of a dedicated grm GPU
reasoning keeps its 2 GPUs untouched. verifier's freed GPU goes to a second ornith replica instead of a standalone qwen-only pod -- both replicas load ornith:35b + qwen2.5:3b-instruct, k8s Service load-balances across them, so 2 concurrent implementer-style calls get independent instances.
2026-08-18 18:25:12 -07:00