Files
summercms/.planning/phases/11.2-ready-to-share-summercms-io-website-and-newsletter-plugin/11.2-03-SUMMARY.md

18 KiB

phase, plan, subsystem, tags, requires, provides, affects, actuals, plan_head_before, plan_head_after, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, coverage, duration, completed, status
phase plan subsystem tags requires provides affects actuals plan_head_before plan_head_after tech-stack key-files key-decisions patterns-established requirements-completed coverage duration completed status
11.2-ready-to-share-summercms-io-website-and-newsletter-plugin 03 testing
go-test
fstest
httptest
node-test
coverage
phase-gate
bash
phase provides
11.2-01 vue-summercmsio-app with terminal.json, copyPayload, activeSection and the node:test suites
phase provides
11.2-02 sm-summercmsio-plugin static handler and routes, the app's build/smoke/check-deploy scripts and terminal check, docsite site_url/site_label
table-driven tests of every static serving rule and route behaviour of the site plugin (98.2% statement coverage)
every branch of checkSiteURL, siteLabel, the site_url/site_label parsing and the option-over-yaml precedence, the escaped header, the 404 and section pages, and the CLI flags in help
ungated tests of the D-40 terminal-check helpers and the remaining scroll-spy edge case
scripts/check-phase11.2.sh, a fail-closed gate across the four repositories (framework, plugin, app, site, built, smoke, deploy, terminal, full, all)
a validated 11.2-VALIDATION.md
11.2 verify-work
cutover
11.3
tokens tasks commits commits_all_repos
16305 3 4 9
2229ca3c60 a2f2d1e5c7
added patterns
Phase gate per repository stage: go test -json through a detector that refuses a fail, a skip, a missing test, zero tests and no tests to run
Static-handler tests set r.URL.Path directly so the handler's own path cleaning is what is tested
Mutation checks in a scratch copy (plugin) or a git archive export (framework), never in the working tree
created modified
scripts/check-phase11.2.sh
../sm-summercmsio-app/plugins/golem15/summercms/static_test.go
../sm-summercmsio-app/plugins/golem15/summercms/routes_test.go
internal/docsite/load_test.go
internal/docsite/theme_test.go
cmd/summer/docs_test.go
../sm-summercmsio-app/plugins/golem15/summercms/links_test.go
../sm-summercmsio-app/terminal_check_test.go
../sm-summercmsio-app/vue-summercmsio-app/tests/scrollSpy.test.ts
.planning/phases/11.2-ready-to-share-summercms-io-website-and-newsletter-plugin/11.2-VALIDATION.md
The gate's --built stage builds in release mode only when the framework checkout build.sh uses (SUMMERCMS_FRAMEWORK, default summercms.go) has v0.1.0; with the tag deferred it runs a dev build and says so
The coexistence test reads the plugin's real patterns from surf.BuildRouter(...).Routes() and registers them on a fresh ServeMux beside literal copies of cabana's admin patterns
TestTerminalScript pins the shipped override form 'git clone <override> summercms' (11.2-02 decision), not the bare 'git clone <override>' the plan text described
TestPageLinks pins the shipped pageLinks contract: duplicates kept in document order (callers dedupe), fragment links kept, og:image appended
check-phase11.2.sh named_tests DIR PKG NAME...: per-repository go -C runs with -json and a required-PASS list; environment changes run in a subshell
id description verification human_judgment
D1 Every D-07/D-47 static serving rule of the site plugin is pinned: content types, immutable only for _nuxt (not _nuxt/builds) and _fonts, no-cache with a strong ETag elsewhere, 304, HEAD, Range, dot-segment and traversal 404s, docs 301s, redirect Locations inside /docs/ and never //, tree 404 pages, no X-Robots-Tag/CSP/X-Frame-Options
kind ref status
unit sm-summercmsio-plugin static_test.go#TestStaticSite,TestStaticDocs,TestStaticConditionalAndRange,TestStaticNoBlockingHeaders,TestStaticRedirectLocations,TestStaticMissing404Page,TestNewHandlersMissingIndex,TestContentType,TestSiteImmutable pass
kind ref status
other scripts/check-phase11.2.sh --plugin (17 named tests, coverage 98.2% >= 90.0%) pass
false
id description verification human_judgment
D2 The plugin assembles alone through surf.Assemble (GET only, POST 405, /backend falls to the site 404), fails closed on an unbuilt tree, registers via init as golem15.summercms with no admin controllers, and its patterns coexist with cabana's on one ServeMux
kind ref status
unit sm-summercmsio-plugin routes_test.go#TestRoutesAssemble,TestRoutesFailClosed,TestRoutesCoexistWithAdminPatterns,TestPluginIdentity,TestPluginEmbeddedTree pass
false
id description verification human_judgment
D3 Every branch of checkSiteURL, siteLabel, site_url/site_label parsing and option precedence; header escaping, link on index, section and 404 pages, exact unset header bytes; --site-url/--site-label in help and the label-without-URL error; docsite coverage 94.2%
kind ref status
unit internal/docsite#TestCheckSiteURL,TestSiteLabel,TestSiteURLPrecedence,TestParseSite,TestSiteLink; cmd/summer#TestDocsBuildSiteFlags,TestDocsSiteFlagsInHelp pass
kind ref status
other scripts/check-phase11.2.sh --framework (named tests, coverage >= 85.0%, check-phase11.1.sh --docs and --forbidden) pass
false
id description verification human_judgment
D4 D-40 terminal-check helpers loadTerminal, terminalScript and terminalEnv have ungated tests; the scroll-spy negative-tops edge case is covered
kind ref status
unit sm-summercmsio-app terminal_check_test.go#TestLoadTerminal,TestTerminalScript,TestTerminalEnv pass
kind ref status
unit vue-summercmsio-app tests/scrollSpy.test.ts#sections scrolled past (negative tops) still count, so the last one stays active pass
false
id description verification human_judgment
D5 scripts/check-phase11.2.sh --all runs framework, plugin, app, site, built, smoke, deploy, terminal and full, and prints phase11.2 all passed
kind ref status
e2e scripts/check-phase11.2.sh --all -> nine 'phase11.2 <stage> passed' lines, 'phase11.2 all passed', exit 0 pass
false
id description verification human_judgment
D6 11.2-VALIDATION.md is validated: per-task map filled and green, nyquist_compliant and wave_0_complete true, manual rows kept for visual UAT, rome bring-up, external links, the verbatim clone and the release build from the real tag
kind ref status
other grep 'status: validated' / 'nyquist_compliant: true' / TestExternalLinks match; grep -c '⬜ pending' = 0 pass
false
id description verification human_judgment rationale
D7 External link reachability and the verbatim terminal clone at cutover (D-38), and the release build from the real v0.1.0 tag (D-42)
true Needs the user to make golem15/summercms public and create the v0.1.0 tag; the gate has --terminal --verbatim and the release branch of --built ready for that run
13min 2026-10-01 complete

Phase 11.2 Plan 03: Unit test coverage and the phase gate Summary

Table-driven fstest tests pin every static serving and route rule of the site plugin (98.2% coverage). Every site_url/site_label branch and the D-40 helpers are tested, and one fail-closed scripts/check-phase11.2.sh --all proves the phase across the four repositories.

Performance

  • Duration: 13 min
  • Started: 2026-10-01T14:25:51Z
  • Completed: 2026-10-01T14:39:19Z
  • Tasks: 3 (tracer + 2 auto)
  • Files modified: 11 (4 in summercms.go plus VALIDATION.md, 3 in the plugin, 1 in the app, 1 in the site, plus 2 gitlinks)

Accomplishments

  • Site plugin (98.2% statement coverage, from fixtures only).
    • static_test.go covers content types, cache rules, ETag/304, HEAD, Range, dot-segment and traversal 404s, docs 301s, redirect Locations, a tree with no 404 page and the load errors.
    • routes_test.go covers the surf assembly, fail-closed boot, coexistence with the admin patterns, the plugin's identity and init registration, and the embedded tree.
    • TestPageLinks and TestResolve cover the link helpers.
  • Framework (docsite coverage 94.2%).
    • TestCheckSiteURL has 21 cases (5 accepted, 16 rejected).
    • TestSiteLabel and TestSiteURLPrecedence (12 cases) cover labels and option-over-yaml precedence. TestParseSite gains rows for blank and two-line labels.
    • TestSiteLink now checks the escaped label, the section page, the 404 page and the exact unset header bytes.
    • TestDocsSiteFlagsInHelp checks both commands' help, and docs:build --site-label without a URL now has an error test.
  • App and site.
    • TestLoadTerminal, TestTerminalScript and TestTerminalEnv run ungated.
    • One scroll-spy case was added for sections scrolled past. The other listed TS edge cases were already covered by the 11.2-01 tests.
  • Gate. scripts/check-phase11.2.sh has the stages --framework, --plugin, --app, --site, --built, --smoke, --deploy, --terminal [--verbatim], --full and --all. Unknown modes exit 2. --all passed end to end.
  • VALIDATION.md is validated, with one row per task across the three plans and the cutover checks kept as manual rows.

Task Commits

Task Commit Repo Message
1 (tracer) 549adaf sm-summercmsio-plugin test: cover every static serving rule and the plugin routes
1 (tracer) e7d9a2e sm-summercmsio-app test: bump the site plugin to its static and route tests (gitlink)
1 (tracer) 18fe100 summercms.go test(11.2): add the phase gate with the plugin stage
2 c3ddd5c vue-summercmsio-app test: cover terminal and scroll-spy edge cases
2 8c718a8 sm-summercmsio-app test: cover the terminal check helpers
2 f34c335 sm-summercmsio-app test: bump the site to its scroll-spy edge case (gitlink)
2 f5f9387 summercms.go test(11.2): cover site_url and site_label and gate the framework, app and site stages
3 29adc23 summercms.go test(11.2): complete the phase gate
3 a2f2d1e summercms.go docs(11.2): validate the phase verification map

Nothing was pushed. No commit has a co-author trailer. No v0.1.0 tag was created.

Verification Evidence

Task 1 (tracer gate). The run is interactive in end-of-phase mode and the tracer's verify is automated-only, so the verify was re-run and passed:

  • go vet is clean.
  • The plan's verify regex gives 16 top-level PASS lines.
  • TestStatic.*|TestRoutes.*|TestPlugin.* gives 47 --- PASS lines, subtests included.
  • scripts/check-phase11.2.sh --plugin passes: 17 named tests and 58 passing tests, subtests included.
  • Coverage is 98.2%.
  • bash -n is clean, and --bogus exits 2.
  • A gate copy with a renamed test refuses with "named tests did not pass (missing, renamed or filtered out)".

Task 1 mutation check (siteImmutable).

  • Setup: in a scratch copy of the plugin (GOWORK=off), siteImmutable was changed to return true for _nuxt/.
  • Result: TestStaticSite failed on /_nuxt/builds/latest.json and /_nuxt/builds/meta/x.json with Cache-Control = "public, max-age=31536000, immutable", want "no-cache".

Task 2.

  • go vet ./... is clean.
  • Eight top-level PASS lines from the plan's verify regex.
  • TestCheckSiteURL prints 21 --- PASS: TestCheckSiteURL/ lines.
  • The app helpers give three PASS lines and no SKIP.
  • --framework, --app and --site pass. The site stage had 30 tests: # pass 30, # fail 0, # skipped 0.

Task 2 mutation check (checkSiteURL).

  • Setup: in a git archive HEAD export of summercms.go with the new load_test.go, the // rejection in checkSiteURL was removed.
  • Result: TestCheckSiteURL/protocol-relative failed with checkSiteURL("//acme.example") = <nil>, want errSiteURL.

Task 3. scripts/check-phase11.2.sh --all exited 0. It printed all nine phase11.2 <stage> passed lines and phase11.2 all passed, with zero refuse:, FAIL, --- FAIL or --- SKIP lines. Stage by stage:

  • built: a dev build, because summercms.go has no v0.1.0 tag. The three build-dependent tests passed.
  • smoke: smoke: ok on postgres:15.
  • deploy: check-deploy: ok.
  • terminal: used the clone override (this checkout) and passed.
  • full: go vet ./... and go test ./... -count=1 ran with the Docker database suites.

Release branch of --built.

  • Setup: SUMMERCMS_FRAMEWORK=<scratchpad>/fw-release, the 11.2-02 scratch clone that carries a local v0.1.0 tag.
  • Result: built: v0.1.0 found …, release build, then build: bin/summercms-io (release v0.1.0) ready and phase11.2 built passed.

Plan verification.

  • All four repositories have an empty git status --porcelain. summercms.go still has the user's untracked SummerCMS landing page.zip, which predates this plan.
  • Plugin coverage is 98.2% (≥ 90.0%). Docsite coverage is 94.2% (≥ 85.0%).

Files Created/Modified

summercms.go

  • scripts/check-phase11.2.sh: the phase gate, with stages and a go test -json detector modelled on check-phase11.1.sh.
  • internal/docsite/load_test.go: TestCheckSiteURL, TestSiteLabel, TestSiteURLPrecedence and new TestParseSite rows.
  • internal/docsite/theme_test.go: TestSiteLink covers escaping, the section page, the 404 page and the exact unset bytes.
  • cmd/summer/docs_test.go: TestDocsSiteFlagsInHelp, and the label-without-URL case in TestDocsBuildSiteFlags.
  • 11.2-VALIDATION.md: validated.

sm-summercmsio-plugin

  • static_test.go and routes_test.go are new.
  • links_test.go gains TestPageLinks and TestResolve. The build-gated tests are unchanged.

sm-summercmsio-app

  • terminal_check_test.go gains the three ungated helper tests. The two gitlink bumps are in the commit table.

vue-summercmsio-app

  • tests/scrollSpy.test.ts gains the negative-tops case.

Decisions Made

See key-decisions in the frontmatter. In short:

  • --built follows the same framework checkout as build.sh.
  • The coexistence test takes the plugin's real patterns from surf's route table.
  • The tests pin the shipped terminalScript override form (git clone <override> summercms) and the shipped pageLinks contract (duplicates kept).

Deviations from Plan

Interpretation notes (no production change)

1. terminalScript override form

  • Plan text: "the first command becomes git clone /tmp/fw".
  • What was tested: the shipped behaviour from the 11.2-02 Rule 1 fix, git clone /tmp/fw summercms. The plan says to test the shipped name and behaviour.

2. pageLinks duplicates

  • Plan text: "including duplicates removed and fragment-only links kept". This is ambiguous.
  • What was tested: the shipped function keeps duplicates in document order, and TestLandingLinks dedupes. The test pins that, along with kept fragment links, decoded entities and the appended og:image.

3. Two plugin statements are not covered

  • plugin.go:48 and static.go:89 are the fs.Sub error returns.
  • fs.Sub fails only for an invalid directory name, and the names here are the constants "public", "site" and "docs", so the branches cannot be reached.
  • Coverage is 98.2% without them.

4. Extra tests beyond the plan's list

  • TestResolve in links_test.go covers the redirect follower and the SUMMERCMS_SITE_DIR override.
  • The gate requires it too.

5. Extra commits in sm-summercmsio-app

  • The gitlink bumps (e7d9a2e, f34c335) are separate commits from the app's own test commit.
  • The sequential executor instructions require committing the updated gitlink whenever a submodule changes.

Total deviations: none needed a production fix. The new tests exposed no defect, so no production code changed in any repository. There are 5 interpretation or scope notes. Impact on plan: none. All acceptance criteria pass.

Issues Encountered

  • Scratch-copy mutation setup. The first run needed GOFLAGS=-mod=mod GOPROXY=off, because the scratch module's go.sum lacked entries that the app's go.work.sum normally provides. No network was used.
  • env -u and bash functions. env -u cannot call a bash function, so the gate unsets variables in subshells. named_tests cleans up its own log.

Known Stubs

None.

Threat Flags

None. This plan adds tests and a local gate script only. The T-11.2-15 mitigation (the detector refuses a skip, a fail, a missing test or zero tests, and --bogus exits 2) and the T-11.2-16 mitigation (the gate sets SUMMERCMS_REQUIRE_BUILD=1 and SUMMERCMS_TERMINAL_CHECK=1 itself and requires PASS) are in place.

User Setup Required

None for this plan. These cutover items are unchanged from 11.2-02:

  1. Push the three site repositories.
  2. Make golem15/summercms public (D-38).
  3. Create and push v0.1.0 (D-42).
  4. Run TestExternalLinks, scripts/check-phase11.2.sh --terminal --verbatim, and --built, which will report a release build.
  5. Deploy on rome.

Next Phase Readiness

  • Phase 11.2 has all three plans complete, and the gate is green. It is ready for /gsd-verify-work, where the manual rows are visual UAT and the cutover checks.
  • Phase 11.3 can reuse TestRoutesCoexistWithAdminPatterns when it activates the admin beside the site.

Self-Check: PASSED

  • Files exist: scripts/check-phase11.2.sh, internal/docsite/load_test.go, internal/docsite/theme_test.go and cmd/summer/docs_test.go; the plugin's static_test.go, routes_test.go and links_test.go; the app's terminal_check_test.go; the site's tests/scrollSpy.test.ts; and 11.2-VALIDATION.md.
  • Commits were found in each repository:
    • summercms.go: 18fe100, f5f9387, 29adc23, a2f2d1e
    • app: e7d9a2e, 8c718a8, f34c335
    • plugin: 549adaf
    • site: c3ddd5c
  • The summercms.go commit count was measured: git rev-list --count 2229ca3..HEAD = 4.
  • git tag -l v0.1.0 in summercms.go prints nothing.

Phase: 11.2-ready-to-share-summercms-io-website-and-newsletter-plugin Completed: 2026-10-01