Skip to content

Claude/review namespace available options wenm6#48

Open
pdfinn wants to merge 2 commits into
masterfrom
claude/review-namespace-available-options-WENM6
Open

Claude/review namespace available options wenm6#48
pdfinn wants to merge 2 commits into
masterfrom
claude/review-namespace-available-options-WENM6

Conversation

@pdfinn
Copy link
Copy Markdown

@pdfinn pdfinn commented Mar 7, 2026

No description provided.

claude added 2 commits March 7, 2026 02:01
Add registernamespace() to probe known namespace paths (/n/llm, /dev/cons,
/tmp/veltro, /lib/certs, etc.) and register them as non-tool resources in
the context zone. The existing Resources section in lucictx.b already
renders entries where rtype != "tool" — it just never got populated.

Each path is checked via sys->stat() so only entries present in the
(possibly restricted) agent namespace get registered, with type labels
(service, device, fs) and via annotations (rw, ro) for filesystem mounts.

https://claude.ai/code/session_016795BsWP8iJJp31xf6Rf1P
Side effects of running build-linux-amd64.sh: pdf.dis recompiled with
minor bytecode differences, viewport.dis newly compiled, lucipres.dis
removed (requires xenith/render.m unavailable in headless build).

https://claude.ai/code/session_016795BsWP8iJJp31xf6Rf1P
@sonarqubecloud
Copy link
Copy Markdown

pdfinn added a commit that referenced this pull request May 18, 2026
…R-27) (#48)

* fix(borders): drop accent contentborder from ftree/charon/matrix

The prior wmclient fix (ab68594) introduced a single subdued window
border via th.windowborder so all wm apps would have a calm,
uniform frame regardless of focus state. But three apps continued
to draw widget.contentborder() over the top of that frame, which
uses th.accent (Brimstone E8553A orange-red, Halo 2266CC blue) and
broke border consistency:

- ftree showed an orange frame around the file tree
- charon showed an orange frame around the page
- matrix showed an orange frame around the layout

Other apps (about, fractals, editor, keyring, man, wallet) did NOT
call contentborder, so they inherited only the subdued wmclient
frame in th.windowborder.

Fix: remove the contentborder calls from those three apps. The
single common border is now the wmclient frame everywhere, and
the only place it's drawn is wmclient.drawborder, which already
re-reads th.windowborder on each retheme(w) call.

widget.contentborder() and accentbdr remain in the widget library
for callers that explicitly want an accent-coloured content frame
(none currently); they are not the right primitive for the outer
window border.

Refs: INFR-27

* fix(wmclient): pre-fill w.image, default kbd drainer (INFR-27, INFR-29)

Two cross-cutting wm app correctness fixes layered on the
contentborder removal in this branch.

INFR-27 white-border root cause:
wmclient.putimage allocates w.image with Refnone+Nofill, leaving
its content as undefined display memory.  Apps that fill w.image.r
themselves overwrite that (about, ftree, editor — all show the
correct subdued frame).  Apps that compute a smaller content rect
via w.imager(w.image.r) and only fill that smaller rect leave a
1-pixel ring inside w.image showing whatever was in display
memory — typically white.

The architectural fix is in wmclient, not the apps: putimage now
pre-fills w.image with screenbg (= th.bg) right after allocation.
Apps that fill w.image.r overwrite this and pay nothing; apps
that don't get a dark themed ring instead of undefined memory.
Resolves the visible "white border" on fractals, keyring,
settings, wallet without needing to touch any of those apps.

INFR-29 UI-freeze root cause:
ctxt.kbd is an unbuffered chan of int (module/draw.m:284).  When
a window has focus, the wm sends kbd events on it.  An app whose
main alt loop has no <-w.ctxt.kbd arm blocks the wm send forever
on the first keypress with focus, deadlocking the entire UI.

Fix is layered:

  1) Architectural safety net (wmclient): wmclient.window() now
     spawns a default kbd drainer that consumes ctxt.kbd until
     the app calls startinput("kbd"), at which point startinput
     signals the drainer to exit and the app reads ctxt.kbd as
     before.  Two new private Window fields wire this up:
       kbdsubscribed: int        # set by startinput("kbd")
       kbdstop:       chan of int
     No app-side change required for the safety net to work; no
     API change for apps that already subscribe to kbd correctly.

  2) Defense-in-depth in the three offending apps (clock, colors,
     view): each now has an explicit `<-w.ctxt.kbd => ; # discard`
     arm in its alt loop.  Redundant with the safety net but
     documents that the app is aware of the kbd channel and chose
     not to subscribe.  view.b is the worst case — it had
     `startinput("kbd"::"ptr"::nil)` (explicitly requested kbd)
     yet never read it.

Refs: INFR-27, INFR-29

* fix(wmclient): keep kbd safety-net state out of Window adt

Adding fields to the Window adt (kbdsubscribed/kbdstop) in the
prior commit changed the adt's interface signature.  Result:
every .dis compiled against the old wmclient.m had a different
mental model of Window's layout, and lucifer.dis failed to load
the new wmclient.dis at runtime:

  link typecheck Wmclient->Window.onscreen() 6458c4bd/abf7c1a
  lucifer: can't load /dis/lib/wmclient.dis: link typecheck ...

Bricks the entire desktop on logon.  23 .b files import
wmclient.m; rebuilding them all every time we add an internal
field is the wrong design.

Refactor: keep the kbd-drainer state module-private inside
wmclient.b — a list of (Wmcontext, stop-chan, subscribed-flag)
keyed by w.ctxt — so the public Window adt is unchanged.
findkbdstate(ctxt) looks up the entry; startinput("kbd") signals
the drainer through it as before.

Window adt is restored to its previous shape so all wmclient
consumers keep working with their existing .dis files.  The
safety net is preserved: every wmclient.window() call still
spawns a drainer, every startinput("kbd") still stops it.

Refs: INFR-29

* fix(theme): block themelistener send so apps don't miss switches (INFR-28)

Every wm app's themelistener was using a non-blocking alt send:

    alt { themech <-= 1 => ; * => ; }

themech is a chan[1] of int.  If the app's main alt loop is in
another arm when an event arrives (pointer, kbd, ctl, ticks,
redraw), the buffer fills with the first signal — and any
SUBSEQUENT signal is silently dropped by the `* => ;` fallback.
This is the intermittent miss the user observed: theme switches
sometimes fail to update already-open apps even though the
luciuisrv -> /n/ui/event pipeline delivered the event correctly.

Fix: use a plain blocking send (`themech <-= 1;` or `ch <-= 1;`).
themelistener is its own dedicated goroutine; blocking it is the
right semantic.  When the main loop is slow, themelistener parks
on the send until the main loop receives.  luciuisrv already
buffers events per-fid so nothing upstream is lost; if a burst
of theme switches arrives while themelistener is parked, the
next read from /n/ui/event drains the queue and triggers as
many retheme cycles as there were events (cheap and correct —
reloadcolors re-reads the live theme file each time).

Apps patched: about, fractals, ftree, editor, keyring, man,
wallet, settings, charon/gui.  All compile + theme handlers
preserved.  No API change.

Refs: INFR-28

* fix(theme): seek fid to 0 in every themelistener (INFR-28 root cause)

Live theme switches were only ever propagating to the active app
once.  Diagnosis required adding stderr traces to themelisteners
and luciuisrv.pushglobalevent — see commit history.

Root cause: /n/ui/event is a streaming queue but it lives on a
styx 9P fid that keeps a client-side offset advancing by every
read's byte count.  After the first successful read the kernel
applies that offset to the server's next Rread reply data; the
client receives a truncated tail (bytes [offset:]) and on the
read after that, offset is past the end and the kernel returns
0 (EOF) — at which point the themelistener exits.  Every
focus-list app thus ran a one-shot listener: whatever event was
queued at startup or arrived first gets delivered, then the
listener dies and no later switch reaches the app.

Reproduced in trace:
  ftree: themelistener: ev='theme brimstone\n'  (16 bytes — full)
  ftree: themelistener: ev='theme halo\n'        (11 bytes — full)
  ftree: themelistener: ev='tone\n'              (5 bytes — bytes
                                                  [11:16] of next
                                                  16-byte event)
  ftree: themelistener: read returned 0, exiting

Fix: sys->seek(fd, big 0, Sys->SEEKSTART) after each successful
read so the client-side offset resets and the next read starts
fresh at 0.  Seek is local to the fid, doesn't go on the wire,
and is cheap.  Verified working in ftree end-to-end.

Applied to every focus-list app's themelistener:
  about, fractals, ftree, editor, keyring, man, wallet, settings,
  charon/gui.

Also kept the earlier server-side hardening from this branch
(luciuisrv replies for Qevent / Qnotification / Qtoast / pending
reads now use Rmsg.Read directly rather than styxservers->readbytes
which would have applied the same offset slicing on the server
side).  Diagnostic stderr traces in luciuisrv + about + ftree
removed.

Refs: INFR-28

* fix(theme): shell + matrix themelisteners (INFR-28 — missed in prior pass)

Same fix as 5f90fab applied to two apps that weren't in the
original focus-list audit:

  shell.b:   missing seek-to-0 and also still had the old
             non-blocking alt themech send pattern (alt { themech
             <-= 1 => ; * => ; }), so even when an event got
             through it could be silently dropped.

  matrix.b:  was opening /lib/lucifer/theme/event — a path that
             doesn't exist in the bundle — so its themelistener
             failed open and exited immediately.  Never received
             any theme events at all.  Switched to /n/ui/event
             like every other app, plus the seek + blocking-send
             fixes.

Refs: INFR-28

* fix(wallet): retheme context menu on theme switch

menu.b caches its colours (mbg, mborder, mhilit, mtext, mdim) as
module-level globals populated in menumod->init() and exposes no
separate retheme() entry point.  Apps using the menu module are
therefore expected to call menumod->init again whenever the theme
changes — ftree, editor, keyring, man, shell, fractals all do this
in their reloadcolors() or themech handler.

wallet was missing that call, so its right-click context menu (and
the per-account detail menu) stayed on the original theme's colour
palette across live theme switches even though every other wallet
surface (frame, list, form, statusbar) tracked correctly.

Fix: call menumod->init(display_g, font) in wallet's themech
handler after the other retheme calls.

Refs: INFR-28

* test(luciuisrv): theme event streaming regression test (INFR-28)

Adds testThemeEventStreaming: a long-lived /n/ui/event subscriber
that observes 5 successive "theme X" events pushed via /n/ui/ctl.
The subscriber opens the fd once, reads in a loop, and sys->seeks
back to 0 between reads — exactly the pattern every wm app's
themelistener now uses.

Before commit 5f90fab this would have failed on the 2nd or 3rd
iteration: the styx fid's client-side offset accumulated by each
read, the kernel applied that offset to the server's next Rread
data, and the third read returned 0 (EOF).  The test asserts each
read returns non-zero bytes and that the event content matches
exactly, so any future regression that breaks the streaming-fd
contract trips it.

The test is open-once / read-many / seek-between deliberately —
closing and reopening between iterations would mask the original
bug.

Test count: 27 -> 28, all passing.

Refs: INFR-28

* fix(theme): re-init widget/menu modules in lucifer zones on retheme

Three lucifer GUI zones (conversation, presentation, context) were
caching theme-derived state in widget and menu library modules
populated only at init() time.  Module-level globals in widget.b
(btnbg, btnborder, btntext, listsel, accentbdr, etc.) and menu.b
(mbg, mborder, mhilit, mtext, mdim) therefore stayed on the
original theme's palette across live theme switches, even though
every direct color variable in each zone's reloadcolors was
updating correctly.

User-visible symptoms (long-standing):
  - Chat dialogue buttons (LLM setup wizard etc.) stayed on the
    pre-switch theme — luciconv's reloadcolors didn't re-init
    widgetmod, so the button surfaces used cached widget colors.
  - Right-hand context view popup menus (file-browser mode in
    particular) didn't follow theme changes — lucictx's
    reloadcolors didn't re-init menumod.
  - Occasionally the taskboard's right-click menu kept its old
    palette — lucipres' reloadcolors didn't re-init menumod.

Fix in each zone's reloadcolors():
  luciconv.b: widgetmod->retheme(display_g) + menumod->init(...)
  lucipres.b: menumod->init(display_g, mainfont)
  lucictx.b:  menumod->init(display_g, mainfont)

Why both functions: widget.b exposes a proper retheme(display)
entry that re-runs the colour setup.  menu.b has no equivalent —
its colours are set only in init().  Adding menu.retheme() is
filed as INFR-35.

Refs: INFR-28, INFR-35
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.

2 participants