This is the filed review document, copied at 09:19 EDT. Its dated claims remain historical. See the current update before acting on an old sign-in request or delivery status. Reply in chat with decisions or feedback.

JA source collector candidate, 20 October 2026

The collector prints a review packet from one local file you explicitly select. It preserves the selected text, identifies its exact source and line range, and can copy the Person and Role cells from team.md into seven roster proposals. It does not turn meeting headings or a line marked “Decided” into facts.

This is a reviewed local collector, with its Claude LSP evidence recorded in the review record. That review found five defects, F1 to F5, which this revision repairs, and three low notes, F6 to F8, which are accepted as described below. The repaired collector passed delivery acceptance and merged through PR79 on October 20 at 03:29 EDT, reviewed head 417d3dc6ab41c6ae41ca5de1a9a90d7566bae588, merge 213dc1f8cdc3a7e40c5a63ab18a33dce91401db2. The collector code is fa9b0579; later commits changed proposal prose. This is a local extraction tool with 30 focused checks, not an activated memory writer or scheduled job. The existing seed proposal and sidecar remain proposals; this collector does not amend them. Production memory stays off: this work changed no flags and made no Honcho, Slack, mail or other memory-service calls. That is not a fresh inspection of production settings. Current tasks remain in their owning records.

Use it

From the repository root, build the existing environment once with uv sync --locked. Then run the collector directly with that environment:

.venv/bin/python scripts/memory_candidates.py team.md --kind roster --audience team

.venv/bin/python scripts/memory_candidates.py \
  meetings/team/makala-1v1-0811-minutes.md --kind minutes \
  --section 'Palette {Palette}'

.venv/bin/python scripts/memory_candidates.py \
  docs/memory-seed/examples/personal-debrief-fixture.md --kind debrief \
  --section Account --mentioned Ben

Output is JSON on stdout. The script writes no file itself, uses the standard library plus local Git reads, and needs no authentication. To save a packet, redirect stdout to a new local review file as shown below. Avoid redirecting to an existing file you want to preserve: shell redirection happens before the collector validates the selection.

The required --kind is the reviewer's classification: roster, minutes, transcript, debrief, or unknown source. Minutes require one exact ATX heading through --section, including its {tag} if present. The selected block runs from that heading through its children and all text before the next heading at the same or a higher level. Whole-file extraction is available for source, debrief and transcript. Missing or duplicate headings fail with exit 2 and no JSON. One invocation selects one file and at most one section; repeat the command for additional sections.

Every block has a resolved absolute path, inclusive source lines, revision, source date, kind, audience and attribution. If the exact read bytes match HEAD, the revision is git:<commit>. Changed or untracked bytes get an honest working_tree marker with the base revision; sources without Git get an unversioned marker. A revision identifies the source snapshot, not the date of the recorded event.

Lines and headings

Line numbers follow what grep -n and sed -n report: a line ends at an LF byte, and nothing else starts a new one. A CRLF file keeps its carriage returns inside each line, so the excerpt is the stored bytes exactly. U+2028, U+0085, form feeds and a lone carriage return are ordinary text. Python's str.splitlines treats several of them as breaks, which is why the earlier version reported a line number one too high in a file containing U+2028.

A heading is an ATX line: up to three leading spaces, one to six hashes, at least one space or tab, then the title. A closing run of hashes, preceded by a space or tab, ends the line and is not part of the title. So ## Decision ## has the title Decision, while ## C# keeps C#. Four or more leading spaces make an indented code line, not a heading. No other Markdown is parsed.

Fenced code blocks open with three or more backticks or tildes and close with a fence of the same character at least as long. Headings and Date lines inside a fence are ignored. An unclosed fence hides everything after it, as it does in CommonMark. The excerpt itself is never altered by these rules.

Dates

A recorded date comes from a single Date: or **Date:** line outside fenced code. The collector supports an ISO day or the English day/month/year format used by the demonstrated minutes. The raw recorded value and its line are retained. Unsupported or malformed recorded dates remain null with recorded_unparsed; undated sources remain unknown. Nothing guesses a date from a filename, file timestamp, due date, or Git commit. A Date line inside a fenced quote, such as a pasted message, does not become the source's date.

--date YYYY-MM-DD supplies a real source date when the reviewer knows it. It wins over anything in the file, is labelled supplied, and rejects malformed values. It is not an observation date. Multiple Date lines outside fences require an explicit date choice.

Audience and attribution

All complete source blocks stay toberton_only, including the roster table. That table contains Chrissy's private Messages routing in its Main lane column. --audience team applies only to the exact Person and Role proposals parsed from this checkout's team.md; it does not broaden the source excerpt or copy the Main lane prose into those proposals. Incoming, forward, Slack aliases and other qualifiers remain exactly as written, without resolving identities or claiming an incoming role is active. The parser requires the known three-column table and rejects malformed rows. It does not parse other tables as rosters.

Minutes and unknown sources produce review-required blocks with no inferred speaker. Transcripts produce evidence_only blocks and no fact candidates; even existing speaker labels are unverified.

--kind debrief declares the account holder as Toberton. The packet records account_of: "Toberton" with account_of_origin: "caller_supplied_not_verified", and its basis says the same. The collector cannot see who wrote the text, so a file that quotes someone else passes through with the same declared holder. Choose --kind source for any text whose author you have not confirmed.

Repeated --mentioned options record names supplied by the reviewer, with that origin explicitly marked. A mention never becomes a speaker or a claim about that person's belief. Filenames containing transcript or debrief cannot accidentally be classified as minutes, but these filename checks are guardrails, not semantic classification of text.

Packets carry the absolute local path of their source, including on each team-audience candidate. That path names this Mac's user and workspace. It stays in the packet on purpose, as provenance, and the packet stays private. Copy a team-audience proposal anywhere else only after removing that path.

Each packet says proposal_only: true and memory_writes: false; every source block and roster proposal has seed_eligible: false. No content is automatically promoted into a seed. Selected blocks can still contain tasks, finance, instructions, tentative discussion or other sensitive text: they are preserved as private evidence for review, not classified as seed facts. Audience labels are metadata on a local packet, not enforced retrieval isolation. Keep the complete packet private, including a packet whose roster proposals are marked team.

Demonstrated packets

These commands made the saved examples at source HEAD a00779df1d4b65fb3301312cb3122afb4d1f9797, the commit before the one that saves them. A saved revision names the commit whose bytes matched the read when the packet was made, so the revision and the commit that stores the packet differ by design.

.venv/bin/python scripts/memory_candidates.py team.md --kind roster --audience team \
  > docs/memory-seed/examples/team.json
.venv/bin/python scripts/memory_candidates.py \
  meetings/team/makala-1v1-0811-minutes.md --kind minutes \
  --section 'Palette {Palette}' > docs/memory-seed/examples/minutes.json
.venv/bin/python scripts/memory_candidates.py \
  docs/memory-seed/examples/personal-debrief-fixture.md --kind debrief \
  --section Account --mentioned Ben > docs/memory-seed/examples/personal-debrief.json
Example Exact source selection Source date Output
Roster team.md:7–15, git:a00779df… Unknown; the table is undated 1 private source block, 7 exact Person/Role proposals explicitly marked team
Minutes meetings/team/makala-1v1-0811-minutes.md:11–18, git:a00779df… 2026-08-11, recorded on line 3; time retained in raw metadata 1 private review block, 0 fact candidates
Personal debrief docs/memory-seed/examples/personal-debrief-fixture.md:8–11, git:a00779df… 2026-10-20, recorded on line 3 1 private review block, account_of Toberton with origin caller_supplied_not_verified, mentioned Ben, speaker null, 0 fact candidates

The debrief packet's revision changed from a working-tree marker to git: in this revision, because the fixture is now tracked and its bytes match HEAD. The earlier working-tree marker described the read made before the fixture was committed in 2f207d59, and that record stays accurate for that read. The debrief fixture is invented test material, not a JA meeting or a statement about Ben.

The tests also read the narrative ## 1. Palette {Palette} section at lines 46 to 55, which the saved minutes packet does not use.

Verification

The repair pass ran these checks on the repaired code:

uv sync --locked
  26 resolved, 24 checked; exit 0
.venv/bin/python -B -m pytest -q -p no:cacheprovider scripts/tests/test_memory_candidates.py
  30 passed in 0.28s (25 existing, 5 new for the repairs)
.venv/bin/python -m ruff check scripts/memory_candidates.py scripts/tests/test_memory_candidates.py
  All checks passed
.venv/bin/python -m ruff format --check scripts/memory_candidates.py scripts/tests/test_memory_candidates.py
  2 files already formatted
pyright
  0 errors, 0 warnings, 0 informations (repository command, pyright 1.1.414)

The lock was checked at the reviewed head, and pyproject.toml, uv.lock and pyrightconfig.json have not changed since. Nothing else imports the collector, so no broader suite ran. The tests cover actual roster and minutes locations, exact excerpts including CRLF and a long block, LF-only line numbers with U+2028, closing and indented headings, fenced headings and Date lines, malformed, unknown and supplied dates, transcript versus debrief attribution including the declared-origin marker, private audience defaults, failed selections, no automatic seed eligibility, CLI failure status, and a fresh extraction after a source edit. Git provenance checks use a disposable temporary repository, not the shared checkout's index.

The LSP lookups and diagnostics for the repair, and the disposition of every finding from the review, are in the review record's repair section. Its only diagnostic is the pre-existing _lane hint, which the command-line pyright does not print.

Launch evidence: Orca dispatch ctx_e5df69890744 reports requested/effective gpt-6.1-sol and high; the actual parent process, PID 61817, has those launch arguments. Session 01a157ff-de1e-7ab1-8b59-2b6fdc1f2114 records the same model and effort in turn_context. The loaded config names context 300000 and compaction 270000; the session's token_count reports usable model_context_window: 285000. These are separate readbacks; no 1M context or settings change was used.

No history, hash store, index, server, schedule, database, automatic discovery, changed-file selection, retirement tracking or memory writer was added. Each invocation is a fresh extraction. The source proposal's broader update/delete seams remain future proposals; this tool does not track supersession or remove anything. It has no semantic secret detector, identity resolver, truth checker or automatic date repair. Selected text is never truncated or split. UTF-8 and ATX headings, read with the rules above, are the supported source formats.

The worktree's .venv and Ruff cache are deliberately retained for ordinary use. No server, browser, background worker or long-running test process was started by this repair. The repair commit names only the collector and its tests, this guide, the review record, and the three regenerated examples. The delivery receipt above closes that candidate handoff; the recorded LSP and focused results are reused, not rerun for this documentation update.