Skip to content

feat: unify external source control and runtime containment#1661

Merged
limityan merged 1 commit into
GCWing:mainfrom
limityan:yanzhn/external-source-control-plane
Jul 21, 2026
Merged

feat: unify external source control and runtime containment#1661
limityan merged 1 commit into
GCWing:mainfrom
limityan:yanzhn/external-source-control-plane

Conversation

@limityan

@limityan limityan commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add one versioned ExternalSourceControlV1 contract for catalog state, host capabilities, closed common actions, typed errors, recovery actions, causation, logs, and metrics.
  • Expose the same control semantics through Desktop/Web, CLI/TUI, and Peer Host; keep Server explicitly read-only and reject mutations before action parsing.
  • Replace four app-local refresh task maps with one external-source control plane containing four typed discovery lanes with generation checks, timeout reuse, stale-completion protection, and single-observer recovery after an abandoned blocking worker exits.
  • Add per-process/execution-domain Safe Mode that keeps discovery and commands visible while retiring managed Tool, Subagent, and MCP execution routes.
  • Consolidate worker, local MCP, Node probe, and Flashgrep child lifecycle into services-core::process_tree, using process groups on Unix and fail-closed kill-on-close Job Objects on Windows.
  • Align extension architecture and OpenCode compatibility documents with the implemented control boundary and the current Bun/Node runtime direction.

Why

External-source state and actions previously differed by host and refresh kind. That made GUI, TUI, Peer, and Server behavior harder to reason about, left no shared Safe Mode, and allowed process cleanup semantics to diverge between executable integrations. This change creates one stable cross-host contract and one reusable lifecycle owner while preserving typed ecosystem adapters and product policy boundaries.

Architecture impact

Concern Before After
Cross-host control Legacy catalog/provider-specific messages One versioned v1 DTO and three closed common actions
Refresh scheduling Four core task-map paths One control plane with four typed lanes
Safe Mode No shared control Volatile state per execution domain/workspace, projected consistently to supported hosts
Process cleanup Direct-child or consumer-specific tree cleanup One services-core process-tree owner for worker, MCP, Node probe, and Flashgrep
Server mutation No explicit shared capability contract Read-only capability projection; mutation rejected at the boundary

Contracts remain behavior-light. Assembly owns policy, generation, and product projection; external-source coordinators own provider-neutral refresh state; services own concrete OS process lifecycle. Public API budgets and feature-owner checks were updated to keep those boundaries enforceable.

User impact

  • Settings and TUI can inspect shared external-source health, refresh sources, enable/disable a source, and toggle Safe Mode where the host supports the action.
  • Existing Settings actions that reveal an external source file or directory continue to resolve sources by stable identity through the same control-plane owner. A dedicated Host capability enables the action only on local Desktop; Server and Peer fail closed, while reveal failures use the shared typed error and recovery UI.
  • TUI adds /extensions status, refresh, source enable/disable, and Safe Mode actions without adding another scheduler; zero-item provider failures retain support, bounded Issues, and Recovery output.
  • Remote/Peer projections use the same DTO rather than reimplementing action and error semantics.
  • WebSocket code/data and Peer message-only typed errors both retain their categories, stages, correlation/causation ids, and recovery actions through the shared API client.
  • Failures return consistent typed categories and recovery actions while bounded logs and TUI summaries avoid leaking workspace paths or raw diagnostic details.

Validation

  • cargo check --workspace
  • cargo test -p bitfun-services-core process_tree
  • cargo test -p bitfun-external-sources
  • cargo test -p bitfun-core external_sources
  • cargo test -p bitfun-product-domains --features external-sources --test external_source_contracts (36 tests)
  • cargo test -p bitfun-cli --bin bitfun (292 tests)
  • cargo test -p bitfun-server external_sources -- --nocapture (6 tests)
  • cargo test -p bitfun-desktop remote_workspace_policy -- --nocapture (3 tests)
  • pnpm --dir src/web-ui run test:run src/infrastructure/api/service-api/ApiClient.test.ts src/infrastructure/api/service-api/ExternalSourcesAPI.test.ts src/infrastructure/config/components/ExternalSourcesConfig.test.tsx src/infrastructure/config/externalSourcePresentation.test.ts (85 tests)
  • pnpm run type-check:web
  • pnpm run i18n:audit
  • pnpm run i18n:contract:test (37 tests)
  • node scripts/check-core-boundaries.mjs
  • pnpm run check:repo-hygiene
  • git diff --check gcwing/main...HEAD

Residual risks and exclusions

  • Process-tree supervision provides deterministic descendant cleanup, not filesystem/network isolation or CPU/memory/process-count limits.
  • Blocking provider discovery is bounded to eight process-wide workers. Eight distinct permanently blocked providers can exhaust that budget until a worker exits or the Host restarts; repeated refreshes cannot create duplicate workers or permits for a blocked provider.
  • Safe Mode is intentionally volatile in this PR; persistence and broader policy administration need an explicit product decision.
  • Server-side mutation and new SSH Remote execution flows are intentionally excluded.
  • Package plugin execution, broader TypeScript runtime support, and OpenCode/Claude Code/Codex hook parity remain follow-up PR work.
  • OpenCode v2 is not yet the stable release boundary. The design therefore remains runtime-adapter based: current Bun support is preserved while Node SEA can be added without making product policy depend on either runtime.

The local three-PR scope/design working document is intentionally excluded from this PR.

@limityan
limityan force-pushed the yanzhn/external-source-control-plane branch 2 times, most recently from 3651a11 to 7ce7a28 Compare July 21, 2026 12:44
Add a versioned cross-host control contract with Safe Mode and shared refresh coordination. Reuse one managed process-tree owner across executable integrations and align the extension architecture documentation.
@limityan
limityan force-pushed the yanzhn/external-source-control-plane branch from 7ce7a28 to a4de3d8 Compare July 21, 2026 12:55
@limityan
limityan merged commit 0c5febe into GCWing:main Jul 21, 2026
5 checks passed
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