Skip to content

Commit 2b0c177

Browse files
akoclaude
andcommitted
docs(fix-issue): drop the duplicate symptom row left by the union merge
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DufwPkjFimB8BoTm7bWbik
1 parent bc131d4 commit 2b0c177

1 file changed

Lines changed: 0 additions & 1 deletion

File tree

.claude/skills/fix-issue.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,5 +761,4 @@ extracting `OffsetExpression`/`LimitExpression`.
761761
| Every open PR goes red at once on `build-and-test` with a failure in a package none of them touched — `--- FAIL: TestSessionLog_PersistAndPrune`, "after reload+prune: 0 records, want 1" — and the same test fails on a clean checkout of `main` | A **time bomb in the test**, not a regression: the fixture pinned `base := time.Date(2026, 8, 1, ...)` against a 30-day retention window, and `NewSessionLogFile` prunes inside `load()` — *before* the test can assign `log2.now`, so the reload prune runs on the real `time.Now()` whatever clock is injected afterwards. It passed for 30 days and then failed permanently, on every branch simultaneously | `cmd/mxcli/tunnelhub/sessions_test.go` (`TestSessionLog_PersistAndPrune`), `cmd/mxcli/tunnelhub/sessions.go` (`load` → `pruneLocked` → `clock`) | **First establish it is not yours**: run the failing test on a clean `origin/main`. Several PRs failing on one unrelated test is the signature. Then make the fixture relative — `base := time.Now().UTC()` — so the record ages, not the calendar, decide the outcome; the other tests in the file keep their fixed base legitimately, because they use `NewSessionLog` and inject the clock before recording. **A date fixture is only safe where no code path reads the real clock**; the moment a constructor prunes, expires or compares against `time.Now()` before the seam is in place, an absolute date has a fuse on it. Control the repair: stub `pruneLocked` to a no-op and confirm the test still fails (2 records, want 1), or the fix is just a test that stopped testing |
762762
| Every page menu item in an **mxcli-authored navigation profile** loses the page's own title, and `mx check` reports one **CW0263 "Empty template"** warning per item while errors stay at 0 (16 of them on a real 11.12.3 app) | `Forms$FormSettings.TitleOverride` written as an **empty** `Microflows$TextTemplate` instead of `null` — the #812 defect above, in the three writers #812 did not touch. An empty template is an override to `""`, not the absence of one. Unlike the ShowPage/button paths there is nothing to preserve: `types.NavMenuItemSpec` has no title field, so MDL cannot author a navigation title override and the value is unconditionally null | `sdk/mpr/writer_navigation.go` (`buildFormSettingsBson`), `mdl/backend/modelsdk/navigation_write.go` (`navFormSettingsBson`), `modelsdk/mpr/nav_patch.go` (`navpBuildFormSettingsBson`) | Emit `{Key: "TitleOverride", Value: nil}` in all three. **Grep the builder's callers before concluding a navigation fix is menu-only** — each of the three is also the profile's **login page** builder (`writer_navigation.go:116`, `navigation_write.go:127`, `nav_patch.go:122`, plus `navigation_profile_add.go:108`), so one edit per engine covers both `Forms$FormAction` and `LoginPageSettings`, and a fix aimed only at menu items would have missed half the emitters. Verify against a **Studio Pro document already in the project**, not against the warning count: a blank app's own navigation unit stores `TitleOverride = null` on both the login settings and the home menu item. Read it with `f=$(grep -ral NavigationDocument app/mprcontents \| head -1)` — `grep -a` is required, a `.mxunit` is raw BSON and plain `grep -rl` skips it as binary — then `strings -a "$f" \| grep -c TextTemplate`: **4 before (3 page items + login page), 0 after**, with `grep -c TitleOverride` staying at 4 so the key is still written. Measured on 11.12.0 on both engines. These three paths are raw `bson.D` → `bson.Marshal` → `UpdateRawUnit`, so #812's second trap (a `codec.RegisterTypeDefaults` `NullFields` entry clobbered by another registration for the same `$Type`) cannot apply — which also means a shape assertion on the builder is the only unit-level guard there is. Repro `mdl-examples/bug-tests/989-navigation-title-override.mdl`. PR #989 |
763763
| `DESCRIBE NAVIGATION` prints `home page` and the menu but **silently omits `login page` and `not found page`**, so pasting its output back (the documented copy workflow) deletes both from the profile. The clauses are on disk and `MXCLI_ENGINE=legacy` prints them | The **reader**, not the writer: `mdl/backend/modelsdk/navigation_read.go` type-asserted only the `$Type`s `modelsdk/gen` declares for those two slots, and neither is what the documents carry — `LoginPageSettings` is stored as `Forms$FormSettings` with the page under `Form` (gen expects `Navigation$NavigationProfileLoginFormSettings` / `LoginPage`), and `NotFoundHomepage` as `Navigation$HomePage` (gen and `generated/metamodel` both expect `Navigation$NotFoundHomePage`). A failed type assertion leaves the field empty, so the loss is silent | `mdl/backend/modelsdk/navigation_read.go` (`navLoginPageOf`, `navNotFoundPageOf`), cross-check `generated/metamodel/types.go` `NavigationNavigationProfile` | **The other engine is the control.** Legacy read the same bytes correctly throughout, which is what identifies a reader bug: `describe navigation X` on both engines must agree, and a disagreement localises the defect to the one that reads through gen. Accept the `$Type` the documents actually carry and keep gen's as a fallback branch. Note the two slots fail in **opposite directions** and want opposite fixes: for the login page a real Studio Pro document and `generated/metamodel` agree with the writers, so **gen** is wrong; for the not-found page — Studio Pro's **"Fallback page"** — metamodel and gen agree with each other and the three mxcli **writers** are the odd one out, emitting `Navigation$HomePage` where Studio Pro stores `Navigation$NotFoundHomePage`. Only a reference document could tell those apart, since mxbuild accepts either; ako/TestApp supplied it. Keep reading both `$Type`s regardless: documents written before the writer fix carry the `HomePage` spelling and must keep round-tripping. Repro `mdl-examples/bug-tests/navigation-describe-profile-pages.mdl` |
764-
| A document mxcli writes carries a different **typed-array marker** (the leading `int32` of a Mendix array) than the equivalent Studio Pro document — e.g. every list in a `CREATE OR REPLACE NAVIGATION` profile was `1` where Studio Pro writes `2` or `3`. No error, no warning, no build failure: it renders and opens | The writers hand-build `bson.A{int32(1)}` per list. The marker is a **per-field constant**, not a function of the list's contents (`Forms$FormSettings.ParameterMappings` is `2` in 816 empty and 306 non-empty documents alike), so it cannot be derived — it has to be read off real documents | `sdk/mpr/writer_navigation.go` + `mdl/backend/modelsdk/navigation_write.go` + `modelsdk/mpr/nav_patch.go` (`navMarker*` / `navpMarker*` constants), `mdl/backend/modelsdk/navigation_profile_add.go`, `modelsdk/codec/defaults.go` (`RegisterListMarker`) for the codec paths | **Census, don't reason.** Walk every `.mxunit` on the machine, tabulate `(parent $Type, field, marker, empty?)`, and take the value the Studio Pro documents carry — 19,078 files across 54 projects settled five of six navigation fields outright. **`int32(1)` is NOT invalid**, whatever `debug-bson.md` used to say: a Marketplace `.mpk` mxcli has never touched uses it for `CustomWidgets$WidgetValueType.AllowedTypes` (212k occurrences) and `Forms$Page.AllowedModuleRoles`. Believing otherwise turns a per-field mismatch into a phantom corruption bug and sends the fix in the wrong direction. Where the census has no observation, say so rather than picking: `HomeItems` is `2` in all 51 stored profiles but every one is empty, and `navigation_profile_add.go` writes `3` from a PED session that cannot be re-run — the constants record the disagreement instead of hiding it. Verify by dumping the written document and the project's own pristine reference and diffing the marker column, not by `mx check`, which is silent on all of it |
765764
| A document mxcli writes carries a different **typed-array marker** (the leading `int32` of a Mendix array) than the equivalent Studio Pro document — e.g. every list in a `CREATE OR REPLACE NAVIGATION` profile was `1` where Studio Pro writes `2` or `3`. No error, no warning, no build failure: it renders and opens | The writers hand-build `bson.A{int32(1)}` per list. The marker is a **per-field constant**, not a function of the list's contents (`Forms$FormSettings.ParameterMappings` is `2` in 816 empty and 306 non-empty documents alike), so it cannot be derived — it has to be read off real documents | `sdk/mpr/writer_navigation.go` + `mdl/backend/modelsdk/navigation_write.go` + `modelsdk/mpr/nav_patch.go` (`navMarker*` / `navpMarker*` constants), `mdl/backend/modelsdk/navigation_profile_add.go`, `modelsdk/codec/defaults.go` (`RegisterListMarker`) for the codec paths | **Census, don't reason.** Walk every `.mxunit` on the machine, tabulate `(parent $Type, field, marker, empty?)`, and take the value the Studio Pro documents carry — 19,078 files across 54 projects settled five of six navigation fields outright. **`int32(1)` is NOT invalid**, whatever `debug-bson.md` used to say: a Marketplace `.mpk` mxcli has never touched uses it for `CustomWidgets$WidgetValueType.AllowedTypes` (212k occurrences) and `Forms$Page.AllowedModuleRoles`. Believing otherwise turns a per-field mismatch into a phantom corruption bug and sends the fix in the wrong direction. Where the census has no observation, **find a document that has one** rather than picking: `HomeItems` was `2` in all 51 stored profiles but every one was empty, and `navigation_profile_add.go` wrote `3` from a PED session that could not be re-run. ako/TestApp settled it — a Studio Pro-authored profile whose `HomeItems` holds two `Navigation$RoleBasedHomePage` elements at marker **2**, the non-empty case the census could not reach. One project with the feature actually configured beats any amount of reasoning about empty lists. Verify by dumping the written document and the project's own pristine reference and diffing the marker column, not by `mx check`, which is silent on all of it |

0 commit comments

Comments
 (0)