Six plans (tracer generator, site UX and checkers, content A, content B,
acme/blog walkthrough, unit tests). SC4/DOCS-04 narrowed to docs/ pages per
D-18; README Go fence conversion logged as a todo.
Per D-09 and DOCS-06, docs/setup/coming-from-wintercms.md maps WinterCMS concepts (Plugin.php, version.yaml and updates, Eloquent models, fields.yaml and columns.yaml, backend controllers and behaviours, routes.php, middleware, config files, lang files, events, artisan commands, queues, the scheduler, mail templates, settings models) to SummerCMS equivalents, names each SummerCMS identifier as a checked `pkg.Ident` span, and marks the WinterCMS areas SummerCMS does not provide (CMS pages, themes, components, the AJAX framework, Snowboard, import/export, record sorting, collections, behaviours, cache, session) as not provided.
Per D-08, site.yaml lists the Setup, Architecture, Plugins and Console sections (with API reference last), and each has the pages in this plan's files list with unique, spaced order values (10, 20, 30...), installation keeping order 20.
Per D-07, every Go fence in these pages carries src= to an Example with `// Output:` or a docs:start region in a module example_test.go, the bodies were written by `summer docs:sync`, and go vet accepts every Example name (so each names a real identifier).
Per D-11, no page or example names a consuming application; examples use acme and blog.
Per D-12, TestDocsTree passes on the real tree after each task: identifiers, links, anchors, command names, forbidden names, fences and frontmatter are clean.
The Console pages name only commands that exist: `summer` tokens from toolCommands() and `./bin/<app>` tokens from the runtime command set, as enforced by the command checker.
cmd/summer TestDocsRequiredPages lists every page of this plan and passes.
Pages describe awkward APIs as they are; no module API changes in this plan, and any gap found is logged as a todo under .planning/todos/pending/.
statement
verification
The pages read in WinterCMS docs tone (second person, present tense, imperative) and are useful to a WinterCMS developer (manual review).
backstop
requirement_id
category
status
verification
resolution
reason
statement
DOCS-06
transparency
resolved
judgment
The concept map has an explicit 'Not provided' column value and the headless nature is stated on the introduction pages.
A WinterCMS developer porting a site must learn early that themes, CMS pages and the AJAX framework do not exist, instead of discovering it mid-port.
The docs must not describe a WinterCMS feature that SummerCMS does not provide as if it were available.
path
provides
contains
docs/setup/coming-from-wintercms.md
WinterCMS to SummerCMS concept map
party.Plugin
path
provides
contains
docs/console/setup-and-maintenance.md
runtime command reference
migrate:status
path
provides
contains
modules/party/example_test.go
verified plugin Example
// Output:
path
provides
contains
cmd/summer/docs_test.go
TestDocsRequiredPages
TestDocsRequiredPages
from
to
via
pattern
docs/setup/coming-from-wintercms.md
modules/party/example_test.go
go fence src= reference
src=modules/party/example_test.go#
from
to
via
pattern
docs/plugins/scheduling.md
modules/pact/example_test.go
go fence src= reference to a schedule Example
src=modules/pact/example_test.go#
from
to
via
pattern
docs/site.yaml
docs/architecture/introduction.md
architecture section listed in sidebar order
architecture
Write framework content A: the Setup section (Introduction, Installation, Configuration, Coming from WinterCMS), Architecture, Plugins and Console, with Go examples as compiled `example_test.go` Examples referenced by `src=`.
Purpose: D-08 (Winter-mirroring sections), D-09 (concept map, DOCS-06) and D-07 (verified examples) for the framework's core: plugins, lifecycle, request flow and the CLI. Every page passes the plan 11.1-02 checkers as it is written.
Output: 16 new or rewritten pages, site.yaml sections, example_test.go files for party, backpack, pact, festival and towel, an extended bonfire example, and TestDocsRequiredPages.
Authoring rules for every page in this plan (from plans 11.1-01 and 11.1-02; the checkers enforce them):
Frontmatter title, description (one sentence, at most 160 characters), section (the directory name), order; the first body line is # <title>.
Headings are plain ASCII text with no links or code spans.
A framework identifier is written as a backticked pkg.Ident or pkg.Type.Member span so the identifier checker verifies it.
Link a module by its README path (../../modules/<m>/README.md), which the site rewrites to the API reference page; link guide pages by relative .md path. Link only to pages that exist when the task commits.
A Go fence is written as a go src=<path>#<fragment> fence with an empty body, then go run ./cmd/summer docs:sync fills it. Never hand-type a Go fence body. YAML, sh and php fences may be written by hand (PHP fences show the WinterCMS side only).
Examples live in modules/<m>/example_test.go, package <m>_test, named after real identifiers (ExampleX, ExampleT_Method), deterministic, ending in // Output:; no database or network. Use neutral names (acme, blog). A docs:start region in a test file is allowed only inside a Test or Example function or a helper one of them calls (the snippet checker enforces it), so every shown snippet runs under go test ./....
Tone: second person, present tense, imperative, as wintercms.com/docs. The docs describe the framework as it is; an awkward API is described as it is and logged as a todo, never changed here.
Stage only the files each task lists (other work may be in the tree).
Task 1: Tracer: a WinterCMS developer finds the concept map in Setup, with checked identifiers and a verified plugin example
docs/setup/coming-from-wintercms.md, modules/party/example_test.go, docs/index.md, cmd/summer/docs_test.go
- README.md (Key concepts, Using SummerCMS in an application)
- modules/party/README.md, modules/pact/README.md, modules/cabana/README.md, modules/lagoon/README.md (identifiers to map)
- `go doc ./modules/party` and `go doc ./modules/pact` output
- .planning/phases/11.1-summercms-documentation-for-humans-and-ai-agents/11.1-RESEARCH.md Q1 "Winter section → SummerCMS page → module(s)" table
- cmd/summer/docs_test.go (TestDocsTree from plans 11.1-01 and 11.1-02)
Per D-09 and DOCS-06, prove one content page end to end (page, identifiers, verified snippet, sidebar, llms, search, checkers) before the bulk.
modules/party/example_test.go (package party_test): ExamplePlugin declares an acme.blog plugin type implementing party.Plugin (ID, Requires, Register, Boot) and prints its ID, ending // Output: acme.blog. Do not call party.Register in the Example (it is process-wide).
docs/setup/coming-from-wintercms.md: title "Coming from WinterCMS", section setup, order 40. Open with two paragraphs on what carries over (plugins that extend each other, YAML admin, models/controllers, scaffolding) and what does not (runtime plugin loading, PHP magic, the frontend). A concept table with columns WinterCMS, SummerCMS, Where: one row each for Plugin.php, version.yaml and updates/, Eloquent models, fields.yaml and columns.yaml, backend controllers with Form/List/Relation behaviours, routes.php, middleware, config/*.php, lang/ files, Event::listen, artisan commands, queued jobs, the scheduler, mail templates, settings models, Laravel broadcasting, Scout search and the HTTP client. Each SummerCMS cell names identifiers as pkg.Ident spans (for example party.Plugin, pact.HasMigrations, pact.HasRoutes, pact.AdminController, festival.Bus, bonfire.Command, pact.HasSchedule) and the Where cell links the module README. Then a "Not provided" table: CMS pages, themes, layouts and partials, components, the AJAX framework and Snowboard, the media manager, import/export, record sorting, collections and behaviours (use Go slices and composition), cache and session (use the Go standard library). Say that the frontend is a separate application that calls the JSON API. Add a "Plugin.php in Go" section with a php fence of a WinterCMS Plugin.php for Acme\Blog and a go src=modules/party/example_test.go#ExamplePlugin fence filled by summer docs:sync.
docs/index.md: add a "Coming from WinterCMS" link.
cmd/summer/docs_test.go: TestDocsRequiredPages holds a slice of required page URLs (start with index, setup/installation, setup/coming-from-wintercms) and asserts each is a page in the loaded tree and is present as .html and .md in a real-tree build.
Run go run ./cmd/summer docs:sync, then go run ./cmd/summer docs:build --check; fix every reported problem in the page, not in the checker.
go vet ./... && go test ./modules/party -run '^ExamplePlugin$' -count=1 -v && go test ./cmd/summer -run '^(TestDocsTree|TestDocsRequiredPages)$' -count=1 -v
<fails_when>non-zero exit, a "--- FAIL" line, or "no tests to run"</fails_when>
<acceptance_criteria>
go test ./modules/party -run '^ExamplePlugin$' -count=1 -v prints --- PASS: ExamplePlugin.
grep -n 'src=modules/party/example_test.go#ExamplePlugin' docs/setup/coming-from-wintercms.md finds a match.
grep -oE '[a-z]+\.[A-Z][A-Za-z0-9]+' docs/setup/coming-from-wintercms.md | sort -u | wc -l prints at least 15 (distinct package-qualified identifiers, each verified by TestDocsTree).
grep -c 'Not provided' docs/setup/coming-from-wintercms.md prints at least 1.
go run ./cmd/summer docs:build --check exits 0.
! grep -rniE 'fonoteka|p(l|ł)ytarium' docs modules/party/example_test.go (no match).
</acceptance_criteria>
The concept map page exists in Setup with every SummerCMS identifier verified and a running plugin Example, and the real-tree checks pass.
Task 2: Architecture and Plugins sections explain the single binary, the lifecycle and how plugins register, schedule, extend and test
docs/site.yaml, docs/architecture/introduction.md, docs/architecture/go-modules-and-workspaces.md, docs/architecture/application-lifecycle.md, docs/architecture/request-lifecycle.md, docs/plugins/registration.md, docs/plugins/scheduling.md, docs/plugins/extending.md, docs/plugins/testing.md, modules/backpack/example_test.go, modules/pact/example_test.go, modules/festival/example_test.go, modules/towel/example_test.go, cmd/summer/docs_test.go
- modules/backpack/README.md, modules/party/README.md, modules/pact/README.md, modules/festival/README.md, modules/towel/README.md, modules/surf/README.md, modules/conga/README.md, modules/tide/README.md
- `go doc -all ./modules/backpack`, `go doc ./modules/pact HasSchedule`, `go doc ./modules/pact Cadence`, `go doc ./modules/festival Bus`, `go doc ./modules/towel`
- internal/build/build.go (generated main shape) and internal/build/scaffold.go (plugin leaves)
- README.md "Using SummerCMS in an application" (go.mod replace example)
- .planning/phases/11-jobs-realtime-and-search-infrastructure/11-02-SUMMARY.md (schedule semantics: ids, Daily/DailyAt/Every limits, schedule:run --once)
Per D-08 (Winter Architecture and Plugins sections, RESEARCH Q1 mapping):
docs/site.yaml: insert architecture ("Architecture") and plugins ("Plugins") after setup in the same change as their first pages.
Architecture pages (orders 10, 20, 30, 40):
introduction.md: one binary with compiled plugins, headless JSON API plus embedded admin SPA, the module map grouped by concern with README links, what runs where (summer tool vs application binary).
go-modules-and-workspaces.md: the framework module path, requiring it with a replace during development, go.work for local plugins, summer.yaml manifest, forking a plugin with a replace directive (Winter "Replacement and forking"). go.mod and summer.yaml appear as text/yaml fences.
application-lifecycle.md: party ordering by Requires, Register then Boot, the backpack.App container and its typed service registry, capability interfaces checked by the kernel, database-dependent boot work through lagoon.OnDatabase. One verified snippet from modules/backpack/example_test.go (for example publishing and looking up a typed service).
request-lifecycle.md: routes collected from pact.HasRoutes, named middleware, groups, constraints, body limits, CORS and recovery in surf, request values in towel context, JSON responses through wire. One verified snippet from modules/towel/example_test.go (ExampleWithLocale or similar with deterministic output).
Plugins pages (orders 10, 20, 30, 40):
registration.md: plugin ID rules (vendor.plugin), party.Plugin, the pact capability interfaces a plugin opts into, embedded config, lang and mail template filesystems, the scaffolded plugin layout.
scheduling.md: pact.HasSchedule, pact.ScheduledCommand, pact.Cadence with Daily, DailyAt and Every and their limits, how conga runs schedules (leader election, one run across instances), schedule:run and schedule:run --once for system cron. One verified snippet from modules/pact/example_test.go that builds a schedule entry and prints it.
extending.md: extending other plugins through festival events, optional dependencies, services published on the app, GORM callbacks for model hooks, forking with replace. One verified snippet from modules/festival/example_test.go (ExampleBus_Fire style: listen, fire, print).
testing.md: go test ./... and -short, Docker-backed tests with testcontainers-go and the ICU locale lagoon requires, parity replay with tide (link the tide README), where Examples fit. Commands as sh fences.
Append the eight page URLs to TestDocsRequiredPages.
Run go run ./cmd/summer docs:sync and go run ./cmd/summer docs:build --check and fix every problem in the pages.
go vet ./... && go test ./modules/backpack ./modules/pact ./modules/festival ./modules/towel -run '^Example' -count=1 -v && go test ./cmd/summer -run '^(TestDocsTree|TestDocsRequiredPages|TestDocsAIOutputsInSync)$' -count=1
<fails_when>non-zero exit, a "--- FAIL" line, or "no tests to run"</fails_when>
<acceptance_criteria>
ls docs/architecture/*.md docs/plugins/*.md | wc -l prints 8.
grep -Ec 'architecture|plugins' docs/site.yaml prints at least 2, and a real-tree build's index.html sidebar links architecture/introduction.html and plugins/registration.html.
Each of modules/backpack/example_test.go, modules/pact/example_test.go, modules/festival/example_test.go, modules/towel/example_test.go contains // Output: (grep -l '// Output:' lists all four).
grep -c 'src=modules/' docs/architecture/application-lifecycle.md docs/architecture/request-lifecycle.md docs/plugins/scheduling.md docs/plugins/extending.md reports at least 1 for each file.
grep -n 'schedule:run --once' docs/plugins/scheduling.md finds a match.
go run ./cmd/summer docs:build --check exits 0.
</acceptance_criteria>
Architecture and Plugins sections are in the sidebar with verified examples for the container, request context, schedules and events, and the real-tree checks pass.
Task 3: Setup and Console sections take a developer from install to every summer and runtime command
docs/site.yaml, docs/index.md, docs/setup/introduction.md, docs/setup/installation.md, docs/setup/configuration.md, docs/console/introduction.md, docs/console/setup-and-maintenance.md, docs/console/scaffolding.md, docs/console/writing-commands.md, docs/console/utilities.md, modules/bonfire/example_test.go, cmd/summer/docs_test.go
- README.md (Requirements, Quick start, Known issues, Development)
- docs/setup/installation.md (plan 11.1-01 version, keep its ExampleCall snippet)
- modules/compass/README.md (config layering, SUMMER_ overrides), modules/lagoon/README.md (database config, key:generate), modules/surf/README.md (http.body_limits), modules/cabana/README.md (admin config, admin:create)
- cmd/summer/main.go and cmd/summer/runtime.go (tool command names, flags, delegation to bin/)
- modules/bonfire/README.md and `go doc -all ./modules/bonfire`
- internal/build/artifact.go (what each make:* command writes)
- .planning/phases/11-jobs-realtime-and-search-infrastructure/11-01-SUMMARY.md and 11-04-SUMMARY.md (queue:work, queue:clear, websockets:* commands)
Per D-08 (Winter Getting started and Console) and D-03 (the docs:* commands are part of the tool):
docs/site.yaml: insert console ("Console") after the sections that exist, before api.
Setup pages:
introduction.md (order 10): what SummerCMS is, the headless model, who it is for, how the sections are organised, links to Installation and Coming from WinterCMS.
installation.md (order 20, rewrite, keep the ExampleCall snippet section): requirements, go install ./cmd/summer, building examples/hello with summer build, running ./bin/hello greeter:hello and ./bin/hello key:generate, creating the database with TEMPLATE template0 ... LOCALE_PROVIDER icu ICU_LOCALE 'pl-PL', the http.body_limits requirement, SUMMER_ environment variables with secrets written as <secret> markers (never real-looking keys), ./bin/hello migrate, ./bin/hello route:list, ./bin/hello serve --addr 127.0.0.1:8080 (loopback in examples). State the current known issues from the root README as a > [!WARNING] callout.
configuration.md (order 30): the config/ directory and per-environment directories, embedded plugin defaults, the SUMMER_ override rule (double underscore separates path segments), the keys an application must set (take them from the module READMEs' Configuration sections: database, app key, body limits, uploads storage, admin JWT secret and prefix, mail driver, queue, realtime, search and push drivers), each linked to its module README. Add a > [!NOTE] that config keys in the docs are reviewed by hand (not checker-verified).
Console pages (orders 10-50):
introduction.md: the summer tool vs the application binary, which summer commands delegate to bin/<binary>, and --help.
setup-and-maintenance.md: every application runtime command with its flags and purpose: migrate, migrate:rollback --plugin, migrate:status, key:generate, serve, route:list, admin:create, admin:reset-password, queue:work --queue, queue:clear, schedule:run --once, websockets:health, websockets:generate-vapid-keys, websockets:test-push; say which ones an application appends itself (the websockets commands come from centrifugo.Commands and flare.Commands).
scaffolding.md: make:plugin, make:model --no-migration, make:migration, make:command, make:job, make:admin-controller, plugin:add, build, dev; the files each writes (from internal/build/artifact.go) and the same-plugin and one-argument forms.
writing-commands.md: bonfire.Command, bonfire.Arg, bonfire.Flag (Bare, Repeatable), bonfire.Input, bonfire.Output, running a command in-process with bonfire.Call and bonfire.Catalog, registering through pact.HasCommands. One or two verified snippets from modules/bonfire/example_test.go (reuse ExampleCall; add an Example for flags if useful).
utilities.md: parity:proxy, parity:record, parity:replay, parity:broadcasts (link the tide README) and docs:build, docs:sync, docs:serve with their flags.
Write every command as summer <name> or ./bin/<app> <name> in sh fences or code spans so the command checker verifies it.
docs/index.md: a short "Where to start" list linking the Setup, Architecture, Plugins and Console introductions.
Append the eight page URLs (introduction, configuration, five console pages; installation is already listed) to TestDocsRequiredPages.
Run go run ./cmd/summer docs:sync and go run ./cmd/summer docs:build --check; fix every problem.
go vet ./... && go test ./modules/bonfire -run '^Example' -count=1 -v && go test ./cmd/summer -run '^(TestDocsTree|TestDocsRequiredPages|TestDocsAIOutputsInSync|TestDocsBuildRealTree)$' -count=1
<fails_when>non-zero exit, a "--- FAIL" line, or "no tests to run"</fails_when>
scripts/check-phase11.1.sh --docs && scripts/check-phase11.1.sh --forbidden
<fails_when>non-zero exit or a line starting "refuse:"</fails_when>
<acceptance_criteria>
ls docs/setup/*.md | wc -l prints 4 and ls docs/console/*.md | wc -l prints 5.
grep -c 'websockets:health' docs/console/setup-and-maintenance.md prints at least 1 and grep -c 'schedule:run' docs/console/setup-and-maintenance.md prints at least 1.
grep -c 'make:admin-controller' docs/console/scaffolding.md prints at least 1.
grep -c 'docs:serve' docs/console/utilities.md prints at least 1.
grep -n 'ICU_LOCALE' docs/setup/installation.md finds a match and grep -n 'src=modules/bonfire/example_test.go#ExampleCall' docs/setup/installation.md still finds a match.
go run ./cmd/summer docs:build --check exits 0.
</acceptance_criteria>
Setup and Console sections document install, configuration and every summer and runtime command, all command names checker-verified, with the real-tree checks and gate docs/forbidden modes green.
<threat_model>
Trust Boundaries
Boundary
Description
docs pages → operators
Operators copy commands and config from the docs into real deployments