diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
 # Changelog for `hgg-analyze-bridge`
 
+## 0.2.0.0 — 2026-08-13
+
+- Supports the hanalyze 0.2.0.1 multi-package split (the dependency on the
+  `hanalyze` umbrella package is unchanged; `Hanalyze.Plot` now ships
+  separately as `hanalyze-plot`).
+- Bilingual (English / Japanese) haddock.
+
 ## 0.1.0.0 — 2026-07-18
 
 First public release on Hackage.
diff --git a/hgg-analyze-bridge.cabal b/hgg-analyze-bridge.cabal
--- a/hgg-analyze-bridge.cabal
+++ b/hgg-analyze-bridge.cabal
@@ -1,13 +1,13 @@
 cabal-version:      3.0
 name:               hgg-analyze-bridge
-version:            0.1.0.0
+version:            0.2.0.0
 extra-doc-files:    CHANGELOG.md
 synopsis:           Bridge from hanalyze (Hanalyze.Model.HBM.ModelGraph) to hgg DAG rendering
 description:
   Renders hanalyze's HBM ModelGraph directly to SVG / PNG / PDF via hgg.
   No graphviz CLI or Mermaid CDN dependency, which makes it suitable for
   embedding in production applications and for offline batch use.
-  .
+
   The existing Mermaid HTML (Hanalyze.Viz.ModelGraph) and Graphviz DOT
   (Hanalyze.Viz.ModelGraphDot) routes in hanalyze remain available;
   choose whichever fits the use case.
@@ -36,9 +36,9 @@
                   , containers           >= 0.6  && < 0.8
                   , vector               >= 0.12 && < 0.14
                   , dataframe-core       ^>= 1.1
-                  , hgg-core    ^>= 0.1
-                  , hgg-frame   ^>= 0.1
-                  , hgg-svg     ^>= 0.1
+                  , hgg-core    ^>= 0.2
+                  , hgg-frame   ^>= 0.2
+                  , hgg-svg     ^>= 0.2
                   , hanalyze >= 0.2 && < 0.3
                   , hmatrix              >= 0.20 && < 0.21
   default-language: Haskell2010
@@ -50,7 +50,7 @@
   build-depends:    base
                   , text
                   , containers
-                  , directory
+                  , directory            >= 1.3  && < 1.4
                   , hgg-analyze-bridge
                   , hanalyze >= 0.2 && < 0.3
   default-language: Haskell2010
@@ -63,7 +63,7 @@
                   , vector               >= 0.12 && < 0.14
                   , containers
                   , text
-                  , directory
+                  , directory            >= 1.3  && < 1.4
                   , hgg-analyze-bridge
                   , hgg-core
                   , hgg-frame
diff --git a/src/Graphics/Hgg/Bridge/Analyze.hs b/src/Graphics/Hgg/Bridge/Analyze.hs
--- a/src/Graphics/Hgg/Bridge/Analyze.hs
+++ b/src/Graphics/Hgg/Bridge/Analyze.hs
@@ -1,33 +1,53 @@
 -- |
 -- Module      : Graphics.Hgg.Bridge.Analyze
--- Description : hanalyze ModelGraph → hgg SVG/PNG/PDF 直描画 bridge
+-- Description : Bridge: renders hanalyze's ModelGraph to SVG/PNG/PDF
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- hanalyze の 'Hanalyze.Model.HBM.ModelGraph' を、 hgg 経由で
+-- [日本語]: hanalyze の 'Hanalyze.Model.HBM.ModelGraph' を、 hgg 経由で
 -- 直接 SVG / PNG / PDF に描画する公開 API。 graphviz CLI / Mermaid CDN 依存なし。
 --
+-- [English]: The public API that renders hanalyze's
+-- 'Hanalyze.Model.HBM.ModelGraph' directly to SVG / PNG / PDF via
+-- hgg, with no dependency on the graphviz CLI or the Mermaid CDN.
+--
 -- == 3 ルートの選び方
 --
--- 同じ 'ModelGraph' を出力する 3 種類のルートがある。 用途に応じて使い分け:
+-- [日本語]: 同じ 'ModelGraph' を出力する 3 種類のルートがある。 用途に応じて使い分け:
 --
--- +---------------+---------------------------------------------+--------------------+-----------------------+
--- | ルート        | 場所                                        | 出力 / 描画依存    | 推奨用途              |
--- +===============+=============================================+====================+=======================+
--- | Mermaid HTML  | @Hanalyze.Viz.ModelGraph.renderModelGraph@  | .html + CDN script | GitHub README、 ノート |
--- +---------------+---------------------------------------------+--------------------+-----------------------+
--- | Graphviz DOT  | @Hanalyze.Viz.ModelGraphDot.toDot@          | .dot text + dot CLI| graphviz 連携、 加工   |
--- +---------------+---------------------------------------------+--------------------+-----------------------+
--- | 本 module     | 'renderModelGraphSVG' (= A3 完了)           | 依存ゼロ           | production、 offline   |
--- |               | 'renderModelGraphPNG' / 'renderModelGraphPDF' (= A4 stub、 backend 待ち) |             |             |
--- +---------------+---------------------------------------------+--------------------+-----------------------+
+-- [Mermaid HTML]: @Hanalyze.Viz.ModelGraph.renderModelGraph@ —
+--   出力は @.html@ で描画に CDN script が要る。 GitHub README やノート向け。
+-- [Graphviz DOT]: @Hanalyze.Viz.ModelGraphDot.toDot@ —
+--   出力は @.dot@ テキストで描画に @dot@ CLI が要る。 graphviz 連携・加工向け。
+-- [本 module]: 'renderModelGraphSVG' は依存ゼロで production / offline 向け。
+--   @renderModelGraphPNG@ / @renderModelGraphPDF@ は backend 待ちの stub。
 --
+-- [English]: There are 3 routes that all output the same 'ModelGraph'.
+-- Choose according to the use case:
+--
+-- [Mermaid HTML]: @Hanalyze.Viz.ModelGraph.renderModelGraph@ —
+--   outputs @.html@, which needs a CDN script to render. For GitHub READMEs
+--   and notebooks.
+-- [Graphviz DOT]: @Hanalyze.Viz.ModelGraphDot.toDot@ — outputs
+--   @.dot@ text, which needs the @dot@ CLI to render. For graphviz
+--   integration and post-processing.
+-- [This module]: 'renderModelGraphSVG' has zero dependencies, for
+--   production / offline use. @renderModelGraphPNG@ / @renderModelGraphPDF@
+--   are stubs pending their backends.
+--
 -- 3 ルートとも同じ 'ModelGraph' 構造 (= node / edge / plate) を表現する。
--- visual layout は実装ごとに異なる: 本ルートは graphviz dot 70-80% 同等品質
--- (Phase 1 §10.1)。
+-- visual layout は実装ごとに異なる: 本ルートは graphviz dot の 70-80% 同等品質。
 --
--- == 使用例 (= A3 で 'renderModelGraphSVG' 公開予定)
+-- [English]: All 3 routes represent the same 'ModelGraph' structure (node /
+-- edge / plate). The visual layout differs between implementations: this
+-- route achieves roughly 70-80% of graphviz dot's quality.
 --
+-- == 使用例
+--
+-- [日本語]: 使用例 ('renderModelGraphSVG' は今後公開予定)。
+-- [English]: A usage example ('renderModelGraphSVG' is planned for future
+-- release).
+--
 -- @
 -- import Graphics.Hgg.Bridge.Analyze (modelGraphToDAGSpec)
 -- import Hanalyze.Model.HBM (buildModelGraph)
@@ -35,7 +55,7 @@
 -- main = do
 --   let mg = buildModelGraph myModel
 --       (nodes, edges, plates) = modelGraphToDAGSpec mg
---   -- → A3 で renderModelGraphSVG file title mg として 1 行で完結予定
+--   -- → 将来的に renderModelGraphSVG file title mg として 1 行で完結予定
 -- @
 {-# LANGUAGE OverloadedStrings #-}
 module Graphics.Hgg.Bridge.Analyze
@@ -64,31 +84,43 @@
 
 import qualified Graphics.Hgg.Bridge.Analyze.Internal as I
 
--- | 'ModelGraph' を ('[DAGNode]', '[DAGEdge]', '[DAGPlate]') の triple に変換。
--- 各要素は 'Graphics.Hgg.Spec.dagFromListsWithPlates' に渡せる形になっている。
+-- | [日本語]: 'ModelGraph' を ('[DAGNode]', '[DAGEdge]', '[DAGPlate]') の triple に変換。
+--   各要素は 'Graphics.Hgg.Spec.dagFromListsWithPlates' に渡せる形になっている。
+--   [English]: Converts a 'ModelGraph' to a triple of ('[DAGNode]',
+--   '[DAGEdge]', '[DAGPlate]'). Each element is already in the form that
+--   'Graphics.Hgg.Spec.dagFromListsWithPlates' accepts.
 modelGraphToDAGSpec
   :: ModelGraph -> ([Spec.DAGNode], [Spec.DAGEdge], [Spec.DAGPlate])
 modelGraphToDAGSpec = I.toDAGTriple
 
--- | 'modelGraphToDAGSpec' の node 部分のみ。
+-- | [日本語]: 'modelGraphToDAGSpec' の node 部分のみ。
+--   [English]: Just the node part of 'modelGraphToDAGSpec'.
 modelGraphToDAGNodes :: ModelGraph -> [Spec.DAGNode]
 modelGraphToDAGNodes = I.toDAGNodes
 
--- | 'modelGraphToDAGSpec' の edge 部分のみ (= dePath は 'Nothing'、 layout で埋まる)。
+-- | [日本語]: 'modelGraphToDAGSpec' の edge 部分のみ (= dePath は 'Nothing'、 layout で埋まる)。
+--   [English]: Just the edge part of 'modelGraphToDAGSpec' (dePath is
+--   'Nothing', filled in later by layout).
 modelGraphToDAGEdges :: ModelGraph -> [Spec.DAGEdge]
 modelGraphToDAGEdges = I.toDAGEdges
 
--- | 'modelGraphToDAGSpec' の plate 部分のみ (= plate label は @"\<name\> (N=\<size\>)"@)。
+-- | [日本語]: 'modelGraphToDAGSpec' の plate 部分のみ (= plate label は @"\<name\> (N=\<size\>)"@)。
+--   [English]: Just the plate part of 'modelGraphToDAGSpec' (plate labels
+--   take the form @"\<name\> (N=\<size\>)"@).
 modelGraphToDAGPlates :: ModelGraph -> [Spec.DAGPlate]
 modelGraphToDAGPlates = I.toDAGPlates
 
 -- ===========================================================================
--- Phase 2 A3: SVG 直描画 API
+-- SVG 直描画 API
 -- ===========================================================================
 
--- | 'ModelGraph' を Phase 1 完了の DAG layout (= Sugiyama framework + plate-aware
--- ordering + Catmull-Rom spline + port snap) でレンダリングし、 'VisualSpec' に
--- 包んで返す。 ユーザは title / theme / size 等を追加合成可能。
+-- | [日本語]: 'ModelGraph' を Sugiyama framework + plate-aware
+--   ordering + Catmull-Rom spline + port snap の DAG layout でレンダリングし、
+--   @VisualSpec@ に包んで返す。 ユーザは title / theme / size 等を追加合成可能。
+--   [English]: Renders a 'ModelGraph' with a DAG layout (Sugiyama framework
+--   + plate-aware ordering + Catmull-Rom splines + port snapping) and
+--   returns it wrapped in a @VisualSpec@. Callers can further compose in
+--   title / theme / size and the like.
 --
 -- @
 -- let spec = modelGraphToVisualSpec mg
@@ -107,8 +139,11 @@
                   positioned routed Spec.LayoutHierarchical plates
   in Easy.purePlot <> Easy.layer (dagSpec <> Easy.size 22)
 
--- | 'ModelGraph' を SVG ファイルに直描画。 title は plot 上部に表示。
--- size / theme 等を細かく指定したい場合は 'modelGraphToVisualSpec' + 'plot' を使う。
+-- | [日本語]: 'ModelGraph' を SVG ファイルに直描画。 title は plot 上部に表示。
+--   size / theme 等を細かく指定したい場合は 'modelGraphToVisualSpec' + @plot@ を使う。
+--   [English]: Renders a 'ModelGraph' directly to an SVG file. The title is
+--   shown at the top of the plot. For finer control over size / theme and
+--   the like, use 'modelGraphToVisualSpec' with @plot@ instead.
 --
 -- @
 -- renderModelGraphSVG \"out\/dag.svg\" \"My HBM\" mg
@@ -122,8 +157,11 @@
            <> Easy.heightMm 700
   in SVGBackend.saveSVG path spec
 
--- | 'renderModelGraphSVG' の ByteString 版 (= ファイル書き出さず Text で返す)。
--- web server / pipeline で SVG を直接他経路に流したいときに使う。
+-- | [日本語]: 'renderModelGraphSVG' の ByteString 版 (= ファイル書き出さず Text で返す)。
+--   web server / pipeline で SVG を直接他経路に流したいときに使う。
+--   [English]: The ByteString variant of 'renderModelGraphSVG' (returns
+--   Text instead of writing a file). Useful when a web server or pipeline
+--   needs to route the SVG elsewhere directly.
 renderModelGraphSVGBytes :: Text -> ModelGraph -> Text
 renderModelGraphSVGBytes titleTxt mg =
   let spec = modelGraphToVisualSpec mg
@@ -139,15 +177,23 @@
 _unusedTextIO = TIO.writeFile
 
 -- ===========================================================================
--- Phase 2 A4: PNG / PDF 直描画 API (= backend 未実装の stub)
+-- PNG / PDF 直描画 API (= backend 未実装の stub)
 -- ===========================================================================
 
--- | __現状 stub__: hgg-rasterific backend は未実装の placeholder
--- (= 実行すると @error \"not implemented yet\"@)。 本 API は signature を先に
--- 公開しておき、 backend 実装後に自動的に動くようにする。
+-- | [日本語]: __現状 stub__: hgg-rasterific backend は未実装の placeholder
+--   (= 実行すると @error \"not implemented yet\"@)。 本 API は signature を先に
+--   公開しておき、 backend 実装後に自動的に動くようにする。
 --
--- 暫定的に PNG が必要なら 'renderModelGraphSVG' で SVG を出力し、 別 tool
--- (= @inkscape@ / @rsvg-convert@ 等) で PNG 化する経路を推奨。
+--   暫定的に PNG が必要なら 'renderModelGraphSVG' で SVG を出力し、 別 tool
+--   (= @inkscape@ / @rsvg-convert@ 等) で PNG 化する経路を推奨。
+--   [English]: __Currently a stub__: a placeholder pending the
+--   hgg-rasterific backend implementation (calling it raises
+--   @error "not implemented yet"@). This API publishes its signature ahead
+--   of time so it will start working automatically once the backend lands.
+--
+--   In the meantime, if PNG is needed, the recommended path is to output
+--   SVG with 'renderModelGraphSVG' and convert it with an external tool
+--   (e.g. @inkscape@ / @rsvg-convert@).
 renderModelGraphPNG :: FilePath -> Text -> ModelGraph -> IO ()
 renderModelGraphPNG _path _titleTxt _mg =
   error $ unlines
@@ -158,12 +204,20 @@
     , "  本 API は backend 実装後に自動的に動作します (= signature 安定)。"
     ]
 
--- | __現状 stub__: hgg-pdf backend は未実装の placeholder
--- (= 実行すると @error \"not implemented yet\"@)。 本 API は signature を先に
--- 公開しておき、 backend 実装後に自動的に動くようにする。
+-- | [日本語]: __現状 stub__: hgg-pdf backend は未実装の placeholder
+--   (= 実行すると @error \"not implemented yet\"@)。 本 API は signature を先に
+--   公開しておき、 backend 実装後に自動的に動くようにする。
 --
--- 暫定的に PDF が必要なら 'renderModelGraphSVG' で SVG を出力し、 別 tool
--- (= @rsvg-convert -f pdf@ / @inkscape --export-pdf@ 等) で PDF 化する経路を推奨。
+--   暫定的に PDF が必要なら 'renderModelGraphSVG' で SVG を出力し、 別 tool
+--   (= @rsvg-convert -f pdf@ / @inkscape --export-pdf@ 等) で PDF 化する経路を推奨。
+--   [English]: __Currently a stub__: a placeholder pending the
+--   hgg-pdf backend implementation (calling it raises @error "not
+--   implemented yet"@). This API publishes its signature ahead of time so
+--   it will start working automatically once the backend lands.
+--
+--   In the meantime, if PDF is needed, the recommended path is to output
+--   SVG with 'renderModelGraphSVG' and convert it with an external tool
+--   (e.g. @rsvg-convert -f pdf@ / @inkscape --export-pdf@).
 renderModelGraphPDF :: FilePath -> Text -> ModelGraph -> IO ()
 renderModelGraphPDF _path _titleTxt _mg =
   error $ unlines
diff --git a/src/Graphics/Hgg/Bridge/Analyze/Internal.hs b/src/Graphics/Hgg/Bridge/Analyze/Internal.hs
--- a/src/Graphics/Hgg/Bridge/Analyze/Internal.hs
+++ b/src/Graphics/Hgg/Bridge/Analyze/Internal.hs
@@ -1,14 +1,22 @@
 -- |
 -- Module      : Graphics.Hgg.Bridge.Analyze.Internal
--- Description : ModelGraph → DAGSpec 変換 (= 公開 API は Bridge.Analyze)
+-- Description : ModelGraph to DAGSpec conversion (public API lives in Bridge.Analyze)
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- 本 module は internal。 直接利用は推奨しない (= API 安定保証なし)。
+-- [日本語]: 本 module は internal。 直接利用は推奨しない (= API 安定保証なし)。
 -- 公開 helper は @Graphics.Hgg.Bridge.Analyze@ に。
 --
--- Phase 2 A2: 'toDAGNodes' / 'toDAGEdges' / 'toDAGPlates' / 'toDAGTriple' の
+-- [English]: This module is internal. Direct use is not recommended (no API
+-- stability is guaranteed). The public helpers live in
+-- @Graphics.Hgg.Bridge.Analyze@.
+--
+-- 'toDAGNodes' / 'toDAGEdges' / 'toDAGPlates' / 'toDAGTriple' の
 -- 変換関数群。 NodeKind / Distribution / Plate stack の mapping を担当。
+--
+-- [English]: The conversion functions 'toDAGNodes' / 'toDAGEdges' /
+-- 'toDAGPlates' / 'toDAGTriple'. Responsible for mapping NodeKind /
+-- Distribution / the plate stack.
 {-# LANGUAGE OverloadedStrings #-}
 module Graphics.Hgg.Bridge.Analyze.Internal
   ( -- * 変換
@@ -34,8 +42,11 @@
 -- 変換層
 -- ===========================================================================
 
--- | 全体変換: 'ModelGraph' → ('[DAGNode]', '[DAGEdge]', '[DAGPlate]')。
--- 公開 API 側で 'Graphics.Hgg.DAG.dagPlotWithPlates' に渡す形に成形する。
+-- | [日本語]: 全体変換: 'ModelGraph' → (@[DAGNode]@, @[DAGEdge]@, @[DAGPlate]@)。
+--   公開 API 側で 'Graphics.Hgg.DAG.dagPlotWithPlates' に渡す形に成形する。
+--   [English]: The full conversion: 'ModelGraph' to (@[DAGNode]@,
+--   @[DAGEdge]@, @[DAGPlate]@). Shapes the result into the form the public
+--   API passes to 'Graphics.Hgg.DAG.dagPlotWithPlates'.
 toDAGTriple :: ModelGraph -> ([Spec.DAGNode], [Spec.DAGEdge], [Spec.DAGPlate])
 toDAGTriple mg =
   ( toDAGNodes  mg
@@ -43,8 +54,11 @@
   , toDAGPlates mg
   )
 
--- | 'mgNodes' を 'DAGNode' に変換。 dnX / dnY は 0 (= layout 計算で埋まる)、
--- dnDist には分布名を 'Just' で入れる (= 空文字列なら 'Nothing' に正規化)。
+-- | [日本語]: 'mgNodes' を @DAGNode@ に変換。 dnX / dnY は 0 (= layout 計算で埋まる)、
+--   dnDist には分布名を 'Just' で入れる (= 空文字列なら 'Nothing' に正規化)。
+--   [English]: Converts 'mgNodes' to @DAGNode@. dnX / dnY start at 0 (filled
+--   in later by layout computation); dnDist holds the distribution name as
+--   'Just' (normalized to 'Nothing' when the name is empty).
 toDAGNodes :: ModelGraph -> [Spec.DAGNode]
 toDAGNodes mg =
   [ Spec.DAGNode
@@ -60,14 +74,21 @@
   where
     nonEmpty t = if T.null t then Nothing else Just t
 
--- | 'mgEdges' (= (parent, child) 列) を 'DAGEdge' に。 dePath = Nothing
--- (= layout 計算で routing される)。 deRoute = Nothing (= 未 bake・layout で確定)。
+-- | [日本語]: 'mgEdges' (= (parent, child) 列) を @DAGEdge@ に。 dePath = Nothing
+--   (= layout 計算で routing される)。 deRoute = Nothing (= 未 bake・layout で確定)。
+--   [English]: Converts 'mgEdges' (a list of (parent, child) pairs) to
+--   @DAGEdge@. dePath is Nothing (routing happens later, during layout
+--   computation); deRoute is Nothing (not yet baked — resolved by layout).
 toDAGEdges :: ModelGraph -> [Spec.DAGEdge]
 toDAGEdges mg = [ Spec.DAGEdge p c Nothing Nothing | (p, c) <- mgEdges mg ]
 
--- | 'mgPlates' (= plate 名 → サイズ N) を 'DAGPlate' に。
--- 各 plate の dpNodeIds は @nodePlates@ に当該 plate 名を含む node を列挙。
--- dpLabel は @"\<plate 名\> (N=\<size\>)"@ の形式 (= dot / PyMC 慣例に近い)。
+-- | [日本語]: 'mgPlates' (= plate 名 → サイズ N) を @DAGPlate@ に。
+--   各 plate の dpNodeIds は @nodePlates@ に当該 plate 名を含む node を列挙。
+--   dpLabel は @"\<plate 名\> (N=\<size\>)"@ の形式 (= dot / PyMC 慣例に近い)。
+--   [English]: Converts 'mgPlates' (plate name to size N) to @DAGPlate@.
+--   Each plate's dpNodeIds lists the nodes whose @nodePlates@ includes that
+--   plate name. dpLabel takes the form @"\<plate name\> (N=\<size\>)"@
+--   (close to the dot / PyMC convention).
 toDAGPlates :: ModelGraph -> [Spec.DAGPlate]
 toDAGPlates mg =
   let nodesInPlate :: Text -> [Text]
@@ -84,16 +105,25 @@
 -- Helpers
 -- ===========================================================================
 
--- | analyze の 'NodeKind' を hgg の 'DAGNodeKind' に。
+-- | [日本語]: analyze の 'NodeKind' を hgg の @DAGNodeKind@ に。
 --
 --   * 'LatentN'        → 'Spec.NodeLatent'    (= 楕円、 stochastic latent)
 --   * 'ObservedN _'    → 'Spec.NodeObserved'  (= 楕円 + 灰塗、 観測)
+--
+--   [English]: Maps analyze's 'NodeKind' to hgg's @DAGNodeKind@.
+--
+--   * 'LatentN' maps to 'Spec.NodeLatent' (an ellipse, a stochastic latent)
+--   * 'ObservedN _' maps to 'Spec.NodeObserved' (an ellipse filled grey, an
+--     observation)
 mapNodeKind :: NodeKind -> Spec.DAGNodeKind
 mapNodeKind LatentN       = Spec.NodeLatent
 mapNodeKind (ObservedN _) = Spec.NodeObserved
 
--- | plate label を @"\<name\> (N=\<size\>)"@ の形式で生成。
--- analyze の Mermaid / Graphviz DOT 出力と同じ形式。
+-- | [日本語]: plate label を @"\<name\> (N=\<size\>)"@ の形式で生成。
+--   analyze の Mermaid / Graphviz DOT 出力と同じ形式。
+--   [English]: Generates the plate label in the form
+--   @"\<name\> (N=\<size\>)"@ — the same format as analyze's Mermaid /
+--   Graphviz DOT output.
 plateLabel :: Text -> Int -> Text
 plateLabel name size = name <> " (N=" <> T.pack (show size) <> ")"
 
diff --git a/src/Graphics/Hgg/Bridge/Stat.hs b/src/Graphics/Hgg/Bridge/Stat.hs
--- a/src/Graphics/Hgg/Bridge/Stat.hs
+++ b/src/Graphics/Hgg/Bridge/Stat.hs
@@ -1,10 +1,10 @@
 -- |
 -- Module      : Graphics.Hgg.Bridge.Stat
--- Description : ggplot 風 stat-in (statLm/statSmooth) の回帰計算を hanalyze に委譲して解決 (Phase 16)
+-- Description : ggplot-style stat-in (statLm/statSmooth) via hanalyze
 -- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
 -- License     : BSD-3-Clause
 --
--- 系統 B (ggplot 風スタット・イン) の解決ロジック (Phase 16)。
+-- [日本語]: 系統 B (ggplot 風スタット・イン) の解決ロジック。
 --
 --   ggplot の @geom_smooth(method="lm")@ / @stat_smooth@ に相当。 ユーザは plot-core の
 --   __stat layer__ (@statLm@ / @statSmooth@) を通常 geom と同じく @<>@ で重ねる:
@@ -16,7 +16,7 @@
 --   @
 --
 --   stat layer (@MStatLM@/@MStatSmooth@) は plot-core が持つ純タグで、 描画前に本モジュールの
---   'resolveStats' が **回帰計算を hanalyze に委譲**して具体 layer (band + line) に展開する。
+--   'resolveStats' が __回帰計算を hanalyze に委譲__して具体 layer (band + line) に展開する。
 --
 --   ★依存方向 (最重要): @plot-core@ は analyze 非依存のまま (タグを持つだけ)。 回帰 fit は
 --   @plot → analyze@ の逆エッジゆえ本 opt-in 隔離 package (`hgg-analyze-bridge`) のみで行う。
@@ -24,10 +24,38 @@
 --   ★使い方: バインド後に 'saveSVGBoundStats' / 'renderBoundStats' を使えば、 bpResolver で
 --   自動的に 'resolveStats' してから描画する (df は 1 回参照)。
 --
---   ★委譲の内訳: @statLm@ = §3.6 @parseModel "y ~ x"@ + @fitLMF@ で fit + LM @confidenceBand@ で
+--   ★委譲の内訳: @statLm@ は @parseModel "y ~ x"@ + @fitLMF@ で fit + LM @confidenceBand@ で
 --   信頼帯 (設計行列は @designMatrix@、 fitLMF と同一 [1,x] 設計)。 @statSmooth@ = @y ~ bs(x,n)@ の
 --   fitLMF (B-spline、 曲線のみ・帯なし)。 stat layer の装飾 (color/stroke/alpha) は展開後の
 --   band/line に引き継がれる。
+--
+-- [English]: The resolution logic for track B (ggplot-style stat-in).
+--
+--   Corresponds to ggplot's @geom_smooth(method="lm")@ / @stat_smooth@.
+--   Users overlay a plot-core __stat layer__ (@statLm@ / @statSmooth@) with
+--   @<>@, just like a normal geom (see the example above).
+--
+--   A stat layer (@MStatLM@/@MStatSmooth@) is a plain tag held by
+--   plot-core; before rendering, this module's 'resolveStats' __delegates the regression computation to hanalyze__
+--   and expands the tag into concrete layers (band + line). (See the @<>@-composed example
+--   above — the decoration on a stat layer works the same as on a normal
+--   geom.)
+--
+--   Dependency direction (most important): @plot-core@ stays
+--   analyze-independent (it only holds the tag). Regression fitting is a
+--   reverse edge (@plot → analyze@), so it is confined to this opt-in
+--   isolation package (`hgg-analyze-bridge`) alone.
+--
+--   Usage: after binding, 'saveSVGBoundStats' / 'renderBoundStats'
+--   automatically call 'resolveStats' with bpResolver before rendering (the
+--   dataframe is referenced only once).
+--
+--   What is delegated: @statLm@ fits via @parseModel "y ~ x"@ + @fitLMF@
+--   and computes the confidence band via LM's @confidenceBand@ (using the
+--   design matrix from @designMatrix@ — the same [1,x] design as fitLMF).
+--   @statSmooth@ fits @y ~ bs(x,n)@ via fitLMF (B-spline, curve only, no
+--   band). A stat layer's decoration (color/stroke/alpha) carries over to
+--   the expanded band/line.
 {-# LANGUAGE OverloadedStrings #-}
 
 module Graphics.Hgg.Bridge.Stat
@@ -66,17 +94,30 @@
 -- resolveStats: VisualSpec 中の未解決 stat layer を band+line に展開
 -- ===========================================================================
 
--- | 'VisualSpec' の各 layer を走査し、 未解決の stat layer (@MStatLM@/@MStatSmooth@) を
+-- | [日本語]: 'VisualSpec' の各 layer を走査し、 未解決の stat layer (@MStatLM@/@MStatSmooth@) を
 --   @Resolver@ でデータ解決 → hanalyze で fit → 具体 layer (band+line / line) に置換する。
 --   それ以外の layer は不変。 解決/fit に失敗した stat layer は黙って除去 (描画を妨げない)。
+--   [English]: Walks each layer of a 'VisualSpec', and for any unresolved
+--   stat layer (@MStatLM@/@MStatSmooth@) resolves its data via the
+--   @Resolver@, fits it with hanalyze, and replaces it with concrete layers
+--   (band+line / line). Other layers are left unchanged. A stat layer that
+--   fails to resolve or fit is silently dropped (so rendering is not
+--   blocked).
 resolveStats :: Resolver -> VisualSpec -> VisualSpec
 resolveStats r vs = vs { vsLayers = concatMap (expandLayer pal r) (vsLayers vs) }
   where pal = statPalette vs
 
--- | B2 群色の元になる categorical palette。 ★Layout の catPalRaw と同じ規律で求める
+-- | [日本語]: 群色の元になる categorical palette。 ★Layout の catPalRaw と同じ規律で求める
 --   (spec.palette 明示 > theme 既定 series)。 これで group 別 stat 線の色が ColorByCol
 --   scatter (renderer は lpCategoricalPalette を index 参照) と一致する。
 --   ggplot hue sentinel (["__ggplot_hue__"]) は群数依存ゆえ 'resolveGrouped' で展開する。
+--   [English]: The categorical palette that group colors are drawn from.
+--   Derived using the same discipline as Layout's catPalRaw (an explicit
+--   spec.palette wins over the theme's default series palette). This keeps
+--   per-group stat line colors consistent with ColorByCol scatter (whose
+--   renderer looks up lpCategoricalPalette by index). The ggplot hue
+--   sentinel (["__ggplot_hue__"]) depends on the group count, so it is
+--   expanded by 'resolveGrouped'.
 statPalette :: VisualSpec -> [Text]
 statPalette vs =
   let themeDefaultPal = themeSeriesPalette (fromMaybe ThemeDefault (getLast (vsTheme vs)))
@@ -91,16 +132,23 @@
   _                -> [ly]
   where grouped f = either (const []) id (resolveGrouped pal r ly f)
 
--- | 単群 stat resolver の型。 装飾/オプションは 'Layer'、 データは xs/ys で受ける
+-- | [日本語]: 単群 stat resolver の型。 装飾/オプションは 'Layer'、 データは xs/ys で受ける
 --   (Resolver からの解決は 'resolveGrouped' が一度だけ行う)。
+--   [English]: The type of a single-group stat resolver. Decoration/options
+--   come via 'Layer', data via xs/ys (resolution from the Resolver is done
+--   once, by 'resolveGrouped').
 type StatFn = Layer -> V.Vector Double -> V.Vector Double -> Either String [Layer]
 
 -- ===========================================================================
--- B2: group 別 fit (= ggplot geom_smooth(aes(color=g)))
+-- group 別 fit (= ggplot geom_smooth(aes(color=g)))
 -- ===========================================================================
 
--- | stat layer の color encoding が群列 ('ColorByCol') を指すなら、 群ごとに分割 fit し
---   群色 (ggplotHue) で複数 line/band を重畳する。 群指定が無ければ単群で 1 回 fit (B1/B3 同等)。
+-- | [日本語]: stat layer の color encoding が群列 ('ColorByCol') を指すなら、 群ごとに分割 fit し
+--   群色 (ggplotHue) で複数 line/band を重畳する。 群指定が無ければ単群で 1 回 fit。
+--   [English]: If a stat layer's color encoding points at a group column
+--   ('ColorByCol'), fits separately per group and overlays multiple
+--   line/bands in the group colors (ggplotHue). Without a group, fits once
+--   as a single group.
 resolveGrouped :: [Text] -> Resolver -> Layer -> StatFn -> Either String [Layer]
 resolveGrouped palRaw r ly f = do
   xs0 <- colOf r (lyEncX ly)
@@ -132,13 +180,17 @@
             in either (const []) id (f ly' gx gy)
       Right (concatMap perGroup (zip [0 ..] groups))
 
--- | lyColor が 'ColorByCol' なら群列を Resolver で文字ベクタに解決 (= 群分割キー)。
+-- | [日本語]: lyColor が 'ColorByCol' なら群列を Resolver で文字ベクタに解決 (= 群分割キー)。
+--   [English]: If lyColor is 'ColorByCol', resolves the group column to a
+--   text vector via the Resolver (the group-splitting key).
 groupColumn :: Resolver -> Layer -> Maybe (V.Vector Text)
 groupColumn r ly = case getLast (lyColor ly) of
   Just (ColorByCol cr) -> resolveTxt r cr
   _                    -> Nothing
 
--- | 出現順を保つ distinct (= Render.nubKeep 同等。 群の色対応を安定させる)。
+-- | [日本語]: 出現順を保つ distinct (= Render.nubKeep 同等。 群の色対応を安定させる)。
+--   [English]: Deduplicates while preserving order of first appearance
+--   (equivalent to Render.nubKeep; keeps group-to-color mapping stable).
 nubKeepOrd :: Eq a => [a] -> [a]
 nubKeepOrd = go []
   where go seen []     = reverse seen
@@ -146,14 +198,22 @@
           | x `elem` seen = go seen xs
           | otherwise     = go (x : seen) xs
 
--- | geom_smooth / stat_lm の回帰線の既定線幅 (Phase 34 A1: ggplot geom_smooth は
+-- | [日本語]: geom_smooth / stat_lm の回帰線の既定線幅 (ggplot geom_smooth は
 --   @linewidth = 2 × 既定線@ = 0.753mm)。@decoOf ly@ (= user 指定 stroke) が後置で
 --   上書きするので、user が 'stroke' を明示した場合はそちらが優先される。
+--   [English]: The default line width for geom_smooth / stat_lm regression
+--   lines (ggplot's geom_smooth uses @linewidth = 2 × the default line@ =
+--   0.753mm). @decoOf ly@ (the user-specified stroke, if any) overrides it
+--   afterward, so an explicit 'stroke' from the user takes priority.
 smoothLineDefault :: Layer
 smoothLineDefault = stroke (0.753 *~ mm)
 
--- | 装飾だけを抜き出した Layer (lyKind/encoding は持たない)。 band/line に @<>@ で合成すると
+-- | [日本語]: 装飾だけを抜き出した Layer (lyKind/encoding は持たない)。 band/line に @<>@ で合成すると
 --   color/stroke/alpha/linetype が引き継がれ、 band/line 自身の lyKind は保たれる (First Monoid)。
+--   [English]: A Layer holding only decoration (no lyKind/encoding).
+--   Composing it into band/line with @<>@ carries over
+--   color/stroke/alpha/linetype while preserving band/line's own lyKind
+--   (the First monoid).
 decoOf :: Layer -> Layer
 decoOf ly = mempty
   { lyColor    = lyColor    ly
@@ -162,13 +222,17 @@
   , lyLinetype = lyLinetype ly
   }
 
--- | stat layer の encoding 列を Resolver で数値ベクタに解決。
+-- | [日本語]: stat layer の encoding 列を Resolver で数値ベクタに解決。
+--   [English]: Resolves a stat layer's encoding column to a numeric vector
+--   via the Resolver.
 colOf :: Resolver -> Last ColRef -> Either String (V.Vector Double)
 colOf r lc = case getLast lc >>= resolveNum r of
   Just v  -> Right v
   Nothing -> Left "stat layer の x/y 列を数値として解決できません"
 
--- | lm: 回帰線 + 95% 信頼帯。 帯は半透明 (alpha 既定 0.2)、 線は装飾引き継ぎ。
+-- | [日本語]: lm: 回帰線 + 95% 信頼帯。 帯は半透明 (alpha 既定 0.2)、 線は装飾引き継ぎ。
+--   [English]: lm: a regression line + 95% confidence band. The band is
+--   semi-transparent (default alpha 0.2); the line inherits the decoration.
 resolveLM :: StatFn
 resolveLM ly xs ys = do
   (fr, _) <- fitFormula "y ~ x" xs ys
@@ -189,9 +253,14 @@
   Right [ bandLy   -- 帯を先に (背面)
         , lineLy ] -- 線を後に (前面)
 
--- | smooth: B-spline 平滑。 knot 数は lyBinCount (既定 6)。
---   B1: 'lyStatLevel' が Just (= 'statSmoothCI') なら bs 設計行列の 'LM.confidenceBand' で
---   信頼帯 (band) + 曲線 (line)、 Nothing (= 'statSmooth') なら曲線のみ。
+-- | [日本語]: smooth: B-spline 平滑。 knot 数は lyBinCount (既定 6)。
+--   'lyStatLevel' が Just (= @statSmoothCI@) なら bs 設計行列の 'LM.confidenceBand' で
+--   信頼帯 (band) + 曲線 (line)、 Nothing (= @statSmooth@) なら曲線のみ。
+--   [English]: smooth: B-spline smoothing. The knot count comes from
+--   lyBinCount (default 6). When 'lyStatLevel' is Just (i.e.
+--   @statSmoothCI@), computes a confidence band (band) + curve (line) via
+--   the bs design matrix's 'LM.confidenceBand'; when Nothing (i.e.
+--   @statSmooth@), computes only the curve.
 resolveSmooth :: StatFn
 resolveSmooth ly xs ys = do
   let n       = maybe 6 id (getLast (lyBinCount ly))
@@ -220,8 +289,12 @@
       Right [ bandLy   -- 帯を先に (背面)
             , lineLy ] -- 線を後に (前面)
 
--- | poly: 多項式回帰 (= ggplot stat_smooth(method="lm", formula=y~poly(x,deg)))。
+-- | [日本語]: poly: 多項式回帰 (= ggplot stat_smooth(method="lm", formula=y~poly(x,deg)))。
 --   次数 deg は lyBinCount (既定 2)。 poly 設計行列の confidenceBand で band+line に展開。
+--   [English]: poly: polynomial regression (equivalent to ggplot's
+--   stat_smooth(method="lm", formula=y~poly(x,deg))). The degree comes from
+--   lyBinCount (default 2). Expanded into band+line via the poly design
+--   matrix's confidenceBand.
 resolvePoly :: StatFn
 resolvePoly ly xs ys = do
   let deg     = maybe 2 id (getLast (lyBinCount ly))
@@ -244,8 +317,12 @@
   Right [ bandLy   -- 帯を先に (背面)
         , lineLy ] -- 線を後に (前面)
 
--- | resid: 残差 vs fitted 診断散布 (= base R plot(lm) #1)。 y~x で fit し、
+-- | [日本語]: resid: 残差 vs fitted 診断散布 (= base R plot(lm) #1)。 y~x で fit し、
 --   各点を (fitted, residual=y-fitted) に写した scatter に展開する (装飾は scatter に引き継ぐ)。
+--   [English]: resid: a residuals-vs-fitted diagnostic scatter (equivalent
+--   to base R's plot(lm) #1). Fits y~x and expands into a scatter mapping
+--   each point to (fitted, residual=y-fitted); decoration carries over to
+--   the scatter.
 resolveResid :: StatFn
 resolveResid ly xs ys = do
   (fr, _) <- fitFormula "y ~ x" xs ys
@@ -255,16 +332,23 @@
       ry     = V.fromList resid
   Right [ scatter (ColNum fx) (ColNum ry) <> decoOf ly ]
 
--- | x/y の 2 列 DataFrame を組み、 formula を parse → fitLMF (回帰計算を analyze に委譲)。
+-- | [日本語]: x/y の 2 列 DataFrame を組み、 formula を parse → fitLMF (回帰計算を analyze に委譲)。
 --   列名は内部固定 ("x"/"y") で、 formula も "x"/"y" を参照する。
+--   [English]: Builds a 2-column x/y DataFrame, parses the formula, then
+--   fits via fitLMF (delegating the regression computation to analyze). The
+--   column names are fixed internally ("x"/"y"), and the formula also
+--   refers to "x"/"y".
 fitFormula :: Text -> V.Vector Double -> V.Vector Double
            -> Either String (FitResult, [Text])
 fitFormula formula xs ys = do
   f <- parseModel formula
   fitLMF f (xyFrame xs ys)
 
--- | formula の設計行列 (= confidenceBand 用)。 fitLMF と同じ modelFrame→designMatrixF 経路を
+-- | [日本語]: formula の設計行列 (= confidenceBand 用)。 fitLMF と同じ modelFrame→designMatrixF 経路を
 --   通すので、 bs(x,n) 等の基底展開も fit と完全一致する。
+--   [English]: The design matrix for a formula (used for confidenceBand).
+--   Goes through the same modelFrame→designMatrixF path as fitLMF, so basis
+--   expansions such as bs(x,n) match the fit exactly.
 designFor :: Text -> V.Vector Double -> V.Vector Double
           -> Either String (LA.Matrix Double)
 designFor formula xs ys = do
@@ -273,7 +357,8 @@
   (dm, _) <- designMatrixF f mf
   Right dm
 
--- | x/y 2 列の内部 DataFrame。
+-- | [日本語]: x/y 2 列の内部 DataFrame。
+--   [English]: The internal 2-column x/y DataFrame.
 xyFrame :: V.Vector Double -> V.Vector Double -> DX.DataFrame
 xyFrame xs ys = DX.fromNamedColumns
   [ ("x", DX.fromList (V.toList xs))
@@ -283,14 +368,19 @@
 -- BoundPlot 向けの描画ラッパ (df 1 回参照・自動解決)
 -- ===========================================================================
 
--- | バインド済プロットの spec を、 自分が持つ resolver で 'resolveStats' する。
+-- | [日本語]: バインド済プロットの spec を、 自分が持つ resolver で 'resolveStats' する。
+--   [English]: Runs 'resolveStats' on a bound plot's spec, using the plot's
+--   own resolver.
 resolveBound :: BoundPlot -> BoundPlot
 resolveBound bp = bp { bpSpec = resolveStats (bpResolver bp) (bpSpec bp) }
 
--- | stat を解決してから SVG 保存 (= ggplot2 の geom_smooth 込み図を 1 回の df 参照で)。
+-- | [日本語]: stat を解決してから SVG 保存 (= ggplot2 の geom_smooth 込み図を 1 回の df 参照で)。
+--   [English]: Resolves stats and then saves to SVG (produces a figure with
+--   a geom_smooth-equivalent, referencing the dataframe only once).
 saveSVGBoundStats :: FilePath -> BoundPlot -> IO ()
 saveSVGBoundStats path = saveSVGBound path . resolveBound
 
--- | stat を解決してから SVG 文字列を返す。
+-- | [日本語]: stat を解決してから SVG 文字列を返す。
+--   [English]: Resolves stats and then returns the SVG string.
 renderBoundStats :: BoundPlot -> Text
 renderBoundStats = renderBound . resolveBound
