architecture.md 回答「computer-host 是什么、边界在哪、契约长什么样」。pairing.md 回答控制面如何第一次连上宿主、密钥存在哪。stability.md 回答「dsh 崩了谁救、host-agent 崩了谁救、一户内存爆了怎么只死这一户」。本文放大其中一层:一台托管 dsh 从无到有、从活跃到休眠再到删除,每一步谁触发、host-agent 做了什么、磁盘上留下什么。所有行为以 host-agent/src/(supervisor / gateway / control)与 ApeMind 侧 aperag/domains/computer/ 的当前实现为准;默认参数来自 host-agent/src/config.ts。
心智模型:把每个实例当成一台 scale-to-zero 的数据库实例——存储(租户 HOME 目录)常驻在 PVC 上,计算(dsh web 进程)按需拉起、闲置回收;唤醒靠流量触达,不靠常驻心跳。
数据根 COMPUTER_DATA_DIR(默认 /data,挂 PVC)。每个实例一棵目录树,实例键即目录名:ApeMind 的 computer_instance.id(ci + 16 hex),对宿主不透明,必须匹配 ^[A-Za-z0-9_-]{1,64}$。镜像里另有一份全租户共用的 CLI,不在 PVC 上:
/usr/local/bin/apemind 镜像内置 CLI(构建时锁版本 + sha256),所有实例进程经 PATH 共用
/opt/dsh-seed/.dsh 镜像内置 web profile seed(含锁版本 @xmanrui/dsh-im 与 @michengai/dsh-automation),只读,不进 PVC
/data/users/<instance_key>/ HOME,0700(防跨租户遍历,与 uid 隔离无关,恒开)
workspace/ dsh 进程的 cwd;agent 读写的文件都在这里
.dsh/ DSH_HOME:dsh 自己的会话、缓存、settings
AGENTS.md 托管引导(host-agent 按 env.json 渲染,手工编辑下次 spawn 覆盖)
.apemind/ 托管注入面,只有 host-agent 写:
meta.json 实例持久状态(desired / lastTrafficAt / createdAt / uid),0600
env.json 控制面注入的环境变量(含 APEMIND_API_KEY),0600
managed.cordis.yml dsh --patch 挂载的托管配置(MCP + 模型投影),0600
dsh.log dsh 进程 stdout/stderr,追加写,0600
.config/apemind/ 托管 CLI 凭证(host-agent 按 env.json 写 default profile)
config.json current_profile=default,0600
profiles/default/state.json base_url + api_key,0600
.config/ .cache/ .local/share/ XDG 三件套,指给 dsh 与租户内工具
目录树在实例首次创建时一次建齐;开启 uid 隔离(COMPUTER_UID_BASE > 0)时整棵树 chown 给该实例分配的 uid。
| 区域 | 写入方 | 性质 |
|---|---|---|
/usr/local/bin/apemind |
镜像构建 | 全租户共用只读二进制,不随 PVC、不随实例删除 |
.apemind/ |
只有 host-agent(受控制面 ensure 驱动) | 投影。权威在 ApeMind 数据库(绑定身份的 managed key、MCP 地址、模型清单);磁盘上这份只是启动进程所需的物化,删了可以从控制面重新生成 |
.dsh/AGENTS.md |
只有 host-agent | 托管引导。权威是 env.json;每次 spawn 前重写。.dsh/ 其余文件仍是 dsh 私有 |
$DSH_HOME/profiles/web 里的默认插件 |
host-agent 只补缺 | 默认 IM / 定时任务插件。权威是镜像 /opt/dsh-seed/.dsh;已有版本和其它插件不覆盖 |
.config/apemind/ |
只有 host-agent | CLI 凭证投影。dsh 从 bash/工具子进程剥掉名字含 KEY、PASSWORD、SECRET、TOKEN 的环境变量,agent 跑 apemind 时读不到 APEMIND_API_KEY;这份 profile 是 CLI 的官方 env 回退。权威仍是 env.json,每次 ensure/spawn 覆盖 |
.dsh/ 其余 |
只有 dsh 进程 | 上游运行时私有。ApeMind 不读它当配置源,也不把它回流主站 |
workspace/ |
租户(经 dsh agent) | 用户磁盘。闲置回收、host 重启都保留;只在显式删除实例时销毁 |
这个分界是双向承诺:ApeMind 改配置永远走「更新数据库 → ensure 重投影」,不直接改 .dsh/settings.yaml;反过来 dsh 里发生的会话、用户自己改的偏好也不会被 ApeMind 收走。落在 $DSH_HOME 与 $XDG_CONFIG_HOME 里的托管文件(AGENTS.md、CLI profile)是宿主派生的,手工编辑下次 spawn 覆盖。
- 二进制位置:
/usr/local/bin/apemind,镜像层。dsh 进程的PATH继承自 host-agent,所以 agent 开箱就能跑apemind。升级 CLI = 换镜像 tag,不改 PVC。 - 身份在何时注入:
POST /api/v2/computer/open。控制面确保绑定身份的托管 key(个人=用户本人,组织=该组织服务用户),把APEMIND_API_KEY、APEMIND_BASE_URL(由 MCP URL 去掉/mcp)、组织实例另加APEMIND_ORG_ID一并放进 ensure 的env。宿主整体重写该实例.apemind/env.json,并派生managed.cordis.yml、.dsh/AGENTS.md与.config/apemind/CLI profile。 - 会不会持久化:会。权威投影是
env.json(PVC,0600)。同一轮 ensure/spawn 再写一份 CLI profile($XDG_CONFIG_HOME/apemind,0700/0600),因为 dsh 工具子进程会剥掉APEMIND_API_KEY,CLI 必须靠这份文件认证。MCP 与模型网关仍读 dsh 进程环境里的 key,不受剥离影响。闲置唤醒再 spawn 时两份一起按env.json重写。下一次 open 整体覆盖(key 轮换走这条);如果托管环境快照发生变化,host 会在这次 ensure 中重启正在运行的 dsh,再返回新的实例状态,因此 MCP/LLM 和 CLI 一起采用新投影。相同快照不会触发重启。
控制面 DELETE /v1/instances/{key} = 停进程 + 拆回环 iptables 规则 + rm -rf 整个 HOME。工作区、会话、注入配置一起消失;下一次 ensure 从零重建。这是「重置」,不是「停止」。目前没有产品页面入口,属于运维操作。
三份正交事实:
- desired(持久,落
meta.json):running | stopped。只有控制面 ensure 会改。表达「允不允许为这个租户启动进程」。闲置回收不准改它。 - status(内存):
stopped | starting | running | error。当前有没有活着的 dsh。host-agent 重启后全部归stopped,不落盘。 - lastTrafficAt(持久,落
meta.json):最后一次租户数据面流量。闲置 sweep 和重启后要不要拉回都读它。init()不得写成「现在」。
stateDiagram-v2
[*] --> stopped: createInstance(建目录/分配 uid)
stopped --> starting: start(ensure desired=running / 网关 wake / 崩溃退避到期)
starting --> running: 回环端口 TCP 探测通过
starting --> error: 启动中退出 / 90s 内未就绪(SIGKILL)
running --> stopped: idleSweep 闲置回收(desired 保持 running)
running --> stopped: ensure desired=stopped(用户主动停止)
running --> stopped: 进程退出且退避次数未超限(自动安排重启)
running --> error: 连续崩溃 > 5 次,放弃重启
error --> starting: 下一次 ensure/wake(失败计数清零)
stopped --> [*]: DELETE(删整个 HOME)
转换细节:
- 启动就绪判定:spawn 后每 300ms 探测一次回环端口,
settings.json的ready_timeout_sec(出厂 90s)内通即running;超时 SIGKILL 并抛 StartError(控制面收到 409)。ApeMind 的 ensure HTTP 超时 120s,就是为了盖住这 90s——冷启动是同步阻塞的,接口返回时实例已可用或已明确失败。 - 停止:SIGTERM,
settings.json的stop_grace_sec(出厂 10s)内没退干净则 SIGKILL。 - 崩溃退避:
running中的进程意外退出且 desired 仍是 running 时,按min(500ms × 2^n, 30s)退避自动重启;连续超过 5 次转error放弃。任何一次 ensure/wake 都会清零失败计数、重新尝试。 - 端口是易耗品:每次启动从
COMPUTER_PORT_BASE(默认 31000)向上找空闲端口,重启后端口可能变。会话 cookie 只含实例键不含端口,所以对用户透明。 - host-agent 重启:
init()扫/data/users/逐个读meta.json恢复注册表,所有实例 status=stopped。不按desired全量拉起。网关先听,再按闲置策略推导:desired=running且lastTrafficAt存在,并且闲置关闭或流量仍在窗口内,则限流拉回。否则保持休眠,等 cookie / 打开再wake()。host-agent 进程自己退出时由 Docker / K8s 整容器拉起,镜像内不再套自动重启,见 stability.md。
sequenceDiagram
participant U as 浏览器
participant A as ApeMind api
participant C as host-agent 控制面(:9090)
participant S as supervisor
participant D as dsh 进程
participant G as host-agent 网关(:8080)
U->>A: POST /api/v2/computer/open (可带 org_id)
A->>A: 解析/惰性创建 computer_instance 行(id 即宿主租户键 ci*)
A->>A: 确保绑定身份的 managed API key(个人=本人;组织=服务用户)
A->>C: PUT /v1/instances/{ci*}<br/>{desired: running, env: {APEMIND_API_KEY, APEMIND_BASE_URL, APEMIND_MCP_URL, …}}
C->>S: ensure(key, running, env)
S->>S: createInstance:建目录树+0700,分配 uid,写 meta.json
S->>S: writeInstanceEnv:写 env.json;派生 managed.cordis.yml 与 .dsh/AGENTS.md
S->>D: spawn dsh(见 3.2),cwd=workspace
S->>S: 每 300ms TCP 探测回环端口,通 → running;装回环 iptables(可选)
C-->>A: 200 InstanceView {status: running, port, started_at, ...}
A->>A: 签 60s 短票(HMAC,含防重放 nonce)
A-->>U: {url: https://computer.../open/<ticket>}
U->>G: GET /open/<ticket>
G->>G: 验签 + nonce 防重放 → 签 12h 会话 cookie
G-->>U: Set-Cookie computer_session → 302 /
U->>G: 后续全部 HTTP/WS(带 cookie)
G->>D: Host 改写 127.0.0.1:port,剥 Origin/sec-fetch-*
命令模板 COMPUTER_DSH_COMMAND,默认:
dsh {patch} --profile web --no-open --port {port}
{port}:本次分配的回环端口。{patch}:存在.apemind/managed.cordis.yml时展开为--patch <该文件>,否则消失。launcher 标志必须在 web 应用自身标志之前,所以模板里用显式占位符控制位置。
进程环境(不继承 host-agent 的环境,白名单构造):
| 变量 | 值 |
|---|---|
PATH / LANG |
继承 PATH;LANG 默认 C.UTF-8 |
HOME |
/data/users/<key> |
USER |
实例键 |
DSH_HOME |
$HOME/.dsh |
XDG_CONFIG_HOME / XDG_CACHE_HOME / XDG_DATA_HOME |
$HOME/.config / .cache / .local/share |
APEMIND_USER_ID |
实例键(对 host 不透明的租户字符串)。不是 ApeMind 用户 id |
APEMIND_INSTANCE_ID |
与 APEMIND_USER_ID 相同的实例键;新代码读这个名字 |
DSH_PERMISSION_MODE |
托管实例拉起时写入 danger-full-access。这是 dsh 官方的进程级部署覆盖,新会话默认 Full access;用户之后在 Settings 改 permission.defaultPreset 仍作用于以后的会话。已有会话的权限钉死不变。控制面若在 env.json 显式给出该键,以其为准。 |
env.json 里的全部键值 |
控制面注入。当前契约:APEMIND_API_KEY(绑定身份托管 key)、APEMIND_BASE_URL(API 源站,不依赖 MCP)、APEMIND_MCP_URL、APEMIND_LLM_BASE_URL、APEMIND_LLM_MODELS、可选 APEMIND_LLM_DEFAULT_MODEL(工作区默认 chat 模型 id,且必须出现在 APEMIND_LLM_MODELS 里);组织实例另有 APEMIND_ORG_ID;可选 APEMIND_DATA_PLANE_USERNAME。键名限 ^[A-Z][A-Z0-9_]{0,63}$ |
uid 隔离开启时以分配的 uid/gid 运行;stdout/stderr 进 .apemind/dsh.log。
managed.cordis.yml 有四段内容。IM 段始终写出;其余按 env 是否齐全条件渲染:
- IM 机器人 RPC(始终):给
xmanrui-dsh-im写rpcAuthority: trusted-host。网关把浏览器 Host 指到回环,面板域名要能管机器人。插件本体在镜像 seed,host-agent 拉起前写入$DSH_HOME/profiles/web。 - MCP 工具(
APEMIND_MCP_URL+APEMIND_API_KEY):插入官方@deepseek-ai/dsh-mcp-client插件行,streamable-http 指向 MCP 地址,Authorization 头用!!js从进程环境读APEMIND_API_KEY。 - 模型提供方投影(
APEMIND_LLM_BASE_URL+APEMIND_API_KEY+ 非空APEMIND_LLM_MODELS):在llm-pi-ai行的 config 上合并一个名为apemind的 provider(api: openai-completions、baseURL指 ApeMind 的 OpenAI 兼容网关、apiKeyEnv: APEMIND_API_KEY),模型列表来自APEMIND_LLM_MODELS——一个 JSON 数组,元素{id, name?, context_window?, vision?}。id是 ApeMind 模型 id(dsh 发起补全时原样回传,网关按它解析上游);name写成 dshPiAiModelProfile.name(选择器文案),不是 provider 级的displayName。JSON 非法或元素缺id时 ensure 直接失败(控制面 400),不写任何文件。每次拉起 dsh 都会按当时的env.json重写 patch,避免宿主升级后仍读到旧 yaml。 - 默认模型路由(
APEMIND_LLM_DEFAULT_MODEL且该 id 已在投影列表里):覆盖组合层agent-default-model为{provider: apemind, model: <id>},替换出厂的deepseek-official/deepseek-v4-flash。用户之后在 dsh 里另选模型仍写$DSH_HOME/settings.yaml,覆盖组合默认值。宿主不写 settings.yaml。
这些段落都只携带环境变量名,密钥不落在 yaml 里,文件泄露不等于密钥泄露(env.json 仍含密钥本体,0600 + uid 隔离保护)。patch 对 dsh 的实际生效行为按锁定的 dsh 版本在 staging 验收(与 MCP 行同一口径)。
磁盘上有四份托管文件,权威如下:
| 文件 | 权威 | 含密钥 |
|---|---|---|
.apemind/env.json |
控制面注入的进程环境;spawn 白名单读它 | 是(APEMIND_API_KEY) |
$XDG_CONFIG_HOME/apemind/profiles/default/state.json |
CLI 在 env 被 scrub 后的默认凭据与 org_id / workspace_kind |
是 |
.apemind/workspace.json |
工作区类型、组织 id、实例键、数据面用户名;给 agent / doctor 读 |
否 |
$DSH_HOME/AGENTS.md |
给模型看的工作区说明;组织版与个人版文案不同 | 否 |
$DSH_HOME/AGENTS.md 在 APEMIND_API_KEY + APEMIND_BASE_URL 齐全时生成。组织版写明没有个人空间、whoami 里的 ro 是平台账号角色、不要用 org role list 判断写权限;个人版写明不要传 --org-id。它是托管文件——每次拉起 dsh 前按 env.json 重写,手工编辑不保留;只出现 env 变量名与 id,不出现密钥。镜像内置 apemind CLI(/usr/local/bin/apemind,构建时锁版本 + sha256 校验),实例进程经继承的 PATH 直接可用。APEMIND_ORG_ID 同时写入 CLI profile 和 workspace.json,不依赖 bash 子进程继承。
同一条 POST /open 路径,ensure 幂等:
- 目录已在,跳过创建;
env字段存在则整体重写env.json、patch 与AGENTS.md。 - 进程已 running 则不动——正在运行的进程环境不会变。组织实例的绑定身份是服务用户(与谁打开无关);open 把同一把服务 key 再写进
env.json,运行中进程仍用上一次 spawn 读到的那份,要生效等下一次冷启动。这是当前接受的语义(见 architecture.md §5)。 - 每次 open 都签发新的 60s 短票;旧会话 cookie 不受影响,同一浏览器多标签共享同一 cookie。
没有心跳协议。 活跃度就是网关观测到的数据面流量:
- 每个代理的 HTTP 请求 touch 一次
lastActivity,并节流写入meta.json的lastTrafficAt; - WebSocket 双向任何数据帧都 touch(1 秒节流,避免热连接高频写时间戳);
- dsh 自己不上报任何东西,浏览器页面关闭 → WS 断 → 流量归零。
回收循环:supervisor 每 60s 扫一遍,status=running 且 now - lastActivity > idle_timeout_sec(出厂 1800s = 30 分钟,见 /data/settings.json)的实例停进程。desired 保持 running——这正是「休眠」和「用户主动停止」的区别。宿主重启后用同一把尺子:假如宿主没死,闲置策略现在还会不会让它开着;会则限流拉回,不会则继续休眠。
唤醒路径(网关内联完成,不经过 ApeMind):
- 带合法 cookie 的请求到达网关;
- 实例存在且 desired=running、status≠running → 网关调
wake()同步拉起(用env.json现存内容),就绪后继续反代本次请求; - 浏览器感知到的只是这一次请求慢了几秒(dsh 启动 + 就绪探测)。
对照数据库的说法:desired 是「实例是否存在于服务目录」,status 是「计算是否在跑」,HOME 是永远在线的存储层,唤醒延迟 = 进程启动时间(秒级),计费/容量只看 running 数。
各请求形态在异常态的响应(HTML 指 GET/HEAD 且 Accept 含 text/html):
| 场景 | HTML 请求 | API/WS 请求 |
|---|---|---|
| 无/过期 cookie | 302 主站 /workspace/computer |
401 / WS 403 |
| 实例从未创建 | 302 主站 | 404 |
| desired=stopped(用户主动停的) | 302 主站 | 503 / WS 403 |
| desired=running 但唤醒失败 | 502 | 502 |
POST /api/v2/computer/stop → ensure desired=stopped → SIGTERM/SIGKILL 停进程。之后网关不会唤醒它(wake 只作用于 desired=running),HTML 访问一律 302 回主站。恢复的唯一路径是再点一次「打开」。组织实例上任何成员 stop 对全组织生效。
| 触发 | ApeMind 行为 | host-agent 控制 API | host 侧动作 |
|---|---|---|---|
| 工作区页加载 + 每 10s 轮询 | GET /api/v2/computer |
GET /v1/instances/{key} |
返回 InstanceView;404 → 前端显示「尚未创建」 |
| 点「打开」 | POST /api/v2/computer/open |
PUT /v1/instances/{key} desired=running + env |
建目录/写注入/拉进程/等就绪,同步返回 |
| 点「停止」 | POST /api/v2/computer/stop |
先 GET,存在才 PUT desired=stopped |
停进程,desired 落盘 |
| 管理员「校验连接」 | 后台配置页 probe | GET /healthz |
返回 version、实例计数/上限、load1、空闲内存 |
| 重置租户(无产品入口) | 运维直调 | DELETE /v1/instances/{key} |
停进程 + 删 HOME,204 |
| 撤权(移出成员/改角色/停用组织) | 事务成功后 best-effort 调用 | POST /v1/instances/{key}/revoke-sessions |
会话代数 +1 落盘,存量会话 cookie 全部失效 |
鉴权全部是 Authorization: Bearer $COMPUTER_CONTROL_TOKEN(常量时间比较)。错误映射:401 未认证、400 参数/实例键非法、404 实例不存在、409 启动失败(StartError)、507 容量满(实例数达 max_instances 或端口耗尽)。ApeMind 侧把非 200 统一包装成 ComputerHostErrorException 冒给前端。
网关是数据路径上唯一一跳(ApeMind 不在数据路径上)。转发卫生:
- 请求:剥
Origin/Referer/sec-fetch-*(dsh 的回环信任门禁才会放行)、hop-by-hop 头、Accept-Encoding固定identity(禁压缩,保逐字流式);Host改写为127.0.0.1:<port>;computer_sessioncookie 从 Cookie 头里剥掉再转发,dsh 看不到会话凭证,租户自己的其他 cookie 原样保留。 - 响应:剥 hop-by-hop 头,加
X-Accel-Buffering: no(提示外层 Ingress 不缓冲)。 - WebSocket:
upgrade事件里手写重构握手行(同样的头卫生 + Host 改写),然后两条 socket 原始对拷;数据帧驱动活跃度 touch。 - 进门校验:带
Origin的请求必须等于COMPUTER_PUBLIC_ORIGIN才放行(无 Origin 或null视为非跨站导航,放行);/open/<ticket>验签 + 单进程内存 nonce 防重放(60s 内复用直接 403)。
托管 dsh 对 ApeMind 的回程有两条,都用同一把 managed key 做 Bearer:
- MCP:
managed.cordis.yml挂的官方 MCP 客户端插件,streamable-http 直连APEMIND_MCP_URL。这条是在线 RPC,不是文件同步——知识库内容不会被镜像进workspace/。 - 模型补全:投影的
apemindprovider 把补全请求发到APEMIND_LLM_BASE_URL(ApeMind 的 OpenAI 兼容网关/v1/llm),model字段是 ApeMind 模型 id;网关在 ApeMind 侧解析成真实提供方账号(base_url + 密钥)后原样透传,提供方密钥永远不进租户环境。
managed key 的生命周期在 ApeMind 侧:api_key 表里 is_managed=true, protected_reason="computer" 的行,每用户至多一把活跃的,复用或按需创建;吊销/轮换只影响 MCP 回程,不影响实例进程本身。
| 数据 | 方向与通道 | 状态 |
|---|---|---|
| 身份 / 谁能开机 | 只在 ApeMind(登录态 + 组织成员校验);host 只见不透明实例键 | 已有 |
| 绑定身份的 managed API key、MCP / CLI 地址 | ApeMind → ensure env → .apemind/env.json → dsh 进程环境;身份是个人本人或组织服务用户,与谁点开无关 |
已有 |
| 模型提供方目录 | ApeMind → ensure env(APEMIND_LLM_BASE_URL / APEMIND_LLM_MODELS)→ managed.cordis.yml provider 行;补全流量走 ApeMind OpenAI 兼容网关(ApeMind 为权威,dsh 设置页在非 loopback 浏览器下本就不可用) |
已有 |
| CLI 二进制与凭证 | 镜像 /usr/local/bin/apemind;进程 env 给 MCP/LLM;CLI profile 给 agent 的 bash |
已有 |
| 知识库 / 检索 / 智能体工具 | dsh → MCP 在线调用;写面 / 长尾走 CLI | 已有 |
workspace/ 文件 |
只属于这台实例;不自动入库、不回流主站 | 恒定边界 |
.dsh/AGENTS.md |
host-agent 按 env 派生;其余 .dsh/ 只属于 dsh |
已有 |
.dsh/ 会话与偏好 |
只属于 dsh;ApeMind 不读不写 | 恒定边界 |
| dsh 聊天记录 ↔ ApeMind 对话历史 | 不互通 | 恒定边界 |
| 参数 | 默认 | 语义 |
|---|---|---|
idle_timeout_sec(/data/settings.json) |
1800 | 闲置回收;0 关闭。热更新见 host-settings.md |
ready_timeout_sec |
90 | 冷启动就绪窗口;探测间隔 300ms |
stop_grace_sec |
10 | SIGTERM 后宽限,超时 SIGKILL |
session_ttl_sec |
7200(2h) | 会话 cookie 寿命;实例被 revoke-sessions 后立刻整体失效 |
| 短票 TTL | 60s(ApeMind 侧常量) | /open/<ticket> 兑换窗口,一次性 |
COMPUTER_PORT_BASE / max_instances |
31000 / 200 | 回环端口段与容量上限 |
COMPUTER_UID_BASE / COMPUTER_LOOPBACK_ISOLATION |
0(关)/ 关 | 每实例 uid 与回环 iptables 隔离;staging 开启(uidBase=20000) |
| 崩溃退避 | min(500ms×2ⁿ, 30s),连续 >5 次放弃 | 代码常量 |
| ApeMind ensure HTTP 超时 | 120s(读接口 10s) | 盖住 90s 就绪窗口 |
| 前端状态轮询 | 10s | 工作区 Computer 页 |
- 多 host 调度与租户指派(architecture.md §4 留了子域扩展位;每台 host 的配对见 pairing.md)。
- 按租户拆 Pod/microVM 的强隔离。
- dsh 版本升级流程(镜像 tag + 回归,见 README)。
- 正在 running 的进程热替换 env:open 只改磁盘,进程环境要等下一次冷启动。
- 冷启动时 ApeMind 调哪个 API?host-agent 依次做哪些事、进程用什么参数和环境起来?
apemindCLI 在哪、身份何时注入、会不会持久化、持久化在哪一层?.apemind/、.dsh/、workspace/、镜像层 CLI 分别归谁写,删实例时哪些数据消失?- 「闲置休眠」和「用户主动停止」在状态机里差在哪个字段?各自怎么恢复?
- 为什么不需要心跳?活跃度信号从哪来,多久无流量会停,唤醒发生在哪一层?
- 闲置超时的权威在 env 还是磁盘,控制面怎么改(host-settings.md)?
- 组织实例换人打开后,绑定身份会不会换成那个成员?MCP / CLI 用的是谁?
- host-agent 容器重启后,正在休眠/运行的实例分别经历什么?