feat(team): add review activity feed
This commit is contained in:
parent
9de48aae3b
commit
da74902c88
|
|
@ -135,6 +135,7 @@ frontend/
|
||||||
- `frontend/src/features/personal-space/` 是空间层入口:`PersonalSpacePage.tsx` 承接桌面个人工作面与独立移动单手布局,`frontend/src/api/space.ts` 只读聚合 `projects` summary、PMFlow OS `truth-state`、`execution-summary` 并生成 `nextActionQueue` 我的下一步队列、继续推进、待确认、review attention、发布关注、发布后反馈关注、下一轮迭代草稿关注、AI 正在推进、草案箱、最近项目摘要;Space P6 的下一步队列按高风险待确认、发布阻塞/失败证据、handoff consumed 后缺少后续 progress、下一轮 draft、发布后反馈/收入/合规信号排序;Space P7 新增 `review_attention`,只读消费 `truth-state.reviewerRouting`,按高风险待我审、`request_changes / rejected` 后待处理、`reviewer_missing` warning、普通 pending review 排序进入“我的下一步”,点击只跳 `/change-review?projectId=<id>&changeSetId=<id>`、已有 `/team-layer?projectId=<id>`、`/execution-bridge?projectId=<id>` 或 `/release-growth?projectId=<id>`;Space P3 的发布关注优先消费 `truth-state.releases` 的 release validation 投影,没有验证投影时才回落 `execution-summary.releaseGate`;Space P4/P5 的发布后反馈/下一轮草稿关注只读消费 `execution-summary.releaseSignals`;不在 Space 写 Project Memory、PMFlowApproval、ProgressEvent、ReleaseValidationRun、FeedbackIngest、RevenueEvent、ComplianceCheckRun、ChangeSet 状态或发布执行,不虚构 reviewer、审查意见或待审 ChangeSet。`components/SpaceChrome.tsx` 承接空间层左侧栏、顶部条与空间用量组件,并被 `/project-launch` 桌面首次新建壳复用;`frontend/src/pages/PersonalSpacePage.tsx` 仅做薄入口。
|
- `frontend/src/features/personal-space/` 是空间层入口:`PersonalSpacePage.tsx` 承接桌面个人工作面与独立移动单手布局,`frontend/src/api/space.ts` 只读聚合 `projects` summary、PMFlow OS `truth-state`、`execution-summary` 并生成 `nextActionQueue` 我的下一步队列、继续推进、待确认、review attention、发布关注、发布后反馈关注、下一轮迭代草稿关注、AI 正在推进、草案箱、最近项目摘要;Space P6 的下一步队列按高风险待确认、发布阻塞/失败证据、handoff consumed 后缺少后续 progress、下一轮 draft、发布后反馈/收入/合规信号排序;Space P7 新增 `review_attention`,只读消费 `truth-state.reviewerRouting`,按高风险待我审、`request_changes / rejected` 后待处理、`reviewer_missing` warning、普通 pending review 排序进入“我的下一步”,点击只跳 `/change-review?projectId=<id>&changeSetId=<id>`、已有 `/team-layer?projectId=<id>`、`/execution-bridge?projectId=<id>` 或 `/release-growth?projectId=<id>`;Space P3 的发布关注优先消费 `truth-state.releases` 的 release validation 投影,没有验证投影时才回落 `execution-summary.releaseGate`;Space P4/P5 的发布后反馈/下一轮草稿关注只读消费 `execution-summary.releaseSignals`;不在 Space 写 Project Memory、PMFlowApproval、ProgressEvent、ReleaseValidationRun、FeedbackIngest、RevenueEvent、ComplianceCheckRun、ChangeSet 状态或发布执行,不虚构 reviewer、审查意见或待审 ChangeSet。`components/SpaceChrome.tsx` 承接空间层左侧栏、顶部条与空间用量组件,并被 `/project-launch` 桌面首次新建壳复用;`frontend/src/pages/PersonalSpacePage.tsx` 仅做薄入口。
|
||||||
- `frontend/src/features/account-settings/` 是 Account Settings 独立产品域:`AccountSettingsPanel.tsx` 承接 `/me` 桌面设置页、移动端分组列表与 bottom sheet,`frontend/src/api/accountSettings.ts` 定义个人资料、默认语言、AI 回答深度、证据展示偏好和四类通知偏好合同;当前已有账号同步 API fallback、本地 UI 通知消费模型、Release/Growth 偏好 helper、post-release / next change review 偏好 helper、`getAccountReminderConsumption(settings, event)` 提醒强度消费合同,以及 `getReviewDecisionNotificationPreference(settings, event)` review decision 偏好合同;支持 `reminderIntensity=silent|normal|prominent` 与 `evidenceDisplay=compact|expanded`,并覆盖 `review_requested / review_approved / review_changes_requested / review_rejected / high_risk_approval_required`;`releaseGate / failureAlert / pendingConfirmation / executionWriteback` 只影响页面内提醒表达强度和证据展开方式,不代表真实邮件、桌面推送或系统通知中心已接入,也不得隐藏真实业务证据、reviewerRouting、approval 或审计状态,不改 OAuth/JWT/auth core;`frontend/src/features/pmflow-os/pages/AccountPage.tsx` 仅做薄入口并复用既有退出登录 bottom sheet。
|
- `frontend/src/features/account-settings/` 是 Account Settings 独立产品域:`AccountSettingsPanel.tsx` 承接 `/me` 桌面设置页、移动端分组列表与 bottom sheet,`frontend/src/api/accountSettings.ts` 定义个人资料、默认语言、AI 回答深度、证据展示偏好和四类通知偏好合同;当前已有账号同步 API fallback、本地 UI 通知消费模型、Release/Growth 偏好 helper、post-release / next change review 偏好 helper、`getAccountReminderConsumption(settings, event)` 提醒强度消费合同,以及 `getReviewDecisionNotificationPreference(settings, event)` review decision 偏好合同;支持 `reminderIntensity=silent|normal|prominent` 与 `evidenceDisplay=compact|expanded`,并覆盖 `review_requested / review_approved / review_changes_requested / review_rejected / high_risk_approval_required`;`releaseGate / failureAlert / pendingConfirmation / executionWriteback` 只影响页面内提醒表达强度和证据展开方式,不代表真实邮件、桌面推送或系统通知中心已接入,也不得隐藏真实业务证据、reviewerRouting、approval 或审计状态,不改 OAuth/JWT/auth core;`frontend/src/features/pmflow-os/pages/AccountPage.tsx` 仅做薄入口并复用既有退出登录 bottom sheet。
|
||||||
- `frontend/src/features/pmflow-os/` 当前承载新的对话驱动前端产品域:`store.tsx` 提供共享 truth store;真实模式通过 `?projectId=<id>` 调用 `frontend/src/api/pmflowOs.ts` 读取后端 `ProjectTruthState` projection,并调用真实 message、`proposed_items` extraction、ChangeItem `accept/edit/defer`、ChangeSet `commit`、review decision、Execution Handoff create/consume、execution progress writeback、release validation run create、release feedback ingest、单条 iteration recommendation -> ChangeSet draft 与同组 iteration recommendation 批量 -> ChangeSet draft API,成功后 refetch truth-state / execution-summary;显式 `?demo=1` 才启用 `command_idle -> ai_extracting -> extraction_ready -> review_open -> writeback_success` 本地演示状态机,以及本地 `promoteAcceptedToGraph` 等演示动作。`pages/` 下包含 `CommandCenter / StructuredExtraction / ChangeReview / MemoryWritebackResult / WorkGraph / ExecutionBridge / ReleaseGrowth / TeamLayer / ProjectMemory / Account` 主页面;`ChangeReviewPage` 真实模式可请求审查、通过、要求修改或拒绝当前 ChangeSet,展示审查状态、建议 reviewer、审查意见和 high-risk approval gate,但不自动 commit;`TeamLayerPage` 真实模式读取 `state.reviewerRouting` 展示 ready/empty/warning、待审 ChangeSet、来源、风险等级、建议审查人或 fallback role、审查原因、待审 item 数、证据数、审查状态、审查意见和请求/决策时间,动作跳转 `/change-review?projectId=<id>&changeSetId=<id>`;`ExecutionBridgePage` 已支持创建 handoff、运行端领取确认和执行进度回写;`ReleaseGrowthPage` 真实模式展示 `execution-summary.releaseGate`、execution evidence、阻塞原因、下一步动作、`latestValidationRun` 和 `releaseSignals`,可创建 release validation run、摄取发布后 feedback、展示 recommendation quality grouping、从真实 recommendation 单条或同组批量生成下一轮待确认 ChangeSet draft,并消费 Account notification preference 静默强调型提醒,但不隐藏真实证据、审计状态或发布后信号;静态发布/增长原型仅保留在显式 demo 模式;后端只记录 review decision/progress/release gate/release validation/release feedback/recommendation draft 元数据,不执行本机命令、真实发布命令、外部支付、真实推送、自动 Project Memory commit 或正式任务创建;`ProjectMemoryPage` 在真实模式消费后端 `truth_nodes + semantic_facts` 的 `projectMemory` 投影,真实模式下 accepted/edited ChangeItem 只有 commit 成功后才进入 Project Memory。`components/` 下除了 `ProjectStageRail / ThreadComposer / ExtractionRail / ChangeGroupPanel / ObjectGraphSection / ContextPacketPanel / ExecutionTimeline / ReleaseGatePanel / TeamFeedPanel` 之外,新增 `ProjectStructuredLoop / PMFlowOsFrame / AccountControls / FeedbackPrimitives` 等行为组件,用来承接项目指挥台、结构化提取、待确认审查、项目记忆写入结果、项目内面包屑、项目切换器、账号退出登录交互,以及 `PageBanner / InlineNotice / HumanDecisionBar / ConfirmDialog / MobileBottomSheet` 这组契约化提示提醒组件;`components/MobileBottomNav.tsx` 是正式应用壳唯一移动底部导航,固定为 `空间 / 指挥台 / 待确认 / 动态 / 我的`。
|
- `frontend/src/features/pmflow-os/` 当前承载新的对话驱动前端产品域:`store.tsx` 提供共享 truth store;真实模式通过 `?projectId=<id>` 调用 `frontend/src/api/pmflowOs.ts` 读取后端 `ProjectTruthState` projection,并调用真实 message、`proposed_items` extraction、ChangeItem `accept/edit/defer`、ChangeSet `commit`、review decision、Execution Handoff create/consume、execution progress writeback、release validation run create、release feedback ingest、单条 iteration recommendation -> ChangeSet draft 与同组 iteration recommendation 批量 -> ChangeSet draft API,成功后 refetch truth-state / execution-summary;显式 `?demo=1` 才启用 `command_idle -> ai_extracting -> extraction_ready -> review_open -> writeback_success` 本地演示状态机,以及本地 `promoteAcceptedToGraph` 等演示动作。`pages/` 下包含 `CommandCenter / StructuredExtraction / ChangeReview / MemoryWritebackResult / WorkGraph / ExecutionBridge / ReleaseGrowth / TeamLayer / ProjectMemory / Account` 主页面;`ChangeReviewPage` 真实模式可请求审查、通过、要求修改或拒绝当前 ChangeSet,展示审查状态、建议 reviewer、审查意见和 high-risk approval gate,但不自动 commit;`TeamLayerPage` 真实模式读取 `state.reviewerRouting` 展示 ready/empty/warning、待审 ChangeSet、来源、风险等级、建议审查人或 fallback role、审查原因、待审 item 数、证据数、审查状态、审查意见和请求/决策时间,动作跳转 `/change-review?projectId=<id>&changeSetId=<id>`;`ExecutionBridgePage` 已支持创建 handoff、运行端领取确认和执行进度回写;`ReleaseGrowthPage` 真实模式展示 `execution-summary.releaseGate`、execution evidence、阻塞原因、下一步动作、`latestValidationRun` 和 `releaseSignals`,可创建 release validation run、摄取发布后 feedback、展示 recommendation quality grouping、从真实 recommendation 单条或同组批量生成下一轮待确认 ChangeSet draft,并消费 Account notification preference 静默强调型提醒,但不隐藏真实证据、审计状态或发布后信号;静态发布/增长原型仅保留在显式 demo 模式;后端只记录 review decision/progress/release gate/release validation/release feedback/recommendation draft 元数据,不执行本机命令、真实发布命令、外部支付、真实推送、自动 Project Memory commit 或正式任务创建;`ProjectMemoryPage` 在真实模式消费后端 `truth_nodes + semantic_facts` 的 `projectMemory` 投影,真实模式下 accepted/edited ChangeItem 只有 commit 成功后才进入 Project Memory。`components/` 下除了 `ProjectStageRail / ThreadComposer / ExtractionRail / ChangeGroupPanel / ObjectGraphSection / ContextPacketPanel / ExecutionTimeline / ReleaseGatePanel / TeamFeedPanel` 之外,新增 `ProjectStructuredLoop / PMFlowOsFrame / AccountControls / FeedbackPrimitives` 等行为组件,用来承接项目指挥台、结构化提取、待确认审查、项目记忆写入结果、项目内面包屑、项目切换器、账号退出登录交互,以及 `PageBanner / InlineNotice / HumanDecisionBar / ConfirmDialog / MobileBottomSheet` 这组契约化提示提醒组件;`components/MobileBottomNav.tsx` 是正式应用壳唯一移动底部导航,固定为 `空间 / 指挥台 / 待确认 / 动态 / 我的`。
|
||||||
|
- `ProjectTruthState.feed` 现在是 Team Feed 只读动态流,由 `backend/app/services/pmflow_os_projection_service.py` 聚合 review request、review decision、ChangeSet 状态、execution progress 与 release gate 事件;`TeamLayerPage` 复用 `TeamFeedPanel` 展示 `state.feed`,只做摘要、空态和跳转,不写审批、不写 ChangeSet、不写通知,也不在真实模式用 mock 动态补齐。
|
||||||
- 旧登录实现 `frontend/src/components/ui/sign-in.tsx` 与 `frontend/src/components/ui/demo.tsx` 已移除,`frontend/src/components/login/` 是当前唯一登录真源。
|
- 旧登录实现 `frontend/src/components/ui/sign-in.tsx` 与 `frontend/src/components/ui/demo.tsx` 已移除,`frontend/src/components/login/` 是当前唯一登录真源。
|
||||||
|
|
||||||
### 5.1 `frontend/src/components/sstc/` 目录说明(模块化拆分后)
|
### 5.1 `frontend/src/components/sstc/` 目录说明(模块化拆分后)
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,8 @@ class PMFlowOSProjectionService:
|
||||||
releases=releases,
|
releases=releases,
|
||||||
metricSignals=metric_signals,
|
metricSignals=metric_signals,
|
||||||
feed=self._project_feed(
|
feed=self._project_feed(
|
||||||
|
review_projection=review_projection,
|
||||||
|
reviewer_routing=reviewer_routing,
|
||||||
execution_summary=execution_summary,
|
execution_summary=execution_summary,
|
||||||
test_runs=test_runs,
|
test_runs=test_runs,
|
||||||
releases=releases,
|
releases=releases,
|
||||||
|
|
@ -1865,30 +1867,187 @@ class PMFlowOSProjectionService:
|
||||||
def _project_feed(
|
def _project_feed(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
review_projection: dict[str, list[dict[str, Any]]],
|
||||||
|
reviewer_routing: dict[str, Any],
|
||||||
execution_summary: ExecutionSummaryProjection,
|
execution_summary: ExecutionSummaryProjection,
|
||||||
test_runs: list[PMFlowTestRun],
|
test_runs: list[PMFlowTestRun],
|
||||||
releases: list[PMFlowRelease],
|
releases: list[PMFlowRelease],
|
||||||
metric_signals: list[PMFlowMetricSignal],
|
metric_signals: list[PMFlowMetricSignal],
|
||||||
) -> list[PMFlowFeedEvent]:
|
) -> list[PMFlowFeedEvent]:
|
||||||
feed: list[PMFlowFeedEvent] = []
|
feed: list[PMFlowFeedEvent] = []
|
||||||
|
feed.extend(self._review_activity_feed(review_projection=review_projection, reviewer_routing=reviewer_routing))
|
||||||
for event in execution_summary.recentProgressEvents[:5]:
|
for event in execution_summary.recentProgressEvents[:5]:
|
||||||
feed.append(
|
feed.append(
|
||||||
PMFlowFeedEvent(
|
PMFlowFeedEvent(
|
||||||
id=f"progress-{event.get('id')}",
|
id=f"progress-{event.get('id')}",
|
||||||
kind="execution",
|
kind="execution",
|
||||||
title=event.get("event_type") or "执行进展",
|
title=self._progress_event_title(event),
|
||||||
summary=event.get("summary") or event.get("workflow_state") or "执行事件已回写",
|
summary=event.get("summary") or event.get("workflow_state") or "执行事件已回写",
|
||||||
timestamp=str(event.get("occurred_at") or ""),
|
timestamp=str(event.get("occurred_at") or ""),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
release_gate_event = self._release_gate_feed_event(execution_summary.releaseGate)
|
||||||
|
if release_gate_event is not None:
|
||||||
|
feed.append(release_gate_event)
|
||||||
for run in test_runs[:3]:
|
for run in test_runs[:3]:
|
||||||
feed.append(PMFlowFeedEvent(id=f"feed-{run.id}", kind="test", title=run.title, summary=run.summary, timestamp=""))
|
feed.append(PMFlowFeedEvent(id=f"feed-{run.id}", kind="test", title=run.title, summary=run.summary, timestamp=""))
|
||||||
for release in releases[:3]:
|
for release in releases[:3]:
|
||||||
feed.append(PMFlowFeedEvent(id=f"feed-{release.id}", kind="release", title=release.title, summary=release.summary, timestamp=""))
|
feed.append(PMFlowFeedEvent(id=f"feed-{release.id}", kind="release", title=release.title, summary=release.summary, timestamp=""))
|
||||||
for signal in metric_signals[:3]:
|
for signal in metric_signals[:3]:
|
||||||
feed.append(PMFlowFeedEvent(id=f"feed-{signal.id}", kind="growth", title=signal.title, summary=signal.summary, timestamp=""))
|
feed.append(PMFlowFeedEvent(id=f"feed-{signal.id}", kind="growth", title=signal.title, summary=signal.summary, timestamp=""))
|
||||||
|
return sorted(feed, key=lambda item: item.timestamp or "", reverse=True)[:18]
|
||||||
|
|
||||||
|
def _review_activity_feed(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
review_projection: dict[str, list[dict[str, Any]]],
|
||||||
|
reviewer_routing: dict[str, Any],
|
||||||
|
) -> list[PMFlowFeedEvent]:
|
||||||
|
feed: list[PMFlowFeedEvent] = []
|
||||||
|
routing_items = list(reviewer_routing.get("items") or [])
|
||||||
|
change_sets = list(review_projection.get("change_sets") or [])
|
||||||
|
change_items = list(review_projection.get("change_items") or [])
|
||||||
|
evidence = list(review_projection.get("evidence") or [])
|
||||||
|
pending_by_set: dict[str, int] = {}
|
||||||
|
evidence_by_set: dict[str, int] = {}
|
||||||
|
for item in change_items:
|
||||||
|
if item.get("status") == "pending_review":
|
||||||
|
pending_by_set[str(item.get("changeSetId") or "")] = pending_by_set.get(str(item.get("changeSetId") or ""), 0) + 1
|
||||||
|
for row in evidence:
|
||||||
|
change_set_id = str(row.get("changeSetId") or "")
|
||||||
|
evidence_by_set[change_set_id] = evidence_by_set.get(change_set_id, 0) + 1
|
||||||
|
|
||||||
|
for item in routing_items:
|
||||||
|
change_set_id = str(item.get("changeSetId") or "")
|
||||||
|
approval_state = str(item.get("approvalState") or "not_requested")
|
||||||
|
title = str(item.get("changeSetTitle") or "待审 ChangeSet")
|
||||||
|
reviewer = self._reviewer_display(item)
|
||||||
|
if approval_state == "requested":
|
||||||
|
feed.append(
|
||||||
|
PMFlowFeedEvent(
|
||||||
|
id=f"review-request-{change_set_id}",
|
||||||
|
kind="review",
|
||||||
|
title="已请求 ChangeSet 审查",
|
||||||
|
summary=f"{title} 已请求 {reviewer} 审查;{item.get('reviewReason') or '等待 reviewer 给出意见。'}",
|
||||||
|
timestamp=str(item.get("requestedAt") or item.get("updatedAt") or item.get("createdAt") or ""),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif approval_state in {"approved", "changes_requested", "rejected"}:
|
||||||
|
feed.append(
|
||||||
|
PMFlowFeedEvent(
|
||||||
|
id=f"review-decision-{change_set_id}-{approval_state}",
|
||||||
|
kind="review",
|
||||||
|
title=self._review_decision_title(approval_state),
|
||||||
|
summary=f"{title}:{item.get('decisionReason') or self._review_decision_summary(approval_state)}",
|
||||||
|
timestamp=str(item.get("decidedAt") or item.get("updatedAt") or item.get("createdAt") or ""),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
for change_set in change_sets[:10]:
|
||||||
|
change_set_id = str(change_set.get("id") or "")
|
||||||
|
if not change_set_id:
|
||||||
|
continue
|
||||||
|
status = str(change_set.get("rawStatus") or change_set.get("status") or "open")
|
||||||
|
feed.append(
|
||||||
|
PMFlowFeedEvent(
|
||||||
|
id=f"changeset-{change_set_id}-{status}",
|
||||||
|
kind="review",
|
||||||
|
title=self._change_set_status_title(status),
|
||||||
|
summary=self._change_set_status_summary(
|
||||||
|
change_set=change_set,
|
||||||
|
pending_count=pending_by_set.get(change_set_id, 0),
|
||||||
|
evidence_count=evidence_by_set.get(change_set_id, 0),
|
||||||
|
),
|
||||||
|
timestamp=str(change_set.get("committedAt") or change_set.get("createdAt") or ""),
|
||||||
|
)
|
||||||
|
)
|
||||||
return feed
|
return feed
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _reviewer_display(item: dict[str, Any]) -> str:
|
||||||
|
reviewer = item.get("suggestedReviewer")
|
||||||
|
if isinstance(reviewer, dict):
|
||||||
|
display = str(reviewer.get("displayName") or reviewer.get("role") or "").strip()
|
||||||
|
if display:
|
||||||
|
return display
|
||||||
|
return str(item.get("fallbackReviewerRole") or "OWNER")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _review_decision_title(approval_state: str) -> str:
|
||||||
|
return {
|
||||||
|
"approved": "审查已通过",
|
||||||
|
"changes_requested": "审查要求修改",
|
||||||
|
"rejected": "审查已拒绝",
|
||||||
|
}.get(approval_state, "审查决策已记录")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _review_decision_summary(approval_state: str) -> str:
|
||||||
|
return {
|
||||||
|
"approved": "reviewer 已通过,仍需人工决定是否 commit。",
|
||||||
|
"changes_requested": "reviewer 要求修改,不能直接写入 Project Memory。",
|
||||||
|
"rejected": "reviewer 已拒绝,本轮不得写入 Project Memory。",
|
||||||
|
}.get(approval_state, "审查状态已更新。")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _change_set_status_title(status: str) -> str:
|
||||||
|
return {
|
||||||
|
"open": "ChangeSet 已创建",
|
||||||
|
"reviewed": "ChangeSet 已完成审查",
|
||||||
|
"committed": "ChangeSet 已写入项目真相层",
|
||||||
|
"partially_committed": "ChangeSet 已部分写入",
|
||||||
|
}.get(status, "ChangeSet 状态已更新")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _change_set_status_summary(*, change_set: dict[str, Any], pending_count: int, evidence_count: int) -> str:
|
||||||
|
title = str(change_set.get("headline") or change_set.get("summary") or "ChangeSet")
|
||||||
|
status = str(change_set.get("rawStatus") or change_set.get("status") or "open")
|
||||||
|
if status == "open":
|
||||||
|
return f"{title} 进入待确认审查;待审 {pending_count} 项,证据 {evidence_count} 条。"
|
||||||
|
if status == "reviewed":
|
||||||
|
return f"{title} 已完成审查;仍需人工决定是否进入 commit。"
|
||||||
|
if status == "committed":
|
||||||
|
return f"{title} 已写入 Project Memory;动态流仅展示结果,不触发写入。"
|
||||||
|
if status == "partially_committed":
|
||||||
|
return f"{title} 已部分写入 Project Memory;未写入项仍需回到 Change Review。"
|
||||||
|
return f"{title} 状态更新为 {status}。"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _progress_event_title(event: dict[str, Any]) -> str:
|
||||||
|
event_type = str(event.get("event_type") or "")
|
||||||
|
return {
|
||||||
|
"handoff_created": "执行交接已创建",
|
||||||
|
"handoff_consumed": "执行交接已领取",
|
||||||
|
"branch_created": "执行分支已创建",
|
||||||
|
"commit": "执行 commit 已回写",
|
||||||
|
"pr_opened": "PR 已打开",
|
||||||
|
"pr_synced": "PR 状态已同步",
|
||||||
|
"test_passed": "测试通过",
|
||||||
|
"test_failed": "测试失败",
|
||||||
|
"checks_passed": "检查通过",
|
||||||
|
"failed": "执行失败",
|
||||||
|
"blocked": "执行阻塞",
|
||||||
|
"merged": "PR 已合并",
|
||||||
|
"accepted": "执行结果已接受",
|
||||||
|
"manual_progress": "执行进展已记录",
|
||||||
|
}.get(event_type, event_type or "执行进展")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _release_gate_feed_event(release_gate: dict[str, Any]) -> Optional[PMFlowFeedEvent]:
|
||||||
|
status = str((release_gate or {}).get("status") or "empty")
|
||||||
|
if status == "empty":
|
||||||
|
return None
|
||||||
|
return PMFlowFeedEvent(
|
||||||
|
id=f"release-gate-{status}",
|
||||||
|
kind="release",
|
||||||
|
title={
|
||||||
|
"ready": "发布门禁已放行",
|
||||||
|
"blocked": "发布门禁已阻塞",
|
||||||
|
"needs_confirmation": "发布门禁需要确认",
|
||||||
|
}.get(status, "发布门禁已更新"),
|
||||||
|
summary=str((release_gate or {}).get("summary") or (release_gate or {}).get("title") or "发布门禁状态已更新。"),
|
||||||
|
timestamp=str((release_gate or {}).get("updatedAt") or ""),
|
||||||
|
)
|
||||||
|
|
||||||
def _project_goal(self, *, project: Project, truth_nodes: list[TruthNode]) -> str:
|
def _project_goal(self, *, project: Project, truth_nodes: list[TruthNode]) -> str:
|
||||||
charter = next((node for node in truth_nodes if self._node_type(node) == "charter"), None)
|
charter = next((node for node in truth_nodes if self._node_type(node) == "charter"), None)
|
||||||
if charter is not None:
|
if charter is not None:
|
||||||
|
|
|
||||||
|
|
@ -1444,6 +1444,235 @@ async def test_truth_state_reviewer_routing_empty_without_pending_changesets(db_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_truth_state_team_feed_aggregates_review_execution_and_release_events(db_env) -> None:
|
||||||
|
session = db_env
|
||||||
|
user, project = await _seed_user_project(session)
|
||||||
|
reviewer = User(
|
||||||
|
tenant_id=1,
|
||||||
|
username="team-feed-reviewer",
|
||||||
|
email="team-feed-reviewer@example.com",
|
||||||
|
password_hash="hashed",
|
||||||
|
name="审查负责人",
|
||||||
|
role="REVIEWER",
|
||||||
|
assigned_domains=[],
|
||||||
|
workload=0,
|
||||||
|
status="active",
|
||||||
|
is_active=True,
|
||||||
|
)
|
||||||
|
session.add(reviewer)
|
||||||
|
await session.flush()
|
||||||
|
session.add(UserProject(tenant_id=1, user_id=reviewer.id, project_id=project.id))
|
||||||
|
thread = PMFlowThread(
|
||||||
|
tenant_id=1,
|
||||||
|
project_id=project.id,
|
||||||
|
title="团队动态线程",
|
||||||
|
objective="验证 Team Feed 只读聚合",
|
||||||
|
status="active",
|
||||||
|
source="project_launch",
|
||||||
|
)
|
||||||
|
charter = TruthNode(
|
||||||
|
tenant_id=1,
|
||||||
|
node_type="charter",
|
||||||
|
project_id=project.id,
|
||||||
|
created_by=user.id,
|
||||||
|
title="团队动态宪章",
|
||||||
|
content={"business_goal": "聚合审查、执行和发布门禁事件"},
|
||||||
|
version=1,
|
||||||
|
status="aligned",
|
||||||
|
)
|
||||||
|
session.add_all([thread, charter])
|
||||||
|
await session.flush()
|
||||||
|
message = PMFlowThreadMessage(
|
||||||
|
tenant_id=1,
|
||||||
|
thread_id=thread.id,
|
||||||
|
project_id=project.id,
|
||||||
|
role="user",
|
||||||
|
content="生成 Team Feed 动态流。",
|
||||||
|
source="web",
|
||||||
|
attachments=[],
|
||||||
|
message_metadata={},
|
||||||
|
status="sent",
|
||||||
|
created_at=datetime(2026, 4, 26, 9, 55, 0),
|
||||||
|
)
|
||||||
|
task = Task(
|
||||||
|
tenant_id=1,
|
||||||
|
truth_node_id=charter.id,
|
||||||
|
project_id=project.id,
|
||||||
|
assignee_id=user.id,
|
||||||
|
ai_recommended_assignees=None,
|
||||||
|
ai_breakdown_payload={"acceptance_criteria": ["Team Feed 只读展示执行进展"]},
|
||||||
|
manual_overrides=None,
|
||||||
|
title="回写 Team Feed 执行事件",
|
||||||
|
description="执行进展进入团队动态",
|
||||||
|
required_skill_tag_ids=[],
|
||||||
|
status="in_progress",
|
||||||
|
priority="high",
|
||||||
|
)
|
||||||
|
repo = RepoBinding(
|
||||||
|
tenant_id=1,
|
||||||
|
project_id=project.id,
|
||||||
|
provider="github",
|
||||||
|
owner="pmflow",
|
||||||
|
repo_name="team-feed",
|
||||||
|
default_branch="main",
|
||||||
|
status="active",
|
||||||
|
)
|
||||||
|
session.add_all([message, task, repo])
|
||||||
|
await session.flush()
|
||||||
|
requested_set = PMFlowChangeSet(
|
||||||
|
tenant_id=1,
|
||||||
|
project_id=project.id,
|
||||||
|
thread_id=thread.id,
|
||||||
|
source_message_id=message.id,
|
||||||
|
status="open",
|
||||||
|
summary="待审变更已请求 reviewer",
|
||||||
|
headline="请求审查的 ChangeSet",
|
||||||
|
extraction_scope="latest_message",
|
||||||
|
routing_meta={
|
||||||
|
"reviewDecision": {
|
||||||
|
"action": "request_review",
|
||||||
|
"approvalState": "requested",
|
||||||
|
"requestedAt": "2026-04-26T10:00:00",
|
||||||
|
"reviewerId": str(reviewer.id),
|
||||||
|
"decisionReason": "请复核高风险变更。",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created_by=user.id,
|
||||||
|
created_at=datetime(2026, 4, 26, 9, 58, 0),
|
||||||
|
)
|
||||||
|
approved_set = PMFlowChangeSet(
|
||||||
|
tenant_id=1,
|
||||||
|
project_id=project.id,
|
||||||
|
thread_id=thread.id,
|
||||||
|
source_message_id=message.id,
|
||||||
|
status="reviewed",
|
||||||
|
summary="审查已通过但未自动提交",
|
||||||
|
headline="已通过审查的 ChangeSet",
|
||||||
|
extraction_scope="latest_message",
|
||||||
|
routing_meta={
|
||||||
|
"reviewDecision": {
|
||||||
|
"action": "approve",
|
||||||
|
"approvalState": "approved",
|
||||||
|
"decidedAt": "2026-04-26T10:20:00",
|
||||||
|
"reviewerId": str(reviewer.id),
|
||||||
|
"decisionReason": "reviewer 通过,不自动 commit。",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created_by=user.id,
|
||||||
|
reviewed_at=datetime(2026, 4, 26, 10, 20, 0),
|
||||||
|
created_at=datetime(2026, 4, 26, 10, 5, 0),
|
||||||
|
)
|
||||||
|
session.add_all([requested_set, approved_set])
|
||||||
|
await session.flush()
|
||||||
|
requested_item = PMFlowChangeItem(
|
||||||
|
tenant_id=1,
|
||||||
|
change_set_id=requested_set.id,
|
||||||
|
project_id=project.id,
|
||||||
|
group="risk",
|
||||||
|
object_type="Risk",
|
||||||
|
object_id=None,
|
||||||
|
title="新增风险:审查动态",
|
||||||
|
summary="用于 Team Feed 的 review request。",
|
||||||
|
diff="新增风险。",
|
||||||
|
payload={},
|
||||||
|
confidence=0.9,
|
||||||
|
risk_level="high",
|
||||||
|
status="pending_review",
|
||||||
|
)
|
||||||
|
approved_item = PMFlowChangeItem(
|
||||||
|
tenant_id=1,
|
||||||
|
change_set_id=approved_set.id,
|
||||||
|
project_id=project.id,
|
||||||
|
group="field_update",
|
||||||
|
object_type="Task",
|
||||||
|
object_id=None,
|
||||||
|
title="更新任务:审查通过",
|
||||||
|
summary="用于 Team Feed 的 review decision。",
|
||||||
|
diff="更新任务。",
|
||||||
|
payload={},
|
||||||
|
confidence=0.86,
|
||||||
|
risk_level="medium",
|
||||||
|
status="accepted",
|
||||||
|
reviewed_at=datetime(2026, 4, 26, 10, 20, 0),
|
||||||
|
)
|
||||||
|
session.add_all([requested_item, approved_item])
|
||||||
|
await session.flush()
|
||||||
|
session.add_all(
|
||||||
|
[
|
||||||
|
PMFlowEvidenceLink(
|
||||||
|
tenant_id=1,
|
||||||
|
project_id=project.id,
|
||||||
|
change_set_id=requested_set.id,
|
||||||
|
change_item_id=requested_item.id,
|
||||||
|
source_type="thread_message",
|
||||||
|
source_id=str(message.id),
|
||||||
|
title="审查请求证据",
|
||||||
|
excerpt="高风险变更需要审查。",
|
||||||
|
display_label="Thread",
|
||||||
|
evidence_metadata={},
|
||||||
|
),
|
||||||
|
PMFlowEvidenceLink(
|
||||||
|
tenant_id=1,
|
||||||
|
project_id=project.id,
|
||||||
|
change_set_id=approved_set.id,
|
||||||
|
change_item_id=approved_item.id,
|
||||||
|
source_type="thread_message",
|
||||||
|
source_id=str(message.id),
|
||||||
|
title="审查决策证据",
|
||||||
|
excerpt="reviewer 已通过。",
|
||||||
|
display_label="Thread",
|
||||||
|
evidence_metadata={},
|
||||||
|
),
|
||||||
|
PMFlowApproval(
|
||||||
|
tenant_id=1,
|
||||||
|
project_id=project.id,
|
||||||
|
change_set_id=approved_set.id,
|
||||||
|
change_item_id=approved_item.id,
|
||||||
|
actor_user_id=reviewer.id,
|
||||||
|
action="approve",
|
||||||
|
decision="approved",
|
||||||
|
before_status="pending_review",
|
||||||
|
after_status="accepted",
|
||||||
|
before_payload={},
|
||||||
|
after_payload={"approvalState": "approved"},
|
||||||
|
reason="reviewer 通过,不自动 commit。",
|
||||||
|
created_at=datetime(2026, 4, 26, 10, 20, 0),
|
||||||
|
),
|
||||||
|
ProgressEvent(
|
||||||
|
tenant_id=1,
|
||||||
|
task_id=task.id,
|
||||||
|
project_id=project.id,
|
||||||
|
user_id=user.id,
|
||||||
|
repo_binding_id=repo.id,
|
||||||
|
event_type="test_failed",
|
||||||
|
source="codex",
|
||||||
|
derived_task_status="failed",
|
||||||
|
summary="Team Feed 单测失败,发布门禁阻塞。",
|
||||||
|
payload={"test_summary": "Team Feed 单测失败", "pr_number": 42},
|
||||||
|
occurred_at=datetime(2026, 4, 26, 11, 0, 0),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
await session.commit()
|
||||||
|
app = _build_app(session, SimpleNamespace(id=user.id, tenant_id=1, role="MEMBER"))
|
||||||
|
|
||||||
|
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||||
|
response = await client.get(f"/pmflow-os/projects/{project.id}/truth-state")
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
feed = response.json()["data"]["feed"]
|
||||||
|
titles = [item["title"] for item in feed]
|
||||||
|
assert "已请求 ChangeSet 审查" in titles
|
||||||
|
assert "审查已通过" in titles
|
||||||
|
assert "ChangeSet 已完成审查" in titles
|
||||||
|
assert "测试失败" in titles
|
||||||
|
assert "发布门禁已阻塞" in titles
|
||||||
|
assert any("请求审查的 ChangeSet" in item["summary"] and "证据 1 条" in item["summary"] for item in feed)
|
||||||
|
assert any("reviewer 通过,不自动 commit" in item["summary"] for item in feed)
|
||||||
|
assert titles.index("发布门禁已阻塞") < titles.index("已请求 ChangeSet 审查")
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_execution_progress_writeback_rejects_repo_outside_project(db_env) -> None:
|
async def test_execution_progress_writeback_rejects_repo_outside_project(db_env) -> None:
|
||||||
session = db_env
|
session = db_env
|
||||||
|
|
|
||||||
|
|
@ -87,10 +87,10 @@
|
||||||
4. `ChangeReview` 的接受、修改、暂缓还没有写入正式对象、审批记录和证据链。
|
4. `ChangeReview` 的接受、修改、暂缓还没有写入正式对象、审批记录和证据链。
|
||||||
5. `ExecutionBridge` 已接入真实 execution-summary/dev-sync、execution handoff、运行端领取和 progress writeback;当前缺口不再是执行桥读写合同,而是执行质量、审查责任和个人队列的产品化。
|
5. `ExecutionBridge` 已接入真实 execution-summary/dev-sync、execution handoff、运行端领取和 progress writeback;当前缺口不再是执行桥读写合同,而是执行质量、审查责任和个人队列的产品化。
|
||||||
6. `ReleaseGrowth` 已接入 execution evidence gate、release validation run、feedback ingest 和 recommendation -> ChangeSet draft 回流;revenue、ROI、compliance 还没有串成完整发布后反馈循环。
|
6. `ReleaseGrowth` 已接入 execution evidence gate、release validation run、feedback ingest 和 recommendation -> ChangeSet draft 回流;revenue、ROI、compliance 还没有串成完整发布后反馈循环。
|
||||||
7. `TeamLayer` 已接入 reviewer routing 与 review decision 状态展示;Role Inbox、Decision Desk、Team Feed 仍缺完整真实数据模型。
|
7. `TeamLayer` 已接入 reviewer routing、review decision 状态展示与 Team Feed 只读动态流;Role Inbox、Decision Desk 仍缺完整真实数据模型。
|
||||||
5. `ExecutionBridge` 页面还没有消费 dev-sync / GitHub / PromptPackage 真实接口。
|
5. `ExecutionBridge` 页面还没有消费 dev-sync / GitHub / PromptPackage 真实接口。
|
||||||
6. `ReleaseGrowth` 已接入 execution evidence gate、release validation run 与 feedback ingest;revenue、ROI、compliance 还没有串成完整发布后反馈循环。
|
6. `ReleaseGrowth` 已接入 execution evidence gate、release validation run 与 feedback ingest;revenue、ROI、compliance 还没有串成完整发布后反馈循环。
|
||||||
7. `TeamLayer` 已接入 reviewer routing / review decision 读模型,能展示待审 ChangeSet、建议审查人、审查原因、风险类型、缺角色 warning、审查状态和审查意见;Role Inbox、Decision Desk、Team Feed 仍缺完整真实数据模型。
|
7. `TeamLayer` 已接入 reviewer routing / review decision 读模型与 Team Feed 只读动态流,能展示待审 ChangeSet、建议审查人、审查原因、风险类型、缺角色 warning、审查状态、审查意见,以及 review / execution / release gate 聚合动态;Role Inbox、Decision Desk 仍缺完整真实数据模型。
|
||||||
|
|
||||||
## 2. 下一步推进方向
|
## 2. 下一步推进方向
|
||||||
|
|
||||||
|
|
@ -825,6 +825,41 @@ P8 可以三条 lane 并行,但共享高冲突文件必须由 Main Flow 或 Sh
|
||||||
|
|
||||||
## 8. 进度台账
|
## 8. 进度台账
|
||||||
|
|
||||||
|
### 2026-04-26 / team-feed-p1-review-activity-stream / implemented
|
||||||
|
|
||||||
|
完成内容:
|
||||||
|
|
||||||
|
- `ProjectTruthState.feed` 从静态/局部 feed 扩展为 Team Feed 只读动态流,聚合 review request、review decision、ChangeSet 状态、execution progress 和 release gate 事件。
|
||||||
|
- 后端只读消费既有 `PMFlowChangeSet / PMFlowChangeItem / PMFlowApproval / PMFlowEvidenceLink / ProgressEvent / releaseGate` 投影,不新增表、不新增 route、不写审批、不写 ChangeSet、不写通知。
|
||||||
|
- `TeamLayerPage` 复用 `TeamFeedPanel` 展示真实 `state.feed`;feed 为空时明确显示无真实动态,不使用 mock 动态冒充团队事件。
|
||||||
|
- `TeamFeedPanel` 增加真实时间格式化和空态,保留角色收件箱/决策台为摘要展示,不塞入业务操作。
|
||||||
|
|
||||||
|
涉及文件:
|
||||||
|
|
||||||
|
- `backend/app/services/pmflow_os_projection_service.py`
|
||||||
|
- `backend/tests/test_pmflow_os_projection_api.py`
|
||||||
|
- `frontend/src/features/pmflow-os/components/TeamFeedPanel.tsx`
|
||||||
|
- `frontend/src/features/pmflow-os/pages/TeamLayerPage.tsx`
|
||||||
|
- `frontend/src/features/pmflow-os/store.api.test.tsx`
|
||||||
|
- `docs/PMFLOW_PRODUCT_DELIVERY_STANDARD.md`
|
||||||
|
- `docs/architecture/CODE_REFERENCE_INDEX.md`
|
||||||
|
- `docs/architecture/ARCHITECTURE_INVENTORY.md`
|
||||||
|
- `CLAUDE.md`
|
||||||
|
|
||||||
|
验证:
|
||||||
|
|
||||||
|
- `PYTHONPATH=backend /opt/homebrew/bin/python3.11 -m py_compile backend/app/services/pmflow_os_projection_service.py backend/app/schemas/pmflow_os.py` 通过。
|
||||||
|
- `PYTHONPATH=backend /opt/homebrew/bin/python3.11 -m pytest backend/tests/test_pmflow_os_projection_api.py -q` 通过:`24 passed`;仍有既有 `backend/app/schemas/recipe.py` Pydantic V2 class-based config deprecation warning。
|
||||||
|
- `cd frontend && npm run test -- src/features/pmflow-os` 通过:`13 passed`;仍有既有 React Router v7 future flag warning。
|
||||||
|
- `cd frontend && npm run typecheck` 通过。
|
||||||
|
- `cd frontend && npm run build` 通过;Vite 仍提示既有 manual chunk circular warning(`ai-steward / sstc / charts / governance` chunk 环)。
|
||||||
|
- `docker compose restart backend` 已执行,`docker compose ps backend` 确认 `pmflow-backend` 恢复 `healthy`。
|
||||||
|
|
||||||
|
未完成或风险:
|
||||||
|
|
||||||
|
- 本轮只做 Team Feed 只读动态流,不新增战略页面,不改 router/nav,不写审批/ChangeSet/通知。
|
||||||
|
- Role Inbox 与 Decision Desk 仍是 TeamLayer 摘要/占位表达,完整真实收件箱与决策台模型不在本 Packet。
|
||||||
|
|
||||||
### 2026-04-26 / big-module-integration-p8 / done
|
### 2026-04-26 / big-module-integration-p8 / done
|
||||||
|
|
||||||
完成内容:
|
完成内容:
|
||||||
|
|
@ -1047,7 +1082,7 @@ P8 可以三条 lane 并行,但共享高冲突文件必须由 Main Flow 或 Sh
|
||||||
未完成或风险:
|
未完成或风险:
|
||||||
|
|
||||||
- 该历史记录对应 Team Review P1,当时只是 reviewer routing 读模型与 TeamLayer 展示;Main Flow P8 之后已接入 review decision / PMFlowApproval 审计,但仍不代表正式 reviewer assignment、权限审批流、通知或自动审查任务已接入。
|
- 该历史记录对应 Team Review P1,当时只是 reviewer routing 读模型与 TeamLayer 展示;Main Flow P8 之后已接入 review decision / PMFlowApproval 审计,但仍不代表正式 reviewer assignment、权限审批流、通知或自动审查任务已接入。
|
||||||
- Role Inbox、Decision Desk、Team Feed 的完整真实数据模型仍是后续 Team lane 工作。
|
- Team Feed P1 已接 review / execution / release gate 只读动态流;Role Inbox、Decision Desk 的完整真实数据模型仍是后续 Team lane 工作。
|
||||||
|
|
||||||
### 2026-04-26 / shell-p7-rebaseline-next-plan / implemented
|
### 2026-04-26 / shell-p7-rebaseline-next-plan / implemented
|
||||||
|
|
||||||
|
|
@ -1129,7 +1164,7 @@ P8 可以三条 lane 并行,但共享高冲突文件必须由 Main Flow 或 Sh
|
||||||
未完成或风险:
|
未完成或风险:
|
||||||
|
|
||||||
- 该历史记录对应 Team Review P1,当时只是 reviewer routing 读模型与 TeamLayer 展示;Main Flow P8 之后已接入 review decision / PMFlowApproval 审计,但仍不代表正式 reviewer assignment、权限审批流、通知或自动审查任务已接入。
|
- 该历史记录对应 Team Review P1,当时只是 reviewer routing 读模型与 TeamLayer 展示;Main Flow P8 之后已接入 review decision / PMFlowApproval 审计,但仍不代表正式 reviewer assignment、权限审批流、通知或自动审查任务已接入。
|
||||||
- Role Inbox、Decision Desk、Team Feed 的完整真实数据模型仍是后续 Team lane 工作。
|
- Team Feed P1 已接 review / execution / release gate 只读动态流;Role Inbox、Decision Desk 的完整真实数据模型仍是后续 Team lane 工作。
|
||||||
|
|
||||||
### 2026-04-26 / big-module-integration-p6 / done
|
### 2026-04-26 / big-module-integration-p6 / done
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -196,9 +196,9 @@
|
||||||
- 前端主包治理已切到“同步首屏最小集 + route/page-section lazy”模式:`frontend/src/router/index.tsx` 保留 `LoginPage / Layout` 这组同步入口,其余后台重页面通过 `React.lazy + Suspense` 懒加载;统一 fallback 在 `frontend/src/components/layout/LazyBoundary.tsx`。P0 公共壳冻结后,大模块 route 归属为:`/space` 归 Space lane,`/project-launch` 是启动层入口,`/pmflow-os` 与 `/command-center / /change-review / /execution-bridge / /release-growth` 归 Main Flow lane,`/me` 归 Account Settings lane,`/settings` 当前仅为 reserved route、尚未实现,新增必须由 Shell / Integration owner 串行处理。`frontend/src/features/personal-space/` 作为空间层入口,通过 `/space` 提供可直接打开的本地预览入口,承载继续推进、待我确认、AI 正在推进、暂存想法、草案箱与新建项目入口。`frontend/src/features/project-launch/` 作为首次进入页 / 新项目启动台产品域,通过 `/project-launch` 提供可直接打开的入口;Phase B 后默认调用真实 `pmflow-launch` draft/confirm API,创建成功态主动作跳转后端返回的 `/pmflow-os?projectId=<id>`,只有显式 `?demo=1` 或 `?dataSource=demo` 才启用本地 mock 状态机。`frontend/src/features/account-settings/` 作为 Account Settings 产品域,通过 `/me` 提供个人资料、默认语言、AI 回答深度、证据展示偏好、待确认/执行回写/发布门禁/失败提醒通知偏好和账户操作入口;该域通过 `frontend/src/api/accountSettings.ts` 建立前端合同,有 token 时优先调用已挂入 `backend/app/api/router.py` 的 `backend/app/api/account_settings_api/` `GET /account-settings/me` / `PUT /account-settings/me` 同步当前账号偏好,后端不可用时明确回落本机暂存,不修改 OAuth/JWT/auth core。`frontend/src/features/pmflow-os/` 作为新产品域,通过 `PMFlowOsProvider` 在应用根部挂载共享 truth store,并提供 `CommandCenter / ChangeReview / WorkGraph / ExecutionBridge / ReleaseGrowth / TeamLayer / ProjectMemory / Account` 主入口;当前 PMFlow OS 页面已切到专属轻壳,桌面端默认隐藏旧 TopBar,并由 `frontend/src/features/pmflow-os/components/PMFlowOsFrame.tsx` 统一承接“左侧稳定导航 + 顶部上下文条 + 中央视图 + 右侧 AI 副驾”的全局骨架,同时承接项目内 `个人空间 / 当前项目名` 面包屑和项目切换器;账号退出登录由 `frontend/src/features/pmflow-os/components/AccountControls.tsx` 统一承接桌面头像下拉、退出确认与移动端 bottom sheet,`frontend/src/features/pmflow-os/pages/AccountPage.tsx` 提供 `/me` 入口并委托 Account Settings 域渲染设置页;正式应用壳移动端底部导航统一由 `frontend/src/features/pmflow-os/components/MobileBottomNav.tsx` 承接,固定为 `空间 / 指挥台 / 待确认 / 动态 / 我的`,其中 `动态` 当前仍是 `/command-center` 占位。`/command-center` 额外提供免登录产品预览壳,`/pmflow-os` 是真实项目上下文 alias。主视觉按 `#2463EB + 白色` 的 Linear-like 高密度原型展开。`UsersPage` 把创建/删除/重置/导入/批量分配对话框拆为按需 chunk,`UserSkillsPage` 与 `WorkloadDetailPage` 的图表也分别拆到了 `frontend/src/pages/user-skills/components/UserSkillsRadarPanel.tsx` 与 `frontend/src/pages/workload-detail/components/WorkloadTrendChart.tsx`。
|
- 前端主包治理已切到“同步首屏最小集 + route/page-section lazy”模式:`frontend/src/router/index.tsx` 保留 `LoginPage / Layout` 这组同步入口,其余后台重页面通过 `React.lazy + Suspense` 懒加载;统一 fallback 在 `frontend/src/components/layout/LazyBoundary.tsx`。P0 公共壳冻结后,大模块 route 归属为:`/space` 归 Space lane,`/project-launch` 是启动层入口,`/pmflow-os` 与 `/command-center / /change-review / /execution-bridge / /release-growth` 归 Main Flow lane,`/me` 归 Account Settings lane,`/settings` 当前仅为 reserved route、尚未实现,新增必须由 Shell / Integration owner 串行处理。`frontend/src/features/personal-space/` 作为空间层入口,通过 `/space` 提供可直接打开的本地预览入口,承载继续推进、待我确认、AI 正在推进、暂存想法、草案箱与新建项目入口。`frontend/src/features/project-launch/` 作为首次进入页 / 新项目启动台产品域,通过 `/project-launch` 提供可直接打开的入口;Phase B 后默认调用真实 `pmflow-launch` draft/confirm API,创建成功态主动作跳转后端返回的 `/pmflow-os?projectId=<id>`,只有显式 `?demo=1` 或 `?dataSource=demo` 才启用本地 mock 状态机。`frontend/src/features/account-settings/` 作为 Account Settings 产品域,通过 `/me` 提供个人资料、默认语言、AI 回答深度、证据展示偏好、待确认/执行回写/发布门禁/失败提醒通知偏好和账户操作入口;该域通过 `frontend/src/api/accountSettings.ts` 建立前端合同,有 token 时优先调用已挂入 `backend/app/api/router.py` 的 `backend/app/api/account_settings_api/` `GET /account-settings/me` / `PUT /account-settings/me` 同步当前账号偏好,后端不可用时明确回落本机暂存,不修改 OAuth/JWT/auth core。`frontend/src/features/pmflow-os/` 作为新产品域,通过 `PMFlowOsProvider` 在应用根部挂载共享 truth store,并提供 `CommandCenter / ChangeReview / WorkGraph / ExecutionBridge / ReleaseGrowth / TeamLayer / ProjectMemory / Account` 主入口;当前 PMFlow OS 页面已切到专属轻壳,桌面端默认隐藏旧 TopBar,并由 `frontend/src/features/pmflow-os/components/PMFlowOsFrame.tsx` 统一承接“左侧稳定导航 + 顶部上下文条 + 中央视图 + 右侧 AI 副驾”的全局骨架,同时承接项目内 `个人空间 / 当前项目名` 面包屑和项目切换器;账号退出登录由 `frontend/src/features/pmflow-os/components/AccountControls.tsx` 统一承接桌面头像下拉、退出确认与移动端 bottom sheet,`frontend/src/features/pmflow-os/pages/AccountPage.tsx` 提供 `/me` 入口并委托 Account Settings 域渲染设置页;正式应用壳移动端底部导航统一由 `frontend/src/features/pmflow-os/components/MobileBottomNav.tsx` 承接,固定为 `空间 / 指挥台 / 待确认 / 动态 / 我的`,其中 `动态` 当前仍是 `/command-center` 占位。`/command-center` 额外提供免登录产品预览壳,`/pmflow-os` 是真实项目上下文 alias。主视觉按 `#2463EB + 白色` 的 Linear-like 高密度原型展开。`UsersPage` 把创建/删除/重置/导入/批量分配对话框拆为按需 chunk,`UserSkillsPage` 与 `WorkloadDetailPage` 的图表也分别拆到了 `frontend/src/pages/user-skills/components/UserSkillsRadarPanel.tsx` 与 `frontend/src/pages/workload-detail/components/WorkloadTrendChart.tsx`。
|
||||||
- PMFlow P8 Review Decision Loop 已由 `big-module-integration-p8` 收口:Main Flow `truth-state.reviewerRouting` 与 `POST /pmflow-os/change-sets/{change_set_id}/review-decisions` 是 reviewer decision / approval audit 真源;Space 只读消费为 `/space` 的 `review_attention` 下一步队列;Account 只提供 `getReviewDecisionNotificationPreference` 页面内提醒偏好;P8 未新增 route/nav,未接真实通知中心,不自动 assign reviewer 或 commit ChangeSet。
|
- PMFlow P8 Review Decision Loop 已由 `big-module-integration-p8` 收口:Main Flow `truth-state.reviewerRouting` 与 `POST /pmflow-os/change-sets/{change_set_id}/review-decisions` 是 reviewer decision / approval audit 真源;Space 只读消费为 `/space` 的 `review_attention` 下一步队列;Account 只提供 `getReviewDecisionNotificationPreference` 页面内提醒偏好;P8 未新增 route/nav,未接真实通知中心,不自动 assign reviewer 或 commit ChangeSet。
|
||||||
- `frontend/src/features/personal-space/PersonalSpacePage.tsx` 是空间首页视图层,`frontend/src/api/space.ts` 是空间工作面只读聚合 API:从 `projects` summary、PMFlow OS `truth-state` 与 `execution-summary` 生成 `nextActionQueue` 我的下一步队列、继续推进、待确认、发布关注、发布后反馈关注、下一轮迭代草稿关注、执行中 / AI 正在推进、暂存想法、草案箱、最近项目摘要;Space P6 的 `nextActionQueue` 按高风险 ChangeSet 待确认、release blocked / failed evidence、handoff consumed 但无后续 progress、iteration draft 待确认、feedback/revenue/compliance 信号待处理排序,并只提供 `/change-review`、`/execution-bridge`、`/release-growth` 跳转。Space P3 的 `releaseAttention` 优先消费 `truth-state.releases` 中由 release validation run 投影出的 release 状态与检查项,把“发布验证阻塞 / 发布验证待确认”显示到 `/space`,没有发布验证投影时才回落到 `execution-summary.releaseGate` 的发布候选或发布门禁阻塞;Space P4/P5 的 `feedbackAttention` 只读消费 `execution-summary.releaseSignals`,把发布后 feedback、revenue、ROI、compliance、iteration recommendation 与已生成的下一轮 ChangeSet draft 关注项显示到 `/space`。发布验证、发布后信号或下一轮 draft 缺失时显示明确空态,不虚构验证、反馈、收入、ROI、合规、建议或 ChangeSet draft 结果。项目主动作进入 `/pmflow-os?projectId=<id>`,待确认项进入 `/change-review?projectId=<id>&changeSetId=<id>`,发布关注和发布后反馈关注项进入 `/release-growth?projectId=<id>`,下一轮 draft 关注项进入 `/change-review?projectId=<id>&changeSetId=<id>`,执行中项进入 `/execution-bridge?projectId=<id>`;暂存想法后端只读聚合尚未接入时只显示 empty/warning,不使用 mock 数据冒充真实内容;移动端为空间首页独立 App 布局,不直接压缩桌面卡片,并保留最近项目区块;`frontend/src/pages/PersonalSpacePage.tsx` 是薄入口。该域只表达个人空间和主流程导航,不做团队空间强切换、企业组织管理、Project Memory 写入、ChangeSet 状态写入、ProgressEvent 写入、ReleaseValidationRun 写入、FeedbackIngest 写入或发布执行。
|
- `frontend/src/features/personal-space/PersonalSpacePage.tsx` 是空间首页视图层,`frontend/src/api/space.ts` 是空间工作面只读聚合 API:从 `projects` summary、PMFlow OS `truth-state` 与 `execution-summary` 生成 `nextActionQueue` 我的下一步队列、继续推进、待确认、发布关注、发布后反馈关注、下一轮迭代草稿关注、执行中 / AI 正在推进、暂存想法、草案箱、最近项目摘要;Space P6 的 `nextActionQueue` 按高风险 ChangeSet 待确认、release blocked / failed evidence、handoff consumed 但无后续 progress、iteration draft 待确认、feedback/revenue/compliance 信号待处理排序,并只提供 `/change-review`、`/execution-bridge`、`/release-growth` 跳转。Space P3 的 `releaseAttention` 优先消费 `truth-state.releases` 中由 release validation run 投影出的 release 状态与检查项,把“发布验证阻塞 / 发布验证待确认”显示到 `/space`,没有发布验证投影时才回落到 `execution-summary.releaseGate` 的发布候选或发布门禁阻塞;Space P4/P5 的 `feedbackAttention` 只读消费 `execution-summary.releaseSignals`,把发布后 feedback、revenue、ROI、compliance、iteration recommendation 与已生成的下一轮 ChangeSet draft 关注项显示到 `/space`。发布验证、发布后信号或下一轮 draft 缺失时显示明确空态,不虚构验证、反馈、收入、ROI、合规、建议或 ChangeSet draft 结果。项目主动作进入 `/pmflow-os?projectId=<id>`,待确认项进入 `/change-review?projectId=<id>&changeSetId=<id>`,发布关注和发布后反馈关注项进入 `/release-growth?projectId=<id>`,下一轮 draft 关注项进入 `/change-review?projectId=<id>&changeSetId=<id>`,执行中项进入 `/execution-bridge?projectId=<id>`;暂存想法后端只读聚合尚未接入时只显示 empty/warning,不使用 mock 数据冒充真实内容;移动端为空间首页独立 App 布局,不直接压缩桌面卡片,并保留最近项目区块;`frontend/src/pages/PersonalSpacePage.tsx` 是薄入口。该域只表达个人空间和主流程导航,不做团队空间强切换、企业组织管理、Project Memory 写入、ChangeSet 状态写入、ProgressEvent 写入、ReleaseValidationRun 写入、FeedbackIngest 写入或发布执行。
|
||||||
- 前端主包治理已切到“同步首屏最小集 + route/page-section lazy”模式:`frontend/src/router/index.tsx` 保留 `LoginPage / Layout` 这组同步入口,其余后台重页面通过 `React.lazy + Suspense` 懒加载;统一 fallback 在 `frontend/src/components/layout/LazyBoundary.tsx`。P0 公共壳冻结后,大模块 route 归属为:`/space` 归 Space lane,`/project-launch` 是启动层入口,`/pmflow-os` 与 `/command-center / /change-review / /execution-bridge / /release-growth` 归 Main Flow lane,`/me` 归 Account Settings lane,`/settings` 当前仅为 reserved route、尚未实现,新增必须由 Shell / Integration owner 串行处理。`frontend/src/features/personal-space/` 作为空间层入口,通过 `/space` 提供可直接打开的本地预览入口,承载继续推进、待我确认、AI 正在推进、暂存想法、草案箱与新建项目入口。`frontend/src/features/project-launch/` 作为首次进入页 / 新项目启动台产品域,通过 `/project-launch` 提供可直接打开的入口;Phase B 后默认调用真实 `pmflow-launch` draft/confirm API,创建成功态主动作跳转后端返回的 `/pmflow-os?projectId=<id>`,只有显式 `?demo=1` 或 `?dataSource=demo` 才启用本地 mock 状态机。`frontend/src/features/account-settings/` 作为 Account Settings 产品域,通过 `/me` 提供个人资料、默认语言、AI 回答深度、证据展示偏好、待确认/执行回写/发布门禁/失败提醒通知偏好和账户操作入口;该域通过 `frontend/src/api/accountSettings.ts` 建立前端合同,有 token 时优先调用已挂入 `backend/app/api/router.py` 的 `backend/app/api/account_settings_api/` `GET /account-settings/me` / `PUT /account-settings/me` 同步当前账号偏好,后端不可用时明确回落本机暂存,不修改 OAuth/JWT/auth core。`frontend/src/features/pmflow-os/` 作为新产品域,通过 `PMFlowOsProvider` 在应用根部挂载共享 truth store,并提供 `CommandCenter / ChangeReview / WorkGraph / ExecutionBridge / ReleaseGrowth / TeamLayer / ProjectMemory / Account` 主入口;当前 PMFlow OS 页面已切到专属轻壳,桌面端默认隐藏旧 TopBar,并由 `frontend/src/features/pmflow-os/components/PMFlowOsFrame.tsx` 统一承接“左侧稳定导航 + 顶部上下文条 + 中央视图 + 右侧 AI 副驾”的全局骨架,同时承接项目内 `个人空间 / 当前项目名` 面包屑和项目切换器;`ChangeReviewPage.tsx` 现在可以请求审查、通过、要求修改或拒绝当前 ChangeSet,并展示审查状态、审查意见与 high-risk approval gate;`TeamLayerPage.tsx` 现在消费 `ProjectTruthState.reviewerRouting(status/summary/items)` 展示待审 ChangeSet、来源、风险等级、建议审查人或 fallback role、审查原因、待审 item 数、证据数、warning、审查状态、审查意见和请求/决策时间,动作跳 `/change-review?projectId=<id>&changeSetId=<id>`;账号退出登录由 `frontend/src/features/pmflow-os/components/AccountControls.tsx` 统一承接桌面头像下拉、退出确认与移动端 bottom sheet,`frontend/src/features/pmflow-os/pages/AccountPage.tsx` 提供 `/me` 入口并委托 Account Settings 域渲染设置页;正式应用壳移动端底部导航统一由 `frontend/src/features/pmflow-os/components/MobileBottomNav.tsx` 承接,固定为 `空间 / 指挥台 / 待确认 / 动态 / 我的`,其中 `动态` 当前仍是 `/command-center` 占位。`/command-center` 额外提供免登录产品预览壳,`/pmflow-os` 是真实项目上下文 alias。主视觉按 `#2463EB + 白色` 的 Linear-like 高密度原型展开。`UsersPage` 把创建/删除/重置/导入/批量分配对话框拆为按需 chunk,`UserSkillsPage` 与 `WorkloadDetailPage` 的图表也分别拆到了 `frontend/src/pages/user-skills/components/UserSkillsRadarPanel.tsx` 与 `frontend/src/pages/workload-detail/components/WorkloadTrendChart.tsx`。
|
- 前端主包治理已切到“同步首屏最小集 + route/page-section lazy”模式:`frontend/src/router/index.tsx` 保留 `LoginPage / Layout` 这组同步入口,其余后台重页面通过 `React.lazy + Suspense` 懒加载;统一 fallback 在 `frontend/src/components/layout/LazyBoundary.tsx`。P0 公共壳冻结后,大模块 route 归属为:`/space` 归 Space lane,`/project-launch` 是启动层入口,`/pmflow-os` 与 `/command-center / /change-review / /execution-bridge / /release-growth` 归 Main Flow lane,`/me` 归 Account Settings lane,`/settings` 当前仅为 reserved route、尚未实现,新增必须由 Shell / Integration owner 串行处理。`frontend/src/features/personal-space/` 作为空间层入口,通过 `/space` 提供可直接打开的本地预览入口,承载继续推进、待我确认、AI 正在推进、暂存想法、草案箱与新建项目入口。`frontend/src/features/project-launch/` 作为首次进入页 / 新项目启动台产品域,通过 `/project-launch` 提供可直接打开的入口;Phase B 后默认调用真实 `pmflow-launch` draft/confirm API,创建成功态主动作跳转后端返回的 `/pmflow-os?projectId=<id>`,只有显式 `?demo=1` 或 `?dataSource=demo` 才启用本地 mock 状态机。`frontend/src/features/account-settings/` 作为 Account Settings 产品域,通过 `/me` 提供个人资料、默认语言、AI 回答深度、证据展示偏好、待确认/执行回写/发布门禁/失败提醒通知偏好和账户操作入口;该域通过 `frontend/src/api/accountSettings.ts` 建立前端合同,有 token 时优先调用已挂入 `backend/app/api/router.py` 的 `backend/app/api/account_settings_api/` `GET /account-settings/me` / `PUT /account-settings/me` 同步当前账号偏好,后端不可用时明确回落本机暂存,不修改 OAuth/JWT/auth core。`frontend/src/features/pmflow-os/` 作为新产品域,通过 `PMFlowOsProvider` 在应用根部挂载共享 truth store,并提供 `CommandCenter / ChangeReview / WorkGraph / ExecutionBridge / ReleaseGrowth / TeamLayer / ProjectMemory / Account` 主入口;当前 PMFlow OS 页面已切到专属轻壳,桌面端默认隐藏旧 TopBar,并由 `frontend/src/features/pmflow-os/components/PMFlowOsFrame.tsx` 统一承接“左侧稳定导航 + 顶部上下文条 + 中央视图 + 右侧 AI 副驾”的全局骨架,同时承接项目内 `个人空间 / 当前项目名` 面包屑和项目切换器;`ChangeReviewPage.tsx` 现在可以请求审查、通过、要求修改或拒绝当前 ChangeSet,并展示审查状态、审查意见与 high-risk approval gate;`TeamLayerPage.tsx` 现在消费 `ProjectTruthState.reviewerRouting(status/summary/items)` 展示待审 ChangeSet、来源、风险等级、建议审查人或 fallback role、审查原因、待审 item 数、证据数、warning、审查状态、审查意见和请求/决策时间,并复用 `TeamFeedPanel` 展示 `ProjectTruthState.feed` 中的 review request、review decision、ChangeSet 状态、execution progress 与 release gate 只读动态,动作跳 `/change-review?projectId=<id>&changeSetId=<id>`;账号退出登录由 `frontend/src/features/pmflow-os/components/AccountControls.tsx` 统一承接桌面头像下拉、退出确认与移动端 bottom sheet,`frontend/src/features/pmflow-os/pages/AccountPage.tsx` 提供 `/me` 入口并委托 Account Settings 域渲染设置页;正式应用壳移动端底部导航统一由 `frontend/src/features/pmflow-os/components/MobileBottomNav.tsx` 承接,固定为 `空间 / 指挥台 / 待确认 / 动态 / 我的`,其中 `动态` 当前仍是 `/command-center` 占位。`/command-center` 额外提供免登录产品预览壳,`/pmflow-os` 是真实项目上下文 alias。主视觉按 `#2463EB + 白色` 的 Linear-like 高密度原型展开。`UsersPage` 把创建/删除/重置/导入/批量分配对话框拆为按需 chunk,`UserSkillsPage` 与 `WorkloadDetailPage` 的图表也分别拆到了 `frontend/src/pages/user-skills/components/UserSkillsRadarPanel.tsx` 与 `frontend/src/pages/workload-detail/components/WorkloadTrendChart.tsx`。
|
||||||
- `frontend/src/features/personal-space/PersonalSpacePage.tsx` 是空间首页视图层,`frontend/src/api/space.ts` 是空间工作面只读聚合 API:从 `projects` summary、PMFlow OS `truth-state` 与 `execution-summary` 生成 `nextActionQueue` 我的下一步队列、继续推进、待确认、发布关注、发布后反馈关注、下一轮迭代草稿关注、执行中 / AI 正在推进、暂存想法、草案箱、最近项目摘要;Space P6 的 `nextActionQueue` 按高风险 ChangeSet 待确认、release blocked / failed evidence、handoff consumed 但无后续 progress、iteration draft 待确认、feedback/revenue/compliance 信号待处理排序,并只提供 `/change-review`、`/execution-bridge`、`/release-growth` 跳转;Space P7 新增 `review_attention`,只读消费 `truth-state.reviewerRouting`,把高风险待我审、`request_changes / rejected` 后待处理、`reviewer_missing` warning 与普通 pending review 排入“我的下一步”,待审/退回/拒绝项只跳 `/change-review?projectId=<id>&changeSetId=<id>`,reviewer 缺失 warning 只跳已有 `/team-layer?projectId=<id>`。Space P3 的 `releaseAttention` 优先消费 `truth-state.releases` 中由 release validation run 投影出的 release 状态与检查项,把“发布验证阻塞 / 发布验证待确认”显示到 `/space`,没有发布验证投影时才回落到 `execution-summary.releaseGate` 的发布候选或发布门禁阻塞;Space P4/P5 的 `feedbackAttention` 只读消费 `execution-summary.releaseSignals`,把发布后 feedback、revenue、ROI、compliance、iteration recommendation 与已生成的下一轮 ChangeSet draft 关注项显示到 `/space`。reviewerRouting、发布验证、发布后信号或下一轮 draft 缺失时显示明确空态,不虚构 reviewer、审查意见、待审 ChangeSet、验证、反馈、收入、ROI、合规、建议或 ChangeSet draft 结果。项目主动作进入 `/pmflow-os?projectId=<id>`,待确认项进入 `/change-review?projectId=<id>&changeSetId=<id>`,发布关注和发布后反馈关注项进入 `/release-growth?projectId=<id>`,下一轮 draft 关注项进入 `/change-review?projectId=<id>&changeSetId=<id>`,执行中项进入 `/execution-bridge?projectId=<id>`;暂存想法后端只读聚合尚未接入时只显示 empty/warning,不使用 mock 数据冒充真实内容;移动端为空间首页独立 App 布局,不直接压缩桌面卡片,并保留最近项目区块;`frontend/src/pages/PersonalSpacePage.tsx` 是薄入口。该域只表达个人空间和主流程导航,不做团队空间强切换、企业组织管理、Project Memory 写入、ChangeSet 状态写入、PMFlowApproval 写入、ProgressEvent 写入、ReleaseValidationRun 写入、FeedbackIngest 写入或发布执行。
|
- `frontend/src/features/personal-space/PersonalSpacePage.tsx` 是空间首页视图层,`frontend/src/api/space.ts` 是空间工作面只读聚合 API:从 `projects` summary、PMFlow OS `truth-state` 与 `execution-summary` 生成 `nextActionQueue` 我的下一步队列、继续推进、待确认、发布关注、发布后反馈关注、下一轮迭代草稿关注、执行中 / AI 正在推进、暂存想法、草案箱、最近项目摘要;Space P6 的 `nextActionQueue` 按高风险 ChangeSet 待确认、release blocked / failed evidence、handoff consumed 但无后续 progress、iteration draft 待确认、feedback/revenue/compliance 信号待处理排序,并只提供 `/change-review`、`/execution-bridge`、`/release-growth` 跳转;Space P7 新增 `review_attention`,只读消费 `truth-state.reviewerRouting`,把高风险待我审、`request_changes / rejected` 后待处理、`reviewer_missing` warning 与普通 pending review 排入“我的下一步”,待审/退回/拒绝项只跳 `/change-review?projectId=<id>&changeSetId=<id>`,reviewer 缺失 warning 只跳已有 `/team-layer?projectId=<id>`。Space P3 的 `releaseAttention` 优先消费 `truth-state.releases` 中由 release validation run 投影出的 release 状态与检查项,把“发布验证阻塞 / 发布验证待确认”显示到 `/space`,没有发布验证投影时才回落到 `execution-summary.releaseGate` 的发布候选或发布门禁阻塞;Space P4/P5 的 `feedbackAttention` 只读消费 `execution-summary.releaseSignals`,把发布后 feedback、revenue、ROI、compliance、iteration recommendation 与已生成的下一轮 ChangeSet draft 关注项显示到 `/space`。reviewerRouting、发布验证、发布后信号或下一轮 draft 缺失时显示明确空态,不虚构 reviewer、审查意见、待审 ChangeSet、验证、反馈、收入、ROI、合规、建议或 ChangeSet draft 结果。项目主动作进入 `/pmflow-os?projectId=<id>`,待确认项进入 `/change-review?projectId=<id>&changeSetId=<id>`,发布关注和发布后反馈关注项进入 `/release-growth?projectId=<id>`,下一轮 draft 关注项进入 `/change-review?projectId=<id>&changeSetId=<id>`,执行中项进入 `/execution-bridge?projectId=<id>`;暂存想法后端只读聚合尚未接入时只显示 empty/warning,不使用 mock 数据冒充真实内容;移动端为空间首页独立 App 布局,不直接压缩桌面卡片,并保留最近项目区块;`frontend/src/pages/PersonalSpacePage.tsx` 是薄入口。该域只表达个人空间和主流程导航,不做团队空间强切换、企业组织管理、Project Memory 写入、ChangeSet 状态写入、PMFlowApproval 写入、ProgressEvent 写入、ReleaseValidationRun 写入、FeedbackIngest 写入或发布执行。
|
||||||
- 前端主包治理已切到“同步首屏最小集 + route/page-section lazy”模式:`frontend/src/router/index.tsx` 保留 `LoginPage / Layout` 这组同步入口,其余后台重页面通过 `React.lazy + Suspense` 懒加载;统一 fallback 在 `frontend/src/components/layout/LazyBoundary.tsx`。P0 公共壳冻结后,大模块 route 归属为:`/space` 归 Space lane,`/project-launch` 是启动层入口,`/pmflow-os` 与 `/command-center / /change-review / /execution-bridge / /release-growth` 归 Main Flow lane,`/me` 归 Account Settings lane,`/settings` 当前仅为 reserved route、尚未实现,新增必须由 Shell / Integration owner 串行处理。`frontend/src/features/personal-space/` 作为空间层入口,通过 `/space` 提供可直接打开的本地预览入口,承载继续推进、待我确认、AI 正在推进、暂存想法、草案箱与新建项目入口。`frontend/src/features/project-launch/` 作为首次进入页 / 新项目启动台产品域,通过 `/project-launch` 提供可直接打开的入口;Phase B 后默认调用真实 `pmflow-launch` draft/confirm API,创建成功态主动作跳转后端返回的 `/pmflow-os?projectId=<id>`,只有显式 `?demo=1` 或 `?dataSource=demo` 才启用本地 mock 状态机。`frontend/src/features/account-settings/` 作为 Account Settings 产品域,通过 `/me` 提供个人资料、默认语言、AI 回答深度、证据展示偏好、待确认/执行回写/发布门禁/失败提醒通知偏好和账户操作入口;该域通过 `frontend/src/api/accountSettings.ts` 建立前端合同,有 token 时优先调用已挂入 `backend/app/api/router.py` 的 `backend/app/api/account_settings_api/` `GET /account-settings/me` / `PUT /account-settings/me` 同步当前账号偏好,后端不可用时明确回落本机暂存,不修改 OAuth/JWT/auth core。`frontend/src/features/pmflow-os/` 作为新产品域,通过 `PMFlowOsProvider` 在应用根部挂载共享 truth store,并提供 `CommandCenter / ChangeReview / WorkGraph / ExecutionBridge / ReleaseGrowth / TeamLayer / ProjectMemory / Account` 主入口;当前 PMFlow OS 页面已切到专属轻壳,桌面端默认隐藏旧 TopBar,并由 `frontend/src/features/pmflow-os/components/PMFlowOsFrame.tsx` 统一承接“左侧稳定导航 + 顶部上下文条 + 中央视图 + 右侧 AI 副驾”的全局骨架,同时承接项目内 `个人空间 / 当前项目名` 面包屑和项目切换器;`TeamLayerPage.tsx` 现在消费 `ProjectTruthState.reviewerRouting(status/summary/items)` 展示待审 ChangeSet、来源、风险等级、建议审查人或 fallback role、审查原因、待审 item 数、证据数和 warning,动作只跳 `/change-review?projectId=<id>&changeSetId=<id>`,不自动 assign reviewer;账号退出登录由 `frontend/src/features/pmflow-os/components/AccountControls.tsx` 统一承接桌面头像下拉、退出确认与移动端 bottom sheet,`frontend/src/features/pmflow-os/pages/AccountPage.tsx` 提供 `/me` 入口并委托 Account Settings 域渲染设置页;正式应用壳移动端底部导航统一由 `frontend/src/features/pmflow-os/components/MobileBottomNav.tsx` 承接,固定为 `空间 / 指挥台 / 待确认 / 动态 / 我的`,其中 `动态` 当前仍是 `/command-center` 占位。`/command-center` 额外提供免登录产品预览壳,`/pmflow-os` 是真实项目上下文 alias。主视觉按 `#2463EB + 白色` 的 Linear-like 高密度原型展开。`UsersPage` 把创建/删除/重置/导入/批量分配对话框拆为按需 chunk,`UserSkillsPage` 与 `WorkloadDetailPage` 的图表也分别拆到了 `frontend/src/pages/user-skills/components/UserSkillsRadarPanel.tsx` 与 `frontend/src/pages/workload-detail/components/WorkloadTrendChart.tsx`。
|
- 前端主包治理已切到“同步首屏最小集 + route/page-section lazy”模式:`frontend/src/router/index.tsx` 保留 `LoginPage / Layout` 这组同步入口,其余后台重页面通过 `React.lazy + Suspense` 懒加载;统一 fallback 在 `frontend/src/components/layout/LazyBoundary.tsx`。P0 公共壳冻结后,大模块 route 归属为:`/space` 归 Space lane,`/project-launch` 是启动层入口,`/pmflow-os` 与 `/command-center / /change-review / /execution-bridge / /release-growth` 归 Main Flow lane,`/me` 归 Account Settings lane,`/settings` 当前仅为 reserved route、尚未实现,新增必须由 Shell / Integration owner 串行处理。`frontend/src/features/personal-space/` 作为空间层入口,通过 `/space` 提供可直接打开的本地预览入口,承载继续推进、待我确认、AI 正在推进、暂存想法、草案箱与新建项目入口。`frontend/src/features/project-launch/` 作为首次进入页 / 新项目启动台产品域,通过 `/project-launch` 提供可直接打开的入口;Phase B 后默认调用真实 `pmflow-launch` draft/confirm API,创建成功态主动作跳转后端返回的 `/pmflow-os?projectId=<id>`,只有显式 `?demo=1` 或 `?dataSource=demo` 才启用本地 mock 状态机。`frontend/src/features/account-settings/` 作为 Account Settings 产品域,通过 `/me` 提供个人资料、默认语言、AI 回答深度、证据展示偏好、待确认/执行回写/发布门禁/失败提醒通知偏好和账户操作入口;该域通过 `frontend/src/api/accountSettings.ts` 建立前端合同,有 token 时优先调用已挂入 `backend/app/api/router.py` 的 `backend/app/api/account_settings_api/` `GET /account-settings/me` / `PUT /account-settings/me` 同步当前账号偏好,后端不可用时明确回落本机暂存,不修改 OAuth/JWT/auth core。`frontend/src/features/pmflow-os/` 作为新产品域,通过 `PMFlowOsProvider` 在应用根部挂载共享 truth store,并提供 `CommandCenter / ChangeReview / WorkGraph / ExecutionBridge / ReleaseGrowth / TeamLayer / ProjectMemory / Account` 主入口;当前 PMFlow OS 页面已切到专属轻壳,桌面端默认隐藏旧 TopBar,并由 `frontend/src/features/pmflow-os/components/PMFlowOsFrame.tsx` 统一承接“左侧稳定导航 + 顶部上下文条 + 中央视图 + 右侧 AI 副驾”的全局骨架,同时承接项目内 `个人空间 / 当前项目名` 面包屑和项目切换器;`TeamLayerPage.tsx` 现在消费 `ProjectTruthState.reviewerRouting(status/summary/items)` 展示待审 ChangeSet、来源、风险等级、建议审查人或 fallback role、审查原因、待审 item 数、证据数和 warning,并复用 `TeamFeedPanel` 展示 `ProjectTruthState.feed` 中的 review request、review decision、ChangeSet 状态、execution progress 与 release gate 只读动态,动作只跳 `/change-review?projectId=<id>&changeSetId=<id>`,不自动 assign reviewer;账号退出登录由 `frontend/src/features/pmflow-os/components/AccountControls.tsx` 统一承接桌面头像下拉、退出确认与移动端 bottom sheet,`frontend/src/features/pmflow-os/pages/AccountPage.tsx` 提供 `/me` 入口并委托 Account Settings 域渲染设置页;正式应用壳移动端底部导航统一由 `frontend/src/features/pmflow-os/components/MobileBottomNav.tsx` 承接,固定为 `空间 / 指挥台 / 待确认 / 动态 / 我的`,其中 `动态` 当前仍是 `/command-center` 占位。`/command-center` 额外提供免登录产品预览壳,`/pmflow-os` 是真实项目上下文 alias。主视觉按 `#2463EB + 白色` 的 Linear-like 高密度原型展开。`UsersPage` 把创建/删除/重置/导入/批量分配对话框拆为按需 chunk,`UserSkillsPage` 与 `WorkloadDetailPage` 的图表也分别拆到了 `frontend/src/pages/user-skills/components/UserSkillsRadarPanel.tsx` 与 `frontend/src/pages/workload-detail/components/WorkloadTrendChart.tsx`。
|
||||||
- `frontend/src/features/project-launch/types.ts`、`mockData.ts`、`useProjectLaunchState.ts` 是新项目启动台状态层;默认真实模式通过 `frontend/src/api/pmflowLaunch.ts` 生成草案并确认创建真实项目,API 失败进入明确失败态,不静默 fallback 成 mock 成功;`mockData.ts` 仅在显式 `?demo=1` 或 `?dataSource=demo` 下作为演示状态机使用。`components/LaunchShell.tsx` 负责桌面/移动分流,桌面端复用 `frontend/src/features/personal-space/components/SpaceChrome.tsx` 的空间左侧栏和顶部条,`LaunchCanvases.tsx` 和 `MobileLaunchLayout.tsx` 承接高保真图中的意图输入、AI 工作、人类确认、草案修改、生成失败、创建成功过渡与移动端 bottom sheet 交互。
|
- `frontend/src/features/project-launch/types.ts`、`mockData.ts`、`useProjectLaunchState.ts` 是新项目启动台状态层;默认真实模式通过 `frontend/src/api/pmflowLaunch.ts` 生成草案并确认创建真实项目,API 失败进入明确失败态,不静默 fallback 成 mock 成功;`mockData.ts` 仅在显式 `?demo=1` 或 `?dataSource=demo` 下作为演示状态机使用。`components/LaunchShell.tsx` 负责桌面/移动分流,桌面端复用 `frontend/src/features/personal-space/components/SpaceChrome.tsx` 的空间左侧栏和顶部条,`LaunchCanvases.tsx` 和 `MobileLaunchLayout.tsx` 承接高保真图中的意图输入、AI 工作、人类确认、草案修改、生成失败、创建成功过渡与移动端 bottom sheet 交互。
|
||||||
- `frontend/src/features/pmflow-os/store.tsx` 当前是 PMFlow OS 共享 truth store:`?projectId=<id>` 时通过 React Query 调用 `frontend/src/api/pmflowOs.ts` 读取真实 `GET /pmflow-os/projects/{project_id}/truth-state` 与 `GET /pmflow-os/projects/{project_id}/execution-summary`,真实模式下项目内 message、`proposed_items` extraction、ChangeItem `accept/edit/defer`、ChangeSet commit、review decision、Execution Handoff create/consume、execution progress writeback、release validation run create、release feedback ingest、单条 iteration recommendation -> ChangeSet draft 与同组 iteration recommendation 批量 -> ChangeSet draft 均调用 `/pmflow-os` 后端并 refetch;只有显式 `?demo=1` 或 `?dataSource=demo` 时才启用本地 mock 演示状态机。真实读取/动作失败会进入错误/空态,不静默 fallback 成 mock 成功。
|
- `frontend/src/features/pmflow-os/store.tsx` 当前是 PMFlow OS 共享 truth store:`?projectId=<id>` 时通过 React Query 调用 `frontend/src/api/pmflowOs.ts` 读取真实 `GET /pmflow-os/projects/{project_id}/truth-state` 与 `GET /pmflow-os/projects/{project_id}/execution-summary`,真实模式下项目内 message、`proposed_items` extraction、ChangeItem `accept/edit/defer`、ChangeSet commit、review decision、Execution Handoff create/consume、execution progress writeback、release validation run create、release feedback ingest、单条 iteration recommendation -> ChangeSet draft 与同组 iteration recommendation 批量 -> ChangeSet draft 均调用 `/pmflow-os` 后端并 refetch;只有显式 `?demo=1` 或 `?dataSource=demo` 时才启用本地 mock 演示状态机。真实读取/动作失败会进入错误/空态,不静默 fallback 成 mock 成功。
|
||||||
- `frontend/src/features/pmflow-os/store.tsx` 仍保留演示用项目内 AI 结构化闭环状态机:`command_idle / ai_extracting / extraction_ready / review_open / writeback_success`。`frontend/src/features/pmflow-os/pages/StructuredExtractionPage.tsx` 是本轮结构化提取页,`ChangeReviewPage.tsx` 是决策与待确认中心,`MemoryWritebackResultPage.tsx` 是项目记忆写入结果页,`WorkGraphPage.tsx` 是项目工作台关系总览与对象投影视图,`ExecutionBridgePage.tsx` 是执行桥上下文包、交接按钮、运行端领取确认、PR/测试与回写状态页;`ReleaseGrowthPage.tsx` 真实模式读取 `execution-summary.releaseGate`、`latestValidationRun` 与 `releaseSignals`,从 branch、commit、PR、test、failed evidence 展示 `可发布 / 阻塞 / 需要人工确认 / 缺少证据` 判断、阻塞原因、下一步动作、发布验证记录和发布后 feedback/revenue/recommendation 信号,缺少发布后信号时显示 empty/warning,不执行发布命令、不展示 mock 发布结果;页面可展示 recommendation quality grouping,把真实 recommendation 单条或同组批量生成下一轮待确认 ChangeSet draft,生成后仍进入 Change Review accept/edit/defer,不自动 commit、不写 Project Memory、不创建正式任务;`ChangeReviewPage.tsx` 会展示 `iteration_recommendation_group` evidence 的来源组、feedback 数、recommendation 数、风险、影响和审查优先级;同时读取 Account notification preference helper,用 `releaseGate` 偏好控制发布门禁强调提醒,用 `failureAlert` 偏好控制失败强调提醒,偏好关闭时只静默提醒表达强度,不隐藏 release evidence、阻塞原因、审计状态、validation run 或 releaseSignals;静态发布/增长原型只保留在显式 demo 模式。A3 已接入后端 truth-state,C1 已接入真实 message/extraction/review 状态机,C2 已接入真实 ChangeSet commit,Phase D 已接入真实 execution-summary/dev-sync,D.2 已接入 `POST /execution-handoffs` 创建 PromptPackage + handoff_created progress event,P1 已接入 `POST /execution-handoffs/{prompt_package_id}/consume` 创建 handoff_consumed progress event 并把 execution status 投影为 coding,Release Growth P1 已接入 execution evidence gate,Release Validation P1 已接入 `POST /release-validation-runs` 创建 `ReleaseValidationRun` 快照,Release Feedback P1 已接入 `POST /release-feedback-ingests` 写入 `FeedbackIngest` 并生成 `IterationRecommendation`,Iteration Loop P1 已接入 `POST /iteration-recommendations/{recommendation_id}/change-set-drafts` 把 recommendation 回流到 Change Review,Iteration Loop P2 已接入 `POST /iteration-recommendation-groups/{group_key}/change-set-drafts` 并在 `releaseSignals.recommendationGroups` 暴露分组/去重/风险/影响合同;当前仍不调用真实 AI 提取,不把 mock 当真实失败 fallback。`ProjectMemoryPage.tsx` 在真实模式下展示后端 `truth_nodes + semantic_facts` 的 `projectMemory` 投影,accepted/edited ChangeItem 只有 commit 成功后才进入 Project Memory。`frontend/src/features/pmflow-os/components/ProjectStructuredLoop.tsx` 提供 `StatusLabel / EvidenceSnippet / ObjectChangeCard / ProjectConversationPanel / StructuredExtractionPanel / ProjectAICopilotPanel` 等闭环组件,并复用契约化 `InlineNotice` 表达“未确认不得写入”的局部提示。
|
- `frontend/src/features/pmflow-os/store.tsx` 仍保留演示用项目内 AI 结构化闭环状态机:`command_idle / ai_extracting / extraction_ready / review_open / writeback_success`。`frontend/src/features/pmflow-os/pages/StructuredExtractionPage.tsx` 是本轮结构化提取页,`ChangeReviewPage.tsx` 是决策与待确认中心,`MemoryWritebackResultPage.tsx` 是项目记忆写入结果页,`WorkGraphPage.tsx` 是项目工作台关系总览与对象投影视图,`ExecutionBridgePage.tsx` 是执行桥上下文包、交接按钮、运行端领取确认、PR/测试与回写状态页;`ReleaseGrowthPage.tsx` 真实模式读取 `execution-summary.releaseGate`、`latestValidationRun` 与 `releaseSignals`,从 branch、commit、PR、test、failed evidence 展示 `可发布 / 阻塞 / 需要人工确认 / 缺少证据` 判断、阻塞原因、下一步动作、发布验证记录和发布后 feedback/revenue/recommendation 信号,缺少发布后信号时显示 empty/warning,不执行发布命令、不展示 mock 发布结果;页面可展示 recommendation quality grouping,把真实 recommendation 单条或同组批量生成下一轮待确认 ChangeSet draft,生成后仍进入 Change Review accept/edit/defer,不自动 commit、不写 Project Memory、不创建正式任务;`ChangeReviewPage.tsx` 会展示 `iteration_recommendation_group` evidence 的来源组、feedback 数、recommendation 数、风险、影响和审查优先级;同时读取 Account notification preference helper,用 `releaseGate` 偏好控制发布门禁强调提醒,用 `failureAlert` 偏好控制失败强调提醒,偏好关闭时只静默提醒表达强度,不隐藏 release evidence、阻塞原因、审计状态、validation run 或 releaseSignals;静态发布/增长原型只保留在显式 demo 模式。A3 已接入后端 truth-state,C1 已接入真实 message/extraction/review 状态机,C2 已接入真实 ChangeSet commit,Phase D 已接入真实 execution-summary/dev-sync,D.2 已接入 `POST /execution-handoffs` 创建 PromptPackage + handoff_created progress event,P1 已接入 `POST /execution-handoffs/{prompt_package_id}/consume` 创建 handoff_consumed progress event 并把 execution status 投影为 coding,Release Growth P1 已接入 execution evidence gate,Release Validation P1 已接入 `POST /release-validation-runs` 创建 `ReleaseValidationRun` 快照,Release Feedback P1 已接入 `POST /release-feedback-ingests` 写入 `FeedbackIngest` 并生成 `IterationRecommendation`,Iteration Loop P1 已接入 `POST /iteration-recommendations/{recommendation_id}/change-set-drafts` 把 recommendation 回流到 Change Review,Iteration Loop P2 已接入 `POST /iteration-recommendation-groups/{group_key}/change-set-drafts` 并在 `releaseSignals.recommendationGroups` 暴露分组/去重/风险/影响合同;当前仍不调用真实 AI 提取,不把 mock 当真实失败 fallback。`ProjectMemoryPage.tsx` 在真实模式下展示后端 `truth_nodes + semantic_facts` 的 `projectMemory` 投影,accepted/edited ChangeItem 只有 commit 成功后才进入 Project Memory。`frontend/src/features/pmflow-os/components/ProjectStructuredLoop.tsx` 提供 `StatusLabel / EvidenceSnippet / ObjectChangeCard / ProjectConversationPanel / StructuredExtractionPanel / ProjectAICopilotPanel` 等闭环组件,并复用契约化 `InlineNotice` 表达“未确认不得写入”的局部提示。
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@
|
||||||
- SSTC 负责人推荐接口:参考 `POST /projects/{project_id}/tasks/{task_id}/recommend-assignee`
|
- SSTC 负责人推荐接口:参考 `POST /projects/{project_id}/tasks/{task_id}/recommend-assignee`
|
||||||
- SSTC 任务更新接口:参考 `PATCH /projects/{project_id}/tasks/{task_id}`
|
- SSTC 任务更新接口:参考 `PATCH /projects/{project_id}/tasks/{task_id}`
|
||||||
- SSTC 发布创建接口:参考 `POST /projects/{project_id}/releases`
|
- SSTC 发布创建接口:参考 `POST /projects/{project_id}/releases`
|
||||||
- PMFlow OS 真实读路径、C1 Change Review API、C2 backend commit、Execution Handoff、Release Evidence Gate、Release Validation Run、Release Feedback Signal、Iteration Loop draft 与 Team reviewer decision loop:参考 `backend/app/api/pmflow_os_api/`、`backend/app/services/pmflow_os_projection_service.py`、`backend/app/services/pmflow_change_review_service.py`、`backend/app/schemas/pmflow_os.py`;只读提供 `GET /pmflow-os/projects/{project_id}/truth-state` 与 `GET /pmflow-os/projects/{project_id}/execution-summary`,复用 `truth_nodes / tasks / semantic_facts / ai_project_control / dev_sync`,并读取 `pmflow_threads / pmflow_thread_messages / pmflow_change_sets / pmflow_change_items / pmflow_approvals / pmflow_evidence_links`;`truth-state.reviewerRouting` 是 `{status, warningCode, summary, items}` 读模型,会从 open/pending ChangeSet、待审 item 风险、跨对象类型、evidence source、项目成员与 `OWNER / REVIEWER` 角色生成 `sourceType / riskLevel / priority / suggestedReviewer / fallbackReviewerRole / targetUrl`,并返回 `reviewDecision / approvalState / requestedAt / decidedAt / decisionReason` 审查决策只读字段;P8 新增 `POST /pmflow-os/change-sets/{change_set_id}/review-decisions`,支持 `request_review / approve / request_changes / reject`,复用 `PMFlowApproval` 写审计,`approve` 满足 high-risk C2 approval gate 但不自动 commit,`request_changes / reject` 不写 Project Memory;C1 写 API 包括 thread message、`proposed_items` extraction、ChangeSet detail、ChangeItem `accept/edit/defer`;C2 backend 已实现 `POST /pmflow-os/change-sets/{change_set_id}/commit`,默认 `mode=atomic`,将 `Requirement / Decision / Risk` 写入 `truth_nodes`,将 `Task` 写入 `truth_nodes(node_type='task') + tasks`,高风险项强制 approval gate;D.2 已实现 `POST /pmflow-os/projects/{project_id}/execution-handoffs`,对已确认任务生成/复用 `PromptPackage` 并创建 `ProgressEvent(event_type='handoff_created')` 起点;P1 已实现 `POST /pmflow-os/projects/{project_id}/execution-handoffs/{prompt_package_id}/consume`,记录运行端领取、更新 `PromptPackage.package_payload.latest_handoff.handoff_state=consumed` 并创建 `ProgressEvent(event_type='handoff_consumed', derived_task_status='coding')`;Release Growth P1 已在 `execution-summary.releaseGate` 中从 branch / commit / PR / test_passed / checks_passed / failed / blocked 等 `ProgressEvent` 推导 `ready / blocked / needs_confirmation / empty`;Release Validation P1 新增 `POST /pmflow-os/projects/{project_id}/release-validation-runs`,从当前 `releaseGate` 固化 `ReleaseValidationRun` 快照并在 `releaseGate.latestValidationRun` 返回最新记录,无 evidence 时返回 `release_validation_evidence_empty`;Release Feedback P1 新增 `POST /pmflow-os/projects/{project_id}/release-feedback-ingests`,复用 `FeedbackIngest / IterationRecommendation` 写入真实发布后反馈,并在 `execution-summary.releaseSignals` 投影真实 `feedback / revenueEvents / recommendations` 与 release gate / validation run 关系;Iteration Loop P1 新增 `POST /pmflow-os/projects/{project_id}/iteration-recommendations/{recommendation_id}/change-set-drafts`,把真实 `IterationRecommendation` 转为 open ChangeSet、pending_review Requirement/Task/Risk/Decision items 与 iteration evidence,重复调用复用既有 draft;Iteration Loop P2 新增 `POST /pmflow-os/projects/{project_id}/iteration-recommendation-groups/{group_key}/change-set-drafts`,并在 `execution-summary.releaseSignals.recommendations` 补 `groupKey / duplicateOf / mergedCount / impactLevel / riskLevel / suggestedChangeTypes / reviewPriority`,在 `recommendationGroups` 聚合同组建议,支持同组 recommendation 批量生成一个可复用 ChangeSet draft 与 `iteration_recommendation_group` evidence;这些步骤均不执行发布命令、外部支付、真实推送、自动 Project Memory commit 或正式 Task 创建
|
- PMFlow OS 真实读路径、C1 Change Review API、C2 backend commit、Execution Handoff、Release Evidence Gate、Release Validation Run、Release Feedback Signal、Iteration Loop draft、Team reviewer decision loop 与 Team Feed 只读动态流:参考 `backend/app/api/pmflow_os_api/`、`backend/app/services/pmflow_os_projection_service.py`、`backend/app/services/pmflow_change_review_service.py`、`backend/app/schemas/pmflow_os.py`;只读提供 `GET /pmflow-os/projects/{project_id}/truth-state` 与 `GET /pmflow-os/projects/{project_id}/execution-summary`,复用 `truth_nodes / tasks / semantic_facts / ai_project_control / dev_sync`,并读取 `pmflow_threads / pmflow_thread_messages / pmflow_change_sets / pmflow_change_items / pmflow_approvals / pmflow_evidence_links`;`truth-state.reviewerRouting` 是 `{status, warningCode, summary, items}` 读模型,会从 open/pending ChangeSet、待审 item 风险、跨对象类型、evidence source、项目成员与 `OWNER / REVIEWER` 角色生成 `sourceType / riskLevel / priority / suggestedReviewer / fallbackReviewerRole / targetUrl`,并返回 `reviewDecision / approvalState / requestedAt / decidedAt / decisionReason` 审查决策只读字段;`truth-state.feed` 是 Team Feed 只读动态流,从 review request / review decision / ChangeSet 状态 / `ProgressEvent` / release gate 聚合,不写审批、不写 ChangeSet、不写通知;P8 新增 `POST /pmflow-os/change-sets/{change_set_id}/review-decisions`,支持 `request_review / approve / request_changes / reject`,复用 `PMFlowApproval` 写审计,`approve` 满足 high-risk C2 approval gate 但不自动 commit,`request_changes / reject` 不写 Project Memory;C1 写 API 包括 thread message、`proposed_items` extraction、ChangeSet detail、ChangeItem `accept/edit/defer`;C2 backend 已实现 `POST /pmflow-os/change-sets/{change_set_id}/commit`,默认 `mode=atomic`,将 `Requirement / Decision / Risk` 写入 `truth_nodes`,将 `Task` 写入 `truth_nodes(node_type='task') + tasks`,高风险项强制 approval gate;D.2 已实现 `POST /pmflow-os/projects/{project_id}/execution-handoffs`,对已确认任务生成/复用 `PromptPackage` 并创建 `ProgressEvent(event_type='handoff_created')` 起点;P1 已实现 `POST /pmflow-os/projects/{project_id}/execution-handoffs/{prompt_package_id}/consume`,记录运行端领取、更新 `PromptPackage.package_payload.latest_handoff.handoff_state=consumed` 并创建 `ProgressEvent(event_type='handoff_consumed', derived_task_status='coding')`;Release Growth P1 已在 `execution-summary.releaseGate` 中从 branch / commit / PR / test_passed / checks_passed / failed / blocked 等 `ProgressEvent` 推导 `ready / blocked / needs_confirmation / empty`;Release Validation P1 新增 `POST /pmflow-os/projects/{project_id}/release-validation-runs`,从当前 `releaseGate` 固化 `ReleaseValidationRun` 快照并在 `releaseGate.latestValidationRun` 返回最新记录,无 evidence 时返回 `release_validation_evidence_empty`;Release Feedback P1 新增 `POST /pmflow-os/projects/{project_id}/release-feedback-ingests`,复用 `FeedbackIngest / IterationRecommendation` 写入真实发布后反馈,并在 `execution-summary.releaseSignals` 投影真实 `feedback / revenueEvents / recommendations` 与 release gate / validation run 关系;Iteration Loop P1 新增 `POST /pmflow-os/projects/{project_id}/iteration-recommendations/{recommendation_id}/change-set-drafts`,把真实 `IterationRecommendation` 转为 open ChangeSet、pending_review Requirement/Task/Risk/Decision items 与 iteration evidence,重复调用复用既有 draft;Iteration Loop P2 新增 `POST /pmflow-os/projects/{project_id}/iteration-recommendation-groups/{group_key}/change-set-drafts`,并在 `execution-summary.releaseSignals.recommendations` 补 `groupKey / duplicateOf / mergedCount / impactLevel / riskLevel / suggestedChangeTypes / reviewPriority`,在 `recommendationGroups` 聚合同组建议,支持同组 recommendation 批量生成一个可复用 ChangeSet draft 与 `iteration_recommendation_group` evidence;这些步骤均不执行发布命令、外部支付、真实推送、自动 Project Memory commit 或正式 Task 创建
|
||||||
- Project Launch 真实创建链:参考 `backend/app/api/pmflow_launch_api/`、`backend/app/services/pmflow_launch_service.py`、`backend/app/schemas/pmflow_launch.py` 与模型 `backend/app/models/pmflow_launch.py`;接口为 `POST /pmflow-launch/drafts` 与 `POST /pmflow-launch/drafts/{draft_id}/confirm`,draft 只写 `pmflow_launch_drafts`,confirm 在同一事务内创建 `projects / user_projects / pmflow_threads / pmflow_thread_messages / truth_nodes / tasks / semantic_facts seed / operation_logs`
|
- Project Launch 真实创建链:参考 `backend/app/api/pmflow_launch_api/`、`backend/app/services/pmflow_launch_service.py`、`backend/app/schemas/pmflow_launch.py` 与模型 `backend/app/models/pmflow_launch.py`;接口为 `POST /pmflow-launch/drafts` 与 `POST /pmflow-launch/drafts/{draft_id}/confirm`,draft 只写 `pmflow_launch_drafts`,confirm 在同一事务内创建 `projects / user_projects / pmflow_threads / pmflow_thread_messages / truth_nodes / tasks / semantic_facts seed / operation_logs`
|
||||||
- PMFlow Change Review 模型与 migration:参考 `backend/app/models/pmflow_change_review.py` 与 `backend/alembic/versions/20260426_add_pmflow_change_review_tables.py`;只包含 `pmflow_change_sets / pmflow_change_items / pmflow_approvals / pmflow_evidence_links`,本阶段不得新增或依赖 `/commit`
|
- PMFlow Change Review 模型与 migration:参考 `backend/app/models/pmflow_change_review.py` 与 `backend/alembic/versions/20260426_add_pmflow_change_review_tables.py`;只包含 `pmflow_change_sets / pmflow_change_items / pmflow_approvals / pmflow_evidence_links`,本阶段不得新增或依赖 `/commit`
|
||||||
|
|
||||||
|
|
@ -110,6 +110,7 @@
|
||||||
- PMFlow OS 共享 truth store 与主链状态动作:参考 `frontend/src/features/pmflow-os/store.tsx`;当前支持 `?projectId=<id>` 走 React Query 读取真实 `truth-state` 与 `execution-summary`,真实模式下 thread message、`proposed_items` extraction、ChangeItem `accept/edit/defer`、ChangeSet commit、review decision、Execution Handoff create/consume、execution progress writeback、release validation run create、release feedback ingest、单条 iteration recommendation -> ChangeSet draft 与同组 iteration recommendation 批量 -> ChangeSet draft 均调后端并 refetch,不本地 promote 入 Project Memory、不伪造 approval、execution event、发布验证记录、发布后信号或下一轮 draft;`?demo=1` 才启用本地 mock 演示状态机和本地动作;项目内 AI 结构化闭环状态机为 `command_idle / ai_extracting / extraction_ready / review_open / writeback_success`
|
- PMFlow OS 共享 truth store 与主链状态动作:参考 `frontend/src/features/pmflow-os/store.tsx`;当前支持 `?projectId=<id>` 走 React Query 读取真实 `truth-state` 与 `execution-summary`,真实模式下 thread message、`proposed_items` extraction、ChangeItem `accept/edit/defer`、ChangeSet commit、review decision、Execution Handoff create/consume、execution progress writeback、release validation run create、release feedback ingest、单条 iteration recommendation -> ChangeSet draft 与同组 iteration recommendation 批量 -> ChangeSet draft 均调后端并 refetch,不本地 promote 入 Project Memory、不伪造 approval、execution event、发布验证记录、发布后信号或下一轮 draft;`?demo=1` 才启用本地 mock 演示状态机和本地动作;项目内 AI 结构化闭环状态机为 `command_idle / ai_extracting / extraction_ready / review_open / writeback_success`
|
||||||
- Account Settings / `/me` 前端产品域与 P1-P8 偏好合同:参考 `frontend/src/features/account-settings/AccountSettingsPanel.tsx`、`frontend/src/features/pmflow-os/pages/AccountPage.tsx`、`frontend/src/api/accountSettings.ts`、`backend/app/api/account_settings_api/`、`backend/app/schemas/account_settings.py` 与 `backend/app/services/account_settings_service.py`;当前覆盖个人资料、默认语言、AI 回答深度、证据展示偏好、待确认、执行回写、发布门禁和失败提醒通知偏好,移动端使用分组列表与 bottom sheet,账户退出仍复用 `AccountControls.tsx`,不改 OAuth/JWT/auth core;P1 后端合同提供 `GET /account-settings/me` 与 `PUT /account-settings/me`,已由 `backend/app/api/router.py` 挂入核心路由组,按当前 `tenant_id + user_id` 保存账号偏好,前端有 token 时优先账号同步,后端不可用时明确回落 `仅本机暂存 / 保存失败`;P2 在 `frontend/src/api/accountSettings.ts` 提供 `shouldShowAccountNotification` 与 `getAccountNotificationConsumption`,把通知偏好映射为页面内提醒消费模型;P3 新增 `getReleaseGateNotificationPreference(settings, event)` 供 Release/Growth 后续消费:`release_gate_*` 与 `release_validation_*` 使用 `releaseGate` 偏好,`failed_event` 使用 `failureAlert` 偏好;P5/P6 的 `getPostReleaseNotificationPreference(settings, event)` 供发布后反馈与下一轮待确认消费:`feedback_received / revenue_signal / compliance_blocked` 使用 `releaseGate` 偏好,`iteration_recommendation / next_change_review` 使用 `pendingConfirmation` 偏好并落到 `change_review` surface;P7 将每类通知偏好扩展为 `reminderIntensity=silent|normal|prominent` 与 `evidenceDisplay=compact|expanded`,并新增 `getAccountReminderConsumption(settings, event)` 覆盖 `change_review_high_risk / iteration_draft_ready / release_blocked / execution_stalled`,稳定返回 `notificationTransport=in_app_only / evidencePolicy=preserve_business_evidence / auditPolicy=preserve_audit_state`;P8 新增 `getReviewDecisionNotificationPreference(settings, event)` 覆盖 `review_requested / review_approved / review_changes_requested / review_rejected / high_risk_approval_required`,统一使用 `pendingConfirmation` 偏好和 `change_review` surface,返回 `reviewerRoutingPolicy=preserve_reviewer_routing / approvalPolicy=preserve_approval_state`,偏好关闭只静默页面内提醒,不隐藏 reviewerRouting、approval、evidence 或 audit state;ReleaseGrowthPage 当前消费 `releaseGate` 与 `failureAlert` 两个偏好,只静默强调型提醒,不隐藏 release evidence、阻塞原因、审计状态、validation run、releaseSignals 或下一轮 ChangeSet draft;这些 helper 只控制本地 UI 提醒消费合同,不代表真实邮件、桌面推送或系统通知中心已接入
|
- Account Settings / `/me` 前端产品域与 P1-P8 偏好合同:参考 `frontend/src/features/account-settings/AccountSettingsPanel.tsx`、`frontend/src/features/pmflow-os/pages/AccountPage.tsx`、`frontend/src/api/accountSettings.ts`、`backend/app/api/account_settings_api/`、`backend/app/schemas/account_settings.py` 与 `backend/app/services/account_settings_service.py`;当前覆盖个人资料、默认语言、AI 回答深度、证据展示偏好、待确认、执行回写、发布门禁和失败提醒通知偏好,移动端使用分组列表与 bottom sheet,账户退出仍复用 `AccountControls.tsx`,不改 OAuth/JWT/auth core;P1 后端合同提供 `GET /account-settings/me` 与 `PUT /account-settings/me`,已由 `backend/app/api/router.py` 挂入核心路由组,按当前 `tenant_id + user_id` 保存账号偏好,前端有 token 时优先账号同步,后端不可用时明确回落 `仅本机暂存 / 保存失败`;P2 在 `frontend/src/api/accountSettings.ts` 提供 `shouldShowAccountNotification` 与 `getAccountNotificationConsumption`,把通知偏好映射为页面内提醒消费模型;P3 新增 `getReleaseGateNotificationPreference(settings, event)` 供 Release/Growth 后续消费:`release_gate_*` 与 `release_validation_*` 使用 `releaseGate` 偏好,`failed_event` 使用 `failureAlert` 偏好;P5/P6 的 `getPostReleaseNotificationPreference(settings, event)` 供发布后反馈与下一轮待确认消费:`feedback_received / revenue_signal / compliance_blocked` 使用 `releaseGate` 偏好,`iteration_recommendation / next_change_review` 使用 `pendingConfirmation` 偏好并落到 `change_review` surface;P7 将每类通知偏好扩展为 `reminderIntensity=silent|normal|prominent` 与 `evidenceDisplay=compact|expanded`,并新增 `getAccountReminderConsumption(settings, event)` 覆盖 `change_review_high_risk / iteration_draft_ready / release_blocked / execution_stalled`,稳定返回 `notificationTransport=in_app_only / evidencePolicy=preserve_business_evidence / auditPolicy=preserve_audit_state`;P8 新增 `getReviewDecisionNotificationPreference(settings, event)` 覆盖 `review_requested / review_approved / review_changes_requested / review_rejected / high_risk_approval_required`,统一使用 `pendingConfirmation` 偏好和 `change_review` surface,返回 `reviewerRoutingPolicy=preserve_reviewer_routing / approvalPolicy=preserve_approval_state`,偏好关闭只静默页面内提醒,不隐藏 reviewerRouting、approval、evidence 或 audit state;ReleaseGrowthPage 当前消费 `releaseGate` 与 `failureAlert` 两个偏好,只静默强调型提醒,不隐藏 release evidence、阻塞原因、审计状态、validation run、releaseSignals 或下一轮 ChangeSet draft;这些 helper 只控制本地 UI 提醒消费合同,不代表真实邮件、桌面推送或系统通知中心已接入
|
||||||
- PMFlow OS 产品页入口:参考 `frontend/src/features/pmflow-os/pages/CommandCenterPage.tsx`、`StructuredExtractionPage.tsx`、`ChangeReviewPage.tsx`、`MemoryWritebackResultPage.tsx`、`WorkGraphPage.tsx`、`ExecutionBridgePage.tsx`、`ReleaseGrowthPage.tsx`、`TeamLayerPage.tsx`、`ProjectMemoryPage.tsx`、`AccountPage.tsx`;`ChangeReviewPage.tsx` 真实模式可对当前 ChangeSet 请求审查、通过、要求修改或拒绝,展示审查状态、建议 reviewer、审查意见和 high-risk approval gate,但不自动 commit;`TeamLayerPage.tsx` 真实模式读取 `state.reviewerRouting` 展示 ready/empty/warning、待审 ChangeSet、来源(下一轮迭代 / AI 提取 / 手动)、风险等级、建议审查人或 fallback role、审查原因、待审 item 数、证据数、审查状态、审查意见、请求/决策时间,并跳转 `/change-review?projectId=<id>&changeSetId=<id>`;`ReleaseGrowthPage.tsx` 真实模式展示 `execution-summary.releaseGate`、execution evidence、阻塞原因、下一步动作、`latestValidationRun` 和 `releaseSignals`,缺证据或缺发布后信号时显示 empty/warning,不展示 mock 发布结果;页面可调用真实 API 创建 release validation run、摄取 release feedback,从真实 recommendation 单条或同组批量生成下一轮待确认 ChangeSet draft,并解释 `iteration_recommendation_group` evidence 的组、反馈、风险、影响和审查优先级;生成后仍进入 Change Review accept/edit/defer,不自动 commit、不写 Project Memory、不执行部署命令、不接外部支付;同时消费 Account notification preference helper,`releaseGate` 关闭时静默发布门禁强调提醒,`failureAlert` 关闭时静默失败强调提醒,所有真实证据和审计状态仍可见;静态高保真发布/增长数据仅保留在显式 demo 模式
|
- PMFlow OS 产品页入口:参考 `frontend/src/features/pmflow-os/pages/CommandCenterPage.tsx`、`StructuredExtractionPage.tsx`、`ChangeReviewPage.tsx`、`MemoryWritebackResultPage.tsx`、`WorkGraphPage.tsx`、`ExecutionBridgePage.tsx`、`ReleaseGrowthPage.tsx`、`TeamLayerPage.tsx`、`ProjectMemoryPage.tsx`、`AccountPage.tsx`;`ChangeReviewPage.tsx` 真实模式可对当前 ChangeSet 请求审查、通过、要求修改或拒绝,展示审查状态、建议 reviewer、审查意见和 high-risk approval gate,但不自动 commit;`TeamLayerPage.tsx` 真实模式读取 `state.reviewerRouting` 展示 ready/empty/warning、待审 ChangeSet、来源(下一轮迭代 / AI 提取 / 手动)、风险等级、建议审查人或 fallback role、审查原因、待审 item 数、证据数、审查状态、审查意见、请求/决策时间,并跳转 `/change-review?projectId=<id>&changeSetId=<id>`;`ReleaseGrowthPage.tsx` 真实模式展示 `execution-summary.releaseGate`、execution evidence、阻塞原因、下一步动作、`latestValidationRun` 和 `releaseSignals`,缺证据或缺发布后信号时显示 empty/warning,不展示 mock 发布结果;页面可调用真实 API 创建 release validation run、摄取 release feedback,从真实 recommendation 单条或同组批量生成下一轮待确认 ChangeSet draft,并解释 `iteration_recommendation_group` evidence 的组、反馈、风险、影响和审查优先级;生成后仍进入 Change Review accept/edit/defer,不自动 commit、不写 Project Memory、不执行部署命令、不接外部支付;同时消费 Account notification preference helper,`releaseGate` 关闭时静默发布门禁强调提醒,`failureAlert` 关闭时静默失败强调提醒,所有真实证据和审计状态仍可见;静态高保真发布/增长数据仅保留在显式 demo 模式
|
||||||
|
- Team Feed 只读动态流:`TeamLayerPage.tsx` 复用 `frontend/src/features/pmflow-os/components/TeamFeedPanel.tsx` 展示 `state.feed`,由后端 `ProjectTruthState.feed` 聚合 review request、review decision、ChangeSet 状态、execution progress 与 release gate 事件;前端只做空态、摘要和跳转展示,不写审批、不写 ChangeSet、不写通知,也不在真实模式 fallback 到 mock 动态。
|
||||||
- PMFlow OS 行为组件:参考 `frontend/src/features/pmflow-os/components/ProjectStructuredLoop.tsx`、`ProjectStageRail.tsx`、`ThreadComposer.tsx`、`ExtractionRail.tsx`、`ChangeGroupPanel.tsx`、`ObjectGraphSection.tsx`、`ContextPacketPanel.tsx`、`ExecutionTimeline.tsx`、`ReleaseGatePanel.tsx`、`TeamFeedPanel.tsx`、`ChangeReviewGroup.tsx`、`WorkbenchPanel.tsx`、`ExecutionBridgeCards.tsx`、`PMFlowOsFrame.tsx`、`AccountControls.tsx`、`FeedbackPrimitives.tsx`、`MobileBottomNav.tsx`;其中 `ProjectStructuredLoop.tsx` 承接 `StatusLabel / EvidenceSnippet / ObjectChangeCard / ProjectConversationPanel / StructuredExtractionPanel / ProjectAICopilotPanel`,`PMFlowOsFrame.tsx` 承接项目内面包屑和项目切换器,`AccountControls.tsx` 承接桌面头像菜单、退出登录确认与移动端 bottom sheet,`FeedbackPrimitives.tsx` 承接 `PageBanner / InlineNotice / HumanDecisionBar / ConfirmDialog / MobileBottomSheet`,`MobileBottomNav.tsx` 承接正式应用壳移动端固定底部导航
|
- PMFlow OS 行为组件:参考 `frontend/src/features/pmflow-os/components/ProjectStructuredLoop.tsx`、`ProjectStageRail.tsx`、`ThreadComposer.tsx`、`ExtractionRail.tsx`、`ChangeGroupPanel.tsx`、`ObjectGraphSection.tsx`、`ContextPacketPanel.tsx`、`ExecutionTimeline.tsx`、`ReleaseGatePanel.tsx`、`TeamFeedPanel.tsx`、`ChangeReviewGroup.tsx`、`WorkbenchPanel.tsx`、`ExecutionBridgeCards.tsx`、`PMFlowOsFrame.tsx`、`AccountControls.tsx`、`FeedbackPrimitives.tsx`、`MobileBottomNav.tsx`;其中 `ProjectStructuredLoop.tsx` 承接 `StatusLabel / EvidenceSnippet / ObjectChangeCard / ProjectConversationPanel / StructuredExtractionPanel / ProjectAICopilotPanel`,`PMFlowOsFrame.tsx` 承接项目内面包屑和项目切换器,`AccountControls.tsx` 承接桌面头像菜单、退出登录确认与移动端 bottom sheet,`FeedbackPrimitives.tsx` 承接 `PageBanner / InlineNotice / HumanDecisionBar / ConfirmDialog / MobileBottomSheet`,`MobileBottomNav.tsx` 承接正式应用壳移动端固定底部导航
|
||||||
- PMFlow OS 原型状态回归测试:参考 `frontend/src/features/pmflow-os/store.test.ts`;真实 API 动作回归参考 `frontend/src/features/pmflow-os/store.api.test.tsx`
|
- PMFlow OS 原型状态回归测试:参考 `frontend/src/features/pmflow-os/store.test.ts`;真实 API 动作回归参考 `frontend/src/features/pmflow-os/store.api.test.tsx`
|
||||||
- Space 工作面回归测试:参考 `frontend/src/features/personal-space/PersonalSpacePage.test.tsx`,覆盖空态、导航只读约束、发布/反馈/迭代草案队列,以及 reviewerRouting -> `review_attention` 的 next action 聚合排序与 `/change-review`、`/team-layer` 跳转合同。
|
- Space 工作面回归测试:参考 `frontend/src/features/personal-space/PersonalSpacePage.test.tsx`,覆盖空态、导航只读约束、发布/反馈/迭代草案队列,以及 reviewerRouting -> `review_attention` 的 next action 聚合排序与 `/change-review`、`/team-layer` 跳转合同。
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ function formatFeedKind(kind: PMFlowFeedEvent["kind"]) {
|
||||||
test: "测试",
|
test: "测试",
|
||||||
release: "发布",
|
release: "发布",
|
||||||
growth: "增长",
|
growth: "增长",
|
||||||
|
agent: "智能体",
|
||||||
};
|
};
|
||||||
return labelMap[kind];
|
return labelMap[kind];
|
||||||
}
|
}
|
||||||
|
|
@ -35,16 +36,22 @@ export function TeamFeedPanel({
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-1 text-sm text-slate-500">团队看到的不是任务拖拽,而是项目真相层最近发生了什么。</div>
|
<div className="mt-1 text-sm text-slate-500">团队看到的不是任务拖拽,而是项目真相层最近发生了什么。</div>
|
||||||
<div className="mt-4 space-y-3">
|
<div className="mt-4 space-y-3">
|
||||||
{feed.map((item) => (
|
{feed.length > 0 ? (
|
||||||
|
feed.map((item) => (
|
||||||
<article key={item.id} className="rounded-[18px] border border-[#e8eef8] bg-[#fbfdff] px-4 py-4">
|
<article key={item.id} className="rounded-[18px] border border-[#e8eef8] bg-[#fbfdff] px-4 py-4">
|
||||||
<div className="flex items-center justify-between gap-3">
|
<div className="flex items-center justify-between gap-3">
|
||||||
<div className="text-sm font-semibold text-slate-950">{item.title}</div>
|
<div className="text-sm font-semibold text-slate-950">{item.title}</div>
|
||||||
<ToneChip label={formatFeedKind(item.kind)} tone={statusTone(item.kind === "test" ? "testing" : "confirmed")} />
|
<ToneChip label={formatFeedKind(item.kind)} tone={statusTone(item.kind === "test" ? "testing" : "confirmed")} />
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 text-sm leading-6 text-slate-500">{item.summary}</div>
|
<div className="mt-2 text-sm leading-6 text-slate-500">{item.summary}</div>
|
||||||
<div className="mt-3 text-[11px] uppercase tracking-[0.18em] text-slate-500">{item.timestamp}</div>
|
<div className="mt-3 text-[11px] uppercase tracking-[0.18em] text-slate-500">{formatFeedTimestamp(item.timestamp)}</div>
|
||||||
</article>
|
</article>
|
||||||
))}
|
))
|
||||||
|
) : (
|
||||||
|
<div className="rounded-[18px] border border-dashed border-[#d8e3f4] bg-[#fbfdff] px-4 py-6 text-sm leading-6 text-slate-500">
|
||||||
|
当前还没有可聚合的团队动态。Team Feed 只展示真实 review、执行和发布门禁事件,不使用 mock 动态。
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<div className="grid gap-4">
|
<div className="grid gap-4">
|
||||||
|
|
@ -57,10 +64,10 @@ export function TeamFeedPanel({
|
||||||
title="角色收件箱"
|
title="角色收件箱"
|
||||||
icon={Inbox}
|
icon={Inbox}
|
||||||
rows={[
|
rows={[
|
||||||
`产品:${inbox.product[0]}`,
|
`产品:${inbox.product[0] || "暂无待处理项"}`,
|
||||||
`工程:${inbox.engineering[0]}`,
|
`工程:${inbox.engineering[0] || "暂无待处理项"}`,
|
||||||
`测试:${inbox.qa[0]}`,
|
`测试:${inbox.qa[0] || "暂无待处理项"}`,
|
||||||
`增长:${inbox.growth[0]}`,
|
`增长:${inbox.growth[0] || "暂无待处理项"}`,
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<RoleInboxPanel
|
<RoleInboxPanel
|
||||||
|
|
@ -78,6 +85,13 @@ export function TeamFeedPanel({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatFeedTimestamp(value: string) {
|
||||||
|
if (!value) return "时间待回写";
|
||||||
|
const date = new Date(value);
|
||||||
|
if (Number.isNaN(date.getTime())) return value;
|
||||||
|
return date.toLocaleString("zh-CN", { hour12: false });
|
||||||
|
}
|
||||||
|
|
||||||
function RoleInboxPanel({
|
function RoleInboxPanel({
|
||||||
title,
|
title,
|
||||||
icon: Icon,
|
icon: Icon,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import {
|
||||||
X,
|
X,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { TeamFeedPanel } from "@/features/pmflow-os/components/TeamFeedPanel";
|
||||||
import { usePMFlowOsStore } from "@/features/pmflow-os/store";
|
import { usePMFlowOsStore } from "@/features/pmflow-os/store";
|
||||||
import type { PMFlowReviewerRouting, PMFlowReviewerRoutingItem, PMFlowRiskLevel } from "@/features/pmflow-os/types";
|
import type { PMFlowReviewerRouting, PMFlowReviewerRoutingItem, PMFlowRiskLevel } from "@/features/pmflow-os/types";
|
||||||
|
|
||||||
|
|
@ -73,11 +74,7 @@ export default function TeamLayerPage() {
|
||||||
warnings={reviewerWarnings}
|
warnings={reviewerWarnings}
|
||||||
onOpenReview={handleOpenReview}
|
onOpenReview={handleOpenReview}
|
||||||
/>
|
/>
|
||||||
<div className="grid gap-4 lg:grid-cols-3">
|
<TeamFeedPanel feed={state.feed} inbox={state.teamInbox} />
|
||||||
<TeamActivityPanel />
|
|
||||||
<DecisionPanel />
|
|
||||||
<RoleInboxPanel />
|
|
||||||
</div>
|
|
||||||
<AgentWorkstationPanel />
|
<AgentWorkstationPanel />
|
||||||
</main>
|
</main>
|
||||||
<div className="hidden min-[1440px]:block">
|
<div className="hidden min-[1440px]:block">
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,22 @@ function realState(): ProjectTruthState {
|
||||||
sourceLabel: "项目线程",
|
sourceLabel: "项目线程",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
state.feed = [
|
||||||
|
{
|
||||||
|
id: "review-request-11",
|
||||||
|
kind: "review",
|
||||||
|
title: "已请求 ChangeSet 审查",
|
||||||
|
summary: "真实变更集 已请求 审查负责人 审查;包含 high risk 变更。",
|
||||||
|
timestamp: "2026-04-26T10:00:00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "release-gate-blocked",
|
||||||
|
kind: "release",
|
||||||
|
title: "发布门禁已阻塞",
|
||||||
|
summary: "执行回写中存在失败或阻塞事件,发布门禁已关闭。",
|
||||||
|
timestamp: "2026-04-26T11:00:00",
|
||||||
|
},
|
||||||
|
];
|
||||||
state.reviewerRouting = reviewerRoutingFixture();
|
state.reviewerRouting = reviewerRoutingFixture();
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
@ -543,6 +559,8 @@ describe("PMFlowOsProvider real change review actions", () => {
|
||||||
expect(screen.getByText("REVIEWER")).toBeInTheDocument();
|
expect(screen.getByText("REVIEWER")).toBeInTheDocument();
|
||||||
expect(screen.getByText("下一轮迭代")).toBeInTheDocument();
|
expect(screen.getByText("下一轮迭代")).toBeInTheDocument();
|
||||||
expect(screen.getByText("证据 1")).toBeInTheDocument();
|
expect(screen.getByText("证据 1")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("已请求 ChangeSet 审查")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("发布门禁已阻塞")).toBeInTheDocument();
|
||||||
expect(screen.getAllByText("待我审").length).toBeGreaterThan(0);
|
expect(screen.getAllByText("待我审").length).toBeGreaterThan(0);
|
||||||
fireEvent.click(screen.getByRole("button", { name: /去审查/ }));
|
fireEvent.click(screen.getByRole("button", { name: /去审查/ }));
|
||||||
await waitFor(() => expect(screen.getByTestId("location").textContent).toBe("/change-review?projectId=123&changeSetId=11"));
|
await waitFor(() => expect(screen.getByTestId("location").textContent).toBe("/change-review?projectId=123&changeSetId=11"));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue