@mrciphersmith/keryx 0.2.9

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 (297) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +351 -0
  3. package/dist/cli.js +48427 -0
  4. package/dist/proxy-worker.js +381 -0
  5. package/package.json +63 -0
  6. package/src/gdgraph/affected.test.ts +100 -0
  7. package/src/gdgraph/affected.ts +135 -0
  8. package/src/gdgraph/build-integrity.test.ts +193 -0
  9. package/src/gdgraph/build-lang.test.ts +399 -0
  10. package/src/gdgraph/build.test.ts +120 -0
  11. package/src/gdgraph/build.ts +804 -0
  12. package/src/gdgraph/config.test.ts +47 -0
  13. package/src/gdgraph/config.ts +113 -0
  14. package/src/gdgraph/core-sources.test.ts +99 -0
  15. package/src/gdgraph/core-sources.ts +20 -0
  16. package/src/gdgraph/enrich.ts +79 -0
  17. package/src/gdgraph/fallback.test.ts +153 -0
  18. package/src/gdgraph/find.test.ts +78 -0
  19. package/src/gdgraph/find.ts +107 -0
  20. package/src/gdgraph/pagerank.ts +129 -0
  21. package/src/gdgraph/path.test.ts +56 -0
  22. package/src/gdgraph/path.ts +112 -0
  23. package/src/gdgraph/query.ts +133 -0
  24. package/src/gdgraph/repomap.test.ts +110 -0
  25. package/src/gdgraph/repomap.ts +193 -0
  26. package/src/gdgraph/service.test.ts +59 -0
  27. package/src/gdgraph/service.ts +51 -0
  28. package/src/gdgraph/staleness.ts +20 -0
  29. package/src/gdgraph/symbol.test.ts +89 -0
  30. package/src/gdgraph/symbol.ts +123 -0
  31. package/src/gdgraph/symbols-capability.test.ts +41 -0
  32. package/src/gdgraph/symbols-capability.ts +49 -0
  33. package/src/gdgraph/target.ts +56 -0
  34. package/src/gdgraph/treesitter/adapter.test.ts +249 -0
  35. package/src/gdgraph/treesitter/adapter.ts +213 -0
  36. package/src/gdgraph/treesitter/extract.test.ts +278 -0
  37. package/src/gdgraph/treesitter/extract.ts +389 -0
  38. package/src/gdgraph/treesitter/grammars.ts +110 -0
  39. package/src/gdgraph/treesitter/no-treesitter-import.test.ts +51 -0
  40. package/src/gdgraph/treesitter/resolve-calls.test.ts +38 -0
  41. package/src/gdgraph/types.ts +63 -0
  42. package/src/gdskills/bundled/rules/core/api-contracts.mdc +148 -0
  43. package/src/gdskills/bundled/rules/core/async-patterns.mdc +185 -0
  44. package/src/gdskills/bundled/rules/core/clean-architecture.mdc +163 -0
  45. package/src/gdskills/bundled/rules/core/code-review-ai-assistant.mdc +49 -0
  46. package/src/gdskills/bundled/rules/core/code-review-b091-profile.mdc +48 -0
  47. package/src/gdskills/bundled/rules/core/code-style-patterns.mdc +54 -0
  48. package/src/gdskills/bundled/rules/core/commit-message-formatting.mdc +25 -0
  49. package/src/gdskills/bundled/rules/core/database-patterns.mdc +162 -0
  50. package/src/gdskills/bundled/rules/core/documentation-management.mdc +106 -0
  51. package/src/gdskills/bundled/rules/core/error-handling.mdc +163 -0
  52. package/src/gdskills/bundled/rules/core/execution-metrics.md +99 -0
  53. package/src/gdskills/bundled/rules/core/frontend-assistant.mdc +40 -0
  54. package/src/gdskills/bundled/rules/core/git-rules.mdc +37 -0
  55. package/src/gdskills/bundled/rules/core/gproject-contracts.mdc +198 -0
  56. package/src/gdskills/bundled/rules/core/implementation-doc-mandate.mdc +149 -0
  57. package/src/gdskills/bundled/rules/core/implementation-plans.mdc +58 -0
  58. package/src/gdskills/bundled/rules/core/jobs-documentation.mdc +221 -0
  59. package/src/gdskills/bundled/rules/core/mobx-store-template.mdc +561 -0
  60. package/src/gdskills/bundled/rules/core/model-selection.mdc +53 -0
  61. package/src/gdskills/bundled/rules/core/nestjs-dto.mdc +50 -0
  62. package/src/gdskills/bundled/rules/core/playwright-testing.mdc +321 -0
  63. package/src/gdskills/bundled/rules/core/requirements-management.mdc +35 -0
  64. package/src/gdskills/bundled/rules/core/requirements-package-standard.mdc +103 -0
  65. package/src/gdskills/bundled/rules/core/review-agent-profile.mdc +49 -0
  66. package/src/gdskills/bundled/rules/core/review-strict-profile.mdc +44 -0
  67. package/src/gdskills/bundled/rules/core/rule-management-workflow.mdc +62 -0
  68. package/src/gdskills/bundled/rules/core/security-baseline.mdc +155 -0
  69. package/src/gdskills/bundled/rules/core/shared-definitions.mdc +79 -0
  70. package/src/gdskills/bundled/rules/core/skill-lifecycle.mdc +55 -0
  71. package/src/gdskills/bundled/rules/core/skills-storage-workflow.mdc +88 -0
  72. package/src/gdskills/bundled/rules/core/solid-principles.mdc +149 -0
  73. package/src/gdskills/bundled/rules/core/storybook-guidelines.mdc +36 -0
  74. package/src/gdskills/bundled/rules/core/subagent-context-construction.md +107 -0
  75. package/src/gdskills/bundled/rules/core/subagent-status-protocol.md +169 -0
  76. package/src/gdskills/bundled/rules/core/tdd-workflow.mdc +96 -0
  77. package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.codex.md +47 -0
  78. package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.cursor.md +55 -0
  79. package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.md +352 -0
  80. package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.opencode.md +39 -0
  81. package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.zed.md +29 -0
  82. package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.codex.md +567 -0
  83. package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.cursor.md +567 -0
  84. package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.md +655 -0
  85. package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.opencode.md +567 -0
  86. package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.zed.md +567 -0
  87. package/src/gdskills/bundled/skills/orchestration/context-collector/input-contract.schema.json +134 -0
  88. package/src/gdskills/bundled/skills/orchestration/context-collector/orchestrator-prompt.md +183 -0
  89. package/src/gdskills/bundled/skills/orchestration/context-collector/output-contract.schema.json +208 -0
  90. package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.codex.md +1412 -0
  91. package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.cursor.md +1412 -0
  92. package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.detail.md +735 -0
  93. package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.md +468 -0
  94. package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.opencode.md +1412 -0
  95. package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.zed.md +1412 -0
  96. package/src/gdskills/bundled/skills/orchestration/feature-analyzer/analysis-request.md +62 -0
  97. package/src/gdskills/bundled/skills/orchestration/feature-analyzer/analysis-request.template.md +79 -0
  98. package/src/gdskills/bundled/skills/orchestration/feature-analyzer/input-contract.schema.json +247 -0
  99. package/src/gdskills/bundled/skills/orchestration/feature-analyzer/orchestrator-prompt.md +362 -0
  100. package/src/gdskills/bundled/skills/orchestration/feature-analyzer/output-contract.schema.json +87 -0
  101. package/src/gdskills/bundled/skills/orchestration/feature-dev/SKILL.codex.md +105 -0
  102. package/src/gdskills/bundled/skills/orchestration/feature-dev/SKILL.cursor.md +105 -0
  103. package/src/gdskills/bundled/skills/orchestration/feature-dev/SKILL.md +165 -0
  104. package/src/gdskills/bundled/skills/orchestration/flow-orchestrator/SKILL.md +379 -0
  105. package/src/gdskills/bundled/skills/orchestration/flow-orchestrator/input-contract.schema.json +33 -0
  106. package/src/gdskills/bundled/skills/orchestration/flow-orchestrator/output-contract.schema.json +41 -0
  107. package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.codex.md +307 -0
  108. package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.cursor.md +307 -0
  109. package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.md +373 -0
  110. package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.opencode.md +307 -0
  111. package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.zed.md +307 -0
  112. package/src/gdskills/bundled/skills/orchestration/issue-analyzer/input-contract.schema.json +130 -0
  113. package/src/gdskills/bundled/skills/orchestration/issue-analyzer/issue-request.template.md +50 -0
  114. package/src/gdskills/bundled/skills/orchestration/issue-analyzer/orchestrator-prompt.md +155 -0
  115. package/src/gdskills/bundled/skills/orchestration/issue-analyzer/output-contract.schema.json +61 -0
  116. package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.codex.md +365 -0
  117. package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.cursor.md +365 -0
  118. package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.md +373 -0
  119. package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.opencode.md +365 -0
  120. package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.zed.md +365 -0
  121. package/src/gdskills/bundled/skills/orchestration/job-documenter/input-contract.schema.json +55 -0
  122. package/src/gdskills/bundled/skills/orchestration/job-documenter/output-contract.schema.json +58 -0
  123. package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.codex.md +1701 -0
  124. package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.cursor.md +1701 -0
  125. package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.md +1734 -0
  126. package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.opencode.md +1701 -0
  127. package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.zed.md +1701 -0
  128. package/src/gdskills/bundled/skills/orchestration/job-orchestrator/input-contract.schema.json +188 -0
  129. package/src/gdskills/bundled/skills/orchestration/job-orchestrator/orchestrator-prompt.md +179 -0
  130. package/src/gdskills/bundled/skills/orchestration/job-orchestrator/output-contract.schema.json +103 -0
  131. package/src/gdskills/bundled/skills/orchestration/job-orchestrator/state.schema.json +164 -0
  132. package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.codex.md +395 -0
  133. package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.cursor.md +395 -0
  134. package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.md +556 -0
  135. package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.opencode.md +395 -0
  136. package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.zed.md +395 -0
  137. package/src/gdskills/bundled/skills/orchestration/task-implementer/input-contract.schema.json +204 -0
  138. package/src/gdskills/bundled/skills/orchestration/task-implementer/orchestrator-prompt.md +206 -0
  139. package/src/gdskills/bundled/skills/orchestration/task-implementer/output-contract.schema.json +51 -0
  140. package/src/gdskills/bundled/skills/orchestration/task-implementer/task-request.template.md +111 -0
  141. package/src/gdskills/bundled/skills/planning/autodoc-analyst/SKILL.md +163 -0
  142. package/src/gdskills/bundled/skills/planning/autodoc-architect/SKILL.md +161 -0
  143. package/src/gdskills/bundled/skills/planning/autodoc-assembler/SKILL.md +128 -0
  144. package/src/gdskills/bundled/skills/planning/autodoc-orchestrator/SKILL.md +321 -0
  145. package/src/gdskills/bundled/skills/planning/autodoc-scanner/SKILL.md +166 -0
  146. package/src/gdskills/bundled/skills/planning/autodoc-writer/SKILL.md +253 -0
  147. package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.claude.md +46 -0
  148. package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.codex.md +90 -0
  149. package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.cursor.md +90 -0
  150. package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.md +90 -0
  151. package/src/gdskills/bundled/skills/planning/consistency-checker/SKILL.codex.md +33 -0
  152. package/src/gdskills/bundled/skills/planning/consistency-checker/SKILL.cursor.md +33 -0
  153. package/src/gdskills/bundled/skills/planning/consistency-checker/SKILL.md +190 -0
  154. package/src/gdskills/bundled/skills/planning/docpack-orchestrator/SKILL.md +142 -0
  155. package/src/gdskills/bundled/skills/planning/docpack-orchestrator/input-contract.schema.json +31 -0
  156. package/src/gdskills/bundled/skills/planning/docpack-orchestrator/output-contract.schema.json +31 -0
  157. package/src/gdskills/bundled/skills/planning/docpack-review/SKILL.md +80 -0
  158. package/src/gdskills/bundled/skills/planning/docpack-review/input-contract.schema.json +20 -0
  159. package/src/gdskills/bundled/skills/planning/docpack-review/output-contract.schema.json +36 -0
  160. package/src/gdskills/bundled/skills/planning/interview/SKILL.codex.md +181 -0
  161. package/src/gdskills/bundled/skills/planning/interview/SKILL.cursor.md +181 -0
  162. package/src/gdskills/bundled/skills/planning/interview/SKILL.md +187 -0
  163. package/src/gdskills/bundled/skills/planning/interviewer/SKILL.claude.md +94 -0
  164. package/src/gdskills/bundled/skills/planning/interviewer/SKILL.codex.md +99 -0
  165. package/src/gdskills/bundled/skills/planning/interviewer/SKILL.cursor.md +99 -0
  166. package/src/gdskills/bundled/skills/planning/interviewer/SKILL.md +105 -0
  167. package/src/gdskills/bundled/skills/planning/patterns-researcher/SKILL.codex.md +33 -0
  168. package/src/gdskills/bundled/skills/planning/patterns-researcher/SKILL.cursor.md +33 -0
  169. package/src/gdskills/bundled/skills/planning/patterns-researcher/SKILL.md +237 -0
  170. package/src/gdskills/bundled/skills/planning/planner/SKILL.codex.md +33 -0
  171. package/src/gdskills/bundled/skills/planning/planner/SKILL.cursor.md +33 -0
  172. package/src/gdskills/bundled/skills/planning/planner/SKILL.md +190 -0
  173. package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.codex.md +193 -0
  174. package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.cursor.md +193 -0
  175. package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.md +193 -0
  176. package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.opencode.md +193 -0
  177. package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.zed.md +193 -0
  178. package/src/gdskills/bundled/skills/planning/prd-creator/input-contract.schema.json +63 -0
  179. package/src/gdskills/bundled/skills/planning/prd-creator/output-contract.schema.json +175 -0
  180. package/src/gdskills/bundled/skills/planning/problem-definer/SKILL.codex.md +31 -0
  181. package/src/gdskills/bundled/skills/planning/problem-definer/SKILL.cursor.md +31 -0
  182. package/src/gdskills/bundled/skills/planning/problem-definer/SKILL.md +153 -0
  183. package/src/gdskills/bundled/skills/planning/project-discovery/SKILL.codex.md +32 -0
  184. package/src/gdskills/bundled/skills/planning/project-discovery/SKILL.cursor.md +32 -0
  185. package/src/gdskills/bundled/skills/planning/project-discovery/SKILL.md +166 -0
  186. package/src/gdskills/bundled/skills/planning/spec-writer/SKILL.codex.md +44 -0
  187. package/src/gdskills/bundled/skills/planning/spec-writer/SKILL.cursor.md +44 -0
  188. package/src/gdskills/bundled/skills/planning/spec-writer/SKILL.md +243 -0
  189. package/src/gdskills/bundled/skills/planning/stack-advisor/SKILL.codex.md +43 -0
  190. package/src/gdskills/bundled/skills/planning/stack-advisor/SKILL.cursor.md +43 -0
  191. package/src/gdskills/bundled/skills/planning/stack-advisor/SKILL.md +193 -0
  192. package/src/gdskills/bundled/skills/platform/agent-entrypoint-distiller/SKILL.md +47 -0
  193. package/src/gdskills/bundled/skills/platform/claude-md-management/SKILL.codex.md +87 -0
  194. package/src/gdskills/bundled/skills/platform/claude-md-management/SKILL.cursor.md +87 -0
  195. package/src/gdskills/bundled/skills/platform/claude-md-management/SKILL.md +87 -0
  196. package/src/gdskills/bundled/skills/platform/hookify/SKILL.codex.md +100 -0
  197. package/src/gdskills/bundled/skills/platform/hookify/SKILL.cursor.md +100 -0
  198. package/src/gdskills/bundled/skills/platform/hookify/SKILL.md +100 -0
  199. package/src/gdskills/bundled/skills/quality/changelog/SKILL.claude.md +45 -0
  200. package/src/gdskills/bundled/skills/quality/changelog/SKILL.codex.md +84 -0
  201. package/src/gdskills/bundled/skills/quality/changelog/SKILL.cursor.md +84 -0
  202. package/src/gdskills/bundled/skills/quality/changelog/SKILL.md +84 -0
  203. package/src/gdskills/bundled/skills/quality/commit/SKILL.codex.md +66 -0
  204. package/src/gdskills/bundled/skills/quality/commit/SKILL.cursor.md +66 -0
  205. package/src/gdskills/bundled/skills/quality/commit/SKILL.md +66 -0
  206. package/src/gdskills/bundled/skills/quality/db-migrate/SKILL.claude.md +40 -0
  207. package/src/gdskills/bundled/skills/quality/db-migrate/SKILL.codex.md +66 -0
  208. package/src/gdskills/bundled/skills/quality/db-migrate/SKILL.cursor.md +66 -0
  209. package/src/gdskills/bundled/skills/quality/db-migrate/SKILL.md +66 -0
  210. package/src/gdskills/bundled/skills/quality/dependency-update/SKILL.claude.md +45 -0
  211. package/src/gdskills/bundled/skills/quality/dependency-update/SKILL.codex.md +81 -0
  212. package/src/gdskills/bundled/skills/quality/dependency-update/SKILL.cursor.md +81 -0
  213. package/src/gdskills/bundled/skills/quality/dependency-update/SKILL.md +81 -0
  214. package/src/gdskills/bundled/skills/quality/deploy/SKILL.claude.md +42 -0
  215. package/src/gdskills/bundled/skills/quality/deploy/SKILL.codex.md +70 -0
  216. package/src/gdskills/bundled/skills/quality/deploy/SKILL.cursor.md +70 -0
  217. package/src/gdskills/bundled/skills/quality/deploy/SKILL.md +70 -0
  218. package/src/gdskills/bundled/skills/quality/metaproject-security/SKILL.md +103 -0
  219. package/src/gdskills/bundled/skills/quality/perf-check/SKILL.claude.md +48 -0
  220. package/src/gdskills/bundled/skills/quality/perf-check/SKILL.codex.md +83 -0
  221. package/src/gdskills/bundled/skills/quality/perf-check/SKILL.cursor.md +83 -0
  222. package/src/gdskills/bundled/skills/quality/perf-check/SKILL.md +83 -0
  223. package/src/gdskills/bundled/skills/quality/pr/SKILL.codex.md +75 -0
  224. package/src/gdskills/bundled/skills/quality/pr/SKILL.cursor.md +75 -0
  225. package/src/gdskills/bundled/skills/quality/pr/SKILL.md +75 -0
  226. package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.codex.md +364 -0
  227. package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.cursor.md +295 -0
  228. package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.md +378 -0
  229. package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.opencode.md +364 -0
  230. package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.zed.md +38 -0
  231. package/src/gdskills/bundled/skills/quality/pr-issue-documenter/input-contract.schema.json +53 -0
  232. package/src/gdskills/bundled/skills/quality/pr-issue-documenter/output-contract.schema.json +46 -0
  233. package/src/gdskills/bundled/skills/quality/push/SKILL.codex.md +52 -0
  234. package/src/gdskills/bundled/skills/quality/push/SKILL.cursor.md +52 -0
  235. package/src/gdskills/bundled/skills/quality/push/SKILL.md +52 -0
  236. package/src/gdskills/bundled/skills/quality/security-audit/SKILL.claude.md +40 -0
  237. package/src/gdskills/bundled/skills/quality/security-audit/SKILL.codex.md +61 -0
  238. package/src/gdskills/bundled/skills/quality/security-audit/SKILL.cursor.md +61 -0
  239. package/src/gdskills/bundled/skills/quality/security-audit/SKILL.md +61 -0
  240. package/src/gdskills/bundled/skills/quality/test-gen/SKILL.claude.md +30 -0
  241. package/src/gdskills/bundled/skills/quality/test-gen/SKILL.codex.md +75 -0
  242. package/src/gdskills/bundled/skills/quality/test-gen/SKILL.cursor.md +75 -0
  243. package/src/gdskills/bundled/skills/quality/test-gen/SKILL.md +75 -0
  244. package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.codex.md +64 -0
  245. package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.cursor.md +74 -0
  246. package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.md +339 -0
  247. package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.opencode.md +48 -0
  248. package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.zed.md +44 -0
  249. package/src/gdskills/bundled/skills/quality/tests-creator/input-contract.schema.json +121 -0
  250. package/src/gdskills/bundled/skills/quality/tests-creator/output-contract.schema.json +127 -0
  251. package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.codex.md +204 -0
  252. package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.cursor.md +204 -0
  253. package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.md +203 -0
  254. package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.opencode.md +204 -0
  255. package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.zed.md +204 -0
  256. package/src/gdskills/bundled/skills/review/code-b091-review/SKILL.codex.md +209 -0
  257. package/src/gdskills/bundled/skills/review/code-b091-review/SKILL.cursor.md +209 -0
  258. package/src/gdskills/bundled/skills/review/code-b091-review/SKILL.md +208 -0
  259. package/src/gdskills/bundled/skills/review/code-b091-review/SKILL.opencode.md +209 -0
  260. package/src/gdskills/bundled/skills/review/code-b091-review/SKILL.zed.md +209 -0
  261. package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.codex.md +263 -0
  262. package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.cursor.md +263 -0
  263. package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.md +258 -0
  264. package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.opencode.md +263 -0
  265. package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.zed.md +263 -0
  266. package/src/gdskills/bundled/skills/review/code-style-review/SKILL.codex.md +175 -0
  267. package/src/gdskills/bundled/skills/review/code-style-review/SKILL.cursor.md +175 -0
  268. package/src/gdskills/bundled/skills/review/code-style-review/SKILL.md +168 -0
  269. package/src/gdskills/bundled/skills/review/code-style-review/SKILL.opencode.md +175 -0
  270. package/src/gdskills/bundled/skills/review/code-style-review/SKILL.zed.md +175 -0
  271. package/src/gdskills/bundled/skills/review/review-architecture/SKILL.md +360 -0
  272. package/src/gdskills/bundled/skills/review/review-backend/SKILL.md +337 -0
  273. package/src/gdskills/bundled/skills/review/review-clean-code/SKILL.md +477 -0
  274. package/src/gdskills/bundled/skills/review/review-core-boundaries/SKILL.md +93 -0
  275. package/src/gdskills/bundled/skills/review/review-flow-graph/SKILL.md +119 -0
  276. package/src/gdskills/bundled/skills/review/review-frontend/SKILL.md +595 -0
  277. package/src/gdskills/bundled/skills/review/review-frontend-conventions/SKILL.md +144 -0
  278. package/src/gdskills/bundled/skills/review/review-highload/SKILL.md +519 -0
  279. package/src/gdskills/bundled/skills/review/review-logic/SKILL.md +323 -0
  280. package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.md +927 -0
  281. package/src/gdskills/bundled/skills/review/review-orchestrator/input-contract.schema.json +153 -0
  282. package/src/gdskills/bundled/skills/review/review-orchestrator/output-contract.schema.json +77 -0
  283. package/src/gdskills/bundled/skills/review/review-orchestrator/review-context.schema.json +389 -0
  284. package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-finding.schema.json +189 -0
  285. package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-input.schema.json +241 -0
  286. package/src/gdskills/bundled/skills/review/review-performance/SKILL.md +344 -0
  287. package/src/gdskills/bundled/skills/review/review-pr-feedback/SKILL.md +327 -0
  288. package/src/gdskills/bundled/skills/review/review-security-code/SKILL.md +348 -0
  289. package/src/gdskills/bundled/skills/review/review-strict/SKILL.md +328 -0
  290. package/src/gdskills/bundled/skills/review/review-style/SKILL.md +343 -0
  291. package/src/gdskills/bundled/skills/review/review-testing-practices/SKILL.md +134 -0
  292. package/src/gdskills/bundled/skills/shared/git-merge-base.md +33 -0
  293. package/src/gdskills/contracts/agent-event.schema.json +32 -0
  294. package/src/gdskills/contracts/orchestrator-state.schema.json +58 -0
  295. package/src/gdskills/contracts/review-finding.schema.json +59 -0
  296. package/src/gdskills/contracts/subagent-dispatch.schema.json +123 -0
  297. package/src/gdskills/contracts/subagent-result.schema.json +136 -0
@@ -0,0 +1,249 @@
1
+ import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
2
+ import { createHash } from "node:crypto";
3
+ import { tmpdir } from "node:os";
4
+ import path from "node:path";
5
+ import { expect, test } from "bun:test";
6
+ import { createTreesitterSpec, type BuildInput } from "./adapter";
7
+ import type { TsNode } from "./extract";
8
+ import { enrichBuildWithSymbols } from "../enrich";
9
+ import type { CallEdge, SymbolLayer, SymbolNode } from "../types";
10
+
11
+ // --- tiny structural mock tree: one top-level function `boot` that calls `tick` ---
12
+ function mk(o: {
13
+ type: string;
14
+ line?: number;
15
+ endLine?: number;
16
+ text?: string;
17
+ fields?: Record<string, TsNode | null>;
18
+ namedChildren?: TsNode[];
19
+ }): TsNode {
20
+ const line = o.line ?? 1;
21
+ const named = o.namedChildren ?? [];
22
+ return {
23
+ type: o.type,
24
+ text: o.text ?? "",
25
+ startPosition: { row: line - 1, column: 0 },
26
+ endPosition: { row: (o.endLine ?? line) - 1, column: 0 },
27
+ childForFieldName: (field: string) => o.fields?.[field] ?? null,
28
+ namedChildren: named,
29
+ children: named,
30
+ };
31
+ }
32
+
33
+ function bootTree(): TsNode {
34
+ const id = (t: string) => mk({ type: "identifier", text: t });
35
+ const body = mk({
36
+ type: "statement_block",
37
+ line: 1,
38
+ namedChildren: [mk({ type: "call_expression", line: 1, fields: { function: id("tick") }, text: "tick()" })],
39
+ });
40
+ const boot = mk({
41
+ type: "function_declaration",
42
+ line: 1,
43
+ endLine: 2,
44
+ fields: { name: id("boot"), parameters: mk({ type: "formal_parameters", text: "()" }) },
45
+ namedChildren: [body],
46
+ });
47
+ const tick = mk({
48
+ type: "function_declaration",
49
+ line: 3,
50
+ endLine: 3,
51
+ fields: { name: id("tick"), parameters: mk({ type: "formal_parameters", text: "()" }) },
52
+ });
53
+ return mk({ type: "program", line: 1, endLine: 3, namedChildren: [boot, tick] });
54
+ }
55
+
56
+ // A structural mock of the `web-tree-sitter` module (a Parser constructor with
57
+ // static `init` + `Language.load`). Parse always returns the bootTree.
58
+ function mockParserModule(): unknown {
59
+ function MockParser(this: unknown) {}
60
+ (MockParser as unknown as { init: () => Promise<void> }).init = async () => {};
61
+ (MockParser as unknown as { Language: { load: (p: string) => Promise<unknown> } }).Language = {
62
+ load: async () => ({}),
63
+ };
64
+ MockParser.prototype.setLanguage = function setLanguage(): void {};
65
+ MockParser.prototype.parse = function parse(): { rootNode: TsNode } {
66
+ return { rootNode: bootTree() };
67
+ };
68
+ return MockParser;
69
+ }
70
+
71
+ // Create a temp workspace whose lockfile pins a real on-disk grammar file so the
72
+ // Asset Resolver verifies it (availability-true), with a config grammarsPath (T1).
73
+ async function makeWorkspaceWithGrammar(): Promise<{ root: string; grammarsDir: string }> {
74
+ const root = await mkdtemp(path.join(tmpdir(), "keryx-ts-"));
75
+ const grammarsDir = path.join(root, "grammars");
76
+ await mkdir(path.join(root, ".metaproject"), { recursive: true });
77
+ await mkdir(grammarsDir, { recursive: true });
78
+ const wasmPath = path.join(grammarsDir, "tree-sitter-typescript.wasm");
79
+ const bytes = Buffer.from("fake-grammar-bytes");
80
+ await writeFile(wasmPath, bytes);
81
+ const sha = createHash("sha256").update(bytes).digest("hex");
82
+ await writeFile(
83
+ path.join(root, ".metaproject", "assets.lock.json"),
84
+ JSON.stringify({
85
+ schemaVersion: 1,
86
+ assets: {
87
+ "tree-sitter-typescript": {
88
+ version: "0.22.0",
89
+ url: "https://example.dev/tree-sitter-typescript.wasm",
90
+ sha256: sha,
91
+ size: bytes.length,
92
+ },
93
+ },
94
+ }),
95
+ );
96
+ return { root, grammarsDir };
97
+ }
98
+
99
+ test("AC5.2 availability-true — adapter isAvailable + run() yields the symbol layer", async () => {
100
+ const { root, grammarsDir } = await makeWorkspaceWithGrammar();
101
+ try {
102
+ const spec = createTreesitterSpec(root, { languages: ["typescript"], grammarsPath: grammarsDir });
103
+ const adapter = spec.load({ dep: mockParserModule(), asset: null });
104
+
105
+ expect(await adapter.isAvailable()).toBe(true);
106
+
107
+ const layer = await adapter.run({ files: [{ path: "src/boot.ts", content: "ignored-by-mock" }] });
108
+ const symbolIds = layer.symbols.map((symbol: SymbolNode) => symbol.id).sort();
109
+ expect(symbolIds).toEqual(["src/boot.ts#boot", "src/boot.ts#tick"]);
110
+ const callKinds = layer.calls.map((call: CallEdge) => `${call.kind}:${call.from}=>${call.to}`);
111
+ expect(callKinds).toContain("calls:src/boot.ts#boot=>src/boot.ts#tick");
112
+ } finally {
113
+ await rm(root, { recursive: true, force: true });
114
+ }
115
+ });
116
+
117
+ test("AC5.2 availability-false — no grammar ⇒ isAvailable false", async () => {
118
+ const root = await mkdtemp(path.join(tmpdir(), "keryx-ts-none-"));
119
+ try {
120
+ await mkdir(path.join(root, ".metaproject"), { recursive: true });
121
+ const spec = createTreesitterSpec(root, { languages: ["typescript"], grammarsPath: null });
122
+ const adapter = spec.load({ dep: mockParserModule(), asset: null });
123
+ expect(await adapter.isAvailable()).toBe(false);
124
+ } finally {
125
+ await rm(root, { recursive: true, force: true });
126
+ }
127
+ });
128
+
129
+ test("availability-false — missing dep ⇒ isAvailable false", async () => {
130
+ const { root, grammarsDir } = await makeWorkspaceWithGrammar();
131
+ try {
132
+ const spec = createTreesitterSpec(root, { languages: ["typescript"], grammarsPath: grammarsDir });
133
+ const adapter = spec.load({ dep: undefined, asset: null });
134
+ expect(await adapter.isAvailable()).toBe(false);
135
+ } finally {
136
+ await rm(root, { recursive: true, force: true });
137
+ }
138
+ });
139
+
140
+ test("AC1.1 additive write path — enrich writes symbols.jsonl + calls.jsonl via a mock adapter", async () => {
141
+ const root = await mkdtemp(path.join(tmpdir(), "keryx-enrich-"));
142
+ try {
143
+ await mkdir(path.join(root, ".metaproject", "data", "gdgraph", "storage"), { recursive: true });
144
+ const expectedLayer: SymbolLayer = {
145
+ symbols: [
146
+ {
147
+ id: "src/x.ts#run",
148
+ kind: "function",
149
+ path: "src/x.ts",
150
+ name: "run",
151
+ container: null,
152
+ startLine: 1,
153
+ endLine: 1,
154
+ language: "typescript",
155
+ signature: "run()",
156
+ },
157
+ ],
158
+ calls: [{ id: "defines:src/x.ts=>src/x.ts#run", from: "src/x.ts", to: "src/x.ts#run", kind: "defines", resolved: true }],
159
+ };
160
+
161
+ const injected = async () => ({
162
+ id: "gdgraph.treesitter",
163
+ isAvailable: async () => true,
164
+ run: async (_input: BuildInput) => expectedLayer,
165
+ });
166
+
167
+ const result = await enrichBuildWithSymbols(root, [{ path: "src/x.ts", content: "" }], injected);
168
+ expect(result.enriched).toBe(true);
169
+ expect(result.symbols).toBe(1);
170
+
171
+ const storage = path.join(root, ".metaproject", "data", "gdgraph", "storage");
172
+ const symbolsFile = await readFile(path.join(storage, "symbols.jsonl"), "utf8");
173
+ const callsFile = await readFile(path.join(storage, "calls.jsonl"), "utf8");
174
+ expect(symbolsFile.trim()).toBe(JSON.stringify(expectedLayer.symbols[0]));
175
+ expect(callsFile.trim()).toBe(JSON.stringify(expectedLayer.calls[0]));
176
+ } finally {
177
+ await rm(root, { recursive: true, force: true });
178
+ }
179
+ });
180
+
181
+ test("Java grammar resolution — grammarForFile selects java for .java files", async () => {
182
+ const root = await mkdtemp(path.join(tmpdir(), "keryx-java-"));
183
+ try {
184
+ const grammarsDir = path.join(root, "grammars");
185
+ await mkdir(path.join(root, ".metaproject"), { recursive: true });
186
+ await mkdir(grammarsDir, { recursive: true });
187
+
188
+ const wasmPath = path.join(grammarsDir, "tree-sitter-java.wasm");
189
+ const bytes = Buffer.from("fake-java-grammar");
190
+ await writeFile(wasmPath, bytes);
191
+ const sha = createHash("sha256").update(bytes).digest("hex");
192
+
193
+ await writeFile(
194
+ path.join(root, ".metaproject", "assets.lock.json"),
195
+ JSON.stringify({
196
+ schemaVersion: 1,
197
+ assets: {
198
+ "tree-sitter-java": {
199
+ version: "0.1.13",
200
+ url: "https://example.dev/tree-sitter-java.wasm",
201
+ sha256: sha,
202
+ size: bytes.length,
203
+ },
204
+ },
205
+ }),
206
+ );
207
+
208
+ const spec = createTreesitterSpec(root, { languages: ["java"], grammarsPath: grammarsDir });
209
+ const adapter = spec.load({ dep: mockParserModule(), asset: null });
210
+ expect(await adapter.isAvailable()).toBe(true);
211
+ } finally {
212
+ await rm(root, { recursive: true, force: true });
213
+ }
214
+ });
215
+
216
+ test("Python grammar resolution — grammarForFile selects python for .py files", async () => {
217
+ const root = await mkdtemp(path.join(tmpdir(), "keryx-python-"));
218
+ try {
219
+ const grammarsDir = path.join(root, "grammars");
220
+ await mkdir(path.join(root, ".metaproject"), { recursive: true });
221
+ await mkdir(grammarsDir, { recursive: true });
222
+
223
+ const wasmPath = path.join(grammarsDir, "tree-sitter-python.wasm");
224
+ const bytes = Buffer.from("fake-python-grammar");
225
+ await writeFile(wasmPath, bytes);
226
+ const sha = createHash("sha256").update(bytes).digest("hex");
227
+
228
+ await writeFile(
229
+ path.join(root, ".metaproject", "assets.lock.json"),
230
+ JSON.stringify({
231
+ schemaVersion: 1,
232
+ assets: {
233
+ "tree-sitter-python": {
234
+ version: "0.1.13",
235
+ url: "https://example.dev/tree-sitter-python.wasm",
236
+ sha256: sha,
237
+ size: bytes.length,
238
+ },
239
+ },
240
+ }),
241
+ );
242
+
243
+ const spec = createTreesitterSpec(root, { languages: ["python"], grammarsPath: grammarsDir });
244
+ const adapter = spec.load({ dep: mockParserModule(), asset: null });
245
+ expect(await adapter.isAvailable()).toBe(true);
246
+ } finally {
247
+ await rm(root, { recursive: true, force: true });
248
+ }
249
+ });
@@ -0,0 +1,213 @@
1
+ // Tree-sitter capability adapter (specification.md §7, §8.1; T-B12).
2
+ //
3
+ // Implements the Block 0 `CapabilityAdapter<BuildInput, SymbolLayer>`:
4
+ // isAvailable() = `web-tree-sitter` imports AND ≥1 configured grammar resolves
5
+ // + verifies via the Asset Resolver.
6
+ // run() = parse each source file and emit a sorted, stable SymbolLayer.
7
+ //
8
+ // This is the ONLY module in `src/` that loads `web-tree-sitter`, and it does so
9
+ // exclusively via `await import()` (C0-2, AC1.5 — enforced by the static guard).
10
+ // It NEVER throws out (C0-11): every parse error is caught and the file is
11
+ // skipped, so an opt-in ceiling can never break the deterministic seam.
12
+
13
+ import type { CapabilityAdapter, CapabilitySpec } from "../../capability/seam";
14
+ import type { CallEdge, SymbolLayer, SymbolNode } from "../types";
15
+ import { extractSymbolLayer, resolveCrossFileCalls, type TsNode } from "./extract";
16
+ import {
17
+ grammarForFile,
18
+ resolveGrammars,
19
+ symbolLanguage,
20
+ toGrammarLanguages,
21
+ type GrammarLanguage,
22
+ type ResolvedGrammar,
23
+ } from "./grammars";
24
+
25
+ export interface FileRecord {
26
+ path: string;
27
+ content: string;
28
+ }
29
+
30
+ export interface BuildInput {
31
+ files: FileRecord[];
32
+ }
33
+
34
+ export interface TreesitterAdapterConfig {
35
+ languages: string[];
36
+ grammarsPath: string | null;
37
+ }
38
+
39
+ // Minimal shapes of the `web-tree-sitter` surface we touch (kept local so the
40
+ // dep is never imported for types either — structural typing only).
41
+ interface ParserLike {
42
+ setLanguage(language: unknown): void;
43
+ parse(input: string): { rootNode: TsNode } | null;
44
+ }
45
+ // Version-tolerant view over the two shipped APIs:
46
+ // 0.22 — default export is the Parser class; `Parser.Language.load`, `Parser.init`.
47
+ // 0.25 — named `Parser` + top-level `Language.load`; no default export.
48
+ interface ParserApi {
49
+ init?: () => Promise<void>;
50
+ loadLanguage: (pathOrBytes: string) => Promise<unknown>;
51
+ create: () => ParserLike;
52
+ }
53
+
54
+ // Build the capability spec for `resolveCapability(cwd, spec)`. Dep-only gate at
55
+ // the seam; grammar resolution happens inside `isAvailable()` because the layer
56
+ // spans multiple grammar assets (one per language).
57
+ export function createTreesitterSpec(
58
+ cwd: string,
59
+ config: TreesitterAdapterConfig,
60
+ ): CapabilitySpec<BuildInput, SymbolLayer> {
61
+ return {
62
+ id: "gdgraph.treesitter",
63
+ optionalDependency: "web-tree-sitter",
64
+ load: (ctx) => new TreesitterAdapter(cwd, config, ctx.dep),
65
+ };
66
+ }
67
+
68
+ class TreesitterAdapter implements CapabilityAdapter<BuildInput, SymbolLayer> {
69
+ readonly id = "gdgraph.treesitter";
70
+ private grammars: ResolvedGrammar[] = [];
71
+
72
+ constructor(
73
+ private readonly cwd: string,
74
+ private readonly config: TreesitterAdapterConfig,
75
+ private readonly dep: unknown,
76
+ ) {}
77
+
78
+ async isAvailable(): Promise<boolean> {
79
+ if (!this.dep) {
80
+ return false;
81
+ }
82
+ const languages = toGrammarLanguages(this.config.languages);
83
+ this.grammars = await resolveGrammars(this.cwd, languages, this.config.grammarsPath);
84
+ return this.grammars.length > 0;
85
+ }
86
+
87
+ async run(input: BuildInput): Promise<SymbolLayer> {
88
+ const available: GrammarLanguage[] = this.grammars.map((grammar) => grammar.language);
89
+ const api = normalizeParserApi(this.dep);
90
+ if (!api) {
91
+ return { symbols: [], calls: [] };
92
+ }
93
+ if (typeof api.init === "function") {
94
+ await api.init();
95
+ }
96
+
97
+ // Load + cache one parser per resolved grammar language.
98
+ const parsers = new Map<GrammarLanguage, ParserLike>();
99
+ for (const grammar of this.grammars) {
100
+ try {
101
+ const language = await api.loadLanguage(grammar.path);
102
+ if (!language) {
103
+ continue;
104
+ }
105
+ const parser = api.create();
106
+ parser.setLanguage(language);
107
+ parsers.set(grammar.language, parser);
108
+ } catch {
109
+ // Grammar load failure ⇒ skip this language (never throw out).
110
+ }
111
+ }
112
+
113
+ const symbols: SymbolNode[] = [];
114
+ const calls: CallEdge[] = [];
115
+ for (const file of [...input.files].sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0))) {
116
+ const language = grammarForFile(file.path, available);
117
+ if (!language) {
118
+ continue;
119
+ }
120
+ const parser = parsers.get(language);
121
+ if (!parser) {
122
+ continue;
123
+ }
124
+ try {
125
+ const tree = parser.parse(file.content);
126
+ if (!tree?.rootNode) {
127
+ continue;
128
+ }
129
+ const layer = extractSymbolLayer(tree.rootNode, file.path, symbolLanguage(language));
130
+ symbols.push(...layer.symbols);
131
+ calls.push(...layer.calls);
132
+ } catch {
133
+ // Parse failure on one file ⇒ skip it deterministically.
134
+ }
135
+ }
136
+
137
+ return {
138
+ symbols: symbols.sort(compareSymbols),
139
+ // Global pass: resolve cross-file calls (per-file extraction can't) before
140
+ // sorting, so callers/impact don't under-report across module boundaries.
141
+ calls: resolveCrossFileCalls(symbols, calls).sort(compareCalls),
142
+ };
143
+ }
144
+ }
145
+
146
+ // Resolve a version-tolerant parser API from whatever `web-tree-sitter` shape the
147
+ // runtime provides (0.22 default-export class vs 0.25 named exports).
148
+ function normalizeParserApi(dep: unknown): ParserApi | null {
149
+ if (!dep) {
150
+ return null;
151
+ }
152
+ const ns = dep as { default?: unknown; Parser?: unknown; Language?: unknown; init?: unknown };
153
+ const ParserClass =
154
+ typeof ns.default === "function"
155
+ ? (ns.default as new () => ParserLike)
156
+ : typeof ns.Parser === "function"
157
+ ? (ns.Parser as new () => ParserLike)
158
+ : typeof dep === "function"
159
+ ? (dep as new () => ParserLike)
160
+ : null;
161
+ if (!ParserClass) {
162
+ return null;
163
+ }
164
+
165
+ const classInit = (ParserClass as unknown as { init?: unknown }).init;
166
+ const init =
167
+ typeof classInit === "function"
168
+ ? (classInit as () => Promise<void>).bind(ParserClass)
169
+ : typeof ns.init === "function"
170
+ ? (ns.init as () => Promise<void>).bind(ns)
171
+ : undefined;
172
+
173
+ // Resolve the grammar loader LAZILY: in 0.22 `Parser.Language.load` only
174
+ // becomes available AFTER `Parser.init()` runs, so binding it eagerly here
175
+ // (before init) would miss it and wrongly disable the whole capability.
176
+ const loadLanguage = (p: string): Promise<unknown> => {
177
+ const classLoad = (ParserClass as unknown as { Language?: { load?: unknown } }).Language;
178
+ if (typeof classLoad?.load === "function") {
179
+ return (classLoad.load as (x: string) => Promise<unknown>).call(classLoad, p); // 0.22
180
+ }
181
+ const nsLoad = ns.Language as { load?: unknown } | undefined;
182
+ if (typeof nsLoad?.load === "function") {
183
+ return (nsLoad.load as (x: string) => Promise<unknown>).call(nsLoad, p); // 0.25
184
+ }
185
+ return Promise.reject(new Error("web-tree-sitter: no Language.load"));
186
+ };
187
+
188
+ return {
189
+ ...(init ? { init } : {}),
190
+ loadLanguage,
191
+ create: () => new ParserClass(),
192
+ };
193
+ }
194
+
195
+ function compareSymbols(a: SymbolNode, b: SymbolNode): number {
196
+ if (a.path !== b.path) {
197
+ return a.path < b.path ? -1 : 1;
198
+ }
199
+ if (a.startLine !== b.startLine) {
200
+ return a.startLine - b.startLine;
201
+ }
202
+ return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
203
+ }
204
+
205
+ function compareCalls(a: CallEdge, b: CallEdge): number {
206
+ if (a.from !== b.from) {
207
+ return a.from < b.from ? -1 : 1;
208
+ }
209
+ if (a.to !== b.to) {
210
+ return a.to < b.to ? -1 : 1;
211
+ }
212
+ return a.kind < b.kind ? -1 : a.kind > b.kind ? 1 : 0;
213
+ }