- Current code has been re-audited against the earlier lightweight-RAG, agent-workspace, and mainline architecture plans.
- The reconciliation now has a dedicated source-of-truth note at
docs/solutions/knowledge-workspace-dag-alignment-2026-06-10.md. - Structured grounded conversation, grouped knowledge points, durable
flashcard_batch/knowledge_runartifacts, workflow-artifact review follow-up, and graph-focus source rendering are all code-backed in the current branch. - The current DAG-backed learning substrate is confirmed in code:
KnowledgeAtom,RelationEdge,TemporalEdge, path queries, and prerequisite-driven learning flows already exist. - [~] The visible answer area still needs contraction so users see the targeted answer first and supporting blocks move to secondary surfaces.
- [~] Left-side knowledge hits are file-first, but still need to converge on a right-pane-first reading model.
- Add a graph-conditioned context-assembly layer between retrieval and answer synthesis so the current DAG becomes a first-class answer-planning substrate.
- Continue ownership reduction in
src/server.ts,src/learning/KnowledgeLearningPlatform.ts,src/frontend/agent_workspace.js, andsrc/frontend/workspace_panes.js.
- All active tracker docs point to the same 2026-06-10 Knowledge Workspace and DAG alignment note.
- The documented current state distinguishes implemented code-backed baselines from unfinished product-surface behavior.
- The current branch is verified, promoted to
main, pushed, and the worktree is clean afterward. - Backward compatibility remains explicit: legacy
assistantMessageand current public runtime APIs are unchanged.
- 已重新按源码审计当前代码与此前 lightweight-RAG、agent-workspace 和主线架构方案的对应关系。
- 本轮对账结果已沉淀为独立主线文档:
docs/solutions/knowledge-workspace-dag-alignment-2026-06-10.md。 - 结构化 grounded conversation、按文档聚合的 knowledge point、durable
flashcard_batch/knowledge_runartifact、workflow-artifact review follow-up,以及 graph-focus 原文渲染都已经有代码支撑。 - 当前 DAG 学习底座已在代码中确认存在:
KnowledgeAtom、RelationEdge、TemporalEdge、path query 与 prerequisite 驱动的学习流都已落地。 - [~] 用户可见回答区仍需继续收缩为“targeted answer 优先,supporting block 退居次级表面”。
- [~] 左侧 knowledge hit 虽已是 file-first,但仍需继续收敛为 right-pane-first 阅读模型。
- 需要在 retrieval 与 answer synthesis 之间补一个 graph-conditioned context-assembly layer,让当前 DAG 成为一等 answer-planning substrate。
- 继续缩减
src/server.ts、src/learning/KnowledgeLearningPlatform.ts、src/frontend/agent_workspace.js、src/frontend/workspace_panes.js的所有权压力。
- 所有活跃看板文档都指向同一份 2026-06-10 知识工作区 / DAG 对齐说明。
- 文档能明确区分“已经代码落地的基线”和“仍未满足的产品行为”。
- 当前分支完成验证、推进到
main、推送并在结束后保持工作区 clean。 - 向前兼容性保持明确:legacy
assistantMessage与当前公开运行时 API 不发生破坏性变化。
- Bridge-first migration baseline is active (
Tauri + Node sidecar + Godot Path Mode). - Runtime path adaptation has been integrated for sidecar and frontend data roots.
- Worker runtime resolution has been stabilized for packaged sidecar scenarios.
- Existing-cache prompt parity in Tauri load flow needs final strict regression confirmation.
- Duplicate load execution guard needs final verification across startup/reconnect scenarios.
- Godot history tracking for center-switch actions needs final acceptance checks.
- Final Electron decommission readiness checklist remains pending.
- Exactly one prompt for cache decision when cache exists.
- Exactly one load/build/restore execution per user-triggered load.
- Stable websocket lifecycle without startup churn side effects.
- History panel records central-node switches from Godot interactions.
- Tauri desktop + Android path documented with Capacitor coexistence strategy.
- Bridge-first 迁移基线已启用(
Tauri + Node sidecar + Godot Path Mode)。 - Sidecar 与前端数据根路径的运行时适配已集成。
- 打包 Sidecar 场景下的 Worker 路径解析已稳定。
- Tauri 加载流程中“缓存已存在提示”一致性仍需最终严格回归确认。
- 重复加载执行防护仍需在启动/重连场景下完成最终验证。
- Godot 中心切换动作的 History 记录仍需最终验收。
- Electron 下线前最终就绪清单仍待完成。
- 缓存存在时只出现一次选择提示。
- 每次用户触发加载仅执行一次 load/build/restore。
- WebSocket 生命周期稳定,无启动抖动副作用。
- Godot 交互触发的中心节点切换可写入 History 面板。
- Tauri 桌面与 Android 路径具备文档化说明,并与 Capacitor 共存策略一致。
- Critical Bug Fix
- Fix Navigation Failure: Tree View defaulting to linear mode on switch center. Ensure
treeLayoutis generated duringswitchCenter.
- Fix Navigation Failure: Tree View defaulting to linear mode on switch center. Ensure
- Data Consistency (Frontend)
- Ensure
inDegreeis correctly calculated and passed in payload.- Ensure
inDegreeis correctly calculated and passed in payload. - Godot: Implement Lazy Loading Visualization
- Backend: Update path_core.js to allow unrestricted context expansion for
forcedExpansionSet. - Frontend Bridge: Update path_app.js to handle
forcedExpansionNodesand pass to worker. - Simplify Lazy Loading UI (Godot)
- Update tree_renderer.gd:
- Remove separate (+)/(-) buttons.
- Implement unified
[ Count ]button (circle with number). - Button toggles
forcedExpansionstate. - Default state is collapsed.
- Ensure path_app.js handles the toggle correctly (reusing existing logic).
- Godot Renderer: Update tree_renderer.gd to calculate visible In-Degree and show (+)/(-) buttons.
- Godot Signals: Wire up expand/collapse signals through
tree_view_panel,path_mode_uitows_client.- (Godot) Implement logic to verify
Visible < Global In-Degreeto show (+).
- (Godot) Implement logic to verify
- Ensure
- Ensure
- Tree View Visual & Interaction Overhaul
- Visual Cleanup (Godot)
- Remove (+)/(-) and
[Count]buttons from tree_renderer.gd. - Remove separate click areas for these buttons.
- Remove (+)/(-) and
- Interaction Update (Godot)
- Double Click: Change to Toggle Expansion (Emit expand/collapse).
- Right Click: Toggle Expansion (Same as Dbl Click).
- Middle Click: Collapse All (Emit new signal
collapse_all_requested). - Long Press: Implement Navigation (Switch Central).
- Add
_processcheck for hold duration. - Draw Progress Ring during hold.
- Trigger navigation on completion.
- Add
- Focus Mode (Godot)
- Add "Focus on this node" checkbox to settings_panel.tscn.
- Implement
focus_node_idstate in tree_renderer.gd (visual only for now). - Update
_drawto dim nodes/edges not connected tofocus_node_idwhen enabled.
- Backend Updates
- Add collapseAll handler in path_app.js.
- Visual Cleanup (Godot)
- Tree Renderer Update (Godot)
- In-Degree Display: Add visualization for in-degree (e.g., small badge/number).
- Last Node Button: Hide expand button for the last node in the chain (target node).
- Bezier Aesthetics:
- Implement edge filtering to avoid skip-level connections.
- Frontend UI Fixes (Electron)
- Fix In-Degree Mismatch: Investigate and correct the data source for In-Degree numbers in the details panel.
- Fix Resizing Layout: Ensure Incoming/Outgoing columns resize proportionally with the window.
- Edge Visibility: Modify renderer to hide edges by default and only show on hover/click.
- In-Degree Display Setting: Add setting to toggle between Visible/Total count (Default: Visible).
- Data Validation
- Disable Path Mode if No Data: Prevent clicking "Path Mode" button if
graphDatais empty/undefined. - Fix False Negative: Ensure
graphDatacheck correctly detects dynamically loaded data in Mini Build mode. - Inline Feedback: Replace
alert()with a text message next to the button.
- Disable Path Mode if No Data: Prevent clicking "Path Mode" button if
- Fix Godot Script Errors
- TreeRenderer Parse Error: Add
class_name TreeRendererto tree_renderer.gd or fix syntax error causing parse failure.
- TreeRenderer Parse Error: Add
- Fix Tree View Interactions
- Fix Right-Click Toggle: Ensure right-click (and double-click) correctly toggles between Expand and Collapse based on current state.
- Fix Collapse All:
- Debug Middle Click binding.
- Add visible "Collapse All" button to UI.
- Fix Regression Errors:
- Restore
_is_pressedandcollapse_all_requestedin tree_renderer.gd.
- Restore
- Verification
- Verify "Expand" button appears for nodes with hidden parents.
- Verify clicking "Expand" reveals "Fair Value" or similar missing nodes.
- Core Algorithm Implementation (path_core.js)
- Data Structure: Implement
Spineidentification (Main Path). - Slot Manager: Create
Y-Axis Allocatorto manage vertical slots per X-column. - Layout Logic:
- Place Spine nodes at
Y=0. - Place Tributaries (Prerequisites) laterally using "Preceding Parent" priority.
- Ensure
Stationary Expansion(Expanding a node does not shift the Spine).
- Place Spine nodes at
- Data Structure: Implement
- Frontend Integration
- Verify
switchCentertriggers correct layout recalculation. - Test with complex graphs to ensure no overlapping nodes.
- Verify
- 关键 Bug 修复 (Critical Bug Fix)
- 修复导航失败: 树状视图在切换中心时默认为线性模式。确保在
switchCenter期间生成treeLayout。
- 修复导航失败: 树状视图在切换中心时默认为线性模式。确保在
- 数据一致性 (前端)
- 确保在有效负载中正确计算并传递
inDegree。- 确保在有效负载中正确计算并传递
inDegree。 - Godot: 实现懒加载可视化
- 后端: 更新 path_core.js 以允许
forcedExpansionSet的无限制上下文扩展。 - 前端桥接: 更新 path_app.js 以处理
forcedExpansionNodes并传递给 Worker。 - 简化懒加载 UI (Godot)
- 更新 tree_renderer.gd:
- 移除单独的 (+)/(-) 按钮。
- 实现统一的
[ 计数 ]按钮(带数字的圆圈)。 - 按钮切换
forcedExpansion状态。 - 默认状态为折叠。
- 确保 path_app.js 正确处理切换(重用现有逻辑)。
- Godot 渲染器: 更新 tree_renderer.gd 以计算可见入度并显示 (+)/(-) 按钮。
- Godot 信号: 通过
tree_view_panel、path_mode_ui将 expand/collapse 信号连接到ws_client。- (Godot) 实现逻辑以验证
可见 < 全局入度以显示 (+)。
- (Godot) 实现逻辑以验证
- 确保在有效负载中正确计算并传递
- 确保在有效负载中正确计算并传递
- 树状视图视觉与交互重修
- 视觉清理 (Godot)
- 从 tree_renderer.gd 中移除 (+)/(-) 和
[Count]按钮。 - 移除这些按钮的单独点击区域。
- 从 tree_renderer.gd 中移除 (+)/(-) 和
- 交互更新 (Godot)
- 双击: 更改为切换扩展(发射 expand/collapse)。
- 右键单击: 切换扩展(与双击相同)。
- 中键单击: 全部折叠(发射新信号
collapse_all_requested)。 - 长按: 实现导航(切换中心)。
- 添加
_process检查保持持续时间。 - 在保持期间绘制进度环。
- 完成时触发导航。
- 添加
- 专注模式 (Godot)
- 向 settings_panel.tscn 添加“聚焦于此节点”复选框。
- 在 tree_renderer.gd 中实现
focus_node_id状态(目前仅视觉)。 - 更新
_draw以在启用时调暗未连接到focus_node_id的节点/边缘。
- 后端更新
- 在 path_app.js 中添加 collapseAll 处理程序。
- 视觉清理 (Godot)
- 树渲染器更新 (Godot)
- 入度显示: 添加入度可视化(例如,小徽章/数字)。
- 最后一个节点按钮: 隐藏链中最后一个节点(目标节点)的展开按钮。
- 贝塞尔美学:
- 实现边缘过滤以避免跳级连接。
- 前端 UI 修复 (Electron)
- 修复入度不匹配: 调查并更正详细信息面板中入度数字的数据源。
- 修复布局调整大小: 确保传入/传出列随窗口按比例调整大小。
- 边缘可见性: 修改渲染器以默认隐藏边缘,仅在悬停/点击时显示。
- 入度显示设置: 添加设置以在可见/总数之间切换(默认:可见)。
- 数据验证
- 这也是如果无数据则禁用路径模式: 如果
graphData为空/未定义,防止点击“路径模式”按钮。 - 修复误报: 确保
graphData检查正确检测 Mini Build 模式下的动态加载数据。 - 内联反馈: 用按钮旁边的文本消息替换
alert()。
- 这也是如果无数据则禁用路径模式: 如果
- 修复 Godot 脚本错误
- TreeRenderer 解析错误: 向 tree_renderer.gd 添加
class_name TreeRenderer或修复导致解析失败的语法错误。
- TreeRenderer 解析错误: 向 tree_renderer.gd 添加
- 修复树状视图交互
- 修复右键切换: 确保右键单击(和双击)根据当前状态正确在展开和折叠之间切换。
- 修复全部折叠:
- 调试中键绑定。
- 向 UI 添加可见的“全部折叠”按钮。
- 修复回归错误:
- 恢复 tree_renderer.gd 中的
_is_pressed和collapse_all_requested。
- 恢复 tree_renderer.gd 中的
- 验证
- 验证“展开”按钮是否出现在具有隐藏父节点的节点上。
- 验证点击“展开”是否显示“公允价值”或类似的缺失节点。
- 核心算法实施 (path_core.js)
- 数据结构: 实现
Spine识别(主路径)。 - 插槽管理器: 创建
Y轴分配器以管理每个 X 列的垂直插槽。 - 布局逻辑:
- 将主干节点放置在
Y=0。 - 使用“先前父节点”优先级横向放置支流(前置节点)。
- 确保
静态展开(展开节点不移动主干)。
- 将主干节点放置在
- 数据结构: 实现
- 前端集成
- 验证
switchCenter触发正确的重新布局计算。 - 使用复杂图表测试以确保没有节点重叠。
- 验证
- Core Algorithm: Ownership System (path_core.js)
- Step 1: Add
expansionOrderparameter togetTreeLayout() - Step 2: Add
currentOwner,ownerPriority,_isOnSpineto layout nodes - Step 3: Implement
tryClaim()with 9 rules - Step 4: Implement
determineVisibility()+isOwnerChainVisible() - Step 5: Filter edges by ownership (Rule 5)
- Step 6: Group hulls by ownership
- Step 1: Add
- Frontend Bridge (path_app.js)
- Step 7: Convert
forcedExpansionNodesSet →expansionOrderArray - Step 8: Add
stickyClaimEnabledsetting
- Step 7: Convert
- Godot Renderer (tree_renderer.gd)
- Step 9: Edge filtering by
currentOwner - Step 10: Hull collision avoidance
- Step 11: Node type coloring (spine/tributary/shared/migrated)
- Step 12: Expansion indicator badge
- Step 9: Edge filtering by
- Worker (path_worker.js)
- Step 13: Pass
expansionOrder+stickyClaimEnabledtogetTreeLayout()
- Step 13: Pass
- Verification
- Test Rule 2 (Preceding Immunity)
- Test Rule 3 (Following Migration)
- Test Rule 6 (Spine Always Visible)
- Test Rule 7 (Sticky Claim toggle)
- Test hull-node collision avoidance
- 核心算法:所有权系统 (path_core.js)
- 步骤 1: 向
getTreeLayout()添加expansionOrder参数 - 步骤 2: 向布局节点添加
currentOwner,ownerPriority,_isOnSpine - 步骤 3: 实现包含 9 条规则的
tryClaim() - 步骤 4: 实现
determineVisibility()+isOwnerChainVisible() - 步骤 5: 按所有权过滤边(规则 5)
- 步骤 6: 按所有权分组 hull
- 步骤 1: 向
- 前端桥接 (path_app.js)
- 步骤 7: 将
forcedExpansionNodesSet 转为expansionOrderArray - 步骤 8: 添加
stickyClaimEnabled设置
- 步骤 7: 将
- Godot 渲染器 (tree_renderer.gd)
- 步骤 9: 按
currentOwner过滤边 - 步骤 10: Hull 碰撞避让
- 步骤 11: 节点类型着色(脊柱/支流/共享/迁移)
- 步骤 12: 展开指示器徽章
- 步骤 9: 按
- Worker (path_worker.js)
- 步骤 13: 传递
expansionOrder+stickyClaimEnabled
- 步骤 13: 传递
- 验证
- 测试规则 2(前置免疫)
- 测试规则 3(后续迁移)
- 测试规则 6(脊柱始终可见)
- 测试规则 7(粘性认领开关)
- 测试 hull-节点碰撞避让
- Duplicate legacy basename identities now fail before graph construction;
RawFile.relativePathis recorded with POSIX separators for future stablesourceUrimigration. - Sidecar and HTTP authorization now share one strict token decision while preserving
Authorization: BearerandX-NoteConnection-Token. - File-backed graph snapshots use unique sibling temp files and refresh the in-process cache only after atomic rename.
- The full code-vs-plan and reference comparison is recorded in
docs/solutions/architecture-hardening-forward-compatibility-2026-08-16.md. -
mobile-slimnow provides deterministic slim staging, PNG-first materialization, and callable bounded local exact ingest/query projection without a sidecar. - [~] Signed APK/AAB extraction and real-device RSS gates remain open; SQLite/WASM persistence is intentionally not claimed by this slice.
- Complete
sourceUrimigration beyond the shipped additive dual-read foundation, then finish route-registry shadow parity, indexed exact/inferred projections, and Bridge capability negotiation before changing public IDs or default routing.
- Existing
NoteNode.id, layouts, route paths,assistantMessage, and snapshot schemas remain readable. - Mobile-low (4-core ARM64, 5,000 docs / 50,000 atoms) stays within 25 MiB app-owned compressed assets and 256 MiB peak RSS; standard mobile uses 35 MiB / 384 MiB for 20,000 docs / 200,000 atoms.
- Local mobile analysis works without Node/Godot/model dependencies; remote inference is optional, cancellable, timeout-bounded, and explainably unavailable offline.
- Every future identity, registry, graph, and Bridge migration has replay/rollback evidence before a default switch.
- 重复 legacy basename 会在建图前失败;
RawFile.relativePath使用/记录,为后续稳定sourceUri迁移提供输入。 - Sidecar 与 HTTP 共用严格 token 判定,同时兼容
Authorization: Bearer与X-NoteConnection-Token。 - 文件图快照使用唯一同目录临时文件,并仅在原子 rename 成功后刷新进程内缓存。
- 完整代码/方案/参考仓库对账已落盘于
docs/solutions/architecture-hardening-forward-compatibility-2026-08-16.md。 -
mobile-slim现在具备 deterministic slim staging、PNG-first materialization,以及不依赖 sidecar 的可调用有界本地 exact ingest/query projection。 - [~] 签名 APK/AAB 解包与真机 RSS 门禁仍未完成;本切片有意不宣称 SQLite/WASM 持久化。
- 在改变公开 ID 或默认路由前,完成稳定
sourceUri双读迁移、route-registry shadow parity、indexed exact/inferred projection 与 Bridge capability negotiation。
- 既有
NoteNode.id、布局、route path、assistantMessage与 snapshot schema 继续可读。 - mobile-low(4 核 ARM64、5,000 docs / 50,000 atoms)应用自有压缩资产不超过 25 MiB、峰值 RSS 不超过 256 MiB;standard mobile 对应 35 MiB / 384 MiB、20,000 docs / 200,000 atoms。
- 移动端无需 Node/Godot/模型依赖即可完成本地分析;远端推理仅作为可取消、带 timeout、离线可解释降级的可选能力。
- 后续 identity、registry、graph、Bridge 迁移必须先有 replay/rollback 证据再切默认。
- Generate versioned portable
sourceUri, deterministicsha256revision, and legacy/relative aliases at theFileLoaderboundary. - Reject NUL/traversal paths and case-folded basename collisions before graph construction.
- Add
NoteNodeidentity metadata as optional fields so old graph snapshots remain valid. - Resolve current IDs, source URIs, relative paths, and legacy aliases through one
Graphregistry; reject alias collisions before mutation. - Preserve old layouts and add URI/relative-path layout and frontmatter dual-read in
GraphBuilder. - Verify with four focused suites (15 tests) and strict TypeScript compilation.
- Do not switch public
NoteNode.iduntil move/rename replay and cross-platform corpus evidence exist. - Complete route-registry shadow parity, indexed explicit/inferred projections, Bridge capability negotiation, and signed device RSS/APK gates.
- 在
FileLoader边界生成版本化可移植sourceUri、确定性sha256revision 以及 legacy/relative alias。 - 在建图前拒绝 NUL/路径穿越和大小写折叠后的 basename 冲突。
- 为
NoteNode增加可选身份字段,保持旧 graph snapshot 可读。 - 通过单一
Graphregistry 解析当前 ID、source URI、relative path 和 legacy alias;写入前拒绝 alias 冲突。 - 保留旧布局,并在
GraphBuilder增加 URI/relative-path 布局与 frontmatter 双读。 - 四个聚焦 suite 共 15 个测试及严格 TypeScript 编译通过。
- 在获得文件移动/重命名 replay 和跨平台语料证据前,不切换公开
NoteNode.id。 - 完成 route-registry shadow parity、indexed explicit/inferred projection、Bridge capability negotiation 以及真机签名 RSS/APK 门禁。
-
mobile-slimnow exposes local ingest, local exact query, optional remote inference, SVG suppression, and explicit asset/RSS budgets throughPlatformCapabilities. -
mobile_exact_analyzer.jsprovides bounded exact lookup, bidirectional neighbor inspection, and directed shortest-path queries without retaining document bodies;storage_provider.jsexposesqueryKnowledgeBaseExact()andfindKnowledgePath(). -
prepare-mobile-slim.jsstages one deterministic frontend directory and emits a manifest;verify-mobile-slim-budget.jsrejects forbidden artifacts and compressed payload/RSS overages. - Capacitor and Tauri Android consume the same staged directory. Tauri Android no longer builds a sidecar by default, and Godot Pathmode is explicit opt-in.
- Focused mobile/platform matrix: 51 tests passed; current staged build measured 119 files, 4,242,970 uncompressed bytes, and 1,543,913 estimated compressed bytes.
- Real-device RSS evidence and signed APK/AAB extraction evidence remain open.
not-measuredis a deliberate state, not a pass. - SQLite persistence, full agent conversation parity, complete
sourceUrimigration beyond additive dual-read, strict route-registry default, and domain extraction remain pending; versioned mobile projection and optional Bridge host adapter execution are delivered, while real cross-host replay remains open.
-
mobile-slim现在通过PlatformCapabilities暴露本地 ingest、本地 exact query、可选远程推理、SVG 抑制以及明确的资源/RSS 预算。 -
mobile_exact_analyzer.js提供有界 exact lookup、双向邻居查询和有向最短路径,不保留文档正文;storage_provider.js暴露queryKnowledgeBaseExact()与findKnowledgePath()。 -
prepare-mobile-slim.js生成唯一 deterministic frontend staging 目录和 manifest;verify-mobile-slim-budget.js会拒绝禁入物及压缩 payload/RSS 超预算。 - Capacitor 与 Tauri Android 消费同一 staging 目录。Tauri Android 默认不再构建 sidecar,Godot Pathmode 改为显式 opt-in。
- 移动/平台定向矩阵通过 51 个测试;本机 staging 测得 119 个文件、未压缩 4,242,970 字节、估算压缩 1,543,913 字节。
- 真机 RSS 证据和签名 APK/AAB 解包证据仍未完成。
not-measured是诚实的未测状态,不是通过状态。 - SQLite 持久化、完整 agent conversation parity、strict route-registry 默认切换、indexed explicit/inferred projection 与 domain 抽取仍待后续阶段;Bridge 2.0 transport contract 已交付。
-
FileLoader.loadFiles()accepts an explicit workspace root; the target/data sync andNoteConnectionpass the configured root so full-workspace and subdirectory builds emit the same relative path andsourceUri. Legacy callers that omit the root remain compatibility-only and are not migration evidence. - Learning ingest accepts additive
sourceUri,revision, andidentityAliases; snapshots retain them and deletes can resolve by URI/alias without changing legacydocumentIdbehavior. - Server and modular data sync propagate identity metadata from the filesystem boundary instead of rebuilding IDs from lossy basename/path normalization.
- Android graph builds reject corpora above 5,000 documents, 16 MiB per document, 64 MiB total input, or 250,000 edges before low-memory projection is persisted; link candidates are extracted at read time so the intermediate projection does not retain document bodies.
- URI-derived identity remains workspace-scoped, while explicit move/rename journal replay now preserves the legacy ID and historical aliases. Old-snapshot, collision, rollback, and cross-root corpus fixtures are still required before canonical-ID cutover.
- Android folder picking, signed APK/AAB extraction, and device RSS remain unverified;
not-measuredmust remain visible until evidence exists. - SQLite persistence, route-registry shadow parity, complete
sourceUrimigration and domain extraction remain separate milestones;版本化 mobile projection 与可选 Bridge host adapter 执行已交付,但真实跨 host replay 仍待完成。
- Added
NOTE_CONNECTION_ROUTE_DISPATCH_MODE=legacy|registry; registry remains the default and diagnostics expose the active mode. - Added
verify:route:shadow: 14 legacy-equivalent probes compare status, body, headers, and persistence side effects; 6 registry-only probes verify expected legacy misses and registry hits. - Restored compatibility fields for modular settings/config routes and legacy error contracts for knowledge, Markdown, render, and clipboard boundaries.
- Added
verify-mobile-artifact.jsfor APK/AAB central-directory inspection, arm64 payload detection, forbidden runtime detection, profile budgets, and release RSS evidence.--require-rss --require-arm64rejects incomplete release evidence. - Added SQLite close/reopen replay coverage and atomic graph rollback coverage.
- G1 passes locally:
npm run verify:route:shadowreportsequivalent=14 registryOnly=6. - G3 local adapter replay passes; this does not prove Web/Tauri/Capacitor/Android cross-host replay.
- [~] G2 still needs a fresh arm64 APK/AAB and device RSS JSON; static staging size is not an artifact or device-memory measurement.
- G4 still requires a recorded old-snapshot/collision/rollback/cross-root corpus before any public canonical-ID cutover.
- 增加
NOTE_CONNECTION_ROUTE_DISPATCH_MODE=legacy|registry;默认仍为 registry,diagnostics 暴露实际模式。 - 增加
verify:route:shadow:14 条 legacy-equivalent probe 对比状态、body、headers 与持久化副作用;6 条 registry-only probe 验证 legacy miss 与 registry hit 预期。 - 为模块化 settings/config 路由恢复兼容字段,并统一 knowledge、Markdown、render、clipboard 边界的旧错误契约。
- 增加
verify-mobile-artifact.js,执行 APK/AAB 中央目录检查、arm64 payload 检测、禁入运行时检测、profile 预算和 release RSS 证据校验;--require-rss --require-arm64会拒绝不完整的 release evidence。 - 增加 SQLite close/reopen replay 覆盖和 graph 原子回滚覆盖。
- G1 已在本机通过:
npm run verify:route:shadow输出equivalent=14 registryOnly=6。 - G3 本机 adapter replay 已通过;这不等于 Web/Tauri/Capacitor/Android 跨 host replay 已证明。
- [~] G2 仍需要新鲜 arm64 APK/AAB 与真机 RSS JSON;静态 staging 大小不是真实产物或设备内存测量。
- G4 仍需记录 old-snapshot/collision/rollback/cross-root corpus,之后才能切换公开 canonical ID。
-
Graph.fromJSON()andGraph.restore()now validate nodes/edges before atomic replay; legacy snapshots without identity fields remain readable. - Learning ingest accepts an explicit
move/renameoperation, persists a bounded identity journal, preserves old aliases, and keeps the legacydocumentIdstable. - Modular
/api/knowledge/ingestnow applies a bounded edge normalizer (JSON, document/alias/content limits, legacy field aliases, and move operations) instead of passing arbitrary JSON into the domain. - Sequential keyword matching uses an inverted anchor index; exact matching semantics remain unchanged while the normal path avoids the previous O(V^2) pair scan.
- Mobile exact projection now carries
sourceUri/revision/aliases, resolves URI references, uses NFC normalization, and reports explicit/inferred/runtime edge counts without retaining document bodies. - PathBridge advertises protocol
2.0, capabilities, request/correlation IDs, analysis request types, and cancellation as additive envelopes; existing clients remain valid. - Registry response/status shadow parity, real Android APK/RSS evidence, SQLite persistence, and canonical public-ID cutover remain blocked by evidence gates.
-
Graph.fromJSON()与Graph.restore()在原子回放前校验 nodes/edges;不含身份字段的旧快照继续可读。 - learning ingest 支持显式
move/rename操作,持久化有界 identity journal,保留旧 alias,并保持旧documentId不变。 - 模块化
/api/knowledge/ingest现在经过有界边界规范化(JSON、文档/alias/正文上限、旧字段别名与 move),不再把任意 JSON 直接交给 domain。 - 顺序 keyword matching 使用倒排锚点索引;exact 语义不变,正常路径避免原先 O(V^2) 全对扫描。
- mobile exact projection 携带
sourceUri/revision/alias,可解析 URI,统一 NFC,并报告 explicit/inferred/runtime 边统计,不保留文档正文。 - PathBridge 以 additive envelope 宣布 protocol
2.0、capability、request/correlation ID、分析请求类型与取消语义;旧客户端仍可用。 - registry response/status shadow parity、真机 APK/RSS 证据、SQLite 持久化和 canonical 公共 ID 切换仍受证据门禁约束。
-
FileLoader.loadFiles()接受显式 workspace root;全库与子目录构建现在生成一致的 relative path 与sourceUri。 - 学习摄入契约接受 additive
sourceUri、revision、identityAliases;快照保留这些字段,删除操作可按 URI/alias 解析,同时不改变旧documentId行为。 - Server 与 modular data sync 从文件系统边界直接传播身份元数据,不再依赖有损 basename/path 归一化重新推导 ID。
- Android 建图在低内存 projection 持久化前拒绝超过 5,000 文档、单文档 16 MiB、总输入 64 MiB 或 250,000 条边的语料;读取时先提取 link candidate,中间 projection 不保留正文。
- URI 派生身份仍是 workspace-scoped;显式 move/rename journal replay 已保留旧 document ID 与历史 alias。切换 canonical ID 前仍必须完成旧 snapshot、collision、rollback 与跨 root 语料测试。
- Android 文件夹选择、签名 APK/AAB 解包和真机 RSS 仍未验证;在获得证据前必须保留
not-measured状态。 - SQLite 持久化、route-registry shadow parity、完整
sourceUri迁移与 domain 抽取仍是独立里程碑;版本化 mobile projection 与可选 Bridge host adapter 执行已交付,真实跨 host replay 仍待完成。
- Added
src/frontend/knowledge_projection_contract.js: schema1, body-free nodes,sourceUri,revision, aliases, edge kind/provenance, bounded evidence references, and bounded adjacency (64 neighbors per direction). - Capacitor graph writes normalize through the contract before
graph_data.json/data.js; the exact analyzer rejects unknown projection versions and preserves local exact query/path limits. - Tauri Rust graph output now emits the same versioned projection metadata and identity fields without retaining Android document bodies; Rust runtime tests cover replayable identity fields and adjacency.
- Added
PathBridgeHostAdapter: host-owned execution foranalyze,query,readEvidence, andexportBundle; correlation IDs, timeout, disconnect cleanup,AbortSignal, and explicit cancel propagation are covered by WebSocket tests. Without an adapter, legacy broadcast behavior remains unchanged. - Fresh slim staging: 120 files, 4,251,345 uncompressed bytes, 1,545,813 estimated compressed bytes; no Godot, desktop sidecar, model, SVG, or forbidden binary payloads.
- A signed arm64 APK/AAB extracted from a fresh build and a physical-device RSS JSON under 256 MiB are still required.
not-measuredis not release evidence. - Android folder selection/import is implemented through an additive Storage Access Framework adapter; device replay evidence is still pending.
- Cross-host projection replay (Web/Tauri/Capacitor/Android), old-snapshot corpus, move/rename corpus, and canonical public-ID migration remain blocked until identity and persistence evidence is complete.
- Added
knowledge_projection_store.jswith persistent/read-through and memory adapters; mobile exact analysis now reads through the store rather than parsing a host asset directly. - Added fixture replay for Web/Tauri/Capacitor/Android covering schema, metadata, exact search, neighbors, and directed paths; unknown schemas fail closed.
- Made Tauri projection writes atomic with sibling temp files and rename, including Windows replacement handling.
- Added Android SAF tree selection, persisted URI permission, bounded streaming copy into app-local
Knowledge_Base, and additive request/poll IPC commands. - Added identity corpus cases for same-content documents, move/rename aliases, and NFC collisions; public IDs remain compatibility keys.
- [~] G2 is partially evidenced: a fresh arm64 slim build produced an unsigned APK (9,555,787 bytes) and AAB (7,179,228 bytes); artifact verification measured 9,433,678 and 6,978,122 compressed payload bytes, with only
arm64-v8a/libnpm_lib.soand no Godot/sidecar/model/SVG entries. Signed artifacts, device import/query workload, and RSS JSON remain open. Kotlin compilation now succeeds with the available Android toolchain. - [~] G3 fixture replay passes, but Android storage replay and SQLite/WASM promotion remain pending.
- G4 canonical-ID cutover remains blocked by old-snapshot rollback and move-journal restart evidence.
-
mobile:prepare:slimnow stages 120 files (4,251,345 uncompressed bytes; 1,545,813 estimated compressed bytes) under the 25 MiB asset budget. -
tauri:android:buildcompletes for arm64 after clearing stale generated outputs; ZIP inspection and the mobile artifact verifier both pass. - Do not promote this to release acceptance until the unsigned artifacts are signed, installed on a representative device, exercised through SAF import plus exact query/path, and accompanied by peak RSS evidence under 256 MiB.
- 新增
knowledge_projection_store.js,提供 persistent/read-through 与 memory adapter;移动 exact analysis 经 store 读取,不再直接解析 host asset。 - 新增 Web/Tauri/Capacitor/Android fixture replay,覆盖 schema、metadata、exact search、neighbor 与 directed path;未知 schema fail closed。
- Tauri projection 写入改为同目录临时文件 + rename,并处理 Windows 替换语义。
- 增加 Android SAF tree 选择、持久化 URI 权限、有界流式复制到 app-local
Knowledge_Base,以及 additive request/poll IPC。 - 增加同内容文档、move/rename alias、NFC collision identity corpus;public ID 仍是兼容 key。
- [~] G2 已有部分证据:新鲜未签名 arm64 APK/AAB 已通过 ZIP 检查与 25 MiB payload budget(APK 9,433,678;AAB 6,978,122 压缩字节),仅含
arm64-v8a/libnpm_lib.so且无 Godot/sidecar/model/SVG。签名产物、真机导入/query workload 与 RSS JSON 仍缺失;当前 Android 工具链 Kotlin 编译已通过。 - [~] G3 fixture replay 已通过,但 Android storage replay 与 SQLite/WASM 提升仍待完成。
- G4 canonical-ID 切换仍被旧 snapshot rollback 与 move-journal 重启证据阻塞。
- 新增
src/frontend/knowledge_projection_contract.js:schema1、无正文节点、sourceUri、revision、alias、边 kind/provenance、有界 evidence reference,以及每个方向最多 64 个邻接。 - Capacitor 在写入
graph_data.json/data.js前统一归一化;exact analyzer 拒绝未知 projection 版本,并继续执行本地 exact query/path 上限。 - Tauri Rust 图输出改为同一版本化 projection 元数据与身份字段;Android 仍不保留正文,Rust 测试覆盖可 replay 的身份字段和 adjacency。
- 新增
PathBridgeHostAdapter:analyze、query、readEvidence、exportBundle由 host 执行;correlation ID、超时、断连清理、AbortSignal与显式 cancel 传播均有 WebSocket 测试。未配置 adapter 时保持旧广播行为。 - 最新 slim staging:120 个文件、未压缩 4,251,345 字节、估算压缩 1,545,813 字节;不含 Godot、桌面 sidecar、模型、SVG 或禁用二进制。
- 仍需新鲜构建的签名 arm64 APK/AAB 解包结果和低于 256 MiB 的真机 RSS JSON;
not-measured不是 release 证据。 - Tauri Android 已实现 Storage Access Framework 文件夹选择/导入:Markdown 在单文档 16 MiB、总输入 64 MiB、5,000 文档和深度 64 限制内流式复制到 app-local
Knowledge_Base,失败时保留旧知识库。 - Web/Tauri/Capacitor/Android 跨 host projection replay、旧 snapshot、move/rename 语料与 canonical 公共 ID 迁移,在身份和持久化证据完成前继续冻结。
- Android SAF import now persists an internal v1 journal, recovers interrupted staging/backup activation on activity startup, and atomically writes result markers.
- Contract suites, TypeScript no-emit, and arm64 Kotlin compilation pass.
- [~] G2 remains static-only: unsigned slim payload passes, but no signing keystore, online device, AVD, or RSS JSON is available.
- [~] G3 has code-level recovery and fixture replay; real Android process death, storage failure, and permission failure evidence remain open.
- G4 public-ID migration remains frozen until identity/edge parity and old snapshot, move/rename, collision, rollback, and alias-continuity corpora pass.
- Android SAF 导入现在持久化内部 v1 journal,在 activity 启动时恢复中断的 staging/backup 激活,并原子写入 result marker。
- 契约测试、TypeScript no-emit 与 arm64 Kotlin 编译已通过。
- [~] G2 仍为静态证据:未签名 slim payload 通过,但当前没有签名 keystore、在线设备、AVD 或 RSS JSON。
- [~] G3 已有代码级恢复与 fixture replay;真实 Android 进程死亡、存储失败与权限失败证据仍未完成。
- G4 公共 ID 迁移继续冻结,直到 identity/edge parity 与旧 snapshot、move/rename、collision、rollback、alias continuity 语料全部通过。
- Signed arm64 device workload and peak RSS evidence / 签名 arm64 真机 workload 与 peak RSS 证据。
- Native Tauri/Capacitor/Android adapter replay / 原生 Tauri/Capacitor/Android adapter replay。
- Android body-free draft proof and transient RSS measurement before any budget increase / 提高预算前证明 Android draft 无正文并测量瞬时 RSS。
- Add APK/AAB signature verification to the release artifact gate; unsigned output is no longer release evidence.
- Add a fail-closed Tauri Android recorder for signed arm64 install, SAF/import/query/path workload, force-stop/reopen continuity, and
/proc/<pid>/status:VmRSScapture. - Keep the workload declarative (
adbArgs) and record artifact hash, masked device, step results, peak RSS, standalone RSS JSON, and logcat. - [~] No signing keystore, online device/AVD, or workload execution is available on this host; G2/G3 remain open.
- Run the harness on low-memory arm64 hardware, then complete native adapter and identity-corpus replay before public-ID or SQLite/WASM promotion.
- Projection replay now uses independent Web, Tauri, Capacitor, and Android host-boundary adapters and labels the report as contract evidence.
- Added additive
canonicalIdmetadata and duplicate-canonical collision rejection while preserving legacy public IDs and layouts. - Expanded route shadow to 17 equivalent probes; malformed JSON and invalid build modes now have matching status/body/header behavior before mutation.
- Added same-content, NFC/case, cross-root, legacy-snapshot, and graph-rollback corpus coverage; Android graph reads are capped before full string allocation.
- [~] Signed device SAF/query/path, process-death continuity, and RSS evidence remain unavailable on this host.
- Keep public-ID and SQLite/WASM default switches frozen until native evidence is recorded.
- Projection replay 改用独立的 Web、Tauri、Capacitor、Android host-boundary adapter,并在报告中标记为 contract evidence。
- 增加 additive
canonicalId与重复 canonical collision 拒绝,同时保留 legacy 公共 ID 与旧 layout。 - route shadow 扩展为 17 条等价 probe;malformed JSON 与非法 build mode 在变更状态前具有一致的 status/body/header 行为。
- 增加同内容、NFC/大小写、跨 root、legacy snapshot 与 graph rollback 语料;Android graph read 在完整字符串分配前受上限约束。
- [~] 当前宿主仍无法提供签名真机 SAF/query/path、进程死亡 continuity 与 RSS 证据。
- 在原生证据记录前继续冻结 public-ID 与 SQLite/WASM 默认开关。
- Propagated additive
canonicalIdthrough TypeScript identity, desktop graph construction, browser identity, Capacitor projection, and Android Rust projection. - Preserved legacy IDs, schema-1 snapshots, layouts, and exact lookup behavior.
- [~] Canonical node/edge semantic parity across Rust and Capacitor is not yet proven; raw JSON equality is not a sufficient oracle.
- Rebuilt slim staging after this source change: 121 files / 4,265,579 uncompressed bytes / 1,549,039 estimated compressed bytes; RSS remains
not measured.
- 将 additive
canonicalId传播到 TypeScript identity、桌面 graph 构建、浏览器 identity、Capacitor projection 与 Android Rust projection。 - 保留 legacy ID、schema-1 snapshot、layout 与 exact lookup 行为。
- [~] Rust 与 Capacitor 的 canonical node/edge 语义 parity 尚未证明;raw JSON 相等不是充分 oracle。
- 本轮源码变更后已重建 slim staging:121 个文件 / 未压缩 4,265,579 字节 / 估算压缩 1,549,039 字节;RSS 仍为
not measured。
- Added a test-only semantic comparator keyed by canonical identity and provenance-aware directed edges; duplicate semantic identities fail closed.
- Aligned Capacitor and Rust direct-path, source-relative, and unique-stem resolution; worker and single-thread Capacitor builders now share the same sourceUri fallback.
- Added nested/relative/Markdown/NFC corpus replay through Capacitor plus an ignored Rust Cargo probe; semantic result is 6 nodes / 4 edges with no mismatch.
- Excluded the comparator from mobile-slim staging; current staging is 121 files / 4,274,600 uncompressed / 1,550,561 estimated compressed bytes, SHA-256
c62d4eec6b1b66d66466b74f1b24ddb49d0c004795a16366f9018337c417baf8. - [~] Signed arm64 device SAF/query/path, force-stop continuity, and RSS
<= 256 MiBremain unproven; public-ID and SQLite/WASM promotion stay frozen.
- 新增仅用于测试的 semantic comparator,按 canonical identity 与保留 provenance 的有向边比较;重复语义 identity 直接 fail closed。
- 对齐 Capacitor 与 Rust 的 direct-path、source-relative、unique-stem resolution;worker 与 single-thread Capacitor builder 共用 sourceUri fallback。
- 通过 Capacitor 与 ignored Rust Cargo probe 回放 nested/relative/Markdown/NFC 语料;语义结果为 6 个节点 / 4 条边且无 mismatch。
- comparator 已排除出 mobile-slim staging;当前 staging 为 121 个文件 / 未压缩 4,274,600 / 估算压缩 1,550,561 字节,SHA-256 为
c62d4eec6b1b66d66466b74f1b24ddb49d0c004795a16366f9018337c417baf8。 - [~] 签名 arm64 真机 SAF/query/path、force-stop continuity 与 RSS
<= 256 MiB仍未证明;public-ID 与 SQLite/WASM 提升继续冻结。
- Added
scripts/verify-mobile-native-recovery.jsas a dependency-free host verifier for the Kotlin import journal contract. It replays active-target precedence, previous-tree restoration, orphan-backup recovery, unsafe path rejection, and unknown-schema rejection. - Added
src/mobile.native.recovery.contract.test.tsandverify:mobile:native-recovery; the report is schema1, carriesevidenceLevel: host-recovery-state-machine, and explicitly setsnativeDeviceEvidence: false. - Verified six deterministic recovery scenarios. The verifier mirrors the production journal phases but is not the Android process, SAF UI, storage-failure, permission-failure, or RSS evidence path.
- Current post-change gates: full Jest
146suites /1,271passed /26skipped; TypeScript no-emit; Rust28passed /1ignored; projection replay4hosts /6nodes /4edges; mobile-slim121files /4,275,083uncompressed /1,550,638estimated compressed bytes; SHA-2565d5bafa20770bf42531b2e39ec62364537e0eade83b29a9aa2209f4f03bf7c38. - [~] G2/G3 still require a signed arm64 device workload, SAF import/query/path, force-stop/reopen continuity, storage and permission failure cases, and RSS
<= 256 MiB; G4 public-ID and SQLite/WASM promotion remain frozen.
Keep recovery verification as a test-only host mirror of the Kotlin journal state machine. This gives deterministic CI coverage without adding JavaScript to the mobile runtime, while the explicit evidence level prevents host replay from being mistaken for native process-death acceptance. Any journal schema or phase change must update the Kotlin implementation, this verifier, and its bilingual evidence record together.
- 新增
scripts/verify-mobile-native-recovery.js,作为 Kotlin import journal 契约的无依赖 host verifier;回放 active target 优先、旧知识库恢复、孤儿 backup 恢复、unsafe path 拒绝与 unknown schema 拒绝。 - 新增
src/mobile.native.recovery.contract.test.ts与verify:mobile:native-recovery;报告使用 schema1,标记evidenceLevel: host-recovery-state-machine,并显式设置nativeDeviceEvidence: false。 - 六个确定性 recovery scenario 已通过。verifier 镜像生产 journal phase,但不属于 Android 进程、SAF UI、存储失败、权限失败或 RSS 证据路径。
- 本轮门禁快照:全量 Jest
146suites /1,271passed /26skipped;TypeScript no-emit;Rust28passed /1ignored;projection replay 为4hosts /6nodes /4edges;mobile-slim 为121文件 / 未压缩4,275,083/ 估算压缩1,550,638字节;SHA-256 为5d5bafa20770bf42531b2e39ec62364537e0eade83b29a9aa2209f4f03bf7c38。 - [~] G2/G3 仍需签名 arm64 真机 workload、SAF import/query/path、force-stop/reopen continuity、存储与权限失败场景及 RSS
<= 256 MiB;G4 public-ID 与 SQLite/WASM 提升继续冻结。
将 recovery verification 保持为 Kotlin journal 状态机的 test-only host mirror。它在不向移动运行时增加 JavaScript 的前提下提供确定性 CI 覆盖,同时通过显式 evidence level 防止把 host replay 误判为原生进程死亡验收。任何 journal schema 或 phase 变化都必须同步更新 Kotlin 实现、该 verifier 与双语证据记录。
- Fixed the outer Android import failure path so it always removes staging data but only clears the journal when no backup exists. A retained backup is the only known-good corpus after rollback failure and must remain available to startup recovery.
- Added a focused contract assertion scoped to the
Knowledge base import failedcatch block. It rejects the destructive cleanup sequence without rejecting legitimate cleanup in successful replacement and recovery branches. - Preserved the public Rust request/poll/result-marker contract, journal schema, mobile-slim profile, and Kotlin ownership. The change adds no runtime JavaScript or database dependency.
- [~] Retained backup/journal recovery is still code-level evidence. A signed arm64 device must exercise rollback failure, next-bind recovery, SAF/storage permission failure, force-stop continuity, and RSS
<= 256 MiBbefore G2/G3 can close.
Prefer recoverability over eager cleanup at the transaction boundary. A failed import reports failed immediately while retaining the previous corpus and journal for the next activity bind; cleanup is performed only after a target is known to be active or a journal is proven empty/unsafe. This keeps forward compatibility and low mobile footprint without hiding a data-loss path behind a generic catch block.
- 修复 Android import 外层失败路径:始终清理 staging;只有不存在 backup 时才清理 journal。回滚失败后 backup 是唯一已知可用知识库,必须留给启动恢复。
- 增加聚焦于
Knowledge base import failedcatch block 的契约断言,只禁止破坏性清理序列,不误伤成功替换与 recovery 分支中的合法清理。 - 保持 Rust request/poll/result-marker 公共契约、journal schema、mobile-slim profile 与 Kotlin owner 不变;不新增移动运行时 JavaScript 或数据库依赖。
- [~] backup/journal 保留目前仍是代码级证据。G2/G3 关闭前,签名 arm64 真机必须覆盖 rollback failure、下次 bind recovery、SAF/存储权限失败、force-stop continuity 与 RSS
<= 256 MiB。
在事务边界优先保证可恢复性,而不是急于清理。失败 import 立即报告 failed,但保留旧知识库与 journal,交由下次 activity bind 恢复;只有确认新 target 已激活,或 journal 已证明为空/不安全时才清理。这样不改变向前兼容契约与移动包体,同时消除通用 catch 中潜在的数据丢失路径。
- Closed the remaining startup-recovery loss path: when a known backup cannot be renamed to the active target, Kotlin now deletes only staging, retains backup and journal, and emits
import_recovery_pendingfor a later retry. Orphan backup rename failure emitsorphan_recovery_pendinginstead of disappearing silently. - Extended the dependency-free host mirror to 8 scenarios, including deterministic journaled/orphan backup-rename failure with retention; the report remains
nativeDeviceEvidence: false. - Generated a fresh Tauri Android release with the slim profile. Unsigned universal APK compressed payload is
9,576,838bytes and AAB is7,055,579bytes, both below the 25 MiB budget; SHA-256 values are recorded in the implementation plan and walkthrough. - [~] Signature verification, SAF workload, device/emulator process-death continuity, retry under real storage/permission faults, and RSS
<= 256 MiBremain external gates. Do not treat unsigned artifacts or host replay as release acceptance.
Recovery must be monotonic with respect to known-good data: an existing backup is never deleted solely because rename failed. Retry state is explicit and idempotent, while empty/unsafe journals remain fail-closed. This keeps the mobile runtime dependency-free and preserves the existing Rust/result-marker contract.
- 关闭启动恢复的剩余数据丢失路径:已知 backup 无法 rename 到 active target 时,Kotlin 只删除 staging,保留 backup 与 journal,并写入
import_recovery_pending等待重试;孤儿 backup rename 失败写入orphan_recovery_pending,不再静默消失。 - 无依赖 host mirror 扩展到 8 个场景,覆盖 journaled 与 orphan backup rename failure,并验证保留语义;报告继续标记
nativeDeviceEvidence: false。 - 使用 slim profile 生成新鲜 Tauri Android release。未签名 universal APK 压缩 payload 为
9,576,838字节,AAB 为7,055,579字节,均低于 25 MiB;SHA-256 已写入实现计划与 walkthrough。 - [~] 签名验证、SAF workload、设备/模拟器进程死亡 continuity、真实存储/权限故障下的重试与 RSS
<= 256 MiB仍是外部门禁。未签名产物与 host replay 不能作为 release acceptance。
恢复相对于已知可用数据必须单调:不能仅因为 rename 失败就删除已有 backup。重试状态显式且幂等;空 journal 与不安全 journal 继续 fail-closed。这样保持移动运行时无额外依赖,并维持既有 Rust/result-marker 契约。
- Re-ran the host gates after Phase 20: Android prerequisite check, TypeScript no-emit, 8-scenario native-recovery mirror, and 4-host projection replay all pass; generated reports remain ignored and the worktree stays clean.
- Inspected the available Android virtual device.
Medium_Phone_API_36.1resolves toE:\Android\avd\Medium_Phone.avd, uses Android36.1,x86_64, Play Store image, and 2 GiB RAM.adb devices -lhas no online target. - Confirmed the AVD is not arm64 evidence. The current release artifact gate requires arm64 payload plus a signed artifact; an x86_64 emulator cannot close that gate and must not be promoted by
--allow-emulator. - Confirmed no repository signing material (
.jks,.keystore,.p12) is available. Release verification therefore remains fail-closed for the unsigned APK/AAB. - [~] G2/G3 still require CI-signed arm64 APK/AAB, online arm64 hardware, the declarative SAF/import/query/path/continuity workload, storage/permission retry evidence, force-stop/reopen continuity, and peak
VmRSS <= 256 MiB.
Treat this host as a contract/build station, not a mobile release lab. Do not change the arm64 target, relax the signature gate, accept x86_64 emulator output, promote SQLite/WASM or canonical public IDs, or raise mobile budgets until a signed arm64 run archives manifest, rss.json, artifact hash, workload results, and logcat evidence. The next executable handoff is CI signing plus an approved arm64 device reservation; no additional runtime dependency is justified by the current evidence.
- Phase 20 后重新执行宿主门禁:Android prerequisite、TypeScript no-emit、8 场景 native-recovery mirror 与 4-host projection replay 均通过;生成报告被忽略,工作区保持 clean。
- 核对现有 Android 虚拟设备:
Medium_Phone_API_36.1实际解析到E:\Android\avd\Medium_Phone.avd,使用 Android36.1、x86_64、Play Store image 与 2 GiB RAM;adb devices -l当前没有 online target。 - 确认该 AVD 不能作为 arm64 证据。当前 release artifact gate 要求 arm64 payload 与签名产物;x86_64 emulator 不能关闭该门禁,不能通过
--allow-emulator晋级。 - 确认仓库没有可用签名材料(
.jks、.keystore、.p12)。因此未签名 APK/AAB 继续被 release verifier fail-closed 拒绝。 - [~] G2/G3 仍需 CI 签名 arm64 APK/AAB、在线 arm64 硬件、声明式 SAF/import/query/path/continuity workload、存储/权限重试证据、force-stop/reopen continuity 与 peak
VmRSS <= 256 MiB。
将当前宿主定位为契约/构建工作站,而不是移动 release 实验室。不改变 arm64 target、不放宽签名门禁、不接受 x86_64 emulator 结果、不提升 SQLite/WASM 或 canonical public ID,也不上调移动预算,直到签名 arm64 运行归档 manifest、rss.json、产物 hash、workload 结果与 logcat。下一项可执行交接是 CI 签名和预约获批的 arm64 设备;现有证据不支持增加任何运行时依赖。
- Added CI-only Android signing configuration. Release jobs now fail closed unless all four signing secrets are present, materialize the keystore ephemerally, require
--require-signed --require-arm64, and remove the keystore after verification. Local builds remain unsigned by default. - Corrected AAB verification semantics:
jarsigner -verify -strictexit code4is accepted only when the archive is otherwise signed and the status means an untrusted/self-signed certificate chain; unsigned or malformed archives remain rejected. - Added signing/workflow contract coverage and completed an ephemeral local signed APK/AAB smoke run. Observed compressed payloads were APK
9,576,838bytes and AAB7,140,668bytes; this is integration evidence only, not release provenance. - Reconciled the current slim profile: 121 files,
4,275,083uncompressed bytes,1,550,638estimated compressed bytes. The largest APK payload is the arm64 Rust library at roughly 7 MiB; payload size is within the 25 MiB budget but does not prove low RSS. - [~] Native acceptance remains open: no approved signing key, online arm64 device, SAF import/query/path workload, force-stop/reopen continuity, storage/permission retry evidence, or
VmRSS <= 256 MiBreport exists. - [~] The workflow calls the output universal, but current artifact inspection found only
arm64-v8anative payload. Treatuniversalas a packaging label, not ABI evidence, until each declared ABI is verified; do not expand ABI coverage merely to satisfy the name. - [~] Android has separate memory risks that must be measured independently: full-string content reads, projection JSON duplication, a 48 MiB frontend projection limit versus Rust output limits, and SAF staging/backup disk peaks. Admission limits are not RSS proof.
Keep the forward-compatible mobile boundary: body-free projection plus host-owned storage/lifecycle primitives, CI-only signing, and exact local analysis. The next implementation slice is evidence collection and budget alignment, not a new database, embedded model, or relaxed ABI/signature gate. Rename the release artifact/profile to arm64 when only arm64 is shipped, or add explicit per-ABI verification before using universal; either choice is safer than relying on a misleading label. Public-ID migration, default SQLite/WASM, Godot inclusion, and budget increases remain frozen until native evidence closes.
- 增加仅 CI 生效的 Android 签名配置:四项 signing secret 不完整时 release 直接 fail closed;keystore 仅临时落盘,校验后删除;release 强制
--require-signed --require-arm64;本地构建默认仍为 unsigned。 - 修正 AAB 验证语义:
jarsigner -verify -strict返回码4仅在归档确实已签名、但证书链不受信任/自签时接受;unsigned 或损坏归档仍拒绝。 - 增加 signing/workflow contract,并完成一次临时本地签名 APK/AAB smoke。观测到的压缩 payload 为 APK
9,576,838字节、AAB7,140,668字节;这只是集成证据,不是 release provenance。 - 对齐当前 slim profile:121 个文件、未压缩
4,275,083字节、估算压缩1,550,638字节。APK 最大项是约 7 MiB 的 arm64 Rust 库;包体低于 25 MiB 不等于 RSS 达标。 - [~] 原生验收仍未关闭:没有获批签名 key、在线 arm64 设备、SAF import/query/path workload、force-stop/reopen continuity、存储/权限重试证据或
VmRSS <= 256 MiB报告。 - [~] workflow 将产物称为 universal,但当前归档只发现
arm64-v8anative payload。在各声明 ABI 均被验证前,universal只能视为打包标签,不能视为 ABI 证据;不能为了匹配名称盲目扩大 ABI。 - [~] Android 仍有必须独立测量的内存风险:完整正文 String 读取、projection JSON 重复驻留、前端 48 MiB projection 上限与 Rust 输出限制不一致,以及 SAF staging/backup 磁盘峰值。admission limit 不能替代 RSS 证明。
保持向前兼容的移动边界:无正文 projection + host 自有存储/生命周期原语 + CI-only signing + local exact analysis。下一步应先完成证据采集与预算对齐,不增加数据库、内置模型,也不放宽 ABI/签名门禁。若当前只发布 arm64,应把 release artifact/profile 改名为 arm64;若确需 universal,则必须增加逐 ABI 验证。两者都比依赖误导性名称稳健。public-ID 迁移、默认 SQLite/WASM、Godot 打包与预算上调继续冻结,直到原生证据闭环。
- Added
config/mobile-budget.v1.jsonand a validated loader shared by slim staging, APK/AAB verification, and the generated mobile manifest. Artifact, RSS, input, graph, depth, and projection limits are now recorded under one schema version. - Added a 48 MiB serialized projection guard to the Rust Android/test path. Graph JSON,
data.js, and target cache variants fail before atomic write when the bounded projection contract is exceeded. - Reused the mobile 16 MiB bounded reader for
read_node_contenton Android and in Rust tests. Oversized content is rejected before returning a large String; desktop production behavior remains unchanged. - Changed the release workflow from the misleading
universaltarget toaarch64, added exactarm64-v8aABI verification, and publish asnoteconnection-arm64-release.apk/.aab; the existing universal commands remain explicit local opt-ins. - Added JS/Rust budget drift contracts and an oversized-content regression test. Rust host tests now cover 30 passed / 1 ignored in the current toolchain.
- [~] Native G2/G3 remains external: approved signing key, online arm64 device, SAF workload, process restart, failure retries, and measured RSS are still required.
Make budgets and artifact claims explicit at every boundary. The versioned contract is additive metadata and does not change projection schema, public IDs, or IPC fields. Failing before projection writes trades support for pathological oversized corpora for deterministic low-memory behavior; the mobile profile is intentionally bounded rather than silently allocating until WebView/native OOM.
- 增加
config/mobile-budget.v1.json与校验 loader,供 slim staging、APK/AAB verifier 与 mobile manifest 共用。artifact、RSS、input、graph、depth 与 projection 上限现在归档在同一 schema version 下。 - Rust Android/test 路径增加 48 MiB serialized projection guard。graph JSON、
data.js与 target cache 超过有界 projection contract 时在 atomic write 前失败。 -
read_node_content在 Android 与 Rust tests 复用 16 MiB bounded reader;超大正文在返回大 String 前被拒绝,桌面生产行为不变。 - release workflow 从容易误导的
universaltarget 改为aarch64,增加精确arm64-v8aABI 验证并以noteconnection-arm64-release.apk/.aab发布;现有 universal 命令继续作为显式本地 opt-in。 - 增加 JS/Rust budget drift contract 与超大正文回归测试;当前工具链 Rust host tests 为 30 passed / 1 ignored。
- [~] 原生 G2/G3 仍是外部门禁:获批签名 key、在线 arm64 设备、SAF workload、进程重启、失败重试与实测 RSS 仍需补齐。
让每个边界都显式表达预算与产物语义。版本化契约是 additive metadata,不改变 projection schema、public ID 或 IPC 字段。在 projection 写入前失败,会牺牲极端超大语料的支持范围,但换取低端设备上的确定性内存行为;移动 profile 必须有界,不能静默分配到 WebView/native OOM。
- 增加轻量
NoteConnectionMobileBudgetbrowser projection,在 storage provider 前加载,并由 contract tests 与版本化 JSON contract 对账。 - Capacitor admission 改用 UTF-8 字节计量,worker 与 single-thread 路径统一执行文档数、单文档字节、总输入字节、边数、目录深度和 serialized projection 上限。
- 增加 Capacitor
stat预检与 decoded UTF-8 兜底,超大正文在正常操作 materialize 前拒绝;目录枚举得到的所有 entry 现在都受深度限制。 - 增加 Tauri bootstrap/IPC generated-asset size guard,并强化 Android evidence harness:要求精确
arm64-v8a、可测设备 RAM 且不超过所选 profile 上限,同时记录 ABI/RAM provenance。 - 将 Android 静态打包与原生 release acceptance 分离:签名 arm64 APK/AAB 先作为 workflow artifact,只有显式 self-hosted workload 与 RSS evidence job 成功后才上传 GitHub Release。
- 当前 mobile-low staging:122 个文件、未压缩 4,283,033 bytes、估算压缩 1,552,689 bytes,content SHA-256 为
c60fe683957faf8fcf88a34b1c766740340c2cdd005bc526cc4efe13befbf77c。 - [~] 原生 G2/G3 仍是外部门禁:当前宿主没有获批 signing key 或在线获批 arm64 设备,SAF/import/query/path、force-stop/reopen continuity、重试场景与实测 RSS 尚未关闭。
WebView/Capacitor 共用一份 additive runtime budget projection,同时保留 native Rust 常量以维持运行时独立。UTF-8 字节上限与 stat-before-read 让不同 host 的移动边界采取保守一致的行为;代价是超大正文确定性拒绝,而不是尽力 ingest。静态产物检查只是必要的打包证据,release 发布必须继续等待签名真机证据。证据归档前不提升 SQLite/WASM、public-ID 迁移、Godot inclusion 或更大预算。
- Added the tiny
NoteConnectionMobileBudgetbrowser projection, loaded before the storage provider, and kept it aligned with the versioned JSON contract through contract tests. - Changed Capacitor admission accounting to UTF-8 bytes and enforced document count, per-document bytes, total input bytes, graph edges, directory depth, and serialized projection bytes in both worker and single-thread paths.
- Added a Capacitor
statpreflight plus decoded UTF-8 fallback guard so an oversized note is rejected before normal operation materializes it; every enumerated entry now obeys the depth limit. - Added Tauri bootstrap/IPC generated-asset size checks and strengthened the Android evidence harness to require exact
arm64-v8a, measurable device RAM within the selected profile ceiling, and recorded ABI/RAM provenance. - Separated static Android packaging from native release acceptance: signed arm64 APK/AAB are workflow artifacts first; GitHub Release upload occurs only after the explicit self-hosted workload and RSS evidence job succeeds.
- Rebuilt the current mobile-low staging: 122 files, 4,283,033 uncompressed bytes, 1,552,689 estimated compressed bytes, content SHA-256
c60fe683957faf8fcf88a34b1c766740340c2cdd005bc526cc4efe13befbf77c. - [~] Native G2/G3 remains external: this host still has no approved signing key or online approved arm64 device, so SAF/import/query/path, force-stop/reopen continuity, retry cases, and measured RSS are not closed.
Keep one additive runtime budget projection for WebView/Capacitor while retaining native Rust constants for runtime independence. UTF-8 byte limits and stat-before-read make the mobile boundary conservative across host implementations; the trade-off is deterministic rejection of oversized notes instead of best-effort ingestion. Static artifact checks are necessary packaging evidence, but release publication must stay behind signed-device evidence. Do not promote SQLite/WASM, public-ID migration, Godot inclusion, or larger budgets until that evidence is archived.
- Preflight
move/renametarget aliases against every active and historical alias before mutation; URI/path/basename collisions fail closed. - Mirror a successful identity transition into
ResourceRegistry, workspace bindings, andIndexLifecyclewithout allocating new resource/projection/index identities. - Add G4 regression coverage for collision rollback visibility and four-owner path convergence after persistence.
- Preserve legacy
documentId, snapshot/projection schemas, mobile runtime dependencies, andmobile-slimpackage boundaries. - Full regression: 148 Jest suites / 1,284 passed / 26 skipped; Rust 30 passed / 1 ignored; four-host projection replay and fresh mobile-low budget passed.
- Add whole-request transaction preflight or journaled rollback for mixed
upsert/move/deletebatches; the current guard is not a claim of full ingest atomicity. - Archive versioned old-snapshot/cross-root/move-journal/collision/rollback manifests before public canonical-ID cutover.
- [~] Native G2/G3 still needs approved signing, arm64 hardware, SAF/query/path workload, force-stop/reopen continuity, retry evidence, and RSS
<= 256 MiB.
- 在 mutation 前对
move/rename目标 alias 与全部 active/historical alias 做预检;URI/path/basename collision fail-closed。 - 成功身份迁移原地同步
ResourceRegistry、workspace binding 与IndexLifecycle,不重新分配 resource/projection/index identity。 - 增加 G4 collision rollback 可见性与持久化后四 owner 路径收敛的回归覆盖。
- 保持旧
documentId、snapshot/projection schema、移动运行时依赖与mobile-slim包体边界不变。 - 全量回归:148 个 Jest suite / 1,284 passed / 26 skipped;Rust 30 passed / 1 ignored;四 host projection replay 与 fresh mobile-low budget 通过。
- 为混合
upsert/move/delete请求增加 whole-request transaction preflight 或 journaled rollback;当前 guard 不宣称完整 ingest 原子性。 - 在 public canonical-ID 切换前归档有版本的 old-snapshot/cross-root/move-journal/collision/rollback manifest。
- [~] 原生 G2/G3 仍需获批 signing、arm64 硬件、SAF/query/path workload、force-stop/reopen continuity、失败重试证据与 RSS
<= 256 MiB。
- Serialize
ingestKnowledgemutations per platform instance so rollback cannot race a concurrent writer. - Capture a deep, versioned graph pre-image before ingest mutation and restore it when an operation, relation recompute, owner mirror, or atomic persistence step fails;
document, atom/evidence, registry, workspace, index, journal, and ID-counter state roll back together. - Reject ambiguous move source aliases instead of selecting the first matching document; owner mirror methods now fail closed when a required owner is missing.
- Add a mixed-batch G4 regression proving a successful first move is not visible after a later collision, and that the original alias remains usable for a subsequent move.
- Preserve all forward-compatibility boundaries: no public-ID change, snapshot/projection schema change, Node sidecar, database, model, Godot asset, or mobile-slim dependency.
- Archive versioned old-snapshot/cross-root/move-journal/collision/rollback manifests and replay them across every host adapter before canonical-ID cutover.
- [~] Native G2/G3 still needs approved signing, arm64 hardware, SAF/query/path workload, force-stop/reopen continuity, retry evidence, and RSS
<= 256 MiB; the rollback pre-image adds transient memory proportional to the current graph and must be measured on the target profile.
- 按 platform instance 串行化
ingestKnowledgemutation,避免 rollback 与并发 writer 竞态。 - 在 ingest mutation 前保存深拷贝的 versioned graph pre-image;operation、relation recompute、owner mirror 或 atomic persistence 失败时整体恢复,document、atom/evidence、registry、workspace、index、journal 与 ID counter 一致回滚。
- move source alias 出现歧义时拒绝而不是选首个匹配;必需 owner 缺失时 mirror 现在 fail-closed。
- 增加 mixed-batch G4 回归:第一步成功、后续 collision 失败后不可观察到第一步状态,原始 alias 仍可用于后续 move。
- 保持所有向前兼容边界:不改变 public ID、snapshot/projection schema,不加入 Node sidecar、数据库、模型、Godot asset 或 mobile-slim 依赖。
- 在 canonical-ID 切换前归档有版本的 old-snapshot/cross-root/move-journal/collision/rollback manifest,并跨所有 host adapter 回放。
- [~] 原生 G2/G3 仍需获批 signing、arm64 硬件、SAF/query/path workload、force-stop/reopen continuity、失败重试证据与 RSS
<= 256 MiB;rollback pre-image 会按当前 graph 产生瞬时内存开销,必须在目标 profile 实测。
- Add
config/identity-corpus.v1.jsonwith eight required old-snapshot, same-content, cross-root/NFC, move-journal, collision, rollback, and four-owner cases. - Add
scripts/verify-identity-corpus.jsto execute the TypeScript identity/persistence replay and invoke the four-host Web/Tauri/Capacitor/Android projection replay. - Add a manifest contract test; the verifier emits
evidenceLevel: host-code-replay,nativeDeviceEvidence: false, a stable result hash, and keeps canonical public-ID cutover blocked. - Replay result: 8 cases passed, 4 projection hosts passed; result hash
4274a5a2d087875d309fdef9dd4232f5704103b9496ee5524744229bf550b5bb. - Final regression after this phase: 149 Jest suites / 1,289 passed / 26 skipped; TypeScript no-emit, Rust 30 passed / 1 ignored, mobile-low budget, native recovery, projection replay, and Diataxis passed.
- Keep public IDs, snapshot/projection schemas, Bridge fields, mobile runtime dependencies, and
mobile-slimunchanged. - Perform an independent canonical-ID migration review using the archived manifest; no public-ID switch is included in this phase.
- [~] Native G2/G3 remains separate: signed arm64 device execution, SAF/permission/retry, force-stop/reopen, and RSS
<= 256 MiBare still unavailable on this host.
- 增加
config/identity-corpus.v1.json,声明八个 old-snapshot、same-content、cross-root/NFC、move-journal、collision、rollback 与四 owner 用例。 - 增加
scripts/verify-identity-corpus.js,实际执行 TypeScript identity/persistence replay,并调用 Web/Tauri/Capacitor/Android 四 host projection replay。 - 增加 manifest contract test;验证器输出
evidenceLevel: host-code-replay、nativeDeviceEvidence: false与稳定 result hash,并继续阻止 canonical public-ID 切换。 - 回放结果:8 个 case 通过,4 个 projection host 通过;result hash 为
4274a5a2d087875d309fdef9dd4232f5704103b9496ee5524744229bf550b5bb。 - 本阶段最终回归:149 个 Jest suite / 1,289 passed / 26 skipped;TypeScript no-emit、Rust 30 passed / 1 ignored、mobile-low budget、native recovery、projection replay 与 Diataxis 通过。
- 保持 public ID、snapshot/projection schema、Bridge 字段、移动运行时依赖与
mobile-slim不变。 - 基于已归档 manifest 独立评审 canonical-ID 迁移;本阶段不切换 public ID。
- [~] 原生 G2/G3 仍独立开放:签名 arm64 真机、SAF/权限/重试、force-stop/reopen 与 RSS
<= 256 MiB当前 host 仍无法提供。
- Add
scripts/verify-canonical-id-readiness.jsas a read-only dry-run over the versioned G4 corpus, four projection hosts, and currentcanonicalIdproducers. - Keep public IDs, snapshot/projection schemas, Bridge fields, and mobile runtime unchanged; the readiness path contains no migration operation.
- Default result is
blockedwithindependentReviewRequired: true;--strictfails closed when native evidence is absent. - Add 4 contract tests for the read-only boundary and compatibility freeze.
- Final regression after this phase: 150 Jest suites / 1,291 passed / 26 skipped; TypeScript no-emit and Diataxis passed.
- Conduct the independent canonical-ID migration review; do not switch
NoteNode.id, old layouts, or public payloads here. - [~] Native G2/G3 remains external until signed arm64, SAF/retry/continuity, and measured RSS evidence exists.
- 增加
scripts/verify-canonical-id-readiness.js,只读检查 versioned G4 corpus、四个 projection host 与当前全部canonicalIdproducer。 - 保持 public ID、snapshot/projection schema、Bridge 字段与移动运行时不变;readiness 路径没有迁移操作。
- 默认结果为
blocked并带independentReviewRequired: true;缺原生证据时--strictfail-closed。 - 增加 4 个只读边界与兼容性冻结契约测试。
- 本阶段最终回归:150 个 Jest suite / 1,291 passed / 26 skipped;TypeScript no-emit 与 Diataxis 通过。
- 执行独立 canonical-ID 迁移评审;本阶段不切换
NoteNode.id、旧 layout 或 public payload。 - [~] 原生 G2/G3 仍是外部门禁,需签名 arm64、SAF/重试/continuity 与 RSS 实测证据。
- Add
mobile:build:releaseas the single documented Android release entry; it delegates to the existing Tauri Android slim build and prerequisite gates. - Add
mobile:build:compatibilityfor explicit historical Capacitor plus Tauri validation while preservingmobile:build:bothfor backward-compatible callers. - Add a mobile pipeline contract preventing the release alias from depending on Capacitor.
- Update English and Chinese README/release guidance; no projection schema, IPC field, public ID, or mobile runtime payload changed.
- Remove the deprecated Capacitor project only after downstream consumers and CI no longer invoke the compatibility alias.
- [~] Native G2/G3 remains independent: the routing fix does not create signed arm64, SAF, continuity, or RSS evidence.
- 增加
mobile:build:release,作为唯一文档化 Android release 入口;它复用现有 Tauri Android slim build 与 prerequisite gate。 - 增加
mobile:build:compatibility,用于显式验证历史 Capacitor + Tauri 双路径,同时保留mobile:build:both兼容旧调用方。 - 增加 mobile pipeline contract,禁止 release alias 依赖 Capacitor。
- 更新中英文 README/release 指引;不改变 projection schema、IPC 字段、public ID 或移动运行时 payload。
- 仅在下游消费者与 CI 不再调用 compatibility alias 后移除 deprecated Capacitor 工程。
- [~] 原生 G2/G3 仍独立开放:路由修复不会生成签名 arm64、SAF、continuity 或 RSS 证据。
- Add a deterministic
graphConditionedContextadapter between the pre-RAG graph answer plan and the evidence budgeter. - Preserve role/score priority; graph plan matches only break same-priority ties and never expand the authorized scope.
- Expose additive
ragContextPack.graphConditioningtrace with matched claims, fragments, atoms, edges, and explicit fallback state. - Wire normal and one-pass recovery RAG assembly through a pre-RAG plan while keeping the final evidence-backed plan unchanged.
- Add focused unit and platform regression coverage; no public ID, IPC, mobile asset, or native evidence claim changed.
- Continue with independent canonical-ID review, strict registry shadow parity, and device evidence as separate gates.
- 在 pre-RAG graph answer plan 与 evidence budgeter 之间增加确定性的
graphConditionedContext适配层。 - 保留 role/score 优先级;图计划只在同优先级内打破平局,不扩大授权 scope。
- 通过 additive
ragContextPack.graphConditioning暴露命中 claim、fragment、atom、edge 与明确 fallback 状态。 - 普通与一次恢复 RAG 都经过 pre-RAG plan;最终带证据 plan 保持不变。
- 增加纯函数与平台回归测试;不改变 public ID、IPC、移动资源或原生证据结论。
- 独立 canonical-ID 评审、strict registry shadow parity 与真机证据继续作为独立门禁。