73 lines
3.0 KiB
Python
73 lines
3.0 KiB
Python
"""伏笔登记 / 状态变更端点的请求/响应 schema(C3 扩 / ARCH §6.2, §7.2)。
|
||
|
||
snake_case;前端经 OpenAPI 生成 TS 类型消费。改字段 → 前端必须 `pnpm gen:api`。
|
||
登记是**作者显式动作**(不变量 #3:伏笔入库不经 AI 静默写库),到期扫描是验收后的
|
||
确定性纯函数置位(M3-d),二者都不在审稿/写章流水线里。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from typing import Any
|
||
|
||
from pydantic import BaseModel, Field
|
||
|
||
# 请求字符串字段长度上界(CR-H9:防超长入参 DoS/成本)。代号=短标识;标题=一句话。
|
||
_CODE_MAX = 100
|
||
_TITLE_MAX = 500
|
||
|
||
|
||
class ForeshadowRegisterRequest(BaseModel):
|
||
"""POST /projects/:id/foreshadow:作者显式登记一条伏笔(status 落 OPEN)。"""
|
||
|
||
code: str = Field(
|
||
min_length=1, max_length=_CODE_MAX, description="伏笔代号,`(project_id, code)` 唯一"
|
||
)
|
||
title: str = Field(min_length=1, max_length=_TITLE_MAX, description="伏笔标题/一句话描述")
|
||
planted_at: int | None = Field(default=None, description="埋设章号")
|
||
content: str | None = Field(default=None, description="伏笔正文/线索")
|
||
expected_close_from: int | None = Field(default=None, description="预期回收窗口起始章")
|
||
expected_close_to: int | None = Field(
|
||
default=None, description="预期回收窗口结束章(到期判据用)"
|
||
)
|
||
importance: str | None = Field(default=None, description="重要度(自由文本,看板用)")
|
||
|
||
|
||
class ForeshadowTransitionRequest(BaseModel):
|
||
"""PATCH /projects/:id/foreshadow/:code:状态机转移 和/或 追加一条进展。
|
||
|
||
两字段皆可选:`to_status` 走状态机(非法 → VALIDATION 信封);`progress_entry`
|
||
append-only 追加到 progress JSONB。二者可同时给(先转移、后追加进展)。
|
||
"""
|
||
|
||
to_status: str | None = Field(
|
||
default=None, description="目标状态(OPEN/PARTIAL/CLOSED/OVERDUE)"
|
||
)
|
||
progress_entry: dict[str, Any] | None = Field(
|
||
default=None, description="追加一条进展记录(append-only,不覆盖历史)"
|
||
)
|
||
|
||
|
||
class ForeshadowView(BaseModel):
|
||
"""伏笔账本视图(登记/状态变更/看板共用;snake_case)。形对齐 `ForeshadowLedgerView`。"""
|
||
|
||
code: str
|
||
title: str
|
||
status: str
|
||
planted_at: int | None = None
|
||
content: str | None = None
|
||
expected_close_from: int | None = None
|
||
expected_close_to: int | None = None
|
||
importance: str | None = None
|
||
links: list[dict[str, Any]] = Field(default_factory=list)
|
||
progress: list[dict[str, Any]] = Field(default_factory=list)
|
||
|
||
|
||
class ForeshadowBoardResponse(BaseModel):
|
||
"""GET /projects/:id/foreshadow?status=:伏笔看板(四泳道 + OVERDUE 字段齐)。
|
||
|
||
`status` 缺省返回全部;按 `code` 升序(repo `list_by_status` 已排序)。前端按
|
||
`status` 分四泳道(OPEN/PARTIAL/CLOSED/OVERDUE),用 `expected_close_to` 标逾期。
|
||
"""
|
||
|
||
foreshadow: list[ForeshadowView] = Field(default_factory=list)
|