diff --git a/docs/API.md b/docs/API.md index cecfca3..93f16f8 100644 --- a/docs/API.md +++ b/docs/API.md @@ -7875,14 +7875,32 @@ window.__AGENTMAIL_TOKEN__ = ''; // 省略则走 Cookie ``` · **确定**: −3 有**至少一个**自洽解释(在飞占位释放)⇒ "缺口已有一个可行解释"(**不是唯一解释**) · **确定**: `reset-demo` **可排除**(硬排除,不依赖单调性);`prune` **不能**用计数/单调性排除 - · **确定(pi 的物证)**: `prune --apply` 与 `reset-demo` **都未跑过** —— 凭**谓词无关的产物** + · ~~**确定(pi 的物证)**: `prune --apply` 与 `reset-demo` **都未跑过** —— 凭**谓词无关的产物**~~ + ⚠️ ★★★ **2026-09-27 04:10 复测: 这条的**物证① 已失效**,整条要降级** (/tmp 无 pre-prune 备份 + backups 目录 0 文件且 mtime 未动) ⚠️ ★★ **强度须限定**(2026-09-27 补: 本文别处已写这个限定、此处漏了 ⇒ 同文件口径不一): 产物是**本机**的 ⇒ 它排除的是「**本机**任何 `--apply`(不论谓词、不论库)」, **不是**「任何机器上都没跑过」—— 后者无任何证据。 物证② 还要再限一层: `PREFIX` **与** `DB` 都可被 env 改 ⇒ 它只覆盖「**默认 prefix + 默认库**」,不是"前缀无关/库无关"。 - ⇒ ★ 三条腿的真强度: 物证① **本机**谓词无关 > 物证② **本机**默认路径 > 「库非空」默认路径 + ⚠️ ★★★ **且物证① 有一个会自己消失的前提**(新增,本轮实测发现): + 它成立需要「**该时段 /tmp 未被清空**」。pi `c6dbc8d0` 当时正是用 + 「争议窗口 ±1h 内**有 21 个别的文件存活**」钉这个前提 —— **那一步很扎实**。 + ★★ 但我 2026-09-27 04:10 重测: 早于 09-26 09:32 的 /tmp 文件 = **0 个**、 + 争议窗口(04:00–06:30)内也是 **0 个**;而 `tmpfiles.d/tmp.conf:11` + 是 `q /tmp ... 10d`(**1 天内不该被清**)⇒ 唯一解释是 **`/tmp` 经历过清空/重启**。 + 且 `findmnt /tmp` ⇒ **tmpfs** ⇒ ★★ **重启即全失**,与 10d 策略无关、**不可恢复**。 + ⇒ 所以「现在 0 个备份」**此刻已不能**推出「09-26 04:57 那会儿没跑过 --apply」。 + ⇒ ★ 修正后的表述(按强度,且**带时刻**): + · `reset-demo` **可排除** —— 凭物证②(`/opt/agentmail/backups/`,**非 tmpfs** ⇒ 跨重启存活, + 0 文件 + mtime 停在 09-14 17:26)✓ **这条不受影响** + · `prune` 的"未跑过"**只在 2026-09-26 04:10 之前**(当次会话内)成立; + 此后**需重新取证**,不能沿用 + ⇒ ★ 教训: 「缺失的产物」当物证时,**必须同时记录** ① 该路径会不会被自动清理 + (tmpfs / tmpfiles / logrotate)②"不是被清掉了"的**同时段旁证**(须**取证当时**记,事后不可补) + ③ 取证时刻 —— ①②③ **都会过期**。已登记 `prune-artifact-evidence-decays-with-reboot`。 + ⇒ ★ 三条腿的真强度: 物证① **本机**谓词无关(**且已过期**)> 物证② **本机**默认路径(非 tmpfs,仍有效) + > 「库非空」默认路径 —— ⚠️ 这条排序是**我此刻据三条腿的覆盖面**推出来的,**不是**我早先写过的原话 (我查了提交史: 找不到我把②③写成"与①同强"的记录 ⇒ **不据此追认我有过那个错**) · **仍不确定**: T1 的真实 bound/total(**无人观测**;pi 改判 bound(T1) ∈ [556, 559] 区间) diff --git a/docs/DEBTS.json b/docs/DEBTS.json index 0a75e57..d39084c 100644 --- a/docs/DEBTS.json +++ b/docs/DEBTS.json @@ -226,6 +226,14 @@ "where": "client/harmony/entry/src/main/ets/pages/MainPage.ets(约 1700 行的 PopIntent 监听者)+ EntryAbility(无 onBackPressed)", "kind": "bug", "note": "2026-09-26 审查发现并**尝试修复失败**,整块撤回。\n\n## 未修好的两个具体问题\n\n① `KEY_COMM_STACK_DEPTH` 停在旧值:退到列表后,下一层\"返回\"输入被吞。\n② `KEY_OPEN_MAIL_ID` 留着上一封:回到列表按回车时以为\"还在详情\",会开**回复**而不是新邮件。\n (连带 `MainPage.closeDetail()` 是死代码 —— 它只被 Esc 那条路调。)\n\n## 为什么没修\n\n2026-09-26 在 `EntryAbility` 加了 `UIAbility.onBackPressed()` → `PopIntent.request()`。\n模拟器(HarmonyOS 6.1.1,HarmonyPhone)实测:\n\n- 应用在前台时按**一次**系统返回键 ⇒ **UIAbility 被销毁**(hilog 有 `HandleAppDied`,\n `aa dump -a` 里 EntryAbility 消失),`harmony-admin` 设备判据因此挂住不返回。\n- 对照实验:把 EntryAbility + ComposeIntent + MainPage 三处 stash 掉重编重装,\n 同一条判据 **31/31 通过**。\n\n⇒ `UIAbility.onBackPressed()` 在这条链上**没被调用到**(`Navigation` 自己先消费了\n返回事件),而改动 `PopIntent` 的回调签名又改变了判据侧的行为。\n\n## 为什么不在模拟器上继续查\n\n要验的是\"框架内部返回事件的分发顺序\"这类**框架行为**,而本机模拟器这一条\n又不能代表真机。与其赌一个**会关掉应用**的半成品,不如整块撤回、留成有\n复现步骤的账。\n\n## 试过并被否掉的三种接法(都写在代码注释里)\n\n1. `Navigation.onPop` —— **不存在**,编译报\n `Property 'onPop' does not exist on type 'NavigationAttribute'`。\n2. `pushPath` 第三个参数 —— **不接受**(只接受 1-2 个)。\n3. `NavPathInfo.onPop` —— 存在,但官方文档写明**只在 `pop()` 带了 result 时才触发**,\n 而系统返回键**不走** `pop(result)` ⇒ 照样漏。\n\n## 建议的下一步\n\n在 `NavDestination` 上挂 `onWillDisappear`(或 `onHidden`),在它里面统一做\n\"重发层数 + 栈空时清发布键\";这条是**每个详情页自己**的出栈时机,\n不依赖谁来分发返回事件 ⇒ 系统返回键、Esc、手势三条路都会经过它。\n需真机确认 `onWillDisappear` 在系统返回键下确实触发。" + }, + { + "id": "prune-artifact-evidence-decays-with-reboot", + "count": 1, + "kind": "物证的**前提会失效**(不是物证本身错)—— 判据/结论的**时效性**无人复核", + "due": "下一次要用「缺失的产物」当物证时(任何 deploy 脚本旁路都算)。★ 到期动作不是'补判据',是**先查该路径会不会被清**、再决定这条物证此刻还能不能用。", + "where": "`deploy/prune-test-sessions.sh:92`(`BAK=\"/tmp/agentmail-pre-prune-$TS.db\"` 字面硬编码);`/tmp` 挂载见 `findmnt /tmp`;清理策略见 `/usr/lib/tmpfiles.d/tmp.conf:11`(`q /tmp ... 10d`)与 `systemd-tmpfiles-clean.timer`", + "note": "★★ 2026-09-27 实测登记(复核 pi `c6dbc8d0` §三 时发现)。\n\n## 形状:**\"现在没有产物\" 推出 \"当时没跑过\" 需要一个前提,而该前提会自己消失**\n```\npi `c6dbc8d0` 给的加强物证(我复核**成立**且是当时**正确**的测法):\n · prune 的 `.backup` 在删除前**无条件**执行(`:95`),路径**字面硬编码** `/tmp`、不做 env 覆盖\n · 当时实测: `agentmail-pre-prune-*` = **0 个**,且**争议窗口 ±1h 内有 21 个别的文件存活**\n ⇒ 用\"同一目录同一时段别的文件还在\"来证明\"不是被清理掉了\" ⇒ **这一步很扎实**\n```\n## ★★ 但我在 2026-09-27 04:10 重测,那个前提**已经不成立**了\n```\n实测: 早于 2026-09-26 09:32 的 /tmp 文件 = **0 个**(争议窗口 04:00–06:30 内也是 **0 个**)\n而 `tmpfiles.d/tmp.conf:11` 是 `q /tmp 1777 root root 10d` ⇒ **1 天内的文件不该被清**\n⇒ 唯一解释: **`/tmp` 经历过清空/重启**\n`findmnt /tmp` ⇒ **tmpfs** ⇒ ★★ **重启即全失**(与 10d 策略无关)\n⇒ 所以: 「现在 0 个备份」**此刻已经不能**推出「09-26 04:57 那会儿没跑过 --apply」\n```\n## 后果: 三条腿的强度**又降一级**(我上一轮已降过一次,这次是同一机制的第二级)\n```\n物证① 覆盖范围随时间**单调收缩**:\n T0(紧邻事件)⇒ 有效(前提成立)\n T0 + 任何一次重启 ⇒ **永久失效**(且不可恢复 —— tmpfs 不留痕迹)\n⇒ ★ 所以定稿里\"『prune --apply』与『reset-demo』都未跑过 —— 凭谓词无关的产物\"这句,\n 在**今天**只能保留**物证②**(`/opt/agentmail/backups/`,**非 tmpfs** ⇒ 跨重启存活)\n ⇒ 物证① 要降为「**在 09-26 04:10 之前**(当次会话内)成立,之后需重新取证」\n```\n## ★ 可判形状(到期时用)\n```\n凡以「缺失的产物」为物证,**必须同时记录三项**,缺一即降级:\n ① 产物路径是否**会**被自动清理(tmpfiles 策略 / tmpfs / logrotate / 手工 rmtree)\n ② 支撑「不是被清掉了」的**同时段旁证**(同目录同时间别的文件仍在)—— 必须在**取证当时**记,事后不可补\n ③ 取证时刻 —— 因为 ①② 都是**会过期的**\n⇒ 与我们已记的「口径会随时间漂」(`recount-labels-must-match-predicates` 补记)同族:\n 那条是**数字**会过期,这条是**物证**会过期。\n⇒ ★ 反过来也成立一条**该做而没做**的: 若某个物证会过期,**结论就该带时刻**。\n 我们此前把「prune 没跑过」写成**无时刻的现在时** ⇒ 这是本条要纠正的写法。\n" } ] }