Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .claude/skills/build-fix/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
name: build-fix
description: Build a cabal component with nix, parse GHC errors and warnings, fix them, and rebuild until clean.
disable-model-invocation: true
argument-hint: [nix-flake-target]
---

Build and iteratively fix GHC errors/warnings for the given nix flake target.

If no argument is given, default to `'.#cardano-rpc:lib:cardano-rpc'`.

Target: $ARGUMENTS

## Procedure

1. Run `nix build '<target>' 2>&1` and capture the output.
2. Parse the output for GHC errors and warnings.
3. If there are errors, fix them one category at a time:
- **Missing imports**: Look up which module exports the symbol. Remember that RIO does NOT re-export everything from Prelude/Data.List (e.g. `sortBy`, `on` need explicit imports).
- **Type mismatches**: Analyze carefully. In cardano-rpc, remember that `Proto msg` is a grapesy wrapper — internal functions use plain proto-lens types, `getProto`/`fmap getProto` at handler boundaries only.
- **Not in scope**: Check if it's a missing import or a typo.
- **Redundant constraints**: Remove them.
- **Redundant imports**: Remove them.
- **Deprecated functions**: Replace with the recommended alternative (e.g. `valueToList` -> `toList` from `GHC.IsList`).
4. After fixing, rebuild.
5. Repeat until the build succeeds with no errors.
6. If there are warnings remaining, fix them too:
- Redundant imports/constraints: remove
- hlint-style suggestions: apply (e.g. lambda to infix)
- Deprecated usage: replace
7. Rebuild one final time to confirm clean output.

## Important rules
- NEVER manually edit files under `gen/` — those are generated by proto-lens.
- If proto generated code needs updating, use `/proto-gen` instead.
- RIO's `^.` works with proto-lens lenses. Do NOT add `lens-family` as a dependency.
- Verify fixes carefully before rebuilding to minimize nix build round-trips (each takes minutes).
23 changes: 23 additions & 0 deletions .claude/skills/proto-gen/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
name: proto-gen
description: Regenerate proto-lens Haskell code from .proto files using buf in the nix dev shell.
disable-model-invocation: true
argument-hint: [package-dir]
---

Regenerate proto-lens code from .proto files.

If no argument is given, default to `cardano-rpc`.

Package directory: $ARGUMENTS

## Procedure

1. Run: `nix develop --command bash -c "cd <package-dir> && buf generate proto"`
2. Verify the command succeeded.
3. Show a summary of which files were regenerated (check git status for changed files under `<package-dir>/gen/`).

## Important rules
- NEVER manually edit files under `gen/` — they are overwritten by this command.
- If buf or proto-lens-protoc are not found, it means you're not in the nix dev shell — always use `nix develop --command`.
- After regeneration, you may need to run `/build-fix` to ensure everything compiles.
30 changes: 30 additions & 0 deletions .claude/skills/rio-check/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
name: rio-check
description: Check if a Haskell function or type is re-exported by the RIO module.
disable-model-invocation: true
argument-hint: [symbol-name]
---

Check whether the symbol `$ARGUMENTS` is re-exported by RIO.

## Procedure

1. Find the RIO package source in the nix store by searching for the RIO module file:
```
find /nix/store -path '*/RIO.hs' -name 'RIO.hs' 2>/dev/null | head -5
```
Or search the project's dependency tree:
```
grep -r 'module RIO' $(nix build '.#cardano-rpc:lib:cardano-rpc' --print-out-paths 2>/dev/null)/lib/ 2>/dev/null
```
2. Search for the symbol in RIO's module exports and re-exports.
3. Report:
- Whether the symbol is available from RIO
- If NOT available, which module to import it from (e.g. `Data.List`, `Data.Map`, etc.)
- Whether RIO hides it (some symbols are explicitly hidden, like `toList`)

## Known RIO gaps (common gotchas)
- `sortBy` — NOT in RIO, import from `Data.List`
- `on` — NOT in RIO, import from `Data.Function`
- `toList` — RIO re-exports from GHC.Exts but some modules hide it; use `GHC.IsList` or import explicitly
- `sortOn`, `sort` — available in RIO
21 changes: 21 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Claude Code notes

## Rules
- Never manually edit generated code (e.g. proto-lens output in `gen/`). Use nix dev shell to run code generation tools (e.g. `nix develop --command bash -c "cd cardano-rpc && buf generate proto"`)
- Never modify the nix store

## cardano-rpc patterns
- `Proto msg` is a grapesy newtype wrapper. Internal functions should use plain proto-lens types, not `Proto`-wrapped. Use `getProto`/`fmap getProto` only at the RPC handler boundary.
- RIO hides many Prelude functions. `sortBy` is NOT re-exported by RIO -- import from `Data.List`. Check RIO re-exports before assuming standard functions are in scope.
- RIO's `^.` works with proto-lens van Laarhoven lenses. No need for `lens-family` dependency.
- Use `toList` (from `GHC.IsList`) instead of deprecated `valueToList` for `Value`.

## Mistakes and wrong assumptions (lessons learned)
- Assumed generated code could be patched by hand -- WRONG. Always use the project's code generation pipeline.
- Assumed proto-lens types would be used wrapped in `Proto` everywhere -- WRONG. `Proto` is only at the gRPC handler boundary. Internal logic uses raw proto-lens types.
- Assumed RIO re-exports all of `Data.List` -- WRONG. `sortBy`, `on`, and others need explicit imports.
- Assumed I needed `lens-family` for proto-lens field access -- WRONG. RIO's `^.` (from `microlens`) is compatible with proto-lens van Laarhoven lenses.
- Used deprecated `valueToList` instead of checking for the current API (`toList` via `GHC.IsList`).
- Left redundant `IsEra` constraint on `matchesTxOutputPattern` -- should check if constraints are actually needed before adding them.
- Wrote lambdas where infix notation was cleaner (`\sub -> f sub x` vs `` `f` x ``). hlint caught this.
- Minimize nix build round-trips: verify types, imports, and constraints carefully before building.
5 changes: 5 additions & 0 deletions cardano-rpc/cardano-rpc.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ library
Cardano.Rpc.Server.Internal.Monad
Cardano.Rpc.Server.Internal.Node
Cardano.Rpc.Server.Internal.Tracing
Cardano.Rpc.Server.Internal.UtxoRpc.Predicate
Cardano.Rpc.Server.Internal.UtxoRpc.Query
Cardano.Rpc.Server.Internal.UtxoRpc.Submit
Cardano.Rpc.Server.Internal.UtxoRpc.Type
Expand Down Expand Up @@ -119,15 +120,18 @@ test-suite cardano-rpc-test
type: exitcode-stdio-1.0
build-depends:
base,
bytestring,
cardano-api,
cardano-api:gen,
cardano-ledger-api,
cardano-ledger-conway,
cardano-ledger-core,
cardano-rpc,
cardano-rpc:gen,
containers,
hedgehog,
hedgehog-extras,
proto-lens,
rio,
tasty,
tasty-hedgehog,
Expand All @@ -139,6 +143,7 @@ test-suite cardano-rpc-test

build-tool-depends: tasty-discover:tasty-discover
other-modules:
Test.Cardano.Rpc.Predicate
Test.Cardano.Rpc.ProtocolParameters
Test.Cardano.Rpc.TxOutput
Test.Cardano.Rpc.Type
Loading
Loading