docs(11.1-01): complete docs generator tracer plan summary

This commit is contained in:
Jakub Zych
2026-09-30 21:28:05 +02:00
parent dc6a03c714
commit e75490e892

View File

@@ -0,0 +1,243 @@
---
phase: 11.1-summercms-documentation-for-humans-and-ai-agents
plan: 01
subsystem: docs
tags: [docs, goldmark, html-template, llms-txt, cli, bonfire]
requires:
- phase: 11-core-framework
provides: "the 22 framework modules with READMEs that the API reference ingests"
provides:
- "internal/docsite: Options, Problem, Result, SyncResult, Check, Build, Sync, Pages, Site, Section, Frontmatter, Page, Ref, ParseSrc, Extract, MarkerFile"
- "summer docs:build (--root --src --out --base-url --check) and summer docs:sync (--root --src)"
- "docs/site.yaml, docs/index.md, docs/setup/installation.md"
- "modules/bonfire/example_test.go ExampleCall, the first src= verified example"
- "one slug parser.IDs (slugIDs) and a headingIDs helper for the plan 11.1-02 link checker"
affects: [11.1-02, 11.1-03, 11.1-04, 11.1-05, 11.1-06]
actuals:
tokens: 24800
tasks: 3
commits: 3
plan_head_before: 63bcbc31b0dabc5fc80b50cdbb2213e440798596
plan_head_after: dc6a03c7142c3e075a16e0d15518d2c5bf81c267
tech-stack:
added: []
patterns:
- "One goldmark pipeline (GFM, safe mode) with AST transformers fed per-page state through parser.Context"
- "Render everything into an in-memory map, then guard and write the output directory"
- "embedmd-style src= fences: the fence body is a byte copy of real, tested source; docs:sync refreshes it"
- "Problems print as file:line: rule: message and block the build"
key-files:
created:
- internal/docsite/docsite.go
- internal/docsite/load.go
- internal/docsite/render.go
- internal/docsite/emit.go
- internal/docsite/snippet.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
- modules/bonfire/example_test.go
- docs/site.yaml
- docs/index.md
- docs/setup/installation.md
modified:
- cmd/summer/main.go
- cmd/summer/main_test.go
- .gitignore
- README.md
key-decisions:
- "Added exported docsite.Pages(opts) (reading-order pages plus load problems, no rendering) so TestDocsAIOutputsInSync and later checkers read the page tree without re-implementing ordering"
- "Module README pages blank the summary line in the body (line count kept) so the lead is not repeated and README problems keep their own line numbers"
- "A type, var or const named by #Ident in a _test.go file counts as run when a reachable Test/Example function references it; functions and regions must be reachable from a Test or Example"
- "Fence rendering uses a goldmark NodeRenderer at priority 100: goldmark registers lower priority values last, so it overrides the default html renderer (1000)"
- "Development commits land on master: the project config uses branching_strategy none and every earlier phase commit is on master"
patterns-established:
- "Content rule: a docs page file starts with frontmatter and its first body line is exactly '# <title>'"
- "Example convention: modules/<m>/example_test.go, package <m>_test, Example<Ident> ending in // Output:"
requirements-completed: [DOCS-01, DOCS-02, DOCS-03, DOCS-04]
coverage:
- id: D1
description: "summer docs:build renders docs/ into a static site with .html pages, .md siblings, llms.txt, llms-full.txt, search-index.json, assets and the .summer-docs marker"
requirement: DOCS-02
verification:
- kind: unit
ref: "cmd/summer/docs_test.go#TestDocsBuildRealTree"
status: pass
- kind: unit
ref: "cmd/summer/docs_test.go#TestDocsTree"
status: pass
human_judgment: false
- id: D2
description: "Output guard refuses a non-empty --out without the marker and an --out equal to the root, inside --src or containing it"
requirement: DOCS-02
verification:
- kind: other
ref: "go run ./cmd/summer docs:build --out <dir with an unrelated file> (exit 1, file kept); --out docs/x, --out ., --out .. (exit 1)"
status: pass
- kind: unit
ref: "internal/docsite/docsite_test.go#TestSyncRewritesDrift (Build writes nothing while a snippet drifts)"
status: pass
human_judgment: false
- id: D3
description: "Every framework module is an API reference page in the sidebar, llms.txt and search; links to READMEs and pages are rewritten"
requirement: DOCS-01
verification:
- kind: unit
ref: "cmd/summer/docs_test.go#TestEveryModuleInSidebar"
status: pass
- kind: unit
ref: "internal/docsite/docsite_test.go#TestReadmeIngestion"
status: pass
- kind: unit
ref: "internal/docsite/docsite_test.go#TestSlugIDs"
status: pass
human_judgment: false
- id: D4
description: "llms.txt, llms-full.txt and the per-page .md files list the same pages in reading order and follow the llms.txt shape"
requirement: DOCS-03
verification:
- kind: unit
ref: "cmd/summer/docs_test.go#TestDocsAIOutputsInSync"
status: pass
human_judgment: false
- id: D5
description: "src= fences are verified copies of tested source; drift or a missing source fails Check and Build; docs:sync rewrites drifted copies; bonfire ExampleCall runs under go test"
requirement: DOCS-04
verification:
- kind: unit
ref: "internal/docsite/docsite_test.go#TestSnippetForms"
status: pass
- kind: unit
ref: "internal/docsite/docsite_test.go#TestSnippetConfinement"
status: pass
- kind: unit
ref: "internal/docsite/docsite_test.go#TestSyncRewritesDrift"
status: pass
- kind: unit
ref: "modules/bonfire/example_test.go#ExampleCall"
status: pass
human_judgment: false
- id: D6
description: "llms.txt and the per-page .md files are useful to an AI agent reading raw files"
verification: []
human_judgment: true
rationale: "Plan marks this truth as a backstop; usefulness to an agent is a judgment call beyond the shape assertions in TestDocsAIOutputsInSync"
duration: 15min
completed: 2026-09-30
status: complete
---
# Phase 11.1 Plan 01: Docs generator tracer Summary
**`summer docs:build` renders docs/ and all 22 module READMEs through goldmark and html/template into HTML, .md siblings, llms.txt, llms-full.txt and a search index. Go fences with `src=` are byte-checked copies of tested source, and `summer docs:sync` refreshes them.**
## Performance
- **Duration:** 15 min
- **Started:** 2026-09-30T19:12:22Z
- **Completed:** 2026-09-30T19:27:06Z
- **Tasks:** 3
- **Files modified:** 18
## Accomplishments
- `internal/docsite` is a stdlib and goldmark generator. It decodes `site.yaml` and frontmatter strictly with goccy/go-yaml `DisallowUnknownField`, reports problems in the UI-SPEC `file:line: rule: message` wording, renders every page in memory and writes nothing when a problem exists.
- Module discovery reads `modules/` at run time. Each directory with non-test Go files becomes `api/<name>` from its README, and a directory with no README is a `readme:` problem. The real tree builds 24 pages: the index, installation and 22 API pages.
- Heading anchors come from a single GitHub-compatible `parser.IDs` implementation (`slugIDs`). Links to `.md` pages and to `modules/<m>/README.md` are rewritten to `.html` URLs in the HTML output and to `.md` URLs in the raw output. `search-index.json` has one entry per H2.
- A `src=` reference can name a whole file, a Go declaration, an Example body with its `// Output:` line, or a `docs:start`/`docs:end` region. The path must stay inside the root: it must be relative and clean, must not follow a symlink out of the root, and must not point at a dotfile, a `.env` file or a nested go.mod module. The referenced code must also run under `go test`: Examples need `// Output:`, `_test.go` fragments must be reachable from a Test or Example, and non-test sources need a package with tests.
- `bonfire.ExampleCall` is shown in `docs/setup/installation.md`. Its fence body was written by `docs:sync`.
## Task Commits
1. **Task 1: Tracer: `summer docs:build` with every output** - `6dacddc` (feat)
2. **Task 2: Every module as an API reference page, shared heading IDs, rewritten links, search entries** - `e433dcf` (feat)
3. **Task 3: Verified snippets, `summer docs:sync`, first Example** - `dc6a03c` (feat)
**Plan metadata:** see the docs(11.1-01) commit that adds this file
## Files Created/Modified
- `internal/docsite/docsite.go`: Options, Problem, Result, Check, Build, the output guard and the file writer
- `internal/docsite/load.go`: site.yaml and frontmatter decoding, the page walk, README ingestion, reading order and Pages
- `internal/docsite/render.go`: the goldmark pipeline, slugIDs, link rewriting, fence annotation and rendering, plain-text extraction and the fence scanner
- `internal/docsite/emit.go`: the page template, .md siblings, llms.txt, llms-full.txt, search-index.json and assets
- `internal/docsite/snippet.go`: Ref, ParseSrc, Extract, the confinement and run rules, the drift check and Sync
- `internal/docsite/theme/templates/page.html`, `theme/assets/site.css`: the tracer shell (sidebar and content) and the light tokens
- `cmd/summer/docs.go`: the `docs:build` and `docs:sync` commands
- `cmd/summer/docs_test.go`: TestDocsTree, TestDocsBuildRealTree, TestEveryModuleInSidebar and TestDocsAIOutputsInSync
- `internal/docsite/docsite_test.go`: TestSlugIDs, TestReadmeIngestion, TestSnippetForms, TestSnippetConfinement and TestSyncRewritesDrift
- `modules/bonfire/example_test.go`: ExampleCall
- `docs/site.yaml`, `docs/index.md`, `docs/setup/installation.md`: the first content
- `cmd/summer/main.go` and `main_test.go` (registration, want list and help flags), `.gitignore` (`/site/`), `README.md` (a `docs/` layout row and a docs:build/docs:sync paragraph in Development)
## Decisions Made
See `key-decisions` in the frontmatter. The most visible is the exported `docsite.Pages`, an addition to the planned interface that does not break it.
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 3 - Blocking] `api` section added to site.yaml in Task 2, not Task 1**
- **Found during:** Task 1
- **Issue:** With `api` listed in site.yaml before README ingestion existed (Task 2), the empty-section rule failed `TestDocsTree`. That would have broken `go test` at the Task 1 commit.
- **Fix:** Task 1 lists only `setup`. Task 2 adds `api` in the same change as its first pages, which is the rule the build enforces.
- **Files modified:** docs/site.yaml
- **Commit:** 6dacddc, e433dcf
**2. [Rule 1 - Bug] Code-block renderer priority**
- **Found during:** Task 3
- **Issue:** At priority 2000 the custom fence renderer never replaced goldmark's default, because goldmark registers lower priority values last. No `<figure class="code">` was emitted.
- **Fix:** Priority 100, with a comment explaining it.
- **Files modified:** internal/docsite/render.go
- **Commit:** dc6a03c
**3. [Scope note] Snippet check wired in load.go**
- Task 3 lists docsite.go and render.go. The call to `checkSnippets` sits in `assemble` in load.go, where the rest of the load pipeline already lives. There is no behaviour difference.
**4. [Content] installation.md links the bonfire README**
- The "Check your install" section links `../../modules/bonfire/README.md`, so the real tree exercises guide-to-README link rewriting.
---
**Total deviations:** 2 auto-fixed (1 blocking, 1 bug), 2 notes. **Impact:** none on scope. Every planned output, test and acceptance criterion is met.
## Issues Encountered
- `gofmt -l` lists `internal/build/registry.go`. This was already the case before this plan, so it was left alone.
- The GSD HEAD assertion treats `master` as protected. The project runs with `branching_strategy: none`, and all earlier phase commits are on master, so this plan's commits are on master too. Setting `git.allow_default_branch_commits: true` would make that explicit.
## Verification
- `go vet ./...` is green, and so is `go test -short ./...` across the repository.
- `go test ./internal/docsite ./cmd/summer ./modules/bonfire -count=1` is green. `ExampleCall` reports `--- PASS`.
- `go run ./cmd/summer docs:build --out <tmp>` writes 24 pages. `docs:sync` reports all snippets up to date. A drifted scratch copy fails `--check` with `snippet: body differs from modules/bonfire/example_test.go#ExampleCall (run: summer docs:sync)`.
- The built output contains no consuming-application names. Its only absolute URL is the source_url caption link to the framework's own forge, and it has no third-party asset origins.
- `go.mod` is unchanged.
## User Setup Required
None. No external service configuration is required.
## Next Phase Readiness
Plan 11.1-02 can replace `page.html` with the full theme, reuse `headingIDs`/`slugIDs` for the anchor checker and `docsite.Pages` for the tree checks, and add `docs:serve`. The `Commands` option field is still to be added by 11.1-02, as planned.
## Self-Check: PASSED
All 14 created files exist. Commits 6dacddc, e433dcf and dc6a03c are in the log.
---
*Phase: 11.1-summercms-documentation-for-humans-and-ai-agents*
*Completed: 2026-09-30*