Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions docs/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,19 +315,18 @@ chattool setup workspace ~/workspace/demo --language en
它会生成一套独立骨架,包括:

- `AGENTS.md`:模型主协议
- `MEMORY.md`:跨 session 记忆
- `README.md`:workspace 的 general-use 入口
- `projects/`:所有实际工作的执行容器,单任务和多任务 project 都从这里展开
- `docs/`:长期文档沉淀
- `core/`:源码仓库目录
- - `ARCHIVE.md`:归档摘要日志
- `.trash/`:workspace 级软删除缓冲区
- `projects/`:所有实际工作的执行容器
- `archive/`:归档后的历史 project
- - `core/`:源码仓库目录
- `scripts/`:workspace 级维护脚本目录
- `skills/`:共享 skills 目录
- `public/`:公开网站和发布目录

默认先用单任务 project;如果是一组围绕同一目标持续推进的大任务,再升级为多任务 project,并在 project 根保留 `PROJECT.md`、`progress.md`、`review.md`。工作区协议现在也会明确:review 由 loop 在模型准备停下时触发;如果是开发任务,每个阶段都要先测试通过、完善文档,再按 `review.md` 的规则完成校验与收尾。

默认模板语言是中文;如果你要英文版协议和 onboarding 文件,可以显式传 `--language en`。

如果目标目录已经是一个已有 workspace,`setup workspace` 不会直接覆盖原有 `AGENTS.md` / `MEMORY.md`;当前更强调通过根目录 `README.md` 和 `projects/README.md` 提供 general-use 入口与结构约定,再逐步完成迁移
如果目标目录已经是一个已有 workspace,`setup workspace` 会优先保留现有 `AGENTS.md` 或历史遗留的 `MEMORY.md`,同时补齐当前结构目录

如果只想先看计划不落盘:

Expand Down
12 changes: 0 additions & 12 deletions docs/env/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,10 @@ chattool setup docker --sudo -i
```bash
chattool setup workspace
chattool setup workspace ~/workspace/demo
chattool setup workspace ~/workspace/demo --with-opencode-loop
chattool setup opencode --install-only --plugin chatloop
```

详细文档:[workspace.md](workspace.md)

### ChatLoop Quickstart

如果你想从零开始体验一次完整的 `PRD.md -> /chatloop -> fresh-start continuation` 流程,可参考:

- [chatloop-quickstart.md](chatloop-quickstart.md)

如果你想看一篇更完整的设计复盘,了解为什么 `chatloop` 要向 `auto-loop` 学 continuation 状态机,以及为什么 `opencode run` 不能代表真实 loop 行为,可参考:

- [../blog/agent-cli/chatloop-from-auto-loop.md](../blog/agent-cli/chatloop-from-auto-loop.md)

### Lark CLI 配置

使用 `setup lark-cli` 快速安装官方 `lark-cli`,并复用 ChatTool 现有的 Feishu 配置。
Expand Down
177 changes: 30 additions & 147 deletions docs/env/workspace.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,8 @@
# Workspace 协作脚手架(setup workspace)

`chattool setup workspace` 用来初始化一个围绕核心项目的“人类-AI 协作工作区
`chattool setup workspace` 用来初始化一个围绕核心项目的人类-AI 协作工作区。

当前版本采用“基础 workspace + 可选配置项”的结构,但任务组织模型已经从旧的 `reports/` / `playgrounds/` 分桶切换到新的 `projects/` 模型。

新建工作区时,命令会直接生成可用的 `README.md`、`AGENTS.md`、`MEMORY.md`。如果目标目录已经像一个 workspace,命令不会贸然覆盖现有 `AGENTS.md` / `MEMORY.md`,而是保留现有协议,同时补齐当前 general-use 的 `README.md` 和结构目录。

基础目录固定生成:

- `projects/`
- `reference/`
- `docs/`
- `core/`
- `skills/`
- `public/`

其中:

- `projects/`:所有实际进行中的 project 容器根目录;默认从最小 `PRD.md` project 开始
- `reference/`:跨多个 project 可复用的长期参考材料
- `core/`:集中放需要加入 workspace 的源码仓库
- `skills/`:共享 skills 目录,默认放在 workspace 根目录
- `public/`:用于部署公开网站和相关发布内容
- `docs/themes/`:按主题整理的长期维护约定,例如 changelog、project 整理与 workspace 维护规则
当前模板以 `projects/` 为执行中心,同时显式区分活跃工作、归档历史和 workspace 级脚本。生成结果默认对齐当前 Playground 工作区风格,不再默认生成根 `README.md`、`IDENTITY.md` 或 `MEMORY.md`。

## 1. 基本用法

Expand All @@ -35,156 +15,59 @@ chattool setup workspace ~/workspace/demo --language en
命令形态:

```bash
chattool setup workspace [PROFILE] [WORKSPACE_DIR] [--language zh|en] [--with-opencode-loop] [--force] [--dry-run] [-i|-I]
chattool setup workspace [PROFILE] [WORKSPACE_DIR] [--language zh|en] [--force] [--dry-run] [-i|-I]
```

- `PROFILE`:可选,当前仅支持 `base`
- `WORKSPACE_DIR`:可选,默认当前目录
- `--language`:模板语言,默认 `zh`,也可显式传 `en`
- `--with-opencode-loop`:启用 OpenCode loop-aware 模板版本,并把全局 `chatloop` plugin / slash commands 安装到 OpenCode home
- `--force`:覆盖已生成文件
- `--dry-run`:只打印将创建的目录与文件,不写入磁盘
- `-i / -I`:强制交互 / 禁止交互

补充语义:

- 如果目标目录已存在 `AGENTS.md` / `MEMORY.md` 等 workspace 标记,优先保留现有协议文件,并补齐当前 general-use 的 `README.md` 与 `projects/` 结构,而不是直接改写现有协议。

## 2. 基础结构

```text
workspace/
├── README.md
├── AGENTS.md
├── MEMORY.md
├── TODO.md
├── ARCHIVE.md
├── .trash/
├── projects/
├── docs/
├── archive/
├── core/
├── scripts/
├── skills/
└── public/
```

其中:

- `AGENTS.md`:模型执行协议
- `TODO.md`:这个 workspace 近期打算做的事
- `ARCHIVE.md`:归档项目摘要日志
- `.trash/`:workspace 级软删除缓冲区
- `projects/`:所有实际工作的执行容器
- `archive/`:归档后的历史 project
- `scripts/`:workspace 级维护脚本

## 3. `projects/` 模型

### 默认 project
默认 project 形状:

```text
projects/MM-DD-<project-name>/
<project-root>/
PRD.md
progress.md
memory.md
.trash/
reports/
scripts/
playground/
reference/
```

如果后续工作自然长出子部分,可以继续在子目录里放新的 `PRD.md`,而不是预先引入复杂项目级别管理结构。

源码仓库访问约定:

- 真实源码仓库默认保留在 `core/`
- 如果当前 project 需要更短的访问路径,可手动在 project 内创建到 `core/<repo-name>` 的符号链接
- 该符号链接是按需行为,不作为模板默认自动生成

workspace-level 参考约定:

- project 内的 `reference/` 只放本次任务局部参考、样例和阶段归档
- 如果某类参考材料已经跨多个 project 可复用,应提升到 workspace 根目录 `reference/`
- 如果某类规则已经明显变成长期维护约定,应提升到 `docs/themes/`

### 设计原则

- workspace 根目录文件用于 general-use 协议与跨 session 上下文
- 实际执行时,应该进入具体 `project` 目录埋头推进
- `PRD.md` 是唯一主入口,用于定义任务含义、需求、范围、约束和完成标准
- `memory.md` / `progress.md` 用于补充当前上下文与进展
- 只有显式触发 `/chatloop ...` 时,`chatloop` 才会在 idle 时 fresh start,重新读取 `PRD.md`(以及必要的 `memory.md` / `progress.md`)

## 4. 可选配置项

交互模式下可以追加额外模块。

### OpenCode loop-aware template

- 使用 `--with-opencode-loop` 时,会切换到 loop-aware workspace 模板版本
- 同时会自动执行一次 OpenCode CLI 的纯安装(等价于 `chattool setup opencode --install-only`)
- 同时把 `chatloop` 全局安装到 OpenCode home(默认 `~/.config/opencode/`,也可通过 `OPENCODE_HOME` 改写),包括:
- `plugins/chatloop/`
- `command/chatloop.md`
- `command/chatloop-project.md`
- `command/chatloop-status.md`
- `command/chatloop-help.md`
- `command/chatloop-stop.md`
- 该版本适合先完善 `PRD.md`,再通过显式 `/chatloop ...` 触发 fresh-start continuation 的工作流
- `chatloop` 可从任意 project 子目录触发,会自动向上寻找最近的 `PRD.md`
- 运行后,状态文件写入当前 project 根目录 `.opencode/chatloop.local.md`,事件记录直接追加到 `.opencode/chatloop.events.log`
- 可通过 `/chatloop-status` 查看当前解析到的 project 根目录、状态文件和事件文件
- `chatloop` 启动首轮就会强制注入 `PRD.md` 路径与读取要求,而不是简单原样转发用户消息
- 每轮都要求输出 `## Completed`、`## Next Steps` 和 `STATUS: IN_PROGRESS` / `STATUS: COMPLETE`
- bootstrap 首轮不允许直接完成;只有进入后续 continuation 后,completion gate 才会生效
- 可通过 `/chatloop-project` 直接查看当前解析到的 project 根目录与 `PRD.md` / state / events 路径
- 只有同时满足 `STATUS: COMPLETE`、`<complete>DONE</complete>` 且 `Next Steps` 没有未完成项时,插件才会停止 continuation

### ChatTool

- 仓库放到 `core/ChatTool/`
- 从仓库内 `skills/` 同步到 workspace 根目录 `./skills/`
- 交互模式下会直接进入该仓库的 GitHub token 输入;默认值优先从当前仓库对应的 `.git-credential` / `.git-credentials` 读取,并以 mask 形式展示,回车可直接复用

### RexBlog

- 仓库放到 `core/RexBlog/`
- 把 `source/_posts` 链接到 `./public/hexo_blog`
- `public/` 根目录默认附带 `README.md`,说明这里用于部署公开网站
- 交互模式下同样会直接进入 GitHub token 输入,可复用当前仓库 token;若暂时不填,也可稍后进入目标仓库执行 `chattool gh set-token`

## 5. 设计原则

- `workspace` 是基础模型
- 额外仓库和发布能力通过“可选配置项”叠加
- 不再为每个场景分叉新的 workspace 命令
- 默认完整做完后再统一汇报结果
- 如果是开发任务,每个阶段要先测试通过、完善文档,再按当前 project 的完成标准收尾

## 8. Workspace Maintenance

当前模板还会生成一个共享 skill:

- `skills/workspace-maintenance/`

适用于这些场景:

- 整理 `projects/` 目录
- 把可复用材料提升到根目录 `reference/`
- 把长期规范提升到 `docs/themes/`
- 校对 workspace 根文档与当前结构是否一致

## 6. dry-run

```bash
chattool setup workspace ~/workspace/demo --dry-run -I
```

适合先确认:

- 将创建哪些目录
- 将写哪些文件
- 将启用哪些可选配置项

## 7. General-Use Entry

当前模型不再依赖 `setup.md` 作为主要入口文件。

工作区的一般入口改为:

- `README.md`:给人和模型的 general-use 说明
- `AGENTS.md`:模型执行协议
- `MEMORY.md`:跨 session 高优先级上下文

如果是已有 workspace,优先保留现有 `AGENTS.md` / `MEMORY.md`,再通过新的 `README.md` 和 `projects/` 结构逐步迁移。
## 4. 归档模型

## 9. Quickstart
- 活跃或近期仍在推进的工作保留在 `projects/`
- 明显不再活跃的项目移动到 `archive/YYYY-MM-DD/`
- 归档摘要写入 workspace 根目录 `ARCHIVE.md`
- 归档过程采用“脚本收集候选 + 模型审查 + 更新 `ARCHIVE.md`”的方式

如果你想看一遍从创建 `PRD.md`、新建 project、再到显式触发 `/chatloop ...` 的完整示例,可参考:
## 5. 可选模块

- [chatloop-quickstart.md](chatloop-quickstart.md)
- `ChatTool`:仓库放到 `core/ChatTool/`,并把仓库内 `skills/` 同步到 workspace 根目录 `skills/`
- `RexBlog`:仓库放到 `core/RexBlog/`,并把 `source/_posts` 链接到 `public/hexo_blog`
9 changes: 0 additions & 9 deletions src/chattool/setup/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ def workspace_setup(
dry_run,
with_chattool,
chattool_source,
with_opencode_loop,
):
setup_workspace(
profile_name=profile,
Expand All @@ -205,7 +204,6 @@ def workspace_setup(
dry_run=dry_run,
with_chattool=with_chattool,
chattool_source=chattool_source,
with_opencode_loop=with_opencode_loop,
)


Expand Down Expand Up @@ -690,13 +688,6 @@ def workspace_setup(
"help": "Git URL or local ChatTool repo path used when --with-chattool is enabled.",
},
),
SetupOptionElement(
param_decls=("--with-opencode-loop/--no-opencode-loop",),
kwargs={
"default": False,
"help": "Use the OpenCode loop-aware workspace template and install the global chatloop plugin and slash commands for OpenCode.",
},
),
),
),
)
18 changes: 1 addition & 17 deletions src/chattool/setup/workspace/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import click

from chattool.setup.opencode import setup_opencode
from chattool.interaction import (
BACK_VALUE,
abort_if_force_without_tty,
Expand Down Expand Up @@ -54,8 +53,6 @@ def _plan_workspace(
language: str,
enabled_options: list[str],
profile,
*,
template_variant: str = "default",
) -> tuple[list[Path], dict[Path, str]]:
dir_paths = [workspace_dir / rel for rel in BASE_DIRS]
dir_paths.extend(workspace_dir / rel for rel in profile.extra_dirs())
Expand All @@ -65,7 +62,6 @@ def _plan_workspace(
profile,
language,
enabled_options,
template_variant=template_variant,
existing_workspace=existing_workspace,
)
planned_files = {workspace_dir / rel: content for rel, content in file_map.items()}
Expand Down Expand Up @@ -106,7 +102,6 @@ def setup_workspace(
dry_run=False,
with_chattool=False,
chattool_source=None,
with_opencode_loop=False,
):
profile_name, workspace_dir = coerce_profile_and_workspace(
profile_name, workspace_dir
Expand All @@ -117,7 +112,6 @@ def setup_workspace(
usage = (
"Usage: chattool setup workspace [PROFILE] [WORKSPACE_DIR] "
"[--language zh|en] [--with-chattool] [--chattool-source <path-or-url>] "
"[--with-opencode-loop] "
"[--force] [--dry-run] [-i|-I]"
)
interactive, can_prompt, force_interactive, _, need_prompt = (
Expand All @@ -135,7 +129,6 @@ def setup_workspace(
"source": chattool_source or workspace_options.CHATTOOL_REPO_URL,
},
"rexblog": {"enabled": False, "source": workspace_options.REXBLOG_REPO_URL},
"opencode_loop": {"enabled": bool(with_opencode_loop)},
}

if need_prompt:
Expand All @@ -158,9 +151,8 @@ def setup_workspace(
enabled_options = [
name for name, item in option_settings.items() if item["enabled"]
]
template_variant = "opencode-loop" if option_settings["opencode_loop"]["enabled"] else "default"
dir_paths, file_map = _plan_workspace(
workspace_path, language, enabled_options, profile, template_variant=template_variant
workspace_path, language, enabled_options, profile
)

if dry_run:
Expand All @@ -177,9 +169,6 @@ def setup_workspace(
write_text_file(path, content, force=force)

applied = []
if option_settings["opencode_loop"]["enabled"]:
setup_opencode(interactive=False, install_only=True, plugin="chatloop")
applied.append(workspace_options.apply_opencode_loop_option(workspace_path))
if option_settings["chattool"]["enabled"]:
applied.append(
workspace_options.apply_chattool_option(
Expand Down Expand Up @@ -220,8 +209,3 @@ def setup_workspace(
click.echo(f"RexBlog repo: {item['repo_dir']}")
click.echo(f"Repo action: {item['repo_action']}")
click.echo(f"Public link: {item['public_link']}")
if item["name"] == "opencode_loop":
click.echo(f"OpenCode home: {item['opencode_home']}")
click.echo(f"ChatLoop plugin: {item['plugin_dir']}")
click.echo(f"ChatLoop commands: {item['commands_dir']}")
click.echo("ChatLoop state and event records are written under each project's .opencode/ directory when /chatloop runs.")
9 changes: 3 additions & 6 deletions src/chattool/setup/workspace/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,11 @@ class BaseProfile(WorkspaceProfile):


BASE_DIRS = [
".trash",
"projects",
"reference",
"docs",
"docs/memory",
"docs/skills",
"docs/themes",
"docs/tools",
"archive",
"core",
"scripts",
"skills",
"public",
]
Expand Down
Loading
Loading