From 7c5174eea70d06b51b5bada606f3f55d4bb18355 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Sat, 10 Oct 2026 16:18:35 +0200 Subject: [PATCH] docs(16.2-06): complete unit coverage and phase gate plan --- .planning/WINDOWS.md | 34 ++- .../16.2-06-SUMMARY.md | 277 ++++++++++++++++++ 2 files changed, 308 insertions(+), 3 deletions(-) create mode 100644 .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-06-SUMMARY.md diff --git a/.planning/WINDOWS.md b/.planning/WINDOWS.md index aada926..d55e5f5 100644 --- a/.planning/WINDOWS.md +++ b/.planning/WINDOWS.md @@ -1,10 +1,10 @@ --- schema_version: 1 -open_count: 12 +open_count: 14 waived_count: 0 fixed_count: 7 -total_count: 19 -last_updated: 2026-10-10T12:04:50.783Z +total_count: 21 +last_updated: 2026-10-10T14:17:06.621Z --- # Broken Windows Ledger @@ -34,6 +34,8 @@ last_updated: 2026-10-10T12:04:50.783Z | 17 | 16.2 | unmet-truth | .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-05-SUMMARY.md | | 16.2-05 D-03 on an HTML post unproven on UAT: post 1 (HTML_POST) was not written after RESTART_TS (updated_at still 2026-10-09), so posts-unchanged passed vacuously for it; a human must re-save post 1 untouched and the SELECT be re-run | fixed | | 2026-10-10T11:35:56.721Z | 2026-10-10T12:04:50.783Z | | 18 | 16.2 | unmet-truth | .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-05-SUMMARY.md | | 16.2-05 D-19 human check pending: a one-word category edit in the Blog Editor saves without a removal notice and shows on the site; post 1 source tab shows the stored HTML unchanged | open | | 2026-10-10T11:35:56.955Z | | | 19 | 16.2 | todo | .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-05-SUMMARY.md | | 16.2-05 UAT root step: install the staging vhost with frame-src https://www.youtube-nocookie.com, nginx -t and reload; unpublish or delete test post uat-16-2-blog-editor (id 105) | open | | 2026-10-10T11:35:57.234Z | | +| 20 | 16.2 | unrun-verify | modules/cabana/field_type_postgres_test.go | | 16.2-06 TestFieldTypeSavePostgres (real-database save, show, untouched and refused update, upload in and out of scope) compiles under go vet but needs a Docker host; run bash scripts/check-phase16.2.sh postgres | open | | 2026-10-10T14:17:06.378Z | | +| 21 | 16.2 | unrun-verify | .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-06-PLAN.md | | sm-journal-plugin: 16.2-06 TestCategoriesAdminBlogEditor (categories_admin_editor_test.go) and the rewritten three-stage TestPostsAdminResaveKeepsHTML compile under go vet but need a Docker host; run bash scripts/check-phase16.2.sh postgres | open | | 2026-10-10T14:17:06.621Z | | ````json [ @@ -283,6 +285,32 @@ last_updated: 2026-10-10T12:04:50.783Z "recorded_at": "2026-10-10T11:35:57.234Z", "resolved_at": null, "milestone": "v1.0" + }, + { + "id": 20, + "kind": "unrun-verify", + "phase": "16.2", + "file": "modules/cabana/field_type_postgres_test.go", + "line": null, + "description": "16.2-06 TestFieldTypeSavePostgres (real-database save, show, untouched and refused update, upload in and out of scope) compiles under go vet but needs a Docker host; run bash scripts/check-phase16.2.sh postgres", + "status": "open", + "reason": "", + "recorded_at": "2026-10-10T14:17:06.378Z", + "resolved_at": null, + "milestone": "v1.0" + }, + { + "id": 21, + "kind": "unrun-verify", + "phase": "16.2", + "file": ".planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-06-PLAN.md", + "line": null, + "description": "sm-journal-plugin: 16.2-06 TestCategoriesAdminBlogEditor (categories_admin_editor_test.go) and the rewritten three-stage TestPostsAdminResaveKeepsHTML compile under go vet but need a Docker host; run bash scripts/check-phase16.2.sh postgres", + "status": "open", + "reason": "", + "recorded_at": "2026-10-10T14:17:06.621Z", + "resolved_at": null, + "milestone": "v1.0" } ] ```` diff --git a/.planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-06-SUMMARY.md b/.planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-06-SUMMARY.md new file mode 100644 index 0000000..80626b9 --- /dev/null +++ b/.planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-06-SUMMARY.md @@ -0,0 +1,277 @@ +--- +phase: 16.2-plugin-provided-field-types-and-the-blog-editor-formwidget +plan: 06 +subsystem: testing +tags: [unit-tests, vitest, node-test, testcontainers, phase-gate, cabana, pact, blog-editor, embeds, d-03] + +requires: + - phase: 16.2-01 + provides: pact field type API (ListValue takes ctx), cabana registry, decode, skip, load, list, writes, routes, SPA PluginField/MLPluginField and fieldTypes loader + - phase: 16.2-02 + provides: golem15-journal-blogeditor element, schema, serializer, embeds, editor corpus + - phase: 16.2-03 + provides: Journal blogeditor/mlblogeditor types, SanitizeHTMLReport, StoreMedia, posts and category hooks + - phase: 16.2-04 + provides: vue-journal-layer expandEmbeds and the four-rule sanitizer mirror + - phase: 16.2-05 + provides: UAT release (v0.1.18) plus the untagged preview pane (quick 261010-iwu) and the admin View site link +provides: + - "Full unit coverage of the phase across summercms.go, sm-journal-plugin and vue-journal-layer (lean rule 3)" + - "The imported-post resave contract (D-03) pinned at the element, PluginField, cabana, Journal Load and Postgres layers" + - "Postgres tests for a Docker host: TestFieldTypeSavePostgres, TestCategoriesAdminBlogEditor, the three-stage TestPostsAdminResaveKeepsHTML" + - "scripts/check-phase16.2.sh: fail-closed stages go, admin, editor, layer, docs, postgres with go/vitest-JSON/TAP detectors and a self-test" + - "16.2-VALIDATION.md map filled with real task IDs, nyquist_compliant and wave_0_complete true" +affects: [16.2 verify-work, v0.1.19 tag, sm-journal-plugin, vue-journal-layer] + +actuals: + tokens: 58692 + tasks: 3 + commits: 5 +plan_head_before: c07da3912b1cc4b5d112200f7af16c5ad3061d02 +plan_head_after: 7e113013a364f8e1668d0b5033e183204ec18d9f +plugin_commits_repo: ../sm-journal-plugin +plugin_head_before: 2c78211cb90e27cf8515b104613c3eac1a0aca5f +plugin_head_after: 85963b19eff80530c301454095377cde1350621a +plugin_commits: 4 +layer_commits_repo: ../vue-journal-layer +layer_head_before: 759e684e862bd8a2f34e2bbcdf258f66aeddad4f +layer_head_after: 782aa4da7d618b0d7e678421fc02dee29e5b9f54 +layer_commits: 1 +task2_start: + summercms.go: 08a2002 + sm-journal-plugin: d5a5413 + +tech-stack: + added: [] + patterns: + - "vitest JSON-reporter detector: a failed, skipped or todo test, a failed file, no passing test or a missing required file or test name fails the gate" + - "Docker-only stages are explicit: --all runs postgres only when a daemon answers and otherwise prints NOT RUN; the stage itself fails without Docker" + - "Edited-block markup compared by shape (element, sorted attributes, text), byte comparison kept for untouched blocks" + +key-files: + created: + - modules/pact/field_type_test.go + - modules/cabana/field_type_test.go + - modules/cabana/field_type_postgres_test.go + - admin/tests/app/fieldTypes.test.ts + - scripts/check-phase16.2.sh + - ../sm-journal-plugin/classes/blog_editor_test.go + - ../sm-journal-plugin/controllers/posts_editor_test.go + - ../sm-journal-plugin/categories_admin_editor_test.go + - ../sm-journal-plugin/tests/blogeditor/element.test.ts + - ../sm-journal-plugin/tests/blogeditor/schema.test.ts + - ../sm-journal-plugin/tests/blogeditor/serializer.test.ts + - ../sm-journal-plugin/tests/blogeditor/embed.test.ts + modified: + - admin/tests/form/PluginField.test.ts + - admin/tests/form/FormField.test.ts + - admin/tests/form/registry.test.ts + - admin/tests/form/formState.test.ts + - admin/tests/list/ListView.test.ts + - admin/tests/shell/AppShell.test.ts + - .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-VALIDATION.md + - .planning/WINDOWS.md + - ../sm-journal-plugin/classes/editor_policy_test.go + - ../sm-journal-plugin/classes/media_store_test.go + - ../sm-journal-plugin/posts_admin_smoke_test.go + - ../sm-journal-plugin/vite.config.ts + - ../vue-journal-layer/tests/embeds.test.ts + - ../vue-journal-layer/tests/htmlGate.test.ts + +key-decisions: + - "The Postgres resave test adapts the plan's locales to the harness: en is the host locale and pl the translation, as plan 03 already recorded" + - "check-phase16.2.sh --all runs the postgres stage only when a Docker daemon answers; without one it prints a loud NOT RUN block and still ends with 'Phase 16.2 gate passed' for the runnable stages. The postgres stage invoked directly fails without Docker, and PHASE162_REQUIRE_POSTGRES=1 makes --all fail too" + - "Edited (re-serialized) blocks are compared by element, attribute set and text rather than bytes: attribute order and the DOM's style normalization change there by design (plan 02); untouched blocks keep the byte comparison" + - "The happy-dom iframe page loading is disabled in the editor tests so no test reaches the network (T-16.2-28)" + +patterns-established: + - "A phase gate names its required tests per stage and fails on a missing one, a skip, a todo or zero tests, in Go, vitest and node:test alike" + +requirements-completed: [D-02, D-03, D-05, D-07, D-10, D-11, D-12, D-13, D-14, D-17, D-18, D-19] + +coverage: + - id: D1 + description: "Imported-post resave contract (D-03): untouched value unchanged at the element (Source tab, tab buttons, preview, reattach), PluginField never re-sets an echoed value, cabana writes and reports nothing for a served value, Journal Load serves HTML verbatim and markdown as content_html" + requirement: D-03 + verification: + - kind: unit + ref: "../sm-journal-plugin/tests/blogeditor/element.test.ts" + status: pass + - kind: unit + ref: "admin/tests/form/PluginField.test.ts#untouched value (D-03)" + status: pass + - kind: unit + ref: "modules/cabana/field_type_test.go#TestFieldTypeUntouched" + status: pass + - kind: unit + ref: "../sm-journal-plugin/classes/blog_editor_test.go#TestBlogEditorLoad" + status: pass + human_judgment: false + - id: D2 + description: "Framework coverage: pact FormFieldError, boot rules, compile, decode 422/500, localized capped notices, Load, ListValue, writes, field-types and upload routes" + requirement: D-11 + verification: + - kind: unit + ref: "bash scripts/check-phase16.2.sh go (19 named framework tests)" + status: pass + human_judgment: false + - id: D3 + description: "Journal coverage: Decode strip-and-report over the 35 payloads, notices and plural forms, LooksLikeHTML, options, ListValue, Upload sniffing and safe names, StoreMedia, policy corpus cross-check, posts hooks" + requirement: D-10 + verification: + - kind: unit + ref: "bash scripts/check-phase16.2.sh go (20 named Journal tests, 16.1 policy tests unchanged since c60abc6)" + status: pass + human_judgment: false + - id: D4 + description: "JS coverage: admin fieldTypes, registry, formState, FormField, ListView, AppShell View site; editor schema, serializer, embed, preview; layer expandEmbeds order and mirror negatives; corpus copies identical" + requirement: D-13 + verification: + - kind: unit + ref: "bash scripts/check-phase16.2.sh admin (1218 tests, 78 files)" + status: pass + - kind: unit + ref: "bash scripts/check-phase16.2.sh editor (220 tests, 7 files)" + status: pass + - kind: unit + ref: "bash scripts/check-phase16.2.sh layer (144 tests, corpus cmp)" + status: pass + human_judgment: false + - id: D5 + description: "Phase gate and validation map" + verification: + - kind: other + ref: "bash scripts/check-phase16.2.sh --self-test && bash scripts/check-phase16.2.sh --all -> Phase 16.2 gate passed" + status: pass + human_judgment: false + - id: D6 + description: "Postgres-backed suites: TestFieldTypeSavePostgres, TestPostsAdminResaveKeepsHTML (HTML, markdown, edited), TestPostsAdminSaveSanitizesHTML, TestCategoriesAdminContent, TestCategoriesAdminBlogEditor, TestJournalSVGEmbed and the rest of the testcontainers suites" + requirement: D-18 + verification: [] + human_judgment: true + rationale: "No Docker on this host (docker.sock permission denied); the tests compile under go vet and fail rather than skip here. Run bash scripts/check-phase16.2.sh postgres on a Docker host before /msd-verify-work" + +duration: 43min +completed: 2026-10-10 +status: complete +--- + +# Phase 16.2 Plan 06: Unit Coverage, Postgres Tests and Phase Gate Summary + +**Every Phase 16.2 behaviour is now pinned by a test that fails on regression: the untouched-resave contract at five layers, the framework's field type rules and routes, the Journal editor types, storage and policy cross-check, the editor element, schema, serializer and embeds, the layer's sanitize-then-expand order, and a fail-closed gate (`scripts/check-phase16.2.sh`) that passes here with the Docker-only suites reported as NOT RUN.** + +## Performance + +- **Duration:** 43 min +- **Started:** 2026-10-10T13:34:11Z +- **Completed:** 2026-10-10T14:17Z +- **Tasks:** 3 (tracer, Go coverage, JS coverage plus gate and validation map) +- **Files:** 26 test, script and planning files across three repositories (14 created, 12 modified), plus one test config (`vite.config.ts`) + +## Accomplishments + +- **Tracer (Task 1, D-03, D-07):** element.test.ts (15 cases: Source tab, tab buttons, echo, preview, reattach, a real Source edit); PluginField echo-on-connect stub; `TestFieldTypeUntouched` (served values skip Decode, writes and notices; one changed locale only; canonical JSON; create never skips); `TestBlogEditorLoad`; `TestPostsAdminResaveKeepsHTML` rewritten in three stages (HTML post, markdown post with imported content_html, edited clean save), byte comparisons without TrimSpace and no meta.notices. +- **Go (Task 2):** pact `TestFormFieldErrorMessage`, `TestFormFieldTypeContract`; cabana `TestFieldTypeRegistry`, `TestFieldTypeOptions`, `TestFieldTypeCompile`, `TestFieldTypeDecode`, `TestFieldTypeNotices`, `TestFieldTypeLoad`, `TestFieldTypeListValue`, `TestFieldTypeWrites`, `TestFieldTypesRoute`, `TestFieldUpload`; Docker `TestFieldTypeSavePostgres`. Journal `TestBlogEditorDecode`, `TestBlogEditorNotices`, `TestLooksLikeHTML`, `TestBlogEditorOptions`, `TestBlogEditorListValue`, `TestBlogEditorUpload`, `TestStoreMedia`, extended `TestEditorOutputPassesPolicy` and `TestSanitizeHTMLReport`, `TestPostsEditorHooks`, Docker `TestCategoriesAdminBlogEditor`. +- **JS (Task 3):** admin `fieldTypes.test.ts` (new) plus registry, formState, FormField, ListView and AppShell (View site: href `origin + "/"`, `_blank`, `noopener noreferrer`, en/pl label and phrasebook keys); editor `schema`, `serializer`, `embed` tests (new) next to the existing smoke, corpus and preview tests; layer embeds (order at the sinks, exact-serialization only, stable global regex, fixed src) and htmlGate (four rules accept, Go negatives stripped, corpus free of danger). +- **Gate:** `scripts/check-phase16.2.sh` with stages go, admin, editor, layer, docs, postgres, `--self-test` (go, TAP and vitest-JSON detectors plus the corpus `cmp` on planted output) and `--all`. +- **Validation map:** every row has real task IDs, commands and statuses; Docker suites are manual rows; `nyquist_compliant: true`, `wave_0_complete: true`. + +## Test counts per repository + +| Repository | Suite | Before | After | +|---|---|---|---| +| summercms.go | Go: new top-level tests in pact and cabana | — | 13 (12 run here + `TestFieldTypeSavePostgres` for Docker) | +| summercms.go | admin vitest | 1190 tests (plan 01), 77 files | 1218 tests, 78 files | +| sm-journal-plugin | Go classes/controllers new top-level tests | — | 9 (+2 extended in place) | +| sm-journal-plugin | Go root (Docker) | — | `TestCategoriesAdminBlogEditor` new, `TestPostsAdminResaveKeepsHTML` rewritten | +| sm-journal-plugin | editor vitest | 55 tests, 3 files | 220 tests, 7 files | +| vue-journal-layer | node --test | 136 | 144 | + +## Task Commits + +**summercms.go** +1. Task 1: `08a2002` test(16.2-06): pin the untouched-value skip in cabana and PluginField +2. Task 2: `3404a4b` test(16.2-06): full unit coverage of the plugin field type framework +3. Task 3: `9f5e807` test(16.2-06): admin SPA coverage of plugin field types and View site; `3da2fd6` test(16.2): phase gate; `7e11301` docs(16.2): complete the validation map + +**sm-journal-plugin** +1. Task 1: `d5a5413` test(16.2-06): pin the imported-post resave contract +2. Task 2: `da7a073` test(16.2-06): full unit coverage of the Journal Blog Editor field types +3. Task 3: `a578dda` test(16.2-06): Blog Editor schema, serializer and embed coverage; `85963b1` test(16.2-06): keep happy-dom iframe pages offline in the editor tests + +**vue-journal-layer** +3. Task 3: `782aa4d` test: pin embed expansion order and the editor policy mirror + +No fix(...) commit: no test exposed a production defect. Nothing was pushed or tagged. + +## Verification + +- Task 1 verify: element vitest 15/15, PluginField 17/17, `--- PASS: TestFieldTypeUntouched`, `--- PASS: TestBlogEditorLoad`, `go -C ../sm-journal-plugin vet ./...` clean. +- Task 2 verify: 13 of 13 named cabana tests pass, 10 of 10 named Journal classes tests pass, `TestPostsEditorHooks` passes, vet clean in both repositories; `git -C ../sm-journal-plugin diff --quiet c60abc6 -- classes/format_html_test.go classes/check_html_test.go classes/format_translation_test.go` exits 0; Task 2's diffs (`08a2002..3404a4b`, `d5a5413..da7a073`) hold only `*_test.go` files. +- Task 3 verify: admin 1218/1218, editor 220/220, layer `# fail 0` (144 pass); `check-phase16.2.sh --self-test` passes; `--all` ends with `Phase 16.2 gate passed` (go, admin, editor, layer, docs PASS; postgres NOT RUN). +- Typecheck: `vue-tsc --noEmit` (admin) and `tsc --noEmit` (plugin) clean; `check-dist.sh` and `check-admin-dist.sh` report current bundles. +- Full `go test ./...`: the only failures in summercms.go (beachcomber, bouncer, cabana, conga, lagoon, lagoon/attach, lighthouse, postcard, docs/examples/blog) and sm-journal-plugin (root, models, updates) are the testcontainers suites failing on `docker.sock: permission denied`; no other failing test line. + +## Docker-host command list (not run here) + +``` +bash scripts/check-phase16.2.sh postgres +# which runs, fail-closed: +go test -json -count=1 -timeout 15m ./modules/cabana # requires TestFieldTypeSavePostgres, TestListRelationSearchPostgres +go -C ../sm-journal-plugin test -json -count=1 -timeout 20m ./... # requires TestPostsFormCompiles, TestPostsAdminCreateSmoke, +# TestPostsAdminResaveKeepsHTML, TestPostsAdminSaveSanitizesHTML, TestCategoriesAdminContent, +# TestCategoriesAdminBlogEditor, TestJournalSVGEmbed +``` + +These cover WINDOWS entries 11, 12, 14, 15, 16, 20 and 21. + +## Decisions Made + +See key-decisions in the frontmatter. + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 2 - Test isolation] happy-dom loaded remote iframe pages in the editor tests** +- **Found during:** Task 1 (baseline run of the plugin vitest suite) +- **Issue:** The quick-task preview tests put payloads with `https://example.test/` iframes into the preview frame's srcdoc; happy-dom tried to fetch them (12 `getaddrinfo ENOTFOUND example.test` per run). The threat model (T-16.2-28) says no test reaches the network. +- **Fix:** `test.environmentOptions.happyDOM.settings.disableIframePageLoading: true` in the plugin's `vite.config.ts` (test block only; the build output is unchanged, `check-dist.sh` passes). The admin suite was checked and makes no such request. +- **Files modified:** ../sm-journal-plugin/vite.config.ts +- **Commit:** 85963b1 + +**2. [Plan text] Locales of the Postgres resave test** +- **Issue:** The plan says "pl and en ... no en translation row ... en content_html translation" with pl as host; the harness (`bootJournal`) makes en the default locale and pl the translation (as plan 03 recorded). +- **Fix:** host assertions on en; the untouched empty value and the translation assertions on pl. The untouched-empty check compares pl `content`/`content_html` presence and the translation row count before and after the PUT. +- **Commit:** d5a5413 + +**3. [Plan text] Edited-block markup compared by shape** +- **Issue:** schema tests that serialize a whole document from the model saw attribute order and style normalization differ from the source (``, `color: red;`). This is plan 02's documented behaviour for edited blocks, not a defect. +- **Fix:** those cases compare element names, sorted attributes and text; untouched blocks keep byte comparisons everywhere. +- **Commit:** a578dda + +**4. Files outside the plan's list** +- `admin/tests/shell/AppShell.test.ts` (the View site link test the orchestrator asked for), `../sm-journal-plugin/vite.config.ts` (deviation 1), `.planning/WINDOWS.md` (entries 20 and 21). + +--- + +**Total deviations:** 1 auto-fixed (test isolation) plus 2 plan-text adaptations and the listed extra files. **Impact:** no production code changed; no assertion that describes shipped behaviour was relaxed (the 16.1 policy test files are unchanged since c60abc6). + +## Issues Encountered + +- No Docker on this host: the Postgres suites compile under go vet and fail rather than skip; see the Docker-host command list. + +## Known Stubs + +None. + +## Next Phase Readiness + +- Run `bash scripts/check-phase16.2.sh postgres` on a Docker host, then /msd-verify-work 16.2 (WINDOWS 18 and 19 remain human UAT items from plan 05). +- The orchestrator tags v0.1.19 separately. +- STATE.md and ROADMAP.md updates are pending: another session holds uncommitted edits to them (see below). + +## Self-Check: PASSED + +- Created files exist: modules/pact/field_type_test.go, modules/cabana/field_type_test.go, modules/cabana/field_type_postgres_test.go, admin/tests/app/fieldTypes.test.ts, scripts/check-phase16.2.sh, ../sm-journal-plugin/classes/blog_editor_test.go, ../sm-journal-plugin/controllers/posts_editor_test.go, ../sm-journal-plugin/categories_admin_editor_test.go, ../sm-journal-plugin/tests/blogeditor/{element,schema,serializer,embed}.test.ts. +- Commits exist: summercms.go 08a2002, 3404a4b, 9f5e807, 3da2fd6, 7e11301; sm-journal-plugin d5a5413, da7a073, a578dda, 85963b1; vue-journal-layer 782aa4d.