@mmmbuto/nexuscrew 0.9.30 → 0.9.32

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,27 @@
2
2
 
3
3
  All notable changes to NexusCrew are tracked here.
4
4
 
5
+ ## Unreleased
6
+
7
+ ## 0.9.32 — 2026-09-19
8
+
9
+ - **Column widths from another window no longer land on the wrong columns.** When a deck's poll merged a remote layout that had restructured its columns (tiles moved between columns, columns fused or split), a merged column could inherit the width of a local column that no longer existed in that shape — a narrow column could become wide and the widths no longer summed to the layout. A remote column now keeps the locally resized width only when it holds exactly the same set of tiles as a local column; a restructured column keeps the width the other window chose.
10
+ - **A closure that reached only some of the peers is retried towards the others.** The retry queue used to take a closure only when *no* peer had received it, so as soon as one peer answered, an unreachable one dropped out of the queue for good — and its copy stayed open, because from that side there is no way to repair it. A closure now enters the queue with the peers that did not answer, a second delivery for the same closure merges the missing peers instead of being discarded, and a retry goes only to those, closing the entry when none is left.
11
+ - **An engine now says where its credential came from, and warns when two files disagree.** Every "compatible" source used to look the same, so a key taken from the shell file, from `ai.env` or from `secure/.env` was indistinguishable — and a value in `secure/.env` silently overrides the canonical `ai.env`. The credential's origin is now reported (source, file path, modification time and the first 8 hex characters of the SHA-256 of the value; the value itself is never shown, logged or returned), and when the same variable is defined in more than one file with a *different* value the engine says so instead of looking healthy — including the case where a stale `providers.zsh` overrides the keys files, which is the same fault with the two sides swapped. The doctor gained an `engine credentials` section, and the engine status carries the same information.
12
+ - **The credential precedence is written down.** `docs/CONFIGURATION.md` now states the real order — environment, NexusCrew store, `providers.zsh`, the keys files (`ai.env` then `secure/.env`, which wins), legacy file — and the per-engine `credentialSourcePolicy`, which until now existed in the code and in the UI but was documented nowhere.
13
+ - **Removing a model now counts the cells that override it.** The "model in use" check looked only at engines, so a cell that pins the model for its own engine did not stop the removal: the engine kept working and the cell was left pointing at a model that no longer existed, which surfaced at the next start. The refusal now names both — the engines and the cells — and the model stays declared.
14
+ - **The tmux server probe says when it could not look.** A server that is not running and a probe that was refused (a permission error on the socket, for instance) were reported as the same thing, so a missing answer read as a healthy server. They are now two distinct outcomes, the second naming its cause.
15
+ - **An engine with its own endpoint is reported ready only if that endpoint answers.** A managed engine whose address is declared by hand used to be "ready" as soon as its binary and credential were in place: a router that was switched off looked healthy, and the mistake surfaced when the cell failed to start. NexusCrew now asks the address itself (`GET /v1/models`, 1.5 s budget, one probe per engine every 30 s) and says which host and port did not answer; an endpoint that answers with an authentication challenge counts as alive, because whether the key is the right one is the client's business, not this check's.
16
+ - **A model can be tested on an engine with its own endpoint.** The model test used to answer "unknown profile" for any engine that is not in the public catalog — exactly the internal routers nobody watches. It now asks the engine's own address: the model is looked up in the endpoint's list, and where the list is absent or empty it falls back to a single-token completion, so "the model is there" and "the model is not there" stay distinguishable. The credential is used where the test runs and never appears in the outcome.
17
+ - **Custom engines now list their declared models in the pickers.** A custom profile has no builtin catalog, so the model lists stayed empty even when models were declared for the engine; the engine list now joins the profile catalog with the declared models (for `pi` custom engines the pinned model stays first in the list).
18
+
19
+ ## 0.9.31 — 2026-09-18
20
+
21
+ - **Deck layout edits survive with several windows open.** A save now rebases and retries instead of failing: the layout is merged per window, an in-flight save is awaited before the next one, a drag that ends with the pointer still down flushes its size, and a rejected save says so in the log instead of losing the change silently.
22
+ - **A model in use is refused by the engine that declares it.** Removing a model now compares against the declaring engine's keys, so an unrelated engine sharing the name no longer blocks the removal — and the rejection names the limit it hit.
23
+ - **The doctor separates the two tmux preload outcomes.** A missing `LD_PRELOAD` support and a tmux server that is not running are reported as different causes, each with its own remedy.
24
+ - **Up to 128 declared models in the fleet catalog (was 64)**; the ceiling is named in the rejection instead of a silent stop.
25
+
5
26
  ## 0.9.30 — 2026-09-16
6
27
 
7
28
  - Internal work references removed from the published package (enforced by the npm payload gate).
@@ -30,6 +30,45 @@ Runtime values follow:
30
30
  defaults < config file < environment
31
31
  ```
32
32
 
33
+ ### Engine credentials
34
+
35
+ A managed engine resolves its credential from the first source that has it, in
36
+ this order:
37
+
38
+ ```text
39
+ environment -> NexusCrew store -> user shell (providers.zsh)
40
+ -> keys files -> legacy file
41
+ ```
42
+
43
+ The keys group is **two files**, read in this order:
44
+
45
+ ```text
46
+ ~/.config/keys/ai.env -> ~/.config/secure/.env
47
+ ```
48
+
49
+ **The last one wins.** A value in `secure/.env` overrides the same variable in
50
+ `ai.env`, on purpose: it is the place to put an override without touching the
51
+ canonical file. Until now that precedence was not documented anywhere, so the
52
+ only way to notice an override was to compare the files by hand — and an engine
53
+ running on a revoked key looked exactly like an engine running on a good one.
54
+
55
+ NexusCrew now reports the origin of the credential it resolved: the source, the
56
+ file path, its modification time and the first 8 hex characters of the SHA-256
57
+ of the value. **The value itself is never shown, logged or returned.** When the
58
+ same variable is defined in more than one file with a *different* value, the
59
+ engine stays configured but says so — in the doctor's `engine credentials`
60
+ section, in the engine status `reason`, and in the `credentialConflict` field of
61
+ `GET /fleet/status`.
62
+
63
+ The order is fixed. An engine can change **where** it looks with
64
+ `credentialSourcePolicy` in its managed profile:
65
+
66
+ | Policy | Meaning |
67
+ |---|---|
68
+ | `auto` (default) | the order above |
69
+ | `environment` | only the service environment |
70
+ | `nexuscrew-store` | only the NexusCrew store (`~/.nexuscrew/credentials.json`) |
71
+
33
72
  Common overrides:
34
73
 
35
74
  | Variable | Purpose |