"""天工阁表模型:后台受托任务(无魂籍的功能代理任务)。 设计依据 mandate-and-capability-model.md §7 与 PRD §9.5: - 任务 Agent 是功能代理,没有魂籍、缘契、情态或独立长期身份; - 承载受托任务、有限分解、受控并行与按证据验收; - 后台 Run(runs.kind=background_task)不占前台席位、不构成第二意识。 """ from datetime import datetime from sqlalchemy import DateTime, ForeignKey, String, Text from sqlalchemy.orm import Mapped, mapped_column from app.core.ids import new_id from app.core.time import utc_now from app.db.base import Base class BackstageTask(Base): """受托任务:委托包 + 验收标准 + 结果证据;可分解(parent 链)受控并行。""" __tablename__ = "backstage_tasks" id: Mapped[str] = mapped_column(String(80), primary_key=True, default=lambda: new_id("task")) owner_scope: Mapped[str] = mapped_column(String(80), nullable=False, index=True) # 委托对象人物(可空:纯功能任务无人物语境) character_id: Mapped[str | None] = mapped_column( String(80), ForeignKey("characters.id"), nullable=True, index=True ) # 父任务(分解链:子任务并行执行,全部完成后父任务进入待验收) parent_task_id: Mapped[str | None] = mapped_column( String(80), ForeignKey("backstage_tasks.id"), nullable=True, index=True ) title: Mapped[str] = mapped_column(String(200), nullable=False) # 最小委托包(受托边界:达成目标与停止条件;任务 Agent 不扩使命) brief: Mapped[str] = mapped_column(Text, nullable=False, default="") # 按证据验收:明确的完成判据 acceptance_criteria: Mapped[str] = mapped_column(Text, nullable=False, default="") # pending / running / awaiting_acceptance / accepted / rejected / failed status: Mapped[str] = mapped_column(String(30), nullable=False, default="pending", index=True) # 执行产出(净化摘要 + 证据引用;不构成身份/记忆写入) result_digest: Mapped[str] = mapped_column(Text, nullable=False, default="") evidence_json: Mapped[str] = mapped_column(Text, nullable=False, default="{}") # 关联后台 Run(kind=background_task,不占前台席位) run_id: Mapped[str | None] = mapped_column(String(80), index=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now) completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))