Skip to content

Commit 1cbe8f2

Browse files
committed
Release v6.2.8 tmux managed policy
1 parent dc9a773 commit 1cbe8f2

12 files changed

Lines changed: 104 additions & 17 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
## Unreleased
44

5+
## v6.2.8 (2026-05-21)
6+
7+
### Config Source, Stop Cleanup, And Tmux Policy Release
8+
9+
- **Config Source Fixes Included**: the current release package includes explicit config source kinds for built-in defaults, user `~/.ccb/ccb.config`, and project `.ccb/ccb.config`, with project config taking highest priority.
10+
- **Kill Cleanup Ordering Included**: `stop_all` defers project tmux namespace destruction until after the socket response finalizer so `ccb kill` and `ccb kill -f` can complete cleanup from inside a CCB pane.
11+
- **Managed Tmux Policy Follow-Up Added**: isolated managed tmux sessions now explicitly enable CCB-owned `mouse on` and `set-clipboard on` policy in project namespaces and detached tmux paths.
12+
513
## v6.2.7 (2026-05-21)
614

715
### Config Source And Stop Cleanup Release

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<img src="https://img.shields.io/badge/Every_Model_Controllable-CF1322?style=for-the-badge" alt="Every Model Controllable">
88
</p>
99

10-
[![Version](https://img.shields.io/badge/version-6.2.7-orange.svg)]()
10+
[![Version](https://img.shields.io/badge/version-6.2.8-orange.svg)]()
1111
[![Platform](https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20Windows-lightgrey.svg)]()
1212

1313
**English** | [Chinese](README_zh.md)
@@ -74,9 +74,9 @@ Build project-local teams with roles, pane layout, provider state, worktree isol
7474
<details>
7575
<summary><b>Latest release highlights</b></summary>
7676

77-
- **Config sources are explicit**: CCB now reports whether the effective config came from the built-in default, user `~/.ccb/ccb.config`, or project `.ccb/ccb.config`.
78-
- **`ccb config validate` shows the active layer**: validation output now includes `config_source_kind` and `used_builtin_default`, and docs/`ccb_config` guidance match the three-layer precedence.
77+
- **Config sources are explicit**: CCB reports whether the effective config came from the built-in default, user `~/.ccb/ccb.config`, or project `.ccb/ccb.config`.
7978
- **`ccb kill` cleanup is ordered after the response**: project tmux namespace destruction is deferred until after `stop_all` finalization, so cleanup completes even when kill is launched from a CCB tmux pane.
79+
- **Managed tmux stays isolated but usable**: CCB now explicitly enables owned `mouse on` and `set-clipboard on` policy in project namespaces and detached tmux paths.
8080

8181
See [Release Notes](#release-notes) for the full history.
8282

@@ -338,6 +338,15 @@ Thanks to the [Linux.do community](https://linux.do) for testing, feedback, and
338338
Historical note: older release notes below may mention `askd`, legacy flags, or removed commands. Those references are kept only as changelog history and do not redefine the current CLI surface.
339339

340340
<details open>
341+
<summary><b>v6.2.8</b> - Config Source, Stop Cleanup, And Tmux Policy Release</summary>
342+
343+
- Includes explicit config source kinds for built-in defaults, user `~/.ccb/ccb.config`, and project `.ccb/ccb.config`, with project config taking highest priority.
344+
- Keeps project tmux namespace destruction deferred until after the stop-all response finalizer so `ccb kill` / `ccb kill -f` can complete cleanup from inside a CCB pane.
345+
- Keeps managed tmux config isolated while explicitly enabling CCB-owned mouse and clipboard support in project namespaces and detached tmux paths.
346+
347+
</details>
348+
349+
<details>
341350
<summary><b>v6.2.7</b> - Config Source And Stop Cleanup Release</summary>
342351

343352
- Reports explicit config source kinds for built-in defaults, user `~/.ccb/ccb.config`, and project `.ccb/ccb.config`, with project config taking highest priority.

README_zh.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<img src="https://img.shields.io/badge/模型皆可控-CF1322?style=for-the-badge" alt="模型皆可控">
88
</p>
99

10-
[![Version](https://img.shields.io/badge/version-6.2.7-orange.svg)]()
10+
[![Version](https://img.shields.io/badge/version-6.2.8-orange.svg)]()
1111
[![Platform](https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20Windows-lightgrey.svg)]()
1212

1313
[English](README.md) | **中文**
@@ -74,9 +74,9 @@
7474
<details>
7575
<summary><b>最新版本亮点</b></summary>
7676

77-
- **配置来源显式化**:CCB 现在会报告当前配置来自内置默认、用户 `~/.ccb/ccb.config`,还是项目 `.ccb/ccb.config`
78-
- **`ccb config validate` 显示生效层级**:validate 输出新增 `config_source_kind``used_builtin_default`,README/docs/`ccb_config` 说明也对齐三层优先级。
77+
- **配置来源显式化**:CCB 会报告当前配置来自内置默认、用户 `~/.ccb/ccb.config`,还是项目 `.ccb/ccb.config`
7978
- **`ccb kill` 清理顺序修复**:project tmux namespace destroy 延后到 `stop_all` 回包后的 finalize 阶段,避免从 CCB tmux pane 执行 kill 时清理只跑一半。
79+
- **Managed tmux 继续隔离但保留可用性**:CCB 在 project namespace 和 detached tmux 路径中显式启用自有 `mouse on``set-clipboard on` policy。
8080

8181
完整历史见 [新版本记录](#新版本记录)
8282

@@ -329,6 +329,15 @@ ccb reinstall
329329
历史说明:下面较旧的发布记录里仍可能出现 `askd`、旧 flag 或已移除命令。这些内容仅作为 changelog 历史保留,不代表当前 CLI 入口。
330330

331331
<details open>
332+
<summary><b>v6.2.8</b> - Config Source, Stop Cleanup, And Tmux Policy Release</summary>
333+
334+
- 包含显式配置来源:内置默认、用户 `~/.ccb/ccb.config`、项目 `.ccb/ccb.config`,并保持项目配置优先级最高。
335+
- 继续将 project tmux namespace destroy 延后到 stop-all response finalizer 之后,让从 CCB pane 执行的 `ccb kill` / `ccb kill -f` 能完成后台清理。
336+
- 保持 managed tmux 配置隔离,同时在 project namespace 和 detached tmux 路径中显式启用 CCB-owned mouse/clipboard support。
337+
338+
</details>
339+
340+
<details>
332341
<summary><b>v6.2.7</b> - Config Source And Stop Cleanup Release</summary>
333342

334343
- 显式报告配置来源:内置默认、用户 `~/.ccb/ccb.config`、项目 `.ccb/ccb.config`,并保持项目配置优先级最高。

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6.2.7
1+
6.2.8

ccb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ backend_env = get_backend_env()
2121
if backend_env and not os.environ.get("CCB_BACKEND_ENV"):
2222
os.environ["CCB_BACKEND_ENV"] = backend_env
2323

24-
VERSION = "6.2.7"
24+
VERSION = "6.2.8"
2525
GIT_COMMIT = "release"
2626
GIT_DATE = "2026-05-11"
2727

docs/ccbd-startup-supervision-contract.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ Out of scope:
101101
- Startup, supervision, and shutdown must be reasoned per project anchor, never globally.
102102
- CCB-managed tmux servers must be started with an isolated tmux config so user-level
103103
tmux plugins, hooks, and global options cannot alter project pane topology.
104+
- Any tmux behavior CCB depends on after config isolation, including mouse and
105+
clipboard support, must be applied as CCB-owned server policy rather than
106+
inherited from user `.tmux.conf`.
104107

105108
### 5.2 One Authoritative Backend
106109

@@ -419,7 +422,7 @@ Project namespace compatibility:
419422
- for a fresh namespace, the `cmd` pane bootstrap happens only after layout finalization and must replace that silent placeholder in place
420423
- project-namespace bootstrap must treat tmux server warmup and tmux server-policy persistence as separate steps:
421424
- `prepare_server` warms the server boundary only
422-
- server-global options that require a live session, such as `destroy-unattached off`, must be applied only after the authoritative project session exists
425+
- server-global options that require a live session, such as `destroy-unattached off`, CCB-managed `mouse on`, and CCB-managed `set-clipboard on`, must be applied only after the authoritative project session exists
423426
- project-owned pane mutation commands, including `respawn-pane` used by `cmd` bootstrap and pane-backed runtime launch/relaunch, must use the same shared tmux ready-retry budget as namespace create/reflow rather than a separate shorter timeout
424427
- namespace session liveness on the project-owned tmux socket must treat both `can't find session` and `no server running on <project socket>` as "namespace absent" for create/recreate decisions; startup must not fail that path as a generic tmux inspect error
425428
- startup must not rely on "real shell first, respawn later" behavior for the `cmd` pane, because that leaves stale prompt residue and can surface zsh no-newline `%` markers

lib/ccbd/services/project_namespace_runtime/backend.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,20 @@ def ensure_server_policy(backend, *, timeout_s: float | None = None) -> None:
4848
failure_message='failed to persist tmux destroy-unattached policy',
4949
timeout_s=timeout_s,
5050
)
51+
_apply_optional_server_policy(backend, option='mouse', value='on', timeout_s=timeout_s)
52+
_apply_optional_server_policy(backend, option='set-clipboard', value='on', timeout_s=timeout_s)
53+
54+
55+
def _apply_optional_server_policy(backend, *, option: str, value: str, timeout_s: float | None = None) -> None:
56+
try:
57+
_tmux_run_ready(
58+
backend,
59+
['set-option', '-g', option, value],
60+
failure_message=f'failed to persist tmux {option} policy',
61+
timeout_s=timeout_s,
62+
)
63+
except Exception:
64+
return
5165

5266

5367
def create_session(

lib/ccbd/services/project_namespace_runtime/ensure_state.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from .backend import find_window, kill_server, session_window_target, window_root_pane
3+
from .backend import ensure_server_policy, find_window, kill_server, session_window_target, window_root_pane
44
from .ensure_context import rebuild_namespace_backend
55
from .ensure_identity import apply_namespace_identity
66
from .models import ProjectNamespace
@@ -65,6 +65,7 @@ def persist_refreshed_namespace(controller, context, *, timeout_s: float | None
6565
raise ValueError('persist_refreshed_namespace requires current state')
6666
control_window_name = str(current.control_window_name or context.desired_control_window_name)
6767
workspace_window_name = str(current.workspace_window_name or context.desired_workspace_window_name)
68+
ensure_server_policy(context.backend, timeout_s=timeout_s)
6869
control_window = find_window(
6970
context.backend,
7071
session_name=context.desired_session_name,

lib/cli/services/runtime_launch_runtime/tmux_panes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ def detached_pane(
102102
def prepare_detached_tmux_server(backend) -> None:
103103
best_effort_tmux_run(backend, ['start-server'])
104104
best_effort_tmux_run(backend, ['set-option', '-g', 'destroy-unattached', 'off'])
105+
best_effort_tmux_run(backend, ['set-option', '-g', 'mouse', 'on'])
106+
best_effort_tmux_run(backend, ['set-option', '-g', 'set-clipboard', 'on'])
105107

106108

107109
def best_effort_tmux_run(backend, argv: list[str]) -> None:

test/test_v2_project_namespace_backend.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def _tmux_run(self, args, *, check=False, capture=False, timeout=None):
4545
stdout='',
4646
stderr='no server running on /tmp/ccb-runtime/test.sock\n',
4747
)
48-
if key == ('set-option', '-g', 'destroy-unattached', 'off') and self.require_session_for_server_policy and not self.session_created:
48+
if key[:2] == ('set-option', '-g') and self.require_session_for_server_policy and not self.session_created:
4949
return subprocess.CompletedProcess(
5050
['tmux', *key],
5151
1,
@@ -106,6 +106,8 @@ def test_prepare_server_then_create_session_and_server_policy_retry_transient_tm
106106

107107
assert backend.calls.count(('start-server',)) == 2
108108
assert backend.calls.count(('set-option', '-g', 'destroy-unattached', 'off')) == 2
109+
assert backend.calls.count(('set-option', '-g', 'mouse', 'on')) == 1
110+
assert backend.calls.count(('set-option', '-g', 'set-clipboard', 'on')) == 1
109111
assert backend.calls.count(
110112
(
111113
'new-session',
@@ -147,7 +149,13 @@ def test_prepare_server_does_not_require_server_policy_before_session_exists(mon
147149

148150
assert backend.calls[0] == ('start-server',)
149151
assert ('set-option', '-g', 'destroy-unattached', 'off') not in backend.calls[:2]
150-
assert backend.calls[-1] == ('set-option', '-g', 'destroy-unattached', 'off')
152+
assert ('set-option', '-g', 'mouse', 'on') not in backend.calls[:2]
153+
assert ('set-option', '-g', 'set-clipboard', 'on') not in backend.calls[:2]
154+
assert backend.calls[-3:] == [
155+
('set-option', '-g', 'destroy-unattached', 'off'),
156+
('set-option', '-g', 'mouse', 'on'),
157+
('set-option', '-g', 'set-clipboard', 'on'),
158+
]
151159

152160

153161
def test_list_windows_retries_transient_tmux_failures(monkeypatch) -> None:
@@ -304,7 +312,11 @@ def test_ensure_server_policy_accepts_fast_probe_timeout(monkeypatch) -> None:
304312

305313
ensure_server_policy(backend, timeout_s=0.0)
306314

307-
assert backend.calls == [('set-option', '-g', 'destroy-unattached', 'off')]
315+
assert backend.calls == [
316+
('set-option', '-g', 'destroy-unattached', 'off'),
317+
('set-option', '-g', 'mouse', 'on'),
318+
('set-option', '-g', 'set-clipboard', 'on'),
319+
]
308320

309321

310322
def test_kill_window_accepts_fast_probe_timeout(monkeypatch) -> None:

0 commit comments

Comments
 (0)