@staix/agent-hub 0.12.29 → 0.12.30

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 (62) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +79 -219
  3. package/docs/agent-notes/README.md +12 -0
  4. package/docs/agent-notes/adapters.md +1 -1
  5. package/docs/agent-notes/bus.md +3 -1
  6. package/docs/agent-notes/daemon.md +10 -0
  7. package/docs/agent-notes/local-worker.md +2 -2
  8. package/docs/agent-notes/tasks.md +9 -0
  9. package/docs/agent-notes/tests.md +1 -1
  10. package/docs/memory.md +70 -152
  11. package/docs/operations.md +199 -14
  12. package/docs/plans/2026-10-16-amem-failure-registry.md +101 -0
  13. package/docs/plans/2026-10-16-amem-p0-baseline.md +110 -0
  14. package/docs/plans/2026-10-16-amem-p2-read-tools.md +28 -0
  15. package/docs/plans/amem-cases.json +482 -0
  16. package/docs/quickstart.md +9 -2
  17. package/docs/security.md +13 -1
  18. package/docs/smoke.md +11 -0
  19. package/docs/specs/2026-09-19-agent-hub-design.md +105 -4
  20. package/docs/verification/2026-10-17-0.12.30.md +70 -0
  21. package/docs/verified.json +13 -13
  22. package/package.json +5 -2
  23. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  24. package/plugins/agent-hub/server.js +64 -44
  25. package/src/cli/console-state.ts +92 -20
  26. package/src/cli/console.ts +22 -5
  27. package/src/cli/help.ts +3 -2
  28. package/src/cli/identity.ts +1 -1
  29. package/src/cli/main.js +2 -2
  30. package/src/cli/main.ts +36 -14
  31. package/src/cli/memory.ts +87 -187
  32. package/src/cli/output.ts +6 -0
  33. package/src/cli/recovery-package.ts +59 -10
  34. package/src/cli/upgrade-runtime.ts +54 -17
  35. package/src/cli/upgrade.ts +8 -0
  36. package/src/hub/board.ts +2 -1
  37. package/src/hub/bus.ts +33 -12
  38. package/src/hub/daemon.ts +134 -27
  39. package/src/hub/envelope.ts +30 -0
  40. package/src/hub/git.ts +2 -38
  41. package/src/hub/hub-tools.ts +5 -1
  42. package/src/hub/manager.ts +1 -1
  43. package/src/hub/memory-candidates.ts +103 -0
  44. package/src/hub/memory-fail.ts +25 -0
  45. package/src/hub/memory-observations.ts +47 -0
  46. package/src/hub/memory-plan-guard.ts +33 -0
  47. package/src/hub/memory-policy.ts +42 -0
  48. package/src/hub/memory-profile-check.ts +170 -0
  49. package/src/hub/memory-profile.ts +192 -0
  50. package/src/hub/memory-staleness.ts +55 -0
  51. package/src/hub/path-policy.ts +8 -0
  52. package/src/hub/project.ts +4 -37
  53. package/src/hub/read-tools.ts +127 -0
  54. package/src/hub/tasks.ts +201 -41
  55. package/src/local/deny.ts +4 -17
  56. package/src/memory/brief.ts +8 -5
  57. package/src/memory/capture.ts +2 -1
  58. package/src/memory/recall.ts +50 -110
  59. package/src/pi/process-signature.ts +2 -42
  60. package/src/memory/import.ts +0 -90
  61. package/src/memory/store.ts +0 -805
  62. package/src/memory/sync.ts +0 -145
@@ -159,8 +159,8 @@ hub CLI / console ── control WS 127.0.0.1:<ctl> ─────────
159
159
  30 s, then goes offline with queued work retained if no report arrives. `--model` maps to `kimi --model <alias> acp`
160
160
  (verified flag). Reusable for `opencode acp`.
161
161
  - Local worker (amended in M3): a hub-native tool-calling loop over non-streaming
162
- `POST /chat/completions` with plain `fetch`, no SDK (the repo keeps zero runtime
163
- dependencies). Tools `read`, `write`, `edit`, `bash`, `git`, `hub_send` (`hub_task_*` with
162
+ `POST /chat/completions` with plain `fetch`, no SDK (the repo keeps zero third-party runtime
163
+ dependencies; the first-party memory core is an exact-pinned library). Tools `read`, `write`, `edit`, `bash`, `git`, `hub_send` (`hub_task_*` with
164
164
  M4). Paths are realpath-scoped to cwd with a secrets denylist; `.git` and `.agenthub` are
165
165
  not writable. `write`, `edit`, `bash` and mutating `git` go through the console permission
166
166
  relay unless the hub runs `--unattended`. Everything that executes runs under seatbelt
@@ -554,7 +554,7 @@ New repo layout:
554
554
  src/hub/ daemon, bus, peer-registry, state-machines, board, budget, router
555
555
  src/adapters/ claude-channel.ts, codex-appserver.ts, acp.ts, local-worker.ts
556
556
  src/switchyard/ config generator, sidecar lifecycle, health
557
- src/memory/ claude-mem worker client, capture for the local worker, recall (inject, brief), remember
557
+ src/memory/ hub memory integration: claude-mem client, capture, briefs and recall; portable core is @staix/agent-mem
558
558
  src/cli/ up, claude, codex, kimi, local, say, tail, board, route, budget, status, logs, kill, init
559
559
  plugins/agent-hub/ .claude-plugin/plugin.json, .mcp.json, server bundle, hooks (SessionStart health, Stop announce)
560
560
  .claude-plugin/marketplace.json
@@ -1255,7 +1255,8 @@ session modes (`default`, `plan`, `auto`, `yolo`) but nothing per server or tool
1255
1255
  ignored with a note in `hub.log` and `ahub doctor`, and is no longer
1256
1256
  machine-local because nothing reads it.
1257
1257
  - Capabilities: `propose`, `assign` (a proposal naming another peer as owner),
1258
- `remember`, `important`. A peer not listed in `capabilities` has all of them,
1258
+ `remember`, `memory_correct` (screened correction candidates only, never acceptance), `memory_read` (the `hub_memory_search`, `hub_memory_show` and
1259
+ `hub_memory_graph` read tools, #412 P2), `important`. A peer not listed in `capabilities` has all of them,
1259
1260
  which keeps today's behaviour, and a listed peer whose value is not a list has
1260
1261
  none; the console user and the hub are never limited. `remember` gates the
1261
1262
  `hub_remember` tool only, not the notes the hub keeps of done summaries and
@@ -1947,6 +1948,63 @@ task list polling does not. `hub_status` stays conductor-only.
1947
1948
  proposer as the actor with reason `manual` (on the `reassigned` or `reserved`
1948
1949
  entry), and writes no conduct audit event; during a PII turn it is refused
1949
1950
  like the conductor's.
1951
+
1952
+ ## Amendment: revision-safe console task and queue operations (issue #424)
1953
+
1954
+ - Task list/show responses add `flowRevision`, the monotonic history length,
1955
+ separate from `planningRevision` and the delivery journal revision. This is
1956
+ additive public metadata and does not bump the control protocol. `Board.update`
1957
+ can check an expected value in its synchronous read-check-write section.
1958
+ - A revision-bound `ahub task assign` uses the new console-only
1959
+ `task_assign_checked`; unchecked `task_assign` remains compatible. The new
1960
+ console-only `task_unassign` and checked operation are unknown to an older hub,
1961
+ which therefore refuses rather than ignoring the revision. A console whose
1962
+ rows lack `flowRevision` refuses task row actions and asks for an upgrade.
1963
+ `ahub queue resolve` accepts an optional displayed revision and otherwise keeps
1964
+ its existing fresh-show behavior. New operations and optional fields preserve
1965
+ the protocol version.
1966
+ - Tasks and Queue selections follow ids across refreshes, never indices into
1967
+ replacement rows. A row-started action fixes its id and revision while peer,
1968
+ reason and final role/action remain editable; confirmation uses the validated
1969
+ final command and its consequence. Refresh follows every completed console
1970
+ command, including failure and saved-but-unconfirmed assignment, without an
1971
+ automatic resend. Existing `AssignmentUndeliveredError` semantics remain.
1972
+ - Tasks `a` assigns owner in `proposed`, `in_progress` and `changes_requested`,
1973
+ and reviewer in `in_review`; waiting owner assignment is a reservation. `u`
1974
+ unassigns, and `r` reviews only in `in_review`. Direct owner reassignment or
1975
+ unassignment in `in_review`, physical task deletion/cancellation and roster
1976
+ removal stay outside this feature.
1977
+ - `Tasks.unassign` is person-only. It refuses `approved` and `backlog`, an
1978
+ already absent role and owner removal in `in_review`. Owner removal clears the
1979
+ owner and reservation and returns active work to `proposed`; reviewer removal
1980
+ keeps the current state. The human reviewer of PII work cannot be removed.
1981
+ Owner removal writes `unassigned` and leaves turn-free cohorts; reviewer
1982
+ removal writes `reviewer changed`. Neither operation routes a replacement,
1983
+ adds a decline exclusion, stops a native process or rolls back effects.
1984
+ - A person `unassigned` event suppresses later automatic owner offers across
1985
+ dependency release, planner pulls, release timers and restart recovery until
1986
+ an explicit assignment or reservation. The marker is derived from history, so
1987
+ no schema migration is needed, and it also fences planner undo and re-pull.
1988
+ Former queued task/review requests are withdrawn, but accepted, dispatching
1989
+ and needs_review deliveries are never implicitly resolved. Withdrawal notices
1990
+ use delivery evidence or accepted/claimed board evidence, never an unread
1991
+ queue alone. Former agents fail current-authority checks while the person's
1992
+ explicit review override remains.
1993
+ - Assignment/review publication has a role-specific fence after every await and
1994
+ immediately before publication. Existing supersession events, role generation
1995
+ and task state suppress obsolete envelopes; accept, done and approval count as
1996
+ supersession even when the owner id is unchanged. Supersession returns the
1997
+ current task rather than aborting the remaining operation. Current metadata is
1998
+ re-read before constructing a still-valid envelope, so reviewer-only changes
1999
+ refresh reviewer content and quiet bookkeeping does not suppress valid owner
2000
+ delivery.
2001
+ - Queue `r` prefills `discard` for `queued` and `retry` for `needs_review`, never
2002
+ `completed` by default. Every resolve needs reason and confirmation. Queued
2003
+ discard removes queued originals; needs-review discard settles its receipt and
2004
+ hold. Retry creates one linked attempt. None cancels a task or claims native
2005
+ or external rollback. Task and queue projections retain their distinct PII and
2006
+ envelope-privacy redaction.
2007
+
1950
2008
  ## Amendment: delegated agent live verification (#408)
1951
2009
 
1952
2010
  - Decision, 2026-10-16: an agent explicitly authorized by the user to perform a live test may use the global `--live-test` flag, before the command and in either order with `--project`. Duplicate global options refuse. Default command classification and malformed/conflicting identity refusals stay unchanged.
@@ -2921,3 +2979,46 @@ and repo-heavy work was coordinated over chat it read too late.
2921
2979
  holder whose pid is gone is reaped. The slot works with no hub running. It is
2922
2980
  not bus-visible; moving it into the hub is the upgrade if pid reuse or reap
2923
2981
  races bite.
2982
+
2983
+
2984
+ ## Amendment: consume the first-party agent-mem package (#412, P5)
2985
+
2986
+ The portable core is the first-party `@staix/agent-mem` library, initially exact-pinned at `0.1.1`; agent-hub keeps zero third-party runtime dependencies. Its store, sync, claude-mem import, project/home helpers and raw memory/goal commands are imported from the package root, with no vendored copies. Platform helpers use the public Node-safe `@staix/agent-mem/platform` subpath: `0.1.0` exposes only a root that loads `bun:sqlite`, which cannot load in Node-hosted Pi extensions. `0.1.1` supplies the required compatibility export without changing the platform algorithms. The package is the single implementation of deny, hardened git, realPath and process identity, re-exported through the existing local/hub/Pi modules so their callers retain one contract. Package storage semantics and the compatibility schema/hash/path invariants are unchanged.
2987
+
2988
+ `src/memory/` retains only hub integration: briefs, recall, the optional claude-mem worker client and capture. The hub owns `src/hub/memory-policy.ts` (`withoutPii`, `promotionScreen`, `mentionsPrivatePath`), `src/hub/read-tools.ts`, task lifecycle writes, lease renewal, model-suggested edges, ask and dashboard consumers. Current project policy is injected through `StoreOptions.screen` and the raw command callbacks. Tasks remains the write authority; PII-turn refusals, current-policy screening before counting/truncation, capture exclusion and the peer read-tool byte budgets remain unchanged.
2989
+
2990
+ `ahub memory` and `ahub goal` keep the hub's argument and identity contract, screened agent-readable views, project configuration and TTL. The standalone person-only `amem` CLI is the package's interface; its `--policy-free` acknowledgement is not an ahub option or a reason to bypass host privacy policy. Memory availability and sync remain fail-open for hub turns, while privacy checks keep their existing fail-closed behavior. Data directory precedence is supplied by the package's `memoryHome()` without migration: `AMEM_HOME`, then `$AGENTHUB_HOME/memory`, then `~/.agenthub/memory`; explicit `StoreOptions.home` retains its parent-directory meaning.
2991
+
2992
+ `docs/memory.md` documents hub integration; [agent-mem](https://github.com/STAIxBWLB/agent-mem) owns the portable data model and CLI documentation. Portable-core import boundary checks belong to the agent-mem package CI. The former hub-local core boundary checker and its check.sh step are removed with the core; the hub keeps its exact first-party dependency pin. Consuming the package does not complete the owed live legs: copied-home old/new parity, source-unchanged checks, rollback and unrun account/device/sandbox receipts are reported separately. No release, runtime replacement or live proof is implied by the source change.
2993
+
2994
+ The consumed package requires Bun >=1.4.2; the hub manifest, plain-JavaScript startup guard and installation guide share that minimum. Node still receives the actionable refusal before any TypeScript or Bun-only import.
2995
+
2996
+ Recovery source preservation retains the exact first-party memory package under the preserved runtime, without copying any other node_modules content or linking to the mutable global install. Package identity/version and all retained dependency bytes participate in the recovery digest; cached or preserved dependency drift is refused. Preserved-source verification requires the package inside its own node_modules, refusing a missing or symlinked copy rather than falling back to a mutable ancestor installation. Staged release verification similarly binds dependency lookup to its retained install directory, including cached releases and a fresh coordinator. Releases without runtime dependencies keep their historical digest.
2997
+
2998
+
2999
+ ## Amendment: P7 Stage A read-only memory presentation (#412 P7-1)
3000
+
3001
+ The exact first-party pin is `@staix/agent-mem` 0.2.0. Agent-hub adds advisory plan-matching live fails to owner briefs and reviewer checklists, optional labeled fail text validated before the 4000-byte cap, person-only decay review, and privacy-filtered bounded read-time staleness markers. The task/PII boundaries remain in Tasks and the daemon. Details and ceilings are in `docs/memory.md`; no new v1 op, stored marker, candidate writer or live-leg claim is introduced.
3002
+
3003
+ The P7-1 hint C3 probe gate assumes the tree is not modified during a call: no probe reaches a declared private/denied path in that scope. Concurrent ancestor swaps by a process running as the person are outside the security threat model and may expose one existence bit; this ceiling has a deterministic witness test.
3004
+
3005
+
3006
+ ## P7 candidate producers and local observations (#412)
3007
+
3008
+ Tasks produces a fail candidate from a public changes-requested review with unmet items, after the current Tasks privacy screen clears the complete candidate text. The review evidence identifies the task, review event and reviewed head (explicitly unknown when absent). Missing cause or retry conditions remain explicitly unknown. Candidate failure never changes the saved review outcome.
3009
+
3010
+ `hub_memory_correct {id, text, reason}` requires its own `memory_correct` capability and refuses a PII turn. Input caps are checked before logging or storage; exact or unique visible-prefix resolution uses the current project and full-record screening. Tasks checks the proposed text like `hub_remember`, then rechecks context and target after asynchronous screening. A successful call records the full target id and revision in CandidateStore and returns only its candidate id and person-review guidance. MCP/Pi/local share the tool definition; capture excludes both arguments and results.
3011
+
3012
+ Journal handoff observes rendered native memory lines in the final preface/brief payload. First positive journal acknowledgement observes delivered for that delivery and its original render context, not a later turn; pull's completed read is the existing journal acknowledgement contract. Peer messages and cleared task completion summaries observe visible `mem:<id8+>` citations. Counter keys use full entry id, project and known task/turn/session plus journal delivery id for rendered/delivered. Unattributed citations use message:<envelope-id> or summary:<task>:<history-index> observation keys with rendered/delivered unknown; these are citation counts, not proof of a causal per-delivery ratio. Absent observations and identities remain unknown. A bounded in-memory render-context map does not reconstruct acknowledgements after restart, so those delivered values remain unknown. Private envelopes, PII tasks and PII turns produce no rows. There is no usage sync or note mutation.
3013
+
3014
+ The machine-local candidate/counter sidecar remains outside native import, recall, briefs, ask and graph evidence. A person accepts or rejects through `amem review` with its existing TTY/policy authority. Dashboard acceptance is deferred. No new v1 operation, note kind or scope is introduced.
3015
+
3016
+ ## Amendment: selected memory profiles in the hub (#412 P9)
3017
+
3018
+ The exact first-party dependency pin is `@staix/agent-mem` 0.3.0. The memory root `M` follows the package's existing home precedence independently of project state. An absent `M/profile.json` binds shared v1; an explicit generation binds `M/generations/G` through the package profile API. The hub supplies current promotion/privacy policy and TTL at that open boundary. Generation reads include the package's readonly legacy bridge; writes and generation sync stay in `G`, outside legacy logs and legacy-main history. No hub tool gains migration or prune authority, and shared-v1 operation semantics remain unchanged.
3019
+
3020
+ One explicit profile binding is used by daemon Tasks, read tools, briefs/recall/ask/dashboard, lease renewal, suggestions and sync. Hub memory and goal CLI opens use the same profile resolution. Invalid selector or missing/corrupt active generation makes native memory unavailable while bus/task service continues, with no automatic shared-v1 fallback. Daemon status distinguishes the memory package/profile binding and availability from hub health. Existing handles remain bound: periodic checks and explicit checks at hub operation entry fence later stale calls rather than rebinding the daemon. No proxy/private core ABI is used. These checks are not atomic with an in-flight core operation, so in-flight cutover is excluded: consumers must be quiesced and closed before migration/selector changes. A public core pre-write hook is the named upgrade path for an atomic fence.
3021
+
3022
+ Candidates/counters remain at the independent root `M/candidates.db` using the package's explicit sidecar home API. They are neither migrated into `G` nor synced. Selector changes fence Tasks candidate producers and retained telemetry callbacks as well as native note operations; asynchronous privacy work rechecks binding before side effects. Standalone generation `amem review` remains unsupported and refuses; this change adds neither candidate acceptance nor dashboard acceptance for generations.
3023
+
3024
+ PII authority, complete-row host screening, capture exclusion, byte budgets and fail-open task delivery remain unchanged. Memory/goal domain JSON remains unchanged; `memoryProfile` is additive only in daemon status, profile-check and the decay object. Synthetic integration must show bridged legacy reads, cross-writes through the package CLI and daemon tools, failure without fallback for invalid/missing generation state, and no note/candidate/counter writes for calls begun after a selector change while bus service remains available. Source/fixture evidence does not authorize real installation, migration or session restart. Real rollout requires separately approved deployed versions and matching live root/profile/selector bindings, synthetic canaries and quiesced/closed/reopened handles. Every running hub using this home needs an authenticated receipt: a matching ready binding, or a generation-capable unbound receipt (`disabled` when native memory is off, `unavailable` when opening failed) proving it holds no memory handle. An unbound daemon and zero running hubs are quiesced for memory; a stale bound handle, unreadable registry or unknown runtime is not ready. Native capture, account/device sync and real memory receipts remain open until observed.
@@ -0,0 +1,70 @@
1
+ # 0.12.30 release verification
2
+
3
+ This record covers release preparation and source review. Publication, installation, running-hub upgrade and real memory migration require their own operational receipts; none is claimed here.
4
+
5
+ ## Candidate
6
+
7
+ Version 0.12.30, control protocol 16, from main `6363f4dbfb1a90900b291a397b892a978922f7b5`. The candidate includes every PR merged since `v0.12.29`: #413, #415, #417, #419, #420, #421, #422, #423, #425, #426, #427, #429 and #430. Every PR body was read against its final merged source; intermediate descriptions of copied memory helpers are superseded by the final single-source package imports.
8
+
9
+ - The portable core is the exact-pinned first-party `@staix/agent-mem` 0.3.0; hub privacy policy and caller authority stay in agent-hub. Shared v1 remains the default, with no automatic migration.
10
+ - Screened memory read tools, display-only recall filtering/deduplication, plan-fail advice, structured fail notes, decay review, file-level staleness and machine-local candidates/counters retain their evidence and privacy boundaries. Generation `amem review` remains refused.
11
+ - Profile binding fails closed for invalid or changed selectors while the bus/board remain available. Person profile-check distinguishes matching ready bindings, authenticated capable unbound/quiesced receipts and unknown/stale runtime evidence; registry scope is explicit.
12
+ - Before migrating a real home, upgrade every hub sharing it to 0.12.30, inventory each registry, obtain positive profile-check receipts, then quiesce consumers and close handles. A ready binding is compatible but still open; the operation-entry fence is not an atomic live-cutover guarantee.
13
+ - Console task and queue controls bind selections to ids/revisions, preserve person unassignment and use peer-specific receipt evidence. Recovery retains exact dependencies and waits for managed peer attachment without creating duplicate terminals.
14
+ - Version 0.13.0's promised removal of `local.bash_network: "direct"` has not happened; the existing ceiling and retirement plan remain unchanged.
15
+
16
+ ## Document review
17
+
18
+ The initial freshness check reproduced all 13 stale documents below. Each was compared with the source changes under its manifest paths since the prior full-SHA stamp through the candidate source. Changed source was traced to the final symbols, not inferred from prose changes alone. No document review was deferred. The already-fresh models note is outside this stale set and keeps its existing stamp.
19
+
20
+ | Document | Prior source stamp | Review result | Checked claims and correction |
21
+ | --- | --- | --- | --- |
22
+ | `README.md` | `0463ea1f251cea17ec7f32a2861de8c554fe4062` | corrected | Current version and Bun requirement; first-party memory tools/candidate boundary, checked console controls and pre-migration upgrade/quiesce order. |
23
+ | `docs/agent-notes/README.md` | `0463ea1f251cea17ec7f32a2861de8c554fe4062` | unchanged | Exact-id console attention selection and navigation remain accurate after the console controls. |
24
+ | `docs/agent-notes/adapters.md` | `0463ea1f251cea17ec7f32a2861de8c554fe4062` | unchanged | Node-safe process identity re-exports, tool catalogs, capability/PII checks and capture exclusions already match the final source. |
25
+ | `docs/agent-notes/benchmarks.md` | `2d3b120ab177e4fd9e6f991d038c22ca4ccb6977` | unchanged | Only deny/process helper re-exports changed in the covered source delta; runner, sandbox and retained benchmark contracts remain accurate. |
26
+ | `docs/agent-notes/budget.md` | `0463ea1f251cea17ec7f32a2861de8c554fe4062` | unchanged | Budget semantics remain unchanged; reviewed shared bus/daemon wiring and retained quota/hold contracts. |
27
+ | `docs/agent-notes/bus.md` | `0463ea1f251cea17ec7f32a2861de8c554fe4062` | corrected | Recall preface merge/deduplication and delivery/counter observation boundaries. |
28
+ | `docs/agent-notes/daemon.md` | `0463ea1f251cea17ec7f32a2861de8c554fe4062` | corrected | Person-only diagnostics wording includes authenticated status and person CLI receipts; reduced shell-readable status stays distinct. |
29
+ | `docs/agent-notes/local-worker.md` | `6dcc7fe00c38f13613bcf53524fa3d1527a708e5` | unchanged | Single-source hardened git/deny re-exports and local-worker memory-tool capture exclusions already match the final source. |
30
+ | `docs/agent-notes/tasks.md` | `0463ea1f251cea17ec7f32a2861de8c554fe4062` | corrected | Revision-bound task/queue controls and the current peer's own acceptance since its latest ownership event. |
31
+ | `docs/agent-notes/tests.md` | `0463ea1f251cea17ec7f32a2861de8c554fe4062` | corrected | Test preload clears inherited AMEM_HOME as well as isolating AGENTHUB_HOME. |
32
+ | `docs/operations.md` | `0463ea1f251cea17ec7f32a2861de8c554fe4062` | corrected | Bun/current version, package/profile rollout, screened tools and candidates, recall, withdrawal evidence and preserved-runtime attachment behavior. |
33
+ | `docs/quickstart.md` | `0463ea1f251cea17ec7f32a2861de8c554fe4062` | corrected | Bun/current release example and person profile-check with upgrade/quiesce/migration order. |
34
+ | `docs/security.md` | `0463ea1f251cea17ec7f32a2861de8c554fe4062` | corrected | First-party platform helper and memory credentials boundary, screened read/correction tools, sidecar isolation and non-atomic profile transition. |
35
+
36
+ The unstamped memory integration guide also clarifies person CLI diagnostics and the all-hubs-0.12.30 migration prerequisite.
37
+
38
+ Reviewed source commit `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` contains the reviewed content, package version and generated plugin assets. A separate manifest follow-up stamps that full source SHA; the manifest need not stamp itself. The release PR must be merged with a merge commit so every stamp remains an ancestor. Before tagging, run `node scripts/check-docs.mjs --require-fresh` on the committed tree again. Source freshness is not a certification of native/live behavior.
39
+
40
+ ## Recorded checks
41
+
42
+ The following existing PR receipts were read back from GitHub at their final heads. Every listed run reports successful Ubuntu, macOS and seeded-guard jobs; these are recorded prior gates, not a substitute for the release candidate's own CI.
43
+
44
+ | PR | Final head | CI run | Recorded result |
45
+ | --- | --- | --- | --- |
46
+ | [#413](https://github.com/STAIxBWLB/agent-hub/pull/413) | `fc25b2ba765196bc403c834d2c136e0b33481c1e` | [38814762057](https://github.com/STAIxBWLB/agent-hub/actions/runs/38814762057) | Ubuntu/macOS `check: OK`; seeded guards passed |
47
+ | [#415](https://github.com/STAIxBWLB/agent-hub/pull/415) | `cc1d70e4984a7a9dc2aee2f1359e749cf31d1b8b` | [38825015199](https://github.com/STAIxBWLB/agent-hub/actions/runs/38825015199) | Ubuntu/macOS `check: OK`; seeded guards passed |
48
+ | [#417](https://github.com/STAIxBWLB/agent-hub/pull/417) | `80d61f5b2fb483a8b33693cca2fcb9c7b9b6d57b` | [38848260715](https://github.com/STAIxBWLB/agent-hub/actions/runs/38848260715) | Ubuntu/macOS `check: OK`; seeded guards passed |
49
+ | [#419](https://github.com/STAIxBWLB/agent-hub/pull/419) | `0a3a8cc253be65911224ddd7e5495d4caffba29c` | [38855570074](https://github.com/STAIxBWLB/agent-hub/actions/runs/38855570074) | Ubuntu/macOS `check: OK`; seeded guards passed |
50
+ | [#420](https://github.com/STAIxBWLB/agent-hub/pull/420) | `649d368d73130bdffcb90109d8125b9135515a30` | [38855611042](https://github.com/STAIxBWLB/agent-hub/actions/runs/38855611042) | Ubuntu/macOS `check: OK`; seeded guards passed |
51
+ | [#421](https://github.com/STAIxBWLB/agent-hub/pull/421) | `d43d3e1047e0aeca4bd074ee17e854ff3e204a13` | [38862981281](https://github.com/STAIxBWLB/agent-hub/actions/runs/38862981281) | Ubuntu/macOS `check: OK`; seeded guards passed |
52
+ | [#422](https://github.com/STAIxBWLB/agent-hub/pull/422) | `8e5ddc7e6cec38d3b6f38d1a3e88d97a9cd15f79` | [38870904837](https://github.com/STAIxBWLB/agent-hub/actions/runs/38870904837) | Ubuntu/macOS `check: OK`; seeded guards passed |
53
+ | [#423](https://github.com/STAIxBWLB/agent-hub/pull/423) | `e934357ce089e3a6fbff9d71de50dd494aebc4b2` | [38878006900](https://github.com/STAIxBWLB/agent-hub/actions/runs/38878006900) | Ubuntu/macOS `check: OK`; seeded guards passed |
54
+ | [#425](https://github.com/STAIxBWLB/agent-hub/pull/425) | `c8ea0f2a64c4443d54e867122709d16c95197f04` | [38894400519](https://github.com/STAIxBWLB/agent-hub/actions/runs/38894400519) | Ubuntu/macOS `check: OK`; seeded guards passed |
55
+ | [#426](https://github.com/STAIxBWLB/agent-hub/pull/426) | `cf293a202605c664a1f74ce8407731be557dfc7f` | [38901783257](https://github.com/STAIxBWLB/agent-hub/actions/runs/38901783257) | Ubuntu/macOS `check: OK`; seeded guards passed |
56
+ | [#427](https://github.com/STAIxBWLB/agent-hub/pull/427) | `0a1b7bc984595b41ba36c15ba1ce88f5983abead` | [38923859188](https://github.com/STAIxBWLB/agent-hub/actions/runs/38923859188) | Ubuntu/macOS `check: OK`; seeded guards passed |
57
+ | [#429](https://github.com/STAIxBWLB/agent-hub/pull/429) | `b0a8e130f6c95e2766a6485ba05f170ef0b8b58c` | [38931755760](https://github.com/STAIxBWLB/agent-hub/actions/runs/38931755760) | Ubuntu/macOS `check: OK`; seeded guards passed |
58
+ | [#430](https://github.com/STAIxBWLB/agent-hub/pull/430) | `138aa9d175152b050a13cd4eafa6154aced56eb4` | [38936506477](https://github.com/STAIxBWLB/agent-hub/actions/runs/38936506477) | Ubuntu/macOS `check: OK`; seeded guards passed |
59
+
60
+ - Preparation: `bun install --frozen-lockfile` and `bun run build` completed under resource admission on the remote Linux runner. The generated plugin is 598 KB and its manifest is stamped 0.12.30; no dependency tree was copied to the Mac.
61
+ - Preparation checks: `bun x tsc --noEmit` and bundle freshness passed on the admitted remote runner; `node scripts/check-package.mjs` reported `package: OK (272 files, @staix/agent-hub@0.12.30)`.
62
+ - The final committed candidate requires its own `scripts/check.sh` or exact-head PR CI on Ubuntu/macOS, including seeded guards, before merge. Committed document freshness and stamp ancestry are checked independently; the tag workflow requires successful CI for the identical release tree before npm publication.
63
+ - The retained source/fixture tests for profile binding, package preservation and same-home cross-writes do not prove an installed native session upgrade or real migration.
64
+
65
+ ## Not verified by this record
66
+
67
+ - Native/live legs in #273 and #1 remain open according to their own ledgers. This release preparation does not turn fixture, CLI or historical operational evidence into native success.
68
+ - #412 P5 live legs L03 (real claude-mem import), L04 (real model suggestions and person confirmation) and L05 (Memory/Long-term tasks visual checks) remain unrun.
69
+ - The person's real-home migration, real remote synchronization and post-migration profile/prune readbacks are not performed in this task. Inventory/quiesce/reopen and runtime capability receipts are prerequisites, not completed results.
70
+ - npm publication/provenance, global CLI and plugin installation, running-hub upgrade, recovery completion and native session continuity need separate readbacks after the release is authorized and executed.
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "documents": {
4
4
  "README.md": {
5
- "verifiedAgainst": "0463ea1f251cea17ec7f32a2861de8c554fe4062",
5
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
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": "0463ea1f251cea17ec7f32a2861de8c554fe4062",
14
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
15
15
  "paths": [
16
16
  "src/",
17
17
  "templates/"
18
18
  ]
19
19
  },
20
20
  "docs/operations.md": {
21
- "verifiedAgainst": "0463ea1f251cea17ec7f32a2861de8c554fe4062",
21
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
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": "0463ea1f251cea17ec7f32a2861de8c554fe4062",
38
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
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": "0463ea1f251cea17ec7f32a2861de8c554fe4062",
46
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
47
47
  "paths": [
48
48
  "src/adapters/",
49
49
  "src/pi/",
@@ -62,7 +62,7 @@
62
62
  ]
63
63
  },
64
64
  "docs/agent-notes/benchmarks.md": {
65
- "verifiedAgainst": "2d3b120ab177e4fd9e6f991d038c22ca4ccb6977",
65
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
66
66
  "paths": [
67
67
  "scripts/benchmarks/",
68
68
  "test/benchmarks/",
@@ -74,7 +74,7 @@
74
74
  ]
75
75
  },
76
76
  "docs/agent-notes/budget.md": {
77
- "verifiedAgainst": "0463ea1f251cea17ec7f32a2861de8c554fe4062",
77
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
78
78
  "paths": [
79
79
  "src/hub/budget.ts",
80
80
  "src/cli/statusline-tee.ts",
@@ -86,7 +86,7 @@
86
86
  ]
87
87
  },
88
88
  "docs/agent-notes/bus.md": {
89
- "verifiedAgainst": "0463ea1f251cea17ec7f32a2861de8c554fe4062",
89
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
90
90
  "paths": [
91
91
  "src/hub/bus.ts",
92
92
  "src/hub/envelope.ts",
@@ -98,7 +98,7 @@
98
98
  ]
99
99
  },
100
100
  "docs/agent-notes/daemon.md": {
101
- "verifiedAgainst": "0463ea1f251cea17ec7f32a2861de8c554fe4062",
101
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
102
102
  "paths": [
103
103
  "src/hub/daemon.ts",
104
104
  "src/hub/control-client.ts",
@@ -135,7 +135,7 @@
135
135
  ]
136
136
  },
137
137
  "docs/agent-notes/local-worker.md": {
138
- "verifiedAgainst": "6dcc7fe00c38f13613bcf53524fa3d1527a708e5",
138
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
139
139
  "paths": [
140
140
  "src/adapters/local-worker.ts",
141
141
  "src/local/",
@@ -155,7 +155,7 @@
155
155
  ]
156
156
  },
157
157
  "docs/agent-notes/tasks.md": {
158
- "verifiedAgainst": "0463ea1f251cea17ec7f32a2861de8c554fe4062",
158
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
159
159
  "paths": [
160
160
  "src/hub/tasks.ts",
161
161
  "src/hub/board.ts",
@@ -172,7 +172,7 @@
172
172
  ]
173
173
  },
174
174
  "docs/agent-notes/tests.md": {
175
- "verifiedAgainst": "0463ea1f251cea17ec7f32a2861de8c554fe4062",
175
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
176
176
  "paths": [
177
177
  "test/",
178
178
  "scripts/check.sh",
@@ -191,7 +191,7 @@
191
191
  ]
192
192
  },
193
193
  "docs/agent-notes/README.md": {
194
- "verifiedAgainst": "0463ea1f251cea17ec7f32a2861de8c554fe4062",
194
+ "verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
195
195
  "paths": [
196
196
  "src/cli/console-state.ts",
197
197
  "src/cli/attention.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staix/agent-hub",
3
- "version": "0.12.29",
3
+ "version": "0.12.30",
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",
@@ -14,7 +14,10 @@
14
14
  "test": "bun test"
15
15
  },
16
16
  "engines": {
17
- "bun": ">=1.3.0"
17
+ "bun": ">=1.4.2"
18
+ },
19
+ "dependencies": {
20
+ "@staix/agent-mem": "0.3.0"
18
21
  },
19
22
  "devDependencies": {
20
23
  "@modelcontextprotocol/sdk": "^1.27.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-hub",
3
- "version": "0.12.29",
3
+ "version": "0.12.30",
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",
@@ -6922,24 +6922,16 @@ var require_dist = __commonJS(function(exports, module) {
6922
6922
 
6923
6923
  // src/hub/control-client.ts
6924
6924
  import { readFileSync as readFileSync2 } from "fs";
6925
- import { join as join2 } from "path";
6925
+ import { join as join3 } from "path";
6926
6926
 
6927
6927
  // src/hub/project.ts
6928
- import { existsSync, lstatSync, readFileSync, realpathSync } from "fs";
6929
- import { basename, dirname, isAbsolute, join, resolve } from "path";
6930
-
6931
- // src/hub/git.ts
6932
- import { spawnSync } from "child_process";
6933
- var SAFE_CONFIG = ["core.fsmonitor=false", "core.hooksPath=/dev/null", "diff.external=", "core.pager=cat", "credential.helper=", "core.askpass="];
6934
- var CREDENTIAL_KEYS = new Set(["credential.helper=", "core.askpass="]);
6935
- var hubGitArgv = (args, opts = {}) => ["git", "--no-pager", ...SAFE_CONFIG.filter((c) => !opts.credentials || !CREDENTIAL_KEYS.has(c)).flatMap((c) => ["-c", c]), ...args];
6936
- var hubGitEnv = (env = process.env) => ({ ...env, GIT_TERMINAL_PROMPT: "0" });
6937
- function hubGitSync(args, options) {
6938
- const argv = hubGitArgv(args);
6939
- return spawnSync(argv[0], argv.slice(1), { ...options, env: hubGitEnv(options.env ?? process.env) });
6940
- }
6928
+ import { existsSync, lstatSync, readFileSync } from "fs";
6929
+ import { dirname as dirname2, isAbsolute, join as join2, resolve as resolve2 } from "path";
6941
6930
 
6942
- // src/hub/project.ts
6931
+ // node_modules/@staix/agent-mem/src/memory/platform.ts
6932
+ import { realpathSync } from "fs";
6933
+ import { basename, dirname, join, resolve, sep } from "path";
6934
+ import { spawnSync, execFileSync } from "child_process";
6943
6935
  var canonical = (path) => {
6944
6936
  const absolute = resolve(path);
6945
6937
  try {
@@ -6949,21 +6941,42 @@ var canonical = (path) => {
6949
6941
  return parent === absolute ? absolute : join(canonical(parent), basename(absolute));
6950
6942
  }
6951
6943
  };
6944
+ function canonicalPath(path) {
6945
+ return canonical(path);
6946
+ }
6947
+ var SAFE_CONFIG = ["core.fsmonitor=false", "core.hooksPath=/dev/null", "diff.external=", "core.pager=cat", "credential.helper=", "core.askpass="];
6948
+ var CREDENTIAL_KEYS = new Set(["credential.helper=", "core.askpass="]);
6949
+ var memoryGitArgv = (args, opts = {}) => ["git", "--no-pager", ...SAFE_CONFIG.filter((c) => !opts.credentials || !CREDENTIAL_KEYS.has(c)).flatMap((c) => ["-c", c]), ...args];
6950
+ function memoryGitEnv(env = process.env, options = {}) {
6951
+ const result = { ...env, GIT_TERMINAL_PROMPT: "0" };
6952
+ if (options.repositoryIsolation) {
6953
+ for (const key of Object.keys(result))
6954
+ if (["GIT_DIR", "GIT_COMMON_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE", "GIT_OBJECT_DIRECTORY", "GIT_ALTERNATE_OBJECT_DIRECTORIES", "GIT_NAMESPACE", "GIT_PREFIX", "GIT_SHALLOW_FILE", "GIT_GRAFT_FILE", "GIT_REPLACE_REF_BASE", "GIT_CONFIG_COUNT", "GIT_CONFIG_PARAMETERS"].includes(key) || /^GIT_CONFIG_(KEY|VALUE)_/.test(key))
6955
+ delete result[key];
6956
+ result.GIT_NO_REPLACE_OBJECTS = "1";
6957
+ }
6958
+ return result;
6959
+ }
6960
+ function memoryGitSync(args, options) {
6961
+ const argv = memoryGitArgv(args);
6962
+ return spawnSync(argv[0], argv.slice(1), { ...options, env: memoryGitEnv(options.env ?? process.env) });
6963
+ }
6964
+ // src/hub/project.ts
6952
6965
  function gitRoot(dir) {
6953
- const result = hubGitSync(["-C", dir, "rev-parse", "--show-toplevel"], { encoding: "utf8" });
6966
+ const result = memoryGitSync(["-C", dir, "rev-parse", "--show-toplevel"], { encoding: "utf8" });
6954
6967
  if (result.status !== 0)
6955
6968
  return;
6956
6969
  const root = result.stdout.trim();
6957
- return root ? canonical(root) : undefined;
6970
+ return root ? canonicalPath(root) : undefined;
6958
6971
  }
6959
6972
  function hasConfig(dir) {
6960
- return existsSync(join(dir, ".agenthub", "config.json"));
6973
+ return existsSync(join2(dir, ".agenthub", "config.json"));
6961
6974
  }
6962
6975
  function projectRoot(cwd) {
6963
- const input = isAbsolute(cwd) ? cwd : resolve(cwd);
6976
+ const input = isAbsolute(cwd) ? cwd : resolve2(cwd);
6964
6977
  let dir;
6965
6978
  try {
6966
- dir = canonical(input);
6979
+ dir = canonicalPath(input);
6967
6980
  if (!lstatSync(dir).isDirectory())
6968
6981
  throw new Error(`${cwd} is not a directory`);
6969
6982
  } catch (error) {
@@ -6971,27 +6984,27 @@ function projectRoot(cwd) {
6971
6984
  }
6972
6985
  const boundary = gitRoot(dir);
6973
6986
  const stop = boundary ?? parseRoot(dir);
6974
- for (let current = dir;; current = dirname(current)) {
6987
+ for (let current = dir;; current = dirname2(current)) {
6975
6988
  if (hasConfig(current))
6976
- return canonical(current);
6977
- if (current === stop || current === dirname(current))
6989
+ return canonicalPath(current);
6990
+ if (current === stop || current === dirname2(current))
6978
6991
  break;
6979
6992
  }
6980
6993
  return boundary ?? dir;
6981
6994
  }
6982
6995
  function parseRoot(dir) {
6983
6996
  let current = dir;
6984
- while (dirname(current) !== current)
6985
- current = dirname(current);
6997
+ while (dirname2(current) !== current)
6998
+ current = dirname2(current);
6986
6999
  return current;
6987
7000
  }
6988
7001
  function stateMarker(stateDir) {
6989
- for (const file of [join(stateDir, "project.json"), join(stateDir, "status.json")]) {
7002
+ for (const file of [join2(stateDir, "project.json"), join2(stateDir, "status.json")]) {
6990
7003
  try {
6991
7004
  const value = JSON.parse(readFileSync(file, "utf8"));
6992
7005
  const root = value.root ?? value.cwd;
6993
7006
  if (typeof root === "string")
6994
- return canonical(root);
7007
+ return canonicalPath(root);
6995
7008
  } catch {}
6996
7009
  }
6997
7010
  return;
@@ -7000,15 +7013,15 @@ function projectContext(cwd, env = process.env) {
7000
7013
  const root = projectRoot(cwd);
7001
7014
  const override = env.AGENTHUB_STATE_DIR?.trim();
7002
7015
  if (!override)
7003
- return { root, stateDir: canonical(join(root, ".agenthub", "state")) };
7016
+ return { root, stateDir: canonicalPath(join2(root, ".agenthub", "state")) };
7004
7017
  const declared = env.AGENTHUB_PROJECT_DIR?.trim();
7005
- const stateDir = canonical(override);
7018
+ const stateDir = canonicalPath(override);
7006
7019
  const recorded = stateMarker(stateDir);
7007
7020
  if (recorded === root)
7008
7021
  return { root, stateDir };
7009
- if (!recorded && declared && canonical(declared) === root)
7022
+ if (!recorded && declared && canonicalPath(declared) === root)
7010
7023
  return { root, stateDir };
7011
- return { root, stateDir: canonical(join(root, ".agenthub", "state")) };
7024
+ return { root, stateDir: canonicalPath(join2(root, ".agenthub", "state")) };
7012
7025
  }
7013
7026
 
7014
7027
  // src/hub/control-client.ts
@@ -7019,8 +7032,8 @@ var PROTOCOL = 16;
7019
7032
  var RECOVERY_SOURCE_PROTOCOLS = [9, 10, 11, 12, 13, 14, 15, PROTOCOL];
7020
7033
  function readControl(stateDir) {
7021
7034
  try {
7022
- const status = JSON.parse(readFileSync2(join2(stateDir, "status.json"), "utf8"));
7023
- const token = readFileSync2(join2(stateDir, "control-token"), "utf8").trim();
7035
+ const status = JSON.parse(readFileSync2(join3(stateDir, "status.json"), "utf8"));
7036
+ const token = readFileSync2(join3(stateDir, "control-token"), "utf8").trim();
7024
7037
  if (!Number.isInteger(status.controlPort) || status.controlPort < 1 || status.controlPort > 65535 || !token)
7025
7038
  return;
7026
7039
  return {
@@ -7318,7 +7331,7 @@ var OUTCOMES_KEPT_MS = 7 * 24 * 3600000;
7318
7331
  // src/hub/roles.ts
7319
7332
  import { createHash } from "crypto";
7320
7333
  import { constants, closeSync, fstatSync, lstatSync as lstatSync2, openSync, readSync, readdirSync } from "fs";
7321
- import { join as join3 } from "path";
7334
+ import { join as join4 } from "path";
7322
7335
 
7323
7336
  // templates/roles/dev/software-architect.md
7324
7337
  var software_architect_default = `---
@@ -7738,7 +7751,7 @@ function loadRoleCatalog(cwd) {
7738
7751
  if (!cwd)
7739
7752
  return { roles, errors };
7740
7753
  try {
7741
- const config = join3(cwd, ".agenthub"), dir = join3(config, "roles");
7754
+ const config = join4(cwd, ".agenthub"), dir = join4(config, "roles");
7742
7755
  for (const path of [config, dir]) {
7743
7756
  const stat = lstatSync2(path);
7744
7757
  if (!stat.isDirectory() || stat.isSymbolicLink())
@@ -7750,7 +7763,7 @@ function loadRoleCatalog(cwd) {
7750
7763
  for (const file of files) {
7751
7764
  const id = file.slice(0, -3);
7752
7765
  try {
7753
- roles.set(id, parseRole(projectRole(join3(dir, file)), id, "project"));
7766
+ roles.set(id, parseRole(projectRole(join4(dir, file)), id, "project"));
7754
7767
  } catch {
7755
7768
  errors.push({ id: ID.test(id) ? id : "invalid-file-id", reason: "invalid or unsafe project role" });
7756
7769
  }
@@ -16153,11 +16166,11 @@ class StdioServerTransport {
16153
16166
 
16154
16167
  // src/adapters/claude-channel.ts
16155
16168
  import { readFileSync as readFileSync3 } from "fs";
16156
- import { join as join4 } from "path";
16169
+ import { join as join5 } from "path";
16157
16170
  // package.json
16158
16171
  var package_default = {
16159
16172
  name: "@staix/agent-hub",
16160
- version: "0.12.29",
16173
+ version: "0.12.30",
16161
16174
  description: "Native multi-agent hub: Claude Code, Codex, Kimi Code, Pi and local inference as peers in one project",
16162
16175
  license: "MIT",
16163
16176
  type: "module",
@@ -16171,7 +16184,10 @@ var package_default = {
16171
16184
  test: "bun test"
16172
16185
  },
16173
16186
  engines: {
16174
- bun: ">=1.3.0"
16187
+ bun: ">=1.4.2"
16188
+ },
16189
+ dependencies: {
16190
+ "@staix/agent-mem": "0.3.0"
16175
16191
  },
16176
16192
  devDependencies: {
16177
16193
  "@modelcontextprotocol/sdk": "^1.27.1",
@@ -16265,7 +16281,11 @@ var TASK_TOOLS = [
16265
16281
  tool("hub_task_list", "The task board. PII tasks show as [pii].", { state: { type: "string", enum: ["proposed", "in_progress", "in_review", "approved", "changes_requested"] }, ready: { type: "boolean", description: "only proposed tasks with nothing left to wait for" } }),
16266
16282
  tool("hub_review", "Give your verdict on a task you were asked to review: map the changed signatures and call sites to the task's plan or detail, read the check result (hub_task_show has it, with the done summary), and list what is unmet. Two changes_requested in a row move the task to another peer.", { id, head: { type: "string", description: "full SHA actually reviewed; enforce binds approval to the current PR head" }, verdict: { type: "string", enum: ["approved", "changes_requested"] }, note: str, unmet: { type: "array", items: str, description: "each requirement of the plan or detail that the change does not meet" } }, ["id", "verdict"]),
16267
16283
  tool("hub_checkpoint", "Answer a checkpoint request from the hub (quota or context window pressure): what you were doing, what is half done, what whoever continues must know. Write the same to .agenthub/checkpoint.md first if you can.", { summary: str, request_id: { type: "string", description: "The request id supplied by a context checkpoint request; required for context checkpoints" } }, ["summary"]),
16268
- tool("hub_remember", "Save a decision, finding, contract or fail to the memory all agents share (the hub's memory and claude-mem); the other agents also get it with their next message. A fail is an approach you tried that does not work, and why: the most useful note, it stops the others spending their quota on it. Do not retry what a fail note rules out without new evidence. Conclusions worth recalling, not chatter. A note on an open task is short-term until the task is approved, when its decisions, contracts and fails become long-term; horizon long keeps it now, scope shared lets the person's other projects find it.", { text: str, title: str, kind: { type: "string", enum: [...NOTE_KINDS] }, task: id, horizon: { type: "string", enum: ["short", "long"] }, scope: { type: "string", enum: ["project", "shared"] } }, ["text"])
16284
+ tool("hub_memory_search", "Search daemon-scoped visible memory, fails first. Query <=200 UTF-8 bytes; default 8, max 20 lines; whole output <=4 KB. Incomplete excerpts are marked. No project argument.", { query: { type: "string", maxLength: 200, description: "At most 200 UTF-8 bytes, enforced by the daemon" }, limit: { type: "integer", minimum: 1, maximum: 20 } }, ["query"]),
16285
+ tool("hub_memory_show", "Read up to 8 visible memory ids or unique prefixes (6..64 UTF-8 bytes each). Original ids redirect; unavailable ids share one refusal. Whole output <=8 KB.", { ids: { type: "array", minItems: 1, maxItems: 8, items: { type: "string", minLength: 6, maxLength: 64, description: "6 to 64 UTF-8 bytes" } } }, ["ids"]),
16286
+ tool("hub_memory_graph", "Read screened memory neighbourhoods, fails first. Up to 8 starts (<=200 UTF-8 bytes each), 1 or 2 hops; default 60/max 120 nodes, max 240 edges, whole output <=6 KB. No project argument.", { starts: { type: "array", minItems: 1, maxItems: 8, items: { type: "string", minLength: 1, maxLength: 200, description: "At most 200 UTF-8 bytes" } }, hops: { type: "integer", enum: [1, 2] }, limit: { type: "integer", minimum: 1, maximum: 120 } }, ["starts"]),
16287
+ tool("hub_memory_correct", "Propose a correction to a visible memory entry. This creates a machine-local candidate only; a person accepts or rejects it with amem review. It never edits a note. id is an exact id or unique visible prefix; text and reason must each fit 4000 UTF-8 bytes.", { id: str, text: str, reason: str }, ["id", "text", "reason"]),
16288
+ tool("hub_remember", "Save a decision, finding, contract or fail to the memory all agents share (the hub's memory and claude-mem); the other agents also get it with their next message. A fail is an approach you tried that does not work, and why: the most useful note, it stops the others spending their quota on it. Do not retry what a fail note rules out without new evidence. Conclusions worth recalling, not chatter. For kind fail, optional approach, symptom, cause, evidence and retry_when strings compose fixed labeled text; text may be omitted when structured fields are supplied. The complete text must fit 4000 UTF-8 bytes and is refused, never truncated, when oversized. A note on an open task is short-term until the task is approved, when its decisions, contracts and fails become long-term; horizon long keeps it now, scope shared lets the person's other projects find it.", { text: str, approach: str, symptom: str, cause: str, evidence: str, retry_when: str, title: str, kind: { type: "string", enum: [...NOTE_KINDS] }, task: id, horizon: { type: "string", enum: ["short", "long"] }, scope: { type: "string", enum: ["project", "shared"] } })
16269
16289
  ];
16270
16290
  var TASK_TOOL_NAMES = new Set(TASK_TOOLS.map((t) => t.name));
16271
16291
  var CONDUCTOR_TOOLS = [
@@ -16328,7 +16348,7 @@ var channel = !toolsMode && process.env.AGENTHUB_CHANNEL === "1";
16328
16348
  function roles() {
16329
16349
  const read = (name) => {
16330
16350
  try {
16331
- return JSON.parse(readFileSync3(join4(projectRoot2, ".agenthub", name), "utf8")).roles ?? {};
16351
+ return JSON.parse(readFileSync3(join5(projectRoot2, ".agenthub", name), "utf8")).roles ?? {};
16332
16352
  } catch {
16333
16353
  return {};
16334
16354
  }
@@ -16341,7 +16361,7 @@ function sessionProfile() {
16341
16361
  for (const name of ["config.json", "config.local.json"]) {
16342
16362
  let data;
16343
16363
  try {
16344
- data = JSON.parse(readFileSync3(join4(projectRoot2, ".agenthub", name), "utf8"));
16364
+ data = JSON.parse(readFileSync3(join5(projectRoot2, ".agenthub", name), "utf8"));
16345
16365
  } catch (error) {
16346
16366
  if (error.code === "ENOENT")
16347
16367
  continue;
@@ -16368,7 +16388,7 @@ function sessionRoles() {
16368
16388
  const read = (name) => {
16369
16389
  let raw;
16370
16390
  try {
16371
- raw = JSON.parse(readFileSync3(join4(projectRoot2, ".agenthub", name), "utf8")).catalog_roles;
16391
+ raw = JSON.parse(readFileSync3(join5(projectRoot2, ".agenthub", name), "utf8")).catalog_roles;
16372
16392
  } catch {
16373
16393
  return {};
16374
16394
  }
@@ -16397,7 +16417,7 @@ var HELD = `another session is attached to the hub as "${peerId}"; this one is s
16397
16417
  var INBOX_CAP = 200;
16398
16418
  function peerHeld() {
16399
16419
  try {
16400
- const status = JSON.parse(readFileSync3(join4(stateDir, "status.json"), "utf8"));
16420
+ const status = JSON.parse(readFileSync3(join5(stateDir, "status.json"), "utf8"));
16401
16421
  const peer = status.peers?.[peerId];
16402
16422
  if (channel && peer?.toolsOnly && !peer.claiming)
16403
16423
  return false;