<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ida-tui.git/docs, branch main</title>
<subtitle>tui for headless ida</subtitle>
<id>https://git.sl0p.foo/ida-tui.git/atom/docs?h=main</id>
<link rel='self' href='https://git.sl0p.foo/ida-tui.git/atom/docs?h=main'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/'/>
<updated>2026-08-20T21:55:52Z</updated>
<entry>
<title>Switch to ida-nexus</title>
<updated>2026-08-20T21:55:52Z</updated>
<author>
<name>Duncan Ogilvie</name>
<email>mr.exodia.tpodt@gmail.com</email>
</author>
<published>2026-08-20T21:55:52Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=f4c1d9b5497fd0d38137b6b345e8171b307c1117'/>
<id>urn:sha1:f4c1d9b5497fd0d38137b6b345e8171b307c1117</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Adopt idb_events and remote module features from ida-codemode</title>
<updated>2026-08-20T21:42:42Z</updated>
<author>
<name>Duncan Ogilvie</name>
<email>mr.exodia.tpodt@gmail.com</email>
</author>
<published>2026-08-20T21:42:42Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=f3715d8de0d255c8b14710acfa120ccb9ea953fd'/>
<id>urn:sha1:f3715d8de0d255c8b14710acfa120ccb9ea953fd</id>
<content type='text'>
</content>
</entry>
<entry>
<title>docs: be honest that the triskel fork is unpublished</title>
<updated>2026-08-15T09:16:52Z</updated>
<author>
<name>blasty</name>
<email>peter@haxx.in</email>
</author>
<published>2026-08-15T09:16:52Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=96ce4ccb2433600e710929a48b55238721ecb061'/>
<id>urn:sha1:96ce4ccb2433600e710929a48b55238721ecb061</id>
<content type='text'>
The install instructions pointed at ~/dev/triskel, a path only I have, so a
reader could not act on them. Say plainly that the patched pytriskel is not
released yet and that native is the supported default.

Also drops the .fastfeedback/SPEED.md references and refreshes a stale
branch name and commit hash in bench_ops.py.
</content>
</entry>
<entry>
<title>docs: drop the triskel evaluation artifacts</title>
<updated>2026-08-15T09:12:11Z</updated>
<author>
<name>blasty</name>
<email>peter@haxx.in</email>
</author>
<published>2026-08-15T09:11:36Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=46e136680d4f2e80c4caf5d83641be786b7c47cb'/>
<id>urn:sha1:46e136680d4f2e80c4caf5d83641be786b7c47cb</id>
<content type='text'>
TRISKEL_EVAL.md and graph_compare.py were intermediary working docs from
choosing the SESE engine. Triskel now ships alongside the native layout
engine, so the evaluation no longer needs to be in the tree; GRAPH_VIEW.md
keeps the part that describes shipping behaviour.

Also drops the local-only ~/dev/triskel/PATCHES.md pointer from pyproject.
</content>
</entry>
<entry>
<title>Re-check the upstream findings report against 0.6.1</title>
<updated>2026-08-13T22:26:27Z</updated>
<author>
<name>blasty</name>
<email>peter@haxx.in</email>
</author>
<published>2026-08-13T22:26:27Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=43874ce87c86d69de1a0f1f770908e35189ec0e8'/>
<id>urn:sha1:43874ce87c86d69de1a0f1f770908e35189ec0e8</id>
<content type='text'>
Items 4, 8 and 9 are fixed (loader switches on reopen, package exports,
py.typed), so the report and the skill no longer claim 4-9 are all open. Item 7
is partial: DatabaseManager grew a DatabaseEventCallback, but there is still
nothing an external caching client can observe, which was the point. 5 and 6
are untouched.

The "are these files byte-identical" re-check recipe is removed: it named
client.py/registry.py/resolver.py, which 0.5.x renamed, so it would have
reported "unchanged" forever. The replacement is a diff of __all__ and the
DatabaseOpenOptions fields, both of which the contract suite now asserts
whenever the library is importable.

Also records two things that cost time here: the loader-switch strip needs
input_path != source, so an .i64 passed directly alongside load options still
fatals; and an editable checkout does not enforce its own dependency floors, so
a `git pull` to 0.6.1 leaves ida-domain/zeromcp silently too old.
</content>
</entry>
<entry>
<title>Docs: re-check ALL nine upstream findings against 0.3.2</title>
<updated>2026-08-09T20:37:44Z</updated>
<author>
<name>blasty</name>
<email>peter@haxx.in</email>
</author>
<published>2026-08-09T20:37:44Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=207a968b70dc475cec766441e2502ffb3029944a'/>
<id>urn:sha1:207a968b70dc475cec766441e2502ffb3029944a</id>
<content type='text'>
Items 1-2 were marked fixed; 3-9 were left 'not re-verified', which was a
gap rather than a finding. Checked all seven.

Item 3 is also FIXED, and by a lot: a same-box A/B (roll the editable
checkout back to 4195f21, measure, roll forward) puts
execute_python('result = 1') at 2.055ms on 0.3.1 and 0.294ms on 0.3.2 --
7.0x, now about the cost of a bare HTTP GET. The 0.3.1 column reproduces
the originally documented 2.025ms almost exactly, which is what makes the
0.3.2 column believable. So the execute_sync marshalling that was ~93% of
the floor is gone, and the 'never make a call per row' rule is much weaker.

Items 4-9 are open by construction: client/registry/resolver/server/
database/worker .py are byte-identical between 0.3.1 and 0.3.2, and all six
items live in those files. Recorded that as the cheap re-check recipe for
the next upstream pull.

SPEED.md taught the obsolete 2ms floor as a design rule; corrected, with a
warning not to go rewrite working batched code to be chatty.
</content>
</entry>
<entry>
<title>Docs: mark the two upstream perf findings fixed in 0.3.2</title>
<updated>2026-08-09T20:16:09Z</updated>
<author>
<name>blasty</name>
<email>peter@haxx.in</email>
</author>
<published>2026-08-09T20:16:09Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=e3bf966f9a7d2bc92c1092a6f81bf09917cdd2dd'/>
<id>urn:sha1:e3bf966f9a7d2bc92c1092a6f81bf09917cdd2dd</id>
<content type='text'>
CODEMODE_UPSTREAM items 1 (timeout_trace) and 2 (to_jsonable) both landed
upstream; note it at the top, on each item and in the priority table, and
flag that items 3-9 are not re-verified against 0.3.2. SPEED.md described
the settrace workaround and its IDATUI_CODEMODE_TRACE knob as current --
both are gone, and its backend table predates 0.3.2.
</content>
</entry>
<entry>
<title>Graph: never hand triskel a block its root cannot reach</title>
<updated>2026-08-09T12:17:13Z</updated>
<author>
<name>blasty</name>
<email>peter@haxx.in</email>
</author>
<published>2026-08-09T12:17:13Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=855047487c6379fb2fe027590f5aeac8942811e6'/>
<id>urn:sha1:855047487c6379fb2fe027590f5aeac8942811e6</id>
<content type='text'>
"EMPTY BL" in the status bar is triskel's own bracket-list assertion from
its SESE pass, and it turned out to be the mild version of the problem.

Triskel's graph root is whichever node was created FIRST, and every
analysis walks out from it. Anything unreachable from that node is
undefined behaviour. We were:
  - creating nodes in id order, so the root was the lowest-numbered
    block rather than the entry, and
  - splitting only WEAKLY connected components, which says nothing about
    reachability.

A 7-block CFG whose entry has no successors -- IDA hands those out for
thunks and for dead code it could not resolve -- SEGFAULTS the
interpreter. That is unsurvivable: it takes the session down and there
is no exception to fall back from.

Now the entry is created first, orphan blocks are attached to it with
phantom edges that steer placement but are never drawn (one edge usually
adopts a whole orphan subgraph, attached at a node no other orphan
reaches), and reachability is asserted in python BEFORE crossing into
C++. This replaces the component splitting entirely: one layout instead
of N stacked side by side, and triskel gets to place the orphans.

The reproducer is now a test (t_unreachable_entry). Remaining fallbacks
on the ls corpus are 8/1200 layouts, all the upstream box-overlap
defect, all but one on 300-500 block functions.
</content>
</entry>
<entry>
<title>Graph: fix the triskel fallbacks, and say why when it still falls back</title>
<updated>2026-08-09T11:55:31Z</updated>
<author>
<name>blasty</name>
<email>peter@haxx.in</email>
</author>
<published>2026-08-09T11:55:31Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=5c1563c395cf29b3d4ad7a4cc26006cc0d055643'/>
<id>urn:sha1:5c1563c395cf29b3d4ad7a4cc26006cc0d055643</id>
<content type='text'>
"engine triskel -&gt; native+triskel-failed" was unreadable and, worse,
gave no reason: the cause went to a logger a TUI user never sees.

Dumped all 400 functions of bin/ls (echo's 128 were not enough) and swept
them at three zoom levels: 6 of 1200 layouts fell back, all of them my
own _verify tripping over a detour that could not be placed.

  - the detour jumped to the nearest side of the FIRST box in the way,
    which in a dense layout is usually inside the next box along. It now
    collects every box the run passes and picks the nearest genuinely
    free line.
  - it skipped the first and last segments because they carry the port
    and the arrowhead. But that is exactly where the failures were:
    triskel is happy to park a block directly above its successor and
    drive the final approach straight through it. Those segments may now
    move ALONG their own box's border, which is free almost every time.
  - repairs are swept to a fixed point: moving one segment stretches its
    neighbours, which can push those into a box.

0/1200 fallbacks after that. Then the bigger corpus turned up a second,
genuinely upstream defect: superimposing SESE regions can leave two
blocks a couple of columns into each other (2 of ls's 400 functions,
in float space, before rounding). Cosmetic in a PNG; here the boxes are
made of text, so one block's disassembly overwrites another's. _verify
now checks it and falls back, which is the right trade.

Reporting, so this is never mute again:
  - stats["engine_error"] carries the reason, the status line shows it,
    and the label is "native (triskel failed)".
  - the corpus test asserts fallbacks are rare AND explained, rather
    than asserting they never happen.

Also lowered AUTO_TRISKEL_MAX_BLOCKS 250 -&gt; 180. Layout runs on every
zoom keypress and triskel knees hard past ~175 blocks (174: 66ms,
233: 489ms, 329: 555ms). The old cap allowed a 489ms stall. The corpus
timing check now measures only sizes `auto` can actually reach, plus a
5s ceiling so nothing blows up quadratically when forced.
</content>
</entry>
<entry>
<title>Graph: name the interpreter when pytriskel is missing</title>
<updated>2026-08-09T11:44:10Z</updated>
<author>
<name>blasty</name>
<email>peter@haxx.in</email>
</author>
<published>2026-08-09T11:44:10Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=9b5e6e993433160c0c03fa00af9186ce630ebb46'/>
<id>urn:sha1:9b5e6e993433160c0c03fa00af9186ce630ebb46</id>
<content type='text'>
./ida-tui runs $IDATUI_PYTHON (default ~/ida-venv), which is not the
repo .venv the tests use -- so the graph view can report pytriskel as
missing while tests/test_graph.py is exercising both engines. "not
installed" on its own sends you to check the wrong python; the status
now names sys.executable, and docs/GRAPH_VIEW.md says to install into
both.
</content>
</entry>
</feed>
