Structured JSON-LD reason on monthly pool retirements (#101 Phase A)#138
Conversation
…tirements Closes the pool-path gap in regen-network#101 Phase A. The buildRetirementReason helper (commit d3c4e80) was wired into: - retirement.ts (MCP tool path) ✅ - retire-subscriber.ts (per-subscriber) ✅ - pool.ts (monthly pool runs) ❌ — still using plain string Pool runs are the on-chain volume — every subscriber's monthly contribution flows through MsgBuyDirect there. The plain-text reason "Monthly pool retirement — Regen Compute" provides no machine-readable context for indexers, the KOI semantic layer, or the eventual CLAMS CosmWasm contract. Now uses buildRetirementReason() with: - source: "subscription" - period: YYYY-MM derived from poolRun.run_date - note: human-readable "covering N subscriber(s)" descriptor Backward compatible: older consumers see a valid string (the JSON serialization of the structured object). Test: new pool.test.ts case "uses structured JSON-LD retirement reason on chain (regen-network#101 Phase A)" captures the broadcast msg, parses retirementReason as JSON, and asserts the @context, type, source, period, and note fields. Full suite: 50/50 passing (49 prior + 1 new). Refs: regen-network#101 (Phase A pool-path gap) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces structured JSON-LD retirement reasons for on-chain transactions, replacing the previous plain text format. It includes a new test case to verify the JSON-LD structure and metadata. Feedback suggests moving the construction of the retirement reason outside the loop to avoid redundant calculations, as the inputs are constant for the entire pool run.
| const period = poolRun.run_date.slice(0, 7); // YYYY-MM | ||
| const poolRetirementReason = buildRetirementReason({ | ||
| note: `Monthly pool retirement covering ${subscribers.length} subscriber${subscribers.length === 1 ? "" : "s"}`, | ||
| period, | ||
| source: "subscription", | ||
| }); |
There was a problem hiding this comment.
The structured retirement reason is being recalculated and stringified inside the batch loop. Since the inputs (poolRun.run_date, subscribers.length, and the literal source) are constant for the entire pool run, this calculation should be moved outside the for loop (before line 279) to avoid redundant work and improve efficiency.
Closes the pool-path gap in #101 Phase A.
Problem
buildRetirementReason(shipped in commitd3c4e80) is wired into:retirement.ts(MCP tool path) ✅retire-subscriber.ts(per-subscriber retirements) ✅pool.ts(monthly pool runs) ❌ — still uses the plain string\"Monthly pool retirement — Regen Compute\"Pool runs are where the on-chain volume happens — every subscriber's monthly contribution flows through
MsgBuyDirectthere. The plain-text reason gives indexers, the KOI semantic layer, and the eventual CLAMS CosmWasm contract no machine-readable context.What this PR does
pool.tsnow callsbuildRetirementReason(...)with:source: \"subscription\"period: "YYYY-MM" derived frompoolRun.run_datenote: human-readable "covering N subscriber(s)" descriptorBackward-compatible: older consumers see a valid string (the JSON serialization).
Test
Full suite: 50/50 passing (49 prior + 1 new).
Test plan
npm run typecheck— cleannpm test— 50/50 passingnpm run build— cleansource: \"subscription\"is the intended literal for ADR-004 / CLAMS alignment. The other call sites use\"mcp_tool\"or\"subscription\"; pool runs are subscription-driven so I went with the latter.Out of scope
subscriberIdfield onStructuredReasonOptionsis declared inretirement-reason.tsbutbuildRetirementReason()doesn't actually serialize it. Worth fixing in its own micro-PR if you want — pool runs cover many subscribers so it doesn't apply here, but it does forretire-subscriber.ts.COMPUTE_FOOTPRINTas an ADR-004 ClaimType) — that work lives inregen-data-standards, not here.Refs: #101 Phase A
🤖 Generated with Claude Code