tianshu-harness 3.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/LICENSE +189 -0
  2. package/README.en.md +1066 -0
  3. package/README.ja.md +1214 -0
  4. package/README.ko.md +1216 -0
  5. package/README.md +309 -0
  6. package/completions/rivet.bash +118 -0
  7. package/completions/rivet.fish +110 -0
  8. package/completions/rivet.ps1 +230 -0
  9. package/completions/rivet.zsh +187 -0
  10. package/dist/account-OAEKORZE.js +47 -0
  11. package/dist/account-login-V6FOLHJR.js +65 -0
  12. package/dist/account-status-KHNPPAFL.js +23 -0
  13. package/dist/agent/worker-process/child.js +407 -0
  14. package/dist/browser-cli-FLNY5ZHI.js +19 -0
  15. package/dist/browser-readiness-LWVGSBD5.js +12 -0
  16. package/dist/build-backends-5KXKR2S4.js +13 -0
  17. package/dist/build-options-66Y4ZE7C.js +9 -0
  18. package/dist/bundled-skills/brainstorming/SKILL.md +139 -0
  19. package/dist/bundled-skills/visual-acceptance/SKILL.md +64 -0
  20. package/dist/chain-7MAMFXZ3.js +10 -0
  21. package/dist/checkpoint-MND4DUIX.js +33 -0
  22. package/dist/chunk-2E6CK2RC.js +392 -0
  23. package/dist/chunk-2EBWGAXD.js +51 -0
  24. package/dist/chunk-2HDP7RMR.js +119 -0
  25. package/dist/chunk-2HKD2UFM.js +1000 -0
  26. package/dist/chunk-2VYRLULP.js +51 -0
  27. package/dist/chunk-2XN7PM4N.js +125 -0
  28. package/dist/chunk-35H7GVNR.js +66 -0
  29. package/dist/chunk-3C3R7JXY.js +77 -0
  30. package/dist/chunk-3VGD2FXB.js +118 -0
  31. package/dist/chunk-424AP7FM.js +534 -0
  32. package/dist/chunk-4J5TZGOE.js +3707 -0
  33. package/dist/chunk-4QJ3Y5JM.js +898 -0
  34. package/dist/chunk-4U2ET7ZY.js +1326 -0
  35. package/dist/chunk-4XPFLICE.js +876 -0
  36. package/dist/chunk-5B2OCU5P.js +31707 -0
  37. package/dist/chunk-5GGOGLSN.js +73 -0
  38. package/dist/chunk-5JRZPLI6.js +251 -0
  39. package/dist/chunk-5TQ3JYBU.js +397 -0
  40. package/dist/chunk-66JPZSGX.js +55 -0
  41. package/dist/chunk-6HSVXHCZ.js +764 -0
  42. package/dist/chunk-6S5FPUS7.js +21 -0
  43. package/dist/chunk-722LQO64.js +131 -0
  44. package/dist/chunk-73NJ7IT7.js +354 -0
  45. package/dist/chunk-7FW3I7WC.js +95 -0
  46. package/dist/chunk-7KUCBNLB.js +173 -0
  47. package/dist/chunk-7RDOV3DF.js +201 -0
  48. package/dist/chunk-A5MNH4ER.js +79 -0
  49. package/dist/chunk-ADIVZ2D5.js +15 -0
  50. package/dist/chunk-AE3P3F6W.js +366 -0
  51. package/dist/chunk-AERM3VGP.js +280 -0
  52. package/dist/chunk-AEWHC4WM.js +246 -0
  53. package/dist/chunk-AOVQ7VIF.js +169 -0
  54. package/dist/chunk-AOYHP3WI.js +12411 -0
  55. package/dist/chunk-B3YEBABJ.js +7160 -0
  56. package/dist/chunk-BCQXEZPJ.js +154 -0
  57. package/dist/chunk-BKTQAYO2.js +418 -0
  58. package/dist/chunk-BSECIPAQ.js +80 -0
  59. package/dist/chunk-BUIMGNDD.js +52 -0
  60. package/dist/chunk-BXHV3GSB.js +10320 -0
  61. package/dist/chunk-C6ZVZCPP.js +139 -0
  62. package/dist/chunk-CEZNQVWM.js +82 -0
  63. package/dist/chunk-CGFZGR7G.js +1492 -0
  64. package/dist/chunk-CGOADM2X.js +337 -0
  65. package/dist/chunk-CI4R6P2B.js +24 -0
  66. package/dist/chunk-D2TCGRSX.js +73 -0
  67. package/dist/chunk-D4PTYFOG.js +154 -0
  68. package/dist/chunk-D54ZWG4T.js +717 -0
  69. package/dist/chunk-DEBI37QB.js +145 -0
  70. package/dist/chunk-DWROHPXP.js +1051 -0
  71. package/dist/chunk-DZ6UOJ5D.js +92 -0
  72. package/dist/chunk-EBJTVRQN.js +81 -0
  73. package/dist/chunk-EGEI2RQA.js +1167 -0
  74. package/dist/chunk-EHHUASO5.js +1305 -0
  75. package/dist/chunk-EPKTIOED.js +41 -0
  76. package/dist/chunk-ER5JW2QZ.js +5681 -0
  77. package/dist/chunk-ETHFACAB.js +315 -0
  78. package/dist/chunk-EXUE5W2F.js +112 -0
  79. package/dist/chunk-EXXICUIW.js +73 -0
  80. package/dist/chunk-FFQSZJOO.js +169 -0
  81. package/dist/chunk-FHFKPGDO.js +85 -0
  82. package/dist/chunk-FW3QKMFX.js +158 -0
  83. package/dist/chunk-GD4ZNZ7W.js +30 -0
  84. package/dist/chunk-GHVMWF2I.js +581 -0
  85. package/dist/chunk-GMKAXSYQ.js +297 -0
  86. package/dist/chunk-HBVF6BWO.js +325 -0
  87. package/dist/chunk-HV4YGVMS.js +379 -0
  88. package/dist/chunk-ILBCKAV6.js +89 -0
  89. package/dist/chunk-J4U4AW46.js +440 -0
  90. package/dist/chunk-J6ESSM47.js +1791 -0
  91. package/dist/chunk-JBZHIC6T.js +2309 -0
  92. package/dist/chunk-JCFWOULR.js +245 -0
  93. package/dist/chunk-JRF5L6OD.js +131 -0
  94. package/dist/chunk-JSS75KCG.js +2014 -0
  95. package/dist/chunk-JSXWIWWJ.js +225 -0
  96. package/dist/chunk-JYV7I2QH.js +98 -0
  97. package/dist/chunk-KIOXTQQL.js +1596 -0
  98. package/dist/chunk-KWVTXT5B.js +89 -0
  99. package/dist/chunk-KX22RD6R.js +33 -0
  100. package/dist/chunk-LA6IPTGH.js +709 -0
  101. package/dist/chunk-LH5VCGLB.js +1796 -0
  102. package/dist/chunk-LQQ6XJ2Y.js +269 -0
  103. package/dist/chunk-MJQ55WZZ.js +65 -0
  104. package/dist/chunk-ML3UKMH3.js +40 -0
  105. package/dist/chunk-MOZPLHSU.js +5526 -0
  106. package/dist/chunk-NGEWJ4DF.js +89 -0
  107. package/dist/chunk-NH6VIOAR.js +211 -0
  108. package/dist/chunk-O5VZQKCB.js +26106 -0
  109. package/dist/chunk-OHSV42QB.js +748 -0
  110. package/dist/chunk-OO3TAHO5.js +4070 -0
  111. package/dist/chunk-OTNHSAGN.js +38282 -0
  112. package/dist/chunk-OUWAC7AQ.js +442 -0
  113. package/dist/chunk-OXMIV4WE.js +270 -0
  114. package/dist/chunk-P5KJURUR.js +229 -0
  115. package/dist/chunk-P6GJOVO6.js +307 -0
  116. package/dist/chunk-QARAGUXX.js +23 -0
  117. package/dist/chunk-R43HJCDX.js +2711 -0
  118. package/dist/chunk-RAXBAWRN.js +210 -0
  119. package/dist/chunk-RK3JHWPT.js +39 -0
  120. package/dist/chunk-RWA23GMM.js +24 -0
  121. package/dist/chunk-S4K4L6IM.js +179 -0
  122. package/dist/chunk-SAXK6LVF.js +124 -0
  123. package/dist/chunk-SEPGEJNK.js +1607 -0
  124. package/dist/chunk-SUJERP5I.js +285 -0
  125. package/dist/chunk-T3ED6BY2.js +913 -0
  126. package/dist/chunk-THKDVSEC.js +90 -0
  127. package/dist/chunk-TI4GSEL5.js +52 -0
  128. package/dist/chunk-TPI73L57.js +164 -0
  129. package/dist/chunk-TVHW77C7.js +338 -0
  130. package/dist/chunk-TWNHOSDT.js +1073 -0
  131. package/dist/chunk-UFMN76QD.js +347 -0
  132. package/dist/chunk-UHGLFRZE.js +205 -0
  133. package/dist/chunk-UTZYPKBF.js +15231 -0
  134. package/dist/chunk-UXNLELW6.js +25 -0
  135. package/dist/chunk-UXXS53EA.js +166 -0
  136. package/dist/chunk-V5DHFGI7.js +171 -0
  137. package/dist/chunk-V5YIPMHV.js +2353 -0
  138. package/dist/chunk-WMUWEO2C.js +754 -0
  139. package/dist/chunk-WOE3D7JM.js +945 -0
  140. package/dist/chunk-X2IK5LVR.js +2592 -0
  141. package/dist/chunk-XU2YXCDL.js +459 -0
  142. package/dist/chunk-YJG5HIX5.js +203 -0
  143. package/dist/chunk-Z3QE7TZM.js +72 -0
  144. package/dist/chunk-Z5Z3JHJY.js +64 -0
  145. package/dist/chunk-ZDIFBJFT.js +168 -0
  146. package/dist/chunk-ZGGCEXDC.js +176 -0
  147. package/dist/chunk-ZMZCZNKU.js +263 -0
  148. package/dist/chunk-ZNC5T65N.js +17 -0
  149. package/dist/chunk-ZO3I3A7O.js +308 -0
  150. package/dist/chunk-ZQKXBUB7.js +217 -0
  151. package/dist/chunk-ZTRINFM2.js +78 -0
  152. package/dist/chunk-ZU7JZCVP.js +193 -0
  153. package/dist/chunk-ZZAWNALS.js +350 -0
  154. package/dist/cli/entry.js +54 -0
  155. package/dist/connector-L5QQTR6Y.js +26 -0
  156. package/dist/context-62DC6EC3.js +31 -0
  157. package/dist/council-convene-NJWPNBDU.js +46 -0
  158. package/dist/create-agent-config-ODSQWNVC.js +55 -0
  159. package/dist/default-registry-2PU3BTAU.js +68 -0
  160. package/dist/deliver-task-KONV4C4M.js +57 -0
  161. package/dist/delivery-gate-v2-F2YVMVGK.js +27 -0
  162. package/dist/domain-knowledge-store-DDZ3F4J7.js +11 -0
  163. package/dist/fetch-core-ZPPYDSZH.js +14 -0
  164. package/dist/galaxy-K72BBDQN.js +91 -0
  165. package/dist/goal-criteria-SCALAU2D.js +141 -0
  166. package/dist/goal-persist-XWY2GDQX.js +19 -0
  167. package/dist/goal-tracker-FXMJ2GVK.js +11 -0
  168. package/dist/headless-LSB6I7PT.js +162 -0
  169. package/dist/headless-coordinator-VDPDMVUT.js +90 -0
  170. package/dist/inject-U55SMB6A.js +39 -0
  171. package/dist/login-flow-CD4ZGXOC.js +59 -0
  172. package/dist/logs-cli-SQVYFMMN.js +283 -0
  173. package/dist/loop-ULZYBDA3.js +76 -0
  174. package/dist/main.js +4064 -0
  175. package/dist/manager-ROZBCWPA.js +171 -0
  176. package/dist/manager-Z7XFFUOM.js +10670 -0
  177. package/dist/meridian-indexer-ZIW363L7.js +21 -0
  178. package/dist/native-resolver-PN34UIVV.js +13 -0
  179. package/dist/node_modules/better-sqlite3/lib/database.js +90 -0
  180. package/dist/node_modules/better-sqlite3/lib/index.js +3 -0
  181. package/dist/node_modules/better-sqlite3/lib/methods/aggregate.js +43 -0
  182. package/dist/node_modules/better-sqlite3/lib/methods/backup.js +67 -0
  183. package/dist/node_modules/better-sqlite3/lib/methods/function.js +31 -0
  184. package/dist/node_modules/better-sqlite3/lib/methods/inspect.js +7 -0
  185. package/dist/node_modules/better-sqlite3/lib/methods/pragma.js +12 -0
  186. package/dist/node_modules/better-sqlite3/lib/methods/serialize.js +16 -0
  187. package/dist/node_modules/better-sqlite3/lib/methods/table.js +189 -0
  188. package/dist/node_modules/better-sqlite3/lib/methods/transaction.js +78 -0
  189. package/dist/node_modules/better-sqlite3/lib/methods/wrappers.js +54 -0
  190. package/dist/node_modules/better-sqlite3/lib/sqlite-error.js +20 -0
  191. package/dist/node_modules/better-sqlite3/lib/util.js +12 -0
  192. package/dist/node_modules/better-sqlite3/package.json +59 -0
  193. package/dist/ownership-ledger-E3WIEKPL.js +9 -0
  194. package/dist/package.json +3 -0
  195. package/dist/path-grants-XRRXHXG7.js +40 -0
  196. package/dist/paths-LVV5IMQN.js +49 -0
  197. package/dist/plan-fact-anchors-LMVQZCW5.js +13 -0
  198. package/dist/plan-store-ODLTTPFB.js +17 -0
  199. package/dist/plan-templates-5FPFBOL6.js +109 -0
  200. package/dist/plugin-loader-ZZKX7ZE6.js +22 -0
  201. package/dist/prefix-budget-62OV5HQC.js +13 -0
  202. package/dist/project-trust-5WS5MOMU.js +31 -0
  203. package/dist/provider-cli-ALDQXIT7.js +37 -0
  204. package/dist/providers-XQYTAVPK.js +11 -0
  205. package/dist/proxy-resolver-V2Y6534D.js +15 -0
  206. package/dist/recovery-cli-KPGY6FY3.js +106 -0
  207. package/dist/review-discipline-MNSYCST5.js +55 -0
  208. package/dist/review-router-BVQZW3MX.js +18 -0
  209. package/dist/seed-capsules/seed-capsule-attack-methodology.md +62 -0
  210. package/dist/seed-capsules/seed-capsule-changgeng.md +31 -0
  211. package/dist/seed-capsules/seed-capsule-design-aesthetics.md +38 -0
  212. package/dist/seed-capsules/seed-capsule-diagnostic-ladder.md +54 -0
  213. package/dist/seed-capsules/seed-capsule-fu.md +39 -0
  214. package/dist/seed-capsules/seed-capsule-huagai.md +73 -0
  215. package/dist/seed-capsules/seed-capsule-kaiyang.md +65 -0
  216. package/dist/seed-capsules/seed-capsule-knowledge-work.md +40 -0
  217. package/dist/seed-capsules/seed-capsule-tanlang.md +47 -0
  218. package/dist/seed-capsules/seed-capsule-tianfu.md +23 -0
  219. package/dist/seed-capsules/seed-capsule-tianliang.md +63 -0
  220. package/dist/seed-capsules/seed-capsule-tianquan.md +32 -0
  221. package/dist/seed-capsules/seed-capsule-tianxuan-ccr.md +22 -0
  222. package/dist/seed-capsules/seed-capsule-tianxuan.md +64 -0
  223. package/dist/seed-capsules/seed-capsule-yaoguang.md +87 -0
  224. package/dist/serve-X2R2UTLF.js +170 -0
  225. package/dist/serve-agent-KHSU6RVV.js +965 -0
  226. package/dist/session-persist-HUUC772H.js +37 -0
  227. package/dist/session-registry-6XUD5C4Y.js +15 -0
  228. package/dist/skill-loader-CK3RMO47.js +48 -0
  229. package/dist/skills/cli-harness-sop.md +207 -0
  230. package/dist/spawn-git-4HFU65AH.js +29 -0
  231. package/dist/sse-EYUTBWUK.js +512 -0
  232. package/dist/starflow-NOFBMPFU.js +30 -0
  233. package/dist/streamableHttp-V67CNJMO.js +447 -0
  234. package/dist/task-contract-6XHBNJQK.js +32 -0
  235. package/dist/task-ledger-3K4TJIER.js +9 -0
  236. package/dist/team-orchestrate-S6NHZP7X.js +64 -0
  237. package/dist/title-extract-QX4XGCYN.js +50 -0
  238. package/dist/todo-QDXGRZZP.js +31 -0
  239. package/dist/todo-store-V3TTO5AH.js +12 -0
  240. package/dist/tool-preset-LU5BYEDZ.js +23 -0
  241. package/dist/tool-tiers-GD742YBN.js +23 -0
  242. package/dist/turndown.es-OI55K6C3.js +17373 -0
  243. package/dist/verification-attribution-EKG4CNUV.js +13 -0
  244. package/dist/volatile-git-MBTST7RA.js +15 -0
  245. package/dist/wave-checkpoint-XLIIHXQA.js +30 -0
  246. package/dist/web-cli-DUG4I35O.js +233 -0
  247. package/dist/web-search-3IK542AA.js +34 -0
  248. package/dist/workers/cpu-worker.js +45 -0
  249. package/dist/workflow-runner-HX7UBAYG.js +297 -0
  250. package/dist/worktree-baseline-O5NCU6M2.js +9 -0
  251. package/package.json +122 -0
  252. package/scripts/check-mobile-env.mjs +76 -0
  253. package/scripts/fetch-native-sqlite.js +392 -0
  254. package/scripts/prune-installed-wasms.js +45 -0
  255. package/scripts/tree-sitter-wasm-keep.js +40 -0
@@ -0,0 +1,709 @@
1
+ #!/usr/bin/env -S node --expose-gc --max-old-space-size=4096
2
+ import { createRequire as __rivetCreateRequire } from 'node:module'; const require = __rivetCreateRequire(import.meta.url);
3
+ import {
4
+ runTypecheckShared
5
+ } from "./chunk-HBVF6BWO.js";
6
+ import {
7
+ spawnHidden
8
+ } from "./chunk-35H7GVNR.js";
9
+ import {
10
+ init_esm_shims
11
+ } from "./chunk-5GGOGLSN.js";
12
+
13
+ // src/agent/verify-command.ts
14
+ init_esm_shims();
15
+ var TOKEN_RE = /^[A-Za-z0-9@._+/\\:=,-]+$/;
16
+ function matchPackageRunner(argv) {
17
+ if (argv[1] === "test") return true;
18
+ return argv[1] === "run" && argv[2] !== void 0 && argv[2] !== "";
19
+ }
20
+ var VERIFY_FAMILIES = {
21
+ npx: (argv) => argv[1] !== void 0 && ["tsc", "vitest", "jest", "tsx"].includes(argv[1]),
22
+ npm: matchPackageRunner,
23
+ pnpm: matchPackageRunner,
24
+ yarn: matchPackageRunner,
25
+ node: (argv) => argv[1] === "--test",
26
+ cargo: (argv) => argv[1] === "test" || argv[1] === "check",
27
+ go: (argv) => argv[1] === "test" || argv[1] === "vet" || argv[1] === "build",
28
+ pytest: () => true,
29
+ python: (argv) => argv[1] === "-m" && argv[2] === "pytest",
30
+ make: (argv) => argv[1] === "test" || argv[1] === "check"
31
+ };
32
+ function parseVerifyCommand(command) {
33
+ const trimmed = command.trim();
34
+ if (trimmed === "") return null;
35
+ const argv = trimmed.split(/\s+/);
36
+ for (const token of argv) {
37
+ if (!TOKEN_RE.test(token)) return null;
38
+ }
39
+ const family = VERIFY_FAMILIES[argv[0]];
40
+ if (!family || !family(argv)) return null;
41
+ return argv;
42
+ }
43
+ function spawnVerifyArgv(cwd, argv, options = {}) {
44
+ if (argv.length === 0 || argv[0] === "") throw new Error("spawnVerifyArgv: empty argv");
45
+ if (process.platform === "win32") {
46
+ const comspec = process.env.ComSpec ?? "cmd.exe";
47
+ return spawnHidden(comspec, ["/d", "/s", "/c", argv.join(" ")], { cwd, shell: false, ...options });
48
+ }
49
+ return spawnHidden(argv[0], argv.slice(1), { cwd, shell: false, ...options });
50
+ }
51
+
52
+ // src/agent/test-presence.ts
53
+ init_esm_shims();
54
+ function isTestFilePath(path) {
55
+ return /[\\/]__tests__[\\/]/i.test(path) || /\.(test|spec)\.[cm]?[jt]sx?$/i.test(path);
56
+ }
57
+ function isSourceFilePath(path) {
58
+ if (isTestFilePath(path)) return false;
59
+ if (/\.d\.[cm]?ts$/i.test(path)) return false;
60
+ if (!/\.[cm]?[jt]sx?$/i.test(path)) return false;
61
+ const normalized = path.replace(/\\/g, "/");
62
+ if (/(^|\/)(docs|doc|examples?|scripts)\//i.test(normalized)) return false;
63
+ const base = normalized.split("/").pop() ?? "";
64
+ if (/\.config\.[cm]?[jt]s$/i.test(base)) return false;
65
+ return true;
66
+ }
67
+ function testPresenceGateEnabled() {
68
+ return process.env.RIVET_TEST_PRESENCE_GATE !== "0";
69
+ }
70
+ function evaluateTestPresence(changedFiles, threshold = 3) {
71
+ const sourceFiles = changedFiles.filter(isSourceFilePath);
72
+ const testFiles = changedFiles.filter(isTestFilePath);
73
+ if (sourceFiles.length >= threshold && testFiles.length === 0) {
74
+ const list = sourceFiles.slice(0, 10).join(", ");
75
+ const more = sourceFiles.length > 10 ? ` (+${sourceFiles.length - 10} more)` : "";
76
+ return {
77
+ ok: false,
78
+ sourceFiles,
79
+ testFiles,
80
+ detail: `${sourceFiles.length} \u4E2A\u6E90\u6587\u4EF6\u53D8\u66F4\u4F46\u96F6\u6D4B\u8BD5\u6587\u4EF6\uFF1A${list}${more}\u3002\u4E3A\u6838\u5FC3\u884C\u4E3A\u8865\u6D4B\u8BD5\u6587\u4EF6\uFF08__tests__/*.test.ts \u6216\u540C\u540D *.test.*\uFF09\u540E\u81EA\u52A8\u653E\u884C\u3002`
81
+ };
82
+ }
83
+ return { ok: true, sourceFiles, testFiles };
84
+ }
85
+
86
+ // src/lsp/server-registry.ts
87
+ init_esm_shims();
88
+ import { execFileSync } from "child_process";
89
+ var LSP_SERVERS = [
90
+ {
91
+ id: "typescript",
92
+ extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"],
93
+ command: "npx",
94
+ args: ["-y", "typescript-language-server", "--stdio"],
95
+ languageId: "typescript",
96
+ languageIdByExt: {
97
+ ".ts": "typescript",
98
+ ".tsx": "typescriptreact",
99
+ ".js": "javascript",
100
+ ".jsx": "javascriptreact",
101
+ ".mjs": "javascript",
102
+ ".cjs": "javascript",
103
+ ".mts": "typescript",
104
+ ".cts": "typescript"
105
+ },
106
+ alwaysAvailable: true
107
+ },
108
+ { id: "pyright", extensions: [".py", ".pyi"], command: "pyright-langserver", args: ["--stdio"], languageId: "python" },
109
+ { id: "gopls", extensions: [".go"], command: "gopls", args: [], languageId: "go" },
110
+ { id: "rust-analyzer", extensions: [".rs"], command: "rust-analyzer", args: [], languageId: "rust" },
111
+ {
112
+ id: "clangd",
113
+ extensions: [".c", ".h", ".cpp", ".cc", ".cxx", ".hpp", ".hh", ".hxx"],
114
+ command: "clangd",
115
+ args: [],
116
+ languageId: "c",
117
+ languageIdByExt: {
118
+ ".c": "c",
119
+ ".h": "c",
120
+ ".cpp": "cpp",
121
+ ".cc": "cpp",
122
+ ".cxx": "cpp",
123
+ ".hpp": "cpp",
124
+ ".hh": "cpp",
125
+ ".hxx": "cpp"
126
+ }
127
+ },
128
+ // jdtls 需要 Java 21+ 运行时(JAVA_HOME 或 PATH 上),且建议用 -data 指定
129
+ // per-project workspace——这两点由用户的 jdtls 安装/包装脚本决定,天枢不代管。
130
+ { id: "jdtls", extensions: [".java"], command: "jdtls", args: [], languageId: "java" },
131
+ // C#:微软官方 roslyn-language-server(VS Code C# 扩展同源)优先,csharp-ls 兜底。
132
+ { id: "roslyn-language-server", extensions: [".cs"], command: "roslyn-language-server", args: ["--stdio"], languageId: "csharp" },
133
+ { id: "csharp-ls", extensions: [".cs"], command: "csharp-ls", args: [], languageId: "csharp" },
134
+ { id: "kotlin-language-server", extensions: [".kt", ".kts"], command: "kotlin-language-server", args: [], languageId: "kotlin" },
135
+ { id: "sourcekit-lsp", extensions: [".swift"], command: "sourcekit-lsp", args: [], languageId: "swift" },
136
+ { id: "dart", extensions: [".dart"], command: "dart", args: ["language-server", "--protocol=lsp"], languageId: "dart" },
137
+ { id: "metals", extensions: [".scala", ".sbt"], command: "metals", args: [], languageId: "scala" },
138
+ { id: "intelephense", extensions: [".php"], command: "intelephense", args: ["--stdio"], languageId: "php" },
139
+ { id: "phpactor", extensions: [".php"], command: "phpactor", args: ["language-server"], languageId: "php" },
140
+ { id: "ruby-lsp", extensions: [".rb", ".rake", ".gemspec"], command: "ruby-lsp", args: [], languageId: "ruby" },
141
+ { id: "solargraph", extensions: [".rb", ".rake", ".gemspec"], command: "solargraph", args: ["stdio"], languageId: "ruby" },
142
+ { id: "lua-language-server", extensions: [".lua"], command: "lua-language-server", args: [], languageId: "lua" },
143
+ { id: "zls", extensions: [".zig", ".zon"], command: "zls", args: [], languageId: "zig" },
144
+ { id: "bash-language-server", extensions: [".sh", ".bash", ".zsh"], command: "bash-language-server", args: ["start"], languageId: "shellscript" },
145
+ { id: "terraform-ls", extensions: [".tf", ".tfvars"], command: "terraform-ls", args: ["serve"], languageId: "terraform" },
146
+ { id: "clojure-lsp", extensions: [".clj", ".cljs", ".cljc", ".edn"], command: "clojure-lsp", args: [], languageId: "clojure" },
147
+ { id: "ocamllsp", extensions: [".ml", ".mli"], command: "ocamllsp", args: [], languageId: "ocaml" },
148
+ { id: "haskell-language-server", extensions: [".hs", ".lhs"], command: "haskell-language-server-wrapper", args: ["--lsp"], languageId: "haskell" },
149
+ { id: "nil", extensions: [".nix"], command: "nil", args: [], languageId: "nix" },
150
+ { id: "vue-language-server", extensions: [".vue"], command: "vue-language-server", args: ["--stdio"], languageId: "vue" },
151
+ { id: "svelteserver", extensions: [".svelte"], command: "svelteserver", args: ["--stdio"], languageId: "svelte" }
152
+ ];
153
+ var whichCache = /* @__PURE__ */ new Map();
154
+ function probeWhich(bin) {
155
+ try {
156
+ execFileSync(process.platform === "win32" ? "where" : "which", [bin], {
157
+ stdio: ["ignore", "ignore", "ignore"],
158
+ timeout: 800,
159
+ windowsHide: true
160
+ });
161
+ return true;
162
+ } catch {
163
+ return false;
164
+ }
165
+ }
166
+ function defaultWhich(bin) {
167
+ const cached = whichCache.get(bin);
168
+ if (cached !== void 0) return cached;
169
+ const found = probeWhich(bin);
170
+ whichCache.set(bin, found);
171
+ return found;
172
+ }
173
+ function extOf(filePath) {
174
+ const i = filePath.lastIndexOf(".");
175
+ return i >= 0 ? filePath.slice(i).toLowerCase() : "";
176
+ }
177
+ function serverDefsForExt(ext) {
178
+ const e = ext.startsWith(".") ? ext.toLowerCase() : `.${ext.toLowerCase()}`;
179
+ return LSP_SERVERS.filter((s) => s.extensions.includes(e));
180
+ }
181
+ function serverDefForExt(ext) {
182
+ return serverDefsForExt(ext)[0] ?? null;
183
+ }
184
+ function isServerAvailable(def, which = defaultWhich) {
185
+ if (def.alwaysAvailable) return true;
186
+ return which(def.binary ?? def.command);
187
+ }
188
+ function serverForFile(filePath, which = defaultWhich) {
189
+ return serverDefsForExt(extOf(filePath)).find((def) => isServerAvailable(def, which)) ?? null;
190
+ }
191
+ function hasServerForFile(filePath) {
192
+ return serverDefForExt(extOf(filePath)) !== null;
193
+ }
194
+ function languageIdForFile(def, filePath) {
195
+ return def.languageIdByExt?.[extOf(filePath)] ?? def.languageId;
196
+ }
197
+ function availableServers(which = defaultWhich) {
198
+ return LSP_SERVERS.filter((s) => isServerAvailable(s, which));
199
+ }
200
+
201
+ // src/lsp/client.ts
202
+ init_esm_shims();
203
+
204
+ // src/lsp/diagnostics.ts
205
+ init_esm_shims();
206
+ var TSC_PATTERN = /^(.+?)\((\d+),(\d+)\): (error|warning) TS\d+: (.+)$/;
207
+ function parseDiagnosticOutput(output, _lang) {
208
+ return output.trim().split("\n").filter(Boolean).map((line) => {
209
+ const m = TSC_PATTERN.exec(line);
210
+ if (!m) return null;
211
+ return {
212
+ file: m[1],
213
+ line: parseInt(m[2], 10),
214
+ col: parseInt(m[3], 10),
215
+ severity: m[4],
216
+ message: m[5]
217
+ };
218
+ }).filter((d) => d !== null);
219
+ }
220
+ function formatDiagnostics(diags) {
221
+ if (diags.length === 0) return "";
222
+ return diags.map((d) => `${d.file}:${d.line}:${d.col} ${d.severity}: ${d.message}`).join("\n");
223
+ }
224
+
225
+ // src/lsp/client.ts
226
+ import { isAbsolute, relative, join } from "path";
227
+ import { spawn } from "child_process";
228
+ import { existsSync } from "fs";
229
+ import { createRequire } from "module";
230
+ var _tscPath = void 0;
231
+ var _tscMissingWarned = false;
232
+ function resolveTscPath(cwd) {
233
+ if (_tscPath !== void 0) return _tscPath;
234
+ const bin = join(cwd, "node_modules", ".bin");
235
+ const candidates = process.platform === "win32" ? [join(bin, "tsc.cmd"), join(bin, "tsc")] : [join(bin, "tsc")];
236
+ for (const candidate of candidates) {
237
+ if (existsSync(candidate)) {
238
+ _tscPath = candidate;
239
+ return candidate;
240
+ }
241
+ }
242
+ _tscPath = null;
243
+ return null;
244
+ }
245
+ async function runTypeCheck(cwd, filePath, timeoutMs = 12e4) {
246
+ const tscPath = resolveTscPath(cwd);
247
+ if (!tscPath) {
248
+ if (!_tscMissingWarned) {
249
+ _tscMissingWarned = true;
250
+ process.stderr.write(
251
+ `[rivet] typecheck gate: node_modules/.bin/tsc not found, falling back to in-process ts.createProgram.
252
+ Install typescript as a devDependency (npm i -D typescript) for subprocess isolation.
253
+ `
254
+ );
255
+ }
256
+ return runTypeCheckInProcess(cwd, filePath);
257
+ }
258
+ const result = await runTscShared(tscPath, cwd, timeoutMs);
259
+ const ranOk = result.status === 0 || result.status === 1;
260
+ const output = result.stdout + result.stderr;
261
+ const allDiagnostics = ranOk ? parseDiagnosticOutput(output, "ts") : [];
262
+ const filtered = filePath === "*" ? allDiagnostics : allDiagnostics.filter((d) => d.file.includes(filePath));
263
+ return {
264
+ diagnostics: filtered,
265
+ formatted: formatDiagnostics(filtered),
266
+ ranOk
267
+ };
268
+ }
269
+ var TSC_GATE_ARGS = ["--noEmit", "--pretty", "false"];
270
+ function runTscShared(tscPath, cwd, timeoutMs) {
271
+ const direct = () => runTscSubprocess(tscPath, cwd, timeoutMs);
272
+ if (process.env.RIVET_TYPECHECK_SHARE === "0") return direct();
273
+ return runTypecheckShared({
274
+ cwd,
275
+ run: direct,
276
+ // 与 npm script 的人读格式分桶:回放另一种格式的原始输出会让 parseDiagnosticOutput 解析错乱。
277
+ variant: TSC_GATE_ARGS.join(" "),
278
+ // 等待预算给满 tsc 自己的超时,不打折:持锁者跑的是同一份检查,等它出结果
279
+ // 几乎总快于自己重跑一遍(后者要付全额时间,还抢走它的核心让两边都更慢)。
280
+ // 打折的后果实测过——等待者集体超时后并发开跑,负载反而更高。
281
+ waitBudgetMs: timeoutMs
282
+ });
283
+ }
284
+ function runTscSubprocess(tscPath, cwd, timeoutMs) {
285
+ return new Promise((resolve2) => {
286
+ const useShell = process.platform === "win32" && tscPath.toLowerCase().endsWith(".cmd");
287
+ const command = useShell ? `"${tscPath}"` : tscPath;
288
+ const child = spawn(command, [...TSC_GATE_ARGS], {
289
+ cwd,
290
+ env: { ...process.env },
291
+ stdio: ["ignore", "pipe", "pipe"],
292
+ windowsHide: true,
293
+ shell: useShell
294
+ });
295
+ let stdout = "";
296
+ let stderr = "";
297
+ const MAX = 10 * 1024 * 1024;
298
+ let killed = false;
299
+ const timer = setTimeout(() => {
300
+ killed = true;
301
+ child.kill("SIGKILL");
302
+ }, timeoutMs);
303
+ child.stdout?.on("data", (chunk) => {
304
+ if (stdout.length < MAX) stdout += chunk.toString("utf8").slice(0, MAX - stdout.length);
305
+ });
306
+ child.stderr?.on("data", (chunk) => {
307
+ if (stderr.length < MAX) stderr += chunk.toString("utf8").slice(0, MAX - stderr.length);
308
+ });
309
+ child.on("error", () => {
310
+ clearTimeout(timer);
311
+ resolve2({ status: null, stdout, stderr });
312
+ });
313
+ child.on("close", (code) => {
314
+ clearTimeout(timer);
315
+ resolve2({ status: killed ? null : code, stdout, stderr });
316
+ });
317
+ });
318
+ }
319
+ var _tsModule;
320
+ var _tsLoadAttempted = false;
321
+ function loadTsModule() {
322
+ if (_tsLoadAttempted) return _tsModule;
323
+ _tsLoadAttempted = true;
324
+ try {
325
+ const require2 = createRequire(import.meta.url);
326
+ _tsModule = require2("typescript");
327
+ } catch {
328
+ }
329
+ return _tsModule;
330
+ }
331
+ async function runTypeCheckInProcess(cwd, filePath) {
332
+ const ts = loadTsModule();
333
+ if (!ts) {
334
+ return { diagnostics: [], formatted: "", ranOk: false };
335
+ }
336
+ const configPath = ts.findConfigFile(cwd, ts.sys.fileExists, "tsconfig.json");
337
+ if (!configPath) {
338
+ return { diagnostics: [], formatted: "", ranOk: false };
339
+ }
340
+ const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
341
+ if (configFile.error) {
342
+ return { diagnostics: [], formatted: "", ranOk: false };
343
+ }
344
+ const parsed = ts.parseJsonConfigFileContent(
345
+ configFile.config,
346
+ ts.sys,
347
+ cwd
348
+ );
349
+ const program = ts.createProgram(parsed.fileNames, {
350
+ ...parsed.options,
351
+ noEmit: true,
352
+ pretty: false
353
+ });
354
+ const allDiagnostics = ts.getPreEmitDiagnostics(program);
355
+ const diagnostics = [];
356
+ for (const d of allDiagnostics) {
357
+ const category = ts.DiagnosticCategory;
358
+ const severity = d.category === category.Error ? "error" : d.category === category.Warning ? "warning" : "info";
359
+ const file = d.file;
360
+ if (!file) continue;
361
+ const absFile = file.fileName;
362
+ const relFile = isAbsolute(absFile) ? relative(cwd, absFile) : absFile;
363
+ const lineChar = ts.getLineAndCharacterOfPosition(file, d.start ?? 0);
364
+ diagnostics.push({
365
+ file: relFile,
366
+ line: lineChar.line + 1,
367
+ col: lineChar.character + 1,
368
+ severity,
369
+ message: ts.flattenDiagnosticMessageText(d.messageText, "\n")
370
+ });
371
+ }
372
+ const filtered = filePath === "*" ? diagnostics : diagnostics.filter((d) => d.file.includes(filePath));
373
+ return {
374
+ diagnostics: filtered,
375
+ formatted: formatDiagnostics(filtered),
376
+ ranOk: true
377
+ };
378
+ }
379
+ function shouldRunDiagnostics(toolName, filePath) {
380
+ if (toolName !== "write_file" && toolName !== "edit_file") return false;
381
+ if (!filePath) return false;
382
+ return hasServerForFile(filePath);
383
+ }
384
+ var DIAGNOSTIC_CONTEXT_LINES = 3;
385
+ var MODEL_INREGION_CAP = 10;
386
+ var MODEL_OUTREGION_LINE_CAP = 5;
387
+ var UI_DIAGNOSTIC_CAP = 20;
388
+ function formatDiagnosticLine(d) {
389
+ const kind = d.severity === 1 ? "ERROR" : "WARNING";
390
+ return `${kind} L${d.range.start.line + 1}: ${d.message}`;
391
+ }
392
+ function filterDiagnosticsForEdit(diagnostics, changedRanges, context = DIAGNOSTIC_CONTEXT_LINES) {
393
+ const relevant = diagnostics.filter((d) => d.severity <= 2);
394
+ if (relevant.length === 0) return { modelText: "", uiText: "" };
395
+ const uiText = relevant.slice(0, UI_DIAGNOSTIC_CAP).map(formatDiagnosticLine).join("\n");
396
+ if (!changedRanges || changedRanges.length === 0) {
397
+ const modelText = relevant.slice(0, MODEL_INREGION_CAP).map(formatDiagnosticLine).join("\n");
398
+ return { modelText, uiText };
399
+ }
400
+ const inRegion = (line1) => changedRanges.some((r) => line1 >= r.start - context && line1 <= r.end + context);
401
+ const inside = [];
402
+ const outsideErrors = [];
403
+ for (const d of relevant) {
404
+ const line1 = d.range.start.line + 1;
405
+ if (inRegion(line1)) inside.push(d);
406
+ else if (d.severity === 1) outsideErrors.push(d);
407
+ }
408
+ const parts = [];
409
+ if (inside.length > 0) {
410
+ parts.push(inside.slice(0, MODEL_INREGION_CAP).map(formatDiagnosticLine).join("\n"));
411
+ }
412
+ if (outsideErrors.length > 0) {
413
+ const lines = outsideErrors.slice(0, MODEL_OUTREGION_LINE_CAP).map((d) => `L${d.range.start.line + 1}`).join(", ");
414
+ const more = outsideErrors.length > MODEL_OUTREGION_LINE_CAP ? ", \u2026" : "";
415
+ parts.push(
416
+ `+${outsideErrors.length} error(s) elsewhere in file (${lines}${more}) \u2014 run typecheck before delivery`
417
+ );
418
+ }
419
+ return { modelText: parts.join("\n"), uiText };
420
+ }
421
+
422
+ // src/agent/typecheck-gate.ts
423
+ init_esm_shims();
424
+ import { isAbsolute as isAbsolute2, relative as relative2, join as join2 } from "path";
425
+ import { statSync, readFileSync } from "fs";
426
+ var TYPECHECK_CMD_RE = /\b(tsc|type-?check)\b/i;
427
+ var defaultRunner = (cwd) => runTypeCheck(cwd, "*");
428
+ var GATE_TSC_TIMEOUT_MS = 3e5;
429
+ var gateTypecheckRunner = (cwd) => runTypeCheck(cwd, "*", GATE_TSC_TIMEOUT_MS);
430
+ function typecheckGateEnabled() {
431
+ const v = process.env.RIVET_TYPECHECK_GATE;
432
+ if (v == null) return true;
433
+ return !/^(0|false|off|no)$/i.test(v.trim());
434
+ }
435
+ function repoWideEnabled() {
436
+ const v = process.env.RIVET_TYPECHECK_REPO_WIDE;
437
+ if (v == null) return true;
438
+ return !/^(0|false|off|no)$/i.test(v.trim());
439
+ }
440
+ var MAX_FILES = 8;
441
+ var MAX_ERRORS_PER_FILE = 5;
442
+ function normalizeDiagFile(cwd, file) {
443
+ const rel = isAbsolute2(file) ? relative2(cwd, file) : file;
444
+ return rel.split("\\").join("/");
445
+ }
446
+ function errorSignature(cwd, d) {
447
+ return `${normalizeDiagFile(cwd, d.file)}|${d.line}|${d.message}`;
448
+ }
449
+ function loadTypecheckBaseline(cwd) {
450
+ try {
451
+ const raw = readFileSync(join2(cwd, ".rivet", "typecheck-baseline.json"), "utf-8");
452
+ const arr = JSON.parse(raw);
453
+ if (!Array.isArray(arr)) return /* @__PURE__ */ new Set();
454
+ return new Set(arr.filter((x) => typeof x === "string"));
455
+ } catch {
456
+ return /* @__PURE__ */ new Set();
457
+ }
458
+ }
459
+ async function runChangedFilesTypecheckOutcome(cwd, changedFiles, run = defaultRunner, baseline = loadTypecheckBaseline(cwd)) {
460
+ const rel = changedFiles.filter((f) => !isAbsolute2(f) && /\.(ts|tsx)$/.test(f));
461
+ if (rel.length === 0) return { status: "clean", result: null, reason: "no changed .ts/.tsx files" };
462
+ const res = await run(cwd);
463
+ if (!res.ranOk) return { status: "inconclusive", result: null, reason: "tsc did not run to completion (crash/timeout)" };
464
+ const byFile = {};
465
+ const driftByFile = {};
466
+ let driftCount = 0;
467
+ const useRepoWide = repoWideEnabled();
468
+ for (const d of res.diagnostics) {
469
+ if (d.severity !== "error") continue;
470
+ if (baseline.has(errorSignature(cwd, d))) continue;
471
+ const nf = normalizeDiagFile(cwd, d.file);
472
+ const hit = rel.find((f) => nf === f || nf.endsWith("/" + f));
473
+ if (hit) {
474
+ const entry = byFile[hit] ??= [];
475
+ if (entry.length < MAX_ERRORS_PER_FILE) {
476
+ entry.push(`L${d.line} ${d.message}`);
477
+ }
478
+ } else if (useRepoWide) {
479
+ driftCount++;
480
+ const entry = driftByFile[nf] ??= [];
481
+ if (entry.length < MAX_ERRORS_PER_FILE) {
482
+ entry.push(`L${d.line} ${d.message}`);
483
+ }
484
+ }
485
+ }
486
+ const brokenFiles = Object.keys(byFile);
487
+ const driftFiles = Object.keys(driftByFile);
488
+ if (brokenFiles.length === 0 && driftFiles.length === 0) return { status: "clean", result: null };
489
+ const parts = [];
490
+ if (brokenFiles.length > 0) {
491
+ const shown = brokenFiles.slice(0, MAX_FILES);
492
+ const segs = shown.map((f) => {
493
+ const errs = byFile[f];
494
+ const more = errs.length >= MAX_ERRORS_PER_FILE ? " (+more)" : "";
495
+ return `${f}: ${errs.join("; ")}${more}`;
496
+ });
497
+ const overflow = brokenFiles.length > MAX_FILES ? ` (+${brokenFiles.length - MAX_FILES} more files)` : "";
498
+ parts.push(`Typecheck broken in changed files \u2014 ${segs.join(" | ")}${overflow}`);
499
+ }
500
+ let repoWide;
501
+ if (driftFiles.length > 0) {
502
+ const shown = driftFiles.slice(0, MAX_FILES);
503
+ const segs = shown.map((f) => {
504
+ const errs = driftByFile[f];
505
+ const more = errs.length >= MAX_ERRORS_PER_FILE ? " (+more)" : "";
506
+ return `${f}: ${errs.join("; ")}${more}`;
507
+ });
508
+ const overflow = driftFiles.length > MAX_FILES ? ` (+${driftFiles.length - MAX_FILES} more files)` : "";
509
+ const driftSummary = `cross-file \u7C7B\u578B\u6F02\u79FB\uFF08\u7591\u4F3C\u4F60\u6539\u7684\u5B9A\u4E49\u5F15\u53D1\u4E0B\u6E38\uFF09\u2014 ${segs.join(" | ")}${overflow}`;
510
+ parts.push(driftSummary);
511
+ repoWide = { byFile: driftByFile, count: driftCount, summary: driftSummary };
512
+ }
513
+ return { status: "errors", result: { brokenFiles, byFile, summary: parts.join(" || "), repoWide } };
514
+ }
515
+ var memoByCwd = /* @__PURE__ */ new Map();
516
+ function changedFilesSignature(cwd, tsFiles) {
517
+ if (tsFiles.length === 0) return null;
518
+ try {
519
+ return tsFiles.slice().sort().map((f) => {
520
+ const st = statSync(isAbsolute2(f) ? f : join2(cwd, f));
521
+ return `${f}:${st.mtimeMs}:${st.size}`;
522
+ }).join("|");
523
+ } catch {
524
+ return null;
525
+ }
526
+ }
527
+ async function runChangedFilesTypecheckOutcomeMemo(cwd, changedFiles, run = defaultRunner, baseline = loadTypecheckBaseline(cwd)) {
528
+ const tsFiles = changedFiles.filter((f) => !isAbsolute2(f) && /\.(ts|tsx)$/.test(f));
529
+ const sig = changedFilesSignature(cwd, tsFiles);
530
+ if (sig) {
531
+ const hit = memoByCwd.get(cwd);
532
+ if (hit && hit.sig === sig) return hit.outcome;
533
+ }
534
+ const outcome = await runChangedFilesTypecheckOutcome(cwd, changedFiles, run, baseline);
535
+ if (sig && outcome.status !== "inconclusive") memoByCwd.set(cwd, { sig, outcome });
536
+ return outcome;
537
+ }
538
+ async function runChangedFilesTypecheckMemo(cwd, changedFiles, run = defaultRunner, baseline = loadTypecheckBaseline(cwd)) {
539
+ const outcome = await runChangedFilesTypecheckOutcomeMemo(cwd, changedFiles, run, baseline);
540
+ return outcome.result;
541
+ }
542
+
543
+ // src/agent/wave-gate.ts
544
+ init_esm_shims();
545
+ import { existsSync as existsSync2 } from "fs";
546
+ import { resolve } from "path";
547
+ function isRunnableVerifyCommand(command) {
548
+ return parseVerifyCommand(command) !== null;
549
+ }
550
+ var gates = /* @__PURE__ */ new Map();
551
+ function key(sessionId) {
552
+ return sessionId ?? "__default__";
553
+ }
554
+ function setWaveGate(record, sessionId) {
555
+ gates.set(key(sessionId), record);
556
+ }
557
+ function getWaveGate(sessionId) {
558
+ return gates.get(key(sessionId));
559
+ }
560
+ function clearWaveGate(sessionId) {
561
+ gates.delete(key(sessionId));
562
+ }
563
+ function isWaveGateEnabled() {
564
+ return process.env.RIVET_WAVE_GATE !== "0";
565
+ }
566
+ function defaultRunCommand(cwd, command) {
567
+ const argv = parseVerifyCommand(command);
568
+ if (!argv) {
569
+ return Promise.resolve({ ok: false, detail: "\u975E\u767D\u540D\u5355\u9A8C\u8BC1\u547D\u4EE4\u5F62\u72B6\u2014\u2014\u62D2\u7EDD shell \u6267\u884C" });
570
+ }
571
+ return new Promise((resolvePromise) => {
572
+ let stdout = "";
573
+ let stderr = "";
574
+ let settled = false;
575
+ const tail = () => `${stdout}
576
+ ${stderr}`.trim().split("\n").slice(-5).join("\n").slice(0, 500);
577
+ const settle = (result) => {
578
+ if (settled) return;
579
+ settled = true;
580
+ resolvePromise(result);
581
+ };
582
+ try {
583
+ const child = spawnVerifyArgv(cwd, argv, { stdio: ["ignore", "pipe", "pipe"] });
584
+ child.stdout?.on("data", (d) => {
585
+ stdout += d.toString();
586
+ });
587
+ child.stderr?.on("data", (d) => {
588
+ stderr += d.toString();
589
+ });
590
+ const timer = setTimeout(() => {
591
+ try {
592
+ child.kill("SIGKILL");
593
+ } catch {
594
+ }
595
+ settle({ ok: false, detail: tail() });
596
+ }, 3e5);
597
+ child.on("close", (code) => {
598
+ clearTimeout(timer);
599
+ if (code === 0) settle({ ok: true });
600
+ else settle({ ok: false, detail: tail() });
601
+ });
602
+ child.on("error", (err) => {
603
+ clearTimeout(timer);
604
+ settle({ ok: false, detail: err.message });
605
+ });
606
+ } catch (err) {
607
+ settle({ ok: false, detail: err instanceof Error ? err.message : String(err) });
608
+ }
609
+ });
610
+ }
611
+ async function evaluateWaveGate(input) {
612
+ const checks = [];
613
+ if (typecheckGateEnabled() && input.changedFiles.length > 0) {
614
+ try {
615
+ const outcome = await runChangedFilesTypecheckOutcomeMemo(
616
+ input.cwd,
617
+ input.changedFiles,
618
+ input.typecheckRunner ?? gateTypecheckRunner
619
+ );
620
+ if (outcome.status === "errors") {
621
+ checks.push({ command: "tsc --noEmit (scoped)", status: "failed", detail: outcome.result.summary });
622
+ } else if (outcome.status === "inconclusive") {
623
+ checks.push({
624
+ command: "tsc --noEmit (scoped)",
625
+ status: "unverifiable",
626
+ detail: `${outcome.reason ?? "tsc did not complete"} \u2014 \u672A\u9A8C\u8BC1\u6309\u5931\u8D25\u62E6\u622A\uFF0C\u590D\u8BC4\u81EA\u52A8\u91CD\u8DD1`,
627
+ blocking: true
628
+ });
629
+ } else {
630
+ checks.push({ command: "tsc --noEmit (scoped)", status: "passed" });
631
+ }
632
+ } catch {
633
+ checks.push({ command: "tsc --noEmit (scoped)", status: "unverifiable", detail: "typecheck runner unavailable" });
634
+ }
635
+ }
636
+ if (testPresenceGateEnabled() && input.changedFiles.length > 0) {
637
+ const exists = input.fileExists ?? ((f) => existsSync2(resolve(input.cwd, f)));
638
+ const presentFiles = input.changedFiles.filter((f) => {
639
+ try {
640
+ return exists(f);
641
+ } catch {
642
+ return false;
643
+ }
644
+ });
645
+ const presence = evaluateTestPresence(presentFiles);
646
+ if (!presence.ok) {
647
+ checks.push({
648
+ command: "test-presence",
649
+ status: "unverifiable",
650
+ detail: presence.detail,
651
+ blocking: true
652
+ });
653
+ } else if (presence.sourceFiles.length > 0) {
654
+ checks.push({ command: "test-presence", status: "passed" });
655
+ }
656
+ }
657
+ const run = input.runCommand ?? defaultRunCommand;
658
+ for (const command of input.commands) {
659
+ if (!isRunnableVerifyCommand(command)) {
660
+ checks.push({ command, status: "unverifiable", detail: "\u975E\u767D\u540D\u5355\u9A8C\u8BC1\u547D\u4EE4\u5F62\u72B6\u2014\u2014\u8BF7\u4EBA\u5DE5\u6267\u884C\u786E\u8BA4" });
661
+ continue;
662
+ }
663
+ const res = await run(input.cwd, command);
664
+ checks.push({ command, status: res.ok ? "passed" : "failed", detail: res.detail });
665
+ }
666
+ return {
667
+ wave: input.wave,
668
+ passed: checks.every((c) => c.status !== "failed" && !(c.blocking && c.status !== "passed")),
669
+ checks,
670
+ changedFiles: input.changedFiles,
671
+ commands: input.commands,
672
+ checkedAt: Date.now()
673
+ };
674
+ }
675
+ function formatWaveGate(record) {
676
+ const lines = [`\u6CE2\u95F4\u95E8\u7981 (wave ${record.wave + 1}): ${record.passed ? "\u2705 \u901A\u8FC7" : "\u274C \u672A\u901A\u8FC7"}`];
677
+ for (const c of record.checks) {
678
+ const icon = c.status === "passed" ? "\u2705" : c.status === "failed" ? "\u274C" : "\u2753";
679
+ lines.push(` ${icon} ${c.command}${c.detail ? ` \u2014 ${c.detail}` : ""}`);
680
+ }
681
+ return lines;
682
+ }
683
+
684
+ export {
685
+ defaultWhich,
686
+ serverForFile,
687
+ languageIdForFile,
688
+ availableServers,
689
+ runTypeCheck,
690
+ shouldRunDiagnostics,
691
+ filterDiagnosticsForEdit,
692
+ parseVerifyCommand,
693
+ spawnVerifyArgv,
694
+ TYPECHECK_CMD_RE,
695
+ GATE_TSC_TIMEOUT_MS,
696
+ typecheckGateEnabled,
697
+ runChangedFilesTypecheckMemo,
698
+ isTestFilePath,
699
+ isSourceFilePath,
700
+ testPresenceGateEnabled,
701
+ evaluateTestPresence,
702
+ isRunnableVerifyCommand,
703
+ setWaveGate,
704
+ getWaveGate,
705
+ clearWaveGate,
706
+ isWaveGateEnabled,
707
+ evaluateWaveGate,
708
+ formatWaveGate
709
+ };