252 lines
22 KiB
Markdown
252 lines
22 KiB
Markdown
---
|
|
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: modules/backpack/app.go
|
|
to: modules/festival
|
|
via: backpack's final post-migration location imports festival through git.golem15.com/golem15/summercms/modules/festival
|
|
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 && test ! -d festival && go test ./modules/festival -count=1 && go test ./backpack -run '^TestEventBusesAreAppScoped$' -count=1 && go test -run '^$' ./examples/hello/... ./examples/hello/plugins/base/... ./examples/hello/plugins/greeter/... ./examples/hello/plugins/optional/... && (cd ../fonoteka.go && go test ./plugins/golem15/user -run '^TestGetApiArrayEventMerge$' -count=1)</automated>
|
|
<fails_when>non-zero exit; festival still exists at repo root; modules/festival missing; a named-test command shows FAIL or lacks its requested test; the compile-only examples command fails to build any workspace module</fails_when>
|
|
</verify>
|
|
<acceptance_criteria>
|
|
- `test -d modules/festival && test ! -d festival` succeeds.
|
|
- `go test ./modules/festival -count=1` prints PASS including TestFireRunsAllListenersAndJoinsErrors.
|
|
- `go test -run '^$' ./examples/hello/... ./examples/hello/plugins/base/... ./examples/hello/plugins/greeter/... ./examples/hello/plugins/optional/...` exits 0, compiling the greeter importer in its nested module context without depending on unrelated example runtime tests.
|
|
- `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 in the framework, examples workspace, and fonoteka contexts, and the moved package plus named importer tests pass.</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/<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.</action>
|
|
<verify>
|
|
<automated>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</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/<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.
|
|
</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 ./.... Explicitly vet the examples/hello root plus base, greeter, and optional nested modules, then compile all four module contexts with go test -run '^$'; the root module wildcard does not traverse nested Go modules, and the compile-only run verifies import resolution without coupling this migration to unrelated example runtime assertions. 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 ./... && go test ./... && go vet ./examples/hello/... ./examples/hello/plugins/base/... ./examples/hello/plugins/greeter/... ./examples/hello/plugins/optional/... && go test -run '^$' ./examples/hello/... ./examples/hello/plugins/base/... ./examples/hello/plugins/greeter/... ./examples/hello/plugins/optional/... && (cd ../fonoteka.go && go vet ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/... && 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.
|
|
- The examples/hello root and base, greeter, and optional nested modules all exit 0 under `go vet` and compile-only `go test -run '^$'`.
|
|
- `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.
|
|
</acceptance_criteria>
|
|
<done>Both repos vet and test green on the nested import paths, every examples/hello module vets and compiles, and fonoteka plugin modules are included.</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 in the framework, examples/hello greeter module, and fonoteka importer contexts. 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, explicit vet plus compile-only test across every examples/hello workspace module, 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, and every examples/hello module vets and compiles. 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>
|