{"owner":"rullerzhou-afk","repo":"clawd-on-desk","hasSkills":true,"totalSkillsCount":5,"totalTokensCount":48950,"categories":["root-instruction","claude-rule","mcp-config","marketplace","plugin-manifest"],"hasMcp":true,"mcpConfig":{"mcpServers":{"clawd-on-desk":{"command":"npx","args":["-y","@modelcontextprotocol/server-clawd-on-desk"]}}},"found":["AGENTS.md","CLAUDE.md",".cursor/mcp.json",".claude-plugin/marketplace.json",".claude-plugin/plugin.json"],"skills":{"AGENTS.md":"# AGENTS.md\n\nThis file is the entry point for coding agents working in this repository. Keep it short and operational. Durable architecture lives in `docs/project/`; `docs/plans/` and `docs/investigations/` are historical evidence unless this file explicitly links them.\n\n## Project Overview\n\nClawd 是一个 Electron 桌宠：通过 hook、日志轮询、plugin 和 extension 感知 AI coding agent 的工作状态，并播放像素风动画。当前支持 Claude Code、Codex CLI、Copilot CLI、Gemini CLI、Antigravity CLI (agy)、Cursor Agent、CodeBuddy、WorkBuddy、Grok Build、Kiro CLI、KiroCrew、Kimi Code CLI (Kimi-CLI)、Qwen Code、ZCode、CodeWhale、opencode、MiMo Code、Pi、OMP (oh-my-pi)、OpenClaw、Hermes Agent、Qoder、QoderWork、QwenWork (千问办公)、Reasonix、DeepSeek Harness、TraeCode (Trae CN)、MiniMax Code；内置 Clawd / Calico / Cloudling 三套主题，支持用户主题，并可经 Settings 从独立 `rullerzhou-afk/clawd-themes` 仓库下载可选官方主题（Hash Sage、Whale-chan，external theme 权限、可卸载）；平台覆盖 Windows、macOS、Linux，UI 支持 en / zh / zh-TW / ko / ja / pt-BR / es。\n\n## Common Commands\n\n```bash\nnpm start\nnpm run build                  # default Windows package\nnpm run build:win:x64\nnpm run build:win:arm64\nnpm run build:win:all\nnpm run build:mac\nnpm run build:linux\nnpm run build:all\nnpm install\nnpm test\nnpm run verify:electron\nnpm run verify:release\nnpm run audit:assets\nnpm run audit:pr-history-assets\nnpm run audit:native-package -- --app-root <extracted-app-root> --target <target-id>\nnpm run create-theme\n\nnpm run install:claude-hooks\nnpm run uninstall:claude-hooks\nnpm run install:cursor-hooks\nnpm run install:gemini-hooks\nnpm run install:antigravity-hooks\nnpm run install:kiro-hooks\nnpm run install:kirocrew-hooks\nnpm run uninstall:kirocrew-hooks\nnpm run install:kimi-hooks\nnpm run install:qwen-hooks\nnpm run install:zcode-hooks\nnpm run uninstall:zcode-hooks\nnpm run install:codewhale-hooks\nnpm run uninstall:codewhale-hooks\nnpm run install:pi-extension\nnpm run uninstall:pi-extension\nnpm run install:omp-extension\nnpm run uninstall:omp-extension\nnpm run install:openclaw-plugin\nnpm run uninstall:openclaw-plugin\nnpm run install:hermes-plugin\nnpm run uninstall:hermes-plugin\nnpm run install:qoder-hooks\nnpm run uninstall:qoder-hooks\nnpm run install:qoderwork-hooks\nnpm run uninstall:qoderwork-hooks\nnpm run install:qwenwork-hooks\nnpm run uninstall:qwenwork-hooks\nnpm run install:reasonix-hooks\nnpm run uninstall:reasonix-hooks\nnpm run install:workbuddy-hooks\nnpm run uninstall:workbuddy-hooks\nnpm run install:grok-hooks\nnpm run uninstall:grok-hooks\nnpm run install:dsh\nnpm run uninstall:dsh\nnpm run install:codex-hooks\nnpm run uninstall:codex-hooks\nnpm run install:codex-debug-hooks\nnpm run uninstall:codex-debug-hooks\nnpm run install:mimocode-plugin\nnpm run uninstall:mimocode-plugin\nnode hooks/codebuddy-install.js\nnode hooks/opencode-install.js\n\nbash test-demo.sh [seconds]\nbash test-mini.sh [seconds]\nbash test-macos.sh\nbash test-oneshot-gate.sh [state] [seconds]\n```\n\n新安装默认只把 Claude Code 和 Codex 标记为已安装并启用；其他 agent 默认未安装、未启用。正常启动时，Clawd 只会为 `integrationInstalled=true` 且 `enabled=true` 的 agent 自动同步 Claude / Codex / Copilot / Gemini / Antigravity / Cursor / CodeBuddy / WorkBuddy / Grok Build / Kiro / KiroCrew / Kimi / Qwen / ZCode / CodeWhale / Qoder / QoderWork / QwenWork / Reasonix / TraeCode / MiniMax Code hooks、opencode / MiMo Code / OpenClaw / Hermes plugins 和 Pi / OMP extensions。Settings Agent 页的 Install 会安装并启用该集成；Uninstall 会卸载 Clawd 管理的 hook/plugin/extension，并同时把该 agent 设为未安装、未启用。单独关闭 enabled 只会跳过启动同步并屏蔽事件/权限入口，不卸载用户已有 hooks / plugins / extensions；重新启用未安装 agent 只打开事件入口，不会写本机集成文件。手动安装命令主要用于调试、重装或远程部署。\nSettings 注册的自定义 HTTP Agent 是独立模型：`customApplications` 是注册真相，对应 `agents[customId]` 必须显式保持 `integrationInstalled=false`。注册只分配 ID 和状态入口，不安装 hook、不观察进程；v1 仅允许已注册且启用的 ID 向 `/state` 上报，`/permission` 永远不提供决定。删除或伪造的 `custom-` ID 必须直接拒绝，不能降级成 Claude Code subagent。\nCopilot CLI 同步走 `<COPILOT_HOME 或 ~/.copilot>/hooks/hooks.json`，marker-based 增量合并只接管含 `copilot-hook.js` 标记的条目，用户其他 entry / 其他 `hooks/*.json` 文件原样保留；hooks.json 或 `settings.json` 顶层 `disableAllHooks: true` 时 doctor 报 warning（不挂 Fix 按钮）。详见 `docs/guides/copilot-setup.md`。\n\n## Read These Docs\n\n- `docs/project/agent-runtime-architecture.md`：运行时架构、模块边界、启动与数据流、多 agent、permission bubble、终端聚焦和自动同步\n- `docs/project/theme-state-ui.md`：状态机、主题系统、settings、mini mode、素材规则、平台限制、待落地 UI 决策\n- `docs/project/release-process.md`：发版 checklist、release note 核对、tag 触发 GitHub 打包和资产确认\n- `docs/guides/copilot-setup.md`：Copilot CLI 自动同步说明、`COPILOT_HOME` 兼容性、手动配置备选模板\n- `docs/guides/dsh-setup.md`：DeepSeek Harness web profile 与桌面版的实验性 plugin 集成状态与普通审批集成\n- `docs/guides/state-mapping.md`：状态 → 动画权威表\n- `docs/guides/guide-theme-creation.md`：主题作者指南\n- `docs/guides/setup-guide.md`：安装、远程 SSH、各 agent 接入\n- `docs/guides/custom-agent-http.md`：自定义 HTTP Agent 的 state-only 接入合约和动态端口发现\n- `docs/guides/known-limitations.md`：用户向已知限制\n- `docs/guides/recap.md`：本地小结的指标口径、coverage、时区/DST、隐私存储与产品红线\n- `docs/guides/codex-wsl-clarification.md`：Codex / WSL 路径与 Node 说明\n- `docs/guides/guide-remote-ssh.md`：Remote SSH 用户流程、Codespaces 单会话 transport 与共享主机边界\n- `docs/guides/telegram-approval.md` / `docs/guides/feishu-lark-remote-approval.md`：远程审批设置与失败回退语义\n- `docs/guides/roam-fence.md`：自由漫游与可选围栏\n\n## Runtime Summary\n\n- HTTP hook / plugin 主路径：`src/server.js` → `src/server-route-state.js` → `src/agent-runtime-main.js` → `src/state.js` → IPC；本地 JSONL monitor 直接进入 `agent-runtime-main`，不经过 HTTP server\n- 权限主路径：`src/server-route-permission.js` → `src/permission.js`；本地 bubble、显式 permission automation 与可选 Telegram / 飞书 Lark 远程审批都可能产生真实决定\n- 桌宠的渲染/输入双窗口由 `src/pet-window-runtime.js` 统一创建和定位；浮层排序与 topmost 行为在 `src/floating-window-runtime.js` / `src/topmost-runtime.js`\n- `src/state.js` 生成的 session snapshot 是 Dashboard、HUD/Orbit 与可选通知/presence/mobile consumer 的共享合约，改字段必须检查所有消费者\n- `src/integration-sync.js` 为已安装且启用的 agent 异步同步 hooks / plugins / extensions；Codex official hooks 为 primary，JSONL 轮询保留为 fallback\n- Claude hook 恢复由 `src/claude-settings-watcher.js` 的目录 watcher + 低频只读巡检共同负责；repair 统一经过 `src/claude-hook-operations.js` 队列并复验，连续失败转 `manual-fix-required`。完整 gate、阈值与 source-missing 语义见 `docs/project/agent-runtime-architecture.md`\n- `src/agent-gate.js` 控制各 agent 的安装意图、启用状态、权限气泡开关和 wait-for-input notification 子开关\n- 设置系统主链路是 `src/prefs.js` → `src/settings-controller.js`（唯一写入者）→ `src/settings-store.js`；`settings-actions*` 负责校验和 pre-commit gates，`settings-effect-router.js` 负责 post-commit runtime effects 与广播\n- 启动时还会尝试自动安装 VS Code / Cursor terminal-focus extension，并初始化 updater\n- Remote SSH 通过 effective transport inspection 区分 ordinary parallel SSH 与 serialized transport；后者由 target-scoped coordinator 编排。远程部署只走 Settings，`scripts/remote-deploy.sh` 已 fail-fast 停用\n\n## Core Files\n\n更细的背景见 `docs/project/agent-runtime-architecture.md` 和 `docs/project/theme-state-ui.md`。\n\n| File | Responsibility |\n|------|------|\n| `src/main.js` | Electron composition root：生命周期、上下文组装与各 runtime / IPC 注册器接线 |\n| `src/server.js` + `src/server-route-state.js` + `src/server-route-permission.js` | HTTP 服务、端口发现、`/state` / `/permission` 路由 |\n| `src/agent-runtime-main.js` + `src/integration-sync.js` | local monitor / official hook 仲裁、Codex turn fence、按 gate 的集成同步 |\n| `src/state.js` | 状态机、多会话合并、优先级、自动回退、睡眠/DND |\n| `src/renderer.js` | 动画切换、SVG 预加载、眼球追踪渲染 |\n| `src/permission.js` + `src/permission-automation-policy.js` + `src/session-automation-coordinator.js` | 权限气泡、自动化策略、per-session 授权与决策回包；远程 client 由 `main.js` 注入 |\n| `src/pet-window-runtime.js` + `src/floating-window-runtime.js` + `src/topmost-runtime.js` | 双窗口 owner、浮层重排、z-order / fullscreen / focusability |\n| `src/update-bubble.js` | 更新气泡创建、测高、跟随桌宠定位，避让 HUD / permission stack |\n| `src/dashboard.js` + `src/dashboard-renderer.js` | Sessions Dashboard 唯一 owner：会话列表、别名编辑、终端跳转、几何持久化，以及同一页面的临时键盘模式 |\n| `src/dashboard-host.js` | Dashboard 普通宿主的平台封装：darwin/win32 用 `BaseWindow + WebContentsView`（无 `ready-to-show`），Linux 保留 `BrowserWindow` |\n| `src/dashboard-quick-mode.js` | 完整 Dashboard 的 1–9 键盘模式（**macOS/Windows only**）：quick 宿主、opacity/input parking、轮次栅栏与冻结数字映射；Windows 显式取消与页面失效的来源恢复在 `src/quick-select-origin-focus.js`，quick 宿主的退出清理挂在 `before-quit` |\n| `src/session-hud.js` + `src/session-hud-renderer.js` | 桌宠旁轻量会话 HUD、折叠行、点击跳转 |\n| `src/session-alias.js` | session alias key 规范化、TTL pruning、Kiro cwd scope |\n| `src/theme-loader.js` + `src/theme-runtime.js` | stateless 主题加载/消毒与唯一 active-theme owner；`waitForThemeReloadSettled` 完成信号 |\n| `src/official-theme-catalog.js` / `-download.js` / `-installer.js` / `-main.js` | 官方可下载主题：严格 catalog/cache、Electron `net.request` 流式下载、受限流式 ZIP 解压与 marker-before-rename、main owner/IPC/共享 `theme` lock |\n| `src/prefs.js` | 偏好 schema、load/save/migrate/validate，设置持久化入口 |\n| `src/settings-actions*.js` + `src/settings-effect-router.js` | 设置 validators / commands / pre-commit gates 与 post-commit runtime effects |\n| `src/settings-controller.js` | 设置系统唯一写入者 |\n| `src/settings-store.js` | 不可变 snapshot store |\n| `src/settings-ui-core.js` + `src/settings-renderer.js` + `src/settings-tab-*.js` | Settings shared UI state、侧栏/tab shell 与各页逻辑 |\n| `src/menu.js` | 托盘 / 右键菜单，串起设置、Dashboard、mini mode、更新入口 |\n| `src/mini.js` | 极简模式入场、滑动、peek、状态映射 |\n| `src/tick.js` | 主循环、鼠标轮询、眼球和 idle/sleep 逻辑 |\n| `src/drag-position.js` | 拖拽落点规范化与跨显示器钳制 |\n| `src/visible-margins.js` | 可视角色边距与 edge pinning 规则 |\n| `src/updater.js` | Git 模式 / `electron-updater` 双路径更新逻辑 |\n| `src/focus.js` | 终端聚焦 |\n| `src/hit-renderer.js` + `src/hit-geometry.js` | 输入窗口命中、拖拽、连击反应 |\n| `src/remote-ssh-runtime.js` | Remote SSH tunnel/ingress 状态机、ordinary health probe、serialized readiness 与重连 |\n| `src/remote-ssh-transport.js` + `src/remote-ssh-transport-coordinator.js` | effective transport inspection、pre-spawn admission、target ownership、drain barrier 与 quarantine |\n| `src/remote-ssh-deploy.js` | Deploy / Repair、身份事务、lease/fencing、wrapper、cleanup 与远端 Codex monitor mutation |\n| `src/remote-ssh-identity.js` + `src/remote-ssh-layout.js` + `src/remote-ssh-ingress.js` | 身份/布局真相与 profile 专属、nonce 校验的本地 ingress |\n| `src/remote-ssh-node.js` + `src/remote-ssh-shell-detect.js` + `src/remote-ssh-local-config.js` | 远端 Node/ shell 探测与本机 SSH config 入口 |\n| `src/remote-ssh-profile.js` | Remote SSH profile schema、校验、默认值和持久化规范化 |\n| `src/remote-ssh-ipc.js` | Remote SSH runtime / deploy / monitor orchestration、intent policy、IPC 状态与进度广播 |\n| `src/remote-ssh-quote.js` | Remote SSH 终端命令与跨平台 shell quoting helper |\n| `agents/registry.js` | agent 注册表 |\n| `agents/codex-log-monitor.js` | Codex JSONL fallback 轮询 |\n| `agents/gemini-log-monitor.js` | legacy Gemini session JSON 轮询器；当前 Gemini hook-only 路径不启动 |\n| `hooks/dsh-install.js` | DeepSeek Harness immutable managed bridge generation、ownership verify、web 与 desktop 两个 profile 的安装 / 修复 / 卸载编排 |\n| `hooks/kirocrew-install.js` + `hooks/kirocrew-store.js` | KiroCrew state-only gateway hooks、upstream-compatible mutation locks and atomic private store writes |\n| `hooks/kirocrew-hook.js` + `hooks/kirocrew-command.js` | KiroCrew state bridge and exact command-shape ownership classifier |\n| `hooks/dsh-notices.js` | DeepSeek Harness 常驻提示的存储与规则（按 profile 的 `notices-<profile>.json`） |\n| `hooks/clawd-hook.js` + `hooks/copilot-hook.js` | Claude Code / Copilot CLI 状态上报脚本 |\n| `hooks/install.js` | Claude hook 注册 / 卸载 |\n| `hooks/auto-start.js` | Claude `SessionStart` 自动拉起 Clawd 的 hook |\n| `hooks/codex-hook.js` / `hooks/codex-install.js` | Codex official hooks 状态与权限审批、安装 / 卸载 |\n| `hooks/cursor-install.js` / `gemini-install.js` / `antigravity-install.js` / `kiro-install.js` / `kimi-install.js` / `qwen-code-install.js` / `codewhale-install.js` / `codebuddy-install.js` / `workbuddy-install.js` / `opencode-install.js` / `pi-install.js` / `openclaw-install.js` / `hermes-install.js` / `qoder-install.js` / `qoderwork-install.js` / `reasonix-install.js` | 各 agent 集成安装逻辑 |\n| `hooks/opencode-family-managed-generation.js` | OpenCode 用户可写托管 generation（canonicalizer、bundle/manifest、stage/promote、target owner record、target-scoped lock）；纯 Node 内置依赖，不进入 Remote SSH `HOOK_FILES` |\n| `hooks/opencode-family-entry-ownership.js` | OpenCode-family plugin entry 的 string/tuple 解析、跨平台路径等价、所有权分类与重复/options 冲突规划（纯逻辑、可注入 fs） |\n| `hooks/opencode-family-install.js` / `hooks/opencode-family-jsonc.js` | 家族注册器：`managedMaterialization:true` 走托管 generation 事务 + 共享 entry planner；`false` 保持 legacy broad-basename register/unregister |\n| `src/doctor-detectors/opencode-managed-inspector.js` | managed OpenCode Doctor inspector（ownership/manifest/生成结构、Fix policy、masked supplementary warning）；接受注入 fs |\n| `hooks/workbuddy-hook.js` | WorkBuddy state + Notification command hook；无 session_id 时返回合法 stdout 后丢弃事件 |\n| `hooks/grok-hook.js` / `hooks/grok-install.js` | Grok Build state + Notification command hook；写入 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json`；`env` marker `CLAWD_GROK_HOOK=v1` 所有权；无 session id 时丢弃；不注册 `/permission` |\n| `hooks/zcode-hook.js` / `hooks/zcode-install.js` | ZCode 状态 + 阻塞式 PermissionRequest hooks（`hookSpecificOutput` 决定 / `{}` 无决定）、`hooks.events.*` 按事件超时增量注册与 Claude-imported Clawd hook 清理 |\n| `hooks/qoder-hook.js` | Qoder state-only 状态上报脚本（Phase 1，stdout 恒为 `{}`） |\n| `hooks/minimax-hook.js` / `hooks/minimax-install.js` | MiniMax Code state-only 本地插件：整目录 install/uninstall（`<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/`），CLAUDE 格式 hooks + exec-form args，10 事件无 PermissionRequest/Notification，`.clawd-managed.json` 结构化所有权凭据、fail closed |\n| `hooks/codex-remote-monitor.js` | 远程 Codex JSONL 轮询并通过 SSH 隧道回传（含 token_count 订阅配额的 metadata_only 上报） |\n| `hooks/claude-statusline.js` / `hooks/antigravity-statusline.js` | 各 CLI statusline 适配器：渲染状态行 + 把订阅配额（rate_limits）以 metadata_only POST 上报；Claude 版支持远程部署（`CLAWD_REMOTE=1` 前缀）与 `--chain` 串联模式（原 statusLine 对象保存在 `~/.claude/hooks/clawd-statusline-chain.json`，卸载时恢复） |\n| `extensions/vscode/extension.js` | VS Code / Cursor 终端 tab 聚焦辅助扩展 |\n\n## Constraints\n\n- `agents/registry.js` 的 capabilities 是权限、subagent、session-end 等路由/gate 的权威来源；不得另写名单代替 capability 判定。但 permission automation eligibility 由更窄的 `isKnownPermissionAgent()` 显式判定（`KNOWN_PERMISSION_AGENTS` + explicit opencode-family membership），不得从 `permissionApproval` 自动派生或合并回 registry capabilities\n- 小结的指标能力例外地只认 `src/recap-metrics.js` 的显式逐 Agent 口径，不得从 registry capabilities 或标准化 event 名推导。只统计已通过 gate、Codex source/replay fence、subagent 与完成仲裁的 accepted activity；DND 继续记录且不切 coverage，suspend/退出/关闭记录才切。`null` 是不支持，绝不能渲染或汇总成 `0`\n- 小结持久层固定为 `~/.clawd/recap-v1/` 下 14 个本地日的最小 HMAC 小票与 400 个本地日的 daily/coverage；不得落 prompt/回复/命令/工具内容、路径/项目、原始 event/session/profile/turn/tool ID，不得增加网络、导出或分享。首版不做 Token、金额、模型、推理强度、Skill、人的工作/编码时长、streak、峰值/最长项、排行榜或生产力评分\n- Claude Code / CodeBuddy 的阻塞式权限审批走 `POST /permission` HTTP hook；普通状态事件走 command hook（CodeBuddy command hook 对所有事件输出 `{}`，不做工具或权限决定）\n- permission automation（off / auto-tools / unattended）和 per-session grant 会在 bubble 渲染前产生真实 allow/answer。agent/family eligibility 是显式白名单；工具分类则因 mode/adapter 而异：auto-tools 对 Claude/Qwen 的未知 built-in fail closed，但其他已知 adapter 不都使用逐工具白名单，unattended 还会有意自动放行可作 Allow/Deny 的未知请求。新增 agent、工具或交互类型必须审查 policy + tests，不能从 `permissionApproval` 推导资格或笼统假设“未知请求都会 defer”\n- Telegram / 飞书 Lark 与本地 bubble 是并行决策通道。远程通道超时、断连、未配置或发送失败不得产生远程决定，更不得转成 deny；有本地 bubble 时请求继续 pending，只有 remote-only 且所有可用 client 都无决定时，整体请求才 no-decision 并回到 agent 原生流程\n- WorkBuddy 通过当前 `~/.workbuddy-ai/settings.json`（旧版兼容 `~/.workbuddy/settings.json`）的 Claude Code 兼容 command hooks 做 **state + Notification only** 集成：不注册 `/permission`，审批始终留在 WorkBuddy 原生沙箱与 GUI；无 `session_id` 的事件返回合法 stdout 后直接丢弃。当前只支持 macOS/Windows 桌面应用，没有已验证的 Linux/WSL CLI；不要把裸 `Electron` 当 WorkBuddy 进程。\n- Grok Build（agent id `grok-build`）通过 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json` 的 Claude Code 兼容 command hooks 做 **local / main-session / state + Notification only** 集成（Phase 1）：stdin 为 camelCase（`sessionId` / `toolName`），`hookEventName` 是 camelCase key + snake_case value，`hook_event_name` 是 snake_case key + PascalCase value。**逐 handler 的 `env` 结构化 marker `CLAWD_GROK_HOOK=v1` 是唯一所有权凭据**；文件名/substring（含 `grok-hook.js.backup`）只用于诊断告警，永不授权改写或删除。安装/卸载只增删含该 marker 的 handler，保留 unknown 顶层键、其他 event、foreign matcher group 与 sibling handler；没有 marker 的既有文件一律原样拒绝。`SessionEnd` 不写 `timeout`（继承 Grok 1.5s teardown），其余事件 5s。Windows 用 `windowsWrapper:\"portable\"` 形态，不得用 `&` / `-EncodedCommand` / 自造 `shell` 字段。Grok 没有 `PermissionRequest`，不注册 `/permission`，adapter 始终输出 `{}`。子代理事件（`subagentType`）直接丢弃；不注册 `SubagentStart` / `SubagentStop`。Grok 默认会扫 `~/.claude/settings.json`，所以 `clawd-hook.js` / `cursor-hook.js` / `auto-start.js` 只在非空官方 `GROK_HOOK_EVENT` 下直接退出，`GROK_HOME` / `GROK_SESSION_ID` / 无关 `GROK_*` 不得触发。`Stop` 只有精确 `reason === \"end_turn\"` 且无 background task / session cron / `stopHookActive` 才算完成，其余由 adapter 本地判定；`channel_closed` / `shutdown` 等 session-end 形态的 Stop 在 fence 之前丢弃。turn 顺序由 `src/grok-turn-fence.js` 的 bounded in-memory fence 仲裁（晚到旧 turn、重复 terminal、continuation Stop、Stop→StopCancelled 纠正）。不进入 subagent / WSL / Remote SSH / startup recovery / terminal focus / quota / context / recap turn 指标。`~/.grok/hooks/clawd.json` 是未发布的 PR preview 路径，只做 warning，不得自动接管或删除。\n- Codex 的阻塞式权限审批走 official `PermissionRequest` command hook：hook 脚本长连接 `POST /permission`，只允许 stdout 返回 sanitized `behavior/message`，`updatedInput` / `updatedPermissions` / `interrupt` 必须 omit。权限模式默认 `auto`（旧 `native` 规范化为 `auto`），仅准确本机 session/turn 的人工 reviewer 证据可进 Clawd；未知、自动 reviewer、MCP/app、远程/WSL 均 no-decision；唯一例外是远程/WSL（路由 reason 为 `nonlocal`）的 Bash/apply_patch 在全局自动放行会立即 allow 时（`wouldAutoAllowPermission`：非 reminder hold、非会话覆盖、非交互子代理）由 Clawd 直接放行（#1186），路由后若设置已变则 no-decision，绝不弹气泡。`intercept` 是显式接管；升级时旧 `intercept` / `native` 统一迁到 Auto 一次，之后重新选择的 Intercept 会保留。不得用全局 config、其他会话或旧回合推断当前请求的审批方；证据不足时返回 no-decision，交还 Codex 原生流程。\n- hook 脚本只允许依赖 Node 内置模块，以及同目录 `hooks/` 下、且登记在 `src/remote-ssh-deploy.js` 的 `HOOK_FILES` 部署清单中的纯 Node helper（如 `server-config.js` / `shared-process.js` / `json-utils.js` / `codex-originator.js` / `codex-subagent-fields.js` / `context-usage.js` / `state-payload-size.js` / `quota-bucket.js` / `claude-rate-limits.js` / `codex-rate-limits.js` / `antigravity-context-usage.js`）；manifest-consistency 测试强制检查依赖闭包，新增 helper 必须登记\n- CJS hook 脚本需要稳定终端 PID 时，必须复用 `hooks/shared-process.js` 的 `createPidResolver()` 及其 lifecycle context；不要复制进程树 walk 或用 `process.ppid` 简化。`getStablePid()` 只是 opencode-family plugin 的内部 resolver\n- `agentCmdlineCheck` 只对进程名在 `agentCmdlineNames` 里的祖先进程运行，默认是 `DEFAULT_AGENT_CMDLINE_NAMES`：`node` / `node.exe`，加上 Linux 上没设过 `process.title` 的 Node 在 `ps -o comm=` 里的名字——Node 23.8–25.4（含全部 24.x）把主线程命名为 `MainThread`、≥ 25.5 为 `node-MainThread`，Linux 报的进程名就是主线程名。传入 `agentCmdlineNames` 会整体替换默认值：只想加名字的 adapter 必须在选项里直接写成 `agentCmdlineNames: new Set([..., ...DEFAULT_AGENT_CMDLINE_NAMES])`（如 ZCode；可以跨行，方括号里只能有普通字符串字面量和 `...DEFAULT_AGENT_CMDLINE_NAMES` 本身，不能有注释或其他表达式；简写属性、先存进变量，或任何不是这个形状的提及（包括注释里的）都会被判不合格，因为文本检查无法核对），只有刻意只探测非 Node 宿主的（WorkBuddy 的 `electron`）例外，`test/shared-process.test.js` 会扫描 `hooks/*.js` 检查\n- opencode v1 权限不走 `permission.ask` hook，而是 event hook + reverse bridge；v2 走 `ctx.permission.hook(\"evaluate\")` 的阻塞 HTTP 响应\n- OpenCode / MiMo v1 原生问题走独立本地 `/question` 长轮询，不复用审批回包；遵循全局 permission bubble 开关与 family 单 agent 开关。只接受已核实的 v1 来源、版本和问题 schema，提交前用原 SDK client 复核精确 request/tool/session，答案保持有序 `string[][]`；无决定返回 204 交还原生。OpenCode 由原生 reply RPC 的 `true` / 404 判定提交结果，MiMo 仍需精确 `question.replied` 答案匹配。子会话问题、OpenCode v2、Remote SSH 及未审核 agent 保持原生；不要改 Claude/Hermes wire 或托管 generation 依赖集合。详见 `docs/guides/agent-questions.md`。\n- opencode-family v1 插件经 `ctx.client` 连回宿主时，主机为通配监听地址（`0.0.0.0` / `[::]`）就按次改用 `127.0.0.1` / `[::1]`（不改宿主共享的客户端配置；非通配地址保持原调用形状）。默认 TUI 走进程内 fetch；`opencode serve` / `web` 下这是对监听地址的真实 HTTP 请求，受宿主进程里的 `HTTP_PROXY` / `NO_PROXY` 影响，而通配地址不会自动绕过代理。桥接回复失败返回 `{ok:false,status,error}`（`status` 为上游状态码，缺省 0）。\n- OpenCode 2.x（npm `@opencode/cli`，issue #1039）由 `hooks/opencode-plugin-v2/` + core.mjs 内 `createOpencodeFamilyPluginV2` 承接：installer 在同一 generation 内额外物化 `opencode-plugin-v2/index.mjs`（v1 四文件、v2 五文件；目录 specifier 解析 index.mjs、无需 package.json，2.0.15 实测），并把它写进 **`plugins` 键**，同时清理 Clawd 自有的旧 `plugin` 条目；用户条目、tuple/options 和 v1 行为保持不变。未被 Clawd 纳管的未知 `plugin` 条目仍只报 loader WARN；v1 对未知 `plugins` 键的静默丢弃只在 **1.18.16+** 成立——1.18.15 及更早会以 `Unrecognized key: plugins` 拒绝整个 config（anomalyco/opencode#41312，2026-08-08 起才忽略未知顶层键），因此 `plugins` 写入由宿主探测决定（`hooks/opencode-host-detect.js` 三态：探测到 v2 才写；探测到 v1 不写并清扫 owned 残留；探测失败不碰该键；`CLAWD_OPENCODE_HOST` 环境变量可钉死结论，Doctor 在无 v2 宿主时不要求 v2 条目）。v2 插件是零 import 纯对象 `{id, setup}`（v2 loader 拒绝函数 default export，`@opencode/...` 裸包名无插件本地 node_modules 不可解析），事件经 `ctx.event.subscribe()`（`session.step/tool/execution.*` 词汇完全换代，未知事件一律忽略），cwd 取事件信封 `location.directory`，标题走 `session.renamed`，context usage 走 `session.step.ended` 的 step tokens（`session.usage.updated` 是 session 累计计费值，不能当占用率）。权限走 **`ctx.permission.hook(\"evaluate\")` 阻塞长连接 POST `/permission`**，决定就是 HTTP 响应体 `{decision: allow|always|deny}`（服务端按 `hook_source === \"opencode-plugin-v2\"` 路由到 v2 阻塞子分支），只有 `200` + 身份头 + 合法 JSON 才采纳决定，204/超时/断连/非 200/任何错误都不改 effect 回原生 ask UI；配置 allow 也进 hook 但绝不降级；单条 shell 命令以 `tool_input.resource` 传输，服务端 v2 分支会为其别名出 `command` 以接入破坏性操作提醒（`mapOpencodeV2ShellResource`，非 shell 工具不映射；全字符串的多 resource 以换行合并作扫描别名）；resources 原样整组转发（对象转 JSON 字符串），不做条数/长度截断，唯一边界是整 body 超 512 KiB 时跳过转发。\"Always allow\" 无宿主持久化 API，用插件内 per-session 内存规则（随常驻 service 生命周期，气泡对 v2 使用单独文案说明关闭/重开终端不会撤销）。插件跑在常驻共享 service（daemon）：`source_pid`/进程树不可信故**整组省略**（终端跳转对 v2 降级），安装/更新后需 `opencode service restart`。`ctx.permission.hook()` 按上游 v2.0.15 类型返回 `Promise<Registration>`：本实例 dispose（setup 返回的 cleanup，宿主也会在插件 scope 关闭时调用）会调用 `registration.dispose()`，注册 Promise reject 只记日志不影响事件订阅。事件订阅**不等待** hook 注册（注册挂起/reject 时状态上报照常），reload **不等待**上一代注销完成；本实例清理先同步完成本地清理（标记 disposed、abort 订阅、身份恢复）再去注销 registration，注册 dispose 有约 2s 上限、超时只记日志，注册未完成就被取代则在注册完成那一刻立即注销，不残留活 hook。上游 v2.0.15 的 trigger 对同名 hook 依次调用每个仍注册的回调、共用同一个可变 event，而我们的注销是异步的，所以 reload 窗口内旧回调可能仍被调用：已退役实例的回调入口检查 `instance.disposed` 后直接返回，不 POST、不改 event。每个 ask 各自转发（`source.id` 是工具调用级、不是 ask 级，同一工具调用会发出多个不同 ask，如 external_directory + edit），不做内容去重。config 顶层重复 `plugins` 键按歧义处理：Doctor 报 `config-corrupt` 不抛异常，register/卸载在首次写入前中止（v1 宿主 sweep 只告警并跳过），v1 `plugin` 键行为不变。v1 1.18.31 tuple 契约、generation 布局、owner/lock 语义不变；`inspectGeneration` 把历史 4 文件集接受为合法 owned-stale 形态以便迁移。真机证据与降级项见 `docs/investigations/opencode-v2-e1-evidence.md`\n- OpenCode 的 plugin 注册不再直接指向打包/源码目录：`agents/opencode-family.js` 的 `managedMaterialization:true`（OpenCode true / MiMo 本次 false）gate materialize、ownership classifier、managed Doctor 与 generation cleanup。开启后 register 必须在目标 home 下维护 `<home>/.clawd/integrations/opencode-family/opencode/homes/<configDirHash>/generations/<bundleHash>/` 的内容寻址 generation（OpenCode v2 当前五文件，历史 v1 四文件），同一 generation 可同时物化 v1/v2 入口文件，但不因此在配置中注册两个键；探测到 v2 宿主时只把 `opencode-plugin-v2` 入口写入 `plugins`，并将 `plugin` 键仅用于清理 Clawd 自有旧条目；v1 宿主和探测不到版本时保持原有 v1 注册路径；bundle allowlist 固定为 `<agent>-plugin/index.mjs` / `<agent>-plugin/package.json` / `opencode-family-plugin/core.mjs` / `opencode-family-plugin/session-ids.mjs` / `opencode-plugin-v2/index.mjs`（v2）。owner record（`owner.json`，literal `clawd-on-desk.opencode-family.target`）与 target-scoped `mutation.lock/`（独立 literal `clawd-on-desk.opencode-family.target.lock`）是所有权与 app-present 真相；lock 被持有时不并发写：interactive Install/Repair/CLI/Uninstall/About cleanup 只做一次短而有界、可注入 delay 的重试，startup automatic 不等待直接 skipped；合法且超时 2 倍以上、PID 明确 ESRCH 才允许 atomic quarantine 接管，corrupt/foreign/live/EPERM 一律不接管；release 只删自己 token 的 `lock.json` 与随后为空的精确目录，禁止 recursive cleanup。owner 的 `activeSourceMarker` 必须是 `<activeSourceRoot>/<pluginDirName>/index.mjs`（共享 canonical 身份、Windows 折叠大小写）且为 regular file，目录/dangling/错 plugin 目录/root 不匹配都不算 live。同一 target 的 source owner 冲突（marker 仍存在）一律 `owner-conflict`，不得来回改 config；旧 owner 的源码 marker 已不存在时，新 source 必须在锁内重读并原子接管 owner（config 已 current 也不例外），否则残留死 owner 会让托管 plugin 永久 inert。锁内若 config 与当前 source owner 都已被并发操作收敛，则本次零 mutation 返回 skipped。lock release 失败不得掩盖结果：成功保留 status 并附 warning + 精确 lock path 的 residualPaths，已有 primary error 时保留原错误。basename 本身永不构成所有权；copy 到 managed layout 外的完整 generation 因缺少对应 owner record 而 inert，只有 verified-current-copy 可 Repair。tuple 契约固定为 OpenCode 1.18.31 实测的 `[specifier, optionsObject]`（隔离 `opencode debug config` 证据：第二项必须是普通对象，数组/字符串第二项会被宿主拒绝）；重写只替换 `plugin[index][0]`，options 值级保留，绝不写回嵌套 tuple，malformed array 原样保留。`options.pluginDir` 仍是 test-only expected-canonical override（跳过 generation/manifest/boundary，但不跳过 ownership/唯一 entry/read-back），`resolvePluginDir()` 仍返回 source。新建文件按当前用户普通写权限落盘：不得加 readonly/deny-write ACL，不得用 `W_OK`/`r+`/INIT 日志/session 活跃做健康门禁。Uninstall 以“活动注册是否移除”为提交依据（`registrationRemoved` false/null 阻止 Settings 提交，undefined 沿用 legacy status），残留 generation 只产生 warning；清理有效 generation 时必须先在同一 `generations/` 内原子改名为非 canonical `.cleanup-*` 再递归删除，删除失败不得占住原 hash 槽。兼容旧版本留下的半残 canonical 目录时，只允许在 owner 已 released、bounded history 精确证明该 canonical entry、且配置无活动 Clawd entry 的条件下，把它原子隔离为 `.recovery-*` 后重新物化；active/foreign/unproven/canonical-in-use 一律继续 fail closed，绝不原地覆盖或修补可疑 bytes。托管 core 的 orphan inert gate（`evaluateManagedLayoutGate`）必须在 `resetDebugLog()` / PID walk / bridge / handler 注册之前，owner marker 缺失、损坏、agentId 不匹配或 `activeSourceMarker` 不存在时返回空 handler；source-direct 模式保持原行为。MiMo 保持 broad-basename register/unregister/Doctor 契约不变。\n- Pi 通过 `~/.pi/agent/extensions/clawd-on-desk` 的 global extension 推送状态；Clawd 对 Pi 是 **state-only**，不接管权限、不弹权限气泡，也不把 Pi 的默认 YOLO 流程改成手动确认\n- OMP (oh-my-pi) 通过 `~/.omp/agent/extensions/clawd-on-desk` 的 global extension 推送状态，agent id `omp`，对 Clawd 同样是 **state-only**。它是 Pi 的 fork（包名 `@oh-my-pi/pi-coding-agent`），所以 `hooks/omp-extension.ts` 刻意与 `hooks/pi-extension.ts` 保持逐行对齐（只差 package import、core import 与函数名），进程树遍历与终端识别不得各自漂移；OMP 独有的差异全部收在 `hooks/omp-extension-core.js`。**完成必须走 `session_stop` 候选 + 终态 `agent_end` 提交的两阶段协议** —— `session_stop` 先保留主会话边界，OMP 再汇总所有 extension 的续跑请求；只有后续 `agent_end.willContinue !== true` 才向 Clawd 发完成。不得直接把任一事件单独映射为完成：仅用 `agent_end` 会把 subagent/调度边界误报为完成，仅用 `session_stop` 则会早于 extension 续跑判定。`session_switch` / `session_branch` 要为被切走的旧 session 补发一条合成 `SessionEnd`，否则 Clawd 会留下一条再也不会有人上报的活动行。session id 命名空间是 `omp:<raw>`，且必须始终带 `session_title`（多个交互式会话合法地共用同一个 cwd，缺标题会让列表和跳转目标无法区分）。安装器遇到社区桥接 `~/.omp/agent/extensions/clawd-on-desk-omp.ts` 时必须 fail closed 跳过：两者上报同一批事件，同时存在会双发。当前 `assets/source/agent-icons/omp.png` 是 `fallback: true` 的占位 π 字形，不是 OMP 官方品牌素材，拿到授权素材后应替换\n- DeepSeek Harness 首发是 **web profile / Windows-first experimental / plugin-only**；rc.6 已于 2026-08-29 完成 macOS / Windows x64 源码运行的真实 API-backed session/approval smoke（#962）；rc.2 Windows packaged-app 证据仅覆盖安装、web boot 与直接 bridge client 的 state/Allow/Deny 往返（#938），不得合并宣称 rc.2 安装包的真实 API 会话已验证。Clawd-managed in-process plugin 监听公开 `session/created`、`session/event`、`session/disposed`、可选 `sessionProjections.onChanged` 与 blocking `approval/request`；标题和上下文仅作为会话元数据同步，不占用生命周期 seq。状态按 session FIFO 上报并携带上游 seq；Clawd 不读取 `$DSH_HOME/storages` projection。普通审批进入独立 DSH `/permission` adapter，只支持人工 Allow Once / Deny；204 / 断连 / DND / disabled 都由 plugin `next()` 交还 DSH 原生 web answerer。`ask_user_question` 始终留在 DSH 原生 provider；DSH 不进入 `KNOWN_PERMISSION_AGENTS`，auto-tools / unattended / per-session grant 全部 DEFER。安装器通过官方 `dsh plugin --profile web add/remove` 管理 immutable marker-owned generation，foreign 同名包 fail closed；版本放行改成按 **小版本族（major.minor）**。维护两张表：一张是唯一写出具体版本/npm artifact/integrity 的已验证 artifact 清单（优先 `@deepseek-ai/dsh@0.2.0-rc.2`（integrity `sha512-EAJ3gPNcVt/uv8X19PMm9NkVhWgT7xXNMk0UKCVm+IQ5rpSQOcsMUa0HWlnYYVybKMsccjcRB21vVVsaXQ6IdA==`，2026-10-04 已做静态接口核对，并在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证了用 Clawd 安装器装出的 generation 的启动同步换代、会话状态、HUD 标题/上下文、Allow/Deny 与消息上的失败标记；其 `tool/result` 把失败标记放在消息 `message.isError` 而不是内容项上，bridge 新旧两种位置都认），并保留 `@deepseek-ai/dsh@0.1.5-rc.3`（integrity `sha512-c0W6Xqc4ChjFcCJkbzPeIxZQdnbKqe+QAcJzWGtogg0ZzsnZRcw3vopMyZ5oZU6E2fmyqGcyDR1sBeiCH4yHcg==`，2026-09-27 已在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证启动同步安装、会话状态、HUD 标题/上下文与 Allow/Deny）、`@deepseek-ai/dsh@0.1.5-rc.1`（integrity `sha512-rmNmzQCg3oIc1z8xH7izRSOuy1TNzq+/NILyfM+7e8DKOyV+yBtg47WEsqR2SiIe1ATec3L/rUa1YhIcfQ2XEg==`）、`@deepseek-ai/dsh@0.1.1-rc.2`（integrity `sha512-UP1UIh6q3Gme/yXRn/QL2P8IsVlv8Shpg22TRJIZPsCRWLm4CBiA1MUvXmJAfsOEETBMLAl+xWPtFw6ICsN3wg==`）与 `@deepseek-ai/dsh@0.1.0-rc.6`（integrity `sha512-brpZfED7ieRa2PQ5tUxMhHrM1pb2CmKFVM/f6yMULBDMicahk+Z2OsHgTwTDnoiZm23Ftu9rQz0NN4pflaoJcg==`）），一张是族表（`0.2` 下限 `0.2.0-rc.2`、`0.1` 下限 `0.1.0-rc.6`）。host 版本经严格解析（拒绝前导零、空预发布标识与 build 元数据）通过、major.minor 命中族、且不低于该族下限即放行；同一族内不同 host 版本共用一个 generation，出现新的小版本必须重新验证并新增一个族。旧的精确 `=<version>` marker 仍按原 range 核对哈希，新 generation 一律写族 range；Install/Repair 按 host 版本所在的族选择目标契约，Uninstall / 手动 npx 命令在 marker 版本已列入清单时钉它自己的 artifact，否则钉同族版本最高的已验证 artifact（无 CLI 且无 marker 时用首选族最新的并记为 assumed）；加锁前后比较的是实际检测到的 host 版本，不看族。DSH 的 `metadata_only` 标题/上下文旁路必须核对目标会话的 `agentId` 确为 `deepseek-harness`，撞名的其他 agent 会话直接丢弃。`47f9438` 仅是源码调查基线，不代表任何 tag/commit 映射。\n- DSH 每个 canonical `DSH_HOME` 的 mutation lock 只有在 owner/schema/token/PID/timestamp/owner-recorded operation timeout 合法、超过该 owner timeout 两倍、且 OS PID probe 明确为 `ESRCH` 时才允许 atomic-rename takeover；live、`EPERM`、unknown、corrupt/foreign owner 一律拒绝并返回精确 lock path。canonical lock 的 owner write/release 禁止 recursive cleanup。无全局 CLI 时生成的手动 npx generation 必须先在同一锁内写 owned reference，手动 add/remove 命令必须显式 pin shell-quoted canonical `DSH_HOME`；malformed/foreign/concurrently replaced reference 一律 fail closed 并保留 generation\n- DSH 桌面版支持（#1119）与 web 共用一个 agent id `deepseek-harness`：web profile 和 DeepSeek Harness 桌面版是两个承载方、各自一个 profile（桌面版是 `$DSH_HOME/profiles/desktop`），但在 Settings 和 Doctor 里仍是**一行**，显示名 `DeepSeek Harness (experimental)`，一次排队操作先 web 后 desktop、一边失败不影响另一边；安装只要有一边核实健康即成功（另一边失败变 warning + 常驻提示），卸载要所有 Clawd 注册都没了才成功。桌面版查找：macOS 用 `/Applications` 或 `~/Applications/DeepSeek Harness.app` 里自带的 `Contents/Resources/runtime/cli/bin/dsh`；Windows 按用户安装，从 `HKCU` 卸载项（显示名以 `DeepSeek Harness ` 开头）与 `%LOCALAPPDATA%\\Programs\\DeepSeek Harness` 找 `resources\\runtime\\cli\\bin\\dsh.cmd`，注册表用 PowerShell 读 UTF-8 JSON、不用 `reg.exe`；Linux 不支持桌面版。静态版本来自 `Info.plist` / 卸载项 `DisplayVersion`，真正动手前跑一次启动器 `--version` 核实。桌面版**永不用 npx**，手动 npx 命令与 manual reference 只属 web。每边角色是 `mutable` / `diagnose` / `not-applicable`：桌面版没装、或 profile 从未初始化（桌面版没打开过）→ 不适用并提示打开一次；foreign 同名包、文件读不了、清理残留、注册查不清、版本不支持、装了不止一个桌面版（`multiple-desktop-installs`）、桌面版找不到但注册还在（`carrier-unavailable`）、桌面版查不清（`desktop-unverifiable`）→ 只报告不动手。启动同步在集成已安装且启用时会把插件加进已初始化的桌面版 profile；桌面版开着也会加载新加的插件，只有插件更新（换了 generation）后要重启。常驻提示在 `hooks/dsh-notices.js`，按 profile 存 `notices-web.json`/`notices-desktop.json`，四种 kind（`restart-required`/`first-install`/`manual-command`/`failed-target`），写不进去只算 warning；提示显示在 Settings → AI Coding Tools 里这一行下面。Doctor 一行详情 `web: …; desktop: …`，状态取适用边里最差，只要有一边能尝试修复且不健康就给修复按钮（`src/doctor-detectors/agent-integrations.js`）。插件在 DSH 里被关掉（依赖在、bundle 行没了）时 `plugin add` 不会重开：显式修复先 remove 再 add（add 前先清掉上游 remove 留下的自有链接，Mac 是符号链接、Windows 是 junction），按 profile 记 `repair-operation-<profile>.json`，中断后下次显式修复续做，启动同步只报 `plugin-disabled-in-dsh`。`generations/` 两边共享，任一边有未处理状态（检查记录、清理残留、坏修复记录或 manual reference、读不了的 profile、符号链接 profile 目录）时清理暂停但不挡安装，卸载残留进 warnings。检查记录按 profile：web `inspection-required.json`、桌面版 `inspection-required-desktop.json`。`plugin add/remove` 写命令两边都超时 300 秒（web 原 120 秒），比上游写锁等待长。上游 `dsh plugin remove` 只清 `link:` 清单和锁、`node_modules` 链接会留下，Clawd 卸载自有插件时确认归属后清掉。Windows 静态查找是同步代码、不起进程，只读异步快照：启动时（不管 DSH 是否启用）、打开 Doctor 前、Agents 页手动扫描时刷新，没快照时桌面版显示\"查不清\"。安装检测把\"找到桌面版\"也算装了 DSH（`src/agent-installation-detector.js`）。桥接插件在 apply 时读 `ctx.profileContext?.name`，只有 desktop profile 才在 state / 审批载荷里带 `dsh_carrier: \"desktop\"`（metadata 不带；web 或未知 profile 一律不带）；Clawd 只接受 DSH + `dsh-plugin` + 本机 + 非 WSL 的载体，按生命周期覆盖或清除、不粘滞，权限 fallback entry 与快照（含签名）都带上它。点击桌面版会话时 `getSessionFocusTarget` 在 darwin/win32 返回 `dsh-desktop`（`dsh://open`），分派先 `shell.openExternal(\"dsh://open\")`，被拒绝再按 `discoverDshDesktopSync({ requireUniqueApp: true })` 的兜底要求唯一安装启动界面程序（macOS `open <appRoot>`、Windows 启动 `<appRoot>\\DeepSeek Harness.exe`，去掉 `ELECTRON_*`/`NODE_OPTIONS`，不用 CLI 启动方式；两份真实路径不同的有效安装视为有歧义，只要还有核实不了的候选也不自动启动，同一份安装的符号链接只算一份）；只能打开应用窗口、不会切到具体对话，web 会话仍不可跳；桌面版启动时会重新打开上次的对话，Clawd 只在这个对话有了动作（提问、工具调用、审批）之后才把它放进 Session HUD（`awaitingActivity` 并入快照 `hiddenFromHud`，但不关跳转；与 Kimi Code 共用同一个标记），Dashboard 照常列出、按钮照常可跳；2026-10-05 macOS 26.6.2 与 Windows 11 x64 源码运行真机验证（桌面版 `0.2.0-rc.2`）：别的窗口在前、最小化、关窗后，点击都经 `dsh://open` 把窗口带到最前；协议打不开时的启动兜底只有单元测试。真机证据：2026-10-04 macOS 源码运行（Clawd `ac64d726`，桌面版 `0.2.0-rc.2` + 全局 `@deepseek-ai/dsh@0.2.0-rc.2`）验证了启动同步把插件装进桌面版（与 web 共用 generation）并出现\"已装进桌面版\"提示、Doctor 一行两边正常，桌面版真实会话的 Allow 建成文件、Deny 后文件内容和 mtime 不变且 Clawd 显示 `PostToolUseFailure`，\"知道了\"后提示消失，改 bridge 源码（同 Clawd 版本）后启动同步两边报 `generation-conflict` 并提示去 Doctor 修复、修复把两边换到新 generation/删旧/出现\"重启桌面版后生效\"、重启后事件来自新宿主进程，设置页卸载后两边依赖与 bundle 行都没了、上游残留链接被清、generation 删除、两边提示清空，再在设置页安装两边都重新装上、桌面版重新出现\"已装进桌面版\"（\"经设置页首次安装\"因此已覆盖），开着 DND 时桌面版的工作区外写文件不弹 Clawd 气泡、返回 no-decision、桌面版弹自己的原生审批框、批准后文件建成且事件照常到达。2026-10-04 Windows 11 x64 经 SSH 用 Node 直跑安装器代码（管理员会话，桌面版在 `%LOCALAPPDATA%` 按用户安装 `0.2.0-rc.2`、全局 dsh `0.1.0-rc.6`，web 在 0.1 族、桌面版在 0.2 族）：PowerShell 读注册表找到桌面版、静态模式无快照时报\"查不清\"且不起进程、自带 `dsh.cmd`（带空格路径）`--version` 返回 `0.2.0-rc.2`、`dsh.cmd plugin --profile desktop add` 经 pnpm junction 装入并核实、记录\"已装进桌面版\"、两族各用一份 generation 并存、Doctor 一行两边有修复按钮、卸载桌面版清依赖与 bundle 行并清掉 `dsh plugin remove` 残留 junction、只删桌面版那份 generation 而保留 web 在用的；2026-10-04 另在 Windows 上以真 Clawd（Electron，源码运行、用户会话、普通权限）验证：先抓到一个只在 Electron 里出现的 bug（Electron 的 fs 把 `app.asar` 当目录、Windows 安装目录核实要求它是文件，于是在真 Clawd 里桌面版被判成没装，已在 `d8190692` 修成\"存在即可\"）；修好后桌面版一直开着（宿主进程未重启），启动同步把插件装进桌面版并记\"已装进桌面版\"，在桌面版新开对话的事件来自那个未重启的宿主进程，**Windows 上桌面版开着也会加载新加的插件**。**未覆盖**：Windows 上桌面版的审批、Windows 上的 Electron 界面（设置页提示、Doctor 窗口、启动预热）、打包后的 app、Linux、HTTP 204 交还与取消、装了多个桌面版。**管理员 junction 观察（推断）**：提升过的管理员进程在 Windows 11 上穿不过非管理员进程建的 junction（PowerShell \"untrusted mount point\"、Node `UNKNOWN`），该会话里 web 的旧 junction 读不到、web add 失败，桌面版同会话新建的 junction 正常；普通权限运行不受影响；由此推断以管理员身份运行 Clawd 可能把普通权限装好的插件读成缺失，未用以管理员身份运行的 Clawd 直接复现\n- OpenClaw 通过 `~/.openclaw/openclaw.json` plugin 路径做 state-only 集成；Phase 1 不做 permission bubble / terminal focus，主要支持本地 `openclaw tui --local`\n- Antigravity CLI (agy) 通过 `~/.gemini/config/hooks.json` 做 **state-only** hook 集成（PreInvocation / PostToolUse / PostInvocation / Stop），**不注册 PreToolUse**。agy LLM 会主动调内置 `ask_permission` 工具，触发 agy 自己的 5 选项 native menu（含 \"Persist to settings.json\" 持久白名单），Clawd 不插手权限决策也不双层确认。`agents/antigravity-cli.js` `capabilities.permissionApproval` / `interactiveBubble` 均为 false。\n- Qwen Code 通过 `~/.qwen/settings.json` 做 hook-only 集成（SessionStart / SessionEnd / UserPromptSubmit / PreToolUse / PostToolUse / Stop / Notification / PermissionRequest），支持状态与阻塞式 `PermissionRequest` 权限气泡；`disableAllHooks: true` 时注册条目不会触发。\n- QwenWork (千问办公) 通过 `~/.QwenWorkCN/settings.json` 做 **hook-only / state-only** 集成（agent id `qwenwork`；SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / Notification / PermissionRequest / PermissionDenied / SessionEnd）。`PermissionRequest` / `PermissionDenied` 只作为观察映射成 `working`（每任务 40+ 次，映射成 notification 会刷屏），hook stdout 恒为 `{}`：Clawd 不产生 allow/deny，不注册 `/permission`，也不进入 permission automation eligibility，唯一决策者是 QwenWork 原生权限流程；`agents/qwenwork.js` 的 `capabilities.permissionApproval` / `interactiveBubble` 均为 false。Windows command 必须保持 `windowsWrapper:\"portable\"`（QwenWork 经 POSIX shell 执行 command hook），PowerShell `-EncodedCommand` **只**用于识别并原地迁移旧条目，不是当前写入形态。marker 只认 `qwenwork-hook.js`，不得仅凭 `name:\"clawd\"` 删除用户 hook；混合 entry 中第三方 hook 原样保留。session id 命名空间是 `qwenwork:<raw>`；`~/.QwenWorkCN/workspace/<id>` 这类内部工作区 cwd 不做 basename 回退，避免 HUD/Dashboard 显示内部 ID。当前真实支持平台只有 macOS / Windows 桌面端（官方下载页 https://qwenwork.cn/download 只提供 macOS 14+ / Windows 10+ / HarmonyOS 6.1+，没有 Linux 客户端），因此 `processNames.linux`、resolver linux agent name 均为空，也不进 `src/wsl-deploy.js` 的 WSL Pair 映射。桌面主进程长驻、不代表 active turn，`startupRecoveryProcessNames` 全空、无 startup recovery。安装/卸载走 Settings → AI Coding Tools，或 `npm run install:qwenwork-hooks` / `npm run uninstall:qwenwork-hooks`；卸载必须同时在 `hooks/cleanup-integrations.js` 的 `MANAGED_AGENT_IDS` / `AGENT_CLEANERS` / `byAgent` 里有条目，否则 About cleanup 只会改 prefs、hook 留在磁盘上\n- ZCode 通过 `~/.zcode/cli/config.json` 的 `hooks.events.*` 集成全部 7 个支持事件（SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / PermissionRequest，无 SessionEnd / Notification）。PermissionRequest 为阻塞式权限审批：hook 长连接 `POST /permission`（HTTP 等待 590s，installer 注册 `timeoutMs: 600000`），有决定时 stdout 返回最小合法 `{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}`（deny 可带 `message`），无决定 / 超时 / 断连 / 任何错误输出 `{}` 并 exit 0，ZCode 回退原生权限流程；`interrupt` / `updatedInput` / `updatedPermissions` / `permissionUpdates` 必须 omit（最小输出 union 按 ZCode 3.5.x 严格 schema 约束；macOS ZCode 3.8.1 已完成真实 hook / 气泡 Allow/Deny 往返，3.5.x PermissionRequest 真机往返未覆盖）。超时单位陷阱：ZCode `timeout` 是秒、`timeoutMs` 才是毫秒，且超时按事件区分（PermissionRequest 600000、state 事件 8000）。Phase 2 只允许人工审批：ZCode 不进入 `KNOWN_PERMISSION_AGENTS`，global / per-session permission automation 在工具面与会话身份审计完成前全部 defer。prefs v14→v15 迁移把 Phase 1 持久化的 `zcode.permissionsEnabled:false` 翻 true（当时开关从未渲染、无用户意图）。配置必须有 `hooks.enabled=true` 才会执行；安装器只在该字段缺失时补 true，显式 `hooks.enabled=false` 或 Clawd 单项 hook 的 `enabled=false` 必须保留，Doctor warning 且不提供会覆盖用户选择的 Fix。ZCode 导入 Claude 配置后，只清理 `.zcode` 中明确引用 `clawd-hook.js` 的 Clawd-owned 条目，绝不改 `~/.claude/settings.json`。安全边界（复核后新增）：`/state` 生命周期 sweep 对 zcode（及 qwen/DSH 等 native-fallback adapter）只允许 no-decision，绝不伪 deny；hook 侧 `tool_input` 预算内原样发送、任何截断（长 Bash 尾部 `rm -rf` 场景）或序列化超 512KiB 一律 fail-closed 输出 `{}` 交还原生 UI；无 allow/answer/plan capability 的 interaction（如 ZCode 真实的 ExitPlanMode / AskUserQuestion）本地气泡与远程卡片都不提供决定入口、直接 204；全局气泡关闭只关本地窗口，Telegram/飞书 remote-only 审批仍可用（per-agent gate 关闭才是全退出）；installer 遇到 foreign `PermissionRequest` hook 时不注册自己的 blocking hook，若 foreign hook 后出现则移除自己的 managed hook（ZCode 同事件 hook 串行执行、后写覆盖，Clawd allow 会盖掉用户 hook 的 deny），Doctor 报 `permission-conflict` 且不给 Fix；六个 Phase 1 managed hook 全部显式 disabled 时新 PermissionRequest 继承 `enabled:false`；服务端 pre-parse 超限一律断连回退，不伪造 deny\n- Qoder / Qoder CN 共用 `qoder` agent，通过 `~/.qoder/settings.json` / `~/.qoder-cn/settings.json` 做 **state-only** hook 集成；各自尊重 `QODER_CONFIG_DIR` / `QODERCN_CONFIG_DIR`，同步所有已初始化目录，不创建缺失版本目录，卸载/cleanup 覆盖两版且只移除 Clawd entries，Doctor 不得让健康的一版掩盖另一版故障。Clawd 只把 `PermissionRequest` / `PermissionDenied` 当 notification 观察，**不替 Qoder 做权限决策**，hook stdout 恒为 `{}`；Windows command 必须保持 `windowsWrapper:\"portable\"`。session id 命名空间是 `qoder:<raw>`；启动恢复只认 CLI `qodercli` / `qoder-cli` / `qoderclicn`，不认闲置 IDE / CN 桌面进程；本机原生会话标题由 `src/qoder-session-title.js` 低频异步增量读取，通过 `updateSessionMetadata` 更新；SessionEnd / 禁用 / 退出取消旧读取，远端与 WSL 路径不在本机读取。2026-10-18 已核对 Windows CN runtime 1.1.69 的真实 SessionStart / UserPromptSubmit / Stop hooks，用户确认开启 Clawd Qoder 接入后任务状态恢复；macOS/Linux CN 未实测\n- TraeCode (Trae CN) 通过 `~/.trae-cn/hooks.json` 做 **hook-only / state-only** 集成。Windows command 必须保持 `windowsWrapper:\"encoded\"`：Trae 的 Windows Sandbox 会把 hook 命令作为 `trae-sandbox.exe --command-line` 的单个原生参数再次转发，普通引号或 `portable` 形态会在含空格路径处拆分；外层必须保持无引号的 PowerShell `-EncodedCommand`，POSIX 则继续使用普通 quoted command。该约束不适用于经 POSIX shell 执行 Windows hook 的 agent（如 Qoder / QwenWork）。\n- MiniMax Code 通过 `<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/` 的 **Clawd 独占本地插件**做 **state-only** 集成（manifest 用 `.claude-plugin/plugin.json`，hooks 文档按 MiniMax 的 CLAUDE sourceFormat 解析；不用 `.minimax-plugin/`，那会走 MINIMAX 格式：matcher 必须非空且不支持 exec-form args）。handler 固定 exec-form `command=node 路径 + args=[minimax-hook.js]`（spawn 直执行、无 shell、免引号），`timeout` 单位是秒且只接受 1–10 的整数（越界的 handler 被丢弃而不是钳制；SessionEnd 事件总预算仅 3s），因此 **PermissionRequest 物理上不可阻塞审批、完全不注册**，也没有 Notification 事件；hook stdout 恒为 `{}`（permissionDecision 缺省 abstain）。目录级所有权只认结构化凭据 `.clawd-managed.json`（`{app:\"clawd-on-desk\",integration:\"minimax\",managed:true,version:1}`，同 Pi 约定；MiniMax 只读 manifest 声明的文件，会忽略它），且凭据与所有受管理路径（`.claude-plugin/`、`hooks/` 及其文件）都不得是符号链接；目录名、manifest name、文档里的 basename/子串乃至整份文档指纹都永不授权改写或递归删除，缺凭据的目录（包括补丁前预发布构建写出的）一律 fail closed，只能手动删除后重装。staging / removal 目录固定落在数据目录（`plugins/` 之外，MiniMax 会把 `plugins/` 下每个目录项都当插件候选，含点号名）：首装在 staging 写全三份文件后一次 rename 发布（只覆盖空目标，非空目录/文件/链接拒绝；空 `clawd-state/` 视为未占用），失败时尽力删除 staging；已拥有的目录原地逐文件更新，中断后仍可证明归属、由下次安装补完。只有 ENOENT/ENOTDIR 算不存在，其他 lstat 错误按无法确认处理，绝不据此宣告卸载。卸载先把已验证目录 rename 出 `plugins/`、复验后再删；移走失败报 error 并保留安装意图，移走成功但删除失败时按已移除提交并在 warnings 里给出残留 `.clawd-minimax-removing-*` 路径，复验失败且移回失败时两个位置都报 `registrationRemoved:null` 并带 `residualPaths`；删不掉且目录仍运行 Clawd hook 时返回 `registrationRemoved:false`（读不清为 `null`），Settings / About 据此保留安装意图。删除后返回前还会复查一次原位置：此时若已有另一个 Clawd 实例重新发布的插件，报“仍在注册”（`registrationRemoved:false`）、不宣称卸载；这次复查是快照，复查之后、Settings 提交之前的安装不在本次结果里（多实例强一致需要覆盖 prefs 提交的跨进程锁，未做）。Settings 界面目前不显示成功结果里的 `warnings` / `residualPaths`：Agents 页安装/卸载只弹“已卸载/已安装”，About 清理只显示计数，只有命令行 cleanup 脚本会打印 warning。进程中途崩溃，或 staging 清理本身失败，可能在数据目录留下 `.clawd-minimax-staging-*` / `.clawd-minimax-removing-*`（MiniMax 不会加载，只能手动删除）；`plugins/` 与数据目录跨文件系统（EXDEV）时不支持。判断外来目录是否仍跑 Clawd hook 按 manifest 声明的 hooks 文档和 MiniMax 默认规则检查（含裸文档外壳、反斜杠路径，以及 shell 形式的 command / commandWindows handler）；Clawd 不建模的 manifest（根 `plugin.json` / `.minimax-plugin/` / `.codex-plugin/`）或读不清时按无法确认处理。node 探测失败时只保留全部 Clawd handler 一致、basename 为 node、存在且可执行、并通过 `node --version` 有界探测的已记录路径（exec-form 无 shell，Dock 启动的桌面 App 的 PATH 里没有 node），安装器与 Doctor 共用 `resolveDesiredNodeBin`。PostCompact 按 #406 上报 thinking（`trigger:\"manual\"` 时 idle），不是 attention。hook 的 `agentNames` 必须全小写（resolver 比较的是小写 basename），且不含桌面版的 “MiniMax Code Helper”：拉起 hook 的 NodeService helper 可能在 App 运行中重启，把它当 agent 会误删活会话，识别应落到长驻的主程序；mcode CLI 启动时执行 `process.title = \"minimax-code\"`，macOS/Linux 上 `ps` 报告的进程名就是 `minimax-code`（按名字匹配），Windows 上仍是 node.exe，靠 `agentCmdlineCheck` 只看 argv 里的脚本位置识别（命令行检查的进程名沿用共享默认 `DEFAULT_AGENT_CMDLINE_NAMES`，已含 Linux 上新版 Node 的主线程名 `mainthread` / `node-mainthread`，MiniMax 不再自带名单）（`node` 后的脚本 basename 是 `mcode`/`minimax-code` 启动器，或脚本路径含 `/@minimax-ai/code/` / `/.minimax-code/`），参数里的目录片段不算——MiniMax 退出时不发 SessionEnd，没有 agent pid 会话就无法按 agent-exit 清理。hook 不触发时的启用步骤在 MiniMax 应用内（`mcode plugin enable clawd-state@local` 或插件面板），磁盘上读不到启用状态，Doctor/Settings 只能提示。session id 命名空间 `minimax:<raw>`，标题走首行 prompt 派生 + 服务端 first-wins（同 traecode）。\n- Kimi Code（agent id `kimi-cli`）的 agent pid 靠进程名识别：CLI 启动即 `process.title = \"kimi-code\"`，libuv 把标题写回原 argv 所占的空间、放不下就截断，所以 macOS/Linux 上 `ps` 与 `pgrep -x` 看到的名字随启动命令长短而变（0.42.0 原生版实测：`kimi` 仍是 `kimi`，`kimi -c` 是 `kimi-co`，`kimi --yolo` 或全路径启动是 `kimi-code`；只有整条启动命令比 `kimi` 还短时（例如不带参数的软链接 `k`）才认不出，`k -c` 显示的已经是 `kimi`）。`hooks/kimi-process-names.js` 必须列全从 `kimi` 到 `kimi-code` 的每一种截断，resolver 与 startup recovery 共用这一组，只写 `kimi-code` 会漏掉 `kimi -c`。拉起 hook 的就是这个改名后的主进程（TUI 在进程内跑 agent 引擎，从 SessionStart 到 SessionEnd 同一个 PID）；其他同名进程（后台更新下载器、经 kimi 二进制跑的插件进程等）都是它的子进程，不跑 hook。resolver 比较小写 basename，macOS 桌面版 `Kimi Code.app` 写成 `kimi code`（它的 agent server 跑在主进程里，hook 由主进程直接拉起）；桌面版关窗后常驻托盘、不代表在干活，同其他桌面 App 一样不进 startup recovery。Windows 上标题只改控制台标题：原生版仍是 `kimi.exe`，npm 版仍是 `node.exe`，命令行检查只认包目录 `/@moonshot-ai/kimi-code/`，不能退回“含 kimi 就算”（Kimi 本身没被认出时，任何命令行提到 kimi 的 node 祖先都会被当成 agent）。Kimi Code 正常 `/exit` 会发 SessionEnd，但关终端、`kill`（0.42.0 实测：SIGTERM 与 SIGKILL 都不发；源码里 SIGTERM 注册了 `stop(143)`，实测为什么没发 SessionEnd 还没查清）、崩溃都不发；没有 agent pid 的会话只要终端 App 还开着就一直留在列表里。桌面端启动时会恢复上次查看的对话、在侧栏点开旧对话也一样，这类只发一条 SessionStart、还没有任何动作的对话不进 Session HUD，Dashboard 照常列出、按钮照常可跳，出现提问/工具/审批/Stop 等动作后自动进 HUD（与 DSH 共用同一个 `awaitingActivity` 标记）。\n- HTTP 服务端口范围固定为 `127.0.0.1:23333-23337`；运行时端口写入 `~/.clawd/runtime.json`\n- Mobile Preview 是独立的 LAN listener，候选范围为 `0.0.0.0:23334-23338`；它不写 `runtime.json`，不得把该范围误写成 hook / custom-agent HTTP ingress 范围\n- 自定义 HTTP Agent 的 sender 必须读取 `~/.clawd/runtime.json`，不能把 23333 写死；注册不等于已连接。custom v1 只支持 `/state`，不支持 `/permission`\n- CodeBuddy PermissionRequest hook 的所有权只认本机 managed URL 或 marker `clawd-on-desk.permission.v1`；纯 `name:\"clawd\"` 不能触发改写/删除。裸 CLI 和 WSL 默认 preserve，Settings/startup/repair 必须显式传 local/custom permission target\n- Remote SSH 的远端 Node 探测要求 Node >= 14；Node discovery/version validation 只在 `src/remote-ssh-node.js`，ordinary tunnel health 与 serialized readiness 在 `src/remote-ssh-runtime.js`，不得互相复制或从已停用脚本另起实现\n- 注册 Claude Code hook 必须 marker-scoped merge：只可更新/删除含 `clawd-hook.js` / `auto-start.js` marker 的 Clawd-owned entry，不得整体覆盖数组或改动无 marker 的用户 entry\n- 注册 Claude Code statusLine 默认只接管空槽或自己的槽（marker `claude-statusline.js`）；本机 Settings 显式开启采集遇到第三方槽时，必须经共存确认并复核原槽指纹，使用 `--local-chain` 和独立的 `clawd-statusline-local-chain.json` 保存/恢复完整原对象。启动/自动修复不得自行取得第三方槽；恢复记录缺失、损坏或不匹配时 fail closed 并保留现场。远程部署仍用 profile 的 `chainStatusline` opt-in 和既有 `--chain` sidecar，不与本机记录混用。订阅配额通过 `metadata_only` POST 进入 session-independent `updateAccountQuota` per-source store；不要把 quota 塞进 `updateSession` opts，也不要以 session 存活作为摄入前提\n- Copilot CLI hooks 走按需自动同步：`hooks/copilot-install.js` 在本地启动仅当 Copilot CLI 已安装且已启用时调用；远端由 Settings Remote SSH deploy controller 调用。路径解析尊重 `COPILOT_HOME` env（trimmed 非空才生效，否则 fallback 到 `~/.copilot`）；`hooks/copilot-hook.js` 的 session-state resolver 同样走 env\n- Remote SSH 的 effective transport 由 `ssh -G` 只读检查决定：ordinary SSH 在没有 retained serialized occupancy 时保持 `context:null` 的 parallel 路径；serialized transport 以有效 target key（不是 profile id）互斥。所有 serialized managed SSH/SCP child 必须持 coordinator 发出的有效 connection/operation context，并通过其 pre-spawn gateway 启动；用户交互终端只有命中 serialized/retained occupancy 时才要求 coordinator 判定 target 完全 idle\n- serialized persistent tunnel 使用同一条 SSH 内嵌 readiness；暂停通过 stdin EOF 请求自然退出并等待 `close`。强杀或带 signal 的 outer `ssh.exe` close 不能证明 nested ProxyCommand 已 drain；timeout/未验证 drain 必须 quarantine，期间禁止新 child、mutation、resume 或 interactive terminal\n- mutation 在 deploy-lock acquire-attempted / lock-owned 后遇到 exit 255、EOF/reset、signal 或其他 unknown result 时不得自动 replay、retry、release lock 或恢复连接；必须保留 primary error 并传播 recovery state，必要时要求 `manual_lock_inspection_required`\n- Remote SSH secure hook 必须同时携带 `CLAWD_REMOTE=1` 与 `CLAWD_SSH_REMOTE=1`，只读 layout identity 并 pin 精确端口；identity 缺失/损坏/不可读必须 fail closed，禁止回退端口扫描\n- Remote SSH deploy-lock acquisition 必须原子化；成功 acquire 后的每个 live mutation 都要在同一远端命令内 fencing 校验，cleanup 还必须锁内重读 installId/profileId/runtimeKey/layoutVersion 所有权。无身份、冲突、ownerless/corrupt lock 均不得自动接管\n- 默认 `account-default` 只支持不同 Unix 账号；同 Unix 账号冲突必须阻止。`profile-isolated` 在真实 SSH/CLI 矩阵完成前由 `CLAWD_ENABLE_EXPERIMENTAL_REMOTE_ISOLATION=1` 发布门隐藏；它只隔离用户级 CLI config/session/runtime 与 Clawd 路由，不代表完整 HOME 或同 UID 安全隔离，project 配置/部分 cache/macOS Claude Keychain auth 仍可能共享\n- Hermes Agent 的 Remote SSH 部署是 `secureDeploy` 内的 `hermes-files` → `install-hermes` 两个阶段，复用同一条 serialized transport、deploy lease、fencing 与所有权检查，没有独立的 Hermes SSH deployer：secure 模式由每个托管 `plugins/clawd-on-desk/` 内的 plugin-local marker `clawd-ssh-secure-v1` latch，latch 后 identity 必须在每次 state/probe/permission 请求时重新读取（禁止 `(mtime,size)` 缓存），且不得发送任何远端 PID / 进程树 metadata；plugin 资产走独立 staging 目录，清理只 `rm -f` 精确文件再 `rmdir`，禁止 `rm -rf`；`REMOTE_IDENTITY_STEP_NAMES` 保持冻结的 8 步不变，不得加入 `installHermes`；Clawd 绝不自动重启 Hermes gateway，托管模块被替换时只报告需要手动重启\n- 禁用 agent 不应卸载 hooks / plugins / extensions：只停止对应 monitor、清理 session / bubble、让 HTTP hook 入口快速 fallback；重新启用未安装 agent 不触发本机 integration sync。卸载集成必须走 Settings Agent 页的 Uninstall / 对应 uninstall 命令，并同时清掉 `integrationInstalled`\n- Kiro 的 `sessionId=\"default\"` 会复用；session alias key 必须按 cwd scope 区分，同时保留旧 `local|kiro-cli|default` 只读 fallback\n- Windows NSIS release 必须产出明确架构的 x64 / ARM64 安装包：`win.artifactName` 保留 `${arch}`，`nsis.buildUniversalInstaller` 保持 `false`\n- 每个 release target 只能保留一个匹配目标架构的 Koffi `koffi.node`；`afterPack` 只允许剪裁 `app.asar.unpacked` 的物理文件，禁止重写 `app.asar`，并必须通过完整 native inventory audit（唯一常设例外是 electron-builder 管理的 Windows ia32 `resources/elevate.exe`）\n- 资源路径统一用 `path.join(__dirname, ...)`\n- 需要编辑发布素材时，先复制到 `assets/source/` 再改，不要直接改工作素材来源不明的文件\n- `assets/source/cloudling-pointer-bridge/` 是 Cloudling 指针桥素材的保留源文件目录；运行时逻辑已内联进主题 SVG，不要把这个 source 目录当临时文件清理\n- 主题状态、sleep/DND、mini mode、状态映射的细节在 `docs/project/theme-state-ui.md`\n- 官方可下载主题（`official-theme-*`）是受管分发层，不是 built-in、也不提升信任：catalog 是固定远端小目录（renderer 只能传 themeId），下载走 Electron main `net.request` 的 manual redirect + 精确 CDN host allowlist + 固定 bytes/SHA-256（未支持 host 返回稳定 `DOWNLOAD_HOST_UNSUPPORTED`，不允许 catalog 扩展 allowlist），ZIP 只在 manager 专属 staging 内流式解压并以 marker-before-rename 同卷提交，最终以 `isBuiltin=false` 加载（`trustedRuntime` 无效）。`setThemeSelection` / `removeTheme` / `officialTheme.commitInstall` / `officialTheme.uninstall` / `theme` update 共用 `lockKey=\"theme\"`；卸载 active 主题必须等 `waitForThemeReloadSettled()`。主仓库附带一份目录快照 `src/official-theme-catalog-snapshot.json`：网络拉取失败时列表先用上一次成功加载的目录（内存 LKG 或磁盘缓存），都没有才用快照；第一次拉取有结果之前（`uninitialized`）不用快照；快照**不作安装依据**，安装仍只认经校验的网络/磁盘目录。快照只作列表回落（仍显示 `offline` 和重试），不含素材与预览图，不写磁盘缓存，且参与版本不能回退的比较；发布前用 `npm run update:official-theme-snapshot` 刷新。不要把 Hash Sage / Whale-chan 的动画素材（APNG / WebP），或把它们写成内置主题的文案带回主仓库\n- Settings 体系里，store 是唯一真相，controller 是唯一写入者；不要绕开 `settings-controller.js`\n- Dashboard 数字快选是**完整 Dashboard 同一页面的临时键盘模式，仅 macOS/Windows**；Linux 明确 NOT SUPPORTED（不是待验证）。平台 gate 的唯一真相是 `shortcut-actions.js` 的 `supportedPlatforms` + `isShortcutActionSupported()`，Settings 展示、globalShortcut 注册/录制、设置命令和冲突占用都必须服从它；遗留的不支持绑定只忽略执行，不删用户 prefs、不占其他快捷键。darwin/win32 的 Dashboard 页面活在 `WebContentsView` 里，`BrowserWindow.fromWebContents()` 对它返回 null、BaseWindow 不触发 `ready-to-show`；页面 WC 一律从 owner 取。禁止用 `hide()`+`showInactive()` 归还已显示的普通宿主（实测会遮挡来源窗口），只能 opacity/input parking 并幂等恢复捕获值。详见 `docs/project/theme-state-ui.md`\n\n## Testing\n\n- 自动化测试使用 Node 内置 test runner：`npm test`\n- `test/*.test.js` 覆盖核心 unit/contract、installer、route、UI/runtime 与 Remote SSH transport/coordinator/identity；部分 fixture 会启动 Node、shell 或 Git Bash 子进程，缺少依赖时可能 skip，不能把全套结果概括成纯逻辑或等价真机验证\n- Remote SSH 真机矩阵与记录在 `scripts/manual/README.md`；Windows OpenSSH + Codespaces stdio 边界及 ordinary-host V15 release gate 不能从 unit tests 互相推断，无法执行时必须明确记录 pending / residual risk\n- Windows Terminal 真机、GUI smoke 与清理必须假定多个 tab/window 共享进程：不得按 PID/进程名 `taskkill`、`Stop-Process` 或宽泛终止 WindowsTerminal、Codex、`cmd.exe`、`ssh.exe`、OpenConsole、conhost。测试终端只能在明确 test-owned session 内 `exit`；无法证明 ownership 就保留现场并请用户手动关闭\n- 当前开发环境是 Windows-first；macOS 特定路径无法在这里手动 QA，改到 mac 逻辑时要用 code-review","CLAUDE.md":"# AGENTS.md\n\nThis file is the entry point for coding agents working in this repository. Keep it short and operational. Durable architecture lives in `docs/project/`; `docs/plans/` and `docs/investigations/` are historical evidence unless this file explicitly links them.\n\n## Project Overview\n\nClawd 是一个 Electron 桌宠：通过 hook、日志轮询、plugin 和 extension 感知 AI coding agent 的工作状态，并播放像素风动画。当前支持 Claude Code、Codex CLI、Copilot CLI、Gemini CLI、Antigravity CLI (agy)、Cursor Agent、CodeBuddy、WorkBuddy、Grok Build、Kiro CLI、KiroCrew、Kimi Code CLI (Kimi-CLI)、Qwen Code、ZCode、CodeWhale、opencode、MiMo Code、Pi、OMP (oh-my-pi)、OpenClaw、Hermes Agent、Qoder、QoderWork、QwenWork (千问办公)、Reasonix、DeepSeek Harness、TraeCode (Trae CN)、MiniMax Code；内置 Clawd / Calico / Cloudling 三套主题，支持用户主题，并可经 Settings 从独立 `rullerzhou-afk/clawd-themes` 仓库下载可选官方主题（Hash Sage、Whale-chan，external theme 权限、可卸载）；平台覆盖 Windows、macOS、Linux，UI 支持 en / zh / zh-TW / ko / ja / pt-BR / es。\n\n## Common Commands\n\n```bash\nnpm start\nnpm run build                  # default Windows package\nnpm run build:win:x64\nnpm run build:win:arm64\nnpm run build:win:all\nnpm run build:mac\nnpm run build:linux\nnpm run build:all\nnpm install\nnpm test\nnpm run verify:electron\nnpm run verify:release\nnpm run audit:assets\nnpm run audit:pr-history-assets\nnpm run audit:native-package -- --app-root <extracted-app-root> --target <target-id>\nnpm run create-theme\n\nnpm run install:claude-hooks\nnpm run uninstall:claude-hooks\nnpm run install:cursor-hooks\nnpm run install:gemini-hooks\nnpm run install:antigravity-hooks\nnpm run install:kiro-hooks\nnpm run install:kirocrew-hooks\nnpm run uninstall:kirocrew-hooks\nnpm run install:kimi-hooks\nnpm run install:qwen-hooks\nnpm run install:zcode-hooks\nnpm run uninstall:zcode-hooks\nnpm run install:codewhale-hooks\nnpm run uninstall:codewhale-hooks\nnpm run install:pi-extension\nnpm run uninstall:pi-extension\nnpm run install:omp-extension\nnpm run uninstall:omp-extension\nnpm run install:openclaw-plugin\nnpm run uninstall:openclaw-plugin\nnpm run install:hermes-plugin\nnpm run uninstall:hermes-plugin\nnpm run install:qoder-hooks\nnpm run uninstall:qoder-hooks\nnpm run install:qoderwork-hooks\nnpm run uninstall:qoderwork-hooks\nnpm run install:qwenwork-hooks\nnpm run uninstall:qwenwork-hooks\nnpm run install:reasonix-hooks\nnpm run uninstall:reasonix-hooks\nnpm run install:workbuddy-hooks\nnpm run uninstall:workbuddy-hooks\nnpm run install:grok-hooks\nnpm run uninstall:grok-hooks\nnpm run install:dsh\nnpm run uninstall:dsh\nnpm run install:codex-hooks\nnpm run uninstall:codex-hooks\nnpm run install:codex-debug-hooks\nnpm run uninstall:codex-debug-hooks\nnpm run install:mimocode-plugin\nnpm run uninstall:mimocode-plugin\nnode hooks/codebuddy-install.js\nnode hooks/opencode-install.js\n\nbash test-demo.sh [seconds]\nbash test-mini.sh [seconds]\nbash test-macos.sh\nbash test-oneshot-gate.sh [state] [seconds]\n```\n\n新安装默认只把 Claude Code 和 Codex 标记为已安装并启用；其他 agent 默认未安装、未启用。正常启动时，Clawd 只会为 `integrationInstalled=true` 且 `enabled=true` 的 agent 自动同步 Claude / Codex / Copilot / Gemini / Antigravity / Cursor / CodeBuddy / WorkBuddy / Grok Build / Kiro / KiroCrew / Kimi / Qwen / ZCode / CodeWhale / Qoder / QoderWork / QwenWork / Reasonix / TraeCode / MiniMax Code hooks、opencode / MiMo Code / OpenClaw / Hermes plugins 和 Pi / OMP extensions。Settings Agent 页的 Install 会安装并启用该集成；Uninstall 会卸载 Clawd 管理的 hook/plugin/extension，并同时把该 agent 设为未安装、未启用。单独关闭 enabled 只会跳过启动同步并屏蔽事件/权限入口，不卸载用户已有 hooks / plugins / extensions；重新启用未安装 agent 只打开事件入口，不会写本机集成文件。手动安装命令主要用于调试、重装或远程部署。\nSettings 注册的自定义 HTTP Agent 是独立模型：`customApplications` 是注册真相，对应 `agents[customId]` 必须显式保持 `integrationInstalled=false`。注册只分配 ID 和状态入口，不安装 hook、不观察进程；v1 仅允许已注册且启用的 ID 向 `/state` 上报，`/permission` 永远不提供决定。删除或伪造的 `custom-` ID 必须直接拒绝，不能降级成 Claude Code subagent。\nCopilot CLI 同步走 `<COPILOT_HOME 或 ~/.copilot>/hooks/hooks.json`，marker-based 增量合并只接管含 `copilot-hook.js` 标记的条目，用户其他 entry / 其他 `hooks/*.json` 文件原样保留；hooks.json 或 `settings.json` 顶层 `disableAllHooks: true` 时 doctor 报 warning（不挂 Fix 按钮）。详见 `docs/guides/copilot-setup.md`。\n\n## Read These Docs\n\n- `docs/project/agent-runtime-architecture.md`：运行时架构、模块边界、启动与数据流、多 agent、permission bubble、终端聚焦和自动同步\n- `docs/project/theme-state-ui.md`：状态机、主题系统、settings、mini mode、素材规则、平台限制、待落地 UI 决策\n- `docs/project/release-process.md`：发版 checklist、release note 核对、tag 触发 GitHub 打包和资产确认\n- `docs/guides/copilot-setup.md`：Copilot CLI 自动同步说明、`COPILOT_HOME` 兼容性、手动配置备选模板\n- `docs/guides/dsh-setup.md`：DeepSeek Harness web profile 与桌面版的实验性 plugin 集成状态与普通审批集成\n- `docs/guides/state-mapping.md`：状态 → 动画权威表\n- `docs/guides/guide-theme-creation.md`：主题作者指南\n- `docs/guides/setup-guide.md`：安装、远程 SSH、各 agent 接入\n- `docs/guides/custom-agent-http.md`：自定义 HTTP Agent 的 state-only 接入合约和动态端口发现\n- `docs/guides/known-limitations.md`：用户向已知限制\n- `docs/guides/recap.md`：本地小结的指标口径、coverage、时区/DST、隐私存储与产品红线\n- `docs/guides/codex-wsl-clarification.md`：Codex / WSL 路径与 Node 说明\n- `docs/guides/guide-remote-ssh.md`：Remote SSH 用户流程、Codespaces 单会话 transport 与共享主机边界\n- `docs/guides/telegram-approval.md` / `docs/guides/feishu-lark-remote-approval.md`：远程审批设置与失败回退语义\n- `docs/guides/roam-fence.md`：自由漫游与可选围栏\n\n## Runtime Summary\n\n- HTTP hook / plugin 主路径：`src/server.js` → `src/server-route-state.js` → `src/agent-runtime-main.js` → `src/state.js` → IPC；本地 JSONL monitor 直接进入 `agent-runtime-main`，不经过 HTTP server\n- 权限主路径：`src/server-route-permission.js` → `src/permission.js`；本地 bubble、显式 permission automation 与可选 Telegram / 飞书 Lark 远程审批都可能产生真实决定\n- 桌宠的渲染/输入双窗口由 `src/pet-window-runtime.js` 统一创建和定位；浮层排序与 topmost 行为在 `src/floating-window-runtime.js` / `src/topmost-runtime.js`\n- `src/state.js` 生成的 session snapshot 是 Dashboard、HUD/Orbit 与可选通知/presence/mobile consumer 的共享合约，改字段必须检查所有消费者\n- `src/integration-sync.js` 为已安装且启用的 agent 异步同步 hooks / plugins / extensions；Codex official hooks 为 primary，JSONL 轮询保留为 fallback\n- Claude hook 恢复由 `src/claude-settings-watcher.js` 的目录 watcher + 低频只读巡检共同负责；repair 统一经过 `src/claude-hook-operations.js` 队列并复验，连续失败转 `manual-fix-required`。完整 gate、阈值与 source-missing 语义见 `docs/project/agent-runtime-architecture.md`\n- `src/agent-gate.js` 控制各 agent 的安装意图、启用状态、权限气泡开关和 wait-for-input notification 子开关\n- 设置系统主链路是 `src/prefs.js` → `src/settings-controller.js`（唯一写入者）→ `src/settings-store.js`；`settings-actions*` 负责校验和 pre-commit gates，`settings-effect-router.js` 负责 post-commit runtime effects 与广播\n- 启动时还会尝试自动安装 VS Code / Cursor terminal-focus extension，并初始化 updater\n- Remote SSH 通过 effective transport inspection 区分 ordinary parallel SSH 与 serialized transport；后者由 target-scoped coordinator 编排。远程部署只走 Settings，`scripts/remote-deploy.sh` 已 fail-fast 停用\n\n## Core Files\n\n更细的背景见 `docs/project/agent-runtime-architecture.md` 和 `docs/project/theme-state-ui.md`。\n\n| File | Responsibility |\n|------|------|\n| `src/main.js` | Electron composition root：生命周期、上下文组装与各 runtime / IPC 注册器接线 |\n| `src/server.js` + `src/server-route-state.js` + `src/server-route-permission.js` | HTTP 服务、端口发现、`/state` / `/permission` 路由 |\n| `src/agent-runtime-main.js` + `src/integration-sync.js` | local monitor / official hook 仲裁、Codex turn fence、按 gate 的集成同步 |\n| `src/state.js` | 状态机、多会话合并、优先级、自动回退、睡眠/DND |\n| `src/renderer.js` | 动画切换、SVG 预加载、眼球追踪渲染 |\n| `src/permission.js` + `src/permission-automation-policy.js` + `src/session-automation-coordinator.js` | 权限气泡、自动化策略、per-session 授权与决策回包；远程 client 由 `main.js` 注入 |\n| `src/pet-window-runtime.js` + `src/floating-window-runtime.js` + `src/topmost-runtime.js` | 双窗口 owner、浮层重排、z-order / fullscreen / focusability |\n| `src/update-bubble.js` | 更新气泡创建、测高、跟随桌宠定位，避让 HUD / permission stack |\n| `src/dashboard.js` + `src/dashboard-renderer.js` | Sessions Dashboard 唯一 owner：会话列表、别名编辑、终端跳转、几何持久化，以及同一页面的临时键盘模式 |\n| `src/dashboard-host.js` | Dashboard 普通宿主的平台封装：darwin/win32 用 `BaseWindow + WebContentsView`（无 `ready-to-show`），Linux 保留 `BrowserWindow` |\n| `src/dashboard-quick-mode.js` | 完整 Dashboard 的 1–9 键盘模式（**macOS/Windows only**）：quick 宿主、opacity/input parking、轮次栅栏与冻结数字映射；Windows 显式取消与页面失效的来源恢复在 `src/quick-select-origin-focus.js`，quick 宿主的退出清理挂在 `before-quit` |\n| `src/session-hud.js` + `src/session-hud-renderer.js` | 桌宠旁轻量会话 HUD、折叠行、点击跳转 |\n| `src/session-alias.js` | session alias key 规范化、TTL pruning、Kiro cwd scope |\n| `src/theme-loader.js` + `src/theme-runtime.js` | stateless 主题加载/消毒与唯一 active-theme owner；`waitForThemeReloadSettled` 完成信号 |\n| `src/official-theme-catalog.js` / `-download.js` / `-installer.js` / `-main.js` | 官方可下载主题：严格 catalog/cache、Electron `net.request` 流式下载、受限流式 ZIP 解压与 marker-before-rename、main owner/IPC/共享 `theme` lock |\n| `src/prefs.js` | 偏好 schema、load/save/migrate/validate，设置持久化入口 |\n| `src/settings-actions*.js` + `src/settings-effect-router.js` | 设置 validators / commands / pre-commit gates 与 post-commit runtime effects |\n| `src/settings-controller.js` | 设置系统唯一写入者 |\n| `src/settings-store.js` | 不可变 snapshot store |\n| `src/settings-ui-core.js` + `src/settings-renderer.js` + `src/settings-tab-*.js` | Settings shared UI state、侧栏/tab shell 与各页逻辑 |\n| `src/menu.js` | 托盘 / 右键菜单，串起设置、Dashboard、mini mode、更新入口 |\n| `src/mini.js` | 极简模式入场、滑动、peek、状态映射 |\n| `src/tick.js` | 主循环、鼠标轮询、眼球和 idle/sleep 逻辑 |\n| `src/drag-position.js` | 拖拽落点规范化与跨显示器钳制 |\n| `src/visible-margins.js` | 可视角色边距与 edge pinning 规则 |\n| `src/updater.js` | Git 模式 / `electron-updater` 双路径更新逻辑 |\n| `src/focus.js` | 终端聚焦 |\n| `src/hit-renderer.js` + `src/hit-geometry.js` | 输入窗口命中、拖拽、连击反应 |\n| `src/remote-ssh-runtime.js` | Remote SSH tunnel/ingress 状态机、ordinary health probe、serialized readiness 与重连 |\n| `src/remote-ssh-transport.js` + `src/remote-ssh-transport-coordinator.js` | effective transport inspection、pre-spawn admission、target ownership、drain barrier 与 quarantine |\n| `src/remote-ssh-deploy.js` | Deploy / Repair、身份事务、lease/fencing、wrapper、cleanup 与远端 Codex monitor mutation |\n| `src/remote-ssh-identity.js` + `src/remote-ssh-layout.js` + `src/remote-ssh-ingress.js` | 身份/布局真相与 profile 专属、nonce 校验的本地 ingress |\n| `src/remote-ssh-node.js` + `src/remote-ssh-shell-detect.js` + `src/remote-ssh-local-config.js` | 远端 Node/ shell 探测与本机 SSH config 入口 |\n| `src/remote-ssh-profile.js` | Remote SSH profile schema、校验、默认值和持久化规范化 |\n| `src/remote-ssh-ipc.js` | Remote SSH runtime / deploy / monitor orchestration、intent policy、IPC 状态与进度广播 |\n| `src/remote-ssh-quote.js` | Remote SSH 终端命令与跨平台 shell quoting helper |\n| `agents/registry.js` | agent 注册表 |\n| `agents/codex-log-monitor.js` | Codex JSONL fallback 轮询 |\n| `agents/gemini-log-monitor.js` | legacy Gemini session JSON 轮询器；当前 Gemini hook-only 路径不启动 |\n| `hooks/dsh-install.js` | DeepSeek Harness immutable managed bridge generation、ownership verify、web 与 desktop 两个 profile 的安装 / 修复 / 卸载编排 |\n| `hooks/kirocrew-install.js` + `hooks/kirocrew-store.js` | KiroCrew state-only gateway hooks、upstream-compatible mutation locks and atomic private store writes |\n| `hooks/kirocrew-hook.js` + `hooks/kirocrew-command.js` | KiroCrew state bridge and exact command-shape ownership classifier |\n| `hooks/dsh-notices.js` | DeepSeek Harness 常驻提示的存储与规则（按 profile 的 `notices-<profile>.json`） |\n| `hooks/clawd-hook.js` + `hooks/copilot-hook.js` | Claude Code / Copilot CLI 状态上报脚本 |\n| `hooks/install.js` | Claude hook 注册 / 卸载 |\n| `hooks/auto-start.js` | Claude `SessionStart` 自动拉起 Clawd 的 hook |\n| `hooks/codex-hook.js` / `hooks/codex-install.js` | Codex official hooks 状态与权限审批、安装 / 卸载 |\n| `hooks/cursor-install.js` / `gemini-install.js` / `antigravity-install.js` / `kiro-install.js` / `kimi-install.js` / `qwen-code-install.js` / `codewhale-install.js` / `codebuddy-install.js` / `workbuddy-install.js` / `opencode-install.js` / `pi-install.js` / `openclaw-install.js` / `hermes-install.js` / `qoder-install.js` / `qoderwork-install.js` / `reasonix-install.js` | 各 agent 集成安装逻辑 |\n| `hooks/opencode-family-managed-generation.js` | OpenCode 用户可写托管 generation（canonicalizer、bundle/manifest、stage/promote、target owner record、target-scoped lock）；纯 Node 内置依赖，不进入 Remote SSH `HOOK_FILES` |\n| `hooks/opencode-family-entry-ownership.js` | OpenCode-family plugin entry 的 string/tuple 解析、跨平台路径等价、所有权分类与重复/options 冲突规划（纯逻辑、可注入 fs） |\n| `hooks/opencode-family-install.js` / `hooks/opencode-family-jsonc.js` | 家族注册器：`managedMaterialization:true` 走托管 generation 事务 + 共享 entry planner；`false` 保持 legacy broad-basename register/unregister |\n| `src/doctor-detectors/opencode-managed-inspector.js` | managed OpenCode Doctor inspector（ownership/manifest/生成结构、Fix policy、masked supplementary warning）；接受注入 fs |\n| `hooks/workbuddy-hook.js` | WorkBuddy state + Notification command hook；无 session_id 时返回合法 stdout 后丢弃事件 |\n| `hooks/grok-hook.js` / `hooks/grok-install.js` | Grok Build state + Notification command hook；写入 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json`；`env` marker `CLAWD_GROK_HOOK=v1` 所有权；无 session id 时丢弃；不注册 `/permission` |\n| `hooks/zcode-hook.js` / `hooks/zcode-install.js` | ZCode 状态 + 阻塞式 PermissionRequest hooks（`hookSpecificOutput` 决定 / `{}` 无决定）、`hooks.events.*` 按事件超时增量注册与 Claude-imported Clawd hook 清理 |\n| `hooks/qoder-hook.js` | Qoder state-only 状态上报脚本（Phase 1，stdout 恒为 `{}`） |\n| `hooks/minimax-hook.js` / `hooks/minimax-install.js` | MiniMax Code state-only 本地插件：整目录 install/uninstall（`<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/`），CLAUDE 格式 hooks + exec-form args，10 事件无 PermissionRequest/Notification，`.clawd-managed.json` 结构化所有权凭据、fail closed |\n| `hooks/codex-remote-monitor.js` | 远程 Codex JSONL 轮询并通过 SSH 隧道回传（含 token_count 订阅配额的 metadata_only 上报） |\n| `hooks/claude-statusline.js` / `hooks/antigravity-statusline.js` | 各 CLI statusline 适配器：渲染状态行 + 把订阅配额（rate_limits）以 metadata_only POST 上报；Claude 版支持远程部署（`CLAWD_REMOTE=1` 前缀）与 `--chain` 串联模式（原 statusLine 对象保存在 `~/.claude/hooks/clawd-statusline-chain.json`，卸载时恢复） |\n| `extensions/vscode/extension.js` | VS Code / Cursor 终端 tab 聚焦辅助扩展 |\n\n## Constraints\n\n- `agents/registry.js` 的 capabilities 是权限、subagent、session-end 等路由/gate 的权威来源；不得另写名单代替 capability 判定。但 permission automation eligibility 由更窄的 `isKnownPermissionAgent()` 显式判定（`KNOWN_PERMISSION_AGENTS` + explicit opencode-family membership），不得从 `permissionApproval` 自动派生或合并回 registry capabilities\n- 小结的指标能力例外地只认 `src/recap-metrics.js` 的显式逐 Agent 口径，不得从 registry capabilities 或标准化 event 名推导。只统计已通过 gate、Codex source/replay fence、subagent 与完成仲裁的 accepted activity；DND 继续记录且不切 coverage，suspend/退出/关闭记录才切。`null` 是不支持，绝不能渲染或汇总成 `0`\n- 小结持久层固定为 `~/.clawd/recap-v1/` 下 14 个本地日的最小 HMAC 小票与 400 个本地日的 daily/coverage；不得落 prompt/回复/命令/工具内容、路径/项目、原始 event/session/profile/turn/tool ID，不得增加网络、导出或分享。首版不做 Token、金额、模型、推理强度、Skill、人的工作/编码时长、streak、峰值/最长项、排行榜或生产力评分\n- Claude Code / CodeBuddy 的阻塞式权限审批走 `POST /permission` HTTP hook；普通状态事件走 command hook（CodeBuddy command hook 对所有事件输出 `{}`，不做工具或权限决定）\n- permission automation（off / auto-tools / unattended）和 per-session grant 会在 bubble 渲染前产生真实 allow/answer。agent/family eligibility 是显式白名单；工具分类则因 mode/adapter 而异：auto-tools 对 Claude/Qwen 的未知 built-in fail closed，但其他已知 adapter 不都使用逐工具白名单，unattended 还会有意自动放行可作 Allow/Deny 的未知请求。新增 agent、工具或交互类型必须审查 policy + tests，不能从 `permissionApproval` 推导资格或笼统假设“未知请求都会 defer”\n- Telegram / 飞书 Lark 与本地 bubble 是并行决策通道。远程通道超时、断连、未配置或发送失败不得产生远程决定，更不得转成 deny；有本地 bubble 时请求继续 pending，只有 remote-only 且所有可用 client 都无决定时，整体请求才 no-decision 并回到 agent 原生流程\n- WorkBuddy 通过当前 `~/.workbuddy-ai/settings.json`（旧版兼容 `~/.workbuddy/settings.json`）的 Claude Code 兼容 command hooks 做 **state + Notification only** 集成：不注册 `/permission`，审批始终留在 WorkBuddy 原生沙箱与 GUI；无 `session_id` 的事件返回合法 stdout 后直接丢弃。当前只支持 macOS/Windows 桌面应用，没有已验证的 Linux/WSL CLI；不要把裸 `Electron` 当 WorkBuddy 进程。\n- Grok Build（agent id `grok-build`）通过 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json` 的 Claude Code 兼容 command hooks 做 **local / main-session / state + Notification only** 集成（Phase 1）：stdin 为 camelCase（`sessionId` / `toolName`），`hookEventName` 是 camelCase key + snake_case value，`hook_event_name` 是 snake_case key + PascalCase value。**逐 handler 的 `env` 结构化 marker `CLAWD_GROK_HOOK=v1` 是唯一所有权凭据**；文件名/substring（含 `grok-hook.js.backup`）只用于诊断告警，永不授权改写或删除。安装/卸载只增删含该 marker 的 handler，保留 unknown 顶层键、其他 event、foreign matcher group 与 sibling handler；没有 marker 的既有文件一律原样拒绝。`SessionEnd` 不写 `timeout`（继承 Grok 1.5s teardown），其余事件 5s。Windows 用 `windowsWrapper:\"portable\"` 形态，不得用 `&` / `-EncodedCommand` / 自造 `shell` 字段。Grok 没有 `PermissionRequest`，不注册 `/permission`，adapter 始终输出 `{}`。子代理事件（`subagentType`）直接丢弃；不注册 `SubagentStart` / `SubagentStop`。Grok 默认会扫 `~/.claude/settings.json`，所以 `clawd-hook.js` / `cursor-hook.js` / `auto-start.js` 只在非空官方 `GROK_HOOK_EVENT` 下直接退出，`GROK_HOME` / `GROK_SESSION_ID` / 无关 `GROK_*` 不得触发。`Stop` 只有精确 `reason === \"end_turn\"` 且无 background task / session cron / `stopHookActive` 才算完成，其余由 adapter 本地判定；`channel_closed` / `shutdown` 等 session-end 形态的 Stop 在 fence 之前丢弃。turn 顺序由 `src/grok-turn-fence.js` 的 bounded in-memory fence 仲裁（晚到旧 turn、重复 terminal、continuation Stop、Stop→StopCancelled 纠正）。不进入 subagent / WSL / Remote SSH / startup recovery / terminal focus / quota / context / recap turn 指标。`~/.grok/hooks/clawd.json` 是未发布的 PR preview 路径，只做 warning，不得自动接管或删除。\n- Codex 的阻塞式权限审批走 official `PermissionRequest` command hook：hook 脚本长连接 `POST /permission`，只允许 stdout 返回 sanitized `behavior/message`，`updatedInput` / `updatedPermissions` / `interrupt` 必须 omit。权限模式默认 `auto`（旧 `native` 规范化为 `auto`），仅准确本机 session/turn 的人工 reviewer 证据可进 Clawd；未知、自动 reviewer、MCP/app、远程/WSL 均 no-decision；唯一例外是远程/WSL（路由 reason 为 `nonlocal`）的 Bash/apply_patch 在全局自动放行会立即 allow 时（`wouldAutoAllowPermission`：非 reminder hold、非会话覆盖、非交互子代理）由 Clawd 直接放行（#1186），路由后若设置已变则 no-decision，绝不弹气泡。`intercept` 是显式接管；升级时旧 `intercept` / `native` 统一迁到 Auto 一次，之后重新选择的 Intercept 会保留。不得用全局 config、其他会话或旧回合推断当前请求的审批方；证据不足时返回 no-decision，交还 Codex 原生流程。\n- hook 脚本只允许依赖 Node 内置模块，以及同目录 `hooks/` 下、且登记在 `src/remote-ssh-deploy.js` 的 `HOOK_FILES` 部署清单中的纯 Node helper（如 `server-config.js` / `shared-process.js` / `json-utils.js` / `codex-originator.js` / `codex-subagent-fields.js` / `context-usage.js` / `state-payload-size.js` / `quota-bucket.js` / `claude-rate-limits.js` / `codex-rate-limits.js` / `antigravity-context-usage.js`）；manifest-consistency 测试强制检查依赖闭包，新增 helper 必须登记\n- CJS hook 脚本需要稳定终端 PID 时，必须复用 `hooks/shared-process.js` 的 `createPidResolver()` 及其 lifecycle context；不要复制进程树 walk 或用 `process.ppid` 简化。`getStablePid()` 只是 opencode-family plugin 的内部 resolver\n- `agentCmdlineCheck` 只对进程名在 `agentCmdlineNames` 里的祖先进程运行，默认是 `DEFAULT_AGENT_CMDLINE_NAMES`：`node` / `node.exe`，加上 Linux 上没设过 `process.title` 的 Node 在 `ps -o comm=` 里的名字——Node 23.8–25.4（含全部 24.x）把主线程命名为 `MainThread`、≥ 25.5 为 `node-MainThread`，Linux 报的进程名就是主线程名。传入 `agentCmdlineNames` 会整体替换默认值：只想加名字的 adapter 必须在选项里直接写成 `agentCmdlineNames: new Set([..., ...DEFAULT_AGENT_CMDLINE_NAMES])`（如 ZCode；可以跨行，方括号里只能有普通字符串字面量和 `...DEFAULT_AGENT_CMDLINE_NAMES` 本身，不能有注释或其他表达式；简写属性、先存进变量，或任何不是这个形状的提及（包括注释里的）都会被判不合格，因为文本检查无法核对），只有刻意只探测非 Node 宿主的（WorkBuddy 的 `electron`）例外，`test/shared-process.test.js` 会扫描 `hooks/*.js` 检查\n- opencode v1 权限不走 `permission.ask` hook，而是 event hook + reverse bridge；v2 走 `ctx.permission.hook(\"evaluate\")` 的阻塞 HTTP 响应\n- OpenCode / MiMo v1 原生问题走独立本地 `/question` 长轮询，不复用审批回包；遵循全局 permission bubble 开关与 family 单 agent 开关。只接受已核实的 v1 来源、版本和问题 schema，提交前用原 SDK client 复核精确 request/tool/session，答案保持有序 `string[][]`；无决定返回 204 交还原生。OpenCode 由原生 reply RPC 的 `true` / 404 判定提交结果，MiMo 仍需精确 `question.replied` 答案匹配。子会话问题、OpenCode v2、Remote SSH 及未审核 agent 保持原生；不要改 Claude/Hermes wire 或托管 generation 依赖集合。详见 `docs/guides/agent-questions.md`。\n- opencode-family v1 插件经 `ctx.client` 连回宿主时，主机为通配监听地址（`0.0.0.0` / `[::]`）就按次改用 `127.0.0.1` / `[::1]`（不改宿主共享的客户端配置；非通配地址保持原调用形状）。默认 TUI 走进程内 fetch；`opencode serve` / `web` 下这是对监听地址的真实 HTTP 请求，受宿主进程里的 `HTTP_PROXY` / `NO_PROXY` 影响，而通配地址不会自动绕过代理。桥接回复失败返回 `{ok:false,status,error}`（`status` 为上游状态码，缺省 0）。\n- OpenCode 2.x（npm `@opencode/cli`，issue #1039）由 `hooks/opencode-plugin-v2/` + core.mjs 内 `createOpencodeFamilyPluginV2` 承接：installer 在同一 generation 内额外物化 `opencode-plugin-v2/index.mjs`（v1 四文件、v2 五文件；目录 specifier 解析 index.mjs、无需 package.json，2.0.15 实测），并把它写进 **`plugins` 键**，同时清理 Clawd 自有的旧 `plugin` 条目；用户条目、tuple/options 和 v1 行为保持不变。未被 Clawd 纳管的未知 `plugin` 条目仍只报 loader WARN；v1 对未知 `plugins` 键的静默丢弃只在 **1.18.16+** 成立——1.18.15 及更早会以 `Unrecognized key: plugins` 拒绝整个 config（anomalyco/opencode#41312，2026-08-08 起才忽略未知顶层键），因此 `plugins` 写入由宿主探测决定（`hooks/opencode-host-detect.js` 三态：探测到 v2 才写；探测到 v1 不写并清扫 owned 残留；探测失败不碰该键；`CLAWD_OPENCODE_HOST` 环境变量可钉死结论，Doctor 在无 v2 宿主时不要求 v2 条目）。v2 插件是零 import 纯对象 `{id, setup}`（v2 loader 拒绝函数 default export，`@opencode/...` 裸包名无插件本地 node_modules 不可解析），事件经 `ctx.event.subscribe()`（`session.step/tool/execution.*` 词汇完全换代，未知事件一律忽略），cwd 取事件信封 `location.directory`，标题走 `session.renamed`，context usage 走 `session.step.ended` 的 step tokens（`session.usage.updated` 是 session 累计计费值，不能当占用率）。权限走 **`ctx.permission.hook(\"evaluate\")` 阻塞长连接 POST `/permission`**，决定就是 HTTP 响应体 `{decision: allow|always|deny}`（服务端按 `hook_source === \"opencode-plugin-v2\"` 路由到 v2 阻塞子分支），只有 `200` + 身份头 + 合法 JSON 才采纳决定，204/超时/断连/非 200/任何错误都不改 effect 回原生 ask UI；配置 allow 也进 hook 但绝不降级；单条 shell 命令以 `tool_input.resource` 传输，服务端 v2 分支会为其别名出 `command` 以接入破坏性操作提醒（`mapOpencodeV2ShellResource`，非 shell 工具不映射；全字符串的多 resource 以换行合并作扫描别名）；resources 原样整组转发（对象转 JSON 字符串），不做条数/长度截断，唯一边界是整 body 超 512 KiB 时跳过转发。\"Always allow\" 无宿主持久化 API，用插件内 per-session 内存规则（随常驻 service 生命周期，气泡对 v2 使用单独文案说明关闭/重开终端不会撤销）。插件跑在常驻共享 service（daemon）：`source_pid`/进程树不可信故**整组省略**（终端跳转对 v2 降级），安装/更新后需 `opencode service restart`。`ctx.permission.hook()` 按上游 v2.0.15 类型返回 `Promise<Registration>`：本实例 dispose（setup 返回的 cleanup，宿主也会在插件 scope 关闭时调用）会调用 `registration.dispose()`，注册 Promise reject 只记日志不影响事件订阅。事件订阅**不等待** hook 注册（注册挂起/reject 时状态上报照常），reload **不等待**上一代注销完成；本实例清理先同步完成本地清理（标记 disposed、abort 订阅、身份恢复）再去注销 registration，注册 dispose 有约 2s 上限、超时只记日志，注册未完成就被取代则在注册完成那一刻立即注销，不残留活 hook。上游 v2.0.15 的 trigger 对同名 hook 依次调用每个仍注册的回调、共用同一个可变 event，而我们的注销是异步的，所以 reload 窗口内旧回调可能仍被调用：已退役实例的回调入口检查 `instance.disposed` 后直接返回，不 POST、不改 event。每个 ask 各自转发（`source.id` 是工具调用级、不是 ask 级，同一工具调用会发出多个不同 ask，如 external_directory + edit），不做内容去重。config 顶层重复 `plugins` 键按歧义处理：Doctor 报 `config-corrupt` 不抛异常，register/卸载在首次写入前中止（v1 宿主 sweep 只告警并跳过），v1 `plugin` 键行为不变。v1 1.18.31 tuple 契约、generation 布局、owner/lock 语义不变；`inspectGeneration` 把历史 4 文件集接受为合法 owned-stale 形态以便迁移。真机证据与降级项见 `docs/investigations/opencode-v2-e1-evidence.md`\n- OpenCode 的 plugin 注册不再直接指向打包/源码目录：`agents/opencode-family.js` 的 `managedMaterialization:true`（OpenCode true / MiMo 本次 false）gate materialize、ownership classifier、managed Doctor 与 generation cleanup。开启后 register 必须在目标 home 下维护 `<home>/.clawd/integrations/opencode-family/opencode/homes/<configDirHash>/generations/<bundleHash>/` 的内容寻址 generation（OpenCode v2 当前五文件，历史 v1 四文件），同一 generation 可同时物化 v1/v2 入口文件，但不因此在配置中注册两个键；探测到 v2 宿主时只把 `opencode-plugin-v2` 入口写入 `plugins`，并将 `plugin` 键仅用于清理 Clawd 自有旧条目；v1 宿主和探测不到版本时保持原有 v1 注册路径；bundle allowlist 固定为 `<agent>-plugin/index.mjs` / `<agent>-plugin/package.json` / `opencode-family-plugin/core.mjs` / `opencode-family-plugin/session-ids.mjs` / `opencode-plugin-v2/index.mjs`（v2）。owner record（`owner.json`，literal `clawd-on-desk.opencode-family.target`）与 target-scoped `mutation.lock/`（独立 literal `clawd-on-desk.opencode-family.target.lock`）是所有权与 app-present 真相；lock 被持有时不并发写：interactive Install/Repair/CLI/Uninstall/About cleanup 只做一次短而有界、可注入 delay 的重试，startup automatic 不等待直接 skipped；合法且超时 2 倍以上、PID 明确 ESRCH 才允许 atomic quarantine 接管，corrupt/foreign/live/EPERM 一律不接管；release 只删自己 token 的 `lock.json` 与随后为空的精确目录，禁止 recursive cleanup。owner 的 `activeSourceMarker` 必须是 `<activeSourceRoot>/<pluginDirName>/index.mjs`（共享 canonical 身份、Windows 折叠大小写）且为 regular file，目录/dangling/错 plugin 目录/root 不匹配都不算 live。同一 target 的 source owner 冲突（marker 仍存在）一律 `owner-conflict`，不得来回改 config；旧 owner 的源码 marker 已不存在时，新 source 必须在锁内重读并原子接管 owner（config 已 current 也不例外），否则残留死 owner 会让托管 plugin 永久 inert。锁内若 config 与当前 source owner 都已被并发操作收敛，则本次零 mutation 返回 skipped。lock release 失败不得掩盖结果：成功保留 status 并附 warning + 精确 lock path 的 residualPaths，已有 primary error 时保留原错误。basename 本身永不构成所有权；copy 到 managed layout 外的完整 generation 因缺少对应 owner record 而 inert，只有 verified-current-copy 可 Repair。tuple 契约固定为 OpenCode 1.18.31 实测的 `[specifier, optionsObject]`（隔离 `opencode debug config` 证据：第二项必须是普通对象，数组/字符串第二项会被宿主拒绝）；重写只替换 `plugin[index][0]`，options 值级保留，绝不写回嵌套 tuple，malformed array 原样保留。`options.pluginDir` 仍是 test-only expected-canonical override（跳过 generation/manifest/boundary，但不跳过 ownership/唯一 entry/read-back），`resolvePluginDir()` 仍返回 source。新建文件按当前用户普通写权限落盘：不得加 readonly/deny-write ACL，不得用 `W_OK`/`r+`/INIT 日志/session 活跃做健康门禁。Uninstall 以“活动注册是否移除”为提交依据（`registrationRemoved` false/null 阻止 Settings 提交，undefined 沿用 legacy status），残留 generation 只产生 warning；清理有效 generation 时必须先在同一 `generations/` 内原子改名为非 canonical `.cleanup-*` 再递归删除，删除失败不得占住原 hash 槽。兼容旧版本留下的半残 canonical 目录时，只允许在 owner 已 released、bounded history 精确证明该 canonical entry、且配置无活动 Clawd entry 的条件下，把它原子隔离为 `.recovery-*` 后重新物化；active/foreign/unproven/canonical-in-use 一律继续 fail closed，绝不原地覆盖或修补可疑 bytes。托管 core 的 orphan inert gate（`evaluateManagedLayoutGate`）必须在 `resetDebugLog()` / PID walk / bridge / handler 注册之前，owner marker 缺失、损坏、agentId 不匹配或 `activeSourceMarker` 不存在时返回空 handler；source-direct 模式保持原行为。MiMo 保持 broad-basename register/unregister/Doctor 契约不变。\n- Pi 通过 `~/.pi/agent/extensions/clawd-on-desk` 的 global extension 推送状态；Clawd 对 Pi 是 **state-only**，不接管权限、不弹权限气泡，也不把 Pi 的默认 YOLO 流程改成手动确认\n- OMP (oh-my-pi) 通过 `~/.omp/agent/extensions/clawd-on-desk` 的 global extension 推送状态，agent id `omp`，对 Clawd 同样是 **state-only**。它是 Pi 的 fork（包名 `@oh-my-pi/pi-coding-agent`），所以 `hooks/omp-extension.ts` 刻意与 `hooks/pi-extension.ts` 保持逐行对齐（只差 package import、core import 与函数名），进程树遍历与终端识别不得各自漂移；OMP 独有的差异全部收在 `hooks/omp-extension-core.js`。**完成必须走 `session_stop` 候选 + 终态 `agent_end` 提交的两阶段协议** —— `session_stop` 先保留主会话边界，OMP 再汇总所有 extension 的续跑请求；只有后续 `agent_end.willContinue !== true` 才向 Clawd 发完成。不得直接把任一事件单独映射为完成：仅用 `agent_end` 会把 subagent/调度边界误报为完成，仅用 `session_stop` 则会早于 extension 续跑判定。`session_switch` / `session_branch` 要为被切走的旧 session 补发一条合成 `SessionEnd`，否则 Clawd 会留下一条再也不会有人上报的活动行。session id 命名空间是 `omp:<raw>`，且必须始终带 `session_title`（多个交互式会话合法地共用同一个 cwd，缺标题会让列表和跳转目标无法区分）。安装器遇到社区桥接 `~/.omp/agent/extensions/clawd-on-desk-omp.ts` 时必须 fail closed 跳过：两者上报同一批事件，同时存在会双发。当前 `assets/source/agent-icons/omp.png` 是 `fallback: true` 的占位 π 字形，不是 OMP 官方品牌素材，拿到授权素材后应替换\n- DeepSeek Harness 首发是 **web profile / Windows-first experimental / plugin-only**；rc.6 已于 2026-08-29 完成 macOS / Windows x64 源码运行的真实 API-backed session/approval smoke（#962）；rc.2 Windows packaged-app 证据仅覆盖安装、web boot 与直接 bridge client 的 state/Allow/Deny 往返（#938），不得合并宣称 rc.2 安装包的真实 API 会话已验证。Clawd-managed in-process plugin 监听公开 `session/created`、`session/event`、`session/disposed`、可选 `sessionProjections.onChanged` 与 blocking `approval/request`；标题和上下文仅作为会话元数据同步，不占用生命周期 seq。状态按 session FIFO 上报并携带上游 seq；Clawd 不读取 `$DSH_HOME/storages` projection。普通审批进入独立 DSH `/permission` adapter，只支持人工 Allow Once / Deny；204 / 断连 / DND / disabled 都由 plugin `next()` 交还 DSH 原生 web answerer。`ask_user_question` 始终留在 DSH 原生 provider；DSH 不进入 `KNOWN_PERMISSION_AGENTS`，auto-tools / unattended / per-session grant 全部 DEFER。安装器通过官方 `dsh plugin --profile web add/remove` 管理 immutable marker-owned generation，foreign 同名包 fail closed；版本放行改成按 **小版本族（major.minor）**。维护两张表：一张是唯一写出具体版本/npm artifact/integrity 的已验证 artifact 清单（优先 `@deepseek-ai/dsh@0.2.0-rc.2`（integrity `sha512-EAJ3gPNcVt/uv8X19PMm9NkVhWgT7xXNMk0UKCVm+IQ5rpSQOcsMUa0HWlnYYVybKMsccjcRB21vVVsaXQ6IdA==`，2026-10-04 已做静态接口核对，并在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证了用 Clawd 安装器装出的 generation 的启动同步换代、会话状态、HUD 标题/上下文、Allow/Deny 与消息上的失败标记；其 `tool/result` 把失败标记放在消息 `message.isError` 而不是内容项上，bridge 新旧两种位置都认），并保留 `@deepseek-ai/dsh@0.1.5-rc.3`（integrity `sha512-c0W6Xqc4ChjFcCJkbzPeIxZQdnbKqe+QAcJzWGtogg0ZzsnZRcw3vopMyZ5oZU6E2fmyqGcyDR1sBeiCH4yHcg==`，2026-09-27 已在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证启动同步安装、会话状态、HUD 标题/上下文与 Allow/Deny）、`@deepseek-ai/dsh@0.1.5-rc.1`（integrity `sha512-rmNmzQCg3oIc1z8xH7izRSOuy1TNzq+/NILyfM+7e8DKOyV+yBtg47WEsqR2SiIe1ATec3L/rUa1YhIcfQ2XEg==`）、`@deepseek-ai/dsh@0.1.1-rc.2`（integrity `sha512-UP1UIh6q3Gme/yXRn/QL2P8IsVlv8Shpg22TRJIZPsCRWLm4CBiA1MUvXmJAfsOEETBMLAl+xWPtFw6ICsN3wg==`）与 `@deepseek-ai/dsh@0.1.0-rc.6`（integrity `sha512-brpZfED7ieRa2PQ5tUxMhHrM1pb2CmKFVM/f6yMULBDMicahk+Z2OsHgTwTDnoiZm23Ftu9rQz0NN4pflaoJcg==`）），一张是族表（`0.2` 下限 `0.2.0-rc.2`、`0.1` 下限 `0.1.0-rc.6`）。host 版本经严格解析（拒绝前导零、空预发布标识与 build 元数据）通过、major.minor 命中族、且不低于该族下限即放行；同一族内不同 host 版本共用一个 generation，出现新的小版本必须重新验证并新增一个族。旧的精确 `=<version>` marker 仍按原 range 核对哈希，新 generation 一律写族 range；Install/Repair 按 host 版本所在的族选择目标契约，Uninstall / 手动 npx 命令在 marker 版本已列入清单时钉它自己的 artifact，否则钉同族版本最高的已验证 artifact（无 CLI 且无 marker 时用首选族最新的并记为 assumed）；加锁前后比较的是实际检测到的 host 版本，不看族。DSH 的 `metadata_only` 标题/上下文旁路必须核对目标会话的 `agentId` 确为 `deepseek-harness`，撞名的其他 agent 会话直接丢弃。`47f9438` 仅是源码调查基线，不代表任何 tag/commit 映射。\n- DSH 每个 canonical `DSH_HOME` 的 mutation lock 只有在 owner/schema/token/PID/timestamp/owner-recorded operation timeout 合法、超过该 owner timeout 两倍、且 OS PID probe 明确为 `ESRCH` 时才允许 atomic-rename takeover；live、`EPERM`、unknown、corrupt/foreign owner 一律拒绝并返回精确 lock path。canonical lock 的 owner write/release 禁止 recursive cleanup。无全局 CLI 时生成的手动 npx generation 必须先在同一锁内写 owned reference，手动 add/remove 命令必须显式 pin shell-quoted canonical `DSH_HOME`；malformed/foreign/concurrently replaced reference 一律 fail closed 并保留 generation\n- DSH 桌面版支持（#1119）与 web 共用一个 agent id `deepseek-harness`：web profile 和 DeepSeek Harness 桌面版是两个承载方、各自一个 profile（桌面版是 `$DSH_HOME/profiles/desktop`），但在 Settings 和 Doctor 里仍是**一行**，显示名 `DeepSeek Harness (experimental)`，一次排队操作先 web 后 desktop、一边失败不影响另一边；安装只要有一边核实健康即成功（另一边失败变 warning + 常驻提示），卸载要所有 Clawd 注册都没了才成功。桌面版查找：macOS 用 `/Applications` 或 `~/Applications/DeepSeek Harness.app` 里自带的 `Contents/Resources/runtime/cli/bin/dsh`；Windows 按用户安装，从 `HKCU` 卸载项（显示名以 `DeepSeek Harness ` 开头）与 `%LOCALAPPDATA%\\Programs\\DeepSeek Harness` 找 `resources\\runtime\\cli\\bin\\dsh.cmd`，注册表用 PowerShell 读 UTF-8 JSON、不用 `reg.exe`；Linux 不支持桌面版。静态版本来自 `Info.plist` / 卸载项 `DisplayVersion`，真正动手前跑一次启动器 `--version` 核实。桌面版**永不用 npx**，手动 npx 命令与 manual reference 只属 web。每边角色是 `mutable` / `diagnose` / `not-applicable`：桌面版没装、或 profile 从未初始化（桌面版没打开过）→ 不适用并提示打开一次；foreign 同名包、文件读不了、清理残留、注册查不清、版本不支持、装了不止一个桌面版（`multiple-desktop-installs`）、桌面版找不到但注册还在（`carrier-unavailable`）、桌面版查不清（`desktop-unverifiable`）→ 只报告不动手。启动同步在集成已安装且启用时会把插件加进已初始化的桌面版 profile；桌面版开着也会加载新加的插件，只有插件更新（换了 generation）后要重启。常驻提示在 `hooks/dsh-notices.js`，按 profile 存 `notices-web.json`/`notices-desktop.json`，四种 kind（`restart-required`/`first-install`/`manual-command`/`failed-target`），写不进去只算 warning；提示显示在 Settings → AI Coding Tools 里这一行下面。Doctor 一行详情 `web: …; desktop: …`，状态取适用边里最差，只要有一边能尝试修复且不健康就给修复按钮（`src/doctor-detectors/agent-integrations.js`）。插件在 DSH 里被关掉（依赖在、bundle 行没了）时 `plugin add` 不会重开：显式修复先 remove 再 add（add 前先清掉上游 remove 留下的自有链接，Mac 是符号链接、Windows 是 junction），按 profile 记 `repair-operation-<profile>.json`，中断后下次显式修复续做，启动同步只报 `plugin-disabled-in-dsh`。`generations/` 两边共享，任一边有未处理状态（检查记录、清理残留、坏修复记录或 manual reference、读不了的 profile、符号链接 profile 目录）时清理暂停但不挡安装，卸载残留进 warnings。检查记录按 profile：web `inspection-required.json`、桌面版 `inspection-required-desktop.json`。`plugin add/remove` 写命令两边都超时 300 秒（web 原 120 秒），比上游写锁等待长。上游 `dsh plugin remove` 只清 `link:` 清单和锁、`node_modules` 链接会留下，Clawd 卸载自有插件时确认归属后清掉。Windows 静态查找是同步代码、不起进程，只读异步快照：启动时（不管 DSH 是否启用）、打开 Doctor 前、Agents 页手动扫描时刷新，没快照时桌面版显示\"查不清\"。安装检测把\"找到桌面版\"也算装了 DSH（`src/agent-installation-detector.js`）。桥接插件在 apply 时读 `ctx.profileContext?.name`，只有 desktop profile 才在 state / 审批载荷里带 `dsh_carrier: \"desktop\"`（metadata 不带；web 或未知 profile 一律不带）；Clawd 只接受 DSH + `dsh-plugin` + 本机 + 非 WSL 的载体，按生命周期覆盖或清除、不粘滞，权限 fallback entry 与快照（含签名）都带上它。点击桌面版会话时 `getSessionFocusTarget` 在 darwin/win32 返回 `dsh-desktop`（`dsh://open`），分派先 `shell.openExternal(\"dsh://open\")`，被拒绝再按 `discoverDshDesktopSync({ requireUniqueApp: true })` 的兜底要求唯一安装启动界面程序（macOS `open <appRoot>`、Windows 启动 `<appRoot>\\DeepSeek Harness.exe`，去掉 `ELECTRON_*`/`NODE_OPTIONS`，不用 CLI 启动方式；两份真实路径不同的有效安装视为有歧义，只要还有核实不了的候选也不自动启动，同一份安装的符号链接只算一份）；只能打开应用窗口、不会切到具体对话，web 会话仍不可跳；桌面版启动时会重新打开上次的对话，Clawd 只在这个对话有了动作（提问、工具调用、审批）之后才把它放进 Session HUD（`awaitingActivity` 并入快照 `hiddenFromHud`，但不关跳转；与 Kimi Code 共用同一个标记），Dashboard 照常列出、按钮照常可跳；2026-10-05 macOS 26.6.2 与 Windows 11 x64 源码运行真机验证（桌面版 `0.2.0-rc.2`）：别的窗口在前、最小化、关窗后，点击都经 `dsh://open` 把窗口带到最前；协议打不开时的启动兜底只有单元测试。真机证据：2026-10-04 macOS 源码运行（Clawd `ac64d726`，桌面版 `0.2.0-rc.2` + 全局 `@deepseek-ai/dsh@0.2.0-rc.2`）验证了启动同步把插件装进桌面版（与 web 共用 generation）并出现\"已装进桌面版\"提示、Doctor 一行两边正常，桌面版真实会话的 Allow 建成文件、Deny 后文件内容和 mtime 不变且 Clawd 显示 `PostToolUseFailure`，\"知道了\"后提示消失，改 bridge 源码（同 Clawd 版本）后启动同步两边报 `generation-conflict` 并提示去 Doctor 修复、修复把两边换到新 generation/删旧/出现\"重启桌面版后生效\"、重启后事件来自新宿主进程，设置页卸载后两边依赖与 bundle 行都没了、上游残留链接被清、generation 删除、两边提示清空，再在设置页安装两边都重新装上、桌面版重新出现\"已装进桌面版\"（\"经设置页首次安装\"因此已覆盖），开着 DND 时桌面版的工作区外写文件不弹 Clawd 气泡、返回 no-decision、桌面版弹自己的原生审批框、批准后文件建成且事件照常到达。2026-10-04 Windows 11 x64 经 SSH 用 Node 直跑安装器代码（管理员会话，桌面版在 `%LOCALAPPDATA%` 按用户安装 `0.2.0-rc.2`、全局 dsh `0.1.0-rc.6`，web 在 0.1 族、桌面版在 0.2 族）：PowerShell 读注册表找到桌面版、静态模式无快照时报\"查不清\"且不起进程、自带 `dsh.cmd`（带空格路径）`--version` 返回 `0.2.0-rc.2`、`dsh.cmd plugin --profile desktop add` 经 pnpm junction 装入并核实、记录\"已装进桌面版\"、两族各用一份 generation 并存、Doctor 一行两边有修复按钮、卸载桌面版清依赖与 bundle 行并清掉 `dsh plugin remove` 残留 junction、只删桌面版那份 generation 而保留 web 在用的；2026-10-04 另在 Windows 上以真 Clawd（Electron，源码运行、用户会话、普通权限）验证：先抓到一个只在 Electron 里出现的 bug（Electron 的 fs 把 `app.asar` 当目录、Windows 安装目录核实要求它是文件，于是在真 Clawd 里桌面版被判成没装，已在 `d8190692` 修成\"存在即可\"）；修好后桌面版一直开着（宿主进程未重启），启动同步把插件装进桌面版并记\"已装进桌面版\"，在桌面版新开对话的事件来自那个未重启的宿主进程，**Windows 上桌面版开着也会加载新加的插件**。**未覆盖**：Windows 上桌面版的审批、Windows 上的 Electron 界面（设置页提示、Doctor 窗口、启动预热）、打包后的 app、Linux、HTTP 204 交还与取消、装了多个桌面版。**管理员 junction 观察（推断）**：提升过的管理员进程在 Windows 11 上穿不过非管理员进程建的 junction（PowerShell \"untrusted mount point\"、Node `UNKNOWN`），该会话里 web 的旧 junction 读不到、web add 失败，桌面版同会话新建的 junction 正常；普通权限运行不受影响；由此推断以管理员身份运行 Clawd 可能把普通权限装好的插件读成缺失，未用以管理员身份运行的 Clawd 直接复现\n- OpenClaw 通过 `~/.openclaw/openclaw.json` plugin 路径做 state-only 集成；Phase 1 不做 permission bubble / terminal focus，主要支持本地 `openclaw tui --local`\n- Antigravity CLI (agy) 通过 `~/.gemini/config/hooks.json` 做 **state-only** hook 集成（PreInvocation / PostToolUse / PostInvocation / Stop），**不注册 PreToolUse**。agy LLM 会主动调内置 `ask_permission` 工具，触发 agy 自己的 5 选项 native menu（含 \"Persist to settings.json\" 持久白名单），Clawd 不插手权限决策也不双层确认。`agents/antigravity-cli.js` `capabilities.permissionApproval` / `interactiveBubble` 均为 false。\n- Qwen Code 通过 `~/.qwen/settings.json` 做 hook-only 集成（SessionStart / SessionEnd / UserPromptSubmit / PreToolUse / PostToolUse / Stop / Notification / PermissionRequest），支持状态与阻塞式 `PermissionRequest` 权限气泡；`disableAllHooks: true` 时注册条目不会触发。\n- QwenWork (千问办公) 通过 `~/.QwenWorkCN/settings.json` 做 **hook-only / state-only** 集成（agent id `qwenwork`；SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / Notification / PermissionRequest / PermissionDenied / SessionEnd）。`PermissionRequest` / `PermissionDenied` 只作为观察映射成 `working`（每任务 40+ 次，映射成 notification 会刷屏），hook stdout 恒为 `{}`：Clawd 不产生 allow/deny，不注册 `/permission`，也不进入 permission automation eligibility，唯一决策者是 QwenWork 原生权限流程；`agents/qwenwork.js` 的 `capabilities.permissionApproval` / `interactiveBubble` 均为 false。Windows command 必须保持 `windowsWrapper:\"portable\"`（QwenWork 经 POSIX shell 执行 command hook），PowerShell `-EncodedCommand` **只**用于识别并原地迁移旧条目，不是当前写入形态。marker 只认 `qwenwork-hook.js`，不得仅凭 `name:\"clawd\"` 删除用户 hook；混合 entry 中第三方 hook 原样保留。session id 命名空间是 `qwenwork:<raw>`；`~/.QwenWorkCN/workspace/<id>` 这类内部工作区 cwd 不做 basename 回退，避免 HUD/Dashboard 显示内部 ID。当前真实支持平台只有 macOS / Windows 桌面端（官方下载页 https://qwenwork.cn/download 只提供 macOS 14+ / Windows 10+ / HarmonyOS 6.1+，没有 Linux 客户端），因此 `processNames.linux`、resolver linux agent name 均为空，也不进 `src/wsl-deploy.js` 的 WSL Pair 映射。桌面主进程长驻、不代表 active turn，`startupRecoveryProcessNames` 全空、无 startup recovery。安装/卸载走 Settings → AI Coding Tools，或 `npm run install:qwenwork-hooks` / `npm run uninstall:qwenwork-hooks`；卸载必须同时在 `hooks/cleanup-integrations.js` 的 `MANAGED_AGENT_IDS` / `AGENT_CLEANERS` / `byAgent` 里有条目，否则 About cleanup 只会改 prefs、hook 留在磁盘上\n- ZCode 通过 `~/.zcode/cli/config.json` 的 `hooks.events.*` 集成全部 7 个支持事件（SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / PermissionRequest，无 SessionEnd / Notification）。PermissionRequest 为阻塞式权限审批：hook 长连接 `POST /permission`（HTTP 等待 590s，installer 注册 `timeoutMs: 600000`），有决定时 stdout 返回最小合法 `{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}`（deny 可带 `message`），无决定 / 超时 / 断连 / 任何错误输出 `{}` 并 exit 0，ZCode 回退原生权限流程；`interrupt` / `updatedInput` / `updatedPermissions` / `permissionUpdates` 必须 omit（最小输出 union 按 ZCode 3.5.x 严格 schema 约束；macOS ZCode 3.8.1 已完成真实 hook / 气泡 Allow/Deny 往返，3.5.x PermissionRequest 真机往返未覆盖）。超时单位陷阱：ZCode `timeout` 是秒、`timeoutMs` 才是毫秒，且超时按事件区分（PermissionRequest 600000、state 事件 8000）。Phase 2 只允许人工审批：ZCode 不进入 `KNOWN_PERMISSION_AGENTS`，global / per-session permission automation 在工具面与会话身份审计完成前全部 defer。prefs v14→v15 迁移把 Phase 1 持久化的 `zcode.permissionsEnabled:false` 翻 true（当时开关从未渲染、无用户意图）。配置必须有 `hooks.enabled=true` 才会执行；安装器只在该字段缺失时补 true，显式 `hooks.enabled=false` 或 Clawd 单项 hook 的 `enabled=false` 必须保留，Doctor warning 且不提供会覆盖用户选择的 Fix。ZCode 导入 Claude 配置后，只清理 `.zcode` 中明确引用 `clawd-hook.js` 的 Clawd-owned 条目，绝不改 `~/.claude/settings.json`。安全边界（复核后新增）：`/state` 生命周期 sweep 对 zcode（及 qwen/DSH 等 native-fallback adapter）只允许 no-decision，绝不伪 deny；hook 侧 `tool_input` 预算内原样发送、任何截断（长 Bash 尾部 `rm -rf` 场景）或序列化超 512KiB 一律 fail-closed 输出 `{}` 交还原生 UI；无 allow/answer/plan capability 的 interaction（如 ZCode 真实的 ExitPlanMode / AskUserQuestion）本地气泡与远程卡片都不提供决定入口、直接 204；全局气泡关闭只关本地窗口，Telegram/飞书 remote-only 审批仍可用（per-agent gate 关闭才是全退出）；installer 遇到 foreign `PermissionRequest` hook 时不注册自己的 blocking hook，若 foreign hook 后出现则移除自己的 managed hook（ZCode 同事件 hook 串行执行、后写覆盖，Clawd allow 会盖掉用户 hook 的 deny），Doctor 报 `permission-conflict` 且不给 Fix；六个 Phase 1 managed hook 全部显式 disabled 时新 PermissionRequest 继承 `enabled:false`；服务端 pre-parse 超限一律断连回退，不伪造 deny\n- Qoder / Qoder CN 共用 `qoder` agent，通过 `~/.qoder/settings.json` / `~/.qoder-cn/settings.json` 做 **state-only** hook 集成；各自尊重 `QODER_CONFIG_DIR` / `QODERCN_CONFIG_DIR`，同步所有已初始化目录，不创建缺失版本目录，卸载/cleanup 覆盖两版且只移除 Clawd entries，Doctor 不得让健康的一版掩盖另一版故障。Clawd 只把 `PermissionRequest` / `PermissionDenied` 当 notification 观察，**不替 Qoder 做权限决策**，hook stdout 恒为 `{}`；Windows command 必须保持 `windowsWrapper:\"portable\"`。session id 命名空间是 `qoder:<raw>`；启动恢复只认 CLI `qodercli` / `qoder-cli` / `qoderclicn`，不认闲置 IDE / CN 桌面进程；本机原生会话标题由 `src/qoder-session-title.js` 低频异步增量读取，通过 `updateSessionMetadata` 更新；SessionEnd / 禁用 / 退出取消旧读取，远端与 WSL 路径不在本机读取。2026-10-18 已核对 Windows CN runtime 1.1.69 的真实 SessionStart / UserPromptSubmit / Stop hooks，用户确认开启 Clawd Qoder 接入后任务状态恢复；macOS/Linux CN 未实测\n- TraeCode (Trae CN) 通过 `~/.trae-cn/hooks.json` 做 **hook-only / state-only** 集成。Windows command 必须保持 `windowsWrapper:\"encoded\"`：Trae 的 Windows Sandbox 会把 hook 命令作为 `trae-sandbox.exe --command-line` 的单个原生参数再次转发，普通引号或 `portable` 形态会在含空格路径处拆分；外层必须保持无引号的 PowerShell `-EncodedCommand`，POSIX 则继续使用普通 quoted command。该约束不适用于经 POSIX shell 执行 Windows hook 的 agent（如 Qoder / QwenWork）。\n- MiniMax Code 通过 `<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/` 的 **Clawd 独占本地插件**做 **state-only** 集成（manifest 用 `.claude-plugin/plugin.json`，hooks 文档按 MiniMax 的 CLAUDE sourceFormat 解析；不用 `.minimax-plugin/`，那会走 MINIMAX 格式：matcher 必须非空且不支持 exec-form args）。handler 固定 exec-form `command=node 路径 + args=[minimax-hook.js]`（spawn 直执行、无 shell、免引号），`timeout` 单位是秒且只接受 1–10 的整数（越界的 handler 被丢弃而不是钳制；SessionEnd 事件总预算仅 3s），因此 **PermissionRequest 物理上不可阻塞审批、完全不注册**，也没有 Notification 事件；hook stdout 恒为 `{}`（permissionDecision 缺省 abstain）。目录级所有权只认结构化凭据 `.clawd-managed.json`（`{app:\"clawd-on-desk\",integration:\"minimax\",managed:true,version:1}`，同 Pi 约定；MiniMax 只读 manifest 声明的文件，会忽略它），且凭据与所有受管理路径（`.claude-plugin/`、`hooks/` 及其文件）都不得是符号链接；目录名、manifest name、文档里的 basename/子串乃至整份文档指纹都永不授权改写或递归删除，缺凭据的目录（包括补丁前预发布构建写出的）一律 fail closed，只能手动删除后重装。staging / removal 目录固定落在数据目录（`plugins/` 之外，MiniMax 会把 `plugins/` 下每个目录项都当插件候选，含点号名）：首装在 staging 写全三份文件后一次 rename 发布（只覆盖空目标，非空目录/文件/链接拒绝；空 `clawd-state/` 视为未占用），失败时尽力删除 staging；已拥有的目录原地逐文件更新，中断后仍可证明归属、由下次安装补完。只有 ENOENT/ENOTDIR 算不存在，其他 lstat 错误按无法确认处理，绝不据此宣告卸载。卸载先把已验证目录 rename 出 `plugins/`、复验后再删；移走失败报 error 并保留安装意图，移走成功但删除失败时按已移除提交并在 warnings 里给出残留 `.clawd-minimax-removing-*` 路径，复验失败且移回失败时两个位置都报 `registrationRemoved:null` 并带 `residualPaths`；删不掉且目录仍运行 Clawd hook 时返回 `registrationRemoved:false`（读不清为 `null`），Settings / About 据此保留安装意图。删除后返回前还会复查一次原位置：此时若已有另一个 Clawd 实例重新发布的插件，报“仍在注册”（`registrationRemoved:false`）、不宣称卸载；这次复查是快照，复查之后、Settings 提交之前的安装不在本次结果里（多实例强一致需要覆盖 prefs 提交的跨进程锁，未做）。Settings 界面目前不显示成功结果里的 `warnings` / `residualPaths`：Agents 页安装/卸载只弹“已卸载/已安装”，About 清理只显示计数，只有命令行 cleanup 脚本会打印 warning。进程中途崩溃，或 staging 清理本身失败，可能在数据目录留下 `.clawd-minimax-staging-*` / `.clawd-minimax-removing-*`（MiniMax 不会加载，只能手动删除）；`plugins/` 与数据目录跨文件系统（EXDEV）时不支持。判断外来目录是否仍跑 Clawd hook 按 manifest 声明的 hooks 文档和 MiniMax 默认规则检查（含裸文档外壳、反斜杠路径，以及 shell 形式的 command / commandWindows handler）；Clawd 不建模的 manifest（根 `plugin.json` / `.minimax-plugin/` / `.codex-plugin/`）或读不清时按无法确认处理。node 探测失败时只保留全部 Clawd handler 一致、basename 为 node、存在且可执行、并通过 `node --version` 有界探测的已记录路径（exec-form 无 shell，Dock 启动的桌面 App 的 PATH 里没有 node），安装器与 Doctor 共用 `resolveDesiredNodeBin`。PostCompact 按 #406 上报 thinking（`trigger:\"manual\"` 时 idle），不是 attention。hook 的 `agentNames` 必须全小写（resolver 比较的是小写 basename），且不含桌面版的 “MiniMax Code Helper”：拉起 hook 的 NodeService helper 可能在 App 运行中重启，把它当 agent 会误删活会话，识别应落到长驻的主程序；mcode CLI 启动时执行 `process.title = \"minimax-code\"`，macOS/Linux 上 `ps` 报告的进程名就是 `minimax-code`（按名字匹配），Windows 上仍是 node.exe，靠 `agentCmdlineCheck` 只看 argv 里的脚本位置识别（命令行检查的进程名沿用共享默认 `DEFAULT_AGENT_CMDLINE_NAMES`，已含 Linux 上新版 Node 的主线程名 `mainthread` / `node-mainthread`，MiniMax 不再自带名单）（`node` 后的脚本 basename 是 `mcode`/`minimax-code` 启动器，或脚本路径含 `/@minimax-ai/code/` / `/.minimax-code/`），参数里的目录片段不算——MiniMax 退出时不发 SessionEnd，没有 agent pid 会话就无法按 agent-exit 清理。hook 不触发时的启用步骤在 MiniMax 应用内（`mcode plugin enable clawd-state@local` 或插件面板），磁盘上读不到启用状态，Doctor/Settings 只能提示。session id 命名空间 `minimax:<raw>`，标题走首行 prompt 派生 + 服务端 first-wins（同 traecode）。\n- Kimi Code（agent id `kimi-cli`）的 agent pid 靠进程名识别：CLI 启动即 `process.title = \"kimi-code\"`，libuv 把标题写回原 argv 所占的空间、放不下就截断，所以 macOS/Linux 上 `ps` 与 `pgrep -x` 看到的名字随启动命令长短而变（0.42.0 原生版实测：`kimi` 仍是 `kimi`，`kimi -c` 是 `kimi-co`，`kimi --yolo` 或全路径启动是 `kimi-code`；只有整条启动命令比 `kimi` 还短时（例如不带参数的软链接 `k`）才认不出，`k -c` 显示的已经是 `kimi`）。`hooks/kimi-process-names.js` 必须列全从 `kimi` 到 `kimi-code` 的每一种截断，resolver 与 startup recovery 共用这一组，只写 `kimi-code` 会漏掉 `kimi -c`。拉起 hook 的就是这个改名后的主进程（TUI 在进程内跑 agent 引擎，从 SessionStart 到 SessionEnd 同一个 PID）；其他同名进程（后台更新下载器、经 kimi 二进制跑的插件进程等）都是它的子进程，不跑 hook。resolver 比较小写 basename，macOS 桌面版 `Kimi Code.app` 写成 `kimi code`（它的 agent server 跑在主进程里，hook 由主进程直接拉起）；桌面版关窗后常驻托盘、不代表在干活，同其他桌面 App 一样不进 startup recovery。Windows 上标题只改控制台标题：原生版仍是 `kimi.exe`，npm 版仍是 `node.exe`，命令行检查只认包目录 `/@moonshot-ai/kimi-code/`，不能退回“含 kimi 就算”（Kimi 本身没被认出时，任何命令行提到 kimi 的 node 祖先都会被当成 agent）。Kimi Code 正常 `/exit` 会发 SessionEnd，但关终端、`kill`（0.42.0 实测：SIGTERM 与 SIGKILL 都不发；源码里 SIGTERM 注册了 `stop(143)`，实测为什么没发 SessionEnd 还没查清）、崩溃都不发；没有 agent pid 的会话只要终端 App 还开着就一直留在列表里。桌面端启动时会恢复上次查看的对话、在侧栏点开旧对话也一样，这类只发一条 SessionStart、还没有任何动作的对话不进 Session HUD，Dashboard 照常列出、按钮照常可跳，出现提问/工具/审批/Stop 等动作后自动进 HUD（与 DSH 共用同一个 `awaitingActivity` 标记）。\n- HTTP 服务端口范围固定为 `127.0.0.1:23333-23337`；运行时端口写入 `~/.clawd/runtime.json`\n- Mobile Preview 是独立的 LAN listener，候选范围为 `0.0.0.0:23334-23338`；它不写 `runtime.json`，不得把该范围误写成 hook / custom-agent HTTP ingress 范围\n- 自定义 HTTP Agent 的 sender 必须读取 `~/.clawd/runtime.json`，不能把 23333 写死；注册不等于已连接。custom v1 只支持 `/state`，不支持 `/permission`\n- CodeBuddy PermissionRequest hook 的所有权只认本机 managed URL 或 marker `clawd-on-desk.permission.v1`；纯 `name:\"clawd\"` 不能触发改写/删除。裸 CLI 和 WSL 默认 preserve，Settings/startup/repair 必须显式传 local/custom permission target\n- Remote SSH 的远端 Node 探测要求 Node >= 14；Node discovery/version validation 只在 `src/remote-ssh-node.js`，ordinary tunnel health 与 serialized readiness 在 `src/remote-ssh-runtime.js`，不得互相复制或从已停用脚本另起实现\n- 注册 Claude Code hook 必须 marker-scoped merge：只可更新/删除含 `clawd-hook.js` / `auto-start.js` marker 的 Clawd-owned entry，不得整体覆盖数组或改动无 marker 的用户 entry\n- 注册 Claude Code statusLine 默认只接管空槽或自己的槽（marker `claude-statusline.js`）；本机 Settings 显式开启采集遇到第三方槽时，必须经共存确认并复核原槽指纹，使用 `--local-chain` 和独立的 `clawd-statusline-local-chain.json` 保存/恢复完整原对象。启动/自动修复不得自行取得第三方槽；恢复记录缺失、损坏或不匹配时 fail closed 并保留现场。远程部署仍用 profile 的 `chainStatusline` opt-in 和既有 `--chain` sidecar，不与本机记录混用。订阅配额通过 `metadata_only` POST 进入 session-independent `updateAccountQuota` per-source store；不要把 quota 塞进 `updateSession` opts，也不要以 session 存活作为摄入前提\n- Copilot CLI hooks 走按需自动同步：`hooks/copilot-install.js` 在本地启动仅当 Copilot CLI 已安装且已启用时调用；远端由 Settings Remote SSH deploy controller 调用。路径解析尊重 `COPILOT_HOME` env（trimmed 非空才生效，否则 fallback 到 `~/.copilot`）；`hooks/copilot-hook.js` 的 session-state resolver 同样走 env\n- Remote SSH 的 effective transport 由 `ssh -G` 只读检查决定：ordinary SSH 在没有 retained serialized occupancy 时保持 `context:null` 的 parallel 路径；serialized transport 以有效 target key（不是 profile id）互斥。所有 serialized managed SSH/SCP child 必须持 coordinator 发出的有效 connection/operation context，并通过其 pre-spawn gateway 启动；用户交互终端只有命中 serialized/retained occupancy 时才要求 coordinator 判定 target 完全 idle\n- serialized persistent tunnel 使用同一条 SSH 内嵌 readiness；暂停通过 stdin EOF 请求自然退出并等待 `close`。强杀或带 signal 的 outer `ssh.exe` close 不能证明 nested ProxyCommand 已 drain；timeout/未验证 drain 必须 quarantine，期间禁止新 child、mutation、resume 或 interactive terminal\n- mutation 在 deploy-lock acquire-attempted / lock-owned 后遇到 exit 255、EOF/reset、signal 或其他 unknown result 时不得自动 replay、retry、release lock 或恢复连接；必须保留 primary error 并传播 recovery state，必要时要求 `manual_lock_inspection_required`\n- Remote SSH secure hook 必须同时携带 `CLAWD_REMOTE=1` 与 `CLAWD_SSH_REMOTE=1`，只读 layout identity 并 pin 精确端口；identity 缺失/损坏/不可读必须 fail closed，禁止回退端口扫描\n- Remote SSH deploy-lock acquisition 必须原子化；成功 acquire 后的每个 live mutation 都要在同一远端命令内 fencing 校验，cleanup 还必须锁内重读 installId/profileId/runtimeKey/layoutVersion 所有权。无身份、冲突、ownerless/corrupt lock 均不得自动接管\n- 默认 `account-default` 只支持不同 Unix 账号；同 Unix 账号冲突必须阻止。`profile-isolated` 在真实 SSH/CLI 矩阵完成前由 `CLAWD_ENABLE_EXPERIMENTAL_REMOTE_ISOLATION=1` 发布门隐藏；它只隔离用户级 CLI config/session/runtime 与 Clawd 路由，不代表完整 HOME 或同 UID 安全隔离，project 配置/部分 cache/macOS Claude Keychain auth 仍可能共享\n- Hermes Agent 的 Remote SSH 部署是 `secureDeploy` 内的 `hermes-files` → `install-hermes` 两个阶段，复用同一条 serialized transport、deploy lease、fencing 与所有权检查，没有独立的 Hermes SSH deployer：secure 模式由每个托管 `plugins/clawd-on-desk/` 内的 plugin-local marker `clawd-ssh-secure-v1` latch，latch 后 identity 必须在每次 state/probe/permission 请求时重新读取（禁止 `(mtime,size)` 缓存），且不得发送任何远端 PID / 进程树 metadata；plugin 资产走独立 staging 目录，清理只 `rm -f` 精确文件再 `rmdir`，禁止 `rm -rf`；`REMOTE_IDENTITY_STEP_NAMES` 保持冻结的 8 步不变，不得加入 `installHermes`；Clawd 绝不自动重启 Hermes gateway，托管模块被替换时只报告需要手动重启\n- 禁用 agent 不应卸载 hooks / plugins / extensions：只停止对应 monitor、清理 session / bubble、让 HTTP hook 入口快速 fallback；重新启用未安装 agent 不触发本机 integration sync。卸载集成必须走 Settings Agent 页的 Uninstall / 对应 uninstall 命令，并同时清掉 `integrationInstalled`\n- Kiro 的 `sessionId=\"default\"` 会复用；session alias key 必须按 cwd scope 区分，同时保留旧 `local|kiro-cli|default` 只读 fallback\n- Windows NSIS release 必须产出明确架构的 x64 / ARM64 安装包：`win.artifactName` 保留 `${arch}`，`nsis.buildUniversalInstaller` 保持 `false`\n- 每个 release target 只能保留一个匹配目标架构的 Koffi `koffi.node`；`afterPack` 只允许剪裁 `app.asar.unpacked` 的物理文件，禁止重写 `app.asar`，并必须通过完整 native inventory audit（唯一常设例外是 electron-builder 管理的 Windows ia32 `resources/elevate.exe`）\n- 资源路径统一用 `path.join(__dirname, ...)`\n- 需要编辑发布素材时，先复制到 `assets/source/` 再改，不要直接改工作素材来源不明的文件\n- `assets/source/cloudling-pointer-bridge/` 是 Cloudling 指针桥素材的保留源文件目录；运行时逻辑已内联进主题 SVG，不要把这个 source 目录当临时文件清理\n- 主题状态、sleep/DND、mini mode、状态映射的细节在 `docs/project/theme-state-ui.md`\n- 官方可下载主题（`official-theme-*`）是受管分发层，不是 built-in、也不提升信任：catalog 是固定远端小目录（renderer 只能传 themeId），下载走 Electron main `net.request` 的 manual redirect + 精确 CDN host allowlist + 固定 bytes/SHA-256（未支持 host 返回稳定 `DOWNLOAD_HOST_UNSUPPORTED`，不允许 catalog 扩展 allowlist），ZIP 只在 manager 专属 staging 内流式解压并以 marker-before-rename 同卷提交，最终以 `isBuiltin=false` 加载（`trustedRuntime` 无效）。`setThemeSelection` / `removeTheme` / `officialTheme.commitInstall` / `officialTheme.uninstall` / `theme` update 共用 `lockKey=\"theme\"`；卸载 active 主题必须等 `waitForThemeReloadSettled()`。主仓库附带一份目录快照 `src/official-theme-catalog-snapshot.json`：网络拉取失败时列表先用上一次成功加载的目录（内存 LKG 或磁盘缓存），都没有才用快照；第一次拉取有结果之前（`uninitialized`）不用快照；快照**不作安装依据**，安装仍只认经校验的网络/磁盘目录。快照只作列表回落（仍显示 `offline` 和重试），不含素材与预览图，不写磁盘缓存，且参与版本不能回退的比较；发布前用 `npm run update:official-theme-snapshot` 刷新。不要把 Hash Sage / Whale-chan 的动画素材（APNG / WebP），或把它们写成内置主题的文案带回主仓库\n- Settings 体系里，store 是唯一真相，controller 是唯一写入者；不要绕开 `settings-controller.js`\n- Dashboard 数字快选是**完整 Dashboard 同一页面的临时键盘模式，仅 macOS/Windows**；Linux 明确 NOT SUPPORTED（不是待验证）。平台 gate 的唯一真相是 `shortcut-actions.js` 的 `supportedPlatforms` + `isShortcutActionSupported()`，Settings 展示、globalShortcut 注册/录制、设置命令和冲突占用都必须服从它；遗留的不支持绑定只忽略执行，不删用户 prefs、不占其他快捷键。darwin/win32 的 Dashboard 页面活在 `WebContentsView` 里，`BrowserWindow.fromWebContents()` 对它返回 null、BaseWindow 不触发 `ready-to-show`；页面 WC 一律从 owner 取。禁止用 `hide()`+`showInactive()` 归还已显示的普通宿主（实测会遮挡来源窗口），只能 opacity/input parking 并幂等恢复捕获值。详见 `docs/project/theme-state-ui.md`\n\n## Testing\n\n- 自动化测试使用 Node 内置 test runner：`npm test`\n- `test/*.test.js` 覆盖核心 unit/contract、installer、route、UI/runtime 与 Remote SSH transport/coordinator/identity；部分 fixture 会启动 Node、shell 或 Git Bash 子进程，缺少依赖时可能 skip，不能把全套结果概括成纯逻辑或等价真机验证\n- Remote SSH 真机矩阵与记录在 `scripts/manual/README.md`；Windows OpenSSH + Codespaces stdio 边界及 ordinary-host V15 release gate 不能从 unit tests 互相推断，无法执行时必须明确记录 pending / residual risk\n- Windows Terminal 真机、GUI smoke 与清理必须假定多个 tab/window 共享进程：不得按 PID/进程名 `taskkill`、`Stop-Process` 或宽泛终止 WindowsTerminal、Codex、`cmd.exe`、`ssh.exe`、OpenConsole、conhost。测试终端只能在明确 test-owned session 内 `exit`；无法证明 ownership 就保留现场并请用户手动关闭\n- 当前开发环境是 Windows-first；macOS 特定路径无法在这里手动 QA，改到 mac 逻辑时要用 code-review",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.claude-plugin/plugin.json)"},"files":{"AGENTS.md":"# AGENTS.md\n\nThis file is the entry point for coding agents working in this repository. Keep it short and operational. Durable architecture lives in `docs/project/`; `docs/plans/` and `docs/investigations/` are historical evidence unless this file explicitly links them.\n\n## Project Overview\n\nClawd 是一个 Electron 桌宠：通过 hook、日志轮询、plugin 和 extension 感知 AI coding agent 的工作状态，并播放像素风动画。当前支持 Claude Code、Codex CLI、Copilot CLI、Gemini CLI、Antigravity CLI (agy)、Cursor Agent、CodeBuddy、WorkBuddy、Grok Build、Kiro CLI、KiroCrew、Kimi Code CLI (Kimi-CLI)、Qwen Code、ZCode、CodeWhale、opencode、MiMo Code、Pi、OMP (oh-my-pi)、OpenClaw、Hermes Agent、Qoder、QoderWork、QwenWork (千问办公)、Reasonix、DeepSeek Harness、TraeCode (Trae CN)、MiniMax Code；内置 Clawd / Calico / Cloudling 三套主题，支持用户主题，并可经 Settings 从独立 `rullerzhou-afk/clawd-themes` 仓库下载可选官方主题（Hash Sage、Whale-chan，external theme 权限、可卸载）；平台覆盖 Windows、macOS、Linux，UI 支持 en / zh / zh-TW / ko / ja / pt-BR / es。\n\n## Common Commands\n\n```bash\nnpm start\nnpm run build                  # default Windows package\nnpm run build:win:x64\nnpm run build:win:arm64\nnpm run build:win:all\nnpm run build:mac\nnpm run build:linux\nnpm run build:all\nnpm install\nnpm test\nnpm run verify:electron\nnpm run verify:release\nnpm run audit:assets\nnpm run audit:pr-history-assets\nnpm run audit:native-package -- --app-root <extracted-app-root> --target <target-id>\nnpm run create-theme\n\nnpm run install:claude-hooks\nnpm run uninstall:claude-hooks\nnpm run install:cursor-hooks\nnpm run install:gemini-hooks\nnpm run install:antigravity-hooks\nnpm run install:kiro-hooks\nnpm run install:kirocrew-hooks\nnpm run uninstall:kirocrew-hooks\nnpm run install:kimi-hooks\nnpm run install:qwen-hooks\nnpm run install:zcode-hooks\nnpm run uninstall:zcode-hooks\nnpm run install:codewhale-hooks\nnpm run uninstall:codewhale-hooks\nnpm run install:pi-extension\nnpm run uninstall:pi-extension\nnpm run install:omp-extension\nnpm run uninstall:omp-extension\nnpm run install:openclaw-plugin\nnpm run uninstall:openclaw-plugin\nnpm run install:hermes-plugin\nnpm run uninstall:hermes-plugin\nnpm run install:qoder-hooks\nnpm run uninstall:qoder-hooks\nnpm run install:qoderwork-hooks\nnpm run uninstall:qoderwork-hooks\nnpm run install:qwenwork-hooks\nnpm run uninstall:qwenwork-hooks\nnpm run install:reasonix-hooks\nnpm run uninstall:reasonix-hooks\nnpm run install:workbuddy-hooks\nnpm run uninstall:workbuddy-hooks\nnpm run install:grok-hooks\nnpm run uninstall:grok-hooks\nnpm run install:dsh\nnpm run uninstall:dsh\nnpm run install:codex-hooks\nnpm run uninstall:codex-hooks\nnpm run install:codex-debug-hooks\nnpm run uninstall:codex-debug-hooks\nnpm run install:mimocode-plugin\nnpm run uninstall:mimocode-plugin\nnode hooks/codebuddy-install.js\nnode hooks/opencode-install.js\n\nbash test-demo.sh [seconds]\nbash test-mini.sh [seconds]\nbash test-macos.sh\nbash test-oneshot-gate.sh [state] [seconds]\n```\n\n新安装默认只把 Claude Code 和 Codex 标记为已安装并启用；其他 agent 默认未安装、未启用。正常启动时，Clawd 只会为 `integrationInstalled=true` 且 `enabled=true` 的 agent 自动同步 Claude / Codex / Copilot / Gemini / Antigravity / Cursor / CodeBuddy / WorkBuddy / Grok Build / Kiro / KiroCrew / Kimi / Qwen / ZCode / CodeWhale / Qoder / QoderWork / QwenWork / Reasonix / TraeCode / MiniMax Code hooks、opencode / MiMo Code / OpenClaw / Hermes plugins 和 Pi / OMP extensions。Settings Agent 页的 Install 会安装并启用该集成；Uninstall 会卸载 Clawd 管理的 hook/plugin/extension，并同时把该 agent 设为未安装、未启用。单独关闭 enabled 只会跳过启动同步并屏蔽事件/权限入口，不卸载用户已有 hooks / plugins / extensions；重新启用未安装 agent 只打开事件入口，不会写本机集成文件。手动安装命令主要用于调试、重装或远程部署。\nSettings 注册的自定义 HTTP Agent 是独立模型：`customApplications` 是注册真相，对应 `agents[customId]` 必须显式保持 `integrationInstalled=false`。注册只分配 ID 和状态入口，不安装 hook、不观察进程；v1 仅允许已注册且启用的 ID 向 `/state` 上报，`/permission` 永远不提供决定。删除或伪造的 `custom-` ID 必须直接拒绝，不能降级成 Claude Code subagent。\nCopilot CLI 同步走 `<COPILOT_HOME 或 ~/.copilot>/hooks/hooks.json`，marker-based 增量合并只接管含 `copilot-hook.js` 标记的条目，用户其他 entry / 其他 `hooks/*.json` 文件原样保留；hooks.json 或 `settings.json` 顶层 `disableAllHooks: true` 时 doctor 报 warning（不挂 Fix 按钮）。详见 `docs/guides/copilot-setup.md`。\n\n## Read These Docs\n\n- `docs/project/agent-runtime-architecture.md`：运行时架构、模块边界、启动与数据流、多 agent、permission bubble、终端聚焦和自动同步\n- `docs/project/theme-state-ui.md`：状态机、主题系统、settings、mini mode、素材规则、平台限制、待落地 UI 决策\n- `docs/project/release-process.md`：发版 checklist、release note 核对、tag 触发 GitHub 打包和资产确认\n- `docs/guides/copilot-setup.md`：Copilot CLI 自动同步说明、`COPILOT_HOME` 兼容性、手动配置备选模板\n- `docs/guides/dsh-setup.md`：DeepSeek Harness web profile 与桌面版的实验性 plugin 集成状态与普通审批集成\n- `docs/guides/state-mapping.md`：状态 → 动画权威表\n- `docs/guides/guide-theme-creation.md`：主题作者指南\n- `docs/guides/setup-guide.md`：安装、远程 SSH、各 agent 接入\n- `docs/guides/custom-agent-http.md`：自定义 HTTP Agent 的 state-only 接入合约和动态端口发现\n- `docs/guides/known-limitations.md`：用户向已知限制\n- `docs/guides/recap.md`：本地小结的指标口径、coverage、时区/DST、隐私存储与产品红线\n- `docs/guides/codex-wsl-clarification.md`：Codex / WSL 路径与 Node 说明\n- `docs/guides/guide-remote-ssh.md`：Remote SSH 用户流程、Codespaces 单会话 transport 与共享主机边界\n- `docs/guides/telegram-approval.md` / `docs/guides/feishu-lark-remote-approval.md`：远程审批设置与失败回退语义\n- `docs/guides/roam-fence.md`：自由漫游与可选围栏\n\n## Runtime Summary\n\n- HTTP hook / plugin 主路径：`src/server.js` → `src/server-route-state.js` → `src/agent-runtime-main.js` → `src/state.js` → IPC；本地 JSONL monitor 直接进入 `agent-runtime-main`，不经过 HTTP server\n- 权限主路径：`src/server-route-permission.js` → `src/permission.js`；本地 bubble、显式 permission automation 与可选 Telegram / 飞书 Lark 远程审批都可能产生真实决定\n- 桌宠的渲染/输入双窗口由 `src/pet-window-runtime.js` 统一创建和定位；浮层排序与 topmost 行为在 `src/floating-window-runtime.js` / `src/topmost-runtime.js`\n- `src/state.js` 生成的 session snapshot 是 Dashboard、HUD/Orbit 与可选通知/presence/mobile consumer 的共享合约，改字段必须检查所有消费者\n- `src/integration-sync.js` 为已安装且启用的 agent 异步同步 hooks / plugins / extensions；Codex official hooks 为 primary，JSONL 轮询保留为 fallback\n- Claude hook 恢复由 `src/claude-settings-watcher.js` 的目录 watcher + 低频只读巡检共同负责；repair 统一经过 `src/claude-hook-operations.js` 队列并复验，连续失败转 `manual-fix-required`。完整 gate、阈值与 source-missing 语义见 `docs/project/agent-runtime-architecture.md`\n- `src/agent-gate.js` 控制各 agent 的安装意图、启用状态、权限气泡开关和 wait-for-input notification 子开关\n- 设置系统主链路是 `src/prefs.js` → `src/settings-controller.js`（唯一写入者）→ `src/settings-store.js`；`settings-actions*` 负责校验和 pre-commit gates，`settings-effect-router.js` 负责 post-commit runtime effects 与广播\n- 启动时还会尝试自动安装 VS Code / Cursor terminal-focus extension，并初始化 updater\n- Remote SSH 通过 effective transport inspection 区分 ordinary parallel SSH 与 serialized transport；后者由 target-scoped coordinator 编排。远程部署只走 Settings，`scripts/remote-deploy.sh` 已 fail-fast 停用\n\n## Core Files\n\n更细的背景见 `docs/project/agent-runtime-architecture.md` 和 `docs/project/theme-state-ui.md`。\n\n| File | Responsibility |\n|------|------|\n| `src/main.js` | Electron composition root：生命周期、上下文组装与各 runtime / IPC 注册器接线 |\n| `src/server.js` + `src/server-route-state.js` + `src/server-route-permission.js` | HTTP 服务、端口发现、`/state` / `/permission` 路由 |\n| `src/agent-runtime-main.js` + `src/integration-sync.js` | local monitor / official hook 仲裁、Codex turn fence、按 gate 的集成同步 |\n| `src/state.js` | 状态机、多会话合并、优先级、自动回退、睡眠/DND |\n| `src/renderer.js` | 动画切换、SVG 预加载、眼球追踪渲染 |\n| `src/permission.js` + `src/permission-automation-policy.js` + `src/session-automation-coordinator.js` | 权限气泡、自动化策略、per-session 授权与决策回包；远程 client 由 `main.js` 注入 |\n| `src/pet-window-runtime.js` + `src/floating-window-runtime.js` + `src/topmost-runtime.js` | 双窗口 owner、浮层重排、z-order / fullscreen / focusability |\n| `src/update-bubble.js` | 更新气泡创建、测高、跟随桌宠定位，避让 HUD / permission stack |\n| `src/dashboard.js` + `src/dashboard-renderer.js` | Sessions Dashboard 唯一 owner：会话列表、别名编辑、终端跳转、几何持久化，以及同一页面的临时键盘模式 |\n| `src/dashboard-host.js` | Dashboard 普通宿主的平台封装：darwin/win32 用 `BaseWindow + WebContentsView`（无 `ready-to-show`），Linux 保留 `BrowserWindow` |\n| `src/dashboard-quick-mode.js` | 完整 Dashboard 的 1–9 键盘模式（**macOS/Windows only**）：quick 宿主、opacity/input parking、轮次栅栏与冻结数字映射；Windows 显式取消与页面失效的来源恢复在 `src/quick-select-origin-focus.js`，quick 宿主的退出清理挂在 `before-quit` |\n| `src/session-hud.js` + `src/session-hud-renderer.js` | 桌宠旁轻量会话 HUD、折叠行、点击跳转 |\n| `src/session-alias.js` | session alias key 规范化、TTL pruning、Kiro cwd scope |\n| `src/theme-loader.js` + `src/theme-runtime.js` | stateless 主题加载/消毒与唯一 active-theme owner；`waitForThemeReloadSettled` 完成信号 |\n| `src/official-theme-catalog.js` / `-download.js` / `-installer.js` / `-main.js` | 官方可下载主题：严格 catalog/cache、Electron `net.request` 流式下载、受限流式 ZIP 解压与 marker-before-rename、main owner/IPC/共享 `theme` lock |\n| `src/prefs.js` | 偏好 schema、load/save/migrate/validate，设置持久化入口 |\n| `src/settings-actions*.js` + `src/settings-effect-router.js` | 设置 validators / commands / pre-commit gates 与 post-commit runtime effects |\n| `src/settings-controller.js` | 设置系统唯一写入者 |\n| `src/settings-store.js` | 不可变 snapshot store |\n| `src/settings-ui-core.js` + `src/settings-renderer.js` + `src/settings-tab-*.js` | Settings shared UI state、侧栏/tab shell 与各页逻辑 |\n| `src/menu.js` | 托盘 / 右键菜单，串起设置、Dashboard、mini mode、更新入口 |\n| `src/mini.js` | 极简模式入场、滑动、peek、状态映射 |\n| `src/tick.js` | 主循环、鼠标轮询、眼球和 idle/sleep 逻辑 |\n| `src/drag-position.js` | 拖拽落点规范化与跨显示器钳制 |\n| `src/visible-margins.js` | 可视角色边距与 edge pinning 规则 |\n| `src/updater.js` | Git 模式 / `electron-updater` 双路径更新逻辑 |\n| `src/focus.js` | 终端聚焦 |\n| `src/hit-renderer.js` + `src/hit-geometry.js` | 输入窗口命中、拖拽、连击反应 |\n| `src/remote-ssh-runtime.js` | Remote SSH tunnel/ingress 状态机、ordinary health probe、serialized readiness 与重连 |\n| `src/remote-ssh-transport.js` + `src/remote-ssh-transport-coordinator.js` | effective transport inspection、pre-spawn admission、target ownership、drain barrier 与 quarantine |\n| `src/remote-ssh-deploy.js` | Deploy / Repair、身份事务、lease/fencing、wrapper、cleanup 与远端 Codex monitor mutation |\n| `src/remote-ssh-identity.js` + `src/remote-ssh-layout.js` + `src/remote-ssh-ingress.js` | 身份/布局真相与 profile 专属、nonce 校验的本地 ingress |\n| `src/remote-ssh-node.js` + `src/remote-ssh-shell-detect.js` + `src/remote-ssh-local-config.js` | 远端 Node/ shell 探测与本机 SSH config 入口 |\n| `src/remote-ssh-profile.js` | Remote SSH profile schema、校验、默认值和持久化规范化 |\n| `src/remote-ssh-ipc.js` | Remote SSH runtime / deploy / monitor orchestration、intent policy、IPC 状态与进度广播 |\n| `src/remote-ssh-quote.js` | Remote SSH 终端命令与跨平台 shell quoting helper |\n| `agents/registry.js` | agent 注册表 |\n| `agents/codex-log-monitor.js` | Codex JSONL fallback 轮询 |\n| `agents/gemini-log-monitor.js` | legacy Gemini session JSON 轮询器；当前 Gemini hook-only 路径不启动 |\n| `hooks/dsh-install.js` | DeepSeek Harness immutable managed bridge generation、ownership verify、web 与 desktop 两个 profile 的安装 / 修复 / 卸载编排 |\n| `hooks/kirocrew-install.js` + `hooks/kirocrew-store.js` | KiroCrew state-only gateway hooks、upstream-compatible mutation locks and atomic private store writes |\n| `hooks/kirocrew-hook.js` + `hooks/kirocrew-command.js` | KiroCrew state bridge and exact command-shape ownership classifier |\n| `hooks/dsh-notices.js` | DeepSeek Harness 常驻提示的存储与规则（按 profile 的 `notices-<profile>.json`） |\n| `hooks/clawd-hook.js` + `hooks/copilot-hook.js` | Claude Code / Copilot CLI 状态上报脚本 |\n| `hooks/install.js` | Claude hook 注册 / 卸载 |\n| `hooks/auto-start.js` | Claude `SessionStart` 自动拉起 Clawd 的 hook |\n| `hooks/codex-hook.js` / `hooks/codex-install.js` | Codex official hooks 状态与权限审批、安装 / 卸载 |\n| `hooks/cursor-install.js` / `gemini-install.js` / `antigravity-install.js` / `kiro-install.js` / `kimi-install.js` / `qwen-code-install.js` / `codewhale-install.js` / `codebuddy-install.js` / `workbuddy-install.js` / `opencode-install.js` / `pi-install.js` / `openclaw-install.js` / `hermes-install.js` / `qoder-install.js` / `qoderwork-install.js` / `reasonix-install.js` | 各 agent 集成安装逻辑 |\n| `hooks/opencode-family-managed-generation.js` | OpenCode 用户可写托管 generation（canonicalizer、bundle/manifest、stage/promote、target owner record、target-scoped lock）；纯 Node 内置依赖，不进入 Remote SSH `HOOK_FILES` |\n| `hooks/opencode-family-entry-ownership.js` | OpenCode-family plugin entry 的 string/tuple 解析、跨平台路径等价、所有权分类与重复/options 冲突规划（纯逻辑、可注入 fs） |\n| `hooks/opencode-family-install.js` / `hooks/opencode-family-jsonc.js` | 家族注册器：`managedMaterialization:true` 走托管 generation 事务 + 共享 entry planner；`false` 保持 legacy broad-basename register/unregister |\n| `src/doctor-detectors/opencode-managed-inspector.js` | managed OpenCode Doctor inspector（ownership/manifest/生成结构、Fix policy、masked supplementary warning）；接受注入 fs |\n| `hooks/workbuddy-hook.js` | WorkBuddy state + Notification command hook；无 session_id 时返回合法 stdout 后丢弃事件 |\n| `hooks/grok-hook.js` / `hooks/grok-install.js` | Grok Build state + Notification command hook；写入 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json`；`env` marker `CLAWD_GROK_HOOK=v1` 所有权；无 session id 时丢弃；不注册 `/permission` |\n| `hooks/zcode-hook.js` / `hooks/zcode-install.js` | ZCode 状态 + 阻塞式 PermissionRequest hooks（`hookSpecificOutput` 决定 / `{}` 无决定）、`hooks.events.*` 按事件超时增量注册与 Claude-imported Clawd hook 清理 |\n| `hooks/qoder-hook.js` | Qoder state-only 状态上报脚本（Phase 1，stdout 恒为 `{}`） |\n| `hooks/minimax-hook.js` / `hooks/minimax-install.js` | MiniMax Code state-only 本地插件：整目录 install/uninstall（`<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/`），CLAUDE 格式 hooks + exec-form args，10 事件无 PermissionRequest/Notification，`.clawd-managed.json` 结构化所有权凭据、fail closed |\n| `hooks/codex-remote-monitor.js` | 远程 Codex JSONL 轮询并通过 SSH 隧道回传（含 token_count 订阅配额的 metadata_only 上报） |\n| `hooks/claude-statusline.js` / `hooks/antigravity-statusline.js` | 各 CLI statusline 适配器：渲染状态行 + 把订阅配额（rate_limits）以 metadata_only POST 上报；Claude 版支持远程部署（`CLAWD_REMOTE=1` 前缀）与 `--chain` 串联模式（原 statusLine 对象保存在 `~/.claude/hooks/clawd-statusline-chain.json`，卸载时恢复） |\n| `extensions/vscode/extension.js` | VS Code / Cursor 终端 tab 聚焦辅助扩展 |\n\n## Constraints\n\n- `agents/registry.js` 的 capabilities 是权限、subagent、session-end 等路由/gate 的权威来源；不得另写名单代替 capability 判定。但 permission automation eligibility 由更窄的 `isKnownPermissionAgent()` 显式判定（`KNOWN_PERMISSION_AGENTS` + explicit opencode-family membership），不得从 `permissionApproval` 自动派生或合并回 registry capabilities\n- 小结的指标能力例外地只认 `src/recap-metrics.js` 的显式逐 Agent 口径，不得从 registry capabilities 或标准化 event 名推导。只统计已通过 gate、Codex source/replay fence、subagent 与完成仲裁的 accepted activity；DND 继续记录且不切 coverage，suspend/退出/关闭记录才切。`null` 是不支持，绝不能渲染或汇总成 `0`\n- 小结持久层固定为 `~/.clawd/recap-v1/` 下 14 个本地日的最小 HMAC 小票与 400 个本地日的 daily/coverage；不得落 prompt/回复/命令/工具内容、路径/项目、原始 event/session/profile/turn/tool ID，不得增加网络、导出或分享。首版不做 Token、金额、模型、推理强度、Skill、人的工作/编码时长、streak、峰值/最长项、排行榜或生产力评分\n- Claude Code / CodeBuddy 的阻塞式权限审批走 `POST /permission` HTTP hook；普通状态事件走 command hook（CodeBuddy command hook 对所有事件输出 `{}`，不做工具或权限决定）\n- permission automation（off / auto-tools / unattended）和 per-session grant 会在 bubble 渲染前产生真实 allow/answer。agent/family eligibility 是显式白名单；工具分类则因 mode/adapter 而异：auto-tools 对 Claude/Qwen 的未知 built-in fail closed，但其他已知 adapter 不都使用逐工具白名单，unattended 还会有意自动放行可作 Allow/Deny 的未知请求。新增 agent、工具或交互类型必须审查 policy + tests，不能从 `permissionApproval` 推导资格或笼统假设“未知请求都会 defer”\n- Telegram / 飞书 Lark 与本地 bubble 是并行决策通道。远程通道超时、断连、未配置或发送失败不得产生远程决定，更不得转成 deny；有本地 bubble 时请求继续 pending，只有 remote-only 且所有可用 client 都无决定时，整体请求才 no-decision 并回到 agent 原生流程\n- WorkBuddy 通过当前 `~/.workbuddy-ai/settings.json`（旧版兼容 `~/.workbuddy/settings.json`）的 Claude Code 兼容 command hooks 做 **state + Notification only** 集成：不注册 `/permission`，审批始终留在 WorkBuddy 原生沙箱与 GUI；无 `session_id` 的事件返回合法 stdout 后直接丢弃。当前只支持 macOS/Windows 桌面应用，没有已验证的 Linux/WSL CLI；不要把裸 `Electron` 当 WorkBuddy 进程。\n- Grok Build（agent id `grok-build`）通过 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json` 的 Claude Code 兼容 command hooks 做 **local / main-session / state + Notification only** 集成（Phase 1）：stdin 为 camelCase（`sessionId` / `toolName`），`hookEventName` 是 camelCase key + snake_case value，`hook_event_name` 是 snake_case key + PascalCase value。**逐 handler 的 `env` 结构化 marker `CLAWD_GROK_HOOK=v1` 是唯一所有权凭据**；文件名/substring（含 `grok-hook.js.backup`）只用于诊断告警，永不授权改写或删除。安装/卸载只增删含该 marker 的 handler，保留 unknown 顶层键、其他 event、foreign matcher group 与 sibling handler；没有 marker 的既有文件一律原样拒绝。`SessionEnd` 不写 `timeout`（继承 Grok 1.5s teardown），其余事件 5s。Windows 用 `windowsWrapper:\"portable\"` 形态，不得用 `&` / `-EncodedCommand` / 自造 `shell` 字段。Grok 没有 `PermissionRequest`，不注册 `/permission`，adapter 始终输出 `{}`。子代理事件（`subagentType`）直接丢弃；不注册 `SubagentStart` / `SubagentStop`。Grok 默认会扫 `~/.claude/settings.json`，所以 `clawd-hook.js` / `cursor-hook.js` / `auto-start.js` 只在非空官方 `GROK_HOOK_EVENT` 下直接退出，`GROK_HOME` / `GROK_SESSION_ID` / 无关 `GROK_*` 不得触发。`Stop` 只有精确 `reason === \"end_turn\"` 且无 background task / session cron / `stopHookActive` 才算完成，其余由 adapter 本地判定；`channel_closed` / `shutdown` 等 session-end 形态的 Stop 在 fence 之前丢弃。turn 顺序由 `src/grok-turn-fence.js` 的 bounded in-memory fence 仲裁（晚到旧 turn、重复 terminal、continuation Stop、Stop→StopCancelled 纠正）。不进入 subagent / WSL / Remote SSH / startup recovery / terminal focus / quota / context / recap turn 指标。`~/.grok/hooks/clawd.json` 是未发布的 PR preview 路径，只做 warning，不得自动接管或删除。\n- Codex 的阻塞式权限审批走 official `PermissionRequest` command hook：hook 脚本长连接 `POST /permission`，只允许 stdout 返回 sanitized `behavior/message`，`updatedInput` / `updatedPermissions` / `interrupt` 必须 omit。权限模式默认 `auto`（旧 `native` 规范化为 `auto`），仅准确本机 session/turn 的人工 reviewer 证据可进 Clawd；未知、自动 reviewer、MCP/app、远程/WSL 均 no-decision；唯一例外是远程/WSL（路由 reason 为 `nonlocal`）的 Bash/apply_patch 在全局自动放行会立即 allow 时（`wouldAutoAllowPermission`：非 reminder hold、非会话覆盖、非交互子代理）由 Clawd 直接放行（#1186），路由后若设置已变则 no-decision，绝不弹气泡。`intercept` 是显式接管；升级时旧 `intercept` / `native` 统一迁到 Auto 一次，之后重新选择的 Intercept 会保留。不得用全局 config、其他会话或旧回合推断当前请求的审批方；证据不足时返回 no-decision，交还 Codex 原生流程。\n- hook 脚本只允许依赖 Node 内置模块，以及同目录 `hooks/` 下、且登记在 `src/remote-ssh-deploy.js` 的 `HOOK_FILES` 部署清单中的纯 Node helper（如 `server-config.js` / `shared-process.js` / `json-utils.js` / `codex-originator.js` / `codex-subagent-fields.js` / `context-usage.js` / `state-payload-size.js` / `quota-bucket.js` / `claude-rate-limits.js` / `codex-rate-limits.js` / `antigravity-context-usage.js`）；manifest-consistency 测试强制检查依赖闭包，新增 helper 必须登记\n- CJS hook 脚本需要稳定终端 PID 时，必须复用 `hooks/shared-process.js` 的 `createPidResolver()` 及其 lifecycle context；不要复制进程树 walk 或用 `process.ppid` 简化。`getStablePid()` 只是 opencode-family plugin 的内部 resolver\n- `agentCmdlineCheck` 只对进程名在 `agentCmdlineNames` 里的祖先进程运行，默认是 `DEFAULT_AGENT_CMDLINE_NAMES`：`node` / `node.exe`，加上 Linux 上没设过 `process.title` 的 Node 在 `ps -o comm=` 里的名字——Node 23.8–25.4（含全部 24.x）把主线程命名为 `MainThread`、≥ 25.5 为 `node-MainThread`，Linux 报的进程名就是主线程名。传入 `agentCmdlineNames` 会整体替换默认值：只想加名字的 adapter 必须在选项里直接写成 `agentCmdlineNames: new Set([..., ...DEFAULT_AGENT_CMDLINE_NAMES])`（如 ZCode；可以跨行，方括号里只能有普通字符串字面量和 `...DEFAULT_AGENT_CMDLINE_NAMES` 本身，不能有注释或其他表达式；简写属性、先存进变量，或任何不是这个形状的提及（包括注释里的）都会被判不合格，因为文本检查无法核对），只有刻意只探测非 Node 宿主的（WorkBuddy 的 `electron`）例外，`test/shared-process.test.js` 会扫描 `hooks/*.js` 检查\n- opencode v1 权限不走 `permission.ask` hook，而是 event hook + reverse bridge；v2 走 `ctx.permission.hook(\"evaluate\")` 的阻塞 HTTP 响应\n- OpenCode / MiMo v1 原生问题走独立本地 `/question` 长轮询，不复用审批回包；遵循全局 permission bubble 开关与 family 单 agent 开关。只接受已核实的 v1 来源、版本和问题 schema，提交前用原 SDK client 复核精确 request/tool/session，答案保持有序 `string[][]`；无决定返回 204 交还原生。OpenCode 由原生 reply RPC 的 `true` / 404 判定提交结果，MiMo 仍需精确 `question.replied` 答案匹配。子会话问题、OpenCode v2、Remote SSH 及未审核 agent 保持原生；不要改 Claude/Hermes wire 或托管 generation 依赖集合。详见 `docs/guides/agent-questions.md`。\n- opencode-family v1 插件经 `ctx.client` 连回宿主时，主机为通配监听地址（`0.0.0.0` / `[::]`）就按次改用 `127.0.0.1` / `[::1]`（不改宿主共享的客户端配置；非通配地址保持原调用形状）。默认 TUI 走进程内 fetch；`opencode serve` / `web` 下这是对监听地址的真实 HTTP 请求，受宿主进程里的 `HTTP_PROXY` / `NO_PROXY` 影响，而通配地址不会自动绕过代理。桥接回复失败返回 `{ok:false,status,error}`（`status` 为上游状态码，缺省 0）。\n- OpenCode 2.x（npm `@opencode/cli`，issue #1039）由 `hooks/opencode-plugin-v2/` + core.mjs 内 `createOpencodeFamilyPluginV2` 承接：installer 在同一 generation 内额外物化 `opencode-plugin-v2/index.mjs`（v1 四文件、v2 五文件；目录 specifier 解析 index.mjs、无需 package.json，2.0.15 实测），并把它写进 **`plugins` 键**，同时清理 Clawd 自有的旧 `plugin` 条目；用户条目、tuple/options 和 v1 行为保持不变。未被 Clawd 纳管的未知 `plugin` 条目仍只报 loader WARN；v1 对未知 `plugins` 键的静默丢弃只在 **1.18.16+** 成立——1.18.15 及更早会以 `Unrecognized key: plugins` 拒绝整个 config（anomalyco/opencode#41312，2026-08-08 起才忽略未知顶层键），因此 `plugins` 写入由宿主探测决定（`hooks/opencode-host-detect.js` 三态：探测到 v2 才写；探测到 v1 不写并清扫 owned 残留；探测失败不碰该键；`CLAWD_OPENCODE_HOST` 环境变量可钉死结论，Doctor 在无 v2 宿主时不要求 v2 条目）。v2 插件是零 import 纯对象 `{id, setup}`（v2 loader 拒绝函数 default export，`@opencode/...` 裸包名无插件本地 node_modules 不可解析），事件经 `ctx.event.subscribe()`（`session.step/tool/execution.*` 词汇完全换代，未知事件一律忽略），cwd 取事件信封 `location.directory`，标题走 `session.renamed`，context usage 走 `session.step.ended` 的 step tokens（`session.usage.updated` 是 session 累计计费值，不能当占用率）。权限走 **`ctx.permission.hook(\"evaluate\")` 阻塞长连接 POST `/permission`**，决定就是 HTTP 响应体 `{decision: allow|always|deny}`（服务端按 `hook_source === \"opencode-plugin-v2\"` 路由到 v2 阻塞子分支），只有 `200` + 身份头 + 合法 JSON 才采纳决定，204/超时/断连/非 200/任何错误都不改 effect 回原生 ask UI；配置 allow 也进 hook 但绝不降级；单条 shell 命令以 `tool_input.resource` 传输，服务端 v2 分支会为其别名出 `command` 以接入破坏性操作提醒（`mapOpencodeV2ShellResource`，非 shell 工具不映射；全字符串的多 resource 以换行合并作扫描别名）；resources 原样整组转发（对象转 JSON 字符串），不做条数/长度截断，唯一边界是整 body 超 512 KiB 时跳过转发。\"Always allow\" 无宿主持久化 API，用插件内 per-session 内存规则（随常驻 service 生命周期，气泡对 v2 使用单独文案说明关闭/重开终端不会撤销）。插件跑在常驻共享 service（daemon）：`source_pid`/进程树不可信故**整组省略**（终端跳转对 v2 降级），安装/更新后需 `opencode service restart`。`ctx.permission.hook()` 按上游 v2.0.15 类型返回 `Promise<Registration>`：本实例 dispose（setup 返回的 cleanup，宿主也会在插件 scope 关闭时调用）会调用 `registration.dispose()`，注册 Promise reject 只记日志不影响事件订阅。事件订阅**不等待** hook 注册（注册挂起/reject 时状态上报照常），reload **不等待**上一代注销完成；本实例清理先同步完成本地清理（标记 disposed、abort 订阅、身份恢复）再去注销 registration，注册 dispose 有约 2s 上限、超时只记日志，注册未完成就被取代则在注册完成那一刻立即注销，不残留活 hook。上游 v2.0.15 的 trigger 对同名 hook 依次调用每个仍注册的回调、共用同一个可变 event，而我们的注销是异步的，所以 reload 窗口内旧回调可能仍被调用：已退役实例的回调入口检查 `instance.disposed` 后直接返回，不 POST、不改 event。每个 ask 各自转发（`source.id` 是工具调用级、不是 ask 级，同一工具调用会发出多个不同 ask，如 external_directory + edit），不做内容去重。config 顶层重复 `plugins` 键按歧义处理：Doctor 报 `config-corrupt` 不抛异常，register/卸载在首次写入前中止（v1 宿主 sweep 只告警并跳过），v1 `plugin` 键行为不变。v1 1.18.31 tuple 契约、generation 布局、owner/lock 语义不变；`inspectGeneration` 把历史 4 文件集接受为合法 owned-stale 形态以便迁移。真机证据与降级项见 `docs/investigations/opencode-v2-e1-evidence.md`\n- OpenCode 的 plugin 注册不再直接指向打包/源码目录：`agents/opencode-family.js` 的 `managedMaterialization:true`（OpenCode true / MiMo 本次 false）gate materialize、ownership classifier、managed Doctor 与 generation cleanup。开启后 register 必须在目标 home 下维护 `<home>/.clawd/integrations/opencode-family/opencode/homes/<configDirHash>/generations/<bundleHash>/` 的内容寻址 generation（OpenCode v2 当前五文件，历史 v1 四文件），同一 generation 可同时物化 v1/v2 入口文件，但不因此在配置中注册两个键；探测到 v2 宿主时只把 `opencode-plugin-v2` 入口写入 `plugins`，并将 `plugin` 键仅用于清理 Clawd 自有旧条目；v1 宿主和探测不到版本时保持原有 v1 注册路径；bundle allowlist 固定为 `<agent>-plugin/index.mjs` / `<agent>-plugin/package.json` / `opencode-family-plugin/core.mjs` / `opencode-family-plugin/session-ids.mjs` / `opencode-plugin-v2/index.mjs`（v2）。owner record（`owner.json`，literal `clawd-on-desk.opencode-family.target`）与 target-scoped `mutation.lock/`（独立 literal `clawd-on-desk.opencode-family.target.lock`）是所有权与 app-present 真相；lock 被持有时不并发写：interactive Install/Repair/CLI/Uninstall/About cleanup 只做一次短而有界、可注入 delay 的重试，startup automatic 不等待直接 skipped；合法且超时 2 倍以上、PID 明确 ESRCH 才允许 atomic quarantine 接管，corrupt/foreign/live/EPERM 一律不接管；release 只删自己 token 的 `lock.json` 与随后为空的精确目录，禁止 recursive cleanup。owner 的 `activeSourceMarker` 必须是 `<activeSourceRoot>/<pluginDirName>/index.mjs`（共享 canonical 身份、Windows 折叠大小写）且为 regular file，目录/dangling/错 plugin 目录/root 不匹配都不算 live。同一 target 的 source owner 冲突（marker 仍存在）一律 `owner-conflict`，不得来回改 config；旧 owner 的源码 marker 已不存在时，新 source 必须在锁内重读并原子接管 owner（config 已 current 也不例外），否则残留死 owner 会让托管 plugin 永久 inert。锁内若 config 与当前 source owner 都已被并发操作收敛，则本次零 mutation 返回 skipped。lock release 失败不得掩盖结果：成功保留 status 并附 warning + 精确 lock path 的 residualPaths，已有 primary error 时保留原错误。basename 本身永不构成所有权；copy 到 managed layout 外的完整 generation 因缺少对应 owner record 而 inert，只有 verified-current-copy 可 Repair。tuple 契约固定为 OpenCode 1.18.31 实测的 `[specifier, optionsObject]`（隔离 `opencode debug config` 证据：第二项必须是普通对象，数组/字符串第二项会被宿主拒绝）；重写只替换 `plugin[index][0]`，options 值级保留，绝不写回嵌套 tuple，malformed array 原样保留。`options.pluginDir` 仍是 test-only expected-canonical override（跳过 generation/manifest/boundary，但不跳过 ownership/唯一 entry/read-back），`resolvePluginDir()` 仍返回 source。新建文件按当前用户普通写权限落盘：不得加 readonly/deny-write ACL，不得用 `W_OK`/`r+`/INIT 日志/session 活跃做健康门禁。Uninstall 以“活动注册是否移除”为提交依据（`registrationRemoved` false/null 阻止 Settings 提交，undefined 沿用 legacy status），残留 generation 只产生 warning；清理有效 generation 时必须先在同一 `generations/` 内原子改名为非 canonical `.cleanup-*` 再递归删除，删除失败不得占住原 hash 槽。兼容旧版本留下的半残 canonical 目录时，只允许在 owner 已 released、bounded history 精确证明该 canonical entry、且配置无活动 Clawd entry 的条件下，把它原子隔离为 `.recovery-*` 后重新物化；active/foreign/unproven/canonical-in-use 一律继续 fail closed，绝不原地覆盖或修补可疑 bytes。托管 core 的 orphan inert gate（`evaluateManagedLayoutGate`）必须在 `resetDebugLog()` / PID walk / bridge / handler 注册之前，owner marker 缺失、损坏、agentId 不匹配或 `activeSourceMarker` 不存在时返回空 handler；source-direct 模式保持原行为。MiMo 保持 broad-basename register/unregister/Doctor 契约不变。\n- Pi 通过 `~/.pi/agent/extensions/clawd-on-desk` 的 global extension 推送状态；Clawd 对 Pi 是 **state-only**，不接管权限、不弹权限气泡，也不把 Pi 的默认 YOLO 流程改成手动确认\n- OMP (oh-my-pi) 通过 `~/.omp/agent/extensions/clawd-on-desk` 的 global extension 推送状态，agent id `omp`，对 Clawd 同样是 **state-only**。它是 Pi 的 fork（包名 `@oh-my-pi/pi-coding-agent`），所以 `hooks/omp-extension.ts` 刻意与 `hooks/pi-extension.ts` 保持逐行对齐（只差 package import、core import 与函数名），进程树遍历与终端识别不得各自漂移；OMP 独有的差异全部收在 `hooks/omp-extension-core.js`。**完成必须走 `session_stop` 候选 + 终态 `agent_end` 提交的两阶段协议** —— `session_stop` 先保留主会话边界，OMP 再汇总所有 extension 的续跑请求；只有后续 `agent_end.willContinue !== true` 才向 Clawd 发完成。不得直接把任一事件单独映射为完成：仅用 `agent_end` 会把 subagent/调度边界误报为完成，仅用 `session_stop` 则会早于 extension 续跑判定。`session_switch` / `session_branch` 要为被切走的旧 session 补发一条合成 `SessionEnd`，否则 Clawd 会留下一条再也不会有人上报的活动行。session id 命名空间是 `omp:<raw>`，且必须始终带 `session_title`（多个交互式会话合法地共用同一个 cwd，缺标题会让列表和跳转目标无法区分）。安装器遇到社区桥接 `~/.omp/agent/extensions/clawd-on-desk-omp.ts` 时必须 fail closed 跳过：两者上报同一批事件，同时存在会双发。当前 `assets/source/agent-icons/omp.png` 是 `fallback: true` 的占位 π 字形，不是 OMP 官方品牌素材，拿到授权素材后应替换\n- DeepSeek Harness 首发是 **web profile / Windows-first experimental / plugin-only**；rc.6 已于 2026-08-29 完成 macOS / Windows x64 源码运行的真实 API-backed session/approval smoke（#962）；rc.2 Windows packaged-app 证据仅覆盖安装、web boot 与直接 bridge client 的 state/Allow/Deny 往返（#938），不得合并宣称 rc.2 安装包的真实 API 会话已验证。Clawd-managed in-process plugin 监听公开 `session/created`、`session/event`、`session/disposed`、可选 `sessionProjections.onChanged` 与 blocking `approval/request`；标题和上下文仅作为会话元数据同步，不占用生命周期 seq。状态按 session FIFO 上报并携带上游 seq；Clawd 不读取 `$DSH_HOME/storages` projection。普通审批进入独立 DSH `/permission` adapter，只支持人工 Allow Once / Deny；204 / 断连 / DND / disabled 都由 plugin `next()` 交还 DSH 原生 web answerer。`ask_user_question` 始终留在 DSH 原生 provider；DSH 不进入 `KNOWN_PERMISSION_AGENTS`，auto-tools / unattended / per-session grant 全部 DEFER。安装器通过官方 `dsh plugin --profile web add/remove` 管理 immutable marker-owned generation，foreign 同名包 fail closed；版本放行改成按 **小版本族（major.minor）**。维护两张表：一张是唯一写出具体版本/npm artifact/integrity 的已验证 artifact 清单（优先 `@deepseek-ai/dsh@0.2.0-rc.2`（integrity `sha512-EAJ3gPNcVt/uv8X19PMm9NkVhWgT7xXNMk0UKCVm+IQ5rpSQOcsMUa0HWlnYYVybKMsccjcRB21vVVsaXQ6IdA==`，2026-10-04 已做静态接口核对，并在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证了用 Clawd 安装器装出的 generation 的启动同步换代、会话状态、HUD 标题/上下文、Allow/Deny 与消息上的失败标记；其 `tool/result` 把失败标记放在消息 `message.isError` 而不是内容项上，bridge 新旧两种位置都认），并保留 `@deepseek-ai/dsh@0.1.5-rc.3`（integrity `sha512-c0W6Xqc4ChjFcCJkbzPeIxZQdnbKqe+QAcJzWGtogg0ZzsnZRcw3vopMyZ5oZU6E2fmyqGcyDR1sBeiCH4yHcg==`，2026-09-27 已在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证启动同步安装、会话状态、HUD 标题/上下文与 Allow/Deny）、`@deepseek-ai/dsh@0.1.5-rc.1`（integrity `sha512-rmNmzQCg3oIc1z8xH7izRSOuy1TNzq+/NILyfM+7e8DKOyV+yBtg47WEsqR2SiIe1ATec3L/rUa1YhIcfQ2XEg==`）、`@deepseek-ai/dsh@0.1.1-rc.2`（integrity `sha512-UP1UIh6q3Gme/yXRn/QL2P8IsVlv8Shpg22TRJIZPsCRWLm4CBiA1MUvXmJAfsOEETBMLAl+xWPtFw6ICsN3wg==`）与 `@deepseek-ai/dsh@0.1.0-rc.6`（integrity `sha512-brpZfED7ieRa2PQ5tUxMhHrM1pb2CmKFVM/f6yMULBDMicahk+Z2OsHgTwTDnoiZm23Ftu9rQz0NN4pflaoJcg==`）），一张是族表（`0.2` 下限 `0.2.0-rc.2`、`0.1` 下限 `0.1.0-rc.6`）。host 版本经严格解析（拒绝前导零、空预发布标识与 build 元数据）通过、major.minor 命中族、且不低于该族下限即放行；同一族内不同 host 版本共用一个 generation，出现新的小版本必须重新验证并新增一个族。旧的精确 `=<version>` marker 仍按原 range 核对哈希，新 generation 一律写族 range；Install/Repair 按 host 版本所在的族选择目标契约，Uninstall / 手动 npx 命令在 marker 版本已列入清单时钉它自己的 artifact，否则钉同族版本最高的已验证 artifact（无 CLI 且无 marker 时用首选族最新的并记为 assumed）；加锁前后比较的是实际检测到的 host 版本，不看族。DSH 的 `metadata_only` 标题/上下文旁路必须核对目标会话的 `agentId` 确为 `deepseek-harness`，撞名的其他 agent 会话直接丢弃。`47f9438` 仅是源码调查基线，不代表任何 tag/commit 映射。\n- DSH 每个 canonical `DSH_HOME` 的 mutation lock 只有在 owner/schema/token/PID/timestamp/owner-recorded operation timeout 合法、超过该 owner timeout 两倍、且 OS PID probe 明确为 `ESRCH` 时才允许 atomic-rename takeover；live、`EPERM`、unknown、corrupt/foreign owner 一律拒绝并返回精确 lock path。canonical lock 的 owner write/release 禁止 recursive cleanup。无全局 CLI 时生成的手动 npx generation 必须先在同一锁内写 owned reference，手动 add/remove 命令必须显式 pin shell-quoted canonical `DSH_HOME`；malformed/foreign/concurrently replaced reference 一律 fail closed 并保留 generation\n- DSH 桌面版支持（#1119）与 web 共用一个 agent id `deepseek-harness`：web profile 和 DeepSeek Harness 桌面版是两个承载方、各自一个 profile（桌面版是 `$DSH_HOME/profiles/desktop`），但在 Settings 和 Doctor 里仍是**一行**，显示名 `DeepSeek Harness (experimental)`，一次排队操作先 web 后 desktop、一边失败不影响另一边；安装只要有一边核实健康即成功（另一边失败变 warning + 常驻提示），卸载要所有 Clawd 注册都没了才成功。桌面版查找：macOS 用 `/Applications` 或 `~/Applications/DeepSeek Harness.app` 里自带的 `Contents/Resources/runtime/cli/bin/dsh`；Windows 按用户安装，从 `HKCU` 卸载项（显示名以 `DeepSeek Harness ` 开头）与 `%LOCALAPPDATA%\\Programs\\DeepSeek Harness` 找 `resources\\runtime\\cli\\bin\\dsh.cmd`，注册表用 PowerShell 读 UTF-8 JSON、不用 `reg.exe`；Linux 不支持桌面版。静态版本来自 `Info.plist` / 卸载项 `DisplayVersion`，真正动手前跑一次启动器 `--version` 核实。桌面版**永不用 npx**，手动 npx 命令与 manual reference 只属 web。每边角色是 `mutable` / `diagnose` / `not-applicable`：桌面版没装、或 profile 从未初始化（桌面版没打开过）→ 不适用并提示打开一次；foreign 同名包、文件读不了、清理残留、注册查不清、版本不支持、装了不止一个桌面版（`multiple-desktop-installs`）、桌面版找不到但注册还在（`carrier-unavailable`）、桌面版查不清（`desktop-unverifiable`）→ 只报告不动手。启动同步在集成已安装且启用时会把插件加进已初始化的桌面版 profile；桌面版开着也会加载新加的插件，只有插件更新（换了 generation）后要重启。常驻提示在 `hooks/dsh-notices.js`，按 profile 存 `notices-web.json`/`notices-desktop.json`，四种 kind（`restart-required`/`first-install`/`manual-command`/`failed-target`），写不进去只算 warning；提示显示在 Settings → AI Coding Tools 里这一行下面。Doctor 一行详情 `web: …; desktop: …`，状态取适用边里最差，只要有一边能尝试修复且不健康就给修复按钮（`src/doctor-detectors/agent-integrations.js`）。插件在 DSH 里被关掉（依赖在、bundle 行没了）时 `plugin add` 不会重开：显式修复先 remove 再 add（add 前先清掉上游 remove 留下的自有链接，Mac 是符号链接、Windows 是 junction），按 profile 记 `repair-operation-<profile>.json`，中断后下次显式修复续做，启动同步只报 `plugin-disabled-in-dsh`。`generations/` 两边共享，任一边有未处理状态（检查记录、清理残留、坏修复记录或 manual reference、读不了的 profile、符号链接 profile 目录）时清理暂停但不挡安装，卸载残留进 warnings。检查记录按 profile：web `inspection-required.json`、桌面版 `inspection-required-desktop.json`。`plugin add/remove` 写命令两边都超时 300 秒（web 原 120 秒），比上游写锁等待长。上游 `dsh plugin remove` 只清 `link:` 清单和锁、`node_modules` 链接会留下，Clawd 卸载自有插件时确认归属后清掉。Windows 静态查找是同步代码、不起进程，只读异步快照：启动时（不管 DSH 是否启用）、打开 Doctor 前、Agents 页手动扫描时刷新，没快照时桌面版显示\"查不清\"。安装检测把\"找到桌面版\"也算装了 DSH（`src/agent-installation-detector.js`）。桥接插件在 apply 时读 `ctx.profileContext?.name`，只有 desktop profile 才在 state / 审批载荷里带 `dsh_carrier: \"desktop\"`（metadata 不带；web 或未知 profile 一律不带）；Clawd 只接受 DSH + `dsh-plugin` + 本机 + 非 WSL 的载体，按生命周期覆盖或清除、不粘滞，权限 fallback entry 与快照（含签名）都带上它。点击桌面版会话时 `getSessionFocusTarget` 在 darwin/win32 返回 `dsh-desktop`（`dsh://open`），分派先 `shell.openExternal(\"dsh://open\")`，被拒绝再按 `discoverDshDesktopSync({ requireUniqueApp: true })` 的兜底要求唯一安装启动界面程序（macOS `open <appRoot>`、Windows 启动 `<appRoot>\\DeepSeek Harness.exe`，去掉 `ELECTRON_*`/`NODE_OPTIONS`，不用 CLI 启动方式；两份真实路径不同的有效安装视为有歧义，只要还有核实不了的候选也不自动启动，同一份安装的符号链接只算一份）；只能打开应用窗口、不会切到具体对话，web 会话仍不可跳；桌面版启动时会重新打开上次的对话，Clawd 只在这个对话有了动作（提问、工具调用、审批）之后才把它放进 Session HUD（`awaitingActivity` 并入快照 `hiddenFromHud`，但不关跳转；与 Kimi Code 共用同一个标记），Dashboard 照常列出、按钮照常可跳；2026-10-05 macOS 26.6.2 与 Windows 11 x64 源码运行真机验证（桌面版 `0.2.0-rc.2`）：别的窗口在前、最小化、关窗后，点击都经 `dsh://open` 把窗口带到最前；协议打不开时的启动兜底只有单元测试。真机证据：2026-10-04 macOS 源码运行（Clawd `ac64d726`，桌面版 `0.2.0-rc.2` + 全局 `@deepseek-ai/dsh@0.2.0-rc.2`）验证了启动同步把插件装进桌面版（与 web 共用 generation）并出现\"已装进桌面版\"提示、Doctor 一行两边正常，桌面版真实会话的 Allow 建成文件、Deny 后文件内容和 mtime 不变且 Clawd 显示 `PostToolUseFailure`，\"知道了\"后提示消失，改 bridge 源码（同 Clawd 版本）后启动同步两边报 `generation-conflict` 并提示去 Doctor 修复、修复把两边换到新 generation/删旧/出现\"重启桌面版后生效\"、重启后事件来自新宿主进程，设置页卸载后两边依赖与 bundle 行都没了、上游残留链接被清、generation 删除、两边提示清空，再在设置页安装两边都重新装上、桌面版重新出现\"已装进桌面版\"（\"经设置页首次安装\"因此已覆盖），开着 DND 时桌面版的工作区外写文件不弹 Clawd 气泡、返回 no-decision、桌面版弹自己的原生审批框、批准后文件建成且事件照常到达。2026-10-04 Windows 11 x64 经 SSH 用 Node 直跑安装器代码（管理员会话，桌面版在 `%LOCALAPPDATA%` 按用户安装 `0.2.0-rc.2`、全局 dsh `0.1.0-rc.6`，web 在 0.1 族、桌面版在 0.2 族）：PowerShell 读注册表找到桌面版、静态模式无快照时报\"查不清\"且不起进程、自带 `dsh.cmd`（带空格路径）`--version` 返回 `0.2.0-rc.2`、`dsh.cmd plugin --profile desktop add` 经 pnpm junction 装入并核实、记录\"已装进桌面版\"、两族各用一份 generation 并存、Doctor 一行两边有修复按钮、卸载桌面版清依赖与 bundle 行并清掉 `dsh plugin remove` 残留 junction、只删桌面版那份 generation 而保留 web 在用的；2026-10-04 另在 Windows 上以真 Clawd（Electron，源码运行、用户会话、普通权限）验证：先抓到一个只在 Electron 里出现的 bug（Electron 的 fs 把 `app.asar` 当目录、Windows 安装目录核实要求它是文件，于是在真 Clawd 里桌面版被判成没装，已在 `d8190692` 修成\"存在即可\"）；修好后桌面版一直开着（宿主进程未重启），启动同步把插件装进桌面版并记\"已装进桌面版\"，在桌面版新开对话的事件来自那个未重启的宿主进程，**Windows 上桌面版开着也会加载新加的插件**。**未覆盖**：Windows 上桌面版的审批、Windows 上的 Electron 界面（设置页提示、Doctor 窗口、启动预热）、打包后的 app、Linux、HTTP 204 交还与取消、装了多个桌面版。**管理员 junction 观察（推断）**：提升过的管理员进程在 Windows 11 上穿不过非管理员进程建的 junction（PowerShell \"untrusted mount point\"、Node `UNKNOWN`），该会话里 web 的旧 junction 读不到、web add 失败，桌面版同会话新建的 junction 正常；普通权限运行不受影响；由此推断以管理员身份运行 Clawd 可能把普通权限装好的插件读成缺失，未用以管理员身份运行的 Clawd 直接复现\n- OpenClaw 通过 `~/.openclaw/openclaw.json` plugin 路径做 state-only 集成；Phase 1 不做 permission bubble / terminal focus，主要支持本地 `openclaw tui --local`\n- Antigravity CLI (agy) 通过 `~/.gemini/config/hooks.json` 做 **state-only** hook 集成（PreInvocation / PostToolUse / PostInvocation / Stop），**不注册 PreToolUse**。agy LLM 会主动调内置 `ask_permission` 工具，触发 agy 自己的 5 选项 native menu（含 \"Persist to settings.json\" 持久白名单），Clawd 不插手权限决策也不双层确认。`agents/antigravity-cli.js` `capabilities.permissionApproval` / `interactiveBubble` 均为 false。\n- Qwen Code 通过 `~/.qwen/settings.json` 做 hook-only 集成（SessionStart / SessionEnd / UserPromptSubmit / PreToolUse / PostToolUse / Stop / Notification / PermissionRequest），支持状态与阻塞式 `PermissionRequest` 权限气泡；`disableAllHooks: true` 时注册条目不会触发。\n- QwenWork (千问办公) 通过 `~/.QwenWorkCN/settings.json` 做 **hook-only / state-only** 集成（agent id `qwenwork`；SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / Notification / PermissionRequest / PermissionDenied / SessionEnd）。`PermissionRequest` / `PermissionDenied` 只作为观察映射成 `working`（每任务 40+ 次，映射成 notification 会刷屏），hook stdout 恒为 `{}`：Clawd 不产生 allow/deny，不注册 `/permission`，也不进入 permission automation eligibility，唯一决策者是 QwenWork 原生权限流程；`agents/qwenwork.js` 的 `capabilities.permissionApproval` / `interactiveBubble` 均为 false。Windows command 必须保持 `windowsWrapper:\"portable\"`（QwenWork 经 POSIX shell 执行 command hook），PowerShell `-EncodedCommand` **只**用于识别并原地迁移旧条目，不是当前写入形态。marker 只认 `qwenwork-hook.js`，不得仅凭 `name:\"clawd\"` 删除用户 hook；混合 entry 中第三方 hook 原样保留。session id 命名空间是 `qwenwork:<raw>`；`~/.QwenWorkCN/workspace/<id>` 这类内部工作区 cwd 不做 basename 回退，避免 HUD/Dashboard 显示内部 ID。当前真实支持平台只有 macOS / Windows 桌面端（官方下载页 https://qwenwork.cn/download 只提供 macOS 14+ / Windows 10+ / HarmonyOS 6.1+，没有 Linux 客户端），因此 `processNames.linux`、resolver linux agent name 均为空，也不进 `src/wsl-deploy.js` 的 WSL Pair 映射。桌面主进程长驻、不代表 active turn，`startupRecoveryProcessNames` 全空、无 startup recovery。安装/卸载走 Settings → AI Coding Tools，或 `npm run install:qwenwork-hooks` / `npm run uninstall:qwenwork-hooks`；卸载必须同时在 `hooks/cleanup-integrations.js` 的 `MANAGED_AGENT_IDS` / `AGENT_CLEANERS` / `byAgent` 里有条目，否则 About cleanup 只会改 prefs、hook 留在磁盘上\n- ZCode 通过 `~/.zcode/cli/config.json` 的 `hooks.events.*` 集成全部 7 个支持事件（SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / PermissionRequest，无 SessionEnd / Notification）。PermissionRequest 为阻塞式权限审批：hook 长连接 `POST /permission`（HTTP 等待 590s，installer 注册 `timeoutMs: 600000`），有决定时 stdout 返回最小合法 `{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}`（deny 可带 `message`），无决定 / 超时 / 断连 / 任何错误输出 `{}` 并 exit 0，ZCode 回退原生权限流程；`interrupt` / `updatedInput` / `updatedPermissions` / `permissionUpdates` 必须 omit（最小输出 union 按 ZCode 3.5.x 严格 schema 约束；macOS ZCode 3.8.1 已完成真实 hook / 气泡 Allow/Deny 往返，3.5.x PermissionRequest 真机往返未覆盖）。超时单位陷阱：ZCode `timeout` 是秒、`timeoutMs` 才是毫秒，且超时按事件区分（PermissionRequest 600000、state 事件 8000）。Phase 2 只允许人工审批：ZCode 不进入 `KNOWN_PERMISSION_AGENTS`，global / per-session permission automation 在工具面与会话身份审计完成前全部 defer。prefs v14→v15 迁移把 Phase 1 持久化的 `zcode.permissionsEnabled:false` 翻 true（当时开关从未渲染、无用户意图）。配置必须有 `hooks.enabled=true` 才会执行；安装器只在该字段缺失时补 true，显式 `hooks.enabled=false` 或 Clawd 单项 hook 的 `enabled=false` 必须保留，Doctor warning 且不提供会覆盖用户选择的 Fix。ZCode 导入 Claude 配置后，只清理 `.zcode` 中明确引用 `clawd-hook.js` 的 Clawd-owned 条目，绝不改 `~/.claude/settings.json`。安全边界（复核后新增）：`/state` 生命周期 sweep 对 zcode（及 qwen/DSH 等 native-fallback adapter）只允许 no-decision，绝不伪 deny；hook 侧 `tool_input` 预算内原样发送、任何截断（长 Bash 尾部 `rm -rf` 场景）或序列化超 512KiB 一律 fail-closed 输出 `{}` 交还原生 UI；无 allow/answer/plan capability 的 interaction（如 ZCode 真实的 ExitPlanMode / AskUserQuestion）本地气泡与远程卡片都不提供决定入口、直接 204；全局气泡关闭只关本地窗口，Telegram/飞书 remote-only 审批仍可用（per-agent gate 关闭才是全退出）；installer 遇到 foreign `PermissionRequest` hook 时不注册自己的 blocking hook，若 foreign hook 后出现则移除自己的 managed hook（ZCode 同事件 hook 串行执行、后写覆盖，Clawd allow 会盖掉用户 hook 的 deny），Doctor 报 `permission-conflict` 且不给 Fix；六个 Phase 1 managed hook 全部显式 disabled 时新 PermissionRequest 继承 `enabled:false`；服务端 pre-parse 超限一律断连回退，不伪造 deny\n- Qoder / Qoder CN 共用 `qoder` agent，通过 `~/.qoder/settings.json` / `~/.qoder-cn/settings.json` 做 **state-only** hook 集成；各自尊重 `QODER_CONFIG_DIR` / `QODERCN_CONFIG_DIR`，同步所有已初始化目录，不创建缺失版本目录，卸载/cleanup 覆盖两版且只移除 Clawd entries，Doctor 不得让健康的一版掩盖另一版故障。Clawd 只把 `PermissionRequest` / `PermissionDenied` 当 notification 观察，**不替 Qoder 做权限决策**，hook stdout 恒为 `{}`；Windows command 必须保持 `windowsWrapper:\"portable\"`。session id 命名空间是 `qoder:<raw>`；启动恢复只认 CLI `qodercli` / `qoder-cli` / `qoderclicn`，不认闲置 IDE / CN 桌面进程；本机原生会话标题由 `src/qoder-session-title.js` 低频异步增量读取，通过 `updateSessionMetadata` 更新；SessionEnd / 禁用 / 退出取消旧读取，远端与 WSL 路径不在本机读取。2026-10-18 已核对 Windows CN runtime 1.1.69 的真实 SessionStart / UserPromptSubmit / Stop hooks，用户确认开启 Clawd Qoder 接入后任务状态恢复；macOS/Linux CN 未实测\n- TraeCode (Trae CN) 通过 `~/.trae-cn/hooks.json` 做 **hook-only / state-only** 集成。Windows command 必须保持 `windowsWrapper:\"encoded\"`：Trae 的 Windows Sandbox 会把 hook 命令作为 `trae-sandbox.exe --command-line` 的单个原生参数再次转发，普通引号或 `portable` 形态会在含空格路径处拆分；外层必须保持无引号的 PowerShell `-EncodedCommand`，POSIX 则继续使用普通 quoted command。该约束不适用于经 POSIX shell 执行 Windows hook 的 agent（如 Qoder / QwenWork）。\n- MiniMax Code 通过 `<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/` 的 **Clawd 独占本地插件**做 **state-only** 集成（manifest 用 `.claude-plugin/plugin.json`，hooks 文档按 MiniMax 的 CLAUDE sourceFormat 解析；不用 `.minimax-plugin/`，那会走 MINIMAX 格式：matcher 必须非空且不支持 exec-form args）。handler 固定 exec-form `command=node 路径 + args=[minimax-hook.js]`（spawn 直执行、无 shell、免引号），`timeout` 单位是秒且只接受 1–10 的整数（越界的 handler 被丢弃而不是钳制；SessionEnd 事件总预算仅 3s），因此 **PermissionRequest 物理上不可阻塞审批、完全不注册**，也没有 Notification 事件；hook stdout 恒为 `{}`（permissionDecision 缺省 abstain）。目录级所有权只认结构化凭据 `.clawd-managed.json`（`{app:\"clawd-on-desk\",integration:\"minimax\",managed:true,version:1}`，同 Pi 约定；MiniMax 只读 manifest 声明的文件，会忽略它），且凭据与所有受管理路径（`.claude-plugin/`、`hooks/` 及其文件）都不得是符号链接；目录名、manifest name、文档里的 basename/子串乃至整份文档指纹都永不授权改写或递归删除，缺凭据的目录（包括补丁前预发布构建写出的）一律 fail closed，只能手动删除后重装。staging / removal 目录固定落在数据目录（`plugins/` 之外，MiniMax 会把 `plugins/` 下每个目录项都当插件候选，含点号名）：首装在 staging 写全三份文件后一次 rename 发布（只覆盖空目标，非空目录/文件/链接拒绝；空 `clawd-state/` 视为未占用），失败时尽力删除 staging；已拥有的目录原地逐文件更新，中断后仍可证明归属、由下次安装补完。只有 ENOENT/ENOTDIR 算不存在，其他 lstat 错误按无法确认处理，绝不据此宣告卸载。卸载先把已验证目录 rename 出 `plugins/`、复验后再删；移走失败报 error 并保留安装意图，移走成功但删除失败时按已移除提交并在 warnings 里给出残留 `.clawd-minimax-removing-*` 路径，复验失败且移回失败时两个位置都报 `registrationRemoved:null` 并带 `residualPaths`；删不掉且目录仍运行 Clawd hook 时返回 `registrationRemoved:false`（读不清为 `null`），Settings / About 据此保留安装意图。删除后返回前还会复查一次原位置：此时若已有另一个 Clawd 实例重新发布的插件，报“仍在注册”（`registrationRemoved:false`）、不宣称卸载；这次复查是快照，复查之后、Settings 提交之前的安装不在本次结果里（多实例强一致需要覆盖 prefs 提交的跨进程锁，未做）。Settings 界面目前不显示成功结果里的 `warnings` / `residualPaths`：Agents 页安装/卸载只弹“已卸载/已安装”，About 清理只显示计数，只有命令行 cleanup 脚本会打印 warning。进程中途崩溃，或 staging 清理本身失败，可能在数据目录留下 `.clawd-minimax-staging-*` / `.clawd-minimax-removing-*`（MiniMax 不会加载，只能手动删除）；`plugins/` 与数据目录跨文件系统（EXDEV）时不支持。判断外来目录是否仍跑 Clawd hook 按 manifest 声明的 hooks 文档和 MiniMax 默认规则检查（含裸文档外壳、反斜杠路径，以及 shell 形式的 command / commandWindows handler）；Clawd 不建模的 manifest（根 `plugin.json` / `.minimax-plugin/` / `.codex-plugin/`）或读不清时按无法确认处理。node 探测失败时只保留全部 Clawd handler 一致、basename 为 node、存在且可执行、并通过 `node --version` 有界探测的已记录路径（exec-form 无 shell，Dock 启动的桌面 App 的 PATH 里没有 node），安装器与 Doctor 共用 `resolveDesiredNodeBin`。PostCompact 按 #406 上报 thinking（`trigger:\"manual\"` 时 idle），不是 attention。hook 的 `agentNames` 必须全小写（resolver 比较的是小写 basename），且不含桌面版的 “MiniMax Code Helper”：拉起 hook 的 NodeService helper 可能在 App 运行中重启，把它当 agent 会误删活会话，识别应落到长驻的主程序；mcode CLI 启动时执行 `process.title = \"minimax-code\"`，macOS/Linux 上 `ps` 报告的进程名就是 `minimax-code`（按名字匹配），Windows 上仍是 node.exe，靠 `agentCmdlineCheck` 只看 argv 里的脚本位置识别（命令行检查的进程名沿用共享默认 `DEFAULT_AGENT_CMDLINE_NAMES`，已含 Linux 上新版 Node 的主线程名 `mainthread` / `node-mainthread`，MiniMax 不再自带名单）（`node` 后的脚本 basename 是 `mcode`/`minimax-code` 启动器，或脚本路径含 `/@minimax-ai/code/` / `/.minimax-code/`），参数里的目录片段不算——MiniMax 退出时不发 SessionEnd，没有 agent pid 会话就无法按 agent-exit 清理。hook 不触发时的启用步骤在 MiniMax 应用内（`mcode plugin enable clawd-state@local` 或插件面板），磁盘上读不到启用状态，Doctor/Settings 只能提示。session id 命名空间 `minimax:<raw>`，标题走首行 prompt 派生 + 服务端 first-wins（同 traecode）。\n- Kimi Code（agent id `kimi-cli`）的 agent pid 靠进程名识别：CLI 启动即 `process.title = \"kimi-code\"`，libuv 把标题写回原 argv 所占的空间、放不下就截断，所以 macOS/Linux 上 `ps` 与 `pgrep -x` 看到的名字随启动命令长短而变（0.42.0 原生版实测：`kimi` 仍是 `kimi`，`kimi -c` 是 `kimi-co`，`kimi --yolo` 或全路径启动是 `kimi-code`；只有整条启动命令比 `kimi` 还短时（例如不带参数的软链接 `k`）才认不出，`k -c` 显示的已经是 `kimi`）。`hooks/kimi-process-names.js` 必须列全从 `kimi` 到 `kimi-code` 的每一种截断，resolver 与 startup recovery 共用这一组，只写 `kimi-code` 会漏掉 `kimi -c`。拉起 hook 的就是这个改名后的主进程（TUI 在进程内跑 agent 引擎，从 SessionStart 到 SessionEnd 同一个 PID）；其他同名进程（后台更新下载器、经 kimi 二进制跑的插件进程等）都是它的子进程，不跑 hook。resolver 比较小写 basename，macOS 桌面版 `Kimi Code.app` 写成 `kimi code`（它的 agent server 跑在主进程里，hook 由主进程直接拉起）；桌面版关窗后常驻托盘、不代表在干活，同其他桌面 App 一样不进 startup recovery。Windows 上标题只改控制台标题：原生版仍是 `kimi.exe`，npm 版仍是 `node.exe`，命令行检查只认包目录 `/@moonshot-ai/kimi-code/`，不能退回“含 kimi 就算”（Kimi 本身没被认出时，任何命令行提到 kimi 的 node 祖先都会被当成 agent）。Kimi Code 正常 `/exit` 会发 SessionEnd，但关终端、`kill`（0.42.0 实测：SIGTERM 与 SIGKILL 都不发；源码里 SIGTERM 注册了 `stop(143)`，实测为什么没发 SessionEnd 还没查清）、崩溃都不发；没有 agent pid 的会话只要终端 App 还开着就一直留在列表里。桌面端启动时会恢复上次查看的对话、在侧栏点开旧对话也一样，这类只发一条 SessionStart、还没有任何动作的对话不进 Session HUD，Dashboard 照常列出、按钮照常可跳，出现提问/工具/审批/Stop 等动作后自动进 HUD（与 DSH 共用同一个 `awaitingActivity` 标记）。\n- HTTP 服务端口范围固定为 `127.0.0.1:23333-23337`；运行时端口写入 `~/.clawd/runtime.json`\n- Mobile Preview 是独立的 LAN listener，候选范围为 `0.0.0.0:23334-23338`；它不写 `runtime.json`，不得把该范围误写成 hook / custom-agent HTTP ingress 范围\n- 自定义 HTTP Agent 的 sender 必须读取 `~/.clawd/runtime.json`，不能把 23333 写死；注册不等于已连接。custom v1 只支持 `/state`，不支持 `/permission`\n- CodeBuddy PermissionRequest hook 的所有权只认本机 managed URL 或 marker `clawd-on-desk.permission.v1`；纯 `name:\"clawd\"` 不能触发改写/删除。裸 CLI 和 WSL 默认 preserve，Settings/startup/repair 必须显式传 local/custom permission target\n- Remote SSH 的远端 Node 探测要求 Node >= 14；Node discovery/version validation 只在 `src/remote-ssh-node.js`，ordinary tunnel health 与 serialized readiness 在 `src/remote-ssh-runtime.js`，不得互相复制或从已停用脚本另起实现\n- 注册 Claude Code hook 必须 marker-scoped merge：只可更新/删除含 `clawd-hook.js` / `auto-start.js` marker 的 Clawd-owned entry，不得整体覆盖数组或改动无 marker 的用户 entry\n- 注册 Claude Code statusLine 默认只接管空槽或自己的槽（marker `claude-statusline.js`）；本机 Settings 显式开启采集遇到第三方槽时，必须经共存确认并复核原槽指纹，使用 `--local-chain` 和独立的 `clawd-statusline-local-chain.json` 保存/恢复完整原对象。启动/自动修复不得自行取得第三方槽；恢复记录缺失、损坏或不匹配时 fail closed 并保留现场。远程部署仍用 profile 的 `chainStatusline` opt-in 和既有 `--chain` sidecar，不与本机记录混用。订阅配额通过 `metadata_only` POST 进入 session-independent `updateAccountQuota` per-source store；不要把 quota 塞进 `updateSession` opts，也不要以 session 存活作为摄入前提\n- Copilot CLI hooks 走按需自动同步：`hooks/copilot-install.js` 在本地启动仅当 Copilot CLI 已安装且已启用时调用；远端由 Settings Remote SSH deploy controller 调用。路径解析尊重 `COPILOT_HOME` env（trimmed 非空才生效，否则 fallback 到 `~/.copilot`）；`hooks/copilot-hook.js` 的 session-state resolver 同样走 env\n- Remote SSH 的 effective transport 由 `ssh -G` 只读检查决定：ordinary SSH 在没有 retained serialized occupancy 时保持 `context:null` 的 parallel 路径；serialized transport 以有效 target key（不是 profile id）互斥。所有 serialized managed SSH/SCP child 必须持 coordinator 发出的有效 connection/operation context，并通过其 pre-spawn gateway 启动；用户交互终端只有命中 serialized/retained occupancy 时才要求 coordinator 判定 target 完全 idle\n- serialized persistent tunnel 使用同一条 SSH 内嵌 readiness；暂停通过 stdin EOF 请求自然退出并等待 `close`。强杀或带 signal 的 outer `ssh.exe` close 不能证明 nested ProxyCommand 已 drain；timeout/未验证 drain 必须 quarantine，期间禁止新 child、mutation、resume 或 interactive terminal\n- mutation 在 deploy-lock acquire-attempted / lock-owned 后遇到 exit 255、EOF/reset、signal 或其他 unknown result 时不得自动 replay、retry、release lock 或恢复连接；必须保留 primary error 并传播 recovery state，必要时要求 `manual_lock_inspection_required`\n- Remote SSH secure hook 必须同时携带 `CLAWD_REMOTE=1` 与 `CLAWD_SSH_REMOTE=1`，只读 layout identity 并 pin 精确端口；identity 缺失/损坏/不可读必须 fail closed，禁止回退端口扫描\n- Remote SSH deploy-lock acquisition 必须原子化；成功 acquire 后的每个 live mutation 都要在同一远端命令内 fencing 校验，cleanup 还必须锁内重读 installId/profileId/runtimeKey/layoutVersion 所有权。无身份、冲突、ownerless/corrupt lock 均不得自动接管\n- 默认 `account-default` 只支持不同 Unix 账号；同 Unix 账号冲突必须阻止。`profile-isolated` 在真实 SSH/CLI 矩阵完成前由 `CLAWD_ENABLE_EXPERIMENTAL_REMOTE_ISOLATION=1` 发布门隐藏；它只隔离用户级 CLI config/session/runtime 与 Clawd 路由，不代表完整 HOME 或同 UID 安全隔离，project 配置/部分 cache/macOS Claude Keychain auth 仍可能共享\n- Hermes Agent 的 Remote SSH 部署是 `secureDeploy` 内的 `hermes-files` → `install-hermes` 两个阶段，复用同一条 serialized transport、deploy lease、fencing 与所有权检查，没有独立的 Hermes SSH deployer：secure 模式由每个托管 `plugins/clawd-on-desk/` 内的 plugin-local marker `clawd-ssh-secure-v1` latch，latch 后 identity 必须在每次 state/probe/permission 请求时重新读取（禁止 `(mtime,size)` 缓存），且不得发送任何远端 PID / 进程树 metadata；plugin 资产走独立 staging 目录，清理只 `rm -f` 精确文件再 `rmdir`，禁止 `rm -rf`；`REMOTE_IDENTITY_STEP_NAMES` 保持冻结的 8 步不变，不得加入 `installHermes`；Clawd 绝不自动重启 Hermes gateway，托管模块被替换时只报告需要手动重启\n- 禁用 agent 不应卸载 hooks / plugins / extensions：只停止对应 monitor、清理 session / bubble、让 HTTP hook 入口快速 fallback；重新启用未安装 agent 不触发本机 integration sync。卸载集成必须走 Settings Agent 页的 Uninstall / 对应 uninstall 命令，并同时清掉 `integrationInstalled`\n- Kiro 的 `sessionId=\"default\"` 会复用；session alias key 必须按 cwd scope 区分，同时保留旧 `local|kiro-cli|default` 只读 fallback\n- Windows NSIS release 必须产出明确架构的 x64 / ARM64 安装包：`win.artifactName` 保留 `${arch}`，`nsis.buildUniversalInstaller` 保持 `false`\n- 每个 release target 只能保留一个匹配目标架构的 Koffi `koffi.node`；`afterPack` 只允许剪裁 `app.asar.unpacked` 的物理文件，禁止重写 `app.asar`，并必须通过完整 native inventory audit（唯一常设例外是 electron-builder 管理的 Windows ia32 `resources/elevate.exe`）\n- 资源路径统一用 `path.join(__dirname, ...)`\n- 需要编辑发布素材时，先复制到 `assets/source/` 再改，不要直接改工作素材来源不明的文件\n- `assets/source/cloudling-pointer-bridge/` 是 Cloudling 指针桥素材的保留源文件目录；运行时逻辑已内联进主题 SVG，不要把这个 source 目录当临时文件清理\n- 主题状态、sleep/DND、mini mode、状态映射的细节在 `docs/project/theme-state-ui.md`\n- 官方可下载主题（`official-theme-*`）是受管分发层，不是 built-in、也不提升信任：catalog 是固定远端小目录（renderer 只能传 themeId），下载走 Electron main `net.request` 的 manual redirect + 精确 CDN host allowlist + 固定 bytes/SHA-256（未支持 host 返回稳定 `DOWNLOAD_HOST_UNSUPPORTED`，不允许 catalog 扩展 allowlist），ZIP 只在 manager 专属 staging 内流式解压并以 marker-before-rename 同卷提交，最终以 `isBuiltin=false` 加载（`trustedRuntime` 无效）。`setThemeSelection` / `removeTheme` / `officialTheme.commitInstall` / `officialTheme.uninstall` / `theme` update 共用 `lockKey=\"theme\"`；卸载 active 主题必须等 `waitForThemeReloadSettled()`。主仓库附带一份目录快照 `src/official-theme-catalog-snapshot.json`：网络拉取失败时列表先用上一次成功加载的目录（内存 LKG 或磁盘缓存），都没有才用快照；第一次拉取有结果之前（`uninitialized`）不用快照；快照**不作安装依据**，安装仍只认经校验的网络/磁盘目录。快照只作列表回落（仍显示 `offline` 和重试），不含素材与预览图，不写磁盘缓存，且参与版本不能回退的比较；发布前用 `npm run update:official-theme-snapshot` 刷新。不要把 Hash Sage / Whale-chan 的动画素材（APNG / WebP），或把它们写成内置主题的文案带回主仓库\n- Settings 体系里，store 是唯一真相，controller 是唯一写入者；不要绕开 `settings-controller.js`\n- Dashboard 数字快选是**完整 Dashboard 同一页面的临时键盘模式，仅 macOS/Windows**；Linux 明确 NOT SUPPORTED（不是待验证）。平台 gate 的唯一真相是 `shortcut-actions.js` 的 `supportedPlatforms` + `isShortcutActionSupported()`，Settings 展示、globalShortcut 注册/录制、设置命令和冲突占用都必须服从它；遗留的不支持绑定只忽略执行，不删用户 prefs、不占其他快捷键。darwin/win32 的 Dashboard 页面活在 `WebContentsView` 里，`BrowserWindow.fromWebContents()` 对它返回 null、BaseWindow 不触发 `ready-to-show`；页面 WC 一律从 owner 取。禁止用 `hide()`+`showInactive()` 归还已显示的普通宿主（实测会遮挡来源窗口），只能 opacity/input parking 并幂等恢复捕获值。详见 `docs/project/theme-state-ui.md`\n\n## Testing\n\n- 自动化测试使用 Node 内置 test runner：`npm test`\n- `test/*.test.js` 覆盖核心 unit/contract、installer、route、UI/runtime 与 Remote SSH transport/coordinator/identity；部分 fixture 会启动 Node、shell 或 Git Bash 子进程，缺少依赖时可能 skip，不能把全套结果概括成纯逻辑或等价真机验证\n- Remote SSH 真机矩阵与记录在 `scripts/manual/README.md`；Windows OpenSSH + Codespaces stdio 边界及 ordinary-host V15 release gate 不能从 unit tests 互相推断，无法执行时必须明确记录 pending / residual risk\n- Windows Terminal 真机、GUI smoke 与清理必须假定多个 tab/window 共享进程：不得按 PID/进程名 `taskkill`、`Stop-Process` 或宽泛终止 WindowsTerminal、Codex、`cmd.exe`、`ssh.exe`、OpenConsole、conhost。测试终端只能在明确 test-owned session 内 `exit`；无法证明 ownership 就保留现场并请用户手动关闭\n- 当前开发环境是 Windows-first；macOS 特定路径无法在这里手动 QA，改到 mac 逻辑时要用 code-review","CLAUDE.md":"# AGENTS.md\n\nThis file is the entry point for coding agents working in this repository. Keep it short and operational. Durable architecture lives in `docs/project/`; `docs/plans/` and `docs/investigations/` are historical evidence unless this file explicitly links them.\n\n## Project Overview\n\nClawd 是一个 Electron 桌宠：通过 hook、日志轮询、plugin 和 extension 感知 AI coding agent 的工作状态，并播放像素风动画。当前支持 Claude Code、Codex CLI、Copilot CLI、Gemini CLI、Antigravity CLI (agy)、Cursor Agent、CodeBuddy、WorkBuddy、Grok Build、Kiro CLI、KiroCrew、Kimi Code CLI (Kimi-CLI)、Qwen Code、ZCode、CodeWhale、opencode、MiMo Code、Pi、OMP (oh-my-pi)、OpenClaw、Hermes Agent、Qoder、QoderWork、QwenWork (千问办公)、Reasonix、DeepSeek Harness、TraeCode (Trae CN)、MiniMax Code；内置 Clawd / Calico / Cloudling 三套主题，支持用户主题，并可经 Settings 从独立 `rullerzhou-afk/clawd-themes` 仓库下载可选官方主题（Hash Sage、Whale-chan，external theme 权限、可卸载）；平台覆盖 Windows、macOS、Linux，UI 支持 en / zh / zh-TW / ko / ja / pt-BR / es。\n\n## Common Commands\n\n```bash\nnpm start\nnpm run build                  # default Windows package\nnpm run build:win:x64\nnpm run build:win:arm64\nnpm run build:win:all\nnpm run build:mac\nnpm run build:linux\nnpm run build:all\nnpm install\nnpm test\nnpm run verify:electron\nnpm run verify:release\nnpm run audit:assets\nnpm run audit:pr-history-assets\nnpm run audit:native-package -- --app-root <extracted-app-root> --target <target-id>\nnpm run create-theme\n\nnpm run install:claude-hooks\nnpm run uninstall:claude-hooks\nnpm run install:cursor-hooks\nnpm run install:gemini-hooks\nnpm run install:antigravity-hooks\nnpm run install:kiro-hooks\nnpm run install:kirocrew-hooks\nnpm run uninstall:kirocrew-hooks\nnpm run install:kimi-hooks\nnpm run install:qwen-hooks\nnpm run install:zcode-hooks\nnpm run uninstall:zcode-hooks\nnpm run install:codewhale-hooks\nnpm run uninstall:codewhale-hooks\nnpm run install:pi-extension\nnpm run uninstall:pi-extension\nnpm run install:omp-extension\nnpm run uninstall:omp-extension\nnpm run install:openclaw-plugin\nnpm run uninstall:openclaw-plugin\nnpm run install:hermes-plugin\nnpm run uninstall:hermes-plugin\nnpm run install:qoder-hooks\nnpm run uninstall:qoder-hooks\nnpm run install:qoderwork-hooks\nnpm run uninstall:qoderwork-hooks\nnpm run install:qwenwork-hooks\nnpm run uninstall:qwenwork-hooks\nnpm run install:reasonix-hooks\nnpm run uninstall:reasonix-hooks\nnpm run install:workbuddy-hooks\nnpm run uninstall:workbuddy-hooks\nnpm run install:grok-hooks\nnpm run uninstall:grok-hooks\nnpm run install:dsh\nnpm run uninstall:dsh\nnpm run install:codex-hooks\nnpm run uninstall:codex-hooks\nnpm run install:codex-debug-hooks\nnpm run uninstall:codex-debug-hooks\nnpm run install:mimocode-plugin\nnpm run uninstall:mimocode-plugin\nnode hooks/codebuddy-install.js\nnode hooks/opencode-install.js\n\nbash test-demo.sh [seconds]\nbash test-mini.sh [seconds]\nbash test-macos.sh\nbash test-oneshot-gate.sh [state] [seconds]\n```\n\n新安装默认只把 Claude Code 和 Codex 标记为已安装并启用；其他 agent 默认未安装、未启用。正常启动时，Clawd 只会为 `integrationInstalled=true` 且 `enabled=true` 的 agent 自动同步 Claude / Codex / Copilot / Gemini / Antigravity / Cursor / CodeBuddy / WorkBuddy / Grok Build / Kiro / KiroCrew / Kimi / Qwen / ZCode / CodeWhale / Qoder / QoderWork / QwenWork / Reasonix / TraeCode / MiniMax Code hooks、opencode / MiMo Code / OpenClaw / Hermes plugins 和 Pi / OMP extensions。Settings Agent 页的 Install 会安装并启用该集成；Uninstall 会卸载 Clawd 管理的 hook/plugin/extension，并同时把该 agent 设为未安装、未启用。单独关闭 enabled 只会跳过启动同步并屏蔽事件/权限入口，不卸载用户已有 hooks / plugins / extensions；重新启用未安装 agent 只打开事件入口，不会写本机集成文件。手动安装命令主要用于调试、重装或远程部署。\nSettings 注册的自定义 HTTP Agent 是独立模型：`customApplications` 是注册真相，对应 `agents[customId]` 必须显式保持 `integrationInstalled=false`。注册只分配 ID 和状态入口，不安装 hook、不观察进程；v1 仅允许已注册且启用的 ID 向 `/state` 上报，`/permission` 永远不提供决定。删除或伪造的 `custom-` ID 必须直接拒绝，不能降级成 Claude Code subagent。\nCopilot CLI 同步走 `<COPILOT_HOME 或 ~/.copilot>/hooks/hooks.json`，marker-based 增量合并只接管含 `copilot-hook.js` 标记的条目，用户其他 entry / 其他 `hooks/*.json` 文件原样保留；hooks.json 或 `settings.json` 顶层 `disableAllHooks: true` 时 doctor 报 warning（不挂 Fix 按钮）。详见 `docs/guides/copilot-setup.md`。\n\n## Read These Docs\n\n- `docs/project/agent-runtime-architecture.md`：运行时架构、模块边界、启动与数据流、多 agent、permission bubble、终端聚焦和自动同步\n- `docs/project/theme-state-ui.md`：状态机、主题系统、settings、mini mode、素材规则、平台限制、待落地 UI 决策\n- `docs/project/release-process.md`：发版 checklist、release note 核对、tag 触发 GitHub 打包和资产确认\n- `docs/guides/copilot-setup.md`：Copilot CLI 自动同步说明、`COPILOT_HOME` 兼容性、手动配置备选模板\n- `docs/guides/dsh-setup.md`：DeepSeek Harness web profile 与桌面版的实验性 plugin 集成状态与普通审批集成\n- `docs/guides/state-mapping.md`：状态 → 动画权威表\n- `docs/guides/guide-theme-creation.md`：主题作者指南\n- `docs/guides/setup-guide.md`：安装、远程 SSH、各 agent 接入\n- `docs/guides/custom-agent-http.md`：自定义 HTTP Agent 的 state-only 接入合约和动态端口发现\n- `docs/guides/known-limitations.md`：用户向已知限制\n- `docs/guides/recap.md`：本地小结的指标口径、coverage、时区/DST、隐私存储与产品红线\n- `docs/guides/codex-wsl-clarification.md`：Codex / WSL 路径与 Node 说明\n- `docs/guides/guide-remote-ssh.md`：Remote SSH 用户流程、Codespaces 单会话 transport 与共享主机边界\n- `docs/guides/telegram-approval.md` / `docs/guides/feishu-lark-remote-approval.md`：远程审批设置与失败回退语义\n- `docs/guides/roam-fence.md`：自由漫游与可选围栏\n\n## Runtime Summary\n\n- HTTP hook / plugin 主路径：`src/server.js` → `src/server-route-state.js` → `src/agent-runtime-main.js` → `src/state.js` → IPC；本地 JSONL monitor 直接进入 `agent-runtime-main`，不经过 HTTP server\n- 权限主路径：`src/server-route-permission.js` → `src/permission.js`；本地 bubble、显式 permission automation 与可选 Telegram / 飞书 Lark 远程审批都可能产生真实决定\n- 桌宠的渲染/输入双窗口由 `src/pet-window-runtime.js` 统一创建和定位；浮层排序与 topmost 行为在 `src/floating-window-runtime.js` / `src/topmost-runtime.js`\n- `src/state.js` 生成的 session snapshot 是 Dashboard、HUD/Orbit 与可选通知/presence/mobile consumer 的共享合约，改字段必须检查所有消费者\n- `src/integration-sync.js` 为已安装且启用的 agent 异步同步 hooks / plugins / extensions；Codex official hooks 为 primary，JSONL 轮询保留为 fallback\n- Claude hook 恢复由 `src/claude-settings-watcher.js` 的目录 watcher + 低频只读巡检共同负责；repair 统一经过 `src/claude-hook-operations.js` 队列并复验，连续失败转 `manual-fix-required`。完整 gate、阈值与 source-missing 语义见 `docs/project/agent-runtime-architecture.md`\n- `src/agent-gate.js` 控制各 agent 的安装意图、启用状态、权限气泡开关和 wait-for-input notification 子开关\n- 设置系统主链路是 `src/prefs.js` → `src/settings-controller.js`（唯一写入者）→ `src/settings-store.js`；`settings-actions*` 负责校验和 pre-commit gates，`settings-effect-router.js` 负责 post-commit runtime effects 与广播\n- 启动时还会尝试自动安装 VS Code / Cursor terminal-focus extension，并初始化 updater\n- Remote SSH 通过 effective transport inspection 区分 ordinary parallel SSH 与 serialized transport；后者由 target-scoped coordinator 编排。远程部署只走 Settings，`scripts/remote-deploy.sh` 已 fail-fast 停用\n\n## Core Files\n\n更细的背景见 `docs/project/agent-runtime-architecture.md` 和 `docs/project/theme-state-ui.md`。\n\n| File | Responsibility |\n|------|------|\n| `src/main.js` | Electron composition root：生命周期、上下文组装与各 runtime / IPC 注册器接线 |\n| `src/server.js` + `src/server-route-state.js` + `src/server-route-permission.js` | HTTP 服务、端口发现、`/state` / `/permission` 路由 |\n| `src/agent-runtime-main.js` + `src/integration-sync.js` | local monitor / official hook 仲裁、Codex turn fence、按 gate 的集成同步 |\n| `src/state.js` | 状态机、多会话合并、优先级、自动回退、睡眠/DND |\n| `src/renderer.js` | 动画切换、SVG 预加载、眼球追踪渲染 |\n| `src/permission.js` + `src/permission-automation-policy.js` + `src/session-automation-coordinator.js` | 权限气泡、自动化策略、per-session 授权与决策回包；远程 client 由 `main.js` 注入 |\n| `src/pet-window-runtime.js` + `src/floating-window-runtime.js` + `src/topmost-runtime.js` | 双窗口 owner、浮层重排、z-order / fullscreen / focusability |\n| `src/update-bubble.js` | 更新气泡创建、测高、跟随桌宠定位，避让 HUD / permission stack |\n| `src/dashboard.js` + `src/dashboard-renderer.js` | Sessions Dashboard 唯一 owner：会话列表、别名编辑、终端跳转、几何持久化，以及同一页面的临时键盘模式 |\n| `src/dashboard-host.js` | Dashboard 普通宿主的平台封装：darwin/win32 用 `BaseWindow + WebContentsView`（无 `ready-to-show`），Linux 保留 `BrowserWindow` |\n| `src/dashboard-quick-mode.js` | 完整 Dashboard 的 1–9 键盘模式（**macOS/Windows only**）：quick 宿主、opacity/input parking、轮次栅栏与冻结数字映射；Windows 显式取消与页面失效的来源恢复在 `src/quick-select-origin-focus.js`，quick 宿主的退出清理挂在 `before-quit` |\n| `src/session-hud.js` + `src/session-hud-renderer.js` | 桌宠旁轻量会话 HUD、折叠行、点击跳转 |\n| `src/session-alias.js` | session alias key 规范化、TTL pruning、Kiro cwd scope |\n| `src/theme-loader.js` + `src/theme-runtime.js` | stateless 主题加载/消毒与唯一 active-theme owner；`waitForThemeReloadSettled` 完成信号 |\n| `src/official-theme-catalog.js` / `-download.js` / `-installer.js` / `-main.js` | 官方可下载主题：严格 catalog/cache、Electron `net.request` 流式下载、受限流式 ZIP 解压与 marker-before-rename、main owner/IPC/共享 `theme` lock |\n| `src/prefs.js` | 偏好 schema、load/save/migrate/validate，设置持久化入口 |\n| `src/settings-actions*.js` + `src/settings-effect-router.js` | 设置 validators / commands / pre-commit gates 与 post-commit runtime effects |\n| `src/settings-controller.js` | 设置系统唯一写入者 |\n| `src/settings-store.js` | 不可变 snapshot store |\n| `src/settings-ui-core.js` + `src/settings-renderer.js` + `src/settings-tab-*.js` | Settings shared UI state、侧栏/tab shell 与各页逻辑 |\n| `src/menu.js` | 托盘 / 右键菜单，串起设置、Dashboard、mini mode、更新入口 |\n| `src/mini.js` | 极简模式入场、滑动、peek、状态映射 |\n| `src/tick.js` | 主循环、鼠标轮询、眼球和 idle/sleep 逻辑 |\n| `src/drag-position.js` | 拖拽落点规范化与跨显示器钳制 |\n| `src/visible-margins.js` | 可视角色边距与 edge pinning 规则 |\n| `src/updater.js` | Git 模式 / `electron-updater` 双路径更新逻辑 |\n| `src/focus.js` | 终端聚焦 |\n| `src/hit-renderer.js` + `src/hit-geometry.js` | 输入窗口命中、拖拽、连击反应 |\n| `src/remote-ssh-runtime.js` | Remote SSH tunnel/ingress 状态机、ordinary health probe、serialized readiness 与重连 |\n| `src/remote-ssh-transport.js` + `src/remote-ssh-transport-coordinator.js` | effective transport inspection、pre-spawn admission、target ownership、drain barrier 与 quarantine |\n| `src/remote-ssh-deploy.js` | Deploy / Repair、身份事务、lease/fencing、wrapper、cleanup 与远端 Codex monitor mutation |\n| `src/remote-ssh-identity.js` + `src/remote-ssh-layout.js` + `src/remote-ssh-ingress.js` | 身份/布局真相与 profile 专属、nonce 校验的本地 ingress |\n| `src/remote-ssh-node.js` + `src/remote-ssh-shell-detect.js` + `src/remote-ssh-local-config.js` | 远端 Node/ shell 探测与本机 SSH config 入口 |\n| `src/remote-ssh-profile.js` | Remote SSH profile schema、校验、默认值和持久化规范化 |\n| `src/remote-ssh-ipc.js` | Remote SSH runtime / deploy / monitor orchestration、intent policy、IPC 状态与进度广播 |\n| `src/remote-ssh-quote.js` | Remote SSH 终端命令与跨平台 shell quoting helper |\n| `agents/registry.js` | agent 注册表 |\n| `agents/codex-log-monitor.js` | Codex JSONL fallback 轮询 |\n| `agents/gemini-log-monitor.js` | legacy Gemini session JSON 轮询器；当前 Gemini hook-only 路径不启动 |\n| `hooks/dsh-install.js` | DeepSeek Harness immutable managed bridge generation、ownership verify、web 与 desktop 两个 profile 的安装 / 修复 / 卸载编排 |\n| `hooks/kirocrew-install.js` + `hooks/kirocrew-store.js` | KiroCrew state-only gateway hooks、upstream-compatible mutation locks and atomic private store writes |\n| `hooks/kirocrew-hook.js` + `hooks/kirocrew-command.js` | KiroCrew state bridge and exact command-shape ownership classifier |\n| `hooks/dsh-notices.js` | DeepSeek Harness 常驻提示的存储与规则（按 profile 的 `notices-<profile>.json`） |\n| `hooks/clawd-hook.js` + `hooks/copilot-hook.js` | Claude Code / Copilot CLI 状态上报脚本 |\n| `hooks/install.js` | Claude hook 注册 / 卸载 |\n| `hooks/auto-start.js` | Claude `SessionStart` 自动拉起 Clawd 的 hook |\n| `hooks/codex-hook.js` / `hooks/codex-install.js` | Codex official hooks 状态与权限审批、安装 / 卸载 |\n| `hooks/cursor-install.js` / `gemini-install.js` / `antigravity-install.js` / `kiro-install.js` / `kimi-install.js` / `qwen-code-install.js` / `codewhale-install.js` / `codebuddy-install.js` / `workbuddy-install.js` / `opencode-install.js` / `pi-install.js` / `openclaw-install.js` / `hermes-install.js` / `qoder-install.js` / `qoderwork-install.js` / `reasonix-install.js` | 各 agent 集成安装逻辑 |\n| `hooks/opencode-family-managed-generation.js` | OpenCode 用户可写托管 generation（canonicalizer、bundle/manifest、stage/promote、target owner record、target-scoped lock）；纯 Node 内置依赖，不进入 Remote SSH `HOOK_FILES` |\n| `hooks/opencode-family-entry-ownership.js` | OpenCode-family plugin entry 的 string/tuple 解析、跨平台路径等价、所有权分类与重复/options 冲突规划（纯逻辑、可注入 fs） |\n| `hooks/opencode-family-install.js` / `hooks/opencode-family-jsonc.js` | 家族注册器：`managedMaterialization:true` 走托管 generation 事务 + 共享 entry planner；`false` 保持 legacy broad-basename register/unregister |\n| `src/doctor-detectors/opencode-managed-inspector.js` | managed OpenCode Doctor inspector（ownership/manifest/生成结构、Fix policy、masked supplementary warning）；接受注入 fs |\n| `hooks/workbuddy-hook.js` | WorkBuddy state + Notification command hook；无 session_id 时返回合法 stdout 后丢弃事件 |\n| `hooks/grok-hook.js` / `hooks/grok-install.js` | Grok Build state + Notification command hook；写入 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json`；`env` marker `CLAWD_GROK_HOOK=v1` 所有权；无 session id 时丢弃；不注册 `/permission` |\n| `hooks/zcode-hook.js` / `hooks/zcode-install.js` | ZCode 状态 + 阻塞式 PermissionRequest hooks（`hookSpecificOutput` 决定 / `{}` 无决定）、`hooks.events.*` 按事件超时增量注册与 Claude-imported Clawd hook 清理 |\n| `hooks/qoder-hook.js` | Qoder state-only 状态上报脚本（Phase 1，stdout 恒为 `{}`） |\n| `hooks/minimax-hook.js` / `hooks/minimax-install.js` | MiniMax Code state-only 本地插件：整目录 install/uninstall（`<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/`），CLAUDE 格式 hooks + exec-form args，10 事件无 PermissionRequest/Notification，`.clawd-managed.json` 结构化所有权凭据、fail closed |\n| `hooks/codex-remote-monitor.js` | 远程 Codex JSONL 轮询并通过 SSH 隧道回传（含 token_count 订阅配额的 metadata_only 上报） |\n| `hooks/claude-statusline.js` / `hooks/antigravity-statusline.js` | 各 CLI statusline 适配器：渲染状态行 + 把订阅配额（rate_limits）以 metadata_only POST 上报；Claude 版支持远程部署（`CLAWD_REMOTE=1` 前缀）与 `--chain` 串联模式（原 statusLine 对象保存在 `~/.claude/hooks/clawd-statusline-chain.json`，卸载时恢复） |\n| `extensions/vscode/extension.js` | VS Code / Cursor 终端 tab 聚焦辅助扩展 |\n\n## Constraints\n\n- `agents/registry.js` 的 capabilities 是权限、subagent、session-end 等路由/gate 的权威来源；不得另写名单代替 capability 判定。但 permission automation eligibility 由更窄的 `isKnownPermissionAgent()` 显式判定（`KNOWN_PERMISSION_AGENTS` + explicit opencode-family membership），不得从 `permissionApproval` 自动派生或合并回 registry capabilities\n- 小结的指标能力例外地只认 `src/recap-metrics.js` 的显式逐 Agent 口径，不得从 registry capabilities 或标准化 event 名推导。只统计已通过 gate、Codex source/replay fence、subagent 与完成仲裁的 accepted activity；DND 继续记录且不切 coverage，suspend/退出/关闭记录才切。`null` 是不支持，绝不能渲染或汇总成 `0`\n- 小结持久层固定为 `~/.clawd/recap-v1/` 下 14 个本地日的最小 HMAC 小票与 400 个本地日的 daily/coverage；不得落 prompt/回复/命令/工具内容、路径/项目、原始 event/session/profile/turn/tool ID，不得增加网络、导出或分享。首版不做 Token、金额、模型、推理强度、Skill、人的工作/编码时长、streak、峰值/最长项、排行榜或生产力评分\n- Claude Code / CodeBuddy 的阻塞式权限审批走 `POST /permission` HTTP hook；普通状态事件走 command hook（CodeBuddy command hook 对所有事件输出 `{}`，不做工具或权限决定）\n- permission automation（off / auto-tools / unattended）和 per-session grant 会在 bubble 渲染前产生真实 allow/answer。agent/family eligibility 是显式白名单；工具分类则因 mode/adapter 而异：auto-tools 对 Claude/Qwen 的未知 built-in fail closed，但其他已知 adapter 不都使用逐工具白名单，unattended 还会有意自动放行可作 Allow/Deny 的未知请求。新增 agent、工具或交互类型必须审查 policy + tests，不能从 `permissionApproval` 推导资格或笼统假设“未知请求都会 defer”\n- Telegram / 飞书 Lark 与本地 bubble 是并行决策通道。远程通道超时、断连、未配置或发送失败不得产生远程决定，更不得转成 deny；有本地 bubble 时请求继续 pending，只有 remote-only 且所有可用 client 都无决定时，整体请求才 no-decision 并回到 agent 原生流程\n- WorkBuddy 通过当前 `~/.workbuddy-ai/settings.json`（旧版兼容 `~/.workbuddy/settings.json`）的 Claude Code 兼容 command hooks 做 **state + Notification only** 集成：不注册 `/permission`，审批始终留在 WorkBuddy 原生沙箱与 GUI；无 `session_id` 的事件返回合法 stdout 后直接丢弃。当前只支持 macOS/Windows 桌面应用，没有已验证的 Linux/WSL CLI；不要把裸 `Electron` 当 WorkBuddy 进程。\n- Grok Build（agent id `grok-build`）通过 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json` 的 Claude Code 兼容 command hooks 做 **local / main-session / state + Notification only** 集成（Phase 1）：stdin 为 camelCase（`sessionId` / `toolName`），`hookEventName` 是 camelCase key + snake_case value，`hook_event_name` 是 snake_case key + PascalCase value。**逐 handler 的 `env` 结构化 marker `CLAWD_GROK_HOOK=v1` 是唯一所有权凭据**；文件名/substring（含 `grok-hook.js.backup`）只用于诊断告警，永不授权改写或删除。安装/卸载只增删含该 marker 的 handler，保留 unknown 顶层键、其他 event、foreign matcher group 与 sibling handler；没有 marker 的既有文件一律原样拒绝。`SessionEnd` 不写 `timeout`（继承 Grok 1.5s teardown），其余事件 5s。Windows 用 `windowsWrapper:\"portable\"` 形态，不得用 `&` / `-EncodedCommand` / 自造 `shell` 字段。Grok 没有 `PermissionRequest`，不注册 `/permission`，adapter 始终输出 `{}`。子代理事件（`subagentType`）直接丢弃；不注册 `SubagentStart` / `SubagentStop`。Grok 默认会扫 `~/.claude/settings.json`，所以 `clawd-hook.js` / `cursor-hook.js` / `auto-start.js` 只在非空官方 `GROK_HOOK_EVENT` 下直接退出，`GROK_HOME` / `GROK_SESSION_ID` / 无关 `GROK_*` 不得触发。`Stop` 只有精确 `reason === \"end_turn\"` 且无 background task / session cron / `stopHookActive` 才算完成，其余由 adapter 本地判定；`channel_closed` / `shutdown` 等 session-end 形态的 Stop 在 fence 之前丢弃。turn 顺序由 `src/grok-turn-fence.js` 的 bounded in-memory fence 仲裁（晚到旧 turn、重复 terminal、continuation Stop、Stop→StopCancelled 纠正）。不进入 subagent / WSL / Remote SSH / startup recovery / terminal focus / quota / context / recap turn 指标。`~/.grok/hooks/clawd.json` 是未发布的 PR preview 路径，只做 warning，不得自动接管或删除。\n- Codex 的阻塞式权限审批走 official `PermissionRequest` command hook：hook 脚本长连接 `POST /permission`，只允许 stdout 返回 sanitized `behavior/message`，`updatedInput` / `updatedPermissions` / `interrupt` 必须 omit。权限模式默认 `auto`（旧 `native` 规范化为 `auto`），仅准确本机 session/turn 的人工 reviewer 证据可进 Clawd；未知、自动 reviewer、MCP/app、远程/WSL 均 no-decision；唯一例外是远程/WSL（路由 reason 为 `nonlocal`）的 Bash/apply_patch 在全局自动放行会立即 allow 时（`wouldAutoAllowPermission`：非 reminder hold、非会话覆盖、非交互子代理）由 Clawd 直接放行（#1186），路由后若设置已变则 no-decision，绝不弹气泡。`intercept` 是显式接管；升级时旧 `intercept` / `native` 统一迁到 Auto 一次，之后重新选择的 Intercept 会保留。不得用全局 config、其他会话或旧回合推断当前请求的审批方；证据不足时返回 no-decision，交还 Codex 原生流程。\n- hook 脚本只允许依赖 Node 内置模块，以及同目录 `hooks/` 下、且登记在 `src/remote-ssh-deploy.js` 的 `HOOK_FILES` 部署清单中的纯 Node helper（如 `server-config.js` / `shared-process.js` / `json-utils.js` / `codex-originator.js` / `codex-subagent-fields.js` / `context-usage.js` / `state-payload-size.js` / `quota-bucket.js` / `claude-rate-limits.js` / `codex-rate-limits.js` / `antigravity-context-usage.js`）；manifest-consistency 测试强制检查依赖闭包，新增 helper 必须登记\n- CJS hook 脚本需要稳定终端 PID 时，必须复用 `hooks/shared-process.js` 的 `createPidResolver()` 及其 lifecycle context；不要复制进程树 walk 或用 `process.ppid` 简化。`getStablePid()` 只是 opencode-family plugin 的内部 resolver\n- `agentCmdlineCheck` 只对进程名在 `agentCmdlineNames` 里的祖先进程运行，默认是 `DEFAULT_AGENT_CMDLINE_NAMES`：`node` / `node.exe`，加上 Linux 上没设过 `process.title` 的 Node 在 `ps -o comm=` 里的名字——Node 23.8–25.4（含全部 24.x）把主线程命名为 `MainThread`、≥ 25.5 为 `node-MainThread`，Linux 报的进程名就是主线程名。传入 `agentCmdlineNames` 会整体替换默认值：只想加名字的 adapter 必须在选项里直接写成 `agentCmdlineNames: new Set([..., ...DEFAULT_AGENT_CMDLINE_NAMES])`（如 ZCode；可以跨行，方括号里只能有普通字符串字面量和 `...DEFAULT_AGENT_CMDLINE_NAMES` 本身，不能有注释或其他表达式；简写属性、先存进变量，或任何不是这个形状的提及（包括注释里的）都会被判不合格，因为文本检查无法核对），只有刻意只探测非 Node 宿主的（WorkBuddy 的 `electron`）例外，`test/shared-process.test.js` 会扫描 `hooks/*.js` 检查\n- opencode v1 权限不走 `permission.ask` hook，而是 event hook + reverse bridge；v2 走 `ctx.permission.hook(\"evaluate\")` 的阻塞 HTTP 响应\n- OpenCode / MiMo v1 原生问题走独立本地 `/question` 长轮询，不复用审批回包；遵循全局 permission bubble 开关与 family 单 agent 开关。只接受已核实的 v1 来源、版本和问题 schema，提交前用原 SDK client 复核精确 request/tool/session，答案保持有序 `string[][]`；无决定返回 204 交还原生。OpenCode 由原生 reply RPC 的 `true` / 404 判定提交结果，MiMo 仍需精确 `question.replied` 答案匹配。子会话问题、OpenCode v2、Remote SSH 及未审核 agent 保持原生；不要改 Claude/Hermes wire 或托管 generation 依赖集合。详见 `docs/guides/agent-questions.md`。\n- opencode-family v1 插件经 `ctx.client` 连回宿主时，主机为通配监听地址（`0.0.0.0` / `[::]`）就按次改用 `127.0.0.1` / `[::1]`（不改宿主共享的客户端配置；非通配地址保持原调用形状）。默认 TUI 走进程内 fetch；`opencode serve` / `web` 下这是对监听地址的真实 HTTP 请求，受宿主进程里的 `HTTP_PROXY` / `NO_PROXY` 影响，而通配地址不会自动绕过代理。桥接回复失败返回 `{ok:false,status,error}`（`status` 为上游状态码，缺省 0）。\n- OpenCode 2.x（npm `@opencode/cli`，issue #1039）由 `hooks/opencode-plugin-v2/` + core.mjs 内 `createOpencodeFamilyPluginV2` 承接：installer 在同一 generation 内额外物化 `opencode-plugin-v2/index.mjs`（v1 四文件、v2 五文件；目录 specifier 解析 index.mjs、无需 package.json，2.0.15 实测），并把它写进 **`plugins` 键**，同时清理 Clawd 自有的旧 `plugin` 条目；用户条目、tuple/options 和 v1 行为保持不变。未被 Clawd 纳管的未知 `plugin` 条目仍只报 loader WARN；v1 对未知 `plugins` 键的静默丢弃只在 **1.18.16+** 成立——1.18.15 及更早会以 `Unrecognized key: plugins` 拒绝整个 config（anomalyco/opencode#41312，2026-08-08 起才忽略未知顶层键），因此 `plugins` 写入由宿主探测决定（`hooks/opencode-host-detect.js` 三态：探测到 v2 才写；探测到 v1 不写并清扫 owned 残留；探测失败不碰该键；`CLAWD_OPENCODE_HOST` 环境变量可钉死结论，Doctor 在无 v2 宿主时不要求 v2 条目）。v2 插件是零 import 纯对象 `{id, setup}`（v2 loader 拒绝函数 default export，`@opencode/...` 裸包名无插件本地 node_modules 不可解析），事件经 `ctx.event.subscribe()`（`session.step/tool/execution.*` 词汇完全换代，未知事件一律忽略），cwd 取事件信封 `location.directory`，标题走 `session.renamed`，context usage 走 `session.step.ended` 的 step tokens（`session.usage.updated` 是 session 累计计费值，不能当占用率）。权限走 **`ctx.permission.hook(\"evaluate\")` 阻塞长连接 POST `/permission`**，决定就是 HTTP 响应体 `{decision: allow|always|deny}`（服务端按 `hook_source === \"opencode-plugin-v2\"` 路由到 v2 阻塞子分支），只有 `200` + 身份头 + 合法 JSON 才采纳决定，204/超时/断连/非 200/任何错误都不改 effect 回原生 ask UI；配置 allow 也进 hook 但绝不降级；单条 shell 命令以 `tool_input.resource` 传输，服务端 v2 分支会为其别名出 `command` 以接入破坏性操作提醒（`mapOpencodeV2ShellResource`，非 shell 工具不映射；全字符串的多 resource 以换行合并作扫描别名）；resources 原样整组转发（对象转 JSON 字符串），不做条数/长度截断，唯一边界是整 body 超 512 KiB 时跳过转发。\"Always allow\" 无宿主持久化 API，用插件内 per-session 内存规则（随常驻 service 生命周期，气泡对 v2 使用单独文案说明关闭/重开终端不会撤销）。插件跑在常驻共享 service（daemon）：`source_pid`/进程树不可信故**整组省略**（终端跳转对 v2 降级），安装/更新后需 `opencode service restart`。`ctx.permission.hook()` 按上游 v2.0.15 类型返回 `Promise<Registration>`：本实例 dispose（setup 返回的 cleanup，宿主也会在插件 scope 关闭时调用）会调用 `registration.dispose()`，注册 Promise reject 只记日志不影响事件订阅。事件订阅**不等待** hook 注册（注册挂起/reject 时状态上报照常），reload **不等待**上一代注销完成；本实例清理先同步完成本地清理（标记 disposed、abort 订阅、身份恢复）再去注销 registration，注册 dispose 有约 2s 上限、超时只记日志，注册未完成就被取代则在注册完成那一刻立即注销，不残留活 hook。上游 v2.0.15 的 trigger 对同名 hook 依次调用每个仍注册的回调、共用同一个可变 event，而我们的注销是异步的，所以 reload 窗口内旧回调可能仍被调用：已退役实例的回调入口检查 `instance.disposed` 后直接返回，不 POST、不改 event。每个 ask 各自转发（`source.id` 是工具调用级、不是 ask 级，同一工具调用会发出多个不同 ask，如 external_directory + edit），不做内容去重。config 顶层重复 `plugins` 键按歧义处理：Doctor 报 `config-corrupt` 不抛异常，register/卸载在首次写入前中止（v1 宿主 sweep 只告警并跳过），v1 `plugin` 键行为不变。v1 1.18.31 tuple 契约、generation 布局、owner/lock 语义不变；`inspectGeneration` 把历史 4 文件集接受为合法 owned-stale 形态以便迁移。真机证据与降级项见 `docs/investigations/opencode-v2-e1-evidence.md`\n- OpenCode 的 plugin 注册不再直接指向打包/源码目录：`agents/opencode-family.js` 的 `managedMaterialization:true`（OpenCode true / MiMo 本次 false）gate materialize、ownership classifier、managed Doctor 与 generation cleanup。开启后 register 必须在目标 home 下维护 `<home>/.clawd/integrations/opencode-family/opencode/homes/<configDirHash>/generations/<bundleHash>/` 的内容寻址 generation（OpenCode v2 当前五文件，历史 v1 四文件），同一 generation 可同时物化 v1/v2 入口文件，但不因此在配置中注册两个键；探测到 v2 宿主时只把 `opencode-plugin-v2` 入口写入 `plugins`，并将 `plugin` 键仅用于清理 Clawd 自有旧条目；v1 宿主和探测不到版本时保持原有 v1 注册路径；bundle allowlist 固定为 `<agent>-plugin/index.mjs` / `<agent>-plugin/package.json` / `opencode-family-plugin/core.mjs` / `opencode-family-plugin/session-ids.mjs` / `opencode-plugin-v2/index.mjs`（v2）。owner record（`owner.json`，literal `clawd-on-desk.opencode-family.target`）与 target-scoped `mutation.lock/`（独立 literal `clawd-on-desk.opencode-family.target.lock`）是所有权与 app-present 真相；lock 被持有时不并发写：interactive Install/Repair/CLI/Uninstall/About cleanup 只做一次短而有界、可注入 delay 的重试，startup automatic 不等待直接 skipped；合法且超时 2 倍以上、PID 明确 ESRCH 才允许 atomic quarantine 接管，corrupt/foreign/live/EPERM 一律不接管；release 只删自己 token 的 `lock.json` 与随后为空的精确目录，禁止 recursive cleanup。owner 的 `activeSourceMarker` 必须是 `<activeSourceRoot>/<pluginDirName>/index.mjs`（共享 canonical 身份、Windows 折叠大小写）且为 regular file，目录/dangling/错 plugin 目录/root 不匹配都不算 live。同一 target 的 source owner 冲突（marker 仍存在）一律 `owner-conflict`，不得来回改 config；旧 owner 的源码 marker 已不存在时，新 source 必须在锁内重读并原子接管 owner（config 已 current 也不例外），否则残留死 owner 会让托管 plugin 永久 inert。锁内若 config 与当前 source owner 都已被并发操作收敛，则本次零 mutation 返回 skipped。lock release 失败不得掩盖结果：成功保留 status 并附 warning + 精确 lock path 的 residualPaths，已有 primary error 时保留原错误。basename 本身永不构成所有权；copy 到 managed layout 外的完整 generation 因缺少对应 owner record 而 inert，只有 verified-current-copy 可 Repair。tuple 契约固定为 OpenCode 1.18.31 实测的 `[specifier, optionsObject]`（隔离 `opencode debug config` 证据：第二项必须是普通对象，数组/字符串第二项会被宿主拒绝）；重写只替换 `plugin[index][0]`，options 值级保留，绝不写回嵌套 tuple，malformed array 原样保留。`options.pluginDir` 仍是 test-only expected-canonical override（跳过 generation/manifest/boundary，但不跳过 ownership/唯一 entry/read-back），`resolvePluginDir()` 仍返回 source。新建文件按当前用户普通写权限落盘：不得加 readonly/deny-write ACL，不得用 `W_OK`/`r+`/INIT 日志/session 活跃做健康门禁。Uninstall 以“活动注册是否移除”为提交依据（`registrationRemoved` false/null 阻止 Settings 提交，undefined 沿用 legacy status），残留 generation 只产生 warning；清理有效 generation 时必须先在同一 `generations/` 内原子改名为非 canonical `.cleanup-*` 再递归删除，删除失败不得占住原 hash 槽。兼容旧版本留下的半残 canonical 目录时，只允许在 owner 已 released、bounded history 精确证明该 canonical entry、且配置无活动 Clawd entry 的条件下，把它原子隔离为 `.recovery-*` 后重新物化；active/foreign/unproven/canonical-in-use 一律继续 fail closed，绝不原地覆盖或修补可疑 bytes。托管 core 的 orphan inert gate（`evaluateManagedLayoutGate`）必须在 `resetDebugLog()` / PID walk / bridge / handler 注册之前，owner marker 缺失、损坏、agentId 不匹配或 `activeSourceMarker` 不存在时返回空 handler；source-direct 模式保持原行为。MiMo 保持 broad-basename register/unregister/Doctor 契约不变。\n- Pi 通过 `~/.pi/agent/extensions/clawd-on-desk` 的 global extension 推送状态；Clawd 对 Pi 是 **state-only**，不接管权限、不弹权限气泡，也不把 Pi 的默认 YOLO 流程改成手动确认\n- OMP (oh-my-pi) 通过 `~/.omp/agent/extensions/clawd-on-desk` 的 global extension 推送状态，agent id `omp`，对 Clawd 同样是 **state-only**。它是 Pi 的 fork（包名 `@oh-my-pi/pi-coding-agent`），所以 `hooks/omp-extension.ts` 刻意与 `hooks/pi-extension.ts` 保持逐行对齐（只差 package import、core import 与函数名），进程树遍历与终端识别不得各自漂移；OMP 独有的差异全部收在 `hooks/omp-extension-core.js`。**完成必须走 `session_stop` 候选 + 终态 `agent_end` 提交的两阶段协议** —— `session_stop` 先保留主会话边界，OMP 再汇总所有 extension 的续跑请求；只有后续 `agent_end.willContinue !== true` 才向 Clawd 发完成。不得直接把任一事件单独映射为完成：仅用 `agent_end` 会把 subagent/调度边界误报为完成，仅用 `session_stop` 则会早于 extension 续跑判定。`session_switch` / `session_branch` 要为被切走的旧 session 补发一条合成 `SessionEnd`，否则 Clawd 会留下一条再也不会有人上报的活动行。session id 命名空间是 `omp:<raw>`，且必须始终带 `session_title`（多个交互式会话合法地共用同一个 cwd，缺标题会让列表和跳转目标无法区分）。安装器遇到社区桥接 `~/.omp/agent/extensions/clawd-on-desk-omp.ts` 时必须 fail closed 跳过：两者上报同一批事件，同时存在会双发。当前 `assets/source/agent-icons/omp.png` 是 `fallback: true` 的占位 π 字形，不是 OMP 官方品牌素材，拿到授权素材后应替换\n- DeepSeek Harness 首发是 **web profile / Windows-first experimental / plugin-only**；rc.6 已于 2026-08-29 完成 macOS / Windows x64 源码运行的真实 API-backed session/approval smoke（#962）；rc.2 Windows packaged-app 证据仅覆盖安装、web boot 与直接 bridge client 的 state/Allow/Deny 往返（#938），不得合并宣称 rc.2 安装包的真实 API 会话已验证。Clawd-managed in-process plugin 监听公开 `session/created`、`session/event`、`session/disposed`、可选 `sessionProjections.onChanged` 与 blocking `approval/request`；标题和上下文仅作为会话元数据同步，不占用生命周期 seq。状态按 session FIFO 上报并携带上游 seq；Clawd 不读取 `$DSH_HOME/storages` projection。普通审批进入独立 DSH `/permission` adapter，只支持人工 Allow Once / Deny；204 / 断连 / DND / disabled 都由 plugin `next()` 交还 DSH 原生 web answerer。`ask_user_question` 始终留在 DSH 原生 provider；DSH 不进入 `KNOWN_PERMISSION_AGENTS`，auto-tools / unattended / per-session grant 全部 DEFER。安装器通过官方 `dsh plugin --profile web add/remove` 管理 immutable marker-owned generation，foreign 同名包 fail closed；版本放行改成按 **小版本族（major.minor）**。维护两张表：一张是唯一写出具体版本/npm artifact/integrity 的已验证 artifact 清单（优先 `@deepseek-ai/dsh@0.2.0-rc.2`（integrity `sha512-EAJ3gPNcVt/uv8X19PMm9NkVhWgT7xXNMk0UKCVm+IQ5rpSQOcsMUa0HWlnYYVybKMsccjcRB21vVVsaXQ6IdA==`，2026-10-04 已做静态接口核对，并在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证了用 Clawd 安装器装出的 generation 的启动同步换代、会话状态、HUD 标题/上下文、Allow/Deny 与消息上的失败标记；其 `tool/result` 把失败标记放在消息 `message.isError` 而不是内容项上，bridge 新旧两种位置都认），并保留 `@deepseek-ai/dsh@0.1.5-rc.3`（integrity `sha512-c0W6Xqc4ChjFcCJkbzPeIxZQdnbKqe+QAcJzWGtogg0ZzsnZRcw3vopMyZ5oZU6E2fmyqGcyDR1sBeiCH4yHcg==`，2026-09-27 已在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证启动同步安装、会话状态、HUD 标题/上下文与 Allow/Deny）、`@deepseek-ai/dsh@0.1.5-rc.1`（integrity `sha512-rmNmzQCg3oIc1z8xH7izRSOuy1TNzq+/NILyfM+7e8DKOyV+yBtg47WEsqR2SiIe1ATec3L/rUa1YhIcfQ2XEg==`）、`@deepseek-ai/dsh@0.1.1-rc.2`（integrity `sha512-UP1UIh6q3Gme/yXRn/QL2P8IsVlv8Shpg22TRJIZPsCRWLm4CBiA1MUvXmJAfsOEETBMLAl+xWPtFw6ICsN3wg==`）与 `@deepseek-ai/dsh@0.1.0-rc.6`（integrity `sha512-brpZfED7ieRa2PQ5tUxMhHrM1pb2CmKFVM/f6yMULBDMicahk+Z2OsHgTwTDnoiZm23Ftu9rQz0NN4pflaoJcg==`）），一张是族表（`0.2` 下限 `0.2.0-rc.2`、`0.1` 下限 `0.1.0-rc.6`）。host 版本经严格解析（拒绝前导零、空预发布标识与 build 元数据）通过、major.minor 命中族、且不低于该族下限即放行；同一族内不同 host 版本共用一个 generation，出现新的小版本必须重新验证并新增一个族。旧的精确 `=<version>` marker 仍按原 range 核对哈希，新 generation 一律写族 range；Install/Repair 按 host 版本所在的族选择目标契约，Uninstall / 手动 npx 命令在 marker 版本已列入清单时钉它自己的 artifact，否则钉同族版本最高的已验证 artifact（无 CLI 且无 marker 时用首选族最新的并记为 assumed）；加锁前后比较的是实际检测到的 host 版本，不看族。DSH 的 `metadata_only` 标题/上下文旁路必须核对目标会话的 `agentId` 确为 `deepseek-harness`，撞名的其他 agent 会话直接丢弃。`47f9438` 仅是源码调查基线，不代表任何 tag/commit 映射。\n- DSH 每个 canonical `DSH_HOME` 的 mutation lock 只有在 owner/schema/token/PID/timestamp/owner-recorded operation timeout 合法、超过该 owner timeout 两倍、且 OS PID probe 明确为 `ESRCH` 时才允许 atomic-rename takeover；live、`EPERM`、unknown、corrupt/foreign owner 一律拒绝并返回精确 lock path。canonical lock 的 owner write/release 禁止 recursive cleanup。无全局 CLI 时生成的手动 npx generation 必须先在同一锁内写 owned reference，手动 add/remove 命令必须显式 pin shell-quoted canonical `DSH_HOME`；malformed/foreign/concurrently replaced reference 一律 fail closed 并保留 generation\n- DSH 桌面版支持（#1119）与 web 共用一个 agent id `deepseek-harness`：web profile 和 DeepSeek Harness 桌面版是两个承载方、各自一个 profile（桌面版是 `$DSH_HOME/profiles/desktop`），但在 Settings 和 Doctor 里仍是**一行**，显示名 `DeepSeek Harness (experimental)`，一次排队操作先 web 后 desktop、一边失败不影响另一边；安装只要有一边核实健康即成功（另一边失败变 warning + 常驻提示），卸载要所有 Clawd 注册都没了才成功。桌面版查找：macOS 用 `/Applications` 或 `~/Applications/DeepSeek Harness.app` 里自带的 `Contents/Resources/runtime/cli/bin/dsh`；Windows 按用户安装，从 `HKCU` 卸载项（显示名以 `DeepSeek Harness ` 开头）与 `%LOCALAPPDATA%\\Programs\\DeepSeek Harness` 找 `resources\\runtime\\cli\\bin\\dsh.cmd`，注册表用 PowerShell 读 UTF-8 JSON、不用 `reg.exe`；Linux 不支持桌面版。静态版本来自 `Info.plist` / 卸载项 `DisplayVersion`，真正动手前跑一次启动器 `--version` 核实。桌面版**永不用 npx**，手动 npx 命令与 manual reference 只属 web。每边角色是 `mutable` / `diagnose` / `not-applicable`：桌面版没装、或 profile 从未初始化（桌面版没打开过）→ 不适用并提示打开一次；foreign 同名包、文件读不了、清理残留、注册查不清、版本不支持、装了不止一个桌面版（`multiple-desktop-installs`）、桌面版找不到但注册还在（`carrier-unavailable`）、桌面版查不清（`desktop-unverifiable`）→ 只报告不动手。启动同步在集成已安装且启用时会把插件加进已初始化的桌面版 profile；桌面版开着也会加载新加的插件，只有插件更新（换了 generation）后要重启。常驻提示在 `hooks/dsh-notices.js`，按 profile 存 `notices-web.json`/`notices-desktop.json`，四种 kind（`restart-required`/`first-install`/`manual-command`/`failed-target`），写不进去只算 warning；提示显示在 Settings → AI Coding Tools 里这一行下面。Doctor 一行详情 `web: …; desktop: …`，状态取适用边里最差，只要有一边能尝试修复且不健康就给修复按钮（`src/doctor-detectors/agent-integrations.js`）。插件在 DSH 里被关掉（依赖在、bundle 行没了）时 `plugin add` 不会重开：显式修复先 remove 再 add（add 前先清掉上游 remove 留下的自有链接，Mac 是符号链接、Windows 是 junction），按 profile 记 `repair-operation-<profile>.json`，中断后下次显式修复续做，启动同步只报 `plugin-disabled-in-dsh`。`generations/` 两边共享，任一边有未处理状态（检查记录、清理残留、坏修复记录或 manual reference、读不了的 profile、符号链接 profile 目录）时清理暂停但不挡安装，卸载残留进 warnings。检查记录按 profile：web `inspection-required.json`、桌面版 `inspection-required-desktop.json`。`plugin add/remove` 写命令两边都超时 300 秒（web 原 120 秒），比上游写锁等待长。上游 `dsh plugin remove` 只清 `link:` 清单和锁、`node_modules` 链接会留下，Clawd 卸载自有插件时确认归属后清掉。Windows 静态查找是同步代码、不起进程，只读异步快照：启动时（不管 DSH 是否启用）、打开 Doctor 前、Agents 页手动扫描时刷新，没快照时桌面版显示\"查不清\"。安装检测把\"找到桌面版\"也算装了 DSH（`src/agent-installation-detector.js`）。桥接插件在 apply 时读 `ctx.profileContext?.name`，只有 desktop profile 才在 state / 审批载荷里带 `dsh_carrier: \"desktop\"`（metadata 不带；web 或未知 profile 一律不带）；Clawd 只接受 DSH + `dsh-plugin` + 本机 + 非 WSL 的载体，按生命周期覆盖或清除、不粘滞，权限 fallback entry 与快照（含签名）都带上它。点击桌面版会话时 `getSessionFocusTarget` 在 darwin/win32 返回 `dsh-desktop`（`dsh://open`），分派先 `shell.openExternal(\"dsh://open\")`，被拒绝再按 `discoverDshDesktopSync({ requireUniqueApp: true })` 的兜底要求唯一安装启动界面程序（macOS `open <appRoot>`、Windows 启动 `<appRoot>\\DeepSeek Harness.exe`，去掉 `ELECTRON_*`/`NODE_OPTIONS`，不用 CLI 启动方式；两份真实路径不同的有效安装视为有歧义，只要还有核实不了的候选也不自动启动，同一份安装的符号链接只算一份）；只能打开应用窗口、不会切到具体对话，web 会话仍不可跳；桌面版启动时会重新打开上次的对话，Clawd 只在这个对话有了动作（提问、工具调用、审批）之后才把它放进 Session HUD（`awaitingActivity` 并入快照 `hiddenFromHud`，但不关跳转；与 Kimi Code 共用同一个标记），Dashboard 照常列出、按钮照常可跳；2026-10-05 macOS 26.6.2 与 Windows 11 x64 源码运行真机验证（桌面版 `0.2.0-rc.2`）：别的窗口在前、最小化、关窗后，点击都经 `dsh://open` 把窗口带到最前；协议打不开时的启动兜底只有单元测试。真机证据：2026-10-04 macOS 源码运行（Clawd `ac64d726`，桌面版 `0.2.0-rc.2` + 全局 `@deepseek-ai/dsh@0.2.0-rc.2`）验证了启动同步把插件装进桌面版（与 web 共用 generation）并出现\"已装进桌面版\"提示、Doctor 一行两边正常，桌面版真实会话的 Allow 建成文件、Deny 后文件内容和 mtime 不变且 Clawd 显示 `PostToolUseFailure`，\"知道了\"后提示消失，改 bridge 源码（同 Clawd 版本）后启动同步两边报 `generation-conflict` 并提示去 Doctor 修复、修复把两边换到新 generation/删旧/出现\"重启桌面版后生效\"、重启后事件来自新宿主进程，设置页卸载后两边依赖与 bundle 行都没了、上游残留链接被清、generation 删除、两边提示清空，再在设置页安装两边都重新装上、桌面版重新出现\"已装进桌面版\"（\"经设置页首次安装\"因此已覆盖），开着 DND 时桌面版的工作区外写文件不弹 Clawd 气泡、返回 no-decision、桌面版弹自己的原生审批框、批准后文件建成且事件照常到达。2026-10-04 Windows 11 x64 经 SSH 用 Node 直跑安装器代码（管理员会话，桌面版在 `%LOCALAPPDATA%` 按用户安装 `0.2.0-rc.2`、全局 dsh `0.1.0-rc.6`，web 在 0.1 族、桌面版在 0.2 族）：PowerShell 读注册表找到桌面版、静态模式无快照时报\"查不清\"且不起进程、自带 `dsh.cmd`（带空格路径）`--version` 返回 `0.2.0-rc.2`、`dsh.cmd plugin --profile desktop add` 经 pnpm junction 装入并核实、记录\"已装进桌面版\"、两族各用一份 generation 并存、Doctor 一行两边有修复按钮、卸载桌面版清依赖与 bundle 行并清掉 `dsh plugin remove` 残留 junction、只删桌面版那份 generation 而保留 web 在用的；2026-10-04 另在 Windows 上以真 Clawd（Electron，源码运行、用户会话、普通权限）验证：先抓到一个只在 Electron 里出现的 bug（Electron 的 fs 把 `app.asar` 当目录、Windows 安装目录核实要求它是文件，于是在真 Clawd 里桌面版被判成没装，已在 `d8190692` 修成\"存在即可\"）；修好后桌面版一直开着（宿主进程未重启），启动同步把插件装进桌面版并记\"已装进桌面版\"，在桌面版新开对话的事件来自那个未重启的宿主进程，**Windows 上桌面版开着也会加载新加的插件**。**未覆盖**：Windows 上桌面版的审批、Windows 上的 Electron 界面（设置页提示、Doctor 窗口、启动预热）、打包后的 app、Linux、HTTP 204 交还与取消、装了多个桌面版。**管理员 junction 观察（推断）**：提升过的管理员进程在 Windows 11 上穿不过非管理员进程建的 junction（PowerShell \"untrusted mount point\"、Node `UNKNOWN`），该会话里 web 的旧 junction 读不到、web add 失败，桌面版同会话新建的 junction 正常；普通权限运行不受影响；由此推断以管理员身份运行 Clawd 可能把普通权限装好的插件读成缺失，未用以管理员身份运行的 Clawd 直接复现\n- OpenClaw 通过 `~/.openclaw/openclaw.json` plugin 路径做 state-only 集成；Phase 1 不做 permission bubble / terminal focus，主要支持本地 `openclaw tui --local`\n- Antigravity CLI (agy) 通过 `~/.gemini/config/hooks.json` 做 **state-only** hook 集成（PreInvocation / PostToolUse / PostInvocation / Stop），**不注册 PreToolUse**。agy LLM 会主动调内置 `ask_permission` 工具，触发 agy 自己的 5 选项 native menu（含 \"Persist to settings.json\" 持久白名单），Clawd 不插手权限决策也不双层确认。`agents/antigravity-cli.js` `capabilities.permissionApproval` / `interactiveBubble` 均为 false。\n- Qwen Code 通过 `~/.qwen/settings.json` 做 hook-only 集成（SessionStart / SessionEnd / UserPromptSubmit / PreToolUse / PostToolUse / Stop / Notification / PermissionRequest），支持状态与阻塞式 `PermissionRequest` 权限气泡；`disableAllHooks: true` 时注册条目不会触发。\n- QwenWork (千问办公) 通过 `~/.QwenWorkCN/settings.json` 做 **hook-only / state-only** 集成（agent id `qwenwork`；SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / Notification / PermissionRequest / PermissionDenied / SessionEnd）。`PermissionRequest` / `PermissionDenied` 只作为观察映射成 `working`（每任务 40+ 次，映射成 notification 会刷屏），hook stdout 恒为 `{}`：Clawd 不产生 allow/deny，不注册 `/permission`，也不进入 permission automation eligibility，唯一决策者是 QwenWork 原生权限流程；`agents/qwenwork.js` 的 `capabilities.permissionApproval` / `interactiveBubble` 均为 false。Windows command 必须保持 `windowsWrapper:\"portable\"`（QwenWork 经 POSIX shell 执行 command hook），PowerShell `-EncodedCommand` **只**用于识别并原地迁移旧条目，不是当前写入形态。marker 只认 `qwenwork-hook.js`，不得仅凭 `name:\"clawd\"` 删除用户 hook；混合 entry 中第三方 hook 原样保留。session id 命名空间是 `qwenwork:<raw>`；`~/.QwenWorkCN/workspace/<id>` 这类内部工作区 cwd 不做 basename 回退，避免 HUD/Dashboard 显示内部 ID。当前真实支持平台只有 macOS / Windows 桌面端（官方下载页 https://qwenwork.cn/download 只提供 macOS 14+ / Windows 10+ / HarmonyOS 6.1+，没有 Linux 客户端），因此 `processNames.linux`、resolver linux agent name 均为空，也不进 `src/wsl-deploy.js` 的 WSL Pair 映射。桌面主进程长驻、不代表 active turn，`startupRecoveryProcessNames` 全空、无 startup recovery。安装/卸载走 Settings → AI Coding Tools，或 `npm run install:qwenwork-hooks` / `npm run uninstall:qwenwork-hooks`；卸载必须同时在 `hooks/cleanup-integrations.js` 的 `MANAGED_AGENT_IDS` / `AGENT_CLEANERS` / `byAgent` 里有条目，否则 About cleanup 只会改 prefs、hook 留在磁盘上\n- ZCode 通过 `~/.zcode/cli/config.json` 的 `hooks.events.*` 集成全部 7 个支持事件（SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / PermissionRequest，无 SessionEnd / Notification）。PermissionRequest 为阻塞式权限审批：hook 长连接 `POST /permission`（HTTP 等待 590s，installer 注册 `timeoutMs: 600000`），有决定时 stdout 返回最小合法 `{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}`（deny 可带 `message`），无决定 / 超时 / 断连 / 任何错误输出 `{}` 并 exit 0，ZCode 回退原生权限流程；`interrupt` / `updatedInput` / `updatedPermissions` / `permissionUpdates` 必须 omit（最小输出 union 按 ZCode 3.5.x 严格 schema 约束；macOS ZCode 3.8.1 已完成真实 hook / 气泡 Allow/Deny 往返，3.5.x PermissionRequest 真机往返未覆盖）。超时单位陷阱：ZCode `timeout` 是秒、`timeoutMs` 才是毫秒，且超时按事件区分（PermissionRequest 600000、state 事件 8000）。Phase 2 只允许人工审批：ZCode 不进入 `KNOWN_PERMISSION_AGENTS`，global / per-session permission automation 在工具面与会话身份审计完成前全部 defer。prefs v14→v15 迁移把 Phase 1 持久化的 `zcode.permissionsEnabled:false` 翻 true（当时开关从未渲染、无用户意图）。配置必须有 `hooks.enabled=true` 才会执行；安装器只在该字段缺失时补 true，显式 `hooks.enabled=false` 或 Clawd 单项 hook 的 `enabled=false` 必须保留，Doctor warning 且不提供会覆盖用户选择的 Fix。ZCode 导入 Claude 配置后，只清理 `.zcode` 中明确引用 `clawd-hook.js` 的 Clawd-owned 条目，绝不改 `~/.claude/settings.json`。安全边界（复核后新增）：`/state` 生命周期 sweep 对 zcode（及 qwen/DSH 等 native-fallback adapter）只允许 no-decision，绝不伪 deny；hook 侧 `tool_input` 预算内原样发送、任何截断（长 Bash 尾部 `rm -rf` 场景）或序列化超 512KiB 一律 fail-closed 输出 `{}` 交还原生 UI；无 allow/answer/plan capability 的 interaction（如 ZCode 真实的 ExitPlanMode / AskUserQuestion）本地气泡与远程卡片都不提供决定入口、直接 204；全局气泡关闭只关本地窗口，Telegram/飞书 remote-only 审批仍可用（per-agent gate 关闭才是全退出）；installer 遇到 foreign `PermissionRequest` hook 时不注册自己的 blocking hook，若 foreign hook 后出现则移除自己的 managed hook（ZCode 同事件 hook 串行执行、后写覆盖，Clawd allow 会盖掉用户 hook 的 deny），Doctor 报 `permission-conflict` 且不给 Fix；六个 Phase 1 managed hook 全部显式 disabled 时新 PermissionRequest 继承 `enabled:false`；服务端 pre-parse 超限一律断连回退，不伪造 deny\n- Qoder / Qoder CN 共用 `qoder` agent，通过 `~/.qoder/settings.json` / `~/.qoder-cn/settings.json` 做 **state-only** hook 集成；各自尊重 `QODER_CONFIG_DIR` / `QODERCN_CONFIG_DIR`，同步所有已初始化目录，不创建缺失版本目录，卸载/cleanup 覆盖两版且只移除 Clawd entries，Doctor 不得让健康的一版掩盖另一版故障。Clawd 只把 `PermissionRequest` / `PermissionDenied` 当 notification 观察，**不替 Qoder 做权限决策**，hook stdout 恒为 `{}`；Windows command 必须保持 `windowsWrapper:\"portable\"`。session id 命名空间是 `qoder:<raw>`；启动恢复只认 CLI `qodercli` / `qoder-cli` / `qoderclicn`，不认闲置 IDE / CN 桌面进程；本机原生会话标题由 `src/qoder-session-title.js` 低频异步增量读取，通过 `updateSessionMetadata` 更新；SessionEnd / 禁用 / 退出取消旧读取，远端与 WSL 路径不在本机读取。2026-10-18 已核对 Windows CN runtime 1.1.69 的真实 SessionStart / UserPromptSubmit / Stop hooks，用户确认开启 Clawd Qoder 接入后任务状态恢复；macOS/Linux CN 未实测\n- TraeCode (Trae CN) 通过 `~/.trae-cn/hooks.json` 做 **hook-only / state-only** 集成。Windows command 必须保持 `windowsWrapper:\"encoded\"`：Trae 的 Windows Sandbox 会把 hook 命令作为 `trae-sandbox.exe --command-line` 的单个原生参数再次转发，普通引号或 `portable` 形态会在含空格路径处拆分；外层必须保持无引号的 PowerShell `-EncodedCommand`，POSIX 则继续使用普通 quoted command。该约束不适用于经 POSIX shell 执行 Windows hook 的 agent（如 Qoder / QwenWork）。\n- MiniMax Code 通过 `<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/` 的 **Clawd 独占本地插件**做 **state-only** 集成（manifest 用 `.claude-plugin/plugin.json`，hooks 文档按 MiniMax 的 CLAUDE sourceFormat 解析；不用 `.minimax-plugin/`，那会走 MINIMAX 格式：matcher 必须非空且不支持 exec-form args）。handler 固定 exec-form `command=node 路径 + args=[minimax-hook.js]`（spawn 直执行、无 shell、免引号），`timeout` 单位是秒且只接受 1–10 的整数（越界的 handler 被丢弃而不是钳制；SessionEnd 事件总预算仅 3s），因此 **PermissionRequest 物理上不可阻塞审批、完全不注册**，也没有 Notification 事件；hook stdout 恒为 `{}`（permissionDecision 缺省 abstain）。目录级所有权只认结构化凭据 `.clawd-managed.json`（`{app:\"clawd-on-desk\",integration:\"minimax\",managed:true,version:1}`，同 Pi 约定；MiniMax 只读 manifest 声明的文件，会忽略它），且凭据与所有受管理路径（`.claude-plugin/`、`hooks/` 及其文件）都不得是符号链接；目录名、manifest name、文档里的 basename/子串乃至整份文档指纹都永不授权改写或递归删除，缺凭据的目录（包括补丁前预发布构建写出的）一律 fail closed，只能手动删除后重装。staging / removal 目录固定落在数据目录（`plugins/` 之外，MiniMax 会把 `plugins/` 下每个目录项都当插件候选，含点号名）：首装在 staging 写全三份文件后一次 rename 发布（只覆盖空目标，非空目录/文件/链接拒绝；空 `clawd-state/` 视为未占用），失败时尽力删除 staging；已拥有的目录原地逐文件更新，中断后仍可证明归属、由下次安装补完。只有 ENOENT/ENOTDIR 算不存在，其他 lstat 错误按无法确认处理，绝不据此宣告卸载。卸载先把已验证目录 rename 出 `plugins/`、复验后再删；移走失败报 error 并保留安装意图，移走成功但删除失败时按已移除提交并在 warnings 里给出残留 `.clawd-minimax-removing-*` 路径，复验失败且移回失败时两个位置都报 `registrationRemoved:null` 并带 `residualPaths`；删不掉且目录仍运行 Clawd hook 时返回 `registrationRemoved:false`（读不清为 `null`），Settings / About 据此保留安装意图。删除后返回前还会复查一次原位置：此时若已有另一个 Clawd 实例重新发布的插件，报“仍在注册”（`registrationRemoved:false`）、不宣称卸载；这次复查是快照，复查之后、Settings 提交之前的安装不在本次结果里（多实例强一致需要覆盖 prefs 提交的跨进程锁，未做）。Settings 界面目前不显示成功结果里的 `warnings` / `residualPaths`：Agents 页安装/卸载只弹“已卸载/已安装”，About 清理只显示计数，只有命令行 cleanup 脚本会打印 warning。进程中途崩溃，或 staging 清理本身失败，可能在数据目录留下 `.clawd-minimax-staging-*` / `.clawd-minimax-removing-*`（MiniMax 不会加载，只能手动删除）；`plugins/` 与数据目录跨文件系统（EXDEV）时不支持。判断外来目录是否仍跑 Clawd hook 按 manifest 声明的 hooks 文档和 MiniMax 默认规则检查（含裸文档外壳、反斜杠路径，以及 shell 形式的 command / commandWindows handler）；Clawd 不建模的 manifest（根 `plugin.json` / `.minimax-plugin/` / `.codex-plugin/`）或读不清时按无法确认处理。node 探测失败时只保留全部 Clawd handler 一致、basename 为 node、存在且可执行、并通过 `node --version` 有界探测的已记录路径（exec-form 无 shell，Dock 启动的桌面 App 的 PATH 里没有 node），安装器与 Doctor 共用 `resolveDesiredNodeBin`。PostCompact 按 #406 上报 thinking（`trigger:\"manual\"` 时 idle），不是 attention。hook 的 `agentNames` 必须全小写（resolver 比较的是小写 basename），且不含桌面版的 “MiniMax Code Helper”：拉起 hook 的 NodeService helper 可能在 App 运行中重启，把它当 agent 会误删活会话，识别应落到长驻的主程序；mcode CLI 启动时执行 `process.title = \"minimax-code\"`，macOS/Linux 上 `ps` 报告的进程名就是 `minimax-code`（按名字匹配），Windows 上仍是 node.exe，靠 `agentCmdlineCheck` 只看 argv 里的脚本位置识别（命令行检查的进程名沿用共享默认 `DEFAULT_AGENT_CMDLINE_NAMES`，已含 Linux 上新版 Node 的主线程名 `mainthread` / `node-mainthread`，MiniMax 不再自带名单）（`node` 后的脚本 basename 是 `mcode`/`minimax-code` 启动器，或脚本路径含 `/@minimax-ai/code/` / `/.minimax-code/`），参数里的目录片段不算——MiniMax 退出时不发 SessionEnd，没有 agent pid 会话就无法按 agent-exit 清理。hook 不触发时的启用步骤在 MiniMax 应用内（`mcode plugin enable clawd-state@local` 或插件面板），磁盘上读不到启用状态，Doctor/Settings 只能提示。session id 命名空间 `minimax:<raw>`，标题走首行 prompt 派生 + 服务端 first-wins（同 traecode）。\n- Kimi Code（agent id `kimi-cli`）的 agent pid 靠进程名识别：CLI 启动即 `process.title = \"kimi-code\"`，libuv 把标题写回原 argv 所占的空间、放不下就截断，所以 macOS/Linux 上 `ps` 与 `pgrep -x` 看到的名字随启动命令长短而变（0.42.0 原生版实测：`kimi` 仍是 `kimi`，`kimi -c` 是 `kimi-co`，`kimi --yolo` 或全路径启动是 `kimi-code`；只有整条启动命令比 `kimi` 还短时（例如不带参数的软链接 `k`）才认不出，`k -c` 显示的已经是 `kimi`）。`hooks/kimi-process-names.js` 必须列全从 `kimi` 到 `kimi-code` 的每一种截断，resolver 与 startup recovery 共用这一组，只写 `kimi-code` 会漏掉 `kimi -c`。拉起 hook 的就是这个改名后的主进程（TUI 在进程内跑 agent 引擎，从 SessionStart 到 SessionEnd 同一个 PID）；其他同名进程（后台更新下载器、经 kimi 二进制跑的插件进程等）都是它的子进程，不跑 hook。resolver 比较小写 basename，macOS 桌面版 `Kimi Code.app` 写成 `kimi code`（它的 agent server 跑在主进程里，hook 由主进程直接拉起）；桌面版关窗后常驻托盘、不代表在干活，同其他桌面 App 一样不进 startup recovery。Windows 上标题只改控制台标题：原生版仍是 `kimi.exe`，npm 版仍是 `node.exe`，命令行检查只认包目录 `/@moonshot-ai/kimi-code/`，不能退回“含 kimi 就算”（Kimi 本身没被认出时，任何命令行提到 kimi 的 node 祖先都会被当成 agent）。Kimi Code 正常 `/exit` 会发 SessionEnd，但关终端、`kill`（0.42.0 实测：SIGTERM 与 SIGKILL 都不发；源码里 SIGTERM 注册了 `stop(143)`，实测为什么没发 SessionEnd 还没查清）、崩溃都不发；没有 agent pid 的会话只要终端 App 还开着就一直留在列表里。桌面端启动时会恢复上次查看的对话、在侧栏点开旧对话也一样，这类只发一条 SessionStart、还没有任何动作的对话不进 Session HUD，Dashboard 照常列出、按钮照常可跳，出现提问/工具/审批/Stop 等动作后自动进 HUD（与 DSH 共用同一个 `awaitingActivity` 标记）。\n- HTTP 服务端口范围固定为 `127.0.0.1:23333-23337`；运行时端口写入 `~/.clawd/runtime.json`\n- Mobile Preview 是独立的 LAN listener，候选范围为 `0.0.0.0:23334-23338`；它不写 `runtime.json`，不得把该范围误写成 hook / custom-agent HTTP ingress 范围\n- 自定义 HTTP Agent 的 sender 必须读取 `~/.clawd/runtime.json`，不能把 23333 写死；注册不等于已连接。custom v1 只支持 `/state`，不支持 `/permission`\n- CodeBuddy PermissionRequest hook 的所有权只认本机 managed URL 或 marker `clawd-on-desk.permission.v1`；纯 `name:\"clawd\"` 不能触发改写/删除。裸 CLI 和 WSL 默认 preserve，Settings/startup/repair 必须显式传 local/custom permission target\n- Remote SSH 的远端 Node 探测要求 Node >= 14；Node discovery/version validation 只在 `src/remote-ssh-node.js`，ordinary tunnel health 与 serialized readiness 在 `src/remote-ssh-runtime.js`，不得互相复制或从已停用脚本另起实现\n- 注册 Claude Code hook 必须 marker-scoped merge：只可更新/删除含 `clawd-hook.js` / `auto-start.js` marker 的 Clawd-owned entry，不得整体覆盖数组或改动无 marker 的用户 entry\n- 注册 Claude Code statusLine 默认只接管空槽或自己的槽（marker `claude-statusline.js`）；本机 Settings 显式开启采集遇到第三方槽时，必须经共存确认并复核原槽指纹，使用 `--local-chain` 和独立的 `clawd-statusline-local-chain.json` 保存/恢复完整原对象。启动/自动修复不得自行取得第三方槽；恢复记录缺失、损坏或不匹配时 fail closed 并保留现场。远程部署仍用 profile 的 `chainStatusline` opt-in 和既有 `--chain` sidecar，不与本机记录混用。订阅配额通过 `metadata_only` POST 进入 session-independent `updateAccountQuota` per-source store；不要把 quota 塞进 `updateSession` opts，也不要以 session 存活作为摄入前提\n- Copilot CLI hooks 走按需自动同步：`hooks/copilot-install.js` 在本地启动仅当 Copilot CLI 已安装且已启用时调用；远端由 Settings Remote SSH deploy controller 调用。路径解析尊重 `COPILOT_HOME` env（trimmed 非空才生效，否则 fallback 到 `~/.copilot`）；`hooks/copilot-hook.js` 的 session-state resolver 同样走 env\n- Remote SSH 的 effective transport 由 `ssh -G` 只读检查决定：ordinary SSH 在没有 retained serialized occupancy 时保持 `context:null` 的 parallel 路径；serialized transport 以有效 target key（不是 profile id）互斥。所有 serialized managed SSH/SCP child 必须持 coordinator 发出的有效 connection/operation context，并通过其 pre-spawn gateway 启动；用户交互终端只有命中 serialized/retained occupancy 时才要求 coordinator 判定 target 完全 idle\n- serialized persistent tunnel 使用同一条 SSH 内嵌 readiness；暂停通过 stdin EOF 请求自然退出并等待 `close`。强杀或带 signal 的 outer `ssh.exe` close 不能证明 nested ProxyCommand 已 drain；timeout/未验证 drain 必须 quarantine，期间禁止新 child、mutation、resume 或 interactive terminal\n- mutation 在 deploy-lock acquire-attempted / lock-owned 后遇到 exit 255、EOF/reset、signal 或其他 unknown result 时不得自动 replay、retry、release lock 或恢复连接；必须保留 primary error 并传播 recovery state，必要时要求 `manual_lock_inspection_required`\n- Remote SSH secure hook 必须同时携带 `CLAWD_REMOTE=1` 与 `CLAWD_SSH_REMOTE=1`，只读 layout identity 并 pin 精确端口；identity 缺失/损坏/不可读必须 fail closed，禁止回退端口扫描\n- Remote SSH deploy-lock acquisition 必须原子化；成功 acquire 后的每个 live mutation 都要在同一远端命令内 fencing 校验，cleanup 还必须锁内重读 installId/profileId/runtimeKey/layoutVersion 所有权。无身份、冲突、ownerless/corrupt lock 均不得自动接管\n- 默认 `account-default` 只支持不同 Unix 账号；同 Unix 账号冲突必须阻止。`profile-isolated` 在真实 SSH/CLI 矩阵完成前由 `CLAWD_ENABLE_EXPERIMENTAL_REMOTE_ISOLATION=1` 发布门隐藏；它只隔离用户级 CLI config/session/runtime 与 Clawd 路由，不代表完整 HOME 或同 UID 安全隔离，project 配置/部分 cache/macOS Claude Keychain auth 仍可能共享\n- Hermes Agent 的 Remote SSH 部署是 `secureDeploy` 内的 `hermes-files` → `install-hermes` 两个阶段，复用同一条 serialized transport、deploy lease、fencing 与所有权检查，没有独立的 Hermes SSH deployer：secure 模式由每个托管 `plugins/clawd-on-desk/` 内的 plugin-local marker `clawd-ssh-secure-v1` latch，latch 后 identity 必须在每次 state/probe/permission 请求时重新读取（禁止 `(mtime,size)` 缓存），且不得发送任何远端 PID / 进程树 metadata；plugin 资产走独立 staging 目录，清理只 `rm -f` 精确文件再 `rmdir`，禁止 `rm -rf`；`REMOTE_IDENTITY_STEP_NAMES` 保持冻结的 8 步不变，不得加入 `installHermes`；Clawd 绝不自动重启 Hermes gateway，托管模块被替换时只报告需要手动重启\n- 禁用 agent 不应卸载 hooks / plugins / extensions：只停止对应 monitor、清理 session / bubble、让 HTTP hook 入口快速 fallback；重新启用未安装 agent 不触发本机 integration sync。卸载集成必须走 Settings Agent 页的 Uninstall / 对应 uninstall 命令，并同时清掉 `integrationInstalled`\n- Kiro 的 `sessionId=\"default\"` 会复用；session alias key 必须按 cwd scope 区分，同时保留旧 `local|kiro-cli|default` 只读 fallback\n- Windows NSIS release 必须产出明确架构的 x64 / ARM64 安装包：`win.artifactName` 保留 `${arch}`，`nsis.buildUniversalInstaller` 保持 `false`\n- 每个 release target 只能保留一个匹配目标架构的 Koffi `koffi.node`；`afterPack` 只允许剪裁 `app.asar.unpacked` 的物理文件，禁止重写 `app.asar`，并必须通过完整 native inventory audit（唯一常设例外是 electron-builder 管理的 Windows ia32 `resources/elevate.exe`）\n- 资源路径统一用 `path.join(__dirname, ...)`\n- 需要编辑发布素材时，先复制到 `assets/source/` 再改，不要直接改工作素材来源不明的文件\n- `assets/source/cloudling-pointer-bridge/` 是 Cloudling 指针桥素材的保留源文件目录；运行时逻辑已内联进主题 SVG，不要把这个 source 目录当临时文件清理\n- 主题状态、sleep/DND、mini mode、状态映射的细节在 `docs/project/theme-state-ui.md`\n- 官方可下载主题（`official-theme-*`）是受管分发层，不是 built-in、也不提升信任：catalog 是固定远端小目录（renderer 只能传 themeId），下载走 Electron main `net.request` 的 manual redirect + 精确 CDN host allowlist + 固定 bytes/SHA-256（未支持 host 返回稳定 `DOWNLOAD_HOST_UNSUPPORTED`，不允许 catalog 扩展 allowlist），ZIP 只在 manager 专属 staging 内流式解压并以 marker-before-rename 同卷提交，最终以 `isBuiltin=false` 加载（`trustedRuntime` 无效）。`setThemeSelection` / `removeTheme` / `officialTheme.commitInstall` / `officialTheme.uninstall` / `theme` update 共用 `lockKey=\"theme\"`；卸载 active 主题必须等 `waitForThemeReloadSettled()`。主仓库附带一份目录快照 `src/official-theme-catalog-snapshot.json`：网络拉取失败时列表先用上一次成功加载的目录（内存 LKG 或磁盘缓存），都没有才用快照；第一次拉取有结果之前（`uninitialized`）不用快照；快照**不作安装依据**，安装仍只认经校验的网络/磁盘目录。快照只作列表回落（仍显示 `offline` 和重试），不含素材与预览图，不写磁盘缓存，且参与版本不能回退的比较；发布前用 `npm run update:official-theme-snapshot` 刷新。不要把 Hash Sage / Whale-chan 的动画素材（APNG / WebP），或把它们写成内置主题的文案带回主仓库\n- Settings 体系里，store 是唯一真相，controller 是唯一写入者；不要绕开 `settings-controller.js`\n- Dashboard 数字快选是**完整 Dashboard 同一页面的临时键盘模式，仅 macOS/Windows**；Linux 明确 NOT SUPPORTED（不是待验证）。平台 gate 的唯一真相是 `shortcut-actions.js` 的 `supportedPlatforms` + `isShortcutActionSupported()`，Settings 展示、globalShortcut 注册/录制、设置命令和冲突占用都必须服从它；遗留的不支持绑定只忽略执行，不删用户 prefs、不占其他快捷键。darwin/win32 的 Dashboard 页面活在 `WebContentsView` 里，`BrowserWindow.fromWebContents()` 对它返回 null、BaseWindow 不触发 `ready-to-show`；页面 WC 一律从 owner 取。禁止用 `hide()`+`showInactive()` 归还已显示的普通宿主（实测会遮挡来源窗口），只能 opacity/input parking 并幂等恢复捕获值。详见 `docs/project/theme-state-ui.md`\n\n## Testing\n\n- 自动化测试使用 Node 内置 test runner：`npm test`\n- `test/*.test.js` 覆盖核心 unit/contract、installer、route、UI/runtime 与 Remote SSH transport/coordinator/identity；部分 fixture 会启动 Node、shell 或 Git Bash 子进程，缺少依赖时可能 skip，不能把全套结果概括成纯逻辑或等价真机验证\n- Remote SSH 真机矩阵与记录在 `scripts/manual/README.md`；Windows OpenSSH + Codespaces stdio 边界及 ordinary-host V15 release gate 不能从 unit tests 互相推断，无法执行时必须明确记录 pending / residual risk\n- Windows Terminal 真机、GUI smoke 与清理必须假定多个 tab/window 共享进程：不得按 PID/进程名 `taskkill`、`Stop-Process` 或宽泛终止 WindowsTerminal、Codex、`cmd.exe`、`ssh.exe`、OpenConsole、conhost。测试终端只能在明确 test-owned session 内 `exit`；无法证明 ownership 就保留现场并请用户手动关闭\n- 当前开发环境是 Windows-first；macOS 特定路径无法在这里手动 QA，改到 mac 逻辑时要用 code-review",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.claude-plugin/plugin.json)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md\n\nThis file is the entry point for coding agents working in this repository. Keep it short and operational. Durable architecture lives in `docs/project/`; `docs/plans/` and `docs/investigations/` are historical evidence unless this file explicitly links them.\n\n## Project Overview\n\nClawd 是一个 Electron 桌宠：通过 hook、日志轮询、plugin 和 extension 感知 AI coding agent 的工作状态，并播放像素风动画。当前支持 Claude Code、Codex CLI、Copilot CLI、Gemini CLI、Antigravity CLI (agy)、Cursor Agent、CodeBuddy、WorkBuddy、Grok Build、Kiro CLI、KiroCrew、Kimi Code CLI (Kimi-CLI)、Qwen Code、ZCode、CodeWhale、opencode、MiMo Code、Pi、OMP (oh-my-pi)、OpenClaw、Hermes Agent、Qoder、QoderWork、QwenWork (千问办公)、Reasonix、DeepSeek Harness、TraeCode (Trae CN)、MiniMax Code；内置 Clawd / Calico / Cloudling 三套主题，支持用户主题，并可经 Settings 从独立 `rullerzhou-afk/clawd-themes` 仓库下载可选官方主题（Hash Sage、Whale-chan，external theme 权限、可卸载）；平台覆盖 Windows、macOS、Linux，UI 支持 en / zh / zh-TW / ko / ja / pt-BR / es。\n\n## Common Commands\n\n```bash\nnpm start\nnpm run build                  # default Windows package\nnpm run build:win:x64\nnpm run build:win:arm64\nnpm run build:win:all\nnpm run build:mac\nnpm run build:linux\nnpm run build:all\nnpm install\nnpm test\nnpm run verify:electron\nnpm run verify:release\nnpm run audit:assets\nnpm run audit:pr-history-assets\nnpm run audit:native-package -- --app-root <extracted-app-root> --target <target-id>\nnpm run create-theme\n\nnpm run install:claude-hooks\nnpm run uninstall:claude-hooks\nnpm run install:cursor-hooks\nnpm run install:gemini-hooks\nnpm run install:antigravity-hooks\nnpm run install:kiro-hooks\nnpm run install:kirocrew-hooks\nnpm run uninstall:kirocrew-hooks\nnpm run install:kimi-hooks\nnpm run install:qwen-hooks\nnpm run install:zcode-hooks\nnpm run uninstall:zcode-hooks\nnpm run install:codewhale-hooks\nnpm run uninstall:codewhale-hooks\nnpm run install:pi-extension\nnpm run uninstall:pi-extension\nnpm run install:omp-extension\nnpm run uninstall:omp-extension\nnpm run install:openclaw-plugin\nnpm run uninstall:openclaw-plugin\nnpm run install:hermes-plugin\nnpm run uninstall:hermes-plugin\nnpm run install:qoder-hooks\nnpm run uninstall:qoder-hooks\nnpm run install:qoderwork-hooks\nnpm run uninstall:qoderwork-hooks\nnpm run install:qwenwork-hooks\nnpm run uninstall:qwenwork-hooks\nnpm run install:reasonix-hooks\nnpm run uninstall:reasonix-hooks\nnpm run install:workbuddy-hooks\nnpm run uninstall:workbuddy-hooks\nnpm run install:grok-hooks\nnpm run uninstall:grok-hooks\nnpm run install:dsh\nnpm run uninstall:dsh\nnpm run install:codex-hooks\nnpm run uninstall:codex-hooks\nnpm run install:codex-debug-hooks\nnpm run uninstall:codex-debug-hooks\nnpm run install:mimocode-plugin\nnpm run uninstall:mimocode-plugin\nnode hooks/codebuddy-install.js\nnode hooks/opencode-install.js\n\nbash test-demo.sh [seconds]\nbash test-mini.sh [seconds]\nbash test-macos.sh\nbash test-oneshot-gate.sh [state] [seconds]\n```\n\n新安装默认只把 Claude Code 和 Codex 标记为已安装并启用；其他 agent 默认未安装、未启用。正常启动时，Clawd 只会为 `integrationInstalled=true` 且 `enabled=true` 的 agent 自动同步 Claude / Codex / Copilot / Gemini / Antigravity / Cursor / CodeBuddy / WorkBuddy / Grok Build / Kiro / KiroCrew / Kimi / Qwen / ZCode / CodeWhale / Qoder / QoderWork / QwenWork / Reasonix / TraeCode / MiniMax Code hooks、opencode / MiMo Code / OpenClaw / Hermes plugins 和 Pi / OMP extensions。Settings Agent 页的 Install 会安装并启用该集成；Uninstall 会卸载 Clawd 管理的 hook/plugin/extension，并同时把该 agent 设为未安装、未启用。单独关闭 enabled 只会跳过启动同步并屏蔽事件/权限入口，不卸载用户已有 hooks / plugins / extensions；重新启用未安装 agent 只打开事件入口，不会写本机集成文件。手动安装命令主要用于调试、重装或远程部署。\nSettings 注册的自定义 HTTP Agent 是独立模型：`customApplications` 是注册真相，对应 `agents[customId]` 必须显式保持 `integrationInstalled=false`。注册只分配 ID 和状态入口，不安装 hook、不观察进程；v1 仅允许已注册且启用的 ID 向 `/state` 上报，`/permission` 永远不提供决定。删除或伪造的 `custom-` ID 必须直接拒绝，不能降级成 Claude Code subagent。\nCopilot CLI 同步走 `<COPILOT_HOME 或 ~/.copilot>/hooks/hooks.json`，marker-based 增量合并只接管含 `copilot-hook.js` 标记的条目，用户其他 entry / 其他 `hooks/*.json` 文件原样保留；hooks.json 或 `settings.json` 顶层 `disableAllHooks: true` 时 doctor 报 warning（不挂 Fix 按钮）。详见 `docs/guides/copilot-setup.md`。\n\n## Read These Docs\n\n- `docs/project/agent-runtime-architecture.md`：运行时架构、模块边界、启动与数据流、多 agent、permission bubble、终端聚焦和自动同步\n- `docs/project/theme-state-ui.md`：状态机、主题系统、settings、mini mode、素材规则、平台限制、待落地 UI 决策\n- `docs/project/release-process.md`：发版 checklist、release note 核对、tag 触发 GitHub 打包和资产确认\n- `docs/guides/copilot-setup.md`：Copilot CLI 自动同步说明、`COPILOT_HOME` 兼容性、手动配置备选模板\n- `docs/guides/dsh-setup.md`：DeepSeek Harness web profile 与桌面版的实验性 plugin 集成状态与普通审批集成\n- `docs/guides/state-mapping.md`：状态 → 动画权威表\n- `docs/guides/guide-theme-creation.md`：主题作者指南\n- `docs/guides/setup-guide.md`：安装、远程 SSH、各 agent 接入\n- `docs/guides/custom-agent-http.md`：自定义 HTTP Agent 的 state-only 接入合约和动态端口发现\n- `docs/guides/known-limitations.md`：用户向已知限制\n- `docs/guides/recap.md`：本地小结的指标口径、coverage、时区/DST、隐私存储与产品红线\n- `docs/guides/codex-wsl-clarification.md`：Codex / WSL 路径与 Node 说明\n- `docs/guides/guide-remote-ssh.md`：Remote SSH 用户流程、Codespaces 单会话 transport 与共享主机边界\n- `docs/guides/telegram-approval.md` / `docs/guides/feishu-lark-remote-approval.md`：远程审批设置与失败回退语义\n- `docs/guides/roam-fence.md`：自由漫游与可选围栏\n\n## Runtime Summary\n\n- HTTP hook / plugin 主路径：`src/server.js` → `src/server-route-state.js` → `src/agent-runtime-main.js` → `src/state.js` → IPC；本地 JSONL monitor 直接进入 `agent-runtime-main`，不经过 HTTP server\n- 权限主路径：`src/server-route-permission.js` → `src/permission.js`；本地 bubble、显式 permission automation 与可选 Telegram / 飞书 Lark 远程审批都可能产生真实决定\n- 桌宠的渲染/输入双窗口由 `src/pet-window-runtime.js` 统一创建和定位；浮层排序与 topmost 行为在 `src/floating-window-runtime.js` / `src/topmost-runtime.js`\n- `src/state.js` 生成的 session snapshot 是 Dashboard、HUD/Orbit 与可选通知/presence/mobile consumer 的共享合约，改字段必须检查所有消费者\n- `src/integration-sync.js` 为已安装且启用的 agent 异步同步 hooks / plugins / extensions；Codex official hooks 为 primary，JSONL 轮询保留为 fallback\n- Claude hook 恢复由 `src/claude-settings-watcher.js` 的目录 watcher + 低频只读巡检共同负责；repair 统一经过 `src/claude-hook-operations.js` 队列并复验，连续失败转 `manual-fix-required`。完整 gate、阈值与 source-missing 语义见 `docs/project/agent-runtime-architecture.md`\n- `src/agent-gate.js` 控制各 agent 的安装意图、启用状态、权限气泡开关和 wait-for-input notification 子开关\n- 设置系统主链路是 `src/prefs.js` → `src/settings-controller.js`（唯一写入者）→ `src/settings-store.js`；`settings-actions*` 负责校验和 pre-commit gates，`settings-effect-router.js` 负责 post-commit runtime effects 与广播\n- 启动时还会尝试自动安装 VS Code / Cursor terminal-focus extension，并初始化 updater\n- Remote SSH 通过 effective transport inspection 区分 ordinary parallel SSH 与 serialized transport；后者由 target-scoped coordinator 编排。远程部署只走 Settings，`scripts/remote-deploy.sh` 已 fail-fast 停用\n\n## Core Files\n\n更细的背景见 `docs/project/agent-runtime-architecture.md` 和 `docs/project/theme-state-ui.md`。\n\n| File | Responsibility |\n|------|------|\n| `src/main.js` | Electron composition root：生命周期、上下文组装与各 runtime / IPC 注册器接线 |\n| `src/server.js` + `src/server-route-state.js` + `src/server-route-permission.js` | HTTP 服务、端口发现、`/state` / `/permission` 路由 |\n| `src/agent-runtime-main.js` + `src/integration-sync.js` | local monitor / official hook 仲裁、Codex turn fence、按 gate 的集成同步 |\n| `src/state.js` | 状态机、多会话合并、优先级、自动回退、睡眠/DND |\n| `src/renderer.js` | 动画切换、SVG 预加载、眼球追踪渲染 |\n| `src/permission.js` + `src/permission-automation-policy.js` + `src/session-automation-coordinator.js` | 权限气泡、自动化策略、per-session 授权与决策回包；远程 client 由 `main.js` 注入 |\n| `src/pet-window-runtime.js` + `src/floating-window-runtime.js` + `src/topmost-runtime.js` | 双窗口 owner、浮层重排、z-order / fullscreen / focusability |\n| `src/update-bubble.js` | 更新气泡创建、测高、跟随桌宠定位，避让 HUD / permission stack |\n| `src/dashboard.js` + `src/dashboard-renderer.js` | Sessions Dashboard 唯一 owner：会话列表、别名编辑、终端跳转、几何持久化，以及同一页面的临时键盘模式 |\n| `src/dashboard-host.js` | Dashboard 普通宿主的平台封装：darwin/win32 用 `BaseWindow + WebContentsView`（无 `ready-to-show`），Linux 保留 `BrowserWindow` |\n| `src/dashboard-quick-mode.js` | 完整 Dashboard 的 1–9 键盘模式（**macOS/Windows only**）：quick 宿主、opacity/input parking、轮次栅栏与冻结数字映射；Windows 显式取消与页面失效的来源恢复在 `src/quick-select-origin-focus.js`，quick 宿主的退出清理挂在 `before-quit` |\n| `src/session-hud.js` + `src/session-hud-renderer.js` | 桌宠旁轻量会话 HUD、折叠行、点击跳转 |\n| `src/session-alias.js` | session alias key 规范化、TTL pruning、Kiro cwd scope |\n| `src/theme-loader.js` + `src/theme-runtime.js` | stateless 主题加载/消毒与唯一 active-theme owner；`waitForThemeReloadSettled` 完成信号 |\n| `src/official-theme-catalog.js` / `-download.js` / `-installer.js` / `-main.js` | 官方可下载主题：严格 catalog/cache、Electron `net.request` 流式下载、受限流式 ZIP 解压与 marker-before-rename、main owner/IPC/共享 `theme` lock |\n| `src/prefs.js` | 偏好 schema、load/save/migrate/validate，设置持久化入口 |\n| `src/settings-actions*.js` + `src/settings-effect-router.js` | 设置 validators / commands / pre-commit gates 与 post-commit runtime effects |\n| `src/settings-controller.js` | 设置系统唯一写入者 |\n| `src/settings-store.js` | 不可变 snapshot store |\n| `src/settings-ui-core.js` + `src/settings-renderer.js` + `src/settings-tab-*.js` | Settings shared UI state、侧栏/tab shell 与各页逻辑 |\n| `src/menu.js` | 托盘 / 右键菜单，串起设置、Dashboard、mini mode、更新入口 |\n| `src/mini.js` | 极简模式入场、滑动、peek、状态映射 |\n| `src/tick.js` | 主循环、鼠标轮询、眼球和 idle/sleep 逻辑 |\n| `src/drag-position.js` | 拖拽落点规范化与跨显示器钳制 |\n| `src/visible-margins.js` | 可视角色边距与 edge pinning 规则 |\n| `src/updater.js` | Git 模式 / `electron-updater` 双路径更新逻辑 |\n| `src/focus.js` | 终端聚焦 |\n| `src/hit-renderer.js` + `src/hit-geometry.js` | 输入窗口命中、拖拽、连击反应 |\n| `src/remote-ssh-runtime.js` | Remote SSH tunnel/ingress 状态机、ordinary health probe、serialized readiness 与重连 |\n| `src/remote-ssh-transport.js` + `src/remote-ssh-transport-coordinator.js` | effective transport inspection、pre-spawn admission、target ownership、drain barrier 与 quarantine |\n| `src/remote-ssh-deploy.js` | Deploy / Repair、身份事务、lease/fencing、wrapper、cleanup 与远端 Codex monitor mutation |\n| `src/remote-ssh-identity.js` + `src/remote-ssh-layout.js` + `src/remote-ssh-ingress.js` | 身份/布局真相与 profile 专属、nonce 校验的本地 ingress |\n| `src/remote-ssh-node.js` + `src/remote-ssh-shell-detect.js` + `src/remote-ssh-local-config.js` | 远端 Node/ shell 探测与本机 SSH config 入口 |\n| `src/remote-ssh-profile.js` | Remote SSH profile schema、校验、默认值和持久化规范化 |\n| `src/remote-ssh-ipc.js` | Remote SSH runtime / deploy / monitor orchestration、intent policy、IPC 状态与进度广播 |\n| `src/remote-ssh-quote.js` | Remote SSH 终端命令与跨平台 shell quoting helper |\n| `agents/registry.js` | agent 注册表 |\n| `agents/codex-log-monitor.js` | Codex JSONL fallback 轮询 |\n| `agents/gemini-log-monitor.js` | legacy Gemini session JSON 轮询器；当前 Gemini hook-only 路径不启动 |\n| `hooks/dsh-install.js` | DeepSeek Harness immutable managed bridge generation、ownership verify、web 与 desktop 两个 profile 的安装 / 修复 / 卸载编排 |\n| `hooks/kirocrew-install.js` + `hooks/kirocrew-store.js` | KiroCrew state-only gateway hooks、upstream-compatible mutation locks and atomic private store writes |\n| `hooks/kirocrew-hook.js` + `hooks/kirocrew-command.js` | KiroCrew state bridge and exact command-shape ownership classifier |\n| `hooks/dsh-notices.js` | DeepSeek Harness 常驻提示的存储与规则（按 profile 的 `notices-<profile>.json`） |\n| `hooks/clawd-hook.js` + `hooks/copilot-hook.js` | Claude Code / Copilot CLI 状态上报脚本 |\n| `hooks/install.js` | Claude hook 注册 / 卸载 |\n| `hooks/auto-start.js` | Claude `SessionStart` 自动拉起 Clawd 的 hook |\n| `hooks/codex-hook.js` / `hooks/codex-install.js` | Codex official hooks 状态与权限审批、安装 / 卸载 |\n| `hooks/cursor-install.js` / `gemini-install.js` / `antigravity-install.js` / `kiro-install.js` / `kimi-install.js` / `qwen-code-install.js` / `codewhale-install.js` / `codebuddy-install.js` / `workbuddy-install.js` / `opencode-install.js` / `pi-install.js` / `openclaw-install.js` / `hermes-install.js` / `qoder-install.js` / `qoderwork-install.js` / `reasonix-install.js` | 各 agent 集成安装逻辑 |\n| `hooks/opencode-family-managed-generation.js` | OpenCode 用户可写托管 generation（canonicalizer、bundle/manifest、stage/promote、target owner record、target-scoped lock）；纯 Node 内置依赖，不进入 Remote SSH `HOOK_FILES` |\n| `hooks/opencode-family-entry-ownership.js` | OpenCode-family plugin entry 的 string/tuple 解析、跨平台路径等价、所有权分类与重复/options 冲突规划（纯逻辑、可注入 fs） |\n| `hooks/opencode-family-install.js` / `hooks/opencode-family-jsonc.js` | 家族注册器：`managedMaterialization:true` 走托管 generation 事务 + 共享 entry planner；`false` 保持 legacy broad-basename register/unregister |\n| `src/doctor-detectors/opencode-managed-inspector.js` | managed OpenCode Doctor inspector（ownership/manifest/生成结构、Fix policy、masked supplementary warning）；接受注入 fs |\n| `hooks/workbuddy-hook.js` | WorkBuddy state + Notification command hook；无 session_id 时返回合法 stdout 后丢弃事件 |\n| `hooks/grok-hook.js` / `hooks/grok-install.js` | Grok Build state + Notification command hook；写入 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json`；`env` marker `CLAWD_GROK_HOOK=v1` 所有权；无 session id 时丢弃；不注册 `/permission` |\n| `hooks/zcode-hook.js` / `hooks/zcode-install.js` | ZCode 状态 + 阻塞式 PermissionRequest hooks（`hookSpecificOutput` 决定 / `{}` 无决定）、`hooks.events.*` 按事件超时增量注册与 Claude-imported Clawd hook 清理 |\n| `hooks/qoder-hook.js` | Qoder state-only 状态上报脚本（Phase 1，stdout 恒为 `{}`） |\n| `hooks/minimax-hook.js` / `hooks/minimax-install.js` | MiniMax Code state-only 本地插件：整目录 install/uninstall（`<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/`），CLAUDE 格式 hooks + exec-form args，10 事件无 PermissionRequest/Notification，`.clawd-managed.json` 结构化所有权凭据、fail closed |\n| `hooks/codex-remote-monitor.js` | 远程 Codex JSONL 轮询并通过 SSH 隧道回传（含 token_count 订阅配额的 metadata_only 上报） |\n| `hooks/claude-statusline.js` / `hooks/antigravity-statusline.js` | 各 CLI statusline 适配器：渲染状态行 + 把订阅配额（rate_limits）以 metadata_only POST 上报；Claude 版支持远程部署（`CLAWD_REMOTE=1` 前缀）与 `--chain` 串联模式（原 statusLine 对象保存在 `~/.claude/hooks/clawd-statusline-chain.json`，卸载时恢复） |\n| `extensions/vscode/extension.js` | VS Code / Cursor 终端 tab 聚焦辅助扩展 |\n\n## Constraints\n\n- `agents/registry.js` 的 capabilities 是权限、subagent、session-end 等路由/gate 的权威来源；不得另写名单代替 capability 判定。但 permission automation eligibility 由更窄的 `isKnownPermissionAgent()` 显式判定（`KNOWN_PERMISSION_AGENTS` + explicit opencode-family membership），不得从 `permissionApproval` 自动派生或合并回 registry capabilities\n- 小结的指标能力例外地只认 `src/recap-metrics.js` 的显式逐 Agent 口径，不得从 registry capabilities 或标准化 event 名推导。只统计已通过 gate、Codex source/replay fence、subagent 与完成仲裁的 accepted activity；DND 继续记录且不切 coverage，suspend/退出/关闭记录才切。`null` 是不支持，绝不能渲染或汇总成 `0`\n- 小结持久层固定为 `~/.clawd/recap-v1/` 下 14 个本地日的最小 HMAC 小票与 400 个本地日的 daily/coverage；不得落 prompt/回复/命令/工具内容、路径/项目、原始 event/session/profile/turn/tool ID，不得增加网络、导出或分享。首版不做 Token、金额、模型、推理强度、Skill、人的工作/编码时长、streak、峰值/最长项、排行榜或生产力评分\n- Claude Code / CodeBuddy 的阻塞式权限审批走 `POST /permission` HTTP hook；普通状态事件走 command hook（CodeBuddy command hook 对所有事件输出 `{}`，不做工具或权限决定）\n- permission automation（off / auto-tools / unattended）和 per-session grant 会在 bubble 渲染前产生真实 allow/answer。agent/family eligibility 是显式白名单；工具分类则因 mode/adapter 而异：auto-tools 对 Claude/Qwen 的未知 built-in fail closed，但其他已知 adapter 不都使用逐工具白名单，unattended 还会有意自动放行可作 Allow/Deny 的未知请求。新增 agent、工具或交互类型必须审查 policy + tests，不能从 `permissionApproval` 推导资格或笼统假设“未知请求都会 defer”\n- Telegram / 飞书 Lark 与本地 bubble 是并行决策通道。远程通道超时、断连、未配置或发送失败不得产生远程决定，更不得转成 deny；有本地 bubble 时请求继续 pending，只有 remote-only 且所有可用 client 都无决定时，整体请求才 no-decision 并回到 agent 原生流程\n- WorkBuddy 通过当前 `~/.workbuddy-ai/settings.json`（旧版兼容 `~/.workbuddy/settings.json`）的 Claude Code 兼容 command hooks 做 **state + Notification only** 集成：不注册 `/permission`，审批始终留在 WorkBuddy 原生沙箱与 GUI；无 `session_id` 的事件返回合法 stdout 后直接丢弃。当前只支持 macOS/Windows 桌面应用，没有已验证的 Linux/WSL CLI；不要把裸 `Electron` 当 WorkBuddy 进程。\n- Grok Build（agent id `grok-build`）通过 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json` 的 Claude Code 兼容 command hooks 做 **local / main-session / state + Notification only** 集成（Phase 1）：stdin 为 camelCase（`sessionId` / `toolName`），`hookEventName` 是 camelCase key + snake_case value，`hook_event_name` 是 snake_case key + PascalCase value。**逐 handler 的 `env` 结构化 marker `CLAWD_GROK_HOOK=v1` 是唯一所有权凭据**；文件名/substring（含 `grok-hook.js.backup`）只用于诊断告警，永不授权改写或删除。安装/卸载只增删含该 marker 的 handler，保留 unknown 顶层键、其他 event、foreign matcher group 与 sibling handler；没有 marker 的既有文件一律原样拒绝。`SessionEnd` 不写 `timeout`（继承 Grok 1.5s teardown），其余事件 5s。Windows 用 `windowsWrapper:\"portable\"` 形态，不得用 `&` / `-EncodedCommand` / 自造 `shell` 字段。Grok 没有 `PermissionRequest`，不注册 `/permission`，adapter 始终输出 `{}`。子代理事件（`subagentType`）直接丢弃；不注册 `SubagentStart` / `SubagentStop`。Grok 默认会扫 `~/.claude/settings.json`，所以 `clawd-hook.js` / `cursor-hook.js` / `auto-start.js` 只在非空官方 `GROK_HOOK_EVENT` 下直接退出，`GROK_HOME` / `GROK_SESSION_ID` / 无关 `GROK_*` 不得触发。`Stop` 只有精确 `reason === \"end_turn\"` 且无 background task / session cron / `stopHookActive` 才算完成，其余由 adapter 本地判定；`channel_closed` / `shutdown` 等 session-end 形态的 Stop 在 fence 之前丢弃。turn 顺序由 `src/grok-turn-fence.js` 的 bounded in-memory fence 仲裁（晚到旧 turn、重复 terminal、continuation Stop、Stop→StopCancelled 纠正）。不进入 subagent / WSL / Remote SSH / startup recovery / terminal focus / quota / context / recap turn 指标。`~/.grok/hooks/clawd.json` 是未发布的 PR preview 路径，只做 warning，不得自动接管或删除。\n- Codex 的阻塞式权限审批走 official `PermissionRequest` command hook：hook 脚本长连接 `POST /permission`，只允许 stdout 返回 sanitized `behavior/message`，`updatedInput` / `updatedPermissions` / `interrupt` 必须 omit。权限模式默认 `auto`（旧 `native` 规范化为 `auto`），仅准确本机 session/turn 的人工 reviewer 证据可进 Clawd；未知、自动 reviewer、MCP/app、远程/WSL 均 no-decision；唯一例外是远程/WSL（路由 reason 为 `nonlocal`）的 Bash/apply_patch 在全局自动放行会立即 allow 时（`wouldAutoAllowPermission`：非 reminder hold、非会话覆盖、非交互子代理）由 Clawd 直接放行（#1186），路由后若设置已变则 no-decision，绝不弹气泡。`intercept` 是显式接管；升级时旧 `intercept` / `native` 统一迁到 Auto 一次，之后重新选择的 Intercept 会保留。不得用全局 config、其他会话或旧回合推断当前请求的审批方；证据不足时返回 no-decision，交还 Codex 原生流程。\n- hook 脚本只允许依赖 Node 内置模块，以及同目录 `hooks/` 下、且登记在 `src/remote-ssh-deploy.js` 的 `HOOK_FILES` 部署清单中的纯 Node helper（如 `server-config.js` / `shared-process.js` / `json-utils.js` / `codex-originator.js` / `codex-subagent-fields.js` / `context-usage.js` / `state-payload-size.js` / `quota-bucket.js` / `claude-rate-limits.js` / `codex-rate-limits.js` / `antigravity-context-usage.js`）；manifest-consistency 测试强制检查依赖闭包，新增 helper 必须登记\n- CJS hook 脚本需要稳定终端 PID 时，必须复用 `hooks/shared-process.js` 的 `createPidResolver()` 及其 lifecycle context；不要复制进程树 walk 或用 `process.ppid` 简化。`getStablePid()` 只是 opencode-family plugin 的内部 resolver\n- `agentCmdlineCheck` 只对进程名在 `agentCmdlineNames` 里的祖先进程运行，默认是 `DEFAULT_AGENT_CMDLINE_NAMES`：`node` / `node.exe`，加上 Linux 上没设过 `process.title` 的 Node 在 `ps -o comm=` 里的名字——Node 23.8–25.4（含全部 24.x）把主线程命名为 `MainThread`、≥ 25.5 为 `node-MainThread`，Linux 报的进程名就是主线程名。传入 `agentCmdlineNames` 会整体替换默认值：只想加名字的 adapter 必须在选项里直接写成 `agentCmdlineNames: new Set([..., ...DEFAULT_AGENT_CMDLINE_NAMES])`（如 ZCode；可以跨行，方括号里只能有普通字符串字面量和 `...DEFAULT_AGENT_CMDLINE_NAMES` 本身，不能有注释或其他表达式；简写属性、先存进变量，或任何不是这个形状的提及（包括注释里的）都会被判不合格，因为文本检查无法核对），只有刻意只探测非 Node 宿主的（WorkBuddy 的 `electron`）例外，`test/shared-process.test.js` 会扫描 `hooks/*.js` 检查\n- opencode v1 权限不走 `permission.ask` hook，而是 event hook + reverse bridge；v2 走 `ctx.permission.hook(\"evaluate\")` 的阻塞 HTTP 响应\n- OpenCode / MiMo v1 原生问题走独立本地 `/question` 长轮询，不复用审批回包；遵循全局 permission bubble 开关与 family 单 agent 开关。只接受已核实的 v1 来源、版本和问题 schema，提交前用原 SDK client 复核精确 request/tool/session，答案保持有序 `string[][]`；无决定返回 204 交还原生。OpenCode 由原生 reply RPC 的 `true` / 404 判定提交结果，MiMo 仍需精确 `question.replied` 答案匹配。子会话问题、OpenCode v2、Remote SSH 及未审核 agent 保持原生；不要改 Claude/Hermes wire 或托管 generation 依赖集合。详见 `docs/guides/agent-questions.md`。\n- opencode-family v1 插件经 `ctx.client` 连回宿主时，主机为通配监听地址（`0.0.0.0` / `[::]`）就按次改用 `127.0.0.1` / `[::1]`（不改宿主共享的客户端配置；非通配地址保持原调用形状）。默认 TUI 走进程内 fetch；`opencode serve` / `web` 下这是对监听地址的真实 HTTP 请求，受宿主进程里的 `HTTP_PROXY` / `NO_PROXY` 影响，而通配地址不会自动绕过代理。桥接回复失败返回 `{ok:false,status,error}`（`status` 为上游状态码，缺省 0）。\n- OpenCode 2.x（npm `@opencode/cli`，issue #1039）由 `hooks/opencode-plugin-v2/` + core.mjs 内 `createOpencodeFamilyPluginV2` 承接：installer 在同一 generation 内额外物化 `opencode-plugin-v2/index.mjs`（v1 四文件、v2 五文件；目录 specifier 解析 index.mjs、无需 package.json，2.0.15 实测），并把它写进 **`plugins` 键**，同时清理 Clawd 自有的旧 `plugin` 条目；用户条目、tuple/options 和 v1 行为保持不变。未被 Clawd 纳管的未知 `plugin` 条目仍只报 loader WARN；v1 对未知 `plugins` 键的静默丢弃只在 **1.18.16+** 成立——1.18.15 及更早会以 `Unrecognized key: plugins` 拒绝整个 config（anomalyco/opencode#41312，2026-08-08 起才忽略未知顶层键），因此 `plugins` 写入由宿主探测决定（`hooks/opencode-host-detect.js` 三态：探测到 v2 才写；探测到 v1 不写并清扫 owned 残留；探测失败不碰该键；`CLAWD_OPENCODE_HOST` 环境变量可钉死结论，Doctor 在无 v2 宿主时不要求 v2 条目）。v2 插件是零 import 纯对象 `{id, setup}`（v2 loader 拒绝函数 default export，`@opencode/...` 裸包名无插件本地 node_modules 不可解析），事件经 `ctx.event.subscribe()`（`session.step/tool/execution.*` 词汇完全换代，未知事件一律忽略），cwd 取事件信封 `location.directory`，标题走 `session.renamed`，context usage 走 `session.step.ended` 的 step tokens（`session.usage.updated` 是 session 累计计费值，不能当占用率）。权限走 **`ctx.permission.hook(\"evaluate\")` 阻塞长连接 POST `/permission`**，决定就是 HTTP 响应体 `{decision: allow|always|deny}`（服务端按 `hook_source === \"opencode-plugin-v2\"` 路由到 v2 阻塞子分支），只有 `200` + 身份头 + 合法 JSON 才采纳决定，204/超时/断连/非 200/任何错误都不改 effect 回原生 ask UI；配置 allow 也进 hook 但绝不降级；单条 shell 命令以 `tool_input.resource` 传输，服务端 v2 分支会为其别名出 `command` 以接入破坏性操作提醒（`mapOpencodeV2ShellResource`，非 shell 工具不映射；全字符串的多 resource 以换行合并作扫描别名）；resources 原样整组转发（对象转 JSON 字符串），不做条数/长度截断，唯一边界是整 body 超 512 KiB 时跳过转发。\"Always allow\" 无宿主持久化 API，用插件内 per-session 内存规则（随常驻 service 生命周期，气泡对 v2 使用单独文案说明关闭/重开终端不会撤销）。插件跑在常驻共享 service（daemon）：`source_pid`/进程树不可信故**整组省略**（终端跳转对 v2 降级），安装/更新后需 `opencode service restart`。`ctx.permission.hook()` 按上游 v2.0.15 类型返回 `Promise<Registration>`：本实例 dispose（setup 返回的 cleanup，宿主也会在插件 scope 关闭时调用）会调用 `registration.dispose()`，注册 Promise reject 只记日志不影响事件订阅。事件订阅**不等待** hook 注册（注册挂起/reject 时状态上报照常），reload **不等待**上一代注销完成；本实例清理先同步完成本地清理（标记 disposed、abort 订阅、身份恢复）再去注销 registration，注册 dispose 有约 2s 上限、超时只记日志，注册未完成就被取代则在注册完成那一刻立即注销，不残留活 hook。上游 v2.0.15 的 trigger 对同名 hook 依次调用每个仍注册的回调、共用同一个可变 event，而我们的注销是异步的，所以 reload 窗口内旧回调可能仍被调用：已退役实例的回调入口检查 `instance.disposed` 后直接返回，不 POST、不改 event。每个 ask 各自转发（`source.id` 是工具调用级、不是 ask 级，同一工具调用会发出多个不同 ask，如 external_directory + edit），不做内容去重。config 顶层重复 `plugins` 键按歧义处理：Doctor 报 `config-corrupt` 不抛异常，register/卸载在首次写入前中止（v1 宿主 sweep 只告警并跳过），v1 `plugin` 键行为不变。v1 1.18.31 tuple 契约、generation 布局、owner/lock 语义不变；`inspectGeneration` 把历史 4 文件集接受为合法 owned-stale 形态以便迁移。真机证据与降级项见 `docs/investigations/opencode-v2-e1-evidence.md`\n- OpenCode 的 plugin 注册不再直接指向打包/源码目录：`agents/opencode-family.js` 的 `managedMaterialization:true`（OpenCode true / MiMo 本次 false）gate materialize、ownership classifier、managed Doctor 与 generation cleanup。开启后 register 必须在目标 home 下维护 `<home>/.clawd/integrations/opencode-family/opencode/homes/<configDirHash>/generations/<bundleHash>/` 的内容寻址 generation（OpenCode v2 当前五文件，历史 v1 四文件），同一 generation 可同时物化 v1/v2 入口文件，但不因此在配置中注册两个键；探测到 v2 宿主时只把 `opencode-plugin-v2` 入口写入 `plugins`，并将 `plugin` 键仅用于清理 Clawd 自有旧条目；v1 宿主和探测不到版本时保持原有 v1 注册路径；bundle allowlist 固定为 `<agent>-plugin/index.mjs` / `<agent>-plugin/package.json` / `opencode-family-plugin/core.mjs` / `opencode-family-plugin/session-ids.mjs` / `opencode-plugin-v2/index.mjs`（v2）。owner record（`owner.json`，literal `clawd-on-desk.opencode-family.target`）与 target-scoped `mutation.lock/`（独立 literal `clawd-on-desk.opencode-family.target.lock`）是所有权与 app-present 真相；lock 被持有时不并发写：interactive Install/Repair/CLI/Uninstall/About cleanup 只做一次短而有界、可注入 delay 的重试，startup automatic 不等待直接 skipped；合法且超时 2 倍以上、PID 明确 ESRCH 才允许 atomic quarantine 接管，corrupt/foreign/live/EPERM 一律不接管；release 只删自己 token 的 `lock.json` 与随后为空的精确目录，禁止 recursive cleanup。owner 的 `activeSourceMarker` 必须是 `<activeSourceRoot>/<pluginDirName>/index.mjs`（共享 canonical 身份、Windows 折叠大小写）且为 regular file，目录/dangling/错 plugin 目录/root 不匹配都不算 live。同一 target 的 source owner 冲突（marker 仍存在）一律 `owner-conflict`，不得来回改 config；旧 owner 的源码 marker 已不存在时，新 source 必须在锁内重读并原子接管 owner（config 已 current 也不例外），否则残留死 owner 会让托管 plugin 永久 inert。锁内若 config 与当前 source owner 都已被并发操作收敛，则本次零 mutation 返回 skipped。lock release 失败不得掩盖结果：成功保留 status 并附 warning + 精确 lock path 的 residualPaths，已有 primary error 时保留原错误。basename 本身永不构成所有权；copy 到 managed layout 外的完整 generation 因缺少对应 owner record 而 inert，只有 verified-current-copy 可 Repair。tuple 契约固定为 OpenCode 1.18.31 实测的 `[specifier, optionsObject]`（隔离 `opencode debug config` 证据：第二项必须是普通对象，数组/字符串第二项会被宿主拒绝）；重写只替换 `plugin[index][0]`，options 值级保留，绝不写回嵌套 tuple，malformed array 原样保留。`options.pluginDir` 仍是 test-only expected-canonical override（跳过 generation/manifest/boundary，但不跳过 ownership/唯一 entry/read-back），`resolvePluginDir()` 仍返回 source。新建文件按当前用户普通写权限落盘：不得加 readonly/deny-write ACL，不得用 `W_OK`/`r+`/INIT 日志/session 活跃做健康门禁。Uninstall 以“活动注册是否移除”为提交依据（`registrationRemoved` false/null 阻止 Settings 提交，undefined 沿用 legacy status），残留 generation 只产生 warning；清理有效 generation 时必须先在同一 `generations/` 内原子改名为非 canonical `.cleanup-*` 再递归删除，删除失败不得占住原 hash 槽。兼容旧版本留下的半残 canonical 目录时，只允许在 owner 已 released、bounded history 精确证明该 canonical entry、且配置无活动 Clawd entry 的条件下，把它原子隔离为 `.recovery-*` 后重新物化；active/foreign/unproven/canonical-in-use 一律继续 fail closed，绝不原地覆盖或修补可疑 bytes。托管 core 的 orphan inert gate（`evaluateManagedLayoutGate`）必须在 `resetDebugLog()` / PID walk / bridge / handler 注册之前，owner marker 缺失、损坏、agentId 不匹配或 `activeSourceMarker` 不存在时返回空 handler；source-direct 模式保持原行为。MiMo 保持 broad-basename register/unregister/Doctor 契约不变。\n- Pi 通过 `~/.pi/agent/extensions/clawd-on-desk` 的 global extension 推送状态；Clawd 对 Pi 是 **state-only**，不接管权限、不弹权限气泡，也不把 Pi 的默认 YOLO 流程改成手动确认\n- OMP (oh-my-pi) 通过 `~/.omp/agent/extensions/clawd-on-desk` 的 global extension 推送状态，agent id `omp`，对 Clawd 同样是 **state-only**。它是 Pi 的 fork（包名 `@oh-my-pi/pi-coding-agent`），所以 `hooks/omp-extension.ts` 刻意与 `hooks/pi-extension.ts` 保持逐行对齐（只差 package import、core import 与函数名），进程树遍历与终端识别不得各自漂移；OMP 独有的差异全部收在 `hooks/omp-extension-core.js`。**完成必须走 `session_stop` 候选 + 终态 `agent_end` 提交的两阶段协议** —— `session_stop` 先保留主会话边界，OMP 再汇总所有 extension 的续跑请求；只有后续 `agent_end.willContinue !== true` 才向 Clawd 发完成。不得直接把任一事件单独映射为完成：仅用 `agent_end` 会把 subagent/调度边界误报为完成，仅用 `session_stop` 则会早于 extension 续跑判定。`session_switch` / `session_branch` 要为被切走的旧 session 补发一条合成 `SessionEnd`，否则 Clawd 会留下一条再也不会有人上报的活动行。session id 命名空间是 `omp:<raw>`，且必须始终带 `session_title`（多个交互式会话合法地共用同一个 cwd，缺标题会让列表和跳转目标无法区分）。安装器遇到社区桥接 `~/.omp/agent/extensions/clawd-on-desk-omp.ts` 时必须 fail closed 跳过：两者上报同一批事件，同时存在会双发。当前 `assets/source/agent-icons/omp.png` 是 `fallback: true` 的占位 π 字形，不是 OMP 官方品牌素材，拿到授权素材后应替换\n- DeepSeek Harness 首发是 **web profile / Windows-first experimental / plugin-only**；rc.6 已于 2026-08-29 完成 macOS / Windows x64 源码运行的真实 API-backed session/approval smoke（#962）；rc.2 Windows packaged-app 证据仅覆盖安装、web boot 与直接 bridge client 的 state/Allow/Deny 往返（#938），不得合并宣称 rc.2 安装包的真实 API 会话已验证。Clawd-managed in-process plugin 监听公开 `session/created`、`session/event`、`session/disposed`、可选 `sessionProjections.onChanged` 与 blocking `approval/request`；标题和上下文仅作为会话元数据同步，不占用生命周期 seq。状态按 session FIFO 上报并携带上游 seq；Clawd 不读取 `$DSH_HOME/storages` projection。普通审批进入独立 DSH `/permission` adapter，只支持人工 Allow Once / Deny；204 / 断连 / DND / disabled 都由 plugin `next()` 交还 DSH 原生 web answerer。`ask_user_question` 始终留在 DSH 原生 provider；DSH 不进入 `KNOWN_PERMISSION_AGENTS`，auto-tools / unattended / per-session grant 全部 DEFER。安装器通过官方 `dsh plugin --profile web add/remove` 管理 immutable marker-owned generation，foreign 同名包 fail closed；版本放行改成按 **小版本族（major.minor）**。维护两张表：一张是唯一写出具体版本/npm artifact/integrity 的已验证 artifact 清单（优先 `@deepseek-ai/dsh@0.2.0-rc.2`（integrity `sha512-EAJ3gPNcVt/uv8X19PMm9NkVhWgT7xXNMk0UKCVm+IQ5rpSQOcsMUa0HWlnYYVybKMsccjcRB21vVVsaXQ6IdA==`，2026-10-04 已做静态接口核对，并在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证了用 Clawd 安装器装出的 generation 的启动同步换代、会话状态、HUD 标题/上下文、Allow/Deny 与消息上的失败标记；其 `tool/result` 把失败标记放在消息 `message.isError` 而不是内容项上，bridge 新旧两种位置都认），并保留 `@deepseek-ai/dsh@0.1.5-rc.3`（integrity `sha512-c0W6Xqc4ChjFcCJkbzPeIxZQdnbKqe+QAcJzWGtogg0ZzsnZRcw3vopMyZ5oZU6E2fmyqGcyDR1sBeiCH4yHcg==`，2026-09-27 已在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证启动同步安装、会话状态、HUD 标题/上下文与 Allow/Deny）、`@deepseek-ai/dsh@0.1.5-rc.1`（integrity `sha512-rmNmzQCg3oIc1z8xH7izRSOuy1TNzq+/NILyfM+7e8DKOyV+yBtg47WEsqR2SiIe1ATec3L/rUa1YhIcfQ2XEg==`）、`@deepseek-ai/dsh@0.1.1-rc.2`（integrity `sha512-UP1UIh6q3Gme/yXRn/QL2P8IsVlv8Shpg22TRJIZPsCRWLm4CBiA1MUvXmJAfsOEETBMLAl+xWPtFw6ICsN3wg==`）与 `@deepseek-ai/dsh@0.1.0-rc.6`（integrity `sha512-brpZfED7ieRa2PQ5tUxMhHrM1pb2CmKFVM/f6yMULBDMicahk+Z2OsHgTwTDnoiZm23Ftu9rQz0NN4pflaoJcg==`）），一张是族表（`0.2` 下限 `0.2.0-rc.2`、`0.1` 下限 `0.1.0-rc.6`）。host 版本经严格解析（拒绝前导零、空预发布标识与 build 元数据）通过、major.minor 命中族、且不低于该族下限即放行；同一族内不同 host 版本共用一个 generation，出现新的小版本必须重新验证并新增一个族。旧的精确 `=<version>` marker 仍按原 range 核对哈希，新 generation 一律写族 range；Install/Repair 按 host 版本所在的族选择目标契约，Uninstall / 手动 npx 命令在 marker 版本已列入清单时钉它自己的 artifact，否则钉同族版本最高的已验证 artifact（无 CLI 且无 marker 时用首选族最新的并记为 assumed）；加锁前后比较的是实际检测到的 host 版本，不看族。DSH 的 `metadata_only` 标题/上下文旁路必须核对目标会话的 `agentId` 确为 `deepseek-harness`，撞名的其他 agent 会话直接丢弃。`47f9438` 仅是源码调查基线，不代表任何 tag/commit 映射。\n- DSH 每个 canonical `DSH_HOME` 的 mutation lock 只有在 owner/schema/token/PID/timestamp/owner-recorded operation timeout 合法、超过该 owner timeout 两倍、且 OS PID probe 明确为 `ESRCH` 时才允许 atomic-rename takeover；live、`EPERM`、unknown、corrupt/foreign owner 一律拒绝并返回精确 lock path。canonical lock 的 owner write/release 禁止 recursive cleanup。无全局 CLI 时生成的手动 npx generation 必须先在同一锁内写 owned reference，手动 add/remove 命令必须显式 pin shell-quoted canonical `DSH_HOME`；malformed/foreign/concurrently replaced reference 一律 fail closed 并保留 generation\n- DSH 桌面版支持（#1119）与 web 共用一个 agent id `deepseek-harness`：web profile 和 DeepSeek Harness 桌面版是两个承载方、各自一个 profile（桌面版是 `$DSH_HOME/profiles/desktop`），但在 Settings 和 Doctor 里仍是**一行**，显示名 `DeepSeek Harness (experimental)`，一次排队操作先 web 后 desktop、一边失败不影响另一边；安装只要有一边核实健康即成功（另一边失败变 warning + 常驻提示），卸载要所有 Clawd 注册都没了才成功。桌面版查找：macOS 用 `/Applications` 或 `~/Applications/DeepSeek Harness.app` 里自带的 `Contents/Resources/runtime/cli/bin/dsh`；Windows 按用户安装，从 `HKCU` 卸载项（显示名以 `DeepSeek Harness ` 开头）与 `%LOCALAPPDATA%\\Programs\\DeepSeek Harness` 找 `resources\\runtime\\cli\\bin\\dsh.cmd`，注册表用 PowerShell 读 UTF-8 JSON、不用 `reg.exe`；Linux 不支持桌面版。静态版本来自 `Info.plist` / 卸载项 `DisplayVersion`，真正动手前跑一次启动器 `--version` 核实。桌面版**永不用 npx**，手动 npx 命令与 manual reference 只属 web。每边角色是 `mutable` / `diagnose` / `not-applicable`：桌面版没装、或 profile 从未初始化（桌面版没打开过）→ 不适用并提示打开一次；foreign 同名包、文件读不了、清理残留、注册查不清、版本不支持、装了不止一个桌面版（`multiple-desktop-installs`）、桌面版找不到但注册还在（`carrier-unavailable`）、桌面版查不清（`desktop-unverifiable`）→ 只报告不动手。启动同步在集成已安装且启用时会把插件加进已初始化的桌面版 profile；桌面版开着也会加载新加的插件，只有插件更新（换了 generation）后要重启。常驻提示在 `hooks/dsh-notices.js`，按 profile 存 `notices-web.json`/`notices-desktop.json`，四种 kind（`restart-required`/`first-install`/`manual-command`/`failed-target`），写不进去只算 warning；提示显示在 Settings → AI Coding Tools 里这一行下面。Doctor 一行详情 `web: …; desktop: …`，状态取适用边里最差，只要有一边能尝试修复且不健康就给修复按钮（`src/doctor-detectors/agent-integrations.js`）。插件在 DSH 里被关掉（依赖在、bundle 行没了）时 `plugin add` 不会重开：显式修复先 remove 再 add（add 前先清掉上游 remove 留下的自有链接，Mac 是符号链接、Windows 是 junction），按 profile 记 `repair-operation-<profile>.json`，中断后下次显式修复续做，启动同步只报 `plugin-disabled-in-dsh`。`generations/` 两边共享，任一边有未处理状态（检查记录、清理残留、坏修复记录或 manual reference、读不了的 profile、符号链接 profile 目录）时清理暂停但不挡安装，卸载残留进 warnings。检查记录按 profile：web `inspection-required.json`、桌面版 `inspection-required-desktop.json`。`plugin add/remove` 写命令两边都超时 300 秒（web 原 120 秒），比上游写锁等待长。上游 `dsh plugin remove` 只清 `link:` 清单和锁、`node_modules` 链接会留下，Clawd 卸载自有插件时确认归属后清掉。Windows 静态查找是同步代码、不起进程，只读异步快照：启动时（不管 DSH 是否启用）、打开 Doctor 前、Agents 页手动扫描时刷新，没快照时桌面版显示\"查不清\"。安装检测把\"找到桌面版\"也算装了 DSH（`src/agent-installation-detector.js`）。桥接插件在 apply 时读 `ctx.profileContext?.name`，只有 desktop profile 才在 state / 审批载荷里带 `dsh_carrier: \"desktop\"`（metadata 不带；web 或未知 profile 一律不带）；Clawd 只接受 DSH + `dsh-plugin` + 本机 + 非 WSL 的载体，按生命周期覆盖或清除、不粘滞，权限 fallback entry 与快照（含签名）都带上它。点击桌面版会话时 `getSessionFocusTarget` 在 darwin/win32 返回 `dsh-desktop`（`dsh://open`），分派先 `shell.openExternal(\"dsh://open\")`，被拒绝再按 `discoverDshDesktopSync({ requireUniqueApp: true })` 的兜底要求唯一安装启动界面程序（macOS `open <appRoot>`、Windows 启动 `<appRoot>\\DeepSeek Harness.exe`，去掉 `ELECTRON_*`/`NODE_OPTIONS`，不用 CLI 启动方式；两份真实路径不同的有效安装视为有歧义，只要还有核实不了的候选也不自动启动，同一份安装的符号链接只算一份）；只能打开应用窗口、不会切到具体对话，web 会话仍不可跳；桌面版启动时会重新打开上次的对话，Clawd 只在这个对话有了动作（提问、工具调用、审批）之后才把它放进 Session HUD（`awaitingActivity` 并入快照 `hiddenFromHud`，但不关跳转；与 Kimi Code 共用同一个标记），Dashboard 照常列出、按钮照常可跳；2026-10-05 macOS 26.6.2 与 Windows 11 x64 源码运行真机验证（桌面版 `0.2.0-rc.2`）：别的窗口在前、最小化、关窗后，点击都经 `dsh://open` 把窗口带到最前；协议打不开时的启动兜底只有单元测试。真机证据：2026-10-04 macOS 源码运行（Clawd `ac64d726`，桌面版 `0.2.0-rc.2` + 全局 `@deepseek-ai/dsh@0.2.0-rc.2`）验证了启动同步把插件装进桌面版（与 web 共用 generation）并出现\"已装进桌面版\"提示、Doctor 一行两边正常，桌面版真实会话的 Allow 建成文件、Deny 后文件内容和 mtime 不变且 Clawd 显示 `PostToolUseFailure`，\"知道了\"后提示消失，改 bridge 源码（同 Clawd 版本）后启动同步两边报 `generation-conflict` 并提示去 Doctor 修复、修复把两边换到新 generation/删旧/出现\"重启桌面版后生效\"、重启后事件来自新宿主进程，设置页卸载后两边依赖与 bundle 行都没了、上游残留链接被清、generation 删除、两边提示清空，再在设置页安装两边都重新装上、桌面版重新出现\"已装进桌面版\"（\"经设置页首次安装\"因此已覆盖），开着 DND 时桌面版的工作区外写文件不弹 Clawd 气泡、返回 no-decision、桌面版弹自己的原生审批框、批准后文件建成且事件照常到达。2026-10-04 Windows 11 x64 经 SSH 用 Node 直跑安装器代码（管理员会话，桌面版在 `%LOCALAPPDATA%` 按用户安装 `0.2.0-rc.2`、全局 dsh `0.1.0-rc.6`，web 在 0.1 族、桌面版在 0.2 族）：PowerShell 读注册表找到桌面版、静态模式无快照时报\"查不清\"且不起进程、自带 `dsh.cmd`（带空格路径）`--version` 返回 `0.2.0-rc.2`、`dsh.cmd plugin --profile desktop add` 经 pnpm junction 装入并核实、记录\"已装进桌面版\"、两族各用一份 generation 并存、Doctor 一行两边有修复按钮、卸载桌面版清依赖与 bundle 行并清掉 `dsh plugin remove` 残留 junction、只删桌面版那份 generation 而保留 web 在用的；2026-10-04 另在 Windows 上以真 Clawd（Electron，源码运行、用户会话、普通权限）验证：先抓到一个只在 Electron 里出现的 bug（Electron 的 fs 把 `app.asar` 当目录、Windows 安装目录核实要求它是文件，于是在真 Clawd 里桌面版被判成没装，已在 `d8190692` 修成\"存在即可\"）；修好后桌面版一直开着（宿主进程未重启），启动同步把插件装进桌面版并记\"已装进桌面版\"，在桌面版新开对话的事件来自那个未重启的宿主进程，**Windows 上桌面版开着也会加载新加的插件**。**未覆盖**：Windows 上桌面版的审批、Windows 上的 Electron 界面（设置页提示、Doctor 窗口、启动预热）、打包后的 app、Linux、HTTP 204 交还与取消、装了多个桌面版。**管理员 junction 观察（推断）**：提升过的管理员进程在 Windows 11 上穿不过非管理员进程建的 junction（PowerShell \"untrusted mount point\"、Node `UNKNOWN`），该会话里 web 的旧 junction 读不到、web add 失败，桌面版同会话新建的 junction 正常；普通权限运行不受影响；由此推断以管理员身份运行 Clawd 可能把普通权限装好的插件读成缺失，未用以管理员身份运行的 Clawd 直接复现\n- OpenClaw 通过 `~/.openclaw/openclaw.json` plugin 路径做 state-only 集成；Phase 1 不做 permission bubble / terminal focus，主要支持本地 `openclaw tui --local`\n- Antigravity CLI (agy) 通过 `~/.gemini/config/hooks.json` 做 **state-only** hook 集成（PreInvocation / PostToolUse / PostInvocation / Stop），**不注册 PreToolUse**。agy LLM 会主动调内置 `ask_permission` 工具，触发 agy 自己的 5 选项 native menu（含 \"Persist to settings.json\" 持久白名单），Clawd 不插手权限决策也不双层确认。`agents/antigravity-cli.js` `capabilities.permissionApproval` / `interactiveBubble` 均为 false。\n- Qwen Code 通过 `~/.qwen/settings.json` 做 hook-only 集成（SessionStart / SessionEnd / UserPromptSubmit / PreToolUse / PostToolUse / Stop / Notification / PermissionRequest），支持状态与阻塞式 `PermissionRequest` 权限气泡；`disableAllHooks: true` 时注册条目不会触发。\n- QwenWork (千问办公) 通过 `~/.QwenWorkCN/settings.json` 做 **hook-only / state-only** 集成（agent id `qwenwork`；SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / Notification / PermissionRequest / PermissionDenied / SessionEnd）。`PermissionRequest` / `PermissionDenied` 只作为观察映射成 `working`（每任务 40+ 次，映射成 notification 会刷屏），hook stdout 恒为 `{}`：Clawd 不产生 allow/deny，不注册 `/permission`，也不进入 permission automation eligibility，唯一决策者是 QwenWork 原生权限流程；`agents/qwenwork.js` 的 `capabilities.permissionApproval` / `interactiveBubble` 均为 false。Windows command 必须保持 `windowsWrapper:\"portable\"`（QwenWork 经 POSIX shell 执行 command hook），PowerShell `-EncodedCommand` **只**用于识别并原地迁移旧条目，不是当前写入形态。marker 只认 `qwenwork-hook.js`，不得仅凭 `name:\"clawd\"` 删除用户 hook；混合 entry 中第三方 hook 原样保留。session id 命名空间是 `qwenwork:<raw>`；`~/.QwenWorkCN/workspace/<id>` 这类内部工作区 cwd 不做 basename 回退，避免 HUD/Dashboard 显示内部 ID。当前真实支持平台只有 macOS / Windows 桌面端（官方下载页 https://qwenwork.cn/download 只提供 macOS 14+ / Windows 10+ / HarmonyOS 6.1+，没有 Linux 客户端），因此 `processNames.linux`、resolver linux agent name 均为空，也不进 `src/wsl-deploy.js` 的 WSL Pair 映射。桌面主进程长驻、不代表 active turn，`startupRecoveryProcessNames` 全空、无 startup recovery。安装/卸载走 Settings → AI Coding Tools，或 `npm run install:qwenwork-hooks` / `npm run uninstall:qwenwork-hooks`；卸载必须同时在 `hooks/cleanup-integrations.js` 的 `MANAGED_AGENT_IDS` / `AGENT_CLEANERS` / `byAgent` 里有条目，否则 About cleanup 只会改 prefs、hook 留在磁盘上\n- ZCode 通过 `~/.zcode/cli/config.json` 的 `hooks.events.*` 集成全部 7 个支持事件（SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / PermissionRequest，无 SessionEnd / Notification）。PermissionRequest 为阻塞式权限审批：hook 长连接 `POST /permission`（HTTP 等待 590s，installer 注册 `timeoutMs: 600000`），有决定时 stdout 返回最小合法 `{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}`（deny 可带 `message`），无决定 / 超时 / 断连 / 任何错误输出 `{}` 并 exit 0，ZCode 回退原生权限流程；`interrupt` / `updatedInput` / `updatedPermissions` / `permissionUpdates` 必须 omit（最小输出 union 按 ZCode 3.5.x 严格 schema 约束；macOS ZCode 3.8.1 已完成真实 hook / 气泡 Allow/Deny 往返，3.5.x PermissionRequest 真机往返未覆盖）。超时单位陷阱：ZCode `timeout` 是秒、`timeoutMs` 才是毫秒，且超时按事件区分（PermissionRequest 600000、state 事件 8000）。Phase 2 只允许人工审批：ZCode 不进入 `KNOWN_PERMISSION_AGENTS`，global / per-session permission automation 在工具面与会话身份审计完成前全部 defer。prefs v14→v15 迁移把 Phase 1 持久化的 `zcode.permissionsEnabled:false` 翻 true（当时开关从未渲染、无用户意图）。配置必须有 `hooks.enabled=true` 才会执行；安装器只在该字段缺失时补 true，显式 `hooks.enabled=false` 或 Clawd 单项 hook 的 `enabled=false` 必须保留，Doctor warning 且不提供会覆盖用户选择的 Fix。ZCode 导入 Claude 配置后，只清理 `.zcode` 中明确引用 `clawd-hook.js` 的 Clawd-owned 条目，绝不改 `~/.claude/settings.json`。安全边界（复核后新增）：`/state` 生命周期 sweep 对 zcode（及 qwen/DSH 等 native-fallback adapter）只允许 no-decision，绝不伪 deny；hook 侧 `tool_input` 预算内原样发送、任何截断（长 Bash 尾部 `rm -rf` 场景）或序列化超 512KiB 一律 fail-closed 输出 `{}` 交还原生 UI；无 allow/answer/plan capability 的 interaction（如 ZCode 真实的 ExitPlanMode / AskUserQuestion）本地气泡与远程卡片都不提供决定入口、直接 204；全局气泡关闭只关本地窗口，Telegram/飞书 remote-only 审批仍可用（per-agent gate 关闭才是全退出）；installer 遇到 foreign `PermissionRequest` hook 时不注册自己的 blocking hook，若 foreign hook 后出现则移除自己的 managed hook（ZCode 同事件 hook 串行执行、后写覆盖，Clawd allow 会盖掉用户 hook 的 deny），Doctor 报 `permission-conflict` 且不给 Fix；六个 Phase 1 managed hook 全部显式 disabled 时新 PermissionRequest 继承 `enabled:false`；服务端 pre-parse 超限一律断连回退，不伪造 deny\n- Qoder / Qoder CN 共用 `qoder` agent，通过 `~/.qoder/settings.json` / `~/.qoder-cn/settings.json` 做 **state-only** hook 集成；各自尊重 `QODER_CONFIG_DIR` / `QODERCN_CONFIG_DIR`，同步所有已初始化目录，不创建缺失版本目录，卸载/cleanup 覆盖两版且只移除 Clawd entries，Doctor 不得让健康的一版掩盖另一版故障。Clawd 只把 `PermissionRequest` / `PermissionDenied` 当 notification 观察，**不替 Qoder 做权限决策**，hook stdout 恒为 `{}`；Windows command 必须保持 `windowsWrapper:\"portable\"`。session id 命名空间是 `qoder:<raw>`；启动恢复只认 CLI `qodercli` / `qoder-cli` / `qoderclicn`，不认闲置 IDE / CN 桌面进程；本机原生会话标题由 `src/qoder-session-title.js` 低频异步增量读取，通过 `updateSessionMetadata` 更新；SessionEnd / 禁用 / 退出取消旧读取，远端与 WSL 路径不在本机读取。2026-10-18 已核对 Windows CN runtime 1.1.69 的真实 SessionStart / UserPromptSubmit / Stop hooks，用户确认开启 Clawd Qoder 接入后任务状态恢复；macOS/Linux CN 未实测\n- TraeCode (Trae CN) 通过 `~/.trae-cn/hooks.json` 做 **hook-only / state-only** 集成。Windows command 必须保持 `windowsWrapper:\"encoded\"`：Trae 的 Windows Sandbox 会把 hook 命令作为 `trae-sandbox.exe --command-line` 的单个原生参数再次转发，普通引号或 `portable` 形态会在含空格路径处拆分；外层必须保持无引号的 PowerShell `-EncodedCommand`，POSIX 则继续使用普通 quoted command。该约束不适用于经 POSIX shell 执行 Windows hook 的 agent（如 Qoder / QwenWork）。\n- MiniMax Code 通过 `<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/` 的 **Clawd 独占本地插件**做 **state-only** 集成（manifest 用 `.claude-plugin/plugin.json`，hooks 文档按 MiniMax 的 CLAUDE sourceFormat 解析；不用 `.minimax-plugin/`，那会走 MINIMAX 格式：matcher 必须非空且不支持 exec-form args）。handler 固定 exec-form `command=node 路径 + args=[minimax-hook.js]`（spawn 直执行、无 shell、免引号），`timeout` 单位是秒且只接受 1–10 的整数（越界的 handler 被丢弃而不是钳制；SessionEnd 事件总预算仅 3s），因此 **PermissionRequest 物理上不可阻塞审批、完全不注册**，也没有 Notification 事件；hook stdout 恒为 `{}`（permissionDecision 缺省 abstain）。目录级所有权只认结构化凭据 `.clawd-managed.json`（`{app:\"clawd-on-desk\",integration:\"minimax\",managed:true,version:1}`，同 Pi 约定；MiniMax 只读 manifest 声明的文件，会忽略它），且凭据与所有受管理路径（`.claude-plugin/`、`hooks/` 及其文件）都不得是符号链接；目录名、manifest name、文档里的 basename/子串乃至整份文档指纹都永不授权改写或递归删除，缺凭据的目录（包括补丁前预发布构建写出的）一律 fail closed，只能手动删除后重装。staging / removal 目录固定落在数据目录（`plugins/` 之外，MiniMax 会把 `plugins/` 下每个目录项都当插件候选，含点号名）：首装在 staging 写全三份文件后一次 rename 发布（只覆盖空目标，非空目录/文件/链接拒绝；空 `clawd-state/` 视为未占用），失败时尽力删除 staging；已拥有的目录原地逐文件更新，中断后仍可证明归属、由下次安装补完。只有 ENOENT/ENOTDIR 算不存在，其他 lstat 错误按无法确认处理，绝不据此宣告卸载。卸载先把已验证目录 rename 出 `plugins/`、复验后再删；移走失败报 error 并保留安装意图，移走成功但删除失败时按已移除提交并在 warnings 里给出残留 `.clawd-minimax-removing-*` 路径，复验失败且移回失败时两个位置都报 `registrationRemoved:null` 并带 `residualPaths`；删不掉且目录仍运行 Clawd hook 时返回 `registrationRemoved:false`（读不清为 `null`），Settings / About 据此保留安装意图。删除后返回前还会复查一次原位置：此时若已有另一个 Clawd 实例重新发布的插件，报“仍在注册”（`registrationRemoved:false`）、不宣称卸载；这次复查是快照，复查之后、Settings 提交之前的安装不在本次结果里（多实例强一致需要覆盖 prefs 提交的跨进程锁，未做）。Settings 界面目前不显示成功结果里的 `warnings` / `residualPaths`：Agents 页安装/卸载只弹“已卸载/已安装”，About 清理只显示计数，只有命令行 cleanup 脚本会打印 warning。进程中途崩溃，或 staging 清理本身失败，可能在数据目录留下 `.clawd-minimax-staging-*` / `.clawd-minimax-removing-*`（MiniMax 不会加载，只能手动删除）；`plugins/` 与数据目录跨文件系统（EXDEV）时不支持。判断外来目录是否仍跑 Clawd hook 按 manifest 声明的 hooks 文档和 MiniMax 默认规则检查（含裸文档外壳、反斜杠路径，以及 shell 形式的 command / commandWindows handler）；Clawd 不建模的 manifest（根 `plugin.json` / `.minimax-plugin/` / `.codex-plugin/`）或读不清时按无法确认处理。node 探测失败时只保留全部 Clawd handler 一致、basename 为 node、存在且可执行、并通过 `node --version` 有界探测的已记录路径（exec-form 无 shell，Dock 启动的桌面 App 的 PATH 里没有 node），安装器与 Doctor 共用 `resolveDesiredNodeBin`。PostCompact 按 #406 上报 thinking（`trigger:\"manual\"` 时 idle），不是 attention。hook 的 `agentNames` 必须全小写（resolver 比较的是小写 basename），且不含桌面版的 “MiniMax Code Helper”：拉起 hook 的 NodeService helper 可能在 App 运行中重启，把它当 agent 会误删活会话，识别应落到长驻的主程序；mcode CLI 启动时执行 `process.title = \"minimax-code\"`，macOS/Linux 上 `ps` 报告的进程名就是 `minimax-code`（按名字匹配），Windows 上仍是 node.exe，靠 `agentCmdlineCheck` 只看 argv 里的脚本位置识别（命令行检查的进程名沿用共享默认 `DEFAULT_AGENT_CMDLINE_NAMES`，已含 Linux 上新版 Node 的主线程名 `mainthread` / `node-mainthread`，MiniMax 不再自带名单）（`node` 后的脚本 basename 是 `mcode`/`minimax-code` 启动器，或脚本路径含 `/@minimax-ai/code/` / `/.minimax-code/`），参数里的目录片段不算——MiniMax 退出时不发 SessionEnd，没有 agent pid 会话就无法按 agent-exit 清理。hook 不触发时的启用步骤在 MiniMax 应用内（`mcode plugin enable clawd-state@local` 或插件面板），磁盘上读不到启用状态，Doctor/Settings 只能提示。session id 命名空间 `minimax:<raw>`，标题走首行 prompt 派生 + 服务端 first-wins（同 traecode）。\n- Kimi Code（agent id `kimi-cli`）的 agent pid 靠进程名识别：CLI 启动即 `process.title = \"kimi-code\"`，libuv 把标题写回原 argv 所占的空间、放不下就截断，所以 macOS/Linux 上 `ps` 与 `pgrep -x` 看到的名字随启动命令长短而变（0.42.0 原生版实测：`kimi` 仍是 `kimi`，`kimi -c` 是 `kimi-co`，`kimi --yolo` 或全路径启动是 `kimi-code`；只有整条启动命令比 `kimi` 还短时（例如不带参数的软链接 `k`）才认不出，`k -c` 显示的已经是 `kimi`）。`hooks/kimi-process-names.js` 必须列全从 `kimi` 到 `kimi-code` 的每一种截断，resolver 与 startup recovery 共用这一组，只写 `kimi-code` 会漏掉 `kimi -c`。拉起 hook 的就是这个改名后的主进程（TUI 在进程内跑 agent 引擎，从 SessionStart 到 SessionEnd 同一个 PID）；其他同名进程（后台更新下载器、经 kimi 二进制跑的插件进程等）都是它的子进程，不跑 hook。resolver 比较小写 basename，macOS 桌面版 `Kimi Code.app` 写成 `kimi code`（它的 agent server 跑在主进程里，hook 由主进程直接拉起）；桌面版关窗后常驻托盘、不代表在干活，同其他桌面 App 一样不进 startup recovery。Windows 上标题只改控制台标题：原生版仍是 `kimi.exe`，npm 版仍是 `node.exe`，命令行检查只认包目录 `/@moonshot-ai/kimi-code/`，不能退回“含 kimi 就算”（Kimi 本身没被认出时，任何命令行提到 kimi 的 node 祖先都会被当成 agent）。Kimi Code 正常 `/exit` 会发 SessionEnd，但关终端、`kill`（0.42.0 实测：SIGTERM 与 SIGKILL 都不发；源码里 SIGTERM 注册了 `stop(143)`，实测为什么没发 SessionEnd 还没查清）、崩溃都不发；没有 agent pid 的会话只要终端 App 还开着就一直留在列表里。桌面端启动时会恢复上次查看的对话、在侧栏点开旧对话也一样，这类只发一条 SessionStart、还没有任何动作的对话不进 Session HUD，Dashboard 照常列出、按钮照常可跳，出现提问/工具/审批/Stop 等动作后自动进 HUD（与 DSH 共用同一个 `awaitingActivity` 标记）。\n- HTTP 服务端口范围固定为 `127.0.0.1:23333-23337`；运行时端口写入 `~/.clawd/runtime.json`\n- Mobile Preview 是独立的 LAN listener，候选范围为 `0.0.0.0:23334-23338`；它不写 `runtime.json`，不得把该范围误写成 hook / custom-agent HTTP ingress 范围\n- 自定义 HTTP Agent 的 sender 必须读取 `~/.clawd/runtime.json`，不能把 23333 写死；注册不等于已连接。custom v1 只支持 `/state`，不支持 `/permission`\n- CodeBuddy PermissionRequest hook 的所有权只认本机 managed URL 或 marker `clawd-on-desk.permission.v1`；纯 `name:\"clawd\"` 不能触发改写/删除。裸 CLI 和 WSL 默认 preserve，Settings/startup/repair 必须显式传 local/custom permission target\n- Remote SSH 的远端 Node 探测要求 Node >= 14；Node discovery/version validation 只在 `src/remote-ssh-node.js`，ordinary tunnel health 与 serialized readiness 在 `src/remote-ssh-runtime.js`，不得互相复制或从已停用脚本另起实现\n- 注册 Claude Code hook 必须 marker-scoped merge：只可更新/删除含 `clawd-hook.js` / `auto-start.js` marker 的 Clawd-owned entry，不得整体覆盖数组或改动无 marker 的用户 entry\n- 注册 Claude Code statusLine 默认只接管空槽或自己的槽（marker `claude-statusline.js`）；本机 Settings 显式开启采集遇到第三方槽时，必须经共存确认并复核原槽指纹，使用 `--local-chain` 和独立的 `clawd-statusline-local-chain.json` 保存/恢复完整原对象。启动/自动修复不得自行取得第三方槽；恢复记录缺失、损坏或不匹配时 fail closed 并保留现场。远程部署仍用 profile 的 `chainStatusline` opt-in 和既有 `--chain` sidecar，不与本机记录混用。订阅配额通过 `metadata_only` POST 进入 session-independent `updateAccountQuota` per-source store；不要把 quota 塞进 `updateSession` opts，也不要以 session 存活作为摄入前提\n- Copilot CLI hooks 走按需自动同步：`hooks/copilot-install.js` 在本地启动仅当 Copilot CLI 已安装且已启用时调用；远端由 Settings Remote SSH deploy controller 调用。路径解析尊重 `COPILOT_HOME` env（trimmed 非空才生效，否则 fallback 到 `~/.copilot`）；`hooks/copilot-hook.js` 的 session-state resolver 同样走 env\n- Remote SSH 的 effective transport 由 `ssh -G` 只读检查决定：ordinary SSH 在没有 retained serialized occupancy 时保持 `context:null` 的 parallel 路径；serialized transport 以有效 target key（不是 profile id）互斥。所有 serialized managed SSH/SCP child 必须持 coordinator 发出的有效 connection/operation context，并通过其 pre-spawn gateway 启动；用户交互终端只有命中 serialized/retained occupancy 时才要求 coordinator 判定 target 完全 idle\n- serialized persistent tunnel 使用同一条 SSH 内嵌 readiness；暂停通过 stdin EOF 请求自然退出并等待 `close`。强杀或带 signal 的 outer `ssh.exe` close 不能证明 nested ProxyCommand 已 drain；timeout/未验证 drain 必须 quarantine，期间禁止新 child、mutation、resume 或 interactive terminal\n- mutation 在 deploy-lock acquire-attempted / lock-owned 后遇到 exit 255、EOF/reset、signal 或其他 unknown result 时不得自动 replay、retry、release lock 或恢复连接；必须保留 primary error 并传播 recovery state，必要时要求 `manual_lock_inspection_required`\n- Remote SSH secure hook 必须同时携带 `CLAWD_REMOTE=1` 与 `CLAWD_SSH_REMOTE=1`，只读 layout identity 并 pin 精确端口；identity 缺失/损坏/不可读必须 fail closed，禁止回退端口扫描\n- Remote SSH deploy-lock acquisition 必须原子化；成功 acquire 后的每个 live mutation 都要在同一远端命令内 fencing 校验，cleanup 还必须锁内重读 installId/profileId/runtimeKey/layoutVersion 所有权。无身份、冲突、ownerless/corrupt lock 均不得自动接管\n- 默认 `account-default` 只支持不同 Unix 账号；同 Unix 账号冲突必须阻止。`profile-isolated` 在真实 SSH/CLI 矩阵完成前由 `CLAWD_ENABLE_EXPERIMENTAL_REMOTE_ISOLATION=1` 发布门隐藏；它只隔离用户级 CLI config/session/runtime 与 Clawd 路由，不代表完整 HOME 或同 UID 安全隔离，project 配置/部分 cache/macOS Claude Keychain auth 仍可能共享\n- Hermes Agent 的 Remote SSH 部署是 `secureDeploy` 内的 `hermes-files` → `install-hermes` 两个阶段，复用同一条 serialized transport、deploy lease、fencing 与所有权检查，没有独立的 Hermes SSH deployer：secure 模式由每个托管 `plugins/clawd-on-desk/` 内的 plugin-local marker `clawd-ssh-secure-v1` latch，latch 后 identity 必须在每次 state/probe/permission 请求时重新读取（禁止 `(mtime,size)` 缓存），且不得发送任何远端 PID / 进程树 metadata；plugin 资产走独立 staging 目录，清理只 `rm -f` 精确文件再 `rmdir`，禁止 `rm -rf`；`REMOTE_IDENTITY_STEP_NAMES` 保持冻结的 8 步不变，不得加入 `installHermes`；Clawd 绝不自动重启 Hermes gateway，托管模块被替换时只报告需要手动重启\n- 禁用 agent 不应卸载 hooks / plugins / extensions：只停止对应 monitor、清理 session / bubble、让 HTTP hook 入口快速 fallback；重新启用未安装 agent 不触发本机 integration sync。卸载集成必须走 Settings Agent 页的 Uninstall / 对应 uninstall 命令，并同时清掉 `integrationInstalled`\n- Kiro 的 `sessionId=\"default\"` 会复用；session alias key 必须按 cwd scope 区分，同时保留旧 `local|kiro-cli|default` 只读 fallback\n- Windows NSIS release 必须产出明确架构的 x64 / ARM64 安装包：`win.artifactName` 保留 `${arch}`，`nsis.buildUniversalInstaller` 保持 `false`\n- 每个 release target 只能保留一个匹配目标架构的 Koffi `koffi.node`；`afterPack` 只允许剪裁 `app.asar.unpacked` 的物理文件，禁止重写 `app.asar`，并必须通过完整 native inventory audit（唯一常设例外是 electron-builder 管理的 Windows ia32 `resources/elevate.exe`）\n- 资源路径统一用 `path.join(__dirname, ...)`\n- 需要编辑发布素材时，先复制到 `assets/source/` 再改，不要直接改工作素材来源不明的文件\n- `assets/source/cloudling-pointer-bridge/` 是 Cloudling 指针桥素材的保留源文件目录；运行时逻辑已内联进主题 SVG，不要把这个 source 目录当临时文件清理\n- 主题状态、sleep/DND、mini mode、状态映射的细节在 `docs/project/theme-state-ui.md`\n- 官方可下载主题（`official-theme-*`）是受管分发层，不是 built-in、也不提升信任：catalog 是固定远端小目录（renderer 只能传 themeId），下载走 Electron main `net.request` 的 manual redirect + 精确 CDN host allowlist + 固定 bytes/SHA-256（未支持 host 返回稳定 `DOWNLOAD_HOST_UNSUPPORTED`，不允许 catalog 扩展 allowlist），ZIP 只在 manager 专属 staging 内流式解压并以 marker-before-rename 同卷提交，最终以 `isBuiltin=false` 加载（`trustedRuntime` 无效）。`setThemeSelection` / `removeTheme` / `officialTheme.commitInstall` / `officialTheme.uninstall` / `theme` update 共用 `lockKey=\"theme\"`；卸载 active 主题必须等 `waitForThemeReloadSettled()`。主仓库附带一份目录快照 `src/official-theme-catalog-snapshot.json`：网络拉取失败时列表先用上一次成功加载的目录（内存 LKG 或磁盘缓存），都没有才用快照；第一次拉取有结果之前（`uninitialized`）不用快照；快照**不作安装依据**，安装仍只认经校验的网络/磁盘目录。快照只作列表回落（仍显示 `offline` 和重试），不含素材与预览图，不写磁盘缓存，且参与版本不能回退的比较；发布前用 `npm run update:official-theme-snapshot` 刷新。不要把 Hash Sage / Whale-chan 的动画素材（APNG / WebP），或把它们写成内置主题的文案带回主仓库\n- Settings 体系里，store 是唯一真相，controller 是唯一写入者；不要绕开 `settings-controller.js`\n- Dashboard 数字快选是**完整 Dashboard 同一页面的临时键盘模式，仅 macOS/Windows**；Linux 明确 NOT SUPPORTED（不是待验证）。平台 gate 的唯一真相是 `shortcut-actions.js` 的 `supportedPlatforms` + `isShortcutActionSupported()`，Settings 展示、globalShortcut 注册/录制、设置命令和冲突占用都必须服从它；遗留的不支持绑定只忽略执行，不删用户 prefs、不占其他快捷键。darwin/win32 的 Dashboard 页面活在 `WebContentsView` 里，`BrowserWindow.fromWebContents()` 对它返回 null、BaseWindow 不触发 `ready-to-show`；页面 WC 一律从 owner 取。禁止用 `hide()`+`showInactive()` 归还已显示的普通宿主（实测会遮挡来源窗口），只能 opacity/input parking 并幂等恢复捕获值。详见 `docs/project/theme-state-ui.md`\n\n## Testing\n\n- 自动化测试使用 Node 内置 test runner：`npm test`\n- `test/*.test.js` 覆盖核心 unit/contract、installer、route、UI/runtime 与 Remote SSH transport/coordinator/identity；部分 fixture 会启动 Node、shell 或 Git Bash 子进程，缺少依赖时可能 skip，不能把全套结果概括成纯逻辑或等价真机验证\n- Remote SSH 真机矩阵与记录在 `scripts/manual/README.md`；Windows OpenSSH + Codespaces stdio 边界及 ordinary-host V15 release gate 不能从 unit tests 互相推断，无法执行时必须明确记录 pending / residual risk\n- Windows Terminal 真机、GUI smoke 与清理必须假定多个 tab/window 共享进程：不得按 PID/进程名 `taskkill`、`Stop-Process` 或宽泛终止 WindowsTerminal、Codex、`cmd.exe`、`ssh.exe`、OpenConsole、conhost。测试终端只能在明确 test-owned session 内 `exit`；无法证明 ownership 就保留现场并请用户手动关闭\n- 当前开发环境是 Windows-first；macOS 特定路径无法在这里手动 QA，改到 mac 逻辑时要用 code-review","isInternal":false,"tokens":24025,"sizeBytes":73755},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# AGENTS.md\n\nThis file is the entry point for coding agents working in this repository. Keep it short and operational. Durable architecture lives in `docs/project/`; `docs/plans/` and `docs/investigations/` are historical evidence unless this file explicitly links them.\n\n## Project Overview\n\nClawd 是一个 Electron 桌宠：通过 hook、日志轮询、plugin 和 extension 感知 AI coding agent 的工作状态，并播放像素风动画。当前支持 Claude Code、Codex CLI、Copilot CLI、Gemini CLI、Antigravity CLI (agy)、Cursor Agent、CodeBuddy、WorkBuddy、Grok Build、Kiro CLI、KiroCrew、Kimi Code CLI (Kimi-CLI)、Qwen Code、ZCode、CodeWhale、opencode、MiMo Code、Pi、OMP (oh-my-pi)、OpenClaw、Hermes Agent、Qoder、QoderWork、QwenWork (千问办公)、Reasonix、DeepSeek Harness、TraeCode (Trae CN)、MiniMax Code；内置 Clawd / Calico / Cloudling 三套主题，支持用户主题，并可经 Settings 从独立 `rullerzhou-afk/clawd-themes` 仓库下载可选官方主题（Hash Sage、Whale-chan，external theme 权限、可卸载）；平台覆盖 Windows、macOS、Linux，UI 支持 en / zh / zh-TW / ko / ja / pt-BR / es。\n\n## Common Commands\n\n```bash\nnpm start\nnpm run build                  # default Windows package\nnpm run build:win:x64\nnpm run build:win:arm64\nnpm run build:win:all\nnpm run build:mac\nnpm run build:linux\nnpm run build:all\nnpm install\nnpm test\nnpm run verify:electron\nnpm run verify:release\nnpm run audit:assets\nnpm run audit:pr-history-assets\nnpm run audit:native-package -- --app-root <extracted-app-root> --target <target-id>\nnpm run create-theme\n\nnpm run install:claude-hooks\nnpm run uninstall:claude-hooks\nnpm run install:cursor-hooks\nnpm run install:gemini-hooks\nnpm run install:antigravity-hooks\nnpm run install:kiro-hooks\nnpm run install:kirocrew-hooks\nnpm run uninstall:kirocrew-hooks\nnpm run install:kimi-hooks\nnpm run install:qwen-hooks\nnpm run install:zcode-hooks\nnpm run uninstall:zcode-hooks\nnpm run install:codewhale-hooks\nnpm run uninstall:codewhale-hooks\nnpm run install:pi-extension\nnpm run uninstall:pi-extension\nnpm run install:omp-extension\nnpm run uninstall:omp-extension\nnpm run install:openclaw-plugin\nnpm run uninstall:openclaw-plugin\nnpm run install:hermes-plugin\nnpm run uninstall:hermes-plugin\nnpm run install:qoder-hooks\nnpm run uninstall:qoder-hooks\nnpm run install:qoderwork-hooks\nnpm run uninstall:qoderwork-hooks\nnpm run install:qwenwork-hooks\nnpm run uninstall:qwenwork-hooks\nnpm run install:reasonix-hooks\nnpm run uninstall:reasonix-hooks\nnpm run install:workbuddy-hooks\nnpm run uninstall:workbuddy-hooks\nnpm run install:grok-hooks\nnpm run uninstall:grok-hooks\nnpm run install:dsh\nnpm run uninstall:dsh\nnpm run install:codex-hooks\nnpm run uninstall:codex-hooks\nnpm run install:codex-debug-hooks\nnpm run uninstall:codex-debug-hooks\nnpm run install:mimocode-plugin\nnpm run uninstall:mimocode-plugin\nnode hooks/codebuddy-install.js\nnode hooks/opencode-install.js\n\nbash test-demo.sh [seconds]\nbash test-mini.sh [seconds]\nbash test-macos.sh\nbash test-oneshot-gate.sh [state] [seconds]\n```\n\n新安装默认只把 Claude Code 和 Codex 标记为已安装并启用；其他 agent 默认未安装、未启用。正常启动时，Clawd 只会为 `integrationInstalled=true` 且 `enabled=true` 的 agent 自动同步 Claude / Codex / Copilot / Gemini / Antigravity / Cursor / CodeBuddy / WorkBuddy / Grok Build / Kiro / KiroCrew / Kimi / Qwen / ZCode / CodeWhale / Qoder / QoderWork / QwenWork / Reasonix / TraeCode / MiniMax Code hooks、opencode / MiMo Code / OpenClaw / Hermes plugins 和 Pi / OMP extensions。Settings Agent 页的 Install 会安装并启用该集成；Uninstall 会卸载 Clawd 管理的 hook/plugin/extension，并同时把该 agent 设为未安装、未启用。单独关闭 enabled 只会跳过启动同步并屏蔽事件/权限入口，不卸载用户已有 hooks / plugins / extensions；重新启用未安装 agent 只打开事件入口，不会写本机集成文件。手动安装命令主要用于调试、重装或远程部署。\nSettings 注册的自定义 HTTP Agent 是独立模型：`customApplications` 是注册真相，对应 `agents[customId]` 必须显式保持 `integrationInstalled=false`。注册只分配 ID 和状态入口，不安装 hook、不观察进程；v1 仅允许已注册且启用的 ID 向 `/state` 上报，`/permission` 永远不提供决定。删除或伪造的 `custom-` ID 必须直接拒绝，不能降级成 Claude Code subagent。\nCopilot CLI 同步走 `<COPILOT_HOME 或 ~/.copilot>/hooks/hooks.json`，marker-based 增量合并只接管含 `copilot-hook.js` 标记的条目，用户其他 entry / 其他 `hooks/*.json` 文件原样保留；hooks.json 或 `settings.json` 顶层 `disableAllHooks: true` 时 doctor 报 warning（不挂 Fix 按钮）。详见 `docs/guides/copilot-setup.md`。\n\n## Read These Docs\n\n- `docs/project/agent-runtime-architecture.md`：运行时架构、模块边界、启动与数据流、多 agent、permission bubble、终端聚焦和自动同步\n- `docs/project/theme-state-ui.md`：状态机、主题系统、settings、mini mode、素材规则、平台限制、待落地 UI 决策\n- `docs/project/release-process.md`：发版 checklist、release note 核对、tag 触发 GitHub 打包和资产确认\n- `docs/guides/copilot-setup.md`：Copilot CLI 自动同步说明、`COPILOT_HOME` 兼容性、手动配置备选模板\n- `docs/guides/dsh-setup.md`：DeepSeek Harness web profile 与桌面版的实验性 plugin 集成状态与普通审批集成\n- `docs/guides/state-mapping.md`：状态 → 动画权威表\n- `docs/guides/guide-theme-creation.md`：主题作者指南\n- `docs/guides/setup-guide.md`：安装、远程 SSH、各 agent 接入\n- `docs/guides/custom-agent-http.md`：自定义 HTTP Agent 的 state-only 接入合约和动态端口发现\n- `docs/guides/known-limitations.md`：用户向已知限制\n- `docs/guides/recap.md`：本地小结的指标口径、coverage、时区/DST、隐私存储与产品红线\n- `docs/guides/codex-wsl-clarification.md`：Codex / WSL 路径与 Node 说明\n- `docs/guides/guide-remote-ssh.md`：Remote SSH 用户流程、Codespaces 单会话 transport 与共享主机边界\n- `docs/guides/telegram-approval.md` / `docs/guides/feishu-lark-remote-approval.md`：远程审批设置与失败回退语义\n- `docs/guides/roam-fence.md`：自由漫游与可选围栏\n\n## Runtime Summary\n\n- HTTP hook / plugin 主路径：`src/server.js` → `src/server-route-state.js` → `src/agent-runtime-main.js` → `src/state.js` → IPC；本地 JSONL monitor 直接进入 `agent-runtime-main`，不经过 HTTP server\n- 权限主路径：`src/server-route-permission.js` → `src/permission.js`；本地 bubble、显式 permission automation 与可选 Telegram / 飞书 Lark 远程审批都可能产生真实决定\n- 桌宠的渲染/输入双窗口由 `src/pet-window-runtime.js` 统一创建和定位；浮层排序与 topmost 行为在 `src/floating-window-runtime.js` / `src/topmost-runtime.js`\n- `src/state.js` 生成的 session snapshot 是 Dashboard、HUD/Orbit 与可选通知/presence/mobile consumer 的共享合约，改字段必须检查所有消费者\n- `src/integration-sync.js` 为已安装且启用的 agent 异步同步 hooks / plugins / extensions；Codex official hooks 为 primary，JSONL 轮询保留为 fallback\n- Claude hook 恢复由 `src/claude-settings-watcher.js` 的目录 watcher + 低频只读巡检共同负责；repair 统一经过 `src/claude-hook-operations.js` 队列并复验，连续失败转 `manual-fix-required`。完整 gate、阈值与 source-missing 语义见 `docs/project/agent-runtime-architecture.md`\n- `src/agent-gate.js` 控制各 agent 的安装意图、启用状态、权限气泡开关和 wait-for-input notification 子开关\n- 设置系统主链路是 `src/prefs.js` → `src/settings-controller.js`（唯一写入者）→ `src/settings-store.js`；`settings-actions*` 负责校验和 pre-commit gates，`settings-effect-router.js` 负责 post-commit runtime effects 与广播\n- 启动时还会尝试自动安装 VS Code / Cursor terminal-focus extension，并初始化 updater\n- Remote SSH 通过 effective transport inspection 区分 ordinary parallel SSH 与 serialized transport；后者由 target-scoped coordinator 编排。远程部署只走 Settings，`scripts/remote-deploy.sh` 已 fail-fast 停用\n\n## Core Files\n\n更细的背景见 `docs/project/agent-runtime-architecture.md` 和 `docs/project/theme-state-ui.md`。\n\n| File | Responsibility |\n|------|------|\n| `src/main.js` | Electron composition root：生命周期、上下文组装与各 runtime / IPC 注册器接线 |\n| `src/server.js` + `src/server-route-state.js` + `src/server-route-permission.js` | HTTP 服务、端口发现、`/state` / `/permission` 路由 |\n| `src/agent-runtime-main.js` + `src/integration-sync.js` | local monitor / official hook 仲裁、Codex turn fence、按 gate 的集成同步 |\n| `src/state.js` | 状态机、多会话合并、优先级、自动回退、睡眠/DND |\n| `src/renderer.js` | 动画切换、SVG 预加载、眼球追踪渲染 |\n| `src/permission.js` + `src/permission-automation-policy.js` + `src/session-automation-coordinator.js` | 权限气泡、自动化策略、per-session 授权与决策回包；远程 client 由 `main.js` 注入 |\n| `src/pet-window-runtime.js` + `src/floating-window-runtime.js` + `src/topmost-runtime.js` | 双窗口 owner、浮层重排、z-order / fullscreen / focusability |\n| `src/update-bubble.js` | 更新气泡创建、测高、跟随桌宠定位，避让 HUD / permission stack |\n| `src/dashboard.js` + `src/dashboard-renderer.js` | Sessions Dashboard 唯一 owner：会话列表、别名编辑、终端跳转、几何持久化，以及同一页面的临时键盘模式 |\n| `src/dashboard-host.js` | Dashboard 普通宿主的平台封装：darwin/win32 用 `BaseWindow + WebContentsView`（无 `ready-to-show`），Linux 保留 `BrowserWindow` |\n| `src/dashboard-quick-mode.js` | 完整 Dashboard 的 1–9 键盘模式（**macOS/Windows only**）：quick 宿主、opacity/input parking、轮次栅栏与冻结数字映射；Windows 显式取消与页面失效的来源恢复在 `src/quick-select-origin-focus.js`，quick 宿主的退出清理挂在 `before-quit` |\n| `src/session-hud.js` + `src/session-hud-renderer.js` | 桌宠旁轻量会话 HUD、折叠行、点击跳转 |\n| `src/session-alias.js` | session alias key 规范化、TTL pruning、Kiro cwd scope |\n| `src/theme-loader.js` + `src/theme-runtime.js` | stateless 主题加载/消毒与唯一 active-theme owner；`waitForThemeReloadSettled` 完成信号 |\n| `src/official-theme-catalog.js` / `-download.js` / `-installer.js` / `-main.js` | 官方可下载主题：严格 catalog/cache、Electron `net.request` 流式下载、受限流式 ZIP 解压与 marker-before-rename、main owner/IPC/共享 `theme` lock |\n| `src/prefs.js` | 偏好 schema、load/save/migrate/validate，设置持久化入口 |\n| `src/settings-actions*.js` + `src/settings-effect-router.js` | 设置 validators / commands / pre-commit gates 与 post-commit runtime effects |\n| `src/settings-controller.js` | 设置系统唯一写入者 |\n| `src/settings-store.js` | 不可变 snapshot store |\n| `src/settings-ui-core.js` + `src/settings-renderer.js` + `src/settings-tab-*.js` | Settings shared UI state、侧栏/tab shell 与各页逻辑 |\n| `src/menu.js` | 托盘 / 右键菜单，串起设置、Dashboard、mini mode、更新入口 |\n| `src/mini.js` | 极简模式入场、滑动、peek、状态映射 |\n| `src/tick.js` | 主循环、鼠标轮询、眼球和 idle/sleep 逻辑 |\n| `src/drag-position.js` | 拖拽落点规范化与跨显示器钳制 |\n| `src/visible-margins.js` | 可视角色边距与 edge pinning 规则 |\n| `src/updater.js` | Git 模式 / `electron-updater` 双路径更新逻辑 |\n| `src/focus.js` | 终端聚焦 |\n| `src/hit-renderer.js` + `src/hit-geometry.js` | 输入窗口命中、拖拽、连击反应 |\n| `src/remote-ssh-runtime.js` | Remote SSH tunnel/ingress 状态机、ordinary health probe、serialized readiness 与重连 |\n| `src/remote-ssh-transport.js` + `src/remote-ssh-transport-coordinator.js` | effective transport inspection、pre-spawn admission、target ownership、drain barrier 与 quarantine |\n| `src/remote-ssh-deploy.js` | Deploy / Repair、身份事务、lease/fencing、wrapper、cleanup 与远端 Codex monitor mutation |\n| `src/remote-ssh-identity.js` + `src/remote-ssh-layout.js` + `src/remote-ssh-ingress.js` | 身份/布局真相与 profile 专属、nonce 校验的本地 ingress |\n| `src/remote-ssh-node.js` + `src/remote-ssh-shell-detect.js` + `src/remote-ssh-local-config.js` | 远端 Node/ shell 探测与本机 SSH config 入口 |\n| `src/remote-ssh-profile.js` | Remote SSH profile schema、校验、默认值和持久化规范化 |\n| `src/remote-ssh-ipc.js` | Remote SSH runtime / deploy / monitor orchestration、intent policy、IPC 状态与进度广播 |\n| `src/remote-ssh-quote.js` | Remote SSH 终端命令与跨平台 shell quoting helper |\n| `agents/registry.js` | agent 注册表 |\n| `agents/codex-log-monitor.js` | Codex JSONL fallback 轮询 |\n| `agents/gemini-log-monitor.js` | legacy Gemini session JSON 轮询器；当前 Gemini hook-only 路径不启动 |\n| `hooks/dsh-install.js` | DeepSeek Harness immutable managed bridge generation、ownership verify、web 与 desktop 两个 profile 的安装 / 修复 / 卸载编排 |\n| `hooks/kirocrew-install.js` + `hooks/kirocrew-store.js` | KiroCrew state-only gateway hooks、upstream-compatible mutation locks and atomic private store writes |\n| `hooks/kirocrew-hook.js` + `hooks/kirocrew-command.js` | KiroCrew state bridge and exact command-shape ownership classifier |\n| `hooks/dsh-notices.js` | DeepSeek Harness 常驻提示的存储与规则（按 profile 的 `notices-<profile>.json`） |\n| `hooks/clawd-hook.js` + `hooks/copilot-hook.js` | Claude Code / Copilot CLI 状态上报脚本 |\n| `hooks/install.js` | Claude hook 注册 / 卸载 |\n| `hooks/auto-start.js` | Claude `SessionStart` 自动拉起 Clawd 的 hook |\n| `hooks/codex-hook.js` / `hooks/codex-install.js` | Codex official hooks 状态与权限审批、安装 / 卸载 |\n| `hooks/cursor-install.js` / `gemini-install.js` / `antigravity-install.js` / `kiro-install.js` / `kimi-install.js` / `qwen-code-install.js` / `codewhale-install.js` / `codebuddy-install.js` / `workbuddy-install.js` / `opencode-install.js` / `pi-install.js` / `openclaw-install.js` / `hermes-install.js` / `qoder-install.js` / `qoderwork-install.js` / `reasonix-install.js` | 各 agent 集成安装逻辑 |\n| `hooks/opencode-family-managed-generation.js` | OpenCode 用户可写托管 generation（canonicalizer、bundle/manifest、stage/promote、target owner record、target-scoped lock）；纯 Node 内置依赖，不进入 Remote SSH `HOOK_FILES` |\n| `hooks/opencode-family-entry-ownership.js` | OpenCode-family plugin entry 的 string/tuple 解析、跨平台路径等价、所有权分类与重复/options 冲突规划（纯逻辑、可注入 fs） |\n| `hooks/opencode-family-install.js` / `hooks/opencode-family-jsonc.js` | 家族注册器：`managedMaterialization:true` 走托管 generation 事务 + 共享 entry planner；`false` 保持 legacy broad-basename register/unregister |\n| `src/doctor-detectors/opencode-managed-inspector.js` | managed OpenCode Doctor inspector（ownership/manifest/生成结构、Fix policy、masked supplementary warning）；接受注入 fs |\n| `hooks/workbuddy-hook.js` | WorkBuddy state + Notification command hook；无 session_id 时返回合法 stdout 后丢弃事件 |\n| `hooks/grok-hook.js` / `hooks/grok-install.js` | Grok Build state + Notification command hook；写入 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json`；`env` marker `CLAWD_GROK_HOOK=v1` 所有权；无 session id 时丢弃；不注册 `/permission` |\n| `hooks/zcode-hook.js` / `hooks/zcode-install.js` | ZCode 状态 + 阻塞式 PermissionRequest hooks（`hookSpecificOutput` 决定 / `{}` 无决定）、`hooks.events.*` 按事件超时增量注册与 Claude-imported Clawd hook 清理 |\n| `hooks/qoder-hook.js` | Qoder state-only 状态上报脚本（Phase 1，stdout 恒为 `{}`） |\n| `hooks/minimax-hook.js` / `hooks/minimax-install.js` | MiniMax Code state-only 本地插件：整目录 install/uninstall（`<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/`），CLAUDE 格式 hooks + exec-form args，10 事件无 PermissionRequest/Notification，`.clawd-managed.json` 结构化所有权凭据、fail closed |\n| `hooks/codex-remote-monitor.js` | 远程 Codex JSONL 轮询并通过 SSH 隧道回传（含 token_count 订阅配额的 metadata_only 上报） |\n| `hooks/claude-statusline.js` / `hooks/antigravity-statusline.js` | 各 CLI statusline 适配器：渲染状态行 + 把订阅配额（rate_limits）以 metadata_only POST 上报；Claude 版支持远程部署（`CLAWD_REMOTE=1` 前缀）与 `--chain` 串联模式（原 statusLine 对象保存在 `~/.claude/hooks/clawd-statusline-chain.json`，卸载时恢复） |\n| `extensions/vscode/extension.js` | VS Code / Cursor 终端 tab 聚焦辅助扩展 |\n\n## Constraints\n\n- `agents/registry.js` 的 capabilities 是权限、subagent、session-end 等路由/gate 的权威来源；不得另写名单代替 capability 判定。但 permission automation eligibility 由更窄的 `isKnownPermissionAgent()` 显式判定（`KNOWN_PERMISSION_AGENTS` + explicit opencode-family membership），不得从 `permissionApproval` 自动派生或合并回 registry capabilities\n- 小结的指标能力例外地只认 `src/recap-metrics.js` 的显式逐 Agent 口径，不得从 registry capabilities 或标准化 event 名推导。只统计已通过 gate、Codex source/replay fence、subagent 与完成仲裁的 accepted activity；DND 继续记录且不切 coverage，suspend/退出/关闭记录才切。`null` 是不支持，绝不能渲染或汇总成 `0`\n- 小结持久层固定为 `~/.clawd/recap-v1/` 下 14 个本地日的最小 HMAC 小票与 400 个本地日的 daily/coverage；不得落 prompt/回复/命令/工具内容、路径/项目、原始 event/session/profile/turn/tool ID，不得增加网络、导出或分享。首版不做 Token、金额、模型、推理强度、Skill、人的工作/编码时长、streak、峰值/最长项、排行榜或生产力评分\n- Claude Code / CodeBuddy 的阻塞式权限审批走 `POST /permission` HTTP hook；普通状态事件走 command hook（CodeBuddy command hook 对所有事件输出 `{}`，不做工具或权限决定）\n- permission automation（off / auto-tools / unattended）和 per-session grant 会在 bubble 渲染前产生真实 allow/answer。agent/family eligibility 是显式白名单；工具分类则因 mode/adapter 而异：auto-tools 对 Claude/Qwen 的未知 built-in fail closed，但其他已知 adapter 不都使用逐工具白名单，unattended 还会有意自动放行可作 Allow/Deny 的未知请求。新增 agent、工具或交互类型必须审查 policy + tests，不能从 `permissionApproval` 推导资格或笼统假设“未知请求都会 defer”\n- Telegram / 飞书 Lark 与本地 bubble 是并行决策通道。远程通道超时、断连、未配置或发送失败不得产生远程决定，更不得转成 deny；有本地 bubble 时请求继续 pending，只有 remote-only 且所有可用 client 都无决定时，整体请求才 no-decision 并回到 agent 原生流程\n- WorkBuddy 通过当前 `~/.workbuddy-ai/settings.json`（旧版兼容 `~/.workbuddy/settings.json`）的 Claude Code 兼容 command hooks 做 **state + Notification only** 集成：不注册 `/permission`，审批始终留在 WorkBuddy 原生沙箱与 GUI；无 `session_id` 的事件返回合法 stdout 后直接丢弃。当前只支持 macOS/Windows 桌面应用，没有已验证的 Linux/WSL CLI；不要把裸 `Electron` 当 WorkBuddy 进程。\n- Grok Build（agent id `grok-build`）通过 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json` 的 Claude Code 兼容 command hooks 做 **local / main-session / state + Notification only** 集成（Phase 1）：stdin 为 camelCase（`sessionId` / `toolName`），`hookEventName` 是 camelCase key + snake_case value，`hook_event_name` 是 snake_case key + PascalCase value。**逐 handler 的 `env` 结构化 marker `CLAWD_GROK_HOOK=v1` 是唯一所有权凭据**；文件名/substring（含 `grok-hook.js.backup`）只用于诊断告警，永不授权改写或删除。安装/卸载只增删含该 marker 的 handler，保留 unknown 顶层键、其他 event、foreign matcher group 与 sibling handler；没有 marker 的既有文件一律原样拒绝。`SessionEnd` 不写 `timeout`（继承 Grok 1.5s teardown），其余事件 5s。Windows 用 `windowsWrapper:\"portable\"` 形态，不得用 `&` / `-EncodedCommand` / 自造 `shell` 字段。Grok 没有 `PermissionRequest`，不注册 `/permission`，adapter 始终输出 `{}`。子代理事件（`subagentType`）直接丢弃；不注册 `SubagentStart` / `SubagentStop`。Grok 默认会扫 `~/.claude/settings.json`，所以 `clawd-hook.js` / `cursor-hook.js` / `auto-start.js` 只在非空官方 `GROK_HOOK_EVENT` 下直接退出，`GROK_HOME` / `GROK_SESSION_ID` / 无关 `GROK_*` 不得触发。`Stop` 只有精确 `reason === \"end_turn\"` 且无 background task / session cron / `stopHookActive` 才算完成，其余由 adapter 本地判定；`channel_closed` / `shutdown` 等 session-end 形态的 Stop 在 fence 之前丢弃。turn 顺序由 `src/grok-turn-fence.js` 的 bounded in-memory fence 仲裁（晚到旧 turn、重复 terminal、continuation Stop、Stop→StopCancelled 纠正）。不进入 subagent / WSL / Remote SSH / startup recovery / terminal focus / quota / context / recap turn 指标。`~/.grok/hooks/clawd.json` 是未发布的 PR preview 路径，只做 warning，不得自动接管或删除。\n- Codex 的阻塞式权限审批走 official `PermissionRequest` command hook：hook 脚本长连接 `POST /permission`，只允许 stdout 返回 sanitized `behavior/message`，`updatedInput` / `updatedPermissions` / `interrupt` 必须 omit。权限模式默认 `auto`（旧 `native` 规范化为 `auto`），仅准确本机 session/turn 的人工 reviewer 证据可进 Clawd；未知、自动 reviewer、MCP/app、远程/WSL 均 no-decision；唯一例外是远程/WSL（路由 reason 为 `nonlocal`）的 Bash/apply_patch 在全局自动放行会立即 allow 时（`wouldAutoAllowPermission`：非 reminder hold、非会话覆盖、非交互子代理）由 Clawd 直接放行（#1186），路由后若设置已变则 no-decision，绝不弹气泡。`intercept` 是显式接管；升级时旧 `intercept` / `native` 统一迁到 Auto 一次，之后重新选择的 Intercept 会保留。不得用全局 config、其他会话或旧回合推断当前请求的审批方；证据不足时返回 no-decision，交还 Codex 原生流程。\n- hook 脚本只允许依赖 Node 内置模块，以及同目录 `hooks/` 下、且登记在 `src/remote-ssh-deploy.js` 的 `HOOK_FILES` 部署清单中的纯 Node helper（如 `server-config.js` / `shared-process.js` / `json-utils.js` / `codex-originator.js` / `codex-subagent-fields.js` / `context-usage.js` / `state-payload-size.js` / `quota-bucket.js` / `claude-rate-limits.js` / `codex-rate-limits.js` / `antigravity-context-usage.js`）；manifest-consistency 测试强制检查依赖闭包，新增 helper 必须登记\n- CJS hook 脚本需要稳定终端 PID 时，必须复用 `hooks/shared-process.js` 的 `createPidResolver()` 及其 lifecycle context；不要复制进程树 walk 或用 `process.ppid` 简化。`getStablePid()` 只是 opencode-family plugin 的内部 resolver\n- `agentCmdlineCheck` 只对进程名在 `agentCmdlineNames` 里的祖先进程运行，默认是 `DEFAULT_AGENT_CMDLINE_NAMES`：`node` / `node.exe`，加上 Linux 上没设过 `process.title` 的 Node 在 `ps -o comm=` 里的名字——Node 23.8–25.4（含全部 24.x）把主线程命名为 `MainThread`、≥ 25.5 为 `node-MainThread`，Linux 报的进程名就是主线程名。传入 `agentCmdlineNames` 会整体替换默认值：只想加名字的 adapter 必须在选项里直接写成 `agentCmdlineNames: new Set([..., ...DEFAULT_AGENT_CMDLINE_NAMES])`（如 ZCode；可以跨行，方括号里只能有普通字符串字面量和 `...DEFAULT_AGENT_CMDLINE_NAMES` 本身，不能有注释或其他表达式；简写属性、先存进变量，或任何不是这个形状的提及（包括注释里的）都会被判不合格，因为文本检查无法核对），只有刻意只探测非 Node 宿主的（WorkBuddy 的 `electron`）例外，`test/shared-process.test.js` 会扫描 `hooks/*.js` 检查\n- opencode v1 权限不走 `permission.ask` hook，而是 event hook + reverse bridge；v2 走 `ctx.permission.hook(\"evaluate\")` 的阻塞 HTTP 响应\n- OpenCode / MiMo v1 原生问题走独立本地 `/question` 长轮询，不复用审批回包；遵循全局 permission bubble 开关与 family 单 agent 开关。只接受已核实的 v1 来源、版本和问题 schema，提交前用原 SDK client 复核精确 request/tool/session，答案保持有序 `string[][]`；无决定返回 204 交还原生。OpenCode 由原生 reply RPC 的 `true` / 404 判定提交结果，MiMo 仍需精确 `question.replied` 答案匹配。子会话问题、OpenCode v2、Remote SSH 及未审核 agent 保持原生；不要改 Claude/Hermes wire 或托管 generation 依赖集合。详见 `docs/guides/agent-questions.md`。\n- opencode-family v1 插件经 `ctx.client` 连回宿主时，主机为通配监听地址（`0.0.0.0` / `[::]`）就按次改用 `127.0.0.1` / `[::1]`（不改宿主共享的客户端配置；非通配地址保持原调用形状）。默认 TUI 走进程内 fetch；`opencode serve` / `web` 下这是对监听地址的真实 HTTP 请求，受宿主进程里的 `HTTP_PROXY` / `NO_PROXY` 影响，而通配地址不会自动绕过代理。桥接回复失败返回 `{ok:false,status,error}`（`status` 为上游状态码，缺省 0）。\n- OpenCode 2.x（npm `@opencode/cli`，issue #1039）由 `hooks/opencode-plugin-v2/` + core.mjs 内 `createOpencodeFamilyPluginV2` 承接：installer 在同一 generation 内额外物化 `opencode-plugin-v2/index.mjs`（v1 四文件、v2 五文件；目录 specifier 解析 index.mjs、无需 package.json，2.0.15 实测），并把它写进 **`plugins` 键**，同时清理 Clawd 自有的旧 `plugin` 条目；用户条目、tuple/options 和 v1 行为保持不变。未被 Clawd 纳管的未知 `plugin` 条目仍只报 loader WARN；v1 对未知 `plugins` 键的静默丢弃只在 **1.18.16+** 成立——1.18.15 及更早会以 `Unrecognized key: plugins` 拒绝整个 config（anomalyco/opencode#41312，2026-08-08 起才忽略未知顶层键），因此 `plugins` 写入由宿主探测决定（`hooks/opencode-host-detect.js` 三态：探测到 v2 才写；探测到 v1 不写并清扫 owned 残留；探测失败不碰该键；`CLAWD_OPENCODE_HOST` 环境变量可钉死结论，Doctor 在无 v2 宿主时不要求 v2 条目）。v2 插件是零 import 纯对象 `{id, setup}`（v2 loader 拒绝函数 default export，`@opencode/...` 裸包名无插件本地 node_modules 不可解析），事件经 `ctx.event.subscribe()`（`session.step/tool/execution.*` 词汇完全换代，未知事件一律忽略），cwd 取事件信封 `location.directory`，标题走 `session.renamed`，context usage 走 `session.step.ended` 的 step tokens（`session.usage.updated` 是 session 累计计费值，不能当占用率）。权限走 **`ctx.permission.hook(\"evaluate\")` 阻塞长连接 POST `/permission`**，决定就是 HTTP 响应体 `{decision: allow|always|deny}`（服务端按 `hook_source === \"opencode-plugin-v2\"` 路由到 v2 阻塞子分支），只有 `200` + 身份头 + 合法 JSON 才采纳决定，204/超时/断连/非 200/任何错误都不改 effect 回原生 ask UI；配置 allow 也进 hook 但绝不降级；单条 shell 命令以 `tool_input.resource` 传输，服务端 v2 分支会为其别名出 `command` 以接入破坏性操作提醒（`mapOpencodeV2ShellResource`，非 shell 工具不映射；全字符串的多 resource 以换行合并作扫描别名）；resources 原样整组转发（对象转 JSON 字符串），不做条数/长度截断，唯一边界是整 body 超 512 KiB 时跳过转发。\"Always allow\" 无宿主持久化 API，用插件内 per-session 内存规则（随常驻 service 生命周期，气泡对 v2 使用单独文案说明关闭/重开终端不会撤销）。插件跑在常驻共享 service（daemon）：`source_pid`/进程树不可信故**整组省略**（终端跳转对 v2 降级），安装/更新后需 `opencode service restart`。`ctx.permission.hook()` 按上游 v2.0.15 类型返回 `Promise<Registration>`：本实例 dispose（setup 返回的 cleanup，宿主也会在插件 scope 关闭时调用）会调用 `registration.dispose()`，注册 Promise reject 只记日志不影响事件订阅。事件订阅**不等待** hook 注册（注册挂起/reject 时状态上报照常），reload **不等待**上一代注销完成；本实例清理先同步完成本地清理（标记 disposed、abort 订阅、身份恢复）再去注销 registration，注册 dispose 有约 2s 上限、超时只记日志，注册未完成就被取代则在注册完成那一刻立即注销，不残留活 hook。上游 v2.0.15 的 trigger 对同名 hook 依次调用每个仍注册的回调、共用同一个可变 event，而我们的注销是异步的，所以 reload 窗口内旧回调可能仍被调用：已退役实例的回调入口检查 `instance.disposed` 后直接返回，不 POST、不改 event。每个 ask 各自转发（`source.id` 是工具调用级、不是 ask 级，同一工具调用会发出多个不同 ask，如 external_directory + edit），不做内容去重。config 顶层重复 `plugins` 键按歧义处理：Doctor 报 `config-corrupt` 不抛异常，register/卸载在首次写入前中止（v1 宿主 sweep 只告警并跳过），v1 `plugin` 键行为不变。v1 1.18.31 tuple 契约、generation 布局、owner/lock 语义不变；`inspectGeneration` 把历史 4 文件集接受为合法 owned-stale 形态以便迁移。真机证据与降级项见 `docs/investigations/opencode-v2-e1-evidence.md`\n- OpenCode 的 plugin 注册不再直接指向打包/源码目录：`agents/opencode-family.js` 的 `managedMaterialization:true`（OpenCode true / MiMo 本次 false）gate materialize、ownership classifier、managed Doctor 与 generation cleanup。开启后 register 必须在目标 home 下维护 `<home>/.clawd/integrations/opencode-family/opencode/homes/<configDirHash>/generations/<bundleHash>/` 的内容寻址 generation（OpenCode v2 当前五文件，历史 v1 四文件），同一 generation 可同时物化 v1/v2 入口文件，但不因此在配置中注册两个键；探测到 v2 宿主时只把 `opencode-plugin-v2` 入口写入 `plugins`，并将 `plugin` 键仅用于清理 Clawd 自有旧条目；v1 宿主和探测不到版本时保持原有 v1 注册路径；bundle allowlist 固定为 `<agent>-plugin/index.mjs` / `<agent>-plugin/package.json` / `opencode-family-plugin/core.mjs` / `opencode-family-plugin/session-ids.mjs` / `opencode-plugin-v2/index.mjs`（v2）。owner record（`owner.json`，literal `clawd-on-desk.opencode-family.target`）与 target-scoped `mutation.lock/`（独立 literal `clawd-on-desk.opencode-family.target.lock`）是所有权与 app-present 真相；lock 被持有时不并发写：interactive Install/Repair/CLI/Uninstall/About cleanup 只做一次短而有界、可注入 delay 的重试，startup automatic 不等待直接 skipped；合法且超时 2 倍以上、PID 明确 ESRCH 才允许 atomic quarantine 接管，corrupt/foreign/live/EPERM 一律不接管；release 只删自己 token 的 `lock.json` 与随后为空的精确目录，禁止 recursive cleanup。owner 的 `activeSourceMarker` 必须是 `<activeSourceRoot>/<pluginDirName>/index.mjs`（共享 canonical 身份、Windows 折叠大小写）且为 regular file，目录/dangling/错 plugin 目录/root 不匹配都不算 live。同一 target 的 source owner 冲突（marker 仍存在）一律 `owner-conflict`，不得来回改 config；旧 owner 的源码 marker 已不存在时，新 source 必须在锁内重读并原子接管 owner（config 已 current 也不例外），否则残留死 owner 会让托管 plugin 永久 inert。锁内若 config 与当前 source owner 都已被并发操作收敛，则本次零 mutation 返回 skipped。lock release 失败不得掩盖结果：成功保留 status 并附 warning + 精确 lock path 的 residualPaths，已有 primary error 时保留原错误。basename 本身永不构成所有权；copy 到 managed layout 外的完整 generation 因缺少对应 owner record 而 inert，只有 verified-current-copy 可 Repair。tuple 契约固定为 OpenCode 1.18.31 实测的 `[specifier, optionsObject]`（隔离 `opencode debug config` 证据：第二项必须是普通对象，数组/字符串第二项会被宿主拒绝）；重写只替换 `plugin[index][0]`，options 值级保留，绝不写回嵌套 tuple，malformed array 原样保留。`options.pluginDir` 仍是 test-only expected-canonical override（跳过 generation/manifest/boundary，但不跳过 ownership/唯一 entry/read-back），`resolvePluginDir()` 仍返回 source。新建文件按当前用户普通写权限落盘：不得加 readonly/deny-write ACL，不得用 `W_OK`/`r+`/INIT 日志/session 活跃做健康门禁。Uninstall 以“活动注册是否移除”为提交依据（`registrationRemoved` false/null 阻止 Settings 提交，undefined 沿用 legacy status），残留 generation 只产生 warning；清理有效 generation 时必须先在同一 `generations/` 内原子改名为非 canonical `.cleanup-*` 再递归删除，删除失败不得占住原 hash 槽。兼容旧版本留下的半残 canonical 目录时，只允许在 owner 已 released、bounded history 精确证明该 canonical entry、且配置无活动 Clawd entry 的条件下，把它原子隔离为 `.recovery-*` 后重新物化；active/foreign/unproven/canonical-in-use 一律继续 fail closed，绝不原地覆盖或修补可疑 bytes。托管 core 的 orphan inert gate（`evaluateManagedLayoutGate`）必须在 `resetDebugLog()` / PID walk / bridge / handler 注册之前，owner marker 缺失、损坏、agentId 不匹配或 `activeSourceMarker` 不存在时返回空 handler；source-direct 模式保持原行为。MiMo 保持 broad-basename register/unregister/Doctor 契约不变。\n- Pi 通过 `~/.pi/agent/extensions/clawd-on-desk` 的 global extension 推送状态；Clawd 对 Pi 是 **state-only**，不接管权限、不弹权限气泡，也不把 Pi 的默认 YOLO 流程改成手动确认\n- OMP (oh-my-pi) 通过 `~/.omp/agent/extensions/clawd-on-desk` 的 global extension 推送状态，agent id `omp`，对 Clawd 同样是 **state-only**。它是 Pi 的 fork（包名 `@oh-my-pi/pi-coding-agent`），所以 `hooks/omp-extension.ts` 刻意与 `hooks/pi-extension.ts` 保持逐行对齐（只差 package import、core import 与函数名），进程树遍历与终端识别不得各自漂移；OMP 独有的差异全部收在 `hooks/omp-extension-core.js`。**完成必须走 `session_stop` 候选 + 终态 `agent_end` 提交的两阶段协议** —— `session_stop` 先保留主会话边界，OMP 再汇总所有 extension 的续跑请求；只有后续 `agent_end.willContinue !== true` 才向 Clawd 发完成。不得直接把任一事件单独映射为完成：仅用 `agent_end` 会把 subagent/调度边界误报为完成，仅用 `session_stop` 则会早于 extension 续跑判定。`session_switch` / `session_branch` 要为被切走的旧 session 补发一条合成 `SessionEnd`，否则 Clawd 会留下一条再也不会有人上报的活动行。session id 命名空间是 `omp:<raw>`，且必须始终带 `session_title`（多个交互式会话合法地共用同一个 cwd，缺标题会让列表和跳转目标无法区分）。安装器遇到社区桥接 `~/.omp/agent/extensions/clawd-on-desk-omp.ts` 时必须 fail closed 跳过：两者上报同一批事件，同时存在会双发。当前 `assets/source/agent-icons/omp.png` 是 `fallback: true` 的占位 π 字形，不是 OMP 官方品牌素材，拿到授权素材后应替换\n- DeepSeek Harness 首发是 **web profile / Windows-first experimental / plugin-only**；rc.6 已于 2026-08-29 完成 macOS / Windows x64 源码运行的真实 API-backed session/approval smoke（#962）；rc.2 Windows packaged-app 证据仅覆盖安装、web boot 与直接 bridge client 的 state/Allow/Deny 往返（#938），不得合并宣称 rc.2 安装包的真实 API 会话已验证。Clawd-managed in-process plugin 监听公开 `session/created`、`session/event`、`session/disposed`、可选 `sessionProjections.onChanged` 与 blocking `approval/request`；标题和上下文仅作为会话元数据同步，不占用生命周期 seq。状态按 session FIFO 上报并携带上游 seq；Clawd 不读取 `$DSH_HOME/storages` projection。普通审批进入独立 DSH `/permission` adapter，只支持人工 Allow Once / Deny；204 / 断连 / DND / disabled 都由 plugin `next()` 交还 DSH 原生 web answerer。`ask_user_question` 始终留在 DSH 原生 provider；DSH 不进入 `KNOWN_PERMISSION_AGENTS`，auto-tools / unattended / per-session grant 全部 DEFER。安装器通过官方 `dsh plugin --profile web add/remove` 管理 immutable marker-owned generation，foreign 同名包 fail closed；版本放行改成按 **小版本族（major.minor）**。维护两张表：一张是唯一写出具体版本/npm artifact/integrity 的已验证 artifact 清单（优先 `@deepseek-ai/dsh@0.2.0-rc.2`（integrity `sha512-EAJ3gPNcVt/uv8X19PMm9NkVhWgT7xXNMk0UKCVm+IQ5rpSQOcsMUa0HWlnYYVybKMsccjcRB21vVVsaXQ6IdA==`，2026-10-04 已做静态接口核对，并在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证了用 Clawd 安装器装出的 generation 的启动同步换代、会话状态、HUD 标题/上下文、Allow/Deny 与消息上的失败标记；其 `tool/result` 把失败标记放在消息 `message.isError` 而不是内容项上，bridge 新旧两种位置都认），并保留 `@deepseek-ai/dsh@0.1.5-rc.3`（integrity `sha512-c0W6Xqc4ChjFcCJkbzPeIxZQdnbKqe+QAcJzWGtogg0ZzsnZRcw3vopMyZ5oZU6E2fmyqGcyDR1sBeiCH4yHcg==`，2026-09-27 已在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证启动同步安装、会话状态、HUD 标题/上下文与 Allow/Deny）、`@deepseek-ai/dsh@0.1.5-rc.1`（integrity `sha512-rmNmzQCg3oIc1z8xH7izRSOuy1TNzq+/NILyfM+7e8DKOyV+yBtg47WEsqR2SiIe1ATec3L/rUa1YhIcfQ2XEg==`）、`@deepseek-ai/dsh@0.1.1-rc.2`（integrity `sha512-UP1UIh6q3Gme/yXRn/QL2P8IsVlv8Shpg22TRJIZPsCRWLm4CBiA1MUvXmJAfsOEETBMLAl+xWPtFw6ICsN3wg==`）与 `@deepseek-ai/dsh@0.1.0-rc.6`（integrity `sha512-brpZfED7ieRa2PQ5tUxMhHrM1pb2CmKFVM/f6yMULBDMicahk+Z2OsHgTwTDnoiZm23Ftu9rQz0NN4pflaoJcg==`）），一张是族表（`0.2` 下限 `0.2.0-rc.2`、`0.1` 下限 `0.1.0-rc.6`）。host 版本经严格解析（拒绝前导零、空预发布标识与 build 元数据）通过、major.minor 命中族、且不低于该族下限即放行；同一族内不同 host 版本共用一个 generation，出现新的小版本必须重新验证并新增一个族。旧的精确 `=<version>` marker 仍按原 range 核对哈希，新 generation 一律写族 range；Install/Repair 按 host 版本所在的族选择目标契约，Uninstall / 手动 npx 命令在 marker 版本已列入清单时钉它自己的 artifact，否则钉同族版本最高的已验证 artifact（无 CLI 且无 marker 时用首选族最新的并记为 assumed）；加锁前后比较的是实际检测到的 host 版本，不看族。DSH 的 `metadata_only` 标题/上下文旁路必须核对目标会话的 `agentId` 确为 `deepseek-harness`，撞名的其他 agent 会话直接丢弃。`47f9438` 仅是源码调查基线，不代表任何 tag/commit 映射。\n- DSH 每个 canonical `DSH_HOME` 的 mutation lock 只有在 owner/schema/token/PID/timestamp/owner-recorded operation timeout 合法、超过该 owner timeout 两倍、且 OS PID probe 明确为 `ESRCH` 时才允许 atomic-rename takeover；live、`EPERM`、unknown、corrupt/foreign owner 一律拒绝并返回精确 lock path。canonical lock 的 owner write/release 禁止 recursive cleanup。无全局 CLI 时生成的手动 npx generation 必须先在同一锁内写 owned reference，手动 add/remove 命令必须显式 pin shell-quoted canonical `DSH_HOME`；malformed/foreign/concurrently replaced reference 一律 fail closed 并保留 generation\n- DSH 桌面版支持（#1119）与 web 共用一个 agent id `deepseek-harness`：web profile 和 DeepSeek Harness 桌面版是两个承载方、各自一个 profile（桌面版是 `$DSH_HOME/profiles/desktop`），但在 Settings 和 Doctor 里仍是**一行**，显示名 `DeepSeek Harness (experimental)`，一次排队操作先 web 后 desktop、一边失败不影响另一边；安装只要有一边核实健康即成功（另一边失败变 warning + 常驻提示），卸载要所有 Clawd 注册都没了才成功。桌面版查找：macOS 用 `/Applications` 或 `~/Applications/DeepSeek Harness.app` 里自带的 `Contents/Resources/runtime/cli/bin/dsh`；Windows 按用户安装，从 `HKCU` 卸载项（显示名以 `DeepSeek Harness ` 开头）与 `%LOCALAPPDATA%\\Programs\\DeepSeek Harness` 找 `resources\\runtime\\cli\\bin\\dsh.cmd`，注册表用 PowerShell 读 UTF-8 JSON、不用 `reg.exe`；Linux 不支持桌面版。静态版本来自 `Info.plist` / 卸载项 `DisplayVersion`，真正动手前跑一次启动器 `--version` 核实。桌面版**永不用 npx**，手动 npx 命令与 manual reference 只属 web。每边角色是 `mutable` / `diagnose` / `not-applicable`：桌面版没装、或 profile 从未初始化（桌面版没打开过）→ 不适用并提示打开一次；foreign 同名包、文件读不了、清理残留、注册查不清、版本不支持、装了不止一个桌面版（`multiple-desktop-installs`）、桌面版找不到但注册还在（`carrier-unavailable`）、桌面版查不清（`desktop-unverifiable`）→ 只报告不动手。启动同步在集成已安装且启用时会把插件加进已初始化的桌面版 profile；桌面版开着也会加载新加的插件，只有插件更新（换了 generation）后要重启。常驻提示在 `hooks/dsh-notices.js`，按 profile 存 `notices-web.json`/`notices-desktop.json`，四种 kind（`restart-required`/`first-install`/`manual-command`/`failed-target`），写不进去只算 warning；提示显示在 Settings → AI Coding Tools 里这一行下面。Doctor 一行详情 `web: …; desktop: …`，状态取适用边里最差，只要有一边能尝试修复且不健康就给修复按钮（`src/doctor-detectors/agent-integrations.js`）。插件在 DSH 里被关掉（依赖在、bundle 行没了）时 `plugin add` 不会重开：显式修复先 remove 再 add（add 前先清掉上游 remove 留下的自有链接，Mac 是符号链接、Windows 是 junction），按 profile 记 `repair-operation-<profile>.json`，中断后下次显式修复续做，启动同步只报 `plugin-disabled-in-dsh`。`generations/` 两边共享，任一边有未处理状态（检查记录、清理残留、坏修复记录或 manual reference、读不了的 profile、符号链接 profile 目录）时清理暂停但不挡安装，卸载残留进 warnings。检查记录按 profile：web `inspection-required.json`、桌面版 `inspection-required-desktop.json`。`plugin add/remove` 写命令两边都超时 300 秒（web 原 120 秒），比上游写锁等待长。上游 `dsh plugin remove` 只清 `link:` 清单和锁、`node_modules` 链接会留下，Clawd 卸载自有插件时确认归属后清掉。Windows 静态查找是同步代码、不起进程，只读异步快照：启动时（不管 DSH 是否启用）、打开 Doctor 前、Agents 页手动扫描时刷新，没快照时桌面版显示\"查不清\"。安装检测把\"找到桌面版\"也算装了 DSH（`src/agent-installation-detector.js`）。桥接插件在 apply 时读 `ctx.profileContext?.name`，只有 desktop profile 才在 state / 审批载荷里带 `dsh_carrier: \"desktop\"`（metadata 不带；web 或未知 profile 一律不带）；Clawd 只接受 DSH + `dsh-plugin` + 本机 + 非 WSL 的载体，按生命周期覆盖或清除、不粘滞，权限 fallback entry 与快照（含签名）都带上它。点击桌面版会话时 `getSessionFocusTarget` 在 darwin/win32 返回 `dsh-desktop`（`dsh://open`），分派先 `shell.openExternal(\"dsh://open\")`，被拒绝再按 `discoverDshDesktopSync({ requireUniqueApp: true })` 的兜底要求唯一安装启动界面程序（macOS `open <appRoot>`、Windows 启动 `<appRoot>\\DeepSeek Harness.exe`，去掉 `ELECTRON_*`/`NODE_OPTIONS`，不用 CLI 启动方式；两份真实路径不同的有效安装视为有歧义，只要还有核实不了的候选也不自动启动，同一份安装的符号链接只算一份）；只能打开应用窗口、不会切到具体对话，web 会话仍不可跳；桌面版启动时会重新打开上次的对话，Clawd 只在这个对话有了动作（提问、工具调用、审批）之后才把它放进 Session HUD（`awaitingActivity` 并入快照 `hiddenFromHud`，但不关跳转；与 Kimi Code 共用同一个标记），Dashboard 照常列出、按钮照常可跳；2026-10-05 macOS 26.6.2 与 Windows 11 x64 源码运行真机验证（桌面版 `0.2.0-rc.2`）：别的窗口在前、最小化、关窗后，点击都经 `dsh://open` 把窗口带到最前；协议打不开时的启动兜底只有单元测试。真机证据：2026-10-04 macOS 源码运行（Clawd `ac64d726`，桌面版 `0.2.0-rc.2` + 全局 `@deepseek-ai/dsh@0.2.0-rc.2`）验证了启动同步把插件装进桌面版（与 web 共用 generation）并出现\"已装进桌面版\"提示、Doctor 一行两边正常，桌面版真实会话的 Allow 建成文件、Deny 后文件内容和 mtime 不变且 Clawd 显示 `PostToolUseFailure`，\"知道了\"后提示消失，改 bridge 源码（同 Clawd 版本）后启动同步两边报 `generation-conflict` 并提示去 Doctor 修复、修复把两边换到新 generation/删旧/出现\"重启桌面版后生效\"、重启后事件来自新宿主进程，设置页卸载后两边依赖与 bundle 行都没了、上游残留链接被清、generation 删除、两边提示清空，再在设置页安装两边都重新装上、桌面版重新出现\"已装进桌面版\"（\"经设置页首次安装\"因此已覆盖），开着 DND 时桌面版的工作区外写文件不弹 Clawd 气泡、返回 no-decision、桌面版弹自己的原生审批框、批准后文件建成且事件照常到达。2026-10-04 Windows 11 x64 经 SSH 用 Node 直跑安装器代码（管理员会话，桌面版在 `%LOCALAPPDATA%` 按用户安装 `0.2.0-rc.2`、全局 dsh `0.1.0-rc.6`，web 在 0.1 族、桌面版在 0.2 族）：PowerShell 读注册表找到桌面版、静态模式无快照时报\"查不清\"且不起进程、自带 `dsh.cmd`（带空格路径）`--version` 返回 `0.2.0-rc.2`、`dsh.cmd plugin --profile desktop add` 经 pnpm junction 装入并核实、记录\"已装进桌面版\"、两族各用一份 generation 并存、Doctor 一行两边有修复按钮、卸载桌面版清依赖与 bundle 行并清掉 `dsh plugin remove` 残留 junction、只删桌面版那份 generation 而保留 web 在用的；2026-10-04 另在 Windows 上以真 Clawd（Electron，源码运行、用户会话、普通权限）验证：先抓到一个只在 Electron 里出现的 bug（Electron 的 fs 把 `app.asar` 当目录、Windows 安装目录核实要求它是文件，于是在真 Clawd 里桌面版被判成没装，已在 `d8190692` 修成\"存在即可\"）；修好后桌面版一直开着（宿主进程未重启），启动同步把插件装进桌面版并记\"已装进桌面版\"，在桌面版新开对话的事件来自那个未重启的宿主进程，**Windows 上桌面版开着也会加载新加的插件**。**未覆盖**：Windows 上桌面版的审批、Windows 上的 Electron 界面（设置页提示、Doctor 窗口、启动预热）、打包后的 app、Linux、HTTP 204 交还与取消、装了多个桌面版。**管理员 junction 观察（推断）**：提升过的管理员进程在 Windows 11 上穿不过非管理员进程建的 junction（PowerShell \"untrusted mount point\"、Node `UNKNOWN`），该会话里 web 的旧 junction 读不到、web add 失败，桌面版同会话新建的 junction 正常；普通权限运行不受影响；由此推断以管理员身份运行 Clawd 可能把普通权限装好的插件读成缺失，未用以管理员身份运行的 Clawd 直接复现\n- OpenClaw 通过 `~/.openclaw/openclaw.json` plugin 路径做 state-only 集成；Phase 1 不做 permission bubble / terminal focus，主要支持本地 `openclaw tui --local`\n- Antigravity CLI (agy) 通过 `~/.gemini/config/hooks.json` 做 **state-only** hook 集成（PreInvocation / PostToolUse / PostInvocation / Stop），**不注册 PreToolUse**。agy LLM 会主动调内置 `ask_permission` 工具，触发 agy 自己的 5 选项 native menu（含 \"Persist to settings.json\" 持久白名单），Clawd 不插手权限决策也不双层确认。`agents/antigravity-cli.js` `capabilities.permissionApproval` / `interactiveBubble` 均为 false。\n- Qwen Code 通过 `~/.qwen/settings.json` 做 hook-only 集成（SessionStart / SessionEnd / UserPromptSubmit / PreToolUse / PostToolUse / Stop / Notification / PermissionRequest），支持状态与阻塞式 `PermissionRequest` 权限气泡；`disableAllHooks: true` 时注册条目不会触发。\n- QwenWork (千问办公) 通过 `~/.QwenWorkCN/settings.json` 做 **hook-only / state-only** 集成（agent id `qwenwork`；SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / Notification / PermissionRequest / PermissionDenied / SessionEnd）。`PermissionRequest` / `PermissionDenied` 只作为观察映射成 `working`（每任务 40+ 次，映射成 notification 会刷屏），hook stdout 恒为 `{}`：Clawd 不产生 allow/deny，不注册 `/permission`，也不进入 permission automation eligibility，唯一决策者是 QwenWork 原生权限流程；`agents/qwenwork.js` 的 `capabilities.permissionApproval` / `interactiveBubble` 均为 false。Windows command 必须保持 `windowsWrapper:\"portable\"`（QwenWork 经 POSIX shell 执行 command hook），PowerShell `-EncodedCommand` **只**用于识别并原地迁移旧条目，不是当前写入形态。marker 只认 `qwenwork-hook.js`，不得仅凭 `name:\"clawd\"` 删除用户 hook；混合 entry 中第三方 hook 原样保留。session id 命名空间是 `qwenwork:<raw>`；`~/.QwenWorkCN/workspace/<id>` 这类内部工作区 cwd 不做 basename 回退，避免 HUD/Dashboard 显示内部 ID。当前真实支持平台只有 macOS / Windows 桌面端（官方下载页 https://qwenwork.cn/download 只提供 macOS 14+ / Windows 10+ / HarmonyOS 6.1+，没有 Linux 客户端），因此 `processNames.linux`、resolver linux agent name 均为空，也不进 `src/wsl-deploy.js` 的 WSL Pair 映射。桌面主进程长驻、不代表 active turn，`startupRecoveryProcessNames` 全空、无 startup recovery。安装/卸载走 Settings → AI Coding Tools，或 `npm run install:qwenwork-hooks` / `npm run uninstall:qwenwork-hooks`；卸载必须同时在 `hooks/cleanup-integrations.js` 的 `MANAGED_AGENT_IDS` / `AGENT_CLEANERS` / `byAgent` 里有条目，否则 About cleanup 只会改 prefs、hook 留在磁盘上\n- ZCode 通过 `~/.zcode/cli/config.json` 的 `hooks.events.*` 集成全部 7 个支持事件（SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / PermissionRequest，无 SessionEnd / Notification）。PermissionRequest 为阻塞式权限审批：hook 长连接 `POST /permission`（HTTP 等待 590s，installer 注册 `timeoutMs: 600000`），有决定时 stdout 返回最小合法 `{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}`（deny 可带 `message`），无决定 / 超时 / 断连 / 任何错误输出 `{}` 并 exit 0，ZCode 回退原生权限流程；`interrupt` / `updatedInput` / `updatedPermissions` / `permissionUpdates` 必须 omit（最小输出 union 按 ZCode 3.5.x 严格 schema 约束；macOS ZCode 3.8.1 已完成真实 hook / 气泡 Allow/Deny 往返，3.5.x PermissionRequest 真机往返未覆盖）。超时单位陷阱：ZCode `timeout` 是秒、`timeoutMs` 才是毫秒，且超时按事件区分（PermissionRequest 600000、state 事件 8000）。Phase 2 只允许人工审批：ZCode 不进入 `KNOWN_PERMISSION_AGENTS`，global / per-session permission automation 在工具面与会话身份审计完成前全部 defer。prefs v14→v15 迁移把 Phase 1 持久化的 `zcode.permissionsEnabled:false` 翻 true（当时开关从未渲染、无用户意图）。配置必须有 `hooks.enabled=true` 才会执行；安装器只在该字段缺失时补 true，显式 `hooks.enabled=false` 或 Clawd 单项 hook 的 `enabled=false` 必须保留，Doctor warning 且不提供会覆盖用户选择的 Fix。ZCode 导入 Claude 配置后，只清理 `.zcode` 中明确引用 `clawd-hook.js` 的 Clawd-owned 条目，绝不改 `~/.claude/settings.json`。安全边界（复核后新增）：`/state` 生命周期 sweep 对 zcode（及 qwen/DSH 等 native-fallback adapter）只允许 no-decision，绝不伪 deny；hook 侧 `tool_input` 预算内原样发送、任何截断（长 Bash 尾部 `rm -rf` 场景）或序列化超 512KiB 一律 fail-closed 输出 `{}` 交还原生 UI；无 allow/answer/plan capability 的 interaction（如 ZCode 真实的 ExitPlanMode / AskUserQuestion）本地气泡与远程卡片都不提供决定入口、直接 204；全局气泡关闭只关本地窗口，Telegram/飞书 remote-only 审批仍可用（per-agent gate 关闭才是全退出）；installer 遇到 foreign `PermissionRequest` hook 时不注册自己的 blocking hook，若 foreign hook 后出现则移除自己的 managed hook（ZCode 同事件 hook 串行执行、后写覆盖，Clawd allow 会盖掉用户 hook 的 deny），Doctor 报 `permission-conflict` 且不给 Fix；六个 Phase 1 managed hook 全部显式 disabled 时新 PermissionRequest 继承 `enabled:false`；服务端 pre-parse 超限一律断连回退，不伪造 deny\n- Qoder / Qoder CN 共用 `qoder` agent，通过 `~/.qoder/settings.json` / `~/.qoder-cn/settings.json` 做 **state-only** hook 集成；各自尊重 `QODER_CONFIG_DIR` / `QODERCN_CONFIG_DIR`，同步所有已初始化目录，不创建缺失版本目录，卸载/cleanup 覆盖两版且只移除 Clawd entries，Doctor 不得让健康的一版掩盖另一版故障。Clawd 只把 `PermissionRequest` / `PermissionDenied` 当 notification 观察，**不替 Qoder 做权限决策**，hook stdout 恒为 `{}`；Windows command 必须保持 `windowsWrapper:\"portable\"`。session id 命名空间是 `qoder:<raw>`；启动恢复只认 CLI `qodercli` / `qoder-cli` / `qoderclicn`，不认闲置 IDE / CN 桌面进程；本机原生会话标题由 `src/qoder-session-title.js` 低频异步增量读取，通过 `updateSessionMetadata` 更新；SessionEnd / 禁用 / 退出取消旧读取，远端与 WSL 路径不在本机读取。2026-10-18 已核对 Windows CN runtime 1.1.69 的真实 SessionStart / UserPromptSubmit / Stop hooks，用户确认开启 Clawd Qoder 接入后任务状态恢复；macOS/Linux CN 未实测\n- TraeCode (Trae CN) 通过 `~/.trae-cn/hooks.json` 做 **hook-only / state-only** 集成。Windows command 必须保持 `windowsWrapper:\"encoded\"`：Trae 的 Windows Sandbox 会把 hook 命令作为 `trae-sandbox.exe --command-line` 的单个原生参数再次转发，普通引号或 `portable` 形态会在含空格路径处拆分；外层必须保持无引号的 PowerShell `-EncodedCommand`，POSIX 则继续使用普通 quoted command。该约束不适用于经 POSIX shell 执行 Windows hook 的 agent（如 Qoder / QwenWork）。\n- MiniMax Code 通过 `<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/` 的 **Clawd 独占本地插件**做 **state-only** 集成（manifest 用 `.claude-plugin/plugin.json`，hooks 文档按 MiniMax 的 CLAUDE sourceFormat 解析；不用 `.minimax-plugin/`，那会走 MINIMAX 格式：matcher 必须非空且不支持 exec-form args）。handler 固定 exec-form `command=node 路径 + args=[minimax-hook.js]`（spawn 直执行、无 shell、免引号），`timeout` 单位是秒且只接受 1–10 的整数（越界的 handler 被丢弃而不是钳制；SessionEnd 事件总预算仅 3s），因此 **PermissionRequest 物理上不可阻塞审批、完全不注册**，也没有 Notification 事件；hook stdout 恒为 `{}`（permissionDecision 缺省 abstain）。目录级所有权只认结构化凭据 `.clawd-managed.json`（`{app:\"clawd-on-desk\",integration:\"minimax\",managed:true,version:1}`，同 Pi 约定；MiniMax 只读 manifest 声明的文件，会忽略它），且凭据与所有受管理路径（`.claude-plugin/`、`hooks/` 及其文件）都不得是符号链接；目录名、manifest name、文档里的 basename/子串乃至整份文档指纹都永不授权改写或递归删除，缺凭据的目录（包括补丁前预发布构建写出的）一律 fail closed，只能手动删除后重装。staging / removal 目录固定落在数据目录（`plugins/` 之外，MiniMax 会把 `plugins/` 下每个目录项都当插件候选，含点号名）：首装在 staging 写全三份文件后一次 rename 发布（只覆盖空目标，非空目录/文件/链接拒绝；空 `clawd-state/` 视为未占用），失败时尽力删除 staging；已拥有的目录原地逐文件更新，中断后仍可证明归属、由下次安装补完。只有 ENOENT/ENOTDIR 算不存在，其他 lstat 错误按无法确认处理，绝不据此宣告卸载。卸载先把已验证目录 rename 出 `plugins/`、复验后再删；移走失败报 error 并保留安装意图，移走成功但删除失败时按已移除提交并在 warnings 里给出残留 `.clawd-minimax-removing-*` 路径，复验失败且移回失败时两个位置都报 `registrationRemoved:null` 并带 `residualPaths`；删不掉且目录仍运行 Clawd hook 时返回 `registrationRemoved:false`（读不清为 `null`），Settings / About 据此保留安装意图。删除后返回前还会复查一次原位置：此时若已有另一个 Clawd 实例重新发布的插件，报“仍在注册”（`registrationRemoved:false`）、不宣称卸载；这次复查是快照，复查之后、Settings 提交之前的安装不在本次结果里（多实例强一致需要覆盖 prefs 提交的跨进程锁，未做）。Settings 界面目前不显示成功结果里的 `warnings` / `residualPaths`：Agents 页安装/卸载只弹“已卸载/已安装”，About 清理只显示计数，只有命令行 cleanup 脚本会打印 warning。进程中途崩溃，或 staging 清理本身失败，可能在数据目录留下 `.clawd-minimax-staging-*` / `.clawd-minimax-removing-*`（MiniMax 不会加载，只能手动删除）；`plugins/` 与数据目录跨文件系统（EXDEV）时不支持。判断外来目录是否仍跑 Clawd hook 按 manifest 声明的 hooks 文档和 MiniMax 默认规则检查（含裸文档外壳、反斜杠路径，以及 shell 形式的 command / commandWindows handler）；Clawd 不建模的 manifest（根 `plugin.json` / `.minimax-plugin/` / `.codex-plugin/`）或读不清时按无法确认处理。node 探测失败时只保留全部 Clawd handler 一致、basename 为 node、存在且可执行、并通过 `node --version` 有界探测的已记录路径（exec-form 无 shell，Dock 启动的桌面 App 的 PATH 里没有 node），安装器与 Doctor 共用 `resolveDesiredNodeBin`。PostCompact 按 #406 上报 thinking（`trigger:\"manual\"` 时 idle），不是 attention。hook 的 `agentNames` 必须全小写（resolver 比较的是小写 basename），且不含桌面版的 “MiniMax Code Helper”：拉起 hook 的 NodeService helper 可能在 App 运行中重启，把它当 agent 会误删活会话，识别应落到长驻的主程序；mcode CLI 启动时执行 `process.title = \"minimax-code\"`，macOS/Linux 上 `ps` 报告的进程名就是 `minimax-code`（按名字匹配），Windows 上仍是 node.exe，靠 `agentCmdlineCheck` 只看 argv 里的脚本位置识别（命令行检查的进程名沿用共享默认 `DEFAULT_AGENT_CMDLINE_NAMES`，已含 Linux 上新版 Node 的主线程名 `mainthread` / `node-mainthread`，MiniMax 不再自带名单）（`node` 后的脚本 basename 是 `mcode`/`minimax-code` 启动器，或脚本路径含 `/@minimax-ai/code/` / `/.minimax-code/`），参数里的目录片段不算——MiniMax 退出时不发 SessionEnd，没有 agent pid 会话就无法按 agent-exit 清理。hook 不触发时的启用步骤在 MiniMax 应用内（`mcode plugin enable clawd-state@local` 或插件面板），磁盘上读不到启用状态，Doctor/Settings 只能提示。session id 命名空间 `minimax:<raw>`，标题走首行 prompt 派生 + 服务端 first-wins（同 traecode）。\n- Kimi Code（agent id `kimi-cli`）的 agent pid 靠进程名识别：CLI 启动即 `process.title = \"kimi-code\"`，libuv 把标题写回原 argv 所占的空间、放不下就截断，所以 macOS/Linux 上 `ps` 与 `pgrep -x` 看到的名字随启动命令长短而变（0.42.0 原生版实测：`kimi` 仍是 `kimi`，`kimi -c` 是 `kimi-co`，`kimi --yolo` 或全路径启动是 `kimi-code`；只有整条启动命令比 `kimi` 还短时（例如不带参数的软链接 `k`）才认不出，`k -c` 显示的已经是 `kimi`）。`hooks/kimi-process-names.js` 必须列全从 `kimi` 到 `kimi-code` 的每一种截断，resolver 与 startup recovery 共用这一组，只写 `kimi-code` 会漏掉 `kimi -c`。拉起 hook 的就是这个改名后的主进程（TUI 在进程内跑 agent 引擎，从 SessionStart 到 SessionEnd 同一个 PID）；其他同名进程（后台更新下载器、经 kimi 二进制跑的插件进程等）都是它的子进程，不跑 hook。resolver 比较小写 basename，macOS 桌面版 `Kimi Code.app` 写成 `kimi code`（它的 agent server 跑在主进程里，hook 由主进程直接拉起）；桌面版关窗后常驻托盘、不代表在干活，同其他桌面 App 一样不进 startup recovery。Windows 上标题只改控制台标题：原生版仍是 `kimi.exe`，npm 版仍是 `node.exe`，命令行检查只认包目录 `/@moonshot-ai/kimi-code/`，不能退回“含 kimi 就算”（Kimi 本身没被认出时，任何命令行提到 kimi 的 node 祖先都会被当成 agent）。Kimi Code 正常 `/exit` 会发 SessionEnd，但关终端、`kill`（0.42.0 实测：SIGTERM 与 SIGKILL 都不发；源码里 SIGTERM 注册了 `stop(143)`，实测为什么没发 SessionEnd 还没查清）、崩溃都不发；没有 agent pid 的会话只要终端 App 还开着就一直留在列表里。桌面端启动时会恢复上次查看的对话、在侧栏点开旧对话也一样，这类只发一条 SessionStart、还没有任何动作的对话不进 Session HUD，Dashboard 照常列出、按钮照常可跳，出现提问/工具/审批/Stop 等动作后自动进 HUD（与 DSH 共用同一个 `awaitingActivity` 标记）。\n- HTTP 服务端口范围固定为 `127.0.0.1:23333-23337`；运行时端口写入 `~/.clawd/runtime.json`\n- Mobile Preview 是独立的 LAN listener，候选范围为 `0.0.0.0:23334-23338`；它不写 `runtime.json`，不得把该范围误写成 hook / custom-agent HTTP ingress 范围\n- 自定义 HTTP Agent 的 sender 必须读取 `~/.clawd/runtime.json`，不能把 23333 写死；注册不等于已连接。custom v1 只支持 `/state`，不支持 `/permission`\n- CodeBuddy PermissionRequest hook 的所有权只认本机 managed URL 或 marker `clawd-on-desk.permission.v1`；纯 `name:\"clawd\"` 不能触发改写/删除。裸 CLI 和 WSL 默认 preserve，Settings/startup/repair 必须显式传 local/custom permission target\n- Remote SSH 的远端 Node 探测要求 Node >= 14；Node discovery/version validation 只在 `src/remote-ssh-node.js`，ordinary tunnel health 与 serialized readiness 在 `src/remote-ssh-runtime.js`，不得互相复制或从已停用脚本另起实现\n- 注册 Claude Code hook 必须 marker-scoped merge：只可更新/删除含 `clawd-hook.js` / `auto-start.js` marker 的 Clawd-owned entry，不得整体覆盖数组或改动无 marker 的用户 entry\n- 注册 Claude Code statusLine 默认只接管空槽或自己的槽（marker `claude-statusline.js`）；本机 Settings 显式开启采集遇到第三方槽时，必须经共存确认并复核原槽指纹，使用 `--local-chain` 和独立的 `clawd-statusline-local-chain.json` 保存/恢复完整原对象。启动/自动修复不得自行取得第三方槽；恢复记录缺失、损坏或不匹配时 fail closed 并保留现场。远程部署仍用 profile 的 `chainStatusline` opt-in 和既有 `--chain` sidecar，不与本机记录混用。订阅配额通过 `metadata_only` POST 进入 session-independent `updateAccountQuota` per-source store；不要把 quota 塞进 `updateSession` opts，也不要以 session 存活作为摄入前提\n- Copilot CLI hooks 走按需自动同步：`hooks/copilot-install.js` 在本地启动仅当 Copilot CLI 已安装且已启用时调用；远端由 Settings Remote SSH deploy controller 调用。路径解析尊重 `COPILOT_HOME` env（trimmed 非空才生效，否则 fallback 到 `~/.copilot`）；`hooks/copilot-hook.js` 的 session-state resolver 同样走 env\n- Remote SSH 的 effective transport 由 `ssh -G` 只读检查决定：ordinary SSH 在没有 retained serialized occupancy 时保持 `context:null` 的 parallel 路径；serialized transport 以有效 target key（不是 profile id）互斥。所有 serialized managed SSH/SCP child 必须持 coordinator 发出的有效 connection/operation context，并通过其 pre-spawn gateway 启动；用户交互终端只有命中 serialized/retained occupancy 时才要求 coordinator 判定 target 完全 idle\n- serialized persistent tunnel 使用同一条 SSH 内嵌 readiness；暂停通过 stdin EOF 请求自然退出并等待 `close`。强杀或带 signal 的 outer `ssh.exe` close 不能证明 nested ProxyCommand 已 drain；timeout/未验证 drain 必须 quarantine，期间禁止新 child、mutation、resume 或 interactive terminal\n- mutation 在 deploy-lock acquire-attempted / lock-owned 后遇到 exit 255、EOF/reset、signal 或其他 unknown result 时不得自动 replay、retry、release lock 或恢复连接；必须保留 primary error 并传播 recovery state，必要时要求 `manual_lock_inspection_required`\n- Remote SSH secure hook 必须同时携带 `CLAWD_REMOTE=1` 与 `CLAWD_SSH_REMOTE=1`，只读 layout identity 并 pin 精确端口；identity 缺失/损坏/不可读必须 fail closed，禁止回退端口扫描\n- Remote SSH deploy-lock acquisition 必须原子化；成功 acquire 后的每个 live mutation 都要在同一远端命令内 fencing 校验，cleanup 还必须锁内重读 installId/profileId/runtimeKey/layoutVersion 所有权。无身份、冲突、ownerless/corrupt lock 均不得自动接管\n- 默认 `account-default` 只支持不同 Unix 账号；同 Unix 账号冲突必须阻止。`profile-isolated` 在真实 SSH/CLI 矩阵完成前由 `CLAWD_ENABLE_EXPERIMENTAL_REMOTE_ISOLATION=1` 发布门隐藏；它只隔离用户级 CLI config/session/runtime 与 Clawd 路由，不代表完整 HOME 或同 UID 安全隔离，project 配置/部分 cache/macOS Claude Keychain auth 仍可能共享\n- Hermes Agent 的 Remote SSH 部署是 `secureDeploy` 内的 `hermes-files` → `install-hermes` 两个阶段，复用同一条 serialized transport、deploy lease、fencing 与所有权检查，没有独立的 Hermes SSH deployer：secure 模式由每个托管 `plugins/clawd-on-desk/` 内的 plugin-local marker `clawd-ssh-secure-v1` latch，latch 后 identity 必须在每次 state/probe/permission 请求时重新读取（禁止 `(mtime,size)` 缓存），且不得发送任何远端 PID / 进程树 metadata；plugin 资产走独立 staging 目录，清理只 `rm -f` 精确文件再 `rmdir`，禁止 `rm -rf`；`REMOTE_IDENTITY_STEP_NAMES` 保持冻结的 8 步不变，不得加入 `installHermes`；Clawd 绝不自动重启 Hermes gateway，托管模块被替换时只报告需要手动重启\n- 禁用 agent 不应卸载 hooks / plugins / extensions：只停止对应 monitor、清理 session / bubble、让 HTTP hook 入口快速 fallback；重新启用未安装 agent 不触发本机 integration sync。卸载集成必须走 Settings Agent 页的 Uninstall / 对应 uninstall 命令，并同时清掉 `integrationInstalled`\n- Kiro 的 `sessionId=\"default\"` 会复用；session alias key 必须按 cwd scope 区分，同时保留旧 `local|kiro-cli|default` 只读 fallback\n- Windows NSIS release 必须产出明确架构的 x64 / ARM64 安装包：`win.artifactName` 保留 `${arch}`，`nsis.buildUniversalInstaller` 保持 `false`\n- 每个 release target 只能保留一个匹配目标架构的 Koffi `koffi.node`；`afterPack` 只允许剪裁 `app.asar.unpacked` 的物理文件，禁止重写 `app.asar`，并必须通过完整 native inventory audit（唯一常设例外是 electron-builder 管理的 Windows ia32 `resources/elevate.exe`）\n- 资源路径统一用 `path.join(__dirname, ...)`\n- 需要编辑发布素材时，先复制到 `assets/source/` 再改，不要直接改工作素材来源不明的文件\n- `assets/source/cloudling-pointer-bridge/` 是 Cloudling 指针桥素材的保留源文件目录；运行时逻辑已内联进主题 SVG，不要把这个 source 目录当临时文件清理\n- 主题状态、sleep/DND、mini mode、状态映射的细节在 `docs/project/theme-state-ui.md`\n- 官方可下载主题（`official-theme-*`）是受管分发层，不是 built-in、也不提升信任：catalog 是固定远端小目录（renderer 只能传 themeId），下载走 Electron main `net.request` 的 manual redirect + 精确 CDN host allowlist + 固定 bytes/SHA-256（未支持 host 返回稳定 `DOWNLOAD_HOST_UNSUPPORTED`，不允许 catalog 扩展 allowlist），ZIP 只在 manager 专属 staging 内流式解压并以 marker-before-rename 同卷提交，最终以 `isBuiltin=false` 加载（`trustedRuntime` 无效）。`setThemeSelection` / `removeTheme` / `officialTheme.commitInstall` / `officialTheme.uninstall` / `theme` update 共用 `lockKey=\"theme\"`；卸载 active 主题必须等 `waitForThemeReloadSettled()`。主仓库附带一份目录快照 `src/official-theme-catalog-snapshot.json`：网络拉取失败时列表先用上一次成功加载的目录（内存 LKG 或磁盘缓存），都没有才用快照；第一次拉取有结果之前（`uninitialized`）不用快照；快照**不作安装依据**，安装仍只认经校验的网络/磁盘目录。快照只作列表回落（仍显示 `offline` 和重试），不含素材与预览图，不写磁盘缓存，且参与版本不能回退的比较；发布前用 `npm run update:official-theme-snapshot` 刷新。不要把 Hash Sage / Whale-chan 的动画素材（APNG / WebP），或把它们写成内置主题的文案带回主仓库\n- Settings 体系里，store 是唯一真相，controller 是唯一写入者；不要绕开 `settings-controller.js`\n- Dashboard 数字快选是**完整 Dashboard 同一页面的临时键盘模式，仅 macOS/Windows**；Linux 明确 NOT SUPPORTED（不是待验证）。平台 gate 的唯一真相是 `shortcut-actions.js` 的 `supportedPlatforms` + `isShortcutActionSupported()`，Settings 展示、globalShortcut 注册/录制、设置命令和冲突占用都必须服从它；遗留的不支持绑定只忽略执行，不删用户 prefs、不占其他快捷键。darwin/win32 的 Dashboard 页面活在 `WebContentsView` 里，`BrowserWindow.fromWebContents()` 对它返回 null、BaseWindow 不触发 `ready-to-show`；页面 WC 一律从 owner 取。禁止用 `hide()`+`showInactive()` 归还已显示的普通宿主（实测会遮挡来源窗口），只能 opacity/input parking 并幂等恢复捕获值。详见 `docs/project/theme-state-ui.md`\n\n## Testing\n\n- 自动化测试使用 Node 内置 test runner：`npm test`\n- `test/*.test.js` 覆盖核心 unit/contract、installer、route、UI/runtime 与 Remote SSH transport/coordinator/identity；部分 fixture 会启动 Node、shell 或 Git Bash 子进程，缺少依赖时可能 skip，不能把全套结果概括成纯逻辑或等价真机验证\n- Remote SSH 真机矩阵与记录在 `scripts/manual/README.md`；Windows OpenSSH + Codespaces stdio 边界及 ordinary-host V15 release gate 不能从 unit tests 互相推断，无法执行时必须明确记录 pending / residual risk\n- Windows Terminal 真机、GUI smoke 与清理必须假定多个 tab/window 共享进程：不得按 PID/进程名 `taskkill`、`Stop-Process` 或宽泛终止 WindowsTerminal、Codex、`cmd.exe`、`ssh.exe`、OpenConsole、conhost。测试终端只能在明确 test-owned session 内 `exit`；无法证明 ownership 就保留现场并请用户手动关闭\n- 当前开发环境是 Windows-first；macOS 特定路径无法在这里手动 QA，改到 mac 逻辑时要用 code-review","isInternal":false,"tokens":24025,"sizeBytes":73755},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.claude-plugin/marketplace.json","title":"Claude Plugin Marketplace Catalog","category":"marketplace","format":"json","content":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.claude-plugin/marketplace.json)","tokens":300,"sizeBytes":207},{"name":"plugin.json","path":".claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.claude-plugin/plugin.json","title":"claude-plugin Plugin Manifest","category":"plugin-manifest","format":"json","content":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.claude-plugin/plugin.json)","tokens":300,"sizeBytes":193},{"name":"mcp.json","path":".cursor/mcp.json","rawUrl":"https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.cursor/mcp.json","title":"Model Context Protocol (MCP) Configuration","category":"mcp-config","format":"json","content":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.cursor/mcp.json)","tokens":300,"sizeBytes":186}],"systemPromptSnippet":"<yakaai_skills repo=\"rullerzhou-afk/clawd-on-desk\">\n<!-- File: AGENTS.md (Tokens: ~24025 | Category: root-instruction) -->\n# AGENTS.md\n\nThis file is the entry point for coding agents working in this repository. Keep it short and operational. Durable architecture lives in `docs/project/`; `docs/plans/` and `docs/investigations/` are historical evidence unless this file explicitly links them.\n\n## Project Overview\n\nClawd 是一个 Electron 桌宠：通过 hook、日志轮询、plugin 和 extension 感知 AI coding agent 的工作状态，并播放像素风动画。当前支持 Claude Code、Codex CLI、Copilot CLI、Gemini CLI、Antigravity CLI (agy)、Cursor Agent、CodeBuddy、WorkBuddy、Grok Build、Kiro CLI、KiroCrew、Kimi Code CLI (Kimi-CLI)、Qwen Code、ZCode、CodeWhale、opencode、MiMo Code、Pi、OMP (oh-my-pi)、OpenClaw、Hermes Agent、Qoder、QoderWork、QwenWork (千问办公)、Reasonix、DeepSeek Harness、TraeCode (Trae CN)、MiniMax Code；内置 Clawd / Calico / Cloudling 三套主题，支持用户主题，并可经 Settings 从独立 `rullerzhou-afk/clawd-themes` 仓库下载可选官方主题（Hash Sage、Whale-chan，external theme 权限、可卸载）；平台覆盖 Windows、macOS、Linux，UI 支持 en / zh / zh-TW / ko / ja / pt-BR / es。\n\n## Common Commands\n\n```bash\nnpm start\nnpm run build                  # default Windows package\nnpm run build:win:x64\nnpm run build:win:arm64\nnpm run build:win:all\nnpm run build:mac\nnpm run build:linux\nnpm run build:all\nnpm install\nnpm test\nnpm run verify:electron\nnpm run verify:release\nnpm run audit:assets\nnpm run audit:pr-history-assets\nnpm run audit:native-package -- --app-root <extracted-app-root> --target <target-id>\nnpm run create-theme\n\nnpm run install:claude-hooks\nnpm run uninstall:claude-hooks\nnpm run install:cursor-hooks\nnpm run install:gemini-hooks\nnpm run install:antigravity-hooks\nnpm run install:kiro-hooks\nnpm run install:kirocrew-hooks\nnpm run uninstall:kirocrew-hooks\nnpm run install:kimi-hooks\nnpm run install:qwen-hooks\nnpm run install:zcode-hooks\nnpm run uninstall:zcode-hooks\nnpm run install:codewhale-hooks\nnpm run uninstall:codewhale-hooks\nnpm run install:pi-extension\nnpm run uninstall:pi-extension\nnpm run install:omp-extension\nnpm run uninstall:omp-extension\nnpm run install:openclaw-plugin\nnpm run uninstall:openclaw-plugin\nnpm run install:hermes-plugin\nnpm run uninstall:hermes-plugin\nnpm run install:qoder-hooks\nnpm run uninstall:qoder-hooks\nnpm run install:qoderwork-hooks\nnpm run uninstall:qoderwork-hooks\nnpm run install:qwenwork-hooks\nnpm run uninstall:qwenwork-hooks\nnpm run install:reasonix-hooks\nnpm run uninstall:reasonix-hooks\nnpm run install:workbuddy-hooks\nnpm run uninstall:workbuddy-hooks\nnpm run install:grok-hooks\nnpm run uninstall:grok-hooks\nnpm run install:dsh\nnpm run uninstall:dsh\nnpm run install:codex-hooks\nnpm run uninstall:codex-hooks\nnpm run install:codex-debug-hooks\nnpm run uninstall:codex-debug-hooks\nnpm run install:mimocode-plugin\nnpm run uninstall:mimocode-plugin\nnode hooks/codebuddy-install.js\nnode hooks/opencode-install.js\n\nbash test-demo.sh [seconds]\nbash test-mini.sh [seconds]\nbash test-macos.sh\nbash test-oneshot-gate.sh [state] [seconds]\n```\n\n新安装默认只把 Claude Code 和 Codex 标记为已安装并启用；其他 agent 默认未安装、未启用。正常启动时，Clawd 只会为 `integrationInstalled=true` 且 `enabled=true` 的 agent 自动同步 Claude / Codex / Copilot / Gemini / Antigravity / Cursor / CodeBuddy / WorkBuddy / Grok Build / Kiro / KiroCrew / Kimi / Qwen / ZCode / CodeWhale / Qoder / QoderWork / QwenWork / Reasonix / TraeCode / MiniMax Code hooks、opencode / MiMo Code / OpenClaw / Hermes plugins 和 Pi / OMP extensions。Settings Agent 页的 Install 会安装并启用该集成；Uninstall 会卸载 Clawd 管理的 hook/plugin/extension，并同时把该 agent 设为未安装、未启用。单独关闭 enabled 只会跳过启动同步并屏蔽事件/权限入口，不卸载用户已有 hooks / plugins / extensions；重新启用未安装 agent 只打开事件入口，不会写本机集成文件。手动安装命令主要用于调试、重装或远程部署。\nSettings 注册的自定义 HTTP Agent 是独立模型：`customApplications` 是注册真相，对应 `agents[customId]` 必须显式保持 `integrationInstalled=false`。注册只分配 ID 和状态入口，不安装 hook、不观察进程；v1 仅允许已注册且启用的 ID 向 `/state` 上报，`/permission` 永远不提供决定。删除或伪造的 `custom-` ID 必须直接拒绝，不能降级成 Claude Code subagent。\nCopilot CLI 同步走 `<COPILOT_HOME 或 ~/.copilot>/hooks/hooks.json`，marker-based 增量合并只接管含 `copilot-hook.js` 标记的条目，用户其他 entry / 其他 `hooks/*.json` 文件原样保留；hooks.json 或 `settings.json` 顶层 `disableAllHooks: true` 时 doctor 报 warning（不挂 Fix 按钮）。详见 `docs/guides/copilot-setup.md`。\n\n## Read These Docs\n\n- `docs/project/agent-runtime-architecture.md`：运行时架构、模块边界、启动与数据流、多 agent、permission bubble、终端聚焦和自动同步\n- `docs/project/theme-state-ui.md`：状态机、主题系统、settings、mini mode、素材规则、平台限制、待落地 UI 决策\n- `docs/project/release-process.md`：发版 checklist、release note 核对、tag 触发 GitHub 打包和资产确认\n- `docs/guides/copilot-setup.md`：Copilot CLI 自动同步说明、`COPILOT_HOME` 兼容性、手动配置备选模板\n- `docs/guides/dsh-setup.md`：DeepSeek Harness web profile 与桌面版的实验性 plugin 集成状态与普通审批集成\n- `docs/guides/state-mapping.md`：状态 → 动画权威表\n- `docs/guides/guide-theme-creation.md`：主题作者指南\n- `docs/guides/setup-guide.md`：安装、远程 SSH、各 agent 接入\n- `docs/guides/custom-agent-http.md`：自定义 HTTP Agent 的 state-only 接入合约和动态端口发现\n- `docs/guides/known-limitations.md`：用户向已知限制\n- `docs/guides/recap.md`：本地小结的指标口径、coverage、时区/DST、隐私存储与产品红线\n- `docs/guides/codex-wsl-clarification.md`：Codex / WSL 路径与 Node 说明\n- `docs/guides/guide-remote-ssh.md`：Remote SSH 用户流程、Codespaces 单会话 transport 与共享主机边界\n- `docs/guides/telegram-approval.md` / `docs/guides/feishu-lark-remote-approval.md`：远程审批设置与失败回退语义\n- `docs/guides/roam-fence.md`：自由漫游与可选围栏\n\n## Runtime Summary\n\n- HTTP hook / plugin 主路径：`src/server.js` → `src/server-route-state.js` → `src/agent-runtime-main.js` → `src/state.js` → IPC；本地 JSONL monitor 直接进入 `agent-runtime-main`，不经过 HTTP server\n- 权限主路径：`src/server-route-permission.js` → `src/permission.js`；本地 bubble、显式 permission automation 与可选 Telegram / 飞书 Lark 远程审批都可能产生真实决定\n- 桌宠的渲染/输入双窗口由 `src/pet-window-runtime.js` 统一创建和定位；浮层排序与 topmost 行为在 `src/floating-window-runtime.js` / `src/topmost-runtime.js`\n- `src/state.js` 生成的 session snapshot 是 Dashboard、HUD/Orbit 与可选通知/presence/mobile consumer 的共享合约，改字段必须检查所有消费者\n- `src/integration-sync.js` 为已安装且启用的 agent 异步同步 hooks / plugins / extensions；Codex official hooks 为 primary，JSONL 轮询保留为 fallback\n- Claude hook 恢复由 `src/claude-settings-watcher.js` 的目录 watcher + 低频只读巡检共同负责；repair 统一经过 `src/claude-hook-operations.js` 队列并复验，连续失败转 `manual-fix-required`。完整 gate、阈值与 source-missing 语义见 `docs/project/agent-runtime-architecture.md`\n- `src/agent-gate.js` 控制各 agent 的安装意图、启用状态、权限气泡开关和 wait-for-input notification 子开关\n- 设置系统主链路是 `src/prefs.js` → `src/settings-controller.js`（唯一写入者）→ `src/settings-store.js`；`settings-actions*` 负责校验和 pre-commit gates，`settings-effect-router.js` 负责 post-commit runtime effects 与广播\n- 启动时还会尝试自动安装 VS Code / Cursor terminal-focus extension，并初始化 updater\n- Remote SSH 通过 effective transport inspection 区分 ordinary parallel SSH 与 serialized transport；后者由 target-scoped coordinator 编排。远程部署只走 Settings，`scripts/remote-deploy.sh` 已 fail-fast 停用\n\n## Core Files\n\n更细的背景见 `docs/project/agent-runtime-architecture.md` 和 `docs/project/theme-state-ui.md`。\n\n| File | Responsibility |\n|------|------|\n| `src/main.js` | Electron composition root：生命周期、上下文组装与各 runtime / IPC 注册器接线 |\n| `src/server.js` + `src/server-route-state.js` + `src/server-route-permission.js` | HTTP 服务、端口发现、`/state` / `/permission` 路由 |\n| `src/agent-runtime-main.js` + `src/integration-sync.js` | local monitor / official hook 仲裁、Codex turn fence、按 gate 的集成同步 |\n| `src/state.js` | 状态机、多会话合并、优先级、自动回退、睡眠/DND |\n| `src/renderer.js` | 动画切换、SVG 预加载、眼球追踪渲染 |\n| `src/permission.js` + `src/permission-automation-policy.js` + `src/session-automation-coordinator.js` | 权限气泡、自动化策略、per-session 授权与决策回包；远程 client 由 `main.js` 注入 |\n| `src/pet-window-runtime.js` + `src/floating-window-runtime.js` + `src/topmost-runtime.js` | 双窗口 owner、浮层重排、z-order / fullscreen / focusability |\n| `src/update-bubble.js` | 更新气泡创建、测高、跟随桌宠定位，避让 HUD / permission stack |\n| `src/dashboard.js` + `src/dashboard-renderer.js` | Sessions Dashboard 唯一 owner：会话列表、别名编辑、终端跳转、几何持久化，以及同一页面的临时键盘模式 |\n| `src/dashboard-host.js` | Dashboard 普通宿主的平台封装：darwin/win32 用 `BaseWindow + WebContentsView`（无 `ready-to-show`），Linux 保留 `BrowserWindow` |\n| `src/dashboard-quick-mode.js` | 完整 Dashboard 的 1–9 键盘模式（**macOS/Windows only**）：quick 宿主、opacity/input parking、轮次栅栏与冻结数字映射；Windows 显式取消与页面失效的来源恢复在 `src/quick-select-origin-focus.js`，quick 宿主的退出清理挂在 `before-quit` |\n| `src/session-hud.js` + `src/session-hud-renderer.js` | 桌宠旁轻量会话 HUD、折叠行、点击跳转 |\n| `src/session-alias.js` | session alias key 规范化、TTL pruning、Kiro cwd scope |\n| `src/theme-loader.js` + `src/theme-runtime.js` | stateless 主题加载/消毒与唯一 active-theme owner；`waitForThemeReloadSettled` 完成信号 |\n| `src/official-theme-catalog.js` / `-download.js` / `-installer.js` / `-main.js` | 官方可下载主题：严格 catalog/cache、Electron `net.request` 流式下载、受限流式 ZIP 解压与 marker-before-rename、main owner/IPC/共享 `theme` lock |\n| `src/prefs.js` | 偏好 schema、load/save/migrate/validate，设置持久化入口 |\n| `src/settings-actions*.js` + `src/settings-effect-router.js` | 设置 validators / commands / pre-commit gates 与 post-commit runtime effects |\n| `src/settings-controller.js` | 设置系统唯一写入者 |\n| `src/settings-store.js` | 不可变 snapshot store |\n| `src/settings-ui-core.js` + `src/settings-renderer.js` + `src/settings-tab-*.js` | Settings shared UI state、侧栏/tab shell 与各页逻辑 |\n| `src/menu.js` | 托盘 / 右键菜单，串起设置、Dashboard、mini mode、更新入口 |\n| `src/mini.js` | 极简模式入场、滑动、peek、状态映射 |\n| `src/tick.js` | 主循环、鼠标轮询、眼球和 idle/sleep 逻辑 |\n| `src/drag-position.js` | 拖拽落点规范化与跨显示器钳制 |\n| `src/visible-margins.js` | 可视角色边距与 edge pinning 规则 |\n| `src/updater.js` | Git 模式 / `electron-updater` 双路径更新逻辑 |\n| `src/focus.js` | 终端聚焦 |\n| `src/hit-renderer.js` + `src/hit-geometry.js` | 输入窗口命中、拖拽、连击反应 |\n| `src/remote-ssh-runtime.js` | Remote SSH tunnel/ingress 状态机、ordinary health probe、serialized readiness 与重连 |\n| `src/remote-ssh-transport.js` + `src/remote-ssh-transport-coordinator.js` | effective transport inspection、pre-spawn admission、target ownership、drain barrier 与 quarantine |\n| `src/remote-ssh-deploy.js` | Deploy / Repair、身份事务、lease/fencing、wrapper、cleanup 与远端 Codex monitor mutation |\n| `src/remote-ssh-identity.js` + `src/remote-ssh-layout.js` + `src/remote-ssh-ingress.js` | 身份/布局真相与 profile 专属、nonce 校验的本地 ingress |\n| `src/remote-ssh-node.js` + `src/remote-ssh-shell-detect.js` + `src/remote-ssh-local-config.js` | 远端 Node/ shell 探测与本机 SSH config 入口 |\n| `src/remote-ssh-profile.js` | Remote SSH profile schema、校验、默认值和持久化规范化 |\n| `src/remote-ssh-ipc.js` | Remote SSH runtime / deploy / monitor orchestration、intent policy、IPC 状态与进度广播 |\n| `src/remote-ssh-quote.js` | Remote SSH 终端命令与跨平台 shell quoting helper |\n| `agents/registry.js` | agent 注册表 |\n| `agents/codex-log-monitor.js` | Codex JSONL fallback 轮询 |\n| `agents/gemini-log-monitor.js` | legacy Gemini session JSON 轮询器；当前 Gemini hook-only 路径不启动 |\n| `hooks/dsh-install.js` | DeepSeek Harness immutable managed bridge generation、ownership verify、web 与 desktop 两个 profile 的安装 / 修复 / 卸载编排 |\n| `hooks/kirocrew-install.js` + `hooks/kirocrew-store.js` | KiroCrew state-only gateway hooks、upstream-compatible mutation locks and atomic private store writes |\n| `hooks/kirocrew-hook.js` + `hooks/kirocrew-command.js` | KiroCrew state bridge and exact command-shape ownership classifier |\n| `hooks/dsh-notices.js` | DeepSeek Harness 常驻提示的存储与规则（按 profile 的 `notices-<profile>.json`） |\n| `hooks/clawd-hook.js` + `hooks/copilot-hook.js` | Claude Code / Copilot CLI 状态上报脚本 |\n| `hooks/install.js` | Claude hook 注册 / 卸载 |\n| `hooks/auto-start.js` | Claude `SessionStart` 自动拉起 Clawd 的 hook |\n| `hooks/codex-hook.js` / `hooks/codex-install.js` | Codex official hooks 状态与权限审批、安装 / 卸载 |\n| `hooks/cursor-install.js` / `gemini-install.js` / `antigravity-install.js` / `kiro-install.js` / `kimi-install.js` / `qwen-code-install.js` / `codewhale-install.js` / `codebuddy-install.js` / `workbuddy-install.js` / `opencode-install.js` / `pi-install.js` / `openclaw-install.js` / `hermes-install.js` / `qoder-install.js` / `qoderwork-install.js` / `reasonix-install.js` | 各 agent 集成安装逻辑 |\n| `hooks/opencode-family-managed-generation.js` | OpenCode 用户可写托管 generation（canonicalizer、bundle/manifest、stage/promote、target owner record、target-scoped lock）；纯 Node 内置依赖，不进入 Remote SSH `HOOK_FILES` |\n| `hooks/opencode-family-entry-ownership.js` | OpenCode-family plugin entry 的 string/tuple 解析、跨平台路径等价、所有权分类与重复/options 冲突规划（纯逻辑、可注入 fs） |\n| `hooks/opencode-family-install.js` / `hooks/opencode-family-jsonc.js` | 家族注册器：`managedMaterialization:true` 走托管 generation 事务 + 共享 entry planner；`false` 保持 legacy broad-basename register/unregister |\n| `src/doctor-detectors/opencode-managed-inspector.js` | managed OpenCode Doctor inspector（ownership/manifest/生成结构、Fix policy、masked supplementary warning）；接受注入 fs |\n| `hooks/workbuddy-hook.js` | WorkBuddy state + Notification command hook；无 session_id 时返回合法 stdout 后丢弃事件 |\n| `hooks/grok-hook.js` / `hooks/grok-install.js` | Grok Build state + Notification command hook；写入 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json`；`env` marker `CLAWD_GROK_HOOK=v1` 所有权；无 session id 时丢弃；不注册 `/permission` |\n| `hooks/zcode-hook.js` / `hooks/zcode-install.js` | ZCode 状态 + 阻塞式 PermissionRequest hooks（`hookSpecificOutput` 决定 / `{}` 无决定）、`hooks.events.*` 按事件超时增量注册与 Claude-imported Clawd hook 清理 |\n| `hooks/qoder-hook.js` | Qoder state-only 状态上报脚本（Phase 1，stdout 恒为 `{}`） |\n| `hooks/minimax-hook.js` / `hooks/minimax-install.js` | MiniMax Code state-only 本地插件：整目录 install/uninstall（`<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/`），CLAUDE 格式 hooks + exec-form args，10 事件无 PermissionRequest/Notification，`.clawd-managed.json` 结构化所有权凭据、fail closed |\n| `hooks/codex-remote-monitor.js` | 远程 Codex JSONL 轮询并通过 SSH 隧道回传（含 token_count 订阅配额的 metadata_only 上报） |\n| `hooks/claude-statusline.js` / `hooks/antigravity-statusline.js` | 各 CLI statusline 适配器：渲染状态行 + 把订阅配额（rate_limits）以 metadata_only POST 上报；Claude 版支持远程部署（`CLAWD_REMOTE=1` 前缀）与 `--chain` 串联模式（原 statusLine 对象保存在 `~/.claude/hooks/clawd-statusline-chain.json`，卸载时恢复） |\n| `extensions/vscode/extension.js` | VS Code / Cursor 终端 tab 聚焦辅助扩展 |\n\n## Constraints\n\n- `agents/registry.js` 的 capabilities 是权限、subagent、session-end 等路由/gate 的权威来源；不得另写名单代替 capability 判定。但 permission automation eligibility 由更窄的 `isKnownPermissionAgent()` 显式判定（`KNOWN_PERMISSION_AGENTS` + explicit opencode-family membership），不得从 `permissionApproval` 自动派生或合并回 registry capabilities\n- 小结的指标能力例外地只认 `src/recap-metrics.js` 的显式逐 Agent 口径，不得从 registry capabilities 或标准化 event 名推导。只统计已通过 gate、Codex source/replay fence、subagent 与完成仲裁的 accepted activity；DND 继续记录且不切 coverage，suspend/退出/关闭记录才切。`null` 是不支持，绝不能渲染或汇总成 `0`\n- 小结持久层固定为 `~/.clawd/recap-v1/` 下 14 个本地日的最小 HMAC 小票与 400 个本地日的 daily/coverage；不得落 prompt/回复/命令/工具内容、路径/项目、原始 event/session/profile/turn/tool ID，不得增加网络、导出或分享。首版不做 Token、金额、模型、推理强度、Skill、人的工作/编码时长、streak、峰值/最长项、排行榜或生产力评分\n- Claude Code / CodeBuddy 的阻塞式权限审批走 `POST /permission` HTTP hook；普通状态事件走 command hook（CodeBuddy command hook 对所有事件输出 `{}`，不做工具或权限决定）\n- permission automation（off / auto-tools / unattended）和 per-session grant 会在 bubble 渲染前产生真实 allow/answer。agent/family eligibility 是显式白名单；工具分类则因 mode/adapter 而异：auto-tools 对 Claude/Qwen 的未知 built-in fail closed，但其他已知 adapter 不都使用逐工具白名单，unattended 还会有意自动放行可作 Allow/Deny 的未知请求。新增 agent、工具或交互类型必须审查 policy + tests，不能从 `permissionApproval` 推导资格或笼统假设“未知请求都会 defer”\n- Telegram / 飞书 Lark 与本地 bubble 是并行决策通道。远程通道超时、断连、未配置或发送失败不得产生远程决定，更不得转成 deny；有本地 bubble 时请求继续 pending，只有 remote-only 且所有可用 client 都无决定时，整体请求才 no-decision 并回到 agent 原生流程\n- WorkBuddy 通过当前 `~/.workbuddy-ai/settings.json`（旧版兼容 `~/.workbuddy/settings.json`）的 Claude Code 兼容 command hooks 做 **state + Notification only** 集成：不注册 `/permission`，审批始终留在 WorkBuddy 原生沙箱与 GUI；无 `session_id` 的事件返回合法 stdout 后直接丢弃。当前只支持 macOS/Windows 桌面应用，没有已验证的 Linux/WSL CLI；不要把裸 `Electron` 当 WorkBuddy 进程。\n- Grok Build（agent id `grok-build`）通过 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json` 的 Claude Code 兼容 command hooks 做 **local / main-session / state + Notification only** 集成（Phase 1）：stdin 为 camelCase（`sessionId` / `toolName`），`hookEventName` 是 camelCase key + snake_case value，`hook_event_name` 是 snake_case key + PascalCase value。**逐 handler 的 `env` 结构化 marker `CLAWD_GROK_HOOK=v1` 是唯一所有权凭据**；文件名/substring（含 `grok-hook.js.backup`）只用于诊断告警，永不授权改写或删除。安装/卸载只增删含该 marker 的 handler，保留 unknown 顶层键、其他 event、foreign matcher group 与 sibling handler；没有 marker 的既有文件一律原样拒绝。`SessionEnd` 不写 `timeout`（继承 Grok 1.5s teardown），其余事件 5s。Windows 用 `windowsWrapper:\"portable\"` 形态，不得用 `&` / `-EncodedCommand` / 自造 `shell` 字段。Grok 没有 `PermissionRequest`，不注册 `/permission`，adapter 始终输出 `{}`。子代理事件（`subagentType`）直接丢弃；不注册 `SubagentStart` / `SubagentStop`。Grok 默认会扫 `~/.claude/settings.json`，所以 `clawd-hook.js` / `cursor-hook.js` / `auto-start.js` 只在非空官方 `GROK_HOOK_EVENT` 下直接退出，`GROK_HOME` / `GROK_SESSION_ID` / 无关 `GROK_*` 不得触发。`Stop` 只有精确 `reason === \"end_turn\"` 且无 background task / session cron / `stopHookActive` 才算完成，其余由 adapter 本地判定；`channel_closed` / `shutdown` 等 session-end 形态的 Stop 在 fence 之前丢弃。turn 顺序由 `src/grok-turn-fence.js` 的 bounded in-memory fence 仲裁（晚到旧 turn、重复 terminal、continuation Stop、Stop→StopCancelled 纠正）。不进入 subagent / WSL / Remote SSH / startup recovery / terminal focus / quota / context / recap turn 指标。`~/.grok/hooks/clawd.json` 是未发布的 PR preview 路径，只做 warning，不得自动接管或删除。\n- Codex 的阻塞式权限审批走 official `PermissionRequest` command hook：hook 脚本长连接 `POST /permission`，只允许 stdout 返回 sanitized `behavior/message`，`updatedInput` / `updatedPermissions` / `interrupt` 必须 omit。权限模式默认 `auto`（旧 `native` 规范化为 `auto`），仅准确本机 session/turn 的人工 reviewer 证据可进 Clawd；未知、自动 reviewer、MCP/app、远程/WSL 均 no-decision；唯一例外是远程/WSL（路由 reason 为 `nonlocal`）的 Bash/apply_patch 在全局自动放行会立即 allow 时（`wouldAutoAllowPermission`：非 reminder hold、非会话覆盖、非交互子代理）由 Clawd 直接放行（#1186），路由后若设置已变则 no-decision，绝不弹气泡。`intercept` 是显式接管；升级时旧 `intercept` / `native` 统一迁到 Auto 一次，之后重新选择的 Intercept 会保留。不得用全局 config、其他会话或旧回合推断当前请求的审批方；证据不足时返回 no-decision，交还 Codex 原生流程。\n- hook 脚本只允许依赖 Node 内置模块，以及同目录 `hooks/` 下、且登记在 `src/remote-ssh-deploy.js` 的 `HOOK_FILES` 部署清单中的纯 Node helper（如 `server-config.js` / `shared-process.js` / `json-utils.js` / `codex-originator.js` / `codex-subagent-fields.js` / `context-usage.js` / `state-payload-size.js` / `quota-bucket.js` / `claude-rate-limits.js` / `codex-rate-limits.js` / `antigravity-context-usage.js`）；manifest-consistency 测试强制检查依赖闭包，新增 helper 必须登记\n- CJS hook 脚本需要稳定终端 PID 时，必须复用 `hooks/shared-process.js` 的 `createPidResolver()` 及其 lifecycle context；不要复制进程树 walk 或用 `process.ppid` 简化。`getStablePid()` 只是 opencode-family plugin 的内部 resolver\n- `agentCmdlineCheck` 只对进程名在 `agentCmdlineNames` 里的祖先进程运行，默认是 `DEFAULT_AGENT_CMDLINE_NAMES`：`node` / `node.exe`，加上 Linux 上没设过 `process.title` 的 Node 在 `ps -o comm=` 里的名字——Node 23.8–25.4（含全部 24.x）把主线程命名为 `MainThread`、≥ 25.5 为 `node-MainThread`，Linux 报的进程名就是主线程名。传入 `agentCmdlineNames` 会整体替换默认值：只想加名字的 adapter 必须在选项里直接写成 `agentCmdlineNames: new Set([..., ...DEFAULT_AGENT_CMDLINE_NAMES])`（如 ZCode；可以跨行，方括号里只能有普通字符串字面量和 `...DEFAULT_AGENT_CMDLINE_NAMES` 本身，不能有注释或其他表达式；简写属性、先存进变量，或任何不是这个形状的提及（包括注释里的）都会被判不合格，因为文本检查无法核对），只有刻意只探测非 Node 宿主的（WorkBuddy 的 `electron`）例外，`test/shared-process.test.js` 会扫描 `hooks/*.js` 检查\n- opencode v1 权限不走 `permission.ask` hook，而是 event hook + reverse bridge；v2 走 `ctx.permission.hook(\"evaluate\")` 的阻塞 HTTP 响应\n- OpenCode / MiMo v1 原生问题走独立本地 `/question` 长轮询，不复用审批回包；遵循全局 permission bubble 开关与 family 单 agent 开关。只接受已核实的 v1 来源、版本和问题 schema，提交前用原 SDK client 复核精确 request/tool/session，答案保持有序 `string[][]`；无决定返回 204 交还原生。OpenCode 由原生 reply RPC 的 `true` / 404 判定提交结果，MiMo 仍需精确 `question.replied` 答案匹配。子会话问题、OpenCode v2、Remote SSH 及未审核 agent 保持原生；不要改 Claude/Hermes wire 或托管 generation 依赖集合。详见 `docs/guides/agent-questions.md`。\n- opencode-family v1 插件经 `ctx.client` 连回宿主时，主机为通配监听地址（`0.0.0.0` / `[::]`）就按次改用 `127.0.0.1` / `[::1]`（不改宿主共享的客户端配置；非通配地址保持原调用形状）。默认 TUI 走进程内 fetch；`opencode serve` / `web` 下这是对监听地址的真实 HTTP 请求，受宿主进程里的 `HTTP_PROXY` / `NO_PROXY` 影响，而通配地址不会自动绕过代理。桥接回复失败返回 `{ok:false,status,error}`（`status` 为上游状态码，缺省 0）。\n- OpenCode 2.x（npm `@opencode/cli`，issue #1039）由 `hooks/opencode-plugin-v2/` + core.mjs 内 `createOpencodeFamilyPluginV2` 承接：installer 在同一 generation 内额外物化 `opencode-plugin-v2/index.mjs`（v1 四文件、v2 五文件；目录 specifier 解析 index.mjs、无需 package.json，2.0.15 实测），并把它写进 **`plugins` 键**，同时清理 Clawd 自有的旧 `plugin` 条目；用户条目、tuple/options 和 v1 行为保持不变。未被 Clawd 纳管的未知 `plugin` 条目仍只报 loader WARN；v1 对未知 `plugins` 键的静默丢弃只在 **1.18.16+** 成立——1.18.15 及更早会以 `Unrecognized key: plugins` 拒绝整个 config（anomalyco/opencode#41312，2026-08-08 起才忽略未知顶层键），因此 `plugins` 写入由宿主探测决定（`hooks/opencode-host-detect.js` 三态：探测到 v2 才写；探测到 v1 不写并清扫 owned 残留；探测失败不碰该键；`CLAWD_OPENCODE_HOST` 环境变量可钉死结论，Doctor 在无 v2 宿主时不要求 v2 条目）。v2 插件是零 import 纯对象 `{id, setup}`（v2 loader 拒绝函数 default export，`@opencode/...` 裸包名无插件本地 node_modules 不可解析），事件经 `ctx.event.subscribe()`（`session.step/tool/execution.*` 词汇完全换代，未知事件一律忽略），cwd 取事件信封 `location.directory`，标题走 `session.renamed`，context usage 走 `session.step.ended` 的 step tokens（`session.usage.updated` 是 session 累计计费值，不能当占用率）。权限走 **`ctx.permission.hook(\"evaluate\")` 阻塞长连接 POST `/permission`**，决定就是 HTTP 响应体 `{decision: allow|always|deny}`（服务端按 `hook_source === \"opencode-plugin-v2\"` 路由到 v2 阻塞子分支），只有 `200` + 身份头 + 合法 JSON 才采纳决定，204/超时/断连/非 200/任何错误都不改 effect 回原生 ask UI；配置 allow 也进 hook 但绝不降级；单条 shell 命令以 `tool_input.resource` 传输，服务端 v2 分支会为其别名出 `command` 以接入破坏性操作提醒（`mapOpencodeV2ShellResource`，非 shell 工具不映射；全字符串的多 resource 以换行合并作扫描别名）；resources 原样整组转发（对象转 JSON 字符串），不做条数/长度截断，唯一边界是整 body 超 512 KiB 时跳过转发。\"Always allow\" 无宿主持久化 API，用插件内 per-session 内存规则（随常驻 service 生命周期，气泡对 v2 使用单独文案说明关闭/重开终端不会撤销）。插件跑在常驻共享 service（daemon）：`source_pid`/进程树不可信故**整组省略**（终端跳转对 v2 降级），安装/更新后需 `opencode service restart`。`ctx.permission.hook()` 按上游 v2.0.15 类型返回 `Promise<Registration>`：本实例 dispose（setup 返回的 cleanup，宿主也会在插件 scope 关闭时调用）会调用 `registration.dispose()`，注册 Promise reject 只记日志不影响事件订阅。事件订阅**不等待** hook 注册（注册挂起/reject 时状态上报照常），reload **不等待**上一代注销完成；本实例清理先同步完成本地清理（标记 disposed、abort 订阅、身份恢复）再去注销 registration，注册 dispose 有约 2s 上限、超时只记日志，注册未完成就被取代则在注册完成那一刻立即注销，不残留活 hook。上游 v2.0.15 的 trigger 对同名 hook 依次调用每个仍注册的回调、共用同一个可变 event，而我们的注销是异步的，所以 reload 窗口内旧回调可能仍被调用：已退役实例的回调入口检查 `instance.disposed` 后直接返回，不 POST、不改 event。每个 ask 各自转发（`source.id` 是工具调用级、不是 ask 级，同一工具调用会发出多个不同 ask，如 external_directory + edit），不做内容去重。config 顶层重复 `plugins` 键按歧义处理：Doctor 报 `config-corrupt` 不抛异常，register/卸载在首次写入前中止（v1 宿主 sweep 只告警并跳过），v1 `plugin` 键行为不变。v1 1.18.31 tuple 契约、generation 布局、owner/lock 语义不变；`inspectGeneration` 把历史 4 文件集接受为合法 owned-stale 形态以便迁移。真机证据与降级项见 `docs/investigations/opencode-v2-e1-evidence.md`\n- OpenCode 的 plugin 注册不再直接指向打包/源码目录：`agents/opencode-family.js` 的 `managedMaterialization:true`（OpenCode true / MiMo 本次 false）gate materialize、ownership classifier、managed Doctor 与 generation cleanup。开启后 register 必须在目标 home 下维护 `<home>/.clawd/integrations/opencode-family/opencode/homes/<configDirHash>/generations/<bundleHash>/` 的内容寻址 generation（OpenCode v2 当前五文件，历史 v1 四文件），同一 generation 可同时物化 v1/v2 入口文件，但不因此在配置中注册两个键；探测到 v2 宿主时只把 `opencode-plugin-v2` 入口写入 `plugins`，并将 `plugin` 键仅用于清理 Clawd 自有旧条目；v1 宿主和探测不到版本时保持原有 v1 注册路径；bundle allowlist 固定为 `<agent>-plugin/index.mjs` / `<agent>-plugin/package.json` / `opencode-family-plugin/core.mjs` / `opencode-family-plugin/session-ids.mjs` / `opencode-plugin-v2/index.mjs`（v2）。owner record（`owner.json`，literal `clawd-on-desk.opencode-family.target`）与 target-scoped `mutation.lock/`（独立 literal `clawd-on-desk.opencode-family.target.lock`）是所有权与 app-present 真相；lock 被持有时不并发写：interactive Install/Repair/CLI/Uninstall/About cleanup 只做一次短而有界、可注入 delay 的重试，startup automatic 不等待直接 skipped；合法且超时 2 倍以上、PID 明确 ESRCH 才允许 atomic quarantine 接管，corrupt/foreign/live/EPERM 一律不接管；release 只删自己 token 的 `lock.json` 与随后为空的精确目录，禁止 recursive cleanup。owner 的 `activeSourceMarker` 必须是 `<activeSourceRoot>/<pluginDirName>/index.mjs`（共享 canonical 身份、Windows 折叠大小写）且为 regular file，目录/dangling/错 plugin 目录/root 不匹配都不算 live。同一 target 的 source owner 冲突（marker 仍存在）一律 `owner-conflict`，不得来回改 config；旧 owner 的源码 marker 已不存在时，新 source 必须在锁内重读并原子接管 owner（config 已 current 也不例外），否则残留死 owner 会让托管 plugin 永久 inert。锁内若 config 与当前 source owner 都已被并发操作收敛，则本次零 mutation 返回 skipped。lock release 失败不得掩盖结果：成功保留 status 并附 warning + 精确 lock path 的 residualPaths，已有 primary error 时保留原错误。basename 本身永不构成所有权；copy 到 managed layout 外的完整 generation 因缺少对应 owner record 而 inert，只有 verified-current-copy 可 Repair。tuple 契约固定为 OpenCode 1.18.31 实测的 `[specifier, optionsObject]`（隔离 `opencode debug config` 证据：第二项必须是普通对象，数组/字符串第二项会被宿主拒绝）；重写只替换 `plugin[index][0]`，options 值级保留，绝不写回嵌套 tuple，malformed array 原样保留。`options.pluginDir` 仍是 test-only expected-canonical override（跳过 generation/manifest/boundary，但不跳过 ownership/唯一 entry/read-back），`resolvePluginDir()` 仍返回 source。新建文件按当前用户普通写权限落盘：不得加 readonly/deny-write ACL，不得用 `W_OK`/`r+`/INIT 日志/session 活跃做健康门禁。Uninstall 以“活动注册是否移除”为提交依据（`registrationRemoved` false/null 阻止 Settings 提交，undefined 沿用 legacy status），残留 generation 只产生 warning；清理有效 generation 时必须先在同一 `generations/` 内原子改名为非 canonical `.cleanup-*` 再递归删除，删除失败不得占住原 hash 槽。兼容旧版本留下的半残 canonical 目录时，只允许在 owner 已 released、bounded history 精确证明该 canonical entry、且配置无活动 Clawd entry 的条件下，把它原子隔离为 `.recovery-*` 后重新物化；active/foreign/unproven/canonical-in-use 一律继续 fail closed，绝不原地覆盖或修补可疑 bytes。托管 core 的 orphan inert gate（`evaluateManagedLayoutGate`）必须在 `resetDebugLog()` / PID walk / bridge / handler 注册之前，owner marker 缺失、损坏、agentId 不匹配或 `activeSourceMarker` 不存在时返回空 handler；source-direct 模式保持原行为。MiMo 保持 broad-basename register/unregister/Doctor 契约不变。\n- Pi 通过 `~/.pi/agent/extensions/clawd-on-desk` 的 global extension 推送状态；Clawd 对 Pi 是 **state-only**，不接管权限、不弹权限气泡，也不把 Pi 的默认 YOLO 流程改成手动确认\n- OMP (oh-my-pi) 通过 `~/.omp/agent/extensions/clawd-on-desk` 的 global extension 推送状态，agent id `omp`，对 Clawd 同样是 **state-only**。它是 Pi 的 fork（包名 `@oh-my-pi/pi-coding-agent`），所以 `hooks/omp-extension.ts` 刻意与 `hooks/pi-extension.ts` 保持逐行对齐（只差 package import、core import 与函数名），进程树遍历与终端识别不得各自漂移；OMP 独有的差异全部收在 `hooks/omp-extension-core.js`。**完成必须走 `session_stop` 候选 + 终态 `agent_end` 提交的两阶段协议** —— `session_stop` 先保留主会话边界，OMP 再汇总所有 extension 的续跑请求；只有后续 `agent_end.willContinue !== true` 才向 Clawd 发完成。不得直接把任一事件单独映射为完成：仅用 `agent_end` 会把 subagent/调度边界误报为完成，仅用 `session_stop` 则会早于 extension 续跑判定。`session_switch` / `session_branch` 要为被切走的旧 session 补发一条合成 `SessionEnd`，否则 Clawd 会留下一条再也不会有人上报的活动行。session id 命名空间是 `omp:<raw>`，且必须始终带 `session_title`（多个交互式会话合法地共用同一个 cwd，缺标题会让列表和跳转目标无法区分）。安装器遇到社区桥接 `~/.omp/agent/extensions/clawd-on-desk-omp.ts` 时必须 fail closed 跳过：两者上报同一批事件，同时存在会双发。当前 `assets/source/agent-icons/omp.png` 是 `fallback: true` 的占位 π 字形，不是 OMP 官方品牌素材，拿到授权素材后应替换\n- DeepSeek Harness 首发是 **web profile / Windows-first experimental / plugin-only**；rc.6 已于 2026-08-29 完成 macOS / Windows x64 源码运行的真实 API-backed session/approval smoke（#962）；rc.2 Windows packaged-app 证据仅覆盖安装、web boot 与直接 bridge client 的 state/Allow/Deny 往返（#938），不得合并宣称 rc.2 安装包的真实 API 会话已验证。Clawd-managed in-process plugin 监听公开 `session/created`、`session/event`、`session/disposed`、可选 `sessionProjections.onChanged` 与 blocking `approval/request`；标题和上下文仅作为会话元数据同步，不占用生命周期 seq。状态按 session FIFO 上报并携带上游 seq；Clawd 不读取 `$DSH_HOME/storages` projection。普通审批进入独立 DSH `/permission` adapter，只支持人工 Allow Once / Deny；204 / 断连 / DND / disabled 都由 plugin `next()` 交还 DSH 原生 web answerer。`ask_user_question` 始终留在 DSH 原生 provider；DSH 不进入 `KNOWN_PERMISSION_AGENTS`，auto-tools / unattended / per-session grant 全部 DEFER。安装器通过官方 `dsh plugin --profile web add/remove` 管理 immutable marker-owned generation，foreign 同名包 fail closed；版本放行改成按 **小版本族（major.minor）**。维护两张表：一张是唯一写出具体版本/npm artifact/integrity 的已验证 artifact 清单（优先 `@deepseek-ai/dsh@0.2.0-rc.2`（integrity `sha512-EAJ3gPNcVt/uv8X19PMm9NkVhWgT7xXNMk0UKCVm+IQ5rpSQOcsMUa0HWlnYYVybKMsccjcRB21vVVsaXQ6IdA==`，2026-10-04 已做静态接口核对，并在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证了用 Clawd 安装器装出的 generation 的启动同步换代、会话状态、HUD 标题/上下文、Allow/Deny 与消息上的失败标记；其 `tool/result` 把失败标记放在消息 `message.isError` 而不是内容项上，bridge 新旧两种位置都认），并保留 `@deepseek-ai/dsh@0.1.5-rc.3`（integrity `sha512-c0W6Xqc4ChjFcCJkbzPeIxZQdnbKqe+QAcJzWGtogg0ZzsnZRcw3vopMyZ5oZU6E2fmyqGcyDR1sBeiCH4yHcg==`，2026-09-27 已在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证启动同步安装、会话状态、HUD 标题/上下文与 Allow/Deny）、`@deepseek-ai/dsh@0.1.5-rc.1`（integrity `sha512-rmNmzQCg3oIc1z8xH7izRSOuy1TNzq+/NILyfM+7e8DKOyV+yBtg47WEsqR2SiIe1ATec3L/rUa1YhIcfQ2XEg==`）、`@deepseek-ai/dsh@0.1.1-rc.2`（integrity `sha512-UP1UIh6q3Gme/yXRn/QL2P8IsVlv8Shpg22TRJIZPsCRWLm4CBiA1MUvXmJAfsOEETBMLAl+xWPtFw6ICsN3wg==`）与 `@deepseek-ai/dsh@0.1.0-rc.6`（integrity `sha512-brpZfED7ieRa2PQ5tUxMhHrM1pb2CmKFVM/f6yMULBDMicahk+Z2OsHgTwTDnoiZm23Ftu9rQz0NN4pflaoJcg==`）），一张是族表（`0.2` 下限 `0.2.0-rc.2`、`0.1` 下限 `0.1.0-rc.6`）。host 版本经严格解析（拒绝前导零、空预发布标识与 build 元数据）通过、major.minor 命中族、且不低于该族下限即放行；同一族内不同 host 版本共用一个 generation，出现新的小版本必须重新验证并新增一个族。旧的精确 `=<version>` marker 仍按原 range 核对哈希，新 generation 一律写族 range；Install/Repair 按 host 版本所在的族选择目标契约，Uninstall / 手动 npx 命令在 marker 版本已列入清单时钉它自己的 artifact，否则钉同族版本最高的已验证 artifact（无 CLI 且无 marker 时用首选族最新的并记为 assumed）；加锁前后比较的是实际检测到的 host 版本，不看族。DSH 的 `metadata_only` 标题/上下文旁路必须核对目标会话的 `agentId` 确为 `deepseek-harness`，撞名的其他 agent 会话直接丢弃。`47f9438` 仅是源码调查基线，不代表任何 tag/commit 映射。\n- DSH 每个 canonical `DSH_HOME` 的 mutation lock 只有在 owner/schema/token/PID/timestamp/owner-recorded operation timeout 合法、超过该 owner timeout 两倍、且 OS PID probe 明确为 `ESRCH` 时才允许 atomic-rename takeover；live、`EPERM`、unknown、corrupt/foreign owner 一律拒绝并返回精确 lock path。canonical lock 的 owner write/release 禁止 recursive cleanup。无全局 CLI 时生成的手动 npx generation 必须先在同一锁内写 owned reference，手动 add/remove 命令必须显式 pin shell-quoted canonical `DSH_HOME`；malformed/foreign/concurrently replaced reference 一律 fail closed 并保留 generation\n- DSH 桌面版支持（#1119）与 web 共用一个 agent id `deepseek-harness`：web profile 和 DeepSeek Harness 桌面版是两个承载方、各自一个 profile（桌面版是 `$DSH_HOME/profiles/desktop`），但在 Settings 和 Doctor 里仍是**一行**，显示名 `DeepSeek Harness (experimental)`，一次排队操作先 web 后 desktop、一边失败不影响另一边；安装只要有一边核实健康即成功（另一边失败变 warning + 常驻提示），卸载要所有 Clawd 注册都没了才成功。桌面版查找：macOS 用 `/Applications` 或 `~/Applications/DeepSeek Harness.app` 里自带的 `Contents/Resources/runtime/cli/bin/dsh`；Windows 按用户安装，从 `HKCU` 卸载项（显示名以 `DeepSeek Harness ` 开头）与 `%LOCALAPPDATA%\\Programs\\DeepSeek Harness` 找 `resources\\runtime\\cli\\bin\\dsh.cmd`，注册表用 PowerShell 读 UTF-8 JSON、不用 `reg.exe`；Linux 不支持桌面版。静态版本来自 `Info.plist` / 卸载项 `DisplayVersion`，真正动手前跑一次启动器 `--version` 核实。桌面版**永不用 npx**，手动 npx 命令与 manual reference 只属 web。每边角色是 `mutable` / `diagnose` / `not-applicable`：桌面版没装、或 profile 从未初始化（桌面版没打开过）→ 不适用并提示打开一次；foreign 同名包、文件读不了、清理残留、注册查不清、版本不支持、装了不止一个桌面版（`multiple-desktop-installs`）、桌面版找不到但注册还在（`carrier-unavailable`）、桌面版查不清（`desktop-unverifiable`）→ 只报告不动手。启动同步在集成已安装且启用时会把插件加进已初始化的桌面版 profile；桌面版开着也会加载新加的插件，只有插件更新（换了 generation）后要重启。常驻提示在 `hooks/dsh-notices.js`，按 profile 存 `notices-web.json`/`notices-desktop.json`，四种 kind（`restart-required`/`first-install`/`manual-command`/`failed-target`），写不进去只算 warning；提示显示在 Settings → AI Coding Tools 里这一行下面。Doctor 一行详情 `web: …; desktop: …`，状态取适用边里最差，只要有一边能尝试修复且不健康就给修复按钮（`src/doctor-detectors/agent-integrations.js`）。插件在 DSH 里被关掉（依赖在、bundle 行没了）时 `plugin add` 不会重开：显式修复先 remove 再 add（add 前先清掉上游 remove 留下的自有链接，Mac 是符号链接、Windows 是 junction），按 profile 记 `repair-operation-<profile>.json`，中断后下次显式修复续做，启动同步只报 `plugin-disabled-in-dsh`。`generations/` 两边共享，任一边有未处理状态（检查记录、清理残留、坏修复记录或 manual reference、读不了的 profile、符号链接 profile 目录）时清理暂停但不挡安装，卸载残留进 warnings。检查记录按 profile：web `inspection-required.json`、桌面版 `inspection-required-desktop.json`。`plugin add/remove` 写命令两边都超时 300 秒（web 原 120 秒），比上游写锁等待长。上游 `dsh plugin remove` 只清 `link:` 清单和锁、`node_modules` 链接会留下，Clawd 卸载自有插件时确认归属后清掉。Windows 静态查找是同步代码、不起进程，只读异步快照：启动时（不管 DSH 是否启用）、打开 Doctor 前、Agents 页手动扫描时刷新，没快照时桌面版显示\"查不清\"。安装检测把\"找到桌面版\"也算装了 DSH（`src/agent-installation-detector.js`）。桥接插件在 apply 时读 `ctx.profileContext?.name`，只有 desktop profile 才在 state / 审批载荷里带 `dsh_carrier: \"desktop\"`（metadata 不带；web 或未知 profile 一律不带）；Clawd 只接受 DSH + `dsh-plugin` + 本机 + 非 WSL 的载体，按生命周期覆盖或清除、不粘滞，权限 fallback entry 与快照（含签名）都带上它。点击桌面版会话时 `getSessionFocusTarget` 在 darwin/win32 返回 `dsh-desktop`（`dsh://open`），分派先 `shell.openExternal(\"dsh://open\")`，被拒绝再按 `discoverDshDesktopSync({ requireUniqueApp: true })` 的兜底要求唯一安装启动界面程序（macOS `open <appRoot>`、Windows 启动 `<appRoot>\\DeepSeek Harness.exe`，去掉 `ELECTRON_*`/`NODE_OPTIONS`，不用 CLI 启动方式；两份真实路径不同的有效安装视为有歧义，只要还有核实不了的候选也不自动启动，同一份安装的符号链接只算一份）；只能打开应用窗口、不会切到具体对话，web 会话仍不可跳；桌面版启动时会重新打开上次的对话，Clawd 只在这个对话有了动作（提问、工具调用、审批）之后才把它放进 Session HUD（`awaitingActivity` 并入快照 `hiddenFromHud`，但不关跳转；与 Kimi Code 共用同一个标记），Dashboard 照常列出、按钮照常可跳；2026-10-05 macOS 26.6.2 与 Windows 11 x64 源码运行真机验证（桌面版 `0.2.0-rc.2`）：别的窗口在前、最小化、关窗后，点击都经 `dsh://open` 把窗口带到最前；协议打不开时的启动兜底只有单元测试。真机证据：2026-10-04 macOS 源码运行（Clawd `ac64d726`，桌面版 `0.2.0-rc.2` + 全局 `@deepseek-ai/dsh@0.2.0-rc.2`）验证了启动同步把插件装进桌面版（与 web 共用 generation）并出现\"已装进桌面版\"提示、Doctor 一行两边正常，桌面版真实会话的 Allow 建成文件、Deny 后文件内容和 mtime 不变且 Clawd 显示 `PostToolUseFailure`，\"知道了\"后提示消失，改 bridge 源码（同 Clawd 版本）后启动同步两边报 `generation-conflict` 并提示去 Doctor 修复、修复把两边换到新 generation/删旧/出现\"重启桌面版后生效\"、重启后事件来自新宿主进程，设置页卸载后两边依赖与 bundle 行都没了、上游残留链接被清、generation 删除、两边提示清空，再在设置页安装两边都重新装上、桌面版重新出现\"已装进桌面版\"（\"经设置页首次安装\"因此已覆盖），开着 DND 时桌面版的工作区外写文件不弹 Clawd 气泡、返回 no-decision、桌面版弹自己的原生审批框、批准后文件建成且事件照常到达。2026-10-04 Windows 11 x64 经 SSH 用 Node 直跑安装器代码（管理员会话，桌面版在 `%LOCALAPPDATA%` 按用户安装 `0.2.0-rc.2`、全局 dsh `0.1.0-rc.6`，web 在 0.1 族、桌面版在 0.2 族）：PowerShell 读注册表找到桌面版、静态模式无快照时报\"查不清\"且不起进程、自带 `dsh.cmd`（带空格路径）`--version` 返回 `0.2.0-rc.2`、`dsh.cmd plugin --profile desktop add` 经 pnpm junction 装入并核实、记录\"已装进桌面版\"、两族各用一份 generation 并存、Doctor 一行两边有修复按钮、卸载桌面版清依赖与 bundle 行并清掉 `dsh plugin remove` 残留 junction、只删桌面版那份 generation 而保留 web 在用的；2026-10-04 另在 Windows 上以真 Clawd（Electron，源码运行、用户会话、普通权限）验证：先抓到一个只在 Electron 里出现的 bug（Electron 的 fs 把 `app.asar` 当目录、Windows 安装目录核实要求它是文件，于是在真 Clawd 里桌面版被判成没装，已在 `d8190692` 修成\"存在即可\"）；修好后桌面版一直开着（宿主进程未重启），启动同步把插件装进桌面版并记\"已装进桌面版\"，在桌面版新开对话的事件来自那个未重启的宿主进程，**Windows 上桌面版开着也会加载新加的插件**。**未覆盖**：Windows 上桌面版的审批、Windows 上的 Electron 界面（设置页提示、Doctor 窗口、启动预热）、打包后的 app、Linux、HTTP 204 交还与取消、装了多个桌面版。**管理员 junction 观察（推断）**：提升过的管理员进程在 Windows 11 上穿不过非管理员进程建的 junction（PowerShell \"untrusted mount point\"、Node `UNKNOWN`），该会话里 web 的旧 junction 读不到、web add 失败，桌面版同会话新建的 junction 正常；普通权限运行不受影响；由此推断以管理员身份运行 Clawd 可能把普通权限装好的插件读成缺失，未用以管理员身份运行的 Clawd 直接复现\n- OpenClaw 通过 `~/.openclaw/openclaw.json` plugin 路径做 state-only 集成；Phase 1 不做 permission bubble / terminal focus，主要支持本地 `openclaw tui --local`\n- Antigravity CLI (agy) 通过 `~/.gemini/config/hooks.json` 做 **state-only** hook 集成（PreInvocation / PostToolUse / PostInvocation / Stop），**不注册 PreToolUse**。agy LLM 会主动调内置 `ask_permission` 工具，触发 agy 自己的 5 选项 native menu（含 \"Persist to settings.json\" 持久白名单），Clawd 不插手权限决策也不双层确认。`agents/antigravity-cli.js` `capabilities.permissionApproval` / `interactiveBubble` 均为 false。\n- Qwen Code 通过 `~/.qwen/settings.json` 做 hook-only 集成（SessionStart / SessionEnd / UserPromptSubmit / PreToolUse / PostToolUse / Stop / Notification / PermissionRequest），支持状态与阻塞式 `PermissionRequest` 权限气泡；`disableAllHooks: true` 时注册条目不会触发。\n- QwenWork (千问办公) 通过 `~/.QwenWorkCN/settings.json` 做 **hook-only / state-only** 集成（agent id `qwenwork`；SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / Notification / PermissionRequest / PermissionDenied / SessionEnd）。`PermissionRequest` / `PermissionDenied` 只作为观察映射成 `working`（每任务 40+ 次，映射成 notification 会刷屏），hook stdout 恒为 `{}`：Clawd 不产生 allow/deny，不注册 `/permission`，也不进入 permission automation eligibility，唯一决策者是 QwenWork 原生权限流程；`agents/qwenwork.js` 的 `capabilities.permissionApproval` / `interactiveBubble` 均为 false。Windows command 必须保持 `windowsWrapper:\"portable\"`（QwenWork 经 POSIX shell 执行 command hook），PowerShell `-EncodedCommand` **只**用于识别并原地迁移旧条目，不是当前写入形态。marker 只认 `qwenwork-hook.js`，不得仅凭 `name:\"clawd\"` 删除用户 hook；混合 entry 中第三方 hook 原样保留。session id 命名空间是 `qwenwork:<raw>`；`~/.QwenWorkCN/workspace/<id>` 这类内部工作区 cwd 不做 basename 回退，避免 HUD/Dashboard 显示内部 ID。当前真实支持平台只有 macOS / Windows 桌面端（官方下载页 https://qwenwork.cn/download 只提供 macOS 14+ / Windows 10+ / HarmonyOS 6.1+，没有 Linux 客户端），因此 `processNames.linux`、resolver linux agent name 均为空，也不进 `src/wsl-deploy.js` 的 WSL Pair 映射。桌面主进程长驻、不代表 active turn，`startupRecoveryProcessNames` 全空、无 startup recovery。安装/卸载走 Settings → AI Coding Tools，或 `npm run install:qwenwork-hooks` / `npm run uninstall:qwenwork-hooks`；卸载必须同时在 `hooks/cleanup-integrations.js` 的 `MANAGED_AGENT_IDS` / `AGENT_CLEANERS` / `byAgent` 里有条目，否则 About cleanup 只会改 prefs、hook 留在磁盘上\n- ZCode 通过 `~/.zcode/cli/config.json` 的 `hooks.events.*` 集成全部 7 个支持事件（SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / PermissionRequest，无 SessionEnd / Notification）。PermissionRequest 为阻塞式权限审批：hook 长连接 `POST /permission`（HTTP 等待 590s，installer 注册 `timeoutMs: 600000`），有决定时 stdout 返回最小合法 `{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}`（deny 可带 `message`），无决定 / 超时 / 断连 / 任何错误输出 `{}` 并 exit 0，ZCode 回退原生权限流程；`interrupt` / `updatedInput` / `updatedPermissions` / `permissionUpdates` 必须 omit（最小输出 union 按 ZCode 3.5.x 严格 schema 约束；macOS ZCode 3.8.1 已完成真实 hook / 气泡 Allow/Deny 往返，3.5.x PermissionRequest 真机往返未覆盖）。超时单位陷阱：ZCode `timeout` 是秒、`timeoutMs` 才是毫秒，且超时按事件区分（PermissionRequest 600000、state 事件 8000）。Phase 2 只允许人工审批：ZCode 不进入 `KNOWN_PERMISSION_AGENTS`，global / per-session permission automation 在工具面与会话身份审计完成前全部 defer。prefs v14→v15 迁移把 Phase 1 持久化的 `zcode.permissionsEnabled:false` 翻 true（当时开关从未渲染、无用户意图）。配置必须有 `hooks.enabled=true` 才会执行；安装器只在该字段缺失时补 true，显式 `hooks.enabled=false` 或 Clawd 单项 hook 的 `enabled=false` 必须保留，Doctor warning 且不提供会覆盖用户选择的 Fix。ZCode 导入 Claude 配置后，只清理 `.zcode` 中明确引用 `clawd-hook.js` 的 Clawd-owned 条目，绝不改 `~/.claude/settings.json`。安全边界（复核后新增）：`/state` 生命周期 sweep 对 zcode（及 qwen/DSH 等 native-fallback adapter）只允许 no-decision，绝不伪 deny；hook 侧 `tool_input` 预算内原样发送、任何截断（长 Bash 尾部 `rm -rf` 场景）或序列化超 512KiB 一律 fail-closed 输出 `{}` 交还原生 UI；无 allow/answer/plan capability 的 interaction（如 ZCode 真实的 ExitPlanMode / AskUserQuestion）本地气泡与远程卡片都不提供决定入口、直接 204；全局气泡关闭只关本地窗口，Telegram/飞书 remote-only 审批仍可用（per-agent gate 关闭才是全退出）；installer 遇到 foreign `PermissionRequest` hook 时不注册自己的 blocking hook，若 foreign hook 后出现则移除自己的 managed hook（ZCode 同事件 hook 串行执行、后写覆盖，Clawd allow 会盖掉用户 hook 的 deny），Doctor 报 `permission-conflict` 且不给 Fix；六个 Phase 1 managed hook 全部显式 disabled 时新 PermissionRequest 继承 `enabled:false`；服务端 pre-parse 超限一律断连回退，不伪造 deny\n- Qoder / Qoder CN 共用 `qoder` agent，通过 `~/.qoder/settings.json` / `~/.qoder-cn/settings.json` 做 **state-only** hook 集成；各自尊重 `QODER_CONFIG_DIR` / `QODERCN_CONFIG_DIR`，同步所有已初始化目录，不创建缺失版本目录，卸载/cleanup 覆盖两版且只移除 Clawd entries，Doctor 不得让健康的一版掩盖另一版故障。Clawd 只把 `PermissionRequest` / `PermissionDenied` 当 notification 观察，**不替 Qoder 做权限决策**，hook stdout 恒为 `{}`；Windows command 必须保持 `windowsWrapper:\"portable\"`。session id 命名空间是 `qoder:<raw>`；启动恢复只认 CLI `qodercli` / `qoder-cli` / `qoderclicn`，不认闲置 IDE / CN 桌面进程；本机原生会话标题由 `src/qoder-session-title.js` 低频异步增量读取，通过 `updateSessionMetadata` 更新；SessionEnd / 禁用 / 退出取消旧读取，远端与 WSL 路径不在本机读取。2026-10-18 已核对 Windows CN runtime 1.1.69 的真实 SessionStart / UserPromptSubmit / Stop hooks，用户确认开启 Clawd Qoder 接入后任务状态恢复；macOS/Linux CN 未实测\n- TraeCode (Trae CN) 通过 `~/.trae-cn/hooks.json` 做 **hook-only / state-only** 集成。Windows command 必须保持 `windowsWrapper:\"encoded\"`：Trae 的 Windows Sandbox 会把 hook 命令作为 `trae-sandbox.exe --command-line` 的单个原生参数再次转发，普通引号或 `portable` 形态会在含空格路径处拆分；外层必须保持无引号的 PowerShell `-EncodedCommand`，POSIX 则继续使用普通 quoted command。该约束不适用于经 POSIX shell 执行 Windows hook 的 agent（如 Qoder / QwenWork）。\n- MiniMax Code 通过 `<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/` 的 **Clawd 独占本地插件**做 **state-only** 集成（manifest 用 `.claude-plugin/plugin.json`，hooks 文档按 MiniMax 的 CLAUDE sourceFormat 解析；不用 `.minimax-plugin/`，那会走 MINIMAX 格式：matcher 必须非空且不支持 exec-form args）。handler 固定 exec-form `command=node 路径 + args=[minimax-hook.js]`（spawn 直执行、无 shell、免引号），`timeout` 单位是秒且只接受 1–10 的整数（越界的 handler 被丢弃而不是钳制；SessionEnd 事件总预算仅 3s），因此 **PermissionRequest 物理上不可阻塞审批、完全不注册**，也没有 Notification 事件；hook stdout 恒为 `{}`（permissionDecision 缺省 abstain）。目录级所有权只认结构化凭据 `.clawd-managed.json`（`{app:\"clawd-on-desk\",integration:\"minimax\",managed:true,version:1}`，同 Pi 约定；MiniMax 只读 manifest 声明的文件，会忽略它），且凭据与所有受管理路径（`.claude-plugin/`、`hooks/` 及其文件）都不得是符号链接；目录名、manifest name、文档里的 basename/子串乃至整份文档指纹都永不授权改写或递归删除，缺凭据的目录（包括补丁前预发布构建写出的）一律 fail closed，只能手动删除后重装。staging / removal 目录固定落在数据目录（`plugins/` 之外，MiniMax 会把 `plugins/` 下每个目录项都当插件候选，含点号名）：首装在 staging 写全三份文件后一次 rename 发布（只覆盖空目标，非空目录/文件/链接拒绝；空 `clawd-state/` 视为未占用），失败时尽力删除 staging；已拥有的目录原地逐文件更新，中断后仍可证明归属、由下次安装补完。只有 ENOENT/ENOTDIR 算不存在，其他 lstat 错误按无法确认处理，绝不据此宣告卸载。卸载先把已验证目录 rename 出 `plugins/`、复验后再删；移走失败报 error 并保留安装意图，移走成功但删除失败时按已移除提交并在 warnings 里给出残留 `.clawd-minimax-removing-*` 路径，复验失败且移回失败时两个位置都报 `registrationRemoved:null` 并带 `residualPaths`；删不掉且目录仍运行 Clawd hook 时返回 `registrationRemoved:false`（读不清为 `null`），Settings / About 据此保留安装意图。删除后返回前还会复查一次原位置：此时若已有另一个 Clawd 实例重新发布的插件，报“仍在注册”（`registrationRemoved:false`）、不宣称卸载；这次复查是快照，复查之后、Settings 提交之前的安装不在本次结果里（多实例强一致需要覆盖 prefs 提交的跨进程锁，未做）。Settings 界面目前不显示成功结果里的 `warnings` / `residualPaths`：Agents 页安装/卸载只弹“已卸载/已安装”，About 清理只显示计数，只有命令行 cleanup 脚本会打印 warning。进程中途崩溃，或 staging 清理本身失败，可能在数据目录留下 `.clawd-minimax-staging-*` / `.clawd-minimax-removing-*`（MiniMax 不会加载，只能手动删除）；`plugins/` 与数据目录跨文件系统（EXDEV）时不支持。判断外来目录是否仍跑 Clawd hook 按 manifest 声明的 hooks 文档和 MiniMax 默认规则检查（含裸文档外壳、反斜杠路径，以及 shell 形式的 command / commandWindows handler）；Clawd 不建模的 manifest（根 `plugin.json` / `.minimax-plugin/` / `.codex-plugin/`）或读不清时按无法确认处理。node 探测失败时只保留全部 Clawd handler 一致、basename 为 node、存在且可执行、并通过 `node --version` 有界探测的已记录路径（exec-form 无 shell，Dock 启动的桌面 App 的 PATH 里没有 node），安装器与 Doctor 共用 `resolveDesiredNodeBin`。PostCompact 按 #406 上报 thinking（`trigger:\"manual\"` 时 idle），不是 attention。hook 的 `agentNames` 必须全小写（resolver 比较的是小写 basename），且不含桌面版的 “MiniMax Code Helper”：拉起 hook 的 NodeService helper 可能在 App 运行中重启，把它当 agent 会误删活会话，识别应落到长驻的主程序；mcode CLI 启动时执行 `process.title = \"minimax-code\"`，macOS/Linux 上 `ps` 报告的进程名就是 `minimax-code`（按名字匹配），Windows 上仍是 node.exe，靠 `agentCmdlineCheck` 只看 argv 里的脚本位置识别（命令行检查的进程名沿用共享默认 `DEFAULT_AGENT_CMDLINE_NAMES`，已含 Linux 上新版 Node 的主线程名 `mainthread` / `node-mainthread`，MiniMax 不再自带名单）（`node` 后的脚本 basename 是 `mcode`/`minimax-code` 启动器，或脚本路径含 `/@minimax-ai/code/` / `/.minimax-code/`），参数里的目录片段不算——MiniMax 退出时不发 SessionEnd，没有 agent pid 会话就无法按 agent-exit 清理。hook 不触发时的启用步骤在 MiniMax 应用内（`mcode plugin enable clawd-state@local` 或插件面板），磁盘上读不到启用状态，Doctor/Settings 只能提示。session id 命名空间 `minimax:<raw>`，标题走首行 prompt 派生 + 服务端 first-wins（同 traecode）。\n- Kimi Code（agent id `kimi-cli`）的 agent pid 靠进程名识别：CLI 启动即 `process.title = \"kimi-code\"`，libuv 把标题写回原 argv 所占的空间、放不下就截断，所以 macOS/Linux 上 `ps` 与 `pgrep -x` 看到的名字随启动命令长短而变（0.42.0 原生版实测：`kimi` 仍是 `kimi`，`kimi -c` 是 `kimi-co`，`kimi --yolo` 或全路径启动是 `kimi-code`；只有整条启动命令比 `kimi` 还短时（例如不带参数的软链接 `k`）才认不出，`k -c` 显示的已经是 `kimi`）。`hooks/kimi-process-names.js` 必须列全从 `kimi` 到 `kimi-code` 的每一种截断，resolver 与 startup recovery 共用这一组，只写 `kimi-code` 会漏掉 `kimi -c`。拉起 hook 的就是这个改名后的主进程（TUI 在进程内跑 agent 引擎，从 SessionStart 到 SessionEnd 同一个 PID）；其他同名进程（后台更新下载器、经 kimi 二进制跑的插件进程等）都是它的子进程，不跑 hook。resolver 比较小写 basename，macOS 桌面版 `Kimi Code.app` 写成 `kimi code`（它的 agent server 跑在主进程里，hook 由主进程直接拉起）；桌面版关窗后常驻托盘、不代表在干活，同其他桌面 App 一样不进 startup recovery。Windows 上标题只改控制台标题：原生版仍是 `kimi.exe`，npm 版仍是 `node.exe`，命令行检查只认包目录 `/@moonshot-ai/kimi-code/`，不能退回“含 kimi 就算”（Kimi 本身没被认出时，任何命令行提到 kimi 的 node 祖先都会被当成 agent）。Kimi Code 正常 `/exit` 会发 SessionEnd，但关终端、`kill`（0.42.0 实测：SIGTERM 与 SIGKILL 都不发；源码里 SIGTERM 注册了 `stop(143)`，实测为什么没发 SessionEnd 还没查清）、崩溃都不发；没有 agent pid 的会话只要终端 App 还开着就一直留在列表里。桌面端启动时会恢复上次查看的对话、在侧栏点开旧对话也一样，这类只发一条 SessionStart、还没有任何动作的对话不进 Session HUD，Dashboard 照常列出、按钮照常可跳，出现提问/工具/审批/Stop 等动作后自动进 HUD（与 DSH 共用同一个 `awaitingActivity` 标记）。\n- HTTP 服务端口范围固定为 `127.0.0.1:23333-23337`；运行时端口写入 `~/.clawd/runtime.json`\n- Mobile Preview 是独立的 LAN listener，候选范围为 `0.0.0.0:23334-23338`；它不写 `runtime.json`，不得把该范围误写成 hook / custom-agent HTTP ingress 范围\n- 自定义 HTTP Agent 的 sender 必须读取 `~/.clawd/runtime.json`，不能把 23333 写死；注册不等于已连接。custom v1 只支持 `/state`，不支持 `/permission`\n- CodeBuddy PermissionRequest hook 的所有权只认本机 managed URL 或 marker `clawd-on-desk.permission.v1`；纯 `name:\"clawd\"` 不能触发改写/删除。裸 CLI 和 WSL 默认 preserve，Settings/startup/repair 必须显式传 local/custom permission target\n- Remote SSH 的远端 Node 探测要求 Node >= 14；Node discovery/version validation 只在 `src/remote-ssh-node.js`，ordinary tunnel health 与 serialized readiness 在 `src/remote-ssh-runtime.js`，不得互相复制或从已停用脚本另起实现\n- 注册 Claude Code hook 必须 marker-scoped merge：只可更新/删除含 `clawd-hook.js` / `auto-start.js` marker 的 Clawd-owned entry，不得整体覆盖数组或改动无 marker 的用户 entry\n- 注册 Claude Code statusLine 默认只接管空槽或自己的槽（marker `claude-statusline.js`）；本机 Settings 显式开启采集遇到第三方槽时，必须经共存确认并复核原槽指纹，使用 `--local-chain` 和独立的 `clawd-statusline-local-chain.json` 保存/恢复完整原对象。启动/自动修复不得自行取得第三方槽；恢复记录缺失、损坏或不匹配时 fail closed 并保留现场。远程部署仍用 profile 的 `chainStatusline` opt-in 和既有 `--chain` sidecar，不与本机记录混用。订阅配额通过 `metadata_only` POST 进入 session-independent `updateAccountQuota` per-source store；不要把 quota 塞进 `updateSession` opts，也不要以 session 存活作为摄入前提\n- Copilot CLI hooks 走按需自动同步：`hooks/copilot-install.js` 在本地启动仅当 Copilot CLI 已安装且已启用时调用；远端由 Settings Remote SSH deploy controller 调用。路径解析尊重 `COPILOT_HOME` env（trimmed 非空才生效，否则 fallback 到 `~/.copilot`）；`hooks/copilot-hook.js` 的 session-state resolver 同样走 env\n- Remote SSH 的 effective transport 由 `ssh -G` 只读检查决定：ordinary SSH 在没有 retained serialized occupancy 时保持 `context:null` 的 parallel 路径；serialized transport 以有效 target key（不是 profile id）互斥。所有 serialized managed SSH/SCP child 必须持 coordinator 发出的有效 connection/operation context，并通过其 pre-spawn gateway 启动；用户交互终端只有命中 serialized/retained occupancy 时才要求 coordinator 判定 target 完全 idle\n- serialized persistent tunnel 使用同一条 SSH 内嵌 readiness；暂停通过 stdin EOF 请求自然退出并等待 `close`。强杀或带 signal 的 outer `ssh.exe` close 不能证明 nested ProxyCommand 已 drain；timeout/未验证 drain 必须 quarantine，期间禁止新 child、mutation、resume 或 interactive terminal\n- mutation 在 deploy-lock acquire-attempted / lock-owned 后遇到 exit 255、EOF/reset、signal 或其他 unknown result 时不得自动 replay、retry、release lock 或恢复连接；必须保留 primary error 并传播 recovery state，必要时要求 `manual_lock_inspection_required`\n- Remote SSH secure hook 必须同时携带 `CLAWD_REMOTE=1` 与 `CLAWD_SSH_REMOTE=1`，只读 layout identity 并 pin 精确端口；identity 缺失/损坏/不可读必须 fail closed，禁止回退端口扫描\n- Remote SSH deploy-lock acquisition 必须原子化；成功 acquire 后的每个 live mutation 都要在同一远端命令内 fencing 校验，cleanup 还必须锁内重读 installId/profileId/runtimeKey/layoutVersion 所有权。无身份、冲突、ownerless/corrupt lock 均不得自动接管\n- 默认 `account-default` 只支持不同 Unix 账号；同 Unix 账号冲突必须阻止。`profile-isolated` 在真实 SSH/CLI 矩阵完成前由 `CLAWD_ENABLE_EXPERIMENTAL_REMOTE_ISOLATION=1` 发布门隐藏；它只隔离用户级 CLI config/session/runtime 与 Clawd 路由，不代表完整 HOME 或同 UID 安全隔离，project 配置/部分 cache/macOS Claude Keychain auth 仍可能共享\n- Hermes Agent 的 Remote SSH 部署是 `secureDeploy` 内的 `hermes-files` → `install-hermes` 两个阶段，复用同一条 serialized transport、deploy lease、fencing 与所有权检查，没有独立的 Hermes SSH deployer：secure 模式由每个托管 `plugins/clawd-on-desk/` 内的 plugin-local marker `clawd-ssh-secure-v1` latch，latch 后 identity 必须在每次 state/probe/permission 请求时重新读取（禁止 `(mtime,size)` 缓存），且不得发送任何远端 PID / 进程树 metadata；plugin 资产走独立 staging 目录，清理只 `rm -f` 精确文件再 `rmdir`，禁止 `rm -rf`；`REMOTE_IDENTITY_STEP_NAMES` 保持冻结的 8 步不变，不得加入 `installHermes`；Clawd 绝不自动重启 Hermes gateway，托管模块被替换时只报告需要手动重启\n- 禁用 agent 不应卸载 hooks / plugins / extensions：只停止对应 monitor、清理 session / bubble、让 HTTP hook 入口快速 fallback；重新启用未安装 agent 不触发本机 integration sync。卸载集成必须走 Settings Agent 页的 Uninstall / 对应 uninstall 命令，并同时清掉 `integrationInstalled`\n- Kiro 的 `sessionId=\"default\"` 会复用；session alias key 必须按 cwd scope 区分，同时保留旧 `local|kiro-cli|default` 只读 fallback\n- Windows NSIS release 必须产出明确架构的 x64 / ARM64 安装包：`win.artifactName` 保留 `${arch}`，`nsis.buildUniversalInstaller` 保持 `false`\n- 每个 release target 只能保留一个匹配目标架构的 Koffi `koffi.node`；`afterPack` 只允许剪裁 `app.asar.unpacked` 的物理文件，禁止重写 `app.asar`，并必须通过完整 native inventory audit（唯一常设例外是 electron-builder 管理的 Windows ia32 `resources/elevate.exe`）\n- 资源路径统一用 `path.join(__dirname, ...)`\n- 需要编辑发布素材时，先复制到 `assets/source/` 再改，不要直接改工作素材来源不明的文件\n- `assets/source/cloudling-pointer-bridge/` 是 Cloudling 指针桥素材的保留源文件目录；运行时逻辑已内联进主题 SVG，不要把这个 source 目录当临时文件清理\n- 主题状态、sleep/DND、mini mode、状态映射的细节在 `docs/project/theme-state-ui.md`\n- 官方可下载主题（`official-theme-*`）是受管分发层，不是 built-in、也不提升信任：catalog 是固定远端小目录（renderer 只能传 themeId），下载走 Electron main `net.request` 的 manual redirect + 精确 CDN host allowlist + 固定 bytes/SHA-256（未支持 host 返回稳定 `DOWNLOAD_HOST_UNSUPPORTED`，不允许 catalog 扩展 allowlist），ZIP 只在 manager 专属 staging 内流式解压并以 marker-before-rename 同卷提交，最终以 `isBuiltin=false` 加载（`trustedRuntime` 无效）。`setThemeSelection` / `removeTheme` / `officialTheme.commitInstall` / `officialTheme.uninstall` / `theme` update 共用 `lockKey=\"theme\"`；卸载 active 主题必须等 `waitForThemeReloadSettled()`。主仓库附带一份目录快照 `src/official-theme-catalog-snapshot.json`：网络拉取失败时列表先用上一次成功加载的目录（内存 LKG 或磁盘缓存），都没有才用快照；第一次拉取有结果之前（`uninitialized`）不用快照；快照**不作安装依据**，安装仍只认经校验的网络/磁盘目录。快照只作列表回落（仍显示 `offline` 和重试），不含素材与预览图，不写磁盘缓存，且参与版本不能回退的比较；发布前用 `npm run update:official-theme-snapshot` 刷新。不要把 Hash Sage / Whale-chan 的动画素材（APNG / WebP），或把它们写成内置主题的文案带回主仓库\n- Settings 体系里，store 是唯一真相，controller 是唯一写入者；不要绕开 `settings-controller.js`\n- Dashboard 数字快选是**完整 Dashboard 同一页面的临时键盘模式，仅 macOS/Windows**；Linux 明确 NOT SUPPORTED（不是待验证）。平台 gate 的唯一真相是 `shortcut-actions.js` 的 `supportedPlatforms` + `isShortcutActionSupported()`，Settings 展示、globalShortcut 注册/录制、设置命令和冲突占用都必须服从它；遗留的不支持绑定只忽略执行，不删用户 prefs、不占其他快捷键。darwin/win32 的 Dashboard 页面活在 `WebContentsView` 里，`BrowserWindow.fromWebContents()` 对它返回 null、BaseWindow 不触发 `ready-to-show`；页面 WC 一律从 owner 取。禁止用 `hide()`+`showInactive()` 归还已显示的普通宿主（实测会遮挡来源窗口），只能 opacity/input parking 并幂等恢复捕获值。详见 `docs/project/theme-state-ui.md`\n\n## Testing\n\n- 自动化测试使用 Node 内置 test runner：`npm test`\n- `test/*.test.js` 覆盖核心 unit/contract、installer、route、UI/runtime 与 Remote SSH transport/coordinator/identity；部分 fixture 会启动 Node、shell 或 Git Bash 子进程，缺少依赖时可能 skip，不能把全套结果概括成纯逻辑或等价真机验证\n- Remote SSH 真机矩阵与记录在 `scripts/manual/README.md`；Windows OpenSSH + Codespaces stdio 边界及 ordinary-host V15 release gate 不能从 unit tests 互相推断，无法执行时必须明确记录 pending / residual risk\n- Windows Terminal 真机、GUI smoke 与清理必须假定多个 tab/window 共享进程：不得按 PID/进程名 `taskkill`、`Stop-Process` 或宽泛终止 WindowsTerminal、Codex、`cmd.exe`、`ssh.exe`、OpenConsole、conhost。测试终端只能在明确 test-owned session 内 `exit`；无法证明 ownership 就保留现场并请用户手动关闭\n- 当前开发环境是 Windows-first；macOS 特定路径无法在这里手动 QA，改到 mac 逻辑时要用 code-review\n\n<!-- File: CLAUDE.md (Tokens: ~24025 | Category: claude-rule) -->\n# AGENTS.md\n\nThis file is the entry point for coding agents working in this repository. Keep it short and operational. Durable architecture lives in `docs/project/`; `docs/plans/` and `docs/investigations/` are historical evidence unless this file explicitly links them.\n\n## Project Overview\n\nClawd 是一个 Electron 桌宠：通过 hook、日志轮询、plugin 和 extension 感知 AI coding agent 的工作状态，并播放像素风动画。当前支持 Claude Code、Codex CLI、Copilot CLI、Gemini CLI、Antigravity CLI (agy)、Cursor Agent、CodeBuddy、WorkBuddy、Grok Build、Kiro CLI、KiroCrew、Kimi Code CLI (Kimi-CLI)、Qwen Code、ZCode、CodeWhale、opencode、MiMo Code、Pi、OMP (oh-my-pi)、OpenClaw、Hermes Agent、Qoder、QoderWork、QwenWork (千问办公)、Reasonix、DeepSeek Harness、TraeCode (Trae CN)、MiniMax Code；内置 Clawd / Calico / Cloudling 三套主题，支持用户主题，并可经 Settings 从独立 `rullerzhou-afk/clawd-themes` 仓库下载可选官方主题（Hash Sage、Whale-chan，external theme 权限、可卸载）；平台覆盖 Windows、macOS、Linux，UI 支持 en / zh / zh-TW / ko / ja / pt-BR / es。\n\n## Common Commands\n\n```bash\nnpm start\nnpm run build                  # default Windows package\nnpm run build:win:x64\nnpm run build:win:arm64\nnpm run build:win:all\nnpm run build:mac\nnpm run build:linux\nnpm run build:all\nnpm install\nnpm test\nnpm run verify:electron\nnpm run verify:release\nnpm run audit:assets\nnpm run audit:pr-history-assets\nnpm run audit:native-package -- --app-root <extracted-app-root> --target <target-id>\nnpm run create-theme\n\nnpm run install:claude-hooks\nnpm run uninstall:claude-hooks\nnpm run install:cursor-hooks\nnpm run install:gemini-hooks\nnpm run install:antigravity-hooks\nnpm run install:kiro-hooks\nnpm run install:kirocrew-hooks\nnpm run uninstall:kirocrew-hooks\nnpm run install:kimi-hooks\nnpm run install:qwen-hooks\nnpm run install:zcode-hooks\nnpm run uninstall:zcode-hooks\nnpm run install:codewhale-hooks\nnpm run uninstall:codewhale-hooks\nnpm run install:pi-extension\nnpm run uninstall:pi-extension\nnpm run install:omp-extension\nnpm run uninstall:omp-extension\nnpm run install:openclaw-plugin\nnpm run uninstall:openclaw-plugin\nnpm run install:hermes-plugin\nnpm run uninstall:hermes-plugin\nnpm run install:qoder-hooks\nnpm run uninstall:qoder-hooks\nnpm run install:qoderwork-hooks\nnpm run uninstall:qoderwork-hooks\nnpm run install:qwenwork-hooks\nnpm run uninstall:qwenwork-hooks\nnpm run install:reasonix-hooks\nnpm run uninstall:reasonix-hooks\nnpm run install:workbuddy-hooks\nnpm run uninstall:workbuddy-hooks\nnpm run install:grok-hooks\nnpm run uninstall:grok-hooks\nnpm run install:dsh\nnpm run uninstall:dsh\nnpm run install:codex-hooks\nnpm run uninstall:codex-hooks\nnpm run install:codex-debug-hooks\nnpm run uninstall:codex-debug-hooks\nnpm run install:mimocode-plugin\nnpm run uninstall:mimocode-plugin\nnode hooks/codebuddy-install.js\nnode hooks/opencode-install.js\n\nbash test-demo.sh [seconds]\nbash test-mini.sh [seconds]\nbash test-macos.sh\nbash test-oneshot-gate.sh [state] [seconds]\n```\n\n新安装默认只把 Claude Code 和 Codex 标记为已安装并启用；其他 agent 默认未安装、未启用。正常启动时，Clawd 只会为 `integrationInstalled=true` 且 `enabled=true` 的 agent 自动同步 Claude / Codex / Copilot / Gemini / Antigravity / Cursor / CodeBuddy / WorkBuddy / Grok Build / Kiro / KiroCrew / Kimi / Qwen / ZCode / CodeWhale / Qoder / QoderWork / QwenWork / Reasonix / TraeCode / MiniMax Code hooks、opencode / MiMo Code / OpenClaw / Hermes plugins 和 Pi / OMP extensions。Settings Agent 页的 Install 会安装并启用该集成；Uninstall 会卸载 Clawd 管理的 hook/plugin/extension，并同时把该 agent 设为未安装、未启用。单独关闭 enabled 只会跳过启动同步并屏蔽事件/权限入口，不卸载用户已有 hooks / plugins / extensions；重新启用未安装 agent 只打开事件入口，不会写本机集成文件。手动安装命令主要用于调试、重装或远程部署。\nSettings 注册的自定义 HTTP Agent 是独立模型：`customApplications` 是注册真相，对应 `agents[customId]` 必须显式保持 `integrationInstalled=false`。注册只分配 ID 和状态入口，不安装 hook、不观察进程；v1 仅允许已注册且启用的 ID 向 `/state` 上报，`/permission` 永远不提供决定。删除或伪造的 `custom-` ID 必须直接拒绝，不能降级成 Claude Code subagent。\nCopilot CLI 同步走 `<COPILOT_HOME 或 ~/.copilot>/hooks/hooks.json`，marker-based 增量合并只接管含 `copilot-hook.js` 标记的条目，用户其他 entry / 其他 `hooks/*.json` 文件原样保留；hooks.json 或 `settings.json` 顶层 `disableAllHooks: true` 时 doctor 报 warning（不挂 Fix 按钮）。详见 `docs/guides/copilot-setup.md`。\n\n## Read These Docs\n\n- `docs/project/agent-runtime-architecture.md`：运行时架构、模块边界、启动与数据流、多 agent、permission bubble、终端聚焦和自动同步\n- `docs/project/theme-state-ui.md`：状态机、主题系统、settings、mini mode、素材规则、平台限制、待落地 UI 决策\n- `docs/project/release-process.md`：发版 checklist、release note 核对、tag 触发 GitHub 打包和资产确认\n- `docs/guides/copilot-setup.md`：Copilot CLI 自动同步说明、`COPILOT_HOME` 兼容性、手动配置备选模板\n- `docs/guides/dsh-setup.md`：DeepSeek Harness web profile 与桌面版的实验性 plugin 集成状态与普通审批集成\n- `docs/guides/state-mapping.md`：状态 → 动画权威表\n- `docs/guides/guide-theme-creation.md`：主题作者指南\n- `docs/guides/setup-guide.md`：安装、远程 SSH、各 agent 接入\n- `docs/guides/custom-agent-http.md`：自定义 HTTP Agent 的 state-only 接入合约和动态端口发现\n- `docs/guides/known-limitations.md`：用户向已知限制\n- `docs/guides/recap.md`：本地小结的指标口径、coverage、时区/DST、隐私存储与产品红线\n- `docs/guides/codex-wsl-clarification.md`：Codex / WSL 路径与 Node 说明\n- `docs/guides/guide-remote-ssh.md`：Remote SSH 用户流程、Codespaces 单会话 transport 与共享主机边界\n- `docs/guides/telegram-approval.md` / `docs/guides/feishu-lark-remote-approval.md`：远程审批设置与失败回退语义\n- `docs/guides/roam-fence.md`：自由漫游与可选围栏\n\n## Runtime Summary\n\n- HTTP hook / plugin 主路径：`src/server.js` → `src/server-route-state.js` → `src/agent-runtime-main.js` → `src/state.js` → IPC；本地 JSONL monitor 直接进入 `agent-runtime-main`，不经过 HTTP server\n- 权限主路径：`src/server-route-permission.js` → `src/permission.js`；本地 bubble、显式 permission automation 与可选 Telegram / 飞书 Lark 远程审批都可能产生真实决定\n- 桌宠的渲染/输入双窗口由 `src/pet-window-runtime.js` 统一创建和定位；浮层排序与 topmost 行为在 `src/floating-window-runtime.js` / `src/topmost-runtime.js`\n- `src/state.js` 生成的 session snapshot 是 Dashboard、HUD/Orbit 与可选通知/presence/mobile consumer 的共享合约，改字段必须检查所有消费者\n- `src/integration-sync.js` 为已安装且启用的 agent 异步同步 hooks / plugins / extensions；Codex official hooks 为 primary，JSONL 轮询保留为 fallback\n- Claude hook 恢复由 `src/claude-settings-watcher.js` 的目录 watcher + 低频只读巡检共同负责；repair 统一经过 `src/claude-hook-operations.js` 队列并复验，连续失败转 `manual-fix-required`。完整 gate、阈值与 source-missing 语义见 `docs/project/agent-runtime-architecture.md`\n- `src/agent-gate.js` 控制各 agent 的安装意图、启用状态、权限气泡开关和 wait-for-input notification 子开关\n- 设置系统主链路是 `src/prefs.js` → `src/settings-controller.js`（唯一写入者）→ `src/settings-store.js`；`settings-actions*` 负责校验和 pre-commit gates，`settings-effect-router.js` 负责 post-commit runtime effects 与广播\n- 启动时还会尝试自动安装 VS Code / Cursor terminal-focus extension，并初始化 updater\n- Remote SSH 通过 effective transport inspection 区分 ordinary parallel SSH 与 serialized transport；后者由 target-scoped coordinator 编排。远程部署只走 Settings，`scripts/remote-deploy.sh` 已 fail-fast 停用\n\n## Core Files\n\n更细的背景见 `docs/project/agent-runtime-architecture.md` 和 `docs/project/theme-state-ui.md`。\n\n| File | Responsibility |\n|------|------|\n| `src/main.js` | Electron composition root：生命周期、上下文组装与各 runtime / IPC 注册器接线 |\n| `src/server.js` + `src/server-route-state.js` + `src/server-route-permission.js` | HTTP 服务、端口发现、`/state` / `/permission` 路由 |\n| `src/agent-runtime-main.js` + `src/integration-sync.js` | local monitor / official hook 仲裁、Codex turn fence、按 gate 的集成同步 |\n| `src/state.js` | 状态机、多会话合并、优先级、自动回退、睡眠/DND |\n| `src/renderer.js` | 动画切换、SVG 预加载、眼球追踪渲染 |\n| `src/permission.js` + `src/permission-automation-policy.js` + `src/session-automation-coordinator.js` | 权限气泡、自动化策略、per-session 授权与决策回包；远程 client 由 `main.js` 注入 |\n| `src/pet-window-runtime.js` + `src/floating-window-runtime.js` + `src/topmost-runtime.js` | 双窗口 owner、浮层重排、z-order / fullscreen / focusability |\n| `src/update-bubble.js` | 更新气泡创建、测高、跟随桌宠定位，避让 HUD / permission stack |\n| `src/dashboard.js` + `src/dashboard-renderer.js` | Sessions Dashboard 唯一 owner：会话列表、别名编辑、终端跳转、几何持久化，以及同一页面的临时键盘模式 |\n| `src/dashboard-host.js` | Dashboard 普通宿主的平台封装：darwin/win32 用 `BaseWindow + WebContentsView`（无 `ready-to-show`），Linux 保留 `BrowserWindow` |\n| `src/dashboard-quick-mode.js` | 完整 Dashboard 的 1–9 键盘模式（**macOS/Windows only**）：quick 宿主、opacity/input parking、轮次栅栏与冻结数字映射；Windows 显式取消与页面失效的来源恢复在 `src/quick-select-origin-focus.js`，quick 宿主的退出清理挂在 `before-quit` |\n| `src/session-hud.js` + `src/session-hud-renderer.js` | 桌宠旁轻量会话 HUD、折叠行、点击跳转 |\n| `src/session-alias.js` | session alias key 规范化、TTL pruning、Kiro cwd scope |\n| `src/theme-loader.js` + `src/theme-runtime.js` | stateless 主题加载/消毒与唯一 active-theme owner；`waitForThemeReloadSettled` 完成信号 |\n| `src/official-theme-catalog.js` / `-download.js` / `-installer.js` / `-main.js` | 官方可下载主题：严格 catalog/cache、Electron `net.request` 流式下载、受限流式 ZIP 解压与 marker-before-rename、main owner/IPC/共享 `theme` lock |\n| `src/prefs.js` | 偏好 schema、load/save/migrate/validate，设置持久化入口 |\n| `src/settings-actions*.js` + `src/settings-effect-router.js` | 设置 validators / commands / pre-commit gates 与 post-commit runtime effects |\n| `src/settings-controller.js` | 设置系统唯一写入者 |\n| `src/settings-store.js` | 不可变 snapshot store |\n| `src/settings-ui-core.js` + `src/settings-renderer.js` + `src/settings-tab-*.js` | Settings shared UI state、侧栏/tab shell 与各页逻辑 |\n| `src/menu.js` | 托盘 / 右键菜单，串起设置、Dashboard、mini mode、更新入口 |\n| `src/mini.js` | 极简模式入场、滑动、peek、状态映射 |\n| `src/tick.js` | 主循环、鼠标轮询、眼球和 idle/sleep 逻辑 |\n| `src/drag-position.js` | 拖拽落点规范化与跨显示器钳制 |\n| `src/visible-margins.js` | 可视角色边距与 edge pinning 规则 |\n| `src/updater.js` | Git 模式 / `electron-updater` 双路径更新逻辑 |\n| `src/focus.js` | 终端聚焦 |\n| `src/hit-renderer.js` + `src/hit-geometry.js` | 输入窗口命中、拖拽、连击反应 |\n| `src/remote-ssh-runtime.js` | Remote SSH tunnel/ingress 状态机、ordinary health probe、serialized readiness 与重连 |\n| `src/remote-ssh-transport.js` + `src/remote-ssh-transport-coordinator.js` | effective transport inspection、pre-spawn admission、target ownership、drain barrier 与 quarantine |\n| `src/remote-ssh-deploy.js` | Deploy / Repair、身份事务、lease/fencing、wrapper、cleanup 与远端 Codex monitor mutation |\n| `src/remote-ssh-identity.js` + `src/remote-ssh-layout.js` + `src/remote-ssh-ingress.js` | 身份/布局真相与 profile 专属、nonce 校验的本地 ingress |\n| `src/remote-ssh-node.js` + `src/remote-ssh-shell-detect.js` + `src/remote-ssh-local-config.js` | 远端 Node/ shell 探测与本机 SSH config 入口 |\n| `src/remote-ssh-profile.js` | Remote SSH profile schema、校验、默认值和持久化规范化 |\n| `src/remote-ssh-ipc.js` | Remote SSH runtime / deploy / monitor orchestration、intent policy、IPC 状态与进度广播 |\n| `src/remote-ssh-quote.js` | Remote SSH 终端命令与跨平台 shell quoting helper |\n| `agents/registry.js` | agent 注册表 |\n| `agents/codex-log-monitor.js` | Codex JSONL fallback 轮询 |\n| `agents/gemini-log-monitor.js` | legacy Gemini session JSON 轮询器；当前 Gemini hook-only 路径不启动 |\n| `hooks/dsh-install.js` | DeepSeek Harness immutable managed bridge generation、ownership verify、web 与 desktop 两个 profile 的安装 / 修复 / 卸载编排 |\n| `hooks/kirocrew-install.js` + `hooks/kirocrew-store.js` | KiroCrew state-only gateway hooks、upstream-compatible mutation locks and atomic private store writes |\n| `hooks/kirocrew-hook.js` + `hooks/kirocrew-command.js` | KiroCrew state bridge and exact command-shape ownership classifier |\n| `hooks/dsh-notices.js` | DeepSeek Harness 常驻提示的存储与规则（按 profile 的 `notices-<profile>.json`） |\n| `hooks/clawd-hook.js` + `hooks/copilot-hook.js` | Claude Code / Copilot CLI 状态上报脚本 |\n| `hooks/install.js` | Claude hook 注册 / 卸载 |\n| `hooks/auto-start.js` | Claude `SessionStart` 自动拉起 Clawd 的 hook |\n| `hooks/codex-hook.js` / `hooks/codex-install.js` | Codex official hooks 状态与权限审批、安装 / 卸载 |\n| `hooks/cursor-install.js` / `gemini-install.js` / `antigravity-install.js` / `kiro-install.js` / `kimi-install.js` / `qwen-code-install.js` / `codewhale-install.js` / `codebuddy-install.js` / `workbuddy-install.js` / `opencode-install.js` / `pi-install.js` / `openclaw-install.js` / `hermes-install.js` / `qoder-install.js` / `qoderwork-install.js` / `reasonix-install.js` | 各 agent 集成安装逻辑 |\n| `hooks/opencode-family-managed-generation.js` | OpenCode 用户可写托管 generation（canonicalizer、bundle/manifest、stage/promote、target owner record、target-scoped lock）；纯 Node 内置依赖，不进入 Remote SSH `HOOK_FILES` |\n| `hooks/opencode-family-entry-ownership.js` | OpenCode-family plugin entry 的 string/tuple 解析、跨平台路径等价、所有权分类与重复/options 冲突规划（纯逻辑、可注入 fs） |\n| `hooks/opencode-family-install.js` / `hooks/opencode-family-jsonc.js` | 家族注册器：`managedMaterialization:true` 走托管 generation 事务 + 共享 entry planner；`false` 保持 legacy broad-basename register/unregister |\n| `src/doctor-detectors/opencode-managed-inspector.js` | managed OpenCode Doctor inspector（ownership/manifest/生成结构、Fix policy、masked supplementary warning）；接受注入 fs |\n| `hooks/workbuddy-hook.js` | WorkBuddy state + Notification command hook；无 session_id 时返回合法 stdout 后丢弃事件 |\n| `hooks/grok-hook.js` / `hooks/grok-install.js` | Grok Build state + Notification command hook；写入 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json`；`env` marker `CLAWD_GROK_HOOK=v1` 所有权；无 session id 时丢弃；不注册 `/permission` |\n| `hooks/zcode-hook.js` / `hooks/zcode-install.js` | ZCode 状态 + 阻塞式 PermissionRequest hooks（`hookSpecificOutput` 决定 / `{}` 无决定）、`hooks.events.*` 按事件超时增量注册与 Claude-imported Clawd hook 清理 |\n| `hooks/qoder-hook.js` | Qoder state-only 状态上报脚本（Phase 1，stdout 恒为 `{}`） |\n| `hooks/minimax-hook.js` / `hooks/minimax-install.js` | MiniMax Code state-only 本地插件：整目录 install/uninstall（`<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/`），CLAUDE 格式 hooks + exec-form args，10 事件无 PermissionRequest/Notification，`.clawd-managed.json` 结构化所有权凭据、fail closed |\n| `hooks/codex-remote-monitor.js` | 远程 Codex JSONL 轮询并通过 SSH 隧道回传（含 token_count 订阅配额的 metadata_only 上报） |\n| `hooks/claude-statusline.js` / `hooks/antigravity-statusline.js` | 各 CLI statusline 适配器：渲染状态行 + 把订阅配额（rate_limits）以 metadata_only POST 上报；Claude 版支持远程部署（`CLAWD_REMOTE=1` 前缀）与 `--chain` 串联模式（原 statusLine 对象保存在 `~/.claude/hooks/clawd-statusline-chain.json`，卸载时恢复） |\n| `extensions/vscode/extension.js` | VS Code / Cursor 终端 tab 聚焦辅助扩展 |\n\n## Constraints\n\n- `agents/registry.js` 的 capabilities 是权限、subagent、session-end 等路由/gate 的权威来源；不得另写名单代替 capability 判定。但 permission automation eligibility 由更窄的 `isKnownPermissionAgent()` 显式判定（`KNOWN_PERMISSION_AGENTS` + explicit opencode-family membership），不得从 `permissionApproval` 自动派生或合并回 registry capabilities\n- 小结的指标能力例外地只认 `src/recap-metrics.js` 的显式逐 Agent 口径，不得从 registry capabilities 或标准化 event 名推导。只统计已通过 gate、Codex source/replay fence、subagent 与完成仲裁的 accepted activity；DND 继续记录且不切 coverage，suspend/退出/关闭记录才切。`null` 是不支持，绝不能渲染或汇总成 `0`\n- 小结持久层固定为 `~/.clawd/recap-v1/` 下 14 个本地日的最小 HMAC 小票与 400 个本地日的 daily/coverage；不得落 prompt/回复/命令/工具内容、路径/项目、原始 event/session/profile/turn/tool ID，不得增加网络、导出或分享。首版不做 Token、金额、模型、推理强度、Skill、人的工作/编码时长、streak、峰值/最长项、排行榜或生产力评分\n- Claude Code / CodeBuddy 的阻塞式权限审批走 `POST /permission` HTTP hook；普通状态事件走 command hook（CodeBuddy command hook 对所有事件输出 `{}`，不做工具或权限决定）\n- permission automation（off / auto-tools / unattended）和 per-session grant 会在 bubble 渲染前产生真实 allow/answer。agent/family eligibility 是显式白名单；工具分类则因 mode/adapter 而异：auto-tools 对 Claude/Qwen 的未知 built-in fail closed，但其他已知 adapter 不都使用逐工具白名单，unattended 还会有意自动放行可作 Allow/Deny 的未知请求。新增 agent、工具或交互类型必须审查 policy + tests，不能从 `permissionApproval` 推导资格或笼统假设“未知请求都会 defer”\n- Telegram / 飞书 Lark 与本地 bubble 是并行决策通道。远程通道超时、断连、未配置或发送失败不得产生远程决定，更不得转成 deny；有本地 bubble 时请求继续 pending，只有 remote-only 且所有可用 client 都无决定时，整体请求才 no-decision 并回到 agent 原生流程\n- WorkBuddy 通过当前 `~/.workbuddy-ai/settings.json`（旧版兼容 `~/.workbuddy/settings.json`）的 Claude Code 兼容 command hooks 做 **state + Notification only** 集成：不注册 `/permission`，审批始终留在 WorkBuddy 原生沙箱与 GUI；无 `session_id` 的事件返回合法 stdout 后直接丢弃。当前只支持 macOS/Windows 桌面应用，没有已验证的 Linux/WSL CLI；不要把裸 `Electron` 当 WorkBuddy 进程。\n- Grok Build（agent id `grok-build`）通过 `<GROK_HOME 或 ~/.grok>/hooks/clawd-on-desk.json` 的 Claude Code 兼容 command hooks 做 **local / main-session / state + Notification only** 集成（Phase 1）：stdin 为 camelCase（`sessionId` / `toolName`），`hookEventName` 是 camelCase key + snake_case value，`hook_event_name` 是 snake_case key + PascalCase value。**逐 handler 的 `env` 结构化 marker `CLAWD_GROK_HOOK=v1` 是唯一所有权凭据**；文件名/substring（含 `grok-hook.js.backup`）只用于诊断告警，永不授权改写或删除。安装/卸载只增删含该 marker 的 handler，保留 unknown 顶层键、其他 event、foreign matcher group 与 sibling handler；没有 marker 的既有文件一律原样拒绝。`SessionEnd` 不写 `timeout`（继承 Grok 1.5s teardown），其余事件 5s。Windows 用 `windowsWrapper:\"portable\"` 形态，不得用 `&` / `-EncodedCommand` / 自造 `shell` 字段。Grok 没有 `PermissionRequest`，不注册 `/permission`，adapter 始终输出 `{}`。子代理事件（`subagentType`）直接丢弃；不注册 `SubagentStart` / `SubagentStop`。Grok 默认会扫 `~/.claude/settings.json`，所以 `clawd-hook.js` / `cursor-hook.js` / `auto-start.js` 只在非空官方 `GROK_HOOK_EVENT` 下直接退出，`GROK_HOME` / `GROK_SESSION_ID` / 无关 `GROK_*` 不得触发。`Stop` 只有精确 `reason === \"end_turn\"` 且无 background task / session cron / `stopHookActive` 才算完成，其余由 adapter 本地判定；`channel_closed` / `shutdown` 等 session-end 形态的 Stop 在 fence 之前丢弃。turn 顺序由 `src/grok-turn-fence.js` 的 bounded in-memory fence 仲裁（晚到旧 turn、重复 terminal、continuation Stop、Stop→StopCancelled 纠正）。不进入 subagent / WSL / Remote SSH / startup recovery / terminal focus / quota / context / recap turn 指标。`~/.grok/hooks/clawd.json` 是未发布的 PR preview 路径，只做 warning，不得自动接管或删除。\n- Codex 的阻塞式权限审批走 official `PermissionRequest` command hook：hook 脚本长连接 `POST /permission`，只允许 stdout 返回 sanitized `behavior/message`，`updatedInput` / `updatedPermissions` / `interrupt` 必须 omit。权限模式默认 `auto`（旧 `native` 规范化为 `auto`），仅准确本机 session/turn 的人工 reviewer 证据可进 Clawd；未知、自动 reviewer、MCP/app、远程/WSL 均 no-decision；唯一例外是远程/WSL（路由 reason 为 `nonlocal`）的 Bash/apply_patch 在全局自动放行会立即 allow 时（`wouldAutoAllowPermission`：非 reminder hold、非会话覆盖、非交互子代理）由 Clawd 直接放行（#1186），路由后若设置已变则 no-decision，绝不弹气泡。`intercept` 是显式接管；升级时旧 `intercept` / `native` 统一迁到 Auto 一次，之后重新选择的 Intercept 会保留。不得用全局 config、其他会话或旧回合推断当前请求的审批方；证据不足时返回 no-decision，交还 Codex 原生流程。\n- hook 脚本只允许依赖 Node 内置模块，以及同目录 `hooks/` 下、且登记在 `src/remote-ssh-deploy.js` 的 `HOOK_FILES` 部署清单中的纯 Node helper（如 `server-config.js` / `shared-process.js` / `json-utils.js` / `codex-originator.js` / `codex-subagent-fields.js` / `context-usage.js` / `state-payload-size.js` / `quota-bucket.js` / `claude-rate-limits.js` / `codex-rate-limits.js` / `antigravity-context-usage.js`）；manifest-consistency 测试强制检查依赖闭包，新增 helper 必须登记\n- CJS hook 脚本需要稳定终端 PID 时，必须复用 `hooks/shared-process.js` 的 `createPidResolver()` 及其 lifecycle context；不要复制进程树 walk 或用 `process.ppid` 简化。`getStablePid()` 只是 opencode-family plugin 的内部 resolver\n- `agentCmdlineCheck` 只对进程名在 `agentCmdlineNames` 里的祖先进程运行，默认是 `DEFAULT_AGENT_CMDLINE_NAMES`：`node` / `node.exe`，加上 Linux 上没设过 `process.title` 的 Node 在 `ps -o comm=` 里的名字——Node 23.8–25.4（含全部 24.x）把主线程命名为 `MainThread`、≥ 25.5 为 `node-MainThread`，Linux 报的进程名就是主线程名。传入 `agentCmdlineNames` 会整体替换默认值：只想加名字的 adapter 必须在选项里直接写成 `agentCmdlineNames: new Set([..., ...DEFAULT_AGENT_CMDLINE_NAMES])`（如 ZCode；可以跨行，方括号里只能有普通字符串字面量和 `...DEFAULT_AGENT_CMDLINE_NAMES` 本身，不能有注释或其他表达式；简写属性、先存进变量，或任何不是这个形状的提及（包括注释里的）都会被判不合格，因为文本检查无法核对），只有刻意只探测非 Node 宿主的（WorkBuddy 的 `electron`）例外，`test/shared-process.test.js` 会扫描 `hooks/*.js` 检查\n- opencode v1 权限不走 `permission.ask` hook，而是 event hook + reverse bridge；v2 走 `ctx.permission.hook(\"evaluate\")` 的阻塞 HTTP 响应\n- OpenCode / MiMo v1 原生问题走独立本地 `/question` 长轮询，不复用审批回包；遵循全局 permission bubble 开关与 family 单 agent 开关。只接受已核实的 v1 来源、版本和问题 schema，提交前用原 SDK client 复核精确 request/tool/session，答案保持有序 `string[][]`；无决定返回 204 交还原生。OpenCode 由原生 reply RPC 的 `true` / 404 判定提交结果，MiMo 仍需精确 `question.replied` 答案匹配。子会话问题、OpenCode v2、Remote SSH 及未审核 agent 保持原生；不要改 Claude/Hermes wire 或托管 generation 依赖集合。详见 `docs/guides/agent-questions.md`。\n- opencode-family v1 插件经 `ctx.client` 连回宿主时，主机为通配监听地址（`0.0.0.0` / `[::]`）就按次改用 `127.0.0.1` / `[::1]`（不改宿主共享的客户端配置；非通配地址保持原调用形状）。默认 TUI 走进程内 fetch；`opencode serve` / `web` 下这是对监听地址的真实 HTTP 请求，受宿主进程里的 `HTTP_PROXY` / `NO_PROXY` 影响，而通配地址不会自动绕过代理。桥接回复失败返回 `{ok:false,status,error}`（`status` 为上游状态码，缺省 0）。\n- OpenCode 2.x（npm `@opencode/cli`，issue #1039）由 `hooks/opencode-plugin-v2/` + core.mjs 内 `createOpencodeFamilyPluginV2` 承接：installer 在同一 generation 内额外物化 `opencode-plugin-v2/index.mjs`（v1 四文件、v2 五文件；目录 specifier 解析 index.mjs、无需 package.json，2.0.15 实测），并把它写进 **`plugins` 键**，同时清理 Clawd 自有的旧 `plugin` 条目；用户条目、tuple/options 和 v1 行为保持不变。未被 Clawd 纳管的未知 `plugin` 条目仍只报 loader WARN；v1 对未知 `plugins` 键的静默丢弃只在 **1.18.16+** 成立——1.18.15 及更早会以 `Unrecognized key: plugins` 拒绝整个 config（anomalyco/opencode#41312，2026-08-08 起才忽略未知顶层键），因此 `plugins` 写入由宿主探测决定（`hooks/opencode-host-detect.js` 三态：探测到 v2 才写；探测到 v1 不写并清扫 owned 残留；探测失败不碰该键；`CLAWD_OPENCODE_HOST` 环境变量可钉死结论，Doctor 在无 v2 宿主时不要求 v2 条目）。v2 插件是零 import 纯对象 `{id, setup}`（v2 loader 拒绝函数 default export，`@opencode/...` 裸包名无插件本地 node_modules 不可解析），事件经 `ctx.event.subscribe()`（`session.step/tool/execution.*` 词汇完全换代，未知事件一律忽略），cwd 取事件信封 `location.directory`，标题走 `session.renamed`，context usage 走 `session.step.ended` 的 step tokens（`session.usage.updated` 是 session 累计计费值，不能当占用率）。权限走 **`ctx.permission.hook(\"evaluate\")` 阻塞长连接 POST `/permission`**，决定就是 HTTP 响应体 `{decision: allow|always|deny}`（服务端按 `hook_source === \"opencode-plugin-v2\"` 路由到 v2 阻塞子分支），只有 `200` + 身份头 + 合法 JSON 才采纳决定，204/超时/断连/非 200/任何错误都不改 effect 回原生 ask UI；配置 allow 也进 hook 但绝不降级；单条 shell 命令以 `tool_input.resource` 传输，服务端 v2 分支会为其别名出 `command` 以接入破坏性操作提醒（`mapOpencodeV2ShellResource`，非 shell 工具不映射；全字符串的多 resource 以换行合并作扫描别名）；resources 原样整组转发（对象转 JSON 字符串），不做条数/长度截断，唯一边界是整 body 超 512 KiB 时跳过转发。\"Always allow\" 无宿主持久化 API，用插件内 per-session 内存规则（随常驻 service 生命周期，气泡对 v2 使用单独文案说明关闭/重开终端不会撤销）。插件跑在常驻共享 service（daemon）：`source_pid`/进程树不可信故**整组省略**（终端跳转对 v2 降级），安装/更新后需 `opencode service restart`。`ctx.permission.hook()` 按上游 v2.0.15 类型返回 `Promise<Registration>`：本实例 dispose（setup 返回的 cleanup，宿主也会在插件 scope 关闭时调用）会调用 `registration.dispose()`，注册 Promise reject 只记日志不影响事件订阅。事件订阅**不等待** hook 注册（注册挂起/reject 时状态上报照常），reload **不等待**上一代注销完成；本实例清理先同步完成本地清理（标记 disposed、abort 订阅、身份恢复）再去注销 registration，注册 dispose 有约 2s 上限、超时只记日志，注册未完成就被取代则在注册完成那一刻立即注销，不残留活 hook。上游 v2.0.15 的 trigger 对同名 hook 依次调用每个仍注册的回调、共用同一个可变 event，而我们的注销是异步的，所以 reload 窗口内旧回调可能仍被调用：已退役实例的回调入口检查 `instance.disposed` 后直接返回，不 POST、不改 event。每个 ask 各自转发（`source.id` 是工具调用级、不是 ask 级，同一工具调用会发出多个不同 ask，如 external_directory + edit），不做内容去重。config 顶层重复 `plugins` 键按歧义处理：Doctor 报 `config-corrupt` 不抛异常，register/卸载在首次写入前中止（v1 宿主 sweep 只告警并跳过），v1 `plugin` 键行为不变。v1 1.18.31 tuple 契约、generation 布局、owner/lock 语义不变；`inspectGeneration` 把历史 4 文件集接受为合法 owned-stale 形态以便迁移。真机证据与降级项见 `docs/investigations/opencode-v2-e1-evidence.md`\n- OpenCode 的 plugin 注册不再直接指向打包/源码目录：`agents/opencode-family.js` 的 `managedMaterialization:true`（OpenCode true / MiMo 本次 false）gate materialize、ownership classifier、managed Doctor 与 generation cleanup。开启后 register 必须在目标 home 下维护 `<home>/.clawd/integrations/opencode-family/opencode/homes/<configDirHash>/generations/<bundleHash>/` 的内容寻址 generation（OpenCode v2 当前五文件，历史 v1 四文件），同一 generation 可同时物化 v1/v2 入口文件，但不因此在配置中注册两个键；探测到 v2 宿主时只把 `opencode-plugin-v2` 入口写入 `plugins`，并将 `plugin` 键仅用于清理 Clawd 自有旧条目；v1 宿主和探测不到版本时保持原有 v1 注册路径；bundle allowlist 固定为 `<agent>-plugin/index.mjs` / `<agent>-plugin/package.json` / `opencode-family-plugin/core.mjs` / `opencode-family-plugin/session-ids.mjs` / `opencode-plugin-v2/index.mjs`（v2）。owner record（`owner.json`，literal `clawd-on-desk.opencode-family.target`）与 target-scoped `mutation.lock/`（独立 literal `clawd-on-desk.opencode-family.target.lock`）是所有权与 app-present 真相；lock 被持有时不并发写：interactive Install/Repair/CLI/Uninstall/About cleanup 只做一次短而有界、可注入 delay 的重试，startup automatic 不等待直接 skipped；合法且超时 2 倍以上、PID 明确 ESRCH 才允许 atomic quarantine 接管，corrupt/foreign/live/EPERM 一律不接管；release 只删自己 token 的 `lock.json` 与随后为空的精确目录，禁止 recursive cleanup。owner 的 `activeSourceMarker` 必须是 `<activeSourceRoot>/<pluginDirName>/index.mjs`（共享 canonical 身份、Windows 折叠大小写）且为 regular file，目录/dangling/错 plugin 目录/root 不匹配都不算 live。同一 target 的 source owner 冲突（marker 仍存在）一律 `owner-conflict`，不得来回改 config；旧 owner 的源码 marker 已不存在时，新 source 必须在锁内重读并原子接管 owner（config 已 current 也不例外），否则残留死 owner 会让托管 plugin 永久 inert。锁内若 config 与当前 source owner 都已被并发操作收敛，则本次零 mutation 返回 skipped。lock release 失败不得掩盖结果：成功保留 status 并附 warning + 精确 lock path 的 residualPaths，已有 primary error 时保留原错误。basename 本身永不构成所有权；copy 到 managed layout 外的完整 generation 因缺少对应 owner record 而 inert，只有 verified-current-copy 可 Repair。tuple 契约固定为 OpenCode 1.18.31 实测的 `[specifier, optionsObject]`（隔离 `opencode debug config` 证据：第二项必须是普通对象，数组/字符串第二项会被宿主拒绝）；重写只替换 `plugin[index][0]`，options 值级保留，绝不写回嵌套 tuple，malformed array 原样保留。`options.pluginDir` 仍是 test-only expected-canonical override（跳过 generation/manifest/boundary，但不跳过 ownership/唯一 entry/read-back），`resolvePluginDir()` 仍返回 source。新建文件按当前用户普通写权限落盘：不得加 readonly/deny-write ACL，不得用 `W_OK`/`r+`/INIT 日志/session 活跃做健康门禁。Uninstall 以“活动注册是否移除”为提交依据（`registrationRemoved` false/null 阻止 Settings 提交，undefined 沿用 legacy status），残留 generation 只产生 warning；清理有效 generation 时必须先在同一 `generations/` 内原子改名为非 canonical `.cleanup-*` 再递归删除，删除失败不得占住原 hash 槽。兼容旧版本留下的半残 canonical 目录时，只允许在 owner 已 released、bounded history 精确证明该 canonical entry、且配置无活动 Clawd entry 的条件下，把它原子隔离为 `.recovery-*` 后重新物化；active/foreign/unproven/canonical-in-use 一律继续 fail closed，绝不原地覆盖或修补可疑 bytes。托管 core 的 orphan inert gate（`evaluateManagedLayoutGate`）必须在 `resetDebugLog()` / PID walk / bridge / handler 注册之前，owner marker 缺失、损坏、agentId 不匹配或 `activeSourceMarker` 不存在时返回空 handler；source-direct 模式保持原行为。MiMo 保持 broad-basename register/unregister/Doctor 契约不变。\n- Pi 通过 `~/.pi/agent/extensions/clawd-on-desk` 的 global extension 推送状态；Clawd 对 Pi 是 **state-only**，不接管权限、不弹权限气泡，也不把 Pi 的默认 YOLO 流程改成手动确认\n- OMP (oh-my-pi) 通过 `~/.omp/agent/extensions/clawd-on-desk` 的 global extension 推送状态，agent id `omp`，对 Clawd 同样是 **state-only**。它是 Pi 的 fork（包名 `@oh-my-pi/pi-coding-agent`），所以 `hooks/omp-extension.ts` 刻意与 `hooks/pi-extension.ts` 保持逐行对齐（只差 package import、core import 与函数名），进程树遍历与终端识别不得各自漂移；OMP 独有的差异全部收在 `hooks/omp-extension-core.js`。**完成必须走 `session_stop` 候选 + 终态 `agent_end` 提交的两阶段协议** —— `session_stop` 先保留主会话边界，OMP 再汇总所有 extension 的续跑请求；只有后续 `agent_end.willContinue !== true` 才向 Clawd 发完成。不得直接把任一事件单独映射为完成：仅用 `agent_end` 会把 subagent/调度边界误报为完成，仅用 `session_stop` 则会早于 extension 续跑判定。`session_switch` / `session_branch` 要为被切走的旧 session 补发一条合成 `SessionEnd`，否则 Clawd 会留下一条再也不会有人上报的活动行。session id 命名空间是 `omp:<raw>`，且必须始终带 `session_title`（多个交互式会话合法地共用同一个 cwd，缺标题会让列表和跳转目标无法区分）。安装器遇到社区桥接 `~/.omp/agent/extensions/clawd-on-desk-omp.ts` 时必须 fail closed 跳过：两者上报同一批事件，同时存在会双发。当前 `assets/source/agent-icons/omp.png` 是 `fallback: true` 的占位 π 字形，不是 OMP 官方品牌素材，拿到授权素材后应替换\n- DeepSeek Harness 首发是 **web profile / Windows-first experimental / plugin-only**；rc.6 已于 2026-08-29 完成 macOS / Windows x64 源码运行的真实 API-backed session/approval smoke（#962）；rc.2 Windows packaged-app 证据仅覆盖安装、web boot 与直接 bridge client 的 state/Allow/Deny 往返（#938），不得合并宣称 rc.2 安装包的真实 API 会话已验证。Clawd-managed in-process plugin 监听公开 `session/created`、`session/event`、`session/disposed`、可选 `sessionProjections.onChanged` 与 blocking `approval/request`；标题和上下文仅作为会话元数据同步，不占用生命周期 seq。状态按 session FIFO 上报并携带上游 seq；Clawd 不读取 `$DSH_HOME/storages` projection。普通审批进入独立 DSH `/permission` adapter，只支持人工 Allow Once / Deny；204 / 断连 / DND / disabled 都由 plugin `next()` 交还 DSH 原生 web answerer。`ask_user_question` 始终留在 DSH 原生 provider；DSH 不进入 `KNOWN_PERMISSION_AGENTS`，auto-tools / unattended / per-session grant 全部 DEFER。安装器通过官方 `dsh plugin --profile web add/remove` 管理 immutable marker-owned generation，foreign 同名包 fail closed；版本放行改成按 **小版本族（major.minor）**。维护两张表：一张是唯一写出具体版本/npm artifact/integrity 的已验证 artifact 清单（优先 `@deepseek-ai/dsh@0.2.0-rc.2`（integrity `sha512-EAJ3gPNcVt/uv8X19PMm9NkVhWgT7xXNMk0UKCVm+IQ5rpSQOcsMUa0HWlnYYVybKMsccjcRB21vVVsaXQ6IdA==`，2026-10-04 已做静态接口核对，并在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证了用 Clawd 安装器装出的 generation 的启动同步换代、会话状态、HUD 标题/上下文、Allow/Deny 与消息上的失败标记；其 `tool/result` 把失败标记放在消息 `message.isError` 而不是内容项上，bridge 新旧两种位置都认），并保留 `@deepseek-ai/dsh@0.1.5-rc.3`（integrity `sha512-c0W6Xqc4ChjFcCJkbzPeIxZQdnbKqe+QAcJzWGtogg0ZzsnZRcw3vopMyZ5oZU6E2fmyqGcyDR1sBeiCH4yHcg==`，2026-09-27 已在 macOS 源码运行版 Clawd + 真实 `dsh web` 与真实模型上验证启动同步安装、会话状态、HUD 标题/上下文与 Allow/Deny）、`@deepseek-ai/dsh@0.1.5-rc.1`（integrity `sha512-rmNmzQCg3oIc1z8xH7izRSOuy1TNzq+/NILyfM+7e8DKOyV+yBtg47WEsqR2SiIe1ATec3L/rUa1YhIcfQ2XEg==`）、`@deepseek-ai/dsh@0.1.1-rc.2`（integrity `sha512-UP1UIh6q3Gme/yXRn/QL2P8IsVlv8Shpg22TRJIZPsCRWLm4CBiA1MUvXmJAfsOEETBMLAl+xWPtFw6ICsN3wg==`）与 `@deepseek-ai/dsh@0.1.0-rc.6`（integrity `sha512-brpZfED7ieRa2PQ5tUxMhHrM1pb2CmKFVM/f6yMULBDMicahk+Z2OsHgTwTDnoiZm23Ftu9rQz0NN4pflaoJcg==`）），一张是族表（`0.2` 下限 `0.2.0-rc.2`、`0.1` 下限 `0.1.0-rc.6`）。host 版本经严格解析（拒绝前导零、空预发布标识与 build 元数据）通过、major.minor 命中族、且不低于该族下限即放行；同一族内不同 host 版本共用一个 generation，出现新的小版本必须重新验证并新增一个族。旧的精确 `=<version>` marker 仍按原 range 核对哈希，新 generation 一律写族 range；Install/Repair 按 host 版本所在的族选择目标契约，Uninstall / 手动 npx 命令在 marker 版本已列入清单时钉它自己的 artifact，否则钉同族版本最高的已验证 artifact（无 CLI 且无 marker 时用首选族最新的并记为 assumed）；加锁前后比较的是实际检测到的 host 版本，不看族。DSH 的 `metadata_only` 标题/上下文旁路必须核对目标会话的 `agentId` 确为 `deepseek-harness`，撞名的其他 agent 会话直接丢弃。`47f9438` 仅是源码调查基线，不代表任何 tag/commit 映射。\n- DSH 每个 canonical `DSH_HOME` 的 mutation lock 只有在 owner/schema/token/PID/timestamp/owner-recorded operation timeout 合法、超过该 owner timeout 两倍、且 OS PID probe 明确为 `ESRCH` 时才允许 atomic-rename takeover；live、`EPERM`、unknown、corrupt/foreign owner 一律拒绝并返回精确 lock path。canonical lock 的 owner write/release 禁止 recursive cleanup。无全局 CLI 时生成的手动 npx generation 必须先在同一锁内写 owned reference，手动 add/remove 命令必须显式 pin shell-quoted canonical `DSH_HOME`；malformed/foreign/concurrently replaced reference 一律 fail closed 并保留 generation\n- DSH 桌面版支持（#1119）与 web 共用一个 agent id `deepseek-harness`：web profile 和 DeepSeek Harness 桌面版是两个承载方、各自一个 profile（桌面版是 `$DSH_HOME/profiles/desktop`），但在 Settings 和 Doctor 里仍是**一行**，显示名 `DeepSeek Harness (experimental)`，一次排队操作先 web 后 desktop、一边失败不影响另一边；安装只要有一边核实健康即成功（另一边失败变 warning + 常驻提示），卸载要所有 Clawd 注册都没了才成功。桌面版查找：macOS 用 `/Applications` 或 `~/Applications/DeepSeek Harness.app` 里自带的 `Contents/Resources/runtime/cli/bin/dsh`；Windows 按用户安装，从 `HKCU` 卸载项（显示名以 `DeepSeek Harness ` 开头）与 `%LOCALAPPDATA%\\Programs\\DeepSeek Harness` 找 `resources\\runtime\\cli\\bin\\dsh.cmd`，注册表用 PowerShell 读 UTF-8 JSON、不用 `reg.exe`；Linux 不支持桌面版。静态版本来自 `Info.plist` / 卸载项 `DisplayVersion`，真正动手前跑一次启动器 `--version` 核实。桌面版**永不用 npx**，手动 npx 命令与 manual reference 只属 web。每边角色是 `mutable` / `diagnose` / `not-applicable`：桌面版没装、或 profile 从未初始化（桌面版没打开过）→ 不适用并提示打开一次；foreign 同名包、文件读不了、清理残留、注册查不清、版本不支持、装了不止一个桌面版（`multiple-desktop-installs`）、桌面版找不到但注册还在（`carrier-unavailable`）、桌面版查不清（`desktop-unverifiable`）→ 只报告不动手。启动同步在集成已安装且启用时会把插件加进已初始化的桌面版 profile；桌面版开着也会加载新加的插件，只有插件更新（换了 generation）后要重启。常驻提示在 `hooks/dsh-notices.js`，按 profile 存 `notices-web.json`/`notices-desktop.json`，四种 kind（`restart-required`/`first-install`/`manual-command`/`failed-target`），写不进去只算 warning；提示显示在 Settings → AI Coding Tools 里这一行下面。Doctor 一行详情 `web: …; desktop: …`，状态取适用边里最差，只要有一边能尝试修复且不健康就给修复按钮（`src/doctor-detectors/agent-integrations.js`）。插件在 DSH 里被关掉（依赖在、bundle 行没了）时 `plugin add` 不会重开：显式修复先 remove 再 add（add 前先清掉上游 remove 留下的自有链接，Mac 是符号链接、Windows 是 junction），按 profile 记 `repair-operation-<profile>.json`，中断后下次显式修复续做，启动同步只报 `plugin-disabled-in-dsh`。`generations/` 两边共享，任一边有未处理状态（检查记录、清理残留、坏修复记录或 manual reference、读不了的 profile、符号链接 profile 目录）时清理暂停但不挡安装，卸载残留进 warnings。检查记录按 profile：web `inspection-required.json`、桌面版 `inspection-required-desktop.json`。`plugin add/remove` 写命令两边都超时 300 秒（web 原 120 秒），比上游写锁等待长。上游 `dsh plugin remove` 只清 `link:` 清单和锁、`node_modules` 链接会留下，Clawd 卸载自有插件时确认归属后清掉。Windows 静态查找是同步代码、不起进程，只读异步快照：启动时（不管 DSH 是否启用）、打开 Doctor 前、Agents 页手动扫描时刷新，没快照时桌面版显示\"查不清\"。安装检测把\"找到桌面版\"也算装了 DSH（`src/agent-installation-detector.js`）。桥接插件在 apply 时读 `ctx.profileContext?.name`，只有 desktop profile 才在 state / 审批载荷里带 `dsh_carrier: \"desktop\"`（metadata 不带；web 或未知 profile 一律不带）；Clawd 只接受 DSH + `dsh-plugin` + 本机 + 非 WSL 的载体，按生命周期覆盖或清除、不粘滞，权限 fallback entry 与快照（含签名）都带上它。点击桌面版会话时 `getSessionFocusTarget` 在 darwin/win32 返回 `dsh-desktop`（`dsh://open`），分派先 `shell.openExternal(\"dsh://open\")`，被拒绝再按 `discoverDshDesktopSync({ requireUniqueApp: true })` 的兜底要求唯一安装启动界面程序（macOS `open <appRoot>`、Windows 启动 `<appRoot>\\DeepSeek Harness.exe`，去掉 `ELECTRON_*`/`NODE_OPTIONS`，不用 CLI 启动方式；两份真实路径不同的有效安装视为有歧义，只要还有核实不了的候选也不自动启动，同一份安装的符号链接只算一份）；只能打开应用窗口、不会切到具体对话，web 会话仍不可跳；桌面版启动时会重新打开上次的对话，Clawd 只在这个对话有了动作（提问、工具调用、审批）之后才把它放进 Session HUD（`awaitingActivity` 并入快照 `hiddenFromHud`，但不关跳转；与 Kimi Code 共用同一个标记），Dashboard 照常列出、按钮照常可跳；2026-10-05 macOS 26.6.2 与 Windows 11 x64 源码运行真机验证（桌面版 `0.2.0-rc.2`）：别的窗口在前、最小化、关窗后，点击都经 `dsh://open` 把窗口带到最前；协议打不开时的启动兜底只有单元测试。真机证据：2026-10-04 macOS 源码运行（Clawd `ac64d726`，桌面版 `0.2.0-rc.2` + 全局 `@deepseek-ai/dsh@0.2.0-rc.2`）验证了启动同步把插件装进桌面版（与 web 共用 generation）并出现\"已装进桌面版\"提示、Doctor 一行两边正常，桌面版真实会话的 Allow 建成文件、Deny 后文件内容和 mtime 不变且 Clawd 显示 `PostToolUseFailure`，\"知道了\"后提示消失，改 bridge 源码（同 Clawd 版本）后启动同步两边报 `generation-conflict` 并提示去 Doctor 修复、修复把两边换到新 generation/删旧/出现\"重启桌面版后生效\"、重启后事件来自新宿主进程，设置页卸载后两边依赖与 bundle 行都没了、上游残留链接被清、generation 删除、两边提示清空，再在设置页安装两边都重新装上、桌面版重新出现\"已装进桌面版\"（\"经设置页首次安装\"因此已覆盖），开着 DND 时桌面版的工作区外写文件不弹 Clawd 气泡、返回 no-decision、桌面版弹自己的原生审批框、批准后文件建成且事件照常到达。2026-10-04 Windows 11 x64 经 SSH 用 Node 直跑安装器代码（管理员会话，桌面版在 `%LOCALAPPDATA%` 按用户安装 `0.2.0-rc.2`、全局 dsh `0.1.0-rc.6`，web 在 0.1 族、桌面版在 0.2 族）：PowerShell 读注册表找到桌面版、静态模式无快照时报\"查不清\"且不起进程、自带 `dsh.cmd`（带空格路径）`--version` 返回 `0.2.0-rc.2`、`dsh.cmd plugin --profile desktop add` 经 pnpm junction 装入并核实、记录\"已装进桌面版\"、两族各用一份 generation 并存、Doctor 一行两边有修复按钮、卸载桌面版清依赖与 bundle 行并清掉 `dsh plugin remove` 残留 junction、只删桌面版那份 generation 而保留 web 在用的；2026-10-04 另在 Windows 上以真 Clawd（Electron，源码运行、用户会话、普通权限）验证：先抓到一个只在 Electron 里出现的 bug（Electron 的 fs 把 `app.asar` 当目录、Windows 安装目录核实要求它是文件，于是在真 Clawd 里桌面版被判成没装，已在 `d8190692` 修成\"存在即可\"）；修好后桌面版一直开着（宿主进程未重启），启动同步把插件装进桌面版并记\"已装进桌面版\"，在桌面版新开对话的事件来自那个未重启的宿主进程，**Windows 上桌面版开着也会加载新加的插件**。**未覆盖**：Windows 上桌面版的审批、Windows 上的 Electron 界面（设置页提示、Doctor 窗口、启动预热）、打包后的 app、Linux、HTTP 204 交还与取消、装了多个桌面版。**管理员 junction 观察（推断）**：提升过的管理员进程在 Windows 11 上穿不过非管理员进程建的 junction（PowerShell \"untrusted mount point\"、Node `UNKNOWN`），该会话里 web 的旧 junction 读不到、web add 失败，桌面版同会话新建的 junction 正常；普通权限运行不受影响；由此推断以管理员身份运行 Clawd 可能把普通权限装好的插件读成缺失，未用以管理员身份运行的 Clawd 直接复现\n- OpenClaw 通过 `~/.openclaw/openclaw.json` plugin 路径做 state-only 集成；Phase 1 不做 permission bubble / terminal focus，主要支持本地 `openclaw tui --local`\n- Antigravity CLI (agy) 通过 `~/.gemini/config/hooks.json` 做 **state-only** hook 集成（PreInvocation / PostToolUse / PostInvocation / Stop），**不注册 PreToolUse**。agy LLM 会主动调内置 `ask_permission` 工具，触发 agy 自己的 5 选项 native menu（含 \"Persist to settings.json\" 持久白名单），Clawd 不插手权限决策也不双层确认。`agents/antigravity-cli.js` `capabilities.permissionApproval` / `interactiveBubble` 均为 false。\n- Qwen Code 通过 `~/.qwen/settings.json` 做 hook-only 集成（SessionStart / SessionEnd / UserPromptSubmit / PreToolUse / PostToolUse / Stop / Notification / PermissionRequest），支持状态与阻塞式 `PermissionRequest` 权限气泡；`disableAllHooks: true` 时注册条目不会触发。\n- QwenWork (千问办公) 通过 `~/.QwenWorkCN/settings.json` 做 **hook-only / state-only** 集成（agent id `qwenwork`；SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / Notification / PermissionRequest / PermissionDenied / SessionEnd）。`PermissionRequest` / `PermissionDenied` 只作为观察映射成 `working`（每任务 40+ 次，映射成 notification 会刷屏），hook stdout 恒为 `{}`：Clawd 不产生 allow/deny，不注册 `/permission`，也不进入 permission automation eligibility，唯一决策者是 QwenWork 原生权限流程；`agents/qwenwork.js` 的 `capabilities.permissionApproval` / `interactiveBubble` 均为 false。Windows command 必须保持 `windowsWrapper:\"portable\"`（QwenWork 经 POSIX shell 执行 command hook），PowerShell `-EncodedCommand` **只**用于识别并原地迁移旧条目，不是当前写入形态。marker 只认 `qwenwork-hook.js`，不得仅凭 `name:\"clawd\"` 删除用户 hook；混合 entry 中第三方 hook 原样保留。session id 命名空间是 `qwenwork:<raw>`；`~/.QwenWorkCN/workspace/<id>` 这类内部工作区 cwd 不做 basename 回退，避免 HUD/Dashboard 显示内部 ID。当前真实支持平台只有 macOS / Windows 桌面端（官方下载页 https://qwenwork.cn/download 只提供 macOS 14+ / Windows 10+ / HarmonyOS 6.1+，没有 Linux 客户端），因此 `processNames.linux`、resolver linux agent name 均为空，也不进 `src/wsl-deploy.js` 的 WSL Pair 映射。桌面主进程长驻、不代表 active turn，`startupRecoveryProcessNames` 全空、无 startup recovery。安装/卸载走 Settings → AI Coding Tools，或 `npm run install:qwenwork-hooks` / `npm run uninstall:qwenwork-hooks`；卸载必须同时在 `hooks/cleanup-integrations.js` 的 `MANAGED_AGENT_IDS` / `AGENT_CLEANERS` / `byAgent` 里有条目，否则 About cleanup 只会改 prefs、hook 留在磁盘上\n- ZCode 通过 `~/.zcode/cli/config.json` 的 `hooks.events.*` 集成全部 7 个支持事件（SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PostToolUseFailure / Stop / PermissionRequest，无 SessionEnd / Notification）。PermissionRequest 为阻塞式权限审批：hook 长连接 `POST /permission`（HTTP 等待 590s，installer 注册 `timeoutMs: 600000`），有决定时 stdout 返回最小合法 `{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}`（deny 可带 `message`），无决定 / 超时 / 断连 / 任何错误输出 `{}` 并 exit 0，ZCode 回退原生权限流程；`interrupt` / `updatedInput` / `updatedPermissions` / `permissionUpdates` 必须 omit（最小输出 union 按 ZCode 3.5.x 严格 schema 约束；macOS ZCode 3.8.1 已完成真实 hook / 气泡 Allow/Deny 往返，3.5.x PermissionRequest 真机往返未覆盖）。超时单位陷阱：ZCode `timeout` 是秒、`timeoutMs` 才是毫秒，且超时按事件区分（PermissionRequest 600000、state 事件 8000）。Phase 2 只允许人工审批：ZCode 不进入 `KNOWN_PERMISSION_AGENTS`，global / per-session permission automation 在工具面与会话身份审计完成前全部 defer。prefs v14→v15 迁移把 Phase 1 持久化的 `zcode.permissionsEnabled:false` 翻 true（当时开关从未渲染、无用户意图）。配置必须有 `hooks.enabled=true` 才会执行；安装器只在该字段缺失时补 true，显式 `hooks.enabled=false` 或 Clawd 单项 hook 的 `enabled=false` 必须保留，Doctor warning 且不提供会覆盖用户选择的 Fix。ZCode 导入 Claude 配置后，只清理 `.zcode` 中明确引用 `clawd-hook.js` 的 Clawd-owned 条目，绝不改 `~/.claude/settings.json`。安全边界（复核后新增）：`/state` 生命周期 sweep 对 zcode（及 qwen/DSH 等 native-fallback adapter）只允许 no-decision，绝不伪 deny；hook 侧 `tool_input` 预算内原样发送、任何截断（长 Bash 尾部 `rm -rf` 场景）或序列化超 512KiB 一律 fail-closed 输出 `{}` 交还原生 UI；无 allow/answer/plan capability 的 interaction（如 ZCode 真实的 ExitPlanMode / AskUserQuestion）本地气泡与远程卡片都不提供决定入口、直接 204；全局气泡关闭只关本地窗口，Telegram/飞书 remote-only 审批仍可用（per-agent gate 关闭才是全退出）；installer 遇到 foreign `PermissionRequest` hook 时不注册自己的 blocking hook，若 foreign hook 后出现则移除自己的 managed hook（ZCode 同事件 hook 串行执行、后写覆盖，Clawd allow 会盖掉用户 hook 的 deny），Doctor 报 `permission-conflict` 且不给 Fix；六个 Phase 1 managed hook 全部显式 disabled 时新 PermissionRequest 继承 `enabled:false`；服务端 pre-parse 超限一律断连回退，不伪造 deny\n- Qoder / Qoder CN 共用 `qoder` agent，通过 `~/.qoder/settings.json` / `~/.qoder-cn/settings.json` 做 **state-only** hook 集成；各自尊重 `QODER_CONFIG_DIR` / `QODERCN_CONFIG_DIR`，同步所有已初始化目录，不创建缺失版本目录，卸载/cleanup 覆盖两版且只移除 Clawd entries，Doctor 不得让健康的一版掩盖另一版故障。Clawd 只把 `PermissionRequest` / `PermissionDenied` 当 notification 观察，**不替 Qoder 做权限决策**，hook stdout 恒为 `{}`；Windows command 必须保持 `windowsWrapper:\"portable\"`。session id 命名空间是 `qoder:<raw>`；启动恢复只认 CLI `qodercli` / `qoder-cli` / `qoderclicn`，不认闲置 IDE / CN 桌面进程；本机原生会话标题由 `src/qoder-session-title.js` 低频异步增量读取，通过 `updateSessionMetadata` 更新；SessionEnd / 禁用 / 退出取消旧读取，远端与 WSL 路径不在本机读取。2026-10-18 已核对 Windows CN runtime 1.1.69 的真实 SessionStart / UserPromptSubmit / Stop hooks，用户确认开启 Clawd Qoder 接入后任务状态恢复；macOS/Linux CN 未实测\n- TraeCode (Trae CN) 通过 `~/.trae-cn/hooks.json` 做 **hook-only / state-only** 集成。Windows command 必须保持 `windowsWrapper:\"encoded\"`：Trae 的 Windows Sandbox 会把 hook 命令作为 `trae-sandbox.exe --command-line` 的单个原生参数再次转发，普通引号或 `portable` 形态会在含空格路径处拆分；外层必须保持无引号的 PowerShell `-EncodedCommand`，POSIX 则继续使用普通 quoted command。该约束不适用于经 POSIX shell 执行 Windows hook 的 agent（如 Qoder / QwenWork）。\n- MiniMax Code 通过 `<MINIMAX_DATA_DIR 或 MAVIS_DATA_DIR 或 ~/.minimax>/plugins/clawd-state/` 的 **Clawd 独占本地插件**做 **state-only** 集成（manifest 用 `.claude-plugin/plugin.json`，hooks 文档按 MiniMax 的 CLAUDE sourceFormat 解析；不用 `.minimax-plugin/`，那会走 MINIMAX 格式：matcher 必须非空且不支持 exec-form args）。handler 固定 exec-form `command=node 路径 + args=[minimax-hook.js]`（spawn 直执行、无 shell、免引号），`timeout` 单位是秒且只接受 1–10 的整数（越界的 handler 被丢弃而不是钳制；SessionEnd 事件总预算仅 3s），因此 **PermissionRequest 物理上不可阻塞审批、完全不注册**，也没有 Notification 事件；hook stdout 恒为 `{}`（permissionDecision 缺省 abstain）。目录级所有权只认结构化凭据 `.clawd-managed.json`（`{app:\"clawd-on-desk\",integration:\"minimax\",managed:true,version:1}`，同 Pi 约定；MiniMax 只读 manifest 声明的文件，会忽略它），且凭据与所有受管理路径（`.claude-plugin/`、`hooks/` 及其文件）都不得是符号链接；目录名、manifest name、文档里的 basename/子串乃至整份文档指纹都永不授权改写或递归删除，缺凭据的目录（包括补丁前预发布构建写出的）一律 fail closed，只能手动删除后重装。staging / removal 目录固定落在数据目录（`plugins/` 之外，MiniMax 会把 `plugins/` 下每个目录项都当插件候选，含点号名）：首装在 staging 写全三份文件后一次 rename 发布（只覆盖空目标，非空目录/文件/链接拒绝；空 `clawd-state/` 视为未占用），失败时尽力删除 staging；已拥有的目录原地逐文件更新，中断后仍可证明归属、由下次安装补完。只有 ENOENT/ENOTDIR 算不存在，其他 lstat 错误按无法确认处理，绝不据此宣告卸载。卸载先把已验证目录 rename 出 `plugins/`、复验后再删；移走失败报 error 并保留安装意图，移走成功但删除失败时按已移除提交并在 warnings 里给出残留 `.clawd-minimax-removing-*` 路径，复验失败且移回失败时两个位置都报 `registrationRemoved:null` 并带 `residualPaths`；删不掉且目录仍运行 Clawd hook 时返回 `registrationRemoved:false`（读不清为 `null`），Settings / About 据此保留安装意图。删除后返回前还会复查一次原位置：此时若已有另一个 Clawd 实例重新发布的插件，报“仍在注册”（`registrationRemoved:false`）、不宣称卸载；这次复查是快照，复查之后、Settings 提交之前的安装不在本次结果里（多实例强一致需要覆盖 prefs 提交的跨进程锁，未做）。Settings 界面目前不显示成功结果里的 `warnings` / `residualPaths`：Agents 页安装/卸载只弹“已卸载/已安装”，About 清理只显示计数，只有命令行 cleanup 脚本会打印 warning。进程中途崩溃，或 staging 清理本身失败，可能在数据目录留下 `.clawd-minimax-staging-*` / `.clawd-minimax-removing-*`（MiniMax 不会加载，只能手动删除）；`plugins/` 与数据目录跨文件系统（EXDEV）时不支持。判断外来目录是否仍跑 Clawd hook 按 manifest 声明的 hooks 文档和 MiniMax 默认规则检查（含裸文档外壳、反斜杠路径，以及 shell 形式的 command / commandWindows handler）；Clawd 不建模的 manifest（根 `plugin.json` / `.minimax-plugin/` / `.codex-plugin/`）或读不清时按无法确认处理。node 探测失败时只保留全部 Clawd handler 一致、basename 为 node、存在且可执行、并通过 `node --version` 有界探测的已记录路径（exec-form 无 shell，Dock 启动的桌面 App 的 PATH 里没有 node），安装器与 Doctor 共用 `resolveDesiredNodeBin`。PostCompact 按 #406 上报 thinking（`trigger:\"manual\"` 时 idle），不是 attention。hook 的 `agentNames` 必须全小写（resolver 比较的是小写 basename），且不含桌面版的 “MiniMax Code Helper”：拉起 hook 的 NodeService helper 可能在 App 运行中重启，把它当 agent 会误删活会话，识别应落到长驻的主程序；mcode CLI 启动时执行 `process.title = \"minimax-code\"`，macOS/Linux 上 `ps` 报告的进程名就是 `minimax-code`（按名字匹配），Windows 上仍是 node.exe，靠 `agentCmdlineCheck` 只看 argv 里的脚本位置识别（命令行检查的进程名沿用共享默认 `DEFAULT_AGENT_CMDLINE_NAMES`，已含 Linux 上新版 Node 的主线程名 `mainthread` / `node-mainthread`，MiniMax 不再自带名单）（`node` 后的脚本 basename 是 `mcode`/`minimax-code` 启动器，或脚本路径含 `/@minimax-ai/code/` / `/.minimax-code/`），参数里的目录片段不算——MiniMax 退出时不发 SessionEnd，没有 agent pid 会话就无法按 agent-exit 清理。hook 不触发时的启用步骤在 MiniMax 应用内（`mcode plugin enable clawd-state@local` 或插件面板），磁盘上读不到启用状态，Doctor/Settings 只能提示。session id 命名空间 `minimax:<raw>`，标题走首行 prompt 派生 + 服务端 first-wins（同 traecode）。\n- Kimi Code（agent id `kimi-cli`）的 agent pid 靠进程名识别：CLI 启动即 `process.title = \"kimi-code\"`，libuv 把标题写回原 argv 所占的空间、放不下就截断，所以 macOS/Linux 上 `ps` 与 `pgrep -x` 看到的名字随启动命令长短而变（0.42.0 原生版实测：`kimi` 仍是 `kimi`，`kimi -c` 是 `kimi-co`，`kimi --yolo` 或全路径启动是 `kimi-code`；只有整条启动命令比 `kimi` 还短时（例如不带参数的软链接 `k`）才认不出，`k -c` 显示的已经是 `kimi`）。`hooks/kimi-process-names.js` 必须列全从 `kimi` 到 `kimi-code` 的每一种截断，resolver 与 startup recovery 共用这一组，只写 `kimi-code` 会漏掉 `kimi -c`。拉起 hook 的就是这个改名后的主进程（TUI 在进程内跑 agent 引擎，从 SessionStart 到 SessionEnd 同一个 PID）；其他同名进程（后台更新下载器、经 kimi 二进制跑的插件进程等）都是它的子进程，不跑 hook。resolver 比较小写 basename，macOS 桌面版 `Kimi Code.app` 写成 `kimi code`（它的 agent server 跑在主进程里，hook 由主进程直接拉起）；桌面版关窗后常驻托盘、不代表在干活，同其他桌面 App 一样不进 startup recovery。Windows 上标题只改控制台标题：原生版仍是 `kimi.exe`，npm 版仍是 `node.exe`，命令行检查只认包目录 `/@moonshot-ai/kimi-code/`，不能退回“含 kimi 就算”（Kimi 本身没被认出时，任何命令行提到 kimi 的 node 祖先都会被当成 agent）。Kimi Code 正常 `/exit` 会发 SessionEnd，但关终端、`kill`（0.42.0 实测：SIGTERM 与 SIGKILL 都不发；源码里 SIGTERM 注册了 `stop(143)`，实测为什么没发 SessionEnd 还没查清）、崩溃都不发；没有 agent pid 的会话只要终端 App 还开着就一直留在列表里。桌面端启动时会恢复上次查看的对话、在侧栏点开旧对话也一样，这类只发一条 SessionStart、还没有任何动作的对话不进 Session HUD，Dashboard 照常列出、按钮照常可跳，出现提问/工具/审批/Stop 等动作后自动进 HUD（与 DSH 共用同一个 `awaitingActivity` 标记）。\n- HTTP 服务端口范围固定为 `127.0.0.1:23333-23337`；运行时端口写入 `~/.clawd/runtime.json`\n- Mobile Preview 是独立的 LAN listener，候选范围为 `0.0.0.0:23334-23338`；它不写 `runtime.json`，不得把该范围误写成 hook / custom-agent HTTP ingress 范围\n- 自定义 HTTP Agent 的 sender 必须读取 `~/.clawd/runtime.json`，不能把 23333 写死；注册不等于已连接。custom v1 只支持 `/state`，不支持 `/permission`\n- CodeBuddy PermissionRequest hook 的所有权只认本机 managed URL 或 marker `clawd-on-desk.permission.v1`；纯 `name:\"clawd\"` 不能触发改写/删除。裸 CLI 和 WSL 默认 preserve，Settings/startup/repair 必须显式传 local/custom permission target\n- Remote SSH 的远端 Node 探测要求 Node >= 14；Node discovery/version validation 只在 `src/remote-ssh-node.js`，ordinary tunnel health 与 serialized readiness 在 `src/remote-ssh-runtime.js`，不得互相复制或从已停用脚本另起实现\n- 注册 Claude Code hook 必须 marker-scoped merge：只可更新/删除含 `clawd-hook.js` / `auto-start.js` marker 的 Clawd-owned entry，不得整体覆盖数组或改动无 marker 的用户 entry\n- 注册 Claude Code statusLine 默认只接管空槽或自己的槽（marker `claude-statusline.js`）；本机 Settings 显式开启采集遇到第三方槽时，必须经共存确认并复核原槽指纹，使用 `--local-chain` 和独立的 `clawd-statusline-local-chain.json` 保存/恢复完整原对象。启动/自动修复不得自行取得第三方槽；恢复记录缺失、损坏或不匹配时 fail closed 并保留现场。远程部署仍用 profile 的 `chainStatusline` opt-in 和既有 `--chain` sidecar，不与本机记录混用。订阅配额通过 `metadata_only` POST 进入 session-independent `updateAccountQuota` per-source store；不要把 quota 塞进 `updateSession` opts，也不要以 session 存活作为摄入前提\n- Copilot CLI hooks 走按需自动同步：`hooks/copilot-install.js` 在本地启动仅当 Copilot CLI 已安装且已启用时调用；远端由 Settings Remote SSH deploy controller 调用。路径解析尊重 `COPILOT_HOME` env（trimmed 非空才生效，否则 fallback 到 `~/.copilot`）；`hooks/copilot-hook.js` 的 session-state resolver 同样走 env\n- Remote SSH 的 effective transport 由 `ssh -G` 只读检查决定：ordinary SSH 在没有 retained serialized occupancy 时保持 `context:null` 的 parallel 路径；serialized transport 以有效 target key（不是 profile id）互斥。所有 serialized managed SSH/SCP child 必须持 coordinator 发出的有效 connection/operation context，并通过其 pre-spawn gateway 启动；用户交互终端只有命中 serialized/retained occupancy 时才要求 coordinator 判定 target 完全 idle\n- serialized persistent tunnel 使用同一条 SSH 内嵌 readiness；暂停通过 stdin EOF 请求自然退出并等待 `close`。强杀或带 signal 的 outer `ssh.exe` close 不能证明 nested ProxyCommand 已 drain；timeout/未验证 drain 必须 quarantine，期间禁止新 child、mutation、resume 或 interactive terminal\n- mutation 在 deploy-lock acquire-attempted / lock-owned 后遇到 exit 255、EOF/reset、signal 或其他 unknown result 时不得自动 replay、retry、release lock 或恢复连接；必须保留 primary error 并传播 recovery state，必要时要求 `manual_lock_inspection_required`\n- Remote SSH secure hook 必须同时携带 `CLAWD_REMOTE=1` 与 `CLAWD_SSH_REMOTE=1`，只读 layout identity 并 pin 精确端口；identity 缺失/损坏/不可读必须 fail closed，禁止回退端口扫描\n- Remote SSH deploy-lock acquisition 必须原子化；成功 acquire 后的每个 live mutation 都要在同一远端命令内 fencing 校验，cleanup 还必须锁内重读 installId/profileId/runtimeKey/layoutVersion 所有权。无身份、冲突、ownerless/corrupt lock 均不得自动接管\n- 默认 `account-default` 只支持不同 Unix 账号；同 Unix 账号冲突必须阻止。`profile-isolated` 在真实 SSH/CLI 矩阵完成前由 `CLAWD_ENABLE_EXPERIMENTAL_REMOTE_ISOLATION=1` 发布门隐藏；它只隔离用户级 CLI config/session/runtime 与 Clawd 路由，不代表完整 HOME 或同 UID 安全隔离，project 配置/部分 cache/macOS Claude Keychain auth 仍可能共享\n- Hermes Agent 的 Remote SSH 部署是 `secureDeploy` 内的 `hermes-files` → `install-hermes` 两个阶段，复用同一条 serialized transport、deploy lease、fencing 与所有权检查，没有独立的 Hermes SSH deployer：secure 模式由每个托管 `plugins/clawd-on-desk/` 内的 plugin-local marker `clawd-ssh-secure-v1` latch，latch 后 identity 必须在每次 state/probe/permission 请求时重新读取（禁止 `(mtime,size)` 缓存），且不得发送任何远端 PID / 进程树 metadata；plugin 资产走独立 staging 目录，清理只 `rm -f` 精确文件再 `rmdir`，禁止 `rm -rf`；`REMOTE_IDENTITY_STEP_NAMES` 保持冻结的 8 步不变，不得加入 `installHermes`；Clawd 绝不自动重启 Hermes gateway，托管模块被替换时只报告需要手动重启\n- 禁用 agent 不应卸载 hooks / plugins / extensions：只停止对应 monitor、清理 session / bubble、让 HTTP hook 入口快速 fallback；重新启用未安装 agent 不触发本机 integration sync。卸载集成必须走 Settings Agent 页的 Uninstall / 对应 uninstall 命令，并同时清掉 `integrationInstalled`\n- Kiro 的 `sessionId=\"default\"` 会复用；session alias key 必须按 cwd scope 区分，同时保留旧 `local|kiro-cli|default` 只读 fallback\n- Windows NSIS release 必须产出明确架构的 x64 / ARM64 安装包：`win.artifactName` 保留 `${arch}`，`nsis.buildUniversalInstaller` 保持 `false`\n- 每个 release target 只能保留一个匹配目标架构的 Koffi `koffi.node`；`afterPack` 只允许剪裁 `app.asar.unpacked` 的物理文件，禁止重写 `app.asar`，并必须通过完整 native inventory audit（唯一常设例外是 electron-builder 管理的 Windows ia32 `resources/elevate.exe`）\n- 资源路径统一用 `path.join(__dirname, ...)`\n- 需要编辑发布素材时，先复制到 `assets/source/` 再改，不要直接改工作素材来源不明的文件\n- `assets/source/cloudling-pointer-bridge/` 是 Cloudling 指针桥素材的保留源文件目录；运行时逻辑已内联进主题 SVG，不要把这个 source 目录当临时文件清理\n- 主题状态、sleep/DND、mini mode、状态映射的细节在 `docs/project/theme-state-ui.md`\n- 官方可下载主题（`official-theme-*`）是受管分发层，不是 built-in、也不提升信任：catalog 是固定远端小目录（renderer 只能传 themeId），下载走 Electron main `net.request` 的 manual redirect + 精确 CDN host allowlist + 固定 bytes/SHA-256（未支持 host 返回稳定 `DOWNLOAD_HOST_UNSUPPORTED`，不允许 catalog 扩展 allowlist），ZIP 只在 manager 专属 staging 内流式解压并以 marker-before-rename 同卷提交，最终以 `isBuiltin=false` 加载（`trustedRuntime` 无效）。`setThemeSelection` / `removeTheme` / `officialTheme.commitInstall` / `officialTheme.uninstall` / `theme` update 共用 `lockKey=\"theme\"`；卸载 active 主题必须等 `waitForThemeReloadSettled()`。主仓库附带一份目录快照 `src/official-theme-catalog-snapshot.json`：网络拉取失败时列表先用上一次成功加载的目录（内存 LKG 或磁盘缓存），都没有才用快照；第一次拉取有结果之前（`uninitialized`）不用快照；快照**不作安装依据**，安装仍只认经校验的网络/磁盘目录。快照只作列表回落（仍显示 `offline` 和重试），不含素材与预览图，不写磁盘缓存，且参与版本不能回退的比较；发布前用 `npm run update:official-theme-snapshot` 刷新。不要把 Hash Sage / Whale-chan 的动画素材（APNG / WebP），或把它们写成内置主题的文案带回主仓库\n- Settings 体系里，store 是唯一真相，controller 是唯一写入者；不要绕开 `settings-controller.js`\n- Dashboard 数字快选是**完整 Dashboard 同一页面的临时键盘模式，仅 macOS/Windows**；Linux 明确 NOT SUPPORTED（不是待验证）。平台 gate 的唯一真相是 `shortcut-actions.js` 的 `supportedPlatforms` + `isShortcutActionSupported()`，Settings 展示、globalShortcut 注册/录制、设置命令和冲突占用都必须服从它；遗留的不支持绑定只忽略执行，不删用户 prefs、不占其他快捷键。darwin/win32 的 Dashboard 页面活在 `WebContentsView` 里，`BrowserWindow.fromWebContents()` 对它返回 null、BaseWindow 不触发 `ready-to-show`；页面 WC 一律从 owner 取。禁止用 `hide()`+`showInactive()` 归还已显示的普通宿主（实测会遮挡来源窗口），只能 opacity/input parking 并幂等恢复捕获值。详见 `docs/project/theme-state-ui.md`\n\n## Testing\n\n- 自动化测试使用 Node 内置 test runner：`npm test`\n- `test/*.test.js` 覆盖核心 unit/contract、installer、route、UI/runtime 与 Remote SSH transport/coordinator/identity；部分 fixture 会启动 Node、shell 或 Git Bash 子进程，缺少依赖时可能 skip，不能把全套结果概括成纯逻辑或等价真机验证\n- Remote SSH 真机矩阵与记录在 `scripts/manual/README.md`；Windows OpenSSH + Codespaces stdio 边界及 ordinary-host V15 release gate 不能从 unit tests 互相推断，无法执行时必须明确记录 pending / residual risk\n- Windows Terminal 真机、GUI smoke 与清理必须假定多个 tab/window 共享进程：不得按 PID/进程名 `taskkill`、`Stop-Process` 或宽泛终止 WindowsTerminal、Codex、`cmd.exe`、`ssh.exe`、OpenConsole、conhost。测试终端只能在明确 test-owned session 内 `exit`；无法证明 ownership 就保留现场并请用户手动关闭\n- 当前开发环境是 Windows-first；macOS 特定路径无法在这里手动 QA，改到 mac 逻辑时要用 code-review\n\n<!-- File: .claude-plugin/marketplace.json (Tokens: ~300 | Category: marketplace) -->\n# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.claude-plugin/marketplace.json)\n\n<!-- File: .claude-plugin/plugin.json (Tokens: ~300 | Category: plugin-manifest) -->\n# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.claude-plugin/plugin.json)\n\n<!-- File: .cursor/mcp.json (Tokens: ~300 | Category: mcp-config) -->\n# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/rullerzhou-afk/clawd-on-desk/HEAD/.cursor/mcp.json)\n</yakaai_skills>"}