docs(16-05): complete unit tests and phase gate plan

This commit is contained in:
2026-10-09 20:18:50 +02:00
parent a8c65bc71a
commit 1c2dc28588
4 changed files with 319 additions and 8 deletions

View File

@@ -959,7 +959,7 @@ Plans:
3. Public pages that PHP Journal + the current theme rendered have a named successor on Go; sitemap is in if the site still needs it.
4. The new code has unit tests, delivered in the phase's last plan.
**Plans:** 4/5 plans executed
**Plans:** 5/5 plans executed
Plans:
**Wave 1**
@@ -975,7 +975,7 @@ Plans:
- [x] 16-04-PLAN.md — Staging deploy on the PHP site's server (human checkpoint) and smoke over every old URL
**Wave 5** *(blocked on Wave 4 completion)*
- [ ] 16-05-PLAN.md — Unit tests: layer and app node --test (incl. SSR), Go command and boot tests, phase gate
- [x] 16-05-PLAN.md — Unit tests: layer and app node --test (incl. SSR), Go command and boot tests, phase gate
### Phase 17: Blog companions
@@ -1125,7 +1125,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
| 14.2. Local Fonoteka frontend on local SummerCMS backend (INSERTED) | 0/TBD | Not started | - |
| 14.3. One-command app scaffolding (INSERTED) | 4/4 | In Progress| |
| 15. Journal plugin | 4/4 | Complete | 2026-10-06 |
| 16. grzybyfunkcjonalne.pl on reusable blog views | 4/5 | In Progress| |
| 16. grzybyfunkcjonalne.pl on reusable blog views | 5/5 | In Progress| |
| 17. Blog companions | 0/TBD | Not started | - |
| 18. Payment Gateway | 0/TBD | Not started | - |
| 18.1. Payment Gateway Subscriptions | 0/TBD | Not started | - |

View File

@@ -3,17 +3,17 @@ msd_state_version: "1.0"
milestone: v1.0
current_phase: 16
current_phase_name: grzybyfunkcjonalne.pl on reusable blog views
status: executing
status: verifying
stopped_at: Phase 19.1 context gathered
last_updated: "2026-10-09T18:10:21.998Z"
last_updated: "2026-10-09T18:18:13.179Z"
last_activity: 2026-10-09
last_activity_desc: Phase 16 execution started
state_head: cbb8f4c6f5a2c8e96258dde05a673c147eee7ff4
state_head: a8c65bc71a8d45839fb8c7fd49c761df2830bfd4
progress:
total_phases: 34
completed_phases: 13
total_plans: 148
completed_plans: 143
completed_plans: 144
gsd_state_version: "1.0"
milestone_name: milestone
---
@@ -31,7 +31,7 @@ See: .planning/PROJECT.md (updated 2026-09-16)
Phase: 16 (grzybyfunkcjonalne.pl on reusable blog views) — EXECUTING
Plan: 5 of 5
Status: Ready to execute
Status: Phase complete — ready for verification
Last activity: 2026-10-09 - Completed 16-04: staging deploy at uat.grzybyfunkcjonalne.pl, smoke ok (98 urls)
Progress: [██████████] 100%
@@ -198,6 +198,7 @@ Progress: [██████████] 100%
| Phase 16 P02 | 16 min | 3 tasks | 44 files |
| Phase 16 P03 | 22 min | 3 tasks | 32 files |
| Phase 16 P04 | 40min | 3 tasks | 10 files |
| Phase 16 P05 | 19 min | 3 tasks | 27 files |
## Accumulated Context
@@ -640,6 +641,9 @@ Recent decisions affecting current work:
- [Phase 16]: 16-04: staging keeps the UAT basic-auth gate (off for loopback via nginx geo); smoke and curl checks run on the server
- [Phase 16]: 16-04: staging host is uat.grzybyfunkcjonalne.pl; first-journal-post skipped in the import so Go serves the 62 live posts
- [Phase 16]: 16-04: fileblob uploads bucket uses no_tmp_dir=true because /tmp on the server is tmpfs
- [Phase 16]: No layer util needed a fix in 16-05, so vue-journal-layer gets no v0.1.1 tag; the app keeps v0.1.0
- [Phase 16]: The malformed-GA-id SSR test asserts the id appears only as the JSON string in window.__NUXT__.config, since Nuxt serializes public runtime config
- [Phase 16]: The grzyby console test harness creates an ICU pl-PL database via GRZYBY_TEST_ADMIN_DSN or testcontainers and fails, not skips, without one outside -short
### Pending Todos

View File

@@ -0,0 +1,303 @@
---
phase: 16-grzybyfunkcjonalne-pl-on-reusable-blog-views
plan: 05
subsystem: testing (Nuxt layer, site app SSR, Go host and app plugin)
tags: [node-test, tap, nuxt-ssr, go-test, testcontainers, postgres, phase-gate, validation]
status: complete
requires:
- phase: 16-01
provides: "vue-journal-layer utils (routes, client, pagination, htmlGate, sitemap, seo), i18n, testing/fixture-api.mjs and nuxt-server.mjs"
- phase: 16-02
provides: "vue-grzybyfunkcjonalne-app (PHP URL map, gaHeadScripts, menu, FAQ, fixtures and expect.txt)"
- phase: 16-03
provides: "golem15.grzyby commands (import-featured-images, import-categories), boot_test.go, check-deploy.sh"
- phase: 16-04
provides: "staging deploy proven with smoke.sh --url (98 urls)"
provides:
- "vue-journal-layer: pnpm test (node --test) over 7 util test files, 78 tests; main a4dca42 (no new tag, no runtime change)"
- "vue-grzybyfunkcjonalne-app: tests/ssr.test.ts (built server against the fixture API, 16 tests), analytics and content tests; fixture post test-niebezpieczny-wpis; main 5b10bc0"
- "sm-grzybyfunkcjonalne-app: plugins/grzyby/console tests with a fail-closed Postgres harness (GRZYBY_TEST_ADMIN_DSN or testcontainers), TestBackendURIGfadmin, TestGrzybyCommandsRegistered; master 87e5353"
- "summercms.go scripts/check-phase16.sh (--self-test, --layer, --layer-smoke, --app, --host, --plugin, --deploy, --all)"
- "16-VALIDATION.md signed off (nyquist_compliant: true, wave_0_complete: true)"
affects: [phase 16 verification, production cutover of grzybyfunkcjonalne.pl, other Golem15 blogs consuming vue-journal-layer]
actuals:
tokens: 23821 # chars/4 over added lines: host c797ab9..87e5353 (go.sum excluded), app b50c808..5b10bc0, layer 783426c..a4dca42, summercms.go c5e03f4 and a8c65bc
tasks: 3
commits: 3 # MEASURED in sm-grzybyfunkcjonalne-app: git rev-list --count c797ab9..HEAD; plus app 2, layer 1, summercms.go 2 (listed below)
commits: 3
plan_head_before: c797ab9d23e0a9e5d6862811560ab4c832a3c57c # sm-grzybyfunkcjonalne-app
plan_head_after: 87e5353ffc96d8999a4567c086eaad8b177fbad4 # sm-grzybyfunkcjonalne-app, pushed to origin/master
tech-stack:
added: ["testcontainers-go v0.44.0 and modules/postgres v0.44.0 in plugins/grzyby/go.mod (the Journal plugin's pin; test-only)"]
patterns:
- "node --test over .ts with explicit .ts imports; tests in node_modules-free utils, SSR checked through the built server"
- "App SSR test imports the layer's plain .mjs testing helpers from node_modules/vue-journal-layer/testing"
- "Go DB harness: TestMain creates one random ICU database, migrates through lagoon.Migrate + party.Activate, drops only that database, fails outside -short when no database exists"
- "Trap *gorm.DB on a closed port proves a code path makes no query"
- "Phase gate with two fail-closed detectors (go test -json and node TAP), each with a planted-input self-test"
key-files:
created:
- ../sm-grzybyfunkcjonalne-app/vue-grzybyfunkcjonalne-app/tests/ssr.test.ts
- ../sm-grzybyfunkcjonalne-app/vue-grzybyfunkcjonalne-app/tests/analytics.test.ts
- ../sm-grzybyfunkcjonalne-app/vue-grzybyfunkcjonalne-app/tests/content.test.ts
- ../vue-journal-layer/tests/routes.test.ts
- ../vue-journal-layer/tests/client.test.ts
- ../vue-journal-layer/tests/pagination.test.ts
- ../vue-journal-layer/tests/htmlGate.test.ts
- ../vue-journal-layer/tests/sitemap.test.ts
- ../vue-journal-layer/tests/seo.test.ts
- ../vue-journal-layer/tests/i18n.test.ts
- ../sm-grzybyfunkcjonalne-app/plugins/grzyby/console/testmain_test.go
- ../sm-grzybyfunkcjonalne-app/plugins/grzyby/console/import_featured_images_test.go
- ../sm-grzybyfunkcjonalne-app/plugins/grzyby/console/import_categories_test.go
- ../sm-grzybyfunkcjonalne-app/plugins/grzyby/testdata/featured/export/badania-nad-cordycepsem.json
- scripts/check-phase16.sh
modified:
- ../sm-grzybyfunkcjonalne-app/vue-grzybyfunkcjonalne-app/package.json
- ../sm-grzybyfunkcjonalne-app/vue-grzybyfunkcjonalne-app/README.md
- ../sm-grzybyfunkcjonalne-app/vue-grzybyfunkcjonalne-app/tests/fixtures/api/posts.json
- ../sm-grzybyfunkcjonalne-app/vue-grzybyfunkcjonalne-app/tests/fixtures/expect.txt
- ../vue-journal-layer/package.json
- ../vue-journal-layer/README.md
- ../sm-grzybyfunkcjonalne-app/boot_test.go
- ../sm-grzybyfunkcjonalne-app/README.md
- ../sm-grzybyfunkcjonalne-app/plugins/grzyby/go.mod
- ../sm-grzybyfunkcjonalne-app/plugins/grzyby/go.sum
- .planning/phases/16-grzybyfunkcjonalne-pl-on-reusable-blog-views/16-VALIDATION.md
- .planning/phases/16-grzybyfunkcjonalne-pl-on-reusable-blog-views/deferred-items.md
key-decisions:
- "No layer util needed a fix, so vue-journal-layer gets no v0.1.1 tag; the app keeps pinning v0.1.0 and the layer's main carries only tests"
- "The malformed-GA-id SSR case asserts the id appears only as the JSON string in window.__NUXT__.config (Nuxt serializes public runtime config) and nowhere else, instead of a literal absence of alert(1), which Nuxt makes impossible"
- "The grzyby harness creates its database with ICU pl-PL like production and fails, not skips, without GRZYBY_TEST_ADMIN_DSN or Docker outside -short"
- "The gate reads go test -json and node TAP rather than grepping -v text, and requires named tests per stage"
patterns-established:
- "Phase gate per site phase: layer, layer smoke, app (install, build, tests, smokes), host, app plugin with -race, deploy config"
requirements-completed: [SC-4]
coverage:
- id: D1
description: "The built site answers every PHP URL form with the right status, static pages beat /:category, canonical and titles keep ?page=N and the site name, pl only, empty category state, category content above the list, unsafe body blocked, XFF forwarded, feed types, sitemap entries, no forms, and GA only for a valid id (D-14, D-15, D-16, D-21, D-23, D-24, T-16-01, T-16-07)"
requirement: SC-4
verification:
- kind: integration
ref: "../sm-grzybyfunkcjonalne-app/vue-grzybyfunkcjonalne-app/tests/ssr.test.ts (pnpm build && pnpm test: 16 ssr tests pass, 0 skipped)"
status: pass
- kind: other
ref: "mutation: htmlGate isSafeJournalHtml forced true in node_modules copy, rebuild -> 'not ok 8 - T-16-01: an unsafe post body renders the blocked notice only'; restored and rebuilt -> 16/16 pass"
status: pass
human_judgment: false
- id: D2
description: "Layer util unit tests: route normalization and filling, client query building with include_empty=1 and 404 handling, pagination, the HTML gate's Go parity cases, sitemap from journal.routes, SEO values, pl/en key and placeholder parity (D-06, D-13, D-16, D-24, T-16-01)"
requirement: SC-4
verification:
- kind: unit
ref: "pnpm -C ../vue-journal-layer test -> # tests 78, # pass 78, # fail 0, # skipped 0"
status: pass
human_judgment: false
- id: D3
description: "App util and content tests: gaHeadScripts for empty, malformed and valid ids; FAQ 16 entries; MAIN_MENU kinds and label keys; every t() key in app/**/*.vue resolves (D-23, T-16-07)"
requirement: SC-4
verification:
- kind: unit
ref: "../sm-grzybyfunkcjonalne-app/vue-grzybyfunkcjonalne-app/tests/analytics.test.ts and tests/content.test.ts (pnpm test: 25 total, 25 pass)"
status: pass
human_judgment: false
- id: D4
description: "Go tests for grzyby:import-featured-images (blob at attach.BlobKey, system_files row, idempotent, base slug through the export, traversal refused before reading, failures, dry run) and grzyby:import-categories (pl preferred, content written, unchanged rerun, unknown slug, dry run) against a throwaway database (D-21, D-22, T-16-12, T-16-23)"
requirement: SC-4
verification:
- kind: unit
ref: "GRZYBY_TEST_ADMIN_DSN=<throwaway initdb cluster> go -C ../sm-grzybyfunkcjonalne-app/plugins/grzyby test ./... -count=1 -v -race -> 10 top-level --- PASS, no SKIP, no DATA RACE; database list afterwards: postgres, template0, template1"
status: pass
- kind: unit
ref: "without a DSN or Docker: FAIL with the GRZYBY_TEST_ADMIN_DSN message; with -short: 5 pure tests PASS, 5 DB tests SKIP"
status: pass
human_judgment: false
- id: D5
description: "Host boot tests: backend.uri and cabana.AdminPrefix are /gfadmin, admin routes under /gfadmin/ and none under /backend, grzyby commands registered (D-09, T-16-10)"
requirement: SC-4
verification:
- kind: unit
ref: "go -C ../sm-grzybyfunkcjonalne-app test ./... -count=1 -v -run '^(TestBootUserTranslateJournal|TestCORS|TestBackendURIGfadmin|TestGrzybyCommandsRegistered)$' -> 4 PASS"
status: pass
human_judgment: false
- id: D6
description: "Fail-closed phase gate across the three repos and the VALIDATION sign-off (T-16-24)"
requirement: SC-4
verification:
- kind: integration
ref: "bash scripts/check-phase16.sh --all -> PASS self-test, layer, layer-smoke (28 checks), app (25 tests, 36 + 2 smoke checks), host, plugin, deploy; last line 'Phase 16 gate passed'"
status: pass
human_judgment: false
- id: D7
description: "The grzyby harness's testcontainers path (postgres:16-alpine with ICU pl-PL) works where Docker is available"
verification: []
human_judgment: true
rationale: "Docker is unreachable for this user, so only the GRZYBY_TEST_ADMIN_DSN path ran; logged in deferred-items.md"
duration: 19 min
completed: 2026-10-09
---
# Phase 16 Plan 05: Unit tests and phase gate Summary
**Every piece of Phase 16 code now has automated tests. A `node --test` SSR test boots the built grzybyfunkcjonalne.pl server against the fixture Journal API and checks every PHP URL form, the locale, analytics and the HTML gate. 78 layer util tests and 9 app util/content tests run without a build. Go tests cover both grzyby import commands against a throwaway ICU database and the `/gfadmin` boot. `scripts/check-phase16.sh --all` runs everything and ends with "Phase 16 gate passed".**
## Performance
- **Duration:** 19 min
- **Started:** 2026-10-09T17:57:30Z
- **Completed:** 2026-10-09T18:16:14Z
- **Tasks:** 3 (Task 1 a tracer, re-verified before expansion)
- **Files:** 27 across four repositories (15 created, 12 modified)
## Accomplishments
- **SSR tracer (D-15, D-16, D-21, D-23, D-24, T-16-01).** `tests/ssr.test.ts` starts the layer's fixture API and `.output/server/index.mjs` and checks:
- 23 URLs for their status, including `/blog?page=0|abc|3`, `/404`, `/error`, `/rss`, `/feed`, `/en`, `/blog/tag/anything`;
- static pages over `/:category`, the `?page=2` canonical and "Strona 2" title, the post title suffix "| Grzyby Funkcjonalne";
- the empty-state copy on `/amanita-muscaria`, "Cordyceps w pigułce" before the first post card;
- the new fixture post `test-niebezpieczny-wpis`: the blocked class, no `onerror`, no `alert(1)`;
- XFF `198.51.100.9` reaching the fixture API, `include_empty=1` on every categories request;
- RSS content type, sitemap entries, no `<form>`;
- three servers for D-23: default (no gtag), `G-MLSV7WJ6W4` (loader and config call), malformed (no gtag).
- A mutation run (gate forced open in a copy of the layer in `node_modules`) made the T-16-01 case fail, so the case depends on the gate.
- **Layer util tests.** Seven files, 78 tests: `routes`, `client` (fake fetcher), `pagination`, `htmlGate` (the six Go `FormatHTML` cases plus upper case), `sitemap`, `seo`, `i18n` parity. No util needed a fix, so there is no new layer tag.
- **App util and content tests.** `analytics.test.ts` and `content.test.ts`: GA ids, 16 FAQ entries, menu kinds, and every `t()` key in the templates resolving against `pl.json` or the layer's `journal.*` strings.
- **Go tests (D-21, D-22, D-09, T-16-10, T-16-12, T-16-23).**
- `testmain_test.go` creates `grzyby_test_<hex>` with `LOCALE_PROVIDER icu ICU_LOCALE 'pl-PL'`, migrates through `lagoon.Migrate` with translate and Journal activated, and drops only that database.
- Featured images: `TestReadFeaturedImageMap`, `TestValidDiskName`, `TestFeaturedImageSourceEscape` (pure, with a trap database), `TestImportFeaturedImagesRequiresInputs`, `TestImportFeaturedImages`, `TestImportFeaturedImagesFailures`, `TestImportFeaturedImagesDryRun`.
- Categories: `TestReadCategoryMap`, `TestImportCategories`, `TestImportCategoriesDryRun`.
- Host: `TestBackendURIGfadmin`, `TestGrzybyCommandsRegistered`.
- **Gate (T-16-24).** `scripts/check-phase16.sh` has seven stages. Its two detectors (go test JSON and node TAP) each refuse planted fail, skip, todo, zero, no-tests, race and missing-name inputs in `--self-test`.
- **Validation.** 16-VALIDATION.md rows are bound to 16-01-T2 … 16-05-T3 with threat refs and are all green. Wave 0 is ticked, and `nyquist_compliant: true`.
## Task Commits
1. **Task 1 (tracer): SSR test of the built site.**
- App `269ba3d` (test), pushed.
- Host `cae7fd1` (chore: gitlink), pushed.
- Tracer gate: interactive, `end-of-phase`, automated-only verify. Re-ran `pnpm build && pnpm test` (16/16) before expanding.
2. **Task 2: layer util tests and app util/content tests.**
- Layer `a4dca42` (test), pushed to main. No tag, since there was no runtime change.
- App `5b10bc0` (test), pushed.
- Host `a60a031` (chore: gitlink), pushed.
3. **Task 3: Go tests, gate and sign-off.**
- Host `87e5353` (test: grzyby command and boot tests), pushed.
- summercms.go `c5e03f4` (test: Phase 16 gate).
- summercms.go `a8c65bc` (docs: validation sign-off).
**Plan metadata:** the docs(16-05) commit in summercms.go (this SUMMARY, deferred-items.md, STATE, ROADMAP).
## Files Created/Modified
See `key-files`. Notes:
- `tests/fixtures/api/posts.json` gains post 15, `test-niebezpieczny-wpis`. It is dated 2024-01-15 and has no category, so the homepage's latest posts, the category listings and the 2-page `/blog` stay as they were.
- `expect.txt` gains its smoke line (36 checks now).
- The host README documents `go -C plugins/grzyby test ./... -race` and `GRZYBY_TEST_ADMIN_DSN`.
## Decisions Made
See `key-decisions` in the frontmatter.
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Plan data] The malformed GA id is in the page as serialized runtime config**
- **Found during:** Task 1 (first SSR test run: `the malformed id reached the page`).
- **Issue:** Nuxt writes `runtimeConfig.public` into `window.__NUXT__.config`, so `gaId:"G-X');alert(1)//"` appears once as a double-quoted JS string literal. There, the single quote cannot end the string, so nothing executes. The plan's literal "no alert(1)" cannot hold for any public config value.
- **Fix:** The test asserts that there is no `googletagmanager`, no `gtag(`, that the id appears as `gaId:"…"` (JSON-encoded), and that `alert(1)` appears nowhere else on the page.
- **Files modified:** `tests/ssr.test.ts`.
- **Commit:** `269ba3d`.
**2. [Rule 3 - Blocking] Host boot tests need the JWT secrets**
- **Found during:** Task 3 (`TestGrzybyCommandsRegistered`: `golem15.user: jwt.secret is empty`).
- **Fix:** A `setTestSecrets` helper, used by both new tests. They load the committed config through the existing `loadCommittedConfig` copy instead of `compass.Load("config")`, so a local `.env` cannot override `backend.uri` (16-03 decision).
- **Commit:** `87e5353`.
**3. [Rule 3 - Blocking] `go mod tidy` cannot run offline for the test dependencies**
- **Issue:** Tidy wants the test dependencies of testcontainers' own dependencies (rapid, pty, objx), which are not in the module cache.
- **Fix:** I ran `go get` of the pinned versions (v0.44.0, pgx v5.10.0, gorm postgres v1.6.3, translate), then `go mod tidy -e`. `go vet` passes in `-mod=readonly`, workspace and host mode.
- **go.mod changes:** The redundant `toolchain go1.27.0` line was dropped, because the go command rejects it as an update under `-mod=readonly`.
- **Commit:** `87e5353`.
**4. [Scope addition] Extra tests beyond the behavior list**
- I added `TestImportFeaturedImagesRequiresInputs`, `TestImportFeaturedImagesFailures` (also covering base slug without export, sniff mismatch and size mismatch) and `TestImportCategoriesDryRun`.
- Layer tests cover `paginationWindow`, `isNotFound`, `encodeSlugPath`, `htmlToText` and `truncateText`.
- The SSR test also asserts `include_empty=1` on every categories request.
**5. [Plan wording] The gate parses `go test -json`, not `-v` text**
- **Issue:** The plan describes grepping `--- FAIL`, `--- SKIP` and PASS lines. The gate follows `check-phase15.sh` instead: it reads `go test -json -v` events. That is the same fail-closed contract (fail, skip, no tests to run, DATA RACE, missing named PASS) without text-format fragility.
- **Node runs:** They use a TAP detector with named tests per stage.
---
**Total deviations:** 5. That is 1 plan-data correction, 2 blocking fixes and 2 scope or wording adjustments.
**Impact on plan:** Every named artifact, test name, env var and gate line exists. No runtime code changed in any repo.
## Issues Encountered
- **Postgres.** Docker is unreachable for user `golem`, and `GRZYBY_TEST_ADMIN_DSN` was not set.
- I used the sanctioned fallback: a throwaway PostgreSQL 18.6 cluster (`initdb`, ICU pl-PL, trust auth) on 127.0.0.1:55495 in the scratchpad.
- It was passed as `GRZYBY_TEST_ADMIN_DSN` through the environment only.
- The harness needs no code override, so no repo file was touched for it.
- The cluster was stopped and deleted afterwards.
- The testcontainers path is untested here (deferred-items.md).
- **pnpm.** It ran with `TMPDIR` in the scratchpad and the project-drive store, as in 16-01..16-04.
- **summercms.go Go code.** It is unchanged by this plan, which added a shell script and docs only. I did not run `go test ./...` there, because another session has uncommitted edits in that tree.
- **Concurrent work.**
- summercms.go has another session's uncommitted `ROADMAP.md` change and untracked phase 16.1/16.2/18.1 directories. They were left alone.
- `.planning/state.json` stays unstaged.
- The host's untracked `.gsd/` was left alone.
## Known Stubs
None. The plan adds tests, fixtures and docs only.
## Threat Flags
None. No runtime surface was added.
- **T-16-23:** the harness drops only `grzyby_test_<hex>`; after the run the cluster listed only `postgres`, `template0` and `template1`.
- **T-16-SC:** testcontainers-go v0.44.0 is the only Go addition, and no npm package was added.
## User Setup Required
For the full gate on another machine:
- set `GRZYBY_TEST_ADMIN_DSN` (see 16-USER-SETUP.md and the host README), or make Docker available;
- have `nginx` and `pnpm` on the PATH.
## Next Phase Readiness
- Phase 16 is complete: all five plans have SUMMARYs, VALIDATION is signed off, and the gate passes.
- Still open for `/msd-verify-work`:
- the staging visual review (16-04 D5);
- the testcontainers run;
- the deferred items (layer XFF under swr, `cta.png` size, the framework DB-for-plugin-commands gap, the fileblob `no_tmp_dir` default).
## Self-Check: PASSED
- FOUND: all 15 created files and the 12 modified files listed in `key-files`.
- FOUND commits:
- app `269ba3d` and `5b10bc0` on origin/main;
- layer `a4dca42` on origin/main;
- host `cae7fd1`, `a60a031` and `87e5353` on origin/master;
- summercms.go `c5e03f4` and `a8c65bc`.
- Plan verification:
- layer `pnpm test` gives 78/78;
- app build plus `pnpm test` gives 25/25;
- Go plugin `-race` gives 10 PASS;
- host gives 4 PASS;
- `bash scripts/check-phase16.sh --all` ends with "Phase 16 gate passed".
---
*Phase: 16-grzybyfunkcjonalne-pl-on-reusable-blog-views*
*Completed: 2026-10-09*

View File

@@ -20,3 +20,7 @@
- **summercms.go `modules/lagoon/attach`: file buckets write temp files to `os.TempDir()`.** gocloud's fileblob creates the temp file in `/tmp` and renames it into the bucket. On a server whose `/tmp` is tmpfs (the grzybyfunkcjonalne staging server), every write fails with "invalid cross-device link". The host sets `?no_tmp_dir=true` in `config/storage.yaml` (sm-grzybyfunkcjonalne-app 6ef012e). `normalizeBucketURL` could default `no_tmp_dir` for `file://` the same way it defaults `create_dir`, so no host meets this on its first upload. Not changed here: another session owns `modules/`.
- **Visual review of staging (16-04 Task 3 human-check) is pending.** The automated checks all pass. A human still opens the staging pages with the UAT credentials and compares them with the live site (design, Polish copy, featured images, inline media). The admin password step of the original human-check no longer applies: the operator created the admin with a password piped from a file outside the deploy.
- **The plan's verify commands curl `$STAGING_URL` from the executor's machine,** but staging keeps the server's UAT basic-auth gate (operator decision), so they answer 401 from outside. They ran on the server through the loopback bypass instead (DEPLOY.md, "Smoke"). A later plan that checks staging from outside needs the credentials, or should run on the server the same way.
## From 16-05 (unit tests and phase gate)
- **The testcontainers path of the grzyby console test harness has not run.** Docker is unreachable for user `golem`, so `plugins/grzyby/console` ran through `GRZYBY_TEST_ADMIN_DSN` against a throwaway Postgres 18.6 cluster (initdb, ICU) only. Whether `postgres:16-alpine` accepts `ICU_LOCALE 'pl-PL'` in the harness's `CREATE DATABASE` is unverified. Run `go -C sm-grzybyfunkcjonalne-app/plugins/grzyby test ./... -race` once with Docker and without the DSN; if the image lacks the pl-PL ICU data, switch the harness image or drop the ICU clause for the container path.