|
|
|
|
@@ -0,0 +1,302 @@
|
|
|
|
|
---
|
|
|
|
|
phase: 11.1-summercms-documentation-for-humans-and-ai-agents
|
|
|
|
|
plan: 02
|
|
|
|
|
subsystem: docs
|
|
|
|
|
tags: [docs, checkers, goldmark, chroma, theme, search, docs-serve, gate]
|
|
|
|
|
|
|
|
|
|
requires:
|
|
|
|
|
- phase: 11.1-01
|
|
|
|
|
provides: "internal/docsite (Check, Build, Pages, slugIDs, headingIDs, snippet checks), summer docs:build and docs:sync"
|
|
|
|
|
- phase: 11-08
|
|
|
|
|
provides: "stable module READMEs for the identifier checker"
|
|
|
|
|
provides:
|
|
|
|
|
- "docsite.Commands and Options.Commands (nil is a problem, never a silent skip)"
|
|
|
|
|
- "docsite.Serve, docsite.Handler, docsite.DefaultServeAddr"
|
|
|
|
|
- "checkers: identifier, link, command, forbidden, snippet (go fence without src=), callout, heading"
|
|
|
|
|
- "chroma/v2 NodeRenderer mapping tokens onto tok-kw, tok-key, tok-str, tok-com, tok-num, tok-prompt"
|
|
|
|
|
- "UI-SPEC theme: header, sidebar, TOC, pager, footer, search dialog, icons, 404, site.css, site.js, search.js, theme-init.js, vendored fonts"
|
|
|
|
|
- "summer docs:serve (--root --src --base-url --addr --allow-remote) and cmd/summer docsCommands()"
|
|
|
|
|
- "scripts/check-phase11.1.sh with --preconditions --deps --docs --forbidden --claude --self-test --go --all"
|
|
|
|
|
- "CLAUDE.md D-13 rule naming the checkers, D-17 config-key note; wristband default todo"
|
|
|
|
|
affects: [11.1-03, 11.1-04, 11.1-05, 11.1-06, 11.2]
|
|
|
|
|
|
|
|
|
|
tech-stack:
|
|
|
|
|
added:
|
|
|
|
|
- "github.com/alecthomas/chroma/v2 v2.27.0 (direct, D-15)"
|
|
|
|
|
- "github.com/dlclark/regexp2/v2 v2.2.1 (indirect, via chroma)"
|
|
|
|
|
patterns:
|
|
|
|
|
- "Every checker reads one parse per page (parseRaw: renderer parser and slug IDs, no page context) so anchors match the rendered IDs"
|
|
|
|
|
- "Command sets are collected from the real constructors; a test keeps them in step with the generated app main"
|
|
|
|
|
- "Forbidden names are scanned in page sources before render and in every text output after render"
|
|
|
|
|
- "Theme markers are exact UI-SPEC strings asserted by TestBuildSiteMarkers; no inline script, style or on* attribute"
|
|
|
|
|
|
|
|
|
|
key-files:
|
|
|
|
|
created:
|
|
|
|
|
- internal/docsite/check_identifiers.go
|
|
|
|
|
- internal/docsite/check_links.go
|
|
|
|
|
- internal/docsite/check_commands.go
|
|
|
|
|
- internal/docsite/check_forbidden.go
|
|
|
|
|
- internal/docsite/check_policy.go
|
|
|
|
|
- internal/docsite/highlight.go
|
|
|
|
|
- internal/docsite/serve.go
|
|
|
|
|
- internal/docsite/checks_test.go
|
|
|
|
|
- internal/docsite/theme_test.go
|
|
|
|
|
- internal/docsite/theme/templates/header.html
|
|
|
|
|
- internal/docsite/theme/templates/sidebar.html
|
|
|
|
|
- internal/docsite/theme/templates/toc.html
|
|
|
|
|
- internal/docsite/theme/templates/pager.html
|
|
|
|
|
- internal/docsite/theme/templates/footer.html
|
|
|
|
|
- internal/docsite/theme/templates/search.html
|
|
|
|
|
- internal/docsite/theme/templates/icons.html
|
|
|
|
|
- internal/docsite/theme/templates/404.html
|
|
|
|
|
- internal/docsite/theme/assets/site.js
|
|
|
|
|
- internal/docsite/theme/assets/search.js
|
|
|
|
|
- internal/docsite/theme/assets/theme-init.js
|
|
|
|
|
- internal/docsite/theme/assets/LICENSE-lucide.txt
|
|
|
|
|
- internal/docsite/theme/assets/fonts/ (8 woff2 files, LICENSE-dm-sans.txt, LICENSE-dm-mono.txt)
|
|
|
|
|
- scripts/check-phase11.1.sh
|
|
|
|
|
- .planning/todos/pending/wristband-neutral-resource-default.md
|
|
|
|
|
modified:
|
|
|
|
|
- internal/docsite/docsite.go
|
|
|
|
|
- internal/docsite/load.go
|
|
|
|
|
- internal/docsite/render.go
|
|
|
|
|
- internal/docsite/emit.go
|
|
|
|
|
- internal/docsite/docsite_test.go
|
|
|
|
|
- internal/docsite/theme/templates/page.html
|
|
|
|
|
- internal/docsite/theme/assets/site.css
|
|
|
|
|
- cmd/summer/docs.go
|
|
|
|
|
- cmd/summer/docs_test.go
|
|
|
|
|
- cmd/summer/main.go
|
|
|
|
|
- cmd/summer/main_test.go
|
|
|
|
|
- go.mod
|
|
|
|
|
- go.sum
|
|
|
|
|
- README.md
|
|
|
|
|
- CLAUDE.md
|
|
|
|
|
|
|
|
|
|
key-decisions:
|
|
|
|
|
- "The identifier index resolves members promoted through types embedded in the same package; go doc does not resolve promotion, so it stays only as the fallback for anything else"
|
|
|
|
|
- "docsCommands() calls the constructors on backpack.New(&compass.Config{}) with nil plugins; they only capture the app, and nothing runs"
|
|
|
|
|
- "The forbidden-name output scan runs after a clean render; the page-source scan reports first with source file and line"
|
|
|
|
|
- "Callout types are checked in docs pages and module READMEs; the heading rule and the go-fence src= rule apply to docs/ pages only (D-18)"
|
|
|
|
|
- "Link rule for other relative repo paths applies to guide pages only; module READMEs are read on the git host first"
|
|
|
|
|
- "The drawer target is a div#sidebar wrapping the nav, and the search index URL sits on #search-results, so the UI-SPEC markers stay exact"
|
|
|
|
|
- "A pager target on the index page carries no section line"
|
|
|
|
|
|
|
|
|
|
patterns-established:
|
|
|
|
|
- "Checker problem lines follow the UI-SPEC CLI table: file:line: rule: message"
|
|
|
|
|
- "Gate self-tests copy docs/, modules/, go.mod and go.sum into a scratch root and plant one violation per rule"
|
|
|
|
|
|
|
|
|
|
requirements-completed: [DOCS-02, DOCS-04, DOCS-05, DOCS-08]
|
|
|
|
|
|
|
|
|
|
estimate_ref: "tokens 140000, tasks 3, confidence low"
|
|
|
|
|
actuals:
|
|
|
|
|
tokens: 46000
|
|
|
|
|
tasks: 3
|
|
|
|
|
commits: 4
|
|
|
|
|
plan_head_before: 9dcc10177609f22ac535d4dd9972d55f7037e6b8
|
|
|
|
|
plan_head_after: dd11bdb0c7443b69cb1df3df4574fa6a8024cdb8
|
|
|
|
|
|
|
|
|
|
coverage:
|
|
|
|
|
- id: D1
|
|
|
|
|
description: "A stale pkg.Ident span in a docs page, module README or the root README fails go test, docs:build and the gate"
|
|
|
|
|
requirement: DOCS-05
|
|
|
|
|
verification:
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "internal/docsite/checks_test.go#TestIdentifierChecker"
|
|
|
|
|
status: pass
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "cmd/summer/docs_test.go#TestDocsTree"
|
|
|
|
|
status: pass
|
|
|
|
|
- kind: other
|
|
|
|
|
ref: "scripts/check-phase11.1.sh --self-test (bonfire.NoSuchThing plant); go run ./cmd/summer docs:build --check --src <scratch> with lighthouse.NoSuchThing"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D2
|
|
|
|
|
description: "Broken relative links and anchors fail with link: problems computed from the renderer's heading IDs"
|
|
|
|
|
requirement: DOCS-05
|
|
|
|
|
verification:
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "internal/docsite/checks_test.go#TestLinkChecker"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D3
|
|
|
|
|
description: "summer and ./bin/<app> command names are checked against sets collected from the real constructors and example bonfire.Command literals"
|
|
|
|
|
requirement: DOCS-05
|
|
|
|
|
verification:
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "internal/docsite/checks_test.go#TestCommandChecker"
|
|
|
|
|
status: pass
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "cmd/summer/docs_test.go#TestDocsCommandNames"
|
|
|
|
|
status: pass
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "cmd/summer/docs_test.go#TestDocsCommandsMirrorGeneratedMain"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D4
|
|
|
|
|
description: "Consuming-application names fail in sources and outputs without echoing the match"
|
|
|
|
|
requirement: DOCS-05
|
|
|
|
|
verification:
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "internal/docsite/checks_test.go#TestForbiddenChecker"
|
|
|
|
|
status: pass
|
|
|
|
|
- kind: other
|
|
|
|
|
ref: "scripts/check-phase11.1.sh --forbidden and --self-test"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D5
|
|
|
|
|
description: "Go fences in docs/ pages need src=; unknown callouts and non-plain docs/ headings fail"
|
|
|
|
|
requirement: DOCS-04
|
|
|
|
|
verification:
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "internal/docsite/checks_test.go#TestFencePolicy"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D6
|
|
|
|
|
description: "The built site has the UI-SPEC shell, chroma highlighting, 404 page, pager edge cases and no inline script/style/handler"
|
|
|
|
|
requirement: DOCS-02
|
|
|
|
|
verification:
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "internal/docsite/theme_test.go#TestBuildSiteMarkers"
|
|
|
|
|
status: pass
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "cmd/summer/docs_test.go#TestDocsBuildRealTree"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D7
|
|
|
|
|
description: "docs:serve serves on loopback, refuses non-loopback without --allow-remote, returns 404.html with 404 and never a dot-file"
|
|
|
|
|
requirement: DOCS-02
|
|
|
|
|
verification:
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "internal/docsite/theme_test.go#TestServeHandler"
|
|
|
|
|
status: pass
|
|
|
|
|
- kind: unit
|
|
|
|
|
ref: "internal/docsite/theme_test.go#TestServeRefusesNonLoopback"
|
|
|
|
|
status: pass
|
|
|
|
|
- kind: other
|
|
|
|
|
ref: "manual smoke: summer docs:serve on 127.0.0.1, edit rebuilds, a planted problem keeps the previous build"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D8
|
|
|
|
|
description: "CLAUDE.md records D-13, names the checkers and notes deferred config-key checking"
|
|
|
|
|
requirement: DOCS-08
|
|
|
|
|
verification:
|
|
|
|
|
- kind: other
|
|
|
|
|
ref: "scripts/check-phase11.1.sh --claude"
|
|
|
|
|
status: pass
|
|
|
|
|
human_judgment: false
|
|
|
|
|
- id: D9
|
|
|
|
|
description: "Search rows, arrow keys and Enter; no theme flash in all three modes; contrast at 1280/1024/375px; no-JS layout"
|
|
|
|
|
verification: []
|
|
|
|
|
human_judgment: true
|
|
|
|
|
rationale: "Backstop truths in the plan: manual UAT via summer docs:serve (no JS runner without Node). Headless Chromium screenshots at 1400px and 800px in light and dark looked right, but that is not the UAT."
|
|
|
|
|
|
|
|
|
|
duration: 30min
|
|
|
|
|
completed: 2026-09-30
|
|
|
|
|
status: complete
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# Phase 11.1 Plan 02: Docs accuracy gates, theme and docs:serve Summary
|
|
|
|
|
|
|
|
|
|
**Every D-11/D-12 rule now fails `go test` and `docs:build`: stale identifiers, broken links and anchors, unknown commands, consuming-application names, go fences without `src=`, unknown callouts and non-plain headings. The site has the full UI-SPEC WinterCMS-style theme with chroma/v2 highlighting, client-side search, a three-way theme toggle and `summer docs:serve`, and `scripts/check-phase11.1.sh` checks all of it.**
|
|
|
|
|
|
|
|
|
|
## Performance
|
|
|
|
|
|
|
|
|
|
- **Duration:** about 30 min
|
|
|
|
|
- **Started:** 2026-09-30T19:29Z
|
|
|
|
|
- **Completed:** 2026-09-30T19:59Z
|
|
|
|
|
- **Tasks:** 3
|
|
|
|
|
- **Files modified:** 53 (38 without fonts and licences)
|
|
|
|
|
|
|
|
|
|
## Accomplishments
|
|
|
|
|
|
|
|
|
|
- `check_identifiers.go` uses `go/parser` to index every package under `modules/`, sub-packages included. It records funcs, types, consts, vars, methods (generic receivers stripped), fields, embedded types and interface methods, and resolves promoted members. On the real tree it checks 1,268 module spans across 24 pages and the root README with 0 misses.
|
|
|
|
|
- Links and anchors are checked against the heading IDs the renderer produces. Command names come from `toolCommands()` and the constructors the generated main calls (plus `lagoon.KeyGenerateCommand`, `centrifugo.Commands` and `flare.Commands`). Example `bonfire.Command` literals under `docs/examples` and `examples` are parsed, never imported.
|
|
|
|
|
- Consuming-application names are rejected in page sources and in every text output. The problem line never repeats the matched word.
|
|
|
|
|
- Theme: header (wordmark, search trigger with `<kbd>`, theme toggle, Menu), grouped sidebar with API items in DM Mono, TOC column and `toc-inline` (only with 2 or more H2/H3), eyebrow/lead/page actions, callouts, heading permalinks, pager (first page Next only, last page Previous only, section line only across sections), footer with llms links, `404.html`, and 15 inline Lucide icons. DM Sans and DM Mono are vendored with their licences. Nothing loads from a third-party origin.
|
|
|
|
|
- `highlight.go` maps chroma tokens onto the UI-SPEC classes. Shell fences get `tok-prompt` for `$ ` (excluded from copy) and `tok-kw` for the command word.
|
|
|
|
|
- `search.js` loads `search-index.json` on first open. It uses AND-token matching ranked title over heading over text, shows up to 20 rows built with `createElement`/`textContent` and `<mark>` elements, and implements every UI-SPEC state message and live-region count.
|
|
|
|
|
- `summer docs:serve` builds into a temporary directory, serves on `127.0.0.1:8088` by default and refuses any non-loopback address without `--allow-remote`. It returns `404.html` with status 404, never serves dot-files, and rebuilds on change while keeping the last good build.
|
|
|
|
|
- The gate self-test plants 9 violations (identifier, missing README, drifted snippet, frontmatter typo, broken anchor, unknown command, forbidden name, go fence without `src=`, `[!DANGER]`) and each one is refused under its own rule.
|
|
|
|
|
|
|
|
|
|
## Task Commits
|
|
|
|
|
|
|
|
|
|
1. **Task 1: Identifier checker tracer through go test, docs:build and the gate:** `f460529` (feat)
|
|
|
|
|
2. **Task 2: Links, commands, forbidden names, fence policy:** `5d4c1e3` (feat). The docs-rules change was committed separately as `d89e18b` (docs: CLAUDE.md and the wristband todo)
|
|
|
|
|
3. **Task 3: Theme, chroma, search, dark mode, docs:serve:** `dd11bdb` (feat)
|
|
|
|
|
|
|
|
|
|
**Plan metadata:** the docs(11.1-02) commit that adds this file
|
|
|
|
|
|
|
|
|
|
## Files Created/Modified
|
|
|
|
|
|
|
|
|
|
See `key-files` in the frontmatter. The main ones:
|
|
|
|
|
- `internal/docsite/check_*.go`: the five checker files
|
|
|
|
|
- `internal/docsite/highlight.go`: the fence NodeRenderer and chroma mapping. It moved out of render.go
|
|
|
|
|
- `internal/docsite/render.go`: heading permalinks, the callout transformer and renderer, `parseRaw`
|
|
|
|
|
- `internal/docsite/emit.go`: the page view (eyebrow, TOC, pager, edit and Markdown links) and `404.html`
|
|
|
|
|
- `internal/docsite/serve.go`: `Serve`, `Handler` and the loopback check
|
|
|
|
|
- `cmd/summer/docs.go`: `docsCommands()` and `docs:serve`
|
|
|
|
|
|
|
|
|
|
## Decisions Made
|
|
|
|
|
|
|
|
|
|
See `key-decisions` in the frontmatter.
|
|
|
|
|
|
|
|
|
|
## Deviations from Plan
|
|
|
|
|
|
|
|
|
|
### Auto-fixed Issues
|
|
|
|
|
|
|
|
|
|
**1. [Rule 1 - Bug] `go doc` does not resolve promoted members**
|
|
|
|
|
- **Found during:** Task 1
|
|
|
|
|
- **Issue:** The plan relied on the `go doc` fallback to accept members promoted through embedding. `go doc ./modules/x Bus.ID` exits 1 for a field or method promoted from an embedded type.
|
|
|
|
|
- **Fix:** The index records the embedded types of each type and follows them within the package. `go doc` remains the fallback for any other miss.
|
|
|
|
|
- **Files modified:** internal/docsite/check_identifiers.go, internal/docsite/checks_test.go
|
|
|
|
|
- **Commit:** f460529
|
|
|
|
|
|
|
|
|
|
**2. [Rule 3 - Blocking] The exact UI-SPEC markers conflicted with the attributes they needed**
|
|
|
|
|
- **Found during:** Task 3
|
|
|
|
|
- **Issue:** `aria-controls="sidebar"` needs an element with `id="sidebar"`, `search.js` needs the index URL, and the toggle shared an `icon-button` class. Putting those attributes on the nav, the dialog and the toggle broke the exact markers `<nav class="sidebar" aria-label="Documentation">`, `<dialog class="search" id="search">` and `<button class="theme-toggle"`.
|
|
|
|
|
- **Fix:** `div.sidebar-panel#sidebar` wraps the nav, `data-index` sits on `#search-results`, and the toggle's class is exactly `theme-toggle` (it shares the CSS rules).
|
|
|
|
|
- **Files modified:** theme templates, site.css, search.js
|
|
|
|
|
- **Commit:** dd11bdb
|
|
|
|
|
|
|
|
|
|
**3. [Rule 3 - Blocking] Plan 11.1-01 tests asserted the old markup**
|
|
|
|
|
- **Found during:** Task 3
|
|
|
|
|
- **Issue:** `TestReadmeIngestion` expected a bare `<h2 id="usage">Usage</h2>`. `TestDocsAIOutputsInSync` required the set of `.html` files to equal the page URLs, and the new `404.html` broke that.
|
|
|
|
|
- **Fix:** The first now expects the permalink and the second ignores `404.html`. Neither test is weakened.
|
|
|
|
|
- **Files modified:** internal/docsite/docsite_test.go, cmd/summer/docs_test.go
|
|
|
|
|
- **Commit:** dd11bdb
|
|
|
|
|
|
|
|
|
|
### Notes
|
|
|
|
|
|
|
|
|
|
- `go.mod` gained exactly `github.com/alecthomas/chroma/v2` (direct) and `github.com/dlclark/regexp2/v2` (indirect). `go.sum` also has hash lines for chroma's own test dependencies (`alecthomas/assert/v2`, `alecthomas/repr`, `hexops/gotextdiff`). They are not modules of this build, and `--deps` passes. `scripts/check-phase11.sh --hygiene` still passes.
|
|
|
|
|
- `console` counts as a shell fence language alongside `sh`, `shell` and `bash`, both for command checks and for highlighting.
|
|
|
|
|
- Another process edited `modules/lagoon/transaction*.go`, `scripts/check-phase10.sh`, `scripts/check-phase11.sh` and two Phase 11 review files during this run. None of them were staged or touched. `11-REVIEW.md` was left alone as instructed.
|
|
|
|
|
|
|
|
|
|
**Total deviations:** 3 auto-fixed (1 bug, 2 blocking). **Impact:** none on scope.
|
|
|
|
|
|
|
|
|
|
## Issues Encountered
|
|
|
|
|
|
|
|
|
|
- Logged to `deferred-items.md`: a module README summary containing inline code shows raw backticks in the page lead (plan 11.1-01's `splitReadme` behaviour), and `internal/build/registry.go` was not gofmt-clean before this plan.
|
|
|
|
|
|
|
|
|
|
## Verification
|
|
|
|
|
|
|
|
|
|
- `go vet ./...` and `go test -short ./...` are green. `go test ./internal/docsite ./cmd/summer ./modules/... -count=1` (Docker included) is green, and so is `go test -race ./internal/docsite`.
|
|
|
|
|
- `scripts/check-phase11.1.sh` reports `--preconditions`, `--deps`, `--self-test`, `--docs`, `--forbidden` and `--claude` all passed.
|
|
|
|
|
- `go run ./cmd/summer docs:serve --addr 0.0.0.0:8088` exits 1 with the refusal copy. Over HTTP on loopback, `/`, the pages, the assets and `.md` return 200, and `/nope` and `/.summer-docs` return 404 with the Page not found body. The temporary directory is removed on SIGTERM.
|
|
|
|
|
- All plan acceptance greps match. `git diff 9033d81 -- modules/wristband` is empty.
|
|
|
|
|
|
|
|
|
|
## Known Stubs
|
|
|
|
|
|
|
|
|
|
None.
|
|
|
|
|
|
|
|
|
|
## User Setup Required
|
|
|
|
|
|
|
|
|
|
None.
|
|
|
|
|
|
|
|
|
|
## Next Phase Readiness
|
|
|
|
|
|
|
|
|
|
Plans 11.1-03 to 11.1-05 now write content that is checked as it is written. A Go example in a docs page needs `src=`, identifiers and commands must exist, and links must resolve. `summer docs:serve` previews the site. The manual UAT rows (search interaction, theme flash, contrast, no-JS layout) remain for verification.
|
|
|
|
|
|
|
|
|
|
## Self-Check: PASSED
|
|
|
|
|
|
|
|
|
|
All created files exist. Commits f460529, 5d4c1e3, d89e18b and dd11bdb are in the log.
|