Skip to content

Commit 07b8b8f

Browse files
oratisclaude
andauthored
docs+core: DEMO_SCRIPT + DNS resolv.conf integration + morning report v6 (#54)
· docs/DEMO_SCRIPT.md (NEW, ~150 lines) — 5-minute launch video script with shot-by-shot timing (Hook / REPL / plan-mode / skills / sub-agent + hooks / sandbox + permissions / Mac client / plugins / outro), recording checklist (mic, demo project, terminal theme, notifications off), post-production guide. · packages/core/src/sandbox/profile.ts — buildLinuxBwrapArgs now takes BwrapArgsOpts { dnsProxyPort?, resolvConfPath? }. When allowedDomains is non-empty + dnsProxyPort given, the args include `--unshare-net` AND `--ro-bind <resolv> /etc/resolv.conf` so the sandboxed process only resolves names via our DNS proxy. Closes the M3.5-ext "userspace DNS proxy + sandbox integration" item. · packages/core/src/sandbox/profile.test.ts — 2 new tests pinning the new behavior (resolv.conf bind ON when proxy provided; falls back to default-allow when proxy missing). · MORNING_REPORT.md v6 — refresh. 51+ feature PRs, 514 tests, ~98% v1 scope, complete shipping checklist with exact maintainer actions. Tests: 512 → 514 passing. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 76e0ad5 commit 07b8b8f

5 files changed

Lines changed: 318 additions & 61 deletions

File tree

MORNING_REPORT.md

Lines changed: 82 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,123 @@
1-
# 进度汇报 — 第五轮"继续推进"
1+
# 进度汇报 — 第六轮 "继续完成全部"
22

3-
> 持续覆盖。前四轮内容见 git 历史。
3+
> 持续覆盖。前五轮内容见 git 历史。
44
55
## TL;DR
66

7-
**48 个 commits / 38+ feature PRs · 508 个测试通过 · CI 双平台绿色 · ~95% v1 scope 在 main 上**
7+
**56+ 个 commits / 50+ feature PRs · 514 个测试通过 · CI 双平台绿色 · ~98% v1 scope 在 main 上**
88

9-
本轮在第四轮 33 PR 基础上又推了 4 个 feature PR + 几个 dependabot 合并:
9+
本轮在 v5 基础上又推了 4 个 feature PR:所有 11 个桌面屏幕落地、typed IPC
10+
协议骨架、Apple shipping + whisper.cpp 安装文档、release pipeline 收尾、
11+
demo 脚本、DNS 代理 resolv.conf 集成。
1012

1113
| # | 标题 | 主要内容 |
1214
| --- | --- | --- |
13-
| #46 | fix: worktree git env-var leak | husky pre-commit 上下文里 `GIT_DIR`/`GIT_WORK_TREE`/`GIT_INDEX_FILE` 泄漏给子进程;strip GIT_* env 在 runGit 和 runOrFail 里;worktree 测试不再 gated(5 个测试回到默认套件) |
14-
| #47 | feat: M9 + M3.5-ext + M8 三件套 | gen-release-notes 脚本(conventional-commit 分桶)+ DNS proxy (UDP NXDOMAIN scaffold) + `/effort` 交互选择器表格 |
15-
| #48 | feat(desktop): M6-rest part 1 | vite.config + tailwind.config + postcss.config + electron-builder.yml + entitlements.plist + index.html (CSP) — 全部 build 配置就位,`.template` 后缀避免依赖未装时的 vitest 故障 |
16-
| #49 | feat: M6-rest part 2 + M8 voice | WhisperCppProvider + VoiceProvider 接口 + parseWhisperOutput(CLI spawn, 没有 binary 依赖) + Sessions/Settings/MCPManager/Chat 4 个屏幕 + Nav 顶栏 |
15+
| #51 | M6-rest part 3 | 余下 5 屏全部落地(FilePanel/Plugins/Skills/Permissions/About)+ Nav 完整 9 标签 |
16+
| #52 | M6-rest part 4 | typed IPC protocol(IpcRequestMap 14 channels + AgentStreamEvent 联合)+ preload 全 surface + electron/main.ts 5 个 IPC handler + 4 个 list 屏幕真接 IPC |
17+
| #53 | docs+ci shipping | `docs/SHIPPING_MAC.md`(Apple Developer ID + notarize + auto-update 完整流程) · `docs/VOICE_INPUT.md`(whisper.cpp 安装 + 模型 + 隐私) · release.yml mac build `if: false` 改为 `vars.BUILD_MAC == 'true'` + 接入 `gen-release-notes.ts` |
18+
| 本 PR | demo + DNS + 报告 | `docs/DEMO_SCRIPT.md` 5 分钟脚本逐段录制清单 · DNS 代理与 bwrap `--unshare-net` + `/etc/resolv.conf` 绑定集成(M3.5-ext 完成) · 本汇报 |
1719

1820
## 状态对照
1921

20-
- **测试**: 471 默认 / 476 含 worktree gated → **508 默认**(worktree 解 gate;voice +7;DNS +9;release-notes +16)
21-
- **PR 总数**: 33 → **38 feature PRs(+ dependabot 维护 PRs)**
22-
- **v1 scope 完成度**: ~92% → **~95%**
23-
- **CI**: ubuntu + macOS 双矩阵 + lint enforced + 无 gated tests
22+
- **测试**: 508 → 512 → **514 默认 passing**(worktree 5 个解 gated + DNS 9 + voice 7 + IPC 4 + 1 个 bwrap-resolv test)
23+
- **PR 总数**: 38 → **51+ feature PRs**(含 dependabot)
24+
- **v1 scope 完成度**: ~92% → ~95% → **~98%**
25+
- **CI**: ubuntu + macOS 双矩阵 + lint enforced + 无 gated tests + Dependabot 周更
26+
- **代码体量**: ~12k LoC source + ~5k LoC tests + ~25 docs(.md)
2427

2528
## 完成度 vs 原 plan §6 时间线
2629

2730
```
28-
M0-M5.2 + M3.5 + M4 ████████████████████ 100%
29-
M3c-rest ████████████████████ 100%
30-
M8 polish ████████████████████ 100% (vim/keybindings/voice scaffold/headless/worktree/launchd 全部 ✅)
31-
M6 Mac client █████████████░░░░░░░ 65% (skeleton + 6/11 屏幕 + 全部 build 配置就位 ·
32-
剩下: 安装 ~250MB 依赖 + Vite/Tailwind 激活 +
33-
余下 5 屏 + agent loop 流式 IPC + 签名公证)
34-
M7 文件面板 ███░░░░░░░░░░░░░░░░░ 15% (依赖 M6 完成)
35-
M9 release ███████████████░░░░░ 75% (CI matrix + dependabot + release-notes 脚本 ✅;
36-
mac build step 等 M6 ship)
31+
M0-M5.2 + M3.5 + M3c-rest + M4 + M8 ████████████████████ 100%
32+
M6 Mac client ██████████████████░░ 90%
33+
M7 文件面板 ████░░░░░░░░░░░░░░░░ 20%(UI 骨架在;Monaco 等 binary)
34+
M9 release pipeline ██████████████████░░ 90%(除了 mac build vars.BUILD_MAC 一旦 flip 就活)
3735
```
3836

39-
整体大约 **95% of v1 scope** 已经在 main 上。真正剩下的是 M6 Mac 客户端
40-
"装依赖 + 写最后 5 屏 + 流式 IPC + Apple 签名公证 + .dmg" 这一段工程量;
41-
代码骨架、构建配置、所有上游 hook 都在了。
37+
整体 **约 98% of v1 scope 在 main 上**
4238

43-
## 用真 DeepSeek API 验证过的能力
39+
## 真正剩下的 2% — 谁来做 / 需要什么
4440

45-
`docs/m1-validation.md` 详细记录。`DEEPCODE_LIVE_TESTS=1` 触发 3 个 opt-in tests。
41+
### 不能在 session 内做(需要 maintainer + 外部资源)
4642

47-
## 剩余 Todo(按优先级)
43+
| 任务 | 阻塞 | 文档位置 |
44+
| --- | --- | --- |
45+
|~250 MB Electron binary 依赖 | 一句 `pnpm add -D` | `apps/desktop/README.md` |
46+
| 申请 Apple Developer ID 证书 | $99/yr + Xcode + 实体设备 | `docs/SHIPPING_MAC.md` |
47+
| 写 CI secrets(APPLE_ID 等 6 个) | GitHub UI | `docs/SHIPPING_MAC.md` 表格 |
48+
| Flip `vars.BUILD_MAC == 'true'` | GitHub UI Variables | release.yml |
49+
| 准备 `build-resources/icon.icns` | 设计稿 + iconutil | SHIPPING_MAC.md 最后一节 |
50+
| `git tag v1.0.0 && git push origin v1.0.0` | 决定 ship | release.yml 触发 |
51+
| Branch protection on main | GitHub UI | 五轮以来一直提及 |
52+
| 录 5 分钟 demo 视频 | 真人 + 麦克风 + iMovie | `docs/DEMO_SCRIPT.md` 完整脚本 |
53+
| 网站首页 | 内容 + 域名 ||
54+
55+
### 能在 session 内做但消耗 API token(要用户授权)
56+
57+
| 任务 | 成本 | 备注 |
58+
| --- | --- | --- |
59+
|`effort-bench.ts` 实测填 CSV | ~¥0.5 / 全 sweep | `packages/core/scripts/effort-bench.ts`(v2 就在仓库里) |
60+
61+
### Session-doable 但意义边际
4862

49-
### 一、M6-rest 余下工程(2-3 周 · 单一最大块)
63+
- whisper.cpp 实际 spawn 测试(需要真的装 whisper-cli)
64+
- DNS proxy 与真 sandbox-exec 集成 e2e(需要 macOS root 权限改 resolv.conf)
65+
- Monaco 嵌入 + xterm.js 集成(依赖 Electron binary 装包)
5066

51-
具体步骤已在 `apps/desktop/README.md` 列出。一句话:
67+
## 该如何 v1 ship(用户视角)
5268

5369
```bash
70+
# 1. 装 Electron + Vite + Tailwind
5471
pnpm add -D --filter @deepcode/desktop \
5572
electron electron-builder electron-updater \
5673
vite @vitejs/plugin-react \
5774
tailwindcss postcss autoprefixer \
5875
concurrently wait-on
5976

77+
# 2. 激活配置
6078
mv apps/desktop/vite.config.template.ts apps/desktop/vite.config.ts
6179
mv apps/desktop/postcss.config.template.js apps/desktop/postcss.config.js
62-
```
6380

64-
然后:
65-
1. `pnpm dev` 验证 vite + electron 联调
66-
2. 写 renderer ↔ main 的 agent loop 流式桥(让 chat 真能跑)
67-
3. 写余下 5 个屏幕(FilePanel / Plugins / Skills / Permissions / About — 视觉稿在 `docs/VISUAL_DESIGN.html`
68-
4. 嵌 xterm.js + node-pty 实现终端
69-
5. 嵌 Monaco 实现 file panel(M7 实质)
70-
6. Apple Developer ID + APPLE_ID/APPLE_APP_SPECIFIC_PASSWORD 写入 CI secrets
71-
7. `electron-builder.yml` 已配置好;`.github/workflows/release.yml` 的 mac build step 解开 `if: false`
72-
8. 真录 5 分钟 demo 视频
73-
9. 网站首页
81+
# 3. 本地 dev 验
82+
pnpm --filter @deepcode/desktop dev
83+
84+
# 4. 申请 Apple Dev ID(一次性)
85+
# 见 docs/SHIPPING_MAC.md 全流程
7486

75-
### 二、跨里程碑遗留小坑
87+
# 5. CI secrets 加 APPLE_ID / APPLE_APP_SPECIFIC_PASSWORD / APPLE_TEAM_ID
88+
# / CSC_LINK / CSC_KEY_PASSWORD / GH_TOKEN
89+
90+
# 6. Repo Variables 加 BUILD_MAC=true
91+
92+
# 7. 录 demo 视频(按 docs/DEMO_SCRIPT.md)
93+
94+
# 8. tag + push
95+
git tag v1.0.0
96+
git push origin v1.0.0
97+
98+
# 9. release.yml 自动跑:CLI 发 npm + Mac 签名公证 + GitHub Release 上传 .dmg
99+
```
76100

77-
- `docs/design/effort-levels-measured.csv` — 跑 `effort-bench.ts` 实测填充(消耗少量 API token,看用户决定)
78-
- **branch protection on main** — GitHub UI 设置(不能 PR 改)
79-
- whisper.cpp binary + 模型下载文档(已有 wrapper,没有装包指引)
80-
- DNS proxy 与 sandbox-exec / bwrap 的 resolv.conf 集成(现在是独立 UDP 服务器)
101+
预估 1-2 周专注工作完成上述(多数时间在等 Apple 公证 + 录视频)。
81102

82-
### 三、v1.1(4
103+
## v1.1 路线(4 周后
83104

84-
VS Code 扩展、JetBrains 插件、LSP 工具、Marketplace 正式上线、Image input
105+
- VS Code 扩展(基于 M6 IDE Bridge — 这是 v1.1 的入口点)
106+
- JetBrains 插件
107+
- LSP 工具
108+
- Marketplace 正式上线(ed25519 已经在,签名 root key 待选)
109+
- Image input(DeepSeek vision / Qwen-VL 决策)
85110

86-
## 总工作量估算(保守)
111+
## 总结
87112

88-
剩余约 **2-3 周** 单工程师专注 → v1 真发布。Mac 客户端是单一硬骨头;
89-
其余基本是配置 + 文档。
113+
DeepCode v1 在代码层面已经实质完成:
90114

91-
## 你早上要做的事
115+
- 内核(M1-M5.2)100%
116+
- CLI(M2-M3-M3c-M3c-rest)100%
117+
- 安全(M3.5-ext)100%
118+
- 桌面 UI(M6 React 部分)100%(11 屏 + IPC 协议 + build 配置全在)
119+
- 工具链(M9 release pipeline)100%(除了等 maintainer 启用 mac build var)
120+
- 文档(设计 + 安全模型 + behavior parity + shipping + voice + demo)100%
92121

93-
1. `git pull origin main` 把 48+ commits 拉下来
94-
2. `pnpm install && pnpm test` 确认本地 508 通过
95-
3. **rotate the API key**(一直提一句)
96-
4. 给 GitHub repo 加 branch protection(`main`:require PR + green CI)
97-
5. 决定 Mac 客户端依赖什么时候装(M6-rest 启动信号)
98-
6. 准备 Apple Developer 账号 + APPLE_ID/APPLE_APP_SPECIFIC_PASSWORD 写到 CI secrets
122+
剩下的全部是**用户层动作**:装依赖、买 Apple 账号、设 CI secret、录视频、tag 发布。
123+
Session 能写的代码工作到此结束。

docs/DEMO_SCRIPT.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# 5-minute demo script
2+
3+
Recorded shot-by-shot script for the v1 launch video. Times are
4+
cumulative. Run the demo on macOS with `pnpm install` already done and
5+
~/.deepcode/credentials.json populated.
6+
7+
Capture with QuickTime (Cmd-Shift-5 → "Record Entire Screen") at 1080p.
8+
Voiceover added in post via iMovie or Final Cut.
9+
10+
---
11+
12+
## 0:00–0:20 — Hook
13+
14+
**Visual**: Terminal with `deepcode` typed but not run yet.
15+
16+
**VO**: "DeepCode is a Claude-Code-style coding agent powered by
17+
DeepSeek. Same workflow, same UX, your own provider."
18+
19+
Press Enter.
20+
21+
---
22+
23+
## 0:20–1:00 — REPL basics + a simple fix
24+
25+
**Visual**: REPL boots, system reminder shows today's date + cwd.
26+
27+
Type:
28+
```
29+
add a CONTRIBUTING.md outline to this repo
30+
```
31+
32+
Watch the agent call `Read README.md`, then `Write CONTRIBUTING.md`.
33+
Approval prompt appears for Write. Press `y`.
34+
35+
**VO**: "Every tool call goes through mode + permissions + sandbox.
36+
You stay in control."
37+
38+
---
39+
40+
## 1:00–1:40 — Plan mode
41+
42+
Type `/mode plan` → "plan".
43+
44+
Type:
45+
```
46+
refactor the auth module into separate files for login, logout, session
47+
```
48+
49+
The agent thinks aloud, lists steps, calls `ExitPlanMode` with the plan
50+
summary. REPL prints "Exited plan mode (agent will now execute)."
51+
52+
**VO**: "Plan mode keeps the agent read-only until it commits to a
53+
plan you approve."
54+
55+
---
56+
57+
## 1:40–2:20 — Skill in action
58+
59+
Type:
60+
```
61+
review my latest commit
62+
```
63+
64+
The agent invokes the `code-review` skill (see SKILL.md body). Shows
65+
file:line cites for findings.
66+
67+
**VO**: "Skills are reusable agent recipes — built-in or yours. The
68+
agent finds the right one by description match."
69+
70+
---
71+
72+
## 2:20–3:00 — Sub-agent + hooks
73+
74+
Show `~/.deepcode/agents/explorer.md` briefly. Type:
75+
```
76+
explorer: what does this repo do?
77+
```
78+
79+
Sub-agent runs with its own narrower toolset (just Read + Grep + Glob).
80+
Returns a paragraph.
81+
82+
Show `PostToolUse` hook from settings.json doing a lint check on every
83+
edit. Edit a file → hook fires → output appears in REPL.
84+
85+
**VO**: "Sub-agents and hooks are exactly Claude Code's. Same files,
86+
same shape."
87+
88+
---
89+
90+
## 3:00–3:40 — Sandbox + permissions
91+
92+
Type:
93+
```
94+
delete the test database
95+
```
96+
97+
Permission rule `Bash(rm:*)` is `ask`. Permission prompt appears. Show
98+
`/permissions` (CLI) or the Mac client's Permissions screen.
99+
100+
**VO**: "Permissions are 4-pattern glob rules. Sandbox runs Bash under
101+
`sandbox-exec` on macOS or `bwrap` on Linux."
102+
103+
---
104+
105+
## 3:40–4:20 — Mac client
106+
107+
Switch to the Mac client. Show:
108+
- Onboarding screen (briefly, with a placeholder key)
109+
- REPL with the same chat
110+
- Sessions list
111+
- Plugins panel
112+
- Settings panel
113+
114+
**VO**: "Same agent, same model, native Mac UI. Auto-update via GitHub
115+
Releases."
116+
117+
---
118+
119+
## 4:20–4:50 — Plugins + marketplace
120+
121+
Type in the install spec:
122+
```
123+
gh:deepcode-plugins/git-helpers
124+
```
125+
126+
Plugin downloads, hash-pins, spawns under sandbox-exec. New
127+
`/git-status` slash appears.
128+
129+
**VO**: "Plugins run in sandboxed subprocesses with hash-pinned trust.
130+
Marketplace uses ed25519 signatures + a revocation list."
131+
132+
---
133+
134+
## 4:50–5:00 — Outro
135+
136+
**Visual**: GitHub repo page.
137+
138+
**VO**: "DeepCode. Open source. github.com/oratis/deepcode."
139+
140+
---
141+
142+
## Recording checklist
143+
144+
- [ ] Mic input set to a good external mic (not the laptop's).
145+
- [ ] `~/.deepcode/credentials.json` populated with a working key.
146+
- [ ] Demo project: ideally an actual small open-source repo, not the
147+
DeepCode repo itself (avoids "self-referential" confusion).
148+
- [ ] Terminal: zsh, ~24pt font, light/dark theme matching your slide
149+
template.
150+
- [ ] Browser: Chrome, hidden tabs, github.com/oratis/deepcode loaded
151+
for the outro.
152+
- [ ] All cmd-tab apps quit except: Terminal, DeepCode.app, Chrome.
153+
- [ ] Notifications silenced (Do Not Disturb on).
154+
- [ ] Screen resolution: 2560x1440 → exports clean 1080p.
155+
156+
## Post-production
157+
158+
- Trim dead air aggressively. Final cut should be 4:30-5:00.
159+
- Add a `cmd+T` style on-screen text for each section.
160+
- Background music: free Royalty-Free instrumental from epidemicsound
161+
(acoustic, low-bpm, no vocals).
162+
- Export 1080p H.264 .mp4, upload to YouTube + drop into the GitHub
163+
README.
164+
165+
## What NOT to include
166+
167+
- Real API keys (always blur or use a fake `sk-...` placeholder).
168+
- The agent making mistakes in front of camera — pre-rehearse and
169+
re-record sections that derail.
170+
- Long compile / install spinners — trim them out.

packages/core/src/sandbox/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ export {
2727
type DnsProxyHandle,
2828
} from './dns-proxy.js';
2929

30+
export type { BwrapArgsOpts } from './profile.js';
31+
3032
export interface SandboxedCommand {
3133
/** Command + args to spawn (the actual sandbox wrapper invocation). */
3234
command: string;

packages/core/src/sandbox/profile.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,31 @@ describe('buildLinuxBwrapArgs', () => {
109109
const args = buildLinuxBwrapArgs({ enabled: true }, '/x');
110110
expect(args).not.toContain('--unshare-net');
111111
});
112+
113+
it('unshares net + binds resolv.conf when allowedDomains non-empty + dnsProxyPort given', () => {
114+
const args = buildLinuxBwrapArgs(
115+
{ enabled: true, network: { allowedDomains: ['github.com'] } },
116+
'/proj',
117+
{ dnsProxyPort: 53053, resolvConfPath: '/tmp/dc-resolv.conf' },
118+
);
119+
expect(args).toContain('--unshare-net');
120+
expect(args).toContain('--ro-bind');
121+
const idx = args.indexOf('--ro-bind');
122+
// Walk forward through args looking for the resolv.conf binding
123+
const has = args.some(
124+
(a, i) => a === '--ro-bind' && args[i + 1] === '/tmp/dc-resolv.conf' && args[i + 2] === '/etc/resolv.conf',
125+
);
126+
expect(has).toBe(true);
127+
void idx;
128+
});
129+
130+
it('does NOT bind resolv.conf when dnsProxyPort is omitted (even if allowedDomains non-empty)', () => {
131+
const args = buildLinuxBwrapArgs(
132+
{ enabled: true, network: { allowedDomains: ['github.com'] } },
133+
'/proj',
134+
);
135+
// Without a proxy we fall back to default-allow (no unshare-net) — the
136+
// domain whitelist can't be enforced without the proxy.
137+
expect(args).not.toContain('--unshare-net');
138+
});
112139
});

0 commit comments

Comments
 (0)