ultra-builder-pro-cli 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -7
- package/README.md +14 -16
- package/adapters/_shared/codex-assets.cjs +32 -151
- package/adapters/_shared/frontmatter.cjs +2 -2
- package/adapters/_shared/handbook.cjs +3 -3
- package/adapters/_shared/path-rewrite.cjs +0 -3
- package/adapters/_shared/runtime-assets.cjs +11 -4
- package/adapters/_shared/tests/path-rewrite.test.cjs +1 -3
- package/adapters/_shared/tests/resolve-target.test.cjs +1 -11
- package/adapters/_shared/tests/runtime-assets.test.cjs +17 -6
- package/adapters/opencode.js +1 -6
- package/adapters/tests/claude.test.cjs +1 -4
- package/adapters/tests/codex.test.cjs +5 -6
- package/adapters/tests/opencode.test.cjs +1 -2
- package/agents/tdd-runner.md +4 -3
- package/bin/install.js +6 -9
- package/bin/orchestrator.js +11 -4
- package/docs/AGENT-CONTEXT.md +4 -5
- package/docs/ARCHITECTURE.md +3 -4
- package/docs/LEGACY-HERMES.md +5 -81
- package/docs/PLAN.zh-CN.md +35 -42
- package/docs/ROADMAP.md +3 -3
- package/docs/RUNTIME-COMPAT-MATRIX.md +61 -60
- package/mcp-server/lib/pricing.cjs +0 -6
- package/mcp-server/lib/state-ops.cjs +7 -0
- package/mcp-server/lib/telemetry.cjs +4 -0
- package/mcp-server/tests/server-contract.test.cjs +17 -0
- package/mcp-server/tests/state-ops.test.cjs +23 -0
- package/mcp-server/tests/telemetry.test.cjs +14 -0
- package/orchestrator/dispatch-rules.cjs +15 -4
- package/orchestrator/tests/daemon.test.cjs +13 -12
- package/orchestrator/tests/dispatch-rules.test.cjs +12 -10
- package/package.json +3 -5
- package/skills/ultra-init/SKILL.md +0 -1
- package/skills/ultra-verify/SKILL.md +22 -41
- package/skills/ultra-verify/evals/evals.json +22 -24
- package/skills/ultra-verify/references/confidence-system.md +15 -32
- package/skills/ultra-verify/references/cross-verify-modes.md +14 -59
- package/skills/ultra-verify/scripts/verify_wait.py +44 -81
- package/spec/mcp-tools.yaml +3 -3
- package/spec/schemas/skill-manifest.schema.json +2 -2
- package/spec/schemas/state-db.sql +2 -2
- package/adapters/_shared/md-to-toml.cjs +0 -54
- package/adapters/_shared/tests/md-to-toml.test.cjs +0 -48
- package/adapters/gemini.js +0 -204
- package/adapters/tests/gemini.test.cjs +0 -112
- package/skills/gemini-collab/SKILL.md +0 -51
- package/skills/gemini-collab/evals/evals.json +0 -42
package/docs/PLAN.zh-CN.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# ultra-builder-pro-cli — 执行计划 v0.3.1
|
|
2
2
|
|
|
3
|
-
> **2026-07-
|
|
3
|
+
> **2026-07-17 当前生效边界(D50-D51,覆盖下文旧 Phase 7 / D25 / D46 的 memory 与 runtime 设计)**:
|
|
4
4
|
> Ultra Builder Pro 不再拥有 `memory.*`、recall、prompt/transcript/observation/summary
|
|
5
5
|
> 收集 hook 或私有 agent memory。跨会话记忆全部交给独立安装的 cloud-mem/claude-mem。
|
|
6
6
|
> 插件只保留 10 个 Ultra 公共 workflow、4 个 agent-only 规则 skill、宿主专属 collab
|
|
7
7
|
> companion、工作流 hook 与 `.ultra/state.db` 任务权威。Claude Code、Codex、OpenCode
|
|
8
|
-
> 采用各自 native plugin
|
|
8
|
+
> 采用各自 native plugin 呈现,其他旧 runtime adapter 已退役。下文所有与此冲突的
|
|
9
9
|
> memory/hindsight 章节仅作为历史实施记录,不再是当前需求或运行时契约。
|
|
10
10
|
|
|
11
11
|
**状态**:Phase 0-8B 完成(D48 `8224159` 2026-04-18)· v0.3 ready(planner + executor 合线)· 397 tests 全绿 · Phase 9 发布待启动
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
- **Phase 4.6 拆 a/b**(R6 + D35):v0.1 只跑 smoke flow,full conformance 推 v0.2
|
|
23
23
|
- **Codex 第二轮结论**:"小改后开工"(tl;dr);本版已完成小改
|
|
24
24
|
|
|
25
|
-
**总决策数**:D1-
|
|
25
|
+
**总决策数**:D1-D51(当前边界以 D50-D51 为准)
|
|
26
26
|
**总风险数**:R1-R32(v0.3.1 新增 R25-R32 共 8 条)
|
|
27
27
|
|
|
28
28
|
---
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
**自动化 coding 工厂**。
|
|
42
42
|
|
|
43
43
|
**最终形态**(v1.0):
|
|
44
|
-
-
|
|
44
|
+
- 任何一个受支持的 coding agent CLI(Claude / OpenCode / Codex)
|
|
45
45
|
Windsurf)都能消费同一套 Hermes 规则。
|
|
46
46
|
- 独立 session 执行独立 task,无对话污染;失败自动重试带熔断。
|
|
47
47
|
- 跨 session 的记忆、代码图、token 监控通过 MCP 共享。
|
|
@@ -70,7 +70,7 @@ Hermes(Ultra Builder Pro)是一套成熟的 agent 工程系统:
|
|
|
70
70
|
|
|
71
71
|
**A. Claude 独占工具钉死**:`TaskCreate/Update/List`、`AskUserQuestion`、`Skill`、
|
|
72
72
|
`Agent(subagent)`、`TeamCreate/SendMessage`、`/compact` 这 6 类 API 让 Hermes
|
|
73
|
-
离开 Claude Code
|
|
73
|
+
离开 Claude Code 寸步难行。其它两大受支持 runtime(OpenCode / Codex)各
|
|
74
74
|
有原生等价或兼容层,但今天无人对接。
|
|
75
75
|
|
|
76
76
|
**B. 单会话污染与状态不原子**:
|
|
@@ -103,7 +103,7 @@ Hermes(Ultra Builder Pro)是一套成熟的 agent 工程系统:
|
|
|
103
103
|
|
|
104
104
|
| # | 目标 | 可验证条件 | 归属 Phase |
|
|
105
105
|
|---|------|-----------|----------|
|
|
106
|
-
| G1 | Hermes 在 Claude / OpenCode / Codex
|
|
106
|
+
| G1 | Hermes 在 Claude / OpenCode / Codex 三个 runtime 原生可用 | 每 runtime 能跑完整 `init→research→plan→dev→test` | 4 |
|
|
107
107
|
| G2 | 状态权威源单一、并发安全 | SQLite + WAL;20 worker 并发 updateTaskStatus 无丢失 | 2 |
|
|
108
108
|
| G3 | `tasks.json` / context md 降级为投影,state.db 权威 | 所有写入走 state-db;JSON/MD 自动再生成(D18) | 2 |
|
|
109
109
|
| G4 | 每 task 独立会话(新进程 + 独立 worktree + lease),对话不污染 | 2 并发 session 各独立 worktree;kill -9 后 lease 过期可清理 | **4.5** |
|
|
@@ -139,7 +139,7 @@ Hermes(Ultra Builder Pro)是一套成熟的 agent 工程系统:
|
|
|
139
139
|
│ Skill 层 (知识 / 说明书) │
|
|
140
140
|
│ runtime 原生发现 │
|
|
141
141
|
│ Claude: ~/.claude/skills/ OpenCode: ~/.config/opencode │
|
|
142
|
-
│ Codex: ~/.agents/skills/
|
|
142
|
+
│ Codex: ~/.agents/skills/ │
|
|
143
143
|
│ │
|
|
144
144
|
│ ┌─ SKILL.md ──────────────────────────────┐ │
|
|
145
145
|
│ │ - 何时使用 │ │
|
|
@@ -313,7 +313,6 @@ ultra-builder-pro-cli/
|
|
|
313
313
|
│ ├── claude.ts
|
|
314
314
|
│ ├── opencode.ts
|
|
315
315
|
│ ├── codex.ts
|
|
316
|
-
│ ├── gemini.ts
|
|
317
316
|
│ └── _shared/
|
|
318
317
|
├── hooks/ # Python hooks 沿用
|
|
319
318
|
│ ├── *.py (15)
|
|
@@ -473,7 +472,7 @@ ultra-builder-pro-cli/
|
|
|
473
472
|
|
|
474
473
|
**1.3 Skill manifest 规范**(0.5 天)
|
|
475
474
|
- `spec/skill-manifest.schema.json` — 所有 skill 的 frontmatter 规范:
|
|
476
|
-
- name / description / runtime(Claude/OpenCode/Codex/
|
|
475
|
+
- name / description / runtime(Claude/OpenCode/Codex/all)/
|
|
477
476
|
mcp_tools_required / cli_fallback / complexity_hint(Haiku/Sonnet/Opus)
|
|
478
477
|
- **AC**:现有 18 skill 的 frontmatter 校验通过(≥90%,其余写 migration note)。
|
|
479
478
|
|
|
@@ -666,7 +665,7 @@ CLI"。消除对 Claude 独占工具的硬依赖。
|
|
|
666
665
|
做目录搭建 + 空 tasks.json 写入。
|
|
667
666
|
- `ultra-tools/commands/init.cjs`:CLI 兜底做同样事情。
|
|
668
667
|
- 三层都能完成 init → AC 对齐 CLAUDE 下今天的 init 行为。
|
|
669
|
-
- **AC**:在 Claude / OpenCode / Codex
|
|
668
|
+
- **AC**:在 Claude / OpenCode / Codex 任一 runtime 下跑 init,
|
|
670
669
|
产出的 `.ultra/` 目录与当前 Hermes 的 init 输出 diff-equal。
|
|
671
670
|
|
|
672
671
|
**3.2 `/ultra-research` 迁移**(1 天)
|
|
@@ -701,7 +700,7 @@ CLI"。消除对 Claude 独占工具的硬依赖。
|
|
|
701
700
|
- **AC**:全 9 命令迁完。
|
|
702
701
|
|
|
703
702
|
**3.7 AGENTS.md 统一上下文**(1 天)
|
|
704
|
-
- 合并 `CLAUDE.md` / `AGENTS.md`
|
|
703
|
+
- 合并 `CLAUDE.md` / `AGENTS.md` 为统一 **规则注入文件**
|
|
705
704
|
(命名:每 runtime 的原生 context 文件,但内容相同)。
|
|
706
705
|
- 内容:三层架构说明 + 关键 MCP tool 清单 + CLI 命令表 + skill 发现路径。
|
|
707
706
|
- 这是 OMX "scope guard" 能力(§5.2)。
|
|
@@ -709,9 +708,9 @@ CLI"。消除对 Claude 独占工具的硬依赖。
|
|
|
709
708
|
|
|
710
709
|
**3.8 Python hooks 三分拆**(1 天)
|
|
711
710
|
- 按原 PLAN v0.1 的 Phase 3 做:core/ + adapters/(claude / opencode /
|
|
712
|
-
codex
|
|
711
|
+
codex)
|
|
713
712
|
- **AC**:Claude hooks 行为字节级一致;OpenCode/Codex 只接 2 个可达事件
|
|
714
|
-
(§5.4
|
|
713
|
+
(§5.4)。
|
|
715
714
|
|
|
716
715
|
#### Phase 3 gate
|
|
717
716
|
|
|
@@ -723,8 +722,8 @@ CLI"。消除对 Claude 独占工具的硬依赖。
|
|
|
723
722
|
|
|
724
723
|
### Phase 4 — 跨 runtime 分发
|
|
725
724
|
|
|
726
|
-
**目标**:让 skill/MCP/CLI 三层正确安装到 Claude / OpenCode / Codex
|
|
727
|
-
|
|
725
|
+
**目标**:让 skill/MCP/CLI 三层正确安装到 Claude / OpenCode / Codex
|
|
726
|
+
三个 runtime。包含 MCP server 注册、skill 拷贝、CLI PATH、runtime-specific 转换。
|
|
728
727
|
|
|
729
728
|
**前置**:Phase 3(三层可用)
|
|
730
729
|
|
|
@@ -736,8 +735,8 @@ CLI"。消除对 Claude 独占工具的硬依赖。
|
|
|
736
735
|
|
|
737
736
|
**4.1 共享 adapter 工具**(1 天)
|
|
738
737
|
- `adapters/_shared/file-ops.ts` / `frontmatter.ts` / `settings-merge.ts` /
|
|
739
|
-
`path-rewrite.ts`
|
|
740
|
-
- **AC
|
|
738
|
+
`path-rewrite.ts` — 从 v0.1 PLAN §6.2.1 继承。
|
|
739
|
+
- **AC**:共享模块单元测试覆盖率 ≥85%。
|
|
741
740
|
|
|
742
741
|
**4.2 Claude adapter**(1 天)
|
|
743
742
|
- `~/.claude/{skills,commands,agents,hooks}` 直接拷贝。
|
|
@@ -760,18 +759,11 @@ CLI"。消除对 Claude 独占工具的硬依赖。
|
|
|
760
759
|
- MCP server 注册到 `config.toml [mcp_servers]`。
|
|
761
760
|
- **AC**:config.toml 合法;`codex exec "run /ultra-init"` 成功。
|
|
762
761
|
|
|
763
|
-
**4.5 Gemini adapter**(2 天,含 0.5 天 spike)
|
|
764
|
-
- spike:抓 `hooks/hooks.json` + subagent frontmatter。
|
|
765
|
-
- **整体打包成 Gemini extension**(`~/.gemini/extensions/ultra-builder-pro/`)。
|
|
766
|
-
- 命令 md → toml(`md-to-toml.ts`)。
|
|
767
|
-
- MCP server 在 extension manifest 里声明。
|
|
768
|
-
- **AC**:extension 目录合法;gemini 启动识别;`gemini --prompt` 烟测成功。
|
|
769
|
-
|
|
770
762
|
**4.6a Runtime capability matrix + v0.1 smoke flow**(1 天,**D33 收敛**)
|
|
771
|
-
- `docs/RUNTIME-COMPAT-MATRIX.md`:列
|
|
763
|
+
- `docs/RUNTIME-COMPAT-MATRIX.md`:列 3 runtime × ~25 能力点:
|
|
772
764
|
- 问答:AskUserQuestion / CLI menu / MCP `ask.question`
|
|
773
765
|
- Hook 事件:每 runtime 的可用事件名单 + payload 形状
|
|
774
|
-
- Subagent:Claude Task / Codex spawn_agent /
|
|
766
|
+
- Subagent:Claude Task / Codex spawn_agent / OpenCode @mention
|
|
775
767
|
- Usage 统计:token / cost 能否拿到
|
|
776
768
|
- MCP:stdio 稳定性 / HTTP 支持
|
|
777
769
|
- Skill 发现路径
|
|
@@ -780,23 +772,23 @@ CLI"。消除对 Claude 独占工具的硬依赖。
|
|
|
780
772
|
- `tests/conformance/<runtime>/` v0.1 基线:**每 runtime 1-2 条 smoke flow**
|
|
781
773
|
- Flow 1: `install → /ultra-init → task.create → 读投影 tasks.json → uninstall`
|
|
782
774
|
- Flow 2: `/ultra-dev 1` 通过 session.spawn 起 session → 关
|
|
783
|
-
- **AC**:matrix 文档完整;
|
|
775
|
+
- **AC**:matrix 文档完整;3 runtime × 2 smoke = 6 testcase 全绿
|
|
784
776
|
|
|
785
777
|
**4.6b Full conformance suite**(1 天,**D45 2026-04-17 完成**)
|
|
786
|
-
- ✅ 每 runtime 5 capability 完整测试 =
|
|
778
|
+
- ✅ 每 runtime 5 capability 完整测试 = 15 testcase(+ 6 smoke 保留 = 21)
|
|
787
779
|
- ✅ `tests/conformance/_capabilities.cjs` 共享 assertion;各 runtime `conformance.test.cjs` 注入 runtime-specific config
|
|
788
|
-
- ✅ `resolveTarget()` contract test(
|
|
780
|
+
- ✅ `resolveTarget()` contract test(15 tests,3 runtime × 5 scenario)
|
|
789
781
|
- ✅ Phase 4 review backlog 全清(6 P2 + 5 P3 → D45)— 含 `_source` 搬到 sibling `_ubp` 的 env 泄漏修复
|
|
790
782
|
|
|
791
783
|
**4.7 install.js 真实装配**(0.5 天)
|
|
792
784
|
- 从 Phase 0 stub 升级为真调用 adapter。
|
|
793
|
-
- `--claude/--opencode/--codex/--
|
|
785
|
+
- `--claude/--opencode/--codex/--all` + `--local/--global` + `--uninstall`。
|
|
794
786
|
- 幂等:跑两次 install diff = 空。
|
|
795
|
-
- **AC**:
|
|
787
|
+
- **AC**:3 runtime × 2 scope = 6 条安装路径全绿;uninstall 后目录干净。
|
|
796
788
|
|
|
797
789
|
#### Phase 4 gate
|
|
798
790
|
|
|
799
|
-
-
|
|
791
|
+
- 3 runtime 下 `/ultra-init` 都能跑通
|
|
800
792
|
- Claude diff-equal 基线通过
|
|
801
793
|
- runtime-compat-matrix 20 conformance testcase 全绿
|
|
802
794
|
- `docs/RUNTIME-COMPAT-MATRIX.md` 完整产出
|
|
@@ -983,7 +975,7 @@ agent 并行,orchestrator 负责 session 隔离和状态一致。
|
|
|
983
975
|
返回准确依赖集(10 文件项目的命中率 ≥95%)
|
|
984
976
|
|
|
985
977
|
**6.5 Runtime stdout 拦截(可选)**(1 天)
|
|
986
|
-
- orchestrator spawn agent 时拦截 stdout,解析 Anthropic/OpenAI
|
|
978
|
+
- orchestrator spawn agent 时拦截 stdout,解析 Anthropic/OpenAI
|
|
987
979
|
SDK 的 usage 字段(若可达)。
|
|
988
980
|
- 更精准的 token 统计(不依赖 rtk 推测)。
|
|
989
981
|
- **AC**:对一个已知 token 数的 task 做 E2E,telemetry 与官方 usage 误差 <5%。
|
|
@@ -1200,7 +1192,7 @@ files_modified 重叠检测 + 自动合并。这是 "coding 工厂" 的**后端*
|
|
|
1200
1192
|
#### 任务清单
|
|
1201
1193
|
|
|
1202
1194
|
**9.1 CI 矩阵**(1 天)
|
|
1203
|
-
- GitHub Actions:`{claude, opencode, codex
|
|
1195
|
+
- GitHub Actions:`{claude, opencode, codex} × {local, global}`
|
|
1204
1196
|
= 8 jobs + `rtk / code-review-graph / hindsight` 可选集成测试。
|
|
1205
1197
|
- **AC**:所有矩阵单元绿,每周定时跑一次(catch runtime 上游变更)。
|
|
1206
1198
|
|
|
@@ -1275,7 +1267,7 @@ CREATE INDEX events_task ON events(task_id, id);
|
|
|
1275
1267
|
CREATE TABLE sessions (
|
|
1276
1268
|
sid TEXT PRIMARY KEY,
|
|
1277
1269
|
task_id TEXT,
|
|
1278
|
-
runtime TEXT, -- claude|opencode|codex
|
|
1270
|
+
runtime TEXT, -- claude|opencode|codex
|
|
1279
1271
|
pid INTEGER,
|
|
1280
1272
|
worktree_path TEXT,
|
|
1281
1273
|
artifact_dir TEXT,
|
|
@@ -1592,7 +1584,7 @@ Week 18 buffer(ship 中任何 Phase 的 25% 滑动吃掉)
|
|
|
1592
1584
|
| # | 日期 | 决策 | 证据 |
|
|
1593
1585
|
|---|------|------|------|
|
|
1594
1586
|
| D1 | 2026-04-17 | 分发-adapter 路线(不自建 agent) | 用户选;get-shit-done 14 runtime 验证 |
|
|
1595
|
-
| D2 | 2026-04-17 |
|
|
1587
|
+
| D2 | 2026-04-17 | 当前 runtime:Claude + OpenCode + Codex | 0.6.0 收敛后的支持边界 |
|
|
1596
1588
|
| D3 | 2026-04-17 | 包名 `ultra-builder-pro-cli`,短名 `ubp` | 用户选 |
|
|
1597
1589
|
| D4 | 2026-04-17 | 发布渠道:npm + Homebrew + pip | 用户选 |
|
|
1598
1590
|
| D5 | 2026-04-17 | 销毁旧 git,main 重建 | 用户选;历史存 bundle |
|
|
@@ -1601,7 +1593,7 @@ Week 18 buffer(ship 中任何 Phase 的 25% 滑动吃掉)
|
|
|
1601
1593
|
| D8 | 2026-04-17 | settings.json 精简为最小合并模板 | 隐私安全 |
|
|
1602
1594
|
| D9 | 2026-04-17 | README 改写延 Phase 9 | 不阻塞开发 |
|
|
1603
1595
|
| D10 | 2026-04-17 | `hooks/tests/` 不入 npm tarball | 包体精简 |
|
|
1604
|
-
| D11 | 2026-04-17 | 基于官方文档重做 §5 + Phase 2/3 + §9 + §10 |
|
|
1596
|
+
| D11 | 2026-04-17 | 基于官方文档重做 §5 + Phase 2/3 + §9 + §10 | OpenCode、Codex 与 Claude Code 的官方命令、配置、skill、hook 和 subagent 文档 |
|
|
1605
1597
|
| **D12** | **2026-04-17** | **采用 skill + MCP + CLI 三层架构**,skill=说明书、MCP=状态操作主路径、CLI=Bash 兜底 | 参考 CTM(MCP 模式)+ OMC/OMX(skill 模式)+ get-shit-done(CLI 模式);三层分工覆盖 "knowledge / state / hook" 三类需求 |
|
|
1606
1598
|
| **D13** | **2026-04-17** | **规则层 / 执行层双时间线交付**(Phase 1-4 规则层 → v0.1;Phase 5-8 执行层 → v0.2-v0.3) | 用户明确"规则 vs 自动化执行"的维度;降低单次发布复杂度;早让用户拿到可用价值 |
|
|
1607
1599
|
| **D14** | **2026-04-17** | **范围从"分发器"扩展到"自动化 coding 工厂"**,总工时从 4-5 周扩到 11-13 周 | 用户诉求:跨 agent 上下文共享 + 独立对话避污染 + 监控 + 实时代码图 + 记忆系统;不只是 distribution tool |
|
|
@@ -1631,15 +1623,16 @@ Week 18 buffer(ship 中任何 Phase 的 25% 滑动吃掉)
|
|
|
1631
1623
|
| **D38** | **2026-04-17** | **Phase 1 完成** — `spec/` 锁死三层契约:30 个 MCP tool / 7 表 SQLite schema / tasks 与 context 投影 schema / skill manifest / CLI 协议 + 映射表;`npm run test:spec` 5 validator 全绿;新增 `docs/ARCHITECTURE.md` | Phase 1 gate 全过;后续 Phase 只引用 spec/,不再发明 schema |
|
|
1632
1624
|
| **D39** | **2026-04-17** | **Phase 2 完成** — 权威状态层落地:`.ultra/state.db` (7 表 WAL+busy_timeout)、`mcp-server/lib/{state-db,state-ops,projector}.cjs`、`mcp-server/server.cjs`(@modelcontextprotocol/sdk stdio + 7 task.*)、`ultra-tools {db,migrate}` 子命令、`STATE-DB-ACCESS-POLICY.md` + `COMMIT-HASH-BACKFILL.md`;6 gate 全过(20 worker / 3 进程并发 / migration 可逆 / DB 运维 4 子命令 / 投影 ≤1s / task.* MCP 契约 + events.id 无漏);`npm run test:state` 44/44 + `npm run test:spec` 5/5 | Phase 2 gate 全过;spec → state-ops → MCP 写路径成形,Phase 3 命令薄壳化可以基于 task.* MCP tool 重写 |
|
|
1633
1625
|
| **D40** | **2026-04-17** | **Phase 3 完成** — 命令规则化三层迁移:9/9 命令薄壳化(36-54 行,平均 41 行)+ 7 个新 skill (`skills/ultra-{init,plan,dev,test,deliver,status,think,learn}/SKILL.md` 148-340 行) + `skills/ultra-research/SKILL.md` frontmatter 升级;新 MCP tool `task.init_project` + 内置 `templates/.ultra/` 骨架 + `ultra-tools task init-project` CLI;`spec/command-template.md` + `command-manifest.schema.json` + `validate-commands.cjs`(UBP_COMMAND_STRICT=1 9/9 通过);`docs/AGENT-CONTEXT.md` canonical runtime 规则源;`hooks/{adapters,core}/` 骨架 + 4 个 runtime adapter stub;`test:state` 54/54 (+10) + `test:spec` 6/6 (+1) + strict-mode command gate 9/9 migrated 0 failed | Phase 3 gate 全过;skill+MCP+CLI 三层模式在 9 命令全部闭环;Phase 4 adapter 阶段可以直接基于 `docs/AGENT-CONTEXT.md` canonical + hooks/adapters/ stub 展开 |
|
|
1634
|
-
| **D41** | **2026-04-17** | **Phase 4
|
|
1626
|
+
| **D41** | **2026-04-17** | **Phase 4 初始跨 runtime 分发里程碑** — adapter、能力矩阵、smoke flow 与 installer 装配首次闭环;0.6.0 后只保留 Claude Code、OpenCode、Codex 三个 native plugin | 历史里程碑;当前边界由 D51 覆盖 |
|
|
1635
1627
|
| **D46** | **2026-04-17** | **Phase 7 完成 — 智能层落地** — 偏离原 PLAN:**不内嵌 hindsight-server(Python/Docker),改自建 SQLite FTS5 memory store**(理由:PLAN 自己说"避免 Docker"已承认痛点;Node 内嵌 Python 要 subprocess/HTTP 胶水,成本高于直接用 state.db)。**7.1 Memory store**:schema 升 5.2 → 7.1,新增 `memory_entries` 表(task_id/session_id/tag/kind/content/source/ts;kind CHECK `fact/decision/error_fix/pattern/note`)+ `memory_fts` FTS5 虚表 + 3 trigger(ai/ad/au 同步);`mcp-server/lib/memory-store.cjs` retain/recall/reflect 三函数(FTS5 MATCH 构造 escape 用 quote-wrap 防注入;空 query → 近期条目 fallback;bm25 ranking);3 MCP tool `memory.retain/recall/reflect`(spec/mcp-tools.yaml 老 schema 用 scope/ttl_days 方案 → 替换为 kind 方案,更贴事件自动提取);`orchestrator/memory-wrapper.cjs` autoRecallOnSpawn(task.title+trace_to → recall → prefetch.md)+ autoRetainOnClose(event-type heuristic 映射 task_completed→decision / task_circuit_broken→error_fix / session_crashed→pattern / task_stale_marked→fact;**不调 LLM**);session-runner opt-in `autoMemory: true`。**7.2 Tagged task lists**:`deriveBranchTag(cwd)` 用 `spawnSync`(非 throw, 状态码判断) 读 git symbolic-ref + `sanitizeTag`(slash→hyphen, @→dot, 非 `\w.-` 剥离, ≤100 chars);`switchTaskTag` + `task_tag_changed` event;`createTask` 接 `_cwd` 字段自动推导 tag 不覆盖显式传入;MCP `task.switch_tag` + spec/cli-protocol.md 加 33rd mapping;daemon `branchScoped: true` 过滤 pending by current branch tag。**7.3 Skill 萃取(heuristic, 0 LLM cost)**:`orchestrator/skill-miner.cjs` mineSession 扫 session events → 3 signal 触发(`task_completed` → task-completion / `task_circuit_broken` → debug-pattern / `session_crashed` → recovery-pattern)→ 写 `skills/learned/<ts>_<sid>_unverified.md` 含 YAML frontmatter + Problem/Signal/Evidence/Suggested reuse 4 section;idempotent(同 sid 再跑检到已有 draft 则 skip);session-runner opt-in `mineSkill: true` + `skillsRoot`。**聚合**:Phase 7 新增 38 tests(memory-store 11 + memory-wrapper 7 + tagged-tasks 11 + skill-miner 7 + server-contract 1 memory roundtrip + daemon 1 branchScoped),D45 基线 232 → **270 tests 全绿**,0 回归。schema_version 升到 7.1(第三个 seed 行),RequiredTables 加 `memory_entries` | v0.3 准备期:用户现在每 task 起步自动拿到相关历史 prefetch;branch 切换自动过滤任务;debug / crash / 完成自动生成 skill draft;所有 opt-in 默认关,不破坏现有集成 |
|
|
1636
|
-
| **D45** | **2026-04-17** | **Phase 4 backlog
|
|
1637
|
-
| **D44** | **2026-04-17** | **Phase 6 完成** —
|
|
1628
|
+
| **D45** | **2026-04-17** | **Phase 4 backlog 与 full conformance 完工** — 共享 capability assertions、三宿主 install/MCP/hook/skill/idempotency 覆盖与 `resolveTarget` 合约形成自动化防护网 | 当前三宿主 conformance 继续保留并由退役回归契约补强 |
|
|
1629
|
+
| **D44** | **2026-04-17** | **Phase 6 完成** — RTK soft dependency、三宿主 pricing/telemetry、成本面板与 code-graph watcher 落地 | 0.6.0 runtime allowlist 同步约束 telemetry 写入 |
|
|
1638
1630
|
| **D43** | **2026-04-17** | **Phase 5 完成** — 执行层进阶四件套落地:(5.1) `orchestrator/recovery.cjs` `recoverOnBoot` 扫 orphan 用 `process.kill(pid,0)` 探测 pid 存活,死的 → crashed + `task_failure` event(5 tests 含 kill -9 真实集成);(5.2) `circuit_breaker` 表(schema_version 升 4.5 → 5.2,`ensureSchemaVersion` 从 "latest row" 改 "exact match" 解决同 ms seed 排序不稳)+ `recordTaskFailure` 计数器(连续 ≥3 → `tripped_at` + `task_circuit_broken` 一次性 event)+ `resetCircuitBreaker` + `admissionCheck` 短路 `blocked_by_breaker` + `spawnSession` 抛 `CIRCUIT_TRIPPED`(7 tests,含 takeover 不可越过熔断);(5.3) `markTasksStaleBySpecSections` + `consumeSpecChangedEvents` 游标消费 + projector `⚠️ STALE` banner(只对 pending + 幂等,10 tests);(5.4) `orchestrator/daemon.cjs` 轮询 + `routeTask` 按 complexity_hint(haiku/sonnet/opus) 最简路由 + `bin/orchestrator.js` 四子命令 `run/start/stop/status` + `settings.json` `orchestrator.auto_dispatch` opt-in gate(11 tests + 手测 opt-in 拒启/pidfile 生命周期);Recovery 明确不自动 retry(retry 留给 Phase 8B),仅计失败交给熔断;总计 108 tests 全绿(state 76 + orch 26 + spec 6),原 118 基线 +35 无回归 | v0.2 执行层进阶完工;可起 daemon 自动捡 pending task,熔断+恢复+staleness 闭环 |
|
|
1639
1631
|
| **D42** | **2026-04-17** | **Phase 4.5 完成 — v0.1 发布就绪点** — execution-lite 落地:MCP 新增 7 个 session.* tool(spawn/close/get/list/admission_check/heartbeat/subscribe_events;spec 新增 session.list + meta-schema errors minItems 兼容);state-ops 新增 readSession / heartbeatSession / admissionCheck / reapOrphanSessions(D32/D33);`orchestrator/session-runner.cjs` 真 git worktree + child_process + state.db sessions 表 lease/heartbeat(替代 lease.json 文件 — grep 证代码零出现);`ultra-tools session {list,admission,reap,get,heartbeat,close,subscribe}` 7 verb CLI;skills/ultra-status 升级读 session.list + session.subscribe_events;Phase 4.5 gate 全过(2 并发 session 隔离 / 并发 spawn 单活 / kill -9 → orphan 识别 / event subscribe ≤1s latency / 无文件+表双源);总计 118 tests 全绿(state 59 + orch 8 + spec 6 + adapter/conformance/install 45);0 回归 | v0.1 发布就绪点达成:用户装上即可跨 4 runtime 手动并发跑任务、会话独立、事件订阅、活跃会话可见。真·可用最小单元 |
|
|
1640
1632
|
| **D47** | **2026-04-17** | **Phase 8A 完成 — planner 线就绪** — PRD → task graph → execution-plan 全链 MCP:(8A.0) schema 升 7.1 → 8A.1,tasks.parent_id TEXT REFERENCES tasks(id) ON DELETE SET NULL + `tasks_parent` 部分索引;EXPECTED_VERSION bump。(8A.1) `lib/llm-client.cjs` 官方 SDK 双 provider(`@anthropic-ai/sdk` + `openai`,+2 devDeps,用户选 D)按 model 前缀推(claude|opus|sonnet|haiku → anthropic;gpt|o1|o3 → openai),统一 `completeJson({system, user, maxTokens})`;`lib/prd-parser.cjs` Test Double 注入;`orchestrator/planner/prd-prompt.cjs` 模板;`task.parse_prd` input 加 `dry_run`(默认 false)实现 human-gate preview→approve;server.cjs dispatchTool 改 async。(8A.2) `lib/topo.cjs` Kahn + Tarjan SCC — 外部 dep 视已满足;有环返 CYCLE_DETECTED + `err.details.cycles`;errorResponse 扩展 optional `details`。(8A.3) `lib/task-expander.cjs` LLM prompt(sub_count 默认 3)→ 原子 tx(createTask children with parent_id + patchTask parent.status='expanded' → 自动 emit task_expanded);server 前置 parent 检查避免无谓 LLM client 构造。(8A.4a) `orchestrator/planner/plan-builder.cjs` Functional Core;`listWaveConflicts` pair-wise files_modified 交集;parallel wave 取 max(complexity),serial sum;cost 用 `pricing.computeCost`。(8A.4b) `lib/plan-store.cjs` `writeAtomic` 原子落 `.ultra/execution-plan.json`;`loadPlanArtifact` corrupt→null;`selectSection` 投影 tasks/topo/conflicts/all;emit plan_approved。(8A.5) `skills/ultra-plan` PRD Direct workflow — dry_run=true parse → buildPlan → ask.question → approve 走 dry_run=false + plan.export / reject 0 写入;frontmatter mcp_tools_required +5 tool。**spec 扩展**:task.create input 加 `files_modified` + `parent_id`;task.parse_prd input 加 `dry_run`。D46 基线 270 → **361 tests 全绿**(+91:state +71 / orch +20 / spec +5);0 回归 | v0.3 planner 里程碑就绪;execution-plan.json 是 Phase 8B 的权威输入;dry_run 是 human-gate 最小扩展 |
|
|
1641
1633
|
| **D48** | **2026-04-18** | **Phase 8B 完成 — executor 线就绪,v0.3 coding 工厂可用** — (8B.0) schema 不动(tasks.files_modified/session_id/parent_id 齐备);events 新增 5 type(wave_started / wave_completed / plan_completed / merged_back / merge_conflict),利用 events.type 无 CHECK 约束向后兼容。(8B.1) `orchestrator/dispatch-rules.cjs` 声明式规则数组(GSD-2 模式):`evaluate(ctx, rules)` 按 priority 取首个 match 返 `{rule_id, action, runtime}`;3 action(`spawn_agent`/`defer`/`block`);6 DEFAULT_RULES(breaker-blocked / deps-not-ready / no-runtimes / wave-conflict / by-preference / fallback-first-available);ROUTE_PREFERENCES 从 daemon.cjs 移过来;daemon.routeTask 改为 `evaluate` 的 thin wrapper,Phase 5.4 daemon 6 routeTask 测试 0 回归。(8B.2) `orchestrator/parallel-orchestrator.cjs` 读 plan waves → wave.parallel=true 批 `Promise.all` / parallel=false await 串行;前置 dispatch-rules.evaluate;`STATUS_TRANSITIONS` 约束要求 spawn 后 patchTask(in_progress),exit 后 patchTask(completed|pending);失败 task 不短路同 wave 其他任务;`finalizeSession` 调 `closeSession` 统一 session+worktree+可选 autoMerge 生命周期;runPlan 加 `autoMerge`/`mergeBaseBranch` opt-in(默认关,Phase 4/5/6/7/8A 0 回归)。(8B.3) `orchestrator/worktree-manager.cjs` N 并发 git worktree 注册簿:allocate/release/listActive/releaseAll;`listActive` 用 `git worktree list --porcelain` + realpath 规范化(macOS `/var`↔`/private/var` 符号链接坑)+ `.ultra/worktrees/` 域过滤;`releaseAll` 兼作崩溃恢复(git-tracked 清理 + 文件系统孤儿 sweep);Node 单线程 execFileSync 天然序列化避免 `.git/config.lock` 竞争。(8B.4) `orchestrator/auto-merge.cjs` — autoMerge 三出口(no_changes / merged_back / merge_conflict);冲突路径用 `git diff --name-only --diff-filter=U` 在 abort 之前收集;closeSession 加 `autoMerge`/`mergeBaseBranch` opt-in,conflict 时强制 `remove_worktree=false` 保留 worktree 给人。(8B.5 gate) `orchestrator/tests/phase-8b-gate.test.cjs` 三条 gate 全过:10-task PRD 端到端完成率 100%(要求 ≥80%);5 slice 压力 0 git lock 错误;merge 冲突正确识别 + conflict_paths 准确。**总计 +36 tests**(dispatch-rules +12 / worktree-manager +8 / parallel-orchestrator +7 / auto-merge +6 / gate +3),D47 基线 361 → **397 tests 全绿**(state 182 / orch 103 / spec 6 / rest 106),0 回归 | **v0.3 = 自动化 coding 工厂**:8A plan → 8B 执行 → 冲突人审 全链打通;autoMerge 默认关保留手动控制;worktree 全生命周期可观测可恢复 |
|
|
1642
1634
|
| **D50** | **2026-07-15** | **重划插件与记忆边界**:Claude Code、Codex、OpenCode 改为各自 native plugin;只打包 10 个 Ultra 公共 workflow、4 个 agent-only 规则 skill 与宿主专属 collab companion;删除 6 个外部 skill、recall、Impeccable 残留、Ultra memory MCP/store/wrapper/capture hooks;持久记忆由独立 cloud-mem/claude-mem 负责;用户 handbook 通过可预览、可备份的 managed block 显式同步 | 用户确认最终方案;运行时 allowlist、conformance、hook 与 handbook 回归测试共同锁定边界 |
|
|
1635
|
+
| **D51** | **2026-07-17** | **runtime 收敛为 Claude Code、OpenCode、Codex**:删除第四 runtime 的 adapter、安装参数、collab skill、prompt、schema、pricing、调度与测试面;`ultra-verify` 改为当前宿主主责加单一只读外部顾问 | 用户确认不再需要第四 runtime;0.6.0 退役契约阻止其重新进入活跃源码或发布包 |
|
|
1643
1636
|
|
|
1644
1637
|
---
|
|
1645
1638
|
|
|
@@ -1651,8 +1644,8 @@ Week 18 buffer(ship 中任何 Phase 的 25% 滑动吃掉)
|
|
|
1651
1644
|
- **activity-log**:**state.db `events` 表**(v0.3 起不再是文件);append-
|
|
1652
1645
|
only 事件流;Phase 2 建立,全程消费;`.ultra/activity-log.json` 是可选
|
|
1653
1646
|
只读导出。
|
|
1654
|
-
- **AGENTS.md**:各 runtime 原生的项目上下文文件(Claude
|
|
1655
|
-
|
|
1647
|
+
- **AGENTS.md**:各 runtime 原生的项目上下文文件(Claude 使用 CLAUDE.md);
|
|
1648
|
+
Phase 3.7 统一注入。
|
|
1656
1649
|
- **DISPATCH_RULES**:GSD-2 的声明式分派规则表,Phase 8B 移植。
|
|
1657
1650
|
- **Execution-lite**:v0.1 发布的最小执行层 = session 标准单元 + admission
|
|
1658
1651
|
+ event subscribe + 活跃会话可见;Phase 4.5 / D19。
|
package/docs/ROADMAP.md
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
> live in PLAN. If they disagree, PLAN wins.
|
|
6
6
|
|
|
7
7
|
**Goal**: distribute the Ultra Builder Pro engineering loop as native Claude
|
|
8
|
-
Code, OpenCode, and Codex plugins,
|
|
9
|
-
|
|
8
|
+
Code, OpenCode, and Codex plugins, and run it with isolated sessions sharing one
|
|
9
|
+
authoritative workflow store.
|
|
10
10
|
|
|
11
11
|
**First-class runtimes**: Claude Code · OpenCode · Codex.
|
|
12
12
|
|
|
@@ -72,7 +72,7 @@ ultra-tools/ ← CLI fallback, migration, and diagnostics
|
|
|
72
72
|
|
|
73
73
|
bin/install.js ← multi-runtime installer
|
|
74
74
|
bin/handbook.js ← explicit managed user-handbook sync
|
|
75
|
-
adapters/ ← native Claude/OpenCode/Codex plugin builders
|
|
75
|
+
adapters/ ← native Claude/OpenCode/Codex plugin builders
|
|
76
76
|
skills/ ← allowlisted Ultra workflows, internal rules, and collab companions
|
|
77
77
|
hooks/ ← 7 workflow-only Python hooks; OpenCode uses native JavaScript hooks
|
|
78
78
|
docs/
|
|
@@ -1,89 +1,88 @@
|
|
|
1
1
|
# Runtime Compatibility Matrix
|
|
2
2
|
|
|
3
3
|
Current presentation contract for Ultra Builder Pro. Claude Code, OpenCode, and
|
|
4
|
-
Codex are
|
|
5
|
-
|
|
6
|
-
`adapters/_shared/runtime-assets.cjs`.
|
|
4
|
+
Codex are the supported native plugin hosts. The canonical asset boundary lives
|
|
5
|
+
in `adapters/_shared/runtime-assets.cjs`.
|
|
7
6
|
|
|
8
|
-
Legend: **FULL** = native host surface, **DEGRADED** =
|
|
7
|
+
Legend: **FULL** = native host surface, **DEGRADED** = supported but missing an
|
|
9
8
|
equivalent lifecycle/control surface, **N/A** = intentionally not installed.
|
|
10
9
|
|
|
11
10
|
## 1. Plugin and workflow surface
|
|
12
11
|
|
|
13
|
-
| Capability | Claude Code | OpenCode | Codex |
|
|
14
|
-
|
|
15
|
-
| Package form | `.claude-plugin` native plugin | native config bundle + JS plugin | personal `.codex-plugin` |
|
|
16
|
-
| Public entry | `/ultra-*`, `/learn` | `/ultra-*`, `/learn` | `$ultra-builder-pro:<skill>` |
|
|
17
|
-
| Public Ultra workflows | 10 | 10 | 10 |
|
|
18
|
-
| Internal agent-rule skills | 4, non-user-facing | 4, non-user-facing | 4 with implicit invocation disabled |
|
|
19
|
-
| Collaboration companions | `codex-collab`, `
|
|
20
|
-
| External browser/deploy/framework skills | N/A | N/A | N/A |
|
|
12
|
+
| Capability | Claude Code | OpenCode | Codex |
|
|
13
|
+
|---|---|---|---|
|
|
14
|
+
| Package form | `.claude-plugin` native plugin | native config bundle + JS plugin | personal `.codex-plugin` |
|
|
15
|
+
| Public entry | `/ultra-*`, `/learn` | `/ultra-*`, `/learn` | `$ultra-builder-pro:<skill>` |
|
|
16
|
+
| Public Ultra workflows | 10 | 10 | 10 |
|
|
17
|
+
| Internal agent-rule skills | 4, non-user-facing | 4, non-user-facing | 4 with implicit invocation disabled |
|
|
18
|
+
| Collaboration companions | `codex-collab`, `ultra-verify` | `cc-collab`, `codex-collab`, `ultra-verify` | `cc-collab`, `ultra-verify` |
|
|
19
|
+
| External browser/deploy/framework skills | N/A | N/A | N/A |
|
|
21
20
|
|
|
22
|
-
Codex
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
Codex converts the workflows into namespaced skills and records nine legacy
|
|
22
|
+
command mappings in `command-map.json`; `ultra-review` remains directly
|
|
23
|
+
invocable as a skill.
|
|
25
24
|
|
|
26
25
|
## 2. Agents and collaboration
|
|
27
26
|
|
|
28
|
-
| Capability | Claude Code | OpenCode | Codex |
|
|
29
|
-
|
|
30
|
-
| Bundled review/debug agents | FULL, native Markdown agents | FULL,
|
|
31
|
-
| Native bounded delegation |
|
|
32
|
-
| Cross-host advisor | explicit
|
|
33
|
-
| Primary-agent ownership | FULL | FULL | FULL |
|
|
27
|
+
| Capability | Claude Code | OpenCode | Codex |
|
|
28
|
+
|---|---|---|---|
|
|
29
|
+
| Bundled review/debug agents | FULL, native Markdown agents | FULL, native agent frontmatter | FULL, nine managed TOML custom agents |
|
|
30
|
+
| Native bounded delegation | native agent surface | native agent surface | native Codex subagents |
|
|
31
|
+
| Cross-host advisor | explicit and read-only | explicit and read-only | explicit and read-only |
|
|
32
|
+
| Primary-agent ownership | FULL | FULL | FULL |
|
|
34
33
|
|
|
35
|
-
No bundled agent
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
No bundled agent owns private persistent memory. It receives current-checkout
|
|
35
|
+
evidence and bounded context from the primary host, then returns a result for
|
|
36
|
+
primary verification.
|
|
38
37
|
|
|
39
38
|
## 3. Workflow hooks
|
|
40
39
|
|
|
41
|
-
| Lifecycle | Claude Code | OpenCode | Codex |
|
|
42
|
-
|
|
43
|
-
| Session context/health | FULL, native `SessionStart` | FULL, system transform + event refresh | FULL, native `SessionStart` |
|
|
44
|
-
| Active edit boundary | FULL, `PreToolUse Edit|Write` | FULL, `tool.execute.before` rejects projection writes | FULL, `PreToolUse Edit|Write|apply_patch` |
|
|
45
|
-
| Compaction recovery | FULL, `PreCompact` +
|
|
46
|
-
| Incomplete-stop gate | FULL, native blocking `Stop`
|
|
47
|
-
| Subagent lifecycle evidence | FULL | DEGRADED, no equivalent packaged event | FULL |
|
|
40
|
+
| Lifecycle | Claude Code | OpenCode | Codex |
|
|
41
|
+
|---|---|---|---|
|
|
42
|
+
| Session context/health | FULL, native `SessionStart` | FULL, system transform + event refresh | FULL, native `SessionStart` |
|
|
43
|
+
| Active edit boundary | FULL, `PreToolUse Edit|Write` | FULL, `tool.execute.before` rejects projection writes | FULL, `PreToolUse Edit|Write|apply_patch` |
|
|
44
|
+
| Compaction recovery | FULL, `PreCompact` + resume matcher | FULL, native compacting context | FULL, `PreCompact` + `PostCompact` |
|
|
45
|
+
| Incomplete-stop gate | FULL, native blocking `Stop` | DEGRADED, no equivalent blocking stop hook | FULL, native blocking `Stop` |
|
|
46
|
+
| Subagent lifecycle evidence | FULL | DEGRADED, no equivalent packaged event | FULL |
|
|
48
47
|
|
|
49
48
|
All reachable hooks are workflow-only and no-op without an active non-terminal
|
|
50
|
-
`.ultra/workflow-state.json`. No
|
|
51
|
-
|
|
49
|
+
`.ultra/workflow-state.json`. No host receives Ultra prompt capture, transcript
|
|
50
|
+
capture, observation journaling, session-summary memory, generic command
|
|
52
51
|
blocking, or generic post-edit policy.
|
|
53
52
|
|
|
54
53
|
## 4. MCP and state
|
|
55
54
|
|
|
56
|
-
| Capability | Claude Code | OpenCode | Codex |
|
|
57
|
-
|
|
58
|
-
| stdio MCP registration | plugin `.mcp.json` | `opencode.json` local MCP entry | plugin `.mcp.json` |
|
|
59
|
-
| Live contracts | 21 | 21 | 21 |
|
|
60
|
-
| Declared
|
|
61
|
-
| Nine non-live contracts | host-native review/discovery/ask
|
|
62
|
-
| Durable authority | project `.ultra/state.db` | project `.ultra/state.db` | project `.ultra/state.db` |
|
|
63
|
-
| Ultra memory API | N/A | N/A | N/A |
|
|
55
|
+
| Capability | Claude Code | OpenCode | Codex |
|
|
56
|
+
|---|---|---|---|
|
|
57
|
+
| stdio MCP registration | plugin `.mcp.json` | `opencode.json` local MCP entry | plugin `.mcp.json` |
|
|
58
|
+
| Live contracts | 21 | 21 | 21 |
|
|
59
|
+
| Declared contracts | 30 | 30 | 30 |
|
|
60
|
+
| Nine non-live contracts | host-native review/discovery/ask | host-native review/discovery/ask | `codex-capability-map.json` |
|
|
61
|
+
| Durable authority | project `.ultra/state.db` | project `.ultra/state.db` | project `.ultra/state.db` |
|
|
62
|
+
| Ultra memory API | N/A | N/A | N/A |
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
`
|
|
67
|
-
|
|
64
|
+
Only the 21 `task.*`, `session.*`, and `plan.*` operations registered by
|
|
65
|
+
`mcp-server/server.cjs` are advertised as live. Review, impact, skill, and user
|
|
66
|
+
interaction remain host-native surfaces.
|
|
68
67
|
|
|
69
68
|
## 5. User handbook presentation
|
|
70
69
|
|
|
71
|
-
| Capability | Claude Code | OpenCode | Codex |
|
|
72
|
-
|
|
73
|
-
| Durable user file | `~/.claude/CLAUDE.md` | `~/.config/opencode/AGENTS.md` | `~/.codex/AGENTS.md` |
|
|
74
|
-
| Automatic overwrite by plugin install | no | no | no |
|
|
75
|
-
| Explicit managed-block sync | `ubp-handbook --runtime claude` | `ubp-handbook --runtime opencode` | `ubp-handbook --runtime codex` |
|
|
76
|
-
| Backup before change | FULL | FULL | FULL |
|
|
70
|
+
| Capability | Claude Code | OpenCode | Codex |
|
|
71
|
+
|---|---|---|---|
|
|
72
|
+
| Durable user file | `~/.claude/CLAUDE.md` | `~/.config/opencode/AGENTS.md` | `~/.codex/AGENTS.md` |
|
|
73
|
+
| Automatic overwrite by plugin install | no | no | no |
|
|
74
|
+
| Explicit managed-block sync | `ubp-handbook --runtime claude` | `ubp-handbook --runtime opencode` | `ubp-handbook --runtime codex` |
|
|
75
|
+
| Backup before change | FULL | FULL | FULL |
|
|
77
76
|
|
|
78
77
|
## 6. Install, update, and uninstall
|
|
79
78
|
|
|
80
|
-
| Capability | Claude Code | OpenCode | Codex |
|
|
81
|
-
|
|
82
|
-
| Adapter install | FULL | FULL | FULL |
|
|
83
|
-
| Native
|
|
84
|
-
| Removes stale managed assets | FULL | FULL | FULL |
|
|
85
|
-
| Preserves unrelated
|
|
86
|
-
| Uninstall ownership guard | managed plugin root | sentinels + owned MCP entry | managed root/manifest/agent headers |
|
|
79
|
+
| Capability | Claude Code | OpenCode | Codex |
|
|
80
|
+
|---|---|---|---|
|
|
81
|
+
| Adapter install | FULL | FULL | FULL |
|
|
82
|
+
| Native update | next host session | host restart | cachebuster + `codex plugin add`, then new task |
|
|
83
|
+
| Removes stale managed assets | FULL | FULL | FULL |
|
|
84
|
+
| Preserves unrelated config | FULL | FULL | FULL |
|
|
85
|
+
| Uninstall ownership guard | managed plugin root | sentinels + owned MCP entry | managed root/manifest/agent headers |
|
|
87
86
|
|
|
88
87
|
## 7. Verification sources
|
|
89
88
|
|
|
@@ -91,8 +90,10 @@ operations registered by `mcp-server/server.cjs` are advertised as live.
|
|
|
91
90
|
- `tests/conformance/<runtime>/*.test.cjs` verifies command/skill, hook, MCP,
|
|
92
91
|
idempotency, and smoke presentation.
|
|
93
92
|
- `adapters/_shared/tests/runtime-assets.test.cjs` prevents retired or external
|
|
94
|
-
skills and generic/memory hooks from re-entering
|
|
95
|
-
- `
|
|
96
|
-
|
|
93
|
+
skills and generic/memory hooks from re-entering a package.
|
|
94
|
+
- `tests/retired-runtime.test.cjs` prevents retired runtime code or prompt text
|
|
95
|
+
from re-entering active product surfaces.
|
|
96
|
+
- `adapters/_shared/tests/handbook.test.cjs` verifies host rendering, backup,
|
|
97
|
+
migration, and idempotency.
|
|
97
98
|
|
|
98
99
|
Any capability claim elsewhere must match current adapter code and these tests.
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
// Sources (2026-04):
|
|
10
10
|
// Claude: https://www.anthropic.com/pricing
|
|
11
11
|
// OpenAI: https://platform.openai.com/docs/pricing
|
|
12
|
-
// Gemini: https://ai.google.dev/pricing
|
|
13
12
|
//
|
|
14
13
|
// `default` inside each runtime is the fallback when a session did not
|
|
15
14
|
// record which specific model it used.
|
|
@@ -30,11 +29,6 @@ const PRICING = Object.freeze({
|
|
|
30
29
|
// treat as sonnet-equivalent unless a model name is passed in.
|
|
31
30
|
default: { input: 3e-6, output: 15e-6 },
|
|
32
31
|
}),
|
|
33
|
-
gemini: Object.freeze({
|
|
34
|
-
'gemini-2.5-pro': { input: 1.25e-6, output: 10e-6 },
|
|
35
|
-
'gemini-2.5-flash': { input: 0.15e-6, output: 0.6e-6 },
|
|
36
|
-
default: { input: 1.25e-6, output: 10e-6 },
|
|
37
|
-
}),
|
|
38
32
|
});
|
|
39
33
|
|
|
40
34
|
function computeCost(runtime, model, tokens_input, tokens_output) {
|
|
@@ -13,6 +13,7 @@ const path = require('node:path');
|
|
|
13
13
|
const { spawnSync } = require('node:child_process');
|
|
14
14
|
|
|
15
15
|
const { openStateDb } = require('./state-db.cjs');
|
|
16
|
+
const { isSupportedRuntime } = require('../../adapters/_shared/runtime-assets.cjs');
|
|
16
17
|
|
|
17
18
|
const STATUS_TRANSITIONS = Object.freeze({
|
|
18
19
|
pending: new Set(['in_progress', 'blocked', 'expanded']),
|
|
@@ -263,6 +264,9 @@ function appendEventInTx(db, event) {
|
|
|
263
264
|
if (!event || !event.type) {
|
|
264
265
|
throw new StateOpsError('VALIDATION_ERROR', 'event.type is required');
|
|
265
266
|
}
|
|
267
|
+
if (event.runtime != null && !isSupportedRuntime(event.runtime)) {
|
|
268
|
+
throw new StateOpsError('VALIDATION_ERROR', `unsupported runtime: ${event.runtime}`);
|
|
269
|
+
}
|
|
266
270
|
const result = db.prepare(
|
|
267
271
|
`INSERT INTO events (type, task_id, session_id, runtime, payload_json)
|
|
268
272
|
VALUES (?, ?, ?, ?, ?)`,
|
|
@@ -311,6 +315,9 @@ function createSession(db, { sid, task_id, runtime, pid = null, worktree_path, a
|
|
|
311
315
|
if (!sid || !task_id || !runtime || !worktree_path || !artifact_dir) {
|
|
312
316
|
throw new StateOpsError('VALIDATION_ERROR', 'sid, task_id, runtime, worktree_path, artifact_dir required');
|
|
313
317
|
}
|
|
318
|
+
if (!isSupportedRuntime(runtime)) {
|
|
319
|
+
throw new StateOpsError('VALIDATION_ERROR', `unsupported runtime: ${runtime}`);
|
|
320
|
+
}
|
|
314
321
|
const lease = new Date(Date.now() + lease_seconds * 1000).toISOString();
|
|
315
322
|
return tx(db, () => {
|
|
316
323
|
if (!readTask(db, task_id)) {
|
|
@@ -12,6 +12,7 @@ const fs = require('node:fs');
|
|
|
12
12
|
const path = require('node:path');
|
|
13
13
|
|
|
14
14
|
const { computeCost } = require('./pricing.cjs');
|
|
15
|
+
const { isSupportedRuntime } = require('../../adapters/_shared/runtime-assets.cjs');
|
|
15
16
|
|
|
16
17
|
function todayStamp() {
|
|
17
18
|
return new Date().toISOString().slice(0, 10);
|
|
@@ -33,6 +34,9 @@ function appendTelemetry(db, {
|
|
|
33
34
|
payload = null,
|
|
34
35
|
rootDir = '.',
|
|
35
36
|
} = {}) {
|
|
37
|
+
if (runtime != null && !isSupportedRuntime(runtime)) {
|
|
38
|
+
throw new Error(`unsupported runtime: ${runtime}`);
|
|
39
|
+
}
|
|
36
40
|
if (!event_type) throw new Error('appendTelemetry: event_type required');
|
|
37
41
|
|
|
38
42
|
// Auto-derive cost when tokens + runtime known and caller didn't supply one.
|
|
@@ -390,6 +390,23 @@ test('session.admission_check + session.spawn: happy path returns sid and paths'
|
|
|
390
390
|
}
|
|
391
391
|
});
|
|
392
392
|
|
|
393
|
+
test('session.spawn rejects a retired runtime at the MCP schema boundary', async () => {
|
|
394
|
+
const proj = tmpProject();
|
|
395
|
+
const retiredRuntime = ['gem', 'ini'].join('');
|
|
396
|
+
try {
|
|
397
|
+
await withClient(proj, async (client) => {
|
|
398
|
+
await seedTask(client, 's-runtime-guard');
|
|
399
|
+
const spawn = await client.callTool({
|
|
400
|
+
name: 'session.spawn',
|
|
401
|
+
arguments: { task_id: 's-runtime-guard', runtime: retiredRuntime },
|
|
402
|
+
});
|
|
403
|
+
assert.equal(expectError(spawn).code, 'VALIDATION_ERROR');
|
|
404
|
+
});
|
|
405
|
+
} finally {
|
|
406
|
+
fs.rmSync(proj.dir, { recursive: true, force: true });
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
|
|
393
410
|
test('session.spawn refuses second session for same task without takeover (ADMISSION_DENIED)', async () => {
|
|
394
411
|
const proj = tmpProject();
|
|
395
412
|
try {
|
|
@@ -194,6 +194,29 @@ test('createSession requires existing task and emits session_spawned', () => {
|
|
|
194
194
|
}
|
|
195
195
|
});
|
|
196
196
|
|
|
197
|
+
test('runtime-bearing mutations reject unsupported runtimes before touching state', () => {
|
|
198
|
+
const { dir, db } = freshDb();
|
|
199
|
+
const retiredRuntime = ['gem', 'ini'].join('');
|
|
200
|
+
try {
|
|
201
|
+
ops.createTask(db, { id: 'runtime-guard', title: 'guard', type: 'feature', priority: 'P1' });
|
|
202
|
+
assert.throws(
|
|
203
|
+
() => ops.createSession(db, {
|
|
204
|
+
sid: 'unsupported', task_id: 'runtime-guard', runtime: retiredRuntime,
|
|
205
|
+
worktree_path: '/tmp/wt', artifact_dir: '/tmp/art',
|
|
206
|
+
}),
|
|
207
|
+
(error) => error.code === 'VALIDATION_ERROR' && /unsupported runtime/.test(error.message),
|
|
208
|
+
);
|
|
209
|
+
assert.throws(
|
|
210
|
+
() => ops.appendEvent(db, { type: 'task_started', task_id: 'runtime-guard', runtime: retiredRuntime }),
|
|
211
|
+
(error) => error.code === 'VALIDATION_ERROR' && /unsupported runtime/.test(error.message),
|
|
212
|
+
);
|
|
213
|
+
assert.equal(db.prepare("SELECT COUNT(*) AS n FROM sessions").get().n, 0);
|
|
214
|
+
closeStateDb(db);
|
|
215
|
+
} finally {
|
|
216
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
|
|
197
220
|
test('updateSession status=completed emits session_closed', () => {
|
|
198
221
|
const { dir, db } = freshDb();
|
|
199
222
|
try {
|
|
@@ -140,6 +140,20 @@ test('appendTelemetry event_type constraint: invalid value rejected', () => {
|
|
|
140
140
|
} finally { teardown(dir, db); }
|
|
141
141
|
});
|
|
142
142
|
|
|
143
|
+
test('appendTelemetry rejects unsupported runtime labels', () => {
|
|
144
|
+
const { dir, db } = freshFixture();
|
|
145
|
+
const retiredRuntime = ['gem', 'ini'].join('');
|
|
146
|
+
try {
|
|
147
|
+
assert.throws(
|
|
148
|
+
() => telemetry.appendTelemetry(db, {
|
|
149
|
+
event_type: 'tool_call', runtime: retiredRuntime, rootDir: dir,
|
|
150
|
+
}),
|
|
151
|
+
/unsupported runtime/,
|
|
152
|
+
);
|
|
153
|
+
assert.equal(db.prepare('SELECT COUNT(*) AS n FROM telemetry').get().n, 0);
|
|
154
|
+
} finally { teardown(dir, db); }
|
|
155
|
+
});
|
|
156
|
+
|
|
143
157
|
// ─── aggregation ─────────────────────────────────────────────────────────
|
|
144
158
|
|
|
145
159
|
test('aggregateTelemetryByRuntime: groups calls + sums tokens/cost', () => {
|