docs(quick-260928-lf2): rewrite module READMEs and root README
This commit is contained in:
@@ -32,7 +32,7 @@ See: .planning/PROJECT.md (updated 2026-09-16)
|
||||
Phase: 9 — Backend admin authentication and schema pipeline
|
||||
Plan: Not started
|
||||
Status: Ready to plan
|
||||
Last activity: 2026-09-28 — Phase 10.2 complete, transitioned to Phase 9
|
||||
Last activity: 2026-09-28 - Completed quick task 260928-lf2: Rewrite module READMEs and root README as professional app-agnostic docs
|
||||
|
||||
Progress: [██████░░░░] 60%
|
||||
|
||||
@@ -363,6 +363,7 @@ None yet.
|
||||
|---|-------------|------|--------|-----------|
|
||||
| 260927-q23 | fix CR-01: /auth/refresh must enforce tokens_valid_after and is_activated | 2026-09-27 | be4a923 | [260927-q23-fix-cr-01-auth-refresh-must-enforce-toke](./quick/260927-q23-fix-cr-01-auth-refresh-must-enforce-toke/) |
|
||||
| 2 | make admin SPA edit/create and settings forms full width | 2026-09-27 | 2585671 | — |
|
||||
| 260928-lf2 | Rewrite module READMEs and root README as professional app-agnostic docs | 2026-09-28 | fafb12f | [260928-lf2-rewrite-module-readmes-and-root-readme-a](./quick/260928-lf2-rewrite-module-readmes-and-root-readme-a/) |
|
||||
|
||||
## Deferred Items
|
||||
|
||||
|
||||
@@ -0,0 +1,269 @@
|
||||
---
|
||||
phase: quick-260928-lf2
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- modules/backpack/README.md
|
||||
- modules/boardwalk/README.md
|
||||
- modules/bonfire/README.md
|
||||
- modules/bouncer/README.md
|
||||
- modules/cabana/README.md
|
||||
- modules/compass/README.md
|
||||
- modules/festival/README.md
|
||||
- modules/fetchguard/README.md
|
||||
- modules/lagoon/README.md
|
||||
- modules/pact/README.md
|
||||
- modules/party/README.md
|
||||
- modules/phrasebook/README.md
|
||||
- modules/postcard/README.md
|
||||
- modules/surf/README.md
|
||||
- modules/tide/README.md
|
||||
- modules/towel/README.md
|
||||
- modules/wire/README.md
|
||||
- modules/wristband/README.md
|
||||
- README.md
|
||||
- CLAUDE.md
|
||||
autonomous: true
|
||||
requirements: [QUICK-260928-lf2]
|
||||
|
||||
estimate:
|
||||
tokens: 260000
|
||||
raw_tokens: 260000
|
||||
tasks: 3
|
||||
confidence: low
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "Each of the 18 module READMEs follows the approved template: H1 name, one-sentence summary, the import line, then Overview, Features, Usage, API reference, optional Configuration and CLI commands, Dependencies, Testing, in that order"
|
||||
- "No module README and not the root README names a consuming application; examples use neutral names such as blog and acme"
|
||||
- "Every package-qualified identifier (for example surf.BuildRouter) and every bare mixed-case backticked identifier in a module README resolves through go doc against that module"
|
||||
- "Every relative Markdown link in README.md and modules/*/README.md points at a path that exists"
|
||||
- "The root README reads as a framework README: what SummerCMS is, key concepts, requirements, a quick start on examples/hello, the repository layout, an 18-row modules table, the module path plus local replace pattern, development commands, and links to .planning/notes"
|
||||
- "CLAUDE.md has a Documentation section, outside every GSD-managed marker block, that requires module README updates in the same change as any modules/ API, config, CLI or dependency change"
|
||||
- "No Go file changes; go vet ./... and go test ./... stay green"
|
||||
artifacts:
|
||||
- path: "modules/<name>/README.md (x18)"
|
||||
provides: "Professional, app-agnostic per-module documentation built from the real exported API"
|
||||
contains: "## API reference"
|
||||
- path: "README.md"
|
||||
provides: "Generic SummerCMS (Go) framework README with modules table"
|
||||
contains: "](modules/wristband/README.md)"
|
||||
- path: "CLAUDE.md"
|
||||
provides: "Documentation rule keeping module READMEs current"
|
||||
contains: "## Documentation"
|
||||
key_links:
|
||||
- from: "README.md modules table"
|
||||
to: "modules/<name>/README.md"
|
||||
via: "one relative link per module, purpose text matching the module README summary sentence"
|
||||
pattern: "\\]\\(modules/[a-z]+/README\\.md\\)"
|
||||
- from: "modules/<name>/README.md identifiers"
|
||||
to: "exported API of git.golem15.com/golem15/summercms/modules/<name>"
|
||||
via: "go doc resolution check"
|
||||
pattern: "go doc ./modules/"
|
||||
- from: "CLAUDE.md Documentation section"
|
||||
to: "modules/*/README.md and the root README modules table"
|
||||
via: "same-change update rule"
|
||||
pattern: "## Documentation"
|
||||
---
|
||||
|
||||
<!-- planner-discipline-allow: fonoteka -->
|
||||
<!-- planner-discipline-allow: płytarium -->
|
||||
<!-- planner-discipline-allow: plytarium -->
|
||||
<!-- planner-discipline-allow: plytadmin -->
|
||||
<!-- planner-discipline-allow: fonoteka|płytarium|plytarium|plytadmin -->
|
||||
<!-- planner-discipline-allow: co-authored-by -->
|
||||
|
||||
<objective>
|
||||
Rewrite the 18 three-line module READMEs under `modules/` into professional, app-agnostic docs that describe what each package exports today, turn the root `README.md` from an application runbook into a generic SummerCMS (Go) framework README, and add a CLAUDE.md rule that keeps module READMEs current.
|
||||
|
||||
This implements the user-approved design at `/home/jin/.claude/plans/in-phase-10-2-we-enchanted-candy.md` faithfully (template, rules, root README outline, CLAUDE.md rule, commit split, verification). That design is locked: do not add, drop or reorder template sections, and do not skip any verification check.
|
||||
|
||||
Purpose: framework consumers (and agents) get accurate per-module docs; the framework repo stops describing one consuming application, matching the two-repository boundary.
|
||||
Output: 18 rewritten module READMEs, a rewritten root README, a new CLAUDE.md Documentation section, three docs commits. No Go code changes.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/gsd-core/workflows/execute-plan.md
|
||||
@~/.claude/gsd-core/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@/home/jin/.claude/plans/in-phase-10-2-we-enchanted-candy.md
|
||||
@/media/nvme/dev/golem15/summercms.io/summercms/summercms.go/CLAUDE.md
|
||||
@/media/nvme/dev/golem15/summercms.io/summercms/summercms.go/README.md
|
||||
@/media/nvme/dev/golem15/summercms.io/summercms/summercms.go/scripts/check-phase10.2.sh
|
||||
@/media/nvme/dev/golem15/summercms.io/summercms/summercms.go/examples/hello/go.mod
|
||||
@/media/nvme/dev/golem15/summercms.io/summercms/summercms.go/examples/hello/summer.yaml
|
||||
@/media/nvme/dev/golem15/summercms.io/summercms/summercms.go/admin/package.json
|
||||
|
||||
Repo root (all commands run from here): `/media/nvme/dev/golem15/summercms.io/summercms/summercms.go`. Module path: `git.golem15.com/golem15/summercms`. The Bash tool runs bash even though the login shell is fish.
|
||||
|
||||
## Module README template (locked, from the approved design)
|
||||
|
||||
```
|
||||
# <name>
|
||||
|
||||
<One-sentence summary of what the package does.>
|
||||
|
||||
`import "git.golem15.com/golem15/summercms/modules/<name>"`
|
||||
|
||||
## Overview
|
||||
2–4 sentences: the responsibility, where it sits in the framework, and its WinterCMS counterpart if one exists.
|
||||
|
||||
## Features
|
||||
Bullets built from the real exported API.
|
||||
|
||||
## Usage
|
||||
A short, correct Go snippet using real exported identifiers, checked against the source.
|
||||
|
||||
## API reference
|
||||
A table of the main exported types and functions with one-line descriptions. It stays selective: no dump of every symbol.
|
||||
|
||||
## Configuration (only if the module reads compass keys / env vars)
|
||||
## CLI commands (only if it registers cobra commands, e.g. lagoon, cabana, surf route:list)
|
||||
## Dependencies
|
||||
Other summercms modules and third-party libraries it imports, taken from its import list.
|
||||
|
||||
## Testing
|
||||
How to run its tests (`go test ./modules/<name>/...`), plus any build tag or testcontainers requirement (lagoon postgres tests, postcard mailpit).
|
||||
```
|
||||
|
||||
The parenthetical notes after "Configuration" and "CLI commands" are template guidance, not heading text: the headings are exactly `## Configuration` and `## CLI commands`.
|
||||
|
||||
## Rules (locked)
|
||||
|
||||
- Never name a consuming application (the names in the forbidden-name grep below). Say "the application" or "host application", and use neutral example names (`blog`, `acme`).
|
||||
- Every identifier in a README must exist in the package. Verify with `go doc ./modules/<name>` and `grep`.
|
||||
- Leave out any optional section that does not apply rather than padding it.
|
||||
|
||||
## Facts gathered at plan time (verify, do not trust blindly)
|
||||
|
||||
- Go packages: the 18 modules plus one subpackage, `modules/lagoon/attach` (import `git.golem15.com/golem15/summercms/modules/lagoon/attach`). `phrasebook/lang`, `phrasebook/backend/lang`, `boardwalk/dist` and `postcard/assets` are embedded asset trees, not packages.
|
||||
- No module uses `//go:build` tags.
|
||||
- `testdata/` exists in `cabana` and `tide`.
|
||||
- testcontainers-go is used by tests in `bouncer`, `cabana`, `lagoon` (including `lagoon/attach`) and `postcard` (Mailpit). Those tests need Docker and skip under `go test -short`.
|
||||
- Non-test files that register CLI commands: `modules/cabana/commands.go`, `modules/lagoon/commands.go`, `modules/lagoon/keygen.go`, `modules/surf/serve.go`, `modules/surf/routelist_command.go`. `modules/pact/capabilities.go` declares the command capability contract only.
|
||||
- Likely Configuration candidates (confirm by grepping non-test sources for config key reads and `os.Getenv`): cabana (admin.* / backend.*), compass (the loader itself and the `SUMMER_` env overlay), fetchguard (http.fetch.*), lagoon (database.dsn, app.key, app.previous_keys), phrasebook (app.locale, app.fallback_locale), postcard (mail.*), surf.
|
||||
- `summer` CLI commands (cmd/summer): build, dev, plugin:add, make:plugin, make:model, make:migration, make:command, make:job, make:admin-controller, parity:proxy, parity:record, parity:replay. Built app binaries get migrate, migrate:rollback, migrate:status, key:generate, serve, route:list, admin:create, admin:reset-password from the modules.
|
||||
- `examples/hello` builds binary `hello` into `examples/hello/bin/` (gitignored); its config has no database section. `examples/hello/go.mod` shows the local `replace git.golem15.com/golem15/summercms => ../..` pattern.
|
||||
- `admin/package.json` scripts: dev, build, typecheck, test, gen:api.
|
||||
- `.planning/notes/` holds six notes; two have the forbidden application token in their filename, so the root README must link the notes directory and the four app-neutral notes (why-go-not-scala.md, apparatus-dissolved-into-framework.md, plugin-layout-winter-directories.md, oauth2-wristband-direct-port.md) only.
|
||||
- `scripts/check-phase10.2.sh --readmes` requires all 18 module READMEs to exist; `--status` refuses the old pre-alpha status line in README.md.
|
||||
|
||||
## Module batches (source size balanced; for Task 1 fan-out)
|
||||
|
||||
- Batch A: cabana, backpack, towel, wire, festival, party
|
||||
- Batch B: tide, lagoon (with lagoon/attach), bonfire, boardwalk, compass, pact
|
||||
- Batch C: wristband, surf, bouncer, phrasebook, postcard, fetchguard
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Rewrite the 18 module READMEs from the real exported API</name>
|
||||
<files>modules/backpack/README.md, modules/boardwalk/README.md, modules/bonfire/README.md, modules/bouncer/README.md, modules/cabana/README.md, modules/compass/README.md, modules/festival/README.md, modules/fetchguard/README.md, modules/lagoon/README.md, modules/pact/README.md, modules/party/README.md, modules/phrasebook/README.md, modules/postcard/README.md, modules/surf/README.md, modules/tide/README.md, modules/towel/README.md, modules/wire/README.md, modules/wristband/README.md</files>
|
||||
<read_first>/home/jin/.claude/plans/in-phase-10-2-we-enchanted-candy.md (template, rules, verification), the "Module README template", "Rules" and "Facts gathered at plan time" sections of this plan's context block.</read_first>
|
||||
<action>
|
||||
Per module, research before writing, in this order: (a) run `go doc -all ./modules/<name>` (and `go doc -all ./modules/lagoon/attach` for lagoon) and read the full output; (b) read the module's non-test `.go` sources (list them with `find modules/<name> -maxdepth 1 -name '*.go' ! -name '*_test.go'`); for the four largest packages (cabana, tide, lagoon, wristband) read the entry-point files go doc points at and grep the remaining files for config key reads, `os.Getenv`, command registrations and exported constructors instead of reading every file end to end; (c) collect the import list with `go list -f '{{join .Imports "\n"}}' ./modules/<name>` (plus `./modules/lagoon/attach`) and split it into summercms modules, third-party libraries and stdlib; (d) check for `testdata/`, `//go:build` tags, testcontainers or Mailpit usage and `testing.Short()` gates in the `_test.go` files.
|
||||
|
||||
Then write `modules/<name>/README.md` following the template exactly: H1 is the bare module name; one summary sentence; the backticked import line; `## Overview` (2–4 sentences, including the WinterCMS counterpart when one exists, e.g. compass vs Winter config, lagoon vs Winter models/migrations, cabana vs Winter backend controllers/behaviors, bonfire vs artisan console, party vs Winter PluginBase/PluginManager); `## Features` bullets from the exported API; `## Usage` with one short Go snippet using real exported identifiers whose argument lists match the go doc signatures; `## API reference` as a selective Markdown table (identifier, one-line description); `## Configuration` only when the module reads config keys or env vars (list each key, its default and what it controls, all confirmed in source); `## CLI commands` only for modules that register commands (cabana, lagoon, surf: list each command name and its flags from the source); `## Dependencies` from the import list (write "Standard library only." if there are none beyond stdlib); `## Testing` with `go test ./modules/<name>/...`, and for bouncer, cabana, lagoon and postcard state that the integration tests start containers through testcontainers-go, need Docker, and are skipped by `go test -short ./modules/<name>/...`. Document `lagoon/attach` inside the lagoon README (its own import line and table rows in API reference), not as a separate README.
|
||||
|
||||
Writing conventions that make the automated checks meaningful: outside code blocks, write Go identifiers package-qualified (`surf.BuildRouter`, `backpack.App`, `bonfire.Flag.Repeatable`, `attach.Publish`) so the resolver can check them; only backtick a capitalised word when it is a Go identifier of that module (put HTTP methods, header values and prose words in plain text); link other modules with relative paths such as `../surf/README.md`. Per the locked rules: no consuming-application names anywhere, neutral example names (`blog`, `acme`) in snippets and config examples, no secret-looking example values (use placeholders like `change-me` or `<secret>`), and no padding of sections that do not apply.
|
||||
|
||||
Pilot then fan out: write `modules/wire/README.md` first and run all four verify checks below against it; adjust the approach until it passes. Then, when a subagent spawner is available, run the three batches from the context block in parallel with 3 general-purpose agents (6 modules each); give each agent this task's research steps, the template, the rules, the writing conventions and the finished wire README as the reference example, and tell them to write files only (no git). When no spawner is available, process the batches sequentially yourself. Afterwards review all 18 for consistency: same heading set and order, same table column headers (Identifier | Description), same Testing phrasing for the Docker-backed modules, summary sentences that each fit on one line.
|
||||
|
||||
Commit only the 18 README paths, staged by explicit path (the working tree holds unrelated planning changes, so never stage everything): one commit with subject `docs(modules): rewrite module READMEs`, or one commit per batch with that same subject, as the approved design allows. No co-author trailer in any commit message (project and user rule).
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && ! grep -riE 'fonoteka|płytarium|plytarium|plytadmin' modules/*/README.md && echo NAMES OK</automated>
|
||||
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && fail=0; for d in modules/*/; do n=$(basename "$d"); r="$d/README.md"; head -1 "$r" | grep -qx "# $n" || { echo "TITLE $n"; fail=1; }; grep -qF "\`import \"git.golem15.com/golem15/summercms/modules/$n\"\`" "$r" || { echo "IMPORT $n"; fail=1; }; grep -E '^## ' "$r" | sed 's/^## //' | paste -sd';' | grep -qxE 'Overview;Features;Usage;API reference(;Configuration)?(;CLI commands)?;Dependencies;Testing' || { echo "SECTIONS $n"; fail=1; }; grep -qF "go test ./modules/$n/..." "$r" || { echo "TESTCMD $n"; fail=1; }; done; for n in cabana lagoon surf; do grep -qx '## CLI commands' "modules/$n/README.md" || { echo "CLI $n"; fail=1; }; done; for n in bouncer cabana lagoon postcard; do grep -qF -- '-short' "modules/$n/README.md" || { echo "SHORT $n"; fail=1; }; done; [ $fail = 0 ] && echo STRUCTURE OK; exit $fail</automated>
|
||||
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && fail=0; mods="$(ls modules | paste -sd'|')|attach"; for r in modules/*/README.md; do n=$(basename "$(dirname "$r")"); for t in $(grep -oE "\b($mods)\.[A-Z][A-Za-z0-9_]*(\.[A-Z][A-Za-z0-9_]*)?" "$r" | sort -u); do p=${t%%.*}; s=${t#*.}; d=./modules/$p; [ "$p" = attach ] && d=./modules/lagoon/attach; go doc "$d" "$s" >/dev/null 2>&1 || { echo "UNRESOLVED $r: $t"; fail=1; }; done; for t in $(grep -oE '`[A-Z][a-z][A-Za-z0-9]*(\.[A-Z][A-Za-z0-9]*)?`' "$r" | tr -d '`' | sort -u); do go doc "./modules/$n" "$t" >/dev/null 2>&1 || { echo "UNRESOLVED $r: bare $t"; fail=1; }; done; done; [ $fail = 0 ] && echo IDENTS OK; exit $fail</automated>
|
||||
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && fail=0; for r in modules/*/README.md; do d=$(dirname "$r"); for l in $(grep -oE '\]\([^)#[:space:]]+' "$r" | sed 's/^](//' | grep -vE '^(https?|mailto):'); do [ -e "$d/$l" ] || { echo "BROKEN $r -> $l"; fail=1; }; done; done; [ $fail = 0 ] && echo LINKS OK; exit $fail</automated>
|
||||
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && bash scripts/check-phase10.2.sh --readmes && echo READMES EXIST</automated>
|
||||
</verify>
|
||||
<done>All 18 module READMEs follow the locked template and section order, name no consuming application, resolve every checked identifier through go doc, have no broken relative links, document CLI commands for cabana/lagoon/surf and the Docker/-short behaviour for bouncer/cabana/lagoon/postcard, and are committed as `docs(modules): rewrite module READMEs` (one commit or one per batch) with no co-author trailer.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Rewrite the root README as a generic SummerCMS (Go) framework README</name>
|
||||
<files>README.md</files>
|
||||
<read_first>README.md (current), the 18 new modules/*/README.md summary sentences, cmd/summer/main.go and cmd/summer/runtime.go (command names), internal/build/build.go (what summer build generates and where the binary goes), examples/hello/summer.yaml, examples/hello/config/app.yaml, examples/hello/go.mod, admin/package.json, the file list of .planning/notes/.</read_first>
|
||||
<action>
|
||||
Replace `README.md` entirely, following the approved outline in this order: (1) what SummerCMS is: a Go content management framework inspired by WinterCMS, built as a single compiled binary; (2) key concepts: compiled plugins registered at build time, YAML-driven admin forms and lists, a headless API, the scaffolding CLI; (3) requirements: Go 1.27, PostgreSQL, Node.js only for working on the admin SPA, Docker for the testcontainers-backed integration tests; (4) quick start using `examples/hello` and the `summer` CLI (install with `go install ./cmd/summer`, then `summer build` inside `examples/hello`, then run the built binary with `serve` and `migrate`, pointing it at Postgres through the `SUMMER_`-prefixed database DSN env var that compass and lagoon actually read); (5) repository layout covering `admin/`, `cmd/`, `examples/`, `internal/`, `modules/`, `scripts/` with one line each; (6) a modules table with columns Module | Purpose, one row per module (all 18, alphabetical), the Module cell linking `modules/<name>/README.md` and the Purpose cell reusing that README's summary sentence; (7) using SummerCMS in an application: require the module path `git.golem15.com/golem15/summercms` and use a local `replace git.golem15.com/golem15/summercms => ../summercms.go` directive during development, shown with a neutral example module such as `acme`, and point at `examples/hello/go.mod` as the working reference; (8) development: `go vet ./...`, `go test ./...`, `go test -short ./...` for the fast loop without Docker, and the admin SPA npm scripts from admin/package.json run with `npm --prefix admin run <script>`; (9) links to `.planning/notes/` plus the four app-neutral notes named in this plan's context block.
|
||||
|
||||
Before writing the quick start, confirm every command: run `go run ./cmd/summer --help`, then run `summer build` inside `examples/hello` (an installed binary, or `go run ../../cmd/summer build` from that directory) and `./bin/hello --help`, and quote only command names that appear in that output. Afterwards `git status --porcelain examples/` must be empty (bin/ is gitignored); if generation touched a tracked file, restore it with `git checkout -- examples/hello`. If `serve` or `migrate` cannot run without a database, say so in the README and show the env var rather than inventing a flag.
|
||||
|
||||
Per the approved design, drop the application-specific run steps, the cutover status section, the admin path of the consuming application and any sibling application repository link: the root README must not name a consuming application at all (same forbidden-name grep as Task 1). Do not edit any other repository; if that material is missing from the application repo's own README, record it as a follow-up in the SUMMARY instead. Keep the pre-alpha status line refused by `scripts/check-phase10.2.sh --status` out of the file.
|
||||
|
||||
Commit only `README.md`, staged by explicit path, with subject `docs: generic root README` and no co-author trailer.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && ! grep -iE 'fonoteka|płytarium|plytarium|plytadmin' README.md && echo NAMES OK</automated>
|
||||
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && fail=0; for n in $(ls modules); do grep -qF "](modules/$n/README.md)" README.md || { echo "TABLE $n"; fail=1; }; done; for s in 'git.golem15.com/golem15/summercms' 'replace git.golem15.com/golem15/summercms' 'examples/hello' 'summer build' 'go vet ./...' 'go test ./...' 'go test -short' 'npm --prefix admin' '.planning/notes' 'Go 1.27' 'PostgreSQL'; do grep -qF -- "$s" README.md || { echo "MISSING $s"; fail=1; }; done; for dir in admin cmd examples internal modules scripts; do grep -qF "$dir/" README.md || { echo "LAYOUT $dir"; fail=1; }; done; [ $fail = 0 ] && echo ROOT OK; exit $fail</automated>
|
||||
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && fail=0; for r in README.md modules/*/README.md; do d=$(dirname "$r"); for l in $(grep -oE '\]\([^)#[:space:]]+' "$r" | sed 's/^](//' | grep -vE '^(https?|mailto):'); do [ -e "$d/$l" ] || { echo "BROKEN $r -> $l"; fail=1; }; done; done; [ $fail = 0 ] && echo LINKS OK; exit $fail</automated>
|
||||
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && bash scripts/check-phase10.2.sh --status && st=$(git status --porcelain examples/) && test -z "$st" && echo STATUS OK</automated>
|
||||
</verify>
|
||||
<done>README.md is a generic framework README covering all nine outline items, links all 18 module READMEs from the modules table, names no consuming application, has no broken relative links, passes check-phase10.2.sh --status, leaves examples/ clean, and is committed as `docs: generic root README` with no co-author trailer.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: Add the Documentation rule to CLAUDE.md</name>
|
||||
<files>CLAUDE.md</files>
|
||||
<read_first>CLAUDE.md lines 1-30 (hand-written sections and the first GSD marker).</read_first>
|
||||
<action>
|
||||
Insert a new `## Documentation` section into CLAUDE.md directly after the `## Commit rules` section and before the `<!-- GSD:project-start source:PROJECT.md -->` marker. It must sit outside every `<!-- GSD:...-start -->`/`-end -->` block, because those blocks are regenerated by GSD tooling and would drop the rule. Use Edit (a scoped insertion), never a whole-file Write.
|
||||
|
||||
The section states the approved rule as short bullets: (1) any change to a package under `modules/` that touches its exported API, config keys, CLI commands or dependencies must update that module's `README.md` in the same change (the same commit or PR); (2) a new module ships with a `README.md` that follows the standard structure (H1 name, summary sentence, import line, Overview, Features, Usage, API reference, optional Configuration and CLI commands, Dependencies, Testing) and gets a row in the root `README.md` modules table; (3) framework READMEs must never name a consuming application, and examples use neutral names such as `blog` or `acme`; (4) identifiers named in a README must exist in the package, checked with `go doc ./modules/<name> <Identifier>`. Phrase rule (3) generically, without naming any application.
|
||||
|
||||
Leave every other part of CLAUDE.md byte-identical. Commit only `CLAUDE.md`, staged by explicit path, with subject `docs(claude): require module README updates` and no co-author trailer.
|
||||
|
||||
Then run the plan-wide sanity checks: `go vet ./...` and `go test ./...` from the repo root (docs-only change, so they must stay green; the Postgres/Mailpit tests need Docker), and confirm no `.go` file changed and none of the three new commits carries a co-author trailer.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && doc=$(grep -n '^## Documentation$' CLAUDE.md | cut -d: -f1) && commit=$(grep -n '^## Commit rules$' CLAUDE.md | cut -d: -f1) && marker=$(grep -n '^<!-- GSD:project-start' CLAUDE.md | cut -d: -f1) && [ "$commit" -lt "$doc" ] && [ "$doc" -lt "$marker" ] && sed -n "${doc},${marker}p" CLAUDE.md | grep -qF 'README.md' && sed -n "${doc},${marker}p" CLAUDE.md | grep -qF 'modules/' && sed -n "${doc},${marker}p" CLAUDE.md | grep -qi 'modules table' && ! sed -n "${doc},${marker}p" CLAUDE.md | grep -qiE 'fonoteka|płytarium|plytarium' && ns=$(git diff cc584e906e2a67f7e04b979ac632d6e24c21011d --numstat -- CLAUDE.md) && [ "$(printf '%s' "$ns" | cut -f2)" = 0 ] && echo CLAUDE OK</automated>
|
||||
<automated>cd /media/nvme/dev/golem15/summercms.io/summercms/summercms.go && go vet ./... && go test ./... && st=$(git status --porcelain -- '*.go') && test -z "$st" && gd=$(git diff --name-only cc584e906e2a67f7e04b979ac632d6e24c21011d HEAD -- '*.go') && test -z "$gd" && msgs=$(git log cc584e906e2a67f7e04b979ac632d6e24c21011d..HEAD --format=%B) && ! printf '%s' "$msgs" | grep -qi 'co-authored-by' && echo SANITY OK</automated>
|
||||
</verify>
|
||||
<done>CLAUDE.md has a `## Documentation` section between `## Commit rules` and the first GSD marker stating the four-part rule without naming any application, the commit only adds lines, `go vet ./...` and `go test ./...` pass, no Go file changed, and the commit `docs(claude): require module README updates` has no co-author trailer.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
## Trust Boundaries
|
||||
|
||||
| Boundary | Description |
|
||||
|----------|-------------|
|
||||
| repository docs to public readers | READMEs are published with the framework and read by consumers and agents |
|
||||
|
||||
## STRIDE Threat Register
|
||||
|
||||
| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan |
|
||||
|-----------|----------|-----------|----------|-------------|-----------------|
|
||||
| T-lf2-01 | Information disclosure | README config and usage examples | medium | mitigate | Task 1 and Task 2 actions require placeholder values (`change-me`, `<secret>`) for keys, DSNs and JWT secrets; no real credentials or hostnames of a consuming application; the forbidden-name grep keeps application details out |
|
||||
| T-lf2-02 | Tampering (misleading docs) | module README identifiers and links | low | mitigate | go doc resolution check and relative-link check in Task 1/Task 2 verify fail on invented or stale identifiers and dead links |
|
||||
| T-lf2-03 | Repudiation (rule drift) | CLAUDE.md Documentation rule | low | mitigate | Section placed outside GSD-managed marker blocks so regeneration cannot drop it; verify asserts placement |
|
||||
| T-lf2-SC | Tampering | npm/pip/cargo installs | high | accept | No package installs in this plan; only existing tooling (go doc, go list, go vet, go test) runs |
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
Run from `/media/nvme/dev/golem15/summercms.io/summercms/summercms.go` after Task 3 (these are the approved design's checks):
|
||||
- `grep -ri 'fonoteka\|płytarium\|plytarium' README.md modules/*/README.md` returns nothing (Task 1 and Task 2 verify extend it with the old admin path).
|
||||
- Every backticked or package-qualified Go identifier in each module README resolves through `go doc ./modules/<name> <Ident>` (Task 1 IDENTS check).
|
||||
- Every relative `](path)` target in README.md and modules/*/README.md exists (Task 2 LINKS check covers all 19 files).
|
||||
- `go vet ./... && go test ./...` still pass; no `.go` file changed (Task 3 SANITY check).
|
||||
- `bash scripts/check-phase10.2.sh --readmes` and `--status` pass.
|
||||
- `git log --oneline cc584e906e2a67f7e04b979ac632d6e24c21011d..HEAD` (plan-time base) shows the module README commit(s), `docs: generic root README` and `docs(claude): require module README updates`, none with a co-author trailer, and `git diff --name-only cc584e906e2a67f7e04b979ac632d6e24c21011d HEAD -- '*.go'` lists nothing.
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- 18 module READMEs match the locked template, section order and rules; each documents the real exported API, dependencies and test requirements.
|
||||
- Root README is a generic framework README with all nine outline items and an 18-row modules table.
|
||||
- CLAUDE.md carries the Documentation rule outside GSD-managed blocks.
|
||||
- All automated checks in the three tasks pass; three (or up to five, if the module commit is split per batch) docs-only commits with the approved subjects and no co-author trailer.
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Create `.planning/quick/260928-lf2-rewrite-module-readmes-and-root-readme-a/260928-lf2-SUMMARY.md` when done. Include any follow-up for the application repository's README (material removed from the root README that is not yet documented there) as a note, without editing that repository.
|
||||
</output>
|
||||
@@ -0,0 +1,128 @@
|
||||
---
|
||||
phase: quick-260928-lf2
|
||||
plan: 01
|
||||
subsystem: docs
|
||||
status: complete
|
||||
tags: [docs, readme, modules, claude-md]
|
||||
requires: []
|
||||
provides:
|
||||
- "18 app-agnostic module READMEs built from the real exported API"
|
||||
- "Generic SummerCMS (Go) framework root README with an 18-row modules table"
|
||||
- "CLAUDE.md Documentation rule keeping module READMEs current"
|
||||
affects: [README.md, CLAUDE.md, modules/*/README.md]
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "Module README template: H1, summary, import line, Overview, Features, Usage, API reference, optional Configuration/CLI commands, Dependencies, Testing"
|
||||
key-files:
|
||||
created: []
|
||||
modified:
|
||||
- README.md
|
||||
- CLAUDE.md
|
||||
- modules/backpack/README.md
|
||||
- modules/boardwalk/README.md
|
||||
- modules/bonfire/README.md
|
||||
- modules/bouncer/README.md
|
||||
- modules/cabana/README.md
|
||||
- modules/compass/README.md
|
||||
- modules/festival/README.md
|
||||
- modules/fetchguard/README.md
|
||||
- modules/lagoon/README.md
|
||||
- modules/pact/README.md
|
||||
- modules/party/README.md
|
||||
- modules/phrasebook/README.md
|
||||
- modules/postcard/README.md
|
||||
- modules/surf/README.md
|
||||
- modules/tide/README.md
|
||||
- modules/towel/README.md
|
||||
- modules/wire/README.md
|
||||
- modules/wristband/README.md
|
||||
decisions:
|
||||
- "Root README quick start was verified end to end against a throwaway Postgres 16 container; it states the extra config the example needs instead of hiding it"
|
||||
- "Known issues found while verifying (example body limits, pl-PL locale, stale generated main.go) are documented in the root README and left unfixed, since this is a docs-only task"
|
||||
- "Module README commits were split per agent batch (three commits), as the approved design allows"
|
||||
metrics:
|
||||
completed: 2026-09-28
|
||||
tasks: 3
|
||||
files: 20
|
||||
actuals:
|
||||
tokens: 31800
|
||||
tasks: 3
|
||||
commits: 5
|
||||
plan_head_before: cc584e906e2a67f7e04b979ac632d6e24c21011d
|
||||
plan_head_after: fafb12ff02f4693d0380f7fd3ab9f8d32791ee8d
|
||||
commits: 5
|
||||
---
|
||||
|
||||
# Phase quick-260928-lf2 Plan 01: Module READMEs, Generic Root README and Documentation Rule Summary
|
||||
|
||||
The 18 module READMEs were rewritten from each package's real exported API. The root README is now a generic framework README whose quick start was verified against a real Postgres. CLAUDE.md now requires module README updates in the same change as any module API, config, CLI or dependency change.
|
||||
|
||||
## Commits
|
||||
|
||||
| Task | Commit | Subject |
|
||||
|------|--------|---------|
|
||||
| 1 (batch A) | 1bd3494 | docs(modules): rewrite cabana, wire, towel, festival, compass, backpack READMEs |
|
||||
| 1 (batch B) | 3142aeb | docs(modules): rewrite lagoon, tide, pact, party, boardwalk, fetchguard READMEs |
|
||||
| 1 (batch C) | aaa892f | docs(modules): rewrite wristband, bouncer, surf, bonfire, phrasebook, postcard READMEs |
|
||||
| 2 | 70d3c39 | docs: generic root README |
|
||||
| 3 | fafb12f | docs(claude): require module README updates |
|
||||
|
||||
No commit carries a co-author or other attribution trailer.
|
||||
|
||||
## What was done
|
||||
|
||||
- **Task 1** (done earlier, three batch commits): 18 module READMEs follow the locked template and name no consuming application. Every package-qualified identifier resolves through go doc.
|
||||
- **Task 2:** The root `README.md` covers the nine outline items: what SummerCMS is, key concepts, requirements, a quick start on `examples/hello`, the repository layout, the modules table, module path plus local replace, development commands, and design notes. The modules table has 18 rows, and each purpose cell matches that module README's summary sentence exactly (checked by script). The notes section links only the four app-neutral notes.
|
||||
- **Task 3:** `## Documentation` sits between `## Commit rules` and the first `<!-- GSD:project-start -->` marker. It has four bullets: the same-change README update rule, the standard structure plus a modules-table row for new modules, no consuming-application names, and go doc identifier checks. The change only adds lines (7 insertions, 0 deletions).
|
||||
|
||||
## Quick start verification
|
||||
|
||||
Every command in the quick start was confirmed before it was written:
|
||||
- `go run ./cmd/summer --help` and `./bin/hello --help` list the quoted commands.
|
||||
- `summer build` in `examples/hello` produces `bin/hello`.
|
||||
- `greeter:hello` and `key:generate` run without a database.
|
||||
- A throwaway `postgres:16-alpine` container, with a database created with ICU `pl-PL`, was used for the rest. With `SUMMER_DATABASE__DSN`, `SUMMER_APP__KEY` and `SUMMER_STORAGE__UPLOADS__BUCKET_URL=mem://` set, and a temporary `config/http.yaml` holding the body limits, these all succeeded: `migrate`, `migrate:status`, `route:list`, and `serve --addr` (`GET /items/1` returned `{"id":1}`).
|
||||
|
||||
Afterwards the temporary config file was removed, the regenerated `main.go` was restored and the container was stopped. `git status --porcelain examples/` is empty.
|
||||
|
||||
## Checks
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| Forbidden-name grep over README.md and modules/*/README.md | NAMES OK |
|
||||
| Root README content (TABLE/MISSING/LAYOUT) | ROOT OK |
|
||||
| Relative links in README.md and all module READMEs | LINKS OK |
|
||||
| Module README structure (title, import, section order) | STRUCTURE OK |
|
||||
| Package-qualified identifiers resolve via go doc | IDENTS OK |
|
||||
| `scripts/check-phase10.2.sh --readmes` and `--status` | pass |
|
||||
| `git status --porcelain examples/` empty | pass |
|
||||
| CLAUDE.md section placement, additions only | CLAUDE OK |
|
||||
| `go vet ./...`, `go test ./...`, no `.go` changes since cc584e9, no co-author trailer | SANITY OK |
|
||||
|
||||
The Task 1 executors reported that the plain `](` link check gives false positives on Go generics inside code blocks. The plan's check excludes `(`, `#` and whitespace from the target, and it reported no false positives on the final files.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
- **Quick start content.** The plan outline puts `serve` and `migrate` right after `summer build`. In practice they also need `app.key`, an uploads bucket URL, numeric `http.body_limits` values from a config file and an ICU `pl-PL` database. The README states these requirements and adds a Known issues subsection rather than leaving out steps. No Go code or example config was changed.
|
||||
- **Commits on master.** They were made on `master`. The project config uses `branching_strategy: none` and no worktrees, and Task 1 and the orchestrator instructions follow the same practice.
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None.
|
||||
|
||||
## Follow-ups (not fixed; docs-only task)
|
||||
|
||||
1. **`examples/hello` lacks `http.body_limits` config.** surf fails at boot with `surf: config http.body_limits.default_bytes is required`, which breaks `serve`, `route:list` and the example's `TestTypedItemRoute` (confirmed: `cd examples/hello && go test ./...` fails there). The root `go test ./...` does not cover the example module, so it stays green. Fix: add `examples/hello/config/http.yaml` with `default_bytes`/`upload_bytes`, then drop step 2 and the first Known issues bullet from the root README.
|
||||
2. **The `SUMMER_` env overlay cannot set numeric keys that surf reads.** `SUMMER_HTTP__BODY_LIMITS__DEFAULT_BYTES=1048576` is rejected with `must be numeric, got string`. Either compass should coerce these values or surf should parse numeric strings.
|
||||
3. **surf validates `http.body_limits.upload_bytes` but never applies it.**
|
||||
4. **lagoon hardcodes an application locale:** `lagoon.CheckLocale` requires ICU `pl-PL` (`requiredICULocale` in `modules/lagoon/connection.go`). This should be configurable, with `pl-PL` as the application's setting.
|
||||
5. **wristband hardcodes application values:** `wristband.DefaultOptions().Resource` is an application URL, and the scopes and `/oauth/mcp/*` paths are fixed. These should come from options or config.
|
||||
6. **The committed `examples/hello/main.go` is stale.** It predates the generator's `surf.RouteListCommand` and `cabana.RuntimeCommands` wiring, so `summer build` and the example's `TestBuiltBinary*` tests leave it modified. Fix: regenerate and commit it.
|
||||
7. **`key:generate` prints a `✓ ` prefix before the key,** so `export SUMMER_APP__KEY=$(./bin/hello key:generate)` produces an invalid key. The README tells readers to copy the value. Consider printing the bare key to stdout.
|
||||
8. **Application repository README:** the removed application-specific run steps (database setup, admin path, cutover status) should be checked against the application repository's own README. It was not edited here, per the plan.
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
- FOUND: README.md, CLAUDE.md, all 18 modules/*/README.md
|
||||
- FOUND commits: 1bd3494, 3142aeb, aaa892f, 70d3c39, fafb12f
|
||||
Reference in New Issue
Block a user