From 15b0d0d148ee9af00d60f8e4c6bf62c1c29fb5e8 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Tue, 27 Oct 2026 13:36:27 +0100 Subject: [PATCH] docs(32-06): complete the validation map Every task of plans 32-01 to 32-06 with its automated command and the latest status, Wave 0 checked, nyquist_compliant and wave_0_complete true; status stays draft until the full gate is green with the demo mounted. Records the host-only TestNoTideJournalFixtures exception. --- .../phases/32-seo-foundation/32-VALIDATION.md | 103 ++++++++++++------ 1 file changed, 70 insertions(+), 33 deletions(-) diff --git a/.planning/phases/32-seo-foundation/32-VALIDATION.md b/.planning/phases/32-seo-foundation/32-VALIDATION.md index 30b59411..e9e42ba1 100644 --- a/.planning/phases/32-seo-foundation/32-VALIDATION.md +++ b/.planning/phases/32-seo-foundation/32-VALIDATION.md @@ -3,10 +3,13 @@ phase: "32" slug: "seo-foundation" # status lifecycle: draft (seeded by plan-phase) → validated (set by validate-phase §6) # audit-milestone §5.5 distinguishes NOT-VALIDATED (draft) from PARTIAL (validated + nyquist_compliant: false) (#2117) +# status stays draft until scripts/check-phase32.sh --all is green with the +# demo mounted (plan 32-06 Task 5, after the release checkpoint). status: draft -nyquist_compliant: false -wave_0_complete: false +nyquist_compliant: true +wave_0_complete: true created: "2026-10-26" +updated: "2026-10-27" --- # Phase 32 — Validation Strategy @@ -38,37 +41,71 @@ created: "2026-10-26" ## Per-Task Verification Map -Filled by the planner per task. Success-criterion map from research: +Every task of plans 32-01 to 32-06 with its automated command. Status is the latest run (plan SUMMARY or the 32-06 re-run on 2026-10-27). Checkpoint tasks have no command; their answer is recorded in the plan SUMMARY. -| Criterion | Behavior | Test Type | Automated Command | File Exists | Status | -|-----------|----------|-----------|-------------------|-------------|--------| -| SC-1 | Placement: C after A → A, C, B; before first; tab between tabs; shared anchor order; hide; span | unit | `go test -short ./modules/cabana -run 'TestFormExtension'` | ❌ W0 | ⬜ pending | -| SC-1 | Boot errors: unknown anchor, anchor outside `Requires()`, duplicate, cycle | unit | `go test -short ./modules/cabana -run 'TestFormExtensionBootErrors'` | ❌ W0 | ⬜ pending | -| SC-1 | Extension Load/Save inside the save transaction, rollback on error | integration | `go test ./modules/cabana -run 'TestFormExtensionSave'` | ❌ W0 | ⬜ pending | -| SC-1 | SPA renders compiled order | vitest | `npm --prefix admin run test -- tests/form/FormView.test.ts` | ✅ | ⬜ pending | -| SC-2 | Content descriptors optional, existing types unchanged | unit | `go test -short ./modules/signpost ./modules/pact -run 'TestContent'` | ❌ W0 | ⬜ pending | -| SC-2 | Precedence URL rule > record > global > derived, with sources | unit | `go -C ../sm-seo-plugin test -short ./classes -run TestResolverPrecedence` | ❌ W0 | ⬜ pending | -| SC-2 | SEO tab on posts, categories, tags; journal never imports sm-seo-plugin | integration + grep | `go -C ../sm-seo-plugin test ./... -run TestSEOTab`; `scripts/check-phase32.sh` | ❌ W0 | ⬜ pending | -| SC-3 | Redirect graph flatten, back-and-forth, loop refusal (exact/pattern/regex) | unit | `go -C ../sm-seo-plugin test -short ./classes -run 'TestRedirectGraph'` | ❌ W0 | ⬜ pending | -| SC-3 | Record event after commit → 301 (cabana and journal API paths) | integration | `go test ./modules/cabana -run TestRecordEvents`; `go -C ../sm-seo-plugin test ./... -run TestSlugChange301`; `go -C ../sm-journal-plugin test ./... -run TestAPIRecordEvents` | ❌ W0 | ⬜ pending | -| SC-3 | Loops refused from admin, MCP API, CSV import | integration | `go -C ../sm-seo-plugin test ./... -run 'TestLoopRefused'` | ❌ W0 | ⬜ pending | -| SC-4 | Every SEO admin operation has an MCP tool | integration | `go -C ../sm-demo-app test -tags summercms_mcp ./... -run TestSEOToolsCatalog` | ❌ W0 | ⬜ pending | -| SC-4 | Batch dry-run writes nothing; apply all-or-nothing; undo change/batch | integration | `go -C ../sm-seo-plugin test ./... -run 'TestBatch|TestUndo'` | ❌ W0 | ⬜ pending | -| SC-5 | Framework tag; consumers build against it; docs checker | gate | `scripts/check-phase32.sh --all`; `summer docs:build --check` | ❌ W0 | ⬜ pending | +| Task | Requirement | Test Type | Automated Command | Status | +|------|-------------|-----------|-------------------|--------| +| 32-01-T1 | D-91 | decision | (checkpoint: yaml-document form, answered before dispatch) | ✅ answered | +| 32-01-T2 | SC-1 | integration | `go test ./modules/cabana -run TestFormExtensionTracer -count=1`; `go vet ./... && go test -short ./...` | ✅ green | +| 32-01-T3 | SC-1, D-91, D-101 | unit + integration | `go test -short ./modules/cabana -run TestFormExtension -count=1`; `go test ./modules/cabana -run 'TestFormExtensionSave\|TestFormExtensionTracer' -count=1` | ✅ green | +| 32-01-T4 | D-90, SC-1 | docs + vitest | `go test ./cmd/summer -run TestDocsTree && go run ./cmd/summer docs:build --check`; `npm --prefix admin run test -- tests/form/FormView.test.ts`; `scripts/check-admin-openapi.sh --check` | ✅ green | +| 32-02-T1 | D-92, D-93 | decision | (checkpoint: as-planned, answered before dispatch) | ✅ answered | +| 32-02-T2 | SC-3 | integration | `go -C ../sm-journal-plugin test ./... -run TestRecordSavedDescribesNewURL -count=1` | ✅ green | +| 32-02-T3 | D-92, D-102 | integration | `go test ./modules/cabana -run TestRecordEvents -count=1`; `go -C ../sm-journal-plugin test ./... -run 'TestAPIRecordEvents\|TestRecordSavedDescribesNewURL' -count=1` | ✅ green | +| 32-02-T4 | SC-2, D-93, D-58 | unit + integration | `go test -short ./modules/signpost ./modules/pact -run TestContent -count=1`; `go -C ../sm-journal-plugin test ./... -run 'TestContentDescriptors\|TestJournalTagType\|TestTranslatedSlug' -count=1` | ✅ green | +| 32-03-T1 | SC-2 | integration | `go -C ../sm-seo-plugin test ./... -run TestSEOTabTracer -count=1` | ✅ green | +| 32-03-T2 | SC-2 | integration | `go -C ../sm-seo-plugin test ./... -run 'TestResolverPrecedence\|TestSettingsTypeTabs\|TestSEOTabPermission\|TestSEOTabTracer' -count=1` | ✅ green | +| 32-03-T3 | SC-2, SC-4 | integration | `go -C ../sm-seo-plugin test ./... -run 'TestHistoryRecordsAdminWrite\|TestEntryDeletedWithRecord\|TestGenerateEntries' -count=1` | ✅ green | +| 32-03-T4 | T-32-SC | human-verify | (checkpoint: package legitimacy, approved before dispatch) | ✅ answered | +| 32-03-T5 | SC-2, D-09 | integration + typecheck | `npm --prefix ../sm-seo-plugin run typecheck && bash ../sm-seo-plugin/scripts/check-dist.sh`; `go -C ../sm-seo-plugin test ./... -run TestSEOTab -count=1` | ✅ green | +| 32-04-T1 | SC-3 | integration | `go -C ../sm-seo-plugin test ./... -run TestSlugChange301 -count=1` | ✅ green | +| 32-04-T2 | SC-3, D-18, D-19 | integration | `go -C ../sm-seo-plugin test ./... -run 'TestRedirectEngine\|TestLoopRefused\|TestNotFoundLog\|TestAddressChangeFromEvent\|TestSlugChange301' -count=1` | ✅ green | +| 32-04-T3 | D-20a, D-20b, D-20c | integration | `go -C ../sm-seo-plugin test ./... -run 'TestNormalize\|TestStrictURL\|TestOneHop' -count=1` | ✅ green | +| 32-04-T4 | D-22, D-25 | integration + typecheck | `go -C ../sm-seo-plugin test ./... -run 'TestRobotsServed\|TestRobotsTester\|TestVerificationFile' -count=1`; `npm --prefix ../sm-seo-plugin run typecheck && bash ../sm-seo-plugin/scripts/check-dist.sh` | ✅ green | +| 32-05-T1 | SC-4 | integration | `go -C ../sm-seo-plugin test ./... -run TestMCPSetURLSeoTracer -count=1` | ✅ green | +| 32-05-T2 | SC-4, D-13, D-14 | integration | `go -C ../sm-seo-plugin test ./... -run 'TestEveryAdminOperationHasTool\|TestMCPReadToolsAreGET\|TestIssues\|TestMCPSetURLSeoTracer' -count=1` | ✅ green | +| 32-05-T3 | SC-3, SC-4, D-12, D-13 | integration | `go -C ../sm-seo-plugin test ./... -run 'TestBatch\|TestUndo\|TestLoopRefused\|TestCSVTransfer' -count=1` | ✅ green | +| 32-05-T4 | SC-4, SC-5 | gate | `bash scripts/check-phase32.sh --self-test`; `PHASE32_ALLOW_UNMOUNTED=1 bash scripts/check-phase32.sh --go --plugins --consumers --docs --marker` | ⚠️ green except `--plugins` (host-only: see below) | +| 32-06-T1 | SC-5, D-106 | gate | `bash scripts/check-phase32.sh --self-test && bash scripts/check-phase32.sh --additive --compat`; `go vet ./scripts/apisurface && go run ./scripts/apisurface modules/pact` | ⚠️ additive green; compat green with `PHASE32_SKIP_TESTS='^TestNoTideJournalFixtures$'` (host-only) | +| 32-06-T2 | SC-1, SC-2, SC-3, D-91, D-92, D-93 | unit | `go test -short ./modules/cabana ./modules/signpost -run 'TestFormExtension\|TestRecordEventDiff\|TestContent' -count=1` | ✅ green | +| 32-06-T3 | SC-2, SC-3, SC-4, D-09, D-22, D-25 | unit + vitest | `go -C ../sm-seo-plugin test -short ./classes -count=1`; `npm --prefix ../sm-seo-plugin run test`; `go -C ../sm-journal-plugin test -count=1 ./... -run 'TestContentDescriptors\|TestJournalTagType\|TestTranslatedSlug\|TestAPIRecordEvents'` | ✅ green | +| 32-06-T4 | SC-5, Q-01 | decision | (checkpoint: release, release-no-apps or hold) | ⬜ pending | +| 32-06-T5 | SC-5, SC-2, SC-4 | gate + integration | `bash scripts/check-phase32.sh --all`; `go -C ../sm-demo-app test -short -tags summercms_mcp -run 'TestGoModRequiresTags\|TestSEOTabMounted\|TestSEOToolsCatalog' -count=1 .` | ⬜ pending (after the checkpoint) | -*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky* +Success criteria map (from research): + +| Criterion | Behavior | Test Type | Automated Command | Status | +|-----------|----------|-----------|-------------------|--------| +| SC-1 | Placement: C after A → A, C, B; before first; tab between tabs; shared anchor order; hide; span | unit | `go test -short ./modules/cabana -run 'TestFormExtension'` | ✅ green | +| SC-1 | Boot errors: unknown anchor, anchor outside `Requires()`, duplicate, cycle, and every other extension refusal | unit | `go test -short ./modules/cabana -run 'TestFormExtensionBootErrors'` | ✅ green | +| SC-1 | Extension Load/Save inside the save transaction, rollback on error | integration | `go test ./modules/cabana -run 'TestFormExtensionSave'` | ✅ green | +| SC-1 | SPA renders compiled order | vitest | `npm --prefix admin run test -- tests/form/FormView.test.ts` | ✅ green | +| SC-2 | Content descriptors optional, existing types unchanged | unit | `go test -short ./modules/signpost ./modules/pact -run 'TestContent'` | ✅ green | +| SC-2 | Precedence URL rule > record > global > derived, with sources | unit + integration | `go -C ../sm-seo-plugin test -short ./classes -run TestResolverPrecedence`; `go -C ../sm-seo-plugin test . -run TestResolverPrecedence` | ✅ green | +| SC-2 | SEO tab on posts, categories, tags; journal never imports sm-seo-plugin | integration + grep | `go -C ../sm-seo-plugin test ./... -run TestSEOTab`; `scripts/check-phase32.sh --marker` | ✅ green | +| SC-3 | Redirect graph flatten, back-and-forth, loop refusal (exact/pattern/regex) | unit | `go -C ../sm-seo-plugin test -short ./classes -run 'TestRedirectGraph'` | ✅ green | +| SC-3 | Record event after commit → 301 (cabana and journal API paths) | integration | `go test ./modules/cabana -run TestRecordEvents`; `go -C ../sm-seo-plugin test ./... -run TestSlugChange301`; `go -C ../sm-journal-plugin test ./... -run TestAPIRecordEvents` | ✅ green | +| SC-3 | Loops refused from admin, MCP API, CSV import | integration | `go -C ../sm-seo-plugin test ./... -run 'TestLoopRefused'` | ✅ green | +| SC-4 | Every SEO admin operation has an MCP tool | integration | `go -C ../sm-seo-plugin test . -run TestEveryAdminOperationHasTool`; `go -C ../sm-demo-app test -tags summercms_mcp ./... -run TestSEOToolsCatalog` | ⚠️ plugin green; the demo test runs once the demo mounts the plugin (32-06 Task 5) | +| SC-4 | Batch dry-run writes nothing; apply all-or-nothing; undo change/batch | integration | `go -C ../sm-seo-plugin test ./... -run 'TestBatch\|TestUndo'` | ✅ green | +| SC-5 | Framework change strictly additive; consumers build against it | gate | `scripts/check-phase32.sh --additive --compat` | ✅ green (compat with the host-only skip) | +| SC-5 | Framework tag; demo mounted; docs checker | gate | `scripts/check-phase32.sh --all`; `summer docs:build --check` | ⬜ pending (32-06 Task 5) | + +*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ green with a recorded exception* + +**Host-only exception.** On this host `TestNoTideJournalFixtures` (sm-journal-plugin) cannot read `../fonoteka.go/parity/fixtures/mcp/mcp-oauth.yaml` (owned by another user, mode 0600). It fails the `--plugins` stage and the compat stage's Journal tests; with `PHASE32_SKIP_TESTS='^TestNoTideJournalFixtures$'` every other check of both stages passes. The file's permissions are not changed by the phase. --- ## Wave 0 Requirements -- [ ] `modules/cabana/form_extension_test.go` — placement and boot-error tables -- [ ] `modules/cabana/record_events_test.go` — after-commit and rollback (testcontainers) -- [ ] `modules/signpost` content-descriptor tests -- [ ] `../sm-seo-plugin/testmain_test.go` (`flag.Parse()` + `testing.Short()`) and a fake content plugin fixture -- [ ] `../sm-seo-plugin/package.json`, `vite.config.ts`, vitest setup -- [ ] `scripts/check-phase32.sh` modelled on `scripts/check-phase19.7.sh`, with a grep stage: no SEO identifiers under `modules/` (D-90), no consuming app named -- [ ] `journal-tag` menu item type test in sm-journal-plugin +- [x] `modules/cabana/form_extensions_test.go` (with `form_extensions_smoke_test.go`) — placement and boot-error tables +- [x] `modules/cabana/record_events_test.go` (pure diff) and `record_events_postgres_test.go` — after-commit and rollback (testcontainers) +- [x] `modules/signpost/content_test.go` — content-descriptor tests +- [x] `../sm-seo-plugin/testmain_test.go` (`flag.Parse()` + `testing.Short()`) and a fake content plugin fixture +- [x] `../sm-seo-plugin/package.json`, `vite.config.ts`, vitest setup (`tests/elements/*.test.ts`) +- [x] `scripts/check-phase32.sh` modelled on `scripts/check-phase19.7.sh`, with a grep stage: no SEO identifiers under `modules/` (D-90), no consuming app named; plus the additive and compat stages +- [x] `journal-tag` menu item type test in sm-journal-plugin (`TestJournalTagType`, `TestJournalTagTypePages`) --- @@ -84,11 +121,11 @@ Filled by the planner per task. Success-criterion map from research: ## Validation Sign-Off -- [ ] All tasks have `` verify or Wave 0 dependencies -- [ ] Sampling continuity: no 3 consecutive tasks without automated verify -- [ ] Wave 0 covers all MISSING references -- [ ] No watch-mode flags -- [ ] Feedback latency < 60s -- [ ] `nyquist_compliant: true` set in frontmatter +- [x] All tasks have `` verify or Wave 0 dependencies (checkpoint tasks excepted) +- [x] Sampling continuity: no 3 consecutive tasks without automated verify +- [x] Wave 0 covers all MISSING references +- [x] No watch-mode flags +- [x] Feedback latency < 60s (quick loop: `go test -short` in the touched repository) +- [x] `nyquist_compliant: true` set in frontmatter -**Approval:** pending +**Approval:** validation map complete; `status: validated` waits for `scripts/check-phase32.sh --all` green with the demo mounted (32-06 Task 5).