diff --git a/.planning/phases/15-journal-plugin/15-01-SUMMARY.md b/.planning/phases/15-journal-plugin/15-01-SUMMARY.md new file mode 100644 index 0000000..08efa5a --- /dev/null +++ b/.planning/phases/15-journal-plugin/15-01-SUMMARY.md @@ -0,0 +1,232 @@ +--- +phase: 15-journal-plugin +plan: 01 +subsystem: plugins +tags: [journal, gormigrate, translate, translatable, postgres, gitlink, cors] + +requires: + - phase: 14.2.1 + provides: "sm-translate-plugin Translatable/SetTranslated/MorphName, sm-grzybyfunkcjonalne-app user+translate mount" +provides: + - "sm-journal-plugin clone at D-23 with ID golem15.journal and Requires golem15.translate" + - "squashed golem15_journal_* tables plus backend_users.golem15_bloghub_author_slug" + - "Post/Category Translatable MorphName PHP class strings and TestPostTranslatableSmoke" + - "proof-host three-plugin boot TestBootUserTranslateJournal and CORS _journal/api/*" +affects: [15-02, 15-03, 15-04, 16] + +actuals: + tokens: 10000 + tasks: 3 + commits: 6 +plan_head_before: a28bb1e4ece6040850793b90eb543474d2dd2e8a +plugin_repo_head_after: bb903a68509159e90dac6a77a0124d2b2dd14843 +host_repo_head_after: 41c9b9212dbe11c3b1da5d0a87323b2245d32f6a + +tech-stack: + added: [] + patterns: + - "Sibling plugin go.mod replaces only summercms => ../summercms.go; other plugin replaces live in go.work" + - "models tests call Plugin.Migrations() instead of importing updates (models leaf check)" + - "Proof host gitlink at plugins/golem15/journal with go.work use and go.mod replace" + +key-files: + created: + - ../sm-journal-plugin/go.mod + - ../sm-journal-plugin/plugin.go + - ../sm-journal-plugin/README.md + - ../sm-journal-plugin/models/post.go + - ../sm-journal-plugin/models/category.go + - ../sm-journal-plugin/models/tag.go + - ../sm-journal-plugin/models/settings.go + - ../sm-journal-plugin/models/post_translatable_smoke_test.go + - ../sm-journal-plugin/updates/202610060001_create_golem15_journal_posts.go + - ../sm-journal-plugin/updates/202610060002_create_golem15_journal_categories.go + - ../sm-journal-plugin/updates/202610060003_create_golem15_journal_tags.go + - ../sm-journal-plugin/updates/202610060004_create_golem15_journal_posts_categories.go + - ../sm-journal-plugin/updates/202610060005_create_golem15_journal_posts_tags.go + - ../sm-journal-plugin/updates/202610060006_create_golem15_journal_settings.go + - ../sm-journal-plugin/updates/202610060007_add_author_slug_to_backend_users.go + - ../sm-journal-plugin/lang/en/lang.yaml + - ../sm-journal-plugin/lang/pl/lang.yaml + modified: + - ../sm-grzybyfunkcjonalne-app/summer.yaml + - ../sm-grzybyfunkcjonalne-app/go.work + - ../sm-grzybyfunkcjonalne-app/go.mod + - ../sm-grzybyfunkcjonalne-app/.gitmodules + - ../sm-grzybyfunkcjonalne-app/boot_test.go + - ../sm-grzybyfunkcjonalne-app/plugins.gen.go + - ../sm-grzybyfunkcjonalne-app/config/http.yaml + +key-decisions: + - "Go schema is squashed to golem15_journal_* from PHP pin 02110eb1; rainlab-era names are not created" + - "translate replace stays in journal go.work, not go.mod, so the host workspace module path does not conflict" + - "Uncategorized is seeded (A4 PHP seed_all_tables still inserts it); first post is not seeded" + - "slug is in Translatable() as well as TranslatableIndexes() because SetTranslated requires a declared translatable field" + +patterns-established: + - "Compiled journal plugin: party.Register, HasMigrations/HasModels/HasLang, Requires exactly golem15.translate" + - "Host mounts user, translate, journal as gitlinks; TestBootUserTranslateJournal asserts three IDs" + - "Plugin README stays application-neutral (the application / blog / acme)" + +requirements-completed: [D-01, D-02, D-03, D-04, D-06, D-07, D-09, D-10, D-17, D-18, D-19, D-20, D-21, D-22, D-23] + +coverage: + - id: D1 + description: "sm-journal-plugin exists at D-23 with module git.golem15.com/golem15/sm-journal-plugin, ID golem15.journal, Requires exactly golem15.translate" + requirement: D-09 + verification: + - kind: unit + ref: "../sm-journal-plugin#TestPostTranslatableSmoke" + status: pass + - kind: other + ref: "git ls-remote git@git.golem15.com:golem15/sm-journal-plugin.git" + status: pass + human_judgment: false + - id: D2 + description: "Migration 202610060001 creates golem15_journal_posts; English lives on the host row and Polish title/slug in golem15_translate_attributes" + requirement: D-10 + verification: + - kind: integration + ref: "../sm-journal-plugin/models#TestPostTranslatableSmoke" + status: pass + human_judgment: false + - id: D3 + description: "Proof host Activate returns user, translate, and journal; gitlink plugins/golem15/journal; plugins.gen.go blank-imports sm-journal-plugin" + requirement: D-18 + verification: + - kind: unit + ref: "../sm-grzybyfunkcjonalne-app#TestBootUserTranslateJournal" + status: pass + human_judgment: false + - id: D4 + description: "After migrate, six golem15_journal_* tables exist, backend_users.golem15_bloghub_author_slug exists, settings.search_use_typesense defaults false" + requirement: D-04 + verification: + - kind: integration + ref: "../sm-journal-plugin/updates#TestJournalTables" + status: pass + human_judgment: false + - id: D5 + description: "en/pl phrasebooks exist, plugin README is application-neutral, host CORS includes _journal/api/* with supports_credentials false" + requirement: D-06 + verification: + - kind: other + ref: "go test ./... -short; python README forbidden-name scan; grep _journal/api/* config/http.yaml" + status: pass + human_judgment: false + - id: D6 + description: "PHP journal tree at SHA 02110eb1c0c3861370b0b9b47b209a0702ac5d88 is unmodified" + requirement: D-07 + verification: + - kind: other + ref: "git -C /media/nvme/dev/golem15/fonoteka/plugins/golem15/journal rev-parse HEAD && git diff empty" + status: pass + human_judgment: false + +duration: 11min +completed: 2026-10-06 +status: complete +--- + +# Phase 15 Plan 01: Clone journal plugin, squash schema, boot three plugins Summary + +**Compiled sm-journal-plugin persists one en/pl Post through translate, mounts in sm-grzybyfunkcjonalne-app with user+translate, and ships squashed golem15_journal_* plus CORS** + +## Performance + +- **Duration:** 11 min +- **Started:** 2026-10-06T16:19:00Z +- **Completed:** 2026-10-06T16:29:41Z +- **Tasks:** 3 +- **Files modified:** 31 + +## Accomplishments +- Cloned `sm-journal-plugin` with ID `golem15.journal`, `Requires` exactly `golem15.translate`, and squashed posts DDL +- `TestPostTranslatableSmoke` stores English on the host row and Polish in `golem15_translate_attributes` under MorphName `Golem15\Journal\Models\Post` +- Proof host Activate returns three plugins including `golem15.journal`; `summer build` regenerates `plugins.gen.go` +- Categories, tags, pivots, settings singleton ID=1, and `backend_users.golem15_bloghub_author_slug` migrate; Uncategorized is seeded, posts are not +- en/pl UI catalogs, application-neutral README, host CORS `_journal/api/*` with `supports_credentials: false` + +## Task Commits + +Each task was committed atomically in the owning repo: + +1. **Task 1: Clone the plugin, persist one en/pl Post title, and boot the host with three plugins** + - `54322128fb6d4fb9d73e3b74e5575c86e9798c68` (feat) sm-journal-plugin tracer + - `445022ef711274cb4ea1973a5b10ee7afc047a53` (fix) models leaf + go.mod translate replace + - `d77f945c05f372b2ca221c5a0acb21137d46e330` (feat) sm-grzybyfunkcjonalne-app mount +2. **Task 2: Add categories, tags, pivots, settings singleton, and author_slug** - `9ae4b9141eaec1bb8efb367f8d8f525f15f23dc8` (feat) sm-journal-plugin +3. **Task 3: Add en/pl phrasebook, neutral README, and host CORS** + - `bb903a68509159e90dac6a77a0124d2b2dd14843` (feat) sm-journal-plugin lang/README + - `41c9b9212dbe11c3b1da5d0a87323b2245d32f6a` (feat) host CORS + gitlink `bb903a6` + +**Plan metadata:** (this commit) + +## Files Created/Modified +- `../sm-journal-plugin/plugin.go` - compiled registration, Requires translate, HasMigrations/HasModels/HasLang +- `../sm-journal-plugin/models/post.go` - TableName, MorphName, Translatable, AttachRelations, belongsTo BackendUser +- `../sm-journal-plugin/updates/202610060001` through `007` - squashed journal DDL and author slug +- `../sm-journal-plugin/README.md` - application-neutral plugin docs +- `../sm-grzybyfunkcjonalne-app/summer.yaml`, `go.work`, `go.mod`, `.gitmodules`, `boot_test.go`, `plugins.gen.go`, `config/http.yaml` - three-plugin host + CORS + +## Decisions Made +- Squash to `golem15_journal_*` only; do not emit rainlab-era table names +- Keep `sm-translate-plugin` replace in journal `go.work`, not `go.mod`, matching the host workspace `use` of translate +- Seed Uncategorized because PHP `seed_all_tables.php` at this pin still inserts it (A4); do not seed the first post +- Declare `slug` on `Translatable()` so `SetTranslated` accepts the indexed slug + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 3 - Blocking] models cannot import updates** +- **Found during:** Task 1 (`summer build`) +- **Issue:** `checkModelsLeaf` rejects `models/post_translatable_smoke_test.go` importing `.../updates` +- **Fix:** Smoke test calls `(&journal.Plugin{}).Migrations()` and `(&translate.Plugin{}).Migrations()` +- **Files modified:** `../sm-journal-plugin/models/post_translatable_smoke_test.go` +- **Verification:** `summer build` in the host; `TestPostTranslatableSmoke` PASS +- **Committed in:** `445022e` (Task 1 fix) + +**2. [Rule 3 - Blocking] go.mod translate replace collides with host workspace** +- **Found during:** Task 1 (host `go vet`) +- **Issue:** `replace => ../sm-translate-plugin` from `plugins/golem15/journal` points at a second path next to `use ./plugins/golem15/translate` +- **Fix:** Drop the translate replace from plugin `go.mod`; keep it in plugin `go.work` +- **Files modified:** `../sm-journal-plugin/go.mod` +- **Verification:** host `go vet` and `TestBootUserTranslateJournal` PASS +- **Committed in:** `445022e` (Task 1 fix) + +**3. [Rule 2 - Missing Critical] slug must be translatable for SetTranslated** +- **Found during:** Task 1 (`TestPostTranslatableSmoke`) +- **Issue:** PHP `$translatable` includes `['slug','index'=>true]`; indexes-only made `SetTranslated(..., "slug", "pl", ...)` fail +- **Fix:** Add `slug` to `Post.Translatable()` (and Category) +- **Files modified:** `../sm-journal-plugin/models/post.go`, `models/category.go` +- **Verification:** `TestPostTranslatableSmoke` PASS +- **Committed in:** `5432212` / Task 2 Category + +**4. [A4] Seed Uncategorized despite RESEARCH grep skip** +- **Found during:** Task 2 (execute-time read of PHP `seed_all_tables.php`) +- **Issue:** Plan said RESEARCH grep found no seeder — skip; A4 said verify at execute. The pin seeder still inserts Uncategorized and a first post +- **Fix:** Seed Uncategorized only; do not seed posts +- **Files modified:** `../sm-journal-plugin/updates/202610060002_create_golem15_journal_categories.go` +- **Verification:** `TestJournalTables` asserts one `uncategorized` row and zero posts +- **Committed in:** `9ae4b91` (Task 2) + +--- + +**Total deviations:** 4 auto-fixed (3 blocking/correctness, 1 A4 seeder) +**Impact on plan:** Required for host mount, translate writes, and PHP pin fidelity. No scope creep. + +## Issues Encountered +- `git submodule add` from a local path needed `protocol.file.allow=always`; `.gitmodules` URL was then set to `git@git.golem15.com:golem15/sm-journal-plugin.git` +- Journal remote still has no refs; gitlink records local SHA `bb903a6`. Do not push unless asked +- Host submodule is a separate checkout from the sibling; Task 2/3 SHAs were fetched from the sibling with file protocol + +## User Setup Required +None - no external service configuration required. + +## Next Phase Readiness +Ready for 15-02 (admin YAML, FormatHTML, permissions/nav, import/export). Public `/_journal/api/v1` handlers are not in this plan; CORS path is in place. Plugin remote is empty until a later push. + +--- +*Phase: 15-journal-plugin* +*Completed: 2026-10-06*