){setBusy(true);setError('');setNotice('');try{await work();await refresh();}catch(e:any){setError(e.message);}finally{setBusy(false);}}
async function importFolder(){await action(async()=>{const files=await encodeFiles(pending);await send('POST','/library/skills/import',{project_id:project.id,files,required_field:requiredField||null});setPending([]);setNotice('标准 Skills 文件夹已保存,卡片以人工导入草稿进入池中。');});}
- async function create(){await action(async()=>{const content=kind==='skill'?{engine:'required',inputs:[field],code:'manual.'+field,title,instructions:instruction,description:instruction}:{effect:'advisory',on_match:'supplement',description:instruction,conditions:[{code:'manual.'+field,field,operator:'lt',threshold,title,suggestion:instruction}]};
+ async function create(){await action(async()=>{if(kind==='template'||kind==='data_card'){const content=kind==='template'?{sections:configuration.split('\n').filter(Boolean).map((line,index)=>({id:['overview','findings','judgment'][index]||'section'+index,title:line,dependencies:['*']})),instructions:instruction}:{source_id:sourceId,...JSON.parse(configuration)};await send('POST','/library/configuration/cards',{project_id:project.id,kind,name:title,content});setCreating(false);setNotice('人工配置已保存为草稿,评测通过并独立审核后才能发布。');return;}const content=kind==='skill'?{engine:'required',inputs:[field],code:'manual.'+field,title,instructions:instruction,description:instruction}:{effect:'advisory',on_match:'supplement',description:instruction,conditions:[{code:'manual.'+field,field,operator:'lt',threshold,title,suggestion:instruction}]};
await send('POST',`/prescreen/projects/${encodeURIComponent(project.id)}/knowledge-candidates`,{kind,title,origin:'manual',version:'1.0.0',content});setCreating(false);setNotice('人工草稿已进入卡片池,评测与独立审核后才可用于预审。');});}
async function transition(card:any,step:string){await action(async()=>{const result=await send('POST',`/prescreen/knowledge-candidates/${encodeURIComponent(card.id)}/transitions`,{action:step});setNotice(step==='evaluate'?(result.passed?'当前版本隔离评测通过。':'评测未通过:'+result.checks.map((c:any)=>c.detail||c.case).join(';')):'卡片已发布。');});}
async function revise(card:any){await action(async()=>{const changes:any={};if(samples.trim())changes.test_cases=JSON.parse(samples);await send('PATCH',`/prescreen/knowledge-candidates/${encodeURIComponent(card.id)}`,{requirement:revision,changes,note:revision||'补充独立测试样本',expected_revision:card.revision});setNotice('已保存草稿修订,需要重新评测。');});}
@@ -23,13 +23,14 @@ export default function KnowledgePools({project,identity,send,refreshKey=0}:any)
KNOWLEDGE ASSETS可复用的经验卡片池
来源颜色与风险等级分别表达;只有已发布卡片能装配 Agent。
{canEdit&&
}
{setPending(Array.from(e.target.files||[]));e.currentTarget.value='';}}/>
{error&&{error}
}{notice&&{notice}
}
- {[['skill','Skills'],['rule_set','Rules'],['data_card','数据卡片']].map(([key,label])=>)}
+ {[['skill','Skills'],['rule_set','Rules'],['data_card','数据卡片'],['template','模板语言卡']].map(([key,label])=>)}
{pending.length>0&&确认导入标准文件夹 · {pending.length} 个文件
{pending[0]?.webkitRelativePath.split('/')[0]} · 总计 {(pending.reduce((n,f)=>n+f.size,0)/1024).toFixed(1)} KB
{pending.slice(0,8).map(f=>- {f.webkitRelativePath}
)}
可绑定一个标准字段作为缺件核查入口;文件内容保留,工具白名单由系统限定。
}
- {creating&&kind!=='data_card'&&}
+ {creating&&['data_card','template'].includes(kind)&&人工创建{kind==='template'?'模板语言卡':'数据卡'}草稿
{kind==='data_card'&&}}
+ {creating&&['skill','rule_set'].includes(kind)&&}
{loading&&正在读取 SQLite 卡片版本…
}
{!loading&&!shown.length&&尚无{kind==='rule_set'?' Rules ':'此类'}卡片
可以提炼历史经验或人工创建;空池不会自动补成已发布卡片。
}
- {shown.map(card=>{const history=card.origin==='history_derived';const key=`${card.id}:${card.version}:${card.status}:${card.revision}`;return
{history?:} {history?'AI 提炼':card.import_method==='folder'?'文件夹导入':card.edited_by?'人工创建':'系统内置'}{card.status==='published'?'已发布':'草稿'} · v{card.version}
{card.name}
{card.description||card.instructions||'查看卡片依据与适用条件'}
{card.case_count?`来源 ${card.case_count} 条案例 · `:''}{card.engine==='model'?'模型方法':card.kind==='rule_set'?'建议规则':'受控核查'}{card.scope==='demo'?' · 模拟域':''}
{card.kind==='skill'&&}
- {expanded===key&&适用条件 {JSON.stringify(card.conditions||[])};例外 {card.exception_note||'未定义,须人工确认'}
来源 {(card.source_evidence_ids||[]).join('、')||'人工/内置配置'};版本哈希 {card.content_hash?.slice(0,16)}
{card.evaluation&&
隔离评测:{card.evaluation.passed?'通过':'未通过'}
}{canEdit&&card.status==='draft'&&<>
{card.edited_by!==identity?.id&&}
{card.edited_by===identity?.id&&
发布需要独立审核人:另一位配置管理员。
}>}
}
+ {shown.map(card=>{const history=card.origin==='history_derived';const key=`${card.id}:${card.version}:${card.status}:${card.revision}`;return
{history?:} {history?'AI 提炼':card.import_method==='folder'?'文件夹导入':card.edited_by?'人工创建':'系统内置'}{card.hidden?'已隐藏':card.status==='published'?'已发布':'草稿'} · v{card.version}
{card.name}
{card.description||card.instructions||'查看卡片依据与适用条件'}
{card.case_count?`来源 ${card.case_count} 条案例 · `:''}{card.engine==='model'?'模型方法':card.kind==='rule_set'?'建议规则':'受控核查'}{card.scope==='demo'?' · 模拟域':''}
{canEdit&&card.status==='published'&&}{card.kind==='skill'&&}
+ {expanded===key&&{card.kind==='template'&&
章节:{card.sections?.map((section:any)=>section.title).join(' → ')}。模板影响报告结构,不影响核查与概率。
}{card.kind==='data_card'&&
数据源 {card.source_id} · 查询与映射 {JSON.stringify(card.mapping)}
}
适用条件 {JSON.stringify(card.conditions||[])};例外 {card.exception_note||'未定义,须人工确认'}
来源 {(card.source_evidence_ids||[]).join('、')||'人工/内置配置'};版本哈希 {card.content_hash?.slice(0,16)}
{card.evaluation&&
隔离评测:{card.evaluation.passed?'通过':'未通过'}
}{canEdit&&card.status==='draft'&&<>{['skill','rule_set'].includes(card.kind)&&<>
>}
{card.edited_by!==identity?.id&&}
{card.edited_by===identity?.id&&
发布需要独立审核人:另一位配置管理员。
}>}
}
;})}
{opened&&setOpened(null)}/>}
;
diff --git a/src/components/xingbang/LeaseCaseDialog.tsx b/src/components/xingbang/LeaseCaseDialog.tsx
index f1546ac..296d51e 100644
--- a/src/components/xingbang/LeaseCaseDialog.tsx
+++ b/src/components/xingbang/LeaseCaseDialog.tsx
@@ -5,5 +5,5 @@ import {LeaseCase} from '@/lib/lease-library';
export default function LeaseCaseDialog({item,onClose}:{item:LeaseCase;onClose:()=>void}) {
const dialog=useRef(null);
useEffect(()=>{dialog.current?.showModal();},[]);
- return ;
+ return ;
}
diff --git a/src/components/xingbang/LeaseLibraryWorkbench.tsx b/src/components/xingbang/LeaseLibraryWorkbench.tsx
index 13d27dc..5140d54 100644
--- a/src/components/xingbang/LeaseLibraryWorkbench.tsx
+++ b/src/components/xingbang/LeaseLibraryWorkbench.tsx
@@ -31,7 +31,7 @@ export default function LeaseLibraryWorkbench({project,identity,send}:any) {
{preview&&解析条件:{mode==='sql'?preview.sql:JSON.stringify(preview.filters)}}{!canEdit&&客户经理可查看历史案例;经验加工由配置管理员操作。}
{error&&{error}
}{notice&&{notice}
}
{state==='loading'&&正在读取 SQLite 案例库…
}{state==='empty'&&没有符合条件的案例,请修改筛选。
}
-
+
实际 {items.length} 条 · 每页20条 · 第 {page+1}/{pages} 页 {source}
+
查看概率口径与情景计算依据
@@ -224,7 +226,7 @@ export default function PrescreenPanel({project, request, busy, setBusy, setErro
方案没有维度时不补占位轴,也不给出任何结论。
}
{shown.layout !== "empty" && <>
{shown.reason}
- {shown.layout === "radar" &&
}
+ {shown.layout === "radar" &&
r.id===run.id)?.steps||[]).map((s:any)=>[s.skill?.id||s.step_id,s.skill?.name||s.name]))} />}
{dimensions.map((item) => {
@@ -287,7 +289,7 @@ export default function PrescreenPanel({project, request, busy, setBusy, setErro
}
/** 六到八轴证据雷达。基线虚线、情景实线,旁边始终有等价文字列表。 */
-function RadarChart({dimensions, scenarioStages}: {dimensions: any[]; scenarioStages: Map
}) {
+function RadarChart({dimensions, scenarioStages, labels={}}: {dimensions: any[]; scenarioStages: Map; labels?:Record}) {
const radius = 90;
const count = dimensions.length;
const point = (index: number, stage: number | null) => {
@@ -304,9 +306,9 @@ function RadarChart({dimensions, scenarioStages}: {dimensions: any[]; scenarioSt
});
// 只有真的存在被假设的维度才画实线:没勾选时把基线复制成"所选情景"是误导
const hasScenario = Array.from(scenarioStages.values()).some((item) => item.assumed);
- return
+ return
虚线为基线,实线为所选假设;两者都只是阶段,不是分数。
diff --git a/src/components/xingbang/QualitySettings.tsx b/src/components/xingbang/QualitySettings.tsx
new file mode 100644
index 0000000..7252327
--- /dev/null
+++ b/src/components/xingbang/QualitySettings.tsx
@@ -0,0 +1,9 @@
+"use client";
+import {useEffect,useState} from 'react';
+import {ShieldCheck,Server,CircleOff,PlugZap} from 'lucide-react';
+export default function QualitySettings({send}:any){
+ const [value,setValue]=useState
(null),[key,setKey]=useState(''),[busy,setBusy]=useState(false),[message,setMessage]=useState(''),[error,setError]=useState('');
+ useEffect(()=>{send('GET','/library/quality/settings').then(setValue).catch((e:any)=>setError(e.message));},[]);
+ async function action(probe=false){setBusy(true);setError('');setMessage('');try{if(probe){const result=await send('POST','/library/quality/probe');setMessage(result.message);}else{const result=await send('PUT','/library/quality/settings',{provider:value.provider,endpoint:value.endpoint||'',model:value.model||'',allow_external:!!value.allow_external,...(key?{api_key:key}:{})});setValue(result);setKey('');setMessage('专项配置已保存,只影响后续质检。');}}catch(e:any){setError(e.message);}finally{setBusy(false);}}
+ return JUDGMENT PROVIDER专项判断与轨迹质检
主审由 miniOpenClaw 编排 Skills、Rules 和受控 Tools;这里检查编排过程是否完整、有据可查。
{error&&{error}
}{message&&{message}
}{!value?正在读取专项配置…
:<>{[['disabled','关闭专项模型',CircleOff],['local','本地兼容判断模型',Server],['jev','Jev · TypeSafe',ShieldCheck]].map(([id,label,Icon]:any)=>)}
{value.provider!=='disabled'&&}{value.provider==='jev'&&}前往轨迹质检 配置修订 v{value.revision} · {value.rubric_version} · 影子质检。连接通过不代表任务质量验证通过;关闭或失败均不产生默认分值。专项置信度不等于评审会通过概率。
>};
+}
diff --git a/src/components/xingbang/TrajectoryPanel.tsx b/src/components/xingbang/TrajectoryPanel.tsx
index 93076f2..a0b054c 100644
--- a/src/components/xingbang/TrajectoryPanel.tsx
+++ b/src/components/xingbang/TrajectoryPanel.tsx
@@ -72,8 +72,8 @@ export default function TrajectoryPanel({project, identity, send, view="all"}: a
useEffect(() => {
if (runs.length) {
const first = runs[0].id;
- setRunId(first);
- load(first);
+ const query=new URLSearchParams(location.search),requested=query.get("run");const target=runs.some((r:any)=>r.id===requested)?requested!:first;setRunId(target);setOpenStep(query.get("step")||"");
+ load(target);
} else {setTrajectory(null); setLoaded(true);}
setForm(EMPTY_FORM); setNotice("");
loadOutcomes();
diff --git a/src/components/xingbang/TrajectoryQualityPanel.tsx b/src/components/xingbang/TrajectoryQualityPanel.tsx
new file mode 100644
index 0000000..94d2cdd
--- /dev/null
+++ b/src/components/xingbang/TrajectoryQualityPanel.tsx
@@ -0,0 +1,11 @@
+"use client";
+import {useEffect,useRef,useState} from 'react';
+import {ScanLine,CheckCircle2,ArrowUpRight} from 'lucide-react';
+const labels:any={missing:'是否有未完成核查',unsupported:'是否有缺少证据引用的通过项',deviation:'是否执行了未冻结的组件'};
+export default function TrajectoryQualityPanel({project,send}:any){
+ const [runId,setRunId]=useState(''),[items,setItems]=useState([]),[busy,setBusy]=useState(false),[error,setError]=useState('');const ticket=useRef(0);
+ const runs=(project.runs||[]).filter((r:any)=>['completed','partial','failed','cancelled'].includes(r.status));
+ useEffect(()=>{const current=++ticket.current;setRunId(runs[0]?.id||'');setItems([]);setError('');send('GET',`/library/projects/${encodeURIComponent(project.id)}/quality`).then((data:any)=>{if(current===ticket.current)setItems(data.items);}).catch((e:any)=>{if(current===ticket.current)setError(e.message);});return()=>{ticket.current++;};},[project.id]);
+ async function inspect(){const current=ticket.current;setBusy(true);setError('');try{const row=await send('POST',`/library/projects/${encodeURIComponent(project.id)}/quality`,{run_id:runId});if(current===ticket.current)setItems(old=>[row,...old]);}catch(e:any){if(current===ticket.current)setError(e.message);}finally{setBusy(false);}}
+ return TRAJECTORY QUALITY这次核查过程,哪里需要改进
选择一次已结束的预审,检查缺漏、证据引用和组件版本,再定位到对应步骤。
01 选择运行→02 核查轨迹→03 回看问题步骤→04 人工提改进候选
{error&&{error}
}{!runs.length?先完成一次 AI 预审,再检查它的调用轨迹。
:<>>}{items.filter(r=>r.run_id===runId).map(row=>{row.config.provider==='disabled'?'规则审计':row.config.provider==='jev'?'Jev 专项质检':'本地模型专项质检'} · 配置 v{row.config.revision}{row.created_at.slice(0,16)}
{row.judgment.reason}
{row.checks.length?row.checks.map((c:any,index:number)=>{c.message}步骤 {c.step_id} · {c.code}定位步骤 ):规则审计未发现上述结构问题;不代表材料真实性已经核验。
}{Object.entries(row.judgment.answers||{}).map(([k,v]:any)=>{labels[k]}{v.metric==='boolean'?(v.value?'是':'否'):`判断为是:${Math.round(v.value*100)}%`}
)}{row.judgment.status==='failed'&&{row.judgment.code} · 未生成模型判断
}快照摘要 {row.input_hash.slice(0,16)} · 主审意见与概率保持原值 · 质检只读编排元数据)}{!items.length&&尚无质检记录。结果保留配置版本,可在后续会议结果对照时回看。
};
+}
diff --git a/src/components/xingbang/navigation.css b/src/components/xingbang/navigation.css
index 149709b..42c6ec4 100644
--- a/src/components/xingbang/navigation.css
+++ b/src/components/xingbang/navigation.css
@@ -19,3 +19,5 @@
.xb-role-switch>span{font-size:12px}.xb-role-switch select{font-size:14px;cursor:pointer}
.xb-overview-heading h1{font-size:30px;line-height:1.35}.xb-overview-heading p{font-size:14px;line-height:1.75;color:#667970}
@media(max-width:760px){.xb-agent-nav a{font-size:12px;min-height:38px;padding:8px}.xb-brand b{font-size:14px}.xb-overview-heading h1{font-size:26px}}
+
+.xb-extra-nav{margin:8px 0}.xb-extra-nav>summary{font-size:12px;cursor:pointer;padding:10px 12px;color:#B5C9BE}.xb-extra-nav>a{display:flex;align-items:center;gap:10px;padding:11px 12px;border-radius:8px;font-size:13px;color:#B5C9BE}.xb-extra-nav>a:hover,.xb-extra-nav>a.selected{background:#244D41;color:#FFF}
diff --git a/src/components/xingbang/v2-workbench.css b/src/components/xingbang/v2-workbench.css
index 1fd5457..d9868f0 100644
--- a/src/components/xingbang/v2-workbench.css
+++ b/src/components/xingbang/v2-workbench.css
@@ -25,3 +25,11 @@
@media(max-width:900px){.xb-v2 .xb-agent-nav{width:190px;padding:22px 12px}.xb-v2 .ra-main{margin-left:190px;padding:24px 20px}.v2-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}.v2-card-grid,.v2-assembly-grid{grid-template-columns:minmax(0,1fr)}.v2-section-heading{align-items:start;flex-wrap:wrap}}
@media(max-width:760px){.xb-v2 .xb-agent-nav{position:relative;width:100%;flex-direction:row;flex-wrap:wrap;align-items:center;padding:12px;gap:6px}.xb-v2 .xb-agent-nav .xb-brand{width:100%;padding:4px 6px 14px}.xb-v2 .xb-agent-nav a{font-size:12px;min-height:40px;padding:9px}.xb-v2 .xb-nav-group,.xb-v2 .xb-project-context,.xb-v2 .xb-nav-spacer{display:none}.xb-v2 .xb-agent-nav .xb-role-switch{margin:6px 0}.xb-v2 .xb-role-switch>span{width:auto}.xb-v2 .ra-main{margin:0;padding:24px 16px}.v2-metrics{gap:10px}.v2-metrics article{padding:14px}.v2-surface,.xb-v2 .xb-panel,.xb-v2 .xb-task{padding:18px}.v2-steps{display:block}.v2-steps li{margin-bottom:16px}.v2-form-grid,.v2-file-layout,.v2-comparison-grid{grid-template-columns:1fr}.v2-file-layout aside{border-right:0;border-bottom:1px solid var(--v2-line)}.v2-probability{padding:18px;gap:16px;flex-wrap:wrap}}
@media(prefers-reduced-motion:reduce){.xb-v2 *{animation:none!important;transition:none!important;scroll-behavior:auto!important}}
+
+.v2-environment{font-size:12px;color:var(--v2-muted);border:1px solid var(--v2-line);border-radius:999px;padding:7px 12px;white-space:nowrap;background:var(--v2-surface)}
+.v2-provider-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;margin:22px 0}.v2-provider{display:flex;flex-direction:column;gap:12px;align-items:flex-start;border:1px solid var(--v2-line);background:var(--v2-surface);border-radius:12px;padding:22px;text-align:left;color:var(--v2-muted)}.v2-provider b{font-size:15px;color:var(--v2-text)}.v2-provider small{font-size:12px}.v2-provider.selected{border-color:var(--v2-primary);background:var(--v2-bg);box-shadow:inset 0 0 0 1px var(--v2-primary);color:var(--v2-primary)}
+.v2-quality-flow{display:flex;gap:12px;align-items:center;flex-wrap:wrap;padding:18px;border-radius:10px;background:var(--v2-bg);margin:20px 0;color:var(--v2-muted);font-size:13px}.v2-quality-flow i{font-style:normal}.v2-quality-report{border:1px solid var(--v2-line);border-radius:12px;padding:22px;margin-top:20px}.v2-quality-report>p{margin:16px 0;color:var(--v2-muted);font-size:13px}.v2-quality-report>small{display:block;margin-top:16px;color:var(--v2-muted);font-size:11px}.v2-quality-issue{display:flex;flex-wrap:wrap;gap:10px;align-items:center;padding:14px 0;border-bottom:1px solid var(--v2-line)}.v2-quality-issue b{font-size:13px;flex:1;min-width:250px}.v2-quality-issue small,.v2-quality-issue a{font-size:12px;color:var(--v2-muted)}.v2-quality-issue a{display:flex;gap:4px;color:var(--v2-primary)}.v2-quality-answer{display:flex;justify-content:space-between;gap:16px;font-size:13px;padding:12px;border-radius:7px;background:var(--v2-bg);margin-top:10px}
+.v2-influences{margin:28px 0}.v2-influence-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}.v2-influence{background:var(--v2-surface);border:1px solid var(--v2-line);border-radius:12px;padding:20px}.v2-influence.blocked{border-color:var(--v2-ai)}.v2-influence h4{margin:15px 0 12px;font-size:15px}.v2-influence>small{display:block;margin-top:14px;font-size:11px;color:var(--v2-muted)}.v2-stage-change{display:flex;gap:8px;align-items:center;font-size:12px;color:var(--v2-muted)}.v2-scenario-stage{color:var(--v2-primary)}.v2-check-result{font-size:13px;border-top:1px solid var(--v2-line);padding-top:12px;margin-top:12px}.v2-check-result p{margin:8px 0}.v2-check-result small{font-size:11px;color:var(--v2-muted)}.v2-result{font-size:11px;background:var(--v2-bg);border-radius:5px;padding:4px 8px}.v2-result.result-pass{color:var(--v2-primary)}.v2-result.result-issue,.v2-result.result-error{color:var(--v2-ai)}.v2-advice{color:var(--v2-muted);line-height:1.7}.v2-assistant-entry{display:block;border:1px solid var(--v2-line);border-radius:10px;padding:15px 20px;background:var(--v2-surface);margin:18px 0;color:var(--v2-primary);font-size:13px}.v2-assembly-grid{grid-template-columns:repeat(4,minmax(0,1fr))}.xb-v2 button:focus-visible,.xb-v2 a:focus-visible,.xb-v2 input:focus-visible,.xb-v2 select:focus-visible{outline:2px solid var(--v2-primary);outline-offset:3px}
+@media(max-width:1100px){.v2-assembly-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:700px){.v2-provider-grid,.v2-influence-grid,.v2-assembly-grid{grid-template-columns:1fr}.v2-quality-flow{gap:8px}}
+
+.v2-radar{padding:24px;background:radial-gradient(ellipse at center,#EDF5F1 0%,var(--v2-surface) 72%);border:1px solid var(--v2-line);border-radius:12px;margin:18px 0;text-align:center}.v2-radar svg{max-width:100%;height:auto;color:var(--v2-primary)}.v2-radar polygon[data-series="baseline"]{stroke:var(--v2-muted);stroke-width:1.5;fill:#52675C0B}.v2-radar polygon[data-series="scenario"]{stroke:var(--v2-primary);stroke-width:2.5;fill:#17634C;fill-opacity:.18}.v2-radar p{font-size:12px;color:var(--v2-muted);margin-top:12px}