tres-rollup-review
>
git clone --depth 1 https://github.com/anthropics/claude-plugins-community /tmp/tres-rollup-review && cp -r /tmp/tres-rollup-review/tres-finance-plugin/skills/tres-rollup-review ~/.claude/skills/tres-rollup-reviewSKILL.md
# TRES Finance — Rollup Review
Take a fully-specified rollup rule and compute **exactly** which sub-transactions it
will claim — with every one of its filters applied — then flag genuine problems. You
do NOT design new rollups and you do NOT execute mutations.
All GraphQL runs through the **TRES Finance MCP connector** (`execute` tool). All
variable keys and nested input fields MUST use **camelCase**, never snake_case.
---
## What this adds over tres-rollup-rules
The `tres-rollup-rules` discovery step groups sub-txs only at the
(wallet, asset, direction) level — it never applies a single candidate's *full* filter
combination (fees + method_ids + subtx_type + amount bounds + counterparty +
excludeRollups together). This skill does exactly that, per rule, via the
`subTransactionRollupRulePreview` query (which runs the engine's real
`query_sub_transactions`), giving:
- the **exact** match count → the **zero-match gate** (a rule that matches nothing must
not be created), and
- pre-create **overlap awareness**, so the user only ever sees viable proposals.
It is also usable **standalone** to review a rule someone submitted (Mode B) — a case
the discovery skill doesn't cover.
---
## Two modes
### Mode A — pre-create gate (invoked by `tres-rollup-rules`)
When `tres-rollup-rules` invokes this skill (via the Skill tool), these instructions
load into the **same** context that already holds the candidate rule objects — they
are not passed as arguments, they are already in the conversation above. Iterate those
candidates **one at a time**; for each, run the checks below and emit exactly one
verdict:
- **PASS** — clean, ready to propose (include the exact sub-tx + parent-tx count).
- **DROP** — matches 0 sub-txs; must not be created.
- **FIX** — a config problem with the exact change (e.g. "minAmount > maxAmount",
"recipientIdentifier on an INFLOW rule — should be senderIdentifier").
Overlaps are reported as **notes**, not DROP/FIX (see Check 2). Produce one verdict line
per candidate, then control returns to `tres-rollup-rules` Step 2.5.
### Mode B — standalone review (when asked to review submitted/pending rules)
Fetch pending rules and review each; produce a per-rule findings summary.
```graphql
query PendingRollupRules {
subTransactionRollupRule(status: "Pending", limit: 50) {
totalCount
results { id name interval startDate endDate status rule createdBy createdAt }
}
}
```
The status filter is title-case (`"Pending"`, `"Active"`, `"Disabled"`). If
`totalCount` is 0, say "No pending rollup requests in this org" and stop.
---
## Ground truth — how a rule selects sub-transactions
A rule claims sub-transactions matching ALL of (this mirrors the engine's
`query_sub_transactions`):
- `belongsTo_In: [internal_account_id]`, `asset_In: [asset_id]` (the asset KEY),
`platform` matches, `balanceFactor` matches `balance_factor`
- already-rolled-up (`excludeRollups`) and derived/locked/synced sub-txs excluded
- `fees`: `EXCLUDE` drops GAS/FEE, `ONLY` keeps only GAS/FEE, `INCLUDE` keeps all
- optional narrowing: `method_ids`, `min_amount`/`max_amount`, `subtx_type`,
`sender_identifier`/`recipient_identifier`,
`original_sender_prefix`/`original_recipient_prefix`
The rule JSON (as stored / returned) uses snake_case. `balance_factor = -1` is
**OUTFLOW**, `+1` is **INFLOW** — get this right or every direction check is backwards.
### Verified subTransaction filter names
| Intent | Filter |
|---|---|
| Wallet | `belongsTo_In: [ID]` |
| Asset by key | `asset_In: [ID]` |
| Direction | `balanceFactor: Float` (-1 / 1) |
| Min / max amount | `amount_Gte` / `amount_Lte` |
| Sender / recipient | `sender_Identifier_In: [String]` / `recipient_Identifier_In: [String]` |
| Method id | `tx_MethodId: String` (single) / `tx_Classification_MethodId_In: [String]` |
| Sub-tx type | `type: String` / `type_In: [String]` (lowercase FinancialAction value) |
| Exclude already-rolled-up | `excludeRollups: true` |
| Exclude gas/fee | `excludeGasFees: true` |
| Dates | `timestamp_Gte` / `timestamp_Lte` (DateTime) |
`type` / `type_In` take the **lowercase** FinancialAction value (`"gas"`, `"fee"`,
`"reward"`, …) — opposite casing from the rule's UPPERCASE `subtxType` enum. So
`subtx_type` is countable exactly (`type: "<value>"`) and `fees: ONLY` ≈
`type_In: ["gas", "fee"]`.
> Gotcha: `fees: ONLY` already selects GAS+FEE, so a gas/fee rollup needs `fees: ONLY`
> alone — adding `subtxType: GAS` on top is redundant (and narrows to GAS, dropping FEE).
**`typeId` is NOT a rule filter here.** `type_id` is only the rollup rule's id **when
paired with** `type_In: ["rollup", "rollup_fee"]`. On other types it means something
else entirely. To inspect what an existing rollup rule produced, query
`type_In: ["rollup","rollup_fee"], typeId: "<rule_id>"` — never `typeId` alone.
**Sentinel dates (operational note):** if `startDate == "0001-01-01"` or
`endDate == "9999-12-31"`, omit that bound (don't pass the sentinel — it may not parse).
Unbounded dates are normal and preferred; they are NOT a finding.
**Evidence:** the on-chain hash is `tx.identifier` (sub-select `tx { identifier }`),
never `typeId`. For examples also pull `amount`, `sender { identifier }`,
`recipient { identifier }`, `asset { symbol key }`.
---
## Scope — DISABLED rules are out of scope
Only **Active** and **Pending** rules are live. Never query, compare against, or flag
DISABLED rules (they're superseded versions).
---
## The checks
### Check 1 — Exact impact (the core; always run)
Get the ground-truth count straight from the engine via the
`subTransactionRollupRulePreview` query — it runs the real `query_sub_transactions`
with **all** of the rule's filters applied server-side, so you never reconstruct
filters by hand:
```graphql
query RollupPreview($rule: RollupRuleInputType!, $startDate: Date, $endDate: Date, $interval: Interval) {
subTransactionRollupRulePreview(rule: $rule, startDate: $startDate, endDate: $endDate, interval:Explain a topic like I'm a 5 year old. Use when the user types /eli5 <topic> or asks for a dead-simple picture explainer of how something works.
Use the `quickdesign` CLI to generate AI media — UGC promo videos, image edits, product creatives, video upscales — through Seedance, Kling, Sora2, Nano Banana, and GPT Image. Invoke this skill whenever the user asks for a talking-avatar video, multi-segment ad / promo / explainer, image edit (object swap, angle change, state change), product photoshoot, or video upscale via QuickDesign.
Use only when the user explicitly asks for a TestDino audit of Playwright automated test code. Routes through the audit tools the TestDino MCP server exposes (get_audit_report + submit_audit_report, or the legacy test_audit). For generic code review or non-Playwright targets, do a normal review instead.
Use when the user wants to check TestDino connection status, validate their PAT, discover available organizations and projects, or find the right projectId. Always call this first when the project context is ambiguous before any other TestDino tool.
Use when the user wants to manage a manual execution run or update case-level results inside a run — listing runs, creating runs for a release, inspecting a run, assigning cases, or marking case results (passed/failed/blocked/skipped/retest/untested). Accepts counter-style IDs like RUN-12 and TC-156.
Use when the user wants to create, update, or browse manual QA test cases and suites in TestDino — not execution runs. Covers list_manual_test_suites, list_manual_test_cases, get_manual_test_case, create_manual_test_case, update_manual_test_case, create_manual_test_suite.
Use when the user wants to browse, inspect, create, or update releases/milestones in a TestDino project. Covers list_releases, get_release, create_release, and update_release. Accepts counter-style IDs like MS-12.
Use when the user wants to inspect automated test runs, list failed or flaky tests, debug a failing testcase with historical context, or filter runs by branch, commit, author, environment, browser, status, or tags. Includes list_testruns, get_run_details, list_testcase, get_testcase_details, and debug_testcase.