Repository navigation
feat: M1-M3 application + seed-release hardening (Windows x64, first code sync) - #1
Merged
Merged
Conversation
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)
…retire pre-CSP build
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)
There was a problem hiding this comment.
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
refis 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 usesdangerouslySetInnerHTMLfor 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
eventkey; the later"modify"overwrites"external_modify_placeholder", making the placeholder string ineffective. Remove the duplicate key and keep only the intendedeventvalue, 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.idis redundant and makes the call site look suspicious. Replace it withspace.iddirectly 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.skipwhenprocess.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 chooseopen(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 } | ||
| ] |
Ychris12138
force-pushed
the
feat/m1-m3-seed-release
branch
from
September 11, 2026 14:14
f7d93c9 to
07dcc52
Compare
36 tasks
- 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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
这是什么
本仓库的首次代码同步:M1–M3 全部实现成果 + 种子发布加固 + PR 审查修订。基线(main)是 M0 规划文档;本 PR = 整个应用(前端 + Tauri 壳 + storage 层 + 测试 + 发布工程)。
提交概要(重写后哈希)
03a995da6ba31a141cfa66418961701c53807dcc52应用概要
src/storage/core.ts无 Tauri API),同一核心将来配 node:fs 即成 MCP server(第二步)~/ResearchThread,与代码仓库分离),git 每日自动快照兜底种子发布加固
storage/atomicWrite.ts:失败/中断后原文件或备份必有一个可恢复,启动扫描恢复;故障注入测试覆盖updateTaskMeta/appendEntry/updateEntry/updateProjectDescription/saveWeekly)——保存前比对磁盘内容与应用最后已知内容,冲突弹「覆盖/重载/取消」不静默覆盖。(初版描述称 appendEntry 纯追加不设卡,系笔误:实现中它同样走冲突检查并整文件重写,比纯追加更安全。)storage/snapshot.ts:git 检测 → 仓库级身份兜底 → 补空仓提交 → 每日首启提交;失败界面持久警告deleteTask/deleteInboxItem移入.trash/(时间戳前缀,不物理删除)——事务写保护不了 delete,这是当天未快照文件的唯一丢失防线;含移回恢复的往返测试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.github/workflows/ci.yml(npm ci → test → build)在每个 PR/push 强制执行npm run make-release归拢release/(gitignore)+ 版本三处一致强制 + 脏工作区/过期构建警告,规范见 docs/release.md审查响应(首轮 Request changes)
test-and-build,本 PR 可见绿色 check.trash/软删除 + 往返测试 + 文档验证证据
test-and-build绿(checkout → npm ci → npm test → npm run build),历史重写后已在新 head 重跑确认npm run tauri dev与 release 产物(生产 CSP)实机截图验证 UI 完整渲染、IPC/fs/watch 正常npm run tauri buildNSIS 包 2.69 MB,SHA-256b83a6c94…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)
v0.1.0-seed并在发布渠道公布 SHA-256