diff --git a/.planning/phases/19.3-framework-transport-and-infrastructure-for-wavepath/19.3-05-SUMMARY.md b/.planning/phases/19.3-framework-transport-and-infrastructure-for-wavepath/19.3-05-SUMMARY.md index 409c0dc..f38590c 100644 --- a/.planning/phases/19.3-framework-transport-and-infrastructure-for-wavepath/19.3-05-SUMMARY.md +++ b/.planning/phases/19.3-framework-transport-and-infrastructure-for-wavepath/19.3-05-SUMMARY.md @@ -3,7 +3,7 @@ phase: 19.3-framework-transport-and-infrastructure-for-wavepath plan: 05 subsystem: testing tags: [gate, bouncer, turnstile, cors, api-docs, cooler, redis, miniredis, rate-limit, s3, build-tags, site-cache, nuxt-layers, release] -status: in-progress +status: complete requires: - phase: 19.3-01 @@ -19,14 +19,15 @@ provides: - "SC-4 unit tests for every piece of new code of the phase, in summercms.go, three plugins and three layers" - "github.com/alicebob/miniredis/v2 v2.40.0 as a test-only dependency (human-approved)" - "19.3-VALIDATION.md per-task map filled, wave_0_complete true" -affects: [19.3 release (Task 7), /msd-verify-work 19.3, /msd-validate-phase 19.3] + - "summercms v0.1.27 tagged and pushed; sm-faq-plugin, sm-menu-plugin and sm-journal-plugin require v0.1.27 on origin" +affects: [/msd-verify-work 19.3, /msd-validate-phase 19.3, sm-grzybyfunkcjonalne-app plugin submodule pointers] actuals: - tokens: 53300 - tasks: 6 - commits: 8 + tokens: 56050 + tasks: 7 + commits: 9 plan_head_before: 6035ccc194a74a9124ece17ce3c8301689cbc8ac -plan_head_after: 8f5325300c94fe7fb18e60b47102bc2443a0a17c +plan_head_after: 9921768bbf0814671a89eafd45f949afcc113a11 tech-stack: added: @@ -64,6 +65,12 @@ key-files: - go.mod - go.sum - ../sm-journal-plugin/site_cache_admin_test.go + - ../sm-journal-plugin/go.mod + - ../sm-journal-plugin/go.sum + - ../sm-faq-plugin/go.mod + - ../sm-faq-plugin/go.sum + - ../sm-menu-plugin/go.mod + - ../sm-menu-plugin/go.sum - ../vue-faq-layer/tests/sitePurge.test.ts - ../vue-menu-layer/tests/sitePurge.test.ts - ../vue-journal-layer/tests/sitePurge.test.ts @@ -73,44 +80,121 @@ key-decisions: - "Phase gate reuses check-phase18.1.sh's go test -json detector: a skip, a missing name, no tests, zero tests or a build failure fails the stage" - "miniredis is test-only: only _test.go files in modules/cooler import it (Task 4 reply: approved)" - "Journal's plan-04 Docker test renamed to TestCategoriesAdminFrameworkKeysWin so the unit test owns TestSiteCacheFrameworkKeysWin" - - "Release proposal: framework tag v0.1.27 (highest v0.1.26 plus one, free on origin); nothing pushed or tagged before the Task 7 reply" + - "Phase 19.3 released as summercms v0.1.27 (Task 7 reply: release); the three plugins require v0.1.27, the app's plugin submodule pointers are not bumped yet" -requirements-completed: [] +requirements-completed: [SC-1, SC-2, SC-3, SC-4, D-01, D-02, D-03, D-04, D-05, D-07, D-08, D-09, D-10, D-11, D-12, D-13, D-15, D-16, D-17, D-18] -duration: 41min (plan wall time so far, both executor runs) -completed: pending (Task 7 release decision) +coverage: + - deliverable: "Fail-closed phase gate scripts/check-phase19.3.sh" + human_judgment: false + verification: + - kind: command + ref: "bash scripts/check-phase19.3.sh --all" + status: pass + - deliverable: "SC-4 unit tests across framework, plugins and layers" + human_judgment: false + verification: + - kind: command + ref: "bash scripts/check-phase19.3.sh --all (go, docker, plugins, layers stages)" + status: pass + - kind: command + ref: "go test -count=1 ./... (41 packages, Docker suites included)" + status: pass + - deliverable: "Release v0.1.27 with plugins bumped and all commits pushed" + human_judgment: false + verification: + - kind: command + ref: "git ls-remote --tags origin refs/tags/v0.1.27 (non-empty); master == origin/master in every repo" + status: pass + - kind: command + ref: "GOWORK=off go test -count=1 ./... in sm-faq-plugin, sm-menu-plugin, sm-journal-plugin after the bump" + status: pass + +duration: 49min (wall time 17:19Z to 18:08Z, including the Task 4 and Task 7 checkpoint waits) +completed: 2026-10-15 --- -# Phase 19.3 Plan 05: unit tests, phase gate and release decision Summary +# Phase 19.3 Plan 05: unit tests, phase gate and release Summary -**Fail-closed gate `scripts/check-phase19.3.sh` requiring every new 19.3 test by name across the framework, three plugins and three Nuxt layers. Green on all six stages, Docker included. Release v0.1.27 waits on the human's decision.** +**Fail-closed gate `scripts/check-phase19.3.sh` requires every new 19.3 test by name across the framework, three plugins and three Nuxt layers. It passed on all six stages, Docker included. The phase is released as summercms v0.1.27, and the FAQ, menu and Journal plugins now require that tag on origin.** ## Checkpoint replies ### Task 4 (miniredis legitimacy check) -Reply, verbatim, recorded (commit b139651) before any go.mod change of Task 5: +The reply below was recorded verbatim (commit b139651) before any go.mod change in Task 5: > approved -Orchestrator instruction with it: install github.com/alicebob/miniredis/v2@v2.40.0 as test-only (only `_test.go` files in modules/cooler may import it). Verified after Task 5: `grep -n 'github.com/alicebob/miniredis/v2 v2.40.0' go.mod` prints line 10; `grep -rl 'alicebob/miniredis' --include='*.go' modules | grep -vc '_test.go$'` prints 0. +The orchestrator sent this instruction with it: install github.com/alicebob/miniredis/v2@v2.40.0 as a test-only dependency, so only `_test.go` files in modules/cooler may import it. Checked after Task 5: `grep -n 'github.com/alicebob/miniredis/v2 v2.40.0' go.mod` prints line 10, and `grep -rl 'alicebob/miniredis' --include='*.go' modules | grep -vc '_test.go$'` prints 0. ### Task 7 (release decision) -Pending. Proposed tag: **v0.1.27**. The reply, the tag and every pushed hash go here. +The reply below is recorded verbatim: + +> release + +The orchestrator scoped it to exactly the "release" option: + +1. Tag v0.1.27 and push master and the tag. +2. Bump the three plugins, test them and push them. +3. Push the layer test commits, with no new layer tags. +4. Push the plan 04 app commits, vue app first. + +It also set these rules: never force-push, run fetch and a divergence check before each push, deploy nothing, and leave the app's plugin submodule pointer bump out of scope. + +## Release record + +- **Tag:** `v0.1.27` is an annotated tag (object d0e39437) on summercms.go master 9921768. `git ls-remote --tags origin refs/tags/v0.1.27` prints `d0e39437b5b56ba77b82267693de189bf5d1329d` and peels to `9921768bbf0814671a89eafd45f949afcc113a11`. +- **Preflight before each push:** + - `git fetch origin --tags` ran in every repository, and nothing was behind origin. + - v0.1.27 was free on origin before tagging, and `go vet ./... && go build ./...` passed on 9921768. + - The only change since the green `--all` gate run is planning docs. +- **summercms.go:** pushed master `af9dad6..9921768`. This covers plan 04's 6f9f2e2 and 6035ccc and this plan's 619916b through 9921768. Then the tag was pushed. `git rev-parse master` equals `git rev-parse origin/master`. The final SUMMARY and state commit lands after the tag and is pushed plainly to master. +- **Plugins:** + - Each one ran `GOWORK=off go get git.golem15.com/golem15/summercms@v0.1.27` and `GOWORK=off go mod tidy`. + - The tidy added go-redis v9.23.0, otter v2.3.0, google/wire and the AWS SDK v2 modules as indirect requires. + - `GOWORK=off go vet ./...` and `GOWORK=off go test -count=1 ./...` passed in all three, Docker suites included. `go test -short ./...` also passed through the workspace. + - Pushed main: + - sm-faq-plugin `c60ae6e..fa90e83` (e117bb4, then fa90e83 "chore(19.3-05): require summercms v0.1.27"). + - sm-menu-plugin `559d96b..fe27b9a` (6c08f1a, fe27b9a). + - sm-journal-plugin `d7943fb..a99e9a1` (ebfb710, a99e9a1). + - `grep -n "git.golem15.com/golem15/summercms v0.1.27"` prints one line per go.mod: faq line 7, menu line 6, journal line 8. +- **Layers (test commits only, no new tags):** + - vue-faq-layer `e26f22e..96b6bc0` + - vue-menu-layer `3bc7729..dd0ee35` + - vue-journal-layer `3e0b377..5936f66` +- **App, vue app first:** + - vue-grzybyfunkcjonalne-app `bc143fa..0ee97d0`. + - Then sm-grzybyfunkcjonalne-app `4bab6f1..129c0df` (f9cafe2, d604509, 85939c3, 129c0df). +- **No force-push, no deploy.** ## Performance -- **Started:** 2026-10-15T17:19:19Z (first executor run; resumed after the Task 4 checkpoint) -- **Tasks:** 6 of 7 complete (Task 7 is the blocking release checkpoint) -- **Framework commits since the plan ledger:** 8 (6035ccc..8f53253) +- **Started:** 2026-10-15T17:19:19Z, across three executor runs with checkpoints at Task 4 and Task 7. +- **Completed:** 2026-10-15T18:08Z +- **Tasks:** 7 of 7 +- **Framework commits since the plan ledger:** 9 (6035ccc..9921768), measured when this SUMMARY was written. The completion commit follows. +- **Commits in other repositories:** 9 in all. Six are test commits (Task 6) and three are plugin go.mod bumps (Task 7). ## Accomplishments -- The gate has stages `--self-test`, `go`, `docker`, `plugins`, `layers` and `docs`, plus `--all`. A stage fails when a required test is missing, skipped or red. `--all` reports NOT RUN docker when no Docker daemon answers, and fails instead when PHASE193_REQUIRE_DOCKER=1. -- The cooler suites cover the memory and Redis caches and the rate-limit parity table, run through surf.MemoryStore, miniredis and real Redis. They also cover concurrency, the fallback on a Redis error, the key prefixes, Install, FromApp, and the site-cache purge on Postgres (rollback, commit, nested transactions, a 500 answer, a slow receiver and an unreachable one). -- In the plugins: the FAQ and menu `purgeSiteCache` helper tests, and the Journal's deprecated-key tests (framework keys win; alias keys deprecated or invalid; no keys). -- In the layers: the shared purge spec grows from 6 to 11 tests, byte-identical in all three layers. New ones include route-handler specs for 404, 401 and 200, the purge count and the log line, timing-safe comparison across bearer lengths, and parse edge cases. +- The gate has stages `--self-test`, `go`, `docker`, `plugins`, `layers` and `docs`, plus `--all`. + - A stage fails when a required test is missing, skipped or red. + - When no Docker daemon answers, `--all` reports docker as NOT RUN. It fails instead when PHASE193_REQUIRE_DOCKER=1. +- The cooler suites cover: + - the memory and Redis caches; + - the rate-limit parity table, run through surf.MemoryStore, miniredis and real Redis; + - concurrency, the fallback on a Redis error and the key prefixes; + - Install and FromApp; + - the site-cache purge on Postgres: rollback, commit, nested transactions, a 500 answer, a slow receiver and an unreachable one. +- In the plugins: tests for the FAQ and menu `purgeSiteCache` helpers, and for the Journal's deprecated keys (framework keys win; alias keys are deprecated or invalid; no keys). +- In the layers: the shared purge spec grows from 6 to 11 tests and is byte-identical in all three layers. The new tests cover: + - route-handler specs for 404, 401 and 200; + - the purge count and the log line; + - timing-safe comparison across bearer lengths; + - parse edge cases. +- Release: v0.1.27 is published. The three plugins on origin build against it without a sibling checkout. ## Task Commits @@ -130,6 +214,13 @@ Pending. Proposed tag: **v0.1.27**. The reply, the tag and every pushed hash go | 6 | vue-journal-layer | 5936f66 | test(19.3-05): site purge route handler specs and edge cases | | 6 | summercms.go | f57fc12 | test(19.3-05): gate plugins, layers and docs stages | | 6 | summercms.go | 8f53253 | docs(19.3-05): validation map filled, wave 0 complete | +| (docs) | summercms.go | 9921768 | docs(19.3-05): summary through Task 6 and the release sheet; state at the Task 7 checkpoint | +| 7 | summercms.go | tag v0.1.27 (d0e3943 on 9921768) | v0.1.27: cooler, bouncer cookies and Turnstile, CORS hardening and profiles, api-docs, build tags and opt-in S3, public_url, pact.ReorderAfterSave (Phase 19.3) | +| 7 | sm-faq-plugin | fa90e83 | chore(19.3-05): require summercms v0.1.27 | +| 7 | sm-menu-plugin | fe27b9a | chore(19.3-05): require summercms v0.1.27 | +| 7 | sm-journal-plugin | a99e9a1 | chore(19.3-05): require summercms v0.1.27 | + +The Task 7 pushes also carried plan 04's app commits: vue-grzybyfunkcjonalne-app 0ee97d0, then sm-grzybyfunkcjonalne-app f9cafe2, d604509, 85939c3 and 129c0df. ## Test names per repository (all required by the gate) @@ -137,7 +228,7 @@ Pending. Proposed tag: **v0.1.27**. The reply, the tag and every pushed hash go - bouncer: 17 names (TestLoadCookieConfigDefaults … TestTurnstileNeverLogsSecret). - surf: 23 names (TestCORSCredentialsWildcardRefused … TestBuildRouterNeverDials, including TestCORSOptionsMatchesLaravel). - internal/build: 4 names. - - attach: 4 names, run twice (untagged and `-tags summercms_s3`). + - attach: 4 names, run twice (untagged and with `-tags summercms_s3`). - cooler: TestMemoryCache, TestMemoryCacheTTL, TestMemoryCacheBounded, TestMemoryIncrementConcurrent, TestRememberDegrades, TestRedisCache, TestRedisFlushOnlyPrefix, TestRateLimitParity, TestRateLimitConcurrentNeverExceedsMax, TestRateLimitFallbackOnError, TestRateLimitKeyPrefix, TestInstallConfigErrors, TestInstallPingWarning, TestInstallReusesFromApp, TestFromAppLazy, TestInstallSiteCacheValidation, TestSiteCachePurgeConfig, TestSiteCachePurgeRequest, TestSiteCacheFromApp. - **summercms.go, docker stage:** - cabana: TestReorderHookRunsInTx, TestReorderHookErrorRollsBack, TestReorderWithoutHookUnchanged. @@ -145,27 +236,30 @@ Pending. Proposed tag: **v0.1.27**. The reply, the tag and every pushed hash go - cooler: TestRateLimitParityDocker, TestRedisCacheDocker, TestSiteCacheAfterCommitOnly, TestSiteCacheFailureNeverFails. - **Plugins, plugins stage:** - FAQ and menu `./controllers`: TestPurgeSiteCacheWithoutTx, TestPurgeSiteCacheWithoutPurger. - - Journal: TestSiteCacheFrameworkKeysWin, TestSiteCacheAliasKeysDeprecated, TestSiteCacheNoKeys; `./classes` TestSiteCachePurgeConfig, TestSiteCachePurgeRequest. + - Journal: TestSiteCacheFrameworkKeysWin, TestSiteCacheAliasKeysDeprecated, TestSiteCacheNoKeys; `./classes`: TestSiteCachePurgeConfig, TestSiteCachePurgeRequest. - **Plugins, docker stage:** TestFaqAdminPurgesSiteCache, TestMenuAdminPurgesSiteCache, TestCategoriesAdminPurgesSiteCache, TestPostsAdminPurgesSiteCache, TestCategoriesAdminFrameworkKeysWin. -- **Layers, layers stage:** 11 `sitePurge:` names per layer, plus `cmp` of server/lib/siteCachePurge.ts, server/api/__site__/cache/purge.post.ts and tests/sitePurge.test.ts across the three layers. +- **Layers, layers stage:** 11 `sitePurge:` names per layer, plus a `cmp` of server/lib/siteCachePurge.ts, server/api/__site__/cache/purge.post.ts and tests/sitePurge.test.ts across the three layers. ## Gate runs -Run on 2026-10-15 on a Docker host: +All runs were on 2026-10-15 on a Docker host: -- `bash scripts/check-phase19.3.sh --all`: PASS self-test, go, plugins, layers, docs, docker. "Phase 19.3 gate passed". Docker ran; it was not NOT RUN. -- `go test -count=1 -run '^TestDocsTree$' ./cmd/summer`: ok. `(cd examples/hello && go test ./...)`: ok. Result: release-gate-ok. -- Full `go test -count=1 ./...` (all Docker suites): exit 0, 41 packages ok, no FAIL lines. -- Fail-closed checks: - - Task 1: renaming TestForgetTokenCookie made the go stage exit 1 (reverted, not committed), and `nosuchstage` exits 2 with usage. - - Task 6: a planted consuming-application name in modules/cooler/redis.go made `docs` exit 1, and a one-line drift in vue-menu-layer's spec made `layers` exit 1. Both were reverted and never committed. +- `bash scripts/check-phase19.3.sh --all` passed self-test, go, plugins, layers, docs and docker, ending with "Phase 19.3 gate passed". The docker stage actually ran; it was not NOT RUN. +- `go test -count=1 -run '^TestDocsTree$' ./cmd/summer` and `(cd examples/hello && go test ./...)` both passed, giving release-gate-ok. +- A full `go test -count=1 ./...` with all Docker suites exited 0: 41 packages ok and no FAIL lines. +- Before tagging, `go vet ./... && go build ./...` passed on 9921768. +- After the bump, each plugin passed `GOWORK=off go vet ./...` and `GOWORK=off go test -count=1 ./...`, Docker included. +- Fail-closed checks (every planted break was reverted and never committed): + - Task 1: renaming TestForgetTokenCookie made the go stage exit 1, and `nosuchstage` exits 2 with a usage line. + - Task 6: a planted consuming-application name in modules/cooler/redis.go made `docs` exit 1, and a one-line drift in vue-menu-layer's spec made `layers` exit 1. ## Decisions Made - The gate reuses check-phase18.1.sh's `go test -json` detector. A skip, a missing name, no tests, zero tests or a build failure all fail the stage. -- The cooler Docker suites start one container per test (Postgres for the purge, redis:7-alpine for the rest) instead of a TestMain. Nothing starts before flag parsing, and `-short` skips them inside the test. -- The docs stage checks the lines the phase added (`git diff ^`, `.planning` excluded) for consuming-application names. The names are split in the script so it does not match itself; PHASE193_BASE overrides the base. -- Test expectation for TestStoreDiskExtension: the "js under octet-stream" row expects content_type text/javascript (from the extension when the sniff is generic, the plan 03 rule) and the disk name `.bin` (D-15). +- Each cooler Docker test starts its own container instead of sharing one through a TestMain: Postgres for the purge tests, redis:7-alpine for the rest. Nothing starts before flag parsing, and each test skips itself under `-short`. +- The docs stage scans the lines the phase added (`git diff ^`, with `.planning` excluded) for consuming-application names. The names are split in the script so the scan does not match itself, and PHASE193_BASE overrides the base. +- TestStoreDiskExtension, row "js under octet-stream": the test expects content_type text/javascript and the disk name `.bin`. The content type comes from the extension because the sniff is generic (the plan 03 rule); the disk name follows D-15. +- Release (Task 7, reply "release"): v0.1.27 is an annotated tag on master. The plugin bump commits use the subject `chore(19.3-05): require summercms v0.1.27`. The app's plugin submodule pointers stay where they are (out of scope; see Follow-ups). ## Deviations from Plan @@ -173,46 +267,47 @@ Run on 2026-10-15 on a Docker host: **1. [Rule 3 - Blocking] Task 3 verify grep could never match** - **Found during:** Task 3 -- **Issue:** `grep -q -- '^--- PASS: TestOpenBucketS3$'` cannot match because `go test -v` appends the duration. +- **Issue:** `grep -q -- '^--- PASS: TestOpenBucketS3$'` cannot match, because `go test -v` appends the duration to the line. - **Fix:** checked with `grep -qE '^--- PASS: ( |$)'` instead (T3-VERIFY-OK). The gate itself uses the JSON detector. - **Commit:** 38f6d65 **2. [Rule 3 - Blocking] Duplicate test name in the Journal test binary** - **Found during:** Task 6 -- **Issue:** plan 04 had added a Docker test `TestSiteCacheFrameworkKeysWin` in package journal_test, and the plan gives the same name to the new unit test in package journal. `-run '^TestSiteCacheFrameworkKeysWin$'` matched both, so under `-short` one skipped and the gate's skip detector failed the stage. +- **Issue:** plan 04 had added a Docker test named `TestSiteCacheFrameworkKeysWin` in package journal_test, and this plan gives the same name to the new unit test in package journal. `-run '^TestSiteCacheFrameworkKeysWin$'` matched both. Under `-short` the Docker one skipped, and the gate's skip detector failed the stage. - **Fix:** renamed the Docker test to `TestCategoriesAdminFrameworkKeysWin` (it saves a category with both key sets) and required it in the docker stage. The unit test keeps the plan's name. - **Files modified:** ../sm-journal-plugin/site_cache_admin_test.go - **Commit:** ebfb710 **3. [Discretion] Branch the plugin helper unit tests cannot reach** -- `TestPurgeSiteCacheWithoutPurger` covers a nil app, a nil app result and an app without keys. A unit test cannot reach the branch "inside a transaction, no purger": cabana has no exported constructor for a context carrying a transaction, and this plan allows no production changes. The plugins' Docker admin suites reach it. Logged in deferred-items.md. +- `TestPurgeSiteCacheWithoutPurger` covers a nil app, a nil app result and an app without keys. +- No unit test can reach the branch "inside a transaction, no purger". cabana has no exported constructor for a context carrying a transaction, and this plan allows no production changes. +- The plugins' Docker admin suites reach that branch. The gap is logged in deferred-items.md. No production code changed in this plan. ## Issues Encountered -- go-redis logs `failed to dial after 5 attempts` to stderr on each failing call against a stopped Redis. On a dead Redis, `Cache.Remember` waits for those retries (about 1.7 s) unless the caller's context has a deadline. Logged in deferred-items.md as a follow-up. The earlier follow-up, a committed test for the Redis-outage fallback of the rate-limit store, is now TestRateLimitFallbackOnError: each attempt answers from the fallback within about AttemptTimeout, with one warning naming the endpoint. -- Earlier finding (df7db6c), unchanged: S3 object metadata carries the sniffed content type, so an HTML body uploaded as note.txt is stored with Content-Type text/html. +- On each failing call against a stopped Redis, go-redis logs `failed to dial after 5 attempts` to stderr. With Redis down, `Cache.Remember` waits about 1.7 s for those retries unless the caller's context has a deadline. Logged in deferred-items.md as a follow-up. +- The earlier follow-up, a committed test for the rate-limit store's fallback during a Redis outage, is now TestRateLimitFallbackOnError. Each attempt answers from the fallback within about AttemptTimeout and logs one warning naming the endpoint. +- Earlier finding (df7db6c), unchanged: S3 object metadata carries the sniffed content type. An HTML body uploaded as note.txt is stored with Content-Type text/html. + +## Follow-ups + +- **Not done, outside the release reply's scope:** sm-grzybyfunkcjonalne-app still points its plugin submodules at the plan 04 commits: plugins/golem15/faq c60ae6e, journal d7943fb and menu 559d96b. Bumping them to fa90e83, a99e9a1 and fe27b9a (the v0.1.27 go.mod commits) is a separate app commit. It needs its own go-ahead, and then a push. +- Apps that build against ../summercms.go need `go mod tidy` once for go-redis, otter and the AWS SDK modules. sm-grzybyfunkcjonalne-app already has it (f9cafe2). +- Nothing was deployed. Manual UAT for /msd-verify-work 19.3 is still open: subdomain cookies, a real S3 bucket and a live purge. +- Left untouched in the working trees, as instructed: sm-journal-plugin/go.work.sum, sm-grzybyfunkcjonalne-app/.gsd/, and an untracked `sm-grzybyfunkcjonalne-app/sm-grzybyfunkcjonalne-app` entry inside the app checkout. It is not from this plan. ## Known Stubs None. -## Release sheet (Task 7, awaiting the human's reply) +## Next Phase Readiness -- **Proposed tag:** v0.1.27. The current latest framework tag is v0.1.26 (5c2b0e1, 2026-10-14). `git ls-remote --tags origin refs/tags/v0.1.27` prints nothing, so the tag is free. -- **Preflight:** framework paths clean. `git fetch origin --tags` done. `HEAD..origin/master` is empty. origin/master is af9dad6. -- **Public surfaces the tag publishes:** - - cooler and its keys `redis.url`, `cache.*` and `http.rate_limit.store`, plus `site_cache.purge_url` and `site_cache.purge_token`. - - `auth.cookie.*` and the bouncer cookie and Turnstile API. - - `http.cors` hardening, `http.cors_profiles` and `cors:`. - - `turnstile.*` and `http.api_docs.*`. - - summer.yaml `build.tags` and the `summercms_s3` tag. - - `storage.uploads.public_url` and `pact.ReorderAfterSave`. -- **Framework commits to push:** origin/master..HEAD, which is plan 04's 6f9f2e2 and 6035ccc plus this plan's commits from 619916b on (with the final SUMMARY commit). v0.1.26..HEAD holds the whole phase. -- **Plugin and layer commits not pushed yet** (all test-only, from this plan): sm-faq-plugin e117bb4, sm-menu-plugin 6c08f1a, sm-journal-plugin ebfb710, vue-faq-layer 96b6bc0, vue-menu-layer dd0ee35, vue-journal-layer 5936f66. The layer tags v0.2.0 and v0.4.0 from plan 04 are already on origin. -- **App commits from plan 04 Task 5 not pushed yet:** vue-grzybyfunkcjonalne-app 0ee97d0 (push first), then sm-grzybyfunkcjonalne-app f9cafe2, d604509, 85939c3 and 129c0df. -- **Plugin go.mod:** the three plugins require summercms v0.1.23 (with a local replace). After "release" they move to v0.1.27 through `GOWORK=off go get` and `go mod tidy`. -- Apps building against ../summercms.go need `go mod tidy` once for go-redis, otter and the AWS SDK modules (sm-grzybyfunkcjonalne-app already has f9cafe2). +Plan 05 is the last plan of phase 19.3, so the phase is complete. The next steps are /msd-verify-work 19.3 for manual UAT and the app's plugin pointer bump listed above. - +## Self-Check: PASSED + +- All 17 created test and gate files exist. +- All 20 listed commits are reachable from origin in their repositories: summercms.go, three plugins, three layers, the vue app and the app. +- `refs/tags/v0.1.27` on origin is d0e3943, which peels to 9921768.