# Autonomní ingestní pipeline — sjednocená sdílená složka (UnifiedIngest)

**Status:** návrh dokumentace k připravené implementaci (čeká na schválení vlastníka, není zapsáno do `src/`)  
**Komponenta:** `src/cyberbrain26/product/shared_root.py` (nový soubor) + úprava `src/cyberbrain26/product/__init__.py`  
**Rozsah:** dokumentace, markdown — nezasahuje do kódu, testů ani konfigurace

---

## 1. Cíl a architektura

Účelem je sjednotit rozptýlená data uživatele napříč zařízeními (Debian Mentem, virtuálka s CyberBrain26, Android telefon, tablet s kontejnerem a lokálním modelem) do jedné sdílené složky `SHARED_ROOT` a zpracovat je autonomním ingestním pipelinem.

### Datový tok

```
dropzone (inbox/)  →  fronta (claim_batch → processing/<batch_id>/)  →  třídění (sorted/ | duplicates/)  →  index (index/ + ingest-manifest.jsonl)
```

1. **Dropzone / fronta** — soubory přibývají do `inbox/` (např. přes Syncthing, rclone, ruční kopírování). Pipeline si nárokuje dávku (`claim_batch`) a přesune první `N` souborů (max. `BATCH_LIMIT_MAX = 10`) atomickým `rename` do `processing/<batch_id>/`.
2. **Třídění** — soubory se třídí do `sorted/` nebo `duplicates/` podle obsahu/otisku. Citlivé soubory se přeskočí se statusem `skipped` a důvodem `[REDACTED]`.
3. **Index** — každý krok se zapisuje do append-only JSONL manifestu `ingest-manifest.jsonl`. `index/` obsahuje výsledný index.

### Fail-closed principy

- Žádný tichý fallback. Pokud nelze určit `SHARED_ROOT`, pipeline selže s chybou, nikoli tichým použití nesprávné cesty.
- `rclone` se nikdy nespouští přes `rclone config`; kontroluje se pouze existence `~/.config/rclone/rclone.conf`.
- Citlivé cesty (`.ssh`, `.gnupg`, `*.kdbx`, `auth.json`, `credentials.json`, `*.key`, `*.pem`, klíčová slova `secret`/`token`/`cred`/`password`) se detekují přes `is_sensitive_path()` a přeskočí se s redakcí.

---

## 2. Adresářová struktura SHARED_ROOT

```
<SHARED_ROOT>/                      (výchozí: ~/UnifiedIngest, env UNIFIED_INGEST_ROOT)
├── inbox/                          dropzone — příchozí soubory ke zpracování
├── processing/                     fronta — zpracovávající se dávky <batch_id>/
├── sorted/                         tříděné, jedinečné soubory
├── duplicates/                     duplikáty
├── index/                          výsledek indexace
├── tasks/                          úkoly pipeline
└── manifest/
    └── ingest-manifest.jsonl       append-only JSONL manifest (režim 0o600)
```

Všechny podsložky se vytvářejí s režimem `0o700`; cesty v manifestu jsou relativní vůči `SHARED_ROOT`.

---

## 3. Objevování SHARED_ROOT (discovery)

Funkce `resolve_shared_root(explicit=None)` volí kořen v tomto pořadí (fail-closed, první dostupná možnost vyhrává):

1. `explicit` — přímo předaná cesta (nejvyšší priorita)
2. proměnná prostředí `UNIFIED_INGEST_ROOT`
3. existující Syncthing složka (detekována přes `~/.config/syncthing/config.xml`, pouze existence)
4. `~/Sync/`
5. `~/Documents/`
6. `~/Downloads/`
7. fallback `~/UnifiedIngest/`

Pomocné funkce:

- `detect_syncthing_folders()` — čte `~/.config/syncthing/config.xml` (pouze ověření existence souboru)
- `is_rclone_configured()` — kontroluje pouze existenci `~/.config/rclone/rclone.conf` (nikdy nespouští `rclone config`)
- `list_mountpoints()` — čte `/proc/mounts`, `/mnt`, `/media`
- `ensure_shared_root()` — vytvoří kořen + 7 podsložek s režimem `0o700` + prázdný manifest

---

## 4. Bezpečnostní pravidla

| Pravidlo | Popis |
|----------|-------|
| Fail-closed | Selhání Discovery / schválení / sandboxu blokuje zpracování, žádný tichý fallback |
| Ignore-list | `SENSITIVE_PATTERNS` filtraje citlivé cesty (.ssh, .gnupg, *.kdbx, auth.json, credentials.json, *.key, *.pem, secret/token/cred/password) |
| Redakce | Citlivé soubory se přeskočí se statusem `skipped` a důvodem `[REDACTED]` (obsah se nikdy nezapíše do manifestu) |
| Režim souborů | Složky `0o700`, manifest `0o600` |
| Relativní cesty | Manifest ukládá cesty relativně vůči `SHARED_ROOT` (neabsolutní, neobsahují domovský adresář uživatele) |
| Atomický přesun | Soubory z `inbox/` do `processing/<batch_id>/` přes atomický `rename` |
| Dávkový limit | `claim_batch` maximálně `BATCH_LIMIT_MAX = 10` souborů na dávku |

---

## 5. Schema manifestu (`ingest-manifest.jsonl`)

Jeden JSON objekt na řádek (JSONL), append-only, režim `0o600`. Přehled polí (bez předepisování příliš detailů):

- `batch_id` — identifikátor dávky (`claim_batch`)
- `action` — typ akce (např. `claimed`, `processed`, `skipped`, `indexed`)
- `path` — cesta relativní vůči `SHARED_ROOT`
- `status` — `ok` / `skipped` / `error`
- `reason` — důvod (u citlivých souborů `[REDACTED]`)
- `timestamp` — časové razítko události
- `size` / `sha256` — volitelné metadata souboru (velikost, otisk)

Příklad řádku (ilustrační):

```jsonl
{"batch_id":"batch-20261104-0001","action":"claimed","path":"inbox/dokument.pdf","status":"ok","timestamp":"2026-11-04T21:00:00Z","size":12345,"sha256":"..."}
{"batch_id":"batch-20261104-0001","action":"skipped","path":"inbox/.ssh/id_rsa","status":"skipped","reason":"[REDACTED]","timestamp":"..."}
```

---

## 6. Postupné kroky implementace (1–5)

### Krok 1 — Minimální start (kostra)

- Vytvořit `src/cyberbrain26/product/shared_root.py` s konstantami: `ENV_SHARED_ROOT`, `DEFAULT_SHARED_ROOT`, `INGEST_SUBDIRS`, `MANIFEST_FILENAME`, `BATCH_LIMIT_MAX`, `SENSITIVE_PATTERNS`.
- Implementovat `resolve_shared_root()`, `ensure_shared_root()`, `manifest_path()`, `manifest_write()`.
- Rozšířit `__all__` v `src/cyberbrain26/product/__init__.py` o symboly z `shared_root`.
- Ověřit: `ensure_shared_root()` vytvoří kořen + 7 podsložek (`0o700`) + prázdný manifest (`0o600`).

### Krok 2 — Objevování a detekce prostředí

- `detect_syncthing_folders()` (existence `~/.config/syncthing/config.xml`)
- `is_rclone_configured()` (existence `~/.config/rclone/rclone.conf`, bez spuštění rclone)
- `list_mountpoints()` (`/proc/mounts`, `/mnt`, `/media`)
- `is_sensitive_path()` detekce citlivých cest

### Krok 3 — Claim dávky a atomický přesun

- `claim_batch(shared_root=None, limit=10)` — přesune první `N` souborů (max 10) z `inbox/` do `processing/<batch_id>/` přes atomický `rename`.
- Claim zapsat do manifestu. Citlivé soubory přeskočit se statusem `skipped` a důvodem `[REDACTED]`.

### Krok 4 — Třídění a index

- Přesun ze `processing/<batch_id>/` do `sorted/` nebo `duplicates/` podle otisku.
- Zápis výsledku do `index/` a do manifestu (`action: indexed`).

### Krok 5 — Integrace do CyberBrain26

- Propojit s `promptmaster` → `orchestrator` (jediný delegátor) a delegační maticí v `.kilo/agent/orchestrator.md`.
- Navázat na `product/local_store.py` (resolve datového adresáře, DB, retention) — `SHARED_ROOT` je nezávislá složka, není to `CYBERBRAIN_DATA_DIR`; ostatní product vrstva zůstává beze změny.
- Ověřit bránami: Gate 1 (pytest, ruff, mypy), Gate 2 (diff, coverage), Gate 3 (nezávislý auditor).

---

## 7. Integrace do CyberBrain26

Pipeline patří do vrstvy `product/` vedle `local_store.py`, `approvals.py` a `doctor.py`. `local_store.py` řeší resoluci datového adresáře/DB/retenci (`CYBERBRAIN_DATA_DIR`, `CYBERBRAIN_DB_PATH`, `CYBERBRAIN_RETENTION_DAYS`); `shared_root.py` řeší resoluci `SHARED_ROOT` přes `UNIFIED_INGEST_ROOT`. Oba jsou nezávislé, sdílejí princip fail-closed discovery přes proměnné prostředí a explicitní fallback.

Orchestrace vstupuje přes `promptmaster` → `orchestrator` (jediný delegátor, D14/D6). Delegace pro subagenty je v `.kilo/agent/orchestrator.md` (§ Delegační matice). `documenter` má `edit: allow` pouze pro markdown (tento soubor); `implementer` zapisuje do `src/` až po schválení vlastníka.

---

## 8. Omezení a poznámky

- Implementace `shared_root.py` je připravená k zápisu do `src/`, ale čeká na schválení vlastníka (zápis do `src/` vyžaduje `implementer` + owner approval).
- Dokumentace popisuje stav připravené implementace, ne nasazený kód.
- Pokud vlastníka schválení neudělí, zůstává jen tato dokumentace (návrh).

---

Související: `.kilo/plans/CyberBrain26cil-031026-v2.md` (autoritativní plán), `.kilo/agent/orchestrator.md` (delegační matice), `product/local_store.py`.
