How to review a call
The method these records are written to — a coverage ledger, three mechanical scans, and a two-pass rule.
| Field | Value |
|---|---|
| Version | 2.2 |
| Written | 2026-08-21 |
| Updated | 2026-08-22 |
| For | A Cowork/chat session reviewing a Fireflies recording and producing notes |
| Companion doc | Build state v3.1 — the full build state, same folder |
| Open items | Open items v1.6 — the D-register, and the only one |
| Subject file | the simulator |
BLUF — what you are doing
You are reading a call transcript about the BoRo Stage 2 chat lifecycle simulator and producing notes a build session will act on directly.
Critical framing: the call reviewed the build described in §2 and §3 of this brief. It happened after that work, and the participants had it in front of them. So most of what you hear will be feedback on specific things that already exist — a card, a chip, a timer, a menu — not blue-sky discussion. §3 is a vocabulary map for exactly that reason: when someone says “the plate” or “the overdue card” or “In process”, you need to know what they are pointing at.
Your job is not to summarise. Sort what was said into six buckets:
- Answers to the open questions in §5 — highest-value output
- Change requests against something in §3 that already exists
- New scope that does not exist yet
- Contradictions — where the call conflicts with a ratified decision (§4) or a hard rule (§6)
- Confirmations — something was reviewed and explicitly approved. These matter: several items in §5 are waiting on exactly this, and “he said it looked right” closes them.
- Acknowledged gaps — anything either party says is not done, still to do, or forgotten. Distinct from New Scope (nobody has claimed it) and from a Change Request (it exists and is wrong). Added v2.1: the first pass over the 2026-08-21 call lost two of these — “I got to do the form” and “I didn’t do the QR one” — because a five-bucket sort has nowhere to put them.
Identify speakers from the transcript rather than assuming. Likely: CJ Oltman (owner, ratifies design decisions), Brad Larson (developer, owns the lifecycle logic and the original file), Jaydan Nguyen (workshop). Attribution is not optional — eight items in §5 can only be settled by Brad, so “the team agreed” is unusable for those.
1 / What the thing is
A single self-contained HTML document — a 23-stage clickable simulation of the BoRo rental conversation, about 175 KB. It is a specification, not a prototype: product-side buttons are deliberately inert, with one exception (the conversation-list filter). It is what the developer builds from.
Two layers, deliberately distinct:
- Capture wrapper — blue-slate tooling chrome that never wears product colour. Controls: Renter/Lender, the stage picker, Prev/Next, Desktop/Mobile, Dark/Light, Lane A/Lane B (with an ⓘ explainer), and Notes/Styles/Hidden for the bottom panel.
- Product preview — the real BoRo chat on the shipped Design System tokens, synced to
boro-tokens.cssv2.9 / DS v2.21.
The Styles panel is the design handoff — a live token map, component geometry, and ~50 flags recording every ratified decision, deviation and open question. Any decision from the call has to land there.
2 / What was built immediately before this call
All of this is new as of 2026-08-21 and is the most likely subject of the discussion. Roughly in order:
Polish batch 2
- Timers, two weights — display (big numeral + progress bar) and line — with one magnitude formatter: a date over a week out, days inside a week, minutes inside a day, seconds only in the last hour.
SESSION_MINUTES30 → 45, applied per FSD §10.2. The cards used to say “30 min window”.- Map plate on the five location cards.
- Date separators, emitted only where the day changes.
- Segment counter (five pips, current amber) for Lane B, plus the Lane A / Lane B toggle.
- A
latecard — the stage previously had a red chip over a green “Return meetup” card and nothing else. - Deleted the dead
.action-rowthe composer was still emitting behinddisplay:none. - Fixed card foot padding — the terms panel was sitting flush on the card border.
Token resync — the file was on tokens v2.8 while the DS had shipped v2.9. One value had drifted:
light --content-tertiary, which was failing AA on every surface. Fixed by adopting the DS’s stone-550.
Batch 3
- Light chips became a tint (Lab 14) — matching dark’s construction with a deeper ink shift.
- Chip dictionary — three renames across five stages.
- Card actions run full width, side by side when the labels fit, stacked when they don’t.
- The thread became cumulative — the single biggest change. See §3.
- Lane toggle gated to the stages it affects, with a hover/focus explainer.
Batch 4 — the round of feedback just before the call
- Map pin centred in the geofence and ~40% smaller, reversing “anchored at the tip, ring raised 9px”.
- The plate carries no status colour — pin and ring were taking the card’s tone.
- The map redrawn to read as a place — road casings, a diagonal, parkland, water.
- One 12px gap between every card block, replacing per-block margins.
- “Check-in · One arrived” disappears once both have arrived.
- The inspection card became “In process” — amber, clock icon — instead of green/Approved.
- Short button labels — Complete & Rent Item, Finish & Return Item.
- An entry point for extensions — the stage existed with no way to reach it.
- Real product names — DeWalt 20V MAX Cordless Drill, Ryobi 1900 PSI Electric Pressure Washer, Dyson Airwrap Multi-Styler.
Batch 5
- Badge vocabulary closed — “Approved” was on eleven of twelve cards in a finished thread.
- Bolding — fact labels, the
Commitment hold:lead-in, timer labels.
Batch 6 — landed last
- The rental now carries the display timer, same as the inspection session, settling to a line once past.
- Sidebar restructured — Renting/Lending toggle full width under the headline, filter beside it (All · Needs your action · In process · Completed · Cancelled & terminated). The filter works.
- ⋮, “+” and filter menus all drawn open and gated, disabled items showing their reason.
- On desktop the chip moved to the relation line under the product name; mobile keeps the right edge.
Two labs published for review
- Light Chip Tier (Lab 14) — the light-chip tint decision. Ratified.
- Line Timer Lab (Lab 15, round 2) — how to bind a line timer’s label to its value. Still open.
3 / Vocabulary map — what people are pointing at
The 23 stages, in picker order:
interest · inspection-requested · inspection-scheduled · gps-checkin · gps-one-arrived ·
qr-handshake · inspection-underway · inspection-return-confirm · inspection-concluded ·
rental-requested · rental-scheduled · rental-underway · extension-requested · return-scheduled ·
return-assessment · review-pending · rental-concluded · schedule-denied · cancelled ·
terminated-noshow · late · dispute · not-returned
The cards that can appear in a thread (a “lifecycle card” — white, elevated, 3px status rail, icon in a filled disc):
| Card | When |
|---|---|
| Try-on / inspection meetup | proposed → approved → completed |
| Schedule denied | the denial branch |
| Check-in · Nobody here yet / One arrived / Both arrived | the check-in chain |
| Inspection timer | the running 45-minute session |
| Item returned · Try-on complete | after the try-on |
| Rental pickup meetup | proposed → approved → completed |
| Rental active | the live rental, with the display timer and (Lane B) the segment counter |
| Extension requested | the extension branch |
| Return meetup · Condition assessment / Condition accepted / Damage flagged | the return |
| Rental complete | settlement + review window |
| Return is overdue | the 9-hour grace clock |
| Meetup no show · Item not returned | terminal |
Components, by the name people use
- chip — the status pill (header + conversation rows). Tone derives from rental status.
- badge — the pill on a card header. Closed vocabulary: Approved · Completed · Active · Pending · In process · Ready to pair · Under review · Flagged · Denied · Overdue · Expired · Closed.
- the plate / the map — the map plate with the 100-ft geofence ring and the centred pin.
- display timer vs line timer — the two weights.
- the pips / segment counter — Lane B’s five six-day segments.
- the sheet / the menu — ⋮ (utilities), “+” (lifecycle actions), and the list filter.
- the dock and the brand header — both were built and removed; if they come up, they are gone by decision, not by oversight.
- Lane A / Lane B — ≤$100 no Shield vs $101–$1,000 with Shield and Refresh Taps.
- Refresh Tap — Lane B’s mid-term Shield re-authorization. Not built yet.
The thread is cumulative. Every event at or before the current stage renders, so a completed rental shows 12 cards where it used to show 3. Only the event at the current stage is live — everything behind it has no running clock and no buttons. If someone says the thread is “long”, this is why, and it was deliberate.
4 / Ratified — do not re-open, but DO flag reversals
Most of these were ratified in the same session the call reviewed, so the call may well be reacting to them. If it re-litigates one, write it up as a reversal with who asked and why.
- Chip tone derives from status, never a hand-picked hue.
disputed→ error. - Both themes are a tint. Light = hue at 34%, label pushed 55% toward black. Dark = same wash, label lifted 35% toward white. The percentages differ because a literal mirror fails AA on every tone.
- Rails, discs and bars take the opaque
--hue-*set — never the chip wash. - Reading column 760px, left-aligned. Composer is three controls. Card actions full width.
- Timers: two weights, not four. Display for a clock you are standing in — the session, the rental, the grace window. Line for a date that qualifies something else.
- Map plate: pin centred, no status colour, no venue label.
- Menus drawn open and gated; a disabled item shows its reason rather than hiding.
- My chat bubble is
surface-inverse, not brand red. Messages group into runs. - Approve is Primary, Deny is Neutral. Brand red is spent exactly twice on a thread.
Numbers from the FSD — not negotiable without an FSD change
- Session = 45 minutes, one per phase (§10.2).
- Late grace = 9 hours, hard (§12.1), two paths: self return (free), BoRo Recovery ($25 + $0.75/mile).
- Max term 30 days both lanes; Lane B = five six-day segments, four Refresh Taps (§13.1, §13.4).
- Geofence = 100 feet (§10.1).
5 / The open questions — what we are listening for
If the call answers or confirms any of these, quote the exact words and name the speaker.
Only Brad can settle these
| # | Question | Status |
|---|---|---|
| 1 | A real Late chip? |
His note says “Intentional: no Late chip” — but the overdue card now carries an Overdue badge while the chip above it still reads Rental · Underway. One line to add. |
| 2 | A chip for extension-requested? |
His note: “Chip does not change — keep it loud.” |
| 3 | Cancelled vs Terminated on a no-show | Ops and finance need to tell user-quit from no-show. |
| 4 | Close-while-accepted |
Live code allows closing after a hold is authorized. Blocked, or priced as a forfeit? |
| 5 | Composer in the review window and in a dispute | Read-only, support-only, or normal Send? |
| 6 | Hold amount on the pending card? | Currently only in the terms panel. |
| 7 | The late card’s copy + its BoRo Recovery action |
Card is new and FSD-derived; BoRo Recovery is not in his renterCan list. |
| 8 | SESSION_MINUTES 30 → 45 |
Applied per FSD. His gap note still carries the question against live inspection_duration_minutes. |
Integration / process
| # | Question |
|---|---|
| 9 | boro-shared/tailwind/boro-theme.css carries no semantic tokens — only the brand ramp, two surface steps, spacing and radii. There is nothing in the app to build this against. This is the real integration blocker. |
| 10 | CSS variables vs Tailwind for the handoff |
| 11 | Does the full DS token set land in boro-shared? |
| 12 | Repo / branch currency, Figma link and edit access |
| 13 | RentalStageChip.tsx fails WCAG AA on 5 of 12 states — worst 2.00:1 on the chip meaning a lender owes a decision. Live in the app today. |
In front of CJ right now
| # | Question |
|---|---|
| 14 | Line timer treatment — Lab 15 round 2 recommends icon + sentence (“Meetup starts in 1 day”). Round 1’s pill was rejected as underwhelming. |
| 15 | Past segment pips drawn in success — the ratified decision named only “current one amber”. |
| 16 | Is the Lane A / Lane B toggle worth keeping before Refresh Tap gives Lane B more to differ on? |
| 17 | The badge spread on a long thread — a finished rental now shows many Completed badges in a row. Reviewed but not settled. |
6 / Hard rules — flag anything that breaks one
Not preferences. If the call asks for something that violates one, write it up as a conflict, not an action item.
STAGES[],SAMPLE_CHATandALWAYSare Brad’s master — verified byte-identical on every deploy (STAGES[]= 26,286 characters). Labels, dates and copy are derived in the presentation layer instead.- Token drift is checked on every deploy. A colour value change is a DS-doc-first change.
- Where the FSD and a built screen disagree, the FSD governs and the screen is the defect.
- Verify by measurement, never by eye.
(Corrected 2026-08-24. Over-stated as written.
Universal_SOP§3 settles it: measuring and looking catch different classes and neither is reachable from the other — measurement catches a value one step off or a state that never renders; looking catches a semantic contradiction nobody thought to assert. The rule is measure and look. Two defects passed the suite and were caught by a screenshot in seconds — a form whose two buttons both read Cancel and meant opposite things, and a contact-sheet tile that ejected every card action into the grid. A third followed on 2026-08-24: eleven places where a lost space rendered as “another onHandoffs”. This entry is left as written because it is a record of what was said on the day.) - Sample items are screened against Terms of Service §8.4 — not FSD §14.3, which has no item schedule. Any new sample item named on the call must be screened by make and model.
7 / What is queued, so new asks land in the right place
Polish batch 2— done- Chip dictionary — three renames done; items 1–2 above are what remain
- The two check-in chains — biggest lift. Pickup and return. Reuse the inspection components, do not fork
- Eight form stages — meetup chooser, propose try-on, propose pickup, cancellation confirm, report a problem, extension request, flag damage, condition capture
- Refresh Tap —
refresh-tap-due/refresh-tap-failedwith the mandatory double-hold disclosure - All-stages view (cumulative history itself is done)
Menu gating— done
If the call introduces new scope, say where it slots in and what it displaces.
8 / How to write the notes
One markdown document, these sections, kept short — a build session will act on it directly.
## BLUF
Two or three sentences: what the call changes about the work.
## Confirmations
What was reviewed and explicitly approved. Include the question number from §5 where it closes one.
## Acknowledged gaps
Anything either party said is not done, still to do, or forgotten. Quote it and name who said it.
## Answers to open questions
Per item: the §5 number, the answer, the exact quote, who said it.
Then say plainly which of the 17 were NOT addressed — a blocker that stayed blocked is a finding.
## Change requests
Against something that already exists in §3. Name the component, what changes, who asked.
## New scope
What does not exist yet, and where it slots into §7.
## Conflicts to resolve
Anything contradicting §4 or §6, or the FSD. Quote both sides.
## Not actionable
One line. Context worth knowing that implies no change.
Coverage obligation — do this before writing a word
The sections above specify the output. They do not by themselves oblige you to account for the input, and that is how the first pass over the 2026-08-21 call lost two acknowledged gaps: a bucket sort silently discards whatever fits no bucket.
- Build a coverage ledger. Split the transcript into blocks — one per stage on a walkthrough call, about two minutes otherwise. Every block must yield either a numbered note or an explicit “no action.” A block with neither is a block you have not read. Coverage is then checkable rather than felt.
- Run the mechanical scans before writing, not after:
- Owner statements —
I (got to|need to|didn't|haven't|have to),we (still have to|need to|didn't),missing,forgot,gotta. These are spoken in five seconds with no emphasis; they do not stand out on a read but they do to a regex. This is the scan that catches bucket 6. - Unanswered questions — every
?from either speaker: answered within ~10 lines, or it is an open item. - Hedges near decisions —
I guess,we'll see,for now,I don't know,maybe,probably. A hedged direction is not a ratification and must not be written up as one.
- Owner statements —
- Two passes, always. Pass 1 extracts. Pass 2 re-reads the transcript against your written notes, looking only for content the notes do not cite. Never write from a single read.
Rules
- Quote, don’t paraphrase, for anything that changes a decision. Name the speaker every time.
- Do not invent agreement. Discussed-but-unsettled is a legitimate and more useful answer than a confident wrong one.
- Do not soften a conflict. If the call asks for something that breaks §6, say so in those terms.
- Silence is data. If a whole area of §2 went unmentioned, say so — it usually means it is accepted.
- If it is unclear who said something, say it is unclear rather than guessing.
9 / Changelog
v2.1 — 2026-08-21. Added bucket 6, Acknowledged gaps, and the §8 coverage obligation — a coverage ledger, three mechanical scans, and a two-pass rule. Both come from a real failure: the first pass over the 2026-08-21 call dropped two acknowledged gaps that were plainly in the transcript, because a five-bucket sort has nowhere to file “I have not built this yet.” Also corrected the companion reference, which pointed at Build state v1.7; it is v2.1. Nothing else changed.
v2.2 — 2026-08-22. Companion reference corrected again — it pointed at HANDOFF v2.1 and that document is
now v3.1 — and a pointer to the open-items register added, since a reader producing call notes needs to know
where a D-tag is authoritative. This is the second time this line has gone stale, which is the argument for
the pointer being to the register rather than to a version number. Nothing else changed.
v2.0 — 2026-08-21. Written for the post-build review call.