@a9n-shoji/rvw 0.3.1 → 0.3.2

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.
Files changed (153) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +11 -4
  3. package/dist/cli.mjs +274 -25
  4. package/dist/cli.mjs.map +3 -3
  5. package/dist/web/assets/CommentThread-CMXtuZ98.js +33 -0
  6. package/dist/web/assets/DocumentViewer-D-UGIxCU.js +1417 -0
  7. package/dist/web/assets/MarkdownTable-7Sm_sj1E.js +7 -0
  8. package/dist/web/assets/MermaidExpandedView-CyWRss2q.js +4 -0
  9. package/dist/web/assets/MermaidSurface-Dt2_Hu6n.js +344 -0
  10. package/dist/web/assets/WalkthroughViewer-CuJMrKOW.js +43 -0
  11. package/dist/web/assets/abnfDiagram-N423BO3Z-DjhFeHQj.js +1 -0
  12. package/dist/web/assets/architecture-TIHT7OUA-CsHfPErM.js +1 -0
  13. package/dist/web/assets/architectureDiagram-T3A2C74G-4zQ-4s9L.js +36 -0
  14. package/dist/web/assets/{blockDiagram-VBNYF7ZC-C77pTjUb.js → blockDiagram-VBNYF7ZC-Bh91Tm8T.js} +1 -1
  15. package/dist/web/assets/{c4Diagram-5PPSVZJV-DGHS-vVy.js → c4Diagram-5PPSVZJV-BHgLhSdB.js} +1 -1
  16. package/dist/web/assets/ccount-DFmD81E1.js +1 -0
  17. package/dist/web/assets/channel-BmC0cAv-.js +1 -0
  18. package/dist/web/assets/{chunk-2GRJ4B5K-DeUANCIz.js → chunk-2GRJ4B5K-sTPzFBtk.js} +1 -1
  19. package/dist/web/assets/chunk-3NCLNEKW-k0AW8Qyp.js +1 -0
  20. package/dist/web/assets/{chunk-4I5QYGJK-CMh2oglh.js → chunk-4I5QYGJK-q_8xEFmv.js} +1 -1
  21. package/dist/web/assets/chunk-5FCAYU7R-Dh5nylU8.js +1 -0
  22. package/dist/web/assets/chunk-5HE753X5-Bw-yg4kO.js +1 -0
  23. package/dist/web/assets/chunk-5JV3BV7I-Cy5pj3QY.js +1 -0
  24. package/dist/web/assets/{chunk-5RXB4S5H-DKTEiVyP.js → chunk-5RXB4S5H-BcuYQqlM.js} +1 -1
  25. package/dist/web/assets/chunk-5TONJI2A-DQOY3q1H.js +2 -0
  26. package/dist/web/assets/{chunk-6Q2QTUOP-CcgtbZZN.js → chunk-6Q2QTUOP-DDI96JMg.js} +1 -1
  27. package/dist/web/assets/{chunk-7Z6QIM7H-ktwy8mS7.js → chunk-7Z6QIM7H-B8QX_5g4.js} +1 -1
  28. package/dist/web/assets/chunk-BIQX33UG-DZEsGuSn.js +1 -0
  29. package/dist/web/assets/chunk-CQNSW5MT-B8S09OIh.js +1 -0
  30. package/dist/web/assets/chunk-CYSBUYHQ-C1Rf4art.js +1 -0
  31. package/dist/web/assets/chunk-EMLP6XTP-RLD4nXpI.js +1 -0
  32. package/dist/web/assets/{chunk-GF5L2VYU-C3sn41mA.js → chunk-GF5L2VYU-CJin2HQO.js} +1 -1
  33. package/dist/web/assets/{chunk-I66GZJ75-PkPnHXQJ.js → chunk-I66GZJ75-CEntV2nF.js} +1 -1
  34. package/dist/web/assets/chunk-J7OUQ5F2-XLdTvjUm.js +2 -0
  35. package/dist/web/assets/chunk-JG7HCLWE-BYfiSaVt.js +2 -0
  36. package/dist/web/assets/{chunk-JQJVKLGR-C7Y_Zm_L.js → chunk-JQJVKLGR-Bnum3gum.js} +3 -3
  37. package/dist/web/assets/{chunk-KBJHAD2P-CPGb1KEF.js → chunk-KBJHAD2P-DwPs20tJ.js} +1 -1
  38. package/dist/web/assets/chunk-MOZMSUNE-XVucA-n6.js +1 -0
  39. package/dist/web/assets/{chunk-NSK5VX7P-CiYrTyo0.js → chunk-NSK5VX7P-AmYQxFLu.js} +1 -1
  40. package/dist/web/assets/chunk-OSBZ3O6U-CrKZOUOr.js +1 -0
  41. package/dist/web/assets/chunk-QBLGF6JB-CxAyS2mW.js +1 -0
  42. package/dist/web/assets/{chunk-QR6OTTB3-Cxc4CBz3.js → chunk-QR6OTTB3-VIu9ZqqS.js} +1 -1
  43. package/dist/web/assets/chunk-R7FJI6CG-Cnn3gE-Y.js +1 -0
  44. package/dist/web/assets/chunk-U6XO7XAA-BFxjP5U3.js +2 -0
  45. package/dist/web/assets/{chunk-UBXNYLIW-Cu8_QUds.js → chunk-UBXNYLIW-D4XAD8w6.js} +1 -1
  46. package/dist/web/assets/{chunk-W5SLKNZC-xEW_C207.js → chunk-W5SLKNZC-B8QG_JAG.js} +1 -1
  47. package/dist/web/assets/{chunk-WRU74C26-lur1bNcP.js → chunk-WRU74C26-CS8zeNym.js} +1 -1
  48. package/dist/web/assets/chunk-YOTPTUD7-D0vRKqYp.js +1 -0
  49. package/dist/web/assets/chunk-ZIRB5QZD-O39ZBUk3.js +32 -0
  50. package/dist/web/assets/classDiagram-JCYQIIEL-DyY7Kt3N.js +1 -0
  51. package/dist/web/assets/classDiagram-v2-OCEON4UE-DyY7Kt3N.js +1 -0
  52. package/dist/web/assets/cynefin-VYW2F7L2-Ds2Fw2Y0.js +1 -0
  53. package/dist/web/assets/cynefinDiagram-MW4NZA55-DaNC4kY7.js +62 -0
  54. package/dist/web/assets/{dagre-VZM6K2ZE-DzKymXhT.js → dagre-VZM6K2ZE-DJ845MyA.js} +1 -1
  55. package/dist/web/assets/{diagram-7IWD3JNH-B1TUtKVL.js → diagram-7IWD3JNH-98E00vZR.js} +3 -3
  56. package/dist/web/assets/diagram-B4RE2ZJO-BpMQ8ico.js +3 -0
  57. package/dist/web/assets/diagram-LBJQPF4R-BZ8RNQpZ.js +24 -0
  58. package/dist/web/assets/diagram-Q27KOJAE-Bn1wtc7g.js +24 -0
  59. package/dist/web/assets/diagram-UB23O5K3-B314M-wb.js +41 -0
  60. package/dist/web/assets/dist-DCGa16l5.js +145 -0
  61. package/dist/web/assets/ebnfDiagram-BXEA7PRR-CqKM-cL0.js +1 -0
  62. package/dist/web/assets/{erDiagram-JOGREHBK-DlhKVbK5.js → erDiagram-JOGREHBK-CVMcNMlx.js} +1 -1
  63. package/dist/web/assets/eventmodeling-45OFAUF4-CLEiVx5s.js +1 -0
  64. package/dist/web/assets/flowDiagram-UKHOOZJN-8dur6GAS.js +1 -0
  65. package/dist/web/assets/{ganttDiagram-PKOTCBZU-Buwx6kT-.js → ganttDiagram-PKOTCBZU-DALoGLHl.js} +1 -1
  66. package/dist/web/assets/gitGraph-TEB2WS4Q-CZFBqwW-.js +1 -0
  67. package/dist/web/assets/gitGraphDiagram-DS77QQ5N-BY_jOOb-.js +106 -0
  68. package/dist/web/assets/index-BNcvGFlf.css +1 -0
  69. package/dist/web/assets/index-BwIKbLJ1.js +11 -0
  70. package/dist/web/assets/info-DKCQHKI2--1InqQeT.js +1 -0
  71. package/dist/web/assets/infoDiagram-6WML65LV-CNMbrlEJ.js +2 -0
  72. package/dist/web/assets/{ishikawaDiagram-WSZJBQD7-u7_elIzl.js → ishikawaDiagram-WSZJBQD7-NODY49Zb.js} +2 -2
  73. package/dist/web/assets/{journeyDiagram-NVQOT4AX-C2jFr8oy.js → journeyDiagram-NVQOT4AX-v9CJWB8Y.js} +1 -1
  74. package/dist/web/assets/{kanban-definition-27J2QSJJ-D-7UHdx4.js → kanban-definition-27J2QSJJ-Cv2iL7No.js} +3 -3
  75. package/dist/web/assets/lib-p2IERBh0.js +9 -0
  76. package/dist/web/assets/{line-CQAM_baC.js → line-Dah7RomF.js} +1 -1
  77. package/dist/web/assets/mermaid-parser.core-BcQae2Lb.js +4 -0
  78. package/dist/web/assets/mermaid.core-BVyLgPb6.js +11 -0
  79. package/dist/web/assets/{mindmap-definition-FAOFIHXS-tXNzs65p.js → mindmap-definition-FAOFIHXS-BD9fkU-f.js} +1 -1
  80. package/dist/web/assets/packet-7NZHBO7P-BGMXB0XL.js +1 -0
  81. package/dist/web/assets/pegDiagram-VL7TDLO6-D-HL9Pvp.js +1 -0
  82. package/dist/web/assets/pie-RZYD4A2V-DgYg3tCt.js +1 -0
  83. package/dist/web/assets/pieDiagram-7S7Q4E2Y-Sam5BEo-.js +39 -0
  84. package/dist/web/assets/preload-helper-Czpn1I53.js +1 -0
  85. package/dist/web/assets/{quadrantDiagram-CIZ2JOQS-Ck1WL56V.js → quadrantDiagram-CIZ2JOQS-BNXhvOJb.js} +1 -1
  86. package/dist/web/assets/radar-I7S5WNFK-Ag-zp_Rq.js +1 -0
  87. package/dist/web/assets/railroad-3IZDKUUU-aibJDIDV.js +1 -0
  88. package/dist/web/assets/railroad-abnf-AHOZXSZD-BBMEuvIl.js +1 -0
  89. package/dist/web/assets/railroad-ebnf-EBAXGLYW-Be1nseej.js +1 -0
  90. package/dist/web/assets/railroad-peg-LSFZ7HO6-DIvD-Eyb.js +1 -0
  91. package/dist/web/assets/railroadDiagram-AXF67PYL-C6-GuR01.js +1 -0
  92. package/dist/web/assets/{requirementDiagram-LRYGKXZP-C-GtPNYS.js → requirementDiagram-LRYGKXZP-Dew1VZVc.js} +1 -1
  93. package/dist/web/assets/{sankeyDiagram-W5VNT64P-DiFurH1m.js → sankeyDiagram-W5VNT64P-BNlHXupx.js} +1 -1
  94. package/dist/web/assets/{sequenceDiagram-SI44F4Z6-BBJvY7He.js → sequenceDiagram-SI44F4Z6-CHZhbxWH.js} +1 -1
  95. package/dist/web/assets/stateDiagram-OKZ733FA-BP7TOkRY.js +1 -0
  96. package/dist/web/assets/stateDiagram-v2-UEYNNEHI-BoFgs-SF.js +1 -0
  97. package/dist/web/assets/swimlanes-SLNWSIFB-DfMga4nB.js +2 -0
  98. package/dist/web/assets/swimlanesDiagram-ULZ7WXOC-CpfunQZj.js +8 -0
  99. package/dist/web/assets/{timeline-definition-Z64GVDOM-CPtTrFUL.js → timeline-definition-Z64GVDOM-DjC-PWK6.js} +1 -1
  100. package/dist/web/assets/treeView-QDETBFTQ-uHZ-3Fz8.js +1 -0
  101. package/dist/web/assets/treemap-6X3UGDF4-BnUKyy3l.js +1 -0
  102. package/dist/web/assets/{vennDiagram-T6HMQDX7-BjWQrcS4.js → vennDiagram-T6HMQDX7-CJzy1Vav.js} +2 -2
  103. package/dist/web/assets/wardley-OPB4EBWU-Da7TLC2F.js +1 -0
  104. package/dist/web/assets/{wardleyDiagram-T6FBY63Y-DHLZ0oPi.js → wardleyDiagram-T6FBY63Y-C9BlVo6M.js} +3 -3
  105. package/dist/web/assets/{xychartDiagram-ELKLHX3M-CEJ_HkG9.js → xychartDiagram-ELKLHX3M-B0WUxsYy.js} +3 -3
  106. package/dist/web/index.html +6 -2
  107. package/package.json +1 -1
  108. package/skills/rvw-walkthrough/SKILL.md +4 -4
  109. package/skills/rvw-walkthrough/agents/openai.yaml +1 -1
  110. package/skills/rvw-walkthrough/references/walkthrough-authoring.md +11 -0
  111. package/dist/web/assets/DocumentViewer-C7UMfzam.js +0 -1561
  112. package/dist/web/assets/MarkdownTable-Dg8UkuDK.js +0 -15
  113. package/dist/web/assets/WalkthroughViewer-BvS7o2T0.js +0 -42
  114. package/dist/web/assets/abnfDiagram-N423BO3Z-C2idvncb.js +0 -1
  115. package/dist/web/assets/architecture-TIHT7OUA-C7fqtQhb.js +0 -1
  116. package/dist/web/assets/architectureDiagram-T3A2C74G-Cdm5LY27.js +0 -36
  117. package/dist/web/assets/channel-DwAsM5u1.js +0 -1
  118. package/dist/web/assets/classDiagram-JCYQIIEL-ZOHoHid8.js +0 -1
  119. package/dist/web/assets/classDiagram-v2-OCEON4UE-ZOHoHid8.js +0 -1
  120. package/dist/web/assets/cynefin-VYW2F7L2-D8ja_01T.js +0 -1
  121. package/dist/web/assets/cynefinDiagram-MW4NZA55-DRefzYPy.js +0 -62
  122. package/dist/web/assets/diagram-B4RE2ZJO-DQ7yWH6C.js +0 -3
  123. package/dist/web/assets/diagram-LBJQPF4R-h5ld83dF.js +0 -24
  124. package/dist/web/assets/diagram-Q27KOJAE-CQyWB8j1.js +0 -24
  125. package/dist/web/assets/diagram-UB23O5K3-SmscW8SS.js +0 -41
  126. package/dist/web/assets/ebnfDiagram-BXEA7PRR-B6Uv9Fga.js +0 -1
  127. package/dist/web/assets/eventmodeling-45OFAUF4-hg8ilqKd.js +0 -1
  128. package/dist/web/assets/flowDiagram-UKHOOZJN-DlU6Mvry.js +0 -1
  129. package/dist/web/assets/gitGraph-TEB2WS4Q-DcKoIebc.js +0 -1
  130. package/dist/web/assets/gitGraphDiagram-DS77QQ5N-6hyOioar.js +0 -106
  131. package/dist/web/assets/index-CLhFOtpL.css +0 -1
  132. package/dist/web/assets/index-DYmdeW10.js +0 -384
  133. package/dist/web/assets/info-DKCQHKI2-BTrntoWR.js +0 -1
  134. package/dist/web/assets/infoDiagram-6WML65LV-C9vEklZc.js +0 -2
  135. package/dist/web/assets/mermaid-parser.core-D2z7ZOcE.js +0 -7
  136. package/dist/web/assets/mermaid.core-d5lQFkUm.js +0 -42
  137. package/dist/web/assets/packet-7NZHBO7P-Ck4WifuO.js +0 -1
  138. package/dist/web/assets/pegDiagram-VL7TDLO6-CI2wa80w.js +0 -1
  139. package/dist/web/assets/pie-RZYD4A2V-HqKGJX8R.js +0 -1
  140. package/dist/web/assets/pieDiagram-7S7Q4E2Y-DiANc3xh.js +0 -39
  141. package/dist/web/assets/radar-I7S5WNFK-BGZ0ArkI.js +0 -1
  142. package/dist/web/assets/railroad-3IZDKUUU-CG80mKUm.js +0 -1
  143. package/dist/web/assets/railroad-abnf-AHOZXSZD-siyTaNqs.js +0 -1
  144. package/dist/web/assets/railroad-ebnf-EBAXGLYW-CXsuiW_x.js +0 -1
  145. package/dist/web/assets/railroad-peg-LSFZ7HO6-2Zrn2h_2.js +0 -1
  146. package/dist/web/assets/railroadDiagram-AXF67PYL-DqLD6_Ag.js +0 -1
  147. package/dist/web/assets/stateDiagram-OKZ733FA-CJJJoWYF.js +0 -1
  148. package/dist/web/assets/stateDiagram-v2-UEYNNEHI-Cwihtgsj.js +0 -1
  149. package/dist/web/assets/swimlanes-SLNWSIFB-DDD-kqF3.js +0 -2
  150. package/dist/web/assets/swimlanesDiagram-ULZ7WXOC-CthM5wkr.js +0 -8
  151. package/dist/web/assets/treeView-QDETBFTQ-CXpMsauD.js +0 -1
  152. package/dist/web/assets/treemap-6X3UGDF4-DODWUMCI.js +0 -1
  153. package/dist/web/assets/wardley-OPB4EBWU-HV6ftDhi.js +0 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,21 @@
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.3.2] - 2026-08-31
9
+
10
+ ### Added
11
+
12
+ - Markdown、comment、WalkthroughのMermaid図をviewportサイズのreview workspaceへ展開し、Fit・zoom・
13
+ scroll、resizableなcomment rail、code referenceのpeekとreview画面へのnavigationを利用できる機能
14
+ - WalkthroughのMermaid bindingをflowchartとclassDiagramに加え、sequenceDiagramのparticipant / actor、
15
+ stateDiagram-v2のstate、erDiagramのentity、architecture-betaのserviceへ拡張
16
+
17
+ ### Changed
18
+
19
+ - Walkthroughのcode referenceを保存済みの最新PR headへ遅延解決し、fileが不変ならexact range、変更時は
20
+ sourceとdestinationで一意な未変更rangeだけを対応付け。安全に特定できない場合はimmutableなsource commitへ
21
+ fallbackし、rename / copyも一意な直接successorだけを追跡
22
+
8
23
  ## [0.3.1] - 2026-08-28
9
24
 
10
25
  ### Added
package/README.md CHANGED
@@ -16,7 +16,7 @@ Agentが実装
16
16
 
17
17
  Git commit / GitHub Pull Request
18
18
 
19
- Agentが任意でcommit固定のWalkthroughを提示
19
+ Agentが任意でsource anchor付きWalkthroughを提示
20
20
 
21
21
  rvwで意図・説明・変更・repository全体を読む
22
22
 
@@ -118,7 +118,7 @@ viewerはこの流れのために次を提供します。
118
118
 
119
119
  ## Agentの説明を人間の順序で検証する
120
120
 
121
- 外部Agentは`rvw-walkthrough` SkillとCLIを使い、実装説明を一つのcommitへ固定してrvwへ提示できます。
121
+ 外部Agentは`rvw-walkthrough` SkillとCLIを使い、実装説明を一つのsource commitをanchorとしてrvwへ提示できます。
122
122
 
123
123
  ```bash
124
124
  rvw walkthrough publish --stdin --json
@@ -128,7 +128,14 @@ rvw walkthrough publish --stdin --json
128
128
  構成されます。参照は意味のある複数行range、単行、またはfile全体を指せます。rvwは登録時にcommit、
129
129
  path、指定された行範囲を検証します。publishしてもbrowserは開かれず、
130
130
  active tabやscroll位置も変わりません。人間がviewerのWalkthroughを開き、必要なreferenceを選んだ
131
- 時だけ、exact sourceがdocument tabへ開き、行指定があれば範囲全体が強調されます。通常clickは左ペイン、
131
+ 時だけ、`sourceOid`のanchorから最新PR headへcode位置を保守的に解決します。追跡できれば最新code、
132
+ 変更や曖昧さがあれば参照時点のcodeを明示して開きます。行指定はfile全体が同一、または選択範囲が
133
+ source/latest双方で一意な場合だけ解決し、範囲全体を強調します。元pathが消えたrenameはcopy候補も含めて後継が1件のときだけ追従します。
134
+ 変更表示は選択中の比較がlatestで終わる場合だけtop barのPR比較範囲を使い、historical範囲では別revisionへ
135
+ lineを誤適用せずlatest全文を表示します。fallbackでは、同じfileまたは明確なrename先があればline保証なしで
136
+ 最新fileも開けます。このactionも比較終端がlatestと一致するときだけ変更表示を使い、historical範囲ではlatest全文を
137
+ 開きます。解決後にPR headが進んだ場合、または同じWalkthrough IDのreference座標が変わった場合はstaleとし、
138
+ 解決時/現在のSHAと表示中のanchorを示します。staleな判断とlatest file actionを隠して明示的な再解決だけを提供します。通常clickは左ペイン、
132
139
  `Cmd` / `Ctrl`を押しながら選べば右ペインへ開きます。説明tabは残るため、
133
140
  複数のclaimと実装を任意の順序・任意のタイミングで往復できます。
134
141
 
@@ -197,7 +204,7 @@ rvw Skillを使って、https://github.com/owner/repository/pull/123 をreview
197
204
 
198
205
  Walkthroughを作る場合は、説明したい対象と必要な作成指示をセッションへ伝えて`rvw-walkthrough` Skillを使います。
199
206
  Skillは明示された指示を優先し、未指定の作成判断だけを既定guideで補って、reviewerが変更または実装対象の
200
- mental modelを作るための最初の読解経路を構成します。文書の見出しや説明順序は固定せず、commit固定の
207
+ mental modelを作るための最初の読解経路を構成します。文書の見出しや説明順序は固定せず、source anchorを持つ
201
208
  reference付きartifactとして検証してpublishします。Walkthrough全体へのコメントから説明を改善する場合は、
202
209
  現在内容を取得して同じURIを更新し、重複した「改訂版」を追加しません。
203
210
 
package/dist/cli.mjs CHANGED
@@ -19895,7 +19895,7 @@ import path5 from "node:path";
19895
19895
  import { TextDecoder as TextDecoder2 } from "node:util";
19896
19896
 
19897
19897
  // src/shared/constants.ts
19898
- var APP_VERSION = "0.3.1";
19898
+ var APP_VERSION = "0.3.2";
19899
19899
  var PROTOCOL_VERSION = 4;
19900
19900
  var VIEWER_ID_HEADER = "x-rvw-viewer-id";
19901
19901
  var VIEWER_OPEN_LEASE_HEADER = "x-rvw-viewer-open-lease";
@@ -20396,6 +20396,10 @@ var GitClient = class {
20396
20396
  );
20397
20397
  return parseCommitLog(output);
20398
20398
  }
20399
+ async firstParent(cwd, oid) {
20400
+ const parents = await runText("git", ["show", "-s", "--format=%P", oid], { cwd });
20401
+ return parents.split(" ").filter(Boolean)[0] ?? null;
20402
+ }
20399
20403
  async tree(cwd, oid) {
20400
20404
  const result = await runProcess("git", ["ls-tree", "-r", "-z", "--long", oid], { cwd });
20401
20405
  return parseLsTree(result.stdout);
@@ -20408,6 +20412,23 @@ var GitClient = class {
20408
20412
  );
20409
20413
  return parseNameStatus(result.stdout);
20410
20414
  }
20415
+ async changedFilesWithCopies(cwd, oldOid, newOid) {
20416
+ const result = await runProcess(
20417
+ "git",
20418
+ [
20419
+ "diff",
20420
+ "--name-status",
20421
+ "-z",
20422
+ "--find-renames",
20423
+ "--find-copies",
20424
+ "--find-copies-harder",
20425
+ oldOid,
20426
+ newOid
20427
+ ],
20428
+ { cwd }
20429
+ );
20430
+ return parseNameStatus(result.stdout);
20431
+ }
20411
20432
  async readDocument(cwd, sourceOid, filePath) {
20412
20433
  assertGitPath(filePath);
20413
20434
  const result = await runProcess("git", ["ls-tree", "-z", "--long", sourceOid, "--", filePath], {
@@ -28071,11 +28092,22 @@ function selectedLineText(value, startLine, endLine) {
28071
28092
  function lines(text5) {
28072
28093
  return normalizeLf(text5).split("\n");
28073
28094
  }
28095
+ function countLineRangeOccurrences(documentLines, selected) {
28096
+ let occurrences = 0;
28097
+ for (let index2 = 0; index2 <= documentLines.length - selected.length; index2 += 1) {
28098
+ if (selected.every((line, offset) => documentLines[index2 + offset] === line)) {
28099
+ occurrences += 1;
28100
+ }
28101
+ }
28102
+ return occurrences;
28103
+ }
28074
28104
  function mapUnchangedLineRange(sourceText, destinationText, startLine, endLine) {
28075
28105
  if (startLine < 1 || endLine < startLine) return null;
28076
28106
  const sourceLines = lines(sourceText);
28077
28107
  if (endLine > sourceLines.length) return null;
28078
28108
  if (sourceText === destinationText) return { startLine, endLine };
28109
+ const selected = sourceLines.slice(startLine - 1, endLine);
28110
+ if (countLineRangeOccurrences(sourceLines, selected) !== 1) return null;
28079
28111
  const mapping = /* @__PURE__ */ new Map();
28080
28112
  let sourceIndex = 1;
28081
28113
  let destinationIndex = 1;
@@ -28101,14 +28133,8 @@ function mapUnchangedLineRange(sourceText, destinationText, startLine, endLine)
28101
28133
  for (let line = startLine; line <= endLine; line += 1) {
28102
28134
  if (mapping.get(line) !== mappedStart + line - startLine) return null;
28103
28135
  }
28104
- const selected = sourceLines.slice(startLine - 1, endLine);
28105
- let occurrences = 0;
28106
28136
  const destinationLines = lines(destinationText);
28107
- for (let index2 = 0; index2 <= destinationLines.length - selected.length; index2 += 1) {
28108
- if (selected.every((line, offset) => destinationLines[index2 + offset] === line))
28109
- occurrences += 1;
28110
- if (occurrences > 1) return null;
28111
- }
28137
+ if (countLineRangeOccurrences(destinationLines, selected) !== 1) return null;
28112
28138
  return { startLine: mappedStart, endLine: mappedEnd };
28113
28139
  }
28114
28140
  function findUniqueQuotedLineRange(quotedText, destinationText) {
@@ -28136,6 +28162,11 @@ function placeMutableDocumentComment(anchor, currentText) {
28136
28162
  return range ? { outdated: false, range } : { outdated: true, range: null };
28137
28163
  }
28138
28164
 
28165
+ // src/domain/walkthrough-reference.ts
28166
+ function walkthroughReferenceFingerprint(sourceOid, reference) {
28167
+ return JSON.stringify([sourceOid, reference.path, reference.startLine, reference.endLine]);
28168
+ }
28169
+
28139
28170
  // src/domain/source-excerpt.ts
28140
28171
  var SOURCE_EXCERPT_CONTEXT_LINES = 20;
28141
28172
  var MAX_SOURCE_EXCERPT_LINES = 200;
@@ -41105,7 +41136,8 @@ var codeReferenceIdPattern = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
41105
41136
  var walkthroughDiagramNodePattern = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
41106
41137
  var mermaidIdentifierPattern = /[A-Za-z][A-Za-z0-9_-]{0,63}/g;
41107
41138
  var mermaidEdgePattern = /[<|o*x]*[-.=~]{2,}[|o*x>]*/g;
41108
- var mermaidKeywords = /* @__PURE__ */ new Set([
41139
+ var mermaidClassShorthandPattern = /:::[A-Za-z][A-Za-z0-9_-]*(?:,[A-Za-z][A-Za-z0-9_-]*)*/g;
41140
+ var flowchartAndClassKeywords = /* @__PURE__ */ new Set([
41109
41141
  "class",
41110
41142
  "classDef",
41111
41143
  "classDiagram",
@@ -41117,12 +41149,19 @@ var mermaidKeywords = /* @__PURE__ */ new Set([
41117
41149
  "style",
41118
41150
  "subgraph"
41119
41151
  ]);
41120
- function mermaidIdentifiers(value) {
41121
- return [...value.matchAll(mermaidIdentifierPattern)].map(([identifier]) => identifier).filter((identifier) => !mermaidKeywords.has(identifier));
41152
+ var noMermaidKeywords = /* @__PURE__ */ new Set();
41153
+ function mermaidIdentifiers(value, excludedKeywords) {
41154
+ return [...value.matchAll(mermaidIdentifierPattern)].map(([identifier]) => identifier).filter((identifier) => !excludedKeywords.has(identifier));
41122
41155
  }
41123
- function mermaidLineWithoutLabels(value) {
41156
+ function mermaidLineWithoutComment(value) {
41124
41157
  const commentIndex = value.indexOf("%%");
41125
- const uncommented = commentIndex === -1 ? value : value.slice(0, commentIndex);
41158
+ return commentIndex === -1 ? value : value.slice(0, commentIndex);
41159
+ }
41160
+ function mermaidLineWithoutClassShorthand(value) {
41161
+ return value.replace(mermaidClassShorthandPattern, "");
41162
+ }
41163
+ function mermaidLineWithoutLabels(value) {
41164
+ const uncommented = mermaidLineWithoutComment(value);
41126
41165
  const withoutQuotedLabels = uncommented.replace(/"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'/g, " ").replace(/\|[^|]*\|/g, " ").replace(/--\s+[^-\n]+\s+-->/g, " -->").replace(/-\.\s+[^.\n]+\s+\.->/g, " -.->").replace(/==\s+[^=\n]+\s+==>/g, " ==>");
41127
41166
  let result = "";
41128
41167
  const closingDelimiters = [];
@@ -41147,33 +41186,105 @@ function mermaidLineWithoutLabels(value) {
41147
41186
  }
41148
41187
  return result;
41149
41188
  }
41150
- function addMermaidEdgeEndpoints(line, nodeIds) {
41151
- const edges = [...line.matchAll(mermaidEdgePattern)];
41189
+ function addMermaidEdgeEndpoints(line, nodeIds, excludedKeywords) {
41190
+ const endpointLine = mermaidLineWithoutClassShorthand(line);
41191
+ const edges = [...endpointLine.matchAll(mermaidEdgePattern)];
41152
41192
  for (let index2 = 0; index2 < edges.length; index2 += 1) {
41153
41193
  const edge = edges[index2];
41154
41194
  const edgeStart = edge.index;
41155
41195
  const edgeEnd = edgeStart + edge[0].length;
41156
41196
  const leftStart = index2 === 0 ? 0 : edges[index2 - 1].index + edges[index2 - 1][0].length;
41157
- const rightEnd = index2 + 1 === edges.length ? line.length : edges[index2 + 1].index;
41158
- const left = line.slice(leftStart, edgeStart);
41159
- const right = line.slice(edgeEnd, rightEnd);
41160
- const leftIdentifiers = mermaidIdentifiers(left);
41161
- const rightIdentifiers = mermaidIdentifiers(right);
41197
+ const rightEnd = index2 + 1 === edges.length ? endpointLine.length : edges[index2 + 1].index;
41198
+ const left = endpointLine.slice(leftStart, edgeStart);
41199
+ const right = endpointLine.slice(edgeEnd, rightEnd);
41200
+ const leftIdentifiers = mermaidIdentifiers(left, excludedKeywords);
41201
+ const rightIdentifiers = mermaidIdentifiers(right, excludedKeywords);
41162
41202
  const leftEndpoints = left.includes("&") ? leftIdentifiers : leftIdentifiers.slice(-1);
41163
41203
  const rightEndpoints = right.includes("&") ? rightIdentifiers : rightIdentifiers.slice(0, 1);
41164
41204
  for (const identifier of [...leftEndpoints, ...rightEndpoints]) nodeIds.add(identifier);
41165
41205
  }
41166
41206
  }
41207
+ function addSequenceMessageParticipants(line, nodeIds) {
41208
+ const message = line.match(
41209
+ /^([A-Za-z][A-Za-z0-9_-]{0,63})\s*<*[-=]+[)>x]+\s*[+-]?([A-Za-z][A-Za-z0-9_-]{0,63})\b/
41210
+ );
41211
+ if (!message) return;
41212
+ nodeIds.add(message[1]);
41213
+ nodeIds.add(message[2]);
41214
+ }
41215
+ var erCardinalitySource = [
41216
+ "one\\s+or\\s+zero",
41217
+ "one\\s+or\\s+(?:more|many)",
41218
+ "zero\\s+or\\s+(?:one|more|many)",
41219
+ "only\\s+one",
41220
+ "many\\([01]\\)",
41221
+ "[01]\\+",
41222
+ "many",
41223
+ "one",
41224
+ "\\d+(?:\\.\\d+)?"
41225
+ ].join("|");
41226
+ var erTextualRelationshipPattern = new RegExp(
41227
+ `^([A-Za-z][A-Za-z0-9_-]{0,63})\\s+(?:${erCardinalitySource})\\s+(?:to|optionally\\s+to)\\s+(?:${erCardinalitySource})\\s+([A-Za-z][A-Za-z0-9_-]{0,63})\\b`,
41228
+ "i"
41229
+ );
41230
+ function addErRelationshipEntities(line, nodeIds) {
41231
+ const relationship = line.match(
41232
+ /^([A-Za-z][A-Za-z0-9_-]{0,63})\s+[|o}{]+[.-]{2}[|o}{]+\s+([A-Za-z][A-Za-z0-9_-]{0,63})\b/
41233
+ ) ?? line.match(erTextualRelationshipPattern);
41234
+ if (!relationship) return;
41235
+ nodeIds.add(relationship[1]);
41236
+ nodeIds.add(relationship[2]);
41237
+ }
41167
41238
  function addMermaidDiagramNodes(source, nodeIds) {
41168
41239
  const lines2 = source.split("\n");
41169
41240
  const header = lines2.map((line) => mermaidLineWithoutLabels(line).trim()).find((line) => line.length > 0);
41170
- const diagramType = header?.match(/^(flowchart|graph|classDiagram)\b/)?.[1];
41241
+ const diagramType = header?.match(
41242
+ /^(flowchart|graph|classDiagram|sequenceDiagram|stateDiagram-v2|erDiagram|architecture-beta)\b/
41243
+ )?.[1];
41171
41244
  if (!diagramType) return;
41172
41245
  for (const rawLine of lines2) {
41173
- for (const statement of mermaidLineWithoutLabels(rawLine).split(";")) {
41246
+ const diagramLine = diagramType === "erDiagram" || diagramType === "sequenceDiagram" ? mermaidLineWithoutComment(rawLine) : mermaidLineWithoutLabels(rawLine);
41247
+ for (const statement of diagramLine.split(";")) {
41174
41248
  const line = statement.trim();
41175
- if (!line || /^(flowchart|graph|classDiagram)\b/.test(line)) continue;
41176
- addMermaidEdgeEndpoints(line, nodeIds);
41249
+ if (!line || /^(flowchart|graph|classDiagram|sequenceDiagram|stateDiagram-v2|erDiagram|architecture-beta)\b/.test(
41250
+ line
41251
+ )) {
41252
+ continue;
41253
+ }
41254
+ if (diagramType === "sequenceDiagram") {
41255
+ const participant = line.match(
41256
+ /^(?:participant|actor)\s+([A-Za-z][A-Za-z0-9_-]{0,63})(?:\s*@\s*\{|\s+as\b|\s*$)/
41257
+ )?.[1];
41258
+ if (participant) nodeIds.add(participant);
41259
+ else addSequenceMessageParticipants(line, nodeIds);
41260
+ continue;
41261
+ }
41262
+ if (diagramType === "architecture-beta") {
41263
+ const service = line.match(/^service\s+([A-Za-z][A-Za-z0-9_-]{0,63})(?:\s|\(|$)/)?.[1];
41264
+ if (service) nodeIds.add(service);
41265
+ continue;
41266
+ }
41267
+ if (diagramType === "stateDiagram-v2") {
41268
+ addMermaidEdgeEndpoints(line, nodeIds, noMermaidKeywords);
41269
+ const alias = line.match(/^state\s+.+?\s+as\s+([A-Za-z][A-Za-z0-9_-]{0,63})\b/)?.[1];
41270
+ const declaration = alias ? void 0 : line.match(/^state\s+([A-Za-z][A-Za-z0-9_-]{0,63})(?:\s|\{|$)/)?.[1];
41271
+ const describedState = line.match(/^([A-Za-z][A-Za-z0-9_-]{0,63})\s*:/)?.[1];
41272
+ const standaloneState = line.match(/^([A-Za-z][A-Za-z0-9_-]{0,63})$/)?.[1];
41273
+ for (const identifier of [alias, declaration, describedState, standaloneState]) {
41274
+ if (identifier) nodeIds.add(identifier);
41275
+ }
41276
+ continue;
41277
+ }
41278
+ if (diagramType === "erDiagram") {
41279
+ const entityLine = mermaidLineWithoutClassShorthand(line);
41280
+ addErRelationshipEntities(entityLine, nodeIds);
41281
+ const entity = entityLine.match(
41282
+ /^([A-Za-z][A-Za-z0-9_-]{0,63})(?:\s*\[[^\]\n]+\])?\s*(?:\{|$)/
41283
+ )?.[1];
41284
+ if (entity) nodeIds.add(entity);
41285
+ continue;
41286
+ }
41287
+ addMermaidEdgeEndpoints(line, nodeIds, flowchartAndClassKeywords);
41177
41288
  if (diagramType === "classDiagram") {
41178
41289
  const declaration = line.match(/^class\s+([A-Za-z][A-Za-z0-9_-]{0,63})\b/)?.[1];
41179
41290
  const memberOwner = line.match(/^([A-Za-z][A-Za-z0-9_-]{0,63})\s*:/)?.[1];
@@ -42091,6 +42202,133 @@ var RvwService = class {
42091
42202
  }
42092
42203
  return walkthrough;
42093
42204
  }
42205
+ async walkthroughReferenceFallbackTarget(pullRequest, sourceOid, filePath) {
42206
+ const diffBaseOid = await this.git.firstParent(pullRequest.localRepositoryPath, sourceOid);
42207
+ if (!diffBaseOid) {
42208
+ return {
42209
+ sourceOid,
42210
+ path: filePath,
42211
+ diffBaseOid: null,
42212
+ oldPath: filePath,
42213
+ newPath: filePath,
42214
+ hasDiff: false
42215
+ };
42216
+ }
42217
+ const change = (await this.git.changedFiles(pullRequest.localRepositoryPath, diffBaseOid, sourceOid)).find((candidate) => candidate.newPath === filePath);
42218
+ return {
42219
+ sourceOid,
42220
+ path: filePath,
42221
+ diffBaseOid,
42222
+ oldPath: change?.oldPath ?? filePath,
42223
+ newPath: change?.newPath ?? filePath,
42224
+ hasDiff: change !== void 0
42225
+ };
42226
+ }
42227
+ async resolveWalkthroughReference(pullRequestId, walkthroughId, referenceId) {
42228
+ const pullRequest = this.getPullRequest(pullRequestId);
42229
+ const walkthrough = this.getWalkthrough(pullRequestId, walkthroughId);
42230
+ const reference = walkthrough.references.find((candidate) => candidate.id === referenceId);
42231
+ if (!reference) {
42232
+ throw new RvwError("NOT_FOUND", "Walkthrough\u306Ecode reference\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", {
42233
+ status: 404
42234
+ });
42235
+ }
42236
+ const referenceFingerprint = walkthroughReferenceFingerprint(walkthrough.sourceOid, reference);
42237
+ const sourceDocument = await this.getDocument({
42238
+ kind: "repository-file",
42239
+ pullRequestId,
42240
+ sourceOid: walkthrough.sourceOid,
42241
+ path: reference.path
42242
+ });
42243
+ const latestHeadOid = pullRequest.latestHeadOid;
42244
+ let latestPath = reference.path;
42245
+ let latestDocument;
42246
+ if (walkthrough.sourceOid === latestHeadOid) {
42247
+ latestDocument = sourceDocument;
42248
+ } else {
42249
+ latestDocument = await this.getDocument({
42250
+ kind: "repository-file",
42251
+ pullRequestId,
42252
+ sourceOid: latestHeadOid,
42253
+ path: reference.path
42254
+ });
42255
+ if (latestDocument.availability === "missing") {
42256
+ const successorPaths = [
42257
+ ...new Set(
42258
+ (await this.git.changedFilesWithCopies(
42259
+ pullRequest.localRepositoryPath,
42260
+ walkthrough.sourceOid,
42261
+ latestHeadOid
42262
+ )).filter(
42263
+ (candidate) => (candidate.status.startsWith("R") || candidate.status.startsWith("C")) && candidate.oldPath === reference.path && candidate.newPath !== null
42264
+ ).map((candidate) => candidate.newPath)
42265
+ )
42266
+ ];
42267
+ latestPath = successorPaths.length === 1 ? successorPaths[0] : null;
42268
+ latestDocument = latestPath === null ? null : await this.getDocument({
42269
+ kind: "repository-file",
42270
+ pullRequestId,
42271
+ sourceOid: latestHeadOid,
42272
+ path: latestPath
42273
+ });
42274
+ }
42275
+ }
42276
+ const latestFileExists = latestDocument !== null && latestDocument.availability !== "missing";
42277
+ const latestFileDisplayable = latestDocument?.availability === "available";
42278
+ const mappedRange = reference.startLine === null || reference.endLine === null ? latestFileDisplayable ? null : void 0 : sourceDocument.availability === "available" && latestDocument?.availability === "available" ? mapUnchangedLineRange(
42279
+ sourceDocument.text ?? "",
42280
+ latestDocument.text ?? "",
42281
+ reference.startLine,
42282
+ reference.endLine
42283
+ ) : null;
42284
+ const resolvedToLatest = latestFileDisplayable && (reference.startLine === null || reference.endLine === null || mappedRange !== null);
42285
+ if (resolvedToLatest && latestPath !== null && latestDocument !== null) {
42286
+ return {
42287
+ outcome: "latest",
42288
+ anchorSourceOid: walkthrough.sourceOid,
42289
+ latestHeadOid,
42290
+ referenceFingerprint,
42291
+ target: {
42292
+ sourceOid: latestHeadOid,
42293
+ path: latestPath,
42294
+ diffBaseOid: null,
42295
+ oldPath: latestPath,
42296
+ newPath: latestPath,
42297
+ hasDiff: false,
42298
+ startLine: mappedRange?.startLine ?? reference.startLine,
42299
+ endLine: mappedRange?.endLine ?? reference.endLine
42300
+ },
42301
+ latestFile: null,
42302
+ document: latestDocument
42303
+ };
42304
+ }
42305
+ const targetFile = await this.walkthroughReferenceFallbackTarget(
42306
+ pullRequest,
42307
+ walkthrough.sourceOid,
42308
+ reference.path
42309
+ );
42310
+ const latestFile = latestFileExists && latestPath !== null ? {
42311
+ sourceOid: latestHeadOid,
42312
+ path: latestPath,
42313
+ diffBaseOid: null,
42314
+ oldPath: latestPath,
42315
+ newPath: latestPath,
42316
+ hasDiff: false
42317
+ } : null;
42318
+ return {
42319
+ outcome: "source-fallback",
42320
+ anchorSourceOid: walkthrough.sourceOid,
42321
+ latestHeadOid,
42322
+ referenceFingerprint,
42323
+ target: {
42324
+ ...targetFile,
42325
+ startLine: reference.startLine,
42326
+ endLine: reference.endLine
42327
+ },
42328
+ latestFile,
42329
+ document: sourceDocument
42330
+ };
42331
+ }
42094
42332
  getWalkthroughByUri(uri) {
42095
42333
  const walkthrough = this.database.getWalkthrough(parseWalkthroughUri(uri));
42096
42334
  if (!walkthrough) {
@@ -42139,7 +42377,7 @@ var RvwService = class {
42139
42377
  if (!markdown.mermaidNodeIds.has(nodeId)) {
42140
42378
  throw new RvwError(
42141
42379
  "INVALID_INPUT",
42142
- `Mermaid node\u304C\u672C\u6587\u306Eflowchart\u307E\u305F\u306FclassDiagram\u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ${nodeId}`
42380
+ `Mermaid binding\u5BFE\u8C61\u304C\u672C\u6587\u306E\u5BFE\u5FDCdiagram\u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ${nodeId}`
42143
42381
  );
42144
42382
  }
42145
42383
  }
@@ -46840,6 +47078,17 @@ function createApp(service, options) {
46840
47078
  walkthroughs: service.listWalkthroughs(context.req.param("id"))
46841
47079
  })
46842
47080
  );
47081
+ app.get(
47082
+ "/api/pull-requests/:id/walkthroughs/:walkthroughId/references/:referenceId/resolve",
47083
+ async (context) => context.json({
47084
+ ok: true,
47085
+ resolution: await service.resolveWalkthroughReference(
47086
+ context.req.param("id"),
47087
+ context.req.param("walkthroughId"),
47088
+ context.req.param("referenceId")
47089
+ )
47090
+ })
47091
+ );
46843
47092
  app.get(
46844
47093
  "/api/pull-requests/:id/walkthroughs/:walkthroughId",
46845
47094
  (context) => context.json({