Skip to content

One field catalogue instead of three lists that had already drifted apart - #1

Merged
Hawkynt merged 1 commit into
mainfrom
field-registry
Aug 17, 2026
Merged

One field catalogue instead of three lists that had already drifted apart#1
Hawkynt merged 1 commit into
mainfrom
field-registry

Conversation

@Hawkynt

@Hawkynt Hawkynt commented Aug 17, 2026

Copy link
Copy Markdown
Owner

What

Adding a column meant editing three separate lists: a sort-key enum in Core, a ColumnSet in the window, and a third in the terminal. Three places to add a field is three places to forget one — and the terminal had already been forgotten, still carrying its original thirteen columns while the window had grown to thirty-eight.

FieldRegistry replaces all three. One declaration per field, carrying:

  • the stable key (--sort, saved layouts and search terms all resolve through it)
  • both headers, full and short, plus a description
  • kind and unit, so a formatter and a filter can be chosen from the declaration
  • which platforms can fill it, what reading it costs, widths, alignment, sort direction

FieldAccessor reads a field three ways from that one declaration — as text, as a number, as an ordering.

Why it matters

Both front-ends render through the accessor and ProcessView sorts through it, so:

  • Sorting by a column cannot disagree with what the column shows. They are the same code path now.
  • A value reads identically in the window and the terminal, because it is literally the same code producing it.
  • Every field key became a --sort key for free. --sort=private.ws and --sort=faults.delta both work; neither was ever written down as a sort key.

The golden terminal frame is unchanged byte for byte — that is the evidence the rewrite preserved rendering, rather than the claim that it did.

PRD §103

§103 requires that no field be introduced inside a front-end, and honestly recorded that nothing enforced it. EveryFieldInTheEnumIsRegistered now fails the build when an enum value has no descriptor, so steps 1–8 (collector side) cannot be skipped. Steps 9–13 — GUI, TUI, CLI, export schema, tests — remain on the author; §103 is updated to say exactly that rather than claiming more.

Tests

14 new, 157 total. Beyond the registration check: keys and headers are unique, no alias collides with another field's key, every key/alias/header round-trips through TryParse, graphs are unsortable and everything else is sortable, every short header fits its terminal width (the "PU %" clipping bug, now unrepeatable), no field throws when read, a derived field with no second sample reads as pending rather than zero, an unknown counter has no number at all — so > 0 and == 0 both correctly fail to match it — and unknown sorts below a real zero.

Verification

  • 157 tests, both UTF-8 and C locales
  • --self-test 25/25
  • Benchmarks: budgets met
  • Golden frame byte-identical

Notes

C# 14 made field a contextual keyword inside property accessors; a foreach (var field in ...) in one binds the backing field instead of the loop variable.

… apart

Adding a column meant editing a sort-key enum in Core, a ColumnSet in the window and a third list in
the terminal. Three places to add a field is three places to forget one, and the terminal was already
a field behind: it had never grown the sixteen columns the window gained.

FieldRegistry is now the single declaration. Each field states its stable key, both headers, a
description, its kind and unit, which platforms can fill it, what reading it costs, its width in
pixels and in cells, its alignment and its sort direction. FieldAccessor reads it three ways from
that one declaration — as text, as a number, and as an ordering — and everything else consumes those:
the window renders through it, the terminal renders through it, and ProcessView sorts through it.

Which means sorting by a column can no longer disagree with what that column displays, and a value
reads identically in both front-ends because it is literally the same code producing it. The golden
terminal frame is unchanged byte for byte, which is the evidence that the rewrite kept the rendering
intact rather than the claim that it did.

Every field key became a --sort key for free: --sort=private.ws and --sort=faults.delta both work,
and neither was ever written down as one.

The 39th field cannot now be added and silently forgotten: EveryFieldInTheEnumIsRegistered fails the
build when an enum value has no descriptor. PRD §103 asked for that check and said, honestly, that
nothing enforced it. Half of it is enforced now — the collector-side steps. The GUI/TUI/CLI/export
steps are still on whoever adds the field.

Also caught in passing: in C# 14 "field" is a keyword inside a property accessor, so a foreach over
"field" in one binds the backing field instead of the loop variable.

157 tests, 25 self-test checks, budgets met.
@Hawkynt
Hawkynt merged commit 875bbcf into main Aug 17, 2026
11 checks passed
@Hawkynt
Hawkynt deleted the field-registry branch August 17, 2026 07:09
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