Skip to content

Six near-zero fixes, and the rule that found a third one nobody had opened the menu to see - #202

Merged
dmitrat merged 1 commit into
mainfrom
studio-ui-near-zero-six
Aug 15, 2026
Merged

Six near-zero fixes, and the rule that found a third one nobody had opened the menu to see#202
dmitrat merged 1 commit into
mainfrom
studio-ui-near-zero-six

Conversation

@dmitrat

@dmitrat dmitrat commented Aug 15, 2026

Copy link
Copy Markdown
Owner

A1, A2, A4, B1, B2 and D3 of Docs/STUDIO-UI-FIX-PLAN-2026-08-15.md, in one pass. Every guard was run red against the unfixed code part by part — twelve sabotage arms in three runs — and no part had an empty red set.

A1 — the printed gesture is the one that runs

Written up as two menu labels. The real work is the rule over every printed gesture, and the rule named three:

printed the command's real gesture what the printed key does
File ▸ New Query Tab Ctrl+N Ctrl+T opens New Database
View ▸ Refresh F5 Ctrl+R runs the statement under the cursor
Query ▸ Execute F5 Ctrl+Shift+F5 runs the statement under the cursor, not the script

The third was in no report — nobody had opened the Query menu looking for it. New Database now prints the Ctrl+N it has always owned.

InputGesture on an Avalonia MenuItem is a label and binds nothing, so none of this changes what any key does — and that is also why no existing rule could see it: the printed text is in neither KeyboardMap nor the declared KeyBindings, which is all the two existing rules compare. The new rule is the third direction. It resolves each item's Command to its own name so the tab strip's $parent[UserControl]… path and the File menu's WorkspaceTabsVm.… compare equal, normalises Enter against Return, carries four exemptions that are each a named decision keyed by item and gesture, and asserts the surface — 16 printed, 12 checked — so "nothing left to find" cannot read like "the folder moved".

Consequence written down rather than hidden: the Query menu no longer mentions F5, which WS-25 made the primary run key. Adding an Execute statement item is a menu-content question and stays open.

A2 — English plurals at one

Explorer.Summary had its nouns inside the format string with raw numbers passed in, so the status bar printed 1 views, 1 triggers while the Database tab — same counts, same second — printed 1 table correctly through Localization.Plural. Four families existed; Count.Sequences is added to both catalogues.

The fixture that could not see this is any fixture with none or several of something. StudioFixture has exactly one view and one trigger, and nothing had ever asserted its status line.

A4 — the page cache line opened with a bare separator

· 0 pages · holding 170 pages, 0 dirty on demo.witdb. Driven against a file written today the same line reads clock · 1000 pages · holding 2 pages, 0 dirty, so the engine answers the question and the older file simply does not carry the value. The field is dropped with its separator rather than filled with a name invented for it.

CacheLine is static and public on purpose: every file this repository can write records the kind, so a case driving a real connection can only ever see the arm that was already right.

B1 — «Editing» over five disabled buttons

NoKey had every editing control [disabled], correctly, while the status bar said Editing table: NoKey and the footer advertised Ctrl+S: Commit and Del: Delete row.

The gate is the tab's own IsReadOnly — the one CanAddRow, CanDeleteRow and CanCommit are computed from — and not the WorkspaceTabViewModel.IsReadOnly it shadows, which means the connection was opened read-only. Two concepts, one name. The markup guard is structural: all seven hints must have a gated ancestor, so leaving one of the three status states open goes red.

B2 — the storage options' baseline

Vertically centred in a UniformGrid whose row height comes from the tallest description; the outlier moves with the language (LSM in English, «В памяти» in Russian), so a screenshot review pinned to one language blames the wrong control.

The lint is deliberately narrow — two or more radio buttons side by side with at least one wrapping description, which is the shape that produces the defect. The wide rule over all 66 horizontal sibling groups is not written: it would report legend and caption rows, and an exemption written for a false positive is a hole in a rule wearing a comment's clothes.

D3 — and the plan's attribution was wrong

Recorded as a label built from a raw theme name. It is not: the caption has come from the catalogue since #139 (2026-08-07). What fails is the moment — it is written at startup and on a theme change, and nothing re-read it when the catalogue was swapped, so a language change left «Dark» on a Russian window. Same family as C1.

The sixth localisation rule is about when rather than what: a caption a view writes from the catalogue must either be written by a static factory that constructs the window it fills (built fresh per showing) or its file must subscribe to LanguageChanged. The discriminator is mechanical, so both dialogs pass without an exemption.

Driven, not only tested

Five of the six were driven in a freshly built Studio — the installed rc.1 is the unfixed build and can only reproduce — against the calibration database, which now lives in Docs/calib/ (gitignored, survives the session) and has the Flag NULL row D1 needs:

  • Ctrl+T / Ctrl+N / Ctrl+Shift+F5 / Ctrl+R on screen in three menus;
  • calib: 6 tables, 1 view, 2 indexes, 1 trigger, 0 sequences;
  • NoKey announced as viewing with no footer hints, Marks still editing with them;
  • «Тёмная» the instant the language changed, no restart;
  • the three storage options on one baseline in Russian.

A4 was not driven — it needs a file whose header predates the field — and its guard is over the composing function instead.

One finding, not fixed here

Because the derived IsReadOnly shadows the base, a table on a read-only connection has every editing button enabled: UpdateStatus never reads the connection's mode, so the refusal arrives from the engine after the person has typed. Behaviour rather than chrome, and not one of the six; recorded in the plan beside B1.

Studio 898 cases, up from 891.

🤖 Generated with Claude Code

…pened the menu to see

A1, A2, A4, B1, B2 and D3 of STUDIO-UI-FIX-PLAN-2026-08-15, in one pass. Every guard was
run red against the unfixed code part by part - twelve arms in three runs - and no part
had an empty red set.

A1 was written as two menu labels. The real work is the rule over every printed gesture,
and the rule named THREE: New Query Tab printed Ctrl+N (which opens New Database), View >
Refresh printed F5 (which runs the statement under the cursor), and Query > Execute
printed F5 for ExecuteQueryCommand, which is on Ctrl+Shift+F5. The third was in no report
because nobody had opened the Query menu looking for it. New Database now prints the
Ctrl+N it has always owned. InputGesture on an Avalonia MenuItem is a label and binds
nothing, so none of this changes what any key does - which is also why no existing rule
could see it: the printed text is in neither KeyboardMap nor the list of KeyBindings. The
new rule is the third direction, resolves each MenuItem's Command to its own name so that
the tab strip's $parent path and the File menu's compare equal, normalises Enter against
Return, carries four exemptions that are each a named decision, and asserts the SURFACE -
16 printed gestures, 12 checked - so that "nothing left to find" cannot read like "the
folder moved".

A2 is one string. Explorer.Summary had its nouns inside the format string with raw numbers
passed in, so the status bar printed "1 views, 1 triggers" while the Database tab, over the
same counts in the same second, printed "1 table" correctly through Localization.Plural.
Four families existed; Count.Sequences is added to both catalogues. The fixture that could
not see this is every fixture with none or several of something - StudioFixture has exactly
one view and one trigger, and nothing had ever asserted its status line.

A4: the page cache line opened with a bare separator on a database whose header predates
the cache kind. Driven against a file written today the same line reads "clock . 1000 pages
. holding 2 pages, 0 dirty", so the engine answers it and the older file simply does not
carry it. The field is dropped with its separator rather than filled with an invented name.
The composing function is static and public because every file this repository can write
records the kind - a case over a real connection can only see the arm that was already
right.

B1: NoKey had every editing control disabled, correctly, while the status bar said "Editing
table: NoKey" and the footer advertised Ctrl+S and Del. The gate is the tab's own
IsReadOnly - the one CanAddRow, CanDeleteRow and CanCommit are computed from - and NOT the
WorkspaceTabViewModel.IsReadOnly it shadows, which means the connection was opened
read-only. The markup guard is structural: all seven hints must have a gated ancestor, so
leaving one of the three status states open goes red.

B2: the three storage options are vertically centred in a UniformGrid whose row height
comes from the tallest description, and the outlier moves with the language - LSM in
English, "In memory" in Russian. The lint is deliberately narrow: two or more radio buttons
side by side with at least one wrapping description, which is the shape that produces the
defect. The wide rule over all 66 horizontal sibling groups is not written, because it
would report legend and caption rows and an exemption written for a false positive is a
hole in a rule wearing a comment's clothes.

D3 was recorded as an untranslated label and it is not. The caption has come from the
catalogue since 2026-08-07; what fails is the MOMENT - it is written at startup and on a
theme change, and nothing re-read it when the catalogue was swapped, so a language change
left "Dark" on a Russian window. The new rule is about when rather than what: a caption a
view writes from the catalogue must either be written by a static factory that constructs
its own window, or its file must subscribe to LanguageChanged. Both dialogs pass on the
first arm, so neither needed an exemption.

Five of the six were driven in a freshly built Studio against the recreated calibration
database, which now lives in Docs/calib rather than a scratchpad. A4 was not driven: it
needs a file whose header predates the field.

Studio 898 cases, up from 891.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dmitrat
dmitrat merged commit 89ac429 into main Aug 15, 2026
1 of 2 checks passed
@dmitrat
dmitrat deleted the studio-ui-near-zero-six branch August 15, 2026 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant