{"owner":"vyperlang","repo":"vyper","hasSkills":true,"totalSkillsCount":7,"totalTokensCount":5360,"categories":["anthropic-skill","claude-rule"],"hasMcp":false,"mcpConfig":null,"found":["skills/codegen.md","CLAUDE.md","skills/testing.md","skills/semantics.md","skills/contributing.md","skills/SKILL.md","skills/venom.md"],"skills":{"skills/codegen.md":"# Code Generation\n\n## Experimental Pipeline: Direct-to-Venom\n\nAST → `vyper/codegen_venom/` → Venom IR → optimization passes → assembly → bytecode.\n\n### `vyper/codegen_venom/`\n\nTranslates annotated Vyper AST directly to Venom SSA IR.\n\n- `module.py` — entry point, module-level codegen\n- `expr.py` — expression translation\n- `stmt.py` — statement translation\n- `arithmetic.py` — numeric operations\n- `builtins/` — built-in function codegen\n- `abi/` — ABI encoding/decoding\n- `context.py` — codegen context (variable tracking, etc.)\n\n### Venom → Assembly\n\nAfter Venom IR is constructed, `vyper/venom/` runs optimization passes then\n`venom/venom_to_assembly.py` emits EVM assembly. The assembler in `vyper/evm/assembler/`\nproduces final bytecode.\n\n## Default Production Pipeline: Legacy IR\n\nAST → `vyper/codegen/` → s-expression IR (`IRnode`) → `vyper/ir/compile_ir.py` → assembly → bytecode.\n\nThis is the current default. See [vyper/ir/README.md](../vyper/ir/README.md) for IR grammar and structure.\n\nKey difference: legacy IR is tree-shaped s-expressions, Venom is SSA basic blocks.\n","CLAUDE.md":"# Vyper Compiler — Agent Guide\n\nPythonic smart contract language targeting the EVM. v0.4.x, Python 3.11+.\n\n## Quick Commands\n\n```bash\nuv sync --extra dev              # install deps (per-worktree .venv, recommended)\nuv run vyper contract.vy                # compile a contract\nuv run vyper -f ir_runtime contract.vy  # inspect Venom IR\nuv run vyper -f asm contract.vy         # inspect assembly\nuv run ./quicktest.sh -m \"not fuzzing\"  # run tests (-nauto by default via setup.cfg)\nuv run make lint                        # enforces code style (same as CI)\n```\n\n## Architecture, Code Style, Entry Points\n\nSee [skills/SKILL.md](skills/SKILL.md) for compilation pipeline, directory map, code style, and key entry points.\n\n## Topic Deep-Dives\n\n- **[Venom IR](skills/venom.md)** — SSA IR design, passes, optimization, working with Venom code\n- **[Semantics & Frontend](skills/semantics.md)** — Type system, analysis phases, namespace, validation\n- **[Code Generation](skills/codegen.md)** — Legacy IR, Venom codegen, the two pipelines\n- **[Testing](skills/testing.md)** — Test structure, fixtures, running tests, writing new tests\n- **[Contributing](skills/contributing.md)** — Commit message standards, PR workflow, code style summary\n","skills/testing.md":"# Testing\n\n## Running Tests\n\n```bash\n./quicktest.sh -m \"not fuzzing\"          # standard test run (-nauto by default via setup.cfg)\n./quicktest.sh tests/unit/               # unit tests only\n./quicktest.sh tests/functional/         # functional tests only\n./quicktest.sh tests/unit/compiler/venom/ # venom unit tests\n./quicktest.sh --hevm -m hevm            # hevm-based tests (needs hevm in PATH)\n```\n\n`quicktest.sh` wraps pytest with `-q -s --instafail -x` (bail on first failure).\n\n## Test Organization\n\n```\ntests/\n├── unit/           # isolated component tests\n│   ├── ast/\n│   ├── semantics/\n│   ├── compiler/\n│   │   └── venom/  # venom pass & analysis tests\n│   ├── cli/\n│   └── ...\n├── functional/     # end-to-end compilation & execution\n│   ├── builtins/\n│   ├── codegen/\n│   ├── grammar/\n│   ├── syntax/\n│   └── venom/\n├── conftest.py     # shared fixtures\n├── evm_backends/   # EVM execution backends for tests\n└── venom_utils.py  # helpers for venom tests\n```\n\n## Key Fixtures & Helpers\n\n- `tests/conftest.py` — main fixtures (compiler invocation, EVM backends)\n- `tests/evm_backends/` — pluggable EVM execution (pyevm, pyrevm)\n- `tests/venom_utils.py` — helpers for constructing Venom IR in tests\n\n## Writing Tests\n\n- Functional tests typically compile a Vyper snippet and execute it against an EVM backend\n- Venom unit tests construct IR programmatically, run passes, and assert on the result\n- Use `pytest.mark.fuzzing` for slow/fuzz tests (skipped in quick runs)\n- Use `pytest.mark.hevm` for hevm-specific tests\n","skills/semantics.md":"# Semantics & Frontend\n\nType checking, validation, and semantic analysis of Vyper AST.\n\nPrimary reference: [vyper/semantics/README.md](../vyper/semantics/README.md) — full control flow, design, examples.\n\n## Pipeline\n\n```\nSource → pre_parser → Python AST → Vyper AST → semantic analysis → annotated AST\n```\n\n### AST Phase (`vyper/ast/`)\n\nSee [vyper/ast/README.md](../vyper/ast/README.md).\n\n- `pre_parser.py`: Vyper source → parseable Python (substitutes `struct`/`interface` → `class`, etc.)\n- `grammar.lark`: Lark grammar definition (for reference/making sure we adhere to a bnf spec)\n- `nodes.py`: Vyper AST node classes (use `__slots__`)\n- `parse.py` / `utils.py`: `parse_to_ast()` — main entry\n\n### Semantic Analysis Phase (`vyper/semantics/`)\n\nEntry: `vyper.semantics.analyze_module()`\n\nFour steps:\n1. **Pre-typecheck** (`analysis/pre_typecheck.py`): fold constant expressions\n2. **Namespace init** (`namespace.py`): populate builtins, types, env vars\n3. **Module validation** (`analysis/module.py`): storage vars, user types, imports, function sigs\n4. **Local validation** (`analysis/local.py`): per-function type checking and annotation\n\n## Type System (`vyper/semantics/types/`)\n\nType classes live in `vyper/semantics/types/`. Convention: classes end in `T` (e.g. `IntegerT`, `ModuleT`).\nBase classes in `bases.py`. Browse the directory for the full set — file names map to type categories\n(primitives, bytestrings, subscriptable, user-defined, function, module).\n\nType inference (aka type synthesis) is very limited and only for expressions: `(x: uint8) + 1` has type `uint8`, this is done by `_ExprAnalyser().get_possible_types_from_node`.\nType checking is done by `ExprVisitor`.\nThose are not fully decoupled however.\n\n## Namespace\n\n`Namespace` (`namespace.py`) is a dict subclass with scoping via context manager:\n\n```python\nwith namespace.enter_scope():\n    namespace[\"x\"] = some_type\n# x no longer exists here\n```\n\nScopes: builtin → module → local → (for/if blocks).\n\n## Analysis\n\nAnalysis and validation logic lives in `vyper/semantics/analysis/`. Key files:\n- `module.py` — module-level validation (storage, types, imports)\n- `local.py` — `FunctionNodeVisitor`, per-function validation\n- `annotation.py` — type annotation of expressions\n\nBrowse the directory for the full set. Also see `data_locations.py` and `environment.py` at the `semantics/` level.\n","skills/contributing.md":"# Contributing\n\nSee also: [README.md](../README.md) for installation instructions and command cheat-sheet,\n[docs/contributing.rst](../docs/contributing.rst) for general contribution guidelines,\n[docs/style-guide.rst](../docs/style-guide.rst) for code style, naming, imports, exceptions, tests, and docs conventions.\n\n## Commit Messages\n\nWe use squash merges for PRs. The squash commit message is the permanent record — it goes into\n`git log`, changelogs, and blame. The diff shows *what* changed; the PR shows *how* it evolved.\nThe commit message must explain **why**.\n\n### Format\n\n[Conventional Commits](https://www.conventionalcommits.org/). On squash-merge, the PR title becomes the commit subject line. The PR template's \"Commit message\" section becomes the body.\n\n**PR title** (becomes subject line):\n```\n<type>[scope]: <description>\n```\n\n**PR \"Commit message\" section** (becomes body):\n```\n<body>\n```\n\nTypes: `feat`, `fix`, `refactor`, `perf`, `chore`, `release`.\nScope is **required**. Validated by CI — see [pull-request.yaml](../.github/workflows/pull-request.yaml) for the canonical list.\nCurrent scopes: `venom`, `lang`, `codegen`, `parser`, `stdlib`, `ux`, `ir`, `test`, `docs`, `ci`, `build`, `tool`.\n\n### Subject Line (PR title)\n\n- Imperative, present tense (\"add X\" not \"added X\")\n- ~50 chars, lowercase, no period\n- Scope in brackets: `feat[venom]: add tail-merge pass`\n\n### Formatting\n\nWrap body at 72 chars. Use `fmt_commit_msg.py` to format — it defaults to `commitmsg.txt` and modifies in place.\n\n**Workflow for writing/updating the commit message in a PR:**\n\n```bash\n# 1. Write the commit message BODY to commitmsg.txt\n#    Do NOT include the subject line (type[scope]: description) —\n#    that comes from the PR title on squash-merge.\ncat > commitmsg.txt << 'EOF'\nmotivation paragraph here... (see \"Body\" section below)\n\nimplementation paragraph here...\nEOF\n\n# 2. Format it (wraps at 72 chars, preserves lists/code blocks)\npython fmt_commit_msg.py   # reads/overwrites commitmsg.txt, prints result to stdout\n\n# 3. Get the current PR body\ngh pr view <N> --json body -q .body > /tmp/pr_body.md\n\n# 4. Replace the ```-fenced block under \"### Commit message\" in /tmp/pr_body.md\n#    with the contents of commitmsg.txt (use Edit tool or sed)\n\n# 5. Upload\ngh pr edit <N> --body-file /tmp/pr_body.md\n```\n\nDo NOT write to `/tmp` or other locations and manually copy-paste — the script is designed to work on `commitmsg.txt` in the repo root. The file is gitignored.\n\n### Body — Explain Why and Context\n\nThe body is the most important part. It should answer:\n\n- **What problem does this solve?** What was broken, missing, or suboptimal?\n- **Why this approach?** What alternatives were considered? What tradeoffs were made?\n- **What are the non-obvious consequences?** Side effects, invariants established or broken, perf impact?\n\nDon't enumerate every file touched or mechanically list what each function does — that's the diff.\nDo explain the *reasoning* behind structural decisions, the bug mechanism, or the design rationale.\n\nCommit messages should not be tied to a particular issue tracker. Use `GH 1234` instead of `#1234` — the `#` syntax is GitHub-specific and creates links that are meaningless outside GitHub.\n\n### Good Example (from recent history)\n\nPR title: `fix[venom]: fix allocation in ternary fall through`\n\nCommit message body:\n```\n`Mem2Var._fix_adds` ensures `add` instructions on alloca pointers are\nrecognized by `BasePtrAnalysis` so it can track pointer provenance\nthrough arithmetic. When a ternary expression merges two\npointer paths via a `phi` node, the `add` sits downstream of the phi\nrather than as a direct use of the alloca — so `_fix_adds` never saw it.\n\nThe same gap existed in the caller guard: `_process_alloca_var`\nonly dispatched to `_fix_adds` when a direct `add` use was present,\nsilently skipping allocas whose only non-trivial uses were behind\nphi/assign nodes.\n\nAdditionally, following phi/assign chains introduces the possibility of\ncycles through loop back-edges, so add a visited set to terminate\ngracefully.\n```\n\nNote: explains the *mechanism* of the bug (why it happened), not just \"fixed a crash in X\".\n\n### Another Good Example\n\nPR title: `fix[venom]: treat immutables as global allocations`\n\nCommit message body:\n```\nthe immutables region (allocated at position 0 during deploy) was not\nreserved across function boundaries. when `ConcretizeMemLocPass` ran for\ninternal functions, it started with an empty reserved set, allowing\nfunction-local buffers to overlap position 0 and clobber immutable\nvalues.\n\nadd a `global_allocation` set to `MemoryAllocator` that persists across\nper-function allocation rounds. register the immutables alloca as global\nat IR conversion time.\n```\n\nNote: first paragraph is pure *why* (the bug mechanism). Second paragraph is a concise *what* — just enough to orient a reader, not a line-by-line walkthrough.\n\n### Anti-Patterns\n\n- ❌ \"Fix bug\" / \"Update code\" — says nothing\n- ❌ Listing every changed file or function — that's the diff\n- ❌ Only *what* with no *why* — \"add field X to class Y, call Z in function W\"\n- ❌ Copying the PR description verbatim (PR descriptions track evolution and review; commit messages are the final, distilled record)\n\n## Pull Requests\n\n- Fork from `master`\n- Write tests for new features; place them under `tests/`\n- Larger changes: discuss in Discord `#compiler-dev` first\n- PRs are squash-merged. See [Format](#format) for how the PR title and \"Commit message\" section map onto the final commit.\n- Work from your individual fork. PRs target `vyperlang/vyper` upstream:\n  ```bash\n  gh pr create --repo vyperlang/vyper --base master --head <fork-owner>:<branch>\n  ```\n- Follow the PR template (`.github/PULL_REQUEST_TEMPLATE.md`): What/How/Verify/Commit message/Changelog\n- To edit PR or issue bodies:\n  ```bash\n  gh pr view <N> --json body -q .body > /tmp/pr_body.md  # get current text\n  # edit /tmp/pr_body.md with Edit tool\n  gh pr edit <N> --body-file /tmp/pr_body.md              # upload\n  ```\n- **NEVER rebase and force-push a branch that is already under review.** Rebasing destroys review context (inline comments become orphaned, diff history is lost). If you need to pull in upstream changes on a PR branch, **merge `master` into your branch**.\n\n## Keeping Docs Current\n\nIf anything you have done requires content updates to any files in `skills/` or `CLAUDE.md`, update them as part of the same PR.\n\n## Git Quick Reference\n\n```bash\n# ALWAYS check what's pushed before amending.\n# Only amend commits not yet pushed\ngit log --oneline origin/<branch>..HEAD\n\n# undo a bad amend or commit (find the pre-amend state in reflog)\ngit reflog -10\ngit reset --mixed <good-sha>     # unstages changes, keeps working tree\ngit add <files> && git commit    # recommit cleanly\n\n# sync with upstream on a branch under review (NEVER rebase+force-push)\ngit merge master\n\n# interactive rebase doesn't work in non-interactive shells — use reset+cherry-pick instead\ngit stash                        # protect uncommitted work\ngit reset --hard <target>\ngit cherry-pick <commits>        # resolve conflicts manually\ngit stash pop\n```\n\n## Code Style Summary\n\nFull details in [docs/style-guide.rst](../docs/style-guide.rst). Highlights:\n\n- PEP 8, 100 char line length, enforced by `make lint`\n- Type classes end in `T` (`IntegerT`, `ModuleT`)\n- Method naming: `get_` (pure), `fetch_` (side effects), `build_` (creates new), classmethod `from_` (creates new from specific source), `check_` (pure, no raise, returns boolean), `validate_` (raises or returns None)\n- No builtin exceptions — use custom exception classes from `vyper/exceptions.py`\n- f-strings for string formatting\n- Import modules, not objects (avoids circular deps)\n- Cross-package imports must not reach beyond root namespace of target package\n- Tests: no mocking, no interdependence (xdist parallel), parametrize where logical\n","skills/SKILL.md":"---\nname: vyper-compiler\ndescription: Vyper smart contract compiler internals. Use when working on the Vyper compiler codebase — compilation pipeline, Venom IR, semantic analysis, code generation, testing, or contributing. Triggers on vyper compiler development, Venom passes, AST/semantics changes, codegen work, or test writing.\n---\n\n# Vyper Compiler\n\nPythonic smart contract language targeting the EVM. v0.4.x, Python 3.11+.\n\n## Quick Commands\n\n```bash\nuv sync                                 # install deps (per-worktree .venv, recommended, includes dev group)\nuv run vyper contract.vy                # compile a contract\nuv run vyper -f ir_runtime contract.vy  # inspect Venom IR\nuv run vyper -f asm contract.vy         # inspect assembly\nuv run ./quicktest.sh                   # run tests (`-nauto -m \"not fuzzing\"` by default via setup.cfg)\nuv run make lint                        # enforces code style (same as CI)\n```\n\nPrefix all commands with `uv run` — it activates the local `.venv` per invocation, which is necessary in non-interactive shells. Each worktree gets its own `.venv`, so no cross-contamination.\n\nAlternative: `pip install . --group dev` + `PYTHONPATH=.` prefix on every command. **Never `pip install -e .`** — it creates an egg-link in site-packages that permanently points the venv at one worktree, breaking all others.\n\n## Compilation Pipeline\n\n```\nSource (.vy)\n  │\n  ├─ vyper/ast/            → Parse to AST (pre_parser → Python AST → Vyper AST)\n  ├─ vyper/semantics/      → Type check, validate, annotate AST\n  ├─ vyper/codegen/        → AST → s-expr IR (default production pipeline)\n  ├─ vyper/ir/             → s-expr IR → assembly → bytecode\n  └─ vyper/evm/            → Assembly → bytecode\n```\n\nExperimental Venom path (`--experimental-codegen`):\n```\n  ├─ vyper/codegen_venom/  → AST → Venom SSA IR\n  └─ vyper/venom/          → Venom IR optimization passes → assembly\n```\n\nOrchestrated by `vyper/compiler/phases.py` (`CompilerData`). Each phase is lazy.\n\n## Directory Map\n\n| Directory | Purpose |\n|-----------|---------|\n| `vyper/ast/` | Parsing, AST nodes, pre-parser. See [AST README](../vyper/ast/README.md) |\n| `vyper/semantics/` | Type system, analysis, validation. See [Semantics README](../vyper/semantics/README.md) |\n| `vyper/codegen/` | AST → s-expr IR (default production pipeline) |\n| `vyper/ir/` | s-expr IR → assembly → bytecode. See [IR README](../vyper/ir/README.md) |\n| `vyper/codegen_venom/` | AST → Venom IR (experimental, `--experimental-codegen`) |\n| `vyper/venom/` | Venom SSA IR: passes, analysis, assembly emission. See [Venom README](../vyper/venom/README.md) |\n| `vyper/compiler/` | Pipeline orchestration, settings, output formats. See [Compiler README](../vyper/compiler/README.md) |\n| `vyper/builtins/` | Built-in functions and interfaces |\n| `vyper/evm/` | EVM opcodes, assembler |\n| `vyper/cli/` | CLI entry points (`vyper`, `vyper-ir`, `venom`) |\n| `tests/unit/` | Unit tests (ast, semantics, compiler, venom) |\n| `tests/functional/` | Functional tests (builtins, codegen, grammar, syntax, venom) |\n\n## Topic Deep-Dives\n\n- **[Venom IR](venom.md)** — SSA IR design, passes, optimization, working with Venom code\n- **[Semantics & Frontend](semantics.md)** — Type system, analysis phases, namespace, validation\n- **[Code Generation](codegen.md)** — Legacy IR, Venom codegen, the two pipelines\n- **[Testing](testing.md)** — Test structure, fixtures, running tests, writing new tests\n- **[Contributing](contributing.md)** — Commit message standards, PR workflow, code style summary\n\n## Code Style\n\nEnforced by `make lint` (also what CI runs). Includes `black`, `flake8`, `isort`, `mypy`.\n\n- Line length: 100\n- No inline imports; standard library → third-party → local\n- snake_case for variables (`tmp = ...`), DromedaryCase (aka upper camelCase) for classes (`ExprAnalyzer`), type classes end in `T` (e.g. `IntegerT`, `ModuleT`)\n\n## Key Entry Points\n\n| What | Where |\n|------|-------|\n| Main compile function | `vyper.compiler.compile_code()` |\n| Pipeline phases | `vyper.compiler.phases.CompilerData` |\n| AST parsing | `vyper.ast.parse.parse_to_ast()` |\n| Semantic analysis | `vyper.semantics.analyze_module()` |\n| Legacy codegen | `vyper.codegen.module` |\n| AST → Venom IR | `vyper.codegen_venom.module` |\n| Venom → assembly | `vyper.venom.generate_assembly_experimental()` |\n| CLI entry | `vyper.cli.vyper_compile` |\n","skills/venom.md":"# Venom IR\n\nSSA-based intermediate representation for Vyper. Inspired by LLVM IR, adapted for stack-based EVM.\n\nPrimary reference: [vyper/venom/README.md](../vyper/venom/README.md) — full instruction set, grammar, examples.\n\n## Structure\n\n```\nIRContext → IRFunction(s) → IRBasicBlock(s) → IRInstruction(s)\n```\n\n- Variables: `%`-prefixed, immutable after assignment (SSA)\n- Basic blocks: non-branching, terminated by `jmp`/`jnz`/`djmp`/`ret`/`return`/`stop`/`exit`\n- Normalized form: no block has both multiple predecessors AND multiple successors\n\n## Key Files\n\nCore data structures in `vyper/venom/`:\n- `context.py` — `IRContext`, top-level container\n- `function.py` — `IRFunction`\n- `basicblock.py` — `IRBasicBlock`, `IRInstruction`, `IROperand`\n- `builder.py` — helper for programmatic IR construction\n- `venom_to_assembly.py` — final pass: Venom → EVM assembly\n- `parser.py` — text format parser (for testing)\n\nPasses and analysis live in `venom/passes/` and `venom/analysis/` respectively.\n\n## Pass Architecture\n\nPasses inherit from base classes in `venom/passes/base_pass.py`. Three categories:\n- **Analysis** — `venom/analysis/` (CFG, DFG, liveness, dominators, etc.)\n- **Transformation** — normalization, SSA construction, phi elimination\n- **Optimization** — DCE, SCCP, CSE, load elimination, mem2var, inlining, etc.\n\nPass ordering matters — e.g. assembly emission requires normalization, which requires CFG.\n\nBrowse `venom/passes/` and `venom/analysis/` for the full set. File names are self-descriptive.\n\n## Inspecting Venom Output\n\n```bash\nvyper -f ir_runtime contract.vy        # Venom IR (runtime)\nvyper -f ir contract.vy                # Venom IR (deploy)\nvyper -f cfg_runtime contract.vy       # CFG as dot graph\nvyper -f asm contract.vy               # final assembly\n```\n\nEnable Venom: `--experimental-codegen` flag or `#pragma experimental-codegen` in source.\n\n## Entry Path\n\nAST → `vyper/codegen_venom/` → Venom IR (direct translation, no legacy IR involved).\nEntry point: `vyper/codegen_venom/module.py`.\n"},"files":{"skills/codegen.md":"# Code Generation\n\n## Experimental Pipeline: Direct-to-Venom\n\nAST → `vyper/codegen_venom/` → Venom IR → optimization passes → assembly → bytecode.\n\n### `vyper/codegen_venom/`\n\nTranslates annotated Vyper AST directly to Venom SSA IR.\n\n- `module.py` — entry point, module-level codegen\n- `expr.py` — expression translation\n- `stmt.py` — statement translation\n- `arithmetic.py` — numeric operations\n- `builtins/` — built-in function codegen\n- `abi/` — ABI encoding/decoding\n- `context.py` — codegen context (variable tracking, etc.)\n\n### Venom → Assembly\n\nAfter Venom IR is constructed, `vyper/venom/` runs optimization passes then\n`venom/venom_to_assembly.py` emits EVM assembly. The assembler in `vyper/evm/assembler/`\nproduces final bytecode.\n\n## Default Production Pipeline: Legacy IR\n\nAST → `vyper/codegen/` → s-expression IR (`IRnode`) → `vyper/ir/compile_ir.py` → assembly → bytecode.\n\nThis is the current default. See [vyper/ir/README.md](../vyper/ir/README.md) for IR grammar and structure.\n\nKey difference: legacy IR is tree-shaped s-expressions, Venom is SSA basic blocks.\n","CLAUDE.md":"# Vyper Compiler — Agent Guide\n\nPythonic smart contract language targeting the EVM. v0.4.x, Python 3.11+.\n\n## Quick Commands\n\n```bash\nuv sync --extra dev              # install deps (per-worktree .venv, recommended)\nuv run vyper contract.vy                # compile a contract\nuv run vyper -f ir_runtime contract.vy  # inspect Venom IR\nuv run vyper -f asm contract.vy         # inspect assembly\nuv run ./quicktest.sh -m \"not fuzzing\"  # run tests (-nauto by default via setup.cfg)\nuv run make lint                        # enforces code style (same as CI)\n```\n\n## Architecture, Code Style, Entry Points\n\nSee [skills/SKILL.md](skills/SKILL.md) for compilation pipeline, directory map, code style, and key entry points.\n\n## Topic Deep-Dives\n\n- **[Venom IR](skills/venom.md)** — SSA IR design, passes, optimization, working with Venom code\n- **[Semantics & Frontend](skills/semantics.md)** — Type system, analysis phases, namespace, validation\n- **[Code Generation](skills/codegen.md)** — Legacy IR, Venom codegen, the two pipelines\n- **[Testing](skills/testing.md)** — Test structure, fixtures, running tests, writing new tests\n- **[Contributing](skills/contributing.md)** — Commit message standards, PR workflow, code style summary\n","skills/testing.md":"# Testing\n\n## Running Tests\n\n```bash\n./quicktest.sh -m \"not fuzzing\"          # standard test run (-nauto by default via setup.cfg)\n./quicktest.sh tests/unit/               # unit tests only\n./quicktest.sh tests/functional/         # functional tests only\n./quicktest.sh tests/unit/compiler/venom/ # venom unit tests\n./quicktest.sh --hevm -m hevm            # hevm-based tests (needs hevm in PATH)\n```\n\n`quicktest.sh` wraps pytest with `-q -s --instafail -x` (bail on first failure).\n\n## Test Organization\n\n```\ntests/\n├── unit/           # isolated component tests\n│   ├── ast/\n│   ├── semantics/\n│   ├── compiler/\n│   │   └── venom/  # venom pass & analysis tests\n│   ├── cli/\n│   └── ...\n├── functional/     # end-to-end compilation & execution\n│   ├── builtins/\n│   ├── codegen/\n│   ├── grammar/\n│   ├── syntax/\n│   └── venom/\n├── conftest.py     # shared fixtures\n├── evm_backends/   # EVM execution backends for tests\n└── venom_utils.py  # helpers for venom tests\n```\n\n## Key Fixtures & Helpers\n\n- `tests/conftest.py` — main fixtures (compiler invocation, EVM backends)\n- `tests/evm_backends/` — pluggable EVM execution (pyevm, pyrevm)\n- `tests/venom_utils.py` — helpers for constructing Venom IR in tests\n\n## Writing Tests\n\n- Functional tests typically compile a Vyper snippet and execute it against an EVM backend\n- Venom unit tests construct IR programmatically, run passes, and assert on the result\n- Use `pytest.mark.fuzzing` for slow/fuzz tests (skipped in quick runs)\n- Use `pytest.mark.hevm` for hevm-specific tests\n","skills/semantics.md":"# Semantics & Frontend\n\nType checking, validation, and semantic analysis of Vyper AST.\n\nPrimary reference: [vyper/semantics/README.md](../vyper/semantics/README.md) — full control flow, design, examples.\n\n## Pipeline\n\n```\nSource → pre_parser → Python AST → Vyper AST → semantic analysis → annotated AST\n```\n\n### AST Phase (`vyper/ast/`)\n\nSee [vyper/ast/README.md](../vyper/ast/README.md).\n\n- `pre_parser.py`: Vyper source → parseable Python (substitutes `struct`/`interface` → `class`, etc.)\n- `grammar.lark`: Lark grammar definition (for reference/making sure we adhere to a bnf spec)\n- `nodes.py`: Vyper AST node classes (use `__slots__`)\n- `parse.py` / `utils.py`: `parse_to_ast()` — main entry\n\n### Semantic Analysis Phase (`vyper/semantics/`)\n\nEntry: `vyper.semantics.analyze_module()`\n\nFour steps:\n1. **Pre-typecheck** (`analysis/pre_typecheck.py`): fold constant expressions\n2. **Namespace init** (`namespace.py`): populate builtins, types, env vars\n3. **Module validation** (`analysis/module.py`): storage vars, user types, imports, function sigs\n4. **Local validation** (`analysis/local.py`): per-function type checking and annotation\n\n## Type System (`vyper/semantics/types/`)\n\nType classes live in `vyper/semantics/types/`. Convention: classes end in `T` (e.g. `IntegerT`, `ModuleT`).\nBase classes in `bases.py`. Browse the directory for the full set — file names map to type categories\n(primitives, bytestrings, subscriptable, user-defined, function, module).\n\nType inference (aka type synthesis) is very limited and only for expressions: `(x: uint8) + 1` has type `uint8`, this is done by `_ExprAnalyser().get_possible_types_from_node`.\nType checking is done by `ExprVisitor`.\nThose are not fully decoupled however.\n\n## Namespace\n\n`Namespace` (`namespace.py`) is a dict subclass with scoping via context manager:\n\n```python\nwith namespace.enter_scope():\n    namespace[\"x\"] = some_type\n# x no longer exists here\n```\n\nScopes: builtin → module → local → (for/if blocks).\n\n## Analysis\n\nAnalysis and validation logic lives in `vyper/semantics/analysis/`. Key files:\n- `module.py` — module-level validation (storage, types, imports)\n- `local.py` — `FunctionNodeVisitor`, per-function validation\n- `annotation.py` — type annotation of expressions\n\nBrowse the directory for the full set. Also see `data_locations.py` and `environment.py` at the `semantics/` level.\n","skills/contributing.md":"# Contributing\n\nSee also: [README.md](../README.md) for installation instructions and command cheat-sheet,\n[docs/contributing.rst](../docs/contributing.rst) for general contribution guidelines,\n[docs/style-guide.rst](../docs/style-guide.rst) for code style, naming, imports, exceptions, tests, and docs conventions.\n\n## Commit Messages\n\nWe use squash merges for PRs. The squash commit message is the permanent record — it goes into\n`git log`, changelogs, and blame. The diff shows *what* changed; the PR shows *how* it evolved.\nThe commit message must explain **why**.\n\n### Format\n\n[Conventional Commits](https://www.conventionalcommits.org/). On squash-merge, the PR title becomes the commit subject line. The PR template's \"Commit message\" section becomes the body.\n\n**PR title** (becomes subject line):\n```\n<type>[scope]: <description>\n```\n\n**PR \"Commit message\" section** (becomes body):\n```\n<body>\n```\n\nTypes: `feat`, `fix`, `refactor`, `perf`, `chore`, `release`.\nScope is **required**. Validated by CI — see [pull-request.yaml](../.github/workflows/pull-request.yaml) for the canonical list.\nCurrent scopes: `venom`, `lang`, `codegen`, `parser`, `stdlib`, `ux`, `ir`, `test`, `docs`, `ci`, `build`, `tool`.\n\n### Subject Line (PR title)\n\n- Imperative, present tense (\"add X\" not \"added X\")\n- ~50 chars, lowercase, no period\n- Scope in brackets: `feat[venom]: add tail-merge pass`\n\n### Formatting\n\nWrap body at 72 chars. Use `fmt_commit_msg.py` to format — it defaults to `commitmsg.txt` and modifies in place.\n\n**Workflow for writing/updating the commit message in a PR:**\n\n```bash\n# 1. Write the commit message BODY to commitmsg.txt\n#    Do NOT include the subject line (type[scope]: description) —\n#    that comes from the PR title on squash-merge.\ncat > commitmsg.txt << 'EOF'\nmotivation paragraph here... (see \"Body\" section below)\n\nimplementation paragraph here...\nEOF\n\n# 2. Format it (wraps at 72 chars, preserves lists/code blocks)\npython fmt_commit_msg.py   # reads/overwrites commitmsg.txt, prints result to stdout\n\n# 3. Get the current PR body\ngh pr view <N> --json body -q .body > /tmp/pr_body.md\n\n# 4. Replace the ```-fenced block under \"### Commit message\" in /tmp/pr_body.md\n#    with the contents of commitmsg.txt (use Edit tool or sed)\n\n# 5. Upload\ngh pr edit <N> --body-file /tmp/pr_body.md\n```\n\nDo NOT write to `/tmp` or other locations and manually copy-paste — the script is designed to work on `commitmsg.txt` in the repo root. The file is gitignored.\n\n### Body — Explain Why and Context\n\nThe body is the most important part. It should answer:\n\n- **What problem does this solve?** What was broken, missing, or suboptimal?\n- **Why this approach?** What alternatives were considered? What tradeoffs were made?\n- **What are the non-obvious consequences?** Side effects, invariants established or broken, perf impact?\n\nDon't enumerate every file touched or mechanically list what each function does — that's the diff.\nDo explain the *reasoning* behind structural decisions, the bug mechanism, or the design rationale.\n\nCommit messages should not be tied to a particular issue tracker. Use `GH 1234` instead of `#1234` — the `#` syntax is GitHub-specific and creates links that are meaningless outside GitHub.\n\n### Good Example (from recent history)\n\nPR title: `fix[venom]: fix allocation in ternary fall through`\n\nCommit message body:\n```\n`Mem2Var._fix_adds` ensures `add` instructions on alloca pointers are\nrecognized by `BasePtrAnalysis` so it can track pointer provenance\nthrough arithmetic. When a ternary expression merges two\npointer paths via a `phi` node, the `add` sits downstream of the phi\nrather than as a direct use of the alloca — so `_fix_adds` never saw it.\n\nThe same gap existed in the caller guard: `_process_alloca_var`\nonly dispatched to `_fix_adds` when a direct `add` use was present,\nsilently skipping allocas whose only non-trivial uses were behind\nphi/assign nodes.\n\nAdditionally, following phi/assign chains introduces the possibility of\ncycles through loop back-edges, so add a visited set to terminate\ngracefully.\n```\n\nNote: explains the *mechanism* of the bug (why it happened), not just \"fixed a crash in X\".\n\n### Another Good Example\n\nPR title: `fix[venom]: treat immutables as global allocations`\n\nCommit message body:\n```\nthe immutables region (allocated at position 0 during deploy) was not\nreserved across function boundaries. when `ConcretizeMemLocPass` ran for\ninternal functions, it started with an empty reserved set, allowing\nfunction-local buffers to overlap position 0 and clobber immutable\nvalues.\n\nadd a `global_allocation` set to `MemoryAllocator` that persists across\nper-function allocation rounds. register the immutables alloca as global\nat IR conversion time.\n```\n\nNote: first paragraph is pure *why* (the bug mechanism). Second paragraph is a concise *what* — just enough to orient a reader, not a line-by-line walkthrough.\n\n### Anti-Patterns\n\n- ❌ \"Fix bug\" / \"Update code\" — says nothing\n- ❌ Listing every changed file or function — that's the diff\n- ❌ Only *what* with no *why* — \"add field X to class Y, call Z in function W\"\n- ❌ Copying the PR description verbatim (PR descriptions track evolution and review; commit messages are the final, distilled record)\n\n## Pull Requests\n\n- Fork from `master`\n- Write tests for new features; place them under `tests/`\n- Larger changes: discuss in Discord `#compiler-dev` first\n- PRs are squash-merged. See [Format](#format) for how the PR title and \"Commit message\" section map onto the final commit.\n- Work from your individual fork. PRs target `vyperlang/vyper` upstream:\n  ```bash\n  gh pr create --repo vyperlang/vyper --base master --head <fork-owner>:<branch>\n  ```\n- Follow the PR template (`.github/PULL_REQUEST_TEMPLATE.md`): What/How/Verify/Commit message/Changelog\n- To edit PR or issue bodies:\n  ```bash\n  gh pr view <N> --json body -q .body > /tmp/pr_body.md  # get current text\n  # edit /tmp/pr_body.md with Edit tool\n  gh pr edit <N> --body-file /tmp/pr_body.md              # upload\n  ```\n- **NEVER rebase and force-push a branch that is already under review.** Rebasing destroys review context (inline comments become orphaned, diff history is lost). If you need to pull in upstream changes on a PR branch, **merge `master` into your branch**.\n\n## Keeping Docs Current\n\nIf anything you have done requires content updates to any files in `skills/` or `CLAUDE.md`, update them as part of the same PR.\n\n## Git Quick Reference\n\n```bash\n# ALWAYS check what's pushed before amending.\n# Only amend commits not yet pushed\ngit log --oneline origin/<branch>..HEAD\n\n# undo a bad amend or commit (find the pre-amend state in reflog)\ngit reflog -10\ngit reset --mixed <good-sha>     # unstages changes, keeps working tree\ngit add <files> && git commit    # recommit cleanly\n\n# sync with upstream on a branch under review (NEVER rebase+force-push)\ngit merge master\n\n# interactive rebase doesn't work in non-interactive shells — use reset+cherry-pick instead\ngit stash                        # protect uncommitted work\ngit reset --hard <target>\ngit cherry-pick <commits>        # resolve conflicts manually\ngit stash pop\n```\n\n## Code Style Summary\n\nFull details in [docs/style-guide.rst](../docs/style-guide.rst). Highlights:\n\n- PEP 8, 100 char line length, enforced by `make lint`\n- Type classes end in `T` (`IntegerT`, `ModuleT`)\n- Method naming: `get_` (pure), `fetch_` (side effects), `build_` (creates new), classmethod `from_` (creates new from specific source), `check_` (pure, no raise, returns boolean), `validate_` (raises or returns None)\n- No builtin exceptions — use custom exception classes from `vyper/exceptions.py`\n- f-strings for string formatting\n- Import modules, not objects (avoids circular deps)\n- Cross-package imports must not reach beyond root namespace of target package\n- Tests: no mocking, no interdependence (xdist parallel), parametrize where logical\n","skills/SKILL.md":"---\nname: vyper-compiler\ndescription: Vyper smart contract compiler internals. Use when working on the Vyper compiler codebase — compilation pipeline, Venom IR, semantic analysis, code generation, testing, or contributing. Triggers on vyper compiler development, Venom passes, AST/semantics changes, codegen work, or test writing.\n---\n\n# Vyper Compiler\n\nPythonic smart contract language targeting the EVM. v0.4.x, Python 3.11+.\n\n## Quick Commands\n\n```bash\nuv sync                                 # install deps (per-worktree .venv, recommended, includes dev group)\nuv run vyper contract.vy                # compile a contract\nuv run vyper -f ir_runtime contract.vy  # inspect Venom IR\nuv run vyper -f asm contract.vy         # inspect assembly\nuv run ./quicktest.sh                   # run tests (`-nauto -m \"not fuzzing\"` by default via setup.cfg)\nuv run make lint                        # enforces code style (same as CI)\n```\n\nPrefix all commands with `uv run` — it activates the local `.venv` per invocation, which is necessary in non-interactive shells. Each worktree gets its own `.venv`, so no cross-contamination.\n\nAlternative: `pip install . --group dev` + `PYTHONPATH=.` prefix on every command. **Never `pip install -e .`** — it creates an egg-link in site-packages that permanently points the venv at one worktree, breaking all others.\n\n## Compilation Pipeline\n\n```\nSource (.vy)\n  │\n  ├─ vyper/ast/            → Parse to AST (pre_parser → Python AST → Vyper AST)\n  ├─ vyper/semantics/      → Type check, validate, annotate AST\n  ├─ vyper/codegen/        → AST → s-expr IR (default production pipeline)\n  ├─ vyper/ir/             → s-expr IR → assembly → bytecode\n  └─ vyper/evm/            → Assembly → bytecode\n```\n\nExperimental Venom path (`--experimental-codegen`):\n```\n  ├─ vyper/codegen_venom/  → AST → Venom SSA IR\n  └─ vyper/venom/          → Venom IR optimization passes → assembly\n```\n\nOrchestrated by `vyper/compiler/phases.py` (`CompilerData`). Each phase is lazy.\n\n## Directory Map\n\n| Directory | Purpose |\n|-----------|---------|\n| `vyper/ast/` | Parsing, AST nodes, pre-parser. See [AST README](../vyper/ast/README.md) |\n| `vyper/semantics/` | Type system, analysis, validation. See [Semantics README](../vyper/semantics/README.md) |\n| `vyper/codegen/` | AST → s-expr IR (default production pipeline) |\n| `vyper/ir/` | s-expr IR → assembly → bytecode. See [IR README](../vyper/ir/README.md) |\n| `vyper/codegen_venom/` | AST → Venom IR (experimental, `--experimental-codegen`) |\n| `vyper/venom/` | Venom SSA IR: passes, analysis, assembly emission. See [Venom README](../vyper/venom/README.md) |\n| `vyper/compiler/` | Pipeline orchestration, settings, output formats. See [Compiler README](../vyper/compiler/README.md) |\n| `vyper/builtins/` | Built-in functions and interfaces |\n| `vyper/evm/` | EVM opcodes, assembler |\n| `vyper/cli/` | CLI entry points (`vyper`, `vyper-ir`, `venom`) |\n| `tests/unit/` | Unit tests (ast, semantics, compiler, venom) |\n| `tests/functional/` | Functional tests (builtins, codegen, grammar, syntax, venom) |\n\n## Topic Deep-Dives\n\n- **[Venom IR](venom.md)** — SSA IR design, passes, optimization, working with Venom code\n- **[Semantics & Frontend](semantics.md)** — Type system, analysis phases, namespace, validation\n- **[Code Generation](codegen.md)** — Legacy IR, Venom codegen, the two pipelines\n- **[Testing](testing.md)** — Test structure, fixtures, running tests, writing new tests\n- **[Contributing](contributing.md)** — Commit message standards, PR workflow, code style summary\n\n## Code Style\n\nEnforced by `make lint` (also what CI runs). Includes `black`, `flake8`, `isort`, `mypy`.\n\n- Line length: 100\n- No inline imports; standard library → third-party → local\n- snake_case for variables (`tmp = ...`), DromedaryCase (aka upper camelCase) for classes (`ExprAnalyzer`), type classes end in `T` (e.g. `IntegerT`, `ModuleT`)\n\n## Key Entry Points\n\n| What | Where |\n|------|-------|\n| Main compile function | `vyper.compiler.compile_code()` |\n| Pipeline phases | `vyper.compiler.phases.CompilerData` |\n| AST parsing | `vyper.ast.parse.parse_to_ast()` |\n| Semantic analysis | `vyper.semantics.analyze_module()` |\n| Legacy codegen | `vyper.codegen.module` |\n| AST → Venom IR | `vyper.codegen_venom.module` |\n| Venom → assembly | `vyper.venom.generate_assembly_experimental()` |\n| CLI entry | `vyper.cli.vyper_compile` |\n","skills/venom.md":"# Venom IR\n\nSSA-based intermediate representation for Vyper. Inspired by LLVM IR, adapted for stack-based EVM.\n\nPrimary reference: [vyper/venom/README.md](../vyper/venom/README.md) — full instruction set, grammar, examples.\n\n## Structure\n\n```\nIRContext → IRFunction(s) → IRBasicBlock(s) → IRInstruction(s)\n```\n\n- Variables: `%`-prefixed, immutable after assignment (SSA)\n- Basic blocks: non-branching, terminated by `jmp`/`jnz`/`djmp`/`ret`/`return`/`stop`/`exit`\n- Normalized form: no block has both multiple predecessors AND multiple successors\n\n## Key Files\n\nCore data structures in `vyper/venom/`:\n- `context.py` — `IRContext`, top-level container\n- `function.py` — `IRFunction`\n- `basicblock.py` — `IRBasicBlock`, `IRInstruction`, `IROperand`\n- `builder.py` — helper for programmatic IR construction\n- `venom_to_assembly.py` — final pass: Venom → EVM assembly\n- `parser.py` — text format parser (for testing)\n\nPasses and analysis live in `venom/passes/` and `venom/analysis/` respectively.\n\n## Pass Architecture\n\nPasses inherit from base classes in `venom/passes/base_pass.py`. Three categories:\n- **Analysis** — `venom/analysis/` (CFG, DFG, liveness, dominators, etc.)\n- **Transformation** — normalization, SSA construction, phi elimination\n- **Optimization** — DCE, SCCP, CSE, load elimination, mem2var, inlining, etc.\n\nPass ordering matters — e.g. assembly emission requires normalization, which requires CFG.\n\nBrowse `venom/passes/` and `venom/analysis/` for the full set. File names are self-descriptive.\n\n## Inspecting Venom Output\n\n```bash\nvyper -f ir_runtime contract.vy        # Venom IR (runtime)\nvyper -f ir contract.vy                # Venom IR (deploy)\nvyper -f cfg_runtime contract.vy       # CFG as dot graph\nvyper -f asm contract.vy               # final assembly\n```\n\nEnable Venom: `--experimental-codegen` flag or `#pragma experimental-codegen` in source.\n\n## Entry Path\n\nAST → `vyper/codegen_venom/` → Venom IR (direct translation, no legacy IR involved).\nEntry point: `vyper/codegen_venom/module.py`.\n"},"items":[{"name":"codegen.md","path":"skills/codegen.md","rawUrl":"https://raw.githubusercontent.com/vyperlang/vyper/HEAD/skills/codegen.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"# Code Generation\n\n## Experimental Pipeline: Direct-to-Venom\n\nAST → `vyper/codegen_venom/` → Venom IR → optimization passes → assembly → bytecode.\n\n### `vyper/codegen_venom/`\n\nTranslates annotated Vyper AST directly to Venom SSA IR.\n\n- `module.py` — entry point, module-level codegen\n- `expr.py` — expression translation\n- `stmt.py` — statement translation\n- `arithmetic.py` — numeric operations\n- `builtins/` — built-in function codegen\n- `abi/` — ABI encoding/decoding\n- `context.py` — codegen context (variable tracking, etc.)\n\n### Venom → Assembly\n\nAfter Venom IR is constructed, `vyper/venom/` runs optimization passes then\n`venom/venom_to_assembly.py` emits EVM assembly. The assembler in `vyper/evm/assembler/`\nproduces final bytecode.\n\n## Default Production Pipeline: Legacy IR\n\nAST → `vyper/codegen/` → s-expression IR (`IRnode`) → `vyper/ir/compile_ir.py` → assembly → bytecode.\n\nThis is the current default. See [vyper/ir/README.md](../vyper/ir/README.md) for IR grammar and structure.\n\nKey difference: legacy IR is tree-shaped s-expressions, Venom is SSA basic blocks.\n","isInternal":false,"tokens":290,"sizeBytes":1117},{"name":"contributing.md","path":"skills/contributing.md","rawUrl":"https://raw.githubusercontent.com/vyperlang/vyper/HEAD/skills/contributing.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"# Contributing\n\nSee also: [README.md](../README.md) for installation instructions and command cheat-sheet,\n[docs/contributing.rst](../docs/contributing.rst) for general contribution guidelines,\n[docs/style-guide.rst](../docs/style-guide.rst) for code style, naming, imports, exceptions, tests, and docs conventions.\n\n## Commit Messages\n\nWe use squash merges for PRs. The squash commit message is the permanent record — it goes into\n`git log`, changelogs, and blame. The diff shows *what* changed; the PR shows *how* it evolved.\nThe commit message must explain **why**.\n\n### Format\n\n[Conventional Commits](https://www.conventionalcommits.org/). On squash-merge, the PR title becomes the commit subject line. The PR template's \"Commit message\" section becomes the body.\n\n**PR title** (becomes subject line):\n```\n<type>[scope]: <description>\n```\n\n**PR \"Commit message\" section** (becomes body):\n```\n<body>\n```\n\nTypes: `feat`, `fix`, `refactor`, `perf`, `chore`, `release`.\nScope is **required**. Validated by CI — see [pull-request.yaml](../.github/workflows/pull-request.yaml) for the canonical list.\nCurrent scopes: `venom`, `lang`, `codegen`, `parser`, `stdlib`, `ux`, `ir`, `test`, `docs`, `ci`, `build`, `tool`.\n\n### Subject Line (PR title)\n\n- Imperative, present tense (\"add X\" not \"added X\")\n- ~50 chars, lowercase, no period\n- Scope in brackets: `feat[venom]: add tail-merge pass`\n\n### Formatting\n\nWrap body at 72 chars. Use `fmt_commit_msg.py` to format — it defaults to `commitmsg.txt` and modifies in place.\n\n**Workflow for writing/updating the commit message in a PR:**\n\n```bash\n# 1. Write the commit message BODY to commitmsg.txt\n#    Do NOT include the subject line (type[scope]: description) —\n#    that comes from the PR title on squash-merge.\ncat > commitmsg.txt << 'EOF'\nmotivation paragraph here... (see \"Body\" section below)\n\nimplementation paragraph here...\nEOF\n\n# 2. Format it (wraps at 72 chars, preserves lists/code blocks)\npython fmt_commit_msg.py   # reads/overwrites commitmsg.txt, prints result to stdout\n\n# 3. Get the current PR body\ngh pr view <N> --json body -q .body > /tmp/pr_body.md\n\n# 4. Replace the ```-fenced block under \"### Commit message\" in /tmp/pr_body.md\n#    with the contents of commitmsg.txt (use Edit tool or sed)\n\n# 5. Upload\ngh pr edit <N> --body-file /tmp/pr_body.md\n```\n\nDo NOT write to `/tmp` or other locations and manually copy-paste — the script is designed to work on `commitmsg.txt` in the repo root. The file is gitignored.\n\n### Body — Explain Why and Context\n\nThe body is the most important part. It should answer:\n\n- **What problem does this solve?** What was broken, missing, or suboptimal?\n- **Why this approach?** What alternatives were considered? What tradeoffs were made?\n- **What are the non-obvious consequences?** Side effects, invariants established or broken, perf impact?\n\nDon't enumerate every file touched or mechanically list what each function does — that's the diff.\nDo explain the *reasoning* behind structural decisions, the bug mechanism, or the design rationale.\n\nCommit messages should not be tied to a particular issue tracker. Use `GH 1234` instead of `#1234` — the `#` syntax is GitHub-specific and creates links that are meaningless outside GitHub.\n\n### Good Example (from recent history)\n\nPR title: `fix[venom]: fix allocation in ternary fall through`\n\nCommit message body:\n```\n`Mem2Var._fix_adds` ensures `add` instructions on alloca pointers are\nrecognized by `BasePtrAnalysis` so it can track pointer provenance\nthrough arithmetic. When a ternary expression merges two\npointer paths via a `phi` node, the `add` sits downstream of the phi\nrather than as a direct use of the alloca — so `_fix_adds` never saw it.\n\nThe same gap existed in the caller guard: `_process_alloca_var`\nonly dispatched to `_fix_adds` when a direct `add` use was present,\nsilently skipping allocas whose only non-trivial uses were behind\nphi/assign nodes.\n\nAdditionally, following phi/assign chains introduces the possibility of\ncycles through loop back-edges, so add a visited set to terminate\ngracefully.\n```\n\nNote: explains the *mechanism* of the bug (why it happened), not just \"fixed a crash in X\".\n\n### Another Good Example\n\nPR title: `fix[venom]: treat immutables as global allocations`\n\nCommit message body:\n```\nthe immutables region (allocated at position 0 during deploy) was not\nreserved across function boundaries. when `ConcretizeMemLocPass` ran for\ninternal functions, it started with an empty reserved set, allowing\nfunction-local buffers to overlap position 0 and clobber immutable\nvalues.\n\nadd a `global_allocation` set to `MemoryAllocator` that persists across\nper-function allocation rounds. register the immutables alloca as global\nat IR conversion time.\n```\n\nNote: first paragraph is pure *why* (the bug mechanism). Second paragraph is a concise *what* — just enough to orient a reader, not a line-by-line walkthrough.\n\n### Anti-Patterns\n\n- ❌ \"Fix bug\" / \"Update code\" — says nothing\n- ❌ Listing every changed file or function — that's the diff\n- ❌ Only *what* with no *why* — \"add field X to class Y, call Z in function W\"\n- ❌ Copying the PR description verbatim (PR descriptions track evolution and review; commit messages are the final, distilled record)\n\n## Pull Requests\n\n- Fork from `master`\n- Write tests for new features; place them under `tests/`\n- Larger changes: discuss in Discord `#compiler-dev` first\n- PRs are squash-merged. See [Format](#format) for how the PR title and \"Commit message\" section map onto the final commit.\n- Work from your individual fork. PRs target `vyperlang/vyper` upstream:\n  ```bash\n  gh pr create --repo vyperlang/vyper --base master --head <fork-owner>:<branch>\n  ```\n- Follow the PR template (`.github/PULL_REQUEST_TEMPLATE.md`): What/How/Verify/Commit message/Changelog\n- To edit PR or issue bodies:\n  ```bash\n  gh pr view <N> --json body -q .body > /tmp/pr_body.md  # get current text\n  # edit /tmp/pr_body.md with Edit tool\n  gh pr edit <N> --body-file /tmp/pr_body.md              # upload\n  ```\n- **NEVER rebase and force-push a branch that is already under review.** Rebasing destroys review context (inline comments become orphaned, diff history is lost). If you need to pull in upstream changes on a PR branch, **merge `master` into your branch**.\n\n## Keeping Docs Current\n\nIf anything you have done requires content updates to any files in `skills/` or `CLAUDE.md`, update them as part of the same PR.\n\n## Git Quick Reference\n\n```bash\n# ALWAYS check what's pushed before amending.\n# Only amend commits not yet pushed\ngit log --oneline origin/<branch>..HEAD\n\n# undo a bad amend or commit (find the pre-amend state in reflog)\ngit reflog -10\ngit reset --mixed <good-sha>     # unstages changes, keeps working tree\ngit add <files> && git commit    # recommit cleanly\n\n# sync with upstream on a branch under review (NEVER rebase+force-push)\ngit merge master\n\n# interactive rebase doesn't work in non-interactive shells — use reset+cherry-pick instead\ngit stash                        # protect uncommitted work\ngit reset --hard <target>\ngit cherry-pick <commits>        # resolve conflicts manually\ngit stash pop\n```\n\n## Code Style Summary\n\nFull details in [docs/style-guide.rst](../docs/style-guide.rst). Highlights:\n\n- PEP 8, 100 char line length, enforced by `make lint`\n- Type classes end in `T` (`IntegerT`, `ModuleT`)\n- Method naming: `get_` (pure), `fetch_` (side effects), `build_` (creates new), classmethod `from_` (creates new from specific source), `check_` (pure, no raise, returns boolean), `validate_` (raises or returns None)\n- No builtin exceptions — use custom exception classes from `vyper/exceptions.py`\n- f-strings for string formatting\n- Import modules, not objects (avoids circular deps)\n- Cross-package imports must not reach beyond root namespace of target package\n- Tests: no mocking, no interdependence (xdist parallel), parametrize where logical\n","isInternal":false,"tokens":1985,"sizeBytes":7938},{"name":"semantics.md","path":"skills/semantics.md","rawUrl":"https://raw.githubusercontent.com/vyperlang/vyper/HEAD/skills/semantics.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"# Semantics & Frontend\n\nType checking, validation, and semantic analysis of Vyper AST.\n\nPrimary reference: [vyper/semantics/README.md](../vyper/semantics/README.md) — full control flow, design, examples.\n\n## Pipeline\n\n```\nSource → pre_parser → Python AST → Vyper AST → semantic analysis → annotated AST\n```\n\n### AST Phase (`vyper/ast/`)\n\nSee [vyper/ast/README.md](../vyper/ast/README.md).\n\n- `pre_parser.py`: Vyper source → parseable Python (substitutes `struct`/`interface` → `class`, etc.)\n- `grammar.lark`: Lark grammar definition (for reference/making sure we adhere to a bnf spec)\n- `nodes.py`: Vyper AST node classes (use `__slots__`)\n- `parse.py` / `utils.py`: `parse_to_ast()` — main entry\n\n### Semantic Analysis Phase (`vyper/semantics/`)\n\nEntry: `vyper.semantics.analyze_module()`\n\nFour steps:\n1. **Pre-typecheck** (`analysis/pre_typecheck.py`): fold constant expressions\n2. **Namespace init** (`namespace.py`): populate builtins, types, env vars\n3. **Module validation** (`analysis/module.py`): storage vars, user types, imports, function sigs\n4. **Local validation** (`analysis/local.py`): per-function type checking and annotation\n\n## Type System (`vyper/semantics/types/`)\n\nType classes live in `vyper/semantics/types/`. Convention: classes end in `T` (e.g. `IntegerT`, `ModuleT`).\nBase classes in `bases.py`. Browse the directory for the full set — file names map to type categories\n(primitives, bytestrings, subscriptable, user-defined, function, module).\n\nType inference (aka type synthesis) is very limited and only for expressions: `(x: uint8) + 1` has type `uint8`, this is done by `_ExprAnalyser().get_possible_types_from_node`.\nType checking is done by `ExprVisitor`.\nThose are not fully decoupled however.\n\n## Namespace\n\n`Namespace` (`namespace.py`) is a dict subclass with scoping via context manager:\n\n```python\nwith namespace.enter_scope():\n    namespace[\"x\"] = some_type\n# x no longer exists here\n```\n\nScopes: builtin → module → local → (for/if blocks).\n\n## Analysis\n\nAnalysis and validation logic lives in `vyper/semantics/analysis/`. Key files:\n- `module.py` — module-level validation (storage, types, imports)\n- `local.py` — `FunctionNodeVisitor`, per-function validation\n- `annotation.py` — type annotation of expressions\n\nBrowse the directory for the full set. Also see `data_locations.py` and `environment.py` at the `semantics/` level.\n","isInternal":false,"tokens":612,"sizeBytes":2402},{"name":"SKILL.md","path":"skills/SKILL.md","rawUrl":"https://raw.githubusercontent.com/vyperlang/vyper/HEAD/skills/SKILL.md","title":"vyper-compiler","category":"anthropic-skill","format":"markdown","content":"---\nname: vyper-compiler\ndescription: Vyper smart contract compiler internals. Use when working on the Vyper compiler codebase — compilation pipeline, Venom IR, semantic analysis, code generation, testing, or contributing. Triggers on vyper compiler development, Venom passes, AST/semantics changes, codegen work, or test writing.\n---\n\n# Vyper Compiler\n\nPythonic smart contract language targeting the EVM. v0.4.x, Python 3.11+.\n\n## Quick Commands\n\n```bash\nuv sync                                 # install deps (per-worktree .venv, recommended, includes dev group)\nuv run vyper contract.vy                # compile a contract\nuv run vyper -f ir_runtime contract.vy  # inspect Venom IR\nuv run vyper -f asm contract.vy         # inspect assembly\nuv run ./quicktest.sh                   # run tests (`-nauto -m \"not fuzzing\"` by default via setup.cfg)\nuv run make lint                        # enforces code style (same as CI)\n```\n\nPrefix all commands with `uv run` — it activates the local `.venv` per invocation, which is necessary in non-interactive shells. Each worktree gets its own `.venv`, so no cross-contamination.\n\nAlternative: `pip install . --group dev` + `PYTHONPATH=.` prefix on every command. **Never `pip install -e .`** — it creates an egg-link in site-packages that permanently points the venv at one worktree, breaking all others.\n\n## Compilation Pipeline\n\n```\nSource (.vy)\n  │\n  ├─ vyper/ast/            → Parse to AST (pre_parser → Python AST → Vyper AST)\n  ├─ vyper/semantics/      → Type check, validate, annotate AST\n  ├─ vyper/codegen/        → AST → s-expr IR (default production pipeline)\n  ├─ vyper/ir/             → s-expr IR → assembly → bytecode\n  └─ vyper/evm/            → Assembly → bytecode\n```\n\nExperimental Venom path (`--experimental-codegen`):\n```\n  ├─ vyper/codegen_venom/  → AST → Venom SSA IR\n  └─ vyper/venom/          → Venom IR optimization passes → assembly\n```\n\nOrchestrated by `vyper/compiler/phases.py` (`CompilerData`). Each phase is lazy.\n\n## Directory Map\n\n| Directory | Purpose |\n|-----------|---------|\n| `vyper/ast/` | Parsing, AST nodes, pre-parser. See [AST README](../vyper/ast/README.md) |\n| `vyper/semantics/` | Type system, analysis, validation. See [Semantics README](../vyper/semantics/README.md) |\n| `vyper/codegen/` | AST → s-expr IR (default production pipeline) |\n| `vyper/ir/` | s-expr IR → assembly → bytecode. See [IR README](../vyper/ir/README.md) |\n| `vyper/codegen_venom/` | AST → Venom IR (experimental, `--experimental-codegen`) |\n| `vyper/venom/` | Venom SSA IR: passes, analysis, assembly emission. See [Venom README](../vyper/venom/README.md) |\n| `vyper/compiler/` | Pipeline orchestration, settings, output formats. See [Compiler README](../vyper/compiler/README.md) |\n| `vyper/builtins/` | Built-in functions and interfaces |\n| `vyper/evm/` | EVM opcodes, assembler |\n| `vyper/cli/` | CLI entry points (`vyper`, `vyper-ir`, `venom`) |\n| `tests/unit/` | Unit tests (ast, semantics, compiler, venom) |\n| `tests/functional/` | Functional tests (builtins, codegen, grammar, syntax, venom) |\n\n## Topic Deep-Dives\n\n- **[Venom IR](venom.md)** — SSA IR design, passes, optimization, working with Venom code\n- **[Semantics & Frontend](semantics.md)** — Type system, analysis phases, namespace, validation\n- **[Code Generation](codegen.md)** — Legacy IR, Venom codegen, the two pipelines\n- **[Testing](testing.md)** — Test structure, fixtures, running tests, writing new tests\n- **[Contributing](contributing.md)** — Commit message standards, PR workflow, code style summary\n\n## Code Style\n\nEnforced by `make lint` (also what CI runs). Includes `black`, `flake8`, `isort`, `mypy`.\n\n- Line length: 100\n- No inline imports; standard library → third-party → local\n- snake_case for variables (`tmp = ...`), DromedaryCase (aka upper camelCase) for classes (`ExprAnalyzer`), type classes end in `T` (e.g. `IntegerT`, `ModuleT`)\n\n## Key Entry Points\n\n| What | Where |\n|------|-------|\n| Main compile function | `vyper.compiler.compile_code()` |\n| Pipeline phases | `vyper.compiler.phases.CompilerData` |\n| AST parsing | `vyper.ast.parse.parse_to_ast()` |\n| Semantic analysis | `vyper.semantics.analyze_module()` |\n| Legacy codegen | `vyper.codegen.module` |\n| AST → Venom IR | `vyper.codegen_venom.module` |\n| Venom → assembly | `vyper.venom.generate_assembly_experimental()` |\n| CLI entry | `vyper.cli.vyper_compile` |\n","frontmatter":{"name":"vyper-compiler","description":"Vyper smart contract compiler internals. Use when working on the Vyper compiler codebase — compilation pipeline, Venom IR, semantic analysis, code generation, testing, or contributing. Triggers on vyper compiler development, Venom passes, AST/semantics changes, codegen work, or test writing."},"isInternal":false,"tokens":1186,"sizeBytes":4472},{"name":"testing.md","path":"skills/testing.md","rawUrl":"https://raw.githubusercontent.com/vyperlang/vyper/HEAD/skills/testing.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"# Testing\n\n## Running Tests\n\n```bash\n./quicktest.sh -m \"not fuzzing\"          # standard test run (-nauto by default via setup.cfg)\n./quicktest.sh tests/unit/               # unit tests only\n./quicktest.sh tests/functional/         # functional tests only\n./quicktest.sh tests/unit/compiler/venom/ # venom unit tests\n./quicktest.sh --hevm -m hevm            # hevm-based tests (needs hevm in PATH)\n```\n\n`quicktest.sh` wraps pytest with `-q -s --instafail -x` (bail on first failure).\n\n## Test Organization\n\n```\ntests/\n├── unit/           # isolated component tests\n│   ├── ast/\n│   ├── semantics/\n│   ├── compiler/\n│   │   └── venom/  # venom pass & analysis tests\n│   ├── cli/\n│   └── ...\n├── functional/     # end-to-end compilation & execution\n│   ├── builtins/\n│   ├── codegen/\n│   ├── grammar/\n│   ├── syntax/\n│   └── venom/\n├── conftest.py     # shared fixtures\n├── evm_backends/   # EVM execution backends for tests\n└── venom_utils.py  # helpers for venom tests\n```\n\n## Key Fixtures & Helpers\n\n- `tests/conftest.py` — main fixtures (compiler invocation, EVM backends)\n- `tests/evm_backends/` — pluggable EVM execution (pyevm, pyrevm)\n- `tests/venom_utils.py` — helpers for constructing Venom IR in tests\n\n## Writing Tests\n\n- Functional tests typically compile a Vyper snippet and execute it against an EVM backend\n- Venom unit tests construct IR programmatically, run passes, and assert on the result\n- Use `pytest.mark.fuzzing` for slow/fuzz tests (skipped in quick runs)\n- Use `pytest.mark.hevm` for hevm-specific tests\n","isInternal":false,"tokens":426,"sizeBytes":1655},{"name":"venom.md","path":"skills/venom.md","rawUrl":"https://raw.githubusercontent.com/vyperlang/vyper/HEAD/skills/venom.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"# Venom IR\n\nSSA-based intermediate representation for Vyper. Inspired by LLVM IR, adapted for stack-based EVM.\n\nPrimary reference: [vyper/venom/README.md](../vyper/venom/README.md) — full instruction set, grammar, examples.\n\n## Structure\n\n```\nIRContext → IRFunction(s) → IRBasicBlock(s) → IRInstruction(s)\n```\n\n- Variables: `%`-prefixed, immutable after assignment (SSA)\n- Basic blocks: non-branching, terminated by `jmp`/`jnz`/`djmp`/`ret`/`return`/`stop`/`exit`\n- Normalized form: no block has both multiple predecessors AND multiple successors\n\n## Key Files\n\nCore data structures in `vyper/venom/`:\n- `context.py` — `IRContext`, top-level container\n- `function.py` — `IRFunction`\n- `basicblock.py` — `IRBasicBlock`, `IRInstruction`, `IROperand`\n- `builder.py` — helper for programmatic IR construction\n- `venom_to_assembly.py` — final pass: Venom → EVM assembly\n- `parser.py` — text format parser (for testing)\n\nPasses and analysis live in `venom/passes/` and `venom/analysis/` respectively.\n\n## Pass Architecture\n\nPasses inherit from base classes in `venom/passes/base_pass.py`. Three categories:\n- **Analysis** — `venom/analysis/` (CFG, DFG, liveness, dominators, etc.)\n- **Transformation** — normalization, SSA construction, phi elimination\n- **Optimization** — DCE, SCCP, CSE, load elimination, mem2var, inlining, etc.\n\nPass ordering matters — e.g. assembly emission requires normalization, which requires CFG.\n\nBrowse `venom/passes/` and `venom/analysis/` for the full set. File names are self-descriptive.\n\n## Inspecting Venom Output\n\n```bash\nvyper -f ir_runtime contract.vy        # Venom IR (runtime)\nvyper -f ir contract.vy                # Venom IR (deploy)\nvyper -f cfg_runtime contract.vy       # CFG as dot graph\nvyper -f asm contract.vy               # final assembly\n```\n\nEnable Venom: `--experimental-codegen` flag or `#pragma experimental-codegen` in source.\n\n## Entry Path\n\nAST → `vyper/codegen_venom/` → Venom IR (direct translation, no legacy IR involved).\nEntry point: `vyper/codegen_venom/module.py`.\n","isInternal":false,"tokens":550,"sizeBytes":2060},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/vyperlang/vyper/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# Vyper Compiler — Agent Guide\n\nPythonic smart contract language targeting the EVM. v0.4.x, Python 3.11+.\n\n## Quick Commands\n\n```bash\nuv sync --extra dev              # install deps (per-worktree .venv, recommended)\nuv run vyper contract.vy                # compile a contract\nuv run vyper -f ir_runtime contract.vy  # inspect Venom IR\nuv run vyper -f asm contract.vy         # inspect assembly\nuv run ./quicktest.sh -m \"not fuzzing\"  # run tests (-nauto by default via setup.cfg)\nuv run make lint                        # enforces code style (same as CI)\n```\n\n## Architecture, Code Style, Entry Points\n\nSee [skills/SKILL.md](skills/SKILL.md) for compilation pipeline, directory map, code style, and key entry points.\n\n## Topic Deep-Dives\n\n- **[Venom IR](skills/venom.md)** — SSA IR design, passes, optimization, working with Venom code\n- **[Semantics & Frontend](skills/semantics.md)** — Type system, analysis phases, namespace, validation\n- **[Code Generation](skills/codegen.md)** — Legacy IR, Venom codegen, the two pipelines\n- **[Testing](skills/testing.md)** — Test structure, fixtures, running tests, writing new tests\n- **[Contributing](skills/contributing.md)** — Commit message standards, PR workflow, code style summary\n","isInternal":false,"tokens":311,"sizeBytes":1243}],"systemPromptSnippet":"<yakaai_skills repo=\"vyperlang/vyper\">\n<!-- File: skills/codegen.md (Tokens: ~290 | Category: anthropic-skill) -->\n# Code Generation\n\n## Experimental Pipeline: Direct-to-Venom\n\nAST → `vyper/codegen_venom/` → Venom IR → optimization passes → assembly → bytecode.\n\n### `vyper/codegen_venom/`\n\nTranslates annotated Vyper AST directly to Venom SSA IR.\n\n- `module.py` — entry point, module-level codegen\n- `expr.py` — expression translation\n- `stmt.py` — statement translation\n- `arithmetic.py` — numeric operations\n- `builtins/` — built-in function codegen\n- `abi/` — ABI encoding/decoding\n- `context.py` — codegen context (variable tracking, etc.)\n\n### Venom → Assembly\n\nAfter Venom IR is constructed, `vyper/venom/` runs optimization passes then\n`venom/venom_to_assembly.py` emits EVM assembly. The assembler in `vyper/evm/assembler/`\nproduces final bytecode.\n\n## Default Production Pipeline: Legacy IR\n\nAST → `vyper/codegen/` → s-expression IR (`IRnode`) → `vyper/ir/compile_ir.py` → assembly → bytecode.\n\nThis is the current default. See [vyper/ir/README.md](../vyper/ir/README.md) for IR grammar and structure.\n\nKey difference: legacy IR is tree-shaped s-expressions, Venom is SSA basic blocks.\n\n<!-- File: skills/contributing.md (Tokens: ~1985 | Category: anthropic-skill) -->\n# Contributing\n\nSee also: [README.md](../README.md) for installation instructions and command cheat-sheet,\n[docs/contributing.rst](../docs/contributing.rst) for general contribution guidelines,\n[docs/style-guide.rst](../docs/style-guide.rst) for code style, naming, imports, exceptions, tests, and docs conventions.\n\n## Commit Messages\n\nWe use squash merges for PRs. The squash commit message is the permanent record — it goes into\n`git log`, changelogs, and blame. The diff shows *what* changed; the PR shows *how* it evolved.\nThe commit message must explain **why**.\n\n### Format\n\n[Conventional Commits](https://www.conventionalcommits.org/). On squash-merge, the PR title becomes the commit subject line. The PR template's \"Commit message\" section becomes the body.\n\n**PR title** (becomes subject line):\n```\n<type>[scope]: <description>\n```\n\n**PR \"Commit message\" section** (becomes body):\n```\n<body>\n```\n\nTypes: `feat`, `fix`, `refactor`, `perf`, `chore`, `release`.\nScope is **required**. Validated by CI — see [pull-request.yaml](../.github/workflows/pull-request.yaml) for the canonical list.\nCurrent scopes: `venom`, `lang`, `codegen`, `parser`, `stdlib`, `ux`, `ir`, `test`, `docs`, `ci`, `build`, `tool`.\n\n### Subject Line (PR title)\n\n- Imperative, present tense (\"add X\" not \"added X\")\n- ~50 chars, lowercase, no period\n- Scope in brackets: `feat[venom]: add tail-merge pass`\n\n### Formatting\n\nWrap body at 72 chars. Use `fmt_commit_msg.py` to format — it defaults to `commitmsg.txt` and modifies in place.\n\n**Workflow for writing/updating the commit message in a PR:**\n\n```bash\n# 1. Write the commit message BODY to commitmsg.txt\n#    Do NOT include the subject line (type[scope]: description) —\n#    that comes from the PR title on squash-merge.\ncat > commitmsg.txt << 'EOF'\nmotivation paragraph here... (see \"Body\" section below)\n\nimplementation paragraph here...\nEOF\n\n# 2. Format it (wraps at 72 chars, preserves lists/code blocks)\npython fmt_commit_msg.py   # reads/overwrites commitmsg.txt, prints result to stdout\n\n# 3. Get the current PR body\ngh pr view <N> --json body -q .body > /tmp/pr_body.md\n\n# 4. Replace the ```-fenced block under \"### Commit message\" in /tmp/pr_body.md\n#    with the contents of commitmsg.txt (use Edit tool or sed)\n\n# 5. Upload\ngh pr edit <N> --body-file /tmp/pr_body.md\n```\n\nDo NOT write to `/tmp` or other locations and manually copy-paste — the script is designed to work on `commitmsg.txt` in the repo root. The file is gitignored.\n\n### Body — Explain Why and Context\n\nThe body is the most important part. It should answer:\n\n- **What problem does this solve?** What was broken, missing, or suboptimal?\n- **Why this approach?** What alternatives were considered? What tradeoffs were made?\n- **What are the non-obvious consequences?** Side effects, invariants established or broken, perf impact?\n\nDon't enumerate every file touched or mechanically list what each function does — that's the diff.\nDo explain the *reasoning* behind structural decisions, the bug mechanism, or the design rationale.\n\nCommit messages should not be tied to a particular issue tracker. Use `GH 1234` instead of `#1234` — the `#` syntax is GitHub-specific and creates links that are meaningless outside GitHub.\n\n### Good Example (from recent history)\n\nPR title: `fix[venom]: fix allocation in ternary fall through`\n\nCommit message body:\n```\n`Mem2Var._fix_adds` ensures `add` instructions on alloca pointers are\nrecognized by `BasePtrAnalysis` so it can track pointer provenance\nthrough arithmetic. When a ternary expression merges two\npointer paths via a `phi` node, the `add` sits downstream of the phi\nrather than as a direct use of the alloca — so `_fix_adds` never saw it.\n\nThe same gap existed in the caller guard: `_process_alloca_var`\nonly dispatched to `_fix_adds` when a direct `add` use was present,\nsilently skipping allocas whose only non-trivial uses were behind\nphi/assign nodes.\n\nAdditionally, following phi/assign chains introduces the possibility of\ncycles through loop back-edges, so add a visited set to terminate\ngracefully.\n```\n\nNote: explains the *mechanism* of the bug (why it happened), not just \"fixed a crash in X\".\n\n### Another Good Example\n\nPR title: `fix[venom]: treat immutables as global allocations`\n\nCommit message body:\n```\nthe immutables region (allocated at position 0 during deploy) was not\nreserved across function boundaries. when `ConcretizeMemLocPass` ran for\ninternal functions, it started with an empty reserved set, allowing\nfunction-local buffers to overlap position 0 and clobber immutable\nvalues.\n\nadd a `global_allocation` set to `MemoryAllocator` that persists across\nper-function allocation rounds. register the immutables alloca as global\nat IR conversion time.\n```\n\nNote: first paragraph is pure *why* (the bug mechanism). Second paragraph is a concise *what* — just enough to orient a reader, not a line-by-line walkthrough.\n\n### Anti-Patterns\n\n- ❌ \"Fix bug\" / \"Update code\" — says nothing\n- ❌ Listing every changed file or function — that's the diff\n- ❌ Only *what* with no *why* — \"add field X to class Y, call Z in function W\"\n- ❌ Copying the PR description verbatim (PR descriptions track evolution and review; commit messages are the final, distilled record)\n\n## Pull Requests\n\n- Fork from `master`\n- Write tests for new features; place them under `tests/`\n- Larger changes: discuss in Discord `#compiler-dev` first\n- PRs are squash-merged. See [Format](#format) for how the PR title and \"Commit message\" section map onto the final commit.\n- Work from your individual fork. PRs target `vyperlang/vyper` upstream:\n  ```bash\n  gh pr create --repo vyperlang/vyper --base master --head <fork-owner>:<branch>\n  ```\n- Follow the PR template (`.github/PULL_REQUEST_TEMPLATE.md`): What/How/Verify/Commit message/Changelog\n- To edit PR or issue bodies:\n  ```bash\n  gh pr view <N> --json body -q .body > /tmp/pr_body.md  # get current text\n  # edit /tmp/pr_body.md with Edit tool\n  gh pr edit <N> --body-file /tmp/pr_body.md              # upload\n  ```\n- **NEVER rebase and force-push a branch that is already under review.** Rebasing destroys review context (inline comments become orphaned, diff history is lost). If you need to pull in upstream changes on a PR branch, **merge `master` into your branch**.\n\n## Keeping Docs Current\n\nIf anything you have done requires content updates to any files in `skills/` or `CLAUDE.md`, update them as part of the same PR.\n\n## Git Quick Reference\n\n```bash\n# ALWAYS check what's pushed before amending.\n# Only amend commits not yet pushed\ngit log --oneline origin/<branch>..HEAD\n\n# undo a bad amend or commit (find the pre-amend state in reflog)\ngit reflog -10\ngit reset --mixed <good-sha>     # unstages changes, keeps working tree\ngit add <files> && git commit    # recommit cleanly\n\n# sync with upstream on a branch under review (NEVER rebase+force-push)\ngit merge master\n\n# interactive rebase doesn't work in non-interactive shells — use reset+cherry-pick instead\ngit stash                        # protect uncommitted work\ngit reset --hard <target>\ngit cherry-pick <commits>        # resolve conflicts manually\ngit stash pop\n```\n\n## Code Style Summary\n\nFull details in [docs/style-guide.rst](../docs/style-guide.rst). Highlights:\n\n- PEP 8, 100 char line length, enforced by `make lint`\n- Type classes end in `T` (`IntegerT`, `ModuleT`)\n- Method naming: `get_` (pure), `fetch_` (side effects), `build_` (creates new), classmethod `from_` (creates new from specific source), `check_` (pure, no raise, returns boolean), `validate_` (raises or returns None)\n- No builtin exceptions — use custom exception classes from `vyper/exceptions.py`\n- f-strings for string formatting\n- Import modules, not objects (avoids circular deps)\n- Cross-package imports must not reach beyond root namespace of target package\n- Tests: no mocking, no interdependence (xdist parallel), parametrize where logical\n\n<!-- File: skills/semantics.md (Tokens: ~612 | Category: anthropic-skill) -->\n# Semantics & Frontend\n\nType checking, validation, and semantic analysis of Vyper AST.\n\nPrimary reference: [vyper/semantics/README.md](../vyper/semantics/README.md) — full control flow, design, examples.\n\n## Pipeline\n\n```\nSource → pre_parser → Python AST → Vyper AST → semantic analysis → annotated AST\n```\n\n### AST Phase (`vyper/ast/`)\n\nSee [vyper/ast/README.md](../vyper/ast/README.md).\n\n- `pre_parser.py`: Vyper source → parseable Python (substitutes `struct`/`interface` → `class`, etc.)\n- `grammar.lark`: Lark grammar definition (for reference/making sure we adhere to a bnf spec)\n- `nodes.py`: Vyper AST node classes (use `__slots__`)\n- `parse.py` / `utils.py`: `parse_to_ast()` — main entry\n\n### Semantic Analysis Phase (`vyper/semantics/`)\n\nEntry: `vyper.semantics.analyze_module()`\n\nFour steps:\n1. **Pre-typecheck** (`analysis/pre_typecheck.py`): fold constant expressions\n2. **Namespace init** (`namespace.py`): populate builtins, types, env vars\n3. **Module validation** (`analysis/module.py`): storage vars, user types, imports, function sigs\n4. **Local validation** (`analysis/local.py`): per-function type checking and annotation\n\n## Type System (`vyper/semantics/types/`)\n\nType classes live in `vyper/semantics/types/`. Convention: classes end in `T` (e.g. `IntegerT`, `ModuleT`).\nBase classes in `bases.py`. Browse the directory for the full set — file names map to type categories\n(primitives, bytestrings, subscriptable, user-defined, function, module).\n\nType inference (aka type synthesis) is very limited and only for expressions: `(x: uint8) + 1` has type `uint8`, this is done by `_ExprAnalyser().get_possible_types_from_node`.\nType checking is done by `ExprVisitor`.\nThose are not fully decoupled however.\n\n## Namespace\n\n`Namespace` (`namespace.py`) is a dict subclass with scoping via context manager:\n\n```python\nwith namespace.enter_scope():\n    namespace[\"x\"] = some_type\n# x no longer exists here\n```\n\nScopes: builtin → module → local → (for/if blocks).\n\n## Analysis\n\nAnalysis and validation logic lives in `vyper/semantics/analysis/`. Key files:\n- `module.py` — module-level validation (storage, types, imports)\n- `local.py` — `FunctionNodeVisitor`, per-function validation\n- `annotation.py` — type annotation of expressions\n\nBrowse the directory for the full set. Also see `data_locations.py` and `environment.py` at the `semantics/` level.\n\n<!-- File: skills/SKILL.md (Tokens: ~1186 | Category: anthropic-skill) -->\n---\nname: vyper-compiler\ndescription: Vyper smart contract compiler internals. Use when working on the Vyper compiler codebase — compilation pipeline, Venom IR, semantic analysis, code generation, testing, or contributing. Triggers on vyper compiler development, Venom passes, AST/semantics changes, codegen work, or test writing.\n---\n\n# Vyper Compiler\n\nPythonic smart contract language targeting the EVM. v0.4.x, Python 3.11+.\n\n## Quick Commands\n\n```bash\nuv sync                                 # install deps (per-worktree .venv, recommended, includes dev group)\nuv run vyper contract.vy                # compile a contract\nuv run vyper -f ir_runtime contract.vy  # inspect Venom IR\nuv run vyper -f asm contract.vy         # inspect assembly\nuv run ./quicktest.sh                   # run tests (`-nauto -m \"not fuzzing\"` by default via setup.cfg)\nuv run make lint                        # enforces code style (same as CI)\n```\n\nPrefix all commands with `uv run` — it activates the local `.venv` per invocation, which is necessary in non-interactive shells. Each worktree gets its own `.venv`, so no cross-contamination.\n\nAlternative: `pip install . --group dev` + `PYTHONPATH=.` prefix on every command. **Never `pip install -e .`** — it creates an egg-link in site-packages that permanently points the venv at one worktree, breaking all others.\n\n## Compilation Pipeline\n\n```\nSource (.vy)\n  │\n  ├─ vyper/ast/            → Parse to AST (pre_parser → Python AST → Vyper AST)\n  ├─ vyper/semantics/      → Type check, validate, annotate AST\n  ├─ vyper/codegen/        → AST → s-expr IR (default production pipeline)\n  ├─ vyper/ir/             → s-expr IR → assembly → bytecode\n  └─ vyper/evm/            → Assembly → bytecode\n```\n\nExperimental Venom path (`--experimental-codegen`):\n```\n  ├─ vyper/codegen_venom/  → AST → Venom SSA IR\n  └─ vyper/venom/          → Venom IR optimization passes → assembly\n```\n\nOrchestrated by `vyper/compiler/phases.py` (`CompilerData`). Each phase is lazy.\n\n## Directory Map\n\n| Directory | Purpose |\n|-----------|---------|\n| `vyper/ast/` | Parsing, AST nodes, pre-parser. See [AST README](../vyper/ast/README.md) |\n| `vyper/semantics/` | Type system, analysis, validation. See [Semantics README](../vyper/semantics/README.md) |\n| `vyper/codegen/` | AST → s-expr IR (default production pipeline) |\n| `vyper/ir/` | s-expr IR → assembly → bytecode. See [IR README](../vyper/ir/README.md) |\n| `vyper/codegen_venom/` | AST → Venom IR (experimental, `--experimental-codegen`) |\n| `vyper/venom/` | Venom SSA IR: passes, analysis, assembly emission. See [Venom README](../vyper/venom/README.md) |\n| `vyper/compiler/` | Pipeline orchestration, settings, output formats. See [Compiler README](../vyper/compiler/README.md) |\n| `vyper/builtins/` | Built-in functions and interfaces |\n| `vyper/evm/` | EVM opcodes, assembler |\n| `vyper/cli/` | CLI entry points (`vyper`, `vyper-ir`, `venom`) |\n| `tests/unit/` | Unit tests (ast, semantics, compiler, venom) |\n| `tests/functional/` | Functional tests (builtins, codegen, grammar, syntax, venom) |\n\n## Topic Deep-Dives\n\n- **[Venom IR](venom.md)** — SSA IR design, passes, optimization, working with Venom code\n- **[Semantics & Frontend](semantics.md)** — Type system, analysis phases, namespace, validation\n- **[Code Generation](codegen.md)** — Legacy IR, Venom codegen, the two pipelines\n- **[Testing](testing.md)** — Test structure, fixtures, running tests, writing new tests\n- **[Contributing](contributing.md)** — Commit message standards, PR workflow, code style summary\n\n## Code Style\n\nEnforced by `make lint` (also what CI runs). Includes `black`, `flake8`, `isort`, `mypy`.\n\n- Line length: 100\n- No inline imports; standard library → third-party → local\n- snake_case for variables (`tmp = ...`), DromedaryCase (aka upper camelCase) for classes (`ExprAnalyzer`), type classes end in `T` (e.g. `IntegerT`, `ModuleT`)\n\n## Key Entry Points\n\n| What | Where |\n|------|-------|\n| Main compile function | `vyper.compiler.compile_code()` |\n| Pipeline phases | `vyper.compiler.phases.CompilerData` |\n| AST parsing | `vyper.ast.parse.parse_to_ast()` |\n| Semantic analysis | `vyper.semantics.analyze_module()` |\n| Legacy codegen | `vyper.codegen.module` |\n| AST → Venom IR | `vyper.codegen_venom.module` |\n| Venom → assembly | `vyper.venom.generate_assembly_experimental()` |\n| CLI entry | `vyper.cli.vyper_compile` |\n\n<!-- File: skills/testing.md (Tokens: ~426 | Category: anthropic-skill) -->\n# Testing\n\n## Running Tests\n\n```bash\n./quicktest.sh -m \"not fuzzing\"          # standard test run (-nauto by default via setup.cfg)\n./quicktest.sh tests/unit/               # unit tests only\n./quicktest.sh tests/functional/         # functional tests only\n./quicktest.sh tests/unit/compiler/venom/ # venom unit tests\n./quicktest.sh --hevm -m hevm            # hevm-based tests (needs hevm in PATH)\n```\n\n`quicktest.sh` wraps pytest with `-q -s --instafail -x` (bail on first failure).\n\n## Test Organization\n\n```\ntests/\n├── unit/           # isolated component tests\n│   ├── ast/\n│   ├── semantics/\n│   ├── compiler/\n│   │   └── venom/  # venom pass & analysis tests\n│   ├── cli/\n│   └── ...\n├── functional/     # end-to-end compilation & execution\n│   ├── builtins/\n│   ├── codegen/\n│   ├── grammar/\n│   ├── syntax/\n│   └── venom/\n├── conftest.py     # shared fixtures\n├── evm_backends/   # EVM execution backends for tests\n└── venom_utils.py  # helpers for venom tests\n```\n\n## Key Fixtures & Helpers\n\n- `tests/conftest.py` — main fixtures (compiler invocation, EVM backends)\n- `tests/evm_backends/` — pluggable EVM execution (pyevm, pyrevm)\n- `tests/venom_utils.py` — helpers for constructing Venom IR in tests\n\n## Writing Tests\n\n- Functional tests typically compile a Vyper snippet and execute it against an EVM backend\n- Venom unit tests construct IR programmatically, run passes, and assert on the result\n- Use `pytest.mark.fuzzing` for slow/fuzz tests (skipped in quick runs)\n- Use `pytest.mark.hevm` for hevm-specific tests\n\n<!-- File: skills/venom.md (Tokens: ~550 | Category: anthropic-skill) -->\n# Venom IR\n\nSSA-based intermediate representation for Vyper. Inspired by LLVM IR, adapted for stack-based EVM.\n\nPrimary reference: [vyper/venom/README.md](../vyper/venom/README.md) — full instruction set, grammar, examples.\n\n## Structure\n\n```\nIRContext → IRFunction(s) → IRBasicBlock(s) → IRInstruction(s)\n```\n\n- Variables: `%`-prefixed, immutable after assignment (SSA)\n- Basic blocks: non-branching, terminated by `jmp`/`jnz`/`djmp`/`ret`/`return`/`stop`/`exit`\n- Normalized form: no block has both multiple predecessors AND multiple successors\n\n## Key Files\n\nCore data structures in `vyper/venom/`:\n- `context.py` — `IRContext`, top-level container\n- `function.py` — `IRFunction`\n- `basicblock.py` — `IRBasicBlock`, `IRInstruction`, `IROperand`\n- `builder.py` — helper for programmatic IR construction\n- `venom_to_assembly.py` — final pass: Venom → EVM assembly\n- `parser.py` — text format parser (for testing)\n\nPasses and analysis live in `venom/passes/` and `venom/analysis/` respectively.\n\n## Pass Architecture\n\nPasses inherit from base classes in `venom/passes/base_pass.py`. Three categories:\n- **Analysis** — `venom/analysis/` (CFG, DFG, liveness, dominators, etc.)\n- **Transformation** — normalization, SSA construction, phi elimination\n- **Optimization** — DCE, SCCP, CSE, load elimination, mem2var, inlining, etc.\n\nPass ordering matters — e.g. assembly emission requires normalization, which requires CFG.\n\nBrowse `venom/passes/` and `venom/analysis/` for the full set. File names are self-descriptive.\n\n## Inspecting Venom Output\n\n```bash\nvyper -f ir_runtime contract.vy        # Venom IR (runtime)\nvyper -f ir contract.vy                # Venom IR (deploy)\nvyper -f cfg_runtime contract.vy       # CFG as dot graph\nvyper -f asm contract.vy               # final assembly\n```\n\nEnable Venom: `--experimental-codegen` flag or `#pragma experimental-codegen` in source.\n\n## Entry Path\n\nAST → `vyper/codegen_venom/` → Venom IR (direct translation, no legacy IR involved).\nEntry point: `vyper/codegen_venom/module.py`.\n\n<!-- File: CLAUDE.md (Tokens: ~311 | Category: claude-rule) -->\n# Vyper Compiler — Agent Guide\n\nPythonic smart contract language targeting the EVM. v0.4.x, Python 3.11+.\n\n## Quick Commands\n\n```bash\nuv sync --extra dev              # install deps (per-worktree .venv, recommended)\nuv run vyper contract.vy                # compile a contract\nuv run vyper -f ir_runtime contract.vy  # inspect Venom IR\nuv run vyper -f asm contract.vy         # inspect assembly\nuv run ./quicktest.sh -m \"not fuzzing\"  # run tests (-nauto by default via setup.cfg)\nuv run make lint                        # enforces code style (same as CI)\n```\n\n## Architecture, Code Style, Entry Points\n\nSee [skills/SKILL.md](skills/SKILL.md) for compilation pipeline, directory map, code style, and key entry points.\n\n## Topic Deep-Dives\n\n- **[Venom IR](skills/venom.md)** — SSA IR design, passes, optimization, working with Venom code\n- **[Semantics & Frontend](skills/semantics.md)** — Type system, analysis phases, namespace, validation\n- **[Code Generation](skills/codegen.md)** — Legacy IR, Venom codegen, the two pipelines\n- **[Testing](skills/testing.md)** — Test structure, fixtures, running tests, writing new tests\n- **[Contributing](skills/contributing.md)** — Commit message standards, PR workflow, code style summary\n</yakaai_skills>"}