diff --git a/AGENTS-CN.md b/AGENTS-CN.md index 040e045b1d..4ce7bef07b 100644 --- a/AGENTS-CN.md +++ b/AGENTS-CN.md @@ -101,6 +101,11 @@ pnpm run desktop:build:nsis:fast # Windows 安装器,release-fast profile ## 全局规则 +### 流程产物 + +- 不要新增或更新 `docs/superpowers/**` 下的文件。临时计划、设计和实现过程文档仅保留在本地; + 需要长期维护的架构或功能事实应合并到对应的已有文档,用户使用说明应放到所属应用的 README。 + ### 国际化 - Locale id、alias、fallback 和各形态默认语言统一由 diff --git a/AGENTS.md b/AGENTS.md index 9b46c75074..fd0108c892 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -106,6 +106,13 @@ type error and a bundling error can surface in either order; both are prefixed ## Global rules +### Process artifacts + +- Do not add or update files under `docs/superpowers/**`. Keep temporary + planning, design, and implementation-process artifacts local. Move durable + architecture or feature facts into the existing document for that area, and + put user-facing guidance in the owning app README. + ### Internationalization - Locale ids, aliases, fallback rules, and surface defaults are owned by diff --git a/docs/features/session-runtime-usage-report-design.md b/docs/features/session-runtime-usage-report-design.md index 18dff82bea..08d32d3cd9 100644 --- a/docs/features/session-runtime-usage-report-design.md +++ b/docs/features/session-runtime-usage-report-design.md @@ -218,7 +218,8 @@ It also provides summary aggregation by model and session. ### Existing CLI surfaces - CLI chat mode already recognizes slash commands. -- `/history` already shows basic session statistics. +- `/sessions` opens the session browser; `/resume`, `/continue`, and `/history` are aliases. +- `/status` shows current runtime facts and the latest primary-model request observed by the TUI. - CLI session messages and tool cards already persist tool call count and tool duration. ## Original Gaps and Current Implementation Status @@ -277,7 +278,8 @@ Risk if skipped: Missing: - CLI `AgentEvent` does not currently surface token usage, model round timing, or context compression as first-class events. -- CLI `/history` is basic and not equivalent to `/usage`. +- CLI `/status` reports the latest observed request rather than cumulative session usage; `/history` + is an alias for the session browser and is not a usage-report entrypoint. Required change: @@ -1206,7 +1208,7 @@ Steps: Functional guardrails: - Do not make `/usage` asynchronous model work. -- Do not replace `/history`; `/history` can remain the lightweight legacy command until a separate cleanup. +- Do not overload `/sessions` or its aliases with usage-report behavior. - Do not require Desktop-only state for CLI reports. - Do not make the CLI command depend on a Tauri API or Desktop workspace state. - Do not print sensitive raw tool details that Desktop would redact. @@ -1224,7 +1226,8 @@ Verification: - CLI `/help` includes `/usage`. - `/usage` output appears in chat without a model request. -- Existing `/history`, `/clear`, and normal message send behavior still work. +- Existing `/sessions` aliases, `/new` and `/clear` fresh-session behavior, and normal message send + behavior still work. - CLI output redacts the same sensitive detail categories as Desktop P0. ### Task 6: Desktop `/usage` command and local Markdown insertion diff --git a/docs/superpowers/plans/2026-07-30-tui-manual-context-compaction.md b/docs/superpowers/plans/2026-07-30-tui-manual-context-compaction.md deleted file mode 100644 index 32ee843002..0000000000 --- a/docs/superpowers/plans/2026-07-30-tui-manual-context-compaction.md +++ /dev/null @@ -1,313 +0,0 @@ -# TUI Manual Context Compaction Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Add OpenCode-compatible `/compact` and `/summarize` commands to Embedded and Shared TUI through one runtime-owned, cancellable, audited manual-compaction lifecycle. - -**Architecture:** Add one stable session-compaction port to `bitfun-runtime-ports`, inject it into `AgentRuntime`, and implement it in Core by starting an owned maintenance task with a caller-supplied turn ID. Project that port through private Shared TUI IPC v8 and convert existing compression events into the existing TUI `ContextCompression` tool card. - -**Tech Stack:** Rust, Tokio, Serde, Ratatui, BitFun Agent Runtime ports, private local IPC. - -## Global Constraints - -- Primary command is `/compact`; the only compatibility alias is `/summarize`. -- Preserve idle-only admission and do not introduce queueing. -- Do not add a keyboard shortcut or multi-key keymap support. -- Do not change compression prompts, algorithms, automatic thresholds, or artifact schemas. -- Do not change Relay, Server, Peer, ACP, SDK Host, Web UI, extensions, or customization behavior. -- Shared IPC remains private to the first-party TUI and moves from protocol version 7 to 8. -- Caller-generated turn IDs must preserve disconnect cancellation and outcome-unknown behavior. -- Idle admission must be atomic with ordinary dialog-turn admission, and the compaction snapshot must be captured only after the maintenance turn owns the Session. -- Planning may be cancelled; once the atomic commit gate wins, context commit must finish without exposing a false idle state. -- The maintenance Turn is visible in the authoritative transcript but remains excluded from model context; live and restored tool payloads retain the same compression identity and `applied` state. -- Keep the combined PR below 8k changed lines and squash to one final commit. - ---- - -### Task 1: Add the narrow Runtime contract and facade - -**Files:** -- Modify: `src/crates/contracts/runtime-ports/src/lib.rs` -- Modify: `src/crates/execution/agent-runtime/src/runtime.rs` -- Modify: `src/crates/execution/agent-runtime/src/sdk.rs` - -**Interfaces:** -- Produces: `AgentSessionCompactionRequest`, `AgentSessionCompactionResult`, `AgentSessionCompactionPort`. -- Produces: `AgentRuntimeBuilder::with_session_compaction_port` and `AgentRuntime::start_session_compaction`. - -- [x] **Step 1: Write failing Runtime tests** - -Add a recording provider and tests proving that the runtime forwards exact session/turn identities and returns typed `NotAvailable` when the port is absent: - -```rust -#[derive(Default)] -struct RecordingCompactionPort { - requests: Mutex>, -} - -#[async_trait::async_trait] -impl AgentSessionCompactionPort for RecordingCompactionPort { - async fn start_session_compaction( - &self, - request: AgentSessionCompactionRequest, - ) -> PortResult { - self.requests.lock().unwrap().push(request.clone()); - Ok(AgentSessionCompactionResult { - session_id: request.session_id, - turn_id: request.turn_id, - }) - } -} -``` - -- [x] **Step 2: Verify RED** - -Run: `cargo test -p bitfun-agent-runtime session_compaction -- --nocapture` - -Expected: compilation fails because the request, result, port, builder method, and runtime method do not exist. - -- [x] **Step 3: Implement the minimal contract and forwarding path** - -Add serializable camelCase DTOs and the narrow async trait in `runtime-ports`; add the optional port field, builder injection, debug projection, and forwarding method in `AgentRuntime`; re-export only these stable types through `sdk`. - -- [x] **Step 4: Verify GREEN** - -Run: - -```powershell -cargo test -p bitfun-runtime-ports -cargo test -p bitfun-agent-runtime session_compaction -- --nocapture -``` - -Expected: both commands pass. - -### Task 2: Move manual compaction into the owned Core turn lifecycle - -**Files:** -- Modify: `src/crates/assembly/core/src/agentic/coordination/coordinator.rs` -- Modify: `src/crates/assembly/core/src/agentic/execution/execution_engine.rs` -- Modify: `src/crates/assembly/core/src/service_agent_runtime.rs` - -**Interfaces:** -- Consumes: `AgentSessionCompactionPort` and its request/result DTOs. -- Produces: one accepted maintenance task registered with active-session execution, settlement, cancellation, and an atomic planning/commit gate. -- Preserves: `ConversationCoordinator::compact_session_manually(String) -> BitFunResult<()>` for Desktop. - -- [x] **Step 1: Write failing gate and assembly tests** - -Add tests proving: - -```rust -let gate = ManualCompactionCommitGate::planning(); -assert!(gate.try_cancel()); -assert!(!gate.try_begin_commit()); - -let gate = ManualCompactionCommitGate::planning(); -assert!(gate.try_begin_commit()); -assert!(!gate.try_cancel()); -``` - -Add a source/assembly contract test proving all Core TUI-capable runtime builders register `with_session_compaction_port`. - -- [x] **Step 2: Verify RED** - -Run: `cargo test -p bitfun-core manual_compaction --features product-full -- --nocapture` - -Expected: fails because the commit gate and runtime-port implementation do not exist. - -- [x] **Step 3: Implement the start/task split** - -Refactor the current synchronous body into: - -```rust -async fn start_manual_compaction_task( - &self, - session_id: String, - requested_turn_id: Option, -) -> BitFunResult; - -pub async fn compact_session_manually(&self, session_id: String) -> BitFunResult<()>; -``` - -`ManualCompactionTask` contains the accepted turn ID and a private oneshot completion receiver. The runtime port calls the start function with `Some(request.turn_id)` and drops the receiver; the Desktop compatibility method awaits it. - -Register before spawn: - -- `register_session_execution` lease; -- `turn_settlements.register_accepted` registration; -- `CancellationToken` in `ExecutionEngine`; -- `ManualCompactionCommitGate` in a coordinator map keyed by turn ID. - -The owned task persists completed, failed, or cancelled state exactly once, removes the gate and cancel token, and only then releases settlement/active-execution guards. Maintenance and ordinary dialog turns share one mutation-locked idle admission path; context is captured after that admission so a racing user turn cannot be omitted from the committed replacement. - -- [x] **Step 4: Make planning cancellation-aware** - -Pass the cancellation token and commit gate to `compact_session_context`. Wrap only `build_planned_compression_result` in cancellation selection. After planning, atomically call `try_begin_commit`; if cancellation already won, return `BitFunError::Cancelled`. Once commit wins, finish the existing replacement/persistence/event tail without another cancellation branch. - -Teach `cancel_dialog_turn` to consult the manual gate before changing state: planning cancellation follows the existing cancellation path; commit-winning turns ignore the late cancellation request and retain processing state until completion. - -- [x] **Step 5: Inject the port and verify GREEN** - -Register the coordinator as `AgentSessionCompactionPort` in the shared Core runtime builder paths, then run: - -```powershell -cargo test -p bitfun-core manual_compaction --features product-full -- --nocapture -cargo test -p bitfun-agent-runtime session_compaction -- --nocapture -``` - -Expected: tests pass with one terminal owner and no duplicate state transition. - -The completion finalizer treats post-commit turn/session persistence failures as an explicit failed terminal result while retaining an idle in-memory Session. Persisted transcript projection includes the maintenance Turn and its exact tool payload without restoring that Turn into model-visible context. - -### Task 3: Extend private Shared TUI IPC to protocol v8 - -**Files:** -- Modify: `src/crates/adapters/agent-runtime-ipc/src/protocol.rs` -- Modify: `src/crates/adapters/agent-runtime-ipc/src/operation.rs` -- Modify: `src/crates/adapters/agent-runtime-ipc/src/server.rs` -- Modify: `src/crates/adapters/agent-runtime-ipc/src/tests/protocol_contracts.rs` -- Modify: `src/crates/adapters/agent-runtime-ipc/src/tests/shared_controller.rs` -- Modify: `src/apps/cli/src/shared_runtime.rs` - -**Interfaces:** -- Consumes: `AgentSessionCompactionRequest` and `AgentRuntime::start_session_compaction`. -- Produces: `RuntimeIpcOperation::CompactSession`, returning the existing `TurnAccepted` result. - -- [x] **Step 1: Write failing protocol/rules/controller tests** - -Test JSON round-trip and exact operation rules: - -```rust -let operation = RuntimeIpcOperation::CompactSession { - request: AgentSessionCompactionRequest { - session_id: "session-1".into(), - turn_id: "turn-compact-1".into(), - }, -}; -let rules = operation.rules(); -assert_eq!(rules.session_requirement, RuntimeIpcSessionRequirement::CurrentController); -assert!(rules.requires_idle); -assert!(rules.side_effecting); -``` - -Extend the shared-controller fixture to prove the supplied turn ID becomes the connection's active turn and disconnect triggers cancellation. - -- [x] **Step 2: Verify RED** - -Run: `cargo test -p bitfun-agent-runtime-ipc compact -- --nocapture` - -Expected: compilation fails because `CompactSession` is not defined and protocol remains v7. - -- [x] **Step 3: Implement protocol v8 operation** - -Add the enum variant, current-controller/idle/side-effecting rules, `session_id` projection, provisional-turn extraction shared with `SubmitTurn`, handler dispatch to `AgentRuntime`, and `TurnAccepted` result. Increment `PROTOCOL_VERSION` to 8 and update explicit protocol assertions. - -- [x] **Step 4: Verify GREEN** - -Run: `cargo test -p bitfun-agent-runtime-ipc compact -- --nocapture` - -Expected: protocol, controller, disconnect, and cancellation tests pass. - -### Task 4: Add exact competitor-compatible TUI commands and feedback - -**Files:** -- Modify: `src/apps/cli/src/actions.rs` -- Modify: `src/apps/cli/src/agent/runtime_client.rs` -- Modify: `src/apps/cli/src/modes/chat/commands.rs` -- Modify: `src/apps/cli/src/modes/chat/run.rs` -- Modify: `src/apps/cli/src/chat_state.rs` -- Modify: `src/apps/cli/src/modes/chat/tests.rs` - -**Interfaces:** -- Consumes: runtime/IPC compaction start operation and authoritative `AgenticEvent` compression events. -- Produces: `ActionHandler::CompactSession`, aliases `/compact` and `/summarize`, and live `ContextCompression` tool-card projection. - -- [x] **Step 1: Write failing action and argument tests** - -Prove both aliases resolve to one idle-only action in Embedded and Shared modes, no invented alias exists, and non-empty arguments return `Usage: /compact` without starting runtime work. - -- [x] **Step 2: Write failing runtime-client parity tests** - -Add a focused test/source contract proving Embedded calls `runtime.start_session_compaction(request)` and Shared sends `RuntimeIpcOperation::CompactSession { request }`, both with a caller-generated stable turn ID. - -- [x] **Step 3: Write failing compression projection tests** - -Add a pure projection helper and tests proving: - -- `ContextCompressionStarted` creates a running `ContextCompression` tool card; -- `ContextCompressionCompleted` records tokens before/after, summary source, duration, and success; -- `ContextCompressionFailed` records failure; -- unrelated sessions/turns do not mutate current TUI state. - -- [x] **Step 4: Verify RED** - -Run: `cargo test -p bitfun-cli compact -- --nocapture` - -Expected: tests fail because the action, runtime client, and event projection do not exist. - -- [x] **Step 5: Implement the minimal TUI slice** - -Add the exact action aliases, call the runtime client through the existing synchronous dispatch boundary, and set an immediate accepted/error status. Convert compression events to existing `ToolEventData` values and feed `ChatState::handle_tool_event`; do not add another compaction UI model. - -- [x] **Step 6: Verify GREEN** - -Run: - -```powershell -cargo test -p bitfun-cli compact -- --nocapture -cargo test -p bitfun-cli -``` - -Expected: all CLI tests pass in both runtime projections. - -### Task 5: Align architecture constraints and validate the combined PR - -**Files:** -- Modify: `src/crates/adapters/agent-runtime-ipc/AGENTS.md` -- Modify: `docs/architecture/agent-runtime-deployment-design.md` -- Modify: `docs/architecture/cli-product-line-design.md` -- Modify: `docs/superpowers/plans/2026-07-30-tui-manual-context-compaction.md` - -- [x] **Step 1: Update the closed operation contract** - -Document protocol v8, the single TUI consumer, current-controller/idle requirements, caller-provided turn identity, disconnect cancellation, and explicit non-goals. Do not describe the private wire as a public SDK or server protocol. - -- [x] **Step 2: Mark completed plan steps and self-review the plan/spec** - -Check for placeholders, contradictory command names, protocol version drift, and scope leakage. - -- [x] **Step 3: Run required verification** - -```powershell -cargo test -p bitfun-runtime-ports -cargo test -p bitfun-agent-runtime -cargo test -p bitfun-agent-runtime-ipc -cargo test -p bitfun-cli -cargo check -p bitfun-core --features product-full -node scripts/check-core-boundaries.mjs -git diff --check -``` - -Expected: every command passes. If a broader pre-existing failure remains, capture exact evidence and ensure focused changed-path tests pass. - -- [x] **Step 4: Audit size and scope** - -Run: - -```powershell -git diff --stat gcwing/main...HEAD -git diff --numstat gcwing/main...HEAD -git status -sb -``` - -Expected: only PR1+PR2 files are present and total changed lines remain below 8k. - -- [x] **Step 5: Independent adversarial review and repair** - -Ask an isolated reviewer to inspect the combined diff for ownership leaks, cancellation/commit races, Shared IPC controller gaps, false terminal states, command incompatibility, transcript divergence, and unnecessary scope. Fix every actionable finding and rerun affected checks. - -Review repairs covered atomic dialog/maintenance admission, post-commit terminal finalization, persisted maintenance transcript restoration, and live/restored compression identity plus `applied` parity. - -- [x] **Step 6: Squash, push fork, and open Draft PR** - -Create one final conventional commit, push only to `origin` (`limityan/BitFun`), and open a Draft PR against `GCWing/BitFun:main` with design, impact, risk, and validation details. diff --git a/docs/superpowers/plans/2026-07-30-tui-session-context-status.md b/docs/superpowers/plans/2026-07-30-tui-session-context-status.md deleted file mode 100644 index 2586755e93..0000000000 --- a/docs/superpowers/plans/2026-07-30-tui-session-context-status.md +++ /dev/null @@ -1,63 +0,0 @@ -# TUI Session and Context Status Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Make CLI TUI session navigation, fresh-session aliases, and model-context status truthful in both Embedded and Shared runtimes. - -**Architecture:** Keep the change inside the CLI adapter. Project the existing `TokenUsageUpdated` event into a small UI-owned snapshot for the latest primary-model request, render that snapshot without claiming it is cumulative session usage, and reuse the existing session picker for history. No new runtime owner, transport request, or persistence contract is introduced. - -**Tech Stack:** Rust, Ratatui, existing BitFun CLI action registry and agentic event contracts. - -## Global Constraints - -- Do not modify Relay, shared IPC, Core runtime behavior, Web UI, or extension/customization paths. -- Preserve the existing `/usage` command as the authoritative cumulative report where supported. -- Keep `/status` transient; it must not add a persisted conversation message. -- Treat subagent usage and last-round usage as distinct from session totals. -- Keep the total PR below 8k changed lines and prefer one final commit. - ---- - -### Task 1: Correct slash-command semantics - -**Files:** -- Modify: `src/apps/cli/src/actions.rs` -- Modify: `src/apps/cli/src/modes/chat/commands.rs` -- Modify: `src/apps/cli/src/ui/startup.rs` - -- [x] Add failing registry tests proving `/status` is available in Shared TUI, `/sessions` exposes OpenCode-compatible `/resume` and `/continue` aliases, `/history` resolves to the existing session picker for compatibility, and `/clear` resolves to the same new-session action as `/new`. -- [x] Run the focused action tests and confirm they fail for the missing behavior. -- [x] Add the `Status` handler, route `/history` through `Sessions`, add the OpenCode-compatible session aliases, and remove the misleading history-statistics action. -- [x] Remove the TUI-only clear-conversation action and make `/clear` an alias for `/new`, matching OpenCode's fresh-session semantics without inventing a new clear-screen command. -- [x] Run the focused action tests and confirm they pass. - -### Task 2: Preserve truthful primary-model context facts - -**Files:** -- Modify: `src/apps/cli/src/chat_state.rs` -- Modify: `src/apps/cli/src/modes/chat/run.rs` -- Add: `src/apps/cli/src/ui/chat/status.rs` -- Modify: `src/apps/cli/src/modes/chat.rs` -- Modify: `src/apps/cli/src/ui/chat.rs` - -- [x] Add failing unit tests for the latest primary-model usage snapshot and status text, including unknown context, known context percentage, and no session-total claim. -- [x] Run the focused tests and confirm they fail for the missing projection and formatter. -- [x] Replace `ChatMetadata::total_tokens` with a UI-owned `ModelTokenUsageSnapshot` containing only stable event facts used by the TUI. -- [x] Ignore subagent usage and unrelated turn events while retaining the latest primary-model request facts. -- [x] Add a pure transient `/status` formatter covering session, runtime, workspace, approval mode, and observed context facts. -- [x] Run the focused tests and confirm they pass. - -### Task 3: Wire the popup and status bar, then verify the PR - -**Files:** -- Modify: `src/apps/cli/src/modes/chat/commands.rs` -- Modify: `src/apps/cli/src/ui/chat/render.rs` -- Modify: `src/apps/cli/src/ui/command_menu.rs` -- Modify: `src/apps/cli/src/ui/command_palette.rs` - -- [x] Add failing tests for compact status-bar text with known, unknown, and missing context-window values. -- [x] Run the focused tests and confirm they fail for the old token-total display. -- [x] Wire `/status` to the existing transient info popup in both runtime modes. -- [x] Replace all `Tokens:` session-total labels with truthful latest-request context text, omitting unavailable data rather than showing zero. -- [x] Run `cargo test -p bitfun-cli`, `cargo check -p bitfun-cli`, and `git diff --check`; run `cargo fmt -p bitfun-cli -- --check` and record its unrelated baseline drift. -- [x] Adversarially review the full diff for runtime parity, active-turn behavior, misleading copy, accidental persistence, duplicate aliases, and out-of-scope files; fix all actionable findings. diff --git a/docs/superpowers/specs/2026-07-30-tui-manual-context-compaction-design.md b/docs/superpowers/specs/2026-07-30-tui-manual-context-compaction-design.md deleted file mode 100644 index d5d8063b9d..0000000000 --- a/docs/superpowers/specs/2026-07-30-tui-manual-context-compaction-design.md +++ /dev/null @@ -1,195 +0,0 @@ -# TUI Manual Context Compaction Design - -**Status:** Approved for implementation by the 2026-07-30 request to complete PR2 and combine it with the existing TUI session/status work. - -## Goal - -Expose BitFun's existing manual context-compaction capability through both Embedded and Shared TUI without duplicating compression policy or weakening session ownership, cancellation, persistence, or audit semantics. - -The user entry points are `/compact` and the OpenCode-compatible alias `/summarize`. No BitFun-specific synonym or new shortcut is introduced. - -## Current State - -- Core already performs manual compaction as a persisted `ManualCompaction` maintenance turn and emits context-compression plus dialog-turn lifecycle events. -- Desktop already calls `ConversationCoordinator::compact_session_manually`. -- The CLI action registry has no manual-compaction action. -- `AgentRuntime`, runtime ports, and private Shared TUI IPC do not expose manual compaction. -- The Shared TUI protocol is version 7 and its documented closed operation set does not include compaction. -- Manual compaction currently waits for the model operation inline and is not registered in the same active-turn, settlement, and cancellation lifecycle used by TUI dialog turns. - -## Competitor Compatibility - -OpenCode uses `/compact` as the primary command and `/summarize` as an alias. Codex also exposes `/compact` as a dedicated runtime operation instead of sending it as an ordinary model prompt. - -BitFun will match those command names and dedicated-operation semantics. It will retain BitFun's current idle-only admission rule rather than introducing Codex-style queuing. OpenCode's `Ctrl+X C` shortcut is intentionally deferred because BitFun's keymap currently supports a single key chord; inventing a different shortcut or adding leader sequences would be unrelated scope. - -## Considered Approaches - -### 1. Send `/compact` as a normal prompt - -Rejected. This would make compression depend on model interpretation, pollute model-visible context, and bypass the existing maintenance-turn audit path. - -### 2. Call Core directly from the CLI - -Rejected. Embedded and Shared TUI would diverge, the CLI would depend on the concrete coordinator, and cancellation/disconnect ownership would remain incomplete. - -### 3. Add one narrow runtime-owned compaction capability - -Selected. A typed runtime port starts the existing Core maintenance operation, and the private Shared IPC projects exactly that capability to its only consumer, the first-party TUI. - -## Architecture - -```text -/compact | /summarize - | - v -CLI Action Registry - | - v -CliAgentRuntimeClient - | | - | Embedded | Shared - v v -AgentRuntime Runtime IPC v8 - \ / - v v -AgentSessionCompactionPort - | - v -ConversationCoordinator - | - v -ExecutionEngine compaction plan -> cancellation gate -> atomic commit tail - | - v -Authoritative events and persisted ManualCompaction turn -``` - -### Runtime contract - -`bitfun-runtime-ports` adds: - -```rust -pub struct AgentSessionCompactionRequest { - pub session_id: String, - pub turn_id: String, -} - -pub struct AgentSessionCompactionResult { - pub session_id: String, - pub turn_id: String, -} - -#[async_trait::async_trait] -pub trait AgentSessionCompactionPort: Send + Sync { - async fn start_session_compaction( - &self, - request: AgentSessionCompactionRequest, - ) -> PortResult; -} -``` - -The caller supplies a stable turn ID. This lets Shared IPC record the provisional active turn before executing the side effect, preserving disconnect cancellation and outcome-unknown handling. - -`AgentRuntime` stores the optional port, exposes `start_session_compaction`, and returns a typed `NotAvailable` error when a product assembly does not register it. - -### Core lifecycle - -The coordinator splits manual compaction into start and completion: - -1. Validate exact session/turn identities and require an idle, context-loaded session. -2. Atomically admit the persisted maintenance turn with the caller-provided turn ID through the same mutation lock used by ordinary dialog turns. -3. Read the authoritative context only after the maintenance turn owns the Session, so a racing dialog turn cannot be omitted. -4. Register active-session execution, exact turn settlement, a cancellation token, and a manual-compaction commit gate. -5. Emit `DialogTurnStarted` and return the accepted turn identity immediately. -6. Run compression in an owned task. -7. Persist exactly one terminal status and return the in-memory session to idle only when the owned task settles. - -The existing synchronous Desktop compatibility method starts the same task and awaits its private completion receiver. It does not create a second execution path. - -### Cancellation and commit safety - -Manual compaction has two phases: - -- **Planning:** cancellation wins through an atomic planning/cancelled transition and cancels the model future. The maintenance turn is persisted as cancelled. -- **Committing:** the compaction plan has already been accepted for context replacement. Cancellation no longer clears session state; the commit tail finishes and reports completion. - -The transition uses a small atomic gate shared by the coordinator and execution engine. A compare-and-swap prevents cancellation and commit from both winning. The gate is registered only for manual compaction and removed when the task settles. - -This avoids a state where the session appears idle while context replacement or persistence continues. - -The maintenance Turn is model-invisible but transcript-visible. Transcript reads project canonical persisted Turn records rather than reconstructing the maintenance entry from model context, retaining exact compression/tool identity and the `applied` fact after restart. If context commit succeeds but terminal Turn or idle-state persistence fails, the finalizer emits one explicit failed dialog terminal and returns an error that states the compaction was already applied; it never leaves Shared TUI waiting on a missing terminal event. - -### Shared IPC - -The private protocol moves from version 7 to version 8 and adds: - -```rust -RuntimeIpcOperation::CompactSession { - request: AgentSessionCompactionRequest, -} -``` - -Rules: - -- current controller only; -- current session must be idle; -- side-effecting; -- supplied turn ID becomes the provisional active turn; -- success reuses `RuntimeIpcOperationResult::TurnAccepted`; -- disconnect and explicit cancel reuse the existing turn-cancellation operation. - -No Server, Relay, Peer, ACP, SDK Host, or public wire protocol is changed. - -### TUI behavior - -- `/compact` is the primary entry; `/summarize` resolves to the same action. -- Both are shown only in chat/startup surfaces where the existing action projection permits session operations. -- Extra arguments are rejected with `Usage: /compact`. -- The action is idle-only in both Embedded and Shared modes. -- Acceptance shows immediate status while authoritative events drive processing state. -- Compression events are projected into the existing `ContextCompression` tool-card presentation, so live execution and restored transcript use the same visual vocabulary. -- Completion shows token reduction and source facts already carried by the event; failure and cancellation reuse existing turn terminal handling. - -## Error Handling - -- Missing runtime port: typed not-available error, surfaced in the TUI status line. -- Busy/error session: Core and IPC both fail closed; the action registry prevents the normal busy invocation path. -- Duplicate or invalid turn ID: rejected before starting a second maintenance turn. -- Shared request timeout after side-effect admission: existing outcome-unknown disconnect handling applies because the provisional turn ID is known. -- Event stream failure: existing CLI active-turn cancellation and embedded handoff guidance applies. -- Cancellation after commit wins: operation completes; no false cancelled terminal state is emitted. -- Post-commit terminal persistence failure: the Session returns to idle in memory, emits one failed terminal event, and reports that context replacement was already applied. - -## Scope Exclusions - -- Relay and remote protocol changes -- Extension or customization behavior -- Compression prompt, algorithm, automatic threshold, or artifact-schema changes -- Web UI behavior changes -- Public Server/API/SDK Host exposure -- Generic maintenance-command framework -- Busy-session queueing -- New keyboard shortcut or leader-sequence support - -## Verification - -- Runtime-port DTO and runtime forwarding tests -- Atomic cancellation/commit gate tests -- Core accepted-turn and terminal-settlement tests using existing coordinator fixtures where practical -- Atomic dialog/maintenance admission, post-commit failure finalization, and persisted transcript restoration tests -- IPC v8 serialization, rules, provisional active-turn, and disconnect-cancellation tests -- CLI action alias/availability/argument tests -- Embedded/Shared runtime-client equivalence tests -- TUI context-compression projection tests -- `cargo test -p bitfun-runtime-ports` -- `cargo test -p bitfun-agent-runtime` -- `cargo test -p bitfun-agent-runtime-ipc` -- `cargo test -p bitfun-cli` -- `cargo check -p bitfun-core --features product-full` -- `node scripts/check-core-boundaries.mjs` -- `git diff --check` - -## Delivery - -This work is combined with the existing TUI session aliases and truthful context-status changes in one PR. The final branch is rebased on current `gcwing/main`, reviewed as one diff, and squashed to one commit before pushing to `limityan/BitFun`. diff --git a/src/apps/cli/README.md b/src/apps/cli/README.md index dc06e02031..5ab94d6a63 100644 --- a/src/apps/cli/README.md +++ b/src/apps/cli/README.md @@ -80,6 +80,20 @@ only when the current invocation may approve tool requests. Non-interactive `exe `AskUserQuestion`; provide all required input in the initial prompt. The hidden legacy `--confirm` flag maps to the safe default and should not be used in new automation. +### Interactive session and context commands + +The Embedded and Shared TUI use the same session command names: + +- `/sessions` opens the session browser; `/resume`, `/continue`, and `/history` are aliases. +- `/new` starts a fresh conversation session; `/clear` is its OpenCode-compatible alias and does not + merely clear the terminal display. +- `/status` opens a transient view of current session, runtime, workspace, approval, and latest + primary-model request facts observed by this TUI. It is not a cumulative usage report; use + `/usage` for cumulative session usage in Embedded TUI. +- `/compact` compacts the current session's model context without deleting saved conversation + history; `/summarize` is its OpenCode-compatible alias. Compaction is available only while the + session is idle. + The interactive TUI supports per-session worktree isolation through `/worktree`. Run the command without arguments to toggle it, or use `/worktree on`, `/worktree off`, and `/worktree status`. The header shows the active branch and `Worktree: on|off`; detached managed worktrees use their base