Files
summercms/.planning/phases/14.2.1-translate-plugin/14.2.1-VERIFICATION.md
2026-10-06 16:40:06 +02:00

30 KiB
Raw Blame History

phase, verified, status, score, covered_files, covered_digest, covered_files_note, behavior_unverified, overrides_applied, re_verification, advisory, human_verification
phase verified status score covered_files covered_digest covered_files_note behavior_unverified overrides_applied re_verification advisory human_verification
14.2.1-translate-plugin 2026-10-06T14:40:00Z human_needed 16/16 must-haves verified
.planning/phases/14.2.1-translate-plugin/14.2.1-01-PLAN.md
.planning/phases/14.2.1-translate-plugin/14.2.1-01-SUMMARY.md
.planning/phases/14.2.1-translate-plugin/14.2.1-02-PLAN.md
.planning/phases/14.2.1-translate-plugin/14.2.1-02-SUMMARY.md
.planning/phases/14.2.1-translate-plugin/14.2.1-03-PLAN.md
.planning/phases/14.2.1-translate-plugin/14.2.1-03-SUMMARY.md
.planning/phases/14.2.1-translate-plugin/14.2.1-04-PLAN.md
.planning/phases/14.2.1-translate-plugin/14.2.1-04-SUMMARY.md
.planning/phases/14.2.1-translate-plugin/14.2.1-05-PLAN.md
.planning/phases/14.2.1-translate-plugin/14.2.1-05-SUMMARY.md
.planning/phases/14.2.1-translate-plugin/14.2.1-06-PLAN.md
.planning/phases/14.2.1-translate-plugin/14.2.1-06-SUMMARY.md
admin/src/api/schema.d.ts
admin/src/components/form/fields/MLMarkdownField.vue
admin/src/components/form/fields/MLTextField.vue
admin/src/components/form/formContext.ts
admin/src/components/form/formState.ts
admin/src/components/form/mlLocale.ts
admin/src/components/form/registry.ts
admin/src/components/relation/RelationChildModal.vue
admin/src/views/FormView.vue
admin/tests/form/MLFields.test.ts
admin/tests/form/formState.test.ts
docs/backend/admin-controllers.md
docs/backend/forms.md
modules/cabana/README.md
modules/cabana/crud.go
modules/cabana/field_markdown.go
modules/cabana/field_ml.go
modules/cabana/form_schema.go
modules/cabana/http.go
modules/cabana/ml_smoke_test.go
modules/cabana/ml_test.go
modules/cabana/openapi_conformance_test.go
modules/cabana/relation.go
modules/cabana/relation_child.go
modules/cabana/relation_child_ml_test.go
modules/cabana/schema_types.go
modules/surf/locale_from_principal.go
modules/surf/locale_resolver.go
modules/surf/router.go
scripts/check-phase14.2.1.sh
v2:sha256:e8c9c72cd5252f44d6193fa658ea95663432905c4a061fd228887f46a07c4402 verification.fingerprint covers only paths under the summercms.go root. Sibling implementation read this pass: sm-translate-plugin b3e0e26 (plugin.go, Locale/Attribute/Index models, five golem15_translate_* migrations, Translator, Translatable, TranslatedExact, Locales admin, AdminWriter, integration/admin/migration tests); sm-grzybyfunkcjonalne-app 1860ad6 (summer.yaml, plugins.gen.go, go.work, gitlinks, boot_test.go). Host translate gitlink is b3e0e26. PHP pin /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate HEAD 725d547ec839f02b5fdc0f0a6faaed601a414d50, clean tree, not edited. 0 0
previous_status previous_score gaps_closed gaps_remaining regressions
gaps_found 14/16
Cabana markdown/mltext/mlmarkdown compose; nested locale writes are not dropped
The SPA exposes one locale selector per ML field, switches all ML controls together, supports copy-from-locale, and sends every locale as Record<string,string>
test expected why_human
Boot the proof host and open Locales in the admin SPA Sign in as an administrator holding golem15.translate.manage_locales; English then Polski appear in sort_order; name/enabled can be edited; a user without the permission cannot open the controller Needs a running host, admin login, and visual confirmation of the Locales screen. Harvested from 14.2.1-04-PLAN.md and 14.2.1-06-PLAN.md human-checks. Automated tests cover HTTP 403/list order, not the SPA chrome.
test expected why_human
With the proof host and admin SPA, open a Journal-shaped form with mltext when one is available Create lists en and pl (not a single English box); one locale selector per ML field; switching one selector switches the others; save/reload still shows both locales Harvested from 14.2.1-06-PLAN.md. Vitest proves seed/selector/broadcast/copy-from against provided ['en','pl'], not a running SPA against schema meta from the live writer. The proof host has no production mltext YAML (only test-harness fields); do not invent a pass. Relation-child ML UAT can wait for Phase 15 if this host has no child ML form.

Phase 14.2.1: Translate plugin Verification Report

Phase Goal: Golem15.Translate is ported to Go as sm-translate-plugin so Journal (Phase 15) can keep translatable fields. Lean core only: Locale model and Locales admin, Translatable API, cabana mltext/mlmarkdown, and PHP Translator locale resolution (URL prefix / session / cookie / default). Verified: 2026-10-06T14:40:00Z Status: human_needed Re-verification: Yes — after gap closure (plans 05 CR-01 and 06 WR-02)

MVP note: ROADMAP does not mark this phase mode: mvp. User Flow Coverage is derived from ROADMAP success criteria and CONTEXT D-17.

Prior report (2026-10-06T12:48:00Z) was gaps_found 14/16. CR-01 and WR-02 are closed in source. All 16 must-have truths are now VERIFIED. Status is human_needed because harvested SPA UAT remains; it is not a pass.

User Flow Coverage

Step Expected Evidence Status
Proof host boots user+translate party.Activate loads golem15.user then golem15.translate; Locales controller and manage_locales are registered; submodules are gitlinks sm-grzybyfunkcjonalne-app/plugins.gen.go, summer.yaml, gitlink b3e0e26; TestBootUserTranslate exists ✓
Operators manage locales YAML CRUD gated by exactly golem15.translate.manage_locales; seed en then pl; no Messages admin controllers/locales.go RequiredPermissions; production Permissions() is only manage_locales ✓ API; SPA list/edit is human
Fixture saves and reads en+pl through Translatable / WithLocale Default on host columns; pl in golem15_translate_attributes; missing pl falls back classes/translatable.go; Translated still does D-11; TranslatedExact does not ✓ API
Journal-shaped admin form is one screen with a locale switch Enabled locales on create/load/save; nested {en,pl} posted and rehydrated FormMeta.EnabledLocales; hydrateMLRecord + TranslatedExact; SPA FORM_ENABLED_LOCALES; TestMLHydration / Vitest create+GET; live SPA UAT still human ✓ code; ⏳ SPA UAT

Goal Achievement

Observable Truths

# Truth Status Evidence
1 Plugin repo exists with golem15_translate_* schema (locales, attributes, indexes, empty messages table), Locale model, en/pl seed, and context-safe Translator ✓ VERIFIED Module git.golem15.com/golem15/sm-translate-plugin HEAD b3e0e26, ID golem15.translate. Five gormigrate files create golem15_translate_locales|attributes|indexes|messages. Locale.TableName() is golem15_translate_locales. --php / --layout / --forbidden PASS this pass. Translator.Locale reads towel.Locale(ctx) only.
2 Translatable API (Translatable(), WithLocale, get/set, default-locale fallback) and permissioned Locales admin work; a fixture model saves and reads en+pl ✓ VERIFIED classes.Translatable plus Translated / SetTranslated / WithLocale. Locales permission is exactly golem15.translate.manage_locales. Translated still applies D-11; admin hydration uses TranslatedExact.
3 Cabana markdown / mltext / mlmarkdown compose ✓ VERIFIED formFieldTypes includes all three (form_schema.go:29). MLMarkdownField.vue renders MarkdownField. TestMLFieldTypes PASS this pass (go test ./modules/cabana -count=1 -run 'TestMLFieldTypes$'). Registry tests register the three types.
4 Nested locale writes are not dropped ✓ VERIFIED CR-01/WR-02 closed. Host CRUDService.save still liftMLValues then applyMLTranslations then hydrateMLRecord (crud.go:600, :688, :709). CreateChild/UpdateChild lift on in.Body before fillChild (relation_child.go:168-172, :330-334) and apply after PK (:183, :345). ShowChild hydrates (:296). TestMLNestedSave PASS; TestMLHydration PASS (create/show {en,pl}; english-only pl: ""); TestRelationChildMLNestedSave PASS (create/update/show + de 422 with no insert). SPA create seeds {[code]: ""}; mergeMLValue keeps siblings on a GET string.
5 Docs, OpenAPI, TS types and boardwalk dist/ update in the same change ✓ VERIFIED docs/backend/forms.md, docs/backend/admin-controllers.md, modules/cabana/README.md document EnabledLocales, TranslatedExact, hydrateMLRecord, and child lift. schema.d.ts has enabledLocales?: string[]. boardwalk/dist/assets/index-B08bxLq5.js contains mltext/mlmarkdown. Gate --forbidden found no consuming-application names.
6 Proof host sm-grzybyfunkcjonalne-app boots with user+translate; unit tests are the last plan ✓ VERIFIED Host HEAD 1860ad6. summer.yaml lists user then translate; gitlink plugins/golem15/translate → b3e0e26. Plan 06 is the dedicated named-test/gate close of the gap round; plan 04 remains the original last-of-phase test plan. --layout PASS this pass.
7 D-01/D-02/D-03/D-04: implementation is derived only from the read-only PHP tree at SHA 725d547ec839f02b5fdc0f0a6faaed601a414d50; no PHP file changes ✓ VERIFIED bash scripts/check-phase14.2.1.sh --php this pass: phase14.2.1 php passed (725d547…). Porcelain empty.
8 D-07/D-12: resolver selects URL prefix, valid user preferred_locale, remembered golem15.translate.locale, cookie-gated Accept-Language, then default; surf stores only a validated code on context ✓ VERIFIED Translator.Resolve order still URL → preferred → remembered → AL (unless manual flag) → default (translator.go:75-103). Surf router.go:712-714 writes towel.WithLocale from resolver.Resolve.
9 KERN-07: no package-level mutable current locale; Translator.Locale(ctx) and towel.WithLocale carry request state ✓ VERIFIED No package currentLocale. Translator.Locale reads context then defaultCode. Rewrite clones the request.
10 D-15/D-16: module is git.golem15.com/golem15/sm-translate-plugin, package translate, plugin ID golem15.translate, sibling checkout ✓ VERIFIED Plugin.ID(); remote git@git.golem15.com:golem15/sm-translate-plugin.git; path /media/nvme/dev/golem15/summercms.io/summercms/sm-translate-plugin. Host submodule plugins/golem15/translate mode 160000.
11 D-10: default-locale values remain in host columns; each non-default locale is one JSON object row in golem15_translate_attributes; indexed values are mirrored to golem15_translate_indexes ✓ VERIFIED SetTranslated still writes default via host Update; non-default upserts one attribute JSON object. hydrateMLRecord does not change that write path.
12 D-05: Locales is ordinary cabana CRUD, permission-gated by exactly golem15.translate.manage_locales; no Messages controller, permission, or navigation ✓ VERIFIED RequiredPermissions returns only PermissionManageLocales. Permissions() is only manage_locales. --forbidden PASS (no production manage_messages).
13 Locale form writes only code/name/is_enabled; is_default and sort_order cannot be mass-assigned; permissioned make-default preserves disabled/default lifecycle guards ✓ VERIFIED Fillable is code,name,is_enabled. WR-01 concurrent two-default race remains untested (advisory, not a gap).
14 The SPA exposes one locale selector per ML field, switches all ML controls together, supports copy-from-locale, and sends every locale as Record<string,string> ✓ VERIFIED CR-01 closed. MLTextField/MLMarkdownField inject FORM_ENABLED_LOCALES and list those codes (locales computed is no longer Object.keys / ['en']). FormView provides schemaEnabledLocales(schema.meta); RelationChildModal re-provides the parent inject. Create initialValues(fields, enabledLocales) seeds {[code]: ""}. adopt uses mergeMLValue. editablePayload sends localeRecord. Vitest this pass: npx vitest run tests/form/MLFields.test.ts tests/form/formState.test.ts — 42 passed, including create seed listing en+pl, GET-string merge keeping pl, one selector per field, broadcast switch, copy-from, empty-pl payload. Live SPA UAT is still human (below).
15 Markdown preview uses goldmark without unsafe HTML and cannot execute translated raw HTML/script/event-handler/javascript content ✓ VERIFIED RenderMarkdown uses goldmark.New(); no html.WithUnsafe. SPA preview is text interpolation, no v-html=.
16 Nested locale maps are lifted before ProjectWritableFields drops maps; default locale fills the host field and non-default locales reach the translate writer inside the host save transaction ✓ VERIFIED Host path unchanged (crud.go:600 then :688 inside s.transaction). Child path now mirrors it on tx (relation_child.go). TestMLNestedSave and TestRelationChildMLNestedSave both assert unlifted maps empty at projection, English on host, pl via writer, de rejected.

Score: 16/16 truths verified (0 present, behavior-unverified)

Advisory (New Scope, Unevidenced)

None. WR-01 (makeDefault race), WR-03 (enabled backend prefix), and IN-02/IN-03/IN-04 were out of the gap-closure contract, were not in the prior gaps: list, and were not re-opened. Evidence gate: not blocking.

Required Artifacts

gsd-tools verify.artifacts still does not emit per-file JSON for sibling ../sm-translate-plugin/... paths. Manual three-level check:

Artifact Expected Status Details
../sm-translate-plugin/plugin.go Compiled plugin, Resolver + TranslationWriter publish ✓ EXISTS + SUBSTANTIVE + WIRED Boot publishes surf.LocaleResolver and cabana.TranslationWriter.
../sm-translate-plugin/updates/202610060001_create_golem15_translate_locales.go Squashed Locale schema ✓ EXISTS + SUBSTANTIVE golem15_translate_locales.
../sm-translate-plugin/updates/202610060004_create_golem15_translate_messages.go Empty compatibility Messages table ✓ EXISTS + SUBSTANTIVE Created; no admin.
../sm-translate-plugin/classes/translator.go Context-only Translator ✓ EXISTS + SUBSTANTIVE + WIRED Published from Boot; surf stores result on context.
../sm-translate-plugin/classes/translatable.go Translatable contracts ✓ EXISTS + SUBSTANTIVE + WIRED Translated (D-11) and TranslatedExact (no fallback).
../sm-translate-plugin/classes/admin_writer.go Plugin adapter including TranslatedExact ✓ EXISTS + SUBSTANTIVE + WIRED AdminWriter.TranslatedExact delegates to classes.TranslatedExact; var _ cabana.TranslationWriter.
../sm-translate-plugin/controllers/locales.go Permissioned Locales admin ✓ EXISTS + SUBSTANTIVE + WIRED RequiredPermissions; registered via admin.go.
modules/surf/locale_resolver.go Optional resolver contract ✓ EXISTS + SUBSTANTIVE + WIRED Used in router.go.
modules/cabana/schema_types.go FormMeta.EnabledLocales ✓ EXISTS + SUBSTANTIVE + WIRED json:"enabledLocales,omitempty".
modules/cabana/field_ml.go Lift + hydrate + TranslationWriter ✓ EXISTS + SUBSTANTIVE + WIRED hydrateMLRecord writes "" when TranslatedExact ok is false. Wired from CRUD Show/save and relation-child create/update/show. Not used from list projection.
modules/cabana/relation.go RelationService.writer ✓ EXISTS + SUBSTANTIVE + WIRED Same unexported Lookup as CRUDService.
modules/cabana/relation_child.go lift before fillChild, apply after PK, hydrate ✓ EXISTS + SUBSTANTIVE + WIRED WR-02 closed.
modules/cabana/relation_child_ml_test.go Named child nested-ML proof ✓ EXISTS + SUBSTANTIVE TestRelationChildMLNestedSave PASS this pass.
admin/src/components/form/formContext.ts FORM_ENABLED_LOCALES ✓ EXISTS + SUBSTANTIVE + WIRED Injected by FormView; re-provided by RelationChildModal.
admin/src/components/form/fields/MLMarkdownField.vue Locale-aware markdown editor ✓ EXISTS + SUBSTANTIVE + WIRED Options from schema inject, not value keys.
admin/src/components/form/fields/MLTextField.vue Locale-aware text editor ✓ EXISTS + SUBSTANTIVE + WIRED Same.
admin/src/views/FormView.vue adopt merges hydrated maps ✓ EXISTS + SUBSTANTIVE + WIRED mergeMLValue; create seeds via initialValues.
docs/backend/forms.md Field-type docs ✓ EXISTS + SUBSTANTIVE Documents EnabledLocales, exact hydration, child lift.
../sm-grzybyfunkcjonalne-app/summer.yaml user+translate plugin list ✓ EXISTS + SUBSTANTIVE + WIRED Generates plugins.gen.go.
scripts/check-phase14.2.1.sh Fail-closed phase gate ✓ EXISTS + SUBSTANTIVE FRAMEWORK_REQUIRE includes TestMLHydration and TestRelationChildMLNestedSave. Echoes Phase 14.2.1 gate passed. Cheap stages PASS this pass.
.planning/phases/14.2.1-translate-plugin/14.2.1-SECURITY-REVIEW.md ASVS L1 threat evidence ✓ EXISTS + SUBSTANTIVE T-14.2.1-19/22/23 mapped to named tests.

Artifacts: fully verified at exists + substantive + wired. Prior hollow SPA locale options are gone.

From To Via Status Details
plugin.go Boot modules/surf/locale_resolver.go Publish[surf.LocaleResolver] ✓ WIRED Translator implements the interface.
modules/surf/router.go modules/towel towel.WithLocale(resolver.Resolve(...)) ✓ WIRED Lines 712-714.
translator.go models/locale.go is_enabled query in enabledCodes ✓ WIRED Candidates must match enabled rows.
translatable.go golem15_translate_attributes SetTranslated upsert JSON ✓ WIRED attribute_data.
translatable.go golem15_translate_indexes indexed upsert ✓ WIRED TranslatableIndexes.
controllers/locales.go models/locale.go cabana CRUD + hooks ✓ WIRED RequiredPermissions.
modules/cabana/http.go modules/cabana/schema_types.go enabledContentLocales → FormMeta.EnabledLocales ✓ WIRED formSchema copies codes onto view.Meta and envelope; relationSchema envelope meta; list schemas do not call the helper.
modules/cabana/crud.go modules/cabana/field_ml.go liftMLValues / hydrateMLRecord ✓ WIRED ShowRecord and save.
modules/cabana/http.go modules/cabana/relation.go relations() Lookup[TranslationWriter] ✓ WIRED Matches crud().
modules/cabana/relation_child.go modules/cabana/field_ml.go liftMLValues then applyMLTranslations then hydrateMLRecord ✓ WIRED WR-02.
classes/admin_writer.go classes/translatable.go TranslatedExact / SetTranslated ✓ WIRED Exact path never calls Translated (D-11).
admin/src/views/FormView.vue ML field components FORM_ENABLED_LOCALES ✓ WIRED Inject drives selector options.
FormView.adopt / RelationChildModal.adopt nested ML maps mergeMLValue ✓ WIRED Map overlays seed; host string becomes first enabled code and keeps siblings.
summer.yaml plugins.gen.go summer build blank imports ✓ WIRED Both submodule modules.

Wiring: 14/14 connections verified (prior 5 NOT WIRED links are now WIRED).

Data-Flow Trace (Level 4)

Artifact Data Variable Source Produces Real Data Status
Locales list/form locale rows GORM golem15_translate_locales via cabana CRUD Yes ✓ FLOWING
Translator.Resolve request locale enabled Locale rows + URL/cookie/AL Yes, validated codes ✓ FLOWING
Translated / SetTranslated field text host column or attribute_data JSON Yes ✓ FLOWING
Cabana ML save (HTTP) nested locale map request body → lift → host scalar + writer Yes ✓ FLOWING
Cabana GET/Show ML field data[field] hydrateMLRecord after projectFullRecord: default from host column, others from TranslatedExact Locale map; missing pl is "" ✓ FLOWING
Relation-child create/update/show child ML field same lift/apply/hydrate on tx Yes (TestRelationChildMLNestedSave) ✓ FLOWING
Form schema meta enabledLocales TranslationWriter.EnabledLocales Enabled codes when writer published ✓ FLOWING
SPA ML locale <select> locales FORM_ENABLED_LOCALES from schema meta Schema codes, not value keys ✓ FLOWING
SPA create ML value initialValues {[code]: ""} for every enabled locale Seeded from schema ✓ FLOWING
Markdown preview preview pane interpolated source text Real source; not RenderMarkdown HTML ✓ FLOWING (text)

Behavioral Spot-Checks

Behavior Command Result Status
PHP pin SHA + clean tree bash scripts/check-phase14.2.1.sh --php phase14.2.1 php passed (725d547…) ✓ PASS
Host/plugin layout --layout phase14.2.1 layout passed ✓ PASS
Forbidden Winter names / AutoMigrate / v-html / app names --forbidden phase14.2.1 forbidden passed ✓ PASS
Gate detector fail-closed --self-test phase14.2.1 self-test passed ✓ PASS
Security review IDs --security phase14.2.1 security passed ✓ PASS
Cabana ML types go test ./modules/cabana -count=1 -run 'TestMLFieldTypes$' PASS 0.086s ✓ PASS
Nested host save go test ./modules/cabana -count=1 -run 'TestMLNestedSave$' PASS 4.371s ✓ PASS
Hydration without D-11 go test ./modules/cabana -count=1 -run 'TestMLHydration$' PASS 4.586s; english-only pl: "" ✓ PASS
Relation-child nested ML go test ./modules/cabana -count=1 -run 'TestRelationChildMLNestedSave$' PASS 4.301s ✓ PASS
SPA ML create/GET/selector npx vitest run tests/form/MLFields.test.ts tests/form/formState.test.ts 2 files, 42 tests passed ✓ PASS
Full gate --all not re-run (cabana -race ~30m) Script still ends with Phase 14.2.1 gate passed; FRAMEWORK_REQUIRE includes the two named tests that passed this pass. Plan 06 SUMMARY claimed --all printed that line. ? SKIP

Probe Execution

No scripts/*/tests/probe-*.sh. The phase gate is scripts/check-phase14.2.1.sh. Cheap stages PASS this pass (table above). --plugin / --framework / --admin / --host / --all were not re-executed here; named tests that the gate requires for CR-01/WR-02 passed in this process.

Requirements Coverage

No REQUIREMENTS.md IDs map to this phase (Requirements: TBD in ROADMAP; grep of REQUIREMENTS.md for Phase 14.2.1 is empty). CONTEXT D-01..D-17 are the contract. Plans 01–04 declare D-01..D-17; plans 05–06 cite D-06 and D-17 for gap closure. Every ID is accounted for.

Requirement Source Plan Description Status Evidence
D-01 01, 04 PHP pin 725d547 ✓ SATISFIED --php PASS
D-02 01, 04 Freeze at that SHA ✓ SATISFIED Gate compares HEAD to the pin
D-03 01, 04 Read frozen tree at fonoteka path ✓ SATISFIED Path exists, SHA matches
D-04 01, 04 Do not edit PHP ✓ SATISFIED Clean porcelain
D-05 02, 04 Lean Locale + Locales admin only ✓ SATISFIED No Messages controller/permission/nav
D-06 03, 04, 05, 06 mltext/mlmarkdown; Journal form stays one screen with a locale switch ✓ SATISFIED (code) Field types compile; schema EnabledLocales; SPA inject; child lift. Live SPA UAT remains human.
D-07 01, 04 URL / session / cookie / default, not header-only ✓ SATISFIED Translator.Resolve order
D-08 01, 02, 04 Seed en+pl, not de ✓ SATISFIED Seed SQL
D-09 02, 03, 04 Translatable() []string ✓ SATISFIED Interface + fixture models
D-10 01, 02, 04 Go tables golem15_translate_* ✓ SATISFIED Production DDL; --forbidden refuses Winter names
D-11 02, 04 Missing translation falls back to default ✓ SATISFIED Translated still falls back. Admin GET uses TranslatedExact and does not apply D-11 (hydrateMLRecord writes "" when ok is false; TestMLHydration english-only pl: "").
D-12 01, 02, 03, 04 Min API: WithLocale, get/set, Translator current locale ✓ SATISFIED Exported funcs + context Locale
D-13 03, 04 Host is sm-grzybyfunkcjonalne-app with user+translate ✓ SATISFIED plugins.gen.go
D-14 03, 04 Local host checkout path ✓ SATISFIED Sibling directory exists
D-15 01, 03, 04 Public Gitea remote + module path ✓ SATISFIED git remote -v
D-16 01, 03, 04 Sibling plugin checkout; host submodule + go.work replace ✓ SATISFIED gitlink 160000 b3e0e26
D-17 02, 03, 04, 05, 06 App boots; Locales admin works; fixture saves/reads en+pl through ML fields and WithLocale ✓ SATISFIED (code) Boot + API fixture + permissioned Locales HTTP + hydrated admin maps + relation-child nested save. SPA one-screen UAT is human.

Coverage: 17/17 requirements satisfied in code (D-06/D-17 SPA chrome still needs human).

Decision Coverage

gsd-tools check.decision-coverage-verify: { honoured: 17, total: 17, not_honored: [] } — “All trackable CONTEXT.md decisions are honored by shipped artifacts.” Non-blocking substring gate. D-06 is now honored as a working one-screen switch in source (selectors read schema locales), not merely as artifact presence.

Test Quality Audit

Test File Linked Req Active Skipped Circular Assertion Level Verdict
updates/migrations_test.go D-08/D-10 yes skip only without Docker no value OK
classes/translator_resolve_test.go D-07 yes no no behavioral OK
classes/translatable_test.go D-09/D-11/D-12 yes no no value OK
locales_admin_test.go D-05 yes no no behavioral OK
integration_test.go D-17 API yes no no behavioral HTTP OK
modules/cabana/ml_test.go D-06 types / nested lift / hydration yes no no behavioral OK — TestMLHydration proves missing pl is empty
modules/cabana/relation_child_ml_test.go D-06/D-17 child yes no no behavioral OK
admin/tests/form/MLFields.test.ts D-06 SPA yes no no behavioral on create seed, GET string, and maps OK (prior INSUFFICIENT closed)
admin/tests/form/formState.test.ts D-06 seed/adopt yes no no value OK

Disabled tests on requirements: 0. Circular patterns detected: 0. Insufficient assertions: 0 (create {} / GET string coverage now present).

Anti-Patterns Found

File Line Pattern Severity Impact
(none in gap-closure files) — TBD/FIXME/XXX — Debt-marker scan clean
../sm-translate-plugin/controllers/locales.go makeDefault Two unordered Updates 📋 Advisory WR-01; out of this closure; sequential guards hold
../sm-translate-plugin/models/locale.go code index Not UNIQUE 📋 Advisory WR-03; out of this closure

Anti-patterns: prior CR-01/WR-02 blockers are gone. Remaining notes are advisory, not blockers (evidence gate).

Debt-marker scan on phase-touched production files this pass: no TBD/FIXME/XXX.

Human Verification Required

Automated CR-01/WR-02 gaps are closed. SPA UAT is not invented as a pass.

1. Locales admin in the proof-host SPA

Test: Boot sm-grzybyfunkcjonalne-app; sign in as an administrator holding golem15.translate.manage_locales; open Locales; confirm English then Polski; edit name/enabled; confirm a user without the permission cannot open the controller. Expected: List order en then pl; permitted fields save; forbidden user is 403/hidden. Why human: Needs running host + admin login. Harvested from 14.2.1-04-PLAN.md and 14.2.1-06-PLAN.md.

2. Journal-shaped mltext form (when available)

Test: With the executor-started proof host and admin SPA, when a Journal-shaped form with mltext is available, confirm one locale selector per ML field listing en and pl on create (not a single English box), that switching one selector switches the others, and that save/reload still shows both locales. Expected: Create lists en and pl; selectors switch together; save/reload keeps both locales. Why human: Harvested from 14.2.1-06-PLAN.md. Vitest mounts with injected ['en','pl']; it does not boot the SPA against live schema meta. The proof host has no production mltext YAML (only admin_harness_test.go fixture fields). Do not invent a pass. Relation-child ML UAT can wait for Phase 15 if this host has no child ML form.

Gaps Summary

No blocking gaps. Prior CR-01 (admin ML locale switch) and WR-02 (relation-child nested ML maps) are closed in source with named tests that passed this pass.

Human verification items remain; overall status is human_needed, not passed.

Verification Metadata

Verification approach: Goal-backward re-verification (prior must-haves reused; failed items full 3-level; passed items existence + sanity). SUMMARY.md used only as a file-list hint. Must-haves source: Prior VERIFICATION.md (ROADMAP Phase 14.2.1 Success Criteria + 14.2.1-01..04 PLAN frontmatter; 05/06 restated the two failed truths) Automated checks: cheap gate stages 5 passed / 0 failed; TestMLFieldTypes PASS; TestMLNestedSave PASS; TestMLHydration PASS; TestRelationChildMLNestedSave PASS; Vitest 42/42 PASS Human checks required: 2 (Locales SPA; Journal-shaped mltext when available — relation-child UAT waits for Phase 15) Total verification time: ~25 min CR-01 / WR-02: independently re-read in source; REVIEW.md (status: clean) not rubber-stamped winter_translate_ in Go production DDL:* absent Phase gate phrase: scripts/check-phase14.2.1.sh still prints Phase 14.2.1 gate passed; --all not re-run this pass


Verified: 2026-10-06T14:40:00Z Verifier: the agent (gsd-verifier)