← Work · 04 / Automation · meetings

Assign or Flag

Turns a meeting transcript into owned, dated tasks. Never invents an owner.

[ N ]
meetings processed
4
owner states, not one
at-most-once
delivery, leased before send
n8n · Claude · JavaScript · Google Sheets · Gmail · Calendar · Dockerpersonal project[ year ][ repo ]
The sheet, one screenshot A few rows mid-week: task, owner, resolved deadline, the transcript line it came from, status. Include at least one row flagged unassigned. The columns are the argument — let them be readable, no annotation.
Every row traces back to a line somebody actually said.
01

The problem

Someone says "Priya will handle the pricing page" and the meeting moves on. There may be two Priyas. There may be none — she might have been on the call as a guest, or the speaker might have misremembered who volunteered.

A person reading the transcript notices the gap and asks. A system doesn't. It produces an owner called Priya and passes it downstream in exactly the same shape as a real one.

The failure isn't that a name gets invented. It's that an invented owner and a correct one are indistinguishable by the time anything acts on them — so the wrong person ignores a task, the right person never hears about it, and the record says everything is fine.

02

What changed

BeforeAfter
ExtractionOne model call producing finished rowsModel locates and classifies; code decides
Dates"By Friday" resolved by the modelResolved in code, against the meeting date
OwnersNearest matching nameExact or alias match, or flagged
AmbiguityPick the likeliestRefuse, and surface both candidates
DeliverySend, then mark it sentClaim the row, then send
ProvenanceThe extracted textThe text plus the line it came from

Anchoring dates to the meeting date rather than the current date is what made the rest reliable. A transcript processed three days late still resolves "by Friday" to the Friday the speaker meant. Anchor to now and every deadline in a late-processed meeting shifts by a week — silently, into a plausible-looking date, which is the kind of bug nobody reports because nobody notices.

03

How it works

A transcript lands in a watched folder. Its header is read in code for the meeting date, the organiser, and the attendee list, because everything downstream is measured against those three. The body is numbered line by line and handed to one model call, which returns a summary, the decisions stated aloud, and each action item with an owner, a deadline phrase, and the line number where it was said.

Code takes over from there. Deadline phrases resolve by precedence against the meeting date. Names resolve against a directory with aliases — one match assigns, no match flags, two matches flags. The excerpt attached to each item is sliced out of the original file using the line number, so it's the words that were spoken rather than the model's rendering of them. Rows are written invisible, then made visible in one update, so a reader can never catch a meeting half written.

04

Architecture

  1. Watch. A file appears in a Drive folder. Source-agnostic — the system doesn't care what put it there.
  2. Parse. Header read in code, body line-numbered, one model call against a declared schema. The response is checked for shape and truncation before anything is written.
  3. Resolve. Dates by precedence against the meeting date. Names against the directory. Four owner states: resolved, collective, unassigned, ambiguous.
  4. Commit. Rows written as drafts, then flipped to live in a single update. The dispatcher reads only live rows, so it cannot observe a partial meeting.
  5. Dispatch. Every fifteen minutes: claim the row, then send. One email per person, not one per task.
Architecture diagram Two loops sharing one table — intake firing once per meeting, dispatch firing on a clock. Draw the draft-to-live flip as a gate the dispatcher cannot see past.
Nothing is visible downstream until the whole meeting is committed.
05

The decision

A system that can't say "I don't know who" will always name someone.

The tempting version assigns everything. Most names in a transcript are unambiguous, the directory usually has one obvious match, and a system that leaves items unowned looks unfinished next to one that fills every field. Fuzzy matching would close nearly all of it, and it would be right most of the time.

It's the "most of the time" that costs. When a name matches nobody, or matches two people equally, the item is written with no owner and surfaced under Needs attention instead. The cost lands on a person: on some share of items, someone has to make a call the system could have made for them, and those items sit untouched until they do. That's a worse demo, and a better outcome, because an unassigned task fails in a section of the email specifically headed to be read.

The delivery semantics follow the same instinct. The row is claimed before the send rather than after, so a crash between "email left" and "status written" drops a reminder instead of repeating one. A duplicate teaches people to ignore the channel; a gap is recoverable, because the item is still sitting there marked open.

06

What's next

Audio in, so a recording can be dropped in the folder and transcribed in the same pass. Fuzzy resolution scoped to meeting attendees only, so a first name resolves against who was actually in the room rather than the whole directory. Chunking for long transcripts — truncation is currently detected and refused, not handled. [ Confirm before publishing ] Completion tracking, because the system knows whether a reminder went out and nothing about whether the work happened.