Review: Implement billing follow-up agent for Westside Basketball

review-1903-2026-07-25 Review

review needs-refinement

Verdict: NEEDS_REFINEMENT

Template Completeness

  • [x] Type -- Feature
  • [x] Lineage -- Standalone, first ticket for Nemo project
  • [x] Repo -- ldraney/nemo
  • [x] User Story -- well-formed (As Marcus, I want...)
  • [x] Context -- thorough background on the 28-player billing campaign
  • [x] File Targets -- 8 files to create, 2 files excluded
  • [x] Feature Flag -- none
  • [x] Acceptance Criteria -- 9 criteria
  • [x] Test Expectations -- 4 test items + run command
  • [x] Constraints -- 6 constraints listed
  • [x] Checklist -- present
  • [x] Related -- present
All required template sections are present.

Traceability

  • [x] story:billing-follow-up label -- present on board item
  • [ ] story note MISSING -- project-nemo page does not exist (404). [SCOPE] Create project page project-nemo with user-stories section containing the billing-follow-up story.
  • [x] arch:nemo-agent label -- present on board item
  • [ ] arch note MISSING -- arch-nemo-agent note does not exist (404). [SCOPE] Create architecture note arch-nemo-agent for the agent component.
  • [x] Forgejo issue -- ldraney/nemo#1, state: open

File Targets

  • [x] src/webhook.py -- to create; repo is currently docs-only, path is valid
  • [x] src/agent.py -- to create; consistent with architecture doc
  • [x] src/tools.py -- to create; consistent with architecture doc
  • [x] src/config.py -- to create; consistent with architecture doc
  • [x] Dockerfile -- to create; standard for containerized service
  • [x] pyproject.toml -- to create; standard Python project file
  • [x] .woodpecker/ci.yaml -- to create; matches platform CI convention
  • [x] .pre-commit-config.yaml -- to create; matches platform convention
  • [x] docs/ -- excluded (already exists in repo)
  • [x] projects/westside-billing-agent/workflow.md -- excluded (exists in repo)
All file targets are valid for a greenfield service in a docs-only repo.

Repo Placement

Issue is filed on ldraney/nemo and all file targets are in the nemo repo -- correct. However, there is an undocumented cross-repo dependency:
  • AC #2 references GET /api/v1/players/:id/billing but the westside-basketball Rails app has NO JSON API endpoints at all. The routes.rb has no api/v1 namespace and no API controllers exist.
  • The workflow doc (projects/westside-billing-agent/workflow.md) explicitly lists "JSON API endpoints" under "What Is NOT Built" and proposes two options: (A) JSON API on Rails, or (B) Direct API access via kubectl/Stripe/Gmail.
  • The ticket implicitly assumes Option A without creating a companion westside-basketball ticket for the API endpoints.
  • AC #4 references ParentMailer#billing_followup but that method does not exist. ParentMailer only has announcement, payment_reminder, and quick_send.
The ticket must either: (a) add a cross-repo dependency ticket on westside-basketball for JSON API + mailer work, or (b) rewrite the approach to use Option B (direct API access) and clarify which mailer method to use.

Dependencies

  • Only item on board-nemo; no board-level blockers or blocked items.
  • Cross-repo dependency (undocumented): Rails JSON API endpoints (/api/v1/players/:id/billing, PATCH /api/v1/orders/:id, POST /api/v1/orders, POST /api/v1/emails/send, GET /api/v1/emails/inbox) do not exist in westside-basketball. No ticket exists to create them.
  • Cross-repo dependency (undocumented): ParentMailer#billing_followup does not exist in westside-basketball. Only announcement, payment_reminder, quick_send exist.
  • Operational dependencies: Postmark account + DNS setup, Anthropic API key, Stripe API key, k8s namespace creation -- not code dependencies but need to exist before deployment.

Acceptance Criteria

9 acceptance criteria listed. Assessment:
  • AC #1 (Postmark triggers agent) -- testable via webhook mock
  • AC #2 (Agent pulls from Rails JSON API) -- BLOCKED: API does not exist in the Rails app
  • AC #3 (Standard fixes) -- testable with mock data
  • AC #4 (Draft billing email via Postmark) -- references nonexistent billing_followup mailer; also, the architecture doc says Nemo sends via Postmark outbound, but the workflow doc references ParentMailer (Rails Gmail delivery). These contradict each other.
  • AC #5-6 (Marcus approval flow) -- testable
  • AC #7 (One player at a time) -- testable
  • AC #8 (Persistent state on restart) -- testable
  • AC #9 (Custom email handling for edge cases) -- vague; what edge cases specifically? "no-show, disputed, left program" are mentioned in Constraints but not mapped to specific AC behaviors

Blast Radius

  • Nemo is a new standalone service, so blast radius within its own repo is contained.
  • Cross-repo impact on westside-basketball is the primary concern: JSON API endpoints, mailer methods, and potentially auth token setup.
  • No existing Postmark integration anywhere in the infrastructure -- this is net-new infrastructure.
  • Email sending conflict: architecture.md says Nemo sends via Postmark outbound, workflow.md says emails go through ParentMailer (Rails + Gmail). The ticket must pick one approach.

Decomposition Assessment

NEEDS DECOMPOSITION -- route to skill-decompose-ticket
  • 8 file targets in 1 repo -- exceeds the 3+ file threshold
  • 9 acceptance criteria -- exceeds the 5 AC threshold
  • Estimated agent work far exceeds 5 minutes -- building an entire FastAPI service with Claude agent loop, Postmark webhook handling, tool definitions, persistent state, Dockerfile, CI pipeline, and pre-commit config is a multi-hour effort
  • Cross-repo dependency -- Rails JSON API and/or mailer work needs a separate ticket on westside-basketball
Suggested decomposition axes:
  • Skeleton service (FastAPI webhook + config + Dockerfile + CI + pre-commit) -- infra only, no agent logic
  • Agent loop core (agent.py + tools.py) -- Claude API integration with tool use
  • Postmark integration (inbound parsing + outbound sending + signature validation)
  • Billing workflow logic (standard fixes, email drafting, approval parsing)
  • State management (persistent state file, resume on restart)
  • Cross-repo: westside-basketball JSON API endpoints (separate repo ticket)

Recommendation

  • [SCOPE] Create project page project-nemo with user-stories section containing the billing-follow-up story entry.
  • [SCOPE] Create architecture note arch-nemo-agent for the agent component. The architecture.md in the repo is detailed -- this can be derived from it.
  • [BODY] Resolve the data access approach: either commit to Option A (JSON API on Rails, which requires a cross-repo dependency ticket on westside-basketball) or Option B (direct API access via Stripe/kubectl). Update AC #2 accordingly.
  • [BODY] Resolve the email sending approach: architecture.md says Postmark outbound, workflow.md says ParentMailer (Rails + Gmail). Pick one and update AC #4 and the File Targets section.
  • [BODY] Fix AC #4: ParentMailer#billing_followup does not exist. Either reference announcement/quick_send or add a cross-repo dependency to create the method.
  • [BODY] AC #9 (custom email handling) is too vague for agent verification. Enumerate the specific edge cases and expected agent behavior for each.
  • [DECOMPOSE] 8 file targets and 9 AC across a full greenfield service far exceed the 5-minute rule. Route to skill-decompose-ticket for sub-ticket creation. Suggested decomposition: skeleton service, agent loop, Postmark integration, billing workflow, state management, and cross-repo Rails API work.