Compare commits
No commits in common. "master" and "task/redeploy-fix" have entirely different histories.
master
...
task/redep
|
|
@ -1,116 +0,0 @@
|
|||
---
|
||||
name: kb-authoring
|
||||
description: Conventions for writing/editing source knowledge-base documents under kb/**/*.md (frontmatter schema, type taxonomy, visibility default, validation). Trigger whenever creating or editing a file under kb/ — this is about authoring the sources, not publishing kb-site (see kb-publish for that).
|
||||
---
|
||||
|
||||
## Scope
|
||||
|
||||
This skill governs **writing kb/\*\*/\*.md documents themselves** — the OKF-format
|
||||
knowledge base sources. It is not about publishing them: for "should I run the
|
||||
publish script", see the `kb-publish` skill, referenced again at the bottom
|
||||
here.
|
||||
|
||||
`docs/sessions/*.md` files use `type: session-log` frontmatter and are validated
|
||||
by the same script, but they are **not** kb/ documents — they are a running
|
||||
diary of work sessions. **Never convert a session log into a kb/ doc** and
|
||||
never move/copy a kb/ doc's content into docs/sessions/. If material in a
|
||||
session log deserves a permanent home (a decision, an incident writeup, a
|
||||
runbook), write a **new** file under kb/ that captures it properly — don't
|
||||
relocate the diary entry.
|
||||
|
||||
## Frontmatter schema (OKF v0.1)
|
||||
|
||||
Every kb/ document opens with a YAML frontmatter block (`---` ... `---`) as
|
||||
the first thing in the file. Validated by `scripts/kb/check_okf.py` — read
|
||||
that file if you need the exact rules; summary:
|
||||
|
||||
| Field | Required | Values | Notes |
|
||||
|---|---|---|---|
|
||||
| `okf` | yes | `"0.1"` | Pinned. Always this literal string, quoted. |
|
||||
| `type` | yes | one of the taxonomy below | Determines which `kb/<type>s/` directory the file lives in. |
|
||||
| `visibility` | yes | `private` \| `public` | **Default is `private`.** See below — never default to `public`. |
|
||||
| `status` | yes | `active` \| `deprecated` \| `planned` | `planned` = decisions not yet made / work not yet started. `deprecated` requires `superseded_by`. |
|
||||
| `updated` | yes | `YYYY-MM-DD` | Bump every time you edit the file's content. |
|
||||
| `links` | yes (may be `[]`) | list of paths | Relative to **this file's own directory**, e.g. `../phases/backlog.md` or `sibling-doc.md`. Every entry must resolve to an existing file — check_okf verifies this. |
|
||||
| `as_of` | only for `type: audit` | `YYYY-MM-DD` | Required exactly when `type: audit`, forbidden otherwise. See "audit" below for why this is a separate field from `updated`. |
|
||||
| `superseded_by` | only when `status: deprecated` | free text or path | Required exactly when `status: deprecated`, forbidden otherwise. Points to whatever replaced this doc (a doc path, or prose describing the replacement if there's no single successor file). |
|
||||
| `contradicts` | optional | list | Free-text notes about known conflicts with other sources (e.g. "CLAUDE.md says X, but the directory doesn't exist"). Entries that look like a `.md` path (contain `/` and end in `.md`) are checked for existence like `links`; plain-text entries are not. |
|
||||
| `stub` | optional | bool | Marks a doc as a placeholder/incomplete. Must be a real YAML bool (`true`/`false`), not a string. |
|
||||
|
||||
## Type taxonomy — kb/<type>s/
|
||||
|
||||
| `type` | Directory | What goes here |
|
||||
|---|---|---|
|
||||
| `node` | `kb/nodes/` | One doc per physical/virtual host — role, configured services, runtime data paths. Mirrors `hosts/<node>/`. |
|
||||
| `service` | `kb/services/` | One doc per deployed service — what it is, how it's used/configured. Mirrors `services/<svc>/`. |
|
||||
| `subsystem` | `kb/subsystems/` | Cross-cutting architecture/design docs describing how something works *in general* (access model, agent system, deployment conventions) — not tied to a single node or service. Kept in sync with current reality (unlike `audit`, see below). |
|
||||
| `decision` | `kb/decisions/` | A choice that was made (or is still open, `status: planned`) plus its rationale — forward-looking, governs future behavior. Gets edited in place and re-dated as the decision evolves; it is not a historical log of what happened. |
|
||||
| `incident` | `kb/incidents/` | A factual account of something that broke: symptom, root cause, fix/status, at a point in time. Slug conventionally date-prefixed (`YYYY-MM-DD-short-description.md`) since incidents are anchored to when they happened. Content generally stays close to the as-happened account rather than being rewritten into "current state" prose. |
|
||||
| `runbook` | `kb/runbooks/` | Step-by-step operational procedure — deploy, install, recover, troubleshoot. Imperative, command-heavy, meant to be followed live. |
|
||||
| `phase` | `kb/phases/` | A project/milestone plan broken into steps, tracking progress (including backlog/roll-up index docs). |
|
||||
| `audit` | `kb/audits/` | A **point-in-time snapshot** of actual/verified state (ground truth recon), never an ongoing description. Requires `as_of` — the date the finding was true — kept distinct from `updated` (the date the doc text was last edited) precisely because an audit's findings can go stale even when nobody touches the file. Slug conventionally date-suffixed (`topic-YYYY-MM-DD.md`). |
|
||||
|
||||
`session-log` also exists as a `type` value (for `docs/sessions/`) but is **out
|
||||
of scope for `kb/`** — see Scope above.
|
||||
|
||||
### Decision vs incident vs runbook vs audit — how ambiguous cases got resolved
|
||||
|
||||
This came up repeatedly during the kb/ migration (docs that mixed genres got
|
||||
split, not force-fit into one type):
|
||||
|
||||
- **decision vs incident**: a doc that both narrates "here's what broke" *and*
|
||||
states "here's the guardrail we adopted because of it" is two documents.
|
||||
Split the incident account into `kb/incidents/`, keep (or extract) the
|
||||
resulting decision/guardrail into `kb/decisions/`. Example:
|
||||
`home-assistant/DESIGN.md` → `kb/decisions/ha-configs-as-code.md` +
|
||||
`kb/incidents/2026-07-22-ha-dwie-instancje.md`.
|
||||
- **decision vs runbook**: if a decision doc contains a reusable operational
|
||||
recipe (install steps, recovery procedure), that section is a runbook, not
|
||||
part of the decision's rationale. Split it out. Example:
|
||||
`deploy-runner` → `kb/services/job-deploy-runner.md` (how it works) +
|
||||
`kb/decisions/deploy-runner-uzasadnienie.md` (why) +
|
||||
`kb/runbooks/deploy-runner-install.md` (how to install/operate it).
|
||||
- **subsystem vs audit**: a `subsystem` doc is the *maintained* description of
|
||||
how something is designed/intended to work — you keep it in sync. An
|
||||
`audit` is a *frozen* investigation result ("I checked X on this date and
|
||||
found Y") — you don't rewrite it as things change, you write a new audit
|
||||
or a decision/incident instead. This is why `audit` got its own `as_of`
|
||||
field distinct from `updated`.
|
||||
- When in doubt, prefer splitting a doc across two types over stretching one
|
||||
type's frontmatter to cover mixed content — that's the pattern the
|
||||
migration itself followed (see git log `feat(kb): SPLIT ...` commits for
|
||||
worked examples).
|
||||
|
||||
## Visibility default: private
|
||||
|
||||
**`visibility` defaults to `private`.** Every new document must be written
|
||||
`private` unless the operator has explicitly and consciously decided it
|
||||
should be `public` — never infer or default to `public` on your own, even if
|
||||
the content looks harmless. `visibility: public` documents are the only ones
|
||||
`scripts/kb/gen_pages.py` will ever emit to the public kb-site (fail-closed:
|
||||
missing/unparseable/unrecognized `visibility` is treated as private).
|
||||
|
||||
## After every change to kb/**/*.md
|
||||
|
||||
Run the validator and fix anything it flags before considering the edit done:
|
||||
|
||||
```bash
|
||||
python3 scripts/kb/check_okf.py
|
||||
```
|
||||
|
||||
It checks frontmatter parses, `okf` is pinned, `type`/`visibility`/`status`
|
||||
are from their closed lists, dates are well-formed, `as_of`/`superseded_by`
|
||||
are present exactly when required, and every `links`/path-like `contradicts`
|
||||
entry resolves to a real file. A red run means something is broken — fix it,
|
||||
don't skip it.
|
||||
|
||||
## Creating a new document
|
||||
|
||||
Use `scripts/kb/new-doc.sh <type> <slug> [--public]` to scaffold a
|
||||
correctly-placed file with valid frontmatter, then fill in the content.
|
||||
|
||||
## If you just made a public change
|
||||
|
||||
If a file you created or edited carries `visibility: public`, don't forget
|
||||
the KB site itself doesn't update on its own — see the `kb-publish` skill for
|
||||
the one-line reminder to run `scripts/kb/publish.sh`.
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
---
|
||||
name: kb-publish
|
||||
description: At session close, asks the operator whether to publish the KB site if kb/**/*.md changed this session. Trigger whenever the session is wrapping up (save-session, "kończymy sesję", natural end of task) and this session's own edits, or a merge/diff visible in git, touched files under kb/.
|
||||
---
|
||||
|
||||
## What this skill does
|
||||
|
||||
Trigger point: **session close**, not every response. Session close means the
|
||||
operator signals they're wrapping up — e.g. invoking `save-session`, saying
|
||||
something like "kończymy sesję" / "koniec na dziś" / "wrap up", or the task
|
||||
reaching its natural end with no further work queued. Don't act on this skill
|
||||
mid-session just because a `kb/` file was touched.
|
||||
|
||||
At that moment, if this session touched `kb/**/*.md` — either through your
|
||||
own edits or through a merge/diff you observed in git — **ask the operator
|
||||
directly**, as a question requiring a yes/no answer, not a passive reminder:
|
||||
|
||||
> Sesja dotknęła kb/. Zregenerować i zasugerować publikację (`bash scripts/kb/publish.sh`)?
|
||||
|
||||
- If the operator confirms (any affirmative reply): print the ready-to-paste
|
||||
command block so they can copy it straight into their own shell:
|
||||
|
||||
```bash
|
||||
bash scripts/kb/publish.sh
|
||||
```
|
||||
|
||||
Do not run it yourself — see below.
|
||||
- If the operator declines: drop it, nothing more to do.
|
||||
- If the operator doesn't respond or ignores the question (moves on to
|
||||
something else, ends the conversation): do **not** ask again in this
|
||||
session. One ask per session, max.
|
||||
|
||||
## What this skill does NOT do
|
||||
|
||||
**Never run `scripts/kb/publish.sh` yourself**, under any circumstances, even
|
||||
if the operator's task prompt says to deploy, publish, or calibrate. The
|
||||
script SSHes into PIHA and overwrites the live `kb-site` content volume on
|
||||
production — that is out of scope for a worktree agent and requires an
|
||||
explicit, direct instruction from the operator in the current turn.
|
||||
|
||||
If the operator explicitly asks you to run it, that instruction stands on its
|
||||
own — this skill only governs the session-close question, not that request.
|
||||
|
|
@ -93,7 +93,7 @@ services:
|
|||
|
||||
preflight fills `arch`, `ram_mb`, `docker_present`, `mm_runtime` — do NOT guess these.
|
||||
|
||||
Full schema: `kb/runbooks/node-onboarding-tool.md`.
|
||||
Full schema: `scripts/onboard/README.md`.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -22,8 +22,6 @@ venv/
|
|||
*.egg-info/
|
||||
packages/*/build/
|
||||
jobs/*/build/
|
||||
# wyjscie generatorow (scripts/kb/gen_pages.py -> build/kb-site/) — artefakt, nie zrodlo
|
||||
build/
|
||||
|
||||
# Tools
|
||||
.aider*
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ Pipeline stages: **prepare → validate → deploy → verify → diagnose (on f
|
|||
## Node Onboarding
|
||||
|
||||
New nodes are onboarded via `scripts/onboard/` — an idempotent bash tool driven by
|
||||
`hosts/<node>/node.yaml` manifests (no Ansible). See `kb/runbooks/node-onboarding-tool.md` for
|
||||
`hosts/<node>/node.yaml` manifests (no Ansible). See `scripts/onboard/README.md` for
|
||||
the full schema, step status table, and gotchas.
|
||||
|
||||
Key fields in `node.yaml`: `ssh_user`, `first_contact` (LAN IP — not `.local`),
|
||||
|
|
@ -93,7 +93,7 @@ Agent → /opt/homelab/actions/pending/<id>.json
|
|||
→ Executor dispatches to the target node → completed / failed
|
||||
```
|
||||
|
||||
The executor never connects to a node (deliberate — see kb/phases/backlog.md
|
||||
The executor never connects to a node (deliberate — see docs/backlog.md
|
||||
"Remediacja floty bez SSH"). It writes a dispatch file that the node collects:
|
||||
|
||||
| Action type | Inbox | Executed on the node by |
|
||||
|
|
@ -109,7 +109,7 @@ Agents must never execute destructive actions (restarts, deploys, config changes
|
|||
|
||||
## Event System
|
||||
|
||||
Events are append-only, one JSON file per event, flat under `/opt/homelab/events/<node>/evt-<node>-<unixts>-<type>[-<service>].json`.
|
||||
Events are append-only JSON lines at `/opt/homelab/events/YYYY-MM-DD/<node>/events.jsonl`.
|
||||
|
||||
Emit via `scripts/lib/events.sh` (shell) or `scripts/lib/events.py` (Python).
|
||||
|
||||
|
|
|
|||
26
README.md
26
README.md
|
|
@ -31,29 +31,29 @@ Action approval flow: `pending/` → operator approves → `approved/` → execu
|
|||
|
||||
## Repository Structure
|
||||
|
||||
- `docs/`: [Infrastructure Standards](kb/subsystems/standards.md) and [Deployment Conventions](kb/subsystems/deployment.md).
|
||||
- `kb/phases/subsystem-a-naprawa.md`: [Current Maintenance Plan (Control Plane)](kb/phases/subsystem-a-naprawa.md).
|
||||
- `docs/`: [Infrastructure Standards](docs/standards.md) and [Deployment Conventions](docs/deployment.md).
|
||||
- `docs/architecture/PLAN-subsystem-a-2026-07-28.md`: [Current Maintenance Plan (Control Plane)](docs/architecture/PLAN-subsystem-a-2026-07-28.md).
|
||||
- `hosts/`: Host-specific configurations and service assignments.
|
||||
- `services/`: Reusable Docker Compose service definitions.
|
||||
- `scripts/`: Deployment and management scripts.
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. **Standardization**: Follow the [Infrastructure Standards](kb/subsystems/standards.md).
|
||||
2. **Deployment**: See [Deployment Conventions](kb/subsystems/deployment.md) for how to roll out changes.
|
||||
1. **Standardization**: Follow the [Infrastructure Standards](docs/standards.md).
|
||||
2. **Deployment**: See [Deployment Conventions](docs/deployment.md) for how to roll out changes.
|
||||
3. **SATURN**: Remember that SATURN is the only node where commits should be made.
|
||||
|
||||
## Documentation Index
|
||||
|
||||
- [Current Maintenance Plan (Control Plane)](kb/phases/subsystem-a-naprawa.md)
|
||||
- [Infrastructure Standards](kb/subsystems/standards.md)
|
||||
- [Agent Operating Procedures](kb/subsystems/agent-operating-procedures.md) (For AI/Non-Human Agents)
|
||||
- [Deployment Conventions](kb/subsystems/deployment.md)
|
||||
- [Hardware](kb/nodes/legacy-hardware.md)
|
||||
- [Networking](kb/subsystems/networking.md)
|
||||
- [Services](kb/subsystems/legacy-services-list.md)
|
||||
- [Node Capabilities](kb/subsystems/capability-model.md)
|
||||
- [Action Model](kb/subsystems/action-approval-model.md)
|
||||
- [Current Maintenance Plan (Control Plane)](docs/architecture/PLAN-subsystem-a-2026-07-28.md)
|
||||
- [Infrastructure Standards](docs/standards.md)
|
||||
- [Agent Operating Procedures](docs/agents.md) (For AI/Non-Human Agents)
|
||||
- [Deployment Conventions](docs/deployment.md)
|
||||
- [Hardware](docs/hardware.md)
|
||||
- [Networking](docs/networking.md)
|
||||
- [Services](docs/services.md)
|
||||
- [Node Capabilities](docs/capabilities.md)
|
||||
- [Action Model](services/agent-system/action-model.md)
|
||||
|
||||
---
|
||||
*Note: This repository documents the state of the homelab. Runtime state lives outside the repository in `/opt/homelab`.*
|
||||
|
|
|
|||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: private
|
||||
status: deprecated
|
||||
updated: 2026-04-15
|
||||
links: []
|
||||
superseded_by: "kb/subsystems/fleet-inventory.md + hosts/<node>/capabilities.yaml (stub z 2026-04-15, sprzed floty)"
|
||||
---
|
||||
|
||||
# Access
|
||||
|
||||
## Description
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: public
|
||||
status: active
|
||||
updated: 2026-05-20
|
||||
links: []
|
||||
---
|
||||
|
||||
# Agent Operating Procedures
|
||||
|
||||
This document defines the operating procedures, constraints, and interaction protocols for non-human agents (AI agents, autonomous scripts) within the Homelab Codex ecosystem.
|
||||
|
|
@ -15,9 +6,9 @@ This document defines the operating procedures, constraints, and interaction pro
|
|||
|
||||
1. **Read-Only by Default**: Agents should assume read-only access to the `/opt/homelab` runtime unless explicitly executing an approved action.
|
||||
2. **Git as Authority**: The repository on **SATURN** is the source of truth. Agents must not modify the runtime state on nodes directly without corresponding (or pending) Git state, unless it's an emergency mitigation.
|
||||
3. **Human-in-the-Loop (HIL)**: All destructive or structural changes (restarts, deployments, config changes) must follow the [Action Approval Model](action-approval-model.md).
|
||||
3. **Human-in-the-Loop (HIL)**: All destructive or structural changes (restarts, deployments, config changes) must follow the [Action Approval Model](../services/agent-system/action-model.md).
|
||||
4. **Idempotency**: All scripts and actions proposed or executed by agents MUST be idempotent.
|
||||
5. **Context-Awareness**: Agents MUST read the `README.md` and `kb/subsystems/agent-operating-procedures.md` at the start of every session to align with current infrastructure standards.
|
||||
5. **Context-Awareness**: Agents MUST read the `README.md` and `docs/agents.md` at the start of every session to align with current infrastructure standards.
|
||||
|
||||
## 2. Agent Roles
|
||||
|
||||
|
|
@ -1,17 +1,8 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: decision
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-29
|
||||
links: []
|
||||
---
|
||||
|
||||
# Architektura — decyzje obowiązujące
|
||||
|
||||
Stan decyzji na 2026-07-28. Podstawa dowodowa:
|
||||
[RECON-multiagent-2026-07-27.md](../subsystems/recon-multiagent.md); plan wykonawczy:
|
||||
[PLAN-subsystem-a-2026-07-28.md](../phases/subsystem-a-naprawa.md). Zmiana którejkolwiek
|
||||
[RECON-multiagent-2026-07-27.md](RECON-multiagent-2026-07-27.md); plan wykonawczy:
|
||||
[PLAN-subsystem-a-2026-07-28.md](PLAN-subsystem-a-2026-07-28.md). Zmiana którejkolwiek
|
||||
decyzji wymaga aktualizacji tego pliku z nową datą.
|
||||
|
||||
## Dwa subsystemy (2026-07-28)
|
||||
|
|
@ -42,7 +33,7 @@ Stack ai-cluster na vps (openclaw, codex-worker, planner-worker, service-ops-wor
|
|||
redis, mosquitto) jest **wygaszany, nie migrowany**. Bus `codex/*` martwy od
|
||||
2026-06-09 (zero nowych połączeń). Branch `task/ai-cluster-solaria` zostaje
|
||||
**niezmergowany** — pełni rolę dokumentacji. Kontenery na vps zostaną zatrzymane w
|
||||
osobnej, nadzorowanej sesji. Szczegóły: [ai-cluster-LEGACY.md](ai-cluster-legacy.md).
|
||||
osobnej, nadzorowanej sesji. Szczegóły: [ai-cluster-LEGACY.md](ai-cluster-LEGACY.md).
|
||||
|
||||
## Approvale zostają HITL (2026-07-28)
|
||||
|
||||
|
|
@ -1,15 +1,6 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-28
|
||||
links: []
|
||||
---
|
||||
|
||||
# Plan naprawy subsystemu A (control-plane) — 2026-07-28
|
||||
|
||||
Kontekst: kb/subsystems/recon-multiagent.md. Decyzje bazowe:
|
||||
Kontekst: docs/architecture/RECON-multiagent-2026-07-27.md. Decyzje bazowe:
|
||||
- Flota dzieli się na dwa subsystemy. A = utrzymaniowy (control-plane, node-agenty,
|
||||
self-healing) — ten plan. B = zleceniowy (dyspozytor + Telegram + KB + HA +
|
||||
homelab-ops) — prowadzony w osobnym projekcie, poza tym planem.
|
||||
|
|
@ -1,16 +1,6 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: audit
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-30
|
||||
as_of: 2026-07-30
|
||||
links: []
|
||||
---
|
||||
|
||||
# Recon — node-agent vs stability-agent (2026-07-30)
|
||||
|
||||
Read-only recon. Ground truth: `kb/subsystems/recon-multiagent.md`
|
||||
Read-only recon. Ground truth: `docs/architecture/RECON-multiagent-2026-07-27.md`
|
||||
(A1, A2, B7, D15). Source read at master @ `473bf8e`; this branch is cut from
|
||||
master @ `0650eb8`. The two intervening merges (`0650eb8` ha-mcp, `cb8a19d`
|
||||
kb-query tests) touch none of the audited paths — `services/node-agent/`,
|
||||
|
|
@ -66,7 +56,7 @@ control plane, stability-agent feeds the agent-system UI, and stability-agent's
|
|||
half of the event store is a write-only archive nothing has ever read.
|
||||
|
||||
A prior recon reached the same conclusion about the event path on 2026-07-06
|
||||
(`kb/audits/prometheus-cutover-2026-07-06.md:88-91`); it has not been acted on.
|
||||
(`docs/infra/prometheus-cutover-recon-2026-07-06.md:88-91`); it has not been acted on.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -307,7 +297,7 @@ prefix that `container_service_name()` was written to strip.
|
|||
- Remove entries from `hosts/solaria/services.yaml` and `hosts/vps/services.yaml`.
|
||||
- `docker compose down` on vps, piha, solaria (chelsty-infra when reachable).
|
||||
- Purge or archive `/opt/homelab/events/2026-*/` on all four nodes (~5 MB on piha, mostly May).
|
||||
- Update CLAUDE.md (agent-system architecture §1, event-path claim at line 100), `kb/services/chelsty-stability-agent.md`, recon A1/A2/B7.
|
||||
- Update CLAUDE.md (agent-system architecture §1, event-path claim at line 100), `docs/chelsty-stability-agent.md`, recon A1/A2/B7.
|
||||
- **Not covered by the cleanup:** the Redis publisher must be rehomed first or the UI loss is permanent.
|
||||
|
||||
### (b) Merge stability-agent's unique checks into node-agent
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-30
|
||||
links: []
|
||||
---
|
||||
|
||||
# Architecture Recon — multi-agent systems (2026-07-27)
|
||||
|
||||
Read-only recon of the two multi-agent systems (control-plane, ai-cluster) across vps,
|
||||
|
|
@ -615,7 +606,7 @@ No runtime state was touched.
|
|||
|
||||
**Legacy**
|
||||
|
||||
- `kb/decisions/ai-cluster-legacy.md`: ai-cluster is retired in place,
|
||||
- `docs/architecture/ai-cluster-LEGACY.md`: ai-cluster is retired in place,
|
||||
not migrated (bus idle since 2026-06-09, C9); branch `task/ai-cluster-solaria`
|
||||
stays unmerged as documentation; surviving patterns listed; runtime
|
||||
retirement runbook (stop stack on vps, observe `free -m`, remove containers)
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: decision
|
||||
visibility: public
|
||||
status: active
|
||||
updated: 2026-07-30
|
||||
links: []
|
||||
---
|
||||
|
||||
# ai-cluster — LEGACY, wygaszany (decyzja 2026-07-28)
|
||||
|
||||
## Decyzja
|
||||
|
|
@ -14,7 +5,7 @@ links: []
|
|||
Stack **ai-cluster** działający na vps (`ai-cluster-openclaw-1`, `codex-worker`,
|
||||
`planner-worker`, `service-ops-worker`, `redis`, `mosquitto`) jest **wygaszany,
|
||||
nie migrowany**. Podstawa (recon
|
||||
[RECON-multiagent-2026-07-27.md](../subsystems/recon-multiagent.md), C9):
|
||||
[RECON-multiagent-2026-07-27.md](RECON-multiagent-2026-07-27.md), C9):
|
||||
bus `codex/*` jest martwy od **2026-06-09** — zero nowych połączeń przez ~7 tygodni,
|
||||
workery trzymają tylko puste długożyjące połączenia.
|
||||
|
||||
1276
docs/backlog.md
Normal file
1276
docs/backlog.md
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: public
|
||||
status: active
|
||||
updated: 2026-05-20
|
||||
links: []
|
||||
---
|
||||
|
||||
# Node Capability Model
|
||||
|
||||
This document defines the capability model for the homelab infrastructure. The goal is to provide a declarative way to describe what each node can do, its constraints, and its suitability for various workloads.
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: node
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-05-27
|
||||
links:
|
||||
- ../runbooks/chelsty-deploy-recovery.md
|
||||
---
|
||||
|
||||
# CHELSTY Runtime
|
||||
|
||||
This document describes the runtime environment and deployment flow for CHELSTY, an offline-capable home automation edge node split across two VMs.
|
||||
|
|
@ -110,6 +100,48 @@ services:
|
|||
|
||||
Remove `monitor: false` once node-agent is bootstrapped on this VM.
|
||||
|
||||
## Deployment Flow
|
||||
|
||||
### Initial Bootstrap
|
||||
```bash
|
||||
./scripts/bootstrap/chelsty-runtime.sh
|
||||
```
|
||||
|
||||
### Deploy services
|
||||
```bash
|
||||
./scripts/deploy/deploy-node.sh chelsty-infra
|
||||
./scripts/deploy/deploy-node.sh chelsty-ha
|
||||
```
|
||||
|
||||
### Manual (SSH) — chelsty-infra uses docker-compose v1
|
||||
```bash
|
||||
ssh oskar@100.122.201.22
|
||||
cd ~/homelab-codex-ws/services/<service>
|
||||
docker-compose -f docker-compose.yml \
|
||||
-f ../../hosts/chelsty-infra/runtime/<service>/docker-compose.override.yml \
|
||||
up -d --build --force-recreate
|
||||
```
|
||||
|
||||
> **Note:** `docker compose` (v2) is **not** available on chelsty-infra — always use `docker-compose` (hyphenated, v1 1.29.2).
|
||||
|
||||
## Recovery Procedures
|
||||
|
||||
### Mosquitto stopped
|
||||
```bash
|
||||
ssh oskar@100.122.201.22 "docker start mosquitto"
|
||||
# Ensure restart policy is correct:
|
||||
docker update --restart unless-stopped mosquitto
|
||||
```
|
||||
|
||||
### Zigbee2MQTT won't start
|
||||
1. Check logs: `docker logs zigbee2mqtt --tail 50`
|
||||
2. Verify SLZB-06U reachable from host: `nc -zv 192.168.1.105 6638`
|
||||
3. Verify config is not empty: `cat /opt/homelab/data/zigbee2mqtt/data/configuration.yaml`
|
||||
4. If config missing, recreate from the minimal template above
|
||||
|
||||
### SLZB-06U unreachable
|
||||
`192.168.1.105:6638` EHOSTUNREACH means the coordinator is offline or the LAN is down. Zigbee2MQTT will keep retrying — no restart needed once the coordinator returns.
|
||||
|
||||
## Critical Backup Sets
|
||||
|
||||
| Data | Path |
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: service
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-05-20
|
||||
links: []
|
||||
---
|
||||
|
||||
### CHELSTY Stability Agent
|
||||
|
||||
The stability-agent on CHELSTY provides local observability and health monitoring for the node's services and infrastructure.
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: private
|
||||
status: deprecated
|
||||
updated: 2026-04-15
|
||||
links: []
|
||||
superseded_by: "kb/subsystems/fleet-inventory.md + hosts/<node>/capabilities.yaml (stub z 2026-04-15, sprzed floty)"
|
||||
---
|
||||
|
||||
# Core Stack
|
||||
|
||||
## Description
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-25
|
||||
links:
|
||||
- ../incidents/deploy-sh-vps-niszczy-control-plane.md
|
||||
---
|
||||
|
||||
# Deployment Conventions
|
||||
|
||||
This document describes the GitOps-lite deployment process for the homelab.
|
||||
|
|
@ -20,6 +10,21 @@ This document describes the GitOps-lite deployment process for the homelab.
|
|||
4. **Tailscale Mesh**: All hosts are connected via Tailscale, allowing secure communication without public port exposure.
|
||||
5. **Host Autonomy**: Services that must operate during WAN or Git outages keep their runtime dependencies on the execution node or local LAN.
|
||||
|
||||
## ⚠️ ZNANY BUG — `deploy.sh vps` niszczy control-plane (2026-06-25)
|
||||
|
||||
`deploy.sh vps` uruchamia `deploy-node.sh` w pętli po wszystkich serwisach VPS, w tym
|
||||
`control-plane`. Pętla używa innego `COMPOSE_PROJECT_NAME` niż `deploy-local.sh`
|
||||
(który uruchamiany jest z `cwd=services/control-plane`). Niezgodność project-name powoduje
|
||||
`Recreate` → `No such container` → `set -e` przerywa pętlę → **observer, supervisor,
|
||||
executor i operator-ui znikają z VPS.**
|
||||
|
||||
**Dopóki bug nie zostanie naprawiony (backlog — Krytyczny):**
|
||||
- Do deployu control-plane używać: `ssh -t vps 'cd ~/homelab-codex-ws && cd services/control-plane && bash deploy-local.sh'`
|
||||
- Inne serwisy VPS deployować punktowo: `deploy-node.sh` z `--service <name>` lub przez SSH + `docker compose up -d`
|
||||
- **NIE uruchamiać `deploy.sh vps` bez pełnej świadomości ryzyka.**
|
||||
|
||||
---
|
||||
|
||||
## Staged Deployment Framework
|
||||
|
||||
The homelab uses a modularized staged deployment framework located at `scripts/deploy/deploy.sh`. This script is designed to be resumable, stage-aware, and observable, with core logic split into maintainable libraries in `scripts/lib/`.
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: public
|
||||
status: active
|
||||
updated: 2026-05-12
|
||||
links: []
|
||||
---
|
||||
|
||||
# Homelab Event System
|
||||
|
||||
The homelab multi-agent platform uses a filesystem-first event architecture for observability, auditability, and agent reasoning.
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: node
|
||||
visibility: private
|
||||
status: deprecated
|
||||
updated: 2026-04-15
|
||||
links: []
|
||||
superseded_by: "hosts/<node>/capabilities.yaml + kb/subsystems/fleet-inventory.md"
|
||||
---
|
||||
|
||||
# Hardware
|
||||
|
||||
## Description
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: node
|
||||
visibility: private
|
||||
status: deprecated
|
||||
updated: 2026-04-15
|
||||
links: []
|
||||
superseded_by: "kb/nodes/vps.md + kb/subsystems/fleet-inventory.md (stub z 2026-04-15, sprzed floty)"
|
||||
---
|
||||
|
||||
# Hetzner VPS
|
||||
|
||||
## Description
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: incident
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-30
|
||||
links: []
|
||||
---
|
||||
|
||||
# Incydent: zniknięcie kontenera `ollama` na SOLARII — 2026-07-30
|
||||
|
||||
**Status:** root-cause ustalony, potwierdzony logiem i kodem. Fix NIE zaimplementowany (świadomie — patrz §7).
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-03
|
||||
links: []
|
||||
---
|
||||
|
||||
# Inwentaryzacja floty homelab-codex — 2026-06-30
|
||||
|
||||
Zebrano: 2026-06-30 17:09 CEST
|
||||
|
|
@ -1,17 +1,8 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-02
|
||||
links: []
|
||||
---
|
||||
|
||||
# Weryfikacja inwentaryzacji floty 2026-06-30 — stan na 2026-07-02
|
||||
|
||||
Zebrano: 2026-07-02 ~15:20 CEST (read-only recon, zero zmian na nodach).
|
||||
Metoda: ssh + `docker ps -a / inspect / logs`, `free/df/nproc/lscpu/lsblk`, `git branch/log` (odczyt),
|
||||
`curl` do fleet-prometheus API. Porównanie z `kb/subsystems/fleet-inventory.md` (23 rozjazdy)
|
||||
`curl` do fleet-prometheus API. Porównanie z `docs/infra/inventory-2026-06-30.md` (23 rozjazdy)
|
||||
oraz z repo na `master` (HEAD `22adfb1`).
|
||||
|
||||
Dostępność nodów podczas weryfikacji:
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: audit
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-16
|
||||
as_of: 2026-07-16
|
||||
links: []
|
||||
---
|
||||
|
||||
# Recon: lustro `event=dead prom=up` — 1507 mismatchy w shadow-liveness.log (2026-07-16)
|
||||
|
||||
READ-ONLY recon. Zero zmian w kodzie/serwisach. Wszystkie czasy **UTC**
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: audit
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-14
|
||||
as_of: 2026-07-14
|
||||
links: []
|
||||
---
|
||||
|
||||
# Monitoring coverage — co biega vs co jest monitorowane (recon 2026-07-14)
|
||||
|
||||
**Pytanie:** czy wszystkie serwisy floty są monitorowane?
|
||||
|
|
@ -131,7 +121,7 @@ compose-service kontenera.
|
|||
| owntracks-prometheus-exporter-prometheus-owntracks-exporter-1 | linusgroh/prometheus-owntracks-exporter | Up 2w | 0.0.0.0:8780→80 |
|
||||
| own-tracks-frontend-owntracks-frontend-1 | owntracks/frontend | Up 2w | 0.0.0.0:8084→80 |
|
||||
|
||||
Zmiany vs audyt 2026-06-30 (`kb/subsystems/fleet-inventory.md`): **przybyły** paperless,
|
||||
Zmiany vs audyt 2026-06-30 (`docs/infra/inventory-2026-06-30.md`): **przybyły** paperless,
|
||||
paperless-db, paperless-broker (Deploy 1, 2026-07-10); **zniknęły** diskover i elasticsearch
|
||||
(w audycie 06-30 były w 33 shadow; dziś nie biegają). 06-30: 40 kontenerów → dziś: 42.
|
||||
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-07
|
||||
links: []
|
||||
---
|
||||
|
||||
# Migracja okit.pl: 42.pl (FreeDNS) -> Cloudflare — plan faz
|
||||
|
||||
Cel: okit.pl na Cloudflare (jak kapala.org) -> wildcard *.okit.pl DNS-01 ->
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: runbook
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-16
|
||||
links: []
|
||||
---
|
||||
|
||||
# Ollama SOLARIA: manual → declarative cutover runbook
|
||||
|
||||
Date: 2026-07-15
|
||||
|
|
@ -97,7 +88,7 @@ bind-mount the existing model directory.**
|
|||
docker exec ollama ollama ps
|
||||
```
|
||||
3. Embeddings endpoint + vector dimension (deferred check from
|
||||
`kb/phases/kb-m5-faza2.md` §6 step 2):
|
||||
`docs/kb/modules/05-faza2-plan.md` §6 step 2):
|
||||
```bash
|
||||
curl -s http://localhost:11434/api/embeddings -d '{"model":"bge-m3","prompt":"test"}' \
|
||||
| python3 -c "import json,sys; v=json.load(sys.stdin)['embedding']; print(len(v))"
|
||||
|
|
@ -145,7 +136,7 @@ SOLARIA:
|
|||
- Given the missing driver, the cutover proceeded **in CPU-only mode**: the
|
||||
`deploy.resources` GPU reservation was commented out in
|
||||
`services/ollama/docker-compose.yml` (commit `f57a01a`), and the driver fix
|
||||
was filed as a backlog item (see `kb/phases/backlog.md`) blocking the module 5
|
||||
was filed as a backlog item (see `docs/backlog.md`) blocking the module 5
|
||||
mail-embedding phase.
|
||||
- **2026-07-16: driver fixed.** Installed `nvidia-driver-595-open` from the
|
||||
distro repository — not the old `ppa:graphics-drivers/ppa` (jammy), which
|
||||
|
|
@ -1,16 +1,6 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: audit
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-02
|
||||
as_of: 2026-07-02
|
||||
links: []
|
||||
---
|
||||
|
||||
# Audyt odchudzania PIHA — 2026-07-02
|
||||
|
||||
> Faza 1 (READ-ONLY) modulu 0 filaru dokumentow (`kb/phases/kb-m0-piha-slim.md`).
|
||||
> Faza 1 (READ-ONLY) modulu 0 filaru dokumentow (`docs/kb/modules/00-piha-slim.md`).
|
||||
> Zadna akcja nie zostala wykonana — wylacznie `docker stats/inspect/logs`, `ss`, `curl` (odczyt).
|
||||
> Stan w momencie audytu: **RAM 7.9Gi total, 5.0Gi used, 2.9Gi available; swap 4Gi total, 2.0Gi uzyty.**
|
||||
> 41 kontenerow Up (inwentaryzacja 2026-06-30 liczyla 40; wszystkie nadal biega).
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: audit
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-06
|
||||
as_of: 2026-07-06
|
||||
links: []
|
||||
---
|
||||
|
||||
# Prometheus liveness cutover — recon starego toru (2026-07-06)
|
||||
|
||||
Read-only recon przed cutoverem liveności floty na Prometheus `up{}`. Mapa obecnego
|
||||
|
|
@ -300,7 +290,7 @@ renderuje `health`/`status`/`last_seen`), `/unhealthy` (`:302-334`), `/summary`,
|
|||
chelsty/chelsty-infra (exporter DOWN po LTE, 2026-06-26).
|
||||
- Reguła `NodeDown` (`rules/liveness.yml:21-28`): `up{node=~"vps|piha"} == 0`,
|
||||
`for: 5m`, severity critical. solaria/lustro świadomie wykluczone (`:12-16` —
|
||||
planned power-off; docelowo anomaly detection, `kb/phases/backlog.md:390-406`).
|
||||
planned power-off; docelowo anomaly detection, `docs/backlog.md:390-406`).
|
||||
Bez Alertmanagera by design (`:3-7`) — delivery = brain-watchdog poll `/api/v1/alerts`.
|
||||
- node_exporter w repo tylko dla VPS (`services/node_exporter/`, network_mode: host,
|
||||
`hosts/vps/services.yaml:36-43`). Exportery na piha/solaria/lustro **nie mają
|
||||
|
|
@ -348,7 +338,7 @@ chelsty-infra, chelsty-ha, lustro.
|
|||
| lustro | TAK (`:50-52`) | NIE | TAK (bez stability-agenta) | jw. |
|
||||
| **chelsty-infra** | **NIE** (`:57-60`, exporter DOWN po LTE) | NIE | **TAK** (remote TTL 900/3600, `liveness.py:43-50`) | **tylko stary tor — cutover totalny zostawiłby go bez liveności** |
|
||||
| chelsty-ha | NIE | NIE | NIE (`hosts/chelsty-ha/services.yaml:6-12`, `monitor: false`) | już dziś bez liveności (pośrednio przez MQTT chelsty-infra) — cutover nic nie zmienia |
|
||||
| saturn | NIE (`:55`, laptop) | NIE | NIE (brak `hosts/saturn/services.yaml`, `kb/phases/backlog.md:423`) | już dziś bez liveności — cutover nic nie zmienia |
|
||||
| saturn | NIE (`:55`, laptop) | NIE | NIE (brak `hosts/saturn/services.yaml`, `docs/backlog.md:423`) | już dziś bez liveności — cutover nic nie zmienia |
|
||||
|
||||
**Chelsty offline ~34 dni — jak traktuje go stara rura:** eventy buforują się lokalnie
|
||||
(rsync fail = non-fatal, `node_agent.py:560-566`), `last_seen` na VPS zamrożone sprzed
|
||||
|
|
@ -361,7 +351,7 @@ totalnym chelsty-infra nie miałby żadnej liveności i żadnego przejścia offl
|
|||
Dodatkowo docs sygnalizują konflikt IP w komentarzach `prometheus.yml:57` vs
|
||||
`hosts/chelsty-infra/host.yaml:12` — do wyjaśnienia przy ewentualnym dodawaniu scrape.
|
||||
*(rzeczywisty bieżący stan chelsty — do weryfikacji na żywo; ostatni zapis:
|
||||
UNREACHABLE, `kb/subsystems/fleet-inventory-verify.md:17,151`)*
|
||||
UNREACHABLE, `docs/infra/inventory-verify-2026-07-02.md:17,151`)*
|
||||
|
||||
**Wniosek twardy:** cutover NIE może być globalny. Docelowa architektura to
|
||||
**hybryda per-node**: `up{}` dla scrape'owanych (vps, piha, solaria, lustro),
|
||||
|
|
@ -460,7 +450,7 @@ z `last_seen` — rzadszy heartbeat przy niezmienionych TTL-ach = fałszywe degr
|
|||
- chelsty-infra: zbadać exporter-over-LTE (`prometheus.yml:57-60` + konflikt IP
|
||||
z `hosts/chelsty-infra/host.yaml:12`); do tego czasu zostaje na torze eventowym.
|
||||
- NodeDown dla solaria/lustro: świadomie odroczone do anomaly detection
|
||||
(`kb/phases/backlog.md:390-406`) — nie wciągać do cutoveru.
|
||||
(`docs/backlog.md:390-406`) — nie wciągać do cutoveru.
|
||||
- Watchdog na sam Prometheus (D.2 pkt 5) — mały task przy etapie 3.
|
||||
- saturn / chelsty-ha: świadomie poza monitoringiem — status quo.
|
||||
|
||||
|
|
@ -468,7 +458,7 @@ z `last_seen` — rzadszy heartbeat przy niezmienionych TTL-ach = fałszywe degr
|
|||
|
||||
**Seria.** Minimalnie trzy taski implementacyjne + weryfikacje między nimi:
|
||||
(1) etap 1 shadow-read; (2) etap 3 flaga per-node (po tygodniu etapu 2);
|
||||
(3) watchdog-na-Prometheusa + aktualizacja `kb/subsystems/observer.md`.
|
||||
(3) watchdog-na-Prometheusa + aktualizacja `docs/observer-runtime.md`.
|
||||
Etap 0 to czynność operatorska (runtime, nie repo). Etap 5 to niezależny backlog.
|
||||
|
||||
---
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-15
|
||||
links: []
|
||||
---
|
||||
|
||||
# Prometheus cutover — Etap 2: analiza zgodności shadow-run (2026-07-15)
|
||||
|
||||
Analiza READ-ONLY logów `SHADOW_LIVENESS_MISMATCH` observera (parallel-run od
|
||||
|
|
@ -164,7 +155,7 @@ Skutek uboczny do zaakceptowania świadomie: syntetyczne `node_stale`/
|
|||
wyłączeniu **wcześniej, ale nie liczniej** — te eventy już dziś powstają co noc
|
||||
(21:32/21:39 dla lustro, każdorazowo dla solaria). Cutover nie zwiększa wolumenu
|
||||
alertów. Docelowe wyciszenie planowych okien off to wątek anomaly-detection
|
||||
z backlogu (`kb/phases/backlog.md:390-406`) — **niezależny od cutoveru i nieblokujący**;
|
||||
z backlogu (`docs/backlog.md:390-406`) — **niezależny od cutoveru i nieblokujący**;
|
||||
`NodeDown` dla solaria/lustro słusznie pozostaje wyłączony.
|
||||
|
||||
### Rekomendowany mapping (potwierdzenie rekomendacji z recon F/Etap 2)
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: audit
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-27
|
||||
as_of: 2026-07-27
|
||||
links: []
|
||||
---
|
||||
|
||||
# Audyt niezarządzanych stacków na VPS — 2026-07-27
|
||||
|
||||
Recon read-only przed konsolidacją do GitOps. Zebrane przez `ssh vps` (user `oskar`,
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: service
|
||||
visibility: private
|
||||
status: deprecated
|
||||
updated: 2026-04-15
|
||||
links: []
|
||||
superseded_by: "brak katalogu services/joplin/ w repo — patrz contradicts w kb/subsystems/repo-operating-contract.md"
|
||||
---
|
||||
|
||||
# Joplin Server
|
||||
|
||||
## Description
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-16
|
||||
links: []
|
||||
---
|
||||
|
||||
# Eval-set: pilot retrieval (faza 2, krok 7) — 2026-07-16
|
||||
|
||||
Stan bazy: document_chunk = 2683 chunki (bge-m3, dim 1024), 160 dokumentów z 186 kopert paperless.
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-26
|
||||
links:
|
||||
- ../decisions/kb-log-decyzji.md
|
||||
---
|
||||
|
||||
# Baza wiedzy — przegląd i log decyzji (homelab-codex · KB)
|
||||
|
||||
> Master-dokument inicjatywy. Stoi ponad dokumentami per-projekt (`kb-01-email-design.md`, …).
|
||||
|
|
@ -92,6 +82,21 @@ Dwa dolne tiery są per-filar i neutralne. Dwa górne są wspólne dla wszystkic
|
|||
|
||||
---
|
||||
|
||||
## Decyzje — zamknięte vs otwarte
|
||||
|
||||
**Zamknięte:**
|
||||
- Spine: Postgres + pgvector (nie Qdrant).
|
||||
- Embed: **bge-m3** (multilingual, długi kontekst — pod polski lepszy niż multilingual-e5).
|
||||
- Załączniki: indeksowane w **II turze** (MVP najpierw czysty tekst).
|
||||
- Warstwa 3 startuje jako **cienki graf encji**; federacja przy zapytaniu dochodzi później (docelowo hybryda).
|
||||
- Dokumenty: Nextcloud + Paperless-ngx.
|
||||
|
||||
**Otwarte:**
|
||||
- **Transakcje:** agregator vs CSV, pokrycie mBanku, Revolut, koszt (filar #4).
|
||||
- **Maile §design:** sizing archiwum / node (ile waży Gmail), unifikacja adaptera (jeden IMAP dla obu vs JMAP+IMAP osobno).
|
||||
|
||||
---
|
||||
|
||||
## Tor równoległy (nie tutaj)
|
||||
|
||||
Hardening homelabu / stabilizacja control-plane — osobny wątek.
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-08-06
|
||||
links: []
|
||||
---
|
||||
|
||||
# Filar maili — projekt (homelab-codex · KB · projekt #1)
|
||||
|
||||
> Pierwszy filar. Wzorzec referencyjny dla pozostałych (archiwum, embeddingi na SOLARIA, szkielet agenta, deploy).
|
||||
|
|
@ -27,22 +18,9 @@ Realna potrzeba to najpierw **archiwum**, nie „RAG nad mailami". Dwie warstwy,
|
|||
|
||||
Gmail **nie jest porzucany** — zostaje jako konto śmieciowe / loginy / 2FA. Stąd maile mają dwa żywe wejścia:
|
||||
|
||||
- **Fastmail** — `source: fastmail`, adapter **IMAP** (hasło aplikacji). Primary: tu ląduje sensowna poczta na przyszłość.
|
||||
- **Fastmail** — `source: fastmail`, adapter **JMAP** (read-only token). Primary: tu ląduje sensowna poczta na przyszłość.
|
||||
- **Gmail** — `source: gmail`, adapter **IMAP** (protokół, nie Gmail API → przenośność). Ciągły sync żywej skrzynki.
|
||||
|
||||
> **Korekta 2026-08-06 — Fastmail przez IMAP, nie JMAP.** Do tej daty ten dokument (i §7, §9
|
||||
> oraz §10 planu fazy mailowej) przewidywał dla Fastmaila **JMAP** i osobny `jobs/fastmail-poller`.
|
||||
> Zapis historyczny: *„Fastmail — adapter JMAP (read-only token)"*, 2026-06-24.
|
||||
>
|
||||
> Decyzja z 2026-08-06 (recon `kb/audits/mail-sync-2026-08-06.md` Decyzja (b), zatwierdzona
|
||||
> przez operatora) domyka otwartą od czerwca decyzję „unifikacja adaptera" z §9 na rzecz
|
||||
> **jednego wspólnego IMAP-a dla obu kont**, w jednym jobie `jobs/mail-imap-sync`. Powody:
|
||||
> JMAP synchronizuje po `state` — elegancko i niepotrzebnie przy jednym ticku na godzinę
|
||||
> i ~37 mailach na dobę, skoro UIDVALIDITY/UIDNEXT rozwiązuje ten sam problem i tak trzeba go
|
||||
> zaimplementować dla Gmaila; jeden adapter to jeden zestaw testów, jedna klasa błędów i jedna
|
||||
> ścieżka hardeningu 8-bitowych nagłówków. JMAP nie jest zamknięty na zawsze — koperta
|
||||
> i archiwum są protokołowo obojętne, więc wymiana transportu nie dotyka danych.
|
||||
|
||||
Plus jednorazowy **bulk historyczny Gmaila** (eksport „All Mail" / Takeout → surowy dump do archiwum). Operacja odwracalna i niezależna od reszty pipeline'u — robimy pierwsza. Urgency spadła (konto żyje), ale historia warta zassania od razu.
|
||||
|
||||
---
|
||||
|
|
@ -94,9 +72,7 @@ Załączniki: **II tura** (MVP = czysty tekst + nagłówki).
|
|||
## 7. Deploy
|
||||
|
||||
- Wszystko w `homelab-codex`, przez Git na SATURN, konwencja override `hosts/<node>/runtime/<svc>/`.
|
||||
- Usługi: `mail-imap-sync` (Fastmail + Gmail, jeden job — korekta 2026-08-06; wcześniej
|
||||
planowane jako osobne `jmap-poller` + `imap-poller`), `indexer`, embed (ollama na SOLARIA),
|
||||
`postgres+pgvector`, `mail-agent`; bulk importer jako one-shot job.
|
||||
- Usługi: `jmap-poller` (Fastmail), `imap-poller` (Gmail), `indexer`, embed (ollama na SOLARIA), `postgres+pgvector`, `mail-agent`; bulk importer jako one-shot job.
|
||||
- Deploy skryptem czytającym `inventory/topology.yaml`.
|
||||
|
||||
---
|
||||
|
|
@ -105,10 +81,8 @@ Załączniki: **II tura** (MVP = czysty tekst + nagłówki).
|
|||
|
||||
1. ✅ Zamroź kopertę + postaw Postgres+pgvector. *(2026-06-17)*
|
||||
2. ✅ **Bulk Gmail historyczny → archiwum** — `jobs/gmail-bulk-import/` — **KOD GOTOWY** *(2026-06-24)*; nie uruchomiony (Takeout ~27 GB na SOLARIA, do transferu na PIHA).
|
||||
3. ~~Fastmail JMAP live ingest~~ → **Fastmail IMAP live sync** → archiwum. *(korekta
|
||||
2026-08-06; kod gotowy, pierwszy żywy run po stronie operatora —
|
||||
`kb/runbooks/mail-sync-run.md`)*
|
||||
4. Gmail IMAP live sync → archiwum. *(j.w. — ten sam job `jobs/mail-imap-sync`)*
|
||||
3. Fastmail JMAP live ingest → archiwum.
|
||||
4. Gmail IMAP live sync → archiwum.
|
||||
5. Filtr archiwum→indeks.
|
||||
6. Indexer (parse → chunk → embed bge-m3) → pgvector.
|
||||
7. Cienki agent maili + tool dla warstwy 4.
|
||||
|
|
@ -117,12 +91,8 @@ Załączniki: **II tura** (MVP = czysty tekst + nagłówki).
|
|||
|
||||
## 9. Decyzje otwarte (do przyklepania przed/w trakcie startu)
|
||||
|
||||
- ✅ **Sizing Gmaila** — ZAMKNIĘTE: 225 030 kopert, archiwum ~27 GB na PIHA (Etap B, 2026-08-06).
|
||||
- ✅ **Unifikacja adaptera** — ZAMKNIĘTE 2026-08-06 na rzecz **jednego IMAP-a** dla obu kont
|
||||
(Decyzja (b) reconu, uzasadnienie w §2 wyżej).
|
||||
- **Sizing Fastmaila** — OTWARTE, i celowo: przesądza o tym, czy ciągniemy historię konta czy
|
||||
tylko przyrost. Rozstrzyga pomiar `mail-imap-sync --measure`, nie zgadywanie —
|
||||
`kb/runbooks/mail-sync-run.md` §5.
|
||||
- **Sizing Gmaila** — ile realnie waży „All Mail"? (przesądza node/dysk archiwum).
|
||||
- **Unifikacja adaptera** — jeden wspólny IMAP dla Fastmail + Gmail (mniej kodu) vs JMAP dla Fastmail + IMAP dla Gmail (JMAP bogatszy)?
|
||||
- **Reguły filtra** — startowa lista blacklist domen/nagłówków.
|
||||
- Vector store: pgvector **przyklepane** (spine).
|
||||
- Embed model: bge-m3 **przyklepane**.
|
||||
|
|
@ -1,18 +1,9 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-01
|
||||
links: []
|
||||
---
|
||||
|
||||
# KB filar #2 — Dokumenty (Nextcloud + Paperless) — design
|
||||
|
||||
> Dokument-master filaru dokumentow. Stoi pod `kb-00-overview.md`.
|
||||
> Cel: kazda sesja / Claude Code startuje z pelnym kontekstem decyzji.
|
||||
> Status: ARCHITEKTURA ZAMKNIETA (2026-07-01), implementacja modulowa czeka.
|
||||
> Moduly implementacyjne: `kb/phases/kb-m*.md` — puszczane CC jeden po drugim.
|
||||
> Moduly implementacyjne: `docs/kb/modules/0X-*.md` — puszczane CC jeden po drugim.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-02
|
||||
links: []
|
||||
---
|
||||
|
||||
# Modul 0 — Odchudzic PIHA (prerekwizyt filaru dokumentow)
|
||||
|
||||
> Prerekwizyt modulow 2/4 (Paperless/Nextcloud na PIHA). Bez tego PIHA nie ma
|
||||
|
|
@ -15,7 +6,7 @@ links: []
|
|||
## STATUS: prerekwizyt RAM SPELNIONY (2026-07-02)
|
||||
|
||||
Faza 1 (audyt read-only) + faza 2 (egzekucja po review Oskara) wykonane —
|
||||
szczegoly: `kb/audits/piha-slim-2026-07-02.md` (sekcja "Korekta po review
|
||||
szczegoly: `docs/infra/piha-slim-audit-2026-07-02.md` (sekcja "Korekta po review
|
||||
+ egzekucja").
|
||||
|
||||
- **Kryterium >= 1.5Gi available: SPELNIONE.** Przed egzekucja: 2.8Gi available
|
||||
|
|
@ -37,7 +28,7 @@ Zwolnic RAM na PIHA (dzis: 3.1Gi available, swap 2G uzyty) tak, by lekki Paperle
|
|||
serwis wszedl z zapasem, nie na styku swap.
|
||||
|
||||
## Wymogi
|
||||
- Audyt 33 shadow-kontenerow (lista w `kb/subsystems/fleet-inventory.md`).
|
||||
- Audyt 33 shadow-kontenerow (lista w `docs/infra/inventory-2026-06-30.md`).
|
||||
- Zidentyfikowac kandydatow do usuniecia/przeniesienia/wylaczenia:
|
||||
- **elasticsearch 1Gi** — kto tego uzywa? (wikijs? diskover?) — jesli martwy, ubic
|
||||
- **diskover** — jednorazowy indekser? czy chodzi ciagle bez potrzeby?
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: decision
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-01
|
||||
links: []
|
||||
---
|
||||
|
||||
# Modul 1 — SSO Forgejo-OIDC (decyzja + wzorzec wpiecia)
|
||||
|
||||
> Fundament tozsamosci dla filaru dokumentow (i szerzej homelaba). Zapisuje decyzje
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-01
|
||||
links: []
|
||||
---
|
||||
|
||||
# Modul 2 — Paperless-ngx serwis (na PIHA)
|
||||
|
||||
> Serwis dokumentow: UI+API+Postgres+Redis. Always-on na PIHA. OCR-worker OSOBNO
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-01
|
||||
links: []
|
||||
---
|
||||
|
||||
# Modul 3 — Paperless OCR-worker (SOLARIA + fallback PIHA)
|
||||
|
||||
> Ciezki OCR odseparowany od serwisu. Worker na SOLARIA (moc), fallback PIHA (wolno).
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-02
|
||||
links: []
|
||||
---
|
||||
|
||||
# Modul 4 — Nextcloud (drive/WebDAV + OIDC)
|
||||
|
||||
> Drugi adapter dokumentow: zamiennik Google Drive, dowolne pliki + sync. Zrodlo
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-02
|
||||
links: []
|
||||
---
|
||||
|
||||
# Modul 5 — Ingest dokumentow -> koperta KB
|
||||
|
||||
> Adapter obu zrodel (Paperless API + Nextcloud WebDAV) -> koperta KB. Domyka filar #2
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-30
|
||||
links: []
|
||||
---
|
||||
|
||||
# Raport dedup: fallback embed SOLARIA→PIHA — e7625cd (master) vs 3d4ee38 (task/kb-f4-fallback)
|
||||
|
||||
**Data**: 2026-07-30 · **Worktree**: `task/kb-fallback-dedup` · **Status**: salvage **wykonany**
|
||||
|
|
@ -71,10 +62,10 @@ zegarem, master trzyma to samo wewnątrz `EmbedRouter` (też injektowalny zegar)
|
|||
| `services/kb-query/{README,env.example,service.yaml,docker-compose.yml}` | ~±58 | duplikat | **porzuć** | inny (porzucony) schemat env `OLLAMA_PIHA_URL`; master bogatszy (testy A/B/C, rename `OLLAMA_URL`→`EMBED_PRIMARY_URL`) |
|
||||
| `packages/kb-retrieval/src/kb_retrieval/embed.py` (`timeout_s` w `embed_chunk`) | +16 | duplikat funkcji | **porzuć** | master osiąga twardy timeout przez `asyncio.wait_for` bez zmiany współdzielonego pakietu — mniejsza powierzchnia zmian, ten sam efekt |
|
||||
| `jobs/documents-ingest/eval/retrieval_eval.py` (`--transport {direct,http}` + `--base-url`) | +109 | **unikalna wartość** | **cherry-pick** | plan §2 decyzja 6 / §9 (bramka HTTP-equivalence) — **na masterze w ogóle nie istnieje**; e7625cd nie tknął tego pliku, patch aplikuje się czysto; kod woła tylko `GET /search` i czyta `envelope_id`/`dist`/`source` — w pełni zgodny z odpowiedzią mastera |
|
||||
| `kb/phases/kb-m5-documents-ingest-fazy.md` | +6 | **unikalna wartość** | **cherry-pick** | dokumentacja powyższego, idzie w parze |
|
||||
| `jobs/documents-ingest/README.md` | +6 | **unikalna wartość** | **cherry-pick** | dokumentacja powyższego, idzie w parze |
|
||||
| `docs/sessions/2026-07-27-kb-f4-fallback.md` | +189 | **unikalna wartość** | **adaptuj** | jedyny zapis: (1) znalezisko osieroconego natywnego `ollama.service` na PIHA + jego wyłączenie 2026-07-27 i backlog odinstalowania, (2) kalibracja live ollama-piha (GO: peak ~983 MiB, ~4.2–5.3 s/embed), (3) metodologia i wyniki bramki §9 (HTTP-equivalence 0 rozbieżności; sol-down Δ~3e-4), (4) rsync-deploy → dirty working tree na PIHA. Wciągnąć z dopiskiem redakcyjnym, że zmergowana implementacja to **inny kod** (e7625cd) i wyniki bramki wymagają powtórki |
|
||||
| `services/ollama-piha/*` (5 plików) | +155 | duplikat | **porzuć** | wersja mastera lepsza: named volume `ollama_piha_models` (uzasadnienie uid-pattern PIHA), healthcheck sprawdza obecność `bge-m3`, bind tylko 127.0.0.1+LAN |
|
||||
| `hosts/piha/runtime/ollama-piha/docker-compose.override.yml` | +13 | duplikat + **1 unikalny fakt** | **adaptuj (mikro)** | ten sam `mem_limit: 2560m`; ale komentarz brancha zawiera potwierdzony pomiar (peak ~983 MiB), a master wciąż mówi „Confirm/trim after live calibration" — dopisać wynik kalibracji do komentarza override'u i/lub sekcji „Calibration" w `kb/services/ollama-piha.md` |
|
||||
| `hosts/piha/runtime/ollama-piha/docker-compose.override.yml` | +13 | duplikat + **1 unikalny fakt** | **adaptuj (mikro)** | ten sam `mem_limit: 2560m`; ale komentarz brancha zawiera potwierdzony pomiar (peak ~983 MiB), a master wciąż mówi „Confirm/trim after live calibration" — dopisać wynik kalibracji do komentarza override'u i/lub sekcji „Calibration" w `services/ollama-piha/README.md` |
|
||||
| `hosts/piha/services.yaml` | ±26 | duplikat | **porzuć** | master ma własny wpis `ollama-piha` + soft-dependency kb-query; drobna różnica (`offline_required: true` na branchu vs `false` na masterze) — master źródłem prawdy |
|
||||
|
||||
---
|
||||
|
|
@ -107,7 +98,7 @@ skonfigurowanego → `EmbedBackendError`, `fallback_status` (up/unconfigured), s
|
|||
## 4. Rekomendacja zbiorcza (lista do zatwierdzenia)
|
||||
|
||||
1. **S1 — cherry-pick**: `retrieval_eval.py --transport http --base-url` + akapit w
|
||||
`kb/phases/kb-m5-documents-ingest-fazy.md` (plan §2 D6/§9; aplikuje się czysto, zero zależności
|
||||
`jobs/documents-ingest/README.md` (plan §2 D6/§9; aplikuje się czysto, zero zależności
|
||||
od porzuconego kodu brancha).
|
||||
2. **S2 — adaptuj**: `docs/sessions/2026-07-27-kb-f4-fallback.md` → `docs/sessions/`
|
||||
z dopiskiem redakcyjnym na górze (implementacja z tej sesji porzucona na rzecz
|
||||
|
|
@ -116,7 +107,7 @@ skonfigurowanego → `EmbedBackendError`, `fallback_status` (up/unconfigured), s
|
|||
3. **S3 — adaptuj**: luki testowe T1 + T2 (T3 opcjonalnie) do `test_embed_router.py`.
|
||||
4. **S4 — adaptuj (mikro)**: wynik kalibracji 2026-07-27 (peak ~983 MiB, ~4.2–5.3 s,
|
||||
werdykt GO) do komentarza `hosts/piha/runtime/ollama-piha/docker-compose.override.yml`
|
||||
i sekcji Calibration w `kb/services/ollama-piha.md` — pomiar dotyczył kontenera
|
||||
i sekcji Calibration w `services/ollama-piha/README.md` — pomiar dotyczył kontenera
|
||||
ollama-piha (ta sama konfiguracja: obraz, `OLLAMA_KEEP_ALIVE=0`, `mem_limit 2560m`),
|
||||
więc **przenosi się** na wersję mastera; różni się tylko storage (bind vs named
|
||||
volume), co nie wpływa na RAM/latencję.
|
||||
|
|
@ -130,7 +121,7 @@ skonfigurowanego → `EmbedBackendError`, `fallback_status` (up/unconfigured), s
|
|||
(3d4ee38) i worktree `~/homelab-codex-ws-kb-f4-fallback` po zakończeniu salvage.
|
||||
- **(b) Powtórka testu sol-down na żywym masterze**: kalibracja i bramka z 2026-07-27
|
||||
dotyczyły **innego kodu** (`fallback.py`, env `OLLAMA_PIHA_URL`) — na wdrożonym
|
||||
e7625cd trzeba przejść testy A/B/C z `kb/services/kb-query.md` oraz bramkę
|
||||
e7625cd trzeba przejść testy A/B/C z `services/kb-query/README.md` oraz bramkę
|
||||
`retrieval_eval.py --transport http` (po S1): HTTP-equivalence przy SOLARIA-up
|
||||
(identyczne `dist`) i sol-down (Δ≤epsilon, kolejność top-k identyczna; baseline
|
||||
z 27.07: Δ~3e-4). Symulacja wg README: `EMBED_PRIMARY_URL=http://192.0.2.1:11434`
|
||||
|
|
@ -1,32 +1,16 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-08-06
|
||||
links: []
|
||||
---
|
||||
|
||||
# Moduł 5, faza mailowa — treść maili w retrievalu (RECON + PLAN)
|
||||
|
||||
> Status (2026-08-06): Kroki 0-5 WYKONANE na żywo (chunker wydzielony, hybrid
|
||||
> retrieval, Etap A apply na żywej bazie, bramka jakościowa **PASS** — patrz §8).
|
||||
> **Etap B (Krok 6) ZAMKNIĘTY 2026-08-06**: pełny korpus gmail jest zchunkowany
|
||||
> i zembedowany (389 012 chunków, zero nie-excluded bez wektora) — patrz §9
|
||||
> „Wynik Etapu B". **Krok 7 (przyrostówka IMAP) — IN PROGRESS 2026-08-06**:
|
||||
> recon `kb/audits/mail-sync-2026-08-06.md` wykonany, decyzje operatora (a)-(g)
|
||||
> **zatwierdzone w całości 2026-08-06**, implementacja w repo (§10 „Zakres
|
||||
> wdrożony"). **Kod nie łączył się z żywym kontem** — pierwszy sync, pomiar
|
||||
> Fastmaila i aktywacja timera to kroki operatora wg
|
||||
> `kb/runbooks/mail-sync-run.md`.
|
||||
> Status (2026-07-23): Kroki 0-4 WYKONANE na żywo (chunker wydzielony, hybrid
|
||||
> retrieval, Etap A apply na żywej bazie), Krok 5 (bramka jakościowa) **PASS**
|
||||
> — patrz §8 dla liczb i werdyktu. Etap B (pełne archiwum) i Krok 7 (recon
|
||||
> IMAP/JMAP) wciąż przed nami.
|
||||
>
|
||||
> Kontynuacja `05-faza4-plan.md` (faza 4: `packages/kb-retrieval` wydzielone,
|
||||
> serwis `kb-query` z UI działa na PIHA — „KB po raz pierwszy odpowiada przez
|
||||
> HTTP", 2026-07-22, `docs/sessions/2026-07-22.md`). Faza mailowa = odpowiedź na
|
||||
> feedback operatora z POC wyszukiwarki: **„mało danych, brak połączeń"**.
|
||||
> W punkcie wyjścia (2026-07-22) 225 030 kopert gmail miało w bazie tylko
|
||||
> nagłówki — treści leżały wyłącznie w archiwum .eml na PIHA (stan zamknięty
|
||||
> Etapem B, §9). Ta faza wprowadza treści maili do `document_chunk`
|
||||
> 225 030 kopert gmail ma dziś w bazie tylko nagłówki — treści leżą wyłącznie
|
||||
> w archiwum .eml na PIHA. Ta faza wprowadza treści maili do `document_chunk`
|
||||
> i udostępnia je w retrievalu. **To nadal wyszukiwarka, nie chat** — synteza,
|
||||
> Drive Takeout i backfill 70k załączników PDF pozostają poza zakresem (§11).
|
||||
|
||||
|
|
@ -468,8 +452,7 @@ i idempotencji (drugi przebieg = zero insertów). Definition of Done z CLAUDE.md
|
|||
`hybrid_query` analogicznie do `cascade_query` (jeden embed zapytania).
|
||||
- `kb-query`: `mode` pattern `^(cascade|flat|hybrid)$`; **domyślny `mode`
|
||||
przełączany na `hybrid` dopiero po PASS bramki (§8)** — do tego czasu
|
||||
hybrid dostępny jawnie. *(Wykonane 2026-08-06: default = `hybrid`, patrz
|
||||
DoD (d) w §12.)* Wyniki gmail w UI już obsłużone (faza 4: subject/from
|
||||
hybrid dostępny jawnie. Wyniki gmail w UI już obsłużone (faza 4: subject/from
|
||||
z headers + „Kopiuj Message-ID").
|
||||
- Testy jednostkowe na mockach (merge, pusta gałąź summary, pusta gałąź mail).
|
||||
|
||||
|
|
@ -584,8 +567,7 @@ płonił bramki co uruchomienie).
|
|||
|
||||
**`kb-query` domyślny `mode`**: przełączenie na `hybrid` jako follow-up (poza
|
||||
zakresem tego zamknięcia bramki — `kb-query`'s `mode` param zmiana to osobna,
|
||||
mała zmiana w serwisie, nie w `packages/kb-retrieval`). **Wykonane 2026-08-06**
|
||||
po regresji na pełnym korpusie (Etap B) — szczegóły przy DoD (d) w §12.
|
||||
mała zmiana w serwisie, nie w `packages/kb-retrieval`).
|
||||
|
||||
## 9. Krok 6 — Etap B: pełne archiwum
|
||||
|
||||
|
|
@ -607,139 +589,8 @@ po regresji na pełnym korpusie (Etap B) — szczegóły przy DoD (d) w §12.
|
|||
|
||||
**Szacunek: 1 sesja (run w tle).**
|
||||
|
||||
### Decyzje operatora do Etapu B (2026-08-04) — przed runem
|
||||
|
||||
Recon przed Etapem B (mirror archiwum na SOLARII żyje: 225 057 plików / 27 GB; RTT
|
||||
SOLARIA→PIHA 0,83 ms; PIHA 140 GB wolne, baza 397 MB; M1 — `NODE_TYPE=lte_node`
|
||||
na node-agencie SOLARII — zdeployowane, więc kontener Ollamy nie zniknie po
|
||||
zatrzymaniu) wykazał dwie rzeczy do rozstrzygnięcia. Decyzje:
|
||||
|
||||
1. **Run w plastrach po 50k** (`--limit 50000 --offset 0/50k/100k/150k/200k`),
|
||||
log per plaster, `nice`/`ionice`. Powód: brak checkpointu (restart = ponowny
|
||||
parse od początku listy, ~1 h) + nocne wyłączanie SOLARII. Plaster ≈ 25–40 min.
|
||||
Tempo kolejnych plastrów po obserwacji PIHA po pierwszym.
|
||||
2. **Circuit breaker w jobie: TAK** — `--max-embed-failures` (domyślnie 5),
|
||||
abort z kodem wyjścia 2 po N kolejnych nieudanych batchach embed. Powód:
|
||||
parse jest jednowątkowy i wyprzedza GPU, więc martwa Ollama (4 incydenty)
|
||||
zamieniłaby 2-godzinny przebieg w 200k+ `chunks_errors` bez ani jednego
|
||||
zapisu. Licznik zeruje się po udanym batchu.
|
||||
3. **Dry-run całości pomijamy** — idempotencja i odwracalność flag newsletterowych
|
||||
wystarczają; ewentualna kalibracja heurystyki na dekadzie 2010–2015 po fakcie,
|
||||
na już zapisanych flagach.
|
||||
4. Przełączenie domyślnego `mode` kb-query na `hybrid` (DoD (d)) — **poza zakresem
|
||||
Etapu B**, osobny task po PASS regresji. *(Wykonany 2026-08-06 — DoD (d) w §12.)*
|
||||
|
||||
### Hardening toru embed przed Etapem B (2026-08-05)
|
||||
|
||||
Recon pod kątem batchingu potwierdził, że batch `/api/embed` (Krok 1) działa zgodnie
|
||||
z §1.4 — ale wykazał w torze backfillu **błąd blokujący dla Etapu B** i dwie luki:
|
||||
|
||||
1. **BUG (naprawiony)**: `flush_embed_buffer` łapał wyłącznie `aiohttp.ClientError`, a
|
||||
wyczerpanie `ClientTimeout(total=...)` rzuca goły `builtins.TimeoutError`, który **nie**
|
||||
jest jego podklasą (zweryfikowane empirycznie na aiohttp 3.14.3). Zawieszona Ollama —
|
||||
czyli dokładnie jej udokumentowany failure mode, „przyjmuje połączenie i milczy", nie
|
||||
„odmawia" — wywalała cały run nieobsłużonym wyjątkiem: **bez breakera i bez flushu
|
||||
threadingu**. Na plastrze 50k oznaczało to utratę już zarobionej pracy. Klasy przejściowe
|
||||
nazwane teraz jawnie w `kb_retrieval.embed.TRANSIENT_EMBED_ERRORS`.
|
||||
2. **Brak retry** — jeden blip sieciowy spisywał na straty cały batch (64 chunki). Dodane:
|
||||
`--embed-retries` (default 2) z backoffem wykładniczym.
|
||||
3. **Brak obsługi błędu częściowego** — `/api/embed` jest all-or-nothing, więc jeden trujący
|
||||
chunk zabijał batch w kółko i mógł wywalić breaker przy **żywym** backendzie. Dodana
|
||||
bisekcja po nieudanych retry, ale tylko gdy `/api/tags` potwierdza, że backend żyje;
|
||||
przy martwym batch od razu „gives up" (bisekcja martwego backendu kosztowałaby 2n-1
|
||||
żądań i opóźniała breaker). Porażka częściowa **nie** przesuwa już breakera.
|
||||
|
||||
Decyzja 2 (circuit breaker) obowiązuje w zaostrzonej formie: licznik liczy **give-upy**
|
||||
(backend padł), nie dowolne nieudane batche. Fallback SOLARIA→PIHA dla backfillu **świadomie
|
||||
nie powstaje** — 271k chunków × 790 ms CPU ≈ 60 h na 8 GB PIHA dzielonym z HA i Paperlessem;
|
||||
właściwą odpowiedzią na martwy backend jest exit 2 i wznowienie plastra. Tor online (`kb-query`
|
||||
→ `embed_router`) ma fallback i tak zostaje — te dwie ścieżki są rozdzielone celowo.
|
||||
|
||||
Doszedł też `mail-body-ingest-bench` — sweep batch size na realnych chunkach (read-only),
|
||||
żeby liczby z §1.4 dało się odtworzyć po zmianie GPU albo wersji Ollamy.
|
||||
|
||||
### Wynik Etapu B (ZAMKNIĘTY, 2026-08-06)
|
||||
|
||||
Pełny korpus gmail jest zchunkowany i zembedowany: **389 012 chunków**
|
||||
`document_chunk`, z czego **0 nie-excluded bez embeddingu** — weryfikacja
|
||||
przebiegła idempotentnymi plastrami 0-4 (`--offset 0/50k/100k/150k/200k
|
||||
--limit 50000 --batch-size 64`, wszystkie EXIT 0) plus fix bajtu NUL (`4ec0b78`).
|
||||
|
||||
Cross-tab na żywej bazie (kb-postgres@PIHA):
|
||||
|
||||
| Miara | Wartość |
|
||||
|---|---|
|
||||
| `document_chunk` total | **389 012** |
|
||||
| nie-excluded **bez** embeddingu | **0** |
|
||||
| nie-excluded z wektorem | 187 025 |
|
||||
| `newsletter`-flagged bez wektora | 201 849 (odwracalne, Decyzja 4) |
|
||||
| excluded **z** wektorem | 138 (artefakt kolejności flagowania, nieszkodliwy) |
|
||||
|
||||
**Korpus był w pełni zembedowany jeszcze przed plastrami z 2026-08-06** —
|
||||
zapamiętany stan „6,4k embedded z Etapu A, ~225k kopert do backfillu" był
|
||||
nieaktualny, wcześniejsze przebiegi pokryły całość. Dzisiejsze runy to pełna,
|
||||
idempotentna weryfikacja. Źródło mylącego odczytu: licznik
|
||||
`chunks_already_embedded` liczy **istnienie wiersza w DB** (w tym chunków
|
||||
newsletter-flagged bez wektora), a nie obecność wektora.
|
||||
|
||||
**Bug NUL (naprawiony, `4ec0b78`)**: bajt `0x00` w treści maili z 2007 (Sony
|
||||
Ericsson, 3 chunki, plaster offset 50k) wywalał insert
|
||||
(`asyncpg.CharacterNotInRepertoireError` — PostgreSQL nie przyjmuje `0x00`
|
||||
w `text`). Fix: strip `\x00` przed chunkowaniem i embedem + liczniki
|
||||
`nul_bytes_stripped` / `mails_nul_sanitized`. Re-run plastra 1: EXIT 0,
|
||||
3 chunki dobrane. Znany follow-up (osobny task): `jobs/gmail-header-backfill`
|
||||
i `jobs/gmail-bulk-import` mają tę samą latentną podatność na NUL w nagłówkach
|
||||
zapisywanych do `jsonb`.
|
||||
|
||||
Szczegóły runu: `docs/sessions/2026-08-06-kb-etapb-backfill.md`.
|
||||
|
||||
Uwaga do czytania wyników: na pełnym korpusie `exit 1` jest spodziewany
|
||||
(pojedyncze `parse_errors` — §1.5 dokumentuje ~9 maili na fallbacku compat32).
|
||||
Werdyktem jest bilans i liczniki w linii `summary`, nie kod wyjścia. `exit 2`
|
||||
oznacza co innego: backend embed padł, trzeba wznowić plaster po naprawie Ollamy.
|
||||
|
||||
## 10. Krok 7 — IMAP/JMAP przyrostówka (zarys; szczegóły = osobny recon)
|
||||
|
||||
> **Stan: IN PROGRESS (2026-08-06).** Recon:
|
||||
> `kb/audits/mail-sync-2026-08-06.md`; decyzje (a)-(g) zatwierdzone przez
|
||||
> operatora 2026-08-06 w całości, implementacja opisana niżej. Zarys
|
||||
> poniżej pochodzi z 2026-07-22 i zachowuję go jako zapis intencji. Recon
|
||||
> rozstrzyga inaczej dwa jego punkty: (1) **Fastmail przez IMAP, nie JMAP**
|
||||
> (unifikacja adaptera — jeden `jobs/mail-imap-sync` zamiast
|
||||
> `fastmail-poller` + `gmail-imap-poller`), (2) spoiwem z torem body nie jest
|
||||
> `--since`, tylko kolejka „koperty bez chunków". Reszta zarysu (poll zamiast
|
||||
> IDLE, reuse `save_eml`/`insert_envelope`, sekrety w `/opt/homelab/config/`)
|
||||
> się potwierdziła.
|
||||
|
||||
### Zakres wdrożony (2026-08-06)
|
||||
|
||||
| # | Element | Gdzie |
|
||||
|---|---|---|
|
||||
| 1 | Adapter IMAP, jeden na oba konta — EXAMINE + `BODY.PEEK[]` (nigdy nie ustawia `\Seen`), wybór folderu po atrybucie SPECIAL-USE | `packages/kb-mail/src/kb_mail/imap.py` |
|
||||
| 2 | Model stanu synca: `plan_folder_sync` (pierwszy tick / przyrost / unieważnienie UIDVALIDITY) + `contiguous_last_uid` (kursor tylko po nieprzerwanym ciągu sukcesów) | `packages/kb-mail/src/kb_mail/sync_state.py` |
|
||||
| 3 | Migracja `005_mail_sync_state.sql`, klucz `(account, folder)` — Decyzja (f) | `services/kb-postgres/init/` |
|
||||
| 4 | Job przyrostówki: fetch → `save_eml` → `insert_envelope(entities=[headers, attachment…])` → kursor. **Nie chunkuje i nie embeduje** | `jobs/mail-imap-sync/` |
|
||||
| 5 | Ekstrakcja wspólnego parse'u (`parse_headers`, `message_id`, `parse_date`, `parse_attachments`) do `kb-mail` — klucz dedup z jednej implementacji | `packages/kb-mail/src/kb_mail/{headers,message}.py` |
|
||||
| 6 | `--sources` + `--only-unchunked` w `mail-body-ingest`; pre-fetch kluczy chunków zawężony do zbioru roboczego | `jobs/mail-body-ingest/` |
|
||||
| 7 | `DEFAULT_SUMMARYLESS_SOURCES += "fastmail"` — Decyzja (g), w tym samym commicie co źródło | `packages/kb-retrieval/` |
|
||||
| 8 | Etap mailowy w `kb-ingest` (kolejka „koperty bez chunków") + takt timera 03:30 → co 2 h — Decyzja (d) | `jobs/documents-ingest/` |
|
||||
| 9 | Jednostki systemd (**nieaktywowane**) + deklaracja jednostek host-level | `jobs/mail-imap-sync/systemd/`, `hosts/piha/jobs.yaml` |
|
||||
| 10 | Metryki `.prom` per konto + reguła `KbMailSyncStale` | `services/fleet-prometheus/rules/kb-mail-sync.yml` |
|
||||
| 11 | `env.example` z placeholderami; poświadczenia wyłącznie ze środowiska — Decyzja (c) | `jobs/mail-imap-sync/env.example` |
|
||||
| 12 | Runbook pierwszego uruchomienia + checklista punktów `[do weryfikacji na żywo]` z reconu | `kb/runbooks/mail-sync-run.md` |
|
||||
|
||||
Dokumentacja serwisu: `kb/services/job-mail-imap-sync.md`.
|
||||
|
||||
**Poza zakresem tej implementacji, świadomie:** pierwszy żywy sync, pomiar
|
||||
`STATUS (MESSAGES)` na Fastmailu i wynikająca z niego **decyzja o historii
|
||||
Fastmaila** (Decyzja (e) — recon celowo jej nie podejmuje, bo zależy od liczby,
|
||||
której nikt jeszcze nie zna), oraz aktywacja timera. Wszystko to robi operator
|
||||
wg runbooka. Alert „cisza w skrzynce" **odrzucony** (decyzja operatora, zgodna
|
||||
z reconem §3.4): zero nowych maili to legalny stan skrzynki, a alert zapalający
|
||||
się na zdrowym systemie zostaje wyciszony — i przestaje działać wtedy, gdy jest
|
||||
potrzebny. Jedyny alert to `KbMailSyncStale` („czy poller w ogóle działa"),
|
||||
który fałszywych trafień nie ma.
|
||||
|
||||
Zakotwiczone w kb-00 jako etapy 3–4 (`jobs/fastmail-poller`,
|
||||
`jobs/gmail-imap-poller`). Zarys decyzji do tamtego reconu:
|
||||
|
||||
|
|
@ -766,24 +617,20 @@ Zakotwiczone w kb-00 jako etapy 3–4 (`jobs/fastmail-poller`,
|
|||
| `mail_ui_url` (klikalny link do maila w UI) | kb-00 etap 6, pole zarezerwowane w kb-query | z modułem mail-UI |
|
||||
| Graf wątków / entity_link z `entities[type=threading]` | ta faza tylko zapisuje surowiec (Decyzja 10) | przyszła faza „połączenia" |
|
||||
| Streszczenia selektywne maili (hybryda Haiku) | Decyzja 6 — odłożona | po ocenie trybu hybrid w praktyce |
|
||||
| ~~IMAP/JMAP przyrostówka — implementacja~~ | Krok 7 | **wykonane 2026-08-06** (§10 „Zakres wdrożony"); pierwszy żywy sync po stronie operatora |
|
||||
| Historia Fastmaila (pełny zaciąg vs tylko przyrost) | Decyzja (e) reconu | po pomiarze `mail-imap-sync --measure` — runbook §5 |
|
||||
| Alert per konto na wiek najnowszego maila (`kb_mail_sync_last_message_ts`) | recon §3.4 | po miesiącu obserwacji; próg z pomiaru, nie z góry |
|
||||
| Etykiety Gmaila w `entities` (`X-GM-LABELS`) | recon §2.3 | odłożone — `X-GM-EXT-1` przywiązuje kod do Google, wprost wbrew „protokół, nie provider" |
|
||||
| IMAP/JMAP przyrostówka — implementacja | Krok 7 (zarys) | osobny recon + pakiet |
|
||||
|
||||
## 12. Plan implementacji (kolejność = zależności)
|
||||
|
||||
| # | Krok | Zależy od | Szacunek | Stan | Dowód (2026-08-04) |
|
||||
|---|---|---|---|---|---|
|
||||
| 0 | Chunker → `packages/kb-mail` | — | 0,5 sesji | **WYKONANE** | `348ce10`; `packages/kb-mail/src/kb_mail/chunking.py` + `tests/test_chunking.py` |
|
||||
| 1 | `embed_batch` w kb-retrieval | — | 0,5 sesji | **WYKONANE** | `51998fd`; `kb_retrieval/embed.py:61` (`embed_batch`) + `tests/test_embed.py` |
|
||||
| 2 | Job `mail-body-ingest` | 0, 1 | 2 sesje | **WYKONANE** | `ad0ef40` (job), `a95524c` (README), `fc5c698` (fix html_to_text); `jobs/mail-body-ingest/` + `tests/test_ingest.py` |
|
||||
| 3 | Tryb hybrid (kb-retrieval + kb-query) | — (równolegle z 2) | 1 sesja | **WYKONANE** | `a640cf1`; `kb_retrieval/retrieval.py:112` (`hybrid_retrieve`), `:195` (`hybrid_query`), `kb-query/app/main.py:119` (`mode` pattern). Domyślny `mode` przełączony na `hybrid` 2026-08-06 (follow-up z §8, DoD (d) niżej) |
|
||||
| 4 | rsync + Etap A (12 mies.) + kalibracja | 2 | 1 sesja | **WYKONANE** | §7 „Wynik Etapu A" (run na żywo 2026-07-23); potwierdzone na żywej bazie 2026-08-04: `document_chunk` gmail = 33 871 (6 398 z embeddingiem + 27 473 `newsletter`) — zgodne co do sztuki z tabelą §7 |
|
||||
| 5 | Bramka jakościowa (eval mailowy + regresja) | 3, 4 + zapytania od operatora | 1 sesja | **WYKONANE** (PASS) | §8 „Wynik bramki"; `56f64e9` (eval + queries.yaml dla hybrid), `bce635c` (`mail_hit@3`, próg N2, werdykt PASS), `71eb264` (`--transport http`) |
|
||||
| 6 | Etap B (pełne archiwum) + regresja + obserwacja PIHA | 5 = PASS | 1 sesja | **WYKONANE** (2026-08-06) | §9 „Wynik Etapu B"; żywa baza: 389 012 chunków, 0 nie-excluded bez embeddingu. Weryfikacja plastrami 0-4 (wszystkie EXIT 0) + fix NUL `4ec0b78`; `docs/sessions/2026-08-06-kb-etapb-backfill.md` |
|
||||
| 7 | Recon przyrostówki IMAP/JMAP | — (po 6) | 1 sesja (poza DoD fazy) | **WYKONANE** (2026-08-06) | `kb/audits/mail-sync-2026-08-06.md`. Ustalenia: korpus urywa się 2026-06-19 (dziura 48 dni ≈ 1 800 maili), zero kodu IMAP w repo, brak modelu stanu synca; cały nowy kod to jeden `jobs/mail-imap-sync` + 4 drobne zmiany w istniejącym torze. Decyzje (a)-(g) zatwierdzone przez operatora 2026-08-06 |
|
||||
| 8 | Implementacja przyrostówki IMAP | 7 + decyzje (a)-(g) | 2 sesje (poza DoD fazy) | **IN PROGRESS** (2026-08-06) | Zakres w §10 „Zakres wdrożony". Testy zielone: 80 (`mail-imap-sync`) + 111 (`kb-mail`) + 191 (`documents-ingest`) + 127 (`mail-body-ingest` / `kb-retrieval`). **Nie uruchomione na żywym koncie** — pierwszy sync, pomiar Fastmaila i aktywacja timera po stronie operatora (`kb/runbooks/mail-sync-run.md`) |
|
||||
| # | Krok | Zależy od | Szacunek |
|
||||
|---|---|---|---|
|
||||
| 0 | Chunker → `packages/kb-mail` | — | 0,5 sesji |
|
||||
| 1 | `embed_batch` w kb-retrieval | — | 0,5 sesji |
|
||||
| 2 | Job `mail-body-ingest` | 0, 1 | 2 sesje |
|
||||
| 3 | Tryb hybrid (kb-retrieval + kb-query) | — (równolegle z 2) | 1 sesja |
|
||||
| 4 | rsync + Etap A (12 mies.) + kalibracja | 2 | 1 sesja |
|
||||
| 5 | Bramka jakościowa (eval mailowy + regresja) | 3, 4 + zapytania od operatora | 1 sesja |
|
||||
| 6 | Etap B (pełne archiwum) + regresja + obserwacja PIHA | 5 = PASS | 1 sesja |
|
||||
| 7 | Recon przyrostówki IMAP/JMAP | — (po 6) | 1 sesja (poza DoD fazy) |
|
||||
|
||||
**Kryterium ukończenia fazy mailowej:** (a) pełny korpus gmail zchunkowany
|
||||
(bilans domknięty, `parse_errors` na poziomie pojedynczych sztuk jak
|
||||
|
|
@ -792,28 +639,11 @@ hybrid, (c) bramka §8 PASS wraz z regresją po Etapie B, (d) `kb-query`
|
|||
domyślnie odpowiada trybem hybrid na `kb.kapala.org`, (e) koperty gmail mają
|
||||
`entities[type=threading]`.
|
||||
|
||||
**(d) SPEŁNIONE w repo 2026-08-06** — domyślny `mode` w `/search` przełączony
|
||||
`cascade` → `hybrid` (`services/kb-query/app/main.py`, walidator `Query`;
|
||||
frontend przestał wysyłać `mode` przy odznaczonym „tryb flat", więc UI
|
||||
dziedziczy domyślny tryb API). Podstawa: eval na **pełnym** korpusie
|
||||
(187 025 zembedowanych chunków mailowych w HNSW, §9) —
|
||||
kryterium 1 (regresja paperless) **PASS**: żaden istniejący hit nie
|
||||
zdegradował ani we flat, ani w hybrid; mailowe **hit@3 = 5/5**; koszt
|
||||
hybrydy to jedno dodatkowe zapytanie SQL na wyszukiwanie. Surowe wyniki:
|
||||
`eval-http-2026-08-06.json` i `eval-direct-2026-08-06.json`
|
||||
w `~/kb/mail/ingest-logs` na PIHA (celowo niecommitowane — artefakt runu).
|
||||
Jawne `?mode=cascade` / `?mode=flat` działają bez zmian.
|
||||
**Deploy na PIHA robi operator z mastera po mergu** — do tego czasu
|
||||
`kb.kapala.org` nadal odpowiada kaskadą.
|
||||
|
||||
## 13. Szacunki zbiorcze
|
||||
|
||||
- **Dane**: +~496k wierszy `document_chunk` (~271k z embeddingiem, ~225k
|
||||
flagowanych `newsletter`); baza 250 MB → ~5–7 GB (dysk PIHA: 144 GB wolne,
|
||||
zapas >20×). HNSW rośnie inkrementalnie przy insertach — bez rebuildu.
|
||||
**Wykonanie (2026-08-06, §9): 389 012 wierszy — 187 025 z embeddingiem,
|
||||
201 849 flagowanych `newsletter`.** Mniej niż ekstrapolacja z §1.3, bo
|
||||
quote-strip (Decyzja 2) realnie ucina objętość, co §1.3 zapowiadał.
|
||||
- **GPU/czas runów**: Etap A <1 h e2e; Etap B: parse ~0,5–1 h (24 rdzenie)
|
||||
+ embed ~1–1,5 h (batch 64, zmierzone 8–18 ms/chunk) + inserty do PIHA.
|
||||
- **Koszty zewnętrzne: 0 USD** (bez streszczeń — Decyzja 6).
|
||||
|
|
@ -827,11 +657,6 @@ Jawne `?mode=cascade` / `?mode=flat` działają bez zmian.
|
|||
|
||||
## 14. Podsumowanie dla Oskara
|
||||
|
||||
> **Uwaga (2026-08-06):** poniższe to podsumowanie z chwili reconu (2026-07-22),
|
||||
> zachowane jako zapis intencji. Plan został wykonany — treści 225k maili są
|
||||
> w bazie i w retrievalu (§9 „Wynik Etapu B"); otwarty jest już tylko Krok 7
|
||||
> (przyrostówka IMAP/JMAP).
|
||||
|
||||
Treści Twoich 225 tysięcy maili leżą dziś martwe w 27 GB archiwum na PIHA —
|
||||
w bazie są tylko nagłówki, a wyszukiwarka z fazy 4 słusznie skarży się „mało
|
||||
danych". Ten plan wprowadza je do retrievalu w ~7 sesji i za 0 USD: ponowny
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-13
|
||||
links: []
|
||||
---
|
||||
|
||||
# Modul 5, faza 2 — koperta dokumentow + embeddingi + cross-source (RECON + PLAN)
|
||||
|
||||
> Status: RECON ZAKONCZONY (2026-07-13), architektura DO ZATWIERDZENIA. Zaden kod nie
|
||||
|
|
@ -545,7 +536,7 @@ zeby dalo sie uruchomic partiami i zweryfikowac progres bez czekania na cale 225
|
|||
rzedu dziesiatek-set chunkow/s. Caly pilot (2–3k chunkow) → **rzedu minut**, nie wymaga
|
||||
specjalnego batchowania/partii.
|
||||
- **Skala docelowa (70k zalacznikow z maili)**: modul 5 faza-1 to swiadomie **probka, nie
|
||||
bulk** (`kb/phases/kb-m5-documents-ingest-fazy.md` — decyzja architektoniczna). Realny wolumen
|
||||
bulk** (`jobs/documents-ingest/README.md` — decyzja architektoniczna). Realny wolumen
|
||||
ktory trafi do embeddingu zalezy od (a) throughput OCR-workera na SOLARII (modul 3) —
|
||||
**to jest waskie gardlo skalowania, nie embedding** — oraz (b) filtra selektywnosci
|
||||
(decyzja #6). Sam embedding bge-m3 nie bedzie bottleneckiem nawet przy tysiacach
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-08-27
|
||||
links: []
|
||||
---
|
||||
|
||||
# Moduł 5, faza 3 — warstwa kompilacji (RECON + PLAN)
|
||||
|
||||
> Status: RECON ZAKOŃCZONY (2026-07-16), plan DO ZATWIERDZENIA. Zero kodu, zero migracji,
|
||||
|
|
@ -448,7 +439,7 @@ Próbka 25 dokumentów (stratyfikowana: polisy, faktury, umowy, urzędowe, FLL/s
|
|||
- **kompletność faktów kluczowych** (kwoty, daty, strony, numery),
|
||||
- **jakość tagów** (trafność + zgodność ze słownikiem).
|
||||
|
||||
Wynik do `kb/phases/kb-m5-faza3-pilot-streszczen.md`: tabela per dokument + wnioski.
|
||||
Wynik do `docs/kb/modules/05-faza3-pilot-streszczen.md`: tabela per dokument + wnioski.
|
||||
**Kryterium „lokalny wystarcza na skalę mailową"**: mediana wierności = 2 (zero tolerancji
|
||||
dla przekręconych kwot — to trafia do wiki) i kompletność ≥ 80% punktów API. Jeśli lokalny
|
||||
nie daje rady → decyzja o skali mailowej rozważa API z polityką eskalacji fazy 5 (koszt
|
||||
|
|
@ -505,7 +496,7 @@ aktywnych chunków, N większe niż liczba kopert, no-summaries short-circuit)
|
|||
pakietu przechodzi.
|
||||
|
||||
**Eval-set utrwalony**: `jobs/documents-ingest/eval/queries.yaml` (7 zapytań z pilota
|
||||
07-16, 1:1 z `kb/phases/kb-m5-eval-retrieval-pilot.md`, ten plik pozostał nietknięty —
|
||||
07-16, 1:1 z `docs/kb/eval/retrieval-pilot-2026-07-16.md`, ten plik pozostał nietknięty —
|
||||
`queries.yaml` to jego wersjonowana kopia robocza). Skrypt bramki (read-only, integracyjny,
|
||||
**nie wchodzi do pytest**): `jobs/documents-ingest/eval/retrieval_eval.py`.
|
||||
|
||||
|
|
@ -560,19 +551,10 @@ Adapter i embed są już idempotentne — nowość to wyłącznie orkiestracja i
|
|||
`/etc/systemd/system/`, `systemctl enable --now kb-ingest.timer`). Pierwszy
|
||||
systemd-timer w repo — świadomie host-level, nie kontener (joby potrzebują jednocześnie
|
||||
LAN, DB i plików hosta; konteneryzacja nic tu nie daje).
|
||||
- **Harmonogram**: ~~`OnCalendar=*-*-* 03:30`~~ → **`OnCalendar=0/2:00:00` (co 2 h) od
|
||||
2026-08-06**, `Persistent=true` (nadgania po reboocie). Zmiana wynika z Decyzji (d) reconu
|
||||
przyrostówki (`kb/audits/mail-sync-2026-08-06.md` §3.3): o 03:30 SOLARIA prawie na pewno
|
||||
śpi (potwierdzone odczytem `kb_ingest_embed_skipped 1`), a od tej daty tick dostaje też
|
||||
etap mailowy — ~60 nowych chunków na dobę pomijanych każdej nocy zapaliłyby
|
||||
`KbEmbedBacklogGrowing` na stałe. Co 2 h zamiast stałej godziny dopasowanej do nawyków
|
||||
operatora: probe Ollamy sam wybiera okno, więc któryś tick w nie trafi niezależnie od tego,
|
||||
o której SOLARIA wstaje w danym tygodniu.
|
||||
- **Harmonogram**: `OnCalendar=*-*-* 03:30`, `Persistent=true` (nadgania po reboocie).
|
||||
- **Sekwencja skryptu**: adapter `--apply` → chunk_embed `--apply`
|
||||
(`OLLAMA_URL=http://solaria:11434`) → **mail_body_ingest `--only-unchunked`** (dodane
|
||||
2026-08-06 — konsument kolejki, którą wypełnia `jobs/mail-imap-sync`; import miękki, więc
|
||||
venv bez tego pakietu pomija etap zamiast wywracać wrapper) → summarize → embed-summaries.
|
||||
Log do `/opt/homelab/logs/kb-ingest/run-YYYYMMDD.log`.
|
||||
(`OLLAMA_URL=http://solaria:11434`) → (po decyzji z pilota, rozszerzenie później:
|
||||
summarize nowych dokumentów). Log do `/opt/homelab/logs/kb-ingest/run-YYYYMMDD.log`.
|
||||
- **Tolerancja na SOLARIĘ offline** (`availability_target: medium`): wrapper odróżnia
|
||||
„Ollama nieosiągalna" (probe `GET /api/tags` przed embedem; brak → pomiń embed,
|
||||
odnotuj, **to nie jest fail** — nadrobi następny run, bo embed jest idempotentny) od
|
||||
|
|
@ -628,17 +610,6 @@ Adapter i embed są już idempotentne — nowość to wyłącznie orkiestracja i
|
|||
> półprodukt kompilacji) i PO filtrze śmieciowych chunków. Pełna wiki po fazie mailowej
|
||||
> (przyrostówka) — wcześniej kompilat byłby fotografią przeszłości.
|
||||
|
||||
**Inwariant 7 (dodany 2026-08-27 — rozszerzenie, nie zmiana inwariantów 1–6
|
||||
powyżej, które pozostają NIE podlega zmianie):** decyzja (f),
|
||||
`kb/audits/wiki-kompilat-recon-2026-08-26.md` §10, zatwierdzona przez operatora
|
||||
w całości 2026-08-27. Kompilacja strony wiki **nigdy** nie czyta `source='wiki'`
|
||||
jako dowodu (`exclude_sources=('wiki',)` w `cascade_retrieve`/`hybrid_retrieve`) —
|
||||
retrieval na potrzeby kompilacji zawsze wyklucza wiki, czyta wyłącznie warstwę
|
||||
dowodową (mail, paperless). Tylko `/search` (warstwa użytkownika, po zbudowaniu
|
||||
syntezy odpowiedzi — inwariant 5, faza 5) widzi wiki w kaskadzie. Mitygacja
|
||||
self-citation/citogenesis przy źródle retrievalu, nie tylko przez lint (inwariant
|
||||
3) po fakcie — patrz audyt §7 dla pełnego rozumowania.
|
||||
|
||||
### 8.2 Rozwinięcie wykonawcze (szczegóły, decyzje architektoniczne bez zmian)
|
||||
|
||||
**Repozytorium** (rozstrzygnięcie punktu 6 szkicu): osobne repo `kb-wiki` — decyzja 7,
|
||||
|
|
@ -720,7 +691,7 @@ streszczeń). Kandydaci na pierwsze strony (encje z pilota): PZU/WARTA (polisy),
|
|||
## 9. Poza zakresem fazy 3
|
||||
|
||||
Granice planu — wszystko poniżej jest świadomie odłożone, z istniejącym miejscem w
|
||||
roadmapie (`kb/subsystems/kb-overview.md` „Stan etapów/Backlog", sesja
|
||||
roadmapie (`docs/kb/kb-00-overview.md` „Stan etapów/Backlog", sesja
|
||||
`docs/sessions/2026-07-16.md`, backlog operatora):
|
||||
|
||||
| Temat | Gdzie zakotwiczone | Kiedy |
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: phase
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-22
|
||||
links: []
|
||||
---
|
||||
|
||||
# Moduł 5, faza 4 — kb-query + UI (RECON + PLAN)
|
||||
|
||||
> Status: RECON ZAKOŃCZONY (2026-07-22), plan DO ZATWIERDZENIA. Zero kodu, zero
|
||||
|
|
@ -68,7 +59,7 @@ links: []
|
|||
|
||||
### 1.3 PIHA — budżet RAM (istotne dla decyzji D2 / lokalnego fallbacku)
|
||||
|
||||
- Audyt `kb/audits/piha-slim-2026-07-02.md`: po "bezpiecznym usuń"
|
||||
- Audyt `docs/infra/piha-slim-audit-2026-07-02.md`: po "bezpiecznym usuń"
|
||||
(elasticsearch+diskover+stary llm-gateway) available rosło z **2.9Gi do ~3.8Gi**
|
||||
(na 8 GB total, +4 GB swap). To jest **jedyna zweryfikowana liczba w repo i ma
|
||||
3 tygodnie** — od tego dnia na PIHA doszły (GitOps, z `mem_limit`): paperless+db+broker
|
||||
|
|
@ -97,7 +88,7 @@ domeny `*.kapala.org`:
|
|||
(cert #51 *.okit.pl, cert osobny dla *.kapala.org — sesje ją tylko konfigurują
|
||||
ręcznie/SQL-em, nigdy nie deployują z repo). kb-query dogania się do tego samego
|
||||
wzorca: nowy vhost w `npm@PIHA`, TLS z **już istniejącego** wildcard `*.kapala.org`
|
||||
(pokrywa `paper.`/`cloud.`/`vikunja.kapala.org` — `kb/decisions/kb-dokumenty-otwarte.md`
|
||||
(pokrywa `paper.`/`cloud.`/`vikunja.kapala.org` — `docs/kb/modules/DECYZJE-do-podjecia.md`
|
||||
#6) — **żaden nowy certyfikat nie jest potrzebny**.
|
||||
- **DNS — dwie warstwy, obie trzeba dotknąć** (lekcja `okit-cloudflare-migracja.md`
|
||||
§"WAZNE: split-horizon DNS"): (a) Cloudflare rekord A → Tailscale IP PIHA
|
||||
|
|
@ -261,7 +252,7 @@ przed backfillem" z fazy 3 §3.1 (zmierz, obejrzyj, dopiero wtedy zaufaj progowi
|
|||
### Decyzja 3 — Linki do źródeł: paperless vs gmail
|
||||
|
||||
**Paperless**: URL do dokumentu — **do zweryfikowania na żywym Paperless przed
|
||||
implementacją** (repo nie ma zapisanego przykładu, `kb/phases/kb-m2-paperless.md`
|
||||
implementacją** (repo nie ma zapisanego przykładu, `docs/kb/modules/02-paperless-service.md`
|
||||
dokumentuje tylko subdomenę, nie ścieżkę). Kandydat wg konwencji paperless-ngx UI:
|
||||
`https://paper.kapala.org/documents/<id>/details` (Angular routing) — `envelope_id`
|
||||
`paperless:<id>` już niesie surowy `<id>` do wstawienia. Krok implementacji: jeden
|
||||
|
|
@ -471,7 +462,7 @@ Jedna strona (Jinja2 template + vanilla JS + CSS, serwowane z tego samego FastAP
|
|||
- Pole zapytania + submit (Enter albo przycisk).
|
||||
- Wyniki grupowane po `envelope_id` (dokument), w obrębie dokumentu chunki
|
||||
posortowane po `dist`.
|
||||
- Kolorowanie progów (progi z fazy 3, `kb/phases/kb-m5-faza3.md` §1.2,
|
||||
- Kolorowanie progów (progi z fazy 3, `docs/kb/modules/05-faza3-plan.md` §1.2,
|
||||
zweryfikowane bramką): `dist < 0.45` zielony, `0.45–0.55` żółty, `> 0.55` —
|
||||
**nie renderować wyniku**, tylko komunikat "brak odpowiedzi w KB" (żółta/czerwona
|
||||
strefa nadal renderuje wynik z ostrzeżeniem wizualnym; czerwona = brak sensownego
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: decision
|
||||
visibility: private
|
||||
status: planned
|
||||
updated: 2026-07-09
|
||||
links: []
|
||||
---
|
||||
|
||||
# Decyzje do podjęcia — filar dokumentów (moduły 2/3/4)
|
||||
|
||||
> Zbiorcza lista decyzji z przygotowania configów (2026-07-06, branch
|
||||
|
|
@ -63,7 +54,7 @@ zdecydować, czy podbić concurrency, czy zostawić zapas na ollama/AI.
|
|||
rsync/borg → SOLARIA (2 TB, ta sama LAN). Retencja: 7 dziennych +
|
||||
4 tygodniowe + 6 miesięcznych. Offsite (np. restic → chmura) zostaje jako
|
||||
future-note, poza zakresem tego etapu. Cron/skrypt deployowy powstaje przy
|
||||
deployu modułu 2, nie teraz. Szczegóły: `kb/services/paperless.md`.
|
||||
deployu modułu 2, nie teraz. Szczegóły: `services/paperless/README.md`.
|
||||
|
||||
- **4. Redis brokera: `requirepass`.** Broker (6380) dostaje hasło —
|
||||
`PAPERLESS_REDIS_PASSWORD` w `.env` po obu stronach (paperless@PIHA,
|
||||
|
|
@ -76,7 +67,7 @@ zdecydować, czy podbić concurrency, czy zostawić zapas na ollama/AI.
|
|||
+ SOLARIA po NFS) świadomie zaakceptowane — indeks jest odtwarzalny
|
||||
(`document_index reindex`), oryginałom nic nie grozi. Bez zmian w
|
||||
configu; fallback-worker na PIHA zostaje. Szczegóły:
|
||||
`kb/services/paperless-worker.md`.
|
||||
`services/paperless-worker/README.md`.
|
||||
|
||||
- **6. Domeny: `kapala.org` (mesh, prywatne).** `paper.kapala.org`
|
||||
(Paperless), `cloud.kapala.org` (Nextcloud) — potwierdzone, `*.okit.pl`
|
||||
|
|
@ -99,7 +90,7 @@ zdecydować, czy podbić concurrency, czy zostawić zapas na ollama/AI.
|
|||
maintainerów paperless-ngx (nieoficjalnie wspierany): ten sam obraz,
|
||||
`command: celery --app paperless worker`, wspólny Redis+Postgres+storage,
|
||||
identyczne ścieżki kontenerowe i numeryczny UID po obu stronach. Pełny
|
||||
wynik badania + ryzyka: `kb/services/paperless-worker.md`.
|
||||
wynik badania + ryzyka: `services/paperless-worker/README.md`.
|
||||
- Storage dokumentów na PIHA; NFS export → SOLARIA po LAN
|
||||
(192.168.31.5 → 192.168.31.70), nie Tailscale.
|
||||
- AOF w Redis brokera (kolejka przeżywa restart — zero utraty zadań).
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-05-11
|
||||
links:
|
||||
- ../runbooks/service-operational-recovery.md
|
||||
---
|
||||
|
||||
# Service Lifecycle and Recovery
|
||||
|
||||
This document defines the lifecycle of a service in the homelab and the procedures for operational recovery.
|
||||
|
|
@ -35,6 +25,25 @@ This document defines the lifecycle of a service in the homelab and the procedur
|
|||
- `docker compose down`.
|
||||
- Archive `/opt/homelab/data/<service>` if necessary.
|
||||
|
||||
## Operational Recovery
|
||||
|
||||
### 1. Container Failure
|
||||
If a service is unhealthy:
|
||||
- Check `docker compose logs`.
|
||||
- Restart: `docker compose restart`.
|
||||
- Recreate: `docker compose up -d --force-recreate`.
|
||||
|
||||
### 2. Node Failure
|
||||
If a host node fails:
|
||||
- Services with `owner_node` matching the failed node must be recovered on a backup node or the node must be restored.
|
||||
- Persistence data must be restored from backups to `/opt/homelab/data/<service>`.
|
||||
|
||||
### 3. Dependency Recovery
|
||||
If a dependency fails:
|
||||
- Services depending on it might report unhealthy status.
|
||||
- Recover the dependency first.
|
||||
- Re-verify dependent services.
|
||||
|
||||
## Persistent Data Conventions
|
||||
|
||||
- **Data**: `/opt/homelab/data/<service>` - Primary persistent state.
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: private
|
||||
status: deprecated
|
||||
updated: 2026-04-15
|
||||
links: []
|
||||
superseded_by: "kb/subsystems/fleet-inventory.md + hosts/<node>/capabilities.yaml (stub z 2026-04-15, sprzed floty)"
|
||||
---
|
||||
|
||||
# Networking
|
||||
|
||||
## Description
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: runbook
|
||||
visibility: public
|
||||
status: active
|
||||
updated: 2026-05-12
|
||||
links: []
|
||||
---
|
||||
|
||||
# Node Onboarding Workflow
|
||||
|
||||
This document describes the process of onboarding a new Linux machine into the homelab platform.
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: public
|
||||
status: active
|
||||
updated: 2026-06-17
|
||||
links: []
|
||||
---
|
||||
|
||||
# Observer Runtime
|
||||
|
||||
The Observer Runtime is a lightweight agent responsible for synthesizing the operational world state of the homelab from raw events, logs, and state files.
|
||||
65
docs/questions.md
Normal file
65
docs/questions.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# Unknowns and Clarification Questions
|
||||
|
||||
## Description
|
||||
|
||||
This page lists information that is missing or unclear from the current homelab documentation.
|
||||
|
||||
## Current configuration
|
||||
|
||||
The currently documented configuration is limited to:
|
||||
|
||||
- Raspberry Pi 5 as the main server.
|
||||
- Docker, Portainer, and Nginx Proxy Manager as the core stack.
|
||||
- NAT with forwarded ports:
|
||||
- `80-81` to `4480-4481`
|
||||
- `443` to `4443`
|
||||
- Public access through Nginx Proxy Manager with Let's Encrypt HTTPS.
|
||||
- Private access through Tailscale.
|
||||
- Hetzner VPS handoff:
|
||||
- Hostname: `ubuntu-4gb-hel1-1`
|
||||
- Tailscale IP: `100.95.58.48`
|
||||
- Public IPv4: `135.181.153.108`
|
||||
- Public IPv6: `2a01:4f9:c014:98f0::1`
|
||||
- Running container: `npm`
|
||||
- Joplin files created but not running.
|
||||
|
||||
## Known facts
|
||||
|
||||
- The homelab is documented only from the known facts above.
|
||||
- Anything not listed as known remains unconfirmed.
|
||||
|
||||
## Unknown / needs clarification
|
||||
|
||||
1. What operating system and version is running on the Raspberry Pi 5?
|
||||
2. What is the Raspberry Pi 5 RAM size?
|
||||
3. What storage devices are used, and where is persistent service data stored?
|
||||
4. What is the Raspberry Pi 5 LAN IP address?
|
||||
5. Is the Raspberry Pi 5 using DHCP or a static IP address?
|
||||
6. What router or firewall performs NAT and port forwarding?
|
||||
7. Is the WAN IP static, dynamic, or behind CGNAT?
|
||||
8. Does external port `80` map to internal port `4480`, and does external port `81` map to internal port `4481`?
|
||||
9. Are the forwarded ports TCP only, UDP only, or both?
|
||||
10. Are any other ports forwarded?
|
||||
11. What domain names or subdomains point to the homelab?
|
||||
12. What are the Nginx Proxy Manager proxy hosts?
|
||||
13. Which services are public, and which are private-only?
|
||||
14. Is HTTP-to-HTTPS redirection enabled in Nginx Proxy Manager?
|
||||
15. Are Nginx Proxy Manager access lists used?
|
||||
16. How are Docker, Portainer, and Nginx Proxy Manager deployed?
|
||||
17. Are Docker Compose files, Portainer stacks, or other manifests available?
|
||||
18. What containers are currently running?
|
||||
19. What Docker networks and volumes exist?
|
||||
20. What is the Tailscale device name for the Raspberry Pi 5?
|
||||
21. Does the Raspberry Pi 5 advertise Tailscale subnet routes?
|
||||
22. Is the Raspberry Pi 5 configured as a Tailscale exit node?
|
||||
23. Is Tailscale SSH enabled?
|
||||
24. What backup system exists, if any?
|
||||
25. What monitoring or alerting exists, if any?
|
||||
26. Is the Hetzner VPS part of the homelab documentation scope, a separate system, or both?
|
||||
27. What is the operating system version on `ubuntu-4gb-hel1-1`?
|
||||
28. Is public Nginx Proxy Manager admin access on port `81` intentionally reachable on `135.181.153.108`?
|
||||
29. Has DNS record `joplin.okit.pl -> 135.181.153.108` been created?
|
||||
30. Has optional AAAA record `joplin.okit.pl -> 2a01:4f9:c014:98f0::1` been created?
|
||||
31. Has `POSTGRES_PASSWORD=CHANGE_ME_STRONG_PASSWORD` been changed before first Joplin production start?
|
||||
32. Has the Nginx Proxy Manager proxy host for `joplin.okit.pl` been created?
|
||||
33. Are ports `80` and `443` publicly reachable on the Hetzner VPS for Let's Encrypt HTTP validation?
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: public
|
||||
status: active
|
||||
updated: 2026-05-11
|
||||
links: []
|
||||
---
|
||||
|
||||
# Service Model and Healthchecks
|
||||
|
||||
This document defines the normalized service model for the homelab.
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: subsystem
|
||||
visibility: private
|
||||
status: deprecated
|
||||
updated: 2026-04-15
|
||||
links: []
|
||||
superseded_by: "kb/subsystems/fleet-inventory.md + hosts/<node>/capabilities.yaml (stub z 2026-04-15, sprzed floty)"
|
||||
---
|
||||
|
||||
# Services
|
||||
|
||||
## Description
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-05-27
|
||||
links: []
|
||||
---
|
||||
|
||||
# SESSION: Budowa planner-agent — LLM-based diagnostics
|
||||
|
||||
**DATA:** 2026-05-27
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-05-27
|
||||
links: []
|
||||
---
|
||||
|
||||
# SESSION: Stabilizacja systemu wieloagentowego homelabu
|
||||
|
||||
**DATE:** 2026-05-27
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-09
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-08 — onboarding LUSTRO (RPi4 / Magic Mirror / KEN)
|
||||
|
||||
## Cel
|
||||
|
|
@ -90,7 +81,7 @@ przez Tailscale działa bezhasłowo. Verify czysty (arch=aarch64).
|
|||
|
||||
## Learnings
|
||||
|
||||
(odzwierciedlone też w `kb/runbooks/node-onboarding-tool.md`)
|
||||
(odzwierciedlone też w `scripts/onboard/README.md`)
|
||||
|
||||
- mDNS `.local` zawodny do automatyzacji → `first_contact` przez IP lub tailscale, nie `.local`
|
||||
- istniejący node z userem uid=1000: użyj go zamiast tworzyć `oskar` (kolizja uid)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-09
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-09 — flota recovery + LUSTRO register
|
||||
|
||||
## Cel
|
||||
|
|
@ -130,4 +121,4 @@ Docelowo: osobny worktree per task.
|
|||
|
||||
## Tech-debt złapany w sesji
|
||||
|
||||
→ wpisany do `kb/phases/backlog.md`
|
||||
→ wpisany do `docs/backlog.md`
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-11
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-10/11 — lustro SSH shipping fix + ha-diag-agent piha
|
||||
|
||||
## Cel
|
||||
|
|
@ -79,13 +70,13 @@ solaria / piha / chelsty to wciąż **stare root kontenery** node-agenta
|
|||
(piha Created 2026-05-27, uid 0). Ich mount `/root/.ssh` działa tylko dlatego,
|
||||
że kontenery są sprzed `user: "1000:1000"`. Pierwszy `--force-recreate` / reboot
|
||||
hosta / update obrazu przełączy je na uid 1000 i shipping padnie jak na lustrze.
|
||||
**NIE RECREATE bez fixu.** Szczegóły i fix: `kb/phases/backlog.md`.
|
||||
**NIE RECREATE bez fixu.** Szczegóły i fix: `docs/backlog.md`.
|
||||
|
||||
---
|
||||
|
||||
## Tech-debt złapany w sesji
|
||||
|
||||
→ wpisany do `kb/phases/backlog.md` (flota-bomba, ha-diag-agent blocked,
|
||||
→ wpisany do `docs/backlog.md` (flota-bomba, ha-diag-agent blocked,
|
||||
poison-quarantine review, `--omit-dir-times`, stale komentarz node_agent.py,
|
||||
shipping success na `logger.debug`, event-bloat lustro na VPS).
|
||||
|
||||
|
|
@ -96,8 +87,8 @@ fa59625 docs(ha-diag-agent): replace curl verify commands with docker exec
|
|||
d7e0d31 fix(ha-diag-agent): remove host port mapping for 8087
|
||||
|
||||
### Files changed
|
||||
kb/runbooks/ha-diag-agent-deploy.md | 4 ++--
|
||||
kb/services/ha-diag-agent.md | 4 ++--
|
||||
services/ha-diag-agent/DEPLOY.md | 4 ++--
|
||||
services/ha-diag-agent/README.md | 4 ++--
|
||||
services/ha-diag-agent/docker-compose.yml | 3 ---
|
||||
services/ha-diag-agent/service.yaml | 3 ---
|
||||
4 files changed, 4 insertions(+), 10 deletions(-))
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-17
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-17 — KB foundations (etap 1 maili)
|
||||
|
||||
## Cel
|
||||
|
|
@ -120,14 +111,14 @@ services/kb-postgres/service.yaml
|
|||
services/kb-postgres/env.example
|
||||
services/kb-postgres/healthcheck.sh
|
||||
services/kb-postgres/init/001_envelope.sql
|
||||
kb/services/kb-postgres.md
|
||||
services/kb-postgres/README.md
|
||||
hosts/solaria/runtime/kb-postgres/docker-compose.override.yml
|
||||
hosts/solaria/services.yaml
|
||||
inventory/topology.yaml
|
||||
packages/kb-mail/pyproject.toml
|
||||
packages/kb-mail/src/kb_mail/{__init__,envelope,db,archive}.py
|
||||
packages/kb-mail/tests/{conftest,test_envelope,test_archive,test_db,test_migration}.py
|
||||
kb/subsystems/kb-overview.md (etap 1 done, konwencja packages/)
|
||||
docs/kb/kb-00-overview.md (etap 1 done, konwencja packages/)
|
||||
CLAUDE.md (sekcja Shared Python Libraries)
|
||||
docs/sessions/2026-06-17-kb-foundations.md
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-17
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-17 — Vikunja OIDC+GitOps · Observer heartbeat-TTL · panel-source
|
||||
|
||||
## Zrobione i wdrożone
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-22
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-22 — KB spine relokowany na PIHA + przygotowanie hosta
|
||||
|
||||
## Cel
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-22
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-22 — decyzja: Prometheus jako źródło prawdy dla liveness floty
|
||||
|
||||
## Cel
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-24
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-24 — KB etap 2: importer Gmail (kod gotowy)
|
||||
|
||||
## Cel
|
||||
|
|
@ -171,7 +162,7 @@ jobs/gmail-bulk-import/pyproject.toml
|
|||
jobs/gmail-bulk-import/tests/test_importer.py
|
||||
hosts/piha/capabilities.yaml
|
||||
.gitignore
|
||||
kb/subsystems/kb-overview.md (etap 2 gotowy, konwencja jobs/)
|
||||
kb/subsystems/kb-mail-pillar.md (§8 krok 2 = kod gotowy)
|
||||
docs/kb/kb-00-overview.md (etap 2 gotowy, konwencja jobs/)
|
||||
docs/kb/kb-01-email-design.md (§8 krok 2 = kod gotowy)
|
||||
docs/sessions/2026-06-24-kb-gmail-importer.md
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-24
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-24 — fleet-prometheus etap 1: scaffold + deploy-node hostname fix
|
||||
|
||||
## Cel
|
||||
|
|
@ -108,7 +99,7 @@ docker compose \
|
|||
|
||||
---
|
||||
|
||||
## Nowe tech-debty (dodane do `kb/phases/backlog.md`)
|
||||
## Nowe tech-debty (dodane do `docs/backlog.md`)
|
||||
|
||||
1. **Rozjazd stanu Docker Compose na VPS** — serwisy `node-agent`, `control-plane` i inne
|
||||
stworzone innym `project-name` niż `deploy-node.sh` oczekuje; Recreate pada na stale
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-26
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-25 — KB etap 2: bulk import Gmail uruchomiony
|
||||
|
||||
## Cel
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-25
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-25 — fleet-prometheus etap 1: uruchomienie na VPS + incydent mózgu
|
||||
|
||||
## Cel
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-26
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-26 — fleet-prometheus etap 2: targety floty + zamknięcie buga deploy.sh vps
|
||||
|
||||
## Cel
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-30
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-30 — Inwentaryzacja floty + gaszenie dysku SATURN
|
||||
|
||||
## Cel
|
||||
|
|
@ -19,7 +10,7 @@ architekturą dokumentów KB. Start od weryfikacji stanu faktycznego wszystkich
|
|||
- CC (Sonnet 4.6) w worktree `fleet-inventory` zebrał stan faktyczny (docker ps +
|
||||
free/df/nproc) z 4 dostępnych nodów: PIHA, VPS, SOLARIA, SATURN. LUSTRO+CHELSTY
|
||||
offline (timeout :22) -> oznaczone UNREACHABLE.
|
||||
- Wynik: `kb/subsystems/fleet-inventory.md` — 23 zpriorytetyzowane rozjazdy.
|
||||
- Wynik: `docs/infra/inventory-2026-06-30.md` — 23 zpriorytetyzowane rozjazdy.
|
||||
- Kluczowe ustalenia:
|
||||
- **forgejo** biega na PIHA (always-on), ale `service.yaml owner_node=saturn` — rozjazd
|
||||
- **mosquitto** biega na VPS, `service.yaml owner=piha`, na PIHA go nie ma
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-30
|
||||
links: []
|
||||
---
|
||||
|
||||
# 2026-06-30 — Migracja kapala.org → Cloudflare + wildcard DNS-01, HA i Immich na mesh
|
||||
|
||||
## Cel
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-06-30
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-06-30 — fleet-prometheus liveness: reguły NodeDown + wpięcie watchdog→Prometheus
|
||||
|
||||
## Cel
|
||||
|
|
|
|||
|
|
@ -1,16 +1,7 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-02
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-02 — Modul 0 (odchudzenie PIHA) + migracja Forgejo/Vikunja na kapala.org
|
||||
|
||||
## Modul 0 kb-02 — WYKONANY (faza 1 audyt + faza 2 egzekucja)
|
||||
- Audyt CC (read-only): kb/audits/piha-slim-2026-07-02.md
|
||||
- Audyt CC (read-only): docs/infra/piha-slim-audit-2026-07-02.md
|
||||
- Review Oskara skorygowal audyt: llm-gateway = WLASNY kod (FastAPI-router LLM,
|
||||
/opt/llm-gateway, proxy do Ollama@SOLARIA) — NIE martwy; immich MUSI byc 24/7
|
||||
na PIHA (SOLARIA sesyjna) — rekomendacja przeniesienia wykreslona.
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-02
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-02 — recon-weryfikacja inwentaryzacji + rozbrojenie trzech min
|
||||
|
||||
## Cel
|
||||
|
|
@ -21,7 +12,7 @@ Sesja tylko-recon + minimalne fixy; bez deployów nowych feature'ów.
|
|||
|
||||
### Recon-weryfikacja inwentaryzacji floty (commit `57a6dff`, read-only)
|
||||
|
||||
Wynik: `kb/subsystems/fleet-inventory-verify.md`.
|
||||
Wynik: `docs/infra/inventory-verify-2026-07-02.md`.
|
||||
|
||||
**Bilans 23 rozjazdów z audytu 2026-06-30**:
|
||||
- **20 wciąż aktualnych** — nic się samo nie naprawiło.
|
||||
|
|
@ -100,7 +91,7 @@ Po jednej linii per plik; `owner_node` nie występował nigdzie indziej w repo.
|
|||
nie rezolwuje z SOLARII; brak formalnego override mem_limit fleet-prometheus
|
||||
w `hosts/vps/runtime/` (siedzi w bazowym compose — kosmetyka).
|
||||
|
||||
Wpisy dodane do `kb/phases/backlog.md` w tej sesji.
|
||||
Wpisy dodane do `docs/backlog.md` w tej sesji.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-06
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-06 — cutover liveności na Prometheus: recon starego toru + Etap 0 udowodniony w boju
|
||||
|
||||
## Cel
|
||||
|
|
@ -22,7 +13,7 @@ Prometheus → brain-watchdog → Telegram, którego brakowało od 2026-06-30.
|
|||
|
||||
### Recon cutoveru — wmergowany (commit `d94bb38`)
|
||||
|
||||
Wynik: `kb/audits/prometheus-cutover-2026-07-06.md` (517 linii, read-only,
|
||||
Wynik: `docs/infra/prometheus-cutover-recon-2026-07-06.md` (517 linii, read-only,
|
||||
zero zmian w kodzie). Kluczowe ustalenia:
|
||||
|
||||
- **Cutover to podmiana klasyfikacji liveności w JEDNYM miejscu** —
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-07
|
||||
links: []
|
||||
---
|
||||
|
||||
# Session log 2026-07-07 — Immich upload fix / pimain cleanup (kontynuacja 2026-07-03)
|
||||
|
||||
## Kontekst
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-07
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-07 — okit.pl Faza 1 (wildcard cert) + przepiecie 9 hostow
|
||||
|
||||
## Kontekst
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-09
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-09 — KB configi (9 decyzji) + wzorzec dzielenia plikow (Nextcloud twierdza + Gokapi)
|
||||
|
||||
## Kontekst
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-10
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-10 — Deploy 1 Paperless (DZIALA) + swap PIHA + npm-API tool w akcji
|
||||
|
||||
## Glowne osiagniecie: Paperless serwis LIVE
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-12
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-12 — Deploy 2: split-host OCR-worker (DZIALA) + decyzja kierunku KB
|
||||
|
||||
## Deploy 2 — OCR-worker na SOLARIA przez NFS: DZIALA end-to-end
|
||||
|
|
@ -46,7 +37,7 @@ maila = ta sama encja, DOWOD zasady kb-00 #7), (3) interfejs pytan (RAG) — pie
|
|||
realnej uzytecznosci. Dopiero POTEM dopelniac importy (reszta Takeout, zdjecia, transakcje).
|
||||
|
||||
## TODO nastepne
|
||||
- MODUL 5 (koperta + ingest + embeddingi + cross-source) — kb/phases/kb-m5-documents-ingest.md
|
||||
- MODUL 5 (koperta + ingest + embeddingi + cross-source) — docs/kb/modules/05-documents-ingest.md
|
||||
- Import probki zalacznikow z maili (kilkaset, nie 70k) — do zbudowania RAG
|
||||
- Interfejs pytan / RAG — warstwa uzytkowa
|
||||
- Deploy 3 (Nextcloud), Deploy 4 (Gokapi) — configi gotowe, czekaja
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-15
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-15 — Prometheus cutover Etap 2 (analiza GO) + domknięcie rodziny bugów event-pipeline/checkpoint
|
||||
|
||||
## Kontekst
|
||||
|
|
@ -27,12 +18,12 @@ parsowany z nazwy `evt-<node>-<ts>-...` (fallback mtime, **nigdy 0** dla
|
|||
istniejącego pliku — 0 = leksykalne "starszy niż checkpoint" = dokładnie ten
|
||||
poison), migracja starych path-checkpointów przy starcie. Zdeployowany na VPS
|
||||
(observer `StartedAt` 07-14). Zweryfikowany dziś jako kompletny i zdeployowany.
|
||||
Szczegóły: `kb/phases/backlog.md` (sekcja "Bug: checkpoint observera po ścieżce
|
||||
Szczegóły: `docs/backlog.md` (sekcja "Bug: checkpoint observera po ścieżce
|
||||
leksykalnej").
|
||||
|
||||
### 2. docs(infra) analiza Etapu 2 shadow-run (Fable, `8fec62d`)
|
||||
|
||||
`kb/phases/prometheus-cutover-etap2.md` — 165 mismatchy
|
||||
`docs/infra/prometheus-shadow-etap2-analiza-2026-07-15.md` — 165 mismatchy
|
||||
`SHADOW_LIVENESS_MISMATCH` solaria/lustro w dobie 2026-07-14 WYJAŚNIONE: dwa
|
||||
nocne wyłączenia węzłów (lustro 21:30 UTC — regularny power-off, solaria
|
||||
21:34 UTC). Wzorzec `event=fresh prom=down` to **nie** "żywy węzeł niewidziany
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-16
|
||||
links: []
|
||||
---
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -31,7 +22,7 @@ links: []
|
|||
|
||||
### 1. RECON lustro shipping (Fable, commit `542bba4`)
|
||||
|
||||
`kb/audits/lustro-shipping-2026-07-16.md` — 1507 mismatchy `lustro event=dead prom=up` w trwałym logu WYJAŚNIONE: (a) wczorajszy kontrolowany test (node-agent stał 3h20m, nie 15 min jak zakładano) + (b) poranny boot-race 56s. **Werdykt: shipping lustro działa, ZERO recurring problemu.** Prometheus 0 pomyłek w 48h — wzmacnia rekomendację GO dla Etapu 3 cutoveru.
|
||||
`docs/infra/lustro-shipping-recon-2026-07-16.md` — 1507 mismatchy `lustro event=dead prom=up` w trwałym logu WYJAŚNIONE: (a) wczorajszy kontrolowany test (node-agent stał 3h20m, nie 15 min jak zakładano) + (b) poranny boot-race 56s. **Werdykt: shipping lustro działa, ZERO recurring problemu.** Prometheus 0 pomyłek w 48h — wzmacnia rekomendację GO dla Etapu 3 cutoveru.
|
||||
|
||||
Znaleziska poboczne: lustro biega na obrazie sprzed 5 tyg (deploy-node bez `--build` — patrz fix #2 niżej); fake-hwclock boot-race (RPi bez RTC — pierwszy event po boocie ma stary stempel, dropnięty przez timestamp checkpoint).
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-20
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-17/18 — KB faza 3: kroki 2-5 DOMKNIĘTE
|
||||
|
||||
## Krok 2 — migracja 004 + pilot streszczeń A/B (17.07)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-22
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-17…21 — wątek KB: faza 3 kroki 3-5 DONE (+ incydenty)
|
||||
|
||||
**Krok 3 — kaskada summary→chunk:** bramka **PASS at N=10, k=5** (N-sweep {1..20}: N=5 to zmierzona podłoga, N=10 niesie 2× margines); kaskada nie degraduje niczego, na 186 dok nie poprawia (test architektury pod skalę mailową, zgodnie z przewidywaniem planu); koszt +1 SQL, zero dodatkowych embedów. cascade_query = domyślna ścieżka kb-query; flat_query zostaje jako baseline. Eval przepisany do wersjonowanego eval/queries.yaml + retrieval_eval.py.
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-22
|
||||
links: []
|
||||
---
|
||||
|
||||
# 2026-07-22 — HA: incydent dwóch mózgów, cutover ken, archiwum legacy
|
||||
|
||||
## Odkrycie
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-22
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-22 — KB faza 4: recon + kroki 1-2 (kb-query LIVE na PIHA)
|
||||
|
||||
**Recon+plan fazy 4** (05-faza4-plan.md, 603 linie): D1 wydzielenie packages/kb-retrieval (documents-ingest ciągnie anthropic+CLI — nie do obrazu serwisu); D2 fallback embed z pełną maszyną stanów, ale gate'owany kalibracją RAM na żywym PIHA (audyt nieaktualny, ~3.8Gi zajęte — plan daje kryteria i alternatywę: jawna degradacja 503 zamiast łamania inwariantu modelu); OIDC wbudowane w apkę (authlib, wzorzec repo — nigdy forward-auth); gmail: envelope_id już JEST Message-ID.
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-23
|
||||
links: []
|
||||
---
|
||||
|
||||
# 2026-07-22/23 — Control-plane: dziura w operator_ui + pierwszy pełny cykl remediacji bez SSH
|
||||
|
||||
Zamknięcie wielosesyjnego wątku "czemu mózg nie leczy floty". Dwa dni pracy,
|
||||
|
|
@ -70,7 +61,7 @@ approval → executor → node-agent → docker restart → completed.
|
|||
test E2E padł: agent rzucał `[Errno 13] Permission denied:
|
||||
/opt/homelab/actions/dispatch` co cykl. Root cause to ZNANY, POWRACAJĄCY
|
||||
(już 4. raz — patrz sekcja "Tech-debt: globalny porządek uid/gid/uprawnień
|
||||
we flocie" w `kb/phases/backlog.md`) motyw
|
||||
we flocie" w `docs/backlog.md`) motyw
|
||||
uid/gid na PIHA: oskar ma uid 1004, kontener agenta biega jako uid 1000
|
||||
(= user `pi` na hoście). `/opt/homelab/actions` było `oskar:oskar
|
||||
drwxr-xr-x` (utworzone w maju), podczas gdy DZIAŁAJĄCY wzorzec to
|
||||
|
|
@ -111,7 +102,7 @@ approval → executor → node-agent → docker restart → completed.
|
|||
Pierwszy w historii systemu pełny cykl remediacji end-to-end potwierdzony w
|
||||
produkcji (PIHA), bez SSH z control-plane do węzłów. Publiczna dziura
|
||||
autoryzacji na `operator_ui.py:18180` zamknięta (bind ograniczony do
|
||||
Tailscale). Otwarte follow-upy — patrz `kb/phases/backlog.md` (retry-w-nieskończoność
|
||||
Tailscale). Otwarte follow-upy — patrz `docs/backlog.md` (retry-w-nieskończoność
|
||||
zepsutego JSON, uprawnienia `actions/` na innych węzłach, brak twardego checka
|
||||
`.env`/`TAILSCALE_BIND_IP` w `deploy-local.sh`, brak autoryzacji w
|
||||
`operator_ui.py`, zapchana approval queue przez `alert_only`, brak
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-23
|
||||
links: []
|
||||
---
|
||||
|
||||
# 2026-07-22/23 — HA: adapter api, import ken, deploy.sh, otwarcie fazy 1
|
||||
|
||||
## Wykonane
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-23
|
||||
links: []
|
||||
---
|
||||
|
||||
# 2026-07-23 (cd.) — HA: klima E2E, audyt Fable, fix-pack 1
|
||||
|
||||
## Klima salonowa — pierwsza automatyzacja LLM przez repo (E2E)
|
||||
|
|
|
|||
|
|
@ -1,15 +1,6 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-23
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-23 — KB faza 4: ingress kb.kapala.org (krok 5/§8)
|
||||
|
||||
**Zakres**: wyłącznie ingress (`kb/phases/kb-m5-faza4.md` §8, krok 5) —
|
||||
**Zakres**: wyłącznie ingress (`docs/kb/modules/05-faza4-plan.md` §8, krok 5) —
|
||||
frontend i `/search` już LIVE na PIHA (port 8230) od sesji 2026-07-22. Zero
|
||||
zmian w kodzie kb-query w tej sesji.
|
||||
|
||||
|
|
@ -70,8 +61,8 @@ w tej samej sesji, osobnym przebiegiem po zgłoszeniu przez operatora:
|
|||
Potwierdzone w repo (zgodnie z `05-faza4-plan.md` §1.4): **brak wzorca
|
||||
forward-auth/reverse-proxy-level auth** — NPM community edition go nie ma
|
||||
(sprawdzone: brak `oauth2-proxy`/`authelia`/`forward_auth` w kodzie repo poza
|
||||
wzmiankami "przyszła opcja" w `kb/subsystems/kb-documents-pillar.md` i
|
||||
`kb/nodes/vps.md`). Wszystkie 3 precedensy (paperless/nextcloud/vikunja)
|
||||
wzmiankami "przyszła opcja" w `docs/kb/kb-02-documents-design.md` i
|
||||
`hosts/vps/README.md`). Wszystkie 3 precedensy (paperless/nextcloud/vikunja)
|
||||
robią OIDC **wewnątrz aplikacji**. kb-query nie ma dziś żadnego logowania.
|
||||
|
||||
Zgodnie z instrukcją zadania: **nie budowano** nowego komponentu auth.
|
||||
|
|
@ -122,7 +113,7 @@ username collision, `docs/sessions/2026-07-10-paperless-deploy.md`).
|
|||
|
||||
## Pliki repo zmienione
|
||||
|
||||
- `kb/services/kb-query.md` — sekcja "Ingress" (co żyje, co nie, dlaczego
|
||||
- `services/kb-query/README.md` — sekcja "Ingress" (co żyje, co nie, dlaczego
|
||||
auth odłożone) zastępuje starą notatkę "not wired up yet".
|
||||
- `docs/sessions/2026-07-23-kb-f4-ingress.md` — ten dokument.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-27
|
||||
links: []
|
||||
---
|
||||
|
||||
# 2026-07-27 — HA: legacy zamkniete, kasacje, pimirror, sonda Zigbee
|
||||
|
||||
## Wykonane
|
||||
|
|
|
|||
|
|
@ -1,15 +1,6 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-30
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-07-27 — KB faza 4: fallback embed SOLARIA→PIHA (krok 3, ostatni element rdzenia)
|
||||
|
||||
> **Dopisek redakcyjny (2026-07-30, dedup — `kb/phases/kb-m5-faza4-fallback-dedup.md`):**
|
||||
> **Dopisek redakcyjny (2026-07-30, dedup — `docs/kb/modules/05-fallback-dedup-raport.md`):**
|
||||
> implementacja kodu z tej sesji (`app/fallback.py`, branch `task/kb-f4-fallback`, 3d4ee38)
|
||||
> została **porzucona** — do mastera weszła równoległa, szersza implementacja tego samego
|
||||
> kroku planu (e7625cd, `app/embed_router.py`, 2026-07-29) i to ona biega na PIHA. Ten log
|
||||
|
|
@ -23,7 +14,7 @@ links: []
|
|||
> Z delty brancha uratowano ponadto: `retrieval_eval.py --transport http` (plan §2 D6/§9)
|
||||
> i luki testowe T1/T2 przeniesione do `test_embed_router.py`.
|
||||
|
||||
**Zakres**: `kb/phases/kb-m5-faza4.md` §2 decyzja 2 / §5 — aktywny fallback
|
||||
**Zakres**: `docs/kb/modules/05-faza4-plan.md` §2 decyzja 2 / §5 — aktywny fallback
|
||||
embedu, ostatni brakujący element rdzenia fazy 4 (frontend i ingress LIVE od
|
||||
2026-07-22/23, `docs/sessions/2026-07-23-kb-f4-ingress.md`). Zero zmian w schemacie
|
||||
DB, zero zmian w `kb_retrieval`'s retrieval logice — wyłącznie warstwa embed + health.
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-28
|
||||
links: []
|
||||
---
|
||||
|
||||
# Session log 2026-07-28
|
||||
|
||||
## Session 21:59
|
||||
|
|
@ -19,8 +10,8 @@ e8aa3e3 docs(architecture): recon multiagent 2026-07-27
|
|||
|
||||
### Files changed
|
||||
```
|
||||
kb/phases/subsystem-a-naprawa.md | 60 +++
|
||||
kb/subsystems/recon-multiagent.md | 551 +++++++++++++++++++++++
|
||||
docs/architecture/PLAN-subsystem-a-2026-07-28.md | 60 +++
|
||||
docs/architecture/RECON-multiagent-2026-07-27.md | 551 +++++++++++++++++++++++
|
||||
2 files changed, 611 insertions(+)
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-07-30
|
||||
links: []
|
||||
---
|
||||
|
||||
# 2026-07-30 — HA: legacy zamknięte, MCP read-only (faza 2a)
|
||||
|
||||
## Legacy — finał
|
||||
|
|
|
|||
|
|
@ -1,90 +0,0 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-08-04
|
||||
links: []
|
||||
---
|
||||
|
||||
# Session log 2026-07-31 — KB Faza 4: zamknięcie + pilot narty27
|
||||
|
||||
## Zakres
|
||||
Finalne domknięcie fazy 4 subsystemu B (KB) — **na twardo** — oraz podsumowanie
|
||||
pilota fazy 5 (narty27), wykonanego równolegle.
|
||||
|
||||
## Faza 4 — zamknięcie (na twardo)
|
||||
|
||||
### Dedup podwójnej implementacji fallbacku embed
|
||||
- Rozstrzygnięcie: master (`e7625cd`, `app/embed_router.py`) = źródło prawdy.
|
||||
- Z porzuconego brancha uratowano S1–S4 (`cb8a19d`):
|
||||
- `retrieval_eval.py --transport http`
|
||||
- session log 27.07
|
||||
- testy luk T1–T3
|
||||
- komentarz kalibracji progów dist.
|
||||
- Pełny rozbiór obu implementacji: `kb/phases/kb-m5-faza4-fallback-dedup.md`.
|
||||
|
||||
### Deploy na PIHA (z mastera)
|
||||
- `ollama-piha`: named volume `ollama_piha_models`, model bge-m3, `KEEP_ALIVE=0`.
|
||||
- `kb-query`: port 8230, bind 192.168.31.5, `EMBED_FALLBACK_URL` ustawione.
|
||||
|
||||
### Test sol-down — PASS na żywej produkcji
|
||||
Przebieg: pause ollama@SOLARIA → cache 30 s trzyma `up` → zapytanie przełącza się
|
||||
one-shot na PIHA (`embed_backend: piha`, wyniki poprawne) → `sol_status: down` →
|
||||
unpause → powrót `up` w ≤35 s.
|
||||
|
||||
Dodatkowo zaobserwowano **samoistne, jednorazowe zadziałanie breakera na produkcji** —
|
||||
przyczyna nieustalona, zachowanie zgodne z projektem (przełączenie i powrót bez
|
||||
utraty odpowiedzi).
|
||||
|
||||
### Progi dist (skalibrowane, obowiązują)
|
||||
`<0.45` hit / `0.45–0.55` szara strefa / `>0.55` brak odpowiedzi.
|
||||
|
||||
## Pilot fazy 5 — narty27 (POC, zostaje na stałe)
|
||||
|
||||
Publiczna wystawka `narty27.kapala.org` zbudowana **pełnym wzorcem docelowym fazy 5
|
||||
w miniaturze**:
|
||||
|
||||
markdown+frontmatter (OKF v0.1) → walidator konformancji (`check_okf`) → generatory
|
||||
(graf cytoscape, karty HTML, tabela porównawcza, zdjęcia z filtrem percepcyjnym,
|
||||
landing) → statyczny hosting (PIHA nginx + named volume) → publiczny ingress
|
||||
(NPM VPS + Let's Encrypt).
|
||||
|
||||
Źródło treści: `~/narty-2027/saalbach-kb` — lokalny git na SOLARII, **celowo poza repo
|
||||
infry**. Infra: `services/narty27`.
|
||||
|
||||
### Wnioski do przeniesienia na fazę 5 (wiki-kompilat)
|
||||
|
||||
1. **OKF v0.1 działa w praktyce**, a pinowanie wersji okazało się słuszne — spec
|
||||
ewoluuje (v0.2: `timestamp` → `generated: {by, at}`, provenance first-class;
|
||||
migracja = jedna zamiana pola). Przy fazie 5 rozważyć start od razu na v0.2 albo
|
||||
pin v0.1 z zaplanowaną migracją.
|
||||
2. **Walidator-lint jako stały element pipeline'u** wiki, nie jednorazowy skrypt.
|
||||
3. **Bug upstreamu `knowledge-catalog`**: generator grafu pomija linki od `/` wbrew
|
||||
§5.1 własnej spec → napisany własny generator. Kandydat na issue/PR do
|
||||
`GoogleCloudPlatform/knowledge-catalog`.
|
||||
4. **Reserved files**: `index.md` bez frontmattera (poza `okf_version` w root) —
|
||||
walidator to łapie.
|
||||
5. **Warstwa prezentacji z generatorów** — tani, użyteczny wzorzec do reużycia nad
|
||||
wiki-kompilatem KB.
|
||||
6. **Każdy artefakt ma mieć dom w gicie; sesje mają logi.**
|
||||
|
||||
## Otwarte po sesji
|
||||
|
||||
1. **`expected_envelope` w `mail_queries`** (`jobs/documents-ingest/eval/queries.yaml`)
|
||||
— nadal `null` (placeholdery, artefakt danych, nie kodu); kryterium 4 bramki na
|
||||
stubie nie przechodzi wyłącznie z tego powodu.
|
||||
2. **`hosts/solaria/runtime/ollama/docker-compose.override.yml` — brak w repo**
|
||||
(rozjazd repo↔runtime na SOLARII).
|
||||
3. **R1–R3 node-agent** (incydent `kb/incidents/2026-07-30-ollama-solaria-vanish.md`)
|
||||
— **niezrobione**: R1 `_prune_stopped_containers` nie może kasować kontenerów
|
||||
zarządzanych, R2 rate-limit dla `ai_node`/`standard`, R3 logowanie usuniętych
|
||||
zasobów. Przyczyna nadal aktywna → blokuje/warunkuje fazę mailową
|
||||
(M1 = mitygacja doraźna na czas backfillu).
|
||||
|
||||
## Następne kroki
|
||||
|
||||
1. Faza mailowa: batching Ollamy → backfill ~225k kopert → IMAP przyrostówka →
|
||||
PDF-y (~336) → GDrive Takeout.
|
||||
2. Blokada/ryzyko: node-agent R1–R3 (unfiltered prune) — eskalacja do subsystemu A;
|
||||
mitygacja M1 na SOLARII na czas backfillu.
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-08-05
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-08-05 — batching embed (start fazy mailowej)
|
||||
|
||||
## Weryfikacja zaległości
|
||||
|
||||
- **Uninstall natywnego `ollama.service` na PIHA — POTWIERDZONY.** Unit i binarka nie
|
||||
istnieją.
|
||||
- **Session log fazy 4 istniał już na masterze** (`e619c00`). Zgłoszony brak był fałszywym
|
||||
alarmem z niedociągniętego working tree na SOLARII.
|
||||
- **`task/prune-fix` (R1–R3 + M1 VPS) gotowy do review** w subsystemie A — `0526af1`,
|
||||
285 insertions, z testami.
|
||||
|
||||
## Task `kb-mail-batching`
|
||||
|
||||
Zmergowany do mastera: `02a0079` + `75116ad`.
|
||||
|
||||
### Bug blokujący Etap B (znaleziony i naprawiony)
|
||||
|
||||
Goły `builtins.TimeoutError` z wyczerpanego `aiohttp` `ClientTimeout` **nie był łapany**
|
||||
przez `flush_embed_buffer` — obsługa łapała wyłącznie `ClientError`. Skutek: zawieszona
|
||||
Ollama (failure mode „przyjmuje połączenie i milczy") wywalała cały run, bez breakera
|
||||
i bez flushu. Klasy przejściowe wyliczone są teraz jawnie w `TRANSIENT_EMBED_ERRORS`.
|
||||
|
||||
### `embed_batch_resilient()`
|
||||
|
||||
- Retry z backoffem wykładniczym.
|
||||
- Po wyczerpaniu retry — probe `/api/tags`:
|
||||
- backend **żywy** → bisekcja izolująca trujący chunk,
|
||||
- backend **martwy** → `gave_up`, bez bisekcji.
|
||||
|
||||
### Semantyka breakera (zmiana)
|
||||
|
||||
Breaker liczy **give-upy** (backend down wg probe), nie nieudane batche. Porażka częściowa
|
||||
nie przesuwa licznika. Zmiana znaczenia `--max-embed-failures` opisana w
|
||||
`kb/phases/kb-m5-faza-mailowa.md` §9.
|
||||
|
||||
### Parametryzacja i metryki
|
||||
|
||||
- Flagi: `--batch-size`, `--embed-retries`, `--embed-backoff`, `--embed-timeout`
|
||||
(env `MAIL_INGEST_*`).
|
||||
- Metryka `embed_ms_per_chunk`.
|
||||
- Wiersze zembedowane w umierającym batchu są commitowane przed abortem.
|
||||
|
||||
### Decyzja: brak fallbacku SOLARIA→PIHA dla backfillu
|
||||
|
||||
Świadomie **nie powstaje** — 790 ms/embed na CPU × 271k ≈ 60 h na współdzielonym nodzie.
|
||||
Tor online (`embed_router`) zachowuje fallback. Rozdział torów udokumentowany w docstringu
|
||||
`embed.py` / `embed_batch` oraz w `kb/services/job-mail-body-ingest.md`.
|
||||
|
||||
### Benchmark `mail-body-ingest-bench`
|
||||
|
||||
Read-only (SELECT + inferencja). Wyniki na SOLARII (bge-m3, GPU), próbka 640 chunków
|
||||
(avg 1559 znaków):
|
||||
|
||||
| batch | ms/chunk |
|
||||
|------:|---------:|
|
||||
| 32 | 22.70 |
|
||||
| 64 | 16.57 |
|
||||
| 128 | 15.82 |
|
||||
|
||||
**Default batch 64 POTWIERDZONY** — zysk z 128 to ~4.5%, a przy 64 koszt bisekcji jest
|
||||
mniejszy. Ekstrapolacja na 271k chunków: **~1.25 h GPU** vs ~11 h przy per-request.
|
||||
|
||||
### Testy
|
||||
|
||||
117 testów zielonych.
|
||||
|
||||
## Wyjątki procesowe
|
||||
|
||||
Żadnych. Commit z PIHA nie zaistniał — CC nie dopisał wskaźnika, uznano za zbędne.
|
||||
|
||||
## TODO wynikające
|
||||
|
||||
- **Rotacja hasła `kb-postgres`** — poszło do historii shella i na screeny sesji.
|
||||
- **`POSTGRES_PASSWORD` plaintext w `services/*/service.yaml`** — kandydat na backlog
|
||||
sekretów.
|
||||
- **`kb-site` `robots.txt` blokuje fetch Claude** (`ROBOTS_DISALLOWED`) — fix: `X-Robots-Tag
|
||||
noindex` zamiast `Disallow` (wariant B), przy okazji taska `kb-site`.
|
||||
- **Backfill 271k** — dopiero po merge + deploy `task/prune-fix` (subsystem A).
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-08-05
|
||||
links: []
|
||||
---
|
||||
|
||||
# Session log 2026-08-05
|
||||
|
||||
## Session 22:47
|
||||
|
||||
Redeploy node-agenta R1/R2/R3 na flotę (supervised, checkpointy zatwierdzane przez
|
||||
operatora). Incydent źródłowy: `kb/incidents/2026-07-30-ollama-solaria-vanish.md`.
|
||||
|
||||
### Commits
|
||||
|
||||
Ta sesja **nie wprowadziła żadnych commitów** poza niniejszym logiem — deploy runtime,
|
||||
zero zmian w kodzie. Granica wyznaczona fallbackiem 24 h (poprzedni log sesji nie używa
|
||||
nagłówków `## Session HH:MM`), więc poniższa lista obejmuje też wcześniejszą pracę
|
||||
operatora z tego samego okna, niezwiązaną z tym deployem:
|
||||
|
||||
```
|
||||
bb3792d docs(kb-site): przekaz ACCESS_TOKEN generatorowi w procedurze publikacji
|
||||
f5c6f3b fix(kb-site): token bramki w kazdym linku wewnetrznym generatora
|
||||
04251b5 docs(sessions): log sesji 2026-08-05 — batching embed (start fazy mailowej)
|
||||
75116ad docs(kb-retrieval): rozdzial torow embed takze w docstringu embed_batch
|
||||
02a0079 feat(kb-mail-batching): retry + izolacja trujacego chunka w torze embed + benchmark
|
||||
71eaab0 feat(supervisor): duty-cycle nodes — liveness transitions logged, not actioned
|
||||
19548d8 fix(kb-site): wycofaj robots.txt — blokowal legalny fetch z tokenem
|
||||
67e49a0 docs(kb-site): przepisz nieaktualne kb.okit.pl na kb-e2a24af3.okit.pl
|
||||
db81cb1 feat(kb-site): noindex + robots.txt + obscure subdomain jako domyslny base-url
|
||||
7282a5e docs(recon): sciezka redeploy — fix jest w repo od 2026-08-03, nie jest wdrozony
|
||||
```
|
||||
|
||||
### Files changed
|
||||
|
||||
Brak — drzewo robocze czyste przez całą sesję, poza tym plikiem.
|
||||
|
||||
### Deploys
|
||||
|
||||
Recon wykazał, że zakres jest węższy niż zakładano: PIHA i VPS **już** miały kod R1/R2/R3
|
||||
(weryfikacja sha256 pliku w kontenerze vs repo). Realny zakres: SOLARIA i LUSTRO.
|
||||
LUSTRO nie było w pierwotnej liście, a było jedynym nodem faktycznie kasującym bez filtra.
|
||||
|
||||
| Node | Przed | Po | Wynik |
|
||||
|---|---|---|---|
|
||||
| SOLARIA | `c80a711f` (2026-07-22, pre-R1) | `438111e2` | OK, bez rollbacku |
|
||||
| LUSTRO | `460d5cc5` (2026-06-11, 658 linii) | `3260c74a` | OK, bez rollbacku |
|
||||
| PIHA | `9141cc61` — sha == repo HEAD | bez zmian | deploy pominięty (już aktualny) |
|
||||
| VPS | `27be875d` — R1/R2/R3 obecne | bez zmian | deploy pominięty (różnice tylko w komentarzach) |
|
||||
|
||||
Weryfikacja po deployu na obu wdrożonych nodach: kontener `Up (healthy)`, zero tracebacków,
|
||||
sha256 `node_agent.py` w runtime == repo HEAD, brak wykonywalnego `containers.prune()`,
|
||||
`docker ps -a` identyczne z pre-snapshotem, heartbeat świeży. `NODE_TYPE` zachowane
|
||||
(SOLARIA `lte_node` = M1, LUSTRO `sd_card`). Marker `last-docker-cleanup` na LUSTRO
|
||||
nie wyzerował się przy recreate.
|
||||
|
||||
Test e2e na SOLARII (kanarek `restart=unless-stopped` bez labela compose): zatrzymany,
|
||||
przeżył 151 s (>2× CHECK_INTERVAL) jako `exited`, nie usunięty. Dry-run logiki filtra
|
||||
bez wywołania `remove()`: REMOVE=0 na obu nodach.
|
||||
|
||||
Obrazy sprzed deployu otagowane `node-agent:rollback-pre-r1` na SOLARII i LUSTRO
|
||||
(na SOLARII były dangling — groziło zjedzenie celu rollbacku przez przyszły prune).
|
||||
|
||||
### Narrative
|
||||
|
||||
> _user-provided summary_
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-08-06
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-08-06 — Etap B: weryfikacja korpusu + fix NUL (ZAMKNIĘTY)
|
||||
|
||||
## Przebieg plastrów
|
||||
|
||||
Plastry 0-4 (`--offset 0/50000/100000/150000/200000 --limit 50000 --batch-size 64`)
|
||||
— **wszystkie EXIT 0** po fixie. Cały korpus 225k kopert przeskanowany
|
||||
idempotentnie, zero strat.
|
||||
|
||||
## Bug znaleziony i naprawiony: NUL byte (0x00) w treści maila
|
||||
|
||||
Plaster offset 50k wywalił się na mailach z 2007 (Sony Ericsson, 3 chunki):
|
||||
bajt NUL w tekście → `asyncpg.CharacterNotInRepertoireError` przy insercie
|
||||
(PostgreSQL nie przyjmuje `0x00` w `text`).
|
||||
|
||||
Fix `4ec0b78`: strip `\x00` przed chunkowaniem i embedem + liczniki
|
||||
`nul_bytes_stripped` / `mails_nul_sanitized`. Re-run plastra 1: **EXIT 0**,
|
||||
3 chunki dobrane.
|
||||
|
||||
## Weryfikacja w DB (kb-postgres@PIHA, `document_chunk`)
|
||||
|
||||
| Miara | Wartość |
|
||||
|---|---|
|
||||
| `document_chunk` total | **389 012** |
|
||||
| nie-excluded **bez** embeddingu | **0** |
|
||||
| nie-excluded z wektorem | 187 025 |
|
||||
| newsletter-flagged bez wektora | 201 849 (odwracalne) |
|
||||
| excluded **z** wektorem | 138 (artefakt kolejności flagowania, nieszkodliwy) |
|
||||
|
||||
## Wniosek
|
||||
|
||||
**Korpus był w pełni zembedowany jeszcze przed dzisiejszymi plastrami.**
|
||||
Zapamiętany stan „6,4k embedded z Etapu A, ~225k kopert do backfillu" był
|
||||
nieaktualny — wcześniejsze przebiegi pokryły całość. Dzisiejsze runy to
|
||||
w praktyce pełna, idempotentna weryfikacja korpusu (plus wykrycie i naprawa
|
||||
buga NUL).
|
||||
|
||||
Źródło mylącego odczytu: licznik `chunks_already_embedded` liczy **istnienie
|
||||
wiersza w DB** (w tym chunków newsletter-flagged bez wektora), a nie obecność
|
||||
wektora — stąd niespójne wrażenie z liczników plastrów.
|
||||
|
||||
## Środowisko
|
||||
|
||||
- venv w głównym repo (`pip install -e` dla `kb-mail` / `kb-retrieval` /
|
||||
`mail-body-ingest`).
|
||||
- tmux `backfill`, logi w `~/kb/mail/ingest-logs/` (poza repo).
|
||||
|
||||
## Follow-upy
|
||||
|
||||
- `jobs/gmail-header-backfill` i `jobs/gmail-bulk-import` używają
|
||||
`sanitize_surrogates` na nagłówkach zapisywanych do `jsonb` — **ta sama
|
||||
latentna podatność na NUL**. Nieruszone w tej sesji, osobny task.
|
||||
- **Rotacja hasła `kb-postgres`** — nadal otwarta (z sesji 2026-08-05).
|
||||
|
||||
## Następny krok fazy mailowej
|
||||
|
||||
**IMAP przyrostówka gmail + fastmail** (`source='fastmail'`) — teraz odblokowana.
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue