@mmmbuto/nexuscrew 0.9.41 → 0.9.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  All notable changes to NexusCrew are tracked here.
4
4
 
5
+ ## 0.9.43 — 2026-09-24
6
+
7
+ - **On the phone, the first tap previews a cell and the second opens it.** A tap on a row now shows that cell's stream in the upper half of the screen, read-only and in the same font as the main terminal, and the preview's − and + move that one value; the second tap on the same row opens the cell, after a fresh re-read that still refuses a cell which died between the two taps. Rows have a fixed height and clip what is inside them, so a long name, both badges and the telemetry stay within their own row and a tap cannot land on the row below any more; a cell states **one** condition instead of showing two at once, and the node name rises once into the group header instead of repeating on every row. The dot only reports the state — looking live is the row's first tap, and the preview replaces it on this surface. A scroll is not a tap, and a gesture that is cancelled, started by a second finger, or dragged past its threshold neither selects nor opens, while Enter and Space keep working as the keyboard activation. The selection dies with its row: a cell that disappears, stops, or leaves the active filter closes the preview, and when it comes back it must be selected again rather than reopening on its own. (commits f0c0638, 20f6fea, 2dd71d0, 9678c34, 48c66ae, 1a22171, 73e218e)
8
+ - **The mobile top bar keeps the zoom controls and gathers the rest into one menu.** The keyboard, files, panel and renderer switches leave the bar and move into the ⋯ menu, which is the same actions menu the cell rows already use, in its two existing shells — the bottom sheet on the phone and the anchored popover on the desktop: no second menu to learn, and the panel entry appears only for a cell that publishes one. The centre of the bar now carries both the engine and the state, and its subtitle truncates instead of sliding under the buttons on a narrow screen. (commit f0c0638)
9
+ - **A federated question that cannot be answered now says which of the two reasons it is.** The read-only card showed one message even when the cause was not the grant but a missing feed of the owner's node — the card had arrived over push while the subscription was never activated — so the button that was offered could not have fixed anything. The state of that view is now kept next to the grants: without it the card says to enable reception, with a live view and a denied grant the message stays what it was. Permissions are unchanged; only the text is. (commit 3b06b91)
10
+ - **codex-vl 0.156.1 is accepted by the cell hooks guard.** The fork's binary after the upstream merge reports itself as 0.156.1, and the table of proven versions admits it next to 0.155.1, with a test that covers acceptance and refusal — trust stays per exact hash, never per prefix, so any other version is still turned away. (commit b544f4f)
11
+
12
+ ## 0.9.42 — 2026-09-23
13
+
14
+ - **A cell that has finished stays "stopped" instead of turning unverified.** The expiry window applied to every state, so a cell whose turn had ended more than five minutes earlier fell back to "unverified": the UI showed an uncertain cell while it was simply stopped, with the right generation. Expiry exists for one case only — a turn interrupted with Ctrl-C emits no event and would stay "working" forever — and it no longer applies to "stopped", a state that stays true and that the process ending already invalidates. (commit 3594905)
15
+ - **A "stopped" state no longer outlives what should invalidate it.** Three cases the removed expiry had been hiding: an internal restart happens inside the same launch, so the generation does not change — the supervisor now declares the client's exit before every return, and that reads as "unverified", never "stopped", while the client is dead or backing off; an activity file that carries no generation is not bound to any launch and is discarded once a launch publishes one; and if a launch cannot publish its generation, no hooks are injected for it — a state nobody can invalidate is more honestly reported as unverified, with a log line saying why. (commit 700816d)
16
+ - **A client's exit wins over timestamp order, and a discarded write says so.** A stop event whose timestamp sat inside the reader's future tolerance stayed published after the client had died: the exit carried an older timestamp, the writer discarded it while still returning success, and the view kept saying "stopped" over a dead client. The exit is authoritative now — it is republished right after the state it invalidates, never into the future the reader rejects, and the reading becomes "unverified" — and any other discarded event returns a failure, so the caller can tell "your event is not in the store" from "done". An event arriving after the exit renews the state: the exit invalidates the past, not the future. (commit 5846c0e)
17
+ - **Turn state is published for codex cells too, and only where the hook is trusted.** Codex cells published no turn state at all, so the UI showed them as unverified: true, but it was information that could be had. They now use codex's own hook system, under one extra constraint — a hook passed on the command line is not trusted until its hash appears in the client's hook state, otherwise the client opens a review dialog and the cell stalls on a question nobody sees. The hash is computed the way the client expects it (of the canonical JSON of a normalized identity, not of the command text), the hook table travels inline, interruption is part of the event matrix, and the events, the writer and the format are the same as for Claude cells, with the user's own hooks untouched. Hooks are injected only on proven versions, and the gate runs the binary the cell actually resolves rather than the one on the process path, with a short time cap: where the trust key cannot be proven (Windows, Termux) nothing is injected and the cell stays unverified with a log line, which costs less than a cell stuck on a dialog. (commits 119fa86, 250d469, ed4fe2d, 91ad9f0)
18
+ - **A stale answer can no longer overwrite a fresh one in the desktop rail.** The desktop poll runs every four seconds while a federated read may take up to eight, so two rounds stayed in flight together and the older answer could land last, rolling the cell list back to a superseded outcome. A round already in flight now makes the tick skip, a superseded outcome is never applied, the guard is invalidated when the effect is cleaned up and re-checked before every write, and every request carries a time cap below the poll period — **including the body**, which used to be uncovered because the timer stopped when the headers arrived: a body that does not arrive within the cap is a failed read, not an empty answer. A failed local read is also declared to the roster instead of being presented as authoritative. (commits 8051fd6, b62d204, f00b233, fef0908)
19
+ - **The AI desktop switch governs the container and the button that opens it.** The panel button that opened a blank page was a switch with no wire: the panel existed even with its container stopped, and the proxy's 502 reached the frame as an empty page that reported itself as loaded. The container is now commanded without a shell (argument vector, fixed name, time cap, outcome always reported), an explicit key rules, and a switch nobody has ever touched loses nothing — the default is derived from the container only where it makes sense, never in the hot status path. Settings gain the switch with the true outcome of the command: the save is not rolled back, so the switch states what is wanted and the badge states whether the world got there. The page served when the panel does not answer announces itself to the window that hosts it, with the trust placed in the receiver — the frame that is actually on screen, its declared origin, the expected type — so the panel moves from "loaded" to "unreachable" with Retry, and a failed start shows the cause instead of being wiped by a reopen that promises the same outcome. "Start" appears only for the local node's desktop panel: a remote cell never starts another node's container. Other people's containers keep the behaviour they had. (commits 79ef96a, 86d148e)
20
+ - **One menu for a cell's actions, on every surface.** Assigning or removing the Live host, pinning, booting at startup and watching a cell live are now a single menu with two shells — an anchored popover on the desktop and a sheet from the bottom on the phone — and an action that does not apply (capability missing, cell off, no handler) **is absent**: not a disabled item, an item that is not there, so the menu never promises what it cannot do. (commit da211e2)
21
+ - **In the desktop sidebar the row keeps fewer buttons and says more state.** The star and the boot toggle leave the row: a cell keeps the actions menu and the power button, and its state reads at a glance — two lines instead of one clipped, activity in relative form, the new-file badge, a LIVE mark on the cell hosting the stream, the reorder handle only while the pointer or the focus is there. The line naming the Live host becomes a strip, and the outcome of the last command arrives there too. Hovering the status dot raises a small preview of that cell — the same body as the full peek, three sources, stream by default — and the pin turns it into the free window. (commit 1a7985e)
22
+ - **On the phone, the cell list and the cell selector follow the same design.** The mobile home adopts the same actions menu and the same strip, and reordering becomes a **mode**: the handles appear when it is switched on, not always. Tapping a row **opens** the cell, and a fresh re-check always comes first — if the read fails the row does not say "off", it says it could not verify, and a verified dead cell remains the only case that can be called no longer active. The dot opens the live stream **directly**: on a phone there is no hover cloud, and looking is not going. The cell selector moves its header to the top, gains the reorder mode, marks "you are here" on the cell being worked in, gets its own actions sheet, and its status line is readable at 12 px — on a switched-off row the dimming no longer drags the status text down with it. A remote cell's preview window reads the sessions of **its own node**, never a locally same-named one. (commits 52ae1af, 22b315c, 9cf0701, 28bb61b, 23f9573, 8a8fe3d, caa9469)
23
+ - **A remote row's new-file badge reads its own node's sessions.** The count was read from the **local** sessions: a same-named session on this node attributed its files to the cell of another node, and when no same-named session existed the badge disappeared even with real new files waiting. (commit d63677b)
24
+
5
25
  ## 0.9.41 — 2026-09-23
6
26
 
7
27
  - **Cells show three honest states instead of a guess.** Managed Claude cells now feed a per-cell activity record from real lifecycle hooks, served through `/sessions`: working, stopped, or unverifiable. Where the terminal title proves nothing, the UI says "unverified" instead of inventing idle; expired data downgrades to unverified rather than a fake idle, and a process death invalidates the record instead of freezing it. (commits d319230, e389509, 4490e89, c66acce)