Skip to content

impl(pm-stack): spend attribution projection — session to issue/epic resolution, unattributed shown (#1259 slice 1) #4822

Open

Description

@dezren39

Part of epic #1184; implementation follow-up of design issue #1259 (spend rollups). Design note: doc/spend-rollups-design-1259.md (PR linked from #1259).

Scope

Build the spend-attribution projection in the pm-stack aggregator: a versioned, pure projection that turns existing per-session usage records into per-issue / per-epic / per-project spend facts. Consume existing sources only — do NOT build new collectors:

Attribution rules (per the design note)

  • Queue-bound sessions resolve exactly: lane-ledger session binding → queue task → issue number.
  • Fleet-worktree sessions resolve from the worktree directory name (~/git/fleet/<task>-<issue>-<slug>).
  • Sub-sessions roll up to their root session (parentId); never double-counted.
  • Epic/project resolution reuses the existing hierarchy seams (epicRef / parent chains in pm-stack/aggregator/src/model.ts, rollups in src/epics.ts); Project Area is a display grouping, not an attribution key.
  • Anything unresolved lands in an explicit unattributed bucket with a reason code (no-binding, no-worktree, parent-left-pool, source-gap). Unattributed spend is shown, never dropped or guessed onto an epic.
  • Every projected fact carries attributionVersion; raw source records are never rewritten.

Acceptance criteria

  • Projection is a pure, tested module: same inputs + same version → identical output.
  • Unit tests cover: bound session, worktree session, sub-session rollup, each unattributed reason code, and a session whose parent chain leaves the fetched pool.
  • Totals reconcile: sum(attributed) + unattributed = source totals, per unit, asserted in tests.
  • No new collector, exporter, or instrumentation in OpenCode/OpenChamber.

Checks

  • bun test and bunx tsc --noEmit in pm-stack/aggregator pass (CI on the PR).

Activity

  1. added
    kind/featureNew feature or capability request
    priority/normalOrdinary priority (the default)
    effort/mMedium: expected under 1 day of work
    app/pm-stackpm-stack (Pad/Grist) in developing-today/code
    on Nov 3, 2026
  2. added
    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
    on Nov 3, 2026
  3. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: triaged (coverage pass)
    Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 40 (priority/normal). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
    Found via: coverage pass 2026-11-03

  4. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  5. 1 remaining item

  6. removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 3, 2026
  7. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done (triage)

    • Agent: queue worker (repo-worker-code), lane code-c shift
    • Session / ID: task 8447 → implementation task 8769
    • Found via: queue claim (coverage triage)
    • Task: Triage of the spend-attribution projection at current main.

    Verdict: still live, unblocked, fully specified. Verified at origin/main dda1def97:

    • Not built: attributionVersion appears nowhere in pm-stack/aggregator (src or tests), and there is no spend/attribution projection module in aggregator/src — the grep hits for "attribution" are quota/saas extraction, not this projection.
    • Design present: doc/spend-rollups-design-1259.md is on main.
    • Sources present, as the design assumes: pm-stack/opencode-usage-export/opencode-usage-export.mjs emits per-session docs with parentId and directory; pm-stack/aggregator/src/snapshots.ts is the append-only usage-YYYY-MM.jsonl store; hierarchy seams exist (model.ts:109 epicRef, rollups in epics.ts).
    • No blockers: no new collector is needed (and the issue forbids one); the lane-ledger binding and fleet worktree naming the rules consume are the fleet's standing conventions.

    Routing: implementation enqueued as task 8769 (priority 40) with this issue's scope, attribution rules, and acceptance carried verbatim — pure versioned projection, unattributed bucket with the four reason codes, reconciliation invariant asserted in tests, bun test + bunx tsc --noEmit as the checks. This issue stays open for task 8769.

  8. added
    queue/queuedHas a queued task in the Supabase agent queue
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 3, 2026
  9. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  10. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

    • Agent: queue worker (repo-worker-code), lane 9aca43b4-5439-4939-9f71-323f5d32521b
    • Session / ID: task 8769
    • Found via: OpenChamber scheduled lane claim
    • Task: Implement the v1 spend attribution projection and reconciliation tests.
    • Outcome: PR feat(pm-stack): project spend attribution facts (#4822) #5164 opened: feat(pm-stack): project spend attribution facts (#4822) #5164 (head d577df915f61669eb09d798c1627f9d2a1409c7d).
    • Verification: targeted test 7/7 and focused strict TypeScript check pass. No PR checks are configured for pm-stack aggregator: the aggregator workflows trigger on main pushes only. Full local suite had 2 existing /api/health assertions fail; full typecheck reports the existing HealthView.conflicts fixture error.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/pm-stackpm-stack (Pad/Grist) in developing-today/codeeffort/mMedium: expected under 1 day of workkind/featureNew feature or capability requestpriority/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