Skip to content

Match REPL colours, pane surfaces and drawers to the reference (#881, 1/3) - #885

Merged
taras merged 4 commits into
mainfrom
agent/issue-881-pr1-integrated
Oct 10, 2026
Merged

taras merged 4 commits into
mainfrom
agent/issue-881-pr1-integrated

Conversation

@taras

@taras taras commented Oct 10, 2026 •

Copy link
Copy Markdown
Owner

Stack 1/3 — followed by #886 and #887. Merge bottom-up.

Why

The REPL’s flat colours and weak pane/drawer separation obscure the hierarchy in the original Terminal Interface reference. This is slice 1 of #881: colours, surfaces and drawers.

What changes

Before: a row has one text colour, focus can overwrite semantic emphasis, and drawers have little separation from the reading behind them.

After: source and JSON characters carry their semantic colours, including overflowing rows; focus adds weight and a cyan cue. Pane backgrounds, the gold drawer rule and inset, waiting-accent titles, and distinct field names/values follow the reference.

How it works

Immutable private token runs travel with a row’s plain view data. Layout emits bounded text operations inside the same measured element, retaining one node and one target per row. XMD/JSON classification changes presentation without validating or rewriting the text.

Review guide

Start with packages/cli/src/repl/description.ts, presentation-text.ts and presentation-style.ts; then review run clipping in layout.ts, drawer surfaces in application.ts, and repl-presentation-style.test.ts.

What must stay true

  • Measurement, admission, mounted targets and focus remain engine/Freedom-owned.
  • Semantic colours survive focus and overflow; independent archive literals and the one-bit palette-drift control discriminate regressions.
  • Cold reopening changes neither the Journal nor provider log.

How to verify it

Focused feedback at accepted 080b6ec80ca74e614789e8d2252857ac281df7e5:

deno task test packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-forms.test.ts

28 tests / 105 steps passed; whitespace gate passed. All 35 production/reference pairs were independently opened; five mutation controls fail their named assertions and restore source bytes.

Scope

Includes private token-run presentation, pane/drawer styling, the independent reference fixture and affected screen-reading assertions. Lifecycle, generated-source restructuring and History belong to the dependent slices.

Risks and limitations

The measured drawer rule costs one visible row; the existing later-window control preserves access to submit and validation. This publication uses the existing integration commit c7d54769d56661bef38cee8549b148f3bf87a904, which mechanically merges accepted PR 1 with main 4c0414be1010f69f11bff0d1d634623a5b08f886; no new product change or commit is introduced. The integrated stack was reviewed in PR 2 and PR 3.

Draft publication only: delivery verification and required merge gates remain outstanding. The local visual packet and Planner acceptance are retained under .reviewer/issue-881/; no public evidence attachment is claimed.

Scope confirmation

  • Every changed file supports this slice’s purpose.
  • Unrelated cleanup and formatting changes are excluded.
  • Mechanical fixture/assertion changes are identified.
  • The description distinguishes focused implementation evidence from delivery verification.

taras added 4 commits October 8, 2026 09:47
XMD source and JSON keep their own colours wherever this screen shows them
verbatim, panes and drawers have surfaces of their own, and a drawer says where
the reading behind it stops.

A row whose characters mean different things now carries immutable token runs:
plain view data, issued by the composition module, concatenating to exactly the
text the row draws. The ops builder emits one text operation per run inside the
one element the row was measured as, so a row reading as several things is still
one node, one bound and one pointer target.

A private `presentation-text.ts` says what the characters of the two readings
this screen shows verbatim are — executable Markdown source and a serialized
JSON value — one line at a time, classifying nothing it was not handed. It
validates nothing, evaluates nothing and rewrites nothing, and JSON is
classified from a value this product already parsed rather than from a guess
about arbitrary text.

Focus no longer repaints a row. It adds weight, and the cue in front of the row
is the one run the focus colour belongs to, so the row a keystroke reaches stays
readable as the thing it is while selection keeps its own surface.

The application paints its own uncovered area, a question or permission drawer is
named in the waiting accent, a field's name and the value in it are told apart,
and the contextual drawer is bounded by a rule along the top of its rectangle and
inset one cell on each side. Both belong to the measured rectangle: the content
window is measured at what they leave, which costs that window one row and two
columns at every profile and is why UI16 and UI17 now reach `[submit]` and the
validation row through one `[v later]`.
The engine wraps each text operation on its own, and a row is one cell tall:
several stretches whose total is wider than the element each show their own
first line and leave the cells their remainder went to blank. A 400-column
generated tag in a 118-column drawer came out with its quoted values missing —
found by capturing the gallery, which the focused tests could not reach because
every example in them fits.

A row carries its stretches only when the element it was measured in holds them
whole, read off the constraint the element was opened with. A row the engine
must wrap is drawn as the one thing it is, which is the reading this screen has
always shown. The regression commits a tag far wider than any supported drawer
and holds every written cell to being the next character of the source.
Planner feedback on f0b8eb1: three frozen requirements were unmet.

**R1.** An overflowing row went through a single-colour fallback, so the Plan
preview read as ordinary source and, at 72×20, a populated field painted its
visible value as though it were the field's name. The fallback existed because
the engine wraps each text operation on its own. The stretches are now cut at
the room the element has instead: nothing wraps, every character the row can
show keeps the role it has and the order it was in, and the cue in front of a
focused row is still the one cyan thing. A row whose width the flow decides —
only the pass that is asking what the widths are draws one — is unchanged.

The overflow regression now asserts the delimiter, tag, attribute, quoted
value, reference and prose roles on the overflowing row itself, that no row is
one colour throughout, and that the narrow populated form keeps its field's
name and its value apart. The gallery audit no longer accepts a tag drawn as
one stretch.

**R2.** The new assertions read expected RGB from the production palette, which
would have stayed green through a palette drift. They now read a fixture
transcribed from the corrected Terminal Interface archive — its `S`, `C` and
`Y` constants, with the archive hash and the sources they came from — so the
two sides of every comparison are independent. Changing one palette entry by a
single bit now fails three rows.

**R3.** The frozen resize endpoints are taken with the populated project
question open, so the refusal and the recovery prove the editable question and
its values survive, rather than substituting the permission drawer.
@taras
taras added this pull request to stack #888 October 10, 2026 02:32
@taras
taras marked this pull request as ready for review October 10, 2026 02:40
@taras
taras merged commit 160e354 into main Oct 10, 2026
43 of 44 checks passed
@taras
taras deleted the agent/issue-881-pr1-integrated branch October 10, 2026 03:16
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