# ARIS on DeepSeek Harness

[English](https://github.com/wanshuiyin/Auto-claude-code-research-in-sleep/tree/dsh-aris#readme) | 中文

> 这是 `dsh-aris` 发行分支。完整的 ARIS 项目——全部工作流、文档、其他宿主的适配——在 [`main`](https://github.com/wanshuiyin/Auto-claude-code-research-in-sleep) 上。

在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 里跑 ARIS 研究工作流：上游 83 个 ARIS 技能（同步到上游 `341f914`）、3 个本地技能和 9 个 Claude 审稿覆盖层全部进入原生技能目录，审稿仍由 Codex 跨模型独立执行。

技能文件零改动。这个 bundle 只是一层配置加一个简短适配器——不打补丁改 Harness 代码，也不 fork。

## 安装

```sh
dsh plugin --profile web add dsh-aris
```

装完重启 profile。插件代码在启动时加载，只刷新页面不够。

`dsh plugin` 会调用 **pnpm**，而 Harness 不自带它。PATH 上没有 pnpm，安装会直接退出、什么都不做。

## 前置条件

**已安装并登录的 Codex CLI。** 它就是那位独立审稿人。本 bundle 启动 `codex mcp-server`，且从不覆盖它的模型和推理档位——**`~/.codex/config.toml` 就是审稿人姿态契约**。ARIS 要求非 DeepSeek 家族、xhigh 档：

```toml
model = "gpt-6-astra"
model_reasoning_effort = "xhigh"
```

Codex 起不来时，Harness 直接启动失败，而不是跑一个没有审稿人的组合。这是刻意的：**没有独立审稿人的 ARIS 不是 ARIS**。

**一个 DeepSeek API key**，通过 Harness 的 Models 页面或 `DEEPSEEK_API_KEY` 提供。

**走 HTTP 代理时**，启动 Harness 要带 `NODE_USE_ENV_PROXY=1`。否则 Node 的 fetch 不认 `http_proxy`，模型请求会以 `TRANSPORT` 失败。这个变量必须在 Node 启动时就存在，配置层补不回来。

**可选——把执行者也管住。** ARIS 的审稿人自带作用域限制：那段禁止提议哈希、禁止防御性脚手架、禁止 corner-case 加固、禁止把判断过度机械化的文本，**内嵌在会产出审查 prompt 的技能里，零配置生效**。但没有任何东西以同样方式约束**执行者**。补上有两条路，而且它们不是一回事：

- **ARIS 自己的红线，一个开关。** `aris-scope-limits` 这一行随包提供但默认关闭；在你 profile 的 patch 里写 `disabled: false` 就把同一段文本应用到执行者。它在加载时读取包内的 `skills/shared-references/review-scope-limits.md`，所以**审阅者那条路和执行者这条路不可能漂移**。默认关闭是因为它在每个请求上都花 token。
- **完整的 [HERO](https://github.com/wanshuiyin/HERO-Anti-OverDefense) 契约。** 把它的规范块粘进项目的 `AGENTS.md` 或 `CLAUDE.md`，或粘进 `$DSH_HOME/AGENTS.md` 覆盖所有 dsh 项目——Harness 自己会加载这些文件。本 bundle **不 vendor HERO 的文本**，它的正典在 HERO 自己的 `RULES.md` 里。

## 验证

```sh
dsh --profile web --dump-config | grep -A2 aris-
```

然后在会话里敲 `/`，技能菜单会列出 ARIS 技能。要验最关键的那一环：让模型用一个简单 prompt 调 `mcp__codex__codex`，报出它看到的 `threadId`，再用 `mcp__codex__codex-reply` 续接一次。**能看见 `threadId`，多轮审稿才成立。**

## ARIS 标签页

Web UI 的会话里会在「对话」「轨迹」之后多出一个 **ARIS** 标签页（`order: 15`，位于轨迹和 LiveBench 之间）。标签页分两层：

- **顶部是只读运行状态**：只呈现审稿人和循环自身产物说了什么，**不写入、不推进轮次、不把分数转成完成判断**。它读的是会话工作区里的 `review-stage/REVIEW_STATE.json`，所以在该目录跑完第一轮 `auto-review-loop` 之前是空的。
- **下方是交互式 ARIS 工作台**：技能触发、工作流向导、Idea 看板、实验、Wiki 图谱、审计链等；它通过两个 JSON 端点——`/api/aris-run`（运行状态）与 `/api/aris-wb`（工作台）——读取工作区产物，并且始终绑定当前会话。工作台不再以左下角全屏浮层出现，底部输入框仍然可用。

最上面那一栏（运行状态摘要）就是这个标签页存在的理由：**这一轮是谁审的**，以及 ARIS 能否确认审稿人与执行者属于不同的模型家族。走 Codex 后端时这一项**按设计就是 `unverified`**——Codex 能报告自己是谁，但没有任何东西独立证明执行者是谁，所以 ARIS 记为 `identity_assurance: caller_declared`。读作"路由一致，但未获认证"。

标签页里还常驻两条诚实边界，值得在此重复：状态是**每轮结束时写入**、不是持续更新，所以长轮次期间显示的是上一轮；`completed` 只表示**循环结束**——正面结论**或**跑满轮次——**绝不表示工作已通过**。

## 本地新增（dsh-aris-panel）

- **Claude 审稿通道：9 个薄覆盖层。** `research-review`、`research-refine`、`auto-review-loop`、`kill-argument`、`proof-checker`、`paper-plan`、`paper-figure`、`paper-write`、`auto-paper-improvement-loop` 各有一个 `<name>-claude` 覆盖层：运行时加载最新主技能全文，只把审稿通道从 Codex MCP 换成 `claude-review` MCP。`$ARGUMENTS` 带 `reviewer: claude`，或用户在对话里要求「用 Claude 审稿」时，各工作流自动改走这些变体；没有覆盖层的 6 个审计类技能仍走 Codex，最终报告标注 `reviewer: claude (partial)`。每次上游同步后运行 `python tools/build_claude_overlays.py` 重建；上游新增覆盖层未映射的审稿工具时，`test/test_claude_overlays.py` 会失败。
- **`/verify-manager`：想法验证一条龙。** 在与主线同名、加 `_verify-` 前缀的平行目录里，一次调用走完：可证伪假设与预注册判据 → 方案与任务 → 运行（含基线复现）→ 对照基线分析 → 下一轮新思路。主线只读，结论成立才经交接说明转正。用自然语言触发，如「我有个想法需要验证」「做个简单的验证实验」；说「全量 / 主线 / 正式实验 / 跑基线」时不走它，进入 `/experiment-plan` → `/experiment-bridge`。
- **`/human-in-loop-refine`：人在环路方案修订。** ARIS 初稿出来后，把你的评价与要求、参考论文（提取创新点和实现思路）、实验想法和奇思妙想综合成修订方案，暂存在 `_refine/rNN/`。每条改动分为有依据 / 需验证 / 否决；它包含 `/verify-manager`，需验证的条目自动交给它跑实验，结论回流。你确认后才改主线。
- **`aris/`：上游快照。** ARIS 仓库的完整副本（commit 见 `aris/UPSTREAM.txt`，不含 `.git` 和 `.env`），用于参考和重新同步；DSH 只从 `skills/` 加载技能。
- **`/gpt-image-2`**：本机 OpenAI 兼容出图转接，供 `paper-writing` 的 `illustration: gpt-image-2` 调用。
- **deep-audit 档位用 `max` 而非 `ultra`。** 上游把 deep audit 固定为 `gpt-6-astra` + `ultra`；本机 Codex 模型目录里 `gpt-6-astra` 只有 `none/high/xhigh/max`，因此语料统一本地化为 `max`（见 `shared-references/reviewer-routing.md` 中的说明）。

## 这一层改了什么

| 配置行 | 作用 |
|---|---|
| `agent-default-model` | 执行者换成 `deepseek-flash` |
| `aris-skills` | 挂载技能语料（上游 83 个 + 本地 3 个 + 9 个 Claude 覆盖层）、发布 `ARIS_REPO`、补回 Codex 的 `threadId`、提供 ARIS 标签页 |
| `aris-codex` | 经 MCP 接入 `codex mcp-server`，单次调用预算 20 分钟，工作目录钉死在稳定位置 |

技能语料挂在 bundled 档（最低优先级），所以项目级或用户级的同名技能永远优先。执行者模型是部署默认值而非锁定值：已保存的模型设置或会话内选择都会覆盖它。

## 基于 clone 开发

```sh
ARIS_REPO=/absolute/path/to/aris NODE_USE_ENV_PROXY=1 \
  dsh --profile web --patch /absolute/path/to/aris/dsh/checkout.patch.yml
```

改技能即时生效，不用重启。`ARIS_REPO` 是必需的，没设会以指名该变量的报错终止加载。

这个 overlay **不等价于**已安装的 bundle：它补不回 Codex 的 `threadId`，所以多轮 `codex-reply`（因而 hard 档的 Debate Protocol）只有装包才可用。两者互斥：对已装 bundle 的 profile 再叠这个 overlay，会因为配置行 id 重复而失败——去掉其中一个。

## 已知限制

- **跟随一个 Harness 版本窗口，并以 peerDependency 声明。** DeepSeek Harness 处于技术预览；本 bundle 把 `@deepseek-ai/dsh >=0.1.7-rc.2 <0.3.0-0` 声明为 optional peerDependency。传输层测试在 `0.2.1-rc.2` 上通过（此前在 `0.2.0-rc.2` 上也通过）；它所用的 `HostConnectionFetch` 注册表在这个窗口内的各版本都存在。dsh 的 peerDependency 门禁会读这个范围：不兼容的运行时会在启动日志里**整体跳过本 bundle**。升到更新版本后：先跑 `node node_modules/dsh-aris-panel/test/transport-smoke.mjs`，再放宽范围，或用 `dsh plugin allow-version` 授予精确版本豁免。
- **面板的浏览器传输走 HTTP，不再走 RPC channel。** dsh 的通用 channel 注册表（`connection.rpc.handle`）是从 Connection 自己的上下文里解析 `webServer` 的，而 dsh 并不在那里注入它（`0.1.7-rc.2` 至 `0.2.1-rc.2` 均如此），于是树外插件的 channel 注册直接抛错，每次调用都变成 SPA 兜底返回的 HTTP 405。ARIS 改为在 `/api` 前缀上挂精确 Fetch 路由（`HostConnectionFetch.register`），dsh 为 `/api` 提供 Host/Origin 信任围栏与浏览器会话 Cookie；自 `0.2.1` 起共享处理器还规定精确路由只服务 owner peer，浏览器会话就是这个 owner。`test/transport-smoke.mjs` 把这两半契约都钉住（含非 owner peer 得到 403）；它覆盖不到载体自身的鉴权链路，所以请用真实 host 复核：`POST /api/aris-run` 与 `/api/aris-wb` —— 400 = 已挂载，403 = 被 owner 门拒绝，404 = 未挂载。
- **不把任何 dsh 包声明为 npm 依赖。** 内置包由宿主提供，通过 profile 的模块回退从 Harness 安装目录解析。Harness 自己的规约就要求 `@deepseek-ai/dsh-*` 不进 `dependencies`；而且这些子包与 CLI **锁步发版**，本 bundle 无论钉哪个范围，都会和用户已装的版本打架。上面的 peer 范围只是兼容性声明，且标为 optional，因此永远不会拉进第二份运行时副本。
- **`web_fetch` 关闭。** 原版 dsh 默认关闭它，本 bundle 也不打开——打开就意味着依赖一个 provider 包。需要联网的技能改用 `web_search`，或用 `bash` 跑 `curl`。
- **审稿线程连续性是进程内的。** Harness 重启、或任何一次 MCP 重连替换了 Codex 子进程，已保存的 `threadId` 都会失效，之后的轮次从新线程开始；无论如何 `review-stage/REVIEWER_MEMORY.md` 都是持久记录。
- **Codex 自己的推理过程不进 Harness 日志。** 返回的只有判词。调用参数和判词都会落日志，审稿人的中间工作留在 Codex 那侧。
- **超过 50 KB 的判词会被落盘**，上下文里只留预览。审稿普遍很长的话，调高 `spill-policy` 行的 `maxInlineBytes`。
