@vibelord/lanes 1.2.0 → 1.5.0

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.
Files changed (46) hide show
  1. package/package.json +1 -1
  2. package/payload/lanes/README.md +7 -5
  3. package/payload/lanes/VERSION +1 -1
  4. package/payload/lanes/bin/lanes +1091 -76
  5. package/payload/lanes/container/hooks/grok-cli-hooks.json +8 -0
  6. package/payload/lanes/container/hooks/grok-hooks.json +12 -0
  7. package/payload/lanes/container/hooks/kimi-hooks.toml +49 -0
  8. package/payload/lanes/container/lane +55 -8
  9. package/payload/lanes/container/lane-mcp +120 -22
  10. package/payload/lanes/container/lane-signal +86 -23
  11. package/payload/lanes/container/lane_core.py +524 -36
  12. package/payload/lanes/container/throttle-pulse +456 -0
  13. package/payload/lanes/docs/ARCHITECTURE.md +357 -34
  14. package/payload/lanes/docs/DESIGN.md +13 -3
  15. package/payload/lanes/docs/INSTALL.md +47 -10
  16. package/payload/lanes/docs/RUNBOOK.md +761 -12
  17. package/payload/lanes/docs/USERGUIDE.md +421 -46
  18. package/payload/lanes/holders.lock +5 -0
  19. package/payload/lanes/install/enable-docs.sh +78 -0
  20. package/payload/lanes/install/host-install.sh +39 -5
  21. package/payload/lanes/libexec/agent_state.py +604 -12
  22. package/payload/lanes/libexec/docs_store.py +995 -0
  23. package/payload/lanes/libexec/docsd.py +2010 -0
  24. package/payload/lanes/libexec/economy_poll.py +6 -2
  25. package/payload/lanes/libexec/harness_grok.py +742 -0
  26. package/payload/lanes/libexec/lanes_lib.py +143 -20
  27. package/payload/lanes/libexec/mdlite.py +575 -0
  28. package/payload/lanes/libexec/members.py +5 -0
  29. package/payload/lanes/libexec/notify.py +65 -5
  30. package/payload/lanes/libexec/sidebar.py +626 -25
  31. package/payload/lanes/libexec/statusd.py +530 -32
  32. package/payload/lanes/libexec/tokens.py +42 -9
  33. package/payload/lanes/libexec/update.py +171 -26
  34. package/payload/lanes/libexec/uploads.py +538 -0
  35. package/payload/lanes/libexec/users.py +31 -3
  36. package/payload/lanes/site/site.example.conf +4 -0
  37. package/payload/lanes/systemd/lanes-docsd.service +29 -0
  38. package/payload/lanes/web/Caddyfile +24 -1
  39. package/payload/lanes/web/README.md +86 -8
  40. package/payload/lanes/web/browser.js +2 -4
  41. package/payload/lanes/web/docs.css +52 -0
  42. package/payload/lanes/web/docs.js +36 -0
  43. package/payload/lanes/web/mobile.js +3 -2
  44. package/payload/lanes/web/upload.css +17 -0
  45. package/payload/lanes/web/upload.js +84 -0
  46. package/payload/manifest.json +5 -3
@@ -189,6 +189,14 @@ guessed variant on what may be a light background (`test_sidebar.ViewStatusScree
189
189
  | `▲` | U+25B2 | `^` | accent | mark `pinned` |
190
190
  | `✓` | U+2713 | `OK` | tone-done | mark `ok` |
191
191
  | `✗` | U+2717 | `X` | tone-urgent | mark `fail` |
192
+ | `▤` | U+25A4 | `#` | ink-dim | mark `docs` |
193
+ | `⚙` | U+2699 | `@` | ink-dim | mark `fleet-throttle` |
194
+ | `◆` | U+25C6 | `*` | ink-dim | mark `fleet-provider` |
195
+ | `▣` | U+25A3 | `[` | ink-dim | mark `fleet-host` |
196
+ | `▰` | U+25B0 | `=` | tone-done | mark `bar-usable` |
197
+ | `▱` | U+25B1 | `~` | ink-dim | mark `bar-cooling` |
198
+ | `▪` | U+25AA | `:` | tone-attention | mark `bar-benched` |
199
+ | `·` | U+00B7 | `.` | ink-faint | mark `bar-dead` |
192
200
  | `⚠` | U+26A0 | `!` | tone-attention | economy `starving` |
193
201
  | `↓` | U+2193 | `v` | tone-attention | economy `downgraded` |
194
202
  | `$` | U+0024 | `$` | ink-dim | economy `paid` |
@@ -264,7 +272,9 @@ real list scrolls where `⋮` is:
264
272
  ```
265
273
 
266
274
  Row 3 is the cursor row (▌, no ›, bold name; on the `selected` band in truecolor and 256); row 4 is the viewing lane in this slot (›, bold); row 7 is shown in
267
- viewport b (²) with two viewers (··). The same frame in ASCII mode, first rows:
275
+ viewport b (²) with two viewers (··). Once the workspace's lanes have published documents (plan W10 W7) the upload
276
+ strip reads ` ↑ uploads · ▤ docs 3 (U)`, one OSC 8 link to the docs page, and the cursor row's name links to its
277
+ lane's documents; `d` puts that link in the footer. A link changes no cell of the frame. The same frame in ASCII mode, first rows:
268
278
 
269
279
  ```
270
280
  Sakio !1 ?2 >6 v1
@@ -310,14 +320,14 @@ Each budget is pinned by a test; a budget that is not met is an open defect row,
310
320
  | Budget | Pin |
311
321
  |---|---|
312
322
  | `render(35 lanes + 5 unregistered, 36×60)` median of 50 after 5 warm-ups ≤ 2.0 ms hard (CI, loose); design target ≤ 0.9× the same-run baseline cold (today 0.459 ms here, binary-safe read) and ≤ 0.10 ms warm (row cache) — MEASURED 2026-10-04 after Task 23: cold 0.64× met; warm 0.27–0.31 ms at load ~23–30, NOT met, DEF-1510 open; the target is not raised | `test_sidebar_budget.test_desktop_render_time_and_frame` (time) + bench numbers in the commit message of every task touching `render()` |
313
- | Frame ≤ 9216 B truecolor, ≤ 5632 B in `LANES_COLOR=16`, ≤ 6144 B (16 + 512) in `LANES_COLOR=256` at 36×60, the cursor on a registrable ghost row (today, cockpit v3 P2, MEASURED 2026-10-07: truecolor 7310 B dark / 6890 B light, 16 4618 B, 256 5821 B dark / 5805 B light; 7034 / 6598 / 4618 B before P2 with the same cursor; 4330 B in both on the DEF-1417 fixture, 4297 B before it — `LANES_COLOR` is not read before Task 22) | same test, `len(frame)` |
323
+ | Frame ≤ 9216 B truecolor, ≤ 5632 B in `LANES_COLOR=16`, ≤ 6144 B (16 + 512) in `LANES_COLOR=256` at 36×60, the cursor on a registrable ghost row (today, cockpit v3 P2, MEASURED 2026-10-07: truecolor 7310 B dark / 6890 B light, 16 4618 B, 256 5821 B dark / 5805 B light; 7034 / 6598 / 4618 B before P2 with the same cursor; 4330 B in both on the DEF-1417 fixture, 4297 B before it — `LANES_COLOR` is not read before Task 22). Docs cockpit (plan W10 W7, MEASURED 2026-10-08) with its OSC 8 links on the strip and the cursor row and a 53-character origin: truecolor 7483 B, 16 4791 B, 256 5994 B dark / 5978 B light; with `d`'s footer link 7576 / 4884 / 6087 / 6071 B — no budget raised | same test, `len(frame)`; `test_the_d_footer_link_keeps_every_frame_budget` |
314
324
  | Exactly `viewports` `open()` calls of target files per render (12 over 6 renders at 2 viewports today); `subprocess.Popen`/`run` never called | `test_render_opens_only_target_files_and_never_forks` (open counter on the view dir, Popen/run patched to raise) |
315
325
  | Every emitted row ≤ 36 cells and column 36 blank on every row that is not made of the `rule` glyph alone. At Task 21 (before the one-row strip) the four upload-box rows are exempt as well — rows starting with `─ ┌ │ └`; Task 24 narrows the exemption to the rule when it removes the box | `test_no_row_exceeds_36_cells_and_column_36_is_blank` (ANSI- and OSC-stripped, binary-safe sink read, `cell_width`; and, because the strip hides positioned writes, every CHA/CUP column in the raw frame < 36 — today's maximum is 34; amendment 2026-10-04; and, because text positioned left of 36 can still run into it, every raw row walked cell by cell — `highest_cell` — writes no cell past 35, 36 on the exempt rows, over a fixture whose registrable ghosts carry both the `+` and the `×`; DEF-1417) with its detectors proven by `test_sidebar_budget_sabotage` |
316
326
  | Per tick ≤ 8 `stat()` at one viewport — registry, status, target, health, `flags/sockets-lost` (today's five), economy (Task 12), `devices/<device>.json` (Task 22), `views/<device>/<ws>.sidebar.cmd` (cockpit v3 S4: 7 → 8, a deliberate amendment — `Ctrl-Alt-/` and `Ctrl-Alt-u` hand their key over as that file instead of typing it; measured 8 on 2026-10-06) — plus one per extra viewport; zero timers added; the OSC 11 query and the focus-report request (`?1004h`) are one write at start; the sidebar.cmd file is stat()ed once more per read of keys (never per tick) | `test_tick_stats_at_most_eight_files` (one viewport); `test_theme_query_is_written_once` |
317
327
  | Upload: select timeout stays 1.0 while uploading; `dirty` only on `.progress` mtime change | `test_upload_does_not_shorten_the_tick` (Task 24) |
318
328
  | `render_mobile(35, 48×60)` ≤ 2.0 ms hard, frame ≤ 6144 B; target ≤ 0.45 ms cold / ≤ 0.10 ms warm (today 0.352 ms / 1663 B; 4058 B truecolor after cockpit v3 P2, 3991 B before) | `test_mobile_render_time_and_frame` |
319
329
  | `reload(force)` unchanged (0.14 ms at 35 / 0.39 ms at 183); fleet attention computed inside it from the loaded dict — NOT shown met: Task 24 measured 0.26–0.44 ms at 35 / 0.69–0.80 ms at 183 and Task 12 0.296 → 0.386 ms at 35 (load 30–62; the 0.14/0.39 figures are quiet-host figures), DEF-1564 open; the budget is not raised | bench in Task 24's and Task 12's commit messages; DEF-1564 |
320
- | Phone: exactly one `setInterval(`, zero `setTimeout(`, no `backdrop-filter`, a painted `box-shadow` only in `.lanes-sheet-panel` and `.zj-mobile-menu` (a `box-shadow: none` override, as on the security modal, is not paint work and is not counted); `fetch(` absent; mobile.css grows ≤ 2048 B over today's 16 934 B, mobile.js ≤ 3072 B over today's 19 102 B (measured 2026-10-03; the caps are baseline + allowance, quoted in the test); `index.html` keeps its 9 SRI-pinned upstream assets | `test_web.test_js_timers_unchanged`, `test_web.test_no_scroll_time_effects`, `test_web.test_bundle_growth`, `test_web.test_integrity_pins_untouched` |
330
+ | Phone: exactly one `setInterval(`, zero `setTimeout(`, no `backdrop-filter`, a painted `box-shadow` only in `.lanes-sheet-panel` and `.zj-mobile-menu` (a `box-shadow: none` override, as on the security modal, is not paint work and is not counted); `fetch(` absent until W9 V3's one `/enrol/site`; mobile.css grows ≤ 2048 B over today's 16 934 B, mobile.js ≤ 3072 B over today's 19 102 B (measured 2026-10-03; the caps are baseline + allowance, quoted in the test), raised since by exactly what phone shell input v2, its review fixes, the cockpit v3 sync and the docs cockpit's **Docs** row (plan W10 W7, +135 B) MEASURED: the cap equals today's 24 747 B (spec §8 has the steps); `index.html` keeps its 9 SRI-pinned upstream assets | `test_web.test_js_timers_unchanged`, `test_web.test_no_scroll_time_effects`, `test_web.test_bundle_growth`, `test_web.test_integrity_pins_untouched` |
321
331
  | Zellij: config.kdl grows by the theme + ui block only (~4 KB), `load_plugins {}` empty, no `rename-tab` from the sidebar | `test_keybinds.test_theme_block_and_plugin_free`, `test_tokens.test_generated_blocks_match_committed_files` |
322
332
  | Unit suite stays under 75 s wall (MEASURED 2026-10-04 after Task 21: 833 tests, 124–176 s at load ~30–60 — exceeded, DEF-1415 open; the budget is not raised); new pins are exact-string asserts, no sleeps; `tokens.py --check` ≤ 50 ms, contrast test ≤ 10 ms | observed in each task's run step |
323
333
 
@@ -46,6 +46,12 @@ verifies archive checksums, installs the pinned binaries, registers this checkou
46
46
  `lanes-statusd`, `lanes-sync.timer`, `lanes-ensure.timer`, `lanes-gc.timer` and `lanes-update.timer` (which updates an
47
47
  npm-installed server by itself and leaves a checkout alone, section 6). It creates an empty workspace catalog
48
48
  only if no configuration exists. Host protection, temporary-file deletion and web access remain opt-in.
49
+ It also enables and restarts the enrolment service (`lanes-enrold`) and the docs service (`lanes-docsd`), then
50
+ installs the docs page's pinned Mermaid with `install/enable-docs.sh` (a download from npm checked against both
51
+ digests in `holders.lock`, into `~/.local/share/lanes/vendor/`; a re-run finds it and downloads nothing). That step is
52
+ never fatal: the install's last lines say `Mermaid for the docs page: ok`, `skipped (<why>)` (no network, a missing
53
+ prerequisite: diagrams show as source until `sh ~/.local/share/lanes/current/install/enable-docs.sh` succeeds) or
54
+ `refused (<why>)` (a digest that is not the pin: nothing installed).
49
55
 
50
56
  ## 2. Configure workspaces and editor sync
51
57
 
@@ -112,11 +118,18 @@ account with UID 1000. With `--write` it then applies these steps in order:
112
118
  or to the title the board already has. A board that already disagrees stops the run before the container is
113
119
  touched.
114
120
  2. **Contract.** Runs `lanes install-container`: the `lane` contract, and the Lanes MCP server (`lane-mcp`) in
115
- Claude Code's `~/.claude.json` and Codex's `~/.codex/config.toml` (only where it is missing; the old file is kept
121
+ Claude Code's `~/.claude.json` and Codex's `~/.codex/config.toml`, and in Kimi Code's, Grok Build's and grok-cli's
122
+ files where those harnesses are installed (only where it is missing; the old file is kept
116
123
  as `<file>.bak-<UTC time>`). The `lane-mcp` row of the table then says whether that changed either file.
117
124
  3. **Agent hooks.** Runs `lanes hooks install --write`, first for Claude and then for Codex. Your own hooks and
118
125
  keys are kept, with a backup of each changed file. A Lanes hook group that is already installed stays where
119
- it is, even when Throttle's setup has added its own group around it.
126
+ it is, even when Throttle's setup has added its own group around it. Then for Kimi Code, Grok Build and grok-cli
127
+ (`hooks-kimi`, `hooks-grok`, `hooks-grok-cli`), each only when its home (`~/.kimi-code`, `~/.grok-build`, `~/.grok`)
128
+ is in the container, else `skipped`. Two steps run only when you name them: `--step kimi-notify` (Kimi Code's
129
+ `tui.toml` `notification_condition = "always"`) and `--step grok-build` (Grok Build installed into
130
+ `~/.grok-build` from its stable channel, before step 2, so its MCP entry and hooks land in the same run; the
131
+ channel publishes no checksum, so the receipt's `warn` row records the download's size and sha256 as
132
+ unverified). The [runbook](RUNBOOK.md#harnesses) has the details.
120
133
  4. **Throttle.** Asks the container, as UID 1000, whether it has a `throttle` and whether Throttle is configured
121
134
  there (`~/.config/throttle/config.toml` exists). Only a configured Throttle gets `throttle setup
122
135
  --install-clients`, which then runs without a person. A first setup needs one: it signs in to claude.ai with a
@@ -157,11 +170,23 @@ replaces only its own files, by rename, and never a `zmx-*` binary a running lan
157
170
  | `bin/lane-mcp` | The Lanes MCP server for the agents (left out with `--no-mcp`) |
158
171
  | `bin/zmx-*` | The pinned zmx holder (optional lanes only) |
159
172
  | `VERSION`, `hooks/`, `env.sh` | The release that installed them, the hook definitions `lanes hooks install` merges, and the shell settings new shells source |
173
+ | `bin/throttle-pulse` | The Throttle pulse (1.4.0): reads the daemon's loopback control port every 10 s (GET only) and writes `state/throttle.json`, which the host's statusd reads for the sidebar's fleet block. Installed in every container, **started only in the daemon's container** |
160
174
 
161
175
  It installs no agent hook (that is `lanes hooks install`, opt-in) and, unless `--no-mcp`, adds the agents' MCP entries
162
176
  below. A re-run after a server update (the update does it itself for every container `lanes sync` knows) brings every
163
177
  file to the installed release.
164
178
 
179
+ Since 1.4.0 `lanes install-container` also starts the Throttle pulse — but only in the container the Throttle daemon runs
180
+ in: the one `LANES_THROTTLE_CONTAINER` in the server's `~/.config/lanes/site.conf` names, else the container of the
181
+ board's Throttle tab (`tools--throttle-monitor`). There it runs `docker exec -d <container> tmux -L lanes-pulse new -d -s pulse
182
+ ~/.lz/bin/throttle-pulse --loop`, a loop on a tmux socket of its own; every other container gets the file and nothing
183
+ runs. The daemon binds its own container's loopback (DEF-1525), which the host cannot reach, so the pulse runs beside it
184
+ and the host reads its file through the container's root. statusd starts it again the same way when its file is more
185
+ than 90 s old while that container runs (at most once every 10 minutes, never on a host under critical pressure).
186
+ Without a token it reads the daemon's open routes only; spend and burn figures need the operator's one-time `lanes
187
+ throttle adopt-token <container>` ([user guide](USERGUIDE.md#fleet)). Every server update re-runs `lanes
188
+ install-container` for each container `lanes sync` knows, so the pulse file follows the installed release.
189
+
165
190
  `lanes install-container <name>` (and so `lanes onboard`, step 2 above) also gives the container's agents the Lanes
166
191
  MCP server, `~/.lz/bin/lane-mcp`. With it, the agent in a lane can do these things in its own container:
167
192
 
@@ -400,7 +425,7 @@ refuse; the Debian 12 and Ubuntu 24.04 packages are 2.6) and Tailscale on the se
400
425
  its tailnet. The web services use
401
426
  loopback ports **8082** (native Zellij) and **8083** (Lanes frontend); private HTTPS uses **8443**. The enrolment
402
427
  service every server install runs (`lanes-enrold`) listens on loopback **8184** and is reached as `/enrol/*` through
403
- the frontend.
428
+ the frontend; the docs service (`lanes-docsd`, W10) listens on loopback **8185** and is reached as `/lanes-docs/*`.
404
429
  Reserve those ports for Lanes on this host. Caddy runs as a separate user service with its admin API disabled.
405
430
 
406
431
  Once, a server administrator allows the workspace account to manage Tailscale Serve:
@@ -585,17 +610,22 @@ refused before anything is fetched. It runs in three phases. Pre-commit: the pre
585
610
  Commit: `install/services.py --install` writes the units and moves `current` (below). Post-commit, from the release
586
611
  just installed (`libexec/update.py`): `systemctl --user daemon-reload`; `lanes sync`; `systemctl --user restart
587
612
  lanes-statusd.service`; `systemctl --user try-restart` of `lanes-economy`, `lanes-notify`, `lanes-enrold`,
588
- `lanes-mobile`, `lanes-web` and `lanes-studio-host` (each restarted only when it runs; nothing is enabled); `lanes
589
- install-container <name>` for each container `lanes sync` recorded with a home volume; `lanes reload-views`; `lanes
590
- ensure --if-layout-changed` (each view whose tabs this release lays out differently is rebuilt when no client is
613
+ `lanes-docsd`, `lanes-mobile`, `lanes-web` and `lanes-studio-host` (each restarted only when it runs; nothing is
614
+ enabled), with `sh install/enable-docs.sh` right after `lanes-docsd`'s (the docs page's Mermaid, step `enable-docs`);
615
+ `lanes install-container <name>` for each container `lanes sync` recorded with a home volume (the contract files
616
+ again, the Throttle pulse among them since 1.4.0, so the pulse follows the host's release); `lanes
617
+ reload-views`; `lanes ensure --if-layout-changed` (each view whose tabs this release lays out differently is rebuilt when no client is
591
618
  attached, and otherwise marked `update ready · reload (r)` in its sidebar footer until it is rebuilt — by `r`, by
592
619
  `lanes rebuild <device>`, or by `lanes-ensure.timer` once its last client has left). Every post-commit step runs
593
620
  whatever the one before it returned, and each is stopped after 300 s. `lanes
594
621
  sync` exiting 1 — a board with an error, which it reports while keeping that board's previous lanes — is a warning
595
622
  (`WARN`, `"warning": true` in the record) that leaves the result `ok`; a sync that does not answer or cannot start is a
596
- failure like any other step. The terminal or the journal gets one line per phase and step;
623
+ failure like any other step. The Mermaid step's exit 1 (a prerequisite or the download), a download stopped after
624
+ 300 s, and exit 3 (refused: no valid pin, a digest mismatch, nothing installed) are warnings too, recorded with
625
+ `outcome` (`skipped`, `refused`) and `reason` (the script's last line), and the summary line names it (`mermaid ok`,
626
+ `mermaid skipped: <reason>`); any other status of it is a failure. The terminal or the journal gets one line per phase and step;
597
627
  `~/.local/state/lanes/update/last.log` holds the full output and `update/last.json` the outcome: `{checked_at,
598
- latest, installed, previous, result, steps: [{name, rc}], log}`, `result` being `ok`, `partial` (installed, a step
628
+ latest, installed, previous, result, steps: [{name, rc[, warning][, outcome, reason]}], log}`, `result` being `ok`, `partial` (installed, a step
599
629
  after the switch failed: exit 4), `refused` (a prerequisite, no installed release or another install said no, nothing
600
630
  changed: exit 3) or `failed` (nothing was installed: exit 1). `--update-only` takes neither `--check` nor
601
631
  `--no-start`. A full install (no `--update-only`) writes no record; a failing `lanes sync` there is a warning too, and
@@ -625,10 +655,17 @@ use the same overrides when reinstalling. `LANES_WORKSPACES` is also carried int
625
655
  when supplied; the standard configuration directory is the simplest default.
626
656
 
627
657
  After updating server code with a full install, restart the status observer with `systemctl --user restart
628
- lanes-statusd.service` (`--update-only` does that and the restarts below). The installer itself restarts the enrolment service (`lanes-enrold`) and a running web frontend (`lanes-mobile`, so
658
+ lanes-statusd.service` (`--update-only` does that and the restarts below). The installer itself restarts the enrolment service (`lanes-enrold`), the docs service (`lanes-docsd`, which answers nothing until that same pin is set — RUNBOOK "Docs service") and a running web frontend (`lanes-mobile`, so
629
659
  Caddy reads the new tree's Caddyfile; browser clients reconnect). On the first server install with enrolment, run the
630
660
  runbook's operator verification and pin its result with `lanes enrol mode request` (or `invite`) — see
631
661
  [Approve a request](#approve-a-request); a pinned mode survives this restart and every later one.
662
+ The docs service answers only once that pin says `request` (an `invite` pin, or none, refuses every docs request).
663
+ On the first server install with the docs service (operator gate 1 of the docs plan: the full `npx
664
+ @vibelord/lanes@<release> --server`, which enables `lanes-docsd` and installs Mermaid), re-run the Serve header check
665
+ so the pin is `request`; until then `lanes doctor` says `⚠ docs: refuses until the Serve header check is pinned`, and
666
+ afterwards `✓ docs: pinned`, with `lanes-docsd` answering on its port and the Mermaid pin's state (RUNBOOK "Docs
667
+ service"). Then `lanes install-container <name>` per container gives its agents `lane publish` and the
668
+ `lanes_publish` MCP tool (an update does that for every recorded container).
632
669
  If you enabled the Studio Host and selected a new `throttle-rc` or edited its config, restart
633
670
  `lanes-studio-host` (re-running `install/enable-studio-host.sh` does that, after `studio host --check`).
634
671
  If web service definitions or the pinned Zellij binary changed, restart `lanes-web` and `lanes-mobile` too;
@@ -640,7 +677,7 @@ Normal paths:
640
677
  | Path | Contents |
641
678
  | --- | --- |
642
679
  | `~/.config/lanes/` | Site profile, client settings and server workspace configuration; `update.conf` (`channel=stable`: `lanes update` follows the `lanes-stable` dist-tag) |
643
- | `~/.local/share/lanes/` | Client copy, pinned binaries, download cache, npm-staged trees (`pkg/<version>/`; on a server `lanes gc` prunes them), the `current` link to the installed tree (the one path the units, `~/.local/bin/lanes` and the view layouts name), `current.previous` (the tree `current` named before the last install that moved it) and `.install.lock` (the lock installs and unit re-renders take turns on) |
680
+ | `~/.local/share/lanes/` | Client copy, pinned binaries, download cache, the docs page's pinned Mermaid (`vendor/`, from `install/enable-docs.sh`, which every server install and update runs), npm-staged trees (`pkg/<version>/`; on a server `lanes gc` prunes them), the `current` link to the installed tree (the one path the units, `~/.local/bin/lanes` and the view layouts name), `current.previous` (the tree `current` named before the last install that moved it) and `.install.lock` (the lock installs and unit re-renders take turns on) |
644
681
  | `~/.local/state/lanes/` | Host registry, device selections, status, upload handoff and housekeeping projections; `members/`, `invites/`, `enrol-requests/` and the append-only `enrol.log` of the enrolment service; `run/<name>.tree`, the tree each service started from (`lanes version` compares them with `current`; `lanes doctor` flags each one whose process runs older code); `update/last.json` and `update/last.log`, the outcome and output of the last `--update-only` run (with `lanes update`'s last `check`, a rollback's `bad`), and `update/.lock`, the run lock every server install and update holds while it runs; `update/npx`, the npx the npm installer recorded for `lanes update`, and `locks/update.lock`, held by the one `lanes update` that runs |
645
682
  | `~/.local/state/lanes/studio-host/` | Optional Studio Host: published public key, deploy receipt, enrolment record, migrated unit text (`lanes studio-host re-key --yes` clears the key half after a revoke) |
646
683
  | `~/.config/throttle-rc/`, `~/.local/share/throttle-rc/` | Optional Studio Host config, machine key and enrolment receipt (throttle-rc's own files) |