@a9n-shoji/rvw 0.1.1 → 0.2.1

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 (111) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +44 -13
  3. package/dist/cli.mjs +896 -279
  4. package/dist/cli.mjs.map +4 -4
  5. package/dist/web/assets/DocumentViewer-DvrDlIpR.js +1560 -0
  6. package/dist/web/assets/MarkdownTable-DbDc9VoP.js +7 -0
  7. package/dist/web/assets/WalkthroughViewer-aDUeKC3B.js +1 -0
  8. package/dist/web/assets/{abnfDiagram-N423BO3Z-Ck9r3vgI.js → abnfDiagram-N423BO3Z-fQDP4qYL.js} +1 -1
  9. package/dist/web/assets/architecture-TIHT7OUA-CuFS9GkN.js +1 -0
  10. package/dist/web/assets/{architectureDiagram-T3A2C74G-CuKnSDyu.js → architectureDiagram-T3A2C74G-D3Aon3Nd.js} +1 -1
  11. package/dist/web/assets/{blockDiagram-VBNYF7ZC-BQg6daf-.js → blockDiagram-VBNYF7ZC-DS1DcAqy.js} +1 -1
  12. package/dist/web/assets/{c4Diagram-5PPSVZJV-DlH9a39M.js → c4Diagram-5PPSVZJV-BHQWz7l2.js} +1 -1
  13. package/dist/web/assets/channel-CTWz7tRI.js +1 -0
  14. package/dist/web/assets/{chunk-2GRJ4B5K-BVLXBbte.js → chunk-2GRJ4B5K-CaahxDVT.js} +1 -1
  15. package/dist/web/assets/{chunk-4I5QYGJK-DiwTdMc_.js → chunk-4I5QYGJK-Bat5hdXD.js} +1 -1
  16. package/dist/web/assets/{chunk-5RXB4S5H-DxlG3rKg.js → chunk-5RXB4S5H-jyonN41f.js} +1 -1
  17. package/dist/web/assets/{chunk-6Q2QTUOP-DOnYF_EB.js → chunk-6Q2QTUOP-BBo9TYzL.js} +1 -1
  18. package/dist/web/assets/{chunk-7Z6QIM7H-e6n3pq6e.js → chunk-7Z6QIM7H-CGSwsKhC.js} +1 -1
  19. package/dist/web/assets/{chunk-GF5L2VYU-FUD5NaJd.js → chunk-GF5L2VYU-Cuca3bAY.js} +1 -1
  20. package/dist/web/assets/{chunk-I66GZJ75-CgtIbVp9.js → chunk-I66GZJ75-DRdqLSyH.js} +1 -1
  21. package/dist/web/assets/{chunk-JQJVKLGR-m8efG8h-.js → chunk-JQJVKLGR-8xhLkhs2.js} +1 -1
  22. package/dist/web/assets/{chunk-KBJHAD2P-C0ildSCF.js → chunk-KBJHAD2P-oOV-3e5-.js} +1 -1
  23. package/dist/web/assets/{chunk-NSK5VX7P-DJim9vRL.js → chunk-NSK5VX7P-CXit1l3q.js} +1 -1
  24. package/dist/web/assets/{chunk-QR6OTTB3-D3ng5jSq.js → chunk-QR6OTTB3-DcdCU-01.js} +1 -1
  25. package/dist/web/assets/{chunk-UBXNYLIW-r4FNgMUm.js → chunk-UBXNYLIW-i72Hgljr.js} +1 -1
  26. package/dist/web/assets/{chunk-W5SLKNZC-BxwOtp_h.js → chunk-W5SLKNZC-DetAQo7M.js} +1 -1
  27. package/dist/web/assets/{chunk-WRU74C26-DAa9M2Ku.js → chunk-WRU74C26-DDUvJFNs.js} +1 -1
  28. package/dist/web/assets/classDiagram-JCYQIIEL-BJQv9QuO.js +1 -0
  29. package/dist/web/assets/classDiagram-v2-OCEON4UE-BJQv9QuO.js +1 -0
  30. package/dist/web/assets/{cynefin-VYW2F7L2-D_MdPIfm.js → cynefin-VYW2F7L2-fd-v6ani.js} +1 -1
  31. package/dist/web/assets/{cynefinDiagram-MW4NZA55-BQ16VR2b.js → cynefinDiagram-MW4NZA55-DRsVpAC3.js} +1 -1
  32. package/dist/web/assets/{dagre-VZM6K2ZE-BcYktfC7.js → dagre-VZM6K2ZE-BnRSs_fe.js} +1 -1
  33. package/dist/web/assets/{diagram-7IWD3JNH-BQ-4OKZa.js → diagram-7IWD3JNH-D1g0PR4y.js} +1 -1
  34. package/dist/web/assets/{diagram-B4RE2ZJO-C24yZ4GQ.js → diagram-B4RE2ZJO-DuDKsQLp.js} +1 -1
  35. package/dist/web/assets/{diagram-LBJQPF4R-wMs9ij7l.js → diagram-LBJQPF4R-COpzgGe7.js} +1 -1
  36. package/dist/web/assets/{diagram-Q27KOJAE-CQR8qV1D.js → diagram-Q27KOJAE-DR2vRbPE.js} +1 -1
  37. package/dist/web/assets/{diagram-UB23O5K3-D8Fm2CWy.js → diagram-UB23O5K3-hs4VGPP7.js} +1 -1
  38. package/dist/web/assets/{ebnfDiagram-BXEA7PRR-DctbWdRA.js → ebnfDiagram-BXEA7PRR-B_4NlK9q.js} +1 -1
  39. package/dist/web/assets/{erDiagram-JOGREHBK-CMXJzItT.js → erDiagram-JOGREHBK-JyoZ3U-o.js} +1 -1
  40. package/dist/web/assets/eventmodeling-45OFAUF4-CfUhQK5g.js +1 -0
  41. package/dist/web/assets/flowDiagram-UKHOOZJN-FFZ82SPa.js +1 -0
  42. package/dist/web/assets/{ganttDiagram-PKOTCBZU-B6UdI6h5.js → ganttDiagram-PKOTCBZU-f37I0Twm.js} +1 -1
  43. package/dist/web/assets/{gitGraph-TEB2WS4Q-C7YUJfov.js → gitGraph-TEB2WS4Q-B_QWjr7j.js} +1 -1
  44. package/dist/web/assets/{gitGraphDiagram-DS77QQ5N-CKIazrRX.js → gitGraphDiagram-DS77QQ5N-AZsaC0hu.js} +1 -1
  45. package/dist/web/assets/index-CY_JoUL3.js +384 -0
  46. package/dist/web/assets/index-kK3hngnz.css +1 -0
  47. package/dist/web/assets/{info-DKCQHKI2-Dj4QbgxZ.js → info-DKCQHKI2-BRfisbEI.js} +1 -1
  48. package/dist/web/assets/{infoDiagram-6WML65LV-CkPZHoSH.js → infoDiagram-6WML65LV-CaIb64N5.js} +1 -1
  49. package/dist/web/assets/{ishikawaDiagram-WSZJBQD7-C1U-aqaM.js → ishikawaDiagram-WSZJBQD7-BoJrcTja.js} +1 -1
  50. package/dist/web/assets/{journeyDiagram-NVQOT4AX-BFmnFTx5.js → journeyDiagram-NVQOT4AX-CRR1dZy8.js} +1 -1
  51. package/dist/web/assets/{kanban-definition-27J2QSJJ-C5KXffho.js → kanban-definition-27J2QSJJ-D5skDuP4.js} +1 -1
  52. package/dist/web/assets/{line-CPlnGb39.js → line-BKKx0vSh.js} +1 -1
  53. package/dist/web/assets/{mermaid-parser.core-CQYajAMQ.js → mermaid-parser.core-DvZnIth0.js} +3 -3
  54. package/dist/web/assets/{mermaid.core-SFGI5XV8.js → mermaid.core-hykiOF_o.js} +4 -4
  55. package/dist/web/assets/{mindmap-definition-FAOFIHXS-Dxek7WcS.js → mindmap-definition-FAOFIHXS-BN2LQ4Yn.js} +1 -1
  56. package/dist/web/assets/{packet-7NZHBO7P-CAR0tDyo.js → packet-7NZHBO7P-CS5I0NlV.js} +1 -1
  57. package/dist/web/assets/{pegDiagram-VL7TDLO6-CN_CBGXn.js → pegDiagram-VL7TDLO6-WvOdhbxo.js} +1 -1
  58. package/dist/web/assets/{pie-RZYD4A2V-CAy1ZkLF.js → pie-RZYD4A2V-BwNAZrQ1.js} +1 -1
  59. package/dist/web/assets/{pieDiagram-7S7Q4E2Y-Do--6qr_.js → pieDiagram-7S7Q4E2Y-CbyrZjm7.js} +1 -1
  60. package/dist/web/assets/{quadrantDiagram-CIZ2JOQS-_d72nP_y.js → quadrantDiagram-CIZ2JOQS-CW9YBxAO.js} +1 -1
  61. package/dist/web/assets/{radar-I7S5WNFK-D_NREiMx.js → radar-I7S5WNFK-DBoCLDNH.js} +1 -1
  62. package/dist/web/assets/{railroad-3IZDKUUU-DU7RDpQt.js → railroad-3IZDKUUU-BOjpYyDz.js} +1 -1
  63. package/dist/web/assets/railroad-abnf-AHOZXSZD-DQhDS2pf.js +1 -0
  64. package/dist/web/assets/railroad-ebnf-EBAXGLYW-Dtt2kOaN.js +1 -0
  65. package/dist/web/assets/railroad-peg-LSFZ7HO6-nfH8zno6.js +1 -0
  66. package/dist/web/assets/{railroadDiagram-AXF67PYL-DNZ982Bc.js → railroadDiagram-AXF67PYL-BdOOOq8o.js} +1 -1
  67. package/dist/web/assets/{requirementDiagram-LRYGKXZP-BNEqDsk3.js → requirementDiagram-LRYGKXZP-DIYlSrTb.js} +1 -1
  68. package/dist/web/assets/{sankeyDiagram-W5VNT64P-BBdI8stM.js → sankeyDiagram-W5VNT64P-Cc1IGxp_.js} +1 -1
  69. package/dist/web/assets/{sequenceDiagram-SI44F4Z6-3zzNyCI7.js → sequenceDiagram-SI44F4Z6-CJsPO9Z9.js} +1 -1
  70. package/dist/web/assets/{stateDiagram-OKZ733FA-PtqkKvef.js → stateDiagram-OKZ733FA-B033gpHZ.js} +1 -1
  71. package/dist/web/assets/stateDiagram-v2-UEYNNEHI-wS01qj3t.js +1 -0
  72. package/dist/web/assets/{swimlanes-SLNWSIFB-CPWjF8YR.js → swimlanes-SLNWSIFB-C0Tstg7e.js} +1 -1
  73. package/dist/web/assets/swimlanesDiagram-ULZ7WXOC-DoAqfWAd.js +8 -0
  74. package/dist/web/assets/{timeline-definition-Z64GVDOM-Cyh2AdbF.js → timeline-definition-Z64GVDOM-BA3y-16W.js} +1 -1
  75. package/dist/web/assets/{treeView-QDETBFTQ-zPmED5io.js → treeView-QDETBFTQ-BUNq-JXr.js} +1 -1
  76. package/dist/web/assets/{treemap-6X3UGDF4-Cd2gjC8X.js → treemap-6X3UGDF4-FIR_NbUo.js} +1 -1
  77. package/dist/web/assets/{vennDiagram-T6HMQDX7-BaNEKHnw.js → vennDiagram-T6HMQDX7-IeFFjnlq.js} +1 -1
  78. package/dist/web/assets/{wardley-OPB4EBWU-B5ry0Fo7.js → wardley-OPB4EBWU-DQAX4LKo.js} +1 -1
  79. package/dist/web/assets/{wardleyDiagram-T6FBY63Y-BHvM4Wb0.js → wardleyDiagram-T6FBY63Y-guGPPMAG.js} +1 -1
  80. package/dist/web/assets/{xychartDiagram-ELKLHX3M-Qgza2Rjo.js → xychartDiagram-ELKLHX3M-Cj0v359_.js} +1 -1
  81. package/dist/web/index.html +2 -2
  82. package/migrations/009_comment_watch.sql +30 -0
  83. package/migrations/010_comment_post_references.sql +17 -0
  84. package/package.json +1 -1
  85. package/skills/rvw/SKILL.md +117 -6
  86. package/skills/rvw/agents/openai.yaml +2 -2
  87. package/skills/rvw-walkthrough/SKILL.md +18 -9
  88. package/skills/rvw-walkthrough/references/walkthrough-authoring.md +105 -0
  89. package/skills/rvw-watch-comments/SKILL.md +294 -0
  90. package/skills/rvw-watch-comments/agents/openai.yaml +4 -0
  91. package/skills/rvw-watch-comments/scripts/auto-ack.mjs +211 -0
  92. package/skills/rvw-watch-comments/scripts/preflight.mjs +108 -0
  93. package/skills/rvw-watch-comments/scripts/rvw-command.mjs +80 -0
  94. package/skills/rvw-watch-comments/scripts/watch-driver.mjs +272 -0
  95. package/skills/rvw-watch-comments/scripts/watch-state.mjs +827 -0
  96. package/dist/web/assets/DocumentViewer-ERTovlNY.js +0 -1560
  97. package/dist/web/assets/MarkdownImagePlaceholder-BseUb-vG.js +0 -36
  98. package/dist/web/assets/WalkthroughViewer-4HaKxbeO.js +0 -2
  99. package/dist/web/assets/architecture-TIHT7OUA-9PYQORPB.js +0 -1
  100. package/dist/web/assets/channel-zAJ9N7Xu.js +0 -1
  101. package/dist/web/assets/classDiagram-JCYQIIEL-DW7PwlYE.js +0 -1
  102. package/dist/web/assets/classDiagram-v2-OCEON4UE-DW7PwlYE.js +0 -1
  103. package/dist/web/assets/eventmodeling-45OFAUF4-mByhu-2v.js +0 -1
  104. package/dist/web/assets/flowDiagram-UKHOOZJN-DTgITdYW.js +0 -1
  105. package/dist/web/assets/index-B8_aim9s.css +0 -1
  106. package/dist/web/assets/index-DAM-rdgA.js +0 -355
  107. package/dist/web/assets/railroad-abnf-AHOZXSZD-D0hTyA1H.js +0 -1
  108. package/dist/web/assets/railroad-ebnf-EBAXGLYW-DzkmoqWU.js +0 -1
  109. package/dist/web/assets/railroad-peg-LSFZ7HO6-u3hJ9iID.js +0 -1
  110. package/dist/web/assets/stateDiagram-v2-UEYNNEHI-BY3gjuqo.js +0 -1
  111. package/dist/web/assets/swimlanesDiagram-ULZ7WXOC-DK-u00Uf.js +0 -8
package/dist/cli.mjs CHANGED
@@ -18512,7 +18512,7 @@ function date4(params) {
18512
18512
  config(en_default());
18513
18513
 
18514
18514
  // src/infrastructure/db/database.ts
18515
- import { randomUUID } from "node:crypto";
18515
+ import { createHash, randomUUID } from "node:crypto";
18516
18516
  import {
18517
18517
  chmodSync,
18518
18518
  closeSync,
@@ -18736,6 +18736,9 @@ function mapPullRequest(row) {
18736
18736
  repository: stringValue(row, "repository"),
18737
18737
  number: numberValue(row, "number"),
18738
18738
  url: stringValue(row, "github_url"),
18739
+ latestAuthorLogin: nullableString(row, "latest_author_login"),
18740
+ latestHeadRepositoryOwner: nullableString(row, "latest_head_repository_owner"),
18741
+ latestHeadRepositoryName: nullableString(row, "latest_head_repository_name"),
18739
18742
  localRepositoryPath: stringValue(row, "local_repository_path"),
18740
18743
  gitCommonDir: stringValue(row, "git_common_dir"),
18741
18744
  latestTitle: stringValue(row, "latest_title"),
@@ -18751,6 +18754,32 @@ function mapPullRequest(row) {
18751
18754
  updatedAt: stringValue(row, "updated_at")
18752
18755
  };
18753
18756
  }
18757
+ function mapCodeReference(row) {
18758
+ return {
18759
+ id: stringValue(row, "reference_id"),
18760
+ label: stringValue(row, "label"),
18761
+ path: stringValue(row, "file_path"),
18762
+ startLine: nullableNumber(row, "start_line"),
18763
+ endLine: nullableNumber(row, "end_line"),
18764
+ description: nullableString(row, "description")
18765
+ };
18766
+ }
18767
+ function mapCommentPost(row, references = []) {
18768
+ return {
18769
+ id: stringValue(row, "id"),
18770
+ commentId: stringValue(row, "comment_id"),
18771
+ body: stringValue(row, "body"),
18772
+ relatedCommitOid: nullableString(row, "related_commit_oid"),
18773
+ references,
18774
+ authorLabel: nullableString(row, "author_label"),
18775
+ isRoot: numberValue(row, "is_root") === 1,
18776
+ createdAt: stringValue(row, "created_at"),
18777
+ updatedAt: stringValue(row, "updated_at")
18778
+ };
18779
+ }
18780
+ function hashIdempotencyKey(value) {
18781
+ return createHash("sha256").update(value, "utf8").digest("hex");
18782
+ }
18754
18783
  function findMigrationsDirectory(explicit) {
18755
18784
  if (explicit) return explicit;
18756
18785
  const moduleDirectory = path4.dirname(fileURLToPath2(import.meta.url));
@@ -18982,6 +19011,33 @@ var RvwDatabase = class {
18982
19011
  const row = this.database.prepare("SELECT value FROM app_meta WHERE key = 'change_sequence'").get();
18983
19012
  return Number(stringValue(row, "value"));
18984
19013
  }
19014
+ getCommentWatchDatabaseId() {
19015
+ const row = this.database.prepare("SELECT value FROM app_meta WHERE key = 'comment_watch_database_id'").get();
19016
+ if (!row) throw new RvwError("DATABASE_ERROR", "comment watch\u306Edatabase ID\u304C\u3042\u308A\u307E\u305B\u3093\u3002");
19017
+ return stringValue(row, "value");
19018
+ }
19019
+ getLatestCommentPostEventSequence() {
19020
+ const row = this.database.prepare("SELECT COALESCE(MAX(sequence), 0) AS sequence FROM comment_post_events").get();
19021
+ return numberValue(row, "sequence");
19022
+ }
19023
+ listCommentPostEvents(afterSequence, limit) {
19024
+ const rows = this.database.prepare(
19025
+ `SELECT e.*, CASE WHEN p.id IS NULL THEN 1 ELSE 0 END AS deleted
19026
+ FROM comment_post_events e
19027
+ LEFT JOIN comment_posts p ON p.id = e.post_id
19028
+ WHERE e.sequence > ?
19029
+ ORDER BY e.sequence ASC
19030
+ LIMIT ?`
19031
+ ).all(afterSequence, limit);
19032
+ return rows.map((row) => ({
19033
+ sequence: numberValue(row, "sequence"),
19034
+ createdAt: stringValue(row, "created_at"),
19035
+ postId: stringValue(row, "post_id"),
19036
+ commentRef: stringValue(row, "comment_ref"),
19037
+ pullRequestUrl: stringValue(row, "pull_request_url"),
19038
+ deleted: numberValue(row, "deleted") === 1
19039
+ }));
19040
+ }
18985
19041
  getThemePreference() {
18986
19042
  const row = this.database.prepare("SELECT value FROM app_meta WHERE key = 'theme_preference'").get();
18987
19043
  if (!row) {
@@ -19037,14 +19093,18 @@ var RvwDatabase = class {
19037
19093
  `INSERT INTO pull_requests(
19038
19094
  id, host, owner, repository, number, github_url,
19039
19095
  local_repository_path, git_common_dir,
19096
+ latest_author_login, latest_head_repository_owner, latest_head_repository_name,
19040
19097
  latest_title, latest_body, latest_base_ref_name, latest_head_ref_name,
19041
19098
  latest_base_oid, latest_head_oid, github_updated_at, fetched_at,
19042
19099
  created_at, updated_at, latest_comparison_base_oid
19043
- ) VALUES (?, 'github.com', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
19100
+ ) VALUES (?, 'github.com', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
19044
19101
  ON CONFLICT(host, owner, repository, number) DO UPDATE SET
19045
19102
  github_url = excluded.github_url,
19046
19103
  local_repository_path = excluded.local_repository_path,
19047
19104
  git_common_dir = excluded.git_common_dir,
19105
+ latest_author_login = excluded.latest_author_login,
19106
+ latest_head_repository_owner = excluded.latest_head_repository_owner,
19107
+ latest_head_repository_name = excluded.latest_head_repository_name,
19048
19108
  latest_title = excluded.latest_title,
19049
19109
  latest_body = excluded.latest_body,
19050
19110
  latest_base_ref_name = excluded.latest_base_ref_name,
@@ -19063,6 +19123,9 @@ var RvwDatabase = class {
19063
19123
  github.url,
19064
19124
  repository.localRepositoryPath,
19065
19125
  repository.gitCommonDir,
19126
+ github.authorLogin,
19127
+ github.headRepositoryOwner,
19128
+ github.headRepositoryName,
19066
19129
  github.title,
19067
19130
  github.body,
19068
19131
  github.baseRefName,
@@ -19117,6 +19180,16 @@ var RvwDatabase = class {
19117
19180
  const posts = this.database.prepare(
19118
19181
  "SELECT count(*) AS count FROM comment_posts WHERE comment_id IN (SELECT id FROM comments WHERE pull_request_id = ?)"
19119
19182
  ).get(pullRequestId);
19183
+ const commentReferences = this.database.prepare(
19184
+ `SELECT count(*) AS count
19185
+ FROM comment_post_references
19186
+ WHERE post_id IN (
19187
+ SELECT posts.id
19188
+ FROM comment_posts AS posts
19189
+ JOIN comments ON comments.id = posts.comment_id
19190
+ WHERE comments.pull_request_id = ?
19191
+ )`
19192
+ ).get(pullRequestId);
19120
19193
  const targets = this.database.prepare(
19121
19194
  "SELECT count(*) AS count FROM comment_targets WHERE comment_id IN (SELECT id FROM comments WHERE pull_request_id = ?)"
19122
19195
  ).get(pullRequestId);
@@ -19127,6 +19200,7 @@ var RvwDatabase = class {
19127
19200
  return {
19128
19201
  comments: numberValue(comments, "count"),
19129
19202
  posts: numberValue(posts, "count"),
19203
+ commentReferences: numberValue(commentReferences, "count"),
19130
19204
  targets: numberValue(targets, "count"),
19131
19205
  walkthroughs: numberValue(walkthroughs, "count"),
19132
19206
  walkthroughReferences: numberValue(walkthroughReferences, "count"),
@@ -19137,17 +19211,34 @@ var RvwDatabase = class {
19137
19211
  this.database.prepare("DELETE FROM comments WHERE pull_request_id = ?").run(pullRequestId);
19138
19212
  this.database.prepare("DELETE FROM walkthroughs WHERE pull_request_id = ?").run(pullRequestId);
19139
19213
  }
19140
- listWalkthroughReferences(walkthroughId) {
19141
- return this.database.prepare(
19142
- "SELECT * FROM walkthrough_references WHERE walkthrough_id = ? ORDER BY sort_order ASC"
19143
- ).all(walkthroughId).map((row) => ({
19144
- id: stringValue(row, "reference_id"),
19145
- label: stringValue(row, "label"),
19146
- path: stringValue(row, "file_path"),
19147
- startLine: nullableNumber(row, "start_line"),
19148
- endLine: nullableNumber(row, "end_line"),
19149
- description: nullableString(row, "description")
19150
- }));
19214
+ codeReferenceStorage(kind) {
19215
+ return kind === "comment-post" ? { table: "comment_post_references", ownerColumn: "post_id" } : { table: "walkthrough_references", ownerColumn: "walkthrough_id" };
19216
+ }
19217
+ listCodeReferences(kind, ownerId) {
19218
+ const { table, ownerColumn } = this.codeReferenceStorage(kind);
19219
+ return this.database.prepare(`SELECT * FROM ${table} WHERE ${ownerColumn} = ? ORDER BY sort_order ASC`).all(ownerId).map(mapCodeReference);
19220
+ }
19221
+ insertCodeReferences(kind, ownerId, references) {
19222
+ if (references.length === 0) return;
19223
+ const { table, ownerColumn } = this.codeReferenceStorage(kind);
19224
+ const insertReference = this.database.prepare(
19225
+ `INSERT INTO ${table}(
19226
+ ${ownerColumn}, reference_id, label, file_path, start_line, end_line,
19227
+ description, sort_order
19228
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
19229
+ );
19230
+ references.forEach((reference, index2) => {
19231
+ insertReference.run(
19232
+ ownerId,
19233
+ reference.id,
19234
+ reference.label,
19235
+ reference.path,
19236
+ reference.startLine,
19237
+ reference.endLine,
19238
+ reference.description,
19239
+ index2
19240
+ );
19241
+ });
19151
19242
  }
19152
19243
  mapWalkthrough(row) {
19153
19244
  const id = stringValue(row, "id");
@@ -19160,7 +19251,7 @@ var RvwDatabase = class {
19160
19251
  body: stringValue(row, "body"),
19161
19252
  authorLabel: nullableString(row, "author_label"),
19162
19253
  diagramBindings: stringRecordValue(row, "diagram_bindings_json"),
19163
- references: this.listWalkthroughReferences(id),
19254
+ references: this.listCodeReferences("walkthrough", id),
19164
19255
  createdAt: stringValue(row, "created_at")
19165
19256
  };
19166
19257
  }
@@ -19206,7 +19297,7 @@ var RvwDatabase = class {
19206
19297
  JSON.stringify(input.diagramBindings),
19207
19298
  now
19208
19299
  );
19209
- this.insertWalkthroughReferences(id, input.references);
19300
+ this.insertCodeReferences("walkthrough", id, input.references);
19210
19301
  this.incrementChangeSequence();
19211
19302
  });
19212
19303
  const walkthrough = this.getWalkthrough(id);
@@ -19215,26 +19306,6 @@ var RvwDatabase = class {
19215
19306
  }
19216
19307
  return walkthrough;
19217
19308
  }
19218
- insertWalkthroughReferences(walkthroughId, references) {
19219
- const insertReference = this.database.prepare(
19220
- `INSERT INTO walkthrough_references(
19221
- walkthrough_id, reference_id, label, file_path, start_line, end_line,
19222
- description, sort_order
19223
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
19224
- );
19225
- references.forEach((reference, index2) => {
19226
- insertReference.run(
19227
- walkthroughId,
19228
- reference.id,
19229
- reference.label,
19230
- reference.path,
19231
- reference.startLine,
19232
- reference.endLine,
19233
- reference.description,
19234
- index2
19235
- );
19236
- });
19237
- }
19238
19309
  updateWalkthrough(id, input) {
19239
19310
  this.immediateTransaction(() => {
19240
19311
  const result = this.database.prepare(
@@ -19253,7 +19324,7 @@ var RvwDatabase = class {
19253
19324
  throw new RvwError("NOT_FOUND", "Walkthrough\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", { status: 404 });
19254
19325
  }
19255
19326
  this.database.prepare("DELETE FROM walkthrough_references WHERE walkthrough_id = ?").run(id);
19256
- this.insertWalkthroughReferences(id, input.references);
19327
+ this.insertCodeReferences("walkthrough", id, input.references);
19257
19328
  this.incrementChangeSequence();
19258
19329
  });
19259
19330
  const walkthrough = this.getWalkthrough(id);
@@ -19303,14 +19374,30 @@ var RvwDatabase = class {
19303
19374
  const now = (/* @__PURE__ */ new Date()).toISOString();
19304
19375
  const id = randomUUID();
19305
19376
  const postId = randomUUID();
19377
+ const pullRequest = this.getPullRequest(input.pullRequestId);
19378
+ if (!pullRequest) throw new RvwError("PR_NOT_FOUND", "Pull Request\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002");
19306
19379
  this.immediateTransaction(() => {
19307
19380
  this.database.prepare(
19308
19381
  "INSERT INTO comments(id, pull_request_id, created_head_oid, resolved_at, created_at, updated_at) VALUES (?, ?, ?, NULL, ?, ?)"
19309
19382
  ).run(id, input.pullRequestId, input.createdHeadOid, now, now);
19310
19383
  this.insertCommentTarget(id, input.target);
19311
19384
  this.database.prepare(
19312
- "INSERT INTO comment_posts(id, comment_id, body, related_commit_oid, author_label, is_root, created_at, updated_at) VALUES (?, ?, ?, NULL, ?, 1, ?, ?)"
19313
- ).run(postId, id, input.body, input.authorLabel ?? null, now, now);
19385
+ "INSERT INTO comment_posts(id, comment_id, body, related_commit_oid, author_label, is_root, created_at, updated_at) VALUES (?, ?, ?, ?, ?, 1, ?, ?)"
19386
+ ).run(
19387
+ postId,
19388
+ id,
19389
+ input.body,
19390
+ input.relatedCommitOid ?? null,
19391
+ input.authorLabel ?? null,
19392
+ now,
19393
+ now
19394
+ );
19395
+ this.insertCodeReferences("comment-post", postId, input.references ?? []);
19396
+ this.database.prepare(
19397
+ `INSERT INTO comment_post_events(
19398
+ post_id, comment_ref, pull_request_url, created_at
19399
+ ) VALUES (?, ?, ?, ?)`
19400
+ ).run(postId, formatCommentUri(id), pullRequest.url, now);
19314
19401
  this.incrementChangeSequence();
19315
19402
  });
19316
19403
  const comment = this.getComment(id);
@@ -19461,6 +19548,7 @@ var RvwDatabase = class {
19461
19548
  commentId: comment.id,
19462
19549
  body: stringValue(row, "root_body"),
19463
19550
  relatedCommitOid: nullableString(row, "root_related_commit_oid"),
19551
+ references: [],
19464
19552
  authorLabel: nullableString(row, "root_author_label"),
19465
19553
  isRoot: true,
19466
19554
  createdAt: stringValue(row, "root_created_at"),
@@ -19474,65 +19562,116 @@ var RvwDatabase = class {
19474
19562
  listCommentPosts(commentId) {
19475
19563
  return this.database.prepare(
19476
19564
  "SELECT * FROM comment_posts WHERE comment_id = ? ORDER BY is_root DESC, created_at ASC, id ASC"
19477
- ).all(commentId).map((row) => ({
19478
- id: stringValue(row, "id"),
19479
- commentId: stringValue(row, "comment_id"),
19480
- body: stringValue(row, "body"),
19481
- relatedCommitOid: nullableString(row, "related_commit_oid"),
19482
- authorLabel: nullableString(row, "author_label"),
19483
- isRoot: numberValue(row, "is_root") === 1,
19484
- createdAt: stringValue(row, "created_at"),
19485
- updatedAt: stringValue(row, "updated_at")
19486
- }));
19565
+ ).all(commentId).map((row) => {
19566
+ const postId = stringValue(row, "id");
19567
+ return mapCommentPost(row, this.listCodeReferences("comment-post", postId));
19568
+ });
19569
+ }
19570
+ getCommentPost(postId) {
19571
+ const row = this.database.prepare("SELECT * FROM comment_posts WHERE id = ?").get(postId);
19572
+ return row ? mapCommentPost(row, this.listCodeReferences("comment-post", postId)) : null;
19487
19573
  }
19488
19574
  insertReply(commentId, input, incrementSequence = true) {
19489
- if (!this.getComment(commentId))
19490
- throw new RvwError("COMMENT_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002");
19491
- const id = randomUUID();
19492
- const now = (/* @__PURE__ */ new Date()).toISOString();
19575
+ let result;
19493
19576
  const write = () => {
19577
+ const comment = this.getComment(commentId);
19578
+ if (!comment) {
19579
+ throw new RvwError("COMMENT_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002");
19580
+ }
19581
+ const pullRequest = this.getPullRequest(comment.pullRequestId);
19582
+ if (!pullRequest) throw new RvwError("PR_NOT_FOUND", "Pull Request\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002");
19583
+ const relatedCommitOid = input.relatedCommitOid ?? null;
19584
+ const authorLabel = input.authorLabel ?? null;
19585
+ const idempotencyKeyHash = input.idempotencyKey === void 0 ? null : hashIdempotencyKey(input.idempotencyKey);
19586
+ const idempotencyRequestHash2 = idempotencyKeyHash === null ? null : input.idempotencyRequestHash ?? hashIdempotencyKey(
19587
+ JSON.stringify({
19588
+ operation: "comment.reply",
19589
+ commentId,
19590
+ body: input.body,
19591
+ relatedCommitOid,
19592
+ authorLabel,
19593
+ references: input.references ?? []
19594
+ })
19595
+ );
19596
+ if (idempotencyKeyHash !== null) {
19597
+ const existingRow = this.database.prepare("SELECT * FROM comment_reply_idempotency WHERE key_hash = ?").get(idempotencyKeyHash);
19598
+ if (existingRow) {
19599
+ if (stringValue(existingRow, "request_hash") !== idempotencyRequestHash2) {
19600
+ throw new RvwError(
19601
+ "IDEMPOTENCY_CONFLICT",
19602
+ "\u540C\u3058idempotencyKey\u304C\u5225\u306Ecomment reply\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002"
19603
+ );
19604
+ }
19605
+ const postId = stringValue(existingRow, "post_id");
19606
+ const existing = this.getCommentPost(postId);
19607
+ if (!existing) {
19608
+ throw new RvwError(
19609
+ "IDEMPOTENCY_RESULT_DELETED",
19610
+ "\u3053\u306EidempotencyKey\u3067\u4F5C\u6210\u3057\u305Fcomment reply\u306F\u65E2\u306B\u524A\u9664\u3055\u308C\u3066\u3044\u307E\u3059\u3002",
19611
+ { details: { postId } }
19612
+ );
19613
+ }
19614
+ result = existing;
19615
+ return;
19616
+ }
19617
+ }
19618
+ const id = randomUUID();
19619
+ const now = (/* @__PURE__ */ new Date()).toISOString();
19494
19620
  this.database.prepare(
19495
19621
  "INSERT INTO comment_posts(id, comment_id, body, related_commit_oid, author_label, is_root, created_at, updated_at) VALUES (?, ?, ?, ?, ?, 0, ?, ?)"
19496
- ).run(
19497
- id,
19498
- commentId,
19499
- input.body,
19500
- input.relatedCommitOid ?? null,
19501
- input.authorLabel ?? null,
19502
- now,
19503
- now
19504
- );
19622
+ ).run(id, commentId, input.body, relatedCommitOid, authorLabel, now, now);
19623
+ this.insertCodeReferences("comment-post", id, input.references ?? []);
19624
+ this.database.prepare(
19625
+ `INSERT INTO comment_post_events(
19626
+ post_id, comment_ref, pull_request_url, created_at
19627
+ ) VALUES (?, ?, ?, ?)`
19628
+ ).run(id, comment.ref, pullRequest.url, now);
19629
+ if (idempotencyKeyHash !== null && idempotencyRequestHash2 !== null) {
19630
+ this.database.prepare(
19631
+ "INSERT INTO comment_reply_idempotency(key_hash, request_hash, post_id, created_at) VALUES (?, ?, ?, ?)"
19632
+ ).run(idempotencyKeyHash, idempotencyRequestHash2, id, now);
19633
+ }
19505
19634
  this.database.prepare("UPDATE comments SET updated_at = ? WHERE id = ?").run(now, commentId);
19506
19635
  if (incrementSequence) this.incrementChangeSequence();
19636
+ result = {
19637
+ id,
19638
+ commentId,
19639
+ body: input.body,
19640
+ relatedCommitOid,
19641
+ references: input.references ?? [],
19642
+ authorLabel,
19643
+ isRoot: false,
19644
+ createdAt: now,
19645
+ updatedAt: now
19646
+ };
19507
19647
  };
19508
19648
  if (incrementSequence) this.immediateTransaction(write);
19509
19649
  else write();
19510
- return {
19511
- id,
19512
- commentId,
19513
- body: input.body,
19514
- relatedCommitOid: input.relatedCommitOid ?? null,
19515
- authorLabel: input.authorLabel ?? null,
19516
- isRoot: false,
19517
- createdAt: now,
19518
- updatedAt: now
19519
- };
19650
+ if (!result) throw new RvwError("DATABASE_ERROR", "\u8FD4\u4FE1\u7D50\u679C\u3092\u8AAD\u307F\u51FA\u305B\u307E\u305B\u3093\u3002");
19651
+ return result;
19520
19652
  }
19521
- updateCommentPost(commentId, postId, body) {
19653
+ updateCommentPost(commentId, postId, body, relatedCommitOid, references) {
19522
19654
  const now = (/* @__PURE__ */ new Date()).toISOString();
19523
19655
  this.immediateTransaction(() => {
19524
- const result = this.database.prepare(
19656
+ const result = relatedCommitOid === void 0 ? this.database.prepare(
19525
19657
  "UPDATE comment_posts SET body = ?, updated_at = ? WHERE id = ? AND comment_id = ?"
19526
- ).run(body, now, postId, commentId);
19658
+ ).run(body, now, postId, commentId) : this.database.prepare(
19659
+ `UPDATE comment_posts SET body = ?, related_commit_oid = ?, updated_at = ?
19660
+ WHERE id = ? AND comment_id = ?`
19661
+ ).run(body, relatedCommitOid, now, postId, commentId);
19527
19662
  if (Number(result.changes) === 0) {
19528
19663
  throw new RvwError("COMMENT_POST_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u6295\u7A3F\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", {
19529
19664
  status: 404
19530
19665
  });
19531
19666
  }
19667
+ if (references !== void 0) {
19668
+ this.database.prepare("DELETE FROM comment_post_references WHERE post_id = ?").run(postId);
19669
+ this.insertCodeReferences("comment-post", postId, references);
19670
+ }
19532
19671
  this.database.prepare("UPDATE comments SET updated_at = ? WHERE id = ?").run(now, commentId);
19533
19672
  this.incrementChangeSequence();
19534
19673
  });
19535
- const post = this.listCommentPosts(commentId).find((candidate) => candidate.id === postId);
19674
+ const post = this.getCommentPost(postId);
19536
19675
  if (!post) {
19537
19676
  throw new RvwError("COMMENT_POST_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u6295\u7A3F\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", {
19538
19677
  status: 404
@@ -19599,7 +19738,10 @@ var RvwDatabase = class {
19599
19738
  {
19600
19739
  body: update.reply,
19601
19740
  relatedCommitOid,
19602
- authorLabel: update.authorLabel ?? "Agent"
19741
+ references: update.references ?? [],
19742
+ authorLabel: update.authorLabel ?? "Agent",
19743
+ ...update.idempotencyKey === void 0 ? {} : { idempotencyKey: update.idempotencyKey },
19744
+ ...update.idempotencyRequestHash === void 0 ? {} : { idempotencyRequestHash: update.idempotencyRequestHash }
19603
19745
  },
19604
19746
  false
19605
19747
  );
@@ -19617,23 +19759,28 @@ import path5 from "node:path";
19617
19759
  import { TextDecoder as TextDecoder2 } from "node:util";
19618
19760
 
19619
19761
  // src/shared/constants.ts
19620
- var APP_VERSION = "0.1.1";
19621
- var PROTOCOL_VERSION = 2;
19762
+ var APP_VERSION = "0.2.1";
19763
+ var PROTOCOL_VERSION = 3;
19622
19764
  var VIEWER_ID_HEADER = "x-rvw-viewer-id";
19623
19765
  var GIT_OBJECT_ID_PATTERN = /^[0-9a-f]{40,64}$/i;
19624
19766
  var MAX_TEXT_DOCUMENT_BYTES = 1024 * 1024;
19625
19767
  var MAX_MARKDOWN_ASSET_BYTES = 5 * 1024 * 1024;
19626
19768
  var MAX_COMMENT_BODY_BYTES = 64 * 1024;
19627
19769
  var MAX_AUTHOR_LABEL_CHARACTERS = 100;
19770
+ var MAX_IDEMPOTENCY_KEY_CHARACTERS = 200;
19628
19771
  var DEFAULT_COMMENT_LIST_LIMIT = 50;
19629
19772
  var MAX_COMMENT_LIST_LIMIT = 100;
19773
+ var DEFAULT_COMMENT_WATCH_LIMIT = 100;
19774
+ var MAX_COMMENT_WATCH_LIMIT = 100;
19775
+ var DEFAULT_COMMENT_WATCH_INTERVAL_SECONDS = 10;
19776
+ var MAX_COMMENT_WATCH_INTERVAL_SECONDS = 300;
19630
19777
  var MAX_COMMENT_LIST_BODY_PREVIEW_BYTES = 512;
19778
+ var MAX_CODE_REFERENCES = 200;
19779
+ var MAX_CODE_REFERENCE_LABEL_CHARACTERS = 200;
19780
+ var MAX_CODE_REFERENCE_PATH_CHARACTERS = 4096;
19781
+ var MAX_CODE_REFERENCE_DESCRIPTION_CHARACTERS = 1e3;
19631
19782
  var MAX_WALKTHROUGH_BODY_BYTES = 256 * 1024;
19632
- var MAX_WALKTHROUGH_REFERENCES = 200;
19633
19783
  var MAX_WALKTHROUGH_TITLE_CHARACTERS = 200;
19634
- var MAX_WALKTHROUGH_REFERENCE_LABEL_CHARACTERS = 200;
19635
- var MAX_WALKTHROUGH_REFERENCE_PATH_CHARACTERS = 4096;
19636
- var MAX_WALKTHROUGH_REFERENCE_DESCRIPTION_CHARACTERS = 1e3;
19637
19784
  var MAX_SEARCH_QUERY_BYTES = 1024;
19638
19785
  var MAX_SEARCH_RESULTS = 500;
19639
19786
  var MAX_SEARCH_STDOUT_BYTES = 8 * 1024 * 1024;
@@ -20269,6 +20416,9 @@ var GitClient = class {
20269
20416
 
20270
20417
  // src/infrastructure/github/github-client.ts
20271
20418
  var ghPullRequestSchema = external_exports.object({
20419
+ author: external_exports.object({ login: external_exports.string().min(1) }).nullable(),
20420
+ headRepository: external_exports.object({ name: external_exports.string().min(1) }).nullable(),
20421
+ headRepositoryOwner: external_exports.object({ login: external_exports.string().min(1) }).nullable(),
20272
20422
  number: external_exports.number().int().positive(),
20273
20423
  url: external_exports.url(),
20274
20424
  title: external_exports.string(),
@@ -20309,6 +20459,7 @@ var GitHubClient = class {
20309
20459
  async getPullRequest(reference, cwd) {
20310
20460
  await this.assertAuthenticated();
20311
20461
  const fields = [
20462
+ "author",
20312
20463
  "number",
20313
20464
  "url",
20314
20465
  "title",
@@ -20358,6 +20509,9 @@ var GitHubClient = class {
20358
20509
  repository: identity.repository,
20359
20510
  number: parsed.data.number,
20360
20511
  url: parsed.data.url,
20512
+ authorLogin: parsed.data.author?.login ?? null,
20513
+ headRepositoryOwner: parsed.data.headRepositoryOwner?.login ?? null,
20514
+ headRepositoryName: parsed.data.headRepository?.name ?? null,
20361
20515
  title: parsed.data.title,
20362
20516
  body: parsed.data.body ?? "",
20363
20517
  baseRefName: parsed.data.baseRefName,
@@ -20372,6 +20526,7 @@ var GitHubClient = class {
20372
20526
  };
20373
20527
 
20374
20528
  // src/application/rvw-service.ts
20529
+ import { createHash as createHash3 } from "node:crypto";
20375
20530
  import path6 from "node:path";
20376
20531
 
20377
20532
  // node_modules/.pnpm/mdast-util-to-string@4.0.0/node_modules/mdast-util-to-string/lib/index.js
@@ -27307,6 +27462,28 @@ function defaultOnError(left, right) {
27307
27462
  }
27308
27463
  }
27309
27464
 
27465
+ // src/domain/comment-watch-cursor.ts
27466
+ var CURSOR_VERSION = 1;
27467
+ var DATABASE_ID_PATTERN = /^[0-9a-f]{32}$/;
27468
+ function formatCommentWatchCursor(cursor) {
27469
+ return Buffer.from(
27470
+ JSON.stringify({ v: CURSOR_VERSION, d: cursor.databaseId, s: cursor.sequence }),
27471
+ "utf8"
27472
+ ).toString("base64url");
27473
+ }
27474
+ function parseCommentWatchCursor(value) {
27475
+ try {
27476
+ if (value.length === 0 || value.length > 512) throw new Error("cursor length");
27477
+ const decoded = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
27478
+ if (decoded.v !== CURSOR_VERSION || typeof decoded.d !== "string" || !DATABASE_ID_PATTERN.test(decoded.d) || typeof decoded.s !== "number" || !Number.isSafeInteger(decoded.s) || decoded.s < 0) {
27479
+ throw new Error("cursor shape");
27480
+ }
27481
+ return { databaseId: decoded.d, sequence: decoded.s };
27482
+ } catch (error51) {
27483
+ throw new RvwError("INVALID_INPUT", "comment watch cursor\u304C\u4E0D\u6B63\u3067\u3059\u3002", { cause: error51 });
27484
+ }
27485
+ }
27486
+
27310
27487
  // node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/diff/base.js
27311
27488
  var Diff = class {
27312
27489
  diff(oldStr, newStr, options = {}) {
@@ -27527,7 +27704,7 @@ function diffArrays(oldArr, newArr, options) {
27527
27704
  }
27528
27705
 
27529
27706
  // src/domain/pr-markdown.ts
27530
- import { createHash } from "node:crypto";
27707
+ import { createHash as createHash2 } from "node:crypto";
27531
27708
  function normalizeLf(value) {
27532
27709
  return value.replace(/\r\n?/g, "\n");
27533
27710
  }
@@ -27537,7 +27714,7 @@ function buildPullRequestMarkdown(title, body) {
27537
27714
  ${normalizeLf(body)}`;
27538
27715
  }
27539
27716
  function hashDocument(value) {
27540
- return createHash("sha256").update(normalizeLf(value), "utf8").digest("hex");
27717
+ return createHash2("sha256").update(normalizeLf(value), "utf8").digest("hex");
27541
27718
  }
27542
27719
  function selectedLineText(value, startLine, endLine) {
27543
27720
  const lines2 = normalizeLf(value).split("\n");
@@ -27686,12 +27863,24 @@ function assertAuthorLabel(authorLabel) {
27686
27863
  );
27687
27864
  }
27688
27865
  }
27866
+ function assertIdempotencyKey(idempotencyKey2) {
27867
+ if (idempotencyKey2 === void 0) return;
27868
+ if (idempotencyKey2.length === 0 || idempotencyKey2.length > MAX_IDEMPOTENCY_KEY_CHARACTERS) {
27869
+ throw new RvwError(
27870
+ "INVALID_INPUT",
27871
+ `idempotencyKey\u306F1\u301C${MAX_IDEMPOTENCY_KEY_CHARACTERS}\u6587\u5B57\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
27872
+ );
27873
+ }
27874
+ }
27875
+ function idempotencyRequestHash(value) {
27876
+ return createHash3("sha256").update(JSON.stringify(value), "utf8").digest("hex");
27877
+ }
27689
27878
  function assertLinePair(startLine, endLine) {
27690
27879
  if (startLine === null !== (endLine === null)) {
27691
27880
  throw new RvwError("INVALID_INPUT", "\u884C\u7BC4\u56F2\u306F\u958B\u59CB\u884C\u3068\u7D42\u4E86\u884C\u3092\u4E21\u65B9\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
27692
27881
  }
27693
27882
  }
27694
- var walkthroughReferenceIdPattern = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
27883
+ var codeReferenceIdPattern = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
27695
27884
  var walkthroughDiagramNodePattern = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
27696
27885
  var mermaidIdentifierPattern = /[A-Za-z][A-Za-z0-9_-]{0,63}/g;
27697
27886
  var mermaidEdgePattern = /[<|o*x]*[-.=~]{2,}[|o*x>]*/g;
@@ -27785,7 +27974,7 @@ function addMermaidDiagramNodes(source, nodeIds) {
27785
27974
  }
27786
27975
  }
27787
27976
  }
27788
- function analyzeWalkthroughMarkdown(body) {
27977
+ function analyzeReferenceMarkdown(body) {
27789
27978
  const root = fromMarkdown(body);
27790
27979
  const definitions = /* @__PURE__ */ new Map();
27791
27980
  const visit = (node2, callback) => {
@@ -27814,9 +28003,9 @@ function analyzeWalkthroughMarkdown(body) {
27814
28003
  mermaidNodeIds
27815
28004
  };
27816
28005
  }
27817
- function assertWalkthroughPath(filePath) {
27818
- if (filePath.length > MAX_WALKTHROUGH_REFERENCE_PATH_CHARACTERS || filePath.includes("\\") || path6.posix.isAbsolute(filePath) || path6.posix.normalize(filePath) !== filePath || filePath === "." || filePath.startsWith("../")) {
27819
- throw new RvwError("INVALID_INPUT", `walkthrough\u306Epath\u304C\u4E0D\u6B63\u3067\u3059: ${filePath}`);
28006
+ function assertCodeReferencePath(filePath) {
28007
+ if (filePath.length > MAX_CODE_REFERENCE_PATH_CHARACTERS || filePath.includes("\\") || path6.posix.isAbsolute(filePath) || path6.posix.normalize(filePath) !== filePath || filePath === "." || filePath.startsWith("../")) {
28008
+ throw new RvwError("INVALID_INPUT", `code reference\u306Epath\u304C\u4E0D\u6B63\u3067\u3059: ${filePath}`);
27820
28009
  }
27821
28010
  }
27822
28011
  var RvwService = class {
@@ -27969,13 +28158,33 @@ var RvwService = class {
27969
28158
  `commentUpdates\u306B\u306Freply\u307E\u305F\u306Fresolve\u304C\u5FC5\u8981\u3067\u3059: ${update.commentRef}`
27970
28159
  );
27971
28160
  }
28161
+ if (!update.reply.trim() && (update.references?.length ?? 0) > 0) {
28162
+ throw new RvwError(
28163
+ "INVALID_INPUT",
28164
+ `reply\u306E\u306A\u3044comment update\u3078code reference\u306F\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093: ${update.commentRef}`
28165
+ );
28166
+ }
27972
28167
  if (update.reply.trim()) assertTextBody(update.reply);
27973
28168
  assertAuthorLabel(update.authorLabel);
28169
+ assertIdempotencyKey(update.idempotencyKey);
28170
+ const authorLabel = update.authorLabel ?? "Agent";
27974
28171
  return {
27975
28172
  commentId,
27976
28173
  reply: update.reply,
27977
28174
  resolve: update.resolve,
27978
- ...update.authorLabel === void 0 ? {} : { authorLabel: update.authorLabel }
28175
+ ...update.references === void 0 ? {} : { references: update.references },
28176
+ ...update.authorLabel === void 0 ? {} : { authorLabel: update.authorLabel },
28177
+ ...update.idempotencyKey === void 0 ? {} : { idempotencyKey: update.idempotencyKey },
28178
+ ...update.idempotencyKey === void 0 ? {} : {
28179
+ idempotencyRequestHash: idempotencyRequestHash({
28180
+ operation: "pr.sync.comment-update",
28181
+ commentId,
28182
+ reply: update.reply,
28183
+ resolve: update.resolve,
28184
+ authorLabel,
28185
+ references: update.references ?? []
28186
+ })
28187
+ }
27979
28188
  };
27980
28189
  });
27981
28190
  }
@@ -27999,6 +28208,19 @@ var RvwService = class {
27999
28208
  github.headOid
28000
28209
  );
28001
28210
  await this.git.ensureCommitRef(repository.worktreePath, github.number, github.headOid);
28211
+ for (const update of updates) {
28212
+ if (!update.reply.trim()) continue;
28213
+ const comment = this.database.getComment(update.commentId);
28214
+ if (!comment) {
28215
+ throw new RvwError("COMMENT_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002");
28216
+ }
28217
+ await this.validateCodeReferences(this.getPullRequest(comment.pullRequestId), {
28218
+ sourceOid: github.headOid,
28219
+ body: update.reply,
28220
+ references: update.references ?? [],
28221
+ subject: "comment sync reply"
28222
+ });
28223
+ }
28002
28224
  const repositoryLocation = {
28003
28225
  localRepositoryPath: repository.worktreePath,
28004
28226
  gitCommonDir: repository.gitCommonDir
@@ -28235,6 +28457,90 @@ var RvwService = class {
28235
28457
  throw new RvwError("INVALID_INPUT", `${subject}\u306E\u884C\u7BC4\u56F2\u304C\u6587\u66F8\u5916\u3067\u3059\u3002`);
28236
28458
  }
28237
28459
  }
28460
+ async validateCodeReferences(pullRequest, input) {
28461
+ const markdown = analyzeReferenceMarkdown(input.body);
28462
+ if (input.references.length > MAX_CODE_REFERENCES) {
28463
+ throw new RvwError(
28464
+ "INVALID_INPUT",
28465
+ `${input.subject}\u306Ecode reference\u306F${MAX_CODE_REFERENCES}\u4EF6\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
28466
+ );
28467
+ }
28468
+ if ((input.references.length > 0 || markdown.referenceIds.length > 0) && !input.sourceOid) {
28469
+ throw new RvwError(
28470
+ "INVALID_INPUT",
28471
+ `${input.subject}\u3067code reference\u3092\u4F7F\u3046\u5834\u5408\u306Frelated commit\u304C\u5FC5\u8981\u3067\u3059\u3002`
28472
+ );
28473
+ }
28474
+ if (input.sourceOid) await this.assertCommitAvailable(pullRequest, input.sourceOid);
28475
+ const referenceIds = /* @__PURE__ */ new Set();
28476
+ for (const reference of input.references) {
28477
+ if (!codeReferenceIdPattern.test(reference.id) || referenceIds.has(reference.id)) {
28478
+ throw new RvwError(
28479
+ "INVALID_INPUT",
28480
+ `code reference ID\u304C\u4E0D\u6B63\u307E\u305F\u306F\u91CD\u8907\u3057\u3066\u3044\u307E\u3059: ${reference.id}`
28481
+ );
28482
+ }
28483
+ referenceIds.add(reference.id);
28484
+ assertCodeReferencePath(reference.path);
28485
+ if (reference.label.trim().length === 0 || reference.label.length > MAX_CODE_REFERENCE_LABEL_CHARACTERS) {
28486
+ throw new RvwError("INVALID_INPUT", `code reference label\u304C\u4E0D\u6B63\u3067\u3059: ${reference.id}`);
28487
+ }
28488
+ if (reference.description !== null && reference.description.length > MAX_CODE_REFERENCE_DESCRIPTION_CHARACTERS) {
28489
+ throw new RvwError(
28490
+ "INVALID_INPUT",
28491
+ `code reference description\u304C\u9577\u3059\u304E\u307E\u3059: ${reference.id}`
28492
+ );
28493
+ }
28494
+ const content3 = await this.getDocument({
28495
+ kind: "repository-file",
28496
+ pullRequestId: pullRequest.id,
28497
+ sourceOid: input.sourceOid,
28498
+ path: reference.path
28499
+ });
28500
+ if (content3.availability !== "available") {
28501
+ throw new RvwError("INVALID_INPUT", `code reference\u3092\u8868\u793A\u3067\u304D\u307E\u305B\u3093: ${reference.path}`);
28502
+ }
28503
+ this.validateLineRange(
28504
+ content3.text ?? "",
28505
+ reference.startLine,
28506
+ reference.endLine,
28507
+ `code reference ${reference.id}`
28508
+ );
28509
+ }
28510
+ const malformedReference = markdown.referenceIds.find(
28511
+ (referenceId) => !codeReferenceIdPattern.test(referenceId)
28512
+ );
28513
+ if (malformedReference !== void 0) {
28514
+ throw new RvwError(
28515
+ "INVALID_INPUT",
28516
+ `Markdown reference ID\u304C\u4E0D\u6B63\u3067\u3059: ${malformedReference || "(empty)"}`
28517
+ );
28518
+ }
28519
+ const missingReference = markdown.referenceIds.find(
28520
+ (referenceId) => !referenceIds.has(referenceId)
28521
+ );
28522
+ if (missingReference) {
28523
+ throw new RvwError(
28524
+ "INVALID_INPUT",
28525
+ `Markdown reference\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ${missingReference}`
28526
+ );
28527
+ }
28528
+ const usedReferenceIds = /* @__PURE__ */ new Set([
28529
+ ...markdown.referenceIds,
28530
+ ...input.additionalUsedReferenceIds ?? []
28531
+ ]);
28532
+ const unusedReference = input.references.find(
28533
+ (reference) => !usedReferenceIds.has(reference.id)
28534
+ );
28535
+ if (unusedReference) {
28536
+ const usageSurface = input.additionalUsedReferenceIds === void 0 ? "\u672C\u6587" : "\u672C\u6587\u307E\u305F\u306Fbinding";
28537
+ throw new RvwError(
28538
+ "INVALID_INPUT",
28539
+ `code reference\u304C${usageSurface}\u304B\u3089\u53C2\u7167\u3055\u308C\u3066\u3044\u307E\u305B\u3093: ${unusedReference.id}`
28540
+ );
28541
+ }
28542
+ return markdown;
28543
+ }
28238
28544
  async prepareCommentTarget(pullRequest, target) {
28239
28545
  if (target.kind === "pull-request") return target;
28240
28546
  if (target.kind === "walkthrough") {
@@ -28296,11 +28602,33 @@ var RvwService = class {
28296
28602
  const pullRequest = this.getPullRequest(input.pullRequestId);
28297
28603
  const target = await this.prepareCommentTarget(pullRequest, input.target);
28298
28604
  assertAuthorLabel(input.authorLabel);
28299
- return this.database.createComment({
28605
+ const body = assertTextBody(input.body);
28606
+ const references = input.references ?? [];
28607
+ await this.validateCodeReferences(pullRequest, {
28608
+ sourceOid: input.relatedCommitOid ?? null,
28609
+ body,
28610
+ references,
28611
+ subject: "comment post"
28612
+ });
28613
+ const write = () => this.database.createComment({
28300
28614
  pullRequestId: pullRequest.id,
28301
28615
  createdHeadOid: pullRequest.latestHeadOid,
28302
28616
  target,
28303
- body: assertTextBody(input.body),
28617
+ body,
28618
+ ...input.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.relatedCommitOid },
28619
+ references,
28620
+ ...input.authorLabel === void 0 ? {} : { authorLabel: input.authorLabel }
28621
+ });
28622
+ return input.relatedCommitOid ? await this.writeWithRetainedCommit(pullRequest, input.relatedCommitOid, "comment", write) : write();
28623
+ }
28624
+ async createCommentForReference(input) {
28625
+ const pullRequest = this.resolveStoredPullRequest(input.pullRequest);
28626
+ return await this.createComment({
28627
+ pullRequestId: pullRequest.id,
28628
+ target: input.target,
28629
+ body: input.body,
28630
+ ...input.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.relatedCommitOid },
28631
+ ...input.references === void 0 ? {} : { references: input.references },
28304
28632
  ...input.authorLabel === void 0 ? {} : { authorLabel: input.authorLabel }
28305
28633
  });
28306
28634
  }
@@ -28340,7 +28668,7 @@ var RvwService = class {
28340
28668
  result.pullRequest.url,
28341
28669
  result.pullRequest.localRepositoryPath
28342
28670
  ) : null;
28343
- const staleAgainstGitHub = live ? live.title !== result.pullRequest.latestTitle || live.body !== result.pullRequest.latestBody || live.baseOid !== result.pullRequest.latestBaseOid || live.headOid !== result.pullRequest.latestHeadOid || live.updatedAt !== result.pullRequest.githubUpdatedAt : null;
28671
+ const staleAgainstGitHub = live ? live.title !== result.pullRequest.latestTitle || live.body !== result.pullRequest.latestBody || live.headRepositoryOwner !== result.pullRequest.latestHeadRepositoryOwner || live.headRepositoryName !== result.pullRequest.latestHeadRepositoryName || live.baseOid !== result.pullRequest.latestBaseOid || live.headOid !== result.pullRequest.latestHeadOid || live.updatedAt !== result.pullRequest.githubUpdatedAt : null;
28344
28672
  return {
28345
28673
  ...result,
28346
28674
  latestPlacement,
@@ -28389,6 +28717,39 @@ var RvwService = class {
28389
28717
  }
28390
28718
  };
28391
28719
  }
28720
+ listCommentPostEvents(cursor, limit = DEFAULT_COMMENT_WATCH_LIMIT) {
28721
+ if (!Number.isInteger(limit) || limit < 1 || limit > MAX_COMMENT_WATCH_LIMIT) {
28722
+ throw new RvwError(
28723
+ "INVALID_INPUT",
28724
+ `comment watch\u306Elimit\u306F1\u301C${MAX_COMMENT_WATCH_LIMIT}\u306E\u6574\u6570\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
28725
+ );
28726
+ }
28727
+ const databaseId = this.database.getCommentWatchDatabaseId();
28728
+ const parsed = cursor === void 0 ? null : parseCommentWatchCursor(cursor);
28729
+ if (parsed !== null && parsed.databaseId !== databaseId) {
28730
+ throw new RvwError("INVALID_INPUT", "comment watch cursor\u306F\u5225\u306Ervw database\u7528\u3067\u3059\u3002");
28731
+ }
28732
+ const latestAtStart = this.database.getLatestCommentPostEventSequence();
28733
+ if (parsed !== null && parsed.sequence > latestAtStart) {
28734
+ throw new RvwError("INVALID_INPUT", "comment watch cursor\u306Fdatabase\u306E\u6700\u65B0event\u3088\u308A\u5148\u3067\u3059\u3002");
28735
+ }
28736
+ const afterSequence = parsed?.sequence ?? latestAtStart;
28737
+ const rawEvents = this.database.listCommentPostEvents(afterSequence, limit);
28738
+ const events = rawEvents.map((event) => ({
28739
+ cursor: formatCommentWatchCursor({ databaseId, sequence: event.sequence }),
28740
+ event
28741
+ }));
28742
+ const lastSequence = rawEvents.at(-1)?.sequence ?? afterSequence;
28743
+ const latestSequence = this.database.getLatestCommentPostEventSequence();
28744
+ return {
28745
+ databaseId,
28746
+ startCursor: formatCommentWatchCursor({ databaseId, sequence: afterSequence }),
28747
+ cursor: formatCommentWatchCursor({ databaseId, sequence: lastSequence }),
28748
+ anchoredAtCurrent: parsed === null,
28749
+ hasMore: lastSequence < latestSequence,
28750
+ events
28751
+ };
28752
+ }
28392
28753
  listComments(pullRequestId, resolved) {
28393
28754
  this.getPullRequest(pullRequestId);
28394
28755
  return this.database.listComments(pullRequestId, resolved);
@@ -28430,50 +28791,16 @@ var RvwService = class {
28430
28791
  `walkthrough\u672C\u6587\u306F1\u301C${MAX_WALKTHROUGH_BODY_BYTES} UTF-8 bytes\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
28431
28792
  );
28432
28793
  }
28433
- if (input.references.length === 0 || input.references.length > MAX_WALKTHROUGH_REFERENCES) {
28794
+ if (input.references.length === 0 || input.references.length > MAX_CODE_REFERENCES) {
28434
28795
  throw new RvwError(
28435
28796
  "INVALID_INPUT",
28436
- `walkthrough reference\u306F1\u301C${MAX_WALKTHROUGH_REFERENCES}\u4EF6\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
28797
+ `walkthrough reference\u306F1\u301C${MAX_CODE_REFERENCES}\u4EF6\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
28437
28798
  );
28438
28799
  }
28439
28800
  assertAuthorLabel(input.authorLabel);
28440
- const referenceIds = /* @__PURE__ */ new Set();
28441
- for (const reference of input.references) {
28442
- if (!walkthroughReferenceIdPattern.test(reference.id) || referenceIds.has(reference.id)) {
28443
- throw new RvwError(
28444
- "INVALID_INPUT",
28445
- `walkthrough reference ID\u304C\u4E0D\u6B63\u307E\u305F\u306F\u91CD\u8907\u3057\u3066\u3044\u307E\u3059: ${reference.id}`
28446
- );
28447
- }
28448
- referenceIds.add(reference.id);
28449
- assertWalkthroughPath(reference.path);
28450
- if (reference.label.trim().length === 0 || reference.label.length > MAX_WALKTHROUGH_REFERENCE_LABEL_CHARACTERS) {
28451
- throw new RvwError("INVALID_INPUT", `reference label\u304C\u4E0D\u6B63\u3067\u3059: ${reference.id}`);
28452
- }
28453
- if (reference.description !== null && reference.description.length > MAX_WALKTHROUGH_REFERENCE_DESCRIPTION_CHARACTERS) {
28454
- throw new RvwError("INVALID_INPUT", `reference description\u304C\u9577\u3059\u304E\u307E\u3059: ${reference.id}`);
28455
- }
28456
- const content3 = await this.getDocument({
28457
- kind: "repository-file",
28458
- pullRequestId: pullRequest.id,
28459
- sourceOid: input.sourceOid,
28460
- path: reference.path
28461
- });
28462
- if (content3.availability !== "available") {
28463
- throw new RvwError(
28464
- "INVALID_INPUT",
28465
- `walkthrough reference\u3092\u8868\u793A\u3067\u304D\u307E\u305B\u3093: ${reference.path}`
28466
- );
28467
- }
28468
- this.validateLineRange(
28469
- content3.text ?? "",
28470
- reference.startLine,
28471
- reference.endLine,
28472
- `walkthrough reference ${reference.id}`
28473
- );
28474
- }
28475
- const markdown = analyzeWalkthroughMarkdown(input.body);
28801
+ const markdown = analyzeReferenceMarkdown(input.body);
28476
28802
  const diagramBindings = input.diagramBindings ?? {};
28803
+ const referenceIds = new Set(input.references.map((reference) => reference.id));
28477
28804
  for (const [nodeId, referenceId] of Object.entries(diagramBindings)) {
28478
28805
  if (!walkthroughDiagramNodePattern.test(nodeId)) {
28479
28806
  throw new RvwError("INVALID_INPUT", `Mermaid node ID\u304C\u4E0D\u6B63\u3067\u3059: ${nodeId}`);
@@ -28491,35 +28818,13 @@ var RvwService = class {
28491
28818
  );
28492
28819
  }
28493
28820
  }
28494
- const markdownReferenceIds = markdown.referenceIds;
28495
- const malformedReference = markdownReferenceIds.find(
28496
- (referenceId) => !walkthroughReferenceIdPattern.test(referenceId)
28497
- );
28498
- if (malformedReference !== void 0) {
28499
- throw new RvwError(
28500
- "INVALID_INPUT",
28501
- `Markdown reference ID\u304C\u4E0D\u6B63\u3067\u3059: ${malformedReference || "(empty)"}`
28502
- );
28503
- }
28504
- const missingReference = markdownReferenceIds.find(
28505
- (referenceId) => !referenceIds.has(referenceId)
28506
- );
28507
- if (missingReference) {
28508
- throw new RvwError(
28509
- "INVALID_INPUT",
28510
- `Markdown reference\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ${missingReference}`
28511
- );
28512
- }
28513
- const usedReferenceIds = /* @__PURE__ */ new Set([...markdownReferenceIds, ...Object.values(diagramBindings)]);
28514
- const unusedReference = input.references.find(
28515
- (reference) => !usedReferenceIds.has(reference.id)
28516
- );
28517
- if (unusedReference) {
28518
- throw new RvwError(
28519
- "INVALID_INPUT",
28520
- `walkthrough reference\u304C\u672C\u6587\u307E\u305F\u306FMermaid binding\u304B\u3089\u53C2\u7167\u3055\u308C\u3066\u3044\u307E\u305B\u3093: ${unusedReference.id}`
28521
- );
28522
- }
28821
+ await this.validateCodeReferences(pullRequest, {
28822
+ sourceOid: input.sourceOid,
28823
+ body: input.body,
28824
+ references: input.references,
28825
+ additionalUsedReferenceIds: Object.values(diagramBindings),
28826
+ subject: "Walkthrough"
28827
+ });
28523
28828
  return {
28524
28829
  sourceOid: input.sourceOid,
28525
28830
  title,
@@ -28529,7 +28834,7 @@ var RvwService = class {
28529
28834
  references: input.references
28530
28835
  };
28531
28836
  }
28532
- async writeWalkthroughWithRetainedCommit(pullRequest, sourceOid, write) {
28837
+ async writeWithRetainedCommit(pullRequest, sourceOid, subject, write) {
28533
28838
  const commitRef = await this.git.ensureCommitRef(
28534
28839
  pullRequest.localRepositoryPath,
28535
28840
  pullRequest.number,
@@ -28544,7 +28849,7 @@ var RvwService = class {
28544
28849
  } catch (cleanupError) {
28545
28850
  throw new RvwError(
28546
28851
  "LOCAL_STATE_INCONSISTENT",
28547
- "Walkthrough\u306E\u66F8\u304D\u8FBC\u307F\u5931\u6557\u5F8C\u306BGit ref\u3092\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002",
28852
+ `${subject}\u306E\u66F8\u304D\u8FBC\u307F\u5931\u6557\u5F8C\u306BGit ref\u3092\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002`,
28548
28853
  { cause: cleanupError }
28549
28854
  );
28550
28855
  }
@@ -28555,9 +28860,10 @@ var RvwService = class {
28555
28860
  async publishWalkthrough(input) {
28556
28861
  const pullRequest = this.resolveStoredPullRequest(input.pullRequest);
28557
28862
  const content3 = await this.validateWalkthroughContent(pullRequest, input);
28558
- return await this.writeWalkthroughWithRetainedCommit(
28863
+ return await this.writeWithRetainedCommit(
28559
28864
  pullRequest,
28560
28865
  content3.sourceOid,
28866
+ "Walkthrough",
28561
28867
  () => this.database.createWalkthrough({
28562
28868
  pullRequestId: pullRequest.id,
28563
28869
  ...content3
@@ -28570,9 +28876,10 @@ var RvwService = class {
28570
28876
  ...input,
28571
28877
  authorLabel: input.authorLabel === void 0 ? walkthrough.authorLabel : input.authorLabel
28572
28878
  });
28573
- return await this.writeWalkthroughWithRetainedCommit(
28879
+ return await this.writeWithRetainedCommit(
28574
28880
  pullRequest,
28575
28881
  content3.sourceOid,
28882
+ "Walkthrough",
28576
28883
  () => this.database.updateWalkthrough(walkthrough.id, content3)
28577
28884
  );
28578
28885
  }
@@ -28598,13 +28905,32 @@ var RvwService = class {
28598
28905
  if (!comment)
28599
28906
  throw new RvwError("COMMENT_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", { status: 404 });
28600
28907
  assertAuthorLabel(input.authorLabel);
28601
- if (input.relatedCommitOid) {
28602
- await this.assertCommitAvailable(
28603
- this.getPullRequest(comment.pullRequestId),
28604
- input.relatedCommitOid
28605
- );
28606
- }
28607
- return this.database.insertReply(id, { ...input, body: assertTextBody(input.body) });
28908
+ assertIdempotencyKey(input.idempotencyKey);
28909
+ const pullRequest = this.getPullRequest(comment.pullRequestId);
28910
+ const body = assertTextBody(input.body);
28911
+ const references = input.references ?? [];
28912
+ await this.validateCodeReferences(pullRequest, {
28913
+ sourceOid: input.relatedCommitOid ?? null,
28914
+ body,
28915
+ references,
28916
+ subject: "comment reply"
28917
+ });
28918
+ const write = () => this.database.insertReply(id, {
28919
+ ...input,
28920
+ body,
28921
+ references,
28922
+ ...input.idempotencyKey === void 0 ? {} : {
28923
+ idempotencyRequestHash: idempotencyRequestHash({
28924
+ operation: "comment.reply",
28925
+ commentId: id,
28926
+ body,
28927
+ relatedCommitOid: input.relatedCommitOid ?? null,
28928
+ authorLabel: input.authorLabel ?? null,
28929
+ references
28930
+ })
28931
+ }
28932
+ });
28933
+ return input.relatedCommitOid ? await this.writeWithRetainedCommit(pullRequest, input.relatedCommitOid, "comment", write) : write();
28608
28934
  }
28609
28935
  setCommentResolved(uriOrId, resolved) {
28610
28936
  const id = uriOrId.startsWith("rvw://") ? parseCommentUri(uriOrId) : uriOrId;
@@ -28614,8 +28940,44 @@ var RvwService = class {
28614
28940
  const id = uriOrId.startsWith("rvw://") ? parseCommentUri(uriOrId) : uriOrId;
28615
28941
  return this.database.deleteComment(id);
28616
28942
  }
28617
- updateCommentPost(commentId, postId, body) {
28618
- return this.database.updateCommentPost(commentId, postId, assertTextBody(body));
28943
+ async updateCommentPost(commentId, postId, body) {
28944
+ const comment = this.database.getComment(commentId);
28945
+ const post = comment?.posts.find((candidate) => candidate.id === postId);
28946
+ if (!comment || !post) {
28947
+ throw new RvwError("COMMENT_POST_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u6295\u7A3F\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", {
28948
+ status: 404
28949
+ });
28950
+ }
28951
+ const usedReferenceIds = new Set(analyzeReferenceMarkdown(body).referenceIds);
28952
+ return await this.editCommentPost(commentId, postId, {
28953
+ body,
28954
+ references: post.references.filter((reference) => usedReferenceIds.has(reference.id))
28955
+ });
28956
+ }
28957
+ async editCommentPost(uriOrId, postId, input) {
28958
+ const commentId = uriOrId.startsWith("rvw://") ? parseCommentUri(uriOrId) : uriOrId;
28959
+ const comment = this.database.getComment(commentId);
28960
+ if (!comment) {
28961
+ throw new RvwError("COMMENT_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", { status: 404 });
28962
+ }
28963
+ const post = comment.posts.find((candidate) => candidate.id === postId);
28964
+ if (!post) {
28965
+ throw new RvwError("COMMENT_POST_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u6295\u7A3F\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", {
28966
+ status: 404
28967
+ });
28968
+ }
28969
+ const body = assertTextBody(input.body);
28970
+ const relatedCommitOid = input.relatedCommitOid === void 0 ? post.relatedCommitOid : input.relatedCommitOid;
28971
+ const references = input.references ?? post.references;
28972
+ const pullRequest = this.getPullRequest(comment.pullRequestId);
28973
+ await this.validateCodeReferences(pullRequest, {
28974
+ sourceOid: relatedCommitOid,
28975
+ body,
28976
+ references,
28977
+ subject: "comment post"
28978
+ });
28979
+ const write = () => this.database.updateCommentPost(commentId, postId, body, input.relatedCommitOid, references);
28980
+ return relatedCommitOid ? await this.writeWithRetainedCommit(pullRequest, relatedCommitOid, "comment", write) : write();
28619
28981
  }
28620
28982
  deleteReply(commentId, postId) {
28621
28983
  return this.database.deleteReply(commentId, postId);
@@ -28813,7 +29175,7 @@ function createRuntime(options = {}) {
28813
29175
  }
28814
29176
 
28815
29177
  // src/infrastructure/skills/skill-installer.ts
28816
- import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
29178
+ import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
28817
29179
  import {
28818
29180
  cpSync,
28819
29181
  existsSync as existsSync2,
@@ -28829,7 +29191,11 @@ import {
28829
29191
  import os3 from "node:os";
28830
29192
  import path7 from "node:path";
28831
29193
  import { fileURLToPath as fileURLToPath3 } from "node:url";
28832
- var skillNames = ["rvw", "rvw-walkthrough"];
29194
+ var skillNames = [
29195
+ "rvw",
29196
+ "rvw-walkthrough",
29197
+ "rvw-watch-comments"
29198
+ ];
28833
29199
  var INSTALL_METADATA_FILE = ".rvw-install.json";
28834
29200
  var INSTALL_METADATA_SCHEMA_VERSION = 1;
28835
29201
  var MAX_DIGEST_ENTRIES = 1e4;
@@ -28843,7 +29209,7 @@ var adapters = {
28843
29209
  }
28844
29210
  };
28845
29211
  function directoryDigest(directory) {
28846
- const hash2 = createHash2("sha256");
29212
+ const hash2 = createHash4("sha256");
28847
29213
  let entriesSeen = 0;
28848
29214
  let bytesSeen = 0;
28849
29215
  const walk = (current, relative) => {
@@ -32638,6 +33004,167 @@ var Hono2 = class extends Hono {
32638
33004
  }
32639
33005
  };
32640
33006
 
33007
+ // src/application/agent-command-schemas.ts
33008
+ var nonEmptyString = external_exports.string().min(1);
33009
+ var commentUri = external_exports.string().regex(/^rvw:\/\/comment\//);
33010
+ var walkthroughUri = external_exports.string().regex(/^rvw:\/\/walkthrough\//);
33011
+ var nullableCommentLine = external_exports.number().int().positive().nullable().optional().default(null);
33012
+ var idempotencyKey = external_exports.string().min(1).max(MAX_IDEMPOTENCY_KEY_CHARACTERS).optional();
33013
+ var commentTargetInputSchema = external_exports.union([
33014
+ external_exports.object({ kind: external_exports.literal("pull-request") }).strict(),
33015
+ external_exports.object({
33016
+ kind: external_exports.literal("walkthrough"),
33017
+ walkthroughId: external_exports.uuid(),
33018
+ startLine: nullableCommentLine,
33019
+ endLine: nullableCommentLine
33020
+ }).strict(),
33021
+ external_exports.object({
33022
+ kind: external_exports.literal("document"),
33023
+ documentKind: external_exports.literal("pull-request-markdown"),
33024
+ startLine: nullableCommentLine,
33025
+ endLine: nullableCommentLine
33026
+ }).strict(),
33027
+ external_exports.object({
33028
+ kind: external_exports.literal("document"),
33029
+ documentKind: external_exports.literal("repository-file"),
33030
+ sourceOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN),
33031
+ path: nonEmptyString,
33032
+ startLine: nullableCommentLine,
33033
+ endLine: nullableCommentLine
33034
+ }).strict()
33035
+ ]).superRefine((target, context) => {
33036
+ if (target.kind === "pull-request") return;
33037
+ if (target.startLine === null !== (target.endLine === null)) {
33038
+ context.addIssue({
33039
+ code: "custom",
33040
+ message: "startLine\u3068endLine\u306F\u4E21\u65B9\u6307\u5B9A\u3059\u308B\u304B\u3001\u4E21\u65B9\u7701\u7565\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
33041
+ });
33042
+ return;
33043
+ }
33044
+ if (target.startLine !== null && target.endLine !== null && target.endLine < target.startLine) {
33045
+ context.addIssue({
33046
+ code: "custom",
33047
+ message: "endLine\u306FstartLine\u4EE5\u4E0A\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
33048
+ });
33049
+ }
33050
+ });
33051
+ var codeReferenceInputSchema = external_exports.object({
33052
+ id: external_exports.string().regex(/^[A-Za-z][A-Za-z0-9_-]{0,63}$/),
33053
+ label: external_exports.string().min(1).max(MAX_CODE_REFERENCE_LABEL_CHARACTERS),
33054
+ path: external_exports.string().min(1).max(MAX_CODE_REFERENCE_PATH_CHARACTERS),
33055
+ startLine: external_exports.number().int().positive().nullable().optional().default(null),
33056
+ endLine: external_exports.number().int().positive().nullable().optional().default(null),
33057
+ description: external_exports.string().max(MAX_CODE_REFERENCE_DESCRIPTION_CHARACTERS).nullable()
33058
+ }).strict().superRefine((reference, context) => {
33059
+ if (reference.startLine === null !== (reference.endLine === null)) {
33060
+ context.addIssue({
33061
+ code: "custom",
33062
+ message: "startLine\u3068endLine\u306F\u4E21\u65B9\u6307\u5B9A\u3059\u308B\u304B\u3001\u4E21\u65B9\u7701\u7565\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
33063
+ });
33064
+ return;
33065
+ }
33066
+ if (reference.startLine !== null && reference.endLine !== null && reference.endLine < reference.startLine) {
33067
+ context.addIssue({
33068
+ code: "custom",
33069
+ message: "endLine\u306FstartLine\u4EE5\u4E0A\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
33070
+ });
33071
+ }
33072
+ });
33073
+ var optionalCodeReferences = external_exports.array(codeReferenceInputSchema).max(MAX_CODE_REFERENCES).optional();
33074
+ function requireRelatedCommitForReferences(input, context) {
33075
+ if ((input.references?.length ?? 0) > 0 && !input.relatedCommitOid) {
33076
+ context.addIssue({
33077
+ code: "custom",
33078
+ path: ["relatedCommitOid"],
33079
+ message: "code reference\u3092\u6301\u3064comment post\u306B\u306FrelatedCommitOid\u304C\u5FC5\u8981\u3067\u3059\u3002"
33080
+ });
33081
+ }
33082
+ }
33083
+ var commentCreateInputSchema = external_exports.object({
33084
+ pullRequest: nonEmptyString,
33085
+ target: commentTargetInputSchema,
33086
+ body: external_exports.string().min(1).refine((value) => value.trim().length > 0).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_COMMENT_BODY_BYTES, {
33087
+ message: `body\u306FUTF-8\u3067${MAX_COMMENT_BODY_BYTES} bytes\uFF0864 KiB\uFF09\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
33088
+ }),
33089
+ authorLabel: external_exports.string().max(MAX_AUTHOR_LABEL_CHARACTERS).nullable().optional(),
33090
+ relatedCommitOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN).nullable().optional(),
33091
+ references: optionalCodeReferences
33092
+ }).strict().superRefine(requireRelatedCommitForReferences);
33093
+ var commentReplyInputSchema = external_exports.object({
33094
+ body: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_COMMENT_BODY_BYTES, {
33095
+ message: `body\u306FUTF-8\u3067${MAX_COMMENT_BODY_BYTES} bytes\uFF0864 KiB\uFF09\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
33096
+ }),
33097
+ authorLabel: external_exports.string().max(MAX_AUTHOR_LABEL_CHARACTERS).nullable().optional(),
33098
+ relatedCommitOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN).nullable().optional(),
33099
+ references: optionalCodeReferences,
33100
+ idempotencyKey
33101
+ }).strict().superRefine(requireRelatedCommitForReferences);
33102
+ var commentPostEditInputSchema = external_exports.object({
33103
+ body: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_COMMENT_BODY_BYTES, {
33104
+ message: `body\u306FUTF-8\u3067${MAX_COMMENT_BODY_BYTES} bytes\uFF0864 KiB\uFF09\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
33105
+ }),
33106
+ relatedCommitOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN).nullable().optional(),
33107
+ references: optionalCodeReferences
33108
+ }).strict();
33109
+ var pullRequestSyncInputSchema = external_exports.object({
33110
+ pullRequest: nonEmptyString,
33111
+ commentUpdates: external_exports.array(
33112
+ external_exports.object({
33113
+ commentRef: commentUri,
33114
+ reply: external_exports.string().refine((value) => Buffer.byteLength(value, "utf8") <= MAX_COMMENT_BODY_BYTES, {
33115
+ message: `reply\u306FUTF-8\u3067${MAX_COMMENT_BODY_BYTES} bytes\uFF0864 KiB\uFF09\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
33116
+ }),
33117
+ resolve: external_exports.boolean(),
33118
+ references: optionalCodeReferences,
33119
+ idempotencyKey
33120
+ }).strict()
33121
+ ).max(500).optional()
33122
+ }).strict();
33123
+ var walkthroughContentInputSchema = external_exports.object({
33124
+ sourceOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN),
33125
+ title: external_exports.string().min(1).max(MAX_WALKTHROUGH_TITLE_CHARACTERS),
33126
+ body: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_WALKTHROUGH_BODY_BYTES),
33127
+ authorLabel: external_exports.string().max(MAX_AUTHOR_LABEL_CHARACTERS).nullable().optional(),
33128
+ diagramBindings: external_exports.record(external_exports.string(), external_exports.string()).optional(),
33129
+ references: external_exports.array(codeReferenceInputSchema).min(1).max(MAX_CODE_REFERENCES)
33130
+ }).strict();
33131
+ var walkthroughPublishInputSchema = walkthroughContentInputSchema.extend({
33132
+ pullRequest: nonEmptyString
33133
+ });
33134
+ var walkthroughUpdateInputSchema = walkthroughContentInputSchema;
33135
+ var agentCommandInputSchemas = {
33136
+ doctor: external_exports.object({ cwd: nonEmptyString }).strict(),
33137
+ "pr.refresh": external_exports.object({ reference: nonEmptyString }).strict(),
33138
+ "pr.sync": pullRequestSyncInputSchema.extend({
33139
+ repositoryPath: nonEmptyString.optional(),
33140
+ allowUntracked: external_exports.boolean().default(false)
33141
+ }),
33142
+ "pr.attach": external_exports.object({ reference: nonEmptyString, repositoryPath: nonEmptyString }).strict(),
33143
+ "pr.reset.preview": external_exports.object({ reference: nonEmptyString }).strict(),
33144
+ "pr.reset": external_exports.object({ reference: nonEmptyString, confirmed: external_exports.literal(true) }).strict(),
33145
+ "comment.list": external_exports.object({
33146
+ reference: nonEmptyString,
33147
+ resolved: external_exports.boolean().optional(),
33148
+ limit: external_exports.number().int().min(1).max(MAX_COMMENT_LIST_LIMIT).default(DEFAULT_COMMENT_LIST_LIMIT),
33149
+ offset: external_exports.number().int().min(0).default(0)
33150
+ }).strict(),
33151
+ "comment.watch": external_exports.object({
33152
+ cursor: external_exports.string().min(1).max(512).optional(),
33153
+ limit: external_exports.number().int().min(1).max(MAX_COMMENT_WATCH_LIMIT)
33154
+ }).strict(),
33155
+ "comment.create": commentCreateInputSchema,
33156
+ "comment.get": external_exports.object({ uri: commentUri, live: external_exports.boolean().default(false) }).strict(),
33157
+ "comment.reply": external_exports.object({ uri: commentUri, reply: commentReplyInputSchema }).strict(),
33158
+ "comment.edit": external_exports.object({ uri: commentUri, postId: nonEmptyString, edit: commentPostEditInputSchema }).strict(),
33159
+ "comment.resolve": external_exports.object({ uri: commentUri }).strict(),
33160
+ "comment.reopen": external_exports.object({ uri: commentUri }).strict(),
33161
+ "walkthrough.get": external_exports.object({ uri: walkthroughUri }).strict(),
33162
+ "walkthrough.publish": walkthroughPublishInputSchema,
33163
+ "walkthrough.update": external_exports.object({ uri: walkthroughUri, content: walkthroughUpdateInputSchema }).strict(),
33164
+ "walkthrough.delete.preview": external_exports.object({ uri: walkthroughUri }).strict(),
33165
+ "walkthrough.delete": external_exports.object({ uri: walkthroughUri, confirmed: external_exports.literal(true) }).strict()
33166
+ };
33167
+
32641
33168
  // src/server/schemas.ts
32642
33169
  var nullableLine = external_exports.number().int().positive().nullable();
32643
33170
  var commentTargetSchema = external_exports.union([
@@ -32675,15 +33202,35 @@ var createCommentSchema = external_exports.object({
32675
33202
  pullRequestId: external_exports.uuid(),
32676
33203
  target: commentTargetSchema,
32677
33204
  body: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_COMMENT_BODY_BYTES),
32678
- authorLabel: external_exports.string().max(MAX_AUTHOR_LABEL_CHARACTERS).nullable().optional()
33205
+ authorLabel: external_exports.string().max(MAX_AUTHOR_LABEL_CHARACTERS).nullable().optional(),
33206
+ relatedCommitOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN).nullable().optional(),
33207
+ references: external_exports.array(codeReferenceInputSchema).optional()
33208
+ }).superRefine((input, context) => {
33209
+ if ((input.references?.length ?? 0) > 0 && !input.relatedCommitOid) {
33210
+ context.addIssue({
33211
+ code: "custom",
33212
+ path: ["relatedCommitOid"],
33213
+ message: "code reference\u3092\u6301\u3064comment post\u306B\u306FrelatedCommitOid\u304C\u5FC5\u8981\u3067\u3059\u3002"
33214
+ });
33215
+ }
32679
33216
  });
32680
33217
  var replySchema = external_exports.object({
32681
33218
  body: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_COMMENT_BODY_BYTES),
32682
33219
  relatedCommitOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN).nullable().optional(),
32683
- authorLabel: external_exports.string().max(MAX_AUTHOR_LABEL_CHARACTERS).nullable().optional()
33220
+ authorLabel: external_exports.string().max(MAX_AUTHOR_LABEL_CHARACTERS).nullable().optional(),
33221
+ references: external_exports.array(codeReferenceInputSchema).optional()
33222
+ }).superRefine((input, context) => {
33223
+ if ((input.references?.length ?? 0) > 0 && !input.relatedCommitOid) {
33224
+ context.addIssue({
33225
+ code: "custom",
33226
+ path: ["relatedCommitOid"],
33227
+ message: "code reference\u3092\u6301\u3064comment post\u306B\u306FrelatedCommitOid\u304C\u5FC5\u8981\u3067\u3059\u3002"
33228
+ });
33229
+ }
32684
33230
  });
32685
33231
  var editCommentPostSchema = external_exports.object({
32686
- body: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_COMMENT_BODY_BYTES)
33232
+ body: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_COMMENT_BODY_BYTES),
33233
+ references: external_exports.array(codeReferenceInputSchema).optional()
32687
33234
  });
32688
33235
 
32689
33236
  // src/server/app.ts
@@ -32935,6 +33482,8 @@ function createApp(service, options) {
32935
33482
  pullRequestId: input.pullRequestId,
32936
33483
  target: input.target,
32937
33484
  body: input.body,
33485
+ ...input.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.relatedCommitOid },
33486
+ ...input.references === void 0 ? {} : { references: input.references },
32938
33487
  ...input.authorLabel === void 0 ? {} : { authorLabel: input.authorLabel }
32939
33488
  })
32940
33489
  },
@@ -32949,7 +33498,8 @@ function createApp(service, options) {
32949
33498
  post: await service.replyToComment(context.req.param("id"), {
32950
33499
  body: input.body,
32951
33500
  ...input.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.relatedCommitOid },
32952
- ...input.authorLabel === void 0 ? {} : { authorLabel: input.authorLabel }
33501
+ ...input.authorLabel === void 0 ? {} : { authorLabel: input.authorLabel },
33502
+ ...input.references === void 0 ? {} : { references: input.references }
32953
33503
  })
32954
33504
  },
32955
33505
  201
@@ -32959,11 +33509,14 @@ function createApp(service, options) {
32959
33509
  const input = editCommentPostSchema.parse(await context.req.json());
32960
33510
  return context.json({
32961
33511
  ok: true,
32962
- post: service.updateCommentPost(
33512
+ post: input.references === void 0 ? await service.updateCommentPost(
32963
33513
  context.req.param("id"),
32964
33514
  context.req.param("postId"),
32965
33515
  input.body
32966
- )
33516
+ ) : await service.editCommentPost(context.req.param("id"), context.req.param("postId"), {
33517
+ body: input.body,
33518
+ references: input.references
33519
+ })
32967
33520
  });
32968
33521
  });
32969
33522
  app.delete(
@@ -33179,7 +33732,7 @@ async function startServer(service, options = {}) {
33179
33732
  }
33180
33733
 
33181
33734
  // src/server/agent-socket.ts
33182
- import { createHash as createHash3, randomUUID as randomUUID4 } from "node:crypto";
33735
+ import { createHash as createHash5, randomUUID as randomUUID4 } from "node:crypto";
33183
33736
  import {
33184
33737
  chmodSync as chmodSync2,
33185
33738
  existsSync as existsSync5,
@@ -33193,88 +33746,6 @@ import {
33193
33746
  import net from "node:net";
33194
33747
  import os4 from "node:os";
33195
33748
  import path9 from "node:path";
33196
-
33197
- // src/application/agent-command-schemas.ts
33198
- var nonEmptyString = external_exports.string().min(1);
33199
- var commentUri = external_exports.string().regex(/^rvw:\/\/comment\//);
33200
- var walkthroughUri = external_exports.string().regex(/^rvw:\/\/walkthrough\//);
33201
- var commentReplyInputSchema = external_exports.object({
33202
- body: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_COMMENT_BODY_BYTES),
33203
- authorLabel: external_exports.string().max(MAX_AUTHOR_LABEL_CHARACTERS).nullable().optional(),
33204
- relatedCommitOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN).nullable().optional()
33205
- }).strict();
33206
- var pullRequestSyncInputSchema = external_exports.object({
33207
- pullRequest: nonEmptyString,
33208
- commentUpdates: external_exports.array(
33209
- external_exports.object({
33210
- commentRef: commentUri,
33211
- reply: external_exports.string().refine((value) => Buffer.byteLength(value, "utf8") <= MAX_COMMENT_BODY_BYTES),
33212
- resolve: external_exports.boolean()
33213
- }).strict()
33214
- ).max(500).optional()
33215
- }).strict();
33216
- var walkthroughReferenceInputSchema = external_exports.object({
33217
- id: external_exports.string().regex(/^[A-Za-z][A-Za-z0-9_-]{0,63}$/),
33218
- label: external_exports.string().min(1).max(MAX_WALKTHROUGH_REFERENCE_LABEL_CHARACTERS),
33219
- path: external_exports.string().min(1).max(MAX_WALKTHROUGH_REFERENCE_PATH_CHARACTERS),
33220
- startLine: external_exports.number().int().positive().nullable().optional().default(null),
33221
- endLine: external_exports.number().int().positive().nullable().optional().default(null),
33222
- description: external_exports.string().max(MAX_WALKTHROUGH_REFERENCE_DESCRIPTION_CHARACTERS).nullable()
33223
- }).strict().superRefine((reference, context) => {
33224
- if (reference.startLine === null !== (reference.endLine === null)) {
33225
- context.addIssue({
33226
- code: "custom",
33227
- message: "startLine\u3068endLine\u306F\u4E21\u65B9\u6307\u5B9A\u3059\u308B\u304B\u3001\u4E21\u65B9\u7701\u7565\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
33228
- });
33229
- return;
33230
- }
33231
- if (reference.startLine !== null && reference.endLine !== null && reference.endLine < reference.startLine) {
33232
- context.addIssue({
33233
- code: "custom",
33234
- message: "endLine\u306FstartLine\u4EE5\u4E0A\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
33235
- });
33236
- }
33237
- });
33238
- var walkthroughContentInputSchema = external_exports.object({
33239
- sourceOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN),
33240
- title: external_exports.string().min(1).max(MAX_WALKTHROUGH_TITLE_CHARACTERS),
33241
- body: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_WALKTHROUGH_BODY_BYTES),
33242
- authorLabel: external_exports.string().max(MAX_AUTHOR_LABEL_CHARACTERS).nullable().optional(),
33243
- diagramBindings: external_exports.record(external_exports.string(), external_exports.string()).optional(),
33244
- references: external_exports.array(walkthroughReferenceInputSchema).min(1).max(MAX_WALKTHROUGH_REFERENCES)
33245
- }).strict();
33246
- var walkthroughPublishInputSchema = walkthroughContentInputSchema.extend({
33247
- pullRequest: nonEmptyString
33248
- });
33249
- var walkthroughUpdateInputSchema = walkthroughContentInputSchema;
33250
- var agentCommandInputSchemas = {
33251
- doctor: external_exports.object({ cwd: nonEmptyString }).strict(),
33252
- "pr.refresh": external_exports.object({ reference: nonEmptyString }).strict(),
33253
- "pr.sync": pullRequestSyncInputSchema.extend({
33254
- repositoryPath: nonEmptyString.optional(),
33255
- allowUntracked: external_exports.boolean().default(false)
33256
- }),
33257
- "pr.attach": external_exports.object({ reference: nonEmptyString, repositoryPath: nonEmptyString }).strict(),
33258
- "pr.reset.preview": external_exports.object({ reference: nonEmptyString }).strict(),
33259
- "pr.reset": external_exports.object({ reference: nonEmptyString, confirmed: external_exports.literal(true) }).strict(),
33260
- "comment.list": external_exports.object({
33261
- reference: nonEmptyString,
33262
- resolved: external_exports.boolean().optional(),
33263
- limit: external_exports.number().int().min(1).max(MAX_COMMENT_LIST_LIMIT).default(DEFAULT_COMMENT_LIST_LIMIT),
33264
- offset: external_exports.number().int().min(0).default(0)
33265
- }).strict(),
33266
- "comment.get": external_exports.object({ uri: commentUri, live: external_exports.boolean().default(false) }).strict(),
33267
- "comment.reply": external_exports.object({ uri: commentUri, reply: commentReplyInputSchema }).strict(),
33268
- "comment.resolve": external_exports.object({ uri: commentUri }).strict(),
33269
- "comment.reopen": external_exports.object({ uri: commentUri }).strict(),
33270
- "walkthrough.get": external_exports.object({ uri: walkthroughUri }).strict(),
33271
- "walkthrough.publish": walkthroughPublishInputSchema,
33272
- "walkthrough.update": external_exports.object({ uri: walkthroughUri, content: walkthroughUpdateInputSchema }).strict(),
33273
- "walkthrough.delete.preview": external_exports.object({ uri: walkthroughUri }).strict(),
33274
- "walkthrough.delete": external_exports.object({ uri: walkthroughUri, confirmed: external_exports.literal(true) }).strict()
33275
- };
33276
-
33277
- // src/server/agent-socket.ts
33278
33749
  var MAX_CLI_STDIN_BYTES = 40 * 1024 * 1024;
33279
33750
  var MAX_AGENT_MESSAGE_BYTES = MAX_CLI_STDIN_BYTES + 64 * 1024;
33280
33751
  var AGENT_SOCKET_PROTOCOL_VERSION = 1;
@@ -33302,7 +33773,7 @@ function agentSocketPath(databaseFilePath) {
33302
33773
  if (configuredPath) return configuredPath;
33303
33774
  const user = process.getuid?.() ?? os4.userInfo().username.replace(/[^A-Za-z0-9_-]/g, "_");
33304
33775
  const databasePath = path9.resolve(databaseFilePath ?? databasePathConfiguration().filePath);
33305
- const databaseKey = createHash3("sha256").update(databasePath).digest("hex").slice(0, 16);
33776
+ const databaseKey = createHash5("sha256").update(databasePath).digest("hex").slice(0, 16);
33306
33777
  return path9.join(os4.tmpdir(), `rvw-agent-${user}`, `${databaseKey}.sock`);
33307
33778
  }
33308
33779
  function ensurePrivateSocketDirectory(socketPath) {
@@ -33407,6 +33878,16 @@ async function dispatchAgentSocketRequest(service, rawRequest) {
33407
33878
  offset: input.offset
33408
33879
  });
33409
33880
  }
33881
+ case "comment.watch": {
33882
+ const input = parseOperationInput("comment.watch", request.input);
33883
+ return service.listCommentPostEvents(input.cursor, input.limit);
33884
+ }
33885
+ case "comment.create": {
33886
+ const input = parseOperationInput("comment.create", request.input);
33887
+ return await service.createCommentForReference(
33888
+ input
33889
+ );
33890
+ }
33410
33891
  case "comment.get": {
33411
33892
  const input = parseOperationInput("comment.get", request.input);
33412
33893
  return await service.getCommentReviewContext(input.uri, { live: input.live });
@@ -33418,6 +33899,14 @@ async function dispatchAgentSocketRequest(service, rawRequest) {
33418
33899
  input.reply
33419
33900
  );
33420
33901
  }
33902
+ case "comment.edit": {
33903
+ const input = parseOperationInput("comment.edit", request.input);
33904
+ return await service.editCommentPost(input.uri, input.postId, {
33905
+ body: input.edit.body,
33906
+ ...input.edit.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.edit.relatedCommitOid },
33907
+ ...input.edit.references === void 0 ? {} : { references: input.edit.references }
33908
+ });
33909
+ }
33421
33910
  case "comment.resolve": {
33422
33911
  const input = parseOperationInput("comment.resolve", request.input);
33423
33912
  return service.setCommentResolved(input.uri, true);
@@ -33972,11 +34461,20 @@ var commentListOptionsSchema = external_exports.object({
33972
34461
  limit: external_exports.coerce.number().int().min(1).max(MAX_COMMENT_LIST_LIMIT).default(DEFAULT_COMMENT_LIST_LIMIT),
33973
34462
  offset: external_exports.coerce.number().int().min(0).default(0)
33974
34463
  });
34464
+ var commentWatchOptionsSchema = external_exports.object({
34465
+ after: external_exports.string().min(1).max(512).optional(),
34466
+ interval: external_exports.coerce.number().int().min(1).max(MAX_COMMENT_WATCH_INTERVAL_SECONDS).default(DEFAULT_COMMENT_WATCH_INTERVAL_SECONDS),
34467
+ limit: external_exports.coerce.number().int().min(1).max(MAX_COMMENT_WATCH_LIMIT).default(DEFAULT_COMMENT_WATCH_LIMIT),
34468
+ once: external_exports.boolean().optional().default(false),
34469
+ jsonSeq: external_exports.literal(true)
34470
+ });
33975
34471
  var commentPullRequestOutputSchema = external_exports.object({
33976
34472
  url: external_exports.string(),
33977
34473
  owner: external_exports.string(),
33978
34474
  repository: external_exports.string(),
33979
34475
  number: external_exports.number().int(),
34476
+ authorLogin: external_exports.string().nullable(),
34477
+ headRepository: external_exports.object({ owner: external_exports.string(), name: external_exports.string(), url: external_exports.string() }).strict().nullable(),
33980
34478
  title: external_exports.string(),
33981
34479
  body: external_exports.string().optional(),
33982
34480
  baseRefName: external_exports.string(),
@@ -34055,11 +34553,20 @@ var commentPlacementOutputSchema = external_exports.union([
34055
34553
  path: external_exports.string().nullable()
34056
34554
  }).strict()
34057
34555
  ]);
34556
+ var codeReferenceOutputSchema = external_exports.object({
34557
+ id: external_exports.string(),
34558
+ label: external_exports.string(),
34559
+ path: external_exports.string(),
34560
+ startLine: external_exports.number().int().nullable(),
34561
+ endLine: external_exports.number().int().nullable(),
34562
+ description: external_exports.string().nullable()
34563
+ }).strict();
34058
34564
  var commentPostOutputSchema = external_exports.object({
34059
34565
  id: external_exports.string(),
34060
34566
  commentId: external_exports.string(),
34061
34567
  body: external_exports.string(),
34062
34568
  relatedCommitOid: external_exports.string().nullable(),
34569
+ references: external_exports.array(codeReferenceOutputSchema),
34063
34570
  authorLabel: external_exports.string().nullable(),
34064
34571
  isRoot: external_exports.boolean(),
34065
34572
  createdAt: external_exports.string(),
@@ -34086,16 +34593,7 @@ var walkthroughOutputSchema = external_exports.object({
34086
34593
  body: external_exports.string(),
34087
34594
  authorLabel: external_exports.string().nullable(),
34088
34595
  diagramBindings: external_exports.record(external_exports.string(), external_exports.string()),
34089
- references: external_exports.array(
34090
- external_exports.object({
34091
- id: external_exports.string(),
34092
- label: external_exports.string(),
34093
- path: external_exports.string(),
34094
- startLine: external_exports.number().int().nullable(),
34095
- endLine: external_exports.number().int().nullable(),
34096
- description: external_exports.string().nullable()
34097
- }).strict()
34098
- ),
34596
+ references: external_exports.array(codeReferenceOutputSchema),
34099
34597
  createdAt: external_exports.string()
34100
34598
  }).strict();
34101
34599
  var sourceExcerptOutputSchema = external_exports.object({
@@ -34124,6 +34622,8 @@ var commentGetOutputSchema = external_exports.object({
34124
34622
  liveCheckedAt: external_exports.string().nullable(),
34125
34623
  staleAgainstGitHub: external_exports.boolean().nullable(),
34126
34624
  live: external_exports.object({
34625
+ authorLogin: external_exports.string().nullable(),
34626
+ headRepository: external_exports.object({ owner: external_exports.string(), name: external_exports.string(), url: external_exports.string() }).strict().nullable(),
34127
34627
  title: external_exports.string(),
34128
34628
  body: external_exports.string().optional(),
34129
34629
  baseRefName: external_exports.string(),
@@ -34183,11 +34683,18 @@ function truncateUtf82(value, maxBytes) {
34183
34683
  return { value: result, truncated: true };
34184
34684
  }
34185
34685
  function formatPullRequest(pullRequest, options = {}) {
34686
+ const headRepository = pullRequest.latestHeadRepositoryOwner && pullRequest.latestHeadRepositoryName ? {
34687
+ owner: pullRequest.latestHeadRepositoryOwner,
34688
+ name: pullRequest.latestHeadRepositoryName,
34689
+ url: `https://github.com/${pullRequest.latestHeadRepositoryOwner}/${pullRequest.latestHeadRepositoryName}`
34690
+ } : null;
34186
34691
  return {
34187
34692
  url: pullRequest.url,
34188
34693
  owner: pullRequest.owner,
34189
34694
  repository: pullRequest.repository,
34190
34695
  number: pullRequest.number,
34696
+ authorLogin: pullRequest.latestAuthorLogin,
34697
+ headRepository,
34191
34698
  title: pullRequest.latestTitle,
34192
34699
  ...options.includeBody ? { body: pullRequest.latestBody } : {},
34193
34700
  baseRefName: pullRequest.latestBaseRefName,
@@ -34245,6 +34752,12 @@ function formatCommentGetOutput(result, options = {}) {
34245
34752
  liveCheckedAt: result.githubState.liveCheckedAt,
34246
34753
  staleAgainstGitHub: result.githubState.staleAgainstGitHub,
34247
34754
  live: result.githubState.live ? {
34755
+ authorLogin: result.githubState.live.authorLogin,
34756
+ headRepository: result.githubState.live.headRepositoryOwner && result.githubState.live.headRepositoryName ? {
34757
+ owner: result.githubState.live.headRepositoryOwner,
34758
+ name: result.githubState.live.headRepositoryName,
34759
+ url: `https://github.com/${result.githubState.live.headRepositoryOwner}/${result.githubState.live.headRepositoryName}`
34760
+ } : null,
34248
34761
  title: result.githubState.live.title,
34249
34762
  ...options.includePrBody ? { body: result.githubState.live.body } : {},
34250
34763
  baseRefName: result.githubState.live.baseRefName,
@@ -34256,6 +34769,12 @@ function formatCommentGetOutput(result, options = {}) {
34256
34769
  }
34257
34770
  });
34258
34771
  }
34772
+ function formatCommentWatchEvent(item) {
34773
+ return {
34774
+ cursor: item.cursor,
34775
+ event: item.event
34776
+ };
34777
+ }
34259
34778
  function formatCommentListOutput(result, state) {
34260
34779
  return commentListOutputSchema.parse({
34261
34780
  ok: true,
@@ -34295,6 +34814,13 @@ function writeJson(value) {
34295
34814
  process.stdout.write(`${JSON.stringify(value)}
34296
34815
  `);
34297
34816
  }
34817
+ function writeJsonSequence(value) {
34818
+ process.stdout.write(`${JSON.stringify(value)}
34819
+ `);
34820
+ }
34821
+ async function waitForCommentWatchInterval(milliseconds) {
34822
+ await new Promise((resolve) => setTimeout(resolve, milliseconds));
34823
+ }
34298
34824
  function writeOutput(options, value, human) {
34299
34825
  if (options.json) writeJson(value);
34300
34826
  else process.stdout.write(`${human}
@@ -34668,9 +35194,13 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
34668
35194
  appVersion: APP_VERSION,
34669
35195
  capabilities: [
34670
35196
  "agent.transport",
35197
+ "comment.create",
34671
35198
  "comment.list",
35199
+ "comment.watch",
34672
35200
  "comment.read",
34673
35201
  "comment.reply",
35202
+ "comment.edit",
35203
+ "comment.codeReferences",
34674
35204
  "comment.resolve",
34675
35205
  "comment.reopen",
34676
35206
  "pullRequest.sync",
@@ -34782,7 +35312,7 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
34782
35312
  writeOutput(
34783
35313
  options,
34784
35314
  result2,
34785
- `\u524A\u9664\u5BFE\u8C61: \u30B3\u30E1\u30F3\u30C8${preview.counts.comments}\u3001\u8FD4\u4FE1${preview.counts.posts}\u3001\u5BFE\u8C61${preview.counts.targets}\u3001Walkthrough${preview.counts.walkthroughs}\u3001\u30B3\u30FC\u30C9\u53C2\u7167${preview.counts.walkthroughReferences}\u3001Git ref${preview.counts.gitRefs}
35315
+ `\u524A\u9664\u5BFE\u8C61: \u30B3\u30E1\u30F3\u30C8${preview.counts.comments}\u3001\u8FD4\u4FE1${preview.counts.posts}\u3001\u30B3\u30E1\u30F3\u30C8\u5185\u30B3\u30FC\u30C9\u53C2\u7167${preview.counts.commentReferences}\u3001\u5BFE\u8C61${preview.counts.targets}\u3001Walkthrough${preview.counts.walkthroughs}\u3001Walkthrough\u30B3\u30FC\u30C9\u53C2\u7167${preview.counts.walkthroughReferences}\u3001Git ref${preview.counts.gitRefs}
34786
35316
  \u7D9A\u884C\u3059\u308B\u306B\u306F --yes \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
34787
35317
  );
34788
35318
  process.exitCode = 2;
@@ -34870,6 +35400,75 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
34870
35400
  );
34871
35401
  writeJson({ ok: true, deleted });
34872
35402
  });
35403
+ comment.command("watch").description("\u5168\u767B\u9332PR\u3067\u8D77\u52D5\u5F8C\u306B\u4F5C\u6210\u3055\u308C\u305Froot comment\u3068reply\u3092\u76E3\u8996").option("--after <cursor>", "\u4EE5\u524D\u306Ewatch cursor\u304B\u3089\u518D\u958B").option(
35404
+ "--interval <seconds>",
35405
+ `poll\u9593\u9694\uFF08\u65E2\u5B9A: ${DEFAULT_COMMENT_WATCH_INTERVAL_SECONDS}\u79D2\uFF09`,
35406
+ String(DEFAULT_COMMENT_WATCH_INTERVAL_SECONDS)
35407
+ ).option(
35408
+ "--limit <limit>",
35409
+ `\u4E00\u5EA6\u306B\u53D6\u5F97\u3059\u308B\u6700\u5927event\u6570\uFF08\u65E2\u5B9A: ${DEFAULT_COMMENT_WATCH_LIMIT}\uFF09`,
35410
+ String(DEFAULT_COMMENT_WATCH_LIMIT)
35411
+ ).option("--once", "\u73FE\u5728\u53D6\u5F97\u53EF\u80FD\u306Aevent\u3092\u51FA\u529B\u3057\u3066\u7D42\u4E86").requiredOption("--json-seq", "RFC 7464 JSON text sequence\u3067\u51FA\u529B").action(async (rawOptions) => {
35412
+ const options = commentWatchOptionsSchema.parse(rawOptions);
35413
+ let cursor = options.after;
35414
+ let first = true;
35415
+ let stopping = false;
35416
+ const stop = () => {
35417
+ stopping = true;
35418
+ };
35419
+ process.once("SIGINT", stop);
35420
+ process.once("SIGTERM", stop);
35421
+ try {
35422
+ do {
35423
+ const result = await callService(
35424
+ "comment.watch",
35425
+ {
35426
+ ...cursor === void 0 ? {} : { cursor },
35427
+ limit: options.limit
35428
+ },
35429
+ () => getRuntime().service.listCommentPostEvents(cursor, options.limit)
35430
+ );
35431
+ if (first) {
35432
+ writeJsonSequence({
35433
+ type: "ready",
35434
+ databaseId: result.databaseId,
35435
+ cursor: result.startCursor,
35436
+ anchoredAtCurrent: result.anchoredAtCurrent
35437
+ });
35438
+ }
35439
+ for (const item of result.events) {
35440
+ writeJsonSequence({ type: "comment-posted", ...formatCommentWatchEvent(item) });
35441
+ }
35442
+ cursor = result.cursor;
35443
+ first = false;
35444
+ if (options.once || stopping) break;
35445
+ if (!result.hasMore) {
35446
+ await waitForCommentWatchInterval(options.interval * 1e3);
35447
+ }
35448
+ } while (!stopping);
35449
+ writeJsonSequence({ type: "stopped", cursor });
35450
+ } finally {
35451
+ process.off("SIGINT", stop);
35452
+ process.off("SIGTERM", stop);
35453
+ }
35454
+ });
35455
+ comment.command("create").requiredOption("--stdin", "stdin\u304B\u3089JSON\u3092\u8AAD\u3080").requiredOption("--json", "JSON\u3067\u51FA\u529B").description("\u767B\u9332\u6E08\u307FPR\u3078\u672A\u89E3\u6C7A\u30B3\u30E1\u30F3\u30C8\u3092\u4E00\u4EF6\u4F5C\u6210").action(async () => {
35456
+ const input = commentCreateInputSchema.parse(await readStdinJson());
35457
+ const request = {
35458
+ pullRequest: input.pullRequest,
35459
+ target: input.target,
35460
+ body: input.body,
35461
+ ...input.authorLabel === void 0 ? {} : { authorLabel: input.authorLabel },
35462
+ ...input.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.relatedCommitOid },
35463
+ ...input.references === void 0 ? {} : { references: input.references }
35464
+ };
35465
+ const created = await callService(
35466
+ "comment.create",
35467
+ request,
35468
+ async () => await getRuntime().service.createCommentForReference(request)
35469
+ );
35470
+ writeJson({ ok: true, comment: created });
35471
+ });
34873
35472
  comment.command("list").argument("<pull-request>", "\u767B\u9332\u6E08\u307FPR URL\u307E\u305F\u306F\u756A\u53F7").option("--state <state>", "unresolved\u3001resolved\u3001all\uFF08\u65E2\u5B9A: unresolved\uFF09", "unresolved").option(
34874
35473
  "--limit <limit>",
34875
35474
  `1\u30DA\u30FC\u30B8\u306E\u6700\u5927\u4EF6\u6570\uFF08\u65E2\u5B9A: ${DEFAULT_COMMENT_LIST_LIMIT}\uFF09`,
@@ -34902,7 +35501,9 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
34902
35501
  const reply = {
34903
35502
  body: input.body,
34904
35503
  ...input.authorLabel === void 0 ? {} : { authorLabel: input.authorLabel },
34905
- ...input.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.relatedCommitOid }
35504
+ ...input.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.relatedCommitOid },
35505
+ ...input.references === void 0 ? {} : { references: input.references },
35506
+ ...input.idempotencyKey === void 0 ? {} : { idempotencyKey: input.idempotencyKey }
34906
35507
  };
34907
35508
  const post = await callService(
34908
35509
  "comment.reply",
@@ -34911,6 +35512,20 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
34911
35512
  );
34912
35513
  writeJson({ ok: true, post });
34913
35514
  });
35515
+ comment.command("edit").argument("<comment-uri>").requiredOption("--post <post-id>", "\u7DE8\u96C6\u3059\u308Bpost ID").requiredOption("--stdin", "stdin\u304B\u3089JSON\u3092\u8AAD\u3080").requiredOption("--json", "JSON\u3067\u51FA\u529B").action(async (uri, options) => {
35516
+ const input = commentPostEditInputSchema.parse(await readStdinJson());
35517
+ const edit = {
35518
+ body: input.body,
35519
+ ...input.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.relatedCommitOid },
35520
+ ...input.references === void 0 ? {} : { references: input.references }
35521
+ };
35522
+ const post = await callService(
35523
+ "comment.edit",
35524
+ { uri, postId: options.post, edit },
35525
+ async () => await getRuntime().service.editCommentPost(uri, options.post, edit)
35526
+ );
35527
+ writeJson({ ok: true, post });
35528
+ });
34914
35529
  comment.command("resolve").argument("<comment-uri>").requiredOption("--json", "JSON\u3067\u51FA\u529B").action(async (uri) => {
34915
35530
  const comment2 = await callService(
34916
35531
  "comment.resolve",
@@ -34958,13 +35573,15 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
34958
35573
  }
34959
35574
  async function runCli(argv = process.argv) {
34960
35575
  const json3 = argv.includes("--json");
35576
+ const jsonSequence = argv.includes("--json-seq");
34961
35577
  try {
34962
35578
  await createProgram().parseAsync(argv);
34963
35579
  } catch (error51) {
34964
35580
  const rvwError = error51 instanceof external_exports.ZodError ? new RvwError("INVALID_INPUT", "\u5165\u529B\u304CCLI schema\u306B\u9069\u5408\u3057\u307E\u305B\u3093\u3002", {
34965
35581
  details: external_exports.treeifyError(error51)
34966
35582
  }) : asRvwError(error51);
34967
- if (json3) writeJson({ ok: false, error: rvwError.toJSON() });
35583
+ if (jsonSequence) writeJsonSequence({ type: "error", error: rvwError.toJSON() });
35584
+ else if (json3) writeJson({ ok: false, error: rvwError.toJSON() });
34968
35585
  else process.stderr.write(`rvw: ${rvwError.message}
34969
35586
  ${rvwError.suggestions.join("\n")}
34970
35587
  `);