@staix/agent-hub 0.30.0 → 0.32.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 (130) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +13 -7
  3. package/docs/agent-notes/README.md +1 -0
  4. package/docs/agent-notes/adapters.md +5 -2
  5. package/docs/agent-notes/budget.md +1 -0
  6. package/docs/agent-notes/bus.md +11 -4
  7. package/docs/agent-notes/daemon.md +16 -8
  8. package/docs/agent-notes/local-worker.md +1 -0
  9. package/docs/agent-notes/tasks.md +7 -3
  10. package/docs/agent-notes/tests.md +6 -4
  11. package/docs/design/adapters.md +52 -0
  12. package/docs/design/agent-hub-architecture.md +46 -0
  13. package/docs/design/bus.md +178 -1
  14. package/docs/design/task-board.md +82 -0
  15. package/docs/dogfood.md +23 -4
  16. package/docs/events.md +3 -0
  17. package/docs/memory.md +17 -1
  18. package/docs/operations.md +355 -78
  19. package/docs/profiles.md +35 -0
  20. package/docs/quickstart.md +24 -5
  21. package/docs/security.md +178 -60
  22. package/docs/specs/2026-09-19-agent-hub-design.md +127 -14
  23. package/docs/specs/2026-09-19-multi-project-design.md +7 -2
  24. package/docs/verification/2026-11-04-1171-channel-client-evidence.md +31 -0
  25. package/docs/verification/2026-11-05-0.31.0.md +182 -0
  26. package/docs/verification/2026-11-05-claude-implementer-2.1.318.md +70 -0
  27. package/docs/verification/2026-11-05-hardcoded-values-classification-rules.md +311 -0
  28. package/docs/verification/2026-11-05-hardcoded-values-ratchet.md +55 -0
  29. package/docs/verification/2026-11-06-0.32.0.md +149 -0
  30. package/docs/verification/2026-11-06-rooms-presence-cost.md +152 -0
  31. package/docs/verification/claude-shell-wrapper-native.py +1 -1
  32. package/docs/verified.json +14 -14
  33. package/package.json +3 -4
  34. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  35. package/plugins/agent-hub/server.js +4393 -3609
  36. package/src/adapters/acp.ts +5 -4
  37. package/src/adapters/channel-peer.ts +72 -3
  38. package/src/adapters/claude-channel-evidence.ts +52 -0
  39. package/src/adapters/claude-channel.ts +61 -18
  40. package/src/adapters/claude-implementer.ts +29 -7
  41. package/src/adapters/claude-print-child.ts +12 -2
  42. package/src/adapters/codex-appserver.ts +13 -12
  43. package/src/adapters/compat.ts +3 -3
  44. package/src/adapters/definitions/builtin-metadata.ts +13 -13
  45. package/src/adapters/definitions/qwen.ts +1 -0
  46. package/src/adapters/local-worker.ts +61 -18
  47. package/src/adapters/pi.ts +48 -6
  48. package/src/adapters/registry-types.ts +12 -0
  49. package/src/adapters/registry.ts +2 -0
  50. package/src/adapters/reviewer-print.ts +50 -11
  51. package/src/broker/server.ts +44 -13
  52. package/src/broker/store.ts +38 -8
  53. package/src/cli/answer-args.ts +50 -0
  54. package/src/cli/attention.ts +17 -2
  55. package/src/cli/backlog-return-args.ts +37 -0
  56. package/src/cli/console-question.ts +110 -0
  57. package/src/cli/console-state.ts +78 -17
  58. package/src/cli/console.ts +54 -1
  59. package/src/cli/handoff-args.ts +15 -5
  60. package/src/cli/handoff-output.ts +15 -2
  61. package/src/cli/help.ts +8 -5
  62. package/src/cli/identity.ts +13 -3
  63. package/src/cli/main.ts +128 -16
  64. package/src/cli/memory.ts +107 -3
  65. package/src/cli/output.ts +29 -6
  66. package/src/cli/pet.ts +4 -4
  67. package/src/cli/results-args.ts +30 -0
  68. package/src/cli/room.ts +20 -10
  69. package/src/cli/runtime-version-warning.ts +50 -0
  70. package/src/cli/status-lines.ts +41 -1
  71. package/src/cli/tail-render.ts +1 -0
  72. package/src/cli/upgrade-interactive.ts +14 -2
  73. package/src/hub/action-class.ts +9 -1
  74. package/src/hub/board.ts +369 -18
  75. package/src/hub/bus.ts +511 -53
  76. package/src/hub/completion-detail.ts +50 -0
  77. package/src/hub/completions-store.ts +168 -0
  78. package/src/hub/completions.ts +120 -0
  79. package/src/hub/config-apply.ts +7 -5
  80. package/src/hub/config-reload.ts +10 -1
  81. package/src/hub/control-client.ts +40 -4
  82. package/src/hub/daemon.ts +1576 -139
  83. package/src/hub/delivery-failure.ts +14 -0
  84. package/src/hub/delivery-hints.ts +14 -4
  85. package/src/hub/delivery-journal.ts +751 -42
  86. package/src/hub/delivery-superseded.ts +4 -1
  87. package/src/hub/envelope.ts +3 -3
  88. package/src/hub/events.ts +6 -0
  89. package/src/hub/handoff.ts +145 -6
  90. package/src/hub/hub-tools.ts +56 -7
  91. package/src/hub/manager.ts +59 -3
  92. package/src/hub/memory-policy.ts +44 -1
  93. package/src/hub/memory-sync-policy.ts +109 -0
  94. package/src/hub/memory-sync-state.ts +145 -0
  95. package/src/hub/no-writes.ts +1 -1
  96. package/src/hub/operational-settings.ts +11 -2
  97. package/src/hub/operational-view.ts +12 -1
  98. package/src/hub/peers.ts +25 -2
  99. package/src/hub/planning.ts +6 -1
  100. package/src/hub/question-desk.ts +201 -0
  101. package/src/hub/question-detach.ts +6 -0
  102. package/src/hub/questions.ts +260 -0
  103. package/src/hub/research-evidence.ts +106 -0
  104. package/src/hub/restart.ts +14 -0
  105. package/src/hub/review-anchor.ts +181 -0
  106. package/src/hub/review-brief.ts +13 -0
  107. package/src/hub/review-comments.ts +115 -0
  108. package/src/hub/review-findings.ts +7 -2
  109. package/src/hub/review-material.ts +76 -0
  110. package/src/hub/routing.ts +3 -1
  111. package/src/hub/task-sweep.ts +2 -0
  112. package/src/hub/tasks.ts +577 -63
  113. package/src/memory/capture.ts +5 -2
  114. package/src/pet/config.ts +25 -13
  115. package/src/rooms/commands.ts +61 -16
  116. package/src/rooms/link.ts +338 -36
  117. package/src/rooms/liveness.ts +11 -0
  118. package/src/rooms/remote-peer.ts +186 -19
  119. package/src/rooms/service.ts +475 -35
  120. package/src/rooms/status.ts +8 -1
  121. package/src/rooms/store.ts +447 -65
  122. package/src/rooms/wire.ts +24 -6
  123. package/src/ui/index.html +142 -9
  124. package/src/ui/needs.ts +10 -4
  125. package/src/ui/plugin-questions.ts +56 -0
  126. package/src/ui/plugin-results.ts +81 -0
  127. package/src/ui/plugin.ts +207 -27
  128. package/src/pet/window.html +0 -114
  129. package/src/pet/window.jxa.js +0 -122
  130. package/src/pet/window.ts +0 -154
@@ -803,7 +803,9 @@ atomically install that candidate against its persisted pin. Replaying an old
803
803
  candidate must never reset the minimum epoch or a grace deadline.
804
804
 
805
805
  A frame's public header is `{v,type,room,epoch,sender,recipients,seq}` plus nonce,
806
- ciphertext and signature. Recipients are hub fingerprints, not local peer ids.
806
+ ciphertext and signature. Presence may add the signed optional `ephemeral: true`
807
+ header (#1204 T1); every other value for that optional field refuses. Recipients
808
+ are hub fingerprints, not local peer ids.
807
809
  The body is opaque encrypted bytes, including any eventual local addressing,
808
810
  kind, trace and text. Frame AAD is exactly UTF-8 `room|epoch|sender|seq`. A
809
811
  sender-specific AES key is HKDF-derived from the epoch root and room/epoch/sender/
@@ -974,7 +976,14 @@ survive queue ACKs/restart: the last accepted digest or an identical retained ol
974
976
  packet is idempotent without requeueing; conflicting or
975
977
  unknown lower sequences refuse. FIFO uses SQLite admission row order, never lexical
976
978
  sequence strings or clock ties. Full queues refuse new packets without evicting
977
- accepted ones. Prior-epoch grace may expire a packet before its ordinary TTL.
979
+ accepted durable ones. Ephemeral presence replaces only prior ephemeral rows of
980
+ that sender and retains only currently ready recipients; disconnect/restart
981
+ removes those recipients, while sender floors and durable work remain. The same
982
+ queue/byte caps still apply. A frame-level `queue_full` includes its verified
983
+ digest. Links retain the sealed frame and retry after 250 ms, doubling to 30 s,
984
+ with one frame awaiting storage acceptance so later sequences cannot overtake it.
985
+ Applications stay in the local outbox; T2 owns receipt persistence and deadline/
986
+ restart replay changes. Prior-epoch grace may expire a packet before its ordinary TTL.
978
987
 
979
988
  One packet per recipient socket is in flight. `{v:1,type:"received",digest}` removes
980
989
  only that identity from the packet's remaining recipients, then returns
@@ -1114,6 +1123,16 @@ not project config or synced memory. A hub stop closes links and retains members
1114
1123
  A person may explicitly import a pinned signed roster to reactivate a left room;
1115
1124
  automatic link traffic cannot reactivate it.
1116
1125
 
1126
+
1127
+ The optional ephemeral field is used only after an opted-in connection receives
1128
+ `ephemeral: true` in the broker ready control. The upgrade header is
1129
+ `x-agent-hub-ephemeral: 1`; brokers preserve the old closed ready shape for
1130
+ clients that do not opt in. Missing advertisement means legacy presence frames,
1131
+ with dedupe/backoff still active. The broker withholds ephemeral frames from older member hubs
1132
+ until upgraded; application chat stays wire-compatible. See the [compatibility
1133
+ ceiling](../design/bus.md#room-wire-compatibility-1204-t1); #1204 T4 owns full codec
1134
+ feature negotiation.
1135
+
1117
1136
  ### Durable state and outbound link
1118
1137
 
1119
1138
  `<hub-state>/rooms/rooms.db` is schema version 1, SQLite DELETE/EXTRA with exclusive
@@ -1152,9 +1171,12 @@ at most 8 pending packets/2 MiB per link, 1 MiB packet/backpressure limits and a
1152
1171
  minutes and do not block local work. Stop, leave, replacement and rotation fence
1153
1172
  all awaited work by link generation.
1154
1173
 
1174
+ With latest-per-sender coalescing, A awaiting C can have its queued request replaced by A's broadcast reply to B. T3's periodic idle refresh requests another observation without waiting for a state change or reconnect; per-(sender,recipient) coalescing remains a possible stronger transport design. Legacy brokers retain the state-change/reconnect behavior without periodic refresh.
1175
+
1155
1176
  Presence is an encrypted, signed frame containing only exposed peer ids and closed
1156
1177
  idle/busy/paused/offline states. It is sent on connection and coalesced peer-state
1157
- changes, never titles, bodies, private task context or credentials. Unknown payload
1178
+ changes, skipping identical snapshots except explicit peer refresh exchanges,
1179
+ never titles, bodies, private task context or credentials. Unknown payload
1158
1180
  types and unexposed ids refuse before replay commit. Broker ACKs are transport
1159
1181
  facts only. A canonical room/recipient-bound frame that is refused or stale is
1160
1182
  recorded in a durable metadata-only drop ledger before transport retirement ACK.
@@ -1256,15 +1278,20 @@ exposed local peer's queue**. It does not mean native or model execution. Person
1256
1278
  views say **completed (admitted)**. Broker `stored` means accepted ciphertext
1257
1279
  only; a transport retirement ACK is not application completion.
1258
1280
 
1259
- Schema3 of the private `rooms.db` migrates schema1/2 without replacing identity,
1281
+ Schema5 retains a nullable canonical outgoing content hash. Cross-root reuse of
1282
+ a retained application requires matching content and peer/recipient, no disposition
1283
+ or permanent hold, and inherited creation/expiry times; legacy NULL refuses it.
1284
+ Schema5 of the private `rooms.db` migrates schema1 through 4 without replacing identity,
1260
1285
  pins, counters, floors or retained traffic. A receiver commits its crypto inbox,
1261
1286
  then application `pending -> dispatching` before publishing into the separate
1262
1287
  Bus journal. A crash or failure in that cross-DB publication window becomes
1263
- `needs_review`, with no automatic republish or fabricated receipt. Sender
1264
- `dispatching`/`accepted` rows become `needs_review` at restart. A same-process
1265
- reconnect drains never-handed offline queues once. A late signed receipt is kept
1266
- as evidence on `needs_review` and shown with the person's disposition view; it
1267
- never auto-settles. Known safe refusals retain the Bus's existing poison policy.
1288
+ `needs_review`, with no automatic receiver republish or fabricated receipt.
1289
+ Sender `dispatching`/`accepted` rows recover from validated durable intent under
1290
+ the same application and delivery ids, retaining their original queue expiry.
1291
+ A valid late signed receipt may settle an unresolved ordinary sender hold;
1292
+ invocation uncertainty remains person-settled. Person dispositions and invalidated
1293
+ recipient bindings remain authoritative. Signed
1294
+ remote safe refusals are terminal; native poison-envelope policy is unchanged.
1268
1295
 
1269
1296
  Signed seq/floors are the permanent primary replay protection. Duplicate seqs
1270
1297
  are retired without a second admission; a known identical completed application
@@ -1275,6 +1302,9 @@ oldest settled rows are evicted first. Pending, dispatching and unresolved
1275
1302
  `needs_review` are never evicted. An all-unsettled cap refuses with the room and
1276
1303
  count. Outside retention or after settled eviction, there is no historical
1277
1304
  app-id dedupe claim; an old signed frame is still refused by its seq floor.
1305
+ Automatic resend can reach this settled-eviction ceiling and repeat admission
1306
+ under a fresh ciphertext sequence: exactly once within dedupe ceiling. Pinning
1307
+ retryable identities or #737 receipt confirmation is the upgrade path.
1278
1308
 
1279
1309
  The trace high-water mark is kept for the tombstone retention (30 days / 10,000
1280
1310
  per room, settled rows evicted first); outside it there is no historical trace
@@ -1288,16 +1318,17 @@ Offline Bus queues count toward the 200-per-room ceiling before transport starts
1288
1318
  `hub_send` refuses beyond it. Original host deadlines survive handoff and restart.
1289
1319
  Unknown legacy deadlines fail closed to `needs_review`. Machine-local
1290
1320
  `rooms.ack_timeout_s` defaults to 600 (1..86,400); `rooms.queue_ttl_h` defaults to
1291
- 24 (1..168). A single deadline-driven host timer handles ack/queue expiry. No
1292
- uncertain work is silently retried. Explicit terminal-history retries without
1321
+ 24 (1..168). A single deadline-driven host timer handles ACK retries and queue
1322
+ expiry. Only validated durable sender intent is retried automatically; missing
1323
+ or corrupt local evidence remains held. Explicit terminal-history retries without
1293
1324
  recipient proof refuse; the person can author a fresh message deliberately.
1294
1325
  An expired or missing original enqueue deadline also refuses a person retry
1295
1326
  before any disposition is recorded; a retry never invents a fresh TTL.
1296
1327
 
1297
1328
  The ACK deadline starts at durable application handoff, before a broker `stored`
1298
- reply, and is never extended by that reply. An unstored frame therefore becomes
1299
- `needs_review` within the same ACK timeout instead of holding the peer for the
1300
- queue TTL. Known pre-admission capacity or journal-unavailable refusals retain
1329
+ reply, and is never extended by that reply. Its expiry schedules another attempt
1330
+ under the same application id, without resetting the original queue TTL. Queue
1331
+ expiry or a permanent refusal ends automatic sending. Known pre-admission capacity or journal-unavailable refusals retain
1301
1332
  their pending plaintext for the next online/disposition retry without preventing
1302
1333
  later room packets and receipts from being processed. Status reads apply no
1303
1334
  disposition. Settled chat plaintext rows are pruned independently of presence
@@ -2782,6 +2813,12 @@ push `accepted` and show none of them.
2782
2813
  sources add protocol 15 (0.12.17 through 0.12.19); the transition from a real
2783
2814
  0.12.19 hub is not yet proven.
2784
2815
 
2816
+ ## Amendment: inherited Claude channel marker requires direct-parent evidence (issue #1171)
2817
+
2818
+ - `AGENTHUB_CHANNEL=1` alone does not enable push. Claude Code child processes, including `daemon run` and `bg-spare`, inherit it without the development-channel flag. The plugin's direct parent must have a bounded, readable `ps -ww` row whose leading argv tokens are `claude --dangerously-load-development-channels` and one exact supported target (`plugin:agent-hub@agent-hub` or `server:agent-hub`). Print/background/daemon forms, a repeated development-channel flag, unreadable or malformed output, a changed parent pid, and unknown targets fail closed to tools-only.
2819
+ - The classifier is conservative because `ps` renders a flattened command line; matching is restricted to the prefix and remaining tokens are checked for known mode-changing forms. This is same-user process observation, not authentication. No client-side Claude channel capability was found in the inspected Claude Code 2.1.318 client path, and the server's own advertised capability is not proof. Unknown evidence keeps messages queued for `hub_inbox`.
2820
+ - `status.json` reports `attachMode` and a closed `attachEvidence` label for an attached Claude peer; human `ahub status` shows the same pair. Older clients that omit the evidence field retain their prior attachment behavior and display `unreported`.
2821
+
2785
2822
  ## Amendment: channel queue visibility and explicit pull (issue #493)
2786
2823
 
2787
2824
  - A channel session's `hub_inbox` reads the daemon queue through the same
@@ -3945,6 +3982,8 @@ run has no hub command lineage.
3945
3982
 
3946
3983
  ## Amendment: standalone attention window (#391 Task B, supersedes #280 dashboard pet)
3947
3984
 
3985
+ Historical surface, retired by #1012. Current presentation contract: [console surfaces](../design/agent-hub-architecture.md#console-presentation-surfaces).
3986
+
3948
3987
  The #280 phase-4 dashboard pet is replaced by an optional standalone macOS JXA
3949
3988
  window. Task B adds the window first; #391 Task A removes the existing in-page
3950
3989
  character and retains shared attention counts/navigation. Terminal characters
@@ -6452,3 +6491,77 @@ Each pack supplies criterion ids in its rubric and exactly one advisory check en
6452
6491
  ## Amendment: research campaigns, experiment receipts and runner attestation (#930, #932, #1018)
6453
6492
 
6454
6493
  The implementation contract for #929 R1 and R3 and for #1018 is `docs/specs/2026-11-01-research-campaigns-design.md`: campaign, protocol, attempt and receipt schemas and bounds; the provenance levels `declared`, `host-observed`, `runner-attested` and `person-attested`; the Board tables; the person-only activation, attestation and runner registration; the `ahub study` and `hub_study_*` / `hub_experiment_*` wire names; the `research_records` recovery feature; and the delivery slices (#596 to #602). Slices that must differ amend that document in their own PR.
6494
+
6495
+ ## Amendment: anchored review packages (#1056)
6496
+
6497
+ The current contract is recorded in [Task Board](../design/task-board.md#anchored-review-packages-1056). Optional finding anchors use the published acon review shape, with stricter hub UTF-8 write bounds. Person drafts are board-local until one explicit console-authorized Send creates one immutable package and one count-only history entry. Owner completion can claim sent comment IDs resolved without claiming person verification. Placement is recomputed over guarded task-scoped Git/projection material; stored anchors never move.
6498
+
6499
+ The acon plugin uses `ActionMeta` and `host.ui.review` from the published DOM-free 0.1.3 contract as types only; there is no new runtime dependency or renderer. A private/PII view withholds text, and trusted package markers exclude quote/body content from logs, tails, incoming labels and memory capture without making a public task private. Recovery sections are optional for older snapshots. The owner's live document package-format confirmation remains a separate manual check; fixture and code evidence do not claim that confirmation.
6500
+
6501
+ ### Receipt publication ordering (#1204 T2)
6502
+
6503
+ A chat ciphertext transport ACK follows the signed receipt ciphertext's local
6504
+ durable RoomStore outbox commit. The receipt replays after reconnect or restart
6505
+ until the broker confirms storage. Waiting for broker storage before the chat ACK
6506
+ would deadlock at capacity one. No receipt or native completion is inferred from
6507
+ socket send alone.
6508
+ ACK after durable local commit of either the receipt or the inbox entry.
6509
+ Deferred application admission retains the durable crypto inbox entry, ACKs the
6510
+ chat to free broker capacity, and later commits its final receipt to the same
6511
+ durable outbox when admission resumes.
6512
+
6513
+ A session keeps its refresh request pending for every asked recipient until a
6514
+ validated presence from that member arrives. Later non-reply snapshots retain
6515
+ requestReply while anyone is pending; replies never carry requestReply. The set
6516
+ is bounded by the current roster and resets at reconnect or membership change.
6517
+
6518
+ Room application retries preserve the application id, canonical delivery id and
6519
+ original queue TTL, using a fresh authenticated ciphertext sequence where needed.
6520
+ The ACK timeout schedules resend rather than uncertainty; queue expiry or a
6521
+ permanent refusal remains inspectable. A signed late receipt may settle an
6522
+ unresolved ordinary remote hold once without overriding a person disposition.
6523
+ Invocation uncertainty retains its person-only ledger hold. Receiver application
6524
+ deduplication, current identity/privacy fences and all caps remain.
6525
+
6526
+
6527
+ ### Room liveness and person-visible rotation (#1204 T3)
6528
+
6529
+ The T3 contract is [room liveness and epoch changes](../design/bus.md#room-liveness-and-epoch-changes-1204-t3).
6530
+ The broker's existing negotiated ephemeral bit alone enables 30-second periodic
6531
+ `requestReply` publication and three-period (90-second) local observation aging.
6532
+ It adds no wire payload kind, codec advertisement or native `PeerState` value.
6533
+ Legacy brokers have no periodic refresh or aging and explicitly report liveness
6534
+ untracked, with a broker upgrade step. The existing state-change dedupe,
6535
+ request/reply fencing, caps, privacy and T2 receipt/dedupe ceilings remain.
6536
+
6537
+ An asynchronous, idempotent stop fences publication synchronously, attempts one
6538
+ signed offline snapshot in FIFO order behind an attempted head, and disconnects
6539
+ within two seconds while retaining durable intents and receipt outbox rows.
6540
+ Failure leaves supporting recipients to age the observation; it grants no
6541
+ remote process-stop or execution authority. Refresh period and observation clock
6542
+ are fixture seams. Restored observations cannot establish freshness; clock
6543
+ rollback makes displayed liveness unknown and status reads mutate neither time
6544
+ nor delivery state. Aging is advisory only and never changes outbound admissibility;
6545
+ signed roster, exposure, link and Bus proofs remain authoritative. Explicit signed
6546
+ offline presence keeps its existing handling, and the broker can queue for members
6547
+ that are not live.
6548
+
6549
+ Person previews for epoch-changing owner exposure, invite acceptance, revocation
6550
+ and existing-room `join --roster` adoption bind the current roster digest and the
6551
+ sorted, exact set of already sealed unresolved Store delivery ids. Link
6552
+ application publication is quiesced before the final recheck and commit; a new or
6553
+ settled id invalidates the preview. Bus-only unsealed work is excluded.
6554
+ RoomStore uses its existing schema and `boundary_refused` reason to quarantine
6555
+ old active intents atomically with the epoch and remove sendable ciphertext.
6556
+ T2's crash-gap quarantine remains the recovery fence, not a new T3 repair.
6557
+ T3 gives matching local Bus deliveries `needs_review` with fixed journal reason
6558
+ `room epoch rotated; inspect ahub queue show <id>` and room-status
6559
+ `holdReason: "epoch rotated"`. Terminal rows and person
6560
+ dispositions remain authoritative; rotation is not completion, replay or
6561
+ cancellation. A committed rotation whose local journal hold cannot be written
6562
+ returns `epoch_rotated_hold_unavailable` with an inspection step, without
6563
+ restoring old sendability.
6564
+
6565
+ Source and isolated fixture coverage are listed in [dogfood](../dogfood.md).
6566
+ Those fixtures do not establish installed or two-machine liveness. #1204 remains
6567
+ open for T4's full capability advertisement and compatibility work.
@@ -99,8 +99,13 @@ visual redesign, automatic merging and npm publication.
99
99
  Same-machine cross-project routing is no longer out of scope: work that belongs to another project that runs agent-hub is registered on that project's board.
100
100
 
101
101
  - **Target.** `project` names a project in the machine registry (its canonical root or its id). An unregistered target, the caller's own project and a target whose daemon is not running are refused, the last with the person's action (`ahub up` in that project). Nothing is queued.
102
- - **Who and what.** The person (`ahub task handoff --project <root|id> [<class>] <title...> [--path <p>]... [--issue <n>] [--task <n>] [--detail <text>]`), or a configured planner or the conductor (`hub_task_handoff`). A feature or behavior change first needs a spec issue in the target repository, passed as `issue`; a mechanical chore goes straight to a task. The request is closed (unknown fields refused), bounded (8 KiB whole) and repository-relative for paths.
102
+ - **Who and what.** The person (`ahub task handoff --project <root|id> [<class>] <title...> [--path <p>]... [--issue <n>] [--task <n>] [--detail <text>] [--duplicate-ok <reason>]`), or a configured planner or the conductor (`hub_task_handoff`). A feature or behavior change first needs a spec issue in the target repository, passed as `issue`; a mechanical chore goes straight to a task. The request is closed (unknown fields refused), bounded (8 KiB whole) and repository-relative for paths.
103
103
  - **Transport.** The origin's daemon reads the target's control descriptor (same machine user) and sends `task_handoff` as a console-role control message with origin `{ projectId, peer, taskId? }`. The target's `Tasks` creates an ownerless proposal made by the hub, with the origin recorded in `task_handoff_origin`; its own routing and planner take it from there. The origin peer has no identity or authority in the target: it is a record, never a roster peer.
104
104
  - **Follow-back.** On accepted, in review, approved, declined and cancelled the target sends `task_handoff_event`; the origin records it in `task_handoff_outbound` and delivers one `kind: task` envelope to the requesting peer (`agent-hub task 123 approved: PR #N at <sha>`: an event name, a PR number and a full head, never target text). An origin that was down asks the target for the current state of its open handoffs when it starts (`task_handoff_states`). `ahub board --handoffs` and `hub_task_handoffs` list them.
105
+ - **Duplicates and cancel (#1175).** A handoff naming a spec issue (`issue`) that already has an open task on the target's board (proposed, backlog, in progress, in review or changes requested; a `[pii]` row is never named) is refused before any row exists, with the open task ids, unless the sender passes `duplicate_ok` (a reason of up to 300 characters, recorded in the task's detail). An issue number identifies work only together with its repository: `sdlc.repo`, `external {repo, issue}` (an imported backlog row) and a slug `refs.repo` that name another repository than the target's do not count. The target's configured, rostered conductor may cancel a handed-off task that nobody has accepted and that has no execution evidence, with a reason; the origin hears `cancelled` through the follow-back, never the reason. A target from before this check refuses `duplicate_ok` as an unknown field, which the sender reports as "upgrade the target hub or hand off without `duplicate_ok`".
106
+ - **Idempotent request (#1203 T1).** The origin mints a `handoffKey` (UUID v4) per request, or takes the one a retry passes (`--key`, `handoffKey`), and sends it in the `task_handoff` request body to a target that advertises `task_handoff_key`. The target stores it with a digest of what was asked in `task_handoff_origin` (unique per origin project) and writes the proposal and the origin row in one board transaction (`Board.proposeHandoff`). A key it already holds answers with that task (`replayed`) before the duplicate check and before any PII screen; the same key for a different request is refused. A timeout or a closed connection is not a refusal: the origin sends the same key once more, then asks the target by key (`task_handoff_by_key`, answered only to the asking project and only with the fields a live event carries), and otherwise reports the new refusal code `outcome_unknown`, naming the key to retry with. The origin records its outbound row from the reply or the by-key answer, never resetting a row that already exists.
107
+ - **Converging follow-back (#1203 T2).** Each `task_handoff_event` carries `seq`, the target task's flow revision (its history length), to an origin that advertises `task_handoff_seq`. The origin keeps the sequence of the last applied event in the outbound row and ignores an event whose `seq` is not newer: it changes nothing and sends no envelope, decided inside the one board write, so events that arrive out of order (each uses its own connection) cannot move a row backwards. An event without `seq` (an older target) applies as before. The origin's catch-up (`task_handoff_states`, which now also returns `seq`) runs at start, every 5 minutes and when a target's control descriptor changes, over every row that is not cancelled and, for an approved one, was updated within the last 7 days (a reviewer can withdraw an approval; the origin only learns of it through the sequence), with no 200-row cap and in requests of at most 200 task ids. `changes_requested` and `reopened` are events, sent only to an origin that advertises `task_handoff_seq`. A catch-up pass never overlaps another, never holds a board write and stops at shutdown. `ahub board --handoffs` still lists the 200 most recently changed rows; that cap is for display only.
108
+ - **Diagnostics and repair (#1203 T3).** Every failure is visible and repairable by the person. A connection to a target that fails is named by the error's code and never by its message: 4426 (the wire versions share no protocol) is `older_target` and says to upgrade whichever hub is older, 4404 (another hub or instance answers) is the new refusal code `mismatch` and says to check `ahub projects`, a connect timeout says the hub may be stuck (`ahub status`), and only an unreachable hub says "not running" with `ahub up`. A failed notify, catch-up pass or handoff writes one `hub.log` line per target and cause in each window (15 minutes), with a fixed cause phrase and never a task title or the target's text. `ahub task handoff --list` (the person's command, read-only) shows each handoff with its age since the last report and `reachable`, `unreachable` with its cause and next step, or `moved` (the project id is not in the machine registry: it was removed or its root changed, and the id is a hash of the root), read from the registry and the target's descriptor file without opening a connection. `ahub task handoff --sync` (the person or the conductor) runs a catch-up pass now and answers with the refreshed list; it waits for a pass already running and then runs its own, for at most 20 seconds (under the caller's 30 second control timeout, because the pass asks targets one after another): past that it answers with the list as it stands, `syncing: true` and the number of targets still pending, the pass goes on in the background, and the CLI prints "catch-up still running for N targets: run `ahub task handoff --list` in a minute". An agent gets the same list from `hub_task_handoffs` (now with `age`, `ageMs`, `reach` and `cause`) and cannot sync. A catch-up request that gets no usable reply (the target refused it, timed out or dropped the connection) is a failure like any other: its target reads `unreachable` with the cause "no answer to the state request" and the step `ahub status` in that project, one log line is written, and the earlier failure is not cleared. If the pass itself fails, `--sync` answers `synced: false` with that cause instead of `synced: true`.
109
+ - **Follow-back envelope (#1203 T1).** It carries `refs.handoff {project, task}` (the target's project and task) and no `refs.task`, so the bus never judges it against a local task that happens to have the same number; the one-line body is unchanged.
105
110
  - **Privacy.** Refused during a private (PII) turn and for a `[pii]` task named with `task`; the target refuses text that matches a PII pattern or that its screen cannot clear. No memory, evidence or turn content crosses beyond the handoff fields.
106
- - **Compatibility.** The additive daemon feature `task_handoff` (no protocol bump: a new message type is answered as unknown by an older hub, and an optional field is ignored). An older target is refused with a named "upgrade the target hub" error, and a recovery target without the label is refused while either handoff table holds a row.
111
+ - **Compatibility.** The additive daemon features `task_handoff` and, from #1203 T1, `task_handoff_key` and `task_handoff_seq` (the latter: a target sends `seq` and the two new events only to an origin that has it; an origin ignores a missing `seq`). `task_handoff_key` (an origin sends no key to a target without it and keeps the earlier behavior, a timeout there is `outcome_unknown` without a retry key, and the request is not repeated). Neither feature bumps the protocol: a new message type is answered as unknown by an older hub, and an optional field is ignored, except `duplicate_ok` and `handoffKey`, which an older target refuses as unknown fields (so the key is sent only to a target that advertises it). An older target is refused with a named "upgrade the target hub" error, and a recovery target without the label is refused while either handoff table holds a row.
@@ -0,0 +1,31 @@
1
+ # Channel client evidence for #1171
2
+
3
+ ## Scope
4
+
5
+ This investigation checked the installed first-party Claude Code 2.1.318 artifact and read process metadata on macOS on 2026-11-04. It did not start a model session, modify a running client, capture a live MCP handshake, or establish that a particular notification reached a model.
6
+
7
+ The artifact was the existing native installation at `~/.local/share/claude/versions/2.1.318`. Its embedded build metadata names Git revision `ca1fa9dea62c1027756786c841c548788644560d` and build time `2026-11-03T18:52:53Z`.
8
+
9
+ ## Client initialization and channel registration
10
+
11
+ The inspected stdio MCP client construction passes capabilities through `_Xt`, `pOn` or `uOn`, and `W`. That path builds roots/list-change and elicitation capabilities, with conditional MCP application extensions. The inspected path contains no channel-specific client capability or flag-dependent channel opt-in field.
12
+
13
+ Channel registration is a separate path. It checks the server's channel declaration, protocol compatibility, provider and organization policy, and the session's selected channel entries. A generic MCP client capability therefore cannot establish that this session opted into this channel. This is a bounded observation about these paths in 2.1.318, not a claim about every client version.
14
+
15
+ The [official channel reference](https://code.claude.com/docs/en/channels-reference) describes the channel capability as a server declaration. It also documents the development flag as interactive-only; print mode ignores that flag. No usable client initialization signal was found in the inspected artifact and reference.
16
+
17
+ ## Direct-parent fallback
18
+
19
+ The existing `claudeNativeLaunch` implementation prepends the development-channel flag and a selected exact target before native passthrough arguments. The target is normally `plugin:agent-hub@agent-hub`; its existing matching MCP configuration path can select `server:agent-hub`.
20
+
21
+ A passive process observation corroborated this layout for the running native TUIs: process 10310 and several other observed TUIs had the exact known flag/target prefix. The observed background daemon, process 17739, did not. Two other Claude process rows exposed only the process name, which cannot establish support. The observation emitted only identifiers and classification results, without retaining command bodies, paths or prompts.
22
+
23
+ The proposed fallback was communicated to the reviewer before implementation: require the existing launcher marker together with bounded evidence from the direct parent's actual invocation. An inherited marker alone is insufficient. Unknown process metadata must remain tools-only. Searching an arbitrary command substring would be unsafe because a prompt or an option value can contain the same flag text.
24
+
25
+ The flag evidence has a deliberate ceiling: it establishes the inspected launch form, not organization policy, user confirmation, protocol registration or model consumption. Unrecognized launch forms must remain pull-only. The separate #1172 settlement work is needed for notifications that are accepted by the transport but never confirmed by the session.
26
+
27
+ ## Verification boundaries
28
+
29
+ Synthetic fixtures must distinguish an inherited marker without parent evidence from the supported launcher form, and keep the former's messages readable through `hub_inbox`. Negative cases include print/background forms, repeated or misplaced flags, unknown targets and unavailable process metadata. Status must expose a closed evidence value, never command text.
30
+
31
+ Source tests, the committed-head remote gate, hosted CI and native message-consumption receipts are separate evidence. This investigation supplies no native delivery receipt.
@@ -0,0 +1,182 @@
1
+ # 0.31.0 release verification
2
+
3
+ This record covers release preparation and source review. It claims no installation, no running-hub upgrade to 0.31.0 and no live TUI launch.
4
+
5
+ ## Candidate
6
+
7
+ Initial preparation: version 0.31.0, prepared from main 3185dd4c (33 commits since v0.30.0; the tool's count of 34 includes this branch's CHANGELOG commit 7e2a3257, 16 of them `feat`; bump rule: minor). The release commits carry the version, the CHANGELOG section, the bundle and the documentation stamps.
8
+
9
+ ## Completion after the release follow-ups (task 744)
10
+
11
+ The single intended release remains 0.31.0. Completion starts from main
12
+ `9e4f24c3b222b6faa40309eeb0a91a54107dfe6e` on the exact branch
13
+ `release/0.31.0`; no version, runtime, bundle or fixture version is changed here.
14
+ At preparation, npm's `latest` was 0.30.0 and the remote `v0.31.0` tag was absent.
15
+ The earlier release PRs #1218 and #1223 are already merged, but the four source
16
+ PRs below landed afterward. This follow-up must also be merged with a merge
17
+ commit and the default subject, preserving the reviewed-stamp ancestors for the
18
+ guarded tag. It neither records consent nor creates a tag or npm publication.
19
+
20
+ The board approval head equals each merged PR's head (`mismatch: false`).
21
+ GitHub readback found every listed check completed successfully or skipped,
22
+ with no failed or pending check. Counts below are head-specific hosted checks,
23
+ not installed/native acceptance or a new full-suite result for this docs branch.
24
+
25
+ | PR / task | Approved head | Merge commit | Hosted CI |
26
+ | --- | --- | --- | --- |
27
+ | [#1213](https://github.com/STAIxBWLB/agent-hub/pull/1213), task 739 | `6a304ccbdc2b9ab511f6f85af7fb8fbaee18f1ce` | `c58958d3a13c4de0317fdfb72745a88943315e93` | 19 success, 2 skipped |
28
+ | [#1224](https://github.com/STAIxBWLB/agent-hub/pull/1224), task 714 | `cf20b1d30fe314938c013b34b8a394e8aed1474f` | `b7408fffccdfcdce88fd0e04c2cbecf91c44d7c8` | 21 success, 2 skipped |
29
+ | [#1215](https://github.com/STAIxBWLB/agent-hub/pull/1215), task 734 | `4ffbab00e3a10a32c2955c76873b424f4d5434f8` | `4a4f87ed445bb32df13f9b371f8792dde740de65` | 19 success, 2 skipped |
30
+ | [#1228](https://github.com/STAIxBWLB/agent-hub/pull/1228), task 743 | `8c6d28bbd49f9d2b28e5ab62c28fd81d8a1e6f72` | `9e4f24c3b222b6faa40309eeb0a91a54107dfe6e` | 19 success, 2 skipped |
31
+
32
+ CHANGELOG now includes failure causes/unresolved failed counts, the handoff
33
+ reachability/repair diagnostics, the exact agent-mem 0.21.0 pin and complete
34
+ bounded declined inspection, and the missing task 739 convention entry.
35
+ Unreleased is empty. The old #1173 wait for agent-mem#260/#261 is replaced:
36
+ AC4 is complete, while automatic v3 sync remains unsupported pending the
37
+ activation and fresh host-attestation path in agent-mem#281. No activation or
38
+ attestation is fabricated. Task 736/T3 and task 737/T4 are not in this release.
39
+
40
+ The hub N-1 fixture stays 0.30.0 with agent-mem 0.20.1. The additive nullable
41
+ `deliveries.failure_cause` column does not raise hub schema version 2; the older
42
+ recovery reader ignores the extra diagnostic snapshot key. The existing
43
+ `peer_takeover` compatibility statement is retained. Memory claims are limited
44
+ to [agent-mem's published 0.21.0 notes](https://github.com/STAIxBWLB/agent-mem/blob/v0.21.0/CHANGELOG.md):
45
+ its N-1 proof uses 0.20.3, not the 0.20.1 bundled by hub 0.30.0. Those notes keep
46
+ curated/capture/hook-spool/candidate/work-list/setup receipt v1/v2 formats,
47
+ shared-v1/generation/v1-v2 shard sync and index version/name unchanged, and
48
+ record 0.20.3 refusing activated v3. This report does not extend that versioned
49
+ proof to 0.20.1 or claim supported v3 activation/automatic sync.
50
+
51
+ ### Document review for task 744
52
+
53
+ The 14 stale documents were reviewed against the task 714, 734 and 743 deltas
54
+ only; task 739 changes classification metadata without runtime behavior.
55
+ Changed documents:
56
+
57
+ - `docs/quickstart.md`: correct the 0.31.0 upgrade paragraph, additive failure
58
+ column, current exact memory pin and the automatic-v3 limitation; retain the
59
+ historical 0.30.0 pin note and global CLI/plugin update step.
60
+ - `docs/operations.md`: correct the mismatch next step (`ahub projects`, with
61
+ `ahub up` conditional on the intended target not running).
62
+ - `docs/security.md`: correct the old 0.18.0 pin; distinguish safe status
63
+ placement counts from failure logging and bounded person-only inspection;
64
+ state the activation/attestation limitation.
65
+ - `docs/agent-notes/adapters.md`: carry typed structured failure diagnostics
66
+ without treating the diagnostic as settlement or trusting native text.
67
+ - `docs/agent-notes/bus.md`: preserve typed causes through persistence/retry,
68
+ use metadata-only unresolved counts, and distinguish unavailable from zero.
69
+
70
+ Reviewed without content changes:
71
+
72
+ - `README.md`: version/protocol and high-level memory/handoff claims remain true.
73
+ - `docs/agent-notes/README.md`: historical background is unchanged.
74
+ - `docs/agent-notes/benchmarks.md`: no benchmark protocol or end-cause change.
75
+ - `docs/agent-notes/budget.md`: quota/accounting and pause semantics are unchanged.
76
+ - `docs/agent-notes/daemon.md`: current policy/profile sync fences and handoff
77
+ diagnostic codes, authority and bounded sync behavior remain accurate.
78
+ - `docs/agent-notes/local-worker.md`: the watchdog cause is additive; cancellation
79
+ and uncertainty remain unchanged, with typed diagnostics owned by adapters.
80
+ - `docs/agent-notes/tasks.md`: task/handoff authority and the write-time memory
81
+ projection remain valid.
82
+ - `docs/agent-notes/tests.md`: fake boundaries, exact-pin fixtures and the
83
+ type-only overload adaptation do not change the test instructions.
84
+ - `src/cli/help.ts`: handoff `--list`/`--sync` match main and the argument parser;
85
+ status/queue/declined forms and native entry definitions are unchanged.
86
+
87
+ Only these 14 reviewed documents were restamped through
88
+ `bun scripts/release-prepare.ts restamp <document>... --reviewed` at the reviewed
89
+ content commit `af37f8fd8b44a2c566aa47629ec5b02ee9f91d69`. The stamp-only commit
90
+ `7db76b365d0b3e0ef0b946468193dab7b3393bd8` retains that ancestor; the already
91
+ fresh models document was not restamped.
92
+
93
+ ### Completion checks for task 744
94
+
95
+ On dgx02, `remote_dev.py verify` checked committed head
96
+ `7db76b365d0b3e0ef0b946468193dab7b3393bd8` (tree `656a468fbfd1`) with
97
+ `node scripts/check-docs.mjs --require-fresh && scripts/check.sh --changed`.
98
+ The run completed in 31 seconds with:
99
+
100
+ ```text
101
+ docs: OK (0 stale documents)
102
+ roles: OK (17 bounded definitions)
103
+ inventory: OK (3276 entries, 2121 classified, 1155 in the baseline of known-unclassified keys)
104
+ package: OK (793 files, @staix/agent-hub@0.31.0)
105
+ check: --changed found no affected tests
106
+ check: OK (changed)
107
+ ```
108
+
109
+ Typecheck and bundle freshness also passed. This was a documentation-only
110
+ changed gate, not a new full runtime test run. The following documentation-only update
111
+ records that completed result; final-head checks and hosted CI are recorded on
112
+ the PR and remain the merge gate. No tag, consent, publication, installation or
113
+ live upgrade was performed.
114
+
115
+ ## Reviews
116
+
117
+ Pull requests named by the commits since v0.30.0: #1216, #1211, #1214, #738, #1212, #1210, #1207, #1209, #1206, #1205, #1202, #1201, #1192, #1200, #1197, #1195, #1194, #1189, #1191, #1190, #1186, #1183, #1188, #1181, #1185, #1187, #1184, #1182, #1170, #1169, #1168, #1167, #1166, #1165.
118
+
119
+ `#738` in that list is hub task 738 named in #1212's subject, not a pull request of this range.
120
+
121
+ Each of the 33 merged at the head its hub task approved, read from the board (`ahub board --json`: `approval.head` equals the task's `refs.commit` and the PR's head, `mismatch: false`), with that head's CI green on ubuntu and macOS (18 to 21 checks pass, 2 skipped, none failing). Approvals by claude unless named:
122
+
123
+ - #1165 (task 695) at 5d1c984e; #1166 (696) at 71f1e1f0; #1167 (693) at ca882f2b; #1168 (694) at 59f352da; #1169 (697) at e5500129; #1170 (700) at 884036ba; #1181 (708) at 0b9fbe07; #1182 (715) at 56521a35; #1183 (702) at 56f1e7c5; #1184 (710) at 97bfcba4; #1185 (703) at c762d8a7; #1186 (704) at 96703ec9; #1187 (711) at 9e2b2719; #1188 (716) at 72958d19; #1189 (712) at 054cc353; #1190 (724) at 1ecdeb32; #1191 (717) at db519b67; #1192 (722) at dd5e87ff; #1195 (705) at 61168f74; #1197 (723) at 680f3c1f; #1200 (727) at a6c886bb; #1201 (718) at 96d01a2d; #1202 (725) at e0a5c1a3; #1205 (728) at e2bca26f; #1206 (732) at c38895a6; #1207 (719) at 6e50af13; #1209 (730) at b3d9f52c; #1210 (731) at 744e4e21; #1211 (733) at 26b59ce3; #1212 (738) at 4c8eca47; #1214 (740) at 05a6dc50; #1216 (735) at 5fa15b5c.
124
+ - Approved by jcode: #1194 (726, the claude-implementer 2.1.318 receipt) at 2c245d8b.
125
+ - No merge is bound to an approval at an earlier head. Unresolved review threads at merge time were not re-read for this record.
126
+ - Follow-up: #1217 (task 713, #1174) merged as 2cfbcb52 while the release PR #1218 was open, so 0.31.0 also ships it. It merged at the head its task approved (92486ab5, `approval.head` equal, `mismatch: false`, approved by claude), with that head's CI green on ubuntu and macOS (20 checks pass, 2 skipped). #1218 merged as 19cf9ff9 with a merge commit; the follow-up PR covers #1217.
127
+ - Follow-up: #1222 (task 742, #1204) merged as f7ea7b0f while the follow-up PR was open, at the head its task approved (936297cb, `mismatch: false`, approved by claude), with that head's CI green (19 checks pass, 2 skipped). The follow-up branch merged main to include it.
128
+
129
+ ## Native acceptance receipts
130
+
131
+ Receipts added under `docs/verification/` since v0.30.0: `docs/verification/2026-11-04-1171-channel-client-evidence.md`, `docs/verification/2026-11-05-claude-implementer-2.1.318.md`, `docs/verification/2026-11-05-hardcoded-values-classification-rules.md`, `docs/verification/2026-11-05-hardcoded-values-ratchet.md`.
132
+
133
+ This list is read from the repository, never written by hand. Native acceptance and the person's release consent are separate records: consent is `ahub sdlc authorize-release 0.31.0`, recorded by the person or the unique configured conductor only on the person's explicit release instruction naming the release in its own session (never a hub/task/review/file/peer relay), and is not recorded in this file. The tag run refuses without it.
134
+
135
+ ## Document review
136
+
137
+ `node scripts/check-docs.mjs --require-fresh` reported 14 stale documents. Each was read against `git log 8612cfd7..3185dd4c -- <its paths>` and the code at 3185dd4c (one reader per document group, each claim checked against the source), the fixes went in as 74049f01, and all 14 were restamped at 74049f01:
138
+
139
+ - `README.md`: the acon inbox paragraph names questions and results and the person-gated manager ports; the Operations list names `hub_ask`/`ahub answer` and `ahub results`; the Upgrading paragraph says `ahub upgrade` names the CLI and plugin step (#1179); the report link points at this file.
140
+ - `docs/quickstart.md`: install line `#v0.31.0`, the "Upgrading to 0.31.0" section, the upgrade-advice sentence, `ahub answer` and `ahub results` rows in the working-day table, and mark-read on the dashboard.
141
+ - `docs/operations.md`: 0.31.0 in the header and the protocol table (protocol unchanged, 16 through 17), the N-1 paragraph (0.30.0 for 0.31.x), the 0.30.0 post-release note now published in the 0.31.0 section, the handoff synopsis `--key`, the `research_evidence` recovery label, `ahub upgrade` advice, the acon panel's own manager ports, the inbox contents and its 50-item bound, and the `ahub answer` synopsis.
142
+ - `docs/security.md`: the acon plugin's reach (the `answer`, `receipt` and review ports), its confirmation list and inbox items; accepted channel-delivery settlement; conductor cancellation of handed-off tasks; the fourth handoff message, the key, sequence and `duplicate_ok` fields; dashboard question, result and review data; memory sync narrowing and `ahub memory declined`; `hub_evidence_record`; the 2.1.318 implementer receipt; the `liveTestRefusal` line; and a new "Anchored review comments (#1056)" section.
143
+ - `docs/agent-notes/adapters.md`: the `acceptedSettlement` port (#1172) and the owned input observers (#1056).
144
+ - `docs/agent-notes/budget.md`: transient `Bus.pause`/`resume` write no snapshot (#1214).
145
+ - `docs/agent-notes/bus.md`: pushed vs pulled answer parents, review-observer telemetry suppression, owner-audience reviews never moot, explicit-channel `accepted` resolution, accepted-delivery expiry, review provenance and room delivery rows.
146
+ - `docs/agent-notes/daemon.md`: the recovery floor list (`research_evidence`, `review_comments`, `review_observer_input_state`, `accepted_delivery_settlement`), the DOING privacy screens, review observer input, channel push evidence, the inbox project listing budget, held-hint rendering, memory sync policy outcomes and the retired pet window.
147
+ - `docs/agent-notes/local-worker.md`: the review-turn exclusion (#1181, #1192).
148
+ - `docs/agent-notes/tasks.md`: `Board.proposeHandoff`, `task_handoff_by_key`, sequence-ordered events and the periodic catch-up; claim evidence links; person review comments; long-term memory screening.
149
+ - `docs/agent-notes/tests.md`: time-bounded waits (#1163), the fake-ripwire probe (#1197), channel parent evidence in fixtures (#1171) and the published fixtures' retarget rule (#1168).
150
+ - No change needed: `src/cli/help.ts` (every form the 8 commits added matches `main.ts` and its parsers), `docs/agent-notes/README.md` and `docs/agent-notes/benchmarks.md` (each read; the commits in range do not change what they state).
151
+ - Not acted on, outside the stale set: AGENTS.md "Area notes" does not yet name the new files `src/hub/review-comments.ts`, `review-anchor.ts`, `review-material.ts`, `research-evidence.ts`, `memory-sync-policy.ts`, `question-detach.ts`, `completion-detail.ts`, `memory-sync-state.ts`, `src/ui/plugin-questions.ts` and the new `src/cli/*-args.ts` parsers; `test/specs-tasks.test.ts` and `test/broker-server.test.ts` still bound a wait by event-loop turns.
152
+
153
+ - Follow-up review of #1217: after #1218 merged, `check-docs --require-fresh` on main reported 12 documents stale by #1217 (and the #1218 merge). Each was re-read against #1217's diff only, the fixes went in as 142c80c7, and all 12 were restamped at 142c80c7:
154
+ - `README.md`: the Operations list names `ahub peer takeover`.
155
+ - `docs/operations.md`: the newest-hello sentence now applies only to a session that does not opt in to standby.
156
+ - `docs/security.md`: a paragraph on person-only takeover, standby fencing and display-only ids and PIDs.
157
+ - `docs/agent-notes/adapters.md`: the retained standby port (`retainStandby`, `takeover`, `ownsSocket`, closes 4405 and 4403).
158
+ - `docs/agent-notes/daemon.md`: the `peer_takeover` control message and detached-connection rule.
159
+ - `docs/agent-notes/tests.md`: close the fixture owner before attaching a second opted-in session.
160
+ - `src/cli/help.ts`: `ahub peer takeover` lists the `--json` and `--color` flags `main.ts` accepts.
161
+ - No change needed: `docs/agent-notes/README.md` (the `o` key acts on the selected row's displayed standby id, within the exact-row rule), `budget.md`, `bus.md`, `tasks.md` (#1217 changes no pause, queue or task path) and `docs/quickstart.md`.
162
+ - CHANGELOG: a #1217 entry under 0.31.0, and the N-1 statement names `peer_takeover`, `ahub peer takeover` and the standby opt-in in both directions.
163
+ - Follow-up review of #1222: the merge of main left 9 documents stale by its `src/hub/bus.ts` and `src/rooms/link.ts` changes. Each was re-read against #1222's diff, the one fix went in as aceed883, and all 9 were restamped there:
164
+ - `docs/agent-notes/bus.md`: a closed `Bus` publishes nothing and touches no journal or observer.
165
+ - No change needed: `README.md`, `docs/operations.md`, `docs/security.md`, `docs/quickstart.md`, `budget.md`, `daemon.md`, `tasks.md`, `tests.md` (their presence and queue statements still hold; #1222 changes no surface, setting or wire field).
166
+ - CHANGELOG: a #1222 entry under 0.31.0; it changes no N-1 surface.
167
+
168
+ ## Checks
169
+
170
+ - `node scripts/check-docs.mjs --require-fresh`: `docs: OK (0 stale documents)` after the restamp at 74049f01.
171
+ - `scripts/check.sh --changed origin/main` on dgx02 (`remote_dev.py verify`) at e8f3a694 (tree a0576a8b) selected the full suite: `docs: OK (0 stale documents)`, `roles: OK`, `inventory: OK` (3267 entries, 1155 in the baseline), typecheck (`bun x tsc --noEmit`), the bundle check (`bun scripts/build.mjs --check`), `package: OK (791 files, @staix/agent-hub@0.31.0)`, and 11891 pass, 101 skip, 0 fail across 916 files with Bun 1.4.2; no daemon leaks; `check: OK`. It includes the published-runtime interoperability tests in both directions against 0.30.0 (release N-1) and 0.25.0 (protocol floor). Later commits on the release branch change only this report.
172
+ - The release PR's exact-head CI on ubuntu and macOS is the gate for the merge.
173
+ - Follow-up for #1217: `node scripts/check-docs.mjs --require-fresh` is `docs: OK (0 stale documents)` after the restamp at 142c80c7. `scripts/check.sh --changed origin/main` on dgx02 at 1acb9645 (tree e1a307e0) ran typecheck, the bundle check, `inventory: OK`, `package: OK (791 files, @staix/agent-hub@0.31.0)` and the 25 test files the change touches: 347 pass, 0 fail; `check: OK (changed)`. #1217's own full-suite and hosted CI receipts are in its PR. After that gate the branch merged main for #1222 (its own full dgx02 gate and hosted CI are in #1222) and added only documents, stamps and CHANGELOG lines; `check-docs --require-fresh` is clean at the final head. The follow-up PR's exact-head CI gates its merge, which must also be a merge commit.
174
+
175
+ ## Known gaps, not blocking
176
+
177
+ - No installation, running-hub upgrade to 0.31.0 or live TUI launch was done for this record.
178
+ - #1053: AC1 live receipts and the T1 timeout measurement stay open; the per-adapter `hub_ask` waits are provisional.
179
+ - #1056 and #1204 (T3, T4) stay open; #1196 stays open until the person measures the live acon console.
180
+ - #1173: complete bounded declined listings are available. Automatic v3 sync still lacks the supported activation and fresh host-attestation path in agent-mem#281.
181
+ - #1184: the channel-evidence fallback reads the direct parent's process row; it is not authentication, and a published client opt-in is the upgrade path.
182
+ - The N-1 fixture lock remains the Bun 1.4.2 lock for 0.30.0. Prior published-runtime interoperability evidence is recorded above; this documentation-only completion adds no new full-runtime claim.
@@ -0,0 +1,70 @@
1
+ # Claude Code 2.1.318 headless implementer receipt
2
+
3
+ Date: 2026-11-05. Scope: #888 (claude-implementer row). This repeats the procedures of the [2.1.316 receipt](2026-10-31-claude-implementer-2.1.316.md) on the installed Claude Code 2.1.318, with 2.1.316 run through the same producers as the control: the permission transport (Write, production-name Bash, Bash `updatedInput` rewrite) and the host shell wrapper. Source head: `801c6453`. Platform: macOS arm64, host Bun 1.4.3.
4
+
5
+ Result: every case passed on both binaries. `2.1.318` is added to `COMPAT["claude-implementer"].verified`. 2.1.317 is installed but was not run and is not verified by this receipt.
6
+
7
+ | Native version | Binary SHA-256 |
8
+ | --- | --- |
9
+ | Claude Code 2.1.316 (control) | `64c327e92b2c5e0f78c0a980c5a518121e1f0d140ca771ca5dd4488d1a2dcb3f` |
10
+ | Claude Code 2.1.318 | `677a2ea7bf576cedd20e191d973914ed8a41796f53a63b1923381ddc4d5b5e7d` |
11
+
12
+ The 2.1.316 hash matches the 2.1.316 receipt, so the control is the binary it certified.
13
+
14
+ ## Upstream changes since 2.1.316
15
+
16
+ Read from the upstream [CHANGELOG](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md) entries for 2.1.317 and 2.1.318. Items that touch permissions, MCP, hooks, settings sources, process lifetime or the Bash tool:
17
+
18
+ - **2.1.317, a check that asks before a web or shell tool call sends the account email address to the network**: a new ask. It fires only when a command carries the signed-in account's email; the model-free runs have no account, so this receipt does not exercise it. A real-account run that triggers it goes through the same permission prompt tool as any other ask.
19
+ - **2.1.317, child processes of a stopped shell command sent SIGTERM twice**: fixed. The producers still require every native child's process group to be empty afterwards; this tightens cleanup and loosens nothing.
20
+ - **2.1.317, edits to settings files in the first second after launch not taking effect** and **old transcripts not cleaned up for runs using `--setting-sources`**: fixed. The hub passes `--settings` with permission rules only before launch and an isolated `CLAUDE_CONFIG_DIR`, so neither changes the child's settings or permission inputs.
21
+ - **2.1.317, `claude -p` exiting 0 when a full disk lost its transcript or `~/.claude.json` writes**: it now exits 1. That makes a storage failure visible as a failed turn, not a silent success.
22
+ - **2.1.317, `claude -p` inside a cloud or self-hosted runner session sharing that session's ID** (`CLAUDE_CODE_DISABLE_NESTED_SESSION_ID`): the hub's implementer child is not started inside a runner session and gets the hub-built environment.
23
+ - **2.1.318, stdio MCP servers that exit on the version probe re-probed on every start; a server that dies in under 3s is pinned to the legacy handshake for 7 days**: the implementer child's MCP server (`--strict-mcp-config`, the hub permission server) does not exit on the probe; the transport runs below still negotiate and answer on 2.1.318.
24
+ - **2.1.318, a message sent right after a model change still running after Stop in headless sessions**: Stop now cancels it. The hub does not change models mid-turn in the implementer child.
25
+ - **2.1.318, MCP tool errors**: a call made before the tool is loaded now returns its input schema. This changes error text only; the permission tool is loaded before the first tool call in every run below.
26
+ - **2.1.318, unattended runs no longer rewrite `~/.claude.json` when nothing changed**, and a non-valid `~/.claude.json` now fails the start: the child runs with an isolated HOME and a fresh config.
27
+ - **2.1.318, git commits and PR creation when the Bash tool runs macOS's `/bin/bash`**: reliability only; the wrapper's persistent-cwd control below still passes.
28
+
29
+ Nothing in these entries changes `--permission-prompts host`, `--permission-prompt-tool`, `--strict-mcp-config`, `--setting-sources` or the `updatedInput` reply contract. This reading is of the changelog text, not the binary's source, which is not public.
30
+
31
+ ## Runs
32
+
33
+ Each producer ran both binaries sequentially with an isolated HOME and `CLAUDE_CONFIG_DIR`, a fixture MCP server, a deterministic loopback provider and the literal API key `synthetic-probe-not-a-credential`. No account, provider request or model inference was involved. Every native child's process group was confirmed empty afterwards and every binary hash was unchanged.
34
+
35
+ ```sh
36
+ python3 docs/verification/claude-permission-transport-native.py OUT/write --claude 2.1.316 --claude 2.1.318
37
+ python3 docs/verification/claude-permission-transport-native.py OUT/bash --tool Bash --server-name agent-hub --permission-tool hub_permission_request --require-tool-use-id --claude ... --claude ...
38
+ python3 docs/verification/claude-permission-transport-native.py OUT/rewrite --tool Bash --rewrite-bash --server-name agent-hub --permission-tool hub_permission_request --require-tool-use-id --claude ... --claude ...
39
+ python3 docs/verification/claude-shell-wrapper-native.py OUT/wrapper --bun ABSOLUTE_BUN --claude ... --claude ...
40
+ ```
41
+
42
+ (binary arguments are the absolute installed paths; `--bun` was the Homebrew Bun 1.4.3 path resolved with `readlink -f`, since `command -v bun` names a shell function in an interactive zsh).
43
+
44
+ | Producer | Cases per binary | 2.1.316 | 2.1.318 |
45
+ | --- | --- | --- | --- |
46
+ | Write transport (allow, deny, missing tool, hook deny/allow, MCP error, disconnect, pending, deadline) | 9 | 9 pass | 9 pass |
47
+ | Bash transport, production server and tool names, `tool_use_id` required | 9 | 9 pass | 9 pass |
48
+ | Bash `updatedInput` command replacement (allow, deny) | 2 | 2 pass | 2 pass |
49
+ | Host shell wrapper (persistent-cwd control, fixed-wrapper rewrite with replay refusal) | 2 | 2 pass | 2 pass |
50
+
51
+ Per-case shapes on 2.1.318 match the control: pending stopped externally at the deadline; wrapper control 3 requests and 2 permission calls, wrapper rewrite 4 requests and 3 permission calls with the effect counter at exactly 1 after replay.
52
+
53
+ The only producer change is the version allow-list in `claude-shell-wrapper-native.py`, which now admits `2.1.318`.
54
+
55
+ | Artifact | SHA-256 |
56
+ | --- | --- |
57
+ | Permission producer (unchanged) | `8f8885f7153b3a236f3b3f8ce49a344b908f2af3b3aba8b064762d82d1ecf12a` |
58
+ | Wrapper producer (this change) | `af61fcd08df7da42708226d73949646581d4b9d66d5c243de2c9d2c80afccb23` |
59
+ | Wrapper host fixture (unchanged) | `616e6711e392f0eee7e3fa1c7bdc47a537dfa86bcc8ffb30e549ca94e5a71cef` |
60
+ | Fixed CLI wrapper (unchanged) | `8ff56514a6e3f25bce0784775d396df199b58b1b93f55ad0e8747bbc729d2fd8` |
61
+ | Write receipt JSON | `c0977198860c5a5141f7d49e8a52616aa4556b406975de8adb25f3ef1d0dbc52` |
62
+ | Bash receipt JSON | `14a44372f3b44b32956aecd37e50836fb39f9a2847ad7b33e6185fb9784fac55` |
63
+ | Rewrite receipt JSON | `ee3d66252006581a0481fe326313b674b1437d27b9adc8e617690c0efc45d3af` |
64
+ | Wrapper receipt JSON | `2996280113526fd41a005a510656f47c0f20d4dba46d11611191238ed9576a4f` |
65
+
66
+ The receipt JSON files stay in the local diagnostic directory; they carry local paths and are not committed.
67
+
68
+ ## Evidence boundaries
69
+
70
+ Unchanged from the earlier receipts: no real provider authentication, model tool selection, person approval interaction, task-session resume or production-daemon task binding is proved, and this is not a runtime receipt gate. The 2.1.317 account-email ask is not exercised (no account). Native version admission and binary fencing remain required. The Monitor tool is still an unrewritten prompt-tool path. Exact-head package gate and CI are recorded on the PR.