Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,36 @@
5. README.md 的「版本历史」表只保留最近 3 版,旧版只进本文件。
-->

## v5.23.4 - 2026-11-11

### 修复

- **桌面壳导出「假成功」**(PR #344):桌面版点导出时磁盘上没有文件,界面却弹「已导出」。根因是 pywebview / WebView2 默认不放行下载(`ALLOW_DOWNLOADS` 为假时 `DownloadStarting` 被静默取消),前端 `download()` 后无条件报成功。改为 `POST /api/wb/backup/save` 由 Python 显式落盘并返回真实 path / bytes,前端只在拿到 path 时提示成功;Android 仍保持 501 回退系统下载。
- **`requirements.lock.txt` 装不上**(PR #352):两个依赖冲突让锁文件不可解——`numpy==2.5.4` 要求 Python>=3.12 而项目 `.venv` 固定 3.11,`pydantic-core==2.50.4` 与 `pydantic==2.14.2` 精确要求的 `2.50.2` 冲突。已分别回退到 `2.4.6` 与 `2.50.2`。

### 内部

- **批量依赖升级**(PR #351):fastapi 0.162.0→0.162.2、click 8.5.0→8.5.1、typer 0.27.3→0.28.0、typing-inspection 0.4.4→0.4.5;`actions/cache` v4→v6(8 处)。六个 dependabot PR 合成一笔,避免逐个把 lock 文件整文件重写。
- **依赖治理**:`.github/dependabot.yml` 对 numpy 暂缓 minor/major(解除条件=项目最低 Python 升到 3.12)。dependabot 对 `requirements*.txt` 的单包升级不做整体一致性求解,CI 又只装 `requirements.txt`(不读 lock),因此合并此类 PR 前必须真跑 `uv pip install --dry-run -r requirements.lock.txt`。
- **新增守卫**:`tools/wb_export_probe.mjs`(5 场景,钉「无 path 不报成功」)+ `tests/test_wb_export_save.py`(6 用例)。

### 已知限制(Known Limitations)

- **桌面导出只在 `desktop.py` 实跑验证**:冻结后的 exe、真实磁盘写失败路径、macOS / Linux 均未验证。
- **arm64 真机仍未点检**:v5.23.3 的两处修复(阅读页模板、退出重进补载)只在 x86_64 模拟器(`emulator` 渠道 debug 包)验证;本版 Android 侧无功能变化,但含 `static/` 改动 ⇒ 仍需覆盖安装才生效。
- **本地测试环境有既有噪声**:本机全量为 3040 passed,另有 2 failed + 3 errors 属环境问题——`test_frontend_layers` 的 GBK 控制台解码,以及 `test_player_tray_probe` / `test_probe_json_contract`(在未改动的 master 上同样失败)。CI 上全部通过。
- **重复卡存量未合并**:写入侧已幂等,未建 UNIQUE,历史重复仍在库中。

### 回滚(Rollback)

- **代码 / 产物**:可回退至 `v5.23.3` 发布包(`v5.23.1` 白屏、`v5.23.2` 阅读页不可用,均不宜作为回退目标);`build-release.yml` 由 tag 触发。
- **Android**:`versionCode` 由 `52303` 升至 `52304`,不可回滚;只能卸载重装旧 APK(会清应用私有数据,须先备份);`versionCode` 不得回拨。
- **数据位置 / 格式**:未搬移数据目录、未改变数据文件格式。
- **Schema**:零 DDL、零迁移,旧版可直接读同一 SQLite。
- **配置 / 发布通道**:无新增必需配置或密钥;git revert 可回退代码。桌面导出改由 Python 落盘后,回退版本会恢复「导出假成功」的旧行为。

---

## v5.23.3 - 2026-11-11

### 修复
Expand Down
45 changes: 23 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
# DeLector · 德语欧标沉浸精读与考点剖析工作台

<p align="center">
<img src="https://img.shields.io/badge/Release-v5.23.3-blue?style=flat-square" alt="Release Version" />
<img src="https://img.shields.io/badge/Release-v5.23.4-blue?style=flat-square" alt="Release Version" />
<img src="https://img.shields.io/badge/Python-3.10%20%7C%203.11-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python Version" />
<img src="https://img.shields.io/badge/FastAPI-0.110+-009688?style=flat-square&logo=fastapi&logoColor=white" alt="FastAPI" />
<img src="https://img.shields.io/badge/spaCy-German%20NLP-09A3D5?style=flat-square&logo=spacy&logoColor=white" alt="spaCy" />
<img src="https://img.shields.io/badge/CEFR-A1~C1%20Goethe-E63946?style=flat-square" alt="CEFR Ladder" />
<img src="https://img.shields.io/badge/AI%20Model-deepseek-brightgreen?style=flat-square" alt="AI Model" />
<img src="https://img.shields.io/badge/Tests-3037%2F3044%20Passed-2EA44F?style=flat-square" alt="Pytest" />
<img src="https://img.shields.io/badge/Tests-3040%2F3054%20Passed-2EA44F?style=flat-square" alt="Pytest" />
<img src="https://img.shields.io/badge/License-Apache%202.0-blue?style=flat-square" alt="License" />
</p>

<!-- Tests 徽章口径(可复算,非推算):**v5.23.3 发布分支本地全量(2026-11-11)**。
分子 = `python -m pytest tests` 的 3037 passed;分母 = 同一轮实跑总数 3044(passed + 5 skipped + 1 xfailed + 1 failed)。
口径说明:本机 `--collect-only` 现在报 3052,比实跑多 8 条(存在「依赖本地产物/条件跳过」的收集项),
故分母采用实跑总数,不采用 collect-only 数字——两者不等时以实跑为准。环境:Windows 11 / Python 3.11(.venv)。
那 1 条 failed 是 tests/test_frontend_layers.py::test_gate_cli_reports_file_line_rule_and_raw_line:
本机 GBK 控制台把子进程输出的中文字面量解码成乱码(在 v5.23.0 的 master 上同样失败,与本版改动无关),
Linux/CI 环境不受影响,故分子按 passed 计、不把它算成回归。
下一次本地全量重跑后 MUST 同时更新分子与分母。 -->
<!-- Tests 徽章口径(可复算,非推算):**v5.23.4 发布分支本地全量(2026-11-11)**。
分子 = `python -m pytest tests` 的 3040 passed;分母 = `--collect-only -q` 的 3054 collected
(= 3040 passed + 8 skipped + 1 xfailed + 2 failed + 3 errors)。环境:Windows 11 / Python 3.11(项目级 .venv)。
本机残留 5 条噪声,全部与本版改动无关(在未改动的 master 上同样失败):
- tests/test_frontend_layers.py::test_gate_cli_reports_file_line_rule_and_raw_line(GBK 控制台解码中文字面量)
- tests/test_player_tray_probe.py::test_player_tray_probe_clean_run
- tests/test_probe_json_contract.py 的 3 条(ERROR)
CI(Linux)上全部通过,故分子按 passed 计、不把这些算成回归。
本地 .venv 已按 `uv pip install -r requirements.lock.txt` 升到 fastapi 0.162.2 / click 8.5.1 /
typer 0.28.0 / typing-inspection 0.4.5,因此该数字覆盖了新依赖。 -->

<p align="center">
<b>专为德语学习者与歌德(A1–C1)/ 德福(TestDaF)/ DSH 备考打造的学术级伴读与句法剖析系统。</b><br/>
Expand Down Expand Up @@ -57,22 +59,21 @@ docker compose up -d --build # 或 Docker 容器化一键部署

## 多平台下载发布包

> **v5.23.3 最新版本亮点(2026-11-11)**:
> - **修复「点开文章毫无反应」**:阅读页状态模板引用了已删除的变量,一进阅读页就抛 `ReferenceError`(v5.23.1 / v5.23.2 都带)。本版已修,并用 x86_64 模拟器实测:点开文章能正常渲染正文、CEFR 光谱与跟读条。
> - **修复 Android「退出重进后停在 Webpage not available」**:首帧导航早于本地服务就绪,Service Worker 的 network-first 拿不到页面;旧逻辑见「已经在应用 origin 上」就跳过重载,于是永远停在错误页。本版在服务就绪后发现窗口里没有我们的 JS 就补载一次。
> - **若你装了 v5.23.1 或 v5.23.2,请直接升级本版**(前者白屏、后者阅读页不可用);也可回退 v5.23.0。
> - **阅读页不再把「还没准备好」显示成「加载错误」**:详情不再在请求里同步等 spaCy 分词;有旧结果先给你读,没有时显示「正在准备德语分词模型」并自动重试,只有真的打不开才给出带「重试」按钮的提示。
> - **健康检查暴露分词状态**:`/api/health` 新增 `nlp` 字段(ready / loading / error / unavailable),排障时能直接看出是模型未就绪还是真的出错。
> **v5.23.4 最新版本亮点(2026-11-11)**:
> - **桌面版导出不再「假成功」**:以前点导出会弹「已导出」但磁盘上没有文件(WebView2 默认不放行下载、请求被静默取消)。现在由 Python 显式落盘并回传真实路径与字节数,只有真正写成功才提示成功。
> - **修复依赖锁文件装不上的问题**:`requirements.lock.txt` 里 numpy 被升到只支持 Python 3.12 的版本、pydantic-core 与 pydantic 精确版本冲突;已回退到与 Python 3.11 兼容的组合。
> - **依赖批量升级**:fastapi 0.162.2、click 8.5.1、typer 0.28.0、typing-inspection 0.4.5,CI 缓存动作升到 v6。
> - **v5.23.3 的阅读页修复仍在本版**(阅读页状态模板、Android 退出重进自动补载);若你装了 v5.23.1 / v5.23.2,请直接升级本版。

> **Android 用户注意**:含 `static/` 改动的版本需**覆盖安装**才生效。
> 完整版本变更细节见 [CHANGELOG.md](CHANGELOG.md)。

| 平台 | 版本 | 说明 | 下载通道 |
| ------------------ | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| **Windows x64** | `v5.23.3` | 原生桌面窗口 + 系统托盘,免装 Python,解压双击 `DeLector.exe`;需 Win10+ 与 WebView2 运行时(Win11 自带;Win10 缺运行时的表现见[已知限制](#已知限制));首次启动把数据放到 `%LOCALAPPDATA%\DeLector` | [下载 ZIP 包 (GitHub Releases)](https://github.com/ROM4n2/DeLector/releases/tag/v5.23.3) |
| **macOS** | `v5.23.3` | 解压后进入 `DeLector-v5.23.3-macOS/`,运行其中的裸可执行文件 `./DeLector`(不是 `.app` 包)。正常 `tar -xzf` 解压会保留可执行位,若权限丢失先 `chmod +x DeLector`。包未做代码签名与公证,若被 Gatekeeper 拦截请右键「打开」,或在终端执行 `xattr -d com.apple.quarantine DeLector`。 | [下载 TAR.GZ 包 (GitHub Releases)](https://github.com/ROM4n2/DeLector/releases/tag/v5.23.3) |
| **Linux x64** | `v5.23.3` | 解压后进入 `DeLector-v5.23.3-Linux-x64/`,运行 `./DeLector`(正常 `tar -xzf` 解压会保留可执行位,若权限丢失先 `chmod +x DeLector`)。包在 CI 的 Ubuntu 环境构建,未在其他发行版验证。 | [下载 TAR.GZ 包 (GitHub Releases)](https://github.com/ROM4n2/DeLector/releases/tag/v5.23.3) |
| **Android** | `v5.23.3` | 内嵌 Python 运行时与 spaCy 离线模型,单机独立运行;正式包只出 **arm64-v8a**,CI 用 `keytool` 校验 APK 与 keystore 的 SHA256 证书指纹一致。**arm64 真机未验证**(仅 x86_64 模拟器)。 | [下载 APK 安装包 (GitHub Releases)](https://github.com/ROM4n2/DeLector/releases/tag/v5.23.3) |
| **Windows x64** | `v5.23.4` | 原生桌面窗口 + 系统托盘,免装 Python,解压双击 `DeLector.exe`;需 Win10+ 与 WebView2 运行时(Win11 自带;Win10 缺运行时的表现见[已知限制](#已知限制));首次启动把数据放到 `%LOCALAPPDATA%\DeLector` | [下载 ZIP 包 (GitHub Releases)](https://github.com/ROM4n2/DeLector/releases/tag/v5.23.4) |
| **macOS** | `v5.23.4` | 解压后进入 `DeLector-v5.23.4-macOS/`,运行其中的裸可执行文件 `./DeLector`(不是 `.app` 包)。正常 `tar -xzf` 解压会保留可执行位,若权限丢失先 `chmod +x DeLector`。包未做代码签名与公证,若被 Gatekeeper 拦截请右键「打开」,或在终端执行 `xattr -d com.apple.quarantine DeLector`。 | [下载 TAR.GZ 包 (GitHub Releases)](https://github.com/ROM4n2/DeLector/releases/tag/v5.23.4) |
| **Linux x64** | `v5.23.4` | 解压后进入 `DeLector-v5.23.4-Linux-x64/`,运行 `./DeLector`(正常 `tar -xzf` 解压会保留可执行位,若权限丢失先 `chmod +x DeLector`)。包在 CI 的 Ubuntu 环境构建,未在其他发行版验证。 | [下载 TAR.GZ 包 (GitHub Releases)](https://github.com/ROM4n2/DeLector/releases/tag/v5.23.4) |
| **Android** | `v5.23.4` | 内嵌 Python 运行时与 spaCy 离线模型,单机独立运行;正式包只出 **arm64-v8a**,CI 用 `keytool` 校验 APK 与 keystore 的 SHA256 证书指纹一致。**arm64 真机未验证**(仅 x86_64 模拟器)。 | [下载 APK 安装包 (GitHub Releases)](https://github.com/ROM4n2/DeLector/releases/tag/v5.23.4) |

---

Expand Down Expand Up @@ -197,9 +198,9 @@ DeLector/

| 版本 | 发布日期 | 里程碑概要 |
| :--- | :--- | :--- |
| **v5.23.4** | 2026-11-11 | 桌面导出改为 Python 显式落盘(不再假成功)· 修复 requirements.lock.txt 不可解(numpy / pydantic-core 与 Python 3.11 冲突)· 依赖批量升级与 CI 缓存动作 v6 |
| **v5.23.3** | 2026-11-11 | 修复「点开文章无反应」(阅读页模板引用已删除变量)· 修复 Android 退出重进停在 Webpage not available(就绪后补载一次)· x86_64 模拟器实测通过 |
| **v5.23.2** | 2026-11-10 | 修复 v5.23.1 全平台白屏(前端模块图重复导出导致解析期崩溃)· 新增「node 真链接整张模块图」守卫;**阅读页仍不可用,请用 v5.23.3** |
| **v5.23.1** | 2026-11-10 | 阅读页「未就绪显示成加载错误」修复的设计与实现;**本版前端白屏,请用 v5.23.3** |
| **v5.23.2** | 2026-11-10 | 修复 v5.23.1 全平台白屏(前端模块图重复导出导致解析期崩溃)· 新增「node 真链接整张模块图」守卫;**阅读页不可用,请用 v5.23.4** |

> 更早的版本(v5.14.0–v5.21.1 等)已完整迁入 [CHANGELOG.md](CHANGELOG.md),本页只保留最近三版。

Expand Down
6 changes: 5 additions & 1 deletion WORKMEMORY/PROJECT_OVERVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@

## 当前状态

- **最新发布 v5.23.3(2026-11-11)** —— **修复「点开文章毫无反应」+ Android「退出重进停在 Webpage not available」**(x86_64 模拟器实测通过)。
- **最新发布 v5.23.4(2026-11-11)** —— **桌面导出真落盘 + 依赖锁文件可解性修复**。
- 桌面导出(#344):pywebview/WebView2 默认不放行下载、`DownloadStarting` 被静默取消,旧前端仍无条件报成功;改为 `POST /api/wb/backup/save` 由 Python 落盘并回传真实 path/bytes,前端只在拿到 path 时报成功。
- 依赖(#351/#352):fastapi 0.162.2 / click 8.5.1 / typer 0.28.0 / typing-inspection 0.4.5 / `actions/cache` v6;并把 lock 里 numpy 2.5.4→2.4.6(要求 Py≥3.12)、pydantic-core 2.50.4→2.50.2(与 pydantic 2.14.2 精确 pin 冲突)。dependabot 对 numpy 暂缓 minor/major。
- 教训:dependabot 对 `requirements*.txt` 单包升级不做整体求解,CI 只装 `requirements.txt` 不读 lock ⇒ 合并前必须跑 `uv pip install --dry-run -r requirements.lock.txt`。
- **上一版 v5.23.3(2026-11-11)** —— **修复「点开文章毫无反应」+ Android「退出重进停在 Webpage not available」**(x86_64 模拟器实测通过)。
- ① 阅读页 `_readerStateHtml` 删了 `const bar` 却留着 `${bar}` ⇒ 点文章抛 `ReferenceError`,交互静默失效(v5.23.1/v5.23.2 均带)。
- ② 首帧导航早于本地服务就绪时,SW 的 network-first fetch 不经过 `shouldInterceptRequest` ⇒ ERR_FAILED;错误页 URL 仍是应用 origin 且不触发 `onPageFinished`,旧 `skip_reload` 判据把它当加载成功。修法:就绪后探针发现窗口里没有 `window.notifyServerReady` 就补载一次(一次性)。
- 新守卫:`test_reader_state_template_uses_only_declared_vars`(变异自证)。
Expand Down
9 changes: 9 additions & 0 deletions WORKMEMORY/work.log
Original file line number Diff line number Diff line change
Expand Up @@ -566,3 +566,12 @@ dependabot 积压 6 个 PR 一次性处理:合 1 个批量 PR(#351),其
- 顺带发现:`requirements.txt` 的 **blob 是 CRLF**(早于 .gitattributes 契约写入),`requirements.lock.txt` 与 3 个 workflow 的 blob 是 LF —— 同一仓库两种存量,任何编辑这两个方向都会触发整文件重写。本次让 `requirements.txt` 由 git `text` 属性规范化成 LF(一次性 43 行 diff,已在提交信息与 PR 正文写明),lock 与 workflow 保持 LF 零噪声。
- 验证口径:本地 `.venv` 仍是旧版本,**没有**本地证明新依赖兼容 —— 由 CI 的 `pip install -r requirements.txt` + 全量门禁裁决。PR CI 全绿(13 项);合并后 master push run `815afe9` 也 success(actions/cache v6 在 GH 托管 runner 上可用,8 处替换无告警)。
- 本地补跑:CI 定义/依赖清单相关守卫 116 passed;3 个 workflow YAML 可解析(jobs 8/5/1 不变)。

### 2026-11-11 06:05 | deepseek-v4.1-flash | DECISION
Caps: filesystem-read, filesystem-write, shell-exec, git
发版 v5.23.4(判据驱动:`git diff --stat v5.23.3..origin/master -- static/` 非空 ⇒ 有用户可见面)。
- 用户可见面来自 PR #344(桌面导出真落盘:原先 WebView2 不放行下载、请求被静默取消,前端仍报「已导出」;改为 `POST /api/wb/backup/save` 由 Python 落盘并回传真实 path/bytes)。
- 同一区间还有 #351(批量依赖升级 + actions/cache v6)与 #352(lock 可解性修复),属内部改动,不单独构成发版理由。
- **依赖事故(本轮新发现)**:#351 合并后 `uv pip install -r requirements.lock.txt` **不可解**——① `numpy==2.5.4` 要求 Python≥3.12 而项目 .venv 固定 3.11(dependabot 早先 a8ab228 单包 bump 引入)② `pydantic-core==2.50.4` 与 `pydantic==2.14.2` 精确要求的 2.50.2 冲突。修法:numpy→2.4.6、pydantic-core→2.50.2,并在 dependabot.yml 对 numpy 暂缓 minor/major(解除条件=最低 Python 升到 3.12)。
- **判据缺口**:CI 只装 `requirements.txt`、**不读 lock**,所以 dependabot 把 lock 改成不可解组合时 CI 全绿。此后合并任何依赖 PR 前必须真跑 `uv pip install --dry-run -r requirements.lock.txt`(等价「锁文件可解」探针)。
- 本地验证(项目级 .venv,不用全局 pip):`uv pip install --python ./.venv/Scripts/python.exe -r requirements.lock.txt` 成功,实际版本 fastapi 0.162.2 / click 8.5.1 / typer 0.28.0 / typing-inspection 0.4.5 / numpy 2.4.6 / pydantic 2.14.2 + core 2.50.2;升级后全量 pytest 3040 passed / 3054 collected(2 failed + 3 errors 为本地既有噪声:GBK 解码、player_tray_probe、probe_json_contract —— 已在纯 master 上用 stash 复验同样红)。
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ plugins {

// 版本号只维护一个源头:git tag。CI 从 tag 推导后通过环境变量注入,
// 本地构建无环境变量时用 fallback 默认值。
def releaseVersionName = System.getenv("DELECTOR_VERSION_NAME") ?: "5.23.3"
def releaseVersionCode = (System.getenv("DELECTOR_VERSION_CODE") ?: "52303").toInteger()
def releaseVersionName = System.getenv("DELECTOR_VERSION_NAME") ?: "5.23.4"
def releaseVersionCode = (System.getenv("DELECTOR_VERSION_CODE") ?: "52304").toInteger()

// 钉死的签名 keystore。CI 把它从 secret 解到 $RUNNER_TEMP(永不进工作树),
// 本地开发与 fork 没有这个环境变量,签名配置整段不生效、回落到 AGP 自动生成的
Expand Down
Loading
Loading