Skip to content

research_workflow_live + check_package: note and resolution JSON blocks are shape-trusted — a non-object marker/block raises a bare AttributeError naming no file, while the receipt path in the same file is guarded #6857

Open

Description

@dezren39

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 via fail() ("note body hash mismatch", naming the path).
  • research_workflow_live.receipts() on a receipt whose JSON is [] fails cleanly via fail() — because check_receipt() (research_workflow_live.py:384) checks isinstance(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 first note.get(...).
  • resolve_command()'s already-resolved scan (research_workflow_live.py:469): a concept file containing a resolution block whose JSON is [], "x" or 42 → same raw AttributeError at json.loads(block).get("note"). resolve-note therefore 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.py check_package(): the resolution scan (:813-816, entry = json.loads(block) then entry.get("note")) and the notes loop (:838-846, note = json.loads(found[1]) then note.get(...)) — a non-object block there fails check the 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 with fail() naming the note path and the expected object shape, before any .get.
  • resolve_command()'s resolution scan and check_package()'s resolution scan reject a non-object resolution block with fail() naming the concept file, instead of raw .get on 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

  1. developing-today commented on Nov 7, 2026

    @developing-today
    Contributor
  2. added
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/small-fixQueue packet kind: bounded fix with reproduction and targeted tests
    priority/normalOrdinary priority (the default)
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    app/research-workflowscripts/research_workflow* + sync_research_workflow tooling
    on Nov 7, 2026
  3. dezren39 commented on Nov 7, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

  4. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    queue/claimedQueue worker lifecycle state
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 8, 2026
  5. dezren39 commented on Nov 8, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  6. dezren39 commented on Nov 8, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · PR opened

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    app/research-workflowscripts/research_workflow* + sync_research_workflow toolingkind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobstatus:in-reviewtask/small-fixQueue packet kind: bounded fix with reproduction and targeted tests

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions