diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index d5069b9..a0cc588 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -899,12 +899,12 @@ Plans: 5. `docs/setup/installation.md` leads with the one-liner, `go-modules-and-workspaces.md` and the console docs cover `summer new`, and `llms.txt`/`llms-full.txt` include the changes; docs checks pass. 6. Generator Go tests (golden output plus a real build of the scaffold in a temp dir) are the last plan. -**Plans:** 4 plans +**Plans:** 1/4 plans executed Plans: **Wave 1** -- [ ] 14.3-01-PLAN.md — `summer new` generator: starter plugin via make:plugin/plugin:add, relative go.work, config, .env + lagoon.GenerateAppKey, compose, CLAUDE.md/AGENTS.md, first commit, D-12 docker gate +- [x] 14.3-01-PLAN.md — `summer new` generator: starter plugin via make:plugin/plugin:add, relative go.work, config, .env + lagoon.GenerateAppKey, compose, CLAUDE.md/AGENTS.md, first commit, D-12 docker gate **Wave 2** *(blocked on Wave 1 completion)* - [ ] 14.3-02-PLAN.md — Bootstrap script in `modules/sunrise`, `GET /new` in the site plugin, node:24-bookworm acceptance, security review @@ -1089,7 +1089,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → | 14. Domain jobs and external integrations | 6/6 | In Progress| | | 14.1. OAuth identities and fonoteka me routes (INSERTED) | 2/2 | Complete | 2026-10-05 | | 14.2. Local Fonoteka frontend on local SummerCMS backend (INSERTED) | 0/TBD | Not started | - | -| 14.3. One-command app scaffolding (INSERTED) | 0/4 | Not started | - | +| 14.3. One-command app scaffolding (INSERTED) | 1/4 | In Progress| | | 15. Journal plugin | 4/4 | Complete | 2026-10-06 | | 16. grzybyfunkcjonalne.pl on reusable blog views | 0/TBD | Not started | - | | 17. Blog companions | 0/TBD | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index 9b214c7..ce85ed0 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -1,19 +1,19 @@ --- gsd_state_version: "1.0" milestone: v1.0 -current_phase: "14.2" -current_phase_name: local-fonoteka-frontend-on-local-summercms-backend +current_phase: "14.3" +current_phase_name: "One-command app scaffolding: summer new and summercms.io/new bootstrap script" status: executing -stopped_at: Phase 14.2 context gathered -last_updated: "2026-10-07T22:23:37.716Z" -last_activity: 2026-10-07 -last_activity_desc: Completed quick task 261006-s0v (remove ML copy-from locale UI) -state_head: 498f4b4f3af1a7057e96f81ccf714a4b3c79f428 +stopped_at: Completed 14.3-01-PLAN.md +last_updated: "2026-10-08T09:45:45.397Z" +last_activity: 2026-10-08 +last_activity_desc: Phase 14.3 execution started +state_head: 6695ab422aa0155f49c7ca87bdcb5fbf405c9e35 progress: total_phases: 31 completed_phases: 13 - total_plans: 139 - completed_plans: 135 + total_plans: 143 + completed_plans: 136 milestone_name: milestone --- @@ -24,14 +24,14 @@ milestone_name: milestone See: .planning/PROJECT.md (updated 2026-09-16) **Core value:** An existing WinterCMS-shaped app can be ported plugin by plugin to a single Go binary without its frontend noticing: the PHP version's API contract is the acceptance test. -**Current focus:** Phase 15 — Journal plugin +**Current focus:** Phase 14.3 — One-command app scaffolding: summer new and summercms.io/new bootstrap script ## Current Position -Phase: 14.2 (local-fonoteka-frontend-on-local-summercms-backend) — READY TO EXECUTE -Plan: 4 of 4 -Status: Ready for phase verification -Last activity: 2026-10-07 — Completed quick task 261007-qgx: record heading from translatable (mltext) fields +Phase: 14.3 (One-command app scaffolding: summer new and summercms.io/new bootstrap script) — EXECUTING +Plan: 2 of 4 +Status: Ready to execute +Last activity: 2026-10-08 — Phase 14.3 execution started Progress: [██████████] 100% @@ -189,6 +189,7 @@ Progress: [██████████] 100% | Phase 15 P15-01 | 11 | 3 tasks | 31 files | | Phase 15 P15-02 | 75 min | 3 tasks | 39 files | | Phase 15 P15-03 | 80 min | 3 tasks | 22 files | +| Phase 14.3 P01 | 13 min | 3 tasks | 17 files | ## Accumulated Context @@ -604,6 +605,10 @@ Recent decisions affecting current work: - [Phase 15]: NavigationItem has no IconSvg; journal-icon.svg is go:embed in AdminFS; user_id is WritableForeignKey and FormBeforeCreate stamps it when empty - [Phase 15]: 15-04 security review was executor-self-performed (no gsd-security-auditor in this Cursor session); every cited TestName was re-run. Wave-3 HTTP tests stay at plugin root; controllers/api holds clampPerPage/media path units plus EndToEnd stubs. - [Phase 15]: Host journal gitlink is a nested clone; bump via file:// fetch with protocol.file.allow=always. TestSearchGateOff must not skip. +- [Phase 14.3]: bonfire accepts new as a bare command name for summer new +- [Phase 14.3]: summer new compose.yaml publishes postgres:16 on 127.0.0.1:54320 only (user/password summer) +- [Phase 14.3]: summer new falls back to SummerCMS only for missing git identity keys +- [Phase 14.3]: plugin:add writes go.work use paths relative to the go.work directory ### Pending Todos @@ -666,6 +671,6 @@ Items acknowledged and carried forward from previous milestone close: ## Session Continuity -Last session: 2026-10-07T17:58:21.728Z -Stopped at: Phase 14.2 context gathered -Resume file: .planning/phases/14.2-local-fonoteka-frontend-on-local-summercms-backend/14.2-CONTEXT.md +Last session: 2026-10-08T09:45:44.793Z +Stopped at: Completed 14.3-01-PLAN.md +Resume file: None diff --git a/.planning/phases/14.3-one-command-app-scaffolding-summer-new-and-summercms-io-new/14.3-01-SUMMARY.md b/.planning/phases/14.3-one-command-app-scaffolding-summer-new-and-summercms-io-new/14.3-01-SUMMARY.md new file mode 100644 index 0000000..74c1ab2 --- /dev/null +++ b/.planning/phases/14.3-one-command-app-scaffolding-summer-new-and-summercms-io-new/14.3-01-SUMMARY.md @@ -0,0 +1,215 @@ +--- +phase: 14.3-one-command-app-scaffolding-summer-new-and-summercms-io-new +plan: 01 +subsystem: cli +tags: [summer-new, scaffolding, internal-build, go-work, lagoon, compose, postgres16] + +requires: + - phase: 01-framework-kernel-foundation + provides: make:plugin, plugin:add, summer build (internal/build), bonfire commands + - phase: 05-data-layer-full-fidelity + provides: lagoon app.key handling and key:generate +provides: + - "summer new [--framework] [--no-plugin] [--no-git] writing a ready-to-run sm--app" + - "build.NewOptions, build.NewApp, build.ValidateAppName; unexported planNewApp/genFile for golden tests" + - "make:plugin opt-in starter route (StarterRoute) in the single routes.go template" + - "plugin:add writes relative go.work use paths" + - "lagoon.GenerateAppKey" + - "examples/hello/config/http.yaml (TestTypedItemRoute green)" + - "scripts/check-phase14.3.sh --generator (D-12 on real PostgreSQL 16)" +affects: [14.3-02 bootstrap script, 14.3-03 docs, 14.3-04 unit tests] + +actuals: + tokens: 11696 + tasks: 3 + commits: 6 +plan_head_before: 86fcd5d4fd2b8347629592a254029573cb67c7d3 +plan_head_after: 6695ab422aa0155f49c7ca87bdcb5fbf405c9e35 + +tech-stack: + added: [] + patterns: + - "Pure planNewApp (renders genFile list, reads only the framework go.mod) plus an executor that writes, then reuses makePlugin/AddPlugin/generate" + - "relModulePath helper shared by editAppModule, runGoWorkUse and the app replace" + - "frameworkFromBinary package variable so tests can replace binary-source detection" + +key-files: + created: + - internal/build/new.go + - internal/build/new_test.go + - internal/build/stubs/new.tmpl + - examples/hello/config/http.yaml + - scripts/check-phase14.3.sh + modified: + - internal/build/scaffold.go + - internal/build/stubs/plugin.tmpl + - cmd/summer/main.go + - cmd/summer/main_test.go + - modules/bonfire/command.go + - modules/bonfire/command_test.go + - modules/bonfire/README.md + - modules/lagoon/keygen.go + - modules/lagoon/keygen_test.go + - modules/lagoon/README.md + - README.md + - docs/setup/installation.md + +key-decisions: + - "bonfire accepts `new` as a bare command name (alongside build, dev, serve, migrate); required for `summer new`" + - "compose.yaml values (postgres:16, summer/summer, 127.0.0.1:54320) are literal in new.tmpl; Go constants build the matching .env DSN" + - "Fallback git identity is applied per missing key only (user.name and/or user.email), with a warning" + - "AGENTS.md is a relative symlink to CLAUDE.md" + - "Generated-app commit carries no trailers; .env is excluded by .gitignore written before git add -A" + +patterns-established: + - "New app templates live in stubs/new.tmpl under define names prefixed new/" + - "Any error after os.Mkdir of the target removes the target (it did not exist before the run)" + +requirements-completed: [D-01, D-02, D-03, D-04, D-05, D-06, D-07, D-08, D-09, D-10, D-11, D-12, D-22, D-23, D-24, D-25, D-27] + +coverage: + - id: D1 + description: "summer new writes sm--app with a relative framework replace, relative go.work, config/ and a starter plugin whose GET /{$} route is listed by route:list" + requirement: D-05 + verification: + - kind: integration + ref: "internal/build/new_test.go#TestNewAppSmoke" + status: pass + - kind: integration + ref: "internal/build/build_test.go#TestMakeAndAddPluginOnHelloCopy" + status: pass + human_judgment: false + - id: D2 + description: "Name rule, existing-target refusal, missing-framework error naming --framework, sibling detection and --no-plugin build" + requirement: D-02 + verification: + - kind: other + ref: "Task 2 verify shell block (-trimpath summer; RULES-OK)" + status: pass + human_judgment: false + - id: D3 + description: "Generated app builds, migrates on compose PostgreSQL 16 and serves the starter route with no edits; .env 0600 untracked, one fallback-identity commit, AGENTS.md symlink, no root go.sum" + requirement: D-12 + verification: + - kind: e2e + ref: "bash scripts/check-phase14.3.sh --generator" + status: pass + human_judgment: false + - id: D4 + description: "lagoon.GenerateAppKey exported; key:generate output unchanged" + requirement: D-08 + verification: + - kind: unit + ref: "modules/lagoon/keygen_test.go#TestEncryptedKeyGeneratePrints32ByteBase64" + status: pass + - kind: unit + ref: "modules/lagoon/keygen_test.go#TestGenerateAppKeyIs32ByteBase64" + status: pass + human_judgment: false + - id: D5 + description: "examples/hello serves without a manual config step" + requirement: D-07 + verification: + - kind: integration + ref: "go -C examples/hello test ./..." + status: pass + human_judgment: false + - id: D6 + description: "Generated CLAUDE.md wording is neutral and useful for agents" + requirement: D-10 + verification: [] + human_judgment: true + rationale: "Tone and usefulness of agent instructions need a human read; greps only prove the required links and names are present" + +duration: 13min +completed: 2026-10-08 +status: complete +--- + +# Phase 14.3 Plan 01: summer new generator Summary + +**`summer new ` writes a ready-to-run sm--app (relative framework replace and go.work, config/, starter plugin with GET /, .env with a fresh key, postgres:16 compose on 127.0.0.1:54320, CLAUDE.md/AGENTS.md, first git commit) that builds, migrates and serves with no edits.** + +## Performance + +- **Duration:** 13 min +- **Started:** 2026-10-08T09:32:14Z +- **Completed:** 2026-10-08T09:44:54Z +- **Tasks:** 3 +- **Files modified:** 17 + +## Accomplishments + +- `build.NewApp` plus `summer new` with `--framework`, `--no-plugin`, `--no-git`; framework resolution `--framework` > sibling `summercms`/`summercms.go` > binary source tree, each checked by module path. +- Shared code-path fixes: `make:plugin` gains an opt-in starter route in the same template (plain output byte-identical, verified against the previous template); `plugin:add` writes relative `go.work` paths. +- Refusals: invalid names (regex, Go keywords, `main`, `internal`), any existing target, a target inside the framework checkout, a missing parent; a failed run removes its own target. +- `lagoon.GenerateAppKey` exported and documented; `examples/hello` ships `config/http.yaml`. +- `scripts/check-phase14.3.sh --generator` proves D-12 on real PostgreSQL 16: `GET /` returned `{"message":"Hello from SummerCMS","plugin":"golem15.demo"}`. + +## Task Commits + +1. **Task 1: summer new tracer** - `7bc955a` (feat) +2. **Task 2: framework detection, refusals, cleanup, --no-plugin** - `c33ebf3` (feat), hello fix `cc7386d` (fix) +3. **Task 3: key, compose, agent notes, git, next steps, gate** - `ca5b296` (feat, lagoon), `147ef24` (feat, generator), `6695ab4` (chore, gate) + +## Files Created/Modified + +- `internal/build/new.go` - NewOptions, NewApp, ValidateAppName, resolveFramework, binarySourceFramework, planNewApp, populateApp, initGit +- `internal/build/stubs/new.tmpl` - go.mod, config/*, .env, .env.example, compose.yaml, .gitignore, CLAUDE.md, next steps +- `internal/build/stubs/plugin.tmpl` - routes.go `{{if .StarterRoute}}` branch +- `internal/build/scaffold.go` - makePlugin(pluginOptions), relModulePath, relative runGoWorkUse +- `internal/build/new_test.go` - TestNewAppSmoke +- `cmd/summer/main.go`, `cmd/summer/main_test.go` - `new` command and its test entries +- `modules/bonfire/command.go`, `command_test.go`, `README.md` - `new` allowed as a bare name +- `modules/lagoon/keygen.go`, `keygen_test.go`, `README.md` - GenerateAppKey +- `examples/hello/config/http.yaml`, `README.md`, `docs/setup/installation.md` - body_limits gap closed +- `scripts/check-phase14.3.sh` - generator gate + +## Decisions Made + +- `new` is added to bonfire's bare-name allowlist (see deviation 1). +- Fallback git identity covers only the missing keys, so a user with `user.name` set but no email keeps their name. +- Compose values are literal in the template so the loopback-only binding is greppable; the DSN is assembled from matching Go constants. + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 3 - Blocking] bonfire rejected the bare command name `new`** +- **Found during:** Task 1 +- **Issue:** `bonfire.NewRoot` only accepts `build`, `dev`, `serve`, `migrate` as bare names; `TestToolCommandNames` failed with `plugin command name must be namespace:verb: "new"`. +- **Fix:** Added `new` to `validCommandName`, to `TestValidBareRuntimeCommandNames`, and to the bonfire README sentence listing bare names (project documentation rule). +- **Files modified:** modules/bonfire/command.go, modules/bonfire/command_test.go, modules/bonfire/README.md +- **Verification:** `go test ./modules/bonfire/ ./cmd/summer/` pass +- **Committed in:** 7bc955a + +**2. [Rule 1 - Bug] Gate script EXIT trap referenced function locals** +- **Found during:** Task 3 +- **Issue:** The cleanup trap runs after `stage_generator` returns, when its `local` variables are gone, so Docker cleanup would have been skipped. +- **Fix:** Made `tmp`, `app`, `project`, `server_pid` globals. +- **Verification:** After the gate run no `phase143` containers or volumes remain and the temp dir is removed. +- **Committed in:** 6695ab4 + +--- + +**Total deviations:** 2 auto-fixed (1 blocking, 1 bug). **Impact:** Both necessary; the bonfire change only widens the accepted name set (non-breaking). + +## Issues Encountered + +- `internal/build/registry.go` is listed by `gofmt -l` before this plan; untouched (out of scope). + +## User Setup Required + +None - no external service configuration required. + +## Next Phase Readiness + +- Plan 02 can call `summer new --framework ` from the bootstrap script; next steps are printed by `summer new` itself (no `cd` line). +- Plan 03 should document `summer new` (console docs, installation one-liner, go-modules page, relative `plugin:add` go.work paths) and may drop the remaining hello `main.go` known-issue bullet. +- Plan 04 can golden-test `planNewApp` with `testAppKey` and replace `frameworkFromBinary`. + +--- +*Phase: 14.3-one-command-app-scaffolding-summer-new-and-summercms-io-new* +*Completed: 2026-10-08* + +## Self-Check: PASSED