From b01bd7797606b6f003d618f00b3a06726e7672d7 Mon Sep 17 00:00:00 2001 From: ribdsp <113304041+ribdsp@users.noreply.github.com> Date: Fri, 28 Aug 2026 08:50:51 +0700 Subject: [PATCH 01/12] refactor: remove personal names from code comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The repository is going open source, and per-file ownership headers in the comments do not survive that transition: `Owner: X.`, `Implemented — x, Day n:` and `TODO(x), Day n:` name people who are no longer the only readers. Comments only. Every changed line is inside a comment block, verified with: git diff -U0 | grep -E '^[+-]' | grep -vE '^(\+\+\+|---)' \ | grep -vE '^[+-]\s*(\*|//|/\*\*)' which returns nothing. Gates unchanged from before the pass: tsc --noEmit exit 0, 19 files / 257 tests passing. What was kept deliberately: - credit lines in LICENSE, README.md and CONTRIBUTING.md — those are meant to carry names - git log and git blame — history is not rewritten, and commit authorship is legitimate contribution record for an open-source project - both live TODO markers, still greppable as `TODO:` with their description intact — deleting a marker while implementing around it would destroy the only record of outstanding work Technical content in the headers was preserved rather than dropped: a header reading `Owner: X, over Y's lib/z.` becomes `Wraps lib/z.`, so the dependency it documented survives the loss of the two names. --- bugbait/scripts/record-fixtures.mjs | 2 -- bugbait/src/app/api/cities/route.ts | 2 -- bugbait/src/app/api/provinces/route.ts | 2 -- bugbait/src/app/checkout/page.tsx | 4 +--- bugbait/src/app/page.tsx | 4 +--- bugbait/src/components/recorder-panel.tsx | 2 -- bugbait/src/lib/bugs.ts | 5 +---- bugbait/src/lib/record.ts | 4 +--- traces/src/app/globals.css | 3 +-- traces/src/app/layout.tsx | 2 -- traces/src/app/page.tsx | 4 +--- traces/src/app/tool-surface.tsx | 4 +--- traces/src/components/agent/activity-feed.tsx | 4 +--- traces/src/components/agent/agent-lane.tsx | 4 ++-- traces/src/components/agent/ask-human-visual-prompt.tsx | 4 ++-- traces/src/components/agent/hypothesis-cards.tsx | 4 ++-- traces/src/components/agent/report-draft.tsx | 4 ++-- traces/src/components/player/mark-point-overlay.tsx | 4 ++-- traces/src/components/player/player-controls.tsx | 4 +--- traces/src/components/player/replay-stage.tsx | 2 +- traces/src/components/player/use-playhead.ts | 2 +- traces/src/components/timeline/annotation-marker.tsx | 2 -- traces/src/components/timeline/axis.ts | 2 -- traces/src/components/timeline/bisect-trace.tsx | 4 +--- traces/src/components/timeline/event-track.tsx | 4 ++-- traces/src/components/timeline/timeline.tsx | 4 +--- traces/src/components/ui/author-badge.tsx | 2 -- traces/src/components/ui/format-time.ts | 2 -- traces/src/components/ui/resizable-split.tsx | 2 -- traces/src/components/ui/sample-recordings.ts | 2 +- traces/src/components/ui/tool-status-banner.tsx | 2 -- traces/src/components/ui/use-clock.ts | 2 -- traces/src/lib/bisect/bisect.ts | 2 +- traces/src/lib/bisect/predicate.ts | 2 +- traces/src/lib/dom/compress-dom.ts | 4 ++-- traces/src/lib/dom/diff-dom.ts | 4 +--- traces/src/lib/dom/measure-layout.ts | 4 ++-- traces/src/lib/replay/checkpoint-index.ts | 2 -- traces/src/lib/replay/event-digest.ts | 2 -- traces/src/lib/replay/load-recording.ts | 2 -- traces/src/lib/replay/replay-engine.ts | 2 -- traces/src/lib/replay/rrweb-events.ts | 2 -- traces/src/lib/report/build-report.ts | 4 +--- traces/src/lib/store/session.ts | 2 +- traces/src/lib/webmcp/blocking.ts | 4 ++-- traces/src/lib/webmcp/polyfill.ts | 2 -- traces/src/lib/webmcp/register-tools.ts | 4 +--- traces/src/lib/webmcp/tool-types.ts | 2 -- traces/src/lib/webmcp/tools/annotate.ts | 4 +--- traces/src/lib/webmcp/tools/ask-human-visual.ts | 4 ++-- traces/src/lib/webmcp/tools/bisect.ts | 4 ++-- traces/src/lib/webmcp/tools/claim-next-task.ts | 4 +--- traces/src/lib/webmcp/tools/diff-dom.ts | 4 ++-- traces/src/lib/webmcp/tools/find-element.ts | 2 -- traces/src/lib/webmcp/tools/index.ts | 2 +- traces/src/lib/webmcp/tools/list-events.ts | 2 +- traces/src/lib/webmcp/tools/measure-layout.ts | 4 ++-- traces/src/lib/webmcp/tools/propose-hypotheses.ts | 4 +--- traces/src/lib/webmcp/tools/propose-report.ts | 4 +--- traces/src/lib/webmcp/tools/read-console.ts | 2 +- traces/src/lib/webmcp/tools/read-dom-at.ts | 2 +- traces/src/lib/webmcp/tools/read-network.ts | 2 -- traces/src/lib/webmcp/tools/read-session-meta.ts | 2 -- traces/src/lib/webmcp/tools/seek.ts | 4 +--- traces/src/lib/webmcp/tools/snapshot-finding.ts | 4 +--- traces/src/lib/webmcp/tools/tool-context.ts | 2 +- traces/src/lib/webmcp/tools/tool-support.ts | 4 ++-- traces/tailwind.config.ts | 4 +--- 68 files changed, 60 insertions(+), 146 deletions(-) diff --git a/bugbait/scripts/record-fixtures.mjs b/bugbait/scripts/record-fixtures.mjs index 65cf5fa..5baaba8 100644 --- a/bugbait/scripts/record-fixtures.mjs +++ b/bugbait/scripts/record-fixtures.mjs @@ -1,8 +1,6 @@ /** * Regenerates the sample recordings in `traces/public/recordings/` by driving a real browser. * - * Owner: Vicko. - * * **These are scripted fixtures, not human sessions,** and the difference is worth being precise about. * Everything in the resulting file is real: a real Chrome, the real bugbait build, the real * `rrweb.record()`, real HTTP to the real stub endpoints, real layout and real CSS. What is synthetic is diff --git a/bugbait/src/app/api/cities/route.ts b/bugbait/src/app/api/cities/route.ts index e1c7882..6460943 100644 --- a/bugbait/src/app/api/cities/route.ts +++ b/bugbait/src/app/api/cities/route.ts @@ -4,8 +4,6 @@ import { LATENCY_MS } from '@/lib/bugs' /** * `GET /api/cities` — always succeeds, always returns cities. * - * Owner: Vicko. - * * There is no scenario branch here, and that is the interesting part. In the `race` scenario this * endpoint behaves perfectly: 200, a full list, in under a second. The bug is entirely on the client, * which reads the list once during its first render — before this response exists — and never looks diff --git a/bugbait/src/app/api/provinces/route.ts b/bugbait/src/app/api/provinces/route.ts index f374020..3806b06 100644 --- a/bugbait/src/app/api/provinces/route.ts +++ b/bugbait/src/app/api/provinces/route.ts @@ -4,8 +4,6 @@ import { isBug, LATENCY_MS, SCENARIO_HEADER } from '@/lib/bugs' /** * `GET /api/provinces` — the request at the centre of the primary demo bug. * - * Owner: Vicko. - * * When the `empty-province` scenario is armed this returns **200 with `[]`**, and the distinction from * a 500 is the whole point. An error status shows up red in a network tab and the investigation takes * four seconds; a success that happens to be empty looks like nothing at all, and only the *shape* of diff --git a/bugbait/src/app/checkout/page.tsx b/bugbait/src/app/checkout/page.tsx index d2e8fbd..78fe393 100644 --- a/bugbait/src/app/checkout/page.tsx +++ b/bugbait/src/app/checkout/page.tsx @@ -15,8 +15,6 @@ import { RecorderPanel } from '@/components/recorder-panel' /** * The checkout form. Every bug lives here. * - * Owner: Vicko. - * * The form has to be genuinely ordinary — name, address, province, city, postcode, card, pay — because * the investigation is only interesting if the page looks like something that would ship. A page with * one dropdown and a broken button demonstrates nothing; the agent has to actually find the failing @@ -34,7 +32,7 @@ import { RecorderPanel } from '@/components/recorder-panel' * rendered markup. The recording captures the DOM; anything written there hands the agent the * answer and makes the demo a re-enactment. * - * Day 5 (vicko) — implemented. Three notes on how each bug is kept invisible in the finished DOM, + * Three notes on how each bug is kept invisible in the finished DOM, * because that property is the argument of the whole project and the easiest thing to break by accident: * * - **empty-province.** `/api/provinces` is requested the moment this page mounts and resolves 1.5s diff --git a/bugbait/src/app/page.tsx b/bugbait/src/app/page.tsx index 20fb873..acc86fd 100644 --- a/bugbait/src/app/page.tsx +++ b/bugbait/src/app/page.tsx @@ -8,8 +8,6 @@ import { RecorderPanel } from '@/components/recorder-panel' /** * The cart. The recording starts here. * - * Owner: Vicko. - * * It exists so the session has a beginning that isn't the broken page. An agent investigating a * checkout failure benefits from a recording that includes the navigation into checkout — that * navigation is in `read_session_meta`, and "the bug appeared 4s after entering /checkout" is a much @@ -18,7 +16,7 @@ import { RecorderPanel } from '@/components/recorder-panel' * Keep the interaction here small and natural: adjust a quantity, then continue. Enough to make the * session look like a real one, not so much that the demo video spends its first ten seconds shopping. * - * Day 5 (vicko) — implemented. Two things about it that are less obvious than they look: + * Two things about it that are less obvious than they look: * * - the "Continue to checkout" link carries **no** `?bug=` parameter. The scenario is armed once, on * arrival, and then lives in `sessionStorage` (see `armScenario`), because a query parameter would diff --git a/bugbait/src/components/recorder-panel.tsx b/bugbait/src/components/recorder-panel.tsx index e9d6e18..904c8cd 100644 --- a/bugbait/src/components/recorder-panel.tsx +++ b/bugbait/src/components/recorder-panel.tsx @@ -7,8 +7,6 @@ import { currentRecorder, isRecording, startRecording, type RecorderHandle, type /** * The recorder control. * - * Owner: Vicko. - * * The requirement that shapes this whole component: **it must not exist in the DOM during a take.** * rrweb captures the document, so a "Download recording" button in the capture becomes a button the * agent finds while investigating, reasons about, and possibly reports. `blockClass` would not help — diff --git a/bugbait/src/lib/bugs.ts b/bugbait/src/lib/bugs.ts index 73c5162..13ccd2e 100644 --- a/bugbait/src/lib/bugs.ts +++ b/bugbait/src/lib/bugs.ts @@ -1,8 +1,6 @@ /** * The bugs, as data. * - * Owner: Vicko. - * * Every bug is selected with a query parameter — `/checkout?bug=empty-province` — for one reason: the * recording has to be reproducible. Anyone cloning this repo must be able to produce the same session * we did, or the sample recordings are magic artefacts nobody can regenerate. A bug that only happens @@ -116,8 +114,7 @@ export const BUG_SPECS: Record = { } /* - * Day 5 (vicko) — implemented. Where each half of that assignment landed, so whoever changes a bug - * next knows which file to open: + * Where the moving parts of a bug live, so whoever changes one next knows which file to open: * * - the bugs themselves live in `app/checkout/page.tsx`, driven by `activeBug(location.search)` * - the endpoints are stubbed *inside* this app — `app/api/provinces/route.ts` and diff --git a/bugbait/src/lib/record.ts b/bugbait/src/lib/record.ts index 901a52f..60d4b84 100644 --- a/bugbait/src/lib/record.ts +++ b/bugbait/src/lib/record.ts @@ -6,8 +6,6 @@ import { record } from 'rrweb' /** * Records the session and hands back a JSON file Traces can load. * - * Owner: Vicko. - * * Two decisions here that matter more than the code: * * **Record inputs as masked.** rrweb can capture every keystroke, and this is a checkout form — @@ -268,7 +266,7 @@ export function currentRecorder(): RecorderHandle | null { } /* - * Day 5 (vicko) — implemented. What that assignment asked for and where it is: + * The three decisions in `startRecording` the rest of the pipeline depends on: * * - `checkoutEveryNms` is the load-bearing option: it forces periodic full snapshots, which is what * checkpoint-index.ts indexes and what makes each bisect probe cost ~1s instead of ~10s. Each one diff --git a/traces/src/app/globals.css b/traces/src/app/globals.css index a98fcc7..3b5a594 100644 --- a/traces/src/app/globals.css +++ b/traces/src/app/globals.css @@ -3,9 +3,8 @@ @tailwind utilities; /* - * Owner: Faiq. * - * Deliberately almost empty. The visual direction is Faiq's to make on Day 6, and a scaffold that + * Deliberately almost empty. The visual direction is a Day 6 decision, and a scaffold that * pre-picks a font stack and a palette makes that decision by default rather than on purpose. What is * here is only what the replay mechanism needs, plus the two globals that would otherwise be * rediscovered at 2am. diff --git a/traces/src/app/layout.tsx b/traces/src/app/layout.tsx index 1f0252b..bb4e0a3 100644 --- a/traces/src/app/layout.tsx +++ b/traces/src/app/layout.tsx @@ -11,8 +11,6 @@ export const metadata: Metadata = { /** * The root layout, and the only place the tool surface is mounted. * - * Owner: Faiq (shell), Vicko (registration). - * * Registration lives in a client component rendered here rather than in `page.tsx`, so it survives * navigation without re-registering. One `AbortController` inside `register-tools.ts` owns the whole * surface; scattering registration into components is the version that leaves stale tools pointing at diff --git a/traces/src/app/page.tsx b/traces/src/app/page.tsx index 114ee00..7d8f802 100644 --- a/traces/src/app/page.tsx +++ b/traces/src/app/page.tsx @@ -15,8 +15,6 @@ import { ResizableSplit } from '@/components/ui/resizable-split' /** * The whole app, on one screen. * - * Owner: Faiq. - * * Two panels, and the split says what the product is: the replay on the left is what the human is * looking at, the agent's work on the right is what the agent is doing, and the timeline underneath * belongs to both of them. Nothing here is behind a tab. A viewer should be able to watch an agent @@ -30,7 +28,7 @@ import { ResizableSplit } from '@/components/ui/resizable-split' * MarkPointOverlay is no longer mounted here: it belongs to the stage it dims, and mounting it in both * places would have rendered the question twice the day `pendingAsk` first got set. * - * Implemented — faiq, Day 6: + * What shipped, and why: * - `a` focuses the agent lane and `p` focuses the scrubber, which are the two things a hand reaches for * during the demo: hand the agent a task, then drive the replay. Both are a long mouse trip apart on a * 1280px screen, and the panel between them is where the interesting output appears. diff --git a/traces/src/app/tool-surface.tsx b/traces/src/app/tool-surface.tsx index 8650097..5e4edec 100644 --- a/traces/src/app/tool-surface.tsx +++ b/traces/src/app/tool-surface.tsx @@ -7,8 +7,6 @@ import { ToolStatusBanner } from '@/components/ui/tool-status-banner' /** * Registers every tool exactly once, and reports whether it worked. * - * Owner: Vicko. - * * The cleanup is what makes this safe, and it is not optional. React 19 in development mounts effects * twice — mount, unmount, mount — so without `unregisterTools()` on the way out you get a duplicate * surface where every call is ambiguous. Aborting on cleanup makes the double pass a no-op, and gives @@ -29,7 +27,7 @@ export function ToolSurface() { try { result = registerTools() } catch (error: unknown) { - // registerTools is Vicko's Day 3. Until it exists, the app still loads and says why it can't. + // If registration throws, the app still loads and says why it can't. const message = error instanceof Error ? error.message : 'registration failed' result = { mode: 'unavailable', registered: [] } // eslint-disable-next-line no-console -- the only diagnostic path before the banner is real diff --git a/traces/src/components/agent/activity-feed.tsx b/traces/src/components/agent/activity-feed.tsx index 6b8f19f..34c8567 100644 --- a/traces/src/components/agent/activity-feed.tsx +++ b/traces/src/components/agent/activity-feed.tsx @@ -9,8 +9,6 @@ import type { ActivityEntry } from '@/types/domain' /** * A running account of who did what. * - * Owner: Faiq. - * * The feed is correct for free if the store's rules hold: every mutation goes through an action, and * every action appends one entry carrying its `author`. If an entry is ever missing here, the bug is * in the store — something wrote state directly — and this component is the place it becomes visible. @@ -19,7 +17,7 @@ import type { ActivityEntry } from '@/types/domain' * Newest first, and undo lives on the entry rather than in a global "undo last" button. The human's * veto is per-contribution: reject the agent's third marker without touching the other two. * - * Implemented — faiq, Day 4: + * What shipped, and why: * - newest first, and the list scrolls itself to the top only when it was already there. Reading history * while an agent works is the case that matters: `[overflow-anchor:none]` plus a scroll correction keeps * the same lines under the eye in every browser, rather than depending on native scroll anchoring, which diff --git a/traces/src/components/agent/agent-lane.tsx b/traces/src/components/agent/agent-lane.tsx index 6f8fa94..cbe306d 100644 --- a/traces/src/components/agent/agent-lane.tsx +++ b/traces/src/components/agent/agent-lane.tsx @@ -9,7 +9,7 @@ import type { Task, TaskStatus } from '@/types/domain' /** * Where a human hands work to the agent. * - * Owner: Faiq. Pairs with `claim_next_task`. + * Pairs with `claim_next_task`. * * A human types a task; the agent picks it up by calling `claim_next_task`, which blocks until one * exists. That inversion is the interesting part — the agent waits on the person rather than the @@ -20,7 +20,7 @@ import type { Task, TaskStatus } from '@/types/domain' * with no click in between, is the clearest demonstration in the whole app that something else is * genuinely reading this page. * - * Implemented — faiq, Day 4: + * What shipped, and why: * - three treatments, because the flip between them is the demonstration: `open` waiting, `claimed` * with a live "working" indication and how long it has been held, `done` struck through * - Enter submits and Shift+Enter starts a newline, which needs a textarea rather than an input diff --git a/traces/src/components/agent/ask-human-visual-prompt.tsx b/traces/src/components/agent/ask-human-visual-prompt.tsx index 812f2da..6c84f27 100644 --- a/traces/src/components/agent/ask-human-visual-prompt.tsx +++ b/traces/src/components/agent/ask-human-visual-prompt.tsx @@ -10,7 +10,7 @@ import { useSessionStore } from '@/lib/store/session' /** * The panel-side view of a question the agent cannot answer alone. * - * Owner: Faiq. The clickable half lives in MarkPointOverlay, on the player. + * The clickable half lives in MarkPointOverlay, on the player. * * Split deliberately: the *question* belongs in the agent panel with everything else the agent said, * and the *answer* is given on the player, because the answer includes where the human clicked. One @@ -20,7 +20,7 @@ import { useSessionStore } from '@/lib/store/session' * When a question is pending, this is the most important thing on screen. Say what is being asked and * that the agent is waiting; a quiet card gets missed and the gate times out for no reason. * - * Implemented — faiq, Day 4: + * What shipped, and why: * - the question, that the agent is waiting, how long it has been waiting, and that the answer is given * on the player — naming `hintAtMs` when the agent suggested somewhere to look * - past `GATE_TIMEOUT_MS` the card says the first call has already returned a ticket and that answering diff --git a/traces/src/components/agent/hypothesis-cards.tsx b/traces/src/components/agent/hypothesis-cards.tsx index 8244493..ab91256 100644 --- a/traces/src/components/agent/hypothesis-cards.tsx +++ b/traces/src/components/agent/hypothesis-cards.tsx @@ -8,7 +8,7 @@ import type { Hypothesis, HypothesisStatus } from '@/types/domain' /** * The agent's ranked explanations, waiting on a human's judgement. * - * Owner: Faiq. Pairs with `propose_hypotheses`, which blocks until one is promoted or rejected. + * Pairs with `propose_hypotheses`, which blocks until one is promoted or rejected. * * The tool call is suspended while these cards are on screen. That is the point of the interaction — * the agent has done the work it can do and is now asking a person to decide — and it means the cards @@ -19,7 +19,7 @@ import type { Hypothesis, HypothesisStatus } from '@/types/domain' * all of them at once on the timeline. Checking a claim should cost one click, because that is the * habit worth building in whoever is watching. * - * Implemented — faiq, Day 4: + * What shipped, and why: * - the agent's own order, numbered 1..n, because the ranking is part of what it said — and because the * store's feed lines say "promoted hypothesis 2", which is only true if 2 is what the screen calls it * - confidence as a bar. Never a percentage: the number is the agent's claim about its own reasoning, and diff --git a/traces/src/components/agent/report-draft.tsx b/traces/src/components/agent/report-draft.tsx index a6d6452..46ac58b 100644 --- a/traces/src/components/agent/report-draft.tsx +++ b/traces/src/components/agent/report-draft.tsx @@ -10,7 +10,7 @@ import type { Recording, Report } from '@/types/domain' /** * The output of the whole investigation: a bug report the human can approve, edit, or copy. * - * Owner: Faiq. Pairs with `propose_report`. + * Pairs with `propose_report`. * * One rule this component must not soften: a step with `verified: false` is rendered **as unverified**, * next to the verified ones. `buildReport` marks a step unverified when no recorded event supports it, @@ -21,7 +21,7 @@ import type { Recording, Report } from '@/types/domain' * Every timestamp is clickable and seeks. A report whose claims can be verified in one click is the * artefact worth ending the demo on. * - * Implemented — faiq, Day 5: + * What shipped, and why: * - every field of `Report`, with each timestamp a seek * - unverified steps say the word and explain it in a sentence, once, under the list. Colour alone would * leave the distinction to whoever noticed the amber, and it is the most important distinction here. diff --git a/traces/src/components/player/mark-point-overlay.tsx b/traces/src/components/player/mark-point-overlay.tsx index ed20c07..4edd3c3 100644 --- a/traces/src/components/player/mark-point-overlay.tsx +++ b/traces/src/components/player/mark-point-overlay.tsx @@ -7,7 +7,7 @@ import { sessionActions, useSessionStore } from '@/lib/store/session' /** * The overlay that turns a human's glance into structured data. * - * Owner: Faiq. Pairs with the `ask_human_visual` tool. + * Pairs with the `ask_human_visual` tool. * * While `pendingAsk` is set, the replay area becomes clickable: the human clicks the moment they are * talking about, and that click supplies `markedTimestamp` in the answer. That is the whole reason @@ -17,7 +17,7 @@ import { sessionActions, useSessionStore } from '@/lib/store/session' * Keep the overlay out of the way when there's no question pending. An always-on click target on the * player surprises people who were trying to scrub. * - * Implemented — faiq, Day 4: + * What shipped, and why: * - the stage dims and the question sits over it, so a waiting agent is impossible to miss * - the marked moment is the playhead, shown live in the card. The stage is a *spatial* surface — a * click on it names a place, not an instant — so the moment is set on the timeline, which this overlay diff --git a/traces/src/components/player/player-controls.tsx b/traces/src/components/player/player-controls.tsx index a0b35d2..e426972 100644 --- a/traces/src/components/player/player-controls.tsx +++ b/traces/src/components/player/player-controls.tsx @@ -14,8 +14,6 @@ import { sessionActions, useSessionStore } from '@/lib/store/session' /** * Play, pause, speed, and the current position. * - * Owner: Faiq. - * * The one non-obvious requirement: the playhead position shown here is the *store's* `currentTime`, * not the Replayer's. Both a human dragging the scrubber and the agent calling `seek` write to the * store, so reading from the store is what makes an agent-driven seek visible in the UI at all. Read @@ -27,7 +25,7 @@ import { sessionActions, useSessionStore } from '@/lib/store/session' * Nothing here touches the Replayer either. Every control writes `setCurrentTime(_, 'human')` and the * frame follows through `usePlayheadSync`, which is what keeps one clock authoritative instead of two. * - * Implemented — faiq, Day 2: + * What shipped, and why: * - play/pause and 0.5× / 1× / 2×, held in local state by `usePlayback` — neither is the agent's * business, and `SessionState` is frozen * - a scrubber writing through `setCurrentTime(atMs, 'human')`, quantised to the arrow-key step so a diff --git a/traces/src/components/player/replay-stage.tsx b/traces/src/components/player/replay-stage.tsx index 76c2f7e..a215365 100644 --- a/traces/src/components/player/replay-stage.tsx +++ b/traces/src/components/player/replay-stage.tsx @@ -12,7 +12,7 @@ import { sessionActions, useSessionStore } from '@/lib/store/session' /** * Mounts the rrweb Replayer and publishes the engine so tools can drive it. * - * Owner: Faiq (component), over Riko's lib/replay. + * Sits over lib/replay. * * This is the only component in the app that owns a non-React object with a lifecycle, so it is the * only one that needs care: diff --git a/traces/src/components/player/use-playhead.ts b/traces/src/components/player/use-playhead.ts index 62f5a86..1a2e134 100644 --- a/traces/src/components/player/use-playhead.ts +++ b/traces/src/components/player/use-playhead.ts @@ -8,7 +8,7 @@ import type { Author } from '@/types/domain' /** * The three pieces of playhead behaviour the store deliberately does not own. * - * Owner: Faiq, over Riko's lib/replay and Vicko's lib/store. + * Sits over lib/replay and lib/store. * * `setCurrentTime` writes the store and stops there — see the comment on it in lib/store/session.ts, * which is about *feed noise* rather than about pixels. Nothing in the store moves the replay. The diff --git a/traces/src/components/timeline/annotation-marker.tsx b/traces/src/components/timeline/annotation-marker.tsx index 7fcaf56..e6099c4 100644 --- a/traces/src/components/timeline/annotation-marker.tsx +++ b/traces/src/components/timeline/annotation-marker.tsx @@ -14,8 +14,6 @@ interface AnnotationMarkerProps { /** * One labelled moment on the timeline, with the controls that keep the human in charge of it. * - * Owner: Faiq. - * * Two things this component is responsible for, and both are requirements rather than polish: * * 1. **Authorship is visible.** An agent's marker must never be mistaken for the human's. Colour diff --git a/traces/src/components/timeline/axis.ts b/traces/src/components/timeline/axis.ts index 0f1ea31..e7ad0f5 100644 --- a/traces/src/components/timeline/axis.ts +++ b/traces/src/components/timeline/axis.ts @@ -1,8 +1,6 @@ /** * Turning a recording time into a position on the axis. * - * Owner: Faiq. - * * Three components draw onto the same 96px strip — the axis itself, the event track and the bisect trace — * and every one of them needs the same two answers: where does this millisecond sit, and which way should * its label hang so it stays inside the panel. Keeping both here is what makes a tick, a marker and a probe diff --git a/traces/src/components/timeline/bisect-trace.tsx b/traces/src/components/timeline/bisect-trace.tsx index dd4f6a9..29ecb3c 100644 --- a/traces/src/components/timeline/bisect-trace.tsx +++ b/traces/src/components/timeline/bisect-trace.tsx @@ -9,8 +9,6 @@ import { anchorFor, percentOf } from './axis' /** * The binary search, drawn. * - * Owner: Faiq. - * * The most persuasive four seconds of the demo, and the reason to build it properly. Each probe * appears in order, the searched window visibly halves, and the answer converges on a millisecond. * A viewer who has never heard of WebMCP watches a search happen inside a web page and understands @@ -20,7 +18,7 @@ import { anchorFor, percentOf } from './axis' * Animate in trace order with a short stagger (~80ms). Rendering all six probes at once shows the * result but not the search, which is the part worth showing. * - * Implemented — faiq, Day 4: + * What shipped, and why: * - one dot per probe, in three treatments: filled bright for true, filled dim for false, and a hollow * ring for `elementMissing`. That last one is a different claim — "there was nothing to ask about" * rather than "the answer was no" — and merging the two is how a report ends up describing an element diff --git a/traces/src/components/timeline/event-track.tsx b/traces/src/components/timeline/event-track.tsx index 6112183..f848a4c 100644 --- a/traces/src/components/timeline/event-track.tsx +++ b/traces/src/components/timeline/event-track.tsx @@ -10,7 +10,7 @@ import { anchorFor, percentOf } from './axis' /** * The bottom band of the timeline: what actually happened, as ticks. * - * Owner: Faiq, over Riko's event-digest. + * Sits over lib/replay/event-digest. * * Same digest the agent sees through `list_events`, drawn instead of listed. That correspondence is * worth protecting: when the agent says "there's a failed request at 12.1s", the human should find a @@ -20,7 +20,7 @@ import { anchorFor, percentOf } from './axis' * the recording id. Recomputing thousands of events on every playhead tick is the obvious way to make * scrubbing stutter. * - * Implemented — faiq, Day 3: + * What shipped, and why: * - one tick per event, positioned through the shared `percentOf` so a tick, a marker and a bisect probe * at the same millisecond land on the same pixel * - colour is severity, from the same `severityOf` the markers use, in the same three fills — so the two diff --git a/traces/src/components/timeline/timeline.tsx b/traces/src/components/timeline/timeline.tsx index 54b56f4..0cd9a80 100644 --- a/traces/src/components/timeline/timeline.tsx +++ b/traces/src/components/timeline/timeline.tsx @@ -11,8 +11,6 @@ import { EventTrack } from './event-track' /** * The shared timeline: one horizontal axis that both the human and the agent write to. * - * Owner: Faiq. - * * This is the component that carries the collaboration claim. Everything the agent finds lands here, * on the same axis as everything the human noticed, colour-coded by author. Someone watching the demo * should be able to see, without narration, that two parties were working on one artefact. @@ -20,7 +18,7 @@ import { EventTrack } from './event-track' * All positioning is a percentage of `durationMs`, never pixels. The panel is resizable and the demo * gets recorded at a different width than anyone develops at. * - * Implemented — faiq, Day 2 (axis) and Day 4 (layers): + * What shipped, and why: * - the layers stack in DOM order, seek button *first*. Children with no `z-index` paint in document * order, so the full-area button being last was what made every layer above it unclickable and * forced `AnnotationMarker`'s `z-10`. Putting it first is the fix; the `z-10` stays because it is diff --git a/traces/src/components/ui/author-badge.tsx b/traces/src/components/ui/author-badge.tsx index 6e50588..8bfb3dd 100644 --- a/traces/src/components/ui/author-badge.tsx +++ b/traces/src/components/ui/author-badge.tsx @@ -8,8 +8,6 @@ interface AuthorBadgeProps { /** * Who did this — the smallest component in the project and one of the most load-bearing. * - * Owner: Faiq. - * * The challenge asks for the agent to have an identity distinguishable from the human's. Every marker, * hypothesis, activity line and report shows this badge, which is why it exists as a component instead * of as a colour repeated in twelve places: the day someone decides agent contributions should read diff --git a/traces/src/components/ui/format-time.ts b/traces/src/components/ui/format-time.ts index 16e8de6..fcd3740 100644 --- a/traces/src/components/ui/format-time.ts +++ b/traces/src/components/ui/format-time.ts @@ -1,8 +1,6 @@ /** * How a recording time is written on the timeline — ticks, marker labels, bisect probes. * - * Owner: Faiq. - * * One decimal, always, and always seconds. The reason it is a shared function rather than a `.toFixed` * at each call site: a human's most common act in this app is checking an agent's claimed timestamp * against the timeline, and that comparison is meaningless if the marker says `28.4s` and the tick above diff --git a/traces/src/components/ui/resizable-split.tsx b/traces/src/components/ui/resizable-split.tsx index 5cb5d7a..9762b75 100644 --- a/traces/src/components/ui/resizable-split.tsx +++ b/traces/src/components/ui/resizable-split.tsx @@ -5,8 +5,6 @@ import { useCallback, useEffect, useRef, useState } from 'react' /** * The two-panel split, with a divider a human can move. * - * Owner: Faiq. - * * There is exactly one split in this app, which is why this renders `section` and `aside` rather than * two anonymous divs: the replay is the content, the agent's lane is beside it, and that reading should * survive being handed to a screen reader. diff --git a/traces/src/components/ui/sample-recordings.ts b/traces/src/components/ui/sample-recordings.ts index 6677d8a..4e3d168 100644 --- a/traces/src/components/ui/sample-recordings.ts +++ b/traces/src/components/ui/sample-recordings.ts @@ -3,7 +3,7 @@ import type { Recording } from '@/types/domain' /** * The three sample recordings, as a static list. * - * Owner: Faiq. Shared by the picker in the header and the empty state on the stage, so the names a + * Shared by the picker in the header and the empty state on the stage, so the names a * judge reads in one place are the names that load in the other. * * Why hardcoded rather than read from the directory: Traces is a static export. There is no server at diff --git a/traces/src/components/ui/tool-status-banner.tsx b/traces/src/components/ui/tool-status-banner.tsx index d7448cf..4f4a973 100644 --- a/traces/src/components/ui/tool-status-banner.tsx +++ b/traces/src/components/ui/tool-status-banner.tsx @@ -10,8 +10,6 @@ interface ToolStatusBannerProps { /** * Says out loud whether the tool surface is actually live. * - * Owner: Faiq. - * * Without this, the failure mode is brutal: the origin trial token is missing or expired, no tool ever * registers, and the page looks completely fine. Someone loses an evening to that — probably during * judging, on a browser that isn't ours. diff --git a/traces/src/components/ui/use-clock.ts b/traces/src/components/ui/use-clock.ts index 5a95453..f67b215 100644 --- a/traces/src/components/ui/use-clock.ts +++ b/traces/src/components/ui/use-clock.ts @@ -5,8 +5,6 @@ import { useEffect, useState } from 'react' /** * A wall clock that re-renders, for the two places that show elapsed real time. * - * Owner: Faiq. - * * `ActivityEntry.at` and `AskHumanVisual.askedAt` are `Date.now()` values, not recording times, so "3s * ago" and "waiting 14s" go stale the moment they are painted. A shared ticker keeps that in one place and * makes the cost explicit: one interval per consumer, at whatever coarseness that consumer actually needs. diff --git a/traces/src/lib/bisect/bisect.ts b/traces/src/lib/bisect/bisect.ts index 0fe65c3..fd0ffa9 100644 --- a/traces/src/lib/bisect/bisect.ts +++ b/traces/src/lib/bisect/bisect.ts @@ -104,7 +104,7 @@ function finalize( /** * Binary-search the replay timeline for the first moment a predicate holds. * - * Owner: Riko. Contract: docs/tools.md#4-bisect. + * Contract: docs/tools.md#4-bisect. * * This is the idea the project is built on. The agent doesn't fetch a value; it sends a predicate and * the page runs a search, replaying to a different point in time on each iteration. Six probes over a diff --git a/traces/src/lib/bisect/predicate.ts b/traces/src/lib/bisect/predicate.ts index 191507e..8bbf5e2 100644 --- a/traces/src/lib/bisect/predicate.ts +++ b/traces/src/lib/bisect/predicate.ts @@ -3,7 +3,7 @@ import type { Predicate, PredicateKind } from '@/types/domain' /** * The security boundary of Traces. * - * Owner: Riko. Contract: docs/tools.md#predicates. Threats: docs/threat-model.md (T1, T2). + * Contract: docs/tools.md#predicates. Threats: docs/threat-model.md (T1, T2). * * A predicate arrives from a language model, so it is untrusted input in the strongest sense: it may * be malformed, it may be adversarial, and it may be a confident attempt to smuggle in an diff --git a/traces/src/lib/dom/compress-dom.ts b/traces/src/lib/dom/compress-dom.ts index 6f1489e..0e57fc8 100644 --- a/traces/src/lib/dom/compress-dom.ts +++ b/traces/src/lib/dom/compress-dom.ts @@ -3,7 +3,7 @@ import type { CompressedDomResult } from '@/types/domain' /** * The agent-legible DOM representation. * - * Owner: Riko. Full specification: docs/agent-legible-dom.md. + * Full specification: docs/agent-legible-dom.md. * * This is the most consequential file in the project, and the reason is worth stating plainly: an * unbudgeted DOM dump is a *silent* failure. Send 800 KB of HTML and nothing throws — the agent @@ -397,7 +397,7 @@ function clampToBudget(dom: string): { dom: string; clamped: boolean } { /** * Compress a DOM subtree into the agent-legible representation. * - * Owner: Riko. Specification and budget: docs/agent-legible-dom.md. + * Specification and budget: docs/agent-legible-dom.md. * * Inclusion rules, applied in priority order (see the PRIORITY_ constants above): * 1. interactive elements — input, select, textarea, button, a[href], [role], [tabindex] diff --git a/traces/src/lib/dom/diff-dom.ts b/traces/src/lib/dom/diff-dom.ts index a054771..b5b3b5d 100644 --- a/traces/src/lib/dom/diff-dom.ts +++ b/traces/src/lib/dom/diff-dom.ts @@ -190,7 +190,7 @@ function compareAttributes(selector: string, before: Entry, after: Entry, into: * `document.cloneNode(true)` is the clone that works, and it is the only one that does: `importNode` * refuses a document node outright (`NotSupportedError`, measured, in both realms). The deep clone * carries `