docs(33-01): complete framework seams, phase gate and release ledger plan
This commit is contained in:
@@ -0,0 +1,254 @@
|
|||||||
|
---
|
||||||
|
phase: 33-seo-output-audit-and-content
|
||||||
|
plan: 01
|
||||||
|
subsystem: framework
|
||||||
|
tags: [pact, signpost, cabana, content-descriptor, field-types, gate-script, release-ledger]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- phase: 32-seo-foundation
|
||||||
|
provides: pact.ContentDescriptor, signpost content registry, plugin field types, form extensions, check-phase32.sh engine
|
||||||
|
provides:
|
||||||
|
- pact.ContentDescriptor.Kind and Tools with ContentKind*/ContentTool* constants
|
||||||
|
- pact.ContentRecord.PublishedAt, Parents, Authors, TopHeading
|
||||||
|
- pact.ContentLocale.Images, Videos, Headings and the value types ContentRef, ContentPerson, ContentImage, ContentVideo, ContentHeading
|
||||||
|
- pact.FormFieldType.RequestOptions merged into served typeOptions per schema request
|
||||||
|
- scripts/check-phase33.sh (eleven stages plus --all)
|
||||||
|
- 33-release-log.md (v0.6.1 planned contents and release order)
|
||||||
|
affects: [33-02, 33-03, 33-04, 33-05, 33-06, 33-07, 33-08, 33-09, 33-10, 33-11, 33-12, 33-13, 33-14]
|
||||||
|
|
||||||
|
actuals:
|
||||||
|
tokens: 24700
|
||||||
|
tasks: 4
|
||||||
|
commits: 4
|
||||||
|
plan_head_before: 399efed845bc7dc7e6a1dbd26ed74d78172684e4
|
||||||
|
plan_head_after: 21aa4e5
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "Optional descriptor facts: new slices are nil-or-empty alike; signpost hands records through untouched"
|
||||||
|
- "Per-request field options: computed once per type per schema request, merged into a copy, fields.yaml wins, errors fail open with one WARN"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- modules/signpost/content_fields_smoke_test.go
|
||||||
|
- modules/cabana/field_request_options_smoke_test.go
|
||||||
|
- scripts/check-phase33.sh
|
||||||
|
- .planning/phases/33-seo-output-audit-and-content/33-release-log.md
|
||||||
|
modified:
|
||||||
|
- modules/pact/content.go
|
||||||
|
- modules/pact/capabilities.go
|
||||||
|
- modules/cabana/field_type.go
|
||||||
|
- modules/cabana/http.go
|
||||||
|
- modules/cabana/schema_types.go
|
||||||
|
- modules/cabana/admin_openapi.go
|
||||||
|
- modules/signpost/example_content_test.go
|
||||||
|
- modules/cabana/example_field_type_test.go
|
||||||
|
- admin/openapi/admin.json
|
||||||
|
- admin/src/api/schema.d.ts
|
||||||
|
- docs/plugins/menu-item-types.md
|
||||||
|
- docs/backend/field-types.md
|
||||||
|
- modules/pact/README.md
|
||||||
|
- modules/signpost/README.md
|
||||||
|
- modules/cabana/README.md
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Task 1 Decision A (Jakub 2026-11-04): as-planned; P33-01 descriptor fields/constants/value types and P33-02 FormFieldType.RequestOptions exactly as the plan names them"
|
||||||
|
- "Task 1 Decision B (Jakub 2026-11-04): WR-02 accepted; pact.RecordSaved.Locale stays the primary tag of the request locale (released in v0.5.2)"
|
||||||
|
- "Task 1 Decision C (Jakub 2026-11-04): Phase 33 delivers SummerCMS v0.6.1 (patch, additive); additive and marker stages compare with v0.6.0; plans reading v0.5.1/v0.5.2 mean v0.6.0/v0.6.1"
|
||||||
|
- "RequestOptions receives the application database bound to the request context, nil when none is configured"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "Content facts: a content type may set Kind/Tools and per-record PublishedAt/Parents/Authors/TopHeading/Images/Videos/Headings; consumers read them through signpost without importing the content plugin"
|
||||||
|
- "Phase gate: check-phase33.sh stage engine; a missing repository fails with 'missing <path>'"
|
||||||
|
|
||||||
|
requirements-completed: [SC-2, SC-3, D-93, D-90, D-106, D-43, D-86, D-31, D-85, D-50, D-51, D-96, D-10]
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
- id: D1
|
||||||
|
description: "Additive content descriptor fields and value types, handed through signpost.Describe and signpost.Records unchanged; a type without them describes as before"
|
||||||
|
requirement: "D-93"
|
||||||
|
verification:
|
||||||
|
- kind: unit
|
||||||
|
ref: "modules/signpost/content_fields_smoke_test.go#TestContentDescriptorFields"
|
||||||
|
status: pass
|
||||||
|
- kind: unit
|
||||||
|
ref: "modules/signpost/example_content_test.go#ExampleRegistry_MatchPath"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D2
|
||||||
|
description: "pact.FormFieldType.RequestOptions merged into served typeOptions (every screen, fields.yaml wins, once per type per request, error fails open with one warning, unchanged schema without it, form extension fields, authenticated handler only)"
|
||||||
|
requirement: "SC-3"
|
||||||
|
verification:
|
||||||
|
- kind: unit
|
||||||
|
ref: "modules/cabana/field_request_options_smoke_test.go#TestFieldTypeRequestOptions"
|
||||||
|
status: pass
|
||||||
|
- kind: other
|
||||||
|
ref: "scripts/check-admin-openapi.sh --check"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D3
|
||||||
|
description: "Framework API strictly additive against v0.6.0 and no framework line names SEO, a sitemap, JSON-LD or an application"
|
||||||
|
requirement: "D-106"
|
||||||
|
verification:
|
||||||
|
- kind: other
|
||||||
|
ref: "bash scripts/check-phase33.sh --go --docs --marker --additive"
|
||||||
|
status: pass
|
||||||
|
- kind: other
|
||||||
|
ref: "bash scripts/check-phase33.sh --compat"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D4
|
||||||
|
description: "check-phase33.sh with eleven stages; self-test detects an API removal, an interface method, a marker hit, a failing go test and a missing repository"
|
||||||
|
verification:
|
||||||
|
- kind: other
|
||||||
|
ref: "bash scripts/check-phase33.sh --self-test"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D5
|
||||||
|
description: "33-release-log.md records v0.6.1 planned contents, the six Phase 32 fixes as already released in v0.5.2, plugin/layer tag state and the release order"
|
||||||
|
verification: []
|
||||||
|
human_judgment: true
|
||||||
|
rationale: "A planning ledger; its accuracy and the release order are Jakub's call before 33-14 tags anything"
|
||||||
|
|
||||||
|
duration: 22min
|
||||||
|
completed: 2026-11-04
|
||||||
|
status: complete
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 33 Plan 01: Framework seams, phase gate and release ledger Summary
|
||||||
|
|
||||||
|
**Optional content facts on pact.ContentDescriptor/Record/Locale (kind, MCP tools, first publication, parents, authors, top heading, images, videos, heading outline), per-request plugin field options through pact.FormFieldType.RequestOptions, the eleven-stage check-phase33.sh gate and the v0.6.1 release ledger**
|
||||||
|
|
||||||
|
## Task 1 answers (Jakub, 2026-11-04)
|
||||||
|
|
||||||
|
Later plans (33-02 to 33-14) use these:
|
||||||
|
|
||||||
|
1. **Decision A: as-planned.** P33-01 and P33-02 are adopted exactly as written, no rename:
|
||||||
|
- `pact.ContentDescriptor.Kind string` with `ContentKindArticle = "article"`, `ContentKindCollection = "collection"`, `ContentKindProfile = "profile"`, `ContentKindPage = "page"`;
|
||||||
|
- `pact.ContentDescriptor.Tools map[string]string` with `ContentToolEdit = "edit"`, `ContentToolHeadings = "headings"`, `ContentToolImageAlt = "image_alt"` (values are full MCP tool names);
|
||||||
|
- `pact.ContentRecord.PublishedAt *time.Time`, `Parents []ContentRef`, `Authors []ContentPerson`, `TopHeading int`;
|
||||||
|
- `pact.ContentLocale.Images []ContentImage`, `Videos []ContentVideo`, `Headings []ContentHeading`;
|
||||||
|
- `ContentRef{Type, ID string}`, `ContentPerson{Name string; Ref ContentRef}`, `ContentImage{URL, Alt string; Decorative bool; Width, Height int}`, `ContentVideo{Provider, ID string}`, `ContentHeading{Level int; Text string}`;
|
||||||
|
- `pact.FormFieldType.RequestOptions func(ctx context.Context, db *gorm.DB) (map[string]any, error)` with `json:"-"`.
|
||||||
|
2. **Decision B: WR-02 accepted.** `pact.RecordSaved.Locale` stays the primary tag of the request locale, as released in v0.5.2 (commit 1583651). 32-UAT.md is left to verify-work.
|
||||||
|
3. **Decision C: version base.** Tags v0.5.2, v0.5.3 and v0.6.0 already exist and contain all six Phase 32 fixes (676ca53, 5471b66, d660cd0, 468af06, 1583651, 0e187cf). This phase delivers **SummerCMS v0.6.1** (patch, additive per D-106). `check-phase33.sh --additive` compares against the newest tag not containing HEAD (computed, currently v0.6.0); `--marker` diffs from v0.6.0 (`PHASE33_BASE`). **Where a Phase 33 plan says v0.5.1 (base) or v0.5.2 (target), read v0.6.0 and v0.6.1.** Nothing is pushed or tagged before 33-14.
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 22 min (continuation; Task 1 answered before this run)
|
||||||
|
- **Started:** 2026-11-04T07:26:44Z
|
||||||
|
- **Completed:** 2026-11-04T07:49:00Z
|
||||||
|
- **Tasks:** 4 (Task 1 decision, Tasks 2-4 executed)
|
||||||
|
- **Files modified:** 19
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- Content types can describe kind, fixing MCP tools, first publication, ordered parents, authors, top heading level, images (with alt and a decorative flag), videos and the heading outline; signpost hands them through, and a type without them is unaffected.
|
||||||
|
- A plugin field type can serve per-request options to its element through the existing `typeOptions` attribute; the compiled schema is never mutated and errors fail open.
|
||||||
|
- `scripts/check-phase33.sh` gates the phase: `--self-test`, `--go`, `--docs`, `--marker`, `--additive`, `--admin`, `--plugins` and `--compat` all pass on this host.
|
||||||
|
- `33-release-log.md` records the v0.6.1 contents and the release order 33-14 follows.
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
1. **Task 1: Confirm descriptor fields, RequestOptions, RecordSaved.Locale meaning**: no commit (decision, answers above)
|
||||||
|
2. **Task 2: Content descriptor fields (tracer)**: `561a56c` (feat)
|
||||||
|
3. **Task 3: Per-request options for plugin field types**: `4cd35c9` (feat)
|
||||||
|
4. **Task 4: Phase gate script and release log**: `6ea43bb` (test, group A), `21aa4e5` (docs, group B)
|
||||||
|
|
||||||
|
**Plan metadata:** this SUMMARY commit (docs)
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `modules/pact/content.go`: Kind, Tools, the kind and tool constants, the record and locale fields and the five value types.
|
||||||
|
- `modules/pact/capabilities.go`: `FormFieldType.RequestOptions` with its doc comment (no secrets, fails open).
|
||||||
|
- `modules/cabana/field_type.go`: `mergeRequestOptions` (once per type, copy-merge, fields.yaml wins, one WARN on error).
|
||||||
|
- `modules/cabana/http.go`: form schema route calls it on the request's own field slice; `requestDB` helper.
|
||||||
|
- `modules/cabana/schema_types.go`, `modules/cabana/admin_openapi.go`, `admin/openapi/admin.json`, `admin/src/api/schema.d.ts`: typeOptions description now names per-request options.
|
||||||
|
- `modules/signpost/content_fields_smoke_test.go`: `TestContentDescriptorFields` (full type, plain type, nil vs empty slices).
|
||||||
|
- `modules/cabana/field_request_options_smoke_test.go`: `TestFieldTypeRequestOptions`, one subtest per behaviour line plus the authenticated-handler check (T-33-01).
|
||||||
|
- `modules/signpost/example_content_test.go`, `modules/cabana/example_field_type_test.go`: runnable examples that the docs embed.
|
||||||
|
- `docs/plugins/menu-item-types.md`, `docs/backend/field-types.md`, `modules/pact/README.md`, `modules/signpost/README.md`, `modules/cabana/README.md`: documentation of every new identifier.
|
||||||
|
- `scripts/check-phase33.sh`: phase gate.
|
||||||
|
- `.planning/phases/33-seo-output-audit-and-content/33-release-log.md`: release ledger.
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- The Task 1 answers above.
|
||||||
|
- `RequestOptions` gets the application database bound to the request context, or nil when the application has none. The test service has no database, and a type that needs one can check for nil.
|
||||||
|
- The compat stage reads the sitemap and Journal plugins at their releases before the phase (v0.1.2, v0.3.1) and sm-demo-app at its HEAD when 33-01 ran (da481c9). It uses read-only snapshots, not worktrees in the sibling repos.
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 3 - Blocking] Version base moved from v0.5.1/v0.5.2 to v0.6.0/v0.6.1 (Jakub's ruling, Decision C)**
|
||||||
|
- **Found during:** Task 1 (checkpoint), applied in Task 4
|
||||||
|
- **Issue:** The plan was written before v0.5.2, v0.5.3 and v0.6.0 were tagged, so the six Phase 32 fixes are already released.
|
||||||
|
- **Fix:** The additive stage still computes the newest tag that does not contain HEAD (v0.6.0). The marker base is `PHASE33_BASE=v0.6.0`. The release log lists the fixes as "already released in v0.5.2" and plans v0.6.1. The commit subject of group B is `docs(33-01): release log for v0.6.1`, not `... v0.5.2`.
|
||||||
|
- **Files modified:** scripts/check-phase33.sh, 33-release-log.md
|
||||||
|
- **Committed in:** 6ea43bb, 21aa4e5
|
||||||
|
|
||||||
|
**2. [Rule 3 - Blocking] Plugin tags moved past the plan's ranges**
|
||||||
|
- **Found during:** Task 4
|
||||||
|
- **Issue:** The plan pasted `sm-seo-plugin v0.1.0..HEAD` and `sm-journal-plugin v0.2.5..HEAD` as unreleased fixes. Those commits are now released in sm-seo-plugin v0.1.1 and sm-journal-plugin v0.2.6 to v0.3.1, and no plugin or layer has unreleased commits.
|
||||||
|
- **Fix:** The release log has a table of the newest tag per repository with "none" unreleased. Versions are still read from `git tag` in 33-14.
|
||||||
|
- **Committed in:** 21aa4e5
|
||||||
|
|
||||||
|
**3. [Rule 3 - Blocking] Docs checker requires src= snippets for go code blocks**
|
||||||
|
- **Found during:** Task 3
|
||||||
|
- **Issue:** The docs checker refuses a hand-written go snippet in docs/backend/field-types.md.
|
||||||
|
- **Fix:** Added a runnable `headingLevels` func and `ExampleCompileFormWithTypes_requestOptions` to modules/cabana/example_field_type_test.go. The page embeds the func through `src=`.
|
||||||
|
- **Committed in:** 4cd35c9
|
||||||
|
|
||||||
|
**4. [Rule 2 - Marker] pact README addition moved to a new bullet**
|
||||||
|
- **Found during:** Task 2
|
||||||
|
- **Issue:** Editing the existing descriptor bullet re-added its pre-existing word "sitemaps" as a changed line, which the D-90 marker stage would flag.
|
||||||
|
- **Fix:** The new facts are described in a separate "Content facts" bullet, and the original line is unchanged.
|
||||||
|
- **Committed in:** 561a56c
|
||||||
|
|
||||||
|
**5. [TDD] Task 3 RED evidence not committed separately**
|
||||||
|
- **Found during:** Task 3
|
||||||
|
- **Issue:** The plan's commit-group table gives Task 3 one commit (`feat(cabana): ...`), while tdd.md's cycle commits `test(...)` first. The plan is `type: execute`, not `type: tdd`.
|
||||||
|
- **Fix:** I followed the plan's single commit. RED was recorded before implementing: TestFieldTypeRequestOptions failed on 4 behaviour subtests (`typeOptions=map[rows:4]`, `calls=0`, no warning logged), and `check tdd-red-evidence` returned RED_EVIDENCE_OK. GREEN then passed all 8 subtests.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Total deviations:** 5 (3 blocking, 1 marker-safety, 1 TDD commit-shape note)
|
||||||
|
**Impact on plan:** The API shape and behaviour are exactly as planned. Only version numbers, the ledger contents and the doc mechanics changed.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
- The compat stage reports sm-feedback-plugin, sm-presentations-plugin and sm-quizzes-plugin as "skipped (fails at v0.6.0 too)": they do not resolve the framework through a scratch workspace at either revision. These failures predate this plan and are not caused by it.
|
||||||
|
- shellcheck warns SC2034 (`type` unused) in the copied `snapshot_submodules`. check-phase32.sh has the same warning, so I left it as is.
|
||||||
|
|
||||||
|
## Verification run
|
||||||
|
|
||||||
|
- `go vet ./... && go test -short ./...`: green after every commit.
|
||||||
|
- `go test ./modules/signpost -run 'TestContentDescriptorFields|Example' -v`: PASS (5 subtests, 3 examples).
|
||||||
|
- `go test ./modules/cabana -run 'TestFieldTypeRequestOptions|TestFormExtensionUnextendedSchemaUnchanged' -v`: PASS (8 subtests).
|
||||||
|
- `scripts/check-admin-openapi.sh --check`: exit 0. `check-phase33.sh --admin` (openapi + dist): passed.
|
||||||
|
- `go test ./cmd/summer -run TestDocsTree` and `summer docs:build --check`: no problems.
|
||||||
|
- `bash scripts/check-phase33.sh --self-test`: passed (37 checks). Without an argument it exits 2 and prints the usage.
|
||||||
|
- `bash scripts/check-phase33.sh --go --docs --marker --additive`: PASS all four; additive: cabana +0, pact +35, signpost +0 lines against v0.6.0.
|
||||||
|
- `bash scripts/check-phase33.sh --plugins`: passed (sm-seo-plugin 77 and sm-journal-plugin 232 vitest tests).
|
||||||
|
- `bash scripts/check-phase33.sh --compat`: passed.
|
||||||
|
- Not run here: `--layers` (vue-seo-layer `testing/guard-check.mjs` arrives in 33-08), `--consumers`, `--docker`.
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
|
||||||
|
None. No external service configuration is required.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
- 33-02 (Blog Editor) can use `RequestOptions` for `headingLevels` and `genericAnchors`, and 33-03 onward can fill and read the content facts.
|
||||||
|
- 33-14 tags framework **v0.6.1** and follows 33-release-log.md.
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
- FOUND: modules/pact/content.go, modules/pact/capabilities.go, modules/signpost/content_fields_smoke_test.go, modules/cabana/field_request_options_smoke_test.go, scripts/check-phase33.sh, 33-release-log.md
|
||||||
|
- FOUND commits: 561a56c, 4cd35c9, 6ea43bb, 21aa4e5
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 33-seo-output-audit-and-content*
|
||||||
|
*Completed: 2026-11-04*
|
||||||
Reference in New Issue
Block a user