docs(10.2): create phase plan

This commit is contained in:
Jakub Zych
2026-09-28 01:46:23 +02:00
parent 195bf2ce75
commit 039cfeddfd
5 changed files with 511 additions and 9 deletions

View File

@@ -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/<name>/ 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/<name>; 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/<name>/ 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.
<objective>
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/<name>/` for all 18 packages, import prefix `git.golem15.com/golem15/summercms/modules/<name>`, 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.
</objective>
<execution_context>
@~/.claude/gsd-core/workflows/execute-plan.md
@~/.claude/gsd-core/templates/summary.md
</execution_context>
<context>
@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
<interfaces>
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.
</interfaces>
</context>
## Artifacts this phase produces
- Directory `modules/` holding the 18 beach packages (same `package` names)
- Import path prefix `git.golem15.com/golem15/summercms/modules/<name>`
- 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
<tasks>
<task type="tracer">
<name>Task 1: Nest festival end to end — git mv, rewrite its importers, test the moved package</name>
<reversibility rating="costly">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.</reversibility>
<files>modules/festival/**, backpack/app.go, examples/hello/plugins/greeter/plugin.go, ../fonoteka.go/plugins/golem15/user/classes/events_test.go</files>
<read_first>.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</read_first>
<action>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.</action>
<verify>
<automated>test -d modules/festival &amp;&amp; test ! -d festival &amp;&amp; go test ./modules/festival -count=1 &amp;&amp; go test ./backpack -run '^TestEventBusesAreAppScoped$' -count=1 &amp;&amp; (cd ../fonoteka.go &amp;&amp; go test ./plugins/golem15/user -run '^TestGetApiArrayEventMerge$' -count=1)</automated>
<fails_when>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"</fails_when>
</verify>
<acceptance_criteria>
- `test -d modules/festival &amp;&amp; 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).
</acceptance_criteria>
<done>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.</done>
</task>
<task type="auto">
<name>Task 2: Nest the remaining 17 packages and rewrite every leftover importer and path literal</name>
<reversibility rating="costly">The remaining import-path rewrite touches ~220 files across both repos; costly, not one-way, no checkpoint.</reversibility>
<files>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/**</files>
<read_first>.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</read_first>
<action>Per D-02, git mv each remaining root beach directory into modules/&lt;name&gt;/: 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/&lt;name&gt;. 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.</action>
<verify>
<automated>test -d modules/cabana &amp;&amp; test ! -d cabana &amp;&amp; test -d modules/boardwalk/dist &amp;&amp; grep -F -- '--dir modules/cabana' scripts/check-admin-openapi.sh &amp;&amp; grep -F 'modules/boardwalk/dist' scripts/check-admin-dist.sh admin/vite.config.ts &amp;&amp; grep -F 'modules/tide/testdata/one-route-spec.yaml' scripts/check-phase2.sh scripts/check-phase3.sh &amp;&amp; grep -F './modules/phrasebook' scripts/check-phase4.sh &amp;&amp; grep -F './modules/lagoon' scripts/check-phase9.sh &amp;&amp; grep -F './modules/cabana' scripts/check-phase10.sh &amp;&amp; grep -F '../modules/boardwalk/dist' admin/vite.config.ts</automated>
<fails_when>non-zero exit; any of the 18 beach names still a directory at repo root; any listed grep prints no matching line</fails_when>
</verify>
<acceptance_criteria>
- `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/&lt;beach&gt;` that lacks `/modules/`.
- `test -f go.mod &amp;&amp; test ! -f modules/cabana/go.mod &amp;&amp; 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.
</acceptance_criteria>
<done>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.</done>
</task>
<task type="auto">
<name>Task 3: go vet and go test both repositories including fonoteka plugin modules</name>
<files>modules/**, ../fonoteka.go/plugins/**</files>
<read_first>.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</read_first>
<action>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.</action>
<verify>
<automated>go vet ./... &amp;&amp; go test ./... &amp;&amp; (cd ../fonoteka.go &amp;&amp; go vet ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/... &amp;&amp; go test ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/...)</automated>
<fails_when>non-zero exit; any package FAIL; output contains "build failed" or "no required module provides package" for a beach import</fails_when>
</verify>
<acceptance_criteria>
- Both repository commands exit 0.
- `test ! -d compass &amp;&amp; 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.
</acceptance_criteria>
<done>Both repos vet and test green on the nested import paths, including fonoteka plugin modules.</done>
</task>
</tasks>
<threat_model>
## 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 |
</threat_model>
<verification>
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.
</verification>
<success_criteria>
- `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/.
</success_criteria>
<output>
Create `.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-01-SUMMARY.md` when done.
</output>

View File

@@ -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/<name>/ 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/<name>/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.
<objective>
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/&lt;name&gt;/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.
</objective>
<execution_context>
@~/.claude/gsd-core/workflows/execute-plan.md
@~/.claude/gsd-core/templates/summary.md
</execution_context>
<context>
@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
<interfaces>
10.2-01 left packages at modules/&lt;name&gt;/ with import prefix git.golem15.com/golem15/summercms/modules/&lt;name&gt;. 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.
</interfaces>
</context>
## Artifacts this phase produces
- `modules/<name>/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
<tasks>
<task type="auto">
<name>Task 1: Write one short README.md per modules/&lt;name&gt; from the code</name>
<files>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</files>
<read_first>.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</read_first>
<action>Per D-07, after the nest is green, do an explore-quality pass over the code in each modules/&lt;name&gt;/ (exported types and the primary .go file, plus a quick git grep of who imports git.golem15.com/golem15/summercms/modules/&lt;name&gt;). Write modules/&lt;name&gt;/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.</action>
<verify>
<automated>test -f modules/festival/README.md &amp;&amp; test -f modules/cabana/README.md &amp;&amp; test -f modules/compass/README.md &amp;&amp; wc -l modules/*/README.md | awk 'BEGIN{bad=0} $2!="total" &amp;&amp; ($1&lt;2 || $1&gt;40){bad=1; print} END{exit bad}'</automated>
<fails_when>non-zero exit; any of the 18 modules/*/README.md missing; a README is under 2 lines or over 40 lines (essay or stub)</fails_when>
</verify>
<acceptance_criteria>
- `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).
</acceptance_criteria>
<done>Eighteen short module READMEs exist, each derived from the code, each naming an entry point.</done>
</task>
<task type="auto">
<name>Task 2: Replace root README.md with framework onboarding, login recreate, and honest cutover</name>
<files>README.md</files>
<read_first>.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</read_first>
<action>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/&lt;name&gt;/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.</action>
<verify>
<automated>test -f README.md &amp;&amp; grep -q 'fonoteka.go' README.md &amp;&amp; grep -q 'modules/' README.md &amp;&amp; grep -q 'plytadmin' README.md &amp;&amp; grep -q 'Phase 15' README.md &amp;&amp; grep -q 'docs/deploy/plytarium.com.md' README.md</automated>
<fails_when>non-zero exit; any required grep prints no matching line</fails_when>
</verify>
<acceptance_criteria>
- 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/&lt;name&gt;/README.md` path.
</acceptance_criteria>
<done>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.</done>
</task>
<task type="auto">
<name>Task 3: Unit and hygiene gate — scripts/check-phase10.2.sh plus both-repo go test</name>
<files>scripts/check-phase10.2.sh</files>
<read_first>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</read_first>
<action>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/&lt;name&gt;/ 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.</action>
<verify>
<automated>bash -n scripts/check-phase10.2.sh &amp;&amp; scripts/check-phase10.2.sh --self-test &amp;&amp; scripts/check-phase10.2.sh --all</automated>
<fails_when>non-zero exit; --self-test output lacks a passed line or contains "refuse:" for the clean tree; --all prints "refuse:" or a package FAIL</fails_when>
</verify>
<acceptance_criteria>
- `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.
</acceptance_criteria>
<done>The 10.2 gate fails closed on layout, import, README, and stale-status regressions, and both repos stay vet/test green.</done>
</task>
</tasks>
<threat_model>
## 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 |
</threat_model>
<verification>
`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.
</verification>
<success_criteria>
- 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.
</success_criteria>
<output>
Create `.planning/phases/10.2-nest-framework-packages-under-modules-and-write-run-docs/10.2-02-SUMMARY.md` when done.
</output>

View File

@@ -0,0 +1 @@
No external API integration: layout move and onboarding docs only.