Add source citation copy for Ranker handoff

This commit is contained in:
OpenClaw Bot
2026-05-27 14:51:20 +02:00
parent 3ff7272720
commit 8e6040e90c
+22
View File
@@ -197,10 +197,29 @@ function renderLane(ranked, laneId) {
`;
}
function sourceCitation(data) {
const brief = data.brief || {};
const source = brief.source || data.handoff?.source || data.input?.provenance || {};
const trace = brief.quickGlance?.sourceTrace || {};
const parts = [
source.artifactId ? `Artifact: ${source.artifactId}` : '',
source.conceptMapId ? `Concept Map: ${source.conceptMapId}` : '',
source.snapshotTitle ? `Title: ${source.snapshotTitle}` : '',
trace.sourceSection ? `Source section: ${trace.sourceSection}` : '',
trace.sourceId ? `Source item: ${trace.sourceId}` : '',
trace.sourceTitle ? `Source title: ${trace.sourceTitle}` : '',
trace.sourceQuote ? `Source quote: ${trace.sourceQuote}` : '',
source.originalPromptExcerpt ? `Original prompt: ${source.originalPromptExcerpt}` : '',
].filter(Boolean);
return parts.length ? parts.join('\n') : 'No source citation was carried into this result.';
}
function markdownBrief(data) {
const brief = data.brief || {};
const glance = brief.quickGlance || {};
const ranked = data.ranked || [];
const citation = sourceCitation(data);
const hasCitation = !citation.startsWith('No source citation');
const lanes = ['do', 'test', 'defer', 'park'];
const laneTitles = { do: 'Do first', test: 'Validate next', defer: 'Defer', park: 'Park / cut' };
return [
@@ -215,6 +234,7 @@ function markdownBrief(data) {
`- Evidence question: ${glance.evidenceQuestion || 'n/a'}`,
`- Biggest trap: ${glance.biggestTrap || 'n/a'}`,
`- Confidence: ${data.rankConfidence?.level || 'n/a'}${data.rankConfidence?.reason || ''}`,
...(hasCitation ? ['', '## Source citation', citation] : []),
'',
...lanes.flatMap((lane) => {
const items = ranked.filter((item) => item.lane?.id === lane);
@@ -238,6 +258,7 @@ function attachResultActions(data) {
document.querySelector('#copyBrief')?.addEventListener('click', () => copyText(markdownBrief(data), 'Decision brief'));
document.querySelector('#copyActions')?.addEventListener('click', () => copyText((data.brief?.next48Hours || []).map((step, index) => `${index + 1}. ${step}`).join('\n'), '48h actions'));
document.querySelector('#copyJson')?.addEventListener('click', () => copyText(JSON.stringify({ brief: data.brief, ranked: data.ranked, buildOrder: data.buildOrderDetails, handoff: data.handoff }, null, 2), 'JSON handoff'));
document.querySelector('#copySource')?.addEventListener('click', () => copyText(sourceCitation(data), 'Source citation'));
}
function renderResults(data) {
@@ -266,6 +287,7 @@ function renderResults(data) {
<button class="button ghost" type="button" id="copyBrief">Copy decision brief</button>
<button class="button ghost" type="button" id="copyActions">Copy 48h actions</button>
<button class="button ghost" type="button" id="copyJson">Copy JSON handoff</button>
<button class="button ghost" type="button" id="copySource">Copy source citation</button>
</div>
<div class="lane-board">