--- phase: 14.2.1-translate-plugin plan: 03 subsystem: i18n tags: [translate, cabana, markdown, mltext, mlmarkdown, TranslationWriter, proof-host, sm-grzybyfunkcjonalne-app] requires: - phase: 14.2.1-02 provides: "Translatable SetTranslated/Translated/WithLocale and permissioned Locales admin" provides: - "cabana markdown, mltext, and mlmarkdown field types with nested locale-map lifting" - "Framework-owned cabana.TranslationWriter plus sm-translate-plugin Boot adapter" - "Safe cabana.RenderMarkdown (goldmark, no unsafe HTML)" - "SPA MarkdownField, MLTextField, MLMarkdownField with shared locale selector" - "Docs, regenerated OpenAPI/TS, committed boardwalk dist" - "sm-grzybyfunkcjonalne-app boots golem15.user + golem15.translate from durable submodules" affects: [14.2.1-04 tests, 15-journal-plugin] actuals: tokens: 27343 tasks: 3 commits: 2 plan_head_before: 234111d245d300e19dcfc33b00f311c881a214fb plan_head_after: e3b3475b1cb5d3321e72be8863df6af6527db6b2 plugin_repo_head_after: a3553b9c4b8a9c83debe950198f568ee9b6000a6 host_repo_head_after: 4d32e86 tech-stack: added: [] patterns: - "ML locale maps are lifted before ProjectWritableFields; default locale fills the host scalar; other locales go through TranslationWriter inside the host save transaction" - "Proof host mounts compiled plugins as git submodules at plugins/golem15/{user,translate} with go.work use plus host and workspace replaces" key-files: created: - modules/cabana/field_ml.go - modules/cabana/field_markdown.go - modules/cabana/ml_smoke_test.go - admin/src/components/form/fields/MarkdownField.vue - admin/src/components/form/fields/MLTextField.vue - admin/src/components/form/fields/MLMarkdownField.vue - admin/tests/form/MLFields.test.ts - ../sm-translate-plugin/classes/admin_writer.go - ../sm-grzybyfunkcjonalne-app/summer.yaml - ../sm-grzybyfunkcjonalne-app/go.work - ../sm-grzybyfunkcjonalne-app/.gitmodules - ../sm-grzybyfunkcjonalne-app/boot_test.go modified: - modules/cabana/form_schema.go - modules/cabana/crud.go - modules/cabana/README.md - docs/backend/forms.md - docs/backend/admin-controllers.md - admin/src/components/form/registry.ts - admin/src/components/form/formState.ts - admin/tests/form/registry.test.ts - modules/boardwalk/dist/ - ../sm-translate-plugin/plugin.go key-decisions: - "Task 2 locked grzyby-submodules: the proof host is sm-grzybyfunkcjonalne-app with plugins/golem15/user and plugins/golem15/translate" - "Host go.work replace points at ../summercms.go so the plugin sibling replace is overridden when mounted" patterns-established: - "cabana.TranslationWriter lives in the framework; the translate plugin Boot-publishes an adapter; there is no public translate-write endpoint" - "mlmarkdown composes MarkdownField; goldmark stays in cabana.RenderMarkdown without html.WithUnsafe" requirements-completed: [D-06, D-09, D-12, D-13, D-14, D-15, D-16, D-17] coverage: - id: D1 description: "Nested mltext save lifts the locale map, writes English on the host column, and Polish through TranslationWriter" requirement: D-06 verification: - kind: unit ref: "modules/cabana#TestMLNestedSaveSmoke" status: pass human_judgment: false - id: D2 description: "SPA registry resolves markdown/mltext/mlmarkdown, sends nested locale records, and sanitizes markdown preview" requirement: D-06 verification: - kind: unit ref: "admin/tests/form/MLFields.test.ts" status: pass - kind: unit ref: "admin/tests/form/registry.test.ts" status: pass human_judgment: false - id: D3 description: "Cabana README, forms/admin docs, OpenAPI, generated TS types, and boardwalk dist stay in sync with application-neutral examples" verification: - kind: other ref: "go test ./cmd/summer -run TestDocsTree && go run ./cmd/summer docs:build --check" status: pass - kind: other ref: "scripts/check-admin-openapi.sh && npm --prefix admin run build" status: pass human_judgment: false - id: D4 description: "sm-grzybyfunkcjonalne-app mounts user and translate as submodules, generates the plugin list, and registers Locales admin" requirement: D-13 verification: - kind: integration ref: "sm-grzybyfunkcjonalne-app#TestBootUserTranslate" status: pass human_judgment: false - id: D5 description: "Task 2 proof-host layout locked as grzyby-submodules" requirement: D-13 verification: [] human_judgment: true rationale: "Layout choice is a recorded human decision, not an automated assertion" duration: 5min completed: 2026-10-06 status: complete --- # Phase 14.2.1 Plan 03: Cabana ML fields and proof-host boot Summary **Cabana markdown/mltext/mlmarkdown with transactional TranslationWriter saves, regenerated admin artifacts, and sm-grzybyfunkcjonalne-app booting user+translate from durable submodules** ## Performance - **Duration:** 5 min (continuation from Task 2; Task 1 landed in a prior executor) - **Started:** 2026-10-06T11:23:45Z - **Completed:** 2026-10-06T11:29:17Z - **Tasks:** 3 - **Files modified:** 40 - **Token actuals:** 27343 (chars/4 excluding rebuilt `modules/boardwalk/dist`; 320645 including it) ## Accomplishments - Cabana accepts `markdown`, `mltext`, and `mlmarkdown`. Nested locale maps are lifted before `ProjectWritableFields`; the default locale fills the host scalar; other locales reach `cabana.TranslationWriter` inside the permissioned host save transaction. `cabana.RenderMarkdown` uses goldmark without unsafe HTML. - The SPA sends `Record` per ML field, shares one locale selector across controls, copies from another locale, and composes `mlmarkdown` from `MarkdownField`. - Cabana README, `docs/backend/forms.md`, and admin-controller save semantics are updated with acme/blog examples. OpenAPI was regenerated (unchanged), TypeScript types regenerated, and `modules/boardwalk/dist/` rebuilt. - Task 2 recorded **grzyby-submodules**. `sm-grzybyfunkcjonalne-app` mounts `plugins/golem15/user` @ `0fe5b91` and `plugins/golem15/translate` @ `a3553b9`, uses go.work plus host replaces, lists only `golem15.user` and `golem15.translate`, and `TestBootUserTranslate` activates both plugins and sees Locales admin. Journal is absent. Go tables remain `golem15_translate_*`. ## Task Commits Each task was committed atomically: 1. **Task 1: Submit one mltext map through cabana and persist default plus Polish values** - `a04116d` (feat) summercms.go — markdown and multilingual cabana fields - `a3553b9` (feat) sm-translate-plugin — publish cabana TranslationWriter adapter 2. **Task 2: Confirm the one-way proof-host submodule layout** — decision `grzyby-submodules` (no code commit) 3. **Task 3: Complete docs/OpenAPI/TS/dist and boot the user+translate proof host** - `e3b3475` (feat) summercms.go — docs, registry tests, boardwalk dist - `4d32e86` (feat) sm-grzybyfunkcjonalne-app — host layout and boot smoke **Plan metadata:** (this commit) The proof host was not pushed. summercms.go was not pushed. ## Files Created/Modified - `modules/cabana/field_ml.go` — locale-map lift and TranslationWriter bridge - `modules/cabana/field_markdown.go` — `RenderMarkdown` - `modules/cabana/ml_smoke_test.go` — nested `{en,pl}` save smoke - `admin/src/components/form/fields/{Markdown,MLText,MLMarkdown}Field.vue` - `admin/tests/form/MLFields.test.ts` and `registry.test.ts` - `modules/cabana/README.md`, `docs/backend/forms.md`, `docs/backend/admin-controllers.md` - `modules/boardwalk/dist/` — regenerated Vite output - `../sm-translate-plugin/classes/admin_writer.go` and `plugin.go` Boot publish - `../sm-grzybyfunkcjonalne-app/{summer.yaml,go.mod,go.work,.gitmodules,main.go,plugins.gen.go,boot_test.go}` ## Decisions Made - Task 2 selected **grzyby-submodules**: durable proof-host layout is `sm-grzybyfunkcjonalne-app` with `plugins/golem15/user` and `plugins/golem15/translate`, matching D-13/D-16 and sm-bm-app. `fonoteka-host` and `vendored-copy` were not taken. - Host `go.work` replace `git.golem15.com/golem15/summercms => ../summercms.go` overrides the translate plugin's sibling `../summercms.go` replace when the plugin is mounted at `plugins/golem15/translate`. - OpenAPI/TS were regenerated with `scripts/check-admin-openapi.sh`; the document did not change because no swag annotations were added. Dist was rebuilt, not hand-edited. ## Deviations from Plan ### Auto-fixed Issues **1. [Rule 3 - Blocking] Vitest `--run` paths are relative to `admin/`** - **Found during:** Task 3 verify - **Issue:** `npm --prefix admin test -- --run admin/tests/form/registry.test.ts ...` reports no test files because Vitest's cwd is `admin/` and `include` is `tests/**/*.test.ts`. - **Fix:** Ran `tests/form/registry.test.ts tests/form/MLFields.test.ts` (50 passed). - **Files modified:** none - **Verification:** Vitest `Test Files 2 passed (2)`, `Tests 50 passed (50)` - **Committed in:** n/a (command-only) --- **Total deviations:** 1 auto-fixed (1 blocking) **Impact on plan:** Required for the written verify command's intent. No API or layout change. ## Issues Encountered None beyond the Vitest path mismatch. ## Authentication Gates None. ## User Setup Required None - no external service configuration required. ## Next Phase Readiness - Ready for 14.2.1-04 unit/integration tests. - Journal (Phase 15) can mount on this host using the same submodule paths. - Proof host commit `4d32e86` is local only; push when a later plan requires it. --- *Phase: 14.2.1-translate-plugin* *Completed: 2026-10-06* ## Self-Check: PASSED