From 50157f0d5bb08c03b0f19e55f154816d3fdaa13e Mon Sep 17 00:00:00 2001 From: gator Date: Thu, 17 Sep 2026 06:45:22 +0000 Subject: [PATCH] trailer.html: show what viewers understood, not what reviewers thought The review panel rendered the old critique shape - errors, suggestions, strengths. The comprehension test produces something else: three summaries written by readers who saw only the script, and the writer's own list of what the trailer failed to convey. The gap list leads, because that is what the revision consumes and what the author needs to decide about. Each reader's summary is then shown verbatim, with what they were still asking and whether they would watch the film - reading three strangers describe your trailer badly is the most persuasive evidence there is that it does not tell the story. "Got wrong" is called out separately from "missed". A trailer that leaves something out is incomplete; one that leads a viewer to the wrong conclusion is worse, and they are different problems to fix. --- trailer.html | 112 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 39 deletions(-) diff --git a/trailer.html b/trailer.html index c49cfea..728dcaa 100644 --- a/trailer.html +++ b/trailer.html @@ -60,14 +60,20 @@ border-radius:999px;padding:0 6px} .vobadge{color:var(--muted);font-size:11px;border:1px solid var(--line); border-radius:999px;padding:0 6px} - .revs{margin:0 0 22px} - .rev{border:1px solid var(--line);border-radius:10px;padding:12px 14px;margin-bottom:10px} - .rev h4{margin:0 0 6px;font-size:14px} - .rev h4 .n{color:var(--accent2);font-weight:600;margin-left:8px} - .rev ul{margin:4px 0 8px;padding-left:18px;font-size:13px} - .rev .er{color:#e0685f} - .rev .kp{color:var(--accent2)} - .rev .sh{color:var(--muted);font-variant-numeric:tabular-nums} + .gaps{border:1px solid var(--accent);border-radius:10px;padding:14px 16px;margin:0 0 14px} + .gaps h4{margin:0 0 4px;font-size:15px;color:var(--accent)} + .gaps .verdict{font-size:14px;margin:0 0 10px} + .gaps ol{margin:0;padding-left:20px;font-size:13px} + .gaps li{margin-bottom:7px} + .gaps .fix{color:var(--muted);display:block} + .gaps .sh{color:var(--muted);font-variant-numeric:tabular-nums} + .rd{border:1px solid var(--line);border-radius:10px;padding:12px 14px;margin-bottom:10px} + .rd h4{margin:0 0 6px;font-size:14px} + .rd h4 .n{color:var(--accent2);font-weight:600;margin-left:8px} + .rd blockquote{margin:0 0 8px;font-size:14px;border-left:2px solid var(--line);padding-left:10px} + .rd .kv{color:var(--muted);font-size:12.5px;margin:2px 0} + .rd ul{margin:6px 0 0;padding-left:18px;font-size:13px} + .rd .wrong{color:#e0685f} .tools{display:flex;gap:7px;flex-wrap:wrap;align-items:center;margin-top:10px} .tools button{font-size:12px;padding:5px 10px} .chk{font-size:12px;border-radius:999px;padding:1px 8px;border:1px solid var(--line);color:var(--muted)} @@ -114,8 +120,6 @@ function busyRun() { return RUN && /^(writing|reviewing|revising)$/.test(String(RUN.stage || "")); } - // A shot is busy while it is being written, drawn or filmed. Any of those - // means the package on screen is about to change. function busyShots() { return (PKG.shots || []).some(function (s) { return s.writing || s.drawing || s.filming; }); @@ -141,13 +145,14 @@ if (!busy && timer) { clearInterval(timer); timer = null; } } - // A refresh keeps the tab you are on and the box you are typing in. async function refresh() { var r = await api("run_status", { run_id: runId }); if (!r.ok) return; RUN = r.run; DRAFTS = r.drafts || []; document.getElementById("sub").textContent = sub(); paintTabs(); + var rv = await api("list_reviews", { run_id: runId }); + REVIEWS = (rv && rv.reviews) || []; await openTab(CUR); tick(); } @@ -179,7 +184,8 @@ var extra = d.state === "writing" ? 'writing…' : d.state === "failed" ? 'failed' : (s && !/^(drawn|failed)/.test(s)) ? '' + esc(s) + '' - : d.score ? '' + d.score + '' + : d.score ? '' + + d.score + '' : ''; return ''); else if (undrawn) out.push(''); else out.push('storyboard drawn' + (meta.draw_usd ? ' · $' + Number(meta.draw_usd).toFixed(2) : '') + ''); @@ -244,10 +251,12 @@ var others = DRAFTS.filter(function (d) { return d.writer !== RUN.lead_writer && /^ready/.test(String(d.state)); }).length; if (RUN.stage === "reviewing") - out.push(''); + out.push(''); else if (others) - out.push(''); + out.push(''); if (RUN.stage === "revising") out.push(''); else if (REVIEWS.length || Object.keys(NOTES).length) @@ -264,26 +273,55 @@ return out.join(""); } + // What readers understood, and what the writer says it failed to say. function reviewsHtml(meta) { var mine = REVIEWS.filter(function (r) { return r.subject === meta.writer && Number(r.iteration) === Number(meta.iteration); }); if (!mine.length) return ""; - return '
' + mine.map(function (r) { - function list(items, cls, fmt) { - return (!items || !items.length) ? "" - : ''; - } - return '

' + esc(r.label) + '' + esc(r.score) + '/100

' - + list(r.errors, "er", function (e) { - return '
  • ' + (e.shot ? 'shot ' + esc(e.shot) + ' ' : '') - + esc(e.problem || "") + (e.fix ? ' — ' + esc(e.fix) + '' : '') + '
  • '; }) - + list(r.suggestions, "", function (s) { - return '
  • ' + (s.shot ? 'shot ' + esc(s.shot) + ' ' : '') - + esc(s.change || "") + '
  • '; }) - + list(r.strengths, "kp", function (s) { - return '
  • ' + esc(typeof s === "string" ? s : JSON.stringify(s)) + '
  • '; }) + var gaps = mine.filter(function (r) { return r.reviewer === "__gaps__"; })[0]; + var readers = mine.filter(function (r) { return r.reviewer !== "__gaps__"; }); + var out = ""; + + if (gaps) { + var v = gaps.strengths && gaps.strengths.verdict; + var list = gaps.suggestions || []; + out += '

    What this trailer does not tell a viewer

    ' + + (v ? '

    ' + esc(v) + '

    ' : '') + + (list.length ? '
      ' + list.map(function (g) { + return '
    1. ' + esc(g.what || "") + + 'shot ' + esc(g.shot || "?") + ' → ' + + esc(g.fix || "") + '
    2. '; }).join("") + '
    ' : '') + '
    '; - }).join("") + '
    '; + } + + out += readers.map(function (r) { + var s = r.strengths || {}, e = r.errors || {}; + if (typeof s !== "object") s = {}; + if (typeof e !== "object") e = {}; + function ul(items, cls) { + return (!items || !items.length) ? "" + : ''; + } + return '

    ' + esc(r.label) + ' watched it without reading the book' + + (r.score ? '' + + r.score + '/100' : '') + '

    ' + + (s.summary ? '
    ' + esc(s.summary) + '
    ' : '') + + '
    main character: ' + esc(s.who || "not clear to them") + '
    ' + + '
    what they want: ' + esc(s.wants || "not clear to them") + '
    ' + + '
    what is in the way: ' + esc(s.obstacle || "not clear to them") + '
    ' + + (s.would_watch ? '
    would they watch the film: ' + + esc(s.would_watch) + '
    ' : '') + + (s.unanswered && s.unanswered.length + ? '
    still asking:
    ' + ul(s.unanswered, "") : '') + + (e.missed && e.missed.length ? '
    they missed:
    ' + ul(e.missed, "") : '') + + (e.got_wrong && e.got_wrong.length + ? '
    the trailer misled them:
    ' + ul(e.got_wrong, "wrong") : '') + + '
    '; + }).join(""); + + return '
    ' + out + '
    '; } function paneHtml(meta, draft) { @@ -318,9 +356,7 @@ }).join("") + '
    '; var body = insertHtml("start"); - shots.forEach(function (s) { - body += shotHtml(s, voice) + insertHtml(s.id); - }); + shots.forEach(function (s) { body += shotHtml(s, voice) + insertHtml(s.id); }); return head + probs + '
    ' + barHtml(meta) + '
    ' + reviewsHtml(meta) + castHtml + body; @@ -420,8 +456,6 @@ + ''; } - // ------------------------------------------------------------ actions - async function act(name, payload, msg) { var r = await api(name, payload); if (!r.ok) { showMsg("msg", r.error || "That did not work."); return null; } @@ -431,7 +465,7 @@ } document.getElementById("pane").addEventListener("click", async function (e) { - var hit = function (attr) { var el = e.target.closest("[" + attr + "]"); return el; }; + var hit = function (attr) { return e.target.closest("[" + attr + "]"); }; var el, r; if ((el = hit("data-cancel"))) { EDITING = null; openTab(CUR); return; } @@ -443,14 +477,14 @@ if (rough.length < 20) { showMsg("msg", "Say what happens in the scene."); return; } el.disabled = true; r = await act("add_shot", { draft_id: CUR, after: el.getAttribute("data-addgo"), rough: rough }); - EDITING = null; if (r) { await refresh(); } return; + EDITING = null; if (r) await refresh(); return; } if ((el = hit("data-rewrite"))) { var rw = document.getElementById("rough").value.trim(); if (rw.length < 20) { showMsg("msg", "Say what should change."); return; } el.disabled = true; r = await act("write_shot", { draft_id: CUR, shot_id: el.getAttribute("data-rewrite"), rough: rw }); - EDITING = null; if (r) { await refresh(); } return; + EDITING = null; if (r) await refresh(); return; } if ((el = hit("data-drawone"))) { el.disabled = true;