Skip to content

feat: M1-M3 application + seed-release hardening (Windows x64, first code sync) - #1

Merged
Ychris12138 merged 4 commits into
mainfrom
feat/m1-m3-seed-release
Sep 12, 2026
Merged

Ychris12138 merged 4 commits into
mainfrom
feat/m1-m3-seed-release

Conversation

@Ychris12138

@Ychris12138 Ychris12138 commented Sep 11, 2026 •

Copy link
Copy Markdown
Owner

这是什么

本仓库的首次代码同步:M1–M3 全部实现成果 + 种子发布加固 + PR 审查修订。基线(main)是 M0 规划文档;本 PR = 整个应用(前端 + Tauri 壳 + storage 层 + 测试 + 发布工程)。

修订记录:① 按首轮审查意见补充(见「审查响应」);② 全历史作者邮箱已重写为 GitHub noreply(仓库公开当天处理,哈希因此全部变化,树内容不变)。CI 为 merge gate:test-and-build 必须绿。

提交概要(重写后哈希)

内容 提交
M1–M3 应用全量源码 + 种子发布加固(事务写/单实例/冲突防护/每日快照/草稿保护) 03a995d
release/ 发布包流程 + 安装器中文/须知页 + 首启欢迎卡 a6ba31a
发布规范 docs/release.md + make-release 门槛自检 141cfa6
构建命令去除机器特定用户名路径 6418961
审查修订:CSP、CI 工作流、.trash 软删除、README 刷新 701c538
发布记录:0.1.0-seed 候选构建,废弃 pre-CSP 构建 07dcc52

应用概要

  • Tauri 2 + React 19 + Vite + Tailwind v4,IDE 式四区布局(侧栏树 / 中间视图 / 底部终端 / 右侧详情);当前种子构建 Windows x64(macOS 计划中未验证)
  • storage 纯核心 + IO 适配器拆分(src/storage/core.ts 无 Tauri API),同一核心将来配 node:fs 即成 MCP server(第二步)
  • 数据 = 本地 Markdown 文件树(~/ResearchThread,与代码仓库分离),git 每日自动快照兜底

种子发布加固

  1. 事务式写入 storage/atomicWrite.ts:失败/中断后原文件或备份必有一个可恢复,启动扫描恢复;故障注入测试覆盖
  2. 单实例 tauri-plugin-single-instance(Rust 端实际启用)
  3. 外部编辑并发防护:五条保存路径全部设卡(updateTaskMeta / appendEntry / updateEntry / updateProjectDescription / saveWeekly)——保存前比对磁盘内容与应用最后已知内容,冲突弹「覆盖/重载/取消」不静默覆盖。(初版描述称 appendEntry 纯追加不设卡,系笔误:实现中它同样走冲突检查并整文件重写,比纯追加更安全。)
  4. 每日快照健康 storage/snapshot.ts:git 检测 → 仓库级身份兜底 → 补空仓提交 → 每日首启提交;失败界面持久警告
  5. 脏草稿退出保护(含周文档草稿)+ 周文档重新生成/冲突覆盖二次确认
  6. 软删除:deleteTask / deleteInboxItem 移入 .trash/(时间戳前缀,不物理删除)——事务写保护不了 delete,这是当天未快照文件的唯一丢失防线;含移回恢复的往返测试
  7. renderer 安全边界:生产线 CSP 开启(default-src 'self' + Tauri IPC 端点,devCsp 含 HMR ws);防闪烁内联脚本外置为 /theme-init.js;两处 dangerouslySetInnerHTML 均为 escape-first 白名单渲染(src/lib/markdown.ts)。shell capability 列为高权限边界写入 docs/release.md §5-0
  8. CI 门槛:.github/workflows/ci.yml(npm ci → test → build)在每个 PR/push 强制执行
  9. 发布工程:npm run make-release 归拢 release/(gitignore)+ 版本三处一致强制 + 脏工作区/过期构建警告,规范见 docs/release.md

审查响应(首轮 Request changes)

审查项 处置
🔴 CSP null + shell 高权限 已修:生产 CSP + devCsp;内联主题脚本外置;HTML 入口审计入红线
🔴 无 CI 验证 已修:GitHub Actions test-and-build,本 PR 可见绿色 check
🟠 提交邮箱公开(含 main 基线) 已处理:全历史重写为 GitHub noreply 并 force push(树内容不变)
🟠 删除不可恢复(当天丢失窗口) 已修:.trash/ 软删除 + 往返测试 + 文档
🟡 README 过期("待接入/待建")+ macOS 表述 已修:技术栈对齐现状;首句改「当前种子构建 Windows x64,macOS 计划未验证」
🟡 PR 描述 appendEntry 错误 本描述已修正(见上文第 3 条)

验证证据

  • CI(可重复):test-and-build 绿(checkout → npm ci → npm test → npm run build),历史重写后已在新 head 重跑确认
  • 本地:vitest 60/60;npm run tauri dev 与 release 产物(生产 CSP)实机截图验证 UI 完整渲染、IPC/fs/watch 正常
  • npm run tauri build NSIS 包 2.69 MB,SHA-256 b83a6c94…f60a48(docs/release.md §8);pre-CSP 构建 b3a893fb… 已标记废弃勿分发

明确不在仓库里

src-tauri/target/(~8 GB 构建缓存)、node_modules/、release/ 产物、用户数据目录——全部 gitignore,零跟踪。最大入库文件 WebView2Loader.dll(160 KB,安装器必需资源)。

发布前剩余关卡(docs/release.md §4-6)

  • 干净 Windows 账户实测(首装/无 git 警告/单实例/升级/卸载重装/快照恢复演练)
  • 打 tag v0.1.0-seed 并在发布渠道公布 SHA-256

Copilot AI lite review requested due to automatic review settings September 11, 2026 13:47
Copilot stopped reviewing on behalf of Ychris12138 due to an error September 11, 2026 14:08
yr added 2 commits September 11, 2026 22:10
- production CSP (default-src 'self' baseline, ipc endpoints for Tauri,
  stricter devCsp with HMR ws); theme-restore script externalized from
  inline (blocked under script-src 'self'); both dangerouslySetInnerHTML
  call sites audited escape-first (src/lib/markdown.ts)
- minimal GitHub Actions CI: npm ci -> npm test -> npm run build on
  every PR/push; merge gate is CI green, not verbal evidence
- deleteTask / deleteInboxItem now soft-delete into .trash/ (timestamped,
  never physical delete) -- transactional write cannot protect delete;
  recovery = move back or git; watcher filters .trash; round-trip test
- README: remove stale 'pending' tech-stack lines, state Windows x64
  seed reality (macOS planned, unverified)
- release.md: red line 0 (renderer security boundary: CSP + shell
  capability + escape-first HTML), red line 6 (soft delete), CI gate
  section; AGENTS.md/seed manual aligned; appendEntry docs corrected
  (all five save paths conflict-guarded, not four)
Ychris12138 added a commit that referenced this pull request Sep 11, 2026
- production CSP (default-src 'self' baseline, ipc endpoints for Tauri,
  stricter devCsp with HMR ws); theme-restore script externalized from
  inline (blocked under script-src 'self'); both dangerouslySetInnerHTML
  call sites audited escape-first (src/lib/markdown.ts)
- minimal GitHub Actions CI: npm ci -> npm test -> npm run build on
  every PR/push; merge gate is CI green, not verbal evidence
- deleteTask / deleteInboxItem now soft-delete into .trash/ (timestamped,
  never physical delete) -- transactional write cannot protect delete;
  recovery = move back or git; watcher filters .trash; round-trip test
- README: remove stale 'pending' tech-stack lines, state Windows x64
  seed reality (macOS planned, unverified)
- release.md: red line 0 (renderer security boundary: CSP + shell
  capability + escape-first HTML), red line 6 (soft delete), CI gate
  section; AGENTS.md/seed manual aligned; appendEntry docs corrected
  (all five save paths conflict-guarded, not four)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Copilot was unable to run its full agentic suite in this review.

Pull request overview

This PR bootstraps the app into a Tauri + Vite + React workspace with a file-backed storage layer, adding data-safety guarantees (atomic writes, external-edit conflict guarding, git snapshot health), along with M3 features like weekly skeleton generation, search, and a minimal markdown preview. It also adds comprehensive Vitest coverage plus Windows seed-release tooling and documentation.

Changes:

  • Add storage primitives: atomic write + recovery, git snapshot health checks, weekly skeleton generator, fs adapter, conflict error type.
  • Add UI-level M2/M3 features: file watcher normalization, terminal panel, weekly view editing/preview, in-memory search, markdown renderer, editor dirty tracking.
  • Add test suite and release tooling/docs (Vitest tests, NSIS packaging config, release bundling script, seed manual & release playbook).

Reviewed changes

Copilot reviewed 71 out of 127 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
vite.config.ts Adds Vite plugins, aliasing, fixed dev port for Tauri, and Vitest configuration.
tsconfig.json Enables strict TS settings and path alias for @/*.
tests/weekly.test.ts Tests weekly skeleton determinism, week range edges, archived projects, and frontmatter archived round-trip.
tests/storageNode.test.ts Node fs adapter integration tests for StorageDataAccess lifecycle + watcher + conflict strategy.
tests/search-markdown.test.ts Validates pure search function and markdown rendering (including XSS escaping).
tests/parity.test.ts Ensures MockDataAccess and StorageDataAccess produce equivalent domain state for the same scenario.
tests/core.test.ts Tests storage core round-trip contract, ISO week edge cases, and activity log serialization.
tests/atomicWrite.test.ts Fault-injection tests for atomic writes + interrupted-write recovery.
src/types.ts Defines shared domain types and the DataAccess/AppDataAccess contract (projects now support archived).
src/storage/weekly.ts Implements deterministic weekly skeleton generation from events + snapshot.
src/storage/snapshot.ts Adds git snapshot “health” check and daily auto-snapshot logic with visible failure reasons.
src/storage/git.ts Adds runGit, gitSnapshot, and a file-manager opener via plugin-shell.
src/storage/fsAdapter.ts Defines storage IO interface and Tauri plugin-fs adapter implementation.
src/storage/errors.ts Introduces ExternalConflictError for external edit conflict guarding.
src/storage/atomicWrite.ts Implements atomic write protocol (.rt-tmp/.rt-bak) and startup recovery scan.
src/mockData.ts Provides seed mock dataset for UI (spaces/projects/tasks with realistic content).
src/main.tsx Bootstraps app, initializes data access, registers global shortcut in Tauri.
src/lib/watcher.ts Adds debounced watcher integration and Windows path normalization + filtering.
src/lib/status.ts Task sorting/grouping helpers and status labels/colors.
src/lib/settings.ts Adds persisted settings store (theme, density, plugins gating, etc.) and appearance application.
src/lib/selfWrites.ts Tracks recent app self-writes so watcher can distinguish external edits.
src/lib/search.ts Adds pure in-memory search + snippet generator with archived filtering support.
src/lib/markdown.ts Adds small dependency-free markdown subset renderer with HTML escaping.
src/lib/format.ts Adds date formatting + slug helpers.
src/lib/editorState.ts Adds global “dirty editor” tracking used for watcher strategy and exit protection.
src/lib/cn.ts Adds cn() helper combining clsx + tailwind-merge.
src/lib/agentRunner.ts Adds AgentRunner abstraction on top of plugin-shell + command-line parsing helper.
src/dataAccess.ts Implements MockDataAccess, Tauri storage init, snapshot health plumbing, and exports.
src/components/ui-bits.tsx Adds shared UI primitives (buttons, inputs, empty state, badge).
src/components/terminal-panel.tsx Adds xterm-based terminal panel wired to AgentRunner (Tauri only).
src/components/task-detail.tsx Adds task editor + entry editing with dirty tracking and two-step delete.
src/components/sidebar.tsx Adds space/project tree with inline creation and archived-filtering toggle.
src/components/selection.ts Adds selection model and default selection IDs.
src/components/search-view.tsx Adds search UI backed by searchAll() and inbox indexing.
src/components/plugins-view.tsx Adds plugin gating UI wired to settings.
src/components/inspector-rail.tsx Adds right ribbon controls for inspector/bottom panel toggles.
src/components/icons.tsx Adds icon set used across the UI.
src/components/icon-ribbon.tsx Adds left ribbon navigation, gating items by plugin flags.
src/components/extra-views.tsx Adds Today/Weekly/Graph views and weekly edit/preview flow with conflict handling.
src/components/appearance-sync.tsx Syncs persisted settings to DOM theme variables and listens to system theme.
src/components/agent-view.tsx Adds placeholder Agent view with settings toggles (plan/act).
src-tauri/tauri.conf.json Configures Tauri v2 app bundle (NSIS target, fixed devUrl, resources, CSP disabled).
src-tauri/src/main.rs Tauri desktop entry point.
src-tauri/src/lib.rs Registers Tauri plugins (fs, shell, global shortcuts, single instance).
src-tauri/icons/android/values/ic_launcher_background.xml Android icon resource (template).
src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml Android adaptive icon (template).
src-tauri/capabilities/default.json Grants fs/shell/global-shortcut capabilities and scopes to $HOME/ResearchThread/**.
src-tauri/build.rs Tauri build script.
src-tauri/INSTALL-NOTES.txt Seed installer notes shown by NSIS.
src-tauri/Cargo.toml Tauri Rust crate config + plugin dependencies.
src-tauri/.gitignore Ignores build outputs and generated schemas.
src-tauri/.cargo/config.toml Windows GNU linker/rust-lld config.
scripts/make-release.mjs Packaging script to assemble release/ artifacts plus version consistency checks.
scripts/install-sdk.ps1 Helper to install Windows SDK into VS Build Tools (one-off).
scripts/gen-icon.mjs One-off icon generator script.
public/favicon.svg Adds app favicon asset.
package.json Defines scripts and dependencies (Vite/React/Tauri plugins/Vitest/etc.).
index.html Adds early theme boot script based on persisted settings.
docs/seed-manual.md Seed user manual (install notes, privacy, git snapshots, feedback template).
docs/release.md Release playbook (process, hard constraints, safety/privacy red lines).
UI.md Updated UI spec doc reflecting relaxed constraints and plugin gating.
README.md Updates project status, docs links, and quick-start instructions.
AGENTS.md Updates current status, release constraints, and data-safety baseline.
.gitignore Ignores ui_ref/ and release/ output folder.
Suppressed comments (7)

src/storage/weekly.ts:1

  • Date.UTC(year, month, day)expects a 0-based month, but the code passes the ISO month as 1–12. This will skew stale-day calculations and any other day-diff usage. Convert the parsed month tomonth - 1before callingDate.UTC(for bothlaterandearlier`).
    src/storage/weekly.ts:1
  • When ref is null, this will emit a trailing separator (e.g. …」·) because only the trailing space is trimmed. Build the location suffix conditionally (include the · only when a location exists) to avoid malformed weekly output for events that cannot be resolved to a task ref.
    src-tauri/tauri.conf.json:1
  • Disabling CSP (csp: null) significantly increases the blast radius of any XSS (especially since the UI uses dangerouslySetInnerHTML for markdown previews). Prefer a restrictive CSP and explicitly whitelist only what is needed for this app; if some inline styles/scripts are required, narrow it (e.g., allow specific hashes/nonces) rather than fully disabling CSP.
    tests/weekly.test.ts:1
  • This object literal has a duplicate event key; the later "modify" overwrites "external_modify_placeholder", making the placeholder string ineffective. Remove the duplicate key and keep only the intended event value, or move the placeholder text into a different field/comment so the test data is unambiguous.
    tests/storageNode.test.ts:1
  • The ternary project.id ? space.id : space.id is redundant and makes the call site look suspicious. Replace it with space.id directly to reduce confusion and keep the test focused on the behavior under test.
    tests/storageNode.test.ts:1
  • Node's fs.watch({ recursive: true }) is not supported on Linux (it works on Windows/macOS). If CI runs on Linux, this test will be flaky or fail. Consider skipping the watcher integration test on unsupported platforms (e.g. it.skip when process.platform === "linux"), or use a cross-platform watcher (like chokidar) for the test adapter.
    src/storage/git.ts:1
  • This is Windows-specific (explorer). If the app is intended to be cross-platform (README/Docs mention macOS), this will break on non-Windows. Prefer a platform-agnostic opener (e.g. Tauri opener plugin / shell open command per-platform) or branch on OS and choose open (macOS) / xdg-open (Linux) / explorer (Windows).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +34 to +43
"allow": [
{ "name": "git", "cmd": "git", "args": true },
{ "name": "claude", "cmd": "claude", "args": true },
{ "name": "codex", "cmd": "codex", "args": true },
{ "name": "cmd", "cmd": "cmd", "args": true },
{ "name": "powershell", "cmd": "powershell", "args": true },
{ "name": "explorer", "cmd": "explorer", "args": true },
{ "name": "npm", "cmd": "npm", "args": true },
{ "name": "node", "cmd": "node", "args": true }
]
- diffDays passed 1-12 months to Date.UTC (expects 0-11); crossing
  months skewed stale-day math by 1-3 days (e.g. 14-day boundary judged
  as 13). Normalize month-1 before Date.UTC; boundary tests at exactly
  14 days (stale) and 13 days (not stale) fail on the old math
- create_task line no longer leaves a trailing '·' when the task ref
  cannot be resolved; regression assertion
- tests: drop duplicate 'event' key in weekly fixture; simplify a
  meaningless conditional in storageNode
- release.md §5-0: re-tighten shell allowlist at 2a/2b (Issue #2)
@Ychris12138
Ychris12138 merged commit d296f72 into main Sep 12, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants