bulldogger 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90b1681b42b715c3a8c90836ae9fe8c2378d15fb542b014512ad9cbab6451089
4
- data.tar.gz: 9535ac4a1206eb1dd91bef0170abf2d7d877ac4a18257dd47faafb15c4bcfa71
3
+ metadata.gz: 5fd076d39e5f2dcaf2d18cd10c8863a406ec9cc06f37874bcf85e5e4dcb22020
4
+ data.tar.gz: d966b9455420d78ac41a8cbc84354b3ae3d674bb89f419a1ba4890ba6b07d52b
5
5
  SHA512:
6
- metadata.gz: 042df51e319ebf9d8057d2f9125cffdd8437c6b3898e1ee5d450c33be21bec3d1218321f2256e0ea5cd51d4f9c1c73d9350e2fcfb2a40424ac7deb8d627df473
7
- data.tar.gz: 27e433a4e256a55150270aa5448a8fb9ee06d378a1e528236d63b5f558016e04724cf574382ae64b9730f878deb3e3d5b49f3825b9ba4865de0f40ff86f93b1c
6
+ metadata.gz: f152d7d4d1c4d3be122dfaa37db861661102f89aac9eb0636e8c142b91853aceacab4132a0709454f1231adec64a327b32a3b94a759fce2d74102541fd130b1b
7
+ data.tar.gz: 978f85bc4b6dd7bde8bd5c2f040780d612d5574ea322ca9148cac04faaac3d3cd670ce94fc84d7545d627804d780b45af040e9af71fbf293ec28aebe3947afc1
data/CHANGELOG.md ADDED
@@ -0,0 +1,70 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0
4
+
5
+ ### A failing test now leads to the value that caused it
6
+
7
+ `0.1.0` could not do that for the most ordinary failure there is. When an
8
+ assertion fails, the method that produced the wrong value has already
9
+ returned, so the snapshot held the test framework and the test body and no
10
+ application code. Measured against two real gems, it found nothing.
11
+
12
+ - **replay**: bulldogger re-runs the one failing test in a child process
13
+ under full recording, and the trace holds the producing call with its
14
+ arguments and its return. The child keeps the parent suite's result
15
+ untouched, and a green run replays nothing. Evidence gains `replay` and
16
+ `replay_reproduced`.
17
+ - **Replay runs only when it can add something.** A propagating exception
18
+ leaves the raising method on the stack with its locals, so the snapshot
19
+ already answers and no second run happens. Evidence records that choice
20
+ in `replay_skipped_reason` rather than staying silent. `replay_on_failure`
21
+ accepts `true`, `:always`, and `false`; `BULLDOGGER_REPLAY` accepts `0`,
22
+ `1`, and `always`.
23
+ - **The failure output says which file to read and why.** The line worth
24
+ opening carries a short clause, so the first step needs nothing else.
25
+ Four states each say what they hold, including a replay whose child
26
+ passed, which shows a passing run rather than the failure.
27
+
28
+ ### Running bulldogger over its own suite
29
+
30
+ - **`Bulldogger::Instance`** separates the observing tool from the subject
31
+ under test. A single module singleton could not be both, because a suite's
32
+ own setup resets bulldogger for test isolation and destroyed any outer
33
+ observer. The module now delegates to a default instance, and
34
+ `Bulldogger::Minitest.instance=` and `Bulldogger::RSpec.instance=` accept
35
+ another one.
36
+ - `rake dogfood` covers the unit suite as well as acceptance.
37
+
38
+ ### Reaching the skill
39
+
40
+ - **`exe/bulldogger`** answers two questions: `skill path` prints the
41
+ location of the skill shipped with the installed gem, and `version` prints
42
+ the version.
43
+ - Evidence, probe evidence, and record headers carry a `skill` key holding
44
+ that path. The key is omitted when the file is absent, because a path that
45
+ does not resolve costs a reader more than a missing one.
46
+ - The skill teaches what the files cannot: that an absent local means the run
47
+ could not see it, that a probe reporting zero calls was blind rather than
48
+ idle, and how to walk a trace from a symptom down to the value's origin.
49
+
50
+ ### Cost
51
+
52
+ - Redaction matches one union pattern instead of nine separate ones, which
53
+ took value capture from about 41x to between 34x and 37x. Redaction was
54
+ about half the cost of serializing one local, and almost no name matches
55
+ any pattern.
56
+
57
+ ### Documentation
58
+
59
+ - `README.ja.md` translates the README. `README.md` stays the source of the
60
+ claims.
61
+ - `docs/design-decisions.md` records the observation limits found while
62
+ building this: `Coverage` cannot see lines under a `TracePoint` callback,
63
+ and neither can a probe, which is why bulldogger cannot probe its own
64
+ serialization path.
65
+
66
+ ## 0.1.0
67
+
68
+ First release. A failing Ruby test writes a JSON snapshot of its own failure
69
+ and names the file in its output, with `probe` and `record` as explicit verbs
70
+ for targeted and full observation.
data/README.ja.md ADDED
@@ -0,0 +1,383 @@
1
+ # bulldogger
2
+
3
+ このファイルは `README.md` の翻訳であり、内容が一致しない場合は `README.md` を正とします。
4
+
5
+ bulldogger は Ruby のテスト失敗を、コーディングエージェント向けの構造化された証拠として書き出します。
6
+ 各 JSON ファイルには、例外、バックトレース、取得したフレームの値が含まれます。
7
+ 失敗出力には、そのファイルの絶対パスが示されます。
8
+
9
+ 開発と計測には Ruby 4.0.6 と debug 1.11.1 を使用しました。
10
+ bulldogger 0.2.0 では独立したインスタンスを追加し、ドッグフーディングをユニットテストスイートまで拡張しました。
11
+
12
+ ## インストール
13
+
14
+ テストグループに両方の gem を追加します。
15
+
16
+ ```ruby
17
+ gem "bulldogger", group: :test
18
+ gem "debug", group: :test
19
+ ```
20
+
21
+ `debug` gem は `DEBUGGER__.capture_frames` を提供し、bulldogger は各フレームのローカル変数を取得できます。
22
+ Ruby は `debug` を bundled gem として配布しています。
23
+ Bundler はアプリケーションの Gemfile に `debug` が含まれる場合に限って、この gem を利用可能にします。
24
+
25
+ `debug` がない場合、bulldogger は例外が発生したフレームのローカル変数を記録します。
26
+ 残りのフレームについては、ファイル、行、ラベルのデータを記録します。
27
+
28
+ デフォルトブランチからエージェントホストへ skill をインストールします。
29
+
30
+ ```sh
31
+ gh skill install meganemura/bulldogger
32
+ ```
33
+
34
+ バージョンをそろえる必要がある場合は、インストール済みの gem と一致するコピーを使います。
35
+
36
+ ```sh
37
+ bulldogger skill path
38
+ ```
39
+
40
+ 最初のコマンドはエージェントホストに skill をインストールし、2 番目のコマンドは一致する gem 内のコピーを表示します。
41
+
42
+ CLI には次のサブコマンドがあります。
43
+
44
+ ```text
45
+ bulldogger skill path
46
+ bulldogger version
47
+ bulldogger --version
48
+ ```
49
+
50
+ フレームワーク用のエントリーポイントを 1 つ追加します。
51
+
52
+ Minitest では、次の行を `test_helper.rb` に追加します。
53
+
54
+ ```ruby
55
+ require "bulldogger/minitest"
56
+ ```
57
+
58
+ RSpec では、次の行を `spec_helper.rb` に追加します。
59
+
60
+ ```ruby
61
+ require "bulldogger/rspec"
62
+ ```
63
+
64
+ 各エントリーポイントは取得を開始し、失敗した各テストを記録します。
65
+ テストスイートが終了すると、実行インデックスを完成させます。
66
+
67
+ ## 独立したインスタンスの使用
68
+
69
+ `Bulldogger` モジュールは API を `Bulldogger.default` に委譲します。
70
+ `Bulldogger.start` や `Bulldogger.probe` などの既存の呼び出しは、このデフォルトインスタンスを使います。
71
+
72
+ 2 つの取得ライフサイクルを同時に動かす必要がある場合は、別のインスタンスを作成します。
73
+
74
+ ```ruby
75
+ observer = Bulldogger::Instance.new
76
+ observer.start
77
+ ```
78
+
79
+ 各インスタンスは、設定、取得の購読、実行、証拠の状態を所有します。
80
+ モジュールのファサードが提供する失敗、probe、record、SQLite 変換の各メソッドも利用できます。
81
+
82
+ インテグレーションには、デフォルトの代わりに指定したインスタンスを使えます。
83
+
84
+ ```ruby
85
+ Bulldogger::Minitest.instance = observer
86
+ Bulldogger::RSpec.instance = observer
87
+ ```
88
+
89
+ テストスイートが始まる前にインスタンスを指定します。
90
+ この分離により、テストのセットアップがデフォルトインスタンスを置き換えても、外側のオブザーバーは動作を続けられます。
91
+
92
+ ## 3 つの方法
93
+
94
+ bulldogger は、実行時の証拠を収集する 3 つの方法を提供します。
95
+
96
+ - 失敗スナップショットがデフォルトです。例外が発生しない green テストではデータを取得しません。伝播した例外については、フレームとローカル変数から答えを得られます。アサーションではアプリケーションの呼び出しがすでに戻っているため、bulldogger は完全な記録のもとでテストを 1 回リプレイします。
97
+ - `probe` は、明示的な 1 回の実行中に指定したメソッドを監視します。
98
+ - `record` は、明示的な 1 回の実行中にすべての Ruby メソッド呼び出しをトレースします。
99
+
100
+ 失敗したテストが証拠のパスをすでに示している場合は、失敗スナップショットを使います。
101
+ 1 つのメソッドを調べる場合や、変更の前後で動作を比較する場合は `probe` を使います。
102
+ 呼び出しシーケンス全体を追う必要がある場合は `record` を使います。
103
+
104
+ ## 失敗出力
105
+
106
+ 次のコマンドから、この出力を得ました。
107
+
108
+ ```sh
109
+ bundle exec ruby -Ilib test/fixtures/minitest_red/red_test.rb
110
+ ```
111
+
112
+ ```text
113
+ 1) Error:
114
+ RedTest#test_deep_raise:
115
+ ArgumentError: expected 3 to equal the sum of [1, 2, 3]
116
+ test/fixtures/minitest_red/app.rb:9:in 'Order.total'
117
+ test/fixtures/minitest_red/red_test.rb:20:in 'RedTest#test_deep_raise'
118
+ bulldogger evidence: /home/you/project/tmp/bulldogger/run-20260829-100406-58231/001-RedTest-test_deep_raise.json (raising method is in these frames)
119
+ ```
120
+
121
+ 括弧内の案内がある行のパスを開きます。
122
+ このファイルには、1 件の失敗と取得した実行時の値が含まれます。
123
+ この伝播した例外の証拠ファイルには `replay_skipped_reason: "application_frame_available"` があり、`Order.total` フレームにアプリケーションのローカル変数が含まれるため、リプレイは実行されませんでした。
124
+
125
+ 失敗に対してリプレイを実行すると、`bulldogger replay:` 行が表示されます。
126
+ 括弧内の説明は、再現した失敗または成功したリプレイを示します。
127
+ 規則、設定、副作用については、[失敗したテストのリプレイ](#失敗したテストのリプレイ)を参照してください。
128
+
129
+ 各実行では次の配置を使います。
130
+
131
+ ```text
132
+ tmp/bulldogger/
133
+ latest -> run-20260829-100406-58231
134
+ run-20260829-100406-58231/
135
+ 001-RedTest-test_deep_raise.json
136
+ 002-RedTest-test_assertion_failure.json
137
+ trace-001.jsonl
138
+ index.json
139
+ ```
140
+
141
+ [`bulldogger` skill](skills/bulldogger/SKILL.md) は、エージェントがこれらのファイルを調べる方法を説明します。
142
+ [証拠スキーマ](docs/evidence-schema.md)は、すべてのフィールドと取得モードを定義します。
143
+
144
+ ## 失敗したテストのリプレイ
145
+
146
+ アサーションが例外を発生させる時点では、テスト対象のコードはすでに戻っています。
147
+ この場合、失敗スナップショットにはテストフレームワークとテスト本体が含まれ、アプリケーションのフレームは含まれません。
148
+ フレーム数を増やしても役に立たず、誤った値を生成した呼び出しはすでにスタックから外れています。
149
+
150
+ bulldogger は完全な記録のもとで失敗したテスト 1 件を再実行し、その値に到達します。
151
+ 例外の形は異なり、例外の伝播中はアプリケーションコードがスタックに残ります。
152
+ スナップショットにコードとローカル変数がすでに含まれるため、bulldogger はリプレイを省略します。
153
+
154
+ デフォルトの規則は、テストファイル外にあるアプリケーションフレームを数えます。
155
+ そのフレームが 0 件ならリプレイし、1 件以上なら `replay_skipped_reason: "application_frame_available"` を付けて省略します。
156
+ この理由があり `replay` キーがない場合、フレームから答えを得られます。
157
+
158
+ リプレイは子プロセスで動くため、親テストスイートの結果は変わりません。
159
+ green の実行ではリプレイを行わないため、green のときにコストがないという特性も保たれます。
160
+ 追加コストはアサーション型の失敗後に限って発生し、デフォルトでは分離されたプロセスで 1 回だけ実行します。
161
+
162
+ 証拠には、トレースの絶対パスを持つ `replay` キーが追加されます。
163
+ さらに `replay_reproduced` キーも追加されます。
164
+ 子プロセスが失敗終了するとこのキーは `true` になり、成功すると `false` になります。
165
+ `false` は、その失敗が単独では再現しなかったことを示します。
166
+ 通常は、実行順序や別のテストとの共有状態に依存するテストを示唆します。
167
+
168
+ 失敗出力は、有用な実行時データを含むファイルを示します。
169
+
170
+ ```text
171
+ bulldogger evidence: /abs/path/evidence.json
172
+ bulldogger replay: /abs/path/trace.jsonl (value was produced before the assertion raised)
173
+ ```
174
+
175
+ 成功したリプレイでは `(test passed alone; this trace shows the passing run)` を使います。
176
+ リプレイを実行できない場合、証拠の行は値の生成元がフレームにないことを示します。
177
+ リプレイが無効な場合、証拠の括弧内には `BULLDOGGER_REPLAY=1` も示されます。
178
+ 取得に失敗した場合、スナップショットにフレームがないことを示します。
179
+
180
+ リプレイの設定は次のとおりです。
181
+
182
+ | 属性 | デフォルト | 効果 |
183
+ |---|---|---|
184
+ | `replay_on_failure` | `true` | テストファイル外のアプリケーションコードをフレームが含まない場合にリプレイします。`:always` はすべての失敗をリプレイします。`false` はリプレイしません。 |
185
+ | `max_replays` | `1` | 1 回の実行に対するリプレイ数を制限します。 |
186
+ | `replay_timeout` | `60` | bulldogger がリプレイの子プロセスを中止するまでの秒数です。中止したリプレイは `replay` キーも `replay_reproduced` キーも書きません。 |
187
+
188
+ デフォルトの規則は、リプレイするテストを絞ります。
189
+ リプレイしたテストは、ファイル書き込み、外部リクエスト、サンドボックスアカウントの変更などの各副作用を再度実行します。
190
+ 1 つのプロセスでリプレイを無効にするには `BULLDOGGER_REPLAY=0` を設定します。
191
+ すべての失敗をリプレイするには `BULLDOGGER_REPLAY=always` を設定します。
192
+ アプリケーションで同じ方針を設定するには、`config.replay_on_failure` に `false` または `:always` を指定します。
193
+ `BULLDOGGER_MAX_REPLAYS` は上限を上書きします。
194
+ `BULLDOGGER_DISABLE=1` は、ほかのすべての取得とともにリプレイも無効にします。
195
+
196
+ [リプレイのリファレンス](skills/bulldogger/references/replay.md)は、エージェントがトレースを値の生成元まで絞り込む方法を説明します。
197
+ [トレーススキーマ](docs/trace-schema.md)は、リプレイトレースが持つイベントフィールドを定義します。
198
+
199
+ ## probe によるメソッドの指定
200
+
201
+ 対象名を指定し、関連するテストまたは処理を囲みます。
202
+
203
+ ```ruby
204
+ before_path = Bulldogger.probe("Billing::Invoice#amount") do
205
+ run_related_test
206
+ end
207
+ ```
208
+
209
+ 証拠は、引数と戻り値のクラス、`nil` 値、例外による終了、呼び出し元を要約します。
210
+ デフォルトでは最初の 10 サンプルをシリアライズし、すべての呼び出しを数えます。
211
+
212
+ 変更の前後で probe を実行し、2 つのファイルを比較します。
213
+
214
+ ```ruby
215
+ result = Bulldogger.probe_compare(before_path, after_path)
216
+ result.fetch("identical")
217
+ ```
218
+
219
+ `identical` の値が `true` なら、比較した動作は同じです。
220
+ 比較の対象は、呼び出し回数、クラス、`nil` の数、例外による終了、パラメーター、呼び出し元、正規化したサンプルです。
221
+
222
+ 次の抜粋は、生成した probe ファイルから得ました。
223
+
224
+ ```json
225
+ {
226
+ "kind": "probe",
227
+ "targets": ["ProseSample#amount"],
228
+ "methods": {
229
+ "ProseSample#amount": {
230
+ "calls": 3,
231
+ "raised_exits": 1,
232
+ "returns": {
233
+ "classes": {"Integer": 1, "NilClass": 1},
234
+ "nil_count": 1,
235
+ "samples": [{"value": "21"}, {"value": "nil"}]
236
+ },
237
+ "raised": {"ArgumentError": 1},
238
+ "callers": {"-e:1:in 'block in <main>'": 3}
239
+ }
240
+ },
241
+ "limits": {"max_samples": 10, "max_value_length": 200}
242
+ }
243
+ ```
244
+
245
+ ## 呼び出しシーケンスの記録
246
+
247
+ 完全な呼び出しシーケンスが必要な場合は、対象を絞った 1 つの処理を囲みます。
248
+
249
+ ```ruby
250
+ trace_path = Bulldogger.record do
251
+ run_related_test
252
+ end
253
+ ```
254
+
255
+ 結果は JSONL ファイルであり、ヘッダーと call、return、raise の各イベントに対応するオブジェクトを含みます。
256
+ 次の抜粋は、生成したトレースから得ました。
257
+
258
+ ```jsonl
259
+ {"schema_version":1,"kind":"record","events":["call","return","raise"],"limits":{"max_value_length":200}}
260
+ {"event":"call","seq":1,"depth":1,"path":"-e","line":1,"method":"ProseTrace#outer","args":{"value":{"value":"3"}}}
261
+ {"event":"return","seq":4,"depth":1,"path":"-e","line":1,"method":"ProseTrace#outer","return":{"value":"6"}}
262
+ {"event":"raise","seq":7,"depth":2,"path":"-e","line":1,"method":"ProseTrace#inner","exception":{"class":"ArgumentError","message":"negative"}}
263
+ {"event":"return","seq":8,"depth":2,"path":"-e","line":1,"method":"ProseTrace#inner","raised":true}
264
+ ```
265
+
266
+ [トレーススキーマ](docs/trace-schema.md)は、イベントフィールドと検証済みの `jq` クエリーを定義します。
267
+
268
+ JSONL が主要な記録形式です。
269
+ `sqlite3` gem が利用できる場合、`Bulldogger.trace_to_sqlite(trace_path, db_path)` は既存のトレースを変換します。
270
+ 変換処理は soft require を使うため、bulldogger の実行時依存関係は 0 件のままです。
271
+
272
+ ## コスト
273
+
274
+ `TracePoint(:raise)` は、アプリケーションコードが rescue する例外を含む、発生したすべての例外を監視します。
275
+ この計測には Ruby 4.0.6 を使用しました。
276
+ 各条件を 3 回実行し、表には各中央値を示します。
277
+
278
+ | 条件 | bulldogger なし | bulldogger あり | 比率 |
279
+ |---|---:|---:|---:|
280
+ | 例外が発生しない 2,000,000 回の no-op 反復 | 0.0423s | 0.0424s | 1.00x |
281
+ | 10,000 回の raise と rescue | 0.0055s | 0.4468s | 81.14x |
282
+ | ファイル出力を伴う 200 件の失敗記録 | 0.0001s | 0.0277s | 413.58x |
283
+
284
+ この計測では、2 番目の条件で例外 1 件あたり 44.126 microseconds かかりました。
285
+
286
+ 取得コストの内訳を次に示します。
287
+
288
+ | 段階 | 例外 1 件あたりの追加コスト |
289
+ |---|---:|
290
+ | `TracePoint(:raise)` を購読 | 0.136 microseconds |
291
+ | `DEBUGGER__.capture_frames` を呼び出し | 1.288 microseconds |
292
+ | シリアライズ、秘匿、リングへの挿入 | 23.220 microseconds |
293
+
294
+ この計測ではフレーム取得のコストは小さく、その後の処理が計測コストの大部分を占めます。
295
+
296
+ このテストでは、例外が発生しない green のテストスイートに計測可能なオーバーヘッドはありませんでした。
297
+ green のテストスイートでも例外を発生させて rescue する場合があり、その各例外には取得コストがかかります。
298
+
299
+ ### 明示的な動詞のコスト
300
+
301
+ 比例関係の計測ハーネスでは、両方の動詞に 1 つのアプリケーションフィクスチャを使いました。
302
+ `probe` では対象メソッドの呼び出し 1 回あたり 1461.5 ns を計測しました。
303
+ `record` ではトレース対象の呼び出し 1 回あたり 4249.5 ns を計測しました。
304
+
305
+ `probe` のコストは対象メソッドの呼び出し数に比例し、計測ハーネスではその数を M と呼びます。
306
+ `record` のコストはトレース対象の全呼び出し数に比例し、計測ハーネスではその数を N と呼びます。
307
+ M/N が 0.25 のとき、このフィクスチャでは `probe` が 8.70x、`record` が 104.93x でした。
308
+ これらの比率はこのアプリケーションフィクスチャに対する値であり、別のアプリケーションでは M/N の値が異なります。
309
+
310
+ record 専用の計測ハーネスでは、値の取得が 36.19x でした。
311
+ JSONL への書き込みを含む完全な処理は 54.72x でした。
312
+ 同じ機械で繰り返し計測すると、値の取得は 34x から 37x、完全な処理は 48x から 55x の範囲に収まりました。
313
+ これらの数値は定数ではなく範囲として読んでください。
314
+
315
+ `probe` と `record` は、変更の前後に対象を絞って 1 回実行する明示的な動詞です。
316
+ テストスイート全体へ継続的に適用しないでください。
317
+
318
+ ## bulldogger の無効化
319
+
320
+ 1 つのテストプロセスで取得と出力を無効にするには、`BULLDOGGER_DISABLE=1` を設定します。
321
+ `BULLDOGGER_DISABLED=1` は同じ動作をする別名です。
322
+
323
+ どちらかのスイッチを使うと、起動処理は `TracePoint(:raise)` の購読前に戻ります。
324
+ 証拠を書かず、実行ディレクトリを作らず、失敗に証拠の行を追加しません。
325
+ リプレイは、このスイッチが省略する証拠処理から始まるため、実行されません。
326
+ テストの終了コードと失敗数は変わりません。
327
+ 受け入れテストは、Minitest と RSpec についてこの動作を確認しています。
328
+
329
+ rescue を多用する green のテストスイートでは、bulldogger を無効にした状態で 1.00x を計測しました。
330
+
331
+ ## 環境変数
332
+
333
+ 次の環境変数は、子テストプロセスを設定します。
334
+
335
+ | 変数 | 受け付ける値 | デフォルトと効果 |
336
+ |---|---|---|
337
+ | `BULLDOGGER_DISABLE` | `1` | デフォルトでは取得が有効です。`1` は取得と出力を無効にします。 |
338
+ | `BULLDOGGER_DISABLED` | `1` | `BULLDOGGER_DISABLE` の別名です。 |
339
+ | `BULLDOGGER_OUTPUT_DIR` | 空でないパス | デフォルトは作業ディレクトリからの相対パス `tmp/bulldogger` です。 |
340
+ | `BULLDOGGER_FRAME_SOURCE` | `capture_frames` または `degraded` | デフォルトでは自動選択します。 |
341
+ | `BULLDOGGER_REPLAY` | `0`、`1`、または `always` | デフォルトは `1` です。フレームから答えを得られない場合にリプレイします。`0` はリプレイを無効にします。`always` はすべての失敗をリプレイします。 |
342
+ | `BULLDOGGER_MAX_REPLAYS` | 整数 | 1 回の実行に対するリプレイ数 `max_replays` を上書きします。デフォルトは `1` です。 |
343
+
344
+ ## シークレットと上限
345
+
346
+ 取得した値にはシークレットが含まれる可能性があります。
347
+ bulldogger は値に対して `inspect` を呼ぶ前に、各ローカル変数名を検査します。
348
+ 一致するローカル変数は `{"redacted": true, "reason": "name"}` となり、`value` フィールドを持ちません。
349
+
350
+ デフォルトのパターンは、大文字と小文字を区別せずに次の名前と一致します。
351
+
352
+ - `password`、`passwd`、`pass`
353
+ - `secret`、`token`
354
+ - `api_key`、`api-key`
355
+ - 単語としての `key`
356
+ - `credential`、`auth`、`session`、`cookie`
357
+
358
+ 名前が曖昧な場合、パターンは秘匿する側へ寄せます。
359
+ たとえば `/auth/i` は `author` と `authorized` にも一致します。
360
+ アプリケーションは `Bulldogger.config.redact_patterns` を独自の正規表現で置き換えられます。
361
+ Bulldogger は redactor を構築するときに、これらのパターンを 1 つの union にコンパイルします。
362
+ 元の配列をその場で変更しても、既存の redactor は変わりません。
363
+ そのパターンを使う取得またはトレースのセッションを Bulldogger が構築する前に、新しいパターン配列を割り当てます。
364
+
365
+ bulldogger は Hash をレンダリングするときにキーも検査します。
366
+ 一致するキーのレンダリング値は文字列 `"[REDACTED]"` になります。
367
+
368
+ デフォルトでは 20 フレームと、各フレームの 50 ローカル変数を保持します。
369
+ レンダリングした各値は 200 文字を保持し、各 Array または Hash は 10 要素を保持します。
370
+ 証拠ファイルは、省略または切り詰めたデータを示します。
371
+
372
+ ## バージョン 0.2 の範囲
373
+
374
+ Version 0.2 は、失敗スナップショット、失敗時の自動リプレイ、対象を指定した probe、明示的な完全記録、独立したインスタンスを提供します。
375
+ JSON の証拠と JSONL のトレースを書き出します。
376
+ Version 0.2 の境界は、ファイル成果物とオフラインの SQLite 変換機能を公開します。
377
+
378
+ [設計判断](docs/design-decisions.md)は、3 つの方法と計測コストを説明します。
379
+
380
+ ## ライセンス
381
+
382
+ MIT です。
383
+ `LICENSE` を参照してください。