コマンドラインからGitHub issueの本文やコメントを読み取り専用で確認し、URLや番号から対象リポジトリを指定する手順を案内します。
- issueの本文とコメントを読みたいとき
- URLからissueの内容を確認したいとき
- 別リポジトリのissueを参照したいとき
コンパイラのテスト出力差分を、意図した変更と隠れた不具合に分けて確認します。診断メッセージと内部出力を別々に評価し、更新後のテスト結果まで点検する手順を示します。
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.
実行スコア 未検証
インストール方法を見るCarbonのツールチェーンで、// CHECK:STDOUT:や// CHECK:STDERR:の更新差分を判断する手順を示します。自動更新によってテストが通っても、出力が意図した動作を表すとは限りません。差分の各変更に原因を説明できるかを基準に、ユーザーに見える診断メッセージ(STDERR)と、内部表現(STDOUT)を分けて確認します。命令や型、制御フローの変化など構造的な差分には個別の理由を求め、名前の付け替えや位置番号のずれは機械的な変化として見極めます。診断の差分を事前の予測と照らし、更新が収束するまで確認したうえで、テスト実行やファイル名の接頭辞も点検します。
テスト出力の自動更新後に、差分をそのまま受け入れてよいか判断したいときに役立ちます。リファクタリングで予期しない診断変更がないか、内部出力の変化がコード変更に見合っているかをレビューする場面にも向いています。
// CHECK:STDOUT:や// CHECK:STDERR:の行を手で編集して差分を合わせる手順ではありません。確認にはリポジトリのテスト更新手順とテスト実行が関係します。
この紹介文は、公開されている SKILL.md をもとに AI(OpenAI Codex)が作成しました。正確な仕様は下の原文を確認してください。
SKILL.md の記述から、注意が要る操作と導入の前提を AI が確認しました。点数は実際に動かした結果(実行検証)だけで付けています。
点数には入れていません。 2026年10月26日 時点で AI(OpenAI Codex)が判定しました。目安なので、入れる前に原文も確認してください。
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Most toolchain work moves file test output. ./toolchain/autoupdate_testdata.py
rewrites the // CHECK:STDOUT: and // CHECK:STDERR: lines in
toolchain/*/testdata/ to match current behavior, so after running it the tests
pass again whether or not the new behavior is right. Deciding that the new
output is the output you wanted is a separate, manual step, and it is the step
this skill covers.
Three skills divide the work:
[!IMPORTANT] Never hand-edit
// CHECK:STDOUT:or// CHECK:STDERR:lines. Everything below is about changing the code until the generated output is right, never about editing the output to match the code.
Every line of testdata churn must have a cause you can name. Not "it is similar to the other changes", not "the tests pass now" — an actual sentence saying which code change produced it and why that is the intended result.
A diff you cannot narrate is a diff you have not reviewed. Changes you cannot explain are where regressions hide, because a regression and an intended change look exactly alike once the autoupdater has written them down.
[!CAUTION] Autoupdating is destructive to your evidence. Once the autoupdater has run, the previous expectations are gone from the working copy. Read the diff after every autoupdate run, and if something changed for a reason you cannot name, fix the code before autoupdating again. Recovering the old expectations later means reverting and re-running.
Treat them separately; they have different standards of proof.
STDERR is user-visible behavior. These are the diagnostics a Carbon programmer sees. A change here is a change to the language implementation as users experience it, so each one needs an individual justification. For a refactoring, the expected STDERR diff is empty.
STDOUT is internal representation. SemIR dumps, parse trees, LLVM IR. Users never see it. Churn here is normal and often unavoidable, so the standard is not "no change" but "no change I cannot account for".
For a change that is supposed to preserve behavior, write the list of accepted STDERR changes down before you autoupdate, and keep it current. Order matters more than form: written first, the list is a prediction the diff can falsify; written afterwards, it is a description of whatever happened, and describes a regression exactly as well as an intended change.
The list does not have to be a deliverable. Scratch notes you never publish do the job, because the work is in committing to the list, not in presenting it. What a reader needs is not the list but its exceptions: diagnostics that changed without being predicted, and predictions that did not occur. Both are findings. The matches are not, and reporting them buries the two entries that matter.
Sort each STDOUT change into mechanical or structural.
Expected, and cheap to accept in bulk once you have confirmed the pattern:
%x.loc18_46.3 embed a line,
column, and disambiguating index. Two different events move them:
[!TIP] Mechanical churn is usually wide and shallow: the same substitution, repeated across many files. If a "mechanical" pattern needs a different explanation in each file, it is not mechanical.
Each of these needs its own explanation:
[concrete = ...], [symbolic = ...], or other constant-value
annotations.--dump-raw-sem-ir output when you did
not intend to change the id layout.A diff that removes instructions looks like an optimization. Whether it is one depends on what the changed function owes its caller, and two functions can produce the same shrinking diff for opposite reasons:
The instruction count is identical evidence in both cases, so it cannot be the thing you judge. Decide what the function is required to produce; the count follows from that.
The same reasoning runs in reverse: a diff that adds instructions is not automatically a regression.
The fail_ and todo_ prefixes (see
Toolchain tests) say how much the recorded
diagnostics are worth:
fail_... — the test should and does produce errors. The recorded
diagnostic is the specification. Changing it is a user-visible behavior
change and needs justification on its own merits.fail_todo_... — the test produces errors (or crashes) but shouldn't,
or produces the wrong errors. The recorded diagnostic is explicitly not
the specification; the file exists to record that today's behavior is wrong.
Changing it replaces one wrong answer with another. That is acceptable when
you can say why the new message follows from your change and why it is no
further from the intended eventual behavior — which, for many such files, is
no diagnostic at all.todo_fail_... — the test should produce errors but does not. Gaining a
diagnostic here may be progress, not a regression. Either way the file
must be renamed, since the framework requires a fail_ prefix on any file
that errors: fail_... if it now produces the right error, fail_todo_...
if the error is the wrong one. Both renames make the test pass, so record
which case it is instead of letting the rename settle it.todo_... — behavior is wrong but produces no errors, and shouldn't.
Gaining a diagnostic here is a regression unless you can argue otherwise.[!IMPORTANT] This is a reason to look at the filename before judging a diagnostic change, not a license to ignore
todo_files. "It was already broken" does not excuse making it differently broken for no reason.
If your change moves a test between the states above, the prefix must move with
it: when the test is fixed, when it starts failing, and when it starts failing
differently. The correspondence between the fail_ prefix and whether
compilation actually failed is enforced by the test framework, not by the
autoupdater, so it surfaces when you run bazelisk test and not when you
autoupdate. Autoupdating is not a substitute for running the tests.
Only that half of the name is checked. Nothing enforces todo_, so a file whose
behavior you have just fixed can keep its todo_ prefix indefinitely and still
pass. A missing fail_ stops the build; a stale todo_ is silent, and is yours
to catch.
When a fix drops a file's prefix, also check that the file still belongs where it is and that its comments do not still describe the old broken behavior.
When a diagnostic becomes less specific — a general "unsupported" message replacing one that named the problem — that usually means a code path stopped finding information it previously had. Sometimes that is correct: the information was misleading, and the old message was confidently wrong.
Do not accept it silently and do not reject it reflexively. Say which direction it moved and whether the new message is closer to or further from the eventual intended behavior.
If you removed something you believed was doing work and no testdata moved, that is not a missing test run — it is the proof that the thing was a no-op. Say so explicitly; it is one of the strongest pieces of evidence a refactoring can produce.
The converse is also informative. If you expected a path to churn and it didn't, either your model of the code is wrong or that path is untested. Find out which, and consider adding a test before continuing.
Set a rough expectation for the size of the diff before you run the autoupdater, and treat a large mismatch in either direction as a finding.
Editing test input (the Carbon source, not the CHECK lines) to make a diff look better is a behavior change in disguise. Deleting a test that now produces awkward output is worse. If a test's input has to change, that is a separate, explicitly-justified change, not diff cleanup.
NOAUTOUPDATE files. Their expectations are maintained by hand. They
fail under bazelisk test rather than being silently rewritten._test.cpp. When several assertions in one of these break together, often
only the first failure is reported, so fixing it can reveal another. Re-run
until clean rather than assuming one fix was the whole repair.testdata/, and documentation that quotes compiler
output.Autoupdate everything, then read the diff a directory at a time. Passing no paths is the default and updates every file test in the toolchain:
./toolchain/autoupdate_testdata.py
Narrow the scope only while iterating on one subdirectory you know you are not done with, where each round would otherwise regenerate output you have already read:
./toolchain/autoupdate_testdata.py toolchain/check/testdata/SUBDIR/**/*
The globs are expanded by the shell; the script filters its arguments to
.carbon files under a testdata/ directory.
[!TIP] If intermediate states crash on
CARBON_CHECKfailures, pass--non-fatal-checksso you can see the full set of downstream damage in one run instead of one crash at a time.
[!IMPORTANT] Return to the full scope before judging the diff. Whether churn is proportional to the change, and whether a change to one phase moved another phase's testdata, are only visible across everything.
One pass is not always enough, because the autoupdater's output is part of its
own input. // CHECK:STDERR: lines sit inline, immediately above the source
line they describe, and the compiler reads them as comments in the file.
Gaining or losing a diagnostic therefore moves every source line below it.
Within a single run, the compiler has already read the file as it was, so the two kinds of output end up in different states:
[[@LINE+N]], and the autoupdater recomputes N as it
places them.%x.loc18_46.3 embed
an absolute line and column with no filename attached, and the autoupdater
only remaps file.carbon:18-style references. Nothing rewrites the loc,
so it still describes where the instruction was before the diagnostic
lines moved it.Running again compiles the shifted file and the names catch up. The diagnostic set does not change this time, so nothing shifts again and a third run is a no-op. Keep running the autoupdater until it stops changing files: one pass when the diagnostics held still, two when they didn't.
[!WARNING] The intermediate state is self-inconsistent, not just unfinished: its
locnames describe a file layout that no longer exists. Keep reading the diff after every run — that rule does not change — but do not chase positional churn to a cause until the file has converged, and do not present the diff until then either.
The converging pass should be positional renumbering and nothing else. If it
moves an instruction, a type, or a constant value, then something other than a
loc name is sensitive to where lines fall in the file. Find out what before
accepting it.
The file tests do catch a file left unconverged, since each test re-runs the
autoupdate in memory and fails with
Autoupdate would make changes to the file content when the result differs. But
that arrives at bazelisk test time, after you have already read a diff that
was describing a file which had moved out from under it.
Inspect the diagnostics first, since that is the acceptance criterion:
# STDERR-only view, with jj.
jj --no-pager diff --git 'glob:toolchain/*/testdata/**' \
| grep -E '^[-+].*CHECK:STDERR'
# The same, with git.
git diff -- 'toolchain/*/testdata/*' \
| grep -E '^[-+].*CHECK:STDERR'
For a structured view separating test input, STDERR, and STDOUT changes, use the helper from the Summarize testdata changes skill:
jj --no-pager diff --git 'glob:toolchain/*/testdata/**' \
| python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py
git diff -- 'toolchain/*/testdata/*' \
| python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py
The argument after the tool name is not interchangeable: glob:... is a jj
fileset, -- ... is a git pathspec. --git and --no-pager are jj flags; git
already emits this format and skips the pager when piped.
Then run the tests, which is what catches prefix mismatches and non-autoupdated expectations:
bazelisk test //toolchain/...
See the Bazel usage skill.
Before presenting a testdata diff as finished:
loc
name describes a stale line numbering.まだレビューはありません。使ってみた感想をお寄せください。
ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。
まだコメントはありません。最初のコメントを書いてみませんか。
コマンドラインからGitHub issueの本文やコメントを読み取り専用で確認し、URLや番号から対象リポジトリを指定する手順を案内します。
AIアシスタントがCarbonのコードベースを扱う際に、専用ツールでファイルを閲覧・検索・編集し、一時ファイルを管理するためのルールを示します。
Bazeliskを使ったCarbonプロジェクトのビルド、テスト、実行、デバッグの基本手順を確認し、対象を絞った検証やASanの利用方法も把握できます。
Carbonコンパイラに組み込み関数を追加する際の登録、型シグネチャ検証、定数評価、LLVMコード生成、テスト方法を案内します。
Carbonツールチェーンのコードを書く際に、言語ごとの整形方法やコメント、命名、ドキュメント、コミットメッセージの基準を確認できます。
Carbonコンパイラのエラーや警告を定義し、書式やソース位置のラベルを整え、テストで網羅性を確かめる方法を案内します。