feat: M2 — 写→审(一致性)→裁决→验收(事务);未决冲突禁验收

- 续审 Agent 声明(AgentSpec) + 结构化输出契约(ContinuityReview/Conflict 五类)
- LangGraph 并行审子图(可扩四审) + collect 落 chapter_reviews 留痕 + review SSE(section/conflict)
- 验收-side Repository:章节 accepted 版本晋升 + digest append-only + 审稿留痕/裁决
- API:review(SSE) + reviews 历史 + accept(单原子事务:晋升 version + 终稿 digest + 裁决留痕)
- 冲突 gate:未决裁决拦截(CONFLICT_UNRESOLVED);digest 从终稿提炼(不变量#4)
- 前端:审稿报告页 + 冲突就地标注 + 裁决(采纳/忽略/手改) + 未决禁验收 + 「本次将更新」清单
- M2 E2E:真实 DB + 多档位 mock 网关零 token 走通 写→审→裁决→验收→摘要入库
- 多 agent 协同台账(PROGRESS.md) + 共享记忆(memory/contracts·decisions·gotchas)
This commit is contained in:
Yaojia Wang
2026-06-18 11:38:28 +02:00
parent b523b4fd21
commit 68f194a043
36 changed files with 3881 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
import { notFound } from "next/navigation";
import { ReviewReport } from "@/components/review/ReviewReport";
import { fetchProject, fetchReviews } from "@/lib/api/server";
import { latestReview } from "@/lib/review/history";
interface PageProps {
params: Promise<{ id: string }>;
searchParams: Promise<{ chapter?: string }>;
}
const DEFAULT_CHAPTER_NO = 1;
// 审稿报告页UX §6.4。Server Component 取项目 + 审稿留痕历史(新→旧);
// ReviewReportClient承载 SSE 重审 / 裁决 / 验收交互。
export default async function ReviewPage({ params, searchParams }: PageProps) {
const { id } = await params;
const { chapter } = await searchParams;
const chapterNo = parsePositiveInt(chapter) ?? DEFAULT_CHAPTER_NO;
try {
const project = await fetchProject(id);
const history = await fetchReviews(id, chapterNo);
return (
<ReviewReport
project={project}
chapterNo={chapterNo}
initialReview={latestReview(history.reviews)}
initialDraft=""
/>
);
} catch {
notFound();
}
}
function parsePositiveInt(raw: string | undefined): number | null {
if (!raw) return null;
const n = Number.parseInt(raw, 10);
return Number.isInteger(n) && n > 0 ? n : null;
}