Skip to content

feat: RTT 結果バーに log スケールモードを追加#14

Merged
yuu61 merged 9 commits into
masterfrom
feature/rtt-log-scale
Jun 13, 2026
Merged

feat: RTT 結果バーに log スケールモードを追加#14
yuu61 merged 9 commits into
masterfrom
feature/rtt-log-scale

Conversation

@yuu61

@yuu61 yuu61 commented Jun 13, 2026

Copy link
Copy Markdown
Owner

概要

RTT 結果バー(▁▂▃▄▅▆▇█)に opt-in の対数スケールモードを追加します。既存の線形スケールは完全に保存し、デフォルトの挙動は変わりません。

実デプロイでは RTT が 0.012ms(LAN)〜15ms(WAN/インターネット)と桁をまたいで混在し、線形スケールでは低 RTT 帯が全部最下段 に潰れて差が見えません。対数モードはこれを 1 本のバーに収めます。

使い方

  • l キー … 対数係数を巡回 lin → xe → xe2 → lin(線形 / 底 e / 底 e²)
  • ↑/↓ … スケール値を増減。はしごを sub-ms まで拡張(0.01〜100ms)。対数モードではこの値が窓の floor(左端)として効く
  • -s / scale ディレクティブ小数を受理(例 -s 0.5scale 0.5

ヘッダ表示は線形が RTT Scale 10ms、対数が RTT floor 10ms xe(係数ラベルは底 e が xe、底 e² が xe2)。

契約変更(README 同時更新済み)

  • -s/--scale が小数可に(後方互換の拡張: 既存の整数指定はそのまま動作)
  • 新しい l キーバインド
  • リロード(SIGHUP / R)でスケール・対数係数・精度を保持

設計上の要点

  • 対数バケッティング: step = ln(rtt/scale) / lnBase[0,7] にクランプ。線形と同一の左閉・半開区間規約。境界の浮動小数誤差は index 空間で boundaryEpsilon を加算して補正(barForStep 内に集約)。
  • 係数テーブルはデータ駆動: logFactors{Label, LnBase} の named type。スライス添字ではなく LnBase(ln 除数)を値として持つので、底10 など非 e^n の係数も 1 行追加で済む。
  • 失敗は Result.Code で表現X/t/s)— 対数モードでも不変。
  • グリフ=1桁・ASCII ラベル: 係数ラベルは ASCII(xe/xe2)。×e/×e² の East-Asian-Ambiguous 文字は CJK 端末で2セル描画され桁ずれを起こすため不採用(主要4 OS の標準等幅フォント調査で、(U+212F) が全 OS で欠落・上付き文字も曖昧幅で崩れることを確認済み)。

レビュー対応

3 ラウンドのコードレビューを反映:

  1. 線形境界補正・scaleDown クランプ・CLI Inf ガード
  2. 凡例ラベルの ambiguous 幅 ASCII 化・scale 検証を config.ValidScale に集約
  3. /code-review ultra(xhigh): logFactors をデータ駆動化(添字≠除数の暗黙契約を解消)・既定値/述語の単一情報源化(config.DefaultScaleresolveScale の cfg 側も ValidScale)・doc/protocol 整理

検証

  • make check 全通過(tidy-check / fmt-check / vet / lint / test)
  • make test-race 通過
  • 新規テスト: 対数バケッティング・境界安定性・線形境界 epsilon 回帰・失敗コード pass-through・リロード保持

yuu61 added 5 commits June 12, 2026 17:58
l キーで log 係数を off→e→e² と巡回し、log モードでは ↑/↓ の scale 値を
対数窓の floor(左端)として使う。scale を int→float64 化してサブミリ秒
スケール(0.01ms〜)に対応し、↑/↓ のラダーを sub-ms まで拡張した。

- monitor: Glyph/rttGlyph に logK 引数を追加。段=floor(ln(rtt/floor)/logK)
  を [0,7] にクランプし、linear と同じ左閉・半開の境界規約にそろえる。境界
  の浮動小数落ちは index 空間の epsilon で補正し、float ドメインで clamp して
  から int 変換(gosec G115 を nolint なしの実ガードで解消)
- config/cli: scale ディレクティブと -s/--scale を float64 化(小数受理、
  lenient 維持+Inf ガード)
- tui: l キーで logK 巡回・凡例に (l)og[lin/×e/×e²]・リロードで logK 保持
- README: -s 小数可・l キー・log モードを利用者契約として記載

linear(logK=0)の挙動は完全保存。make fmt/vet/lint/test/test-race 全通過。
マルチエージェント / codex レビューで挙がった実バグと契約の不備を修正。

実バグ:
- 線形バケットに浮動小数の境界補正が無く、小数スケールで帯境界ちょうどの RTT が
  1 段低く描画されていた(rttGlyph(0.3,0.1)→▃)。rttGlyph を linear/log 統一の
  step 計算にして boundaryEpsilon を両モードへ適用し、clamp を barForStep に集約。
  線形境界テストを epsilon の実効回帰ガードにした
- scaleDown が下限ラング未満で増加していた(-s 0.005 で ↓ が 0.01 に倍増)。
  scaleUp の上端ガードの鏡像として cur を保持
- CLI の -s Inf が resolveScale を通過し全バーをフラットラインさせていた。config
  側と同じ math.IsInf ガードを CLI 値にも適用

表示 / 契約:
- log モードでヘッダを "RTT floor 10ms ×e" に変更(floor の意味を明示し、係数を
  前方表示して 80 桁端末でのクリップを回避)。凡例は (l)og に簡略
- logModes 定数 + logLabel の switch を logFactors テーブル 1 本に統合
- README の対数窓の桁数を約 3.0/6.1 桁に訂正(7 段 = e^7/e^14)

テスト追加:
- 線形境界の epsilon 回帰ガード、l キー巡回・凡例・View 経路の logK 受け渡し・
  リロード保持、config の scale inf/nan、resolveScale の非有限値

make fmt/vet/lint/test/test-race 全通過。
claude code review のマージブロッカーと低 severity 指摘に対応。

マージブロッカー:
- log モードの係数ラベル ×e/×e²(U+00D7/U+00B2)は East Asian Ambiguous 幅で、
  日本語端末では 2 セル描画されて keysLine がレンダラの計算幅とずれ、画面が崩れる。
  ASCII の xe/xe2 に変更(README・テストも追従、終端 '.' で厳密照合)

その他:
- scale の妥当性判定(>0 かつ有限)を config.ValidScale に集約。scaleDirective・
  resolveScale・tui.New の 3 箇所のドリフトを防止(main の math 依存を解消)
- tui.New が Options.Scale を正規化(resolveScale を介さない呼び出しで退化値が
  全バーを ▁ にするのを防ぐ、Cols と同様)
- logFactors のコメントに「添字 == logK == e の指数」契約と ASCII 制約を明記
- scale フィールドの doc に log モードでの floor 転用を追記(3 ファイル)
- TestResolveScale に NaN ケース、リロード保持テストを終端照合に強化

make fmt/vet/lint/test/test-race 全通過。
/code-review ultra(xhigh) の確認済み指摘のうち correctness/cleanup/doc を対応。
意図的と裁定された 3 件(テスト重複・adjustRTTScale 二重ディスパッチ・log 起動指定の
非対称)は、いずれもレビュー自身が intentional/採用非推奨としたため不対応。

単一情報源化(上位3件を同方向で解消):
- logFactors を named type logFactor{Label, LnBase} 化(precisionMode に倣う)。
  スライス添字が ln 除数(logK)を兼ねる暗黙契約を解消し、Glyph には float64 の LnBase を
  渡す。底10など非 e^n の係数も行追加だけで済む(rttGlyph 変更不要)。
  併せて model の logK フィールドを logIdx に改名(添字であって除数でないことを明示)。
- 既定スケールを config.DefaultScale に集約。cmd の defaultScale=10.0 と tui の
  fallbackScale=10 の手動同期コピーを解消し、ValidScale の隣に置いて単一情報源化。
- resolveScale の cfg 側 `cfg > 0` を config.ValidScale(cfg) に統一。directive パーサを
  経ない Config.Scale 生成元が現れても +Inf が素通りしない。

その他:
- barForStep が boundaryEpsilon を自前で加算するよう変更。nudge→truncate プロトコルを
  関数境界に跨らせず、将来の第二の呼び出し元が加算を忘れて off-by-one を再発させない。
- Glyph/rttGlyph の doc を `logK==0 で linear/それ以外 log` から
  `lnBase<=0 で linear/正で log` へ字句修正(負の値も無音で linear なのは仕様どおり)。
- keysLine の %g を strconv.FormatFloat('f',-1) に。明示指定 -s 1000000 の "1e+06ms"
  指数表記を回避。はしご値(0.01/10/100)はバイト一致のまま。

テストも lnBase 語彙・config.DefaultScale 参照・cfg 非有限フォールバックに追従。
make check 全通過(tidy-check/fmt-check/vet/lint/test)・test-race 通過。go.sum 不変。
@claude

claude Bot commented Jun 13, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

yuu61 added 4 commits June 13, 2026 10:15
/code-review ultra(xhigh) 第2回の確認済み指摘 9 件に対応。

正確性:
- ValidScale を実用範囲 [1e-4, 1e6] ms に限定。極端な有限値(例 -s 1e-300)が
  ① scaleLabel('f',-1) を約300文字に膨張させ keys 凡例を画面外へ追い出す
  ② 全 RTT を最終バンド超過にして結果バーを全部 █ にする ── を両方封じる。
  範囲判定が IsInf を包含するため math 依存も解消。README に実用範囲を明記。
- 明示した無効な -s(inf/nan/負数/範囲外)を起動時警告として可視化。フォールバック
  挙動(ValidScale で却下 → config/既定)は不変のまま、これまで黙って捨てていた入力を
  scaleWarning(cli, resolved) 経由で Options.Warnings に載せ、TUI 先頭に表示する。
  旧 int フラグでは inf/nan がハード parse エラーだった回帰の診断を取り戻す。

クリーンアップ(単一情報源化):
- config.ScaleOrDefault に「無効→既定」正規化を集約し、resolveScale 末尾と
  tui.New の重複を解消。
- activeLogFactor(i) 自由関数を Model メソッド m.logFactor() に(precMode に倣う)。
  呼び出し側が誤インデックスを渡す余地を消す。
- targetLine のグリフループから m.logFactor() をループ外へホイスト
  (R×W 回/フレームの冗長なクランプ+構造体コピーを除去)。
- -s/--scale の usage を config.DefaultScale から生成(リテラル "10" の乖離を防止)。
- logFactors の doc を明確化(index 0 の "lin" は巡回スロットの placeholder で
  非描画、線形モードは "RTT Scale" の文言で自己ラベルする旨)。

テスト:
- TestValidScale / TestScaleOrDefault / TestScaleWarning と Options.Warnings の
  描画テストを追加(範囲境界・極端値・inf/nan・警告の可視化)。
- TestScaleStepKeys の Down 押下回数と床ラベルを len(scaleSteps)/scaleLabel から導出。
- TestRttGlyphLog を TestRttGlyphLogBoundaryStability のスイープ非重複ケースに削減
  (床未満・バンド中間・巨大オーバーフロー・ガード・線形パススルー)。

make check 全通過(tidy-check/fmt-check/vet/lint/test)・test-race 通過。go.sum 不変。
/code-review ultra(xhigh) 第5回の確認済み指摘 5 件に対応(正確性バグなし・全件 low)。

正確性/挙動:
- CLI 警告(無効な -s の診断)がリロードで消える不具合を修正。warnings 合成を
  composeWarnings(cli, target) に一本化し New と handleReload の両方が経由する。
  フォールバック中の scale は生きているのに警告だけ消えヘッダーが 1 行ずれる回帰を封じる。
  TestOptionsWarningsSurface にリロード後も CLI 警告が残ることの検証を追加。

クリーンアップ(単一情報源化):
- resolveScale と scaleWarning の二重 ValidScale 判定を解消。
  resolveScale(cli, cfg) (float64, string) がスケールと警告を一度に計算し、
  値と警告のペアが規約頼みで乖離する余地を消す。main の rawScale 一時変数も除去。
- 警告文中の有効範囲ハードコード("~0.0001..1000000 ms")を撤廃。
  minScale/maxScale を MinScale/MaxScale としてエクスポートし、
  strconv.FormatFloat で定数から整形(DefaultScale と同じ単一情報源の方針)。

ドキュメント/コメント整合:
- README の scale フォールバック記述を実装に合わせて訂正。不正な -s はまず有効な
  scale ディレクティブへ、それも無ければ既定 10。無視された -s は起動時警告に出る旨も明記。
- TestParseConfigScaleLenient の古いコメント(存在しない math.IsInf ガード/n>0 チェック)を
  単一 ValidScale 範囲判定での却下に書き換え。

テスト:
- TestResolveScale を警告込みに拡張し旧 TestScaleWarning を統合。警告が実効値
  (using %gms)を名指しすることまで固定化。

make check 全通過(tidy-check/fmt-check/vet/lint/test)・test-race 通過。go.sum 不変。
正確性:
- 明示的な -s 0 / --scale=0 が無警告でフォールバックする穴を修正(P2)。
  *scale == 0 センチネルは未指定と明示 0 を区別できないため、flag.Visit で
  フラグが実際に指定されたかを判定する scaleFlagSet を追加。明示された不正値
  (0・負数・inf・nan・範囲外)を漏れなく起動時警告に載せる。README が 0 を
  不正値として警告対象に挙げている契約とも整合。
- 警告文からライブ変更で陳腐化する実効値("using Nms instead")を除去(P3)。
  警告はヘッダーに永続表示される一方、↑/↓ で m.scale は変わるため、実効値を
  埋め込むと「using 5ms」表示の横でフッターが「RTT Scale 10ms」になる矛盾が
  起きていた。文言を "using the configured or default scale" にし、実効値は
  常に正しいフッターの "RTT Scale" 行に委ねる。

構造:
- resolveScale を (float64, string) からスケール専用 float64 に戻し、警告生成を
  parseArgs へ移動。警告が実効値非依存になったため config ロード前に確定でき、
  明示判定が可能な flag 層で一元的に行える。
- scaleWarning(cli) は有効範囲を config.MinScale/MaxScale から整形(継続)。

テスト:
- TestResolveScale をスケール専用に戻す。
- TestParseArgsScaleWarning を新設(-s 0 明示・--scale=0・負数・inf・nan・範囲外・
  未指定・有効値の 8 ケース)。明示 0 が警告される P2 の回帰ガード。

make check 全通過(tidy-check/fmt-check/vet/lint/test)・test-race 通過。go.sum 不変。
- config_test: TestParseConfigScaleLenient に有限・正・範囲外の scale 1e-300/1e300
  を追加。IsInf/IsNaN ガード+素の n>0 への退行を捕捉する(nan 単独では捕捉できず、
  inf は符号でしか効かない=有限の大小を検証できるのはこの2ケースのみ)
- main: scaleWarning が拒否値を %g・境界を 'f' で出す使い分けを設計判断としてコメント化。
  'f' 統一は -s 1e-300 でラベルが ~300 字に膨張し MinScale の趣旨に反するため採らない
@yuu61 yuu61 merged commit 9038192 into master Jun 13, 2026
3 checks passed
@yuu61 yuu61 deleted the feature/rtt-log-scale branch June 13, 2026 03:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant