# DSH Visual Acceptance V0.1 技术架构 > English companion: [architecture.en.md](architecture.en.md). 架构边界变更时,两个版本必须同次同步。 > 本文区分实测机制与目标设计。详见 [Spike 报告](spike-report.md)。 ## 1. 架构结论 采用“核心中立、DSH 薄适配、无常驻服务”的分阶段混合架构: ```text DSH Web Client conversation.view │ ▼ DSH Host Adapter run lifecycle / workspace boundary / artifact access │ ▼ Local Runner ───────── Provider Adapters Chrome CDP ModLens / Vision CLI / optional VLM │ ▼ Acceptance Core schema / issue identity / decision / retest │ ▼ Workspace-local Storage manifests / evidence / screenshots / reports ``` V0.1 不启动常驻 Daemon。每次 Run 由 DSH Host 启动 Runner,结束后释放 Chrome、监听端口和临时目录,降低鉴权、端口冲突和僵尸进程成本。 ### 当前闭环 Beta 实装 截至 `0.1.1-closed-loop-beta`,已落地的链路是: ```text conversation.view UI → localhost Host API → workspace/session validation → Chrome CDP deterministic runner → Finding Candidate → project-level Issue + append-only Decision → local read-only Change Package → immutable Matrix Retest + candidate relations → human verification ``` Provider 实际推理和自动 Agent 会话注入仍是目标架构,不在当前 Beta 中。异常信号只生成 Candidate;正式 Issue、Decision 与 `resolved` 均需要人工操作。当前交接边界是本地 Markdown/JSON 修改包及“复制”,不是“已发送给 Agent”。 ### `0.1.2-responsive-acceptance` 源码候选 本轮保持上述模块边界,新增四项薄能力:`coverage-presets.mjs` 生成版本化 Matrix;Host 的 `/breakpoints` 读取可访问样式表并返回完整性;Runner 增加基础质量事实、截图内容校验和同 Matrix Diff;Checkpoint 增加受控 `actions`。Run Schema 升为 `0.1.2-responsive-acceptance`,Issue/Decision/Change Package 继续使用 `0.1.1-closed-loop`,避免把独立生命周期对象隐式迁移。 ## 2. 模块边界 ### Acceptance Core 不得依赖 DSH、React、Chrome 或任一视觉 Provider,负责: - 版本化 Schema; - Target 和 Matrix; - Evidence 来源; - Issue 指纹与生命周期; - 人工 Decision; - Retest 合并; - 声明强度检查。 ### Local Runner 负责确定性事实: - 启动/连接 Chrome; - 固定 CSS 视口和主题; - 导航与 Ready 条件; - console、exception、request、HTTP 状态; - 图片、样式、字体; - Layout/Visual/Requested Viewport; - 横向溢出; - Viewport Meta、基础可访问名称/标签、重复 ID 与水平越界交互元素; - 截图内容校验、原 Matrix Retest 像素 Diff 与环境清单。 ### Provider Adapter 统一契约: ```ts interface VisualProvider { probe(): Promise analyze(input: ProviderInput, signal: AbortSignal): Promise } ``` Provider 的能力声明、实际探测和本次执行结果必须分开。禁止从其他 DSH 插件的非公开模块导入实现。 ### DSH Adapter - Host:运行任务、路径围栏、Artifact 索引和生命周期; - Client:只使用正式 `conversation.view` Slot; - 当前 DSH 版本建立兼容矩阵; - 不访问 DSH 内部 DOM 和私有 CSS 类。 ## 3. 数据模型 ```text AcceptanceProject ├─ AcceptanceRun[] │ ├─ immutable Target / Matrix snapshot │ ├─ CheckpointResult[] │ ├─ FindingCandidate[] │ └─ RetestRelation[] └─ Issue[] ├─ stable scope / detector fingerprint ├─ lifecycle ├─ append-only decisionHistory └─ append-only verificationHistory ``` Issue 使用两个当前状态与两条不可覆盖历史: ```yaml lifecycle: active | resolved | unresolved | regressed decision: pending | approved-fix | accepted-risk | dismissed | deferred decisionHistory: DecisionEvent[] verificationHistory: VerificationEvent[] ``` ## 4. 执行时序 ```mermaid sequenceDiagram actor U as Human participant C as DSH Client participant H as DSH Host participant R as Local Runner U->>C: 确认 Target 与 Matrix C->>H: 创建 Acceptance Run H->>R: 执行确定性检查 R-->>H: Runtime Evidence + Screenshots H-->>C: Finding Candidates U->>C: 立为 Issue / 新增手工 Issue U->>C: 批准修改 / 接受风险 / 驳回 / 延后 C->>H: 保存 Decision C->>H: 生成本地修改包 H-->>U: Markdown / JSON + 复制 U->>C: 修改后复验 H->>R: 重放同一 Matrix H-->>C: 六类候选复验关系 U->>C: 确认 / 否决 / 合并 / 拆分 ``` ## 5. 状态复现契约 V0.1 支持三种确定性方式: 1. URL/Query; 2. 用户提供 Fixture; 3. 有限的确定性浏览器动作。 自然语言“进入错误状态”不是正式契约。每个 Checkpoint 必须有 Ready 条件;超时进入 `unreached`。 ### 5.1 检查对象与路径契约 `Target` 是用户选定的确切页面,而非仅一个站点 Origin。Checkpoint 的页面路径为 `/` 时,Runner 必须保留 Target 自身的 pathname 与既有 query;只有填写 `/reports.html` 等非根路径,才允许切换同 Origin 内的页面。Runner 保存最终 URL,Client 展示“实际打开”路径,供用户核对检查对象。 `state` / `theme` 查询参数只是一种复现方式,不是状态已到达的证明。若页面只支持点击、内存状态或其他未声明的触发方式,Ready 超时必须为 `unreached`,只生成 Finding Candidate,不得据此创建正式 Issue 或写入 `resolved`。 ## 6. 存储 当前实际存储结构: ```text .dsh-visual-acceptance/ ├── project.json ├── schema.json ├── runs//manifest.json ├── runs//screenshots/ ├── issues.json └── change-packages/ ├── .md └── .json ``` 要求: - Schema 带版本; - 写入采用临时文件后原子替换; - 图片和报告使用相对路径; - 默认不进入 Git,由用户自行选择; - 不记录 Cookie、Authorization Header、页面现有输入框值或完整网络 Body。用户显式声明的 `fill/select` 值会保存在本地 Run Matrix,但从公开动作证据和 Change Package 中移除;因此状态配方禁止凭据。 Run、项目级 Issue 和修改包均采用临时文件加原子替换。目录权限为 `0700`,manifest、PNG、JSON 与 Markdown 为 `0600`。同一 Host 进程内的 Issue 变更按工作区串行化,避免并发追加 Decision 丢失;当前尚未实现跨进程文件锁,因此不支持两个 DSH 进程同时修改同一 Profile 与工作区。旧 `0.1.0-slice` Run 保持只读可见;首次写入 Issue 时初始化 `schema.json / project.json / issues.json`,不删除旧 Run。 ## 7. Host API(当前实装) 所有接口仅接受 loopback 来源,并由 Host 通过 `sessionQuery` 反查真实会话工作区: | 方法 | 路径 | 用途 | |---|---|---| | GET | `/visual-acceptance/context` | 读取会话工作区与能力边界 | | POST | `/visual-acceptance/breakpoints` | 读取 Target 可访问 CSS 媒体查询并返回断点与完整性 | | GET | `/visual-acceptance/runs` | 列出工作区 Run | | POST | `/visual-acceptance/runs` | 校验输入、创建并异步执行 Run | | GET | `/visual-acceptance/runs/:runId` | 读取 Run 详情与进度 | | POST | `/visual-acceptance/runs/:runId/cancel` | 取消活动 Run | | POST | `/visual-acceptance/runs/:runId/retest` | 从完成的基线 Run 复制不可变 Matrix 并创建 Retest | | GET | `/visual-acceptance/runs/:runId/screenshots/:name` | 读取本地截图证据 | | GET / POST | `/visual-acceptance/issues` | 列出项目级 Issue / 从 Candidate 或截图创建 Issue | | GET | `/visual-acceptance/issues/:issueId` | 读取 Issue 与历史 | | POST | `/visual-acceptance/issues/:issueId/decision` | 追加人工 Decision Event | | POST | `/visual-acceptance/issues/:issueId/relations` | 保存人工复验、否决、合并或拆分 | | POST | `/visual-acceptance/issues/:issueId/change-package` | 仅为 `approved-fix` 生成本地修改包 | Client 提供的 `cwd` 不被信任。远程 URL、工作区外 HTML、越界 Run ID 和越界截图文件名在 Host/Core 层拒绝。 同一会话只允许一个活动 Run,避免并发启动多个 Chrome;取消或结束后才能创建下一 Run。Retest 比较在 Host 返回完成态前补齐,避免 Client 因竞态停在空关系状态。 ## 8. 安全边界 - 默认只访问用户明确提供的本地目标; - 远程 URL 后置,并需要 Host Allowlist; - 截图可能含隐私内容,默认不上传; - Provider 只得到最小必要截图或裁剪; - CLI 使用参数数组,禁止 Shell 字符串拼接; - 超时后终止子进程; - Run 结束释放 Chrome、端口和临时目录; - 未经人工确认不生成修改包;当前不自动向 Agent 发送任何修改指令。 ## 9. 兼容策略 维护以下兼容矩阵: | 范围 | 当前证据 | 发布要求 | |---|---|---| | DSH Host `0.1.1-rc.2` | E3 | 自动生命周期测试 | | `conversation.view` | E3 | 已在真实 DSH Web 会话挂载并完成 Run | | DSH Web UI | E3 | 1440px 与 390px、控制台、Run/取消实测 | | DSH Desktop 壳层 | 用户确认 Tab 可见;自动化未覆盖 | 深浅色、关闭重开 | | Chrome CDP 151 | E3 | 最低与当前版本各一轮 | | ModLens 3.23.1 | 仅探测 | 固定样例输出适配测试 | ## 10. `0.1.2` 之后的工程缺口 当前 Host、存储、确定性 Runner、Candidate、Issue、Decision、修改包与 Retest 已形成 Fixture 闭环;仍需要补充: - 破坏性版本升级时的显式 Schema 迁移工具(当前仅兼容读取旧 Run); - 跨进程 Issue 存储锁与冲突恢复; - 参考设计图身份、对齐与比较;当前仅有 Retest 截图像素变化 Candidate; - Provider 真实执行和证据最小化; - 自动 Agent 会话注入;当前只能复制本地只读修改包; - Desktop 深浅色与升级兼容矩阵; - 5 个真实本地项目的修改与同 Matrix Retest 试点。