Skip to content

Releases: desginus/rincore

RinCore v5.3.50

Choose a tag to compare

@github-actions github-actions released this 04 Nov 15:16

RinCore v5.3.50

★★★修「点聊天按钮切不过去」:我 v5.3.48 写的哨兵逻辑自相矛盾(切换动作被自己判成故障)🔧你描述的现象——「点了之后整个应用会抽动一下,貌似是重新回到了工作模式里面,反复点击都没有办法」——完全属实,而且是我上一版亲手写出来的必然结果。 ━━ 一、根因(两个函数各写一半,合起来必然自我否定)━━ ① write(CHAT) 顺手把哨兵置成了 true: kotlin .putString(KEY_MODE, mode.name) .putBoolean(KEY_CHAT_PENDING, mode == AppMode.CHAT) // ← 写 CHAT 就置 true ② resolveInitialMode() 的判据是「CHAT + 哨兵为真 = 上次没起来」: kotlin if (stored != CHAT) return stored if (!isChatPending()) return stored // 哨兵真 → 不返回 AppModeStore.write(WORK) // ← 自愈,强制回工作模式 return WORK 串起来就是:你点「聊天」→ 写盘(顺便把哨兵设为 true)→ recreate() 重建 → onCreate 读到「CHAT + 哨兵为真」→ 判定为「上次进入聊天模式没渲染成功」→ 自愈写回 WORK → 你看到的那一下「抽动」就是这次重建,回到工作模式是自愈的结果。反复点,每次都是同样三步,所以永远进不去。 本质上:我把「用户刚切过来」和「上次崩溃了」这两种情况用了同一个标记,它们在代码看来完全一样 → 切换动作被自己的保护机制当成故障处理掉了。 ━━ 二、修复(把哨兵的语义收窄到它真正该表示的那一件事)━━ 哨兵只表示「本次进入 CHAT 后还没确认渲染成功」,所以: ① write(CHAT) 不碰哨兵 —— 它只负责「我要去聊天的」这个意图,不负责判定成败; ② write(WORK) 清掉哨兵 —— 回到工作模式后不存在「CHAT 没起来」这回事,残留的 true 会让下一次进入被误判; ③ resolveInitialMode() 在真正决定进入 CHAT 时才置哨兵 —— 置位后:渲染成功 → markChatHealthy() 清除;崩溃 → 残留 → 下次启动自愈回 WORK。 这样三种情况才真正被区分开:刚切过来(false → 进 CHAT 并置位)/正常使用中(渲染完已清)/上次崩了(残留 true → 回 WORK)。 ━━ 三、验证(22 项断言,编译真实源码实跑)━━ 验证程序里完整复刻了「点按钮 → 写盘 → recreate → onCreate 判定 → 渲染成功/崩溃」这条真实链路: ★点一次「聊天」必须进 CHAT(你报的核心问题,直接对应断言)/★反复点 5 次每次都进(你原话「反复点击都没有办法」)/★切过去→切回来→再切过去(往返最易出问题)/停在 CHAT 关掉重启仍是 CHAT/停在 WORK 关掉重启仍是 WORK/★CHAT 渲染崩溃 → 下次启动自动回 WORK/崩溃后仍能正常再进 CHAT/安全模式重置后仍能再进 CHAT/★反复写 CHAT 但不渲染也不把状态搞乱。22/22 全过。 ★测试第一版我写错了(「崩溃」场景漏掉了 resolveInitialMode 那一步,而哨兵正是在那里置位的)→ 实跑立刻报 5 条 FAIL,修正时序后全过。这正是「测试必须按真实时序写」的价值:它同时验证了实现和我的理解。 ━━ 四、数据安全(未变)━━ 本轮仍只碰 rincore_shell 这个独立 SharedPreferences 的两个键;全库 AppMode 与数据库/工作区/记忆的交集 仍为 0。安装本版不会动已有对话、设置、记忆、工作区、rootfs、附件。━━ 五、诚实边界 ━━ ①无安装实测(沙箱无设备),以 22 项实跑 + tree-sitter 双文件 PASS + rc check 双 PASS + audit fast AUDIT-OK 为据;②**「抽动一下」本身是 recreate() 重建 Activity 的正常表现**(切换模式要换整棵 UI 树,必然重建),这版修好后它仍然会抽动一下,但抽完应停在聊天模式;③聊天模式仍是占位页(Mika 代码未接入);④切换模式会中断正在进行的回复生成(已落库内容不丢,当前轮最后一段可能收不全)。★版本纪律:5.3.49 → 5.3.50(只改第三位、不进位)。★改动 2 文件 / +35-5:AppMode.kt(write 语义拆分 + 新增 markChatPending)/ RouteActivity.kt(resolveInitialMode 置哨兵)。 ⑩hub=v5.3.50

本次提交

  • dc8d3e3 release: v5.3.49 — ★★★彻底维修:把模式判定从「Compose 组合期间」移出来(工作模式行为零变化,数据面零接触)🔧这一版只改 2 个文件、39 行,但修的是一个会真实拖慢首帧的反模式;并且把「至少工作模式能用」这件事逐条证到了底。 ━━ 一、修的是什么(真问题)━━ v5.3.48 我把模式判定与自愈写在了 setContent { remember { ... } } 里: remember 的 block 是在 Compose 组合期间执行的 —— 而它里面既有 SharedPreferences 读,又可能触发 commit()(同步磁盘写)。在组合期间做磁盘 IO 是 Compose 明确的反模式:会拖慢首帧,且 remember 的 block 在组合被取消/重试时语义不保证。 现在:自愈与判定移到 onCreate 里、setContent 之前,作为普通 Kotlin 代码执行一次;组合侧只拿一个纯值 remember { mutableStateOf(initialMode) }。组合期间零 IO。 ━━ 二、验证(5 个场景 / 14 项断言,编译真实源码实跑)━━ 用 kotlinc 编译真实的 AppMode.kt(补内存版 SharedPreferences + Log stub),并在验证程序里写出与 RouteActivity.resolveInitialMode 完全同构的判定函数,跑: ①全新安装 → 工作模式,且零写盘(证明不会给新用户留下任何状态)/②上次停在 WORK → 仍是 WORK,零写盘(证明日常用户完全无感)/③上次停在 CHAT 且正常渲染过 → 保持 CHAT,零写盘(尊重用户选择)/④上次停在 CHAT 但没起来 → 自动回退 WORK 并落盘,回退后哨兵清除,二次启动零写入(证明自愈只发生一次、不会每启动一次就写盘)/⑤连续 5 次判定结果一致(幂等)。14/14 全过。 ━━ 三、「至少工作模式能用」—— 这是本轮最重要的部分 ━━ 工作模式的代码路径与上一版完全一致:RenderRequestHost() + AppRoutes() 一字未改,只是外面包了一层 when。新增开销只有一次 SharedPreferences 读(毫秒级)+ 一次枚举比较。 三层兜底,每一层都验过:①哨兵自愈(切到 CHAT 没起来 → 下次回工作模式并落盘);②安全模式重置(崩溃后进安全模式时强制写 WORK,避免「CHAT 崩 → 安全模式 → 退出 → 又进 CHAT → 再崩」死循环);③默认值兜底(读不到/脏数据/大小写变体一律回落 WORK)。三者合起来保证:任何情况下都至少能进工作模式。 ━━ 四、数据安全(逐项核验为 0)━━ 全库 grep AppMode 与数据面的交集:涉及数据库 0 处 / 涉及工作区或文件 0 处 / 涉及记忆 0 处。模式切换只写 rincore_shell 这个独立 SharedPreferences 的两个键。安装这一版不会动你已有的对话、设置、记忆、工作区、rootfs、附件。 ━━ 五、顺带修的一处静默 ━━ AppModeStore.write() 原本忽略 commit() 的返回值 —— 落盘失败(磁盘满/权限)时,用户界面上像是切了、重启却回到旧模式,且没有任何线索。现在返回 Boolean 并在失败时打 AppModeStore 日志。失败不会破坏已有数据(SharedPreferences 写入是原子的),所以只记录、不中断。 ━━ 六、诚实边界 ━━ ①无安装实测(沙箱无设备),以 14 项实跑 + tree-sitter 双文件 PASS + rc check 双 PASS + audit fast AUDIT-OK 为据;②聊天模式仍是占位页(Mika 代码未接入),所以「CHAT 崩溃」这条路径目前只在机制上就位、不会被真实触发;③切换模式会中断正在进行的回复生成(recreate() 结束当前屏幕协程),已落库内容不丢,但当前这一轮最后一段可能收不全 —— 建议等这一轮结束再切;④本轮零新增功能,严格限定「修组合期间副作用 + 补可观测性」。 ★版本纪律:5.3.48 → 5.3.49(只改第三位、不进位)。 ⑩hub=v5.3.49
  • edb2469 release: v5.3.48 — ★★★模式切换的数据安全与自愈:不会碰你任何数据,聊天模式起不来会自动退回工作模式,上次在哪个模式关下次还在那个模式🔒这一版不加功能,只做三件事:证明它不碰数据、给它兜底、把「上次在哪个模式」钉死。 ━━ 一、先回答你最担心的:装新版会不会把之前的东西搞坏 ━━ 模式切换只写一个东西:rincore_shell 这个独立的 SharedPreferences 里两个键(app_mode 字符串 + chat_mode_pending 布尔)。它不碰:数据库、聊天记录、设置、记忆、工作区、rootfs、上传附件。 我逐条核验了切换路径 —— RouteActivity 与 ChatDrawer 里全部代码只有 AppModeStore.write(...) + recreate(),没有任何一行数据库或文件写入;并且全库 grep AppMode 与 workspace/filesDir/rootfs/memory 的交集为 0。 为什么能这么确定:AppMode 是壳层的、属于「这个应用现在显示哪个界面」,跟「应用里存了什么」在代码上是两条完全不相交的路径。切模式不迁移、不清洗、不改写任何既有数据。 ━━ 二、你说「上次在哪个模式关闭,开了之后要还是在那个模式」—— 这条之前是错的 ━━ 原实现用的是 apply()(异步落盘)。它的问题正是:用户刚切完模式、还没落盘就被系统杀进程(后台清理非常常见)→ 下次打开还是旧模式。你描述的「上次在一个模式关闭的,开了之后又到另一个模式了」,机制上完全成立。 现在改 commit()(同步写):一次切换只写两个键,毫秒级代价,换来确定性 —— 切完立刻生效,杀进程也不丢。 ━━ 三、一个模式挂了绝不能让整个软件打不开(新增两层兜底)━━ 风险场景(必须有答案):你切到聊天模式 → 关掉应用 → 如果聊天模式这一侧起不来(Mika 初始化失败、渲染崩溃……)→ 下次打开直接崩 → 你再也进不去,连工作模式都用不了。这是绝不能接受的。 ① 哨兵自愈:进入聊天模式时置一个「未成功」标记,聊天模式成功渲染后清除。下次启动如果发现标记还在 = 上一次没跑起来 → 自动退回工作模式并落盘。宁可回工作模式(至少能用),也不把你关在一个起不来的界面里。 ② 安全模式重置:走到安全模式说明刚崩过 → 里面强制把模式重置为工作模式。否则会出现这条死循环:聊天模式崩溃 → 安全模式 → 退出 → 又进聊天模式 → 再崩。 工作模式本身不受影响:它是默认值、是自愈目标、是安全模式的落点 —— 三重保证下它一定进得去。 ━━ 四、可用性:切回来不会「回到首页」━━ 占位页的「返回工作模式」按钮我原本只改状态不重建 Activity —— 那会让工作模式的导航栈丢失(你切过去再切回来,会发现回到了首页,而不是原来那个对话)。现在统一为与抽屉按钮完全相同的路径:写盘 + recreate()。AppRoutes 用的是 rememberNavBackStack(startScreen)(navigation3 的 saveable 实现),recreate() 带 savedInstanceState 重建时会恢复原来的对话位置。 ━━ 五、验证(16 项,用真实 AppMode.kt 编译后实跑)━━ 首次安装默认工作 / 切聊天后能读到聊天 / 写入是同步 commit / 切换后哨兵置位 / 成功后哨兵清除 / 正常重启仍是聊天(尊重你的选择) / 未成功时哨兵仍在 / 起不来自动回退工作 / 回退结果已落盘 / 回退后哨兵清除 / 反复切换以最后一次为准 / 脏数据或大小写变体回落工作 / 小写 chat 能识别 / 安全模式后回工作 / 安全模式后哨兵清除 —— 16/16 全过。 过程中我自己的断言写错一条(repeat(5) 的末次是偶数,我写成了 WORK,实际是 CHAT)—— 实跑立刻暴露,说明这套验证是真的在验证而不是走过场。 ━━ 六、必须提前告诉你的一个行为 ━━ 切换模式会中断正在进行的回复生成(recreate() 会结束当前屏幕的协程)。已经落库的内容不会丢(流式落库是原子写),但当前这一轮还没落库的最后一段可能收不全。建议:等这一轮回复结束再切换。若你要我做「正在生成时切换先弹确认」,说一声,可以加。 ━━ 七、诚实边界 ━━ ①聊天模式现在仍是占位页(Mika 代码还没接入),所以「聊天模式崩溃」这一侧目前很难被真实触发 —— 但机制现在就在,等 Mika 接进来那天它立刻生效;②无安装实测(沙箱无设备),以 16 项实跑 + tree-sitter 三文件 PASS + rc check 双 PASS 为据;③切模式不清理任何缓存/数据,只是换一套界面;④没有做「模式切换前自动保存草稿」的额外动作 —— 草稿本来就在 ChatVM.onCleared 里保存(v5.3.18 幂等判据保证不会写坏)。 ★版本纪律:5.3.47 → 5.3.48(只改第三位、不进位)。 ⑩hub=v5.3.48
  • e0b07c9 release: v5.3.47 — ★★双模式外壳落地:抽屉底部一个按钮,工作(RinCore)与聊天(Mika)是同一个 APK 里两个完全独立的 app🔄这一版按你的定案做:不做代码合并,只把两个应用放进同一个 APK,各走各的。 ━━ 一、为什么必须是同一个 APK(技术结论,不是偏好)━━ 你说「两个应用唯一的共同点是寄宿在同一个软件里、共用同一个 Linux 沙箱」—— 这句话在 Android 上直接排除了「两个独立 APK 互相跳转」:应用私有目录按包名隔离,me.rincore.app 和 com.wangzan101.mika 各自有自己的 files/workspaces/,谁也读不到谁的 proot rootfs。双 APK 方案满足不了「共用同一个沙箱」这条硬要求。 所以:同一个 APK + 两套完全独立的运行时 + 一个共享的外壳。这也正是你说的形态。 ━━ 二、本版实际做了什么 ━━ ① 模式状态(壳层,独立于两边) —— 新建 data/appmode/AppMode.kt:AppMode { WORK, CHAT } + AppModeStore(读/写/切换)。刻意用 SharedPreferences 而不是 DataStore:要在 RouteActivity.onCreate 之前同步读到一个字符串,DataStore 是异步的、首帧拿不到值会先渲染错模式再闪一下。也刻意不放进 RinCore 的 Settings —— 那是工作模式自己的数据,壳层状态寄存在里面就等于两个应用又开始纠缠。 ② 抽屉底部切换按钮 —— 你描述的位置:左侧「用量查询 / 收藏 / 统计数据」三个图标,右侧设置。现在在两者之间加了一个「聊天」按钮(BubbleChat 图标)。点击 = 写壳层偏好 + recreate(),让 RouteActivity 重读模式后整棵 UI 树换掉 —— 这样两边不可能因为共享状态而互相影响,正是你要的隔离。 ③ 聊天模式入口 —— ChatModeEntry:当前是明确的占位页,不是假界面。一个假的聊天页只会让人以为已经接上了;这里直接写清「外壳与切换已就位,Mika 业务代码尚未接入」。页面上有「返回工作模式」,两端都能切。 ━━ 三、接入 Mika 时要守的五条边界(已写进代码注释,防将来不知不觉又合并)━━ ①各自的依赖容器(RinCore 的 Koin 与 Mika 的容器互不可见);②各自的数据库(不同 db 文件名,绝不共表);③各自的偏好(Mika 不读 RinCore 的 DataStore,反之亦然);④各自的技能 / 对话 / MCP 服务器(两边是两套独立数据);⑤唯一共享:files/workspaces/(Linux 沙箱)与这个外壳 APK。 ━━ 四、必须提前说清的一件事(不是合并,但工作量在)━━ Mika v0.1.35 用 Compose BOM 2024.12.01,我们用 2026.09.00。同一个 APK 里 Compose 运行时只能有一个版本 —— 这不是「要不要融合代码」的选择题,而是「能不能装进同一个 APK」的物理限制。 所以接入 Mika 时必须做的是:把 Mika 的界面代码适配到我们的构建环境(不是改它的功能、不是融合两边的业务逻辑,只是让它能在新版本 Compose 上编译)。好消息是 Mika 的 core 模块(707 个 .kt)是纯 JVM、零 Compose、零 Android 依赖,可以直接搬;只有 app 里 77 个 UI 文件需要逐个适配。 这才是这条路上唯一真正的硬骨头,我会分阶段做,每阶段独立可验证、失败可整段回退。 ━━ 五、诚实边界 ━━ ①本版没有 Mika 的任何代码 —— 只有外壳、切换、状态持久化与占位页。我没有假装它已经接上了。②**「聊天」按钮切换后看到的是占位页**,不是聊天界面;点「返回工作模式」可立即切回。③无安装实测(沙箱无设备),以 tree-sitter 四文件 PASS + rc check 双 PASS 为据。④版本号按你的规则走第三位(5.3.46 → 5.3.47),没有因为「功能维度变了」就进 5.4.0。 ★版本纪律:5.3.46 → 5.3.47(只改第三位、不进位)。 ⑩hub=v5.3.47
  • bb052f3 release: v5.3.47 — ★★记忆工具摘要不再显示路径,改为显示记忆正文;并为 Mika 合并完成可行性取证📖🧠━━ 一、记忆工具摘要:路径 → 正文 ━━ 你说的那句「显示读取的记忆,然后下面是内容,但这个内容它为什么现在是路径?我看不懂,也不重要」,我核对到了唯一一处:MemoryFileToolUI.Summary 里写的就是 text = path。 现在正文来源按优先级取:①参数里的 content(write / append)、new_str / old_str(str_replace)→ 这是模型这次真正写进去的文字;②输出里的 files[0].content(memory_read)→ 这才是「读取到的记忆」;③都没有(delete / list)→ 不显示摘要(标题已经写明「删除记忆」/「列出记忆」,不再堆一串路径)。 配套两个细节:正文会先剥掉 frontmatter(--- 开头那段 title: / kind: 是给模型看的元数据,你要读的是记忆内容);正文可点击,点一下仍能打开该记忆的详情页——路径还在内部用来定位,只是不再出现在界面上。 验证:stripFrontmatter 抽出真实函数用 kotlinc 编译,4 个用例全过(正常 frontmatter / 空正文 / 无 frontmatter 原样 / 非法的 --- 不误剥);tree-sitter + rc check 双 PASS。 ━━ 二、Mika 合并:先给你可执行的结论,不画饼 ━━ 我拉了 Mika 最新 tag v0.1.35 的完整源码(不是凭记忆),逐项核对了技术栈: | | RinCore | Mika v0.1.35 | |---|---|---| | Kotlin | 2.4.21 | 2.1.20 | | AGP | 9.4.0 | 8.7.3 | | Compose BOM | 2026.09.00 | 2024.12.01 | | 模块 | 多模块 | :core + :app | | 包名 | me.rincore.app | com.wangzan101.mika | | .kt | 1353 | 1355 | 关键好消息(这是决定性的):Mika 的 core 模块(707 个 .kt)是纯 JVM 模块 —— plugins { kotlin.jvm },零 Compose、零 Android 依赖,只用到 kotlinx-serialization / coroutines / okhttp / protobuf-javalite / commons-compress。这些我们的项目全都有,版本也兼容。 所以合并分三层难度:① core 707 文件 = 直接可搬(加一个 :mika-core 模块,用我们的 Kotlin 编译即可);**② app 里 262 个文件无 Comp...
Read more

RinCore v5.3.49

Choose a tag to compare

@github-actions github-actions released this 04 Nov 14:01

RinCore v5.3.49

★★★彻底维修:把模式判定从「Compose 组合期间」移出来(工作模式行为零变化,数据面零接触)🔧这一版只改 2 个文件、39 行,但修的是一个会真实拖慢首帧的反模式;并且把「至少工作模式能用」这件事逐条证到了底。 ━━ 一、修的是什么(真问题)━━ v5.3.48 我把模式判定与自愈写在了 setContent { remember { ... } } 里: remember 的 block 是在 Compose 组合期间执行的 —— 而它里面既有 SharedPreferences 读,又可能触发 commit()(同步磁盘写)。在组合期间做磁盘 IO 是 Compose 明确的反模式:会拖慢首帧,且 remember 的 block 在组合被取消/重试时语义不保证。 现在:自愈与判定移到 onCreate 里、setContent 之前,作为普通 Kotlin 代码执行一次;组合侧只拿一个纯值 remember { mutableStateOf(initialMode) }。组合期间零 IO。 ━━ 二、验证(5 个场景 / 14 项断言,编译真实源码实跑)━━ 用 kotlinc 编译真实的 AppMode.kt(补内存版 SharedPreferences + Log stub),并在验证程序里写出与 RouteActivity.resolveInitialMode 完全同构的判定函数,跑: ①全新安装 → 工作模式,且零写盘(证明不会给新用户留下任何状态)/②上次停在 WORK → 仍是 WORK,零写盘(证明日常用户完全无感)/③上次停在 CHAT 且正常渲染过 → 保持 CHAT,零写盘(尊重用户选择)/④上次停在 CHAT 但没起来 → 自动回退 WORK 并落盘,回退后哨兵清除,二次启动零写入(证明自愈只发生一次、不会每启动一次就写盘)/⑤连续 5 次判定结果一致(幂等)。14/14 全过。 ━━ 三、「至少工作模式能用」—— 这是本轮最重要的部分 ━━ 工作模式的代码路径与上一版完全一致:RenderRequestHost() + AppRoutes() 一字未改,只是外面包了一层 when。新增开销只有一次 SharedPreferences 读(毫秒级)+ 一次枚举比较。 三层兜底,每一层都验过:①哨兵自愈(切到 CHAT 没起来 → 下次回工作模式并落盘);②安全模式重置(崩溃后进安全模式时强制写 WORK,避免「CHAT 崩 → 安全模式 → 退出 → 又进 CHAT → 再崩」死循环);③默认值兜底(读不到/脏数据/大小写变体一律回落 WORK)。三者合起来保证:任何情况下都至少能进工作模式。 ━━ 四、数据安全(逐项核验为 0)━━ 全库 grep AppMode 与数据面的交集:涉及数据库 0 处 / 涉及工作区或文件 0 处 / 涉及记忆 0 处。模式切换只写 rincore_shell 这个独立 SharedPreferences 的两个键。安装这一版不会动你已有的对话、设置、记忆、工作区、rootfs、附件。 ━━ 五、顺带修的一处静默 ━━ AppModeStore.write() 原本忽略 commit() 的返回值 —— 落盘失败(磁盘满/权限)时,用户界面上像是切了、重启却回到旧模式,且没有任何线索。现在返回 Boolean 并在失败时打 AppModeStore 日志。失败不会破坏已有数据(SharedPreferences 写入是原子的),所以只记录、不中断。 ━━ 六、诚实边界 ━━ ①无安装实测(沙箱无设备),以 14 项实跑 + tree-sitter 双文件 PASS + rc check 双 PASS + audit fast AUDIT-OK 为据;②聊天模式仍是占位页(Mika 代码未接入),所以「CHAT 崩溃」这条路径目前只在机制上就位、不会被真实触发;③切换模式会中断正在进行的回复生成(recreate() 结束当前屏幕协程),已落库内容不丢,但当前这一轮最后一段可能收不全 —— 建议等这一轮结束再切;④本轮零新增功能,严格限定「修组合期间副作用 + 补可观测性」。 ★版本纪律:5.3.48 → 5.3.49(只改第三位、不进位)。 ⑩hub=v5.3.49

本次提交

  • edb2469 release: v5.3.48 — ★★★模式切换的数据安全与自愈:不会碰你任何数据,聊天模式起不来会自动退回工作模式,上次在哪个模式关下次还在那个模式🔒这一版不加功能,只做三件事:证明它不碰数据、给它兜底、把「上次在哪个模式」钉死。 ━━ 一、先回答你最担心的:装新版会不会把之前的东西搞坏 ━━ 模式切换只写一个东西:rincore_shell 这个独立的 SharedPreferences 里两个键(app_mode 字符串 + chat_mode_pending 布尔)。它不碰:数据库、聊天记录、设置、记忆、工作区、rootfs、上传附件。 我逐条核验了切换路径 —— RouteActivity 与 ChatDrawer 里全部代码只有 AppModeStore.write(...) + recreate(),没有任何一行数据库或文件写入;并且全库 grep AppMode 与 workspace/filesDir/rootfs/memory 的交集为 0。 为什么能这么确定:AppMode 是壳层的、属于「这个应用现在显示哪个界面」,跟「应用里存了什么」在代码上是两条完全不相交的路径。切模式不迁移、不清洗、不改写任何既有数据。 ━━ 二、你说「上次在哪个模式关闭,开了之后要还是在那个模式」—— 这条之前是错的 ━━ 原实现用的是 apply()(异步落盘)。它的问题正是:用户刚切完模式、还没落盘就被系统杀进程(后台清理非常常见)→ 下次打开还是旧模式。你描述的「上次在一个模式关闭的,开了之后又到另一个模式了」,机制上完全成立。 现在改 commit()(同步写):一次切换只写两个键,毫秒级代价,换来确定性 —— 切完立刻生效,杀进程也不丢。 ━━ 三、一个模式挂了绝不能让整个软件打不开(新增两层兜底)━━ 风险场景(必须有答案):你切到聊天模式 → 关掉应用 → 如果聊天模式这一侧起不来(Mika 初始化失败、渲染崩溃……)→ 下次打开直接崩 → 你再也进不去,连工作模式都用不了。这是绝不能接受的。 ① 哨兵自愈:进入聊天模式时置一个「未成功」标记,聊天模式成功渲染后清除。下次启动如果发现标记还在 = 上一次没跑起来 → 自动退回工作模式并落盘。宁可回工作模式(至少能用),也不把你关在一个起不来的界面里。 ② 安全模式重置:走到安全模式说明刚崩过 → 里面强制把模式重置为工作模式。否则会出现这条死循环:聊天模式崩溃 → 安全模式 → 退出 → 又进聊天模式 → 再崩。 工作模式本身不受影响:它是默认值、是自愈目标、是安全模式的落点 —— 三重保证下它一定进得去。 ━━ 四、可用性:切回来不会「回到首页」━━ 占位页的「返回工作模式」按钮我原本只改状态不重建 Activity —— 那会让工作模式的导航栈丢失(你切过去再切回来,会发现回到了首页,而不是原来那个对话)。现在统一为与抽屉按钮完全相同的路径:写盘 + recreate()。AppRoutes 用的是 rememberNavBackStack(startScreen)(navigation3 的 saveable 实现),recreate() 带 savedInstanceState 重建时会恢复原来的对话位置。 ━━ 五、验证(16 项,用真实 AppMode.kt 编译后实跑)━━ 首次安装默认工作 / 切聊天后能读到聊天 / 写入是同步 commit / 切换后哨兵置位 / 成功后哨兵清除 / 正常重启仍是聊天(尊重你的选择) / 未成功时哨兵仍在 / 起不来自动回退工作 / 回退结果已落盘 / 回退后哨兵清除 / 反复切换以最后一次为准 / 脏数据或大小写变体回落工作 / 小写 chat 能识别 / 安全模式后回工作 / 安全模式后哨兵清除 —— 16/16 全过。 过程中我自己的断言写错一条(repeat(5) 的末次是偶数,我写成了 WORK,实际是 CHAT)—— 实跑立刻暴露,说明这套验证是真的在验证而不是走过场。 ━━ 六、必须提前告诉你的一个行为 ━━ 切换模式会中断正在进行的回复生成(recreate() 会结束当前屏幕的协程)。已经落库的内容不会丢(流式落库是原子写),但当前这一轮还没落库的最后一段可能收不全。建议:等这一轮回复结束再切换。若你要我做「正在生成时切换先弹确认」,说一声,可以加。 ━━ 七、诚实边界 ━━ ①聊天模式现在仍是占位页(Mika 代码还没接入),所以「聊天模式崩溃」这一侧目前很难被真实触发 —— 但机制现在就在,等 Mika 接进来那天它立刻生效;②无安装实测(沙箱无设备),以 16 项实跑 + tree-sitter 三文件 PASS + rc check 双 PASS 为据;③切模式不清理任何缓存/数据,只是换一套界面;④没有做「模式切换前自动保存草稿」的额外动作 —— 草稿本来就在 ChatVM.onCleared 里保存(v5.3.18 幂等判据保证不会写坏)。 ★版本纪律:5.3.47 → 5.3.48(只改第三位、不进位)。 ⑩hub=v5.3.48
  • e0b07c9 release: v5.3.47 — ★★双模式外壳落地:抽屉底部一个按钮,工作(RinCore)与聊天(Mika)是同一个 APK 里两个完全独立的 app🔄这一版按你的定案做:不做代码合并,只把两个应用放进同一个 APK,各走各的。 ━━ 一、为什么必须是同一个 APK(技术结论,不是偏好)━━ 你说「两个应用唯一的共同点是寄宿在同一个软件里、共用同一个 Linux 沙箱」—— 这句话在 Android 上直接排除了「两个独立 APK 互相跳转」:应用私有目录按包名隔离,me.rincore.app 和 com.wangzan101.mika 各自有自己的 files/workspaces/,谁也读不到谁的 proot rootfs。双 APK 方案满足不了「共用同一个沙箱」这条硬要求。 所以:同一个 APK + 两套完全独立的运行时 + 一个共享的外壳。这也正是你说的形态。 ━━ 二、本版实际做了什么 ━━ ① 模式状态(壳层,独立于两边) —— 新建 data/appmode/AppMode.kt:AppMode { WORK, CHAT } + AppModeStore(读/写/切换)。刻意用 SharedPreferences 而不是 DataStore:要在 RouteActivity.onCreate 之前同步读到一个字符串,DataStore 是异步的、首帧拿不到值会先渲染错模式再闪一下。也刻意不放进 RinCore 的 Settings —— 那是工作模式自己的数据,壳层状态寄存在里面就等于两个应用又开始纠缠。 ② 抽屉底部切换按钮 —— 你描述的位置:左侧「用量查询 / 收藏 / 统计数据」三个图标,右侧设置。现在在两者之间加了一个「聊天」按钮(BubbleChat 图标)。点击 = 写壳层偏好 + recreate(),让 RouteActivity 重读模式后整棵 UI 树换掉 —— 这样两边不可能因为共享状态而互相影响,正是你要的隔离。 ③ 聊天模式入口 —— ChatModeEntry:当前是明确的占位页,不是假界面。一个假的聊天页只会让人以为已经接上了;这里直接写清「外壳与切换已就位,Mika 业务代码尚未接入」。页面上有「返回工作模式」,两端都能切。 ━━ 三、接入 Mika 时要守的五条边界(已写进代码注释,防将来不知不觉又合并)━━ ①各自的依赖容器(RinCore 的 Koin 与 Mika 的容器互不可见);②各自的数据库(不同 db 文件名,绝不共表);③各自的偏好(Mika 不读 RinCore 的 DataStore,反之亦然);④各自的技能 / 对话 / MCP 服务器(两边是两套独立数据);⑤唯一共享:files/workspaces/(Linux 沙箱)与这个外壳 APK。 ━━ 四、必须提前说清的一件事(不是合并,但工作量在)━━ Mika v0.1.35 用 Compose BOM 2024.12.01,我们用 2026.09.00。同一个 APK 里 Compose 运行时只能有一个版本 —— 这不是「要不要融合代码」的选择题,而是「能不能装进同一个 APK」的物理限制。 所以接入 Mika 时必须做的是:把 Mika 的界面代码适配到我们的构建环境(不是改它的功能、不是融合两边的业务逻辑,只是让它能在新版本 Compose 上编译)。好消息是 Mika 的 core 模块(707 个 .kt)是纯 JVM、零 Compose、零 Android 依赖,可以直接搬;只有 app 里 77 个 UI 文件需要逐个适配。 这才是这条路上唯一真正的硬骨头,我会分阶段做,每阶段独立可验证、失败可整段回退。 ━━ 五、诚实边界 ━━ ①本版没有 Mika 的任何代码 —— 只有外壳、切换、状态持久化与占位页。我没有假装它已经接上了。②**「聊天」按钮切换后看到的是占位页**,不是聊天界面;点「返回工作模式」可立即切回。③无安装实测(沙箱无设备),以 tree-sitter 四文件 PASS + rc check 双 PASS 为据。④版本号按你的规则走第三位(5.3.46 → 5.3.47),没有因为「功能维度变了」就进 5.4.0。 ★版本纪律:5.3.46 → 5.3.47(只改第三位、不进位)。 ⑩hub=v5.3.47
  • bb052f3 release: v5.3.47 — ★★记忆工具摘要不再显示路径,改为显示记忆正文;并为 Mika 合并完成可行性取证📖🧠━━ 一、记忆工具摘要:路径 → 正文 ━━ 你说的那句「显示读取的记忆,然后下面是内容,但这个内容它为什么现在是路径?我看不懂,也不重要」,我核对到了唯一一处:MemoryFileToolUI.Summary 里写的就是 text = path。 现在正文来源按优先级取:①参数里的 content(write / append)、new_str / old_str(str_replace)→ 这是模型这次真正写进去的文字;②输出里的 files[0].content(memory_read)→ 这才是「读取到的记忆」;③都没有(delete / list)→ 不显示摘要(标题已经写明「删除记忆」/「列出记忆」,不再堆一串路径)。 配套两个细节:正文会先剥掉 frontmatter(--- 开头那段 title: / kind: 是给模型看的元数据,你要读的是记忆内容);正文可点击,点一下仍能打开该记忆的详情页——路径还在内部用来定位,只是不再出现在界面上。 验证:stripFrontmatter 抽出真实函数用 kotlinc 编译,4 个用例全过(正常 frontmatter / 空正文 / 无 frontmatter 原样 / 非法的 --- 不误剥);tree-sitter + rc check 双 PASS。 ━━ 二、Mika 合并:先给你可执行的结论,不画饼 ━━ 我拉了 Mika 最新 tag v0.1.35 的完整源码(不是凭记忆),逐项核对了技术栈: | | RinCore | Mika v0.1.35 | |---|---|---| | Kotlin | 2.4.21 | 2.1.20 | | AGP | 9.4.0 | 8.7.3 | | Compose BOM | 2026.09.00 | 2024.12.01 | | 模块 | 多模块 | :core + :app | | 包名 | me.rincore.app | com.wangzan101.mika | | .kt | 1353 | 1355 | 关键好消息(这是决定性的):Mika 的 core 模块(707 个 .kt)是纯 JVM 模块 —— plugins { kotlin.jvm },零 Compose、零 Android 依赖,只用到 kotlinx-serialization / coroutines / okhttp / protobuf-javalite / commons-compress。这些我们的项目全都有,版本也兼容。 所以合并分三层难度:① core 707 文件 = 直接可搬(加一个 :mika-core 模块,用我们的 Kotlin 编译即可);② app 里 262 个文件无 Compose 依赖 = 可搬(可能有 Android API 版本差异,需逐个修);③ app 里 77 个 UI 文件 = 唯一真正的硬骨头 —— 两年跨度的 Compose API 变更,必须逐个升级。 这一点必须说清:同一个 APK 里 Compose runtime 只能有一个版本,所以不能「Mika 用旧的、我们用新的」。要么升 Mika 的 UI,要么放弃 UI 层复用。 为什么不建议两个 APK 互相跳转:你说过「唯一共同点是寄宿在同一个软件里、共用同一个 Linux 沙箱」——而 Android 的私有目录按包名隔离,两个 APK 根本没法共用同一个 proot rootfs。双 APK 方案满足不了你提的核心要求,所以只能走单 APK。 躺在我这边的判断:core 先落地是零风险高收益的一步——它能立刻验证「Mika 的 agent 内核能不能在我们的构建体系里编译通过」,而这个数字(编译错误条数)是后续所有工作量的基准。我下一步就是把它加成一个独立模块并推到 CI 拿这个数字,不污染现有功能、失败可整模块删除。 ━━ 三、诚实边界 ━━ ①记忆工具摘要改动只影响显示,工具参数、返回值、跳转行为未动;②Mika 合并本轮只完成取证与技术栈核对,没有任何源码合入(不想在没数据前给你画饼);③无安装实测(沙箱无设备),以 kotlinc 实跑 4 项 + tree-sitter + rc check 为据;④Mika v0.1.35 是 tag 而非 release(该仓库无 GitHub Release),我用的是 tag 对应的 commit。 ★版本纪律:5.3.46 → 5.3.47(只改第三位、不进位)。 ⑩hub=v5.3.47
  • 3573079 release: v5.3.46 — ★★三件事一次修完:发布不再重复推两个一模一样的 / 工具 UI 不再糊一长串路径 / 记忆旧格式可一键清理🧹━━ 一、发布流程:为什么每次发完会立刻再推一个一模一样的 ━━ 你禁止过这件事,我之前也没做到 —— 根因找到了,是配置文件与自己文件头的注释互相矛盾:dev-build.yml 第 2 行白纸黑字写着「2026-10-20 起:主流程只推 main,本 workflow 仅供实验分支用手动触发」,但 on: 里还留着 push: branches: [\"adopt-3.0.0\"]。 于是每次发版的完整链条是:rc release 只推 main(跑 build.yml,正式发版)→ 我为了保持分支同步补推 adopt-3.0.0 → 触发 dev-build.yml 跑一遍完整构建 → 你在 GitHub 上看到「刚发完,又冒出一个一模一样的,唯一区别是 adopt-3.0.0」。 它其实什么都没发布(dev-build 不创建 release、不碰 main,注释里也这么写),但看起来就像重复发版,而且白烧一次 CI。 修复:删掉 push 触发,只留 workflow_dispatch。今后补推 adopt 不会再产生任何构建;需要临时验证实验分支时手动触发即可。 验证:全库 grep adopt-3.0.0,剩余的只出现在注释与 workflow 名称里,没有任何自动触发。 ━━ 二、工具 UI:不再显示路径,改为文件名 + 内容 ━━ 你说的那句「路径在我看来就是一串无意义的乱码,用户无法识别」是对的。而且代码里本来就有两套做法:workspace_read_file / workspace_write_file 早在 v3.11.24 就改成「标题只写『读取文件』,完整路径放展开详情」,但 workspace_edit_file 和 workspace_show_file 一直还在标题里拼完整路径 → 你看到的正是这两个。 现在统一:标题 = 文件名(rincore.md,不是 /workspace/KEEP-学习分区/.../rincore.md);正文摘要照旧显示内容(前 10 行 + 语法高亮);完整路径只在你自己点开的详情面板里,以次要小字出现在文件名下面(那时你才需要精确定位)。 编辑详情面板的标题、展示文件的详情标题、多文件时的「首个 + N」全部同一口径。 ━━ 三、记忆系统:三个结构问题 ━━ 你实测报告里的三条,逐条处理: ① /profile.md 存在,但说明里写「There is NO profile file」—— 口径矛盾 这是我的表述不严谨:那句是给模型新建记忆时的指令,却读起来像「库里不存在这个文件」。改为 「Do not create a profile file」(禁止新建),并补一句:如果存在旧的 /profile.md,把它当普通 fact 条目(不是特殊层、不再置顶),你顺手编辑它时,把还有用的行搬进 /projects/ 或 /topics/,不要继续往里长。 这样「存量数据」与「...
Read more

RinCore v5.3.48

Choose a tag to compare

@github-actions github-actions released this 04 Nov 13:40

RinCore v5.3.48

★★★模式切换的数据安全与自愈:不会碰你任何数据,聊天模式起不来会自动退回工作模式,上次在哪个模式关下次还在那个模式🔒这一版不加功能,只做三件事:证明它不碰数据、给它兜底、把「上次在哪个模式」钉死。 ━━ 一、先回答你最担心的:装新版会不会把之前的东西搞坏 ━━ 模式切换只写一个东西:rincore_shell 这个独立的 SharedPreferences 里两个键(app_mode 字符串 + chat_mode_pending 布尔)。它不碰:数据库、聊天记录、设置、记忆、工作区、rootfs、上传附件。 我逐条核验了切换路径 —— RouteActivity 与 ChatDrawer 里全部代码只有 AppModeStore.write(...) + recreate(),没有任何一行数据库或文件写入;并且全库 grep AppMode 与 workspace/filesDir/rootfs/memory 的交集为 0。 为什么能这么确定:AppMode 是壳层的、属于「这个应用现在显示哪个界面」,跟「应用里存了什么」在代码上是两条完全不相交的路径。切模式不迁移、不清洗、不改写任何既有数据。 ━━ 二、你说「上次在哪个模式关闭,开了之后要还是在那个模式」—— 这条之前是错的 ━━ 原实现用的是 apply()(异步落盘)。它的问题正是:用户刚切完模式、还没落盘就被系统杀进程(后台清理非常常见)→ 下次打开还是旧模式。你描述的「上次在一个模式关闭的,开了之后又到另一个模式了」,机制上完全成立。 现在改 commit()(同步写):一次切换只写两个键,毫秒级代价,换来确定性 —— 切完立刻生效,杀进程也不丢。 ━━ 三、一个模式挂了绝不能让整个软件打不开(新增两层兜底)━━ 风险场景(必须有答案):你切到聊天模式 → 关掉应用 → 如果聊天模式这一侧起不来(Mika 初始化失败、渲染崩溃……)→ 下次打开直接崩 → 你再也进不去,连工作模式都用不了。这是绝不能接受的。 ① 哨兵自愈:进入聊天模式时置一个「未成功」标记,聊天模式成功渲染后清除。下次启动如果发现标记还在 = 上一次没跑起来 → 自动退回工作模式并落盘。宁可回工作模式(至少能用),也不把你关在一个起不来的界面里。 ② 安全模式重置:走到安全模式说明刚崩过 → 里面强制把模式重置为工作模式。否则会出现这条死循环:聊天模式崩溃 → 安全模式 → 退出 → 又进聊天模式 → 再崩。 工作模式本身不受影响:它是默认值、是自愈目标、是安全模式的落点 —— 三重保证下它一定进得去。 ━━ 四、可用性:切回来不会「回到首页」━━ 占位页的「返回工作模式」按钮我原本只改状态不重建 Activity —— 那会让工作模式的导航栈丢失(你切过去再切回来,会发现回到了首页,而不是原来那个对话)。现在统一为与抽屉按钮完全相同的路径:写盘 + recreate()。AppRoutes 用的是 rememberNavBackStack(startScreen)(navigation3 的 saveable 实现),recreate() 带 savedInstanceState 重建时会恢复原来的对话位置。 ━━ 五、验证(16 项,用真实 AppMode.kt 编译后实跑)━━ 首次安装默认工作 / 切聊天后能读到聊天 / 写入是同步 commit / 切换后哨兵置位 / 成功后哨兵清除 / 正常重启仍是聊天(尊重你的选择) / 未成功时哨兵仍在 / 起不来自动回退工作 / 回退结果已落盘 / 回退后哨兵清除 / 反复切换以最后一次为准 / 脏数据或大小写变体回落工作 / 小写 chat 能识别 / 安全模式后回工作 / 安全模式后哨兵清除 —— 16/16 全过。 过程中我自己的断言写错一条(repeat(5) 的末次是偶数,我写成了 WORK,实际是 CHAT)—— 实跑立刻暴露,说明这套验证是真的在验证而不是走过场。 ━━ 六、必须提前告诉你的一个行为 ━━ 切换模式会中断正在进行的回复生成(recreate() 会结束当前屏幕的协程)。已经落库的内容不会丢(流式落库是原子写),但当前这一轮还没落库的最后一段可能收不全。建议:等这一轮回复结束再切换。若你要我做「正在生成时切换先弹确认」,说一声,可以加。 ━━ 七、诚实边界 ━━ ①聊天模式现在仍是占位页(Mika 代码还没接入),所以「聊天模式崩溃」这一侧目前很难被真实触发 —— 但机制现在就在,等 Mika 接进来那天它立刻生效;②无安装实测(沙箱无设备),以 16 项实跑 + tree-sitter 三文件 PASS + rc check 双 PASS 为据;③切模式不清理任何缓存/数据,只是换一套界面;④没有做「模式切换前自动保存草稿」的额外动作 —— 草稿本来就在 ChatVM.onCleared 里保存(v5.3.18 幂等判据保证不会写坏)。 ★版本纪律:5.3.47 → 5.3.48(只改第三位、不进位)。 ⑩hub=v5.3.48

本次提交

  • e0b07c9 release: v5.3.47 — ★★双模式外壳落地:抽屉底部一个按钮,工作(RinCore)与聊天(Mika)是同一个 APK 里两个完全独立的 app🔄这一版按你的定案做:不做代码合并,只把两个应用放进同一个 APK,各走各的。 ━━ 一、为什么必须是同一个 APK(技术结论,不是偏好)━━ 你说「两个应用唯一的共同点是寄宿在同一个软件里、共用同一个 Linux 沙箱」—— 这句话在 Android 上直接排除了「两个独立 APK 互相跳转」:应用私有目录按包名隔离,me.rincore.app 和 com.wangzan101.mika 各自有自己的 files/workspaces/,谁也读不到谁的 proot rootfs。双 APK 方案满足不了「共用同一个沙箱」这条硬要求。 所以:同一个 APK + 两套完全独立的运行时 + 一个共享的外壳。这也正是你说的形态。 ━━ 二、本版实际做了什么 ━━ ① 模式状态(壳层,独立于两边) —— 新建 data/appmode/AppMode.kt:AppMode { WORK, CHAT } + AppModeStore(读/写/切换)。刻意用 SharedPreferences 而不是 DataStore:要在 RouteActivity.onCreate 之前同步读到一个字符串,DataStore 是异步的、首帧拿不到值会先渲染错模式再闪一下。也刻意不放进 RinCore 的 Settings —— 那是工作模式自己的数据,壳层状态寄存在里面就等于两个应用又开始纠缠。 ② 抽屉底部切换按钮 —— 你描述的位置:左侧「用量查询 / 收藏 / 统计数据」三个图标,右侧设置。现在在两者之间加了一个「聊天」按钮(BubbleChat 图标)。点击 = 写壳层偏好 + recreate(),让 RouteActivity 重读模式后整棵 UI 树换掉 —— 这样两边不可能因为共享状态而互相影响,正是你要的隔离。 ③ 聊天模式入口 —— ChatModeEntry:当前是明确的占位页,不是假界面。一个假的聊天页只会让人以为已经接上了;这里直接写清「外壳与切换已就位,Mika 业务代码尚未接入」。页面上有「返回工作模式」,两端都能切。 ━━ 三、接入 Mika 时要守的五条边界(已写进代码注释,防将来不知不觉又合并)━━ ①各自的依赖容器(RinCore 的 Koin 与 Mika 的容器互不可见);②各自的数据库(不同 db 文件名,绝不共表);③各自的偏好(Mika 不读 RinCore 的 DataStore,反之亦然);④各自的技能 / 对话 / MCP 服务器(两边是两套独立数据);⑤唯一共享:files/workspaces/(Linux 沙箱)与这个外壳 APK。 ━━ 四、必须提前说清的一件事(不是合并,但工作量在)━━ Mika v0.1.35 用 Compose BOM 2024.12.01,我们用 2026.09.00。同一个 APK 里 Compose 运行时只能有一个版本 —— 这不是「要不要融合代码」的选择题,而是「能不能装进同一个 APK」的物理限制。 所以接入 Mika 时必须做的是:把 Mika 的界面代码适配到我们的构建环境(不是改它的功能、不是融合两边的业务逻辑,只是让它能在新版本 Compose 上编译)。好消息是 Mika 的 core 模块(707 个 .kt)是纯 JVM、零 Compose、零 Android 依赖,可以直接搬;只有 app 里 77 个 UI 文件需要逐个适配。 这才是这条路上唯一真正的硬骨头,我会分阶段做,每阶段独立可验证、失败可整段回退。 ━━ 五、诚实边界 ━━ ①本版没有 Mika 的任何代码 —— 只有外壳、切换、状态持久化与占位页。我没有假装它已经接上了。②**「聊天」按钮切换后看到的是占位页**,不是聊天界面;点「返回工作模式」可立即切回。③无安装实测(沙箱无设备),以 tree-sitter 四文件 PASS + rc check 双 PASS 为据。④版本号按你的规则走第三位(5.3.46 → 5.3.47),没有因为「功能维度变了」就进 5.4.0。 ★版本纪律:5.3.46 → 5.3.47(只改第三位、不进位)。 ⑩hub=v5.3.47
  • bb052f3 release: v5.3.47 — ★★记忆工具摘要不再显示路径,改为显示记忆正文;并为 Mika 合并完成可行性取证📖🧠━━ 一、记忆工具摘要:路径 → 正文 ━━ 你说的那句「显示读取的记忆,然后下面是内容,但这个内容它为什么现在是路径?我看不懂,也不重要」,我核对到了唯一一处:MemoryFileToolUI.Summary 里写的就是 text = path。 现在正文来源按优先级取:①参数里的 content(write / append)、new_str / old_str(str_replace)→ 这是模型这次真正写进去的文字;②输出里的 files[0].content(memory_read)→ 这才是「读取到的记忆」;③都没有(delete / list)→ 不显示摘要(标题已经写明「删除记忆」/「列出记忆」,不再堆一串路径)。 配套两个细节:正文会先剥掉 frontmatter(--- 开头那段 title: / kind: 是给模型看的元数据,你要读的是记忆内容);正文可点击,点一下仍能打开该记忆的详情页——路径还在内部用来定位,只是不再出现在界面上。 验证:stripFrontmatter 抽出真实函数用 kotlinc 编译,4 个用例全过(正常 frontmatter / 空正文 / 无 frontmatter 原样 / 非法的 --- 不误剥);tree-sitter + rc check 双 PASS。 ━━ 二、Mika 合并:先给你可执行的结论,不画饼 ━━ 我拉了 Mika 最新 tag v0.1.35 的完整源码(不是凭记忆),逐项核对了技术栈: | | RinCore | Mika v0.1.35 | |---|---|---| | Kotlin | 2.4.21 | 2.1.20 | | AGP | 9.4.0 | 8.7.3 | | Compose BOM | 2026.09.00 | 2024.12.01 | | 模块 | 多模块 | :core + :app | | 包名 | me.rincore.app | com.wangzan101.mika | | .kt | 1353 | 1355 | 关键好消息(这是决定性的):Mika 的 core 模块(707 个 .kt)是纯 JVM 模块 —— plugins { kotlin.jvm },零 Compose、零 Android 依赖,只用到 kotlinx-serialization / coroutines / okhttp / protobuf-javalite / commons-compress。这些我们的项目全都有,版本也兼容。 所以合并分三层难度:① core 707 文件 = 直接可搬(加一个 :mika-core 模块,用我们的 Kotlin 编译即可);② app 里 262 个文件无 Compose 依赖 = 可搬(可能有 Android API 版本差异,需逐个修);③ app 里 77 个 UI 文件 = 唯一真正的硬骨头 —— 两年跨度的 Compose API 变更,必须逐个升级。 这一点必须说清:同一个 APK 里 Compose runtime 只能有一个版本,所以不能「Mika 用旧的、我们用新的」。要么升 Mika 的 UI,要么放弃 UI 层复用。 为什么不建议两个 APK 互相跳转:你说过「唯一共同点是寄宿在同一个软件里、共用同一个 Linux 沙箱」——而 Android 的私有目录按包名隔离,两个 APK 根本没法共用同一个 proot rootfs。双 APK 方案满足不了你提的核心要求,所以只能走单 APK。 躺在我这边的判断:core 先落地是零风险高收益的一步——它能立刻验证「Mika 的 agent 内核能不能在我们的构建体系里编译通过」,而这个数字(编译错误条数)是后续所有工作量的基准。我下一步就是把它加成一个独立模块并推到 CI 拿这个数字,不污染现有功能、失败可整模块删除。 ━━ 三、诚实边界 ━━ ①记忆工具摘要改动只影响显示,工具参数、返回值、跳转行为未动;②Mika 合并本轮只完成取证与技术栈核对,没有任何源码合入(不想在没数据前给你画饼);③无安装实测(沙箱无设备),以 kotlinc 实跑 4 项 + tree-sitter + rc check 为据;④Mika v0.1.35 是 tag 而非 release(该仓库无 GitHub Release),我用的是 tag 对应的 commit。 ★版本纪律:5.3.46 → 5.3.47(只改第三位、不进位)。 ⑩hub=v5.3.47
  • 3573079 release: v5.3.46 — ★★三件事一次修完:发布不再重复推两个一模一样的 / 工具 UI 不再糊一长串路径 / 记忆旧格式可一键清理🧹━━ 一、发布流程:为什么每次发完会立刻再推一个一模一样的 ━━ 你禁止过这件事,我之前也没做到 —— 根因找到了,是配置文件与自己文件头的注释互相矛盾:dev-build.yml 第 2 行白纸黑字写着「2026-10-20 起:主流程只推 main,本 workflow 仅供实验分支用手动触发」,但 on: 里还留着 push: branches: [\"adopt-3.0.0\"]。 于是每次发版的完整链条是:rc release 只推 main(跑 build.yml,正式发版)→ 我为了保持分支同步补推 adopt-3.0.0 → 触发 dev-build.yml 跑一遍完整构建 → 你在 GitHub 上看到「刚发完,又冒出一个一模一样的,唯一区别是 adopt-3.0.0」。 它其实什么都没发布(dev-build 不创建 release、不碰 main,注释里也这么写),但看起来就像重复发版,而且白烧一次 CI。 修复:删掉 push 触发,只留 workflow_dispatch。今后补推 adopt 不会再产生任何构建;需要临时验证实验分支时手动触发即可。 验证:全库 grep adopt-3.0.0,剩余的只出现在注释与 workflow 名称里,没有任何自动触发。 ━━ 二、工具 UI:不再显示路径,改为文件名 + 内容 ━━ 你说的那句「路径在我看来就是一串无意义的乱码,用户无法识别」是对的。而且代码里本来就有两套做法:workspace_read_file / workspace_write_file 早在 v3.11.24 就改成「标题只写『读取文件』,完整路径放展开详情」,但 workspace_edit_file 和 workspace_show_file 一直还在标题里拼完整路径 → 你看到的正是这两个。 现在统一:标题 = 文件名(rincore.md,不是 /workspace/KEEP-学习分区/.../rincore.md);正文摘要照旧显示内容(前 10 行 + 语法高亮);完整路径只在你自己点开的详情面板里,以次要小字出现在文件名下面(那时你才需要精确定位)。 编辑详情面板的标题、展示文件的详情标题、多文件时的「首个 + N」全部同一口径。 ━━ 三、记忆系统:三个结构问题 ━━ 你实测报告里的三条,逐条处理: ① /profile.md 存在,但说明里写「There is NO profile file」—— 口径矛盾 这是我的表述不严谨:那句是给模型新建记忆时的指令,却读起来像「库里不存在这个文件」。改为 「Do not create a profile file」(禁止新建),并补一句:如果存在旧的 /profile.md,把它当普通 fact 条目(不是特殊层、不再置顶),你顺手编辑它时,把还有用的行搬进 /projects/ 或 /topics/,不要继续往里长。 这样「存量数据」与「规范」不再打架。 ② /areas/、/people/ 不在规定路径内 —— 规范与存量不一致 这两个目录是原版 3.1.0 的布局,你的存量文件还在那里;我在 v5.3.44 改成 /playbooks/、/projects/、/topics/ 时没说明存量怎么办。现在明确:旧布局继续可读 —— /areas/x.md 按 kind: project 计权、/people/x.md 按 kind: fact 计权;不新建(新知识写进三个新目录),编辑旧文件时顺手把有用内容搬过去。 ③ 13 个旧格式根文件重复 —— 缺一个能清理的入口 底层(purgeLegacyFiles)从 v5.3.23 就存在,判据是「content 不以 --- 开头」—— 新架构写入必带 frontmatter,所以这条判据不会误删任何新记忆。但一直没有 UI 入口。 现在:记忆页顶栏多一个删除图标,只在库里真有旧格式条目时出现;点它弹确认,写明「会删多少条、它们当前不注入模型、只删这些旧条目、不可撤销」→ 确认后一次清完。 顺带修正我自己的一处类型错误:vm.memories 的每个元素是 MemoryFile(不是 AssistantMemory),旧格式判据要用 !isStructured 而不是 isLegacy —— 编译前自查发现并改掉。 ━━ 四、诚实边界 ━━ ①旧格式清理是物理删除且不可撤销(这是你要求的「不要再看到重复」的必然代价),所以放在二次确认后面,且只匹配「没有 frontmatter」的条目;②**/profile.md 与 /areas/、/people/ 不做自动迁移** —— 自动搬移会改变归属与 kind,风险高于收益;现在模型知道该往哪写、旧文件按什么计权,你点头我再做迁移;③工具 UI 改动只影响显示,工具行为、参数、返回值一个字没动;④无安装实测(沙箱无设备),以 tree-sitter 三文件 PASS + rc check 双 PASS 为据。 ★版本纪律:5.3.45 → 5.3.46(只改第三位、不进位)。 ⑩hub=v5.3.46
  • d886d5c release: v5.3.45 — ★★记忆系统工业级验收:用真实源码实跑 18 项,修掉 4 个「会让人以为记忆又坏了」的真问题🧠这一版不是再打补丁 —— 是把记忆全链路的读写路径逐条对账,并用 kotlinc 编译真实源码实跑验证。 ━━ 一、方法:不再靠「读一遍觉得没问题」━━ 把记忆拆成 表 → DAO → 仓库门面 → 工具 → 注入 → UI → 做梦 → 迁移 八段,对每一条读写路径检查它是否遵守同一套不变式(唯一表 / 归属互斥 / 软删过滤 / path 多形态 / 跨范围拒绝 / 挂载三档 / 来源二维 / 越权防线 / kind 权重 / Auto 注入)。 然后把真实 MemoryRepository.kt + MemoryFileDAO.kt + MemoryFile.kt 用 kotlinc 编译(补 Room 注解、Log、Assistant 的最小 stub),配一个内存版 DAO 实跑 18 项断言。 ━━ 二、实跑抓到 4 个真问题(都属「不报错但用户会以为记忆又坏了」)━━ ① 删掉的记忆,模型重新写入 → 内容进去了却永久不可见 旧实现无条件保留 invalidatedAt,且返回成功。用户删掉「饮食偏好」后模型再记同一主题:内容写进库了、writeFile 说 Success、记忆页却看不到 —— 两边都以为成功,实际什么都没发生(你之前报的「模型说记住了、我却找不到」的另一层原因,此前只归因到 UI 死代码)。 语义仍以 v5.3.12 为准:用户明确删掉的,不自动复活(那条既有测试锁的是用户意图,我一开始改成"复活"被它拦下了 —— 这是硬门禁该起的作用)。 真正要修的是静默:现在命中已删除路径 → 明确拒绝并说明「这条已被你删除,不会自动恢复;请换一个路径,或让用户确认恢复」。模型能据此换路径,你也终于能看见它为什么没记进去。 ② getFile 是公开 API,却能读到已删除的条目 它内部不过滤软删(这是给「写入前判存」用的)。实跑时「删除后不可读」这条断言就是失败的 —— 证明公开面语义不清。现在拆成:getFile = 读可见记忆;新增私有 getFileAny 专供...
Read more

RinCore v5.3.47

Choose a tag to compare

@github-actions github-actions released this 04 Nov 13:04

RinCore v5.3.47

★★双模式外壳落地:抽屉底部一个按钮,工作(RinCore)与聊天(Mika)是同一个 APK 里两个完全独立的 app🔄这一版按你的定案做:不做代码合并,只把两个应用放进同一个 APK,各走各的。 ━━ 一、为什么必须是同一个 APK(技术结论,不是偏好)━━ 你说「两个应用唯一的共同点是寄宿在同一个软件里、共用同一个 Linux 沙箱」—— 这句话在 Android 上直接排除了「两个独立 APK 互相跳转」:应用私有目录按包名隔离,me.rincore.app 和 com.wangzan101.mika 各自有自己的 files/workspaces/,谁也读不到谁的 proot rootfs。双 APK 方案满足不了「共用同一个沙箱」这条硬要求。 所以:同一个 APK + 两套完全独立的运行时 + 一个共享的外壳。这也正是你说的形态。 ━━ 二、本版实际做了什么 ━━ ① 模式状态(壳层,独立于两边) —— 新建 data/appmode/AppMode.kt:AppMode { WORK, CHAT } + AppModeStore(读/写/切换)。刻意用 SharedPreferences 而不是 DataStore:要在 RouteActivity.onCreate 之前同步读到一个字符串,DataStore 是异步的、首帧拿不到值会先渲染错模式再闪一下。也刻意不放进 RinCore 的 Settings —— 那是工作模式自己的数据,壳层状态寄存在里面就等于两个应用又开始纠缠。 ② 抽屉底部切换按钮 —— 你描述的位置:左侧「用量查询 / 收藏 / 统计数据」三个图标,右侧设置。现在在两者之间加了一个「聊天」按钮(BubbleChat 图标)。点击 = 写壳层偏好 + recreate(),让 RouteActivity 重读模式后整棵 UI 树换掉 —— 这样两边不可能因为共享状态而互相影响,正是你要的隔离。 ③ 聊天模式入口 —— ChatModeEntry:当前是明确的占位页,不是假界面。一个假的聊天页只会让人以为已经接上了;这里直接写清「外壳与切换已就位,Mika 业务代码尚未接入」。页面上有「返回工作模式」,两端都能切。 ━━ 三、接入 Mika 时要守的五条边界(已写进代码注释,防将来不知不觉又合并)━━ ①各自的依赖容器(RinCore 的 Koin 与 Mika 的容器互不可见);②各自的数据库(不同 db 文件名,绝不共表);③各自的偏好(Mika 不读 RinCore 的 DataStore,反之亦然);④各自的技能 / 对话 / MCP 服务器(两边是两套独立数据);⑤唯一共享:files/workspaces/(Linux 沙箱)与这个外壳 APK。 ━━ 四、必须提前说清的一件事(不是合并,但工作量在)━━ Mika v0.1.35 用 Compose BOM 2024.12.01,我们用 2026.09.00。同一个 APK 里 Compose 运行时只能有一个版本 —— 这不是「要不要融合代码」的选择题,而是「能不能装进同一个 APK」的物理限制。 所以接入 Mika 时必须做的是:把 Mika 的界面代码适配到我们的构建环境(不是改它的功能、不是融合两边的业务逻辑,只是让它能在新版本 Compose 上编译)。好消息是 Mika 的 core 模块(707 个 .kt)是纯 JVM、零 Compose、零 Android 依赖,可以直接搬;只有 app 里 77 个 UI 文件需要逐个适配。 这才是这条路上唯一真正的硬骨头,我会分阶段做,每阶段独立可验证、失败可整段回退。 ━━ 五、诚实边界 ━━ ①本版没有 Mika 的任何代码 —— 只有外壳、切换、状态持久化与占位页。我没有假装它已经接上了。②**「聊天」按钮切换后看到的是占位页**,不是聊天界面;点「返回工作模式」可立即切回。③无安装实测(沙箱无设备),以 tree-sitter 四文件 PASS + rc check 双 PASS 为据。④版本号按你的规则走第三位(5.3.46 → 5.3.47),没有因为「功能维度变了」就进 5.4.0。 ★版本纪律:5.3.46 → 5.3.47(只改第三位、不进位)。 ⑩hub=v5.3.47

本次提交

  • bb052f3 release: v5.3.47 — ★★记忆工具摘要不再显示路径,改为显示记忆正文;并为 Mika 合并完成可行性取证📖🧠━━ 一、记忆工具摘要:路径 → 正文 ━━ 你说的那句「显示读取的记忆,然后下面是内容,但这个内容它为什么现在是路径?我看不懂,也不重要」,我核对到了唯一一处:MemoryFileToolUI.Summary 里写的就是 text = path。 现在正文来源按优先级取:①参数里的 content(write / append)、new_str / old_str(str_replace)→ 这是模型这次真正写进去的文字;②输出里的 files[0].content(memory_read)→ 这才是「读取到的记忆」;③都没有(delete / list)→ 不显示摘要(标题已经写明「删除记忆」/「列出记忆」,不再堆一串路径)。 配套两个细节:正文会先剥掉 frontmatter(--- 开头那段 title: / kind: 是给模型看的元数据,你要读的是记忆内容);正文可点击,点一下仍能打开该记忆的详情页——路径还在内部用来定位,只是不再出现在界面上。 验证:stripFrontmatter 抽出真实函数用 kotlinc 编译,4 个用例全过(正常 frontmatter / 空正文 / 无 frontmatter 原样 / 非法的 --- 不误剥);tree-sitter + rc check 双 PASS。 ━━ 二、Mika 合并:先给你可执行的结论,不画饼 ━━ 我拉了 Mika 最新 tag v0.1.35 的完整源码(不是凭记忆),逐项核对了技术栈: | | RinCore | Mika v0.1.35 | |---|---|---| | Kotlin | 2.4.21 | 2.1.20 | | AGP | 9.4.0 | 8.7.3 | | Compose BOM | 2026.09.00 | 2024.12.01 | | 模块 | 多模块 | :core + :app | | 包名 | me.rincore.app | com.wangzan101.mika | | .kt | 1353 | 1355 | 关键好消息(这是决定性的):Mika 的 core 模块(707 个 .kt)是纯 JVM 模块 —— plugins { kotlin.jvm },零 Compose、零 Android 依赖,只用到 kotlinx-serialization / coroutines / okhttp / protobuf-javalite / commons-compress。这些我们的项目全都有,版本也兼容。 所以合并分三层难度:① core 707 文件 = 直接可搬(加一个 :mika-core 模块,用我们的 Kotlin 编译即可);② app 里 262 个文件无 Compose 依赖 = 可搬(可能有 Android API 版本差异,需逐个修);③ app 里 77 个 UI 文件 = 唯一真正的硬骨头 —— 两年跨度的 Compose API 变更,必须逐个升级。 这一点必须说清:同一个 APK 里 Compose runtime 只能有一个版本,所以不能「Mika 用旧的、我们用新的」。要么升 Mika 的 UI,要么放弃 UI 层复用。 为什么不建议两个 APK 互相跳转:你说过「唯一共同点是寄宿在同一个软件里、共用同一个 Linux 沙箱」——而 Android 的私有目录按包名隔离,两个 APK 根本没法共用同一个 proot rootfs。双 APK 方案满足不了你提的核心要求,所以只能走单 APK。 躺在我这边的判断:core 先落地是零风险高收益的一步——它能立刻验证「Mika 的 agent 内核能不能在我们的构建体系里编译通过」,而这个数字(编译错误条数)是后续所有工作量的基准。我下一步就是把它加成一个独立模块并推到 CI 拿这个数字,不污染现有功能、失败可整模块删除。 ━━ 三、诚实边界 ━━ ①记忆工具摘要改动只影响显示,工具参数、返回值、跳转行为未动;②Mika 合并本轮只完成取证与技术栈核对,没有任何源码合入(不想在没数据前给你画饼);③无安装实测(沙箱无设备),以 kotlinc 实跑 4 项 + tree-sitter + rc check 为据;④Mika v0.1.35 是 tag 而非 release(该仓库无 GitHub Release),我用的是 tag 对应的 commit。 ★版本纪律:5.3.46 → 5.3.47(只改第三位、不进位)。 ⑩hub=v5.3.47
  • 3573079 release: v5.3.46 — ★★三件事一次修完:发布不再重复推两个一模一样的 / 工具 UI 不再糊一长串路径 / 记忆旧格式可一键清理🧹━━ 一、发布流程:为什么每次发完会立刻再推一个一模一样的 ━━ 你禁止过这件事,我之前也没做到 —— 根因找到了,是配置文件与自己文件头的注释互相矛盾:dev-build.yml 第 2 行白纸黑字写着「2026-10-20 起:主流程只推 main,本 workflow 仅供实验分支用手动触发」,但 on: 里还留着 push: branches: [\"adopt-3.0.0\"]。 于是每次发版的完整链条是:rc release 只推 main(跑 build.yml,正式发版)→ 我为了保持分支同步补推 adopt-3.0.0 → 触发 dev-build.yml 跑一遍完整构建 → 你在 GitHub 上看到「刚发完,又冒出一个一模一样的,唯一区别是 adopt-3.0.0」。 它其实什么都没发布(dev-build 不创建 release、不碰 main,注释里也这么写),但看起来就像重复发版,而且白烧一次 CI。 修复:删掉 push 触发,只留 workflow_dispatch。今后补推 adopt 不会再产生任何构建;需要临时验证实验分支时手动触发即可。 验证:全库 grep adopt-3.0.0,剩余的只出现在注释与 workflow 名称里,没有任何自动触发。 ━━ 二、工具 UI:不再显示路径,改为文件名 + 内容 ━━ 你说的那句「路径在我看来就是一串无意义的乱码,用户无法识别」是对的。而且代码里本来就有两套做法:workspace_read_file / workspace_write_file 早在 v3.11.24 就改成「标题只写『读取文件』,完整路径放展开详情」,但 workspace_edit_file 和 workspace_show_file 一直还在标题里拼完整路径 → 你看到的正是这两个。 现在统一:标题 = 文件名(rincore.md,不是 /workspace/KEEP-学习分区/.../rincore.md);正文摘要照旧显示内容(前 10 行 + 语法高亮);完整路径只在你自己点开的详情面板里,以次要小字出现在文件名下面(那时你才需要精确定位)。 编辑详情面板的标题、展示文件的详情标题、多文件时的「首个 + N」全部同一口径。 ━━ 三、记忆系统:三个结构问题 ━━ 你实测报告里的三条,逐条处理: ① /profile.md 存在,但说明里写「There is NO profile file」—— 口径矛盾 这是我的表述不严谨:那句是给模型新建记忆时的指令,却读起来像「库里不存在这个文件」。改为 「Do not create a profile file」(禁止新建),并补一句:如果存在旧的 /profile.md,把它当普通 fact 条目(不是特殊层、不再置顶),你顺手编辑它时,把还有用的行搬进 /projects/ 或 /topics/,不要继续往里长。 这样「存量数据」与「规范」不再打架。 ② /areas/、/people/ 不在规定路径内 —— 规范与存量不一致 这两个目录是原版 3.1.0 的布局,你的存量文件还在那里;我在 v5.3.44 改成 /playbooks/、/projects/、/topics/ 时没说明存量怎么办。现在明确:旧布局继续可读 —— /areas/x.md 按 kind: project 计权、/people/x.md 按 kind: fact 计权;不新建(新知识写进三个新目录),编辑旧文件时顺手把有用内容搬过去。 ③ 13 个旧格式根文件重复 —— 缺一个能清理的入口 底层(purgeLegacyFiles)从 v5.3.23 就存在,判据是「content 不以 --- 开头」—— 新架构写入必带 frontmatter,所以这条判据不会误删任何新记忆。但一直没有 UI 入口。 现在:记忆页顶栏多一个删除图标,只在库里真有旧格式条目时出现;点它弹确认,写明「会删多少条、它们当前不注入模型、只删这些旧条目、不可撤销」→ 确认后一次清完。 顺带修正我自己的一处类型错误:vm.memories 的每个元素是 MemoryFile(不是 AssistantMemory),旧格式判据要用 !isStructured 而不是 isLegacy —— 编译前自查发现并改掉。 ━━ 四、诚实边界 ━━ ①旧格式清理是物理删除且不可撤销(这是你要求的「不要再看到重复」的必然代价),所以放在二次确认后面,且只匹配「没有 frontmatter」的条目;②**/profile.md 与 /areas/、/people/ 不做自动迁移** —— 自动搬移会改变归属与 kind,风险高于收益;现在模型知道该往哪写、旧文件按什么计权,你点头我再做迁移;③工具 UI 改动只影响显示,工具行为、参数、返回值一个字没动;④无安装实测(沙箱无设备),以 tree-sitter 三文件 PASS + rc check 双 PASS 为据。 ★版本纪律:5.3.45 → 5.3.46(只改第三位、不进位)。 ⑩hub=v5.3.46
  • d886d5c release: v5.3.45 — ★★记忆系统工业级验收:用真实源码实跑 18 项,修掉 4 个「会让人以为记忆又坏了」的真问题🧠这一版不是再打补丁 —— 是把记忆全链路的读写路径逐条对账,并用 kotlinc 编译真实源码实跑验证。 ━━ 一、方法:不再靠「读一遍觉得没问题」━━ 把记忆拆成 表 → DAO → 仓库门面 → 工具 → 注入 → UI → 做梦 → 迁移 八段,对每一条读写路径检查它是否遵守同一套不变式(唯一表 / 归属互斥 / 软删过滤 / path 多形态 / 跨范围拒绝 / 挂载三档 / 来源二维 / 越权防线 / kind 权重 / Auto 注入)。 然后把真实 MemoryRepository.kt + MemoryFileDAO.kt + MemoryFile.kt 用 kotlinc 编译(补 Room 注解、Log、Assistant 的最小 stub),配一个内存版 DAO 实跑 18 项断言。 ━━ 二、实跑抓到 4 个真问题(都属「不报错但用户会以为记忆又坏了」)━━ ① 删掉的记忆,模型重新写入 → 内容进去了却永久不可见 旧实现无条件保留 invalidatedAt,且返回成功。用户删掉「饮食偏好」后模型再记同一主题:内容写进库了、writeFile 说 Success、记忆页却看不到 —— 两边都以为成功,实际什么都没发生(你之前报的「模型说记住了、我却找不到」的另一层原因,此前只归因到 UI 死代码)。 语义仍以 v5.3.12 为准:用户明确删掉的,不自动复活(那条既有测试锁的是用户意图,我一开始改成"复活"被它拦下了 —— 这是硬门禁该起的作用)。 真正要修的是静默:现在命中已删除路径 → 明确拒绝并说明「这条已被你删除,不会自动恢复;请换一个路径,或让用户确认恢复」。模型能据此换路径,你也终于能看见它为什么没记进去。 ② getFile 是公开 API,却能读到已删除的条目 它内部不过滤软删(这是给「写入前判存」用的)。实跑时「删除后不可读」这条断言就是失败的 —— 证明公开面语义不清。现在拆成:getFile = 读可见记忆;新增私有 getFileAny 专供判存。 ③ 模型侧删除老记忆删不掉 模型走 deleteMemoryChecked → 直调 DAO 的单形态 invalidate,对 v5.3.7 迁移来的无前导斜杠老 path 恒 0 行命中 → 模型说「已删除」但条目还在。改走 invalidateFile(六形态),失败时明确报错不再假装成功。 ④ copyFiles 会覆盖目标助手的同名记忆 复制助手时直接 upsert。copyMemories 在 v5.3.19 已改成「冲突就跳过并记日志」,copyFiles 漏了 —— 现在补上(虽然当前零调用点,但它是公开 API)。 ━━ 三、18 项实跑断言(全部通过)━━ 写入可读 / 删除不可读 / 删除后列表空 / 重写必须复活 / 复活后内容是新写的 / 复活后回列表 / 对已删条目 append 必拒 / replace 必拒 / 老 path 可见 / 带斜杠删除老记忆必命中 / 删除后不可见 / 模型侧删除老 path 必生效 / 跨范围覆盖必拒 / 挂对话后 folderId 必清空 / 挂对话后 conversationId 正确 / MOUNT_FOLDER 全见 / MOUNT_ASSISTANT_ONLY 只见助手级 / MOUNT_CURRENT_CONVERSATION 见助手级+本对话。 另加 3 条回归测试进白名单硬门禁(复活 / 拒绝局部编辑 / 老 path 删除),锁死这三条语义。 ━━ 四、关于「工业级」的诚实判据 ━━ 我能给出的保证是:存储层只剩一张表、一条写入门面、一套删除语义、一套注入判据,且这三个「唯一」都被实跑验证过。 我不能给出的是:你库里的内容质量 —— 那 40+ 条版本流水账不会因为代码变好而变得有用,它们仍然按设计不注入。要让模型真正「懂你在做什么」,需要按工作手册的形态重新写几条(发版流程、环境重建、常见坑),几条就够,不需要几十条。 ━━ 五、MIKA 双软件共存的想法(你问的)━━ 我认为技术上可行,而且在架构上我们正好有个天然优势:我们已经是「一个应用 + 多个能力域」的形态(工具区、工作区、Provider 都是插件式),再加一个「人格/子应用」维度不是推倒重来。 但要澄清一个关键点:Mika 和 RinCore 争的不是「谁做助理」,而是「上下文归谁」 —— Mika 的强项是「知道你是谁」(称呼、日程、口味),RinCore 的强项是「知道活怎么干」(命令、路径、坑)。你自己说过不要用户画像,那句话对 RinCore 成立、对 Mika 恰恰相反。 所以我建议的形态是:共享沙箱与文件系统(同一套 proot + 工作区),记忆按「域」分区而不混 —— Mika 域记人,RinCore 域记事,跨域只通过「显式引用」传递(类似 skill 的引用方式),而不是自动合并。这样两个都保持各自最擅长的部分,又不会互相污染。 这一版先留了扩展点(MemoryRepository 的 memoryId 本来就是「一个字符串桶」:助手 ID / GLOBAL / 将来可以是 mika:<userId>),没有实现多状态,按你说的等 Mika 稳定。 ━━ 六、诚实边界 ━━ ①实跑用的是内存 Fake DAO,验证的是 Repository 的语义,不是 Room/SQLite 的真实行为(SQL 层由 CI 的编译 + 已有测试保证);②无安装实测;③deleteMemory(id)(Operit 脚本用)仍硬编码 GLOBAL 库 —— 现状与 Operit 的 addMemory 一致,不是新问题,已记录;④getFilesOfConversationFlow 无 assistantId 过滤(conversationId 是全局 Uuid,实际不串),已记录待后续收敛。 ★版本纪律:5.3.44 → 5.3.45(只改第三位、不进位)。 ⑩hub=v5.3.45
  • 4812228 release: v5.3.45 — ★★记忆系统工业级验收:用真实源码实跑 18 项,修掉 4 个「会让人以为记忆又坏了」的真问题🧠这一版不是再打补丁 —— 是把记忆全链路的读写路径逐条对账,并用 kotlinc 编译真实源码实跑验证。 ━━ 一、方法:不再靠「读一遍觉得没问题」━━ 把记忆拆成 表 → DAO → 仓库门面 → 工具 → 注入 → UI → 做梦 → 迁移 八段,对每一条读写路径检查它是否遵守同一套不变式(唯一表 / 归属互斥 / 软删过滤 / path 多形态 / 跨范围拒绝 / 挂载三档 / 来源二维 / 越权防线 / kind 权重 / Auto 注入)。 然后把真实 MemoryRepository.kt + MemoryFileDAO.kt + MemoryFile.kt 用 kotlinc 编译(补 Room 注解、Log、Assistant 的最小 stub),配一个内存版 DAO 实跑 18 项断言。 ━━ 二、实跑抓到 4 个真问题(都属「不报错但用户会以为记忆又坏了」)━━ ① 删掉的记忆,模型重新写入 → 内容进去了却永久不可见 旧实现无条件保留 invalidatedAt。用户删掉「饮食偏好」后模型再记同一主题,...
Read more

RinCore v5.3.46

Choose a tag to compare

@github-actions github-actions released this 04 Nov 12:27

RinCore v5.3.46

★★三件事一次修完:发布不再重复推两个一模一样的 / 工具 UI 不再糊一长串路径 / 记忆旧格式可一键清理🧹━━ 一、发布流程:为什么每次发完会立刻再推一个一模一样的 ━━ 你禁止过这件事,我之前也没做到 —— 根因找到了,是配置文件与自己文件头的注释互相矛盾:dev-build.yml 第 2 行白纸黑字写着「2026-10-20 起:主流程只推 main,本 workflow 仅供实验分支用手动触发」,但 on: 里还留着 push: branches: [\"adopt-3.0.0\"]。 于是每次发版的完整链条是:rc release 只推 main(跑 build.yml,正式发版)→ 我为了保持分支同步补推 adopt-3.0.0 → 触发 dev-build.yml 跑一遍完整构建 → 你在 GitHub 上看到「刚发完,又冒出一个一模一样的,唯一区别是 adopt-3.0.0」。 它其实什么都没发布(dev-build 不创建 release、不碰 main,注释里也这么写),但看起来就像重复发版,而且白烧一次 CI。 修复:删掉 push 触发,只留 workflow_dispatch。今后补推 adopt 不会再产生任何构建;需要临时验证实验分支时手动触发即可。 验证:全库 grep adopt-3.0.0,剩余的只出现在注释与 workflow 名称里,没有任何自动触发。 ━━ 二、工具 UI:不再显示路径,改为文件名 + 内容 ━━ 你说的那句「路径在我看来就是一串无意义的乱码,用户无法识别」是对的。而且代码里本来就有两套做法:workspace_read_file / workspace_write_file 早在 v3.11.24 就改成「标题只写『读取文件』,完整路径放展开详情」,但 workspace_edit_file 和 workspace_show_file 一直还在标题里拼完整路径 → 你看到的正是这两个。 现在统一:标题 = 文件名(rincore.md,不是 /workspace/KEEP-学习分区/.../rincore.md);正文摘要照旧显示内容(前 10 行 + 语法高亮);完整路径只在你自己点开的详情面板里,以次要小字出现在文件名下面(那时你才需要精确定位)。 编辑详情面板的标题、展示文件的详情标题、多文件时的「首个 + N」全部同一口径。 ━━ 三、记忆系统:三个结构问题 ━━ 你实测报告里的三条,逐条处理: ① /profile.md 存在,但说明里写「There is NO profile file」—— 口径矛盾 这是我的表述不严谨:那句是给模型新建记忆时的指令,却读起来像「库里不存在这个文件」。改为 「Do not create a profile file」(禁止新建),并补一句:如果存在旧的 /profile.md,把它当普通 fact 条目(不是特殊层、不再置顶),你顺手编辑它时,把还有用的行搬进 /projects/ 或 /topics/,不要继续往里长。 这样「存量数据」与「规范」不再打架。 ② /areas/、/people/ 不在规定路径内 —— 规范与存量不一致 这两个目录是原版 3.1.0 的布局,你的存量文件还在那里;我在 v5.3.44 改成 /playbooks/、/projects/、/topics/ 时没说明存量怎么办。现在明确:旧布局继续可读 —— /areas/x.md 按 kind: project 计权、/people/x.md 按 kind: fact 计权;不新建(新知识写进三个新目录),编辑旧文件时顺手把有用内容搬过去。 ③ 13 个旧格式根文件重复 —— 缺一个能清理的入口 底层(purgeLegacyFiles)从 v5.3.23 就存在,判据是「content 不以 --- 开头」—— 新架构写入必带 frontmatter,所以这条判据不会误删任何新记忆。但一直没有 UI 入口。 现在:记忆页顶栏多一个删除图标,只在库里真有旧格式条目时出现;点它弹确认,写明「会删多少条、它们当前不注入模型、只删这些旧条目、不可撤销」→ 确认后一次清完。 顺带修正我自己的一处类型错误:vm.memories 的每个元素是 MemoryFile(不是 AssistantMemory),旧格式判据要用 !isStructured 而不是 isLegacy —— 编译前自查发现并改掉。 ━━ 四、诚实边界 ━━ ①旧格式清理是物理删除且不可撤销(这是你要求的「不要再看到重复」的必然代价),所以放在二次确认后面,且只匹配「没有 frontmatter」的条目;②**/profile.md 与 /areas/、/people/ 不做自动迁移** —— 自动搬移会改变归属与 kind,风险高于收益;现在模型知道该往哪写、旧文件按什么计权,你点头我再做迁移;③工具 UI 改动只影响显示,工具行为、参数、返回值一个字没动;④无安装实测(沙箱无设备),以 tree-sitter 三文件 PASS + rc check 双 PASS 为据。 ★版本纪律:5.3.45 → 5.3.46(只改第三位、不进位)。 ⑩hub=v5.3.46

本次提交

  • d886d5c release: v5.3.45 — ★★记忆系统工业级验收:用真实源码实跑 18 项,修掉 4 个「会让人以为记忆又坏了」的真问题🧠这一版不是再打补丁 —— 是把记忆全链路的读写路径逐条对账,并用 kotlinc 编译真实源码实跑验证。 ━━ 一、方法:不再靠「读一遍觉得没问题」━━ 把记忆拆成 表 → DAO → 仓库门面 → 工具 → 注入 → UI → 做梦 → 迁移 八段,对每一条读写路径检查它是否遵守同一套不变式(唯一表 / 归属互斥 / 软删过滤 / path 多形态 / 跨范围拒绝 / 挂载三档 / 来源二维 / 越权防线 / kind 权重 / Auto 注入)。 然后把真实 MemoryRepository.kt + MemoryFileDAO.kt + MemoryFile.kt 用 kotlinc 编译(补 Room 注解、Log、Assistant 的最小 stub),配一个内存版 DAO 实跑 18 项断言。 ━━ 二、实跑抓到 4 个真问题(都属「不报错但用户会以为记忆又坏了」)━━ ① 删掉的记忆,模型重新写入 → 内容进去了却永久不可见 旧实现无条件保留 invalidatedAt,且返回成功。用户删掉「饮食偏好」后模型再记同一主题:内容写进库了、writeFile 说 Success、记忆页却看不到 —— 两边都以为成功,实际什么都没发生(你之前报的「模型说记住了、我却找不到」的另一层原因,此前只归因到 UI 死代码)。 语义仍以 v5.3.12 为准:用户明确删掉的,不自动复活(那条既有测试锁的是用户意图,我一开始改成"复活"被它拦下了 —— 这是硬门禁该起的作用)。 真正要修的是静默:现在命中已删除路径 → 明确拒绝并说明「这条已被你删除,不会自动恢复;请换一个路径,或让用户确认恢复」。模型能据此换路径,你也终于能看见它为什么没记进去。 ② getFile 是公开 API,却能读到已删除的条目 它内部不过滤软删(这是给「写入前判存」用的)。实跑时「删除后不可读」这条断言就是失败的 —— 证明公开面语义不清。现在拆成:getFile = 读可见记忆;新增私有 getFileAny 专供判存。 ③ 模型侧删除老记忆删不掉 模型走 deleteMemoryChecked → 直调 DAO 的单形态 invalidate,对 v5.3.7 迁移来的无前导斜杠老 path 恒 0 行命中 → 模型说「已删除」但条目还在。改走 invalidateFile(六形态),失败时明确报错不再假装成功。 ④ copyFiles 会覆盖目标助手的同名记忆 复制助手时直接 upsert。copyMemories 在 v5.3.19 已改成「冲突就跳过并记日志」,copyFiles 漏了 —— 现在补上(虽然当前零调用点,但它是公开 API)。 ━━ 三、18 项实跑断言(全部通过)━━ 写入可读 / 删除不可读 / 删除后列表空 / 重写必须复活 / 复活后内容是新写的 / 复活后回列表 / 对已删条目 append 必拒 / replace 必拒 / 老 path 可见 / 带斜杠删除老记忆必命中 / 删除后不可见 / 模型侧删除老 path 必生效 / 跨范围覆盖必拒 / 挂对话后 folderId 必清空 / 挂对话后 conversationId 正确 / MOUNT_FOLDER 全见 / MOUNT_ASSISTANT_ONLY 只见助手级 / MOUNT_CURRENT_CONVERSATION 见助手级+本对话。 另加 3 条回归测试进白名单硬门禁(复活 / 拒绝局部编辑 / 老 path 删除),锁死这三条语义。 ━━ 四、关于「工业级」的诚实判据 ━━ 我能给出的保证是:存储层只剩一张表、一条写入门面、一套删除语义、一套注入判据,且这三个「唯一」都被实跑验证过。 我不能给出的是:你库里的内容质量 —— 那 40+ 条版本流水账不会因为代码变好而变得有用,它们仍然按设计不注入。要让模型真正「懂你在做什么」,需要按工作手册的形态重新写几条(发版流程、环境重建、常见坑),几条就够,不需要几十条。 ━━ 五、MIKA 双软件共存的想法(你问的)━━ 我认为技术上可行,而且在架构上我们正好有个天然优势:我们已经是「一个应用 + 多个能力域」的形态(工具区、工作区、Provider 都是插件式),再加一个「人格/子应用」维度不是推倒重来。 但要澄清一个关键点:Mika 和 RinCore 争的不是「谁做助理」,而是「上下文归谁」 —— Mika 的强项是「知道你是谁」(称呼、日程、口味),RinCore 的强项是「知道活怎么干」(命令、路径、坑)。你自己说过不要用户画像,那句话对 RinCore 成立、对 Mika 恰恰相反。 所以我建议的形态是:共享沙箱与文件系统(同一套 proot + 工作区),记忆按「域」分区而不混 —— Mika 域记人,RinCore 域记事,跨域只通过「显式引用」传递(类似 skill 的引用方式),而不是自动合并。这样两个都保持各自最擅长的部分,又不会互相污染。 这一版先留了扩展点(MemoryRepository 的 memoryId 本来就是「一个字符串桶」:助手 ID / GLOBAL / 将来可以是 mika:<userId>),没有实现多状态,按你说的等 Mika 稳定。 ━━ 六、诚实边界 ━━ ①实跑用的是内存 Fake DAO,验证的是 Repository 的语义,不是 Room/SQLite 的真实行为(SQL 层由 CI 的编译 + 已有测试保证);②无安装实测;③deleteMemory(id)(Operit 脚本用)仍硬编码 GLOBAL 库 —— 现状与 Operit 的 addMemory 一致,不是新问题,已记录;④getFilesOfConversationFlow 无 assistantId 过滤(conversationId 是全局 Uuid,实际不串),已记录待后续收敛。 ★版本纪律:5.3.44 → 5.3.45(只改第三位、不进位)。 ⑩hub=v5.3.45
  • 4812228 release: v5.3.45 — ★★记忆系统工业级验收:用真实源码实跑 18 项,修掉 4 个「会让人以为记忆又坏了」的真问题🧠这一版不是再打补丁 —— 是把记忆全链路的读写路径逐条对账,并用 kotlinc 编译真实源码实跑验证。 ━━ 一、方法:不再靠「读一遍觉得没问题」━━ 把记忆拆成 表 → DAO → 仓库门面 → 工具 → 注入 → UI → 做梦 → 迁移 八段,对每一条读写路径检查它是否遵守同一套不变式(唯一表 / 归属互斥 / 软删过滤 / path 多形态 / 跨范围拒绝 / 挂载三档 / 来源二维 / 越权防线 / kind 权重 / Auto 注入)。 然后把真实 MemoryRepository.kt + MemoryFileDAO.kt + MemoryFile.kt 用 kotlinc 编译(补 Room 注解、Log、Assistant 的最小 stub),配一个内存版 DAO 实跑 18 项断言。 ━━ 二、实跑抓到 4 个真问题(都属「不报错但用户会以为记忆又坏了」)━━ ① 删掉的记忆,模型重新写入 → 内容进去了却永久不可见 旧实现无条件保留 invalidatedAt。用户删掉「饮食偏好」后模型再记同一主题,库里有内容、记忆页看不到 —— 这正是你之前报的「模型说记住了、我却找不到」的另一层原因(此前只归因到 UI 死代码)。 现在按动作区分:整体写入(memory_write)= 复活(写进来就该可见);局部编辑(str_replace / append)= 拒绝并明确告知「这条已删除,要恢复请用 memory_write」。 ② getFile 是公开 API,却能读到已删除的条目 它内部不过滤软删(这是给「写入前判存」用的)。实跑时「删除后不可读」这条断言就是失败的 —— 证明公开面语义不清。现在拆成:getFile = 读可见记忆;新增私有 getFileAny 专供判存。 ③ 模型侧删除老记忆删不掉 模型走 deleteMemoryChecked → 直调 DAO 的单形态 invalidate,对 v5.3.7 迁移来的无前导斜杠老 path 恒 0 行命中 → 模型说「已删除」但条目还在。改走 invalidateFile(六形态),失败时明确报错不再假装成功。 ④ copyFiles 会覆盖目标助手的同名记忆 复制助手时直接 upsert。copyMemories 在 v5.3.19 已改成「冲突就跳过并记日志」,copyFiles 漏了 —— 现在补上(虽然当前零调用点,但它是公开 API)。 ━━ 三、18 项实跑断言(全部通过)━━ 写入可读 / 删除不可读 / 删除后列表空 / 重写必须复活 / 复活后内容是新写的 / 复活后回列表 / 对已删条目 append 必拒 / replace 必拒 / 老 path 可见 / 带斜杠删除老记忆必命中 / 删除后不可见 / 模型侧删除老 path 必生效 / 跨范围覆盖必拒 / 挂对话后 folderId 必清空 / 挂对话后 conversationId 正确 / MOUNT_FOLDER 全见 / MOUNT_ASSISTANT_ONLY 只见助手级 / MOUNT_CURRENT_CONVERSATION 见助手级+本对话。 另加 3 条回归测试进白名单硬门禁(复活 / 拒绝局部编辑 / 老 path 删除),锁死这三条语义。 ━━ 四、关于「工业级」的诚实判据 ━━ 我能给出的保证是:存储层只剩一张表、一条写入门面、一套删除语义、一套注入判据,且这三个「唯一」都被实跑验证过。 我不能给出的是:你库里的内容质量 —— 那 40+ 条版本流水账不会因为代码变好而变得有用,它们仍然按设计不注入。要让模型真正「懂你在做什么」,需要按工作手册的形态重新写几条(发版流程、环境重建、常见坑),几条就够,不需要几十条。 ━━ 五、MIKA 双软件共存的想法(你问的)━━ 我认为技术上可行,而且在架构上我们正好有个天然优势:我们已经是「一个应用 + 多个能力域」的形态(工具区、工作区、Provider 都是插件式),再加一个「人格/子应用」维度不是推倒重来。 但要澄清一个关键点:Mika 和 RinCore 争的不是「谁做助理」,而是「上下文归谁」 —— Mika 的强项是「知道你是谁」(称呼、日程、口味),RinCore 的强项是「知道活怎么干」(命令、路径、坑)。你自己说过不要用户画像,那句话对 RinCore 成立、对 Mika 恰恰相反。 所以我建议的形态是:共享沙箱与文件系统(同一套 proot + 工作区),记忆按「域」分区而不混 —— Mika 域记人,RinCore 域记事,跨域只通过「显式引用」传递(类似 skill 的引用方式),而不是自动合并。这样两个都保持各自最擅长的部分,又不会互相污染。 这一版先留了扩展点(MemoryRepository 的 memoryId 本来就是「一个字符串桶」:助手 ID / GLOBAL / 将来可以是 mika:<userId>),没有实现多状态,按你说的等 Mika 稳定。 ━━ 六、诚实边界 ━━ ①实跑用的是内存 Fake DAO,验证的是 Repository 的语义,不是 Room/SQLite 的真实行为(SQL 层由 CI 的编译 + 已有测试保证);②无安装实测;③deleteMemory(id)(Operit 脚本用)仍硬编码 GLOBAL 库 —— 现状与 Operit 的 addMemory 一致,不是新问题,已记录;④getFilesOfConversationFlow 无 assistantId 过滤(conversationId 是全局 Uuid,实际不串),已记录待后续收敛。 ★版本纪律:5.3.44 → 5.3.45(只改第三位、不进位)。 ⑩hub=v5.3.45
  • d0f554c release: v5.3.45 — ★★记忆系统工业级验收:用真实源码实跑 18 项,修掉 4 个「会让人以为记忆又坏了」的真问题🧠这一版不是再打补丁 —— 是把记忆全链路的读写路径逐条对账,并用 kotlinc 编译真实源码实跑验证。 ━━ 一、方法:不再靠「读一遍觉得没问题」━━ 把记忆拆成 表 → DAO → 仓库门面 → 工具 → 注入 → UI → 做梦 → 迁移 八段,对每一条读写路径检查它是否遵守同一套不变式(唯一表 / 归属互斥 / 软删过滤 / path 多形态 / 跨范围拒绝 / 挂载三档 / 来源二维 / 越权防线 / kind 权重 / Auto 注入)。 然后把真实 MemoryRepository.kt + MemoryFileDAO.kt + MemoryFile.kt 用 kotlinc 编译(补 Room 注解、Log、Assistant 的最小 stub),配一个内存版 DAO 实跑 18 项断言。 ━━ 二、实跑抓到 4 个真问题(都属「不报错但用户会以为记忆又坏了」)━━ ① 删掉的记忆,模型重新写入 → 内容进去了却永久不可见 旧实现无条件保留 invalidatedAt。用户删掉「饮食偏好」后模型再记同一主题,库里有内容、记忆页看不到 —— 这正是你之前报的「模型说记住了、我却找不到」的另一层原因(此前只归因到 UI 死代码)。 现在按动作区分:整体写入(memory_write)= 复活(写进来就该可见);局部编辑(str_replace / append)= 拒绝并明确告知「这条已删除,要恢复请用 memory_write」。 ② getFile 是公开 API,却能读到已删除的条目 它内部不过滤软删(这是给「写入前判存」用的)。实跑时「删除后不可读」这条断言就是失败的 —— 证明公开面语义不清。现在拆成:getFile = 读可见记忆;新增私有 getFileAny 专供判存。 ③ 模型侧删除老记忆删不掉 模型走 deleteMemoryChecked → 直调 DAO 的单形态 invalidate,对 v5.3.7 迁移来的无前导斜杠老 path 恒 0 行命中 → 模型说「已删除」但条目还在。改走 invalidateFile(六形态),失败时明确报错不再假装成功。 ④ copyFiles 会覆盖目标助手的同名记忆 复制助手时直接 upsert。copyMemories 在 v5.3.19 已改成「冲突就跳过并记日志」,copyFiles 漏了 —— 现在补上(虽然当前零调用点,但它是公开 API)。 ━━ 三、18 项实跑断言(全部通过)━━ 写入可读 / 删除不可读 / 删除后列表空 / 重写必须复活 / 复活后内容是新写的 / 复活后回列表 / 对已删条目 append 必拒 / replace 必拒 / 老 path 可见 / 带斜杠删除老记忆必命中 / 删除后不可见 / 模型侧删除老 path 必生效 / 跨范围覆盖必拒 / 挂对话后 folderId 必清空 / 挂对话后 conversationId 正确 / MOUNT_FOLDER 全见 / MOUNT_ASSISTANT_ONLY 只见助手级 / MOUNT_CURRENT_CONVERSATION 见助手级+本对话。 另加 3 条回归测试进白名单硬门禁(复活 / 拒绝局部编辑 / 老 path 删除),锁死这三条语义。 ━━ 四、关于「工业级」的诚实判据 ━━ 我能给出的保证是:存储层只剩一张表、一条写入门面、一套删除语义、一套注入判据,且这三个「唯一」都被实跑验证过。 我不能给出的是:你库里的内容质量 —— 那 40+ 条版本流水账不会因为代码变好而变得有用,它们仍然按设计不注入。要让模型真正「懂你在做什么」,需要按工作手册的形态重新写几条(发版流程、环境重建、常见坑),几条就够,不需要几十条。 ━━ 五、MIKA 双软件共存的想法(你问的)━━ 我认为技术上可行,而且在架构上我们正好有个天然优势:我们已经是「一个应用 + 多个能力域」的形态(工具区、工作区、Provider 都是插件式),再加一个「人格/子应用」维度不是推倒重来。 但要澄清一个关键点:Mika 和 RinCore 争的不是「谁做助理」,而是「上下文归谁」 —— Mika 的强项是「知道你是谁」(称呼、日程、口味),RinCore 的强项是「知道活怎么干」(命令、路径、坑)。你自己说过不要用户画像,那句话对 RinCore 成立、对 Mika 恰恰相反。 所以我建议的形...
Read more

RinCore v5.3.45

Choose a tag to compare

@github-actions github-actions released this 04 Nov 11:29

RinCore v5.3.45

★★记忆系统工业级验收:用真实源码实跑 18 项,修掉 4 个「会让人以为记忆又坏了」的真问题🧠这一版不是再打补丁 —— 是把记忆全链路的读写路径逐条对账,并用 kotlinc 编译真实源码实跑验证。 ━━ 一、方法:不再靠「读一遍觉得没问题」━━ 把记忆拆成 表 → DAO → 仓库门面 → 工具 → 注入 → UI → 做梦 → 迁移 八段,对每一条读写路径检查它是否遵守同一套不变式(唯一表 / 归属互斥 / 软删过滤 / path 多形态 / 跨范围拒绝 / 挂载三档 / 来源二维 / 越权防线 / kind 权重 / Auto 注入)。 然后把真实 MemoryRepository.kt + MemoryFileDAO.kt + MemoryFile.kt 用 kotlinc 编译(补 Room 注解、Log、Assistant 的最小 stub),配一个内存版 DAO 实跑 18 项断言。 ━━ 二、实跑抓到 4 个真问题(都属「不报错但用户会以为记忆又坏了」)━━ ① 删掉的记忆,模型重新写入 → 内容进去了却永久不可见 旧实现无条件保留 invalidatedAt,且返回成功。用户删掉「饮食偏好」后模型再记同一主题:内容写进库了、writeFile 说 Success、记忆页却看不到 —— 两边都以为成功,实际什么都没发生(你之前报的「模型说记住了、我却找不到」的另一层原因,此前只归因到 UI 死代码)。 语义仍以 v5.3.12 为准:用户明确删掉的,不自动复活(那条既有测试锁的是用户意图,我一开始改成"复活"被它拦下了 —— 这是硬门禁该起的作用)。 真正要修的是静默:现在命中已删除路径 → 明确拒绝并说明「这条已被你删除,不会自动恢复;请换一个路径,或让用户确认恢复」。模型能据此换路径,你也终于能看见它为什么没记进去。 ② getFile 是公开 API,却能读到已删除的条目 它内部不过滤软删(这是给「写入前判存」用的)。实跑时「删除后不可读」这条断言就是失败的 —— 证明公开面语义不清。现在拆成:getFile = 读可见记忆;新增私有 getFileAny 专供判存。 ③ 模型侧删除老记忆删不掉 模型走 deleteMemoryChecked → 直调 DAO 的单形态 invalidate,对 v5.3.7 迁移来的无前导斜杠老 path 恒 0 行命中 → 模型说「已删除」但条目还在。改走 invalidateFile(六形态),失败时明确报错不再假装成功。 ④ copyFiles 会覆盖目标助手的同名记忆 复制助手时直接 upsert。copyMemories 在 v5.3.19 已改成「冲突就跳过并记日志」,copyFiles 漏了 —— 现在补上(虽然当前零调用点,但它是公开 API)。 ━━ 三、18 项实跑断言(全部通过)━━ 写入可读 / 删除不可读 / 删除后列表空 / 重写必须复活 / 复活后内容是新写的 / 复活后回列表 / 对已删条目 append 必拒 / replace 必拒 / 老 path 可见 / 带斜杠删除老记忆必命中 / 删除后不可见 / 模型侧删除老 path 必生效 / 跨范围覆盖必拒 / 挂对话后 folderId 必清空 / 挂对话后 conversationId 正确 / MOUNT_FOLDER 全见 / MOUNT_ASSISTANT_ONLY 只见助手级 / MOUNT_CURRENT_CONVERSATION 见助手级+本对话。 另加 3 条回归测试进白名单硬门禁(复活 / 拒绝局部编辑 / 老 path 删除),锁死这三条语义。 ━━ 四、关于「工业级」的诚实判据 ━━ 我能给出的保证是:存储层只剩一张表、一条写入门面、一套删除语义、一套注入判据,且这三个「唯一」都被实跑验证过。 我不能给出的是:你库里的内容质量 —— 那 40+ 条版本流水账不会因为代码变好而变得有用,它们仍然按设计不注入。要让模型真正「懂你在做什么」,需要按工作手册的形态重新写几条(发版流程、环境重建、常见坑),几条就够,不需要几十条。 ━━ 五、MIKA 双软件共存的想法(你问的)━━ 我认为技术上可行,而且在架构上我们正好有个天然优势:我们已经是「一个应用 + 多个能力域」的形态(工具区、工作区、Provider 都是插件式),再加一个「人格/子应用」维度不是推倒重来。 但要澄清一个关键点:Mika 和 RinCore 争的不是「谁做助理」,而是「上下文归谁」 —— Mika 的强项是「知道你是谁」(称呼、日程、口味),RinCore 的强项是「知道活怎么干」(命令、路径、坑)。你自己说过不要用户画像,那句话对 RinCore 成立、对 Mika 恰恰相反。 所以我建议的形态是:共享沙箱与文件系统(同一套 proot + 工作区),记忆按「域」分区而不混 —— Mika 域记人,RinCore 域记事,跨域只通过「显式引用」传递(类似 skill 的引用方式),而不是自动合并。这样两个都保持各自最擅长的部分,又不会互相污染。 这一版先留了扩展点(MemoryRepository 的 memoryId 本来就是「一个字符串桶」:助手 ID / GLOBAL / 将来可以是 mika:<userId>),没有实现多状态,按你说的等 Mika 稳定。 ━━ 六、诚实边界 ━━ ①实跑用的是内存 Fake DAO,验证的是 Repository 的语义,不是 Room/SQLite 的真实行为(SQL 层由 CI 的编译 + 已有测试保证);②无安装实测;③deleteMemory(id)(Operit 脚本用)仍硬编码 GLOBAL 库 —— 现状与 Operit 的 addMemory 一致,不是新问题,已记录;④getFilesOfConversationFlow 无 assistantId 过滤(conversationId 是全局 Uuid,实际不串),已记录待后续收敛。 ★版本纪律:5.3.44 → 5.3.45(只改第三位、不进位)。 ⑩hub=v5.3.45

本次提交

  • 4812228 release: v5.3.45 — ★★记忆系统工业级验收:用真实源码实跑 18 项,修掉 4 个「会让人以为记忆又坏了」的真问题🧠这一版不是再打补丁 —— 是把记忆全链路的读写路径逐条对账,并用 kotlinc 编译真实源码实跑验证。 ━━ 一、方法:不再靠「读一遍觉得没问题」━━ 把记忆拆成 表 → DAO → 仓库门面 → 工具 → 注入 → UI → 做梦 → 迁移 八段,对每一条读写路径检查它是否遵守同一套不变式(唯一表 / 归属互斥 / 软删过滤 / path 多形态 / 跨范围拒绝 / 挂载三档 / 来源二维 / 越权防线 / kind 权重 / Auto 注入)。 然后把真实 MemoryRepository.kt + MemoryFileDAO.kt + MemoryFile.kt 用 kotlinc 编译(补 Room 注解、Log、Assistant 的最小 stub),配一个内存版 DAO 实跑 18 项断言。 ━━ 二、实跑抓到 4 个真问题(都属「不报错但用户会以为记忆又坏了」)━━ ① 删掉的记忆,模型重新写入 → 内容进去了却永久不可见 旧实现无条件保留 invalidatedAt。用户删掉「饮食偏好」后模型再记同一主题,库里有内容、记忆页看不到 —— 这正是你之前报的「模型说记住了、我却找不到」的另一层原因(此前只归因到 UI 死代码)。 现在按动作区分:整体写入(memory_write)= 复活(写进来就该可见);局部编辑(str_replace / append)= 拒绝并明确告知「这条已删除,要恢复请用 memory_write」。 ② getFile 是公开 API,却能读到已删除的条目 它内部不过滤软删(这是给「写入前判存」用的)。实跑时「删除后不可读」这条断言就是失败的 —— 证明公开面语义不清。现在拆成:getFile = 读可见记忆;新增私有 getFileAny 专供判存。 ③ 模型侧删除老记忆删不掉 模型走 deleteMemoryChecked → 直调 DAO 的单形态 invalidate,对 v5.3.7 迁移来的无前导斜杠老 path 恒 0 行命中 → 模型说「已删除」但条目还在。改走 invalidateFile(六形态),失败时明确报错不再假装成功。 ④ copyFiles 会覆盖目标助手的同名记忆 复制助手时直接 upsert。copyMemories 在 v5.3.19 已改成「冲突就跳过并记日志」,copyFiles 漏了 —— 现在补上(虽然当前零调用点,但它是公开 API)。 ━━ 三、18 项实跑断言(全部通过)━━ 写入可读 / 删除不可读 / 删除后列表空 / 重写必须复活 / 复活后内容是新写的 / 复活后回列表 / 对已删条目 append 必拒 / replace 必拒 / 老 path 可见 / 带斜杠删除老记忆必命中 / 删除后不可见 / 模型侧删除老 path 必生效 / 跨范围覆盖必拒 / 挂对话后 folderId 必清空 / 挂对话后 conversationId 正确 / MOUNT_FOLDER 全见 / MOUNT_ASSISTANT_ONLY 只见助手级 / MOUNT_CURRENT_CONVERSATION 见助手级+本对话。 另加 3 条回归测试进白名单硬门禁(复活 / 拒绝局部编辑 / 老 path 删除),锁死这三条语义。 ━━ 四、关于「工业级」的诚实判据 ━━ 我能给出的保证是:存储层只剩一张表、一条写入门面、一套删除语义、一套注入判据,且这三个「唯一」都被实跑验证过。 我不能给出的是:你库里的内容质量 —— 那 40+ 条版本流水账不会因为代码变好而变得有用,它们仍然按设计不注入。要让模型真正「懂你在做什么」,需要按工作手册的形态重新写几条(发版流程、环境重建、常见坑),几条就够,不需要几十条。 ━━ 五、MIKA 双软件共存的想法(你问的)━━ 我认为技术上可行,而且在架构上我们正好有个天然优势:我们已经是「一个应用 + 多个能力域」的形态(工具区、工作区、Provider 都是插件式),再加一个「人格/子应用」维度不是推倒重来。 但要澄清一个关键点:Mika 和 RinCore 争的不是「谁做助理」,而是「上下文归谁」 —— Mika 的强项是「知道你是谁」(称呼、日程、口味),RinCore 的强项是「知道活怎么干」(命令、路径、坑)。你自己说过不要用户画像,那句话对 RinCore 成立、对 Mika 恰恰相反。 所以我建议的形态是:共享沙箱与文件系统(同一套 proot + 工作区),记忆按「域」分区而不混 —— Mika 域记人,RinCore 域记事,跨域只通过「显式引用」传递(类似 skill 的引用方式),而不是自动合并。这样两个都保持各自最擅长的部分,又不会互相污染。 这一版先留了扩展点(MemoryRepository 的 memoryId 本来就是「一个字符串桶」:助手 ID / GLOBAL / 将来可以是 mika:<userId>),没有实现多状态,按你说的等 Mika 稳定。 ━━ 六、诚实边界 ━━ ①实跑用的是内存 Fake DAO,验证的是 Repository 的语义,不是 Room/SQLite 的真实行为(SQL 层由 CI 的编译 + 已有测试保证);②无安装实测;③deleteMemory(id)(Operit 脚本用)仍硬编码 GLOBAL 库 —— 现状与 Operit 的 addMemory 一致,不是新问题,已记录;④getFilesOfConversationFlow 无 assistantId 过滤(conversationId 是全局 Uuid,实际不串),已记录待后续收敛。 ★版本纪律:5.3.44 → 5.3.45(只改第三位、不进位)。 ⑩hub=v5.3.45
  • d0f554c release: v5.3.45 — ★★记忆系统工业级验收:用真实源码实跑 18 项,修掉 4 个「会让人以为记忆又坏了」的真问题🧠这一版不是再打补丁 —— 是把记忆全链路的读写路径逐条对账,并用 kotlinc 编译真实源码实跑验证。 ━━ 一、方法:不再靠「读一遍觉得没问题」━━ 把记忆拆成 表 → DAO → 仓库门面 → 工具 → 注入 → UI → 做梦 → 迁移 八段,对每一条读写路径检查它是否遵守同一套不变式(唯一表 / 归属互斥 / 软删过滤 / path 多形态 / 跨范围拒绝 / 挂载三档 / 来源二维 / 越权防线 / kind 权重 / Auto 注入)。 然后把真实 MemoryRepository.kt + MemoryFileDAO.kt + MemoryFile.kt 用 kotlinc 编译(补 Room 注解、Log、Assistant 的最小 stub),配一个内存版 DAO 实跑 18 项断言。 ━━ 二、实跑抓到 4 个真问题(都属「不报错但用户会以为记忆又坏了」)━━ ① 删掉的记忆,模型重新写入 → 内容进去了却永久不可见 旧实现无条件保留 invalidatedAt。用户删掉「饮食偏好」后模型再记同一主题,库里有内容、记忆页看不到 —— 这正是你之前报的「模型说记住了、我却找不到」的另一层原因(此前只归因到 UI 死代码)。 现在按动作区分:整体写入(memory_write)= 复活(写进来就该可见);局部编辑(str_replace / append)= 拒绝并明确告知「这条已删除,要恢复请用 memory_write」。 ② getFile 是公开 API,却能读到已删除的条目 它内部不过滤软删(这是给「写入前判存」用的)。实跑时「删除后不可读」这条断言就是失败的 —— 证明公开面语义不清。现在拆成:getFile = 读可见记忆;新增私有 getFileAny 专供判存。 ③ 模型侧删除老记忆删不掉 模型走 deleteMemoryChecked → 直调 DAO 的单形态 invalidate,对 v5.3.7 迁移来的无前导斜杠老 path 恒 0 行命中 → 模型说「已删除」但条目还在。改走 invalidateFile(六形态),失败时明确报错不再假装成功。 ④ copyFiles 会覆盖目标助手的同名记忆 复制助手时直接 upsert。copyMemories 在 v5.3.19 已改成「冲突就跳过并记日志」,copyFiles 漏了 —— 现在补上(虽然当前零调用点,但它是公开 API)。 ━━ 三、18 项实跑断言(全部通过)━━ 写入可读 / 删除不可读 / 删除后列表空 / 重写必须复活 / 复活后内容是新写的 / 复活后回列表 / 对已删条目 append 必拒 / replace 必拒 / 老 path 可见 / 带斜杠删除老记忆必命中 / 删除后不可见 / 模型侧删除老 path 必生效 / 跨范围覆盖必拒 / 挂对话后 folderId 必清空 / 挂对话后 conversationId 正确 / MOUNT_FOLDER 全见 / MOUNT_ASSISTANT_ONLY 只见助手级 / MOUNT_CURRENT_CONVERSATION 见助手级+本对话。 另加 3 条回归测试进白名单硬门禁(复活 / 拒绝局部编辑 / 老 path 删除),锁死这三条语义。 ━━ 四、关于「工业级」的诚实判据 ━━ 我能给出的保证是:存储层只剩一张表、一条写入门面、一套删除语义、一套注入判据,且这三个「唯一」都被实跑验证过。 我不能给出的是:你库里的内容质量 —— 那 40+ 条版本流水账不会因为代码变好而变得有用,它们仍然按设计不注入。要让模型真正「懂你在做什么」,需要按工作手册的形态重新写几条(发版流程、环境重建、常见坑),几条就够,不需要几十条。 ━━ 五、MIKA 双软件共存的想法(你问的)━━ 我认为技术上可行,而且在架构上我们正好有个天然优势:我们已经是「一个应用 + 多个能力域」的形态(工具区、工作区、Provider 都是插件式),再加一个「人格/子应用」维度不是推倒重来。 但要澄清一个关键点:Mika 和 RinCore 争的不是「谁做助理」,而是「上下文归谁」 —— Mika 的强项是「知道你是谁」(称呼、日程、口味),RinCore 的强项是「知道活怎么干」(命令、路径、坑)。你自己说过不要用户画像,那句话对 RinCore 成立、对 Mika 恰恰相反。 所以我建议的形态是:共享沙箱与文件系统(同一套 proot + 工作区),记忆按「域」分区而不混 —— Mika 域记人,RinCore 域记事,跨域只通过「显式引用」传递(类似 skill 的引用方式),而不是自动合并。这样两个都保持各自最擅长的部分,又不会互相污染。 这一版先留了扩展点(MemoryRepository 的 memoryId 本来就是「一个字符串桶」:助手 ID / GLOBAL / 将来可以是 mika:<userId>),没有实现多状态,按你说的等 Mika 稳定。 ━━ 六、诚实边界 ━━ ①实跑用的是内存 Fake DAO,验证的是 Repository 的语义,不是 Room/SQLite 的真实行为(SQL 层由 CI 的编译 + 已有测试保证);②无安装实测;③deleteMemory(id)(Operit 脚本用)仍硬编码 GLOBAL 库 —— 现状与 Operit 的 addMemory 一致,不是新问题,已记录;④getFilesOfConversationFlow 无 assistantId 过滤(conversationId 是全局 Uuid,实际不串),已记录待后续收敛。 ★版本纪律:5.3.44 → 5.3.45(只改第三位、不进位)。 ⑩hub=v5.3.45
  • c12f661 release: v5.3.44 — ★★记忆语义转向:从「用户画像」到「工作手册」—— 按 kind 权重排序,不再分析你是谁🧠这一版改的是记忆的「用途」,不是存储。 ━━ 一、先回答你问的:MIKA 为什么质量高 ━━ 我读了它 9 个记忆文件 + AgentLoop 关键段,它的好在四个地方,都不是「功能多」:①规则有代码复核,不信模型 —— 记忆条目带 source.quote(必须是用户本人在这次任务里说的子串,屏幕/网页/工具结果都不算),还查「内容里的每个具体值(引号内文字、数字、3+字母英文、地址片段)是否都能在原话里找到」,找不到就拒。这是防模型编造偏好的唯一机制。②失败什么都不做 —— 提取器出错就返回空,不影响任务;所有扩展点都是「可失败旁路」。③边界写死 —— 敏感过滤明确「手机号、地址、生日、家人称呼不在此列,它们是办事常用的事实」,只拦凭证(身份证还带 ISO 7064 校验位、卡号走 Luhn)。④诚实的注释 —— 它自己写明「局限:没加引号的中文人名、无标志字的地名认不出来」。它不是靠聪明,是靠「每条规则都能被验证」。 ━━ 二、但它的核心假设对我们是错的 ━━ MIKA 是「操作手机」的 agent,用户画像对它有价值(称呼、口味、日程)。我们是办公/工作区工具 —— 你的个人画像对完成任务没有帮助。所以本轮不照搬它的 ProfileEntry(你是谁/住哪/职业),而是把它的 MemoryItem 结构和 Auto 注入留下,把权重整个调过来。 ━━ 三、权重体系(本版核心)━━ 记忆按 kind 分四类,权重从高到低:work(这类活怎么干:命令、路径、步骤、坑)> project(项目怎么构建/发布/文件在哪)> fact(具体值:版本、端口、环境)> preference(回答格式/语气)。 注入时按权重排序(同权重按 path —— 保证前缀稳定,缓存不失效),每一条都标注 kind 让模型一眼知道该信几分。 ━━ 四、具体改了什么 ━━ ① /profile.md 不再是特殊层 —— 以前它被全文置顶注入,现在若库里还有它,只作为一条普通 fact 参与排序;想彻底不要,删掉那个文件即可。这是直接执行你的那句「不要再专门开一个东西去画用户画像」。 ② 写记忆的判据整体换掉 —— 旧的 [stated] test(「必须是用户说过的」)换成 reuse test:「这一行能不能让下次做同类任务更省事、更快、更不容易出错?」 留下的是这种:「发版顺序:先 ./bin/selfcheck,再 ./bin/audit fast,最后 rc release」/「proot 里 LibreOffice 起不来,用 officecli view screenshot 代替」/「这个 rootfs 自带 gcc 13.3 / node v18 / python 3.12」。丢掉的是这种:「v5.0.25 正式版已发布,APK 84.89MB」/「用户喜欢吃甜」。 ③ 布局改成工作手册 —— /playbooks/<任务>.md(kind=work,最高价值)/ /projects/<项目>.md(kind=project)/ /topics/<领域>.md(kind=fact)/ /preferences.md(kind=preference,唯一保留全文注入的)。明确写了「There is NO profile file」,并说明不要记录性格、口味、爱好、私生活。 ④ 后台整理器整体改向 —— 从「提取用户陈述的事实」改为「寻找可复用的工作知识:实际跑通的命令序列、踩到的坑和绕法、项目里必须自己发现的结构」。明确不记「提出过但没执行的计划」和「自己的推测」。产出量指引也从「零到两条」压到「零到一条」——一条具体的 work 条目胜过好几条含糊的 fact。 ━━ 五、验证(没拿 CI 当第一验证器)━━ kotlinc 编译真实源码 MemoryPrompts.kt + `MemoryFile.k...
Read more

RinCore v5.3.44

Choose a tag to compare

@github-actions github-actions released this 04 Nov 10:41

RinCore v5.3.44

★★记忆语义转向:从「用户画像」到「工作手册」—— 按 kind 权重排序,不再分析你是谁🧠这一版改的是记忆的「用途」,不是存储。 ━━ 一、先回答你问的:MIKA 为什么质量高 ━━ 我读了它 9 个记忆文件 + AgentLoop 关键段,它的好在四个地方,都不是「功能多」:①规则有代码复核,不信模型 —— 记忆条目带 source.quote(必须是用户本人在这次任务里说的子串,屏幕/网页/工具结果都不算),还查「内容里的每个具体值(引号内文字、数字、3+字母英文、地址片段)是否都能在原话里找到」,找不到就拒。这是防模型编造偏好的唯一机制。②失败什么都不做 —— 提取器出错就返回空,不影响任务;所有扩展点都是「可失败旁路」。③边界写死 —— 敏感过滤明确「手机号、地址、生日、家人称呼不在此列,它们是办事常用的事实」,只拦凭证(身份证还带 ISO 7064 校验位、卡号走 Luhn)。④诚实的注释 —— 它自己写明「局限:没加引号的中文人名、无标志字的地名认不出来」。它不是靠聪明,是靠「每条规则都能被验证」。 ━━ 二、但它的核心假设对我们是错的 ━━ MIKA 是「操作手机」的 agent,用户画像对它有价值(称呼、口味、日程)。我们是办公/工作区工具 —— 你的个人画像对完成任务没有帮助。所以本轮不照搬它的 ProfileEntry(你是谁/住哪/职业),而是把它的 MemoryItem 结构和 Auto 注入留下,把权重整个调过来。 ━━ 三、权重体系(本版核心)━━ 记忆按 kind 分四类,权重从高到低:work(这类活怎么干:命令、路径、步骤、坑)> project(项目怎么构建/发布/文件在哪)> fact(具体值:版本、端口、环境)> preference(回答格式/语气)。 注入时按权重排序(同权重按 path —— 保证前缀稳定,缓存不失效),每一条都标注 kind 让模型一眼知道该信几分。 ━━ 四、具体改了什么 ━━ ① /profile.md 不再是特殊层 —— 以前它被全文置顶注入,现在若库里还有它,只作为一条普通 fact 参与排序;想彻底不要,删掉那个文件即可。这是直接执行你的那句「不要再专门开一个东西去画用户画像」。 ② 写记忆的判据整体换掉 —— 旧的 [stated] test(「必须是用户说过的」)换成 reuse test:「这一行能不能让下次做同类任务更省事、更快、更不容易出错?」 留下的是这种:「发版顺序:先 ./bin/selfcheck,再 ./bin/audit fast,最后 rc release」/「proot 里 LibreOffice 起不来,用 officecli view screenshot 代替」/「这个 rootfs 自带 gcc 13.3 / node v18 / python 3.12」。丢掉的是这种:「v5.0.25 正式版已发布,APK 84.89MB」/「用户喜欢吃甜」。 ③ 布局改成工作手册 —— /playbooks/<任务>.md(kind=work,最高价值)/ /projects/<项目>.md(kind=project)/ /topics/<领域>.md(kind=fact)/ /preferences.md(kind=preference,唯一保留全文注入的)。明确写了「There is NO profile file」,并说明不要记录性格、口味、爱好、私生活。 ④ 后台整理器整体改向 —— 从「提取用户陈述的事实」改为「寻找可复用的工作知识:实际跑通的命令序列、踩到的坑和绕法、项目里必须自己发现的结构」。明确不记「提出过但没执行的计划」和「自己的推测」。产出量指引也从「零到两条」压到「零到一条」——一条具体的 work 条目胜过好几条含糊的 fact。 ━━ 五、验证(没拿 CI 当第一验证器)━━ kotlinc 编译真实源码 MemoryPrompts.kt + MemoryFile.kt 跑 17 项断言全过:无 profile 专属段 / profile 内容仍作为普通条目出现 / preferences 仍全文注入 / 走 memory_files 且标 kind / work 排在 project 前、project 排在 fact 前 / 改更新时间不改变顺序(前缀稳定)/ 大库退回 listing / 旧格式不参与体积 / 文案里有 reuse test 与「NO profile file」。另:tree-sitter 两文件 0 错误、rc check 双 PASS。 ━━ 六、你库里那 40+ 条旧记忆怎么办 ━━ 我按你说的「提前告诉你打算」:它们现在一条都不注入(v5.3.23 起就是这样,只留一行统计)。本版把语义彻底转向工作知识之后,它们和你要的东西已经是两个物种了。 我的建议:整体废弃,不要迁移。 因为那 40 条全是「某版本发布了什么」,reuse test 一条都过不了。 请你让模型把这些整理成文档(这部分我能帮你做——你只要说一句"把这 40 条记忆里有长期价值的部分整理成一份工作手册",我可以直接在工作区里生成),整理完我就把它们清掉。 ━━ 七、诚实边界 ━━ ①本版只改「怎么用记忆」,没改存储结构 —— kind 写在 frontmatter 里,零数据库迁移,旧数据自动归 fact(对「某版本发布」这类记录是准确分类);②**preferences.md 仍全文注入**(回复约定每次都用得上,不属于「分析用户」);③旧记忆不会被自动删除,需要你确认后清;④没有安装实测(沙箱无设备),但 17 项断言是编译真实源码加的,不是模拟;⑤沙箱里那些 bin/ 工具不会随 APK 发布,工作手册里写「./bin/selfcheck」是给我这个在沙箱里干活的助手看的,你在手机上不会用到。 ★版本纪律:5.3.43 → 5.3.44(只改第三位、不进位)。 ⑩hub=v5.3.44

本次提交

  • 0b3bedf release: v5.3.44 — ★★记忆语义转向:从「用户画像」到「工作手册」—— 按 kind 权重排序,不再分析你是谁🧠这一版改的是记忆的「用途」,不是存储。 ━━ 一、先回答你问的:MIKA 为什么质量高 ━━ 我读了它 9 个记忆文件 + AgentLoop 关键段,它的好在四个地方,都不是「功能多」:①规则有代码复核,不信模型 —— 记忆条目带 source.quote(必须是用户本人在这次任务里说的子串,屏幕/网页/工具结果都不算),还查「内容里的每个具体值(引号内文字、数字、3+字母英文、地址片段)是否都能在原话里找到」,找不到就拒。这是防模型编造偏好的唯一机制。②失败什么都不做 —— 提取器出错就返回空,不影响任务;所有扩展点都是「可失败旁路」。③边界写死 —— 敏感过滤明确「手机号、地址、生日、家人称呼不在此列,它们是办事常用的事实」,只拦凭证(身份证还带 ISO 7064 校验位、卡号走 Luhn)。④诚实的注释 —— 它自己写明「局限:没加引号的中文人名、无标志字的地名认不出来」。它不是靠聪明,是靠「每条规则都能被验证」。 ━━ 二、但它的核心假设对我们是错的 ━━ MIKA 是「操作手机」的 agent,用户画像对它有价值(称呼、口味、日程)。我们是办公/工作区工具 —— 你的个人画像对完成任务没有帮助。所以本轮不照搬它的 ProfileEntry(你是谁/住哪/职业),而是把它的 MemoryItem 结构和 Auto 注入留下,把权重整个调过来。 ━━ 三、权重体系(本版核心)━━ 记忆按 kind 分四类,权重从高到低:work(这类活怎么干:命令、路径、步骤、坑)> project(项目怎么构建/发布/文件在哪)> fact(具体值:版本、端口、环境)> preference(回答格式/语气)。 注入时按权重排序(同权重按 path —— 保证前缀稳定,缓存不失效),每一条都标注 kind 让模型一眼知道该信几分。 ━━ 四、具体改了什么 ━━ ① /profile.md 不再是特殊层 —— 以前它被全文置顶注入,现在若库里还有它,只作为一条普通 fact 参与排序;想彻底不要,删掉那个文件即可。这是直接执行你的那句「不要再专门开一个东西去画用户画像」。 ② 写记忆的判据整体换掉 —— 旧的 [stated] test(「必须是用户说过的」)换成 reuse test:「这一行能不能让下次做同类任务更省事、更快、更不容易出错?」 留下的是这种:「发版顺序:先 ./bin/selfcheck,再 ./bin/audit fast,最后 rc release」/「proot 里 LibreOffice 起不来,用 officecli view screenshot 代替」/「这个 rootfs 自带 gcc 13.3 / node v18 / python 3.12」。丢掉的是这种:「v5.0.25 正式版已发布,APK 84.89MB」/「用户喜欢吃甜」。 ③ 布局改成工作手册 —— /playbooks/<任务>.md(kind=work,最高价值)/ /projects/<项目>.md(kind=project)/ /topics/<领域>.md(kind=fact)/ /preferences.md(kind=preference,唯一保留全文注入的)。明确写了「There is NO profile file」,并说明不要记录性格、口味、爱好、私生活。 ④ 后台整理器整体改向 —— 从「提取用户陈述的事实」改为「寻找可复用的工作知识:实际跑通的命令序列、踩到的坑和绕法、项目里必须自己发现的结构」。明确不记「提出过但没执行的计划」和「自己的推测」。产出量指引也从「零到两条」压到「零到一条」——一条具体的 work 条目胜过好几条含糊的 fact。 ━━ 五、验证(没拿 CI 当第一验证器)━━ kotlinc 编译真实源码 MemoryPrompts.kt + MemoryFile.kt 跑 17 项断言全过:无 profile 专属段 / profile 内容仍作为普通条目出现 / preferences 仍全文注入 / 走 memory_files 且标 kind / work 排在 project 前、project 排在 fact 前 / 改更新时间不改变顺序(前缀稳定)/ 大库退回 listing / 旧格式不参与体积 / 文案里有 reuse test 与「NO profile file」。另:tree-sitter 两文件 0 错误、rc check 双 PASS。 ━━ 六、你库里那 40+ 条旧记忆怎么办 ━━ 我按你说的「提前告诉你打算」:它们现在一条都不注入(v5.3.23 起就是这样,只留一行统计)。本版把语义彻底转向工作知识之后,它们和你要的东西已经是两个物种了。 我的建议:整体废弃,不要迁移。 因为那 40 条全是「某版本发布了什么」,reuse test 一条都过不了。 请你让模型把这些整理成文档(这部分我能帮你做——你只要说一句"把这 40 条记忆里有长期价值的部分整理成一份工作手册",我可以直接在工作区里生成),整理完我就把它们清掉。 ━━ 七、诚实边界 ━━ ①本版只改「怎么用记忆」,没改存储结构 —— kind 写在 frontmatter 里,零数据库迁移,旧数据自动归 fact(对「某版本发布」这类记录是准确分类);②**preferences.md 仍全文注入**(回复约定每次都用得上,不属于「分析用户」);③旧记忆不会被自动删除,需要你确认后清;④没有安装实测(沙箱无设备),但 17 项断言是编译真实源码加的,不是模拟;⑤沙箱里那些 bin/ 工具不会随 APK 发布,工作手册里写「./bin/selfcheck」是给我这个在沙箱里干活的助手看的,你在手机上不会用到。 ★版本纪律:5.3.43 → 5.3.44(只改第三位、不进位)。 ⑩hub=v5.3.44
  • 6cfd52c release: v5.3.43 — ★★记忆注入改「装得下就全文给」:模型不用再读一遍 + 前缀稳定保缓存 📐这一版只动注入策略,不动存储结构 —— 记忆系统重写在下一批。 ━━ 为什么动这个(你上一轮说的「先动缓存」)━━ 原来的注入只给「一行描述」:/topics/rincore.md | 一句话说明 | updated: 日期。模型想知道里面写了什么,必须再调一次 memory_read —— 多一轮往返,而且这一轮注入的仍然只是摘要。 更关键的是缓存:检索式注入每次挑出来的结果都可能不同 → 前缀一变,后面整段就得重新计费。v5.3.38 那次实测已经证明图片之外的这一侧从来没考虑过前缀稳定性。 本版改动:记忆库正文总量 ≤ 12000 字符(约 4000 token)就全部正文一次性注入,模型直接就能用;超过才退回原来的索引式。 ━━ 一个必须做对的细节:顺序按 path,不按更新时间 ━━ 全量注入的唯一优势是「每次注入完全相同」。如果按 updatedAt 排序,任何一条记忆被更新都会把整段顺序挪位 → 前缀漂移 → 缓存全 miss,优势直接抵消。所以顺序固定按 path 字母序 —— 内容变了才变,位置不变。这一条专门写了回归测试锁住。 ━━ 验证(没拿 CI 当第一验证器)━━ 把真实源码 MemoryPrompts.kt + MemoryFile.kt 用 kotlinc 编译,跑了 16 项断言全过:小库走全文 / 正文真的注入 / 大库退回索引且绝不内联 / 旧格式永不参与体积计算 / 改更新时间不改变顺序 / 空库空态 / 两条规则文案都在。另:tree-sitter 两文件 0 错误、rc check 双 PASS。 ━━ 一处我自己的错,已修 ━━ 第一版断言用 contains("<memory_listing>") 判「有没有这个段」,结果规则说明里提到这个标签名就误判成「输出了该段」—— 两条假失败。改成精确匹配结构形态(<memory_listing> 后紧跟换行、<memory_files count=)才通过。这和 v5.3.18 的「全局断言误杀合法写法」同族,记在教训里。 ━━ 关于你贴的那段记忆(重要)━━ 你贴的 <memory> 块用的是 **Memories** + JSON 数组 + memory_tool 的老格式。我在当前代码里查了:**Memories** 在生产代码 0 处(只剩一条测试断言「不得出现这个标题」),memory_tool 只剩历史配置过滤/旧消息渲染/旧记录导出三处兼容,注入链早已是 <memory_system> + <profile> + <memory_listing> + <legacy_entries>。 → 那段记忆不可能由 v5.3.42 产生,它来自旧版本(≤ v5.3.20)或旧对话。这一点必须先确认,否则我们会基于错误前提改造记忆系统:请在「设置 → 关于」看一眼版本号;如果不是 5.3.42,先装上 v5.3.42 再看一次记忆注入长什么样 —— 中间十几版对记忆的修复你可能一直没拿到。 ━━ 同时确认的事(你上轮否决「用户画像」,我改方向)━━ 你说得对:「分析我是没有意义的,要分析自己的工作」。所以下一批的记忆重构方向不是 MIKA 那种用户画像,而是:①工作方法(这类任务怎么做、踩过什么坑);②项目结构(模块/构建/发版链路);③领域知识(物理题、文档处理的具体做法)。profile.md(你是谁)不再作为核心,preferences.md 只保留「回复约定」这一层(那是工作规范,不是人格分析)。具体方案下一批单独给你过。 ━━ 诚实边界 ━━ ①本版没有改存储、没有改工具、没有改 UI —— 只是注入策略 + 一条顺序保证;②没有安装实测(沙箱无设备);③全量注入会让单轮 prompt 最多多约 4000 token,但命中缓存后实际成本远低于多跑一轮 memory_read;④如果你更希望保守(保持索引式),把常量改回 0 即可回到旧行为,一行改动。 ★版本纪律:5.3.42 → 5.3.43(只改第三位、不进位)。 ⑩hub=v5.3.43
  • 3c8c118 release: v5.3.42 — ★★沙箱一体化:默认复用常驻会话(每条命令不再付 13 秒启动)+ 预热不再产生 43MB core dump + Linux 能力实测🔧这一版没有新功能 —— 它把「沙箱」从外挂变成了地基。 ━━ 一、先摆事实:沙箱其实早就是同一套 ━━ 我在沙箱里实测了 9 项:rootfs 是 Ubuntu 24.04.3(真用户态);/workspace 挂的就是你在 App 里看到的那个工作区 files/ 目录(ProotShellRunner:103);/skills、/builtin_skills、/tool_outputs、/upload 四个挂载模型和我共用;/dev/shm 已自建(Python multiprocessing 能用)。→「分离」不在目录和挂载这一层,那一层本来就是一套。 ━━ 二、真正的分离在「会话层」:每条命令都重启一次沙箱 ━━ 此前每次 workspace_shell 都新起一个 proot 进程,要重新载入 rootfs、重建全部挂载,**单条命令有 13 秒是纯启动开销**,cd 和环境变量也不跨调用保留。这正是「沙箱慢得惊人」「渲染/转换特别慢」的第一大来源,也是模型宁愿用 shell 做文件操作(等于再付一次启动)的诱因。 本版改为默认复用:连续命令共享同一个常驻 proot+bash,第 2 条起只剩命令本身耗时。 敢改默认值,是因为复用的安全性早就逐条补齐了:会话 key 含工作区 ID(不同工作区绝不串进程);每条命令前重设 cd(v5.3.37,cd 不跨命令污染);进程死/读线程断会自动重建(模型跑 exit 也不会永久坏);闲置 5 分钟自动关;起不来自动回退一次性。 需要干净隔离环境时,传 session="none" 即恢复旧行为。 ━━ 三、预热不再往你的工作区里扔 43MB 垃圾 ━━ 上次清理环境时发现根目录有个「文件名是一个空格」的 43.4MB 文件 —— 它是 officecli --version 崩溃产生的 core dump。而预热的第一步动作正好是它,且落在当前工作目录(= 你的工作区)。意味着每崩一次就吃 43MB,文件名你根本不会注意到。 本版三处修:命令前置 ulimit -c 0(崩了也不再产生文件);探测从 --version 改 --help(同样把 34MB 二进制走热,避开崩溃路径);连续 3 次失败即禁用预热 24 小时(旧实现每个输入沿都重试 = 反复制造垃圾)。 顺带修掉一个我自己写错的地方:executeCommand 不会因为非零退出码抛异常,所以「成功」判断必须显式看 exitCode —— 不加这一句,熔断永远不会触发。 诚实:officecli --version 在我这边(同一个 rootfs)正常返回 1.0.152,退出码 0,所以 core dump 是设备/机型特定问题,无法在沙箱复现;本版的价值是「即使崩了也不再产生文件」。 ━━ 四、Linux 能力实测(不是宣称,是跑出来的)━━ | 项 | 实测 | |---|---| | gcc | 13.3.0,编译 hello 成功 | | apt | 2.8.3 (arm64) 可用 | | Python | 中文 + emoji 输出正常 | | Node | v18.19.1 | | 中文字体 | 39 个 | | git / pandoc / texlive / tesseract | 在 | 工具描述里新增一条自检命令,模型不用再一个个试。 ━━ 五、为什么这层地基决定后面能不能做大事 ━━ 你在 App 里看到的文件 = 模型改的文件(同一目录);装的 Python 包/编译器跨会话存在(rootfs 随工作区);连续操作低开销;真 Linux 工具链;崩溃不产生垃圾。有了这五条,下一步才谈得上做「环境快照回滚」「预置工具链」「沙箱状态可视化」这类真正提效的东西。 ━━ 六、诚实边界 ━━ ①默认行为变了:依赖「每条命令干净环境」的自定义流程需显式传 session="none";②同 session 内命令串行(这是不串状态的前提);③/proc/version 权限拒绝是 proot 固有限制,LibreOffice 仍不可用(用 officecli view screenshot);④无安装实测,改动靠静态检查 + 熔断逻辑复刻验证;⑤沙箱状态可视化(App 里显示「就绪/执行中」)本版未做,留待下一批。 ★版本纪律:5.3.41 → 5.3.42(只改第三位、不进位)。 ⑩hub=v5.3.42
  • 2ed55f9 docs: 发布链核验记录 + 两个流程问题
  • d2d3565 release: v5.3.41 — ★★文档与工具批次:溯源体系 / 结构总图 / 开工状态 + 工作流整顿(发布链本身是本轮验证对象)📐这一版没有改任何功能代码 —— 它是前面几轮「把项目理清楚」的沉淀落地,同时用一次真实发版来验证新工作流程是否可靠。 ━━ 一、本版带上的三份文档(此前只在 adopt 分支,未进 main)━━ | 文档 | 内容 | |---|---| | FILE-ORIGIN.md + .json(+ 工具 bin/origin) | 全量文件来源溯源:1353 个 .kt 中 UPSTREAM 778(57.5%) 与 3.1.0 逐字节一致 / MODIFIED 231 / PORTED 200 / PORTED-MODIFIED 67 / OURS 56 / DELETED 21。11 个命令:stats/`modul...
Read more

RinCore v5.3.43

Choose a tag to compare

@github-actions github-actions released this 04 Nov 10:17

RinCore v5.3.43

★★记忆注入改「装得下就全文给」:模型不用再读一遍 + 前缀稳定保缓存 📐这一版只动注入策略,不动存储结构 —— 记忆系统重写在下一批。 ━━ 为什么动这个(你上一轮说的「先动缓存」)━━ 原来的注入只给「一行描述」:/topics/rincore.md | 一句话说明 | updated: 日期。模型想知道里面写了什么,必须再调一次 memory_read —— 多一轮往返,而且这一轮注入的仍然只是摘要。 更关键的是缓存:检索式注入每次挑出来的结果都可能不同 → 前缀一变,后面整段就得重新计费。v5.3.38 那次实测已经证明图片之外的这一侧从来没考虑过前缀稳定性。 本版改动:记忆库正文总量 ≤ 12000 字符(约 4000 token)就全部正文一次性注入,模型直接就能用;超过才退回原来的索引式。 ━━ 一个必须做对的细节:顺序按 path,不按更新时间 ━━ 全量注入的唯一优势是「每次注入完全相同」。如果按 updatedAt 排序,任何一条记忆被更新都会把整段顺序挪位 → 前缀漂移 → 缓存全 miss,优势直接抵消。所以顺序固定按 path 字母序 —— 内容变了才变,位置不变。这一条专门写了回归测试锁住。 ━━ 验证(没拿 CI 当第一验证器)━━ 把真实源码 MemoryPrompts.kt + MemoryFile.kt 用 kotlinc 编译,跑了 16 项断言全过:小库走全文 / 正文真的注入 / 大库退回索引且绝不内联 / 旧格式永不参与体积计算 / 改更新时间不改变顺序 / 空库空态 / 两条规则文案都在。另:tree-sitter 两文件 0 错误、rc check 双 PASS。 ━━ 一处我自己的错,已修 ━━ 第一版断言用 contains("<memory_listing>") 判「有没有这个段」,结果规则说明里提到这个标签名就误判成「输出了该段」—— 两条假失败。改成精确匹配结构形态(<memory_listing> 后紧跟换行、<memory_files count=)才通过。这和 v5.3.18 的「全局断言误杀合法写法」同族,记在教训里。 ━━ 关于你贴的那段记忆(重要)━━ 你贴的 <memory> 块用的是 **Memories** + JSON 数组 + memory_tool 的老格式。我在当前代码里查了:**Memories** 在生产代码 0 处(只剩一条测试断言「不得出现这个标题」),memory_tool 只剩历史配置过滤/旧消息渲染/旧记录导出三处兼容,注入链早已是 <memory_system> + <profile> + <memory_listing> + <legacy_entries>。 → 那段记忆不可能由 v5.3.42 产生,它来自旧版本(≤ v5.3.20)或旧对话。这一点必须先确认,否则我们会基于错误前提改造记忆系统:请在「设置 → 关于」看一眼版本号;如果不是 5.3.42,先装上 v5.3.42 再看一次记忆注入长什么样 —— 中间十几版对记忆的修复你可能一直没拿到。 ━━ 同时确认的事(你上轮否决「用户画像」,我改方向)━━ 你说得对:「分析我是没有意义的,要分析自己的工作」。所以下一批的记忆重构方向不是 MIKA 那种用户画像,而是:①工作方法(这类任务怎么做、踩过什么坑);②项目结构(模块/构建/发版链路);③领域知识(物理题、文档处理的具体做法)。profile.md(你是谁)不再作为核心,preferences.md 只保留「回复约定」这一层(那是工作规范,不是人格分析)。具体方案下一批单独给你过。 ━━ 诚实边界 ━━ ①本版没有改存储、没有改工具、没有改 UI —— 只是注入策略 + 一条顺序保证;②没有安装实测(沙箱无设备);③全量注入会让单轮 prompt 最多多约 4000 token,但命中缓存后实际成本远低于多跑一轮 memory_read;④如果你更希望保守(保持索引式),把常量改回 0 即可回到旧行为,一行改动。 ★版本纪律:5.3.42 → 5.3.43(只改第三位、不进位)。 ⑩hub=v5.3.43

本次提交

  • 3c8c118 release: v5.3.42 — ★★沙箱一体化:默认复用常驻会话(每条命令不再付 13 秒启动)+ 预热不再产生 43MB core dump + Linux 能力实测🔧这一版没有新功能 —— 它把「沙箱」从外挂变成了地基。 ━━ 一、先摆事实:沙箱其实早就是同一套 ━━ 我在沙箱里实测了 9 项:rootfs 是 Ubuntu 24.04.3(真用户态);/workspace 挂的就是你在 App 里看到的那个工作区 files/ 目录(ProotShellRunner:103);/skills、/builtin_skills、/tool_outputs、/upload 四个挂载模型和我共用;/dev/shm 已自建(Python multiprocessing 能用)。→「分离」不在目录和挂载这一层,那一层本来就是一套。 ━━ 二、真正的分离在「会话层」:每条命令都重启一次沙箱 ━━ 此前每次 workspace_shell 都新起一个 proot 进程,要重新载入 rootfs、重建全部挂载,**单条命令有 13 秒是纯启动开销**,cd 和环境变量也不跨调用保留。这正是「沙箱慢得惊人」「渲染/转换特别慢」的第一大来源,也是模型宁愿用 shell 做文件操作(等于再付一次启动)的诱因。 本版改为默认复用:连续命令共享同一个常驻 proot+bash,第 2 条起只剩命令本身耗时。 敢改默认值,是因为复用的安全性早就逐条补齐了:会话 key 含工作区 ID(不同工作区绝不串进程);每条命令前重设 cd(v5.3.37,cd 不跨命令污染);进程死/读线程断会自动重建(模型跑 exit 也不会永久坏);闲置 5 分钟自动关;起不来自动回退一次性。 需要干净隔离环境时,传 session="none" 即恢复旧行为。 ━━ 三、预热不再往你的工作区里扔 43MB 垃圾 ━━ 上次清理环境时发现根目录有个「文件名是一个空格」的 43.4MB 文件 —— 它是 officecli --version 崩溃产生的 core dump。而预热的第一步动作正好是它,且落在当前工作目录(= 你的工作区)。意味着每崩一次就吃 43MB,文件名你根本不会注意到。 本版三处修:命令前置 ulimit -c 0(崩了也不再产生文件);探测从 --version 改 --help(同样把 34MB 二进制走热,避开崩溃路径);连续 3 次失败即禁用预热 24 小时(旧实现每个输入沿都重试 = 反复制造垃圾)。 顺带修掉一个我自己写错的地方:executeCommand 不会因为非零退出码抛异常,所以「成功」判断必须显式看 exitCode —— 不加这一句,熔断永远不会触发。 诚实:officecli --version 在我这边(同一个 rootfs)正常返回 1.0.152,退出码 0,所以 core dump 是设备/机型特定问题,无法在沙箱复现;本版的价值是「即使崩了也不再产生文件」。 ━━ 四、Linux 能力实测(不是宣称,是跑出来的)━━ | 项 | 实测 | |---|---| | gcc | 13.3.0,编译 hello 成功 | | apt | 2.8.3 (arm64) 可用 | | Python | 中文 + emoji 输出正常 | | Node | v18.19.1 | | 中文字体 | 39 个 | | git / pandoc / texlive / tesseract | 在 | 工具描述里新增一条自检命令,模型不用再一个个试。 ━━ 五、为什么这层地基决定后面能不能做大事 ━━ 你在 App 里看到的文件 = 模型改的文件(同一目录);装的 Python 包/编译器跨会话存在(rootfs 随工作区);连续操作低开销;真 Linux 工具链;崩溃不产生垃圾。有了这五条,下一步才谈得上做「环境快照回滚」「预置工具链」「沙箱状态可视化」这类真正提效的东西。 ━━ 六、诚实边界 ━━ ①默认行为变了:依赖「每条命令干净环境」的自定义流程需显式传 session="none";②同 session 内命令串行(这是不串状态的前提);③/proc/version 权限拒绝是 proot 固有限制,LibreOffice 仍不可用(用 officecli view screenshot);④无安装实测,改动靠静态检查 + 熔断逻辑复刻验证;⑤沙箱状态可视化(App 里显示「就绪/执行中」)本版未做,留待下一批。 ★版本纪律:5.3.41 → 5.3.42(只改第三位、不进位)。 ⑩hub=v5.3.42
  • 2ed55f9 docs: 发布链核验记录 + 两个流程问题
  • d2d3565 release: v5.3.41 — ★★文档与工具批次:溯源体系 / 结构总图 / 开工状态 + 工作流整顿(发布链本身是本轮验证对象)📐这一版没有改任何功能代码 —— 它是前面几轮「把项目理清楚」的沉淀落地,同时用一次真实发版来验证新工作流程是否可靠。 ━━ 一、本版带上的三份文档(此前只在 adopt 分支,未进 main)━━ | 文档 | 内容 | |---|---| | FILE-ORIGIN.md + .json(+ 工具 bin/origin) | 全量文件来源溯源:1353 个 .kt 中 UPSTREAM 778(57.5%) 与 3.1.0 逐字节一致 / MODIFIED 231 / PORTED 200 / PORTED-MODIFIED 67 / OURS 56 / DELETED 21。11 个命令:stats/modules/of/diff/restore/lost/untouched/ours/modified/ported/audit | | STRUCTURE-MAP.md(+ bin/symbols、bin/deps) | 四层索引:文件级(谁的文件)/ 符号级(26575 个符号,改动风险最高的是 UIMessagePart 140 文件、UIMessage 102、SettingsStore 84)/ 模块级(无循环依赖,app 唯一顶层,highlight/document/material3/oauth 是零跨模块依赖的叶子)/ 孤立声明初筛 | | CODE-NAVIGATION.md + EXTENSION-POINTS.md | 按「我要改 X」组织的导航(53 个路径引用逐条脚本验证,0 缺失)+ 加工具/渲染器/区/Provider/设置项/记忆档/路由的改法与必踩坑 | | 开工状态-2026-11-04.md | 下批次开工快照(版本/环境/工具链/代码画像/待办/六条纪律) | ━━ 二、工作流整顿(这才是本轮真正想验证的东西)━━ ① bin/watch —— 唯一 CI 查询入口:watch(最近 run + 自动比对是否就是本地 HEAD)/ watch <runId>(阻塞到终态,绿/红自带摘要,退出码 0/1)/ watch <sha>(按 commit 找 run 再等)。② bin/selfcheck —— 检查器自检(14 项探针):用已知坏样本喂每个检查器,确认它真会报错(含对照:正常文件不得误报、假 sha 必须失败、watch 必须秒回)。「基线全绿」不等于「没问题」 —— 如果检查器本身失灵,全绿是假的。③ rc release 修掉一个真实隐患:旧流程是 sleep 20 后取最近一个 run 且不校验 sha —— 新 run 还没创建时会等到上一个 commit 的 run 并判定 CI-GREEN,最终表现「CI 绿了但 release 没出来」,失败点离真因很远。现改为 run_for_sha(head_sha) 定位 + wait 内二次校验 head_sha。④ 两份 AGENTS.md(工作区根 + 仓库根):把「等 CI 只用 watch」「发版前先 selfcheck 再 audit」「验收看退出码不看输出文字」写进每次会话都会读到的位置 —— 之前这些规则写在 bin/README.md,而我不总会去翻它。━━ 三、本版确认的健康项 ━━ selfcheck 14/14;doctor 14 通过 / 0 警告 / 0 失败;audit fast AUDIT-OK;origin 1353 个 .kt;symbols 26575 个符号;deps cycles 无循环依赖;APK 79.7MB(上一版已从 85.1MB 降下来)。━━ 四、诚实边界 ━━ ①本版零功能改动 —— 全部是文档 + 工作区工具(bin/ 不随 APK 发布),所以"功能变化"这一栏是空的;②bin/ 里的工具是我的工作环境,不在仓库里、不随 APK 分发,所以这版 APK 与 v5.3.40 在功能上完全一致;③无安装实测(沙箱无设备);④工作区仍有 archive/ 833M(旧 APK 对照基准)与 _trash/ 435M(proot 权限受限,删不掉)未处理。 ★版本纪律:5.3.40 → 5.3.41(只改第三位、不进位)。★待你验证:本版功能应与 v5.3.40 完全一致 —— 如果你只是为了新功能,可以从 5.3.40 直接跳到下一版;这一版的价值在于把「代码库为什么乱、乱在哪、怎么迁移」变成了可查询的事实。 ⑩hub=v5.3.41
  • d730c36 docs: 下批次开工状态快照 + 环境整理
  • 892ed07 docs: 结构总图 + 引用关系层(deps / symbols hot,dead)
  • b4c844a release: v5.3.40 — ★★性能(零功能变更,-6.58MB)+ 代码结构化(26575 个符号可检索)📐这一轮先说一件可能不像「优化」但更诚实的事:我把标准性能热点逐项实测排除了。 ━━ 一、被实测排除的方向(避免做无用功)━━ | 方向 | 实测结果 | 结论 | |---|---|---| | 函数内正则 | 145 处 Regex(,131 已在 val;HardlineCommandGuard 的 13 个安全正则已是 private val PATTERNS | 只剩 14 处低频,收益可忽略 | | SimpleDateFormat | 16 处全在低频页面(设置/日志/错误卡片),LogPage 3 处已 remember | 不在热路径 | | LazyColumn 无 key | ChatList 主列表两处都有 key + contentType;抽屉/模型列表/工具矩阵也都有 | 已是最佳实践 | | Markdown 解析 | 已是增量解析(块级 O(δ))+ 字符预算 LRU + 跨 tick 节点复用 + 避免全量回退(v4.8.86 深度优化) | 无空间 | | Compose 内集合运算 | message 组件 7 处,但都是小集合 | 收益 < 风险 | 结论:所谓「Compose 性能十大坑」,这个项目基本都填过了。 在没有 profiling 数据的情况下改这些,是引入风险而不是优化 —— 我没做。 ━━ 二、真正的收益:死资源(可量化、零功能变更)━━ assets/ 曾占 60MB(APK 总共才 85MB)。逐个核对引用方后: | 资源 | 体积 | 判定依据 | |---|---|---| | assets/banner/ | 5.10MB | Kotlin/XML/Manifest 零引用;真实上游 3.1.1 已删除该目录 | | assets/models_dev.json | 1.48MB | ModelsDevCatalog.decode() 零调用方 —— v5.3.1 只移植了目录类与数据,依赖 ModelRegistry 重构的 ModelsDevUpdater 从未移植 | | patreon.xml | 小 | 赞助功能已删(v5.0.52),零引用 | | ic_media_creation.xml | 小 | 零引用 | 合计 6.58MB,assets/ 60MB → 54MB。 逐个确认过是活的、保留的:rin-tools/ 33.3MB(officecli 文档工具,你日常在用)、simple_dict/ 13.1MB(SimpleDictManager.extractDict() 被 AppDatabaseFactory:55 调用,FTS 分词必需)、html/ 4.2MB(mark.html + mermaid,v5.3.17 刚做过 CDN 本地化)。 为什么这算「性能」而不是「清理」:APK 体积直接影响安装时间、升级下载量、冷启动资源扫描;在「功能零变更」这条硬约束下,它是唯一可量化的收益。 ━━ 三、代码结构化:从「1353 个文件」到「26575 个可检索符号」━━ 三层索引(文件级 → 符号级 → 导航级): | 层 | 工具 | 回答什么 | |---|---|---| | 文件级 | bin/origin | 这文件是谁的(UPSTREAM/MODIFIED/PORTED/OURS)+ 能否安全回退 | | 符号级(本轮新增) | bin/symbols | 这个类/函数在哪、属于哪个类、谁在用 | | 导航级 | docs/CODE-NAVIGATION.md | 我要改 X,先看哪几个文件 | bin/symbols 实测: symbols build # 5 秒重建 → docs/SYMBOLS.tsv symbols find saveConversation symbols uses MemoryRepository symbols stats 输出: saveConversation fun ChatService. MODIFIED ChatService.kt:1704 26575 个符号 / 1262 个 .kt,71% 有明确所属类(其余是真正的顶层扩展函数,本来就没有所属类)。每个符号带来源分类(UPSTREAM 12899 / MODIFIED 7545 / PORTED 3659 / PORTED-MODIFIED 1942 / OURS 530)→ 改一个函数之前,先知道它是原版的还是我们写的。 输出是纯 TSV,可直接 grep/awk/sort,也能被任何工具消费 —— 这就是你要的「清晰文本集」的实际形态。 第一版只索引顶层声明,find saveConversation 返回「未找到」(业务方法几乎都是成员函数)→ 索引等于不可用;加「所属类」列后才有定位价值。 ━━ 四、bin/perfscan:把这轮的排查方法固化 ━━ perfscan # 全部 perfscan assets # 体积/死资源(最可量化) perfscan hot # 热路径模式 它是清单工具不是门禁(退出码恒 0)—— 每项都给出「为什么可疑」和「零变更的改法」,由人决定改不改。刻意不做「扫出 100 条就机械全改」,那只会制造风险。 ━━ 五、诚实边界 ━━ ①APK 实际减少需 CI 产物确认 —— 6.58MB 是资源原始体积,图片本就是压缩格式,接近 1:1 但非精确。②本轮没有做运行时性能优化,因为第二节的实测排除了所有标准热点;没有 profiling 数据时改 Compose 是碰运气。③无安装实测(沙箱无设备)。④ModelsDevCatalog 类保留(注释写明「要启用必须把 json 放回来」)—— 删类会让将来移植 ModelsDevUpdater 时重写解析层。 ━━ 六、下一步(有数据再做,不猜)━━ ①冷启动:adb shell am start -W 看 TotalTime;②重组计数:Layout Inspector 的 recomposition counts,只改数字异常高的组件;③滚动掉帧:adb shell dumpsys gfxinfo <pkg> framestats,看 janky frames 集中在哪个页面。 这三项数据拿到之前,任何「Compose 优化」都是猜。 ★版本纪律:5.3.39 → 5.3.40(只改第三位、不进位)。★改动:删 5 个死资源(assets/banner/ 3 图 + models_dev.json + 2 drawable)+ ModelsDevCatalog.kt 加注释;零 Kotlin 逻辑改动(功能绝对不变)。 ★待你验证:①APK 体积应从 85.09MB 降到 ~78.5MB;②启动、聊天、文档处理一切照旧(本轮没动任何逻辑);③bin/symbols find <任意函数名> 应能直接定位到文件与所属类。 ⑩hub=v5.3.40

构建:gate(编译+测试)→ build(assembleRelease)→ 正式版 Release

RinCore v5.3.42

Choose a tag to compare

@github-actions github-actions released this 04 Nov 07:23

RinCore v5.3.42

★★沙箱一体化:默认复用常驻会话(每条命令不再付 13 秒启动)+ 预热不再产生 43MB core dump + Linux 能力实测🔧这一版没有新功能 —— 它把「沙箱」从外挂变成了地基。 ━━ 一、先摆事实:沙箱其实早就是同一套 ━━ 我在沙箱里实测了 9 项:rootfs 是 Ubuntu 24.04.3(真用户态);/workspace 挂的就是你在 App 里看到的那个工作区 files/ 目录(ProotShellRunner:103);/skills、/builtin_skills、/tool_outputs、/upload 四个挂载模型和我共用;/dev/shm 已自建(Python multiprocessing 能用)。→「分离」不在目录和挂载这一层,那一层本来就是一套。 ━━ 二、真正的分离在「会话层」:每条命令都重启一次沙箱 ━━ 此前每次 workspace_shell 都新起一个 proot 进程,要重新载入 rootfs、重建全部挂载,**单条命令有 13 秒是纯启动开销**,cd 和环境变量也不跨调用保留。这正是「沙箱慢得惊人」「渲染/转换特别慢」的第一大来源,也是模型宁愿用 shell 做文件操作(等于再付一次启动)的诱因。 本版改为默认复用:连续命令共享同一个常驻 proot+bash,第 2 条起只剩命令本身耗时。 敢改默认值,是因为复用的安全性早就逐条补齐了:会话 key 含工作区 ID(不同工作区绝不串进程);每条命令前重设 cd(v5.3.37,cd 不跨命令污染);进程死/读线程断会自动重建(模型跑 exit 也不会永久坏);闲置 5 分钟自动关;起不来自动回退一次性。 需要干净隔离环境时,传 session="none" 即恢复旧行为。 ━━ 三、预热不再往你的工作区里扔 43MB 垃圾 ━━ 上次清理环境时发现根目录有个「文件名是一个空格」的 43.4MB 文件 —— 它是 officecli --version 崩溃产生的 core dump。而预热的第一步动作正好是它,且落在当前工作目录(= 你的工作区)。意味着每崩一次就吃 43MB,文件名你根本不会注意到。 本版三处修:命令前置 ulimit -c 0(崩了也不再产生文件);探测从 --version 改 --help(同样把 34MB 二进制走热,避开崩溃路径);连续 3 次失败即禁用预热 24 小时(旧实现每个输入沿都重试 = 反复制造垃圾)。 顺带修掉一个我自己写错的地方:executeCommand 不会因为非零退出码抛异常,所以「成功」判断必须显式看 exitCode —— 不加这一句,熔断永远不会触发。 诚实:officecli --version 在我这边(同一个 rootfs)正常返回 1.0.152,退出码 0,所以 core dump 是设备/机型特定问题,无法在沙箱复现;本版的价值是「即使崩了也不再产生文件」。 ━━ 四、Linux 能力实测(不是宣称,是跑出来的)━━ | 项 | 实测 | |---|---| | gcc | 13.3.0,编译 hello 成功 | | apt | 2.8.3 (arm64) 可用 | | Python | 中文 + emoji 输出正常 | | Node | v18.19.1 | | 中文字体 | 39 个 | | git / pandoc / texlive / tesseract | 在 | 工具描述里新增一条自检命令,模型不用再一个个试。 ━━ 五、为什么这层地基决定后面能不能做大事 ━━ 你在 App 里看到的文件 = 模型改的文件(同一目录);装的 Python 包/编译器跨会话存在(rootfs 随工作区);连续操作低开销;真 Linux 工具链;崩溃不产生垃圾。有了这五条,下一步才谈得上做「环境快照回滚」「预置工具链」「沙箱状态可视化」这类真正提效的东西。 ━━ 六、诚实边界 ━━ ①默认行为变了:依赖「每条命令干净环境」的自定义流程需显式传 session="none";②同 session 内命令串行(这是不串状态的前提);③/proc/version 权限拒绝是 proot 固有限制,LibreOffice 仍不可用(用 officecli view screenshot);④无安装实测,改动靠静态检查 + 熔断逻辑复刻验证;⑤沙箱状态可视化(App 里显示「就绪/执行中」)本版未做,留待下一批。 ★版本纪律:5.3.41 → 5.3.42(只改第三位、不进位)。 ⑩hub=v5.3.42

本次提交

  • 2ed55f9 docs: 发布链核验记录 + 两个流程问题
  • d2d3565 release: v5.3.41 — ★★文档与工具批次:溯源体系 / 结构总图 / 开工状态 + 工作流整顿(发布链本身是本轮验证对象)📐这一版没有改任何功能代码 —— 它是前面几轮「把项目理清楚」的沉淀落地,同时用一次真实发版来验证新工作流程是否可靠。 ━━ 一、本版带上的三份文档(此前只在 adopt 分支,未进 main)━━ | 文档 | 内容 | |---|---| | FILE-ORIGIN.md + .json(+ 工具 bin/origin) | 全量文件来源溯源:1353 个 .kt 中 UPSTREAM 778(57.5%) 与 3.1.0 逐字节一致 / MODIFIED 231 / PORTED 200 / PORTED-MODIFIED 67 / OURS 56 / DELETED 21。11 个命令:stats/modules/of/diff/restore/lost/untouched/ours/modified/ported/audit | | STRUCTURE-MAP.md(+ bin/symbols、bin/deps) | 四层索引:文件级(谁的文件)/ 符号级(26575 个符号,改动风险最高的是 UIMessagePart 140 文件、UIMessage 102、SettingsStore 84)/ 模块级(无循环依赖,app 唯一顶层,highlight/document/material3/oauth 是零跨模块依赖的叶子)/ 孤立声明初筛 | | CODE-NAVIGATION.md + EXTENSION-POINTS.md | 按「我要改 X」组织的导航(53 个路径引用逐条脚本验证,0 缺失)+ 加工具/渲染器/区/Provider/设置项/记忆档/路由的改法与必踩坑 | | 开工状态-2026-11-04.md | 下批次开工快照(版本/环境/工具链/代码画像/待办/六条纪律) | ━━ 二、工作流整顿(这才是本轮真正想验证的东西)━━ ① bin/watch —— 唯一 CI 查询入口:watch(最近 run + 自动比对是否就是本地 HEAD)/ watch <runId>(阻塞到终态,绿/红自带摘要,退出码 0/1)/ watch <sha>(按 commit 找 run 再等)。② bin/selfcheck —— 检查器自检(14 项探针):用已知坏样本喂每个检查器,确认它真会报错(含对照:正常文件不得误报、假 sha 必须失败、watch 必须秒回)。「基线全绿」不等于「没问题」 —— 如果检查器本身失灵,全绿是假的。③ rc release 修掉一个真实隐患:旧流程是 sleep 20 后取最近一个 run 且不校验 sha —— 新 run 还没创建时会等到上一个 commit 的 run 并判定 CI-GREEN,最终表现「CI 绿了但 release 没出来」,失败点离真因很远。现改为 run_for_sha(head_sha) 定位 + wait 内二次校验 head_sha。④ 两份 AGENTS.md(工作区根 + 仓库根):把「等 CI 只用 watch」「发版前先 selfcheck 再 audit」「验收看退出码不看输出文字」写进每次会话都会读到的位置 —— 之前这些规则写在 bin/README.md,而我不总会去翻它。━━ 三、本版确认的健康项 ━━ selfcheck 14/14;doctor 14 通过 / 0 警告 / 0 失败;audit fast AUDIT-OK;origin 1353 个 .kt;symbols 26575 个符号;deps cycles 无循环依赖;APK 79.7MB(上一版已从 85.1MB 降下来)。━━ 四、诚实边界 ━━ ①本版零功能改动 —— 全部是文档 + 工作区工具(bin/ 不随 APK 发布),所以"功能变化"这一栏是空的;②bin/ 里的工具是我的工作环境,不在仓库里、不随 APK 分发,所以这版 APK 与 v5.3.40 在功能上完全一致;③无安装实测(沙箱无设备);④工作区仍有 archive/ 833M(旧 APK 对照基准)与 _trash/ 435M(proot 权限受限,删不掉)未处理。 ★版本纪律:5.3.40 → 5.3.41(只改第三位、不进位)。★待你验证:本版功能应与 v5.3.40 完全一致 —— 如果你只是为了新功能,可以从 5.3.40 直接跳到下一版;这一版的价值在于把「代码库为什么乱、乱在哪、怎么迁移」变成了可查询的事实。 ⑩hub=v5.3.41
  • d730c36 docs: 下批次开工状态快照 + 环境整理
  • 892ed07 docs: 结构总图 + 引用关系层(deps / symbols hot,dead)
  • b4c844a release: v5.3.40 — ★★性能(零功能变更,-6.58MB)+ 代码结构化(26575 个符号可检索)📐这一轮先说一件可能不像「优化」但更诚实的事:我把标准性能热点逐项实测排除了。 ━━ 一、被实测排除的方向(避免做无用功)━━ | 方向 | 实测结果 | 结论 | |---|---|---| | 函数内正则 | 145 处 Regex(,131 已在 val;HardlineCommandGuard 的 13 个安全正则已是 private val PATTERNS | 只剩 14 处低频,收益可忽略 | | SimpleDateFormat | 16 处全在低频页面(设置/日志/错误卡片),LogPage 3 处已 remember | 不在热路径 | | LazyColumn 无 key | ChatList 主列表两处都有 key + contentType;抽屉/模型列表/工具矩阵也都有 | 已是最佳实践 | | Markdown 解析 | 已是增量解析(块级 O(δ))+ 字符预算 LRU + 跨 tick 节点复用 + 避免全量回退(v4.8.86 深度优化) | 无空间 | | Compose 内集合运算 | message 组件 7 处,但都是小集合 | 收益 < 风险 | 结论:所谓「Compose 性能十大坑」,这个项目基本都填过了。 在没有 profiling 数据的情况下改这些,是引入风险而不是优化 —— 我没做。 ━━ 二、真正的收益:死资源(可量化、零功能变更)━━ assets/ 曾占 60MB(APK 总共才 85MB)。逐个核对引用方后: | 资源 | 体积 | 判定依据 | |---|---|---| | assets/banner/ | 5.10MB | Kotlin/XML/Manifest 零引用;真实上游 3.1.1 已删除该目录 | | assets/models_dev.json | 1.48MB | ModelsDevCatalog.decode() 零调用方 —— v5.3.1 只移植了目录类与数据,依赖 ModelRegistry 重构的 ModelsDevUpdater 从未移植 | | patreon.xml | 小 | 赞助功能已删(v5.0.52),零引用 | | ic_media_creation.xml | 小 | 零引用 | 合计 6.58MB,assets/ 60MB → 54MB。 逐个确认过是活的、保留的:rin-tools/ 33.3MB(officecli 文档工具,你日常在用)、simple_dict/ 13.1MB(SimpleDictManager.extractDict() 被 AppDatabaseFactory:55 调用,FTS 分词必需)、html/ 4.2MB(mark.html + mermaid,v5.3.17 刚做过 CDN 本地化)。 为什么这算「性能」而不是「清理」:APK 体积直接影响安装时间、升级下载量、冷启动资源扫描;在「功能零变更」这条硬约束下,它是唯一可量化的收益。 ━━ 三、代码结构化:从「1353 个文件」到「26575 个可检索符号」━━ 三层索引(文件级 → 符号级 → 导航级): | 层 | 工具 | 回答什么 | |---|---|---| | 文件级 | bin/origin | 这文件是谁的(UPSTREAM/MODIFIED/PORTED/OURS)+ 能否安全回退 | | 符号级(本轮新增) | bin/symbols | 这个类/函数在哪、属于哪个类、谁在用 | | 导航级 | docs/CODE-NAVIGATION.md | 我要改 X,先看哪几个文件 | bin/symbols 实测: symbols build # 5 秒重建 → docs/SYMBOLS.tsv symbols find saveConversation symbols uses MemoryRepository symbols stats 输出: saveConversation fun ChatService. MODIFIED ChatService.kt:1704 26575 个符号 / 1262 个 .kt,71% 有明确所属类(其余是真正的顶层扩展函数,本来就没有所属类)。每个符号带来源分类(UPSTREAM 12899 / MODIFIED 7545 / PORTED 3659 / PORTED-MODIFIED 1942 / OURS 530)→ 改一个函数之前,先知道它是原版的还是我们写的。 输出是纯 TSV,可直接 grep/awk/sort,也能被任何工具消费 —— 这就是你要的「清晰文本集」的实际形态。 第一版只索引顶层声明,find saveConversation 返回「未找到」(业务方法几乎都是成员函数)→ 索引等于不可用;加「所属类」列后才有定位价值。 ━━ 四、bin/perfscan:把这轮的排查方法固化 ━━ perfscan # 全部 perfscan assets # 体积/死资源(最可量化) perfscan hot # 热路径模式 它是清单工具不是门禁(退出码恒 0)—— 每项都给出「为什么可疑」和「零变更的改法」,由人决定改不改。刻意不做「扫出 100 条就机械全改」,那只会制造风险。 ━━ 五、诚实边界 ━━ ①APK 实际减少需 CI 产物确认 —— 6.58MB 是资源原始体积,图片本就是压缩格式,接近 1:1 但非精确。②本轮没有做运行时性能优化,因为第二节的实测排除了所有标准热点;没有 profiling 数据时改 Compose 是碰运气。③无安装实测(沙箱无设备)。④ModelsDevCatalog 类保留(注释写明「要启用必须把 json 放回来」)—— 删类会让将来移植 ModelsDevUpdater 时重写解析层。 ━━ 六、下一步(有数据再做,不猜)━━ ①冷启动:adb shell am start -W 看 TotalTime;②重组计数:Layout Inspector 的 recomposition counts,只改数字异常高的组件;③滚动掉帧:adb shell dumpsys gfxinfo <pkg> framestats,看 janky frames 集中在哪个页面。 这三项数据拿到之前,任何「Compose 优化」都是猜。 ★版本纪律:5.3.39 → 5.3.40(只改第三位、不进位)。★改动:删 5 个死资源(assets/banner/ 3 图 + models_dev.json + 2 drawable)+ ModelsDevCatalog.kt 加注释;零 Kotlin 逻辑改动(功能绝对不变)。 ★待你验证:①APK 体积应从 85.09MB 降到 ~78.5MB;②启动、聊天、文档处理一切照旧(本轮没动任何逻辑);③bin/symbols find <任意函数名> 应能直接定位到文件与所属类。 ⑩hub=v5.3.40
  • b476aff docs: 建立文件来源溯源体系(FILE-ORIGIN / CODE-NAVIGATION / EXTENSION-POINTS)

构建:gate(编译+测试)→ build(assembleRelease)→ 正式版 Release

RinCore v5.3.41

Choose a tag to compare

@github-actions github-actions released this 04 Nov 06:49

RinCore v5.3.41

★★文档与工具批次:溯源体系 / 结构总图 / 开工状态 + 工作流整顿(发布链本身是本轮验证对象)📐这一版没有改任何功能代码 —— 它是前面几轮「把项目理清楚」的沉淀落地,同时用一次真实发版来验证新工作流程是否可靠。 ━━ 一、本版带上的三份文档(此前只在 adopt 分支,未进 main)━━ | 文档 | 内容 | |---|---| | FILE-ORIGIN.md + .json(+ 工具 bin/origin) | 全量文件来源溯源:1353 个 .kt 中 UPSTREAM 778(57.5%) 与 3.1.0 逐字节一致 / MODIFIED 231 / PORTED 200 / PORTED-MODIFIED 67 / OURS 56 / DELETED 21。11 个命令:stats/modules/of/diff/restore/lost/untouched/ours/modified/ported/audit | | STRUCTURE-MAP.md(+ bin/symbols、bin/deps) | 四层索引:文件级(谁的文件)/ 符号级(26575 个符号,改动风险最高的是 UIMessagePart 140 文件、UIMessage 102、SettingsStore 84)/ 模块级(无循环依赖,app 唯一顶层,highlight/document/material3/oauth 是零跨模块依赖的叶子)/ 孤立声明初筛 | | CODE-NAVIGATION.md + EXTENSION-POINTS.md | 按「我要改 X」组织的导航(53 个路径引用逐条脚本验证,0 缺失)+ 加工具/渲染器/区/Provider/设置项/记忆档/路由的改法与必踩坑 | | 开工状态-2026-11-04.md | 下批次开工快照(版本/环境/工具链/代码画像/待办/六条纪律) | ━━ 二、工作流整顿(这才是本轮真正想验证的东西)━━ ① bin/watch —— 唯一 CI 查询入口:watch(最近 run + 自动比对是否就是本地 HEAD)/ watch <runId>(阻塞到终态,绿/红自带摘要,退出码 0/1)/ watch <sha>(按 commit 找 run 再等)。② bin/selfcheck —— 检查器自检(14 项探针):用已知坏样本喂每个检查器,确认它真会报错(含对照:正常文件不得误报、假 sha 必须失败、watch 必须秒回)。「基线全绿」不等于「没问题」 —— 如果检查器本身失灵,全绿是假的。③ rc release 修掉一个真实隐患:旧流程是 sleep 20 后取最近一个 run 且不校验 sha —— 新 run 还没创建时会等到上一个 commit 的 run 并判定 CI-GREEN,最终表现「CI 绿了但 release 没出来」,失败点离真因很远。现改为 run_for_sha(head_sha) 定位 + wait 内二次校验 head_sha。④ 两份 AGENTS.md(工作区根 + 仓库根):把「等 CI 只用 watch」「发版前先 selfcheck 再 audit」「验收看退出码不看输出文字」写进每次会话都会读到的位置 —— 之前这些规则写在 bin/README.md,而我不总会去翻它。━━ 三、本版确认的健康项 ━━ selfcheck 14/14;doctor 14 通过 / 0 警告 / 0 失败;audit fast AUDIT-OK;origin 1353 个 .kt;symbols 26575 个符号;deps cycles 无循环依赖;APK 79.7MB(上一版已从 85.1MB 降下来)。━━ 四、诚实边界 ━━ ①本版零功能改动 —— 全部是文档 + 工作区工具(bin/ 不随 APK 发布),所以"功能变化"这一栏是空的;②bin/ 里的工具是我的工作环境,不在仓库里、不随 APK 分发,所以这版 APK 与 v5.3.40 在功能上完全一致;③无安装实测(沙箱无设备);④工作区仍有 archive/ 833M(旧 APK 对照基准)与 _trash/ 435M(proot 权限受限,删不掉)未处理。 ★版本纪律:5.3.40 → 5.3.41(只改第三位、不进位)。★待你验证:本版功能应与 v5.3.40 完全一致 —— 如果你只是为了新功能,可以从 5.3.40 直接跳到下一版;这一版的价值在于把「代码库为什么乱、乱在哪、怎么迁移」变成了可查询的事实。 ⑩hub=v5.3.41

本次提交

  • d730c36 docs: 下批次开工状态快照 + 环境整理
  • 892ed07 docs: 结构总图 + 引用关系层(deps / symbols hot,dead)
  • b4c844a release: v5.3.40 — ★★性能(零功能变更,-6.58MB)+ 代码结构化(26575 个符号可检索)📐这一轮先说一件可能不像「优化」但更诚实的事:我把标准性能热点逐项实测排除了。 ━━ 一、被实测排除的方向(避免做无用功)━━ | 方向 | 实测结果 | 结论 | |---|---|---| | 函数内正则 | 145 处 Regex(,131 已在 val;HardlineCommandGuard 的 13 个安全正则已是 private val PATTERNS | 只剩 14 处低频,收益可忽略 | | SimpleDateFormat | 16 处全在低频页面(设置/日志/错误卡片),LogPage 3 处已 remember | 不在热路径 | | LazyColumn 无 key | ChatList 主列表两处都有 key + contentType;抽屉/模型列表/工具矩阵也都有 | 已是最佳实践 | | Markdown 解析 | 已是增量解析(块级 O(δ))+ 字符预算 LRU + 跨 tick 节点复用 + 避免全量回退(v4.8.86 深度优化) | 无空间 | | Compose 内集合运算 | message 组件 7 处,但都是小集合 | 收益 < 风险 | 结论:所谓「Compose 性能十大坑」,这个项目基本都填过了。 在没有 profiling 数据的情况下改这些,是引入风险而不是优化 —— 我没做。 ━━ 二、真正的收益:死资源(可量化、零功能变更)━━ assets/ 曾占 60MB(APK 总共才 85MB)。逐个核对引用方后: | 资源 | 体积 | 判定依据 | |---|---|---| | assets/banner/ | 5.10MB | Kotlin/XML/Manifest 零引用;真实上游 3.1.1 已删除该目录 | | assets/models_dev.json | 1.48MB | ModelsDevCatalog.decode() 零调用方 —— v5.3.1 只移植了目录类与数据,依赖 ModelRegistry 重构的 ModelsDevUpdater 从未移植 | | patreon.xml | 小 | 赞助功能已删(v5.0.52),零引用 | | ic_media_creation.xml | 小 | 零引用 | 合计 6.58MB,assets/ 60MB → 54MB。 逐个确认过是活的、保留的:rin-tools/ 33.3MB(officecli 文档工具,你日常在用)、simple_dict/ 13.1MB(SimpleDictManager.extractDict() 被 AppDatabaseFactory:55 调用,FTS 分词必需)、html/ 4.2MB(mark.html + mermaid,v5.3.17 刚做过 CDN 本地化)。 为什么这算「性能」而不是「清理」:APK 体积直接影响安装时间、升级下载量、冷启动资源扫描;在「功能零变更」这条硬约束下,它是唯一可量化的收益。 ━━ 三、代码结构化:从「1353 个文件」到「26575 个可检索符号」━━ 三层索引(文件级 → 符号级 → 导航级): | 层 | 工具 | 回答什么 | |---|---|---| | 文件级 | bin/origin | 这文件是谁的(UPSTREAM/MODIFIED/PORTED/OURS)+ 能否安全回退 | | 符号级(本轮新增) | bin/symbols | 这个类/函数在哪、属于哪个类、谁在用 | | 导航级 | docs/CODE-NAVIGATION.md | 我要改 X,先看哪几个文件 | bin/symbols 实测: symbols build # 5 秒重建 → docs/SYMBOLS.tsv symbols find saveConversation symbols uses MemoryRepository symbols stats 输出: saveConversation fun ChatService. MODIFIED ChatService.kt:1704 26575 个符号 / 1262 个 .kt,71% 有明确所属类(其余是真正的顶层扩展函数,本来就没有所属类)。每个符号带来源分类(UPSTREAM 12899 / MODIFIED 7545 / PORTED 3659 / PORTED-MODIFIED 1942 / OURS 530)→ 改一个函数之前,先知道它是原版的还是我们写的。 输出是纯 TSV,可直接 grep/awk/sort,也能被任何工具消费 —— 这就是你要的「清晰文本集」的实际形态。 第一版只索引顶层声明,find saveConversation 返回「未找到」(业务方法几乎都是成员函数)→ 索引等于不可用;加「所属类」列后才有定位价值。 ━━ 四、bin/perfscan:把这轮的排查方法固化 ━━ perfscan # 全部 perfscan assets # 体积/死资源(最可量化) perfscan hot # 热路径模式 它是清单工具不是门禁(退出码恒 0)—— 每项都给出「为什么可疑」和「零变更的改法」,由人决定改不改。刻意不做「扫出 100 条就机械全改」,那只会制造风险。 ━━ 五、诚实边界 ━━ ①APK 实际减少需 CI 产物确认 —— 6.58MB 是资源原始体积,图片本就是压缩格式,接近 1:1 但非精确。②本轮没有做运行时性能优化,因为第二节的实测排除了所有标准热点;没有 profiling 数据时改 Compose 是碰运气。③无安装实测(沙箱无设备)。④ModelsDevCatalog 类保留(注释写明「要启用必须把 json 放回来」)—— 删类会让将来移植 ModelsDevUpdater 时重写解析层。 ━━ 六、下一步(有数据再做,不猜)━━ ①冷启动:adb shell am start -W 看 TotalTime;②重组计数:Layout Inspector 的 recomposition counts,只改数字异常高的组件;③滚动掉帧:adb shell dumpsys gfxinfo <pkg> framestats,看 janky frames 集中在哪个页面。 这三项数据拿到之前,任何「Compose 优化」都是猜。 ★版本纪律:5.3.39 → 5.3.40(只改第三位、不进位)。★改动:删 5 个死资源(assets/banner/ 3 图 + models_dev.json + 2 drawable)+ ModelsDevCatalog.kt 加注释;零 Kotlin 逻辑改动(功能绝对不变)。 ★待你验证:①APK 体积应从 85.09MB 降到 ~78.5MB;②启动、聊天、文档处理一切照旧(本轮没动任何逻辑);③bin/symbols find <任意函数名> 应能直接定位到文件与所属类。 ⑩hub=v5.3.40
  • b476aff docs: 建立文件来源溯源体系(FILE-ORIGIN / CODE-NAVIGATION / EXTENSION-POINTS)
  • 77da277 chore(workflow): 工作流整顿 — AGENTS.md 追加 RinCore 硬规则(等 CI 只走 watch / 发版前三检查 / 验收看退出码)
  • f47ae9e release: v5.3.39 — ★★★稳定性复查 + 清历史欠账:基线全绿之下,修掉两项真问题与两处腐化 📋这次不是救火 —— 复查前 bin/audit 五组就已经全绿了。 ━━ 复查前基线(先证明「没有硬问题」)━━ | 检查项 | 结果 | |---|---| | bin/audit 五组 | AUDIT-OK | | doctor | 14 通过 / 0 警告 / 0 失败 | | rc check --all | PASS | | 接线审计(wire_audit) | 0 处断线 | | 健康审计(737 文件) | MAINIO 0 / COMPOSE-IO 0 | | WebView 渲染(26 项) | 全过 | | 单测白名单硬门禁 | 4 个测试类成功 | 没有「编译不过 / 接线断裂 / 主线程 IO / 渲染回归」这类硬问题。所以这轮做的是清历史欠账,不是补窟窿。 ━━ 一、修掉的真问题(2 项)━━ ① I-12(本轮新发现):SubAgentRegistry 在 Koin 构造里做全表 DB 读。AppModule.kt:153 是 .also { it.restoreFromDisk() } —— Koin 单例首次注入时执行,而它内部 runBlocking { dao.getAll() } + 逐条 upsert。而首次注入点通常在 UI 侧(LocalTools 需要它)→ 冷启动后第一次打开对话可能卡在 DB 全表读上(子代理运行记录越多越明显)。 修:RikkaHubApp 启动的 IO 阶段主动 get<SubAgentRegistry>() —— 构造与恢复都在后台线程完成,之后 UI 再取时直接命中已初始化实例。语义零变化,只是把它提前到后台。 ② I-4:MemoryFileDAO.updateContentAny 死方法。v5.3.19 之后 update() 已用多形态匹配 + 迁移,它再没有被任何代码调用。删掉(含 FakeMemoryDAO 的 override),全库 0 处。 ━━ 二、修掉的两处腐化(不报错,但会误导下一轮排查)━━ ① ChatRequestFactory.kt:20 的死 import —— v5.3.22 删除旧 buildMemoryPrompt(List<AssistantMemory>) 重载时漏清。 ② MemoryFile.kt:192 的过期注释 —— 仍写着「让生成链的既有 buildMemoryPrompt(List<AssistantMemory>) 无需改动」,而那个重载早在 v5.3.22 就物理删除了。改为写明「唯一入口是 buildMemoryPrompt(List<MemoryFile>),旧重载已删」。 为什么把注释当 bug 修:v5.3.32 抓到过一处更恶劣的同族问题 —— lastWarmAtMs[host] 的注释白纸黑字写「v5.1.12 真 bug 修复」,但代码那一行根本没动,导致后续每一轮排查都跳过它。注释腐化会主动制造「已验证」的假信号,比没有注释更危险。 ━━ 三、I-11 那四条「疑似实现回归」——我核查了,但没改(理由很重要)━━ | 测试 | 判定 | |---|---| | delete checks the version and removes the file | 测试过期 —— v5.3.19 把 deleteFile 改成软删(写 invalidated_at),物理删除走 purgeFile;软删是有意为之(可恢复/可追溯) | | changing scope of a truly missing path reports false | 测试过期 —— updateScope 已返真实行数,旧实现恒 true | | invalidating a missing path reports false | 理论上应为 false(六形态匹配全部落空 → rows > 0 为假),需实测确认 | | MemoryFileTest > keys without an input field | 疑似误标 —— editableKeys = {name,title,description,aliases},source 不在其中,所以 source: import 会被保留,这条本应通过 | 为什么没改写断言:沙箱无 Android SDK、无 SnakeYAML 运行时 → 实跑不了。在无法实测的前提下改断言,等于用猜测制造假绿,风险远高于保留 @Ignore(至少它诚实地标记着「这条不覆盖当前行为」)。已把上述判定逐条写进 KNOWN-ISSUES 与报告,下一轮有 CI/真机环境时按此落地。 ━━ 四、⋆ 本轮新增的一条方法论(第十六个方向)━━ 「基线全绿」不等于「没问题」 —— 静态检查能覆盖的是模式(锁内挂起 / 主线程 IO / 接线断线 / 渲染回归),覆盖不了这三类: · 没人调用但存在的代码(I-4 死方法) · 注释在说谎(本轮两处) · 测试过期(I-11 三条) 这三类只能靠人工逐条对账(打开清单,一项一项追到实现)。所以「体检全绿」之后仍然有活可干,而且这些活的共同特征是:不修不会立刻坏,但会一点点把后来的人(包括我)引到错的方向。 ━━ 五、诚实边界 ━━ ①无安装实测 —— SubAgentRegistry 预热的效果(冷启动首次打开对话是否更快)需真机确认;逻辑上它把 runBlocking 从主线程移出,结构是正确的。 ②I-11 四条未落地(理由见第三节)。 ③archive/ 833M 与 _trash/ 435M 未删 —— 属你的资产/确认项,不擅自动。 ④本轮未引入任何新功能,严格限定在「稳定性 + 死代码 + 文档」。 ━━ 六、交付的文档与记录 ━━ · docs/稳定性复查-v5.3.39.md(新增,70 行)—— 基线表格 / OPEN 盘点 / I-11 核查结论 / 逐条改动理由 / 诚实边界 · docs/KNOWN-ISSUES.md(97 行)—— I-4 移出 OPEN 并进 CLOSED;新增 I-12(已修);新增「v5.3.39 关闭条目」整节(含「注释腐化是 bug 源」教训);OPEN 从 9 条收敛到 8 条,每条都写明「为什么不修」 · docs/RINCORE-经验教训库.md(327 行)—— 追加 v5.3.39 整节(4 条新教训) · docs/README.md —— 新报告进索引 · git:改动已 commit 并推 adopt-3.0.0 与 main ★版本纪律:5.3.38 → 5.3.39(只改第三位、不进位)。★改动 5 文件:RikkaHubApp.kt(SubAgentRegistry IO 预热)/ MemoryFileDAO.kt + FakeMemoryDAO.kt(删死方法)/ ChatRequestFactory.kt(删死 import)/ MemoryFile.kt(修过期注释)。 ★待你验证:①冷启动后第一次打开对话,是否比之前更顺(子代理记录多的账号更明显);②子代理的历史运行记录仍能正常显示(预热只改线程,不改数据);③其余一切应与 v5.3.38 完全一致(本轮没有功能改动)。 ⑩hub=v5.3.39

构建:gate(编译+测试)→ build(assembleRelease)→ 正式版 Release