From 90a2055c20ee85cd82a0b9cc57a531050d4f237a Mon Sep 17 00:00:00 2001 From: Nora Date: Wed, 8 Jul 2026 23:01:55 -0600 Subject: [PATCH] docs(spec): SP42 doc-pass design --- .../2026-07-08-cyclone-doc-pass-design.md | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 docs/superpowers/specs/2026-07-08-cyclone-doc-pass-design.md diff --git a/docs/superpowers/specs/2026-07-08-cyclone-doc-pass-design.md b/docs/superpowers/specs/2026-07-08-cyclone-doc-pass-design.md new file mode 100644 index 0000000..a5bc6bd --- /dev/null +++ b/docs/superpowers/specs/2026-07-08-cyclone-doc-pass-design.md @@ -0,0 +1,117 @@ +# Sub-project 42 — Doc-Pass: Reconcile Stale Docs with SP23–SP41 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 SP23–SP41 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): …`.** 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. \ No newline at end of file