news 2026/9/13 3:00:24

Super Productivity 仓库 AI 协同开发指南:架构地图、同步不变量与工程护栏

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Super Productivity 仓库 AI 协同开发指南:架构地图、同步不变量与工程护栏

Super Productivity 仓库 AI 协同开发指南:架构地图、同步不变量与工程护栏

【免费下载链接】super-productivitySuper Productivity is an advanced todo list app with integrated Timeboxing and time tracking capabilities. It also comes with integrations for Jira, GitLab, GitHub and Open Project.项目地址: https://gitcode.com/GitHub_Trending/su/super-productivity

导读

Super Productivity 是一款基于 Angular + Electron + Capacitor 的待办事项与时间追踪应用,其仓库为 AI Agent 提供了一份专门的协作指南CLAUDE.md——它既是一张架构地图(feature、op-log、pfapi、packages 的职责划分),也是一套工程红线(同步正确性不变量、lint 强制的编码护栏、1200 行服务上限),更是一份可执行的命令手册(checkFile、单元测试、Electron 测试、Playwright E2E)。读完本文,你将掌握这个仓库的目录结构、核心开发命令、同步系统的 11 条正确性规则与反模式清单,并能以与仓库维护者一致的方式提交高质量改动。

仓库地图:从 feature 到 op-log 的分层架构

CLAUDE.md首先给出了一份精简的仓库地图,指向整个项目的代码组织方式。结合目录结构,各层职责如下:

  • src/app/features/ —— 功能模块(tasks、planner、project、schedule、boards 等),其中tasks/是核心热路径,任务组件在超长可滚动列表中每个任务渲染一次,任何改动都必须经过性能双重检查(见下文“项目规则”)。
  • src/app/root-store/ —— NgRx 根 store;meta/存放跨实体的 meta-reducers,是实现“多实体变更 = 一次 meta-reducer 处理”的关键位置。
  • src/app/op-log/ —— 操作日志同步管线(capture、apply、persistence、validation),是整个同步系统的核心,包含持久化(如 operation-log-store.service.ts)与验证(如 frozen-state.spec.ts)。
  • src/app/pfapi/ —— 底层持久化层(model/database controllers)。
  • src/app/imex/ —— 导入/导出与同步设置 UI。
  • src/app/core/、core-ui/、ui/ —— 核心服务与共享 UI 构建块;util/ 存放纯函数工具。
  • packages/ —— workspace 包:sync-coresync-providers(共享同步逻辑)、shared-schemasuper-sync-serverplugin-apiplugin-dev
  • electron/ —— Electron 主进程(测试为*.test.cjs);android/ 与 ios/ 为 Capacitor 壳。
  • e2e/ —— Playwright 测试套件,配套的 Agent 指南见 e2e/CLAUDE.md。

值得注意:Electron 主进程测试必须是*.test.cjs而不能是.spec.ts,因为 electron/tsconfig.electron.json 排除了*.spec.ts——一个误放在electron/下的 spec 会被静默跳过、永远不运行。

产品原则:构建决策的底层约束

CLAUDE.md从项目宣言(Deep Work, Your Way)中提炼出四条影响构建决策的产品原则,每个新功能都要以此权衡:

  1. 避免功能膨胀(Avoid feature creep):这是个人深度工作工具,不是团队管理或报表产品。优先用最小改动解决真实问题;新 UI、设置项与同步面都是永久成本,先扩展现有构建块,功能只有让用户“更快”而非“更忙”才允许发布。
  2. 更少噪音、更深专注(Less noise, more depth):拒绝持续弹窗、虚荣仪表盘、连击与多巴胺循环。提醒与通知是核心功能,但一切抓眼球的东西默认关闭并保持安静(流畅而非摩擦)。
  3. 适应而非强加(Adapt, don't impose):人们计划、追踪、反思的方式各不相同,所以新行为以构建块形式发布。优先一个冷静的默认值而非新开关;只有当真实工作流确实分化时才加设置(“不构建 → 冷静默认 → 可选设置”的决策链)。
  4. 隐私与离线优先(Privacy & offline first):无分析、无追踪、无遥测。核心任务与时间追踪必须完全离线可用;同步与在线集成是可选层,优雅降级、绝不成为前置条件。

开工前必读:任务类型与文档映射

CLAUDE.md按任务类型列出了“必需阅读”,保证改动与既有约定对齐:

改动类型必读文档
样式改动docs/styling-guide.md
面向用户的功能改动docs/documentation-guide.md
同步、op-log、向量时钟docs/sync-and-op-log/
涉及同步状态的 Effects/reducers/批量派发docs/sync-and-op-log/contributor-sync-model.md
E2E 测试e2e/CLAUDE.md
承重架构决策ARCHITECTURE-DECISIONS.md
评审功能或 PRdocs/feature-review-guide.md
判断同步 bug 是否真实/严重程度docs/sync-and-op-log/sync-severity-triage.md

核心命令:从单文件检查到全套 E2E

CLAUDE.md强调一条硬性规定:任何修改过的.ts.scss文件,在报告完成前必须先运行npm run checkFile <filepath>。完整的命令矩阵如下(对应 package.json 中的 scripts):

npm run checkFile <filepath> # 对单个文件执行 prettier + lint npm run prettier # 多文件格式化 npm run lint # 多文件 lint npm test # 全部单元测试(Jasmine/Karma,.spec.ts 与被测文件同目录) npm run test:file <filepath> # 运行单个 spec npm run test:electron # Electron 主进程测试——electron/*.test.cjs,而非 .spec.ts npm run e2e # 全部 E2E(Playwright,较慢) npm run e2e:file <path> -- --retries=0 # 单条 E2E(约 20s/条);追加 --grep "name" 过滤单测 npm start # Electron 开发模式 ng serve # Web 开发模式(或 npm run startFrontend) npm run dist # 生产构建(本机可用的所有平台)

补充细节:npm run lint的真实构成

从 package.json 可以看到,npm run lint并不是单一命令,而是五个阶段:

  • lint:ts——ng lint(基于 eslint.config.js 的 flat config);
  • lint:scss——stylelint "**/*.scss" "src/assets/themes/*.css"
  • lint:css-vars——node tools/check-css-vars.js,校验主题 CSS 变量完整性;
  • test:lint-rules——node eslint-local-rules/run-specs.js,运行仓库内置 lint 规则自身的单测(每个本地规则都带同名.spec.js);
  • test:toolstest:mac-icon—— 校验工具脚本与 macOS 图标契约。

E2E 的运行策略

CLAUDE.md建议:SuperSync 与 WebDAV 全套 E2E 通过 GitHub Actions 手动派发E2E Tests (Scheduled)运行,而不是在本地跑全套——工作流提供了专用的 WebDAV 与分片的 SuperSync 任务,可选的grep输入只过滤 SuperSync 任务。本地则优先单文件运行:

npm run e2e:file tests/feature/test.spec.ts -- --retries=0 --grep "should X"

SuperSync 本地 E2E 通过 docker-compose 启动:docker compose -f docker-compose.yaml -f docker-compose.supersync.yaml up -d supersync,再配合scripts/wait-for-supersync.sh等待健康检查(详见 e2e/CLAUDE.md)。全部 E2E 参考同样见 e2e/CLAUDE.md,其中定义了 page objects(workViewPagetaskPage等)、fixture 表、断言助手与关键规则(每条测试必须以workViewPage.waitForTaskList()开头、禁止waitForTimeout()、测试间完全隔离等)。

项目规则:编码规范与工程护栏

CLAUDE.md的项目规则是改动前必须遵守的硬约束:

  • 翻译:UI 字符串一律通过T/TranslateService;只编辑en.json,绝不编辑其他语言文件(见 src/assets/i18n/)。
  • 隐私:无分析、无追踪,除非用户显式同步,否则用户数据留在本地。
  • 依赖:PR 不得向根项目的dependencies/devDependencies新增包;优先使用平台 API、既有包或仓库内的小实现。单独插件作用域内的依赖仅在其必要且隔离时允许。
  • Electron:使用 Electron 专有 API 前必须检查IS_ELECTRON
  • 模板:纯 HTML、最小化 CSS/类,节制使用 Angular Material(见 docs/styling-guide.md)。
  • 样式评审:不得为一次性上下文需求在本地重排 Angular Material 或共享src/app/ui/组件样式,包括通过.mat-*.mdc-*button[mat-*]覆盖按钮样式;优先复用既有 inputs/classes/tokens,需要新变体时应做成可复用或加入共享样式层。
  • 严格 TypeScript:禁止any(确属未知时用unknown)。
  • 状态:绝不修改 NgRx state——reducer 必须返回新对象;优先使用 Signals 而非 Observables。
  • 测试:新服务与状态逻辑必须配套单元测试。
  • 服务体积上限:任何 service 不得超过 1200 行(物理行,含空行与注释),由 eslint 的max-lines**/*.service.ts上强制(eslint.config.js),spec 除外。超限前按职责拆分:抽取协作者、把纯逻辑移到 utils 或packages/。既有超限文件在eslint.config.js中以 warning 降级(该名单只允许缩小、绝不允许增长)。
  • Agent 控制文件:未经用户当前任务显式要求,不得修改AGENTS.mdCLAUDE.md.agents/**.codex/**;此类改动须与产品/代码改动隔离在独立 commit 或 PR 中,并说明其对未来 Agent 行为的影响。新增事故派生规则时只保留“不变量 + 强制执行 + issue/文档指针”,叙述性内容移到docs/,引用的统计数据必须标注日期("measured YYYY-MM")。
  • 加固需要实例支撑(Hardening needs an observed instance):添加护栏(lint 规则分支、运行时断言、防御性检查)前,先在仓库中 grep 到它捕获的形状的真实出现;零出现 → 记录为已知缺口。生成的允许清单只能缩小:绝不因误报而扩张,而是修复检查或带理由地限定禁用。
  • 它配得上存在吗(Does it earn its place?):新功能的第一评审问题是“它是否应该存在”,而不是 diff 是否正确。新增复杂度是永久的,正确且经过测试但“不配存在”的实现依然应该被拒绝——把陈述动机当作需要验证的主张,而不是默认接受的上下文。
  • 代码评审:权衡改动引入的长期成本——维护负担、难逆转的选择(数据形状、公开/插件 API、同步格式)、锁定依赖、只在规模化或跨同步客户端时暴露的陷阱——而不只是当前 diff 是否正确。
  • 任务组件是热路径:任何对 src/app/features/tasks/task/task.component.* 的改动都必须复查负面性能影响——避免模板中的函数/getter 调用、额外变更检测工作、未清理的订阅——并在大型任务列表上验证。

同步正确性规则:一个不变量,十一条铁律

CLAUDE.md强调:同步系统的每次改动都是高风险操作——一个隐蔽 bug 可能静默损坏或丢失跨设备用户数据且难以恢复。规则 1–3 与 6 本质上是同一个不变量:

一个用户意图 = 一个 op;重放/远程 op 不得再次触发 effects。

完整推导见 docs/sync-and-op-log/contributor-sync-model.md。在改动前阅读对应源码与文档获取完整推理。

严重度判断与可复现起点

  • 判断同步 bug 严重度前master会发布给真实用户——Play internal track、Snapedgesupersync:latest都会从每次 push 自动发布。不要从日期或最新 tag 推断“已发布”,要用git tag --contains证明。未复现的发现不等于误报。→ docs/sync-and-op-log/sync-severity-triage.md
  • 从可复现问题开始:任何同步改动必须以可复现的失败为起点——针对真实数据形状(fixture 或播种的 DB 状态)的失败测试或脚本化 E2E 复现,而不是 mock 的接缝。没有观察到的端到端失败就做的加固,正是同步层堆积过度防御复杂度的原因。

十一条规则详解

规则 1:Effects 注入LOCAL_ACTIONS,绝不注入Actions唯一例外是 op-log 捕获 effect 使用ALL_ACTIONS;远程归档副作用走ArchiveOperationHandler而非ALL_ACTIONS。由 lint 规则no-actions-in-effects强制(eslint-local-rules/rules/no-actions-in-effects.js,该文件注释说明这是“单一同步不变量”的 Boundary 1:重放与远程 op 必须永不重触发 effects)。token 实现见 src/app/util/local-actions.token.ts:LOCAL_ACTIONS通过filter(action => !action.meta?.isRemote)过滤掉标记为远程/重放的 action 并share()ALL_ACTIONS则透传完整的Actions流,仅供必须响应远程操作且内部处理isRemote的 effect 使用。

规则 2:优先 action 驱动的 effect;selector 驱动的 effect 需要skipDuringSyncWindow()。由 lint 规则require-hydration-guard强制。

规则 3:多实体变更 = meta-reducer,而非 effect 扇出(一次 reducer 处理 = 一个 op)。实现在 src/app/root-store/meta/task-shared-meta-reducers/,其中包含task-shared-crud.reducer.tslww-update.meta-reducer.tstask-batch-update.reducer.ts等,配套大量 spec 与 integration spec 验证重放确定性。

规则 4:逻辑时钟——“今天是哪天?”必须路由到DateService(src/app/core/date/date.service.ts)的getLogicalTodayDateisTodaytodayStr。纯 reducer/selector 以参数形式接收startOfNextDayDiffMs并调用isTodayWithOffset保证重放确定性。DateService.startOfNextDayDiffprivate,在服务边界使用getStartOfNextDayDiffMs()(该访问器为只读,纯工具需要以参数接收此值)。底层纯函数位于 src/app/util/start-of-next-day.util.ts 与 src/app/util/is-today.util.ts,并有对应.spec.ts覆盖边界(如 #7645:非法时间字符串会使整对参数不可信,应重置为默认值)。

规则 5:TODAY_TAG'TODAY')是虚拟标签——绝不加入task.tagIds;成员关系来自task.dueWithTimetask.dueDayTODAY_TAG.taskIds只存顺序。定义见 src/app/features/tag/tag.const.ts,完整论证见ARCHITECTURE-DECISIONS.mdDecision #2。

规则 6:批量派发循环——循环后必须await new Promise(r => setTimeout(r, 0)),否则 50+ 次快速派发会丢状态。详见 docs/sync-and-op-log/contributor-sync-model.md 与OperationApplierService.applyOperations()

规则 7:SYNC_IMPORT/BACKUP_IMPORT替换状态并有意识地丢弃并发 op(向量时钟判定为 CONCURRENT 或 LESS_THAN)——这是设计而非 bug。实现在SyncImportFilterService

规则 8:向量时钟——MAX_VECTOR_CLOCK_SIZE = 20。服务器在冲突检测后、存储前裁剪。详见 docs/sync-and-op-log/vector-clocks.md。

规则 9:日志——用Log.log({ id: task.id }),绝不用Log.log(task)Log.log(title)——日志历史可导出,绝不可记录用户内容。由 lint 规则no-user-content-in-logs强制(eslint.config.js),该规则以error级别让新泄露在引入它的 PR 上直接挂 CI。

规则 10:schema bump 的默认答案是“不 bump”——bump 保护不了已发布舰队、近乎不可逆、即使安全也不免费。新 op 语义必须在旧客户端上优雅降级(LwwUpdatePayloadenvelope / 惰性 marker 模式)。旧客户端会错误应用的改动不能仅靠 bump 发布;旧客户端能容忍的改动则根本不需要 bump。见 packages/shared-schema/src/schema-version.ts(当前CURRENT_SCHEMA_VERSION = 4MIN_SUPPORTED_SCHEMA_VERSION = 1,且刻意不设前向兼容带),规范策略在 docs/sync-and-op-log/operation-log-architecture.md §A.7.11 "Bump Policy"。

规则 11:持久化模型的新 REQUIRED 字段会破坏所有既有安装——必须设为可选(?)并加运行时默认值。用户磁盘上已有数据缺少该字段,typia 会在水合时拒绝;TypeScript 只守卫新数据,导致构建绿灯但每个既有安装校验失败,且失败潜伏到无关 bump 把旧数据拖上迁移路径。由 src/app/op-log/validation/frozen-state.spec.ts 守护——若它失败,修模型而非修 fixture。完整分析见 docs/sync-and-op-log/persisted-model-fields.md。

反模式清单:被禁止的写法与替代方案

CLAUDE.md以表格形式给出了最常踩的反模式:

禁止应改为
any类型恰当的类型,确属未知时用unknown
直接 DOM 访问Angular 绑定、viewChild()
构造函数中的副作用asyncpipe 或toSignal
订阅后不清理takeUntilDestroyed()或 async pipe
新代码使用NgModulesstandalone components
重声明 Material 主题样式复用既有主题变量
一次性.mat-*.mdc-*button[mat-*]或共享组件覆盖可复用的 inputs、tokens 或共享样式

这些反模式与上文“项目规则”中的 eslint 强制项一一对应:例如no-actions-in-effectsrequire-hydration-guardno-multi-entity-effectrequire-entity-registryrequire-text-localeno-adapter-in-txrequire-frontier-report-on-ops-appendno-user-content-in-logsno-console等本地规则均在 eslint.config.js 与 eslint-local-rules/rules/ 中实现,其中每条规则都带自身的.spec.js单测(由npm run test:lint-rules执行),确保“能失败的检查确实会失败”。

此外,eslint.config.js 还内置了若干层边界护栏,体现同样的纪律:src/app/uisrc/app/core不得反向导入features/(静态与动态导入双重拦截)、packages/sync-core必须保持领域无关(禁止导入 Angular/NgRx/app 代码)、sync-providers只能使用sync-core的公开导出等——这些边界在 CI 上以零违规维持。

如何利用这份指南高效贡献

  1. 改动前先对号入座:按上文的“任务类型 × 必读文档”表读对应文档,同步相关改动必读 contributor-sync-model.md。
  2. 改动中守纪律:遵守严格 TS(无any)、不可变 NgRx state、无新增依赖、模板走构建块、服务不超过 1200 行。
  3. 改动后先自检再报告:对每个修改的.ts/.scss文件运行npm run checkFile,为新增服务与状态逻辑补.spec.ts,同步改动则以可复现失败开头并逐条对照 11 条规则。
  4. 善用 CI:全套 SuperSync/WebDAV E2E 通过手动派发.github/workflows/e2e-scheduled.yml运行,本地只需npm run e2e:file <path> -- --retries=0快速迭代。

这份指南的本质是用“文档 + lint 强制 + 源码组织”把同步正确性不变量固化成可执行约束,让 Agent 与人类开发者共享同一套判断标准——理解它,就等于理解了 Super Productivity 的工程灵魂。

【免费下载链接】super-productivitySuper Productivity is an advanced todo list app with integrated Timeboxing and time tracking capabilities. It also comes with integrations for Jira, GitLab, GitHub and Open Project.项目地址: https://gitcode.com/GitHub_Trending/su/super-productivity

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 2:59:04

二进制反汇编原理与Python实现指南

1. 二进制与反汇编基础概念二进制文件是计算机程序的最终表现形式&#xff0c;它由处理器能够直接执行的机器指令组成。当我们谈论"二进制转反汇编"时&#xff0c;实际上是在讨论如何将这种机器可读的代码转换回人类可理解的汇编语言形式。1.1 二进制文件的本质二进制…

作者头像 李华
网站建设 2026/9/13 2:55:58

ICPC真题解析:Kruskal重构树与动态线性基实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 2:53:32

聚合路由器 vs 5G CPE:广电直播推流的播出级选型解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 2:50:22

LEBERT中文NER实战:词汇融合与CRF解码全解析

简介&#xff1a;面向中文NER任务中词汇信息融合效果的验证需求&#xff0c;资源包提供了完整可复现的LEBERT与BERT基线实现&#xff0c;适合NLP初学者、课程设计学生以及需要做模型对比的算法工程师&#xff0c;重点解决中文命名实体识别中词汇特征如何有效注入预训练模型的问…

作者头像 李华