# 2026-06-27 MD-H5-05 Capability Contract ## 用户目标 从 `02-P/plan-progress.markdown` 的 `P-20260626-m4c-handshake-coordination` 领取 Mindraw 侧 `MD-H5-05`,统一 Mindraw live transport capability payload / doctor 语义。完成后回写总台账 Progress Log,保存 QA 证据和会话记忆;不领取 `PM-*` / `H*`,不改 m4c `03-O`。 ## 已完成事项 - 重新读取 `/Users/ar/.codex/AGENTS.md`、项目 `AGENTS.md`、`INDEX.md`、`CODEGRAPH.md` 和总台账中 `MD-H5-05` / `M4C-H5-08` / `PM-H5-CAPABILITY-CONTRACT-GATE` 状态。 - 定位 capability 语义矛盾来源:`mindrawGetCapabilities()` 旧顶层字段仍返回 `documentLease/createAiResultFrame=unavailable`,transport nested capability 和真实写回链路已为 write-capable。 - 将 canonical capability contract 固定为 `h5-md-h5-05-canonical-v1`。 - 统一 `write-api.json`、`/capabilities`、JSON-RPC `mindraw.app.get_capabilities` 顶层 `capabilities` 为: - `openDocumentState=read` - `liveFrameContext=read` - `documentLease=write` - `createAiResultFrame=write` - `arbitraryJsonPatch=false` - 保留 `transport.capabilities` 为兼容 alias,并标记 `aliasOf: "capabilities"`。 - 更新 doctor:输出 `appApi.capabilityContractVersion` / `appApi.capabilities`,并将旧 read-only payload 判为 `appWriteLease=invalid` / `MINDRAW_APP_API_CAPABILITY_INCOMPLETE`。 - 构建并启动当前源码本地 QA debug App,生成新 runtime capability,完成 live contract smoke。 - 回写总台账并将 `MD-H5-05` 标记完成,下一步归属 PM / m4c `M4C-H5-08`。 ## 关键决策 - 顶层 `capabilities` 是唯一 canonical capability 事实源。 - `transport.capabilities` 不再表达独立语义,只作为兼容别名。 - 旧 `documentLease=createAiResultFrame=unavailable` payload 不再是 valid H5 live transport contract。 - App 退出 / stale 仍以真实 `/health` 为准;payload schema 合法不等于运行态可用。 ## 文件变更 - `src/lib/mindrawAppReadApi.ts` - `src/lib/mindrawAppReadApi.test.ts` - `src/lib/mindrawAppApiTransport.ts` - `src/lib/mindrawAppApiTransport.test.ts` - `src-tauri/src/app_api_transport.rs` - `scripts/mindraw-doctor.mjs` - `scripts/mindraw-doctor.test.mjs` - `CODEGRAPH.md` - `INDEX.md` - `02-P/plan-progress.markdown` - `02-P/qa/mindraw-h5-capability-contract-check.md` - `02-P/qa/mindraw-h5-capability-contract-check.json` ## 验证结果 - `npm run test:run -- src/lib/mindrawAppReadApi.test.ts src/lib/mindrawAppApiTransport.test.ts src/lib/mindrawAppWriteApi.smoke.test.ts`:PASS,3 files / 19 tests。 - `npm run doctor:mindraw:test`:PASS,14 tests。 - `cargo test --manifest-path src-tauri/Cargo.toml app_api_transport`:PASS,4 tests。 - `npm run tauri -- build --debug --bundles app`:PASS,本地 QA debug App 构建成功。 - 外部 capability contract smoke:PASS,证据见 `02-P/qa/mindraw-h5-capability-contract-check.json`。 - live doctor:`appWriteLease=pass`。 - legacy read-only doctor:`appWriteLease=invalid`。 - stale canonical doctor:`appWriteLease=stale`. - `git diff --check`:PASS,无输出。 - `cargo fmt --manifest-path src-tauri/Cargo.toml`:未执行成功,本机缺 `rustfmt`。 ## 未决问题 - `M4C-H5-08` 仍需由 m4c 侧收口 consumer / contract guard。 - `PM-H5-CAPABILITY-CONTRACT-GATE` 仍由 PM 统一判定,Mindraw 本轮不收敛 Gate。 - endpoint / token 仍是运行态临时值,App 退出后必须重新读取 capability 并检查 `/health`。 ## 后续建议 - PM 等 `M4C-H5-08` 回写后再收敛 `PM-H5-CAPABILITY-CONTRACT-GATE`。 - 如果后续出现多实例覆盖 capability 的问题,应由 PM 拆出 single-instance / heartbeat / ownership hardening 任务。