本文件是项目唯一的长期规则来源。它只保留可复用的原则、流程、环境约束和当前交付状态;一次性排障过程、界面细节、截图和临时记录不写入这里。 规则只写在
AGENTS.md。docs下为具体方面的细则与补充。需要的时候再看。
本项目是自用开发版:不得擅自添加面向用户的数据处理条数上限、章节上限、结果截断,大小限制,长度限制,或其他的“保护性”限制,用户自己搞自己炸了,自己负责。不要把用户当巨婴。。需要控制运行资源时只能采用透明、统一的调度机制,不能丢弃用户请求、静默截断数据或把限制伪装成成功;任何确需限制的外部系统约束必须直接暴露并记录原因。
版本一升级,AI 配置就重置,不管以前是什么。版本只看 AgentConfig.SCHEMA_VERSION,对不上就过期,过期就删了重建。
再次强调,版本一升级,AI 配置就重置,不管以前是什么。版本只看 AgentConfig.SCHEMA_VERSION,对不上就过期,过期就删了重建。
第3次强调,版本一升级,AI 配置就重置,不管以前是什么。版本只看 AgentConfig.SCHEMA_VERSION,对不上就过期,过期就删了重建。
不校验、不迁移、不保留旧配置,旧数据,直接重置。
禁止写任何兼容旧数据的代码!!!!!!! 直接重置!!!!!!
这是自用应用,不要在乎不存在的用户的历史数据,每次升级直接重置。
每次开始编程前,先重申并遵守以下原则:
解决根本问题,拒绝任何兜底;有问题,直接暴露。统一维护、统一修复,避免特殊代码不断膨胀。鼓励调查,鼓励详细日志和探针,鼓励联网搜索。
本项目的默认工作模式永远是纯编码模式。 用户未明确点名其他模式或验证动作时,不得启动编译、测试、运行、设备操作、动态调试、安装或回归;完成根因确认和必要源码修改后,立即提交并推送。
具体要求:
- 先定位事实、边界和根因,再修改代码;不能用静默回退、吞异常、默认值补丁或仅覆盖症状的分支掩盖问题。
- 相同问题应收敛到共同抽象、共同入口或共同数据源。新增特殊逻辑前,先证明现有统一路径无法正确表达该需求。
- 结论必须区分“已由证据确认”和“仍属假设”。复杂问题要补足日志、探针、截图或 trace,使后续排查可以复现。
- 任何失败都必须说明原因和下一步。构建异常在解决后记录现象、根因、修复方式和是否交付;只把能长期复用的结论保留在本文件,并及时修正或删除失效规则。
项目规则中已经明确规定的默认工作流属于用户未另行指定时的默认执行项,不视为擅自扩展;用户明确指令始终优先。语义不清时立即停下并询问,不自行猜测。
- 用户请求按字面含义执行,不推定隐藏含义,不擅自扩展任务范围,不以“顺便完善”“完整闭环”或其他理由追加用户未要求的工作。
- 用户要求修改某个文件、整理代码或执行其他具体动作时,只完成明确要求的事项。完成的独立修改按第 5 节 Git 规则自动分类提交;自动提交属于修改工作的固定收尾,不视为扩大任务范围,也不需要用户另行要求。
- 除全自动模式外,只有用户明确要求正式编译、安装或正式回归时,才执行对应动作。用户明确启用全自动模式后,可为解决当前问题自动执行编译、安装、运行、测试、回归和循环迭代,无需逐项再次授权。
- 用户未明确指定工作模式时,一律使用纯编码模式:确认根因后修改必要源码,完成后提交并推送,然后结束。纯编码模式禁止编译、构建、测试、运行、设备操作、动态调试、F 工具、安装和回归;只有用户明确要求其他模式或具体验证动作时才切换。
写代码和排障统一按下面的模式理解。模式决定“做到哪一步、是否进入验证、由谁操作、何时结束”,不改变根因优先、构建约束、代码修改授权和 Git 规则。
默认模式就是纯编码模式。 用户只描述问题、要求修复、要求改代码,或没有明确点名任何工作模式时,都按纯编码模式执行。只有用户明确说“低频率人工介入模式”“半自动模式 / 高频率人工介入模式”“全自动模式”,或明确要求正式编译、安装、正式回归时,才进入对应模式。任何模式都不得自行升级。
| 模式 | 触发说法 | AI / Codex 负责 | 人工负责 | 源码修改 | 编译 / 测试 / 动态验证 / 安装 / 回归 | 结束条件 |
|---|---|---|---|---|---|---|
| 纯编码模式 | 默认模式;用户未明确指定其他模式时;或明确说“纯编码模式” | 静态定位并确认根因,把解决方案直接落实到源码 | 无 | 是 | 全部不做;包括测试编译,也不得用编译找错 | 代码写完并按 Git 规则提交、推送后立即结束 |
| 低频率人工介入模式 | “低频率人工介入模式” | 排查、形成方案,并通过 F 工具把临时补丁注入当前设备进程 | 补丁注入后自行长期测试,并在下一轮反馈结果 | 默认不是;F 补丁不是源码修改 | 不自动编译、不自动测试、不自动安装、不自动回归 | F 补丁和状态悬浮窗保持有效后结束当前调试回合 |
| 半自动 / 高频率人工介入模式 | “半自动模式”“半自动调试模式”“高频率人工介入模式” | 持续运行 Frida、日志、截图、Perfetto、Winscope 等采集与分析 | 在同一连续回合中实时点击、滑动、返回、翻页、启动播放等 | 按用户授权;动态补丁可用于验证 | 不自动编译、不自动测试、不自动安装、不自动回归;仅做当前运行进程上的动态诊断/验证 | 在同一回合持续复现、观察、分析,直到当前问题确认或用户停止 |
| 全自动模式 | 仅当用户明确说“全自动模式” | 完整接管问题闭环:自主复现 → 定位根因 → 修改源码 → 提交并推送 → 自动编译 → 自动安装和运行 → 自动测试和回归;如果问题仍未解决,继续重复以上流程直到问题收敛。 | 无 | 是 | 是;这是所有模式中唯一会主动自动编译、自动测试并持续循环迭代的模式 | 自动循环直到修复被验证通过,或证据证明当前方案不可行并形成明确结论 |
| 正式验证 / 交付 | 用户明确要求“正式编译”“安装”“正式回归”“完整验证闭环”或交付 | 按用户明确授权执行对应正式动作 | 仅在明确需要人工操作时参与 | 已完成的源码必须先提交 | 是,仅执行用户明确要求的部分 | 对应正式动作完成并记录结果;完整闭环为 appC 编译 → 设备安装 → 复现与回归 |
这是最轻量、也是默认的源码修改模式:找到原因 → 把问题落实到代码 → 写完立即提交并推送 → 到此结束。 纯编码模式的目标是完成代码修改,不承担任何验证工作。
- 先通过源码、调用链、配置、已有日志、仓库搜索和现有证据定位并确认根因;不得为了找错、确认能否通过或提前发现小问题而启动编译、构建或测试。
- 确认原因后只修改解决该问题所必需的代码;不顺手增加测试、动态探针、额外重构、文档或其他非必要工作。
- 写完后只做静态收尾检查,例如
git diff/git status和必要的代码审查;这不属于运行验证。随后立即按第 5 节 Git 规则提交并自动推送,不等待用户另行要求。 - 纯编码模式禁止任何验证性操作,包括 Gradle 编译、构建、测试、Lint、启动 APP、设备操作、ADB、uiautomator2、Frida/F 工具、截图、logcat、Perfetto、Winscope、安装和回归;也不得新增、修改或删除测试和 CI 文件,或为了测试额外修改生产代码。
- 这样做是为了避免编译同时占用时间和大量内存,并避免多个并行编码请求与正式编译争抢构建资源。纯编码阶段允许把尚未暴露的编译小错误留到之后的正式编译阶段统一发现和处理,不得为了提前消灭这些错误而把纯编码模式升级成验证模式。
- 只有用户明确要求某项验证动作或明确切换到其他模式时,才执行该动作;否则代码提交、推送完成即结束。
这是“AI 完成动态方案,人工之后慢慢测试”的模式。
- AI 先完成原因排查和动态方案验证所需准备,再通过 F 工具把补丁注入当前设备中正在运行的阅读C-自用(appC)进程。
- 补丁注入成功后,不设置自动失效时间,并同时显示持续可见、足够醒目的状态悬浮窗,明确标记“Frida 补丁已注入并生效”。
- 补丁与悬浮窗保持同一生命周期;补丁仍有效时,悬浮窗不得自行消失。
- 注入完成后结束当前调试回合,不继续要求人工实时配合;之后由人工自行测试,并在下一轮对话反馈结果。
- F 工具补丁属于运行时临时验证,不等于把补丁写入源码。
“半自动模式”“半自动调试模式”和“高频率人工介入模式”视为同一套协作协议:AI 持续采集和分析,人工实时操作界面。
- 调试工具链由 Codex 持续运行和采集,包括显式目标的 ADB、uiautomator2、截图、logcat、Perfetto、Winscope 和 Frida;根据当前问题和假设选择需要的工具,不设固定升级层级。
- 界面操作由用户实时完成,包括点击、滑动、返回、打开菜单、启动播放和翻页。Codex 根据当前排障目标持续准备采集、观察和分析,不要求用户逐轮确认下一步。
- 这是一个连续调试回合,不得把每个操作拆成“先停下来询问、等待回复、再启动工具”的串行流程;工具采集、日志读取和证据对齐应在用户操作窗口内持续进行。
- Codex 可以在 commentary 中简短说明当前正在监听的目标和所需操作,但不得重复已经明确的操作指令,也不得因为等待用户操作而结束调试回合。
- 人工每次操作后,AI 立即继续观察和分析,不把结果留到下一轮再处理。
- 每次复现必须记录开始时间、用户操作窗口、结束时间和使用的设备。
- 本模式不改变构建约束、诊断与动态验证规则或代码修改授权。
这是用户明确点名后才启用的最高强度工作模式,也是所有模式中唯一会自动编译、自动测试、自动安装/运行并持续循环迭代的模式。它不是“只做动态诊断”,而是由 AI 完整接管从定位到最终验证的整个工程闭环。
- 启用后,AI 不再等待用户逐项授权编译、安装、测试或回归;这些动作属于全自动模式本身的固定权限。
- 全自动模式按以下流程循环执行:自主复现 → 定位根因 → 修改源码 → 提交并推送 → 正式编译
appC→ 安装到目标设备 → 自动运行、测试和回归。若验证失败,直接进入下一轮修复,直到问题解决或确认当前方案不可行。 - AI 自主选择 ADB、uiautomator2、截图、logcat、Frida、Perfetto、Winscope 等工具;Frida 既可用于定位,也可用于在正式编译前快速验证假设,但不能替代最终自动编译后的实际回归。
- 编译或测试暴露出的源码错误、资源错误、运行错误或新回归,直接进入下一轮修复,不停下来等用户确认;这正是全自动模式与其他模式的核心区别。
- 每一轮正式编译、安装、产物校验和回归仍必须遵守第 3 节的版本、构建和产物约束;“自动”只表示无需逐项人工授权,不表示可以绕过正式构建规则。
- 结束条件是:当前问题已在自动编译后的真实 APK 上完成自动复现与回归并确认解决;或者经过自动迭代后有充分证据证明当前方向不可行,并形成明确原因与下一步。
正式验证不是排障模式的自动下一步,而是独立授权层级。
- 用户只要求“正式编译”“安装”或“正式回归”其中一项时,只执行该项,不自行补齐其他动作。
- 用户明确要求“完整验证闭环”时,执行:正式编译
appCAPK → 安装到目标设备 → 复现并回归验证。 - 所有正式动作继续遵守第 3 节的构建、版本和产物约束。
- F 工具就是 Frida。 用户说“F 工具”时按 Frida 理解。
- “用 F 工具推上去永久有效”表示:把补丁通过 Frida 注入到当前设备中正在运行的阅读C-自用(appC)APP,并且不设置失效时间,用于持续验证方案可靠性;不是把补丁写进源码。
- 任何需要持续有效的 F 工具补丁,注入成功后必须同时显示持续可见、足够醒目的悬浮窗,明确标记“Frida 补丁已注入并生效”;补丁仍有效时悬浮窗不得自行消失。
- 用户明确要求正式验证或交付代码改动时,只能使用正式
appC变体:app\build\outputs\apk\app\c。禁止以中间 Gradle 任务、debug APK 或改名旧包充当正式验证/交付物。 - 正式编译必须使用目标分支最新且已经提交的完整源码和资源。禁止从旧提交、detached worktree、临时快照或其他落后副本构建。编译前确认目标分支、
HEAD和工作区一致;编译期间如果目标分支出现新提交,必须基于新的分支头重新编译。 - 覆盖安装前必须显式传入
VERSION_CODE和VERSION_NAME。VERSION_NAME仅用于展示,格式为3.26.MMddHH:其中3.26后面的MMddHH是 UTC(世界零点)编译时间(月份、日期、小时),因此版本名按 UTC 时间记录。 - 如果 APK 或本文件基线里的
versionName时间部分异常、跑到未来,直接按正确的 UTC 时间修正即可;这不会触发降级,因为安卓升级、降级判断只看versionCode。 VERSION_CODE是与时间无关的独立整数序号,不是时间戳,不得按日期解读或计算;每次交付只需比最近一次交付的VERSION_CODE大,保持单调递增。appCflavor 会自动添加版本名后缀c,传给-PVERSION_NAME的值不得包含c。最终必须以aapt输出为准,产物版本名应为3.26.MMddHHc。- 若只是 APK 文件名末尾的
c多一个或少一个,或文件名中的versionName文本写错,而aapt dump badging确认 APK 内部versionName、versionCode和包名均正确,直接修正文件名或记录即可,不得为此重新编译;只有 APK 内部元数据确实错误时才重编译。 - 编译前直接使用第 6 节的最近交付基线,不查设备已安装版本。确认新版本后,只删除
app\build\outputs\apk\app\c中对应的旧 APK,绝不删除宽泛目录或源码。
- JDK:
C:\Program Files\Eclipse Adoptium\jdk-17.0.19.10-hotspot - Android SDK:
D:\AI\audio\android-sdk - Gradle user home:
D:\AI\audio\android-gradle-user-home - Gradle wrapper:
8.14.4; compileSdk:36
$OutputEncoding = [Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)
$env:JAVA_HOME = 'C:\Program Files\Eclipse Adoptium\jdk-17.0.19.10-hotspot'
$env:ANDROID_HOME = 'D:\AI\audio\android-sdk'
$env:ANDROID_SDK_ROOT = 'D:\AI\audio\android-sdk'
$env:GRADLE_USER_HOME = 'D:\AI\audio\android-gradle-user-home'
$env:Path = @(
"$env:JAVA_HOME\bin",
"$env:ANDROID_HOME\cmdline-tools\latest\bin",
"$env:ANDROID_HOME\platform-tools"
) + ($env:Path -split ';') -join ';'
$versionCode = <new-version-code> # 独立递增整数,不是时间戳
$versionName = '3.26.<MMddHH>' # <MMddHH> uses UTC; appC automatically appends c
.\gradlew.bat ':app:assembleAppC' '-Pabi=arm64-v8a' "-PVERSION_CODE=$versionCode" "-PVERSION_NAME=$versionName" --console=plain --warning-mode=summary- 任何可能长时间运行的命令都必须监控实际进度;以进程、CPU、日志和产物是否持续变化判断是否仍在运行,不得无限等待,也不得仅凭启动器退出或工具超时误判任务失败。
- 构建失败时先读取实际错误、文件、行号和异常信息,再判断根因;不得在没有证据时把源码错误、文件锁、缓存问题或内存问题混为一谈并盲目重跑。
- 只有证据明确指向缓存、Gradle/Kotlin 进程、文件锁或内存问题时,才执行对应的进程清理、冷编译或局部构建目录清理;不得无依据删除整个构建目录,也不得终止不属于本次任务的进程。
- 同一检出目录同时只允许一个正式构建。构建结束、中断或失败后,必须清理属于本次构建的残留进程;构建结果以真实日志、退出状态和产物校验为准。
主代码只经 app/src/main/java/io/legado/app/plugin 的空接口与注册表(ReadAloudEngines / TtsVoiceDirectories / 各 flavor 的 AppPlugins.init)接触专有功能;插件缺失时主代码正常运行:引擎列表不渲染该行、路由到未内置引擎 id 明示回退系统 TTS、AI 选角在发音人目录缺失时自动降级。
版本与应用名:自用版(assembleAppC / io.legado.app.dev)应用名 阅读C-自用;公开版(assembleOssRelease / io.legado.app.c)应用名 阅读C。文档、Release 正文、日常交流一律使用上述应用名,不得再把自用版称为"阅读C"。
- 自用版使用
assembleAppC,应用名固定为阅读C-自用,包名固定为io.legado.app.dev。appflavor 会包含app/src/app中的全部专有功能和依赖,并通过自有AppPlugins注册;自用版与公开版包名不同,可同时安装。 - 公开版使用
assembleOssRelease,应用名固定为阅读C,包名固定为io.legado.app.c,版本名为3.26.MMddHH,不带后缀。ossflavor 不包含app/src/app中的任何专有源码、so、组件声明或专有依赖。 - 新增专有功能一律放
app/src/app(或另开 flavor 专属源集)并在自有AppPlugins注册;开源构建自动剥离。 - 若公开发布整个仓库源码而非仅 APK,
app/src/app下的专有代码会随源码泄露,需要导出过滤(只发布 APK 不受影响)。
编译选择规则(默认自用,按用户点名才变):
- 用户未指明构建路线时,"编译/正式编译/交付"一律指自用构建
assembleAppC(阅读C-自用),完全沿用"不可变交付约束"与本节的版本、产物规则;不得自行切换成开源构建。 - 仅当用户明确要求“开源编译”“发布编译”或“oss 编译”时,才执行
assembleOssRelease;构建时传入-PVERSION_CODE和-PVERSION_NAME,版本名不带c后缀,产物位于app\build\outputs\apk\oss\release\,并使用aapt和apksigner验证;公开版固定包名为io.legado.app.c、应用名为阅读C。不得将assembleOssRelease产物作为自用版交付,也不得将assembleAppC产物作为公开版发布。 - 用户明确要求"双编译"时,两个构建都执行:先自用
assembleAppC,再开源assembleOssRelease,各自完整走一遍版本传参与产物验证;两包包名不同(自用io.legado.app.dev/ 公开io.legado.app.c),互不影响覆盖安装,可共存装在同一设备。 - 只允许构建两个 release 系产物:自用版
assembleAppC和公开版assembleOssRelease,绝对禁止任何 debug buildType。自用版(appC)沿用 SDK 自带的 debug 签名;公开版(oss)改用仓库根signing/debug.keystore(与 SDK debug 同口令体系、不同密钥,证书 SHA-256 见 README 签名说明);signing/只存本地、私有备份,公开镜像剥离,公开克隆缺文件时自动回退 SDK debug 签名;所有 APK 必须通过apksigner验证。
开源源码发布(历史清洗镜像):
- 远程
origin(CCSSNE/legadoC)是公开仓库(默认分支own)。origin/own= 本地完整历史剥离专有路径后的清洗镜像;本地own= 完整私有历史,同步推送私有备份仓private(CCSSNE/legadoC-private,已验证private:true)。 - 所有专有和自用代码必须放在剥离清单指定的路径中,现行专有代码统一放在
app/src/app;signing/(公开版签名密钥)同样只存本地,公开镜像剥离。AGENTS.md、docs、tools不在剥离范围,会随公开历史发布;新增专有功能前必须确认对应路径已经加入剥离清单。 - 严禁把本地
own直接git push到origin/own:两边历史不同,非快进必被拒(这是防泄露保护,不得绕过);强推会把专有历史重新公开。(私有备份仓private收的就是完整历史,直接git push private own快进属正常操作,不在禁止之列。) - 公开源码只能通过仓库根目录的
publish-oss-source.ps1发布。脚本负责临时克隆、剥离专有路径、校验历史、生成公开镜像并推送到origin/own,同时把完整私有历史推送到private。禁止绕过脚本直接把本地own推送到origin/own。 - 已有 fork 与 GitHub 服务端缓存可能仍留存清洗前的旧对象;需要彻底清除时联系 GitHub Support(remove sensitive data)。
- 剥离清单改动必须同步脚本头部注释与本节;新增专有功能若不放进剥离清单所列路径(新专有功能一律放
app/src/app),必须先更新剥离清单再发布。 - README 等随公开镜像全文公开:更新记录只写开源构建(oss flavor)也包含的主代码功能,专有功能(百度引擎等)一律不得写入 README;写入前按功能对应源码是否在
app/src/main判定,不确定时先查源码位置再落笔。
$apk = 'D:\AI\audio\legadoC-own\app\build\outputs\apk\app\c\legado_app_<version>.apk'
& "$env:ANDROID_HOME\build-tools\36.0.0\aapt.exe" dump badging $apk
& "$env:ANDROID_HOME\build-tools\36.0.0\apksigner.bat" verify --<
8000
/span>print-certs $apk交付前确认两版身份:公开版(阅读C)= 包名 io.legado.app.c、应用名 阅读C、产物来自 assembleOssRelease;自用版(阅读C-自用)= 包名 io.legado.app.dev、应用名 阅读C-自用、产物来自 assembleAppC;两版版本号均需递增、arm64-v8a、apksigner 退出码为 0。部分 META-INF 条目未受签名保护的提示可接受。
应用名核对是强制校验项(2026-09-02 明文):aapt dump badging 输出的 application-label-zh(及 application-label 默认值)必须逐字匹配目标版本的应用名——自用版为 阅读C-自用、公开版为 阅读C。aapt 输出与预期不符即视为构建失败,不得宣称验证通过;严禁只看 package/versionCode/versionName/native-code 就判定符合标准。核对命令固定如下,必须检查截取结果中的 label 值:
& "$env:ANDROID_HOME\build-tools\36.0.0\aapt.exe" dump badging $apk | Select-String -Pattern "application-label-zh:|package:"- 应用名由各版本独立源集决定,修改时必须同步核对:自用版 appC 由 buildType
c源集app/src/c/res/values*(/strings.xml)覆盖(app_name、app_name_sigma、receiving_shared_label);公开版 oss 由 flavoross源集app/src/oss/res/values*(/strings.xml)覆盖。main 里的@string/app_name(阅读 C)只是共享兜底,不是任何版本的实际交付名。
UI 设计相关规则(无头弹窗策略、UI 内核与浮层规范、异步 UI 与局部模糊)已单独维护在 docs/ui-design-spec.md。
- 应用主题统一为
Base.AppTheme(Theme.AppCompat.DayNight系),对话框窗口主题同属 AppCompat 家族。MaterialButton在构造器强制校验Theme.MaterialComponents主题(TabLayout、FloatingActionButton、TextInputLayout 均无此强制校验),放进任何对话框布局都会在 inflate 时直接崩溃;布局禁止使用这类强制校验控件,弹窗与列表条目按钮统一用<Button>+?android:attr/buttonBarButtonStyle+@color/selector_btn_text_color。
每个设置的界面默认值与实际读取默认值必须一致:
- 界面默认值在
app\src\main\res\xml\pref_config_*.xml的android:defaultValue。 - 实际默认值在
AppConfig.kt及各调用点的getPrefBoolean、getPrefInt、getPrefString。getPrefBoolean(key)不带默认参数时默认是false。 - 修改任意设置默认值时,全库搜索该 key 的所有读取点,逐一核对类型和值;界面显示与实际行为不一致属于缺陷,不能接受“默认分支行为等价”作为理由。
- 背景图这类文件型默认值不能写成某台设备的绝对路径。必须把素材随 APK 提供,并由统一主题初始化在
applyDayNightInit()前复制到应用私有目录,再为尚未配置的日间/夜间 key 写入该稳定路径。backgroundImage/backgroundImageNight缺失表示从未配置;空字符串表示用户明确移除背景,后续启动不得覆盖。 uiLayoutAlpha的值表示“全局界面透明度”:0为不透明、100为全透明。数值到物理表面 alpha 的换算只能在UiCorner.uiLayoutSurfaceAlpha()中发生;普通 UI、底栏玻璃外壳和液态玻璃内容均复用该入口,业务页面不得再自行反向计算。
工作模式的定义、人工介入频率和 F 工具持续补丁规则统一见第 1 节“工作模式与执行层级”。本节只定义所有调试模式共同使用的诊断能力。
- ADB、
uiautomator2、截图、logcat、源码检查、运行时对象检查、Frida、Perfetto、Winscope 都可以参与找原因、收敛假设和验证现象;它们是并列的诊断工具,需要什么,用什么。 - Frida 本身既是找原因的工具,也是验证解决方案的工具:可以用
trace、运行时对象检查或 Hook 观察真实行为、试探变量、缩小原因范围;不需要等其他工具先得出结论后才能使用。 - 动态验证只能证明当前运行环境中的假设与方案;不能被可靠等价注入的资源/XML、Manifest、Gradle、native 或类结构改动,必须明确标记为“Frida 未完整验证”,不得冒充正式 APK 回归。
理想环境操作: uiautomator2 / ADB │ ▼ ──────── AI ──────── │ │ │ │ │ └── Perfetto │ │ 看时间/线程/帧 │ │ │ └────────── Winscope trace │ 看 Window/Surface │ └────────────────── Frida / AI Debug Probe 看真实运行时对象和调用链
AI 铁律(死路,见到先复述给用户再定夺):模型永远只当参数,不配自己的东西;大模型只认通用协议,要接别的协议就在上面写转接层,下游不动;画图/视频参数相同的模型挤一个供应商,不同的复制一个供应商。想原生兼容 Anthropic、谷歌、OpenAI Response 协议,或把配置绑到模型上,属于吃饱了没事干,此路不通。全文见 AiCreationProviderStore 头部注释。
- 发布前重新执行第 3 节的 APK 验证。tag 必须为
v<versionName>,与 APK 版本名一致;target_commitish指向own分支最新提交。 - Release 正文通过 UTF-8 无 BOM JSON 文件提交:设置
PYTHONUTF8=1,用json.dump(..., ensure_ascii=False)生成(本机一律用python;python3.exe只是 WindowsApps 存根,调用无输出无动作),并使用curl.exe --data-binary "@<file>"。不得将中文正文或二进制通过 PowerShell 文本管道传递。 - APK 上传使用
Content-Type: application/octet-stream和curl.exe --data-binary @<apk>。 - 发布后通过 API 和 GitHub 网页复查中文、排版、
draft=false、prerelease与用户要求一致(正式版为false,用户点名 Pre 版时为true)、tag、目标提交、资产大小和下载 200;发现乱码则用 UTF-8 无 BOM JSON PATCH 后重新复查。Pre 版创建时显式传"make_latest": "false",使Latest标记保持在正式版不动。 - 公开仓库(
origin/ CCSSNE/legadoC)的 Release 只允许上传文件名含oss的公开版 APK(assembleOssRelease产物,包名io.legado.app.c、应用名阅读C);自用版 APK(assembleAppC产物,包名io.legado.app.dev、文件名legado_app_*)绝对禁止作为资产出现在公开仓库的任何 Release(含 Pre 版)。判定以aapt包名为准,改名不算数。 - 上一条是软性流程钩子:Git 钩子拦不到 Release 通道(网页 /
gh/ API 上传不经过本地commit/push),只能靠上传前执行第 3 节产物验证并核对文件名含oss来自觉遵守;上传后按上一条复查Release资产,发现历史误传立即删除对应资产。
-
git 提交必须为中文说明。 如果遇到历史的提交是英文说明,也会顺手改为中文,并且强推到线上。
-
提交前检查
git status、git diff、git log。只暂存本次需要的文件,不提交 APK、构建日志、trace 或临时文件。 -
提交信息简洁且准确,遵循现有仓库风格。
-
项目不使用远程 CI:
.github/workflows下全部工作流已移除,远程 Actions 无存量运行负担。单元测试与编译检查一律在本地执行;不得重新引入或恢复远程 CI 工作流。 -
每个独立修改完成并通过代码审查后必须立即自动创建一个只包含该修改的 Git 提交,不等待用户另行要求,也不能把多个无关修改堆积后一次提交。正式 APK 编译只能在这些提交完成后开始;正式编译、安装和回归通过后,再提交版本基线与验证记录。发生回归时只允许从这些明确提交边界回退,禁止猜测性撤销工作区文件。
-
本地出现新提交后,立即运行
publish-oss-source.ps1:把清洗后的公开镜像同步到origin/own,并把完整私有历史同步到private。禁止直接git push origin own。自动推送只包含 Git 提交,不包含 GitHub Release;Release 必须由用户明确要求后才能创建。
仅保留最近一次已交付版本,下一次覆盖安装必须在此基础上递增:
- 最近一次自用版交付为
3.26.100716c/10900,2026-10-07,基于提交033bb147(README 追加 2026-10-08 更新记录;其前为 21 条 legado-sk 移植修复 + 10 条人工修补提交)使用assembleAppC编译成功(BUILD SUCCESSFUL in 1m 20s,75 actionable tasks: 13 executed, 62 up-to-date)。产物包名io.legado.app.dev、versionName3.26.100716c、versionCode10900、架构arm64-v8a,aapt确认应用名阅读C-自用(label-zh 逐字匹配)、apksigner verify退出码 0;APK 位于app\build\outputs\apk\app\c\legado_app_3.26.100716_10900.apk(47.84 MB),尚未安装。 - 最近一次公开版交付为
3.26.100717/10901,2026-10-07,基于提交ea32a2ed(README 追加公开版签名说明;改用signing/debug.keystore签名)使用assembleOssRelease编译成功(BUILD SUCCESSFUL in 2m 2s,121 actionable tasks: 21 executed, 100 up-to-date)。产物包名io.legado.app.c、versionName3.26.100717(无 c 后缀)、versionCode10901,aapt确认应用名阅读C(label-zh 逐字匹配),apksigner verify --print-certs确认证书 SHA-256 为仓库密钥70:CB:…:89:5C(非 SDK debug)、退出码 0;APK 位于app\build\outputs\apk\oss\release\legado_oss_3.26.100717_10901.apk(37.76 MB),已发布正式版v3.26.100717(release id405987454,prerelease=false,复查 tag/目标分支/中文正文/签名变更说明/资产 39598825 字节与下载 200 均正常;v3.26.100716(SDK 签名)已删 Release 及 tag 下架)。
每次交付后当场更新本节。历史发布信息应从 Git、GitHub Release 或提交记录查询,不在本文件累积。