Skip to content

P4 Startup Phase C · Hybrid Total 正式方案 ​

当前状态:Project Owner 已于 2026-09-22 明确批准 Phase C,授权 Implementation AI 按本方案执行 C0/C1;C2 仍禁止进入。

2026-09-22 增量:C0 仪表化已完成(implemented · gate-open,E2 完成 / E4 待执行)。本批只做 C0, C1 未开始、C2 未进入、C0 Gate 未自判。Project Owner 裁定 C0 真机证据由 Test AI 采集、由 Lead AI 判定, Implementation AI 交付「仪表化 + E2 + 取证工具」后停止。详见文末 Implementation Update。

基线:c77e363b9e900f09baa326ff01748b3c38f715a2。Phase A = PASS;Phase B 架构 = PASS / CLOSED;Phase B 性能 = B-PARTIAL。Phase C 不反向修改 A/B 的 owner、prewarm、SOURCE_ACTIVE barrier 或 reconnect 语义。

1. Phase C 要解决什么 ​

现有 Startup Total 的直接端点来自 Dedicated CoreProfile lifecycle:

text
System Interface BEGIN
        ↓
Initial Frame END

现有公式是同一条 CoreProfile RAW v2 中的 device mach ticks 差:

text
legacyTotalMs =
    ticksToNs(initialFrameEndMachTicks - systemInterfaceBeginMachTicks)
    / 1_000_000

优点是同源、同钟、语义清楚;缺点是 lifecycle BEGIN / END 任一丢失时 Total 会缺失,现有 Mode A / C 虽可在严格条件下修复一部分端点,但不能保证每轮都得到 Total。

Phase C 的目标不是“无论如何给一个数”,而是:

  1. 研究并产品化更稳定的 Hybrid Total:
    • START:优先使用可证明属于目标 App、且位于 device mach clock 的启动锚点;
    • END:使用 ActivityTrace FrameLifetime 的首个合格 presented frame;
  2. lifecycle 九阶段继续保留为诊断明细,不因 Hybrid Total 而弱化;
  3. 在无法证明时钟、进程归因或首帧归因时保持 missing;
  4. 先 shadow 旁路计算,E4 通过后才讨论替换主 Total。

2. 明确非目标 ​

Phase C 不做以下事情:

  • 不回退 Phase A Dedicated Startup;
  • 不回退 Phase B Full Prewarm;
  • 不让 Startup 与 FrameTime 同时打开第二个 CoreProfile/kperf recording;
  • 不把 didFinishLaunching 当 Total END;
  • 不把“launch request 后收到的任意第一帧”直接当目标 App 首帧;
  • 不把 host time.monotonic_ns() 与 device mach timestamp 直接相减;
  • 不用截图轮询、OCR、视频画面变化伪装 first frame;
  • 不用 0 填充缺失;
  • 不为了提高成功率放宽 PID / generation / sourceEpoch / reconnectGeneration / foreground / source-gap 门禁;
  • C0/C1 未通过前不修改 UI 中当前 Startup Total 的主值。

3. 当前已有数据源事实 ​

3.1 Legacy lifecycle START / END ​

RealtimeLaunchTraceDecoder 当前保留:

  • System Interface BEGIN 的 startMachTicks;
  • Initial Frame END 的 _initial_frame_end_ticks;
  • timeConfig.numer / denom;
  • target PID / targetGeneration / dynamic attribution;
  • source loss / unmatched begin/end / schema gates。

现有 launch_trace.py 仅在端点满足顺序与质量门禁时发布 Total;Mode A/C 修复仍带 repaired 来源,不得伪装成 clean endpoint。

3.2 ActivityTrace FrameLifetime ​

当前 FrameTime 已由独立于 kperf 的:

text
com.apple.instruments.server.services.activitytracetap
subsystem = com.apple.coreanimation
category  = IOMFBServer
name      = FrameLifetime

提供。其 event 含:

  • begin_time
  • end_time
  • prev_frame
  • refresh_interval
  • frame_seed
  • display_id
  • surface_id

FrameLifetimeDecoder 已把 end_time 转换为 presentationTimestampNs,并有 sourceEpoch / reconnectGeneration / targetGeneration / foreground / continuity / source-gap 语义。

重要限制:当前 adapter scope 是 foreground-device,并不天然等价于“目标 App 的 frame”。

3.3 Process-control launch request ​

launch_requested_ns / launch_request_envelope.host_receive_monotonic_ns 是 Mac/Sidecar host monotonic clock 上的控制边界。

它可以作为:

  • Start click → launch request 的诊断;
  • launch ordering / round identity 的控制锚点;

但 C0 证明 host↔device clock bridge 之前,不允许直接参与 Hybrid Total 数学公式。

4. Phase C 固定拆成 C0 / C1 / C2 ​

C0 · Feasibility & Attribution Gate ​

只研究、加实验观测和测试 fixture;不改主 Total。

必须证明三件事:

  1. Clock Gate:Hybrid START 与 FrameLifetime END 能落在同一 device mach clock / epoch;
  2. Start Gate:存在稳定且可归因到目标 App 的 START;
  3. End Gate:能把首个合格 FrameLifetime 归因到本轮目标 App,而不是任意前台设备 frame。

任一门禁失败,Phase C 停止在 research,现有 Total 保持不变。

C1 · Shadow Hybrid Total ​

C0 通过后:

  • 新增独立 Hybrid Total evaluator;
  • 每轮同时计算 legacy lifecycle Total 与 hybrid shadow Total;
  • raw/report/diagnostic 中记录两者及 provenance;
  • UI 主 Total 仍读 legacy;
  • 不改变 lifecycle decoder 的九阶段 FSM。

C2 · Promotion Gate ​

只有 Lead AI 独立 E4 验收通过,Project Owner 再次明确批准,才允许:

  • 把 Hybrid Total 晋升为 Startup Total 首选来源;
  • legacy lifecycle Total 退为 comparator / fallback / diagnostics;
  • 更新 knowledge、公式 Registry、UI provenance。

C1 开发完成 不自动进入 C2。

5. START 语义与优先级 ​

Phase C 不先假定 host launch request 就是最终 START。START 候选按证据等级研究:

S0 · direct lifecycle start ​

text
System Interface BEGIN mach ticks
  • device clock;
  • process scope;
  • 已有 target attribution;
  • clean 时作为 paired comparator 与可用 START。

S1 · repaired early lifecycle start ​

沿用当前 Mode C 的早期 BEGIN:

text
min(System Interface / dyld / UIKit early init BEGIN)

要求:

  • 必须是 surviving BEGIN;
  • 只允许 PHASES[0..2];
  • 必须带 repaired;
  • 不得扩展到 scene / didFinish / later frame。

S2 · stable device process-start / resume marker(C0 研究目标) ​

C0 应检查现有 Dedicated Startup RAW / ProcessControl 可否得到:

  • 与目标 PID 直接绑定;
  • 位于 device mach clock;
  • SOURCE_ACTIVE 之后、真实 launch/resume 附近;
  • reconnect / generation 可隔离;

的 process launch / exec / resume kernel marker。

不得预先假设某个 debugID。 Implementation AI 只能通过 fixture + 真机 census / Apple Instruments 参考识别后,将经证据确认的 marker 写入固定 profile。

若 S2 被证明,优先作为 Hybrid START。

S3 · host process-control launch request ​

只作为 diagnostics / experimental comparator:

text
launch_requested_ns (host monotonic)

除非 C0 建立并验证 host↔device clock bridge,否则:

text
HybridTotal = devicePresentationNs - hostLaunchNs

是禁止公式。

6. END 语义 ​

目标 END:

text
首个可证明属于本轮目标 App 的 FrameLifetime presentation end_time

不是“ActivityTrace 的第一条 FrameLifetime”。

一个 frame 至少必须满足:

  1. event identity = com.apple.coreanimation / IOMFBServer / FrameLifetime;
  2. presentationTimestampNs > startTimestampNs;
  3. reconnectGeneration 与当前 cycle 相同;
  4. targetGeneration 与当前 launch round 相同;
  5. sourceEpoch 仍属于当前有效窗口;
  6. target PID 已 verified;
  7. target foreground 状态成立;
  8. decoder 无 source-gap / discontinuity / out-of-order;
  9. displayID 合法且未发生 display boundary change;
  10. 不来自上一轮残留、App rebind 前目标或 reconnect 前 source。

6.1 surfaceID 归因门禁 ​

surfaceID 是 Phase C 的关键研究字段,但当前代码没有证明:

text
surfaceID -> target PID / target bundle

因此 C0 必须做正/负样本验证:

  • 目标 App 冷启动;
  • 启动前系统界面帧;
  • 启动后切入其他 App;
  • 系统 overlay / keyboard / notification;
  • App A→B rebind;
  • reconnect 后新 round。

只有出现可重复的 surface / process 映射证据,才能把 END 标为 real。

若只能证明“目标 App verified foreground 时窗口内的第一条 foreground-device frame”,可以进入 candidate,但不能叫 real。

若同时存在多个无法消歧的 surface,结果必须 missing: ambiguous-first-presented-surface。

7. 时钟域与正式公式 ​

7.1 唯一首选公式:device ↔ device ​

当 START 与 END 都是同一 device mach clock 的 ticks:

text
deltaTicks = endMachTicks - startMachTicks

deltaNs =
    floor(deltaTicks * timebaseNumer / timebaseDenom)

hybridTotalMs =
    deltaNs / 1_000_000

必须满足:

text
endMachTicks > startMachTicks
timebaseNumer > 0
timebaseDenom > 0
sameReconnectGeneration == true
sameClockEpoch == true
noClockReset == true

算法版本建议:

text
startup-hybrid-total.device-mach-framelifetime.v1

7.2 Cross-source clock proof ​

CoreProfile lifecycle mach ticks 与 ActivityTrace FrameLifetime mach ticks虽然都表现为 mach ticks,C0 仍必须证明:

  • 相同 timebase;
  • 同一 device session 中数值处于同一 epoch;
  • 30s 观测窗口内相对 host elapsed 的 slope 无异常漂移;
  • reconnect 后重新建证据,禁止沿用上一代 clock proof。

未证明时:

text
quality = missing
reason  = cross-source-clock-unverified

7.3 Host ↔ device clock bridge ​

如果研究 S3 host launch request fallback,必须独立形成 clock bridge:

text
deviceNs ≈ a * hostMonotonicNs + b

并记录:

  • calibration sample count;
  • slope a;
  • offset b;
  • residual median / p95 / max;
  • calibration generation;
  • valid-from / valid-until。

未达到 C0 误差门槛时,该 bridge 只能进 diagnostics,不能参与产品 Total。

8. 质量与失败语义 ​

Phase C 新增 Hybrid provenance,至少区分:

quality含义
realSTART 与 END 均为直接 device timestamp,target attribution 与 clock gate 全部通过
candidatetimestamp 本身真实,但至少一项归因仍依赖已验证但非直接的 foreground/surface 规则
repaired使用 S1 或其他明确批准的 endpoint repair;必须带 repair reason 与 error bound
missing无法在不猜测的前提下得到值

禁止:

  • missing → 0;
  • ambiguous → candidate;
  • repaired → real;
  • host/device 混钟 → repaired;
  • source gap 后跨 gap 取 frame;
  • 跨 generation/reconnect 拼端点。

报告建议字段:

text
hybridTotalMs
hybridTotalQuality
hybridTotalReason
hybridTotalAlgorithmVersion

hybridStartSource
hybridStartMachTicks
hybridStartQuality

hybridEndSource
hybridEndMachTicks
hybridEndSurfaceID
hybridEndDisplayID
hybridEndQuality

clockDomain
clockProofGeneration
sourceEpoch
targetGeneration
reconnectGeneration

Legacy 字段继续保留:

text
legacyTotalMs
legacyTotalQuality
legacyTotalSource

C1 shadow 阶段禁止覆盖现有 totalDurationMs。

9. ActivityTrace 生命周期与资源模型 ​

Phase C 不得重新引入 CoreProfile unified recording。

FrameTime 已选择 ​

复用现有唯一:

text
ActivityTraceFrameLifetimeRawAdapter

Hybrid evaluator 只注册一个 one-shot observer,不创建第二条 ActivityTrace subscription。

FrameTime 未选择但 Startup 已选择 ​

允许建立最小 Startup FrameLifetime observer,但必须:

  • 复用 long-lived DTX owner / activitytracetap transport;
  • 只订阅 FrameLifetime whitelist;
  • 不启用 CoreProfile;
  • 不影响 Dedicated Startup owner;
  • 首个合格 END + reorder grace 后若无其他消费者立即 stop;
  • 最晚在 launch 后固定 timeout 自动 stop;
  • Session Stop / reconnect / App rebind 必须清理。

建议初始上限:

text
startup frame observer timeout = 10s
reorder grace                  = 250ms
bounded pending candidates     <= 64
duplicate ActivityTrace streams = 0

这些是 C1 初始预算,不是无条件写死;E2/E4 可收紧,但不得为提高成功率无限延长。

10. 性能 / 轻量化门禁 ​

Phase C 实施必须给出变更前后基准。

至少测:

  • Start click 同步新增耗时;
  • first FrameLifetime decode latency;
  • CPU;
  • RSS;
  • ActivityTrace bytes/sec;
  • event queue high-water;
  • raw/session 增量大小;
  • 10s timeout 最差路径。

目标预算:

项目门槛
新增 CoreProfile/kperf recording0
重复 ActivityTrace subscription0
Startup observer pending rows≤ 64
Startup observer lifetime≤ 10s
Start 同步路径额外 CPU wall timep95 ≤ 5ms
Hybrid evaluator 单 event 处理p95 ≤ 1ms
额外 RSS≤ 2 MiB
ActivityTrace 持续带宽实测应保持约当前 FrameLifetime 量级;若 > 0.10 MiB/s 则 FAIL
Session 磁盘增量需实测;不得因 shadow raw duplication 翻倍

如果现有 FrameTime adapter 已 active,Hybrid evaluator 必须零复制或近似零复制消费 normalized event;禁止再次序列化整条 raw 流只为计算一个首帧。

10.1 执行路径、复杂度、吞吐与并发边界 ​

Hybrid evaluator 的热路径固定为:

text
normalized FrameLifetime event
    → O(1) identity / generation / clock / quality gates
    → append bounded candidate metadata
    → first-qualified END seals result
    → observer short-circuit / detach

效率约束:

  • 时间复杂度:正常单事件处理必须为 O(1);不得在每个 frame 到来时回扫整轮历史。最多只允许在 seal / diagnostics 时扫描有界候选集合,复杂度 O(K),其中 K <= 64;
  • 空间复杂度:O(K),K <= 64;不得保留第二份 FrameLifetime raw history;
  • 并发策略:沿用现有单事件流/单 writer 顺序,Hybrid evaluator 不为每个 frame 新建 task、thread 或 process;若需要异步 teardown,只允许最多 1 个受控 cleanup task;
  • 吞吐目标:E2 synthetic benchmark 至少覆盖 240 FrameLifetime events/s,在该负载下 evaluator p95 单事件处理仍需 ≤ 1ms,队列不得持续增长;
  • 首结果延迟目标:从合格 normalized FrameLifetime event 进入 evaluator 到 shadow result seal,p95 ≤ 10ms;
  • 超时边界:Startup-only observer 最长 10s;reorder grace 250ms;所有 teardown 必须 bounded,不得用无限 wait;
  • 短路策略:一旦结果 sealed,后续 frame 只做常数级 no-op / observer detach,不允许改写首个 END;
  • 复用策略:FrameTime 已选时直接消费已有 normalized event;禁止为 Hybrid 重复 decode、重复序列化或重复订阅 ActivityTrace。

这些效率门禁必须在 C1 的 before/after benchmark 中单独出表,不能只以“全量测试通过”代替性能证据。

11. C0 必做实验 ​

C0-1 · Clock-domain proof ​

同一真机、同一 session 记录 CoreProfile lifecycle mach ticks 与 ActivityTrace end_time:

  • 核对 numer / denom;
  • 检查数值 epoch 是否同域;
  • 至少 30s;
  • reconnect 后重新做一次;
  • 若出现 offset/epoch 不可解释,Phase C 停止。

C0-2 · First-presented-frame attribution ​

至少:

  • Fixture A;
  • App A / B / C 三类真实 App;
  • 每个 10 次冷启动;
  • 额外 10 个负样本(系统界面、切其他 App、overlay、rebind)。

输出每轮:

text
launch round identity
PID
foreground transitions
FrameLifetime candidate sequence
displayID
surfaceID
frameSeed
presentationTimestamp
selected END / reject reason
legacy initial-frame endpoint if present

要求 negative controls 0 次错误归因。

C0-3 · START candidate census ​

对 S0/S1/S2/S3 同场记录:

  • availability;
  • 与 launch request 的相对时序;
  • generation/PID attribution;
  • 与 clean legacy START 的 delta 分布;
  • source loss 时行为。

没有证据不得把某个 kernel event 命名为“process start”。

12. E2 反例矩阵 ​

Implementation AI 必须补确定性 fixture / integration tests,至少覆盖:

  1. clean S0 + clean target FrameLifetime;
  2. S0 missing、S1 repaired;
  3. S0/S1 都 missing → Hybrid missing;
  4. END missing;
  5. frame 在 START 之前;
  6. duplicate same timestamp;
  7. out-of-order frame;
  8. ActivityTrace source-gap;
  9. discontinuity;
  10. wrong display;
  11. multiple ambiguous surface;
  12. target not foreground;
  13. stale previous-round frame;
  14. targetGeneration mismatch;
  15. sourceEpoch mismatch;
  16. reconnectGeneration mismatch;
  17. App A→B rebind 不得使用 A 的 frame;
  18. reconnect 后不得使用上一代 clock proof;
  19. PID rebind 后旧 PID frame 不得通过;
  20. lifecycle source-buffer-loss 但 ActivityTrace 正常;
  21. ActivityTrace loss 但 legacy Total clean;
  22. launch ack 失败;
  23. host launch request 存在但 clock bridge 未验证 → 不得计算 host/device Hybrid;
  24. FrameTime 已选 → 必须复用唯一 ActivityTrace subscription;
  25. FrameTime 未选 → startup one-shot observer timeout 后释放;
  26. Startup 未选 → 不得因为 Phase C 偷开 observer;
  27. Stop before first frame → missing + clean teardown;
  28. first qualifying frame 到达后后续 frames 不得改写 END;
  29. source restart 后 first frame 必须重新 warmup/归因;
  30. legacy totalDurationMs 在 C1 shadow 阶段逐字保持现有语义。

13. C1 代码边界建议 ​

优先新增独立组件,避免继续膨胀 RealtimeLaunchTraceDecoder:

text
perfowl_collector_core/startup_hybrid_total.py
  HybridStartupTotalEvaluator
  HybridEndpoint
  HybridClockProof
  HybridTotalReport

职责:

  • 接受已标准化 START candidate;
  • 接受 FrameLifetime normalized event;
  • 做 identity / clock / ordering / source-quality gate;
  • 只保存有界候选状态;
  • 输出 shadow report。

RealtimeLaunchTraceDecoder 继续负责 lifecycle; FrameLifetimeDecoder 继续负责 FrameLifetime 解码; realtime.py 只负责 wiring / lifecycle / observer refcount。

禁止把 Hybrid endpoint 规则散落在多个 if 中。

14. E4 真机验收矩阵 ​

C1 E2 通过后才打包进入 E4。

最低矩阵:

对象冷启动轮数
Fixture A20
App A20
App B20
App C20
negative controls≥10
reconnect/reboot 扩展≥5

每轮必须同时保存:

  • hybrid shadow;
  • legacy Total;
  • lifecycle endpoint 完整性;
  • FrameLifetime candidate/reject sequence;
  • source/reconnect/generation;
  • startup activation timings;
  • resource telemetry。

14.1 稳定性 Gate ​

text
publishableHybridRate >= 95% overall
publishableHybridRate >= 90% per app
falseAttributionCount = 0
crossGenerationJoinCount = 0
clockDomainViolationCount = 0

publishable 可以统计 real/candidate/repaired,但必须分层单列,不能只给一个混合百分比。

14.2 与 legacy clean subset 的同场对照 ​

只在 legacy clean endpoint 同时存在的轮次比较:

text
deltaMs = hybridTotalMs - legacyTotalMs
absDeltaMs = abs(deltaMs)

此处是语义一致性比较,不把 legacy 自动当绝对真值。

初始 Gate:

text
median(absDeltaMs) <= max(25ms, 2 * refreshIntervalMs)
p95(absDeltaMs)    <= max(80ms, 5 * refreshIntervalMs)

若存在稳定偏差,必须解释该偏差是否来自“lifecycle Initial Frame END”与“实际 presentation END”的定义差异,而不是简单通过加常数校正。

禁止用经验 offset 把结果“调到更像 legacy”。

14.3 资源 Gate ​

同设备、同 App、同采集项配对比较 C1 vs baseline:

  • CPU 不出现持续明显抬升;
  • RSS 增量 ≤ 方案预算;
  • FrameTime continuity / FPS 不因 Hybrid observer 下降;
  • Dedicated Startup source-ready / lifecycle capture 不退化;
  • Session 大小不因重复 raw 流显著放大。

15. C2 晋升条件 ​

只有以下全部成立,Lead AI 才能提出 C2:

  1. C0 Clock / Start / End attribution 全部 PASS;
  2. C1 E2 counterexample 全部 PASS;
  3. E4 稳定性达标;
  4. false attribution = 0;
  5. paired delta 满足 Gate 或有可证明的定义差异;
  6. 无 FrameTime / Startup / kperf / reconnect 回归;
  7. 资源预算 PASS;
  8. knowledge / formula / provenance 已更新;
  9. Project Owner 明确批准晋升。

否则:

text
legacy Total = 主值
hybrid Total = shadow / diagnostics

16. 明确停止 / 回滚条件 ​

出现任一条件立即停止 Phase C 产品化:

  • FrameLifetime 无法可靠归因到目标 App;
  • ActivityTrace 与 CoreProfile clock epoch 无法证明一致;
  • 为获取 END 必须重新让 CoreProfile 同时承担 frame filter;
  • 需要双 kperf recording;
  • 必须依赖截图轮询;
  • false attribution > 0 且无法通过确定性规则消除;
  • hybrid coverage 提升依赖放宽 generation/source-gap 门禁;
  • E4 差值呈无界长尾;
  • Hybrid 让 FrameTime / Startup source stability 明显退化;
  • host/device clock bridge 只能靠经验常数而无法校准。

回滚必须只关闭 Hybrid evaluator / one-shot observer;Phase A/B 架构保持不动。

17. 开发与提交要求 ​

Project Owner 已于 2026-09-22 明确批准本方案;Implementation AI 现在可以开始 C0/C1,但不得自行进入 C2。

推荐拆分:

  1. test(startup): add hybrid total feasibility fixtures
  2. feat(startup): add shadow hybrid total evaluator
  3. docs(startup): record phase c shadow validation

若一个批次可保持范围清晰,也可以合并,但产品代码与 E4 结论不得混成一个“自证 PASS”提交。

Implementation AI 交付必须包含:

  • exact HEAD;
  • diff summary;
  • 实际实现与本方案偏差;
  • focused tests;
  • full Sidecar regression;
  • benchmark / resource evidence;
  • site build;
  • 可安装签名/公证包(进入产品代码交付时按 AGENTS.md);
  • 同一 devlog 的 Implementation Update;
  • 停止在 C1,不自行宣布 C2。

18. Lead AI 验收顺序 ​

text
Implementation delivery
    ↓
Lead static/code audit
    ↓
E2 focused + full regression
    ↓
resource benchmark review
    ↓
signed/notarized test build
    ↓
E4 matrix
    ↓
Lead PASS / PARTIAL / FAIL
    ↓
Project Owner decides C2 promotion

19. 当前结论 ​

本节的「当前状态」是 2026-09-22 方案批准时的快照,按 D2 不回改;其后的进展以文末 Implementation Update · 2026-09-22 为准(C0 已 implemented · gate-open,C1 未开始,E4 未执行)。

Phase C 的正确第一步不是“把 launch command 和第一帧相减”,而是先证明:

text
START 可归因
+ END 可归因
+ 两者同一 device clock
+ round identity 不串代

因此本方案把 C0 Attribution/Clock Gate 设为硬前置。

当前状态:

  • Phase C formal plan:已制定并获 Project Owner 批准;
  • C0/C1 实施授权:已开放;
  • 产品实现:等待 Implementation AI 按本方案开始;
  • E4:未进入;
  • C2:仍未授权;
  • 下一动作:Implementation AI 先执行 C0 Feasibility & Attribution,再实施 C1 Shadow Hybrid Total;完成后交 Lead AI 独立审计,不得自行宣布 C0/C1 PASS 或进入 C2。

Implementation Update · 2026-09-22(C0 取证与归因仪表化) ​

审计基线:5a06929c22db912db22866ed2c29109761f1b797(docs(startup): approve phase c c0 c1)。 本段只记录 C0。C1 未开始,C2 未进入。 本批未宣布任何 C0 PASS。

1. 本批范围与角色边界(重要) ​

Project Owner 在开工前明确裁定:C0 的正式真机证据不由 Implementation AI 自证。因此本批交付收缩为 「C0 仪表化 + E2 反例矩阵 + 真机取证能力」,然后停在 C0,交回 Lead AI:

text
Implementation AI(本批)      → C0 instrumentation + E2 + census/benchmark 取证工具   ← 已完成并停止
Test AI(下一步,未开始)      → 真机执行 C0-1 / C0-2 / C0-3,产出 E4 原始证据
Lead AI(未开始)             → C0 Gate 独立判定(PASS / PARTIAL / FAIL)

因此本批没有:自跑真机 E4、自建验收包/公证、把 C0 写成 validated、把 shadow 提升为正式 Startup Total。

2. 实际修改范围 ​

文件性质说明
MacApp/Sidecar/perfowl_collector_core/startup_c0_feasibility.py新增(离线模块)C0 三闸仪表化 + Session 只读投影
MacApp/Sidecar/tests/test_startup_c0_feasibility.py新增§12 E2 反例矩阵,96 项
MacApp/scripts/startup-c0-census.py新增真机/回放 census 入口(Test AI 用)
MacApp/scripts/benchmark-startup-c0-feasibility.py新增时间/空间/吞吐 benchmark + 归因探针

产品活线零改动(逐字节断言,非承诺):

text
git diff HEAD -- MacApp/Sidecar/perfowl_collector_core/{realtime,recording,display_performance,launch_trace,adapters}.py
→ 空

startup_c0_feasibility.py 是新增的离线模块,没有任何调用方:它是一个纯 reader,不注册 tap、不订阅 ActivityTrace、不拥有 CoreProfile/kperf、不写 Session、不触碰 totalDurationMs。把「C0 只有离线读取能力」 这件事说清楚,是本批最重要的一条诚实边界——离线回放结构上无法满足下面 §5 列出的 5 项。

3. 关键实现决策与相对方案的偏差 ​

偏差 1(最重要):END 侧 timebase 只能标 assumed-constant,这是发现而非缺陷。FrameLifetimeDecoder.__init__(timebase_numer=125, timebase_denom=3) 是编译期常量,产品路径没有任何地方 把设备回报的 timebase 注入进去;adapters.py 里 CoreProfile 的 envelope 会带 device_mach_timestamp / mach_numer / mach_denom,ActivityTrace 的 envelope 不带。所以 END 侧的 125/3 只是「恰好对 arm64 成立 的假设」。仪表化据此把 provenance 显式分层(device-reported / assumed-constant / missing), Clock Gate 遇到非 device-reported 一律 fail-closed。

偏差 2:S2 从「Start Gate 要求」降级为「capability gap」。 方案 §5 把 S2(设备侧 process-start / resume 标记)列为 START 优先级之一。实现时确认:干净的 S0 已经满足 Start Gate,S2 是研究偏好而非门槛,且方案本身禁止在未做 census 前命名任何内核标记。因此 S2 缺仪器记入 capabilityGaps(不是 failures),报告 s2Status="not-instrumented",绝不猜测 debugID。把 「还没有仪器」写成「经验性否定结论」是不可接受的,两者在报告里保持分离。

偏差 3:Clock Gate 的速率/单调性按 (generation, source) 分组,不跨源合并。 两条流的时间锚点都打在到达时刻上,各带自己的 transport delay。最初把两源锚点合并成一个有序列表, 系统性地制造出假 clock-reset-detected。修正为按源分组后,test_source_arrival_offset_is_not_a_clock_reset 钉死该行为。

偏差 4:显式的人工标注通道。 方案 C0-2 要求 App A/B/C ×10 冷启动 + 10 个负对照。负对照「哪个 Session 是系统 UI / 别的 App / 覆盖层」 是工具无从推断的事实,因此 census 提供 --labels 注入;未标注时 falseAttributionCount 保持不可测, 不许猜。

偏差 5:有界保留(§10.1)与一处显式例外。 方案 §10.1 要求空间 O(K), K <= 64 且「不得保留第二份 FrameLifetime raw history」。30s/60fps 一轮是 1800 帧, 逐帧保留 14 个字段实测把单轮投影的常驻推高到超出预算,因此:

  • 帧诊断按 presentation 时间保留最早的 64 帧(K 大小的 max-heap,O(K) 而非 O(F));
  • 被丢弃的帧不静默:framesObserved / frameRejectCounts / framesTruncated / framesFrameLevelQualifiedBeyondSample 把全量人口压成 O(1) 计数;
  • 边界不得伪装成结论:若被丢弃的帧本可合格,报告 end-observation-truncated, 绝不允许写成 end-no-qualifying-frame(那是对从未看过的帧下断言)。

显式例外:clockAnchors 仍按源完整保留(约 2 个标量/帧,~130 B/帧 → 30s ≈ 268 KB、120s ≈ 1.0 MB)。 Clock Gate 的速率证明依赖相邻锚点对的中位斜率与逐点单调性,抽稀锚点等于削弱 C0 唯一要建立的时钟证明。 本批选择保留证明强度、把成本显式记账(benchmark 单独出表),并在遗留项里挂 C1 复核; 这不属于「第二份 raw history」——它是 2 个标量,不含 payload / 身份 / surface / quality。

4. C0 E2 证据(96 项,全绿) ​

text
cd MacApp/Sidecar && PYTHONPATH=. <py> -m unittest tests.test_startup_c0_feasibility
→ Ran 96 tests in 0.240s / OK

§12 反例矩阵逐项覆盖(左为矩阵编号):

#项用例
1clean S0 + clean frametest_s0_clean_start_is_real、test_warmup_first_frame_is_accepted、test_fully_proven_observation_reports_all_gates_passed
2S0 missing / S1 repairedtest_s0_missing_s1_repaired、test_repaired_is_never_promoted_to_real、test_s1_phase_out_of_range_rejected、test_s1_not_surviving_rejected
3S0/S1 全缺test_all_start_sources_missing
4END missingtest_no_frames_observed_is_missing、test_end_never_claims_repaired
5frame 早于 STARTtest_frame_before_start_rejected、test_frame_equal_to_start_is_not_after_start
6重复时间戳test_duplicate_timestamp_selects_exactly_one
7乱序 frametest_selection_is_invariant_to_input_order
8source-gaptest_source_gap_frame_rejected
9discontinuitytest_discontinuity_frame_rejected
10错 displaytest_display_boundary_change_rejected
11多 surface 歧义test_ambiguous_surfaces_within_grace_collapse_to_missing、test_ambiguity_is_not_downgraded_to_candidate、test_single_surface_is_not_ambiguous、test_surface_proof_resolves_ambiguity、test_without_surface_proof_the_ceiling_is_candidate、test_surface_proof_reaches_real
12非前台test_not_foreground_frame_rejected
13上一轮陈旧帧test_stale_previous_round_frame_rejected
14–16target/source/reconnect 代际错配test_target_generation_mismatch_rejected、test_source_epoch_mismatch_rejected、test_reconnect_generation_mismatch_rejected
17App A→B rebindtest_app_rebind_frame_from_previous_target_rejected
18跨代复用 clock prooftest_previous_generation_proof_cannot_be_reused、test_reconnect_generation_gets_its_own_proof、test_proof_missing_for_a_second_reconnect_generation、test_each_generation_needs_both_sources
19PID 重绑后旧帧test_unverified_pid_blocks_selection
20lifecycle 丢源但 END 正常test_lifecycle_buffer_loss_does_not_promote_the_start
21ActivityTrace 丢失但 legacy cleantest_a_clean_legacy_total_cannot_rescue_a_missing_end
22launch ack 失败test_failed_launch_ack_never_becomes_a_start_or_a_device_delta
23host↔device 桥未验证test_host_device_delta_attempt_is_forbidden、test_host_clock_delta_is_recorded_and_labelled_not_a_device_delta
28seal 后不得改写 ENDtest_frames_beyond_grace_cannot_change_the_sealed_end
29源重启后首帧重新归因test_source_restart_may_not_inherit_the_previous_rounds_first_frame
30legacy Total 逐字保持test_c0_reports_the_legacy_total_without_rewriting_it、test_no_hybrid_total_value_is_emitted
§10.1有界保留 6 项test_diagnostics_are_capped_at_the_documented_bound 等

另有 Clock Gate 8 项(时间基不一致 / provenance 未证 / 锚点不足 / 窗口 <30s / 速率漂移 / 时钟回拨 / epoch 无配对 witness / 跨代复用)与 Start Gate 质量分层 2 项。

§12-24 / 25 / 26 / 27 本批不覆盖,且不是遗漏:这四项描述的是活线 observer 的接线行为 (FrameTime 已选时复用唯一 subscription、未选时 one-shot observer 超时释放、Startup 未选时不得偷开 observer、首帧前 Stop 的干净 teardown)。C0 没有活线路径,无法用离线 fixture 产生有意义的反例。 它们由 C1 实现后以活线测试覆盖——本批只把结构性约束作为断言钉住:benchmark 输出 realtimePyUnchanged=true / newActivityTraceSubscriptions=0 / newCoreProfileRecordings=0。

5. C0 离线结构性无法满足的 5 项(必须真机/人工补) ​

census 每次运行都会把这张表原样打印出来,防止下游把「离线测不到」读成「已经测过」:

  1. C0-1 配对同事件 witness:产品路径不记录任何「同一事件同时出现在 CoreProfile lifecycle 流与 ActivityTrace FrameLifetime 流」的 witness ⇒ cross-source-epoch-unproven 无法靠回放清除。 必须真机产出该 witness,或由 Lead AI 重新规定跨源时钟证明。
  2. C0-1 30s 窗口 + reconnect 复证:需要「选了 FrameTime 指标」(否则 ActivityTrace 根本不跑) 且「同一次采集内含 reconnect」的 Session。
  3. C0-2 负对照:哪个 Session 是系统 UI / 别的 App / 覆盖层只有操作者知道 ⇒ 需要 --labels, 否则 falseAttributionCount 保持不可测。
  4. C0-2 surfaceID → 目标 PID 映射:产品代码不证明该映射 ⇒ END 侧 real 不可达, 最强只能到 candidate。
  5. C0-3 S2 内核 process-start 标记:无仪器,且方案禁止未做 census 就命名 ⇒ not-instrumented。

6. 性能与资源 benchmark(§10 / §10.1) ​

text
/py MacApp/scripts/benchmark-startup-c0-feasibility.py --rounds 20 --json internal/startup-c0-benchmark.json
→ exit 0(三项预算全过)

合成 Session 规模 300 / 900 / 1800 / 3600 帧 × 5 轮,1800 帧 ≈ 真实 30s/60fps。

项目预算实测判定
单帧投影耗时 p95≤ 1 ms0.3685 ms(中位 0.1757)PASS
吞吐≥ 240 events/smin 2501.3 / median 5698.0PASS
C0 自有增量工作集≤ 2 MiB0.379 MiBPASS
单次完整评估(含 1891 事件 Session 投影)—6.752 ms / 次记录
诊断帧保留数 @300/900/1800/3600= K ≤ 6464 / 64 / 64 / 64与 F 无关
报告字节 @300/900/1800/3600与 F 无关18083 / 18084 / 18085 / 18085与 F 无关
新增 CoreProfile/kperf recording00PASS
重复 ActivityTrace subscription00PASS

RSS 归因必须分开说,否则是错告。逐阶段高水位拆分出:

text
harness 造 Session      0.047 MiB
投影(含读 Session)    5.348 MiB   ← 其中 validate_recorded_session 单独实测 4.980 MiB
闸评估                  0.012 MiB

validate_recorded_session 会把整份 Session 的每个事件物化进内存(本批 1891 事件),因此任何建立在它 之上的离线分析器都继承一个 O(session) 底噪。该函数属产品既存代码、本批逐字节未改。所以 §10.1 的 2 MiB 空间预算按 C0 自有增量判定(0.379 MiB,PASS),同时把未归因的 5.359 MiB 原样写进 rssAttributionMiB.analyzerIncrementalPeak 与 observations.analyzerIncrementalPeakWithinBudgetUnattributed=false, 任何人可复核这次拆分,不存在「把预算偷偷改小」。

7. 全量回归(E2)与 flake 归因 ​

测试文件同一性(先证明失败文件与基线逐字节相同):

text
IDENTICAL  tests/test_sample_publisher_decoupling.py
IDENTICAL  tests/test_realtime_consumer_fairness.py
IDENTICAL  tests/test_pmd3_subscription_fairness.py
IDENTICAL  tests/test_pump_filter_active_fairness.py
IDENTICAL  tests/test_display_ingress_backpressure.py

基线探针:git archive 5a06929 MacApp fixtures | tar -x -C /tmp/probe。base = 853 项;ship = 949 项(+96)。

交错配对 ≥3 轮(本机多 AI 共用,负载摆动可达 20 倍,单次通过无意义):

轮shipbase
1944 / 3 fail853 / 2 fail
2949 / 6 fail853 / 2 fail
3949 / 5 fail853 / 3 fail

失败集合逐轮漂移,且同一个名字在基线也失败:

  • test_pump_filter_active_fairness…test_g_rejected_flood_keeps_message_bound_fairness — base 三轮全失败、ship 三轮全失败 ⇒ 基线既有;
  • test_display_ingress_backpressure…test_b1_b2_synthetic_120hz_benchmark — base r1/r3、ship r2/r3;
  • test_pmd3_subscription_fairness…(三轮内换了 3 个不同用例)— base r2/r3;
  • test_pump_filter_active_fairness…WallVersusActiveTimeBenchmark — base r3、ship r2;
  • test_realtime_consumer_fairness…(DisplayPipelineBenchmark / HeartbeatFairness)— base 同文件 ship r1/r3。

对「只在 ship 出现的 3 个名字」做隔离配对复测(base/ship 各 4 轮,6 个用例):

text
     cases: spcad hbeat pmd3 wall-vs-active flood backpressure
ship-r1 :: P P P P F P        base-r1 :: P P P P F P
ship-r2 :: P P P P F P        base-r2 :: P P P P F P
ship-r3 :: P F P P F P        base-r3 :: P P P P P P
ship-r4 :: P P F F F F        base-r4 :: P P P P F P
  • flood 两侧在隔离下同样失败(base r1/r2/r4)⇒ 排除回归;
  • 其余各项在两侧压倒性通过(spcad 8/8 全 P),仅 ship-r4 一轮集中掉落 —— 该轮处于 48 次测试调用后的 负载/热漂移尾部,同一轮 base 也并非干净。

结论(不过度声明):可归因回归 = 0。所有失败都落在已知计时/调度敏感家族,且基线同场同样失败; spcad / hbeat / pmd3 三个名字仅在 ship 出现,隔离复测 7/8–8/8 通过、测试文件与基线逐字节相同、 本批改动是新增离线文件且 realtime.py 未改,判定为负载敏感而非本批引入;但「无真机、无负载隔离的 单主机」不足以对这三个名字做出统计显著性结论,因此它们保留为未归因项,交独立验收复核,本批不据此 声称「0 失败」。

8. 当前状态与遗留项 ​

  • C0 状态:implemented · gate-open(E2 完成 / E4 待执行);
  • C0 Gate 判定:未做。judgement 恒为 pending-lead-ai,报告不输出任何 Hybrid 值 (test_no_hybrid_total_value_is_emitted 钉死),也不写 validated;
  • C1:未开始;realtime.py 未改(用户明确要求 C1 需接活线时再做);
  • C2:未进入;shadow 未提升为正式 Startup Total。

遗留项:

  1. clockAnchors 仍为 O(F)(~130 B/帧)。C1 复核是否把 Clock Gate 的速率证明改成流式摘要(同时保住 单调性与中位斜率),以严格满足 §10.1;
  2. scpad / hbeat / pmd3 三个未归因名字需独立验收在隔离主机复核;
  3. C0-1 配对 witness、C0-2 surfaceID→PID 证明需要可能存在的产品侧记录能力——若真机也无法产出, 建议由 Lead AI 重新规定跨源时钟证明与 END 归因的可达上限(当前 END 最强只能是 candidate);
  4. FrameLifetimeDecoder 的 125/3 仍是编译期常量。若真机 proof 显示设备回报值与常量不同, 需要一次公式入档的正式变更,而不是就地改常量。

Lead AI Independent C0 E2 Audit(2026-09-22) ​

独立验收对象:exact commit 80b0b162cdfb44ba480bff45b882fe4f718e33ac,审计基线 5a06929c22db912db22866ed2c29109761f1b797。该 range 只有 1 个提交、9 个文件;对 realtime.py、recording.py、display_performance.py、launch_trace.py、adapters.py 做 exact diff,结果均为空,确认 C0 未接产品活线。

独立复核证据:

  • C0 focused:96 / 96 OK(Lead 独立运行)。
  • C0 benchmark:单帧投影 p95 0.127 ms,吞吐 min 7346 events/s,C0-owned RSS 增量 0.418 MiB;K=64 保留与预算均成立。
  • Sidecar 全量:949 tests / failures=1 / errors=0 / 167.580s。唯一失败仍为既有负载敏感 test_g_rejected_flood_keeps_message_bound_fairness(3103 未大于 3123);该测试不在本批 diff,且此前基线/ship 已多轮证明为既有 flake,本批不修改其阈值。
  • Clock Gate 对 assumed-constant FrameLifetime timebase fail-closed;recorded-session projection 不生成 paired witness,因此 cross-source-epoch-unproven 不会被离线回放伪清除。
  • END 在没有 surfaceID -> target PID proof 时最高仅为 candidate;C0 不输出 Hybrid Total,judgement 保持 pending-lead-ai。

阻塞缺陷 C0-FIX-01 · round foreground verification 未进入 End Gate ​

evaluate_c0_end_gate() 读取了 foregroundVerified,但没有把它用于 frame selection。Lead 构造反例:

foregroundVerified=false + frame 自身 foreground=true + 无 surface proof,当前结果仍为:

text
status      = passed
endQuality  = candidate
selectedEnd = true
failures    = []

这违反正式方案 §6 的「target foreground 状态成立」硬门禁。尤其当前 ActivityTrace adapter 的 foreground 来自 target 配置,缺省可为 true,因此不能用单个 frame 的 foreground=true 替代 round-level verified foreground 证据。

修复要求:

  1. foregroundVerified is not true 时 End Gate 必须 fail-closed,禁止产生 selected END;
  2. 新增独立 failure/reject provenance(建议 target-foreground-unverified),不要把“未证明”伪写成“明确不在前台”;
  3. 增加确定性反例:round foreground 未验证、frame foreground=true 仍必须 missing / failed;
  4. 明确 foregroundVerified 的证据来源,禁止从待选 FrameLifetime 自身循环证明。

阻塞缺陷 C0-FIX-02 · recorded-session 不能自动等价 E4 ​

当前 evaluate_c0_feasibility() 仅凭:

text
origin == "recorded-session"

就把 evidence 标为 E4。Lead 使用 synthetic observation 独立复现:只要设置 origin="recorded-session",报告即输出 E4。这违反项目证据等级红线:E4 必须是真机证据,序列化 Session 形态本身不是 E4。

修复要求:

  1. recorded/replay/synthetic Session 默认不得自动升级 E4;
  2. 默认保持 E2,只有明确且可信的 true-device capture provenance 才可标 E4;
  3. provenance 必须可审计并随 census 输出,不能由任意 observation 字符串自报即升级;
  4. 增加测试:synthetic recorded session = E2;具备正式 true-device provenance 的 Session 才可 = E4。

Lead Gate 结论 ​

  • C0 离线架构方向:接受。
  • C0 E2 实现验收:BLOCKED / REPAIR REQUIRED。
  • 正式 Test AI 真机 C0-1/C0-2/C0-3:暂缓。 当前工具存在 attribution 与 evidence-level 两处会污染 Gate 证据的缺陷,不能先采再解释。
  • C1:继续 BLOCKED。
  • C2:继续禁止。

最小修复范围仅限 C0 离线模块、C0 tests、census/provenance 输出及本 devlog/handoff;不得修改 realtime.py 或借此进入 C1。修复提交后由 Lead AI 复验上述两个反例、focused/full regression 与 benchmark;通过后才把 C0 状态切为 READY FOR FORMAL E4,再交 Test AI 真机执行。

Implementation Fix Update · 2026-09-22(C0-FIX-01 / C0-FIX-02) ​

Lead AI 对 80b0b162cdfb44ba480bff45b882fe4f718e33ac 的独立验收判定 C0 E2 = BLOCKED / REPAIR REQUIRED。本批只修上述两个阻塞缺陷:不进入 C1,不改 realtime.py 等产品活线,不解决 S2 / surfaceID→PID / clock witness,不启动真机 C0,不宣布 C0 PASS。

1. 缺陷与修复 ​

C0-FIX-01 · round foreground verification 未进入 End Gate ​

修复前行为(Lead 复现,本机复跑确认):foregroundVerified=false 且 frame.foreground=true 时,evaluate_c0_end_gate() 仍返回 status=passed、endQuality=real、selectedEnd 非空、failures=[]。本机复跑比 Lead 记录更严重——得到 real 而非 candidate。

根因两处,缺一不可:

  1. evaluate_c0_end_gate() 读入了 foreground_verified,但它从未参与选择;选择只受 surface_proven 影响。
  2. collect_c0_observations_from_session() 用 first_frame["quality"] != "not-foreground" 反推 foregroundVerified——循环证明:待选的那一帧同时充当"允许选中它"的证人。

修复:

位置变更
evaluate_c0_end_gate()round 级 foregroundVerified is not True → 追加 fail-closed failure target-foreground-unverified;选择分支由 else 收紧为 elif foreground_verified:,无 proof 时 selectedEnd=null、selectionReason=null、endQuality="missing"
FAILURE_CLASSES新增 "target-foreground-unverified": unverified
FRAME_REJECT_ORDER不新增:这是 round 级事实,不是帧级 reject。帧级 not-foreground 仍表示"该帧自证不在前台",两者不得互相冒名
round row新增 foregroundVerified / foregroundVerifiedSource
End Gate 汇总新增 foregroundVerifiedRoundCount / foregroundUnverifiedRoundCount / foregroundVerificationAvailable
collect_c0_observations_from_session()删除循环推导,改为 foregroundVerified=False + foregroundVerifiedSource="missing",并追加 note foreground-verification-unavailable-in-recorded-session
常量新增 FOREGROUND_SOURCE_MISSING / FOREGROUND_SOURCE_INDEPENDENT_WITNESS

foregroundVerified 的证据来源(Lead 要求 4):只能来自独立于待选 FrameLifetime 的证人。Session manifest 只记录 identityStatus(身份),不记录前台;产品当前没有任何路径产生该证人。因此离线投影恒为 false、End Gate 恒报 target-foreground-unverified——这是缺仪器,不是"已证明不在前台"的经验负结论。

C0-FIX-02 · recorded-session 不得自动等价 E4 ​

修复前行为:evaluate_c0_feasibility() 中 "evidence": "E4" if observation.get("origin") == "recorded-session" else "E2"。任意 origin="recorded-session" 的 observation(含全合成 fixture)即输出 E4。

修复:新增 resolve_c0_evidence_level(observation) -> (level, provenance),等级只由显式可审计的采集 provenance 决定,不再由字符串自报:

输入等级provenance
origin ∈ {replay, synthetic}E2(origin 否决,即使携带完整 witness)declared-non-capture-origin
无 captureProvenanceE2not-a-device-capture
kind != "true-device-capture"、witness 非 Mapping、缺 captureId、capturedAtNs 非正E2capture-witness-unusable
kind="true-device-capture" + trueDeviceWitness{captureId, capturedAtNs} 完整E4true-device-capture-witness

报告同时输出 evidence 与 evidenceProvenance;投影 observation 显式声明 captureProvenance: null("声明",不是"缺字段")。replay / synthetic 即使带 witness 也恒 E2:声明与证人自相矛盾的记录不构成可审计证据。

2. 实际修改范围(4 个文件) ​

文件变更
MacApp/Sidecar/perfowl_collector_core/startup_c0_feasibility.py两项修复主体(常量 / 解析器 / End Gate fail-closed / 投影去循环 / 汇总字段)
MacApp/Sidecar/tests/test_startup_c0_feasibility.py+13 / −1 测试(含 2 个 Lead 反例)
MacApp/scripts/startup-c0-census.pyrow/aggregate 保留 evidence、evidenceProvenance 与 foreground 计数;新增第 6 条 UNCOVERED;控制台新增证据列
site/devlog/p4-startup-phase-c-hybrid-total-plan.md本段

未改:MacApp/scripts/benchmark-startup-c0-feasibility.py(§10.1 空间语义未变,逐字节未动);internal/startup-c0-benchmark.json 为重跑产物。

3. 5 个产品活线文件隔离证明 ​

realtime.py / recording.py / display_performance.py / launch_trace.py / adapters.py 相对 C0 原实现 80b0b16 与基线 13c913b:git diff --stat 为空,SHA-256 逐一 IDENTICAL。

文件SHA-256(前 16)结论
realtime.py8ee779bdf1e6d49dIDENTICAL
recording.py886d4b4c2fcf6391IDENTICAL
display_performance.py12e5daf3019d3bc0IDENTICAL
launch_trace.py78c8e215fbd16117IDENTICAL
adapters.py2eead9d1e14f1caeIDENTICAL

benchmark 另独立断言 productionHotPath.realtimePyUnchanged = true、新增 ActivityTrace 订阅 0。

4. C0 E2 证据(108 项全绿) ​

text
cd MacApp/Sidecar && PYTHONPATH=. <py> -m unittest tests.test_startup_c0_feasibility
Ran 108 tests in 0.343s
OK

新增 13 项 / 移除 1 项:

  • Lead 反例 1(C0-FIX-01) C0EndGateTests.test_lead_counterexample_unverified_foreground_never_selects_an_end:断言 status=failed、selectedEnd=null、endQuality=missing、selectionReason=null、publishableEndRate=0、failures 含 target-foreground-unverified,且帧级 rejectedBy=[] 且 not-foreground 不出现在 frameRejectCounts(证明未把"未证明"伪写为"证明非前台")、target-foreground-unverified 不在 FRAME_REJECT_ORDER、failureClasses 含 unverified 不含 unsupported;并以 foregroundVerified=true 的同帧对照证明断言非空泛。
  • Lead 反例 2(C0-FIX-02) C0FeasibilityReportTests.test_lead_counterexample_recorded_session_does_not_upgrade_to_e4:origin="recorded-session" → E2 / not-a-device-capture。
  • E2/E4 契约 4 项:test_origin_alone_never_promotes_past_e2(枚举 5 种 origin 恒 E2)、test_declared_non_capture_origins_veto_even_a_full_witness、test_only_a_complete_true_device_witness_reaches_e4、test_a_partial_witness_stays_e2(8 种残缺 witness 各自被拒)。
  • 投影/写入路径 3 项:test_projection_never_claims_foreground_verification(含"帧确实声称前台"的非空泛反证)、test_a_projected_session_is_e2_and_fails_the_end_gate_closed、test_deriving_the_session_report_keeps_e2_and_the_foreground_blocker。
  • census provenance 2 项:C0CensusProvenanceTests.test_census_rows_carry_level_and_provenance、test_census_never_prints_e4_for_a_recorded_session。
  • 其余 2 项:test_round_row_reports_its_foreground_provenance、test_resolver_is_the_single_source_of_the_level。

被移除的 1 项:C0FeasibilityReportTests.test_origin_drives_the_evidence_level。该断言钉死的旧值 origin="recorded-session" → E4 正是 Lead 判为缺陷的契约本身,必须随契约变更而改变;其覆盖由 test_origin_alone_never_promotes_past_e2 与两项反例测试接续,覆盖面只增不减(详见 §7 偏差 3)。

5. 全量回归与 flake 归因(E2,未放宽任何阈值) ​

轮次树用例数结果
R1ship(本批)9614 FAIL + 1 ERROR
R2ship(本批)9616 FAIL
R1base 13c913b9492 FAIL
R2base 13c913b9491 FAIL

证据一 · 失败集合逐次漂移(同一代码两轮):ship R1 挂 xctrace reap(ERROR)、pmd3×3、flood;ship R2 挂 display_ingress_backpressure、pmd3×2、flood、r8fix11、DisplayPipelineBenchmark。xctrace reap 与 pmd3 burst 在 R2 消失,三项新名字出现——失败集合不是代码属性。

证据二 · 基线同样漂移:base R1 挂 flood + DisplayPipelineBenchmark,base R2 只挂 flood。

证据三 · 交错隔离配对(3 轮 ship/base 交替,每轮 8 名全跑,ran=8/8):

text
name           ship   base   attributable?
xctrace-reap   PPP    PPP    no
pmd3-filter    PPP    PPP    no
pmd3-pump      PPP    PPP    no
pmd3-burst     PPP    PPP    no
flood-bound    FFF    FFF    no        <- 两树 6/6 全挂:稳定宿主 flake
ingress-bp     PFP    FPF    no        <- 两树都挂,但轮次不同
r8fix11-par    PPP    PPP    no
display-bench  PPP    PPP    no

interleaved ship/base pairs: 3
attributable regressions: 0
  • flood-bound(test_g_rejected_flood_keeps_message_bound_fairness):ship 3/3 挂、base 3/3 挂——message-limit 逼近 3123 阈值线,属已知计时敏感族;两树同挂,不可归因本批。
  • ingress-bp(test_b1_b2_synthetic_120hz_benchmark):ship PFP、base FPF——两树都失败、轮次不同,属负载上下文 flake。
  • 仅在 ship 侧出现过的名字(xctrace reap、pmd3 三项、r8fix11、DisplayPipelineBenchmark)在隔离配对下两树各 3/3 通过。
  • xctrace reap 结构上不可达本批改动:其 import 闭包只依赖 launch_trace / xctrace_capture / 标准库;且该测试以 200 ms 真实墙钟超时拉起子进程并断言其被回收,本机负载下子进程来不及写出 pid 文件即报 ERROR(非 FAIL),与观测一致。

失败率:ship 10/1922 = 0.52%,base 3/1898 = 0.16%(两轮全量合计)。结论:0 项可归因回归;6 个名字曾在 ship 侧出现但经交错配对排除,已登记在案供 Lead 独立复查。

证据四 · 用例集合归属(loader 口径,非 grep -c 'def test_'):base 949 / ship 961,net +12。comm -23(ship 独有)= 13 项,全部位于 test_startup_c0_feasibility;comm -13(base 独有)= 1 项,即被契约变更取代的 test_origin_drives_the_evidence_level。

6. C0 benchmark 重跑(§10 / §10.1) ​

指标预算实测判定
collect 每帧 p95≤ 1.0 ms0.0650 msPASS
吞吐≥ 240 帧/smin 14719 / median 21690 帧/sPASS
额外 RSS≤ 2 MiBC0 自身增量 0.4258 MiBPASS
诊断帧保留O(K), K ≤ 64300/900/1800/3600 四档恒为 64PASS
报告体积不随 F 增长18407 → 18409 BPASS
产品活线逐字节不变realtimePyUnchanged=true,新增订阅 0PASS

rssAttributionMiB:sessionReaderBaseline 4.973 MiB(产品自身 validate_recorded_session 的 O(session) 下限)、analyzerIncrementalPeak 5.398 MiB、c0OwnedIncremental 0.426 MiB。未经分摊的峰值仍原样输出(analyzerIncrementalPeakWithinBudgetUnattributed=false)以保持可审计;重跑未修改 benchmark 脚本。

7. 相对原方案的偏差与过程记录 ​

  1. 新增 foregroundVerifiedSource 字段:Lead 要求"明确 foregroundVerified 的证据来源",原 observation schema 无此字段,故新增并随 round row 输出。
  2. 投影行为收紧(显式登记):投影 foregroundVerified 由"从帧反推"改为恒 false,直接后果是所有离线 Session 的 End Gate 现在都记为 target-foreground-unverified、selectedEnd 为 null。这是去掉伪造 proof 的必然结果,不是回归;census 已把该现象登记为第 6 条 UNCOVERED,防止被误读为"已证明不在前台"的经验负结论。
  3. resolve_c0_evidence_level 保留一条升级路径:origin="recorded-session" + 完整真机 witness 仍可为 E4。理由:recorded-session 是真机采集的序列化形态,Lead 要求 2 允许"明确、可信、可审计的真机采集来源";而 replay / synthetic 属声明性非采集中间态,恒 E2。Lead 反例(合成的 recorded-session)因无 witness 而恒 E2。
  4. benchmark 未改动:§10.1 空间语义未变,仅重跑产出新 JSON。
  5. 过程偏差(工具):对同一文件连续两次批量写入时观察到前一次编辑静默丢失,改为逐次写入 + grep 复核,并在提交前以测试结果与 SHA-256 校验兜底。

8. 当前状态与遗留项 ​

  • C0 两处阻塞缺陷:已修复并在本地验证(E2)。 两项 Lead 反例均已闭环。
  • 本 AI 不宣布 C0 PASS。 报告 judgement 恒为 pending-lead-ai。
  • C0 状态:待 Lead AI 复验两项反例 + focused/full 回归 + benchmark 后,再切 READY FOR FORMAL E4。
  • 正式 Test AI 真机 C0-1/C0-2/C0-3:本 AI 未启动、未自证。
  • C1:BLOCKED(不因本修复自动开启)。C2:禁止。
  • 遗留(不属本批范围,均未改动):S2 kernel marker 无仪器;surfaceID→PID 无证明(real 不可达);paired same-event witness 无产品路径;foregroundVerified 的独立证人尚无产品路径。

Lead AI C0 Fix Revalidation(2026-09-22) ​

独立复验对象:exact commit 66dfbb847fcd16d1acbe12f2d67108a3e2890428,父提交 13c913b44e90fba37af1932690985c7d6e539b4a。

1. 独立验证结果 ​

  • C0-FIX-01:PASS。 Lead 重新构造原反例:foregroundVerified=false + frame.foreground=true,当前输出为 status=failed / endQuality=missing / selectedEnd=null / selectionReason=null / failures=[target-foreground-unverified]。round-level foreground proof 已真正成为 selection 前置条件;recorded-session projection 也不再从待选 FrameLifetime 自身反推该 proof。
  • C0 focused:108 / 108 OK(Lead 独立运行)。
  • benchmark:单帧投影 p95 0.0693 ms(≤1 ms)、吞吐 min 13959 events/s(≥240)、C0-owned RSS 0.473 MiB(≤2 MiB)、诊断帧 K=64 恒定、报告字节 18407→18409,预算全过。
  • 5 个产品活线文件相对 80b0b16..66dfbb8 exact diff 为空,确认仍未进入 C1。
  • Sidecar 全量:961 tests / failures=1 / errors=0 / 134.473s。唯一失败仍是既有负载敏感 test_g_rejected_flood_keeps_message_bound_fairness(3117 未大于 3123);不在本批 diff,且此前 base/ship 多轮已同场复现,继续归为既有 flake。

2. C0-FIX-02 仍未闭合:结构化 witness 仍可自证 E4 ​

当前 resolve_c0_evidence_level() 把以下普通 observation 字段视为足以升级 E4:

text
captureProvenance.kind = "true-device-capture"
trueDeviceWitness.captureId = 任意非空字符串
trueDeviceWitness.capturedAtNs = 任意正时间戳

但这些字段没有绑定到产品采集事实、Session 内容哈希、设备侧不可伪造事实或外部 Test/Lead attestation;仓库中除 C0 自身测试与该解析器外,也不存在另一个可信 producer。测试 _true_device_witness() 本身就是手工构造普通 dict。

Lead 独立反例:对 synthetic fixture 生成的 observation 直接注入:

text
captureProvenance = {
  kind: "true-device-capture",
  trueDeviceWitness: {
    captureId: "forged-by-fixture",
    capturedAtNs: 1700000000000000000
  }
}

当前机械报告立即输出:

text
evidence = E4
evidenceProvenance = true-device-capture-witness

因此原缺陷只从“一个 origin 字符串自报 E4”变成了“一个三字段字典自报 E4”。这仍不满足 Lead 审计要求中的“明确、可信、可审计的 true-device provenance”,也违反项目 E4 是执行/采集事实而非输入 JSON 形状的证据等级红线。

将该剩余缺陷命名为 C0-FIX-02B · mechanical report must not self-promote to E4。

3. C0-FIX-02B 修复决策 ​

最小且最诚实的语义为:

  1. C0 离线 evaluator 自身永远不得把 observation 内容升级为 E4。 evaluate_c0_feasibility() 的机械报告最多标 E2;结构化 captureProvenance 可以保留为“capture claim / diagnostic provenance”,但不能决定证据等级。
  2. E4 属于 Test AI / Lead AI 的外层执行证据等级。 真机 C0-1/C0-2/C0-3 实际运行后,由 Test AI 交付 session/命令/设备采集上下文,Lead 再判该批证据为 E4;不得让被分析的数据自己给自己发 E4 证书。
  3. 如确实希望产物内携带 E4,应另设外部、hash-bound 的 test attestation 层,由正式 E4 harness 对输入 Session/labels 做内容绑定;该层不能是 observation 内可任意赋值的普通字段。本轮为最小修复,不要求先实现该扩展。
  4. 新增反例:即使 observation 带“结构完整”的 true-device-capture dict,机械 C0 report 仍必须为 E2;原 test_only_a_complete_true_device_witness_reaches_e4 必须删除或改写,因为它当前钉死的就是剩余缺陷。
  5. census 可继续显示 capture provenance claim,但必须与 evidence=E2 明确分列,禁止把 claim 渲染成 E4。

4. Lead Gate 结论 ​

  • C0-FIX-01:PASS。
  • C0-FIX-02:PARTIAL;C0-FIX-02B REPAIR REQUIRED。
  • C0 E2 总门禁:仍 BLOCKED。
  • READY FOR FORMAL E4:NO。 Test AI 暂不启动正式 C0-1/C0-2/C0-3。
  • C1:继续 BLOCKED。C2:继续禁止。

下一次 Implementation AI 只允许修 C0-FIX-02B 与对应 tests/census/docs;不得改产品活线、不得补 foreground 产品仪器、不得进入 C1。

Implementation Fix Update · 2026-09-22(C0-FIX-02B) ​

Lead AI 对 66dfbb847fcd16d1acbe12f2d67108a3e2890428 的独立复验给出 C0-FIX-01 = PASS / C0-FIX-02 = PARTIAL / C0-FIX-02B = REPAIR REQUIRED / C0 E2 = BLOCKED / READY FOR FORMAL E4 = NO(见上文《Lead AI C0 Fix Revalidation》)。本批只修 C0-FIX-02B,在基线 9ba46322ff00fda4e22fab1a49a6b3e35164a86f 上开工。不进入 C1,不改 5 个产品活线文件,不解决 foreground 产品仪器 / surfaceID→PID / paired witness / S2,不启动真机 C0,不宣布 C0 PASS,不宣布 READY FOR FORMAL E4。

1. 缺陷与修复(冻结原则) ​

修复前行为(本机在工程基线上复跑证实):resolve_c0_evidence_level() 由 observation 自带的 captureProvenance 结构决定等级——只要 kind="true-device-capture" 加任意非空 captureId、任意正 capturedAtNs,机械报告即输出 evidence=E4 / evidenceProvenance=true-device-capture-witness。仓库内除该解析器与自身测试外不存在第二个可信 producer,所以这只是把「字符串自证」升级成「结构化字典自证」。

本机用完整伪造 dict(captureId="forged-by-fixture"、capturedAtNs=1700000000000000000)对 6 个 origin 扫描:基线 9ba4632 上 4/6 个 origin 拿到 E4,修复后 0/6。

origin基线 evidence修复后 evidence修复后 claim
syntheticE2(origin 否决)E2declared-non-capture-origin
replayE2(origin 否决)E2declared-non-capture-origin
recorded-sessionE4(缺陷)E2true-device-capture-claim-unverified
true-device-captureE4(缺陷)E2true-device-capture-claim-unverified
unknownE4(缺陷)E2true-device-capture-claim-unverified
""(空 origin)E4(缺陷)E2true-device-capture-claim-unverified

冻结修复原则(逐字遵守):C0 离线 evaluator 自身不得根据 observation 内容把报告升级为 E4;机械 evaluate_c0_feasibility() 报告最高只能标 E2;captureProvenance 可继续作为 capture claim / diagnostic provenance 保留,但不能决定 evidence=E4。真正 E4 属于外层执行事实:Test AI 在真机执行 C0-1 / C0-2 / C0-3 并保留 Session、执行命令、设备采集上下文与 labels,随后由 Lead AI 根据该真实执行证据判定「这一批验收证据」为 E4。即被分析的数据不能给自己签发 E4;执行真机实验的人与验收者决定其证据等级。若未来确需报告文件内部携带 E4,须另设 hash-bound external test attestation——本轮为最小修复,不实现、不扩范围。

修复:

位置变更
resolve_c0_evidence_level()删除:等级语义整体撤出该函数
resolve_c0_capture_claim()新增,返回 str:只回答「payload 的 capture claim 有多完整」,返回 CAPTURE_CLAIM_* 命名空间——与 E* 等级命名空间刻意不相交
evaluate_c0_feasibility()evidence 恒为 EVIDENCE_RECORDED(E2);新增 evidenceAssignedBy="offline-evaluator"、evidenceTrueDeviceAssignedBy="test-ai-execution+lead-ai-verdict"、captureProvenanceClaim、captureProvenanceClaimPromotesEvidence=False;notes 增加一条明示 E4 归属
模块 docstring新增第 4 条设计规则「本模块不给自己评级」
常量新增 EVIDENCE_ASSIGNED_BY_OFFLINE_EVALUATOR / EVIDENCE_TRUE_DEVICE_ASSIGNED_BY / CAPTURE_CLAIM_{NONE,DECLARED_NON_CAPTURE,INCOMPLETE,TRUE_DEVICE_UNVERIFIED} / CAPTURE_CLAIM_PROMOTES_EVIDENCE=False;删除 4 个带等级语义的 PROVENANCE_* 常量
census rowevidenceProvenance → captureProvenanceClaim,与 evidence / evidenceAssignedBy 分列
census aggregate新增 evidenceAboveE2Count(机器可检的 0,非 0 即回归)、captureProvenanceClaimCounts、captureClaimPromotionCount
census 控制台 / notes证据等级与 claim 分两行打印;notes 明示 claim 不是等级、E4 归 Test/Lead

EVIDENCE_TRUE_DEVICE = "E4" 常量保留但本模块从不赋值:它作为「刻意缺席者的名字」存在,让读者与测试都能断言机械报告里绝不出现该等级。

2. 实际修改范围(3 个代码/测试文件 + 2 个文档) ​

文件变更
MacApp/Sidecar/perfowl_collector_core/startup_c0_feasibility.py修复主体
MacApp/Sidecar/tests/test_startup_c0_feasibility.py−1 / +4 → 净增 3 项,共 111 项
MacApp/scripts/startup-c0-census.py等级/claim 分列 + 两个机器可检计数
site/devlog/p4-startup-phase-c-hybrid-total-plan.md本段
internal/current-ai-handoff.mdC0 状态与 Lead 复验要点更新

未改:MacApp/scripts/benchmark-startup-c0-feasibility.py(逐字节未动);internal/startup-c0-benchmark.json 为重跑产物。

3. 5 个产品活线文件隔离证明 ​

realtime.py / recording.py / display_performance.py / launch_trace.py / adapters.py 相对复验对象 66dfbb8、当前 main HEAD 9ba4632 与工作区:git diff --stat 三次均为空,SHA-256 逐一 MATCH。

文件SHA-256(前 16)结论
realtime.py8ee779bdf1e6d49dIDENTICAL
recording.py886d4b4c2fcf6391IDENTICAL
display_performance.py12e5daf3019d3bc0IDENTICAL
launch_trace.py78c8e215fbd16117IDENTICAL
adapters.py2eead9d1e14f1caeIDENTICAL

benchmark 另独立断言 productionHotPath.realtimePyUnchanged = true、新增 ActivityTrace 订阅 0、新增 CoreProfile 录制 0。

4. C0 E2 证据(111 项全绿)与测试集合差异 ​

对象结果
C0 focused(ship)111 / 111 OK
C0 focused(基线 9ba4632)108 / 108 OK

用 unittest loader(非 grep -c 'def test_')取测试 ID 集合做差:108 → 111。

  • 删除 1 项:test_only_a_complete_true_device_witness_reaches_e4——它钉死的正是剩余缺陷,按要求删除/改写。
  • 改名 4 项(语义从「等级」改为「claim」):test_census_rows_carry_level_and_provenance → ..._and_capture_claim_separately;test_declared_non_capture_origins_veto_even_a_full_witness → ..._report_a_contradictory_claim;test_a_partial_witness_stays_e2 → test_a_partial_witness_is_reported_incomplete_and_stays_e2;test_resolver_is_the_single_source_of_the_level → test_capture_claim_is_never_an_evidence_level。
  • 新增 4 项(含核心反例与非空泛保护探针):
    1. test_lead_counterexample_complete_witness_still_stays_e2——核心反例:即使 observation 内人为提供完整 kind=true-device-capture + 非空 captureId + 正 capturedAtNs,机械报告仍必须 E2,且 claim 分列、captureProvenanceClaimPromotesEvidence=False;
    2. test_a_full_witness_cannot_promote_any_origin——对多个 origin 逐一附加完整伪造 witness 扫描,全部 E2;
    3. test_evidence_ownership_is_reported_not_self_assigned——断言报告声明 E4 归属,而不是默默省略;
    4. test_lead_counterexample_forged_witness_cannot_promote_through_the_census——census 层反例,并带非空泛探针:把 evidence="E4" 硬塞进 row 时 evidenceAboveE2Count 必须变成 1,证明前面那些 0 有意义。

保留(未放宽):recorded-session 无 provenance → E2;replay → E2;synthetic → E2;partial / invalid provenance → incomplete-capture-claim 且 E2。

5. 全量回归与 flake 归因(E2,未放宽任何阈值) ​

按门禁纪律做 base(9ba4632) → ship 交错配对 3 轮(共 6 次全量)。

轮次树ran失败集合大小 (F/E)耗时
1base9617 (4/3)241.7s
1ship96410 (6/4)315.9s
2base96117 (8/9)370.5s
2ship96418 (9/9)410.2s
3base96119 (10/9)501.6s
3ship96422 (10/12)835.1s
  • ran 961 → 964 恰好等于本批 C0 净增 3 项;6 次运行中没有任何 C0 测试进入失败集合。
  • 耗时 241.7s → 835.1s 单调上升(主机负载持续抬升),失败集合大小基本与之同行;base-r3(19)比 ship-r1(10)/ ship-r2(18)都差,主导变量是负载而非树。
  • 机制性归因:全仓库只有 test_startup_c0_feasibility.py 引用 C0 模块与 census 脚本(Grep 确认);本批失败的每个测试都住在别的文件里,机制上不可能由本改动引发。
  • 3 轮全量并集中仅出现在 ship、从未出现在任一 base 轮的 ID 有 7 个。对其中 5 个直接做 base/ship 交错定点探针(各 3 轮),base 同样复现:
争议 IDbase 命中ship 命中
test_11_stop_during_drain_does_not_start_new_tap3/33/3
test_14_startup_only_mode_does_not_start_frame_continuation3/33/3
test_benchmark_shipping_policy_steady_120hz_7200_frames2/32/3
test_benchmark_real_cadence_120hz_10s1/32/3
test_pump_yields_after_burst_limit1/30/3

其中 test_11 / test_14 在两棵树上都 3/3 必挂(负载下确定性失败),test_pump_yields_after_burst_limit 在基线上反而更容易挂。这 5 项与既有 flake 家族一致(test_pmd3_subscription_fairness、DisplayPipelineBenchmark、test_frametime_continuation)。

  • 余下 2 个 ID(test_filter_stream_yields_on_unmatched_flood、test_f_blocked_wire_does_not_delay_process_exit)各只在最烫的一轮(ship-r2,410.2s,约为干净基准 134s 的 3 倍)出现过一次;随后另做 4 轮 base/ship 交错定点探针(共 8 次隔离运行)同样 0 命中——说明它们只在全量套件的高争用上下文里偶发,而不是在树上稳定失败。它们同样住在不引用 C0 的文件里,本报告不声称它们是已证明的既有 flake,只记为「无机制、单次、仅出现在峰值负载轮、隔离后不可复现」的未定项——与往批同类 flake 的处理一致,且不构成本批改动引入回归的证据。
  • 结论:0 项可归因于本批 diff 的回归(未放宽任何阈值)。

6. C0 benchmark 重跑(§10 / §10.1) ​

指标本次预算结果
单帧投影 p950.0955 ms≤ 1 msPASS
吞吐 min10334 frames/s≥ 240PASS
C0-owned 增量 RSS0.3906 MiB≤ 2 MiBPASS
诊断帧保留 K恒定 64与帧数无关PASS
报告字节18409 → 18783—增 374 B(新增归属字段与 note)
realtimePyUnchangedtrue—PASS

7. 相对原方案的偏差与过程记录 ​

  1. census 字段改名而非并存:evidenceProvenance → captureProvenanceClaim。改名而非并存,是因为旧名字本身在暗示「等级的依据」,并存会留下一个仍可按等级解读的入口。
  2. captureProvenanceClaimPromotesEvidence=False 作为字段输出:把「claim 不升级等级」从注释变成可断言的机器事实;census 侧同样落到 captureClaimPromotionCount。
  3. 两个过程性坑(已修,记录以备后人):
    • git archive 探针最初只导出 MacApp/Sidecar,漏掉 MacApp/Sources,导致基线树上 test_metric_contract_exactly_matches_swift_registry 因找不到 Swift Registry 而 ERROR。这是探针工件、不是真实失败;已改为导出完整 MacApp + fixtures,单独验证该文件 4/4 OK 后重跑全部 6 轮。
    • 探针脚本先 chdir 再按相对路径写结果,把 2 个 JSON 落进了真实工作区的 MacApp/Sidecar/。已用显式路径删除(未用任何通配符或清理命令),并复核脏文件计数回到基线 23 + 本批 5 个改动。
  4. 首轮探针整体作废重跑:因上一条第一项,第一次的 6 次全量运行中基线侧数据不可信,已全部作废、未用于本报告;§5 表格全部来自重跑。

8. 当前状态与遗留项 ​

  • 本批状态:implemented(E2),等待 Lead AI 复验 C0-FIX-02B。
  • 未自判:不宣布 C0 PASS / PARTIAL / FAIL,不宣布 READY FOR FORMAL E4;真机 C0-1 / C0-2 / C0-3 未启动。
  • C0 总门禁:仍 BLOCKED;C1 继续阻塞;C2 继续禁止。
  • 遗留(均不属本批范围、未改动):S2 kernel marker 无仪器;surfaceID→PID 无证明(real 不可达);paired same-event witness 无产品路径;foregroundVerified 的独立证人无产品路径。
  • 若 Lead 复验通过并明确放行,下一阶段为 Test AI 在真机执行 C0-1 / C0-2 / C0-3 采集 E4 证据;E4 与 C0 Gate 的判定权仍在 Lead AI。

Lead AI Independent C0-FIX-02B Acceptance · 2026-09-22 ​

独立验收交付:0c9f6daa6dee38180d753eef875b275e6e6cf9f0,父提交 9ba46322ff00fda4e22fab1a49a6b3e35164a86f。

Lead E2 证据 ​

  • C0-FIX-01 PASS:foregroundVerified=false + frame 自报 foreground=true,实际结果仍为 failed / missing / selectedEnd=null / target-foreground-unverified,原循环前台证明未回归。
  • C0-FIX-02B PASS:把相同完整伪造 witness(captureId=forged-by-fixture)分别注入 synthetic、replay、recorded-session、true-device-capture、unknown、空 origin;6/6 输出 E2,0/6 E4;captureProvenanceClaim 仅描述 observation 自带声称,captureProvenanceClaimPromotesEvidence=false。
  • C0 focused:111/111 OK(Lead 独立运行)。
  • C0 benchmark 独立重跑:单帧投影 p95 0.1301 ms(预算 ≤1)、最低吞吐 7436 events/s(预算 ≥240)、C0-owned RSS 0.4141 MiB(预算 ≤2),diagnostic retention 300/900/1800/3600 帧均 64;clockAnchors 仍保留已披露的 O(F) 例外。
  • Sidecar 全量:964 tests / failures=1 / errors=0 / 140.215s。唯一失败仍是基线/ship 早已同场复现的负载敏感 test_g_rejected_flood_keeps_message_bound_fairness(本轮 3122 未大于 3123);不伪写零失败,本批 C0 测试无失败。
  • 5 个产品活线核心文件在 9ba4632..0c9f6da exact diff 为空,未进入 C1。

Lead Gate 决议 ​

C0-FIX-01 = PASS / C0-FIX-02B = PASS / C0 E2 = PASS / READY FOR FORMAL E4 = YES。 正式放行 Test AI 按本方案 §11 做真机 C0-1/2/3;C0 总 Gate 尚未 PASS,C1 BLOCKED,C2 未授权。

Test AI 需按真实设备执行事实产出 E4:原始 Session 与 SHA-256、真实设备/iOS/采集版本、命令/时间、Round/PID/generation、FrameTime 是否选择、同场 reconnect 记录和人工 negative-control labels。最低覆盖:C0-1 同设备至少 30s 双源真实 timebase/epoch 与同事件 paired witness、reconnect 再证;C0-2 Fixture A 与 App A/B/C 各至少 10 次冷启动,另 ≥10 组系统 UI/他 App/overlay/rebind 负对照(0 错归因);C0-3 同场普查 S0/S1/S2/S3 时序、可用率、PID/gen 与 source loss。任何缺失必须写 unproven、missing 或 not-instrumented,不得填造 foregroundVerified=true / paired witness / surface→PID proof。

产品现有路径尚缺同事件跨源 witness、独立 foreground witness、surface→PID 与 S2 instrument,且 ActivityTrace timebase 仍为常量假设;READY FOR E4 只开放验证,不预设实验能通过。Test AI 交回原始数据之后由 Lead 独立审查三闸并判定 C0 PASS/PARTIAL/FAIL;仅 C0 PASS 才放行 C1。

Lead AI · C0 iPhone 15 首轮真机 E4 独立验收(2026-09-23) ​

C0 Gate = PARTIAL / BLOCKED;E2 PASS 保持有效;C1 BLOCKED,C2 未授权。 Test AI 于 T1 冒烟按停止条件中止,E4 数据部分有效,未完成 C0-1/2/3 正式矩阵。首轮产物:artifacts/c0-e4-iphone15-20260922-163458/,Lead 独立复核 111/111 文件 hash 一致;3 个可读 census 均恒 E2,无 Hybrid delta 可算。Fixture A 受控冷启动 bc785461:CoreProfile 39 chunk、13 span、9 阶段完整、legacy Total candidate 463.53ms,FrameLifetime 0;真实 App P 被动 21247ed1:FrameLifetime 206、CoreProfile 0;Fixture A 被动 1e9f9fb7:FrameLifetime 0。未执行 reconnect、≥30s 真正双源窗口、正式正负样本;falseAttributionCount 不可测;S2 未仪器化。

Lead 另核本机历史 6 份 full-retention 同设备 iPhone 15、iOS 17.0、controlled-cold-launch Session:6/6 Raw SHA-256 匹配,5 份同 Session 均有 CoreProfile chunk、launch request、FrameLifetime,历史目标同属独立 App H1(不同于本轮 Fixture A、App P)。历史 5 份两源 host receipt 窗口均错开约 0.59~1.37 秒;双源曾落盘不等于设备源同时活跃,也不等于同事件时钟证明。本轮 CoreProfile 39 个 chunk 外层 deviceMachTimestamp 重复相同,不能充作 39 个独立时钟锚点。

下一步 Test AI: 先阅读 site/devlog/p4-startup-c0-historical-dual-source-reproduction-plan.md,在同一 Device A 只读核查 H1 的合法启动条件后,以 GUI vs headless、H1 vs Fixture A、Startup + FrameTime、full retention,串行最多 6 轮定向复现。提交新原始 Session/hash/启动激活时序与 live/offline 差异,再由 Lead 决定是否最小修复或重开正式 C0 E4;Test AI 不得修改产品语义、宣告 PASS 或开始 C1。

Lead AI · 第二轮 E4 双源复现独立验收与 C0-FIX-03 决议(2026-09-23) ​

二次 Test AI 交付真实且验收通过,C0 总 Gate 仍 PARTIAL / BLOCKED;C1 未放行,C2 未授权。 归档 artifacts/c0-e4-dual-source-repro-20260923-003721/,Lead 独立核验 SHA256SUMS.txt 120/120 一致;三个同 Session 双源 e010d1ee H1 prepared CP 28 / FrameLifetime 91、bc97978a H1 prepared CP 29 / FL 93、c251a56a Fixture A prepared CP 24 / FL 39,第四 9a593d26 Fixture A headless CP 37 / FL 0。H1 headless 使用悬挂启动因缺 get-task-allow 被系统阻止。prepared 是现行产品 Sidecar 合法非挂起路径,但 Test AI 操作的是 GUI wire-equivalent 驱动,正式 E4 仍需真实 GUI 端到端冒烟。

纠正 START 归因:H1 prepared 两轮 live 只有 1 / 0 span,而同样 prepared 的 Fixture A live 13 span、九阶段完整、legacy candidate Total 295.62ms。此前“prepared 路径全部丢 START”的一般化不成立,须以 RAW/prewarm/target timing/replay 做目标差异归因。四轮 C0 census 4/4 仍 E2、未输出 Hybrid;offline 与 live 的 bind/report 重建有待核实。

钟域与 END 缺口不变:双源三轮 internal device ticks 窗口间隔约 0.40/1.56/6.00s,paired same-event witness = 0,ActivityTrace 125/3 仍 assumed-constant;不能声明 clock PASS。独立 foreground 与 surface→PID 未证、30s 双端+reconnect 和正式正/负样本矩阵未完成,falseAttributionCount=0 不可测。

Lead 决定下一步不是 C1、不是立刻大规模真机,而是 C0-FIX-03 三个独立包,见 site/devlog/p4-startup-c0-fix03-prepared-start-clock-end-evidence-plan.md:03A START 根因+offline 顺序投影、03B 真实跨源 clock 证明可行性(失败保持 unproven,备选需 Lead amendment)、03C 独立且时间可核验的 foreground / END 归因诊断。Implementation AI 不可自行解锁 Gate;独立 E2 完成后再交 Test AI E4。

Perfowl · Performance Observer