Skip to content

feat: add network, bridges and automations web pages#18

Merged
pedronauck merged 7 commits into
mainfrom
pn/web
Apr 14, 2026
Merged

feat: add network, bridges and automations web pages#18
pedronauck merged 7 commits into
mainfrom
pn/web

Conversation

@pedronauck
Copy link
Copy Markdown
Member

@pedronauck pedronauck commented Apr 14, 2026

Summary by CodeRabbit

  • New Features

    • Network tab: channels, peers, read-only timelines, create-channel with agent selection, channel/peer detail views, and peer/channel messages.
    • Bridges: provider discovery & listing, provider-aware bridge list/detail, create-bridge dialog, test-delivery tool, and new providers endpoint.
  • Telemetry & Persistence

    • Persisted network message history; bridge delivery and health now report last-success timestamps.
  • UI/UX Improvements

    • Sidebar links for Network and Bridges; new panels, dialogs, summaries, and improved relative-time and metric displays.

@pedronauck pedronauck self-assigned this Apr 14, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 14, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 03ed37fc-60a7-4adf-9caf-13c8475c0d7e

📥 Commits

Reviewing files that changed from the base of the PR and between c3b4ecc and 8fdc109.

⛔ Files ignored due to path filters (42)
  • .agents/skills/systematic-qa/SKILL.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/systematic-qa/assets/issue-template.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/systematic-qa/assets/verification-report-template.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/systematic-qa/references/checklist.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/systematic-qa/references/project-signals.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/systematic-qa/scripts/discover-project-contract.py is excluded by !.agents/**
  • .compozy/tasks/ext-ideas/research/analysis_claude_code.md is excluded by !**/*.md
  • .compozy/tasks/ext-ideas/research/analysis_ecosystem.md is excluded by !**/*.md
  • .compozy/tasks/ext-ideas/research/analysis_hermes.md is excluded by !**/*.md
  • .compozy/tasks/ext-ideas/research/integrations.md is excluded by !**/*.md
  • .compozy/tasks/extensability/analysis/analysis_claude_code.md is excluded by !**/*.md
  • .compozy/tasks/extensability/analysis/analysis_goclaw.md is excluded by !**/*.md
  • .compozy/tasks/extensability/analysis/analysis_hermes.md is excluded by !**/*.md
  • .compozy/tasks/extensability/analysis/analysis_openclaw.md is excluded by !**/*.md
  • .compozy/tasks/extensability/analysis/analysis_openfang.md is excluded by !**/*.md
  • .compozy/tasks/extensability/analysis/analysis_pi_mono.md is excluded by !**/*.md
  • docs/ideas/ext-ideas/research/analysis.md is excluded by !**/*.md
  • docs/ideas/ext-ideas/research/analysis_claude_code.md is excluded by !**/*.md
  • docs/ideas/ext-ideas/research/analysis_ecosystem.md is excluded by !**/*.md
  • docs/ideas/ext-ideas/research/analysis_hermes.md is excluded by !**/*.md
  • docs/ideas/ext-ideas/research/analysis_openclaw.md is excluded by !**/*.md
  • docs/ideas/ext-ideas/research/analysis_pi_mono.md is excluded by !**/*.md
  • docs/ideas/ext-ideas/research/integrations.md is excluded by !**/*.md
  • docs/ideas/ext-ideas/research/integrations_communication.md is excluded by !**/*.md
  • docs/ideas/ext-ideas/research/integrations_data_ai.md is excluded by !**/*.md
  • docs/ideas/ext-ideas/research/integrations_devops.md is excluded by !**/*.md
  • docs/ideas/ext-ideas/research/integrations_specialized.md is excluded by !**/*.md
  • docs/ideas/extensability/_meta.md is excluded by !**/*.md
  • docs/ideas/extensability/analysis.md is excluded by !**/*.md
  • docs/ideas/extensability/analysis/analysis_claude_code.md is excluded by !**/*.md
  • docs/ideas/extensability/analysis/analysis_cross_cutting.md is excluded by !**/*.md
  • docs/ideas/extensability/analysis/analysis_goclaw.md is excluded by !**/*.md
  • docs/ideas/extensability/analysis/analysis_hermes.md is excluded by !**/*.md
  • docs/ideas/extensability/analysis/analysis_openclaw.md is excluded by !**/*.md
  • docs/ideas/extensability/analysis/analysis_openfang.md is excluded by !**/*.md
  • docs/ideas/extensability/analysis/analysis_pi_mono.md is excluded by !**/*.md
  • docs/ideas/extensability/analysis/analysis_research_extensibility.md is excluded by !**/*.md
  • docs/ideas/qa-e2e/README.md is excluded by !**/*.md
  • openapi/agh.json is excluded by !**/*.json
  • sdk/examples/telegram-reference/extension.toml is excluded by !**/*.toml
  • skills-lock.json is excluded by !**/*.json
  • web/src/generated/agh-openapi.d.ts is excluded by !**/generated/**
📒 Files selected for processing (121)
  • internal/api/contract/bridges.go
  • internal/api/contract/contract.go
  • internal/api/contract/responses.go
  • internal/api/core/bridges.go
  • internal/api/core/bridges_test.go
  • internal/api/core/conversions.go
  • internal/api/core/handlers.go
  • internal/api/core/interfaces.go
  • internal/api/core/network.go
  • internal/api/core/network_details.go
  • internal/api/core/network_test.go
  • internal/api/core/session_workspace.go
  • internal/api/core/test_helpers_test.go
  • internal/api/httpapi/bridges_integration_test.go
  • internal/api/httpapi/bridges_test.go
  • internal/api/httpapi/handlers.go
  • internal/api/httpapi/handlers_test.go
  • internal/api/httpapi/httpapi_integration_test.go
  • internal/api/httpapi/routes.go
  • internal/api/httpapi/server.go
  • internal/api/spec/spec.go
  • internal/api/spec/spec_test.go
  • internal/api/testutil/apitest.go
  • internal/api/udsapi/bridges_test.go
  • internal/api/udsapi/handlers_test.go
  • internal/api/udsapi/routes.go
  • internal/api/udsapi/server.go
  • internal/api/udsapi/udsapi_integration_test.go
  • internal/automation/schedule_test.go
  • internal/bridges/delivery_broker.go
  • internal/bridges/delivery_broker_test.go
  • internal/bridges/delivery_metrics.go
  • internal/bridges/types.go
  • internal/cli/cli_integration_test.go
  • internal/daemon/bridges.go
  • internal/daemon/bridges_test.go
  • internal/daemon/daemon.go
  • internal/daemon/daemon_test.go
  • internal/daemon/extensions.go
  • internal/extension/manager_test.go
  • internal/extension/manifest.go
  • internal/extension/manifest_test.go
  • internal/network/audit.go
  • internal/network/audit_test.go
  • internal/network/manager.go
  • internal/network/manager_test.go
  • internal/observe/bridges.go
  • internal/observe/bridges_test.go
  • internal/store/globaldb/global_db.go
  • internal/store/globaldb/global_db_network_messages.go
  • internal/store/globaldb/global_db_network_messages_test.go
  • internal/store/store.go
  • internal/store/types.go
  • web/src/components/app-sidebar.test.tsx
  • web/src/components/app-sidebar.tsx
  • web/src/routeTree.gen.ts
  • web/src/routes/_app/-automation.integration.test.tsx
  • web/src/routes/_app/-bridges.test.tsx
  • web/src/routes/_app/-network.test.tsx
  • web/src/routes/_app/automation.tsx
  • web/src/routes/_app/bridges.tsx
  • web/src/routes/_app/network.tsx
  • web/src/systems/automation/components/automation-detail-panel.test.tsx
  • web/src/systems/automation/components/automation-detail-panel.tsx
  • web/src/systems/automation/components/automation-editor-dialog.tsx
  • web/src/systems/automation/components/automation-form-primitives.tsx
  • web/src/systems/automation/components/automation-job-form.test.tsx
  • web/src/systems/automation/components/automation-job-form.tsx
  • web/src/systems/automation/components/automation-list-panel.test.tsx
  • web/src/systems/automation/components/automation-list-panel.tsx
  • web/src/systems/automation/components/automation-run-history.tsx
  • web/src/systems/automation/components/automation-trigger-form.test.tsx
  • web/src/systems/automation/components/automation-trigger-form.tsx
  • web/src/systems/automation/index.ts
  • web/src/systems/automation/lib/automation-drafts.test.ts
  • web/src/systems/automation/lib/automation-drafts.ts
  • web/src/systems/automation/lib/automation-formatters.test.ts
  • web/src/systems/automation/lib/automation-formatters.ts
  • web/src/systems/bridges/adapters/bridges-api.test.ts
  • web/src/systems/bridges/adapters/bridges-api.ts
  • web/src/systems/bridges/components/bridge-create-dialog.test.tsx
  • web/src/systems/bridges/components/bridge-create-dialog.tsx
  • web/src/systems/bridges/components/bridge-detail-panel.tsx
  • web/src/systems/bridges/components/bridge-empty-state.tsx
  • web/src/systems/bridges/components/bridge-list-panel.tsx
  • web/src/systems/bridges/components/bridge-provider-card.tsx
  • web/src/systems/bridges/components/bridge-test-delivery-dialog.tsx
  • web/src/systems/bridges/hooks/use-bridge-actions.test.tsx
  • web/src/systems/bridges/hooks/use-bridge-actions.ts
  • web/src/systems/bridges/hooks/use-bridges.test.tsx
  • web/src/systems/bridges/hooks/use-bridges.ts
  • web/src/systems/bridges/index.ts
  • web/src/systems/bridges/lib/bridge-drafts.ts
  • web/src/systems/bridges/lib/bridge-formatters.ts
  • web/src/systems/bridges/lib/query-keys.test.ts
  • web/src/systems/bridges/lib/query-keys.ts
  • web/src/systems/bridges/lib/query-options.test.ts
  • web/src/systems/bridges/lib/query-options.ts
  • web/src/systems/bridges/types.ts
  • web/src/systems/network/adapters/network-api.ts
  • web/src/systems/network/components/network-channel-detail-panel.tsx
  • web/src/systems/network/components/network-channels-list-panel.tsx
  • web/src/systems/network/components/network-create-channel-dialog.tsx
  • web/src/systems/network/components/network-empty-state.tsx
  • web/src/systems/network/components/network-peer-detail-panel.tsx
  • web/src/systems/network/components/network-peers-list-panel.tsx
  • web/src/systems/network/hooks/use-network-actions.ts
  • web/src/systems/network/hooks/use-network.ts
  • web/src/systems/network/index.ts
  • web/src/systems/network/lib/network-formatters.ts
  • web/src/systems/network/lib/query-keys.ts
  • web/src/systems/network/lib/query-options.ts
  • web/src/systems/network/types.ts
  • web/src/systems/session/components/message-bubble.tsx
  • web/src/systems/workspace/adapters/workspace-api.test.ts
  • web/src/systems/workspace/adapters/workspace-api.ts
  • web/src/systems/workspace/hooks/use-workspaces.test.tsx
  • web/src/systems/workspace/hooks/use-workspaces.ts
  • web/src/systems/workspace/index.ts
  • web/src/systems/workspace/lib/query-keys.ts
  • web/src/systems/workspace/lib/query-options.ts

Walkthrough

Adds bridge provider discovery/listing and last-success telemetry; implements a persisted network subsystem (channels, peers, messages) with DB schema, store APIs, new HTTP/UDS routes and handlers, core interfaces and handler wiring, web UI/hook surfaces for Bridges and Network, message/audit timeline persistence, manifest bridge metadata, and extensive tests.

Changes

Cohort / File(s) Summary
API Contracts & Responses
internal/api/contract/bridges.go, internal/api/contract/contract.go, internal/api/contract/responses.go
Added BridgeProvidersResponse and provider-shaped DTOs; extended BridgeHealthPayload with last_success_at; added network DTOs for channels/peers/messages/metrics and new response wrapper types.
Core Handlers & Interfaces
internal/api/core/bridges.go, internal/api/core/interfaces.go, internal/api/core/handlers.go, internal/api/core/network.go, internal/api/core/network_details.go
Added ListBridgeProviders handler and BridgeService.ListProviders; introduced NetworkStore interface and threaded it through BaseHandlers; implemented network endpoints (peers/channels/messages/peer detail/create channel) and session-enrichment/helpers.
Conversions & Observability
internal/api/core/conversions.go, internal/observe/bridges.go
Populated last_success_at in Bridge health conversion and observation from delivery metrics.
Audit / Message Persistence & Manager
internal/network/audit.go, internal/network/manager.go, internal/network/audit_test.go
Added delivered audit direction and RecordDelivered; introduced MessageStore and timeline normalization to persist network messages alongside audit entries.
Store / DB schema & implementation
internal/store/store.go, internal/store/types.go, internal/store/globaldb/global_db.go, internal/store/globaldb/global_db_network_messages.go
Added NetworkMessageStore interface, NetworkMessageEntry/NetworkMessageQuery types, created network_message_log table and indexes, and implemented WriteNetworkMessage / ListNetworkMessages with tests.
Daemon / Bridge runtime & metrics
internal/bridges/types.go, internal/bridges/delivery_metrics.go, internal/bridges/delivery_broker.go, internal/daemon/bridges.go
Added BridgeProvider type and extension-registry discovery; recorded/exposed per-instance lastSuccessAt delivery metric; implemented bridgeRuntime.ListProviders.
Server wiring & routes
internal/api/httpapi/routes.go, internal/api/udsapi/routes.go, internal/api/httpapi/server.go, internal/api/udsapi/server.go, internal/api/httpapi/handlers.go
Registered /api/bridges/providers and network routes (/api/network/...); added WithNetworkStore option and passed networkStore into handler construction.
Web — Bridges frontend
web/src/systems/bridges/*, web/src/routeTree.gen.ts, web/src/components/app-sidebar.tsx
New Bridges frontend modules: adapters, hooks, types, formatters, query keys/options, UI components (list/detail/provider/create/test), route integration and tests.
Web — Network frontend
web/src/systems/network/*, web/src/routeTree.gen.ts, web/src/components/app-sidebar.tsx
New Network frontend modules: adapters, hooks, types, formatters, query keys/options, UI components (channels/peers lists, detail panels, create dialog, empty states), route integration and tests.
Tests & Test Utilities
internal/api/core/bridges_test.go, internal/api/testutil/apitest.go, internal/api/httpapi/bridges_test.go, internal/api/udsapi/bridges_test.go, internal/store/globaldb/global_db_network_messages_test.go, assorted web tests
Extensive unit/integration tests added or extended for bridge providers, network endpoints, audit/message persistence, daemon registry, and web UI; added StubNetworkStore and extended StubBridgeService.
Extension manifest & helpers
internal/extension/manifest.go, internal/extension/manifest_test.go, internal/daemon/extensions.go
Added [bridge] manifest section (platform/display_name) with conditional validation for bridge-capable extensions; refactored manifest/snapshot loading helpers.
Misc UI & infra tweaks
assorted web and server files (automation, session message rendering, workspace API/hooks)
Various UI refactors and small infra/test wiring adjustments (e.g., remove lazy MessageMarkdown import, automation editor/dialog refactors, workspace fetch/detail additions).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API_Router as API Router
    participant Handlers as BaseHandlers
    participant Runtime as Runtime (Sessions/Peers)
    participant Store as NetworkStore / GlobalDB
    participant Audit as AuditWriter

    Client->>API_Router: HTTP GET/POST /api/network/... or /api/bridges/providers
    API_Router->>Handlers: invoke handler (NetworkChannels/CreateNetworkChannel/ListBridgeProviders/...)
    Handlers->>Runtime: query sessions/peers or create sessions
    Runtime-->>Handlers: session/peer info
    Handlers->>Store: ListNetworkMessages / WriteNetworkMessage (persist/read)
    Store-->>Handlers: persisted messages / query results
    Handlers->>Audit: RecordSent / RecordDelivered (emit audit + timeline)
    Audit->>Store: WriteNetworkMessage (timeline persistence path)
    Handlers-->>API_Router: JSON response (200/201 or error)
    API_Router-->>Client: HTTP response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/src/routes/_app/-automation.integration.test.tsx (1)

314-342: ⚠️ Potential issue | 🟡 Minor

Wrap all post-mutation assertions in waitFor() to prevent flaky tests.

Both handleSubmitJob and handleTriggerNow properly await mutateAsync() before calling side effects. However, the test assertions race those completions—user.click() returns when the event is processed, not when the async handler finishes. The create job test leaves the toast assertion outside waitFor(), and the trigger now test has no waitFor() at all.

💡 Suggested fix
     await user.click(screen.getByTestId("submit-job-form"));

     await waitFor(() => {
       expect(mockCreateJobMutateAsync).toHaveBeenCalledWith(
         expect.objectContaining({
           agent_name: "writer",
           name: "nightly-docs",
           scope: "workspace",
           workspace_id: "ws_test",
         })
       );
+      expect(toast.success).toHaveBeenCalledWith("Created job nightly-docs.");
     });
-
-    expect(toast.success).toHaveBeenCalledWith("Created job nightly-docs.");

     await user.click(screen.getByTestId("trigger-job-btn"));

-    expect(mockTriggerJobMutateAsync).toHaveBeenCalledWith({ id: "job_daily_review" });
-    expect(toast.success).toHaveBeenCalledWith("Queued run run_queued.");
-    expect(screen.getByTestId("automation-run-run_queued")).toBeInTheDocument();
+    await waitFor(() => {
+      expect(mockTriggerJobMutateAsync).toHaveBeenCalledWith({ id: "job_daily_review" });
+      expect(toast.success).toHaveBeenCalledWith("Queued run run_queued.");
+      expect(screen.getByTestId("automation-run-run_queued")).toBeInTheDocument();
+    });

Also applies to: 373-381

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/routes/_app/-automation.integration.test.tsx` around lines 314 - 342,
The tests are asserting side-effects before the async mutate handlers finish;
wrap all post-mutation assertions in waitFor to avoid flakes: in the create-job
test ensure the toast.success assertion is moved inside a waitFor that also
checks mockCreateJobMutateAsync was called (referencing mockCreateJobMutateAsync
and toast.success), and in the trigger-now test wrap its assertions similarly
(referencing handleTriggerNow/mutateAsync and any mockTriggerMutateAsync/toast
calls) so both the mutation and subsequent side-effect assertions wait for
completion.
🟡 Minor comments (24)
web/src/systems/session/components/message-bubble.tsx-5-5 (1)

5-5: ⚠️ Potential issue | 🟡 Minor

Use path alias import for MessageMarkdown.

Line 5 uses a relative import; this should use the @/* alias convention for web imports.

Suggested change
-import { MessageMarkdown } from "./message-markdown";
+import { MessageMarkdown } from "@/systems/session/components/message-markdown";

As per coding guidelines, "Use path alias @/* to map to ./src/* for all imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/session/components/message-bubble.tsx` at line 5, The import
in message-bubble.tsx currently uses a relative path for MessageMarkdown; update
the import to use the project path-alias (e.g., import MessageMarkdown from
"@/systems/session/components/message-markdown") so it follows the `@/`* → ./src/*
convention and keeps consistency with other web imports; ensure the imported
symbol name MessageMarkdown remains unchanged.
web/src/systems/bridges/components/bridge-provider-card.tsx-4-10 (1)

4-10: ⚠️ Potential issue | 🟡 Minor

Convert these relative imports to @/ aliases.

Use the project alias consistently for imports under web/src.
As per coding guidelines, "Use path alias @/* to map to ./src/* for all imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/components/bridge-provider-card.tsx` around lines 4 -
10, Replace the relative imports in bridge-provider-card.tsx with the project
path alias by changing imports that reference "../lib/bridge-formatters" and
"../types" to use "@/systems/bridges/lib/bridge-formatters" and
"@/systems/bridges/types" respectively; ensure the imported symbols
bridgeProviderHealthTone, bridgeProviderStateTone, buildBridgeProviderKey,
isBridgeProviderSelectable and the BridgeProvider type are preserved exactly and
update any other similar relative imports in this file to use the `@/` alias
consistently.
web/src/systems/bridges/components/bridge-list-panel.tsx-7-13 (1)

7-13: ⚠️ Potential issue | 🟡 Minor

Use @/ alias imports for local modules.

Please switch these relative imports to alias-based imports for consistency with project rules.
As per coding guidelines, "Use path alias @/* to map to ./src/* for all imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/components/bridge-list-panel.tsx` around lines 7 -
13, Update the relative imports in bridge-list-panel.tsx to use the project path
alias: replace the import of bridgeScopeTone, bridgeStatusTone,
formatBridgeRelativeTime from "../lib/bridge-formatters" with
"@/lib/bridge-formatters" and replace the type import of BridgeHealthMap and
BridgeSummary from "../types" with "@/systems/bridges/types" (or the correct
aliased path that maps to the original types location) so the component uses the
`@/` alias for local modules consistently.
web/src/systems/bridges/components/bridge-test-delivery-dialog.tsx-23-25 (1)

23-25: ⚠️ Potential issue | 🟡 Minor

Switch local imports to the @/ alias.

Please replace these relative imports with alias-based imports to match project conventions.
As per coding guidelines, "Use path alias @/* to map to ./src/* for all imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/components/bridge-test-delivery-dialog.tsx` around
lines 23 - 25, Update the two local imports to use the project path alias `@/`
instead of relative paths: replace the import of bridgeProviderStateTone and
describeBridgeTestTarget from "../lib/bridge-formatters" with the alias import
from "@/systems/bridges/lib/bridge-formatters", and replace the types
BridgeTestDeliveryDraft and TestBridgeDeliveryResponse imported from "../types"
with "@/systems/bridges/types" (or the correct alias target matching those
symbols) so they follow the project's `@/*` mapping; ensure the imported symbol
names remain unchanged.
web/src/systems/bridges/components/bridge-empty-state.tsx-13-16 (1)

13-16: ⚠️ Potential issue | 🟡 Minor

Replace relative imports with @/ aliases.

Please align these imports with the project-wide alias rule.
As per coding guidelines, "Use path alias @/* to map to ./src/* for all imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/components/bridge-empty-state.tsx` around lines 13 -
16, The imports in bridge-empty-state.tsx use relative paths; update them to the
project alias form by replacing the relative import paths with "@/..."
equivalents — specifically change imports referencing
isBridgeProviderSelectable, the BridgeProvider type, and BridgeProviderCard to
use the "@/..." alias (e.g., import { isBridgeProviderSelectable } from
"@/systems/bridges/lib/bridge-formatters"; import type { BridgeProvider } from
"@/systems/bridges/types"; import { BridgeProviderCard } from
"@/systems/bridges/components/bridge-provider-card") so they follow the
project's path-alias rule.
web/src/systems/bridges/lib/bridge-formatters.ts-11-11 (1)

11-11: ⚠️ Potential issue | 🟡 Minor

Avoid returning a shared mutable defaults object.

Returning a module-level {} can cause accidental cross-call state leakage if any consumer mutates the returned value.

Proposed fix
-const EMPTY_DELIVERY_DEFAULTS: BridgeDeliveryDefaults = {};
-
 export function normalizeBridgeDeliveryDefaults(value: unknown): BridgeDeliveryDefaults {
   if (!value || typeof value !== "object" || Array.isArray(value)) {
-    return EMPTY_DELIVERY_DEFAULTS;
+    return {};
   }

Also applies to: 87-90

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/lib/bridge-formatters.ts` at line 11, The
module-level EMPTY_DELIVERY_DEFAULTS constant exposes a shared mutable object
(BridgeDeliveryDefaults) that can leak state across callers; replace returns of
EMPTY_DELIVERY_DEFAULTS with a fresh empty object each time (e.g., return {} as
BridgeDeliveryDefaults or use a factory like createEmptyDeliveryDefaults()), and
apply the same change for the other defaults referenced around lines 87-90
(ensure any constants there are returned by value, not by reference, or replaced
with small factory functions) so callers receive isolated objects instead of a
shared mutable instance.
web/src/systems/bridges/lib/bridge-formatters.ts-120-124 (1)

120-124: ⚠️ Potential issue | 🟡 Minor

Extract this inline object shape into an interface.

Defining the routing-policy object shape inline makes reuse harder and breaks the project TypeScript shape convention.
As per coding guidelines, "web/**/*.ts?(x): Use interface for defining object shapes in TypeScript (pattern is in Zod schemas and types)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/lib/bridge-formatters.ts` around lines 120 - 124,
Extract the inline object shape used in describeBridgeRoutingPolicy into a named
exported interface (e.g., BridgeRoutingPolicy) and replace the inline type
annotation in the function signature with that interface; update the function
signature export function describeBridgeRoutingPolicy(policy:
BridgeRoutingPolicy): string and export the new interface so it can be reused
elsewhere and conform to the project's TypeScript shape convention.
web/src/systems/bridges/lib/bridge-formatters.ts-1-7 (1)

1-7: ⚠️ Potential issue | 🟡 Minor

Use @/ alias imports instead of relative paths.

Please replace relative imports here with the project alias to keep module boundaries consistent.
As per coding guidelines, "Use path alias @/* to map to ./src/* for all imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/lib/bridge-formatters.ts` around lines 1 - 7, The
import of types (BridgeDeliveryDefaults, BridgeProvider, BridgeRoute,
BridgeScope, BridgeStatus) uses a relative path; update the import source to use
the project path alias (e.g. replace the relative "../types" with
"@/systems/bridges/types") so the import reads from the "@/..." alias and keeps
module boundaries consistent while retaining the same imported symbols.
web/src/systems/bridges/components/bridge-test-delivery-dialog.tsx-56-59 (1)

56-59: ⚠️ Potential issue | 🟡 Minor

Guard against duplicate submit while pending.

The form handler should no-op when isPending to prevent repeated submission from keyboard/programmatic form submit paths.

Proposed fix
           onSubmit={event => {
             event.preventDefault();
+            if (isPending) {
+              return;
+            }
             onSubmit();
           }}

Also applies to: 216-216

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/components/bridge-test-delivery-dialog.tsx` around
lines 56 - 59, Guard the form submit handlers against duplicate submits by
checking the isPending flag and returning early; update the inline onSubmit
handler (the event => { event.preventDefault(); onSubmit(); } callback) to first
if (isPending) { event.preventDefault(); return; } then proceed to call
onSubmit(), and apply the same change to the other identical form submit handler
in this file (the second onSubmit occurrence).
web/src/systems/bridges/components/bridge-list-panel.tsx-24-34 (1)

24-34: ⚠️ Potential issue | 🟡 Minor

Move inline props object shape to an interface.

This props shape should be declared as an interface and reused, rather than typed inline in the function signature.
As per coding guidelines, "web/**/*.ts?(x): Use interface for defining object shapes in TypeScript (pattern is in Zod schemas and types)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/components/bridge-list-panel.tsx` around lines 24 -
34, Declare a named interface (e.g., BridgeListItemProps) describing the props
shape used by BridgeListItem with fields bridge: BridgeSummary; health?:
BridgeHealthMap[string]; isSelected: boolean; onSelect: () => void; then update
the BridgeListItem function signature to accept (props: BridgeListItemProps) or
destructure with ({ bridge, health, isSelected, onSelect }: BridgeListItemProps)
instead of the inline type; keep the interface adjacent to the component so it
can be reused elsewhere.
web/src/systems/bridges/lib/bridge-drafts.ts-1-13 (1)

1-13: ⚠️ Potential issue | 🟡 Minor

Use @/ aliases for these imports.

Please switch relative imports in this module to the configured path alias.
As per coding guidelines, "Use path alias @/* to map to ./src/* for all imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/lib/bridge-drafts.ts` around lines 1 - 13, Replace
the relative imports with the project path alias: change the import of
buildBridgeProviderKey, isBridgeProviderSelectable,
normalizeBridgeDeliveryDefaults (currently imported from "./bridge-formatters")
and the types BridgeCreateDraft, BridgeProvider, BridgeSummary,
BridgeTestDeliveryDraft (currently from "../types") to use the configured
"@/..." alias form per the coding guidelines so the same modules are imported
via the alias instead of relative paths.
web/src/systems/bridges/lib/bridge-formatters.ts-190-205 (1)

190-205: ⚠️ Potential issue | 🟡 Minor

Relative-time boundaries are rounded the wrong way.

Using Math.round can overstate elapsed/remaining time near boundaries (e.g., ~30s becomes 1m). Use floor-based bucketing for stable labels.

Proposed fix
-  const diffMinutes = Math.round(Math.abs(diffMs) / (1000 * 60));
+  const diffMinutes = Math.floor(Math.abs(diffMs) / (1000 * 60));
@@
-  const diffHours = Math.round(diffMinutes / 60);
+  const diffHours = Math.floor(diffMinutes / 60);
@@
-  const diffDays = Math.round(diffHours / 24);
+  const diffDays = Math.floor(diffHours / 24);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/lib/bridge-formatters.ts` around lines 190 - 205, The
relative-time labels overstate near boundaries because
diffMinutes/diffHours/diffDays use Math.round; change to floor-based bucketing:
compute diffMinutes as Math.floor(Math.abs(diffMs) / (1000 * 60)) and treat
"Just now" when Math.abs(diffMs) < 1000 * 60, then use diffMinutes for the
minute branch, compute diffHours = Math.floor(diffMinutes / 60) and diffDays =
Math.floor(diffHours / 24), and keep the existing sign checks (diffMs >= 0) when
returning `In ...` vs `... ago` for the symbols diffMs, diffMinutes, diffHours,
diffDays in this function.
internal/api/httpapi/httpapi_integration_test.go-1017-1019 (1)

1017-1019: ⚠️ Potential issue | 🟡 Minor

Return an empty providers list instead of nil.

nil here can surface as "providers": null in API responses, while list endpoints should stay shape-stable as arrays. Prefer returning an empty slice.

Proposed fix
 func (s *integrationBridgeService) ListProviders(context.Context) ([]bridgepkg.BridgeProvider, error) {
-	return nil, nil
+	return []bridgepkg.BridgeProvider{}, nil
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/httpapi/httpapi_integration_test.go` around lines 1017 - 1019,
The ListProviders method currently returns nil for the providers slice causing
JSON "providers": null; update the function
(integrationBridgeService.ListProviders) to return an empty slice instead of
nil, e.g. return []bridgepkg.BridgeProvider{}, nil (or initialize a zero-length
slice variable and return it) so API responses remain shape-stable arrays.
web/src/systems/network/hooks/use-network-actions.ts-5-7 (1)

5-7: ⚠️ Potential issue | 🟡 Minor

Use @/* aliases instead of relative imports.

These imports violate the web import-path convention and can fail consistency checks.

Suggested fix
-import { createNetworkChannel } from "../adapters/network-api";
-import { networkKeys } from "../lib/query-keys";
-import type { CreateNetworkChannelRequest } from "../types";
+import { createNetworkChannel } from "@/systems/network/adapters/network-api";
+import { networkKeys } from "@/systems/network/lib/query-keys";
+import type { CreateNetworkChannelRequest } from "@/systems/network/types";

As per coding guidelines, "Use path alias @/* to map to ./src/* for all imports."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/network/hooks/use-network-actions.ts` around lines 5 - 7,
Replace the relative imports in use-network-actions.ts with path-alias imports
rooted at `@/src`: change imports referencing "../adapters/network-api",
"../lib/query-keys", and "../types" to use the corresponding alias paths (e.g.,
"@/systems/network/adapters/network-api", "@/systems/network/lib/query-keys",
"@/systems/network/types") so that createNetworkChannel, networkKeys, and
CreateNetworkChannelRequest are imported via the `@/`* mapping to ./src/*.
web/src/systems/bridges/lib/query-options.test.ts-8-8 (1)

8-8: ⚠️ Potential issue | 🟡 Minor

Switch this import to the project alias path.

Using a relative import here breaks the enforced web import convention.

Suggested fix
-import {
-  bridgeDetailOptions,
-  bridgeProvidersOptions,
-  bridgeRoutesOptions,
-  bridgesListOptions,
-} from "./query-options";
+import {
+  bridgeDetailOptions,
+  bridgeProvidersOptions,
+  bridgeRoutesOptions,
+  bridgesListOptions,
+} from "@/systems/bridges/lib/query-options";

As per coding guidelines, "Use path alias @/* to map to ./src/* for all imports."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/lib/query-options.test.ts` at line 8, Replace the
relative import of "./query-options" in the test file with the project
path-alias import that starts with "@/". Locate the import statement that
references "./query-options" and change it to the corresponding alias path
(e.g., "@/systems/bridges/lib/query-options") so it follows the enforced web
import convention and resolves from src via the `@/`* mapping; keep the imported
symbol names unchanged.
internal/api/core/network.go-259-267 (1)

259-267: ⚠️ Potential issue | 🟡 Minor

Keep the peer-id fallback when display_name is blank.

A non-nil PeerCard.DisplayName containing only whitespace now produces an empty DisplayName instead of falling back to peer.PeerID.

💡 Suggested fix
  displayName := peer.PeerID
  if peer.PeerCard.DisplayName != nil {
-   displayName = strings.TrimSpace(*peer.PeerCard.DisplayName)
+   if trimmed := strings.TrimSpace(*peer.PeerCard.DisplayName); trimmed != "" {
+     displayName = trimmed
+   }
  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/core/network.go` around lines 259 - 267, The current code trims
PeerCard.DisplayName but unconditionally assigns that possibly-empty string to
displayName; update the logic in the function that builds NetworkPeerPayload
(the displayName variable assignment using peer.PeerCard.DisplayName) so that
after calling strings.TrimSpace(*peer.PeerCard.DisplayName) you only use the
trimmed value when it is non-empty, otherwise keep the fallback of peer.PeerID;
ensure the condition references peer.PeerCard.DisplayName and the trimmed result
before assigning DisplayName in the returned contract.NetworkPeerPayload.
web/src/systems/automation/components/automation-job-form.tsx-357-360 (1)

357-360: ⚠️ Potential issue | 🟡 Minor

Make the enabled label mode-aware.

Enabled on create is accurate for new jobs, but misleading in edit mode where the checkbox is toggling the job's current state. A conditional label like mode === "create" ? "Enabled on create" : "Enabled" would avoid that mismatch.

💡 Suggested fix
           <AutomationCheckbox
             checked={draft.enabled ?? true}
             description="Disabled jobs stay visible but never dispatch on their schedule."
-            label="Enabled on create"
+            label={mode === "create" ? "Enabled on create" : "Enabled"}
             onCheckedChange={checked => onChange({ ...draft, enabled: checked })}
           />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/automation/components/automation-job-form.tsx` around lines
357 - 360, Update the AutomationCheckbox label to be mode-aware: when the
component is in create mode show "Enabled on create" and in edit mode show
"Enabled". Locate the AutomationCheckbox usage (the one using draft.enabled) in
automation-job-form.tsx and change the label to choose between "Enabled on
create" and "Enabled" based on the component's mode prop/state (e.g., mode ===
"create" ? "Enabled on create" : "Enabled"), keeping the rest of the props
(checked={draft.enabled ?? true}, description) unchanged.
internal/store/globaldb/global_db_network_messages.go-17-18 (1)

17-18: ⚠️ Potential issue | 🟡 Minor

Wrap the validation failures with store-specific context.

Both paths return raw Validate() errors, which makes upstream failures harder to attribute once they bubble out of the store layer. Wrapping still preserves errors.Is/errors.As.

Proposed fix
 	if err := entry.Validate(); err != nil {
-		return err
+		return fmt.Errorf("store: validate network message entry: %w", err)
 	}
@@
 	if err := query.Validate(); err != nil {
-		return nil, err
+		return nil, fmt.Errorf("store: validate network message query: %w", err)
 	}

As per coding guidelines, **/*.go: Use explicit error returns with wrapped context: fmt.Errorf("context: %w", err).

Also applies to: 50-51

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/store/globaldb/global_db_network_messages.go` around lines 17 - 18,
The raw returns of entry.Validate() should be wrapped with store-specific
context; replace both plain "if err := entry.Validate(); err != nil { return err
}" occurrences with code that wraps the error using fmt.Errorf, e.g. "if err :=
entry.Validate(); err != nil { return fmt.Errorf(\"global store: validate
network entry: %w\", err) }" (and add fmt to imports if missing) so upstream
callers get contextualized errors while preserving error unwrapping.
internal/store/globaldb/global_db_network_messages.go-70-72 (1)

70-72: ⚠️ Potential issue | 🟡 Minor

Don't discard rows.Close() errors.

This introduces an _-ignored error in a new store path. If the close is intentionally best-effort, please document that; otherwise propagate it.

As per coding guidelines, **/*.go: Never ignore errors with _ — every error must be handled or have a written justification.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/store/globaldb/global_db_network_messages.go` around lines 70 - 72,
The defer currently swallows the error from rows.Close() (defer func() { _ =
rows.Close() }()), which violates the rule to never ignore errors; update the
defer to capture and handle the error (e.g., assign err := rows.Close() and
either log it with the package logger or propagate it by setting a named return
error or wrapping it before returning) instead of discarding it, or add an
explicit comment explaining why a best-effort close is acceptable; target the
rows.Close() call in the same function in global_db_network_messages.go and
ensure the chosen handling follows project logging/propagation conventions.
internal/api/core/network_test.go-1013-1023 (1)

1013-1023: ⚠️ Potential issue | 🟡 Minor

Assert the created agent names explicitly.

Right now this only proves that two sessions were created for the right workspace/channel. It would still pass if the handler created the wrong two agents.

Suggested assertion tightening
  if got, want := len(createCalls), 2; got != want {
  	t.Fatalf("len(createCalls) = %d, want %d", got, want)
  }
+ expectedAgents := map[string]struct{}{
+ 	"coder":    {},
+ 	"reviewer": {},
+ }
  for _, call := range createCalls {
+ 	if _, ok := expectedAgents[call.AgentName]; !ok {
+ 		t.Fatalf("Create() agent = %q, want coder/reviewer", call.AgentName)
+ 	}
+ 	delete(expectedAgents, call.AgentName)
  	if got, want := call.Workspace, "ws-1"; got != want {
  		t.Fatalf("Create() workspace = %q, want %q", got, want)
  	}
  	if got, want := call.Channel, "builders"; got != want {
  		t.Fatalf("Create() channel = %q, want %q", got, want)
  	}
  }
+ if len(expectedAgents) != 0 {
+ 	t.Fatalf("missing Create() calls for agents: %#v", expectedAgents)
+ }

As per coding guidelines, **/*_test.go: MUST test meaningful business logic, not trivial operations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/core/network_test.go` around lines 1013 - 1023, The test
currently verifies createCalls length and Workspace/Channel but not which agents
were created; update the loop over createCalls to also assert the agent name for
each call (e.g., check call.AgentName or call.Agent) against the expected agent
names list (two specific names), using t.Fatalf on mismatch so the test fails if
the wrong agents were created while retaining the existing Workspace/Channel
assertions for Create().
internal/network/audit.go-193-201 (1)

193-201: ⚠️ Potential issue | 🟡 Minor

Preserve the original message text in the timeline.

strings.TrimSpace(sayBody.Text) strips leading/trailing whitespace and terminal newlines, so the stored transcript can differ from what was actually sent. That becomes user-visible in the read-only channel timeline.

Suggested fix
-		Text:      strings.TrimSpace(sayBody.Text),
+		Text:      sayBody.Text,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/network/audit.go` around lines 193 - 201, The stored timeline
currently calls strings.TrimSpace(sayBody.Text) when building the
store.NetworkMessageEntry, which strips the original leading/trailing whitespace
and newlines; change the Text field to store the raw message by assigning
sayBody.Text directly (keep trimming for other fields like
MessageID/SessionID/Channel/PeerFrom/Kind/Intent if desired) so the
NetworkMessageEntry.Text preserves the exact original content sent.
web/src/systems/automation/lib/automation-formatters.ts-346-358 (1)

346-358: ⚠️ Potential issue | 🟡 Minor

Scope summaries should use the filtered count.

The "global" and "workspace" branches ignore visibleCount and report totalCount instead. If totalCount is the full collection size, the summary overstates scoped views as soon as a scope filter is applied.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/automation/lib/automation-formatters.ts` around lines 346 -
358, The summary currently uses totalCount for scoped summaries causing
overstatement; update the branches in the formatter (look for scopeFilter,
visibleCount, totalCount, totalNoun, activeWorkspaceName) so that the "global"
branch and the workspace branch(s) return strings using visibleCount instead of
totalCount (keep the "all" branch using totalCount); ensure the template
literals for `${...} ${totalNoun}` use visibleCount where a scope filter is
applied and preserve the activeWorkspaceName interpolation for the workspace
message.
web/src/systems/automation/components/automation-detail-panel.tsx-159-166 (1)

159-166: ⚠️ Potential issue | 🟡 Minor

Manual jobs render as cron jobs here.

When job.schedule is absent, this falls back to "cron" and shows "Cron schedule", while describeSchedule(job.schedule) returns "Manual". Unscheduled jobs will look scheduled.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/automation/components/automation-detail-panel.tsx` around
lines 159 - 166, The code defaults mode to "cron" when job.schedule is missing,
causing unscheduled jobs to display as cron; update the logic so mode is
computed from job.schedule presence (e.g., mode = job.schedule ?
job.schedule.mode ?? "cron" : "manual"), adjust ScheduleIcon to handle a
"manual" case, and make scheduleValue return a "Manual" label (or use
describeSchedule(job.schedule)) when job.schedule is undefined so unscheduled
jobs render correctly. Ensure you update references to mode, ScheduleIcon, and
scheduleValue accordingly.
web/src/systems/network/lib/network-formatters.ts-189-203 (1)

189-203: ⚠️ Potential issue | 🟡 Minor

Guard invalid timestamps in sort comparators to avoid NaN ordering behavior.

Both sortNetworkChannels and sortNetworkPeers parse timestamps without validating the result. If a malformed string reaches these functions, new Date(malformed).getTime() returns NaN, breaking sort determinism when used in comparisons. This pattern is already handled correctly in getPeerPresenceTone (line 141) which checks Number.isNaN(parsed.getTime()).

Extract timestamp parsing into a helper function that returns 0 for both missing and invalid timestamps:

Proposed fix
+function parseTimestampOrZero(value?: string | null): number {
+  if (!value) {
+    return 0;
+  }
+  const parsed = new Date(value).getTime();
+  return Number.isNaN(parsed) ? 0 : parsed;
+}
+
 export function sortNetworkChannels(channels: NetworkChannelSummary[]) {
   return [...channels].sort((left, right) => {
-    const leftMessageTime = left.last_message_at ? new Date(left.last_message_at).getTime() : 0;
-    const rightMessageTime = right.last_message_at ? new Date(right.last_message_at).getTime() : 0;
+    const leftMessageTime = parseTimestampOrZero(left.last_message_at);
+    const rightMessageTime = parseTimestampOrZero(right.last_message_at);

Apply the same fix to sortNetworkPeers (lines 215–230) for last_seen.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/network/lib/network-formatters.ts` around lines 189 - 203,
The sort comparators use new Date(...).getTime() without validating and can
produce NaN; add a small helper (e.g., safeTimestampMillis or
parseTimestampToMillis) that accepts a string | undefined, returns 0 for
undefined or invalid dates (use Number.isNaN(parsed.getTime()) to detect), and
replace the direct new Date(...).getTime() calls inside sortNetworkChannels
(left.last_message_at/right.last_message_at) and sortNetworkPeers
(left.last_seen/right.last_seen) to use this helper so sorting remains
deterministic for malformed timestamps.
🧹 Nitpick comments (17)
web/src/systems/workspace/adapters/workspace-api.ts (1)

30-32: Consider using a typed error class for consistency with other adapters.

Per coding guidelines, API adapters should use typed error classes (e.g., WorkspaceApiError) rather than raw Error. While this follows the existing pattern in the file, newer adapters like bridges-api.ts use BridgesApiError which allows consumers to inspect status for error handling.

This is a pre-existing pattern, so deferring to a follow-up refactor is reasonable.

As per coding guidelines: "Use typed error classes in API adapters — never throw raw errors"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/workspace/adapters/workspace-api.ts` around lines 30 - 32,
Replace the raw throw new Error(...) with throwing the typed WorkspaceApiError:
when apiRequestFailed(response, error) is true, construct and throw new
WorkspaceApiError(...) using the same message from
defaultApiErrorMessage("Failed to fetch workspace", response, error) and include
the HTTP status (from response.status) and original error details so callers can
inspect .status; update the throw site in workspace-api.ts to use
WorkspaceApiError instead of Error and ensure WorkspaceApiError is
imported/available.
internal/cli/cli_integration_test.go (1)

1170-1172: Prefer returning an empty provider slice from the test stub.

Using an empty slice keeps list responses array-shaped in integration flows.

Suggested change
 func (s *integrationBridgeService) ListProviders(context.Context) ([]bridgepkg.BridgeProvider, error) {
-	return nil, nil
+	return []bridgepkg.BridgeProvider{}, nil
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cli/cli_integration_test.go` around lines 1170 - 1172, The test stub
integrationBridgeService.ListProviders currently returns (nil, nil) which yields
a null in list responses; change it to return an empty slice and nil error by
returning []bridgepkg.BridgeProvider{} , nil so callers receive an empty array
instead of null—update the ListProviders method on integrationBridgeService
accordingly.
internal/api/core/bridges.go (1)

38-52: Prefer StatusForBridgeError(err) for consistency.

This handler currently hard-codes 500 for provider listing failures; using StatusForBridgeError(err) would keep bridge error mapping consistent across endpoints.

Proposed tweak
 	providers, err := bridges.ListProviders(c.Request.Context())
 	if err != nil {
-		h.respondError(c, http.StatusInternalServerError, err)
+		h.respondError(c, StatusForBridgeError(err), err)
 		return
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/core/bridges.go` around lines 38 - 52, In ListBridgeProviders,
replace the hard-coded http.StatusInternalServerError path when
bridges.ListProviders returns an error by calling StatusForBridgeError(err) and
passing that status into h.respondError so bridge errors are mapped
consistently; locate the ListBridgeProviders method, the bridges.ListProviders
call, and the h.respondError invocation and swap the fixed 500 status for
StatusForBridgeError(err).
web/src/systems/workspace/adapters/workspace-api.test.ts (1)

53-64: Add abort-signal coverage for fetchWorkspace as well.

The new test covers the success path, but it doesn’t validate signal propagation to fetch, which is part of your list-query test contract.

✅ Suggested test addition
 describe("fetchWorkspace", () => {
   it("loads the resolved workspace detail payload", async () => {
     mockJsonResponse(mockWorkspaceDetail);

     const result = await fetchWorkspace("ws_alpha");

     expect(result).toEqual(mockWorkspaceDetail);
     await expectFetchRequest({
       path: "/api/workspaces/ws_alpha",
     });
   });
+
+  it("passes an abort signal to fetch", async () => {
+    mockJsonResponse(mockWorkspaceDetail);
+
+    const controller = new AbortController();
+    await fetchWorkspace("ws_alpha", controller.signal);
+
+    await expectFetchRequest({
+      path: "/api/workspaces/ws_alpha",
+      signal: controller.signal,
+    });
+  });
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/workspace/adapters/workspace-api.test.ts` around lines 53 -
64, Add a test that verifies abort-signal propagation for fetchWorkspace by
calling fetchWorkspace("ws_alpha", { signal }) with an AbortController.signal
(or similar) and asserting the underlying fetch received that signal; reuse
mockJsonResponse(mockWorkspaceDetail) and the existing expectFetchRequest helper
to assert path "/api/workspaces/ws_alpha" and that the request options include
the provided signal (or that fetch was called with the same signal). Ensure the
new test mirrors the success test structure but passes an AbortController.signal
and checks signal propagation to fetchWorkspace.
web/src/systems/workspace/hooks/use-workspaces.ts (2)

12-16: Extract hook options into an interface.

Please replace the inline object-shape type with a named interface for consistency.

Proposed type shape refactor
+interface UseWorkspaceOptions {
+  enabled?: boolean;
+}
+
-export function useWorkspace(workspaceID: string, options?: { enabled?: boolean }) {
+export function useWorkspace(workspaceID: string, options?: UseWorkspaceOptions) {

As per coding guidelines, web/**/*.ts?(x): "Use interface for defining object shapes in TypeScript".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/workspace/hooks/use-workspaces.ts` around lines 12 - 16,
Replace the inline options object type in the useWorkspace hook with a named
interface: define an interface (e.g., WorkspaceHookOptions) that declares
optional enabled?: boolean, update the function signature to use options?:
WorkspaceHookOptions, and ensure the call-site logic (enabled: options?.enabled
?? Boolean(workspaceID)) and existing references to workspaceDetailOptions and
useQuery remain unchanged.

5-5: Use @/* alias imports in this updated hook module.

The new import should follow the project alias convention instead of relative paths.

Proposed import cleanup
-import { resolveWorkspace, type ResolveWorkspaceParams } from "../adapters/workspace-api";
-import { workspaceKeys } from "../lib/query-keys";
-import { workspaceDetailOptions, workspacesListOptions } from "../lib/query-options";
+import { resolveWorkspace, type ResolveWorkspaceParams } from "@/systems/workspace/adapters/workspace-api";
+import { workspaceKeys } from "@/systems/workspace/lib/query-keys";
+import { workspaceDetailOptions, workspacesListOptions } from "@/systems/workspace/lib/query-options";

As per coding guidelines, web/src/**/*.{ts,tsx}: "Use path alias @/* to map to ./src/* for all imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/workspace/hooks/use-workspaces.ts` at line 5, Replace the
relative import in use-workspaces.ts so it uses the project path alias instead
of a relative path: change the import of workspaceDetailOptions and
workspacesListOptions (currently from "../lib/query-options") to use the "@/..."
alias that maps to ./src (e.g. import from
"@/systems/workspace/lib/query-options"). Update the import statement only; keep
the imported symbols workspaceDetailOptions and workspacesListOptions unchanged.
internal/api/core/bridges_test.go (1)

199-233: Prefer table-driven subtests for the new provider handler test.

Please convert this new case to a t.Run("Should...") table-driven shape to match the test suite standard.

As per coding guidelines, **/*_test.go: "Use table-driven tests with subtests (t.Run) as default".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/core/bridges_test.go` around lines 199 - 233, Convert the flat
TestBridgeHandlersListProviders into a table-driven subtest using t.Run: wrap
the existing setup (newBridgeHandlerFixture with the stubbed ListProvidersFn),
request (performRequest to "/bridges/providers"), assertions (status check,
DecodeJSONResponse, length and field checks) into a subtest entry (e.g., name
"Should list providers") inside a table of test cases and iterate running each
case with t.Run; keep the same assertions and use the existing identifiers
TestBridgeHandlersListProviders, newBridgeHandlerFixture, performRequest, and
contract.BridgeProvidersResponse so the behavior is unchanged but now follows
the suite standard of table-driven subtests.
internal/api/udsapi/bridges_test.go (1)

127-159: Align this new UDS handler test with table-driven subtests.

Please wrap this in t.Run("Should...") table-driven structure for consistency with the repository’s Go test policy.

As per coding guidelines, **/*_test.go: "Use table-driven tests with subtests (t.Run) as default in Go tests" and "MUST use t.Run("Should...") pattern for ALL test cases".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/udsapi/bridges_test.go` around lines 127 - 159, Wrap the
existing TestListBridgeProvidersHandlerReturnsRequestedPayload into a
table-driven subtest using t.Run with a "Should..." description (e.g.,
t.Run("Should return requested payload", func(t *testing.T) { ... })), so the
test body (setup of homePaths, stubBridgeService, engine via
newTestRouter/newTestHandlersWithBridges, performRequest, decodeJSONResponse and
assertions) is executed inside the subtest closure; keep the original test name
and contents but move them into a single-entry table-driven structure (if you
want to demonstrate the table pattern, you may create a slice of test cases and
iterate with t.Run for each, but at minimum wrap the existing scenario in t.Run)
ensuring TestListBridgeProvidersHandlerReturnsRequestedPayload still calls
t.Parallel() outside or inside the subtest as appropriate.
internal/extension/manifest_test.go (1)

467-505: Please refactor this new validation test into t.Run("Should...") subtests.

The assertions are useful, but this new case should follow the suite’s required table-driven/subtest pattern.

As per coding guidelines, **/*_test.go: "Use table-driven tests with subtests (t.Run) as default" and "MUST use t.Run("Should...") pattern for ALL test cases".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/extension/manifest_test.go` around lines 467 - 505, Refactor
TestManifestValidate_RequiresBridgeMetadataForBridgeAdapters into multiple
t.Run("Should...") subtests that each isolate one assertion: e.g., t.Run("Should
return ErrManifestInvalid when bridge metadata missing") to create a fresh
manifest via expectedManifest(), set manifest.Capabilities.Provides to include
extensionprotocol.CapabilityProvideBridgeAdapter, call manifest.Validate() and
assert errors.Is(err, ErrManifestInvalid) and errors.As to
*ManifestValidationError with Field == "bridge.platform"; t.Run("Should require
bridge.display_name after platform set") to set manifest.Bridge.Platform =
"telegram", call Validate and assert validationErr.Field ==
"bridge.display_name"; and t.Run("Should pass when bridge metadata complete") to
set manifest.Bridge.DisplayName = "Telegram" and assert Validate() returns nil;
keep withDaemonVersion(t, "0.6.0") either once outside or in each subtest as
appropriate.
web/src/systems/bridges/hooks/use-bridge-actions.ts (1)

27-43: Consider optimistic updates for improved UX.

Both mutation hooks correctly use onSettled for cache invalidation per guidelines. For useCreateBridge, optimistic updates aren't applicable since there's no prior state. However, useTestBridgeDelivery could potentially benefit from an optimistic loading indicator pattern via onMutate/onError snapshots if the UI shows delivery test status.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/bridges/hooks/use-bridge-actions.ts` around lines 27 - 43,
Add optimistic update handling to useTestBridgeDelivery: implement an onMutate
in useTestBridgeDelivery that uses the queryClient to snapshot and optionally
set a temporary "testing" state for the bridge (keyed by the bridge id), return
the snapshot for rollback, and implement onError to restore the snapshot if the
mutation fails; keep the existing onSettled to call
invalidateBridgeQueries(queryClient, id) to refresh from server. Reference
useTestBridgeDelivery, testBridgeDelivery, invalidateBridgeQueries, and
queryClient when locating where to add onMutate and onError.
web/src/systems/network/components/network-channels-list-panel.tsx (2)

17-25: Extract ChannelListItem props into an interface.

The inline object type here is out of step with the repository’s TypeScript shape rule. A small ChannelListItemProps interface keeps this consistent with the rest of web/.

As per coding guidelines, "Use interface for defining object shapes in TypeScript (pattern is in Zod schemas and types)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/network/components/network-channels-list-panel.tsx` around
lines 17 - 25, Create a ChannelListItemProps interface and use it as the
component props type instead of the inline object type: define interface
ChannelListItemProps { channel: NetworkChannelSummary; isSelected: boolean;
onSelect: () => void; } and update the ChannelListItem function signature to
accept (props: ChannelListItemProps) or ({ channel, isSelected, onSelect }:
ChannelListItemProps). This keeps the component consistent with the repo’s
TypeScript shape rule and references the existing NetworkChannelSummary,
isSelected, onSelect, and ChannelListItem symbols.

50-96: Add loading and error states to the panel API.

This component can only render a filled list or an empty state, so routes have to special-case loading and failure outside the panel. That breaks the “component owns all states” rule for UI components in web/.

As per coding guidelines, "Handle all loading, error, and empty states in components — never assume data exists".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/network/components/network-channels-list-panel.tsx` around
lines 50 - 96, NetworkChannelsListPanel currently only handles populated or
empty lists; extend its API and rendering to own loading and error states by
updating NetworkChannelsListPanelProps to include isLoading:boolean and
error?:string (or Error) alongside existing props (channels, searchQuery,
selectedChannel, onSearchChange, onSelectChannel), then update
NetworkChannelsListPanel to: when isLoading render a centered loading indicator
(with data-testid), when error render a centered error message (with
data-testid), otherwise keep the existing empty/filled-channel rendering; ensure
ChannelListItem usage and selection behavior remain unchanged.
web/src/systems/network/components/network-peers-list-panel.tsx (2)

22-30: Move PeerListItem props into an interface.

The inline object type here breaks the repository’s TypeScript shape convention. Defining a PeerListItemProps interface would keep this aligned with the rest of the web/ codebase.

As per coding guidelines, "Use interface for defining object shapes in TypeScript (pattern is in Zod schemas and types)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/network/components/network-peers-list-panel.tsx` around lines
22 - 30, Create an interface named PeerListItemProps that declares isSelected:
boolean, onSelect: () => void, and peer: NetworkPeerSummary, then replace the
inline prop type in the PeerListItem function signature with PeerListItemProps
(i.e., function PeerListItem(props: PeerListItemProps) or destructure with ({
isSelected, onSelect, peer }: PeerListItemProps)). Ensure the new interface is
defined in the same module (and exported if other files import it) and update
any usages that referenced the inline type.

66-112: Let the panel render loading and error states too.

Right now this component only knows how to render a list or an empty state, so routes have to branch around it for loading/failure. That pushes state ownership out of the component and conflicts with the UI-state rule for web/ components.

As per coding guidelines, "Handle all loading, error, and empty states in components — never assume data exists".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/network/components/network-peers-list-panel.tsx` around lines
66 - 112, NetworkPeersListPanel currently only renders peers or an empty state;
update the component signature (NetworkPeersListPanel props) to accept
isLoading: boolean and error?: Error|string (or similar) and use them to render
three additional states: when isLoading true show a loading placeholder/spinner
(eg. data-testid="network-peers-list-loading"), when error is present show an
error message UI (eg. data-testid="network-peers-list-error"), and only fall
back to the existing "No peers found" empty message when not loading and no
error. Make sure the Input/search area remains visible in all states, keep
existing PeerListItem rendering (peers.map) unchanged, and add the new testids
so callers and tests can target loading/error states.
internal/store/globaldb/global_db_network_messages_test.go (1)

97-121: Convert the guard-clause matrix into table-driven subtests.

These nil-receiver / nil-context / closed-store checks all follow the same pattern, so a t.Run("Should...") table would remove duplication and make future guard cases cheaper to add. As per coding guidelines, "Use table-driven tests with subtests (t.Run) as default".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/store/globaldb/global_db_network_messages_test.go` around lines 97 -
121, The test TestGlobalDBNetworkMessageGuardClauses is repetitive; convert it
to a table-driven set of subtests using t.Run by defining a slice of cases
(e.g., name, setup function returning receiver and ctx, operation enum or func
type for WriteNetworkMessage/ListNetworkMessages, expected error predicate) and
iterate running each case as a subtest; for each case call the appropriate
method (referencing WriteNetworkMessage, ListNetworkMessages and Close) on
nilDB/globalDB with nilGlobalContext or after Close as needed and assert the
expected non-nil or store.ErrClosed error accordingly so the nil-receiver,
nil-context and closed-store checks become compact subtests.
web/src/routes/_app/bridges.tsx (1)

33-34: Import WorkspacePageShell through the workspace barrel.

This route is reaching into another system’s internals. Please re-export the shell from @/systems/workspace and import it from there so the boundary stays stable.

As per coding guidelines, "Only import from cross-system dependencies through the public barrel export (@/systems/<domain>), never reach into another system's internals".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/routes/_app/bridges.tsx` around lines 33 - 34, The import reaches
into workspace internals by importing WorkspacePageShell from
"@/systems/workspace/components/workspace-page-shell"; instead re-export
WorkspacePageShell from the workspace public barrel (add export {
WorkspacePageShell } from "./components/workspace-page-shell" in the
"@/systems/workspace" index) and update this file to import WorkspacePageShell
from "@/systems/workspace" (keep useActiveWorkspace import as-is) so the route
only uses the public barrel export.
web/src/systems/network/lib/network-formatters.ts (1)

151-154: Prefer an interface for the metric card shape instead of an inline object type.

Use a named interface for this return shape to align with project TS conventions.

Proposed refactor
+interface NetworkMetricCard {
+  detail?: string;
+  label: string;
+  value: string;
+}
+
 export function getNetworkMetricCards(
   status: NetworkStatus | undefined,
   channelCount: number
-): Array<{ detail?: string; label: string; value: string }> {
+): NetworkMetricCard[] {

As per coding guidelines, web/**/*.ts?(x): Use interface for defining object shapes in TypeScript (pattern is in Zod schemas and types).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/systems/network/lib/network-formatters.ts` around lines 151 - 154,
The return type of getNetworkMetricCards currently uses an inline object type;
replace that inline type with a named interface (e.g., NetworkMetricCard)
declared near the top of the file and use it in getNetworkMetricCards's
signature and any related code. Define interface NetworkMetricCard { detail?:
string; label: string; value: string } and update the function signature to
return Array<NetworkMetricCard> (or NetworkMetricCard[]) so the shape follows
the project's TypeScript conventions.

Comment thread internal/api/core/network_details.go
Comment thread internal/api/core/network_details.go
Comment thread internal/api/core/network_details.go Outdated
Comment thread internal/api/core/network.go Outdated
Comment thread internal/daemon/bridges.go
Comment thread web/src/routes/_app/network.tsx Outdated
Comment thread web/src/systems/bridges/components/bridge-create-dialog.tsx Outdated
Comment thread web/src/systems/network/components/network-create-channel-dialog.tsx Outdated
Comment thread web/src/systems/network/hooks/use-network-actions.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (1)
web/src/routes/_app/-network.test.tsx (1)

74-76: ⚠️ Potential issue | 🟠 Major

Replace React.ReactNode with the imported ReactNode type.

Lines 74 and 327 reference React.ReactNode but only ReactNode is imported (line 3), not the React namespace. This causes TypeScript errors that will fail make web-typecheck.

Proposed fix
-  createFileRoute: () => (opts: { component: () => React.ReactNode }) => ({
+  createFileRoute: () => (opts: { component: () => ReactNode }) => ({
     component: opts.component,
   }),
-const NetworkPage = (Route as unknown as { component: () => React.ReactNode }).component;
+const NetworkPage = (Route as unknown as { component: () => ReactNode }).component;

,

Also applies to: 327-327

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/routes/_app/-network.test.tsx` around lines 74 - 76, The type
reference React.ReactNode used in createFileRoute should be replaced with the
imported ReactNode type; update the signature in createFileRoute (and the other
occurrence around the second reference) to use ReactNode instead of
React.ReactNode so it matches the import (ReactNode) and fixes the TypeScript
error.
🧹 Nitpick comments (1)
internal/api/core/network.go (1)

115-129: Use StatusForNetworkError(err) directly here.

This branch now mirrors the same network-error allowlist already centralized in internal/api/core/errors.go. The next error added there can silently regress to a 500 here until both places are updated.

Possible simplification
 	channels, err := h.networkChannelPayloads(c.Request.Context(), service)
 	if err != nil {
-		status := http.StatusInternalServerError
-		if errors.Is(err, ErrNetworkValidation) ||
-			errors.Is(err, network.ErrLocalPeerNotFound) ||
-			errors.Is(err, network.ErrTargetPeerNotFound) ||
-			errors.Is(err, network.ErrMissingField) ||
-			errors.Is(err, network.ErrInvalidField) ||
-			errors.Is(err, network.ErrInvalidKind) ||
-			errors.Is(err, network.ErrInvalidBody) ||
-			errors.Is(err, network.ErrExpired) ||
-			errors.Is(err, network.ErrReplayTooOld) {
-			status = StatusForNetworkError(err)
-		}
-		h.respondError(c, status, err)
+		h.respondError(c, StatusForNetworkError(err), err)
 		return
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/core/network.go` around lines 115 - 129, The error handling in
networkChannelPayloads duplicates an allowlist of network errors; replace the
manual errors.Is checks with a single call to StatusForNetworkError(err) to
derive the HTTP status and call h.respondError(c, StatusForNetworkError(err),
err). Locate the block around the call to networkChannelPayloads and remove the
long errors.Is chain (references: networkChannelPayloads, ErrNetworkValidation,
network.ErrLocalPeerNotFound, network.ErrTargetPeerNotFound,
network.ErrMissingField, network.ErrInvalidField, network.ErrInvalidKind,
network.ErrInvalidBody, network.ErrExpired, network.ErrReplayTooOld) so the code
always uses StatusForNetworkError(err) for the status.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/api/core/network_test.go`:
- Around line 354-427: The test
TestBaseHandlersNetworkPeersUseBestEffortSessionEnrichment (and the other
top-level tests noted) should be converted into t.Run subtests following the
"Should..." pattern: wrap each logical assertion or endpoint scenario inside
t.Run("Should ...", func(t *testing.T){ ... }) and keep the existing setup
(localSessionID, brokenSessionID, manager, fixture, ListPeersFn,
request/response assertions) inside the subtest body; ensure each assertion
becomes its own subtest name (e.g., "Should return enriched display name for
local session", "Should fall back to peer card display name when status lookup
fails"), move t.Parallel() into individual subtests if parallelism is desired,
and apply the same refactor to the other top-level tests referenced (the blocks
covering lines 429-497, 499-601, 812-1404) so each endpoint/contract assertion
is a table-driven or named t.Run("Should...") subtest for clearer failure
localization.

In `@internal/network/audit_test.go`:
- Around line 120-173: The tests should be converted into t.Run subtests so
failures are isolated: update TestAuditWriterRecordsDeliveredDirection and
TestAuditWriterPersistsTimelineMessagesForSayEnvelopesForSayEnvelopesOnly to use
t.Run("Should ...") subtests around each behavior (e.g., a subtest for recording
delivered direction that calls NewAuditWriter, writer.RecordDelivered and
asserts storeSink.entries[0].Direction; and separate subtests inside the
PersistsTimeline... test for persisting messages, deduplication between
RecordSent/RecordReceived calls, and ignoring non-say envelopes that call
writer.RecordSent/RecordReceived/now and assert storeSink.messages contents such
as MessageID, Intent and Text). Keep existing setup (recordingAuditStore,
NewAuditWriter, writer.now) but move each logical assertion block into its own
t.Run with descriptive "Should..." names and maintain t.Parallel() at the top of
each parent test.

In `@internal/network/audit.go`:
- Around line 124-131: normalizeTimelineMessageEntry is being called regardless
of w.messageStore and WriteNetworkMessage may run even if WriteNetworkAudit
failed, causing failures for file-only writers and orphan timeline rows; change
the sequence in RecordSent/RecordReceived so that you first attempt the audit
write via w.store.WriteNetworkAudit(ctx, entry) (keep existing join behavior),
then only if w.messageStore != nil proceed to call
normalizeTimelineMessageEntry(sessionID, direction, envelope, entry.Timestamp)
and handle its error, and only after normalize succeeds call
w.messageStore.WriteNetworkMessage(ctx, messageEntry); ensure that if the audit
write returns an error you skip the message write to avoid orphan rows and that
normalization is never invoked when w.messageStore == nil so normalization
errors cannot break audit-only flows.

In `@web/src/systems/bridges/components/bridge-create-dialog.test.tsx`:
- Around line 4-5: Replace the two relative imports with project path-alias
imports so the test uses the "@/..." alias convention: update the import for
BridgeCreateDraft (currently from "../types") to import from
"@/systems/bridges/types" and update the import for BridgeCreateDialog
(currently from "./bridge-create-dialog") to import from
"@/systems/bridges/components/bridge-create-dialog"; ensure the imported symbols
BridgeCreateDraft and BridgeCreateDialog remain unchanged.

---

Duplicate comments:
In `@web/src/routes/_app/-network.test.tsx`:
- Around line 74-76: The type reference React.ReactNode used in createFileRoute
should be replaced with the imported ReactNode type; update the signature in
createFileRoute (and the other occurrence around the second reference) to use
ReactNode instead of React.ReactNode so it matches the import (ReactNode) and
fixes the TypeScript error.

---

Nitpick comments:
In `@internal/api/core/network.go`:
- Around line 115-129: The error handling in networkChannelPayloads duplicates
an allowlist of network errors; replace the manual errors.Is checks with a
single call to StatusForNetworkError(err) to derive the HTTP status and call
h.respondError(c, StatusForNetworkError(err), err). Locate the block around the
call to networkChannelPayloads and remove the long errors.Is chain (references:
networkChannelPayloads, ErrNetworkValidation, network.ErrLocalPeerNotFound,
network.ErrTargetPeerNotFound, network.ErrMissingField, network.ErrInvalidField,
network.ErrInvalidKind, network.ErrInvalidBody, network.ErrExpired,
network.ErrReplayTooOld) so the code always uses StatusForNetworkError(err) for
the status.
🪄 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: 7da7840f-ccfb-4d52-9258-638fc32e9915

📥 Commits

Reviewing files that changed from the base of the PR and between f789f10 and bd6a886.

⛔ Files ignored due to path filters (95)
  • .agents/skills/compozy/SKILL.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/compozy/references/cli-reference.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/compozy/references/skills-reference.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/compozy/references/workflow-guide.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/karpathy-kb/SKILL.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/karpathy-kb/assets/concept-index-template.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/karpathy-kb/assets/dashboard-template.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/karpathy-kb/assets/log-template.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/karpathy-kb/assets/source-index-template.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/karpathy-kb/assets/topic-claude-template.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/karpathy-kb/assets/wiki-article-template.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/karpathy-kb/scripts/lint-wiki.py is excluded by !.agents/**
  • .agents/skills/karpathy-kb/scripts/new-topic.sh is excluded by !.agents/**
  • .agents/skills/kb/SKILL.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/kb/references/architecture.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/kb/references/cli-ingest-codebase.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/kb/references/cli-inspect.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/kb/references/cli-search-index.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/kb/references/compilation-guide.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/kb/references/error-handling.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/kb/references/frontmatter-schemas.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/kb/references/lint-procedure.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/kb/references/output-formats.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/kb/references/tooling-tips.md is excluded by !**/*.md, !.agents/**
  • .codex/plans/2026-04-13-automation-bridges-paper-redesign.md is excluded by !**/*.md
  • .codex/plans/2026-04-13-network-paper-pages.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/_tasks.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/_techspec.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/adrs/adr-001.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/adrs/adr-002.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/adrs/adr-003.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/adrs/adr-004.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/adrs/adr-005.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/adrs/adr-006.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/analysis/analysis_agh-harness.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/analysis/analysis_goclaw.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/analysis/analysis_multica.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/analysis/analysis_paperclip.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/review-round-1.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_01.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_02.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_03.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_04.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_05.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_06.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_07.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_08.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_09.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_10.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_11.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_12.md is excluded by !**/*.md
  • .compozy/tasks/core-tasks/task_13.md is excluded by !**/*.md
  • .compozy/tasks/extension-registry/_tasks.md is excluded by !**/*.md
  • .compozy/tasks/extension-registry/_techspec.md is excluded by !**/*.md
  • .compozy/tasks/extension-registry/adrs/adr-001.md is excluded by !**/*.md
  • .compozy/tasks/extension-registry/adrs/adr-002.md is excluded by !**/*.md
  • .compozy/tasks/extension-registry/adrs/adr-003.md is excluded by !**/*.md
  • .compozy/tasks/extension-registry/adrs/adr-004.md is excluded by !**/*.md
  • .compozy/tasks/extension-registry/task_01.md is excluded by !**/*.md
  • .compozy/tasks/extension-registry/task_02.md is excluded by !**/*.md
  • .compozy/tasks/extension-registry/task_03.md is excluded by !**/*.md
  • .compozy/tasks/extension-registry/task_04.md is excluded by !**/*.md
  • .compozy/tasks/extension-registry/task_05.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/_meta.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_001.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_002.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_003.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_004.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_005.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_006.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_007.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_008.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_009.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_010.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_011.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_012.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_013.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_014.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_015.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_016.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_017.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_018.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_019.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_020.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_021.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_022.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_023.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_024.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_025.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_026.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_027.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_028.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_029.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_030.md is excluded by !**/*.md
  • .compozy/tasks/web-pages/reviews-001/issue_031.md is excluded by !**/*.md
📒 Files selected for processing (47)
  • internal/api/core/bridges.go
  • internal/api/core/bridges_test.go
  • internal/api/core/network.go
  • internal/api/core/network_details.go
  • internal/api/core/network_test.go
  • internal/api/httpapi/httpapi_integration_test.go
  • internal/api/udsapi/bridges_test.go
  • internal/cli/cli_integration_test.go
  • internal/daemon/bridges.go
  • internal/daemon/bridges_test.go
  • internal/extension/manifest_test.go
  • internal/network/audit.go
  • internal/network/audit_test.go
  • internal/store/globaldb/global_db_network_messages.go
  • internal/store/globaldb/global_db_network_messages_test.go
  • web/src/routes/_app/-automation.integration.test.tsx
  • web/src/routes/_app/-bridges.test.tsx
  • web/src/routes/_app/-network.test.tsx
  • web/src/routes/_app/automation.tsx
  • web/src/routes/_app/bridges.tsx
  • web/src/routes/_app/network.tsx
  • web/src/systems/automation/components/automation-detail-panel.test.tsx
  • web/src/systems/automation/components/automation-detail-panel.tsx
  • web/src/systems/automation/components/automation-job-form.test.tsx
  • web/src/systems/automation/components/automation-job-form.tsx
  • web/src/systems/automation/lib/automation-formatters.test.ts
  • web/src/systems/automation/lib/automation-formatters.ts
  • web/src/systems/bridges/components/bridge-create-dialog.test.tsx
  • web/src/systems/bridges/components/bridge-create-dialog.tsx
  • web/src/systems/bridges/components/bridge-empty-state.tsx
  • web/src/systems/bridges/components/bridge-list-panel.tsx
  • web/src/systems/bridges/components/bridge-provider-card.tsx
  • web/src/systems/bridges/components/bridge-test-delivery-dialog.tsx
  • web/src/systems/bridges/lib/bridge-drafts.ts
  • web/src/systems/bridges/lib/bridge-formatters.ts
  • web/src/systems/bridges/lib/query-options.test.ts
  • web/src/systems/network/components/network-channels-list-panel.tsx
  • web/src/systems/network/components/network-create-channel-dialog.tsx
  • web/src/systems/network/components/network-peers-list-panel.tsx
  • web/src/systems/network/hooks/use-network-actions.ts
  • web/src/systems/network/lib/network-formatters.ts
  • web/src/systems/session/components/message-bubble.tsx
  • web/src/systems/workspace/adapters/workspace-api.test.ts
  • web/src/systems/workspace/adapters/workspace-api.ts
  • web/src/systems/workspace/hooks/use-workspaces.test.tsx
  • web/src/systems/workspace/hooks/use-workspaces.ts
  • web/src/systems/workspace/index.ts
✅ Files skipped from review due to trivial changes (3)
  • web/src/systems/automation/components/automation-detail-panel.test.tsx
  • web/src/routes/_app/-bridges.test.tsx
  • web/src/systems/automation/lib/automation-formatters.ts
🚧 Files skipped from review as they are similar to previous changes (11)
  • internal/cli/cli_integration_test.go
  • web/src/systems/automation/components/automation-job-form.test.tsx
  • internal/api/udsapi/bridges_test.go
  • internal/extension/manifest_test.go
  • internal/store/globaldb/global_db_network_messages_test.go
  • web/src/systems/automation/lib/automation-formatters.test.ts
  • internal/store/globaldb/global_db_network_messages.go
  • web/src/routes/_app/-automation.integration.test.tsx
  • internal/daemon/bridges.go
  • web/src/routes/_app/automation.tsx
  • internal/api/core/network_details.go

Comment thread internal/api/core/network_test.go
Comment thread internal/network/audit_test.go
Comment thread internal/network/audit.go
Comment thread web/src/systems/bridges/components/bridge-create-dialog.test.tsx Outdated
pedronauck added a commit that referenced this pull request Apr 14, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
web/src/routes/_app/-network.test.tsx (2)

208-208: Use the @/ path alias for this import.

Line 208 uses a relative import ("./network"), which violates the project import rule for web source files.

Suggested change
-import { Route } from "./network";
+import { Route } from "@/routes/_app/network";

As per coding guidelines, "Use path alias @/* to map to ./src/* for all imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/routes/_app/-network.test.tsx` at line 208, The test file
-network.test.tsx imports Route via a relative path ("./network"); replace that
with the project path alias so the import uses "@/routes/_app/network" (i.e.,
import { Route } from "@/routes/_app/network") to satisfy the web source file
import rule and keep the reference to the Route symbol intact.

61-66: Replace inline object-shape type literals with interfaces.

These segments define object shapes inline; this file should use interface declarations instead for object-shape types.

Suggested change
+interface MockLinkProps {
+  children: ReactNode;
+  params?: { id?: string };
+  to: string;
+  [key: string]: unknown;
+}
+
+interface MockWorkspacePageShellProps {
+  children: ReactNode;
+  controls?: ReactNode;
+  meta?: ReactNode;
+  title: string;
+}
+
+interface RouteWithComponent {
+  component: () => ReactNode;
+}
+
 vi.mock("@tanstack/react-router", () => ({
   Link: ({
     children,
     to,
     params,
     ...props
-  }: {
-    children: ReactNode;
-    params?: { id?: string };
-    to: string;
-    [key: string]: unknown;
-  }) => {
+  }: MockLinkProps) => {
@@
-  createFileRoute: () => (opts: { component: () => ReactNode }) => ({
+  createFileRoute: () => (opts: RouteWithComponent) => ({
     component: opts.component,
   }),
 }));
@@
   WorkspacePageShell: ({
     children,
     controls,
     meta,
     title,
-  }: {
-    children: ReactNode;
-    controls?: ReactNode;
-    meta?: ReactNode;
-    title: string;
-  }) => (
+  }: MockWorkspacePageShellProps) => (
@@
-const NetworkPage = (Route as unknown as { component: () => ReactNode }).component;
+const NetworkPage = (Route as unknown as RouteWithComponent).component;

As per coding guidelines, "web/**/*.ts?(x): Use interface for defining object shapes in TypeScript (pattern is in Zod schemas and types)".

Also applies to: 89-94, 327-327

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/routes/_app/-network.test.tsx` around lines 61 - 66, Replace the
inline object-shape type literal used for the component props (the parameter
typed in the block starting with "}: { children: ReactNode; params?: { id?:
string }; to: string; [key: string]: unknown; }) => {") with a named interface
(e.g., NetworkLinkProps) and use that interface for the parameter type; do the
same for the other inline object-shape literals referenced (the shapes around
lines 89-94 and at 327) by declaring appropriately named interfaces and swapping
the inline types for those interface names so all object-shape types in this
file use interface declarations.
internal/api/core/network_test.go (1)

357-1438: Consider adding t.Parallel() inside independent new subtests.

Most of these t.Run("Should ...") cases build isolated fixtures and can run safely in parallel to keep suite runtime lower.

As per coding guidelines, "Use t.Parallel() for independent subtests in Go tests."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/core/network_test.go` around lines 357 - 1438, Many subtests
(e.g. the "Should enrich local peers..." case, and subtests inside
TestBaseHandlersNetworkErrorsAndDisabledMode like "ShouldReturnDisabledStatus",
"ShouldReturnServiceUnavailableWhenNetworkServiceMissing",
"ShouldMapNetworkStatusErrorTo500", etc.) are missing t.Parallel(), so they
don't run concurrently; add t.Parallel() as the first line inside each
independent t.Run closure (for examples see subtests with titles "Should enrich
local peers and fall back to peer-card display names on lookup failures", and
all "Should..." subtests within TestBaseHandlersNetworkErrorsAndDisabledMode,
TestValidationErrorHelpersPreserveInnerErrorChain,
TestBaseHandlersNetworkChannelEndpointsIgnoreStoppedSessions,
TestBaseHandlersNetworkChannelMessagesPreserveRemoteAuthors,
TestBaseHandlersCreateNetworkChannelCreatesSessionsPerAgent,
TestBaseHandlersNetworkPeerDetailUsesAuditMetrics) to mark them parallel-safe
and reduce overall test runtime.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/src/routes/_app/-network.test.tsx`:
- Around line 504-513: The toast.success assertion is currently synchronous and
can race with the mutation; change it to be asserted asynchronously by awaiting
a waitFor that checks toast.success was called with "Created channel
deployments." (i.e., replace the immediate
expect(toast.success).toHaveBeenCalledWith(...) with await waitFor(() =>
expect(toast.success).toHaveBeenCalledWith("Created channel deployments."))).
Keep the existing waitFor for mockCreateNetworkChannelMutateAsync and the
reference to mockCreateNetworkChannelMutateAsync and toast.success so the test
reliably waits for the toast dispatch.

---

Nitpick comments:
In `@internal/api/core/network_test.go`:
- Around line 357-1438: Many subtests (e.g. the "Should enrich local peers..."
case, and subtests inside TestBaseHandlersNetworkErrorsAndDisabledMode like
"ShouldReturnDisabledStatus",
"ShouldReturnServiceUnavailableWhenNetworkServiceMissing",
"ShouldMapNetworkStatusErrorTo500", etc.) are missing t.Parallel(), so they
don't run concurrently; add t.Parallel() as the first line inside each
independent t.Run closure (for examples see subtests with titles "Should enrich
local peers and fall back to peer-card display names on lookup failures", and
all "Should..." subtests within TestBaseHandlersNetworkErrorsAndDisabledMode,
TestValidationErrorHelpersPreserveInnerErrorChain,
TestBaseHandlersNetworkChannelEndpointsIgnoreStoppedSessions,
TestBaseHandlersNetworkChannelMessagesPreserveRemoteAuthors,
TestBaseHandlersCreateNetworkChannelCreatesSessionsPerAgent,
TestBaseHandlersNetworkPeerDetailUsesAuditMetrics) to mark them parallel-safe
and reduce overall test runtime.

In `@web/src/routes/_app/-network.test.tsx`:
- Line 208: The test file -network.test.tsx imports Route via a relative path
("./network"); replace that with the project path alias so the import uses
"@/routes/_app/network" (i.e., import { Route } from "@/routes/_app/network") to
satisfy the web source file import rule and keep the reference to the Route
symbol intact.
- Around line 61-66: Replace the inline object-shape type literal used for the
component props (the parameter typed in the block starting with "}: { children:
ReactNode; params?: { id?: string }; to: string; [key: string]: unknown; }) =>
{") with a named interface (e.g., NetworkLinkProps) and use that interface for
the parameter type; do the same for the other inline object-shape literals
referenced (the shapes around lines 89-94 and at 327) by declaring appropriately
named interfaces and swapping the inline types for those interface names so all
object-shape types in this file use interface declarations.
🪄 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: a8dc484f-8eda-4c43-b7fd-e5abd170564d

📥 Commits

Reviewing files that changed from the base of the PR and between bd6a886 and 091297c.

📒 Files selected for processing (6)
  • internal/api/core/network.go
  • internal/api/core/network_test.go
  • internal/network/audit.go
  • internal/network/audit_test.go
  • web/src/routes/_app/-network.test.tsx
  • web/src/systems/bridges/components/bridge-create-dialog.test.tsx
✅ Files skipped from review due to trivial changes (1)
  • internal/network/audit.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/network/audit_test.go

Comment on lines +504 to +513
await waitFor(() =>
expect(mockCreateNetworkChannelMutateAsync).toHaveBeenCalledWith({
agent_names: ["polybot-main", "coder-agent-01"],
channel: "deployments",
workspace_id: "ws_main",
})
);
expect(mockCreateNetworkChannelMutateAsync).toHaveBeenCalledOnce();
expect(toast.success).toHaveBeenCalledWith("Created channel deployments.");
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Make the toast success assertion asynchronous to avoid timing flakiness.

toast.success is asserted immediately after waitFor on mutation call. If toast dispatch happens on a later microtask, this can become flaky.

Suggested change
-    expect(mockCreateNetworkChannelMutateAsync).toHaveBeenCalledOnce();
-    expect(toast.success).toHaveBeenCalledWith("Created channel deployments.");
+    expect(mockCreateNetworkChannelMutateAsync).toHaveBeenCalledOnce();
+    await waitFor(() => {
+      expect(toast.success).toHaveBeenCalledWith("Created channel deployments.");
+    });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/routes/_app/-network.test.tsx` around lines 504 - 513, The
toast.success assertion is currently synchronous and can race with the mutation;
change it to be asserted asynchronously by awaiting a waitFor that checks
toast.success was called with "Created channel deployments." (i.e., replace the
immediate expect(toast.success).toHaveBeenCalledWith(...) with await waitFor(()
=> expect(toast.success).toHaveBeenCalledWith("Created channel deployments."))).
Keep the existing waitFor for mockCreateNetworkChannelMutateAsync and the
reference to mockCreateNetworkChannelMutateAsync and toast.success so the test
reliably waits for the toast dispatch.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
web/src/routes/_app/network.tsx (3)

333-343: Consider extracting inline handlers for dialog props.

The inline arrow functions for onChannelNameChange and onToggleAgent create new references on each render. For a top-level route component this is typically acceptable, but extracting them to useCallback hooks would prevent unnecessary re-renders of NetworkCreateChannelDialog if it's memoized.

♻️ Optional extraction pattern
+  const handleChannelNameChange = useCallback((channelName: string) => {
+    setCreateDraft(currentDraft => ({
+      ...currentDraft,
+      channelName,
+    }));
+  }, []);
+
+  const handleToggleAgent = useCallback((agentName: string) => {
+    setCreateDraft(currentDraft => toggleDraftAgent(currentDraft, agentName));
+  }, []);
+
   // Then in JSX:
-        onChannelNameChange={channelName =>
-          setCreateDraft(currentDraft => ({
-            ...currentDraft,
-            channelName,
-          }))
-        }
+        onChannelNameChange={handleChannelNameChange}
         ...
-        onToggleAgent={agentName =>
-          setCreateDraft(currentDraft => toggleDraftAgent(currentDraft, agentName))
-        }
+        onToggleAgent={handleToggleAgent}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/routes/_app/network.tsx` around lines 333 - 343, The inline arrow
props for onChannelNameChange and onToggleAgent are recreated each render and
can trigger unnecessary re-renders of NetworkCreateChannelDialog; extract them
into stable callbacks using useCallback (e.g., define handleChannelNameChange =
useCallback(channelName => setCreateDraft(d => ({ ...d, channelName })),
[setCreateDraft]) and handleToggleAgent = useCallback(agentName =>
setCreateDraft(d => toggleDraftAgent(d, agentName)), [setCreateDraft,
toggleDraftAgent]) and then pass these handlers (and keep
onOpenChange={setCreateDialogOpen} and onSubmit={handleCreateChannel}) to the
dialog to maintain identical behavior while providing stable function
references.

110-123: Redundant condition checks in loading state logic.

isNetworkStatusLoading (line 55) already includes the !networkStatusQuery.data check. The additional && !networkStatusQuery.data on lines 112 and 119 is redundant.

♻️ Proposed simplification
   const isChannelsListLoading =
     !isNetworkDisabled &&
-    ((isNetworkStatusLoading && !networkStatusQuery.data) ||
+    (isNetworkStatusLoading ||
       (networkChannelsQuery.isLoading && !networkChannelsQuery.data));
   const channelsListError = !isNetworkDisabled
     ? (networkStatusError ?? (!networkChannelsQuery.data ? networkChannelsQuery.error : null))
     : null;
   const isPeersListLoading =
     !isNetworkDisabled &&
-    ((isNetworkStatusLoading && !networkStatusQuery.data) ||
+    (isNetworkStatusLoading ||
       (networkPeersQuery.isLoading && !networkPeersQuery.data));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/routes/_app/network.tsx` around lines 110 - 123, The loading checks
for isChannelsListLoading and isPeersListLoading duplicate the
"!networkStatusQuery.data" condition because isNetworkStatusLoading already
encodes that; update the two expressions (the ones assigning
isChannelsListLoading and isPeersListLoading) to remove the redundant "&&
!networkStatusQuery.data" clause so each becomes: not disabled AND
(isNetworkStatusLoading || networkChannelsQuery.isLoading &&
!networkChannelsQuery.data) (and similarly for networkPeersQuery) — locate the
assignments to isChannelsListLoading and isPeersListLoading in network.tsx and
simplify those boolean expressions accordingly while leaving channelsListError
and peersListError logic unchanged.

82-96: Auto-selection may shift unexpectedly when sort order changes.

The effective selection falls back to visibleChannels[0] or visiblePeers[0] when the prior selection is no longer in the filtered list. Per sortNetworkChannels, channels are sorted by last_message_at descending—new incoming messages can reorder the list and silently move the user's focus to a different item.

If preserving user selection is important, consider only auto-selecting on initial mount or when the list transitions from empty to populated, rather than on every filter/sort change.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/routes/_app/network.tsx` around lines 82 - 96, The current
auto-selection logic in effectiveSelectedChannel and effectiveSelectedPeerId
causes focus to jump when sortNetworkChannels reorders
visibleChannels/visiblePeers; change the logic to only auto-select when the
component first mounts or when the visible list transitions from empty to
non-empty (instead of on every change). Implement this by tracking a ref or
previous length (e.g., hasAutoSelectedChannel/hasAutoSelectedPeer or
prevVisibleChannelsLength/prevVisiblePeersLength) and only fall back to
visibleChannels[0]?.channel or visiblePeers[0]?.peer_id when the ref is false or
previous length was 0; after performing the initial auto-select set the ref to
true so subsequent sorts/filters won’t override an existing user-selected
selectedChannel/selectedPeerId. Ensure both effectiveSelectedChannel and
effectiveSelectedPeerId use the same pattern and keep sortNetworkChannels
behavior unchanged.
web/src/routes/_app/automation.tsx (1)

75-83: Consider extracting parameter type to an interface.

The inline object type for buildEmptyState parameters could be extracted to a named interface for consistency with the coding guideline "Use interface for defining object shapes."

♻️ Suggested refactor
+interface BuildEmptyStateParams {
+  activeTab: AutomationTab;
+  hasQuery: boolean;
+  onCreate: () => void;
+}
+
-function buildEmptyState({
-  activeTab,
-  hasQuery,
-  onCreate,
-}: {
-  activeTab: AutomationTab;
-  hasQuery: boolean;
-  onCreate: () => void;
-}) {
+function buildEmptyState({ activeTab, hasQuery, onCreate }: BuildEmptyStateParams) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/routes/_app/automation.tsx` around lines 75 - 83, The inline
parameter object for the buildEmptyState function should be extracted into a
named interface (e.g., BuildEmptyStateProps) to follow the project guideline of
using interface for object shapes; create the interface with properties
activeTab: AutomationTab, hasQuery: boolean, and onCreate: () => void, then
update the buildEmptyState signature to accept (props: BuildEmptyStateProps) and
update any call sites accordingly to pass the same object shape.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@web/src/routes/_app/automation.tsx`:
- Around line 75-83: The inline parameter object for the buildEmptyState
function should be extracted into a named interface (e.g., BuildEmptyStateProps)
to follow the project guideline of using interface for object shapes; create the
interface with properties activeTab: AutomationTab, hasQuery: boolean, and
onCreate: () => void, then update the buildEmptyState signature to accept
(props: BuildEmptyStateProps) and update any call sites accordingly to pass the
same object shape.

In `@web/src/routes/_app/network.tsx`:
- Around line 333-343: The inline arrow props for onChannelNameChange and
onToggleAgent are recreated each render and can trigger unnecessary re-renders
of NetworkCreateChannelDialog; extract them into stable callbacks using
useCallback (e.g., define handleChannelNameChange = useCallback(channelName =>
setCreateDraft(d => ({ ...d, channelName })), [setCreateDraft]) and
handleToggleAgent = useCallback(agentName => setCreateDraft(d =>
toggleDraftAgent(d, agentName)), [setCreateDraft, toggleDraftAgent]) and then
pass these handlers (and keep onOpenChange={setCreateDialogOpen} and
onSubmit={handleCreateChannel}) to the dialog to maintain identical behavior
while providing stable function references.
- Around line 110-123: The loading checks for isChannelsListLoading and
isPeersListLoading duplicate the "!networkStatusQuery.data" condition because
isNetworkStatusLoading already encodes that; update the two expressions (the
ones assigning isChannelsListLoading and isPeersListLoading) to remove the
redundant "&& !networkStatusQuery.data" clause so each becomes: not disabled AND
(isNetworkStatusLoading || networkChannelsQuery.isLoading &&
!networkChannelsQuery.data) (and similarly for networkPeersQuery) — locate the
assignments to isChannelsListLoading and isPeersListLoading in network.tsx and
simplify those boolean expressions accordingly while leaving channelsListError
and peersListError logic unchanged.
- Around line 82-96: The current auto-selection logic in
effectiveSelectedChannel and effectiveSelectedPeerId causes focus to jump when
sortNetworkChannels reorders visibleChannels/visiblePeers; change the logic to
only auto-select when the component first mounts or when the visible list
transitions from empty to non-empty (instead of on every change). Implement this
by tracking a ref or previous length (e.g.,
hasAutoSelectedChannel/hasAutoSelectedPeer or
prevVisibleChannelsLength/prevVisiblePeersLength) and only fall back to
visibleChannels[0]?.channel or visiblePeers[0]?.peer_id when the ref is false or
previous length was 0; after performing the initial auto-select set the ref to
true so subsequent sorts/filters won’t override an existing user-selected
selectedChannel/selectedPeerId. Ensure both effectiveSelectedChannel and
effectiveSelectedPeerId use the same pattern and keep sortNetworkChannels
behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 20b4f36c-8bc5-4495-965d-e1133ae76eb5

📥 Commits

Reviewing files that changed from the base of the PR and between 091297c and c3b4ecc.

⛔ Files ignored due to path filters (8)
  • .agents/skills/systematic-qa/SKILL.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/systematic-qa/assets/issue-template.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/systematic-qa/assets/verification-report-template.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/systematic-qa/references/checklist.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/systematic-qa/references/project-signals.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/systematic-qa/scripts/discover-project-contract.py is excluded by !.agents/**
  • docs/ideas/qa-e2e/README.md is excluded by !**/*.md
  • skills-lock.json is excluded by !**/*.json
📒 Files selected for processing (13)
  • web/src/routes/_app/-automation.integration.test.tsx
  • web/src/routes/_app/-network.test.tsx
  • web/src/routes/_app/automation.tsx
  • web/src/routes/_app/network.tsx
  • web/src/systems/automation/components/automation-job-form.test.tsx
  • web/src/systems/automation/components/automation-job-form.tsx
  • web/src/systems/automation/components/automation-trigger-form.test.tsx
  • web/src/systems/automation/components/automation-trigger-form.tsx
  • web/src/systems/automation/index.ts
  • web/src/systems/automation/lib/automation-drafts.test.ts
  • web/src/systems/automation/lib/automation-drafts.ts
  • web/src/systems/network/hooks/use-network.ts
  • web/src/systems/network/lib/query-options.ts
✅ Files skipped from review due to trivial changes (1)
  • web/src/routes/_app/-network.test.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/src/systems/automation/components/automation-job-form.test.tsx

pedronauck added a commit that referenced this pull request May 26, 2026
## 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>
This was referenced May 26, 2026
pedronauck added a commit that referenced this pull request May 26, 2026
## 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>
pedronauck added a commit that referenced this pull request May 26, 2026
## 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>
pedronauck added a commit that referenced this pull request May 27, 2026
## 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 -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](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>
pedronauck added a commit that referenced this pull request May 27, 2026
## 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 -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant