Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
.research-analysis { margin-block: 16px; padding: 24px; border: 1px solid var(--pw-line); border-radius: 12px; min-width: 0; color: var(--pw-text); background: var(--pw-bg); font-size: var(--text-body); line-height: var(--leading-prose); overflow-wrap: anywhere; }
.research-analysis > header, .analysis-source > header { display: flex; align-items: start; justify-content: space-between; gap: 16px; }
.analysis-header-actions { display: flex; gap: 8px; flex-shrink: 0; }
.analysis-report-title { display: flex; align-items: center; gap: 4px; }
.analysis-report-meta { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 16px; margin-block-start: 4px; }
.research-analysis .analysis-report-meta > p { margin: 0; font-size: var(--text-body); }
.analysis-report-meta > span { color: var(--pw-muted); font-size: var(--text-body); }
.research-analysis-entry { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.research-analysis-entry-actions, .analysis-scope { display: flex; align-items: center; gap: 4px; }
.research-analysis-entry > small { font-size: var(--text-caption); color: var(--pw-muted); }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useCallback, useEffect, useLayoutEffect, useRef, useState} from "react";
import {ArrowLeft, ArrowUpRight, ChevronDown, CircleHelp, LoaderCircle, RefreshCw, Sparkles, TriangleAlert, X} from "lucide-react";
import {ArrowLeft, ArrowUpRight, ChevronDown, CircleHelp, History, LoaderCircle, RefreshCw, Sparkles, TriangleAlert, X} from "lucide-react";
import type {AssessmentCitation, TrajectoryAssessment, TrajectoryEpisode, TrajectoryOutputLanguage, TrajectoryContinuation} from "../../../../../../loopx/control_plane/capabilities/trajectory_assessment_types.js";
import {ResearchProgress, episodeQuestionGroups, metricCopy, verdictLabel, type ResearchProgressPack} from "./goal-research-progress";
import {requestJson} from "../../data/chat";
Expand Down Expand Up @@ -487,18 +487,23 @@ export function ResearchAnalysisPanel({analysis: a, onHistory}: {analysis: Contr
: benefit?.unknown ? (zh ? "原目标收益的检验情况仍未知" : "Original-objective utility testing remains unknown")
: benefit?.yes ? (zh ? "模型记录了收益检验;这不等于收益为正" : "The model identified a utility test; this does not imply positive utility")
: (zh ? "此方法未覆盖原目标收益检验" : "This method does not cover original-objective utility testing");
const scope = p ? <>{p.episode_count} {zh ? "个研究片段" : "research episodes"} · {p.selection.exhaustive ? (zh ? "固定范围" : "Fixed scope") : (zh ? "定向抽样" : "Purposive sample")}</> : null;
const scopeHelp = p ? <ContextHelp label={zh ? "分析范围" : "Analysis scope"} icon={result?.synthesis ? Sparkles : undefined}>
{result?.synthesis ? <p><strong>{zh ? "Agent 分析 · 未校准" : "Agent analysis · uncalibrated"}</strong></p> : null}
<p>{p.selection.exhaustive ? (zh ? "覆盖此固定分析范围;不等于覆盖全部研究。" : "Covers this fixed analysis scope, not necessarily the whole research history.") : (zh ? "定向抽样,仅分析选定研究片段;范围外或未捕获的工作未纳入,不代表全程。" : "Purposive sample of selected episodes; work outside this scope or not captured is excluded. It does not represent the whole run.")}</p>
<p>{zh ? "正向诊断、证据采用与最终任务收益分别判断。没有综合分数,也不据此推断因果或整体研究质量。引用存在不代表模型解释已被独立核验。" : "Diagnostic value, evidence adoption and task utility are separate. There is no total score, causal claim or whole-run quality rating. Citations do not independently verify model interpretations."}</p>
{result ? Object.values(metricCopy).map(label => <p key={label[1]}><strong>{label[zh ? 0 : 1]}</strong> · {label[zh ? 2 : 3]}</p>) : null}
<p>{zh ? "下方仍显示当前研究 Goal 的已记录历史。" : "The current research Goal’s recorded history remains below."}</p>
</ContextHelp> : null;
return <div className={`research-analysis${result?.synthesis ? " has-synthesis" : ""}`} ref={a.panel} tabIndex={-1} role="region" aria-label={zh ? "轨迹深度分析" : "Trajectory analysis"} onKeyDown={event => {if (event.key === "Escape") {event.stopPropagation(); a.close();}}}>
<header><div><h3>{result?.synthesis ? (zh ? "研究汇报" : "Research report") : (zh ? "轨迹深度分析" : "Trajectory analysis")}</h3>{p?.title ? <p>{p.title}</p> : null}</div><div className="analysis-header-actions">{result?.synthesis && onHistory ? <button type="button" onClick={onHistory}>{zh ? "Goal 研究历程" : "Goal research history"}</button> : null}{result ? <button type="button" onClick={() => void a.read().catch(() => undefined)} aria-label={zh ? "刷新分析结果" : "Refresh analysis result"}><RefreshCw size={15} aria-hidden/></button> : null}<button type="button" onClick={a.close} aria-label={zh ? "关闭分析" : "Close analysis"}><X size={16} aria-hidden/></button></div></header>
<header><div>{result?.synthesis ? <><div className="analysis-report-title"><h3>{zh ? "研究汇报" : "Research report"}</h3>{scopeHelp}</div>
<div className="analysis-report-meta">{p?.title ? <p>{p.title}</p> : null}<span>{scope}</span></div></>
: <><h3>{zh ? "轨迹深度分析" : "Trajectory analysis"}</h3>{p?.title ? <p>{p.title}</p> : null}</>}</div><div className="analysis-header-actions">{result?.synthesis && onHistory ? <button type="button" onClick={onHistory} aria-label={zh ? "Goal 研究历程" : "Goal research history"} title={zh ? "Goal 研究历程" : "Goal research history"}><History size={16} aria-hidden/></button> : null}{result ? <button type="button" onClick={() => void a.read().catch(() => undefined)} aria-label={zh ? "刷新分析结果" : "Refresh analysis result"}><RefreshCw size={15} aria-hidden/></button> : null}<button type="button" onClick={a.close} aria-label={zh ? "关闭分析" : "Close analysis"}><X size={16} aria-hidden/></button></div></header>
{a.error ? <div className="analysis-error" role="alert">{zh ? "分析请求未完成,已保存结果保留。" : "The analysis request did not complete; saved results are preserved."} <button type="button" onClick={() => void a.read().catch(() => undefined)}>{zh ? "重试读取" : "Retry reading"}</button><ContextHelp label={zh ? "失败详情" : "Failure details"}><p>{a.error}</p></ContextHelp></div> : null}
{a.snapshot?.catalog.unreadable_pack_ids?.length && !p?.continuation_unavailable ? <p className="analysis-warning">{zh ? "部分历史分析暂不可读" : "Some historical analyses cannot be read"} · {a.snapshot.catalog.unreadable_pack_ids.length}</p> : null}
<AnalysisReadState analysis={a}/>
{p ? <>
<div className="analysis-scope">{p.episode_count} {zh ? "个研究片段" : "research episodes"} · {p.selection.exhaustive ? (zh ? "固定范围" : "Fixed scope") : (zh ? "定向抽样" : "Purposive sample")}<ContextHelp label={zh ? "分析范围" : "Analysis scope"}>
<p>{p.selection.exhaustive ? (zh ? "覆盖此固定分析范围;不等于覆盖全部研究。" : "Covers this fixed analysis scope, not necessarily the whole research history.") : (zh ? "定向抽样,仅分析选定研究片段;范围外或未捕获的工作未纳入,不代表全程。" : "Purposive sample of selected episodes; work outside this scope or not captured is excluded. It does not represent the whole run.")}</p>
<p>{zh ? "正向诊断、证据采用与最终任务收益分别判断。没有综合分数,也不据此推断因果或整体研究质量。引用存在不代表模型解释已被独立核验。" : "Diagnostic value, evidence adoption and task utility are separate. There is no total score, causal claim or whole-run quality rating. Citations do not independently verify model interpretations."}</p>
{result ? Object.values(metricCopy).map(label => <p key={label[1]}><strong>{label[zh ? 0 : 1]}</strong> · {label[zh ? 2 : 3]}</p>) : null}
<p>{zh ? "下方仍显示当前研究 Goal 的已记录历史。" : "The current research Goal’s recorded history remains below."}</p>
</ContextHelp></div>
{!result?.synthesis ? <div className="analysis-scope">{scope}{scopeHelp}</div> : null}
<AnalysisContinuation pack={p} analysis={a}/>
{p.result && !sourceAvailable ? <p className="analysis-warning">{reasonCopy(p.reason_code, zh)}</p> : null}
{p.result_attempt && p.result_attempt !== p.job?.attempt ? <ContextHelp label={zh ? "本次分析未完成" : "Current analysis incomplete"} icon={TriangleAlert}><p className="analysis-warning" role="status">{zh ? "当前重试尚未完成,显示上次已保存分析。" : "The current retry is incomplete; showing the previously saved analysis."}</p></ContextHelp> : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@
.research-reading-order button { min-height: 44px; padding: 6px 0; background: none; border: 0; color: var(--pw-text); font: inherit; font-size: var(--text-body); cursor: pointer; }
.research-reading-order > span { color: var(--pw-muted); }
.research-reading-layer { min-width: 0; scroll-margin-block-start: 16px; }
.research-reading-layer .research-synthesis { margin-block: 24px 32px; }
.research-reading-layer .research-synthesis:not(.research-synthesis-detail) { margin-block: 24px 32px; }
.research-reading-layer:focus, .research-history-heading:focus { outline: none; }

@media (max-width: 640px) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
.research-synthesis { margin-block: 24px; max-width: 82ch; color: var(--pw-text); font-size: var(--text-lead); line-height: var(--leading-prose); overflow-wrap: anywhere; }
.research-synthesis > header { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 16px; }
.research-synthesis > header { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.research-synthesis :is(h3,h4,h5,h6) { margin: 0; color: var(--pw-text); font-size: inherit; font-weight: 600; line-height: var(--leading-body); }
.research-synthesis > header > span { color: var(--pw-muted); font-size: var(--text-body); }
.research-synthesis .research-synthesis-summary { margin-block: 12px 8px; }
.research-synthesis p, .research-progress .research-synthesis p, .research-analysis .research-synthesis p { margin-block: 8px 12px; font-size: var(--text-lead); color: var(--pw-text); }
.research-synthesis summary { cursor: pointer; min-height: 44px; padding-block: 10px; }
Expand All @@ -21,11 +20,12 @@
.research-synthesis button:hover { text-decoration: underline; text-underline-offset: 3px; }
.research-synthesis .research-review-episodes { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 4px 0; border: 0; background: none; color: var(--pw-text); font: inherit; font-size: var(--text-body); cursor: pointer; }
.research-synthesis button:focus-visible, .research-synthesis summary:focus-visible { outline: 2px solid var(--pw-blue); outline-offset: 2px; }
.research-synthesis-detail { max-width: none; }
.research-synthesis-detail { max-width: none; margin-block-start: 16px; }
.research-report-tabs { display: flex; gap: 24px; border-block-end: 1px solid var(--pw-line); margin-block: 16px; }
.research-report-tabs > button { min-height: 44px; border: 0; border-block-end: 2px solid transparent; padding: 10px 0; background: none; color: var(--pw-muted); font: inherit; cursor: pointer; }
.research-report-tabs > button[aria-selected="true"] { border-block-end-color: var(--pw-text); color: var(--pw-text); }
.research-report-tabs > button > span { margin-inline-start: 8px; color: var(--pw-muted); font-size: var(--text-body); }
.research-synthesis-detail .research-report-tabs { margin-block-start: 0; }
.research-synthesis .research-report-tabs > button { min-height: 44px; border: 0; border-block-end: 2px solid transparent; border-radius: 0; padding: 10px 0; background: none; color: var(--pw-muted); font: inherit; cursor: pointer; }
.research-synthesis .research-report-tabs > button[aria-selected="true"] { border-block-end-color: var(--pw-text); color: var(--pw-text); }
.research-synthesis .research-report-tabs > button > span { margin-inline-start: 8px; color: var(--pw-muted); font-size: var(--text-body); }
.research-report-comparison { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }
.research-report-finding, .research-report-experiment { border-block-start: 1px solid var(--pw-line); padding-block: 16px; }
.research-report-finding > h5, .research-report-experiment h5 { margin-block-end: 8px; }
Expand All @@ -39,12 +39,12 @@
@media (max-width: 640px) {
.research-analysis.has-synthesis > header { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
.research-analysis.has-synthesis > header > div:first-child { display: contents; }
.research-analysis.has-synthesis > header h3 { grid-column: 1; grid-row: 1; align-self: center; }
.research-analysis.has-synthesis > header p { grid-column: 1 / -1; grid-row: 2; }
.research-analysis.has-synthesis > header .analysis-report-title { grid-column: 1; grid-row: 1; }
.research-analysis.has-synthesis > header .analysis-report-meta { grid-column: 1 / -1; grid-row: 2; }
.research-analysis.has-synthesis > header .analysis-header-actions { grid-column: 2; grid-row: 1; }
.research-report-comparison { grid-template-columns: 1fr; gap: 12px; }
.research-synthesis dl { grid-template-columns: 1fr; gap: 4px; }
.research-synthesis dd { margin-block-end: 12px; }
.research-synthesis > header { gap: 4px 12px; }
.research-synthesis > header { gap: 4px; }
}
.research-synthesis-detail { container-type: inline-size; }
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {useId, useState, type ReactNode} from "react";
import {ArrowDownRight, ArrowUpRight} from "lucide-react";
import {ArrowDownRight, ArrowUpRight, Sparkles} from "lucide-react";
import type {AssessmentCitation, TrajectoryResearchSynthesis} from "../../../../../../loopx/control_plane/capabilities/trajectory_assessment_types.js";
import {ContextHelp} from "./context-help";
import "./goal-research-synthesis.css";

type Props = {synthesis: TrajectoryResearchSynthesis; zh: boolean; detail?: boolean;
Expand Down Expand Up @@ -78,9 +79,12 @@ export function ResearchSynthesis({synthesis: s, zh, detail = false, onExpand, o
</>;
}
return <section className={`research-synthesis${detail ? " research-synthesis-detail" : ""}`} aria-label={zh ? "研究汇报" : "Research report"}>
<header>{!detail ? <h3>{zh ? "研究汇报" : "Research report"}</h3> : null}<span>{zh ? "Agent 分析" : "Agent analysis"}</span>
{!detail && onExpand ? <button type="button" className="research-report-expand" onClick={event => onExpand(event.currentTarget)}>{zh ? "深入解读" : "Read deeper"}<ArrowUpRight size={14} aria-hidden/></button> : null}
</header>
{!detail ? <header><h3>{zh ? "研究汇报" : "Research report"}</h3>
<ContextHelp label={zh ? "Agent 分析 · 未校准" : "Agent analysis · uncalibrated"} icon={Sparkles}>
<p>{zh ? "此汇报是 Agent 对选定证据的分析;引用可读不等于解释已被独立核验。" : "This report is the Agent’s analysis of selected evidence; readable citations do not independently verify its interpretation."}</p>
</ContextHelp>
{onExpand ? <button type="button" className="research-report-expand" onClick={event => onExpand(event.currentTarget)}>{zh ? "深入解读" : "Read deeper"}<ArrowUpRight size={14} aria-hidden/></button> : null}
</header> : null}
{!detail ? overview : null}
{body}
</section>;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading