From 5cd5dd2fcf0b24f4661fc70fe19d9777a6de1a86 Mon Sep 17 00:00:00 2001 From: OpenClaw Bot Date: Wed, 27 May 2026 15:30:34 +0200 Subject: [PATCH] Expose Ranker source traces in result cards --- public/app.js | 34 +++++++++++++++++++++++++++++++--- public/index.html | 6 +++--- public/styles.css | 2 +- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/public/app.js b/public/app.js index dbceb23..48b427a 100644 --- a/public/app.js +++ b/public/app.js @@ -61,8 +61,13 @@ function parsePastedJsonPayload(value) { try { const parsed = JSON.parse(jsonText); const looksLikeBridgePayload = parsed && typeof parsed === 'object' && !Array.isArray(parsed) && ( - parsed.schema || parsed.featureSet || parsed.snapshot || parsed.conceptMap || parsed.buildOrder || parsed.lenses || parsed.reference_code || parsed.referenceCode || parsed.artifactId || parsed.ideaText - || Array.isArray(parsed.nextActions) || Array.isArray(parsed.nextMoves) || Array.isArray(parsed.validateNext) || Array.isArray(parsed.deferred) || Array.isArray(parsed.parkingLot) + parsed.schema || parsed.featureSet || parsed.feature_set || parsed.snapshot || parsed.conceptMap || parsed.concept_map || parsed.buildOrder || parsed.build_order || parsed.lenses + || parsed.payload || parsed.rankPayload || parsed.scattermindPayload || parsed.conceptMapJson + || parsed.reference_code || parsed.referenceCode || parsed.artifactId || parsed.sourceArtifactId || parsed.source_artifact_id + || parsed.ideaText || parsed.idea_text || parsed.originalPrompt || parsed.original_prompt || parsed.sourceSummary || parsed.source_summary || parsed.opening_reflection || parsed.restated_idea + || Array.isArray(parsed.features) || Array.isArray(parsed.actions) || Array.isArray(parsed.candidates) + || Array.isArray(parsed.nextActions) || Array.isArray(parsed.next_actions) || Array.isArray(parsed.nextMoves) || Array.isArray(parsed.next_moves) + || Array.isArray(parsed.validateNext) || Array.isArray(parsed.validate_next) || Array.isArray(parsed.deferred) || Array.isArray(parsed.parkingLot) || Array.isArray(parsed.parking_lot) ); return looksLikeBridgePayload ? parsed : null; } catch { @@ -105,7 +110,8 @@ function payloadFromForm(formPayload) { const optionsJson = parsePastedJsonPayload(formPayload.optionsText); const embedded = ideaJson || optionsJson; if (!embedded) return formPayload; - const merged = { ...embedded }; + const unwrapped = embedded.payload || embedded.rankPayload || embedded.scattermindPayload || embedded.conceptMapJson || embedded; + const merged = { ...unwrapped }; if (!merged.mode && formPayload.mode) merged.mode = formPayload.mode; if (String(formPayload.context || '').trim() && !merged.context) merged.context = formPayload.context; return merged; @@ -142,6 +148,26 @@ function renderSourceTrace(sourceTrace = {}) { `; } +function renderItemSourceTrace(item = {}) { + const provenance = item.provenance || {}; + const trace = { + sourceSection: provenance.sourceSection || '', + sourceId: provenance.sourceId || '', + sourceTitle: provenance.sourceTitle || '', + sourceQuote: provenance.sourceQuote || '', + }; + const hasTrace = trace.sourceSection || trace.sourceId || trace.sourceQuote; + if (!hasTrace) return ''; + const label = [trace.sourceTitle, trace.sourceId || trace.sourceSection].filter(Boolean).join(' · '); + return ` +
+ Source trace${label ? ` · ${escapeHtml(label)}` : ''} + ${trace.sourceQuote ? `

${escapeHtml(trace.sourceQuote)}

` : ''} + ${trace.sourceSection ? `Section: ${escapeHtml(trace.sourceSection)}` : ''} +
+ `; +} + function renderHandoffStatus(handoff = {}) { const readiness = handoff.readiness || {}; if (!readiness.status) return ''; @@ -174,6 +200,7 @@ function renderRankCard(item) {
Evidence question

${escapeHtml(item.evidenceQuestion || 'What proof would change this ranking?')}

Success / kill signal

${escapeHtml(item.successSignal || '')} ${escapeHtml(item.killSignal ? `Kill if: ${item.killSignal}` : '')}

+ ${renderItemSourceTrace(item)} ${renderMetrics(item.metrics)} ${renderPills(item.scoringNotes || [])} @@ -210,6 +237,7 @@ function sourceCitation(data) { trace.sourceTitle ? `Source title: ${trace.sourceTitle}` : '', trace.sourceQuote ? `Source quote: ${trace.sourceQuote}` : '', source.originalPromptExcerpt ? `Original prompt: ${source.originalPromptExcerpt}` : '', + source.sourceSummaryExcerpt ? `Source summary: ${source.sourceSummaryExcerpt}` : '', ].filter(Boolean); return parts.length ? parts.join('\n') : 'No source citation was carried into this result.'; } diff --git a/public/index.html b/public/index.html index 228b9a5..9183460 100644 --- a/public/index.html +++ b/public/index.html @@ -4,9 +4,9 @@ - + Ranker — feedback front door for messy decisions - +
@@ -127,6 +127,6 @@ Or paste a Scattermind Concept Map JSON object here; Ranker will preserve source
- + diff --git a/public/styles.css b/public/styles.css index 5392175..a252a98 100644 --- a/public/styles.css +++ b/public/styles.css @@ -39,4 +39,4 @@ button,input,textarea{font:inherit} button{cursor:pointer} a{color:inherit;text- .lane-column .rank-card{box-shadow:none;margin:0;border-width:1.5px}.lane-column .rank-card h3{font-size:clamp(20px,2vw,28px)}.lane-column .metrics{grid-template-columns:1fr}.signal-pills{margin:10px 0}.signal-pills span{background:#f0e8d9;font-size:10px;padding:5px 8px}.action-strip{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:14px 0}.action-strip>div{border:1.5px solid var(--hair);background:#fff6e6;padding:10px}.action-strip span{color:var(--blue2);font-size:10px}.action-strip p{margin:0;font-size:13px;line-height:1.35}.reflection-room{margin-top:24px}.expert-card{position:relative}.expert-card::before{content:"“";position:absolute;right:14px;top:0;font-size:72px;line-height:1;color:rgba(36,92,255,.16);font-weight:1000} @media (max-width:1100px){.lane-board{grid-template-columns:repeat(2,minmax(0,1fr))}.quick-glance{grid-template-columns:repeat(2,minmax(0,1fr))}.action-strip{grid-template-columns:1fr}} @media (max-width:700px){.lane-board,.quick-glance{grid-template-columns:1fr}.memo-head::after{position:static;display:inline-block;margin-top:14px;transform:none}.result-actions .button{width:100%;justify-content:center}.quick-glance{box-shadow:6px 6px 0 var(--ink)}.quick-glance>div{min-height:auto}} -.source-trace{margin:-4px 0 22px;padding:14px 16px;border:2px dashed var(--ink);background:#fff6e5;color:var(--ink2);box-shadow:5px 5px 0 rgba(21,19,15,.16)}.source-trace span,.handoff-card>span{display:block;margin-bottom:8px;color:var(--blue2);text-transform:uppercase;letter-spacing:.12em;font-size:11px;font-weight:1000}.source-trace b{display:block;margin-bottom:6px;font-size:14px}.source-trace p{margin:0;color:var(--muted);line-height:1.45}.handoff-card{border-left:8px solid var(--green)}.handoff-card.status-usable-with-warnings{border-left-color:var(--amber)}.handoff-card.status-needs-source-context,.handoff-card.status-blocked{border-left-color:var(--red)}.handoff-warnings{display:grid;gap:6px;margin-top:12px}.handoff-warnings code{display:block;white-space:normal;border:1px solid var(--hair);background:#f3eee4;padding:7px 9px;font-size:12px;color:var(--ink2)} +.source-trace{margin:-4px 0 22px;padding:14px 16px;border:2px dashed var(--ink);background:#fff6e5;color:var(--ink2);box-shadow:5px 5px 0 rgba(21,19,15,.16)}.source-trace span,.handoff-card>span{display:block;margin-bottom:8px;color:var(--blue2);text-transform:uppercase;letter-spacing:.12em;font-size:11px;font-weight:1000}.source-trace b{display:block;margin-bottom:6px;font-size:14px}.source-trace p{margin:0;color:var(--muted);line-height:1.45}.item-source-trace{margin:12px 0;padding:9px 10px;border:1.5px dashed var(--hair);background:#fffaf1;color:var(--ink2)}.item-source-trace summary{cursor:pointer;color:var(--blue2);font-size:11px;font-weight:1000;letter-spacing:.08em;text-transform:uppercase}.item-source-trace p{margin:8px 0 6px;color:var(--muted);font-size:13px;line-height:1.4}.item-source-trace small{display:block;color:var(--muted);font-size:11px;font-weight:800}.handoff-card{border-left:8px solid var(--green)}.handoff-card.status-usable-with-warnings{border-left-color:var(--amber)}.handoff-card.status-needs-source-context,.handoff-card.status-blocked{border-left-color:var(--red)}.handoff-warnings{display:grid;gap:6px;margin-top:12px}.handoff-warnings code{display:block;white-space:normal;border:1px solid var(--hair);background:#f3eee4;padding:7px 9px;font-size:12px;color:var(--ink2)}