Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8469565
refactor: deepen architecture ownership boundaries
DragonnZhang Aug 21, 2026
18b797a
Merge remote-tracking branch 'origin/main' into pr-9682
DragonnZhang Aug 23, 2026
f868e3e
test(cli): stabilize legacy extension update-check timeout test
DragonnZhang Aug 23, 2026
08aeba4
fix(ci): record cd-cua-driver.yml's shipped size in the workflow size…
DragonnZhang Aug 23, 2026
2912015
Merge remote-tracking branch 'origin/main' into pr-9682
DragonnZhang Aug 24, 2026
e9ffc4e
fix(acp-bridge): refuse only hazardous toJSON shapes in transport byt…
DragonnZhang Aug 24, 2026
1365489
test(webui): pin cleanup-detach exemption release on load reject/cancel
DragonnZhang Aug 24, 2026
855c047
refactor(cli): drop dead InvalidClientIdError re-export, restore barr…
DragonnZhang Aug 24, 2026
4192d0c
test(acp-bridge,webui): pin transport-safety and attachment-lifecycle…
DragonnZhang Aug 24, 2026
e3392b9
fix(cli,acp-bridge,webui): correct barrel comment; pin generation/han…
DragonnZhang Aug 25, 2026
be5a4ec
Merge remote-tracking branch 'origin/main' into pr-9682
DragonnZhang Aug 25, 2026
4f735c7
fix(cli): rename missed resolveTrustedWorkspaceRuntimeFromParam call …
DragonnZhang Aug 25, 2026
ae8768f
test(cli): disambiguate duplicate resolveTrustedRuntime describe title
DragonnZhang Aug 25, 2026
cf3eff9
Merge remote-tracking branch 'origin/main' into pr-9682
DragonnZhang Aug 25, 2026
44ad9cc
fix(web-shell): port admission restore block to PromptAdmissionAttempt
DragonnZhang Aug 25, 2026
5b80e4c
Merge branch 'main' into dragon/architecture-governance
wenshao Aug 26, 2026
6afd3c9
test(cli): fold route-selection assertion into existing resolveTruste…
DragonnZhang Aug 26, 2026
c793288
Merge remote-tracking branch 'upstream/main' into dragon/architecture…
DragonnZhang Aug 26, 2026
e64a40e
Merge remote-tracking branch 'origin/main' into dragon/architecture-g…
DragonnZhang Aug 27, 2026
4e15220
fix(webui): tie the cleanup-detach exemption to the preserving load
DragonnZhang Aug 27, 2026
af40436
style(cli): dedupe the bridgeTypes type imports in session-list
DragonnZhang Aug 27, 2026
4807839
fix(webui): typecheck-clean the reload supersession test (#9682)
DragonnZhang Aug 28, 2026
024c12c
Merge remote-tracking branch 'origin/main' into dragon/architecture-g…
DragonnZhang Aug 28, 2026
2712d25
Merge remote-tracking branch 'origin/main' into dragon/architecture-g…
DragonnZhang Aug 28, 2026
af12a01
fix(webui): guard cleanup-detach releases with the attempted load (R9…
DragonnZhang Aug 28, 2026
5be8b5d
docs(webui): precise R9-1 comment scope, rename to attemptedLoadForIt…
DragonnZhang Aug 28, 2026
1422d79
Merge remote-tracking branch 'origin/main' into dragon/architecture-g…
DragonnZhang Aug 29, 2026
ea7e945
test(webui): add R9-1 pinning fixture from maintainer verification (#…
DragonnZhang Aug 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions docs/design/architecture-deepening-2026-08-21.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Architecture deepening pass

## Goal

Improve locality and leverage in five high-churn seams without changing user-visible behavior:

1. make ACP transport-safety policy a deep internal module;
2. make workspace runtime and trust selection a single route policy;
3. remove the CLI-local ACP compatibility re-export shim;
4. centralize Web Shell prompt-admission and retry transitions;
5. centralize WebUI session-attachment ownership transitions.

This is a staged refactor. Each stage must remain independently testable and must preserve the existing public package and daemon protocols.

## Behavioral Invariants

### ACP transport safety

- Bounded daemon channels keep the existing frame, queue, active-handler, and byte limits.
- Invalid, cyclic, accessor-backed, or oversized values continue to fail closed before entering an unbounded SDK queue.
- Request errors exposed to SDK logging remain redacted, while unbounded public bridges retain their existing error text.
- A transport-budget failure retires the channel exactly once and triggers the existing teardown path.

### Workspace-qualified routes

- Workspace selectors continue to accept registered ids and portable absolute paths.
- Missing or inactive runtimes keep the existing `workspace_mismatch` and `workspace_runtime_unavailable` responses.
- Trusted-only routes keep returning `untrusted_workspace` without invoking their operation.
- Read routes retain their permissive cwd fallback; mutation routes retain fail-closed cwd handling.
- Route registration and middleware order in `createServeApp()` do not change.

### ACP imports

- The CLI's public exports remain available from the same CLI entrypoint.
- Internal callers import implementation and types from their owning `@qwen-code/acp-bridge` subpath.
- Startup fast paths do not acquire new ACP value imports.

### Prompt admission and retry

- Stale session owners cannot commit, retry, or restore prompt state.
- Definitely rejected, admitted, and unknown admission outcomes keep their existing UI behavior.
- Failed-message retry and turn-error retry keep their existing transcript-identity checks.
- The first extraction owns state transitions only; React rendering and daemon transport remain in `App.tsx`.

### Session attachment

- A superseded load cannot attach, detach, or report errors for the current session.
- Load watchdogs and detach cleanup remain idempotent.
- Same-session refresh, cross-session switching, missing sessions, and controlled session props retain current behavior.
- The first extraction owns pending-load and attachment epochs only; transcript replay and SSE projection stay in the provider.

## Module Direction

The new internal modules must not import their former composition roots. `bridge.ts`, `spawnChannel.ts`, `App.tsx`, and `DaemonSessionProvider.tsx` remain adapters that bind deep policy to their existing runtimes.

The new interfaces should expose decisions and transitions, not React setters, Express responses, SDK connection objects, or broad dependency bags. A proposed module fails the deletion test if removing it merely inlines a few predicates into its caller.

## Staging

1. Move ACP value projection, budgets, redaction, and guard lifecycle behind one internal transport-safety module; retain bridge and spawn-channel integration tests.
2. Add trusted workspace resolution to the existing route policy and migrate qualified routes incrementally.
3. Replace CLI-local shim imports with owning package subpaths, preserve CLI public re-exports, then delete the shim.
4. Extract the prompt-admission attempt and retry transition model, then adapt existing App callbacks to it.
5. Extract pending session-load ownership and attachment epochs, then adapt actions and the provider effect to the shared model.

## Verification

- ACP bridge: `bridge.test.ts`, `spawnChannel.test.ts`, package typecheck.
- Serve routes and imports: `workspace-route-runtime.test.ts`, affected route tests, `fast-path.test.ts`, `server-default-bridge-wiring.test.ts`, CLI typecheck.
- Web Shell: focused prompt admission and retry cases in `App.test.tsx`, package typecheck.
- WebUI: `actions.test.ts`, `attachment-lifecycle.test.ts`, focused attachment and session-switch cases in `DaemonSessionProvider.test.tsx`, package typecheck.
- Repository: build, typecheck, formatting/lint checks for changed files, and two clean diff-audit passes.

## Non-goals

- Splitting large files to meet a line-count target.
- Changing REST, ACP, SSE, or React context contracts.
- Reordering Express middleware or route registration.
- Rewriting transcript replay, right-panel orchestration, or daemon runtime disposal in this pass.
- Introducing a generic state-machine framework or a new dependency.
2 changes: 1 addition & 1 deletion docs/developers/daemon/02-serve-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@

- Event-bus primitives are imported from `@qwen-code/acp-bridge/eventBus`.
- Status primitives are imported from `@qwen-code/acp-bridge/status`.
- `serve/acp-session-bridge.ts` remains as the CLI-local compatibility facade for the broader bridge surface.
- The broader bridge surface is imported directly from its owning `@qwen-code/acp-bridge` subpaths.

## Flow

Expand Down
2 changes: 1 addition & 1 deletion docs/developers/daemon/03-acp-bridge.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ calls; it carries `clientId`, `fromLoopback: boolean`, and `promptId`.
- `MCP_RESTART_TIMEOUT_MS = 300_000` (5 min) — the bridge timeout for `/workspace/mcp/:server/restart` is intentionally large because `McpClientManager.MAX_DISCOVERY_TIMEOUT_MS` can be up to 5 min for stdio servers. A shorter deadline would produce false timeouts while the ACP child kept reconnecting in the background.
- `BridgeOptions.eventRingSize > 1_000_000` throws at construction.
- `connection.unstable_resumeSession` is exposed through the stable `session_resume` daemon capability; `unstable_session_resume` remains advertised as a deprecated compatibility alias for older SDKs. Clients should feature-detect `session_resume`.
- The bridge package is `@qwen-code/acp-bridge`. Current code imports event-bus and status primitives directly from package subpaths; `serve/acp-session-bridge.ts` remains as the CLI-local compatibility facade for the broader bridge surface.
- The bridge package is `@qwen-code/acp-bridge`. CLI code imports the implementation, status, errors, and types directly from their owning package subpaths.

## References

Expand Down
2 changes: 1 addition & 1 deletion docs/developers/qwen-serve-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -3242,7 +3242,7 @@ The connection then closes.
| `packages/cli/src/serve/server.ts` | Express app assembly, middleware ordering, and remaining direct routes |
| `packages/cli/src/serve/routes/*.ts` | Focused Express route groups, including session, SSE, workspace auth, workspace status, and file routes |
| `packages/cli/src/serve/auth.ts` | bearer + Host allowlist + CORS deny |
| `packages/cli/src/serve/acp-session-bridge.ts` | CLI-local bridge compatibility facade for spawn-or-attach, per-session FIFO, and permission registry |
| `packages/acp-bridge/src/bridge.ts` | ACP bridge orchestration for spawn-or-attach, per-session FIFO, and permission registry |
| `packages/acp-bridge/src/status.ts` | read-only daemon status wire types + `ServeErrorKind` + `BridgeTimeoutError` + `mapDomainErrorToErrorKind` |
| `packages/cli/src/serve/env-snapshot.ts` | pure helper that builds `/workspace/env` payloads from `process.*` state, including credential redaction |
| `packages/acp-bridge/src/eventBus.ts` | bounded async queue + replay ring |
Expand Down
9 changes: 4 additions & 5 deletions packages/acp-bridge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,15 @@ either form resolves to the same module at runtime. Pick by intent:

Both variants are stable across the F1 lift.

## Backward compatibility
## CLI integration

CLI code imports event-bus and in-memory channel primitives directly from
`@qwen-code/acp-bridge/eventBus` and
`@qwen-code/acp-bridge/inMemoryChannel`.

`packages/cli/src/serve/acp-session-bridge.ts` remains as the CLI-local
compatibility facade for the broader bridge surface, forwarding previously
exported symbols (`createHttpAcpBridge`, `defaultSpawnChannelFactory`,
`BridgeClient`, typed errors, and type aliases) from the lifted subpaths.
The CLI imports the broader bridge surface from its owning package subpaths.
Its public serve entrypoint still re-exports the supported bridge factories,
types, errors, and status helpers for downstream compatibility.

## See also

Expand Down
Loading
Loading