Files
summercms/.planning/phases/11.1-summercms-documentation-for-humans-and-ai-agents/11.1-06-SUMMARY.md

17 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, estimate_ref, actuals, plan_head_before, plan_head_after, coverage, duration, completed, status
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed estimate_ref actuals plan_head_before plan_head_after coverage duration completed status
11.1-summercms-documentation-for-humans-and-ai-agents 06 docs
docs
tests
coverage
fixtures
gate
acceptance
validation
phase provides
11.1-05 the acme/blog walkthrough and its tests under docs/examples/blog
phase provides
11.1-02 the checkers, the theme, docs:serve and scripts/check-phase11.1.sh
phase provides
11.1-01 internal/docsite (Check, Build, Sync, Pages) and the docs commands
internal/docsite/testdata/clean: a repository root that passes every docs check
internal/docsite/testdata/violations: 63 planted cases, one fault and a want.txt each
TestPlantedViolations, TestCleanFixture and TestBuildOutputGuard
Branch-level tests for load, render, emit, snippets, highlighting, serve and the checkers; internal/docsite at 94.8% statement coverage
TestPhase11_1Acceptance with subtests SC1 to SC5 on the real tree
scripts/check-phase11.1.sh --named and the final --all
11.1-VALIDATION.md validated
11.2
added patterns
Planted-violation corpus: a clean fixture plus per-case overlay directories whose want.txt names the rule, file and message of the one problem the plant must produce
Gate detector over go test -json: named tests must PASS; FAIL, SKIP, build failure, zero tests and no tests to run all refuse
Forbidden-name plants are assembled at run time from split literals, so no committed file names a consuming application
created modified
internal/docsite/violations_test.go
internal/docsite/testdata/clean/
internal/docsite/testdata/violations/
internal/docsite/load_test.go
internal/docsite/render_test.go
internal/docsite/emit_test.go
internal/docsite/snippet_test.go
internal/docsite/highlight_test.go
internal/docsite/serve_test.go
cmd/summer/phase11_1_acceptance_test.go
internal/docsite/checks_test.go
internal/docsite/theme_test.go
internal/docsite/docsite_test.go
internal/docsite/load.go
internal/docsite/snippet.go
internal/docsite/serve.go
cmd/summer/docs_test.go
scripts/check-phase11.1.sh
.planning/phases/11.1-summercms-documentation-for-humans-and-ai-agents/11.1-VALIDATION.md
Violation cases are overlays on testdata/clean (only the changed files plus want.txt and an optional remove.txt), not full copies: the planted fault is the whole diff of a case and the corpus stays small
A case passes only when Check reports exactly one problem with the expected rule, file and message, and Build refuses the same tree and writes nothing
Frontmatter plants that drop a page go on an unlinked page (faq.md), so the dropped page does not also break a link
--named lists the generator, CLI and walkthrough tests by name and derives the module tests from source: every TestDocs* and every Example with an output comment in a package that has example_test.go
A CRLF or BOM page stays refused, now with a message naming the encoding
New checker rule: add a testdata/violations/<case>/ overlay with its want.txt in the same change
Gate stages that run go test use go_json_named, which refuses skips, zero matches and missing names
DOCS-01
DOCS-02
DOCS-03
DOCS-04
DOCS-05
DOCS-06
DOCS-07
DOCS-08
tokens 120000, tasks 3, confidence low
tokens tasks commits
38500 3 6
4c68d31862 85ce154640
id description requirement verification human_judgment
D1 Every checker rule has a planted fixture that must produce exactly its own problem; the clean fixture produces none DOCS-05
kind ref status
unit internal/docsite/violations_test.go#TestPlantedViolations pass
kind ref status
unit internal/docsite/violations_test.go#TestCleanFixture pass
kind ref status
other scripts/check-phase11.1.sh --self-test pass
false
id description requirement verification human_judgment
D2 Build refuses an --out equal to the root, inside or containing --src, containing the root, reached through a symlink into docs/, or an unmarked non-empty directory, and leaves a sentinel untouched DOCS-02
kind ref status
unit internal/docsite/violations_test.go#TestBuildOutputGuard pass
false
id description requirement verification human_judgment
D3 internal/docsite statement coverage is at least 85% (94.8% measured) DOCS-05
kind ref status
unit go test ./internal/docsite -count=1 -coverprofile (94.8%) pass
false
id description requirement verification human_judgment
D4 Each ROADMAP success criterion is asserted on the real tree DOCS-01
kind ref status
unit cmd/summer/phase11_1_acceptance_test.go#TestPhase11_1Acceptance pass
false
id description requirement verification human_judgment
D5 The phase gate is fail-closed: --named refuses a failed, skipped, missing or renamed test and no tests to run; --all runs every stage and the full go test without -short DOCS-05
kind ref status
other scripts/check-phase11.1.sh --all (phase11.1 all passed) pass
kind ref status
other scratch copy with TestPlantedViolations renamed, TestCleanFixture removed, then skipped: --named refused each time pass
false
id description verification human_judgment rationale
D6 Search and dark mode work in summer docs:serve
true Manual-only rows in 11.1-VALIDATION.md, left for /gsd-verify-work (no JS runner without a Node toolchain)
29min 2026-10-01 complete

Phase 11.1 Plan 06: Unit tests, planted-violation corpus and final gate Summary

Every docs checker rule now has a planted fixture that must fail for its own reason, internal/docsite is at 94.8% statement coverage, one acceptance subtest per success criterion passes on the real tree, and scripts/check-phase11.1.sh --all (with the new --named stage) prints phase11.1 all passed.

Performance

  • Duration: about 29 min
  • Started: 2026-09-30T21:47:19Z
  • Completed: 2026-09-30T22:16Z
  • Tasks: 3
  • Files modified: 168 (144 of them fixture files)

Accomplishments

  • Planted-violation corpus. testdata/clean is a small root with a go.mod, three sections, four guide pages, a demo module with a README, an Example with // Output:, a Go region, a YAML region, links with anchors, commands and callouts. It passes Check, Build (6 pages) and Sync. There are 63 overlay cases under testdata/violations, covering every rule: frontmatter (13 variants), site (2), section, page, readme (2), snippet (21, including confinement, run rules, unclosed fences and the go fence without src=), identifier (5, including the ambiguous package name), link and anchor (7), command (4), callout (2) and heading (4). Five more plants are built at run time: the forbidden name in a source, the accented variant, the forbidden name reaching only the outputs, a symlink out of the root and a symlink to a dotfile.
  • Coverage. New branch tests cover strict site.yaml, frontmatter splitting (including CRLF and BOM), README ingestion, module discovery, slug IDs, link rewriting for every link class, callouts, heading anchors, the TOC threshold, exact llms.txt and llms-full.txt shapes, .md siblings, the search-index schema and its 300-rune cap, base_url prefixing, generic and grouped declarations, dedent, Sync preservation and all-or-nothing writes, every tok-* class for go, yaml, json and sh, the loopback policy, Handler branches, rebuild keeping the last good build, live watch rebuilds, the identifier index forms, the go doc fallback, command token forms and example command literals. Coverage went from 83.9% to 94.8%.
  • CLI tests. docs:build --check and docs:build print each problem and docs:build: N problems, nothing written. The tests also cover docs:sync output (up to date, updated, problems) and the docs:serve refusal.
  • Acceptance. TestPhase11_1Acceptance checks five things. SC1: the sections, the frontmatter and a sidebar entry for every module. SC2: every theme marker, the 4 assets and 8 fonts, no exec of node, npm or npx (checked with go/ast), and that docs:serve is registered. SC3: pages, .html, .md, llms.txt and llms-full.txt agree in reading order. SC4: zero problems, every go fence has src=, every Example has an output comment and every referenced directory is a root-module package. SC5: the concept map and walkthrough exist, every walkthrough go fence is a src= copy of docs/examples/blog, and go list includes the blog packages.
  • Gate. --self-test also runs the corpus through a go test -json detector. --named runs 42 docsite tests, 12 cmd/summer tests, the 11 walkthrough tests and every module TestDocs* and output Example by exact name. --all runs preconditions, deps, self-test, docs, forbidden, claude, named and go.

Task Commits

  1. Task 1: Tracer: planted fixture per rule, run by the gate: 1d38e73 (test)
  2. Task 2: Branch-level tests to 94.8% coverage, with three fixes: 28afd4d (test)
  3. Task 3: Acceptance subtests and the final gate: c1c9a9f (test); VALIDATION.md: 9419d5d (docs)
  4. Gate scratch cleanup on refusal, found in the final sweep: 85ce154 (fix)

Plan metadata: f2413f6 added this file with STATE, ROADMAP and REQUIREMENTS; a second docs(11.1-06) commit records the cleanup fix

Files Created/Modified

See key-files in the frontmatter. internal/docsite/testdata/ holds the clean fixture (13 files) and the 63 case directories.

Decisions Made

See key-decisions in the frontmatter.

Deviations from Plan

Auto-fixed Issues

1. [Rule 3 - Blocking] The gate self-test baseline failed on the current tree

  • Found during: Task 1
  • Issue: --self-test copied only docs/, modules/, go.mod and go.sum. Since plan 11.1-03 the pages show greeter:hello, a command the checker collects from examples/hello, so the unplanted scratch copy failed its baseline.
  • Fix: The scratch copy now also carries README.md and the tracked files of examples/ (via git ls-files, which skips the 41 MB of built binaries in examples/hello/bin).
  • Files modified: scripts/check-phase11.1.sh
  • Commit: 1d38e73

2. [Rule 1 - Bug] CRLF and BOM pages got a misleading frontmatter message

  • Found during: Task 2 (TestFrontmatterEncodingProblems failed first)
  • Issue: A page with CRLF line endings or a UTF-8 BOM was told it "must start with a --- frontmatter block", which it does.
  • Fix: frontmatterBlockProblem names the encoding ("the file uses CRLF line endings; save it with LF line endings", "the file starts with a UTF-8 byte order mark; save it without one"). The page is still refused.
  • Files modified: internal/docsite/load.go, internal/docsite/load_test.go
  • Commit: 28afd4d

3. [Rule 1 - Bug] src=#Type.Method missed a parenthesised receiver

  • Found during: Task 2 (TestSnippetGenericsAndGroups failed first on Box.Paren)
  • Issue: funcKey did not unwrap *ast.ParenExpr, so func (b (*Box[T])) Paren() was keyed Paren and #Box.Paren was not found. The identifier index already handled this form.
  • Fix: funcKey unwraps parentheses.
  • Files modified: internal/docsite/snippet.go, internal/docsite/snippet_test.go
  • Commit: 28afd4d

4. [Rule 1 - Bug] docs:serve could miss an edit made right after it announced itself

  • Found during: Task 2 (TestServeWatchRebuilds timed out under -race)
  • Issue: Serve printed the serving line before the watch goroutine had created its watcher and added its watches, so an early edit produced no rebuild.
  • Fix: Serve creates the watcher and adds the watches before it listens and prints; watch takes the watcher. With the fix, the serve tests pass 6 of 6 runs under -race.
  • Files modified: internal/docsite/serve.go, internal/docsite/serve_test.go
  • Commit: 28afd4d

Plan adjustments

  • Violation cases are overlays on the clean fixture rather than full copies. Each case is still one fault plus a want.txt, and the test copies the clean root and applies the overlay in t.TempDir().
  • The corpus has 63 committed cases, not the 30 listed. The planned cases are all there, plus site, page, second readme, env file, backslash, unclean path, directory, no tests, unrun function and type, unparsable Go, unclosed fence, empty path, module and root README identifiers, ambiguous package, source-file, absolute and empty links, README links, app name used as a tool command, README command and callout, and autolink heading.
  • The plan's "go doc fallback accepting a promoted member" cannot be tested as worded: go doc does not resolve promotion (plan 11.1-02 found this), and the index handles promotion itself. TestIdentifierGoDocFallback shows that the fallback accepts a declared member, caches answers and never passes a non-identifier to the argv. It also shows that a member promoted from another package is still a problem after the fallback runs.
  • testdata/violations/snippet-unparsable-go/lib/lib.go does not parse on purpose, so a repository-wide gofmt -l lists it. No gate runs gofmt, and the go tool ignores testdata.

5. [Rule 1 - Bug] The docs gate left its scratch copy in /tmp on a refusal

  • Found during: the final cleanup sweep (two 48 MB /tmp/tmp.* directories from the Task 1 baseline refusals)
  • Issue: Every stage removed its mktemp directory with a RETURN trap, but a refusal exits from inside the stage, so the trap never ran.
  • Fix: An EXIT trap removes every stage's scratch paths. The self-test now copies examples/ with tar --exclude='examples/*/bin' instead of git ls-files, so a PHASE11_1_ROOT copy without .git works. A planted refusal against a scratch copy left the /tmp/tmp.* count unchanged (29 before and after), and the two leaked directories were removed.
  • Files modified: scripts/check-phase11.1.sh
  • Commit: 85ce154

Total deviations: 5 auto-fixed (1 blocking, 4 bugs). The three Go fixes each landed with a test that failed before the fix and passed after it. Impact: none on scope.

Mutation and refusal checks (run once by hand)

  • In a scratch copy of the repository, deleting the body of the identifier checker's miss branch (checkIdentifiers) made TestPlantedViolations/identifier-unknown, identifier-unknown-member, identifier-module-readme and identifier-root-readme fail.
  • In a scratch copy with PHASE11_1_ROOT pointing at it, renaming TestPlantedViolations made --named refuse with refuse: named tests did not pass (missing, renamed or filtered out): .../internal/docsite TestPlantedViolations. Removing TestCleanFixture refused the same way, and adding t.Skip to it refused with refuse: skipped .../internal/docsite TestCleanFixture.
  • Appending a go fence without src= to docs/index.md made TestPhase11_1Acceptance fail. The file was restored with git checkout -- docs/index.md.

Issues Encountered

  • None beyond the deviations. go.work.sum, .gsd/, the summer binary and the other pre-existing untracked files were not staged. .planning/milestone.lock and .planning/state.json were left unstaged.

Verification

  • go vet ./... is clean.
  • go test ./... -count=1 (Docker) exits 0 with 35 ok packages and no FAIL line.
  • go test -race ./internal/docsite passes.
  • Coverage of go test ./internal/docsite -count=1 -coverprofile is 94.8%.
  • go test ./internal/docsite -run '^TestPlantedViolations$' -count=1 -v prints 68 --- PASS: TestPlantedViolations/ lines.
  • go test ./cmd/summer -run '^TestPhase11_1Acceptance$' -count=1 -v prints 5 --- PASS: TestPhase11_1Acceptance/SC lines.
  • scripts/check-phase11.1.sh --all prints phase11.1 all passed (2m39s, and again in 1m49s after the cleanup fix).
  • Every automated row command in 11.1-VALIDATION.md for plans 01 to 06 exits 0.
  • grep -rniE 'fonoteka|p(l|ł)ytarium' internal/docsite/testdata internal/docsite/violations_test.go finds nothing.

Known Stubs

None. The new files are tests and fixtures.

User Setup Required

None.

Next Phase Readiness

Phase 11.1 is ready for /gsd-verify-work. The two manual UAT rows (search, and dark mode across widths and without JS) are the only open items. Phase 11.2 can serve the built docs as they are, and it can reuse the --named detector pattern.

Self-Check: PASSED

All 10 key created files exist, 63 case directories are present, and commits 1d38e73, 28afd4d, c1c9a9f, 9419d5d, f2413f6 and 85ce154 are in the log.