Skip to content

fix(web): simplify teacher evidence details - #9

Merged
alexdancer merged 2 commits into
mainfrom
fm/huddle-teacher-details-prune-b2
Jul 30, 2026
Merged

fix(web): simplify teacher evidence details#9
alexdancer merged 2 commits into
mainfrom
fm/huddle-teacher-details-prune-b2

Conversation

@alexdancer

Copy link
Copy Markdown
Owner

Intent

Simplify the teacher-facing Evidence Desk report based on the reviewed walkthrough: retain only one clear, accessible ‘Show exact contributing evidence’ disclosure with useful exact attempt/session result, answer, and timing content; remove the entire Additional evidence area and any teacher-facing additional cause, rule, quality-detail, or expandable technical-provenance UI. Keep rank, priority, confidence, conversation opener, student comparison, and a concise deterministic-fallback cue. Make the smallest frontend-only change, preserve backend scoring and data contracts, and verify responsive spacing and regression coverage.

What Changed

  • Place the dominant finding’s exact attempts and sessions behind one accessible disclosure while retaining results, selected answers, and timing details.
  • Remove additional-signal evidence, cause counts and context, rule-quality details, and expandable narration provenance from the teacher-facing report; keep a concise fallback cue.
  • Update responsive styling, rendering regressions, and product documentation to match the streamlined Evidence Desk flow while preserving backend evidence contracts.

Risk Assessment

✅ Low: The frontend-only change conforms to the requested presentation, preserves scoring and application data contracts, and leaves only a minor non-functional simplification opportunity.

Testing

After resolving the isolated worktree’s missing dependencies, the focused Vitest regression passed and desktop/mobile browser checks demonstrated the simplified report end to end with useful exact attempt/session evidence, no additional or technical-provenance UI, and no horizontal overflow; reviewer-visible HTML and screenshots were captured and all worktree test artifacts were cleaned.

  • Evidence: Desktop report — disclosure collapsed (local file: /var/folders/nt/rdk7cjs538l8zphln24q2k900000gn/T/no-mistakes-evidence/01KYT0NN5F6PGZEV8HBX4KW45J/evidence-desk-desktop-collapsed.png)
  • Evidence: Desktop report — exact evidence expanded (local file: /var/folders/nt/rdk7cjs538l8zphln24q2k900000gn/T/no-mistakes-evidence/01KYT0NN5F6PGZEV8HBX4KW45J/evidence-desk-desktop-expanded.png)
  • Evidence: 390px mobile report — exact evidence expanded (local file: /var/folders/nt/rdk7cjs538l8zphln24q2k900000gn/T/no-mistakes-evidence/01KYT0NN5F6PGZEV8HBX4KW45J/evidence-desk-mobile-expanded.png)
Evidence: Interactive report rendered from changed components and production CSS
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Huddle Evidence Desk — focused validation</title>
  <style>
:root {
  --huddle-bg: #ffffff;
  --huddle-surface: #faf7f8;
  --huddle-surface-strong: #f3edef;
  --huddle-ink: #241c1f;
  --huddle-muted: #675c61;
  --huddle-brand: #9a2148;
  --huddle-brand-dark: #771735;
  --huddle-line: #e4dadd;
  --huddle-blue: #1757a6;
  --huddle-blue-soft: #edf5ff;
  --huddle-green: #176c4b;
  --huddle-green-soft: #edf9f2;
  --huddle-warn: #8b4f00;
}

* {
  box-sizing: border-box;
}

html {
  min-width: 300px;
}

body {
  margin: 0;
  color: var(--huddle-ink);
  background: var(--huddle-bg);
  font-family:
    Inter,
    ui-sans-serif,
    system-ui,
    -apple-system,
    BlinkMacSystemFont,
    'Segoe UI',
    sans-serif;
  font-size: 15px;
  line-height: 1.45;
}

h1,
h2,
h3 {
  line-height: 1.18;
  text-wrap: balance;
}

p {
  text-wrap: pretty;
}

a {
  color: var(--huddle-blue);
}

button,
input {
  font: inherit;
}

button {
  cursor: pointer;
}

button:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

:focus-visible {
  outline: 3px solid #2767bd;
  outline-offset: 3px;
}

.app-header {
  position: sticky;
  top: 0;
  z-index: 20;
  min-height: 64px;
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 9px max(18px, calc((100vw - 1320px) / 2));
  border-bottom: 1px solid var(--huddle-line);
  background: rgba(255, 255, 255, 0.97);
}

.app-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--huddle-ink);
  font-size: 1.08rem;
  font-weight: 850;
  letter-spacing: -0.025em;
  text-decoration: none;
}

.app-logo {
  width: 30px;
  height: 30px;
  display: inline-grid;
  place-items: center;
  border-radius: 8px;
  background: var(--huddle-brand);
  color: white;
  font-size: 0.9rem;
}

.app-nav {
  display: flex;
  gap: 20px;
}

.app-nav a {
  color: var(--huddle-muted);
  font-size: 0.9rem;
  font-weight: 700;
  text-decoration: none;
}

.app-nav a:hover {
  color: var(--huddle-brand);
}

.app-scope {
  margin: 0 0 0 auto;
  color: var(--huddle-muted);
  font-size: 0.76rem;
  line-height: 1.25;
  text-align: right;
}

.app-scope strong {
  display: block;
  color: var(--huddle-ink);
}

.site-main {
  width: min(1120px, calc(100% - 32px));
  margin: 0 auto;
  padding: 64px 0;
}

.hero {
  min-height: 62vh;
  display: grid;
  grid-template-columns: 1.35fr 0.8fr;
  gap: 48px;
  align-items: center;
}

.eyebrow-global {
  margin: 0 0 10px;
  color: var(--huddle-brand);
  font-size: 0.78rem;
  font-weight: 850;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.hero h1 {
  max-width: 13ch;
  margin: 0;
  font-size: clamp(2.3rem, 6vw, 4.8rem);
  line-height: 0.98;
  letter-spacing: -0.04em;
}

.hero h1 span {
  color: var(--huddle-brand);
}

.hero-copy {
  max-width: 43rem;
  margin: 24px 0;
  color: var(--huddle-muted);
  font-size: 1.12rem;
  line-height: 1.65;
}

.actions,
.workflow-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.button,
button {
  min-height: 44px;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  padding: 9px 15px;
  border: 1px solid var(--huddle-brand);
  border-radius: 9px;
  background: var(--huddle-brand);
  color: white;
  font-weight: 750;
  text-decoration: none;
}

.button:hover,
button:hover {
  background: var(--huddle-brand-dark);
}

.button.secondary {
  background: white;
  color: var(--huddle-brand);
}

.promise-card {
  padding: 26px;
  border: 1px solid var(--huddle-line);
  border-radius: 14px;
  background: white;
}

.promise-card h2 {
  margin-top: 0;
}

.promise-list {
  display: grid;
  gap: 15px;
  padding: 0;
  list-style: none;
}

.promise-list li {
  position: relative;
  padding-left: 24px;
  color: var(--huddle-muted);
}

.promise-list li::before {
  content: '✓';
  position: absolute;
  left: 0;
  color: var(--huddle-green);
  font-weight: 850;
}

.auth-page {
  min-height: calc(100vh - 64px);
  display: grid;
  grid-template-columns: minmax(300px, 0.85fr) minmax(360px, 1.15fr);
}

.auth-intro {
  min-height: 560px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(36px, 7vw, 90px);
  background: var(--huddle-brand);
  color: white;
}

.auth-intro > p {
  margin: 0 0 24px;
  font-weight: 750;
}

.auth-intro h1 {
  max-width: 10ch;
  margin: 0 0 16px;
  font-size: 2.9rem;
  letter-spacing: -0.035em;
}

.auth-intro span {
  max-width: 34ch;
  font-size: 1.05rem;
}

.auth-main {
  display: grid;
  place-items: center;
  padding: clamp(28px, 7vw, 80px);
}

.auth-box {
  width: min(100%, 430px);
}

.auth-box h2 {
  margin: 0 0 8px;
  font-size: 1.65rem;
}

.auth-box > p {
  color: var(--huddle-muted);
}

.form-stack {
  display: grid;
  gap: 15px;
  margin-top: 26px;
}

.form-stack label,
.upload-row label {
  display: grid;
  gap: 7px;
  color: var(--huddle-ink);
  font-weight: 700;
}

.form-stack input,
.upload-row input {
  width: 100%;
  min-height: 46px;
  padding: 10px 12px;
  border: 1px solid #cfc2c7;
  border-radius: 8px;
  background: white;
}

.policy-note {
  padding: 12px 14px;
  border: 1px solid #b8d1ee;
  border-radius: 9px;
  background: var(--huddle-blue-soft);
  color: #234a78 !important;
}

.workflow-page {
  width: min(820px, calc(100% - 32px));
  margin: 0 auto;
  padding: 52px 0 70px;
}

.import-workflow {
  display: grid;
  gap: 18px;
}

.workflow-heading h1 {
  margin: 0 0 8px;
  font-size: 2rem;
  letter-spacing: -0.025em;
}

.workflow-heading p {
  max-width: 62ch;
  margin: 0;
  color: var(--huddle-muted);
}

.sample-download {
  width: max-content;
  font-weight: 700;
}

.upload-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px;
  align-items: flex-end;
  padding: 20px 0;
  border-top: 1px solid var(--huddle-line);
  border-bottom: 1px solid var(--huddle-line);
}

.import-result {
  padding-top: 8px;
}

.import-result h2 {
  font-size: 1.15rem;
}

.import-result dl {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px 20px;
  margin: 0;
  padding: 16px 0;
  border-top: 1px solid var(--huddle-line);
  border-bottom: 1px solid var(--huddle-line);
}

.import-result dt {
  color: var(--huddle-muted);
}

.import-result dd {
  margin: 0;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.evidence-desk,
.desk-state {
  width: min(1320px, calc(100% - 32px));
  margin: 0 auto;
  padding: 30px 0 56px;
}

.desk-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
}

.desk-header h1,
.desk-state h1 {
  margin: 0;
  font-size: 2rem;
  letter-spacing: -0.025em;
}

.desk-header p {
  margin: 6px 0 0;
  color: var(--huddle-muted);
}

.desk-freshness,
.recovery {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px 13px;
  margin: 22px 0 18px;
  padding: 11px 14px;
  border: 1px solid var(--huddle-line);
  border-radius: 10px;
  background: var(--huddle-surface);
  color: var(--huddle-muted);
  font-size: 0.82rem;
}

.desk-freshness strong,
.recovery strong {
  color: var(--huddle-ink);
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--huddle-green);
}

.status-dot-warning {
  background: var(--huddle-warn);
}

.freshness-push {
  margin-left: auto;
}

.recovery {
  background: var(--huddle-blue-soft);
  color: #244a78;
}

.desk-grid {
  min-height: 620px;
  display: grid;
  grid-template-columns: minmax(330px, 0.78fr) minmax(0, 1.4fr);
  overflow: hidden;
  border: 1px solid var(--huddle-line);
  border-radius: 12px;
}

.evidence-rail {
  min-width: 0;
  border-right: 1px solid var(--huddle-line);
  background: var(--huddle-surface);
}

.rail-heading {
  padding: 18px;
  border-bottom: 1px solid var(--huddle-line);
}

.rail-heading h2 {
  margin: 0 0 4px;
  font-size: 1rem;
}

.rail-heading p {
  margin: 0;
  color: var(--huddle-muted);
  font-size: 0.82rem;
}

.evidence-rail ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

.evidence-rail li {
  border-bottom: 1px solid var(--huddle-line);
}

.rail-link {
  width: 100%;
  display: grid;
  grid-template-columns: 32px 

... [2824 bytes truncated] ...

;
  font-size: 0.8rem;
}

.provenance strong,
.provenance small {
  display: block;
}

.provenance small {
  margin-top: 2px;
}

.metrics {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  overflow: hidden;
  margin: 0;
  border: 1px solid var(--huddle-line);
  border-radius: 10px;
  background: var(--huddle-line);
}

.metrics div {
  padding: 13px;
  background: white;
}

.metrics dt {
  color: var(--huddle-muted);
  font-size: 0.78rem;
}

.metrics dd {
  margin: 5px 0 0;
  font-size: 1.05rem;
  font-weight: 800;
}

.prerequisite-context {
  margin-top: 18px;
}

.prerequisite-context h4 {
  margin: 0 0 8px;
  font-size: 0.9rem;
}

.prerequisite-context p {
  margin: 0;
  color: var(--huddle-muted);
}

.teacher-evidence-disclosure {
  overflow: hidden;
  border: 1px solid var(--huddle-line);
  border-radius: 10px;
}

.teacher-evidence-disclosure > summary {
  padding: 14px;
  cursor: pointer;
  font-weight: 780;
}

.teacher-evidence-body {
  padding: 0 14px 14px;
  border-top: 1px solid var(--huddle-line);
}

.teacher-evidence-body > p {
  margin: 12px 0;
  color: var(--huddle-muted);
  font-size: 0.86rem;
}

.teacher-evidence-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.teacher-evidence-item {
  display: grid;
  grid-template-columns: minmax(132px, 0.35fr) minmax(0, 1fr);
  gap: 14px;
  padding: 14px 0;
  border-top: 1px solid var(--huddle-line);
}

.teacher-evidence-when {
  display: grid;
  align-content: start;
  gap: 3px;
  color: var(--huddle-muted);
  font-size: 0.8rem;
}

.teacher-evidence-when time {
  color: var(--huddle-ink);
  font-weight: 700;
}

.teacher-evidence-content > strong {
  display: block;
}

.teacher-evidence-content dl {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin: 6px 0 0;
}

.teacher-evidence-content dl > div {
  display: flex;
  gap: 4px;
  font-size: 0.82rem;
}

.teacher-evidence-content dt {
  color: var(--huddle-muted);
}

.teacher-evidence-content dd {
  margin: 0;
}

.result-correct {
  color: var(--huddle-green);
  font-weight: 750;
}

.result-incorrect {
  color: #942532;
  font-weight: 750;
}

.acknowledgment {
  margin: 18px 22px 0;
  padding: 10px 12px;
  border-radius: 9px;
  background: var(--huddle-green-soft);
  color: var(--huddle-green);
  font-size: 0.82rem;
  font-weight: 700;
}

.desk-state {
  max-width: 700px;
  padding-top: 14vh;
  text-align: center;
}

.desk-state p {
  color: var(--huddle-muted);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 760px) {
  .app-header {
    gap: 14px;
    padding: 10px 14px;
  }

  .app-nav {
    margin-left: auto;
    gap: 14px;
  }

  .app-scope {
    display: none;
  }

  .site-main {
    padding-top: 36px;
  }

  .hero {
    min-height: auto;
    grid-template-columns: 1fr;
  }

  .auth-page {
    display: block;
  }

  .auth-intro {
    min-height: auto;
    padding: 34px 20px;
  }

  .auth-intro h1 {
    max-width: 14ch;
    font-size: 2rem;
  }

  .auth-main {
    display: block;
    padding: 34px 20px 50px;
  }

  .workflow-page {
    width: min(100% - 24px, 620px);
    padding-top: 30px;
  }

  .upload-row {
    grid-template-columns: 1fr;
  }

  .upload-row button {
    width: 100%;
  }

  .evidence-desk,
  .desk-state {
    width: 100%;
    padding: 22px 12px 40px;
  }

  .freshness-push {
    width: 100%;
    margin-left: 21px;
  }

  .desk-grid {
    display: block;
    min-height: 0;
    border-right: 0;
    border-left: 0;
    border-radius: 0;
  }

  .evidence-rail {
    border-right: 0;
  }

  .desk-grid.has-selection .evidence-rail {
    display: none;
  }

  .workspace-slot {
    display: none;
  }

  .desk-grid.has-selection .workspace-slot {
    display: block;
  }

  .evidence-workspace {
    padding: 18px 14px;
  }

  .metrics {
    grid-template-columns: 1fr;
  }

  .teacher-evidence-item {
    grid-template-columns: 1fr;
    gap: 6px;
  }

  .teacher-evidence-content dl {
    display: grid;
    gap: 4px;
  }

  .acknowledgment {
    margin: 14px 14px 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition: none !important;
    animation: none !important;
  }
}

.evidence-fixture { max-width: 1440px; margin: 0 auto; }
.fixture-label { align-self: center; color: var(--huddle-muted); font-size: .85rem; }
.evidence-fixture-rail { min-height: 100%; }
@media (max-width: 760px) { .fixture-label { display: none; } }
  </style>
</head>
<body>
<main class="evidence-desk evidence-fixture"><header class="desk-header"><div><h1>Evidence desk</h1></div><span class="fixture-label">Synthetic guide workspace</span></header><div class="desk-grid has-selection"><nav class="evidence-rail evidence-fixture-rail" aria-label="Ranked reports"><div class="rail-heading"><h2>Today’s attention queue</h2><p>1 student</p></div><ol><li><a class="rail-link selected" href="#report-title"><span class="rail-rank" aria-hidden="true">1</span><div class="rail-copy"><strong>Avery</strong><span>Guessing pattern · 4.4A</span><small>Not yet seen</small></div><span class="rail-chevron" aria-hidden="true">›</span></a></li></ol></nav><section class="workspace-slot"><article class="evidence-workspace" aria-labelledby="report-title"><header class="report-heading"><div class="report-status-line" aria-label="Rank #1 today. Urgent priority. Medium confidence."><span class="priority priority-urgent"><span aria-hidden="true">◆</span> Urgent priority</span><span class="rank-label">#1 today</span><span class="confidence">Medium confidence</span></div><h2 id="report-title">Avery · 4.4A</h2><p>Guessing pattern · Add and subtract</p></header><section class="finding-intro"><h3>Why Huddle ranked this</h3><p>Avery selected the same incorrect answer across recent attempts while working faster than their usual correct pace.</p><blockquote><strong>Conversation opener</strong><br/>Show me your first step, then tell me what made answer B feel right.</blockquote></section><aside class="provenance" aria-label="Wording status"><span aria-hidden="true">◇</span><span><strong>Deterministic fallback</strong><small>Wording is based only on this report’s evidence.</small></span></aside><section class="report-context" aria-labelledby="report-context-heading"><h3 id="report-context-heading">Context for this report</h3><dl class="metrics"><div><dt>Usual correct pace</dt><dd>3.2 sec</dd></div><div><dt>Recent attempt pace</dt><dd>1.5 sec</dd></div><div><dt>Consecutive incorrect responses</dt><dd>2</dd></div></dl><div class="prerequisite-context"><h4>Prerequisite checked</h4><p>4.3E · Fractions — 73% mastery (adequate)</p></div></section><section class="teacher-evidence" aria-label="Exact contributing evidence from Avery&#x27;s work"><details class="teacher-evidence-disclosure"><summary>Show exact contributing evidence</summary><div class="teacher-evidence-body"><p>Each attempt and work session appears once, even when it supports more than one pattern.</p><ol class="teacher-evidence-list" aria-label="Evidence from Avery&#x27;s work"><li class="teacher-evidence-item"><div class="teacher-evidence-when"><time dateTime="2026-07-29T07:31:22.125Z">Jul 29, 2:31 AM CDT</time><span>Active work: 1.5 sec</span><span>Elapsed: 1.5 sec</span></div><div class="teacher-evidence-content"><strong>4.4A · Add and subtract</strong><dl><div><dt>Result</dt><dd class="result-incorrect">Incorrect</dd></div><div><dt>Answer selected</dt><dd>B</dd></div><div><dt>Useful misconception</dt><dd>reversed operation</dd></div><div><dt>Hints</dt><dd>2 used</dd></div></dl></div></li><li class="teacher-evidence-item"><div class="teacher-evidence-when"><time dateTime="2026-07-29T07:30:00.000Z">Jul 29, 2:30 AM CDT</time><span>Through <time dateTime="2026-07-29T07:40:00.000Z">Jul 29, 2:40 AM CDT</time></span><span>600 sec total</span></div><div class="teacher-evidence-content"><strong>Work session</strong><dl><div><dt>Activities recorded</dt><dd>7</dd></div></dl></div></li></ol></div></details></section></article></section></div></main>
</body>
</html>

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 1 info
  • ℹ️ apps/web/app/board/lib/teacher-report-view.ts:68 - After excluding additional-signal evidence, these single-element source arrays and their outer loops are redundant, while the adjacent comment still claims the helper combines evidence across several signals. Iterate evidence.exact.attempts and evidence.exact.sessions directly, retaining the maps for deduplication, and update the comment to describe dominant-signal evidence.
✅ **Test** - passed

✅ No issues found.

  • git diff 6c8936396ccbcd294b8b46ea6792e9b5af49a40e..4f1516a9eb80ff40012f2d0eb278eac3c6a2a47e — confirmed the change is limited to four frontend/test files
  • npm ci — installed locked dependencies after the initial Vitest command found no local installation
  • node_modules/.bin/vitest run apps/web/test/evidence-desk-rendering.test.ts — targeted rendering, accessibility, disclosure, copy-removal, and responsive regression coverage
  • node_modules/.bin/tsx .tmp-no-mistakes/evidence-render.tsx — rendered changed components and production CSS with injected additional evidence; verified one disclosure and exclusion of additional activity/provenance
  • Playwright WebKit at 1440×1200 — inspected and captured collapsed and expanded teacher-report states
  • Playwright WebKit at 390×844 — inspected expanded report; verified scrollWidth === clientWidth === 390, one disclosure, and no forbidden additional/provenance text
  • Removed temporary dependencies, package build outputs, browser runtime, Playwright state, and evidence-generation harness from the worktree; retained only dedicated evidence files
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@alexdancer
alexdancer merged commit 7fd06ba into main Jul 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant