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.
This commit is contained in:
2026-10-27 13:36:27 +01:00
parent 8c961f5fb5
commit 15b0d0d148

View File

@@ -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 `<automated>` 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 `<automated>` 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).