Repository navigation
feat(occupancy): list harness sessions from one helper per host - #208
Conversation
|
Reviewed at cfde9dc. It merges cleanly and typecheck, build and tests pass, and I found no shell or argv injection. I am not merging it because it stores a new bearer token ( (Review notes prepared with Claude Code on behalf of the maintainer.) |
cfde9dc to
c4d0b68
Compare
|
Re-verified at c4d0b68. It does not merge into main (conflicts in (Review notes prepared with Claude Code on behalf of the maintainer.) |
The dashboard polls one on-box occupancy helper per machine. OpenClaw, OpenCode, and oh-my-pi are read-only ACP metadata. Hermes and DeepSeek Harness keep private adapters. ACP timestamps stay unlabeled, and a helper auth failure stays a helper error.
c4d0b68 to
4672e2e
Compare
|
Re-reviewed at 4672e2e. It is a rebase of c4d0b68 and merges cleanly with main now (typecheck and build pass; server 1102/1103 with one load-related timeout that passes alone, frontend 798), but the occupancy code itself is unchanged, so the earlier findings still apply: (Review notes prepared with Claude Code on behalf of the maintainer.) |
…arness-observability # Conflicts: # CHANGELOG.md
|
The six failures in #208 (comment) are repaired at
The original published commit remains an ancestor. Current main Validation: occupancy tests 59/59; UTC frontend 815/815; typecheck and build pass. The broad server run is not green: 1,117 passed, 33 failed, 1 skipped, with failures in unchanged collector/GPU-clock/tool fixtures and a WebSocket timing test that passes alone. The host-timezone frontend run has one unchanged UTC-date expectation failure. Commands and limits are in the updated PR body. This repair leaves the wizard/list presentation unchanged. Independent UI interaction and screenshot QA remains unverified. Live profiles, HTTPS deployment and signal-resistant descendants were not tested. The decision on helper-token storage and operator-set URLs remains with the maintainer; nothing was deployed or merged. |
|
Re-reviewed at de49bba; it merges cleanly with main, typecheck passes and the occupancy and helper tests pass (59/59). Fixed since the last review: the adapter child has (Review notes prepared with Claude Code on behalf of the maintainer.) |
|
The six remaining findings are fixed at I merged upstream main
Validation on this tree:
This repair does not redesign the wizard/list presentation. Independent wizard/list interaction and screenshot QA remains unverified, as previously disclosed. Live harness profiles, remote HTTPS deployment, and descendant trees beyond the owned child fixtures were not exercised. The decision on helper-token storage and operator-set outbound URLs stays with the maintainer. Nothing was deployed or merged. |
|
Status at ad6a519: no new commits since the 2026-10-19 re-review; the author's latest comment lists the 8-second DSH refresh budget, the 1 MB response cap and per-adapter refresh guards. The code is not merged in this pass because it stores a new bearer token ( (Review notes prepared with Claude Code on behalf of the maintainer.) |
|
The current helper and occupancy tests pass 70/70 in a scratch worktree, while this branch has three conflicts with main 00151b5. The HTTPS policy, bounded whole-response fetch, and shared adapter deadline address earlier findings ( |
…arness-observability # Conflicts: # CHANGELOG.md # README.md # package.json
|
The updated branch now reconciles cleanly with current main, and all 70 focused helper/occupancy tests pass. The HTTPS policy, bounded response handling and shared adapter deadline address the earlier findings ( |
|
Now on main as 94cef5e (merge of the branch, authorship preserved; CHANGELOG credits @kesslerio). Approved for merge by the maintainer after the secrets/network review: helper URLs pass the allowlist and are pinned to the resolved addresses ( |
78 upstream commits: MQTT publishing (MiaAI-Lab#248), harness occupancy helpers (MiaAI-Lab#208), GPU clock cap from Settings (MiaAI-Lab#218), settings i18n foundation (MiaAI-Lab#226), configurable GPU temperature limits (MiaAI-Lab#273), Locals/Splash engines, TensorFold cache-counter fixes (MiaAI-Lab#252/MiaAI-Lab#260/MiaAI-Lab#272) and the zsh-safe remote probes (MiaAI-Lab#255/MiaAI-Lab#257). Conflict resolutions: - server/collectors/LlmProbe.js + its TensorFold test: took main's implementation, which supersedes this fork's /health `live` + /metrics work with the cache-counter precedence, running/waiting aliases, histogram validation and prefill holds. This drops the fork's parallel /metrics fetch (micro-optimisation only). - SystemCollector: main's zsh-safe find probes merged into the fork's build/parse refactor, keeping the fork-only RAPL package-power reads; _getRemoteNetwork now uses the injected executor (the merge had left the fork body calling sshExec, which made main's zsh-glob corpus test run real SSH). - OverviewPage: FleetKpis keeps the fork's placement but takes all sparks, so hidden cluster workers count in the KPI tiles (main's fix). - SparkPage: main's column layout (History in the hardware column, storage/network in the right column) over the fork's full-width History panel. - SettingsDialog: fork VulnHunter/REA opt-in toggles kept, metrics-history toggle switched to main's i18n keys. - index.js: fork vulnHunt/rea spark cleanup kept alongside MQTT removeUnit/applySettings. - CHANGELOG/README/package.json: both sides' entries kept; test globs unioned so the fork-only models/autopower/vulnhunt suites still run.
Related: #55
TL;DR
Each LLM card lists harness sessions from one occupancy helper on that machine. The dashboard reads the helper's cache on a timer. It does not open an ACP connection for each session or each poll. This is the forward-port of #55 onto current main, rebuilt around that single helper.
What Problem This Solves
Polling each harness from the dashboard would start a process per session, and an ACP client can slip into calls that create or resume a session. Hermes' ACP
session/listcan also write while it backfills a directory, and it returns no usable rows. The card still needs those sessions, with a finite age, and the dashboard should not run a shell on the box.Why This Change Was Made
One helper process per host does the discovery. OpenClaw, OpenCode, and oh-my-pi answer only ACP
initializeandsession/list. Hermes and DeepSeek Harness keep private read-only adapters. The dashboard stores the helper URL and bearer token, pins each fetch to an allowlisted address, and drops a poll that finishes after disable or reconfigure. An ACP timestamp never becomes Generating or Stalled.The helper now contains adapter startup failures, excludes its HTTP bearer from subprocess environments, and bounds ACP stdout frames and diagnostic history. Dashboard snapshots use cached configuration; malformed config retains the last valid copy, while mutations refuse to overwrite it. Helper response disconnects, timeouts and malformed envelopes fail the refresh.
User Impact
Settings, the command palette, and + Harness open a wizard: pick harnesses, one helper URL and token, then a route onto a Spark and port. Check shows coverage and a count, not titles. The card shows title, age, and context. Generating and Stalled appear only for a Hermes or DeepSeek Harness session the adapter marks running. Age is 1 hour to 14 days, default 12 hours.
Risk and Rollout
Nothing is listed until a helper is saved. The helper refuses
0.0.0.0and::, and it requires a bearer token off loopback. The dashboard rejects userinfo, redirects, and DNS answers outside the allowlist (loopback, plusSPARKDASH_HELPER_HOSTS). Helper tokens are stored apart from SSH passwords and LLM API keys. Spark monitor generation is unchanged. A helper HTTP error, including 401, comes back as a helper failure so the dashboard access-token dialog stays closed.The maintainer still needs to decide whether to accept helper-token storage and operator-set outbound URLs. This update does not deploy or merge the change.
Evidence
df6a22371d0bd7d25f9dd7486f7b8c5702a70fcdwith an ordinary merge at08442fd819ade404bb0b3513ccc1d8d59b484b7b. The previously published headad6a51978353a88aaf89356976588c1c1cc20143remains an ancestor. Conflicts inCHANGELOG.md,README.md, andpackage.jsonare resolved with current-main changes and the occupancy docs and test globs retained. Forge readback confirms this head onkesslerio/sparkDash:fm/sparkdash-pr55-harness-observability, based ondf6a223, withmergeable: true(clean). No CI checks are configured.node --test scripts/occupancy-helper/*.test.js server/occupancy/__tests__/*.test.js: 70/70 passed. Coverage includes allowed loopback reads, denied bad bearers and all-interface binds, LAN HTTP bearer refusal, DNS pinning and redirect rejection, helper mutation rate limits, corrupt configuration, a failed helper beside a healthy one, response deadlines and body caps, child secret isolation, ACP bounds and owned-child cleanup, valid and malformed helper replies, Hermes empty and cancellable database reads, and DSH timeouts and cancellation. Allowed and denied tests includeloopback may run without a token and reads do not spawn another bridge,a wrong bearer is denied and the body is not served,all-interface and unauthenticated reachable binds are refused before any spawn,a bearer is refused over LAN HTTP before any request and loopback HTTP remains allowed,forbidden DNS answers are rejected and a pinned connection ignores a later lookup, andhelper PUT and DELETE share a principal mutation budget before writes or reconfiguration. Lifecycle and isolation tests includea missing adapter binary reports unavailable without crashing the helper,DSH aborts stalled headers and bodies within its total refresh budget,DSH rejects oversized streamed JSON and cancels the reader,real DSH stalled sockets close on deadline and a later list succeeds,a stalled DSH slot cannot block later ACP refreshes and close aborts its request,optional model lookups share the list deadline instead of restarting it,an existing empty Hermes directory is unavailable,a pending Hermes database read yields the event loop,a real Hermes database child yields to timers and is killed on cancellation, andoversized stdout terminates the owned real child and permits a fresh child.npm run typecheck,npm run build, andTZ=UTC npm run test:frontendpassed. The frontend suite passed 655/655 tests in 85 files. The build still warns about large chunks.npm teststopped after the server suite returned 1,178 passed, 4 failed, and 16 skipped. Its&&prevents the frontend command from running after that failure; the frontend suite passed separately above. The 4 failures are in test files unchanged from current main: the Intel GPU fixture removes a directory withoutrecursive, two GPU-clock fake-sudo fixtures call/usr/bin/install(absent on this host), and Tool Eval's missing-uvmessage assertion fails. The broad server suite is not green.chrome-devtools-mcpruntime is unavailable here, and I did not install a package to obtain it. No live profiles or helper credentials were used. Remote HTTPS deployment and descendant trees beyond the owned-child fixtures remain untested.