follow-through 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Waiga Arya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,580 @@
1
+ Metadata-Version: 2.4
2
+ Name: follow-through
3
+ Version: 0.2.0
4
+ Summary: Find the commitments in a transcript and track them until they are closed. Runs entirely on your machine.
5
+ Author: Waiga Arya
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Waiga Arya
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/Waiga/follow-through
29
+ Project-URL: Issues, https://github.com/Waiga/follow-through/issues
30
+ Keywords: transcripts,meetings,commitments,accountability,cli,offline
31
+ Classifier: Development Status :: 3 - Alpha
32
+ Classifier: Environment :: Console
33
+ Classifier: Intended Audience :: End Users/Desktop
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Programming Language :: Python :: 3.11
36
+ Classifier: Programming Language :: Python :: 3.12
37
+ Classifier: Programming Language :: Python :: 3.13
38
+ Classifier: Topic :: Office/Business
39
+ Classifier: Topic :: Text Processing :: Linguistic
40
+ Requires-Python: >=3.11
41
+ Description-Content-Type: text/markdown
42
+ License-File: LICENSE
43
+ Dynamic: license-file
44
+
45
+ # Follow Through
46
+
47
+ People commit to things out loud. In a meeting, on a call, in a voice note. The
48
+ commitment is real; the record is not. It sits inside a transcript nobody reads
49
+ again, and a week later nobody can say what was promised, by whom, or whether it
50
+ happened.
51
+
52
+ Transcription is already solved. Almost every meeting tool emits text. What is
53
+ missing is the step after: turning that text into a list of obligations you can
54
+ actually close.
55
+
56
+ Follow Through is a command-line tool that reads a transcript, finds the
57
+ statements that commit someone to a future action, and tracks each one until you
58
+ say it is done.
59
+
60
+ It reads English and Hinglish — Hindi spoken in Roman script, which is what
61
+ transcription tools return for most of India. That is not a bonus feature.
62
+ English-only rules do not degrade gracefully on a Hindi conversation: they
63
+ return nothing at all, while reporting nothing wrong.
64
+
65
+ The Hinglish rules were added after the English-only version missed the
66
+ commitments in one real Hindi-English meeting transcript, where every promise
67
+ looked like "main hi follow up dalta hu". That is a single private transcript,
68
+ scored by the person who wrote the rules. It explains why the module exists; it
69
+ is not evidence that it works. The Hinglish rules have never been measured
70
+ against any public corpus, no such corpus is known to me, and the Hinglish
71
+ example in this repository is invented.
72
+
73
+ It runs entirely on your machine. No account, no API key, no network call. Your
74
+ transcripts are never uploaded anywhere.
75
+
76
+ That is enforced, not just promised. `tests/test_offline.py` reads this package's
77
+ own source on every run and fails if any module imports something that can reach
78
+ the network, names one of the `os` functions that starts another program —
79
+ however it is spelled, including behind an alias, an aliased import, or a string
80
+ passed to `getattr` — or reaches for `__import__`, `eval` or `exec`. Each
81
+ detector has its own test proving it can fail, and one test smuggles a working
82
+ exfiltration path in to confirm it is caught.
83
+
84
+ Being precise about what that is: it is a static read of this package's source, on
85
+ a package that declares no dependencies. It is a guard against drift, not a
86
+ sandbox. It does not run the code and it cannot vouch for your Python
87
+ installation. What it does is make the offline promise expensive to break by
88
+ accident and impossible to break in the obvious ways without a test turning red.
89
+
90
+ ## Install
91
+
92
+ Follow Through needs Python 3.11 or newer and has no dependencies.
93
+
94
+ ```bash
95
+ python3 -m pip install --no-deps .
96
+ ```
97
+
98
+ ## Use it
99
+
100
+ Start with a transcript. Any plain text file works — exported meeting notes, a
101
+ transcription, or something you typed yourself.
102
+
103
+ ```bash
104
+ follow-through extract examples/weekly-sync.txt
105
+ ```
106
+
107
+ ```
108
+ 8a6295803ccc Sam by Friday I'll send the signed lease to finance by Friday.
109
+ 35a117fe08a0 owner not stated no stated deadline Can you also share the insurance certificate?
110
+ ab66f295b196 Jordan by October 3 Jordan will pull the carrier rates by October 3.
111
+ 1f0e51f8120a Jordan in 3 days I'll have a first cut ready in 3 days.
112
+ 4312edaecc56 owner not stated no stated deadline We'll need to decide on the second shift before the move.
113
+ 4095a62ef115 Jordan tonight Let me draft the shift plan tonight.
114
+ 694cf1f34f39 owner not stated no stated deadline Please confirm the headcount with HR.
115
+ 37f8c8a83e0d Alex today I'll update the risk register today.
116
+ 0bc8f26c2cae O'Brien next week O'Brien will countersign the lease next week.
117
+ ```
118
+
119
+ Five other lines in that transcript were left out on purpose: two hypotheticals,
120
+ one thing already done, one "maybe", and a "let me know". Each of them contains a
121
+ phrase the tool otherwise treats as a commitment.
122
+
123
+ `extract` records nothing. When the list looks right, keep it:
124
+
125
+ ```bash
126
+ follow-through track examples/weekly-sync.txt
127
+ ```
128
+
129
+ That writes a ledger to `.follow-through/ledger.json`. Run it again over the same
130
+ file after it has grown and only the new commitments are added — nothing is
131
+ duplicated, and nothing you have already closed comes back.
132
+
133
+ A commitment is identified by its wording, its owner, and the file it came from.
134
+ The file matters: people promise the same thing, in the same words, every week.
135
+ If last week's transcript and this week's were treated as one, the second promise
136
+ would silently match the first one you closed and disappear.
137
+
138
+ The file is recorded as the path you gave, shortened, not as an absolute path —
139
+ otherwise the same transcript would produce different ids on different machines.
140
+ One consequence worth knowing: if two directories each hold a `standup.txt` and
141
+ both are tracked from inside themselves into one shared ledger, both record
142
+ `standup.txt` and merge. Run `track` from a common parent and the paths differ,
143
+ so they stay separate.
144
+
145
+ See what is still open, close something, and write a report:
146
+
147
+ ```bash
148
+ follow-through list
149
+ follow-through close 8a62 --note "lease countersigned and filed"
150
+ follow-through report
151
+ ```
152
+
153
+ `report` writes Markdown and HTML to `reports/`. Open commitments are grouped by
154
+ person, with the unattributed ones in their own visible group — those are the
155
+ ones that actually go missing.
156
+
157
+ A worked example of the finished report is in
158
+ [`examples/expected-report.md`](examples/expected-report.md).
159
+
160
+ ## Hinglish
161
+
162
+ The same command, on [`examples/weekly-sync-hinglish.txt`](examples/weekly-sync-hinglish.txt):
163
+
164
+ ```
165
+ 30c32ccddb01 Neha kal tak Main signed copy finance ko kal tak bhej dungi.
166
+ ```
167
+
168
+ Hindi puts two things in different places from English, and both matter.
169
+
170
+ **Who is committing is in the verb ending, not in a pronoun.** `-unga` / `-ungi`
171
+ is "I will", `-enge` is "we will", `-ega` / `-egi` after a name is "she will" or
172
+ "he will" — which is how work actually gets handed to someone in a Hindi meeting.
173
+ The rules match the ending, so verbs nobody thought to list are still caught.
174
+
175
+ **When it is due is at the end of the phrase.** `kal` is "tomorrow"; `kal tak` is
176
+ "by tomorrow". Only the second one sets a deadline, and only the second one
177
+ overrules the filler list.
178
+
179
+ **The Hindi rules only run on Hindi sentences.** Roman script hides the
180
+ difference between a Hindi verb and an ordinary English word: `fungi` ends like
181
+ `karungi`, `Ortega` like `karega`, `karo` is a syrup and `bolo` is a tie. Applied
182
+ to everything, these rules invented commitments in English sentences and invented
183
+ people to own them.
184
+
185
+ So a sentence has to look like Hindi first. Either it contains a Hindi function
186
+ word — `hai`, `ko`, `kar`, `nahi` — or it contains an unmistakably Hindi verb: a
187
+ **lowercase** word ending `-ega`, `-egi`, `-enge`, `-unga`, `-ungi`. The
188
+ lowercase part is what does the work. Hindi verbs are not capitalised in the
189
+ middle of a sentence, and the English words that share those endings are proper
190
+ nouns: Ortega, Vega, Omega, Noriega. That one distinction separates
191
+ "Amazon listing Farhan update karega" from "Maria Ortega raised the issue"
192
+ without needing a dictionary of either language.
193
+
194
+ Transliteration is not standardised — people write `hu` and `hoon`, `kar dunga`
195
+ and `kardunga`. The common spellings are covered and the list will always be
196
+ incomplete. Adding to it is the single most useful contribution anyone can make,
197
+ and the rules are plain data in
198
+ [`follow_through/hinglish.py`](follow_through/hinglish.py).
199
+
200
+ ## What it will not do
201
+
202
+ This list is the design, not a disclaimer.
203
+
204
+ - **It will not find every commitment.** It matches patterns in text. Something
205
+ phrased unusually will be missed, and some of what it finds will not really be
206
+ a commitment. Every report says so.
207
+ - **It will not guess who owns something.** If the transcript does not say, the
208
+ owner stays `unknown`. It will not attribute a line to whoever was talking
209
+ most, and it will not turn `From:` or `TODO:` into an owner. "We'll decide on
210
+ Friday" commits a room, not whoever said "we", so that stays `unknown` too.
211
+ An owner is whoever the text names, which may be a team — "Legal will review
212
+ the contract" records Legal, because that is who was named.
213
+ - **It will not guess a deadline.** No timing phrase means no deadline. It records
214
+ the phrase the speaker actually used — `by Friday`, `in 3 days` — as text, and
215
+ never converts it to a calendar date, because that would mean assuming when the
216
+ conversation happened.
217
+ - **It will not decide that something was done.** Only you close an entry, and a
218
+ reason is required when you do.
219
+ - **It will not score anyone.** There is no reliability metric and no leaderboard.
220
+ - **It will not send anything anywhere.**
221
+
222
+ One rule sits underneath all of these: absence of evidence is reported as
223
+ unknown, never as a confirmed no.
224
+
225
+ ### Deliberate trade-offs
226
+
227
+ These are choices, not oversights. Each one loses something real, and each one
228
+ was measured against 1,067 real meeting records before it was made.
229
+
230
+ - **A conditional is not a commitment.** "If we extend the last call, we will
231
+ need to ask people to check the model" is rejected, and so is the genuine
232
+ undertaking that sometimes follows one. On the corpus most sentences of this
233
+ shape were conditions rather than promises, so the exclusion stays.
234
+ - **A bare third-party future is only kept when it states a limit.** "A revised
235
+ draft will be posted by Friday" is recorded with no owner. "The routers will
236
+ have the whole table" is not recorded at all, because in a technical meeting
237
+ "will" is more often a prediction than a promise.
238
+ - **An acronym never owns a commitment.** "TCPCL will wait for review" records
239
+ nothing. That also means "IESG will publish it" records nothing. A protocol,
240
+ a document and a working-group short name all look identical to a part
241
+ number, and naming one as the person responsible is exactly the invention
242
+ this tool exists not to make. Write the owner as a word — `Legal`, `Chairs` —
243
+ and it is recorded.
244
+ - **"I can" counts only at the start of a clause, and only unhedged.** "I can
245
+ write the text" is an offer. "It is nice to have this as I can just mirror it
246
+ in my code" is not, and "I could possibly reach out" is not either.
247
+ - **An exclusion applies to the whole sentence.** "I sent the draft last week
248
+ and I'll post the update by Friday" is rejected because of its first half.
249
+ Splitting a sentence into clauses reliably is a bigger change than this tool
250
+ is, and rejecting too much is the safer failure.
251
+ - **A bare institution or a country is still recorded as an owner.** "China will
252
+ continue to expand its fleet" records China, and it is a forecast rather than
253
+ anything anybody in the room can be held to. The article rule above catches
254
+ "the Committee" and "the Department"; it cannot catch "China" or "Congress",
255
+ because a bare capitalised proper noun naming a state has exactly the same
256
+ shape as a surname. Separating them needs a gazetteer or a part-of-speech
257
+ tagger, and this package carries no dependencies. It is a limit of the tool in
258
+ this genre, written down here rather than half-filtered.
259
+ - **Ambiguous narration is kept rather than dropped.** "Let me go to Mr
260
+ Pugliaresi" is floor management; "I will go to the vendor and get a quote" is
261
+ work, and one sentence does not separate them. So verbs like *go to*, *move
262
+ on* and *turn to* are only treated as narration after "let me" or "let us", or
263
+ when they address somebody by title. Everywhere else the false positive is
264
+ kept, because losing a commitment is the worse error.
265
+ - **A document under forty lines is never measured for wrapping.** Below that
266
+ the percentile is just the longest line again, which is the statistic that
267
+ failed, so short files keep the cautious rule and a wrapped one may still be
268
+ read in fragments. This is the shape of the tool's own examples, which is
269
+ worth saying: the fixtures in this repository are too short to exercise the
270
+ measurement, and that is exactly how the defect in it survived a test suite.
271
+ - **The orthography test needs the evidence to be in the file.** "Due to visa
272
+ rules, we would not comment" is refused in a transcript that says "due to"
273
+ somewhere in lower case, which any real one does many times over. In a file of
274
+ a few lines that happens to use the word only once, and capitalised, there is
275
+ nothing to contradict it and the line is recorded. The test gets stronger the
276
+ longer the document is, which is the opposite of the usual failure and worth
277
+ knowing.
278
+ - **An unmarked action item can lose its owner to the orthography test.**
279
+ "Chairs to schedule an interim", with no bullet and no deadline, in a document
280
+ that also writes "the chairs" in lower case, is dropped. Put a bullet in front
281
+ of it or a date inside it and it is kept. The test removes 630 findings on a
282
+ real corpus that were the preposition frame wearing a capital letter; this is
283
+ what it costs, and it costs it only to single-word owners that are also
284
+ ordinary English words.
285
+ - **One sentence yields one owner.** "Carsten, Jim and Christian volunteered to
286
+ review" records Christian, the name nearest the verb. It records a real
287
+ person, and it under-reports the other two.
288
+
289
+ ## How it decides
290
+
291
+ The rules are ordinary regular expressions, kept together as data in
292
+ [`follow_through/cues.py`](follow_through/cues.py) so you can read and extend
293
+ them without touching any logic. There is no model involved.
294
+
295
+ A sentence becomes a candidate when it contains someone undertaking to do
296
+ something (`I'll`, `we will`, `let me`, `let's`, `I can write`), handing work to
297
+ somebody else (`please send`, `Priya will`, `Mark agreed to`), or writing it down
298
+ as an action item (`Mark to post the revised draft`, `Ask the WG to adopt it`).
299
+ It is rejected when it is hypothetical, negated, tentative, or already in the
300
+ past — `if I get time`, `I don't think I'll`, `I might`, `I already sent`,
301
+ `Mozilla will not implement`.
302
+
303
+ Contractions require their apostrophe, straight or typographic. This reads like
304
+ a detail and is not one: `we'?ll` also matches the ordinary word "well", and on
305
+ 1,067 real transcripts that single optional character produced 36.7% of
306
+ everything the tool reported.
307
+
308
+ A question is only an assignment when it asks for something. "Could you post
309
+ that to the list?" is a request; "Can you explain the difference between the two
310
+ modes?" is a question at a microphone, and recording it as an obligation was the
311
+ tool's second largest source of noise.
312
+
313
+ Nothing quoted is read as a commitment. A scribe writing down what somebody else
314
+ said is reporting, not recording a promise, and a negated future — "X will not
315
+ do Y" — is refused in every person.
316
+
317
+ Four shapes carry a commitment without any of the words above, and all four are
318
+ read:
319
+
320
+ - **Committing in so many words.** "Will you commit to working with my office?"
321
+ and the answer, "I certainly can commit to working with you." The verb is the
322
+ cue. So is an expectation put on the record — "I hope you will consult with
323
+ the public".
324
+ - **A subject the scribe dropped.** "Fangwei: will move the model to that
325
+ format." The label already said who, so the sentence does not. Only read
326
+ where a label is present, and only for an act: "will be sending the text" is
327
+ an undertaking, "will be discussed on the list" has no agent in it and "will
328
+ need more review" is a state.
329
+ - **Reported speech.** "Jankowicz says she will abide by it." Minutes are
330
+ written afterwards, so this is their ordinary voice. The name in front of the
331
+ reporting verb is the person committing.
332
+ - **A note-style action item.** "Mark to post the revised draft."
333
+
334
+ That last one is also the most dangerous cue in the tool, because English uses
335
+ the same shape for something else entirely: "According to this scheme", "Due to
336
+ visa rules", "Thanks to the Chair". Three tests keep them apart, and none of
337
+ them is a list of prepositions.
338
+
339
+ The word after `to` has to be able to begin an infinitive. A bare verb does; a
340
+ determiner or a pronoun does not, and that makes the `to` a preposition. `be` is
341
+ allowed, because "Mirja to be the responsible AD" is a real assignment.
342
+
343
+ The head must not be a word this document also writes in lower case. A capital
344
+ at the start of a sentence carries no information — the capital is the sentence.
345
+ When the same file says "due to" and "want to" in lower case elsewhere, the
346
+ capital was punctuation. A name never gets that contradiction, and every word of
347
+ a name has to be contradicted before the head is refused, so "Mark Nottingham"
348
+ survives a document that also contains the verb "mark".
349
+
350
+ A bullet in front of the line, or a deadline inside it, overrides that last
351
+ test. Either is independent evidence that a scribe was writing an item.
352
+
353
+ Against all of that runs one more filter: a first-person undertaking whose verb
354
+ is an act of speech inside the meeting is narration, not a commitment. Yielding,
355
+ recognising, backing up, refreshing your memory and going to the next witness do
356
+ not outlive the room.
357
+
358
+ Owners come from speaker labels. `Alex:`, `[00:14] Sam Okafor:`,
359
+ `Tony Li (TL):`, `Suresh Krishnan, Kaloom:`, `ekr:` and `<mnot>` are all read as
360
+ people; a real transcript uses every one of those shapes. A first-person
361
+ undertaking belongs to whoever is speaking. A named assignment belongs to the
362
+ person named. A collective undertaking belongs to nobody. When two of these
363
+ appear in one sentence the owner is genuinely unclear, so it is left unknown.
364
+
365
+ A heading ends the current speaker's turn, including when it sits alone on its
366
+ line — `Action items:` with nothing after it. A pasted mail quote (`> ...`) ends
367
+ it too: those are somebody else's words.
368
+
369
+ Filler is treated differently from a hypothetical. "I might look at it" and
370
+ "we'll never get this done" are rejected outright, whatever else the sentence
371
+ says. "Let me know if that works" is rejected only because nothing was promised
372
+ by when — "Let me know the vendor's answer by Friday" is kept.
373
+
374
+ What counts for that second rule is a phrase that names when work is due: `by
375
+ Friday`, `before Monday`, `within two days`, `end of week`, `on Thursday`.
376
+ Merely mentioning a time does not, or "can you hear me today?" would be recorded
377
+ as a commitment.
378
+
379
+ The filler patterns match whole utterances rather than openings, because "let me
380
+ start by welcoming everyone" and "let me start the migration" begin identically
381
+ and only one of them is noise.
382
+
383
+ Three details worth knowing, because they are where this could surprise you.
384
+
385
+ A speaker label applies to the lines that follow it until the next label. That is
386
+ how transcripts work, but it does mean an unlabelled line is attributed to
387
+ whoever spoke last. A structural label such as `Notes:` ends that turn rather
388
+ than continuing it.
389
+
390
+ A word is treated as a name when it is capitalised and is not an ordinary English
391
+ word. That is a filter, not name detection. It rejects `From:`, `TODO:` and
392
+ `Actually`; it cannot tell an unusual name from an unusual noun, so a heading it
393
+ has never heard of will read as a speaker. There is a test that says so.
394
+
395
+ An owner is not necessarily a person. Whoever the sentence names is recorded —
396
+ unless an article stands in front of the name. English does not put one in front
397
+ of a person: "Priya will send the deck" names somebody, "The Committee will hold
398
+ a hearing" and "our Chairs will decide" name a thing and a role. That single test
399
+ replaces a list of institutions, and on a real corpus the institutions arrived
400
+ almost entirely wearing "the".
401
+
402
+ Transcripts are usually hard-wrapped at seventy or eighty columns, so a sentence
403
+ routinely spans two lines. Read one line at a time, nearly half of what the tool
404
+ found on raw wrapped files was cut off, and the deadline was normally in the half
405
+ it threw away.
406
+
407
+ So the file is measured first. A hard-wrapped file has a ceiling: nearly every
408
+ line stops just short of one column, and the few that pass it are a URL, a table
409
+ row or a rule of equals signs. That ceiling is read off the 95th percentile of
410
+ the line lengths, never off the longest line — the longest line is the outlier
411
+ the ceiling has to be measured in spite of. A file needs at least forty lines
412
+ before the percentile can exclude anything, and a quarter of its lines have to
413
+ sit in the band just under the ceiling; otherwise it is note-style minutes,
414
+ where joining bullets into each other would be worse than not joining prose.
415
+
416
+ In a file measured as wrapped, a line that stops short of the ceiling without
417
+ punctuation is joined to the one below it whatever case that line starts in.
418
+ Everywhere else the join only happens when the next line begins in lower case,
419
+ which is the cautious rule. The cautious rule on its own was not enough:
420
+ political testimony is full of proper nouns, so continuations begin with a
421
+ capital constantly, and half-sentences like "Venezuelans to speak their minds
422
+ has crumbled" were left looking like action items because they began a line.
423
+
424
+ Every entry keeps the quoted sentence, the file and line it came from, and which
425
+ rules fired. You can always check the tool's work against the source. The line
426
+ number is the line the sentence started on, counted the way an editor counts:
427
+ a page break inside an old plain-text transcript is not a new line.
428
+
429
+ ## Your data
430
+
431
+ - Everything stays in the directory you run it in.
432
+ - File paths are shortened before they are recorded: relative to the directory
433
+ you ran in when the file is below it, otherwise written with `~` in place of
434
+ your home directory. A file outside both is recorded in full, because by then
435
+ there is nothing left to hide.
436
+ - `.gitignore` already excludes `transcripts/`, ledgers, and reports, so your own
437
+ material does not end up in a commit by accident.
438
+ - The examples in this repository are invented. Lumen Freight does not exist, and
439
+ neither do Alex, Sam, or Jordan.
440
+
441
+ ## Tests
442
+
443
+ ```bash
444
+ python3 -m unittest discover -s tests -t . -v
445
+ ```
446
+
447
+ ## Contributing
448
+
449
+ Bounded, useful tasks are listed in [ROADMAP.md](ROADMAP.md), and
450
+ [CONTRIBUTING.md](CONTRIBUTING.md) explains how the project is reviewed. New cue
451
+ patterns are especially welcome — they are data, they are easy to test, and every
452
+ one of them makes the tool find something it used to miss.
453
+
454
+ ## Honest status
455
+
456
+ Version 0.2. The behaviour described here is covered by tests that run on every
457
+ change, and the example above is checked in and compared against real output, so
458
+ the documentation cannot drift away from the code.
459
+
460
+ What it has not had is users. If it misses things in your transcripts, that is
461
+ the most useful thing you could tell me, and an issue is welcome.
462
+
463
+ ## Against real documents
464
+
465
+ Everything above says what the tool is meant to do. This section says what it
466
+ did when it was pointed at documents nobody involved with it had written.
467
+
468
+ **How this was measured.** Which 6,320 documents, how they were selected, which
469
+ of the four measurement passes each figure below belongs to, and the complete
470
+ 800-sentence labelled set with its labels:
471
+ [`docs/corpus-manifest.md`](docs/corpus-manifest.md). Its opening section carries
472
+ the full account of how the 800 labels were produced, including the dispatch-by-
473
+ dispatch record.
474
+
475
+ ### The corpus
476
+
477
+ 6,320 real meeting records, 184 MB: 5,733 IETF working-group minutes spanning
478
+ IETF 65 in 2006 to IETF 126 in 2026, and 587 United States congressional hearing
479
+ transcripts from seven years between 2016 and 2024 (2017 and 2020 were not
480
+ sampled). Both are public records, neither was written for this tool, and no
481
+ example in this repository came from either.
482
+
483
+ ### How it was scored
484
+
485
+ A tool must not be allowed to grade itself, so two measures it did not produce.
486
+ One of them is weaker than that phrasing suggests, and the weakness is stated below
487
+ rather than left for the reader to discover.
488
+
489
+ **The scribes' own answers.** Many IETF minutes carry an "Action items" block a
490
+ human wrote during the meeting. The tool never sees that block; it reads the
491
+ discussion, and the block says what a person present thought was agreed.
492
+
493
+ **A blind labelling, by a model rather than by people.** 800 sentences were drawn
494
+ uniformly at random from a population defined without reference to this tool's
495
+ rules: any sentence in the corpus containing a marker from a fixed list of ordinary
496
+ English future and obligation words. Each was marked a commitment or not by an
497
+ isolated language model instance, five in total: four labelling 200 sentences each,
498
+ and a fifth re-labelling one block of 200 to measure agreement. The fifth agreed
499
+ with the first on 197 of 200, Cohen's kappa 0.92.
500
+
501
+ No person labelled any of the 800 sentences. The isolation was real — each
502
+ instance started fresh, was given the task from linguistic criteria alone, and was
503
+ instructed not to read this tool's source and not to look for its answers, so no
504
+ labeller could have copied it. But the labels come from the same model family that
505
+ wrote the tool being graded, which satisfies "a tool must not grade itself" less
506
+ completely than human annotation would. And the kappa is not human
507
+ inter-annotator agreement: it is two runs of one model on one prompt, so read it
508
+ as rubric stability rather than as evidence that two people would mark these
509
+ sentences the same way. The scribes' own answers above do not have this problem,
510
+ and they are the measure to weight.
511
+
512
+ ### What it did
513
+
514
+ | | v0.1 | v0.2 |
515
+ |---|---|---|
516
+ | precision, 800 blind labels | 0.131 | 0.348 |
517
+ | recall, 800 blind labels | 0.432 | 0.605 |
518
+ | recall, whole pipeline over whole documents | 0.318 | 0.455 |
519
+ | action items the scribes marked and it missed | 1,598 of 1,760 | 1,249 of 1,760 |
520
+ | findings quoted cut off mid-sentence | 62.6% | 11.7% |
521
+ | findings carrying a deadline | 1.5% | 3.7% |
522
+ | hard-wrapped files correctly detected as wrapped | 24% | 84% |
523
+ | total findings over the corpus | 90,529 | 63,540 |
524
+
525
+ Four rounds of fixes sit behind that, and `tests/test_corpus_defects.py` is
526
+ their regression suite: 88 tests whose fixtures are real corpus sentences rather
527
+ than invented ones.
528
+
529
+ The largest single defect was one optional apostrophe. `\bwe'?ll\b` matches the
530
+ ordinary word **well**, and `\bi'?ll\b` matches **ill** — 31,599 findings, more
531
+ than a third of everything the tool reported, came from that alone. It is now 96.
532
+
533
+ The worst was a quoted slogan recorded as an open obligation owned by the group
534
+ the slogan named. Two guards close it, and neither is a list of words.
535
+
536
+ Two of the four rounds existed to fix something an earlier round had introduced.
537
+ The cue added to catch `Mark to post the draft` also fired on the ordinary
538
+ English preposition, so a report carried owners called According, Deferring and
539
+ Due — 5.5% of all findings, now 1.8%. The line-rejoiner added to fix that
540
+ measured a file's width from its longest line, so one URL or table row hid the
541
+ wrap column and it missed 76% of the hard-wrapped files it existed for,
542
+ including the transcript it had been written from. Both were caught by measuring
543
+ again rather than by reading the summary of the fix. A synthetic fixture passes
544
+ because whoever wrote it wrote it clean; only real files disagree with you.
545
+
546
+ ### What this establishes, and what it does not
547
+
548
+ It establishes that the tool survives real input. 6,320 documents, zero crashes,
549
+ zero timeouts, about a seventh of a second each.
550
+
551
+ It establishes that every defect class listed above is real, because each one was
552
+ found in a document somebody actually published.
553
+
554
+ **It does not establish that this tool is good at reading your meetings.**
555
+ Standards-body minutes and parliamentary hearings are two genres it was not
556
+ designed for, in which most sentences containing "will" are prediction,
557
+ procedure or rhetoric rather than promise. These are numbers from hostile
558
+ ground, not a description of ordinary use. No measurement on ordinary business
559
+ meeting transcripts exists, because no public corpus of them does — and a
560
+ precision of 0.348 is not a good score by any reading.
561
+
562
+ Three further limits, stated rather than buried. Both corpora are hard-wrapped
563
+ at about seventy columns, so two thirds of the sampled sentences are cut
564
+ mid-line; that is what the tool sees too, but it is harsher than
565
+ one-sentence-per-line input. The whole corpus is English, so nothing in this
566
+ section says anything at all about the Hinglish rules. And 71% of what human
567
+ scribes wrote down as an action item is still missed: on written minutes this
568
+ tool finds under a third of what a person in the room recorded.
569
+
570
+ Follow Through was built with AI assistance, under human direction and reviewed
571
+ before release.
572
+
573
+ ## Licence
574
+
575
+ MIT. See [LICENSE](LICENSE).
576
+
577
+ ## Author
578
+
579
+ [Waiga Arya](https://www.linkedin.com/in/waigaarya/), Director of Business Strategy and
580
+ Innovation at Sadaway Pvt. Ltd. These tools were built for my own operating problems first.