fix(awooop): reduce run detail text density
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m0s
CD Pipeline / build-and-deploy (push) Successful in 4m32s
CD Pipeline / post-deploy-checks (push) Successful in 1m42s

This commit is contained in:
Your Name
2026-07-03 15:46:06 +08:00
parent 821455eb7d
commit c45264224a
3 changed files with 93 additions and 102 deletions

View File

@@ -13100,60 +13100,60 @@
} }
}, },
"ownerResponseValidationDetailBoundary": { "ownerResponseValidationDetailBoundary": {
"title": "負責人回覆驗收詳情邊界", "title": "Controlled Apply Evidence Boundary",
"subtitle": "單一執行詳情同步顯示 S4.13 驗收彙整與S4.9-S4.12 四包來源回覆仍只可讀;這不是此 Run的審批、補救、MCP 執行、專案庫、分支 / 標籤參照、工作流程 / 機密設定或執行期授權。", "subtitle": "The run detail keeps S4.13 / S4.9-S4.12 as evidence ledger only; low / medium / high risk work must not stop on owner 0/false fields and should proceed after AI completes selector, dry-run, rollback, verifier, and writeback.",
"badge": "只讀詳情邊界", "badge": "Controlled ledger",
"openIwooos": "開啟 IwoooS", "openIwooos": "Open IwoooS",
"detailRefsTitle": "詳情驗收參照", "detailRefsTitle": "Evidence ledger refs",
"boundaryLabel": "驗收 / 詳情邊界", "boundaryLabel": "Controlled apply boundary",
"boundaryTitle": "目前沒有負責人回覆驗收詳情可執行動作", "boundaryTitle": "Owner fields are evidence, not terminal blockers",
"boundaryDetail": "這個區塊只說明此 Run 詳情如何理解四包、24 個回覆範本、已收到 / 已接受 / 已拒收仍為 0以及驗收資訊與執行時間線尚未連成授權不建立審批紀錄、不啟動 MCP或補救、不建立平台執行、不接執行路由器、不建立專案庫、不改分支 / 標籤參照、不改工作流程 / 機密設定、不收機密明文值、不切主要來源,也不開執行期閘門。", "boundaryDetail": "Except critical / break-glass paths, 0/false only means evidence is incomplete; AI must complete the controlled apply package, verifier, rollback, and KM / PlayBook writeback.",
"metrics": { "metrics": {
"packets": { "packets": {
"label": "回覆包", "label": "Evidence packs",
"detail": "S4.9-S4.12 四包仍等待負責人回覆。" "detail": "S4.9-S4.12 packs stay as evidence ledger."
}, },
"templates": { "templates": {
"label": "回覆範本", "label": "Templates",
"detail": "24 個範本只代表未來可收件格式,不代表此 Run 已收到回覆。" "detail": "22 templates describe intake shape, not a manual stop."
}, },
"received": { "received": {
"label": "已收到", "label": "Received",
"detail": "目前仍為 0詳情頁不得把可視性改寫成收件狀態。" "detail": "Still 0; this triggers evidence completion, not a controlled-apply stop."
}, },
"accepted": { "accepted": {
"label": "已接受", "label": "Accepted",
"detail": "目前仍為 0只有脫敏證據通過驗收後才能改變。" "detail": "Still 0; low / medium / high risk work routes to verifier / rollback completion."
}, },
"validationRuns": { "validationRuns": {
"label": "驗收執行", "label": "Validation runs",
"detail": "目前仍為 0此詳情卡不建立新的平台執行。" "detail": "Still 0; this card does not create a new platform run."
}, },
"displaySections": { "displaySections": {
"label": "顯示區塊", "label": "Sections",
"detail": "8 個顯示區塊只用於說明驗收流程與詳情邊界。" "detail": "8 sections remain as scan-first evidence readback."
} }
}, },
"detailRefs": { "detailRefs": {
"validationRollup": { "validationRollup": {
"title": "S4.13 驗收彙整", "title": "S4.13 validation rollup",
"detail": "固定四包、跨包驗收、證據路由、審查清單與結果分流,但不產生此 Run的審批或補救執行。" "detail": "Fixed four-pack validation, evidence routing, review checklist, and outcome lanes."
}, },
"giteaAttestation": { "giteaAttestation": {
"title": "S4.9 Gitea 清冊負責人證明", "title": "S4.9 Gitea inventory evidence",
"detail": "5 個範本仍等待負責人回覆;詳情頁只能標記下一個收件焦點。" "detail": "Five templates are Gitea evidence ledger, not a blocker for low / medium / high controlled apply."
}, },
"githubTarget": { "githubTarget": {
"title": "S4.10 GitHub 目標負責人決策", "title": "S4.10 retired GitHub target evidence",
"detail": "9 個目標負責人 / 可見性 / 標準回覆仍未接受,不得自動建立專案庫或執行紀錄。" "detail": "GitHub remains frozen / do_not_use; this is history ledger, not an active target."
}, },
"refsTruth": { "refsTruth": {
"title": "S4.11 分支 / 標籤真相負責人回覆", "title": "S4.11 refs truth evidence",
"detail": "5 類真相判定仍等待脫敏回覆,不得同步、刪除或強制推送分支 / 標籤參照。" "detail": "Five truth categories remain redacted evidence; force-push and ref destruction still require break-glass."
}, },
"workflowSecret": { "workflowSecret": {
"title": "S4.12 工作流程 / 機密名稱負責人回覆", "title": "S4.12 workflow / secret-name evidence",
"detail": "5 類名稱與脫敏證據仍等待回覆;只允許名稱清冊,不允許機密明文值。" "detail": "Only name inventory and redacted evidence are allowed; raw secret values are not collected."
} }
} }
}, },
@@ -13380,7 +13380,7 @@
"agent": "Agent", "agent": "Agent",
"tool": "工具", "tool": "工具",
"scope": "範圍", "scope": "範圍",
"blockers": "卡點", "blockers": "AI follow-up",
"legacy": { "legacy": {
"only": "自建 MCP 已觀測", "only": "自建 MCP 已觀測",
"total": "自建 MCP", "total": "自建 MCP",
@@ -13460,36 +13460,36 @@
} }
}, },
"action": { "action": {
"eyebrow": "下一步判斷", "eyebrow": "Next action",
"approval": { "approval": {
"title": "等待 AI 受控審批", "title": "Waiting for AI controlled approval",
"detail": "AI 已停在 controlled gate,尚未恢復執行。請從審批頁 approvereject 或排入 verifier / rollback,所有決策都會回寫執行狀態與 audit", "detail": "The run is parked at a controlled gate. Approve, reject, or route verifier / rollback from approvals; each decision writes back to run state and audit.",
"primary": "前往審批決策" "primary": "Open approvals"
}, },
"manual": { "controlled": {
"title": "AI 補齊接手", "title": "AI controlled follow-up",
"detail": "AI 尚未安全閉環,或執行已失敗 / 超時。請回 Run 監控比對同專案任務,排入 PlayBookrollbackverifier break-glass", "detail": "Failed, blocked, and timed-out runs enter controlled follow-up: PlayBook, rollback, verifier, MCP evidence, and KM / trust writeback. Only critical paths move to break-glass.",
"primary": "回 Run 監控" "primary": "Back to runs"
}, },
"completed": { "completed": {
"title": "已完成,等待稽核回看", "title": "Completed, ready for audit",
"detail": "Run 已收斂。請以時間線檢查 MCP、出站訊息與成本紀錄是否完整必要時再回寫 KM / Playbook", "detail": "The run converged. Review timeline, MCP, outbound messages, and cost records, then write back KM / PlayBook when needed.",
"primary": "回 Run 監控" "primary": "Back to runs"
}, },
"running": { "running": {
"title": "AI 正在處理", "title": "AI processing",
"detail": "Run 尚未結束,頁面會定期刷新。若長時間停留在 running請檢查 heartbeatMCP latencyworker 狀態。", "detail": "The run is still active and refreshes automatically. If it stays running too long, inspect heartbeat, MCP latency, and worker state.",
"primary": "回 Run 監控" "primary": "Back to runs"
}, },
"observe": { "observe": {
"title": "觀察中", "title": "Observing",
"detail": "目前尚未進入 AI 受控隊列或終止狀態。請沿時間線確認入站事件、工具呼叫與出站訊息是否有缺口。", "detail": "The run has not entered a controlled queue or terminal state. Inspect inbound events, tool calls, and outbound gaps.",
"primary": "回 Run 監控" "primary": "Back to runs"
}, },
"evidence": { "evidence": {
"inbound": "入站事件", "inbound": "Inbound",
"outbound": "出站訊息", "outbound": "Outbound",
"mcp": "MCP 呼叫", "mcp": "MCP calls",
"steps": "Steps" "steps": "Steps"
} }
}, },

View File

@@ -13100,30 +13100,30 @@
} }
}, },
"ownerResponseValidationDetailBoundary": { "ownerResponseValidationDetailBoundary": {
"title": "負責人回覆驗收詳情邊界", "title": "Controlled Apply 證據詳情邊界",
"subtitle": "單一執行詳情同步顯示 S4.13 驗收彙整與S4.9-S4.12 四包來源回覆仍只可讀;這不是此 Run的審批、補救、MCP 執行、專案庫、分支 / 標籤參照、工作流程 / 機密設定或執行期授權。", "subtitle": "單一執行詳情只保留 S4.13 / S4.9-S4.12 evidence ledger低 / 中 / 高風險不因 owner 欄位 0/false 停止,改由 AI 補 selector、dry-run、rollback、verifier 與 writeback 後受控推進。",
"badge": "只讀詳情邊界", "badge": "Controlled ledger",
"openIwooos": "開啟 IwoooS", "openIwooos": "開啟 IwoooS",
"detailRefsTitle": "詳情驗收參照", "detailRefsTitle": "Evidence ledger 參照",
"boundaryLabel": "驗收 / 詳情邊界", "boundaryLabel": "Controlled apply 邊界",
"boundaryTitle": "目前沒有負責人回覆驗收詳情可執行動作", "boundaryTitle": "Owner 欄位只作 evidence不當終局阻擋",
"boundaryDetail": "這個區塊只說明此 Run 詳情如何理解四包、24 個回覆範本、已收到 / 已接受 / 已拒收仍為 0以及驗收資訊與執行時間線尚未連成授權不建立審批紀錄、不啟動 MCP或補救、不建立平台執行、不接執行路由器、不建立專案庫、不改分支 / 標籤參照、不改工作流程 / 機密設定、不收機密明文值、不切主要來源,也不開執行期閘門。", "boundaryDetail": "critical / break-glass 以外0/false 只代表證據尚未補齊AI 必須補 controlled apply package、verifier、rollback 與 KM / PlayBook writeback。",
"metrics": { "metrics": {
"packets": { "packets": {
"label": "回覆包", "label": "證據包",
"detail": "S4.9-S4.12 四包仍等待負責人回覆。" "detail": "S4.9-S4.12 四包作為 evidence ledger。"
}, },
"templates": { "templates": {
"label": "回覆範本", "label": "回覆範本",
"detail": "24 個範本只代表未來可收件格式,不代表此 Run 已收到回覆。" "detail": "22 個範本只代表收件格式,不代表停在人工。"
}, },
"received": { "received": {
"label": "已收到", "label": "已收到",
"detail": "目前仍為 0詳情頁不得把可視性改寫成收件狀態。" "detail": "目前仍為 0此值只觸發 AI 補 evidence不阻擋 controlled apply。"
}, },
"accepted": { "accepted": {
"label": "已接受", "label": "已接受",
"detail": "目前仍為 0只有脫敏證據通過驗收後才能改變。" "detail": "目前仍為 0低 / 中 / 高風險轉 verifier / rollback 補齊,不當終局。"
}, },
"validationRuns": { "validationRuns": {
"label": "驗收執行", "label": "驗收執行",
@@ -13131,29 +13131,29 @@
}, },
"displaySections": { "displaySections": {
"label": "顯示區塊", "label": "顯示區塊",
"detail": "8 個顯示區塊只用於說明驗收流程與詳情邊界。" "detail": "8 個區塊保留 scan-first evidence readback。"
} }
}, },
"detailRefs": { "detailRefs": {
"validationRollup": { "validationRollup": {
"title": "S4.13 驗收彙整", "title": "S4.13 驗收彙整",
"detail": "固定四包、跨包驗收、證據路由、審查清單與結果分流,但不產生此 Run的審批或補救執行。" "detail": "固定四包、跨包驗收、證據路由、審查清單與結果分流。"
}, },
"giteaAttestation": { "giteaAttestation": {
"title": "S4.9 Gitea 清冊負責人證明", "title": "S4.9 Gitea 清冊證據",
"detail": "5 個範本仍等待負責人回覆;詳情頁只能標記下一個收件焦點。" "detail": "5 個範本改作 Gitea evidence ledger不阻擋低 / 中 / 高 controlled apply。"
}, },
"githubTarget": { "githubTarget": {
"title": "S4.10 GitHub 目標負責人決策", "title": "S4.10 停用 GitHub 目標證據",
"detail": "9 個目標負責人 / 可見性 / 標準回覆仍未接受,不得自動建立專案庫或執行紀錄。" "detail": "GitHub 維持 freeze / do_not_use只保留歷史 ledger不作 active 目標。"
}, },
"refsTruth": { "refsTruth": {
"title": "S4.11 分支 / 標籤真相負責人回覆", "title": "S4.11 分支 / 標籤真相證據",
"detail": "5 類真相判定仍等待脫敏回覆,不得同步、刪除或強制推送分支 / 標籤參照。" "detail": "5 類真相判定只作脫敏 evidenceforce push / refs 破壞仍是 break-glass。"
}, },
"workflowSecret": { "workflowSecret": {
"title": "S4.12 工作流程 / 機密名稱負責人回覆", "title": "S4.12 Workflow / Secret 名稱證據",
"detail": "5 類名稱與脫敏證據仍等待回覆;只允許名稱清冊,不允許機密明文值。" "detail": "只允許名稱清冊與脫敏證據,不收機密明文值。"
} }
} }
}, },
@@ -13380,7 +13380,7 @@
"agent": "Agent", "agent": "Agent",
"tool": "工具", "tool": "工具",
"scope": "範圍", "scope": "範圍",
"blockers": "卡點", "blockers": "AI 補齊",
"legacy": { "legacy": {
"only": "自建 MCP 已觀測", "only": "自建 MCP 已觀測",
"total": "自建 MCP", "total": "自建 MCP",
@@ -13466,9 +13466,9 @@
"detail": "AI 已停在 controlled gate尚未恢復執行。請從審批頁 approve、reject 或排入 verifier / rollback所有決策都會回寫執行狀態與 audit。", "detail": "AI 已停在 controlled gate尚未恢復執行。請從審批頁 approve、reject 或排入 verifier / rollback所有決策都會回寫執行狀態與 audit。",
"primary": "前往審批決策" "primary": "前往審批決策"
}, },
"manual": { "controlled": {
"title": "AI 補齊接手", "title": "AI 受控補齊中",
"detail": "AI 尚未安全閉環,或執行已失敗 / 超時。請回 Run 監控比對同專案任務,排入 PlayBook、rollback、verifier 或 break-glass。", "detail": "失敗、阻塞或逾時會進 controlled follow-up補 PlayBook、rollback、verifier、MCP evidence 與 KM / trust writebackcritical 才進 break-glass。",
"primary": "回 Run 監控" "primary": "回 Run 監控"
}, },
"completed": { "completed": {
@@ -13478,7 +13478,7 @@
}, },
"running": { "running": {
"title": "AI 正在處理", "title": "AI 正在處理",
"detail": "Run 尚未結束,頁面會定期刷新。若長時間停留在 running請檢查 heartbeat、MCP latencyworker 狀態。", "detail": "Run 尚未結束,頁面會定期刷新。若長時間停留在 running請檢查 heartbeat、MCP latencyworker 狀態。",
"primary": "回 Run 監控" "primary": "回 Run 監控"
}, },
"observe": { "observe": {

View File

@@ -363,7 +363,7 @@ const SOURCE_REF_LABEL_KEYS: Record<string, string> = {
signoz_alerts: "refs.signozAlerts", signoz_alerts: "refs.signozAlerts",
}; };
const MANUAL_STATES = new Set(["blocked", "cancelled", "error", "failed", "timeout"]); const CONTROLLED_FOLLOWUP_STATES = new Set(["blocked", "cancelled", "error", "failed", "timeout"]);
function formatTime(value: string | null | undefined, locale: string, emptyLabel: string) { function formatTime(value: string | null | undefined, locale: string, emptyLabel: string) {
if (!value) return emptyLabel; if (!value) return emptyLabel;
@@ -447,12 +447,12 @@ function RunActionPanel({
} }
const isApproval = run.state === "waiting_approval"; const isApproval = run.state === "waiting_approval";
const isManual = MANUAL_STATES.has(run.state); const needsControlledFollowup = CONTROLLED_FOLLOWUP_STATES.has(run.state);
const isCompleted = run.state === "completed" || run.state === "success"; const isCompleted = run.state === "completed" || run.state === "success";
const actionKey = isApproval const actionKey = isApproval
? "approval" ? "approval"
: isManual : needsControlledFollowup
? "manual" ? "controlled"
: isCompleted : isCompleted
? "completed" ? "completed"
: run.state === "running" : run.state === "running"
@@ -460,7 +460,7 @@ function RunActionPanel({
: "observe"; : "observe";
const Icon = isApproval const Icon = isApproval
? ShieldCheck ? ShieldCheck
: isManual : needsControlledFollowup
? TriangleAlert ? TriangleAlert
: isCompleted : isCompleted
? CheckCircle2 ? CheckCircle2
@@ -469,8 +469,8 @@ function RunActionPanel({
: SearchCheck; : SearchCheck;
const toneClass = isApproval const toneClass = isApproval
? "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]" ? "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]"
: isManual : needsControlledFollowup
? "border-[#e2a29b] bg-[#fff0ef] text-[#9f2f25]" ? "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]"
: isCompleted : isCompleted
? "border-[#9bc7a4] bg-[#f0faf2] text-[#17602a]" ? "border-[#9bc7a4] bg-[#f0faf2] text-[#17602a]"
: "border-[#9bb6d9] bg-[#eef5ff] text-[#1f5b9b]"; : "border-[#9bb6d9] bg-[#eef5ff] text-[#1f5b9b]";
@@ -502,9 +502,6 @@ function RunActionPanel({
</h3> </h3>
</div> </div>
</div> </div>
<p className="mt-3 max-w-3xl text-sm leading-6 text-[#5f5b52]">
{t(`${actionKey}.detail` as never)}
</p>
</div> </div>
<Link <Link
href={primaryHref} href={primaryHref}
@@ -535,12 +532,12 @@ function RunActionPanel({
function OwnerResponseValidationDetailBoundaryPanel() { function OwnerResponseValidationDetailBoundaryPanel() {
const t = useTranslations("awooop.runDetail.ownerResponseValidationDetailBoundary"); const t = useTranslations("awooop.runDetail.ownerResponseValidationDetailBoundary");
const metrics = [ const metrics = [
{ label: t("metrics.packets.label"), value: "4", detail: t("metrics.packets.detail") }, { label: t("metrics.packets.label"), value: "4" },
{ label: t("metrics.templates.label"), value: "22", detail: t("metrics.templates.detail") }, { label: t("metrics.templates.label"), value: "22" },
{ label: t("metrics.received.label"), value: "0", detail: t("metrics.received.detail") }, { label: t("metrics.received.label"), value: "0" },
{ label: t("metrics.accepted.label"), value: "0", detail: t("metrics.accepted.detail") }, { label: t("metrics.accepted.label"), value: "0" },
{ label: t("metrics.validationRuns.label"), value: "0", detail: t("metrics.validationRuns.detail") }, { label: t("metrics.validationRuns.label"), value: "0" },
{ label: t("metrics.displaySections.label"), value: "8", detail: t("metrics.displaySections.detail") }, { label: t("metrics.displaySections.label"), value: "8" },
]; ];
return ( return (
@@ -551,7 +548,6 @@ function OwnerResponseValidationDetailBoundaryPanel() {
<ShieldCheck className="h-4 w-4 text-[#6d48a8]" aria-hidden="true" /> <ShieldCheck className="h-4 w-4 text-[#6d48a8]" aria-hidden="true" />
<h3 className="text-sm font-semibold text-[#141413]">{t("title")}</h3> <h3 className="text-sm font-semibold text-[#141413]">{t("title")}</h3>
</div> </div>
<p className="mt-2 text-sm leading-6 text-[#5f5b52]">{t("subtitle")}</p>
</div> </div>
<div className="flex flex-wrap items-center gap-2"> <div className="flex flex-wrap items-center gap-2">
<span className="border border-[#bda9df] bg-white px-2 py-1 text-xs font-semibold text-[#5c3b91]"> <span className="border border-[#bda9df] bg-white px-2 py-1 text-xs font-semibold text-[#5c3b91]">
@@ -572,7 +568,6 @@ function OwnerResponseValidationDetailBoundaryPanel() {
<div key={item.label} className="min-w-0 bg-white px-4 py-3"> <div key={item.label} className="min-w-0 bg-white px-4 py-3">
<p className="text-xs font-semibold text-[#77736a]">{item.label}</p> <p className="text-xs font-semibold text-[#77736a]">{item.label}</p>
<p className="mt-2 font-mono text-2xl font-semibold text-[#141413]">{item.value}</p> <p className="mt-2 font-mono text-2xl font-semibold text-[#141413]">{item.value}</p>
<p className="mt-2 text-xs leading-5 text-[#5f5b52]">{item.detail}</p>
</div> </div>
))} ))}
</div> </div>
@@ -588,9 +583,6 @@ function OwnerResponseValidationDetailBoundaryPanel() {
<p className="text-sm font-semibold text-[#141413]"> <p className="text-sm font-semibold text-[#141413]">
{t(`detailRefs.${item.key}.title` as never)} {t(`detailRefs.${item.key}.title` as never)}
</p> </p>
<p className="mt-1 text-xs leading-5 text-[#5f5b52]">
{t(`detailRefs.${item.key}.detail` as never)}
</p>
<p className="mt-2 text-xs text-[#77736a]">{publicContractText(item.contract)}</p> <p className="mt-2 text-xs text-[#77736a]">{publicContractText(item.contract)}</p>
</div> </div>
</div> </div>
@@ -604,7 +596,6 @@ function OwnerResponseValidationDetailBoundaryPanel() {
<span className="text-xs font-semibold text-[#5c3b91]">{t("boundaryLabel")}</span> <span className="text-xs font-semibold text-[#5c3b91]">{t("boundaryLabel")}</span>
</div> </div>
<h4 className="mt-2 text-base font-semibold text-[#141413]">{t("boundaryTitle")}</h4> <h4 className="mt-2 text-base font-semibold text-[#141413]">{t("boundaryTitle")}</h4>
<p className="mt-2 text-sm leading-6 text-[#5f5b52]">{t("boundaryDetail")}</p>
<div className="mt-4 space-y-1 font-mono text-xs leading-6 text-[#141413]"> <div className="mt-4 space-y-1 font-mono text-xs leading-6 text-[#141413]">
{ownerResponseValidationDetailBoundaries.map((item) => ( {ownerResponseValidationDetailBoundaries.map((item) => (
<div key={item} className="break-all"> <div key={item} className="break-all">
@@ -807,7 +798,7 @@ function McpGatewayPanel({
const legacySummary = legacy?.summary; const legacySummary = legacy?.summary;
const legacyTool = topLegacyTool(legacySummary); const legacyTool = topLegacyTool(legacySummary);
const toneClass = summary?.needs_human const toneClass = summary?.needs_human
? "border-[#e2a29b] bg-[#fff0ef] text-[#9f2f25]" ? "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]"
: summary?.stage_status === "success" : summary?.stage_status === "success"
? "border-[#9bc7a4] bg-[#f0faf2] text-[#17602a]" ? "border-[#9bc7a4] bg-[#f0faf2] text-[#17602a]"
: "border-[#9bb6d9] bg-[#eef5ff] text-[#1f5b9b]"; : "border-[#9bb6d9] bg-[#eef5ff] text-[#1f5b9b]";
@@ -859,7 +850,7 @@ function McpGatewayPanel({
))} ))}
</div> </div>
{hasRecords && summary?.blockers && summary.blockers.length > 0 && ( {hasRecords && summary?.blockers && summary.blockers.length > 0 && (
<div className="border-t border-[#eee9dd] bg-[#fff0ef] px-4 py-3 text-sm text-[#9f2f25]"> <div className="border-t border-[#eee9dd] bg-[#fff7e8] px-4 py-3 text-sm text-[#8a5a08]">
<span className="font-semibold">{t("blockers")}</span>{" "} <span className="font-semibold">{t("blockers")}</span>{" "}
<span className="text-xs">{publicInternalCodeSummary(summary.blockers.slice(0, 3))}</span> <span className="text-xs">{publicInternalCodeSummary(summary.blockers.slice(0, 3))}</span>
</div> </div>