[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M718FND35X9DPTNR7JTX2YX8":3,"skill-same:01M718FND35X9DPTNR7JTX2YX8":84},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":49,"linkOnly":50,"markdownContent":51,"markdownBody":52,"frontMatter":53,"refName":56,"commitSha":57,"skillDirectory":58,"forksCount":59,"repositoryHtmlUrl":60,"repositoryHomepageUrl":6,"ownerHtmlUrl":61,"ownerBlogUrl":62,"ownerDescription":6,"updatedAt":63,"install":64,"resources":77},"01M718FND35X9DPTNR7JTX2YX8","tres-rollup-rules",null,"Analyze an organization's sub-transaction patterns in TRES Finance, identify groups of repetitive transactions, and propose data-driven rollup rules that consolidate them into one aggregated entry per interval (daily or monthly) for cleaner ERP integration. Also lists and deletes rollup rules. Trigger this skill whenever the user asks about rollup rules, transaction aggregation, consolidating transactions, reducing transaction noise, rolling up gas fees, rolling up staking rewards, rolling up micro-transactions, or collapsing many small ledger entries into fewer summary entries. Also trigger on \"create a rollup rule\", \"suggest rollup rules\", \"what should I roll up\", \"show my rollup rules\", \"delete a rollup rule\", \"aggregate transactions\", \"too many transactions\", \"reduce transaction count\", \"roll up fees\", \"daily rollup\", \"monthly rollup\". If a wallet has too many transactions, high-frequency activity, or noisy ledger entries, proactively suggest rollup rules. For computing the EXACT impact of a single already-specified rule or reviewing submitted\u002Fpending rules, use the tres-rollup-review skill instead.","anthropics\u002Fclaude-plugins-community","anthropics","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F76263028?v=4","01M697XGDPXJAVQ8391V2BCYTE","Anthropic","01M718C1RS4JJFM9KNJMTCAYJG",4869,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fclaude-plugins-community\u002Fblob\u002Fmain\u002Ftres-finance-plugin\u002Fskills\u002Ftres-rollup-rules\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000040","财务","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48],"Rules","rollup","tres rollup rules","activity","organization","data-driven","delete","transactions","create","analyze","consolidate","review","Connector","reduce","impact","MCP","up","Wallet","gas","show","2026-11-10 10:12:30",false,"---\nname: tres-rollup-rules\ndescription: >\n  Analyze an organization's sub-transaction patterns in TRES Finance, identify groups of\n  repetitive transactions, and propose data-driven rollup rules that consolidate them into\n  one aggregated entry per interval (daily or monthly) for cleaner ERP integration. Also\n  lists and deletes rollup rules. Trigger this skill whenever the user asks about rollup\n  rules, transaction aggregation, consolidating transactions, reducing transaction noise,\n  rolling up gas fees, rolling up staking rewards, rolling up micro-transactions, or\n  collapsing many small ledger entries into fewer summary entries. Also trigger on \"create\n  a rollup rule\", \"suggest rollup rules\", \"what should I roll up\", \"show my rollup rules\",\n  \"delete a rollup rule\", \"aggregate transactions\", \"too many transactions\", \"reduce\n  transaction count\", \"roll up fees\", \"daily rollup\", \"monthly rollup\". If a wallet has too\n  many transactions, high-frequency activity, or noisy ledger entries, proactively suggest\n  rollup rules. For computing the EXACT impact of a single already-specified rule or\n  reviewing submitted\u002Fpending rules, use the tres-rollup-review skill instead.\ncompatibility: \"Requires TRES Finance MCP connector\"\n---\n\n# TRES Finance — Rollup Rules\n\nAnalyze an organization's sub-transaction patterns, identify groups of repetitive\ntransactions, and propose rollup rules that consolidate them into a single entry per\ninterval for cleaner ERP integration. This is a **data-driven discovery** flow — you find\nthe candidates from the data, validate each against real transactions, then present and\ncreate them.\n\nA rollup rule is keyed on FOUR dimensions that together define exactly which\nsub-transactions it claims:\n**internalAccount (wallet) + asset KEY + platform + balanceFactor (direction)**.\nOptional discriminating filters (fees, methodIds, subtxType, amount bounds,\ncounterparties) narrow it further. Everything you discover and propose must map onto this\nshape — see the Rule Field Reference at the bottom.\n\nA rollup is **non-destructive**: the original raw sub-transactions are always preserved\nand visible in the **Rollup Breakdown** report.\n\nAll GraphQL runs through the **TRES Finance MCP connector** (`execute` tool; validate with\n`validate_query` first when unsure). All variable keys and nested input fields MUST use\n**camelCase** (e.g. `internalAccountId`, `balanceFactor`), NEVER snake_case.\n\n---\n\n## Routing\n\n- **\"Suggest \u002F create \u002F propose rollup rules\"**, **\"too many transactions\"**, **\"roll up\n  X\"** → run the full discovery pipeline (Steps 0–6 below). This is the main flow.\n- **\"Show \u002F list my rollup rules\"** → Section A (List existing rules), then stop.\n- **\"Delete a rollup rule\"** → Section C (Delete rules).\n- **\"Review this specific rule\" \u002F \"what would this rule match\"** → hand off to the\n  **tres-rollup-review** skill.\n\n---\n\n## Step 0 — Confirm Scope\n\nEstablish scope with the user, but keep it light — only the analysis is scoped, the rules\nthemselves are usually open-ended.\n\n### Analysis window (OPTIONAL)\nA period only narrows the *discovery* queries so you look at recent, representative\nactivity. It is NOT required, and it is NOT the rule's date range.\n- \"Q1 2025\" → start: `2025-01-01T00:00:00Z`, end: `2025-03-31T23:59:59Z`\n- \"last 3 months\" → compute from today\n\nIf the user gives no period, analyze all history — that is fine and common.\n\n### Rule date range (PREFER OPEN-ENDED)\nThe rules you create should normally have **no start\u002Fend date** — they default to \"from the\nbeginning of time, indefinitely\" so they keep catching matching transactions going\nforward. Only set `startDate`\u002F`endDate` when the user explicitly wants the rule bounded.\n\n### Wallets (optional, default: all)\nThe user may scope to specific wallets.\n\n### Asset classes (optional, default: all non-spam)\nThe user may scope to specific asset classes (e.g. \"just stablecoins\", \"ETH\"). Remember: a\nclass (e.g. USDC) can span many asset keys\u002Fchains, but each rule targets ONE key — see the\nasset-class bridge in Step 2.\n\n### Clustering guidance (optional)\nHints like \"focus on gas fees\", \"ignore staking rewards under $10\", \"group ETH transfers\nby methodId\".\n\n**Confirm scope briefly, then start:**\n> \"I'll look for rollup candidates across **all wallets** and **all assets** (analyzing\n> **all history**). Rules I propose will be open-ended unless you want them date-bounded.\n> Starting now.\"\n\n---\n\n## Step 1 — Inventory\n\nRun these (in parallel where possible).\n\n### 1a. Wallets\n```graphql\nquery Wallets { internalAccount { totalCount results { id name identifier parentPlatform platforms balancesCount status } } }\n```\nCollect wallet `id` (integer) — this is the rule's `internalAccountId`. Use `platforms`\n(plural list) and `parentPlatform` (string); there is no singular `platform` field on\nwallets.\n\n### 1b. Existing rollup rules (so you don't duplicate coverage)\n```graphql\nquery ExistingRules { subTransactionRollupRule { totalCount results { id name interval status startDate endDate createdBy lastSuccessfulRunAt rule } } }\n```\n`rule` is the JSON config (`internal_account_id`, `asset_id`, `platform`, `balance_factor`,\n`fees`, …). Note which (account, assetKey, direction) tuples are already covered by\n**Active** or **Pending** rules — skip those. Ignore **Disabled** rules (they are\nsuperseded versions, not live coverage). Also study the existing rule **names** here to\nlearn the org's naming convention (see Naming below).\n\n### 1c. Total sub-transactions in scope\n```graphql\nquery InScope($ts_Gte: DateTime, $ts_Lte: DateTime) {\n  subTransaction(timestamp_Gte: $ts_Gte, timestamp_Lte: $ts_Lte) { totalCount }\n}\n```\n(Omit the timestamp args entirely when analyzing all history.)\n\nReport: \"Found X wallets, Y existing rules (Z active), N sub-transactions in scope.\"\n\n---\n\n## Step 2 — Discovery (the core analysis)\n\nUse aggregation queries to find which (wallet, asset, direction) groups have the most\nrepetitive volume, then drill into discriminating filters.\n\n### Filter-name reference (verified — use these EXACT names)\n- Wallet: `belongsTo_In: [ID]` (array, even for one id)\n- Asset by key: `asset_In: [ID]` (array of asset KEYS, e.g. `[\"ethereum_native\"]`)\n- Asset class: `asset_AssetClass_In: [ID]`\n- Direction: `balanceFactor: Float` (`-1` = OUTFLOW, `1` = INFLOW)\n- Amount: `amount_Gte` \u002F `amount_Lte`; fiat: `fiatValue_Gte` \u002F `fiatValue_Lte`\n- Counterparty: `sender_Identifier_In: [String]`, `recipient_Identifier_In: [String]`\n- Method: `tx_MethodId: String` (single) or group by `tx__method_id`\n- Sub-tx type: `type: String` \u002F `type_In: [String]` (FinancialAction) — filter with the\n  **lowercase** value (`\"gas\"`, `\"reward\"`, …); note this is the opposite casing from the\n  mutation's UPPERCASE `subtxType` enum. `groupBy: [\"type\"]` works too.\n- Dates: `timestamp_Gte` \u002F `timestamp_Lte`\n- Exclude already-rolled-up sub-txs: `excludeRollups: true`\n- Exclude gas\u002Ffee sub-txs: `excludeGasFees: true`; exclude spam: `excludeSpam: true`\n- Internal transfers only: `internalTransfer: true`\n\n### Always exclude already-rolled-up sub-txs\nAdd `excludeRollups: true` to every discovery\u002Fcount query. It drops ROLLUP \u002F ROLLUP_FEE\nsub-txs so your counts reflect what a *new* rule would actually capture — matching the\nrollup engine's own selection. Without it, groups a prior rule already rolled up would be\ndouble-counted. (`onlyRollup: false` does NOT do this — it's a no-op.) To inspect what an\nexisting rule produced, query `type_In: [\"rollup\", \"rollup_fee\"], typeId: \"\u003Crule_id>\"` —\n`typeId` only means the rollup rule id when paired with a rollup `type`.\n\n### 2a. Group by the rule's real key (wallet id + asset key + platform + direction)\n```graphql\nquery GroupByKey($ts_Gte: DateTime, $ts_Lte: DateTime) {\n  subTransaction(\n    timestamp_Gte: $ts_Gte, timestamp_Lte: $ts_Lte,\n    excludeRollups: true,\n    groupBy: [\"belongs_to\", \"asset\", \"platform\", \"balance_factor\"],\n    aggregations: [\n      { field: id, function: COUNT, alias: \"count\" },\n      { field: fiatValue, function: AVG, alias: \"avgFiat\" }\n    ]\n  ) {\n    groupedAggregations { groupKey results { alias value } }\n  }\n}\n```\n`groupKey` gives you the wallet **id** (→ `internalAccountId`), the asset **key** (→\n`assetId`), platform, and balanceFactor — exactly the four fields a rule needs, no\nname\u002Fsymbol guessing. Groups under ~50 sub-txs are rarely worth a rule.\n\n### The asset-class bridge\nUsers think in asset *classes* (\"roll up all our USDC\"); a rule targets one asset *key*.\nWhen the user scopes by class, you may first group by `asset__asset_class__symbol` to\nprioritize, but you **must** then expand each promising class into its concrete asset keys\n(Step 2a already returns keys) and propose **one rule per (wallet, assetKey, platform,\ndirection)**. In the report, surface the sibling keys on the same wallet so the user sees\nwhich variants each rule does and does not cover.\n\n### 2b. Drill down by methodId (per significant group)\n```graphql\nquery DrillMethod($ts_Gte: DateTime, $ts_Lte: DateTime, $belongsTo_In: [ID], $asset_In: [ID], $balanceFactor: Float) {\n  subTransaction(\n    timestamp_Gte: $ts_Gte, timestamp_Lte: $ts_Lte,\n    belongsTo_In: $belongsTo_In, asset_In: $asset_In, balanceFactor: $balanceFactor,\n    excludeRollups: true,\n    groupBy: [\"tx__method_id\"],\n    aggregations: [\n      { field: id, function: COUNT, alias: \"count\" },\n      { field: amount, function: AVG, alias: \"avgAmount\" },\n      { field: amount, function: MAX, alias: \"maxAmount\" }\n    ]\n  ) {\n    groupedAggregations { groupKey results { alias value } }\n  }\n}\n```\n\n### 2c. Drill down by sub-tx type (optional)\nRepeat the same query shape with `groupBy: [\"type\"]` to see whether a specific sub-tx type\ndominates the group — useful only if you intend a `subtxType` rule.\n\n### Analysis strategy\nReason about which combinations make the best rules:\n1. **Coverage** — each rule should claim a meaningful share of its group.\n2. **Discriminating filter (when useful, not required)** — the four key fields (wallet +\n   assetKey + platform + direction) plus `fees` fully define most rules. Add an optional\n   narrowing filter (methodIds, amount bounds, counterparty, or `subtxType`) only when it\n   sharpens a heterogeneous group — many good rules use none. `subtxType` in particular is\n   optional; don't add it reflexively.\n3. **Interval** — DAY for high-frequency groups (>~500 sub-txs), MONTH otherwise.\n4. **Existing rules** — skip (account, assetKey, direction) tuples already covered by an\n   Active\u002FPending rule. **Never judge an existing rule by its current match count alone**:\n   a rule that has been running has already rolled up its pool, so the live (non-rollup)\n   sub-txs that remain are just the recent unprocessed few — a hard-working rule looks\n   idle. To see what it actually did, count the rollups it produced:\n   `subTransaction(type_In: [\"rollup\",\"rollup_fee\"], typeId: \"\u003Crule_id>\")`. Only treat a\n   rule as ineffective if it has produced ~nothing **and** matches ~nothing now.\n5. **Overlap (soft)** — two rules on the same wallet + assetKey + platform + direction with\n   non-disjoint filters can claim the same sub-txs. This is not fatal: the engine processes\n   rules deterministically by id (PK), so a shared sub-tx is always claimed by the same\n   rule. Prefer non-overlapping rules, but overlap is a note, not a blocker.\n\nFor each candidate, note WHY this combination was chosen.\n\n---\n\n## Step 2.5 — Validate candidates (MANDATORY quality gate)\n\nAt this point you hold your N candidate rule objects (from Step 2) in context. **Invoke the\n`tres-rollup-review` skill** (via the Skill tool) **once** — this loads the review checks\ninto your *own* context (it is not a separate agent and takes no arguments; the candidates\nare already here, nothing is passed). Then, following those instructions, walk your\ncandidates **one at a time** — for each candidate run the review's Check 1 (one\n`subTransactionRollupRulePreview` call), Check 2, and Check 3 — and record a per-candidate\nverdict: PASS \u002F DROP \u002F FIX, with the exact sub-tx and parent-tx counts. So 10 candidates →\n10 preview calls → 10 verdicts.\n\nAct on the results:\n- **DROP** any candidate that matches **0 sub-txs** (the rule would do nothing).\n- **FIX** config problems (inverted dates, min>max, identifier-on-wrong-direction,\n  mutually-exclusive prefixes, bad cutoffTime).\n- **Note** any overlap with another candidate or an Active\u002FPending rule in the report —\n  overlap is informational (the engine resolves it deterministically by id), so only adjust\n  if the user prefers cleaner separation; do not drop on overlap alone.\n\nCandidates that DROP or have unresolved FIXes don't proceed to Step 3. This gate is what\nkeeps suggestion quality high — do not skip it.\n\n---\n\n## Naming rollup rules\n\nEvery proposed rule needs a clear, consistent `name`. Decide it like this:\n\n1. **Match the org's existing convention first.** From the Active\u002FPending rule names you\n   fetched in Step 1b, infer the org's pattern — separator, field order, casing, how they\n   denote direction\u002Ffees\u002Finterval — and name new rules the same way so they sit naturally\n   alongside the existing ones.\n2. **If there's no clear existing pattern, default to:**\n   `\u003Cwallet name> - \u003Casset symbol> - \u003Cdirection> \u003Cfees label>` and append ` (\u003Cinterval>)`,\n   where the fees label maps:\n   - `fees: ONLY` → `fees` (e.g. \"gas fees\")\n   - `fees: INCLUDE` → `include fees`\n   - `fees: EXCLUDE` → `exclude fees`\n   Example: `EVM Exec Wallet 1 - ETH - outflow fees (monthly)`. When a single\n   discriminating filter defines the rule (e.g. a known method), fold it into the name\n   (e.g. `… - LP exits (daily)`).\n\nKeep names human-readable and unique within the proposal set. Use the same name in the HTML\nreport, the proposal table, and the `name` field of the create mutation.\n\n---\n\n## Step 3 — Present Results\n\n### 3a. HTML proposal report\nWrite a standalone `.html` file to the working directory (e.g.\n`rollup-rules-proposal.html`) and tell the user the path so they can open it. Use the\ntemplate and patterns in `references\u002Fproposal-html-template.html` **verbatim** — copy the\nCSS and skeleton as-is, only replacing the `\u003C!-- PLACEHOLDER -->` comments with actual data\nrows. Do NOT regenerate the CSS or layout. That reference file documents the summary cards,\nthe proposed-rules table, the skipped table, the per-candidate **\"Preview matched txs\"**\nledger link, the impact badges, and the hash\u002Faddress display rule. **Keep the HTML compact**\n(target under 4000 tokens of body).\n\nKey content rules from that reference, called out here because they matter:\n- The Volume column is **always** `Volume (sub-tx \u002F tx)` and values are **always** prefixed\n  with `~` (e.g. `~1,240 \u002F ~310`) — the values are the rollup_review-validated sub-tx and\n  distinct parent-tx counts, and `~` sets the expectation that the Preview link's ledger\n  filters can't express every rule filter exactly.\n- Impact badges: **high volume is a GOOD result, never an alarm** — green HIGH \u002F indigo\n  MEDIUM \u002F grey LOW. Red is reserved for actual problems (the 🟢\u002F🟡\u002F🔴 validation status),\n  never for impact.\n- Skipped table: include candidates the rollup_review gate dropped (e.g. \"0 matching\n  sub-txs\", \"overlaps rule #38211\").\n\n### 3b. Proposal task table\nPresent a **numbered markdown table** in chat — one row per proposed rule — so the user can\napprove by number. Columns: `#`, Rule Name, Wallet (id), Asset \u002F Platform, Direction,\nFilter, Volume (sub-tx \u002F tx), Interval, Validated Impact. Priority hint: HIGH for >1000\nsub-txs, MEDIUM for 200–1000, LOW for \u003C200.\n\n---\n\n## Step 4 — User Review\n\nAsk the user:\n> \"I've proposed X rollup rules (all validated against real transactions). Review the\n> report and table above. You can:\"\n> - **Approve all** — I'll create all proposed rules\n> - **Approve specific rules** — tell me which numbers\n> - **Provide feedback** — tell me what to adjust and I'll re-analyze\n> - **Cancel** — no rules will be created\n\nWait for the user's response before proceeding. **Never create a rule without explicit\nconfirmation.**\n\n---\n\n## Step 5 — Create Rules\n\nFor approved rules, run the `createSubTransactionRollupRules` mutation via the MCP `execute`\ntool (it accepts a batch and returns per-rule results with validation issues):\n\n```graphql\nmutation CreateRollupRules($rules: [RollupRuleCreationRequest]!) {\n  createSubTransactionRollupRules(rules: $rules) {\n    results {\n      rollupRuleId\n      validationIssues { blocking type message }\n    }\n  }\n}\n```\n\nEach entry in `$rules` (all camelCase):\n```json\n{\n  \"name\": \"ETH outflow gas — wallet-1 (daily)\",\n  \"interval\": \"DAY\",\n  \"createdBy\": \"AI\",\n  \"rule\": {\n    \"internalAccountId\": 123,\n    \"assetId\": \"ethereum_native\",\n    \"platform\": \"ETHEREUM\",\n    \"balanceFactor\": \"OUTFLOW\",\n    \"fees\": \"ONLY\",\n    \"methodIds\": [\"0x573ade81\"]\n  }\n}\n```\n\n- **Always set `createdBy: \"AI\"`** so the rule is attributed to AI in the audit trail.\n- **Omit `startDate` \u002F `endDate`** unless the user wants the rule bounded — omitting them\n  makes the rule open-ended.\n- **Only include optional filter fields the user\u002Fanalysis actually set** — do NOT send\n  `null` for unused optional fields, just omit them from the `rule` object.\n- Prefer **creating new rules**. Editing an existing PENDING rule (via top-level\n  `ruleId: \u003Cid>`) is supported, but pending rules may be auto-approved after a delay, so an\n  in-place edit can race with activation — only edit pending when the user explicitly asks.\n\n**Enum values (GraphQL enums, NOT quoted strings, in the query):**\n- `interval`: `DAY` or `MONTH`\n- `platform`: UPPERCASE — `ETHEREUM`, `BASE`, `SOLANA`, `BITCOIN`, …\n- `balanceFactor`: `INFLOW` (incoming, +1) or `OUTFLOW` (outgoing, -1)\n- `fees`: `INCLUDE` (txs + their fees), `EXCLUDE` (txs without fees), `ONLY` (only the fee\n  sub-txs — selects GAS **and** FEE). For a gas\u002Ffee rollup use `fees: ONLY` **by itself**;\n  do NOT also set `subtxType: GAS\u002FFEE` — `ONLY` already covers them, and adding\n  `subtxType: GAS` is redundant and wrongly drops the FEE sub-txs.\n- `subtxType`: a `FinancialAction` enum or null — e.g. `REWARD`, `NATIVE_TRANSFER`,\n  `TOKEN_TRANSFER`. Leave null for gas\u002Ffee rollups (use `fees: ONLY` instead).\n- `createdBy`: `AI`\n\n**Platform casing:** lowercase in query *filters* (`subTransaction(asset_In: [...])`,\n`asset(platform: \"ethereum\")`); UPPERCASE enum in *mutation* inputs (`rule.platform:\nETHEREUM`). Query return values are UPPERCASE too.\n\n**Validation rules the server enforces (never propose a rule that breaks these):**\n- `senderIdentifier` is only valid on **INFLOW** rules; `recipientIdentifier` only on\n  **OUTFLOW** rules (on an outflow the sender is always your wallet, and vice versa).\n- `senderIdentifier` ⊥ `originalSenderPrefix`; `recipientIdentifier` ⊥\n  `originalRecipientPrefix` (mutually exclusive).\n- `startDate` must be before `endDate`.\n- An identical rule (same `rule` JSON) cannot already exist for the org.\n\nThe mutation also re-checks matching transactions and overlaps and returns those as\n`validationIssues` — the rollup_review gate should have caught them already, but the server\nis the final authority.\n\n### Resolving `assetId` and `internalAccountId`\n- `internalAccountId` (integer): from the Step 1 wallet inventory.\n- `assetId` is the asset **key** = `\"\u003Cplatform_lowercase>_\u003Cidentifier>\"`. Native tokens:\n  `ethereum_native`, `base_native`, `solana_native`. ERC-20:\n  `ethereum_0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48` (USDC). Step 2a already returns keys\n  in the groupKey; otherwise look them up:\n```graphql\nquery AssetKeys { asset(key_In: [\"ethereum_native\"]) { results { key identifier platform symbol name parentPlatform } } }\n```\n\n---\n\n## Step 6 — Report Outcomes\n\nFor each per-rule result in the batch response, color-code the outcome so the user sees\nstatus at a glance — **🟢 green** = created with no issues, **🟡 yellow** = created with\nnon-blocking validation issues, **🔴 red** = blocked \u002F not created:\n- `rollupRuleId` present, no `validationIssues` → 🟢 created\n- `rollupRuleId` present with only non-blocking `validationIssues` → 🟡 created, issue noted\n- any `validationIssues` with `blocking: true` (no `rollupRuleId`) → 🔴 FAILED, quote the\n  `message`\n\nCreated rules start in `PENDING` status and activate on the next processing cycle. Use the\nsame 🟢\u002F🟡\u002F🔴 coding in the Step 3 report when surfacing the rollup_review validation\noutcome per proposed rule.\n\n---\n\n## A. List existing rollup rules\n\nWhen the user just wants to see current rules:\n\n```graphql\nquery ListRollupRules($limit: Int, $offset: Int, $status_In: [String]) {\n  subTransactionRollupRule(limit: $limit, offset: $offset, status_In: $status_In) {\n    totalCount\n    results { id name interval startDate endDate nextActivationDate status rule }\n  }\n}\n```\nVariables: `{\"limit\": 50, \"offset\": 0}` (add `status_In: [\"Active\"]` etc. to filter;\nstatus is title-case). Present as a numbered markdown table: Name, ID, Status, Interval,\nDate range (or \"indefinite\"), and the key rule filters (wallet, asset, direction, fees, any\noptional filter). Paginate if `totalCount > 50`.\n\n---\n\n## C. Delete rollup rules\n\nOnly **PENDING** rules can be deleted via the API. Active rules require TRES support.\n\nFirst list the rules (Section A) so the user can identify which to delete, then confirm the\nrule ID(s) before deleting.\n\n```graphql\nmutation DeleteRollupRules($ruleIds: [Int]!) {\n  deleteSubTransactionRollupRules(ruleIds: $ruleIds) {\n    results { deletedIds failures { ruleId reason } }\n  }\n}\n```\nReport `deletedIds` (succeeded) and `failures` (with reasons — typically the rule is\nalready active).\n\n---\n\n## Rule Field Reference (RollupRule)\n\n**Required:** `internalAccountId` (int), `assetId` (asset key), `platform` (enum),\n`balanceFactor` (INFLOW\u002FOUTFLOW), `fees` (INCLUDE\u002FEXCLUDE\u002FONLY).\n\n**Optional (have safe defaults — only set when needed):** `senderIdentifier`,\n`recipientIdentifier`, `originalSenderPrefix`, `originalRecipientPrefix`, `methodIds`\n(list), `maxAmount`, `minAmount`, `excludeFiat` (default false), `excludeInternal` (default\nfalse), `subtxType` (FinancialAction), `bufferInDays` (default 0; days to wait for\nlate-arriving txs), `cutoffTime` (\"HH:MM\"), `rollupInternalTransfersOnly` (default false;\nwhen true, only internal transfers are rolled up and the rollup is paired with its inflow —\nthe system also sets `mergeWithInflowTx` and `runInternalTransferClassificationOnRollups`).\n\n**Top-level request fields:** `name` (required), `interval` (required), `rule` (required),\n`startDate` (optional), `endDate` (optional), `ruleId` (optional — edit a pending rule),\n`createdBy` (set `AI`).\n\n**FinancialAction enum values (for `subtxType`):** TRACE_TRANSFER, TOKEN_TRANSFER,\nNATIVE_TRANSFER, DELEGATION, UNDELEGATION, VEST, UNVEST, VALIDATOR_CREATION, REWARD,\nCOMMISSION, GAS, FEE, EXCHANGE_WITHDRAWAL, EXCHANGE_DEPOSIT, EXCHANGE_TRANSFER,\nEXCHANGE_BUY, EXCHANGE_SELL, EXCHANGE_LOAN, EXCHANGE_SETTLEMENT, REBATE, FIAT_TRANSFER,\nBURNED, ROLLUP, ROLLUP_FEE, PLUG, GROUP, FUNDING, INTEREST, TRANSFER_DELEGATION_REWARD,\nREEVALUATION, PAYMENT, BANK_DEPOSIT, BANK_WITHDRAWAL, MINING_REWARD.\n\n---\n\n## Rules\n\n- **KEEP CONTEXT SMALL** — use aggregations, never fetch full result sets.\n- **Run discovery queries in parallel** where possible.\n- **ALWAYS run the Step 2.5 rollup_review gate** before presenting.\n- **ALWAYS produce both the HTML report AND the proposal table** after analysis.\n- **Explain your reasoning** for each proposed rule.\n- **Always confirm before creating** — present the full proposal and wait for explicit\n  approval before calling the create mutation.\n- **Provide a brief conversational summary** after presenting the report.\n- **Incorporate user clustering guidance** when choosing dimensions.\n\n---\n\n## Limitations — not available via MCP\n\n1. **Editing active rules** — there is no edit for an active rule; recreate (PENDING rules\n   can be edited via `ruleId`, or deleted and recreated).\n2. **Activating\u002Fdeactivating rules** — managed by the backend processing pipeline, not\n   directly controllable via API.\n3. **Viewing rollup breakdown** — the detailed breakdown of which raw transactions were\n   aggregated is in the Rollup Breakdown report in the TRES dashboard.\n4. **Active rule deletion** — only PENDING rules can be deleted via the API; direct the\n   user to TRES support for active rules.\n","# TRES Finance — Rollup Rules\n\nAnalyze an organization's sub-transaction patterns, identify groups of repetitive\ntransactions, and propose rollup rules that consolidate them into a single entry per\ninterval for cleaner ERP integration. This is a **data-driven discovery** flow — you find\nthe candidates from the data, validate each against real transactions, then present and\ncreate them.\n\nA rollup rule is keyed on FOUR dimensions that together define exactly which\nsub-transactions it claims:\n**internalAccount (wallet) + asset KEY + platform + balanceFactor (direction)**.\nOptional discriminating filters (fees, methodIds, subtxType, amount bounds,\ncounterparties) narrow it further. Everything you discover and propose must map onto this\nshape — see the Rule Field Reference at the bottom.\n\nA rollup is **non-destructive**: the original raw sub-transactions are always preserved\nand visible in the **Rollup Breakdown** report.\n\nAll GraphQL runs through the **TRES Finance MCP connector** (`execute` tool; validate with\n`validate_query` first when unsure). All variable keys and nested input fields MUST use\n**camelCase** (e.g. `internalAccountId`, `balanceFactor`), NEVER snake_case.\n\n---\n\n## Routing\n\n- **\"Suggest \u002F create \u002F propose rollup rules\"**, **\"too many transactions\"**, **\"roll up\n  X\"** → run the full discovery pipeline (Steps 0–6 below). This is the main flow.\n- **\"Show \u002F list my rollup rules\"** → Section A (List existing rules), then stop.\n- **\"Delete a rollup rule\"** → Section C (Delete rules).\n- **\"Review this specific rule\" \u002F \"what would this rule match\"** → hand off to the\n  **tres-rollup-review** skill.\n\n---\n\n## Step 0 — Confirm Scope\n\nEstablish scope with the user, but keep it light — only the analysis is scoped, the rules\nthemselves are usually open-ended.\n\n### Analysis window (OPTIONAL)\nA period only narrows the *discovery* queries so you look at recent, representative\nactivity. It is NOT required, and it is NOT the rule's date range.\n- \"Q1 2025\" → start: `2025-01-01T00:00:00Z`, end: `2025-03-31T23:59:59Z`\n- \"last 3 months\" → compute from today\n\nIf the user gives no period, analyze all history — that is fine and common.\n\n### Rule date range (PREFER OPEN-ENDED)\nThe rules you create should normally have **no start\u002Fend date** — they default to \"from the\nbeginning of time, indefinitely\" so they keep catching matching transactions going\nforward. Only set `startDate`\u002F`endDate` when the user explicitly wants the rule bounded.\n\n### Wallets (optional, default: all)\nThe user may scope to specific wallets.\n\n### Asset classes (optional, default: all non-spam)\nThe user may scope to specific asset classes (e.g. \"just stablecoins\", \"ETH\"). Remember: a\nclass (e.g. USDC) can span many asset keys\u002Fchains, but each rule targets ONE key — see the\nasset-class bridge in Step 2.\n\n### Clustering guidance (optional)\nHints like \"focus on gas fees\", \"ignore staking rewards under $10\", \"group ETH transfers\nby methodId\".\n\n**Confirm scope briefly, then start:**\n> \"I'll look for rollup candidates across **all wallets** and **all assets** (analyzing\n> **all history**). Rules I propose will be open-ended unless you want them date-bounded.\n> Starting now.\"\n\n---\n\n## Step 1 — Inventory\n\nRun these (in parallel where possible).\n\n### 1a. Wallets\n```graphql\nquery Wallets { internalAccount { totalCount results { id name identifier parentPlatform platforms balancesCount status } } }\n```\nCollect wallet `id` (integer) — this is the rule's `internalAccountId`. Use `platforms`\n(plural list) and `parentPlatform` (string); there is no singular `platform` field on\nwallets.\n\n### 1b. Existing rollup rules (so you don't duplicate coverage)\n```graphql\nquery ExistingRules { subTransactionRollupRule { totalCount results { id name interval status startDate endDate createdBy lastSuccessfulRunAt rule } } }\n```\n`rule` is the JSON config (`internal_account_id`, `asset_id`, `platform`, `balance_factor`,\n`fees`, …). Note which (account, assetKey, direction) tuples are already covered by\n**Active** or **Pending** rules — skip those. Ignore **Disabled** rules (they are\nsuperseded versions, not live coverage). Also study the existing rule **names** here to\nlearn the org's naming convention (see Naming below).\n\n### 1c. Total sub-transactions in scope\n```graphql\nquery InScope($ts_Gte: DateTime, $ts_Lte: DateTime) {\n  subTransaction(timestamp_Gte: $ts_Gte, timestamp_Lte: $ts_Lte) { totalCount }\n}\n```\n(Omit the timestamp args entirely when analyzing all history.)\n\nReport: \"Found X wallets, Y existing rules (Z active), N sub-transactions in scope.\"\n\n---\n\n## Step 2 — Discovery (the core analysis)\n\nUse aggregation queries to find which (wallet, asset, direction) groups have the most\nrepetitive volume, then drill into discriminating filters.\n\n### Filter-name reference (verified — use these EXACT names)\n- Wallet: `belongsTo_In: [ID]` (array, even for one id)\n- Asset by key: `asset_In: [ID]` (array of asset KEYS, e.g. `[\"ethereum_native\"]`)\n- Asset class: `asset_AssetClass_In: [ID]`\n- Direction: `balanceFactor: Float` (`-1` = OUTFLOW, `1` = INFLOW)\n- Amount: `amount_Gte` \u002F `amount_Lte`; fiat: `fiatValue_Gte` \u002F `fiatValue_Lte`\n- Counterparty: `sender_Identifier_In: [String]`, `recipient_Identifier_In: [String]`\n- Method: `tx_MethodId: String` (single) or group by `tx__method_id`\n- Sub-tx type: `type: String` \u002F `type_In: [String]` (FinancialAction) — filter with the\n  **lowercase** value (`\"gas\"`, `\"reward\"`, …); note this is the opposite casing from the\n  mutation's UPPERCASE `subtxType` enum. `groupBy: [\"type\"]` works too.\n- Dates: `timestamp_Gte` \u002F `timestamp_Lte`\n- Exclude already-rolled-up sub-txs: `excludeRollups: true`\n- Exclude gas\u002Ffee sub-txs: `excludeGasFees: true`; exclude spam: `excludeSpam: true`\n- Internal transfers only: `internalTransfer: true`\n\n### Always exclude already-rolled-up sub-txs\nAdd `excludeRollups: true` to every discovery\u002Fcount query. It drops ROLLUP \u002F ROLLUP_FEE\nsub-txs so your counts reflect what a *new* rule would actually capture — matching the\nrollup engine's own selection. Without it, groups a prior rule already rolled up would be\ndouble-counted. (`onlyRollup: false` does NOT do this — it's a no-op.) To inspect what an\nexisting rule produced, query `type_In: [\"rollup\", \"rollup_fee\"], typeId: \"\u003Crule_id>\"` —\n`typeId` only means the rollup rule id when paired with a rollup `type`.\n\n### 2a. Group by the rule's real key (wallet id + asset key + platform + direction)\n```graphql\nquery GroupByKey($ts_Gte: DateTime, $ts_Lte: DateTime) {\n  subTransaction(\n    timestamp_Gte: $ts_Gte, timestamp_Lte: $ts_Lte,\n    excludeRollups: true,\n    groupBy: [\"belongs_to\", \"asset\", \"platform\", \"balance_factor\"],\n    aggregations: [\n      { field: id, function: COUNT, alias: \"count\" },\n      { field: fiatValue, function: AVG, alias: \"avgFiat\" }\n    ]\n  ) {\n    groupedAggregations { groupKey results { alias value } }\n  }\n}\n```\n`groupKey` gives you the wallet **id** (→ `internalAccountId`), the asset **key** (→\n`assetId`), platform, and balanceFactor — exactly the four fields a rule needs, no\nname\u002Fsymbol guessing. Groups under ~50 sub-txs are rarely worth a rule.\n\n### The asset-class bridge\nUsers think in asset *classes* (\"roll up all our USDC\"); a rule targets one asset *key*.\nWhen the user scopes by class, you may first group by `asset__asset_class__symbol` to\nprioritize, but you **must** then expand each promising class into its concrete asset keys\n(Step 2a already returns keys) and propose **one rule per (wallet, assetKey, platform,\ndirection)**. In the report, surface the sibling keys on the same wallet so the user sees\nwhich variants each rule does and does not cover.\n\n### 2b. Drill down by methodId (per significant group)\n```graphql\nquery DrillMethod($ts_Gte: DateTime, $ts_Lte: DateTime, $belongsTo_In: [ID], $asset_In: [ID], $balanceFactor: Float) {\n  subTransaction(\n    timestamp_Gte: $ts_Gte, timestamp_Lte: $ts_Lte,\n    belongsTo_In: $belongsTo_In, asset_In: $asset_In, balanceFactor: $balanceFactor,\n    excludeRollups: true,\n    groupBy: [\"tx__method_id\"],\n    aggregations: [\n      { field: id, function: COUNT, alias: \"count\" },\n      { field: amount, function: AVG, alias: \"avgAmount\" },\n      { field: amount, function: MAX, alias: \"maxAmount\" }\n    ]\n  ) {\n    groupedAggregations { groupKey results { alias value } }\n  }\n}\n```\n\n### 2c. Drill down by sub-tx type (optional)\nRepeat the same query shape with `groupBy: [\"type\"]` to see whether a specific sub-tx type\ndominates the group — useful only if you intend a `subtxType` rule.\n\n### Analysis strategy\nReason about which combinations make the best rules:\n1. **Coverage** — each rule should claim a meaningful share of its group.\n2. **Discriminating filter (when useful, not required)** — the four key fields (wallet +\n   assetKey + platform + direction) plus `fees` fully define most rules. Add an optional\n   narrowing filter (methodIds, amount bounds, counterparty, or `subtxType`) only when it\n   sharpens a heterogeneous group — many good rules use none. `subtxType` in particular is\n   optional; don't add it reflexively.\n3. **Interval** — DAY for high-frequency groups (>~500 sub-txs), MONTH otherwise.\n4. **Existing rules** — skip (account, assetKey, direction) tuples already covered by an\n   Active\u002FPending rule. **Never judge an existing rule by its current match count alone**:\n   a rule that has been running has already rolled up its pool, so the live (non-rollup)\n   sub-txs that remain are just the recent unprocessed few — a hard-working rule looks\n   idle. To see what it actually did, count the rollups it produced:\n   `subTransaction(type_In: [\"rollup\",\"rollup_fee\"], typeId: \"\u003Crule_id>\")`. Only treat a\n   rule as ineffective if it has produced ~nothing **and** matches ~nothing now.\n5. **Overlap (soft)** — two rules on the same wallet + assetKey + platform + direction with\n   non-disjoint filters can claim the same sub-txs. This is not fatal: the engine processes\n   rules deterministically by id (PK), so a shared sub-tx is always claimed by the same\n   rule. Prefer non-overlapping rules, but overlap is a note, not a blocker.\n\nFor each candidate, note WHY this combination was chosen.\n\n---\n\n## Step 2.5 — Validate candidates (MANDATORY quality gate)\n\nAt this point you hold your N candidate rule objects (from Step 2) in context. **Invoke the\n`tres-rollup-review` skill** (via the Skill tool) **once** — this loads the review checks\ninto your *own* context (it is not a separate agent and takes no arguments; the candidates\nare already here, nothing is passed). Then, following those instructions, walk your\ncandidates **one at a time** — for each candidate run the review's Check 1 (one\n`subTransactionRollupRulePreview` call), Check 2, and Check 3 — and record a per-candidate\nverdict: PASS \u002F DROP \u002F FIX, with the exact sub-tx and parent-tx counts. So 10 candidates →\n10 preview calls → 10 verdicts.\n\nAct on the results:\n- **DROP** any candidate that matches **0 sub-txs** (the rule would do nothing).\n- **FIX** config problems (inverted dates, min>max, identifier-on-wrong-direction,\n  mutually-exclusive prefixes, bad cutoffTime).\n- **Note** any overlap with another candidate or an Active\u002FPending rule in the report —\n  overlap is informational (the engine resolves it deterministically by id), so only adjust\n  if the user prefers cleaner separation; do not drop on overlap alone.\n\nCandidates that DROP or have unresolved FIXes don't proceed to Step 3. This gate is what\nkeeps suggestion quality high — do not skip it.\n\n---\n\n## Naming rollup rules\n\nEvery proposed rule needs a clear, consistent `name`. Decide it like this:\n\n1. **Match the org's existing convention first.** From the Active\u002FPending rule names you\n   fetched in Step 1b, infer the org's pattern — separator, field order, casing, how they\n   denote direction\u002Ffees\u002Finterval — and name new rules the same way so they sit naturally\n   alongside the existing ones.\n2. **If there's no clear existing pattern, default to:**\n   `\u003Cwallet name> - \u003Casset symbol> - \u003Cdirection> \u003Cfees label>` and append ` (\u003Cinterval>)`,\n   where the fees label maps:\n   - `fees: ONLY` → `fees` (e.g. \"gas fees\")\n   - `fees: INCLUDE` → `include fees`\n   - `fees: EXCLUDE` → `exclude fees`\n   Example: `EVM Exec Wallet 1 - ETH - outflow fees (monthly)`. When a single\n   discriminating filter defines the rule (e.g. a known method), fold it into the name\n   (e.g. `… - LP exits (daily)`).\n\nKeep names human-readable and unique within the proposal set. Use the same name in the HTML\nreport, the proposal table, and the `name` field of the create mutation.\n\n---\n\n## Step 3 — Present Results\n\n### 3a. HTML proposal report\nWrite a standalone `.html` file to the working directory (e.g.\n`rollup-rules-proposal.html`) and tell the user the path so they can open it. Use the\ntemplate and patterns in `references\u002Fproposal-html-template.html` **verbatim** — copy the\nCSS and skeleton as-is, only replacing the `\u003C!-- PLACEHOLDER -->` comments with actual data\nrows. Do NOT regenerate the CSS or layout. That reference file documents the summary cards,\nthe proposed-rules table, the skipped table, the per-candidate **\"Preview matched txs\"**\nledger link, the impact badges, and the hash\u002Faddress display rule. **Keep the HTML compact**\n(target under 4000 tokens of body).\n\nKey content rules from that reference, called out here because they matter:\n- The Volume column is **always** `Volume (sub-tx \u002F tx)` and values are **always** prefixed\n  with `~` (e.g. `~1,240 \u002F ~310`) — the values are the rollup_review-validated sub-tx and\n  distinct parent-tx counts, and `~` sets the expectation that the Preview link's ledger\n  filters can't express every rule filter exactly.\n- Impact badges: **high volume is a GOOD result, never an alarm** — green HIGH \u002F indigo\n  MEDIUM \u002F grey LOW. Red is reserved for actual problems (the 🟢\u002F🟡\u002F🔴 validation status),\n  never for impact.\n- Skipped table: include candidates the rollup_review gate dropped (e.g. \"0 matching\n  sub-txs\", \"overlaps rule #38211\").\n\n### 3b. Proposal task table\nPresent a **numbered markdown table** in chat — one row per proposed rule — so the user can\napprove by number. Columns: `#`, Rule Name, Wallet (id), Asset \u002F Platform, Direction,\nFilter, Volume (sub-tx \u002F tx), Interval, Validated Impact. Priority hint: HIGH for >1000\nsub-txs, MEDIUM for 200–1000, LOW for \u003C200.\n\n---\n\n## Step 4 — User Review\n\nAsk the user:\n> \"I've proposed X rollup rules (all validated against real transactions). Review the\n> report and table above. You can:\"\n> - **Approve all** — I'll create all proposed rules\n> - **Approve specific rules** — tell me which numbers\n> - **Provide feedback** — tell me what to adjust and I'll re-analyze\n> - **Cancel** — no rules will be created\n\nWait for the user's response before proceeding. **Never create a rule without explicit\nconfirmation.**\n\n---\n\n## Step 5 — Create Rules\n\nFor approved rules, run the `createSubTransactionRollupRules` mutation via the MCP `execute`\ntool (it accepts a batch and returns per-rule results with validation issues):\n\n```graphql\nmutation CreateRollupRules($rules: [RollupRuleCreationRequest]!) {\n  createSubTransactionRollupRules(rules: $rules) {\n    results {\n      rollupRuleId\n      validationIssues { blocking type message }\n    }\n  }\n}\n```\n\nEach entry in `$rules` (all camelCase):\n```json\n{\n  \"name\": \"ETH outflow gas — wallet-1 (daily)\",\n  \"interval\": \"DAY\",\n  \"createdBy\": \"AI\",\n  \"rule\": {\n    \"internalAccountId\": 123,\n    \"assetId\": \"ethereum_native\",\n    \"platform\": \"ETHEREUM\",\n    \"balanceFactor\": \"OUTFLOW\",\n    \"fees\": \"ONLY\",\n    \"methodIds\": [\"0x573ade81\"]\n  }\n}\n```\n\n- **Always set `createdBy: \"AI\"`** so the rule is attributed to AI in the audit trail.\n- **Omit `startDate` \u002F `endDate`** unless the user wants the rule bounded — omitting them\n  makes the rule open-ended.\n- **Only include optional filter fields the user\u002Fanalysis actually set** — do NOT send\n  `null` for unused optional fields, just omit them from the `rule` object.\n- Prefer **creating new rules**. Editing an existing PENDING rule (via top-level\n  `ruleId: \u003Cid>`) is supported, but pending rules may be auto-approved after a delay, so an\n  in-place edit can race with activation — only edit pending when the user explicitly asks.\n\n**Enum values (GraphQL enums, NOT quoted strings, in the query):**\n- `interval`: `DAY` or `MONTH`\n- `platform`: UPPERCASE — `ETHEREUM`, `BASE`, `SOLANA`, `BITCOIN`, …\n- `balanceFactor`: `INFLOW` (incoming, +1) or `OUTFLOW` (outgoing, -1)\n- `fees`: `INCLUDE` (txs + their fees), `EXCLUDE` (txs without fees), `ONLY` (only the fee\n  sub-txs — selects GAS **and** FEE). For a gas\u002Ffee rollup use `fees: ONLY` **by itself**;\n  do NOT also set `subtxType: GAS\u002FFEE` — `ONLY` already covers them, and adding\n  `subtxType: GAS` is redundant and wrongly drops the FEE sub-txs.\n- `subtxType`: a `FinancialAction` enum or null — e.g. `REWARD`, `NATIVE_TRANSFER`,\n  `TOKEN_TRANSFER`. Leave null for gas\u002Ffee rollups (use `fees: ONLY` instead).\n- `createdBy`: `AI`\n\n**Platform casing:** lowercase in query *filters* (`subTransaction(asset_In: [...])`,\n`asset(platform: \"ethereum\")`); UPPERCASE enum in *mutation* inputs (`rule.platform:\nETHEREUM`). Query return values are UPPERCASE too.\n\n**Validation rules the server enforces (never propose a rule that breaks these):**\n- `senderIdentifier` is only valid on **INFLOW** rules; `recipientIdentifier` only on\n  **OUTFLOW** rules (on an outflow the sender is always your wallet, and vice versa).\n- `senderIdentifier` ⊥ `originalSenderPrefix`; `recipientIdentifier` ⊥\n  `originalRecipientPrefix` (mutually exclusive).\n- `startDate` must be before `endDate`.\n- An identical rule (same `rule` JSON) cannot already exist for the org.\n\nThe mutation also re-checks matching transactions and overlaps and returns those as\n`validationIssues` — the rollup_review gate should have caught them already, but the server\nis the final authority.\n\n### Resolving `assetId` and `internalAccountId`\n- `internalAccountId` (integer): from the Step 1 wallet inventory.\n- `assetId` is the asset **key** = `\"\u003Cplatform_lowercase>_\u003Cidentifier>\"`. Native tokens:\n  `ethereum_native`, `base_native`, `solana_native`. ERC-20:\n  `ethereum_0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48` (USDC). Step 2a already returns keys\n  in the groupKey; otherwise look them up:\n```graphql\nquery AssetKeys { asset(key_In: [\"ethereum_native\"]) { results { key identifier platform symbol name parentPlatform } } }\n```\n\n---\n\n## Step 6 — Report Outcomes\n\nFor each per-rule result in the batch response, color-code the outcome so the user sees\nstatus at a glance — **🟢 green** = created with no issues, **🟡 yellow** = created with\nnon-blocking validation issues, **🔴 red** = blocked \u002F not created:\n- `rollupRuleId` present, no `validationIssues` → 🟢 created\n- `rollupRuleId` present with only non-blocking `validationIssues` → 🟡 created, issue noted\n- any `validationIssues` with `blocking: true` (no `rollupRuleId`) → 🔴 FAILED, quote the\n  `message`\n\nCreated rules start in `PENDING` status and activate on the next processing cycle. Use the\nsame 🟢\u002F🟡\u002F🔴 coding in the Step 3 report when surfacing the rollup_review validation\noutcome per proposed rule.\n\n---\n\n## A. List existing rollup rules\n\nWhen the user just wants to see current rules:\n\n```graphql\nquery ListRollupRules($limit: Int, $offset: Int, $status_In: [String]) {\n  subTransactionRollupRule(limit: $limit, offset: $offset, status_In: $status_In) {\n    totalCount\n    results { id name interval startDate endDate nextActivationDate status rule }\n  }\n}\n```\nVariables: `{\"limit\": 50, \"offset\": 0}` (add `status_In: [\"Active\"]` etc. to filter;\nstatus is title-case). Present as a numbered markdown table: Name, ID, Status, Interval,\nDate range (or \"indefinite\"), and the key rule filters (wallet, asset, direction, fees, any\noptional filter). Paginate if `totalCount > 50`.\n\n---\n\n## C. Delete rollup rules\n\nOnly **PENDING** rules can be deleted via the API. Active rules require TRES support.\n\nFirst list the rules (Section A) so the user can identify which to delete, then confirm the\nrule ID(s) before deleting.\n\n```graphql\nmutation DeleteRollupRules($ruleIds: [Int]!) {\n  deleteSubTransactionRollupRules(ruleIds: $ruleIds) {\n    results { deletedIds failures { ruleId reason } }\n  }\n}\n```\nReport `deletedIds` (succeeded) and `failures` (with reasons — typically the rule is\nalready active).\n\n---\n\n## Rule Field Reference (RollupRule)\n\n**Required:** `internalAccountId` (int), `assetId` (asset key), `platform` (enum),\n`balanceFactor` (INFLOW\u002FOUTFLOW), `fees` (INCLUDE\u002FEXCLUDE\u002FONLY).\n\n**Optional (have safe defaults — only set when needed):** `senderIdentifier`,\n`recipientIdentifier`, `originalSenderPrefix`, `originalRecipientPrefix`, `methodIds`\n(list), `maxAmount`, `minAmount`, `excludeFiat` (default false), `excludeInternal` (default\nfalse), `subtxType` (FinancialAction), `bufferInDays` (default 0; days to wait for\nlate-arriving txs), `cutoffTime` (\"HH:MM\"), `rollupInternalTransfersOnly` (default false;\nwhen true, only internal transfers are rolled up and the rollup is paired with its inflow —\nthe system also sets `mergeWithInflowTx` and `runInternalTransferClassificationOnRollups`).\n\n**Top-level request fields:** `name` (required), `interval` (required), `rule` (required),\n`startDate` (optional), `endDate` (optional), `ruleId` (optional — edit a pending rule),\n`createdBy` (set `AI`).\n\n**FinancialAction enum values (for `subtxType`):** TRACE_TRANSFER, TOKEN_TRANSFER,\nNATIVE_TRANSFER, DELEGATION, UNDELEGATION, VEST, UNVEST, VALIDATOR_CREATION, REWARD,\nCOMMISSION, GAS, FEE, EXCHANGE_WITHDRAWAL, EXCHANGE_DEPOSIT, EXCHANGE_TRANSFER,\nEXCHANGE_BUY, EXCHANGE_SELL, EXCHANGE_LOAN, EXCHANGE_SETTLEMENT, REBATE, FIAT_TRANSFER,\nBURNED, ROLLUP, ROLLUP_FEE, PLUG, GROUP, FUNDING, INTEREST, TRANSFER_DELEGATION_REWARD,\nREEVALUATION, PAYMENT, BANK_DEPOSIT, BANK_WITHDRAWAL, MINING_REWARD.\n\n---\n\n## Rules\n\n- **KEEP CONTEXT SMALL** — use aggregations, never fetch full result sets.\n- **Run discovery queries in parallel** where possible.\n- **ALWAYS run the Step 2.5 rollup_review gate** before presenting.\n- **ALWAYS produce both the HTML report AND the proposal table** after analysis.\n- **Explain your reasoning** for each proposed rule.\n- **Always confirm before creating** — present the full proposal and wait for explicit\n  approval before calling the create mutation.\n- **Provide a brief conversational summary** after presenting the report.\n- **Incorporate user clustering guidance** when choosing dimensions.\n\n---\n\n## Limitations — not available via MCP\n\n1. **Editing active rules** — there is no edit for an active rule; recreate (PENDING rules\n   can be edited via `ruleId`, or deleted and recreated).\n2. **Activating\u002Fdeactivating rules** — managed by the backend processing pipeline, not\n   directly controllable via API.\n3. **Viewing rollup breakdown** — the detailed breakdown of which raw transactions were\n   aggregated is in the Rollup Breakdown report in the TRES dashboard.\n4. **Active rule deletion** — only PENDING rules can be deleted via the API; direct the\n   user to TRES support for active rules.\n",{"name":5,"description":54,"compatibility":55},"Analyze an organization's sub-transaction patterns in TRES Finance, identify groups of repetitive transactions, and propose data-driven rollup rules that consolidate them into one aggregated entry per interval (daily or monthly) for cleaner ERP integration. Also lists and deletes rollup rules. Trigger this skill whenever the user asks about rollup rules, transaction aggregation, consolidating transactions, reducing transaction noise, rolling up gas fees, rolling up staking rewards, rolling up micro-transactions, or collapsing many small ledger entries into fewer summary entries. Also trigger on \"create a rollup rule\", \"suggest rollup rules\", \"what should I roll up\", \"show my rollup rules\", \"delete a rollup rule\", \"aggregate transactions\", \"too many transactions\", \"reduce transaction count\", \"roll up fees\", \"daily rollup\", \"monthly rollup\". If a wallet has too many transactions, high-frequency activity, or noisy ledger entries, proactively suggest rollup rules. For computing the EXACT impact of a single already-specified rule or reviewing submitted\u002Fpending rules, use the tres-rollup-review skill instead.\n","Requires TRES Finance MCP connector","main","163301d1904c0a994539f5226ce0fcd65b8652bf","tres-finance-plugin\u002Fskills\u002Ftres-rollup-rules",357,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fclaude-plugins-community","https:\u002F\u002Fgithub.com\u002Fanthropics","https:\u002F\u002Fanthropic.com","2026-11-11 15:47:52",{"source":8,"skillName":5,"commands":65,"prompt":75,"zipAvailable":76},[66,69,72],{"tool":67,"command":68},"npx","npx skills add anthropics\u002Fclaude-plugins-community --skill tres-rollup-rules",{"tool":70,"command":71},"bunx","bunx skills add anthropics\u002Fclaude-plugins-community --skill tres-rollup-rules",{"tool":73,"command":74},"pnpm","pnpm dlx skills add anthropics\u002Fclaude-plugins-community --skill tres-rollup-rules","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fclaude-plugins-community\u002Fblob\u002Fmain\u002Ftres-finance-plugin\u002Fskills\u002Ftres-rollup-rules\u002FSKILL.md",true,[78],{"path":79,"resourceType":80,"resourceTypeDesc":81,"sizeBytes":82,"sourceHtmlUrl":83},"references\u002Fproposal-html-template.html","REFERENCE","参考文档",8860,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fclaude-plugins-community\u002Fblob\u002Fmain\u002Ftres-finance-plugin\u002Fskills\u002Ftres-rollup-rules\u002Freferences\u002Fproposal-html-template.html",[85,115,140,163,186,206],{"skillNo":86,"name":87,"nameZh":6,"description":88,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":89,"categories":90,"keywords":96,"publishedAt":49},"01M718G9QZ4B2DJVEB3MAW5ZB1","tres-wallets-upload","Upload and onboard multiple on-chain wallets or exchange accounts into Tres Finance. Use this skill whenever the user wants to add wallets, onboard wallets, import wallets, upload wallet addresses, ingest wallets, or connect exchanges into Tres — whether from a file (CSV\u002FExcel) or by typing them manually. This skill guides Claude through the full flow: wallet type selection → input collection → validation → preview with editable HTML table → exchange credential collection (if exchange) → user confirmation → batch creation via the TRES MCP API. Always trigger this skill for wallet onboarding, wallet data ingestion, or any request to \"add wallets to Tres\".","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fclaude-plugins-community\u002Fblob\u002Fmain\u002Ftres-finance-plugin\u002Fskills\u002Ftres-wallets-upload\u002FSKILL.md",[91,94,95],{"categoryNo":92,"categoryName":93,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000004","电子表格",{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},[97,98,99,100,101,46,102,103,104,105,44,106,107,108,109,110,111,112,113,114],"wallets","tres wallets upload","upload","typing","ingestion","chain","creation","xlsx","selection","confirmation","connect","collection","preview","api","batch","guides","on-chain","request",{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":121,"publishedAt":49},"01M718G5RD9064Z574RQ4SEY38","tres-upload-tx-header-validation","The exact column header names required by the TRES Finance bulk transaction CSV upload. Use whenever building, fixing, or validating the header row of a TRES manual transaction or sub-transaction upload CSV — especially after an upload fails with \"Missing required column(s): ...\". Trigger phrases include: 'fix my CSV headers', 'bulk transaction upload failed', 'missing required columns', 'validate TRES upload CSV', 'transaction CSV template headers'. This skill is ONLY about the header naming convention; it does not cover row values or upload workflow. Do NOT trigger for contacts import CSV (use tres-import-contacts), wallet upload CSV (use tres-wallets-upload), or general CSV parsing unrelated to bulk TX upload headers.","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fclaude-plugins-community\u002Fblob\u002Fmain\u002Ftres-finance-plugin\u002Fskills\u002Ftres-upload-tx-header-validation\u002FSKILL.md",[],[122,99,123,124,125,126,46,127,128,129,130,131,132,133,134,135,136,137,138,139],"tres upload tx header validation","validation","bulk","do","import","parsing","for","manual","trigger","fix","missing","general","only","use","workflow","csv","contacts","with",{"skillNo":141,"name":142,"nameZh":6,"description":143,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":144,"categories":145,"keywords":147,"publishedAt":49},"01M718G1F3DBWTX5H9RWPHHB4F","tres-tx-story","Analyze a blockchain transaction by its hash using TRES Finance MCP and generate a visual flow diagram showing all asset movements, followed by a plain-language explanation of what happened. Use this skill whenever the user provides a transaction hash and asks to \"analyze\", \"explain\", \"visualize\", \"diagram\", \"show me what happened in\", or \"tell the story of\" a transaction. Also trigger when the user pastes a tx hash (long hex string starting with 0x) and asks anything about it. Always use this skill for transaction hash analysis — do not attempt to answer from memory alone.","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fclaude-plugins-community\u002Fblob\u002Fmain\u002Ftres-finance-plugin\u002Fskills\u002Ftres-tx-story\u002FSKILL.md",[146],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[148,149,48,150,151,44,152,153,154,38,155,156,157,158,159,160,161,125,162,128],"tres tx story","Story","memory","hex","when","show me","analysis","me","diagram","generate","flow","asset","blockchain","STRING","visualize",{"skillNo":164,"name":165,"nameZh":6,"description":166,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":167,"categories":168,"keywords":170,"publishedAt":49},"01M718FW5ST9J56WY4TJ5G5A7X","tres-settings-management","Manage Organization Settings and Platform Settings via the TRES MCP GraphQL API. Use when users ask about org settings, platform settings, configuration, feature flags, enable\u002Fdisable platforms, balance diff, commit strategy, cost basis, ERP, pricing, sync boundaries, or any setting read\u002Fwrite operation. Trigger phrases include \"get settings\", \"show settings\", \"update settings\", \"change settings\", \"enable platform\", \"disable platform\", \"balance diff\", \"commit strategy\", \"cost basis strategy\", \"set min sync date\", \"configure\", \"turn on\", \"turn off\".","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fclaude-plugins-community\u002Fblob\u002Fmain\u002Ftres-finance-plugin\u002Fskills\u002Ftres-settings-management\u002FSKILL.md",[169],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[171,172,173,174,48,175,44,152,176,177,178,110,179,33,180,181,182,183,184,185],"tres settings management","settings","management","SET","get","configure","ask","commit","change","update","read","write","sync","mcp graphql","flags",{"skillNo":187,"name":188,"nameZh":6,"description":189,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":190,"categories":191,"keywords":194,"publishedAt":49},"01M718FFX3KV2JRFVS2RCM719D","tres-rollup-review","Compute the EXACT sub-transaction impact of a rollup rule in TRES Finance — every filter applied — and flag genuine problems (zero matches, overlap, config mistakes) before the rule is created. Two modes. Mode A: a pre-create quality gate invoked by the tres-rollup-rules skill to vet proposed candidate rules. Mode B: standalone review of a rule someone submitted or of existing PENDING rules. Trigger this skill when the user says \"review this rollup rule\", \"what would this rollup rule actually match\", \"preview the rollup impact\", \"how many transactions would this rule catch\", \"is this rollup rule valid\", \"validate my rollup rule\", \"check my pending rollup rules\", or \"review the rollup requests\". Do NOT use this to design or propose new rollups — that is tres-rollup-rules. This skill only measures impact and flags issues; it never executes mutations.","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fclaude-plugins-community\u002Fblob\u002Fmain\u002Ftres-finance-plugin\u002Fskills\u002Ftres-rollup-review\u002FSKILL.md",[192,193],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},[40,195,30,196,197,198,199,200,134,201,44,43,152,109,202,41,203,204,37,205],"tres rollup review","standalone","never","mode","issues","design","new","candidate","filter","valid","catch",{"skillNo":207,"name":208,"nameZh":6,"description":209,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":210,"categories":211,"keywords":213,"publishedAt":49},"01M718F9C31MH0XFSZ29Z4X7WD","tres-request-skill-update","Submit feedback about the TRES Claude plugin — bug reports, feature requests, skill improvements, new skill ideas, MCP issues, workflow friction, or positive feedback about what's working well. Use this skill whenever the user wants to share any kind of feedback about the plugin, its skills, or the TRES MCP. Trigger phrases include: \"submit feedback\", \"report a bug\", \"request a feature\", \"suggest an improvement\", \"I have an idea\", \"something is broken\", \"the skill isn't working\", \"I love this skill\", \"this worked great\", \"the MCP is returning wrong data\", \"the flow is confusing\", \"can you fix the skill\", \"file a skill request\", \"give feedback\", \"this could be better\". Also trigger proactively when the conversation appears to be wrapping up — e.g. the user says \"thanks\", \"that's all\", \"looks good\", \"we're done\", \"nothing else\", or any other signal that the task is complete. In that case, offer a brief feedback prompt instead of launching the full guided flow. Do NOT trigger for general questions about how a skill works — only when the user wants to submit feedback or the conversation is ending.","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fclaude-plugins-community\u002Fblob\u002Fmain\u002Ftres-finance-plugin\u002Fskills\u002Ftres-request-skill-update\u002FSKILL.md",[212],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[214,114,180,215,216,217,218,219,220,45,131,199,221,134,201,222,44,152,136,223],"skill update","tres request skill update","conversation","brief","broken","submit","re","good","give feedback","you"]