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
11 changes: 11 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
* text=auto
*.cs text eol=lf
*.java text eol=lf
*.swift text eol=lf
*.sh text eol=lf
gradlew text eol=lf
*.traineddata binary
*.png binary
*.jar binary
*.icns binary
*.ico binary
42 changes: 42 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Native builds
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Build and test SwiftUI app
run: xcodebuild -project WriteBench.xcodeproj -scheme WriteBench -configuration Debug -derivedDataPath build -destination 'platform=macOS' CODE_SIGN_IDENTITY=- test
windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Publish WPF app
run: dotnet publish platforms/windows/WriteBench/WriteBench.csproj -c Release -r win-x64 --self-contained true -o publish
- name: Validate domain and real OCR
shell: pwsh
run: |
Copy-Item Documentation/TestImages/ocr-sample-1.png publish/ocr-fixture.png
$result = Start-Process "$pwd/publish/WriteBench.exe" -ArgumentList '--self-test' -Wait -PassThru
if ($result.ExitCode -ne 0) { Get-Content publish/self-test-error.txt; exit 1 }
Get-Content publish/self-test-passed.txt
android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
- name: Build APK and run unit tests
working-directory: platforms/android
run: ./gradlew :app:testDebugUnitTest :app:assembleDebug --no-daemon
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ local.properties
**/obj/
**/build/
Documentation/codex-live-check.json

# Per-machine IDE settings
.idea/
*.iml
3 changes: 3 additions & 0 deletions Design/Exams/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Exam navigation symbols

Original category illustrations: graduation cap (Kaoyan), open book (CET-6), globe (IELTS). They are navigation symbols, not official examination logos or endorsements. Native app variants use the same visual concepts through SF Symbols, WPF paths and Android Canvas.
1 change: 1 addition & 0 deletions Design/Exams/cet6.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions Design/Exams/ielts.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions Design/Exams/kaoyan.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Documentation/Images/windows.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions Documentation/Providers.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# AI grading providers — 1.2
# AI grading providers — 1.3

Defaults verified on 2026-09-13:

Expand All @@ -12,7 +12,7 @@ Each role has its own provider selector. A submission freezes the selected confi

## Direct key entry

A user pastes a DeepSeek key and clicks **使用此 Key**. It works immediately from process memory, without accessing an old Keychain item. **在这台 Mac 上记住 Key** is optional and defaults off. No key is stored in UserDefaults, SwiftData, source, logs or a release package. Keychain reads and updates disallow authentication UI; an inaccessible item asks the user to enter the API key again. A failed optional save leaves the in-memory key usable and reports that it could not be remembered.
A user pastes a DeepSeek key and clicks **使用此 Key**. It works immediately from process memory, without accessing an old Keychain item. **在这台 Mac 上记住 Key** is optional and defaults off. No key is stored in UserDefaults, SwiftData, source, logs or a release package. Submission reads memory only. Explicit persistence and opt-in startup restoration run off the UI thread using a new data-protection Keychain item, with authentication UI disallowed. Legacy development items are never queried. An inaccessible item leaves the user able to enter the API key again. A failed optional save leaves the in-memory key usable and reports that it could not be remembered.

Missing keys block both typed and OCR-confirmed submissions before any provider receives the essay. The draft is saved; the user can continue answering or open Settings. Clearing a key or quitting clears the session key. Remembered keys follow macOS Keychain storage rules.

Expand Down
31 changes: 31 additions & 0 deletions Documentation/Validation.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
# 1.3.0 validation · 2026-09-13

## macOS

- Xcode 26.6, macOS 26.6.2; deployment target macOS 15.
- 29 Swift tests pass, including independent concurrency, strict JSON, local median/spread, cancellation, provider routing, subprocess timeout/cancellation, SwiftData, real Vision OCR, mandatory immersion, rewrite persistence, missing credentials, and Chinese translation submission.
- Checked the actual native English II preparation and full-screen answer sheet. Chinese text enables Hand In. No live word counter appears.
- Found and fixed a real legacy Keychain call blocking the UI. Verified the final native Hand In flow immediately displays the missing DeepSeek API Key alert and retains the draft. Submissions now read memory only; explicit persistence/restoration happens in the background using a new data-protection Keychain item. Legacy development items are untouched.
- Universal arm64 + x86_64 Release build; signature and disk image checks recorded with published artifacts.

## Windows preview 0.1.0

- Built on Windows 11 x64 with .NET SDK 10.0.401. Native WPF executable; self-contained .NET runtime.
- Actual executable self-test passes median, spread, missing/duplicate reviewers, task scales, bundled rubrics, required JSON properties, serialization, and real Tesseract OCR of the repository's synthetic image.
- The real WPF preparation view was rendered at 1320 × 840 for visual inspection with an isolated temporary store. This is view rendering, not a manual live network grading test.
- Eight tasks, independent DeepSeek/Codex configuration, OCR confirmation, history, rewrite and basic statistics implemented. Windows Codex was not logged in on the test host, so no claim of Windows Codex live grading is made.

## Android preview 0.1.0

- Built using the user's installed Android Studio JBR and SDK: Gradle 8.13, AGP 8.13.2, compile/target SDK 35, minimum API 33.
- Five JUnit tests cover translation directions/scales, Chinese answer aggregation, disagreement, incomplete/duplicate judges, exact correction spans and missing-Key rejection.
- Signed release APK passes apksigner verification and installs successfully on the Android 15 ARM64 emulator. The app was built and launched from the installed Android Studio; the actual phone preparation screen was visually inspected. Interactive keyboard/rotation behavior has not been manually verified across physical devices.
- Two Android 15 device tests pass: real bundled ML Kit OCR of the synthetic image, and atomic local history with a Chinese rewrite that preserves the original.
- On-device ML Kit OCR is bundled for Chinese and Latin text. Three real DeepSeek providers are required; no demo grading is in the shipped app.

## Live provider scope

GPT-6 Astra/MAX completed a sample through the actual macOS Swift subprocess service. DeepSeek's official models endpoint was verified with the temporary user-supplied Key. That Key was not committed and has expired. A complete mixed three-provider paid grading session is not claimed as verified; users must enter their own current Key.

---

# WriteBench 1.1.0 — validation

2026-09-13, Xcode 26.6, Swift 6.
Expand Down
4 changes: 2 additions & 2 deletions Documentation/macOS-guide.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# WriteBench 1.2
# WriteBench 1.3

A real native macOS exam-writing workstation, built with Swift 6, SwiftUI, AppKit, SwiftData, Vision and Swift Charts. No web wrapper, external runtime or third-party app dependencies.

Expand All @@ -14,7 +14,7 @@ Double-click **WriteBench.app** in this folder, or open **WriteBench.xcodeproj**

## The writing workflow

1. Choose 考研英语 (英语一小作文/大作文), CET-6 Writing, or IELTS Academic Task 1 / Task 2.
1. Choose 考研英语 (英语一小作文/大作文、英语一/二翻译), CET-6 writing/translation, or IELTS Academic Task 1 / Task 2.
2. Use the supplied **original practice question**, edit/paste your own, or import an image. The pencil beside the question toggles its plain-text editor. 真题库 saves your own labelled question sources; bundled exercises are not presented as past papers.
3. Click **开始答题** (or **⌘Return**) to enter the only answering workspace: native full-screen immersion. Preparation has no essay editor or grading button. The sidebar, exam tabs and decorative cards disappear. The question stays on the left and your answer on the right.
4. The timer starts when you start answering. Kaoyan and CET-6 use a ruled answer area with **no live word count**; IELTS retains a small word count. This is a practice writing surface, not a claim of exact official answer-card dimensions. Native undo/redo and copy/paste remain available through standard shortcuts, without a formatting toolbar. **保存并离开** saves the draft and pauses its timer; continuing requires **开始答题** again. Switching away from the app during an active session does not stop the exam timer. Leaving macOS full screen through the system controls still leaves you in the same minimal answering workspace.
Expand Down
34 changes: 23 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,16 @@ WriteBench 把练习收敛为一条清晰的路径:选题、作答、评阅、

### 支持的考试

<p align="center"><img src="Design/Exams/kaoyan.svg" width="56" alt="考研英语" /> <img src="Design/Exams/cet6.svg" width="56" alt="CET-6 六级" /> <img src="Design/Exams/ielts.svg" width="56" alt="IELTS 雅思" /></p>

| 考试 | 题型 | 评分尺度 |
| :--- | :--- | :--- |
| 考研英语一 | 小作文 · 大作文 | 10 分 · 20 分 |
| CET-6 | Writing | 写作练习原始分 15 分 |
| IELTS Academic | Task 1 · Task 2 | 单项任务 Band 9 |
| **考研英语一** | 小作文 · 大作文 · 英译汉 | 10 分 · 20 分 · 10 分 |
| **考研英语二** | 英译汉段落翻译 | 15 分 |
| **CET-6 六级** | 写作 · 汉译英 | 各 15 分练习尺度 |
| **IELTS 雅思 Academic** | Task 1 · Task 2 | 单项任务 Band 9 |

翻译练习重点检查译义、完整性、逻辑关系和目标语言表达;英语一与英语二使用独立 rubric。考研、六级作答期间不显示计词器。

练习分数用于反馈与自查;内置 rubric 是版本化的实践摘要,不是官方阅卷系统。CET-6 不虚构总分换算,IELTS 不把单篇任务分数当作完整 Writing 成绩。

Expand All @@ -41,14 +46,14 @@ WriteBench 把练习收敛为一条清晰的路径:选题、作答、评阅、
| 平台 | 安装方式 | 当前状态 |
| :--- | :--- | :--- |
| **macOS 15+** | 下载 ZIP / DMG,将 WriteBench.app 放入 Applications | 原生 SwiftUI,Apple silicon + Intel |
| **Windows** | 独立 Windows 原生构建 | 开发中,构建验证完成后上传 |
| **Android** | 为手机重新设计的原生界面 | 开发中,构建验证完成后上传 |
| **Windows 11 x64** | [下载便携 ZIP](https://github.com/Functionhx/WriteBench/releases/download/v1.3.0/WriteBench-0.1.0-Windows-x64.zip),完整解压后运行 WriteBench.exe | 原生 WPF / .NET 10 · 0.1 预览版 |
| **Android 13+** | [下载签名 APK](https://github.com/Functionhx/WriteBench/releases/download/v1.3.0/WriteBench-0.1.0-Android.apk),在手机安装 | 原生 Android Views · 0.1 预览版 |

macOS 当前是本地 ad-hoc 签名版本,尚未经过 Apple Developer ID 公证。公开仓库与安装包不包含 API Key、Codex 登录信息或用户作文。
macOS 当前是本地 ad-hoc 签名版本,尚未经过 Apple Developer ID 公证;Windows 预览版尚未进行 Authenticode 签名。Windows OCR 需要 Microsoft Visual C++ x64 运行库,详见[平台说明](platforms/windows/README.md)。公开仓库与安装包不包含 API Key、Codex 登录信息或用户作文。

## 开始使用

1. 打开 **Settings**,填写自己的 DeepSeek API Key,点击 **使用此 Key**。默认仅在本次运行内存中保留;可勾选 **在这台 Mac 上记住 Key**。
1. 打开 **Settings**,填写自己的 DeepSeek API Key,点击 **使用此 Key**。默认仅在本次运行内存中保留;macOS 可勾选 **在这台 Mac 上记住 Key**。提交时只读已启用的内存 Key,记住与恢复在后台完成。
2. 使用 Codex 评审时,先安装[官方 Codex CLI](https://learn.chatgpt.com/docs/codex-cli),在终端运行 `codex login`。已登录的用户直接点击 **Check Connection**,无需再走浏览器。
3. 选择考试与题型,输入题目,或导入题目图片。
4. 点击 **开始答题**,在沉浸式界面完成作文,然后 **交卷**。
Expand All @@ -68,7 +73,7 @@ macOS 当前是本地 ad-hoc 签名版本,尚未经过 Apple Developer ID 公

</div>

以上是 macOS 版的默认配置,每个角色都可独立选择 Provider。A 检查考试任务和整体质量,B 深入检查语言,C 从原题与原稿重新作出判断。三者并行运行、互不读取对方输出,只有完整且有效的结构化结果才会交给本机计算中位数。
以上是 macOS / Windows 版的默认配置,每个角色都可独立选择 Provider。Android 使用三位独立 DeepSeek 评审,手机无需连接电脑。A 检查考试任务和整体质量,B 深入检查语言,C 从原题与原稿重新作出判断。三者并行运行、互不读取对方输出,只有完整且有效的结构化结果才会交给本机计算中位数。

- **DeepSeek**:官方 API,使用用户自行填写的 Key。
- **ChatGPT · via Codex**:官方本机 CLI,复用用户已有的 ChatGPT 登录,使用 Codex 额度。
Expand All @@ -89,11 +94,13 @@ macOS 当前是本地 ad-hoc 签名版本,尚未经过 Apple Developer ID 公
确认后才进入三评
```

OCR 误识别不应被算成学生的拼写错误。题目、手写作文或混合照片都先经过确认页。图表题需把关键数据与图意补充到题目文字中,再进行文本评阅。
OCR 误识别不应被算成学生的拼写错误。题目、手写作文或混合照片都先经过确认页。macOS 可分别整理混合照片中的题目和答案;Windows / Android 可按两种用途分别导入并保留对应文字。图表题需把关键数据与图意补充到题目文字中,再进行文本评阅。

## 原生界面与图标

白色纸面、克制的蓝色、清晰的层级。macOS 使用 SwiftUI 与 AppKit,输入和窗口行为保持原生。手机端会围绕触屏、软键盘和分段阅读重新组织布局。
<p align="center"><img src="Documentation/Images/windows.png" width="100%" alt="WriteBench 原生 Windows 界面,考研、六级与雅思考试入口" /></p>

白色纸面、克制的蓝色、清晰的层级。macOS 使用 SwiftUI 与 AppKit,输入和窗口行为保持原生。Windows 使用 WPF;Android 使用原生 Views。手机布局围绕考试选择、固定开始按钮、软键盘与纵向阅读组织,避免把桌面侧栏缩进小屏。

<p align="center"><img src="Design/Icon/WriteBench-icon-preview.png" width="100%" alt="WriteBench 原版与精修 W 图标、小尺寸检查及深色品牌资源" /></p>

Expand Down Expand Up @@ -122,14 +129,19 @@ WriteBench/ SwiftUI、领域模型、原生服务与 SwiftData
WriteBenchTests/ 评分、并发、持久化、OCR 与子进程测试
Design/Icon/ 可编辑图标与多尺寸导出
Documentation/ 使用说明、验证记录与 Provider 架构
platforms/windows/ WPF 原生应用、OCR 与本地评分
platforms/android/ Android Studio 项目与手机界面
scripts/ 构建、图标生成与显式联调脚本
```

当前自动化测试覆盖 27 个案例。GPT-6 Astra/MAX 已通过实际 Swift 子进程完成样例评卷;DeepSeek 已验证官方模型接口连接。完整混合三评需用户填入有效 Key 后使用。
macOS 自动化测试覆盖 29 个案例,Android 有 5 个领域测试与 2 个实际设备服务测试;Windows 通过评分、持久化、字段校验及实际 OCR 自检。GPT-6 Astra/MAX 已通过实际 Swift 子进程完成样例评卷;DeepSeek 已验证官方模型接口连接。完整混合三评需用户填入有效 Key 后使用。

<details>
<summary><strong>更多文档</strong></summary>

- [Windows 构建与使用](platforms/windows/README.md)
- [Android Studio 构建与使用](platforms/android/README.md)
- [第三方组件说明](THIRD_PARTY_NOTICES.md)
- [macOS 完整使用说明](Documentation/macOS-guide.md)
- [Provider 架构与认证边界](Documentation/Providers.md)
- [构建与验证记录](Documentation/Validation.md)
Expand Down
12 changes: 12 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
# 1.3.0 · 翻译练习与原生多端

- 新增考研英语一英译汉(10 分)、英语二英译汉(15 分)、六级汉译英(15 分),共用沉浸式作答、真实三评、历史与重写。
- 考试入口使用毕业帽、书本、地球分类图标;题型标签保持简洁。
- 修复 macOS 缺少 Key 时旧开发版 Keychain 读取阻塞:提交只读内存,安全保存/恢复为明确选择的后台操作。旧凭证不自动读取。
- 发布首个 Windows WPF 和 Android 原生预览包(各 0.1.0)。手机端专门设计竖向布局、固定开始按钮、题型滑动标签与软键盘适配。
- 三端采用 DeepSeek V4 Pro / MAX;桌面可选官方 Codex CLI / GPT-6 Astra / MAX。Android 的三位评审均为 DeepSeek。
- 新增翻译忠实度、误译、漏译、增译反馈;中文答案不受英文单词计数限制。
- macOS 29 项测试、Android 5 项领域测试与 2 项设备服务测试、Windows 实际运行/OCR 自检,以及 GitHub 原生构建工作流。详细范围见 Documentation/Validation.md。

macOS 本地 ad-hoc 签名,未公证;Windows 无 Authenticode 签名;Android 使用独立保管的发布签名。模型可用性取决于用户自己的服务账户。

# WriteBench 1.2.0

- 三评服务独立选择,默认 DeepSeek V4 Pro / DeepSeek V4 Pro / GPT-6 Astra(官方 Codex CLI),全部 MAX 思考。
Expand Down
Loading
Loading