feat(ios): W1 leaf packages — ReconnectMachine/PingScheduler, GateState/AwayDigest, HostRegistry, APIClient+pairing probe
T-iOS-5: pure reconnect reducer (1s→30s cap, mirrors terminal-session.ts) + 25s PingScheduler, 16 tests
T-iOS-6: gate epoch tracker (rising-edge semantics, canDecide guard) + AwayDigest reducer, 25 tests
T-iOS-7: HostRegistry with SecItemShim keychain seam, 30 tests, 88.1% own-src coverage
T-iOS-8: APIClient (Origin iff-G invariant) + two-step pairing probe, 45 tests, 98.1% coverage
Contract ruling: probe returns Result<HostEndpoint,_> (Host{id,name} built by pairing VM) —
resolves frozen-contract contradiction reported via BLOCKED protocol; adds Tunables.pairingProbeTimeout(10s)
Verified: 178 tests green across 5 packages; coverage gates pass; zero Owns violations
This commit is contained in:
@@ -306,6 +306,7 @@ public struct AwayDigest: Sendable, Equatable {
|
||||
| `telemetryStaleTtlMs` | 30_000 | 镜像 public/tabs.ts:45 `STATUSLINE_TTL_MS`(= 服务器默认 src/config.ts:63;服务器侧 env 可覆盖——iOS 固化默认值,主机改配置时会漂移,已接受) |
|
||||
| `digestFadeDelay` | 8 s | T-iOS-14 digest 自动淡出 |
|
||||
| `titleMaxLength` | 256 | T-iOS-23 OSC 标题净化上限 |
|
||||
| `pairingProbeTimeout` | 10 s | 配对探针整体 deadline(§3.4 契约裁定新增;两步探针任一步挂起超此时限 → `.timeout`) |
|
||||
| `maxWSMessageBytes` | 16 MiB(`16 * 1024 * 1024`) | ≥ 6 × 默认 SCROLLBACK_BYTES(2 MiB) + 帧包络。**耦合警示(写进 doc comment)**:回放单帧 ≈ SCROLLBACK_BYTES × JSON 转义系数(1–6×,控制字节→`\uXXXX`,src/protocol.ts:186);SCROLLBACK_BYTES 为服务器 env 可调且客户端运行时不可知——超限 → 不可重试 `.replayTooLarge`(§3.2 / T-iOS-9/10) |
|
||||
|
||||
### 3.3 `HostRegistry`
|
||||
@@ -356,7 +357,11 @@ public enum PairingError: Error, Equatable { // [S:hybrid] 错误分类学,逐
|
||||
case tlsFailure, timeout
|
||||
}
|
||||
public func runPairingProbe(endpoint: HostEndpoint, http: any HTTPTransport,
|
||||
ws: any TermTransport) async -> Result<Host, PairingError>
|
||||
ws: any TermTransport) async -> Result<HostEndpoint, PairingError>
|
||||
// 【契约裁定 2026-07-04,T-iOS-8 BLOCKED 上报】原冻结签名返回 Result<Host,…>,但 Host 是 §3.3
|
||||
// HostRegistry 类型,APIClient 依赖边只有 WireProtocol(§1 叶子包零耦合)——签名自相矛盾。
|
||||
// 裁定:探针职责=验证 endpoint,返回 HostEndpoint;Host{id,name} 由 T-iOS-12 PairingViewModel
|
||||
// 构造后入 store(id/name 本就非探针所知)。超时经 Tunables.pairingProbeTimeout(§3.2.1 新增行)。
|
||||
// 探针两步:①GET /live-sessions(无 Origin,验可达+形状) ②WS attach(null)+立即 kill 往返
|
||||
//(带 Origin,验 isOriginAllowed 精确匹配)。任何失败 → 映射到 PairingError,UI 内联显示。
|
||||
// 注:扫码来源的 endpoint 必须先经 T-iOS-12 的"确认 host"步——用户未确认前不得调用本探针(探针①就会联网)。
|
||||
@@ -585,7 +590,7 @@ W5 验收(report-only, 并行)
|
||||
- [ ] `hookDecision` body 形状 `{sessionId,decision,token}`;403 → 显式错误(token 过期话术)
|
||||
- [ ] 探针①失败分支:连接拒绝 → `hostUnreachable`;返回 HTML → `httpOkButNotWebTerminal`
|
||||
- [ ] 探针②失败分支:WS 401 → `originRejected(hint:…)`(hint 含 `ALLOWED_ORIGINS=<scheme>://<拨号 host>[:port]`,与 App 连接的 URL 一致——不含任何 ":443 迷信")
|
||||
- [ ] 探针全通 → `Result.success(Host)`;探针成功路径里 attach(null) 后必发 kill(不留孤儿会话)
|
||||
- [ ] 探针全通 → `Result.success(HostEndpoint)`(契约裁定:Host 由 T-iOS-12 VM 构造,见 §3.4 注);探针成功路径里 attach(null) 后必发 kill(不留孤儿会话)
|
||||
- [ ] 超时(FakeClock)→ `.timeout`
|
||||
- **Steps(实现, GREEN)**: [ ] §3.4 签名 [ ] 服务器约束写进 doc comment(按端点精确):`hookDecision` body ≤ 4 KB(src/server.ts:503)、≤10 次/分/IP(src/server.ts:72,504-508)——P1 增量端点的限额归 T-iOS-38
|
||||
- **Accept**: `swift test --package-path ios/Packages/APIClient` 全绿;覆盖率 ≥ 80%
|
||||
|
||||
@@ -32,7 +32,13 @@
|
||||
- **T-iOS-3 WireProtocol(冻结)**: §3.1 全类型 + Tunables §3.2.1 全表;**59 tests 全绿、覆盖率 100%**(llvm-cov 226/226);300 轮 roundtrip property + 500 轮 fuzz(decodeServer 永不 crash);**跨实现实测**: Swift encoder 输出经 tsx 喂给真 `src/protocol.ts` parseClientMessage → 13 帧+mode 顶层恢复全 PASS。自此冻结。
|
||||
- **T-iOS-4 TestSupport**: FakeTransport(actor,scripted failures+按连接记帧)/FakeClock(class+锁,`waitForSleepers` 确定性栅栏,零真实等待)/FakeHTTPTransport(记录 headers 供 Origin-iff-G 断言);3 smoke 全绿。
|
||||
- **verify(独立 agent 复跑)**: 模拟器构建 exit 0;59+3 tests;覆盖率 100%;spike 6 tests+1 known issue;`git status` 零越界。
|
||||
- 待续: W1(T-iOS-5/6/7/8 并行)→ W2 → W3 → W4 → W5。**偏差(orchestrator 决策)**: W1+ 并行 builder 不用 git worktree(Workflow worktree 合并回主树增加失败面),改为主树直跑——文件互斥 + SwiftPM .build 锁自然串行化构建,禁 agent 碰 git;每波末独立 verify + orchestrator commit 兜底。
|
||||
- **[x] W1 叶子包(T-iOS-5/6/7/8,4 builders;编排 [5→6 串行] ∥ 7 ∥ 8——5/6 同在 SessionCore 包,主树并行会互坏编译)**:
|
||||
- **T-iOS-5 ReconnectMachine+PingScheduler**: 纯 reducer,§3.2 签名逐字;backoff 1s→…→30s 封顶镜像 terminal-session.ts(连上才归零,retry/foregrounded 不重置阶梯——防狂按打穿);Ping 25s/连续 2 miss→connectionLost/取消与断线显式区分。16 测,0 真实等待,文件级覆盖 100%/95%。
|
||||
- **T-iOS-6 GateState+AwayDigest**: epoch 语义逐行镜像 terminal-session.ts:306-311(上升沿 +1、持续帧刷新 detail、下降沿不重置计数器);`canDecide(epoch:)` 防误批;affordance 映射逐字对齐 tabs.ts:345-347(绝不发 raw auto);digest 词表与 `TimelineEvent.knownClasses` 有相等性绊线测试;防御:乱序容忍、Date→ms clamp 不 trap。25 测,两文件 100%。
|
||||
- **T-iOS-7 HostRegistry**: §3.3 契约;KeychainHostStore 经 SecItemShim 缝(swift test 打 fake;真 shim kSecUseDataProtectionKeychain+AfterFirstUnlockThisDeviceOnly,属性字典单点构造+逐字单测);InMemoryHostStore 入 Sources 供 App-VM 测试。30 测,own-Sources 覆盖 88.1%。
|
||||
- **T-iOS-8 APIClient+探针**: 44 测先全绿后 **`[!] BLOCKED` 正确上报冻结契约自相矛盾**——§3.4 `runPairingProbe → Result<Host,…>` 中 Host 是 §3.3 HostRegistry 类型,而 APIClient 依赖边仅 WireProtocol(§1 零耦合),签名无法编译(两轮 review 均漏)。**裁定(orchestrator,三选一取 c)**: 探针职责=验证 endpoint → 返回 `Result<HostEndpoint,…>`,Host{id,name} 由 T-iOS-12 VM 构造(id/name 本非探针所知);同时按法定路径加 `Tunables.pairingProbeTimeout`(10s,§3.2.1 新增行+绊线断言)。裁定已写回 PLAN §3.4/§3.2.1/T-iOS-8,公开包装+冒烟测试由 orchestrator 落地。Origin **iff**-G 入测试名;探针②成功后必带 Origin kill 不留孤儿;403 kill→originRejected(HTTP 侧 G 守卫也是配对必验项)。45 测,own-Sources 覆盖 98.1%。
|
||||
- **W1 验证(orchestrator 亲验)**: 5 包 178 tests 全绿(59+3+41+30+45);覆盖率(own-Sources 口径)SessionCore 99.1%/HostRegistry 88.1%/APIClient 98.1%,全过 80% 门;`git status` 全部在 Owns 内零越界。**发现归 T-iOS-16**: §9 覆盖率命令的 ignore regex 不排静态链入的依赖包源码,CI 接线时须按包过滤(本次已按正确口径亲算)。
|
||||
- 待续: W2(T-iOS-9→10,同包串行)→ W3 → W4 → W5。**偏差(orchestrator 决策,W1 起生效)**: 并行 builder 不用 git worktree(Workflow worktree 合并回主树增加失败面),改为主树直跑——文件互斥 + 同包任务串行化,禁 agent 碰 git;每波末独立 verify + orchestrator commit 兜底。
|
||||
|
||||
### ✅ iOS 客户端实施计划 — `docs/PLAN_IOS_CLIENT.md`(规划完成 — 2026-07-04,main,未提交;纯文档,零代码改动)
|
||||
**多 agent 编排 = 一个 ultracode `Workflow`(66 agents,7 阶段)**:5 读者并行(wire contract 逐 file:line / 功能矩阵 / relay 现状 / 模板规范 / iOS 平台联网调研)→ 3 架构师独立竞标(full-native / WKWebView-hybrid / phased)→ 3 评委多视角打分(UX/工程/安全,**phased 26.5 胜出**,native 23.5、hybrid 16.5,21 条 mustSteal 嫁接)→ 综合简报 → 写手出稿(843 行)→ **4 评审交叉验证**(对照 src/ 源码逐条核实 / iOS API 联网核查 / 安全 / 计划质量)→ 每条 finding 对抗式 verify(CRITICAL/HIGH 双票)→ fixer 应用。
|
||||
|
||||
Reference in New Issue
Block a user