commit 2c4a3f4e2bac0136be81660b00232498d568e64e
parent 2f6210a883f53b3c1a3ede75bb91ecfc726379c0
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Sat, 19 Sep 2026 01:40:44 -0400
report project: "Walk the cut", above the rows
Every clip row already carried a bench link, which is the right control for
"go to that one" and the wrong one for "start": reviewing a cut is watching
every clip in order, and the first clip is where that begins. It was the
eleventh link on a long page, so the bench was findable rather than obvious.
One primary button above the rows, naming the clip it opens, with the two keys
that walk the cut and how much of it has been reviewed -- the same reviewOf()
the bench header and `umtool corrections` read. The per-row links stay.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/umtool/components/projects/ReportProject.tsx b/umtool/components/projects/ReportProject.tsx
@@ -6,7 +6,7 @@ import CopyButton from "@/components/CopyButton";
import CheckSourcesButton from "@/components/dashboard/CheckSourcesButton";
import { fmtAgo, fmtBytes } from "@/lib/format";
import { Markdown } from "@/lib/markdown";
-import { correctionsOf, readClipDetail, sourcesOf } from "@/lib/projects/report.mjs";
+import { correctionsOf, readClipDetail, reviewOf, sourcesOf } from "@/lib/projects/report.mjs";
import { EXPORT_FORMATS, exportableVariants } from "@/lib/report/export.mjs";
import { diffManifests, formatChange } from "@/lib/report/manifest-diff.mjs";
import { listSnapshots, readSnapshot } from "@/lib/report/snapshots.mjs";
@@ -14,6 +14,7 @@ import ReportBuildChain from "./ReportBuildChain";
import SnapshotButton from "./SnapshotButton";
import { decisionsForProject } from "@/lib/projects";
import { badgeVariants, type BadgeVariants } from "@/components/ui/badge";
+import { buttonVariants } from "@/components/ui/button";
import type { Severity } from "@/lib/decisions";
import type { ProjectRef } from "@/lib/project-types";
@@ -80,6 +81,9 @@ export default async function ReportProject({
text: string;
}[];
const clips = entries.filter((e) => e.kind === "clip");
+ // How much of the cut has been walked. One definition, shared with the bench
+ // header and `umtool corrections`.
+ const review = reviewOf(m);
const nonClips = entries.filter((e) => e.kind !== "clip");
const runtime = clips.reduce((n, e) => n + Math.max(0, e.end - e.start), 0);
const showAll = search.all === "1";
@@ -353,6 +357,33 @@ export default async function ReportProject({
<h2 className="micro mb-1.5">
the cut — {entries.length} entries, in array order
</h2>
+ {/* ---- the way in ----
+ Every row carries a bench link, which is the right thing for "go
+ to that one" and the wrong thing for "start". Reviewing a cut is
+ watching every clip in order, and the first clip is where that
+ begins -- so it is a button, above the rows, rather than the
+ eleventh link on the page. */}
+ {clips.length > 0 && (
+ <div
+ data-walk-cut=""
+ className="mb-2 flex flex-wrap items-center gap-x-3 gap-y-1.5 rounded border border-[var(--color-line)] bg-[var(--color-panel)] px-3 py-2"
+ >
+ <Link
+ href={`/browse/${project.id}/clip/${clips[0].id}`}
+ data-walk-start={clips[0].id}
+ className={buttonVariants({ variant: "primary", size: "lg" })}
+ >
+ Walk the cut → start at {clips[0].id}
+ </Link>
+ <span className="text-[11px] text-[var(--color-dim)]">
+ <kbd>p</kbd> / <kbd>n</kbd> move between clips
+ </span>
+ <span className="micro ml-auto" data-walk-progress="">
+ {review.reviewed} of {review.total} reviewed
+ {review.corrected > 0 ? ` · ${review.corrected} corrected` : ""}
+ </span>
+ </div>
+ )}
<ul className="space-y-1">
{entries.map((e) => {
// Anything that is not a CLIP renders generically. The timeline's