Skip to content

Commit 50d7cb3

Browse files
authored
Merge pull request #164 from cubenlp/rex/workspace
Rex/workspace
2 parents 822443b + b82ecfc commit 50d7cb3

20 files changed

+682
-229
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
##### user defined ######
22
*.jsonl
33
playground/
4+
Playground/
5+
workspace/
46

57

68
##### seperated line ######

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
1515
- `chattool setup opencode` 现支持 `-e/--env`,可显式复用 ChatTool 的 OpenAI 配置来源;支持 `.env` 文件路径或 `OpenAI` profile 名称,并按 `显式参数 > -e 指定的 OpenAI 配置 > 当前 OpenAI 配置 > 现有 opencode 配置 > 默认值` 回退
1616
- 新增 `chattool setup workspace [PROFILE] [WORKSPACE_DIR]`,用于在核心项目外围初始化人类-AI 协作工作区骨架;支持 `base` profile、默认中文模板、显式 `--language en``--dry-run` 与已完成 `setup.md` 的保护覆盖语义
1717

18+
### Changed
19+
- `chattool setup workspace` 默认生成的 workspace scaffold 现改为按任务隔离的多任务协作约定:去掉单一 `task.md`,默认使用 `reports/MM-DD-<task-name>/``playgrounds/<task-name>/`;对于长期系列工作,可升级为 `reports/task-sets/<set-name>/``playgrounds/task-sets/<set-name>/` 并维护任务集级进展
20+
- `chattool setup playground` 的外层工作区结构现对齐 `setup workspace`:默认使用 `reports/``playgrounds/``knowledge/`,并把工作区 skills 副本收口到 `knowledge/skills/`;同时继续保留 `ChatTool/` 仓库和 skills 同步逻辑
21+
- `chattool setup workspace``chattool setup playground` 现移除全局 `thoughts/` 面,避免并发任务时出现一个共享的“当前关注点”入口;相关角色统一收口到各任务或任务集的 `reports/` 结构
22+
1823
## [6.5.0] - 2026-03-31
1924

2025
### Changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ chattool explore arxiv get 1706.03762 -v
133133
| PyPI 工具 | `chattool pypi` | 创建、构建、校验、上传与探测 Python 包 |
134134
| MCP 服务 | `chattool mcp start` | 标准 MCP Server,供 Claude/Cursor 调用 |
135135
| 环境安装 | `chattool setup codex/claude/lark-cli` | 安装 Codex / Claude Code / 官方 lark-cli 并写入配置 |
136-
| Playground | `chattool setup playground` | 初始化工作区,并可在完成后复用 `chatenv` 中的 GitHub token 配置 Git HTTPS 鉴权 |
137-
| Workspace | `chattool setup workspace` | 初始化围绕核心项目的人类-AI 协作工作区骨架,沉淀协议、任务面与知识目录 |
136+
| Playground | `chattool setup playground` | 初始化带 `ChatTool/` 仓库的协作工作区,外层结构对齐 `reports/``playgrounds/``knowledge/`,并可复用 GitHub token 配置 Git HTTPS 鉴权 |
137+
| Workspace | `chattool setup workspace` | 初始化围绕核心项目的人类-AI 协作工作区骨架,默认采用 `reports/``playgrounds/` 的多任务并发结构 |
138138
| Skills | `chattool skill install` | 安装 ChatTool skills 到 Codex / Claude Code |
139139
| CC-Connect | `chattool cc` | cc-connect 快速配置与启动 |
140140

README_en.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ chattool image siliconflow generate "a cute dog" -o dog.png
166166
| Screenshot | `chattool serve capture` | Local webpage screenshot service |
167167
| Cert Mgmt | `chattool serve cert` / `chattool client cert` | SSL certificate distribution |
168168
| Setup | `chattool setup codex` | Install Codex CLI and write config (supports `--base-url` / `--model`) |
169+
| Workspace | `chattool setup workspace` | Create a collaboration workspace around a core project with task-isolated `reports/` and `playgrounds/` directories |
170+
| Playground | `chattool setup playground` | Create a ChatTool-centered collaboration workspace with `ChatTool/`, `reports/`, `playgrounds/`, and `knowledge/skills/` |
169171
| Skills | `chattool skill install` | Install ChatTool skills to Codex / Claude Code |
170172
| CC-Connect | `chattool cc` | Quick cc-connect setup and start |
171173

cli-tests/conftest.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import json
44
import re
5+
import sys
56
import time
67
from pathlib import Path
78
from types import SimpleNamespace
@@ -10,6 +11,12 @@
1011
from click.testing import CliRunner
1112
from dotenv import dotenv_values
1213

14+
15+
REPO_ROOT = Path(__file__).resolve().parents[1]
16+
SRC_DIR = REPO_ROOT / "src"
17+
if str(SRC_DIR) not in sys.path:
18+
sys.path.insert(0, str(SRC_DIR))
19+
1320
from chattool.client.main import cli
1421
from chattool.config import BaseEnvConfig, FeishuConfig
1522
from chattool.const import CHATTOOL_ENV_DIR, CHATTOOL_ENV_FILE, CHATTOOL_REPO_DIR
@@ -90,15 +97,19 @@ def create_document(prefix: str = "cli-doc", *, title: str | None = None):
9097
output=create.output,
9198
)
9299

93-
def wait_doc_raw_contains(document_id: str, text: str, *, attempts: int = 5, delay: float = 1.0):
100+
def wait_doc_raw_contains(
101+
document_id: str, text: str, *, attempts: int = 5, delay: float = 1.0
102+
):
94103
last_output = ""
95104
for _ in range(attempts):
96105
raw = invoke("lark", "doc", "raw", document_id)
97106
last_output = raw.output
98107
if text in last_output:
99108
return raw
100109
time.sleep(delay)
101-
raise AssertionError(f"{text!r} not found in document raw output:\n{last_output}")
110+
raise AssertionError(
111+
f"{text!r} not found in document raw output:\n{last_output}"
112+
)
102113

103114
return SimpleNamespace(
104115
tmp_path=tmp_path,

cli-tests/setup/test_chattool_setup_basic.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,20 +97,20 @@ chattool setup lark-cli -i
9797
- `<workspace>/AGENTS.md`
9898
- `<workspace>/CHATTOOL.md`
9999
- `<workspace>/MEMORY.md`
100-
- `<workspace>/Memory/`
101-
- `<workspace>/skills/`
102-
- `<workspace>/scratch/`
100+
- `<workspace>/reports/`
101+
- `<workspace>/playgrounds/`
102+
- `<workspace>/knowledge/`
103103
- `<workspace>/ChatTool/`
104104

105105
预期过程和结果:
106106
1. 首次执行 `chattool setup playground --workspace-dir <workspace> --chattool-source <repo-or-url>`,预期在目标目录下 clone `ChatTool/`
107107
2. 若目标目录只是普通非空目录且当前终端可交互,预期先提示是否继续;确认后继续初始化,并保留已有文件。
108108
3. 若目标目录中已经存在 `ChatTool/`(或历史遗留的 `chattool/`),预期进入更新模式:优先更新仓库,并在交互模式下提示是否同步工作区 `skills/`
109109
4. 预期生成 `AGENTS.md``CHATTOOL.md``MEMORY.md`
110-
5. 预期创建 `Memory/``skills/``scratch/`
111-
6. 预期从 `ChatTool/skills/` 复制或更新 skills 到工作区 `skills/`,并给每个 skill 创建 `experience/` 目录。
110+
5. 预期创建 `reports/``playgrounds/``knowledge/`
111+
6. 预期从 `ChatTool/skills/` 复制或更新 skills 到工作区 `knowledge/skills/`,并给每个 skill 创建 `experience/` 目录。
112112
7. 预期 skills 同步只替换常规文件,不修改已有 `experience/` 内容。
113-
8. 执行 `chattool setup workspace [PROFILE] [WORKSPACE_DIR]`,预期可生成围绕核心项目的独立协作骨架,包括 `AGENTS.md``MEMORY.md``setup.md``task.md``thoughts/``tasks/``playground/``knowledge/`
113+
8. 执行 `chattool setup workspace [PROFILE] [WORKSPACE_DIR]`,预期可生成围绕核心项目的独立协作骨架,包括 `AGENTS.md``MEMORY.md``setup.md``reports/``playgrounds/``knowledge/`,并默认采用按任务隔离的并发协作结构
114114
9. 执行 `chattool setup workspace <workspace> --dry-run -I`,预期仅打印将创建的目录与文件,不实际写入。
115115

116116
参考执行脚本(伪代码):
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# test_chattool_setup_playground_real_basic
2+
3+
验证 `chattool setup playground` 在真实 CLI 下会生成与 workspace 类似的外层协作骨架,同时保留 `ChatTool/` 仓库和同步到 `knowledge/skills/` 的工作区 skills。
4+
5+
## 元信息
6+
7+
- 命令:`chattool setup playground`
8+
- 目的:验证 playground 骨架目录、`knowledge/skills/` 同步位置,以及 ChatTool 仓库 clone 的真实行为。
9+
- 标签:`cli`
10+
- 前置条件:可从本地 ChatTool 仓库作为 clone 源。
11+
- 环境准备:使用临时目录作为 workspace 根目录,不污染仓库。
12+
- 回滚:测试结束后临时目录自动删除。
13+
14+
## 用例 1:基础 playground 落盘新骨架
15+
16+
- 初始环境准备:
17+
- 创建空临时目录作为 workspace 根目录。
18+
- 使用当前本地 ChatTool 仓库作为 `--chattool-source`
19+
20+
预期过程和结果:
21+
1. 执行 `chattool setup playground --workspace-dir <workspace-dir> --chattool-source <repo-dir> -I`,预期命令成功。
22+
2. 预期生成 `AGENTS.md``CHATTOOL.md``MEMORY.md``reports/README.md``playgrounds/README.md``knowledge/README.md`
23+
3. 预期在目标目录下 clone `ChatTool/`
24+
4. 预期 `knowledge/memory/``knowledge/skills/``playgrounds/scratch/` 存在。
25+
5. 预期 skills 从 clone 出来的 `ChatTool/skills/` 同步到 `knowledge/skills/`,并给每个 skill 创建 `experience/README.md`
26+
6. 预期不再创建旧的顶层 `Memory/``skills/``scratch/`
27+
28+
参考执行脚本(伪代码):
29+
30+
```sh
31+
chattool setup playground --workspace-dir /tmp/my-playground --chattool-source /path/to/ChatTool -I
32+
assert new scaffold files exist
33+
assert ChatTool repo exists
34+
assert knowledge/skills contains copied skills with experience readmes
35+
assert legacy top-level Memory/ skills/ scratch/ do not exist
36+
```
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import os
2+
import subprocess
3+
import sys
4+
from pathlib import Path
5+
6+
7+
def _run_chattool_setup_playground(args: list[str]):
8+
repo_root = Path(__file__).resolve().parents[2]
9+
env = os.environ.copy()
10+
src_dir = str(repo_root / "src")
11+
existing = env.get("PYTHONPATH")
12+
env["PYTHONPATH"] = src_dir if not existing else f"{src_dir}:{existing}"
13+
return subprocess.run(
14+
[sys.executable, "-m", "chattool.client.main", "setup", "playground", *args],
15+
text=True,
16+
capture_output=True,
17+
check=False,
18+
env=env,
19+
)
20+
21+
22+
def test_setup_playground_creates_workspace_style_scaffold(tmp_path: Path):
23+
workspace_dir = tmp_path / "playground"
24+
source_dir = Path(__file__).resolve().parents[2]
25+
26+
result = _run_chattool_setup_playground(
27+
[
28+
"--workspace-dir",
29+
str(workspace_dir),
30+
"--chattool-source",
31+
str(source_dir),
32+
"-I",
33+
]
34+
)
35+
36+
assert result.returncode == 0, result.stderr
37+
assert (workspace_dir / "AGENTS.md").exists()
38+
assert (workspace_dir / "CHATTOOL.md").exists()
39+
assert (workspace_dir / "MEMORY.md").exists()
40+
assert (workspace_dir / "reports" / "README.md").exists()
41+
assert (workspace_dir / "playgrounds" / "README.md").exists()
42+
assert (workspace_dir / "playgrounds" / "scratch" / "README.md").exists()
43+
assert (workspace_dir / "knowledge" / "README.md").exists()
44+
assert (workspace_dir / "knowledge" / "memory" / "README.md").exists()
45+
assert (workspace_dir / "knowledge" / "skills" / "README.md").exists()
46+
assert (workspace_dir / "ChatTool").exists()
47+
48+
assert not (workspace_dir / "Memory").exists()
49+
assert not (workspace_dir / "skills").exists()
50+
assert not (workspace_dir / "scratch").exists()
51+
52+
agents = (workspace_dir / "AGENTS.md").read_text(encoding="utf-8")
53+
memory_md = (workspace_dir / "MEMORY.md").read_text(encoding="utf-8")
54+
assert "reports/MM-DD-<task-name>/" in agents
55+
assert "reports/task-sets/<set-name>/" in agents
56+
assert "knowledge/skills/" in agents
57+
assert "knowledge/memory/" in memory_md
58+
59+
copied_skill = workspace_dir / "knowledge" / "skills" / "practice-make-perfact"
60+
assert copied_skill.exists()
61+
assert (copied_skill / "experience" / "README.md").exists()

cli-tests/setup/test_chattool_setup_workspace_real_basic.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# test_chattool_setup_workspace_real_basic
22

3-
验证 `chattool setup workspace` 在真实 CLI 下的基础落盘、默认中文模板、显式英文模板、`--dry-run``setup.md` 保护语义。
3+
验证 `chattool setup workspace` 在真实 CLI 下的基础落盘、支持“默认常规任务 + 可选任务集”的并发 workspace 模板、显式英文模板、`--dry-run``setup.md` 保护语义。
44

55
## 元信息
66

77
- 命令:`chattool setup workspace`
8-
- 目的:验证 workspace 骨架目录、关键模板文件、语言选项,以及 `--force` / `--dry-run` 的真实行为。
8+
- 目的:验证 workspace 骨架目录、默认常规任务与任务集并存的 `reports/` / `playgrounds/` 模板、语言选项,以及 `--force` / `--dry-run` 的真实行为。
99
- 标签:`cli`
1010
- 前置条件:无
1111
- 环境准备:使用临时目录作为 workspace 根目录,不污染仓库。
@@ -18,16 +18,16 @@
1818

1919
预期过程和结果:
2020
1. 执行 `chattool setup workspace <workspace-dir> -I`,预期命令成功。
21-
2. 预期生成 `AGENTS.md``MEMORY.md``setup.md``task.md``thoughts/current.md``tasks/README.md``playground/README.md``knowledge/README.md`
22-
3. `AGENTS.md` 默认应包含中文的 5 层协作架构和知识写入规则
23-
4. `setup.md` 应包含 Discover / Ask / Adapt / Initialise / Set first task / Done 六步清单。
21+
2. 预期生成 `AGENTS.md``MEMORY.md``setup.md``reports/README.md``playgrounds/README.md``knowledge/README.md`
22+
3. `AGENTS.md` 默认应包含中文的多任务协作架构,并同时说明常规任务 `reports/MM-DD-<task-name>/` / `playgrounds/<task-name>/` 与任务集 `reports/task-sets/<set-name>/` / `playgrounds/task-sets/<set-name>/` 规则
23+
4. `setup.md` 应包含 Discover / Ask / Adapt / Initialise / Create first task lanes / Done 六步清单,并明确默认先创建常规任务,只有长期系列任务才改用任务集
2424

2525
参考执行脚本(伪代码):
2626

2727
```sh
2828
chattool setup workspace /tmp/demo-workspace -I
2929
assert workspace files exist
30-
assert AGENTS.md contains architecture and write rules
30+
assert AGENTS.md contains reports/playgrounds task isolation rules
3131
assert setup.md contains six-step checklist
3232
```
3333

cli-tests/setup/test_chattool_setup_workspace_real_basic.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1+
import os
12
import subprocess
23
import sys
34
from pathlib import Path
45

56

67
def _run_chattool_setup_workspace(args: list[str]):
8+
repo_root = Path(__file__).resolve().parents[2]
9+
env = os.environ.copy()
10+
src_dir = str(repo_root / "src")
11+
existing = env.get("PYTHONPATH")
12+
env["PYTHONPATH"] = src_dir if not existing else f"{src_dir}:{existing}"
713
return subprocess.run(
814
[sys.executable, "-m", "chattool.client.main", "setup", "workspace", *args],
915
text=True,
1016
capture_output=True,
1117
check=False,
18+
env=env,
1219
)
1320

1421

@@ -21,24 +28,32 @@ def test_setup_workspace_base_creates_scaffold(tmp_path: Path):
2128
assert (workspace_dir / "AGENTS.md").exists()
2229
assert (workspace_dir / "MEMORY.md").exists()
2330
assert (workspace_dir / "setup.md").exists()
24-
assert (workspace_dir / "task.md").exists()
25-
assert (workspace_dir / "thoughts" / "current.md").exists()
26-
assert (workspace_dir / "tasks" / "README.md").exists()
27-
assert (workspace_dir / "playground" / "README.md").exists()
31+
assert (workspace_dir / "reports" / "README.md").exists()
32+
assert (workspace_dir / "playgrounds" / "README.md").exists()
2833
assert (workspace_dir / "knowledge" / "README.md").exists()
34+
assert not (workspace_dir / "knowledge" / "report").exists()
2935

3036
agents = (workspace_dir / "AGENTS.md").read_text(encoding="utf-8")
3137
setup_md = (workspace_dir / "setup.md").read_text(encoding="utf-8")
3238
assert "## 架构" in agents
3339
assert "## 知识写入规则" in agents
40+
assert "reports/MM-DD-<task-name>/" in agents
41+
assert "reports/task-sets/<set-name>/" in agents
42+
assert "playgrounds/<task-name>/" in agents
43+
assert "playgrounds/task-sets/<set-name>/" in agents
44+
assert "knowledge/memory/YYYY-MM-DD-status.md" in agents
3445
assert "1. **Discover**" in setup_md
3546
assert "6. **Done**" in setup_md
47+
assert "Create first task lanes" in setup_md
48+
assert "默认创建一个常规任务" in setup_md
3649

3750

3851
def test_setup_workspace_english_language_creates_english_templates(tmp_path: Path):
3952
workspace_dir = tmp_path / "workspace"
4053

41-
result = _run_chattool_setup_workspace([str(workspace_dir), "--language", "en", "-I"])
54+
result = _run_chattool_setup_workspace(
55+
[str(workspace_dir), "--language", "en", "-I"]
56+
)
4257

4358
assert result.returncode == 0, result.stderr
4459
agents = (workspace_dir / "AGENTS.md").read_text(encoding="utf-8")
@@ -47,6 +62,7 @@ def test_setup_workspace_english_language_creates_english_templates(tmp_path: Pa
4762
assert "## 架构" not in agents
4863
assert "# Workspace Setup Checklist" in setup_md
4964

65+
5066
def test_setup_workspace_force_does_not_overwrite_completed_setup_md(tmp_path: Path):
5167
workspace_dir = tmp_path / "workspace"
5268

0 commit comments

Comments
 (0)