Skip to content

Commit c4d43fc

Browse files
oratisoratisclaude
authored
docs: close out the governance layer and cut 0.3.0 (#245)
Records the threat-model delta, marks the adoption plan implemented with an honest deviation log, and bumps to 0.3.0 (minor, not patch: the unattended permission clamp in #244 is breaking on 0.x). security-model.md gains three threats (#8 in-project secret reads, #9 unattended permissive inheritance, #10 no audit or undo) and a residual-risk section stating plainly what the file contract is not. It constrains dispatcher tool calls, not Bash; path normalization is string math, not realpath. Describing it as secret protection would be the false confidence the plan named as this feature's main risk. The adoption plan now carries a deviation table rather than a claim of clean execution. Six entries, including two where the plan was simply wrong: PR 0's premise that unattended runs might silently allow (the ask path was already fail-closed), and the four-client consistency test (only two hosts resolve policy independently; VS Code and LSP consume the server's answer, and the tests say so instead of implying four verified paths). Two P2 items remain undone and are listed as such. Found while bumping: the repo's own version-consistency test caught Cargo.lock still pinning 0.2.0, a sixth location RELEASING.md's four-item list never mentioned. Both fixed. Co-authored-by: oratis <happyllammar@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent bb74ee3 commit c4d43fc

11 files changed

Lines changed: 163 additions & 20 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,94 @@ All notable changes to DeepCode are documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.3.0] — 2026-08-08
9+
10+
A workspace-governance layer: what the agent may touch, what it changed, and how
11+
to undo it. Derived from a first-hand study of Floatboat's open **Selfware
12+
protocol** — see [`docs/research/floatboat.md`](docs/research/floatboat.md) for
13+
the research (with evidence grading) and
14+
[`docs/FLOATBOAT_ADOPTION_PLAN.md`](docs/FLOATBOAT_ADOPTION_PLAN.md) for what was
15+
adopted, what was rejected, and where the implementation diverged from the plan.
16+
17+
### ⚠️ Breaking
18+
19+
- **Unattended runs no longer inherit a permissive permission mode.** A
20+
`permissions.defaultMode` of `bypassPermissions` or `acceptEdits` — chosen for
21+
interactive convenience — is clamped to `default` for scheduled jobs, which
22+
run with nobody present to approve anything. Set a job's `profile.mode`
23+
explicitly to opt back in. The clamp names itself and the fix in the job log
24+
on the first run after upgrading. (#244)
25+
26+
### 🔒 Security
27+
28+
- **`.env` could be read, and there was no way to say otherwise.** Permission
29+
rules match on the _tool_; their only path-aware match is a prefix compare
30+
against an argument that is usually an absolute path, so `Read(.env*)` matched
31+
nothing. The new [file contract](docs/file-contract.md) adds the missing axis —
32+
glob × read/write/execute × allow/ask/deny — composed with the existing rules
33+
by most-restrictive-wins. It can only tighten. (#238, #239)
34+
- A contract `deny` **cannot be waived by `bypassPermissions`**. It states
35+
something standing about a path rather than prompting about one call, so the
36+
mode that exists to skip prompts has no business clearing it. (#239)
37+
- Plugin subprocesses are gated by the same path rules; the capability bridge
38+
previously called the dispatcher without a contract. (#239)
39+
- `/combo` drafts exclude paths the contract denies reading and redact
40+
credential-shaped values. A rule that stops at the tool call but not at the
41+
export is not much of a rule. (#243)
42+
43+
### ✨ Added
44+
45+
- **File contract** — `deepcode contract <show|init|check>`. Optional; with no
46+
contract file, behaviour is unchanged. (#238, #239)
47+
- **Change ledger** — `deepcode ledger <list|show|export|rollback>`. An
48+
append-only record pairing each mutation with the request that motivated it
49+
and the checkpoint that reverses it, on two timelines (`changes`,
50+
`governance`). Stored outside the repository so `git status` stays clean.
51+
(#240, #241)
52+
- **No Silent Apply** — explain, preview, accept/reject/defer, rollback point
53+
first. `confirm` is a required argument, so a caller that cannot ask a human
54+
cannot apply. (#241)
55+
- **`runtime/capabilities`** — a protocol method answering what the runtime may
56+
write and which actions always stop for a human, distinct from `initialize`'s
57+
protocol-feature flags. The CLI and app-server build it through one function,
58+
with a test asserting they agree field-for-field. (#242)
59+
- **`/combo`** — distil a finished thread into a `SKILL.md` draft, with
60+
`allowed-tools` derived from the tools actually called. (#243)
61+
- **Trigger profiles** — per-job `mode`, `permissions`, and `sandbox` for
62+
scheduled work. Permissions and sandbox can only tighten. (#244)
63+
- `onApprovalRequired: 'abort'` for scheduled jobs, plus exit code `6`. A job
64+
whose first write is refused otherwise grinds on and reports a confidently
65+
wrong result. (#237)
66+
- `deepcode doctor` prints the runtime capability declaration and the
67+
file-contract warnings. (#242)
68+
69+
### 🐛 Fixed
70+
71+
- Aborting mid-batch left `tool_use` blocks unanswered, which a provider rejects
72+
on resume. Remaining calls now get an explicit "never ran" result. (#237)
73+
- `docs/cli-flags.md`'s exit-code table contradicted the implementation (it
74+
listed `3` as "tool denied" and `5` as "API key invalid"). Corrected against
75+
`apps/cli/src/headless.ts`, which owns the contract. (#237)
76+
77+
### 📄 Documentation
78+
79+
- New: [`docs/file-contract.md`](docs/file-contract.md),
80+
[`docs/change-ledger.md`](docs/change-ledger.md),
81+
[`docs/combo.md`](docs/combo.md),
82+
[`docs/research/floatboat.md`](docs/research/floatboat.md),
83+
[`docs/FLOATBOAT_ADOPTION_PLAN.md`](docs/FLOATBOAT_ADOPTION_PLAN.md).
84+
- `docs/security-model.md` gains threats #8–#10 and a **residual-risk** section
85+
stating plainly that the file contract is policy, not a boundary: it does not
86+
constrain Bash, and only the sandbox does.
87+
88+
### 🚫 Deliberately not adopted
89+
90+
`.self` self-executing distribution (a supply-chain surface for a coding agent),
91+
Floatboat's passive habit observation across files and browser tabs (a privacy
92+
line, and unnecessary — `/combo` gets the value from an explicit invocation),
93+
cross-organisation agent networks, and a second loopback HTTP runtime alongside
94+
the app-server. Reasoning in the adoption plan §3.
95+
896
## [0.2.0] — 2026-08-02
997

1098
Largest release so far: the desktop app, VS Code extension, and LSP server stop

‎README.md‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
DeepCode 让 DeepSeek 可以在本地代码库中执行读取、编辑、命令、审阅、MCP 和可恢复会话工作。项目最初以 Claude Code 兼容为目标,现在正转向经过验证的 Codex 式运行模型:统一任务生命周期、可靠中断、清晰权限边界和跨客户端一致行为。
1717

18-
- **已可用**:Node.js CLI、Tauri macOS 客户端、核心工具、MCP、hooks、skills、plugins、sandbox、sessions、background tasks 与 voice input。
18+
- **已可用**:Node.js CLI、Tauri macOS 客户端、核心工具、MCP、hooks、skills、plugins、sandbox、sessions、background tasks、voice input,以及 0.3.0 的工作区治理层(file contract、change ledger、runtime capabilities、`/combo`、trigger profile)。
1919
- **在收敛**:VS Code/LSP、统一权限、真实取消、thread/turn/item 协议与跨客户端恢复。
2020
- **兼容优先**:继续读取既有 `settings.json`、`DEEPCODE.md`、`AGENTS.md` 和 Claude 风格扩展资产,但不以未经验证的“1:1 parity”作为安全或完成度承诺。
2121
- **设计路线**:完整审查、正反方审议和分阶段 PR 见 [Codex alignment plan](docs/CODEX_ALIGNMENT_PLAN.md)。
@@ -53,6 +53,9 @@ Mac 客户端(v1 即将发布):拖入 Applications → 首启完成 onboar
5353
| [docs/BEHAVIOR_PARITY.md](docs/BEHAVIOR_PARITY.md) | 与 Claude Code 的逐项行为对比 |
5454
| [docs/SHIPPING_MAC.md](docs/SHIPPING_MAC.md) | 给 maintainer:Apple Dev ID + 签名 + 公证全流程 |
5555
| [docs/VOICE_INPUT.md](docs/VOICE_INPUT.md) | 装 whisper.cpp 本地语音输入 |
56+
| [docs/file-contract.md](docs/file-contract.md) | 路径维度权限契约(`deepcode contract`) |
57+
| [docs/change-ledger.md](docs/change-ledger.md) | 变更账本与回滚(`deepcode ledger`) |
58+
| [docs/combo.md](docs/combo.md) | `/combo` —— 把做完的 thread 蒸馏成 skill |
5659
| [docs/DEMO_SCRIPT.md](docs/DEMO_SCRIPT.md) | 5 分钟 launch 视频逐段录制脚本 |
5760

5861
### 设计文档
@@ -61,6 +64,8 @@ Mac 客户端(v1 即将发布):拖入 Applications → 首启完成 onboar
6164
| ---------------------------------------------------------------------------- | --------------------------------------------------- |
6265
| [docs/CODEX_ALIGNMENT_PLAN.md](docs/CODEX_ALIGNMENT_PLAN.md) | 当前整体改造计划、审计证据、正反方审议与 PR 路线 |
6366
| [docs/THREE_WAY_REVIEW.md](docs/THREE_WAY_REVIEW.md) | 与 Claude Code / Codex 的三方能力+界面对比与优先级 |
67+
| [docs/FLOATBOAT_ADOPTION_PLAN.md](docs/FLOATBOAT_ADOPTION_PLAN.md) | 工作区治理层的采纳/拒绝决策记录与实施偏差 |
68+
| [docs/research/floatboat.md](docs/research/floatboat.md) | Floatboat / Selfware 调研(带证据分级) |
6469
| [docs/DEVELOPMENT_PLAN.md](docs/DEVELOPMENT_PLAN.md) | 整体开发方案 v0.5(1500+ 行 / §3 模块 / §6 里程碑) |
6570
| [docs/VISUAL_DESIGN.html](docs/VISUAL_DESIGN.html) | 视觉设计 v0.4(11 屏 mockup) |
6671
| [docs/security-model.md](docs/security-model.md) | 威胁模型 + 防御层 + 攻击向量测试 + 已知缺口 |

‎apps/cli/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "deepcode-cli",
3-
"version": "0.2.0",
3+
"version": "0.3.0",
44
"description": "DeepCode CLI — DeepSeek-powered AI coding agent for real codebases",
55
"license": "MIT",
66
"type": "module",

‎apps/desktop/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@deepcode/desktop",
3-
"version": "0.2.0",
3+
"version": "0.3.0",
44
"private": true,
55
"description": "DeepCode Mac desktop client — Tauri + React",
66
"license": "MIT",

‎apps/desktop/src-tauri/Cargo.lock‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎apps/desktop/src-tauri/Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "deepcode_desktop"
3-
version = "0.2.0"
3+
version = "0.3.0"
44
description = "DeepCode Mac desktop client"
55
authors = ["oratis"]
66
edition = "2021"

‎apps/desktop/src-tauri/tauri.conf.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2",
33
"productName": "DeepCode",
4-
"version": "0.2.0",
4+
"version": "0.3.0",
55
"identifier": "dev.deepcode.desktop",
66
"build": {
77
"frontendDist": "../dist",

‎docs/FLOATBOAT_ADOPTION_PLAN.md‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# 用 Floatboat / Selfware 机制优化 DeepCode 的整体方案
22

3-
> 状态:**提案,未实现**。等待评审后再拆 PR。
3+
> 状态:**已实现**(2026-08-08,PR #237 / #238 / #239 / #240 / #241 / #242 / #243 / #244)。
4+
> 本文保留为决策记录 —— 采纳理由、拒绝理由和未解假设的最终结论都在这里。
45
> 基线:`main@ec94748` · 日期 2026-08-08
56
> 调研依据:[`docs/research/floatboat.md`](research/floatboat.md)(另一独立 PR)
67
> 与 [`CODEX_ALIGNMENT_PLAN.md`](CODEX_ALIGNMENT_PLAN.md) 的关系:**不取代,正交补充**。alignment plan
@@ -495,6 +496,27 @@ DeepCode 已有的更强项要保留:plugin 的 ed25519 签名 + 吊销列表
495496
合完就能回答"agent 改了什么"和"无人值守时会不会乱来"这两个最要紧的问题。
496497
File Contract 接入(PR 2)是唯一需要谨慎评审的一步。
497498

499+
### 4.1 实施后的偏差记录
500+
501+
写下与计划不符的地方,比宣称"照计划完成"有用。
502+
503+
| 项 | 计划 | 实际 |
504+
| ---------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
505+
| PR 0 的问题陈述 | 称无人值守可能"静默放行" | **计划写错了**。`ask` 路径本来就 fail-closed(`runHeadless` 传 `approval: async () => false`)。真正缺的是"停下来"的能力和可见性,PR #237 按事实重写了范围 |
506+
| 权限档位的钳制 | 放在 PR 0 | 推迟到 PR 7。没有 opt-in 的钳制只是破坏,等 `TriggerProfile` 落地才安全 |
507+
| 契约 `deny` 与 `bypassPermissions` | 计划未明确 | 实施时决定 **`deny` 不可被 `bypassPermissions` 豁免**。它是关于路径的常驻声明,不是逐次提示;否则契约最强的一句话也最容易被关掉 |
508+
| 四客户端一致性测试 | 计划要求 4 个客户端逐字段相等 | 实际只有 CLI 与 app-server **独立解析**策略;VS Code / LSP 是协议瘦客户端,逐字节消费 server 的答复,构造上即相等。测试断言前两者,并在文档里说明后两者的理由 —— 不宣称验证了 4 条独立路径 |
509+
| Grep/Glob 结果过滤 | 列为 PR 1 的已知缺口 | 仍未做。契约对 Grep/Glob 只裁决搜索根,命中结果里混入 deny 路径的内容需要工具输出层二次过滤 |
510+
| 制品 `provenance` | 列在 PR 8(P2) | 未做 |
511+
| 触发源抽象(ICS / watch) | 列在 PR 8(P2) | 未做。`cron` 仍只有时间源 |
512+
513+
**未解假设的最终结论**(§7 提的四个):
514+
515+
- **契约默认值**:`recommended` 预设三轴全 `allow`,只 deny 秘密类路径 + 对 agent 指令 / CI / settings 用 `ask`。
516+
- **ledger 默认开**:是。写入极轻且不参与裁决。
517+
- **`/combo` 调不调模型**:结构化部分(`allowed-tools`、步骤、文件)不调;prose 可选。无模型时的产物是可用草稿而非占位符。
518+
- **PR 2 与 alignment plan 的先后**:alignment plan 的 runtime host 收敛已在 0.2.0 完成,因此 PR 2 直接接入既有 `dispatchToolCall`,未产生冲突。
519+
498520
---
499521

500522
## 5. 与现有架构的冲突与化解

‎docs/RELEASING.md‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,15 @@ new token → **Automation** (CI-friendly) → save as `NPM_TOKEN`.
5252

5353
```bash
5454
# 1. Make sure main is green and CHANGELOG.md has an entry for the new version.
55-
# 2. Bump versions everywhere in lockstep:
56-
# - apps/cli/package.json
55+
# 2. Bump versions everywhere in lockstep — all SIX places:
56+
# - packages/core/src/index.ts (VERSION — what `deepcode --version` prints)
57+
# - apps/cli/package.json (what npm publishes)
5758
# - apps/desktop/package.json
5859
# - apps/desktop/src-tauri/tauri.conf.json
5960
# - apps/desktop/src-tauri/Cargo.toml
60-
# (The CI workflow also re-syncs these from the tag.)
61+
# - apps/desktop/src-tauri/Cargo.lock (CI runs `cargo check --locked`)
62+
# (The CI workflow also re-syncs some of these from the tag.)
63+
# `pnpm test` fails if any of them disagree — see scripts/version-consistency.test.ts.
6164
# 3. Tag + push:
6265

6366
git tag v0.1.3

0 commit comments

Comments
 (0)