docs(11-08): complete gap plan summary
This commit is contained in:
@@ -97,7 +97,7 @@ Requirements for v1 (the Płytarium port). Each maps to roadmap phases. "User" b
|
|||||||
|
|
||||||
### Search (SRCH)
|
### Search (SRCH)
|
||||||
|
|
||||||
- [ ] **SRCH-01**: Album documents sync to Typesense scoped by collection_id, behind a settings kill-switch, degrading gracefully when the DB or config is absent
|
- [x] **SRCH-01**: Album documents sync to Typesense scoped by collection_id, behind a settings kill-switch, degrading gracefully when the DB or config is absent
|
||||||
- [ ] **SRCH-02**: The reindex command asserts zero documents with collection_id 0 before and after, and can drop the legacy index
|
- [ ] **SRCH-02**: The reindex command asserts zero documents with collection_id 0 before and after, and can drop the legacy index
|
||||||
|
|
||||||
### Integrations (INTG)
|
### Integrations (INTG)
|
||||||
@@ -227,7 +227,7 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
| RT-01 | Phase 11 | Gaps Found |
|
| RT-01 | Phase 11 | Gaps Found |
|
||||||
| RT-02 | Phase 11 | Gaps Found |
|
| RT-02 | Phase 11 | Gaps Found |
|
||||||
| RT-03 | Phase 11 | Gaps Found |
|
| RT-03 | Phase 11 | Gaps Found |
|
||||||
| SRCH-01 | Phase 11 | Gaps Found |
|
| SRCH-01 | Phase 11 | Complete |
|
||||||
| SRCH-02 | Phase 14 | Pending |
|
| SRCH-02 | Phase 14 | Pending |
|
||||||
| INTG-01 | Phase 14 | Pending |
|
| INTG-01 | Phase 14 | Pending |
|
||||||
| INTG-02 | Phase 14 | Pending |
|
| INTG-02 | Phase 14 | Pending |
|
||||||
|
|||||||
@@ -505,7 +505,7 @@ Plans:
|
|||||||
4. A channel-namespace authorizer registry re-validates on every subscribe; a broadcastable model interface with bulk-write suppression emits exactly one summary event for a bulk operation.
|
4. A channel-namespace authorizer registry re-validates on every subscribe; a broadcastable model interface with bulk-write suppression emits exactly one summary event for a bulk operation.
|
||||||
5. Typesense sync is scoped by `collection_id` behind a settings kill-switch and degrades gracefully without DB/config.
|
5. Typesense sync is scoped by `collection_id` behind a settings kill-switch and degrades gracefully without DB/config.
|
||||||
|
|
||||||
**Plans:** 7/7 plans executed
|
**Plans:** 8/8 plans executed
|
||||||
**Research flag:** yes
|
**Research flag:** yes
|
||||||
|
|
||||||
Plans:
|
Plans:
|
||||||
@@ -527,6 +527,9 @@ Plans:
|
|||||||
**Wave 5** *(blocked on Wave 4 completion)*
|
**Wave 5** *(blocked on Wave 4 completion)*
|
||||||
- [x] 11-07-PLAN.md — Unit tests last: full coverage, failing-when-broken T-11 evidence, check-phase11.sh gate, security review and validation map
|
- [x] 11-07-PLAN.md — Unit tests last: full coverage, failing-when-broken T-11 evidence, check-phase11.sh gate, security review and validation map
|
||||||
|
|
||||||
|
**Wave 6** *(gap closure, blocked on Wave 5 completion)*
|
||||||
|
- [x] 11-08-PLAN.md — CR-01: Cabana writes and SaveAlbum in lagoon.Transaction, lagoon.AfterCommit refuses foreign transactions, committed artist_ids regression tests (summercms.go, fonoteka.go)
|
||||||
|
|
||||||
### 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.
|
||||||
@@ -670,7 +673,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
|
|||||||
| 8. OAuth2.1 authorization server | 10/10 | Complete | 2026-09-23 |
|
| 8. OAuth2.1 authorization server | 10/10 | Complete | 2026-09-23 |
|
||||||
| 9. Backend admin authentication and schema pipeline | 12/12 | In Progress| |
|
| 9. Backend admin authentication and schema pipeline | 12/12 | In Progress| |
|
||||||
| 10. Admin Vue SPA | 5/5 | Complete | 2026-09-27 |
|
| 10. Admin Vue SPA | 5/5 | Complete | 2026-09-27 |
|
||||||
| 11. Jobs, realtime and search infrastructure | 7/7 | In Progress| |
|
| 11. Jobs, realtime and search infrastructure | 8/8 | In Progress| |
|
||||||
| 11.1. SummerCMS documentation for humans and AI agents | 0/TBD | Not started | - |
|
| 11.1. SummerCMS documentation for humans and AI agents | 0/TBD | Not started | - |
|
||||||
| 11.2. Ready to share: summercms.io website and newsletter plugin | 0/TBD | Not started | - |
|
| 11.2. Ready to share: summercms.io website and newsletter plugin | 0/TBD | Not started | - |
|
||||||
| 12. Płytarium API — Collections and Albums | 0/TBD | Not started | - |
|
| 12. Płytarium API — Collections and Albums | 0/TBD | Not started | - |
|
||||||
|
|||||||
@@ -3,17 +3,17 @@ gsd_state_version: "1.0"
|
|||||||
milestone: v1.0
|
milestone: v1.0
|
||||||
current_phase: 11
|
current_phase: 11
|
||||||
current_phase_name: Jobs, realtime and search infrastructure
|
current_phase_name: Jobs, realtime and search infrastructure
|
||||||
status: executing
|
status: verifying
|
||||||
stopped_at: Completed 11-07-PLAN.md
|
stopped_at: Completed 11-08-PLAN.md
|
||||||
last_updated: "2026-09-30T14:09:27.946Z"
|
last_updated: "2026-09-30T19:09:44.022Z"
|
||||||
last_activity: 2026-09-29
|
last_activity: 2026-09-30
|
||||||
last_activity_desc: Phase 11 execution started
|
last_activity_desc: Phase 11 execution started
|
||||||
state_head: dd97fd12a60a31067c6a0d254161d31e36b90c6c
|
state_head: e6777bda9765d792268069432220b32d394c7bc8
|
||||||
progress:
|
progress:
|
||||||
total_phases: 19
|
total_phases: 19
|
||||||
completed_phases: 9
|
completed_phases: 9
|
||||||
total_plans: 86
|
total_plans: 92
|
||||||
completed_plans: 85
|
completed_plans: 86
|
||||||
milestone_name: milestone
|
milestone_name: milestone
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -28,10 +28,10 @@ See: .planning/PROJECT.md (updated 2026-09-16)
|
|||||||
|
|
||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 11 (Jobs, realtime and search infrastructure) — READY TO EXECUTE
|
Phase: 11 (Jobs, realtime and search infrastructure) — EXECUTING
|
||||||
Plan: 7 of 7
|
Plan: 8 of 8
|
||||||
Status: Ready to execute
|
Status: Phase complete — ready for verification
|
||||||
Last activity: 2026-09-29 — Phase 11 execution started
|
Last activity: 2026-09-30 — Phase 11 execution started
|
||||||
|
|
||||||
Progress: [██████░░░░] 60%
|
Progress: [██████░░░░] 60%
|
||||||
|
|
||||||
@@ -140,6 +140,7 @@ Progress: [██████░░░░] 60%
|
|||||||
| Phase 11 P06 | 23 min | 3 tasks | 39 files |
|
| Phase 11 P06 | 23 min | 3 tasks | 39 files |
|
||||||
| Phase 11 P04 | 17 min | 2 tasks | 19 files |
|
| Phase 11 P04 | 17 min | 2 tasks | 19 files |
|
||||||
| Phase 11 P07 | 59min | 3 tasks | 40 files |
|
| Phase 11 P07 | 59min | 3 tasks | 40 files |
|
||||||
|
| Phase 11 P08 | unknown (manual close-out) | 3 tasks | 13 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -385,6 +386,8 @@ Recent decisions affecting current work:
|
|||||||
- [Phase 11]: Savepoint helpers (beachcomber, lighthouse) roll back when RELEASE fails, because a swallowed read error still aborts the Postgres transaction
|
- [Phase 11]: Savepoint helpers (beachcomber, lighthouse) roll back when RELEASE fails, because a swallowed read error still aborts the Postgres transaction
|
||||||
- [Phase 11]: lagoon after-commit callbacks always receive a clean statement on the write's connection; side-effect GORM callbacks declare Before(gorm:commit_or_rollback_transaction)
|
- [Phase 11]: lagoon after-commit callbacks always receive a clean statement on the write's connection; side-effect GORM callbacks declare Before(gorm:commit_or_rollback_transaction)
|
||||||
- [Phase 11]: Phase gates accept a pending skip only by exact test name and pending text (TestBroadcastGoldens/created and /updated until Phase 12), in check-phase11.sh and check-phase10.1.sh
|
- [Phase 11]: Phase gates accept a pending skip only by exact test name and pending text (TestBroadcastGoldens/created and /updated until Phase 12), in check-phase11.sh and check-phase10.1.sh
|
||||||
|
- [Phase 11]: Phase 11-08: lagoon.AfterCommit inside a foreign plain GORM transaction warns and skips the callback instead of running it immediately; Cabana writes and SaveAlbum run in lagoon.Transaction — Lagoon cannot observe a foreign commit; running early sent uncommitted, pre-pivot or rolled-back Album state to Typesense (CR-01)
|
||||||
|
- [Phase 11]: Phase 11-08: a nested lagoon.Transaction given a root handle returns an error (WR-03) — Treating it as a savepoint would commit independently while its callbacks waited on the parent buffer
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -415,6 +418,6 @@ Items acknowledged and carried forward from previous milestone close:
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-09-30T12:57:09.320Z
|
Last session: 2026-09-30T19:09:33.936Z
|
||||||
Stopped at: Completed 11-07-PLAN.md
|
Stopped at: Completed 11-08-PLAN.md
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"phase": "09",
|
"phase": "11",
|
||||||
"session": "codex-thread-id-01a0d740-5347-7f00-9bb6-24c3bbe01139",
|
"session": "codex-thread-id-01a0f286-f1a5-7ce0-b0b8-102d6d67e017",
|
||||||
"pid": 30,
|
"pid": 2,
|
||||||
"updated_at": 1790317872927
|
"updated_at": 1790778676127
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,240 @@
|
|||||||
|
---
|
||||||
|
phase: 11-jobs-realtime-and-search-infrastructure
|
||||||
|
plan: 08
|
||||||
|
subsystem: database
|
||||||
|
tags: [lagoon, after-commit, cabana, beachcomber, typesense, gorm, transactions, gap-closure]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- phase: 11-jobs-realtime-and-search-infrastructure
|
||||||
|
provides: "11-05 beachcomber sync over lagoon.AfterCommit and the fonoteka Album binding; 11-07 clean after-commit handles, the savepoint fix and check-phase11.sh"
|
||||||
|
provides:
|
||||||
|
- "Cabana create/update/delete/bulk-delete and relation Link/Unlink run in lagoon.Transaction, so after-commit work sees the committed row and pivots"
|
||||||
|
- "fonoteka SaveAlbum runs in lagoon.Transaction; the buffered search reload happens after the ordered artist pivots commit"
|
||||||
|
- "lagoon.AfterCommit warns and skips inside a foreign plain GORM *sql.Tx; a nested lagoon.Transaction over a root handle returns an error (WR-03)"
|
||||||
|
- "Regression tests: TestAlbumsAdminSearchUsesCommittedArtists (assembled admin router) and TestSaveAlbumDefersAfterCommitUntilArtistsSync; inverted plain-transaction tests in lagoon, beachcomber and fonoteka"
|
||||||
|
- "T-11-31 and T-11-32 in 11-SECURITY-REVIEW.md, with removal check RC-14 in check-phase11.sh --removal"
|
||||||
|
affects: [11 verification re-run (CR-01), 12 albums API (SearchIDs SQL re-gate), any code that writes searchable models inside its own plain GORM transaction]
|
||||||
|
|
||||||
|
actuals:
|
||||||
|
tokens: 5988
|
||||||
|
tasks: 3
|
||||||
|
commits: 7
|
||||||
|
plan_head_before: 9033d81721d1a0fa77fd9ce234119948aa3d0996
|
||||||
|
plan_head_after: e6777bda9765d792268069432220b32d394c7bc8
|
||||||
|
# commits is `git rev-list --count 9033d81..e6777bd` in summercms.go. It
|
||||||
|
# includes 6f57604 docs(11.1), an unrelated commit that landed between the
|
||||||
|
# 11-08 task commits; the 11-08 commits there are 6. fonoteka.go received 1
|
||||||
|
# more commit on top of c222e030b38a6e63760fbc032c02d2224a2c7b41: 1c88199.
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "Write services that trigger after-commit work run their whole unit (row plus pivots) in lagoon.Transaction and use the callback's ctx and tx throughout"
|
||||||
|
- "lagoon.AfterCommit has four documented cases: lagoon-managed (buffered), implicit single statement (buffered on the statement), foreign *sql.Tx (warned and skipped), outside a transaction (immediate)"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- .planning/phases/11-jobs-realtime-and-search-infrastructure/11-08-SUMMARY.md
|
||||||
|
modified:
|
||||||
|
- modules/cabana/crud.go
|
||||||
|
- modules/cabana/relation.go
|
||||||
|
- modules/lagoon/transaction.go
|
||||||
|
- modules/lagoon/transaction_test.go
|
||||||
|
- modules/lagoon/README.md
|
||||||
|
- modules/beachcomber/sync_test.go
|
||||||
|
- modules/beachcomber/README.md
|
||||||
|
- scripts/check-phase11.sh
|
||||||
|
- .planning/phases/11-jobs-realtime-and-search-infrastructure/11-SECURITY-REVIEW.md
|
||||||
|
- ../fonoteka.go/plugins/golem15/fonoteka/admin_albums_test.go
|
||||||
|
- ../fonoteka.go/plugins/golem15/fonoteka/search_smoke_test.go
|
||||||
|
- ../fonoteka.go/plugins/golem15/fonoteka/classes/album_write_service.go
|
||||||
|
- ../fonoteka.go/plugins/golem15/fonoteka/classes/album_write_service_db_test.go
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "lagoon.AfterCommit inside a foreign plain GORM transaction warns and skips the callback instead of running it immediately: Lagoon cannot observe that commit, and running early leaked uncommitted or rolled-back state to Typesense"
|
||||||
|
- "A nested lagoon.Transaction given a root handle returns an error rather than being treated as a top-level transaction (WR-03 option 'return an error')"
|
||||||
|
- "T-11-31 gets its own removal check (RC-14) so check-phase11.sh --evidence accepts the 11-08 threat register; T-11-32 (medium) is proven by two hand-run mutations recorded in the review"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "A gap plan that adds threat IDs must also add their rows to the phase security review, because the phase gate reads every 11-0*-PLAN.md threat register"
|
||||||
|
|
||||||
|
requirements-completed: [SRCH-01]
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
- id: D1
|
||||||
|
description: "A Cabana admin edit that replaces an Album's artists commits the submitted pivot order and sends Typesense exactly one import whose artist_ids equal that committed order"
|
||||||
|
requirement: SRCH-01
|
||||||
|
verification:
|
||||||
|
- kind: integration
|
||||||
|
ref: "../fonoteka.go/plugins/golem15/fonoteka/admin_albums_test.go#TestAlbumsAdminSearchUsesCommittedArtists"
|
||||||
|
status: pass
|
||||||
|
- kind: integration
|
||||||
|
ref: "go test ./modules/cabana -count=1"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D2
|
||||||
|
description: "lagoon.AfterCommit refuses a foreign plain GORM transaction with a warning; a rolled-back plain transaction reaches no search engine; lagoon-managed and implicit single-statement commits still sync; a nested lagoon.Transaction over a root handle errors without running"
|
||||||
|
requirement: SRCH-01
|
||||||
|
verification:
|
||||||
|
- kind: integration
|
||||||
|
ref: "go test ./modules/lagoon -run '^(TestTransactionAfterCommit|TestTransactionEdges)$' -count=1 -v"
|
||||||
|
status: pass
|
||||||
|
- kind: integration
|
||||||
|
ref: "go test ./modules/beachcomber -run '^TestSyncAfterCommit$' -count=1 -v"
|
||||||
|
status: pass
|
||||||
|
- kind: integration
|
||||||
|
ref: "../fonoteka.go/plugins/golem15/fonoteka/search_smoke_test.go#TestAlbumSearchDeleteAndFailures"
|
||||||
|
status: pass
|
||||||
|
- kind: other
|
||||||
|
ref: "PHASE11_RC=RC-14 scripts/check-phase11.sh --removal"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D3
|
||||||
|
description: "SaveAlbum runs after-commit callbacks only after the ordered artist pivots commit, and none on rollback; validation and market-price provenance tests unchanged and green"
|
||||||
|
requirement: SRCH-01
|
||||||
|
verification:
|
||||||
|
- kind: integration
|
||||||
|
ref: "cd ../fonoteka.go && go test ./plugins/golem15/fonoteka/classes -run '^TestSaveAlbum' -count=1 -v"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D4
|
||||||
|
description: "Phase 11 gate green in both repositories with the 11-08 threats in the security review"
|
||||||
|
verification:
|
||||||
|
- kind: other
|
||||||
|
ref: "bash scripts/check-phase11.sh --all"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
|
||||||
|
duration: unknown (executor stopped before its summary step; see Performance)
|
||||||
|
completed: 2026-09-30
|
||||||
|
status: complete
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 11 Plan 08: Commit-safe Album search sync (gap CR-01) Summary
|
||||||
|
|
||||||
|
**Cabana writes and fonoteka `SaveAlbum` now run in `lagoon.Transaction`, so Typesense receives an Album only after its row and ordered artist pivots commit. `lagoon.AfterCommit` warns and skips inside a foreign plain GORM transaction, so a rollback there never reaches the search engine. A nested `lagoon.Transaction` over a root handle is an error. `check-phase11.sh --all` prints "phase11 all passed".**
|
||||||
|
|
||||||
|
This summary was written in a manual close-out. The 11-08 executor committed all three tasks and then stopped before its summary step. The close-out re-ran every verify command, the phase gate and both repositories' full suites. It fixed the gaps it found in three separate `fix(11-08)` commits.
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** not measured. The executor recorded no start time or commit ledger. Its task commits are timestamped 2026-09-30T18:14:23Z to 18:14:42Z. The follow-up test commit is at 18:49:31Z and the close-out ran from about 18:50Z.
|
||||||
|
- **Completed:** 2026-09-30
|
||||||
|
- **Tasks:** 3 of 3
|
||||||
|
- **Files modified:** 13 (9 in summercms.go including the security review, 4 in fonoteka.go), plus this summary and the planning state files
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- **Task 1 (tracer): an admin artist edit indexes the committed ordered pivots.** `CRUDService.save`, `Delete` and `BulkDelete` (crud.go) and `RelationService.Link` and `Unlink` (relation.go) call `lagoon.Transaction` and use its ctx and tx. The read-only `ShowRecord` (crud.go:255) and relation query (relation.go:449) transactions are unchanged. `TestAlbumsAdminSearchUsesCommittedArtists` drives the router built by `surf.Assemble` with a PUT that replaces the artists. It asserts that the committed pivot order and the single Typesense import's `artist_ids` are the same.
|
||||||
|
- **Task 2: refuse external after-commit work inside unmanaged transactions.** `AfterCommit` keeps its lagoon-buffer and implicit-transaction branches. When the statement's connection pool is a `gorm.TxCommitter` that neither branch covers, it now logs `lagoon: after-commit callback skipped inside unmanaged transaction` and returns. `Transaction` returns `lagoon: nested transaction requires the parent transaction handle` when a parent buffer exists but the handle is not transactional. Tests that used to expect immediate plain-transaction sync now assert the opposite in lagoon, beachcomber and fonoteka. The lagoon README describes all four cases.
|
||||||
|
- **Task 3: SaveAlbum defers sync until the ordered artists commit.** `SaveAlbum` uses `lagoon.Transaction`, and the save-before-pivot order is unchanged. `TestSaveAlbumDefersAfterCommitUntilArtistsSync` registers a create callback that reads the pivots after commit and sees `[second, first]`. Its duplicate-pivot rollback case runs no callback and commits no Album.
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
summercms.go:
|
||||||
|
1. `f7b6b0c`: fix(11-08), make cabana writes commit-safe (Task 1)
|
||||||
|
2. `a33b1ad`: fix(11-08), refuse unmanaged after-commit work (Task 2)
|
||||||
|
3. `2766f34`: test(11-08), keep sync failure coverage managed (Task 2 follow-up: `TestSyncFailuresNonFatal/failed_document_read_inside_a_transaction` moved to `lagoon.Transaction`; with `a33b1ad` alone that test fails)
|
||||||
|
4. `8e0083e`: fix(11-08), document foreign and nested transaction refusal (close-out)
|
||||||
|
5. `d4fc957`: fix(11-08), add the T-11-31 removal check to the phase gate (close-out)
|
||||||
|
6. `e6777bd`: fix(11-08), record T-11-31 and T-11-32 in the security review (close-out)
|
||||||
|
|
||||||
|
fonoteka.go:
|
||||||
|
1. `1c88199`: fix(11-08), defer album sync until committed (Tasks 1 and 3 tests, Task 2 fonoteka test, `SaveAlbum`)
|
||||||
|
|
||||||
|
Not part of 11-08: `6f57604` docs(11.1): create phase plan, which landed between the task commits.
|
||||||
|
|
||||||
|
**Plan metadata:** docs(11-08): complete gap plan summary (this commit)
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
See `key-files` in the frontmatter. The production changes are `modules/cabana/crud.go`, `modules/cabana/relation.go`, `modules/lagoon/transaction.go` and `../fonoteka.go/plugins/golem15/fonoteka/classes/album_write_service.go`. The rest are tests, the lagoon and beachcomber READMEs, the gate script and the security review.
|
||||||
|
|
||||||
|
## Verification (run in the close-out, 2026-09-30)
|
||||||
|
|
||||||
|
Postgres-backed tests ran on testcontainers (Docker). Nothing was skipped except the two broadcast goldens that the gate allows (`TestBroadcastGoldens/created` and `/updated`, pending Phase 12).
|
||||||
|
|
||||||
|
| Command | Result |
|
||||||
|
|---------|--------|
|
||||||
|
| Task 1: `go test ./modules/cabana -count=1` | `ok .../modules/cabana 17.754s` |
|
||||||
|
| Task 1: `(cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^TestAlbumsAdminSearchUsesCommittedArtists$' -count=1 -v)` | `--- PASS: TestAlbumsAdminSearchUsesCommittedArtists (0.86s)` |
|
||||||
|
| Task 2: `go test ./modules/lagoon -run '^(TestTransactionAfterCommit\|TestTransactionEdges)$' -count=1 -v` | `--- PASS: TestTransactionAfterCommit (0.13s)`, `--- PASS: TestTransactionEdges (0.08s)` |
|
||||||
|
| Task 2: `go test ./modules/beachcomber -run '^TestSyncAfterCommit$' -count=1 -v` | PASS, 6 subtests including `plain_gorm_transaction_rollback_sends_nothing` |
|
||||||
|
| Task 2: `(cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^TestAlbumSearchDeleteAndFailures$' -count=1 -v)` | PASS, 10 subtests including `a_foreign_gorm_transaction_rollback_never_reaches_Typesense` |
|
||||||
|
| Task 3: `(cd ../fonoteka.go && go test ./plugins/golem15/fonoteka/classes -run '^TestSaveAlbum' -count=1 -v)` | 9 PASS: `TestSaveAlbumDefersAfterCommitUntilArtistsSync` plus the 8 existing year and market-price provenance tests |
|
||||||
|
| Task 3: `go test ./plugins/golem15/fonoteka -run '^(TestAlbumsAdminSearchUsesCommittedArtists\|TestAlbumSearchDeleteAndFailures)$'` | both PASS |
|
||||||
|
| `go vet ./...` and `go test ./... -count=1` in summercms.go | vet clean; 29 packages `ok`, 0 FAIL |
|
||||||
|
| `go vet` and `go test ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/... -count=1` in fonoteka.go | vet clean; 15 packages `ok`, 7 with no test files, 0 FAIL |
|
||||||
|
| `bash scripts/check-phase11.sh --all` (first run, on the executor's commits) | self-test, hygiene, go, postgres and named passed; **evidence refused: "review has 0 threat rows for T-11-31, want 1"** |
|
||||||
|
| `bash scripts/check-phase11.sh --all` (after `8e0083e`, `d4fc957`, `e6777bd`) | `phase11 all passed` |
|
||||||
|
| `PHASE11_RC=RC-14 bash scripts/check-phase11.sh --removal` | `RC-14 T-11-31 modules/lagoon/transaction.go: fails as required: TestTransactionAfterCommit, .../plain_gorm_transaction_is_refused, .../callback_handle_has_a_clean_statement`; restored |
|
||||||
|
| Hand mutation: Cabana `save` back to a plain `s.DB.Transaction` | `TestAlbumsAdminSearchUsesCommittedArtists` fails: `imports=[] calls=[], want one document`; file restored |
|
||||||
|
| Hand mutation: `SaveAlbum` back to a plain `gdb.Transaction` | `TestSaveAlbumDefersAfterCommitUntilArtistsSync` fails: `callbacks=0 observed=[], want one callback with [3 2]`; file restored |
|
||||||
|
|
||||||
|
Acceptance criteria check:
|
||||||
|
- Task 1: crud.go has exactly three `lagoon.Transaction` write entry points and relation.go has two. The read-only sites are untouched. The test uses the assembled HTTP router, and it compares the import with pivots read on the committed connection after the request. **Pass.**
|
||||||
|
- Task 2: the plain-transaction tests assert zero callbacks or engine calls, and the lagoon one also asserts the warning. The rollback tests see no external request. The nested root-handle case errors without entering its function. The lagoon README covers lagoon-managed, implicit statement, foreign transaction and outside a transaction. **Pass.** The nested root-handle error was missing from the README and the `Transaction` doc comment until `8e0083e`.
|
||||||
|
- Task 3: `SaveAlbum` calls `lagoon.Transaction` with its callback ctx. The new test sees the submitted order and no callback on rollback. The existing validation and provenance tests are green. **Pass.**
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
See `key-decisions` in the frontmatter.
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 1 - Bug] TestSyncFailuresNonFatal still relied on the old plain-transaction behaviour**
|
||||||
|
- **Found during:** Task 2, after `a33b1ad`
|
||||||
|
- **Issue:** `failed_document_read_inside_a_transaction` wrote inside `gdb.Transaction` and expected a "build document" warning. After the refusal no sync ran, so the test failed. This was confirmed in the close-out by restoring the `a33b1ad` version of the file.
|
||||||
|
- **Fix:** the subtest writes through `lagoon.Transaction`. This was left uncommitted when the executor stopped and committed as `2766f34` during the close-out window.
|
||||||
|
- **Commit:** `2766f34`
|
||||||
|
|
||||||
|
**2. [Rule 2 - Missing critical] Documentation contradicted the new behaviour (CLAUDE.md module README rule)**
|
||||||
|
- **Found during:** close-out review of Task 2
|
||||||
|
- **Issue:** `modules/beachcomber/README.md` still said the sync "runs immediately through the transaction's handle" inside a plain GORM transaction. `lagoon.Transaction`'s doc comment and the lagoon README did not mention the new nested root-handle error.
|
||||||
|
- **Fix:** the beachcomber README now says the sync is warned and skipped there, and points to `lagoon.Transaction` or an explicit `Sync` after commit. The lagoon README and doc comment state the nested root-handle error.
|
||||||
|
- **Files modified:** modules/beachcomber/README.md, modules/lagoon/README.md, modules/lagoon/transaction.go (comment only)
|
||||||
|
- **Commit:** `8e0083e`
|
||||||
|
|
||||||
|
**3. [Rule 3 - Blocking] The phase gate refused 11-08's threat register**
|
||||||
|
- **Found during:** plan verification (`check-phase11.sh --all`)
|
||||||
|
- **Issue:** the evidence stage reads the threat table of every `11-0*-PLAN.md` and needs one review row per threat, plus a removal check for each high mitigated threat. T-11-31 (high) and T-11-32 (medium) had no rows.
|
||||||
|
- **Fix:** RC-14 in `removal_table`. It removes the foreign-transaction refusal and requires `TestTransactionAfterCommit` to fail, which it does. The review got rows for T-11-31 and T-11-32, the RC-14 row, and a CR-01 row in the fixes table.
|
||||||
|
- **Commits:** `d4fc957` (script), `e6777bd` (review)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Total deviations:** 3 (1 bug, 1 missing documentation, 1 blocking gate failure). No production behaviour was changed in the close-out; the only code change is a doc comment.
|
||||||
|
|
||||||
|
## TDD Gate Compliance
|
||||||
|
|
||||||
|
The executor committed each task as a single `fix` commit, with its tests in the same commit, so the RED run is not in history. The close-out replaced that evidence with mutations. RC-14 covers the Task 2 refusal. Hand mutations of the Cabana `save` transaction and of `SaveAlbum` make the Task 1 and Task 3 tests fail. Restoring the `a33b1ad` version of `sync_test.go` makes `TestSyncFailuresNonFatal` fail.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
- The fonoteka subtest `an album without a positive collection_id is logged and never sent` now asserts that no warning is logged, because its write happens in a rolled-back foreign transaction. Its name no longer matches its assertion. The zero-collection refusal is still covered by `ToSearchableArray` in the same subtest and by `TestAlbumSearchable/collection_id_zero_is_refused` (RC-07). The warning path for a failed build is covered by beachcomber `TestSyncFailuresNonFatal`. The subtest was not renamed; this is a cosmetic follow-up.
|
||||||
|
- Code that writes searchable models inside its own plain `gorm` transaction now gets no search sync. A Warn log appears instead of a silent skip. No production call site was found besides the Cabana and `SaveAlbum` paths this plan converted, and the full suites in both repositories pass.
|
||||||
|
|
||||||
|
## Known Stubs
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
## Threat Flags
|
||||||
|
|
||||||
|
None. No new endpoint, auth path, file access or schema. The changes narrow when data leaves an open transaction.
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
- Phase 11 verification can be re-run to re-check CR-01. This close-out did not run it and did not mark the phase complete.
|
||||||
|
- Phase 12 still owns the SQL re-gate of `SearchIDs` results. Concurrent commits for the same Album are not serialized (flagged SRCH-01 assumption).
|
||||||
|
- RT-03 is not newly claimed: the Album `updated` broadcast payload timing on admin edits keeps the assumptions recorded in 11-03.
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
- All modified files listed in key-files exist on disk.
|
||||||
|
- summercms.go commits f7b6b0c, a33b1ad, 2766f34, 8e0083e, d4fc957 and e6777bd exist, and so does fonoteka.go commit 1c88199.
|
||||||
@@ -56,13 +56,18 @@
|
|||||||
{
|
{
|
||||||
"number": "11",
|
"number": "11",
|
||||||
"name": "Jobs, realtime and search infrastructure",
|
"name": "Jobs, realtime and search infrastructure",
|
||||||
"status": "pending"
|
"status": "in_progress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"number": "11.1",
|
"number": "11.1",
|
||||||
"name": "SummerCMS documentation for humans and AI agents",
|
"name": "SummerCMS documentation for humans and AI agents",
|
||||||
"status": "pending"
|
"status": "pending"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"number": "11.2",
|
||||||
|
"name": "Ready to share: summercms.io website and newsletter plugin",
|
||||||
|
"status": "pending"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"number": "12",
|
"number": "12",
|
||||||
"name": "Płytarium API — Collections and Albums",
|
"name": "Płytarium API — Collections and Albums",
|
||||||
@@ -86,8 +91,8 @@
|
|||||||
],
|
],
|
||||||
"next": {
|
"next": {
|
||||||
"command": "/gsd:progress --next",
|
"command": "/gsd:progress --next",
|
||||||
"label": "Advance to the next step",
|
"label": "Advance to the next step (verify)",
|
||||||
"reason": "Phase 10.1 of 18 · executing"
|
"reason": "Phase 11 of 19 · ready to verify"
|
||||||
},
|
},
|
||||||
"updated_at": "2026-09-28T20:34:17.786Z"
|
"updated_at": "2026-09-30T19:09:22.774Z"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user