|
|
|
|
@@ -0,0 +1,249 @@
|
|
|
|
|
---
|
|
|
|
|
phase: 11.1-summercms-documentation-for-humans-and-ai-agents
|
|
|
|
|
plan: 06
|
|
|
|
|
subsystem: docs
|
|
|
|
|
tags: [docs, tests, coverage, fixtures, gate, acceptance, validation]
|
|
|
|
|
|
|
|
|
|
requires:
|
|
|
|
|
- phase: 11.1-05
|
|
|
|
|
provides: "the acme/blog walkthrough and its tests under docs/examples/blog"
|
|
|
|
|
- phase: 11.1-02
|
|
|
|
|
provides: "the checkers, the theme, docs:serve and scripts/check-phase11.1.sh"
|
|
|
|
|
- phase: 11.1-01
|
|
|
|
|
provides: "internal/docsite (Check, Build, Sync, Pages) and the docs commands"
|
|
|
|
|
provides:
|
|
|
|
|
- "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"
|
|
|
|
|
affects: [11.2]
|
|
|
|
|
|
|
|
|
|
tech-stack:
|
|
|
|
|
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"
|
|
|
|
|
|
|
|
|
|
key-files:
|
|
|
|
|
created:
|
|
|
|
|
- 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
|
|
|
|
|
modified:
|
|
|
|
|
- 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
|
|
|
|
|
|
|
|
|
|
key-decisions:
|
|
|
|
|
- "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"
|
|
|
|
|
|
|
|
|
|
patterns-established:
|
|
|
|
|
- "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"
|
|
|
|
|
|
|
|
|
|
requirements-completed: [DOCS-01, DOCS-02, DOCS-03, DOCS-04, DOCS-05, DOCS-06, DOCS-07, DOCS-08]
|
|
|
|
|
|
|
|
|
|
estimate_ref: "tokens 120000, tasks 3, confidence low"
|
|
|
|
|
actuals:
|
|
|
|
|
tokens: 38500
|
|
|
|
|
tasks: 3
|
|
|
|
|
commits: 4
|
|
|
|
|
plan_head_before: 4c68d3186206b93e5d1c9c18ee35b3711682c938
|
|
|
|
|
plan_head_after: 9419d5d5e7600218846f3a24729c5a9645b8cbe3
|
|
|
|
|
|
|
|
|
|
coverage:
|
|
|
|
|
- id: D1
|
|
|
|
|
description: "Every checker rule has a planted fixture that must produce exactly its own problem; the clean fixture produces none"
|
|
|
|
|
requirement: DOCS-05
|
|
|
|
|
verification:
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "internal/docsite/violations_test.go#TestPlantedViolations"
|
|
|
|
|
status: pass
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "internal/docsite/violations_test.go#TestCleanFixture"
|
|
|
|
|
status: pass
|
|
|
|
|
- kind: other
|
|
|
|
|
ref: "scripts/check-phase11.1.sh --self-test"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D2
|
|
|
|
|
description: "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"
|
|
|
|
|
requirement: DOCS-02
|
|
|
|
|
verification:
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "internal/docsite/violations_test.go#TestBuildOutputGuard"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D3
|
|
|
|
|
description: "internal/docsite statement coverage is at least 85% (94.8% measured)"
|
|
|
|
|
requirement: DOCS-05
|
|
|
|
|
verification:
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "go test ./internal/docsite -count=1 -coverprofile (94.8%)"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D4
|
|
|
|
|
description: "Each ROADMAP success criterion is asserted on the real tree"
|
|
|
|
|
requirement: DOCS-01
|
|
|
|
|
verification:
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "cmd/summer/phase11_1_acceptance_test.go#TestPhase11_1Acceptance"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D5
|
|
|
|
|
description: "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"
|
|
|
|
|
requirement: DOCS-05
|
|
|
|
|
verification:
|
|
|
|
|
- kind: other
|
|
|
|
|
ref: "scripts/check-phase11.1.sh --all (phase11.1 all passed)"
|
|
|
|
|
status: pass
|
|
|
|
|
- kind: other
|
|
|
|
|
ref: "scratch copy with TestPlantedViolations renamed, TestCleanFixture removed, then skipped: --named refused each time"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D6
|
|
|
|
|
description: "Search and dark mode work in summer docs:serve"
|
|
|
|
|
verification: []
|
|
|
|
|
human_judgment: true
|
|
|
|
|
rationale: "Manual-only rows in 11.1-VALIDATION.md, left for /gsd-verify-work (no JS runner without a Node toolchain)"
|
|
|
|
|
|
|
|
|
|
duration: 29min
|
|
|
|
|
completed: 2026-10-01
|
|
|
|
|
status: 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)
|
|
|
|
|
|
|
|
|
|
**Plan metadata:** the docs(11.1-06) commit that adds this file
|
|
|
|
|
|
|
|
|
|
## 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`.
|
|
|
|
|
|
|
|
|
|
**Total deviations:** 4 auto-fixed (1 blocking, 3 bugs), each fix landed with its failing-then-passing test. **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` in 2m39s.
|
|
|
|
|
- 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 and 9419d5d are in the log.
|