a789495a98
FreeBSD Smoke / FreeBSD Smoke (x86_64) (push) Has been cancelled
CI / Quality Guardrails (push) Has been cancelled
CI / Build & Test (macos-latest) (push) Has been cancelled
CI / Build & Test (ubuntu-latest) (push) Has been cancelled
CI / Build & Test (windows-latest) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / PowerShell Syntax (push) Has been cancelled
CI / Windows Cross-Target Check (Linux) (push) Has been cancelled
180 lines
6.4 KiB
Markdown
180 lines
6.4 KiB
Markdown
# Unified Self-Dev / Normal Server Plan
|
|
|
|
> Status: **Implemented.**
|
|
>
|
|
> This document is preserved as a historical design/rollout plan. The current
|
|
> architecture uses a single shared server, with self-dev handled as a
|
|
> session-local canary capability rather than a separate dedicated daemon/socket.
|
|
> Any references below to `/tmp/jcode-selfdev.sock`, `canary-wrapper`, or
|
|
> `JCODE_SELFDEV_MODE` describe the pre-merge architecture or transition steps,
|
|
> not the current runtime design.
|
|
|
|
## Goal
|
|
|
|
Reduce RAM usage by removing the dedicated self-dev daemon/socket pair and treating self-dev as a **session capability** on the normal shared server.
|
|
|
|
Today, normal sessions and self-dev sessions can end up with separate long-lived server processes, which duplicates:
|
|
|
|
- Tokio runtime overhead
|
|
- allocator heap / fragmentation footprint
|
|
- MCP pool state
|
|
- embedding/model lifecycle machinery
|
|
- event buffers, registries, session maps, swarm maps
|
|
- general server baseline RSS
|
|
|
|
## Current Architecture
|
|
|
|
### Normal mode
|
|
- Main socket: runtime `jcode.sock`
|
|
- Debug socket: runtime `jcode-debug.sock`
|
|
- Startup path: `jcode` -> default client flow -> spawn `jcode serve` if needed
|
|
|
|
### Self-dev mode
|
|
- Main socket: `/tmp/jcode-selfdev.sock`
|
|
- Debug socket: `/tmp/jcode-selfdev-debug.sock`
|
|
- Startup path:
|
|
- repo auto-detection or `jcode self-dev`
|
|
- `cli/selfdev.rs::run_self_dev()`
|
|
- exec into `canary-wrapper`
|
|
- wrapper ensures self-dev server exists on dedicated socket
|
|
- wrapper launches TUI client against that socket
|
|
|
|
## Key Finding From Code Inspection
|
|
|
|
The runtime already supports **per-session self-dev state**:
|
|
|
|
- protocol `Subscribe { working_dir, selfdev }`
|
|
- server subscribe handling can mark only that session as canary/self-dev
|
|
- `selfdev` tool availability is already gated on `session.is_canary`
|
|
- prompt additions are already gated on `session.is_canary`
|
|
- clear/resume/headless flows already preserve or infer canary state per session
|
|
|
|
This means the main remaining split is not the session model, but the **startup / reload / wrapper plumbing**.
|
|
|
|
## Target Architecture
|
|
|
|
### One shared server
|
|
- Main socket: runtime `jcode.sock`
|
|
- Debug socket: runtime `jcode-debug.sock`
|
|
- Self-dev sessions connect to the same server as normal sessions
|
|
|
|
### Self-dev becomes session-local
|
|
A client is self-dev if any of the following are true:
|
|
- explicit `jcode self-dev`
|
|
- current working directory is the jcode repo (auto-detected)
|
|
- resumed session is already canary
|
|
|
|
That client connects to the shared server and sends:
|
|
- `working_dir`
|
|
- `selfdev: true`
|
|
|
|
The server then:
|
|
- marks the session canary
|
|
- registers selfdev tools for that session
|
|
- includes selfdev prompt additions for that session only
|
|
|
|
### Debug socket
|
|
With one shared server, there is one shared debug socket.
|
|
|
|
Consequences:
|
|
- no dedicated self-dev debug socket
|
|
- debug tooling sees both normal and self-dev sessions from the same server
|
|
- selfdev-sensitive actions remain gated by target session canary state
|
|
|
|
## Important Policy Decision
|
|
|
|
If a self-dev session triggers a reload, it reloads the **shared server**.
|
|
That means all clients reconnect.
|
|
|
|
This is the cleanest design for RAM savings.
|
|
|
|
The binary chosen for reload should depend on the **triggering session**, not a server-global self-dev mode flag:
|
|
|
|
- normal session reload -> stable / launcher candidate
|
|
- canary session reload -> repo / canary candidate
|
|
|
|
## Implementation Phases
|
|
|
|
### Phase 1 - Client-side self-dev on shared server path
|
|
**Goal:** stop repo auto-detection from forcing a separate self-dev daemon.
|
|
|
|
Changes:
|
|
- do not auto-divert repo startup into `canary-wrapper`
|
|
- introduce a client-only self-dev signal (separate from server self-dev env)
|
|
- keep using normal server spawn/connect path
|
|
- continue sending `Subscribe { selfdev: true }`
|
|
- prevent the shared server child process from inheriting the client-only self-dev env
|
|
- stop server self-dev detection from inferring self-dev based on current working directory
|
|
|
|
Expected result:
|
|
- opening jcode inside the repo uses the shared server path by default
|
|
- session still becomes canary/self-dev
|
|
- explicit `jcode self-dev` command may still use legacy wrapper temporarily
|
|
|
|
### Phase 2 - Move explicit `jcode self-dev` onto shared server path
|
|
**Goal:** make explicit self-dev command use the same shared-server flow.
|
|
|
|
Changes:
|
|
- simplify `cli/selfdev.rs::run_self_dev()`
|
|
- keep optional `cargo build --release`
|
|
- set client-only self-dev mode
|
|
- connect through normal client/server startup path
|
|
- remove need for `canary-wrapper` in standard usage
|
|
|
|
Expected result:
|
|
- both auto-detected self-dev and explicit `jcode self-dev` share one server
|
|
|
|
### Phase 3 - Session-targeted reload selection
|
|
**Goal:** remove server-global self-dev assumptions from reload/update behavior.
|
|
|
|
Changes:
|
|
- include triggering session context in reload handling
|
|
- choose server exec target based on triggering session canary state
|
|
- always run reload monitor on the shared server, but authorize via session state / request policy
|
|
|
|
Expected result:
|
|
- one shared server can still reload into the right binary
|
|
|
|
### Phase 4 - Remove dedicated self-dev socket assumptions
|
|
**Goal:** fully retire the separate socket model.
|
|
|
|
Changes:
|
|
- deprecate `/tmp/jcode-selfdev.sock` and `/tmp/jcode-selfdev-debug.sock`
|
|
- update docs, tests, and scripts that probe self-dev via separate sockets
|
|
- simplify debug/test tooling to use the shared debug socket
|
|
|
|
## Risks / Tradeoffs
|
|
|
|
### Shared reload impact
|
|
A self-dev-triggered reload affects all clients on the shared server.
|
|
This is the main behavior change and the key tradeoff for RAM savings.
|
|
|
|
### Legacy tooling assumptions
|
|
Some scripts and tests currently prefer the self-dev debug socket path and will need updating.
|
|
|
|
### Scattered env-based logic
|
|
There are multiple `JCODE_SELFDEV_MODE` checks across startup, hot reload, and server behavior; these need to be separated into:
|
|
- client self-dev request
|
|
- server self-dev mode (legacy / compatibility)
|
|
- session canary capability
|
|
|
|
## Files Likely To Change
|
|
|
|
- `src/cli/dispatch.rs`
|
|
- `src/cli/selfdev.rs`
|
|
- `src/cli/hot_exec.rs`
|
|
- `src/server.rs`
|
|
- `src/server/reload.rs`
|
|
- `src/server/client_session.rs`
|
|
- `src/tui/mod.rs`
|
|
- `src/tui/backend.rs`
|
|
- `docs/SERVER_ARCHITECTURE.md`
|
|
- debug/test scripts that assume separate self-dev sockets
|
|
|
|
## Recommended Order
|
|
|
|
1. Land Phase 1 foundations and shared-path client self-dev
|
|
2. Land explicit `jcode self-dev` shared-path behavior
|
|
3. Refactor reload/update selection to be session-targeted
|
|
4. Remove legacy wrapper/socket assumptions and update tests/docs
|