Repository navigation
Parse records Observer already reads: direction blocks, Codex durations, Grok MCP, read success, Codex Read #128
Description
What: Observer parses records it already reads but currently drops or misreads: current AgentsMD direction blocks, Codex command durations, Grok MCP start/completion records, failed reads counted as reads, and Codex Read function calls.
Why: a measured gap inventory on bestia (2026-10-19, see #21) found these parser defects silently blank fields that open Issues need (version comparisons for #52, timing for #25, procedure-read evidence for the Cue adoption report).
So what: an agent implements the five parser fixes with fixtures; no user decision is needed.
Outcome
Each listed native record shape is imported with its real meaning, old ledgers re-derive the fields on the next sync, and anything still unparsed stays visible as a gap, never as a silent NULL.
Contribution to the Objective: native records durably cover usage, tool, skill, read and execution events (Objective "Done when", first bullet).
Measured gaps (bestia ledger, 2026-10-19 13:23-13:55 Warsaw, installed 1.2.6 and checkout c1b563e)
| Gap | Evidence | Needed by |
|---|---|---|
BLOCK_RE (agent_observer/identity.py) requires the end marker right after the JSON, so current sectioned direction blocks are rejected |
1,781 headers / 212 Claude sessions; 1,753 / 917 Codex sessions | AgentsMD version breakdowns (#52, compare) |
Codex _duration accepts only numbers; native durations are {secs, nanos} objects |
61,556 Codex exec results with NULL duration (rechecked by the coordinator) |
#25 |
Grok MCP start/completion records are quarantined in import_errors |
1,095 starts / 234 files; 1,092 completions with duration, success, timeout and retry | #25 |
Failed or pending commands still produce skill_read |
Codex 109 skill reads on exit 1/2; Grok 14 on error, 5 without a result | Cue adoption report (did the agent successfully read the procedure) |
Codex function_call named Read stays a tool_call, never read/skill_read |
Parser branch confirmed; 0 local occurrences on bestia, unknown on rocky and cavallo | Cue adoption report |
Elon record
- Requirements and who asked: fill measured, important capture gaps and drop the rest (the user, 2026-10-19); each row is tied to an asked question (Spectrum council reviews moments where agent work failed the user (confusion, frustration, wrong requirement, inefficiency) #52, Report task completion time, agent durations, failures and recovery delay (Chromeria/Prism evidence) #25, the user's "do agents read the procedure when Cue says it applies?").
- Deleted: passive hooks (no measured gap needs one); task-level quota attribution; Grok multi-location reads (0 affected).
- Bottleneck: parsing records Observer already reads.
- Checked myself: read
BLOCK_REand Codex_durationonc1b563e; reran the Codex NULL-duration count (61,556).
Acceptance criteria
- The current direction block (with section markers and the nonce-carrying end marker) yields validated instruction identity; the old format still parses; marker-shaped free text still fails closed.
- Codex
{secs, nanos}durations becomeduration_ms; numeric forms keep working. - Grok MCP start/completion records import as tool timing and outcome, joined by call ID to existing tool events without double counting.
- A read event carries attempted, failed, pending or successful state; reports that count procedure reads count only successful ones.
- A Codex
Readfunction call with a successful result becomesread, orskill_readunder a Skill directory. - Re-sync of an existing ledger fills these fields idempotently; the capability matrix describes the result.
Design review
- Independent review: Sol (gpt-6.1-sol, medium) gap inventory with read-only queries, 2026-10-19; Grok (grok-4.7, medium) design review found the Codex
Readand failed-read defects. Changes inside existing adapters, no new component. - User decisions: fill important measured gaps, drop the rest (the user, 2026-10-19).
Non-goals
New hooks, ContextMD import (separate Issue), quota parsing (#6), inferring anything a record does not state.
Blockers
None.
Required proof
Fixture tests for each shape (failing first), full suite output, and before/after counts of the queries above on a ledger copy, recorded on this Issue.
Activity
lukemaj commentedon Oct 19, 2026
What changed: The five native parser gaps are implemented in PR #130, with read-state reports and old-source replay.
Why: Existing records were dropping direction identity and timing or overstating successful procedure reads.
So what: The tested and independently reviewed implementation is ready for the merge decision; merge and release remain unperformed.
Candidate and authority
/home/luke/dev/toolboxmd/agent-observer-worktrees/128-parser-gaps; branchfeat/128-parser-gaps.1fbbb0fe3098842d19e04bc5a6b35a3667ecda90; head:8647f156de05bc506f574ae94f28024fd5d3d5d7, pushed to origin.report.pychanges. Shared ingest/privacy changes are limited to replayed durations, read-state enums and MCP metadata.Elon record
Requirements and who asked: The user and #128 require the five measured parser repairs, failing-first fixtures, successful procedure-read counts and idempotent old-ledger repair, including the follow-up multipath review repair and Codex identity check.
Deleted: New hooks, new importers, ContextMD work, release/version changes and new schema tables are unnecessary.
Bottleneck: Correct derivation from existing native records.
Checked myself: Read the exact parser paths, observed six new fixture tests fail on the base, passed the final 871-test suite, inspected native key/type aggregates and replayed only a read-only backup of the 1.3.0 ledger.
Tests
python3 -m unittest tests.test_parser_gapson the original code ran six tests: five failures and one missing-identity error, one or more for each of the five Issue gaps. The same six then passed.python3 -m unittest discover -s tests: exit 0 on8647f156de05bc506f574ae94f28024fd5d3d5d7, one suite at a time:python3 -m compileall -q agent_observer tests: exit 0 on 8647f15.git diff --check: passed.Ledger-copy proof (historical candidate 634fb26)
Audited bestia on 2026-10-19 at
634fb2671ece0522a40b7b45d3bf9827fedac4c0. These retained aggregates were not rerun for the follow-up; its new edge cases are fixture-verified and no live ledger was accessed. Waited foragent-observer --versionto print1.3.0, then usedsqlite3.connect("file:<live-ledger>?mode=ro", uri=True).backup(scratch_connection)into~/.local/state/agent-observer-scratch/128/observer.db. No live-ledger writes or sync. No prompt/transcript contents were printed.Replayed the captured source set using
db.connect(scratch)/db.init_db,claude.import_claude_file,codex.import_codex_file, andgrok.import_grok_sessionwith the same shared_SyncCtxparent index used by sync. The set contains all 238 Claude and 1,064 Codex sources plus 391 Grok sessions owning tool/read evidence or unknown records: 1,693 import operations, 0 failed, 0 missing. Grok sources were restaged at import revision 9 in scratch to verify final-code repair; fixtures verify repeated imports without duplicate rows.The first disposable measurement counter mistakenly added the adapters'
failedlists to an integer; this affected the instrument only. The corrected measurement completed with 0 failures. Reusing a shared Grok parent index avoids repeatedly scanning the containing tree.Native logs were still appendable while the ledger copy stayed isolated, so totals grew between baseline and replay. Count changes are reported explicitly rather than attributing all new events to parser repair.
direction_identity
Before:
[["claude", 238, 0, null], ["codex", 1064, 0, null]]After:
[["claude", 238, 217, 200], ["codex", 1064, 920, 901]]codex_exec_duration
Before:
[[61683, 61683]]After:
[[61896, 0]]grok_mcp_errors
Before:
[[2192]]After:
[[0]]reads_by_state
Before:
[["claude", null, 329], ["codex", "completed", 5421], ["codex", "failed", 109], ["grok", null, 2994], ["opencode", "ok", 66]]After:
[["claude", "ok", 336], ["codex", "failed", 109], ["codex", "ok", 5436], ["grok", "attempted", 7], ["grok", "failed", 13], ["grok", "ok", 2979], ["opencode", "ok", 66]]codex_Read_calls
Before:
[[0]]After:
[[0]]grok_tool_results
Before:
[[31471, 31145]]After:
[[32056, 31728]]Direction columns are harness, session count, non-NULL instruction hash count and ready-direction count. Codex duration columns are total exec results and NULL durations. Skill-read columns are harness, state and count. Grok result columns are total results and results with timing. Successful procedure reports now exclude failed/attempted/pending states. Native Codex
Readoccurrences remain zero, so that shape is fixture-verified only.Result:
[["tool_call", 554], ["tool_result", 553]]Result:
[[0]]Result:
[["missing_id", 1], ["unknown_record", 116], ["usage_conflict", 110]]Result:
[["ok"]]The 554 MCP call rows and 553 result rows are distinct native call identities; repeated start/completion witnesses join them rather than adding counts. Residual Grok diagnostics remain visible and outside these five fixes.
Review follow-up
Review response
The Grok 4.7 medium finding against 634fb26 is reproduced: the exact two-path, two-update case observed only
17.3.1, dropping17.1.0. The same loss occurred when completion arrived in a subsequent sync. Both cases have new real-adapter fixtures. The reader now remembers all validated paths by call ID and observes each once only on success. An incremental import rebuilds that state from the complete prefix already cached for usage replay. This introduces no new disk reads, schema or privacy detail fields.Codex check:
_ingest_response_itemalready acceptscall_id or idfor tool-result events and Read call events, but its Read output lookup used onlycall_id. A real-adapter fixture with id-only call/result records reproducedattemptedinstead ofok. The output identity is now normalized once and used by both the result event and Read lookup/update. This proves the accepted adapter shape; it does not establish that a native Codex writer emits id-only Read outputs. Native Read occurrences in the previous bestia audit were zero.Proof
python3 -m unittest tests.test_parser_gaps tests.test_grok: 64 tests passed.8647f156de05bc506f574ae94f28024fd5d3d5d7: 871 tests, OK, 61.361s.python3 -m compileall -q agent_observer tests: exit 0. Four new regressions in this follow-up ran failing first before their repairs.tests/test_parser_gaps.py; VERSION/manifests unchanged.The incremental path reconstruction also exposed the ledger's first-known-value policy: an existing version-A identity prevented newly completed version-B evidence from replacing it. The fourth new fixture reproduced this. The adapter now refreshes reconstructed path counts after replay while retaining other identity evidence and preferring a release mapped from the instruction hash. This preserves full-import/incremental equivalence without changing generic session-upsert policy or adding storage.
Delivery state
PR #130 is implemented and proved at
8647f156de05bc506f574ae94f28024fd5d3d5d7. Exact-head independent review round 5 passed with no blocking or nonblocking findings; the head hasreview/independent=successfromlukemaj. No merge, version preparation, release, installation or deployment. Website/SEO impact: none, because no website or URL changes.The scratch database and its task directory were deleted and verified absent after retaining these aggregates. Disposable local proof files are removed after this record is published. Worktree and branch remain for the open PR; the merger retires them. Residual non-MCP diagnostics and seven attempted Grok reads remain visible. Native Codex Read coverage on bestia is fixture-only because no such calls occur in this ledger.
fix: recover native parser evidence and successful reads (#128) (#130)
chore(release): prepare 1.4.0 (#137)