Skip to content

Commit 81802aa

Browse files
committed
Release v6.2.2 codex migration prompt hotfix
1 parent ae650c2 commit 81802aa

8 files changed

Lines changed: 117 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.2 (2026-05-18)
6+
7+
### Codex Managed Home Migration Prompt Hotfix
8+
9+
- **Codex External Migration Prompt Disabled In Managed Homes**: managed Codex `config.toml` now forces `[features].external_migration = false` so managed panes do not stop on an interactive migration prompt.
10+
- **Inherited Config Preserved**: source-home Codex config, model/API settings, and existing feature flags are still inherited; only the managed-home external migration prompt is disabled.
11+
- **Fallback Copy Path Hardened**: when TOML parsing is unavailable, the copied managed config still gets a managed `[features]` override for `external_migration = false`.
12+
513
## v6.2.1 (2026-05-18)
614

715
### Inherited CCB Config Skill Release

README.md

Lines changed: 14 additions & 5 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.1-orange.svg)]()
10+
[![Version](https://img.shields.io/badge/version-6.2.2-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,10 +74,10 @@ Build project-local teams with roles, pane layout, provider state, worktree isol
7474
<details>
7575
<summary><b>Latest release highlights</b></summary>
7676

77-
- **Inherited `ccb_config` skill added**: Claude and Codex installs now include a CCB-owned skill for designing `.ccb/ccb.config` and team memory.
78-
- **Inherited skills moved under `inherit_skills/`**: CCB-owned skills are inherited automatically, while optional `useful_tools/` remain user-installable.
79-
- **Ask guidance is shorter**: CCB injects concise English reply guidance, avoids repeating nested-routing instructions in every ask body, and recognizes more explicit-output requests.
80-
- **Memory routing is clearer**: `ccb_config` role memory favors direct owner-to-next-owner handoffs and separate root work packages for parallel chains.
77+
- **Managed Codex no longer stops on migration prompts**: CCB disables Codex `external_migration` only inside managed Codex homes.
78+
- **Inherited Codex config is preserved**: source-home model, API, and feature settings still carry forward; the managed-home override only prevents the interactive migration prompt.
79+
- **Fallback config copy is covered**: even when TOML parsing is unavailable, copied managed Codex config receives the external migration override.
80+
- **Inherited `ccb_config` remains available**: Claude and Codex installs keep the CCB config-design skill introduced in v6.2.1.
8181

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

@@ -339,6 +339,15 @@ Thanks to the [Linux.do community](https://linux.do) for testing, feedback, and
339339
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.
340340

341341
<details open>
342+
<summary><b>v6.2.2</b> - Codex Managed Home Migration Prompt Hotfix</summary>
343+
344+
- Disables `[features].external_migration` inside managed Codex homes so panes do not block on an interactive migration prompt.
345+
- Preserves inherited Codex source-home config, model/API settings, and other feature flags.
346+
- Adds coverage for parsed TOML inheritance and fallback copy behavior when TOML parsing is unavailable.
347+
348+
</details>
349+
350+
<details>
342351
<summary><b>v6.2.1</b> - Inherited CCB Config Skill Release</summary>
343352

344353
- Adds inherited Claude and Codex `ccb_config` skills for designing `.ccb/ccb.config`, choosing agent roles/providers/worktree layout, and updating shared plus per-agent memory.

README_zh.md

Lines changed: 14 additions & 5 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.1-orange.svg)]()
10+
[![Version](https://img.shields.io/badge/version-6.2.2-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,10 +74,10 @@
7474
<details>
7575
<summary><b>最新版本亮点</b></summary>
7676

77-
- **新增继承式 `ccb_config` skill**Claude 和 Codex 安装现在会继承 CCB 自带的配置设计 skill,用于设计 `.ccb/ccb.config` 和团队记忆
78-
- **继承式 skill 统一到 `inherit_skills/`**CCB 自带 skill 自动继承,`useful_tools/` 保持为用户按需安装的可选工具
79-
- **Ask guidance 更短**CCB 注入简洁英文回复指引,不再给每个 ask body 重复 nested-routing 说明,并识别更多显式完整输出要求
80-
- **记忆路由更清晰**`ccb_config` 角色记忆示例强调 owner-to-next-owner 直接交接,以及并行链路使用独立 root work package
77+
- **Managed Codex 不再卡在迁移提示**CCB 只在托管 Codex home 里禁用 Codex `external_migration`
78+
- **保留继承的 Codex 配置**source-home 的 model、API 和其他 feature 设置仍会继承;managed-home override 只阻止交互式迁移提示
79+
- **Fallback config copy 也覆盖**即使 TOML parser 不可用,复制到 managed Codex home 的配置也会追加 external migration override
80+
- **继承式 `ccb_config` 保持可用**:Claude 和 Codex 安装继续包含 v6.2.1 新增的 CCB 配置设计 skill
8181

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

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

332332
<details open>
333+
<summary><b>v6.2.2</b> - Codex Managed Home Migration Prompt Hotfix</summary>
334+
335+
- 在 managed Codex home 内禁用 `[features].external_migration`,避免 pane 被交互式 migration prompt 卡住。
336+
- 保留继承的 Codex source-home config、model/API 设置和其他 feature flags。
337+
- 增加 parsed TOML 继承和 TOML parser 不可用时 fallback copy 行为的测试覆盖。
338+
339+
</details>
340+
341+
<details>
333342
<summary><b>v6.2.1</b> - Inherited CCB Config Skill Release</summary>
334343

335344
- 新增继承式 Claude / Codex `ccb_config` skill,用于设计 `.ccb/ccb.config`、选择 agent 角色/provider/worktree layout,并更新共享和 per-agent memory。

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6.2.1
1+
6.2.2

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.1"
24+
VERSION = "6.2.2"
2525
GIT_COMMIT = "release"
2626
GIT_DATE = "2026-05-11"
2727

lib/provider_profiles/codex_home_config.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
Path('.agents') / 'skills',
4242
Path('plugins'),
4343
)
44+
_MANAGED_CODEX_DISABLED_FEATURES = ('external_migration',)
4445

4546

4647
@dataclass(frozen=True)
@@ -76,7 +77,12 @@ def materialize_codex_home_config(
7677
_write_codex_api_authority_config(target_config, authority, source_config=source_config)
7778
elif _inherits_config(profile) and _inherits_api(profile) and _source_config_valid(source_config):
7879
if source_config.is_file():
79-
_sync_file(source_config, target_config)
80+
payload = _read_source_config_payload(source_config)
81+
if payload:
82+
_write_managed_codex_config(target_config, payload)
83+
else:
84+
_sync_file(source_config, target_config)
85+
_append_managed_codex_feature_overrides(target_config)
8086
else:
8187
_write_managed_config_stub(target_config)
8288
else:
@@ -199,6 +205,25 @@ def _write_managed_config_stub(target: Path) -> None:
199205
target.write_text('# ccb agent-local codex config\n', encoding='utf-8')
200206

201207

208+
def _write_managed_codex_config(target: Path, payload: dict[str, object]) -> None:
209+
target.parent.mkdir(parents=True, exist_ok=True)
210+
sanitized = _disable_interactive_migration_features(payload)
211+
target.write_text(_render_toml_document(sanitized), encoding='utf-8')
212+
213+
214+
def _append_managed_codex_feature_overrides(target: Path) -> None:
215+
if not target.is_file():
216+
return
217+
try:
218+
text = target.read_text(encoding='utf-8')
219+
except Exception:
220+
return
221+
lines = [text.rstrip(), '', '[features]']
222+
for feature_name in _MANAGED_CODEX_DISABLED_FEATURES:
223+
lines.append(f'{feature_name} = false')
224+
target.write_text('\n'.join(lines).lstrip('\n') + '\n', encoding='utf-8')
225+
226+
202227
def _managed_codex_config_payload(source_config: Path, *, authority: CodexApiAuthority) -> dict[str, object]:
203228
payload = {'model_provider': authority.provider_id}
204229
inherited_payload = _strip_route_authority(_read_source_config_payload(source_config))
@@ -212,7 +237,17 @@ def _managed_codex_config_payload(source_config: Path, *, authority: CodexApiAut
212237
'base_url': authority.base_url,
213238
}
214239
}
215-
return payload
240+
return _disable_interactive_migration_features(payload)
241+
242+
243+
def _disable_interactive_migration_features(payload: dict[str, object]) -> dict[str, object]:
244+
sanitized = _clone_mapping(payload)
245+
raw_features = sanitized.get('features')
246+
features = dict(raw_features) if isinstance(raw_features, dict) else {}
247+
for feature_name in _MANAGED_CODEX_DISABLED_FEATURES:
248+
features[feature_name] = False
249+
sanitized['features'] = features
250+
return sanitized
216251

217252

218253
def _import_optional_toml_reader():

test/test_provider_profiles.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,39 @@ def test_materialize_codex_profile_copies_inherited_assets(tmp_path: Path, monke
136136
assert (runtime_home / 'sessions').is_dir()
137137

138138

139+
def test_materialize_codex_profile_disables_external_migration_prompt(tmp_path: Path, monkeypatch) -> None:
140+
project_root = tmp_path / 'repo'
141+
source_home = tmp_path / 'system-codex-home'
142+
source_home.mkdir(parents=True, exist_ok=True)
143+
(source_home / 'config.toml').write_text(
144+
'\n'.join(
145+
[
146+
'model = "gpt-5.5"',
147+
'',
148+
'[features]',
149+
'external_migration = true',
150+
'memories = true',
151+
'',
152+
]
153+
),
154+
encoding='utf-8',
155+
)
156+
monkeypatch.setenv('CODEX_HOME', str(source_home))
157+
158+
profile = materialize_provider_profile(
159+
layout=PathLayout(project_root),
160+
spec=_spec('agent1', provider_profile=ProviderProfileSpec(mode='isolated')),
161+
workspace_path=project_root,
162+
)
163+
164+
config_text = (Path(profile.runtime_home or '') / 'config.toml').read_text(encoding='utf-8')
165+
assert 'model = "gpt-5.5"' in config_text
166+
assert '[features]' in config_text
167+
assert 'memories = true' in config_text
168+
assert 'external_migration = false' in config_text
169+
assert 'external_migration = true' not in config_text
170+
171+
139172
def test_materialize_codex_home_config_falls_back_to_marked_copy_when_symlink_fails(tmp_path: Path, monkeypatch) -> None:
140173
source_home = tmp_path / 'system-codex-home'
141174
target_home = tmp_path / 'managed-codex-home'

test/test_v2_runtime_launch.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,7 +1502,9 @@ def test_codex_launcher_build_start_cmd_does_not_require_toml_parser_for_config_
15021502

15031503
isolated_home = runtime_dir / 'codex-state' / 'home'
15041504
assert f'CODEX_HOME={shlex.quote(str(isolated_home))}' in cmd
1505-
assert (isolated_home / 'config.toml').read_text(encoding='utf-8') == 'model = "gpt-5"\n'
1505+
config_text = (isolated_home / 'config.toml').read_text(encoding='utf-8')
1506+
assert 'model = "gpt-5"' in config_text
1507+
assert 'external_migration = false' in config_text
15061508
assert (isolated_home / 'skills' / 'demo' / 'SKILL.md').read_text(encoding='utf-8') == 'skill\n'
15071509

15081510

@@ -2261,7 +2263,9 @@ def test_codex_launcher_build_start_cmd_refreshes_managed_home_projection(monkey
22612263
_codex_start_cmd(command, spec, runtime_dir, 'sess-refresh-1')
22622264

22632265
isolated_home = runtime_dir / 'codex-state' / 'home'
2264-
assert (isolated_home / 'config.toml').read_text(encoding='utf-8') == 'model = "gpt-5"\n'
2266+
config_text = (isolated_home / 'config.toml').read_text(encoding='utf-8')
2267+
assert 'model = "gpt-5"' in config_text
2268+
assert 'external_migration = false' in config_text
22652269
assert (isolated_home / 'auth.json').read_text(encoding='utf-8') == '{"OPENAI_API_KEY":"old-key"}\n'
22662270
assert (isolated_home / '.tmp' / 'plugins.sha').read_text(encoding='utf-8') == 'plugins-sha-v1\n'
22672271
assert (
@@ -2280,7 +2284,9 @@ def test_codex_launcher_build_start_cmd_refreshes_managed_home_projection(monkey
22802284

22812285
_codex_start_cmd(command, spec, runtime_dir, 'sess-refresh-2')
22822286

2283-
assert (isolated_home / 'config.toml').read_text(encoding='utf-8') == 'model = "gpt-5.1"\n'
2287+
config_text = (isolated_home / 'config.toml').read_text(encoding='utf-8')
2288+
assert 'model = "gpt-5.1"' in config_text
2289+
assert 'external_migration = false' in config_text
22842290
assert (isolated_home / 'auth.json').read_text(encoding='utf-8') == '{"OPENAI_API_KEY":"new-key"}\n'
22852291
assert (isolated_home / '.tmp' / 'plugins.sha').read_text(encoding='utf-8') == 'plugins-sha-v2\n'
22862292
marketplace_payload = json.loads(

0 commit comments

Comments
 (0)