@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,110 @@
1
+ // Grammar WASM resolution via the Block 0 Asset Resolver (specification.md §8.1;
2
+ // T-B11, A-1..A-7). Grammar assets are pinned in `.metaproject/assets.lock.json`
3
+ // and resolved (sha256-verified on EVERY load) through `resolveAsset` — a
4
+ // tampered/missing grammar ⇒ `null` ⇒ the capability degrades to the regex
5
+ // fallback (AC1.6). This module NEVER touches the network and imports no optional
6
+ // dependency.
7
+
8
+ import path from "node:path";
9
+ import { loadAssetsLock, registryFromLock } from "../../assets/lock";
10
+ import { resolveAsset } from "../../assets/resolver";
11
+
12
+ export type GrammarLanguage = "typescript" | "tsx" | "javascript" | "java" | "python";
13
+
14
+ // The asset id for a language's grammar in `assets.lock.json`.
15
+ export function grammarAssetId(language: GrammarLanguage): string {
16
+ return `tree-sitter-${language}`;
17
+ }
18
+
19
+ // Map an extractor language to its parsed-symbol language tag.
20
+ export function symbolLanguage(language: GrammarLanguage): "typescript" | "javascript" | "java" | "python" {
21
+ if (language === "javascript") return "javascript";
22
+ if (language === "python") return "python";
23
+ if (language === "java") return "java";
24
+ return "typescript";
25
+ }
26
+
27
+ export interface ResolvedGrammar {
28
+ language: GrammarLanguage;
29
+ path: string;
30
+ }
31
+
32
+ // Resolve a single grammar to a verified on-disk wasm path, or `null` when the
33
+ // asset is absent / fails checksum. `grammarsPath` (config T1) supplies an
34
+ // optional per-id user override directory of `tree-sitter-<lang>.wasm` files.
35
+ export async function resolveGrammar(
36
+ cwd: string,
37
+ language: GrammarLanguage,
38
+ grammarsPath?: string | null,
39
+ ): Promise<ResolvedGrammar | null> {
40
+ const id = grammarAssetId(language);
41
+ const lock = await loadAssetsLock(cwd);
42
+ const overrides = grammarsPath
43
+ ? { [id]: { path: path.join(grammarsPath, `${id}.wasm`) } }
44
+ : undefined;
45
+ const registry = registryFromLock(lock, overrides);
46
+ const resolved = await resolveAsset(registry, id);
47
+ if (!resolved) {
48
+ return null;
49
+ }
50
+ return { language, path: resolved.path };
51
+ }
52
+
53
+ // Resolve every requested grammar that is available. Unavailable ones are
54
+ // skipped (not an error) — the adapter is available when at least one resolves.
55
+ export async function resolveGrammars(
56
+ cwd: string,
57
+ languages: GrammarLanguage[],
58
+ grammarsPath?: string | null,
59
+ ): Promise<ResolvedGrammar[]> {
60
+ const resolved: ResolvedGrammar[] = [];
61
+ for (const language of languages) {
62
+ const grammar = await resolveGrammar(cwd, language, grammarsPath);
63
+ if (grammar) {
64
+ resolved.push(grammar);
65
+ }
66
+ }
67
+ return resolved;
68
+ }
69
+
70
+ // Normalize config language strings to supported grammar languages.
71
+ export function toGrammarLanguages(languages: string[]): GrammarLanguage[] {
72
+ const out: GrammarLanguage[] = [];
73
+ for (const language of languages) {
74
+ if (
75
+ language === "typescript" ||
76
+ language === "tsx" ||
77
+ language === "javascript" ||
78
+ language === "java" ||
79
+ language === "python"
80
+ ) {
81
+ if (!out.includes(language as GrammarLanguage)) {
82
+ out.push(language as GrammarLanguage);
83
+ }
84
+ }
85
+ }
86
+ return out;
87
+ }
88
+
89
+ // Choose the grammar for a source file path.
90
+ export function grammarForFile(file: string, available: GrammarLanguage[]): GrammarLanguage | null {
91
+ const ext = path.extname(file);
92
+ const preference: GrammarLanguage[] =
93
+ ext === ".tsx"
94
+ ? ["tsx", "typescript"]
95
+ : ext === ".ts"
96
+ ? ["typescript"]
97
+ : ext === ".jsx" || ext === ".js" || ext === ".mjs" || ext === ".cjs"
98
+ ? ["javascript"]
99
+ : ext === ".java"
100
+ ? ["java"]
101
+ : ext === ".py"
102
+ ? ["python"]
103
+ : [];
104
+ for (const language of preference) {
105
+ if (available.includes(language)) {
106
+ return language;
107
+ }
108
+ }
109
+ return null;
110
+ }
@@ -0,0 +1,51 @@
1
+ import { readFile, readdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { expect, test } from "bun:test";
5
+
6
+ // AC1.5 (C0-2): `web-tree-sitter` is imported ONLY via `await import()` inside
7
+ // `src/gdgraph/treesitter/adapter.ts`. This is an ADDITIVE, gdgraph-specific
8
+ // assertion layered on the generic `src/capability/no-optional-imports.test.ts`
9
+ // (which already scans every optionalDependencies package across `src/`).
10
+
11
+ const SRC_ROOT = fileURLToPath(new URL("../../", import.meta.url));
12
+ const ADAPTER = path.join(SRC_ROOT, "gdgraph", "treesitter", "adapter.ts");
13
+
14
+ async function tsFiles(dir: string): Promise<string[]> {
15
+ const entries = await readdir(dir, { withFileTypes: true });
16
+ const files: string[] = [];
17
+ for (const entry of entries) {
18
+ const full = path.join(dir, entry.name);
19
+ if (entry.isDirectory()) {
20
+ files.push(...(await tsFiles(full)));
21
+ } else if (entry.isFile() && entry.name.endsWith(".ts")) {
22
+ files.push(full);
23
+ }
24
+ }
25
+ return files;
26
+ }
27
+
28
+ test("no static import of web-tree-sitter anywhere in src/", async () => {
29
+ const files = await tsFiles(SRC_ROOT);
30
+ const staticImport = /\b(?:import|export)\b[^()]*?\bfrom\s*['"]web-tree-sitter['"]|\bimport\s*['"]web-tree-sitter['"]|\brequire\s*\(\s*['"]web-tree-sitter['"]\s*\)/;
31
+ const violations: string[] = [];
32
+ for (const file of files) {
33
+ const content = await readFile(file, "utf8");
34
+ if (staticImport.test(content)) {
35
+ violations.push(path.relative(SRC_ROOT, file));
36
+ }
37
+ }
38
+ expect(violations).toEqual([]);
39
+ });
40
+
41
+ test("adapter declares web-tree-sitter as a lazy optionalDependency, never a static import", async () => {
42
+ const content = await readFile(ADAPTER, "utf8");
43
+ // The dep is loaded lazily by the seam (`await import(spec.optionalDependency)`
44
+ // in capability/seam.ts) using the id the adapter declares here.
45
+ expect(content).toContain('optionalDependency: "web-tree-sitter"');
46
+ // The adapter never statically imports the dep (types are structural).
47
+ expect(/from\s*['"]web-tree-sitter['"]/.test(content)).toBe(false);
48
+
49
+ const seam = await readFile(path.join(SRC_ROOT, "capability", "seam.ts"), "utf8");
50
+ expect(seam).toContain("await import(spec.optionalDependency)");
51
+ });
@@ -0,0 +1,38 @@
1
+ import { expect, test } from "bun:test";
2
+ import { resolveCrossFileCalls } from "./extract";
3
+ import type { CallEdge, SymbolNode } from "../types";
4
+
5
+ function sym(id: string, name: string, path: string): SymbolNode {
6
+ return { id, kind: "function", path, name, container: null, startLine: 1, endLine: 2, language: "typescript" };
7
+ }
8
+ function unresolved(from: string, to: string): CallEdge {
9
+ return { id: `u:${from}=>${to}`, from, to, kind: "unresolved-call", resolved: false };
10
+ }
11
+
12
+ test("resolves a cross-file member call to a globally-unique symbol", () => {
13
+ const symbols = [sym("src/a.ts#runPipeline", "runPipeline", "src/a.ts"), sym("src/b.ts#caller", "caller", "src/b.ts")];
14
+ // caller (in b.ts) calls `TasksApi.runPipeline` — cross-file, unresolved by per-file extraction
15
+ const calls = [unresolved("src/b.ts#caller", "TasksApi.runPipeline")];
16
+ const out = resolveCrossFileCalls(symbols, calls);
17
+ expect(out).toHaveLength(1);
18
+ expect(out[0]).toMatchObject({ from: "src/b.ts#caller", to: "src/a.ts#runPipeline", kind: "calls", resolved: true });
19
+ });
20
+
21
+ test("leaves an ambiguous name (multiple defs) unresolved — never guesses", () => {
22
+ const symbols = [
23
+ sym("src/a.ts#clonePipeline", "clonePipeline", "src/a.ts"),
24
+ sym("src/b.ts#clonePipeline", "clonePipeline", "src/b.ts"),
25
+ sym("src/c.ts#caller", "caller", "src/c.ts"),
26
+ ];
27
+ const out = resolveCrossFileCalls(symbols, [unresolved("src/c.ts#caller", "x.clonePipeline")]);
28
+ expect(out[0]?.kind).toBe("unresolved-call");
29
+ });
30
+
31
+ test("drops self-edges and passes resolved calls through unchanged", () => {
32
+ const symbols = [sym("src/a.ts#f", "f", "src/a.ts")];
33
+ const resolved: CallEdge = { id: "c", from: "src/a.ts#g", to: "src/a.ts#f", kind: "calls", resolved: true };
34
+ const out = resolveCrossFileCalls(symbols, [unresolved("src/a.ts#f", "f"), resolved]);
35
+ // the self-call f->f is not added as a resolved edge; the pre-resolved call stays
36
+ expect(out.some((c) => c.kind === "calls" && c.from === "src/a.ts#f" && c.to === "src/a.ts#f")).toBe(false);
37
+ expect(out).toContainEqual(resolved);
38
+ });
@@ -0,0 +1,63 @@
1
+ export type GraphNode = {
2
+ id: string;
3
+ kind: "file" | "asset";
4
+ path: string;
5
+ language: "typescript" | "javascript" | "java" | "python" | "asset";
6
+ };
7
+
8
+ export type GraphEdge = {
9
+ id: string;
10
+ from: string;
11
+ to: string;
12
+ kind: "imports" | "asset" | "unresolved";
13
+ specifier: string;
14
+ };
15
+
16
+ export type GraphData = {
17
+ nodes: GraphNode[];
18
+ edges: GraphEdge[];
19
+ // B1 symbol layer — present only when tree-sitter enrichment ran and wrote
20
+ // `storage/symbols.jsonl` / `storage/calls.jsonl`. Missing ⇒ omitted (never an
21
+ // error; `loadGraph` loads them only if present). File-level consumers ignore
22
+ // these fields, keeping the legacy graph shape backward-compatible.
23
+ symbols?: SymbolNode[];
24
+ calls?: CallEdge[];
25
+ };
26
+
27
+ // --- B1 symbol layer types (additive; only materialized in symbols.jsonl /
28
+ // calls.jsonl when the `gdgraph.treesitter` capability is active). ---
29
+
30
+ export type SymbolKind = "function" | "class" | "method" | "interface";
31
+
32
+ export type SymbolNode = {
33
+ // "<path>#<Container>.<name>" (+ "@<startLine>" on name collision).
34
+ id: string;
35
+ kind: SymbolKind;
36
+ // Owning file (matches a file GraphNode.path).
37
+ path: string;
38
+ name: string;
39
+ // Enclosing class/namespace, or null.
40
+ container: string | null;
41
+ // 1-based; positional, for stable disambiguation.
42
+ startLine: number;
43
+ endLine: number;
44
+ language: "typescript" | "javascript" | "java" | "python";
45
+ // Rendered for repomap.
46
+ signature?: string;
47
+ };
48
+
49
+ export type CallEdge = {
50
+ id: string;
51
+ // SymbolNode.id of caller (or file path when caller unknown).
52
+ from: string;
53
+ // SymbolNode.id of callee, or raw callee text when unresolved.
54
+ to: string;
55
+ // "defines": file → symbol containment.
56
+ kind: "calls" | "defines" | "unresolved-call";
57
+ resolved: boolean;
58
+ };
59
+
60
+ export type SymbolLayer = {
61
+ symbols: SymbolNode[];
62
+ calls: CallEdge[];
63
+ };
@@ -0,0 +1,148 @@
1
+ ---
2
+ description: "API contract rules: OpenAPI-first design, semantic versioning, no breaking changes without major version bump, contract testing. Use when designing, modifying, or consuming HTTP APIs."
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # API Contracts
7
+
8
+ ## Purpose
9
+ Prevent silent breaking changes, version drift, and undocumented API behaviour. Enforce OpenAPI-first design and strict versioning discipline.
10
+
11
+ ## When To Apply
12
+ Apply when creating new API endpoints, modifying existing endpoints, changing DTOs/schemas, or writing API client code.
13
+
14
+ ---
15
+
16
+ ## Core Principle: Contract Before Code
17
+
18
+ The OpenAPI spec (or equivalent schema) is the source of truth. Code is generated from or validated against the spec — not the other way around.
19
+
20
+ ```
21
+ 1. Design the endpoint in OpenAPI/schema first
22
+ 2. Review the contract for breaking changes
23
+ 3. Generate or update types/validators from the spec
24
+ 4. Implement the handler
25
+ 5. Write contract tests that validate the spec is honoured
26
+ ```
27
+
28
+ ---
29
+
30
+ ## Rules
31
+
32
+ ### Rule 1: OpenAPI-First for New Endpoints
33
+ Every new HTTP endpoint MUST have an OpenAPI 3.x definition before the handler is implemented:
34
+
35
+ ```yaml
36
+ # Required fields for every endpoint definition
37
+ paths:
38
+ /users/{id}:
39
+ get:
40
+ operationId: getUser # unique, stable identifier
41
+ summary: Get user by ID
42
+ parameters:
43
+ - name: id
44
+ in: path
45
+ required: true
46
+ schema: { type: string, format: uuid }
47
+ responses:
48
+ '200':
49
+ description: User found
50
+ content:
51
+ application/json:
52
+ schema: { $ref: '#/components/schemas/User' }
53
+ '404':
54
+ $ref: '#/components/responses/NotFound'
55
+ '401':
56
+ $ref: '#/components/responses/Unauthorized'
57
+ ```
58
+
59
+ **Required for every endpoint:**
60
+ - `operationId` (stable, unique)
61
+ - All path/query/header parameters documented
62
+ - All response codes documented (including 4xx, 5xx)
63
+ - Request body schema referenced (not inlined) for reuse
64
+
65
+ ### Rule 2: Semantic Versioning for APIs
66
+
67
+ | Change Type | Version Impact | Action Required |
68
+ |---|---|---|
69
+ | Add optional field to response | None / patch | Safe — backwards compatible |
70
+ | Add optional field to request | None / patch | Safe — old clients omit it |
71
+ | Add new endpoint | Minor bump | Document in changelog |
72
+ | Make optional field required | **Major bump** | Breaking change |
73
+ | Remove field from response | **Major bump** | Breaking change |
74
+ | Rename field | **Major bump** | Breaking change |
75
+ | Change field type | **Major bump** | Breaking change |
76
+ | Remove endpoint | **Major bump** | Deprecate first, remove in next major |
77
+
78
+ **Breaking change protocol:**
79
+ 1. Add deprecation notice to old version (`deprecated: true` in OpenAPI)
80
+ 2. Implement new version at `/v{N+1}/...` or with new operationId
81
+ 3. Run old version in parallel for ≥1 release cycle
82
+ 4. Remove old version only after clients have migrated
83
+
84
+ ### Rule 3: Contract Testing
85
+ Every public API endpoint MUST have at least one contract test that:
86
+ - Validates the response shape matches the OpenAPI schema
87
+ - Tests the error responses (at minimum: 400, 404, 401 where applicable)
88
+ - Uses schema validation, not string matching
89
+
90
+ ```typescript
91
+ // Example: contract test using a schema validator
92
+ describe('GET /users/:id contract', () => {
93
+ it('returns User schema on 200', async () => {
94
+ const res = await request(app).get('/users/valid-id');
95
+ expect(res.status).toBe(200);
96
+ expect(res.body).toMatchSchema(UserSchema); // validated against OpenAPI
97
+ });
98
+
99
+ it('returns 404 with NotFound schema on unknown id', async () => {
100
+ const res = await request(app).get('/users/nonexistent');
101
+ expect(res.status).toBe(404);
102
+ expect(res.body).toMatchSchema(NotFoundSchema);
103
+ });
104
+ });
105
+ ```
106
+
107
+ ### Rule 4: No Undocumented Fields
108
+ Every field in a request or response body MUST appear in the schema. Fields not in the schema must be stripped from responses (`additionalProperties: false` in JSON Schema).
109
+
110
+ ### Rule 5: Consistent Error Schema
111
+ All error responses must use the same envelope schema:
112
+
113
+ ```typescript
114
+ interface ApiError {
115
+ code: string; // machine-readable, e.g. "USER_NOT_FOUND"
116
+ message: string; // human-readable
117
+ details?: unknown; // optional structured context
118
+ requestId: string; // for traceability
119
+ }
120
+ ```
121
+
122
+ Never return raw Error objects, stack traces, or ORM error messages to API consumers.
123
+
124
+ ### Rule 6: Idempotency Keys for Mutations
125
+ POST/PUT/PATCH endpoints that create or modify state MUST support idempotency via `Idempotency-Key` header or a stable `clientId` in the body. This prevents duplicate operations on network retry.
126
+
127
+ ---
128
+
129
+ ## Iron Laws
130
+
131
+ **IRON LAW 1: NO breaking change may be deployed without a major version bump and a deprecation period.**
132
+ **IRON LAW 2: The OpenAPI spec is updated BEFORE the implementation — not after as documentation.**
133
+ **IRON LAW 3: Error responses MUST use the standard ApiError envelope — no raw exceptions, no ad-hoc shapes.**
134
+
135
+ ---
136
+
137
+ ## Red Flags — Stop and re-read this rule if you are thinking:
138
+
139
+ | Rationalization | Why it's wrong |
140
+ |---|---|
141
+ | "It's just adding a field, that's not breaking" | Removing a field later will be breaking — document it now to establish the contract |
142
+ | "The spec can wait, I'll document it later" | Specs written after code document what the code does, not what it should do — bugs get documented too |
143
+ | "Renaming a field is internal, consumers will adapt" | Consumers have no way to know a field was renamed — this silently breaks every client |
144
+ | "I'll use v2 later if needed, for now v1 is fine" | Delaying versioning means v1 can never be changed without breaking consumers |
145
+ | "Contract tests slow down development" | Contract tests catch breaking changes before they reach consumers — not after |
146
+ | "The error format doesn't matter as long as the status code is right" | Status codes alone are insufficient for automated error handling — codes and schemas matter |
147
+
148
+ **IRON LAW: A BREAKING CHANGE WITHOUT A VERSION BUMP IS A PRODUCTION INCIDENT WAITING TO HAPPEN.**
@@ -0,0 +1,185 @@
1
+ ---
2
+ description: "Async patterns: Promise.all for parallelism, no unhandled rejections, mandatory timeouts for external calls, no blocking the event loop. Use when writing async/await code, parallel operations, or queue consumers."
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Async Patterns
7
+
8
+ ## Purpose
9
+ Prevent common async pitfalls: sequential execution where parallel is safe, unhandled promise rejections, missing timeouts, and event loop blockage.
10
+
11
+ ## When To Apply
12
+ Apply when writing any `async`/`await` code, calling external services, processing queues, or coordinating multiple async operations.
13
+
14
+ ---
15
+
16
+ ## Rules
17
+
18
+ ### Rule 1: Use Promise.all for Independent Operations
19
+
20
+ Sequential await for independent operations wastes time. Run them in parallel.
21
+
22
+ ```typescript
23
+ // BAD — sequential: takes 300ms (100 + 100 + 100)
24
+ const user = await fetchUser(id);
25
+ const orders = await fetchOrders(id);
26
+ const prefs = await fetchPreferences(id);
27
+
28
+ // GOOD — parallel: takes 100ms (max of 100, 100, 100)
29
+ const [user, orders, prefs] = await Promise.all([
30
+ fetchUser(id),
31
+ fetchOrders(id),
32
+ fetchPreferences(id),
33
+ ]);
34
+ ```
35
+
36
+ **Rule:** If operation B does not depend on the result of operation A, they MUST run in parallel.
37
+
38
+ ### Rule 2: Use Promise.allSettled When Partial Failure is Acceptable
39
+
40
+ ```typescript
41
+ // BAD — one failure cancels all
42
+ const results = await Promise.all([criticalOp(), optionalOp()]); // if optionalOp rejects, criticalOp result is lost
43
+
44
+ // GOOD — each result handled independently
45
+ const [critical, optional] = await Promise.allSettled([criticalOp(), optionalOp()]);
46
+ if (critical.status === 'rejected') throw critical.reason;
47
+ if (optional.status === 'rejected') logger.warn('optional failed', optional.reason);
48
+ ```
49
+
50
+ Use `Promise.all` when ALL operations are required. Use `Promise.allSettled` when SOME can fail gracefully.
51
+
52
+ ### Rule 3: Every External Call Has a Timeout
53
+
54
+ Network calls without timeouts hang indefinitely, blocking resources.
55
+
56
+ ```typescript
57
+ // BAD — hangs forever if service is down
58
+ const response = await fetch('https://api.external.com/data');
59
+
60
+ // GOOD — fails fast after 5 seconds
61
+ const controller = new AbortController();
62
+ const timeout = setTimeout(() => controller.abort(), 5_000);
63
+ try {
64
+ const response = await fetch('https://api.external.com/data', { signal: controller.signal });
65
+ // ...
66
+ } finally {
67
+ clearTimeout(timeout);
68
+ }
69
+
70
+ // GOOD — with a utility wrapper
71
+ const response = await fetchWithTimeout('https://api.external.com/data', { timeout: 5_000 });
72
+ ```
73
+
74
+ **Default timeouts:**
75
+ - Internal service calls: 3s
76
+ - External API calls: 10s
77
+ - Long-running operations (file processing, ML): 60s with progress events
78
+ - Database queries: configure at connection pool level
79
+
80
+ ### Rule 4: No Unhandled Promise Rejections
81
+
82
+ Every promise must have a `.catch()` or be `await`-ed inside a `try/catch`.
83
+
84
+ ```typescript
85
+ // BAD — fire-and-forget without error handling
86
+ sendNotification(userId, message); // rejection is swallowed silently
87
+
88
+ // BAD — floating promise in Express handler
89
+ app.get('/data', (req, res) => {
90
+ loadData(); // not awaited, errors don't propagate to response
91
+ res.json({ ok: true });
92
+ });
93
+
94
+ // GOOD — fire-and-forget with explicit error handling
95
+ sendNotification(userId, message).catch(err => {
96
+ logger.error('notification failed', { userId, err });
97
+ });
98
+
99
+ // GOOD — awaited in async handler
100
+ app.get('/data', async (req, res) => {
101
+ const data = await loadData();
102
+ res.json(data);
103
+ });
104
+ ```
105
+
106
+ ### Rule 5: No CPU-Blocking Operations on the Event Loop
107
+
108
+ Operations that block the event loop starve all other concurrent requests:
109
+ - `JSON.parse` / `JSON.stringify` on payloads > 1MB → use streaming
110
+ - Synchronous file reads in hot paths → use `fs.promises.*`
111
+ - CPU-intensive loops → offload to worker threads
112
+ - Synchronous crypto operations → use `crypto.subtle` or async equivalents
113
+
114
+ ```typescript
115
+ // BAD — blocks event loop for large payload
116
+ app.post('/import', (req, res) => {
117
+ const data = JSON.parse(req.body.payload); // synchronous, large payload blocks
118
+ });
119
+
120
+ // GOOD — streaming parse
121
+ import { pipeline } from 'stream/promises';
122
+ app.post('/import', async (req, res) => {
123
+ await pipeline(req, new JSONStreamParser(), new DataProcessor());
124
+ });
125
+ ```
126
+
127
+ ### Rule 6: Batch Async Operations with Controlled Concurrency
128
+
129
+ Running N async operations at once can overwhelm downstream services. Use a concurrency limiter:
130
+
131
+ ```typescript
132
+ // BAD — 1000 parallel requests to an API
133
+ await Promise.all(items.map(item => processItem(item)));
134
+
135
+ // GOOD — max 10 concurrent operations
136
+ import PLimit from 'p-limit';
137
+ const limit = PLimit(10);
138
+ await Promise.all(items.map(item => limit(() => processItem(item))));
139
+ ```
140
+
141
+ ### Rule 7: Async Initialization Pattern
142
+
143
+ Classes with async setup must not use the constructor for initialization:
144
+
145
+ ```typescript
146
+ // BAD — constructor cannot be async
147
+ class DatabasePool {
148
+ constructor() {
149
+ this.pool = await createPool(); // syntax error
150
+ }
151
+ }
152
+
153
+ // GOOD — factory method pattern
154
+ class DatabasePool {
155
+ private constructor(private readonly pool: Pool) {}
156
+
157
+ static async create(): Promise<DatabasePool> {
158
+ const pool = await createPool();
159
+ return new DatabasePool(pool);
160
+ }
161
+ }
162
+ const db = await DatabasePool.create();
163
+ ```
164
+
165
+ ---
166
+
167
+ ## Iron Laws
168
+
169
+ **IRON LAW 1: Sequential await for independent operations is a performance bug. Use Promise.all.**
170
+ **IRON LAW 2: Every external HTTP call must have an explicit timeout configured.**
171
+ **IRON LAW 3: A floating promise (not awaited, no .catch) is an unhandled rejection waiting to crash the process.**
172
+
173
+ ---
174
+
175
+ ## Red Flags — Stop and re-read this rule if you are thinking:
176
+
177
+ | Rationalization | Why it's wrong |
178
+ |---|---|
179
+ | "I'll add a timeout later if it's needed" | Missing timeouts are invisible until a downstream service hangs — add them when the call is written |
180
+ | "The operation is fast, sequential await is fine" | Sequential operations that are "fast" become bottlenecks under load |
181
+ | "I don't need to await this, it's just a side effect" | Fire-and-forget without `.catch` silently loses errors that may indicate data corruption |
182
+ | "Promise.allSettled is verbose, I'll use Promise.all and handle errors in each function" | Promise.all cancels all operations on first rejection — allSettled gives you full control |
183
+ | "Concurrency limiting adds complexity" | Uncontrolled concurrency causes rate limit errors, OOM, and cascading failures downstream |
184
+
185
+ **IRON LAW: AN ASYNC FUNCTION THAT CAN HANG INDEFINITELY IS A DENIAL-OF-SERVICE VULNERABILITY.**