Files
cyclone/docs/superpowers/specs/2026-07-08-cyclone-doc-pass-design.md
T
2026-07-08 23:01:55 -06:00

117 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sub-project 42 — Doc-Pass: Reconcile Stale Docs with SP23SP41 Reality: Design Spec
**Date:** 2026-07-08
**Status:** Draft, awaiting user sign-off
**Branch:** `sp42-doc-pass`
**Aesthetic direction:** No new UI (docs-only increment; no code paths change).
## 1. Scope
Between SP23 (Ubuntu + Docker + auth + RBAC + LAN-bind product fork, merged `07a7ecb` on 2026-06-23) and SP41 (in-window rebill pipeline, merged `309e6c0` on 2026-07-08), 19 increments landed on `main` without a corresponding documentation alignment pass. The CLAUDE.md, README.md, ARCHITECTURE.md, REQUIREMENTS.md, and the eight `.superpowers/skills/*/SKILL.md` files all carry stale references to:
- the pre-SP21 monolithic `store.py` (~2,423 LOC) and pre-SP36 monolithic `api.py` (~3,548 LOC) — both have since been split;
- `127.0.0.1` as the bind address — SP23 moved the bind to `0.0.0.0` with the host firewall now controlling reachability;
- the "no auth" posture — SP23 landed bcrypt + HttpOnly session cookies via `cyclone.auth.*`;
- the SP23 product fork being "awaiting user decision" — SP23 is in `main`;
- the "SP22 used, next is SP24" / "SP22 used, next is SP25" framing in skill files — last merged SP is SP41, next free is SP42;
- the "12 SQL migrations" claim — 23 migrations are on disk (0001_initial through 0023_visits);
- the "4 router modules" claim in `cyclone-api-router/SKILL.md` — SP36 split `api.py` into 22 routers under `api_routers/`;
- the "Seven subcommands" claim in `cyclone-cli/SKILL.md` — SP24 / SP25 / SP27 / SP28 / SP33 / SP37 / SP38 / SP39 / SP40 / SP41 added ~12 more;
- the "22 specs / 27 plans" / "17 specs / 13 plans" framing — 42 specs and 37 plans are on disk;
- the "single 2412-line module" claim in `cyclone-store/SKILL.md` — SP21 shipped the split into 16 modules.
SP42 is a **docs-only** increment: every change is to `*.md` files. No code paths change; no API endpoints change; no test assertions change.
**In scope:**
- `CLAUDE.md` — refresh the SP-N section (last merged SP, next free, file-size + subpackage claims), the migration count, and the CLI subcommand list (drop the three phantom `parse-999` / `parse-ta1` / `parse-277ca` entries that contradict the body text).
- `README.md` — replace the "binds to `127.0.0.1`, no auth, no internet exposure" lead with the SP23 posture ("always binds to `0.0.0.0`, requires login, LAN-only by design"), update the project-layout block to reflect the post-SP21/SP36 split, and refresh the "Sub-projects 2 through 19 are shipped" framing.
- `docs/ARCHITECTURE.md` — refresh the §1 / §2 / §4.1 / §4.3 / §5.4 / §6.2 / §7.4 / §8.1 / §11.2 / §13.2 blocks. SP23 is shipped (drop "awaiting user decision"). The package-layout map gets `auth/`, `handlers/`, `rebill/`, `reissue/`, `store/` (the SP21 facade), and the full 22-router `api_routers/`. The SP21 split is present-tense. The endpoint enumeration in §8.1 gets refreshed. The §6.3 claim-state diagram gains `partial` (REQUIREMENTS FR-6 already lists it). The §7.4 audit strategy list gets `pcn-exact` (SP31) replacing the stale `auto:pcn_npi_charge` / `auto:pcn_charge` labels. The migration table goes from 12 to 23.
- `docs/REQUIREMENTS.md` — move SP23 from §6.2 backlog to §6.1 shipped. Close R-1 (auth shipped), R-3 (Dockerfile / docker-compose shipped), R-11 (SP21 store split shipped), R-12 (SP36 api.py split shipped) with concrete evidence. Update R-13's migration count to 23. Add SP23SP41 rows to the §6.1 SP table. Update §5.1 LOC claims and module list. Update §5.2 migration table. Update §12.1 / §12.2 spec-and-plan lists.
- `docs/RUNBOOK.md` — replace "the SP23 Docker stack" with "the Docker stack"; keep the existing "Reissue claims (SP24)" section as-is (already correct).
- `.superpowers/skills/cyclone-spec/SKILL.md` — refresh the "As of this writing" header line.
- `.superpowers/skills/cyclone-tests/SKILL.md` — refresh test counts (178 backend tests, 22 fixtures, 130+ frontend test files) and the SP-N "next" pointer.
- `.superpowers/skills/cyclone-store/SKILL.md` — drop the "single 2412-line module, SP21 in progress" framing; update line refs from `store.py:882` to `store/__init__.py:148`; complete the SP21 module list (add `backfill.py`, `claim_acks.py`, `kpis.py`, `resubmissions.py`, `submission_dedup.py`); update line refs from `api.py:1380-1401` / `api.py:1891,2002` to the post-SP36 router files.
- `.superpowers/skills/cyclone-api-router/SKILL.md` — replace "4 router modules" with "22 router modules"; replace the "next refactor target is the parse endpoints" note with the post-SP36 reality; update line refs in the "Mounting in `api.py`" example.
- `.superpowers/skills/cyclone-edi/SKILL.md` — refresh the SP-N "next" pointer.
- `.superpowers/skills/cyclone-frontend-page/SKILL.md` — refresh page / hook / drawer counts (12 pages, 19 hooks, 4 drawers including `ProviderDrawer/` + `AckDrawer/`); refresh SP-N "next" pointer.
- `.superpowers/skills/cyclone-cli/SKILL.md` — replace the "Seven subcommands" claim with the canonical 15+ subcommand list per the actual `cyclone/cli.py`; refresh SP-N "next" pointer.
- `.superpowers/skills/cyclone-tail/SKILL.md` — refresh the "three streaming pages" claim (add `Acks` per SP25 ack-live-tail); replace `api.py:1357-2006` line refs with the post-SP36 router files.
**Out of scope:**
- Any code change. SP42 is docs-only.
- Any new feature description beyond what already exists in code. The spec is a *reconciliation* pass, not a *content* pass.
- Documenting SP34 (`999-acceptance-restore`). The branch was orphaned; SP31 supersedes the underlying race via the 2-of-3 match rule. The doc-pass must not list SP34 as shipped.
- Documenting SP25's three-topic reuse as separate SPs. The historical anomaly is acknowledged in the SP42 spec but the doc pass keeps the merged-message convention (one row per merge commit).
- Resolving the SP24 number collision (reissue-claims vs auth-posture alignment). The current main HEAD merge commit `c9588f7` carries the subject "merge: SP24 reissue-claims into main", so SP24 is the reissue work; the 2026-06-23 docs-only auth-posture-alignment work landed as a sub-task of SP23 and is documented there.
- A full rewrite of any section. The doc-pass updates only the lines that are stale; it does not restructure narrative.
- The dead `backend/src/cyclone/workflow/` directory. R-27 is left Open; deletion is a follow-up increment.
## 2. Decisions (locked during brainstorming)
1. **Docs-only — no code paths change.** Per the cyclone-spec skill convention, this is documented but enforced by reading the diff before each commit. Every commit in the SP42 branch must touch only `*.md` files (plus the spec/plan docs themselves).
2. **One commit per file, prefixed `docs(sp42): <file> …`.** Keeps the SP42 merge commit readable and lets reviewers bisect a single stale doc back to a specific commit if a future refactor pulls a doc claim back out of date.
3. **Mechanical fixes only.** Where the existing prose is correct (RUNBOOK.md §"Submitting claims (canonical — SP37)", the SP38 `ack-orphans` section, the SP41 §3.1 FR-RB-* block in REQUIREMENTS.md, the live-tail wire format table in CLAUDE.md), the doc-pass does not touch them. The pass targets the lines where the prose is provably inconsistent with `git log` + `list_dir` + the actual `backend/src/cyclone/` inventory.
4. **SP23 is shipped everywhere.** Every "SP23 awaiting user decision" / "SP23 product fork" / "SP23 candidate" line in the docs gets rewritten as past tense. This is the single biggest correctness win and the highest-blast-radius fix.
5. **Migration count goes from 12 to 23, every time it appears.** Three docs (CLAUDE.md, ARCHITECTURE.md, REQUIREMENTS.md) all say "12" — they all become "23."
6. **Router count goes from 4 to 22, every time it appears.** `cyclone-api-router/SKILL.md` says "4 router modules"; ARCHITECTURE.md §2 says "4 routers"; REQUIREMENTS.md R-12 says "4 sub-routes". All three become "22."
7. **Store split is present-tense everywhere.** The "SP21 in flight" / "SP21 split is in progress" / "SP21 split is in-flight on `refactor/store-split`" framing in CLAUDE.md, ARCHITECTURE.md, REQUIREMENTS.md, and `cyclone-store/SKILL.md` all become past tense with the merge commit (`4360ef7`) cited as evidence.
8. **CLI subcommand list gets the canonical 15+ enumeration in `cyclone-cli/SKILL.md`.** The "Seven subcommands" line is replaced with the full list from `cyclone/cli.py` (verified against `git log``users`, `submit-batch`, `reissue-claims`, `resubmit-rejected-claims`, `resubmissions`, `validate-837`, `recover-ingest`, `ack-orphans`, `seed`, `backfill-rendering-npi`, `backfill-999-rejections`, `pull-inbound`, `rebill-from-835`, plus the existing `parse-837`, `parse-835`, `validate-npi`, `validate-tax-id`, and the `backup` group).
9. **SP25 reuse is acknowledged in `cyclone-spec/SKILL.md`.** The "Three SP25s (sftp-polling-enablement, ack-live-tail, orphan-data-recovery)" anomaly gets a one-line note in the skill's SP-N overview so future agents don't conflate the three SP25s with one another.
10. **No new skill files.** The exploration found that the SP23 auth work arguably warrants a `cyclone-auth` skill, but adding one is outside the doc-pass scope. It's flagged as a follow-up increment.
## 3. Threat model
The doc-pass changes no code paths and no auth gates. The threat model is unchanged from SP41 (the last shipped SP): the auth boundary is HTTP (login required, bcrypt + HttpOnly session cookie); the file-system threat is local-only and handled by SQLCipher at rest and the macOS Keychain. The doc-pass does not weaken any posture; the README.md "binds to 0.0.0.0, requires login" claim actually tightens the operator's mental model by removing the false "no auth, no internet exposure" framing that was inherited from the pre-SP23 posture.
The doc-pass is itself shipped via the same SP-N merge flow (single atomic merge, no squash, no rebase). The merge commit is the audit trail — `merge: SP42 doc-pass into main`.
## 4. Test impact
Per the cyclone-tests skill convention:
- **No new tests.** SP42 is docs-only; nothing in the codebase is exercised differently.
- **Existing tests:** the full pytest suite (`cd backend && .venv/bin/pytest -q`) plus the full vitest suite (`npm test`) must continue to pass — the doc-pass is a non-regression increment.
- **CI posture:** unchanged (R-26 "no CI workflow" is left Open).
- **Fixtures:** none added.
- **Frontend tests:** none added.
## 5. Spec & plan anchors
- **Spec anchor (this file):** `docs/superpowers/specs/2026-07-08-cyclone-doc-pass-design.md`
- **Plan anchor:** `docs/superpowers/plans/2026-07-08-cyclone-doc-pass.md`
- **Source-of-truth inputs:**
- `git log --all --oneline --grep='merge: SP' | sed 's/.*merge: //' | awk '{print $1}' | sort -V | uniq` — proves the SPs that have actually merged (5, 9-21, 23-41)
- `ls docs/superpowers/specs/ | wc -l` → 42; `ls docs/superpowers/plans/ | wc -l` → 37
- `find backend/src/cyclone/migrations -name '*.sql' | wc -l` → 23
- `ls backend/src/cyclone/api_routers/*.py | wc -l` → 21 routers + `_shared.py` + `__init__.py`
- `ls backend/src/cyclone/store/*.py | wc -l` → 17 modules
- `find backend/src/cyclone -maxdepth 1 -type d` — proves the subpackage list
- `backend/src/cyclone/__main__.py:48` — proves `host=os.environ.get("CYCLONE_HOST", "0.0.0.0")`
## 6. Acceptance criteria
1. `grep -rE 'SP22.*SP24|next free increment is SP24|next increment is SP24|next free is SP24|next is SP25' CLAUDE.md README.md docs/ARCHITECTURE.md docs/REQUIREMENTS.md docs/RUNBOOK.md .superpowers/skills/ 2>/dev/null` returns zero matches.
2. `grep -rE 'awaiting user decision|SP23.*candidate|SP23.*product fork' docs/ARCHITECTURE.md docs/REQUIREMENTS.md 2>/dev/null` returns zero matches (in the SP23 context).
3. `grep -rE 'api\.py.*3,548|3,548 LOC|store\.py.*2,423|2,423 LOC|2,172 LOC|3,145 LOC' CLAUDE.md README.md docs/ARCHITECTURE.md docs/REQUIREMENTS.md .superpowers/skills/ 2>/dev/null` returns zero matches.
4. `grep -rE '127\.0\.0\.1' CLAUDE.md README.md docs/ARCHITECTURE.md docs/REQUIREMENTS.md 2>/dev/null` returns zero matches in the bind-address context.
5. `grep -rE 'no auth, no internet exposure' README.md` returns zero matches.
6. `grep -rE '4 router modules|four router modules' .superpowers/skills/cyclone-api-router/SKILL.md docs/ARCHITECTURE.md docs/REQUIREMENTS.md 2>/dev/null` returns zero matches.
7. `grep -rE 'Seven subcommands|7 subcommands' .superpowers/skills/cyclone-cli/SKILL.md` returns zero matches.
8. `grep -rE 'single 2412-line module|SP21.*in.progress|SP21.*in-flight' .superpowers/skills/cyclone-store/SKILL.md` returns zero matches.
9. `grep -rE '12 SQL migrations' CLAUDE.md docs/ARCHITECTURE.md docs/REQUIREMENTS.md 2>/dev/null` returns zero matches.
10. `cd backend && .venv/bin/pytest -q` exits 0; no regressions.
11. `npm test` exits 0; no regressions.
12. `git log --oneline sp42-doc-pass` shows one `docs(spec):` + one `docs(plan):` commit plus ~13 `docs(sp42):` commits (one per file touched).
13. After the merge to `main`, `git log --oneline main -1` shows the SP42 merge commit with subject `merge: SP42 doc-pass into main`.
14. The single-file diff for `CLAUDE.md`, `README.md`, `ARCHITECTURE.md`, `REQUIREMENTS.md`, `RUNBOOK.md`, and each of the 8 skill files shows the stale lines updated and no semantic rewrites of unrelated prose.