Repository navigation
Description
Problem
The research-workflow note/resolution JSON blocks — the markers that record how one concept answered another — are shape-trusted at every parse site, while the receipt JSON in the same extension is guarded. A note marker or resolution block whose JSON is valid but not an object ([], "x", 42, null) surfaces as a bare AttributeError: 'list' object has no attribute 'get' naming no file or field, instead of the tool's own fail() diagnostic. The CLI catches these types (research_workflow.py main()), so the operator sees only error: 'list' object has no attribute 'get' and cannot tell which note or concept file is malformed.
Sibling filings did not cover this surface: #6854 covered research_workflow.py's profile/state/transcript/concepts/dependencies/triggers; #6856 covered research_workflow_items.py's package manifest. The note/resolution blocks in check_package() and the whole of research_workflow_live.py's note path were not in either.
Evidence (verified this run, laptop @ 65beb42, real files verbatim — sha256 matched origin/main — probe ~/git/fleet/probe-rw-note-shape/)
Controls all behave as designed:
research_workflow_live.read_note()on a valid note returns the note; a dict note with missing fields fails cleanly viafail()("note body hash mismatch", naming the path).research_workflow_live.receipts()on a receipt whose JSON is[]fails cleanly viafail()— becausecheck_receipt()(research_workflow_live.py:384) checksisinstance(entry, dict)first. That is the guarded sibling in the same file.resolve_command()with a well-formed object resolution block succeeds and writes the receipt.
Wrong shapes (all raw AttributeError, none via fail()):
read_note()(research_workflow_live.py:348-356): note marker JSON[],"x",42,null,[1,2]→AttributeError: '<type>' object has no attribute 'get'at the firstnote.get(...).resolve_command()'s already-resolved scan (research_workflow_live.py:469): a concept file containing a resolution block whose JSON is[],"x"or42→ same rawAttributeErroratjson.loads(block).get("note").resolve-notetherefore dies mid-command on a malformed block in any concept file, before it can write or refuse cleanly.- Same unguarded pattern by code read in
research_workflow.pycheck_package(): the resolution scan (:813-816,entry = json.loads(block)thenentry.get("note")) and the notes loop (:838-846,note = json.loads(found[1])thennote.get(...)) — a non-object block there failscheckthe same bare way.
Why it matters
Notes and resolutions are the audit trail of a research package: who told whom what, and how it was dispositioned. They are hand- and agent-edited Markdown embeds — exactly the content most likely to be pasted wrong — and this tool is the checker whose contract everywhere else is a named fail() diagnostic. The one JSON family in the live extension that lacks the guard is the one resolve-note parses before doing anything else, so a single malformed block wedges the disposition workflow with a message that points at nothing. One more instance of the #3068 parsed-is-not-validated pattern, in a file that already contains the correct guard (check_receipt) applied to only one of its three JSON inputs.
Acceptance criteria
read_note()rejects a non-object note marker withfail()naming the note path and the expected object shape, before any.get.resolve_command()'s resolution scan andcheck_package()'s resolution scan reject a non-object resolution block withfail()naming the concept file, instead of raw.geton the unchecked value.check_package()'s notes loop rejects a non-object note marker the same way, naming the note path.- Regression tests (scripts/tests/test_research_workflow_live.py and/or test_research_workflow.py) cover each wrong shape above and assert the clean
fail()diagnostic; the guarded receipt path is unchanged. - Valid notes, resolutions and receipts behave byte-identically; the existing research-workflow suites stay green.
Activity
developing-today commentedon Nov 7, 2026
CODE-2125
dezren39 commentedon Nov 7, 2026
🤖 Agent note · filed
dezren39 commentedon Nov 8, 2026
🤖 Agent note · picked up
queue/11084-6857-research-workflow-json-shapeat15e4a554d4; merged currentorigin/mainand reran workflow tests.pr_opened; CI status will be reported honestly.queue/11084-6857-research-workflow-json-shapedezren39 commentedon Nov 8, 2026
🤖 Agent note · PR opened
pr_opened.