<feed xmlns='http://www.w3.org/2005/Atom'>
<title>pantograph.git/src/tui_engine.zig, branch main</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.
</subtitle>
<id>https://code.tjp.lol/pantograph.git/atom?h=main</id>
<link rel='self' href='https://code.tjp.lol/pantograph.git/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/'/>
<updated>2026-07-06T19:06:23Z</updated>
<entry>
<title>rendering &amp; chat fixes for panto cli</title>
<updated>2026-07-06T19:06:23Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-07-06T14:34:35Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=983e523ca9f8e6a7db56b4aca23a962be95e7051'/>
<id>urn:sha1:983e523ca9f8e6a7db56b4aca23a962be95e7051</id>
<content type='text'>
- resiliency for tool ids that come back from some openai_chat providers
- fixing codepoint width recognition
- implement proper rendering for full markdown as seen from ai models
</content>
</entry>
<entry>
<title>Fix tool override swaps to stay differential</title>
<updated>2026-07-01T15:49:33Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-23T17:20:45Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=5e76e4aa90e70245404c10085e809880635572a0'/>
<id>urn:sha1:5e76e4aa90e70245404c10085e809880635572a0</id>
<content type='text'>
Treat 1:1 component swaps and pure insertions as differential TUI updates
instead of structural changes that force full redraws. Keep full redraws
for net removals and edits above the viewport, and add tests covering the
streaming-tool flicker regression and scrollback behavior.

Also remove the unfinished Go ToolSource batch-registration bridge.
</content>
</entry>
<entry>
<title>tool collapsed state, and fixing dirty component flags</title>
<updated>2026-06-16T17:58:44Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-16T17:49:54Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=28cb3eacfcf1217b4d014dd864005deb2d7f0585'/>
<id>urn:sha1:28cb3eacfcf1217b4d014dd864005deb2d7f0585</id>
<content type='text'>
</content>
</entry>
<entry>
<title>fix: eliminate scrollback-clearing flash when streaming with expanded tool output</title>
<updated>2026-06-10T21:28:16Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-10T20:57:31Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=cee08918509689adbdbd26b6384d5ef3a47e91a2'/>
<id>urn:sha1:cee08918509689adbdbd26b6384d5ef3a47e91a2</id>
<content type='text'>
The root cause was a two-part bug:

1. Engine slot management (tui_engine.zig): The app rebuilds its full
   component list on every new transcript entry. The old approach drained
   every slot then re-added them all, resetting every component's render
   baseline. When earlier content had scrolled into native scrollback
   (viewport_top &gt; 0), the engine's viewport-escape rule escalated any
   cut above the viewport top to a scrollback-clearing full redraw — the
   visible flash on every streamed block while a tool call was expanded.

   Fix: replace drain+rebuild with syncComponents(), which reconciles the
   live slot list in place by finding the longest common prefix and suffix
   (matched by component pointer). Prefix and suffix slots keep their
   baselines verbatim; only the changed region in the middle gets new
   empty slots. A pure insertion (the dominant case: a new transcript
   entry appended just before the pinned input+footer suffix) stays on
   the differential path with no clear. A structural change (slot
   replaced or removed) sets force_full for correctness.

2. RenderCache dirty signal (tui_component.zig): firstLineChanged()
   was returning the retained changed_from diff index even when the cache
   was clean. A first-paint store records changed_from == 0, so a clean
   but previously-rendered component was pegging the differential cut to
   line 0 on every subsequent frame, making unchanged slots above the
   insertion point drag the cut all the way up. Fix: when the cache is
   clean, firstLineChanged() returns null unconditionally. The recorded
   changed_from is now internal render bookkeeping only, not a live
   signal.

Additional changes:
- ToolUse.collapsed_tail_lines raised from 5 to 8 lines.
- ToolUse collapsed-view test updated to use 12 output lines and
  collapsed_tail_lines symbolically so the numbers self-document.
- tui_app.zig: override-slot test comment and assertion clarified to
  reflect that the override owns the slot pointer (not just renders it),
  and the SWAPPED-AT-DETAILS render check replaced with a pointer-equality
  check.
- lua_event_bridge.zig: minor related fixes.
- New tests: syncComponents middle-insertion no-clear, syncComponents
  structural removal forces full, syncComponents override swap; streaming
  expanded-tools no-clear regression test in tui_app.
</content>
</entry>
<entry>
<title>fix streaming rendering</title>
<updated>2026-06-09T18:03:35Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-09T18:01:31Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=af5119901997774ef7d04b1940194ce54a5b35a4'/>
<id>urn:sha1:af5119901997774ef7d04b1940194ce54a5b35a4</id>
<content type='text'>
</content>
</entry>
<entry>
<title>finalize cursor on quit</title>
<updated>2026-06-09T16:13:39Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-09T16:13:26Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=3d535f8360f35132faaeef093d61cf377be5e9cc'/>
<id>urn:sha1:3d535f8360f35132faaeef093d61cf377be5e9cc</id>
<content type='text'>
</content>
</entry>
<entry>
<title>event lifecycle</title>
<updated>2026-06-09T14:52:47Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-09T06:00:56Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=97b10466d83d488ad2cb9e084159a445af74c845'/>
<id>urn:sha1:97b10466d83d488ad2cb9e084159a445af74c845</id>
<content type='text'>
</content>
</entry>
<entry>
<title>keybinding fixes</title>
<updated>2026-06-09T01:56:47Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-08T20:48:33Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=104001d25c9c8cb5ec45ced1678f7c7b70888808'/>
<id>urn:sha1:104001d25c9c8cb5ec45ced1678f7c7b70888808</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Replace print CLIRenderer with differential TUI engine</title>
<updated>2026-06-08T18:25:55Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-08T16:41:30Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=e5ed00c52bb10aec811734c5568c881c41e58474'/>
<id>urn:sha1:e5ed00c52bb10aec811734c5568c881c41e58474</id>
<content type='text'>
Implement TUI Phase 1: a raw-mode terminal, differential render engine,
pinned input box + footer, and component model wired into the libpanto
event stream. Adds foundation modules (theme, key, component, input,
terminal), the render engine, components, and the app loop; removes the
old print CLIRenderer and driveTurn REPL from main.zig.

Also removes scratch status reports (tui-p1/, progress.md) for the now
completed work.
</content>
</entry>
</feed>
