From 039cfeddfd3cb2b8307f7fe674343fb6bb53e5e7 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Mon, 28 Sep 2026 01:46:23 +0200 Subject: [PATCH] docs(10.2): create phase plan --- .planning/ROADMAP.md | 26 ++ .planning/STATE.md | 19 +- .../10.2-01-PLAN.md | 249 ++++++++++++++++++ .../10.2-02-PLAN.md | 225 ++++++++++++++++ .../COVERAGE.md | 1 + 5 files changed, 511 insertions(+), 9 deletions(-) create mode 100644 .planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-01-PLAN.md create mode 100644 .planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-02-PLAN.md create mode 100644 .planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/COVERAGE.md diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 8b1860b..944a688 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -444,6 +444,32 @@ Plans: **Wave 5** *(blocked on Wave 4 completion)* - [x] 10-05-PLAN.md — Unit tests last: Vitest and Go coverage, assembled acceptance, check-phase10.sh gate and security evidence +### Phase 10.2: Nest framework packages under modules and write run docs (INSERTED) + +**Goal:** The 18 beach-named framework packages live under `modules//` with the same names and a single root `go.mod`; importers in summercms.go, examples, and fonoteka.go use `git.golem15.com/golem15/summercms/modules/`; each module has a short README; the root README is honest run/onboarding docs. +**Requirements**: TBD +**Depends on:** Phase 10 +**Repos:** summercms.go, fonoteka.go +**Plans:** 2 plans + +Plans: + +**Wave 1** +- [ ] 10.2-01-PLAN.md — Nest the 18 beach packages under modules/ and rewrite every importer + +**Wave 2** *(blocked on Wave 1 completion)* +- [ ] 10.2-02-PLAN.md — Per-module READMEs, root run docs, and the hygiene/unit-test gate + +### Phase 10.1: Runtime admin extension point (INSERTED) + +**Goal:** [Urgent work - to be planned] +**Requirements**: TBD +**Depends on:** Phase 10 +**Plans:** 0 plans + +Plans: +- [ ] TBD (run $gsd-plan-phase 10.1 to break down) + ### Phase 11: Jobs, realtime and search infrastructure **Goal**: River jobs run on the correct dual-driver split, Centrifugo publishing and channel authorization match the existing server, and Typesense sync stays a re-gated pre-filter — all brought up before the API phases that depend on them (album search needs Typesense sync, CSV import needs River jobs, notifications need the realtime publisher). River's dual-driver split and the Centrifugo/Typesense contracts are the least-implemented-and-verified parts of this research pass. diff --git a/.planning/STATE.md b/.planning/STATE.md index da84e52..a5a84e2 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -1,18 +1,18 @@ --- gsd_state_version: "1.0" milestone: v1.0 -current_phase: 9 -current_phase_name: Backend admin authentication and schema pipeline -status: planning +current_phase: "10.2" +current_phase_name: Nest framework packages under modules and write run docs +status: executing stopped_at: Phase 12 context gathered -last_updated: "2026-09-27T23:28:26.002Z" +last_updated: "2026-09-27T23:45:59.574Z" last_activity: 2026-09-27 last_activity_desc: Phase 10 complete, transitioned to Phase 9 -state_head: 4f2358e26c99b0e4a0b94dcc12e3a5453a59e4cb +state_head: 195bf2ce757d1802f2ae5d0e3052b3e43815822d progress: - total_phases: 16 + total_phases: 17 completed_phases: 9 - total_plans: 72 + total_plans: 74 completed_plans: 72 milestone_name: milestone --- @@ -28,9 +28,9 @@ See: .planning/PROJECT.md (updated 2026-09-16) ## Current Position -Phase: 9 — Backend admin authentication and schema pipeline +Phase: 10.2 (Nest framework packages under modules and write run docs) — READY TO EXECUTE Plan: Not started -Status: planning +Status: Ready to execute Last activity: 2026-09-27 — Phase 10 complete, transitioned to Phase 9 Progress: [██████░░░░] 60% @@ -133,6 +133,7 @@ Progress: [██████░░░░] 60% - Phase 2 edited: edited fields: depends_on (Phase 1), goal (summer parity:* on bonfire, no longer a parallel workstream) - Phase 10.1 inserted after Phase 10: Runtime admin extension point (URGENT) +- Phase 10.2 inserted after Phase 10: Nest framework packages under modules and write run docs (URGENT) ### Decisions diff --git a/.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-01-PLAN.md b/.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-01-PLAN.md new file mode 100644 index 0000000..8a42789 --- /dev/null +++ b/.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-01-PLAN.md @@ -0,0 +1,249 @@ +--- +phase: 10.2-nest-framework-packages-under-modules-and-write-run-docs +plan: "01" +type: execute +wave: 1 +depends_on: [] +files_modified: + - modules/** + - cmd/summer/** + - internal/build/build.go + - internal/build/build_test.go + - internal/build/stubs/artifacts.tmpl + - internal/build/stubs/registry.tmpl + - internal/build/stubs/plugin.tmpl + - internal/dev/** + - examples/hello/** + - admin/vite.config.ts + - scripts/check-phase2.sh + - scripts/check-phase3.sh + - scripts/check-phase4.sh + - scripts/check-phase9.sh + - scripts/check-phase10.sh + - scripts/check-admin-dist.sh + - scripts/check-admin-openapi.sh + - ../fonoteka.go/main.go + - ../fonoteka.go/app/** + - ../fonoteka.go/parity/** + - ../fonoteka.go/plugins/** +autonomous: true +requirements: [] +estimate: + tokens: 140000 + raw_tokens: 70000 + tasks: 3 + confidence: low +must_haves: + truths: + - "D-01/D-02: The 18 beach packages live only under modules// with the same package names; none of those 18 names is a directory at the summercms.go repo root." + - "D-03: admin/, cmd/, examples/, internal/, scripts/, go.mod and README.md stay at repo root; there is still exactly one go.mod (not one Go module per beach package); go.work still uses . and ./examples/hello* only." + - "D-04/D-05: Every remaining importer in summercms.go, examples/, and ../fonoteka.go (including plugin modules) uses git.golem15.com/golem15/summercms/modules/; replace directives still point at the summercms.go tree." + - "D-06: Beach names are unchanged; packages are not remapped onto Winter system/backend/cms names." + - "D-05: go vet ./... and go test ./... are green in summercms.go, and the same pair plus plugin modules is green in ../fonoteka.go." + artifacts: + - path: modules/festival/ + provides: tracer nest of one beach package proving git mv + importer rewrite + go test + - path: modules/ + provides: all 18 beach packages after expansion (backpack boardwalk bonfire bouncer cabana compass festival fetchguard lagoon pact party phrasebook postcard surf tide towel wire wristband) + - path: scripts/check-admin-openapi.sh + provides: swag --dir modules/cabana + - path: scripts/check-admin-dist.sh + provides: drift compare against modules/boardwalk/dist + - path: admin/vite.config.ts + provides: Vite outDir ../modules/boardwalk/dist + - path: internal/build/stubs/plugin.tmpl + provides: generated plugin imports under the modules/ prefix + key_links: + - from: backpack/app.go + to: modules/festival + via: tracer importer rewritten to git.golem15.com/golem15/summercms/modules/festival before the remaining 17 move + pattern: modules/festival + - from: scripts/check-admin-openapi.sh + to: modules/cabana + via: --dir modules/cabana --generalInfo admin_openapi.go + pattern: "--dir modules/cabana" + - from: scripts/check-admin-dist.sh + to: modules/boardwalk/dist + via: diff against the embedded SPA tree after boardwalk moves + pattern: modules/boardwalk/dist + - from: admin/vite.config.ts + to: modules/boardwalk/dist + via: build.outDir after the nest + pattern: "../modules/boardwalk/dist" + - from: ../fonoteka.go/go.mod + to: ../summercms.go + via: replace git.golem15.com/golem15/summercms stays; only import paths change + pattern: "replace git.golem15.com/golem15/summercms" + prohibitions: + - "Do not rename packages or remap them onto Winter system/backend/cms (D-01, D-06)." + - "Do not add a go.mod under any modules// and do not add modules as go.work use entries (D-03)." + - "Do not rewrite historical .planning/phases/** path literals." + - "Do not change fonoteka.go replace paths that point at the summercms.go tree." + - "Do not leave any of the 18 beach names as a directory at the summercms.go repo root." + - "Do not add Go or npm dependencies." +--- + +## Phase Goal + +Nest the 18 beach-named framework libraries under `modules/` with rewritten import paths in both repos, then leave a green `go test` so Phase 11 does not add more packages at the repo root. + + +Prove the nest on one package, then move the remaining 17 and rewrite every importer plus the path-literal scripts so both repositories compile and test green. + +Purpose: D-01 through D-06. Root `ls` must show `modules/`, `cmd/`, `admin/`, `examples/`, `internal/`, `scripts/` instead of eighteen beach directories beside `go.mod`, and this must land before Phase 11. + +Output: `modules//` for all 18 packages, import prefix `git.golem15.com/golem15/summercms/modules/`, retargeted phase/admin scripts, updated `internal/build` stubs, green `go vet`/`go test` in summercms.go and ../fonoteka.go. + +Repos: summercms.go and ../fonoteka.go. Planning docs stay in summercms.go. Commit each repo separately; planning docs and code in separate commits; never add co-author tags. + + + +@~/.claude/gsd-core/workflows/execute-plan.md +@~/.claude/gsd-core/templates/summary.md + + + +@CLAUDE.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/todos/pending/nest-framework-packages-under-modules.md +@.planning/todos/pending/per-module-readmes-after-nest.md +@.planning/todos/pending/rewrite-summercms-readme.md +@README.md +@scripts/check-phase10.sh +@scripts/check-admin-dist.sh +@scripts/check-admin-openapi.sh +@internal/build/build.go +@internal/build/stubs/plugin.tmpl +@admin/vite.config.ts +@../fonoteka.go/go.mod + + +Single Go module at repo-root go.mod (D-03). After a git mv, the import path is the module path plus the new directory. Package clause names stay the beach names (D-01). fonoteka.go replace directives already point at the summercms.go tree and must keep that path. examples/hello/go.mod replace `git.golem15.com/golem15/summercms => ../..` stays valid. go.work uses `.` and `./examples/hello*` only. boardwalk embed is `all:dist` relative to the boardwalk package, so the committed dist tree moves with the package to modules/boardwalk/dist. + + + +## Artifacts this phase produces + +- Directory `modules/` holding the 18 beach packages (same `package` names) +- Import path prefix `git.golem15.com/golem15/summercms/modules/` +- Tracer package `modules/festival` (discretion: festival, not compass — see Task 1) +- Retargeted literals: `scripts/check-admin-openapi.sh --dir modules/cabana`; `scripts/check-admin-dist.sh` and `admin/vite.config.ts` → `modules/boardwalk/dist`; `scripts/check-phase2.sh` and `scripts/check-phase3.sh` → `modules/tide/testdata/one-route-spec.yaml`; `scripts/check-phase4.sh` → `./modules/phrasebook ./modules/postcard`; `scripts/check-phase9.sh` → `./modules/bouncer ./modules/cabana ./modules/lagoon` and Package `git.golem15.com/golem15/summercms/modules/lagoon`; `scripts/check-phase10.sh` HYGIENE_DIRS / `./modules/cabana` / `./modules/bouncer` / `./modules/surf` / `./modules/boardwalk` / Package `git.golem15.com/golem15/summercms/modules/cabana` +- Updated `internal/build/build.go` string literals and `internal/build/stubs/*.tmpl` +- Tests that must stay green: `TestEventBusesAreAppScoped`, `TestFireRunsAllListenersAndJoinsErrors`, `TestGetApiArrayEventMerge`, then full `go test ./...` in both repos + + + + + Task 1: Nest festival end to end — git mv, rewrite its importers, test the moved package + Import-path rewrite touches every importer of the moved package; the module is v0.0.0 and unpublished, so this is costly, not one-way, and needs no checkpoint. + modules/festival/**, backpack/app.go, examples/hello/plugins/greeter/plugin.go, ../fonoteka.go/plugins/golem15/user/classes/events_test.go + .planning/todos/pending/nest-framework-packages-under-modules.md; festival/bus.go; festival/bus_test.go; backpack/app.go; backpack/app_test.go; examples/hello/plugins/greeter/plugin.go; ../fonoteka.go/plugins/golem15/user/classes/events_test.go; go.mod; examples/hello/go.mod; ../fonoteka.go/go.mod + Discretion: do not use compass as the tracer. Grep on 2026-09-28 showed compass imported from about 32 files in this repo plus about 10 in ../fonoteka.go. festival has exactly three importers and no framework imports of its own, so it is the thinnest end-to-end slice (D-01, D-02, D-04). + +Re-verify dependents before the move: search both repos and examples/ for importers of package festival. Expected three files only: backpack/app.go, examples/hello/plugins/greeter/plugin.go, ../fonoteka.go/plugins/golem15/user/classes/events_test.go. If grep finds more, rewrite those too; do not stop at the expected three. + +Create modules/ if needed. git mv the festival directory to modules/festival/. Do not rename the Go package clause (D-01). Do not add a go.mod under modules/festival (D-03). + +Rewrite only festival importers to git.golem15.com/golem15/summercms/modules/festival (D-04). Leave every other beach import on the root-form path. Do not touch ../fonoteka.go replace directives. Do not rewrite .planning/ docs. + +Do not expand to the other 17 packages in this task. + + test -d modules/festival && test ! -d festival && go test ./modules/festival -count=1 && go test ./backpack -run '^TestEventBusesAreAppScoped$' -count=1 && (cd ../fonoteka.go && go test ./plugins/golem15/user -run '^TestGetApiArrayEventMerge$' -count=1) + non-zero exit; festival still exists at repo root; modules/festival missing; any go test line shows FAIL, "no tests to run", or lacks "--- PASS: TestFireRunsAllListenersAndJoinsErrors" / "--- PASS: TestEventBusesAreAppScoped" / "--- PASS: TestGetApiArrayEventMerge" + + + - `test -d modules/festival && test ! -d festival` succeeds. + - `go test ./modules/festival -count=1` prints PASS including TestFireRunsAllListenersAndJoinsErrors. + - `grep -F 'git.golem15.com/golem15/summercms/modules/festival' backpack/app.go examples/hello/plugins/greeter/plugin.go ../fonoteka.go/plugins/golem15/user/classes/events_test.go` prints a hit in each of those three files. + - A search of tracked `*.go` for a festival import that is not under `/modules/` prints no production importer (the three files above use the modules/ form). + + festival lives at modules/festival, its three importers compile against the new path, and the moved package plus one importer in each repo pass named tests. + + + + Task 2: Nest the remaining 17 packages and rewrite every leftover importer and path literal + The remaining import-path rewrite touches ~220 files across both repos; costly, not one-way, no checkpoint. + modules/**, cmd/summer/**, internal/build/build.go, internal/build/build_test.go, internal/build/stubs/artifacts.tmpl, internal/build/stubs/registry.tmpl, internal/build/stubs/plugin.tmpl, internal/dev/**, examples/hello/**, admin/vite.config.ts, scripts/check-phase2.sh, scripts/check-phase3.sh, scripts/check-phase4.sh, scripts/check-phase9.sh, scripts/check-phase10.sh, scripts/check-admin-dist.sh, scripts/check-admin-openapi.sh, ../fonoteka.go/main.go, ../fonoteka.go/app/**, ../fonoteka.go/parity/**, ../fonoteka.go/plugins/** + .planning/todos/pending/nest-framework-packages-under-modules.md; internal/build/build.go; internal/build/stubs/plugin.tmpl; internal/build/stubs/registry.tmpl; internal/build/stubs/artifacts.tmpl; cmd/summer/main.go; cmd/summer/runtime.go; cmd/summer/parity.go; admin/vite.config.ts; scripts/check-admin-openapi.sh; scripts/check-admin-dist.sh; scripts/check-phase10.sh; scripts/check-phase9.sh; scripts/check-phase4.sh; scripts/check-phase3.sh; scripts/check-phase2.sh; examples/hello/go.mod; ../fonoteka.go/go.mod; ../fonoteka.go/plugins/golem15/fonoteka/go.mod; ../fonoteka.go/plugins/golem15/user/go.mod + Per D-02, git mv each remaining root beach directory into modules/<name>/: backpack, boardwalk (including dist), bonfire, bouncer, cabana, compass, fetchguard, lagoon, pact, party, phrasebook, postcard, surf, tide, towel, wire, wristband. Keep package clause names (D-01). Single root go.mod only (D-03). Do not add modules as go.work use entries. + +Per D-04/D-05, rewrite every remaining importer in this repo (~100 files), examples/, and ../fonoteka.go (~124 files, including plugins/golem15/fonoteka and plugins/golem15/user) so the import is git.golem15.com/golem15/summercms/modules/<name>. Cover cmd/summer/*, internal/build/build.go string literals, internal/build/build_test.go, internal/build/stubs/plugin.tmpl, registry.tmpl and artifacts.tmpl, and internal/dev/* if they name a beach import. Leave replace directives pointing at the summercms.go tree. Do not rewrite historical .planning/phases/** files. + +Retarget path literals so later gates do not go red or pass vacuously on missing directories (D-05): +- scripts/check-admin-openapi.sh: --dir modules/cabana (keep --generalInfo admin_openapi.go) +- scripts/check-admin-dist.sh: compare and message against modules/boardwalk/dist +- admin/vite.config.ts: build.outDir '../modules/boardwalk/dist' +- scripts/check-phase2.sh and scripts/check-phase3.sh: --spec modules/tide/testdata/one-route-spec.yaml +- scripts/check-phase4.sh: go test -race paths ./modules/phrasebook ./modules/postcard +- scripts/check-phase9.sh: ./modules/bouncer ./modules/cabana ./modules/lagoon and the self-test Package string git.golem15.com/golem15/summercms/modules/lagoon +- scripts/check-phase10.sh: HYGIENE_DIRS boardwalk/cabana/phrasebook become modules/boardwalk modules/cabana modules/phrasebook; phase10_tests/phase10_go package dirs ./modules/cabana ./modules/bouncer ./modules/surf ./modules/boardwalk; hygiene greps of boardwalk/dist become modules/boardwalk/dist; self-test Package string git.golem15.com/golem15/summercms/modules/cabana + +Do not remap names onto Winter system/backend/cms (D-06). Do not rebuild admin dist (files move with boardwalk). Do not add dependencies. + + test -d modules/cabana && test ! -d cabana && test -d modules/boardwalk/dist && grep -F -- '--dir modules/cabana' scripts/check-admin-openapi.sh && grep -F 'modules/boardwalk/dist' scripts/check-admin-dist.sh admin/vite.config.ts && grep -F 'modules/tide/testdata/one-route-spec.yaml' scripts/check-phase2.sh scripts/check-phase3.sh && grep -F './modules/phrasebook' scripts/check-phase4.sh && grep -F './modules/lagoon' scripts/check-phase9.sh && grep -F './modules/cabana' scripts/check-phase10.sh && grep -F '../modules/boardwalk/dist' admin/vite.config.ts + non-zero exit; any of the 18 beach names still a directory at repo root; any listed grep prints no matching line + + + - `ls` at repo root lists modules/, cmd/, admin/, examples/, internal/, scripts/ and does not list any of the 18 beach names as directories. + - `git ls-files -- '*.go' '*.tmpl' '*.sh'` filtered to this repo plus ../fonoteka.go, excluding `.planning/`, contains no import of `git.golem15.com/golem15/summercms/<beach>` that lacks `/modules/`. + - `test -f go.mod && test ! -f modules/cabana/go.mod && test ! -f modules/festival/go.mod` succeeds. + - `grep -n 'use (' -A20 go.work` still lists only `.` and `./examples/hello*` entries. + - `grep -F 'replace git.golem15.com/golem15/summercms => ../summercms.go' ../fonoteka.go/go.mod` prints 1. + + All 18 packages live under modules/, every importer and listed script/stub/vite outDir uses the nested path, and root ls no longer shows beach directories. + + + + Task 3: go vet and go test both repositories including fonoteka plugin modules + modules/**, ../fonoteka.go/plugins/** + .planning/todos/pending/nest-framework-packages-under-modules.md; go.mod; ../fonoteka.go/go.mod; ../fonoteka.go/plugins/golem15/fonoteka/go.mod; ../fonoteka.go/plugins/golem15/user/go.mod + Per D-05, from summercms.go run go vet ./... and go test ./.... From ../fonoteka.go run go vet ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/... and go test ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/... (same plugin-module set scripts/check-phase10.sh already uses). Do not treat a skipped PostgreSQL test as a pass for a required package that should run. Do not add dependencies. If either repo fails on an old import or a stale script path, fix the leftover from Task 2 and re-run; do not weaken tests. + + go vet ./... && go test ./... && (cd ../fonoteka.go && go vet ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/... && go test ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/...) + non-zero exit; any package FAIL; output contains "build failed" or "no required module provides package" for a beach import + + + - Both repository commands exit 0. + - `test ! -d compass && test -d modules/compass` succeeds (spot-check a non-tracer package). + - A `git grep` of tracked `*.go` `*.tmpl` `*.sh` in both repos (exclude `.planning/`) for `git.golem15.com/golem15/summercms/` followed immediately by a beach name with no `modules/` segment prints nothing. + + Both repos vet and test green on the nested import paths, including fonoteka plugin modules. + + + + + +## Trust Boundaries + +| Boundary | Description | +|----------|-------------| +| Importer → framework package path | A leftover root-form import fails the build or, worse, could compile against a shadow copy if a beach dir were left at root | +| Phase/admin scripts → on-disk package dirs | Greps over missing old directories return empty and can pass vacuously; testdata and swag --dir miss after the move | +| App repo replace → framework tree | replace stays; only import paths change. A mistaken replace rewrite would pull the wrong tree | + +## STRIDE Threat Register + +| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan | +|-----------|----------|-----------|----------|-------------|-----------------| +| T-10.2-01 | Tampering | repo-root beach directories | high | mitigate | git mv only; Task 3 and later 10.2-02 gate refuse if any of the 18 names is still a directory at root | +| T-10.2-02 | Tampering | import paths in *.go/*.tmpl | high | mitigate | Rewrite every importer to the modules/ prefix; go test ./... in both repos fails closed on a missing package | +| T-10.2-03 | Tampering | scripts/check-phase*.sh, check-admin-*.sh, admin/vite.config.ts | high | mitigate | Retarget every listed path literal so hygiene greps scan modules/ and cannot pass on a missing old dir | +| T-10.2-04 | Tampering | modules/*/go.mod or go.work | medium | mitigate | Keep the single root go.mod (D-03); Task 2 acceptance asserts no per-package go.mod and unchanged go.work use list | +| T-10.2-05 | Tampering | package names | medium | mitigate | Keep beach package clauses (D-01/D-06); do not remap onto Winter system/backend/cms | +| T-10.2-SC | Tampering | npm/pip/cargo installs | high | mitigate | No new dependencies this plan; do not run npm install; T-10.2-SC stays reserved | + + + +After Task 1, the festival slice is green. After Task 2, root ls has no beach dirs and the listed scripts contain the nested path literals. After Task 3, `go vet ./... && go test ./...` in summercms.go and the matching pair plus plugin modules in ../fonoteka.go exit 0. + + + +- `ls` at summercms.go root shows modules/, cmd/, admin/, examples/, internal/, scripts/ and none of the 18 beach directories. +- No tracked .go/.tmpl/.sh importer still uses the root-form beach import. +- Both repos test green. Scripts that later gates run now point at modules/. + + + +Create `.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-01-SUMMARY.md` when done. + diff --git a/.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-02-PLAN.md b/.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-02-PLAN.md new file mode 100644 index 0000000..f749d6b --- /dev/null +++ b/.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-02-PLAN.md @@ -0,0 +1,225 @@ +--- +phase: 10.2-nest-framework-packages-under-modules-and-write-run-docs +plan: "02" +type: execute +wave: 2 +depends_on: ["10.2-01"] +files_modified: + - modules/backpack/README.md + - modules/boardwalk/README.md + - modules/bonfire/README.md + - modules/bouncer/README.md + - modules/cabana/README.md + - modules/compass/README.md + - modules/festival/README.md + - modules/fetchguard/README.md + - modules/lagoon/README.md + - modules/pact/README.md + - modules/party/README.md + - modules/phrasebook/README.md + - modules/postcard/README.md + - modules/surf/README.md + - modules/tide/README.md + - modules/towel/README.md + - modules/wire/README.md + - modules/wristband/README.md + - README.md + - scripts/check-phase10.2.sh +autonomous: true +requirements: [] +estimate: + tokens: 80000 + raw_tokens: 40000 + tasks: 3 + confidence: low +must_haves: + truths: + - "D-07: Each modules// has a short README.md of one paragraph stating what the package is, who imports it, and one example entry point (Package.Type or file). No architecture essays and no pasted planning-doc prose." + - "D-08: Root README.md states this repo is framework only (app is sibling fonoteka.go), explains the two-repo go.work replace during development, tells an operator how to recreate the Phase 10 admin login by pointing at fonoteka.go for DSN/migrate/serve, includes an honest not-yet cutover drawn from .planning/notes/go-vs-php-on-plytarium.md (Phase 15 PHP flip), and links modules//README.md instead of listing beach names at root." + - "The fail-closed 10.2 gate refuses leftover root beach directories, leftover root-form beach imports in tracked .go/.tmpl/.sh, a missing module README, and a root README that still claims nothing runs." + - "D-05 remains true after the docs work: go vet ./... and go test ./... stay green in both repos including fonoteka plugin modules." + artifacts: + - path: modules/backpack/README.md + provides: one-paragraph backpack onboarding + - path: modules/cabana/README.md + provides: one-paragraph cabana onboarding + - path: README.md + provides: framework onboarding, two-repo layout, admin-login recreate, honest cutover + - path: scripts/check-phase10.2.sh + provides: fail-closed layout/import/README/vet-test gate with --self-test + key_links: + - from: README.md + to: modules/*/README.md + via: root README points at per-module files instead of an inline beach-name list + pattern: modules/ + - from: README.md + to: ../fonoteka.go/README.md + via: DSN, migrate, and serve live in the app repo + pattern: fonoteka.go + - from: scripts/check-phase10.2.sh + to: README.md + via: refuse if the stale pre-alpha Status sentence is still present + pattern: "--self-test" + prohibitions: + - "Do not invent a production deploy runbook; operator procedure stays in the PHP docs/deploy/plytarium.com.md until Phase 15 (D-08)." + - "Do not paste .planning/ notes, ROADMAP, or CONTEXT into module READMEs (D-07)." + - "Do not rewrite fonoteka.go/README.md in this plan (intended split: that file stays a short run card)." + - "Do not add Go or npm dependencies." + - "Do not remap beach names onto Winter system/backend/cms." +--- + +## Phase Goal + +Write run docs for the nested modules and a fail-closed hygiene gate so a newcomer can onboard from the root README and the layout cannot silently regress. + + +After 10.2-01 is green, write eighteen short module READMEs from the code (D-07), replace the root README (D-08), and ship scripts/check-phase10.2.sh plus both-repo vet/test as the last-plan unit/hygiene gate. + +Purpose: The current root README still claims nothing runs. That is false after Phase 10. Module READMEs and an honest cutover section are the onboarding surface; the gate is Dimension 8 evidence (no VALIDATION.md this run). + +Output: modules/<name>/README.md × 18, rewritten README.md, scripts/check-phase10.2.sh. + +Repo: summercms.go only for the doc files; the gate also runs ../fonoteka.go tests. Commit docs separately from any leftover code fix; never add co-author tags. + + + +@~/.claude/gsd-core/workflows/execute-plan.md +@~/.claude/gsd-core/templates/summary.md + + + +@CLAUDE.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-01-SUMMARY.md +@.planning/todos/pending/per-module-readmes-after-nest.md +@.planning/todos/pending/rewrite-summercms-readme.md +@.planning/todos/pending/nest-framework-packages-under-modules.md +@.planning/notes/go-vs-php-on-plytarium.md +@README.md +@../fonoteka.go/README.md +@scripts/check-phase4.sh +@scripts/check-phase9.sh + + +10.2-01 left packages at modules/<name>/ with import prefix git.golem15.com/golem15/summercms/modules/<name>. Root stay-put dirs are admin/, cmd/, examples/, internal/, scripts/. App binary, DSN, migrate and serve commands live in ../fonoteka.go (see that README: SUMMER_DATABASE__DSN, summer build, ./bin/fonoteka migrate, ./bin/fonoteka serve, pl-PL Postgres). Phase 10 admin URL for fonoteka is backend.uri /plytadmin. Cutover facts come only from .planning/notes/go-vs-php-on-plytarium.md. + + + +## Artifacts this phase produces + +- `modules//README.md` for backpack, boardwalk, bonfire, bouncer, cabana, compass, festival, fetchguard, lagoon, pact, party, phrasebook, postcard, surf, tide, towel, wire, wristband +- Rewritten root `README.md` (framework-only, two-repo replace, admin-login recreate, Phase 15 not-yet cutover, links to module READMEs) +- `scripts/check-phase10.2.sh` with `--self-test` and `--all` +- Gate checks (not new Go test names): leftover root beach dir; leftover root-form beach import; missing module README; stale root Status sentence; `go vet`/`go test` both repos + + + + + Task 1: Write one short README.md per modules/<name> from the code + modules/backpack/README.md, modules/boardwalk/README.md, modules/bonfire/README.md, modules/bouncer/README.md, modules/cabana/README.md, modules/compass/README.md, modules/festival/README.md, modules/fetchguard/README.md, modules/lagoon/README.md, modules/pact/README.md, modules/party/README.md, modules/phrasebook/README.md, modules/postcard/README.md, modules/surf/README.md, modules/tide/README.md, modules/towel/README.md, modules/wire/README.md, modules/wristband/README.md + .planning/todos/pending/per-module-readmes-after-nest.md; .planning/todos/pending/nest-framework-packages-under-modules.md; modules/backpack/app.go; modules/boardwalk/boardwalk.go; modules/bonfire/; modules/bouncer/; modules/cabana/; modules/compass/config.go; modules/festival/bus.go; modules/fetchguard/; modules/lagoon/; modules/pact/; modules/party/; modules/phrasebook/; modules/postcard/; modules/surf/; modules/tide/; modules/towel/; modules/wire/response.go; modules/wristband/; README.md + Per D-07, after the nest is green, do an explore-quality pass over the code in each modules/<name>/ (exported types and the primary .go file, plus a quick git grep of who imports git.golem15.com/golem15/summercms/modules/<name>). Write modules/<name>/README.md for all 18 names listed in files. + +Each file is one paragraph: what the package is for, who imports it (framework peers and/or ../fonoteka.go plugins), and one example entry point such as festival.Bus, compass.Config, cabana.Activate, boardwalk.Handler, surf.BuildRouter, or the owning .go file. No architecture essays. Do not copy .planning/ notes, ROADMAP, or phase plans into these files. Do not invent APIs that are not in the tree. Do not add a per-package go.mod. + + test -f modules/festival/README.md && test -f modules/cabana/README.md && test -f modules/compass/README.md && wc -l modules/*/README.md | awk 'BEGIN{bad=0} $2!="total" && ($1<2 || $1>40){bad=1; print} END{exit bad}' + non-zero exit; any of the 18 modules/*/README.md missing; a README is under 2 lines or over 40 lines (essay or stub) + + + - `for n in backpack boardwalk bonfire bouncer cabana compass festival fetchguard lagoon pact party phrasebook postcard surf tide towel wire wristband; do test -f modules/$n/README.md || exit 1; done` exits 0. + - Each README names at least one exported identifier or file (grep for a `.` type or a `.go` filename). + - `grep -l 'D-0' modules/*/README.md` prints nothing (no planning-decision paste). + + Eighteen short module READMEs exist, each derived from the code, each naming an entry point. + + + + Task 2: Replace root README.md with framework onboarding, login recreate, and honest cutover + README.md + .planning/todos/pending/rewrite-summercms-readme.md; .planning/notes/go-vs-php-on-plytarium.md; README.md; ../fonoteka.go/README.md; .planning/todos/pending/per-module-readmes-after-nest.md; CLAUDE.md + Per D-08, replace README.md. Required sections, in this order: + +1. What this repo is: SummerCMS Go framework only. The application is the sibling ../fonoteka.go (or fonoteka.go next to this repo). This tree is not the app binary. +2. Two-repo layout: development uses a go.work / replace of git.golem15.com/golem15/summercms onto this checkout (cite ../fonoteka.go/go.mod and examples/hello/go.mod). Single go.mod here (D-03). Framework libraries live under modules/. +3. Recreate the Phase 10 admin login that already worked: point at fonoteka.go for DSN (SUMMER_DATABASE__DSN), pl-PL Postgres, `summer build`, `./bin/fonoteka migrate`, `./bin/fonoteka serve`. Admin SPA is embed.FS in that binary; fonoteka backend.uri is /plytadmin. Do not list a summer serve of this repo as the way to open admin. Do not invent extra flags. +4. Honest cutover: drawn only from .planning/notes/go-vs-php-on-plytarium.md. Working local admin login is not a DNS flip of plytarium.com. Flip is Phase 15 after jobs/search (11) and remaining API routes (12-14). Until then, pointing production at this binary would take the public Nuxt app and MCP offline. Operator procedure stays in the PHP docs/deploy/plytarium.com.md. Do not write a production runbook. +5. Modules: point at modules/<name>/README.md instead of listing beach names as root directories. A short link list to the 18 README files is enough. + +Keep a short Why Go / v1-target pointer if useful (existing .planning/notes/why-go-not-scala.md and v1-target-plytarium.md). Remove the current Status sentence that claims nothing runs. Do not paste planning docs. Do not add secrets or a sample production DSN. + + test -f README.md && grep -q 'fonoteka.go' README.md && grep -q 'modules/' README.md && grep -q 'plytadmin' README.md && grep -q 'Phase 15' README.md && grep -q 'docs/deploy/plytarium.com.md' README.md + non-zero exit; any required grep prints no matching line + + + - README.md contains the strings `fonoteka.go`, `modules/`, `SUMMER_DATABASE__DSN` or a clear pointer to the fonoteka.go Database setup section, `plytadmin`, `Phase 15`, and `docs/deploy/plytarium.com.md`. + - README.md does not contain the current Status sentence from the rewrite-summercms-readme todo (the one that says planning-and-research and that nothing runs). + - README.md does not contain a step-by-step nginx/systemd production deploy procedure. + - README.md links at least one `modules/<name>/README.md` path. + + Root README onboards a developer to the two-repo layout, the already-working admin login via fonoteka.go, and an honest Phase 15 cutover, and it points at module READMEs. + + + + Task 3: Unit and hygiene gate — scripts/check-phase10.2.sh plus both-repo go test + scripts/check-phase10.2.sh + scripts/check-phase4.sh; scripts/check-phase9.sh; scripts/check-phase10.sh; README.md; .planning/todos/pending/nest-framework-packages-under-modules.md; .planning/todos/pending/per-module-readmes-after-nest.md; .planning/todos/pending/rewrite-summercms-readme.md + Add scripts/check-phase10.2.sh (bash, set -euo pipefail, executable bit). Model the detector style on scripts/check-phase9.sh / scripts/check-phase4.sh, not the Phase 10 SPA stages. Modes: --self-test and --all (and optional single-stage flags if that keeps the script readable). + +--all must fail closed when any of these is true: +1. Any of the 18 beach names is a directory at the summercms.go repo root. +2. Any tracked `*.go`, `*.tmpl`, or `*.sh` in this repo or ../fonoteka.go still contains a root-form beach import (`git.golem15.com/golem15/summercms/` + name, with no `/modules/` segment). Build the needle from a NAMES array plus the module prefix so the script file is not itself a hit; skip this script and skip `.planning/`. Do not scan historical PLAN.md files. +3. Any modules/<name>/ for those 18 names lacks README.md. +4. Root README.md still contains the stale Status sentence named in the rewrite-summercms-readme todo. +5. `go vet ./...` or `go test ./...` fails in summercms.go, or `go vet ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/...` or the matching `go test` fails in ../fonoteka.go. + +--self-test: bash -n; in a scratch copy, plant each of (1)-(4) one at a time and refuse unless the script exits non-zero and the stderr names that rule (leftover root dir, old import, missing README, stale Status). Do not run the full both-repo go test inside --self-test. + +Reuse the same go vet / go test commands that already worked in 10.2-01 Task 3. Do not invoke check-phase10.sh SPA, OpenAPI, or dist stages. No new dependencies. + + bash -n scripts/check-phase10.2.sh && scripts/check-phase10.2.sh --self-test && scripts/check-phase10.2.sh --all + non-zero exit; --self-test output lacks a passed line or contains "refuse:" for the clean tree; --all prints "refuse:" or a package FAIL + + + - `test -x scripts/check-phase10.2.sh` succeeds. + - `--self-test` exits 0 on the committed tree and has planted-failure coverage for leftover root dir, old import, missing module README, and stale root Status. + - `--all` exits 0 on the committed tree. + - A one-off `mkdir backpack` at repo root followed by the layout stage (or --all) exits non-zero; remove the dir after. + + The 10.2 gate fails closed on layout, import, README, and stale-status regressions, and both repos stay vet/test green. + + + + + +## Trust Boundaries + +| Boundary | Description | +|----------|-------------| +| Operator → root README | Onboarding text can send someone at production or leak a procedure that is not ours yet | +| Hygiene script → working tree | A gate that greps missing old paths, or that matches its own needle, goes green or red for the wrong reason | +| Module README → public git | Pasted planning notes would publish deferred/internal decisions | + +## STRIDE Threat Register + +| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan | +|-----------|----------|-----------|----------|-------------|-----------------| +| T-10.2-06 | Information Disclosure | README.md cutover / login sections | high | mitigate | Point at fonoteka.go for DSN/migrate/serve; no production runbook; cite PHP docs/deploy/plytarium.com.md; no sample secrets (D-08) | +| T-10.2-07 | Tampering | scripts/check-phase10.2.sh | high | mitigate | Fail closed on leftover root beach dirs, root-form imports, missing module READMEs, and the stale Status sentence; --self-test plants each rule | +| T-10.2-08 | Information Disclosure | modules/*/README.md | low | accept | Explore-quality one-paragraph files; D-07 forbids planning-doc paste; residual risk is a bland public description of exported types | +| T-10.2-09 | Repudiation | --self-test skipped | medium | mitigate | --all is not a substitute for --self-test; Task 3 verify runs both; a self-test that accepts a plant must refuse | +| T-10.2-SC | Tampering | npm/pip/cargo installs | high | mitigate | Docs and a bash gate only; no package-manager installs | + + + +`scripts/check-phase10.2.sh --self-test` then `--all`. --all includes both-repo `go vet`/`go test`. A leftover beach directory at repo root, a root-form beach import, a missing module README, or the stale root Status sentence must exit non-zero. + + + +- Eighteen module READMEs and a rewritten root README satisfy D-07 and D-08. +- scripts/check-phase10.2.sh fails closed on the four hygiene/docs signals and keeps both repos green. + + + +Create `.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-02-SUMMARY.md` when done. + diff --git a/.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/COVERAGE.md b/.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/COVERAGE.md new file mode 100644 index 0000000..d39b242 --- /dev/null +++ b/.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/COVERAGE.md @@ -0,0 +1 @@ +No external API integration: layout move and onboarding docs only.