docs(11.1): record plan-count checkpoint decisions, DOCS requirements and pattern map

This commit is contained in:
Jakub Zych
2026-09-30 19:39:50 +02:00
parent 30d3bfec67
commit 9033d81721
4 changed files with 164 additions and 4 deletions

View File

@@ -123,6 +123,17 @@ Requirements for v1 (the Płytarium port). Each maps to roadmap phases. "User" b
- [x] **QA-04**: The first vertical slice (GET /_fonoteka/api/v1/genres) passes the parity diff end to end before further kernel abstraction - [x] **QA-04**: The first vertical slice (GET /_fonoteka/api/v1/genres) passes the parity diff end to end before further kernel abstraction
- [ ] **QA-05**: Cutover: the parity harness is green on all 154 routes and vue-fonoteka-app and fonoteka-mcp run unchanged against the Go backend - [ ] **QA-05**: Cutover: the parity harness is green on all 154 routes and vue-fonoteka-app and fonoteka-mcp run unchanged against the Go backend
### Documentation (DOCS)
- [ ] **DOCS-01**: `docs/` holds Markdown pages with strict YAML frontmatter (title, description, section, order), grouped into the Winter-mirroring sections, and every framework module under `modules/` is reachable from the sidebar through an API reference page ingested from its README
- [ ] **DOCS-02**: `summer docs:build` writes a self-contained static site (sidebar, on-page TOC, prev/next, edit-this-page link, client-side search, light/dark/system theme) and `summer docs:serve` previews it on loopback; no Node toolchain, and the only new dependency is `alecthomas/chroma/v2` for syntax highlighting (approved at the 11.1 plan-count checkpoint)
- [ ] **DOCS-03**: The build emits `llms.txt`, `llms-full.txt` and a clean `.md` beside every `.html` page, and a test asserts all three match the page tree
- [ ] **DOCS-04**: Every Go fence in the docs references compiled source by `src=`; a test fails on a missing or drifted snippet, and referenced Examples carry `// Output:` and run under `go test ./...`
- [ ] **DOCS-05**: `go test ./...` runs checkers that fail on stale identifiers (docs pages and module READMEs), broken internal links and anchors, unknown `summer`/runtime CLI command names and forbidden consuming-application names
- [ ] **DOCS-06**: A "Coming from WinterCMS" page maps Winter concepts to SummerCMS equivalents, and every SummerCMS identifier on it is checker-verified
- [ ] **DOCS-07**: An `acme/blog` porting walkthrough covers models, migrations, routes, an admin controller and a console command; its code is a real in-root package under `docs/examples/blog`, verified by DOCS-04
- [ ] **DOCS-08**: CLAUDE.md's Documentation section records that API, config or CLI changes update both the module README and the affected docs pages, and names the automated checkers
## v2 Requirements ## v2 Requirements
Deferred to a later milestone. Tracked but not in the current roadmap. Deferred to a later milestone. Tracked but not in the current roadmap.
@@ -232,12 +243,20 @@ Which phases cover which requirements. Updated during roadmap creation.
| QA-03 | Phase 2 | Complete | | QA-03 | Phase 2 | Complete |
| QA-04 | Phase 3 | Complete | | QA-04 | Phase 3 | Complete |
| QA-05 | Phase 15 | Pending | | QA-05 | Phase 15 | Pending |
| DOCS-01 | Phase 11.1 | Pending |
| DOCS-02 | Phase 11.1 | Pending |
| DOCS-03 | Phase 11.1 | Pending |
| DOCS-04 | Phase 11.1 | Pending |
| DOCS-05 | Phase 11.1 | Pending |
| DOCS-06 | Phase 11.1 | Pending |
| DOCS-07 | Phase 11.1 | Pending |
| DOCS-08 | Phase 11.1 | Pending |
**Coverage:** **Coverage:**
- v1 requirements: 77 total - v1 requirements: 85 total
- Mapped to phases: 77 - Mapped to phases: 85
- Unmapped: 0 ✓ - Unmapped: 0 ✓
--- ---
*Requirements defined: 2026-09-16* *Requirements defined: 2026-09-16*
*Last updated: 2026-09-28 after adding ADMIN-07 (Phase 10.1 runtime admin extension point); previously 2026-09-16 after roadmap revision (15 phases, split former Phase 13 into Phase 11 jobs/realtime/search infrastructure and Phase 14 domain jobs/integrations, reordered before the API phases; 100% coverage)* *Last updated: 2026-09-30 after adding DOCS-01..08 (Phase 11.1 documentation); previously 2026-09-28 after adding ADMIN-07 (Phase 10.1 runtime admin extension point); previously 2026-09-16 after roadmap revision (15 phases, split former Phase 13 into Phase 11 jobs/realtime/search infrastructure and Phase 14 domain jobs/integrations, reordered before the API phases; 100% coverage)*

View File

@@ -530,7 +530,7 @@ Plans:
### Phase 11.1: SummerCMS documentation for humans and AI agents (INSERTED) ### Phase 11.1: SummerCMS documentation for humans and AI agents (INSERTED)
**Goal:** SummerCMS has a WinterCMS-style documentation set that serves both humans and AI agents. The Markdown source lives in `summercms.go/docs/` and a `summer` CLI command builds it into a static site with sidebar navigation, search, `llms.txt`/`llms-full.txt` and a raw `.md` per page. Every code example compiles and is tested, and a "Coming from WinterCMS" map plus an `acme/blog` porting walkthrough cover the migration path. It documents the framework as it stands after Phase 11 and never names a consuming application. **Goal:** SummerCMS has a WinterCMS-style documentation set that serves both humans and AI agents. The Markdown source lives in `summercms.go/docs/` and a `summer` CLI command builds it into a static site with sidebar navigation, search, `llms.txt`/`llms-full.txt` and a raw `.md` per page. Every code example compiles and is tested, and a "Coming from WinterCMS" map plus an `acme/blog` porting walkthrough cover the migration path. It documents the framework as it stands after Phase 11 and never names a consuming application.
**Requirements**: TBD **Requirements**: DOCS-01, DOCS-02, DOCS-03, DOCS-04, DOCS-05, DOCS-06, DOCS-07, DOCS-08
**Depends on:** Phase 11 **Depends on:** Phase 11
**Repos:** summercms.go **Repos:** summercms.go
**Success Criteria** (what must be TRUE): **Success Criteria** (what must be TRUE):

View File

@@ -51,6 +51,12 @@ Not in this phase:
### Claude's Discretion ### Claude's Discretion
- Exact page list within each section, URL scheme, theme styling (reuse the admin SPA's design tokens if convenient), search index format, and the generator's package location (for example `modules/<beach-name>` or `internal/docs`, following the existing naming convention). - Exact page list within each section, URL scheme, theme styling (reuse the admin SPA's design tokens if convenient), search index format, and the generator's package location (for example `modules/<beach-name>` or `internal/docs`, following the existing naming convention).
### Plan-count checkpoint (2026-09-30)
- **D-14:** Six plans, per RESEARCH.md Q8: tracer (generator core to every output), site UX and accuracy gates, framework content A, framework content B, the `acme/blog` walkthrough, and unit tests last.
- **D-15:** Syntax highlighting uses `github.com/alecthomas/chroma/v2`, approved by the user at this checkpoint (overrides the research's stdlib-only recommendation). It is called from a small custom goldmark `NodeRenderer`; `yuin/goldmark-highlighting` stays rejected. This is the only new dependency; `go.mod` gains chroma/v2 and its transitive `dlclark/regexp2`, and the phase gate asserts no other module is added.
- **D-16:** The walkthrough code is an in-root package under `docs/examples/blog`, covered by root `go test ./...`, plus a scaffold-layout test.
- **D-17:** Raw pages sit beside their HTML pages (`/x/page.html` and `/x/page.md`). Config-key checking is deferred and noted in CLAUDE.md. The wristband default that names the consuming application is logged as a follow-up todo; its API does not change in this phase.
</decisions> </decisions>
<specifics> <specifics>

View File

@@ -0,0 +1,135 @@
# Phase 11.1: SummerCMS documentation for humans and AI agents - Pattern Map
**Mapped:** 2026-09-30
**Files analyzed:** 14 file groups
**Analogs found:** 11 / 14
All analog paths below are git-tracked in `summercms.go`. There is no `docs/` tree and no `example_test.go` anywhere in `modules/` yet (verified). Phase 11 modules exist: `conga`, `lighthouse`, `flare`, `beachcomber`, `tide`.
## File Classification
| New/Modified File | Role | Data Flow | Closest Analog | Match Quality |
|---|---|---|---|---|
| `internal/docsite/*.go` (load, frontmatter, site.yaml, walker, render, emit) | service (generator) | file-I/O, transform | `internal/build/build.go`, `internal/build/manifest.go`, `internal/build/scaffold.go` | role-match |
| `internal/docsite` site.yaml / frontmatter strict decode | utility | transform | `modules/tide/manifest.go:85-104` | exact |
| `internal/docsite/theme/*` (embedded HTML/CSS/JS assets) | config/assets | file-I/O | `internal/build/scaffold.go:20-23` (`//go:embed stubs/*.tmpl`) | role-match |
| `internal/docsite` checkers (identifiers, links, CLI names, forbidden names, src= sync) | test utility | batch | `cmd/summer/main_test.go` (go/parser use, `TestToolCommandNames`) | partial |
| `internal/docsite/*_test.go` | test | file-I/O | `internal/build/build_test.go` (t.TempDir fixtures) | exact |
| `cmd/summer/docs.go` (`docs:build`, `docs:sync`, `docs:serve`) | controller (CLI) | request-response | `cmd/summer/main.go:52-92` | exact |
| `cmd/summer/main.go` (register in `toolCommands()`) | config | - | `cmd/summer/main.go:27-50` | exact |
| `cmd/summer/main_test.go` (extend `TestToolCommandNames`) | test | - | itself, lines 17-54 | exact |
| `modules/<m>/example_test.go` (bonfire first, then party, backpack, compass, festival, phrasebook, towel, lagoon, wire, surf, postcard, bouncer, fetchguard, cabana, conga, lighthouse, flare, beachcomber, tide) | test (Example funcs) | - | `modules/bonfire/call_test.go` (fixture shape only) | partial, no Example* exists |
| `docs/examples/blog/**` (plugin, models, YAML, controller, console cmd, lang, tests) | example plugin | CRUD | `examples/hello/plugins/greeter/`, `examples/hello/hello_test.go` | role-match |
| `scripts/check-phase11.1.sh` | gate script | batch | `scripts/check-phase11.sh` + `scripts/check-phase10.2.sh` | exact |
| `.gitignore` (add `/site/`) | config | - | `.gitignore` "# Go" block | exact |
| `CLAUDE.md` Documentation section (D-13 bullet) | docs rule | - | `CLAUDE.md` Documentation section | exact |
| `docs/**/*.md`, `docs/site.yaml` | content | - | `modules/*/README.md` (tone/structure) | no code analog |
## Pattern Assignments
### `cmd/summer/docs.go` (CLI, request-response)
**Analog:** `cmd/summer/main.go` lines 52-92. Commands are plain `bonfire.Command` values returned by a `xxxCommand()` func; flags via `bonfire.Flag`, `Bare: true` for booleans; errors returned, output via `out.Printf`.
```go
func makePluginCommand() bonfire.Command {
return bonfire.Command{
Name: "make:plugin",
Description: "Scaffold a compiling plugin module from a vendor.plugin id",
Args: []bonfire.Arg{{Name: "id", Description: "Plugin ID in vendor.plugin form", Required: true}},
Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error {
dir, err := os.Getwd()
if err != nil {
return err
}
created, err := build.MakePlugin(ctx, dir, id)
...
out.Printf("created %s\n", created)
return nil
},
}
}
```
Bool flag parsing (for `docs:sync --check` etc.), `cmd/summer/runtime.go:67-87`:
```go
if v, ok := in.Flag("once"); ok {
if once, _ := strconv.ParseBool(v); once { ... }
}
```
Value flags (`--out`, `--addr`): `in.Flag("out")`; repeatable via `Repeatable: true` + `in.Flags(name)` (`modules/conga/commands.go:33-41`).
Keep logic in `internal/docsite` (like `build.App(ctx, dir, out)`); the command only resolves cwd/flags and delegates.
**Registration:** append `docsBuildCommand(), docsSyncCommand(), docsServeCommand()` to the slice in `toolCommands()` (`cmd/summer/main.go:27-50`).
### `cmd/summer/main_test.go` (extend)
Add `"docs:build", "docs:sync", "docs:serve"` to the want list at line 22 and `--out` etc. to `helpWants` (lines 28-37). The CLI-name checker should derive the command set from `toolCommands()` plus each module's `RuntimeCommands` (e.g. `conga.RuntimeCommands`, `modules/lighthouse/centrifugo/commands.go:22`), not a hardcoded list.
### `internal/docsite` strict YAML (site.yaml, frontmatter)
**Analog:** `modules/tide/manifest.go:85-104`
```go
func ParseManifest(raw []byte) (Manifest, error) {
var m Manifest
dec := yaml.NewDecoder(bytes.NewReader(raw), yaml.DisallowUnknownField())
if err := dec.Decode(&m); err != nil {
return Manifest{}, fmt.Errorf("tide: parse manifest: %w", err)
}
...
}
```
Split `LoadX(path)` (os.ReadFile + wrapped error with path) from `ParseX(raw)`; error prefix `docsite: ...`. Import `github.com/goccy/go-yaml` (already in go.mod).
### `internal/docsite` theme assets
**Analog:** `internal/build/scaffold.go:20-23`
```go
//go:embed stubs/*.tmpl
var stubFS embed.FS
var stubTmpl = template.Must(template.ParseFS(stubFS, "stubs/*.tmpl"))
```
Use `html/template` (not text/template) for pages; `embed.FS` for `theme/*.css|js`, copied verbatim into the output dir.
### `internal/docsite/*_test.go`
**Analog:** `internal/build/build_test.go` (e.g. `TestParseManifestRejectsDuplicatesAndInvalidPaths` line 29, `dir := t.TempDir()`). Plain stdlib `testing`, `t.Fatalf("x = %v, want ...")`, no testify (repo convention). Smoke test builds the real `docs/` tree into `t.TempDir()`. Failure-path fixtures written into temp dirs.
### `modules/<m>/example_test.go`
No Example analog exists. Convention to establish: `package <m>_test`, functions `ExampleNewRoot`, `ExampleCall`, ... naming real identifiers, each ending in `// Output:`. Use `// docs:start <region>` / `// docs:end <region>` markers for `src=path#region`. Reusable fixture shape from `modules/bonfire/call_test.go:11-36` (inline `[]Command{{Name: "acme:echo", ...}}` + `Call(ctx, cmds, name, args, &out)`), rewritten with the `bonfire.` qualifier and `context.Background()` instead of `t.Context()`. Use neutral names (`acme`, `blog`). For DB-bound modules (lagoon, conga, beachcomber, lighthouse), prefer non-DB identifiers or regions in existing `_test.go` packages; do not start Postgres in Examples.
### `docs/examples/blog/**`
**Analog:** `examples/hello/plugins/greeter/{go.mod,plugin.go,plugin_test.go}`, `examples/hello/plugins/base/{config,lang,views}`, and `examples/hello/hello_test.go` (package main, imports modules `backpack, bonfire, compass, pact, party, phrasebook, postcard, surf, towel`). The plugin layout leaves come from `internal/build/scaffold.go` `pluginLeaves` (`models`, `classes`, `controllers`, `console`, `jobs`, ...), so the scaffold-layout test can compare against that slice. Note: examples/hello uses its own `go.mod` per plugin; decide whether blog is its own module (then `go test ./...` at root will not cover it; the gate must run it explicitly, as check-phase11 does for the app).
### `scripts/check-phase11.1.sh`
**Analog:** `scripts/check-phase11.sh` (latest) for structure; `scripts/check-phase10.2.sh` for `refuse`/`expect_refusal`.
- Header comment describing the gate, then `set -euo pipefail`, `ROOT="${PHASE11_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"` (11.sh:19-21), `PHASE_DIR=...`.
- `usage()` heredoc listing modes, `exit 2` (11.sh:33-45).
- `refuse() { echo "refuse: $*" >&2; return 1; }` (10.2.sh:25-28).
- `expect_refusal name want ...` : run the check in a scratch copy, fail if it passes, fail if stderr lacks `want` (10.2.sh:105-116).
- `run_self_test`: `bash -n "${BASH_SOURCE[0]}"`, `mktemp -d`, `trap 'rm -rf ...' RETURN`, copy README.md + module READMEs, plant violations (10.2.sh:118-130).
- `run_go`: `(cd "$ROOT" && go vet ./...)` then tests (11.sh:621-627); each mode echoes `phase11.1 <mode> passed`.
- Final `case "${1:-}" in --self-test) ...;; --all) ...;; *) usage ;; esac` (11.sh tail).
- README-table check to reuse for `--preconditions`: `grep -qF "| [$m](modules/$m/README.md) |" "$tree/README.md"` (11.sh:~260).
Modes per RESEARCH Q7: `--preconditions --deps --forbidden --docs --claude --self-test --go --all`. Semantic checks stay in Go tests.
### `.gitignore`
Add `/site/` under the `# Go` block (next to `/dist/`).
### `CLAUDE.md`
Documentation section, 4 bullets ending with the `go doc ./modules/<name> <Identifier>` rule. Add the D-13 bullet and amend the go-doc bullet to name `go test ./internal/docsite/...`. Separate commit from code.
## Shared Patterns
- **Errors:** wrap with package prefix and `%w` (`fmt.Errorf("tide: read manifest %s: %w", path, err)`); commands return errors, `main` prints them.
- **Tests:** stdlib `testing` only, `t.TempDir()`, `t.Fatalf` with got/want.
- **Neutral names:** `acme`, `blog`; the forbidden list (`fonoteka|płytarium|plytarium`) as a constant shared by test and gate.
- **Module discovery:** iterate `modules/*/` dirs dynamically (like hygiene loop in check-phase11.sh around line 255-265) so Phase 11 modules are covered with no code changes.
## No Analog Found
| File | Role | Reason |
|---|---|---|
| goldmark pipeline / renderer in `internal/docsite` | transform | No Markdown rendering in repo; use RESEARCH.md (goldmark v1.8.6 parser/extension notes) |
| search index + `search.js`, `theme-init.js` | frontend asset | No plain-JS assets; admin uses Vue/Tailwind. Take tokens from `admin/src/styles/main.css:83-125` per UI-SPEC |
| `docs/**/*.md` content, `llms.txt`/`llms-full.txt` formats | content | Follow UI-SPEC and RESEARCH (llmstxt.org, Mintlify block format) |
## Metadata
**Analog search scope:** `cmd/summer`, `internal/build`, `modules/{bonfire,conga,lighthouse,tide}`, `examples/hello`, `scripts/check-phase*.sh`, `.gitignore`
**Pattern extraction date:** 2026-09-30