Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
a7cd697
feat: support API key for CryptoCompare market source (#14746)
vbaranov Aug 26, 2026
99f2c84
chore(deps): bump redix from 1.6.0 to 1.8.0 (#14738)
dependabot[bot] Aug 26, 2026
509e8f6
chore(deps-dev): bump phoenix_live_reload from 1.6.2 to 1.7.0 (#14654)
dependabot[bot] Aug 26, 2026
b6e0e0a
perf: Remove unconditional contract_address preload for tokens (#14750)
nikitosing Aug 27, 2026
8f47997
perf: Remove redundant preloads in api/v2/addresses/* (#14751)
nikitosing Aug 28, 2026
3b4147a
perf: Reduce addresses preload queries count (#14755)
Qwerty5Uiop Aug 29, 2026
0995dc3
perf: Deduplicate addresses preloads (#14758)
Qwerty5Uiop Aug 31, 2026
160bba2
chore(deps): bump typed_ecto_schema from 0.4.3 to 0.5.0 (#14761)
dependabot[bot] Aug 31, 2026
45fb7a2
chore(deps): bump phoenix_live_view from 1.2.10 to 1.2.11 (#14764)
dependabot[bot] Sep 1, 2026
99b2ade
chore(deps): bump oban from 2.23.1 to 2.24.0 (#14763)
dependabot[bot] Sep 1, 2026
8b70593
perf: Remove unused GasUsageSum cache with heavy DB query (#14771)
vbaranov Sep 3, 2026
5b10b43
fix: Forward [api?: true] where missed (#14740)
nikitosing Sep 3, 2026
17976c6
perf: Batch uncataloged token transfers scan via Migrator framework (…
vbaranov Sep 4, 2026
8c191dd
perf: Switch address counters to incremental consolidation (#14759)
vbaranov Sep 4, 2026
42b94e6
perf: Switch token counters to incremental consolidation (#14773)
vbaranov Sep 4, 2026
fbf8d89
fix: Disable old broadcast for token transfers without subscribers (#…
Qwerty5Uiop Sep 4, 2026
de8ed34
perf: Preload only rendered transaction fields in v1 tokentx endpoint…
vbaranov Sep 7, 2026
8eca952
perf: Scam addresses ETS cache (#14781)
Qwerty5Uiop Sep 8, 2026
9aeca25
perf: Limit logs before joining transactions in topic-only getLogs (#…
vbaranov Sep 8, 2026
ad84255
chore(deps): bump open_api_spex from 3.22.3 to 3.22.4 (#14790)
dependabot[bot] Sep 8, 2026
abd9e7b
chore(deps): bump joken from 2.6.2 to 2.7.0 (#14792)
dependabot[bot] Sep 8, 2026
c62038f
chore(deps): bump redix from 1.8.0 to 1.8.2 (#14786)
dependabot[bot] Sep 8, 2026
b04e7e7
chore(deps): bump mint from 1.9.3 to 1.10.0 (#14789)
dependabot[bot] Sep 8, 2026
6075396
chore(deps): bump absinthe from 1.11.0 to 1.12.0 (#14784)
dependabot[bot] Sep 8, 2026
2cbbe2d
perf: Make Postgrex prepared statements mode configurable per repo (#…
vbaranov Sep 8, 2026
1d0325b
chore(deps-dev): bump ex_doc from 0.40.3 to 0.40.4 (#14787)
dependabot[bot] Sep 8, 2026
3cdffdf
chore(deps): bump hammer from 7.4.0 to 7.5.0 (#14785)
dependabot[bot] Sep 8, 2026
abeeda3
perf: Optimize join_associations (#14775)
Qwerty5Uiop Sep 9, 2026
bbba374
fix: support hexadecimal block number in eth_getBalance (#14804)
vbaranov Sep 9, 2026
e6788ff
fix: Decouple cache propagation to API nodes from block import (#14778)
vbaranov Sep 9, 2026
cc16547
chore(deps): bump oban from 2.24.0 to 2.24.1 (#14791)
dependabot[bot] Sep 9, 2026
d2a03c2
perf: Deduplicate preloads (#14797)
Qwerty5Uiop Sep 10, 2026
86724dc
feat: support OP Stack post-exec transactions (#14734)
nonsense Sep 10, 2026
e1adb82
fix: Group JSON RPC requests by url type (#14806)
Qwerty5Uiop Sep 10, 2026
5eef09c
v11.3.0
vbaranov Sep 10, 2026
43af7ea
Update CHANGELOG
vbaranov Sep 10, 2026
1e61e6e
chore(deps): bump tesla from 1.21.2 to 1.21.3 (#14783)
dependabot[bot] Sep 14, 2026
069104c
perf: Optimize realtime events broadcast for legacy topics (#14810)
Qwerty5Uiop Sep 14, 2026
dca0fee
fix: support OP Stack Upgrade 20 (Super Root games, SystemConfig v4) …
vbaranov Sep 14, 2026
6037429
chore(deps-dev): bump dialyxir from 1.4.7 to 1.4.8 (#14822)
dependabot[bot] Sep 14, 2026
051fbf1
perf: Use Endpoint.local_broadcast instead of Endpoint.broadcast (#14…
Qwerty5Uiop Sep 15, 2026
982fb44
chore(deps): bump redix from 1.8.2 to 1.9.1 (#14823)
dependabot[bot] Sep 15, 2026
4b99cc9
chore(deps): bump mox from 1.1.0 to 1.3.2 (#14825)
dependabot[bot] Sep 15, 2026
5221aff
chore(deps): bump hammer_backend_redis from 7.1.1 to 7.2.0 (#14826)
dependabot[bot] Sep 15, 2026
bcc8d17
chore(deps-dev): bump cowboy from 2.18.0 to 2.19.0 (#14824)
dependabot[bot] Sep 15, 2026
d1c51cf
perf: reuse preloaded proxy and ABI associations in input decoding (#…
vbaranov Sep 15, 2026
075ca1c
perf: preload signed_authorizations only for EIP-7702 transactions (#…
vbaranov Sep 15, 2026
80113f9
perf: Bound and deduplicate on-demand token total supply fetcher (#14…
vbaranov Sep 15, 2026
fea802f
perf: cache public address tags and index-driven tags lookup (#14833)
vbaranov Sep 15, 2026
50cbcf4
Add missing test
vbaranov Sep 15, 2026
5efb2aa
docs: document OP Stack transaction types in Transaction schema (#14835)
vbaranov Sep 15, 2026
07c097c
v11.3.1
vbaranov Sep 16, 2026
43a8e72
fix: Move counters_corrections after ctb deriving (#14837)
Qwerty5Uiop Sep 17, 2026
9a55cc1
fix: tolerate non-string NFT metadata values in NFTHelper (#14838)
vbaranov Sep 17, 2026
21515c6
fix: dedupe multichain export queue rows to avoid cardinality violati…
vbaranov Sep 17, 2026
b7671f6
fix: increase beacon RPC client response timeout to 30s (#14840)
vbaranov Sep 17, 2026
4670d6d
perf: Preload data for realtime block events by batch (#14842)
Qwerty5Uiop Sep 21, 2026
346d999
perf: refill top addresses cache in the background on API nodes (#14843)
vbaranov Sep 21, 2026
ae478d7
perf: batch chain-specific lookups in realtime block broadcast (#14849)
vbaranov Sep 21, 2026
2da78cd
v11.3.2
vbaranov Sep 21, 2026
ba08ac5
chore(deps): bump redix from 1.9.1 to 1.9.2 (#14853)
dependabot[bot] Sep 22, 2026
7f94d9b
chore(deps): bump phoenix_live_view from 1.2.11 to 1.2.12 (#14850)
dependabot[bot] Sep 22, 2026
5487b16
fix: Bound pending operations PTO->PBO migration batches by transacti…
vbaranov Sep 23, 2026
3ea5c7a
fix: recognize null round errors with epoch suffix in catchup fetcher…
vbaranov Sep 23, 2026
cb602b7
fix: tolerate pending internal transactions at chain head in txlistin…
vbaranov Sep 28, 2026
e1b902f
chore(deps): bump mint from 1.10.0 to 1.10.1 (#14876)
dependabot[bot] Sep 28, 2026
f8d5215
fix: apply a finite timeout to the internal transactions import (#14864)
vbaranov Sep 29, 2026
f09cc3b
feat: add env var to disable transactions count consolidation (#14877)
vbaranov Sep 29, 2026
3b1b7a6
fix: handle multi-id historical transfers when reverting token instan…
vbaranov Sep 29, 2026
2f6b468
fix: handle null nonce/mixHash returned by Nethermind for AuRa blocks…
vbaranov Sep 29, 2026
e23fe2f
fix: do not move the beacon deposit fetcher cursor forward on reorgs …
vbaranov Sep 30, 2026
49f6330
fix: ReindexBlocksWithStaleInternalTransactions migration (#14884)
Qwerty5Uiop Sep 30, 2026
796c680
ex_abi bump: 0.8.4 -> 0.8.5
vbaranov Oct 1, 2026
435e853
Remove deploy_e2e step from docker image publishing
vbaranov Oct 1, 2026
1d11ae8
fix: exclude non-traceable blocks from coin balance catchup init quer…
vbaranov Oct 1, 2026
8651953
Pin ex_abi 0.8.5 from pm
vbaranov Oct 1, 2026
e78c915
fix: Missing blocks clearing on failed import (#14888)
Qwerty5Uiop Oct 1, 2026
69347f3
fix: stop internal transactions import from upserting existing addres…
vbaranov Oct 2, 2026
cd77624
fix: export only supplied coin balances to the multichain balances qu…
vbaranov Oct 2, 2026
3185f58
fix: fix internal transactions fetcher test on zksync chain type (#14…
vbaranov Oct 2, 2026
a031e30
11.3.3
vbaranov Oct 2, 2026
5b7c157
v12.0.0 (#14908)
vbaranov Oct 6, 2026
f11aaf7
WIP: Merge upstream v12.0.0 (has conflicts)
github-actions[bot] Oct 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
130 changes: 130 additions & 0 deletions .agents/agents/leaf-schemas-cataloger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
---
name: leaf-schemas-cataloger
description: "Maintains a cached catalog of leaf type schemas under `apps/block_scout_web/lib/block_scout_web/schemas/api/v2/general/`. Invoke at the start of any OpenAPI spec authoring task that involves selecting or referencing leaf-type schemas. The agent checks a content hash, regenerates the catalog only when leaf files have changed, and writes the result to `.claude/skills/openapi-spec/references/cache/leaf-schemas/catalog.md`. Self-contained — does not depend on the openapi-spec skill prompt."
permissionMode: auto
model: haiku
tools: Bash, Read, Write
---

You maintain a cached, human-readable catalog of leaf type schemas defined in the Blockscout codebase. The catalog is consumed by the `openapi-spec` skill to give the parent agent a fast, accurate vocabulary of available leaf schemas without re-reading every source file each session.

## Workflow

1. **Check freshness.** Run:
```
bash .claude/skills/openapi-spec/scripts/leaf-schemas-cache-check.sh
```
The script emits three `key=value` lines on stdout:
- `state=fresh` or `state=stale`
- `digest=<sha256>` — the current content digest of `general/*.ex`
- `cache_dir=<absolute-path>` — where the catalog and digest live

2. **If `state=fresh`**, stop immediately. Report: `Catalog is fresh (digest=<...>). No work needed.` Do not regenerate.

3. **If `state=stale`**, regenerate:
1. Collect facts:
```
python3 .claude/skills/openapi-spec/scripts/leaf-schemas-collect-facts.py
```
Capture the stdout — it is a single JSON document with one entry per leaf, each containing `module`, `short_name`, `path`, `source`, and up to three `callsites` (file + line).
2. Build the catalog (see "Catalog format" below). Use the source content for every leaf; use callsite locations as **input to interpretation** when a leaf's purpose is not obvious from its name and structure alone — open the referenced files via `Read` and inspect the lines around each callsite to see how the leaf is used in practice. Spend this effort only on leaves whose role is genuinely ambiguous (a name like `Tag`, `ProxyType`, or `Implementation` warrants a look; `AddressHash` or `Timestamp` does not).
3. Write atomically:
- Write the catalog to `<cache_dir>/catalog.md.tmp`, then move to `<cache_dir>/catalog.md`.
- Write the new digest to `<cache_dir>/digest.tmp`, then move to `<cache_dir>/digest`.
- The two `mv` commands ensure that a half-written cache cannot be mistaken for fresh.
4. Report: `Catalog regenerated (digest=<new-digest>, leaves=<count>).`

4. **If a script fails** (non-zero exit, missing file, etc.), report the error verbatim and stop. The parent skill is responsible for falling back to live source reads — your job is to keep the cache truthful or absent, never wrong.

## Catalog format

The catalog is markdown. It must contain exactly these sections in this order:

```markdown
# Leaf Type Schemas Catalog

Auto-generated by the `leaf-schemas-cataloger` agent. Do not edit by hand —
changes are overwritten on the next regeneration.

Source directory: `apps/block_scout_web/lib/block_scout_web/schemas/api/v2/general/`

## Scalar leaves

Leaves whose top-level shape is a JSON primitive (`string` with pattern /
enum / format, `integer`, `boolean`). The "Spec" column captures the full
constraint at a glance.

| Module | Spec | Purpose |
|---|---|---|
| `General.<Name>` | `<type, constraints>` | <one-line purpose> |
| ... |

## Composite leaves

Leaves whose top-level shape is `object` or `array`. The "Shape" column
lists top-level fields (or array element kind) only; refer to the source
file for nested structure.

| Module | Shape | Purpose | Source |
|---|---|---|---|
| `General.<Name>` | `object { field1, field2[]? }` | <one-line purpose> | `general/<file>.ex` |
| ... |
```

### Classification rule

A leaf is **scalar** if its `OpenApiSpex.schema(%{...})` map has `type: :string`, `type: :integer`, `type: :boolean`, or similar primitive at the top level (with optional `pattern:`, `enum:`, `format:`, `nullable:`, `minimum:`, etc.). It is **composite** if its top level is `type: :object`, `type: :array`, or contains `anyOf:` / `oneOf:` at the top level.

### Spec column conventions (scalar table)

- Write the type plainly: `string`, `integer`, `boolean`.
- Append constraints as a comma-separated list: `pattern 0x[a-f0-9]{40}`, `enum: [eip1167, eip1967, ...]`, `format: date-time`, `minimum: 0`, `nullable`.
- For nullable variants, use `string \| null` rather than a separate column. Escape pipe characters (`\|`) inside table cells whenever they appear — GitHub-Flavored Markdown table cells treat raw `|` as a column separator.
- When `pattern:` references `General.<x>_pattern()`, expand it to the actual regex if you can locate the constant in the source; otherwise write `pattern: General.<x>_pattern()`.
- When `enum:` is sourced at runtime from `Ecto.Enum.values(SomeModule, :field)`, look up the actual value list by reading the referenced Ecto schema module under `apps/explorer/lib/explorer/chain/` and inline the literal values in the Spec cell. Do **not** leave `Ecto.Enum.values(...)` in the catalog — the reader needs the concrete vocabulary.

### Shape column conventions (composite table)

- Depth = 1 only. Do not descend into nested objects or arrays of objects.
- Use `object { a, b, c }` for objects; mark optional fields with `?`.
- Use `array<object>` or `array<string>` for arrays.
- Use `anyOf [string, object, ...]` for top-level `anyOf` / `oneOf`.

### Purpose column rules — important

The "Purpose" cell must describe **what the schema represents and the kind of context it appears in**, in *general* terms. It must remain valid even if every current callsite is renamed or restructured.

**Do**:
- Describe the modelled entity ("Ethereum address hash, lowercase 20-byte hex").
- Describe the typical role ("nullable variant for properties that may be absent in proxy contracts").
- Describe the data shape's meaning ("decoded event log parameters with name/type/value triples").

**Do not**:
- Name specific consumer controllers, views, schema modules, or files in the **Purpose** column (`address_controller.ex`, `BlockScoutWeb.Schemas.API.V2.Transaction`, etc.).
- Reference specific actions or endpoints (`/v2/blocks/...`, `:show_address`, etc.).
- Quote line numbers or counts of callers.
- Use words like "used by X" or "called from Y".

Note: the **Source** column of the composite table is *not* a callsite reference — it points at the leaf's own definition file (`general/<file>.ex`), which is structural metadata, not consumer context. Always populate it.

Callsite line context is a tool for *you* to understand the leaf's purpose. It must not leak into the catalog text. If a callsite is the only thing that disambiguates the leaf's purpose, abstract the pattern: instead of "used by `address_controller.ex` to render private tags", write "user-applied label with name and type, attached to account records".

## Atomic write recipe

Always use temp-file-and-rename so that an interrupted run cannot leave a half-written catalog matching a fresh digest:

```bash
printf '%s' "$CATALOG_CONTENT" > "$CACHE_DIR/catalog.md.tmp"
mv "$CACHE_DIR/catalog.md.tmp" "$CACHE_DIR/catalog.md"
printf '%s' "$NEW_DIGEST" > "$CACHE_DIR/digest.tmp"
mv "$CACHE_DIR/digest.tmp" "$CACHE_DIR/digest"
```

The `Write` tool itself is fine — write to `catalog.md.tmp` first, then `mv` via `Bash`. Do **not** write directly to `catalog.md` without the rename step.

## What you do NOT do

- You do not modify source files under `schemas/api/v2/general/`. The catalog is downstream of the code, never upstream.
- You do not edit the `openapi-spec` skill or its references. You only own the cache directory.
- You do not invoke other agents.
- You do not commit changes. The cache directory is gitignored.
2 changes: 2 additions & 0 deletions .agents/agents/openapi-spec-inspector.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,6 @@ The report should include:
6. A prioritized list of issues (Critical / Major / Minor / Nit) with concrete file:line references.
7. Suggested fixes (described, not applied).

Apply the finding-quality gates in `references/inspection-checklist.md` §7 before finalizing items (6) and (7).

Keep the report focused and actionable. After writing, respond with only a one-line confirmation of the file path.
31 changes: 31 additions & 0 deletions .agents/skills/alphabetically-ordered-aliases/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Elixir code style conventions prefer that module aliases are alphabetically orde
- When organizing module aliases at the top of a file
- When multiple aliases from related modules are defined together
- When refactoring code to improve consistency and readability
- When adding a new alias into an existing `alias ...{...}` grouped block
- When touching files that already have `Credo.Check.Readability.AliasOrder` warnings

## Anti-Patterns (Avoid These)

Expand Down Expand Up @@ -75,6 +77,15 @@ For modules with the same prefix like:

Sort by the last component: `Create...` < `Drop...` < `Helper`

For grouped aliases like:

```elixir
alias BlockScoutWeb.API.V2.{ApiView, Helper, InternalTransactionView, TokenView}
```

sort entries exactly as Credo expects by module name order within the group.
When two names share a long prefix (for example `InternalTransaction...`), compare the next character and keep strict lexical order.

### Step 3: Reorder in code

Rearrange the alias statements to match the alphabetical order determined in Step 2.
Expand All @@ -87,6 +98,26 @@ Run Credo to ensure no warnings remain:
mix credo --strict
```

If you changed only a few files, prefer targeted checks first:

```bash
mix credo --strict --files path/to/file1.ex,path/to/file2.ex
```

## Trigger Cues

- Credo output includes: `The alias ... is not alphabetically ordered among its group`
- A diff adds/reorders aliases near module top
- A grouped alias block contains names that are visually close (`InternalTransaction...` vs `InternalTransactions...`)

## Reliable Checklist

1. Re-read every alias group in the touched file after edits.
2. Re-sort grouped aliases (inside `{...}`) and standalone aliases.
3. Ensure new aliases are inserted in-place, not appended.
4. Run `mix format` after edits.
5. Run Credo (targeted or full) and confirm no alias-order warnings remain.

## Example Violations and Fixes

### Violation 1: Helper before DropTransactions
Expand Down
15 changes: 15 additions & 0 deletions .agents/skills/elixir-clause-grouping/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,26 @@ description: Use when refactoring Elixir multi-clause functions, extracting help

In Elixir modules, all clauses of the same function should stay together. Inserting a `defp` helper between clauses of a `def` or `defp` makes the function harder to read and can trigger Credo readability warnings. When shared logic needs to be extracted, keep the original clause group contiguous and place the helper after the full group.

This also applies to Phoenix view modules that define many `render/2` clauses with different templates: all `render/2` clauses still belong to the same function and must be contiguous.

## When to Use

- When refactoring a multi-clause `def` or `defp`
- When extracting duplicated logic from multiple function clauses
- When addressing Credo warnings about clause grouping or readability
- When editing controller, view, or context modules with several clauses of the same function
- During review when a helper was added in the middle of another function's clauses
- When editing Phoenix `render/2` clauses and introducing helper functions nearby
- When adding any `defp` between two definitions that share the same function name/arity
- When you see compiler output like: `clauses with the same name and arity ... should be grouped together`

## Core Rule

- Keep all clauses of the same function contiguous
- Do not place `defp` helpers between clauses of another function
- Extract shared logic into a helper placed after the full clause group
- Before finishing edits, scan up/down around each new helper and verify no same-name/same-arity clauses are split
- In view modules, keep all `render/2` clauses contiguous even if clause heads match different template strings

## Anti-Pattern

Expand Down Expand Up @@ -58,6 +65,14 @@ end
3. Extract shared logic only after the full clause group.
4. Re-check that no unrelated `def` or `defp` appears inside the group.
5. Run formatting after the refactor.
6. For Phoenix views, explicitly verify all `render/2` clauses are contiguous (not only clauses for the same template).
7. If you add a helper used by `render/2`, place it after the last `render/2` clause in the module.

## Trigger Cues

- Compiler warning: `clauses with the same name and arity ... should be grouped together`
- Credo warning about grouping/splitting function clauses
- A diff that inserts `defp` between two `def render(` declarations

## Notes

Expand Down
13 changes: 10 additions & 3 deletions .agents/skills/openapi-spec/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ All paths are relative to `apps/block_scout_web/lib/block_scout_web/`. Most endp
| Account controllers (Private spec) | `controllers/account/api/v2/<domain>_controller.ex` |
| Legacy controllers | `controllers/api/legacy/<domain>_controller.ex` (routed under `/legacy`) |
| V2 schema modules | `schemas/api/v2/<domain>.ex` and `schemas/api/v2/<domain>/*.ex` |
| V2 chain-type schema subdirs | `schemas/api/v2/<chain>/*.ex` (e.g. `schemas/api/v2/{arbitrum,beacon,celo,optimism,scroll,zilliqa,mud}/*.ex`) |
| V2 chain-type schema subdirs | `schemas/api/v2/<chain>/*.ex` (e.g. `schemas/api/v2/{arbitrum,beacon,celo,optimism,scroll,zilliqa}/*.ex`) |
| V2 proxy schemas | `schemas/api/v2/proxy/*.ex` |
| Account schemas (Private spec) | `schemas/api/v2/account/*.ex` |
| Legacy schemas | `schemas/api/legacy/*.ex` |
Expand All @@ -46,6 +46,12 @@ All paths are relative to `apps/block_scout_web/lib/block_scout_web/`. Most endp

**On router coverage of the public spec:** `specs/public.ex` builds `paths` via `Paths.from_router(ApiRouter)`, which picks up everything reachable from `api_router.ex` — including endpoints declared in the sub-routers that `api_router.ex` `forward`s to (api-key, utils, address-badges). Only `TokensApiV2Router` and `SmartContractsApiV2Router` need the extra `Paths.from_routes(...)` merges in `public.ex` because their prefixes are stripped by Phoenix `forward` and must be re-added. A new annotated endpoint placed in any of the other sub-routers needs no extra wiring beyond the `forward` that already exists in `api_router.ex`.

## Leaf-schemas catalog (bootstrap step)

Before any workflow below, invoke the `leaf-schemas-cataloger` agent (prompt: `Refresh the leaf-schemas catalog if stale.`). It maintains a compact catalog of every leaf type schema under `schemas/api/v2/general/` at `references/cache/leaf-schemas/catalog.md` (auto-generated, gitignored). Read that file when picking a primitive leaf type for a response property or parameter `schema:`.

**Fallback:** if the agent fails or the catalog is unavailable, glob `apps/block_scout_web/lib/block_scout_web/schemas/api/v2/general/*.ex` and read individual leaf files as needed.

## Core patterns

### The operation macro
Expand Down Expand Up @@ -144,7 +150,7 @@ The order of tag groups in the generated public spec is not derived from the con
If a new annotated controller introduces a brand-new tag, the agent must register it in the right group, or the tag will still appear in the spec (via controller-side `tags(...)`) but with no ordering guarantee and no entry in the top-level `tags:` list:

- Base endpoint → append the kebab-case tag to `@default_api_categories`.
- Chain-type endpoint → add it inside the relevant `case @chain_identity` branch, matching the existing patterns (module-attribute + `defp` for static lists, full `defp` body when the tag set depends on a runtime flag such as `mud_enabled?()`).
- Chain-type endpoint → add it inside the relevant `case @chain_identity` branch, matching the existing patterns (module-attribute + `defp` for static lists, full `defp` body when the tag set depends on a runtime flag).
- Legacy endpoint → no action; `"legacy"` is already the trailer.

Tags that are already covered by an existing group (e.g. another `addresses` endpoint) need no change.
Expand Down Expand Up @@ -229,7 +235,7 @@ For each parameter the controller reads:
- **Domain-specific but used by multiple operations in the same controller?** Add a private helper function in the controller itself. This avoids polluting `general.ex` with chain-specific concerns while preventing duplication across operations.
- **Truly one-off (single operation)?** Define an inline `%OpenApiSpex.Parameter{}` struct directly in the `operation` macro arguments.

3. **For pagination parameters**, use `define_paging_params(field_names)` — pass the cursor field names as strings, and always include `"items_count"` (the `next_page_params` helper adds it to every cursor automatically). See `references/parameter-discovery.md` section "The `define_paging_params` factory" for details.
3. **For pagination parameters**, use `define_paging_params(field_names)` — pass the cursor field names as strings. See `references/parameter-discovery.md` section "The `define_paging_params` factory" for details.

### Step 3: Create or locate response schema

Expand Down Expand Up @@ -365,6 +371,7 @@ Use this to audit an existing declaration for correctness, completeness, and adh
| `references/inspection-checklist.md` | You're running an audit of an existing declaration (Workflow C) |
| `references/spec-generation-and-verification.md` | You need to generate the spec YAML, validate it, or inspect specific operations/schemas with oastools |
| `references/oastools-audit-recipes.md` | You want to audit the generated spec for spec-wide convention drift or reuse candidates, without reading every source file |
| `references/cache/leaf-schemas/catalog.md` | You need to pick a primitive leaf type (`General.AddressHash`, `General.IntegerString`, `General.Tag`, …) for a property or parameter — auto-generated by the `leaf-schemas-cataloger` agent; invoke it first if missing |

## Using subagents

Expand Down
2 changes: 2 additions & 0 deletions .agents/skills/openapi-spec/references/cache/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!.gitignore
Loading
Loading