diff options
| author | user <user@clank> | 2026-08-13 22:07:45 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-13 22:07:45 +0200 |
| commit | a8ea4e888938e562885b1a0f009f5743939a879b (patch) | |
| tree | 2ae5df21d4919cfe128830376b55dca814418496 /docs/roadmap.md | |
| parent | checks: ignore __pycache__ (the up check imports a sibling check) (diff) | |
| download | sl0ppi-a8ea4e888938e562885b1a0f009f5743939a879b.tar.gz sl0ppi-a8ea4e888938e562885b1a0f009f5743939a879b.tar.xz sl0ppi-a8ea4e888938e562885b1a0f009f5743939a879b.zip | |
sl0p: keep a templated tab's purpose, so runtime tabs get a status bar
Clicking the bar's `+` made a tab with no status bar. The button only exposed
it: pressing `n` in TAB mode did the same, in any `sl0ppi up` session.
The chain: a generated layout had no default_tab_template, so a tab created at
runtime had nothing to take a bar from. It had none because
parse_tab_node_with_template read a tab node's name, cwd and focus but never
its `purpose` -- so templating erased the purpose that IS identity here
(`sl0ppi ls` finds project tabs by it), and the CLI worked around that by
inlining the template into every tab instead of emitting it.
Fixed at the root: a templated tab keeps its own purpose, and the CLI emits
`default_tab_template` again. The generated layout also shrinks -- one copy of
the bar's configuration instead of one per tab.
The two properties trade off against each other, so sl0ppi-up-live.py now
asserts both at once: `sl0ppi ls` still sees a tab per project, and every tab
including one created at runtime has exactly one status bar. Confirmed by
reverting each half separately: without the parser fix the tabs lose their
purpose and `ls` shows "alpha —"; without the CLI change the runtime tab has
zero bars, which is the reported bug.
Two measurement traps cost an hour here and are now written down: counting bars
by grepping dump-layout also counts the template and every swap layout ("4 bars
for 3 tabs"), and list-panes stops reporting borderless plugin panes for a tab
once a client has rendered it.
Also in here, from the same session:
- the split button check found buttons by searching for " + " on any row with a
frame glyph, which matches the stack list's "+N more" once two panes sit side
by side, and then reports the product broken. It now requires the frame
corner the button is drawn against.
- the checks killed their sessions but did not delete them, so each run left an
"EXITED - attach to resurrect" entry: 35 had quietly filled the session
picker. They now delete-session by name.
- and the trap that cost the user their running client: I killed a bare
`sl0ppij` because "there are no user sessions on this box". That was a guess,
not evidence, and wrong. A check's processes always carry that run's own
socket dir or `attach sl0ptest-...`; a bare `sl0ppij` with a cwd in the repo
is a human's. Written into the handover next to the `pkill -f` trap, which is
the same mistake in a different costume.
Diffstat (limited to 'docs/roadmap.md')
| -rw-r--r-- | docs/roadmap.md | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/docs/roadmap.md b/docs/roadmap.md index 068129f..675f82d 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -355,6 +355,42 @@ render half a box. That one function also returns where the content line starts, and click routing reads it — which is why a click on the new box's border hits nothing instead of the widget underneath. +### A tab made at runtime had no status bar + +Reported as "creating a new tab with the icon from the status bar created a tab +without statusbar" -- but the button was innocent: the `n` keybinding did it +too. A generated session had no `default_tab_template`, so there was nothing for +a runtime tab to take a bar from. + +The reason it had none was the trap recorded below: templating a tab dropped its +`purpose`, and purpose is identity, so the CLI inlined the template into every +tab instead. That trap turned out to be one missing line in the fork -- +`parse_tab_node_with_template` read `name`, `cwd`, `focus` and +`split_direction` off the tab node but never `purpose`, so the template's (None) +won. It now keeps the tab's own, and both properties hold at once: + +| | inlined (before) | templated (before) | templated (now) | +|---|---|---|---| +| tab keeps `purpose` | yes | **no** | yes | +| runtime tab gets a bar | **no** | yes | yes | + +So `sessionLayoutKdl` emits `default_tab_template` again, and the generated +layout shrank further: one copy of the bar's configuration for the session +rather than one per tab. `singleTabLayoutKdl` still inlines -- that layout is +handed to a session that already has a template, and emitting another would give +the new tab two bars. + +`sl0ppi-up-live.py` checks both halves, because fixing either one alone +regresses the other: every tab (including one made at runtime) has exactly one +bar, and `sl0ppi ls` still finds a tab per project. Confirmed by reverting each +half in turn and watching the matching assertion fail. + +Counting bars needs care: `dump-layout` includes the template itself and every +swap layout, so grepping it reports definitions as if they were panes -- that +cost an hour of chasing a doubled bar that did not exist. Count panes per tab +from `list-panes`, and do it BEFORE any client attaches (see the trap about what +that hides). + ### `sl0ppi up` and the generated layout Making the bar a `pane_template` broke `sl0ppi up` outright: @@ -385,6 +421,36 @@ attached it stops reporting the borderless plugin pane, which had me believing the bar was gone in cases where it was on screen the whole time. `dump-layout` and the screen agree; `list-panes` does not. +### A tab made at runtime now gets a status bar + +Clicking the bar's `+` (and pressing `n` in TAB mode) produced a tab with no +status bar in `sl0ppi up` sessions. The button only made it visible: a generated +layout had no `default_tab_template`, so there was nothing for a new tab to take +a bar from. + +The reason it had none was `parse_tab_node_with_template`, which read a tab +node's `name`, `cwd` and `focus` but not its `purpose` -- so templating a tab +erased the purpose that is the CLI's notion of identity, and the CLI worked +around it by inlining the template into every tab. That is now fixed at the +root (`sl0p_a_templated_tab_keeps_its_own_purpose`), and the CLI emits the +template again: + +| | inlined (before) | template (now) | +|---|---|---| +| tab keeps `purpose=` | yes | yes | +| runtime `new-tab` has a bar | **no** | yes | +| copies of the bar's config in the layout | one per tab | one | + +Both halves are checked by `sl0ppi-up-live.py`, because they trade off against +each other: it asserts `sl0ppi ls` still sees a tab per project AND that every +tab, including one created at runtime, has exactly one status bar. + +Count bars per tab from `list-panes`, not by grepping `dump-layout`: that dump +also contains the template itself and every swap layout, so substring counting +there reports "4 bars for 3 tabs" and sends you looking for a doubling bug that +does not exist. And do it before any client attaches, because `list-panes` stops +reporting borderless plugin panes for a tab a client has rendered. + ### Still open on the bar Content and further click targets: a close-`x` per tab, session name → session |
