# SubSaipen Read-only research agents that work in parallel. Extension, not Core (RFC SS 1.9). ## Protocol Each subSaipen lives in `.saipen/extensions/subs//` with: - STATE.md (own phase/task/next_action, mode: read-only) - BOARD.md (own tickets: SUB-###) - LOG.md (own event graph: S-###) - kitchen/OUTBOX.md (findings for main agent) **Key rules:** - Read-only: never write to main project. Findings only via OUTBOX. - One write path: main agent collects OUTBOX -> creates tickets -> works them. - OUTBOX validated by `tools/validate.py`: needs status/summary/critical on `ready`. - Patch support: a fixer-type sub (saipython) emits patches with `base_head:` + `verified:`. - **Backpressure** (v7.98.0+): sub pauses own work if >10 `ready` entries pile up unreviewed. - **Boundary check on collect** (v7.98.0+): main agent runs `git status` against whole tree before folding findings. A confused sub that wrote outside its folder gets caught. ## Active sub-agents | Agent | Role | Status | |---|---|---| | **saiwiki** | Wiki maintainer | Scans project, detects drift from wiki, reports refresh needs. 3 OUTBOX cycles completed (WIKI-005 through WIKI-008); refresh W-025 closed. Every finding collected and ticketed. | | **saihunt** | HUNT sweeper | Runs 6-category HUNT scan as parallel subagent | | **saitranslate** | Translation builder | Builds locale packs (read-only limitation: cannot execute TRANSLATE phase). Latest output was Core-reviewed after a boundary violation; all 32 locales + 3 root mirrors + 28 non-Core guides are current at v7.157.0 under one-source parity guards. | | **saipython** | Python fixer | Fixer-type: finds type/error-handling issues, emits patches. Spawned, never run — 5 open tickets, 0 done. WARNs as never-run until first collection. | ## Spawning ``` > saipen sub spawn saiwiki > saipen sub spawn saihunt > saipen sub spawn saipython ``` A bare sub name — `saiwiki`, `saihunt`, `saitranslate`, anything `sai*` — is a role-adopt command: the agent spawns it if missing, becomes it, starts its own cycle. No second command needed. `saipen sub sync` refreshes the shared protocol files (PROTOCOL/README/crew/TEMPLATE) from the SAIPEN home without touching any sub's own history. The main agent stays the single writer. Sub-agents research and report. No write races by construction. ## Collecting OUTBOX ``` Main agent: reads /kitchen/OUTBOX.md validates entry (status: ready? has summary?) creates main-tree tickets from findings marks OUTBOX entry status: reviewed logs: RUN: collect -### -> T-### ``` Write order is crash-safe: create the main ticket and append LOG line FIRST, then mark OUTBOX `reviewed` LAST. Duplicate on retry is safe; a lost finding is not. Non-critical findings go to `_shared/inbox.md` for the next planning round; `critical: true` entries get ticketed immediately on the main board. ## Key distinction: read-only scope vs capability (v7.111.0) `mode: read-only` means two different things: - **Core read-only** = *capability* lock: filesystem write unavailable, bans all 7 phases whose product is a file write (INIT, PLAN, ADD, BUILD, SHIP, CLEAN, TRANSLATE). - **SubSaipen read-only** = *scope* lock: writes its own STATE/BOARD/LOG/kitchen freely, banned from shared tree. Only 4 phases banned (BUILD, SHIP, CLEAN, TRANSLATE). PLAN and ADD are reachable and expected — sub plans own backlog. This means `HUNT -> DONE` is legal for a subSaipen (v7.111.0): a reporting sub's deliverable is its OUTBOX, the "add" step happens during main-agent collect. `saihunt` had been in that state truthfully since its first sweep. Sub STATE.md now validated against Core's full rule set: 9th required field, transition legality, ISO-8601 `updated`, command vocabulary (v7.111.0). ## Validation guards (v7.98.0+) `tools/validate.py` enforces these subSaipen invariants on every invocation: - **Sub next_action format**: every sub STATE.md `next_action` must follow RFC SS 1.2 prefix rules — `WAIT:` with category token, `RESUME:`, `PHASE`, or `saipen` command. Bare prose rejected. - **Self-transition enum check**: if sub's `transition_from` equals its `phase`, the phase must be one of 16 known enum values. - **Adapter path existence**: every `saipen/` path in `extensions/adapters/*.md` must be a real file. - **Liveness check** (v7.99.0): sub with open tickets, zero done, empty OUTBOX WARNs as never-run. `ready` entries WARN as findings waiting on `collect`. - **TEMPLATE validated** (v7.101.0): the shipped TEMPLATE/STATE.md was previously exempted by name — hid a prefix-less `next_action`. Every spawned sub was born non-conformant. Fixed. - **Sub STATE parity** (v7.111.0): sub STATE.md held to Core's rules — 9th required field, transition table, ISO-8601 `updated`, command vocabulary. Was previously checking a fraction. saipython (fixer-type) also has: - **Capability gate**: missing Python/pytest/ruff on host -> degrades to finding-only (saihunt-style), never fakes a `verified:` result. - **Scope discipline**: one fix per patch, minimal diff. P2/P3 only — anything large or architectural goes to `critical` finding for the main agent. ## ДED Voice > "Под-агенты? Как бригада. Один ищет баги, второй чинит Python, третий переводит документацию. Главный агент собирает результаты и делает тикеты. Никто не мешает друг другу. Каждый в своей песочнице. И никаких 'я случайно переписал твой файл'. Потому что читать можно всем, писать — только одному."