xtep-workspace 1.10.10

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 (418) hide show
  1. package/CHANGELOG.md +525 -0
  2. package/README.md +188 -0
  3. package/config/component-versions.json +16 -0
  4. package/config/scenarioCapabilities.json +29 -0
  5. package/config/version-notes.yaml +244 -0
  6. package/dist/adapters/OutputAdapter.d.ts +79 -0
  7. package/dist/adapters/OutputAdapter.d.ts.map +1 -0
  8. package/dist/adapters/OutputAdapter.js +124 -0
  9. package/dist/adapters/OutputAdapter.js.map +1 -0
  10. package/dist/cli/check-node-version.d.ts +3 -0
  11. package/dist/cli/check-node-version.d.ts.map +1 -0
  12. package/dist/cli/check-node-version.js +153 -0
  13. package/dist/cli/check-node-version.js.map +1 -0
  14. package/dist/cli/plugins.d.ts +41 -0
  15. package/dist/cli/plugins.d.ts.map +1 -0
  16. package/dist/cli/plugins.js +742 -0
  17. package/dist/cli/plugins.js.map +1 -0
  18. package/dist/cli/rebuild.d.ts +63 -0
  19. package/dist/cli/rebuild.d.ts.map +1 -0
  20. package/dist/cli/rebuild.js +989 -0
  21. package/dist/cli/rebuild.js.map +1 -0
  22. package/dist/cli/repair.d.ts +7 -0
  23. package/dist/cli/repair.d.ts.map +1 -0
  24. package/dist/cli/repair.js +925 -0
  25. package/dist/cli/repair.js.map +1 -0
  26. package/dist/cli/setup.d.ts +7 -0
  27. package/dist/cli/setup.d.ts.map +1 -0
  28. package/dist/cli/setup.js +452 -0
  29. package/dist/cli/setup.js.map +1 -0
  30. package/dist/cli/update.d.ts +10 -0
  31. package/dist/cli/update.d.ts.map +1 -0
  32. package/dist/cli/update.js +426 -0
  33. package/dist/cli/update.js.map +1 -0
  34. package/dist/cli/webui.d.ts +6 -0
  35. package/dist/cli/webui.d.ts.map +1 -0
  36. package/dist/cli/webui.js +210 -0
  37. package/dist/cli/webui.js.map +1 -0
  38. package/dist/http/index.d.ts +3 -0
  39. package/dist/http/index.d.ts.map +1 -0
  40. package/dist/http/index.js +15 -0
  41. package/dist/http/index.js.map +1 -0
  42. package/dist/http/middleware/errorHandler.d.ts +16 -0
  43. package/dist/http/middleware/errorHandler.d.ts.map +1 -0
  44. package/dist/http/middleware/errorHandler.js +79 -0
  45. package/dist/http/middleware/errorHandler.js.map +1 -0
  46. package/dist/http/routes/admin.d.ts +3 -0
  47. package/dist/http/routes/admin.d.ts.map +1 -0
  48. package/dist/http/routes/admin.js +730 -0
  49. package/dist/http/routes/admin.js.map +1 -0
  50. package/dist/http/routes/backup.d.ts +3 -0
  51. package/dist/http/routes/backup.d.ts.map +1 -0
  52. package/dist/http/routes/backup.js +172 -0
  53. package/dist/http/routes/backup.js.map +1 -0
  54. package/dist/http/routes/config.d.ts +3 -0
  55. package/dist/http/routes/config.d.ts.map +1 -0
  56. package/dist/http/routes/config.js +157 -0
  57. package/dist/http/routes/config.js.map +1 -0
  58. package/dist/http/routes/context.d.ts +3 -0
  59. package/dist/http/routes/context.d.ts.map +1 -0
  60. package/dist/http/routes/context.js +82 -0
  61. package/dist/http/routes/context.js.map +1 -0
  62. package/dist/http/routes/log.d.ts +3 -0
  63. package/dist/http/routes/log.d.ts.map +1 -0
  64. package/dist/http/routes/log.js +105 -0
  65. package/dist/http/routes/log.js.map +1 -0
  66. package/dist/http/routes/memo.d.ts +6 -0
  67. package/dist/http/routes/memo.d.ts.map +1 -0
  68. package/dist/http/routes/memo.js +29 -0
  69. package/dist/http/routes/memo.js.map +1 -0
  70. package/dist/http/routes/node.d.ts +3 -0
  71. package/dist/http/routes/node.d.ts.map +1 -0
  72. package/dist/http/routes/node.js +251 -0
  73. package/dist/http/routes/node.js.map +1 -0
  74. package/dist/http/routes/state.d.ts +3 -0
  75. package/dist/http/routes/state.d.ts.map +1 -0
  76. package/dist/http/routes/state.js +48 -0
  77. package/dist/http/routes/state.js.map +1 -0
  78. package/dist/http/routes/workspace.d.ts +3 -0
  79. package/dist/http/routes/workspace.d.ts.map +1 -0
  80. package/dist/http/routes/workspace.js +249 -0
  81. package/dist/http/routes/workspace.js.map +1 -0
  82. package/dist/http/server.d.ts +10 -0
  83. package/dist/http/server.d.ts.map +1 -0
  84. package/dist/http/server.js +284 -0
  85. package/dist/http/server.js.map +1 -0
  86. package/dist/http/services.d.ts +93 -0
  87. package/dist/http/services.d.ts.map +1 -0
  88. package/dist/http/services.js +297 -0
  89. package/dist/http/services.js.map +1 -0
  90. package/dist/index.d.ts +3 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +1073 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/prompts/guidanceContent.d.ts +18 -0
  95. package/dist/prompts/guidanceContent.d.ts.map +1 -0
  96. package/dist/prompts/guidanceContent.js +814 -0
  97. package/dist/prompts/guidanceContent.js.map +1 -0
  98. package/dist/prompts/index.d.ts +2 -0
  99. package/dist/prompts/index.d.ts.map +1 -0
  100. package/dist/prompts/index.js +4 -0
  101. package/dist/prompts/index.js.map +1 -0
  102. package/dist/prompts/instructions.d.ts +56 -0
  103. package/dist/prompts/instructions.d.ts.map +1 -0
  104. package/dist/prompts/instructions.js +1343 -0
  105. package/dist/prompts/instructions.js.map +1 -0
  106. package/dist/services/BackupService.d.ts +104 -0
  107. package/dist/services/BackupService.d.ts.map +1 -0
  108. package/dist/services/BackupService.js +549 -0
  109. package/dist/services/BackupService.js.map +1 -0
  110. package/dist/services/CapabilityService.d.ts +38 -0
  111. package/dist/services/CapabilityService.d.ts.map +1 -0
  112. package/dist/services/CapabilityService.js +256 -0
  113. package/dist/services/CapabilityService.js.map +1 -0
  114. package/dist/services/ConfigService.d.ts +35 -0
  115. package/dist/services/ConfigService.d.ts.map +1 -0
  116. package/dist/services/ConfigService.js +105 -0
  117. package/dist/services/ConfigService.js.map +1 -0
  118. package/dist/services/ContextService.d.ts +65 -0
  119. package/dist/services/ContextService.d.ts.map +1 -0
  120. package/dist/services/ContextService.js +503 -0
  121. package/dist/services/ContextService.js.map +1 -0
  122. package/dist/services/DetectionService.d.ts +76 -0
  123. package/dist/services/DetectionService.d.ts.map +1 -0
  124. package/dist/services/DetectionService.js +262 -0
  125. package/dist/services/DetectionService.js.map +1 -0
  126. package/dist/services/DispatchService.d.ts +267 -0
  127. package/dist/services/DispatchService.d.ts.map +1 -0
  128. package/dist/services/DispatchService.js +1357 -0
  129. package/dist/services/DispatchService.js.map +1 -0
  130. package/dist/services/EventService.d.ts +81 -0
  131. package/dist/services/EventService.d.ts.map +1 -0
  132. package/dist/services/EventService.js +187 -0
  133. package/dist/services/EventService.js.map +1 -0
  134. package/dist/services/GuidanceService.d.ts +64 -0
  135. package/dist/services/GuidanceService.d.ts.map +1 -0
  136. package/dist/services/GuidanceService.js +259 -0
  137. package/dist/services/GuidanceService.js.map +1 -0
  138. package/dist/services/HealthService.d.ts +43 -0
  139. package/dist/services/HealthService.d.ts.map +1 -0
  140. package/dist/services/HealthService.js +276 -0
  141. package/dist/services/HealthService.js.map +1 -0
  142. package/dist/services/InstallationService.d.ts +62 -0
  143. package/dist/services/InstallationService.d.ts.map +1 -0
  144. package/dist/services/InstallationService.js +204 -0
  145. package/dist/services/InstallationService.js.map +1 -0
  146. package/dist/services/LogService.d.ts +35 -0
  147. package/dist/services/LogService.d.ts.map +1 -0
  148. package/dist/services/LogService.js +189 -0
  149. package/dist/services/LogService.js.map +1 -0
  150. package/dist/services/MemoService.d.ts +39 -0
  151. package/dist/services/MemoService.d.ts.map +1 -0
  152. package/dist/services/MemoService.js +288 -0
  153. package/dist/services/MemoService.js.map +1 -0
  154. package/dist/services/NodeService.d.ts +90 -0
  155. package/dist/services/NodeService.d.ts.map +1 -0
  156. package/dist/services/NodeService.js +958 -0
  157. package/dist/services/NodeService.js.map +1 -0
  158. package/dist/services/OpenSpecParser.d.ts +43 -0
  159. package/dist/services/OpenSpecParser.d.ts.map +1 -0
  160. package/dist/services/OpenSpecParser.js +191 -0
  161. package/dist/services/OpenSpecParser.js.map +1 -0
  162. package/dist/services/ReferenceService.d.ts +35 -0
  163. package/dist/services/ReferenceService.d.ts.map +1 -0
  164. package/dist/services/ReferenceService.js +195 -0
  165. package/dist/services/ReferenceService.js.map +1 -0
  166. package/dist/services/RepairService.d.ts +36 -0
  167. package/dist/services/RepairService.d.ts.map +1 -0
  168. package/dist/services/RepairService.js +429 -0
  169. package/dist/services/RepairService.js.map +1 -0
  170. package/dist/services/SearchService.d.ts +34 -0
  171. package/dist/services/SearchService.d.ts.map +1 -0
  172. package/dist/services/SearchService.js +293 -0
  173. package/dist/services/SearchService.js.map +1 -0
  174. package/dist/services/SessionService.d.ts +136 -0
  175. package/dist/services/SessionService.d.ts.map +1 -0
  176. package/dist/services/SessionService.js +297 -0
  177. package/dist/services/SessionService.js.map +1 -0
  178. package/dist/services/StateService.d.ts +97 -0
  179. package/dist/services/StateService.d.ts.map +1 -0
  180. package/dist/services/StateService.js +846 -0
  181. package/dist/services/StateService.js.map +1 -0
  182. package/dist/services/TutorialService.d.ts +114 -0
  183. package/dist/services/TutorialService.d.ts.map +1 -0
  184. package/dist/services/TutorialService.js +1262 -0
  185. package/dist/services/TutorialService.js.map +1 -0
  186. package/dist/services/WorkspaceService.d.ts +273 -0
  187. package/dist/services/WorkspaceService.d.ts.map +1 -0
  188. package/dist/services/WorkspaceService.js +1764 -0
  189. package/dist/services/WorkspaceService.js.map +1 -0
  190. package/dist/services/index.d.ts +15 -0
  191. package/dist/services/index.d.ts.map +1 -0
  192. package/dist/services/index.js +14 -0
  193. package/dist/services/index.js.map +1 -0
  194. package/dist/storage/FileSystemAdapter.d.ts +223 -0
  195. package/dist/storage/FileSystemAdapter.d.ts.map +1 -0
  196. package/dist/storage/FileSystemAdapter.js +384 -0
  197. package/dist/storage/FileSystemAdapter.js.map +1 -0
  198. package/dist/storage/JsonStorage.d.ts +158 -0
  199. package/dist/storage/JsonStorage.d.ts.map +1 -0
  200. package/dist/storage/JsonStorage.js +613 -0
  201. package/dist/storage/JsonStorage.js.map +1 -0
  202. package/dist/storage/MarkdownStorage.d.ts +178 -0
  203. package/dist/storage/MarkdownStorage.d.ts.map +1 -0
  204. package/dist/storage/MarkdownStorage.js +918 -0
  205. package/dist/storage/MarkdownStorage.js.map +1 -0
  206. package/dist/storage/SessionBindingStorage.d.ts +69 -0
  207. package/dist/storage/SessionBindingStorage.d.ts.map +1 -0
  208. package/dist/storage/SessionBindingStorage.js +131 -0
  209. package/dist/storage/SessionBindingStorage.js.map +1 -0
  210. package/dist/storage/index.d.ts +6 -0
  211. package/dist/storage/index.d.ts.map +1 -0
  212. package/dist/storage/index.js +6 -0
  213. package/dist/storage/index.js.map +1 -0
  214. package/dist/tools/capability.d.ts +18 -0
  215. package/dist/tools/capability.d.ts.map +1 -0
  216. package/dist/tools/capability.js +73 -0
  217. package/dist/tools/capability.js.map +1 -0
  218. package/dist/tools/config.d.ts +14 -0
  219. package/dist/tools/config.d.ts.map +1 -0
  220. package/dist/tools/config.js +61 -0
  221. package/dist/tools/config.js.map +1 -0
  222. package/dist/tools/context.d.ts +22 -0
  223. package/dist/tools/context.d.ts.map +1 -0
  224. package/dist/tools/context.js +139 -0
  225. package/dist/tools/context.js.map +1 -0
  226. package/dist/tools/dispatch.d.ts +41 -0
  227. package/dist/tools/dispatch.d.ts.map +1 -0
  228. package/dist/tools/dispatch.js +380 -0
  229. package/dist/tools/dispatch.js.map +1 -0
  230. package/dist/tools/help.d.ts +44 -0
  231. package/dist/tools/help.d.ts.map +1 -0
  232. package/dist/tools/help.js +227 -0
  233. package/dist/tools/help.js.map +1 -0
  234. package/dist/tools/import.d.ts +17 -0
  235. package/dist/tools/import.d.ts.map +1 -0
  236. package/dist/tools/import.js +96 -0
  237. package/dist/tools/import.js.map +1 -0
  238. package/dist/tools/index.d.ts +12 -0
  239. package/dist/tools/index.d.ts.map +1 -0
  240. package/dist/tools/index.js +13 -0
  241. package/dist/tools/index.js.map +1 -0
  242. package/dist/tools/log.d.ts +21 -0
  243. package/dist/tools/log.d.ts.map +1 -0
  244. package/dist/tools/log.js +93 -0
  245. package/dist/tools/log.js.map +1 -0
  246. package/dist/tools/memo.d.ts +26 -0
  247. package/dist/tools/memo.d.ts.map +1 -0
  248. package/dist/tools/memo.js +188 -0
  249. package/dist/tools/memo.js.map +1 -0
  250. package/dist/tools/node.d.ts +34 -0
  251. package/dist/tools/node.d.ts.map +1 -0
  252. package/dist/tools/node.js +328 -0
  253. package/dist/tools/node.js.map +1 -0
  254. package/dist/tools/search.d.ts +14 -0
  255. package/dist/tools/search.d.ts.map +1 -0
  256. package/dist/tools/search.js +95 -0
  257. package/dist/tools/search.js.map +1 -0
  258. package/dist/tools/session.d.ts +22 -0
  259. package/dist/tools/session.d.ts.map +1 -0
  260. package/dist/tools/session.js +127 -0
  261. package/dist/tools/session.js.map +1 -0
  262. package/dist/tools/state.d.ts +10 -0
  263. package/dist/tools/state.d.ts.map +1 -0
  264. package/dist/tools/state.js +79 -0
  265. package/dist/tools/state.js.map +1 -0
  266. package/dist/tools/workspace.d.ts +38 -0
  267. package/dist/tools/workspace.d.ts.map +1 -0
  268. package/dist/tools/workspace.js +240 -0
  269. package/dist/tools/workspace.js.map +1 -0
  270. package/dist/types/capability.d.ts +36 -0
  271. package/dist/types/capability.d.ts.map +1 -0
  272. package/dist/types/capability.js +3 -0
  273. package/dist/types/capability.js.map +1 -0
  274. package/dist/types/confirmation.d.ts +35 -0
  275. package/dist/types/confirmation.d.ts.map +1 -0
  276. package/dist/types/confirmation.js +3 -0
  277. package/dist/types/confirmation.js.map +1 -0
  278. package/dist/types/context.d.ts +174 -0
  279. package/dist/types/context.d.ts.map +1 -0
  280. package/dist/types/context.js +3 -0
  281. package/dist/types/context.js.map +1 -0
  282. package/dist/types/errors.d.ts +81 -0
  283. package/dist/types/errors.d.ts.map +1 -0
  284. package/dist/types/errors.js +154 -0
  285. package/dist/types/errors.js.map +1 -0
  286. package/dist/types/guidance.d.ts +162 -0
  287. package/dist/types/guidance.d.ts.map +1 -0
  288. package/dist/types/guidance.js +4 -0
  289. package/dist/types/guidance.js.map +1 -0
  290. package/dist/types/health.d.ts +61 -0
  291. package/dist/types/health.d.ts.map +1 -0
  292. package/dist/types/health.js +3 -0
  293. package/dist/types/health.js.map +1 -0
  294. package/dist/types/index.d.ts +10 -0
  295. package/dist/types/index.d.ts.map +1 -0
  296. package/dist/types/index.js +11 -0
  297. package/dist/types/index.js.map +1 -0
  298. package/dist/types/memo.d.ts +132 -0
  299. package/dist/types/memo.d.ts.map +1 -0
  300. package/dist/types/memo.js +3 -0
  301. package/dist/types/memo.js.map +1 -0
  302. package/dist/types/node.d.ts +316 -0
  303. package/dist/types/node.d.ts.map +1 -0
  304. package/dist/types/node.js +3 -0
  305. package/dist/types/node.js.map +1 -0
  306. package/dist/types/repair.d.ts +62 -0
  307. package/dist/types/repair.d.ts.map +1 -0
  308. package/dist/types/repair.js +4 -0
  309. package/dist/types/repair.js.map +1 -0
  310. package/dist/types/search.d.ts +58 -0
  311. package/dist/types/search.d.ts.map +1 -0
  312. package/dist/types/search.js +3 -0
  313. package/dist/types/search.js.map +1 -0
  314. package/dist/types/settings.d.ts +109 -0
  315. package/dist/types/settings.d.ts.map +1 -0
  316. package/dist/types/settings.js +30 -0
  317. package/dist/types/settings.js.map +1 -0
  318. package/dist/types/workspace.d.ts +357 -0
  319. package/dist/types/workspace.d.ts.map +1 -0
  320. package/dist/types/workspace.js +3 -0
  321. package/dist/types/workspace.js.map +1 -0
  322. package/dist/utils/contentValidation.d.ts +47 -0
  323. package/dist/utils/contentValidation.d.ts.map +1 -0
  324. package/dist/utils/contentValidation.js +93 -0
  325. package/dist/utils/contentValidation.js.map +1 -0
  326. package/dist/utils/devLog.d.ts +43 -0
  327. package/dist/utils/devLog.d.ts.map +1 -0
  328. package/dist/utils/devLog.js +94 -0
  329. package/dist/utils/devLog.js.map +1 -0
  330. package/dist/utils/errorLogger.d.ts +27 -0
  331. package/dist/utils/errorLogger.d.ts.map +1 -0
  332. package/dist/utils/errorLogger.js +105 -0
  333. package/dist/utils/errorLogger.js.map +1 -0
  334. package/dist/utils/git.d.ts +123 -0
  335. package/dist/utils/git.d.ts.map +1 -0
  336. package/dist/utils/git.js +400 -0
  337. package/dist/utils/git.js.map +1 -0
  338. package/dist/utils/hash.d.ts +32 -0
  339. package/dist/utils/hash.d.ts.map +1 -0
  340. package/dist/utils/hash.js +37 -0
  341. package/dist/utils/hash.js.map +1 -0
  342. package/dist/utils/id.d.ts +54 -0
  343. package/dist/utils/id.d.ts.map +1 -0
  344. package/dist/utils/id.js +96 -0
  345. package/dist/utils/id.js.map +1 -0
  346. package/dist/utils/index.d.ts +8 -0
  347. package/dist/utils/index.d.ts.map +1 -0
  348. package/dist/utils/index.js +9 -0
  349. package/dist/utils/index.js.map +1 -0
  350. package/dist/utils/logger.d.ts +42 -0
  351. package/dist/utils/logger.d.ts.map +1 -0
  352. package/dist/utils/logger.js +228 -0
  353. package/dist/utils/logger.js.map +1 -0
  354. package/dist/utils/manualChangeFormatter.d.ts +8 -0
  355. package/dist/utils/manualChangeFormatter.d.ts.map +1 -0
  356. package/dist/utils/manualChangeFormatter.js +21 -0
  357. package/dist/utils/manualChangeFormatter.js.map +1 -0
  358. package/dist/utils/paramValidator.d.ts +35 -0
  359. package/dist/utils/paramValidator.d.ts.map +1 -0
  360. package/dist/utils/paramValidator.js +214 -0
  361. package/dist/utils/paramValidator.js.map +1 -0
  362. package/dist/utils/port.d.ts +7 -0
  363. package/dist/utils/port.d.ts.map +1 -0
  364. package/dist/utils/port.js +28 -0
  365. package/dist/utils/port.js.map +1 -0
  366. package/dist/utils/processManager.d.ts +53 -0
  367. package/dist/utils/processManager.d.ts.map +1 -0
  368. package/dist/utils/processManager.js +267 -0
  369. package/dist/utils/processManager.js.map +1 -0
  370. package/dist/utils/sessionLogger.d.ts +28 -0
  371. package/dist/utils/sessionLogger.d.ts.map +1 -0
  372. package/dist/utils/sessionLogger.js +142 -0
  373. package/dist/utils/sessionLogger.js.map +1 -0
  374. package/dist/utils/time.d.ts +15 -0
  375. package/dist/utils/time.d.ts.map +1 -0
  376. package/dist/utils/time.js +32 -0
  377. package/dist/utils/time.js.map +1 -0
  378. package/dist/utils/validation.d.ts +23 -0
  379. package/dist/utils/validation.d.ts.map +1 -0
  380. package/dist/utils/validation.js +88 -0
  381. package/dist/utils/validation.js.map +1 -0
  382. package/docs//346/227/245/345/277/227/347/263/273/347/273/237.md +389 -0
  383. package/docs//347/224/250/346/210/267/346/211/213/345/206/214.md +1446 -0
  384. package/docs//347/224/250/346/210/267/346/211/213/345/206/214/344/270/216/346/212/200/346/234/257/346/214/207/345/215/227.md +873 -0
  385. package/package.json +89 -0
  386. package/plugin/README.md +141 -0
  387. package/plugin/agents/xtep-executor.md +114 -0
  388. package/plugin/agents/xtep-reviewer.md +133 -0
  389. package/plugin/docs/diagnostic-guide.md +128 -0
  390. package/plugin/hooks/hooks.json.deprecated +70 -0
  391. package/plugin/scripts/cursor-hook-entry.cjs +217 -0
  392. package/plugin/scripts/hook-entry.cjs +663 -0
  393. package/plugin/scripts/openspec-import.cjs +714 -0
  394. package/plugin/scripts/shared/binding.cjs +98 -0
  395. package/plugin/scripts/shared/config.cjs +65 -0
  396. package/plugin/scripts/shared/context.cjs +120 -0
  397. package/plugin/scripts/shared/index.cjs +34 -0
  398. package/plugin/scripts/shared/logger.cjs +196 -0
  399. package/plugin/scripts/shared/reminder.cjs +261 -0
  400. package/plugin/scripts/shared/utils.cjs +62 -0
  401. package/plugin/scripts/shared/workspace.cjs +322 -0
  402. package/plugin/skills/aligning-intent/SKILL.md +275 -0
  403. package/plugin/skills/analyzing-measurements/SKILL.md +223 -0
  404. package/plugin/skills/bootstrapping-workspace/SKILL.md +260 -0
  405. package/plugin/skills/designing-solutions/SKILL.md +363 -0
  406. package/plugin/skills/diagnosing-issues/SKILL.md +219 -0
  407. package/plugin/skills/discovering-context/SKILL.md +283 -0
  408. package/plugin/skills/dispatching-parent/SKILL.md +399 -0
  409. package/plugin/skills/executing-task/SKILL.md +340 -0
  410. package/plugin/skills/memo-create/SKILL.md +222 -0
  411. package/plugin/skills/planning-verification/SKILL.md +245 -0
  412. package/plugin/skills/preparing-dispatch/SKILL.md +299 -0
  413. package/plugin/skills/researching-tech/SKILL.md +223 -0
  414. package/plugin/skills/reviewing-quality/SKILL.md +354 -0
  415. package/plugin/skills/reviewing-spec/SKILL.md +333 -0
  416. package/plugin/skills/starting-info-flow/SKILL.md +196 -0
  417. package/web/README.md +5 -0
  418. package//351/205/215/347/275/256/346/226/271/345/274/217.md +330 -0
@@ -0,0 +1,925 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * xtep-workspace repair 命令
4
+ * 单个工作区修复工具:诊断问题、自动修复、交互式修复
5
+ */
6
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, statSync, } from "fs";
7
+ import { homedir } from "os";
8
+ import { join, dirname, basename, resolve } from "path";
9
+ import { fileURLToPath } from "url";
10
+ import { createInterface } from "readline";
11
+ // ES module 兼容
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = dirname(__filename);
14
+ // ============================================================================
15
+ // 配置
16
+ // ============================================================================
17
+ const IS_DEV = process.env.NODE_ENV === "development" || process.env.XTEP_DEV === "true";
18
+ const HOME = homedir();
19
+ const FOLDER_NAME = IS_DEV ? ".xtep-workspace-dev" : ".xtep-workspace";
20
+ const GLOBAL_DIR = join(HOME, FOLDER_NAME);
21
+ const INDEX_PATH = join(GLOBAL_DIR, "index.json");
22
+ // 当前存储版本
23
+ const STORAGE_VERSION = "5.0";
24
+ // ============================================================================
25
+ // 颜色输出
26
+ // ============================================================================
27
+ const colors = {
28
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
29
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
30
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
31
+ blue: (s) => `\x1b[34m${s}\x1b[0m`,
32
+ cyan: (s) => `\x1b[36m${s}\x1b[0m`,
33
+ gray: (s) => `\x1b[90m${s}\x1b[0m`,
34
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
35
+ };
36
+ function info(msg) {
37
+ console.log(`${colors.blue("ℹ")} ${msg}`);
38
+ }
39
+ function success(msg) {
40
+ console.log(`${colors.green("✓")} ${msg}`);
41
+ }
42
+ function warn(msg) {
43
+ console.log(`${colors.yellow("⚠")} ${msg}`);
44
+ }
45
+ function error(msg) {
46
+ console.log(`${colors.red("✗")} ${msg}`);
47
+ }
48
+ function hint(msg) {
49
+ console.log(` ${colors.gray(msg)}`);
50
+ }
51
+ // ============================================================================
52
+ // 工具函数
53
+ // ============================================================================
54
+ function readIndex() {
55
+ if (!existsSync(INDEX_PATH))
56
+ return null;
57
+ try {
58
+ return JSON.parse(readFileSync(INDEX_PATH, "utf-8"));
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
64
+ function writeIndex(index) {
65
+ mkdirSync(dirname(INDEX_PATH), { recursive: true });
66
+ writeFileSync(INDEX_PATH, JSON.stringify(index, null, 2));
67
+ }
68
+ function readJson(path) {
69
+ if (!existsSync(path))
70
+ return null;
71
+ try {
72
+ return JSON.parse(readFileSync(path, "utf-8"));
73
+ }
74
+ catch {
75
+ return null;
76
+ }
77
+ }
78
+ function writeJson(path, data) {
79
+ writeFileSync(path, JSON.stringify(data, null, 2));
80
+ }
81
+ function extractShortId(id) {
82
+ const match = id.match(/^(?:ws-|node-|memo-)?([a-z0-9]+)-([a-z0-9]+)$/);
83
+ return match ? match[1] : id.slice(-8);
84
+ }
85
+ // 创建备份
86
+ function createBackup(filePath) {
87
+ if (!existsSync(filePath))
88
+ return null;
89
+ const dir = dirname(filePath);
90
+ const name = basename(filePath, ".json");
91
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
92
+ const backupName = `${name}.backup.${timestamp}.json`;
93
+ const backupPath = join(dir, backupName);
94
+ try {
95
+ const content = readFileSync(filePath, "utf-8");
96
+ writeFileSync(backupPath, content);
97
+ return backupName;
98
+ }
99
+ catch {
100
+ return null;
101
+ }
102
+ }
103
+ // 交互式输入
104
+ async function prompt(rl, question) {
105
+ return new Promise((resolve) => {
106
+ rl.question(question, (answer) => {
107
+ resolve(answer.trim());
108
+ });
109
+ });
110
+ }
111
+ // 交互式确认
112
+ async function confirm(rl, question) {
113
+ const answer = await prompt(rl, `${question} (y/N): `);
114
+ return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
115
+ }
116
+ /**
117
+ * 解析工作区路径,支持多种输入格式:
118
+ * 1. 完整工作区路径: /project/.xtep-workspace/工作区名_xxx/
119
+ * 2. 项目目录 + 工作区目录名: /project 工作区名_xxx
120
+ * 3. 工作区 ID: ws-xxx-yyy
121
+ */
122
+ function resolveWorkspacePath(input) {
123
+ const resolvedPath = resolve(input);
124
+ // 情况 1: 直接是工作区目录
125
+ if (existsSync(resolvedPath)) {
126
+ const stat = statSync(resolvedPath);
127
+ if (stat.isDirectory()) {
128
+ // 检查是否包含 workspace.json
129
+ const configPath = join(resolvedPath, "workspace.json");
130
+ if (existsSync(configPath)) {
131
+ const wsPath = resolvedPath;
132
+ const wsDirName = basename(wsPath);
133
+ const wsDir = dirname(wsPath);
134
+ const projectRoot = dirname(wsDir);
135
+ // 尝试从 index 中找对应条目
136
+ const index = readIndex();
137
+ // 先尝试通过 dirName 或目录名匹配
138
+ let indexEntry = index?.workspaces.find(w => w.dirName === wsDirName || w.id === wsDirName);
139
+ // 如果没找到,读取 workspace.json 中的 id 再尝试匹配
140
+ if (!indexEntry) {
141
+ const config = readJson(configPath);
142
+ if (config?.id) {
143
+ indexEntry = index?.workspaces.find(w => w.id === config.id);
144
+ }
145
+ }
146
+ return { projectRoot, wsDir, wsDirName, wsPath, indexEntry };
147
+ }
148
+ // 检查是否是项目目录(包含 .xtep-workspace)
149
+ const twDir = join(resolvedPath, FOLDER_NAME);
150
+ if (existsSync(twDir)) {
151
+ // 需要用户指定具体工作区
152
+ error(`请指定具体的工作区目录`);
153
+ hint(`示例: xtep-workspace repair "${twDir}/工作区名_xxx"`);
154
+ // 列出可用工作区
155
+ try {
156
+ const entries = readdirSync(twDir, { withFileTypes: true });
157
+ const workspaces = entries.filter(e => e.isDirectory() && existsSync(join(twDir, e.name, "workspace.json")));
158
+ if (workspaces.length > 0) {
159
+ console.log(`\n可用工作区:`);
160
+ workspaces.forEach(w => {
161
+ console.log(` - ${w.name}`);
162
+ });
163
+ }
164
+ }
165
+ catch { /* ignore */ }
166
+ return null;
167
+ }
168
+ }
169
+ }
170
+ // 情况 2: 通过工作区 ID 查找
171
+ if (input.startsWith("ws-")) {
172
+ const index = readIndex();
173
+ if (index) {
174
+ const entry = index.workspaces.find(w => w.id === input);
175
+ if (entry && entry.dirName) {
176
+ const wsDir = join(entry.projectRoot, FOLDER_NAME);
177
+ const wsPath = join(wsDir, entry.dirName);
178
+ return {
179
+ projectRoot: entry.projectRoot,
180
+ wsDir,
181
+ wsDirName: entry.dirName,
182
+ wsPath,
183
+ indexEntry: entry,
184
+ };
185
+ }
186
+ }
187
+ }
188
+ error(`无法定位工作区: ${input}`);
189
+ hint(`请提供工作区目录的完整路径`);
190
+ return null;
191
+ }
192
+ // ============================================================================
193
+ // 问题诊断
194
+ // ============================================================================
195
+ async function diagnoseWorkspace(location) {
196
+ const issues = [];
197
+ const { projectRoot, wsDir, wsDirName, wsPath, indexEntry } = location;
198
+ // ========== 1. Index 相关问题 ==========
199
+ const index = readIndex();
200
+ // 1.1 工作区未在 index 中注册
201
+ if (!indexEntry) {
202
+ const config = readJson(join(wsPath, "workspace.json"));
203
+ if (config) {
204
+ issues.push({
205
+ id: "not-in-index",
206
+ severity: "warning",
207
+ message: "工作区未在全局索引中注册",
208
+ detail: "工作区可能是手动创建或从其他地方复制的",
209
+ autoFix: async () => {
210
+ if (!index)
211
+ return false;
212
+ const newEntry = {
213
+ id: config.id,
214
+ name: config.name,
215
+ dirName: wsDirName,
216
+ projectRoot,
217
+ status: config.status || "active",
218
+ createdAt: new Date().toISOString(),
219
+ updatedAt: new Date().toISOString(),
220
+ };
221
+ index.workspaces.push(newEntry);
222
+ writeIndex(index);
223
+ return true;
224
+ },
225
+ });
226
+ }
227
+ }
228
+ else {
229
+ // 1.2 index 中 dirName 缺失
230
+ if (!indexEntry.dirName) {
231
+ issues.push({
232
+ id: "index-missing-dirname",
233
+ severity: "error",
234
+ message: "索引条目缺少 dirName 字段",
235
+ autoFix: async () => {
236
+ if (!index)
237
+ return false;
238
+ const entry = index.workspaces.find(w => w.id === indexEntry.id);
239
+ if (entry) {
240
+ entry.dirName = wsDirName;
241
+ writeIndex(index);
242
+ return true;
243
+ }
244
+ return false;
245
+ },
246
+ });
247
+ }
248
+ // 1.3 index 中 dirName 与实际不匹配
249
+ if (indexEntry.dirName && indexEntry.dirName !== wsDirName) {
250
+ issues.push({
251
+ id: "index-dirname-mismatch",
252
+ severity: "error",
253
+ message: `索引中的 dirName 与实际目录名不匹配`,
254
+ detail: `索引: ${indexEntry.dirName}, 实际: ${wsDirName}`,
255
+ autoFix: async () => {
256
+ if (!index)
257
+ return false;
258
+ const entry = index.workspaces.find(w => w.id === indexEntry.id);
259
+ if (entry) {
260
+ entry.dirName = wsDirName;
261
+ writeIndex(index);
262
+ return true;
263
+ }
264
+ return false;
265
+ },
266
+ });
267
+ }
268
+ // 1.4 index 中 projectRoot 与实际不匹配
269
+ if (indexEntry.projectRoot !== projectRoot) {
270
+ issues.push({
271
+ id: "index-projectroot-mismatch",
272
+ severity: "error",
273
+ message: `索引中的 projectRoot 与实际路径不匹配`,
274
+ detail: `索引: ${indexEntry.projectRoot}, 实际: ${projectRoot}`,
275
+ autoFix: async () => {
276
+ if (!index)
277
+ return false;
278
+ const entry = index.workspaces.find(w => w.id === indexEntry.id);
279
+ if (entry) {
280
+ entry.projectRoot = projectRoot;
281
+ writeIndex(index);
282
+ return true;
283
+ }
284
+ return false;
285
+ },
286
+ });
287
+ }
288
+ }
289
+ // ========== 2. workspace.json 问题 ==========
290
+ const configPath = join(wsPath, "workspace.json");
291
+ if (!existsSync(configPath)) {
292
+ issues.push({
293
+ id: "missing-workspace-json",
294
+ severity: "error",
295
+ message: "workspace.json 文件缺失",
296
+ interactiveFix: async (rl) => {
297
+ console.log(`\n需要创建 workspace.json,请提供以下信息:`);
298
+ const id = indexEntry?.id || await prompt(rl, "工作区 ID (如 ws-xxx-yyy): ");
299
+ const name = indexEntry?.name || await prompt(rl, "工作区名称: ");
300
+ if (!id || !name) {
301
+ error("ID 和名称不能为空");
302
+ return false;
303
+ }
304
+ const config = {
305
+ id,
306
+ name,
307
+ dirName: wsDirName,
308
+ status: "active",
309
+ rootNodeId: "root",
310
+ };
311
+ writeJson(configPath, config);
312
+ return true;
313
+ },
314
+ });
315
+ }
316
+ else {
317
+ const config = readJson(configPath);
318
+ if (!config) {
319
+ issues.push({
320
+ id: "invalid-workspace-json",
321
+ severity: "error",
322
+ message: "workspace.json 格式无效 (JSON 解析失败)",
323
+ detail: `文件路径: ${configPath}`,
324
+ interactiveFix: async (rl) => {
325
+ console.log(`\nworkspace.json 文件损坏,无法解析 JSON。`);
326
+ console.log(`\n可选操作:`);
327
+ console.log(` 1. 查看文件内容(前 10 行)`);
328
+ console.log(` 2. 备份并重建 workspace.json`);
329
+ console.log(` 3. 跳过`);
330
+ const choice = await prompt(rl, "请选择 (1/2/3): ");
331
+ if (choice === "1") {
332
+ try {
333
+ const content = readFileSync(configPath, "utf-8");
334
+ const lines = content.split("\n").slice(0, 10);
335
+ console.log(`\n--- 文件内容 (前 10 行) ---`);
336
+ lines.forEach((line, i) => console.log(`${i + 1}: ${line}`));
337
+ console.log(`--- 结束 ---\n`);
338
+ console.log(`请手动编辑文件修复 JSON 格式错误后重新运行 repair`);
339
+ }
340
+ catch (e) {
341
+ error(`读取文件失败: ${e instanceof Error ? e.message : e}`);
342
+ }
343
+ return false;
344
+ }
345
+ if (choice === "2") {
346
+ // 备份损坏的文件
347
+ const backupName = createBackup(configPath);
348
+ if (backupName) {
349
+ info(`已备份损坏文件: ${backupName}`);
350
+ }
351
+ // 从 index 获取信息
352
+ const id = indexEntry?.id || await prompt(rl, "工作区 ID (如 ws-xxx-yyy): ");
353
+ const name = indexEntry?.name || await prompt(rl, "工作区名称: ");
354
+ if (!id || !name) {
355
+ error("ID 和名称不能为空");
356
+ return false;
357
+ }
358
+ const newConfig = {
359
+ id,
360
+ name,
361
+ dirName: wsDirName,
362
+ status: "active",
363
+ rootNodeId: "root",
364
+ };
365
+ writeJson(configPath, newConfig);
366
+ success(`已重建 workspace.json`);
367
+ return true;
368
+ }
369
+ return false;
370
+ },
371
+ });
372
+ }
373
+ else {
374
+ // 2.1 缺少 dirName
375
+ if (!config.dirName) {
376
+ issues.push({
377
+ id: "config-missing-dirname",
378
+ severity: "warning",
379
+ message: "workspace.json 缺少 dirName 字段",
380
+ autoFix: async () => {
381
+ config.dirName = wsDirName;
382
+ writeJson(configPath, config);
383
+ return true;
384
+ },
385
+ });
386
+ }
387
+ // 2.2 dirName 不匹配
388
+ if (config.dirName && config.dirName !== wsDirName) {
389
+ issues.push({
390
+ id: "config-dirname-mismatch",
391
+ severity: "warning",
392
+ message: "workspace.json 中的 dirName 与实际目录名不匹配",
393
+ detail: `配置: ${config.dirName}, 实际: ${wsDirName}`,
394
+ autoFix: async () => {
395
+ config.dirName = wsDirName;
396
+ writeJson(configPath, config);
397
+ return true;
398
+ },
399
+ });
400
+ }
401
+ // 2.3 缺少必要字段
402
+ if (!config.id) {
403
+ issues.push({
404
+ id: "config-missing-id",
405
+ severity: "error",
406
+ message: "workspace.json 缺少 id 字段",
407
+ interactiveFix: async (rl) => {
408
+ const id = await prompt(rl, "请输入工作区 ID (如 ws-xxx-yyy): ");
409
+ if (!id)
410
+ return false;
411
+ config.id = id;
412
+ writeJson(configPath, config);
413
+ return true;
414
+ },
415
+ });
416
+ }
417
+ if (!config.name) {
418
+ issues.push({
419
+ id: "config-missing-name",
420
+ severity: "error",
421
+ message: "workspace.json 缺少 name 字段",
422
+ interactiveFix: async (rl) => {
423
+ const name = await prompt(rl, "请输入工作区名称: ");
424
+ if (!name)
425
+ return false;
426
+ config.name = name;
427
+ writeJson(configPath, config);
428
+ return true;
429
+ },
430
+ });
431
+ }
432
+ }
433
+ }
434
+ // ========== 3. graph.json 问题 ==========
435
+ const graphPath = join(wsPath, "graph.json");
436
+ if (!existsSync(graphPath)) {
437
+ issues.push({
438
+ id: "missing-graph-json",
439
+ severity: "error",
440
+ message: "graph.json 文件缺失",
441
+ autoFix: async () => {
442
+ // 创建基本的 graph.json
443
+ const graph = {
444
+ version: STORAGE_VERSION,
445
+ currentFocus: "root",
446
+ nodes: {
447
+ root: {
448
+ id: "root",
449
+ dirName: "root",
450
+ status: "planning",
451
+ parentId: null,
452
+ children: [],
453
+ },
454
+ },
455
+ };
456
+ writeJson(graphPath, graph);
457
+ // 创建 root 节点目录
458
+ const rootDir = join(wsPath, "nodes", "root");
459
+ mkdirSync(rootDir, { recursive: true });
460
+ writeFileSync(join(rootDir, "Info.md"), `---
461
+ id: root
462
+ type: planning
463
+ title: 根节点
464
+ status: planning
465
+ ---
466
+
467
+ ## 需求
468
+
469
+ (待填写)
470
+ `);
471
+ return true;
472
+ },
473
+ });
474
+ }
475
+ else {
476
+ const graph = readJson(graphPath);
477
+ if (!graph) {
478
+ issues.push({
479
+ id: "invalid-graph-json",
480
+ severity: "error",
481
+ message: "graph.json 格式无效 (JSON 解析失败)",
482
+ detail: `文件路径: ${graphPath}`,
483
+ interactiveFix: async (rl) => {
484
+ console.log(`\ngraph.json 文件损坏,无法解析 JSON。`);
485
+ console.log(colors.yellow(`\n⚠️ 警告:重建 graph.json 会丢失节点关系数据!`));
486
+ console.log(`\n可选操作:`);
487
+ console.log(` 1. 查看文件内容(前 10 行)`);
488
+ console.log(` 2. 备份并重建 graph.json(节点目录仍保留)`);
489
+ console.log(` 3. 跳过`);
490
+ const choice = await prompt(rl, "请选择 (1/2/3): ");
491
+ if (choice === "1") {
492
+ try {
493
+ const content = readFileSync(graphPath, "utf-8");
494
+ const lines = content.split("\n").slice(0, 10);
495
+ console.log(`\n--- 文件内容 (前 10 行) ---`);
496
+ lines.forEach((line, i) => console.log(`${i + 1}: ${line}`));
497
+ console.log(`--- 结束 ---\n`);
498
+ console.log(`请手动编辑文件修复 JSON 格式错误后重新运行 repair`);
499
+ }
500
+ catch (e) {
501
+ error(`读取文件失败: ${e instanceof Error ? e.message : e}`);
502
+ }
503
+ return false;
504
+ }
505
+ if (choice === "2") {
506
+ const confirmed = await confirm(rl, "确认重建 graph.json?节点关系数据将丢失,但节点目录文件会保留");
507
+ if (!confirmed)
508
+ return false;
509
+ // 备份损坏的文件
510
+ const backupName = createBackup(graphPath);
511
+ if (backupName) {
512
+ info(`已备份损坏文件: ${backupName}`);
513
+ }
514
+ // 尝试从节点目录重建
515
+ const nodesDir = join(wsPath, "nodes");
516
+ const newGraph = {
517
+ version: STORAGE_VERSION,
518
+ currentFocus: "root",
519
+ nodes: {
520
+ root: {
521
+ id: "root",
522
+ dirName: "root",
523
+ status: "planning",
524
+ parentId: null,
525
+ children: [],
526
+ },
527
+ },
528
+ };
529
+ // 扫描节点目录,添加为 root 的子节点
530
+ if (existsSync(nodesDir)) {
531
+ try {
532
+ const entries = readdirSync(nodesDir, { withFileTypes: true });
533
+ for (const entry of entries) {
534
+ if (!entry.isDirectory() || entry.name === "root")
535
+ continue;
536
+ const nodeId = `node-recovered-${entry.name}`;
537
+ newGraph.nodes[nodeId] = {
538
+ id: nodeId,
539
+ dirName: entry.name,
540
+ status: "planning",
541
+ parentId: "root",
542
+ children: [],
543
+ };
544
+ newGraph.nodes.root.children.push(nodeId);
545
+ }
546
+ }
547
+ catch { /* ignore */ }
548
+ }
549
+ writeJson(graphPath, newGraph);
550
+ success(`已重建 graph.json,恢复了 ${Object.keys(newGraph.nodes).length - 1} 个节点目录`);
551
+ return true;
552
+ }
553
+ return false;
554
+ },
555
+ });
556
+ }
557
+ else {
558
+ // 3.1 版本检查
559
+ if (graph.version && compareVersion(graph.version, STORAGE_VERSION) > 0) {
560
+ issues.push({
561
+ id: "graph-version-too-high",
562
+ severity: "error",
563
+ message: `graph.json 版本过高`,
564
+ detail: `文件版本: ${graph.version}, 当前支持: ${STORAGE_VERSION}`,
565
+ interactiveFix: async (rl) => {
566
+ console.log(`\ngraph.json 版本 (${graph.version}) 高于当前支持的版本 (${STORAGE_VERSION})。`);
567
+ console.log(`\n这通常意味着此工作区是用更新版本的 XtepWorkspace 创建的。`);
568
+ console.log(`\n${colors.yellow("建议")}: 升级 XtepWorkspace 到最新版本`);
569
+ console.log(` npm install -g xtep-workspace@latest`);
570
+ console.log(`\n可选操作:`);
571
+ console.log(` 1. 强制降级版本号(可能丢失新版本功能)`);
572
+ console.log(` 2. 跳过`);
573
+ const choice = await prompt(rl, "请选择 (1/2): ");
574
+ if (choice === "1") {
575
+ const confirmed = await confirm(rl, `确认将版本从 ${graph.version} 降级到 ${STORAGE_VERSION}?`);
576
+ if (!confirmed)
577
+ return false;
578
+ // 备份
579
+ const backupName = createBackup(graphPath);
580
+ if (backupName) {
581
+ info(`已备份: ${backupName}`);
582
+ }
583
+ graph.version = STORAGE_VERSION;
584
+ writeJson(graphPath, graph);
585
+ success(`已将版本降级到 ${STORAGE_VERSION}`);
586
+ return true;
587
+ }
588
+ return false;
589
+ },
590
+ });
591
+ }
592
+ // 3.2 检查节点目录
593
+ const nodesDir = join(wsPath, "nodes");
594
+ if (existsSync(nodesDir) && graph.nodes) {
595
+ for (const [nodeId, nodeMeta] of Object.entries(graph.nodes)) {
596
+ const nodeDirName = nodeMeta.dirName || nodeId;
597
+ const nodePath = join(nodesDir, nodeDirName);
598
+ if (!existsSync(nodePath)) {
599
+ // 尝试通过 shortId 查找
600
+ const foundDir = findDirByShortId(nodesDir, nodeId);
601
+ if (foundDir) {
602
+ const capturedNodeId = nodeId;
603
+ const capturedFoundDir = foundDir;
604
+ issues.push({
605
+ id: `node-dirname-mismatch-${nodeId}`,
606
+ severity: "warning",
607
+ message: `节点 ${nodeId} 的目录名不匹配`,
608
+ detail: `配置: ${nodeDirName}, 找到: ${foundDir}`,
609
+ autoFix: async () => {
610
+ const g = readJson(graphPath);
611
+ if (g && g.nodes[capturedNodeId]) {
612
+ g.nodes[capturedNodeId].dirName = capturedFoundDir;
613
+ writeJson(graphPath, g);
614
+ return true;
615
+ }
616
+ return false;
617
+ },
618
+ });
619
+ }
620
+ else {
621
+ issues.push({
622
+ id: `node-dir-missing-${nodeId}`,
623
+ severity: "warning",
624
+ message: `节点 ${nodeId} 的目录不存在`,
625
+ detail: `期望目录: ${nodeDirName}`,
626
+ interactiveFix: async (rl) => {
627
+ console.log(`\n节点目录不存在: ${nodeDirName}`);
628
+ console.log(`可选操作:`);
629
+ console.log(` 1. 输入正确的目录名`);
630
+ console.log(` 2. 跳过`);
631
+ const choice = await prompt(rl, "请选择 (1/2): ");
632
+ if (choice === "1") {
633
+ // 列出可用目录
634
+ try {
635
+ const entries = readdirSync(nodesDir, { withFileTypes: true });
636
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name);
637
+ if (dirs.length > 0) {
638
+ console.log(`\n可用目录:`);
639
+ dirs.forEach((d, i) => console.log(` ${i + 1}. ${d}`));
640
+ }
641
+ }
642
+ catch { /* ignore */ }
643
+ const newDir = await prompt(rl, "请输入正确的目录名: ");
644
+ if (newDir && existsSync(join(nodesDir, newDir))) {
645
+ const g = readJson(graphPath);
646
+ if (g && g.nodes[nodeId]) {
647
+ g.nodes[nodeId].dirName = newDir;
648
+ writeJson(graphPath, g);
649
+ return true;
650
+ }
651
+ }
652
+ else {
653
+ error("目录不存在");
654
+ }
655
+ }
656
+ return false;
657
+ },
658
+ });
659
+ }
660
+ }
661
+ }
662
+ }
663
+ }
664
+ }
665
+ return issues;
666
+ }
667
+ // 通过 shortId 查找目录
668
+ function findDirByShortId(parentDir, id) {
669
+ const shortId = extractShortId(id);
670
+ try {
671
+ const items = readdirSync(parentDir, { withFileTypes: true });
672
+ // 优先匹配 _shortId 后缀
673
+ for (const item of items) {
674
+ if (!item.isDirectory())
675
+ continue;
676
+ if (item.name.endsWith(`_${shortId}`)) {
677
+ return item.name;
678
+ }
679
+ }
680
+ // 兜底:包含 shortId
681
+ for (const item of items) {
682
+ if (!item.isDirectory())
683
+ continue;
684
+ if (item.name.includes(shortId)) {
685
+ return item.name;
686
+ }
687
+ }
688
+ }
689
+ catch {
690
+ // ignore
691
+ }
692
+ return null;
693
+ }
694
+ // 版本比较
695
+ function compareVersion(a, b) {
696
+ const [aMajor, aMinor = 0] = a.split(".").map(Number);
697
+ const [bMajor, bMinor = 0] = b.split(".").map(Number);
698
+ if (aMajor !== bMajor)
699
+ return aMajor - bMajor;
700
+ return aMinor - bMinor;
701
+ }
702
+ // ============================================================================
703
+ // 修复执行
704
+ // ============================================================================
705
+ async function runRepair(issues, interactive, dryRun) {
706
+ const result = { fixed: 0, skipped: 0, failed: 0 };
707
+ // 分类问题
708
+ const autoFixable = issues.filter(i => i.autoFix);
709
+ const interactiveFixable = issues.filter(i => !i.autoFix && i.interactiveFix);
710
+ const unfixable = issues.filter(i => !i.autoFix && !i.interactiveFix);
711
+ // 创建 readline 接口(如果需要交互)
712
+ let rl = null;
713
+ if (interactive && interactiveFixable.length > 0) {
714
+ rl = createInterface({
715
+ input: process.stdin,
716
+ output: process.stdout,
717
+ });
718
+ }
719
+ try {
720
+ // 1. 自动修复
721
+ if (autoFixable.length > 0) {
722
+ console.log(`\n${colors.bold("自动修复")} (${autoFixable.length} 个问题)\n`);
723
+ for (const issue of autoFixable) {
724
+ console.log(`${colors.yellow("→")} ${issue.message}`);
725
+ if (issue.detail)
726
+ hint(issue.detail);
727
+ if (dryRun) {
728
+ info("(dry-run) 跳过");
729
+ result.skipped++;
730
+ continue;
731
+ }
732
+ try {
733
+ const ok = await issue.autoFix();
734
+ if (ok) {
735
+ success("已修复");
736
+ result.fixed++;
737
+ }
738
+ else {
739
+ error("修复失败");
740
+ result.failed++;
741
+ }
742
+ }
743
+ catch (e) {
744
+ error(`修复出错: ${e instanceof Error ? e.message : e}`);
745
+ result.failed++;
746
+ }
747
+ }
748
+ }
749
+ // 2. 交互式修复
750
+ if (interactiveFixable.length > 0) {
751
+ if (interactive && rl) {
752
+ console.log(`\n${colors.bold("交互式修复")} (${interactiveFixable.length} 个问题)\n`);
753
+ for (const issue of interactiveFixable) {
754
+ console.log(`\n${colors.yellow("?")} ${issue.message}`);
755
+ if (issue.detail)
756
+ hint(issue.detail);
757
+ if (dryRun) {
758
+ info("(dry-run) 跳过");
759
+ result.skipped++;
760
+ continue;
761
+ }
762
+ try {
763
+ const ok = await issue.interactiveFix(rl);
764
+ if (ok) {
765
+ success("已修复");
766
+ result.fixed++;
767
+ }
768
+ else {
769
+ warn("已跳过");
770
+ result.skipped++;
771
+ }
772
+ }
773
+ catch (e) {
774
+ error(`修复出错: ${e instanceof Error ? e.message : e}`);
775
+ result.failed++;
776
+ }
777
+ }
778
+ }
779
+ else {
780
+ console.log(`\n${colors.bold("需交互式修复")} (${interactiveFixable.length} 个问题)\n`);
781
+ for (const issue of interactiveFixable) {
782
+ console.log(`${colors.yellow("?")} ${issue.message}`);
783
+ if (issue.detail)
784
+ hint(issue.detail);
785
+ result.skipped++;
786
+ }
787
+ hint("\n使用 -i 参数进入交互模式修复这些问题");
788
+ }
789
+ }
790
+ // 3. 无法自动修复的问题
791
+ if (unfixable.length > 0) {
792
+ console.log(`\n${colors.bold("需手动修复")} (${unfixable.length} 个问题)\n`);
793
+ for (const issue of unfixable) {
794
+ console.log(`${colors.red("!")} ${issue.message}`);
795
+ if (issue.detail)
796
+ hint(issue.detail);
797
+ }
798
+ }
799
+ }
800
+ finally {
801
+ if (rl) {
802
+ rl.close();
803
+ }
804
+ }
805
+ return result;
806
+ }
807
+ // ============================================================================
808
+ // 主函数
809
+ // ============================================================================
810
+ function showHelp() {
811
+ console.log(`
812
+ ${colors.bold("XtepWorkspace 工作区修复工具")}
813
+
814
+ ${colors.blue("用法:")}
815
+ xtep-workspace repair <工作区路径> 诊断指定工作区
816
+ xtep-workspace repair --fix <工作区路径> 修复指定工作区
817
+ xtep-workspace repair --fix -i <工作区路径> 交互式修复
818
+
819
+ ${colors.blue("参数:")}
820
+ <工作区路径> 工作区目录的完整路径
821
+ 例如: /project/.xtep-workspace/工作区名_xxx/
822
+ 或者: ws-xxx-yyy (通过 ID 查找)
823
+
824
+ ${colors.blue("选项:")}
825
+ --fix, -f 执行修复(默认只诊断)
826
+ --interactive, -i 交互模式,逐个处理需要用户输入的问题
827
+ --dry-run 模拟运行,不实际修改文件
828
+ --no-backup 不创建备份
829
+ --help, -h 显示帮助
830
+
831
+ ${colors.blue("示例:")}
832
+ xtep-workspace repair /project/.xtep-workspace/MyWork_abc123/
833
+ xtep-workspace repair --fix /project/.xtep-workspace/MyWork_abc123/
834
+ xtep-workspace repair --fix -i ws-abc123-xyz789
835
+ `);
836
+ }
837
+ export default async function main() {
838
+ const args = process.argv.slice(3); // 跳过 node, script, "repair"
839
+ // 解析参数
840
+ const showHelpFlag = args.includes("--help") || args.includes("-h");
841
+ const doFix = args.includes("--fix") || args.includes("-f");
842
+ const interactive = args.includes("--interactive") || args.includes("-i");
843
+ const dryRun = args.includes("--dry-run");
844
+ const noBackup = args.includes("--no-backup");
845
+ // 过滤掉选项,获取路径参数
846
+ const pathArg = args.find(a => !a.startsWith("-"));
847
+ if (showHelpFlag || !pathArg) {
848
+ showHelp();
849
+ return;
850
+ }
851
+ console.log(`\n${colors.bold("XtepWorkspace 工作区修复工具")}\n`);
852
+ // 定位工作区
853
+ const location = resolveWorkspacePath(pathArg);
854
+ if (!location) {
855
+ process.exit(1);
856
+ }
857
+ info(`工作区路径: ${location.wsPath}`);
858
+ // 检查工作区目录是否存在
859
+ if (!existsSync(location.wsPath)) {
860
+ error(`工作区目录不存在: ${location.wsPath}`);
861
+ hint("请确认路径是否正确");
862
+ process.exit(1);
863
+ }
864
+ // 诊断
865
+ info("正在诊断问题...\n");
866
+ const issues = await diagnoseWorkspace(location);
867
+ if (issues.length === 0) {
868
+ success("未发现任何问题!工作区状态正常。");
869
+ return;
870
+ }
871
+ // 显示问题统计
872
+ const errorCount = issues.filter(i => i.severity === "error").length;
873
+ const warnCount = issues.filter(i => i.severity === "warning").length;
874
+ const infoCount = issues.filter(i => i.severity === "info").length;
875
+ console.log(`发现 ${colors.bold(String(issues.length))} 个问题:`);
876
+ if (errorCount > 0)
877
+ console.log(` ${colors.red(`${errorCount} 个错误`)}`);
878
+ if (warnCount > 0)
879
+ console.log(` ${colors.yellow(`${warnCount} 个警告`)}`);
880
+ if (infoCount > 0)
881
+ console.log(` ${colors.gray(`${infoCount} 个提示`)}`);
882
+ const autoCount = issues.filter(i => i.autoFix).length;
883
+ const interactiveCount = issues.filter(i => !i.autoFix && i.interactiveFix).length;
884
+ const manualCount = issues.filter(i => !i.autoFix && !i.interactiveFix).length;
885
+ console.log(`\n修复方式:`);
886
+ if (autoCount > 0)
887
+ console.log(` ${colors.green(`${autoCount} 个可自动修复`)}`);
888
+ if (interactiveCount > 0)
889
+ console.log(` ${colors.yellow(`${interactiveCount} 个需交互修复`)}`);
890
+ if (manualCount > 0)
891
+ console.log(` ${colors.red(`${manualCount} 个需手动修复`)}`);
892
+ if (!doFix) {
893
+ console.log(`\n${colors.gray("提示: 使用 --fix 参数执行修复")}`);
894
+ return;
895
+ }
896
+ // 创建备份
897
+ if (!noBackup && !dryRun) {
898
+ const configPath = join(location.wsPath, "workspace.json");
899
+ const graphPath = join(location.wsPath, "graph.json");
900
+ if (existsSync(configPath)) {
901
+ const backup = createBackup(configPath);
902
+ if (backup)
903
+ info(`已备份 workspace.json: ${backup}`);
904
+ }
905
+ if (existsSync(graphPath)) {
906
+ const backup = createBackup(graphPath);
907
+ if (backup)
908
+ info(`已备份 graph.json: ${backup}`);
909
+ }
910
+ }
911
+ // 执行修复
912
+ const result = await runRepair(issues, interactive, dryRun);
913
+ // 显示结果
914
+ console.log(`\n${colors.bold("修复结果:")}`);
915
+ if (result.fixed > 0)
916
+ console.log(` ${colors.green(`${result.fixed} 个已修复`)}`);
917
+ if (result.skipped > 0)
918
+ console.log(` ${colors.gray(`${result.skipped} 个已跳过`)}`);
919
+ if (result.failed > 0)
920
+ console.log(` ${colors.red(`${result.failed} 个失败`)}`);
921
+ if (result.fixed > 0) {
922
+ console.log(`\n${colors.green("提示:")} 修复完成,请重新启动 XtepWorkspace 服务验证`);
923
+ }
924
+ }
925
+ //# sourceMappingURL=repair.js.map