docs(14.2.1): capture phase context
This commit is contained in:
142
.planning/phases/14.2.1-translate-plugin/14.2.1-CONTEXT.md
Normal file
142
.planning/phases/14.2.1-translate-plugin/14.2.1-CONTEXT.md
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
# Phase 14.2.1: Translate plugin - Context
|
||||||
|
|
||||||
|
**Gathered:** 2026-10-06
|
||||||
|
**Status:** Ready for planning
|
||||||
|
|
||||||
|
<domain>
|
||||||
|
## Phase Boundary
|
||||||
|
|
||||||
|
`Golem15.Translate` is ported to Go as `sm-translate-plugin` so Journal (Phase 15) and later blogs can keep translatable fields. This phase ships the lean core Journal needs: the Locale model and its admin screen, the TranslatableModel behavior, cabana ML field types, and PHP's request-locale resolution.
|
||||||
|
|
||||||
|
The proof host is `sm-grzybyfunkcjonalne-app`, booted with `sm-user-plugin` + `sm-translate-plugin` (Journal mounts in Phase 15). Proof: the app boots, Locales admin works, and a fixture model can save and read `en`+`pl` through ML fields and `WithLocale`.
|
||||||
|
|
||||||
|
`summercms.go` is touched for the ML field types (`mltext`, `mlmarkdown`) and any Translator/request-locale seam the plugin cannot own alone.
|
||||||
|
|
||||||
|
Out of scope: the Messages catalogue and `manage_messages` admin, locale-picker / hreflang / suggestion-banner CMS components, AI and theme console commands, message import/export, and any edit to `wn-translate-plugin`. Those wait for a later translate follow-up if a site needs them.
|
||||||
|
|
||||||
|
</domain>
|
||||||
|
|
||||||
|
<decisions>
|
||||||
|
## Implementation Decisions
|
||||||
|
|
||||||
|
### PHP source of truth
|
||||||
|
- **D-01:** The port contract is `github.com/golem15com/wn-translate-plugin` at git SHA `725d547` (2026-08-26), the pin currently checked out in Płytarium. That tree is newer than grzybyfunkcjonalne.pl (`6e0c146`). — **Reversibility:** costly — Locale tables, attribute storage and Translator behaviour are copied from this tree.
|
||||||
|
- **D-02:** Freeze at `725d547`. Planner and researcher must not silently pick a newer `master`. — **Reversibility:** reversible — a later discussion can re-pin.
|
||||||
|
- **D-03:** Downstream agents read the frozen source from `/media/nvme/dev/golem15/fonoteka/plugins/golem15/translate` (already at that SHA). Do not clone a second copy unless that path is missing or the SHA does not match.
|
||||||
|
- **D-04:** This phase does not edit or PR `wn-translate-plugin`. An urgent PHP upgrade on a live Winter site before that site migrates is allowed as operations. If it lands before plan or execute, re-pin the SHA rather than mixing trees.
|
||||||
|
|
||||||
|
### What ships this phase
|
||||||
|
- **D-05:** Lean only: Locale model + Locales admin (`golem15.translate.manage_locales`), and a TranslatableModel behavior Journal can implement. Messages catalogue, locale-picker components, AI/theme commands and message import/export are deferred. — **Reversibility:** reversible — later plans can add the rest without rewriting Locale.
|
||||||
|
- **D-06:** Cabana gains ML field types (`mltext`, `mlmarkdown`) matching PHP's `ml*` widgets, so a Journal form stays one screen with a locale switch. Phase 15's markdown field (15 D-11) and these ML types must compose (`mlmarkdown` is markdown plus locale). — **Reversibility:** costly — new field types in the typed admin schema and generated TS types.
|
||||||
|
- **D-07:** Port PHP `Translator` locale resolution: URL prefix / session / cookie / default. Do not reduce this phase to `Accept-Language` or a query param only. — **Reversibility:** costly — public blog URLs and the Journal API will depend on this order.
|
||||||
|
- **D-08:** The plugin seeds English and Polish locales, matching Journal 15 D-06.
|
||||||
|
|
||||||
|
### Model API
|
||||||
|
- **D-09:** A Go model declares translatable attributes with a `Translatable() []string` (or equivalent tagged list) the way PHP uses `$translatable`. Journal copies the PHP Post/Category lists. — **Reversibility:** costly — every translatable model in shared plugins will call this.
|
||||||
|
- **D-10:** Storage uses the same tables and columns as this PHP pin (`golem15_translate_*` attributes/indexes/locales — researcher confirms exact names from the frozen updates). No JSON-column alternative. — **Reversibility:** one-way — Winter import and Journal cutover expect those tables.
|
||||||
|
- **D-11:** A missing translation falls back to the default locale, as PHP does.
|
||||||
|
- **D-12:** The exported API other plugins call this phase is the minimum: `WithLocale` on queries, get/set an attribute in a locale, and current locale from Translator. Do not 1:1 every PHP `TranslatableModel` / `Translator` method name unless research shows Journal needs it.
|
||||||
|
|
||||||
|
### Where it boots
|
||||||
|
- **D-13:** The host is `sm-grzybyfunkcjonalne-app` (same as Phase 15 D-18). This phase mounts `sm-user-plugin` + `sm-translate-plugin`; Journal is added in Phase 15. — **Reversibility:** one-way — submodule layout lands in that app.
|
||||||
|
- **D-14:** Local app checkout: `/media/nvme/dev/golem15/summercms.io/summercms/sm-grzybyfunkcjonalne-app/` (sibling of `summercms.go`).
|
||||||
|
- **D-15:** The user creates the public Gitea remote `git@git.golem15.com:golem15/sm-translate-plugin.git` as a manual plan step (it does not exist yet). Module path `git.golem15.com/golem15/sm-translate-plugin`, package `translate`, plugin ID `golem15.translate`.
|
||||||
|
- **D-16:** Local plugin checkout: `/media/nvme/dev/golem15/summercms.io/summercms/sm-translate-plugin/` (sibling of `summercms.go`). The host mounts it as a submodule at `plugins/golem15/translate` with a `go.work` replace.
|
||||||
|
- **D-17:** Phase proof: the app boots with user+translate; Locales admin works; a fixture model can save and read `en`+`pl` through ML fields and `WithLocale`.
|
||||||
|
|
||||||
|
### Claude's Discretion
|
||||||
|
- Exact `golem15_translate_*` table/column names and migration IDs, taken from the frozen PHP updates (D-10), not invented.
|
||||||
|
- ML field YAML type names and SPA locale-switcher chrome, provided they follow cabana fail-loud rules and update the module README, `docs/`, admin OpenAPI, generated TS types and committed `dist/` in the same change.
|
||||||
|
- How `mlmarkdown` shares implementation with Phase 15's markdown field (land the shared primitive here if Journal is otherwise blocked).
|
||||||
|
- Plan count and split, subject to the plan-count checkpoint and "unit tests are the last plan".
|
||||||
|
- Run the security-review agent: locale switching on public requests and admin ML writes are authorization-adjacent.
|
||||||
|
|
||||||
|
</decisions>
|
||||||
|
|
||||||
|
<canonical_refs>
|
||||||
|
## Canonical References
|
||||||
|
|
||||||
|
**Downstream agents MUST read these before planning or implementing.**
|
||||||
|
|
||||||
|
### Roadmap and prior decisions
|
||||||
|
- `.planning/ROADMAP.md` § Phase 14.2.1 — stub goal; this file is the real scope
|
||||||
|
- `.planning/ROADMAP.md` § Phase 15 — Journal depends on this plugin
|
||||||
|
- `.planning/phases/15-journal-plugin/15-CONTEXT.md` — D-09/D-10 (Journal requires translate; translatable title/slug/content), D-06 (`en`+`pl`), D-11 (markdown field), D-18–D-21 (grzyby host)
|
||||||
|
- `.planning/notes/core-plugins-own-repos.md` — `sm-<name>-plugin` layout, module path, submodule mount
|
||||||
|
- `.planning/phases/12.1-user-plugin-admin-screens/12.1-CONTEXT.md` — YAML admin screens, framework-first field types
|
||||||
|
- `.planning/phases/04-cli-scaffolding-i18n-and-mail/04-CONTEXT.md` — phrasebook; this plugin is model-level translation, not UI strings
|
||||||
|
- `.planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-CONTEXT.md` — typed schema, fail-loud YAML
|
||||||
|
|
||||||
|
### PHP contract (read-only) — `/media/nvme/dev/golem15/fonoteka/plugins/golem15/translate` at SHA `725d547`
|
||||||
|
- `Plugin.php` — permissions (`manage_locales`, `manage_messages`), navigation, components (components are out of scope)
|
||||||
|
- `models/Locale.php`, `models/Attribute.php`, `models/Message.php` (Message is out of scope except as a table that must not be broken)
|
||||||
|
- `behaviors/` — TranslatableModel (or equivalent) and how `$translatable` is applied
|
||||||
|
- `classes/Translator.php` — URL prefix / session / cookie / default (D-07)
|
||||||
|
- `controllers/Locales.php` and YAML under `controllers/locales/`, `models/locale/`
|
||||||
|
- `formwidgets/` — PHP `ml*` widgets that D-06 replaces
|
||||||
|
- `updates/` — Locale / attributes / indexes table names and migration IDs (D-10)
|
||||||
|
- `README.md`, `UPGRADE.md`
|
||||||
|
- `tests/` — use as landmines; lean scope means not every PHP test maps 1:1
|
||||||
|
|
||||||
|
### Go references
|
||||||
|
- `../fonoteka.go/plugins/golem15/user/` — mount pattern for the sibling plugin
|
||||||
|
- `modules/cabana/` — field registry; `mltext` / `mlmarkdown` land here
|
||||||
|
- `modules/phrasebook/` — UI strings; do not conflate with model translations
|
||||||
|
- `docs/backend/forms.md`, `docs/backend/admin-controllers.md`
|
||||||
|
|
||||||
|
### Remotes
|
||||||
|
- `git@git.golem15.com:golem15/sm-translate-plugin.git` — **does not exist yet**; user creates it, public
|
||||||
|
- `git@git.golem15.com:golem15/sm-grzybyfunkcjonalne-app.git` — empty proof host, already created
|
||||||
|
- `git@git.golem15.com:golem15/sm-journal-plugin.git` — public, empty; mounted in Phase 15
|
||||||
|
|
||||||
|
</canonical_refs>
|
||||||
|
|
||||||
|
<code_context>
|
||||||
|
## Existing Code Insights
|
||||||
|
|
||||||
|
### Reusable Assets
|
||||||
|
- `sm-user-plugin` mount pattern: `summer.yaml`, submodule at `plugins/golem15/user`, `go.work` replace, `pact.HasAdminControllers`.
|
||||||
|
- cabana field registry (Phase 12.1 `permissioneditor`, Phase 12.2 `fileupload` / `datepicker`): the pattern for `mltext` / `mlmarkdown`.
|
||||||
|
- phrasebook `en`/`pl` for plugin UI strings — separate from Locale rows and attribute translations.
|
||||||
|
- `sm-grzybyfunkcjonalne-app` remote already exists; local directory may not.
|
||||||
|
|
||||||
|
### Established Patterns
|
||||||
|
- Shared plugins: module `git.golem15.com/golem15/sm-<name>-plugin`, package plain (`translate`), plugin ID `golem15.translate`.
|
||||||
|
- Unknown YAML keys fail boot. Framework field types update README, `docs/`, OpenAPI, TS types and `boardwalk` `dist/` in the same change.
|
||||||
|
- PHP originals are not changed. Migrations are append-only. Unit tests are the last plan.
|
||||||
|
|
||||||
|
### Integration Points
|
||||||
|
- New repo `sm-translate-plugin`: Locale model, updates, Locales admin, Translatable behavior, Translator.
|
||||||
|
- `summercms.go` cabana + admin SPA: `mltext`, `mlmarkdown`, locale switcher on forms.
|
||||||
|
- `sm-grzybyfunkcjonalne-app`: first mount of user + translate.
|
||||||
|
- Phase 15 Journal: `Requires` translate; Post/Category `Translatable()` lists; `mltext`/`mlmarkdown` on YAML forms.
|
||||||
|
|
||||||
|
</code_context>
|
||||||
|
|
||||||
|
<specifics>
|
||||||
|
## Specific Ideas
|
||||||
|
|
||||||
|
- Same freeze/read-only/re-pin rules as Journal, applied to Translate.
|
||||||
|
- "Start fast" on `sm-grzybyfunkcjonalne-app` still holds; this phase boots that app without Journal.
|
||||||
|
- Messages, CMS locale components and AI/theme commands were explicitly left out so Journal is not blocked.
|
||||||
|
|
||||||
|
</specifics>
|
||||||
|
|
||||||
|
<deferred>
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- Messages catalogue and `golem15.translate.manage_messages` admin.
|
||||||
|
- Locale picker, alternate hreflang, and locale-suggestion-banner CMS components (Phase 16 views may need a successor).
|
||||||
|
- AI/theme console commands and message import/export.
|
||||||
|
- Remaining PHP locales beyond the `en`+`pl` seed (D-08 is seed rows, not phrasebook files).
|
||||||
|
- Phase 15 should list **Depends on: Phase 14.2.1** in ROADMAP (`$gsd-phase --edit 15`); not done in this discussion.
|
||||||
|
|
||||||
|
### Reviewed Todos (not folded)
|
||||||
|
- `sitemap-plugin-port.md`, `mailblocker-with-mailing.md`, and the other keyword matches from `todo.match-phase 14.2.1`: unrelated housekeeping.
|
||||||
|
|
||||||
|
</deferred>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Phase: 14.2.1-translate-plugin*
|
||||||
|
*Context gathered: 2026-10-06*
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
# Phase 14.2.1: Translate plugin - Discussion Log
|
||||||
|
|
||||||
|
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
|
||||||
|
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
|
||||||
|
|
||||||
|
**Date:** 2026-10-06
|
||||||
|
**Phase:** 14.2.1-translate-plugin
|
||||||
|
**Areas discussed:** PHP source of truth, what ships, model API, where it boots
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PHP source of truth
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Fonoteka pin `725d547` | Newest Płytarium checkout | ✓ |
|
||||||
|
| grzyby pin `6e0c146` | Older ancestor | |
|
||||||
|
| GitHub master at plan time | Moving target | |
|
||||||
|
|
||||||
|
**User's choice:** Freeze at `725d547`, read from the Fonoteka path. Read-only with the same urgent-upgrade re-pin rule as Journal.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What ships
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Lean: Locale + TranslatableModel | Unblocks Journal | ✓ |
|
||||||
|
| Lean plus Messages catalogue | Extra admin | |
|
||||||
|
| Full PHP surface | Picker, AI/theme, import/export | |
|
||||||
|
|
||||||
|
**User's choice:** Lean. Cabana `mltext`/`mlmarkdown`. PHP Translator resolution (URL prefix / session / cookie / default). Seed `en`+`pl`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Model API
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| `Translatable() []string` like PHP `$translatable` | Journal copies the PHP list | ✓ |
|
||||||
|
| YAML-only; models unaware | | |
|
||||||
|
| Same Winter attribute tables | Cutover-compatible | ✓ |
|
||||||
|
| JSON column per field | Breaks Winter import | |
|
||||||
|
| Fallback to default locale | PHP behaviour | ✓ |
|
||||||
|
| Minimum API (`WithLocale`, get/set, Translator) | Enough for Journal | ✓ |
|
||||||
|
| 1:1 every PHP method | | |
|
||||||
|
|
||||||
|
**User's choice:** PHP-like declaration, same tables, PHP fallback, minimum exported API.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Where it boots
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Same `sm-grzybyfunkcjonalne-app` | Matches Phase 15 D-21 | ✓ |
|
||||||
|
| In-module testhost | | |
|
||||||
|
| User creates `sm-translate-plugin` remote | Does not exist yet | ✓ |
|
||||||
|
| Sibling checkout | `summercms/sm-translate-plugin/` | ✓ |
|
||||||
|
| Proof: Locales admin + fixture en+pl | | ✓ |
|
||||||
|
| Plugin tests only | | |
|
||||||
|
|
||||||
|
**User's choice:** Grzyby host with user+translate. User creates the public remote. Proof is boot + Locales admin + fixture model.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Claude's Discretion
|
||||||
|
|
||||||
|
- Exact table/column names from frozen PHP updates
|
||||||
|
- ML field identifiers and docs/OpenAPI/`dist/` bundling
|
||||||
|
- How `mlmarkdown` shares work with Phase 15 markdown
|
||||||
|
- Plan count and split
|
||||||
|
- Security-review agent
|
||||||
|
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- Messages admin, CMS locale components, AI/theme commands
|
||||||
|
- ROADMAP Phase 15 depends_on should include 14.2.1 (`$gsd-phase --edit 15`)
|
||||||
Reference in New Issue
Block a user