分毫不差·同账——代码规范、冲刺任务与计划

分毫不差. 分毫不差. 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区

分毫不差·同账——代码规范、冲刺任务与计划

img

项目内容
这个作业属于哪个课程2601_CS_SE_FZU
这个作业要求在哪里团队第四次作业——站立式会议+α冲刺
团队名称分毫不差
这个作业的目标明确同账在 Alpha 冲刺期间执行的共用、前端、后端、数据库、测试及提交审查规范,写明本次冲刺任务与计划,并说明如何驱使 AI 技术员帮助团队完成设计、编程、测试与文档。覆盖课程目标 7
其他参考文献《阿里巴巴 Java 开发手册》终极版 v1.3.0、华为内部代码规范(《Java 语言编码规范》V1.00)、Google TypeScript Style Guide、Conventional Commits 1.0.0、邹欣《构建之法》第 2 章;链接见文末

目录

  • 一、代码规范怎么读
  • 二、前后端共用
  • 2.1 语言
  • 2.2 命名
  • 2.3 排版
  • 2.4 常量、注释与函数
  • 2.5 金额在三层里的写法
  • 三、前端规范
  • 3.1 TypeScript
  • 3.2 React
  • 3.3 React Native 与 Expo
  • 3.4 页面、请求与样式
  • 四、后端规范
  • 4.1 TypeScript 与 Fastify
  • 4.2 模块与分层
  • 4.3 接口与错误
  • 4.4 事务、金额与幂等
  • 4.5 日志与安全
  • 五、数据库规范
  • 六、测试规范
  • 七、分支、提交与审查
  • 八、合入前的检查
  • 各节所参考的规范
  • 九、冲刺目标
  • 十、职责分工与初始任务量
  • 十一、任务及完成标准
  • 十二、七天安排
  • 十三、燃尽图基线
  • 十四、主路径验收样例
  • 十五、AI 技术员
  • 团队如何交任务给 AI
  • 人如何验收 AI 成果

代码规范见第一至八节。冲刺任务与计划见第九至十四节,AI 技术员见第十五节。

一、代码规范怎么读

本文参考《阿里巴巴 Java 开发手册》终极版 v1.3.0 和华为内部代码规范(《Java 语言编码规范》V1.00),结合项目技术栈制定适用规则。同账采用 TypeScript,移动端使用 React Native / Expo,服务端使用 Fastify,数据库使用 PostgreSQL。Java 专有的线程池、包结构和对象分类不直接移植为本项目要求。

共用规范统一语言、命名、排版和金额表示;前端、后端与数据库章节规定各自的职责和边界;测试章节明确验证要求;提交与审查章节规定变更的合入流程。具体任务、人员分工和验收记录由冲刺计划及对应 Issue 维护。

规范分为三个等级:

img

(1)【强制】 合入前必须满足。未满足的变更不得合入。

(2)【推荐】 原则上采用。确需采用其他方案时,应在审查中说明理由并获得认可;通用规则的调整应同步更新文档。

(3)【参考】 供设计和实现时查阅,不单独作为本轮合入门槛。

规范的执行关系如下:

公开开发规范 → 项目业务与架构约束 → 仓库配置、自动检查和人工审查

本文中的目录均相对于仓库根目录。业务规则以 docs/product-spec.md 为基线,模块边界以 docs/architecture.md 和 docs/modules/ 为依据,可执行命令以根目录 package.json 和 docs/development.md 为准。规范、配置与代码发生冲突时,应在同一变更中核对并统一,避免长期保留两套约定。

项目使用 Node.js 24、pnpm 12.6.0、Expo SDK 57、Fastify 5.12.7、Drizzle ORM 0.45.4、Drizzle Kit 0.31.11 和 PostgreSQL 17;具体依赖版本以 package.json 和唯一的 pnpm-lock.yaml 为准。静态检查使用 TypeScript、ESLint 和 Prettier,服务端及共享包自动化测试使用 Vitest。

二、前后端共用

本节参考《阿里巴巴 Java 开发手册》的命名、常量、格式和注释规约,华为内部代码规范(《Java 语言编码规范》V1.00),以及 Google TypeScript Style Guide。具体命名和格式以本项目约定为准。

2.1 语言

(1)【强制】业务代码使用 TypeScript,开启 strict。不得使用 any 绕过类型检查;类型未知的外部数据使用 unknown,经运行时校验或类型收窄后再访问。确需类型断言或类型检查例外时,应限定范围并说明原因,不得提交无说明的 @ts-ignore 或 @ts-expect-error。

(2)【强制】业务标识符使用含义明确的英文单词及必要的数字、下划线,不使用拼音或中文变量名。面向用户的文案使用中文,集中表达在界面文案或错误响应的 message 中。

(3)【强制】标识符应准确表达业务含义,避免 ret、tmp、data2 等缺乏上下文的命名。局部循环下标可使用 i、j;通用函数中的参数名应能够结合类型和用途理解。

(4)【推荐】布尔变量使用 is、has、can 等前缀,例如 isCreator、hasReceipt,避免双重否定或含义不明确的否定命名。

(5)【强制】移动端与服务端只通过 packages/contracts、packages/domain 共享代码。共享包不得依赖 Node 专有 API、React Native、Fastify 或数据库驱动;移动端不得导入服务端源码和数据库模型。工作区包通过 workspace:* 和包的公开导出使用,不跨目录相对导入其他包的源码。

2.2 命名

位置风格示例
类型、组件PascalCaseExpenseDetail、LedgerStatus
函数、变量、对象字段camelCasecreateExpense、netCents
固定业务上限和算法标识大写字母加下划线MAX_LEDGER_MEMBERS、SETTLEMENT_ALGORITHM
错误码、状态和审计动作的字符串取值大写字母加下划线LEDGER_FROZEN、ACTIVE、EXPENSE_CREATED
组件文件PascalCase,与主要组件同名ConnectionScreen.tsx、Button.tsx
非组件文件小写单词或 kebab-caseservice.ts、query-keys.ts
业务资源目录通常使用小写复数expenses、ledgers
技术或能力目录使用仓库约定名称auth、profile、theme、lib、db

接口类型不加 I 前缀。普通 const 变量、Schema 和配置对象仍按用途使用 camelCase,不因使用 const 声明就全部改为大写。

Expo Router 文件名遵循路由规则,例如 _layout.tsx、[ledgerId] 和路由组目录,不套用普通组件文件的命名要求。接口字段使用 camelCase,数据库列使用 snake_case,通过数据访问层映射。

2.3 排版

(1)【强制】排版结果以根目录 .prettierrc.json 为准,不因个人编辑器设置引入不同风格:

  • 缩进使用 2 个空格。
  • TypeScript 和 JavaScript 字符串优先使用单引号,语句末尾保留分号;JSON 使用双引号。
  • printWidth 为 100,作为格式化目标宽度,由 Prettier 决定具体换行。
  • 尾随逗号遵循 trailingComma: 'all'。
  • 文件使用 UTF-8 编码、LF 换行,保留文件末尾换行,不保留无意义的行尾空格。

(2)【推荐】if、for、while 等控制语句优先使用花括号,尤其是包含嵌套分支或易产生歧义的情况。新增代码应与所在模块保持一致,避免为局部格式调整产生大范围无关差异。

(3)【推荐】行注释的 // 与正文之间保留一个空格;工具指令和特殊语法按相应工具要求书写。

(4)【强制】ESLint 统一使用根目录 eslint.config.mjs,其中包含 JavaScript、typescript-eslint 推荐规则,以及跨端和跨模块导入限制。执行 pnpm check 时不得留下错误或警告。未由工具覆盖的约定通过人工审查确认,不将“检查通过”等同于全部规范已满足。

本节格式规则参考 Prettier 配置说明。编辑器配置应与仓库规则一致,不将未纳入仓库的配置文件视为执行依据。

2.4 常量、注释与函数

(1)【强制】重复使用的业务上限和跨端规则应有唯一来源,通过具名常量或共享 Schema 复用,避免各模块自行定义不同数值。

规则取值或范围
账本成员数最多 12 人,包含创建者;复用 MAX_LEDGER_MEMBERS
分摊参与人数1~12 人,成员不得重复
单笔消费金额1~999999999 分;复用 MAX_EXPENSE_CENTS
按份分摊的份数每名参与成员为 1~10000 的整数
收据数量每笔消费最多 1 张
图片大小单张最多 1048576 字节,即 1 MiB;复用 MAX_IMAGE_BYTES
分页大小默认 20 条,最多 50 条
会话有效期30 天
邀请有效期7 天,重置后旧邀请码失效
幂等结果保留期7 天;客户端结果不确定时的原键重试窗口为 24 小时
请求超时普通请求 10 秒,图片上传 30 秒
临时图片清理超过 24 小时且未绑定、无引用的图片可清理

(2)【推荐】单个函数以不超过 80 行作为团队审查参考。超出时应检查职责是否可以拆分,不为满足行数而拆出缺乏独立含义的函数。

(3)【推荐】注释说明业务原因、边界条件和不变量,不重复代码已直接表达的操作。例如,结算预览为何不能冻结账本、金额分摊差额为何必须拒绝、还款为何不计入消费总额。

(4)【强制】不提交空文件头、无实际内容的模板注释或与实现不符的说明。修改行为时同步维护相关注释。

2.5 金额在三层里的写法

img

(1)【强制】页面输入和展示使用元;接口使用十进制整数分字符串;数据库使用 BIGINT 保存整数分。两端的金额计算统一使用 TypeScript bigint,禁止使用 number 进行金额计算。

页面输入 '300.00' 元
  → parseYuan:30000n 分
  → JSON:amountCents: "30000"
  → 服务端校验并转换为 bigint
  → PostgreSQL:amount_cents = 30000
层表示方式职责
页面300.00 元接收十进制输入;通过共享金额函数解析和格式化
接口amountCents: "30000"传输整数分字符串,使用契约 Schema 校验
数据库amount_cents = 30000保存精确整数分,由数据访问层处理字段映射

金额转换正例:

import { formatYuan, parseYuan } from '@tongzhang/domain';

const amountCents = parseYuan('300.00');
const amountField = { amountCents: amountCents.toString() };
const displayAmount = `${formatYuan(amountCents)} 元`;

以下写法不符合规范:

const amountCents = Math.round(Number(yuanInput) * 100);
const amountField = { amount: 300.0 };

(2)【强制】金额字段应标明单位,例如 amountCents、netCents,不使用含义不明确的 amount、money、price。接口拒绝金额数字值、科学计数法、前导加号、非规范前导零和以元为单位的小数字符串。消费金额必须为正;分摊金额允许为零;净额允许为负。具体边界由共享契约校验。

(3)【强制】状态和分类采用契约规定的字符串取值,不使用数字替代,也不在两端重复定义不一致的枚举。

含义取值
账本状态ACTIVE、SETTLING、SETTLED
分摊方式EQUAL、SHARES、AMOUNT
成员角色CREATOR、MEMBER
消费类别DINING、TRANSPORT、TICKET、LODGING、SHOPPING、OTHER
转账状态PENDING、PAID

(4)【强制】“鼓山一日”作为共用回归账:小安支付食堂消费 12000 分,小白支付门票消费 12000 分,两笔均由四人均分;小陈支付车费 6000 分,由小安、小陈均分。有效消费共 30000 分,消费净额依次为小安 +3000 分、小白 +6000 分、小陈 −3000 分、小丁 −6000 分。结算方案为小陈向小安转账 3000 分、小丁向小白转账 6000 分,共 2 笔、9000 分。结算前全员消费净额之和为零;全部登记已还后,每名成员的剩余净额均为零,消费总额仍为 30000 分。

img

三、前端规范

移动端工程位于 apps/mobile。Expo Router 路由位于 apps/mobile/app;页面、表单、面板和功能状态按模块放在 apps/mobile/src/features。公共组件位于 src/components,主题变量位于 src/theme,HTTP、会话和查询客户端等基础能力位于 src/lib。本项目面向 Android 和 iOS,不新增 Web 页面或 Web 构建。

3.1 TypeScript

本节参考 Google TypeScript Style Guide 和 typescript-eslint。

(1)【强制】组件属性使用 type 或 interface 明确定义。可选字段使用 ?;null 和 undefined 的含义应与契约一致,不无依据扩大可接受类型。

(2)【强制】外部响应经统一 HTTP 层和 Zod Schema 校验后才能用于渲染。校验失败时显示错误,不将未知 JSON 直接用于页面,也不以伪造的零余额或空账本掩盖失败。

(3)【强制】功能实现优先使用具名导出。Expo Router 路由文件按框架要求默认导出路由组件,并引用对应 feature 的页面实现;同一文件不混放多个独立页面。

(4)【推荐】业务状态使用契约导出的类型;面板和交互状态使用可辨识联合类型,避免组合多个布尔变量产生无效状态。

(5)【推荐】仅用于类型检查的导入使用 import type。共享接口类型优先从契约 Schema 推导,不在页面重复维护同名结构。

3.2 React

本节参考 Airbnb React/JSX Style Guide 和 Rules of Hooks。

(1)【强制】新增界面使用函数组件,不新增 class 组件。

(2)【强制】Hook 只在函数组件或自定义 Hook 顶层调用,不置于条件或循环中;Effect 的依赖应完整。自定义 Hook 以 use 开头,按职责放在所属 feature 的文件中;数量增加时可整理到 hooks/ 子目录。

(3)【强制】业务列表使用服务端返回的稳定 ID 作为 key,不使用数组下标标识会增删或重排的记录。

(4)【推荐】组件内部事件处理函数以 handle 开头,传入子组件的事件回调以 on 开头,例如 handleSubmitExpense、onSubmit。

(5)【推荐】组件保持单一职责。约 200 行以上的组件应重点检查是否需要拆分表单区、列表项或结果区;行数仅作为团队审查参考。

(6)【强制】组件不自行实现最终分摊、净额和最少转账算法。输入预览复用 @tongzhang/domain;提交时按契约发送总额、成员及份数或指定金额,由服务端独立重算。精确最少转账方案通过服务端接口获取。

展示组件正例:

import { Text } from 'react-native';
import { formatYuan } from '@tongzhang/domain';

type SplitHintProps = {
  amountCents: bigint;
};

export function SplitHint({ amountCents }: SplitHintProps) {
  return <Text>{formatYuan(amountCents)} 元</Text>;
}

传入的金额应来自共享分摊函数的成员结果或服务端响应。人均分摊可能存在余分,不能用单一平均值代替每名成员的精确金额。

3.3 React Native 与 Expo

本节参考 Expo SDK 57 文档及其中的 SecureStore 说明。涉及 Expo / React Native API 和兼容性的实现应核对该版本文档。

(1)【强制】会话令牌通过统一会话封装保存到 SecureStore,不写入 AsyncStorage、日志或验收截图。进入业务区前在线校验会话;退出或切换账号时清理令牌及相应业务查询缓存。

(2)【强制】上传图片限定为 JPEG / PNG,选择后可先压缩;上传前校验最终文件不超过 1048576 字节。每笔消费最多一张收据。超限或格式不符时在原表单反馈,不发起无效上传;服务端仍须独立校验文件内容。

(3)【强制】流水等长列表使用 FlatList,不使用 ScrollView 一次挂载全部记录。列表项抽为稳定组件,避免在 renderItem 内定义新的组件类型。

(4)【推荐】主要交互区域不小于 44 逻辑像素。底部导航、按钮等公共尺寸通过主题变量或公共组件统一维护。

(5)【强制】相机、相册等权限被拒绝时,应保留当前页面并说明可用操作。需要用户前往系统设置授权时给出明确提示,不以空白页面代替错误反馈。

(6)【参考】列表性能优化以测量结果为依据,确有需要时再评估 FlashList 等方案。

(7)【强制】原生依赖在 apps/mobile 内通过 pnpm exec expo install 安装,不独立升级 React 或 React Native。不手工编辑生成的 ios、android 目录;原生配置通过 Expo 配置和 config plugin 管理。新增原生依赖或修改原生配置后,应重建开发客户端。

3.4 页面、请求与样式

模块组织参考 Airbnb JavaScript Style Guide;金额表示见 2.5,错误响应及状态码见 4.3。

功能目录或文件职责
路由、布局与导航守卫apps/mobile/app连接页面、导航和访问守卫
登录与个人资料apps/mobile/src/features/auth、profile账号交互、本人资料与偏好
账本与邀请apps/mobile/src/features/ledgers、invitations建账、详情、加入、归档和历史
消费与结算apps/mobile/src/features/expenses、settlements表单、流水、结算、已还登记与结清
余额与统计apps/mobile/src/features/balances成员余额和支出统计
图片适配apps/mobile/src/features/images原生上传和受鉴权读取
公共样式与组件apps/mobile/src/theme、components主题变量及可复用界面组件
网络和会话基础能力apps/mobile/src/libHTTP、令牌与查询客户端

(1)【强制】各 feature 的 api.ts 通过统一 HTTP 层发起请求。页面不直接拼接分散地址,不导入服务端代码或 Drizzle 模型。请求和响应复用 packages/contracts 中的 Schema。

(2)【强制】认证和幂等要求以 packages/contracts/src/endpoints.ts 中的 authenticated、idempotent 为准。受保护接口携带 Authorization: Bearer <token>;要求幂等的写接口另带 UUID 形式的 Idempotency-Key。所有写操作禁止自动重试。结果不确定时,可在 24 小时内由用户手动使用原键和原请求内容重试;超过窗口应先核对业务结果,不直接生成新键重交。

(3)【强制】失败时按错误码反馈,通常保留当前页面和内存中的表单输入;会话失效、权限撤销等情况按访问规则处理。

错误码或场景页面处理
VALIDATION_ERROR有 fieldErrors 时显示字段提示,否则显示表单级提示
INVALID_CREDENTIALS停留登录表单并显示错误
UNAUTHENTICATED清理失效会话及业务缓存,返回登录入口
FORBIDDEN停止受限操作,刷新权限;不继续展示无权访问的数据
LEDGER_FROZEN、LEDGER_STATE_INVALID、VERSION_CONFLICT保留可恢复输入,刷新状态并说明限制
分摊合计不符在分摊区域提示并阻止提交,不自动修改金额
RECEIPT_LIMIT、IMAGE_INVALID、PAYLOAD_TOO_LARGE在图片区域反馈,保留其余表单输入
NETWORK_UNAVAILABLE、NETWORK_ERROR、REQUEST_TIMEOUT显示网络或结果未确认提示,按幂等规则提供手动重试
INVALID_RESPONSE、HTTP_ERROR显示请求失败,不使用不可信响应更新业务状态
INVALID_CONFIGURATION提示配置异常,不反复重试业务请求

上述网络、响应解析和配置错误码由移动端 HTTP 层产生,不对应服务端业务错误码。

(4)【强制】金额输入保留十进制字符串,提交前使用共享金额函数转换为整数分字符串。不得通过浮点运算或 Math.round 处理金额。转换失败时保留输入并显示错误。

(5)【强制】业务数据不建立持久缓存或离线队列;表单草稿仅保留在内存中。查询键包含用户身份,退出或切换账号时清理缓存。查询和写操作沿用统一 QueryClient 的重试及网络配置,不在页面自行增加自动重试。

(6)【强制】写入成功后刷新受影响数据。消费变更应使账本、流水、余额、统计和结算预览等相关查询失效;已还登记应刷新结算进度和余额;个人归档应刷新本人账本列表和历史。

(7)【推荐】颜色、字号、圆角和间距从主题变量取得,重复的按钮、卡片等使用公共组件。页面不重复维护同义样式值。

(8)【强制】页面覆盖加载、空态、错误和断网状态;提交期间避免重复触发。分摊、筛选、图片选择及错误提示等使用原页面中的面板或状态,不单独新增全屏路由。

四、后端规范

服务端工程位于 apps/server,业务模块位于 apps/server/src/modules。路由负责协议接入,Service 负责业务权限、状态和事务,Repository 负责数据访问。客户端交互限制不能替代服务端校验。

img

4.1 TypeScript 与 Fastify

本节参考 Fastify Server、Validation and Serialization 和 TypeScript 文档。项目通过 Zod 和 fastify-type-provider-zod 统一请求、响应与接口文档。

(1)【强制】业务模块通过 Fastify 路由插件接入,业务路径使用 /api/v1 前缀。GET /health/live 和 GET /health/ready 位于该前缀之外,允许公开访问;存活检查不依赖数据库,就绪检查验证真实数据库连接。

(2)【强制】接口的方法、路径、认证、幂等、传输格式、状态码和 Schema 统一维护在 packages/contracts/src/endpoints.ts。模块路由通过公共适配器注册,不各自维护另一套协议定义。

(3)【强制】协议接入层负责认证、路径参数、查询参数、请求体校验和响应校验,并调用 Service。不得在路由中实现账务算法或直接操作数据库;业务权限和状态判断由 Service 执行。

(4)【强制】统一使用公共 setErrorHandler。业务异常转换为统一错误响应,不在各路由中捕获后返回另一种 JSON 结构。需要回滚的异常必须继续传播至事务边界。

(5)【强制】Swagger UI 仅在非生产运行环境注册到 /docs;生产环境不开放该入口。环境判定以运行时配置为准。

(6)【强制】按依赖顺序注册数据库、认证和业务模块。会话校验由账号模块注入公共认证入口;基础设施不反向依赖业务模块。跨模块调用只使用对方公开出口,不复制权限或状态规则。

4.2 模块与分层

本节参考《阿里巴巴 Java 开发手册》的应用分层思路,结合 TypeScript 模块化单体组织。项目不单独设置 Manager 层。

层或能力路径职责禁止事项
路由apps/server/src/modules/<模块>/routes.ts注册契约对应的 HTTP 入口直接执行 SQL、控制业务事务、实现账务算法
业务apps/server/src/modules/<模块>/service.ts权限、状态、最终计算和事务协调决定移动端具体导航方式
数据访问apps/server/src/modules/<模块>/repository.ts参数化查询、行锁、结果映射自行决定跨模块业务流程或另开事务
接口契约packages/contracts/src请求和响应 Schema、接口登记表、共享类型依赖应用实现或数据库
跨端纯函数packages/domain/src整数金额、分摊计算和业务上限I/O、平台 API、数据库和 Fastify 依赖
服务端结算算法apps/server/src/modules/settlements/solver.ts精确最少笔数方案和确定性排序下放移动端或混入共享包
HTTP 与数据库基础设施apps/server/src/http、db请求上下文、错误处理、连接、事务、幂等锁、审计写入反向导入业务模块
模块或能力路径边界
账号与本人资料apps/server/src/modules/auth、profile注册、登录、会话、退出、本人资料及偏好
账本与邀请apps/server/src/modules/ledgers、invitations成员权限、账本、邀请、加入、个人归档及历史
消费与分摊apps/server/src/modules/expenses消费增删改查、最终分摊、收据关联
图片apps/server/src/modules/images图片上传、授权读取、绑定校验和清理
余额与统计apps/server/src/modules/balances一致快照下的消费汇总、净额和统计
结算apps/server/src/modules/settlements预览、正式批次、冻结、已还登记与结清
数据库支撑apps/server/src/db、apps/server/drizzleSchema、事务、幂等锁、审计及 SQL 迁移

(1)【强制】跨业务模块仅通过对方 index.ts 的公开导出访问服务、函数和类型,不导入内部路由或绕过模块接口访问内部实现。

(2)【强制】业务查询集中在 Repository,向上返回 camelCase 对象,不将数据库整行或物理列名直接暴露给接口。数据库基础设施、Schema 和迁移中的必要 SQL 不受 Repository 文件位置限制,但同样必须遵守参数绑定和审查要求。

(3)【强制】Service 管理事务边界,跨 Repository、跨模块写入使用同一个 tx。公共权限、图片绑定、审计和幂等能力应能够在调用方事务内执行,不在内部另开独立事务。

具体任务与人员分配以冲刺计划和 Issue 为准。代码所有权以模块边界描述,不以个人名称代替目录和职责。

4.3 接口与错误

本节参考 OWASP REST Security Cheat Sheet 及《阿里巴巴 Java 开发手册》的异常处理原则。

(1)【强制】资源路径使用小写名称,集合通常使用复数。预览、登记、结清、归档等操作沿用接口登记表中的路径,不在客户端自行推导或改名。

(2)【强制】JSON 业务成功响应使用 { data } 包装,分页响应额外包含 page.nextCursor。图片读取返回受鉴权的二进制内容,不包装为 JSON。各接口的成功状态码以登记表为准。

(3)【强制】失败响应统一为以下结构,fieldErrors 可选:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "请求参数不正确",
    "fieldErrors": { "amountCents": ["金额必须大于 0"] }
  },
  "requestId": "39c17774-812c-4f95-8e97-372a3d92b834"
}

message 使用明确的中文说明,移动端根据 code 分支,不匹配完整文案。响应不得包含 SQL、数据库约束名、堆栈或敏感凭据。无字段级信息时,不伪造 fieldErrors。

(4)【强制】区分协议校验与业务校验。Zod 请求校验失败统一返回 VALIDATION_ERROR(400),包括契约中已检查的分摊合计不符;业务层的独立校验按明确约定返回业务错误。不得将所有输入错误都承诺为 422,或要求客户端只识别其中一种。

场景错误码HTTP 状态码
请求字段、日期、金额、份数或契约校验失败VALIDATION_ERROR400
其他请求格式错误BAD_REQUEST400
账号或密码不正确INVALID_CREDENTIALS401
未登录或令牌失效UNAUTHENTICATED401
注册邮箱已被占用EMAIL_TAKEN409
角色或成员权限不足FORBIDDEN403
资源不存在NOT_FOUND404
账本冻结后仍尝试修改消费或成员LEDGER_FROZEN409
当前状态不允许执行操作LEDGER_STATE_INVALID409
版本已过期VERSION_CONFLICT409
账本成员已达上限MEMBER_LIMIT_REACHED409
同一幂等作用域内,同键对应不同请求内容IDEMPOTENCY_CONFLICT409
尚有未登记的转账,不能结清OUTSTANDING_TRANSFERS409
邀请码无效或过期INVITE_INVALID / INVITE_EXPIRED404 / 410
业务层重算发现按金额分摊合计不符SPLIT_SUM_MISMATCH422
业务层收据数量校验失败RECEIPT_LIMIT422
上传字段或文件数量格式无效IMAGE_INVALID400
业务层图片内容校验失败IMAGE_INVALID422
请求体或图片超过大小限制PAYLOAD_TOO_LARGE413
请求超过限流阈值RATE_LIMITED429
未提供相应用例能力FEATURE_NOT_READY501
数据库就绪检查失败SERVICE_UNAVAILABLE503
业务层发现账务不守恒ACCOUNTING_INVARIANT500
未处理的内部异常INTERNAL_ERROR500

业务错误的新增或调整应同步模块说明、服务端测试和移动端处理。原生网络、响应解析和配置错误由移动端生成,见 3.4,不混入本表的 HTTP 状态映射。

(5)【强制】登录失败统一使用“账号或密码错误”,不额外说明邮箱是否已注册。EMAIL_TAKEN 仅用于注册冲突。受保护资源应校验会话及对应成员权限,游标和资源 ID 不能代替授权。

(6)【强制】捕获异常后必须有明确处理:转换为可识别错误、执行必要清理,或继续抛出以触发回滚。禁止空 catch、记录日志后伪装成功,以及使用异常代替常规状态分支;状态校验失败后抛出统一业务异常属于合法处理。

4.4 事务、金额与幂等

本节参考 Drizzle 事务文档。金额表示见 2.5,跨模块事务规则见 4.2。

(1)【强制】消费主记录、分摊、收据关联、相关版本、操作日志和幂等成功结果必须在同一事务中提交。任一必要写入失败时,整个业务操作回滚。

(2)【强制】业务写请求统一执行会话及参数检查,再取得幂等事务锁和账本行锁,随后检查当前权限、状态、版本及关联资源。加入成员、消费变更和正式结算共同锁定同一账本行,防止超员和冻结竞争。锁顺序应一致,Repository 不得绕过外层事务。

(3)【强制】人均和按份分摊使用最大余数法,余数相同时按稳定成员 ID 分配;按份的每人成员份数为 1~10000 的正整数。按金额分摊要求各成员金额非负且合计等于消费总额,不自动修正差额。服务端独立重算并验证成员归属,不信任客户端提交的预览结果。

(4)【强制】消费修改校验消费 version;影响结算的消费或成员变更递增账本版本。正式结算锁定账本后重新检查创建者权限、ACTIVE 状态和预览对应的版本,并重新计算方案。

(5)【强制】结算预览使用一致快照,不写正式批次、不冻结账本。正式结算在同一事务中保存批次和转账快照,并将账本改为 SETTLING;全员消费净额均为零时仍保存零转账批次,由创建者确认后直接进入 SETTLED,不生成零金额转账。

(6)【强制】账本进入 SETTLING 或 SETTLED 后,禁止修改消费和财务相关成员关系。正式结算和整本结清仅创建者可执行;已还登记仅转账付款人或创建者可执行,且仅支持整笔登记。重复登记不得改变首次登记时间。所有转账已登记且逐人剩余净额为零后,创建者方可确认结清。

(7)【强制】个人归档仅允许在 SETTLED 状态执行,只更新本人的 ledger_members.archived_at,不改变账本财务状态或其他成员的可见状态。归档不视为财务成员关系变更。

(8)【强制】不建立余额表。余额和统计通过有效消费、分摊及已登记转账派生;多次查询应使用同一个只读 REPEATABLE READ 事务,或合并为单一 SQL 快照。

  • 已付消费金额、应摊消费金额仅由有效消费和分摊计算。
  • 消费净额=已付消费金额-应摊消费金额。
  • 剩余净额=消费净额+已还转出金额-已还转入金额。
  • 登记已还不改变消费总额,也不改变已付消费金额和应摊消费金额。

(9)【强制】需要幂等的接口按“用户 + 操作作用域 + UUID 键”识别请求,作用域应区分请求方法和规范化资源路径。同键同内容返回已保存的成功结果;同键不同请求摘要返回 IDEMPOTENCY_CONFLICT。重放前仍检查当前身份及访问权限,成功结果与业务写入共用事务并保留 7 天。取得幂等锁本身不等于已完成结果查询、内容比对和结果保存。

(10)【强制】注册、登录、退出、本人资料更新和图片上传不要求幂等键;具体适用范围以接口登记表为准。无论是否要求幂等键,移动端均不得自动重试写操作。

4.5 日志与安全

本节参考 OWASP Password Storage Cheat Sheet、OWASP Logging Cheat Sheet 及《阿里巴巴 Java 开发手册》的安全规约。

(1)【强制】口令使用 Argon2id 加盐哈希。项目参数为 memoryCost = 19456 KiB、timeCost = 2、parallelism = 1、16 字节随机盐、32 字节输出;盐和参数保存在编码串中,写入 users.password_hash。明文口令不得入库、写入日志或幂等结果。

(2)【强制】会话令牌使用 32 字节安全随机值生成,服务端仅在注册或登录成功时向客户端返回原文。auth_sessions 保存 SHA-256 摘要,有效期为 30 天,退出时写入 revoked_at。后续请求通过认证头携带令牌,不将其放入 URL。

(3)【强制】使用 Fastify logger 记录结构化日志。业务日志包含请求标识、动作及结果,涉及账本时附账本 ID;审计日志与业务事务共用 tx。不得记录密码、密码哈希、令牌原文或摘要、连接串、完整图片及无关成员邮箱。审计动作名与错误结果码分别表达,不混用。

(4)【强制】服务端校验账本成员身份和操作角色。记录人或创建者可在 ACTIVE 状态编辑、删除消费;付款人不因付款身份自动获得编辑权限。创建者管理邀请、正式结算和结清;转账付款人或创建者登记已还。

(5)【强制】图片存放于独立 bytea 表 image_assets。未绑定图片仅上传者可读,绑定后仅对应账本成员可读。业务保存时在同一事务中校验上传者、用途、账本归属及绑定状态;编辑消费可保留原收据,不得挪用其他消费的收据。

(6)【强制】服务端校验图片实际解码结果、尺寸和字节大小,不只信任文件名或 MIME。图片读取携带鉴权,并返回禁止持久缓存的响应头;移动端同样不得将其作为离线业务缓存。清理任务仅删除超过 24 小时且未绑定、无引用的临时图片。

(7)【强制】应用凭据和数据库连接配置仅存在于未提交的 .env 或部署环境中,不写入源码、日志或截图。EXPO_PUBLIC_ 变量只能包含可公开配置,不得包含密钥。运行期用户会话令牌按 3.3 保存,不配置为应用环境变量。

(8)【强制】开发 API 与开发 Compose 共用 apps/server/.env 的 PG* 参数。生产仅由 Compose 注入环境变量,API 不加载本地 .env;生产镜像通过发布流程构建,服务器不编译源码。

(9)【强制】登录、邀请码访问等入口遵守统一限流策略,超过阈值返回 RATE_LIMITED。新增路由不得绕过公共认证、限流或错误处理机制。

五、数据库规范

本节参考 PostgreSQL 17 标识符、数值类型、SQL Style Guide、Drizzle 表声明和迁移文档。Java 开发手册中的数据库原则按 PostgreSQL 和项目架构适配;本项目使用外键表达归属,应用层同时执行权限和状态校验。

(1)【强制】表名、列名使用小写字母和下划线,业务实体表通常使用复数。开发数据库默认名为 tongzhang;测试库必须与开发库、生产库隔离,不强制所有环境使用相同库名。

(2)【强制】实体标识使用 UUID;关联表和支撑表按业务唯一性使用适当的主键,例如 expense_splits 使用消费与成员组成的复合主键,idempotency_keys 使用用户、操作和键组成的复合主键。不得为形式统一而移除业务唯一约束。

(3)【强制】金额列使用 BIGINT,单位为分,Drizzle 映射为 bigint。创建、更新、到期等时间点使用 timestamptz,接口按带时区的时间格式传输;消费发生日期使用 date,不得与时间点混用。状态使用约定的文本值和数据库约束,不使用含义不明确的数字。

(4)【强制】业务及支撑表包括 users、auth_sessions、ledgers、ledger_members、invitations、expenses、expense_splits、image_assets、expense_images、settlement_batches、settlement_transfers、idempotency_keys、operation_logs。表定义集中在 apps/server/src/db/schema;新增或调整表结构应同步评估契约、数据访问和业务调用。

(5)【强制】表结构变更按以下顺序执行:修改 Schema → pnpm generate:db 生成迁移 → 审查 SQL 和迁移元数据 → 在专用测试库执行迁移及验证 → 提交 Schema 与迁移。迁移位于 apps/server/drizzle,执行入口为 pnpm migrate:db。共享环境不得使用 schema push。

(6)【强制】已合并迁移不改写内容;后续变更新建迁移。生产库不得手工改表,迁移由部署步骤独立执行,不在 API 启动时自动执行。

(7)【强制】查询使用 Drizzle 查询构建器或参数化 SQL,不拼接用户输入。Repository 对外返回明确结构,敏感字段不得随整行数据进入接口响应。

(8)【强制】外键和必要的复合约束表达跨表归属。图片二进制仅保存在 image_assets;账本保存封面引用,消费收据通过 expense_images 关联,不把图片内容放入消费行或业务列表 JSON。

(9)【推荐】索引应服务已明确的查询、关联约束和唯一性要求,例如按账本读取成员、按账本和日期读取流水、查询幂等结果。新增索引应说明用途,不为未经确认的需求堆积索引。

(10)【推荐】迁移角色与业务运行角色分离,业务连接按最小权限配置。数据库不向公网暴露,备份和恢复验证按部署文档执行。

六、测试规范

本节参考《阿里巴巴 Java 开发手册》的单元测试原则、Vitest 和《构建之法》第 2 章。测试应自动化、相互独立、可重复;详细用例和执行记录另行维护。

(1)【强制】共享包、服务端和基础设施脚本的自动化测试使用仓库统一测试入口。用例之间隔离可变数据,固定必要的时间和随机输入,不依赖执行顺序或人工操作补充断言。

(2)【强制】金额、分摊或结算变更覆盖 2.5 的鼓山回归账,并按改动补充余分、按份、部分成员、自定义金额、全零、人数边界及贪心非最优反例。仅验证总额相等不足以证明逐人分摊正确或笔数最少。

(3)【强制】共享纯函数测试放在对应包的 tests 中;服务端结算算法测试位于 apps/server/tests。pnpm test 执行不依赖数据库的测试。HTTP 协议可通过 Fastify.inject() 验证,数据约束、事务和并发行为必须使用真实 PostgreSQL,不用 SQLite 替代。

(4)【强制】集成测试使用独立测试库,显式设置 TEST_DATABASE_URL 后运行 pnpm test:integration。涉及外键、唯一约束、权限查询、事务回滚、并发锁、幂等重放和图片绑定的修改,应覆盖对应数据库行为。

(5)【推荐】每个测试聚焦一个明确行为,可使用多个断言验证同一行为的不同不变量。名称应说明场景和预期,例如“重复登记已还返回原结果且不改变登记时间”,不将“一项行为”误解为“只能写一个断言”。

(6)【强制】权限、冻结、版本、幂等、图片和分摊的错误分支应有相应用例。涉及接口错误时同时验证错误码、HTTP 状态和写入效果,不能仅检查出现了异常。

(7)【强制】移动端验证覆盖表单错误、空态、断网、输入保留、会话失效和重复点击;关键交互使用适当的组件测试或可复现的原生验收记录。Vitest 服务端测试通过不等于移动端界面或原生功能验收通过。

(8)【强制】验收记录区分模拟接口、真实数据库、Android / iOS JavaScript 导出和原生安装验证。完整流程应核对登录、建账、邀请、消费、图片、预览、正式冻结、已还、结清和个人归档;登记已还后消费总额保持不变。

七、分支、提交与审查

提交格式参考 Conventional Commits 1.0.0。类型和范围的使用结合本项目工作区约定。

(1)【强制】主分支保持可运行,功能和修复通过独立分支及 PR 合入。分支名使用可识别的类型、模块和简短描述,例如 feat/expenses-create、fix/settlement-preview;Codex 创建的分支使用 codex/ 前缀,除非任务另有明确约定。

(2)【强制】提交标题采用 <类型>(<可选范围>): <变更说明>,说明具体结果,避免仅写“update”或“修改”。类型按变更用途选择 feat、fix、test、docs、refactor、build、ci、chore 等;范围使用模块或工作区能力名称,不强制每项跨模块修改归入单一目录。

feat(expenses): 原子保存消费、分摊和收据关联

Refs: #12

(3)【强制】使用本人账号提交,相关 Issue 写明任务范围和验收标准;提交正文或 PR 关联对应 Issue。冲刺记录区分任务链接与签入链接:任务链接指向 Issue,代码变更证据指向 commit 或 PR。

(4)【强制】pnpm 工作区只维护根目录 pnpm-lock.yaml,依赖变更同步提交锁文件,不另生成 npm 或 Yarn 锁文件。.env、密钥、node_modules 和构建产物不提交;不含凭据的 .env.example 按项目需要维护。

(5)【强制】脚本命名采用“动作:对象”,例如 build:ios、migrate:db;组合入口及包内对象明确的命令可保留简短名称。脚本按初始化、开发、构建与导出、数据库、检查与格式化、测试的顺序组织。变更脚本时同步调用方、CI 和文档。

(6)【强制】初始化、开发、原生构建和迁移职责分离:setup 负责初始化,dev 只检查数据库、编译并启动开发进程;原生构建和迁移分别通过独立命令执行,不隐式加入 API 启动流程。

(7)【强制】审查按以下顺序执行:

  • 作者执行适用检查和测试,在 PR 中说明变更、影响范围、验证结果及未验证事项。
  • 模块负责人核对契约、权限、业务状态、数据访问和模块边界;涉及公共能力时由相关模块共同核对。
  • 金额、分摊和结算变更由自动化测试及验收职责复核,包括逐人金额、守恒、最少笔数和已还后的余额。
  • 系统架构职责审查跨模块依赖、事务、迁移及回归风险,确认合入。

(8)【强制】AI 生成的代码遵循相同检查、测试和审查要求。提交者应能够解释实现并对结果负责,不以生成来源替代人工核对。具体人员分配以冲刺计划为准。

八、合入前的检查

合入检查包括静态检查、适用的自动化测试、构建与原生验证、人工审查四个方面。各项要求随变更范围确定,验证记录应能对应本次提交。

静态检查 → 自动化测试 → 适用的构建和原生验证 → 人工审查与合入
变更范围必须完成的验证
代码变更pnpm check,包括共享包构建、类型检查、ESLint 和 Prettier
业务或基础设施逻辑变更相应测试;无数据库测试入口为 pnpm test
数据库、事务、权限查询或并发行为变更专用测试库准备及迁移,显式设置 TEST_DATABASE_URL 后执行 pnpm test:integration
服务端构建或发布相关变更pnpm build:server;涉及容器时执行相应容器验证
共享包、原生依赖或路由变更pnpm export:mobile 和 pnpm doctor:mobile
移动端依赖变更pnpm check:mobile-deps,即在移动端执行 expo install --check
新增原生依赖或修改原生配置pnpm build:ios 或 pnpm build:android 重建开发客户端,并验证对应原生能力

常用基础检查入口:

pnpm check
pnpm test

数据库与原生检查按上表和开发文档补充执行,不在文稿或提交记录中填写真实连接凭据。CI 的适用检查必须通过,不能用本地单项通过替代流水线结果。

提交前逐项核对:

  • 文件位于对应模块;路由与页面实现分离,面板和错误状态未新增独立全屏路由。
  • 请求、响应及认证、幂等要求与契约一致,跨端只通过共享包和 HTTP 协作。
  • 持久化字段变更同步 Schema、迁移和映射;派生字段按需更新契约与计算,不机械增加数据库列。
  • 金额使用整数分和 bigint,分摊与结算由服务端重算,鼓山算例及适用边界用例通过。
  • 写事务由 Service 管理,各 Repository 共用 tx,锁顺序、权限、版本、审计和幂等结果正确。
  • 错误码、HTTP 状态和移动端反馈一致;失败不伪装成功,不自动重试写操作。
  • 图片读写均校验权限,临时资产和已绑定资产按不同规则处理,不建立业务持久缓存。
  • 配置、日志、截图和提交内容未泄露令牌、连接串、密钥及无关个人信息。
  • 命令、文档和 CI 随变更同步,验证记录明确区分自动测试、JS 导出和原生安装验收。
  • 模块审查、适用验收和系统架构合入审查均已完成。

数据库及图片变更按 Schema、迁移、事务和权限链路共同审查。环境与交付职责维护构建、安装和发布记录;技术文档职责按实际版本核对安装、接口和操作说明。业务规则和表结构的修改由对应模块协调,不因交付或文档工作绕过审查。

各节所参考的规范

参考资料用于说明规则来源,不替代项目自身约定。Java 手册按其技术背景理解;华为内部代码规范按《Java 语言编码规范》V1.00 理解;在线文档可能随版本更新,涉及具体 API 时应核对项目锁定版本。

节参考资料
共用规范、分层、异常处理与测试《阿里巴巴 Java 开发手册》终极版 v1.3.0 PDF;项目公开入口(在线内容不默认等同于 v1.3.0 原版)
共用规范、命名与可读性华为内部代码规范(《Java 语言编码规范》V1.00);Google TypeScript Style Guide
排版与静态检查Prettier 配置说明;typescript-eslint
React 与模块组织Airbnb React/JSX;Airbnb JavaScript;Rules of Hooks
Expo 与安全存储Expo SDK 57;SecureStore
接口校验Zod
FastifyServer;Validation and Serialization;TypeScript
安全与日志OWASP 口令存储;OWASP 日志;OWASP REST
数据库PostgreSQL 17 标识符;数值类型;SQL Style Guide;Drizzle 表声明;事务;迁移
测试Vitest;邹欣《构建之法》第 2 章
提交Conventional Commits 1.0.0

九、冲刺目标

本次冲刺为 2026 年 10 月 23 日至 10 月 29 日,共七天。第 1 天是 10 月 23 日,第 7 天是 10 月 29 日,落在作业截止时间之内。

七天完成移动端真实主路径:登录 → 创建账本 → 记一笔消费 → 查看成员余额 → 查看结算预览。复用已有认证、金额分摊和精确结算算法,实现尚未接通的接口及页面。

为验证非零余额,保留最小的手输邀请码加入流程,使用两个通过真实注册接口建立的账号;不直接插入业务数据库冒充 App 加入。消费先打通人均分摊。三种模式的既有金额规则保持不变,其他模式的页面增强不作为本轮完成门槛。

本轮不安排正式冻结、已还登记、结清、归档、图片、扫码和复杂统计图。结算预览仅查询,不能写入正式结算记录或改变 ACTIVE 状态。关于与协议弹窗作为登录入口的辅助功能,由袁湘湘实现。博客不计入工程任务。

十、职责分工与初始任务量

任务点表示相对工作量,不等于工时,也不用来直接比较个人贡献。初始剩余工作量暂定 80 点,由下面 18 项任务组成,第一天核对后作为燃尽图基线。

职责成员本轮负责内容任务点
系统架构饶恩哲全系统设计与关键实现参与、主要前端、PR 审核与合并28
后端一许雅欣成员权限、公共幂等、建账查询、最小邀请加入16
后端二饶慧新增消费、人均分摊服务端重算、消费查询6
后端三叶银珍成员余额、一致快照读取、结算预览8
验收与调整陈林祺主路径验收、问题复现、局部界面修复和复测4
自动化测试李润君主路径 HTTP 集成、金额、权限和重复提交测试6
环境与交付高娅婷环境检查、启动兼容、构建安装验证8
技术文档与弹窗袁湘湘关于/协议/隐私弹窗、安装及主路径操作说明4
合计80

架构、环境、测试、技术文档等已有成果按实际贡献计入 10 月 23 日的成果说明;80 点只统计计划确认时尚待完成的工作,已有成果不重复估点或扣减。Git 作者归属后续单独核对。

十一、任务及完成标准

编号任务负责人点数计划完成完成标准
T01确认主路径接口、数据流与协作基线饶恩哲4第1天(10月23日)接口依赖、错误约定、事务边界与负责人明确,形成任务清单
T02环境检查与启动排障高娅婷4第1天(10月23日)开发成员能启动所需服务,API/数据库连通,有检查脚本和验证记录
T03登录、会话和退出交互饶恩哲6第2天(10月24日)登录使用真实接口,重开在线核验会话,失效会话返回登录,失败保留输入
T04公共权限与完整幂等许雅欣6第2天(10月24日)成员校验可复用;同键同内容重放、异内容冲突;成功结果与业务同事务保存
T05创建账本与列表/详情/成员查询许雅欣6第3天(10月25日)创建者自动入账本并生成邀请,重复创建不重复落库,非成员访问拒绝
T06创建账本与列表/详情页面饶恩哲4第3天(10月25日)页面调用真实接口,创建后可查询,空态和错误状态准确
T07最小邀请预览、加入与前端接入许雅欣,饶恩哲协作4第3天(10月25日)第二个真实账号能手输邀请码加入;过期/非法码拒绝,重复加入不重复写成员
T08关于与协议弹窗袁湘湘2第3天(10月25日)登录页可打开、滚动、关闭弹窗,不新增全屏路由
T09消费新增、查询与分摊事务饶慧6第4天(10月26日)整数分重算人均分摊;消费、分摊、版本、审计与幂等原子提交;重复不多记
T10记账表单与消费展示饶恩哲6第4天(10月26日)能选择付款人/分摊成员并保存,错误保留输入,成功刷新,不自动重试写入
T11余额查询叶银珍4第4天(10月26日)同一快照计算已付、应摊和净额,全员净额和为零,非成员拒绝
T12余额页面饶恩哲4第5天(10月27日)金额和应收/应付与真实记录一致,失败不显示伪造零余额
T13结算预览接口叶银珍4第5天(10月27日)复用已有精确算法,转账守恒、笔数最少,不写正式结算、不冻结账本
T14结算预览页面饶恩哲4第5天(10月27日)展示真实收付款人与金额,退出预览后仍可记账
T15自动化回归李润君6第6天(10月28日)真实 API 和专用数据库跑通主路径;覆盖金额、权限、重复提交与预览只读
T16功能验收与局部修复陈林祺4第6天(10月28日)完成正反用例,提交真实界面缺陷修复,复测通过并记录已知问题
T17构建安装与运行验证高娅婷4第7天(10月29日)候选版完成 Android 安装及主路径验证,记录版本、设备与启动依赖
T18技术文档交付袁湘湘2第7天(10月29日)按文档能安装启动并操作主路径,说明当前限制,步骤与最终版本一致
合计80

每项任务达到标准、完成适用检查并由饶恩哲审核合并后才算完成。开发、测试、工具、弹窗均由实际承担者提交代码。测试和验收从 10 月 23 日持续进行,任务截止日表示最终交付日。

十二、七天安排

天数当日主要任务与分工当日完成门槛
第1天(10月23日)饶恩哲确认范围与接口;许雅欣、饶慧、叶银珍接手模块并开始实现;陈林祺整理用例;李润君准备数据工具;高娅婷排障;袁湘湘开始弹窗T01、T02 完成;已有成果与待办清楚,各职责有可执行任务
第2天(10月24日)饶恩哲接登录会话;许雅欣完成公共能力,饶慧、叶银珍并行实现消费与余额;陈林祺检查账号;李润君补账号和权限;高娅婷验证启动兼容;袁湘湘完善弹窗T03、T04 完成;可真实登录,公共权限与幂等可复用
第3天(10月25日)饶恩哲接建账和最小加入;许雅欣完成建账与邀请,饶慧、叶银珍继续核心接口;陈林祺测试多人加入;高娅婷验证开发客户端;袁湘湘交付弹窗T05~T08 完成;两个账号进入同一真实账本
第4天(10月26日)饶恩哲接记账;饶慧完成消费与分摊,叶银珍完成余额;许雅欣修加入问题;陈林祺测试金额和输入错误;高娅婷检查设备连接;袁湘湘补操作步骤T09~T11 完成;消费可保存且余额接口正确
第5天(10月27日)饶恩哲完成余额与预览页;叶银珍完成预览,许雅欣、饶慧修联调问题;陈林祺跑完整路径;李润君加入预览只读用例;高娅婷准备候选版;袁湘湘补预览说明T12~T14 完成;首次跑通五步主路径
第6天(10月28日)饶恩哲与许雅欣、饶慧、叶银珍修阻塞并审核合并;陈林祺全量复测并完成局部修复;李润君运行自动化回归;高娅婷验证候选版;袁湘湘核对步骤T15、T16 完成;核心回归通过,冻结新增功能
第7天(10月29日)饶恩哲确认最终版本;许雅欣、饶慧、叶银珍复测;陈林祺和李润君提供最终结果;高娅婷完成安装验证;袁湘湘交付运行说明T17、T18 完成;最终版本、运行证据和说明一致

饶恩哲每天参与各部分设计、关键问题处理和 PR 审核合并。接口依赖提前确定,公共能力优先审查,不把联调集中到最后一天。

十三、燃尽图基线

横轴为七天,纵轴为剩余任务点。按上述任务计划完成日,计划剩余点如下,不是实际完成数据:

img

时间初始第1天末(10月23日)第2天末(10月24日)第3天末(10月25日)第4天末(10月26日)第5天末(10月27日)第6天末(10月28日)第7天末(10月29日)
计划剩余点80726044281660

每天站会后记录实际剩余量。未验收任务保留全部点数,不能用“代码写了一半”直接扣一半;必要时先拆成可独立验收的小任务。新增缺陷或范围变化单列估点并记录原因,不回改旧数据,也不将未完任务移出看板来制造燃尽。

十四、主路径验收样例

通过已有真实注册接口准备甲、乙两个账号:甲登录创建账本,乙用邀请码加入;甲支付 120 元,甲乙人均分摊。保存后甲已付 120 元、应摊 60 元、净额 +60 元;乙已付 0 元、应摊 60 元、净额 −60 元。预览应为乙向甲转账 60 元,共一笔。

img

重复提交同一写请求不多记消费;刷新后记录仍在;非法金额、非成员访问与未登录访问应被拒绝;预览后账本保持 ACTIVE,仍可继续新增消费。全流程使用真实 API 和 PostgreSQL,不能以模拟余额替代实现。

环境基线为 Android Development Build、真实 API、数据库与 Metro。JS 导出通过不能视为设备安装通过。代码执行 pnpm check 和适用测试;集成测试显式指定专用 TEST_DATABASE_URL。路由、共享包、依赖或原生配置变化按 AGENTS.md 追加导出、Doctor 与原生重建验证。

十五、AI 技术员

本轮拟引入四类 AI 角色,同一个工具可以承担多个角色。AI 辅助成果由对应人工负责人负责,不计为额外组员,不替代本人提交、审核和验收。

img

AI 角色接收任务输出人工验收负责人及方式
设计与架构 AI主路径拆分、接口依赖、页面状态与异常流程检查设计建议、状态清单、方案差异饶恩哲核对产品范围、模块边界和已有契约,确定是否采纳
编程 AI明确文件范围的接口、组件、测试数据工具或缺陷修复可审查的代码差异、实现说明和验证建议任务负责人逐项读代码、运行检查及真实联调;饶恩哲审核 PR 并合并
测试 AI从规则生成正常/异常用例,补金额、权限、幂等与预览只读测试测试代码、用例和遗漏分析李润君独立核对期望值,使用真实数据库执行;陈林祺从 App 验证交互
文档 AI根据已确认代码和结果整理安装、接口及操作说明文档草稿、缺口清单袁湘湘按步骤实操,饶恩哲核对技术描述与实际范围

团队如何交任务给 AI

人工先建任务,提供目标、相关文件/契约、已存在能力、允许修改范围、依赖和验收标准。先要求 AI 说明理解,再按小任务生成代码或建议,避免一次要求“完成整个项目”。

例如:

在现有消费模块实现新增消费,复用 contracts 和 domain。金额使用 bigint 整数分,服务端重算分摊,业务写入和幂等结果共用 tx,不自动重试写请求。请给出代码差异、依赖及验证方式;同键重放不重复记账、非成员拒绝、两人均分 120 元时各摊 60 元。

人如何验收 AI 成果

  1. 任务负责人核对代码与契约、权限、事务和任务范围,确认可以解释实现。
  2. 运行适用静态检查、测试和真实接口/设备验证,不将 AI 声称测试通过作为证据。
  3. 陈林祺验证用户流程;饶恩哲审核对应 PR,反馈修改后再合并。
  4. 在任务或 PR 中记录 AI 角色、输入任务、采纳/修改内容、人工验证与结果,便于后续说明贡献。

AI 设计、代码、测试期望值和文档均按上述流程核验;本节描述计划中的使用方式,具体贡献以实际记录为准。

...全文

相关推荐

评论
收藏 已收藏
分享
返回顶部