diff --git a/.planning/phases/19.8-console-commands-overhaul/19.8-04-SUMMARY.md b/.planning/phases/19.8-console-commands-overhaul/19.8-04-SUMMARY.md new file mode 100644 index 00000000..6cfaf7df --- /dev/null +++ b/.planning/phases/19.8-console-commands-overhaul/19.8-04-SUMMARY.md @@ -0,0 +1,271 @@ +--- +phase: 19.8-console-commands-overhaul +plan: 04 +subsystem: console +tags: [tests, gate, diary, bonfire, slogtest, goldens, surf, conga, lagoon, cabana, flare, dev] + +requires: + - phase: 19.8-01 + provides: diary (channels, components, daily files, console handler) + - phase: 19.8-02 + provides: bonfire global flags, list, help, errors, widgets, prompts + - phase: 19.8-03 + provides: swept framework commands, request log, summaries, v0.4.0, swept plugins, applications +provides: + - "scripts/check-phase19.8.sh: fail-closed gate (self-test, go, hello, docs, plugins, apps, landing, docker) with --self-test" + - "Unit and golden tests for diary, sunscreen, bonfire, docsite and every swept framework command" + - "fix(bonfire): PeekGlobals reads clustered shorthands (post-release fix, in v0.4.0)" +affects: [19.8 verification, the next framework tag] + +actuals: + tokens: 53163 # chars/4 over the added lines of this plan's diff (goldens excluded) + tasks: 4 # Tasks 1-4 done; Task 5 is the checkpoint, Task 6 waits on its reply + commits: 11 # MEASURED: git rev-list --count plan_head_before..plan_head_after +plan_head_before: b906a31c368ad6a59ea8f6ac82121714ffad20da +plan_head_after: 72b8383c1022a993b66c6cd8b4f739bdee062246 + +tech-stack: + added: [] + patterns: + - "Goldens under modules/bonfire/testdata with an -update flag; color detection cleared per test (plainEnv)" + - "testing/slogtest for the console handler through a key=value line parser, and for the full pipeline through JSON" + - "Interactive-terminal tests on a pseudo-terminal opened with syscall only (/dev/ptmx), no new dependency" + - "Gate additive check finds each plugin's sweep commit by subject and diffs it against its parent" + +key-files: + created: + - scripts/check-phase19.8.sh + - modules/diary/diary_test.go + - modules/diary/config_test.go + - modules/diary/daily_test.go + - modules/diary/console_test.go + - modules/diary/slogtest_test.go + - modules/bonfire/globals_test.go + - modules/bonfire/root_test.go + - modules/bonfire/golden_test.go + - modules/bonfire/errors_test.go + - modules/bonfire/docs_test.go + - modules/bonfire/widgets_test.go + - modules/bonfire/live_test.go + - modules/bonfire/version_test.go + - modules/bonfire/testdata/*.golden (9 files) + - internal/docsite/check_commands_test.go + - modules/surf/summary_test.go + - modules/conga/stats_test.go + - modules/conga/logger_test.go + - modules/conga/confirm_linux_test.go + - modules/lagoon/pending_test.go + - modules/lagoon/commands_flags_test.go + - modules/lagoon/logger_test.go + - modules/lagoon/pty_linux_test.go + - modules/cabana/token_json_test.go + modified: + - modules/bonfire/globals.go + - modules/bonfire/version.go + - modules/sunscreen/sunscreen_test.go + - modules/surf/accesslog_test.go + - modules/flare/commands_test.go + - internal/dev/watch_test.go + - cmd/summer/runtime_test.go + +key-decisions: + - "PeekGlobals reads a single-dash cluster letter by letter like pflag (-qn, -vq, -nvv) and stops at the first non-global letter; released as a post-release fix pending the Task 5 reply" + - "BuildVersion reads build info through an unexported package variable (refactor, no behaviour change) so tests pin the tagged, replaced and go.work cases" + - "Interactive confirmation is tested on a real pseudo-terminal (syscall ioctls on /dev/ptmx) instead of adding a pty dependency or a bonfire test seam" + - "The landing stage runs nuxt generate before the TAP suite and checks the roadmap snapshot against origin/master; TestTerminalCommands (deployed one-liner) is opt-in" + +requirements-completed: [SC-5, D-03, D-08, D-09, D-10, D-12, D-13, D-14, D-15, D-16, D-17, D-18, D-19, D-21, D-23, D-25, D-27, D-28, D-29] + +coverage: + - id: D1 + description: "Fail-closed gate: detectors proven on planted output, additive and NOT SWEPT rules on planted git repositories, docker NOT RUN rule" + requirement: SC-5 + verification: + - kind: other + ref: "bash scripts/check-phase19.8.sh --self-test" + status: pass + human_judgment: false + - id: D2 + description: "diary config rules, floors, verbosity, quiet, daily rotation/retention/permissions/degradation, path confinement, redaction on every driver, control characters, lifecycle, concurrency, slogtest" + requirement: D-08 + verification: + - kind: unit + ref: "modules/diary#TestConfigRules ... TestSlogtestPipeline (27 names in the gate)" + status: pass + human_judgment: false + - id: D3 + description: "bonfire goldens (list, list --all, JSON, styled, help, passthrough help, three error blocks), flags, exit codes, duplicates, version header" + requirement: D-13 + verification: + - kind: unit + ref: "modules/bonfire#TestListGolden, TestHelpGolden, TestErrorGolden, TestPeekGlobals, TestGlobalFlagsAgree, TestExitCodes" + status: pass + human_judgment: true + rationale: "The goldens were created with -update and read against the D-13, D-14 and D-18 previews; layout taste is a person's call" + - id: D4 + description: "Widget matrix, live models, prompts, ConfirmProceed, Secret under -n, PrintAbove" + requirement: D-03 + verification: + - kind: unit + ref: "modules/bonfire#TestWidgetMatrix, TestLiveModels, TestPromptsNoInteraction, TestSecretWithNoInteraction, TestConfirmProceed, TestPrintAbove" + status: pass + - kind: manual_procedural + ref: "throwaway program under script(1) on a pty: spinner, progress and process view print their final frames" + status: pass + human_judgment: false + - id: D5 + description: "Swept framework commands: serve summary/records/report, request log, WorkerStats, PendingMigrations, --pretend, production question, --json, -q data, Reported, summer dev, delegates" + requirement: D-29 + verification: + - kind: unit + ref: "go stage names for surf, conga, lagoon, flare, internal/dev, cmd/summer" + status: pass + - kind: integration + ref: "docker stage: TestServeLifecycle, TestPendingMigrations, TestMigratePretend, TestRollbackPretend, TestDeferredPurgePretend, TestMigrateStatusJSON, TestTokenCreateJSON, TestTokenListJSON, TestTokenCreateQuietKeepsToken" + status: pass + human_judgment: false + - id: D6 + description: "Plugins (15 repositories), applications (5) and landing run from the gate" + requirement: D-17 + verification: + - kind: other + ref: "bash scripts/check-phase19.8.sh --all (PHASE198_REQUIRE_DOCKER=1): every stage PASS" + status: pass + human_judgment: false + +duration: 69min +completed: 2026-10-21 +status: checkpoint +--- + +# Phase 19.8 Plan 04: unit tests and the phase gate Summary + +**A fail-closed `scripts/check-phase19.8.sh` (eight stages, green with `--all` and Docker required) plus unit, golden, slogtest and pseudo-terminal tests for diary, bonfire and every swept framework command; the tests found one bug in released code, `PeekGlobals` ignoring clustered shorthands such as `-qn`, fixed in its own commit and waiting on the Task 5 go-ahead.** + +## Performance + +- **Started:** 2026-10-21T16:47:08Z +- **Checkpoint reached:** 2026-10-21T17:56Z (about 69 min) +- **Tasks:** 4 of 6 done; Task 5 (checkpoint:decision) presented; Task 6 waits on its reply +- **Files:** 40 changed, 6,036 insertions, 7 deletions + +## Accomplishments + +- Gate with stages `self-test`, `go`, `hello`, `docs`, `plugins`, `apps`, `landing`, `docker`; detectors for `go test -json` and node `--test` TAP output, the additive check and the NOT SWEPT rule, each proven on planted input. +- diary: 24 new tests incl. `testing/slogtest` conformance for the console handler and the pipeline, 100 concurrent writers under `-race`, rotation with an injected clock, retention, 0640 files under a strict umask. +- bonfire: 9 goldens and 26 new tests (global flags, exit codes, widgets, live models, prompts, version header). +- Framework commands: summaries and reports, request log (never the path), WorkerStats, the production question on a real pseudo-terminal, `--pretend`, `--json`, `-q` data, Reported failures, `summer dev` with a real child process. +- `--all` runs the 15 swept plugins (short suites, coverage test, `GOWORK=off` build, additive check), the 5 applications (build, `summer build` leaves `main.go` unchanged, `list`, `help migrate`), the landing site and the Docker suites. + +## Task Commits + +1. **Task 1 (tracer): gate with the smoke tests by name**: `9b2fa6c` test(19.8) +2. **Task 2: diary, sunscreen, River and GORM**: `24f4643` test(diary), `db83a14` test(conga,lagoon) +3. **Task 3: bonfire and docsite**: `efb043e` fix(bonfire) (post-release fix), `9641a1b` refactor(bonfire), `7b58ad5` test(bonfire) goldens, `eeeee59` test(bonfire) flags/exit codes/widgets, `fd52868` test(docsite) +4. **Task 4: framework commands and the remaining stages**: `6720cae` test(surf,conga,lagoon), `2baec56` test(cabana,flare,dev,summer), `72b8383` test(19.8) gate stages +5. **Task 5**: checkpoint presented (see below) +6. **Task 6**: waits on the Task 5 reply + +`commits: 11` is measured from the ledger (`b906a31..72b8383`); all eleven are this plan's. The tracer feedback gate re-ran Task 1's automated verify after its commit (green), so expansion continued. + +## Post-release fixes + +| # | Commit | Module | Symptom | Pinning test | In v0.4.0 | Needs require (plugins) | Regenerate (apps) | +|---|--------|--------|---------|--------------|-----------|-------------------------|-------------------| +| 1 | `efb043e` | bonfire | `PeekGlobals` read only `-v` clusters, so `-qn`, `-vq`, `-nvv` were missed before cobra parsed them: the generated main's pre-boot diary setup ignored them (boot logs not quieted), `Execute`'s error block rendered without the `-v` chain, and passthrough commands (summer's delegates) saw no globals. cobra itself parsed them, so the commands ran with the right options. | `TestPeekGlobals`, `TestGlobalFlagsAgree` (rows `combined -qn`, `combined -vq`, `combined -nvv`) | yes | no (no API change) | no (generated `main.go` unchanged; applications pick it up with a framework require bump) | + +Not a fix, nothing to publish: `9641a1b` refactor(bonfire) reads build info through an unexported variable for `TestVersionHeader`; no behaviour change, it rides with the next tag. + +Proposed patch tag: **v0.4.1** (framework only). + +## Task 5 reply + +Pending. Before the reply `git tag --points-at HEAD` printed nothing (no tag on HEAD). + +## --all stage summary + +`PHASE198_REQUIRE_DOCKER=1 TESTCONTAINERS_HOST_OVERRIDE=127.0.0.1 bash scripts/check-phase19.8.sh --all` at `72b8383`: + +``` +PASS self-test +PASS go +PASS hello +PASS docs +PASS plugins +PASS apps +NOT RUN TestTerminalCommands (the deployed one-liner end to end: needs network, Docker and ports 54320 and 8080; set SUMMERCMS_TERMINAL_CHECK=1) +PASS landing +PASS docker +Phase 19.8 gate passed +``` + +`go vet ./...`, `go test -count=1 -short ./...` and `--self-test` were green in the same run. No line of the log starts with `FAIL` or reports an unimplemented stage. + +## Docker + +- **Run.** The docker stage ran (daemon up, `PHASE198_REQUIRE_DOCKER=1`): `TestServeLifecycle`, `TestPendingMigrations`, `TestMigratePretend`, `TestRollbackPretend`, `TestDeferredPurgePretend`, `TestMigrateStatusJSON`, `TestTokenCreateJSON`, `TestTokenListJSON`, `TestTokenCreateQuietKeepsToken`: PASS. +- The complete Docker suites of `modules/lagoon/...`, `modules/cabana`, `modules/surf` and `modules/conga` (`go test -count=1 ./...` without `-short`) also pass with the new tests. +- Plugins: only their short suites run in the gate; the known Docker failures of sitemap, faq, menu and the user plugin's `updates` package (deferred-items.md, plan 03) are not part of this gate. + +## Goldens against the previews + +Read after `-update`; sections, order and alignment match D-13, D-14 and D-18. Intentional differences: the list also shows `help`; help prints the value placeholder as the upper-cased flag name (`--expires=EXPIRES`, the preview shows `DAYS`) and adds the `Global options` and `Help` sections the preview left out; the argument column aligns with the option labels. + +## Decisions Made + +See `key-decisions`. The two worth a look: the post-release fix above, and testing the production question on a real pseudo-terminal (`/dev/ptmx` with `syscall` ioctls, linux build tag), which needs no new dependency and no bonfire test seam. + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] PeekGlobals ignored clustered shorthands** +- **Found during:** Task 3 (`TestGlobalFlagsAgree`) +- **Fix:** read single-dash clusters letter by letter; stop at the first non-global letter +- **Files:** modules/bonfire/globals.go +- **Commit:** `efb043e` (in the Post-release fixes table) + +**2. [Rule 3 - Blocking] No injectable build-info reader** +- **Found during:** Task 3 (`TestVersionHeader`) +- **Fix:** `var readBuildInfo = debug.ReadBuildInfo`, used by `BuildVersion` +- **Commit:** `9641a1b` (refactor, no behaviour change) + +**3. [Rule 3 - Blocking] gate build of library-only plugins** +- `go build -o dir/ ./...` refuses repositories without a main package; the plugins stage uses `GOWORK=off go build ./...`. + +### Recorded differences + +4. **Extra test files** not in the plan's list: `modules/conga/confirm_linux_test.go` (queue:clear's question, `TestQueueClearConfirm`), `modules/lagoon/pty_linux_test.go` (`TestConfirmProductionInteractiveNo`, `TestForceSkipsConfirm`), additional tests `TestDefaultConfig`, `TestConsoleLevelFromOptions`, `TestRouteListJSON` (in summary_test.go), `TestMigrateStatusJSON` (in pending_test.go, Docker). +5. **Component names with dots.** `TestConfigRules` pins the nested form as refused and the literal YAML key as accepted (compass keeps it literal); the docs' "cannot contain dots" wording is a deferred item. +6. **Version header.** Equal `devel` versions collapse to `SummerCMS acme devel`; pinned, deferred. +7. **TestErrorScrubbed** covers the credential shapes `sunscreen.Scrub` knows (Bearer, `sk-`, `x-api-key:`) in the message, explanation, Try line and `-v` chain; a `password=` in a message is not scrubbed (sunscreen contract; deferred). +8. **Widget matrix on a terminal.** Live views on a buffer draw no frames (no window size), so the terminal row checks the live path (three cursor-hide sequences, no fallback lines); `TestLiveModels` renders the frames with a fixed size and a pty run showed every final frame. +9. **TestServeGracefulNil and TestShutdownReportAborted** drive `requestCounter` and `shutdownReport` through a real `http.Server` with serve's drain logic; serve's own wiring of them is covered by `TestServeLifecycle` (Docker). +10. **Landing.** The stage runs `nuxt generate` before the TAP suite (plan 03 deviation 12); `TestTerminalCommands` is opt-in (NOT RUN line); `sync-roadmap.sh --check` uses `ROADMAP_REF=origin/master` because local master carries other sessions' unpushed planning commits. +11. **Verify chain flake.** One run of Task 3's verify chain stopped red after its race step without a visible failure; every piece passed separately and the full chain passed on the rerun. + +**Total deviations:** 3 auto-fixed (1 bug, 2 blocking), 8 recorded differences. + +## Issues Encountered + +- Pre-existing gofmt drift in plan 03 files (`cmd/summer/main.go`, `runtime.go`, `runtime_test.go`, `modules/flare/commands.go`); logged in deferred-items.md. + +## Known Stubs + +None. + +## Threat Flags + +None. No new endpoint or input path; the goldens hold fixed fake values (secret scan over `modules/bonfire/testdata` finds no JWT, `sk-` key or private key header). + +## g15office + +No g15office tool is available in this executor session: the Phase 19.8 milestone task was not commented. Suggested comment once the Task 5 reply is in: "Plan 19.8-04 executed: phase gate green (--all with Docker), one post-release fix (PeekGlobals clustered shorthands); waiting on verification." + +## Next + +Task 5 reply ("release vX.Y.Z", "push-only" or "hold"), then Task 6 under it, then `/msd-verify-work 19.8`. + +## Self-Check: PASSED + +Every created file listed above exists (9 goldens), and the eleven commits `9b2fa6c`, `24f4643`, `db83a14`, `efb043e`, `9641a1b`, `7b58ad5`, `eeeee59`, `fd52868`, `6720cae`, `2baec56`, `72b8383` resolve. diff --git a/.planning/phases/19.8-console-commands-overhaul/deferred-items.md b/.planning/phases/19.8-console-commands-overhaul/deferred-items.md index ca218785..882f6792 100644 --- a/.planning/phases/19.8-console-commands-overhaul/deferred-items.md +++ b/.planning/phases/19.8-console-commands-overhaul/deferred-items.md @@ -18,3 +18,15 @@ Each failure below also fails at the plugin's commit before the sweep, with fram - **sm-user-plugin `updates` migration tests** (`TestExtendUsersMigration`, `TestCreateUserThrottleMigration`, `TestCreateJwtBlacklistMigration`, `user_session_test.go`): "survived rollback", a varying subset per run; also at v0.1.5 with framework v0.3.1. - **Plugin boot logs on `list`.** Application binaries print INFO boot records (for example `paymentgateway: operators registered`) before `list` and `help` output. Already captured by another session as a todo (summercms.go `c1f5ded`, "Quiet plugin boot logs on console commands like --help"). - **sm-demo-app roadmap snapshot vs local master.** `scripts/sync-roadmap.sh --check` fails against local framework master while other sessions' 19.6 and 19.6.1 planning commits are unpushed; it passes with `ROADMAP_REF=origin/master`. Re-sync after those commits are pushed. + +## Found during 19.8-04 (unit tests) + +Recorded, not fixed here: none of them is a defect in released behaviour. + +- **gofmt drift from plan 03.** `gofmt -l` lists `cmd/summer/main.go`, `cmd/summer/runtime.go`, `cmd/summer/runtime_test.go` (map key alignment) and `modules/flare/commands.go`; each already differs at the plan 03 release. The tests added here are formatted. +- **Dotted component names in YAML.** The diary README and `docs/services/logging.md` say component names cannot contain dots. compass keeps a dotted YAML key literal (`components: {golem15.blog: debug}` parses as component `golem15.blog` and works for `diary.For("golem15.blog")`); only the nested form, which `SUMMER_LOG__` variables produce, is refused. `TestConfigRules` pins both. Either reject the literal form or reword the docs ("use names without dots so environment overrides can reach them"). +- **`Version.Header` collapses equal versions.** An application built as `devel` against a `devel` framework prints `SummerCMS acme devel` without `(framework devel)`, the same rule that gives `SummerCMS summer v0.4.0`. Go stamps VCS pseudo-versions on applications, so it shows only with `-buildvcs=false`. Pinned by `TestVersionHeader`. +- **Error blocks scrub credential shapes only.** `RenderError` passes text through `sunscreen.Scrub` (Bearer tokens, `sk-` keys, `x-api-key:`); a `password=...` written into an error message is printed as is. The plan's `TestErrorScrubbed` wording ("a password attribute in the message") is covered for the shapes Scrub knows; extending Scrub is a sunscreen change for every log line and needs its own decision. +- **Live views on a non-terminal writer draw no frames.** `runLive` takes the window size from the terminal; with a buffer the renderer draws nothing but the PrintAbove lines. The widget matrix therefore proves the live path ran (cursor hidden, no fallback lines) and `TestLiveModels` renders the frames with a fixed size; a pty run of spinner, progress and process view printed every final frame (`✓ fast spinner`, `4/4`, `✓ a`, `✗ b bad row`, `Importing 2/2 … 100%`). +- **Landing end-to-end check.** `TestTerminalCommands` (sm-summercmsio-app) runs the deployed one-liner and needs network, Docker and ports 54320 and 8080; the gate runs it only with `SUMMERCMS_TERMINAL_CHECK=1` and prints NOT RUN otherwise. +- **Stray binary in sm-grzybyfunkcjonalne-app.** An untracked `sm-grzybyfunkcjonalne-app` executable sits in that application's root (present before this plan; a `go build` without `-o`). Not this plan's; left alone.