79 lines
3.8 KiB
Markdown
79 lines
3.8 KiB
Markdown
---
|
|
phase: quick-261006-seq
|
|
plan: 01
|
|
subsystem: cabana
|
|
tags: [cabana, ml, hydration, nullable, reflect]
|
|
status: complete
|
|
requires: []
|
|
provides:
|
|
- "hostScalarString dereferences pointer host columns at any depth; nil becomes empty string"
|
|
affects:
|
|
- "Any mltext/mlmarkdown field backed by a nullable pointer GORM column (Journal Categories -> Description)"
|
|
tech-stack:
|
|
added: []
|
|
patterns:
|
|
- "reflect pointer walk before stringifying projected host values"
|
|
key-files:
|
|
created:
|
|
- modules/cabana/ml_nullable_test.go
|
|
modified:
|
|
- modules/cabana/field_ml.go
|
|
decisions:
|
|
- "Fix lives in cabana hostScalarString, not plugin YAML; save path (liftMLValues -> lagoon.Fill) left unchanged and only pinned by the round-trip test"
|
|
- "String kinds return raw text via reflect.Value.String(), bypassing any String() method on named string types"
|
|
metrics:
|
|
duration: "~5 min"
|
|
completed: 2026-10-06
|
|
actuals:
|
|
tokens: 2400
|
|
tasks: 2
|
|
commits: 2
|
|
plan_head_before: 8e22e5f25b67f24759d36e6befdfd6c20433b9ea
|
|
plan_head_after: 4f7e69fd2b25bd55d7c571b31ccfaca2e8ae9ec7
|
|
---
|
|
|
|
# Quick 261006-seq Plan 01: Fix nullable pointer scalars rendering in ML hydration Summary
|
|
|
|
`hostScalarString` now walks pointers through reflect, so an mltext field on a nullable `*string` column hydrates to `""` or to its text. Before the fix it showed `"<nil>"` or a heap address such as `0x36b66873bb0`.
|
|
|
|
## Tasks
|
|
|
|
| Task | Name | Commit | Files |
|
|
| ---- | ---- | ------ | ----- |
|
|
| 1 | Round-trip regression for a *string mltext field, then dereference pointers in hostScalarString | 90b87d6 | modules/cabana/field_ml.go, modules/cabana/ml_nullable_test.go |
|
|
| 2 | Unit tests for hostScalarString and DB-free hydrateMLRecord over pointer scalars | 4f7e69f | modules/cabana/ml_nullable_test.go |
|
|
|
|
## What changed
|
|
|
|
- `modules/cabana/field_ml.go`: `hostScalarString` returns `""` for a nil interface. It then dereferences pointers at any depth and returns `""` for a nil pointer at any depth. String kinds return their raw text, including named string types and bypassing their `String()` methods. Byte slices are decoded as text. Every other kind goes through `fmt.Sprint` of the dereferenced value, never of the pointer. A doc comment was added and `reflect` is now imported.
|
|
- `modules/cabana/ml_nullable_test.go`:
|
|
- `TestMLNullablePointerHost` is a Postgres round trip with `mlNullablePost.Description *string`. It covers a nil host, a cleared value (stored as a pointer to `""`) and a filled value (the host text is stored and Polish goes through `TranslationWriter`).
|
|
- `TestHostScalarString` has 19 table rows.
|
|
- `TestMLHydrationPointerHost` calls `hydrateMLRecord` directly with a nil tx.
|
|
|
|
## TDD evidence
|
|
|
|
RED: before the fix, `TestMLNullablePointerHost` failed with `show description.en = "<nil>"` and `save description.en = "0x36b66873bb0"`. GREEN: it passes after the fix, and `TestMLHydration`, `TestMLNestedSave` and `TestML` still pass.
|
|
|
|
## Verification
|
|
|
|
- `go vet ./...` is clean at both commits.
|
|
- `go test ./... -count=1` is green at both commits, including the testcontainers cabana tests.
|
|
- `gofmt -l modules/cabana` prints nothing.
|
|
- The two commits touch only `modules/cabana/field_ml.go` and `modules/cabana/ml_nullable_test.go`. They change no README, docs or .planning files and carry no co-author trailers.
|
|
|
|
## Deviations from Plan
|
|
|
|
None. The plan was executed as written. One small addition: the file-local `nullableSlug` type has a `String()` method that returns `"decorated"`. The named-string rows therefore show that the raw stored text is returned, not the Stringer output.
|
|
|
|
## Threat Flags
|
|
|
|
None. T-quick-261006-seq-01 is mitigated: tests assert that no hydrated value starts with `0x` or contains `<nil>`.
|
|
|
|
## Self-Check: PASSED
|
|
|
|
- FOUND: modules/cabana/field_ml.go
|
|
- FOUND: modules/cabana/ml_nullable_test.go
|
|
- FOUND: 90b87d6
|
|
- FOUND: 4f7e69f
|