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
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ PlanProof values correctness over persuasion.
- [X] PR 3.3: Failure/Rejection Styles
- [X] PR 3.4: Assumptions & Questions (Show the AI's "Why").
- [X] PR 4.1: Opik Trace Link (Show the "View Trace" button for the judges).
- [X] PR 4.2: Final Polish & UX Tooltips

## Backend Lane (Codex)

Expand Down
44 changes: 28 additions & 16 deletions apps/api/static/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,18 @@ const METRIC_CONFIG = [
/**
* Renders the pre-flight checklist with metric values.
* @param {Object|null} metrics - The validation.metrics object from API response
* @param {boolean} planGenerated - Whether a plan was successfully generated (for defensive UI)
*/
function renderChecklist(metrics) {
function renderChecklist(metrics, planGenerated = false) {
const checklist = elements.checklist;
if (!checklist) return;

// Clear existing items
checklist.innerHTML = '';

// Defensive UI: Show "Data Unavailable" if plan was generated but metrics missing
const showUnavailable = planGenerated && !metrics;

METRIC_CONFIG.forEach((config) => {
const li = document.createElement('li');
li.className = 'checklist-item';
Expand All @@ -156,7 +160,9 @@ function renderChecklist(metrics) {
const passes = hasValue && config.isPass(value);

// Set state class
if (!hasValue) {
if (showUnavailable) {
li.classList.add('checklist-item--unavailable');
} else if (!hasValue) {
li.classList.add('checklist-item--pending');
} else if (passes) {
li.classList.add('checklist-item--pass');
Expand All @@ -165,8 +171,8 @@ function renderChecklist(metrics) {
}

// Build inner HTML
const icon = !hasValue ? '○' : passes ? '✓' : '✗';
const displayValue = hasValue ? config.format(value) : '—';
const icon = showUnavailable ? '⚠' : !hasValue ? '○' : passes ? '✓' : '✗';
const displayValue = showUnavailable ? 'N/A' : hasValue ? config.format(value) : '—';

li.innerHTML = `
<span class="check-icon">${icon}</span>
Expand Down Expand Up @@ -216,28 +222,31 @@ function renderErrors(errors, isPriority = false) {
}

// ==========================================================================
// Opik Trace Link (PR 4.1)
// Opik Trace Link (PR 4.1, updated PR 4.2)
// ==========================================================================

/**
* Shows or hides the Opik trace link section.
* @param {boolean} visible - Whether to show the trace link
* Enables or disables the Opik trace link button.
* @param {boolean} enabled - Whether the trace link should be clickable
* @param {string|null} traceUrl - Optional custom trace URL
*/
function renderTraceLink(visible, traceUrl = null) {
const section = elements.traceSection;
function renderTraceLink(enabled, traceUrl = null) {
const link = elements.traceLink;
if (!section) return;
if (!link) return;

if (!visible) {
section.classList.add('trace-section--hidden');
if (!enabled) {
link.classList.add('btn-trace--disabled');
link.setAttribute('aria-disabled', 'true');
link.setAttribute('title', 'Generate a plan first to view the technical trace.');
return;
}

section.classList.remove('trace-section--hidden');
link.classList.remove('btn-trace--disabled');
link.setAttribute('aria-disabled', 'false');
link.setAttribute('title', 'Inspect the agentic logic, deterministic logs, and LLM spans in the Opik observability suite.');

// Update URL if provided (for future per-trace linking)
if (traceUrl && link) {
if (traceUrl) {
link.href = traceUrl;
}
}
Expand Down Expand Up @@ -598,8 +607,8 @@ function renderValidation(validation) {
validation.status === 'fail' ? 'fail' : 'pending';
renderStatusBadge(status);

// Render checklist with metrics
renderChecklist(validation.metrics || null);
// Render checklist with metrics (planGenerated=true for defensive UI)
renderChecklist(validation.metrics || null, true);

// Render metrics grid (PR 1.4)
renderMetricsGrid(validation.metrics || null);
Expand Down Expand Up @@ -940,6 +949,9 @@ async function generatePlan() {
}

const data = await response.json();

// DEBUG: Log full API response for field verification
console.log('DEBUG: Full API Response:', data);

// Determine if plan is rejected (PR 3.3)
const isRejected = data.validation?.status === 'fail';
Expand Down
39 changes: 31 additions & 8 deletions apps/api/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,17 @@ <h3 class="callout-title">Clarifying Questions</h3>
<div id="timeline-container" class="timeline">
<!-- Timeline items will be rendered here by app.js -->
<div class="timeline-empty">
<p class="empty-message">No plan generated yet.</p>
<p class="empty-hint">Enter your context and click "Generate Plan"</p>
<div class="empty-illustration">
<div class="empty-icon-ring">
<span class="empty-icon">📋</span>
</div>
<div class="empty-sparkle empty-sparkle--1">✦</div>
<div class="empty-sparkle empty-sparkle--2">✧</div>
<div class="empty-sparkle empty-sparkle--3">✦</div>
</div>
<h3 class="empty-title">Ready When You Are</h3>
<p class="empty-message">Paste your context, constraints, and goals on the left.</p>
<p class="empty-hint">We'll build a mathematically verified plan—no hallucinations, no overlaps.</p>
</div>
<!-- Loading State (PR 3.1) -->
<div id="timeline-loading" class="timeline-loading">
Expand All @@ -112,6 +121,7 @@ <h3 class="callout-title">Clarifying Questions</h3>
<aside class="proof-sidebar">
<header class="panel-header">
<h2 class="panel-title">Validation Proof</h2>
<span class="observability-label mono">Observability: Opik / Project: Hackaton</span>
</header>

<!-- Status Badge -->
Expand All @@ -130,7 +140,13 @@ <h3 class="section-title">Extracted Constraints</h3>

<!-- Pre-Flight Checklist -->
<div class="checklist-section">
<h3 class="section-title">Pre-Flight Checks</h3>
<h3 class="section-title">
Pre-Flight Checks
<button type="button" class="info-tooltip" aria-label="What are Pre-Flight Checks?">
<span class="info-icon">ⓘ</span>
<span class="tooltip-content">Binary pass/fail gates that must ALL pass for a valid plan. Zero tolerance for constraint violations, time overlaps, or hallucinated tasks.</span>
</button>
</h3>
<ul id="checklist" class="checklist">
<li class="checklist-item checklist-item--pending">
<span class="check-icon">○</span>
Expand All @@ -157,7 +173,13 @@ <h3 class="section-title">Pre-Flight Checks</h3>

<!-- Metrics Grid (PR 1.4) -->
<div class="metrics-section">
<h3 class="section-title">Validation Metrics</h3>
<h3 class="section-title">
Validation Metrics
<button type="button" class="info-tooltip" aria-label="What are Validation Metrics?">
<span class="info-icon">ⓘ</span>
<span class="tooltip-content">Quantitative measurements from deterministic Python validators. These numbers are computed, not guessed—an LLM never grades its own plan.</span>
</button>
</h3>
<div id="metrics-grid" class="metrics-grid">
<div class="metric-tile" data-metric="constraint_violation_count">
<span class="metric-value mono">—</span>
Expand Down Expand Up @@ -215,14 +237,15 @@ <h3 class="section-title section-title--error">Errors</h3>
</div>

<!-- Opik Trace Link (PR 4.1) -->
<div id="trace-section" class="trace-section trace-section--hidden">
<div id="trace-section" class="trace-section">
<a
id="trace-link"
href="https://www.comet.com/opik/planproof"
href="https://www.comet.com/opik/silviu-druma/projects/Hackaton"
target="_blank"
rel="noopener noreferrer"
class="btn-trace"
title="Inspect the agentic logic, deterministic logs, and LLM spans in the Opik observability suite."
class="btn-trace btn-trace--disabled"
title="Generate a plan first to view the technical trace."
aria-disabled="true"
>
<span class="trace-icon">🔍</span>
<span class="trace-text">View Technical Trace</span>
Expand Down
Loading