diff --git a/.planning/phases/11.1-summercms-documentation-for-humans-and-ai-agents/11.1-01-SUMMARY.md b/.planning/phases/11.1-summercms-documentation-for-humans-and-ai-agents/11.1-01-SUMMARY.md new file mode 100644 index 0000000..7a8a290 --- /dev/null +++ b/.planning/phases/11.1-summercms-documentation-for-humans-and-ai-agents/11.1-01-SUMMARY.md @@ -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 '# '" + - "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*