@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.
- package/CHANGELOG.md +18 -0
- package/README.md +79 -219
- package/docs/agent-notes/README.md +12 -0
- package/docs/agent-notes/adapters.md +1 -1
- package/docs/agent-notes/bus.md +3 -1
- package/docs/agent-notes/daemon.md +10 -0
- package/docs/agent-notes/local-worker.md +2 -2
- package/docs/agent-notes/tasks.md +9 -0
- package/docs/agent-notes/tests.md +1 -1
- package/docs/memory.md +70 -152
- package/docs/operations.md +199 -14
- package/docs/plans/2026-10-16-amem-failure-registry.md +101 -0
- package/docs/plans/2026-10-16-amem-p0-baseline.md +110 -0
- package/docs/plans/2026-10-16-amem-p2-read-tools.md +28 -0
- package/docs/plans/amem-cases.json +482 -0
- package/docs/quickstart.md +9 -2
- package/docs/security.md +13 -1
- package/docs/smoke.md +11 -0
- package/docs/specs/2026-09-19-agent-hub-design.md +105 -4
- package/docs/verification/2026-10-17-0.12.30.md +70 -0
- package/docs/verified.json +13 -13
- package/package.json +5 -2
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +64 -44
- package/src/cli/console-state.ts +92 -20
- package/src/cli/console.ts +22 -5
- package/src/cli/help.ts +3 -2
- package/src/cli/identity.ts +1 -1
- package/src/cli/main.js +2 -2
- package/src/cli/main.ts +36 -14
- package/src/cli/memory.ts +87 -187
- package/src/cli/output.ts +6 -0
- package/src/cli/recovery-package.ts +59 -10
- package/src/cli/upgrade-runtime.ts +54 -17
- package/src/cli/upgrade.ts +8 -0
- package/src/hub/board.ts +2 -1
- package/src/hub/bus.ts +33 -12
- package/src/hub/daemon.ts +134 -27
- package/src/hub/envelope.ts +30 -0
- package/src/hub/git.ts +2 -38
- package/src/hub/hub-tools.ts +5 -1
- package/src/hub/manager.ts +1 -1
- package/src/hub/memory-candidates.ts +103 -0
- package/src/hub/memory-fail.ts +25 -0
- package/src/hub/memory-observations.ts +47 -0
- package/src/hub/memory-plan-guard.ts +33 -0
- package/src/hub/memory-policy.ts +42 -0
- package/src/hub/memory-profile-check.ts +170 -0
- package/src/hub/memory-profile.ts +192 -0
- package/src/hub/memory-staleness.ts +55 -0
- package/src/hub/path-policy.ts +8 -0
- package/src/hub/project.ts +4 -37
- package/src/hub/read-tools.ts +127 -0
- package/src/hub/tasks.ts +201 -41
- package/src/local/deny.ts +4 -17
- package/src/memory/brief.ts +8 -5
- package/src/memory/capture.ts +2 -1
- package/src/memory/recall.ts +50 -110
- package/src/pi/process-signature.ts +2 -42
- package/src/memory/import.ts +0 -90
- package/src/memory/store.ts +0 -805
- 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
|
|
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`, `
|
|
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.
|
package/docs/verified.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"documents": {
|
|
4
4
|
"README.md": {
|
|
5
|
-
"verifiedAgainst": "
|
|
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": "
|
|
14
|
+
"verifiedAgainst": "79a113dfc4395a0e00890ba8b8d2d90bb289ee9f",
|
|
15
15
|
"paths": [
|
|
16
16
|
"src/",
|
|
17
17
|
"templates/"
|
|
18
18
|
]
|
|
19
19
|
},
|
|
20
20
|
"docs/operations.md": {
|
|
21
|
-
"verifiedAgainst": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
6925
|
+
import { join as join3 } from "path";
|
|
6926
6926
|
|
|
6927
6927
|
// src/hub/project.ts
|
|
6928
|
-
import { existsSync, lstatSync, readFileSync
|
|
6929
|
-
import {
|
|
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/
|
|
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 =
|
|
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 ?
|
|
6970
|
+
return root ? canonicalPath(root) : undefined;
|
|
6958
6971
|
}
|
|
6959
6972
|
function hasConfig(dir) {
|
|
6960
|
-
return existsSync(
|
|
6973
|
+
return existsSync(join2(dir, ".agenthub", "config.json"));
|
|
6961
6974
|
}
|
|
6962
6975
|
function projectRoot(cwd) {
|
|
6963
|
-
const input = isAbsolute(cwd) ? cwd :
|
|
6976
|
+
const input = isAbsolute(cwd) ? cwd : resolve2(cwd);
|
|
6964
6977
|
let dir;
|
|
6965
6978
|
try {
|
|
6966
|
-
dir =
|
|
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 =
|
|
6987
|
+
for (let current = dir;; current = dirname2(current)) {
|
|
6975
6988
|
if (hasConfig(current))
|
|
6976
|
-
return
|
|
6977
|
-
if (current === stop || 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 (
|
|
6985
|
-
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 [
|
|
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
|
|
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:
|
|
7016
|
+
return { root, stateDir: canonicalPath(join2(root, ".agenthub", "state")) };
|
|
7004
7017
|
const declared = env.AGENTHUB_PROJECT_DIR?.trim();
|
|
7005
|
-
const stateDir =
|
|
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 &&
|
|
7022
|
+
if (!recorded && declared && canonicalPath(declared) === root)
|
|
7010
7023
|
return { root, stateDir };
|
|
7011
|
-
return { root, stateDir:
|
|
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(
|
|
7023
|
-
const token = readFileSync2(
|
|
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
|
|
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 =
|
|
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(
|
|
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
|
|
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.
|
|
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.
|
|
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("
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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;
|