From 1c2dc28588b6c804989b8e2da85523dc2cbc24e6 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Fri, 9 Oct 2026 20:18:50 +0200 Subject: [PATCH] docs(16-05): complete unit tests and phase gate plan --- .planning/ROADMAP.md | 6 +- .planning/STATE.md | 14 +- .../16-05-SUMMARY.md | 303 ++++++++++++++++++ .../deferred-items.md | 4 + 4 files changed, 319 insertions(+), 8 deletions(-) create mode 100644 .planning/phases/16-grzybyfunkcjonalne-pl-on-reusable-blog-views/16-05-SUMMARY.md diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 3064d08..7613a2b 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -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 | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index af6bcf6..12473f3 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -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 diff --git a/.planning/phases/16-grzybyfunkcjonalne-pl-on-reusable-blog-views/16-05-SUMMARY.md b/.planning/phases/16-grzybyfunkcjonalne-pl-on-reusable-blog-views/16-05-SUMMARY.md new file mode 100644 index 0000000..d61a824 --- /dev/null +++ b/.planning/phases/16-grzybyfunkcjonalne-pl-on-reusable-blog-views/16-05-SUMMARY.md @@ -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= 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 `
`; + - 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_` 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_`; 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* diff --git a/.planning/phases/16-grzybyfunkcjonalne-pl-on-reusable-blog-views/deferred-items.md b/.planning/phases/16-grzybyfunkcjonalne-pl-on-reusable-blog-views/deferred-items.md index e8c2cc7..c27d784 100644 --- a/.planning/phases/16-grzybyfunkcjonalne-pl-on-reusable-blog-views/deferred-items.md +++ b/.planning/phases/16-grzybyfunkcjonalne-pl-on-reusable-blog-views/deferred-items.md @@ -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.