Skip to content

aggregator(jules): mapJulesItems never validates the keeper state — one null or mistyped item discards every Jules session for the run, a string items fabricates phantom sessions #2531

Closed

Description

@dezren39

Problem

mapJulesItems in pm-stack/aggregator/src/sources/jules.ts maps the keeper-written jules-review-state.json into attention-feed entries with no validation of the items container or its elements — the file is parsed with a bare as JulesReviewState cast at the only call site, and every field is dereferenced as if the declared TypeScript shape were guaranteed.

Evidence (verified this run, main 7d1b081c)

  • src/sources/jules.ts:43 — Object.entries(state.items ?? {}) accepts any non-nullish items (object, array, or string).
  • src/sources/jules.ts:47 — title: item.title throws on a null item; :54 — (item.state ?? "").toUpperCase() throws on a non-string state (e.g. a number).
  • scripts/collect-fleet-feed.ts:506-512 — the sole caller wraps the whole block in one catch that logs collector: jules-review state unreadable; no Jules sessions this run, so one malformed element discards every Jules session and the keeper totals for that run, under a message that claims the file was unreadable when it parsed fine.
  • src/sources/jules.ts:85 — julesSummary counts Object.keys(state.items ?? {}), so a string items is counted per character.

Probe (Bun, importing the real src/sources/jules.ts, main 7d1b081c):

Input Result
items: { ses1: null, ses2: {state:"COMPLETED", …} } throws TypeError: null is not an object (evaluating 'item.title') — the valid ses2 entry is lost with it
items: { ses1: { state: 42, … } } throws TypeError: (item.state ?? "").toUpperCase is not a function
top-level null state throws TypeError: null is not an object (evaluating 'state.items')
items: "nope" (string) fabricates 4 phantom sessions with sessionIds "0".."3", all Jules UNKNOWN; julesSummary.tracked reports 4
items: [ {state:"FAILED", …} ] (array) fabricates a session with sessionId "0"

Why it matters

The collector is the only path by which supervised Jules sessions reach the dashboard's needs-you feed and the identity registry (recordFromSessionEntry per entry, same block). A single bad element — a null placeholder or a mistyped field in a state file written by a different program (the keeper, outside this repo) — silently empties the whole Jules surface for that collection run, and the log line misdiagnoses it as an unreadable file, sending any investigation to the wrong place. The string/array shapes are worse in the other direction: they invent sessions that do not exist.

Acceptance criteria

  • mapJulesItems never throws on a malformed state: a non-object top level, a non-plain-object items, and non-object elements are skipped (per element where possible), so valid sibling entries still map.
  • Non-string scalar fields on an otherwise usable item (e.g. numeric state) do not kill the entry or the batch; the entry degrades the way a missing field already does (Jules UNKNOWN).
  • julesSummary's tracked count agrees with the set of items mapJulesItems would consider (no per-character counting of a string items).
  • The collector's Jules block no longer reports a parseable-but-malformed state as "unreadable" — the log distinguishes unreadable/unparseable from malformed-but-recovered, or the mapper's per-element skips are counted/logged.
  • Tests in the aggregator suite (slice2 jules mapping describes) cover: null element among valid ones, numeric state, string items, array items, top-level null.

Dedup

#1587 is julesSummary's freshest-note HHMM selection — a different function and defect. The feed-gate family (#2450/#2451/#2445/#2446/#2439) covers isFleetFeed section checks in live.ts, not this collector-side mapper; searches for mapJulesItems and Jules collector validation returned no covering issue, open or closed.

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    app/aggregatorPackage/app: aggregator (pm-stack in this repo)
    effort/xsTrivial: expected under 30 minutes of work
    on Oct 30, 2026
  2. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator (new-issue-creator-code-b)
    • Session / ID: new-issue-creator-code-b run 2026-10-29 21:50 CDT
    • Found via: filed this run
    • Task: Triage the missing validation in mapJulesItems (src/sources/jules.ts) — pin the per-element skip/degrade shape and the collector log wording, then route a small_fix packet
    • Expectation: effort/xs triage; done = fix layer pinned (mapper gate vs collector gate), acceptance criteria in the issue body
    • Links: probe hidden_files/probe-2026-10-29-laneB-julesitems/ (Bun, real module, main 7d1b081)
  3. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 1, 2026
  4. 16 remaining items

  5. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — state=parked

    • Agent: repo-worker-code
    • Session ID: ses_e5e653a6dd8ffeYOCIOKXL0cY0
    • Queue task: 5362
    • PR: fix(aggregator): validate Jules review items (#2531) #4208 (head 8c7ebc9).
    • Fresh CI: 1 of 2 checks passed; test is pending and none are failing.
    • Targeted verification: bun test test/slice2.test.ts passes (32 tests). Full suite's 2 failures and typecheck diagnostics were reproduced on clean main; no changed-file type diagnostics.
    • Resume: after CI completes, revalidate checks and feedback; merge only if green and the diff remains in scope.
    • Queue: parked until 2026-11-02T06:10:36Z.
  6. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    Agent note — task 5362 (lane F resume)

  7. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — parked (CI pending) — Lane D

  8. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 2, 2026
  9. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — state: picked-up (small_fix task 5362, lane F shift)

  10. added a commit that references this issue on Nov 2, 2026
  11. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — state: done (small_fix task 5362, lane F shift)

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

Metadata

Metadata

Assignees

Labels

app/aggregatorPackage/app: aggregator (pm-stack in this repo)app/pm-stackpm-stack (Pad/Grist) in developing-today/codeeffort/xsTrivial: expected under 30 minutes of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions