<!-- TRELLIS:START -->
# Trellis Instructions

These instructions are for AI assistants working in this project.

Use the `/trellis:start` command when starting a new session to:
- Initialize your developer identity
- Understand current project context
- Read relevant guidelines

Use `@/.trellis/` to learn:
- Development workflow (`workflow.md`)
- Project structure guidelines (`spec/`)
- Developer workspace (`workspace/`)

If you're using Codex, project-scoped helpers may also live in:
- `.agents/skills/` for reusable Trellis skills
- `.codex/agents/` for optional custom subagents

Keep this managed block so 'trellis update' can refresh the instructions.

<!-- TRELLIS:END -->

## 常用运维命令

重启 cc-web 服务：

修改 ccweb 项目后如果需要重启服务，必须先查看当前会话列表中的运行状态。
只有在除当前对话外没有其他 `running` 对话时，才能执行重启；如果仍有其他
运行中的对话，应暂缓重启并告知用户原因。

```bash
pm2 restart ccweb --update-env
```

## Codebase Memory 代码检索约定

本项目内 **graphify 已全面弃用**。后续涉及代码定位、调用链、架构理解、影响面分析、跨模块关系梳理时，默认优先使用 `codebase-memory-mcp`，不要再启用 graphify 技能、graphify CLI 或 `graphify-out` 产物作为主路径。

当前项目的 codebase-memory 项目名：

```text
home-cc-web
```

### 默认检索流程

1. 先确认索引状态：
   - `list_projects`
   - `index_status(project="home-cc-web")`
2. 如果索引缺失或明显过期，先执行：
   - `index_repository(repo_path="/home/cc-web", mode="full", persistence=false)`
3. 需要理解整体结构时，先用：
   - `get_architecture(project="home-cc-web", aspects=["all"])`
4. 需要找功能入口、类、函数、路由时，优先用：
   - `search_graph`
   - `search_code`
5. 需要确认调用关系时，使用：
   - `trace_path(mode="calls", direction="inbound" | "outbound" | "both")`
6. 需要读取具体实现时，先通过 `search_graph` 找到精确 `qualified_name`，再用：
   - `get_code_snippet`
7. `rg` / `sed` 只作为补充校验：
   - 校验最终行号
   - 查未被索引的配置或纯文本
   - 对 MCP 命中结果做交叉验证

### 子代理引导词模板

派发需要理解代码的子代理时，默认加入以下引导：

```text
请优先使用 codebase-memory-mcp 做代码理解：
先 list_projects / index_status 确认项目索引；
再用 search_graph 或 search_code 定位候选函数；
需要调用链时用 trace_path；
需要源码时先拿 qualified_name，再调用 get_code_snippet；
最后只用 rg/sed 校验行号或补查未索引文本。
不要使用 graphify。
```

### 本项目已验证的使用经验

- 无明确引导时，子代理不一定会主动使用 `codebase-memory-mcp`，可能退回 `rg` 或旧的 graphify 路径。
- 明确要求优先使用 `codebase-memory-mcp` 后，能稳定命中函数级入口、调用链和源码片段。
- 对 `codexapp` / `ccweb` 这类跨模块链路，`search_code` + `trace_path` + `get_code_snippet` 的组合比单纯全文检索更快建立上下文。
- 自然语言检索遇到 `developer`、`config`、`message` 等通用词会有噪声；这时应收敛到明确标识符，如 `collaborationMode`、`mcp_servers.ccweb`、`CC_WEB_SOURCE_SESSION_ID`。
- 最终答复中的文件行号仍建议用 `rg -n` 或 `nl -ba` 做一次轻量核验。

### 索引更新与忽略规则

- `auto_index` 是 `codebase-memory-mcp` 的本地配置，按当前 `CBM_CACHE_DIR` 生效；它不是 `.codex/config.toml` 里的项目级开关。
- 当前项目的项目级忽略规则写在 `.cbmignore`。普通源码级 `*.js` / `*.css` 不应一刀切排除；只排除 `*.min.js`、`*.map`、压缩包、构建目录、日志、临时文件、运行态状态文件等。
- watcher 是 Git-based polling：非 Git 项目跳过轮询；Git 项目的轮询间隔为基础 5 秒，每 500 个文件加 1 秒，最长 60 秒。
- 修改 `.cbmignore` 或大范围调整文件后，建议手动执行一次 `index_repository(repo_path="/home/cc-web", mode="full", persistence=false)`，让当前索引立即收敛到最新规则。

## Codex App / hapi 对齐经验

以下约定来自本项目对 `/home/hdzx/2026/hapi` 中 Codex app-server 接入方式的对比结果。后续如果继续维护 `codexapp`，默认按这些约定实现，避免再走偏到“看起来能跑、但拿不到原生协作能力”的分叉路径。

### 1. 初始化链路优先对齐上游协议

- `initialize` 成功后，先发送 `initialized` notification。
- 然后再做 best-effort 的能力探测：
  - `experimentalFeature/enablement/set`，当前至少尝试 `{ enablement: { goals: true } }`
  - `collaborationMode/list`
- 上述探测失败时：
  - 只记录日志
  - 不直接中断 `codexapp` 启动

### 2. collaborationMode 的参数形状必须贴近 hapi

- 一旦本轮使用 `collaborationMode`，`turn/start` 顶层参数应保持精简。
- `model`、`reasoning_effort`、`developer_instructions` 应放入：
  - `collaborationMode.settings.model`
  - `collaborationMode.settings.reasoning_effort`
  - `collaborationMode.settings.developer_instructions`
- 使用 `collaborationMode` 时，不要再重复传顶层 `model` / `effort`，否则容易让 app-server 落到非原生协作路径。

### 3. 自定义跨会话能力走 MCP，不优先走 dynamicTools

- `ccweb_list_conversations`、`ccweb_send_message` 这类自定义能力，优先通过 `thread/start.config.mcp_servers.*` 挂载。
- 不要把它们当成 `dynamicTools` 主路径注入给 `codexapp`。
- 原因：
  - `dynamicTools` 容易污染 app-server 原生工具集
  - 会增加拿不到 `spawn_agent` / `wait_agent` / 原生协作工具的风险

### 4. MCP 配置要做成“线程级”而不是“进程级”

- `codexapp` 是长驻 app-server，不是一次一进程的 CLI 调用。
- 因此 `CC_WEB_SOURCE_SESSION_ID`、`CC_WEB_CROSS_HOP_COUNT` 这类来源上下文，不应只放在 app-server 进程全局环境里。
- 正确做法是随 `thread/start.config.mcp_servers.ccweb.env` 一起下发，让每个线程拿到自己的来源会话上下文。

### 5. guided input 依赖 plan 协作模式

- `request_user_input` 类能力默认按“协作 / plan 模式可用”来设计。
- Default / YOLO 模式下，不要假设引导输入一定可用。
- 如果要做降级：
  - 优先退回普通文本交互
  - 不要让整轮对话因为 guided input 不可用而直接失效

### 6. 能力降级要明确而保守

- 如果运行时拒绝 `collaborationMode`（例如 `unknown field collaborationMode` 或 `unsupported collaboration mode`）：
  - 应记录一次能力降级
  - 后续本轮可退回普通 turn 发送
- 但如果只是 `goals` 或 `collaborationMode/list` 探测失败：
  - 不应直接判定整个 app-server 不可用

### 7. 回归检查要覆盖协议形状，不只看 UI

后续涉及 `codexapp` 的改动，至少要检查这些点：

- `initialize` 后是否真的调用了：
  - `experimentalFeature/enablement/set`
  - `collaborationMode/list`
- `collaborationMode` 存在时：
  - 顶层是否没有重复 `model`
  - 顶层是否没有重复 `effort`
- `ccweb` 能力是否走 `mcpToolCall`，而不是再次退回 `dynamicToolCall`
- mock / regression 中是否覆盖了上述断言

## Composer 快捷指令设计基线

cc-web 的输入框快捷指令是“本轮消息装饰器 / mention”系统，不是 Codex 原生工具面板，也不是手动填写 MCP tool 参数的执行面板。后续维护 `/`、`$`、`@` 时默认遵守以下语义，避免再次出现 `ccweb_prompt_user` 这类“真实可调用但快捷入口消失或语义跑偏”的问题。

### 1. 三类触发符的职责

- `/`：展示 cc-web 命令和当前会话可用的 MCP server/tool mention。选择 MCP tool 后，应插入类似 `mcp:ccweb/ccweb_prompt_user` 的标记，表示“本轮优先/明确使用这个 MCP”。真正的 tool 参数由模型在 MCP tool call 时生成。
- `$`：展示 Codex skills。选择后插入 skill mention，语义同样是给本轮消息增加上下文/偏好，不应直接执行 skill 内声明的 MCP。
- `@`：展示文件/目录和 `.codex/prompts` prompt 模板。不要把 MCP 塞进 `@`，否则会破坏“选文件/选 prompt”的用户预期。

### 2. MCP 候选显示原则

- `/` 中的 MCP 候选必须来自当前会话可运行的配置源：
  - 内置 `ccweb` MCP：来自线程级 `mcp_servers.ccweb`
  - 项目 MCP：来自当前会话 `cwd` 下可用的项目级 Codex MCP 配置
- 不要从历史消息、运行态 tool 名称、skill 的 `agents/*.yaml` 依赖声明里反推出“可用 MCP”。这些只能作为元数据，不代表当前 runtime 真能调用。
- 如果同一个 MCP server/tool 已经能被当前会话注入并调用，不要在 composer 层对个别工具做硬编码过滤。`ccweb_prompt_user` 这类需要结构化参数的工具，也应作为普通 MCP mention 显示，由模型生成参数。

### 3. MCP mention 不是参数构造 UI

- 选择 `mcp:server/tool` 后，默认只插入 mention 文本，不打开自定义参数表单，也不直接调用 `/api/internal/mcp`。
- 不要为某个 MCP tool 单独新增 `composer_mcp_tool_submit`、`tool_form`、`open_argument_form` 这类前端直调路径，除非产品明确新增“手动执行 MCP 工具”的独立能力。
- 如果未来确实要做“手动执行工具”功能，应和 `/` mention 分开设计，不能混进快捷补全语义里。

### 4. 回归覆盖要求

涉及 composer 快捷指令时，至少补这些断言：

- `/` 下应能看到当前会话可用的 MCP server/tool，包括 `mcp:ccweb/ccweb_prompt_user`。
- `mcp:ccweb/ccweb_prompt_user` 应作为普通 `itemType: 'tool'` 候选插入 mention 文本，而不是参数表单入口。
- `$` 不展示 MCP tool；`@` 不展示 MCP tool。
- 不从运行态工具名或历史 `mcp:*` 文本反推 MCP 候选。
- Codex App 侧仍要另行验证 `thread/start.config.mcp_servers.*` 注入和真实 MCP tool call 链路，不能只测 UI 候选。
