The three things that made the deferral inert are all fixed, in the order they were
found: the reply ring could not hold an answer across the ~1,000 records between two
creates; a residency budget could not help because what displaces an answer is what
the SERVER sends, not what the client emits; and so the mechanism had to be retention.
WHAT LANDED
* ILink::DeclareReplyRead + LinkCapabilities::RetainsReplies. The wire declares a
seq will be read BEFORE it publishes, so the declaration cannot race its own
answer; a link with the capability false ignores it, and the window does not
defer on one (CreateWindowEffective() is gated on it).
* StreamLink's ring of the last 8 answers becomes a declared-answer store: a
monotone whitelist plus a cursor, answers kept until their reader TAKES them
(take-and-delete under one lock, bytes swapped into the scratch), and a capacity
of 24 that is FATAL to exceed rather than evicting. An evicted wanted answer is
unrecoverable - re-latching by sending another create wipes the server's record
(PipeApply.cpp:2033) and its PendingUploads (PipeApply.h:332) while the client
cleared its dirty flags at emission (PipeApply.h:298-304) - so the capacity is
sized so it cannot be reached and reaching it says its own name.
* An answer nobody declared is DROPPED, which is what keeps the store bounded by the
client's deferral depth instead of by the server's answer rate. Retain-on-arrival
grows ~11.3 entries per create against a server that ignores the no-reply bit.
* A read that fails after WaitForApplied has returned Reached is now Fatal{ReplyMissing}
naming the seq: on the stream arm the reply frame strictly precedes the progress
frame that publishes appliedSeq, so that combination is a broken invariant, and
retrying it (what the row used to do) wedges the window for the rest of the
process while leaving every deferred object latched on a provisional accept.
* The residency budget is deleted (WireTables.cpp keeps its history), the window
retirement branch drains once before falling back - it could otherwise strand the
answers it was holding - and Detach clears the store.
MEASURED ON THE DEVICE, load frame, both ends rebuilt, frame-sent identical per op
(create 4,536, records 103,097) throughout:
window 1 (R-5's shape) 4,536 takes 28.66 s
window 2 explicit 2,500 17.27 s
window 2 AS THE SHIPPED DEFAULT 2,563 16.52 s
window 4 1,644 11.02 s
window 2 against an OLD SERVER 2,663 16.38 s (zero Fatals)
The last row is the version-skew case the design review named as a must: a server
built before the no-reply bit answers ~55,903 records a frame, the whitelist drops
every answer nobody declared, and the deferral still reads its own back.
GATES (172 + 15 green), and the important one is proved to go red:
* ADeclaredAnswerSurvivesFarMoreInterveningAnswersThanAnyFixedBuffer - reverting the
store to "keep the last 8 arrivals" fails it immediately with "the declared answer
did not survive 64 intervening ones". That is the line between the ring-1024
stand-in and a bounded mechanism.
* AnAnswerNobodyDeclaredIsNotKeptAtAll - red if everything is retained.
* TheWindowRefusesToDeferOnALinkThatCannotRetainAnswers - on the in-process (ShmLink)
arm the knob at 4 must still block every create, red if the capability gate goes.
* The refused-create case now reads the repair that exists on THAT arm (the latch),
and asserts the window's own books are empty there.
NOT DONE, and named: the window has no unit gate on the STREAM arm yet - only the
device runs. Three rounds of this feature were green in the lanes while inert on the
device because the lanes and the device run different transports; the transport-level
retention gates close that for the store, and the window-level one should be built on
StreamClientPublicationTest's real stream session next.
阶段笔记(notes)
这一层放各阶段的全部细节:每个阶段一个目录,目录里的 README.md 是该阶段的汇总(摘要、阶段表原行、逐门实测、落地形状、当时的进度页),其余文件是那个阶段的原始工作笔记——包计划(BRIEF-*.md / TASK-*.md)、契约草稿、集成者逐条裁定(INTEGRATOR-DECISIONS-*.md)、只读审计与普查、包报告、设备记录与证据。顶层的索引(../ROADMAP.md、../MEASUREMENTS.md、../CURRENT_STAGE_PROGRESS.md)只留一句话并链到这里;不属于某个阶段的设计正文在 ../design/,上手与参考在 ../guide/。
按阶段
| 阶段 | 汇总 | 重要文件 |
|---|---|---|
| P0 卫生、度量、门、骨架 | p0/ |
BRIEF-P0.md、p0-device-findings.md |
| P0.5 值头与制品头 | p05/ |
BRIEF-P05.md、p05-results/ |
P1 PipeInputs + verify |
p1/ |
BRIEF-P1.md、P1-LANE-FINDINGS.md |
| P2 渲染状态 CSO | p2/ |
BRIEF-P2.md、INTEGRATOR-DECISIONS.md、ab/、bench/ |
| P3a 句柄 wave 1 | p3a/ |
BRIEF-P3A.md、INTEGRATOR-DECISIONS.md |
| P4a 句柄 wave 2 | p4a/ |
BRIEF-P4A.md、INTEGRATOR-DECISIONS.md、ab-redmi/ |
| P5 传输 + inproc | p5/ |
BRIEF-P5.md、PACKAGE-PREAMBLE.md、p5-results/ |
| P5b verb 迁移 | p5b/ |
BRIEF-P5B.md、p5b-results/p5b-close-codex-review.md |
| P5c 共享内存读点归零 | p5c/ |
p5c-audit-v1.md |
| P5d inproc 性能 | p5d/ |
P5D-INPROC-PERFORMANCE.md(报告)、RESULTS-P5D-R3.md |
| P5e run-ahead | p5e/ |
P5E-RUNAHEAD.md(报告)、INTEGRATOR-DECISIONS-P5E.md(ID-80..136)、TASK-*.md |
| P5f 一切状态上 wire | p5f/ |
P5F-WIRE-COMPLETENESS.md(计划)、close-report.md、magma-runahead.md、HANDOFF-CI-INPROC-20260920.md |
| P6 spawn transport | p6/ |
P6-SPAWN-PLAN.md、P6-CONTRACT-DRAFT.md、P6-ENDSTATE-REVIEW.md、a6-audit-v1.md、gate7-device-ab.md |
| P6.5 两轴传输 + 跨机 | p65/ |
evidence-index.md、validation-status.md、code-review-findings.md |
| P3b / P4b Espryt 深化 | p34b/ |
espryt-d1.md … espryt-d3.md |
| P7 Magma 全量迁移(含 Ph) | p7/ |
PLAN-PH-P34B-P7.md、INTEGRATOR-DECISIONS-P7.md(ID-P7-1..63)、HANDOFF-2026-09-23.md、device-window-*/;审查稿在 handoff/ |
| P12(当前)server 自有屏幕窗口 | p12/ |
PLAN-P12.md、INTEGRATOR-DECISIONS-P12.md、device/ |
| P8 / P9 / P10 / P11 / P13(待排) | p8/、p9/、p10/、p11/、p13/ |
目前只有路线图上的完整范围与出口门 |
跨阶段:DEBTS.md(仍开放的债务与去向)、OPEN-QUESTIONS.md(开放问题全文,编号稳定);handoff/(P7 的集成者审查稿,路径被 P7 交接文档引用,保持原位);recovered/(从失败的 workflow 运行里捞回的 P0–P2 期材料,wf1 设计定稿前的计划草案、wf2 P0、wf3 P0.5、wf4 P1、wf5 P2;与阶段目录逐字节重复的副本已于 2026-09-24 删除,只留独有的)。
旧引用怎么找
2026-09-24 整理时移动的文件(旧笔记、代码注释与契约里仍按旧名引用它们,文件名没变):
| 旧位置 | 新位置 |
|---|---|
docs/Disaggregated/P5D-INPROC-PERFORMANCE.md |
p5d/P5D-INPROC-PERFORMANCE.md |
docs/Disaggregated/P5E-RUNAHEAD.md |
p5e/P5E-RUNAHEAD.md |
docs/Disaggregated/P5F-WIRE-COMPLETENESS.md |
p5f/P5F-WIRE-COMPLETENESS.md |
docs/Disaggregated/P6-SPAWN-PLAN.md、P6-CONTRACT-DRAFT.md、P6-ENDSTATE-REVIEW.md |
p6/ 同名文件 |
docs/Disaggregated/CURRENT_STAGE_STATUS.md |
并入 ../CURRENT_STAGE_PROGRESS.md;其中 P7 的出口门 / 已落地 / 真机三节在 p7/README.md,P12 部分在 p12/README.md |
旧 CURRENT_STAGE_PROGRESS.md 的 P6.5 第一波与 P6 收官快照 |
p65/README.md、p6/README.md |
| 当前阶段页的明细(带裁定编号的表、余项清单、证据位置) | p12/README.md 的"当前状态详情"节 |
docs/Disaggregated/devices/pin-verification-2026-09-07.md |
../guide/pin-verification-2026-09-07.md |
ARCHITECTURE.md 的设计正文(§1–§17、附 A / B) |
../design/ 下十个文件,编号不变;对照表在 ../ARCHITECTURE.md |
旧 README.md 的构建运行、代码地图、术语;旧 ROADMAP.md 的通用纪律 |
../guide/ |
按编号引用的旧章节(小节编号在新位置原样保留):
| 旧引用 | 现在在 |
|---|---|
MEASUREMENTS.md §1 / §2 / §3 / §4 / §5 |
p0 / p1 / p2 / p3a / p4a 的"实测"节 |
MEASUREMENTS.md §6 / §7 / §8 / §9 |
p5 / p5b / p5c / p5d |
MEASUREMENTS.md §10 / §11 / §12 / §13 |
p5e(§10、§11)/ p6 / p34b |
ARCHITECTURE.md §17.1–§17.4 / §17.5 / §17.6 / §17.7 |
p5 / p5b / p5c / p5e 的"落地形状"节(../design/10-phase-shapes.md 留一张索引表) |
ROADMAP.md 阶段表某行、"P5c 计划与审计"、"立即的下一项:P6.5 第一波"、债务表、开放问题 |
对应阶段 README.md 的"阶段表行"节;p5c;p65;DEBTS.md(历史全表在 p5b 末节);OPEN-QUESTIONS.md |
ARCHITECTURE.md:NNN、MEASUREMENTS.md:NNN 这类行号引用 |
指向写下它时的那个版本,今天已不对应;按上下文所说的节去找,或 git show <当时的头>:docs/Disaggregated/<文件> |
~/w7/notes/<phase>/<file>.md |
docs/Disaggregated/notes/<phase>/<file>.md(这些笔记原先只存在于一台机器的 ~/w7/notes/) |
收录规则
| 收录 | 全部 .md 笔记,以及阶段自己决定入库的小脚本、判读工装与证据摘要(如 p7/device-window-*/、p12/device/、p12/gate/) |
| 不收录 | 大体积、随每次运行重新产生、只在产生它的机器上有意义的证据数据:完整运行日志、APK 与 .idsig、nm 转储、设备 logcat。上层文档引用它们时给的是路径,不是内容 |
新阶段开工时建 notes/<阶段>/,把计划、裁定与报告都放进去;阶段收官时补齐该目录的 README.md 汇总,顶层索引只改一行。
不受 citation lint 管
CI 的文档引用 lint 只检查顶层、design/ 与 guide/(.github/workflows/test.yml),本目录不在其中,这是有意的:笔记里的 file:line 写在各自当时的代码头上,拿今天的 HEAD 解析必然大面积失败——那是它们作为历史记录的正确状态。要核对某份笔记的引用,用它自己声明的那个 revision:
python3 scripts/check_doc_citations.py --rev <当时的头> docs/Disaggregated/notes/<phase>/<file>.md