diff --git a/apps/presentation/dashboard/src/features/personal-workspace/explore-finding-copy.ts b/apps/presentation/dashboard/src/features/personal-workspace/explore-finding-copy.ts index 1c15bd7e53..f9ca4ecb13 100644 --- a/apps/presentation/dashboard/src/features/personal-workspace/explore-finding-copy.ts +++ b/apps/presentation/dashboard/src/features/personal-workspace/explore-finding-copy.ts @@ -2,10 +2,12 @@ * These labels do not classify evidence or schedule verification. */ export function exploreFindingCopy(zh: boolean) { return zh ? { + count: (value: number) => `${value} 条结论`, labels: {tentative: "暂定结论", confirmed: "来源记为确认", refuted: "已反驳"}, help: "结论状态说明", meaning: "暂定结论表示来源尚未确认或反驳该结论,可能已有观测与证据;不表示有检查任务排队。确认与反驳也仅表示来源在所述适用范围内的判断,不等于独立验证或目标完成。研究问题是否收束、下一步继续或转向,分别记录。", } : { + count: (value: number) => `${value} ${value === 1 ? "finding" : "findings"}`, labels: {tentative: "Tentative", confirmed: "Recorded confirmation", refuted: "Refuted"}, help: "About finding states", meaning: "Tentative means the source has not confirmed or refuted the finding; observations and evidence may already exist. It does not mean a check is queued. Confirmation and refutation are source judgments within the stated scope, not independent verification or Goal completion. Question closure and the decision to continue or replan are recorded separately.", diff --git a/apps/presentation/dashboard/src/features/personal-workspace/goal-research-history.tsx b/apps/presentation/dashboard/src/features/personal-workspace/goal-research-history.tsx index 9bfdf53841..e7b74a9db3 100644 --- a/apps/presentation/dashboard/src/features/personal-workspace/goal-research-history.tsx +++ b/apps/presentation/dashboard/src/features/personal-workspace/goal-research-history.tsx @@ -100,17 +100,17 @@ export function GoalResearchHistory({goalId, active, zh, refreshRevision = 0, re title: "研究历程", loading: "正在读取完整记录", reading: "读取中", refresh: "刷新记录", all: "回到全图", scope: "Explore 已记录历史", coverage: "其他来源覆盖、尝试发生时序尚未核验", partial: "历史尚未完整载入", failure: "无法继续读取历史。已读记录保留;请重试。", - time: "记录时间(本地)", unknown: "时间未记录", records: "条记录", evidence: "已记录依据", + time: "记录时间(本地)", unknown: "时间未记录", record: "条记录", records: "条记录", evidence: "已记录依据", interpretation: "独立检查与实际采用尚未核验", versions: "来源与版本引用", updates: "历史记录", - changes: "次记录", findings: "条结论", links: "显式关联", missing: "部分关联的来源节点尚未记录", + changes: "次记录", question: "个问题", questions: "个问题", links: "显式关联", missing: "部分关联的来源节点尚未记录", group: "来源分组", lost: "当前记录中找不到所选节点,其他历史仍可浏览。", } : { title: "Research history", loading: "Reading the full recorded history", reading: "Reading", refresh: "Refresh history", all: "Whole graph", scope: "Recorded Explore history", coverage: "Other-source coverage and attempt-time coverage are unverified", partial: "History is not fully loaded", failure: "Cannot continue reading history. Loaded records remain; retry.", - time: "Recorded time (local)", unknown: "Time not recorded", records: "records", evidence: "Recorded evidence", + time: "Recorded time (local)", unknown: "Time not recorded", record: "record", records: "records", evidence: "Recorded evidence", interpretation: "Independent checking and actual adoption are unverified", versions: "Source and version references", updates: "History", - changes: "records", findings: "findings", links: "Explicit relationships", missing: "Some linked source nodes are not recorded", + changes: "records", question: "question", questions: "questions", links: "Explicit relationships", missing: "Some linked source nodes are not recorded", group: "Source grouping", lost: "The selected node is absent from this snapshot. Other history remains readable.", }; // Labels reuse Explore's existing vocabulary; they confer no verification state. @@ -415,12 +415,12 @@ export function GoalResearchHistory({goalId, active, zh, refreshRevision = 0, re {node.latest.node_kind === "experiment" ? : }{kindLabel(node.latest.node_kind)}{stateLabel(node.latest.status)} {node.latest.title}{measured ? {measured.metric} {formatExploreMeasurementValue(measured.latest.measurement.value, zh)} · best {formatExploreMeasurementValue(measured.best?.value ?? null, zh)} {measured.higher_is_better ? "↑" : "↓"} - : {node.updates.length > 1 ? ` · ${node.updates.length} ${copy.changes}` : ""}{node.findings.length ? ` · ${node.findings.length} ${copy.findings}` : ""}} + : {node.updates.length > 1 ? ` · ${node.updates.length} ${copy.changes}` : ""}{node.findings.length ? ` · ${findingCopy.count(node.findings.length)}` : ""}} })} {grouped.groups.map((group, index) => )} ; @@ -475,7 +475,7 @@ export function GoalResearchHistory({goalId, active, zh, refreshRevision = 0, re

{copy.time}{value?.startAt ? <> · — : null} · {busy ? `${copy.reading} ${loaded}${read.total ? ` / ${read.total}` : ""}` : read.total === null ? (zh ? "来源尚未读到" : "Source has not been read") - : `${read.events.length} / ${read.total} ${copy.records}${read.complete ? "" : ` · ${copy.partial}`}`}

+ : `${read.events.length} / ${read.total} ${read.total === 1 ? copy.record : copy.records}${read.complete ? "" : ` · ${copy.partial}`}`}

{!readingSelection ? displayControl : null}
{readFailure ?
@@ -570,7 +570,7 @@ export function GoalResearchHistory({goalId, active, zh, refreshRevision = 0, re {displayControl}
    {selectedMembers.map(node =>
  1. )}
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/goal-research-timeline.tsx b/apps/presentation/dashboard/src/features/personal-workspace/goal-research-timeline.tsx index fea0ae8c92..e3ac2b3a02 100644 --- a/apps/presentation/dashboard/src/features/personal-workspace/goal-research-timeline.tsx +++ b/apps/presentation/dashboard/src/features/personal-workspace/goal-research-timeline.tsx @@ -35,23 +35,23 @@ export function GoalResearchTimeline({timeline, zh, selectedIds, selectedEventId }, [timeline.start, timeline.end]); const findingCopy = exploreFindingCopy(zh); const copy: Copy = zh ? { - early: "前段", middle: "中段", late: "后段", items: "研究项", findings: "结论", + early: "前段", middle: "中段", late: "后段", item: "研究项", items: "研究项", question: "个问题", questions: "个问题", decisions: "显式决策", none: "未记录显式决策", changed: "变化", stopped: "停止", retained: "保留", unstructured: "决策未结构化", unstructuredHint: "结论未按 writeback 结构记录,无法拆出依据与决策。", density: "记录密度", densityHint: "柱高为事件数;浅红为无记录空档", ticks: "转向 / 继续", routes: "研究路线", routeHint: "仅由显式关联或父子分组相连", singles: "未关联研究项", - trail: "决策轨迹", more: "显示更早记录", moreQuestions: "显示更多问题", records: "条决策记录", unknownTime: "时间未知", all: "全部时段", + trail: "决策轨迹", more: "显示更早记录", moreQuestions: "显示更多问题", record: "条决策记录", records: "条决策记录", unknownTime: "时间未知", all: "全部时段", span: "记录跨度", start: "起点", end: "末端", replan: "转向", continue: "继续", stop: "停止", wait: "等待", no_change: "无变化", ask_human: "请人决定", ...findingCopy.labels, unlabeled: "无结论", phaseNote: "按记录时间三等分,仅为阅读分组,不是预声明的评估窗口。", noTime: "没有可用的记录时间,无法放上时间轴;下方记录仍可完整阅读。", whole: "全程", } : { - early: "Early", middle: "Middle", late: "Late", items: "Research items", findings: "Findings", + early: "Early", middle: "Middle", late: "Late", item: "Research item", items: "Research items", question: "question", questions: "questions", decisions: "Explicit decisions", none: "No explicit decision recorded", changed: "Changed", stopped: "Stopped", retained: "Retained", unstructured: "Unstructured decisions", unstructuredHint: "Findings were not recorded in writeback sections; evidence and decisions cannot be separated.", density: "Recording density", densityHint: "Bar height is events; pale red is a recording gap", ticks: "Replan / continue", routes: "Research routes", routeHint: "Connected only by recorded relationships or parent grouping", singles: "Unlinked research items", - trail: "Decision history", more: "Show earlier records", moreQuestions: "Show more questions", records: "decision records", unknownTime: "Unknown time", all: "Whole history", + trail: "Decision history", more: "Show earlier records", moreQuestions: "Show more questions", record: "decision record", records: "decision records", unknownTime: "Unknown time", all: "Whole history", span: "Recorded span", start: "Start", end: "End", replan: "Replan", continue: "Continue", stop: "Stop", wait: "Wait", no_change: "No change", ask_human: "Ask human", ...findingCopy.labels, unlabeled: "No finding", phaseNote: "Equal thirds of record time, for reading only; not a pre-declared evaluation window.", noTime: "No usable record time; the history cannot be placed on a time axis. All records remain readable below.", @@ -96,7 +96,7 @@ export function GoalResearchTimeline({timeline, zh, selectedIds, selectedEventId const counts = Object.entries(item.decisions); return [ `${timeLabel(item.start)} — ${timeLabel(item.end)}`, - `${item.nodes} ${copy.items} · ${item.findings} ${copy.findings}`, + `${item.nodes} ${item.nodes === 1 ? copy.item : copy.items} · ${findingCopy.count(item.findings)}`, LABELS.map(key => `${label(key)} ${item.labels[key] ?? 0}`).join(" · "), timeline.decisions.length ? (counts.length ? `${copy.decisions} · ${counts.map(([key, value]) => `${label(key)} ${value}`).join(" · ")}` : (timeline.structuredCount ? copy.none : copy.unstructured)) : null, ].filter(Boolean).join(" · "); @@ -105,7 +105,7 @@ export function GoalResearchTimeline({timeline, zh, selectedIds, selectedEventId return )}
+ onClick={() => onGroupSelect(group.day)}>{group.nodes.length} {group.nodes.length === 1 ? copy.question : copy.questions})} : null} {swarm.length ? <>
{copy.singles} · {swarm.length}
@@ -233,7 +233,7 @@ function TrailQuestion({group, copy, label, timeLabel, selectedEventId, onSelect return
  • {group.title}

    -
    {group.items.length} {copy.records} +
    {group.items.length} {group.items.length === 1 ? copy.record : copy.records} {knownTimes.length ? {timeLabel(knownTimes.at(-1)!)}{knownTimes.length > 1 ? ` — ${timeLabel(knownTimes[0]!)}` : ""} : null} {knownTimes.length < group.items.length ? {copy.unknownTime} · {group.items.length - knownTimes.length} : null} {exceptions.map(({status, count}) => {label(status)} {count})} diff --git a/docs/development/assets/runtime-source-analysis/research-count-labels/after-en-1440-overview.png b/docs/development/assets/runtime-source-analysis/research-count-labels/after-en-1440-overview.png new file mode 100644 index 0000000000..c207450f48 Binary files /dev/null and b/docs/development/assets/runtime-source-analysis/research-count-labels/after-en-1440-overview.png differ diff --git a/docs/development/assets/runtime-source-analysis/research-count-labels/after-en-1440-questions.png b/docs/development/assets/runtime-source-analysis/research-count-labels/after-en-1440-questions.png new file mode 100644 index 0000000000..92f50edfcd Binary files /dev/null and b/docs/development/assets/runtime-source-analysis/research-count-labels/after-en-1440-questions.png differ diff --git a/docs/development/assets/runtime-source-analysis/research-count-labels/after-en-390-questions.png b/docs/development/assets/runtime-source-analysis/research-count-labels/after-en-390-questions.png new file mode 100644 index 0000000000..3f64460c8a Binary files /dev/null and b/docs/development/assets/runtime-source-analysis/research-count-labels/after-en-390-questions.png differ diff --git a/docs/development/assets/runtime-source-analysis/research-count-labels/after-zh-CN-1440-questions.png b/docs/development/assets/runtime-source-analysis/research-count-labels/after-zh-CN-1440-questions.png new file mode 100644 index 0000000000..9a46e35ef2 Binary files /dev/null and b/docs/development/assets/runtime-source-analysis/research-count-labels/after-zh-CN-1440-questions.png differ diff --git a/docs/development/assets/runtime-source-analysis/research-count-labels/after-zh-CN-390-overview.png b/docs/development/assets/runtime-source-analysis/research-count-labels/after-zh-CN-390-overview.png new file mode 100644 index 0000000000..a740a46e12 Binary files /dev/null and b/docs/development/assets/runtime-source-analysis/research-count-labels/after-zh-CN-390-overview.png differ diff --git a/docs/development/assets/runtime-source-analysis/research-count-labels/before-en-1440-overview.png b/docs/development/assets/runtime-source-analysis/research-count-labels/before-en-1440-overview.png new file mode 100644 index 0000000000..81502c3d60 Binary files /dev/null and b/docs/development/assets/runtime-source-analysis/research-count-labels/before-en-1440-overview.png differ diff --git a/docs/development/assets/runtime-source-analysis/research-count-labels/before-en-1440-questions.png b/docs/development/assets/runtime-source-analysis/research-count-labels/before-en-1440-questions.png new file mode 100644 index 0000000000..47d215717c Binary files /dev/null and b/docs/development/assets/runtime-source-analysis/research-count-labels/before-en-1440-questions.png differ diff --git a/docs/development/assets/runtime-source-analysis/research-count-labels/before-en-390-questions.png b/docs/development/assets/runtime-source-analysis/research-count-labels/before-en-390-questions.png new file mode 100644 index 0000000000..ecf1009cfa Binary files /dev/null and b/docs/development/assets/runtime-source-analysis/research-count-labels/before-en-390-questions.png differ