{"owner":"carbon-language","repo":"carbon-lang","hasSkills":true,"totalSkillsCount":17,"totalTokensCount":24906,"categories":["anthropic-skill","root-instruction","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":[".agents/skills/agent_tools/SKILL.md",".agents/skills/bazel/SKILL.md",".agents/skills/builtins/SKILL.md",".agents/skills/code_style/SKILL.md",".agents/skills/diagnostics/SKILL.md",".agents/skills/github_cli/SKILL.md",".agents/skills/github_issues/SKILL.md",".agents/skills/jj/SKILL.md",".agents/skills/language_server/SKILL.md",".agents/skills/prek/SKILL.md",".agents/skills/proposals/SKILL.md",".agents/skills/review_testdata_changes/SKILL.md",".agents/skills/summarize_testdata_changes/SKILL.md",".agents/skills/toolchain_development/SKILL.md",".agents/skills/toolchain_tests/SKILL.md","AGENTS.md","github_tools/README.md"],"skills":{".agents/skills/agent_tools/SKILL.md":"---\nname: Agent tools\ndescription:\n    Guidelines and restrictions on shell commands and file manipulation tools\n    for AI assistants.\n---\n\n# Agent tools\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nAI assistants working on the Carbon repository **MUST NOT** use legacy or\ngeneric UNIX shell search/edit commands when specialized environment tools\nexist.\n\n## Command line tools restrictions\n\n-   **DO NOT USE**: `cat`, `less`, `grep`, `sed`, or other shell utilities for\n    viewing, searching, or modifying files.\n-   **DO NOT USE**: `patch` to write and apply patch files.\n-   **DO NOT USE**: Writing custom scripts in other languages to circumvent this\n    limitation.\n-   **DO USE**: High-fidelity semantic API tools:\n    -   **Viewing**: Use `view_file` instead of `cat` / `less`.\n    -   **Searching**: Use `grep_search` / `find_by_name` instead of `grep` /\n        `find`.\n    -   **Modifying**: Use `replace_file_content`, `multi_replace_file_content`,\n        or `write_to_file` instead of `sed` / `patch` / `python` edits.\n\nYou may only write and run temporary programs to modify source code if no\nsemantic tool is applicable or when performing complex, systematic transforms\nacross many codebase directories simultaneously.\n\n## Temporary files management\n\nTemporary files and scratchpad test scripts created by the assistant during\nanalysis, experiments, or debugging:\n\n-   **MUST** reside within the `tmp/` subdirectory under the workspace root.\n-   **MUST** be periodically cleaned out and deleted before ending your turn to\n    preserve a clean git workspace.\n",".agents/skills/bazel/SKILL.md":"---\nname: Bazel usage\ndescription:\n    Instructions that **MUST** be followed when using Bazel or Bazelisk to\n    build, test, and debug in the Carbon repository.\n---\n\n# Bazel usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill documents how best to use Bazel when building, testing, or\nmanipulating the Carbon repository's Bazel in any way.\n\n## Bazel wrappers\n\nCarbon uses Bazel for its build system. To ensure consistent versions, the\nproject uses Bazelisk.\n\n> [!IMPORTANT] Always use `bazelisk` whenever you want to run Bazel. Never run\n> `bazel` directly in the Carbon project. Anything you want to do with `bazel`\n> can be done with the `bazelisk` command instead.\n\n-   **Bazelisk**: Try to use `bazelisk` in your existing `$PATH` if available.\n    -   **`run_bazelisk.py`**: If `bazelisk` isn't available, use\n        `./scripts/run_bazelisk.py` to run bazelisk without it being installed.\n\n## Essential commands\n\n### Building\n\n-   **Build all**: `bazelisk build //...`\n-   **Build toolchain**: `bazelisk build //toolchain/...`\n-   **Build specific target**: `bazelisk build //toolchain:carbon`\n\n### Testing\n\n-   **Test all**: `bazelisk test //...:all`\n-   **Test toolchain**: `bazelisk test //toolchain/...`\n-   **Test examples**: `bazelisk test //examples/...`\n\n> [!TIP] Running all of the tests can be slow, so try to narrowly test the\n> immediately relevant parts of the project first, and only expand coverage as\n> necessary to be confident in the changes.\n\n> [!TIP] For specialized instructions on testing and developing the Carbon\n> toolchain, consult these skills:\n>\n> -   [Toolchain tests](/.agents/skills/toolchain_tests/SKILL.md): For\n>     authoring, structuring, and running `file_test` tests.\n> -   [Toolchain development](/.agents/skills/toolchain_development/SKILL.md):\n>     For architecture, essential commands, and debugging the toolchain.\n\n### Running binaries built by Bazel\n\n> [!IMPORTANT] Always manually run binaries built by Bazel using the\n> `bazelisk run` command. Never run the binary directly from `bazel-bin/`.\n\nYou can run the Carbon driver or command line directly via Bazel:\n\n-   `bazelisk run //toolchain -- compile --phase=parse\n    toolchain/parse/testdata/basics/empty.carbon`\n\n## Advanced configurations\n\n### AddressSanitizer (ASan)\n\nTo enable ASan for local testing:\n\n-   Pass `--config=asan`: `bazelisk test --config=asan //...`\n\n## Common pitfalls and troubleshooting\n\n### `bazel clean`\n\nChanges to packages installed on your system (like changing LLVM versions or\ninstalling `libc++`) may not be noticed by Bazel.\n\n-   Run `bazelisk clean` to force cached state to be rebuilt when environment\n    changes occur.\n",".agents/skills/builtins/SKILL.md":"---\nname: Builtin functions\ndescription:\n    Instructions for registering, mapping, constant evaluating, and lowering\n    builtin functions in the Carbon toolchain.\n---\n\n# Builtin Functions in the Carbon Toolchain\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nBuiltin functions are compiler-recognized primitives mapping directly from\nCarbon code expressions (via standard prelude bindings) to optimized backend\nexecution. This document defines the complete structural workflow, C++ patterns,\nconstant evaluation logic, machine lowering mechanics, library bindings, and\nvalidation strategies required to implement builtin functions in the Carbon\ncompiler.\n\n---\n\n## Technical Flow & Lifecycle\n\n```mermaid\ngraph TD\n  Src[Carbon Source Code] -->|Prelude Map| Sem[Semantic Analysis / SemIR]\n  Sem -->|Signature Constraint| Sig[builtin_function_kind.cpp]\n  Sem -->|Phase Evaluation| Eval[eval.cpp Constant Interpreter]\n  Sem -->|Machine Codegen| Lower[handle_call.cpp LLVM Lowering]\n  Eval -->|Diagnostics| Diag[diagnostics/kind.def]\n  Lower -->|Native Instructions| LLVM[LLVM IR Generation]\n```\n\nAdding a builtin function involves a 5-step integration:\n\n1.  **Define the Builtin Kind**: Register the enum in\n    [builtin_function_kind.def](../../../toolchain/sem_ir/builtin_function_kind.def).\n2.  **Signature & Compile-Time Registry**: Declare the mapping name, parameter\n    constraints, and compile-time evaluation residency in\n    [builtin_function_kind.cpp](../../../toolchain/sem_ir/builtin_function_kind.cpp).\n3.  **Compile-Time Interpreter Support**: Wire constant evaluation hooks and\n    bounds/exception diagnostics in\n    [eval.cpp](../../../toolchain/check/eval.cpp).\n4.  **LLVM IR Lowering Support**: Connect target machine generation in\n    [handle_call.cpp](../../../toolchain/lower/handle_call.cpp).\n5.  **Prelude Library Mapping**: Bind primitive interfaces to named builtins\n    under [core/prelude/](../../../core/prelude/).\n\n---\n\n## Detailed Step-by-Step Implementation Guide\n\n### Step 1: Kind Definition & Registration\n\nRegister your builtin function name using the X-macro in\n[builtin_function_kind.def](../../../toolchain/sem_ir/builtin_function_kind.def):\n\n```cpp\n// toolchain/sem_ir/builtin_function_kind.def\n\n// Converts an integer type to a floating-point type.\nCARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntConvertFloat)\n```\n\n### Step 2: Signature Validation & Compile-Time Residence\n\nInside\n[builtin_function_kind.cpp](../../../toolchain/sem_ir/builtin_function_kind.cpp):\n\n1.  **Define Parameter Constraints**: If the parameter requires novel\n    constraints (e.g. \"must be a float type\"), define a template constraint\n    struct checking the matching `SemIR` type instruction (such as `FloatType`\n    or `FloatLiteralType`). Use pre-established semantic helpers:\n\n    -   `TypeParam<I, T>`: Ensures different parameters resolve to identical\n        type structures (e.g., generic constraint matching).\n    -   `AnyInt`, `AnyFloat`, `AnySizedInt`, `AnySizedFloat`, `CharCompatible`,\n        `StdInitializerList`, `NoReturn`.\n\n2.  **Map Literal Name & Register Constraint Signature**: Declare a\n    `BuiltinInfo` constant inside `namespace BuiltinFunctionInfo` matching the\n    macro-defined name:\n\n    ```cpp\n    // toolchain/sem_ir/builtin_function_kind.cpp\n\n    constexpr BuiltinInfo IntConvertFloat = {\n        \"int.convert_float\", ValidateSignature<auto(AnyInt)->AnyFloat>};\n    ```\n\n3.  **Establish Compile-Time Residency Status**: Update\n    `BuiltinFunctionKind::IsCompTimeOnly` to determine if a call requires\n    compile-time evaluation:\n    -   **Checked/Diagnostics Primitives**: Return `true` immediately. Runtime\n        lowering of these is illegal (e.g. `IntConvertFloatChecked`).\n    -   **Runtime Primitives**: Return\n        `AnyLiteralTypes(sem_ir, arg_ids, return_type_id)` to enforce that\n        expressions involving unsized literal values (like `IntLiteral` or\n        `FloatLiteral`) are evaluated exclusively at compile-time (as they lack\n        runtime representation).\n\n---\n\n### Step 3: Constant Evaluation Support\n\nWire the interpreter inside [eval.cpp](../../../toolchain/check/eval.cpp) to\nexecute compile-time computations:\n\n1.  **Implement Constant Evaluation Logic**:\n\n    -   Handle the builtin case inside `MakeConstantForBuiltinCall` (which\n        processes the compile-time execution of the call).\n    -   Confirm type validation phase is `Phase::Concrete` to reject incomplete\n        bindings:\n\n        ```cpp\n        case SemIR::BuiltinFunctionKind::IntConvertFloat: {\n          if (phase != Phase::Concrete) {\n            return MakeConstantResult(context, call, phase);\n          }\n          return PerformIntToFloatConvert(context, loc_id, arg_ids[0], call.type_id,\n                                          /*require_exact=*/false);\n        }\n        ```\n\n    -   Extract inputs safely from local value stores (e.g.\n        `context.ints().Get(arg.int_id)` or\n        `context.floats().Get(arg.float_id)`).\n    -   Leverage high-precision LLVM mathematical structures (`llvm::APInt`,\n        `llvm::APFloat`, `llvm::APSInt`) to handle custom bits and signedness\n        safely.\n\n2.  **Diagnose Invalid Parameters or Exceptions**:\n\n    -   Define compile-time diagnostics inside\n        [kind.def](../../../toolchain/diagnostics/kind.def):\n\n        ```cpp\n        // toolchain/diagnostics/kind.def\n        CARBON_DIAGNOSTIC_KIND(IntTooLargeForFloatType)\n        ```\n\n    -   Emplace localized diagnostic formatting messages where they are caught\n        in `eval.cpp`:\n\n        ```cpp\n        CARBON_DIAGNOSTIC(IntTooLargeForFloatType, Error,\n                          \"integer value {0} too large for floating-point type {1}\",\n                          llvm::APSInt, SemIR::TypeId);\n        context.emitter().Emit(loc_id, IntTooLargeForFloatType, val, dest_type_id);\n        ```\n\n    -   Return `SemIR::ErrorInst::ConstantId` to gracefully abort invalid\n        constant generation rather than crashing the compiler.\n\n3.  **Fast-Path Range Limits**:\n    -   Before evaluating expensive math operations on giant exponents (e.g.\n        `1.0e1000000`), executing range limits check against `dest_width + 64`\n        (sized) or `IntStore::MaxIntWidth` (unsized) is mandatory to prevent\n        out-of-bounds calculations and compile-time memory exhaustion.\n\n---\n\n### Step 4: Machine Code Generation (LLVM Lowering)\n\nInside [handle_call.cpp](../../../toolchain/lower/handle_call.cpp):\n\n1.  **Map to Native LLVM Instructions**: For runtime-eligible builtins, map the\n    call inside `HandleBuiltinCall` to native LLVM IR builder methods:\n\n    ```cpp\n    case SemIR::BuiltinFunctionKind::IntConvertFloat: {\n      auto* operand = context.GetValue(arg_ids[0]);\n      auto* dest_type = context.GetTypeOfInst(inst_id);\n      bool is_signed = IsSignedInt(context, arg_ids[0]);\n      context.SetLocal(\n          inst_id, is_signed\n                       ? context.builder().CreateSIToFP(operand, dest_type)\n                       : context.builder().CreateUIToFP(operand, dest_type));\n      return;\n    }\n    ```\n\n2.  **Assert on Compile-Time-Only Builtins**: Throw a hard assertion on\n    lowering-cases for checked validator builtins that should never hit code\n    generation:\n\n    ```cpp\n    case SemIR::BuiltinFunctionKind::IntConvertFloatChecked: {\n      CARBON_CHECK(builtin_kind.IsCompTimeOnly(\n          context.sem_ir(), arg_ids,\n          context.sem_ir().insts().Get(inst_id).type_id()));\n      CARBON_FATAL(\"Missing constant value for call to comptime-only function\");\n    }\n    ```\n\n---\n\n### Step 5: Standard Library Prelude Integration\n\nMap the standard library primitive interfaces to your newly minted named\nbuiltins under [core/prelude/](../../../core/prelude/):\n\n-   **Primitive Mappings**: Bind Carbon methods directly to string-literal\n    builtin equivalents:\n\n    ```carbon\n    fn Convert[self: Self]() -> Float(To) = \"int.convert_float\";\n    ```\n\n-   **Strict Orphan Rule Compliance**: Carbon's orphan rules prohibit\n    implementing interfaces where neither the type nor the interface is locally\n    defined in the backing source module.\n    -   **Literal Conversions**: Literal types (like `FloatLiteral`,\n        `IntLiteral`) do not have backing Carbon source files. Therefore, an\n        `impl` of `UnsafeAs` (which is defined in `as.carbon`) between two\n        literal types must reside inside `as.carbon` itself.\n    -   **Sized Conversions**: Implementations targeting sized primitives (e.g.\n        `Int(N)`, `Float(N)`) must reside in their respective type source files\n        (such as [int.carbon](../../../core/prelude/types/int.carbon) or\n        [float.carbon](../../../core/prelude/types/float.carbon)) where the\n        backing target type resides to prevent duplicate symbols and structural\n        recursion loops.\n\n---\n\n## High-Fidelity Validation & Test Authoring\n\nFollow the [Toolchain tests](../toolchain_tests/SKILL.md) skill with specialized\npatterns for builtins:\n\n### 1. Checker Builtin File Splits\n\nCreate validation splits under\n[toolchain/check/testdata/builtins/](../../../toolchain/check/testdata/builtins/):\n\n-   **Test Naming Convention**: All tests under\n    [toolchain/check/testdata/builtins/](../../../toolchain/check/testdata/builtins/)\n    must be named after the builtin they are testing, replacing `.` characters\n    in the builtin name with `/` (directories). For example, a test for the\n    builtin `\"char_literal.convert\"` must be located at\n    `toolchain/check/testdata/builtins/char_literal/convert.carbon`.\n-   **Minimal Prelude & Direct Call Isolation**: Builtin tests must **not** test\n    the prelude library or operators. They must use the minimal primitive\n    prelude (`// INCLUDE-FILE:\n    toolchain/testing/testdata/min_prelude/primitives.carbon`) or a smaller\n    prelude, and explicitly declare and call the builtin functions under test\n    directly (e.g., `fn Add(a: f64, b: f64) -> f64 = \"float.add\";`). This\n    isolates the testing of compiler builtins from the library prelude.\n-   **Min-Prelude Limitations**: Standard operators (like `+`, `-`, `/`, `<`,\n    etc.) are **not** available in minimized preludes because the core operators\n    library isn't imported. To write tests with a minimal footprint, call\n    primitive builtins directly (e.g. `float.negate`, `float.div`) inside your\n    test code to build expressions.\n-   **Canonicalized Float Comparison**: In SemIR, real literal representations\n    with identical mathematical values can result in mismatched `RealId` objects\n    based on spelling variations. Verify compile-time constant conversions using\n    canonicalized comparison functions (e.g. passing converted results through\n    `Expect(X as f64)`) to completely avoid spelling mismatches in expected\n    outputs.\n-   **Locals Bypass**: If validating generic implicit conversions, compile-time\n    arguments cannot take local runtime variable parameters. Validate\n    compile-time conversions by passing literal constants directly, and sized\n    variable implicit conversions at runtime.\n\n### 2. Machine Codegen Lowering Splits\n\nCreate testing splits under\n[toolchain/lower/testdata/builtins/](../../../toolchain/lower/testdata/builtins/):\n\n-   Emplace a simple carbon binding to the tested builtin.\n-   Confirm matching LLVM metadata target definitions are mapped precisely\n    (e.g., matching `sitofp i32 %a to float`, `fptosi float %a to i32`).\n",".agents/skills/code_style/SKILL.md":"---\nname: Code style\ndescription:\n    Instructions for code formatting and style guidelines in the Carbon\n    toolchain.\n---\n\n# Code style\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## License\n\n-   **Licenses**: All Carbon files outside of `third_party/` should have a\n    license following\n    [CONTRIBUTING license instructions](/CONTRIBUTING.md#license).\n\n## Formatting\n\n-   **Bazel**: Use `pre-commit run buildifier --files <file.bzl>` to format\n    Bazel files.\n-   **C++**: Use `pre-commit run clang-format --files <file.cpp>` to format C++\n    files.\n-   **Carbon**: The toolchain's `format` command doesn't work well right now.\n    Instead, try to format Carbon code based on other Carbon files and the C++\n    style.\n-   **Markdown**: Use `pre-commit run prettier --files <file.md>` to format\n    markdown files.\n-   **Python**: Use `pre-commit run black --files <file.py>` to format Python\n    files.\n\n## Comments\n\n-   **Describe the code that is there.** A comment should explain what the\n    current code does or why it is the way it is, not narrate what the code used\n    to be. Do not add a comment to justify a deletion or explain that something\n    is no longer necessary; a reader of the new code has no idea what is being\n    contrasted against, and the comment rots as soon as the old shape is\n    forgotten. Put that reasoning in the commit message instead.\n-   **Do not introduce a local variable just to host a comment.** If a call\n    argument reads clearly on its own, inline it rather than naming it so that a\n    comment has somewhere to attach.\n-   **Lead with a plain summary.** Start a doc comment with a direct statement\n    of what the function does or returns, such as \"Returns true if the InstKind\n    is a singleton.\" Put nuance in a following sentence rather than qualifying\n    the summary into something harder to read.\n-   **Re-read a comment before updating it.** When a symbol is renamed or\n    changes meaning, a comment that mentions it is not automatically stale. Work\n    out what the comment actually asserts first: it may be describing what the\n    code _uses_, which is still true, and rewriting it loses information.\n\n## Documentation\n\nThis covers standalone prose: `/docs`, `README.md` files, and the skill files\nunder `.agents/skills`.\n\n-   **Be true of the tree it lands in.** Documentation shipping in the same\n    commit as the code it describes should name that code freely. Documentation\n    that lands separately must not: a reader who greps for an identifier from an\n    unlanded change finds nothing, and a claim that only holds after that change\n    is false until it lands. This is easy to get wrong when writing up a lesson\n    while the change that taught it is still in flight.\n-   **Use placeholders for illustrations.** When an example only needs to show a\n    shape, name it `Foo` rather than reaching for a real symbol. Save real\n    identifiers for documenting that identifier, where going stale is at least\n    detectable.\n-   **Make each point stand alone.** A reader has none of the discussion that\n    produced it. State the rule, and enough of the reason to apply it, without\n    assuming knowledge of the change that motivated it.\n\n## Naming\n\n-   **A name is a claim, so keep it true.** When a change invalidates the\n    invariant a name describes, rename it in the same change. A factory called\n    `MakeSingletonFooId` has to be renamed once `Foo` is no longer a singleton,\n    even though nothing forces you to.\n-   **Types in a signature are part of the claim.** A function returning the id\n    of a namespace should return `InstId`, not `TypeInstId`, because a namespace\n    is not a type. Do not let a convenient wider or narrower id type imply\n    something false.\n-   **Delete a predicate whose name stops distinguishing anything.** If a change\n    widens a test so that it no longer says what its name implies, remove it and\n    let callers use the underlying test, rather than keeping a wrapper that\n    sounds meaningful. What callers actually want is often the inverse, and is\n    worth adding under its own name.\n-   **Name a variable for its role, not its representation.** If the role a\n    value plays is unchanged, keep its name even when a change means it is now\n    held or spelled differently.\n\n## Commit descriptions\n\n-   **Say what the change is, not how you made it.** Describe the resulting\n    code. Only describe process when the process is more interesting than the\n    change, as with a large mechanical transformation.\n-   **Do not narrate your own work.** Statements like \"each such site was\n    audited\" or \"we investigated every caller\" describe effort, not the change.\n-   **Omit routine mechanical steps.** Do not mention running the testdata\n    autoupdater or the formatter. Every change is expected to include those.\n-   **Do not enumerate each edit.** Describe the change as a whole rather than\n    listing every function or file touched; the diff already lists them.\n-   **Use the project's terms precisely.** Reach for the term of art the\n    codebase uses. Calling something a \"type alias\" or a \"namespace\" when it is\n    a named scope misleads, and is worse than a vaguer but accurate word.\n-   **Scope claims to what changed.** Say the specific thing that is now true,\n    rather than a broader statement that happens to contain it.\n\n## Design\n\n-   **Do not distort the data model to improve output.** If printed or golden\n    output is undesirable, change the printer, not the data structures that\n    feed it.\n\n## Style Guides\n\n-   **C++ style**: Follow the\n    [Carbon C++ Project Style Guide](/docs/project/cpp_style_guide.md).\n-   **Markdown style**: Follow the\n    [Google developer documentation style guide](https://developers.google.com/style).\n-   **Python style**: Follow the [PEP 8](https://peps.python.org/pep-0008/)\n    style guide.\n    -   Wrap code and comments to 80 columns.\n    -   Run `pre-commit run flake8 --files <file.py>` to check Python style.\n",".agents/skills/diagnostics/SKILL.md":"---\nname: Diagnostics\ndescription:\n    Instructions for declaring, formatting, emitting, testing, and styling\n    diagnostic messages (errors, warnings, and the labels that explain them) in\n    the Carbon toolchain.\n---\n\n# Diagnostics in the Carbon Toolchain\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThe Carbon compiler features a highly-engineered, context-aware diagnostics\nframework designed to deliver precise, readable, and highly targetable\ndiagnostic output (errors, warnings, and the labels that explain them). This\ndocument establishes strict rules for declaring, formatting, emitting, testing,\nand styling compiler diagnostics.\n\n---\n\n## Architecture Overview\n\n```mermaid\ngraph TD\n  Kind[kind.def Registry] -->|Registration| Enum[Kind Enum ID]\n  Enum -->|Build/Emit| Emitter[Emitter LocT]\n  Emitter -->|ConvertLoc| Loc[Converted Physical Loc]\n  Emitter -->|formatv serialization| Formatting[format_providers.h / Custom Types]\n  Emitter -->|Emit Messages| Consumer[Console / Sorting Consumer]\n  Consumer -->|stable sort| StdErr[Compiler Standard Error]\n```\n\nDiagnostics are handled via three decoupled core components:\n\n1.  **Registry**: Globally enumerated kinds inside\n    [kind.def](../../../toolchain/diagnostics/kind.def).\n2.  **Emitters**: Specialized formatting pipelines (parameterized on custom\n    phase location types `LocT` like `Token` or `LocId`) that convert raw tokens\n    to standardized physical source locations (file, line, column, and the text\n    of the line).\n3.  **Consumers**: Pipelines that process, track, filter, and sort diagnostics.\n    The default `SortingConsumer` buffers and stable-sorts diagnostics based on\n    their `last_byte_offset` matching compiler traversal order to ensure perfect\n    causal ordering.\n\n---\n\n## 1. Declaring and Registering Diagnostics\n\nAll diagnostic types must pass structural uniqueness and coverage verifications.\n\n### The Diagnostic Registry\n\nEvery diagnostic kind must be registered globally as an enum option under\n[kind.def](../../../toolchain/diagnostics/kind.def):\n\n```cpp\n// toolchain/diagnostics/kind.def\nCARBON_DIAGNOSTIC_KIND(RealLiteralTooLargeForUnsizedInt)\n```\n\n### The Uniqueness Rule\n\nTo ensure optimal compile-time and analysis integrity, every diagnostic kind\ndeclared in `kind.def` **MUST** be mapped to **one and only one** C++ macro\ndeclaration (`CARBON_DIAGNOSTIC` or `CARBON_DIAGNOSTIC_ON_SCOPE`).\n\n-   **DO NOT** duplicate diagnostic definitions across different locations.\n-   The C++ representation of the diagnostic is a static/global constant of type\n    `DiagnosticBase<Args...>`.\n-   **Local Scope (Recommended)**: If the diagnostic is unique to a single\n    block/function body, declare it **locally** inside the function body\n    adjacent to its `Emit` trigger:\n\n    ```cpp\n    void ConvertFloatValueToInt(...) {\n      CARBON_DIAGNOSTIC(FloatNaNConvertedToInt, Error,\n                        \"cannot convert NaN to integer type {0}\", SemIR::TypeId);\n      context.emitter().Emit(loc_id, FloatNaNConvertedToInt, dest_type_id);\n    }\n    ```\n\n-   **File Scope**: If the diagnostic is shared among multiple functions inside\n    the _same_ file, declare it at **file scope** inside the anonymous namespace\n    of the `.cpp` file.\n-   **Global Scope**: If a diagnostic (such as a shared helper label) is reused\n    _across different physical files_, define it in a shared header (e.g.\n    context/check helpers) and mark it `extern` where applicable, ensuring the\n    macro is only invoked once.\n\n---\n\n## 2. Formatting Diagnostic Arguments\n\nCarbon diagnostics leverage LLVM's `formatv` engine. Parameters must be passed\nusing strongly-typed arguments to preserve translation capability.\n\n### String Lifetimes & Pitfalls\n\n-   **`llvm::StringRef` is DISALLOWED**: Do not pass `StringRef` as a parameter\n    type to `CARBON_DIAGNOSTIC` due to unsafe lifetime and buffer-allocation\n    boundaries.\n-   **`llvm::StringLiteral` is DISALLOWED**: Do not use literal types as\n    arguments as they prevent future diagnostic localization and translations.\n-   **Use `std::string`**: If string formatting or custom allocations are\n    required, declare the parameter storage type as `std::string`.\n\n### Format Selectors (`format_providers.h`)\n\nUse specialized formatting wrappers under\n[format_providers.h](../../../toolchain/diagnostics/format_providers.h) to\nexpress clean inline options in format strings:\n\n| Wrapper                    | Target Format Style             | Example Usage                  | Output                                                              |\n| :------------------------- | :------------------------------ | :----------------------------- | :------------------------------------------------------------------ |\n| **`BoolAsSelect`**         | `{Index:true\\|false}`           | `\"{0:is signed\\|is unsigned}\"` | Maps bool to selection string.                                      |\n| **`IntAsSelect`**          | `{Index:=Val:String\\|:Default}` | `\"{0:=1:is\\|:are}\"`            | Matches exact options.                                              |\n| **`IntAsSelect` (Plural)** | `{Index:s}`                     | `\"{0} argument{0:s}\"`          | Prints `\"s\"` if value != 1 (e.g., `\"1 argument\"`, `\"3 arguments\"`). |\n\n### Custom Toolchain Type Mappings\n\nCustom structures can define how they serialize inside diagnostics using the\n`DiagnosticType` tag mapping to `Diagnostics::TypeInfo<StorageType>`:\n\n-   **Identifiers & Names** (declared in `check/diagnostic_helpers.h`):\n    -   `NameId`: Formats raw identifier spelling, safely escaping keyword\n        conflicts under backticks automatically.\n    -   `LibraryNameId`: Formats custom library descriptors cleanly (e.g.\n        `default library` or `library \"foo\"`).\n-   **Sized Primitives**:\n    -   `TypedInt`: Formats an `APInt` constant exactly, extracting target\n        signedness representation automatically from its bound type\n        representation.\n-   **Type Formatter Hierarchy**: When choosing parameter types to print\n    compiler type representations, follow this priority list:\n    1.  **`TypeOfInstId` (Preferred)**: Resolves the backing type of an\n        `InstId`, preserving programmatic aliasing, constraints, and source\n        spelling context. Enclosed under backticks automatically.\n    2.  **`InstIdAsType`**: Converts an `InstId` for a type expression, printing\n        custom type layouts under backticks.\n    3.  **`TypeId` (Fallback)**: Canonical description of the type. **Avoid when\n        possible** because type canonicalization loses intermediate source\n        program spelling and aliasing metadata.\n    4.  **`*AsRawType` (e.g. `InstIdAsRawType`, `TypeIdAsRawType`)**: Formats\n        the type layout exactly like their counter-structures above, but\n        **omits** enclosing backticks (useful when inserting types inside larger\n        code snippets).\n\n---\n\n## 3. Fluent Emission Builders & RAII Scopes\n\n### Fluent Builder Pattern\n\nA diagnostic is one message plus the labels that mark the source explaining it.\nUse `Build` to state the message and `Attach` to mark each place the reader has\nto look, chained fluently:\n\n```cpp\nCARBON_DIAGNOSTIC_LABEL(ModifierPrevious, Info, \"`{0}` previously appeared here\",\n                        Lex::TokenKind);\n\ncontext.emitter()\n    .Build(second_node, ModifierRepeated, context.token_kind(second_node))\n    .Attach(first_node, ModifierPrevious, context.token_kind(first_node))\n    .Emit();\n```\n\nLabels are declared with `CARBON_DIAGNOSTIC_LABEL` where they are attached, and\nare not registered in `kind.def`; `check_diagnostics.py` checks that each one is\nattached and covered. A label is either `Primary` -- the range the message\nitself is about -- or `Info`, for somewhere else the reader must look; those two\nare the only categories, because anything not read against the code it names is\nnot a label. `Attach(loc)` with no label marks a range wordlessly, which is what\nto use when a label would only restate the message.\n\nEvery diagnostic should attach at least one label; a message with nothing\nattached has nothing to show. See\n[diagnostics.md](../../../toolchain/docs/diagnostics.md) for which range to pick\nand when a label earns words.\n\n> [!SAFETY] Emitter builders are marked `[[nodiscard]]`. To prevent a developer\n> from creating a builder but failing to terminal-chain `.Emit()`, the builder\n> uses an rvalue overload `Emit() &&` that triggers a compile-time\n> `static_assert(false)`. You must save the builder to an lvalue or execute the\n> chain exactly as `emitter.Build(...).Attach(...).Emit()`.\n\n### RAII Context & Annotation Scopes\n\nManage large checking structures requiring blanket context using RAII block\nscopes:\n\n-   `ContextScope`: Attaches a context to every diagnostic emitted within its\n    scope, describing the higher-level operation that failed because of it. A\n    context is declared with `CARBON_DIAGNOSTIC_CONTEXT`, or\n    `CARBON_DIAGNOSTIC_SOFT_CONTEXT` for one dropped when the diagnostic\n    already has a context:\n\n    ```cpp\n    Diagnostics::ContextScope diagnostic_context(\n        &context.emitter(), [&](auto& builder) {\n          CARBON_DIAGNOSTIC_CONTEXT(\n              QualifiedDeclInIncompleteClassScope,\n              \"cannot declare a member of incomplete class {0}\", SemIR::TypeId);\n          builder.Attach(loc_id, QualifiedDeclInIncompleteClassScope,\n                         context.classes().Get(class_id).self_type_id);\n        });\n    ```\n\n    A context is not a label: its text stands alone as a sentence, which is why\n    it leads the diagnostic rather than following it.\n\n-   `AnnotationScope`: RAII block scope that attaches labels to every diagnostic\n    emitted within it, using the same `Builder` as a direct emission.\n\n---\n\n## 4. Diagnostics Wording Style Guide\n\nRefer to the official\n[Diagnostic message style guide](../../../toolchain/docs/diagnostics.md#diagnostic-message-style-guide)\nfor complete details.\n\nTo maintain message consistency and integrate cleanly with Clang diagnostics in\ninteroperable code, adhere strictly to these rules:\n\n-   **Start with lowercase and omit periods**: Start diagnostic messages with a\n    lowercase letter or quoted code, and do **not** end them with a period\n    (e.g., `\"cannot convert...\"` or ``\"`self` declared...\"``).\n-   **Use backticks for quoted code**: Enclose identifiers, code constructs, and\n    types inside standard backticks (e.g., ``\"`{0}` is bad\"``).\n-   **Phrase as bullet points without articles**: Phrase diagnostics as\n    descriptive bullet points or sentence fragments rather than full sentences.\n    Leave out standard articles (`a`, `an`, `the`) unless necessary for logical\n    clarity. Semicolons can be used to separate fragments within a message.\n-   **Describe the situation and language rule**: Diagnostics should describe\n    the exact situation the toolchain observed. The language rule violated can\n    be mentioned if it wouldn't otherwise be clear:\n    -   _Situation-only_: `\"redeclaration of X\"` (implies that redeclaration is\n        not permitted).\n    -   _Rule-inclusion_: ``\"`self` declared in invalid context; can only be\n        declared in implicit parameter list\"``.\n-   **Wording Choice (\"cannot\" vs \"allowed\")**: Explicitly avoid `\"allowed\"`,\n    `\"legal\"`, `\"permitted\"`, `\"valid\"`, and related passive wording. You may\n    use `\"cannot\"` if needed, but try to use phrasing that does not require it:\n    -   _Correct_: ``\"`export` in `impl` file\"`` (Avoids `\"allowed\"`)\n    -   _Incorrect_: ``\"`export` is only allowed in API files\"``\n    -   _Correct_: ``\"`extern library` specifies current library\"`` (Avoids\n        `\"cannot\"`)\n    -   _Incorrect_: ``\"`extern library` cannot specify the current library\"``\n-   **Developer Intent Hints**: It is acceptable for a diagnostic to guess at\n    the developer's intent and provide a hint _after_ explaining the situation\n    and the rule, but never as a substitute for that:\n    -   _Correct_: ``\"cannot implicitly convert `i32` to `String`; add `as\n        String` for explicit conversion\"``\n    -   _Incorrect_: ``\"add `as String` to convert `i32` to `String`\"`` (Lacks\n        the core violation message).\n-   **Structure for Tooling API**: Try to structure diagnostics such that\n    parameter inputs can be programmatically extracted without string parsing\n    (prefer strongly-typed parameters over format placeholders where possible).\n\n---\n\n## 5. Diagnostics Testing & Coverage Verification\n\nCarbon strictly enforces testing coverage at build-time.\n\n1.  **Tag Verification Requirement**: Every diagnostic kind declared in\n    `kind.def` (which is not blacklisted in the `UntestedKinds` array under\n    [coverage_test.cpp](../../../toolchain/diagnostics/coverage_test.cpp))\n    **MUST** be verified by at least one testcase file inside\n    `toolchain/*/testdata/`.\n2.  **Stderr Checklist Matchers**: The testcase split verifying the diagnostic\n    must catch it using standard CHECK matchers, explicitly tracking the\n    matching enum tag in standard error comments:\n\n    ```carbon\n    // CHECK:STDERR: fail_bounds.carbon:[[@LINE+1]]:15: error: cannot convert NaN to integer type `i32` [FloatNaNConvertedToInt]\n    let a: i32 = Convert(nan_val);\n    ```\n\n3.  **Build Enforcement**: Failing to provide a diagnostic test check matcher\n    triggers a failure on the target test\n    `//toolchain/diagnostics:coverage_test`.\n4.  **Label Enforcement**: A label is declared where it is attached rather than\n    in a central registry, so `coverage_test` has no list of labels to compare a\n    matched name against and leaves any name that isn't a kind alone.\n    [check_diagnostics.py](../../../toolchain/diagnostics/check_diagnostics.py)\n    is what checks them: it reads the declarations and the testdata directly, so\n    it catches a label with no test, a name matched on that is neither a kind\n    nor a label, and a kind registered in `kind.def` that nothing declares. It\n    runs as a pre-commit hook, which CI runs too, rather than as a bazel test --\n    reading every source file is what it needs and what a test in the sandbox\n    cannot do.\n",".agents/skills/github_cli/SKILL.md":"---\nname: GitHub CLI usage\ndescription:\n    Instructions for using the `gh` command to query and inspect GitHub state\n    safely.\n---\n\n# GitHub CLI usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill provides instructions for using the GitHub CLI (`gh`) to query,\ninspect, and search GitHub state (issues, pull requests, repositories) for the\nCarbon project.\n\n## Safety First: Read-Only Usage\n\n> [!IMPORTANT] AI assistants MUST NOT use the `gh` tool to modify any GitHub\n> project state. Do NOT run commands that create, edit, delete, label, comment\n> on, or merge issues, pull requests, releases, or any other resources.\n\n### Allowed Verbs\n\n-   `list`\n-   `view`\n-   `search`\n-   `status`\n-   `api` (Only with `GET` requests)\n\n### Prohibited Verbs\n\n-   `create`\n-   `edit`\n-   `delete`\n-   `merge`\n-   `reopen`\n-   `close`\n-   `comment`\n-   `label`\n\n## Repository Configuration\n\nThe `gh` tool interacts with a default repository when run within a local check\nout. For this project, the default repository is expected to be\n`carbon-language/carbon-lang`.\n\n### Verifying Default Repository\n\nTo verify the current default repository configuration:\n\n```bash\ngh repo view\n```\n\nThe output should indicate the repository is `carbon-language/carbon-lang`.\n\n### Correcting Misconfigurations\n\nIf the default repository is misconfigured (for example, pointing to a personal\nfork or a different repository), the human operator must correct it.\n\n> [!IMPORTANT] AI Assistants MUST NOT attempt to mutate `gh` configuration or\n> run commands that change the default repository (such as\n> `gh repository set-default`).\n\nInstruct the human operator to run the following command to select the correct\ndefault repository:\n\n```bash\ngh repo set-default\n```\n\nThe operator will be prompted to select the correct repository (e.g.,\n`carbon-language/carbon-lang`) from the available remotes.\n\n## Common Query Commands\n\n### Issues\n\n-   **List issues**: `gh issue list`\n-   **View specific issue**: `gh issue view <number>`\n-   **Search issues**: `gh issue search \"<query>\"`\n    -   Example: `gh issue search \"crash\" --state open`\n\n### Pull Requests\n\n-   **List PRs**: `gh pr list`\n-   **View specific PR**: `gh pr view <number>`\n-   **View PR diff**: `gh pr diff <number>`\n-   **Check PR status**: `gh pr status`\n\n### Search\n\n-   **Search code**: `gh search code \"<query>\"`\n-   **Search repositories**: `gh search repos \"<query>\"`\n\n## Advanced Usage: GitHub API\n\nFor queries that are not supported by standard `gh` commands, you can use the\n`gh api` command to query the GitHub REST or GraphQL APIs.\n\n### REST API\n\nQuery the REST API using paths relative to the API root.\n\n-   **List contributors**:\n\n    ```bash\n    gh api repos/carbon-language/carbon-lang/contributors\n    ```\n\n-   **List issue comments**:\n\n    ```bash\n    gh api repos/carbon-language/carbon-lang/issues/<issue_number>/comments\n    ```\n\n### GraphQL API\n\nFor complex queries, use GraphQL to fetch exactly the data needed.\n\n-   **Get repository information**:\n\n    ```bash\n    gh api graphql -f query='\n      query {\n        repository(owner: \"carbon-language\", name: \"carbon-lang\") {\n          description\n          stargazerCount\n        }\n      }\n    '\n    ```\n\n### Pagination\n\nUse the `--paginate` flag to automatically fetch all pages of results.\n\n```bash\ngh api --paginate repos/carbon-language/carbon-lang/issues\n```\n\n### Filtering and Formatting\n\nUse `--json` to request JSON output, and `--jq` or `--template` to filter or\nformat the results.\n\n-   **List PR titles and authors**:\n\n    ```bash\n    gh pr list --json title,author --jq '.[] | \"\\(.title) by \\(.author.login)\"'\n    ```\n\n-   **Format with Go templates**:\n\n    ```bash\n    gh issue list --template '{{range .}}{{.number}} - {{.title}}{{\"\\n\"}}{{end}}'\n    ```\n\n## Documentation References\n\n-   **GitHub CLI Manual**:\n    [cli.github.com/manual](https://cli.github.com/manual/)\n-   **GitHub REST API Documentation**:\n    [docs.github.com/en/rest](https://docs.github.com/en/rest)\n-   **GitHub GraphQL API Documentation**:\n    [docs.github.com/en/graphql](https://docs.github.com/en/graphql)\n",".agents/skills/github_issues/SKILL.md":"---\nname: Accessing GitHub issues\ndescription:\n    Instructions for safely viewing and accessing GitHub issues by way of\n    command line.\n---\n\n# Accessing GitHub issues\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill provides instructions for AI assistants on how to access and view\nGitHub issues. Agents should strongly prefer using the command line `gh` tool to\naccess and view the contents of issues rather than viewing their contents by way\nof a web browser.\n\n## Safety First\n\n> [!IMPORTANT] AI assistants MUST NOT modify any GitHub issue state. Only use\n> read-only access commands like `view` or `list`. Do NOT comment, edit, create,\n> close, or delete issues.\n\n## Accessing Issues\n\nAgents must use this skill to access issues regardless of how they are mentioned\n(for example, by URL or by issue number).\n\n### Basic View\n\nTo view an issue in the current default repository (expected to be Carbon):\n\n```bash\ngh issue view <issue_number>\n```\n\n### Including Full Context (All Comments)\n\nTo ensure the view includes the entire context of the issue, always include the\n`--comments` flag to dump all comments:\n\n```bash\ngh issue view <issue_number> --comments\n```\n\n> [!TIP] If the issue is extremely large and comments are truncated, or you need\n> to process comments programmatically, use the JSON output with `jq`:\n>\n> ```bash\n> gh issue view <issue_number> --json comments --jq '.comments[].body'\n> ```\n\n### Accessing Issues in Other Repositories\n\nTo view an issue in another repository (for example, LLVM), use the `-R` or\n`--repo` flag to specify the repository:\n\n```bash\ngh issue view <issue_number> -R <owner>/<repo> --comments\n```\n\nExamples:\n\n-   **LLVM Issue**:\n\n    ```bash\n    gh issue view 5678 -R llvm/llvm-project --comments\n    ```\n\n-   **Carbon Issue (Explicit)**:\n\n    ```bash\n    gh issue view 1234 -R carbon-language/carbon-lang --comments\n    ```\n\n## Mentions via URL\n\nIf an issue is mentioned via URL, parse the URL to extract the repository owner,\nrepository name, and issue number.\n\n-   **URL pattern**: `https://github.com/<owner>/<repo>/issues/<number>`\n-   **Extraction**:\n    -   Host: `github.com`\n    -   Owner: `<owner>`\n    -   Repo: `<repo>`\n    -   Number: `<number>`\n\nRun the command specifying the repository:\n\n```bash\ngh issue view <number> -R <owner>/<repo> --comments\n```\n",".agents/skills/jj/SKILL.md":"---\nname: Jujutsu (jj) usage\ndescription:\n    Instructions for using Jujutsu (jj) for version control in the Carbon\n    repository.\n---\n\n# Jujutsu (jj) usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Jujutsu](https://github.com/jj-vcs/jj) is a Git-compatible version control\nsystem that may be used in Carbon checkouts.\n\n> [!IMPORTANT] You can detect if Jujutsu is in use by checking for a `.jj`\n> directory in the repository root. If present, you **must** use `jj` and **must\n> not** use `git`. If absent, you **must not** use `jj`.\n\n## General usage\n\nAlways use the `--no-pager` flag when invoking `jj` to prevent the command from\nblocking or waiting for terminal paging.\n\n## Common commands\n\n### Syncing with remote\n\n-   **Fetch from remote**: `jj --no-pager git fetch`\n-   **Create a new change on top of trunk**: `jj --no-pager new trunk`\n-   **Show repository status**: `jj --no-pager status`\n-   **Show commit history**: `jj --no-pager log`\n\n### Managing changes\n\n-   **View diff of current changes**: `jj --no-pager diff`\n-   **Commit changes**: `jj --no-pager commit`\n    -   _Note_: Prefer using `jj commit` over the combination of `jj describe`\n        and `jj new`.\n-   **Abandon/discard current changes**: `jj --no-pager abandon`\n-   **Rebase current change onto trunk**: `jj --no-pager rebase -o trunk`\n\n### Working with a stack of changes\n\nA change is often built as a stack of commits sent up as a single pull request.\nThe stack is not necessarily based on `trunk`; it may be based on another change\nthat is itself still in flight.\n\n> [!WARNING] **Never rewrite the history of a change that has been submitted as\n> a pull request.** Reviewers track a PR by its commits, and squashing,\n> reordering, or abandoning them discards review that is already in progress.\n> This cannot be undone from their side.\n>\n> Before rewriting history in any other case, propose the exact command and wait\n> for confirmation. This applies to `squash`, `rebase`, `abandon`, and\n> `describe` on an existing change.\n\n#### Finding the base of the stack\n\nBookmarks delimit the stack. List the bookmarks that are ancestors of the\nworking copy, nearest first:\n\n```bash\njj --no-pager log -r '::@ & bookmarks()'\n```\n\nReading the result takes care, because two situations produce similar output:\n\n-   **Editing an existing change.** The nearest bookmark names the change being\n    worked on, and the bookmark below it is the base.\n-   **Starting a new change.** The commits above the nearest bookmark have no\n    bookmark of their own yet, so the nearest bookmark is itself the base.\n\n`trunk` is only ever a base. Finding `trunk` nearest means new work is being\nbuilt on top of it, never that `trunk` itself is being worked on.\n\nThe graph does not distinguish the two cases: an unbookmarked or empty commit\nabove a bookmark may be the next commit of that change or the start of a new\none. Ask which it is when it is not clear, and ask before choosing where a fix\nshould land rather than after. Guessing wrong means squashing into a change that\nmay already be under review.\n\nOnce the base is known, use it to scope commands to the current stack:\n\n```bash\njj --no-pager log -r '<base-bookmark>..@'\n```\n\n#### Managing the stack\n\n-   **Fold a fix into an earlier change**:\n    `jj --no-pager squash --into <change-id> [path]`. Follow-up fixes and\n    formatter reflows belong in the change that introduced the code, not in a\n    trailing \"fixes\" commit, unless that change has already been submitted.\n    Naming a path squashes only that part of the working copy, leaving unrelated\n    work in place.\n-   **Descriptions**: only one change in the stack needs a long description, the\n    one used as the pull request description. Every other change gets a short\n    one-line summary. Do not repeat the long text across the stack.\n",".agents/skills/language_server/SKILL.md":"---\nname: Language server\ndescription:\n    Instructions for working on Carbon's LSP language server, including its\n    architecture, its file_test-based tests, and the VS Code extension.\n---\n\n# Language server\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Introduction\n\nThis skill covers [`toolchain/language_server/`](/toolchain/language_server/),\nwhich implements `carbon language-server`, and\n[`utils/vscode/`](/utils/vscode/), the VS Code extension that launches it.\n\n## Architecture\n\nThe server is built on clangd's LSP transport (`clang::clangd`), not on a\nCarbon-specific one. That means clangd's `Protocol.h` types (`Position`,\n`Range`, `Location`, `Hover`, `MarkupContent`) are the interface currency.\n\n-   `server.cpp` / `incoming_messages.cpp`: message dispatch. A handler must be\n    registered in `incoming_messages.cpp` before it can be called.\n-   `handle_*.cpp`: one file per request family, each declaring its entry point\n    in `handle.h`.\n-   `handle_initialize.cpp`: the advertised capabilities. **Adding a capability\n    changes `Content-Length` in every test that calls `initialize`**, so expect\n    a large autoupdate diff.\n-   `context.h` / `context.cpp`: `Context::File` per open document, plus the\n    compile driver. `Context::File::unit()` has a `CARBON_CHECK` on the compile\n    driver, so any handler that reaches for the parse tree must first rule out\n    documents that were never compiled.\n-   `position.h`, `sem_ir_index.h`: mapping source positions to SemIR\n    instructions for real Carbon files.\n-   `sem_ir_text.h`, `handle_sem_ir_text.h`: navigation within the *formatted\n    SemIR* in a test file's `// CHECK:STDOUT:` lines. This is a heuristic text\n    index, deliberately independent of the real SemIR data structures. See\n    [the SemIR text reader](#the-semir-text-reader).\n\n### Document kinds\n\nThe server handles two kinds of document, distinguished by the `languageId`\nfrom `textDocument/didOpen`, with a content sniff as a fallback:\n\n-   `carbon`: a real Carbon file. Compiled; diagnostics published.\n-   `carbon-testdata`: a test file. **Not compiled**, because we lack logic to\n    split it into one file per `// ---` split marker.\n\n> [!IMPORTANT]\n> A handler that assumes every file was compiled will crash on a test file.\n> When adding one, give the test-file path an explicit early return.\n\n## Tests\n\nThere is **no language-server-specific test target**.\n`toolchain/language_server/BUILD` only declares\n`filegroup(name = \"testdata\")`, which is pulled into\n`//toolchain/testing:all_testdata` and run by `//toolchain/testing:file_test`.\n\n```bash\n# Run just the language server tests (or any subset).\nbazelisk test //toolchain/testing:file_test \\\n    --test_arg=--file_tests=toolchain/language_server/testdata/position/hover_and_goto.carbon\n\n# See the raw output, which is much easier to read than a test failure.\nbazelisk run //toolchain/testing:file_test -- --dump_output \\\n    --file_tests=toolchain/language_server/testdata/position/hover_and_goto.carbon\n\n# Update expectations. Never hand-write CHECK lines.\n./toolchain/autoupdate_testdata.py toolchain/language_server/testdata/...\n```\n\nThese tests run serially, because clangd's logging is a global singleton.\n\n### Test file shape\n\nThe request stream is a `// --- STDIN` split written with the `[[@LSP-*]]`\nkeywords, and the responses land in a trailing `// --- AUTOUPDATE-SPLIT`.\nDocuments come from other splits by way of `\"text\": \"FROM_FILE_SPLIT\"`, which\nis substituted with the content of the split whose name matches the `uri`.\n\n```carbon\n// --- position.carbon\nfn Abs(n: i32) -> i32 { return n; }\n\n// --- STDIN\n[[@LSP-CALL:initialize:\"capabilities\": {}]]\n[[@LSP-NOTIFY:textDocument/didOpen:\n  \"textDocument\": {\n    \"uri\": \"file:/position.carbon\",\n    \"languageId\": \"carbon\",\n    \"text\": \"FROM_FILE_SPLIT\"\n  }\n]]\n[[@LSP-CALL:textDocument/hover:\n  \"textDocument\": {\"uri\": \"file:/position.carbon\"},\n  \"position\": {\"line\": 0, \"character\": 3}\n]]\n[[@LSP-CALL:shutdown]]\n[[@LSP-NOTIFY:exit]]\n\n// --- AUTOUPDATE-SPLIT\n```\n\nFull keyword documentation is in\n[`testing/file_test/README.md`](/testing/file_test/README.md).\n\n### Traps\n\n> [!WARNING]\n> **A blank line inside the `STDIN` split breaks the JSON transport.** It\n> terminates a header block, so clangd logs a timestamped\n> `Warning: Missing Content-Length header, or zero-length message.` The\n> timestamp makes the test unreproducible, so it fails on the next run.\n> Comment lines between messages are fine; blank lines are not. A single blank\n> line immediately before `// --- AUTOUPDATE-SPLIT` is also fine.\n\nOther things worth knowing:\n\n-   **`positionEncoding` is UTF-16.** A `character` is a UTF-16 code unit\n    offset, not a byte offset.\n-   **Line and character numbers in requests are 0-based**, while the `locN_M`\n    suffixes in SemIR output are 1-based. Off-by-ones here are silent: the\n    request succeeds and returns the wrong thing.\n-   **A split can hold a document that itself contains `// CHECK:STDOUT:`\n    lines**, because `CHECK` lines only form expectations inside the\n    `AUTOUPDATE-SPLIT`. Such a document still can't contain a literal `// ---`\n    line, which would split the enclosing test file; write it as\n    `[[@0x2f]]/ --- name.carbon`.\n\n## The SemIR text reader\n\n`sem_ir_text.cpp` indexes the formatted SemIR inside a test file's\n`// CHECK:STDOUT:` lines so that hover and go-to-definition work on operand\nnames. It is a heuristic reader, not a parser, and its correctness rests on\nfacts about `toolchain/sem_ir/formatter.cpp` and\n`toolchain/sem_ir/inst_namer.cpp`. Re-check these if the formatter changes:\n\n-   There are exactly four scope keywords: `file`, `generated`, `imports`, and\n    `constants` (`InstNamer::GetScopeName`). Everything else is `@entityname`.\n-   A reference is `%name` within its own scope and `scope.%name` otherwise\n    (`InstNamer::GetNameFor`). Names may contain `.` and may _start_ with one,\n    as in `%.Self.frozen`.\n-   **Type annotations are printed in the `constants` scope.**\n    `Formatter::FormatTypeOfInst` does\n    `llvm::SaveAndRestore file_scope(scope_, InstNamer::ScopeId::Constants)`,\n    so in `%x: %foo = ...` a bare `%foo` means `constants.%foo`. This does not\n    apply to ordinary operands or to `[concrete = ...]` annotations.\n-   **`*_decl` braces hold the declared entity's scope.** The braces of\n    `%F.decl: ... = fn_decl @F [...] { ... } { ... }` are lexically inside\n    `file { }`, but their names belong to `@F`.\n-   **`!with Self:` switches scope without a brace**, until `!members:`\n    switches it back. Brace counting alone cannot see this.\n-   A `specific @F(args) { }` block uses `@F`'s scope and defines nothing; each\n    `%name => value` row references an instruction of the generic.\n\n### Validating a change to the reader\n\nThe unit tests only cover a handful of cases. To check a change against the\nreal corpus, drive the server over a sample of check testdata, hovering on\nevery `%name`, and compare the resolved fraction before and after. Roughly 99%\nof names resolve; the residue are names the formatter references but never\nemits a definition line for, such as `%I.WithSelf.F`, which only ever appears\ninside a `[symbolic = ...]` annotation.\n\nTwo things to get right in such a harness:\n\n-   Feed the request stream from a **file**, not a pipe. The server reads stdin\n    as a file and reports `error: Input/output error` on a pipe.\n-   Read the output as **bytes**. Python's `text=True` rewrites the `\\r\\n`\n    framing, and `Content-Length` counts bytes.\n\n## VS Code extension\n\n[`utils/vscode/`](/utils/vscode/) declares three languages in `package.json`:\n\n| Language id      | Applies to                        |\n| ---------------- | --------------------------------- |\n| `carbon`         | `*.carbon`                        |\n| `carbon-testdata`| `**/testdata/**/*.carbon`         |\n| `semir`          | `*.semir`                         |\n\n> [!NOTE]\n> The TextMate _scope_ for SemIR is `source.carbon-semir`, but the\n> _language id_ is `semir`. Markdown code fences in hover text resolve language\n> ids, so a fence must say ` ```semir `.\n\n`extension.ts` launches the server over stdio, using the `carbonPath` setting\n(default `./bazel-bin/toolchain/carbon`). Its `documentSelector` controls which\nfiles are sent to the server at all; a new document kind has to be added there\nas well as in the server.\n",".agents/skills/prek/SKILL.md":"---\nname: Prek\ndescription:\n    Instructions for running prek, the Carbon pre-submit/style/lint checker,\n    that *MUST* be run before submitting an change.\n---\n\n# Prek\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n`prek` is the Carbon pre-submit, style, and lint checker. Running it is\nmandatory before submitting any changes.\n\n## Running prek\n\nTo run `prek` on all files:\n\n```bash\nprek run -a\n```\n\nTo validate a specific list of files:\n\n```bash\nprek run --files <files>\n```\n\n## Running prek in a Jujutsu (jj) workspace\n\nIf you are working in a Jujutsu workspace, running `prek` directly will fail\nbecause it expects a standard Git repository structure. Instead, use the helper\nscript:\n\n```bash\n./scripts/jj_prek.sh\n```\n\nThis script runs `prek` on all files that have changed between `trunk` and your\ncurrent Jujutsu `@` change.\n\nNote that the script always compares against `trunk`. If your change is based on\nanother bookmark rather than on `trunk`, the script also checks the files\nchanged by that underlying change, so a reported failure may not be in your own\nwork.\n\n## Hooks that rewrite files\n\nSome hooks, notably `clang-format` and `rumdl`, fix problems in place rather\nthan only reporting them. When they do, `prek` reports a failure and exits\nnon-zero even though the tree is now correct.\n\nRe-run `prek` after any failure that modified files, and treat the second, clean\nrun as the result. Review what it changed: a reflow is expected, but a content\nchange may not be what you intended.\n\n## Prek dependency errors\n\n> [!TIP] If `prek` fails with an error about resolving dependencies or security\n> policy, you may be running in a restricted environment where the\n> special-purpose `gpkg` tool is required. Prefix the command with `gpkg`, for\n> example: `gpkg prek run -a` or `gpkg ./scripts/jj_prek.sh`.\n",".agents/skills/proposals/SKILL.md":"---\nname: Proposals\ndescription:\n    Instructions for writing, submitting, and managing Carbon evolution\n    proposals.\n---\n\n# Proposals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Overview\n\nThis skill provides instructions and best practices for working with proposals.\nOnly create a proposal when explicitly directed as part of the task.\n\nMake sure to confirm the desired title for the proposal as that will govern the\nfilename.\n\n## Create a new proposal\n\n1.  **Use the helper script**: Run `./proposals/scripts/new_proposal.py \"Title\"`\n    to create a templated file and instructions for setting up the PR.\n2.  **Proposal file**: The file will be named `proposals/p######-title.md`,\n    where `######` is the 6-digit GitHub pull request number and `title` is a\n    slugified version of the proposal title.\n3.  **Template**: Follow the structure in `proposals/scripts/template.md`,\n    noting the specific `TODO` instructions in each section for the content that\n    should be included there.\n4.  **PR description**: Update the pull request description to match the\n    abstract section in the proposal document.\n\n> [!IMPORTANT] Do _not_ mark the PR ready for review. The user must have the\n> opportunity to review the proposal produced before asking for any review.\n\n## Writing style and best practices\n\n-   **Skimmable**: Use\n    [BLUF](<https://en.wikipedia.org/wiki/BLUF_(communication)>) (Bottom Line Up\n    Front) or\n    [Inverted Pyramid](<https://en.wikipedia.org/wiki/Inverted_pyramid_(journalism)>)\n    style. Keep it brief, focused, and technical.\n-   **Match existing proposal style**: Review [existing proposals](/proposals)\n    (preferring more recent ones with higher numbers) to understand the expected\n    style, wording, and nature of content to include.\n-   **Connect to goals**: In the Rationale section, link to specific goals in\n    [`/docs/project/goals.md`](/docs/project/goals.md) and principles in\n    [`/docs/project/principles`](/docs/project/principles) (e.g.,\n    `error_handling.md`, `one_way.md`).\n-   **Living design**: If the proposal updates design documentation, include\n    those changes in the PR if possible. If deferred, add \"TODO\" comments\n    pointing to the proposal (e.g., `> **TODO:** Document ... adopted in\n    [p######](/proposals/p######-title.md)`). For pervasive changes, file a\n    GitHub issue instead of adding many TODOs.\n\n## Alternatives considered and leads decisions\n\nThere are always alternatives to a proposal, and the proposal should carefully\ninclude sections describing all of them and the rationale for not selecting\nthem. Any living design document updates should focus on fully describing the\nend-state design, and the key motivating aspects of that design. The main\nproposal should focus on _what is changing_ and _why it is changing_, and should\nleave detailed description of the resulting design to the living design\ndocument, and _why not_ rationale to the description of each alternative.\n\n-   **Cover all the alternatives**: Make sure to describe any alternatives\n    considered, even if minor or rejected early.\n-   **Be specific**: Don't be vague about any of the alternatives, or the\n    rationale for not choosing them.\n-   **Connect to goals or principles**: In addition to the rationale section,\n    one of the best rationale structures for rejecting an alternative connects\n    that choice back to the goals or principles relevant.\n-   **Always frame as a tradeoff**: Selecting the proposed direction instead of\n    an alternative is _always_ a tradeoff, with both advantages and\n    disadvantages.\n-   **Where relevant, cite the leads issue** that decides against an\n    alternative, in addition to summarizing the key points, tradeoffs, and\n    rationale for the decision.\n\n> [!IMPORTANT] Don't just list the alternatives, create a sub-section for each\n> alternative and carefully describe the alternative, the advantages,\n> disadvantages and what the core of the decision is to reject each alternative.\n\n> [!IMPORTANT] Carefully research each alternative in the leads issue in order\n> to provide this clear and comprehensive explanation.\n\n## Building from a leads issue\n\nSometimes a proposal is specifically documenting and formalizing a decided leads\nissue. When this is the case, carefully research that leads issue, reading the\noriginal issue text and every comment on the issue. Also read any linked Google\ndocuments, linked issues, examples, gists, or other supplemental information\ncited.\n\n-   **Summarize the leads issue**: Ensure you provide a high level summary of\n    the _decided_ direction of the leads issue as the proposal.\n-   **Capture and document** every key aspect of the decision made and factor\n    that led to the decision. It is important that the proposal stands alone,\n    and the leads issue is merely cited for context and history.\n-   **Stay grounded**: Only include alternatives, rationale, and arguments based\n    on what you find in the issue and related documents. No new information\n    should be in the proposal.\n\nUse the `gh` command line tool to query leads issues in order to carefully\nexamine all of the comments. Follow any mentioned links to gather more data.\nRefer to the [GitHub CLI usage skill](/.agents/skills/github_cli/SKILL.md) for\ndetailed instructions on using the `gh` tool.\n\nAsk the user to clarify any aspects of the leads issue that are unclear rather\nthan continuing to edit the proposal. If there are questions that you don't find\nan answer to in the issue, ask this to the user and let them provide an answer\nthat you use as the basis of what to include.\n\n## Examples are golden\n\nHeavily leverage examples to illustrate both the specifics of the design being\nproposed, and the nature of the change being proposed. More examples to\nillustrate more aspects, corner cases, or provide a more complete understanding\nare almost always good. Comments in example code should focus on what that part\nof the example illustrates from the proposal.\n\n## Keep the PR description in sync with the abstract\n\nWhenever you edit the abstract or notice differences from the PR description,\nyou should update the PR description to match the abstract. The only exception\nis to retain any \"Assisted-by\" or other tags at the end of the description that\nare only needed there and not in the abstract.\n\nIf you are creating or updating a proposal, make sure the PR description in\nquestion contains an `Assisted-by:` tag that is appropriate for describing which\nAI tool is being used.\n",".agents/skills/review_testdata_changes/SKILL.md":"---\nname: Review testdata changes\ndescription:\n    Instructions for judging whether changes to file test output\n    (`// CHECK:STDOUT:` and `// CHECK:STDERR:` lines) are correct, which\n    changes are acceptable churn, and which are regressions in disguise.\n---\n\n# Review testdata changes\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Introduction\n\nMost toolchain work moves file test output. `./toolchain/autoupdate_testdata.py`\nrewrites the `// CHECK:STDOUT:` and `// CHECK:STDERR:` lines in\n`toolchain/*/testdata/` to match current behavior, so after running it the tests\npass again whether or not the new behavior is right. Deciding that the new\noutput is the output you wanted is a separate, manual step, and it is the step\nthis skill covers.\n\nThree skills divide the work:\n\n-   [Toolchain tests](../toolchain_tests/SKILL.md): how to _author_ tests and\n    generate their output.\n-   This skill: how to _judge_ an output diff.\n-   [Summarize testdata changes](../summarize_testdata_changes/SKILL.md): how to\n    _report_ an output diff once you believe it is correct.\n\n> [!IMPORTANT] Never hand-edit `// CHECK:STDOUT:` or `// CHECK:STDERR:` lines.\n> Everything below is about changing the _code_ until the generated output is\n> right, never about editing the output to match the code.\n\n## The rule that generates all the others\n\n**Every line of testdata churn must have a cause you can name.** Not \"it is\nsimilar to the other changes\", not \"the tests pass now\" — an actual sentence\nsaying which code change produced it and why that is the intended result.\n\nA diff you cannot narrate is a diff you have not reviewed. Changes you cannot\nexplain are where regressions hide, because a regression and an intended change\nlook exactly alike once the autoupdater has written them down.\n\n> [!CAUTION] Autoupdating is destructive to your evidence. Once the autoupdater\n> has run, the previous expectations are gone from the working copy. Read the\n> diff after _every_ autoupdate run, and if something changed for a reason you\n> cannot name, fix the code before autoupdating again. Recovering the old\n> expectations later means reverting and re-running.\n\n## STDERR and STDOUT are different kinds of evidence\n\nTreat them separately; they have different standards of proof.\n\n**STDERR is user-visible behavior.** These are the diagnostics a Carbon\nprogrammer sees. A change here is a change to the language implementation as\nusers experience it, so each one needs an individual justification. For a\nrefactoring, the expected STDERR diff is empty.\n\n**STDOUT is internal representation.** SemIR dumps, parse trees, LLVM IR. Users\nnever see it. Churn here is normal and often unavoidable, so the standard is not\n\"no change\" but \"no change I cannot account for\".\n\nFor a change that is supposed to preserve behavior, write the list of accepted\nSTDERR changes down _before_ you autoupdate, and keep it current. Order matters\nmore than form: written first, the list is a prediction the diff can falsify;\nwritten afterwards, it is a description of whatever happened, and describes a\nregression exactly as well as an intended change.\n\nThe list does not have to be a deliverable. Scratch notes you never publish do\nthe job, because the work is in committing to the list, not in presenting it.\nWhat a reader needs is not the list but its exceptions: diagnostics that changed\nwithout being predicted, and predictions that did not occur. Both are findings.\nThe matches are not, and reporting them buries the two entries that matter.\n\n## Judging STDOUT churn\n\nSort each STDOUT change into mechanical or structural.\n\n### Mechanical churn\n\nExpected, and cheap to accept in bulk once you have confirmed the pattern:\n\n-   **Renaming.** An instruction, type, or scope prints under a new name.\n-   **Positional name renumbering.** Names like `%x.loc18_46.3` embed a line,\n    column, and disambiguating index. Two different events move them:\n    -   Adding or removing an instruction at a location renumbers the rest, so a\n        _single_ removed instruction can show up as many changed lines in the\n        same block. Confirm the cascade is a cascade before accepting it as one.\n    -   Adding or removing a _diagnostic_ moves the source lines themselves, so\n        the line component changes everywhere below it in the file. See\n        [Autoupdate to a fixed point](#autoupdate-to-a-fixed-point).\n-   **Fingerprint-derived names.** Mangled names and some scope names are\n    derived from a hash of their inputs. If you changed a hashed input, these\n    move. Confirm that each such difference is _only_ the fingerprint, and not a\n    fingerprint difference concealing a structural one.\n\n> [!TIP] Mechanical churn is usually wide and shallow: the same substitution,\n> repeated across many files. If a \"mechanical\" pattern needs a different\n> explanation in each file, it is not mechanical.\n\n### Structural churn\n\nEach of these needs its own explanation:\n\n-   Instructions appearing or disappearing.\n-   Changed `[concrete = ...]`, `[symbolic = ...]`, or other constant-value\n    annotations.\n-   Changed types on existing instructions.\n-   Changed control flow: new or removed blocks, changed branch targets.\n-   Raw instruction ids renumbering in `--dump-raw-sem-ir` output when you did\n    not intend to change the id layout.\n\n## Fewer instructions is not automatically better\n\nA diff that removes instructions looks like an optimization. Whether it is one\ndepends on what the changed function owes its caller, and two functions can\nproduce the same shrinking diff for opposite reasons:\n\n-   A function that only needs a constant value, but built instructions on the\n    way to it, was doing wasted work. Dropping them and using the constant\n    directly is correct, and the shorter output reflects that.\n-   A function whose caller needs a **non-canonical instruction** can be made\n    shorter the same way, by using the constant instead of creating an\n    instruction of its own — and that is wrong. The instruction carries location\n    information, and symbolic constant substitution operates on it; the constant\n    value alone loses both.\n\nThe instruction count is identical evidence in both cases, so it cannot be the\nthing you judge. Decide what the function is required to produce; the count\nfollows from that.\n\nThe same reasoning runs in reverse: a diff that _adds_ instructions is not\nautomatically a regression.\n\n## Judging STDERR churn\n\n### A diagnostic's authority depends on the file's prefix\n\nThe `fail_` and `todo_` prefixes (see\n[Toolchain tests](../toolchain_tests/SKILL.md)) say how much the recorded\ndiagnostics are worth:\n\n-   **`fail_...`** — the test should and does produce errors. The recorded\n    diagnostic **is the specification**. Changing it is a user-visible behavior\n    change and needs justification on its own merits.\n-   **`fail_todo_...`** — the test produces errors (or crashes) but shouldn't,\n    or produces the wrong errors. The recorded diagnostic is explicitly **not**\n    the specification; the file exists to record that today's behavior is wrong.\n    Changing it replaces one wrong answer with another. That is acceptable when\n    you can say why the new message follows from your change and why it is no\n    further from the intended eventual behavior — which, for many such files, is\n    no diagnostic at all.\n-   **`todo_fail_...`** — the test should produce errors but does not. Gaining a\n    diagnostic here may be _progress_, not a regression. Either way the file\n    must be renamed, since the framework requires a `fail_` prefix on any file\n    that errors: `fail_...` if it now produces the right error, `fail_todo_...`\n    if the error is the wrong one. Both renames make the test pass, so record\n    which case it is instead of letting the rename settle it.\n-   **`todo_...`** — behavior is wrong but produces no errors, and shouldn't.\n    Gaining a diagnostic here is a regression unless you can argue otherwise.\n\n> [!IMPORTANT] This is a reason to look at the _filename_ before judging a\n> diagnostic change, not a license to ignore `todo_` files. \"It was already\n> broken\" does not excuse making it differently broken for no reason.\n\n### Reclassifying tests\n\nIf your change moves a test between the states above, the prefix must move with\nit: when the test is fixed, when it starts failing, and when it starts failing\ndifferently. The correspondence between the `fail_` prefix and whether\ncompilation actually failed is enforced by the test framework, not by the\nautoupdater, so it surfaces when you run `bazelisk test` and not when you\nautoupdate. **Autoupdating is not a substitute for running the tests.**\n\nOnly that half of the name is checked. Nothing enforces `todo_`, so a file whose\nbehavior you have just fixed can keep its `todo_` prefix indefinitely and still\npass. A missing `fail_` stops the build; a stale `todo_` is silent, and is yours\nto catch.\n\nWhen a fix drops a file's prefix, also check that the file still belongs where\nit is and that its comments do not still describe the old broken behavior.\n\n### Vaguer diagnostics are a signal, not a verdict\n\nWhen a diagnostic becomes less specific — a general \"unsupported\" message\nreplacing one that named the problem — that usually means a code path stopped\nfinding information it previously had. Sometimes that is correct: the\ninformation was misleading, and the old message was confidently wrong.\n\nDo not accept it silently and do not reject it reflexively. Say which direction\nit moved and whether the new message is closer to or further from the eventual\nintended behavior.\n\n## Signals in the shape of the diff\n\n### Zero churn is a result\n\nIf you removed something you believed was doing work and _no_ testdata moved,\nthat is not a missing test run — it is the proof that the thing was a no-op.\nSay so explicitly; it is one of the strongest pieces of evidence a refactoring\ncan produce.\n\nThe converse is also informative. If you expected a path to churn and it didn't,\neither your model of the code is wrong or that path is untested. Find out which,\nand consider adding a test before continuing.\n\n### Churn should be proportional to the change\n\n-   **Wide churn from a narrow change** means your model of the code is wrong.\n    Do not autoupdate over it. Find the structural mistake first.\n-   **Narrow churn from a sweeping change** means the affected paths are\n    probably untested.\n\nSet a rough expectation for the size of the diff before you run the autoupdater,\nand treat a large mismatch in either direction as a finding.\n\n### Never make the diff smaller by weakening the test\n\nEditing test _input_ (the Carbon source, not the CHECK lines) to make a diff\nlook better is a behavior change in disguise. Deleting a test that now produces\nawkward output is worse. If a test's input has to change, that is a separate,\nexplicitly-justified change, not diff cleanup.\n\n## What the autoupdater will not fix for you\n\n-   **`NOAUTOUPDATE` files.** Their expectations are maintained by hand. They\n    fail under `bazelisk test` rather than being silently rewritten.\n-   **Hand-written C++ expectations**, for example golden output asserted in a\n    `_test.cpp`. When several assertions in one of these break together, often\n    only the first failure is reported, so fixing it can reveal another. Re-run\n    until clean rather than assuming one fix was the whole repair.\n-   **Golden files outside `testdata/`**, and documentation that quotes compiler\n    output.\n\n## Review loop\n\n### Run the autoupdater\n\nAutoupdate everything, then read the diff a directory at a time. Passing no\npaths is the default and updates every file test in the toolchain:\n\n```bash\n./toolchain/autoupdate_testdata.py\n```\n\nNarrow the scope only while iterating on one subdirectory you know you are not\ndone with, where each round would otherwise regenerate output you have already\nread:\n\n```bash\n./toolchain/autoupdate_testdata.py toolchain/check/testdata/SUBDIR/**/*\n```\n\nThe globs are expanded by the shell; the script filters its arguments to\n`.carbon` files under a `testdata/` directory.\n\n> [!TIP] If intermediate states crash on `CARBON_CHECK` failures, pass\n> `--non-fatal-checks` so you can see the full set of downstream damage in one\n> run instead of one crash at a time.\n\n> [!IMPORTANT] Return to the full scope before judging the diff. Whether churn\n> is proportional to the change, and whether a change to one phase moved another\n> phase's testdata, are only visible across everything.\n\n### Autoupdate to a fixed point\n\nOne pass is not always enough, because the autoupdater's output is part of its\nown input. `// CHECK:STDERR:` lines sit inline, immediately above the source\nline they describe, and the compiler reads them as comments in the file.\nGaining or losing a diagnostic therefore moves every source line below it.\n\nWithin a single run, the compiler has already read the file as it was, so the\ntwo kinds of output end up in different states:\n\n-   **STDERR is correct after one pass.** These lines locate themselves\n    relatively, as `[[@LINE+N]]`, and the autoupdater recomputes `N` as it\n    places them.\n-   **STDOUT is stale after one pass.** SemIR names like `%x.loc18_46.3` embed\n    an absolute line and column with no filename attached, and the autoupdater\n    only remaps `file.carbon:18`-style references. Nothing rewrites the `loc`,\n    so it still describes where the instruction was _before_ the diagnostic\n    lines moved it.\n\nRunning again compiles the shifted file and the names catch up. The diagnostic\nset does not change this time, so nothing shifts again and a third run is a\nno-op. Keep running the autoupdater until it stops changing files: one pass when\nthe diagnostics held still, two when they didn't.\n\n> [!WARNING] The intermediate state is self-inconsistent, not just unfinished:\n> its `loc` names describe a file layout that no longer exists. Keep reading the\n> diff after every run — that rule does not change — but do not chase positional\n> churn to a cause until the file has converged, and do not present the diff\n> until then either.\n\nThe converging pass should be positional renumbering and nothing else. If it\nmoves an instruction, a type, or a constant value, then something other than a\n`loc` name is sensitive to where lines fall in the file. Find out what before\naccepting it.\n\nThe file tests do catch a file left unconverged, since each test re-runs the\nautoupdate in memory and fails with\n`Autoupdate would make changes to the file content` when the result differs. But\nthat arrives at `bazelisk test` time, after you have already read a diff that\nwas describing a file which had moved out from under it.\n\n### Inspect the diff\n\nInspect the diagnostics first, since that is the acceptance criterion:\n\n```bash\n# STDERR-only view, with jj.\njj --no-pager diff --git 'glob:toolchain/*/testdata/**' \\\n  | grep -E '^[-+].*CHECK:STDERR'\n\n# The same, with git.\ngit diff -- 'toolchain/*/testdata/*' \\\n  | grep -E '^[-+].*CHECK:STDERR'\n```\n\nFor a structured view separating test input, STDERR, and STDOUT changes, use the\nhelper from the\n[Summarize testdata changes](../summarize_testdata_changes/SKILL.md) skill:\n\n```bash\njj --no-pager diff --git 'glob:toolchain/*/testdata/**' \\\n  | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\ngit diff -- 'toolchain/*/testdata/*' \\\n  | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n```\n\nThe argument after the tool name is not interchangeable: `glob:...` is a jj\nfileset, `-- ...` is a git pathspec. `--git` and `--no-pager` are jj flags; git\nalready emits this format and skips the pager when piped.\n\n### Run the tests\n\nThen run the tests, which is what catches prefix mismatches and non-autoupdated\nexpectations:\n\n```bash\nbazelisk test //toolchain/...\n```\n\nSee the [Bazel usage](../bazel/SKILL.md) skill.\n\n## Checklist\n\nBefore presenting a testdata diff as finished:\n\n-   [ ] The autoupdater was run until it made no further changes, so no `loc`\n        name describes a stale line numbering.\n-   [ ] The list of accepted STDERR changes was written before autoupdating, and\n        every change either matches it or is reported as an exception.\n-   [ ] Every STDOUT change is either an instance of a named mechanical pattern\n        or has its own explanation.\n-   [ ] Instructions that appeared or disappeared are justified by what the\n        changed function owes its caller, not by the instruction count.\n-   [ ] Files whose prefix no longer matches their behavior have been renamed.\n-   [ ] No test input was changed, and no test was deleted, to make the diff\n        smaller.\n-   [ ] The size of the diff is proportional to the size of the change.\n",".agents/skills/summarize_testdata_changes/SKILL.md":"---\nname: Summarize testdata changes\ndescription:\n    Instructions for summarizing changes to Carbon testdata files\n    (`toolchain/*/testdata`).\n---\n\n# Summarize testdata changes\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill provides instructions for creating a comprehensive report summarizing\nchanges to Carbon testdata files (`toolchain/*/testdata`) and associating them\nwith related code changes.\n\nThis skill is about _reporting_ a diff. For deciding whether the diff is correct\nin the first place, see the\n[Review testdata changes](../review_testdata_changes/SKILL.md) skill.\n\n## Goals\n\nProduce a report that:\n\n1.  Summarizes code changes outside of testdata.\n2.  Groups similar testdata changes together, listing all affected files for\n    each group. **Every change to testdata must be represented by at least one\n    group. This includes changes to CHECK lines.**\n3.  Provides detailed breakdowns of test input changes and diagnostic output\n    changes in the corresponding group. **Every single change to inputs or to\n    STDERR checks must be explicitly mentioned in the group, with either an\n    inline diff or a link to the file.**\n\n## Process\n\n### 1. Identify Changes\n\nUse your VCS (Git or Jujutsu) or query Github to identify changes. For large\nchanges, it is recommended to use the included helper script to extract test\ninput changes.\n\n#### For Git Users:\n\n-   **Summarize code changes**: `git diff --stat -- ':!toolchain/*/testdata/*'`\n    -   To see content of non-testdata changes:\n        `git diff -- ':!toolchain/*/testdata/*'`\n-   **Identify testdata changes**:\n    `git diff --name-only 'toolchain/*/testdata/*'`\n\n#### For Jujutsu (jj) Users:\n\n-   **Summarize code changes**:\n    `jj --no-pager diff --stat '~toolchain/*/testdata'`\n    -   Note: Quoting the fileset `'~toolchain/*/testdata'` is critical if it\n        contains wildcards.\n    -   To see content of non-testdata changes, use `--git` to get standard\n        unified diff format: `jj --no-pager diff --git '~toolchain/*/testdata'`\n-   **Identify testdata changes**:\n    `jj --no-pager diff --name-only 'toolchain/*/testdata'`\n\n#### For Github Pull Requests:\n\n-   **Summarize code changes**: `gh pr diff`\n-   **Identify testdata changes**:\n    `gh pr diff --name-only | grep '^toolchain/.*/testdata'`\n\n#### Handling Specific Revisions:\n\nIf you are summarizing changes in a specific revision (for example, `@-`) or\npull request (for example, #1234), add `-r <rev>` or `<pr_number>` to the\ncommands:\n\n-   `git diff <rev>^ <rev> ...` (or use `git show <rev>`)\n-   `jj --no-pager diff -r <rev> ...`\n-   `gh pr diff <pr_number>`\n\n### 2. Extract Test Input Changes (Recommended)\n\nTo easily identify changes, use the included Python helper script to extract all\ntext additions and removals from the diff, categorized by Input, STDERR, and\nSTDOUT changes. This script reads a unified diff from stdin.\n\n```bash\n# For Git:\ngit diff -- 'toolchain/*/testdata/*' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For Jujutsu (jj):\njj diff --git 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For a specific revision with jj:\njj diff -r @- --git 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For a specific PR with Github:\ngh pr diff 1234 | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n```\n\n### 3. Identify Patterns and Produce a List of Groups\n\n-   Read the diff and produce a list of groups of changes that share a common\n    theme or cause (for example, \"Updated expected output for integer literals\",\n    \"Added tests for new keyword\").\n-   **CRITICAL**: _Every single change_ in the testdata diff must be represented\n    by at least one group. Do not ignore changes to `CHECK` lines.\n    -   If it's not clear what group a change belongs to, create a new group for\n        it.\n-   For each group:\n    -   Provide a brief description of the group.\n    -   (Optional) Briefly note if the group appears to be an intended or\n        unintended consequence of the code changes.\n-   Divide the groups into sections:\n    -   Test Changes: Changes to test inputs (lines not prefixed with\n        `// CHECK`), along with diagnostic output changes where relevant\n    -   Diagnostic Changes: Changes to diagnostic output (lines prefixed with\n        `// CHECK:STDERR`) with no corresponding changes to test inputs\n    -   [Output Type] Changes: Changes to STDOUT (lines prefixed with `//\n        CHECK:STDOUT`)\n        -   Create one section for each relevant kind of test. For example,\n            parser tests should typically be in a \"Parse Tree Changes\" section,\n            check tests should typically be in a \"SemIR Changes\" section, and\n            lower tests should typically be in an \"LLVM IR Changes\" section.\n\n### 4. Improve Grouping\n\n-   Read the list of groups and check to see if any of them should be combined\n    or split apart. If needed, do so.\n\n### 5. Assign Changes to Groups\n\n-   Read the diff again, and then for _each_ change in the diff:\n    -   Add the change to the appropriate group (or, rarely, groups).\n    -   **CRITICAL**: _Every single change_ in the testdata diff must be\n        represented by at least one group. Do not ignore changes to `CHECK`\n        lines.\n    -   If the change affects _test inputs_ (lines not prefixed with `// CHECK`)\n        or _diagnostic output_ (lines prefixed with `// CHECK:STDERR`):\n        -   List the file within the group. Don't just give one or a few\n            examples. Include every file.\n        -   Provide an inline diff if the change is small.\n        -   Provide a link to the file if the change is large.\n    -   Otherwise, if the change only affects _STDOUT_ (lines prefixed with\n        `// CHECK:STDOUT`):\n        -   Ensure the group contains a representative example that matches the\n            current change.\n        -   The representative example should be an inline diff of the change.\n    -   **CRITICAL**: _Every single change_ to test inputs and diagnostic\n        outputs in the files being summarized must be explicitly listed in at\n        least one group. Do not skip changes, even if they are similar to\n        changes you've already seen, and do not just give examples.\n\n### 6. Validation\n\nAs a final validation step:\n\n-   Read through the testdata diff again.\n-   Ensure that every change in the diff is reflected by at least one group in\n    the report.\n\n## Report Template\n\nUse the following template for the generated report:\n\n```markdown\n# `testdata` Change Summary\n\n## Code Changes\n\n[One paragraph summarizing changes outside of testdata.]\n\n## Test Changes\n\n### [Group Name]\n\n[Description of the group.]\n\n[Change 1: diff context OR link]\n\n[Change 2: diff context OR link]\n\n...\n\n## Diagnostic Changes\n\n### [Group Name]\n\n[Description of the group.]\n\n[Change 1: diff context OR link]\n\n[Change 2: diff context OR link]\n\n...\n\n## [Output Type] Changes\n\n### [File Path]\n\n[Description of the group.]\n\n[Example diff context]\n\nChanges of this kind were found in [Number] files. Examples: [List of files]\n\n...\n```\n\nSkip sections that would be empty.\n",".agents/skills/toolchain_development/SKILL.md":"---\nname: Toolchain development\ndescription:\n    Instructions for checking, building, debugging, and understanding the Carbon\n    toolchain.\n---\n\n# Toolchain development\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Toolchain structure\n\n-   Under [`toolchain/`](/toolchain/):\n    -   [`base/`](/toolchain/base/): Base infrastructure and common utilities.\n    -   [`check/`](/toolchain/check/): Semantic analysis (SemIR generation).\n    -   [`lex/`](/toolchain/lex/): Lexing (Source -> Tokens).\n    -   [`lower/`](/toolchain/lower/): Lowering to LLVM IR.\n    -   [`parse/`](/toolchain/parse/): Parsing (Token -> Parse Tree).\n    -   [`sem_ir/`](/toolchain/sem_ir/): Semantic Intermediate Representation\n        (SemIR) definitions.\n\n## Toolchain architecture\n\n-   **Documentation**: Refer to [`toolchain/docs`](/toolchain/docs) for detailed\n    architecture design and patterns.\n    -   Refer to [Toolchain Idioms](/toolchain/docs/idioms.md) for a\n        comprehensive list of patterns (for example, `ValueStore`, formatting\n        `.def` files, struct reflection) used throughout the implementation.\n-   **Builtin Functions**: Refer to the **Builtin functions** skill\n    ([SKILL.md](../builtins/SKILL.md)) for guidelines on registering, mapping,\n    constant evaluating, and lowering compiler builtin primitives (e.g.\n    `\"int.convert_float\"`).\n-   **Language server**: Refer to the **Language server** skill\n    ([SKILL.md](../language_server/SKILL.md)) before working on\n    `toolchain/language_server/` or `utils/vscode/`. Neither follows the\n    patterns described here.\n-   **Phases**: Lex -> Parse -> Check -> Lower.\n-   **Definitions**: Many kinds (tokens, parse nodes, SemIR instructions) are\n    defined in `.def` files and expanded by way of macros.\n-   **Handlers**:\n    -   Parser: `Handle<StateName>` in `parse/handle_*.cpp`.\n    -   Checker: `HandleParseNode` in `check/handle_*.cpp`.\n    -   Lowering: `HandleInst` in `lower/handle_*.cpp`.\n-   **Iteration**: Prefer iterative algorithms over recursive ones to prevent\n    stack exhaustion on complex codebases.\n\n### Essential commands\n\n-   **Test everything**: `bazelisk test //...`\n-   **Test specific target**: `bazelisk test //toolchain/testing:file_test`\n-   **Test specific file**: `bazelisk test //toolchain/testing:file_test\n    --test_arg=--file_tests=<path_to_carbon_file>`\n-   **Build toolchain**: `bazelisk build //toolchain/...`\n\n### Updating test data\n\nCarbon tests often use `file_test` (for example,\n`//toolchain/testing/file_test`). For detailed guidelines on authoring tests,\nincluding file splits, naming conventions (`fail_`, `todo_`), and generating\nminimal output with SemIR dumps, please refer to the **Toolchain tests** skill.\n\nIf you change compiler behavior, you likely need to update expected test\noutputs. **Do not manually edit thousands of lines of expected output.** Use the\nscript:\n\n```bash\n./toolchain/autoupdate_testdata.py\n# Or for a specific file:\n./toolchain/autoupdate_testdata.py toolchain/check/testdata/my_test.carbon\n```\n\n## Debugging and diagnostics\n\n-   **Compiler Diagnostics**: Refer to the **Diagnostics** skill\n    ([SKILL.md](../diagnostics/SKILL.md)) for strict rules on declaring,\n    formatting, emitting, testing, and styling compiler diagnostic messages\n    (errors, warnings, notes).\n-   **Printing to stderr**: Use `llvm::errs() << \"debug info\\n\";`.\n    -   Avoid `std::cout` (it may interfere with tool output).\n-   **SemIR Stringification**:\n    -   SemIR objects often have a `Print` method or `operator<<`.\n    -   `inst.Print(llvm::errs())`\n-   **Debugging Crashes**:\n    -   Bazel sandboxing can hide artifacts. Use `--sandbox_debug` if needed,\n        but often running the binary directly from `bazel-bin/` is easier for\n        debugging.\n\n## Error handling\n\n-   **No exceptions**: Do not use C++ exceptions.\n-   **`ErrorOr<T>`**: Return `ErrorOr<T>` for fallible operations.\n    -   Check with `if (auto result = Function(); result) { Use(*result); }`\n-   **`llvm::Expected<T>`**: Similar to `ErrorOr`, used when interfacing with\n    LLVM.\n\n### Context-Aware Diagnostics\n\nWhen declaring and emitting errors, ensure semantic wording matches the exact\ncontext:\n\n-   **Semantic Precision**: Do not reference \"types\" when raising errors for\n    unsized expressions like `IntLiteral` or `FloatLiteral`. For example, use\n    `RealLiteralTooLargeForUnsizedInt` instead of a diagnostic referencing an\n    \"integer type\".\n-   **Wording Consistency**: Before declaring a new diagnostic in\n    [kind.def](../../../toolchain/diagnostics/kind.def), search for existing\n    diagnostics in the targeted implementation files (for example, other uses of\n    `MaxIntWidth`) to align message structures and parameter expectations.\n\n### Casting (LLVM style)\n\n-   Use `llvm::cast<T>(obj)` (checked, asserts on failure).\n-   Use `llvm::dyn_cast<T>(obj)` (returns null on failure).\n-   Use `llvm::isa<T>(obj)` (boolean check).\n-   **Avoid** `dynamic_cast` and standard RTTI.\n\n### Leverage LLVM APIs\n\nBefore implementing custom algorithms for mathematical, logical, or bitwise\noperations, inspect target LLVM ADT class APIs:\n\n-   **Builtin APIs**: Verify if LLVM classes (such as `APInt`, `APFloat`, or\n    `APSInt`) already offer native equivalents (for example, `.pow()`,\n    `ilogb()`, `.changeSign()`, `convertFromAPInt()`). Avoid duplicate, naive,\n    or inefficient custom loops.\n\n### Data structures\n\n-   Prefer APIs in `common/` and `toolchain/base/` over LLVM ADTs. For example,\n    use `Map` instead of `llvm::DenseMap`.\n-   If no Carbon API exists, prefer LLVM ADTs over standard library ones (for\n    example `llvm::SmallVector`, `llvm::StringRef`).\n-   `StringRef` is a view; be careful with lifetimes.\n\n## Common pitfalls\n\n1.  **Legacy `explorer` references**: The `explorer` prototype has been moved.\n    Ignore references to it in proposals or old docs; focus on `toolchain`.\n2.  **Manually updating test files**: Always check if `autoupdate_testdata.py`\n    can do it for you.\n3.  **Using `std::string` unnecessarily**: Prefer `llvm::StringRef` for\n    arguments.\n4.  **Header includes**: Use specific include orders (often enforced by\n    `clang-format`).\n5.  **Parse node order**: Semantics processes parse nodes in post-order; ensure\n    your parser transitions support this.\n6.  **Builtin implementation gaps**: If adding a primitive builtin function,\n    make sure you address all phases of the lifecycle: macro definition\n    registration, signature validation, compile-time constant evaluation\n    (interpreter), LLVM IR lowering, and prelude modular implementation bindings\n    (avoiding orphan rules). Refer to the **Builtin functions** skill\n    ([SKILL.md](../builtins/SKILL.md)) for details.\n7.  **Premature helper abstraction**: Avoid extracting tiny helper functions\n    that are called from exactly one place and do not significantly modularize\n    complex code. Prefer inlining directly to keep the implementation compact,\n    readable, and localized.\n8.  **Redundant bounds calculations**: Avoid repeating calculations of complex\n    boundary estimations (such as lower and upper bound estimations). Refactor\n    the logic to calculate unified values once, preserving compactness.\n9.  **Trusting stale `clangd` diagnostics**: In-editor diagnostics are only as\n    good as `compile_commands.json`. If it predates a newly added file, `clangd`\n    falls back to a default command and reports nonsense, such as missing\n    standard headers or \"no member named `None`\". Regenerate it with\n    `./scripts/create_compdb.py`, which only takes a few seconds.\n",".agents/skills/toolchain_tests/SKILL.md":"---\nname: Toolchain tests\ndescription:\n    Instructions for authoring, structuring, and running toolchain tests using\n    the file_test infrastructure.\n---\n\n# Toolchain tests\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Introduction\n\nThis skill provides guidelines and patterns for creating and updating tests for\nthe Carbon toolchain, especially file tests in `toolchain/*/testdata/` (for\nexample, `toolchain/check/testdata/`).\n\nToolchain tests evaluate Carbon source files through Lexing, Parsing, Checking,\nand optionally Lowering. Output (for example SemIR dumps, Clang errors) is\ncaptured and validated using inline CHECK records.\n\nLanguage server tests also use `file_test`, but with quite different\nconventions (an LSP message stream, `AUTOUPDATE-SPLIT`, `FROM_FILE_SPLIT`).\nRefer to the **Language server** skill\n([SKILL.md](../language_server/SKILL.md)) for those.\n\n## Structure and Authoring\n\n### File Layout and Headers\n\nTest files must start with the standard Carbon license, followed by\nconfiguration comments. Separate sections with blank comment lines (`//`).\n\n```carbon\n// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/...\n//\n// AUTOUPDATE\n```\n\n-   `// AUTOUPDATE` is mandatory for files using CHECK markers.\n-   `// TIP:` lines are automatically generated by the autoupdater. You do not\n    need to hand-write them. It is harmless to add them, but the script will\n    handle it.\n\n### Minimized Preludes\n\nWhen writing tests entirely unrelated to the Core package, specify a minimal\nprelude file using `// INCLUDE-FILE`. Usually, include\n`toolchain/testing/testdata/min_prelude/` scripts, such as `int.carbon` or\n`primitives.carbon`. This significantly speeds up execution and minimizes STDOUT\nnoise.\n\n-   **Builtin Primitive Testing**: Standard operators (such as `+`, `-`, `/`,\n    `<`, etc.) are **not** imported or available inside minimized preludes. To\n    write tests with a minimal prelude footprint, call primitive builtins\n    directly (e.g., `float.negate`, `float.div`) inside your test code to build\n    expressions.\n\n### Split Tests and `[[@TEST_NAME]]`\n\nA single physical file can test multiple scenarios using split constraints:\n\n```carbon\n// --- passing_case.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// ...\n\n// --- fail_bad_case.carbon\nlibrary \"[[@TEST_NAME]]\";\n// ...\n```\n\n-   **Always** use `library \"[[@TEST_NAME]]\";` in each split rather than\n    hardcoding the library name. This prevents name conflicts, avoids redefining\n    the default library, and keeps the test code clean and templateable.\n-   Exactly `[[@TEST_NAME]]` (including the brackets) must be used. The test\n    infrastructure automatically replaces it with the split's filename minus\n    `todo_` and `fail_` prefixes.\n-   **Do not put code that is expected to pass and code that is expected to fail\n    into the same split.** Validation relies on non-failing splits producing\n    absolutely no errors and failing splits producing the correct compiler\n    errors independently.\n\n### File Prefixing: `fail_` and `todo_`\n\nExpected failures must be differentiated from unexpected failures (and from\nbugs). Include prefixes to name individual split files or the main test:\n\n-   `fail_...`: The test should and does produce compiler errors.\n-   `todo_fail_...`: The test should produce errors but currently does not.\n-   `fail_todo_...`: The test does produce errors or crashes, but it shouldn't\n    (or produces the wrong errors or otherwise misbehaves with errors).\n-   `todo_...`: The test has some incorrect behavior, but doesn't produce errors\n    currently, and shouldn't.\n\n**Main File Naming**: The main test file (and any split-files) must have a\n`fail_` prefix if they have an associated error. **Exception**: The main file\nmay omit `fail_` if it contains a least one split that has a `fail_` prefix.\n\nBoth the `fail_` and `todo_` prefixes are stripped from filename properties like\n`[[@TEST_NAME]]`.\n\n### Constant Evaluation Validation\n\nWhen testing constant evaluation in semantic checker tests, follow these\nconventions to ensure diagnostic stability and accuracy:\n\n-   **Literal Spelling Canonicalization**: In Semantic IR, real literals\n    (floating-point constants) with identical mathematical values can be\n    assigned distinct internal representation identifiers based on spelling\n    variations in source code. To completely prevent literal spelling mismatches\n    in expected output checks, validation tests must be performed using\n    canonical comparison methods (for example, passing converted values through\n    an `Expect(X as f64)` function).\n-   **Generic Parameters Validation**: To bypass compile-time constraints where\n    local runtime variables are rejected as generic function arguments, test\n    generic type conversions at runtime, and validate compile-time conversions\n    by passing static literal values directly into primitive builtin calls.\n-   **Exhaustive Edge Case Verification**: For complex mathematical algorithms\n    (such as floating-point to integer truncation and rounding), map and execute\n    test constraints covering every code branch, conditional exit, and fallback\n    evaluation path.\n-   **Rounding Threshold Boundaries**: Test cases that land extremely close to\n    mathematical boundaries (for example, floating-point literals representing a\n    tiny fraction above 1.0, such as $2^{30} \\times 2^{-30}$ or\n    $10^{10} \\times 10^{-10}$, verifying correct exact truncation down to 1 or\n    0).\n-   **Precise Float Literal Spelling**: Spell floating-point literals in test\n    code with exact mathematical precision targeting target thresholds. For\n    example, if testing the smallest fractional increment above 1.0, use the\n    exact hex fractional representation (e.g. `0x1.0000000000001p0`) or a highly\n    precise decimal fractional spelling (e.g. `1.0000000000000001`) instead of\n    coarse fractions like `1.1` to ensure correct boundary assertions.\n-   **Representation Capacity Boundaries**: Explicitly target edge cases near\n    representation limits of target types. Test combinations of mantissas and\n    exponents that yield values exactly on, just below, or just above the\n    capacity limits of fixed-size destination types (e.g. signed/unsigned\n    targets like `i32` or `u32`).\n-   **Zero-Value Sizing Bounds**: Verify boundary inputs of `0` and `0.0`\n    explicitly. Assert that zero inputs are sized and simplified correctly\n    without triggering calculation underflows, division-by-zero errors, or\n    underestimating required bit allocations.\n\n### Test Code Comments\n\n-   **No agent thinking:** Do not include comments describing your reasoning or\n    \"train of thought\" (for example, \"Wait, but...\") inside the test files. Any\n    comments left in tests should be concise and describe what the test _itself_\n    is validating for human readers.\n\n## SemIR Dumps and Minimizing Output\n\nLimit STDOUT checks to the logic under test. Always use `//@dump-sem-ir-begin`\nand `//@dump-sem-ir-end` around the specific declarations/blocks where SemIR\noutput is desired. Only use these markers and **not**\n`--dump-sem-ir-ranges=if-present` or similar extra args—new tests use\n`//@dump-sem-ir...` to naturally filter output to the highlighted segments based\non the default behavior.\n\n```carbon\n//@dump-sem-ir-begin\nfn F(x:? form(ref i32));\n//@dump-sem-ir-end\n```\n\n## Creating/Updating the Output\n\nAI tools should **never** hand-write or manually touch `// CHECK:STDOUT:` or\n`// CHECK:STDERR:` comments.\n\nWrite your Carbon test code, headers, and `// AUTOUPDATE` then run the test\nupdater:\n\n```bash\n./toolchain/autoupdate_testdata.py toolchain/PATH/TO/YOUR/TEST.carbon\n```\n\nReview the updated test outputs (for example, by way of `git diff`). Ensure\nlogic paths are correctly tested rather than producing massive boilerplate\nblocks.\n\nAutoupdating makes the tests pass whether or not the new behavior is correct, so\ndeciding that the new output is the output you wanted is a separate step. See\nthe [Review testdata changes](../review_testdata_changes/SKILL.md) skill.\n","AGENTS.md":"# Gemini & AI Assistant Guide for Carbon\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis document provides high-density technical context for AI assistants\ncontributing to the Carbon Language project.\n\n## General instructions\n\n-   **Communication**: Be concise, professional, and technical. Use GitHub-style\n    markdown.\n-   **Verification**: Always run relevant tests.\n\n## Bazel usage\n\n> [!IMPORTANT] Always use `bazelisk` instead of `bazel` for all commands in the\n> Carbon project. Refer to the\n> [Bazel usage skill](/.agents/skills/bazel/SKILL.md) for detailed instructions.\n\n## Version control\n\n> [!IMPORTANT] Never rewrite the history of a change that has been submitted as\n> a pull request. Reviewers track a PR by its commits, and rewriting them\n> discards their in-progress review. Ask before rewriting history in any case.\n> Refer to the [Jujutsu (jj) usage skill](/.agents/skills/jj/SKILL.md) for\n> details.\n","github_tools/README.md":"# GitHub\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nScripts for use with GitHub.\n\nSee individual scripts for more details.\n"},"files":{".agents/skills/agent_tools/SKILL.md":"---\nname: Agent tools\ndescription:\n    Guidelines and restrictions on shell commands and file manipulation tools\n    for AI assistants.\n---\n\n# Agent tools\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nAI assistants working on the Carbon repository **MUST NOT** use legacy or\ngeneric UNIX shell search/edit commands when specialized environment tools\nexist.\n\n## Command line tools restrictions\n\n-   **DO NOT USE**: `cat`, `less`, `grep`, `sed`, or other shell utilities for\n    viewing, searching, or modifying files.\n-   **DO NOT USE**: `patch` to write and apply patch files.\n-   **DO NOT USE**: Writing custom scripts in other languages to circumvent this\n    limitation.\n-   **DO USE**: High-fidelity semantic API tools:\n    -   **Viewing**: Use `view_file` instead of `cat` / `less`.\n    -   **Searching**: Use `grep_search` / `find_by_name` instead of `grep` /\n        `find`.\n    -   **Modifying**: Use `replace_file_content`, `multi_replace_file_content`,\n        or `write_to_file` instead of `sed` / `patch` / `python` edits.\n\nYou may only write and run temporary programs to modify source code if no\nsemantic tool is applicable or when performing complex, systematic transforms\nacross many codebase directories simultaneously.\n\n## Temporary files management\n\nTemporary files and scratchpad test scripts created by the assistant during\nanalysis, experiments, or debugging:\n\n-   **MUST** reside within the `tmp/` subdirectory under the workspace root.\n-   **MUST** be periodically cleaned out and deleted before ending your turn to\n    preserve a clean git workspace.\n",".agents/skills/bazel/SKILL.md":"---\nname: Bazel usage\ndescription:\n    Instructions that **MUST** be followed when using Bazel or Bazelisk to\n    build, test, and debug in the Carbon repository.\n---\n\n# Bazel usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill documents how best to use Bazel when building, testing, or\nmanipulating the Carbon repository's Bazel in any way.\n\n## Bazel wrappers\n\nCarbon uses Bazel for its build system. To ensure consistent versions, the\nproject uses Bazelisk.\n\n> [!IMPORTANT] Always use `bazelisk` whenever you want to run Bazel. Never run\n> `bazel` directly in the Carbon project. Anything you want to do with `bazel`\n> can be done with the `bazelisk` command instead.\n\n-   **Bazelisk**: Try to use `bazelisk` in your existing `$PATH` if available.\n    -   **`run_bazelisk.py`**: If `bazelisk` isn't available, use\n        `./scripts/run_bazelisk.py` to run bazelisk without it being installed.\n\n## Essential commands\n\n### Building\n\n-   **Build all**: `bazelisk build //...`\n-   **Build toolchain**: `bazelisk build //toolchain/...`\n-   **Build specific target**: `bazelisk build //toolchain:carbon`\n\n### Testing\n\n-   **Test all**: `bazelisk test //...:all`\n-   **Test toolchain**: `bazelisk test //toolchain/...`\n-   **Test examples**: `bazelisk test //examples/...`\n\n> [!TIP] Running all of the tests can be slow, so try to narrowly test the\n> immediately relevant parts of the project first, and only expand coverage as\n> necessary to be confident in the changes.\n\n> [!TIP] For specialized instructions on testing and developing the Carbon\n> toolchain, consult these skills:\n>\n> -   [Toolchain tests](/.agents/skills/toolchain_tests/SKILL.md): For\n>     authoring, structuring, and running `file_test` tests.\n> -   [Toolchain development](/.agents/skills/toolchain_development/SKILL.md):\n>     For architecture, essential commands, and debugging the toolchain.\n\n### Running binaries built by Bazel\n\n> [!IMPORTANT] Always manually run binaries built by Bazel using the\n> `bazelisk run` command. Never run the binary directly from `bazel-bin/`.\n\nYou can run the Carbon driver or command line directly via Bazel:\n\n-   `bazelisk run //toolchain -- compile --phase=parse\n    toolchain/parse/testdata/basics/empty.carbon`\n\n## Advanced configurations\n\n### AddressSanitizer (ASan)\n\nTo enable ASan for local testing:\n\n-   Pass `--config=asan`: `bazelisk test --config=asan //...`\n\n## Common pitfalls and troubleshooting\n\n### `bazel clean`\n\nChanges to packages installed on your system (like changing LLVM versions or\ninstalling `libc++`) may not be noticed by Bazel.\n\n-   Run `bazelisk clean` to force cached state to be rebuilt when environment\n    changes occur.\n",".agents/skills/builtins/SKILL.md":"---\nname: Builtin functions\ndescription:\n    Instructions for registering, mapping, constant evaluating, and lowering\n    builtin functions in the Carbon toolchain.\n---\n\n# Builtin Functions in the Carbon Toolchain\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nBuiltin functions are compiler-recognized primitives mapping directly from\nCarbon code expressions (via standard prelude bindings) to optimized backend\nexecution. This document defines the complete structural workflow, C++ patterns,\nconstant evaluation logic, machine lowering mechanics, library bindings, and\nvalidation strategies required to implement builtin functions in the Carbon\ncompiler.\n\n---\n\n## Technical Flow & Lifecycle\n\n```mermaid\ngraph TD\n  Src[Carbon Source Code] -->|Prelude Map| Sem[Semantic Analysis / SemIR]\n  Sem -->|Signature Constraint| Sig[builtin_function_kind.cpp]\n  Sem -->|Phase Evaluation| Eval[eval.cpp Constant Interpreter]\n  Sem -->|Machine Codegen| Lower[handle_call.cpp LLVM Lowering]\n  Eval -->|Diagnostics| Diag[diagnostics/kind.def]\n  Lower -->|Native Instructions| LLVM[LLVM IR Generation]\n```\n\nAdding a builtin function involves a 5-step integration:\n\n1.  **Define the Builtin Kind**: Register the enum in\n    [builtin_function_kind.def](../../../toolchain/sem_ir/builtin_function_kind.def).\n2.  **Signature & Compile-Time Registry**: Declare the mapping name, parameter\n    constraints, and compile-time evaluation residency in\n    [builtin_function_kind.cpp](../../../toolchain/sem_ir/builtin_function_kind.cpp).\n3.  **Compile-Time Interpreter Support**: Wire constant evaluation hooks and\n    bounds/exception diagnostics in\n    [eval.cpp](../../../toolchain/check/eval.cpp).\n4.  **LLVM IR Lowering Support**: Connect target machine generation in\n    [handle_call.cpp](../../../toolchain/lower/handle_call.cpp).\n5.  **Prelude Library Mapping**: Bind primitive interfaces to named builtins\n    under [core/prelude/](../../../core/prelude/).\n\n---\n\n## Detailed Step-by-Step Implementation Guide\n\n### Step 1: Kind Definition & Registration\n\nRegister your builtin function name using the X-macro in\n[builtin_function_kind.def](../../../toolchain/sem_ir/builtin_function_kind.def):\n\n```cpp\n// toolchain/sem_ir/builtin_function_kind.def\n\n// Converts an integer type to a floating-point type.\nCARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntConvertFloat)\n```\n\n### Step 2: Signature Validation & Compile-Time Residence\n\nInside\n[builtin_function_kind.cpp](../../../toolchain/sem_ir/builtin_function_kind.cpp):\n\n1.  **Define Parameter Constraints**: If the parameter requires novel\n    constraints (e.g. \"must be a float type\"), define a template constraint\n    struct checking the matching `SemIR` type instruction (such as `FloatType`\n    or `FloatLiteralType`). Use pre-established semantic helpers:\n\n    -   `TypeParam<I, T>`: Ensures different parameters resolve to identical\n        type structures (e.g., generic constraint matching).\n    -   `AnyInt`, `AnyFloat`, `AnySizedInt`, `AnySizedFloat`, `CharCompatible`,\n        `StdInitializerList`, `NoReturn`.\n\n2.  **Map Literal Name & Register Constraint Signature**: Declare a\n    `BuiltinInfo` constant inside `namespace BuiltinFunctionInfo` matching the\n    macro-defined name:\n\n    ```cpp\n    // toolchain/sem_ir/builtin_function_kind.cpp\n\n    constexpr BuiltinInfo IntConvertFloat = {\n        \"int.convert_float\", ValidateSignature<auto(AnyInt)->AnyFloat>};\n    ```\n\n3.  **Establish Compile-Time Residency Status**: Update\n    `BuiltinFunctionKind::IsCompTimeOnly` to determine if a call requires\n    compile-time evaluation:\n    -   **Checked/Diagnostics Primitives**: Return `true` immediately. Runtime\n        lowering of these is illegal (e.g. `IntConvertFloatChecked`).\n    -   **Runtime Primitives**: Return\n        `AnyLiteralTypes(sem_ir, arg_ids, return_type_id)` to enforce that\n        expressions involving unsized literal values (like `IntLiteral` or\n        `FloatLiteral`) are evaluated exclusively at compile-time (as they lack\n        runtime representation).\n\n---\n\n### Step 3: Constant Evaluation Support\n\nWire the interpreter inside [eval.cpp](../../../toolchain/check/eval.cpp) to\nexecute compile-time computations:\n\n1.  **Implement Constant Evaluation Logic**:\n\n    -   Handle the builtin case inside `MakeConstantForBuiltinCall` (which\n        processes the compile-time execution of the call).\n    -   Confirm type validation phase is `Phase::Concrete` to reject incomplete\n        bindings:\n\n        ```cpp\n        case SemIR::BuiltinFunctionKind::IntConvertFloat: {\n          if (phase != Phase::Concrete) {\n            return MakeConstantResult(context, call, phase);\n          }\n          return PerformIntToFloatConvert(context, loc_id, arg_ids[0], call.type_id,\n                                          /*require_exact=*/false);\n        }\n        ```\n\n    -   Extract inputs safely from local value stores (e.g.\n        `context.ints().Get(arg.int_id)` or\n        `context.floats().Get(arg.float_id)`).\n    -   Leverage high-precision LLVM mathematical structures (`llvm::APInt`,\n        `llvm::APFloat`, `llvm::APSInt`) to handle custom bits and signedness\n        safely.\n\n2.  **Diagnose Invalid Parameters or Exceptions**:\n\n    -   Define compile-time diagnostics inside\n        [kind.def](../../../toolchain/diagnostics/kind.def):\n\n        ```cpp\n        // toolchain/diagnostics/kind.def\n        CARBON_DIAGNOSTIC_KIND(IntTooLargeForFloatType)\n        ```\n\n    -   Emplace localized diagnostic formatting messages where they are caught\n        in `eval.cpp`:\n\n        ```cpp\n        CARBON_DIAGNOSTIC(IntTooLargeForFloatType, Error,\n                          \"integer value {0} too large for floating-point type {1}\",\n                          llvm::APSInt, SemIR::TypeId);\n        context.emitter().Emit(loc_id, IntTooLargeForFloatType, val, dest_type_id);\n        ```\n\n    -   Return `SemIR::ErrorInst::ConstantId` to gracefully abort invalid\n        constant generation rather than crashing the compiler.\n\n3.  **Fast-Path Range Limits**:\n    -   Before evaluating expensive math operations on giant exponents (e.g.\n        `1.0e1000000`), executing range limits check against `dest_width + 64`\n        (sized) or `IntStore::MaxIntWidth` (unsized) is mandatory to prevent\n        out-of-bounds calculations and compile-time memory exhaustion.\n\n---\n\n### Step 4: Machine Code Generation (LLVM Lowering)\n\nInside [handle_call.cpp](../../../toolchain/lower/handle_call.cpp):\n\n1.  **Map to Native LLVM Instructions**: For runtime-eligible builtins, map the\n    call inside `HandleBuiltinCall` to native LLVM IR builder methods:\n\n    ```cpp\n    case SemIR::BuiltinFunctionKind::IntConvertFloat: {\n      auto* operand = context.GetValue(arg_ids[0]);\n      auto* dest_type = context.GetTypeOfInst(inst_id);\n      bool is_signed = IsSignedInt(context, arg_ids[0]);\n      context.SetLocal(\n          inst_id, is_signed\n                       ? context.builder().CreateSIToFP(operand, dest_type)\n                       : context.builder().CreateUIToFP(operand, dest_type));\n      return;\n    }\n    ```\n\n2.  **Assert on Compile-Time-Only Builtins**: Throw a hard assertion on\n    lowering-cases for checked validator builtins that should never hit code\n    generation:\n\n    ```cpp\n    case SemIR::BuiltinFunctionKind::IntConvertFloatChecked: {\n      CARBON_CHECK(builtin_kind.IsCompTimeOnly(\n          context.sem_ir(), arg_ids,\n          context.sem_ir().insts().Get(inst_id).type_id()));\n      CARBON_FATAL(\"Missing constant value for call to comptime-only function\");\n    }\n    ```\n\n---\n\n### Step 5: Standard Library Prelude Integration\n\nMap the standard library primitive interfaces to your newly minted named\nbuiltins under [core/prelude/](../../../core/prelude/):\n\n-   **Primitive Mappings**: Bind Carbon methods directly to string-literal\n    builtin equivalents:\n\n    ```carbon\n    fn Convert[self: Self]() -> Float(To) = \"int.convert_float\";\n    ```\n\n-   **Strict Orphan Rule Compliance**: Carbon's orphan rules prohibit\n    implementing interfaces where neither the type nor the interface is locally\n    defined in the backing source module.\n    -   **Literal Conversions**: Literal types (like `FloatLiteral`,\n        `IntLiteral`) do not have backing Carbon source files. Therefore, an\n        `impl` of `UnsafeAs` (which is defined in `as.carbon`) between two\n        literal types must reside inside `as.carbon` itself.\n    -   **Sized Conversions**: Implementations targeting sized primitives (e.g.\n        `Int(N)`, `Float(N)`) must reside in their respective type source files\n        (such as [int.carbon](../../../core/prelude/types/int.carbon) or\n        [float.carbon](../../../core/prelude/types/float.carbon)) where the\n        backing target type resides to prevent duplicate symbols and structural\n        recursion loops.\n\n---\n\n## High-Fidelity Validation & Test Authoring\n\nFollow the [Toolchain tests](../toolchain_tests/SKILL.md) skill with specialized\npatterns for builtins:\n\n### 1. Checker Builtin File Splits\n\nCreate validation splits under\n[toolchain/check/testdata/builtins/](../../../toolchain/check/testdata/builtins/):\n\n-   **Test Naming Convention**: All tests under\n    [toolchain/check/testdata/builtins/](../../../toolchain/check/testdata/builtins/)\n    must be named after the builtin they are testing, replacing `.` characters\n    in the builtin name with `/` (directories). For example, a test for the\n    builtin `\"char_literal.convert\"` must be located at\n    `toolchain/check/testdata/builtins/char_literal/convert.carbon`.\n-   **Minimal Prelude & Direct Call Isolation**: Builtin tests must **not** test\n    the prelude library or operators. They must use the minimal primitive\n    prelude (`// INCLUDE-FILE:\n    toolchain/testing/testdata/min_prelude/primitives.carbon`) or a smaller\n    prelude, and explicitly declare and call the builtin functions under test\n    directly (e.g., `fn Add(a: f64, b: f64) -> f64 = \"float.add\";`). This\n    isolates the testing of compiler builtins from the library prelude.\n-   **Min-Prelude Limitations**: Standard operators (like `+`, `-`, `/`, `<`,\n    etc.) are **not** available in minimized preludes because the core operators\n    library isn't imported. To write tests with a minimal footprint, call\n    primitive builtins directly (e.g. `float.negate`, `float.div`) inside your\n    test code to build expressions.\n-   **Canonicalized Float Comparison**: In SemIR, real literal representations\n    with identical mathematical values can result in mismatched `RealId` objects\n    based on spelling variations. Verify compile-time constant conversions using\n    canonicalized comparison functions (e.g. passing converted results through\n    `Expect(X as f64)`) to completely avoid spelling mismatches in expected\n    outputs.\n-   **Locals Bypass**: If validating generic implicit conversions, compile-time\n    arguments cannot take local runtime variable parameters. Validate\n    compile-time conversions by passing literal constants directly, and sized\n    variable implicit conversions at runtime.\n\n### 2. Machine Codegen Lowering Splits\n\nCreate testing splits under\n[toolchain/lower/testdata/builtins/](../../../toolchain/lower/testdata/builtins/):\n\n-   Emplace a simple carbon binding to the tested builtin.\n-   Confirm matching LLVM metadata target definitions are mapped precisely\n    (e.g., matching `sitofp i32 %a to float`, `fptosi float %a to i32`).\n",".agents/skills/code_style/SKILL.md":"---\nname: Code style\ndescription:\n    Instructions for code formatting and style guidelines in the Carbon\n    toolchain.\n---\n\n# Code style\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## License\n\n-   **Licenses**: All Carbon files outside of `third_party/` should have a\n    license following\n    [CONTRIBUTING license instructions](/CONTRIBUTING.md#license).\n\n## Formatting\n\n-   **Bazel**: Use `pre-commit run buildifier --files <file.bzl>` to format\n    Bazel files.\n-   **C++**: Use `pre-commit run clang-format --files <file.cpp>` to format C++\n    files.\n-   **Carbon**: The toolchain's `format` command doesn't work well right now.\n    Instead, try to format Carbon code based on other Carbon files and the C++\n    style.\n-   **Markdown**: Use `pre-commit run prettier --files <file.md>` to format\n    markdown files.\n-   **Python**: Use `pre-commit run black --files <file.py>` to format Python\n    files.\n\n## Comments\n\n-   **Describe the code that is there.** A comment should explain what the\n    current code does or why it is the way it is, not narrate what the code used\n    to be. Do not add a comment to justify a deletion or explain that something\n    is no longer necessary; a reader of the new code has no idea what is being\n    contrasted against, and the comment rots as soon as the old shape is\n    forgotten. Put that reasoning in the commit message instead.\n-   **Do not introduce a local variable just to host a comment.** If a call\n    argument reads clearly on its own, inline it rather than naming it so that a\n    comment has somewhere to attach.\n-   **Lead with a plain summary.** Start a doc comment with a direct statement\n    of what the function does or returns, such as \"Returns true if the InstKind\n    is a singleton.\" Put nuance in a following sentence rather than qualifying\n    the summary into something harder to read.\n-   **Re-read a comment before updating it.** When a symbol is renamed or\n    changes meaning, a comment that mentions it is not automatically stale. Work\n    out what the comment actually asserts first: it may be describing what the\n    code _uses_, which is still true, and rewriting it loses information.\n\n## Documentation\n\nThis covers standalone prose: `/docs`, `README.md` files, and the skill files\nunder `.agents/skills`.\n\n-   **Be true of the tree it lands in.** Documentation shipping in the same\n    commit as the code it describes should name that code freely. Documentation\n    that lands separately must not: a reader who greps for an identifier from an\n    unlanded change finds nothing, and a claim that only holds after that change\n    is false until it lands. This is easy to get wrong when writing up a lesson\n    while the change that taught it is still in flight.\n-   **Use placeholders for illustrations.** When an example only needs to show a\n    shape, name it `Foo` rather than reaching for a real symbol. Save real\n    identifiers for documenting that identifier, where going stale is at least\n    detectable.\n-   **Make each point stand alone.** A reader has none of the discussion that\n    produced it. State the rule, and enough of the reason to apply it, without\n    assuming knowledge of the change that motivated it.\n\n## Naming\n\n-   **A name is a claim, so keep it true.** When a change invalidates the\n    invariant a name describes, rename it in the same change. A factory called\n    `MakeSingletonFooId` has to be renamed once `Foo` is no longer a singleton,\n    even though nothing forces you to.\n-   **Types in a signature are part of the claim.** A function returning the id\n    of a namespace should return `InstId`, not `TypeInstId`, because a namespace\n    is not a type. Do not let a convenient wider or narrower id type imply\n    something false.\n-   **Delete a predicate whose name stops distinguishing anything.** If a change\n    widens a test so that it no longer says what its name implies, remove it and\n    let callers use the underlying test, rather than keeping a wrapper that\n    sounds meaningful. What callers actually want is often the inverse, and is\n    worth adding under its own name.\n-   **Name a variable for its role, not its representation.** If the role a\n    value plays is unchanged, keep its name even when a change means it is now\n    held or spelled differently.\n\n## Commit descriptions\n\n-   **Say what the change is, not how you made it.** Describe the resulting\n    code. Only describe process when the process is more interesting than the\n    change, as with a large mechanical transformation.\n-   **Do not narrate your own work.** Statements like \"each such site was\n    audited\" or \"we investigated every caller\" describe effort, not the change.\n-   **Omit routine mechanical steps.** Do not mention running the testdata\n    autoupdater or the formatter. Every change is expected to include those.\n-   **Do not enumerate each edit.** Describe the change as a whole rather than\n    listing every function or file touched; the diff already lists them.\n-   **Use the project's terms precisely.** Reach for the term of art the\n    codebase uses. Calling something a \"type alias\" or a \"namespace\" when it is\n    a named scope misleads, and is worse than a vaguer but accurate word.\n-   **Scope claims to what changed.** Say the specific thing that is now true,\n    rather than a broader statement that happens to contain it.\n\n## Design\n\n-   **Do not distort the data model to improve output.** If printed or golden\n    output is undesirable, change the printer, not the data structures that\n    feed it.\n\n## Style Guides\n\n-   **C++ style**: Follow the\n    [Carbon C++ Project Style Guide](/docs/project/cpp_style_guide.md).\n-   **Markdown style**: Follow the\n    [Google developer documentation style guide](https://developers.google.com/style).\n-   **Python style**: Follow the [PEP 8](https://peps.python.org/pep-0008/)\n    style guide.\n    -   Wrap code and comments to 80 columns.\n    -   Run `pre-commit run flake8 --files <file.py>` to check Python style.\n",".agents/skills/diagnostics/SKILL.md":"---\nname: Diagnostics\ndescription:\n    Instructions for declaring, formatting, emitting, testing, and styling\n    diagnostic messages (errors, warnings, and the labels that explain them) in\n    the Carbon toolchain.\n---\n\n# Diagnostics in the Carbon Toolchain\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThe Carbon compiler features a highly-engineered, context-aware diagnostics\nframework designed to deliver precise, readable, and highly targetable\ndiagnostic output (errors, warnings, and the labels that explain them). This\ndocument establishes strict rules for declaring, formatting, emitting, testing,\nand styling compiler diagnostics.\n\n---\n\n## Architecture Overview\n\n```mermaid\ngraph TD\n  Kind[kind.def Registry] -->|Registration| Enum[Kind Enum ID]\n  Enum -->|Build/Emit| Emitter[Emitter LocT]\n  Emitter -->|ConvertLoc| Loc[Converted Physical Loc]\n  Emitter -->|formatv serialization| Formatting[format_providers.h / Custom Types]\n  Emitter -->|Emit Messages| Consumer[Console / Sorting Consumer]\n  Consumer -->|stable sort| StdErr[Compiler Standard Error]\n```\n\nDiagnostics are handled via three decoupled core components:\n\n1.  **Registry**: Globally enumerated kinds inside\n    [kind.def](../../../toolchain/diagnostics/kind.def).\n2.  **Emitters**: Specialized formatting pipelines (parameterized on custom\n    phase location types `LocT` like `Token` or `LocId`) that convert raw tokens\n    to standardized physical source locations (file, line, column, and the text\n    of the line).\n3.  **Consumers**: Pipelines that process, track, filter, and sort diagnostics.\n    The default `SortingConsumer` buffers and stable-sorts diagnostics based on\n    their `last_byte_offset` matching compiler traversal order to ensure perfect\n    causal ordering.\n\n---\n\n## 1. Declaring and Registering Diagnostics\n\nAll diagnostic types must pass structural uniqueness and coverage verifications.\n\n### The Diagnostic Registry\n\nEvery diagnostic kind must be registered globally as an enum option under\n[kind.def](../../../toolchain/diagnostics/kind.def):\n\n```cpp\n// toolchain/diagnostics/kind.def\nCARBON_DIAGNOSTIC_KIND(RealLiteralTooLargeForUnsizedInt)\n```\n\n### The Uniqueness Rule\n\nTo ensure optimal compile-time and analysis integrity, every diagnostic kind\ndeclared in `kind.def` **MUST** be mapped to **one and only one** C++ macro\ndeclaration (`CARBON_DIAGNOSTIC` or `CARBON_DIAGNOSTIC_ON_SCOPE`).\n\n-   **DO NOT** duplicate diagnostic definitions across different locations.\n-   The C++ representation of the diagnostic is a static/global constant of type\n    `DiagnosticBase<Args...>`.\n-   **Local Scope (Recommended)**: If the diagnostic is unique to a single\n    block/function body, declare it **locally** inside the function body\n    adjacent to its `Emit` trigger:\n\n    ```cpp\n    void ConvertFloatValueToInt(...) {\n      CARBON_DIAGNOSTIC(FloatNaNConvertedToInt, Error,\n                        \"cannot convert NaN to integer type {0}\", SemIR::TypeId);\n      context.emitter().Emit(loc_id, FloatNaNConvertedToInt, dest_type_id);\n    }\n    ```\n\n-   **File Scope**: If the diagnostic is shared among multiple functions inside\n    the _same_ file, declare it at **file scope** inside the anonymous namespace\n    of the `.cpp` file.\n-   **Global Scope**: If a diagnostic (such as a shared helper label) is reused\n    _across different physical files_, define it in a shared header (e.g.\n    context/check helpers) and mark it `extern` where applicable, ensuring the\n    macro is only invoked once.\n\n---\n\n## 2. Formatting Diagnostic Arguments\n\nCarbon diagnostics leverage LLVM's `formatv` engine. Parameters must be passed\nusing strongly-typed arguments to preserve translation capability.\n\n### String Lifetimes & Pitfalls\n\n-   **`llvm::StringRef` is DISALLOWED**: Do not pass `StringRef` as a parameter\n    type to `CARBON_DIAGNOSTIC` due to unsafe lifetime and buffer-allocation\n    boundaries.\n-   **`llvm::StringLiteral` is DISALLOWED**: Do not use literal types as\n    arguments as they prevent future diagnostic localization and translations.\n-   **Use `std::string`**: If string formatting or custom allocations are\n    required, declare the parameter storage type as `std::string`.\n\n### Format Selectors (`format_providers.h`)\n\nUse specialized formatting wrappers under\n[format_providers.h](../../../toolchain/diagnostics/format_providers.h) to\nexpress clean inline options in format strings:\n\n| Wrapper                    | Target Format Style             | Example Usage                  | Output                                                              |\n| :------------------------- | :------------------------------ | :----------------------------- | :------------------------------------------------------------------ |\n| **`BoolAsSelect`**         | `{Index:true\\|false}`           | `\"{0:is signed\\|is unsigned}\"` | Maps bool to selection string.                                      |\n| **`IntAsSelect`**          | `{Index:=Val:String\\|:Default}` | `\"{0:=1:is\\|:are}\"`            | Matches exact options.                                              |\n| **`IntAsSelect` (Plural)** | `{Index:s}`                     | `\"{0} argument{0:s}\"`          | Prints `\"s\"` if value != 1 (e.g., `\"1 argument\"`, `\"3 arguments\"`). |\n\n### Custom Toolchain Type Mappings\n\nCustom structures can define how they serialize inside diagnostics using the\n`DiagnosticType` tag mapping to `Diagnostics::TypeInfo<StorageType>`:\n\n-   **Identifiers & Names** (declared in `check/diagnostic_helpers.h`):\n    -   `NameId`: Formats raw identifier spelling, safely escaping keyword\n        conflicts under backticks automatically.\n    -   `LibraryNameId`: Formats custom library descriptors cleanly (e.g.\n        `default library` or `library \"foo\"`).\n-   **Sized Primitives**:\n    -   `TypedInt`: Formats an `APInt` constant exactly, extracting target\n        signedness representation automatically from its bound type\n        representation.\n-   **Type Formatter Hierarchy**: When choosing parameter types to print\n    compiler type representations, follow this priority list:\n    1.  **`TypeOfInstId` (Preferred)**: Resolves the backing type of an\n        `InstId`, preserving programmatic aliasing, constraints, and source\n        spelling context. Enclosed under backticks automatically.\n    2.  **`InstIdAsType`**: Converts an `InstId` for a type expression, printing\n        custom type layouts under backticks.\n    3.  **`TypeId` (Fallback)**: Canonical description of the type. **Avoid when\n        possible** because type canonicalization loses intermediate source\n        program spelling and aliasing metadata.\n    4.  **`*AsRawType` (e.g. `InstIdAsRawType`, `TypeIdAsRawType`)**: Formats\n        the type layout exactly like their counter-structures above, but\n        **omits** enclosing backticks (useful when inserting types inside larger\n        code snippets).\n\n---\n\n## 3. Fluent Emission Builders & RAII Scopes\n\n### Fluent Builder Pattern\n\nA diagnostic is one message plus the labels that mark the source explaining it.\nUse `Build` to state the message and `Attach` to mark each place the reader has\nto look, chained fluently:\n\n```cpp\nCARBON_DIAGNOSTIC_LABEL(ModifierPrevious, Info, \"`{0}` previously appeared here\",\n                        Lex::TokenKind);\n\ncontext.emitter()\n    .Build(second_node, ModifierRepeated, context.token_kind(second_node))\n    .Attach(first_node, ModifierPrevious, context.token_kind(first_node))\n    .Emit();\n```\n\nLabels are declared with `CARBON_DIAGNOSTIC_LABEL` where they are attached, and\nare not registered in `kind.def`; `check_diagnostics.py` checks that each one is\nattached and covered. A label is either `Primary` -- the range the message\nitself is about -- or `Info`, for somewhere else the reader must look; those two\nare the only categories, because anything not read against the code it names is\nnot a label. `Attach(loc)` with no label marks a range wordlessly, which is what\nto use when a label would only restate the message.\n\nEvery diagnostic should attach at least one label; a message with nothing\nattached has nothing to show. See\n[diagnostics.md](../../../toolchain/docs/diagnostics.md) for which range to pick\nand when a label earns words.\n\n> [!SAFETY] Emitter builders are marked `[[nodiscard]]`. To prevent a developer\n> from creating a builder but failing to terminal-chain `.Emit()`, the builder\n> uses an rvalue overload `Emit() &&` that triggers a compile-time\n> `static_assert(false)`. You must save the builder to an lvalue or execute the\n> chain exactly as `emitter.Build(...).Attach(...).Emit()`.\n\n### RAII Context & Annotation Scopes\n\nManage large checking structures requiring blanket context using RAII block\nscopes:\n\n-   `ContextScope`: Attaches a context to every diagnostic emitted within its\n    scope, describing the higher-level operation that failed because of it. A\n    context is declared with `CARBON_DIAGNOSTIC_CONTEXT`, or\n    `CARBON_DIAGNOSTIC_SOFT_CONTEXT` for one dropped when the diagnostic\n    already has a context:\n\n    ```cpp\n    Diagnostics::ContextScope diagnostic_context(\n        &context.emitter(), [&](auto& builder) {\n          CARBON_DIAGNOSTIC_CONTEXT(\n              QualifiedDeclInIncompleteClassScope,\n              \"cannot declare a member of incomplete class {0}\", SemIR::TypeId);\n          builder.Attach(loc_id, QualifiedDeclInIncompleteClassScope,\n                         context.classes().Get(class_id).self_type_id);\n        });\n    ```\n\n    A context is not a label: its text stands alone as a sentence, which is why\n    it leads the diagnostic rather than following it.\n\n-   `AnnotationScope`: RAII block scope that attaches labels to every diagnostic\n    emitted within it, using the same `Builder` as a direct emission.\n\n---\n\n## 4. Diagnostics Wording Style Guide\n\nRefer to the official\n[Diagnostic message style guide](../../../toolchain/docs/diagnostics.md#diagnostic-message-style-guide)\nfor complete details.\n\nTo maintain message consistency and integrate cleanly with Clang diagnostics in\ninteroperable code, adhere strictly to these rules:\n\n-   **Start with lowercase and omit periods**: Start diagnostic messages with a\n    lowercase letter or quoted code, and do **not** end them with a period\n    (e.g., `\"cannot convert...\"` or ``\"`self` declared...\"``).\n-   **Use backticks for quoted code**: Enclose identifiers, code constructs, and\n    types inside standard backticks (e.g., ``\"`{0}` is bad\"``).\n-   **Phrase as bullet points without articles**: Phrase diagnostics as\n    descriptive bullet points or sentence fragments rather than full sentences.\n    Leave out standard articles (`a`, `an`, `the`) unless necessary for logical\n    clarity. Semicolons can be used to separate fragments within a message.\n-   **Describe the situation and language rule**: Diagnostics should describe\n    the exact situation the toolchain observed. The language rule violated can\n    be mentioned if it wouldn't otherwise be clear:\n    -   _Situation-only_: `\"redeclaration of X\"` (implies that redeclaration is\n        not permitted).\n    -   _Rule-inclusion_: ``\"`self` declared in invalid context; can only be\n        declared in implicit parameter list\"``.\n-   **Wording Choice (\"cannot\" vs \"allowed\")**: Explicitly avoid `\"allowed\"`,\n    `\"legal\"`, `\"permitted\"`, `\"valid\"`, and related passive wording. You may\n    use `\"cannot\"` if needed, but try to use phrasing that does not require it:\n    -   _Correct_: ``\"`export` in `impl` file\"`` (Avoids `\"allowed\"`)\n    -   _Incorrect_: ``\"`export` is only allowed in API files\"``\n    -   _Correct_: ``\"`extern library` specifies current library\"`` (Avoids\n        `\"cannot\"`)\n    -   _Incorrect_: ``\"`extern library` cannot specify the current library\"``\n-   **Developer Intent Hints**: It is acceptable for a diagnostic to guess at\n    the developer's intent and provide a hint _after_ explaining the situation\n    and the rule, but never as a substitute for that:\n    -   _Correct_: ``\"cannot implicitly convert `i32` to `String`; add `as\n        String` for explicit conversion\"``\n    -   _Incorrect_: ``\"add `as String` to convert `i32` to `String`\"`` (Lacks\n        the core violation message).\n-   **Structure for Tooling API**: Try to structure diagnostics such that\n    parameter inputs can be programmatically extracted without string parsing\n    (prefer strongly-typed parameters over format placeholders where possible).\n\n---\n\n## 5. Diagnostics Testing & Coverage Verification\n\nCarbon strictly enforces testing coverage at build-time.\n\n1.  **Tag Verification Requirement**: Every diagnostic kind declared in\n    `kind.def` (which is not blacklisted in the `UntestedKinds` array under\n    [coverage_test.cpp](../../../toolchain/diagnostics/coverage_test.cpp))\n    **MUST** be verified by at least one testcase file inside\n    `toolchain/*/testdata/`.\n2.  **Stderr Checklist Matchers**: The testcase split verifying the diagnostic\n    must catch it using standard CHECK matchers, explicitly tracking the\n    matching enum tag in standard error comments:\n\n    ```carbon\n    // CHECK:STDERR: fail_bounds.carbon:[[@LINE+1]]:15: error: cannot convert NaN to integer type `i32` [FloatNaNConvertedToInt]\n    let a: i32 = Convert(nan_val);\n    ```\n\n3.  **Build Enforcement**: Failing to provide a diagnostic test check matcher\n    triggers a failure on the target test\n    `//toolchain/diagnostics:coverage_test`.\n4.  **Label Enforcement**: A label is declared where it is attached rather than\n    in a central registry, so `coverage_test` has no list of labels to compare a\n    matched name against and leaves any name that isn't a kind alone.\n    [check_diagnostics.py](../../../toolchain/diagnostics/check_diagnostics.py)\n    is what checks them: it reads the declarations and the testdata directly, so\n    it catches a label with no test, a name matched on that is neither a kind\n    nor a label, and a kind registered in `kind.def` that nothing declares. It\n    runs as a pre-commit hook, which CI runs too, rather than as a bazel test --\n    reading every source file is what it needs and what a test in the sandbox\n    cannot do.\n",".agents/skills/github_cli/SKILL.md":"---\nname: GitHub CLI usage\ndescription:\n    Instructions for using the `gh` command to query and inspect GitHub state\n    safely.\n---\n\n# GitHub CLI usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill provides instructions for using the GitHub CLI (`gh`) to query,\ninspect, and search GitHub state (issues, pull requests, repositories) for the\nCarbon project.\n\n## Safety First: Read-Only Usage\n\n> [!IMPORTANT] AI assistants MUST NOT use the `gh` tool to modify any GitHub\n> project state. Do NOT run commands that create, edit, delete, label, comment\n> on, or merge issues, pull requests, releases, or any other resources.\n\n### Allowed Verbs\n\n-   `list`\n-   `view`\n-   `search`\n-   `status`\n-   `api` (Only with `GET` requests)\n\n### Prohibited Verbs\n\n-   `create`\n-   `edit`\n-   `delete`\n-   `merge`\n-   `reopen`\n-   `close`\n-   `comment`\n-   `label`\n\n## Repository Configuration\n\nThe `gh` tool interacts with a default repository when run within a local check\nout. For this project, the default repository is expected to be\n`carbon-language/carbon-lang`.\n\n### Verifying Default Repository\n\nTo verify the current default repository configuration:\n\n```bash\ngh repo view\n```\n\nThe output should indicate the repository is `carbon-language/carbon-lang`.\n\n### Correcting Misconfigurations\n\nIf the default repository is misconfigured (for example, pointing to a personal\nfork or a different repository), the human operator must correct it.\n\n> [!IMPORTANT] AI Assistants MUST NOT attempt to mutate `gh` configuration or\n> run commands that change the default repository (such as\n> `gh repository set-default`).\n\nInstruct the human operator to run the following command to select the correct\ndefault repository:\n\n```bash\ngh repo set-default\n```\n\nThe operator will be prompted to select the correct repository (e.g.,\n`carbon-language/carbon-lang`) from the available remotes.\n\n## Common Query Commands\n\n### Issues\n\n-   **List issues**: `gh issue list`\n-   **View specific issue**: `gh issue view <number>`\n-   **Search issues**: `gh issue search \"<query>\"`\n    -   Example: `gh issue search \"crash\" --state open`\n\n### Pull Requests\n\n-   **List PRs**: `gh pr list`\n-   **View specific PR**: `gh pr view <number>`\n-   **View PR diff**: `gh pr diff <number>`\n-   **Check PR status**: `gh pr status`\n\n### Search\n\n-   **Search code**: `gh search code \"<query>\"`\n-   **Search repositories**: `gh search repos \"<query>\"`\n\n## Advanced Usage: GitHub API\n\nFor queries that are not supported by standard `gh` commands, you can use the\n`gh api` command to query the GitHub REST or GraphQL APIs.\n\n### REST API\n\nQuery the REST API using paths relative to the API root.\n\n-   **List contributors**:\n\n    ```bash\n    gh api repos/carbon-language/carbon-lang/contributors\n    ```\n\n-   **List issue comments**:\n\n    ```bash\n    gh api repos/carbon-language/carbon-lang/issues/<issue_number>/comments\n    ```\n\n### GraphQL API\n\nFor complex queries, use GraphQL to fetch exactly the data needed.\n\n-   **Get repository information**:\n\n    ```bash\n    gh api graphql -f query='\n      query {\n        repository(owner: \"carbon-language\", name: \"carbon-lang\") {\n          description\n          stargazerCount\n        }\n      }\n    '\n    ```\n\n### Pagination\n\nUse the `--paginate` flag to automatically fetch all pages of results.\n\n```bash\ngh api --paginate repos/carbon-language/carbon-lang/issues\n```\n\n### Filtering and Formatting\n\nUse `--json` to request JSON output, and `--jq` or `--template` to filter or\nformat the results.\n\n-   **List PR titles and authors**:\n\n    ```bash\n    gh pr list --json title,author --jq '.[] | \"\\(.title) by \\(.author.login)\"'\n    ```\n\n-   **Format with Go templates**:\n\n    ```bash\n    gh issue list --template '{{range .}}{{.number}} - {{.title}}{{\"\\n\"}}{{end}}'\n    ```\n\n## Documentation References\n\n-   **GitHub CLI Manual**:\n    [cli.github.com/manual](https://cli.github.com/manual/)\n-   **GitHub REST API Documentation**:\n    [docs.github.com/en/rest](https://docs.github.com/en/rest)\n-   **GitHub GraphQL API Documentation**:\n    [docs.github.com/en/graphql](https://docs.github.com/en/graphql)\n",".agents/skills/github_issues/SKILL.md":"---\nname: Accessing GitHub issues\ndescription:\n    Instructions for safely viewing and accessing GitHub issues by way of\n    command line.\n---\n\n# Accessing GitHub issues\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill provides instructions for AI assistants on how to access and view\nGitHub issues. Agents should strongly prefer using the command line `gh` tool to\naccess and view the contents of issues rather than viewing their contents by way\nof a web browser.\n\n## Safety First\n\n> [!IMPORTANT] AI assistants MUST NOT modify any GitHub issue state. Only use\n> read-only access commands like `view` or `list`. Do NOT comment, edit, create,\n> close, or delete issues.\n\n## Accessing Issues\n\nAgents must use this skill to access issues regardless of how they are mentioned\n(for example, by URL or by issue number).\n\n### Basic View\n\nTo view an issue in the current default repository (expected to be Carbon):\n\n```bash\ngh issue view <issue_number>\n```\n\n### Including Full Context (All Comments)\n\nTo ensure the view includes the entire context of the issue, always include the\n`--comments` flag to dump all comments:\n\n```bash\ngh issue view <issue_number> --comments\n```\n\n> [!TIP] If the issue is extremely large and comments are truncated, or you need\n> to process comments programmatically, use the JSON output with `jq`:\n>\n> ```bash\n> gh issue view <issue_number> --json comments --jq '.comments[].body'\n> ```\n\n### Accessing Issues in Other Repositories\n\nTo view an issue in another repository (for example, LLVM), use the `-R` or\n`--repo` flag to specify the repository:\n\n```bash\ngh issue view <issue_number> -R <owner>/<repo> --comments\n```\n\nExamples:\n\n-   **LLVM Issue**:\n\n    ```bash\n    gh issue view 5678 -R llvm/llvm-project --comments\n    ```\n\n-   **Carbon Issue (Explicit)**:\n\n    ```bash\n    gh issue view 1234 -R carbon-language/carbon-lang --comments\n    ```\n\n## Mentions via URL\n\nIf an issue is mentioned via URL, parse the URL to extract the repository owner,\nrepository name, and issue number.\n\n-   **URL pattern**: `https://github.com/<owner>/<repo>/issues/<number>`\n-   **Extraction**:\n    -   Host: `github.com`\n    -   Owner: `<owner>`\n    -   Repo: `<repo>`\n    -   Number: `<number>`\n\nRun the command specifying the repository:\n\n```bash\ngh issue view <number> -R <owner>/<repo> --comments\n```\n",".agents/skills/jj/SKILL.md":"---\nname: Jujutsu (jj) usage\ndescription:\n    Instructions for using Jujutsu (jj) for version control in the Carbon\n    repository.\n---\n\n# Jujutsu (jj) usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Jujutsu](https://github.com/jj-vcs/jj) is a Git-compatible version control\nsystem that may be used in Carbon checkouts.\n\n> [!IMPORTANT] You can detect if Jujutsu is in use by checking for a `.jj`\n> directory in the repository root. If present, you **must** use `jj` and **must\n> not** use `git`. If absent, you **must not** use `jj`.\n\n## General usage\n\nAlways use the `--no-pager` flag when invoking `jj` to prevent the command from\nblocking or waiting for terminal paging.\n\n## Common commands\n\n### Syncing with remote\n\n-   **Fetch from remote**: `jj --no-pager git fetch`\n-   **Create a new change on top of trunk**: `jj --no-pager new trunk`\n-   **Show repository status**: `jj --no-pager status`\n-   **Show commit history**: `jj --no-pager log`\n\n### Managing changes\n\n-   **View diff of current changes**: `jj --no-pager diff`\n-   **Commit changes**: `jj --no-pager commit`\n    -   _Note_: Prefer using `jj commit` over the combination of `jj describe`\n        and `jj new`.\n-   **Abandon/discard current changes**: `jj --no-pager abandon`\n-   **Rebase current change onto trunk**: `jj --no-pager rebase -o trunk`\n\n### Working with a stack of changes\n\nA change is often built as a stack of commits sent up as a single pull request.\nThe stack is not necessarily based on `trunk`; it may be based on another change\nthat is itself still in flight.\n\n> [!WARNING] **Never rewrite the history of a change that has been submitted as\n> a pull request.** Reviewers track a PR by its commits, and squashing,\n> reordering, or abandoning them discards review that is already in progress.\n> This cannot be undone from their side.\n>\n> Before rewriting history in any other case, propose the exact command and wait\n> for confirmation. This applies to `squash`, `rebase`, `abandon`, and\n> `describe` on an existing change.\n\n#### Finding the base of the stack\n\nBookmarks delimit the stack. List the bookmarks that are ancestors of the\nworking copy, nearest first:\n\n```bash\njj --no-pager log -r '::@ & bookmarks()'\n```\n\nReading the result takes care, because two situations produce similar output:\n\n-   **Editing an existing change.** The nearest bookmark names the change being\n    worked on, and the bookmark below it is the base.\n-   **Starting a new change.** The commits above the nearest bookmark have no\n    bookmark of their own yet, so the nearest bookmark is itself the base.\n\n`trunk` is only ever a base. Finding `trunk` nearest means new work is being\nbuilt on top of it, never that `trunk` itself is being worked on.\n\nThe graph does not distinguish the two cases: an unbookmarked or empty commit\nabove a bookmark may be the next commit of that change or the start of a new\none. Ask which it is when it is not clear, and ask before choosing where a fix\nshould land rather than after. Guessing wrong means squashing into a change that\nmay already be under review.\n\nOnce the base is known, use it to scope commands to the current stack:\n\n```bash\njj --no-pager log -r '<base-bookmark>..@'\n```\n\n#### Managing the stack\n\n-   **Fold a fix into an earlier change**:\n    `jj --no-pager squash --into <change-id> [path]`. Follow-up fixes and\n    formatter reflows belong in the change that introduced the code, not in a\n    trailing \"fixes\" commit, unless that change has already been submitted.\n    Naming a path squashes only that part of the working copy, leaving unrelated\n    work in place.\n-   **Descriptions**: only one change in the stack needs a long description, the\n    one used as the pull request description. Every other change gets a short\n    one-line summary. Do not repeat the long text across the stack.\n",".agents/skills/language_server/SKILL.md":"---\nname: Language server\ndescription:\n    Instructions for working on Carbon's LSP language server, including its\n    architecture, its file_test-based tests, and the VS Code extension.\n---\n\n# Language server\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Introduction\n\nThis skill covers [`toolchain/language_server/`](/toolchain/language_server/),\nwhich implements `carbon language-server`, and\n[`utils/vscode/`](/utils/vscode/), the VS Code extension that launches it.\n\n## Architecture\n\nThe server is built on clangd's LSP transport (`clang::clangd`), not on a\nCarbon-specific one. That means clangd's `Protocol.h` types (`Position`,\n`Range`, `Location`, `Hover`, `MarkupContent`) are the interface currency.\n\n-   `server.cpp` / `incoming_messages.cpp`: message dispatch. A handler must be\n    registered in `incoming_messages.cpp` before it can be called.\n-   `handle_*.cpp`: one file per request family, each declaring its entry point\n    in `handle.h`.\n-   `handle_initialize.cpp`: the advertised capabilities. **Adding a capability\n    changes `Content-Length` in every test that calls `initialize`**, so expect\n    a large autoupdate diff.\n-   `context.h` / `context.cpp`: `Context::File` per open document, plus the\n    compile driver. `Context::File::unit()` has a `CARBON_CHECK` on the compile\n    driver, so any handler that reaches for the parse tree must first rule out\n    documents that were never compiled.\n-   `position.h`, `sem_ir_index.h`: mapping source positions to SemIR\n    instructions for real Carbon files.\n-   `sem_ir_text.h`, `handle_sem_ir_text.h`: navigation within the *formatted\n    SemIR* in a test file's `// CHECK:STDOUT:` lines. This is a heuristic text\n    index, deliberately independent of the real SemIR data structures. See\n    [the SemIR text reader](#the-semir-text-reader).\n\n### Document kinds\n\nThe server handles two kinds of document, distinguished by the `languageId`\nfrom `textDocument/didOpen`, with a content sniff as a fallback:\n\n-   `carbon`: a real Carbon file. Compiled; diagnostics published.\n-   `carbon-testdata`: a test file. **Not compiled**, because we lack logic to\n    split it into one file per `// ---` split marker.\n\n> [!IMPORTANT]\n> A handler that assumes every file was compiled will crash on a test file.\n> When adding one, give the test-file path an explicit early return.\n\n## Tests\n\nThere is **no language-server-specific test target**.\n`toolchain/language_server/BUILD` only declares\n`filegroup(name = \"testdata\")`, which is pulled into\n`//toolchain/testing:all_testdata` and run by `//toolchain/testing:file_test`.\n\n```bash\n# Run just the language server tests (or any subset).\nbazelisk test //toolchain/testing:file_test \\\n    --test_arg=--file_tests=toolchain/language_server/testdata/position/hover_and_goto.carbon\n\n# See the raw output, which is much easier to read than a test failure.\nbazelisk run //toolchain/testing:file_test -- --dump_output \\\n    --file_tests=toolchain/language_server/testdata/position/hover_and_goto.carbon\n\n# Update expectations. Never hand-write CHECK lines.\n./toolchain/autoupdate_testdata.py toolchain/language_server/testdata/...\n```\n\nThese tests run serially, because clangd's logging is a global singleton.\n\n### Test file shape\n\nThe request stream is a `// --- STDIN` split written with the `[[@LSP-*]]`\nkeywords, and the responses land in a trailing `// --- AUTOUPDATE-SPLIT`.\nDocuments come from other splits by way of `\"text\": \"FROM_FILE_SPLIT\"`, which\nis substituted with the content of the split whose name matches the `uri`.\n\n```carbon\n// --- position.carbon\nfn Abs(n: i32) -> i32 { return n; }\n\n// --- STDIN\n[[@LSP-CALL:initialize:\"capabilities\": {}]]\n[[@LSP-NOTIFY:textDocument/didOpen:\n  \"textDocument\": {\n    \"uri\": \"file:/position.carbon\",\n    \"languageId\": \"carbon\",\n    \"text\": \"FROM_FILE_SPLIT\"\n  }\n]]\n[[@LSP-CALL:textDocument/hover:\n  \"textDocument\": {\"uri\": \"file:/position.carbon\"},\n  \"position\": {\"line\": 0, \"character\": 3}\n]]\n[[@LSP-CALL:shutdown]]\n[[@LSP-NOTIFY:exit]]\n\n// --- AUTOUPDATE-SPLIT\n```\n\nFull keyword documentation is in\n[`testing/file_test/README.md`](/testing/file_test/README.md).\n\n### Traps\n\n> [!WARNING]\n> **A blank line inside the `STDIN` split breaks the JSON transport.** It\n> terminates a header block, so clangd logs a timestamped\n> `Warning: Missing Content-Length header, or zero-length message.` The\n> timestamp makes the test unreproducible, so it fails on the next run.\n> Comment lines between messages are fine; blank lines are not. A single blank\n> line immediately before `// --- AUTOUPDATE-SPLIT` is also fine.\n\nOther things worth knowing:\n\n-   **`positionEncoding` is UTF-16.** A `character` is a UTF-16 code unit\n    offset, not a byte offset.\n-   **Line and character numbers in requests are 0-based**, while the `locN_M`\n    suffixes in SemIR output are 1-based. Off-by-ones here are silent: the\n    request succeeds and returns the wrong thing.\n-   **A split can hold a document that itself contains `// CHECK:STDOUT:`\n    lines**, because `CHECK` lines only form expectations inside the\n    `AUTOUPDATE-SPLIT`. Such a document still can't contain a literal `// ---`\n    line, which would split the enclosing test file; write it as\n    `[[@0x2f]]/ --- name.carbon`.\n\n## The SemIR text reader\n\n`sem_ir_text.cpp` indexes the formatted SemIR inside a test file's\n`// CHECK:STDOUT:` lines so that hover and go-to-definition work on operand\nnames. It is a heuristic reader, not a parser, and its correctness rests on\nfacts about `toolchain/sem_ir/formatter.cpp` and\n`toolchain/sem_ir/inst_namer.cpp`. Re-check these if the formatter changes:\n\n-   There are exactly four scope keywords: `file`, `generated`, `imports`, and\n    `constants` (`InstNamer::GetScopeName`). Everything else is `@entityname`.\n-   A reference is `%name` within its own scope and `scope.%name` otherwise\n    (`InstNamer::GetNameFor`). Names may contain `.` and may _start_ with one,\n    as in `%.Self.frozen`.\n-   **Type annotations are printed in the `constants` scope.**\n    `Formatter::FormatTypeOfInst` does\n    `llvm::SaveAndRestore file_scope(scope_, InstNamer::ScopeId::Constants)`,\n    so in `%x: %foo = ...` a bare `%foo` means `constants.%foo`. This does not\n    apply to ordinary operands or to `[concrete = ...]` annotations.\n-   **`*_decl` braces hold the declared entity's scope.** The braces of\n    `%F.decl: ... = fn_decl @F [...] { ... } { ... }` are lexically inside\n    `file { }`, but their names belong to `@F`.\n-   **`!with Self:` switches scope without a brace**, until `!members:`\n    switches it back. Brace counting alone cannot see this.\n-   A `specific @F(args) { }` block uses `@F`'s scope and defines nothing; each\n    `%name => value` row references an instruction of the generic.\n\n### Validating a change to the reader\n\nThe unit tests only cover a handful of cases. To check a change against the\nreal corpus, drive the server over a sample of check testdata, hovering on\nevery `%name`, and compare the resolved fraction before and after. Roughly 99%\nof names resolve; the residue are names the formatter references but never\nemits a definition line for, such as `%I.WithSelf.F`, which only ever appears\ninside a `[symbolic = ...]` annotation.\n\nTwo things to get right in such a harness:\n\n-   Feed the request stream from a **file**, not a pipe. The server reads stdin\n    as a file and reports `error: Input/output error` on a pipe.\n-   Read the output as **bytes**. Python's `text=True` rewrites the `\\r\\n`\n    framing, and `Content-Length` counts bytes.\n\n## VS Code extension\n\n[`utils/vscode/`](/utils/vscode/) declares three languages in `package.json`:\n\n| Language id      | Applies to                        |\n| ---------------- | --------------------------------- |\n| `carbon`         | `*.carbon`                        |\n| `carbon-testdata`| `**/testdata/**/*.carbon`         |\n| `semir`          | `*.semir`                         |\n\n> [!NOTE]\n> The TextMate _scope_ for SemIR is `source.carbon-semir`, but the\n> _language id_ is `semir`. Markdown code fences in hover text resolve language\n> ids, so a fence must say ` ```semir `.\n\n`extension.ts` launches the server over stdio, using the `carbonPath` setting\n(default `./bazel-bin/toolchain/carbon`). Its `documentSelector` controls which\nfiles are sent to the server at all; a new document kind has to be added there\nas well as in the server.\n",".agents/skills/prek/SKILL.md":"---\nname: Prek\ndescription:\n    Instructions for running prek, the Carbon pre-submit/style/lint checker,\n    that *MUST* be run before submitting an change.\n---\n\n# Prek\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n`prek` is the Carbon pre-submit, style, and lint checker. Running it is\nmandatory before submitting any changes.\n\n## Running prek\n\nTo run `prek` on all files:\n\n```bash\nprek run -a\n```\n\nTo validate a specific list of files:\n\n```bash\nprek run --files <files>\n```\n\n## Running prek in a Jujutsu (jj) workspace\n\nIf you are working in a Jujutsu workspace, running `prek` directly will fail\nbecause it expects a standard Git repository structure. Instead, use the helper\nscript:\n\n```bash\n./scripts/jj_prek.sh\n```\n\nThis script runs `prek` on all files that have changed between `trunk` and your\ncurrent Jujutsu `@` change.\n\nNote that the script always compares against `trunk`. If your change is based on\nanother bookmark rather than on `trunk`, the script also checks the files\nchanged by that underlying change, so a reported failure may not be in your own\nwork.\n\n## Hooks that rewrite files\n\nSome hooks, notably `clang-format` and `rumdl`, fix problems in place rather\nthan only reporting them. When they do, `prek` reports a failure and exits\nnon-zero even though the tree is now correct.\n\nRe-run `prek` after any failure that modified files, and treat the second, clean\nrun as the result. Review what it changed: a reflow is expected, but a content\nchange may not be what you intended.\n\n## Prek dependency errors\n\n> [!TIP] If `prek` fails with an error about resolving dependencies or security\n> policy, you may be running in a restricted environment where the\n> special-purpose `gpkg` tool is required. Prefix the command with `gpkg`, for\n> example: `gpkg prek run -a` or `gpkg ./scripts/jj_prek.sh`.\n",".agents/skills/proposals/SKILL.md":"---\nname: Proposals\ndescription:\n    Instructions for writing, submitting, and managing Carbon evolution\n    proposals.\n---\n\n# Proposals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Overview\n\nThis skill provides instructions and best practices for working with proposals.\nOnly create a proposal when explicitly directed as part of the task.\n\nMake sure to confirm the desired title for the proposal as that will govern the\nfilename.\n\n## Create a new proposal\n\n1.  **Use the helper script**: Run `./proposals/scripts/new_proposal.py \"Title\"`\n    to create a templated file and instructions for setting up the PR.\n2.  **Proposal file**: The file will be named `proposals/p######-title.md`,\n    where `######` is the 6-digit GitHub pull request number and `title` is a\n    slugified version of the proposal title.\n3.  **Template**: Follow the structure in `proposals/scripts/template.md`,\n    noting the specific `TODO` instructions in each section for the content that\n    should be included there.\n4.  **PR description**: Update the pull request description to match the\n    abstract section in the proposal document.\n\n> [!IMPORTANT] Do _not_ mark the PR ready for review. The user must have the\n> opportunity to review the proposal produced before asking for any review.\n\n## Writing style and best practices\n\n-   **Skimmable**: Use\n    [BLUF](<https://en.wikipedia.org/wiki/BLUF_(communication)>) (Bottom Line Up\n    Front) or\n    [Inverted Pyramid](<https://en.wikipedia.org/wiki/Inverted_pyramid_(journalism)>)\n    style. Keep it brief, focused, and technical.\n-   **Match existing proposal style**: Review [existing proposals](/proposals)\n    (preferring more recent ones with higher numbers) to understand the expected\n    style, wording, and nature of content to include.\n-   **Connect to goals**: In the Rationale section, link to specific goals in\n    [`/docs/project/goals.md`](/docs/project/goals.md) and principles in\n    [`/docs/project/principles`](/docs/project/principles) (e.g.,\n    `error_handling.md`, `one_way.md`).\n-   **Living design**: If the proposal updates design documentation, include\n    those changes in the PR if possible. If deferred, add \"TODO\" comments\n    pointing to the proposal (e.g., `> **TODO:** Document ... adopted in\n    [p######](/proposals/p######-title.md)`). For pervasive changes, file a\n    GitHub issue instead of adding many TODOs.\n\n## Alternatives considered and leads decisions\n\nThere are always alternatives to a proposal, and the proposal should carefully\ninclude sections describing all of them and the rationale for not selecting\nthem. Any living design document updates should focus on fully describing the\nend-state design, and the key motivating aspects of that design. The main\nproposal should focus on _what is changing_ and _why it is changing_, and should\nleave detailed description of the resulting design to the living design\ndocument, and _why not_ rationale to the description of each alternative.\n\n-   **Cover all the alternatives**: Make sure to describe any alternatives\n    considered, even if minor or rejected early.\n-   **Be specific**: Don't be vague about any of the alternatives, or the\n    rationale for not choosing them.\n-   **Connect to goals or principles**: In addition to the rationale section,\n    one of the best rationale structures for rejecting an alternative connects\n    that choice back to the goals or principles relevant.\n-   **Always frame as a tradeoff**: Selecting the proposed direction instead of\n    an alternative is _always_ a tradeoff, with both advantages and\n    disadvantages.\n-   **Where relevant, cite the leads issue** that decides against an\n    alternative, in addition to summarizing the key points, tradeoffs, and\n    rationale for the decision.\n\n> [!IMPORTANT] Don't just list the alternatives, create a sub-section for each\n> alternative and carefully describe the alternative, the advantages,\n> disadvantages and what the core of the decision is to reject each alternative.\n\n> [!IMPORTANT] Carefully research each alternative in the leads issue in order\n> to provide this clear and comprehensive explanation.\n\n## Building from a leads issue\n\nSometimes a proposal is specifically documenting and formalizing a decided leads\nissue. When this is the case, carefully research that leads issue, reading the\noriginal issue text and every comment on the issue. Also read any linked Google\ndocuments, linked issues, examples, gists, or other supplemental information\ncited.\n\n-   **Summarize the leads issue**: Ensure you provide a high level summary of\n    the _decided_ direction of the leads issue as the proposal.\n-   **Capture and document** every key aspect of the decision made and factor\n    that led to the decision. It is important that the proposal stands alone,\n    and the leads issue is merely cited for context and history.\n-   **Stay grounded**: Only include alternatives, rationale, and arguments based\n    on what you find in the issue and related documents. No new information\n    should be in the proposal.\n\nUse the `gh` command line tool to query leads issues in order to carefully\nexamine all of the comments. Follow any mentioned links to gather more data.\nRefer to the [GitHub CLI usage skill](/.agents/skills/github_cli/SKILL.md) for\ndetailed instructions on using the `gh` tool.\n\nAsk the user to clarify any aspects of the leads issue that are unclear rather\nthan continuing to edit the proposal. If there are questions that you don't find\nan answer to in the issue, ask this to the user and let them provide an answer\nthat you use as the basis of what to include.\n\n## Examples are golden\n\nHeavily leverage examples to illustrate both the specifics of the design being\nproposed, and the nature of the change being proposed. More examples to\nillustrate more aspects, corner cases, or provide a more complete understanding\nare almost always good. Comments in example code should focus on what that part\nof the example illustrates from the proposal.\n\n## Keep the PR description in sync with the abstract\n\nWhenever you edit the abstract or notice differences from the PR description,\nyou should update the PR description to match the abstract. The only exception\nis to retain any \"Assisted-by\" or other tags at the end of the description that\nare only needed there and not in the abstract.\n\nIf you are creating or updating a proposal, make sure the PR description in\nquestion contains an `Assisted-by:` tag that is appropriate for describing which\nAI tool is being used.\n",".agents/skills/review_testdata_changes/SKILL.md":"---\nname: Review testdata changes\ndescription:\n    Instructions for judging whether changes to file test output\n    (`// CHECK:STDOUT:` and `// CHECK:STDERR:` lines) are correct, which\n    changes are acceptable churn, and which are regressions in disguise.\n---\n\n# Review testdata changes\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Introduction\n\nMost toolchain work moves file test output. `./toolchain/autoupdate_testdata.py`\nrewrites the `// CHECK:STDOUT:` and `// CHECK:STDERR:` lines in\n`toolchain/*/testdata/` to match current behavior, so after running it the tests\npass again whether or not the new behavior is right. Deciding that the new\noutput is the output you wanted is a separate, manual step, and it is the step\nthis skill covers.\n\nThree skills divide the work:\n\n-   [Toolchain tests](../toolchain_tests/SKILL.md): how to _author_ tests and\n    generate their output.\n-   This skill: how to _judge_ an output diff.\n-   [Summarize testdata changes](../summarize_testdata_changes/SKILL.md): how to\n    _report_ an output diff once you believe it is correct.\n\n> [!IMPORTANT] Never hand-edit `// CHECK:STDOUT:` or `// CHECK:STDERR:` lines.\n> Everything below is about changing the _code_ until the generated output is\n> right, never about editing the output to match the code.\n\n## The rule that generates all the others\n\n**Every line of testdata churn must have a cause you can name.** Not \"it is\nsimilar to the other changes\", not \"the tests pass now\" — an actual sentence\nsaying which code change produced it and why that is the intended result.\n\nA diff you cannot narrate is a diff you have not reviewed. Changes you cannot\nexplain are where regressions hide, because a regression and an intended change\nlook exactly alike once the autoupdater has written them down.\n\n> [!CAUTION] Autoupdating is destructive to your evidence. Once the autoupdater\n> has run, the previous expectations are gone from the working copy. Read the\n> diff after _every_ autoupdate run, and if something changed for a reason you\n> cannot name, fix the code before autoupdating again. Recovering the old\n> expectations later means reverting and re-running.\n\n## STDERR and STDOUT are different kinds of evidence\n\nTreat them separately; they have different standards of proof.\n\n**STDERR is user-visible behavior.** These are the diagnostics a Carbon\nprogrammer sees. A change here is a change to the language implementation as\nusers experience it, so each one needs an individual justification. For a\nrefactoring, the expected STDERR diff is empty.\n\n**STDOUT is internal representation.** SemIR dumps, parse trees, LLVM IR. Users\nnever see it. Churn here is normal and often unavoidable, so the standard is not\n\"no change\" but \"no change I cannot account for\".\n\nFor a change that is supposed to preserve behavior, write the list of accepted\nSTDERR changes down _before_ you autoupdate, and keep it current. Order matters\nmore than form: written first, the list is a prediction the diff can falsify;\nwritten afterwards, it is a description of whatever happened, and describes a\nregression exactly as well as an intended change.\n\nThe list does not have to be a deliverable. Scratch notes you never publish do\nthe job, because the work is in committing to the list, not in presenting it.\nWhat a reader needs is not the list but its exceptions: diagnostics that changed\nwithout being predicted, and predictions that did not occur. Both are findings.\nThe matches are not, and reporting them buries the two entries that matter.\n\n## Judging STDOUT churn\n\nSort each STDOUT change into mechanical or structural.\n\n### Mechanical churn\n\nExpected, and cheap to accept in bulk once you have confirmed the pattern:\n\n-   **Renaming.** An instruction, type, or scope prints under a new name.\n-   **Positional name renumbering.** Names like `%x.loc18_46.3` embed a line,\n    column, and disambiguating index. Two different events move them:\n    -   Adding or removing an instruction at a location renumbers the rest, so a\n        _single_ removed instruction can show up as many changed lines in the\n        same block. Confirm the cascade is a cascade before accepting it as one.\n    -   Adding or removing a _diagnostic_ moves the source lines themselves, so\n        the line component changes everywhere below it in the file. See\n        [Autoupdate to a fixed point](#autoupdate-to-a-fixed-point).\n-   **Fingerprint-derived names.** Mangled names and some scope names are\n    derived from a hash of their inputs. If you changed a hashed input, these\n    move. Confirm that each such difference is _only_ the fingerprint, and not a\n    fingerprint difference concealing a structural one.\n\n> [!TIP] Mechanical churn is usually wide and shallow: the same substitution,\n> repeated across many files. If a \"mechanical\" pattern needs a different\n> explanation in each file, it is not mechanical.\n\n### Structural churn\n\nEach of these needs its own explanation:\n\n-   Instructions appearing or disappearing.\n-   Changed `[concrete = ...]`, `[symbolic = ...]`, or other constant-value\n    annotations.\n-   Changed types on existing instructions.\n-   Changed control flow: new or removed blocks, changed branch targets.\n-   Raw instruction ids renumbering in `--dump-raw-sem-ir` output when you did\n    not intend to change the id layout.\n\n## Fewer instructions is not automatically better\n\nA diff that removes instructions looks like an optimization. Whether it is one\ndepends on what the changed function owes its caller, and two functions can\nproduce the same shrinking diff for opposite reasons:\n\n-   A function that only needs a constant value, but built instructions on the\n    way to it, was doing wasted work. Dropping them and using the constant\n    directly is correct, and the shorter output reflects that.\n-   A function whose caller needs a **non-canonical instruction** can be made\n    shorter the same way, by using the constant instead of creating an\n    instruction of its own — and that is wrong. The instruction carries location\n    information, and symbolic constant substitution operates on it; the constant\n    value alone loses both.\n\nThe instruction count is identical evidence in both cases, so it cannot be the\nthing you judge. Decide what the function is required to produce; the count\nfollows from that.\n\nThe same reasoning runs in reverse: a diff that _adds_ instructions is not\nautomatically a regression.\n\n## Judging STDERR churn\n\n### A diagnostic's authority depends on the file's prefix\n\nThe `fail_` and `todo_` prefixes (see\n[Toolchain tests](../toolchain_tests/SKILL.md)) say how much the recorded\ndiagnostics are worth:\n\n-   **`fail_...`** — the test should and does produce errors. The recorded\n    diagnostic **is the specification**. Changing it is a user-visible behavior\n    change and needs justification on its own merits.\n-   **`fail_todo_...`** — the test produces errors (or crashes) but shouldn't,\n    or produces the wrong errors. The recorded diagnostic is explicitly **not**\n    the specification; the file exists to record that today's behavior is wrong.\n    Changing it replaces one wrong answer with another. That is acceptable when\n    you can say why the new message follows from your change and why it is no\n    further from the intended eventual behavior — which, for many such files, is\n    no diagnostic at all.\n-   **`todo_fail_...`** — the test should produce errors but does not. Gaining a\n    diagnostic here may be _progress_, not a regression. Either way the file\n    must be renamed, since the framework requires a `fail_` prefix on any file\n    that errors: `fail_...` if it now produces the right error, `fail_todo_...`\n    if the error is the wrong one. Both renames make the test pass, so record\n    which case it is instead of letting the rename settle it.\n-   **`todo_...`** — behavior is wrong but produces no errors, and shouldn't.\n    Gaining a diagnostic here is a regression unless you can argue otherwise.\n\n> [!IMPORTANT] This is a reason to look at the _filename_ before judging a\n> diagnostic change, not a license to ignore `todo_` files. \"It was already\n> broken\" does not excuse making it differently broken for no reason.\n\n### Reclassifying tests\n\nIf your change moves a test between the states above, the prefix must move with\nit: when the test is fixed, when it starts failing, and when it starts failing\ndifferently. The correspondence between the `fail_` prefix and whether\ncompilation actually failed is enforced by the test framework, not by the\nautoupdater, so it surfaces when you run `bazelisk test` and not when you\nautoupdate. **Autoupdating is not a substitute for running the tests.**\n\nOnly that half of the name is checked. Nothing enforces `todo_`, so a file whose\nbehavior you have just fixed can keep its `todo_` prefix indefinitely and still\npass. A missing `fail_` stops the build; a stale `todo_` is silent, and is yours\nto catch.\n\nWhen a fix drops a file's prefix, also check that the file still belongs where\nit is and that its comments do not still describe the old broken behavior.\n\n### Vaguer diagnostics are a signal, not a verdict\n\nWhen a diagnostic becomes less specific — a general \"unsupported\" message\nreplacing one that named the problem — that usually means a code path stopped\nfinding information it previously had. Sometimes that is correct: the\ninformation was misleading, and the old message was confidently wrong.\n\nDo not accept it silently and do not reject it reflexively. Say which direction\nit moved and whether the new message is closer to or further from the eventual\nintended behavior.\n\n## Signals in the shape of the diff\n\n### Zero churn is a result\n\nIf you removed something you believed was doing work and _no_ testdata moved,\nthat is not a missing test run — it is the proof that the thing was a no-op.\nSay so explicitly; it is one of the strongest pieces of evidence a refactoring\ncan produce.\n\nThe converse is also informative. If you expected a path to churn and it didn't,\neither your model of the code is wrong or that path is untested. Find out which,\nand consider adding a test before continuing.\n\n### Churn should be proportional to the change\n\n-   **Wide churn from a narrow change** means your model of the code is wrong.\n    Do not autoupdate over it. Find the structural mistake first.\n-   **Narrow churn from a sweeping change** means the affected paths are\n    probably untested.\n\nSet a rough expectation for the size of the diff before you run the autoupdater,\nand treat a large mismatch in either direction as a finding.\n\n### Never make the diff smaller by weakening the test\n\nEditing test _input_ (the Carbon source, not the CHECK lines) to make a diff\nlook better is a behavior change in disguise. Deleting a test that now produces\nawkward output is worse. If a test's input has to change, that is a separate,\nexplicitly-justified change, not diff cleanup.\n\n## What the autoupdater will not fix for you\n\n-   **`NOAUTOUPDATE` files.** Their expectations are maintained by hand. They\n    fail under `bazelisk test` rather than being silently rewritten.\n-   **Hand-written C++ expectations**, for example golden output asserted in a\n    `_test.cpp`. When several assertions in one of these break together, often\n    only the first failure is reported, so fixing it can reveal another. Re-run\n    until clean rather than assuming one fix was the whole repair.\n-   **Golden files outside `testdata/`**, and documentation that quotes compiler\n    output.\n\n## Review loop\n\n### Run the autoupdater\n\nAutoupdate everything, then read the diff a directory at a time. Passing no\npaths is the default and updates every file test in the toolchain:\n\n```bash\n./toolchain/autoupdate_testdata.py\n```\n\nNarrow the scope only while iterating on one subdirectory you know you are not\ndone with, where each round would otherwise regenerate output you have already\nread:\n\n```bash\n./toolchain/autoupdate_testdata.py toolchain/check/testdata/SUBDIR/**/*\n```\n\nThe globs are expanded by the shell; the script filters its arguments to\n`.carbon` files under a `testdata/` directory.\n\n> [!TIP] If intermediate states crash on `CARBON_CHECK` failures, pass\n> `--non-fatal-checks` so you can see the full set of downstream damage in one\n> run instead of one crash at a time.\n\n> [!IMPORTANT] Return to the full scope before judging the diff. Whether churn\n> is proportional to the change, and whether a change to one phase moved another\n> phase's testdata, are only visible across everything.\n\n### Autoupdate to a fixed point\n\nOne pass is not always enough, because the autoupdater's output is part of its\nown input. `// CHECK:STDERR:` lines sit inline, immediately above the source\nline they describe, and the compiler reads them as comments in the file.\nGaining or losing a diagnostic therefore moves every source line below it.\n\nWithin a single run, the compiler has already read the file as it was, so the\ntwo kinds of output end up in different states:\n\n-   **STDERR is correct after one pass.** These lines locate themselves\n    relatively, as `[[@LINE+N]]`, and the autoupdater recomputes `N` as it\n    places them.\n-   **STDOUT is stale after one pass.** SemIR names like `%x.loc18_46.3` embed\n    an absolute line and column with no filename attached, and the autoupdater\n    only remaps `file.carbon:18`-style references. Nothing rewrites the `loc`,\n    so it still describes where the instruction was _before_ the diagnostic\n    lines moved it.\n\nRunning again compiles the shifted file and the names catch up. The diagnostic\nset does not change this time, so nothing shifts again and a third run is a\nno-op. Keep running the autoupdater until it stops changing files: one pass when\nthe diagnostics held still, two when they didn't.\n\n> [!WARNING] The intermediate state is self-inconsistent, not just unfinished:\n> its `loc` names describe a file layout that no longer exists. Keep reading the\n> diff after every run — that rule does not change — but do not chase positional\n> churn to a cause until the file has converged, and do not present the diff\n> until then either.\n\nThe converging pass should be positional renumbering and nothing else. If it\nmoves an instruction, a type, or a constant value, then something other than a\n`loc` name is sensitive to where lines fall in the file. Find out what before\naccepting it.\n\nThe file tests do catch a file left unconverged, since each test re-runs the\nautoupdate in memory and fails with\n`Autoupdate would make changes to the file content` when the result differs. But\nthat arrives at `bazelisk test` time, after you have already read a diff that\nwas describing a file which had moved out from under it.\n\n### Inspect the diff\n\nInspect the diagnostics first, since that is the acceptance criterion:\n\n```bash\n# STDERR-only view, with jj.\njj --no-pager diff --git 'glob:toolchain/*/testdata/**' \\\n  | grep -E '^[-+].*CHECK:STDERR'\n\n# The same, with git.\ngit diff -- 'toolchain/*/testdata/*' \\\n  | grep -E '^[-+].*CHECK:STDERR'\n```\n\nFor a structured view separating test input, STDERR, and STDOUT changes, use the\nhelper from the\n[Summarize testdata changes](../summarize_testdata_changes/SKILL.md) skill:\n\n```bash\njj --no-pager diff --git 'glob:toolchain/*/testdata/**' \\\n  | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\ngit diff -- 'toolchain/*/testdata/*' \\\n  | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n```\n\nThe argument after the tool name is not interchangeable: `glob:...` is a jj\nfileset, `-- ...` is a git pathspec. `--git` and `--no-pager` are jj flags; git\nalready emits this format and skips the pager when piped.\n\n### Run the tests\n\nThen run the tests, which is what catches prefix mismatches and non-autoupdated\nexpectations:\n\n```bash\nbazelisk test //toolchain/...\n```\n\nSee the [Bazel usage](../bazel/SKILL.md) skill.\n\n## Checklist\n\nBefore presenting a testdata diff as finished:\n\n-   [ ] The autoupdater was run until it made no further changes, so no `loc`\n        name describes a stale line numbering.\n-   [ ] The list of accepted STDERR changes was written before autoupdating, and\n        every change either matches it or is reported as an exception.\n-   [ ] Every STDOUT change is either an instance of a named mechanical pattern\n        or has its own explanation.\n-   [ ] Instructions that appeared or disappeared are justified by what the\n        changed function owes its caller, not by the instruction count.\n-   [ ] Files whose prefix no longer matches their behavior have been renamed.\n-   [ ] No test input was changed, and no test was deleted, to make the diff\n        smaller.\n-   [ ] The size of the diff is proportional to the size of the change.\n",".agents/skills/summarize_testdata_changes/SKILL.md":"---\nname: Summarize testdata changes\ndescription:\n    Instructions for summarizing changes to Carbon testdata files\n    (`toolchain/*/testdata`).\n---\n\n# Summarize testdata changes\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill provides instructions for creating a comprehensive report summarizing\nchanges to Carbon testdata files (`toolchain/*/testdata`) and associating them\nwith related code changes.\n\nThis skill is about _reporting_ a diff. For deciding whether the diff is correct\nin the first place, see the\n[Review testdata changes](../review_testdata_changes/SKILL.md) skill.\n\n## Goals\n\nProduce a report that:\n\n1.  Summarizes code changes outside of testdata.\n2.  Groups similar testdata changes together, listing all affected files for\n    each group. **Every change to testdata must be represented by at least one\n    group. This includes changes to CHECK lines.**\n3.  Provides detailed breakdowns of test input changes and diagnostic output\n    changes in the corresponding group. **Every single change to inputs or to\n    STDERR checks must be explicitly mentioned in the group, with either an\n    inline diff or a link to the file.**\n\n## Process\n\n### 1. Identify Changes\n\nUse your VCS (Git or Jujutsu) or query Github to identify changes. For large\nchanges, it is recommended to use the included helper script to extract test\ninput changes.\n\n#### For Git Users:\n\n-   **Summarize code changes**: `git diff --stat -- ':!toolchain/*/testdata/*'`\n    -   To see content of non-testdata changes:\n        `git diff -- ':!toolchain/*/testdata/*'`\n-   **Identify testdata changes**:\n    `git diff --name-only 'toolchain/*/testdata/*'`\n\n#### For Jujutsu (jj) Users:\n\n-   **Summarize code changes**:\n    `jj --no-pager diff --stat '~toolchain/*/testdata'`\n    -   Note: Quoting the fileset `'~toolchain/*/testdata'` is critical if it\n        contains wildcards.\n    -   To see content of non-testdata changes, use `--git` to get standard\n        unified diff format: `jj --no-pager diff --git '~toolchain/*/testdata'`\n-   **Identify testdata changes**:\n    `jj --no-pager diff --name-only 'toolchain/*/testdata'`\n\n#### For Github Pull Requests:\n\n-   **Summarize code changes**: `gh pr diff`\n-   **Identify testdata changes**:\n    `gh pr diff --name-only | grep '^toolchain/.*/testdata'`\n\n#### Handling Specific Revisions:\n\nIf you are summarizing changes in a specific revision (for example, `@-`) or\npull request (for example, #1234), add `-r <rev>` or `<pr_number>` to the\ncommands:\n\n-   `git diff <rev>^ <rev> ...` (or use `git show <rev>`)\n-   `jj --no-pager diff -r <rev> ...`\n-   `gh pr diff <pr_number>`\n\n### 2. Extract Test Input Changes (Recommended)\n\nTo easily identify changes, use the included Python helper script to extract all\ntext additions and removals from the diff, categorized by Input, STDERR, and\nSTDOUT changes. This script reads a unified diff from stdin.\n\n```bash\n# For Git:\ngit diff -- 'toolchain/*/testdata/*' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For Jujutsu (jj):\njj diff --git 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For a specific revision with jj:\njj diff -r @- --git 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For a specific PR with Github:\ngh pr diff 1234 | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n```\n\n### 3. Identify Patterns and Produce a List of Groups\n\n-   Read the diff and produce a list of groups of changes that share a common\n    theme or cause (for example, \"Updated expected output for integer literals\",\n    \"Added tests for new keyword\").\n-   **CRITICAL**: _Every single change_ in the testdata diff must be represented\n    by at least one group. Do not ignore changes to `CHECK` lines.\n    -   If it's not clear what group a change belongs to, create a new group for\n        it.\n-   For each group:\n    -   Provide a brief description of the group.\n    -   (Optional) Briefly note if the group appears to be an intended or\n        unintended consequence of the code changes.\n-   Divide the groups into sections:\n    -   Test Changes: Changes to test inputs (lines not prefixed with\n        `// CHECK`), along with diagnostic output changes where relevant\n    -   Diagnostic Changes: Changes to diagnostic output (lines prefixed with\n        `// CHECK:STDERR`) with no corresponding changes to test inputs\n    -   [Output Type] Changes: Changes to STDOUT (lines prefixed with `//\n        CHECK:STDOUT`)\n        -   Create one section for each relevant kind of test. For example,\n            parser tests should typically be in a \"Parse Tree Changes\" section,\n            check tests should typically be in a \"SemIR Changes\" section, and\n            lower tests should typically be in an \"LLVM IR Changes\" section.\n\n### 4. Improve Grouping\n\n-   Read the list of groups and check to see if any of them should be combined\n    or split apart. If needed, do so.\n\n### 5. Assign Changes to Groups\n\n-   Read the diff again, and then for _each_ change in the diff:\n    -   Add the change to the appropriate group (or, rarely, groups).\n    -   **CRITICAL**: _Every single change_ in the testdata diff must be\n        represented by at least one group. Do not ignore changes to `CHECK`\n        lines.\n    -   If the change affects _test inputs_ (lines not prefixed with `// CHECK`)\n        or _diagnostic output_ (lines prefixed with `// CHECK:STDERR`):\n        -   List the file within the group. Don't just give one or a few\n            examples. Include every file.\n        -   Provide an inline diff if the change is small.\n        -   Provide a link to the file if the change is large.\n    -   Otherwise, if the change only affects _STDOUT_ (lines prefixed with\n        `// CHECK:STDOUT`):\n        -   Ensure the group contains a representative example that matches the\n            current change.\n        -   The representative example should be an inline diff of the change.\n    -   **CRITICAL**: _Every single change_ to test inputs and diagnostic\n        outputs in the files being summarized must be explicitly listed in at\n        least one group. Do not skip changes, even if they are similar to\n        changes you've already seen, and do not just give examples.\n\n### 6. Validation\n\nAs a final validation step:\n\n-   Read through the testdata diff again.\n-   Ensure that every change in the diff is reflected by at least one group in\n    the report.\n\n## Report Template\n\nUse the following template for the generated report:\n\n```markdown\n# `testdata` Change Summary\n\n## Code Changes\n\n[One paragraph summarizing changes outside of testdata.]\n\n## Test Changes\n\n### [Group Name]\n\n[Description of the group.]\n\n[Change 1: diff context OR link]\n\n[Change 2: diff context OR link]\n\n...\n\n## Diagnostic Changes\n\n### [Group Name]\n\n[Description of the group.]\n\n[Change 1: diff context OR link]\n\n[Change 2: diff context OR link]\n\n...\n\n## [Output Type] Changes\n\n### [File Path]\n\n[Description of the group.]\n\n[Example diff context]\n\nChanges of this kind were found in [Number] files. Examples: [List of files]\n\n...\n```\n\nSkip sections that would be empty.\n",".agents/skills/toolchain_development/SKILL.md":"---\nname: Toolchain development\ndescription:\n    Instructions for checking, building, debugging, and understanding the Carbon\n    toolchain.\n---\n\n# Toolchain development\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Toolchain structure\n\n-   Under [`toolchain/`](/toolchain/):\n    -   [`base/`](/toolchain/base/): Base infrastructure and common utilities.\n    -   [`check/`](/toolchain/check/): Semantic analysis (SemIR generation).\n    -   [`lex/`](/toolchain/lex/): Lexing (Source -> Tokens).\n    -   [`lower/`](/toolchain/lower/): Lowering to LLVM IR.\n    -   [`parse/`](/toolchain/parse/): Parsing (Token -> Parse Tree).\n    -   [`sem_ir/`](/toolchain/sem_ir/): Semantic Intermediate Representation\n        (SemIR) definitions.\n\n## Toolchain architecture\n\n-   **Documentation**: Refer to [`toolchain/docs`](/toolchain/docs) for detailed\n    architecture design and patterns.\n    -   Refer to [Toolchain Idioms](/toolchain/docs/idioms.md) for a\n        comprehensive list of patterns (for example, `ValueStore`, formatting\n        `.def` files, struct reflection) used throughout the implementation.\n-   **Builtin Functions**: Refer to the **Builtin functions** skill\n    ([SKILL.md](../builtins/SKILL.md)) for guidelines on registering, mapping,\n    constant evaluating, and lowering compiler builtin primitives (e.g.\n    `\"int.convert_float\"`).\n-   **Language server**: Refer to the **Language server** skill\n    ([SKILL.md](../language_server/SKILL.md)) before working on\n    `toolchain/language_server/` or `utils/vscode/`. Neither follows the\n    patterns described here.\n-   **Phases**: Lex -> Parse -> Check -> Lower.\n-   **Definitions**: Many kinds (tokens, parse nodes, SemIR instructions) are\n    defined in `.def` files and expanded by way of macros.\n-   **Handlers**:\n    -   Parser: `Handle<StateName>` in `parse/handle_*.cpp`.\n    -   Checker: `HandleParseNode` in `check/handle_*.cpp`.\n    -   Lowering: `HandleInst` in `lower/handle_*.cpp`.\n-   **Iteration**: Prefer iterative algorithms over recursive ones to prevent\n    stack exhaustion on complex codebases.\n\n### Essential commands\n\n-   **Test everything**: `bazelisk test //...`\n-   **Test specific target**: `bazelisk test //toolchain/testing:file_test`\n-   **Test specific file**: `bazelisk test //toolchain/testing:file_test\n    --test_arg=--file_tests=<path_to_carbon_file>`\n-   **Build toolchain**: `bazelisk build //toolchain/...`\n\n### Updating test data\n\nCarbon tests often use `file_test` (for example,\n`//toolchain/testing/file_test`). For detailed guidelines on authoring tests,\nincluding file splits, naming conventions (`fail_`, `todo_`), and generating\nminimal output with SemIR dumps, please refer to the **Toolchain tests** skill.\n\nIf you change compiler behavior, you likely need to update expected test\noutputs. **Do not manually edit thousands of lines of expected output.** Use the\nscript:\n\n```bash\n./toolchain/autoupdate_testdata.py\n# Or for a specific file:\n./toolchain/autoupdate_testdata.py toolchain/check/testdata/my_test.carbon\n```\n\n## Debugging and diagnostics\n\n-   **Compiler Diagnostics**: Refer to the **Diagnostics** skill\n    ([SKILL.md](../diagnostics/SKILL.md)) for strict rules on declaring,\n    formatting, emitting, testing, and styling compiler diagnostic messages\n    (errors, warnings, notes).\n-   **Printing to stderr**: Use `llvm::errs() << \"debug info\\n\";`.\n    -   Avoid `std::cout` (it may interfere with tool output).\n-   **SemIR Stringification**:\n    -   SemIR objects often have a `Print` method or `operator<<`.\n    -   `inst.Print(llvm::errs())`\n-   **Debugging Crashes**:\n    -   Bazel sandboxing can hide artifacts. Use `--sandbox_debug` if needed,\n        but often running the binary directly from `bazel-bin/` is easier for\n        debugging.\n\n## Error handling\n\n-   **No exceptions**: Do not use C++ exceptions.\n-   **`ErrorOr<T>`**: Return `ErrorOr<T>` for fallible operations.\n    -   Check with `if (auto result = Function(); result) { Use(*result); }`\n-   **`llvm::Expected<T>`**: Similar to `ErrorOr`, used when interfacing with\n    LLVM.\n\n### Context-Aware Diagnostics\n\nWhen declaring and emitting errors, ensure semantic wording matches the exact\ncontext:\n\n-   **Semantic Precision**: Do not reference \"types\" when raising errors for\n    unsized expressions like `IntLiteral` or `FloatLiteral`. For example, use\n    `RealLiteralTooLargeForUnsizedInt` instead of a diagnostic referencing an\n    \"integer type\".\n-   **Wording Consistency**: Before declaring a new diagnostic in\n    [kind.def](../../../toolchain/diagnostics/kind.def), search for existing\n    diagnostics in the targeted implementation files (for example, other uses of\n    `MaxIntWidth`) to align message structures and parameter expectations.\n\n### Casting (LLVM style)\n\n-   Use `llvm::cast<T>(obj)` (checked, asserts on failure).\n-   Use `llvm::dyn_cast<T>(obj)` (returns null on failure).\n-   Use `llvm::isa<T>(obj)` (boolean check).\n-   **Avoid** `dynamic_cast` and standard RTTI.\n\n### Leverage LLVM APIs\n\nBefore implementing custom algorithms for mathematical, logical, or bitwise\noperations, inspect target LLVM ADT class APIs:\n\n-   **Builtin APIs**: Verify if LLVM classes (such as `APInt`, `APFloat`, or\n    `APSInt`) already offer native equivalents (for example, `.pow()`,\n    `ilogb()`, `.changeSign()`, `convertFromAPInt()`). Avoid duplicate, naive,\n    or inefficient custom loops.\n\n### Data structures\n\n-   Prefer APIs in `common/` and `toolchain/base/` over LLVM ADTs. For example,\n    use `Map` instead of `llvm::DenseMap`.\n-   If no Carbon API exists, prefer LLVM ADTs over standard library ones (for\n    example `llvm::SmallVector`, `llvm::StringRef`).\n-   `StringRef` is a view; be careful with lifetimes.\n\n## Common pitfalls\n\n1.  **Legacy `explorer` references**: The `explorer` prototype has been moved.\n    Ignore references to it in proposals or old docs; focus on `toolchain`.\n2.  **Manually updating test files**: Always check if `autoupdate_testdata.py`\n    can do it for you.\n3.  **Using `std::string` unnecessarily**: Prefer `llvm::StringRef` for\n    arguments.\n4.  **Header includes**: Use specific include orders (often enforced by\n    `clang-format`).\n5.  **Parse node order**: Semantics processes parse nodes in post-order; ensure\n    your parser transitions support this.\n6.  **Builtin implementation gaps**: If adding a primitive builtin function,\n    make sure you address all phases of the lifecycle: macro definition\n    registration, signature validation, compile-time constant evaluation\n    (interpreter), LLVM IR lowering, and prelude modular implementation bindings\n    (avoiding orphan rules). Refer to the **Builtin functions** skill\n    ([SKILL.md](../builtins/SKILL.md)) for details.\n7.  **Premature helper abstraction**: Avoid extracting tiny helper functions\n    that are called from exactly one place and do not significantly modularize\n    complex code. Prefer inlining directly to keep the implementation compact,\n    readable, and localized.\n8.  **Redundant bounds calculations**: Avoid repeating calculations of complex\n    boundary estimations (such as lower and upper bound estimations). Refactor\n    the logic to calculate unified values once, preserving compactness.\n9.  **Trusting stale `clangd` diagnostics**: In-editor diagnostics are only as\n    good as `compile_commands.json`. If it predates a newly added file, `clangd`\n    falls back to a default command and reports nonsense, such as missing\n    standard headers or \"no member named `None`\". Regenerate it with\n    `./scripts/create_compdb.py`, which only takes a few seconds.\n",".agents/skills/toolchain_tests/SKILL.md":"---\nname: Toolchain tests\ndescription:\n    Instructions for authoring, structuring, and running toolchain tests using\n    the file_test infrastructure.\n---\n\n# Toolchain tests\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Introduction\n\nThis skill provides guidelines and patterns for creating and updating tests for\nthe Carbon toolchain, especially file tests in `toolchain/*/testdata/` (for\nexample, `toolchain/check/testdata/`).\n\nToolchain tests evaluate Carbon source files through Lexing, Parsing, Checking,\nand optionally Lowering. Output (for example SemIR dumps, Clang errors) is\ncaptured and validated using inline CHECK records.\n\nLanguage server tests also use `file_test`, but with quite different\nconventions (an LSP message stream, `AUTOUPDATE-SPLIT`, `FROM_FILE_SPLIT`).\nRefer to the **Language server** skill\n([SKILL.md](../language_server/SKILL.md)) for those.\n\n## Structure and Authoring\n\n### File Layout and Headers\n\nTest files must start with the standard Carbon license, followed by\nconfiguration comments. Separate sections with blank comment lines (`//`).\n\n```carbon\n// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/...\n//\n// AUTOUPDATE\n```\n\n-   `// AUTOUPDATE` is mandatory for files using CHECK markers.\n-   `// TIP:` lines are automatically generated by the autoupdater. You do not\n    need to hand-write them. It is harmless to add them, but the script will\n    handle it.\n\n### Minimized Preludes\n\nWhen writing tests entirely unrelated to the Core package, specify a minimal\nprelude file using `// INCLUDE-FILE`. Usually, include\n`toolchain/testing/testdata/min_prelude/` scripts, such as `int.carbon` or\n`primitives.carbon`. This significantly speeds up execution and minimizes STDOUT\nnoise.\n\n-   **Builtin Primitive Testing**: Standard operators (such as `+`, `-`, `/`,\n    `<`, etc.) are **not** imported or available inside minimized preludes. To\n    write tests with a minimal prelude footprint, call primitive builtins\n    directly (e.g., `float.negate`, `float.div`) inside your test code to build\n    expressions.\n\n### Split Tests and `[[@TEST_NAME]]`\n\nA single physical file can test multiple scenarios using split constraints:\n\n```carbon\n// --- passing_case.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// ...\n\n// --- fail_bad_case.carbon\nlibrary \"[[@TEST_NAME]]\";\n// ...\n```\n\n-   **Always** use `library \"[[@TEST_NAME]]\";` in each split rather than\n    hardcoding the library name. This prevents name conflicts, avoids redefining\n    the default library, and keeps the test code clean and templateable.\n-   Exactly `[[@TEST_NAME]]` (including the brackets) must be used. The test\n    infrastructure automatically replaces it with the split's filename minus\n    `todo_` and `fail_` prefixes.\n-   **Do not put code that is expected to pass and code that is expected to fail\n    into the same split.** Validation relies on non-failing splits producing\n    absolutely no errors and failing splits producing the correct compiler\n    errors independently.\n\n### File Prefixing: `fail_` and `todo_`\n\nExpected failures must be differentiated from unexpected failures (and from\nbugs). Include prefixes to name individual split files or the main test:\n\n-   `fail_...`: The test should and does produce compiler errors.\n-   `todo_fail_...`: The test should produce errors but currently does not.\n-   `fail_todo_...`: The test does produce errors or crashes, but it shouldn't\n    (or produces the wrong errors or otherwise misbehaves with errors).\n-   `todo_...`: The test has some incorrect behavior, but doesn't produce errors\n    currently, and shouldn't.\n\n**Main File Naming**: The main test file (and any split-files) must have a\n`fail_` prefix if they have an associated error. **Exception**: The main file\nmay omit `fail_` if it contains a least one split that has a `fail_` prefix.\n\nBoth the `fail_` and `todo_` prefixes are stripped from filename properties like\n`[[@TEST_NAME]]`.\n\n### Constant Evaluation Validation\n\nWhen testing constant evaluation in semantic checker tests, follow these\nconventions to ensure diagnostic stability and accuracy:\n\n-   **Literal Spelling Canonicalization**: In Semantic IR, real literals\n    (floating-point constants) with identical mathematical values can be\n    assigned distinct internal representation identifiers based on spelling\n    variations in source code. To completely prevent literal spelling mismatches\n    in expected output checks, validation tests must be performed using\n    canonical comparison methods (for example, passing converted values through\n    an `Expect(X as f64)` function).\n-   **Generic Parameters Validation**: To bypass compile-time constraints where\n    local runtime variables are rejected as generic function arguments, test\n    generic type conversions at runtime, and validate compile-time conversions\n    by passing static literal values directly into primitive builtin calls.\n-   **Exhaustive Edge Case Verification**: For complex mathematical algorithms\n    (such as floating-point to integer truncation and rounding), map and execute\n    test constraints covering every code branch, conditional exit, and fallback\n    evaluation path.\n-   **Rounding Threshold Boundaries**: Test cases that land extremely close to\n    mathematical boundaries (for example, floating-point literals representing a\n    tiny fraction above 1.0, such as $2^{30} \\times 2^{-30}$ or\n    $10^{10} \\times 10^{-10}$, verifying correct exact truncation down to 1 or\n    0).\n-   **Precise Float Literal Spelling**: Spell floating-point literals in test\n    code with exact mathematical precision targeting target thresholds. For\n    example, if testing the smallest fractional increment above 1.0, use the\n    exact hex fractional representation (e.g. `0x1.0000000000001p0`) or a highly\n    precise decimal fractional spelling (e.g. `1.0000000000000001`) instead of\n    coarse fractions like `1.1` to ensure correct boundary assertions.\n-   **Representation Capacity Boundaries**: Explicitly target edge cases near\n    representation limits of target types. Test combinations of mantissas and\n    exponents that yield values exactly on, just below, or just above the\n    capacity limits of fixed-size destination types (e.g. signed/unsigned\n    targets like `i32` or `u32`).\n-   **Zero-Value Sizing Bounds**: Verify boundary inputs of `0` and `0.0`\n    explicitly. Assert that zero inputs are sized and simplified correctly\n    without triggering calculation underflows, division-by-zero errors, or\n    underestimating required bit allocations.\n\n### Test Code Comments\n\n-   **No agent thinking:** Do not include comments describing your reasoning or\n    \"train of thought\" (for example, \"Wait, but...\") inside the test files. Any\n    comments left in tests should be concise and describe what the test _itself_\n    is validating for human readers.\n\n## SemIR Dumps and Minimizing Output\n\nLimit STDOUT checks to the logic under test. Always use `//@dump-sem-ir-begin`\nand `//@dump-sem-ir-end` around the specific declarations/blocks where SemIR\noutput is desired. Only use these markers and **not**\n`--dump-sem-ir-ranges=if-present` or similar extra args—new tests use\n`//@dump-sem-ir...` to naturally filter output to the highlighted segments based\non the default behavior.\n\n```carbon\n//@dump-sem-ir-begin\nfn F(x:? form(ref i32));\n//@dump-sem-ir-end\n```\n\n## Creating/Updating the Output\n\nAI tools should **never** hand-write or manually touch `// CHECK:STDOUT:` or\n`// CHECK:STDERR:` comments.\n\nWrite your Carbon test code, headers, and `// AUTOUPDATE` then run the test\nupdater:\n\n```bash\n./toolchain/autoupdate_testdata.py toolchain/PATH/TO/YOUR/TEST.carbon\n```\n\nReview the updated test outputs (for example, by way of `git diff`). Ensure\nlogic paths are correctly tested rather than producing massive boilerplate\nblocks.\n\nAutoupdating makes the tests pass whether or not the new behavior is correct, so\ndeciding that the new output is the output you wanted is a separate step. See\nthe [Review testdata changes](../review_testdata_changes/SKILL.md) skill.\n","AGENTS.md":"# Gemini & AI Assistant Guide for Carbon\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis document provides high-density technical context for AI assistants\ncontributing to the Carbon Language project.\n\n## General instructions\n\n-   **Communication**: Be concise, professional, and technical. Use GitHub-style\n    markdown.\n-   **Verification**: Always run relevant tests.\n\n## Bazel usage\n\n> [!IMPORTANT] Always use `bazelisk` instead of `bazel` for all commands in the\n> Carbon project. Refer to the\n> [Bazel usage skill](/.agents/skills/bazel/SKILL.md) for detailed instructions.\n\n## Version control\n\n> [!IMPORTANT] Never rewrite the history of a change that has been submitted as\n> a pull request. Reviewers track a PR by its commits, and rewriting them\n> discards their in-progress review. Ask before rewriting history in any case.\n> Refer to the [Jujutsu (jj) usage skill](/.agents/skills/jj/SKILL.md) for\n> details.\n","github_tools/README.md":"# GitHub\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nScripts for use with GitHub.\n\nSee individual scripts for more details.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Gemini & AI Assistant Guide for Carbon\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis document provides high-density technical context for AI assistants\ncontributing to the Carbon Language project.\n\n## General instructions\n\n-   **Communication**: Be concise, professional, and technical. Use GitHub-style\n    markdown.\n-   **Verification**: Always run relevant tests.\n\n## Bazel usage\n\n> [!IMPORTANT] Always use `bazelisk` instead of `bazel` for all commands in the\n> Carbon project. Refer to the\n> [Bazel usage skill](/.agents/skills/bazel/SKILL.md) for detailed instructions.\n\n## Version control\n\n> [!IMPORTANT] Never rewrite the history of a change that has been submitted as\n> a pull request. Reviewers track a PR by its commits, and rewriting them\n> discards their in-progress review. Ask before rewriting history in any case.\n> Refer to the [Jujutsu (jj) usage skill](/.agents/skills/jj/SKILL.md) for\n> details.\n","isInternal":false,"tokens":252,"sizeBytes":1071},{"name":"SKILL.md","path":".agents/skills/agent_tools/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/agent_tools/SKILL.md","title":"Agent tools","category":"anthropic-skill","format":"markdown","content":"---\nname: Agent tools\ndescription:\n    Guidelines and restrictions on shell commands and file manipulation tools\n    for AI assistants.\n---\n\n# Agent tools\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nAI assistants working on the Carbon repository **MUST NOT** use legacy or\ngeneric UNIX shell search/edit commands when specialized environment tools\nexist.\n\n## Command line tools restrictions\n\n-   **DO NOT USE**: `cat`, `less`, `grep`, `sed`, or other shell utilities for\n    viewing, searching, or modifying files.\n-   **DO NOT USE**: `patch` to write and apply patch files.\n-   **DO NOT USE**: Writing custom scripts in other languages to circumvent this\n    limitation.\n-   **DO USE**: High-fidelity semantic API tools:\n    -   **Viewing**: Use `view_file` instead of `cat` / `less`.\n    -   **Searching**: Use `grep_search` / `find_by_name` instead of `grep` /\n        `find`.\n    -   **Modifying**: Use `replace_file_content`, `multi_replace_file_content`,\n        or `write_to_file` instead of `sed` / `patch` / `python` edits.\n\nYou may only write and run temporary programs to modify source code if no\nsemantic tool is applicable or when performing complex, systematic transforms\nacross many codebase directories simultaneously.\n\n## Temporary files management\n\nTemporary files and scratchpad test scripts created by the assistant during\nanalysis, experiments, or debugging:\n\n-   **MUST** reside within the `tmp/` subdirectory under the workspace root.\n-   **MUST** be periodically cleaned out and deleted before ending your turn to\n    preserve a clean git workspace.\n","frontmatter":{"name":"Agent tools","description":"Guidelines and restrictions on shell commands and file manipulation tools for AI assistants."},"isInternal":false,"tokens":388,"sizeBytes":1724},{"name":"SKILL.md","path":".agents/skills/bazel/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/bazel/SKILL.md","title":"Bazel usage","category":"anthropic-skill","format":"markdown","content":"---\nname: Bazel usage\ndescription:\n    Instructions that **MUST** be followed when using Bazel or Bazelisk to\n    build, test, and debug in the Carbon repository.\n---\n\n# Bazel usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill documents how best to use Bazel when building, testing, or\nmanipulating the Carbon repository's Bazel in any way.\n\n## Bazel wrappers\n\nCarbon uses Bazel for its build system. To ensure consistent versions, the\nproject uses Bazelisk.\n\n> [!IMPORTANT] Always use `bazelisk` whenever you want to run Bazel. Never run\n> `bazel` directly in the Carbon project. Anything you want to do with `bazel`\n> can be done with the `bazelisk` command instead.\n\n-   **Bazelisk**: Try to use `bazelisk` in your existing `$PATH` if available.\n    -   **`run_bazelisk.py`**: If `bazelisk` isn't available, use\n        `./scripts/run_bazelisk.py` to run bazelisk without it being installed.\n\n## Essential commands\n\n### Building\n\n-   **Build all**: `bazelisk build //...`\n-   **Build toolchain**: `bazelisk build //toolchain/...`\n-   **Build specific target**: `bazelisk build //toolchain:carbon`\n\n### Testing\n\n-   **Test all**: `bazelisk test //...:all`\n-   **Test toolchain**: `bazelisk test //toolchain/...`\n-   **Test examples**: `bazelisk test //examples/...`\n\n> [!TIP] Running all of the tests can be slow, so try to narrowly test the\n> immediately relevant parts of the project first, and only expand coverage as\n> necessary to be confident in the changes.\n\n> [!TIP] For specialized instructions on testing and developing the Carbon\n> toolchain, consult these skills:\n>\n> -   [Toolchain tests](/.agents/skills/toolchain_tests/SKILL.md): For\n>     authoring, structuring, and running `file_test` tests.\n> -   [Toolchain development](/.agents/skills/toolchain_development/SKILL.md):\n>     For architecture, essential commands, and debugging the toolchain.\n\n### Running binaries built by Bazel\n\n> [!IMPORTANT] Always manually run binaries built by Bazel using the\n> `bazelisk run` command. Never run the binary directly from `bazel-bin/`.\n\nYou can run the Carbon driver or command line directly via Bazel:\n\n-   `bazelisk run //toolchain -- compile --phase=parse\n    toolchain/parse/testdata/basics/empty.carbon`\n\n## Advanced configurations\n\n### AddressSanitizer (ASan)\n\nTo enable ASan for local testing:\n\n-   Pass `--config=asan`: `bazelisk test --config=asan //...`\n\n## Common pitfalls and troubleshooting\n\n### `bazel clean`\n\nChanges to packages installed on your system (like changing LLVM versions or\ninstalling `libc++`) may not be noticed by Bazel.\n\n-   Run `bazelisk clean` to force cached state to be rebuilt when environment\n    changes occur.\n","frontmatter":{"name":"Bazel usage","description":"Instructions that **MUST** be followed when using Bazel or Bazelisk to build, test, and debug in the Carbon repository."},"isInternal":false,"tokens":720,"sizeBytes":2819},{"name":"SKILL.md","path":".agents/skills/builtins/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/builtins/SKILL.md","title":"Builtin functions","category":"anthropic-skill","format":"markdown","content":"---\nname: Builtin functions\ndescription:\n    Instructions for registering, mapping, constant evaluating, and lowering\n    builtin functions in the Carbon toolchain.\n---\n\n# Builtin Functions in the Carbon Toolchain\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nBuiltin functions are compiler-recognized primitives mapping directly from\nCarbon code expressions (via standard prelude bindings) to optimized backend\nexecution. This document defines the complete structural workflow, C++ patterns,\nconstant evaluation logic, machine lowering mechanics, library bindings, and\nvalidation strategies required to implement builtin functions in the Carbon\ncompiler.\n\n---\n\n## Technical Flow & Lifecycle\n\n```mermaid\ngraph TD\n  Src[Carbon Source Code] -->|Prelude Map| Sem[Semantic Analysis / SemIR]\n  Sem -->|Signature Constraint| Sig[builtin_function_kind.cpp]\n  Sem -->|Phase Evaluation| Eval[eval.cpp Constant Interpreter]\n  Sem -->|Machine Codegen| Lower[handle_call.cpp LLVM Lowering]\n  Eval -->|Diagnostics| Diag[diagnostics/kind.def]\n  Lower -->|Native Instructions| LLVM[LLVM IR Generation]\n```\n\nAdding a builtin function involves a 5-step integration:\n\n1.  **Define the Builtin Kind**: Register the enum in\n    [builtin_function_kind.def](../../../toolchain/sem_ir/builtin_function_kind.def).\n2.  **Signature & Compile-Time Registry**: Declare the mapping name, parameter\n    constraints, and compile-time evaluation residency in\n    [builtin_function_kind.cpp](../../../toolchain/sem_ir/builtin_function_kind.cpp).\n3.  **Compile-Time Interpreter Support**: Wire constant evaluation hooks and\n    bounds/exception diagnostics in\n    [eval.cpp](../../../toolchain/check/eval.cpp).\n4.  **LLVM IR Lowering Support**: Connect target machine generation in\n    [handle_call.cpp](../../../toolchain/lower/handle_call.cpp).\n5.  **Prelude Library Mapping**: Bind primitive interfaces to named builtins\n    under [core/prelude/](../../../core/prelude/).\n\n---\n\n## Detailed Step-by-Step Implementation Guide\n\n### Step 1: Kind Definition & Registration\n\nRegister your builtin function name using the X-macro in\n[builtin_function_kind.def](../../../toolchain/sem_ir/builtin_function_kind.def):\n\n```cpp\n// toolchain/sem_ir/builtin_function_kind.def\n\n// Converts an integer type to a floating-point type.\nCARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntConvertFloat)\n```\n\n### Step 2: Signature Validation & Compile-Time Residence\n\nInside\n[builtin_function_kind.cpp](../../../toolchain/sem_ir/builtin_function_kind.cpp):\n\n1.  **Define Parameter Constraints**: If the parameter requires novel\n    constraints (e.g. \"must be a float type\"), define a template constraint\n    struct checking the matching `SemIR` type instruction (such as `FloatType`\n    or `FloatLiteralType`). Use pre-established semantic helpers:\n\n    -   `TypeParam<I, T>`: Ensures different parameters resolve to identical\n        type structures (e.g., generic constraint matching).\n    -   `AnyInt`, `AnyFloat`, `AnySizedInt`, `AnySizedFloat`, `CharCompatible`,\n        `StdInitializerList`, `NoReturn`.\n\n2.  **Map Literal Name & Register Constraint Signature**: Declare a\n    `BuiltinInfo` constant inside `namespace BuiltinFunctionInfo` matching the\n    macro-defined name:\n\n    ```cpp\n    // toolchain/sem_ir/builtin_function_kind.cpp\n\n    constexpr BuiltinInfo IntConvertFloat = {\n        \"int.convert_float\", ValidateSignature<auto(AnyInt)->AnyFloat>};\n    ```\n\n3.  **Establish Compile-Time Residency Status**: Update\n    `BuiltinFunctionKind::IsCompTimeOnly` to determine if a call requires\n    compile-time evaluation:\n    -   **Checked/Diagnostics Primitives**: Return `true` immediately. Runtime\n        lowering of these is illegal (e.g. `IntConvertFloatChecked`).\n    -   **Runtime Primitives**: Return\n        `AnyLiteralTypes(sem_ir, arg_ids, return_type_id)` to enforce that\n        expressions involving unsized literal values (like `IntLiteral` or\n        `FloatLiteral`) are evaluated exclusively at compile-time (as they lack\n        runtime representation).\n\n---\n\n### Step 3: Constant Evaluation Support\n\nWire the interpreter inside [eval.cpp](../../../toolchain/check/eval.cpp) to\nexecute compile-time computations:\n\n1.  **Implement Constant Evaluation Logic**:\n\n    -   Handle the builtin case inside `MakeConstantForBuiltinCall` (which\n        processes the compile-time execution of the call).\n    -   Confirm type validation phase is `Phase::Concrete` to reject incomplete\n        bindings:\n\n        ```cpp\n        case SemIR::BuiltinFunctionKind::IntConvertFloat: {\n          if (phase != Phase::Concrete) {\n            return MakeConstantResult(context, call, phase);\n          }\n          return PerformIntToFloatConvert(context, loc_id, arg_ids[0], call.type_id,\n                                          /*require_exact=*/false);\n        }\n        ```\n\n    -   Extract inputs safely from local value stores (e.g.\n        `context.ints().Get(arg.int_id)` or\n        `context.floats().Get(arg.float_id)`).\n    -   Leverage high-precision LLVM mathematical structures (`llvm::APInt`,\n        `llvm::APFloat`, `llvm::APSInt`) to handle custom bits and signedness\n        safely.\n\n2.  **Diagnose Invalid Parameters or Exceptions**:\n\n    -   Define compile-time diagnostics inside\n        [kind.def](../../../toolchain/diagnostics/kind.def):\n\n        ```cpp\n        // toolchain/diagnostics/kind.def\n        CARBON_DIAGNOSTIC_KIND(IntTooLargeForFloatType)\n        ```\n\n    -   Emplace localized diagnostic formatting messages where they are caught\n        in `eval.cpp`:\n\n        ```cpp\n        CARBON_DIAGNOSTIC(IntTooLargeForFloatType, Error,\n                          \"integer value {0} too large for floating-point type {1}\",\n                          llvm::APSInt, SemIR::TypeId);\n        context.emitter().Emit(loc_id, IntTooLargeForFloatType, val, dest_type_id);\n        ```\n\n    -   Return `SemIR::ErrorInst::ConstantId` to gracefully abort invalid\n        constant generation rather than crashing the compiler.\n\n3.  **Fast-Path Range Limits**:\n    -   Before evaluating expensive math operations on giant exponents (e.g.\n        `1.0e1000000`), executing range limits check against `dest_width + 64`\n        (sized) or `IntStore::MaxIntWidth` (unsized) is mandatory to prevent\n        out-of-bounds calculations and compile-time memory exhaustion.\n\n---\n\n### Step 4: Machine Code Generation (LLVM Lowering)\n\nInside [handle_call.cpp](../../../toolchain/lower/handle_call.cpp):\n\n1.  **Map to Native LLVM Instructions**: For runtime-eligible builtins, map the\n    call inside `HandleBuiltinCall` to native LLVM IR builder methods:\n\n    ```cpp\n    case SemIR::BuiltinFunctionKind::IntConvertFloat: {\n      auto* operand = context.GetValue(arg_ids[0]);\n      auto* dest_type = context.GetTypeOfInst(inst_id);\n      bool is_signed = IsSignedInt(context, arg_ids[0]);\n      context.SetLocal(\n          inst_id, is_signed\n                       ? context.builder().CreateSIToFP(operand, dest_type)\n                       : context.builder().CreateUIToFP(operand, dest_type));\n      return;\n    }\n    ```\n\n2.  **Assert on Compile-Time-Only Builtins**: Throw a hard assertion on\n    lowering-cases for checked validator builtins that should never hit code\n    generation:\n\n    ```cpp\n    case SemIR::BuiltinFunctionKind::IntConvertFloatChecked: {\n      CARBON_CHECK(builtin_kind.IsCompTimeOnly(\n          context.sem_ir(), arg_ids,\n          context.sem_ir().insts().Get(inst_id).type_id()));\n      CARBON_FATAL(\"Missing constant value for call to comptime-only function\");\n    }\n    ```\n\n---\n\n### Step 5: Standard Library Prelude Integration\n\nMap the standard library primitive interfaces to your newly minted named\nbuiltins under [core/prelude/](../../../core/prelude/):\n\n-   **Primitive Mappings**: Bind Carbon methods directly to string-literal\n    builtin equivalents:\n\n    ```carbon\n    fn Convert[self: Self]() -> Float(To) = \"int.convert_float\";\n    ```\n\n-   **Strict Orphan Rule Compliance**: Carbon's orphan rules prohibit\n    implementing interfaces where neither the type nor the interface is locally\n    defined in the backing source module.\n    -   **Literal Conversions**: Literal types (like `FloatLiteral`,\n        `IntLiteral`) do not have backing Carbon source files. Therefore, an\n        `impl` of `UnsafeAs` (which is defined in `as.carbon`) between two\n        literal types must reside inside `as.carbon` itself.\n    -   **Sized Conversions**: Implementations targeting sized primitives (e.g.\n        `Int(N)`, `Float(N)`) must reside in their respective type source files\n        (such as [int.carbon](../../../core/prelude/types/int.carbon) or\n        [float.carbon](../../../core/prelude/types/float.carbon)) where the\n        backing target type resides to prevent duplicate symbols and structural\n        recursion loops.\n\n---\n\n## High-Fidelity Validation & Test Authoring\n\nFollow the [Toolchain tests](../toolchain_tests/SKILL.md) skill with specialized\npatterns for builtins:\n\n### 1. Checker Builtin File Splits\n\nCreate validation splits under\n[toolchain/check/testdata/builtins/](../../../toolchain/check/testdata/builtins/):\n\n-   **Test Naming Convention**: All tests under\n    [toolchain/check/testdata/builtins/](../../../toolchain/check/testdata/builtins/)\n    must be named after the builtin they are testing, replacing `.` characters\n    in the builtin name with `/` (directories). For example, a test for the\n    builtin `\"char_literal.convert\"` must be located at\n    `toolchain/check/testdata/builtins/char_literal/convert.carbon`.\n-   **Minimal Prelude & Direct Call Isolation**: Builtin tests must **not** test\n    the prelude library or operators. They must use the minimal primitive\n    prelude (`// INCLUDE-FILE:\n    toolchain/testing/testdata/min_prelude/primitives.carbon`) or a smaller\n    prelude, and explicitly declare and call the builtin functions under test\n    directly (e.g., `fn Add(a: f64, b: f64) -> f64 = \"float.add\";`). This\n    isolates the testing of compiler builtins from the library prelude.\n-   **Min-Prelude Limitations**: Standard operators (like `+`, `-`, `/`, `<`,\n    etc.) are **not** available in minimized preludes because the core operators\n    library isn't imported. To write tests with a minimal footprint, call\n    primitive builtins directly (e.g. `float.negate`, `float.div`) inside your\n    test code to build expressions.\n-   **Canonicalized Float Comparison**: In SemIR, real literal representations\n    with identical mathematical values can result in mismatched `RealId` objects\n    based on spelling variations. Verify compile-time constant conversions using\n    canonicalized comparison functions (e.g. passing converted results through\n    `Expect(X as f64)`) to completely avoid spelling mismatches in expected\n    outputs.\n-   **Locals Bypass**: If validating generic implicit conversions, compile-time\n    arguments cannot take local runtime variable parameters. Validate\n    compile-time conversions by passing literal constants directly, and sized\n    variable implicit conversions at runtime.\n\n### 2. Machine Codegen Lowering Splits\n\nCreate testing splits under\n[toolchain/lower/testdata/builtins/](../../../toolchain/lower/testdata/builtins/):\n\n-   Emplace a simple carbon binding to the tested builtin.\n-   Confirm matching LLVM metadata target definitions are mapped precisely\n    (e.g., matching `sitofp i32 %a to float`, `fptosi float %a to i32`).\n","frontmatter":{"name":"Builtin functions","description":"Instructions for registering, mapping, constant evaluating, and lowering builtin functions in the Carbon toolchain."},"isInternal":false,"tokens":2628,"sizeBytes":11560},{"name":"SKILL.md","path":".agents/skills/code_style/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/code_style/SKILL.md","title":"Code style","category":"anthropic-skill","format":"markdown","content":"---\nname: Code style\ndescription:\n    Instructions for code formatting and style guidelines in the Carbon\n    toolchain.\n---\n\n# Code style\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## License\n\n-   **Licenses**: All Carbon files outside of `third_party/` should have a\n    license following\n    [CONTRIBUTING license instructions](/CONTRIBUTING.md#license).\n\n## Formatting\n\n-   **Bazel**: Use `pre-commit run buildifier --files <file.bzl>` to format\n    Bazel files.\n-   **C++**: Use `pre-commit run clang-format --files <file.cpp>` to format C++\n    files.\n-   **Carbon**: The toolchain's `format` command doesn't work well right now.\n    Instead, try to format Carbon code based on other Carbon files and the C++\n    style.\n-   **Markdown**: Use `pre-commit run prettier --files <file.md>` to format\n    markdown files.\n-   **Python**: Use `pre-commit run black --files <file.py>` to format Python\n    files.\n\n## Comments\n\n-   **Describe the code that is there.** A comment should explain what the\n    current code does or why it is the way it is, not narrate what the code used\n    to be. Do not add a comment to justify a deletion or explain that something\n    is no longer necessary; a reader of the new code has no idea what is being\n    contrasted against, and the comment rots as soon as the old shape is\n    forgotten. Put that reasoning in the commit message instead.\n-   **Do not introduce a local variable just to host a comment.** If a call\n    argument reads clearly on its own, inline it rather than naming it so that a\n    comment has somewhere to attach.\n-   **Lead with a plain summary.** Start a doc comment with a direct statement\n    of what the function does or returns, such as \"Returns true if the InstKind\n    is a singleton.\" Put nuance in a following sentence rather than qualifying\n    the summary into something harder to read.\n-   **Re-read a comment before updating it.** When a symbol is renamed or\n    changes meaning, a comment that mentions it is not automatically stale. Work\n    out what the comment actually asserts first: it may be describing what the\n    code _uses_, which is still true, and rewriting it loses information.\n\n## Documentation\n\nThis covers standalone prose: `/docs`, `README.md` files, and the skill files\nunder `.agents/skills`.\n\n-   **Be true of the tree it lands in.** Documentation shipping in the same\n    commit as the code it describes should name that code freely. Documentation\n    that lands separately must not: a reader who greps for an identifier from an\n    unlanded change finds nothing, and a claim that only holds after that change\n    is false until it lands. This is easy to get wrong when writing up a lesson\n    while the change that taught it is still in flight.\n-   **Use placeholders for illustrations.** When an example only needs to show a\n    shape, name it `Foo` rather than reaching for a real symbol. Save real\n    identifiers for documenting that identifier, where going stale is at least\n    detectable.\n-   **Make each point stand alone.** A reader has none of the discussion that\n    produced it. State the rule, and enough of the reason to apply it, without\n    assuming knowledge of the change that motivated it.\n\n## Naming\n\n-   **A name is a claim, so keep it true.** When a change invalidates the\n    invariant a name describes, rename it in the same change. A factory called\n    `MakeSingletonFooId` has to be renamed once `Foo` is no longer a singleton,\n    even though nothing forces you to.\n-   **Types in a signature are part of the claim.** A function returning the id\n    of a namespace should return `InstId`, not `TypeInstId`, because a namespace\n    is not a type. Do not let a convenient wider or narrower id type imply\n    something false.\n-   **Delete a predicate whose name stops distinguishing anything.** If a change\n    widens a test so that it no longer says what its name implies, remove it and\n    let callers use the underlying test, rather than keeping a wrapper that\n    sounds meaningful. What callers actually want is often the inverse, and is\n    worth adding under its own name.\n-   **Name a variable for its role, not its representation.** If the role a\n    value plays is unchanged, keep its name even when a change means it is now\n    held or spelled differently.\n\n## Commit descriptions\n\n-   **Say what the change is, not how you made it.** Describe the resulting\n    code. Only describe process when the process is more interesting than the\n    change, as with a large mechanical transformation.\n-   **Do not narrate your own work.** Statements like \"each such site was\n    audited\" or \"we investigated every caller\" describe effort, not the change.\n-   **Omit routine mechanical steps.** Do not mention running the testdata\n    autoupdater or the formatter. Every change is expected to include those.\n-   **Do not enumerate each edit.** Describe the change as a whole rather than\n    listing every function or file touched; the diff already lists them.\n-   **Use the project's terms precisely.** Reach for the term of art the\n    codebase uses. Calling something a \"type alias\" or a \"namespace\" when it is\n    a named scope misleads, and is worse than a vaguer but accurate word.\n-   **Scope claims to what changed.** Say the specific thing that is now true,\n    rather than a broader statement that happens to contain it.\n\n## Design\n\n-   **Do not distort the data model to improve output.** If printed or golden\n    output is undesirable, change the printer, not the data structures that\n    feed it.\n\n## Style Guides\n\n-   **C++ style**: Follow the\n    [Carbon C++ Project Style Guide](/docs/project/cpp_style_guide.md).\n-   **Markdown style**: Follow the\n    [Google developer documentation style guide](https://developers.google.com/style).\n-   **Python style**: Follow the [PEP 8](https://peps.python.org/pep-0008/)\n    style guide.\n    -   Wrap code and comments to 80 columns.\n    -   Run `pre-commit run flake8 --files <file.py>` to check Python style.\n","frontmatter":{"name":"Code style","description":"Instructions for code formatting and style guidelines in the Carbon toolchain."},"isInternal":false,"tokens":1437,"sizeBytes":6138},{"name":"SKILL.md","path":".agents/skills/diagnostics/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/diagnostics/SKILL.md","title":"Diagnostics","category":"anthropic-skill","format":"markdown","content":"---\nname: Diagnostics\ndescription:\n    Instructions for declaring, formatting, emitting, testing, and styling\n    diagnostic messages (errors, warnings, and the labels that explain them) in\n    the Carbon toolchain.\n---\n\n# Diagnostics in the Carbon Toolchain\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThe Carbon compiler features a highly-engineered, context-aware diagnostics\nframework designed to deliver precise, readable, and highly targetable\ndiagnostic output (errors, warnings, and the labels that explain them). This\ndocument establishes strict rules for declaring, formatting, emitting, testing,\nand styling compiler diagnostics.\n\n---\n\n## Architecture Overview\n\n```mermaid\ngraph TD\n  Kind[kind.def Registry] -->|Registration| Enum[Kind Enum ID]\n  Enum -->|Build/Emit| Emitter[Emitter LocT]\n  Emitter -->|ConvertLoc| Loc[Converted Physical Loc]\n  Emitter -->|formatv serialization| Formatting[format_providers.h / Custom Types]\n  Emitter -->|Emit Messages| Consumer[Console / Sorting Consumer]\n  Consumer -->|stable sort| StdErr[Compiler Standard Error]\n```\n\nDiagnostics are handled via three decoupled core components:\n\n1.  **Registry**: Globally enumerated kinds inside\n    [kind.def](../../../toolchain/diagnostics/kind.def).\n2.  **Emitters**: Specialized formatting pipelines (parameterized on custom\n    phase location types `LocT` like `Token` or `LocId`) that convert raw tokens\n    to standardized physical source locations (file, line, column, and the text\n    of the line).\n3.  **Consumers**: Pipelines that process, track, filter, and sort diagnostics.\n    The default `SortingConsumer` buffers and stable-sorts diagnostics based on\n    their `last_byte_offset` matching compiler traversal order to ensure perfect\n    causal ordering.\n\n---\n\n## 1. Declaring and Registering Diagnostics\n\nAll diagnostic types must pass structural uniqueness and coverage verifications.\n\n### The Diagnostic Registry\n\nEvery diagnostic kind must be registered globally as an enum option under\n[kind.def](../../../toolchain/diagnostics/kind.def):\n\n```cpp\n// toolchain/diagnostics/kind.def\nCARBON_DIAGNOSTIC_KIND(RealLiteralTooLargeForUnsizedInt)\n```\n\n### The Uniqueness Rule\n\nTo ensure optimal compile-time and analysis integrity, every diagnostic kind\ndeclared in `kind.def` **MUST** be mapped to **one and only one** C++ macro\ndeclaration (`CARBON_DIAGNOSTIC` or `CARBON_DIAGNOSTIC_ON_SCOPE`).\n\n-   **DO NOT** duplicate diagnostic definitions across different locations.\n-   The C++ representation of the diagnostic is a static/global constant of type\n    `DiagnosticBase<Args...>`.\n-   **Local Scope (Recommended)**: If the diagnostic is unique to a single\n    block/function body, declare it **locally** inside the function body\n    adjacent to its `Emit` trigger:\n\n    ```cpp\n    void ConvertFloatValueToInt(...) {\n      CARBON_DIAGNOSTIC(FloatNaNConvertedToInt, Error,\n                        \"cannot convert NaN to integer type {0}\", SemIR::TypeId);\n      context.emitter().Emit(loc_id, FloatNaNConvertedToInt, dest_type_id);\n    }\n    ```\n\n-   **File Scope**: If the diagnostic is shared among multiple functions inside\n    the _same_ file, declare it at **file scope** inside the anonymous namespace\n    of the `.cpp` file.\n-   **Global Scope**: If a diagnostic (such as a shared helper label) is reused\n    _across different physical files_, define it in a shared header (e.g.\n    context/check helpers) and mark it `extern` where applicable, ensuring the\n    macro is only invoked once.\n\n---\n\n## 2. Formatting Diagnostic Arguments\n\nCarbon diagnostics leverage LLVM's `formatv` engine. Parameters must be passed\nusing strongly-typed arguments to preserve translation capability.\n\n### String Lifetimes & Pitfalls\n\n-   **`llvm::StringRef` is DISALLOWED**: Do not pass `StringRef` as a parameter\n    type to `CARBON_DIAGNOSTIC` due to unsafe lifetime and buffer-allocation\n    boundaries.\n-   **`llvm::StringLiteral` is DISALLOWED**: Do not use literal types as\n    arguments as they prevent future diagnostic localization and translations.\n-   **Use `std::string`**: If string formatting or custom allocations are\n    required, declare the parameter storage type as `std::string`.\n\n### Format Selectors (`format_providers.h`)\n\nUse specialized formatting wrappers under\n[format_providers.h](../../../toolchain/diagnostics/format_providers.h) to\nexpress clean inline options in format strings:\n\n| Wrapper                    | Target Format Style             | Example Usage                  | Output                                                              |\n| :------------------------- | :------------------------------ | :----------------------------- | :------------------------------------------------------------------ |\n| **`BoolAsSelect`**         | `{Index:true\\|false}`           | `\"{0:is signed\\|is unsigned}\"` | Maps bool to selection string.                                      |\n| **`IntAsSelect`**          | `{Index:=Val:String\\|:Default}` | `\"{0:=1:is\\|:are}\"`            | Matches exact options.                                              |\n| **`IntAsSelect` (Plural)** | `{Index:s}`                     | `\"{0} argument{0:s}\"`          | Prints `\"s\"` if value != 1 (e.g., `\"1 argument\"`, `\"3 arguments\"`). |\n\n### Custom Toolchain Type Mappings\n\nCustom structures can define how they serialize inside diagnostics using the\n`DiagnosticType` tag mapping to `Diagnostics::TypeInfo<StorageType>`:\n\n-   **Identifiers & Names** (declared in `check/diagnostic_helpers.h`):\n    -   `NameId`: Formats raw identifier spelling, safely escaping keyword\n        conflicts under backticks automatically.\n    -   `LibraryNameId`: Formats custom library descriptors cleanly (e.g.\n        `default library` or `library \"foo\"`).\n-   **Sized Primitives**:\n    -   `TypedInt`: Formats an `APInt` constant exactly, extracting target\n        signedness representation automatically from its bound type\n        representation.\n-   **Type Formatter Hierarchy**: When choosing parameter types to print\n    compiler type representations, follow this priority list:\n    1.  **`TypeOfInstId` (Preferred)**: Resolves the backing type of an\n        `InstId`, preserving programmatic aliasing, constraints, and source\n        spelling context. Enclosed under backticks automatically.\n    2.  **`InstIdAsType`**: Converts an `InstId` for a type expression, printing\n        custom type layouts under backticks.\n    3.  **`TypeId` (Fallback)**: Canonical description of the type. **Avoid when\n        possible** because type canonicalization loses intermediate source\n        program spelling and aliasing metadata.\n    4.  **`*AsRawType` (e.g. `InstIdAsRawType`, `TypeIdAsRawType`)**: Formats\n        the type layout exactly like their counter-structures above, but\n        **omits** enclosing backticks (useful when inserting types inside larger\n        code snippets).\n\n---\n\n## 3. Fluent Emission Builders & RAII Scopes\n\n### Fluent Builder Pattern\n\nA diagnostic is one message plus the labels that mark the source explaining it.\nUse `Build` to state the message and `Attach` to mark each place the reader has\nto look, chained fluently:\n\n```cpp\nCARBON_DIAGNOSTIC_LABEL(ModifierPrevious, Info, \"`{0}` previously appeared here\",\n                        Lex::TokenKind);\n\ncontext.emitter()\n    .Build(second_node, ModifierRepeated, context.token_kind(second_node))\n    .Attach(first_node, ModifierPrevious, context.token_kind(first_node))\n    .Emit();\n```\n\nLabels are declared with `CARBON_DIAGNOSTIC_LABEL` where they are attached, and\nare not registered in `kind.def`; `check_diagnostics.py` checks that each one is\nattached and covered. A label is either `Primary` -- the range the message\nitself is about -- or `Info`, for somewhere else the reader must look; those two\nare the only categories, because anything not read against the code it names is\nnot a label. `Attach(loc)` with no label marks a range wordlessly, which is what\nto use when a label would only restate the message.\n\nEvery diagnostic should attach at least one label; a message with nothing\nattached has nothing to show. See\n[diagnostics.md](../../../toolchain/docs/diagnostics.md) for which range to pick\nand when a label earns words.\n\n> [!SAFETY] Emitter builders are marked `[[nodiscard]]`. To prevent a developer\n> from creating a builder but failing to terminal-chain `.Emit()`, the builder\n> uses an rvalue overload `Emit() &&` that triggers a compile-time\n> `static_assert(false)`. You must save the builder to an lvalue or execute the\n> chain exactly as `emitter.Build(...).Attach(...).Emit()`.\n\n### RAII Context & Annotation Scopes\n\nManage large checking structures requiring blanket context using RAII block\nscopes:\n\n-   `ContextScope`: Attaches a context to every diagnostic emitted within its\n    scope, describing the higher-level operation that failed because of it. A\n    context is declared with `CARBON_DIAGNOSTIC_CONTEXT`, or\n    `CARBON_DIAGNOSTIC_SOFT_CONTEXT` for one dropped when the diagnostic\n    already has a context:\n\n    ```cpp\n    Diagnostics::ContextScope diagnostic_context(\n        &context.emitter(), [&](auto& builder) {\n          CARBON_DIAGNOSTIC_CONTEXT(\n              QualifiedDeclInIncompleteClassScope,\n              \"cannot declare a member of incomplete class {0}\", SemIR::TypeId);\n          builder.Attach(loc_id, QualifiedDeclInIncompleteClassScope,\n                         context.classes().Get(class_id).self_type_id);\n        });\n    ```\n\n    A context is not a label: its text stands alone as a sentence, which is why\n    it leads the diagnostic rather than following it.\n\n-   `AnnotationScope`: RAII block scope that attaches labels to every diagnostic\n    emitted within it, using the same `Builder` as a direct emission.\n\n---\n\n## 4. Diagnostics Wording Style Guide\n\nRefer to the official\n[Diagnostic message style guide](../../../toolchain/docs/diagnostics.md#diagnostic-message-style-guide)\nfor complete details.\n\nTo maintain message consistency and integrate cleanly with Clang diagnostics in\ninteroperable code, adhere strictly to these rules:\n\n-   **Start with lowercase and omit periods**: Start diagnostic messages with a\n    lowercase letter or quoted code, and do **not** end them with a period\n    (e.g., `\"cannot convert...\"` or ``\"`self` declared...\"``).\n-   **Use backticks for quoted code**: Enclose identifiers, code constructs, and\n    types inside standard backticks (e.g., ``\"`{0}` is bad\"``).\n-   **Phrase as bullet points without articles**: Phrase diagnostics as\n    descriptive bullet points or sentence fragments rather than full sentences.\n    Leave out standard articles (`a`, `an`, `the`) unless necessary for logical\n    clarity. Semicolons can be used to separate fragments within a message.\n-   **Describe the situation and language rule**: Diagnostics should describe\n    the exact situation the toolchain observed. The language rule violated can\n    be mentioned if it wouldn't otherwise be clear:\n    -   _Situation-only_: `\"redeclaration of X\"` (implies that redeclaration is\n        not permitted).\n    -   _Rule-inclusion_: ``\"`self` declared in invalid context; can only be\n        declared in implicit parameter list\"``.\n-   **Wording Choice (\"cannot\" vs \"allowed\")**: Explicitly avoid `\"allowed\"`,\n    `\"legal\"`, `\"permitted\"`, `\"valid\"`, and related passive wording. You may\n    use `\"cannot\"` if needed, but try to use phrasing that does not require it:\n    -   _Correct_: ``\"`export` in `impl` file\"`` (Avoids `\"allowed\"`)\n    -   _Incorrect_: ``\"`export` is only allowed in API files\"``\n    -   _Correct_: ``\"`extern library` specifies current library\"`` (Avoids\n        `\"cannot\"`)\n    -   _Incorrect_: ``\"`extern library` cannot specify the current library\"``\n-   **Developer Intent Hints**: It is acceptable for a diagnostic to guess at\n    the developer's intent and provide a hint _after_ explaining the situation\n    and the rule, but never as a substitute for that:\n    -   _Correct_: ``\"cannot implicitly convert `i32` to `String`; add `as\n        String` for explicit conversion\"``\n    -   _Incorrect_: ``\"add `as String` to convert `i32` to `String`\"`` (Lacks\n        the core violation message).\n-   **Structure for Tooling API**: Try to structure diagnostics such that\n    parameter inputs can be programmatically extracted without string parsing\n    (prefer strongly-typed parameters over format placeholders where possible).\n\n---\n\n## 5. Diagnostics Testing & Coverage Verification\n\nCarbon strictly enforces testing coverage at build-time.\n\n1.  **Tag Verification Requirement**: Every diagnostic kind declared in\n    `kind.def` (which is not blacklisted in the `UntestedKinds` array under\n    [coverage_test.cpp](../../../toolchain/diagnostics/coverage_test.cpp))\n    **MUST** be verified by at least one testcase file inside\n    `toolchain/*/testdata/`.\n2.  **Stderr Checklist Matchers**: The testcase split verifying the diagnostic\n    must catch it using standard CHECK matchers, explicitly tracking the\n    matching enum tag in standard error comments:\n\n    ```carbon\n    // CHECK:STDERR: fail_bounds.carbon:[[@LINE+1]]:15: error: cannot convert NaN to integer type `i32` [FloatNaNConvertedToInt]\n    let a: i32 = Convert(nan_val);\n    ```\n\n3.  **Build Enforcement**: Failing to provide a diagnostic test check matcher\n    triggers a failure on the target test\n    `//toolchain/diagnostics:coverage_test`.\n4.  **Label Enforcement**: A label is declared where it is attached rather than\n    in a central registry, so `coverage_test` has no list of labels to compare a\n    matched name against and leaves any name that isn't a kind alone.\n    [check_diagnostics.py](../../../toolchain/diagnostics/check_diagnostics.py)\n    is what checks them: it reads the declarations and the testdata directly, so\n    it catches a label with no test, a name matched on that is neither a kind\n    nor a label, and a kind registered in `kind.def` that nothing declares. It\n    runs as a pre-commit hook, which CI runs too, rather than as a bazel test --\n    reading every source file is what it needs and what a test in the sandbox\n    cannot do.\n","frontmatter":{"name":"Diagnostics","description":"Instructions for declaring, formatting, emitting, testing, and styling diagnostic messages (errors, warnings, and the labels that explain them) in the Carbon toolchain."},"isInternal":false,"tokens":3242,"sizeBytes":14256},{"name":"SKILL.md","path":".agents/skills/github_cli/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/github_cli/SKILL.md","title":"GitHub CLI usage","category":"anthropic-skill","format":"markdown","content":"---\nname: GitHub CLI usage\ndescription:\n    Instructions for using the `gh` command to query and inspect GitHub state\n    safely.\n---\n\n# GitHub CLI usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill provides instructions for using the GitHub CLI (`gh`) to query,\ninspect, and search GitHub state (issues, pull requests, repositories) for the\nCarbon project.\n\n## Safety First: Read-Only Usage\n\n> [!IMPORTANT] AI assistants MUST NOT use the `gh` tool to modify any GitHub\n> project state. Do NOT run commands that create, edit, delete, label, comment\n> on, or merge issues, pull requests, releases, or any other resources.\n\n### Allowed Verbs\n\n-   `list`\n-   `view`\n-   `search`\n-   `status`\n-   `api` (Only with `GET` requests)\n\n### Prohibited Verbs\n\n-   `create`\n-   `edit`\n-   `delete`\n-   `merge`\n-   `reopen`\n-   `close`\n-   `comment`\n-   `label`\n\n## Repository Configuration\n\nThe `gh` tool interacts with a default repository when run within a local check\nout. For this project, the default repository is expected to be\n`carbon-language/carbon-lang`.\n\n### Verifying Default Repository\n\nTo verify the current default repository configuration:\n\n```bash\ngh repo view\n```\n\nThe output should indicate the repository is `carbon-language/carbon-lang`.\n\n### Correcting Misconfigurations\n\nIf the default repository is misconfigured (for example, pointing to a personal\nfork or a different repository), the human operator must correct it.\n\n> [!IMPORTANT] AI Assistants MUST NOT attempt to mutate `gh` configuration or\n> run commands that change the default repository (such as\n> `gh repository set-default`).\n\nInstruct the human operator to run the following command to select the correct\ndefault repository:\n\n```bash\ngh repo set-default\n```\n\nThe operator will be prompted to select the correct repository (e.g.,\n`carbon-language/carbon-lang`) from the available remotes.\n\n## Common Query Commands\n\n### Issues\n\n-   **List issues**: `gh issue list`\n-   **View specific issue**: `gh issue view <number>`\n-   **Search issues**: `gh issue search \"<query>\"`\n    -   Example: `gh issue search \"crash\" --state open`\n\n### Pull Requests\n\n-   **List PRs**: `gh pr list`\n-   **View specific PR**: `gh pr view <number>`\n-   **View PR diff**: `gh pr diff <number>`\n-   **Check PR status**: `gh pr status`\n\n### Search\n\n-   **Search code**: `gh search code \"<query>\"`\n-   **Search repositories**: `gh search repos \"<query>\"`\n\n## Advanced Usage: GitHub API\n\nFor queries that are not supported by standard `gh` commands, you can use the\n`gh api` command to query the GitHub REST or GraphQL APIs.\n\n### REST API\n\nQuery the REST API using paths relative to the API root.\n\n-   **List contributors**:\n\n    ```bash\n    gh api repos/carbon-language/carbon-lang/contributors\n    ```\n\n-   **List issue comments**:\n\n    ```bash\n    gh api repos/carbon-language/carbon-lang/issues/<issue_number>/comments\n    ```\n\n### GraphQL API\n\nFor complex queries, use GraphQL to fetch exactly the data needed.\n\n-   **Get repository information**:\n\n    ```bash\n    gh api graphql -f query='\n      query {\n        repository(owner: \"carbon-language\", name: \"carbon-lang\") {\n          description\n          stargazerCount\n        }\n      }\n    '\n    ```\n\n### Pagination\n\nUse the `--paginate` flag to automatically fetch all pages of results.\n\n```bash\ngh api --paginate repos/carbon-language/carbon-lang/issues\n```\n\n### Filtering and Formatting\n\nUse `--json` to request JSON output, and `--jq` or `--template` to filter or\nformat the results.\n\n-   **List PR titles and authors**:\n\n    ```bash\n    gh pr list --json title,author --jq '.[] | \"\\(.title) by \\(.author.login)\"'\n    ```\n\n-   **Format with Go templates**:\n\n    ```bash\n    gh issue list --template '{{range .}}{{.number}} - {{.title}}{{\"\\n\"}}{{end}}'\n    ```\n\n## Documentation References\n\n-   **GitHub CLI Manual**:\n    [cli.github.com/manual](https://cli.github.com/manual/)\n-   **GitHub REST API Documentation**:\n    [docs.github.com/en/rest](https://docs.github.com/en/rest)\n-   **GitHub GraphQL API Documentation**:\n    [docs.github.com/en/graphql](https://docs.github.com/en/graphql)\n","frontmatter":{"name":"GitHub CLI usage","description":"Instructions for using the `gh` command to query and inspect GitHub state safely."},"isInternal":false,"tokens":1039,"sizeBytes":4258},{"name":"SKILL.md","path":".agents/skills/github_issues/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/github_issues/SKILL.md","title":"Accessing GitHub issues","category":"anthropic-skill","format":"markdown","content":"---\nname: Accessing GitHub issues\ndescription:\n    Instructions for safely viewing and accessing GitHub issues by way of\n    command line.\n---\n\n# Accessing GitHub issues\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill provides instructions for AI assistants on how to access and view\nGitHub issues. Agents should strongly prefer using the command line `gh` tool to\naccess and view the contents of issues rather than viewing their contents by way\nof a web browser.\n\n## Safety First\n\n> [!IMPORTANT] AI assistants MUST NOT modify any GitHub issue state. Only use\n> read-only access commands like `view` or `list`. Do NOT comment, edit, create,\n> close, or delete issues.\n\n## Accessing Issues\n\nAgents must use this skill to access issues regardless of how they are mentioned\n(for example, by URL or by issue number).\n\n### Basic View\n\nTo view an issue in the current default repository (expected to be Carbon):\n\n```bash\ngh issue view <issue_number>\n```\n\n### Including Full Context (All Comments)\n\nTo ensure the view includes the entire context of the issue, always include the\n`--comments` flag to dump all comments:\n\n```bash\ngh issue view <issue_number> --comments\n```\n\n> [!TIP] If the issue is extremely large and comments are truncated, or you need\n> to process comments programmatically, use the JSON output with `jq`:\n>\n> ```bash\n> gh issue view <issue_number> --json comments --jq '.comments[].body'\n> ```\n\n### Accessing Issues in Other Repositories\n\nTo view an issue in another repository (for example, LLVM), use the `-R` or\n`--repo` flag to specify the repository:\n\n```bash\ngh issue view <issue_number> -R <owner>/<repo> --comments\n```\n\nExamples:\n\n-   **LLVM Issue**:\n\n    ```bash\n    gh issue view 5678 -R llvm/llvm-project --comments\n    ```\n\n-   **Carbon Issue (Explicit)**:\n\n    ```bash\n    gh issue view 1234 -R carbon-language/carbon-lang --comments\n    ```\n\n## Mentions via URL\n\nIf an issue is mentioned via URL, parse the URL to extract the repository owner,\nrepository name, and issue number.\n\n-   **URL pattern**: `https://github.com/<owner>/<repo>/issues/<number>`\n-   **Extraction**:\n    -   Host: `github.com`\n    -   Owner: `<owner>`\n    -   Repo: `<repo>`\n    -   Number: `<number>`\n\nRun the command specifying the repository:\n\n```bash\ngh issue view <number> -R <owner>/<repo> --comments\n```\n","frontmatter":{"name":"Accessing GitHub issues","description":"Instructions for safely viewing and accessing GitHub issues by way of command line."},"isInternal":false,"tokens":598,"sizeBytes":2468},{"name":"SKILL.md","path":".agents/skills/jj/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/jj/SKILL.md","title":"Jujutsu (jj) usage","category":"anthropic-skill","format":"markdown","content":"---\nname: Jujutsu (jj) usage\ndescription:\n    Instructions for using Jujutsu (jj) for version control in the Carbon\n    repository.\n---\n\n# Jujutsu (jj) usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Jujutsu](https://github.com/jj-vcs/jj) is a Git-compatible version control\nsystem that may be used in Carbon checkouts.\n\n> [!IMPORTANT] You can detect if Jujutsu is in use by checking for a `.jj`\n> directory in the repository root. If present, you **must** use `jj` and **must\n> not** use `git`. If absent, you **must not** use `jj`.\n\n## General usage\n\nAlways use the `--no-pager` flag when invoking `jj` to prevent the command from\nblocking or waiting for terminal paging.\n\n## Common commands\n\n### Syncing with remote\n\n-   **Fetch from remote**: `jj --no-pager git fetch`\n-   **Create a new change on top of trunk**: `jj --no-pager new trunk`\n-   **Show repository status**: `jj --no-pager status`\n-   **Show commit history**: `jj --no-pager log`\n\n### Managing changes\n\n-   **View diff of current changes**: `jj --no-pager diff`\n-   **Commit changes**: `jj --no-pager commit`\n    -   _Note_: Prefer using `jj commit` over the combination of `jj describe`\n        and `jj new`.\n-   **Abandon/discard current changes**: `jj --no-pager abandon`\n-   **Rebase current change onto trunk**: `jj --no-pager rebase -o trunk`\n\n### Working with a stack of changes\n\nA change is often built as a stack of commits sent up as a single pull request.\nThe stack is not necessarily based on `trunk`; it may be based on another change\nthat is itself still in flight.\n\n> [!WARNING] **Never rewrite the history of a change that has been submitted as\n> a pull request.** Reviewers track a PR by its commits, and squashing,\n> reordering, or abandoning them discards review that is already in progress.\n> This cannot be undone from their side.\n>\n> Before rewriting history in any other case, propose the exact command and wait\n> for confirmation. This applies to `squash`, `rebase`, `abandon`, and\n> `describe` on an existing change.\n\n#### Finding the base of the stack\n\nBookmarks delimit the stack. List the bookmarks that are ancestors of the\nworking copy, nearest first:\n\n```bash\njj --no-pager log -r '::@ & bookmarks()'\n```\n\nReading the result takes care, because two situations produce similar output:\n\n-   **Editing an existing change.** The nearest bookmark names the change being\n    worked on, and the bookmark below it is the base.\n-   **Starting a new change.** The commits above the nearest bookmark have no\n    bookmark of their own yet, so the nearest bookmark is itself the base.\n\n`trunk` is only ever a base. Finding `trunk` nearest means new work is being\nbuilt on top of it, never that `trunk` itself is being worked on.\n\nThe graph does not distinguish the two cases: an unbookmarked or empty commit\nabove a bookmark may be the next commit of that change or the start of a new\none. Ask which it is when it is not clear, and ask before choosing where a fix\nshould land rather than after. Guessing wrong means squashing into a change that\nmay already be under review.\n\nOnce the base is known, use it to scope commands to the current stack:\n\n```bash\njj --no-pager log -r '<base-bookmark>..@'\n```\n\n#### Managing the stack\n\n-   **Fold a fix into an earlier change**:\n    `jj --no-pager squash --into <change-id> [path]`. Follow-up fixes and\n    formatter reflows belong in the change that introduced the code, not in a\n    trailing \"fixes\" commit, unless that change has already been submitted.\n    Naming a path squashes only that part of the working copy, leaving unrelated\n    work in place.\n-   **Descriptions**: only one change in the stack needs a long description, the\n    one used as the pull request description. Every other change gets a short\n    one-line summary. Do not repeat the long text across the stack.\n","frontmatter":{"name":"Jujutsu (jj) usage","description":"Instructions for using Jujutsu (jj) for version control in the Carbon repository."},"isInternal":false,"tokens":984,"sizeBytes":3964},{"name":"SKILL.md","path":".agents/skills/language_server/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/language_server/SKILL.md","title":"Language server","category":"anthropic-skill","format":"markdown","content":"---\nname: Language server\ndescription:\n    Instructions for working on Carbon's LSP language server, including its\n    architecture, its file_test-based tests, and the VS Code extension.\n---\n\n# Language server\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Introduction\n\nThis skill covers [`toolchain/language_server/`](/toolchain/language_server/),\nwhich implements `carbon language-server`, and\n[`utils/vscode/`](/utils/vscode/), the VS Code extension that launches it.\n\n## Architecture\n\nThe server is built on clangd's LSP transport (`clang::clangd`), not on a\nCarbon-specific one. That means clangd's `Protocol.h` types (`Position`,\n`Range`, `Location`, `Hover`, `MarkupContent`) are the interface currency.\n\n-   `server.cpp` / `incoming_messages.cpp`: message dispatch. A handler must be\n    registered in `incoming_messages.cpp` before it can be called.\n-   `handle_*.cpp`: one file per request family, each declaring its entry point\n    in `handle.h`.\n-   `handle_initialize.cpp`: the advertised capabilities. **Adding a capability\n    changes `Content-Length` in every test that calls `initialize`**, so expect\n    a large autoupdate diff.\n-   `context.h` / `context.cpp`: `Context::File` per open document, plus the\n    compile driver. `Context::File::unit()` has a `CARBON_CHECK` on the compile\n    driver, so any handler that reaches for the parse tree must first rule out\n    documents that were never compiled.\n-   `position.h`, `sem_ir_index.h`: mapping source positions to SemIR\n    instructions for real Carbon files.\n-   `sem_ir_text.h`, `handle_sem_ir_text.h`: navigation within the *formatted\n    SemIR* in a test file's `// CHECK:STDOUT:` lines. This is a heuristic text\n    index, deliberately independent of the real SemIR data structures. See\n    [the SemIR text reader](#the-semir-text-reader).\n\n### Document kinds\n\nThe server handles two kinds of document, distinguished by the `languageId`\nfrom `textDocument/didOpen`, with a content sniff as a fallback:\n\n-   `carbon`: a real Carbon file. Compiled; diagnostics published.\n-   `carbon-testdata`: a test file. **Not compiled**, because we lack logic to\n    split it into one file per `// ---` split marker.\n\n> [!IMPORTANT]\n> A handler that assumes every file was compiled will crash on a test file.\n> When adding one, give the test-file path an explicit early return.\n\n## Tests\n\nThere is **no language-server-specific test target**.\n`toolchain/language_server/BUILD` only declares\n`filegroup(name = \"testdata\")`, which is pulled into\n`//toolchain/testing:all_testdata` and run by `//toolchain/testing:file_test`.\n\n```bash\n# Run just the language server tests (or any subset).\nbazelisk test //toolchain/testing:file_test \\\n    --test_arg=--file_tests=toolchain/language_server/testdata/position/hover_and_goto.carbon\n\n# See the raw output, which is much easier to read than a test failure.\nbazelisk run //toolchain/testing:file_test -- --dump_output \\\n    --file_tests=toolchain/language_server/testdata/position/hover_and_goto.carbon\n\n# Update expectations. Never hand-write CHECK lines.\n./toolchain/autoupdate_testdata.py toolchain/language_server/testdata/...\n```\n\nThese tests run serially, because clangd's logging is a global singleton.\n\n### Test file shape\n\nThe request stream is a `// --- STDIN` split written with the `[[@LSP-*]]`\nkeywords, and the responses land in a trailing `// --- AUTOUPDATE-SPLIT`.\nDocuments come from other splits by way of `\"text\": \"FROM_FILE_SPLIT\"`, which\nis substituted with the content of the split whose name matches the `uri`.\n\n```carbon\n// --- position.carbon\nfn Abs(n: i32) -> i32 { return n; }\n\n// --- STDIN\n[[@LSP-CALL:initialize:\"capabilities\": {}]]\n[[@LSP-NOTIFY:textDocument/didOpen:\n  \"textDocument\": {\n    \"uri\": \"file:/position.carbon\",\n    \"languageId\": \"carbon\",\n    \"text\": \"FROM_FILE_SPLIT\"\n  }\n]]\n[[@LSP-CALL:textDocument/hover:\n  \"textDocument\": {\"uri\": \"file:/position.carbon\"},\n  \"position\": {\"line\": 0, \"character\": 3}\n]]\n[[@LSP-CALL:shutdown]]\n[[@LSP-NOTIFY:exit]]\n\n// --- AUTOUPDATE-SPLIT\n```\n\nFull keyword documentation is in\n[`testing/file_test/README.md`](/testing/file_test/README.md).\n\n### Traps\n\n> [!WARNING]\n> **A blank line inside the `STDIN` split breaks the JSON transport.** It\n> terminates a header block, so clangd logs a timestamped\n> `Warning: Missing Content-Length header, or zero-length message.` The\n> timestamp makes the test unreproducible, so it fails on the next run.\n> Comment lines between messages are fine; blank lines are not. A single blank\n> line immediately before `// --- AUTOUPDATE-SPLIT` is also fine.\n\nOther things worth knowing:\n\n-   **`positionEncoding` is UTF-16.** A `character` is a UTF-16 code unit\n    offset, not a byte offset.\n-   **Line and character numbers in requests are 0-based**, while the `locN_M`\n    suffixes in SemIR output are 1-based. Off-by-ones here are silent: the\n    request succeeds and returns the wrong thing.\n-   **A split can hold a document that itself contains `// CHECK:STDOUT:`\n    lines**, because `CHECK` lines only form expectations inside the\n    `AUTOUPDATE-SPLIT`. Such a document still can't contain a literal `// ---`\n    line, which would split the enclosing test file; write it as\n    `[[@0x2f]]/ --- name.carbon`.\n\n## The SemIR text reader\n\n`sem_ir_text.cpp` indexes the formatted SemIR inside a test file's\n`// CHECK:STDOUT:` lines so that hover and go-to-definition work on operand\nnames. It is a heuristic reader, not a parser, and its correctness rests on\nfacts about `toolchain/sem_ir/formatter.cpp` and\n`toolchain/sem_ir/inst_namer.cpp`. Re-check these if the formatter changes:\n\n-   There are exactly four scope keywords: `file`, `generated`, `imports`, and\n    `constants` (`InstNamer::GetScopeName`). Everything else is `@entityname`.\n-   A reference is `%name` within its own scope and `scope.%name` otherwise\n    (`InstNamer::GetNameFor`). Names may contain `.` and may _start_ with one,\n    as in `%.Self.frozen`.\n-   **Type annotations are printed in the `constants` scope.**\n    `Formatter::FormatTypeOfInst` does\n    `llvm::SaveAndRestore file_scope(scope_, InstNamer::ScopeId::Constants)`,\n    so in `%x: %foo = ...` a bare `%foo` means `constants.%foo`. This does not\n    apply to ordinary operands or to `[concrete = ...]` annotations.\n-   **`*_decl` braces hold the declared entity's scope.** The braces of\n    `%F.decl: ... = fn_decl @F [...] { ... } { ... }` are lexically inside\n    `file { }`, but their names belong to `@F`.\n-   **`!with Self:` switches scope without a brace**, until `!members:`\n    switches it back. Brace counting alone cannot see this.\n-   A `specific @F(args) { }` block uses `@F`'s scope and defines nothing; each\n    `%name => value` row references an instruction of the generic.\n\n### Validating a change to the reader\n\nThe unit tests only cover a handful of cases. To check a change against the\nreal corpus, drive the server over a sample of check testdata, hovering on\nevery `%name`, and compare the resolved fraction before and after. Roughly 99%\nof names resolve; the residue are names the formatter references but never\nemits a definition line for, such as `%I.WithSelf.F`, which only ever appears\ninside a `[symbolic = ...]` annotation.\n\nTwo things to get right in such a harness:\n\n-   Feed the request stream from a **file**, not a pipe. The server reads stdin\n    as a file and reports `error: Input/output error` on a pipe.\n-   Read the output as **bytes**. Python's `text=True` rewrites the `\\r\\n`\n    framing, and `Content-Length` counts bytes.\n\n## VS Code extension\n\n[`utils/vscode/`](/utils/vscode/) declares three languages in `package.json`:\n\n| Language id      | Applies to                        |\n| ---------------- | --------------------------------- |\n| `carbon`         | `*.carbon`                        |\n| `carbon-testdata`| `**/testdata/**/*.carbon`         |\n| `semir`          | `*.semir`                         |\n\n> [!NOTE]\n> The TextMate _scope_ for SemIR is `source.carbon-semir`, but the\n> _language id_ is `semir`. Markdown code fences in hover text resolve language\n> ids, so a fence must say ` ```semir `.\n\n`extension.ts` launches the server over stdio, using the `carbonPath` setting\n(default `./bazel-bin/toolchain/carbon`). Its `documentSelector` controls which\nfiles are sent to the server at all; a new document kind has to be added there\nas well as in the server.\n","frontmatter":{"name":"Language server","description":"Instructions for working on Carbon's LSP language server, including its architecture, its file_test-based tests, and the VS Code extension."},"isInternal":false,"tokens":2148,"sizeBytes":8520},{"name":"SKILL.md","path":".agents/skills/prek/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/prek/SKILL.md","title":"Prek","category":"anthropic-skill","format":"markdown","content":"---\nname: Prek\ndescription:\n    Instructions for running prek, the Carbon pre-submit/style/lint checker,\n    that *MUST* be run before submitting an change.\n---\n\n# Prek\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n`prek` is the Carbon pre-submit, style, and lint checker. Running it is\nmandatory before submitting any changes.\n\n## Running prek\n\nTo run `prek` on all files:\n\n```bash\nprek run -a\n```\n\nTo validate a specific list of files:\n\n```bash\nprek run --files <files>\n```\n\n## Running prek in a Jujutsu (jj) workspace\n\nIf you are working in a Jujutsu workspace, running `prek` directly will fail\nbecause it expects a standard Git repository structure. Instead, use the helper\nscript:\n\n```bash\n./scripts/jj_prek.sh\n```\n\nThis script runs `prek` on all files that have changed between `trunk` and your\ncurrent Jujutsu `@` change.\n\nNote that the script always compares against `trunk`. If your change is based on\nanother bookmark rather than on `trunk`, the script also checks the files\nchanged by that underlying change, so a reported failure may not be in your own\nwork.\n\n## Hooks that rewrite files\n\nSome hooks, notably `clang-format` and `rumdl`, fix problems in place rather\nthan only reporting them. When they do, `prek` reports a failure and exits\nnon-zero even though the tree is now correct.\n\nRe-run `prek` after any failure that modified files, and treat the second, clean\nrun as the result. Review what it changed: a reflow is expected, but a content\nchange may not be what you intended.\n\n## Prek dependency errors\n\n> [!TIP] If `prek` fails with an error about resolving dependencies or security\n> policy, you may be running in a restricted environment where the\n> special-purpose `gpkg` tool is required. Prefix the command with `gpkg`, for\n> example: `gpkg prek run -a` or `gpkg ./scripts/jj_prek.sh`.\n","frontmatter":{"name":"Prek","description":"Instructions for running prek, the Carbon pre-submit/style/lint checker, that *MUST* be run before submitting an change."},"isInternal":false,"tokens":497,"sizeBytes":1962},{"name":"SKILL.md","path":".agents/skills/proposals/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/proposals/SKILL.md","title":"Proposals","category":"anthropic-skill","format":"markdown","content":"---\nname: Proposals\ndescription:\n    Instructions for writing, submitting, and managing Carbon evolution\n    proposals.\n---\n\n# Proposals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Overview\n\nThis skill provides instructions and best practices for working with proposals.\nOnly create a proposal when explicitly directed as part of the task.\n\nMake sure to confirm the desired title for the proposal as that will govern the\nfilename.\n\n## Create a new proposal\n\n1.  **Use the helper script**: Run `./proposals/scripts/new_proposal.py \"Title\"`\n    to create a templated file and instructions for setting up the PR.\n2.  **Proposal file**: The file will be named `proposals/p######-title.md`,\n    where `######` is the 6-digit GitHub pull request number and `title` is a\n    slugified version of the proposal title.\n3.  **Template**: Follow the structure in `proposals/scripts/template.md`,\n    noting the specific `TODO` instructions in each section for the content that\n    should be included there.\n4.  **PR description**: Update the pull request description to match the\n    abstract section in the proposal document.\n\n> [!IMPORTANT] Do _not_ mark the PR ready for review. The user must have the\n> opportunity to review the proposal produced before asking for any review.\n\n## Writing style and best practices\n\n-   **Skimmable**: Use\n    [BLUF](<https://en.wikipedia.org/wiki/BLUF_(communication)>) (Bottom Line Up\n    Front) or\n    [Inverted Pyramid](<https://en.wikipedia.org/wiki/Inverted_pyramid_(journalism)>)\n    style. Keep it brief, focused, and technical.\n-   **Match existing proposal style**: Review [existing proposals](/proposals)\n    (preferring more recent ones with higher numbers) to understand the expected\n    style, wording, and nature of content to include.\n-   **Connect to goals**: In the Rationale section, link to specific goals in\n    [`/docs/project/goals.md`](/docs/project/goals.md) and principles in\n    [`/docs/project/principles`](/docs/project/principles) (e.g.,\n    `error_handling.md`, `one_way.md`).\n-   **Living design**: If the proposal updates design documentation, include\n    those changes in the PR if possible. If deferred, add \"TODO\" comments\n    pointing to the proposal (e.g., `> **TODO:** Document ... adopted in\n    [p######](/proposals/p######-title.md)`). For pervasive changes, file a\n    GitHub issue instead of adding many TODOs.\n\n## Alternatives considered and leads decisions\n\nThere are always alternatives to a proposal, and the proposal should carefully\ninclude sections describing all of them and the rationale for not selecting\nthem. Any living design document updates should focus on fully describing the\nend-state design, and the key motivating aspects of that design. The main\nproposal should focus on _what is changing_ and _why it is changing_, and should\nleave detailed description of the resulting design to the living design\ndocument, and _why not_ rationale to the description of each alternative.\n\n-   **Cover all the alternatives**: Make sure to describe any alternatives\n    considered, even if minor or rejected early.\n-   **Be specific**: Don't be vague about any of the alternatives, or the\n    rationale for not choosing them.\n-   **Connect to goals or principles**: In addition to the rationale section,\n    one of the best rationale structures for rejecting an alternative connects\n    that choice back to the goals or principles relevant.\n-   **Always frame as a tradeoff**: Selecting the proposed direction instead of\n    an alternative is _always_ a tradeoff, with both advantages and\n    disadvantages.\n-   **Where relevant, cite the leads issue** that decides against an\n    alternative, in addition to summarizing the key points, tradeoffs, and\n    rationale for the decision.\n\n> [!IMPORTANT] Don't just list the alternatives, create a sub-section for each\n> alternative and carefully describe the alternative, the advantages,\n> disadvantages and what the core of the decision is to reject each alternative.\n\n> [!IMPORTANT] Carefully research each alternative in the leads issue in order\n> to provide this clear and comprehensive explanation.\n\n## Building from a leads issue\n\nSometimes a proposal is specifically documenting and formalizing a decided leads\nissue. When this is the case, carefully research that leads issue, reading the\noriginal issue text and every comment on the issue. Also read any linked Google\ndocuments, linked issues, examples, gists, or other supplemental information\ncited.\n\n-   **Summarize the leads issue**: Ensure you provide a high level summary of\n    the _decided_ direction of the leads issue as the proposal.\n-   **Capture and document** every key aspect of the decision made and factor\n    that led to the decision. It is important that the proposal stands alone,\n    and the leads issue is merely cited for context and history.\n-   **Stay grounded**: Only include alternatives, rationale, and arguments based\n    on what you find in the issue and related documents. No new information\n    should be in the proposal.\n\nUse the `gh` command line tool to query leads issues in order to carefully\nexamine all of the comments. Follow any mentioned links to gather more data.\nRefer to the [GitHub CLI usage skill](/.agents/skills/github_cli/SKILL.md) for\ndetailed instructions on using the `gh` tool.\n\nAsk the user to clarify any aspects of the leads issue that are unclear rather\nthan continuing to edit the proposal. If there are questions that you don't find\nan answer to in the issue, ask this to the user and let them provide an answer\nthat you use as the basis of what to include.\n\n## Examples are golden\n\nHeavily leverage examples to illustrate both the specifics of the design being\nproposed, and the nature of the change being proposed. More examples to\nillustrate more aspects, corner cases, or provide a more complete understanding\nare almost always good. Comments in example code should focus on what that part\nof the example illustrates from the proposal.\n\n## Keep the PR description in sync with the abstract\n\nWhenever you edit the abstract or notice differences from the PR description,\nyou should update the PR description to match the abstract. The only exception\nis to retain any \"Assisted-by\" or other tags at the end of the description that\nare only needed there and not in the abstract.\n\nIf you are creating or updating a proposal, make sure the PR description in\nquestion contains an `Assisted-by:` tag that is appropriate for describing which\nAI tool is being used.\n","frontmatter":{"name":"Proposals","description":"Instructions for writing, submitting, and managing Carbon evolution proposals."},"isInternal":false,"tokens":1445,"sizeBytes":6650},{"name":"SKILL.md","path":".agents/skills/review_testdata_changes/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/review_testdata_changes/SKILL.md","title":"Review testdata changes","category":"anthropic-skill","format":"markdown","content":"---\nname: Review testdata changes\ndescription:\n    Instructions for judging whether changes to file test output\n    (`// CHECK:STDOUT:` and `// CHECK:STDERR:` lines) are correct, which\n    changes are acceptable churn, and which are regressions in disguise.\n---\n\n# Review testdata changes\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Introduction\n\nMost toolchain work moves file test output. `./toolchain/autoupdate_testdata.py`\nrewrites the `// CHECK:STDOUT:` and `// CHECK:STDERR:` lines in\n`toolchain/*/testdata/` to match current behavior, so after running it the tests\npass again whether or not the new behavior is right. Deciding that the new\noutput is the output you wanted is a separate, manual step, and it is the step\nthis skill covers.\n\nThree skills divide the work:\n\n-   [Toolchain tests](../toolchain_tests/SKILL.md): how to _author_ tests and\n    generate their output.\n-   This skill: how to _judge_ an output diff.\n-   [Summarize testdata changes](../summarize_testdata_changes/SKILL.md): how to\n    _report_ an output diff once you believe it is correct.\n\n> [!IMPORTANT] Never hand-edit `// CHECK:STDOUT:` or `// CHECK:STDERR:` lines.\n> Everything below is about changing the _code_ until the generated output is\n> right, never about editing the output to match the code.\n\n## The rule that generates all the others\n\n**Every line of testdata churn must have a cause you can name.** Not \"it is\nsimilar to the other changes\", not \"the tests pass now\" — an actual sentence\nsaying which code change produced it and why that is the intended result.\n\nA diff you cannot narrate is a diff you have not reviewed. Changes you cannot\nexplain are where regressions hide, because a regression and an intended change\nlook exactly alike once the autoupdater has written them down.\n\n> [!CAUTION] Autoupdating is destructive to your evidence. Once the autoupdater\n> has run, the previous expectations are gone from the working copy. Read the\n> diff after _every_ autoupdate run, and if something changed for a reason you\n> cannot name, fix the code before autoupdating again. Recovering the old\n> expectations later means reverting and re-running.\n\n## STDERR and STDOUT are different kinds of evidence\n\nTreat them separately; they have different standards of proof.\n\n**STDERR is user-visible behavior.** These are the diagnostics a Carbon\nprogrammer sees. A change here is a change to the language implementation as\nusers experience it, so each one needs an individual justification. For a\nrefactoring, the expected STDERR diff is empty.\n\n**STDOUT is internal representation.** SemIR dumps, parse trees, LLVM IR. Users\nnever see it. Churn here is normal and often unavoidable, so the standard is not\n\"no change\" but \"no change I cannot account for\".\n\nFor a change that is supposed to preserve behavior, write the list of accepted\nSTDERR changes down _before_ you autoupdate, and keep it current. Order matters\nmore than form: written first, the list is a prediction the diff can falsify;\nwritten afterwards, it is a description of whatever happened, and describes a\nregression exactly as well as an intended change.\n\nThe list does not have to be a deliverable. Scratch notes you never publish do\nthe job, because the work is in committing to the list, not in presenting it.\nWhat a reader needs is not the list but its exceptions: diagnostics that changed\nwithout being predicted, and predictions that did not occur. Both are findings.\nThe matches are not, and reporting them buries the two entries that matter.\n\n## Judging STDOUT churn\n\nSort each STDOUT change into mechanical or structural.\n\n### Mechanical churn\n\nExpected, and cheap to accept in bulk once you have confirmed the pattern:\n\n-   **Renaming.** An instruction, type, or scope prints under a new name.\n-   **Positional name renumbering.** Names like `%x.loc18_46.3` embed a line,\n    column, and disambiguating index. Two different events move them:\n    -   Adding or removing an instruction at a location renumbers the rest, so a\n        _single_ removed instruction can show up as many changed lines in the\n        same block. Confirm the cascade is a cascade before accepting it as one.\n    -   Adding or removing a _diagnostic_ moves the source lines themselves, so\n        the line component changes everywhere below it in the file. See\n        [Autoupdate to a fixed point](#autoupdate-to-a-fixed-point).\n-   **Fingerprint-derived names.** Mangled names and some scope names are\n    derived from a hash of their inputs. If you changed a hashed input, these\n    move. Confirm that each such difference is _only_ the fingerprint, and not a\n    fingerprint difference concealing a structural one.\n\n> [!TIP] Mechanical churn is usually wide and shallow: the same substitution,\n> repeated across many files. If a \"mechanical\" pattern needs a different\n> explanation in each file, it is not mechanical.\n\n### Structural churn\n\nEach of these needs its own explanation:\n\n-   Instructions appearing or disappearing.\n-   Changed `[concrete = ...]`, `[symbolic = ...]`, or other constant-value\n    annotations.\n-   Changed types on existing instructions.\n-   Changed control flow: new or removed blocks, changed branch targets.\n-   Raw instruction ids renumbering in `--dump-raw-sem-ir` output when you did\n    not intend to change the id layout.\n\n## Fewer instructions is not automatically better\n\nA diff that removes instructions looks like an optimization. Whether it is one\ndepends on what the changed function owes its caller, and two functions can\nproduce the same shrinking diff for opposite reasons:\n\n-   A function that only needs a constant value, but built instructions on the\n    way to it, was doing wasted work. Dropping them and using the constant\n    directly is correct, and the shorter output reflects that.\n-   A function whose caller needs a **non-canonical instruction** can be made\n    shorter the same way, by using the constant instead of creating an\n    instruction of its own — and that is wrong. The instruction carries location\n    information, and symbolic constant substitution operates on it; the constant\n    value alone loses both.\n\nThe instruction count is identical evidence in both cases, so it cannot be the\nthing you judge. Decide what the function is required to produce; the count\nfollows from that.\n\nThe same reasoning runs in reverse: a diff that _adds_ instructions is not\nautomatically a regression.\n\n## Judging STDERR churn\n\n### A diagnostic's authority depends on the file's prefix\n\nThe `fail_` and `todo_` prefixes (see\n[Toolchain tests](../toolchain_tests/SKILL.md)) say how much the recorded\ndiagnostics are worth:\n\n-   **`fail_...`** — the test should and does produce errors. The recorded\n    diagnostic **is the specification**. Changing it is a user-visible behavior\n    change and needs justification on its own merits.\n-   **`fail_todo_...`** — the test produces errors (or crashes) but shouldn't,\n    or produces the wrong errors. The recorded diagnostic is explicitly **not**\n    the specification; the file exists to record that today's behavior is wrong.\n    Changing it replaces one wrong answer with another. That is acceptable when\n    you can say why the new message follows from your change and why it is no\n    further from the intended eventual behavior — which, for many such files, is\n    no diagnostic at all.\n-   **`todo_fail_...`** — the test should produce errors but does not. Gaining a\n    diagnostic here may be _progress_, not a regression. Either way the file\n    must be renamed, since the framework requires a `fail_` prefix on any file\n    that errors: `fail_...` if it now produces the right error, `fail_todo_...`\n    if the error is the wrong one. Both renames make the test pass, so record\n    which case it is instead of letting the rename settle it.\n-   **`todo_...`** — behavior is wrong but produces no errors, and shouldn't.\n    Gaining a diagnostic here is a regression unless you can argue otherwise.\n\n> [!IMPORTANT] This is a reason to look at the _filename_ before judging a\n> diagnostic change, not a license to ignore `todo_` files. \"It was already\n> broken\" does not excuse making it differently broken for no reason.\n\n### Reclassifying tests\n\nIf your change moves a test between the states above, the prefix must move with\nit: when the test is fixed, when it starts failing, and when it starts failing\ndifferently. The correspondence between the `fail_` prefix and whether\ncompilation actually failed is enforced by the test framework, not by the\nautoupdater, so it surfaces when you run `bazelisk test` and not when you\nautoupdate. **Autoupdating is not a substitute for running the tests.**\n\nOnly that half of the name is checked. Nothing enforces `todo_`, so a file whose\nbehavior you have just fixed can keep its `todo_` prefix indefinitely and still\npass. A missing `fail_` stops the build; a stale `todo_` is silent, and is yours\nto catch.\n\nWhen a fix drops a file's prefix, also check that the file still belongs where\nit is and that its comments do not still describe the old broken behavior.\n\n### Vaguer diagnostics are a signal, not a verdict\n\nWhen a diagnostic becomes less specific — a general \"unsupported\" message\nreplacing one that named the problem — that usually means a code path stopped\nfinding information it previously had. Sometimes that is correct: the\ninformation was misleading, and the old message was confidently wrong.\n\nDo not accept it silently and do not reject it reflexively. Say which direction\nit moved and whether the new message is closer to or further from the eventual\nintended behavior.\n\n## Signals in the shape of the diff\n\n### Zero churn is a result\n\nIf you removed something you believed was doing work and _no_ testdata moved,\nthat is not a missing test run — it is the proof that the thing was a no-op.\nSay so explicitly; it is one of the strongest pieces of evidence a refactoring\ncan produce.\n\nThe converse is also informative. If you expected a path to churn and it didn't,\neither your model of the code is wrong or that path is untested. Find out which,\nand consider adding a test before continuing.\n\n### Churn should be proportional to the change\n\n-   **Wide churn from a narrow change** means your model of the code is wrong.\n    Do not autoupdate over it. Find the structural mistake first.\n-   **Narrow churn from a sweeping change** means the affected paths are\n    probably untested.\n\nSet a rough expectation for the size of the diff before you run the autoupdater,\nand treat a large mismatch in either direction as a finding.\n\n### Never make the diff smaller by weakening the test\n\nEditing test _input_ (the Carbon source, not the CHECK lines) to make a diff\nlook better is a behavior change in disguise. Deleting a test that now produces\nawkward output is worse. If a test's input has to change, that is a separate,\nexplicitly-justified change, not diff cleanup.\n\n## What the autoupdater will not fix for you\n\n-   **`NOAUTOUPDATE` files.** Their expectations are maintained by hand. They\n    fail under `bazelisk test` rather than being silently rewritten.\n-   **Hand-written C++ expectations**, for example golden output asserted in a\n    `_test.cpp`. When several assertions in one of these break together, often\n    only the first failure is reported, so fixing it can reveal another. Re-run\n    until clean rather than assuming one fix was the whole repair.\n-   **Golden files outside `testdata/`**, and documentation that quotes compiler\n    output.\n\n## Review loop\n\n### Run the autoupdater\n\nAutoupdate everything, then read the diff a directory at a time. Passing no\npaths is the default and updates every file test in the toolchain:\n\n```bash\n./toolchain/autoupdate_testdata.py\n```\n\nNarrow the scope only while iterating on one subdirectory you know you are not\ndone with, where each round would otherwise regenerate output you have already\nread:\n\n```bash\n./toolchain/autoupdate_testdata.py toolchain/check/testdata/SUBDIR/**/*\n```\n\nThe globs are expanded by the shell; the script filters its arguments to\n`.carbon` files under a `testdata/` directory.\n\n> [!TIP] If intermediate states crash on `CARBON_CHECK` failures, pass\n> `--non-fatal-checks` so you can see the full set of downstream damage in one\n> run instead of one crash at a time.\n\n> [!IMPORTANT] Return to the full scope before judging the diff. Whether churn\n> is proportional to the change, and whether a change to one phase moved another\n> phase's testdata, are only visible across everything.\n\n### Autoupdate to a fixed point\n\nOne pass is not always enough, because the autoupdater's output is part of its\nown input. `// CHECK:STDERR:` lines sit inline, immediately above the source\nline they describe, and the compiler reads them as comments in the file.\nGaining or losing a diagnostic therefore moves every source line below it.\n\nWithin a single run, the compiler has already read the file as it was, so the\ntwo kinds of output end up in different states:\n\n-   **STDERR is correct after one pass.** These lines locate themselves\n    relatively, as `[[@LINE+N]]`, and the autoupdater recomputes `N` as it\n    places them.\n-   **STDOUT is stale after one pass.** SemIR names like `%x.loc18_46.3` embed\n    an absolute line and column with no filename attached, and the autoupdater\n    only remaps `file.carbon:18`-style references. Nothing rewrites the `loc`,\n    so it still describes where the instruction was _before_ the diagnostic\n    lines moved it.\n\nRunning again compiles the shifted file and the names catch up. The diagnostic\nset does not change this time, so nothing shifts again and a third run is a\nno-op. Keep running the autoupdater until it stops changing files: one pass when\nthe diagnostics held still, two when they didn't.\n\n> [!WARNING] The intermediate state is self-inconsistent, not just unfinished:\n> its `loc` names describe a file layout that no longer exists. Keep reading the\n> diff after every run — that rule does not change — but do not chase positional\n> churn to a cause until the file has converged, and do not present the diff\n> until then either.\n\nThe converging pass should be positional renumbering and nothing else. If it\nmoves an instruction, a type, or a constant value, then something other than a\n`loc` name is sensitive to where lines fall in the file. Find out what before\naccepting it.\n\nThe file tests do catch a file left unconverged, since each test re-runs the\nautoupdate in memory and fails with\n`Autoupdate would make changes to the file content` when the result differs. But\nthat arrives at `bazelisk test` time, after you have already read a diff that\nwas describing a file which had moved out from under it.\n\n### Inspect the diff\n\nInspect the diagnostics first, since that is the acceptance criterion:\n\n```bash\n# STDERR-only view, with jj.\njj --no-pager diff --git 'glob:toolchain/*/testdata/**' \\\n  | grep -E '^[-+].*CHECK:STDERR'\n\n# The same, with git.\ngit diff -- 'toolchain/*/testdata/*' \\\n  | grep -E '^[-+].*CHECK:STDERR'\n```\n\nFor a structured view separating test input, STDERR, and STDOUT changes, use the\nhelper from the\n[Summarize testdata changes](../summarize_testdata_changes/SKILL.md) skill:\n\n```bash\njj --no-pager diff --git 'glob:toolchain/*/testdata/**' \\\n  | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\ngit diff -- 'toolchain/*/testdata/*' \\\n  | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n```\n\nThe argument after the tool name is not interchangeable: `glob:...` is a jj\nfileset, `-- ...` is a git pathspec. `--git` and `--no-pager` are jj flags; git\nalready emits this format and skips the pager when piped.\n\n### Run the tests\n\nThen run the tests, which is what catches prefix mismatches and non-autoupdated\nexpectations:\n\n```bash\nbazelisk test //toolchain/...\n```\n\nSee the [Bazel usage](../bazel/SKILL.md) skill.\n\n## Checklist\n\nBefore presenting a testdata diff as finished:\n\n-   [ ] The autoupdater was run until it made no further changes, so no `loc`\n        name describes a stale line numbering.\n-   [ ] The list of accepted STDERR changes was written before autoupdating, and\n        every change either matches it or is reported as an exception.\n-   [ ] Every STDOUT change is either an instance of a named mechanical pattern\n        or has its own explanation.\n-   [ ] Instructions that appeared or disappeared are justified by what the\n        changed function owes its caller, not by the instruction count.\n-   [ ] Files whose prefix no longer matches their behavior have been renamed.\n-   [ ] No test input was changed, and no test was deleted, to make the diff\n        smaller.\n-   [ ] The size of the diff is proportional to the size of the change.\n","frontmatter":{"name":"Review testdata changes","description":"Instructions for judging whether changes to file test output (`// CHECK:STDOUT:` and `// CHECK:STDERR:` lines) are correct, which changes are acceptable churn, and which are regressions in disguise."},"isInternal":false,"tokens":3909,"sizeBytes":16850},{"name":"SKILL.md","path":".agents/skills/summarize_testdata_changes/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/summarize_testdata_changes/SKILL.md","title":"Summarize testdata changes","category":"anthropic-skill","format":"markdown","content":"---\nname: Summarize testdata changes\ndescription:\n    Instructions for summarizing changes to Carbon testdata files\n    (`toolchain/*/testdata`).\n---\n\n# Summarize testdata changes\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill provides instructions for creating a comprehensive report summarizing\nchanges to Carbon testdata files (`toolchain/*/testdata`) and associating them\nwith related code changes.\n\nThis skill is about _reporting_ a diff. For deciding whether the diff is correct\nin the first place, see the\n[Review testdata changes](../review_testdata_changes/SKILL.md) skill.\n\n## Goals\n\nProduce a report that:\n\n1.  Summarizes code changes outside of testdata.\n2.  Groups similar testdata changes together, listing all affected files for\n    each group. **Every change to testdata must be represented by at least one\n    group. This includes changes to CHECK lines.**\n3.  Provides detailed breakdowns of test input changes and diagnostic output\n    changes in the corresponding group. **Every single change to inputs or to\n    STDERR checks must be explicitly mentioned in the group, with either an\n    inline diff or a link to the file.**\n\n## Process\n\n### 1. Identify Changes\n\nUse your VCS (Git or Jujutsu) or query Github to identify changes. For large\nchanges, it is recommended to use the included helper script to extract test\ninput changes.\n\n#### For Git Users:\n\n-   **Summarize code changes**: `git diff --stat -- ':!toolchain/*/testdata/*'`\n    -   To see content of non-testdata changes:\n        `git diff -- ':!toolchain/*/testdata/*'`\n-   **Identify testdata changes**:\n    `git diff --name-only 'toolchain/*/testdata/*'`\n\n#### For Jujutsu (jj) Users:\n\n-   **Summarize code changes**:\n    `jj --no-pager diff --stat '~toolchain/*/testdata'`\n    -   Note: Quoting the fileset `'~toolchain/*/testdata'` is critical if it\n        contains wildcards.\n    -   To see content of non-testdata changes, use `--git` to get standard\n        unified diff format: `jj --no-pager diff --git '~toolchain/*/testdata'`\n-   **Identify testdata changes**:\n    `jj --no-pager diff --name-only 'toolchain/*/testdata'`\n\n#### For Github Pull Requests:\n\n-   **Summarize code changes**: `gh pr diff`\n-   **Identify testdata changes**:\n    `gh pr diff --name-only | grep '^toolchain/.*/testdata'`\n\n#### Handling Specific Revisions:\n\nIf you are summarizing changes in a specific revision (for example, `@-`) or\npull request (for example, #1234), add `-r <rev>` or `<pr_number>` to the\ncommands:\n\n-   `git diff <rev>^ <rev> ...` (or use `git show <rev>`)\n-   `jj --no-pager diff -r <rev> ...`\n-   `gh pr diff <pr_number>`\n\n### 2. Extract Test Input Changes (Recommended)\n\nTo easily identify changes, use the included Python helper script to extract all\ntext additions and removals from the diff, categorized by Input, STDERR, and\nSTDOUT changes. This script reads a unified diff from stdin.\n\n```bash\n# For Git:\ngit diff -- 'toolchain/*/testdata/*' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For Jujutsu (jj):\njj diff --git 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For a specific revision with jj:\njj diff -r @- --git 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For a specific PR with Github:\ngh pr diff 1234 | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n```\n\n### 3. Identify Patterns and Produce a List of Groups\n\n-   Read the diff and produce a list of groups of changes that share a common\n    theme or cause (for example, \"Updated expected output for integer literals\",\n    \"Added tests for new keyword\").\n-   **CRITICAL**: _Every single change_ in the testdata diff must be represented\n    by at least one group. Do not ignore changes to `CHECK` lines.\n    -   If it's not clear what group a change belongs to, create a new group for\n        it.\n-   For each group:\n    -   Provide a brief description of the group.\n    -   (Optional) Briefly note if the group appears to be an intended or\n        unintended consequence of the code changes.\n-   Divide the groups into sections:\n    -   Test Changes: Changes to test inputs (lines not prefixed with\n        `// CHECK`), along with diagnostic output changes where relevant\n    -   Diagnostic Changes: Changes to diagnostic output (lines prefixed with\n        `// CHECK:STDERR`) with no corresponding changes to test inputs\n    -   [Output Type] Changes: Changes to STDOUT (lines prefixed with `//\n        CHECK:STDOUT`)\n        -   Create one section for each relevant kind of test. For example,\n            parser tests should typically be in a \"Parse Tree Changes\" section,\n            check tests should typically be in a \"SemIR Changes\" section, and\n            lower tests should typically be in an \"LLVM IR Changes\" section.\n\n### 4. Improve Grouping\n\n-   Read the list of groups and check to see if any of them should be combined\n    or split apart. If needed, do so.\n\n### 5. Assign Changes to Groups\n\n-   Read the diff again, and then for _each_ change in the diff:\n    -   Add the change to the appropriate group (or, rarely, groups).\n    -   **CRITICAL**: _Every single change_ in the testdata diff must be\n        represented by at least one group. Do not ignore changes to `CHECK`\n        lines.\n    -   If the change affects _test inputs_ (lines not prefixed with `// CHECK`)\n        or _diagnostic output_ (lines prefixed with `// CHECK:STDERR`):\n        -   List the file within the group. Don't just give one or a few\n            examples. Include every file.\n        -   Provide an inline diff if the change is small.\n        -   Provide a link to the file if the change is large.\n    -   Otherwise, if the change only affects _STDOUT_ (lines prefixed with\n        `// CHECK:STDOUT`):\n        -   Ensure the group contains a representative example that matches the\n            current change.\n        -   The representative example should be an inline diff of the change.\n    -   **CRITICAL**: _Every single change_ to test inputs and diagnostic\n        outputs in the files being summarized must be explicitly listed in at\n        least one group. Do not skip changes, even if they are similar to\n        changes you've already seen, and do not just give examples.\n\n### 6. Validation\n\nAs a final validation step:\n\n-   Read through the testdata diff again.\n-   Ensure that every change in the diff is reflected by at least one group in\n    the report.\n\n## Report Template\n\nUse the following template for the generated report:\n\n```markdown\n# `testdata` Change Summary\n\n## Code Changes\n\n[One paragraph summarizing changes outside of testdata.]\n\n## Test Changes\n\n### [Group Name]\n\n[Description of the group.]\n\n[Change 1: diff context OR link]\n\n[Change 2: diff context OR link]\n\n...\n\n## Diagnostic Changes\n\n### [Group Name]\n\n[Description of the group.]\n\n[Change 1: diff context OR link]\n\n[Change 2: diff context OR link]\n\n...\n\n## [Output Type] Changes\n\n### [File Path]\n\n[Description of the group.]\n\n[Example diff context]\n\nChanges of this kind were found in [Number] files. Examples: [List of files]\n\n...\n```\n\nSkip sections that would be empty.\n","frontmatter":{"name":"Summarize testdata changes","description":"Instructions for summarizing changes to Carbon testdata files (`toolchain/*/testdata`)."},"isInternal":false,"tokens":1772,"sizeBytes":7335},{"name":"SKILL.md","path":".agents/skills/toolchain_development/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/toolchain_development/SKILL.md","title":"Toolchain development","category":"anthropic-skill","format":"markdown","content":"---\nname: Toolchain development\ndescription:\n    Instructions for checking, building, debugging, and understanding the Carbon\n    toolchain.\n---\n\n# Toolchain development\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Toolchain structure\n\n-   Under [`toolchain/`](/toolchain/):\n    -   [`base/`](/toolchain/base/): Base infrastructure and common utilities.\n    -   [`check/`](/toolchain/check/): Semantic analysis (SemIR generation).\n    -   [`lex/`](/toolchain/lex/): Lexing (Source -> Tokens).\n    -   [`lower/`](/toolchain/lower/): Lowering to LLVM IR.\n    -   [`parse/`](/toolchain/parse/): Parsing (Token -> Parse Tree).\n    -   [`sem_ir/`](/toolchain/sem_ir/): Semantic Intermediate Representation\n        (SemIR) definitions.\n\n## Toolchain architecture\n\n-   **Documentation**: Refer to [`toolchain/docs`](/toolchain/docs) for detailed\n    architecture design and patterns.\n    -   Refer to [Toolchain Idioms](/toolchain/docs/idioms.md) for a\n        comprehensive list of patterns (for example, `ValueStore`, formatting\n        `.def` files, struct reflection) used throughout the implementation.\n-   **Builtin Functions**: Refer to the **Builtin functions** skill\n    ([SKILL.md](../builtins/SKILL.md)) for guidelines on registering, mapping,\n    constant evaluating, and lowering compiler builtin primitives (e.g.\n    `\"int.convert_float\"`).\n-   **Language server**: Refer to the **Language server** skill\n    ([SKILL.md](../language_server/SKILL.md)) before working on\n    `toolchain/language_server/` or `utils/vscode/`. Neither follows the\n    patterns described here.\n-   **Phases**: Lex -> Parse -> Check -> Lower.\n-   **Definitions**: Many kinds (tokens, parse nodes, SemIR instructions) are\n    defined in `.def` files and expanded by way of macros.\n-   **Handlers**:\n    -   Parser: `Handle<StateName>` in `parse/handle_*.cpp`.\n    -   Checker: `HandleParseNode` in `check/handle_*.cpp`.\n    -   Lowering: `HandleInst` in `lower/handle_*.cpp`.\n-   **Iteration**: Prefer iterative algorithms over recursive ones to prevent\n    stack exhaustion on complex codebases.\n\n### Essential commands\n\n-   **Test everything**: `bazelisk test //...`\n-   **Test specific target**: `bazelisk test //toolchain/testing:file_test`\n-   **Test specific file**: `bazelisk test //toolchain/testing:file_test\n    --test_arg=--file_tests=<path_to_carbon_file>`\n-   **Build toolchain**: `bazelisk build //toolchain/...`\n\n### Updating test data\n\nCarbon tests often use `file_test` (for example,\n`//toolchain/testing/file_test`). For detailed guidelines on authoring tests,\nincluding file splits, naming conventions (`fail_`, `todo_`), and generating\nminimal output with SemIR dumps, please refer to the **Toolchain tests** skill.\n\nIf you change compiler behavior, you likely need to update expected test\noutputs. **Do not manually edit thousands of lines of expected output.** Use the\nscript:\n\n```bash\n./toolchain/autoupdate_testdata.py\n# Or for a specific file:\n./toolchain/autoupdate_testdata.py toolchain/check/testdata/my_test.carbon\n```\n\n## Debugging and diagnostics\n\n-   **Compiler Diagnostics**: Refer to the **Diagnostics** skill\n    ([SKILL.md](../diagnostics/SKILL.md)) for strict rules on declaring,\n    formatting, emitting, testing, and styling compiler diagnostic messages\n    (errors, warnings, notes).\n-   **Printing to stderr**: Use `llvm::errs() << \"debug info\\n\";`.\n    -   Avoid `std::cout` (it may interfere with tool output).\n-   **SemIR Stringification**:\n    -   SemIR objects often have a `Print` method or `operator<<`.\n    -   `inst.Print(llvm::errs())`\n-   **Debugging Crashes**:\n    -   Bazel sandboxing can hide artifacts. Use `--sandbox_debug` if needed,\n        but often running the binary directly from `bazel-bin/` is easier for\n        debugging.\n\n## Error handling\n\n-   **No exceptions**: Do not use C++ exceptions.\n-   **`ErrorOr<T>`**: Return `ErrorOr<T>` for fallible operations.\n    -   Check with `if (auto result = Function(); result) { Use(*result); }`\n-   **`llvm::Expected<T>`**: Similar to `ErrorOr`, used when interfacing with\n    LLVM.\n\n### Context-Aware Diagnostics\n\nWhen declaring and emitting errors, ensure semantic wording matches the exact\ncontext:\n\n-   **Semantic Precision**: Do not reference \"types\" when raising errors for\n    unsized expressions like `IntLiteral` or `FloatLiteral`. For example, use\n    `RealLiteralTooLargeForUnsizedInt` instead of a diagnostic referencing an\n    \"integer type\".\n-   **Wording Consistency**: Before declaring a new diagnostic in\n    [kind.def](../../../toolchain/diagnostics/kind.def), search for existing\n    diagnostics in the targeted implementation files (for example, other uses of\n    `MaxIntWidth`) to align message structures and parameter expectations.\n\n### Casting (LLVM style)\n\n-   Use `llvm::cast<T>(obj)` (checked, asserts on failure).\n-   Use `llvm::dyn_cast<T>(obj)` (returns null on failure).\n-   Use `llvm::isa<T>(obj)` (boolean check).\n-   **Avoid** `dynamic_cast` and standard RTTI.\n\n### Leverage LLVM APIs\n\nBefore implementing custom algorithms for mathematical, logical, or bitwise\noperations, inspect target LLVM ADT class APIs:\n\n-   **Builtin APIs**: Verify if LLVM classes (such as `APInt`, `APFloat`, or\n    `APSInt`) already offer native equivalents (for example, `.pow()`,\n    `ilogb()`, `.changeSign()`, `convertFromAPInt()`). Avoid duplicate, naive,\n    or inefficient custom loops.\n\n### Data structures\n\n-   Prefer APIs in `common/` and `toolchain/base/` over LLVM ADTs. For example,\n    use `Map` instead of `llvm::DenseMap`.\n-   If no Carbon API exists, prefer LLVM ADTs over standard library ones (for\n    example `llvm::SmallVector`, `llvm::StringRef`).\n-   `StringRef` is a view; be careful with lifetimes.\n\n## Common pitfalls\n\n1.  **Legacy `explorer` references**: The `explorer` prototype has been moved.\n    Ignore references to it in proposals or old docs; focus on `toolchain`.\n2.  **Manually updating test files**: Always check if `autoupdate_testdata.py`\n    can do it for you.\n3.  **Using `std::string` unnecessarily**: Prefer `llvm::StringRef` for\n    arguments.\n4.  **Header includes**: Use specific include orders (often enforced by\n    `clang-format`).\n5.  **Parse node order**: Semantics processes parse nodes in post-order; ensure\n    your parser transitions support this.\n6.  **Builtin implementation gaps**: If adding a primitive builtin function,\n    make sure you address all phases of the lifecycle: macro definition\n    registration, signature validation, compile-time constant evaluation\n    (interpreter), LLVM IR lowering, and prelude modular implementation bindings\n    (avoiding orphan rules). Refer to the **Builtin functions** skill\n    ([SKILL.md](../builtins/SKILL.md)) for details.\n7.  **Premature helper abstraction**: Avoid extracting tiny helper functions\n    that are called from exactly one place and do not significantly modularize\n    complex code. Prefer inlining directly to keep the implementation compact,\n    readable, and localized.\n8.  **Redundant bounds calculations**: Avoid repeating calculations of complex\n    boundary estimations (such as lower and upper bound estimations). Refactor\n    the logic to calculate unified values once, preserving compactness.\n9.  **Trusting stale `clangd` diagnostics**: In-editor diagnostics are only as\n    good as `compile_commands.json`. If it predates a newly added file, `clangd`\n    falls back to a default command and reports nonsense, such as missing\n    standard headers or \"no member named `None`\". Regenerate it with\n    `./scripts/create_compdb.py`, which only takes a few seconds.\n","frontmatter":{"name":"Toolchain development","description":"Instructions for checking, building, debugging, and understanding the Carbon toolchain."},"isInternal":false,"tokens":1884,"sizeBytes":7745},{"name":"SKILL.md","path":".agents/skills/toolchain_tests/SKILL.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/.agents/skills/toolchain_tests/SKILL.md","title":"Toolchain tests","category":"anthropic-skill","format":"markdown","content":"---\nname: Toolchain tests\ndescription:\n    Instructions for authoring, structuring, and running toolchain tests using\n    the file_test infrastructure.\n---\n\n# Toolchain tests\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Introduction\n\nThis skill provides guidelines and patterns for creating and updating tests for\nthe Carbon toolchain, especially file tests in `toolchain/*/testdata/` (for\nexample, `toolchain/check/testdata/`).\n\nToolchain tests evaluate Carbon source files through Lexing, Parsing, Checking,\nand optionally Lowering. Output (for example SemIR dumps, Clang errors) is\ncaptured and validated using inline CHECK records.\n\nLanguage server tests also use `file_test`, but with quite different\nconventions (an LSP message stream, `AUTOUPDATE-SPLIT`, `FROM_FILE_SPLIT`).\nRefer to the **Language server** skill\n([SKILL.md](../language_server/SKILL.md)) for those.\n\n## Structure and Authoring\n\n### File Layout and Headers\n\nTest files must start with the standard Carbon license, followed by\nconfiguration comments. Separate sections with blank comment lines (`//`).\n\n```carbon\n// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/...\n//\n// AUTOUPDATE\n```\n\n-   `// AUTOUPDATE` is mandatory for files using CHECK markers.\n-   `// TIP:` lines are automatically generated by the autoupdater. You do not\n    need to hand-write them. It is harmless to add them, but the script will\n    handle it.\n\n### Minimized Preludes\n\nWhen writing tests entirely unrelated to the Core package, specify a minimal\nprelude file using `// INCLUDE-FILE`. Usually, include\n`toolchain/testing/testdata/min_prelude/` scripts, such as `int.carbon` or\n`primitives.carbon`. This significantly speeds up execution and minimizes STDOUT\nnoise.\n\n-   **Builtin Primitive Testing**: Standard operators (such as `+`, `-`, `/`,\n    `<`, etc.) are **not** imported or available inside minimized preludes. To\n    write tests with a minimal prelude footprint, call primitive builtins\n    directly (e.g., `float.negate`, `float.div`) inside your test code to build\n    expressions.\n\n### Split Tests and `[[@TEST_NAME]]`\n\nA single physical file can test multiple scenarios using split constraints:\n\n```carbon\n// --- passing_case.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// ...\n\n// --- fail_bad_case.carbon\nlibrary \"[[@TEST_NAME]]\";\n// ...\n```\n\n-   **Always** use `library \"[[@TEST_NAME]]\";` in each split rather than\n    hardcoding the library name. This prevents name conflicts, avoids redefining\n    the default library, and keeps the test code clean and templateable.\n-   Exactly `[[@TEST_NAME]]` (including the brackets) must be used. The test\n    infrastructure automatically replaces it with the split's filename minus\n    `todo_` and `fail_` prefixes.\n-   **Do not put code that is expected to pass and code that is expected to fail\n    into the same split.** Validation relies on non-failing splits producing\n    absolutely no errors and failing splits producing the correct compiler\n    errors independently.\n\n### File Prefixing: `fail_` and `todo_`\n\nExpected failures must be differentiated from unexpected failures (and from\nbugs). Include prefixes to name individual split files or the main test:\n\n-   `fail_...`: The test should and does produce compiler errors.\n-   `todo_fail_...`: The test should produce errors but currently does not.\n-   `fail_todo_...`: The test does produce errors or crashes, but it shouldn't\n    (or produces the wrong errors or otherwise misbehaves with errors).\n-   `todo_...`: The test has some incorrect behavior, but doesn't produce errors\n    currently, and shouldn't.\n\n**Main File Naming**: The main test file (and any split-files) must have a\n`fail_` prefix if they have an associated error. **Exception**: The main file\nmay omit `fail_` if it contains a least one split that has a `fail_` prefix.\n\nBoth the `fail_` and `todo_` prefixes are stripped from filename properties like\n`[[@TEST_NAME]]`.\n\n### Constant Evaluation Validation\n\nWhen testing constant evaluation in semantic checker tests, follow these\nconventions to ensure diagnostic stability and accuracy:\n\n-   **Literal Spelling Canonicalization**: In Semantic IR, real literals\n    (floating-point constants) with identical mathematical values can be\n    assigned distinct internal representation identifiers based on spelling\n    variations in source code. To completely prevent literal spelling mismatches\n    in expected output checks, validation tests must be performed using\n    canonical comparison methods (for example, passing converted values through\n    an `Expect(X as f64)` function).\n-   **Generic Parameters Validation**: To bypass compile-time constraints where\n    local runtime variables are rejected as generic function arguments, test\n    generic type conversions at runtime, and validate compile-time conversions\n    by passing static literal values directly into primitive builtin calls.\n-   **Exhaustive Edge Case Verification**: For complex mathematical algorithms\n    (such as floating-point to integer truncation and rounding), map and execute\n    test constraints covering every code branch, conditional exit, and fallback\n    evaluation path.\n-   **Rounding Threshold Boundaries**: Test cases that land extremely close to\n    mathematical boundaries (for example, floating-point literals representing a\n    tiny fraction above 1.0, such as $2^{30} \\times 2^{-30}$ or\n    $10^{10} \\times 10^{-10}$, verifying correct exact truncation down to 1 or\n    0).\n-   **Precise Float Literal Spelling**: Spell floating-point literals in test\n    code with exact mathematical precision targeting target thresholds. For\n    example, if testing the smallest fractional increment above 1.0, use the\n    exact hex fractional representation (e.g. `0x1.0000000000001p0`) or a highly\n    precise decimal fractional spelling (e.g. `1.0000000000000001`) instead of\n    coarse fractions like `1.1` to ensure correct boundary assertions.\n-   **Representation Capacity Boundaries**: Explicitly target edge cases near\n    representation limits of target types. Test combinations of mantissas and\n    exponents that yield values exactly on, just below, or just above the\n    capacity limits of fixed-size destination types (e.g. signed/unsigned\n    targets like `i32` or `u32`).\n-   **Zero-Value Sizing Bounds**: Verify boundary inputs of `0` and `0.0`\n    explicitly. Assert that zero inputs are sized and simplified correctly\n    without triggering calculation underflows, division-by-zero errors, or\n    underestimating required bit allocations.\n\n### Test Code Comments\n\n-   **No agent thinking:** Do not include comments describing your reasoning or\n    \"train of thought\" (for example, \"Wait, but...\") inside the test files. Any\n    comments left in tests should be concise and describe what the test _itself_\n    is validating for human readers.\n\n## SemIR Dumps and Minimizing Output\n\nLimit STDOUT checks to the logic under test. Always use `//@dump-sem-ir-begin`\nand `//@dump-sem-ir-end` around the specific declarations/blocks where SemIR\noutput is desired. Only use these markers and **not**\n`--dump-sem-ir-ranges=if-present` or similar extra args—new tests use\n`//@dump-sem-ir...` to naturally filter output to the highlighted segments based\non the default behavior.\n\n```carbon\n//@dump-sem-ir-begin\nfn F(x:? form(ref i32));\n//@dump-sem-ir-end\n```\n\n## Creating/Updating the Output\n\nAI tools should **never** hand-write or manually touch `// CHECK:STDOUT:` or\n`// CHECK:STDERR:` comments.\n\nWrite your Carbon test code, headers, and `// AUTOUPDATE` then run the test\nupdater:\n\n```bash\n./toolchain/autoupdate_testdata.py toolchain/PATH/TO/YOUR/TEST.carbon\n```\n\nReview the updated test outputs (for example, by way of `git diff`). Ensure\nlogic paths are correctly tested rather than producing massive boilerplate\nblocks.\n\nAutoupdating makes the tests pass whether or not the new behavior is correct, so\ndeciding that the new output is the output you wanted is a separate step. See\nthe [Review testdata changes](../review_testdata_changes/SKILL.md) skill.\n","frontmatter":{"name":"Toolchain tests","description":"Instructions for authoring, structuring, and running toolchain tests using the file_test infrastructure."},"isInternal":false,"tokens":1903,"sizeBytes":8381},{"name":"README.md","path":"github_tools/README.md","rawUrl":"https://raw.githubusercontent.com/carbon-language/carbon-lang/HEAD/github_tools/README.md","title":"github_tools Documentation","category":"plugin-manifest","format":"markdown","content":"# GitHub\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nScripts for use with GitHub.\n\nSee individual scripts for more details.\n","isInternal":false,"tokens":60,"sizeBytes":274}],"systemPromptSnippet":"<yakaai_skills repo=\"carbon-language/carbon-lang\">\n<!-- File: AGENTS.md (Tokens: ~252 | Category: root-instruction) -->\n# Gemini & AI Assistant Guide for Carbon\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis document provides high-density technical context for AI assistants\ncontributing to the Carbon Language project.\n\n## General instructions\n\n-   **Communication**: Be concise, professional, and technical. Use GitHub-style\n    markdown.\n-   **Verification**: Always run relevant tests.\n\n## Bazel usage\n\n> [!IMPORTANT] Always use `bazelisk` instead of `bazel` for all commands in the\n> Carbon project. Refer to the\n> [Bazel usage skill](/.agents/skills/bazel/SKILL.md) for detailed instructions.\n\n## Version control\n\n> [!IMPORTANT] Never rewrite the history of a change that has been submitted as\n> a pull request. Reviewers track a PR by its commits, and rewriting them\n> discards their in-progress review. Ask before rewriting history in any case.\n> Refer to the [Jujutsu (jj) usage skill](/.agents/skills/jj/SKILL.md) for\n> details.\n\n<!-- File: .agents/skills/agent_tools/SKILL.md (Tokens: ~388 | Category: anthropic-skill) -->\n---\nname: Agent tools\ndescription:\n    Guidelines and restrictions on shell commands and file manipulation tools\n    for AI assistants.\n---\n\n# Agent tools\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nAI assistants working on the Carbon repository **MUST NOT** use legacy or\ngeneric UNIX shell search/edit commands when specialized environment tools\nexist.\n\n## Command line tools restrictions\n\n-   **DO NOT USE**: `cat`, `less`, `grep`, `sed`, or other shell utilities for\n    viewing, searching, or modifying files.\n-   **DO NOT USE**: `patch` to write and apply patch files.\n-   **DO NOT USE**: Writing custom scripts in other languages to circumvent this\n    limitation.\n-   **DO USE**: High-fidelity semantic API tools:\n    -   **Viewing**: Use `view_file` instead of `cat` / `less`.\n    -   **Searching**: Use `grep_search` / `find_by_name` instead of `grep` /\n        `find`.\n    -   **Modifying**: Use `replace_file_content`, `multi_replace_file_content`,\n        or `write_to_file` instead of `sed` / `patch` / `python` edits.\n\nYou may only write and run temporary programs to modify source code if no\nsemantic tool is applicable or when performing complex, systematic transforms\nacross many codebase directories simultaneously.\n\n## Temporary files management\n\nTemporary files and scratchpad test scripts created by the assistant during\nanalysis, experiments, or debugging:\n\n-   **MUST** reside within the `tmp/` subdirectory under the workspace root.\n-   **MUST** be periodically cleaned out and deleted before ending your turn to\n    preserve a clean git workspace.\n\n<!-- File: .agents/skills/bazel/SKILL.md (Tokens: ~720 | Category: anthropic-skill) -->\n---\nname: Bazel usage\ndescription:\n    Instructions that **MUST** be followed when using Bazel or Bazelisk to\n    build, test, and debug in the Carbon repository.\n---\n\n# Bazel usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill documents how best to use Bazel when building, testing, or\nmanipulating the Carbon repository's Bazel in any way.\n\n## Bazel wrappers\n\nCarbon uses Bazel for its build system. To ensure consistent versions, the\nproject uses Bazelisk.\n\n> [!IMPORTANT] Always use `bazelisk` whenever you want to run Bazel. Never run\n> `bazel` directly in the Carbon project. Anything you want to do with `bazel`\n> can be done with the `bazelisk` command instead.\n\n-   **Bazelisk**: Try to use `bazelisk` in your existing `$PATH` if available.\n    -   **`run_bazelisk.py`**: If `bazelisk` isn't available, use\n        `./scripts/run_bazelisk.py` to run bazelisk without it being installed.\n\n## Essential commands\n\n### Building\n\n-   **Build all**: `bazelisk build //...`\n-   **Build toolchain**: `bazelisk build //toolchain/...`\n-   **Build specific target**: `bazelisk build //toolchain:carbon`\n\n### Testing\n\n-   **Test all**: `bazelisk test //...:all`\n-   **Test toolchain**: `bazelisk test //toolchain/...`\n-   **Test examples**: `bazelisk test //examples/...`\n\n> [!TIP] Running all of the tests can be slow, so try to narrowly test the\n> immediately relevant parts of the project first, and only expand coverage as\n> necessary to be confident in the changes.\n\n> [!TIP] For specialized instructions on testing and developing the Carbon\n> toolchain, consult these skills:\n>\n> -   [Toolchain tests](/.agents/skills/toolchain_tests/SKILL.md): For\n>     authoring, structuring, and running `file_test` tests.\n> -   [Toolchain development](/.agents/skills/toolchain_development/SKILL.md):\n>     For architecture, essential commands, and debugging the toolchain.\n\n### Running binaries built by Bazel\n\n> [!IMPORTANT] Always manually run binaries built by Bazel using the\n> `bazelisk run` command. Never run the binary directly from `bazel-bin/`.\n\nYou can run the Carbon driver or command line directly via Bazel:\n\n-   `bazelisk run //toolchain -- compile --phase=parse\n    toolchain/parse/testdata/basics/empty.carbon`\n\n## Advanced configurations\n\n### AddressSanitizer (ASan)\n\nTo enable ASan for local testing:\n\n-   Pass `--config=asan`: `bazelisk test --config=asan //...`\n\n## Common pitfalls and troubleshooting\n\n### `bazel clean`\n\nChanges to packages installed on your system (like changing LLVM versions or\ninstalling `libc++`) may not be noticed by Bazel.\n\n-   Run `bazelisk clean` to force cached state to be rebuilt when environment\n    changes occur.\n\n<!-- File: .agents/skills/builtins/SKILL.md (Tokens: ~2628 | Category: anthropic-skill) -->\n---\nname: Builtin functions\ndescription:\n    Instructions for registering, mapping, constant evaluating, and lowering\n    builtin functions in the Carbon toolchain.\n---\n\n# Builtin Functions in the Carbon Toolchain\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nBuiltin functions are compiler-recognized primitives mapping directly from\nCarbon code expressions (via standard prelude bindings) to optimized backend\nexecution. This document defines the complete structural workflow, C++ patterns,\nconstant evaluation logic, machine lowering mechanics, library bindings, and\nvalidation strategies required to implement builtin functions in the Carbon\ncompiler.\n\n---\n\n## Technical Flow & Lifecycle\n\n```mermaid\ngraph TD\n  Src[Carbon Source Code] -->|Prelude Map| Sem[Semantic Analysis / SemIR]\n  Sem -->|Signature Constraint| Sig[builtin_function_kind.cpp]\n  Sem -->|Phase Evaluation| Eval[eval.cpp Constant Interpreter]\n  Sem -->|Machine Codegen| Lower[handle_call.cpp LLVM Lowering]\n  Eval -->|Diagnostics| Diag[diagnostics/kind.def]\n  Lower -->|Native Instructions| LLVM[LLVM IR Generation]\n```\n\nAdding a builtin function involves a 5-step integration:\n\n1.  **Define the Builtin Kind**: Register the enum in\n    [builtin_function_kind.def](../../../toolchain/sem_ir/builtin_function_kind.def).\n2.  **Signature & Compile-Time Registry**: Declare the mapping name, parameter\n    constraints, and compile-time evaluation residency in\n    [builtin_function_kind.cpp](../../../toolchain/sem_ir/builtin_function_kind.cpp).\n3.  **Compile-Time Interpreter Support**: Wire constant evaluation hooks and\n    bounds/exception diagnostics in\n    [eval.cpp](../../../toolchain/check/eval.cpp).\n4.  **LLVM IR Lowering Support**: Connect target machine generation in\n    [handle_call.cpp](../../../toolchain/lower/handle_call.cpp).\n5.  **Prelude Library Mapping**: Bind primitive interfaces to named builtins\n    under [core/prelude/](../../../core/prelude/).\n\n---\n\n## Detailed Step-by-Step Implementation Guide\n\n### Step 1: Kind Definition & Registration\n\nRegister your builtin function name using the X-macro in\n[builtin_function_kind.def](../../../toolchain/sem_ir/builtin_function_kind.def):\n\n```cpp\n// toolchain/sem_ir/builtin_function_kind.def\n\n// Converts an integer type to a floating-point type.\nCARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntConvertFloat)\n```\n\n### Step 2: Signature Validation & Compile-Time Residence\n\nInside\n[builtin_function_kind.cpp](../../../toolchain/sem_ir/builtin_function_kind.cpp):\n\n1.  **Define Parameter Constraints**: If the parameter requires novel\n    constraints (e.g. \"must be a float type\"), define a template constraint\n    struct checking the matching `SemIR` type instruction (such as `FloatType`\n    or `FloatLiteralType`). Use pre-established semantic helpers:\n\n    -   `TypeParam<I, T>`: Ensures different parameters resolve to identical\n        type structures (e.g., generic constraint matching).\n    -   `AnyInt`, `AnyFloat`, `AnySizedInt`, `AnySizedFloat`, `CharCompatible`,\n        `StdInitializerList`, `NoReturn`.\n\n2.  **Map Literal Name & Register Constraint Signature**: Declare a\n    `BuiltinInfo` constant inside `namespace BuiltinFunctionInfo` matching the\n    macro-defined name:\n\n    ```cpp\n    // toolchain/sem_ir/builtin_function_kind.cpp\n\n    constexpr BuiltinInfo IntConvertFloat = {\n        \"int.convert_float\", ValidateSignature<auto(AnyInt)->AnyFloat>};\n    ```\n\n3.  **Establish Compile-Time Residency Status**: Update\n    `BuiltinFunctionKind::IsCompTimeOnly` to determine if a call requires\n    compile-time evaluation:\n    -   **Checked/Diagnostics Primitives**: Return `true` immediately. Runtime\n        lowering of these is illegal (e.g. `IntConvertFloatChecked`).\n    -   **Runtime Primitives**: Return\n        `AnyLiteralTypes(sem_ir, arg_ids, return_type_id)` to enforce that\n        expressions involving unsized literal values (like `IntLiteral` or\n        `FloatLiteral`) are evaluated exclusively at compile-time (as they lack\n        runtime representation).\n\n---\n\n### Step 3: Constant Evaluation Support\n\nWire the interpreter inside [eval.cpp](../../../toolchain/check/eval.cpp) to\nexecute compile-time computations:\n\n1.  **Implement Constant Evaluation Logic**:\n\n    -   Handle the builtin case inside `MakeConstantForBuiltinCall` (which\n        processes the compile-time execution of the call).\n    -   Confirm type validation phase is `Phase::Concrete` to reject incomplete\n        bindings:\n\n        ```cpp\n        case SemIR::BuiltinFunctionKind::IntConvertFloat: {\n          if (phase != Phase::Concrete) {\n            return MakeConstantResult(context, call, phase);\n          }\n          return PerformIntToFloatConvert(context, loc_id, arg_ids[0], call.type_id,\n                                          /*require_exact=*/false);\n        }\n        ```\n\n    -   Extract inputs safely from local value stores (e.g.\n        `context.ints().Get(arg.int_id)` or\n        `context.floats().Get(arg.float_id)`).\n    -   Leverage high-precision LLVM mathematical structures (`llvm::APInt`,\n        `llvm::APFloat`, `llvm::APSInt`) to handle custom bits and signedness\n        safely.\n\n2.  **Diagnose Invalid Parameters or Exceptions**:\n\n    -   Define compile-time diagnostics inside\n        [kind.def](../../../toolchain/diagnostics/kind.def):\n\n        ```cpp\n        // toolchain/diagnostics/kind.def\n        CARBON_DIAGNOSTIC_KIND(IntTooLargeForFloatType)\n        ```\n\n    -   Emplace localized diagnostic formatting messages where they are caught\n        in `eval.cpp`:\n\n        ```cpp\n        CARBON_DIAGNOSTIC(IntTooLargeForFloatType, Error,\n                          \"integer value {0} too large for floating-point type {1}\",\n                          llvm::APSInt, SemIR::TypeId);\n        context.emitter().Emit(loc_id, IntTooLargeForFloatType, val, dest_type_id);\n        ```\n\n    -   Return `SemIR::ErrorInst::ConstantId` to gracefully abort invalid\n        constant generation rather than crashing the compiler.\n\n3.  **Fast-Path Range Limits**:\n    -   Before evaluating expensive math operations on giant exponents (e.g.\n        `1.0e1000000`), executing range limits check against `dest_width + 64`\n        (sized) or `IntStore::MaxIntWidth` (unsized) is mandatory to prevent\n        out-of-bounds calculations and compile-time memory exhaustion.\n\n---\n\n### Step 4: Machine Code Generation (LLVM Lowering)\n\nInside [handle_call.cpp](../../../toolchain/lower/handle_call.cpp):\n\n1.  **Map to Native LLVM Instructions**: For runtime-eligible builtins, map the\n    call inside `HandleBuiltinCall` to native LLVM IR builder methods:\n\n    ```cpp\n    case SemIR::BuiltinFunctionKind::IntConvertFloat: {\n      auto* operand = context.GetValue(arg_ids[0]);\n      auto* dest_type = context.GetTypeOfInst(inst_id);\n      bool is_signed = IsSignedInt(context, arg_ids[0]);\n      context.SetLocal(\n          inst_id, is_signed\n                       ? context.builder().CreateSIToFP(operand, dest_type)\n                       : context.builder().CreateUIToFP(operand, dest_type));\n      return;\n    }\n    ```\n\n2.  **Assert on Compile-Time-Only Builtins**: Throw a hard assertion on\n    lowering-cases for checked validator builtins that should never hit code\n    generation:\n\n    ```cpp\n    case SemIR::BuiltinFunctionKind::IntConvertFloatChecked: {\n      CARBON_CHECK(builtin_kind.IsCompTimeOnly(\n          context.sem_ir(), arg_ids,\n          context.sem_ir().insts().Get(inst_id).type_id()));\n      CARBON_FATAL(\"Missing constant value for call to comptime-only function\");\n    }\n    ```\n\n---\n\n### Step 5: Standard Library Prelude Integration\n\nMap the standard library primitive interfaces to your newly minted named\nbuiltins under [core/prelude/](../../../core/prelude/):\n\n-   **Primitive Mappings**: Bind Carbon methods directly to string-literal\n    builtin equivalents:\n\n    ```carbon\n    fn Convert[self: Self]() -> Float(To) = \"int.convert_float\";\n    ```\n\n-   **Strict Orphan Rule Compliance**: Carbon's orphan rules prohibit\n    implementing interfaces where neither the type nor the interface is locally\n    defined in the backing source module.\n    -   **Literal Conversions**: Literal types (like `FloatLiteral`,\n        `IntLiteral`) do not have backing Carbon source files. Therefore, an\n        `impl` of `UnsafeAs` (which is defined in `as.carbon`) between two\n        literal types must reside inside `as.carbon` itself.\n    -   **Sized Conversions**: Implementations targeting sized primitives (e.g.\n        `Int(N)`, `Float(N)`) must reside in their respective type source files\n        (such as [int.carbon](../../../core/prelude/types/int.carbon) or\n        [float.carbon](../../../core/prelude/types/float.carbon)) where the\n        backing target type resides to prevent duplicate symbols and structural\n        recursion loops.\n\n---\n\n## High-Fidelity Validation & Test Authoring\n\nFollow the [Toolchain tests](../toolchain_tests/SKILL.md) skill with specialized\npatterns for builtins:\n\n### 1. Checker Builtin File Splits\n\nCreate validation splits under\n[toolchain/check/testdata/builtins/](../../../toolchain/check/testdata/builtins/):\n\n-   **Test Naming Convention**: All tests under\n    [toolchain/check/testdata/builtins/](../../../toolchain/check/testdata/builtins/)\n    must be named after the builtin they are testing, replacing `.` characters\n    in the builtin name with `/` (directories). For example, a test for the\n    builtin `\"char_literal.convert\"` must be located at\n    `toolchain/check/testdata/builtins/char_literal/convert.carbon`.\n-   **Minimal Prelude & Direct Call Isolation**: Builtin tests must **not** test\n    the prelude library or operators. They must use the minimal primitive\n    prelude (`// INCLUDE-FILE:\n    toolchain/testing/testdata/min_prelude/primitives.carbon`) or a smaller\n    prelude, and explicitly declare and call the builtin functions under test\n    directly (e.g., `fn Add(a: f64, b: f64) -> f64 = \"float.add\";`). This\n    isolates the testing of compiler builtins from the library prelude.\n-   **Min-Prelude Limitations**: Standard operators (like `+`, `-`, `/`, `<`,\n    etc.) are **not** available in minimized preludes because the core operators\n    library isn't imported. To write tests with a minimal footprint, call\n    primitive builtins directly (e.g. `float.negate`, `float.div`) inside your\n    test code to build expressions.\n-   **Canonicalized Float Comparison**: In SemIR, real literal representations\n    with identical mathematical values can result in mismatched `RealId` objects\n    based on spelling variations. Verify compile-time constant conversions using\n    canonicalized comparison functions (e.g. passing converted results through\n    `Expect(X as f64)`) to completely avoid spelling mismatches in expected\n    outputs.\n-   **Locals Bypass**: If validating generic implicit conversions, compile-time\n    arguments cannot take local runtime variable parameters. Validate\n    compile-time conversions by passing literal constants directly, and sized\n    variable implicit conversions at runtime.\n\n### 2. Machine Codegen Lowering Splits\n\nCreate testing splits under\n[toolchain/lower/testdata/builtins/](../../../toolchain/lower/testdata/builtins/):\n\n-   Emplace a simple carbon binding to the tested builtin.\n-   Confirm matching LLVM metadata target definitions are mapped precisely\n    (e.g., matching `sitofp i32 %a to float`, `fptosi float %a to i32`).\n\n<!-- File: .agents/skills/code_style/SKILL.md (Tokens: ~1437 | Category: anthropic-skill) -->\n---\nname: Code style\ndescription:\n    Instructions for code formatting and style guidelines in the Carbon\n    toolchain.\n---\n\n# Code style\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## License\n\n-   **Licenses**: All Carbon files outside of `third_party/` should have a\n    license following\n    [CONTRIBUTING license instructions](/CONTRIBUTING.md#license).\n\n## Formatting\n\n-   **Bazel**: Use `pre-commit run buildifier --files <file.bzl>` to format\n    Bazel files.\n-   **C++**: Use `pre-commit run clang-format --files <file.cpp>` to format C++\n    files.\n-   **Carbon**: The toolchain's `format` command doesn't work well right now.\n    Instead, try to format Carbon code based on other Carbon files and the C++\n    style.\n-   **Markdown**: Use `pre-commit run prettier --files <file.md>` to format\n    markdown files.\n-   **Python**: Use `pre-commit run black --files <file.py>` to format Python\n    files.\n\n## Comments\n\n-   **Describe the code that is there.** A comment should explain what the\n    current code does or why it is the way it is, not narrate what the code used\n    to be. Do not add a comment to justify a deletion or explain that something\n    is no longer necessary; a reader of the new code has no idea what is being\n    contrasted against, and the comment rots as soon as the old shape is\n    forgotten. Put that reasoning in the commit message instead.\n-   **Do not introduce a local variable just to host a comment.** If a call\n    argument reads clearly on its own, inline it rather than naming it so that a\n    comment has somewhere to attach.\n-   **Lead with a plain summary.** Start a doc comment with a direct statement\n    of what the function does or returns, such as \"Returns true if the InstKind\n    is a singleton.\" Put nuance in a following sentence rather than qualifying\n    the summary into something harder to read.\n-   **Re-read a comment before updating it.** When a symbol is renamed or\n    changes meaning, a comment that mentions it is not automatically stale. Work\n    out what the comment actually asserts first: it may be describing what the\n    code _uses_, which is still true, and rewriting it loses information.\n\n## Documentation\n\nThis covers standalone prose: `/docs`, `README.md` files, and the skill files\nunder `.agents/skills`.\n\n-   **Be true of the tree it lands in.** Documentation shipping in the same\n    commit as the code it describes should name that code freely. Documentation\n    that lands separately must not: a reader who greps for an identifier from an\n    unlanded change finds nothing, and a claim that only holds after that change\n    is false until it lands. This is easy to get wrong when writing up a lesson\n    while the change that taught it is still in flight.\n-   **Use placeholders for illustrations.** When an example only needs to show a\n    shape, name it `Foo` rather than reaching for a real symbol. Save real\n    identifiers for documenting that identifier, where going stale is at least\n    detectable.\n-   **Make each point stand alone.** A reader has none of the discussion that\n    produced it. State the rule, and enough of the reason to apply it, without\n    assuming knowledge of the change that motivated it.\n\n## Naming\n\n-   **A name is a claim, so keep it true.** When a change invalidates the\n    invariant a name describes, rename it in the same change. A factory called\n    `MakeSingletonFooId` has to be renamed once `Foo` is no longer a singleton,\n    even though nothing forces you to.\n-   **Types in a signature are part of the claim.** A function returning the id\n    of a namespace should return `InstId`, not `TypeInstId`, because a namespace\n    is not a type. Do not let a convenient wider or narrower id type imply\n    something false.\n-   **Delete a predicate whose name stops distinguishing anything.** If a change\n    widens a test so that it no longer says what its name implies, remove it and\n    let callers use the underlying test, rather than keeping a wrapper that\n    sounds meaningful. What callers actually want is often the inverse, and is\n    worth adding under its own name.\n-   **Name a variable for its role, not its representation.** If the role a\n    value plays is unchanged, keep its name even when a change means it is now\n    held or spelled differently.\n\n## Commit descriptions\n\n-   **Say what the change is, not how you made it.** Describe the resulting\n    code. Only describe process when the process is more interesting than the\n    change, as with a large mechanical transformation.\n-   **Do not narrate your own work.** Statements like \"each such site was\n    audited\" or \"we investigated every caller\" describe effort, not the change.\n-   **Omit routine mechanical steps.** Do not mention running the testdata\n    autoupdater or the formatter. Every change is expected to include those.\n-   **Do not enumerate each edit.** Describe the change as a whole rather than\n    listing every function or file touched; the diff already lists them.\n-   **Use the project's terms precisely.** Reach for the term of art the\n    codebase uses. Calling something a \"type alias\" or a \"namespace\" when it is\n    a named scope misleads, and is worse than a vaguer but accurate word.\n-   **Scope claims to what changed.** Say the specific thing that is now true,\n    rather than a broader statement that happens to contain it.\n\n## Design\n\n-   **Do not distort the data model to improve output.** If printed or golden\n    output is undesirable, change the printer, not the data structures that\n    feed it.\n\n## Style Guides\n\n-   **C++ style**: Follow the\n    [Carbon C++ Project Style Guide](/docs/project/cpp_style_guide.md).\n-   **Markdown style**: Follow the\n    [Google developer documentation style guide](https://developers.google.com/style).\n-   **Python style**: Follow the [PEP 8](https://peps.python.org/pep-0008/)\n    style guide.\n    -   Wrap code and comments to 80 columns.\n    -   Run `pre-commit run flake8 --files <file.py>` to check Python style.\n\n<!-- File: .agents/skills/diagnostics/SKILL.md (Tokens: ~3242 | Category: anthropic-skill) -->\n---\nname: Diagnostics\ndescription:\n    Instructions for declaring, formatting, emitting, testing, and styling\n    diagnostic messages (errors, warnings, and the labels that explain them) in\n    the Carbon toolchain.\n---\n\n# Diagnostics in the Carbon Toolchain\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThe Carbon compiler features a highly-engineered, context-aware diagnostics\nframework designed to deliver precise, readable, and highly targetable\ndiagnostic output (errors, warnings, and the labels that explain them). This\ndocument establishes strict rules for declaring, formatting, emitting, testing,\nand styling compiler diagnostics.\n\n---\n\n## Architecture Overview\n\n```mermaid\ngraph TD\n  Kind[kind.def Registry] -->|Registration| Enum[Kind Enum ID]\n  Enum -->|Build/Emit| Emitter[Emitter LocT]\n  Emitter -->|ConvertLoc| Loc[Converted Physical Loc]\n  Emitter -->|formatv serialization| Formatting[format_providers.h / Custom Types]\n  Emitter -->|Emit Messages| Consumer[Console / Sorting Consumer]\n  Consumer -->|stable sort| StdErr[Compiler Standard Error]\n```\n\nDiagnostics are handled via three decoupled core components:\n\n1.  **Registry**: Globally enumerated kinds inside\n    [kind.def](../../../toolchain/diagnostics/kind.def).\n2.  **Emitters**: Specialized formatting pipelines (parameterized on custom\n    phase location types `LocT` like `Token` or `LocId`) that convert raw tokens\n    to standardized physical source locations (file, line, column, and the text\n    of the line).\n3.  **Consumers**: Pipelines that process, track, filter, and sort diagnostics.\n    The default `SortingConsumer` buffers and stable-sorts diagnostics based on\n    their `last_byte_offset` matching compiler traversal order to ensure perfect\n    causal ordering.\n\n---\n\n## 1. Declaring and Registering Diagnostics\n\nAll diagnostic types must pass structural uniqueness and coverage verifications.\n\n### The Diagnostic Registry\n\nEvery diagnostic kind must be registered globally as an enum option under\n[kind.def](../../../toolchain/diagnostics/kind.def):\n\n```cpp\n// toolchain/diagnostics/kind.def\nCARBON_DIAGNOSTIC_KIND(RealLiteralTooLargeForUnsizedInt)\n```\n\n### The Uniqueness Rule\n\nTo ensure optimal compile-time and analysis integrity, every diagnostic kind\ndeclared in `kind.def` **MUST** be mapped to **one and only one** C++ macro\ndeclaration (`CARBON_DIAGNOSTIC` or `CARBON_DIAGNOSTIC_ON_SCOPE`).\n\n-   **DO NOT** duplicate diagnostic definitions across different locations.\n-   The C++ representation of the diagnostic is a static/global constant of type\n    `DiagnosticBase<Args...>`.\n-   **Local Scope (Recommended)**: If the diagnostic is unique to a single\n    block/function body, declare it **locally** inside the function body\n    adjacent to its `Emit` trigger:\n\n    ```cpp\n    void ConvertFloatValueToInt(...) {\n      CARBON_DIAGNOSTIC(FloatNaNConvertedToInt, Error,\n                        \"cannot convert NaN to integer type {0}\", SemIR::TypeId);\n      context.emitter().Emit(loc_id, FloatNaNConvertedToInt, dest_type_id);\n    }\n    ```\n\n-   **File Scope**: If the diagnostic is shared among multiple functions inside\n    the _same_ file, declare it at **file scope** inside the anonymous namespace\n    of the `.cpp` file.\n-   **Global Scope**: If a diagnostic (such as a shared helper label) is reused\n    _across different physical files_, define it in a shared header (e.g.\n    context/check helpers) and mark it `extern` where applicable, ensuring the\n    macro is only invoked once.\n\n---\n\n## 2. Formatting Diagnostic Arguments\n\nCarbon diagnostics leverage LLVM's `formatv` engine. Parameters must be passed\nusing strongly-typed arguments to preserve translation capability.\n\n### String Lifetimes & Pitfalls\n\n-   **`llvm::StringRef` is DISALLOWED**: Do not pass `StringRef` as a parameter\n    type to `CARBON_DIAGNOSTIC` due to unsafe lifetime and buffer-allocation\n    boundaries.\n-   **`llvm::StringLiteral` is DISALLOWED**: Do not use literal types as\n    arguments as they prevent future diagnostic localization and translations.\n-   **Use `std::string`**: If string formatting or custom allocations are\n    required, declare the parameter storage type as `std::string`.\n\n### Format Selectors (`format_providers.h`)\n\nUse specialized formatting wrappers under\n[format_providers.h](../../../toolchain/diagnostics/format_providers.h) to\nexpress clean inline options in format strings:\n\n| Wrapper                    | Target Format Style             | Example Usage                  | Output                                                              |\n| :------------------------- | :------------------------------ | :----------------------------- | :------------------------------------------------------------------ |\n| **`BoolAsSelect`**         | `{Index:true\\|false}`           | `\"{0:is signed\\|is unsigned}\"` | Maps bool to selection string.                                      |\n| **`IntAsSelect`**          | `{Index:=Val:String\\|:Default}` | `\"{0:=1:is\\|:are}\"`            | Matches exact options.                                              |\n| **`IntAsSelect` (Plural)** | `{Index:s}`                     | `\"{0} argument{0:s}\"`          | Prints `\"s\"` if value != 1 (e.g., `\"1 argument\"`, `\"3 arguments\"`). |\n\n### Custom Toolchain Type Mappings\n\nCustom structures can define how they serialize inside diagnostics using the\n`DiagnosticType` tag mapping to `Diagnostics::TypeInfo<StorageType>`:\n\n-   **Identifiers & Names** (declared in `check/diagnostic_helpers.h`):\n    -   `NameId`: Formats raw identifier spelling, safely escaping keyword\n        conflicts under backticks automatically.\n    -   `LibraryNameId`: Formats custom library descriptors cleanly (e.g.\n        `default library` or `library \"foo\"`).\n-   **Sized Primitives**:\n    -   `TypedInt`: Formats an `APInt` constant exactly, extracting target\n        signedness representation automatically from its bound type\n        representation.\n-   **Type Formatter Hierarchy**: When choosing parameter types to print\n    compiler type representations, follow this priority list:\n    1.  **`TypeOfInstId` (Preferred)**: Resolves the backing type of an\n        `InstId`, preserving programmatic aliasing, constraints, and source\n        spelling context. Enclosed under backticks automatically.\n    2.  **`InstIdAsType`**: Converts an `InstId` for a type expression, printing\n        custom type layouts under backticks.\n    3.  **`TypeId` (Fallback)**: Canonical description of the type. **Avoid when\n        possible** because type canonicalization loses intermediate source\n        program spelling and aliasing metadata.\n    4.  **`*AsRawType` (e.g. `InstIdAsRawType`, `TypeIdAsRawType`)**: Formats\n        the type layout exactly like their counter-structures above, but\n        **omits** enclosing backticks (useful when inserting types inside larger\n        code snippets).\n\n---\n\n## 3. Fluent Emission Builders & RAII Scopes\n\n### Fluent Builder Pattern\n\nA diagnostic is one message plus the labels that mark the source explaining it.\nUse `Build` to state the message and `Attach` to mark each place the reader has\nto look, chained fluently:\n\n```cpp\nCARBON_DIAGNOSTIC_LABEL(ModifierPrevious, Info, \"`{0}` previously appeared here\",\n                        Lex::TokenKind);\n\ncontext.emitter()\n    .Build(second_node, ModifierRepeated, context.token_kind(second_node))\n    .Attach(first_node, ModifierPrevious, context.token_kind(first_node))\n    .Emit();\n```\n\nLabels are declared with `CARBON_DIAGNOSTIC_LABEL` where they are attached, and\nare not registered in `kind.def`; `check_diagnostics.py` checks that each one is\nattached and covered. A label is either `Primary` -- the range the message\nitself is about -- or `Info`, for somewhere else the reader must look; those two\nare the only categories, because anything not read against the code it names is\nnot a label. `Attach(loc)` with no label marks a range wordlessly, which is what\nto use when a label would only restate the message.\n\nEvery diagnostic should attach at least one label; a message with nothing\nattached has nothing to show. See\n[diagnostics.md](../../../toolchain/docs/diagnostics.md) for which range to pick\nand when a label earns words.\n\n> [!SAFETY] Emitter builders are marked `[[nodiscard]]`. To prevent a developer\n> from creating a builder but failing to terminal-chain `.Emit()`, the builder\n> uses an rvalue overload `Emit() &&` that triggers a compile-time\n> `static_assert(false)`. You must save the builder to an lvalue or execute the\n> chain exactly as `emitter.Build(...).Attach(...).Emit()`.\n\n### RAII Context & Annotation Scopes\n\nManage large checking structures requiring blanket context using RAII block\nscopes:\n\n-   `ContextScope`: Attaches a context to every diagnostic emitted within its\n    scope, describing the higher-level operation that failed because of it. A\n    context is declared with `CARBON_DIAGNOSTIC_CONTEXT`, or\n    `CARBON_DIAGNOSTIC_SOFT_CONTEXT` for one dropped when the diagnostic\n    already has a context:\n\n    ```cpp\n    Diagnostics::ContextScope diagnostic_context(\n        &context.emitter(), [&](auto& builder) {\n          CARBON_DIAGNOSTIC_CONTEXT(\n              QualifiedDeclInIncompleteClassScope,\n              \"cannot declare a member of incomplete class {0}\", SemIR::TypeId);\n          builder.Attach(loc_id, QualifiedDeclInIncompleteClassScope,\n                         context.classes().Get(class_id).self_type_id);\n        });\n    ```\n\n    A context is not a label: its text stands alone as a sentence, which is why\n    it leads the diagnostic rather than following it.\n\n-   `AnnotationScope`: RAII block scope that attaches labels to every diagnostic\n    emitted within it, using the same `Builder` as a direct emission.\n\n---\n\n## 4. Diagnostics Wording Style Guide\n\nRefer to the official\n[Diagnostic message style guide](../../../toolchain/docs/diagnostics.md#diagnostic-message-style-guide)\nfor complete details.\n\nTo maintain message consistency and integrate cleanly with Clang diagnostics in\ninteroperable code, adhere strictly to these rules:\n\n-   **Start with lowercase and omit periods**: Start diagnostic messages with a\n    lowercase letter or quoted code, and do **not** end them with a period\n    (e.g., `\"cannot convert...\"` or ``\"`self` declared...\"``).\n-   **Use backticks for quoted code**: Enclose identifiers, code constructs, and\n    types inside standard backticks (e.g., ``\"`{0}` is bad\"``).\n-   **Phrase as bullet points without articles**: Phrase diagnostics as\n    descriptive bullet points or sentence fragments rather than full sentences.\n    Leave out standard articles (`a`, `an`, `the`) unless necessary for logical\n    clarity. Semicolons can be used to separate fragments within a message.\n-   **Describe the situation and language rule**: Diagnostics should describe\n    the exact situation the toolchain observed. The language rule violated can\n    be mentioned if it wouldn't otherwise be clear:\n    -   _Situation-only_: `\"redeclaration of X\"` (implies that redeclaration is\n        not permitted).\n    -   _Rule-inclusion_: ``\"`self` declared in invalid context; can only be\n        declared in implicit parameter list\"``.\n-   **Wording Choice (\"cannot\" vs \"allowed\")**: Explicitly avoid `\"allowed\"`,\n    `\"legal\"`, `\"permitted\"`, `\"valid\"`, and related passive wording. You may\n    use `\"cannot\"` if needed, but try to use phrasing that does not require it:\n    -   _Correct_: ``\"`export` in `impl` file\"`` (Avoids `\"allowed\"`)\n    -   _Incorrect_: ``\"`export` is only allowed in API files\"``\n    -   _Correct_: ``\"`extern library` specifies current library\"`` (Avoids\n        `\"cannot\"`)\n    -   _Incorrect_: ``\"`extern library` cannot specify the current library\"``\n-   **Developer Intent Hints**: It is acceptable for a diagnostic to guess at\n    the developer's intent and provide a hint _after_ explaining the situation\n    and the rule, but never as a substitute for that:\n    -   _Correct_: ``\"cannot implicitly convert `i32` to `String`; add `as\n        String` for explicit conversion\"``\n    -   _Incorrect_: ``\"add `as String` to convert `i32` to `String`\"`` (Lacks\n        the core violation message).\n-   **Structure for Tooling API**: Try to structure diagnostics such that\n    parameter inputs can be programmatically extracted without string parsing\n    (prefer strongly-typed parameters over format placeholders where possible).\n\n---\n\n## 5. Diagnostics Testing & Coverage Verification\n\nCarbon strictly enforces testing coverage at build-time.\n\n1.  **Tag Verification Requirement**: Every diagnostic kind declared in\n    `kind.def` (which is not blacklisted in the `UntestedKinds` array under\n    [coverage_test.cpp](../../../toolchain/diagnostics/coverage_test.cpp))\n    **MUST** be verified by at least one testcase file inside\n    `toolchain/*/testdata/`.\n2.  **Stderr Checklist Matchers**: The testcase split verifying the diagnostic\n    must catch it using standard CHECK matchers, explicitly tracking the\n    matching enum tag in standard error comments:\n\n    ```carbon\n    // CHECK:STDERR: fail_bounds.carbon:[[@LINE+1]]:15: error: cannot convert NaN to integer type `i32` [FloatNaNConvertedToInt]\n    let a: i32 = Convert(nan_val);\n    ```\n\n3.  **Build Enforcement**: Failing to provide a diagnostic test check matcher\n    triggers a failure on the target test\n    `//toolchain/diagnostics:coverage_test`.\n4.  **Label Enforcement**: A label is declared where it is attached rather than\n    in a central registry, so `coverage_test` has no list of labels to compare a\n    matched name against and leaves any name that isn't a kind alone.\n    [check_diagnostics.py](../../../toolchain/diagnostics/check_diagnostics.py)\n    is what checks them: it reads the declarations and the testdata directly, so\n    it catches a label with no test, a name matched on that is neither a kind\n    nor a label, and a kind registered in `kind.def` that nothing declares. It\n    runs as a pre-commit hook, which CI runs too, rather than as a bazel test --\n    reading every source file is what it needs and what a test in the sandbox\n    cannot do.\n\n<!-- File: .agents/skills/github_cli/SKILL.md (Tokens: ~1039 | Category: anthropic-skill) -->\n---\nname: GitHub CLI usage\ndescription:\n    Instructions for using the `gh` command to query and inspect GitHub state\n    safely.\n---\n\n# GitHub CLI usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill provides instructions for using the GitHub CLI (`gh`) to query,\ninspect, and search GitHub state (issues, pull requests, repositories) for the\nCarbon project.\n\n## Safety First: Read-Only Usage\n\n> [!IMPORTANT] AI assistants MUST NOT use the `gh` tool to modify any GitHub\n> project state. Do NOT run commands that create, edit, delete, label, comment\n> on, or merge issues, pull requests, releases, or any other resources.\n\n### Allowed Verbs\n\n-   `list`\n-   `view`\n-   `search`\n-   `status`\n-   `api` (Only with `GET` requests)\n\n### Prohibited Verbs\n\n-   `create`\n-   `edit`\n-   `delete`\n-   `merge`\n-   `reopen`\n-   `close`\n-   `comment`\n-   `label`\n\n## Repository Configuration\n\nThe `gh` tool interacts with a default repository when run within a local check\nout. For this project, the default repository is expected to be\n`carbon-language/carbon-lang`.\n\n### Verifying Default Repository\n\nTo verify the current default repository configuration:\n\n```bash\ngh repo view\n```\n\nThe output should indicate the repository is `carbon-language/carbon-lang`.\n\n### Correcting Misconfigurations\n\nIf the default repository is misconfigured (for example, pointing to a personal\nfork or a different repository), the human operator must correct it.\n\n> [!IMPORTANT] AI Assistants MUST NOT attempt to mutate `gh` configuration or\n> run commands that change the default repository (such as\n> `gh repository set-default`).\n\nInstruct the human operator to run the following command to select the correct\ndefault repository:\n\n```bash\ngh repo set-default\n```\n\nThe operator will be prompted to select the correct repository (e.g.,\n`carbon-language/carbon-lang`) from the available remotes.\n\n## Common Query Commands\n\n### Issues\n\n-   **List issues**: `gh issue list`\n-   **View specific issue**: `gh issue view <number>`\n-   **Search issues**: `gh issue search \"<query>\"`\n    -   Example: `gh issue search \"crash\" --state open`\n\n### Pull Requests\n\n-   **List PRs**: `gh pr list`\n-   **View specific PR**: `gh pr view <number>`\n-   **View PR diff**: `gh pr diff <number>`\n-   **Check PR status**: `gh pr status`\n\n### Search\n\n-   **Search code**: `gh search code \"<query>\"`\n-   **Search repositories**: `gh search repos \"<query>\"`\n\n## Advanced Usage: GitHub API\n\nFor queries that are not supported by standard `gh` commands, you can use the\n`gh api` command to query the GitHub REST or GraphQL APIs.\n\n### REST API\n\nQuery the REST API using paths relative to the API root.\n\n-   **List contributors**:\n\n    ```bash\n    gh api repos/carbon-language/carbon-lang/contributors\n    ```\n\n-   **List issue comments**:\n\n    ```bash\n    gh api repos/carbon-language/carbon-lang/issues/<issue_number>/comments\n    ```\n\n### GraphQL API\n\nFor complex queries, use GraphQL to fetch exactly the data needed.\n\n-   **Get repository information**:\n\n    ```bash\n    gh api graphql -f query='\n      query {\n        repository(owner: \"carbon-language\", name: \"carbon-lang\") {\n          description\n          stargazerCount\n        }\n      }\n    '\n    ```\n\n### Pagination\n\nUse the `--paginate` flag to automatically fetch all pages of results.\n\n```bash\ngh api --paginate repos/carbon-language/carbon-lang/issues\n```\n\n### Filtering and Formatting\n\nUse `--json` to request JSON output, and `--jq` or `--template` to filter or\nformat the results.\n\n-   **List PR titles and authors**:\n\n    ```bash\n    gh pr list --json title,author --jq '.[] | \"\\(.title) by \\(.author.login)\"'\n    ```\n\n-   **Format with Go templates**:\n\n    ```bash\n    gh issue list --template '{{range .}}{{.number}} - {{.title}}{{\"\\n\"}}{{end}}'\n    ```\n\n## Documentation References\n\n-   **GitHub CLI Manual**:\n    [cli.github.com/manual](https://cli.github.com/manual/)\n-   **GitHub REST API Documentation**:\n    [docs.github.com/en/rest](https://docs.github.com/en/rest)\n-   **GitHub GraphQL API Documentation**:\n    [docs.github.com/en/graphql](https://docs.github.com/en/graphql)\n\n<!-- File: .agents/skills/github_issues/SKILL.md (Tokens: ~598 | Category: anthropic-skill) -->\n---\nname: Accessing GitHub issues\ndescription:\n    Instructions for safely viewing and accessing GitHub issues by way of\n    command line.\n---\n\n# Accessing GitHub issues\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill provides instructions for AI assistants on how to access and view\nGitHub issues. Agents should strongly prefer using the command line `gh` tool to\naccess and view the contents of issues rather than viewing their contents by way\nof a web browser.\n\n## Safety First\n\n> [!IMPORTANT] AI assistants MUST NOT modify any GitHub issue state. Only use\n> read-only access commands like `view` or `list`. Do NOT comment, edit, create,\n> close, or delete issues.\n\n## Accessing Issues\n\nAgents must use this skill to access issues regardless of how they are mentioned\n(for example, by URL or by issue number).\n\n### Basic View\n\nTo view an issue in the current default repository (expected to be Carbon):\n\n```bash\ngh issue view <issue_number>\n```\n\n### Including Full Context (All Comments)\n\nTo ensure the view includes the entire context of the issue, always include the\n`--comments` flag to dump all comments:\n\n```bash\ngh issue view <issue_number> --comments\n```\n\n> [!TIP] If the issue is extremely large and comments are truncated, or you need\n> to process comments programmatically, use the JSON output with `jq`:\n>\n> ```bash\n> gh issue view <issue_number> --json comments --jq '.comments[].body'\n> ```\n\n### Accessing Issues in Other Repositories\n\nTo view an issue in another repository (for example, LLVM), use the `-R` or\n`--repo` flag to specify the repository:\n\n```bash\ngh issue view <issue_number> -R <owner>/<repo> --comments\n```\n\nExamples:\n\n-   **LLVM Issue**:\n\n    ```bash\n    gh issue view 5678 -R llvm/llvm-project --comments\n    ```\n\n-   **Carbon Issue (Explicit)**:\n\n    ```bash\n    gh issue view 1234 -R carbon-language/carbon-lang --comments\n    ```\n\n## Mentions via URL\n\nIf an issue is mentioned via URL, parse the URL to extract the repository owner,\nrepository name, and issue number.\n\n-   **URL pattern**: `https://github.com/<owner>/<repo>/issues/<number>`\n-   **Extraction**:\n    -   Host: `github.com`\n    -   Owner: `<owner>`\n    -   Repo: `<repo>`\n    -   Number: `<number>`\n\nRun the command specifying the repository:\n\n```bash\ngh issue view <number> -R <owner>/<repo> --comments\n```\n\n<!-- File: .agents/skills/jj/SKILL.md (Tokens: ~984 | Category: anthropic-skill) -->\n---\nname: Jujutsu (jj) usage\ndescription:\n    Instructions for using Jujutsu (jj) for version control in the Carbon\n    repository.\n---\n\n# Jujutsu (jj) usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Jujutsu](https://github.com/jj-vcs/jj) is a Git-compatible version control\nsystem that may be used in Carbon checkouts.\n\n> [!IMPORTANT] You can detect if Jujutsu is in use by checking for a `.jj`\n> directory in the repository root. If present, you **must** use `jj` and **must\n> not** use `git`. If absent, you **must not** use `jj`.\n\n## General usage\n\nAlways use the `--no-pager` flag when invoking `jj` to prevent the command from\nblocking or waiting for terminal paging.\n\n## Common commands\n\n### Syncing with remote\n\n-   **Fetch from remote**: `jj --no-pager git fetch`\n-   **Create a new change on top of trunk**: `jj --no-pager new trunk`\n-   **Show repository status**: `jj --no-pager status`\n-   **Show commit history**: `jj --no-pager log`\n\n### Managing changes\n\n-   **View diff of current changes**: `jj --no-pager diff`\n-   **Commit changes**: `jj --no-pager commit`\n    -   _Note_: Prefer using `jj commit` over the combination of `jj describe`\n        and `jj new`.\n-   **Abandon/discard current changes**: `jj --no-pager abandon`\n-   **Rebase current change onto trunk**: `jj --no-pager rebase -o trunk`\n\n### Working with a stack of changes\n\nA change is often built as a stack of commits sent up as a single pull request.\nThe stack is not necessarily based on `trunk`; it may be based on another change\nthat is itself still in flight.\n\n> [!WARNING] **Never rewrite the history of a change that has been submitted as\n> a pull request.** Reviewers track a PR by its commits, and squashing,\n> reordering, or abandoning them discards review that is already in progress.\n> This cannot be undone from their side.\n>\n> Before rewriting history in any other case, propose the exact command and wait\n> for confirmation. This applies to `squash`, `rebase`, `abandon`, and\n> `describe` on an existing change.\n\n#### Finding the base of the stack\n\nBookmarks delimit the stack. List the bookmarks that are ancestors of the\nworking copy, nearest first:\n\n```bash\njj --no-pager log -r '::@ & bookmarks()'\n```\n\nReading the result takes care, because two situations produce similar output:\n\n-   **Editing an existing change.** The nearest bookmark names the change being\n    worked on, and the bookmark below it is the base.\n-   **Starting a new change.** The commits above the nearest bookmark have no\n    bookmark of their own yet, so the nearest bookmark is itself the base.\n\n`trunk` is only ever a base. Finding `trunk` nearest means new work is being\nbuilt on top of it, never that `trunk` itself is being worked on.\n\nThe graph does not distinguish the two cases: an unbookmarked or empty commit\nabove a bookmark may be the next commit of that change or the start of a new\none. Ask which it is when it is not clear, and ask before choosing where a fix\nshould land rather than after. Guessing wrong means squashing into a change that\nmay already be under review.\n\nOnce the base is known, use it to scope commands to the current stack:\n\n```bash\njj --no-pager log -r '<base-bookmark>..@'\n```\n\n#### Managing the stack\n\n-   **Fold a fix into an earlier change**:\n    `jj --no-pager squash --into <change-id> [path]`. Follow-up fixes and\n    formatter reflows belong in the change that introduced the code, not in a\n    trailing \"fixes\" commit, unless that change has already been submitted.\n    Naming a path squashes only that part of the working copy, leaving unrelated\n    work in place.\n-   **Descriptions**: only one change in the stack needs a long description, the\n    one used as the pull request description. Every other change gets a short\n    one-line summary. Do not repeat the long text across the stack.\n\n<!-- File: .agents/skills/language_server/SKILL.md (Tokens: ~2148 | Category: anthropic-skill) -->\n---\nname: Language server\ndescription:\n    Instructions for working on Carbon's LSP language server, including its\n    architecture, its file_test-based tests, and the VS Code extension.\n---\n\n# Language server\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Introduction\n\nThis skill covers [`toolchain/language_server/`](/toolchain/language_server/),\nwhich implements `carbon language-server`, and\n[`utils/vscode/`](/utils/vscode/), the VS Code extension that launches it.\n\n## Architecture\n\nThe server is built on clangd's LSP transport (`clang::clangd`), not on a\nCarbon-specific one. That means clangd's `Protocol.h` types (`Position`,\n`Range`, `Location`, `Hover`, `MarkupContent`) are the interface currency.\n\n-   `server.cpp` / `incoming_messages.cpp`: message dispatch. A handler must be\n    registered in `incoming_messages.cpp` before it can be called.\n-   `handle_*.cpp`: one file per request family, each declaring its entry point\n    in `handle.h`.\n-   `handle_initialize.cpp`: the advertised capabilities. **Adding a capability\n    changes `Content-Length` in every test that calls `initialize`**, so expect\n    a large autoupdate diff.\n-   `context.h` / `context.cpp`: `Context::File` per open document, plus the\n    compile driver. `Context::File::unit()` has a `CARBON_CHECK` on the compile\n    driver, so any handler that reaches for the parse tree must first rule out\n    documents that were never compiled.\n-   `position.h`, `sem_ir_index.h`: mapping source positions to SemIR\n    instructions for real Carbon files.\n-   `sem_ir_text.h`, `handle_sem_ir_text.h`: navigation within the *formatted\n    SemIR* in a test file's `// CHECK:STDOUT:` lines. This is a heuristic text\n    index, deliberately independent of the real SemIR data structures. See\n    [the SemIR text reader](#the-semir-text-reader).\n\n### Document kinds\n\nThe server handles two kinds of document, distinguished by the `languageId`\nfrom `textDocument/didOpen`, with a content sniff as a fallback:\n\n-   `carbon`: a real Carbon file. Compiled; diagnostics published.\n-   `carbon-testdata`: a test file. **Not compiled**, because we lack logic to\n    split it into one file per `// ---` split marker.\n\n> [!IMPORTANT]\n> A handler that assumes every file was compiled will crash on a test file.\n> When adding one, give the test-file path an explicit early return.\n\n## Tests\n\nThere is **no language-server-specific test target**.\n`toolchain/language_server/BUILD` only declares\n`filegroup(name = \"testdata\")`, which is pulled into\n`//toolchain/testing:all_testdata` and run by `//toolchain/testing:file_test`.\n\n```bash\n# Run just the language server tests (or any subset).\nbazelisk test //toolchain/testing:file_test \\\n    --test_arg=--file_tests=toolchain/language_server/testdata/position/hover_and_goto.carbon\n\n# See the raw output, which is much easier to read than a test failure.\nbazelisk run //toolchain/testing:file_test -- --dump_output \\\n    --file_tests=toolchain/language_server/testdata/position/hover_and_goto.carbon\n\n# Update expectations. Never hand-write CHECK lines.\n./toolchain/autoupdate_testdata.py toolchain/language_server/testdata/...\n```\n\nThese tests run serially, because clangd's logging is a global singleton.\n\n### Test file shape\n\nThe request stream is a `// --- STDIN` split written with the `[[@LSP-*]]`\nkeywords, and the responses land in a trailing `// --- AUTOUPDATE-SPLIT`.\nDocuments come from other splits by way of `\"text\": \"FROM_FILE_SPLIT\"`, which\nis substituted with the content of the split whose name matches the `uri`.\n\n```carbon\n// --- position.carbon\nfn Abs(n: i32) -> i32 { return n; }\n\n// --- STDIN\n[[@LSP-CALL:initialize:\"capabilities\": {}]]\n[[@LSP-NOTIFY:textDocument/didOpen:\n  \"textDocument\": {\n    \"uri\": \"file:/position.carbon\",\n    \"languageId\": \"carbon\",\n    \"text\": \"FROM_FILE_SPLIT\"\n  }\n]]\n[[@LSP-CALL:textDocument/hover:\n  \"textDocument\": {\"uri\": \"file:/position.carbon\"},\n  \"position\": {\"line\": 0, \"character\": 3}\n]]\n[[@LSP-CALL:shutdown]]\n[[@LSP-NOTIFY:exit]]\n\n// --- AUTOUPDATE-SPLIT\n```\n\nFull keyword documentation is in\n[`testing/file_test/README.md`](/testing/file_test/README.md).\n\n### Traps\n\n> [!WARNING]\n> **A blank line inside the `STDIN` split breaks the JSON transport.** It\n> terminates a header block, so clangd logs a timestamped\n> `Warning: Missing Content-Length header, or zero-length message.` The\n> timestamp makes the test unreproducible, so it fails on the next run.\n> Comment lines between messages are fine; blank lines are not. A single blank\n> line immediately before `// --- AUTOUPDATE-SPLIT` is also fine.\n\nOther things worth knowing:\n\n-   **`positionEncoding` is UTF-16.** A `character` is a UTF-16 code unit\n    offset, not a byte offset.\n-   **Line and character numbers in requests are 0-based**, while the `locN_M`\n    suffixes in SemIR output are 1-based. Off-by-ones here are silent: the\n    request succeeds and returns the wrong thing.\n-   **A split can hold a document that itself contains `// CHECK:STDOUT:`\n    lines**, because `CHECK` lines only form expectations inside the\n    `AUTOUPDATE-SPLIT`. Such a document still can't contain a literal `// ---`\n    line, which would split the enclosing test file; write it as\n    `[[@0x2f]]/ --- name.carbon`.\n\n## The SemIR text reader\n\n`sem_ir_text.cpp` indexes the formatted SemIR inside a test file's\n`// CHECK:STDOUT:` lines so that hover and go-to-definition work on operand\nnames. It is a heuristic reader, not a parser, and its correctness rests on\nfacts about `toolchain/sem_ir/formatter.cpp` and\n`toolchain/sem_ir/inst_namer.cpp`. Re-check these if the formatter changes:\n\n-   There are exactly four scope keywords: `file`, `generated`, `imports`, and\n    `constants` (`InstNamer::GetScopeName`). Everything else is `@entityname`.\n-   A reference is `%name` within its own scope and `scope.%name` otherwise\n    (`InstNamer::GetNameFor`). Names may contain `.` and may _start_ with one,\n    as in `%.Self.frozen`.\n-   **Type annotations are printed in the `constants` scope.**\n    `Formatter::FormatTypeOfInst` does\n    `llvm::SaveAndRestore file_scope(scope_, InstNamer::ScopeId::Constants)`,\n    so in `%x: %foo = ...` a bare `%foo` means `constants.%foo`. This does not\n    apply to ordinary operands or to `[concrete = ...]` annotations.\n-   **`*_decl` braces hold the declared entity's scope.** The braces of\n    `%F.decl: ... = fn_decl @F [...] { ... } { ... }` are lexically inside\n    `file { }`, but their names belong to `@F`.\n-   **`!with Self:` switches scope without a brace**, until `!members:`\n    switches it back. Brace counting alone cannot see this.\n-   A `specific @F(args) { }` block uses `@F`'s scope and defines nothing; each\n    `%name => value` row references an instruction of the generic.\n\n### Validating a change to the reader\n\nThe unit tests only cover a handful of cases. To check a change against the\nreal corpus, drive the server over a sample of check testdata, hovering on\nevery `%name`, and compare the resolved fraction before and after. Roughly 99%\nof names resolve; the residue are names the formatter references but never\nemits a definition line for, such as `%I.WithSelf.F`, which only ever appears\ninside a `[symbolic = ...]` annotation.\n\nTwo things to get right in such a harness:\n\n-   Feed the request stream from a **file**, not a pipe. The server reads stdin\n    as a file and reports `error: Input/output error` on a pipe.\n-   Read the output as **bytes**. Python's `text=True` rewrites the `\\r\\n`\n    framing, and `Content-Length` counts bytes.\n\n## VS Code extension\n\n[`utils/vscode/`](/utils/vscode/) declares three languages in `package.json`:\n\n| Language id      | Applies to                        |\n| ---------------- | --------------------------------- |\n| `carbon`         | `*.carbon`                        |\n| `carbon-testdata`| `**/testdata/**/*.carbon`         |\n| `semir`          | `*.semir`                         |\n\n> [!NOTE]\n> The TextMate _scope_ for SemIR is `source.carbon-semir`, but the\n> _language id_ is `semir`. Markdown code fences in hover text resolve language\n> ids, so a fence must say ` ```semir `.\n\n`extension.ts` launches the server over stdio, using the `carbonPath` setting\n(default `./bazel-bin/toolchain/carbon`). Its `documentSelector` controls which\nfiles are sent to the server at all; a new document kind has to be added there\nas well as in the server.\n\n<!-- File: .agents/skills/prek/SKILL.md (Tokens: ~497 | Category: anthropic-skill) -->\n---\nname: Prek\ndescription:\n    Instructions for running prek, the Carbon pre-submit/style/lint checker,\n    that *MUST* be run before submitting an change.\n---\n\n# Prek\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n`prek` is the Carbon pre-submit, style, and lint checker. Running it is\nmandatory before submitting any changes.\n\n## Running prek\n\nTo run `prek` on all files:\n\n```bash\nprek run -a\n```\n\nTo validate a specific list of files:\n\n```bash\nprek run --files <files>\n```\n\n## Running prek in a Jujutsu (jj) workspace\n\nIf you are working in a Jujutsu workspace, running `prek` directly will fail\nbecause it expects a standard Git repository structure. Instead, use the helper\nscript:\n\n```bash\n./scripts/jj_prek.sh\n```\n\nThis script runs `prek` on all files that have changed between `trunk` and your\ncurrent Jujutsu `@` change.\n\nNote that the script always compares against `trunk`. If your change is based on\nanother bookmark rather than on `trunk`, the script also checks the files\nchanged by that underlying change, so a reported failure may not be in your own\nwork.\n\n## Hooks that rewrite files\n\nSome hooks, notably `clang-format` and `rumdl`, fix problems in place rather\nthan only reporting them. When they do, `prek` reports a failure and exits\nnon-zero even though the tree is now correct.\n\nRe-run `prek` after any failure that modified files, and treat the second, clean\nrun as the result. Review what it changed: a reflow is expected, but a content\nchange may not be what you intended.\n\n## Prek dependency errors\n\n> [!TIP] If `prek` fails with an error about resolving dependencies or security\n> policy, you may be running in a restricted environment where the\n> special-purpose `gpkg` tool is required. Prefix the command with `gpkg`, for\n> example: `gpkg prek run -a` or `gpkg ./scripts/jj_prek.sh`.\n\n<!-- File: .agents/skills/proposals/SKILL.md (Tokens: ~1445 | Category: anthropic-skill) -->\n---\nname: Proposals\ndescription:\n    Instructions for writing, submitting, and managing Carbon evolution\n    proposals.\n---\n\n# Proposals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Overview\n\nThis skill provides instructions and best practices for working with proposals.\nOnly create a proposal when explicitly directed as part of the task.\n\nMake sure to confirm the desired title for the proposal as that will govern the\nfilename.\n\n## Create a new proposal\n\n1.  **Use the helper script**: Run `./proposals/scripts/new_proposal.py \"Title\"`\n    to create a templated file and instructions for setting up the PR.\n2.  **Proposal file**: The file will be named `proposals/p######-title.md`,\n    where `######` is the 6-digit GitHub pull request number and `title` is a\n    slugified version of the proposal title.\n3.  **Template**: Follow the structure in `proposals/scripts/template.md`,\n    noting the specific `TODO` instructions in each section for the content that\n    should be included there.\n4.  **PR description**: Update the pull request description to match the\n    abstract section in the proposal document.\n\n> [!IMPORTANT] Do _not_ mark the PR ready for review. The user must have the\n> opportunity to review the proposal produced before asking for any review.\n\n## Writing style and best practices\n\n-   **Skimmable**: Use\n    [BLUF](<https://en.wikipedia.org/wiki/BLUF_(communication)>) (Bottom Line Up\n    Front) or\n    [Inverted Pyramid](<https://en.wikipedia.org/wiki/Inverted_pyramid_(journalism)>)\n    style. Keep it brief, focused, and technical.\n-   **Match existing proposal style**: Review [existing proposals](/proposals)\n    (preferring more recent ones with higher numbers) to understand the expected\n    style, wording, and nature of content to include.\n-   **Connect to goals**: In the Rationale section, link to specific goals in\n    [`/docs/project/goals.md`](/docs/project/goals.md) and principles in\n    [`/docs/project/principles`](/docs/project/principles) (e.g.,\n    `error_handling.md`, `one_way.md`).\n-   **Living design**: If the proposal updates design documentation, include\n    those changes in the PR if possible. If deferred, add \"TODO\" comments\n    pointing to the proposal (e.g., `> **TODO:** Document ... adopted in\n    [p######](/proposals/p######-title.md)`). For pervasive changes, file a\n    GitHub issue instead of adding many TODOs.\n\n## Alternatives considered and leads decisions\n\nThere are always alternatives to a proposal, and the proposal should carefully\ninclude sections describing all of them and the rationale for not selecting\nthem. Any living design document updates should focus on fully describing the\nend-state design, and the key motivating aspects of that design. The main\nproposal should focus on _what is changing_ and _why it is changing_, and should\nleave detailed description of the resulting design to the living design\ndocument, and _why not_ rationale to the description of each alternative.\n\n-   **Cover all the alternatives**: Make sure to describe any alternatives\n    considered, even if minor or rejected early.\n-   **Be specific**: Don't be vague about any of the alternatives, or the\n    rationale for not choosing them.\n-   **Connect to goals or principles**: In addition to the rationale section,\n    one of the best rationale structures for rejecting an alternative connects\n    that choice back to the goals or principles relevant.\n-   **Always frame as a tradeoff**: Selecting the proposed direction instead of\n    an alternative is _always_ a tradeoff, with both advantages and\n    disadvantages.\n-   **Where relevant, cite the leads issue** that decides against an\n    alternative, in addition to summarizing the key points, tradeoffs, and\n    rationale for the decision.\n\n> [!IMPORTANT] Don't just list the alternatives, create a sub-section for each\n> alternative and carefully describe the alternative, the advantages,\n> disadvantages and what the core of the decision is to reject each alternative.\n\n> [!IMPORTANT] Carefully research each alternative in the leads issue in order\n> to provide this clear and comprehensive explanation.\n\n## Building from a leads issue\n\nSometimes a proposal is specifically documenting and formalizing a decided leads\nissue. When this is the case, carefully research that leads issue, reading the\noriginal issue text and every comment on the issue. Also read any linked Google\ndocuments, linked issues, examples, gists, or other supplemental information\ncited.\n\n-   **Summarize the leads issue**: Ensure you provide a high level summary of\n    the _decided_ direction of the leads issue as the proposal.\n-   **Capture and document** every key aspect of the decision made and factor\n    that led to the decision. It is important that the proposal stands alone,\n    and the leads issue is merely cited for context and history.\n-   **Stay grounded**: Only include alternatives, rationale, and arguments based\n    on what you find in the issue and related documents. No new information\n    should be in the proposal.\n\nUse the `gh` command line tool to query leads issues in order to carefully\nexamine all of the comments. Follow any mentioned links to gather more data.\nRefer to the [GitHub CLI usage skill](/.agents/skills/github_cli/SKILL.md) for\ndetailed instructions on using the `gh` tool.\n\nAsk the user to clarify any aspects of the leads issue that are unclear rather\nthan continuing to edit the proposal. If there are questions that you don't find\nan answer to in the issue, ask this to the user and let them provide an answer\nthat you use as the basis of what to include.\n\n## Examples are golden\n\nHeavily leverage examples to illustrate both the specifics of the design being\nproposed, and the nature of the change being proposed. More examples to\nillustrate more aspects, corner cases, or provide a more complete understanding\nare almost always good. Comments in example code should focus on what that part\nof the example illustrates from the proposal.\n\n## Keep the PR description in sync with the abstract\n\nWhenever you edit the abstract or notice differences from the PR description,\nyou should update the PR description to match the abstract. The only exception\nis to retain any \"Assisted-by\" or other tags at the end of the description that\nare only needed there and not in the abstract.\n\nIf you are creating or updating a proposal, make sure the PR description in\nquestion contains an `Assisted-by:` tag that is appropriate for describing which\nAI tool is being used.\n\n<!-- File: .agents/skills/review_testdata_changes/SKILL.md (Tokens: ~3909 | Category: anthropic-skill) -->\n---\nname: Review testdata changes\ndescription:\n    Instructions for judging whether changes to file test output\n    (`// CHECK:STDOUT:` and `// CHECK:STDERR:` lines) are correct, which\n    changes are acceptable churn, and which are regressions in disguise.\n---\n\n# Review testdata changes\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Introduction\n\nMost toolchain work moves file test output. `./toolchain/autoupdate_testdata.py`\nrewrites the `// CHECK:STDOUT:` and `// CHECK:STDERR:` lines in\n`toolchain/*/testdata/` to match current behavior, so after running it the tests\npass again whether or not the new behavior is right. Deciding that the new\noutput is the output you wanted is a separate, manual step, and it is the step\nthis skill covers.\n\nThree skills divide the work:\n\n-   [Toolchain tests](../toolchain_tests/SKILL.md): how to _author_ tests and\n    generate their output.\n-   This skill: how to _judge_ an output diff.\n-   [Summarize testdata changes](../summarize_testdata_changes/SKILL.md): how to\n    _report_ an output diff once you believe it is correct.\n\n> [!IMPORTANT] Never hand-edit `// CHECK:STDOUT:` or `// CHECK:STDERR:` lines.\n> Everything below is about changing the _code_ until the generated output is\n> right, never about editing the output to match the code.\n\n## The rule that generates all the others\n\n**Every line of testdata churn must have a cause you can name.** Not \"it is\nsimilar to the other changes\", not \"the tests pass now\" — an actual sentence\nsaying which code change produced it and why that is the intended result.\n\nA diff you cannot narrate is a diff you have not reviewed. Changes you cannot\nexplain are where regressions hide, because a regression and an intended change\nlook exactly alike once the autoupdater has written them down.\n\n> [!CAUTION] Autoupdating is destructive to your evidence. Once the autoupdater\n> has run, the previous expectations are gone from the working copy. Read the\n> diff after _every_ autoupdate run, and if something changed for a reason you\n> cannot name, fix the code before autoupdating again. Recovering the old\n> expectations later means reverting and re-running.\n\n## STDERR and STDOUT are different kinds of evidence\n\nTreat them separately; they have different standards of proof.\n\n**STDERR is user-visible behavior.** These are the diagnostics a Carbon\nprogrammer sees. A change here is a change to the language implementation as\nusers experience it, so each one needs an individual justification. For a\nrefactoring, the expected STDERR diff is empty.\n\n**STDOUT is internal representation.** SemIR dumps, parse trees, LLVM IR. Users\nnever see it. Churn here is normal and often unavoidable, so the standard is not\n\"no change\" but \"no change I cannot account for\".\n\nFor a change that is supposed to preserve behavior, write the list of accepted\nSTDERR changes down _before_ you autoupdate, and keep it current. Order matters\nmore than form: written first, the list is a prediction the diff can falsify;\nwritten afterwards, it is a description of whatever happened, and describes a\nregression exactly as well as an intended change.\n\nThe list does not have to be a deliverable. Scratch notes you never publish do\nthe job, because the work is in committing to the list, not in presenting it.\nWhat a reader needs is not the list but its exceptions: diagnostics that changed\nwithout being predicted, and predictions that did not occur. Both are findings.\nThe matches are not, and reporting them buries the two entries that matter.\n\n## Judging STDOUT churn\n\nSort each STDOUT change into mechanical or structural.\n\n### Mechanical churn\n\nExpected, and cheap to accept in bulk once you have confirmed the pattern:\n\n-   **Renaming.** An instruction, type, or scope prints under a new name.\n-   **Positional name renumbering.** Names like `%x.loc18_46.3` embed a line,\n    column, and disambiguating index. Two different events move them:\n    -   Adding or removing an instruction at a location renumbers the rest, so a\n        _single_ removed instruction can show up as many changed lines in the\n        same block. Confirm the cascade is a cascade before accepting it as one.\n    -   Adding or removing a _diagnostic_ moves the source lines themselves, so\n        the line component changes everywhere below it in the file. See\n        [Autoupdate to a fixed point](#autoupdate-to-a-fixed-point).\n-   **Fingerprint-derived names.** Mangled names and some scope names are\n    derived from a hash of their inputs. If you changed a hashed input, these\n    move. Confirm that each such difference is _only_ the fingerprint, and not a\n    fingerprint difference concealing a structural one.\n\n> [!TIP] Mechanical churn is usually wide and shallow: the same substitution,\n> repeated across many files. If a \"mechanical\" pattern needs a different\n> explanation in each file, it is not mechanical.\n\n### Structural churn\n\nEach of these needs its own explanation:\n\n-   Instructions appearing or disappearing.\n-   Changed `[concrete = ...]`, `[symbolic = ...]`, or other constant-value\n    annotations.\n-   Changed types on existing instructions.\n-   Changed control flow: new or removed blocks, changed branch targets.\n-   Raw instruction ids renumbering in `--dump-raw-sem-ir` output when you did\n    not intend to change the id layout.\n\n## Fewer instructions is not automatically better\n\nA diff that removes instructions looks like an optimization. Whether it is one\ndepends on what the changed function owes its caller, and two functions can\nproduce the same shrinking diff for opposite reasons:\n\n-   A function that only needs a constant value, but built instructions on the\n    way to it, was doing wasted work. Dropping them and using the constant\n    directly is correct, and the shorter output reflects that.\n-   A function whose caller needs a **non-canonical instruction** can be made\n    shorter the same way, by using the constant instead of creating an\n    instruction of its own — and that is wrong. The instruction carries location\n    information, and symbolic constant substitution operates on it; the constant\n    value alone loses both.\n\nThe instruction count is identical evidence in both cases, so it cannot be the\nthing you judge. Decide what the function is required to produce; the count\nfollows from that.\n\nThe same reasoning runs in reverse: a diff that _adds_ instructions is not\nautomatically a regression.\n\n## Judging STDERR churn\n\n### A diagnostic's authority depends on the file's prefix\n\nThe `fail_` and `todo_` prefixes (see\n[Toolchain tests](../toolchain_tests/SKILL.md)) say how much the recorded\ndiagnostics are worth:\n\n-   **`fail_...`** — the test should and does produce errors. The recorded\n    diagnostic **is the specification**. Changing it is a user-visible behavior\n    change and needs justification on its own merits.\n-   **`fail_todo_...`** — the test produces errors (or crashes) but shouldn't,\n    or produces the wrong errors. The recorded diagnostic is explicitly **not**\n    the specification; the file exists to record that today's behavior is wrong.\n    Changing it replaces one wrong answer with another. That is acceptable when\n    you can say why the new message follows from your change and why it is no\n    further from the intended eventual behavior — which, for many such files, is\n    no diagnostic at all.\n-   **`todo_fail_...`** — the test should produce errors but does not. Gaining a\n    diagnostic here may be _progress_, not a regression. Either way the file\n    must be renamed, since the framework requires a `fail_` prefix on any file\n    that errors: `fail_...` if it now produces the right error, `fail_todo_...`\n    if the error is the wrong one. Both renames make the test pass, so record\n    which case it is instead of letting the rename settle it.\n-   **`todo_...`** — behavior is wrong but produces no errors, and shouldn't.\n    Gaining a diagnostic here is a regression unless you can argue otherwise.\n\n> [!IMPORTANT] This is a reason to look at the _filename_ before judging a\n> diagnostic change, not a license to ignore `todo_` files. \"It was already\n> broken\" does not excuse making it differently broken for no reason.\n\n### Reclassifying tests\n\nIf your change moves a test between the states above, the prefix must move with\nit: when the test is fixed, when it starts failing, and when it starts failing\ndifferently. The correspondence between the `fail_` prefix and whether\ncompilation actually failed is enforced by the test framework, not by the\nautoupdater, so it surfaces when you run `bazelisk test` and not when you\nautoupdate. **Autoupdating is not a substitute for running the tests.**\n\nOnly that half of the name is checked. Nothing enforces `todo_`, so a file whose\nbehavior you have just fixed can keep its `todo_` prefix indefinitely and still\npass. A missing `fail_` stops the build; a stale `todo_` is silent, and is yours\nto catch.\n\nWhen a fix drops a file's prefix, also check that the file still belongs where\nit is and that its comments do not still describe the old broken behavior.\n\n### Vaguer diagnostics are a signal, not a verdict\n\nWhen a diagnostic becomes less specific — a general \"unsupported\" message\nreplacing one that named the problem — that usually means a code path stopped\nfinding information it previously had. Sometimes that is correct: the\ninformation was misleading, and the old message was confidently wrong.\n\nDo not accept it silently and do not reject it reflexively. Say which direction\nit moved and whether the new message is closer to or further from the eventual\nintended behavior.\n\n## Signals in the shape of the diff\n\n### Zero churn is a result\n\nIf you removed something you believed was doing work and _no_ testdata moved,\nthat is not a missing test run — it is the proof that the thing was a no-op.\nSay so explicitly; it is one of the strongest pieces of evidence a refactoring\ncan produce.\n\nThe converse is also informative. If you expected a path to churn and it didn't,\neither your model of the code is wrong or that path is untested. Find out which,\nand consider adding a test before continuing.\n\n### Churn should be proportional to the change\n\n-   **Wide churn from a narrow change** means your model of the code is wrong.\n    Do not autoupdate over it. Find the structural mistake first.\n-   **Narrow churn from a sweeping change** means the affected paths are\n    probably untested.\n\nSet a rough expectation for the size of the diff before you run the autoupdater,\nand treat a large mismatch in either direction as a finding.\n\n### Never make the diff smaller by weakening the test\n\nEditing test _input_ (the Carbon source, not the CHECK lines) to make a diff\nlook better is a behavior change in disguise. Deleting a test that now produces\nawkward output is worse. If a test's input has to change, that is a separate,\nexplicitly-justified change, not diff cleanup.\n\n## What the autoupdater will not fix for you\n\n-   **`NOAUTOUPDATE` files.** Their expectations are maintained by hand. They\n    fail under `bazelisk test` rather than being silently rewritten.\n-   **Hand-written C++ expectations**, for example golden output asserted in a\n    `_test.cpp`. When several assertions in one of these break together, often\n    only the first failure is reported, so fixing it can reveal another. Re-run\n    until clean rather than assuming one fix was the whole repair.\n-   **Golden files outside `testdata/`**, and documentation that quotes compiler\n    output.\n\n## Review loop\n\n### Run the autoupdater\n\nAutoupdate everything, then read the diff a directory at a time. Passing no\npaths is the default and updates every file test in the toolchain:\n\n```bash\n./toolchain/autoupdate_testdata.py\n```\n\nNarrow the scope only while iterating on one subdirectory you know you are not\ndone with, where each round would otherwise regenerate output you have already\nread:\n\n```bash\n./toolchain/autoupdate_testdata.py toolchain/check/testdata/SUBDIR/**/*\n```\n\nThe globs are expanded by the shell; the script filters its arguments to\n`.carbon` files under a `testdata/` directory.\n\n> [!TIP] If intermediate states crash on `CARBON_CHECK` failures, pass\n> `--non-fatal-checks` so you can see the full set of downstream damage in one\n> run instead of one crash at a time.\n\n> [!IMPORTANT] Return to the full scope before judging the diff. Whether churn\n> is proportional to the change, and whether a change to one phase moved another\n> phase's testdata, are only visible across everything.\n\n### Autoupdate to a fixed point\n\nOne pass is not always enough, because the autoupdater's output is part of its\nown input. `// CHECK:STDERR:` lines sit inline, immediately above the source\nline they describe, and the compiler reads them as comments in the file.\nGaining or losing a diagnostic therefore moves every source line below it.\n\nWithin a single run, the compiler has already read the file as it was, so the\ntwo kinds of output end up in different states:\n\n-   **STDERR is correct after one pass.** These lines locate themselves\n    relatively, as `[[@LINE+N]]`, and the autoupdater recomputes `N` as it\n    places them.\n-   **STDOUT is stale after one pass.** SemIR names like `%x.loc18_46.3` embed\n    an absolute line and column with no filename attached, and the autoupdater\n    only remaps `file.carbon:18`-style references. Nothing rewrites the `loc`,\n    so it still describes where the instruction was _before_ the diagnostic\n    lines moved it.\n\nRunning again compiles the shifted file and the names catch up. The diagnostic\nset does not change this time, so nothing shifts again and a third run is a\nno-op. Keep running the autoupdater until it stops changing files: one pass when\nthe diagnostics held still, two when they didn't.\n\n> [!WARNING] The intermediate state is self-inconsistent, not just unfinished:\n> its `loc` names describe a file layout that no longer exists. Keep reading the\n> diff after every run — that rule does not change — but do not chase positional\n> churn to a cause until the file has converged, and do not present the diff\n> until then either.\n\nThe converging pass should be positional renumbering and nothing else. If it\nmoves an instruction, a type, or a constant value, then something other than a\n`loc` name is sensitive to where lines fall in the file. Find out what before\naccepting it.\n\nThe file tests do catch a file left unconverged, since each test re-runs the\nautoupdate in memory and fails with\n`Autoupdate would make changes to the file content` when the result differs. But\nthat arrives at `bazelisk test` time, after you have already read a diff that\nwas describing a file which had moved out from under it.\n\n### Inspect the diff\n\nInspect the diagnostics first, since that is the acceptance criterion:\n\n```bash\n# STDERR-only view, with jj.\njj --no-pager diff --git 'glob:toolchain/*/testdata/**' \\\n  | grep -E '^[-+].*CHECK:STDERR'\n\n# The same, with git.\ngit diff -- 'toolchain/*/testdata/*' \\\n  | grep -E '^[-+].*CHECK:STDERR'\n```\n\nFor a structured view separating test input, STDERR, and STDOUT changes, use the\nhelper from the\n[Summarize testdata changes](../summarize_testdata_changes/SKILL.md) skill:\n\n```bash\njj --no-pager diff --git 'glob:toolchain/*/testdata/**' \\\n  | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\ngit diff -- 'toolchain/*/testdata/*' \\\n  | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n```\n\nThe argument after the tool name is not interchangeable: `glob:...` is a jj\nfileset, `-- ...` is a git pathspec. `--git` and `--no-pager` are jj flags; git\nalready emits this format and skips the pager when piped.\n\n### Run the tests\n\nThen run the tests, which is what catches prefix mismatches and non-autoupdated\nexpectations:\n\n```bash\nbazelisk test //toolchain/...\n```\n\nSee the [Bazel usage](../bazel/SKILL.md) skill.\n\n## Checklist\n\nBefore presenting a testdata diff as finished:\n\n-   [ ] The autoupdater was run until it made no further changes, so no `loc`\n        name describes a stale line numbering.\n-   [ ] The list of accepted STDERR changes was written before autoupdating, and\n        every change either matches it or is reported as an exception.\n-   [ ] Every STDOUT change is either an instance of a named mechanical pattern\n        or has its own explanation.\n-   [ ] Instructions that appeared or disappeared are justified by what the\n        changed function owes its caller, not by the instruction count.\n-   [ ] Files whose prefix no longer matches their behavior have been renamed.\n-   [ ] No test input was changed, and no test was deleted, to make the diff\n        smaller.\n-   [ ] The size of the diff is proportional to the size of the change.\n\n<!-- File: .agents/skills/summarize_testdata_changes/SKILL.md (Tokens: ~1772 | Category: anthropic-skill) -->\n---\nname: Summarize testdata changes\ndescription:\n    Instructions for summarizing changes to Carbon testdata files\n    (`toolchain/*/testdata`).\n---\n\n# Summarize testdata changes\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis skill provides instructions for creating a comprehensive report summarizing\nchanges to Carbon testdata files (`toolchain/*/testdata`) and associating them\nwith related code changes.\n\nThis skill is about _reporting_ a diff. For deciding whether the diff is correct\nin the first place, see the\n[Review testdata changes](../review_testdata_changes/SKILL.md) skill.\n\n## Goals\n\nProduce a report that:\n\n1.  Summarizes code changes outside of testdata.\n2.  Groups similar testdata changes together, listing all affected files for\n    each group. **Every change to testdata must be represented by at least one\n    group. This includes changes to CHECK lines.**\n3.  Provides detailed breakdowns of test input changes and diagnostic output\n    changes in the corresponding group. **Every single change to inputs or to\n    STDERR checks must be explicitly mentioned in the group, with either an\n    inline diff or a link to the file.**\n\n## Process\n\n### 1. Identify Changes\n\nUse your VCS (Git or Jujutsu) or query Github to identify changes. For large\nchanges, it is recommended to use the included helper script to extract test\ninput changes.\n\n#### For Git Users:\n\n-   **Summarize code changes**: `git diff --stat -- ':!toolchain/*/testdata/*'`\n    -   To see content of non-testdata changes:\n        `git diff -- ':!toolchain/*/testdata/*'`\n-   **Identify testdata changes**:\n    `git diff --name-only 'toolchain/*/testdata/*'`\n\n#### For Jujutsu (jj) Users:\n\n-   **Summarize code changes**:\n    `jj --no-pager diff --stat '~toolchain/*/testdata'`\n    -   Note: Quoting the fileset `'~toolchain/*/testdata'` is critical if it\n        contains wildcards.\n    -   To see content of non-testdata changes, use `--git` to get standard\n        unified diff format: `jj --no-pager diff --git '~toolchain/*/testdata'`\n-   **Identify testdata changes**:\n    `jj --no-pager diff --name-only 'toolchain/*/testdata'`\n\n#### For Github Pull Requests:\n\n-   **Summarize code changes**: `gh pr diff`\n-   **Identify testdata changes**:\n    `gh pr diff --name-only | grep '^toolchain/.*/testdata'`\n\n#### Handling Specific Revisions:\n\nIf you are summarizing changes in a specific revision (for example, `@-`) or\npull request (for example, #1234), add `-r <rev>` or `<pr_number>` to the\ncommands:\n\n-   `git diff <rev>^ <rev> ...` (or use `git show <rev>`)\n-   `jj --no-pager diff -r <rev> ...`\n-   `gh pr diff <pr_number>`\n\n### 2. Extract Test Input Changes (Recommended)\n\nTo easily identify changes, use the included Python helper script to extract all\ntext additions and removals from the diff, categorized by Input, STDERR, and\nSTDOUT changes. This script reads a unified diff from stdin.\n\n```bash\n# For Git:\ngit diff -- 'toolchain/*/testdata/*' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For Jujutsu (jj):\njj diff --git 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For a specific revision with jj:\njj diff -r @- --git 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For a specific PR with Github:\ngh pr diff 1234 | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n```\n\n### 3. Identify Patterns and Produce a List of Groups\n\n-   Read the diff and produce a list of groups of changes that share a common\n    theme or cause (for example, \"Updated expected output for integer literals\",\n    \"Added tests for new keyword\").\n-   **CRITICAL**: _Every single change_ in the testdata diff must be represented\n    by at least one group. Do not ignore changes to `CHECK` lines.\n    -   If it's not clear what group a change belongs to, create a new group for\n        it.\n-   For each group:\n    -   Provide a brief description of the group.\n    -   (Optional) Briefly note if the group appears to be an intended or\n        unintended consequence of the code changes.\n-   Divide the groups into sections:\n    -   Test Changes: Changes to test inputs (lines not prefixed with\n        `// CHECK`), along with diagnostic output changes where relevant\n    -   Diagnostic Changes: Changes to diagnostic output (lines prefixed with\n        `// CHECK:STDERR`) with no corresponding changes to test inputs\n    -   [Output Type] Changes: Changes to STDOUT (lines prefixed with `//\n        CHECK:STDOUT`)\n        -   Create one section for each relevant kind of test. For example,\n            parser tests should typically be in a \"Parse Tree Changes\" section,\n            check tests should typically be in a \"SemIR Changes\" section, and\n            lower tests should typically be in an \"LLVM IR Changes\" section.\n\n### 4. Improve Grouping\n\n-   Read the list of groups and check to see if any of them should be combined\n    or split apart. If needed, do so.\n\n### 5. Assign Changes to Groups\n\n-   Read the diff again, and then for _each_ change in the diff:\n    -   Add the change to the appropriate group (or, rarely, groups).\n    -   **CRITICAL**: _Every single change_ in the testdata diff must be\n        represented by at least one group. Do not ignore changes to `CHECK`\n        lines.\n    -   If the change affects _test inputs_ (lines not prefixed with `// CHECK`)\n        or _diagnostic output_ (lines prefixed with `// CHECK:STDERR`):\n        -   List the file within the group. Don't just give one or a few\n            examples. Include every file.\n        -   Provide an inline diff if the change is small.\n        -   Provide a link to the file if the change is large.\n    -   Otherwise, if the change only affects _STDOUT_ (lines prefixed with\n        `// CHECK:STDOUT`):\n        -   Ensure the group contains a representative example that matches the\n            current change.\n        -   The representative example should be an inline diff of the change.\n    -   **CRITICAL**: _Every single change_ to test inputs and diagnostic\n        outputs in the files being summarized must be explicitly listed in at\n        least one group. Do not skip changes, even if they are similar to\n        changes you've already seen, and do not just give examples.\n\n### 6. Validation\n\nAs a final validation step:\n\n-   Read through the testdata diff again.\n-   Ensure that every change in the diff is reflected by at least one group in\n    the report.\n\n## Report Template\n\nUse the following template for the generated report:\n\n```markdown\n# `testdata` Change Summary\n\n## Code Changes\n\n[One paragraph summarizing changes outside of testdata.]\n\n## Test Changes\n\n### [Group Name]\n\n[Description of the group.]\n\n[Change 1: diff context OR link]\n\n[Change 2: diff context OR link]\n\n...\n\n## Diagnostic Changes\n\n### [Group Name]\n\n[Description of the group.]\n\n[Change 1: diff context OR link]\n\n[Change 2: diff context OR link]\n\n...\n\n## [Output Type] Changes\n\n### [File Path]\n\n[Description of the group.]\n\n[Example diff context]\n\nChanges of this kind were found in [Number] files. Examples: [List of files]\n\n...\n```\n\nSkip sections that would be empty.\n\n<!-- File: .agents/skills/toolchain_development/SKILL.md (Tokens: ~1884 | Category: anthropic-skill) -->\n---\nname: Toolchain development\ndescription:\n    Instructions for checking, building, debugging, and understanding the Carbon\n    toolchain.\n---\n\n# Toolchain development\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Toolchain structure\n\n-   Under [`toolchain/`](/toolchain/):\n    -   [`base/`](/toolchain/base/): Base infrastructure and common utilities.\n    -   [`check/`](/toolchain/check/): Semantic analysis (SemIR generation).\n    -   [`lex/`](/toolchain/lex/): Lexing (Source -> Tokens).\n    -   [`lower/`](/toolchain/lower/): Lowering to LLVM IR.\n    -   [`parse/`](/toolchain/parse/): Parsing (Token -> Parse Tree).\n    -   [`sem_ir/`](/toolchain/sem_ir/): Semantic Intermediate Representation\n        (SemIR) definitions.\n\n## Toolchain architecture\n\n-   **Documentation**: Refer to [`toolchain/docs`](/toolchain/docs) for detailed\n    architecture design and patterns.\n    -   Refer to [Toolchain Idioms](/toolchain/docs/idioms.md) for a\n        comprehensive list of patterns (for example, `ValueStore`, formatting\n        `.def` files, struct reflection) used throughout the implementation.\n-   **Builtin Functions**: Refer to the **Builtin functions** skill\n    ([SKILL.md](../builtins/SKILL.md)) for guidelines on registering, mapping,\n    constant evaluating, and lowering compiler builtin primitives (e.g.\n    `\"int.convert_float\"`).\n-   **Language server**: Refer to the **Language server** skill\n    ([SKILL.md](../language_server/SKILL.md)) before working on\n    `toolchain/language_server/` or `utils/vscode/`. Neither follows the\n    patterns described here.\n-   **Phases**: Lex -> Parse -> Check -> Lower.\n-   **Definitions**: Many kinds (tokens, parse nodes, SemIR instructions) are\n    defined in `.def` files and expanded by way of macros.\n-   **Handlers**:\n    -   Parser: `Handle<StateName>` in `parse/handle_*.cpp`.\n    -   Checker: `HandleParseNode` in `check/handle_*.cpp`.\n    -   Lowering: `HandleInst` in `lower/handle_*.cpp`.\n-   **Iteration**: Prefer iterative algorithms over recursive ones to prevent\n    stack exhaustion on complex codebases.\n\n### Essential commands\n\n-   **Test everything**: `bazelisk test //...`\n-   **Test specific target**: `bazelisk test //toolchain/testing:file_test`\n-   **Test specific file**: `bazelisk test //toolchain/testing:file_test\n    --test_arg=--file_tests=<path_to_carbon_file>`\n-   **Build toolchain**: `bazelisk build //toolchain/...`\n\n### Updating test data\n\nCarbon tests often use `file_test` (for example,\n`//toolchain/testing/file_test`). For detailed guidelines on authoring tests,\nincluding file splits, naming conventions (`fail_`, `todo_`), and generating\nminimal output with SemIR dumps, please refer to the **Toolchain tests** skill.\n\nIf you change compiler behavior, you likely need to update expected test\noutputs. **Do not manually edit thousands of lines of expected output.** Use the\nscript:\n\n```bash\n./toolchain/autoupdate_testdata.py\n# Or for a specific file:\n./toolchain/autoupdate_testdata.py toolchain/check/testdata/my_test.carbon\n```\n\n## Debugging and diagnostics\n\n-   **Compiler Diagnostics**: Refer to the **Diagnostics** skill\n    ([SKILL.md](../diagnostics/SKILL.md)) for strict rules on declaring,\n    formatting, emitting, testing, and styling compiler diagnostic messages\n    (errors, warnings, notes).\n-   **Printing to stderr**: Use `llvm::errs() << \"debug info\\n\";`.\n    -   Avoid `std::cout` (it may interfere with tool output).\n-   **SemIR Stringification**:\n    -   SemIR objects often have a `Print` method or `operator<<`.\n    -   `inst.Print(llvm::errs())`\n-   **Debugging Crashes**:\n    -   Bazel sandboxing can hide artifacts. Use `--sandbox_debug` if needed,\n        but often running the binary directly from `bazel-bin/` is easier for\n        debugging.\n\n## Error handling\n\n-   **No exceptions**: Do not use C++ exceptions.\n-   **`ErrorOr<T>`**: Return `ErrorOr<T>` for fallible operations.\n    -   Check with `if (auto result = Function(); result) { Use(*result); }`\n-   **`llvm::Expected<T>`**: Similar to `ErrorOr`, used when interfacing with\n    LLVM.\n\n### Context-Aware Diagnostics\n\nWhen declaring and emitting errors, ensure semantic wording matches the exact\ncontext:\n\n-   **Semantic Precision**: Do not reference \"types\" when raising errors for\n    unsized expressions like `IntLiteral` or `FloatLiteral`. For example, use\n    `RealLiteralTooLargeForUnsizedInt` instead of a diagnostic referencing an\n    \"integer type\".\n-   **Wording Consistency**: Before declaring a new diagnostic in\n    [kind.def](../../../toolchain/diagnostics/kind.def), search for existing\n    diagnostics in the targeted implementation files (for example, other uses of\n    `MaxIntWidth`) to align message structures and parameter expectations.\n\n### Casting (LLVM style)\n\n-   Use `llvm::cast<T>(obj)` (checked, asserts on failure).\n-   Use `llvm::dyn_cast<T>(obj)` (returns null on failure).\n-   Use `llvm::isa<T>(obj)` (boolean check).\n-   **Avoid** `dynamic_cast` and standard RTTI.\n\n### Leverage LLVM APIs\n\nBefore implementing custom algorithms for mathematical, logical, or bitwise\noperations, inspect target LLVM ADT class APIs:\n\n-   **Builtin APIs**: Verify if LLVM classes (such as `APInt`, `APFloat`, or\n    `APSInt`) already offer native equivalents (for example, `.pow()`,\n    `ilogb()`, `.changeSign()`, `convertFromAPInt()`). Avoid duplicate, naive,\n    or inefficient custom loops.\n\n### Data structures\n\n-   Prefer APIs in `common/` and `toolchain/base/` over LLVM ADTs. For example,\n    use `Map` instead of `llvm::DenseMap`.\n-   If no Carbon API exists, prefer LLVM ADTs over standard library ones (for\n    example `llvm::SmallVector`, `llvm::StringRef`).\n-   `StringRef` is a view; be careful with lifetimes.\n\n## Common pitfalls\n\n1.  **Legacy `explorer` references**: The `explorer` prototype has been moved.\n    Ignore references to it in proposals or old docs; focus on `toolchain`.\n2.  **Manually updating test files**: Always check if `autoupdate_testdata.py`\n    can do it for you.\n3.  **Using `std::string` unnecessarily**: Prefer `llvm::StringRef` for\n    arguments.\n4.  **Header includes**: Use specific include orders (often enforced by\n    `clang-format`).\n5.  **Parse node order**: Semantics processes parse nodes in post-order; ensure\n    your parser transitions support this.\n6.  **Builtin implementation gaps**: If adding a primitive builtin function,\n    make sure you address all phases of the lifecycle: macro definition\n    registration, signature validation, compile-time constant evaluation\n    (interpreter), LLVM IR lowering, and prelude modular implementation bindings\n    (avoiding orphan rules). Refer to the **Builtin functions** skill\n    ([SKILL.md](../builtins/SKILL.md)) for details.\n7.  **Premature helper abstraction**: Avoid extracting tiny helper functions\n    that are called from exactly one place and do not significantly modularize\n    complex code. Prefer inlining directly to keep the implementation compact,\n    readable, and localized.\n8.  **Redundant bounds calculations**: Avoid repeating calculations of complex\n    boundary estimations (such as lower and upper bound estimations). Refactor\n    the logic to calculate unified values once, preserving compactness.\n9.  **Trusting stale `clangd` diagnostics**: In-editor diagnostics are only as\n    good as `compile_commands.json`. If it predates a newly added file, `clangd`\n    falls back to a default command and reports nonsense, such as missing\n    standard headers or \"no member named `None`\". Regenerate it with\n    `./scripts/create_compdb.py`, which only takes a few seconds.\n\n<!-- File: .agents/skills/toolchain_tests/SKILL.md (Tokens: ~1903 | Category: anthropic-skill) -->\n---\nname: Toolchain tests\ndescription:\n    Instructions for authoring, structuring, and running toolchain tests using\n    the file_test infrastructure.\n---\n\n# Toolchain tests\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Introduction\n\nThis skill provides guidelines and patterns for creating and updating tests for\nthe Carbon toolchain, especially file tests in `toolchain/*/testdata/` (for\nexample, `toolchain/check/testdata/`).\n\nToolchain tests evaluate Carbon source files through Lexing, Parsing, Checking,\nand optionally Lowering. Output (for example SemIR dumps, Clang errors) is\ncaptured and validated using inline CHECK records.\n\nLanguage server tests also use `file_test`, but with quite different\nconventions (an LSP message stream, `AUTOUPDATE-SPLIT`, `FROM_FILE_SPLIT`).\nRefer to the **Language server** skill\n([SKILL.md](../language_server/SKILL.md)) for those.\n\n## Structure and Authoring\n\n### File Layout and Headers\n\nTest files must start with the standard Carbon license, followed by\nconfiguration comments. Separate sections with blank comment lines (`//`).\n\n```carbon\n// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/...\n//\n// AUTOUPDATE\n```\n\n-   `// AUTOUPDATE` is mandatory for files using CHECK markers.\n-   `// TIP:` lines are automatically generated by the autoupdater. You do not\n    need to hand-write them. It is harmless to add them, but the script will\n    handle it.\n\n### Minimized Preludes\n\nWhen writing tests entirely unrelated to the Core package, specify a minimal\nprelude file using `// INCLUDE-FILE`. Usually, include\n`toolchain/testing/testdata/min_prelude/` scripts, such as `int.carbon` or\n`primitives.carbon`. This significantly speeds up execution and minimizes STDOUT\nnoise.\n\n-   **Builtin Primitive Testing**: Standard operators (such as `+`, `-`, `/`,\n    `<`, etc.) are **not** imported or available inside minimized preludes. To\n    write tests with a minimal prelude footprint, call primitive builtins\n    directly (e.g., `float.negate`, `float.div`) inside your test code to build\n    expressions.\n\n### Split Tests and `[[@TEST_NAME]]`\n\nA single physical file can test multiple scenarios using split constraints:\n\n```carbon\n// --- passing_case.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// ...\n\n// --- fail_bad_case.carbon\nlibrary \"[[@TEST_NAME]]\";\n// ...\n```\n\n-   **Always** use `library \"[[@TEST_NAME]]\";` in each split rather than\n    hardcoding the library name. This prevents name conflicts, avoids redefining\n    the default library, and keeps the test code clean and templateable.\n-   Exactly `[[@TEST_NAME]]` (including the brackets) must be used. The test\n    infrastructure automatically replaces it with the split's filename minus\n    `todo_` and `fail_` prefixes.\n-   **Do not put code that is expected to pass and code that is expected to fail\n    into the same split.** Validation relies on non-failing splits producing\n    absolutely no errors and failing splits producing the correct compiler\n    errors independently.\n\n### File Prefixing: `fail_` and `todo_`\n\nExpected failures must be differentiated from unexpected failures (and from\nbugs). Include prefixes to name individual split files or the main test:\n\n-   `fail_...`: The test should and does produce compiler errors.\n-   `todo_fail_...`: The test should produce errors but currently does not.\n-   `fail_todo_...`: The test does produce errors or crashes, but it shouldn't\n    (or produces the wrong errors or otherwise misbehaves with errors).\n-   `todo_...`: The test has some incorrect behavior, but doesn't produce errors\n    currently, and shouldn't.\n\n**Main File Naming**: The main test file (and any split-files) must have a\n`fail_` prefix if they have an associated error. **Exception**: The main file\nmay omit `fail_` if it contains a least one split that has a `fail_` prefix.\n\nBoth the `fail_` and `todo_` prefixes are stripped from filename properties like\n`[[@TEST_NAME]]`.\n\n### Constant Evaluation Validation\n\nWhen testing constant evaluation in semantic checker tests, follow these\nconventions to ensure diagnostic stability and accuracy:\n\n-   **Literal Spelling Canonicalization**: In Semantic IR, real literals\n    (floating-point constants) with identical mathematical values can be\n    assigned distinct internal representation identifiers based on spelling\n    variations in source code. To completely prevent literal spelling mismatches\n    in expected output checks, validation tests must be performed using\n    canonical comparison methods (for example, passing converted values through\n    an `Expect(X as f64)` function).\n-   **Generic Parameters Validation**: To bypass compile-time constraints where\n    local runtime variables are rejected as generic function arguments, test\n    generic type conversions at runtime, and validate compile-time conversions\n    by passing static literal values directly into primitive builtin calls.\n-   **Exhaustive Edge Case Verification**: For complex mathematical algorithms\n    (such as floating-point to integer truncation and rounding), map and execute\n    test constraints covering every code branch, conditional exit, and fallback\n    evaluation path.\n-   **Rounding Threshold Boundaries**: Test cases that land extremely close to\n    mathematical boundaries (for example, floating-point literals representing a\n    tiny fraction above 1.0, such as $2^{30} \\times 2^{-30}$ or\n    $10^{10} \\times 10^{-10}$, verifying correct exact truncation down to 1 or\n    0).\n-   **Precise Float Literal Spelling**: Spell floating-point literals in test\n    code with exact mathematical precision targeting target thresholds. For\n    example, if testing the smallest fractional increment above 1.0, use the\n    exact hex fractional representation (e.g. `0x1.0000000000001p0`) or a highly\n    precise decimal fractional spelling (e.g. `1.0000000000000001`) instead of\n    coarse fractions like `1.1` to ensure correct boundary assertions.\n-   **Representation Capacity Boundaries**: Explicitly target edge cases near\n    representation limits of target types. Test combinations of mantissas and\n    exponents that yield values exactly on, just below, or just above the\n    capacity limits of fixed-size destination types (e.g. signed/unsigned\n    targets like `i32` or `u32`).\n-   **Zero-Value Sizing Bounds**: Verify boundary inputs of `0` and `0.0`\n    explicitly. Assert that zero inputs are sized and simplified correctly\n    without triggering calculation underflows, division-by-zero errors, or\n    underestimating required bit allocations.\n\n### Test Code Comments\n\n-   **No agent thinking:** Do not include comments describing your reasoning or\n    \"train of thought\" (for example, \"Wait, but...\") inside the test files. Any\n    comments left in tests should be concise and describe what the test _itself_\n    is validating for human readers.\n\n## SemIR Dumps and Minimizing Output\n\nLimit STDOUT checks to the logic under test. Always use `//@dump-sem-ir-begin`\nand `//@dump-sem-ir-end` around the specific declarations/blocks where SemIR\noutput is desired. Only use these markers and **not**\n`--dump-sem-ir-ranges=if-present` or similar extra args—new tests use\n`//@dump-sem-ir...` to naturally filter output to the highlighted segments based\non the default behavior.\n\n```carbon\n//@dump-sem-ir-begin\nfn F(x:? form(ref i32));\n//@dump-sem-ir-end\n```\n\n## Creating/Updating the Output\n\nAI tools should **never** hand-write or manually touch `// CHECK:STDOUT:` or\n`// CHECK:STDERR:` comments.\n\nWrite your Carbon test code, headers, and `// AUTOUPDATE` then run the test\nupdater:\n\n```bash\n./toolchain/autoupdate_testdata.py toolchain/PATH/TO/YOUR/TEST.carbon\n```\n\nReview the updated test outputs (for example, by way of `git diff`). Ensure\nlogic paths are correctly tested rather than producing massive boilerplate\nblocks.\n\nAutoupdating makes the tests pass whether or not the new behavior is correct, so\ndeciding that the new output is the output you wanted is a separate step. See\nthe [Review testdata changes](../review_testdata_changes/SKILL.md) skill.\n\n<!-- File: github_tools/README.md (Tokens: ~60 | Category: plugin-manifest) -->\n# GitHub\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nScripts for use with GitHub.\n\nSee individual scripts for more details.\n</yakaai_skills>"}