This repository has been archived on 2026-09-13. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BPOS-TMP-REPO/apps/api/src/modules/minute/contract.ts
T
ChaiHaoandClaude Opus 5 a60acb2e02 M6(3/n): minute 与 report —— L8 两个模块补齐
minute(纪要):工作台五要素里唯一的主动动作。
  纪要本身不产生责任,唯一通往责任的路是决议经登记触发起单 —— 登记人即来源。
  正文可续、决议只增;同一决议不重复起单(起单一刻已有一条带来源的流在跑)。

report(汇报):日/周/月/年对任务日志的聚合投影,零手工汇报。
  未提交的草案每次取回都重算 —— 汇报是投影不是账本,提交那刻才固定为事实快照。
  度量八指标落在这里(§4 注:度量是只读投影,不设独立模块):
  自主率 / 纠正率 / 有效自主率 / 打扰率 / 断点率 / DMN 覆盖率 / 单位成本 / 终态分布。
  口径全部挂归侧标签与事件流,零埋点;单位成本的分母只认放行通过。
  周窗口以周一为首日,按 UTC 切分(单组织单时区)。

FactSource 只读 memory 与 task,一行都不另记 —— 五要素同源。

gates: tsc / eslint / depcruise(305 模块)/ api-report / 377 测试 全绿
日报已在真实系统上由 A1 任务日志聚合出来,含治理干预两行

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-27 03:39:10 +08:00

59 lines
2.3 KiB
TypeScript

/**
* module: minute —— 对外类型(编码规范 §10.1;语义出处 OS 2.1 / 3.1)。
*
* 纪要是工作台五要素里**唯一的主动动作**:团队主动维护上传的沉淀(会议纪要等)。
* 它本身不产生责任;责任的产生只有一条路——**决议经登记触发转为工作流的启动**,
* 「登记人即来源」。所以本模块的写面很薄,重头在「决议 → 登记起单」这一跳。
*/
import type { StaffId } from '@contracts';
import type { Minute, MinuteResolution, ResolutionState } from './internal/domain/minute.ts';
export type { Minute, MinuteResolution, ResolutionState };
export class MinuteNotFoundError extends Error {
constructor(readonly minuteId: string) {
super(`纪要不存在:${minuteId}`);
this.name = 'MinuteNotFoundError';
}
}
export class ResolutionAlreadyRegisteredError extends Error {
constructor(
readonly resolutionId: string,
readonly workflowId: string,
) {
super(`决议 ${resolutionId} 已登记起单(工作流 ${workflowId})—— 同一决议不重复起单`);
this.name = 'ResolutionAlreadyRegisteredError';
}
}
export type CreateMinuteInput = {
readonly title: string;
readonly body: string;
readonly authorId: StaffId;
/** 与会/相关人 —— 仅作沉淀标注,不产生责任 */
readonly participants?: readonly StaffId[];
readonly occurredOn: string;
readonly resolutions?: ReadonlyArray<{ text: string; ownerId?: StaffId | undefined }>;
};
export type RegisterInput = {
readonly resolutionId: string;
/** 登记人 —— 凡单必有来源,登记触发的来源就是他 */
readonly byId: StaffId;
readonly processPackageId: string;
/** 按调用接口 schema 填写的输入(表单由 schema 自动渲染) */
readonly data: Record<string, unknown>;
};
export type MinuteService = {
list(limit?: number): Promise<Minute[]>;
get(minuteId: string): Promise<Minute>;
create(input: CreateMinuteInput): Promise<Minute>;
/** 只增不改的编辑:正文可续,决议只增 —— 纪要是沉淀,不是可覆写的文档 */
appendResolution(minuteId: string, text: string, ownerId?: StaffId): Promise<Minute>;
/** 决议 → 登记起单:登记人即来源;同一决议只起一次单 */
register(input: RegisterInput): Promise<{ workflowId: string; resolutionId: string }>;
};