@staix/agent-hub 0.32.0 → 0.33.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 (43) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +2 -2
  3. package/docs/design/bus.md +68 -2
  4. package/docs/dogfood.md +1 -0
  5. package/docs/memory.md +9 -3
  6. package/docs/operations.md +47 -14
  7. package/docs/quickstart.md +12 -2
  8. package/docs/security.md +28 -9
  9. package/docs/specs/2026-09-19-agent-hub-design.md +31 -4
  10. package/docs/specs/2026-09-20-upgrade-recovery-design.md +7 -3
  11. package/docs/verification/2026-11-06-0.33.0.md +222 -0
  12. package/docs/verification/2026-11-06-claude-implementer-2.1.319.md +57 -0
  13. package/docs/verification/2026-11-06-codex-0167-reviewer-isolation.md +56 -0
  14. package/docs/verification/2026-11-06-codex-0167-reviewer-tool-call.md +66 -0
  15. package/docs/verification/2026-11-06-kimi-251-reviewer-compat.md +88 -0
  16. package/docs/verification/2026-11-06-orca-1.4.250-cli-contract.md +50 -0
  17. package/docs/verification/2026-11-06-qwen-0268-acp.md +75 -0
  18. package/docs/verification/2026-11-06-qwen-0268-dual-output.md +44 -0
  19. package/docs/verification/claude-shell-wrapper-native.py +1 -1
  20. package/docs/verified.json +10 -10
  21. package/package.json +2 -2
  22. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  23. package/plugins/agent-hub/server.js +528 -206
  24. package/src/adapters/compat.ts +11 -11
  25. package/src/broker/protocol.ts +5 -0
  26. package/src/broker/server.ts +54 -4
  27. package/src/broker/store.ts +6 -3
  28. package/src/cli/output.ts +5 -1
  29. package/src/cli/room.ts +17 -5
  30. package/src/cli/status-lines.ts +8 -1
  31. package/src/cli/terminal-recovery.ts +37 -15
  32. package/src/hub/bus.ts +7 -0
  33. package/src/hub/daemon.ts +13 -4
  34. package/src/rooms/application.ts +15 -0
  35. package/src/rooms/commands.ts +76 -16
  36. package/src/rooms/health.ts +32 -0
  37. package/src/rooms/link.ts +267 -43
  38. package/src/rooms/remote-peer.ts +18 -3
  39. package/src/rooms/service.ts +27 -12
  40. package/src/rooms/status.ts +57 -1
  41. package/src/rooms/store.ts +20 -1
  42. package/src/rooms/wire.ts +10 -8
  43. package/src/ui/index.html +1 -1
@@ -0,0 +1,75 @@
1
+ # Qwen Code 0.26.8 ACP receipt
2
+
3
+ Date: 2026-11-06. Task #749, Refs #888, `qwen` row only. This repeats the [0.26.5 ACP receipt](2026-11-03-qwen-0265-acp.md) with the exact published `@qwen-code/qwen-code@0.26.8`, isolated installation and native controls. The [dual-output receipt](2026-11-06-qwen-0268-dual-output.md) owns the separate TUI decision.
4
+
5
+ **Decision: add exactly `0.26.8` to `COMPAT.qwen.verified`.** Every ACP leg and the reviewed optional install-lifecycle replay passed natively on macOS arm64, repeating the previous receipt's platform. The earlier Linux x86_64 run is additional evidence. No intermediate release, range or dual-output admission is inferred.
6
+
7
+ ## Artifact and isolation
8
+
9
+ The [official release](https://github.com/QwenLM/qwen-code/releases/tag/v0.26.8) and [npm artifact](https://registry.npmjs.org/@qwen-code/qwen-code/0.26.8) identify the same commit. npm installed into a new private prefix with scratch HOME, cache and tmp, empty user/global npm configs and no global installer. The installed lock's integrity matches the registry SRI. A separate private 0.26.1 prefix supplies the dual-output control; the person's global 0.26.1 installation is read-only.
10
+
11
+ | Artifact | Binding |
12
+ | --- | --- |
13
+ | npm release and upstream tag | `0.26.8`, `21ed8f1efbb351b973d96e2bc9efa78f278df99c` |
14
+ | npm integrity | `sha512-/BD+zs+VmOqInnYed3sxj7OKpBjAyZ7qoMw7Y9vLAur7QS66hsoiNAjUaON0yw6fS7WPTzN8mFZYvn3jdA3c/Q==` |
15
+ | `cli-entry.js` SHA-256 | `113efe4104a9fc66f507d34bfd6abbd896ceb77de47f4b468a0825a327fdc6a5` |
16
+ | `chunks/acpAgent-WH2KFCHG.js` SHA-256 | `bf55d693c0c9a1e682c4be2f65b74d1c7642923541cd95acdab1f7b764f60c47` |
17
+ | Primary native host | macOS arm64, Node 24.18.1, npm 11.16.0 |
18
+ | Additional host | dgx02 isolated Linux x86_64 container, Node 24.22.0, npm 11.19.1 |
19
+
20
+ npm held one lifecycle script in each Linux prefix and the fresh Mac candidate prefix, `@qwen-code/audio-capture` `install` (`node install.js`). The exact script is identical in candidate and control, SHA-256 `bf91a3db08fdaf1622a0fa938f1f0e29cef712586ca13c2b0ac2422dd3f916fd`. It invokes `node-gyp-build` for the optional microphone addon, reports a non-fatal fallback and exits 0 if no addon can be built. No script was disabled to make a probe pass. The exact scripts were replayed in both Linux prefixes and the Mac candidate prefix under their private HOME/tmp and private executable PATH, with build concurrency at two, and exited 0. Fresh ACP and permission probes after the replay passed again. A prior exit 75 deferred this leg; only the subsequent completed replay is install proof. This does not qualify microphone functionality.
21
+
22
+ Both platform runs used the same producers and a fresh temporary HOME/cwd, private `QWEN_HOME`, `QWEN_RUNTIME_DIR` and `XDG_CONFIG_HOME`, a synthetic key and fixed model with `--auth-type openai --model fixture-model --openai-base-url http://127.0.0.1:9/v1 --telemetry=false`. The ACP Node preload denied network APIs and recorded six blocked startup attempts. This is preload evidence, not kernel network isolation.
23
+
24
+ The same read-only configuration snapshot as the previous receipt covered files under the person's `~/.qwen` and `~/.pi/agent` (excluding sessions, logs, cache, install and bin, and files at least 2 MiB), plus global qwen's `cli-entry.js` and `package.json`. All 9,576 entries matched before and after both the remote runs and the later actual Mac installation/probes; aggregate manifest SHA-256 `7c8dfc2ddfbaf1fdadfbcc78881918d225aeca1393a230fdfb5e0216fcfc97a3`. No real configuration or global binary was an installation target.
25
+
26
+ ## Native ACP, no prompts
27
+
28
+ `qwen --acp --bare --advisor off` initialized protocol version 1 with `agentInfo` name `qwen-code`, title `Qwen Code` and version `0.26.8`. Only the synthetic OpenAI terminal auth method was offered. `session/new` succeeded and exposed only `fixture-model`.
29
+
30
+ The available native mode ids were `plan`, `default`, `auto-edit`, `auto` and `yolo`, initially `default`. Every transition in `default -> auto-edit -> yolo -> default` returned an acknowledgement. This proves the hub's existing three mapped ids as a subset; it adds no mapping for `plan` or `auto`. ACP prompts sent: 0. The leader exited after its owned group received SIGTERM and the producer confirmed `groupGone: true`.
31
+
32
+ ## Actual published permission handler
33
+
34
+ An exports-only scratch copy of the actual published ACP chunk appended `export{SubAgentTracker,toPermissionOptions,resolvePermissionOutcome}` beside the original, preserving relative imports. The original chunk was not edited. Synthetic client/tool/event ports invoked the native `SubAgentTracker.createApprovalHandler` directly, without a model-generated tool turn.
35
+
36
+ - The request bound the fixture session, pending tool-call id, raw input, native MCP metadata and permission progress updates.
37
+ - The exact options were `proceed_always_project` and `proceed_always_user` as `allow_always`, `proceed_once` as `allow_once`, and `cancel` as `reject_once`.
38
+ - Allow-once reached `event.respond` as `proceed_once`; a second actual callback with a cancelled outcome reached it as `cancel`.
39
+ - The real outcome helper rejected an unoffered option. No permission-fixture network attempt was recorded.
40
+
41
+ ## Actual macOS arm64 repetition
42
+
43
+ Review finding `qwen-0268-macos-evidence-missing` identified that the verified set is not platform-scoped. The Linux-only receipt did not prove admission on this Mac. A fresh Mac private prefix therefore repeated the actual published artifact, using empty npm configs and private HOME/cache/tmp with Node 24.18.1. The original global Qwen 0.26.1 binary and real homes were not launch or install targets.
44
+
45
+ Native resource admission was checked manually before this explicit native exception: 18 logical CPUs, load 4.31, CPU idle 85%, memory pressure normal (`1`), Foundation thermal state nominal (`0`), no active swap-in/out and no direct local repository build/test/install job. No source clone or local build/test gate ran. npm's held optional microphone lifecycle was reviewed and replayed in the private prefix before the ACP probes; it exited 0, without claiming microphone functionality.
46
+
47
+ The native Mac returned `qwen-code` version 0.26.8 and protocol 1, created a session, advertised the same five mode ids and fixture model, and acknowledged `default -> auto-edit -> yolo -> default`. ACP prompts sent: 0. The actual published permission handler passed allow-once, cancellation and unoffered-option refusal with the same exact options. All owned processes were gone after SIGTERM (`groupGone: true`); six startup network API calls were blocked by the unchanged preload. The 9,576-entry real-home/global-entry snapshot matched byte for byte before and after this native run.
48
+
49
+ ## Not verified
50
+
51
+ Microphone functionality, Intel macOS, a real login/provider, model-generated permission turns, model behavior, token/quota behavior and TUI qualification. The scoped claim is the native ACP/permission behavior on the exact artifact and the two explicitly named hosts above. This run does not review every upstream source change. Host changed-source checks and exact-head hosted CI are separate PR evidence. `docs/verified.json` is not restamped.
52
+
53
+ ## Evidence fingerprints
54
+
55
+ Producers and native result JSONs remain outside git under `scratchpad/temp/agent-hub-749`. Linux private npm packages remain on dgx02; the independent Mac private prefix is under `mac/prefix`, outside the global installation. The ACP producer differs from the previous one only in paths, expected version and OS temp-root binding; the permission producer changes import/output bindings. The dual v2 producer changes only the platform annotation, preserving all workload assertions and timeouts.
56
+
57
+ | File | SHA-256 |
58
+ | --- | --- |
59
+ | `qwen-acp-probe.py` | `897ff1b615f93da8cf5d0a93a5ce150eadfc55e87dce1d44625ad833c236691f` |
60
+ | `qwen-acp-result.json` | `af079bbc67b7392716583b168ba7aaf662638df769b857bbf5097f88f11336fe` |
61
+ | `qwen-permission.mjs` | `d777feb9070f254238f5ecf57f510e6af88e817b559919f65160bfd7db02a154` |
62
+ | `qwen-permission-result.json` | `958a77ea7618e0efd04a78520aadf83654e5b74a0158a05061d0bed4406d7c31` |
63
+ | `deny-network.cjs` | `361148af658dd4b65ed35308622ec99bb882ec5a25fab54581776546f139e892` |
64
+ | `replay-audio.sh` | `b4bfb8bb3206a4fc658c8b62cb55150a9d949cddea9d265dbc9732ef4cba27cd` |
65
+
66
+ Mac-specific evidence, in addition to the Linux fingerprints above:
67
+
68
+ | File | SHA-256 |
69
+ | --- | --- |
70
+ | `mac/run-native.sh` | `d32db1e1cf23a4bd0e898b93fb1db4c0f217d730e1c8c8d4eef1613111b40c75` |
71
+ | `mac/results/artifact.json` | `2c9d34a97b206a6463ebe2ee4aa1de8c73c945bf1e0de189e8bc8474deccc92d` |
72
+ | `mac/results/qwen-acp-result.json` | `fee582148aa37e826285f6d642dc4eb7cbc1469076ecd7548ecb381133b1e212` |
73
+ | `mac/results/qwen-permission-result.json` | `958a77ea7618e0efd04a78520aadf83654e5b74a0158a05061d0bed4406d7c31` |
74
+ | `mac/real-before.json` | `7c8dfc2ddfbaf1fdadfbcc78881918d225aeca1393a230fdfb5e0216fcfc97a3` |
75
+ | `mac/real-after.json` | `7c8dfc2ddfbaf1fdadfbcc78881918d225aeca1393a230fdfb5e0216fcfc97a3` |
@@ -0,0 +1,44 @@
1
+ # Qwen 0.26.8 dual-output attempt, not qualified
2
+
3
+ Date: 2026-11-06. Task #749, Refs #888, the separate `qwen-dual` row. The [ACP receipt](2026-11-06-qwen-0268-acp.md) does not qualify the TUI. This repeats the [0.26.5 attempt](2026-11-03-qwen-0265-dual-output.md) using the same corrected v2 producer, fixed OpenAI-compatible loopback responses and a private 0.26.1 matched control. No account, real credential or model inference was used.
4
+
5
+ **Decision: do not add 0.26.8 to `COMPAT["qwen-dual"].verified`.** Required Q2 did not pass. Exactly 0.26.1 stays verified for this entry, and the qwen-dual row is unchanged. This is not qualified, even though the other selected legs passed.
6
+
7
+ ## Artifact and controls
8
+
9
+ The exact candidate is the ACP receipt's private-prefix `@qwen-code/qwen-code@0.26.8`, npm/upstream commit `21ed8f1efbb351b973d96e2bc9efa78f278df99c`. The control is a separately installed private `@qwen-code/qwen-code@0.26.1`; neither control nor candidate uses the person's global prefix. Both entry files have SHA-256 `113efe4104a9fc66f507d34bfd6abbd896ceb77de47f4b468a0825a327fdc6a5`. Entry equality is not program equality; the runtime is in version-specific chunks.
10
+
11
+ The runs used a dgx02 Linux x86_64 container and Node 24.22.0. Each case had a PTY, private HOME/cwd, input/event files, scratch git project, synthetic key and deterministic loopback server. The guard positive control passed, every observed Node process loaded the guard, every owned process group was confirmed gone and every fixture root was removed. Model inference calls: 0. Preload evidence is not a kernel network sandbox or an independent audit of arbitrary native subprocess sockets.
12
+
13
+ The real macOS configuration/global-install snapshot was unchanged across these remote runs: 9,576 entries, same aggregate manifest SHA-256 `7c8dfc2ddfbaf1fdadfbcc78881918d225aeca1393a230fdfb5e0216fcfc97a3`, with the previous receipt's documented snapshot exclusions. No real HOME or global installation was targeted. The optional audio-capture install lifecycle was subsequently replayed in both private prefixes and exited 0, as tracked in the ACP receipt; it cannot make the failed Q2 a pass.
14
+
15
+ ## Observed outcomes
16
+
17
+ | Check | 0.26.8 | Matched 0.26.1 control |
18
+ | --- | --- | --- |
19
+ | Q7 version and network-guard positive control | pass, 0.26.8 | pass, 0.26.1 |
20
+ | Q2 second submit becomes a separate user turn after the first completes | **fail**: `Q2 fewer than two user events` | **fail**, same error and workload |
21
+ | Q3 shell/native MCP `can_use_tool`, allow/deny, TUI Enter, duplicate refusal and read-only control | pass | not selected |
22
+ | Q4 external cancel/SIGINT leaves the turn running; person Esc stops it and next turn works | pass, existing ceiling retained | not selected |
23
+ | Q5 unread event FIFO does not block the TUI answer | pass | not selected |
24
+ | Q6 resume id, no old-submit replay, prior context in resumed request | pass | not selected |
25
+
26
+ Q2 recorded `prematureSecondUser: false` and `userCount: 1` in both versions. The final assistant contained both submitted markers, followed by one `message_stop`; the required second distinct user event was absent. The matched failure prevents attribution as a new 0.26.8 regression. It also prevents this workload from establishing the queued-submit observation in the [original 0.26.1 receipt](2026-10-25-qwen-dual-output-t0.md). No assertion, workload or timeout was weakened to make Q2 pass.
27
+
28
+ Q3 observed actual shell and `mcp__t0__t0_echo` requests with exact input, tool-use id and permission suggestions. Allow and TUI Enter produced the one intended effect; duplicate responses were errors without a second effect. Deny left its marker absent and a later turn worked. Read-only commands ran without approval. The tiny native MCP fixture handler ran exactly once and only after allow.
29
+
30
+ Q4 bound the native TUI PID and process identity before signalling it. It records the same report-only cancellation ceiling, not permission for the hub to signal a person's terminal. Q6 preserved the session id, rotated the event file like the host adapter, retained old input without replay and observed the prior context token in a resumed fixed provider request; model recall quality is unverified.
31
+
32
+ ## Not verified
33
+
34
+ Q2 on any version with this producer, macOS and other platforms, real account/provider, model choices/quality, token/quota behavior, and a new qwen-dual admission. A scoped native result does not review every upstream source change. Explicit failed and unselected legs remain as recorded. Host tests and exact-head hosted CI are separate PR evidence. No TUI adapter, queue, cancellation policy, real install or existing 0.26.1 admission changed.
35
+
36
+ ## Evidence fingerprints
37
+
38
+ The corrected producer and JSON results remain outside git under `scratchpad/temp/agent-hub-749`.
39
+
40
+ | File | SHA-256 |
41
+ | --- | --- |
42
+ | `qwen-dual-probe-v2.py` | `57714a102ce61083eda04dd092bc837704362428c133f34f6772744508965f93` |
43
+ | `qwen-dual-0268-result.json` | `c52155b7338bce515c77aaad1582dc39aed71cca62aebc53eb851b226b073e0a` |
44
+ | `qwen-dual-0261-control-result.json` | `867a223826a4e6e8fe31934269649bee90dce26478044a0ef5534202f190211e` |
@@ -68,7 +68,7 @@ results=[]
68
68
  for raw_binary in args.claude:
69
69
  binary=pathlib.Path(raw_binary).resolve(); identity=ROOT/('identity-'+binary.name); identity.mkdir()
70
70
  version=subprocess.run([str(binary),'--version'],env={'HOME':str(identity),'CLAUDE_CONFIG_DIR':str(identity/'config'),'PATH':'/usr/bin:/bin'},capture_output=True,text=True,timeout=10)
71
- assert version.returncode==0 and version.stdout.strip().split()[0] in ('2.1.309','2.1.310','2.1.314','2.1.316','2.1.318'),(version.returncode,version.stdout)
71
+ assert version.returncode==0 and version.stdout.strip().split()[0] in ('2.1.309','2.1.310','2.1.314','2.1.316','2.1.318','2.1.319'),(version.returncode,version.stdout)
72
72
  label=version.stdout.strip().split()[0]; digest=sha(binary)
73
73
  for mode in ('context','normalized'):
74
74
  d=ROOT/(label+'-'+mode); d.mkdir(); home=d/'home';home.mkdir(); work=d/"work 'quoted'";work.mkdir();(work/'sub').mkdir()
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "documents": {
4
4
  "README.md": {
5
- "verifiedAgainst": "2f4c372a6ce48dc01acb4a002f6a46e9557cbd17",
5
+ "verifiedAgainst": "ab8ae6f400d741ee9060d3087489e59996a72086",
6
6
  "paths": [
7
7
  "package.json",
8
8
  "src/",
@@ -11,14 +11,14 @@
11
11
  ]
12
12
  },
13
13
  "docs/security.md": {
14
- "verifiedAgainst": "2f4c372a6ce48dc01acb4a002f6a46e9557cbd17",
14
+ "verifiedAgainst": "ab8ae6f400d741ee9060d3087489e59996a72086",
15
15
  "paths": [
16
16
  "src/",
17
17
  "templates/"
18
18
  ]
19
19
  },
20
20
  "docs/operations.md": {
21
- "verifiedAgainst": "2f4c372a6ce48dc01acb4a002f6a46e9557cbd17",
21
+ "verifiedAgainst": "ab8ae6f400d741ee9060d3087489e59996a72086",
22
22
  "paths": [
23
23
  "package.json",
24
24
  "src/",
@@ -35,7 +35,7 @@
35
35
  ]
36
36
  },
37
37
  "docs/quickstart.md": {
38
- "verifiedAgainst": "2f4c372a6ce48dc01acb4a002f6a46e9557cbd17",
38
+ "verifiedAgainst": "ab8ae6f400d741ee9060d3087489e59996a72086",
39
39
  "paths": [
40
40
  "package.json",
41
41
  "src/",
@@ -43,7 +43,7 @@
43
43
  ]
44
44
  },
45
45
  "docs/agent-notes/adapters.md": {
46
- "verifiedAgainst": "2f4c372a6ce48dc01acb4a002f6a46e9557cbd17",
46
+ "verifiedAgainst": "10efdc8b0ea114ae858fff4ede65de09f6c55604",
47
47
  "paths": [
48
48
  "src/adapters/",
49
49
  "src/pi/",
@@ -93,7 +93,7 @@
93
93
  ]
94
94
  },
95
95
  "docs/agent-notes/budget.md": {
96
- "verifiedAgainst": "2f4c372a6ce48dc01acb4a002f6a46e9557cbd17",
96
+ "verifiedAgainst": "10efdc8b0ea114ae858fff4ede65de09f6c55604",
97
97
  "paths": [
98
98
  "src/hub/budget.ts",
99
99
  "src/cli/statusline-tee.ts",
@@ -117,7 +117,7 @@
117
117
  ]
118
118
  },
119
119
  "docs/agent-notes/bus.md": {
120
- "verifiedAgainst": "2f4c372a6ce48dc01acb4a002f6a46e9557cbd17",
120
+ "verifiedAgainst": "10efdc8b0ea114ae858fff4ede65de09f6c55604",
121
121
  "paths": [
122
122
  "src/hub/bus.ts",
123
123
  "src/hub/envelope.ts",
@@ -132,7 +132,7 @@
132
132
  ]
133
133
  },
134
134
  "docs/agent-notes/daemon.md": {
135
- "verifiedAgainst": "2f4c372a6ce48dc01acb4a002f6a46e9557cbd17",
135
+ "verifiedAgainst": "ab8ae6f400d741ee9060d3087489e59996a72086",
136
136
  "paths": [
137
137
  "src/hub/daemon.ts",
138
138
  "src/hub/control-client.ts",
@@ -243,7 +243,7 @@
243
243
  ]
244
244
  },
245
245
  "docs/agent-notes/tasks.md": {
246
- "verifiedAgainst": "2f4c372a6ce48dc01acb4a002f6a46e9557cbd17",
246
+ "verifiedAgainst": "10efdc8b0ea114ae858fff4ede65de09f6c55604",
247
247
  "paths": [
248
248
  "src/hub/tasks.ts",
249
249
  "src/hub/board.ts",
@@ -291,7 +291,7 @@
291
291
  ]
292
292
  },
293
293
  "docs/agent-notes/tests.md": {
294
- "verifiedAgainst": "4ad77748c96383bdef8e55a11ff53808a1359500",
294
+ "verifiedAgainst": "ab8ae6f400d741ee9060d3087489e59996a72086",
295
295
  "paths": [
296
296
  "test/",
297
297
  "scripts/check.sh",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staix/agent-hub",
3
- "version": "0.32.0",
3
+ "version": "0.33.0",
4
4
  "description": "Native multi-agent hub: Claude Code, Codex, Kimi Code, Pi and local inference as peers in one project",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -17,7 +17,7 @@
17
17
  "bun": ">=1.4.2"
18
18
  },
19
19
  "dependencies": {
20
- "@staix/agent-mem": "0.21.0"
20
+ "@staix/agent-mem": "0.22.1"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@modelcontextprotocol/sdk": "^1.27.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-hub",
3
- "version": "0.32.0",
3
+ "version": "0.33.0",
4
4
  "description": "Channel between Claude Code and the agent-hub daemon: peer messages from Codex, Kimi and the local worker arrive as channel events; hub_send replies.",
5
5
  "author": {
6
6
  "name": "Young Joon Lee",