Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save akonan/b7f5d6fd0f72b4c5fa070fc397266870 to your computer and use it in GitHub Desktop.

Select an option

Save akonan/b7f5d6fd0f72b4c5fa070fc397266870 to your computer and use it in GitHub Desktop.
Anthropic long-running agents process summary
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Anthropic Workshop: Long-Running Agent Loops</title>
<style>
:root{--bg:#07090b;--panel:#10161c;--panel2:#0c1117;--line:#2cf4ff33;--text:#e6f7f8;--muted:#87a6ad;--cyan:#2cf4ff;--amber:#ffbd45;--green:#6dff9d;--red:#ff5d66;--purple:#c89bff;--shadow:0 0 40px #2cf4ff16}*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:radial-gradient(circle at 20% -10%,#17404b 0 18%,transparent 38%),radial-gradient(circle at 85% 8%,#463015 0 14%,transparent 34%),linear-gradient(180deg,#07090b,#0b0f13 55%,#060708);color:var(--text);font:15px/1.62 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}body:before{content:"";position:fixed;inset:0;pointer-events:none;opacity:.18;background:linear-gradient(#ffffff05 1px,transparent 1px),linear-gradient(90deg,#ffffff05 1px,transparent 1px);background-size:34px 34px}body:after{content:"";position:fixed;inset:0;pointer-events:none;background:repeating-linear-gradient(180deg,transparent 0 8px,#0006 9px);mix-blend-mode:overlay;opacity:.22}.bar{position:sticky;top:0;z-index:20;display:flex;justify-content:space-between;align-items:center;gap:12px;padding:10px 16px;background:#050708e8;border-bottom:1px solid var(--line);backdrop-filter:blur(14px);box-shadow:0 0 20px #000}.bar b{color:var(--cyan);text-shadow:0 0 12px #2cf4ff66}.bar button,.panel button{border:1px solid #ffbd4577;background:#ffbd451c;color:#ffe0a3;border-radius:4px;padding:9px 12px;font:800 12px ui-monospace,monospace;cursor:pointer;text-transform:uppercase}.wrap{max-width:1260px;margin:auto;padding:34px 20px 90px}.hero{position:relative;min-height:58vh;border:1px solid var(--line);background:linear-gradient(135deg,#10161ce8,#07090be8);box-shadow:var(--shadow);padding:44px;overflow:hidden}.hero:after{content:"LOOPS";position:absolute;right:18px;bottom:-46px;font:900 170px/.8 Impact,sans-serif;color:#2cf4ff0a;letter-spacing:.06em}.kicker{color:var(--amber);text-transform:uppercase;letter-spacing:.24em;font-weight:900;font-size:12px}h1{font:900 clamp(42px,7vw,92px)/.88 Impact,Haettenschweiler,sans-serif;letter-spacing:.01em;margin:18px 0;text-transform:uppercase;color:#f1ffff;text-shadow:0 0 30px #2cf4ff33}h2{font:900 clamp(24px,4vw,48px)/.95 Impact,Haettenschweiler,sans-serif;text-transform:uppercase;letter-spacing:.03em;margin:0 0 18px;color:#f1ffff}h3{margin:0 0 8px;color:#fff}.lede{max-width:900px;font-size:19px;color:#d1edef}.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:14px}.section,.card{border:1px solid var(--line);background:linear-gradient(180deg,#10161cd9,#0b0f13d9);box-shadow:var(--shadow)}.section{margin-top:18px;padding:26px}.card{padding:18px;min-height:160px}.span3{grid-column:span 3}.span4{grid-column:span 4}.span6{grid-column:span 6}.span8{grid-column:span 8}.span12{grid-column:span 12}.stat{font:900 46px/.9 Impact,sans-serif;color:var(--green);text-shadow:0 0 18px #6dff9d44}.chip{display:inline-block;border:1px solid #2cf4ff55;background:#2cf4ff12;color:#a9fbff;padding:4px 8px;margin:3px;text-transform:uppercase;font-size:11px}.muted{color:var(--muted)}table{width:100%;border-collapse:collapse;background:#05070899}th,td{border-bottom:1px solid #2cf4ff22;padding:11px;text-align:left;vertical-align:top}th{color:var(--amber);text-transform:uppercase;font-size:12px;background:#ffbd450c}.flow{display:flex;gap:10px;align-items:stretch;margin:10px 0 18px}.node{flex:1;border:1px solid #2cf4ff44;background:#050708aa;padding:15px;min-width:0}.node strong{color:var(--cyan)}.arrow{align-self:center;color:var(--amber);font:900 26px Impact}.loop{border-color:#ffbd4566;background:linear-gradient(180deg,#17120a,#0b0f13)}.red{color:var(--red)}.green{color:var(--green)}.amber{color:var(--amber)}.purple{color:var(--purple)}.callout{border-left:4px solid var(--amber);background:#ffbd450d;padding:13px 15px;margin:14px 0}.small{font-size:13px}.commentable{position:relative;outline:0 solid transparent;transition:.12s}.commentable:hover{outline:1px solid var(--amber);outline-offset:4px;cursor:cell}.commentable.has-comments{box-shadow:inset 0 0 0 2px var(--amber),0 0 26px #ffbd4533}.comment-pin{position:absolute;right:8px;top:8px;background:var(--amber);color:#080808;border-radius:2px;font:900 11px ui-monospace;padding:2px 6px}.panel{display:none;position:fixed;right:16px;top:60px;width:min(430px,calc(100vw - 32px));max-height:calc(100vh - 80px);overflow:auto;z-index:30;background:#050708f4;border:1px solid var(--line);box-shadow:0 0 70px #000;padding:18px}.panel.open{display:block}.panel textarea{width:100%;min-height:120px;background:#090d11;color:var(--text);border:1px solid #2cf4ff44;padding:12px;font:14px/1.45 ui-monospace,monospace}.comment-item{border:1px solid #2cf4ff33;background:#2cf4ff0a;margin:10px 0;padding:10px}a{color:var(--cyan)}code{color:var(--green);background:#6dff9d12;border:1px solid #6dff9d33;padding:1px 4px}ol li,ul li{margin:8px 0}@media(max-width:900px){.span3,.span4,.span6,.span8{grid-column:span 12}.flow{flex-direction:column}.arrow{transform:rotate(90deg)}.hero{padding:26px}.hero:after{font-size:88px}}
</style>
</head>
<body>
<div class="bar"><div><b>AGENT PROCESS REPORT</b> · <span id="count">0 comments</span></div><div><button onclick="togglePanel()">Comments</button> <button onclick="copyMarkdown()">Copy Markdown</button></div></div>
<aside class="panel" id="panel"><h3>COMMENT BUFFER</h3><p class="muted">Click any highlighted report element, write feedback, then export comments as Markdown.</p><div id="target" class="muted">No target selected.</div><textarea id="commentText" placeholder="Comment for selected element..."></textarea><p><button onclick="saveComment()">Save</button> <button onclick="copyMarkdown()">Copy All</button></p><div id="comments"></div></aside>
<main class="wrap">
<section class="hero commentable" id="hero" data-title="Executive summary">
<div class="kicker">Video summary · Anthropic workshop · agents that run for hours</div>
<h1>Long-running agents are won by harness loops, not just bigger models.</h1>
<p class="lede commentable" id="summary" data-title="Summary paragraph">Ash Prabaker and Andrew Wilson describe how Anthropic moved from agents that could run ~20 minutes to systems that can run for hours or days. The central lesson: model progress matters, but durable autonomy comes from external process—persistent artifacts, fresh or compacted context management, adversarial evaluator loops, tool-based verification, and repeated prompt/harness tuning from traces.</p>
<span class="chip">generator/evaluator</span><span class="chip">planner</span><span class="chip">contracts</span><span class="chip">Playwright verification</span><span class="chip">trace tuning</span>
</section>
<section class="section commentable" id="core-thesis" data-title="Core thesis"><h2>Core thesis</h2>
<div class="grid">
<div class="card span4 commentable" id="problem-context" data-title="Problem: context"><div class="stat">01</div><h3>Context fails over time</h3><p>Agents suffer amnesia in new sessions, context rot in long sessions, and “context anxiety” near the end of the window, where they rush to finish.</p></div>
<div class="card span4 commentable" id="problem-planning" data-title="Problem: planning"><div class="stat">02</div><h3>Planning is brittle</h3><p>Out of the box, models try to one-shot, half-build a feature, or run out of context with a half-finished product.</p></div>
<div class="card span4 commentable" id="problem-judgment" data-title="Problem: judgment"><div class="stat">03</div><h3>Self-judgment is weak</h3><p>Models often rubber-stamp their own output: a button exists but no backend; a page looks done but core interaction does nothing.</p></div>
</div>
<div class="callout commentable" id="main-takeaway" data-title="Main takeaway"><b>Takeaway:</b> Use the model as a worker inside a process. The harness supplies memory, work decomposition, verification pressure, and stop/restart conditions.</div>
</section>
<section class="section commentable" id="evolution" data-title="Evolution timeline"><h2>How the stack evolved</h2>
<table class="commentable" id="timeline-table" data-title="Evolution table"><thead><tr><th>Stage</th><th>Model/harness shift</th><th>Process consequence</th></tr></thead><tbody>
<tr><td>Early Claude Code</td><td>Could run maybe ~20 minutes; struggled with bash details.</td><td>Needed strong scaffolding and short tasks.</td></tr>
<tr><td>Sonnet 3.7 + Claude Code preview</td><td>Claude Code released partly to learn how developers used Claude for coding.</td><td>Harness behavior and model training began co-evolving.</td></tr>
<tr><td>Ralph-loop era</td><td>Plan into features, pick one task, fresh context; or Claude Code plugin with stop hook + max iterations + safe word.</td><td>Deterministic continuation: better to fail predictably than succeed unpredictably.</td></tr>
<tr><td>Sonnet/Opus 4.5</td><td>Better context awareness, checkpoints, Agent SDK, cheaper subagents; Opus planning + Sonnet workhorse.</td><td>Planning, rewind, teams, and multi-agent patterns became economical.</td></tr>
<tr><td>Skills + programmatic tool use</td><td>Progressive disclosure loads only skill frontmatter first; tools can be scripted and only final result returned.</td><td>Less context waste; more deterministic work outside the LLM.</td></tr>
<tr><td>Opus/Sonnet 4.6</td><td>More agentic; 1M context GA; server-side compaction; single long-running sessions viable.</td><td>Some old scaffolding can be deleted; generator/evaluator remains core.</td></tr>
</tbody></table>
</section>
<section class="section commentable" id="loop-map" data-title="Loop map"><h2>The loops they describe</h2>
<div class="grid">
<div class="card span6 loop commentable" id="loop-core-agent" data-title="Core agent loop"><h3>1. Core agent loop</h3><div class="flow"><div class="node"><strong>Model</strong><br>decides next action</div><div class="arrow"></div><div class="node"><strong>Tools/MCP</strong><br>run commands, browsers, servers</div><div class="arrow"></div><div class="node"><strong>Context</strong><br>Claude.md, skills, slash commands, permissions</div></div><p class="small muted">This is the primitive loop in the Agent SDK / Claude Code: decide, tool, observe, continue, possibly delegate to subagents.</p></div>
<div class="card span6 loop commentable" id="loop-ralph" data-title="Ralph loop"><h3>2. Ralph / continuation loop</h3><div class="flow"><div class="node"><strong>Plan</strong><br>break prompt into features</div><div class="arrow"></div><div class="node"><strong>Fresh task session</strong><br>work one slice</div><div class="arrow"></div><div class="node"><strong>Stop hook</strong><br>continue until max iterations, safe word, or done</div></div><p class="small muted">Anthropic’s Claude Code plugin variant ran inside one session and relied on compaction, with a stop hook intercepting normal stopping.</p></div>
<div class="card span6 loop commentable" id="loop-november" data-title="Original long-running harness loop"><h3>3. Original long-running harness</h3><div class="flow"><div class="node"><strong>Initializer</strong><br>one-line prompt → artifacts</div><div class="arrow"></div><div class="node"><strong>Feature loop</strong><br>pick one unpassed feature</div><div class="arrow"></div><div class="node"><strong>Verify + commit</strong><br>tests, Puppeteer, mark pass</div></div><p class="small muted">Artifacts included <code>featurelist.json</code>, progress file, git repo, init script, and completion flags. JSON was preferred because models were less likely to overwrite it than Markdown.</p></div>
<div class="card span6 loop commentable" id="loop-gan" data-title="GAN-style generator/evaluator loop"><h3>4. GAN-style generator/evaluator</h3><div class="flow"><div class="node"><strong>Generator</strong><br>builds</div><div class="arrow"></div><div class="node"><strong>Evaluator</strong><br>uses Playwright, scores, critiques</div><div class="arrow"></div><div class="node"><strong>Restart if needed</strong><br>patch or throw away</div></div><p class="small muted">They split context windows, prompts, and jobs. The critic is tuned to be harsh; the builder is not trusted to be self-critical.</p></div>
<div class="card span6 loop commentable" id="loop-contract" data-title="Contract negotiation loop"><h3>5. Contract negotiation loop</h3><div class="flow"><div class="node"><strong>Generator proposes</strong><br>“I’ll build X; verify via Y”</div><div class="arrow"></div><div class="node"><strong>Evaluator pushes back</strong><br>scope too big, tests too weak, edge cases missing</div><div class="arrow"></div><div class="node"><strong>Contract</strong><br>testable assertions on disk</div></div><p class="small muted">This bridges high-level user stories and concrete test criteria. The evaluator grades against the negotiated contract, not just the original vague prompt.</p></div>
<div class="card span6 loop commentable" id="loop-meta" data-title="Trace-tuning loop"><h3>6. Harness improvement loop</h3><div class="flow"><div class="node"><strong>Run</strong><br>save transcripts/traces</div><div class="arrow"></div><div class="node"><strong>Read line by line</strong><br>find judgment divergence</div><div class="arrow"></div><div class="node"><strong>Tune prompts/rubrics</strong><br>repeat until trustworthy</div></div><p class="small muted">They emphasize reading traces more than simply running more experiments. Another agent can grep/play through transcripts and suggest prompt updates.</p></div>
</div>
</section>
<section class="section commentable" id="planner-generator-evaluator" data-title="Planner-generator-evaluator process"><h2>Current simplified process: planner → generator ↔ evaluator</h2>
<div class="flow commentable" id="pge-flow" data-title="PGE flow"><div class="node"><strong>Planner / PM</strong><br>One-line prompt → high-level creative direction and sprint/workflow outline. Avoids granular technical over-specification.</div><div class="arrow"></div><div class="node"><strong>Generator / builder</strong><br>Builds features, writes code, can pivot or restart.</div><div class="arrow"></div><div class="node"><strong>Evaluator / QA</strong><br>Uses browser/app tools, screenshots, network/console errors, and rubric to critique.</div><div class="arrow"></div><div class="node"><strong>Filesystem state</strong><br>Contracts, logs, JSON breadcrumbs, docs, progress.</div></div>
<h3>Step-by-step</h3><ol>
<li class="commentable" id="pge-step-1" data-title="PGE step 1"><b>User gives a vague outcome:</b> e.g. “build a retro game maker.”</li>
<li class="commentable" id="pge-step-2" data-title="PGE step 2"><b>Planner produces outer boundaries:</b> product direction, workflows/sprints, likely features. It should not nail every technical detail because planner errors cascade across hours.</li>
<li class="commentable" id="pge-step-3" data-title="PGE step 3"><b>Generator and evaluator negotiate done:</b> via Markdown/files on disk, generator proposes scope/tests, evaluator challenges weak tests and missing edge cases.</li>
<li class="commentable" id="pge-step-4" data-title="PGE step 4"><b>They create granular contract criteria:</b> in the Retro Forge example, 27 criteria. Granular criteria make critiques actionable.</li>
<li class="commentable" id="pge-step-5" data-title="PGE step 5"><b>Generator builds:</b> possibly in a continuous session with compaction on newer models, or sprint-by-sprint/fresh contexts on older models.</li>
<li class="commentable" id="pge-step-6" data-title="PGE step 6"><b>Evaluator verifies by using the product:</b> Playwright / Chrome MCP / computer use, screenshots, console and network errors, real UI interactions, not just diffs or unit tests.</li>
<li class="commentable" id="pge-step-7" data-title="PGE step 7"><b>Evaluator scores and critiques:</b> for front-end/design tasks, rubric includes design, originality, craft, functionality, with extra weight on design/originality when functionality is already strong.</li>
<li class="commentable" id="pge-step-8" data-title="PGE step 8"><b>Generator patches or restarts:</b> if it cannot hill-climb against the rubric, the evaluator may tell it to delete everything and restart. This was a key difference versus self-evaluation.</li>
<li class="commentable" id="pge-step-9" data-title="PGE step 9"><b>State is persisted:</b> JSON breadcrumbs such as tried/evaluated/bug/fix/worked, plus high-level live docs and file structure notes for future humans or agents.</li>
</ol>
</section>
<section class="section commentable" id="rubric" data-title="Evaluator rubric"><h2>Evaluator design details</h2>
<div class="grid">
<div class="card span3 commentable" id="rubric-design" data-title="Rubric: design"><div class="stat">D</div><h3>Design</h3><p>Does it look and feel good? Is there taste, hierarchy, spacing, composition?</p></div>
<div class="card span3 commentable" id="rubric-originality" data-title="Rubric: originality"><div class="stat">O</div><h3>Originality</h3><p>Penalizes generic AI slop: purple gradients, template aesthetics, obvious defaults.</p></div>
<div class="card span3 commentable" id="rubric-craft" data-title="Rubric: craft"><div class="stat">C</div><h3>Craft</h3><p>Completeness, polish, edge-case handling, interaction detail.</p></div>
<div class="card span3 commentable" id="rubric-functionality" data-title="Rubric: functionality"><div class="stat">F</div><h3>Functionality</h3><p>Does the thing actually work under real usage, not just pass a superficial test?</p></div>
</div>
<div class="callout commentable" id="critic-tuning" data-title="Critic tuning"><b>Important nuance:</b> out-of-the-box Claude is a poor general QA agent because the same generosity/sycophancy bias affects judge systems. They spent significant time tuning the critic on small layout bugs, edge cases, and human taste divergences.</div>
</section>
<section class="section commentable" id="case-studies" data-title="Case studies"><h2>Case studies mentioned</h2>
<table class="commentable" id="case-table" data-title="Case table"><thead><tr><th>Prompt / app</th><th>Solo loop result</th><th>Harness result</th><th>What the process caught</th></tr></thead><tbody>
<tr><td>Retro game maker</td><td>Looked fine: opening screen, sprite editor, palette, preview. But play mode failed: arrow keys and space did nothing.</td><td>“Retro Forge,” ~$200 and ~6 hours. New-project dialog, richer canvas, 54-color palette, AI level assistant, debug HUD, real physics loop, collisions, controls.</td><td>Evaluator actually launched/played the game and knew what “game works” meant.</td></tr>
<tr><td>Web app QA examples</td><td>CI/unit tests might pass.</td><td>Evaluator caught FastAPI route ordering issues that could break production and a delete-key Boolean logic bug.</td><td>Browser/app usage caught issues diffs and tests might miss.</td></tr>
<tr><td>DAW/music app</td><td>A model generation earlier, likely not viable.</td><td>Latest simplified harness produced a fleshed-out music-creation app; agent set tempo/key, melody, drums. Music quality was bad because Claude cannot hear, but app quality was strong.</td><td>Shows newer models need fewer rounds and simpler scaffolding.</td></tr>
</tbody></table>
</section>
<section class="section commentable" id="harness-adjustment" data-title="Adjusting harness over time"><h2>How they adjust harnesses as models improve</h2>
<table class="commentable" id="adjustment-table" data-title="Harness adjustment table"><thead><tr><th>Harness component</th><th>Why it existed</th><th>What changed</th><th>Decision rule</th></tr></thead><tbody>
<tr><td>Fresh context resets</td><td>Avoid smart-zone/dumb-zone issues and context rot.</td><td>With Opus 4.6 and 1M context, Anthropic moved toward one continuous session with compaction for this pattern.</td><td>Keep if evals prove it helps; strip when newer models handle coherence.</td></tr>
<tr><td>Sprint decomposition</td><td>Critical for Opus 4.5 to keep long builds coherent.</td><td>Opus 4.6 could hold a ~2-hour continuous build without being force-fed one feature at a time.</td><td>Use model behavior, not dogma.</td></tr>
<tr><td>Evaluator cadence</td><td>Previously ran every sprint.</td><td>Now often runs at the end of a one-shot generation, then passes critique back.</td><td>Reduce loop frequency when the builder can stay coherent longer.</td></tr>
<tr><td>Planner role</td><td>Sets product direction.</td><td>Kept high-level; not a constant intervention loop.</td><td>Planner sets outer lines; builder/evaluator negotiate details.</td></tr>
</tbody></table>
</section>
<section class="section commentable" id="implementation-recipe" data-title="Implementation recipe"><h2>Recipe you can copy</h2>
<ol>
<li><b>Define roles:</b> planner, generator, evaluator. Optionally add specialized generator/evaluator pairs in a longer workflow.</li>
<li><b>Persist shared state on disk:</b> contracts, progress, JSON breadcrumbs, high-level docs, transcript logs.</li>
<li><b>Give the evaluator real tools:</b> Playwright MCP, Chrome MCP, computer use, screenshots, console/network inspection.</li>
<li><b>Write a harsh rubric:</b> include subjective taste if relevant. Subjective quality is gradable if you write down your opinion and calibrate examples.</li>
<li><b>Force done-negotiation before building:</b> generator and evaluator agree on concrete assertions and tests.</li>
<li><b>Let the evaluator reject and restart:</b> do not only patch. Restarting from scratch can escape local maxima.</li>
<li><b>Read traces:</b> find where model judgment diverged from yours; encode those lessons into prompts, skills, templates, or memory.</li>
<li><b>Re-evaluate the scaffolding every model release:</b> harnesses are temporary prosthetics for model weaknesses.</li>
</ol>
</section>
<section class="section commentable" id="qa-notes" data-title="Q&A notes"><h2>Important Q&A notes</h2>
<ul>
<li><b>Ralph loops still have a place:</b> multiple fresh sessions vs one compacted session depends on use case and evals. Context rot is becoming less severe but is not “solved” universally.</li>
<li><b>Watching the browser is a trust gap:</b> early on you watch/read traces; mature harnesses should be trusted to run and report back.</li>
<li><b>Human-in-loop can be a hook:</b> stop conditions can hand back to a human, accept a developer message, then continue. But Anthropic’s goal here is to bake stability into the harness rather than permanently rely on humans.</li>
<li><b>Greenfield fit is strongest:</b> the showcased pattern is opinionated and best for greenfield apps. Brownfield requires project-specific rubrics, tests, and SDLC automation.</li>
<li><b>For long-lived products:</b> leave breadcrumbs: timestamped attempts, evaluation findings, fixes, whether fixes worked, plus live high-level docs/file structure.</li>
<li><b>Team collaboration remains unsolved:</b> observability and team-owned harnesses are still greenfield software areas; version control, PRs, and worktrees remain practical safeguards.</li>
</ul>
</section>
<section class="section commentable" id="five-slide" data-title="Five key reminders"><h2>The five-slide memory</h2>
<div class="grid">
<div class="card span4 commentable" id="remember-self-eval" data-title="Self-evaluation trap"><h3><span class="red">Self-evaluation is a trap</span></h3><p>Use an adversarial evaluator instead of asking one agent to check its own work.</p></div>
<div class="card span4 commentable" id="remember-compaction" data-title="Compaction caveat"><h3><span class="amber">Compaction ≠ coherence</span></h3><p>Lossy summaries drift. Structured handoffs and clean contexts remain valuable.</p></div>
<div class="card span4 commentable" id="remember-subjective" data-title="Subjective grading"><h3><span class="purple">Subjective quality is gradable</span></h3><p>If you have a strong view, write it down and calibrate with examples.</p></div>
<div class="card span6 commentable" id="remember-traces" data-title="Read traces"><h3><span class="green">Read the traces</span></h3><p>Only trace reading shows which scaffold to keep, delete, or adjust as the frontier moves.</p></div>
<div class="card span6 commentable" id="remember-frontier" data-title="Moving frontier"><h3><span class="cyan">The frontier moves</span></h3><p>Harness design is not dead; it co-evolves with models and should shrink or change when model weaknesses disappear.</p></div>
</div>
</section>
</main>
<script>
const storeKey='anthropic-agent-loops-comments-v1:'+location.pathname;let selected=null;let comments=JSON.parse(localStorage.getItem(storeKey)||'{}');
const $=id=>document.getElementById(id);const all=()=>[...document.querySelectorAll('.commentable[id]')];const titleOf=el=>el.dataset.title||el.id;
function renderPins(){all().forEach(el=>{el.classList.toggle('has-comments',!!comments[el.id]?.length);let p=el.querySelector(':scope > .comment-pin');if(p)p.remove();if(comments[el.id]?.length){p=document.createElement('span');p.className='comment-pin';p.textContent=comments[el.id].length;el.appendChild(p)}});let n=Object.values(comments).reduce((a,b)=>a+b.length,0);$('count').textContent=n+' comment'+(n===1?'':'s')}
function togglePanel(){$('panel').classList.toggle('open');renderList()}function selectEl(el){selected=el;$('panel').classList.add('open');$('target').innerHTML='<b>Target:</b> <a href="#'+el.id+'">#'+el.id+'</a> — '+titleOf(el);$('commentText').value='';renderList()}
function saveComment(){if(!selected)return alert('Click a report element first.');let text=$('commentText').value.trim();if(!text)return;comments[selected.id]=comments[selected.id]||[];comments[selected.id].push({text,at:new Date().toISOString(),title:titleOf(selected)});localStorage.setItem(storeKey,JSON.stringify(comments));$('commentText').value='';renderPins();renderList()}
function renderList(){let box=$('comments');box.innerHTML='';Object.entries(comments).forEach(([id,items])=>items.forEach((c,i)=>{let d=document.createElement('div');d.className='comment-item';d.innerHTML='<b><a href="#'+id+'">#'+id+'</a> '+c.title+'</b><br><span class="muted">'+c.at+'</span><p></p><button>Delete</button>';d.querySelector('p').textContent=c.text;d.querySelector('button').onclick=()=>{comments[id].splice(i,1);if(!comments[id].length)delete comments[id];localStorage.setItem(storeKey,JSON.stringify(comments));renderPins();renderList()};box.appendChild(d)}));if(!box.innerHTML)box.innerHTML='<p class="muted">No comments yet.</p>'}
function markdown(){let lines=['# Comments on Anthropic long-running agent loops',''];Object.entries(comments).forEach(([id,items])=>items.forEach(c=>{lines.push('## ['+c.title+'](#'+id+')');lines.push('Element: `#'+id+'`');lines.push('');lines.push(c.text);lines.push('')}));return lines.join('\n')}
async function copyMarkdown(){let md=markdown();try{await navigator.clipboard.writeText(md);alert('Copied comments as Markdown.')}catch(e){prompt('Copy comments:',md)}}
document.addEventListener('click',e=>{let el=e.target.closest('.commentable[id]');if(el&&!e.target.closest('.bar,.panel')){selectEl(el);e.preventDefault();e.stopPropagation()}});renderPins();renderList();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment