@aron98/load-lock 0.1.2 → 1.1.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.
- package/README.md +40 -12
- package/demo/demo.sh +1 -1
- package/dist/adapters/opencode/plugin.js +39 -18
- package/dist/adapters/opencode/tui.d.ts +61 -0
- package/dist/adapters/opencode/tui.js +358 -0
- package/dist/cli/hook.js +35 -1
- package/dist/cli/install.js +708 -24
- package/dist/cli/main.js +130 -61
- package/dist/cli/top.d.ts +7 -0
- package/dist/cli/top.js +99 -0
- package/dist/core/daemon.d.ts +25 -4
- package/dist/core/daemon.js +67 -30
- package/dist/core/persist.js +5 -12
- package/dist/core/state.js +7 -0
- package/dist/dashboard/feed.d.ts +74 -0
- package/dist/dashboard/feed.js +256 -0
- package/dist/dashboard/frame.d.ts +13 -0
- package/dist/dashboard/frame.js +95 -0
- package/dist/dashboard/view.d.ts +149 -0
- package/dist/dashboard/view.js +214 -0
- package/dist/mcp/server.d.ts +2 -1
- package/dist/mcp/server.js +54 -19
- package/dist/policy/text.d.ts +1 -1
- package/dist/policy/text.js +3 -0
- package/dist/shared/client.d.ts +10 -0
- package/dist/shared/client.js +41 -14
- package/dist/shared/protocol.d.ts +29 -0
- package/dist/shared/transport.d.ts +40 -0
- package/dist/shared/transport.js +136 -0
- package/dist/shared/wait-turn.d.ts +29 -0
- package/dist/shared/wait-turn.js +315 -0
- package/dist/test/cli.test.d.ts +1 -0
- package/dist/test/cli.test.js +99 -0
- package/dist/test/dashboard.test.d.ts +1 -0
- package/dist/test/dashboard.test.js +406 -0
- package/dist/test/hook.test.js +53 -3
- package/dist/test/install.test.d.ts +1 -0
- package/dist/test/install.test.js +658 -0
- package/dist/test/mcp.test.js +36 -1
- package/dist/test/platform.test.d.ts +1 -0
- package/dist/test/platform.test.js +193 -0
- package/dist/test/testutil.js +4 -1
- package/dist/test/tui.test.d.ts +1 -0
- package/dist/test/tui.test.js +89 -0
- package/dist/test/wait-turn.test.d.ts +1 -0
- package/dist/test/wait-turn.test.js +376 -0
- package/docs/ADAPTERS.md +5 -2
- package/docs/AGENT_GUIDE.md +34 -1
- package/docs/ARCHITECTURE.md +25 -5
- package/docs/COMPATIBILITY.md +217 -26
- package/docs/OPERATIONS.md +335 -8
- package/package.json +25 -1
- package/skills/load-lock/SKILL.md +4 -0
package/docs/COMPATIBILITY.md
CHANGED
|
@@ -11,6 +11,10 @@ Status labels mean exactly this:
|
|
|
11
11
|
against the harness's documented hook/tool JSON contracts
|
|
12
12
|
(`src/test/hook.test.ts`, `src/test/mcp.test.ts`), but the harness itself
|
|
13
13
|
was not installed during verification.
|
|
14
|
+
- **Implemented + config-tested** — installer shipped; install/uninstall
|
|
15
|
+
round-trip tested against a temp HOME and validated against the harness's
|
|
16
|
+
documented config schemas (`src/test/install.test.ts`), but the harness
|
|
17
|
+
itself was not installed during verification.
|
|
14
18
|
- **Proposed / fallback** — research-verified harness capabilities only; no
|
|
15
19
|
adapter shipped beyond the generic MCP path.
|
|
16
20
|
|
|
@@ -31,14 +35,14 @@ Status labels mean exactly this:
|
|
|
31
35
|
| Harness | MCP tools | Policy injection | Compaction restore | Idle wakeup | Async push into context | Cleanup fidelity | Overall |
|
|
32
36
|
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
33
37
|
| **OpenCode** (v2) | Native plugin, `load_lock_*` (better than MCP) | Context hook every model call | Yes (hook re-fires per model call) | Yes — `session.synthetic` at execution boundary (live-verified; never interrupts in-flight shell) | Yes (live-verified) | Full: `run_with_permit` tracked jobs + session heartbeats | **Implemented + live-verified** |
|
|
34
|
-
| **Claude Code** | MCP `mcp__load-lock__*` (user scope) | `SessionStart` hook plain-stdout context | Yes (SessionStart matcher `compact`) | Yes — `Stop` hook decision-block + async `await-offer` (`asyncRewake`) | Yes, via asyncRewake (
|
|
35
|
-
| **Codex CLI** | MCP `mcp__load-lock__*` (config.toml) | `SessionStart` + `SubagentStart` additionalContext; `~/.codex/AGENTS.md` | Yes (SessionStart matcher `compact`) | Yes — `Stop` hook `decision:"block"` continuation | Partial: async background hooks do NOT start a new turn (documented limitation); stop-hook covers turn boundaries | Full via MCP `run_with_permit` + server heartbeats | **Implemented +
|
|
36
|
-
| **Gemini CLI** | Yes (`settings.json` mcpServers) | `GEMINI.md` global (config `context.fileName`) | Via global GEMINI.md (always loaded) | No
|
|
37
|
-
| **GitHub Copilot CLI** | Yes (`copilot mcp
|
|
38
|
-
| **Cursor** | Yes (`.cursor/mcp.json
|
|
39
|
-
| **Cline** | Yes (`cline_mcp_settings.json
|
|
40
|
-
| **Roo Code** | Yes (
|
|
41
|
-
| **Goose** | Yes (`~/.config/goose/config.yaml`) | `.goosehints` (global
|
|
38
|
+
| **Claude Code** | MCP `mcp__load-lock__*` (user scope) — live-verified round-trip | `SessionStart` hook plain-stdout context (live-verified: model quoted the brief verbatim) | Yes (SessionStart matcher `compact`) — live-verified after `/compact` | Yes — `Stop` hook decision-block + async `await-offer` (`asyncRewake`), both live-verified | Yes, via asyncRewake (live-verified; the wake text itself is not rendered by the TTY, but the wake drives the full claim lifecycle) | Full via MCP `run_with_permit` + server heartbeats (live-verified incl. a job outliving the claude process) | **Implemented + live-verified** |
|
|
39
|
+
| **Codex CLI** | MCP `mcp__load-lock__*` (config.toml) | `SessionStart` + `SubagentStart` additionalContext; `~/.codex/AGENTS.md` | Yes (SessionStart matcher `compact`) | Yes — `Stop` hook `decision:"block"` continuation | Partial: async background hooks do NOT start a new turn (documented limitation); stop-hook covers turn boundaries | Full via MCP `run_with_permit` + server heartbeats | **Implemented + live-verified** (interactive TUI in Docker; exec-mode MCP blocked upstream — see Tier 2 notes) |
|
|
40
|
+
| **Gemini CLI** | Yes (`settings.json` mcpServers, first-class installer) | `GEMINI.md` global (config `context.fileName`) | Via global GEMINI.md (always loaded) | No hooks — `wait_for_turn` bounded sleep is the primary idle mechanism | No | Via MCP `run_with_permit` only | **Implemented (fallback tier, config-tested)** |
|
|
41
|
+
| **GitHub Copilot CLI** | Yes (`~/.copilot/mcp-config.json`, merge-only installer; verify with `copilot mcp list`) | `~/.copilot/copilot-instructions.md` (marked section) | Via global instructions file | Hooks reported in ecosystem content but **not verified in official docs** — none installed; `wait_for_turn` bounded sleep is the primary idle mechanism | Unverified | Via MCP `run_with_permit` only | **Implemented (fallback tier, config-tested)** |
|
|
42
|
+
| **Cursor** | Yes (project `.cursor/mcp.json`, merge-only installer) | `.cursor/rules/load-lock.mdc` (dedicated Always-apply rule file) | Rules re-apply (Always) | Yes — `stop` hook `{"followup_message":...}` continuation (hooks v1, officially documented) | No async watcher shipped; stop hook covers turn boundaries | Via MCP `run_with_permit` only | **Implemented + contract-tested** (hooks tier; not live-verified) |
|
|
43
|
+
| **Cline** | Yes (`cline_mcp_settings.json`, merge-only installer) | `~/.cline/rules/load-lock.md` (dedicated rule file) | Rules always loaded | No hooks — `wait_for_turn` bounded sleep is the primary idle mechanism | No | Via MCP `run_with_permit` only | **Implemented (fallback tier, config-tested)** |
|
|
44
|
+
| **Roo Code** | Yes (project `.roo/mcp.json` + existing global `mcp_settings.json`, merge-only installer) | `~/.roo/rules/load-lock.md` (dedicated rule file) | Rules always loaded | No hooks — `wait_for_turn` bounded sleep is the primary idle mechanism | No | Via MCP `run_with_permit` only | **Implemented (fallback tier, config-tested)** |
|
|
45
|
+
| **Goose** | Yes (`~/.config/goose/config.yaml` `extensions` block, merge-only installer) | `.goosehints` (global, marked section) | Hints always loaded | No hooks — `wait_for_turn` bounded sleep is the primary idle mechanism | No | Via MCP `run_with_permit` only | **Implemented (fallback tier, config-tested)** |
|
|
42
46
|
| **Aider** | **No MCP support** | CONVENTIONS.md / `.aider.conf.yml` | Read each run | N/A | N/A | CLI-only: same-shell `load-lock acquire ... && cmd; load-lock release ...` (manual) | Proposed (manual CLI tier) |
|
|
43
47
|
|
|
44
48
|
## How each integration tier works
|
|
@@ -52,14 +56,23 @@ Global plugin (`load-lock install --harness opencode`) registers:
|
|
|
52
56
|
- a `load-lock` skill with the full agent guide,
|
|
53
57
|
- daemon event watcher → `ctx.session.synthetic` offer messages with the
|
|
54
58
|
real claim token, delivered at execution boundaries,
|
|
55
|
-
- per-session heartbeats
|
|
59
|
+
- per-session heartbeats,
|
|
60
|
+
- the package's `./tui` export: a **live lock-status dashboard panel**
|
|
61
|
+
(issue #10) inside the opencode TUI — `/load-lock` opens the
|
|
62
|
+
`load-lock.dashboard` session panel in-window (issue #24: side panel,
|
|
63
|
+
not full-screen) with pools, holder cards, offer countdowns, queue,
|
|
64
|
+
paused, event feed, `inspect_machine`; a clickable sidebar widget
|
|
65
|
+
(`load-lock 0/3`, health-colored; `gl` as the mouse-free fallback) and
|
|
66
|
+
a home-footer `lock 1/1·Q2` indicator; and an `x` force-release flow
|
|
67
|
+
gated behind an explicit select + confirm (the panel itself is read-only
|
|
68
|
+
and never acquires a permit).
|
|
56
69
|
|
|
57
70
|
Verified live on opencode v2.0.29: plugin load, policy visible to the model,
|
|
58
71
|
tool round-trip (acquire → queued → wakeup → claim → release), execution-
|
|
59
72
|
boundary delivery without interrupting a running `sleep`, skill visible,
|
|
60
73
|
and graceful handling of a deliberately missed offer (paused → cancel).
|
|
61
74
|
|
|
62
|
-
### Tier 2 — Claude Code / Codex CLI (hooks + MCP,
|
|
75
|
+
### Tier 2 — Claude Code / Codex CLI (hooks + MCP, live-verified)
|
|
63
76
|
|
|
64
77
|
`load-lock install --harness claude-code|codex` configures the MCP server
|
|
65
78
|
(user scope) plus hooks:
|
|
@@ -76,20 +89,152 @@ and graceful handling of a deliberately missed offer (paused → cancel).
|
|
|
76
89
|
shown); the agent claims via `pending`/`claim`.
|
|
77
90
|
|
|
78
91
|
Contract tests cover all hook stdin/stdout shapes against the documented
|
|
79
|
-
harness contracts.
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
harness contracts. Claude Code is additionally **live-verified** (in Docker,
|
|
93
|
+
via `docker/run-claude-verify.sh` against the real `claude` CLI): SessionStart
|
|
94
|
+
policy brief in context at startup; the same brief re-injected after
|
|
95
|
+
`/compact` (the model quoted the fresh "load-lock now:" line, not a stale
|
|
96
|
+
copy); the full MCP round-trip acquire → queued → offer → claim →
|
|
97
|
+
`run_with_permit` → auto-release; the `Stop` hook decision-block live (async
|
|
98
|
+
watcher disabled so the stop path was exercised directly); the async
|
|
99
|
+
`await-offer` (`asyncRewake`) watcher waking an idle interactive session,
|
|
100
|
+
which then claimed and released; a `Task`-tool subagent using the MCP tools
|
|
101
|
+
and seeing the policy; and a `run_with_permit` background job that
|
|
102
|
+
outlived the `claude` process and was auto-released. One nuance: the TUI does
|
|
103
|
+
not render the async watcher's stderr wake text — the wake still works (the
|
|
104
|
+
session resumes and the claim round-trip succeeds), only the message is not
|
|
105
|
+
shown.
|
|
82
106
|
|
|
83
|
-
|
|
107
|
+
Codex CLI (0.163.0) is live-verified end-to-end in Docker
|
|
108
|
+
(`docker/verify-codex.sh`, driven through a real pty TUI session via
|
|
109
|
+
`docker/codex-pty.py`): SessionStart policy injection visible to the model,
|
|
110
|
+
MCP `status`/`acquire`/`claim`/`release` round-trip, FIFO queueing behind a
|
|
111
|
+
competing CLI holder, and Stop-hook `decision:"block"` wakeup that continues
|
|
112
|
+
the session with the claim instruction. The verification drives the real
|
|
113
|
+
interactive hook-trust review (the "Hooks need review" dialog) once —
|
|
114
|
+
`--dangerously-bypass-hook-trust` is deliberately NOT used because it forces
|
|
115
|
+
codex embedded mode, which never injects MCP tools (real users trust the
|
|
116
|
+
hooks once via `/hooks`; the installer prints this). Note: async background
|
|
117
|
+
hooks do not wake an idle Codex session — the Stop hook covers turn
|
|
118
|
+
boundaries only (verified as such).
|
|
119
|
+
|
|
120
|
+
Two upstream/provider constraints shaped the harness:
|
|
121
|
+
|
|
122
|
+
- Headless `codex exec` cannot inject MCP tools at all
|
|
123
|
+
(openai/codex#38689), so live verification drives the interactive TUI
|
|
124
|
+
through a pty.
|
|
125
|
+
- codex 0.163.0 declares MCP tools to the Responses API using the
|
|
126
|
+
`namespace` tool type; the trustedtokens/GLM endpoint silently drops
|
|
127
|
+
namespace tools, which made MCP tools invisible to the model even in the
|
|
128
|
+
TUI. The verification container therefore fronts the API with
|
|
129
|
+
`docker/codex-api-shim.js`, which rewrites namespaces to flat
|
|
130
|
+
`mcp__<server>__<tool>` function tools on the wire (request, SSE
|
|
131
|
+
response, and conversation history). This is a verification-harness
|
|
132
|
+
workaround for the provider, not a change to load-lock itself.
|
|
133
|
+
|
|
134
|
+
### Tier 2 (contract-tested) — Cursor (hooks + MCP)
|
|
135
|
+
|
|
136
|
+
Cursor 1.7 (Sept 2025) introduced hooks as a beta with an under-documented
|
|
137
|
+
JSON contract — the original reason Cursor sat on the MCP-fallback tier
|
|
138
|
+
(issue #6: "do not ship against an unstable contract"). As of 2026-10-19 the
|
|
139
|
+
official docs at https://cursor.com/docs/hooks fully document the hooks
|
|
140
|
+
system with no beta caveats (per-event reference, common input schema, exit
|
|
141
|
+
codes, config-source priority, cloud-agent support, third-party hook
|
|
142
|
+
compatibility), so the contract is now treated as stable and the adapter
|
|
143
|
+
below shipped (issue #6).
|
|
144
|
+
|
|
145
|
+
`load-lock install --harness cursor --project <dir>` wires (all
|
|
146
|
+
project-level, merge-only, reversible by uninstall):
|
|
147
|
+
|
|
148
|
+
- **MCP server** — `mcpServers.load-lock` (stdio, absolute node path) in
|
|
149
|
+
`<project>/.cursor/mcp.json` (documented project MCP config).
|
|
150
|
+
- **Stop hook** — flat hooks-v1 entry
|
|
151
|
+
`{"type":"command","command":"<node> <cli> hook cursor stop"}` in
|
|
152
|
+
`<project>/.cursor/hooks.json` (`{"version":1,"hooks":{"stop":[...]}}`;
|
|
153
|
+
`version` is added only if absent, user entries preserved).
|
|
154
|
+
- **Rule** — dedicated `<project>/.cursor/rules/load-lock.mdc` with YAML
|
|
155
|
+
frontmatter `alwaysApply: true` (note: plain `.md` files in
|
|
156
|
+
`.cursor/rules` are ignored by Cursor — the rule must be `.mdc`).
|
|
157
|
+
|
|
158
|
+
The handler's documented stop contract: stdin carries `workspace_roots`
|
|
159
|
+
(no `cwd`) and `loop_count` (number of prior stop-hook followups for the
|
|
160
|
+
conversation); stdout JSON `{"followup_message":"..."}` is auto-submitted as
|
|
161
|
+
the next user message — Cursor's loop-style idle wakeup, analogous to
|
|
162
|
+
Claude/Codex `decision:"block"`. The handler is silent unless the daemon has
|
|
163
|
+
an offer matching `workspace_roots[0]`, and silent when `loop_count > 0`
|
|
164
|
+
(Cursor's equivalent of `stop_hook_active` — prevents wakeup loops;
|
|
165
|
+
Cursor's own `loop_limit` default of 5 per script is a second backstop).
|
|
166
|
+
|
|
167
|
+
**Verification status: contract-tested, not live-verified.** The stdin
|
|
168
|
+
parsing, followup payload, loop guard and silence paths are tested against
|
|
169
|
+
the documented contract in `src/test/hook.test.ts`; the install/uninstall
|
|
170
|
+
round-trip (user config preserved, idempotent re-install, clean bare-project
|
|
171
|
+
uninstall) is tested in `src/test/install.test.ts`. No Cursor install
|
|
172
|
+
exists on the verification machine, so end-to-end behavior inside the real
|
|
173
|
+
editor is unverified — the installer output says so explicitly. Sources:
|
|
174
|
+
official docs (https://cursor.com/docs/hooks, checked 2026-10-19), 1.7
|
|
175
|
+
release announcement (forum.cursor.com, Sept 2025), GitButler deep-dive
|
|
176
|
+
(Sept 2025), InfoQ coverage (Oct 2025).
|
|
177
|
+
|
|
178
|
+
### Tier 3 — MCP-only fallback (Gemini CLI, Copilot CLI, Cline, Roo Code, Goose)
|
|
84
179
|
|
|
85
180
|
The MCP server itself carries the policy in its `instructions`, every tool
|
|
86
181
|
result surfaces pending offers (tool-boundary delivery), and
|
|
87
|
-
`inspect_machine`/`get_config`/`configure` work unchanged.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
182
|
+
`inspect_machine`/`get_config`/`configure` work unchanged.
|
|
183
|
+
|
|
184
|
+
**Every tier-3 MCP harness ships a first-class merge-only installer**
|
|
185
|
+
(Gemini CLI landed with issue #1; Copilot CLI, Cline, Roo Code
|
|
186
|
+
and Goose with issue #2). Cursor moved up to the hooks tier with its own
|
|
187
|
+
installer in issue #6 (see the Cursor section above). Each installer merges
|
|
188
|
+
into the harness's real config file
|
|
189
|
+
and never deletes anything the user wrote; `load-lock uninstall` removes
|
|
190
|
+
exactly the entries the installer added:
|
|
191
|
+
|
|
192
|
+
- **Gemini CLI** — `mcpServers.load-lock` (stdio) into
|
|
193
|
+
`~/.gemini/settings.json` + a marked policy section in
|
|
194
|
+
`~/.gemini/GEMINI.md`.
|
|
195
|
+
- **Copilot CLI** — `mcpServers.load-lock` (`type: local`) into
|
|
196
|
+
`~/.copilot/mcp-config.json` (verify with `copilot mcp list`) + a marked
|
|
197
|
+
section in `~/.copilot/copilot-instructions.md`. Hooks are reported in
|
|
198
|
+
ecosystem content but unverified in official docs, so the installer ships
|
|
199
|
+
none — no idle wakeup is claimed.
|
|
200
|
+
- **Cline** — `mcpServers.load-lock` into the MCP settings file
|
|
201
|
+
(`~/.cline/data/settings/cline_mcp_settings.json`, or the path in
|
|
202
|
+
`CLINE_MCP_SETTINGS_PATH`) + a dedicated `~/.cline/rules/load-lock.md`
|
|
203
|
+
(our own file, so uninstall is a simple delete).
|
|
204
|
+
- **Roo Code** — `mcpServers.load-lock` into `<project>/.roo/mcp.json`
|
|
205
|
+
(pass `--project`) plus every **existing** global `mcp_settings.json`
|
|
206
|
+
(VS Code globalStorage for Roo/Zoo; existing files only — the installer
|
|
207
|
+
never guesses storage paths) + a dedicated `~/.roo/rules/load-lock.md`.
|
|
208
|
+
- **Goose** — an `extensions.load-lock` stdio block (marker-tagged
|
|
209
|
+
block-mapping YAML) into `~/.config/goose/config.yaml`
|
|
210
|
+
(XDG_CONFIG_HOME respected) + a marked section in
|
|
211
|
+
`~/.config/goose/.goosehints`.
|
|
212
|
+
|
|
213
|
+
Install/uninstall round-trips for all five are tested against a temp HOME
|
|
214
|
+
and validated against the harnesses' documented config schemas
|
|
215
|
+
(`src/test/install.test.ts`), but not live-verified against real
|
|
216
|
+
harnesses — hence *config-tested*.
|
|
217
|
+
|
|
218
|
+
`load-lock install --harness generic` still prints snippets for harnesses
|
|
219
|
+
without a dedicated installer.
|
|
220
|
+
Idle policy: these harnesses get no push notifications, so the PRIMARY
|
|
221
|
+
idle mechanism is the MCP `wait_for_turn` tool — a bounded, honest sleep
|
|
222
|
+
until it is the caller's turn. Queued agents call
|
|
223
|
+
`mcp__load-lock__wait_for_turn` (optionally with `timeout_ms`, default
|
|
224
|
+
600000, capped by the machine's `maxTurnWaitMs` config) and get a
|
|
225
|
+
structured result on every path: `granted` (the offer was auto-claimed —
|
|
226
|
+
`permit_token` included), `still_queued` (timeout, with queue position
|
|
227
|
+
and holders), `paused`/`cancelled`, or `not_found` (e.g. the daemon
|
|
228
|
+
restarted). The wait itself holds no permit and consumes no capacity;
|
|
229
|
+
harness tool cancellation aborts it cleanly. (Codex CLI note: async
|
|
230
|
+
background hooks never wake an idle session there either — the Stop hook
|
|
231
|
+
covers turn boundaries only — so the same `wait_for_turn` sleep is the
|
|
232
|
+
honest pattern for Codex subagents without hook wiring.)
|
|
233
|
+
|
|
234
|
+
Still missing on this tier: automatic context re-injection — there is no
|
|
235
|
+
push channel, so a woken agent relies on tool results (which carry
|
|
236
|
+
pending offers) rather than harness messages. We do not pretend these
|
|
237
|
+
harnesses got push notifications.
|
|
93
238
|
|
|
94
239
|
### Tier 4 — Aider (manual CLI)
|
|
95
240
|
|
|
@@ -97,6 +242,28 @@ No MCP/hooks; nothing to install. Agents (or humans) use the CLI directly in
|
|
|
97
242
|
the shell: `load-lock acquire ... && load-lock run -- <cmd>` handles
|
|
98
243
|
acquire→run→release in one command line.
|
|
99
244
|
|
|
245
|
+
## Live dashboard surfaces (issue #10)
|
|
246
|
+
|
|
247
|
+
`load-lock dashboard` is portable and harness-agnostic: any integration that
|
|
248
|
+
spawns the daemon gets the same live dashboard in any terminal. The table
|
|
249
|
+
below is deliberately honest about what each harness gets **inside its own
|
|
250
|
+
UI** — where no UI surface exists, we say so rather than claim parity.
|
|
251
|
+
|
|
252
|
+
| Harness | In-harness dashboard | Also available |
|
|
253
|
+
| --- | --- | --- |
|
|
254
|
+
| **OpenCode** | Native TUI panel: `/load-lock` opens `load-lock.dashboard` **in-window** as a side panel (also opened by the `gl` binding or a click on the sidebar widget) with pools, holder cards, offer claim-window countdowns, queue, paused, event feed, `inspect_machine`; home-footer `lock 1/1` indicator on the home screen plus a clickable, health-colored `load-lock 0/3` widget in the session sidebar; `x` force-release behind select + confirm. Implemented as the package's `./tui` companion plugin (main plugin unchanged). Live-verified: opencode 2.0.29 (panel render, palette/slash command, confirm-gated force-release) and opencode 2.0.32 in a real pty (sidebar widget render, click-to-open, `gl`, in-window presentation). | `load-lock dashboard` (alias `top`) |
|
|
255
|
+
| **Claude Code** | None in-app — Claude Code has no plugin UI surface. The model can report status via the `load_lock_status` MCP tool at tool boundaries, and each `SessionStart` hook injects a one-line machine summary. | `load-lock dashboard` (any terminal) |
|
|
256
|
+
| **Codex CLI** | None in-app — same reason. `load_lock_status` MCP tool; `SessionStart`/`SubagentStart` machine summary. | `load-lock dashboard` (alias `top`) |
|
|
257
|
+
| **Gemini CLI** | None in-app (no hooks, no UI plugin surface). `load_lock_status` MCP tool at tool boundaries. | `load-lock dashboard` (alias `top`) |
|
|
258
|
+
| **Copilot CLI, Cursor, Cline, Roo Code, Goose** | None in-app. MCP `status` tool where the MCP server is configured. | `load-lock dashboard` (alias `top`) |
|
|
259
|
+
| **Aider** | None (no MCP either). | `load-lock dashboard` (alias `top`) |
|
|
260
|
+
|
|
261
|
+
All dashboard surfaces are **read-only viewers that never acquire a
|
|
262
|
+
permit**; the single admin action (force-release) is gated behind an
|
|
263
|
+
explicit confirm. Data plumbing (event-cursor resume, daemon-restart
|
|
264
|
+
reconnect, view-model shaping, frame rendering) is covered by
|
|
265
|
+
`src/test/dashboard.test.ts`.
|
|
266
|
+
|
|
100
267
|
## Session identity per harness
|
|
101
268
|
|
|
102
269
|
| Harness | Identity | Notes |
|
|
@@ -104,13 +271,37 @@ acquire→run→release in one command line.
|
|
|
104
271
|
| OpenCode | plugin context `sessionID` (also MCP `_meta` when used) | automatic |
|
|
105
272
|
| Claude Code | hooks get `session_id`; MCP tools take explicit `agent_id` | policy instructs agents to pass it |
|
|
106
273
|
| Codex | hooks get `session_id`; MCP tools take explicit `agent_id` | same |
|
|
274
|
+
| Cursor | hooks get `conversation_id` (no `cwd` — `workspace_roots[0]` identifies the request); MCP tools take explicit `agent_id` | same |
|
|
107
275
|
| Tier 3 | explicit `agent_id` argument | falls back to per-server-process id |
|
|
108
276
|
|
|
277
|
+
## Platform matrix
|
|
278
|
+
|
|
279
|
+
| Platform | Status | Notes |
|
|
280
|
+
| --- | --- | --- |
|
|
281
|
+
| **Linux** | Implemented + live-verified | Primary target; all daemon/protocol/CLI tests and the 3-worktree demo run here. `/proc`-based liveness with start-time PID-reuse defense. |
|
|
282
|
+
| **macOS** | Implemented, limitations documented | Works; liveness falls back from `/proc` start times to `kill(pid, 0)` (weaker PID-reuse defense), no cgroup limits. See OPERATIONS.md. |
|
|
283
|
+
| **Windows** | Implemented, unit-tested on Linux — **not Windows-verified** | Named-pipe transport (`\\.\pipe\load-lock`), `%LOCALAPPDATA%` state dir, `kill(pid, 0)` liveness, `taskkill /T` job-tree kills. Covered by `src/test/platform.test.ts` via platform injection; no Windows machine was available for end-to-end verification. See the Windows procedure in OPERATIONS.md. |
|
|
284
|
+
|
|
109
285
|
## Verified vs proposed — summary counts
|
|
110
286
|
|
|
111
|
-
- Live-verified: OpenCode (full adapter, including wakeup)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
(
|
|
115
|
-
|
|
116
|
-
|
|
287
|
+
- Live-verified: OpenCode (full adapter, including wakeup); Claude Code
|
|
288
|
+
(full adapter in Docker: policy injection, compact restore, Stop-hook and
|
|
289
|
+
asyncRewake wakeup paths, subagents, background-job cleanup); Codex CLI
|
|
290
|
+
(Docker, interactive TUI: policy injection, MCP round-trip, FIFO queueing
|
|
291
|
+
behind a CLI holder, Stop-hook decision-block wakeup; exec-mode MCP
|
|
292
|
+
injection blocked upstream — see Tier 2 notes).
|
|
293
|
+
- Contract-tested: Cursor (hooks-v1 stop-hook adapter + installer, tested
|
|
294
|
+
against the officially documented hooks JSON contract; no Cursor install
|
|
295
|
+
on the verification machine — see the Cursor section under Tier 2).
|
|
296
|
+
- Config-tested: Gemini CLI, Copilot CLI, Cline, Roo Code, Goose (installer
|
|
297
|
+
round-trips, temp HOME; real harnesses not installed on the verification
|
|
298
|
+
machine).
|
|
299
|
+
- Core daemon/protocol/CLI: 68 automated tests + scripted 3-worktree demo
|
|
300
|
+
(three independent agent processes, real git worktrees, one pool), including
|
|
301
|
+
9 dashboard tests (view-model shaping, event-cursor resume across a daemon
|
|
302
|
+
restart, reconnect, and a `load-lock dashboard --once` render smoke test) and
|
|
303
|
+
9 bounded-wait tests (multi-process `wait_for_turn`: FIFO wake with
|
|
304
|
+
auto-claim, timeout/pause/cancel/restart/abort paths, `maxTurnWaitMs` cap,
|
|
305
|
+
MCP snake_case round trip).
|
|
306
|
+
- Proposed (researched capabilities, generic adapter only):
|
|
307
|
+
Aider.
|