# Workspace 唯一事实来源是 [`docs/plan.md`](plan.md)。本文定义磁盘布局。 ## Project 布局 每个 Project(DSH workspace 根目录)一个 `workspace/` 交付树。本地 Docker 下 按 Worker 白名单顶层目录逐目录 bind(`.git/` 与 `.dsh-pentester/` 物理上 不在容器内);远程 Docker 下是共享 named volume 的本地镜像,阶段边界才做 full sync。详见下文「规则」。 ``` / └── workspace/ # 交付树 = 容器 /workspace(仅当前 Target) ├── .dsh-pentester/ # Workspace 级注册表 │ └── targets.json # Target registry(schemaVersion 1) └── targets/ └── / # 每个 Target 独立子树 ├── .git/ # 宿主侧 git 仓库(全跟踪;不随 volume 同步) ├── .dsh-pentester/ # 宿主控制态(Worker 不可修改) │ ├── run.json # 唯一机器状态:target/scope/RoE/language/stageAdvancePolicy(automatic|manual|custom+instruction;缺省 automatic)/status(active|stopped|completed)/currentStage/stageStatuses/delegations + id(UUID)/instanceId(7 hex)/revision(单调递增 mutation fence)/preEngagementCallId/restartedFrom(schemaVersion 3) │ ├── workspace.json # 工作区元数据(id/target/language/created/gitBranch) │ └── events.jsonl # append-only 事件日志 ├── .gitignore # tmp/ cache/ *.log ├── target/ # target.json scope.md roe.md inputs/ ├── stages/ │ ├── 01-pre-engagement/ │ │ ├── summary.md # 宿主在 advance 时写 │ │ └── delegations/ │ │ └── D-001/ │ │ ├── input/ # task_prompt 快照(不可变) │ │ ├── work/ # 默认执行 cwd(过程文件) │ │ ├── artifacts/ # 给后续 Worker 的正式产出 │ │ ├── evidence/ # 支撑结论的证明材料 │ │ └── result.md # 当前正式可交付结果(Worker 写/更新) │ ├── 02-intelligence-gathering/ … │ └── 07-reporting/ … ├── findings/ # 提升后的 findings.md / threat-model.md ├── report/ # report.md(最终交付) └── traffic/ # 流量记录(pcap/mitm;git 全跟踪) ``` 规则: - **Target 隔离**:每个 Target 拥有独立的 `.git/`、`.dsh-pentester/`、`run.json`、 文件系统树。Worker 只看到当前 Target 的 `/workspace`,看不到兄弟 Target。 - **Workspace 级**:`workspace/.dsh-pentester/targets.json` 是唯一的跨 Target 共享文件, 只记录 Target 注册信息(id、rootSessionId、dirName)。 - 每 Delegation 一个独立目录,ID 在 branch timeline 内跨 Stage 全局递增。 - `result.md` 是 Delegation 的当前正式可交付结果:Worker 写/更新。 - `target/inputs/pre-engagement.md` 记录七题确认的审计摘要(Target / Scope / RoE / Language / Stage Advance Policy —— policy 由 proof 派生,模型参数不可绕过)。 - Trace 的 Agent 下方 Deliverable 节点读取各 delegation 的 `result.md` / `evidence/` / `artifacts/` 元数据(count + sample names, 不读正文)与 canonical `findings/`、`assets/`(按 sourceDelegationId 聚合); `work/` scratch 不进入 Trace。 - Worker 默认 cwd = 自己的 `work/`;只写自己的 delegation 目录,可读整个 `/workspace/`。 - 容器 `/workspace`:远程 Docker = 该 Target 的 named volume;本地 Docker = 按 Worker 白名单顶层目录(`target/ assets/ findings/ stages/ report/ traffic/`) 逐目录 bind —— `.git/` 与 `.dsh-pentester/` 物理上不在容器内(不可读、不可写)。 - 同步(仅远程模式):push 与 pull 都是 mirror 语义,且都排除 `.git/` 与 `.dsh-pentester/`(集中 PathPolicy:pull 在任何写盘之前拒绝控制态条目, 绝不被容器侧归档覆盖宿主 run.json)。pull 对普通文件做 temp+rename 原子 发布;transport 全程不跟随 symlink;受资源上限约束 (条目数 / 单文件 / 总量 / 路径长度)。 - Git:每个 Target 独立 `.git/`。阶段完成时宿主做约定式 commit + tag。 rollback 只影响当前 Target,兄弟 Target 不受影响。 - 审计依赖 DSH session log、events.jsonl 与磁盘交付物。 不需要:`STATUS.md`、`INDEX.*`、`manifest.json`、`logs/`、Deliverable Registry、 全局 `assets.json`。 ## Pentester Home 布局 插件自身的配置与运行时数据在 Pentester Home(`DSH_PENTESTER_HOME` > `$DSH_HOME/dsh-pentester` > `~/.dsh/dsh-pentester`),与任何 project 交付树 分离,不 mount 进容器: ``` ~/.dsh/dsh-pentester/ ├── settings.json # Settings V4(dockerHost / stageAgents / stageAgentsDefaultsVersion / mcpServers) ├── agents/ # Custom Agent Profiles(热更新) ├── skills/ # Custom Skills —— 自己加 skill 就放这里 │ └── .skill/ │ └── SKILL.md # frontmatter name+description,正文即指令 ├── agent-overrides/ # Builtin Agent 用户 Overlay(.yml) ├── skill-packs/ │ └── 1.0.1/ # 已安装的 Builtin Skill Pack(Settings 初始化) │ ├── .installation.json │ └── skills/ … # builtin 962 skills(只读) └── runtime/ └── skill-snapshots/ # 每 Delegation 的 frozen grant 快照(Host-only) └── //-/ ├── manifest.json # frozen grant(native provider 的 grant 来源) └── .skill/ … # bundle 副本(skill tool on-demand 读取) ``` 加自定义 skill:在 `skills/` 下建 `.skill/SKILL.md` 即可(详见 [skill-runtime-v4.md §4.1](skill-runtime-v4.md))。目录热更新,无需重启。 ## 多 Target 语义 ``` Project └── Shared Workspace ├── Target A │ ├── Root Session A │ └── PentestRun A ├── Target B │ ├── Root Session B │ └── PentestRun B └── Target C ... ``` - 同一 Target 再次发起 → 询问 [Continue] [Restart] - Continue:打开原有 Root Session,不创建新 Run - Restart:清除该 Target 旧数据,创建新 Run,当前 Session 成为新 controller - 不同 Target:必须新建 Pentester Root Session ## Runtime workspace 映射(Wave 14) Host 侧的 workspace 布局不变(上表)。**Runtime 侧**另有各自的物理根: ```text Docker /workspace ← 容器内 workspace 根 (本地模式:按 Worker 白名单顶层目录 bind host 目录; 远程模式:per-run named volume + 镜像同步) SSH //workspace ← 远端 workspace 根 //.control ← host-owned exec guard (workspaceRoot 默认 /tmp/dsh-pentester;SSH 无 Toolbox 镜像语义) ``` Worker 只看到**逻辑路径**(workspace 相对 POSIX 路径): ```text stages/-/delegations/D-00N/work ← Delegation 默认 cwd ``` `pentester_exec` 的 `cwd` 相对它解析(默认 `.`)。绝对路径、`..`、 `.git`、`.dsh-pentester` 一律被拒绝(`src/runtime/logical-path.ts`)。 Worker 永远不需要知道 `/workspace/...` 或远端 SFTP 路径。 远端同步语义与 Docker 远程模式一致:push 排除 `.git` / `.dsh-pentester` (Host 控制态)与 symlink;pull 是**镜像**语义(Runtime 侧没有的本地幽灵 文件会被删除,控制态除外),文件本地原子发布(tmp + rename)。