Repository navigation
refactor: workspace isolation across runtime surfaces - #145
Conversation
Hard cut workspace isolation across Network, session, observe, hooks, and memory session surfaces. - Qualify AGH Network identity by workspace across store, API, CLI, native, SDK, web, generated references, and docs. - Scope session by-ID, observe events, HookRuns, and memory session ledger/replay routes with route workspace ownership validation. - Add canonical Go, web, SDK, site, and static subject coverage plus the QA contract discovery helper used by release QA. - Regenerate OpenAPI, web contracts, and runtime/site references.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThis PR adds workspace-scoped routing and payload fields across API, CLI, extension, daemon, and network flows, updates network protocol/runtime workspace handling, adds prompt delivery metadata and runtime prompt sections, and refreshes tests, specs, and helpers to match the new scoped behavior. ChangesWorkspace-scoped API and transport updates
Workspace-aware clients and tool surfaces
Workspace-scoped network runtime
Prompt and runtime prompt changes
Small supporting changes
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
|
There was a problem hiding this comment.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
internal/extension/contract/host_api.go (1)
827-830:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
observe.eventsis still advertised as parameter-optional.
ObserveEventsParamsnow requiresworkspace_id, butHostAPIMethodObserveEventsstill setsOptionalParams: true. That leaves the generated Host API contract saying callers may omit params even though the runtime now needs workspace scope, so extensions can type-check and then fail at runtime.Please make the method spec non-optional to keep the generated contract aligned with the new workspace-scoped behavior.
Based on learnings, "No partial-surface completions — any change touching a public surface closes the loop end-to-end: contract → HTTP handler → UDS handler → CLI client → CLI command → extension/config/docs surfaces → tests → docs".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/extension/contract/host_api.go` around lines 827 - 830, The method spec advertises ObserveEventsParams as optional but ObserveEventsParams now requires workspace_id, so update HostAPIMethodObserveEvents to make params required by setting OptionalParams: false (or removing OptionalParams if default is required) so the generated contract accurately reflects that ObserveEventsParams (used by HostAPIMethodObserveEvents) is mandatory; update the HostAPIMethodObserveEvents definition accordingly to prevent callers from omitting params.internal/api/core/network_test.go (1)
951-996:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftAssert
workspace_idpropagation in service stubs used by workspace-scoped tests.The updated
ListPeersFn/ListChannelsFnsignatures acceptworkspaceID, but this segment ignores it. That allows handlers to drop/misroute workspace scoping without failing tests.Suggested hardening pattern
- ListPeersFn: func(_ context.Context, _ string, channel string) ([]network.PeerInfo, error) { + ListPeersFn: func(_ context.Context, workspaceID string, channel string) ([]network.PeerInfo, error) { + if got, want := workspaceID, "ws-workspace"; got != want { + t.Fatalf("ListPeers() workspaceID = %q, want %q", got, want) + } ... }, - ListChannelsFn: func(context.Context, string) ([]network.ChannelInfo, error) { + ListChannelsFn: func(_ context.Context, workspaceID string) ([]network.ChannelInfo, error) { + if got, want := workspaceID, "ws-workspace"; got != want { + t.Fatalf("ListChannels() workspaceID = %q, want %q", got, want) + } ... },Based on learnings: No partial-surface completions — any change touching a public surface closes the loop end-to-end: contract → HTTP handler → UDS handler → CLI client → CLI command → extension/config/docs surfaces → tests → docs.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/api/core/network_test.go` around lines 951 - 996, The test stubs for ListPeersFn and ListChannelsFn ignore the new workspaceID parameter, allowing workspace-scoped routing bugs to slip; update the stub implementations (ListPeersFn and ListChannelsFn) to validate the incoming workspaceID (e.g., assert it equals the expected test workspace id) and branch or fail the test when it does not match so workspace propagation is enforced in tests; ensure any added assertion references the workspaceID parameter and adjust returned peers/channels only for the matching workspaceID to harden workspace-scoped behavior.internal/extension/host_api_network_test.go (1)
871-893:⚠️ Potential issue | 🟠 Major | ⚡ Quick winMake workspace filtering strict in the host API network stub.
When a request provides
workspace_id, the stub currently still returns entries whoseWorkspaceIDis empty. This can mask cross-workspace isolation regressions in tests.Proposed fix
- if trimmedWorkspaceID != "" && peer.WorkspaceID != "" && peer.WorkspaceID != trimmedWorkspaceID { + if trimmedWorkspaceID != "" && peer.WorkspaceID != trimmedWorkspaceID { continue } ... - if trimmedWorkspaceID != "" && channel.WorkspaceID != "" && channel.WorkspaceID != trimmedWorkspaceID { + if trimmedWorkspaceID != "" && channel.WorkspaceID != trimmedWorkspaceID { continue }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/extension/host_api_network_test.go` around lines 871 - 893, The stub's workspace filter is too permissive: when a non-empty workspaceID is provided, entries with an empty WorkspaceID should not be returned. In hostAPINetworkServiceStub.ListChannels (and the analogous peer-listing loop), change the condition so that when trimmedWorkspaceID != "" you require channel.WorkspaceID == trimmedWorkspaceID (i.e., if channel.WorkspaceID != trimmedWorkspaceID then continue), thereby excluding entries with empty WorkspaceID instead of allowing them through.internal/network/peer.go (1)
469-505:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
ListPeerscurrently ignoreschannelwhenworkspaceIDis empty, causing an unintended broad result set.
ListPeers("", "some-channel", at)falls through to the aggregate branch and returns peers across all channels/workspaces. For workspace isolation, this should fail closed (or at least enforce explicit semantics).Suggested fail-closed fix
- if trimmedWorkspaceID != "" && trimmedChannel != "" { - return listPeersForChannelLocked(r, trimmedWorkspaceID, trimmedChannel) - } + if trimmedChannel != "" { + if trimmedWorkspaceID == "" { + return nil + } + return listPeersForChannelLocked(r, trimmedWorkspaceID, trimmedChannel) + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/network/peer.go` around lines 469 - 505, ListPeers currently only calls listPeersForChannelLocked when both trimmedWorkspaceID and trimmedChannel are non-empty, so ListPeers("", "chan", ...) falls through and returns peers across all channels; change this to fail-closed by detecting when trimmedChannel != "" but trimmedWorkspaceID == "" and returning an explicit error (or empty result) instead of aggregating. Update the early-return logic in ListPeers to check trimmedChannel alone and call listPeersForChannelLocked only when both are present, otherwise return the error/empty result; ensure references to trimmedWorkspaceID, trimmedChannel, ListPeers, and listPeersForChannelLocked are used so the fix is applied in the correct location.
🧹 Nitpick comments (7)
internal/api/core/authored_context_test.go (1)
205-221: ⚡ Quick winAssert the 404 payload too.
These subtests only check the status code and that the spies were not invoked. Please also assert the response body/error payload so the ownership-rejection contract can’t regress while still returning
404.As per coding guidelines, "In Go tests, assert both status code AND response body — status code alone is insufficient".
Also applies to: 223-243
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/api/core/authored_context_test.go` around lines 205 - 221, The test "Should reject foreign workspace heartbeat status session" currently only checks HTTP 404 and that statusSpy.calls == 0; update it to also decode and assert the response body/error payload matches the ownership-rejection contract (e.g., the JSON error structure returned by the handler) so the body and fields (error code/message and any workspace_id/session_id context) are validated; use the existing recorder to read recorder.Body, unmarshal into the expected error struct or map, and assert expected keys/values, and apply the same change to the sibling subtest at the other location that checks heartbeat rejection (the one referenced at lines 223-243) so both status code and response body are asserted.internal/api/udsapi/udsapi_integration_test.go (1)
1029-1033: ⚡ Quick winAssert resolved workspace identity matches created session workspace identity.
You resolve a workspace first, then create a session and use that session workspace for trigger scope, but never assert they match. Add an explicit equality check to make this flow deterministic.
Based on learnings: Keep execution paths deterministic and observable.Suggested patch
if resolved.Workspace.ID == "" { t.Fatal("expected resolved workspace id") } createdSession := createIntegrationSessionPayload(t, runtime) + if createdSession.WorkspaceID != resolved.Workspace.ID { + t.Fatalf( + "created session workspace_id = %q, want resolved workspace id %q", + createdSession.WorkspaceID, + resolved.Workspace.ID, + ) + } createResp := mustUnixRequest(Also applies to: 1040-1041
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/api/udsapi/udsapi_integration_test.go` around lines 1029 - 1033, Add an explicit equality assertion that the resolved workspace ID matches the workspace ID returned by the created session to make the flow deterministic: after resolving the workspace (variable resolved) and after creating the session via createIntegrationSessionPayload (variable createdSession), assert resolved.Workspace.ID == createdSession.Workspace.ID (and add the same check near the second occurrence around the 1040–1041 area) so the test fails if the session used for triggers is not the resolved workspace.internal/api/core/agent_channels_internal_test.go (1)
31-32: ⚡ Quick winValidate
workspaceIDinListChannelsFnstubs.These stubs currently ignore workspace scope, so they won’t fail if the handler passes the wrong workspace.
Suggested patch
-ListChannelsFn: func(context.Context, string) ([]network.ChannelInfo, error) { +ListChannelsFn: func(_ context.Context, workspaceID string) ([]network.ChannelInfo, error) { + if workspaceID != "ws-1" { + t.Fatalf("ListChannels() workspaceID = %q, want ws-1", workspaceID) + } return []network.ChannelInfo{{Channel: "builders", PeerCount: 2}}, nil },-ListChannelsFn: func(context.Context, string) ([]network.ChannelInfo, error) { +ListChannelsFn: func(_ context.Context, workspaceID string) ([]network.ChannelInfo, error) { + if workspaceID != "ws-1" { + t.Fatalf("ListChannels() workspaceID = %q, want ws-1", workspaceID) + } return []network.ChannelInfo{{Channel: "builders", PeerCount: 1}}, nil },Based on learnings: No partial-surface completions — any change touching a public surface closes the loop end-to-end: contract → HTTP handler → UDS handler → CLI client → CLI command → extension/config/docs surfaces → tests → docs
Also applies to: 215-216
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/api/core/agent_channels_internal_test.go` around lines 31 - 32, The ListChannelsFn test stubs ignore the workspaceID parameter so tests won't catch handlers using the wrong workspace; update the ListChannelsFn stub(s) in agent_channels_internal_test.go to validate the incoming workspaceID argument (the first string parameter in the func(context.Context, string) signature) and return an error if it does not match the expected test workspace ID used by the test, ensuring you update every occurrence of ListChannelsFn in that file (including the other stub instance referenced in the comment) so the test fails when the handler passes the wrong workspace.internal/api/udsapi/network_test.go (1)
164-165: ⚡ Quick winAssert workspace scope in
ListPeersFntest doubles.Both updated stubs accept workspace input but don’t verify it, so a workspace-routing regression could slip through.
Suggested patch
-ListPeersFn: func(_ context.Context, _ string, channel string) ([]network.PeerInfo, error) { +ListPeersFn: func(_ context.Context, workspaceID string, channel string) ([]network.PeerInfo, error) { + if workspaceID != networkUDSTestWorkspaceID { + t.Fatalf("ListPeers() workspaceID = %q, want %s", workspaceID, networkUDSTestWorkspaceID) + } if channel != "builders" { t.Fatalf("ListPeers() channel = %q, want builders", channel) } ... },-ListPeersFn: func(context.Context, string, string) ([]network.PeerInfo, error) { +ListPeersFn: func(_ context.Context, workspaceID string, _ string) ([]network.PeerInfo, error) { + if workspaceID != networkUDSTestWorkspaceID { + t.Fatalf("ListPeers() workspaceID = %q, want %s", workspaceID, networkUDSTestWorkspaceID) + } return []network.PeerInfo{{Based on learnings: No partial-surface completions — any change touching a public surface closes the loop end-to-end: contract → HTTP handler → UDS handler → CLI client → CLI command → extension/config/docs surfaces → tests → docs
Also applies to: 244-245
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/api/udsapi/network_test.go` around lines 164 - 165, The ListPeersFn test double currently ignores the workspace parameter (it's an underscore), so change its signature to capture the workspace (e.g., func(_ context.Context, workspace string, channel string) ...) and assert workspace == expectedWorkspace (use t.Fatalf or t.Errorf) before checking channel; do the same for the other ListPeersFn stub(s) referenced (the other occurrences mentioned in the comment) so all test doubles validate the workspace routing and fail the test on mismatch.internal/api/core/memory_services_test.go (1)
245-283: ⚡ Quick winAdd
t.Parallel()in the newly added subtests.The new
t.Runblocks run serially; this diverges from the repo’s default test concurrency rule.Suggested patch
t.Run("Should reject foreign workspace before ledger service access", func(t *testing.T) { + t.Parallel() ... for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { + t.Parallel() resp := performRequest(t, engine, tc.method, tc.path, tc.body) ... }) }As per coding guidelines: In Go tests, use
t.Run("Should ...")subtest pattern andt.Parallelby default (witht.Setenvopt-out for environment-sensitive tests)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/api/core/memory_services_test.go` around lines 245 - 283, Add test parallelization: inside the top-level t.Run("Should reject foreign workspace before ledger service access", ...) and inside each inner t.Run(tc.name, ...) call t.Parallel() as the first line of the subtest function so the tests run concurrently; locate the block that constructs ledger := &stubMemorySessionLedgerService{}, engine := newMemoryServiceRouter(...), and the loop that calls performRequest(t, engine, ...) and insert t.Parallel() at the start of both the outer and inner subtest closures.internal/network/manager.go (1)
1256-1282: 💤 Low valueConsider including workspaceID in the error message for debugging clarity.
The error at line 1279 only includes
targetChannelbut nottargetWorkspaceID. In a multi-workspace environment, including the workspace ID would help diagnose subscription issues.💡 Suggested improvement
if err := runtime.broadcastSub.Unsubscribe(); err != nil && !errors.Is(err, nats.ErrConnectionClosed) { - return fmt.Errorf("network: unsubscribe broadcast subject for %q: %w", targetChannel, err) + return fmt.Errorf("network: unsubscribe broadcast subject for workspace %q channel %q: %w", targetWorkspaceID, targetChannel, err) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/network/manager.go` around lines 1256 - 1282, The error message in releaseBroadcastSubscription only mentions targetChannel; update the fmt.Errorf call where runtime.broadcastSub.Unsubscribe() returns an error to include targetWorkspaceID (and optionally the peerChannelKey) for better debugging: locate the releaseBroadcastSubscription method and modify the error formatting around the Unsubscribe call (currently referencing targetChannel) to include targetWorkspaceID (e.g., "unsubscribe broadcast subject for workspace %q channel %q: %w") while preserving the existing check for nats.ErrConnectionClosed and the current return flow.internal/api/core/network_details.go (1)
398-445: 💤 Low valueConsider checking context cancellation instead of ignoring it.
Line 403 explicitly ignores the context with
_ = ctx. Per context discipline guidelines, consider checkingctx.Err()for early cancellation, especially since this function performs validation that could be skipped if the request is already cancelled.💡 Suggested improvement
func (h *BaseHandlers) resolveCreateNetworkChannelRequest( ctx context.Context, req contract.CreateNetworkChannelRequest, resolved *workspacepkg.ResolvedWorkspace, ) (string, string, workspacepkg.ResolvedWorkspace, []string, error) { - _ = ctx + if err := ctx.Err(); err != nil { + return "", "", workspacepkg.ResolvedWorkspace{}, nil, err + } if resolved == nil {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/api/core/network_details.go` around lines 398 - 445, In resolveCreateNetworkChannelRequest replace the ignored context (`_ = ctx`) with an early cancellation check: call if err := ctx.Err(); err != nil { return "", "", workspacepkg.ResolvedWorkspace{}, nil, err } (or wrap/convert the ctx error into your NewNetworkValidationError if you prefer consistent error types) so that the function aborts immediately on context cancellation/deadline instead of continuing validation work.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/api/core/agent_channels.go`:
- Around line 291-303: validateReplySource trims and checks source values but
DirectRoomIdentity is called with raw source.Channel/source.From which can
produce mismatched direct room IDs; before calling network.DirectRoomIdentity
(and when building sendReq fields like To/Channel/DirectID), use trimmed values
(e.g., assign trimmedChannel := strings.TrimSpace(source.Channel) and
trimmedFrom := strings.TrimSpace(source.From)) and pass those to
network.DirectRoomIdentity and ptrString(...) so the same normalized identifiers
are used throughout (update the DirectRoomIdentity call and the sendReq
Channel/To fields to use the trimmed variables).
In `@internal/api/core/tools.go`:
- Around line 184-188: The handlers are validating ownership with
routeSessionInWorkspace(c) but then rebuild scope from raw params
(workspaceRefFromRoute / c.Param) which can diverge; change the code to use the
resolved values returned by routeSessionInWorkspace to construct scope and for
any subsequent body/path identifier checks. Concretely, capture the returned
workspace/session IDs from routeSessionInWorkspace(c) (instead of discarding
them), pass those into sessionToolScope (or build the scope object directly) and
use that scope when calling h.Tools.List and when comparing request body or path
identifiers; apply the same change to the other handler blocks referenced
(around the other ranges noted) so all comparisons and registry lookups use the
canonical resolved scope rather than raw route params.
In `@internal/api/core/workspace_scope.go`:
- Around line 124-130: The route currently lets an empty sessionID fall through
to requireSessionInWorkspace causing non-deterministic status codes; instead, in
the handler right after computing sessionID (the variable sessionID used above),
if sessionID == "" return a deterministic 400: call h.respondError(c,
http.StatusBadRequest, fmt.Errorf("missing session_id route parameter")) (or
your API's standard bad-request error) and return, before calling
requireSessionInWorkspace; keep references to sessionID,
requireSessionInWorkspace, statusForWorkspaceScopedResourceError and
respondError to locate the change.
In `@internal/api/spec/spec_test.go`:
- Around line 547-555: The test for the session tools GET (variables
sessionTools obtained via operationFor) is missing assertions for the path
parameters; update the test to assert that the operation declares the
"workspace_id" and "session_id" path params (as done for sessionSearch) by
calling the same path-parameter assertion helper used elsewhere (e.g., the
helper that checks path params for sessionSearch) after creating sessionTools
and before assertResponseStatus, so the spec test verifies both workspace_id and
session_id are required for the
"/api/workspaces/{workspace_id}/sessions/{session_id}/tools" GET operation.
In `@internal/api/udsapi/agent_channels_test.go`:
- Around line 213-214: The test stub for ListChannelsFn currently ignores the
workspace argument; update the ListChannelsFn stub used in
agent_channels_test.go to assert that the incoming workspace value equals the
expected workspace for the test (e.g., compare the function's second parameter
to the test's workspace variable) and fail the test if it differs, then continue
to return the same []network.ChannelInfo{{Channel: "builders", PeerCount: 2}},
nil; reference the ListChannelsFn function literal to add this assertion so the
test enforces workspace propagation/isolation.
In `@internal/api/udsapi/handlers_test.go`:
- Around line 170-183: The parity filter for network routes currently only
matches the global "/api/network" surface and omits workspace-scoped routes;
update the parity checks (the test in handlers_test.go that filters routes) to
also match "/api/workspaces/:workspace_id/network/..." (e.g., "GET
/api/workspaces/:workspace_id/network/inbox", ".../peers",
".../channels/:channel/threads/:thread_id/messages", etc.) by extending the
regex or adding an OR branch so both "/api/network/..." and
"/api/workspaces/:workspace_id/network/..." routes are included in the parity
assertions. Ensure the updated filter/re matcher is used where the test
currently filters network routes so the new workspace-scoped routes in the
provided list are covered by the parity checks.
In `@internal/cli/helpers_test.go`:
- Around line 1204-1213: The HookRuns stub in stubClient validates workspaceRef
but doesn't pass it to the callback (s.hookRunsFn), so update the stub to
forward workspaceRef into the callback: change the invocation inside
stubClient.HookRuns to call s.hookRunsFn(ctx, workspaceRef, query) and update
the hookRunsFn field/type and any places that set or call it (tests/mocks) to
accept the workspaceRef parameter so workspace scoping can be asserted
end-to-end.
In `@internal/daemon/native_config_hook_tools.go`:
- Around line 375-382: The code resolves a workspace but never attaches it to
the hook-runs query and unconditionally enforces session existence; update the
flow in the handler that calls nativeNetworkWorkspaceID and QueryHookRuns so
that after resolving workspaceID you set query.WorkspaceID = workspaceID before
calling n.deps.Observer.QueryHookRuns, and only call nativeSessionInWorkspace
when query.SessionID is non-empty (i.e., make nativeSessionInWorkspace
conditional on query.SessionID != ""), so session_id remains optional and
workspace filtering is passed through to QueryHookRuns.
In `@internal/daemon/native_tools_test.go`:
- Around line 884-897: The test currently only checks err != nil for the
foreign-workspace Call to toolspkg.ToolIDHooksRuns and thus can mask unrelated
backend errors; update the assertion to use the project helpers
requireToolCode/requireToolReason (the same pattern used in surrounding
native-tool tests) to assert the specific tool error code and reason returned by
foreignRegistry.Call(t.Context(), toolspkg.Scope{}, toolspkg.CallRequest{ToolID:
toolspkg.ToolIDHooksRuns, Input: json.RawMessage(...)}) and keep the existing
check that foreignObserver.hookRunCalls == 0; apply the same replacement (err !=
nil -> requireToolCode/requireToolReason checks) to the other occurrences
referenced (around lines 2856-2866 and 3453-3464) so the contract is pinned to
the intended ownership rejection error.
In `@internal/daemon/native_tools.go`:
- Around line 3564-3585: The current nativeNetworkWorkspaceID resolves the
stable/network workspace identifier but nativeSessionInWorkspace is comparing
that value to session.Info.WorkspaceID; change the flow so you resolve two
distinct IDs: keep nativeNetworkWorkspaceID as-is for network/stable operations,
add (or reuse) a resolver that returns the registry-backed/session-ownership
workspace ID (e.g., a new nativeRegistryWorkspaceID or extend the Resolve call
to produce RegistryWorkspaceID) and update nativeSessionInWorkspace to use the
registry-backed value when checking session.Info.WorkspaceID; locate usages
around nativeNetworkWorkspaceID and nativeSessionInWorkspace and replace the
argument passed to nativeSessionInWorkspace with the registry-form ID (the
lookup used in the other block at the same region should be mirrored for session
ownership checks).
In `@internal/extension/host_api_authored_context_test.go`:
- Around line 98-164: The test
TestHostAPIHandlerSessionsSoulRefreshRequiresWorkspaceOwnership contains two
scenarios and must be split into t.Run subtests: wrap the "owned workspace
refresh" portion (the initial successful refresh assertions that use
env.createSession, refresher checks, decodeResult, and refresher.calls
assertions) in a t.Run("Should refresh soul for owned workspace") with its own
t.Parallel(), and wrap the "foreign workspace rejection" portion (the
env.addForeignWorkspace call, second env.handler.Handle invocation,
assertRPCErrorCode check, and final refresher.calls assertion) in a separate
t.Run("Should reject soul refresh from foreign workspace") with t.Parallel();
keep the existing setup (env, refresher, grants) accessible to both subtests or
move shared setup into the parent test body before the t.Run calls. Ensure each
subtest name follows the "Should ..." pattern.
In `@internal/extension/host_api_test.go`:
- Around line 389-402: Wrap the existing test
TestHostAPIHandlerSandboxInfoRejectsForeignWorkspace in a t.Run subtest with a
"Should ..." name, and extend the assertion after calling env.call (the ext
method "sandbox/info") to also check the RPC error payload/message contains the
expected fragment (e.g., workspace not found or foreign workspace) in addition
to the existing assertRPCErrorCode call; locate the test by the function name
TestHostAPIHandlerSandboxInfoRejectsForeignWorkspace and the
env.call/assertRPCErrorCode usage, add a t.Run wrapper and an assertion on the
returned err payload/message (or its .Message/.Error field) to ensure both
status code and response body are validated (apply the same pattern to the
similar case around the other test at lines ~544-559).
In `@internal/network/tasks.go`:
- Line 360: The lookup uses raw ingress fields which can include
leading/trailing spaces while TaskIngressContext.Validate() trims them; before
calling m.peers.RemoteByPeer(...) normalize the identifiers (e.g. apply
strings.TrimSpace) for ingress.WorkspaceID, ingress.Channel, and ingress.PeerID
(or use any normalized/validated properties on TaskIngressContext if available)
so the peer lookup uses the same trimmed values as validation and avoids false
peer_not_found rejections.
---
Outside diff comments:
In `@internal/api/core/network_test.go`:
- Around line 951-996: The test stubs for ListPeersFn and ListChannelsFn ignore
the new workspaceID parameter, allowing workspace-scoped routing bugs to slip;
update the stub implementations (ListPeersFn and ListChannelsFn) to validate the
incoming workspaceID (e.g., assert it equals the expected test workspace id) and
branch or fail the test when it does not match so workspace propagation is
enforced in tests; ensure any added assertion references the workspaceID
parameter and adjust returned peers/channels only for the matching workspaceID
to harden workspace-scoped behavior.
In `@internal/extension/contract/host_api.go`:
- Around line 827-830: The method spec advertises ObserveEventsParams as
optional but ObserveEventsParams now requires workspace_id, so update
HostAPIMethodObserveEvents to make params required by setting OptionalParams:
false (or removing OptionalParams if default is required) so the generated
contract accurately reflects that ObserveEventsParams (used by
HostAPIMethodObserveEvents) is mandatory; update the HostAPIMethodObserveEvents
definition accordingly to prevent callers from omitting params.
In `@internal/extension/host_api_network_test.go`:
- Around line 871-893: The stub's workspace filter is too permissive: when a
non-empty workspaceID is provided, entries with an empty WorkspaceID should not
be returned. In hostAPINetworkServiceStub.ListChannels (and the analogous
peer-listing loop), change the condition so that when trimmedWorkspaceID != ""
you require channel.WorkspaceID == trimmedWorkspaceID (i.e., if
channel.WorkspaceID != trimmedWorkspaceID then continue), thereby excluding
entries with empty WorkspaceID instead of allowing them through.
In `@internal/network/peer.go`:
- Around line 469-505: ListPeers currently only calls listPeersForChannelLocked
when both trimmedWorkspaceID and trimmedChannel are non-empty, so ListPeers("",
"chan", ...) falls through and returns peers across all channels; change this to
fail-closed by detecting when trimmedChannel != "" but trimmedWorkspaceID == ""
and returning an explicit error (or empty result) instead of aggregating. Update
the early-return logic in ListPeers to check trimmedChannel alone and call
listPeersForChannelLocked only when both are present, otherwise return the
error/empty result; ensure references to trimmedWorkspaceID, trimmedChannel,
ListPeers, and listPeersForChannelLocked are used so the fix is applied in the
correct location.
---
Nitpick comments:
In `@internal/api/core/agent_channels_internal_test.go`:
- Around line 31-32: The ListChannelsFn test stubs ignore the workspaceID
parameter so tests won't catch handlers using the wrong workspace; update the
ListChannelsFn stub(s) in agent_channels_internal_test.go to validate the
incoming workspaceID argument (the first string parameter in the
func(context.Context, string) signature) and return an error if it does not
match the expected test workspace ID used by the test, ensuring you update every
occurrence of ListChannelsFn in that file (including the other stub instance
referenced in the comment) so the test fails when the handler passes the wrong
workspace.
In `@internal/api/core/authored_context_test.go`:
- Around line 205-221: The test "Should reject foreign workspace heartbeat
status session" currently only checks HTTP 404 and that statusSpy.calls == 0;
update it to also decode and assert the response body/error payload matches the
ownership-rejection contract (e.g., the JSON error structure returned by the
handler) so the body and fields (error code/message and any
workspace_id/session_id context) are validated; use the existing recorder to
read recorder.Body, unmarshal into the expected error struct or map, and assert
expected keys/values, and apply the same change to the sibling subtest at the
other location that checks heartbeat rejection (the one referenced at lines
223-243) so both status code and response body are asserted.
In `@internal/api/core/memory_services_test.go`:
- Around line 245-283: Add test parallelization: inside the top-level
t.Run("Should reject foreign workspace before ledger service access", ...) and
inside each inner t.Run(tc.name, ...) call t.Parallel() as the first line of the
subtest function so the tests run concurrently; locate the block that constructs
ledger := &stubMemorySessionLedgerService{}, engine :=
newMemoryServiceRouter(...), and the loop that calls performRequest(t, engine,
...) and insert t.Parallel() at the start of both the outer and inner subtest
closures.
In `@internal/api/core/network_details.go`:
- Around line 398-445: In resolveCreateNetworkChannelRequest replace the ignored
context (`_ = ctx`) with an early cancellation check: call if err := ctx.Err();
err != nil { return "", "", workspacepkg.ResolvedWorkspace{}, nil, err } (or
wrap/convert the ctx error into your NewNetworkValidationError if you prefer
consistent error types) so that the function aborts immediately on context
cancellation/deadline instead of continuing validation work.
In `@internal/api/udsapi/network_test.go`:
- Around line 164-165: The ListPeersFn test double currently ignores the
workspace parameter (it's an underscore), so change its signature to capture the
workspace (e.g., func(_ context.Context, workspace string, channel string) ...)
and assert workspace == expectedWorkspace (use t.Fatalf or t.Errorf) before
checking channel; do the same for the other ListPeersFn stub(s) referenced (the
other occurrences mentioned in the comment) so all test doubles validate the
workspace routing and fail the test on mismatch.
In `@internal/api/udsapi/udsapi_integration_test.go`:
- Around line 1029-1033: Add an explicit equality assertion that the resolved
workspace ID matches the workspace ID returned by the created session to make
the flow deterministic: after resolving the workspace (variable resolved) and
after creating the session via createIntegrationSessionPayload (variable
createdSession), assert resolved.Workspace.ID == createdSession.Workspace.ID
(and add the same check near the second occurrence around the 1040–1041 area) so
the test fails if the session used for triggers is not the resolved workspace.
In `@internal/network/manager.go`:
- Around line 1256-1282: The error message in releaseBroadcastSubscription only
mentions targetChannel; update the fmt.Errorf call where
runtime.broadcastSub.Unsubscribe() returns an error to include targetWorkspaceID
(and optionally the peerChannelKey) for better debugging: locate the
releaseBroadcastSubscription method and modify the error formatting around the
Unsubscribe call (currently referencing targetChannel) to include
targetWorkspaceID (e.g., "unsubscribe broadcast subject for workspace %q channel
%q: %w") while preserving the existing check for nats.ErrConnectionClosed and
the current return flow.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ba50257c-0dd8-4db5-9ef4-faa0cfc02843
⛔ Files ignored due to path filters (75)
.agents/skills/qa-execution/scripts/discover-project-contract.pyis excluded by!.agents/**COPY.mdis excluded by!**/*.mddocs/_memory/analysis/analysis_existing_surfaces.mdis excluded by!**/*.mddocs/_memory/analysis/analysis_qmd_collections.mdis excluded by!**/*.mddocs/_memory/glossary.mdis excluded by!**/*.mddocs/_memory/lessons/L-001-detached-prompt-lifetime.mdis excluded by!**/*.mddocs/_memory/standing_directives.mdis excluded by!**/*.mddocs/ideas/complex-scenarios/network.mdis excluded by!**/*.mdinternal/CLAUDE.mdis excluded by!**/*.mdopenapi/agh.jsonis excluded by!**/*.jsonpackages/site/CLAUDE.mdis excluded by!**/*.mdpackages/site/content/blog/posts/introducing-agh-the-first-agent-network-protocol.mdxis excluded by!**/*.mdxpackages/site/content/protocol/capability-discovery.mdxis excluded by!**/*.mdxpackages/site/content/protocol/conformance.mdxis excluded by!**/*.mdxpackages/site/content/protocol/delivery.mdxis excluded by!**/*.mdxpackages/site/content/protocol/ed25519-jcs.mdxis excluded by!**/*.mdxpackages/site/content/protocol/envelope.mdxis excluded by!**/*.mdxpackages/site/content/protocol/examples.mdxis excluded by!**/*.mdxpackages/site/content/protocol/guide/minimal-sender.mdxis excluded by!**/*.mdxpackages/site/content/protocol/guide/nats-transport.mdxis excluded by!**/*.mdxpackages/site/content/protocol/guide/testing.mdxis excluded by!**/*.mdxpackages/site/content/protocol/guide/trust-verification.mdxis excluded by!**/*.mdxpackages/site/content/protocol/implementation-status.mdxis excluded by!**/*.mdxpackages/site/content/protocol/index.mdxis excluded by!**/*.mdxpackages/site/content/protocol/interactions.mdxis excluded by!**/*.mdxpackages/site/content/protocol/message-kinds.mdxis excluded by!**/*.mdxpackages/site/content/protocol/nats.mdxis excluded by!**/*.mdxpackages/site/content/protocol/overview.mdxis excluded by!**/*.mdxpackages/site/content/protocol/peer-discovery.mdxis excluded by!**/*.mdxpackages/site/content/protocol/verification.mdxis excluded by!**/*.mdxpackages/site/content/runtime/api-reference/index.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/agh.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/hooks/runs.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/channels.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/directs/index.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/directs/list.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/directs/messages.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/directs/resolve.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/directs/show.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/inbox.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/index.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/peers.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/send.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/status.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/threads/index.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/threads/list.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/threads/messages.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/threads/show.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/work/index.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/work/lookup.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/network/work/status.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/observe/events.mdxis excluded by!**/*.mdxpackages/site/content/runtime/cli-reference/observe/index.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/agents/soul.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/hooks/declaration.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/hooks/event-catalog.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/memory/best-practices.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/memory/system.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/network/channels-and-peers.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/network/directs.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/network/index.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/network/protocol.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/network/threads.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/network/work.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/sessions/events.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/sessions/health.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/sessions/lifecycle.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/sessions/permissions.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/sessions/resume.mdxis excluded by!**/*.mdxpackages/site/content/runtime/guides/choose-an-operator-surface.mdxis excluded by!**/*.mdxpackages/site/content/runtime/guides/coordinate-agents-over-network.mdxis excluded by!**/*.mdxsdk/typescript/src/generated/contracts.tsis excluded by!**/generated/**web/e2e/fixtures/__tests__/runtime-seed.test.tsis excluded by!**/fixtures/**web/e2e/fixtures/runtime-seed.tsis excluded by!**/fixtures/**web/src/generated/agh-openapi.d.tsis excluded by!**/generated/**
📒 Files selected for processing (225)
internal/api/contract/contract.gointernal/api/contract/contract_test.gointernal/api/core/agent_channels.gointernal/api/core/agent_channels_internal_test.gointernal/api/core/authored_context.gointernal/api/core/authored_context_test.gointernal/api/core/bridges.gointernal/api/core/bridges_test.gointernal/api/core/conversions.gointernal/api/core/error_paths_test.gointernal/api/core/handler_edge_cases_test.gointernal/api/core/handlers.gointernal/api/core/handlers_internal_test.gointernal/api/core/handlers_test.gointernal/api/core/hooks_test.gointernal/api/core/interfaces.gointernal/api/core/memory.gointernal/api/core/memory_services_test.gointernal/api/core/network.gointernal/api/core/network_conversations.gointernal/api/core/network_details.gointernal/api/core/network_test.gointernal/api/core/payload_helpers_test.gointernal/api/core/test_helpers_test.gointernal/api/core/tools.gointernal/api/core/tools_test.gointernal/api/core/workspace_scope.gointernal/api/core/workspaces.gointernal/api/httpapi/handlers_error_test.gointernal/api/httpapi/handlers_test.gointernal/api/httpapi/helpers_test.gointernal/api/httpapi/hooks_integration_test.gointernal/api/httpapi/hooks_test.gointernal/api/httpapi/httpapi_integration_test.gointernal/api/httpapi/network_test.gointernal/api/httpapi/prompt.gointernal/api/httpapi/routes.gointernal/api/httpapi/session-clear_test.gointernal/api/httpapi/sessions.gointernal/api/httpapi/stream_helpers_test.gointernal/api/httpapi/transport_parity_integration_test.gointernal/api/spec/authored_context.gointernal/api/spec/authored_context_test.gointernal/api/spec/spec.gointernal/api/spec/spec_test.gointernal/api/testutil/memory_routes.gointernal/api/testutil/network_stub.gointernal/api/udsapi/agent_channels_test.gointernal/api/udsapi/extensions_additional_test.gointernal/api/udsapi/handlers_error_test.gointernal/api/udsapi/handlers_test.gointernal/api/udsapi/helpers_test.gointernal/api/udsapi/network_test.gointernal/api/udsapi/prompt.gointernal/api/udsapi/resources_test.gointernal/api/udsapi/routes.gointernal/api/udsapi/sessions.gointernal/api/udsapi/stream_helpers_test.gointernal/api/udsapi/transport_parity_integration_test.gointernal/api/udsapi/udsapi_integration_test.gointernal/cli/client.gointernal/cli/client_test.gointernal/cli/command_paths_test.gointernal/cli/helpers_test.gointernal/cli/hooks.gointernal/cli/hooks_test.gointernal/cli/network.gointernal/cli/network_client_test.gointernal/cli/network_test.gointernal/cli/observe.gointernal/cli/workspace.gointernal/daemon/authored_context_transport_test.gointernal/daemon/daemon_acpmock_faults_integration_test.gointernal/daemon/daemon_memory_e2e_integration_test.gointernal/daemon/daemon_network_collaboration_integration_test.gointernal/daemon/daemon_test.gointernal/daemon/hooks_bridge.gointernal/daemon/memory_runtime.gointernal/daemon/memory_runtime_test.gointernal/daemon/native_config_hook_tools.gointernal/daemon/native_memory_admin_tools.gointernal/daemon/native_tools.gointernal/daemon/native_tools_test.gointernal/daemon/notifier_test.gointernal/daemon/tools_transport_parity_test.gointernal/extension/contract/host_api.gointernal/extension/host_api.gointernal/extension/host_api_authored_context.gointernal/extension/host_api_authored_context_test.gointernal/extension/host_api_bridges.gointernal/extension/host_api_integration_test.gointernal/extension/host_api_network.gointernal/extension/host_api_network_test.gointernal/extension/host_api_tasks.gointernal/extension/host_api_test.gointernal/extension/reference_integration_test.gointernal/memory/dream.gointernal/memory/dream_test.gointernal/network/audit.gointernal/network/audit_test.gointernal/network/delivery_test.gointernal/network/envelope.gointernal/network/envelope_integration_test.gointernal/network/helpers_test.gointernal/network/hooks_test.gointernal/network/lifecycle_test.gointernal/network/manager.gointernal/network/manager_integration_test.gointernal/network/manager_test.gointernal/network/peer.gointernal/network/peer_test.gointernal/network/perf_bench_test.gointernal/network/router.gointernal/network/router_integration_test.gointernal/network/router_test.gointernal/network/tasks.gointernal/network/tasks_integration_test.gointernal/network/tasks_test.gointernal/network/transport.gointernal/network/transport_integration_test.gointernal/network/transport_test.gointernal/network/validate.gointernal/network/validate_test.gointernal/observe/observer.gointernal/observe/query.gointernal/observe/tasks.gointernal/observe/tasks_test.gointernal/session/interfaces.gointernal/session/manager_helpers.gointernal/session/manager_prompt.gointernal/session/manager_test.gointernal/session/network_peer.gointernal/situation/service.gointernal/situation/service_test.gointernal/store/globaldb/global_db.gointernal/store/globaldb/global_db_model_catalog_test.gointernal/store/globaldb/global_db_network_audit.gointernal/store/globaldb/global_db_network_audit_test.gointernal/store/globaldb/global_db_network_channels.gointernal/store/globaldb/global_db_network_channels_test.gointernal/store/globaldb/global_db_network_conversation_repository_test.gointernal/store/globaldb/global_db_network_conversations.gointernal/store/globaldb/global_db_network_conversations_test.gointernal/store/globaldb/global_db_network_messages.gointernal/store/globaldb/global_db_network_messages_test.gointernal/store/globaldb/global_db_observe.gointernal/store/globaldb/global_db_task_claim_test.gointernal/store/globaldb/global_db_test.gointernal/store/network_conversation_types_test.gointernal/store/store.gointernal/store/store_helpers_test.gointernal/store/types.gointernal/testutil/e2e/mock_agents.gointernal/testutil/e2e/mock_agents_test.gointernal/testutil/e2e/runtime_harness.gointernal/testutil/e2e/runtime_harness_helpers_test.gointernal/testutil/e2e/transport_parity_test.gointernal/tools/builtin/hooks.gointernal/tools/builtin/memory_admin.gointernal/tools/builtin/network.gointernal/tools/builtin/observe.gointernal/tools/builtin/sessions.gopackages/site/app/blog/page.tsxpackages/site/app/changelog/metadata.tspackages/site/app/llms.txt/route.tspackages/site/components/blog/__tests__/blog-navigation.test.tsxpackages/site/components/blog/featured-post.tsxpackages/site/components/landing/__tests__/landing.test.tsxpackages/site/components/landing/comparison.tsxpackages/site/components/landing/final-cta.tsxpackages/site/components/landing/hero.tsxpackages/site/components/landing/network-protocol-visual.tsxpackages/site/components/landing/network-section.tsxpackages/site/lib/__tests__/blog-metadata.test.tspackages/site/lib/__tests__/docs-route-metadata.test.tspackages/site/lib/__tests__/protocol-rfc-hard-cut.test.tspackages/site/lib/__tests__/public-heading-hierarchy.test.tsxpackages/site/lib/__tests__/public-route-metadata.test.tspackages/site/lib/__tests__/public-search-index.test.tspackages/site/lib/__tests__/runtime-docs-truth.test.tspackages/site/lib/__tests__/site-config.test.tspackages/site/lib/__tests__/static-route-metadata.test.tspackages/site/lib/blog.tspackages/site/lib/site-config.tspackages/slides/slides/agh-network/index.tsxpackages/ui/src/components/custom/__tests__/queue-health-sparkline.test.tsxpackages/ui/src/components/custom/stories/action-result-banner.stories.tsxpackages/ui/src/components/custom/stories/code-block.stories.tsxpackages/ui/src/components/custom/stories/detail-header.stories.tsxpackages/ui/src/components/custom/stories/json-viewer.stories.tsxpackages/ui/src/components/custom/stories/kind-chip.stories.tsxpackages/ui/src/components/custom/stories/pill.stories.tsxpackages/ui/src/components/custom/stories/timeline-event.stories.tsxsdk/typescript/src/__tests__/host-api.test.tssdk/typescript/src/host-api.tssdk/typescript/src/index.tsweb/e2e/__tests__/extensibility.spec.tsweb/e2e/__tests__/jobs-hardening.spec.tsweb/e2e/__tests__/knowledge.spec.tsweb/e2e/__tests__/network.spec.tsweb/e2e/__tests__/sandbox.spec.tsweb/e2e/__tests__/session-hardening.spec.tsweb/e2e/__tests__/session-onboarding.spec.tsweb/e2e/__tests__/session-provider-override.spec.tsweb/e2e/__tests__/skills.spec.tsweb/e2e/__tests__/triggers-hardening.spec.tsweb/src/components/__tests__/topbar-shell.test.tsxweb/src/components/assistant-ui/stories/session-thread.stories.tsxweb/src/components/design-system-showcase.tsxweb/src/hooks/routes/__tests__/use-session-page-controls.test.tsxweb/src/hooks/routes/__tests__/workspace-scope-filter.test.tsweb/src/hooks/routes/use-automation-page.tsweb/src/hooks/routes/use-bridges-page.tsweb/src/hooks/routes/use-session-detail-page.tsweb/src/hooks/routes/use-session-page-controls.tsweb/src/hooks/routes/use-tasks-page.tsweb/src/hooks/routes/workspace-scope-filter.tsweb/src/routeTree.gen.tsweb/src/routes/_app/__tests__/-agents.$name.sessions.$id.test.tsxweb/src/routes/_app/__tests__/-bridges.test.tsxweb/src/routes/_app/__tests__/-network-routes.test.tsweb/src/routes/_app/__tests__/-network-task14-routes.test.tsweb/src/routes/_app/network.$workspaceId.$channel.activity.tsxweb/src/routes/_app/network.$workspaceId.$channel.directs.$directId.tsxweb/src/routes/_app/network.$workspaceId.$channel.directs.tsx
Add the current AGH Network v2 RFC and mark the older Network RFCs as historical/superseded for runtime identity and NATS subject grammar. Also tighten protocol docs and RFC truth tests so public docs keep direct as a conversation surface rather than a message kind.
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
internal/api/udsapi/network_test.go (1)
18-18: ⚡ Quick winUse the workspace constant in all route strings to avoid drift.
networkUDSTestWorkspaceIDwas introduced, but request paths still inline"ws-workspace"in several places. This makes future workspace-ID test updates brittle.♻️ Suggested cleanup
+ networkBase := "/api/workspaces/" + networkUDSTestWorkspaceID + "/network" - inboxResp := performRequest(t, engine, http.MethodGet, "/api/workspaces/ws-workspace/network/inbox", nil) + inboxResp := performRequest(t, engine, http.MethodGet, networkBase+"/inbox", nil) - sendResp := performRequest(t, engine, http.MethodPost, "/api/workspaces/ws-workspace/network/send", []byte(`{}`)) + sendResp := performRequest(t, engine, http.MethodPost, networkBase+"/send", []byte(`{}`)) - "/api/workspaces/ws-workspace/network/send", + networkBase + "/send", - "/api/workspaces/ws-workspace/network/inbox?session_id=sess-a", + networkBase + "/inbox?session_id=sess-a", - "/api/workspaces/ws-workspace/network/channels/builders/directs/resolve", + networkBase + "/channels/builders/directs/resolve", - resp := performRequest(t, engine, http.MethodGet, "/api/workspaces/ws-workspace/network/peers", nil) + resp := performRequest(t, engine, http.MethodGet, networkBase+"/peers", nil)Also applies to: 35-35, 43-43, 56-56, 114-114, 140-140, 222-222, 276-276
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/api/udsapi/network_test.go` at line 18, Tests in internal/api/udsapi/network_test.go use the literal "ws-workspace" in request paths instead of the new constant networkUDSTestWorkspaceID; update all route strings (e.g. in the tests that build request URLs around the names mentioned at lines like 35, 43, 56, 114, 140, 222, 276) to use the networkUDSTestWorkspaceID constant so the workspace ID is centralized and won't drift; find occurrences of "/workspaces/\"ws-workspace\"" or similar concatenations and replace them with string building that references networkUDSTestWorkspaceID (keeping the surrounding path segments intact).internal/api/core/authored_context_test.go (1)
205-249: ⚡ Quick winAdd
t.Parallel()inside the new subtests.Both subtests follow the
t.Run("Should ...")pattern, but neither callst.Parallel(). Add it at the top of each subtest body to align with the test concurrency standard.Suggested patch
t.Run("Should reject foreign workspace heartbeat status session", func(t *testing.T) { + t.Parallel() req := httptest.NewRequestWithContext( context.Background(), http.MethodGet, @@ t.Run("Should reject foreign workspace heartbeat wake session", func(t *testing.T) { + t.Parallel() body := []byte( "{\"workspace_id\":\"ws-foreign\",\"agent_name\":\"coder\",\"session_id\":\"sess-owned\",\"source\":\"manual\"}", )As per coding guidelines,
**/*_test.go: Uset.Run("Should ...")subtests andt.Parallel()by default in Go tests.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/api/core/authored_context_test.go` around lines 205 - 249, The two subtests "Should reject foreign workspace heartbeat status session" and "Should reject foreign workspace heartbeat wake session" are missing t.Parallel(); add a call to t.Parallel() as the first statement inside each t.Run subtest body (inside the anonymous func for those tests) so the tests run concurrently with other parallel subtests and follow the repo test-concurrency standard.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/api/core/authored_context_test.go`:
- Around line 461-467: The test hardcodes the workspace in the registered route
which bypasses workspace_id param binding; update the route registration inside
registerRoute (the fixture.Engine.POST call that wires RefreshSessionSoul) to
use a workspace param, e.g.
"/workspaces/:workspace_id/sessions/:id/soul/refresh", and ensure the test's
path value (the path variable) matches that pattern
("/workspaces/ws-workspace/sessions/sess_1/soul/refresh") so the
handlerFixture.RegisterRoute and RefreshSessionSoul exercise workspace_id
binding correctly.
In `@internal/api/core/tools_test.go`:
- Around line 443-470: The tests call performRequest for the session list and
session search paths and only assert HTTP status and registry side-effects
(listResp, searchResp, registry.lastList(), registry.lastSearch()); add
assertions that decode and validate the JSON response bodies for both listResp
and searchResp to ensure the payload shape is correct (e.g., expected top-level
fields, types, counts or specific entries). Update the test to unmarshal
listResp.Body and searchResp.Body into appropriate structs or maps and assert
expected keys/values (for example presence of tools array/items, length matching
limit, and any expected tool fields), so serialization/contract regressions are
caught alongside status and scope checks.
---
Nitpick comments:
In `@internal/api/core/authored_context_test.go`:
- Around line 205-249: The two subtests "Should reject foreign workspace
heartbeat status session" and "Should reject foreign workspace heartbeat wake
session" are missing t.Parallel(); add a call to t.Parallel() as the first
statement inside each t.Run subtest body (inside the anonymous func for those
tests) so the tests run concurrently with other parallel subtests and follow the
repo test-concurrency standard.
In `@internal/api/udsapi/network_test.go`:
- Line 18: Tests in internal/api/udsapi/network_test.go use the literal
"ws-workspace" in request paths instead of the new constant
networkUDSTestWorkspaceID; update all route strings (e.g. in the tests that
build request URLs around the names mentioned at lines like 35, 43, 56, 114,
140, 222, 276) to use the networkUDSTestWorkspaceID constant so the workspace ID
is centralized and won't drift; find occurrences of
"/workspaces/\"ws-workspace\"" or similar concatenations and replace them with
string building that references networkUDSTestWorkspaceID (keeping the
surrounding path segments intact).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 03b749bb-bc1c-4a72-9c1d-c5c1bc3dc35d
⛔ Files ignored due to path filters (38)
.oxlintrc.jsonis excluded by!**/*.json.skeeper.ymlis excluded by!**/*.ymlCLAUDE.mdis excluded by!**/*.mdDESIGN.mdis excluded by!**/*.mdbun.lockis excluded by!**/*.lock,!**/*.lockdocs/_memory/_synthesis.mdis excluded by!**/*.mddocs/_memory/analysis/analysis_existing_surfaces.mdis excluded by!**/*.mddocs/_memory/analysis/analysis_qmd_collections.mdis excluded by!**/*.mddocs/_memory/glossary.mdis excluded by!**/*.mddocs/_memory/lessons/L-025-greenfield-hardcut-current-protocol-version.mdis excluded by!**/*.mddocs/_memory/lessons/README.mdis excluded by!**/*.mddocs/design/new-proposal/redesign-toolcall-card.htmlis excluded by!docs/design/**/*docs/rfcs/003_agh-network-OLD.mdis excluded by!**/*.mddocs/rfcs/003_agh-network-v0.mdis excluded by!**/*.mddocs/rfcs/004_agh-network-v1.mdis excluded by!**/*.mddocs/rfcs/005_capability-catalogs-agent-directories.mdis excluded by!**/*.mdpackage.jsonis excluded by!**/*.jsonpackages/site/content/blog/posts/introducing-agh-the-first-agent-network-protocol.mdxis excluded by!**/*.mdxpackages/site/content/protocol/capability-discovery.mdxis excluded by!**/*.mdxpackages/site/content/protocol/conformance.mdxis excluded by!**/*.mdxpackages/site/content/protocol/delivery.mdxis excluded by!**/*.mdxpackages/site/content/protocol/ed25519-jcs.mdxis excluded by!**/*.mdxpackages/site/content/protocol/envelope.mdxis excluded by!**/*.mdxpackages/site/content/protocol/examples.mdxis excluded by!**/*.mdxpackages/site/content/protocol/guide/minimal-sender.mdxis excluded by!**/*.mdxpackages/site/content/protocol/guide/nats-transport.mdxis excluded by!**/*.mdxpackages/site/content/protocol/guide/testing.mdxis excluded by!**/*.mdxpackages/site/content/protocol/guide/trust-verification.mdxis excluded by!**/*.mdxpackages/site/content/protocol/implementation-status.mdxis excluded by!**/*.mdxpackages/site/content/protocol/message-kinds.mdxis excluded by!**/*.mdxpackages/site/content/protocol/nats.mdxis excluded by!**/*.mdxpackages/site/content/protocol/overview.mdxis excluded by!**/*.mdxpackages/site/content/protocol/peer-discovery.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/agents/definitions.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/agents/spawning.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/configuration/agent-md.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/network/channels-and-peers.mdxis excluded by!**/*.mdxpackages/site/content/runtime/core/network/protocol.mdxis excluded by!**/*.mdx
📒 Files selected for processing (101)
.gitignoreMakefileinternal/acp/client.gointernal/acp/client_test.gointernal/acp/types.gointernal/api/core/agent_channels.gointernal/api/core/agent_channels_internal_test.gointernal/api/core/authored_context_test.gointernal/api/core/memory_services_test.gointernal/api/core/network_test.gointernal/api/core/prompt_stream.gointernal/api/core/prompt_stream_test.gointernal/api/core/tools.gointernal/api/core/tools_test.gointernal/api/core/workspace_scope.gointernal/api/spec/spec_test.gointernal/api/udsapi/agent_channels_test.gointernal/api/udsapi/handlers_test.gointernal/api/udsapi/network_test.gointernal/api/udsapi/udsapi_integration_test.gointernal/cli/helpers_test.gointernal/cli/hooks_test.gointernal/cli/network_client_test.gointernal/cli/network_test.gointernal/daemon/boot.gointernal/daemon/composed_assembler_test.gointernal/daemon/daemon_test.gointernal/daemon/harness_context.gointernal/daemon/harness_context_integration_test.gointernal/daemon/harness_context_test.gointernal/daemon/native_config_hook_tools.gointernal/daemon/native_tools.gointernal/daemon/native_tools_test.gointernal/daemon/prompt_sections.gointernal/daemon/runtime_prompt.gointernal/extension/host_api_authored_context_test.gointernal/extension/host_api_test.gointernal/network/audit_test.gointernal/network/delivery_test.gointernal/network/envelope.gointernal/network/helpers_test.gointernal/network/hooks_test.gointernal/network/lifecycle_test.gointernal/network/manager_integration_test.gointernal/network/manager_test.gointernal/network/peer.gointernal/network/peer_test.gointernal/network/perf_bench_test.gointernal/network/router.gointernal/network/router_test.gointernal/network/tasks.gointernal/network/tasks_test.gointernal/network/transport.gointernal/network/transport_test.gointernal/network/validate.gointernal/network/validate_test.gointernal/session/manager_hooks_test.gointernal/session/manager_start.gointernal/situation/service_test.gointernal/store/types.gointernal/testutil/e2e/runtime_harness_helpers_test.gointernal/transcript/transcript_test.gointernal/transcript/ui_messages.golint-plugins/__tests__/compozy-design-system.test.mjslint-plugins/compozy-design-system.mjsmagefile.gopackages/site/app/blog/[slug]/page.tsxpackages/site/app/blog/categories/[category]/page.tsxpackages/site/app/blog/page.tsxpackages/site/app/changelog/page.tsxpackages/site/app/error.tsxpackages/site/app/global.csspackages/site/app/not-found.tsxpackages/site/components/blog/continue-reading.tsxpackages/site/components/blog/kind-chip.tsxpackages/site/components/blog/prose.tsxpackages/site/components/landing/autonomy-kernel-section.tsxpackages/site/components/landing/bento-section.tsxpackages/site/components/landing/bridges-section.tsxpackages/site/components/landing/comparison.tsxpackages/site/components/landing/extensibility-section.tsxpackages/site/components/landing/features-section.tsxpackages/site/components/landing/final-cta.tsxpackages/site/components/landing/hero.tsxpackages/site/components/landing/install-section.tsxpackages/site/components/landing/network-protocol-visual.tsxpackages/site/components/landing/primitives/code-block.tsxpackages/site/components/landing/primitives/feature-card.tsxpackages/site/components/landing/primitives/section-frame.tsxpackages/site/components/landing/runtime-micro-diagram.tsxpackages/site/components/landing/sandbox-section.tsxpackages/site/components/protocol/architecture-diagram.tsxpackages/site/components/site/home-header.tsxpackages/site/lib/__tests__/protocol-rfc-hard-cut.test.tspackages/site/remotion/hero/components/hooks/use-typewriter.tspackages/site/remotion/hero/components/message-agent.tsxpackages/ui/src/components/combobox.tsxpackages/ui/src/components/custom/code-block.tsxpackages/ui/src/components/custom/connection-indicator.tsxpackages/ui/src/components/custom/detail-inspector.tsxpackages/ui/src/components/custom/hooks/use-code-block.ts
✅ Files skipped from review due to trivial changes (2)
- .gitignore
- internal/daemon/boot.go
🚧 Files skipped from review as they are similar to previous changes (14)
- internal/api/spec/spec_test.go
- internal/api/core/workspace_scope.go
- internal/cli/hooks_test.go
- internal/daemon/native_config_hook_tools.go
- internal/cli/network_client_test.go
- internal/api/core/tools.go
- internal/api/core/memory_services_test.go
- internal/cli/network_test.go
- internal/cli/helpers_test.go
- internal/api/core/agent_channels_internal_test.go
- internal/api/udsapi/udsapi_integration_test.go
- internal/daemon/native_tools.go
- internal/api/udsapi/handlers_test.go
- internal/daemon/native_tools_test.go
| path: "/workspaces/ws-workspace/sessions/sess_1/soul/refresh", | ||
| body: []byte(`{"expected_digest":"sha256:old"}`), | ||
| registerRoute: func(fixture handlerFixture) { | ||
| fixture.Engine.POST("/sessions/:id/soul/refresh", fixture.Handlers.RefreshSessionSoul) | ||
| fixture.Engine.POST( | ||
| "/workspaces/ws-workspace/sessions/:id/soul/refresh", | ||
| fixture.Handlers.RefreshSessionSoul, | ||
| ) |
There was a problem hiding this comment.
Use a workspace path parameter in route registration.
Registering with "/workspaces/ws-workspace/sessions/:id/soul/refresh" hardcodes the workspace and skips workspace_id param binding behavior. Using :workspace_id keeps this test aligned with the workspace-scoped contract and catches param-related regressions.
Suggested patch
registerRoute: func(fixture handlerFixture) {
fixture.Engine.POST(
- "/workspaces/ws-workspace/sessions/:id/soul/refresh",
+ "/workspaces/:workspace_id/sessions/:id/soul/refresh",
fixture.Handlers.RefreshSessionSoul,
)
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| path: "/workspaces/ws-workspace/sessions/sess_1/soul/refresh", | |
| body: []byte(`{"expected_digest":"sha256:old"}`), | |
| registerRoute: func(fixture handlerFixture) { | |
| fixture.Engine.POST("/sessions/:id/soul/refresh", fixture.Handlers.RefreshSessionSoul) | |
| fixture.Engine.POST( | |
| "/workspaces/ws-workspace/sessions/:id/soul/refresh", | |
| fixture.Handlers.RefreshSessionSoul, | |
| ) | |
| path: "/workspaces/ws-workspace/sessions/sess_1/soul/refresh", | |
| body: []byte(`{"expected_digest":"sha256:old"}`), | |
| registerRoute: func(fixture handlerFixture) { | |
| fixture.Engine.POST( | |
| "/workspaces/:workspace_id/sessions/:id/soul/refresh", | |
| fixture.Handlers.RefreshSessionSoul, | |
| ) | |
| }, |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@internal/api/core/authored_context_test.go` around lines 461 - 467, The test
hardcodes the workspace in the registered route which bypasses workspace_id
param binding; update the route registration inside registerRoute (the
fixture.Engine.POST call that wires RefreshSessionSoul) to use a workspace
param, e.g. "/workspaces/:workspace_id/sessions/:id/soul/refresh", and ensure
the test's path value (the path variable) matches that pattern
("/workspaces/ws-workspace/sessions/sess_1/soul/refresh") so the
handlerFixture.RegisterRoute and RefreshSessionSoul exercise workspace_id
binding correctly.
| listResp := performRequest(t, engine, http.MethodGet, "/workspaces/ws-alias/sessions/sess-1/tools", nil) | ||
| if listResp.Code != http.StatusOK { | ||
| t.Fatalf("session list status = %d, want %d; body=%s", listResp.Code, http.StatusOK, listResp.Body.String()) | ||
| } | ||
| listScope := registry.lastList() | ||
| if listScope.WorkspaceID != "ws-stable" || listScope.SessionID != "sess-1" { | ||
| t.Fatalf("list scope = %#v, want resolved stable workspace and route session", listScope) | ||
| } | ||
|
|
||
| searchResp := performRequest( | ||
| t, | ||
| engine, | ||
| http.MethodPost, | ||
| "/workspaces/ws-alias/sessions/sess-1/tools/search", | ||
| []byte(`{"query":"skill","limit":1,"workspace_id":"ws-stable","session_id":"sess-1"}`), | ||
| ) | ||
| if searchResp.Code != http.StatusOK { | ||
| t.Fatalf( | ||
| "session search status = %d, want %d; body=%s", | ||
| searchResp.Code, | ||
| http.StatusOK, | ||
| searchResp.Body.String(), | ||
| ) | ||
| } | ||
| searchScope, _ := registry.lastSearch() | ||
| if searchScope.WorkspaceID != "ws-stable" || searchScope.SessionID != "sess-1" { | ||
| t.Fatalf("search scope = %#v, want resolved stable workspace and route session", searchScope) | ||
| } |
There was a problem hiding this comment.
Assert response payloads on successful session list/search calls.
These assertions currently verify status and scope side effects, but not the HTTP payload shape. Add body checks to catch serialization/contract regressions on success paths.
Suggested patch
listResp := performRequest(t, engine, http.MethodGet, "/workspaces/ws-alias/sessions/sess-1/tools", nil)
if listResp.Code != http.StatusOK {
t.Fatalf("session list status = %d, want %d; body=%s", listResp.Code, http.StatusOK, listResp.Body.String())
}
+ var listPayload contract.ToolsResponse
+ decodeToolJSON(t, listResp.Body.Bytes(), &listPayload)
+ if got, want := len(listPayload.Tools), 1; got != want {
+ t.Fatalf("session list tool count = %d, want %d", got, want)
+ }
listScope := registry.lastList()
if listScope.WorkspaceID != "ws-stable" || listScope.SessionID != "sess-1" {
t.Fatalf("list scope = %#v, want resolved stable workspace and route session", listScope)
}
@@
if searchResp.Code != http.StatusOK {
t.Fatalf(
"session search status = %d, want %d; body=%s",
searchResp.Code,
http.StatusOK,
searchResp.Body.String(),
)
}
+ var searchPayload contract.ToolsResponse
+ decodeToolJSON(t, searchResp.Body.Bytes(), &searchPayload)
+ if got, want := len(searchPayload.Tools), 1; got != want {
+ t.Fatalf("session search tool count = %d, want %d", got, want)
+ }
searchScope, _ := registry.lastSearch()
if searchScope.WorkspaceID != "ws-stable" || searchScope.SessionID != "sess-1" {
t.Fatalf("search scope = %#v, want resolved stable workspace and route session", searchScope)
}As per coding guidelines "**/*_test.go: Assert both status code and response body in HTTP tests; status-code-only assertions are insufficient".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| listResp := performRequest(t, engine, http.MethodGet, "/workspaces/ws-alias/sessions/sess-1/tools", nil) | |
| if listResp.Code != http.StatusOK { | |
| t.Fatalf("session list status = %d, want %d; body=%s", listResp.Code, http.StatusOK, listResp.Body.String()) | |
| } | |
| listScope := registry.lastList() | |
| if listScope.WorkspaceID != "ws-stable" || listScope.SessionID != "sess-1" { | |
| t.Fatalf("list scope = %#v, want resolved stable workspace and route session", listScope) | |
| } | |
| searchResp := performRequest( | |
| t, | |
| engine, | |
| http.MethodPost, | |
| "/workspaces/ws-alias/sessions/sess-1/tools/search", | |
| []byte(`{"query":"skill","limit":1,"workspace_id":"ws-stable","session_id":"sess-1"}`), | |
| ) | |
| if searchResp.Code != http.StatusOK { | |
| t.Fatalf( | |
| "session search status = %d, want %d; body=%s", | |
| searchResp.Code, | |
| http.StatusOK, | |
| searchResp.Body.String(), | |
| ) | |
| } | |
| searchScope, _ := registry.lastSearch() | |
| if searchScope.WorkspaceID != "ws-stable" || searchScope.SessionID != "sess-1" { | |
| t.Fatalf("search scope = %#v, want resolved stable workspace and route session", searchScope) | |
| } | |
| listResp := performRequest(t, engine, http.MethodGet, "/workspaces/ws-alias/sessions/sess-1/tools", nil) | |
| if listResp.Code != http.StatusOK { | |
| t.Fatalf("session list status = %d, want %d; body=%s", listResp.Code, http.StatusOK, listResp.Body.String()) | |
| } | |
| var listPayload contract.ToolsResponse | |
| decodeToolJSON(t, listResp.Body.Bytes(), &listPayload) | |
| if got, want := len(listPayload.Tools), 1; got != want { | |
| t.Fatalf("session list tool count = %d, want %d", got, want) | |
| } | |
| listScope := registry.lastList() | |
| if listScope.WorkspaceID != "ws-stable" || listScope.SessionID != "sess-1" { | |
| t.Fatalf("list scope = %#v, want resolved stable workspace and route session", listScope) | |
| } | |
| searchResp := performRequest( | |
| t, | |
| engine, | |
| http.MethodPost, | |
| "/workspaces/ws-alias/sessions/sess-1/tools/search", | |
| []byte(`{"query":"skill","limit":1,"workspace_id":"ws-stable","session_id":"sess-1"}`), | |
| ) | |
| if searchResp.Code != http.StatusOK { | |
| t.Fatalf( | |
| "session search status = %d, want %d; body=%s", | |
| searchResp.Code, | |
| http.StatusOK, | |
| searchResp.Body.String(), | |
| ) | |
| } | |
| var searchPayload contract.ToolsResponse | |
| decodeToolJSON(t, searchResp.Body.Bytes(), &searchPayload) | |
| if got, want := len(searchPayload.Tools), 1; got != want { | |
| t.Fatalf("session search tool count = %d, want %d", got, want) | |
| } | |
| searchScope, _ := registry.lastSearch() | |
| if searchScope.WorkspaceID != "ws-stable" || searchScope.SessionID != "sess-1" { | |
| t.Fatalf("search scope = %#v, want resolved stable workspace and route session", searchScope) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@internal/api/core/tools_test.go` around lines 443 - 470, The tests call
performRequest for the session list and session search paths and only assert
HTTP status and registry side-effects (listResp, searchResp,
registry.lastList(), registry.lastSearch()); add assertions that decode and
validate the JSON response bodies for both listResp and searchResp to ensure the
payload shape is correct (e.g., expected top-level fields, types, counts or
specific entries). Update the test to unmarshal listResp.Body and
searchResp.Body into appropriate structs or maps and assert expected keys/values
(for example presence of tools array/items, length matching limit, and any
expected tool fields), so serialization/contract regressions are caught
alongside status and scope checks.
## Release v0.0.1 This PR prepares the release of version v0.0.1. ### Changelog ## 0.0.1 - 2026-05-26 ### Other Changes - Lessons learned ### ♻️ Refactoring - Project structure (#7) - Kb improvements (#12) - Rename spaces to channels (#17) - Add extensions gaps (#21) - Improve tool calls ui (#22) - Remove web app header - Module improvements (#29) - Memory improvements (#35) - Storybook for web and ui (#38) - Enable AGH network by default for new installs (#57) - Hermes adjustments (#69) - Badges design (#84) - Storybook scenario and logos gallery - Migrate typescript tests (#114) - Internal go packages (#120) - Ui patterns (#127) - Improve e2e tests (#130) - Ui redesign - Workspace isolation across runtime surfaces (#145) - Prod ready applies (#162) - Tool card ui (#164) - Alpha on logo - Prod ready features (#167) - Thread sheet (#202) ### 🎉 Features - Implement config foundation packages - Implement sqlite store package - Add ACP client package - Add session lifecycle manager - Implement observe package - Add daemon composition root - Add uds api server - Implement cli package - Add http api server - Add system design - Add foundation types, schemas, and layout shell for web client - Add daemon health polling and agent sidebar systems for web client - Add session system CRUD, streaming core, and session store for web client - Add chat view, messages, and composer tests for web client - Add tool cards and renderers for web client - Add file-backed memory store core - Scaffold memory session seams - Add memory dream consolidation service - Wire memory assembler into daemon - Add memory api and cli - New skills system (#1) - Add workspace entity (#5) - Add new skill capabilities (#8) - Web ui v2 (#9) - Improve hooks system (#10) - Session resilience (#11) - Add extensability (#13) - Add automation (#16) - Add channels (#14) - Add network implementation (#15) - Add network, bridges and automations web pages (#18) - Ext registry (#20) - Add core tasks (#19) - Bridge adapters (#23) - Add site (#26) - Add ext refac and sandbox (#25) - Settings ui (#37) - Tasks ui (#36) - Harness improvements (#44) - Agent capabilities (#49) - Redesign ui (#48) - Unify capability (#53) - Redesign network workspace (#59) - Add task deletion and split session delete from stop (#58) - Session provider selection (#60) - Production grade adjustments (#66) - Autonomous system (#75) - Add agent session route (#80) - Tools registry (#85) - Agents soul (#88) - Add network threads (#105) - Orchestration improvements (#106) - Memory v2 (#108) - Agent categories (#113) - Providers model (#118) - Add canonical AGH bundled skill (#143) - Onboarding and improvements (#198) - Onboarding and improvements (#201) ### 🐛 Bug Fixes - Review round - Review rounds - Resolve memory extensibility review batch - Embed web into daemon - Defaults agents - Acp integration (#4) - Lint errors - Prd folder - Remove orphan web actions and dead surfaces (#55) - Qa testing and fixes (#73) - New review rounds (#82) - Security audit (#90) - Release qa round (#95) - Add missing tools (#141) - New qa round (#147) - Advanced qa round (#149) - Homebrew tap - Final review round (#151) - Daemon healthy - Reasoning models (#158) - Lint errors (#160) - Review round (#168) - Release adjustments (#171) - Stabilize release ci fixtures - Stabilize release integration gate - Stabilize release verify gates - Stabilize release integration flows - Stabilize release verify gates - Stabilize main verify shutdown - Ignore stale acpmock cancel - Marketplace search focus and filtering (#193) - Website video - Workspace command select ### 📚 Documentation - Update agents.md - Update prd - Update skills - Update compozy tasks - Update compozy - Update compozy - Add new skills - Archive prd - Update prds - Update rfc - Update prds - Update prds - Add automation prd - Channels prd - Update prd - Update prd - New prds - Archive prds - Bridges adapters prd - Sandbox prd - Update - Archive prd - Update - Add new prd - New design - Update prd - Archive prds - Update prds - Tasks-ui prd tasks - Update prd - Update design docs - Agent capabilities prd - Improve site docs - Remove old design references - Udpate - Autonomous prd - Update skills - Blog design - Agent sould prd - Final qa plan - Update - Remove codex ledgers from gitignore - Remove not needed files - Udpate ledger - Update cy-codex-loop skill - Orchestration improves prd - Update prds - Orch improvs prd - Memv2 prd - Providers model prd - Update refacs prd - New design proposal - Update rules - Update skills - New blog posts (#173) - Format docs - Remove old design files - Remove old - Skeeper update ### 📦 Build System - Initial structure - Commitlint - Frontend base structure - Update vscode settings - Add subagents - Coderabbit - Prd and tooling - Bun lock - Lint tooling - Copy.md and tooling adjusts - Add repoclone rc - Upgrade skeeper to v0.2.0 - Update go.mod - Adopt task artifacts into skeeper - Sync codex plans with skeeper - Skeeper lock - Skeeper lock - New skills - Skeeper lock - Skeeper lock - Skeeper lock - Update deps and go - Regenerate daytona sidecar assets for go 1.26.3 - Fix cliff - Ignore docs on fmt - Build web assets before goreleaser - Extend release dry-run timeout ### 🔧 CI/CD - Lint errors - Fint release pr - Fix goreleaser ### 🧪 Testing - Add e2e tests (#27) - Qa rounds (#78) - Improve test suite (#138) - Harden daemon-served restart reloads - Harden daemon-served readiness waits - Stabilize dashboard focus assertion - Stabilize release integration gates - Stabilize release e2e markers - Stabilize release e2e flows Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## Release v0.0.1 This PR prepares the release of version v0.0.1. ### Changelog ## 0.0.1 - 2026-05-26 ### Other Changes - Lessons learned ### ♻️ Refactoring - Project structure (#7) - Kb improvements (#12) - Rename spaces to channels (#17) - Add extensions gaps (#21) - Improve tool calls ui (#22) - Remove web app header - Module improvements (#29) - Memory improvements (#35) - Storybook for web and ui (#38) - Enable AGH network by default for new installs (#57) - Hermes adjustments (#69) - Badges design (#84) - Storybook scenario and logos gallery - Migrate typescript tests (#114) - Internal go packages (#120) - Ui patterns (#127) - Improve e2e tests (#130) - Ui redesign - Workspace isolation across runtime surfaces (#145) - Prod ready applies (#162) - Tool card ui (#164) - Alpha on logo - Prod ready features (#167) - Thread sheet (#202) ### 🎉 Features - Implement config foundation packages - Implement sqlite store package - Add ACP client package - Add session lifecycle manager - Implement observe package - Add daemon composition root - Add uds api server - Implement cli package - Add http api server - Add system design - Add foundation types, schemas, and layout shell for web client - Add daemon health polling and agent sidebar systems for web client - Add session system CRUD, streaming core, and session store for web client - Add chat view, messages, and composer tests for web client - Add tool cards and renderers for web client - Add file-backed memory store core - Scaffold memory session seams - Add memory dream consolidation service - Wire memory assembler into daemon - Add memory api and cli - New skills system (#1) - Add workspace entity (#5) - Add new skill capabilities (#8) - Web ui v2 (#9) - Improve hooks system (#10) - Session resilience (#11) - Add extensability (#13) - Add automation (#16) - Add channels (#14) - Add network implementation (#15) - Add network, bridges and automations web pages (#18) - Ext registry (#20) - Add core tasks (#19) - Bridge adapters (#23) - Add site (#26) - Add ext refac and sandbox (#25) - Settings ui (#37) - Tasks ui (#36) - Harness improvements (#44) - Agent capabilities (#49) - Redesign ui (#48) - Unify capability (#53) - Redesign network workspace (#59) - Add task deletion and split session delete from stop (#58) - Session provider selection (#60) - Production grade adjustments (#66) - Autonomous system (#75) - Add agent session route (#80) - Tools registry (#85) - Agents soul (#88) - Add network threads (#105) - Orchestration improvements (#106) - Memory v2 (#108) - Agent categories (#113) - Providers model (#118) - Add canonical AGH bundled skill (#143) - Onboarding and improvements (#198) - Onboarding and improvements (#201) ### 🐛 Bug Fixes - Review round - Review rounds - Resolve memory extensibility review batch - Embed web into daemon - Defaults agents - Acp integration (#4) - Lint errors - Prd folder - Remove orphan web actions and dead surfaces (#55) - Qa testing and fixes (#73) - New review rounds (#82) - Security audit (#90) - Release qa round (#95) - Add missing tools (#141) - New qa round (#147) - Advanced qa round (#149) - Homebrew tap - Final review round (#151) - Daemon healthy - Reasoning models (#158) - Lint errors (#160) - Review round (#168) - Release adjustments (#171) - Stabilize release ci fixtures - Stabilize release integration gate - Stabilize release verify gates - Stabilize release integration flows - Stabilize release verify gates - Stabilize main verify shutdown - Ignore stale acpmock cancel - Marketplace search focus and filtering (#193) - Website video - Workspace command select ### 📚 Documentation - Update agents.md - Update prd - Update skills - Update compozy tasks - Update compozy - Update compozy - Add new skills - Archive prd - Update prds - Update rfc - Update prds - Update prds - Add automation prd - Channels prd - Update prd - Update prd - New prds - Archive prds - Bridges adapters prd - Sandbox prd - Update - Archive prd - Update - Add new prd - New design - Update prd - Archive prds - Update prds - Tasks-ui prd tasks - Update prd - Update design docs - Agent capabilities prd - Improve site docs - Remove old design references - Udpate - Autonomous prd - Update skills - Blog design - Agent sould prd - Final qa plan - Update - Remove codex ledgers from gitignore - Remove not needed files - Udpate ledger - Update cy-codex-loop skill - Orchestration improves prd - Update prds - Orch improvs prd - Memv2 prd - Providers model prd - Update refacs prd - New design proposal - Update rules - Update skills - New blog posts (#173) - Format docs - Remove old design files - Remove old - Skeeper update ### 📦 Build System - Initial structure - Commitlint - Frontend base structure - Update vscode settings - Add subagents - Coderabbit - Prd and tooling - Bun lock - Lint tooling - Copy.md and tooling adjusts - Add repoclone rc - Upgrade skeeper to v0.2.0 - Update go.mod - Adopt task artifacts into skeeper - Sync codex plans with skeeper - Skeeper lock - Skeeper lock - New skills - Skeeper lock - Skeeper lock - Skeeper lock - Update deps and go - Regenerate daytona sidecar assets for go 1.26.3 - Fix cliff - Ignore docs on fmt - Build web assets before goreleaser - Extend release dry-run timeout ### 🔧 CI/CD - Lint errors - Fint release pr - Fix goreleaser - Fix release ### 🧪 Testing - Add e2e tests (#27) - Qa rounds (#78) - Improve test suite (#138) - Harden daemon-served restart reloads - Harden daemon-served readiness waits - Stabilize dashboard focus assertion - Stabilize release integration gates - Stabilize release e2e markers - Stabilize release e2e flows Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## Release v0.0.2 This PR prepares the release of version v0.0.2. ### Changelog ## 0.0.2 - 2026-05-26 ### Other Changes - Lessons learned ### ♻️ Refactoring - Project structure (#7) - Kb improvements (#12) - Rename spaces to channels (#17) - Add extensions gaps (#21) - Improve tool calls ui (#22) - Remove web app header - Module improvements (#29) - Memory improvements (#35) - Storybook for web and ui (#38) - Enable AGH network by default for new installs (#57) - Hermes adjustments (#69) - Badges design (#84) - Storybook scenario and logos gallery - Migrate typescript tests (#114) - Internal go packages (#120) - Ui patterns (#127) - Improve e2e tests (#130) - Ui redesign - Workspace isolation across runtime surfaces (#145) - Prod ready applies (#162) - Tool card ui (#164) - Alpha on logo - Prod ready features (#167) - Thread sheet (#202) ### 🎉 Features - Implement config foundation packages - Implement sqlite store package - Add ACP client package - Add session lifecycle manager - Implement observe package - Add daemon composition root - Add uds api server - Implement cli package - Add http api server - Add system design - Add foundation types, schemas, and layout shell for web client - Add daemon health polling and agent sidebar systems for web client - Add session system CRUD, streaming core, and session store for web client - Add chat view, messages, and composer tests for web client - Add tool cards and renderers for web client - Add file-backed memory store core - Scaffold memory session seams - Add memory dream consolidation service - Wire memory assembler into daemon - Add memory api and cli - New skills system (#1) - Add workspace entity (#5) - Add new skill capabilities (#8) - Web ui v2 (#9) - Improve hooks system (#10) - Session resilience (#11) - Add extensability (#13) - Add automation (#16) - Add channels (#14) - Add network implementation (#15) - Add network, bridges and automations web pages (#18) - Ext registry (#20) - Add core tasks (#19) - Bridge adapters (#23) - Add site (#26) - Add ext refac and sandbox (#25) - Settings ui (#37) - Tasks ui (#36) - Harness improvements (#44) - Agent capabilities (#49) - Redesign ui (#48) - Unify capability (#53) - Redesign network workspace (#59) - Add task deletion and split session delete from stop (#58) - Session provider selection (#60) - Production grade adjustments (#66) - Autonomous system (#75) - Add agent session route (#80) - Tools registry (#85) - Agents soul (#88) - Add network threads (#105) - Orchestration improvements (#106) - Memory v2 (#108) - Agent categories (#113) - Providers model (#118) - Add canonical AGH bundled skill (#143) - Onboarding and improvements (#198) - Onboarding and improvements (#201) ### 🐛 Bug Fixes - Review round - Review rounds - Resolve memory extensibility review batch - Embed web into daemon - Defaults agents - Acp integration (#4) - Lint errors - Prd folder - Remove orphan web actions and dead surfaces (#55) - Qa testing and fixes (#73) - New review rounds (#82) - Security audit (#90) - Release qa round (#95) - Add missing tools (#141) - New qa round (#147) - Advanced qa round (#149) - Homebrew tap - Final review round (#151) - Daemon healthy - Reasoning models (#158) - Lint errors (#160) - Review round (#168) - Release adjustments (#171) - Stabilize release ci fixtures - Stabilize release integration gate - Stabilize release verify gates - Stabilize release integration flows - Stabilize release verify gates - Stabilize main verify shutdown - Ignore stale acpmock cancel - Marketplace search focus and filtering (#193) - Website video - Workspace command select ### 📚 Documentation - Update agents.md - Update prd - Update skills - Update compozy tasks - Update compozy - Update compozy - Add new skills - Archive prd - Update prds - Update rfc - Update prds - Update prds - Add automation prd - Channels prd - Update prd - Update prd - New prds - Archive prds - Bridges adapters prd - Sandbox prd - Update - Archive prd - Update - Add new prd - New design - Update prd - Archive prds - Update prds - Tasks-ui prd tasks - Update prd - Update design docs - Agent capabilities prd - Improve site docs - Remove old design references - Udpate - Autonomous prd - Update skills - Blog design - Agent sould prd - Final qa plan - Update - Remove codex ledgers from gitignore - Remove not needed files - Udpate ledger - Update cy-codex-loop skill - Orchestration improves prd - Update prds - Orch improvs prd - Memv2 prd - Providers model prd - Update refacs prd - New design proposal - Update rules - Update skills - New blog posts (#173) - Format docs - Remove old design files - Remove old - Skeeper update ### 📦 Build System - Initial structure - Commitlint - Frontend base structure - Update vscode settings - Add subagents - Coderabbit - Prd and tooling - Bun lock - Lint tooling - Copy.md and tooling adjusts - Add repoclone rc - Upgrade skeeper to v0.2.0 - Update go.mod - Adopt task artifacts into skeeper - Sync codex plans with skeeper - Skeeper lock - Skeeper lock - New skills - Skeeper lock - Skeeper lock - Skeeper lock - Update deps and go - Regenerate daytona sidecar assets for go 1.26.3 - Fix cliff - Ignore docs on fmt - Build web assets before goreleaser - Extend release dry-run timeout ### 🔧 CI/CD - Lint errors - Fint release pr - Fix goreleaser - Fix release - Fix release process ### 🧪 Testing - Add e2e tests (#27) - Qa rounds (#78) - Improve test suite (#138) - Harden daemon-served restart reloads - Harden daemon-served readiness waits - Stabilize dashboard focus assertion - Stabilize release integration gates - Stabilize release e2e markers - Stabilize release e2e flows - Improve suite speed Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## Release v0.0.2 This PR prepares the release of version v0.0.2. ### Changelog ## 0.0.2 - 2026-05-26 ### Other Changes - Lessons learned ### ♻️ Refactoring - Project structure (#7) - Kb improvements (#12) - Rename spaces to channels (#17) - Add extensions gaps (#21) - Improve tool calls ui (#22) - Remove web app header - Module improvements (#29) - Memory improvements (#35) - Storybook for web and ui (#38) - Enable AGH network by default for new installs (#57) - Hermes adjustments (#69) - Badges design (#84) - Storybook scenario and logos gallery - Migrate typescript tests (#114) - Internal go packages (#120) - Ui patterns (#127) - Improve e2e tests (#130) - Ui redesign - Workspace isolation across runtime surfaces (#145) - Prod ready applies (#162) - Tool card ui (#164) - Alpha on logo - Prod ready features (#167) - Thread sheet (#202) ### 🎉 Features - Implement config foundation packages - Implement sqlite store package - Add ACP client package - Add session lifecycle manager - Implement observe package - Add daemon composition root - Add uds api server - Implement cli package - Add http api server - Add system design - Add foundation types, schemas, and layout shell for web client - Add daemon health polling and agent sidebar systems for web client - Add session system CRUD, streaming core, and session store for web client - Add chat view, messages, and composer tests for web client - Add tool cards and renderers for web client - Add file-backed memory store core - Scaffold memory session seams - Add memory dream consolidation service - Wire memory assembler into daemon - Add memory api and cli - New skills system (#1) - Add workspace entity (#5) - Add new skill capabilities (#8) - Web ui v2 (#9) - Improve hooks system (#10) - Session resilience (#11) - Add extensability (#13) - Add automation (#16) - Add channels (#14) - Add network implementation (#15) - Add network, bridges and automations web pages (#18) - Ext registry (#20) - Add core tasks (#19) - Bridge adapters (#23) - Add site (#26) - Add ext refac and sandbox (#25) - Settings ui (#37) - Tasks ui (#36) - Harness improvements (#44) - Agent capabilities (#49) - Redesign ui (#48) - Unify capability (#53) - Redesign network workspace (#59) - Add task deletion and split session delete from stop (#58) - Session provider selection (#60) - Production grade adjustments (#66) - Autonomous system (#75) - Add agent session route (#80) - Tools registry (#85) - Agents soul (#88) - Add network threads (#105) - Orchestration improvements (#106) - Memory v2 (#108) - Agent categories (#113) - Providers model (#118) - Add canonical AGH bundled skill (#143) - Onboarding and improvements (#198) - Onboarding and improvements (#201) ### 🐛 Bug Fixes - Review round - Review rounds - Resolve memory extensibility review batch - Embed web into daemon - Defaults agents - Acp integration (#4) - Lint errors - Prd folder - Remove orphan web actions and dead surfaces (#55) - Qa testing and fixes (#73) - New review rounds (#82) - Security audit (#90) - Release qa round (#95) - Add missing tools (#141) - New qa round (#147) - Advanced qa round (#149) - Homebrew tap - Final review round (#151) - Daemon healthy - Reasoning models (#158) - Lint errors (#160) - Review round (#168) - Release adjustments (#171) - Stabilize release ci fixtures - Stabilize release integration gate - Stabilize release verify gates - Stabilize release integration flows - Stabilize release verify gates - Stabilize main verify shutdown - Ignore stale acpmock cancel - Marketplace search focus and filtering (#193) - Website video - Workspace command select ### 📚 Documentation - Update agents.md - Update prd - Update skills - Update compozy tasks - Update compozy - Update compozy - Add new skills - Archive prd - Update prds - Update rfc - Update prds - Update prds - Add automation prd - Channels prd - Update prd - Update prd - New prds - Archive prds - Bridges adapters prd - Sandbox prd - Update - Archive prd - Update - Add new prd - New design - Update prd - Archive prds - Update prds - Tasks-ui prd tasks - Update prd - Update design docs - Agent capabilities prd - Improve site docs - Remove old design references - Udpate - Autonomous prd - Update skills - Blog design - Agent sould prd - Final qa plan - Update - Remove codex ledgers from gitignore - Remove not needed files - Udpate ledger - Update cy-codex-loop skill - Orchestration improves prd - Update prds - Orch improvs prd - Memv2 prd - Providers model prd - Update refacs prd - New design proposal - Update rules - Update skills - New blog posts (#173) - Format docs - Remove old design files - Remove old - Skeeper update ### 📦 Build System - Initial structure - Commitlint - Frontend base structure - Update vscode settings - Add subagents - Coderabbit - Prd and tooling - Bun lock - Lint tooling - Copy.md and tooling adjusts - Add repoclone rc - Upgrade skeeper to v0.2.0 - Update go.mod - Adopt task artifacts into skeeper - Sync codex plans with skeeper - Skeeper lock - Skeeper lock - New skills - Skeeper lock - Skeeper lock - Skeeper lock - Update deps and go - Regenerate daytona sidecar assets for go 1.26.3 - Fix cliff - Ignore docs on fmt - Build web assets before goreleaser - Extend release dry-run timeout ### 🔧 CI/CD - Lint errors - Fint release pr - Fix goreleaser - Fix release - Fix release process - Fix release sync - Decouple release dry-run npm auth - Persist web assets git auth ### 🧪 Testing - Add e2e tests (#27) - Qa rounds (#78) - Improve test suite (#138) - Harden daemon-served restart reloads - Harden daemon-served readiness waits - Stabilize dashboard focus assertion - Stabilize release integration gates - Stabilize release e2e markers - Stabilize release e2e flows - Improve suite speed <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated web assets dependency to a newer version for improved stability and performance. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/compozy/agh/pull/211?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## Release v0.0.2 This PR prepares the release of version v0.0.2. ### Changelog ## 0.0.2 - 2026-05-27 ### Other Changes - Lessons learned ### ♻️ Refactoring - Project structure (#7) - Kb improvements (#12) - Rename spaces to channels (#17) - Add extensions gaps (#21) - Improve tool calls ui (#22) - Remove web app header - Module improvements (#29) - Memory improvements (#35) - Storybook for web and ui (#38) - Enable AGH network by default for new installs (#57) - Hermes adjustments (#69) - Badges design (#84) - Storybook scenario and logos gallery - Migrate typescript tests (#114) - Internal go packages (#120) - Ui patterns (#127) - Improve e2e tests (#130) - Ui redesign - Workspace isolation across runtime surfaces (#145) - Prod ready applies (#162) - Tool card ui (#164) - Alpha on logo - Prod ready features (#167) - Thread sheet (#202) ### 🎉 Features - Implement config foundation packages - Implement sqlite store package - Add ACP client package - Add session lifecycle manager - Implement observe package - Add daemon composition root - Add uds api server - Implement cli package - Add http api server - Add system design - Add foundation types, schemas, and layout shell for web client - Add daemon health polling and agent sidebar systems for web client - Add session system CRUD, streaming core, and session store for web client - Add chat view, messages, and composer tests for web client - Add tool cards and renderers for web client - Add file-backed memory store core - Scaffold memory session seams - Add memory dream consolidation service - Wire memory assembler into daemon - Add memory api and cli - New skills system (#1) - Add workspace entity (#5) - Add new skill capabilities (#8) - Web ui v2 (#9) - Improve hooks system (#10) - Session resilience (#11) - Add extensability (#13) - Add automation (#16) - Add channels (#14) - Add network implementation (#15) - Add network, bridges and automations web pages (#18) - Ext registry (#20) - Add core tasks (#19) - Bridge adapters (#23) - Add site (#26) - Add ext refac and sandbox (#25) - Settings ui (#37) - Tasks ui (#36) - Harness improvements (#44) - Agent capabilities (#49) - Redesign ui (#48) - Unify capability (#53) - Redesign network workspace (#59) - Add task deletion and split session delete from stop (#58) - Session provider selection (#60) - Production grade adjustments (#66) - Autonomous system (#75) - Add agent session route (#80) - Tools registry (#85) - Agents soul (#88) - Add network threads (#105) - Orchestration improvements (#106) - Memory v2 (#108) - Agent categories (#113) - Providers model (#118) - Add canonical AGH bundled skill (#143) - Onboarding and improvements (#198) - Onboarding and improvements (#201) ### 🐛 Bug Fixes - Review round - Review rounds - Resolve memory extensibility review batch - Embed web into daemon - Defaults agents - Acp integration (#4) - Lint errors - Prd folder - Remove orphan web actions and dead surfaces (#55) - Qa testing and fixes (#73) - New review rounds (#82) - Security audit (#90) - Release qa round (#95) - Add missing tools (#141) - New qa round (#147) - Advanced qa round (#149) - Homebrew tap - Final review round (#151) - Daemon healthy - Reasoning models (#158) - Lint errors (#160) - Review round (#168) - Release adjustments (#171) - Stabilize release ci fixtures - Stabilize release integration gate - Stabilize release verify gates - Stabilize release integration flows - Stabilize release verify gates - Stabilize main verify shutdown - Ignore stale acpmock cancel - Marketplace search focus and filtering (#193) - Website video - Workspace command select ### 📚 Documentation - Update agents.md - Update prd - Update skills - Update compozy tasks - Update compozy - Update compozy - Add new skills - Archive prd - Update prds - Update rfc - Update prds - Update prds - Add automation prd - Channels prd - Update prd - Update prd - New prds - Archive prds - Bridges adapters prd - Sandbox prd - Update - Archive prd - Update - Add new prd - New design - Update prd - Archive prds - Update prds - Tasks-ui prd tasks - Update prd - Update design docs - Agent capabilities prd - Improve site docs - Remove old design references - Udpate - Autonomous prd - Update skills - Blog design - Agent sould prd - Final qa plan - Update - Remove codex ledgers from gitignore - Remove not needed files - Udpate ledger - Update cy-codex-loop skill - Orchestration improves prd - Update prds - Orch improvs prd - Memv2 prd - Providers model prd - Update refacs prd - New design proposal - Update rules - Update skills - New blog posts (#173) - Format docs - Remove old design files - Remove old - Skeeper update ### 📦 Build System - Initial structure - Commitlint - Frontend base structure - Update vscode settings - Add subagents - Coderabbit - Prd and tooling - Bun lock - Lint tooling - Copy.md and tooling adjusts - Add repoclone rc - Upgrade skeeper to v0.2.0 - Update go.mod - Adopt task artifacts into skeeper - Sync codex plans with skeeper - Skeeper lock - Skeeper lock - New skills - Skeeper lock - Skeeper lock - Skeeper lock - Update deps and go - Regenerate daytona sidecar assets for go 1.26.3 - Fix cliff - Ignore docs on fmt - Build web assets before goreleaser - Extend release dry-run timeout - Fix release dry-run token contract ### 🔧 CI/CD - Lint errors - Fint release pr - Fix goreleaser - Fix release - Fix release process - Fix release sync - Decouple release dry-run npm auth - Persist web assets git auth - Require npm auth before release merge ### 🧪 Testing - Add e2e tests (#27) - Qa rounds (#78) - Improve test suite (#138) - Harden daemon-served restart reloads - Harden daemon-served readiness waits - Stabilize dashboard focus assertion - Stabilize release integration gates - Stabilize release e2e markers - Stabilize release e2e flows - Improve suite speed <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated dependencies to latest versions. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/compozy/agh/pull/214?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Summary
Hard cuts workspace isolation across the remaining runtime surfaces that still had channel-only or bare session identity.
workspace_id + channelacross store keys, API routes, CLI/native tools, extension Host API, generated contracts, web routes/query keys, and docs./api/workspaces/{workspace_id}/...with server-side ownership validation before protected reads or mutations./api/network/statusand/api/observe/health.Release Notes
Features
Bug Fixes
Documentation
agh-network/v0toagh-network/v2.QA And Review Evidence
cy-impl-peer-reviewthrough Compozy/Claude Opus reached SHIP on round 4:.peer-reviews/20260513T063807Z-workspace-isolation-hard-cut/impl-review-summary-round4.md..codex/loop/workspace-isolation/analysis/opus-qa-coverage-report.md, verdictFIX_BEFORE_SHIP..codex/loop/workspace-isolation/analysis/opus-qa-coverage-closure-report.md, verdictSHIP, no new release blockers.qa-report/qa-executioncompleted with 0 filed issues:.compozy/tasks/workspace-isolation-hard-cut/qa/verification-report.md./Users/pedronauck/dev/qa-labs/agh-workspace-isolation-hard-cut-20260513-083558-013517-lab/qa-artifacts/qa/bootstrap-manifest.json.http://127.0.0.1:62018./Users/pedronauck/dev/qa-labs/agh-workspace-isolation-hard-cut-20260513-083558-013517-lab/qa-artifacts/qa/screenshots/network-route-threads.png/Users/pedronauck/dev/qa-labs/agh-workspace-isolation-hard-cut-20260513-083558-013517-lab/qa-artifacts/qa/screenshots/network-route-empty-channels.png/Users/pedronauck/dev/qa-labs/agh-workspace-isolation-hard-cut-20260513-083558-013517-lab/qa-artifacts/qa/screenshots/network-shell-default.pngVerification
Full gate before commit:
Full gate after commit
76afabb8:Full gate after RFC follow-up commit
6fb41e8d:The Vite build emitted the existing chunk-size warning during both full gates; lint reported 0 warnings and 0 errors.
Focused evidence also run during remediation:
Notes
skeeper sync --dry-runreported it would push 5720 specs, so no skeeper sync was applied in this PR to avoid unrelated generated churn..codex/loopand.compozy/tasksare intentionally not committed.Summary by CodeRabbit
New Features
Refactor