--- 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*