@heyai-rules/pilo-masterkit 1.2.2 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (709) hide show
  1. package/.agent/agents/PILO_MASTER.md +77 -77
  2. package/.agent/agents/backend-specialist.md +263 -263
  3. package/.agent/agents/code-archaeologist.md +106 -106
  4. package/.agent/agents/csharp-reviewer.md +101 -0
  5. package/.agent/agents/dart-build-resolver.md +201 -0
  6. package/.agent/agents/database-architect.md +226 -226
  7. package/.agent/agents/debugger.md +225 -225
  8. package/.agent/agents/devops-engineer.md +242 -242
  9. package/.agent/agents/documentation-writer.md +104 -104
  10. package/.agent/agents/explorer-agent.md +73 -73
  11. package/.agent/agents/frontend-specialist.md +593 -593
  12. package/.agent/agents/game-developer.md +162 -162
  13. package/.agent/agents/gan-evaluator.md +209 -0
  14. package/.agent/agents/gan-generator.md +131 -0
  15. package/.agent/agents/gan-planner.md +99 -0
  16. package/.agent/agents/healthcare-reviewer.md +83 -0
  17. package/.agent/agents/mobile-developer.md +377 -377
  18. package/.agent/agents/opensource-forker.md +198 -0
  19. package/.agent/agents/opensource-packager.md +249 -0
  20. package/.agent/agents/opensource-sanitizer.md +188 -0
  21. package/.agent/agents/orchestrator.md +416 -416
  22. package/.agent/agents/penetration-tester.md +188 -188
  23. package/.agent/agents/performance-optimizer.md +446 -187
  24. package/.agent/agents/personas/athena-agent/agent.json +10 -0
  25. package/.agent/agents/personas/athena-agent/athena-backend-logic-architecture-profile.md +189 -0
  26. package/.agent/agents/personas/athena-agent/context-files/agents.md +55 -0
  27. package/.agent/agents/personas/athena-agent/context-files/identity.md +23 -0
  28. package/.agent/agents/personas/athena-agent/context-files/soul.md +51 -0
  29. package/.agent/agents/personas/athena-agent/context-files/user-predefined.md +15 -0
  30. package/.agent/agents/personas/athena-agent/user-context-files/system/bootstrap.md +37 -0
  31. package/.agent/agents/personas/athena-agent/user-context-files/system/user.md +45 -0
  32. package/.agent/agents/personas/da-vinci-agent/agent.json +10 -0
  33. package/.agent/agents/personas/da-vinci-agent/context-files/agents.md +55 -0
  34. package/.agent/agents/personas/da-vinci-agent/context-files/identity.md +23 -0
  35. package/.agent/agents/personas/da-vinci-agent/context-files/soul.md +51 -0
  36. package/.agent/agents/personas/da-vinci-agent/context-files/user-predefined.md +15 -0
  37. package/.agent/agents/personas/da-vinci-agent/da-vinci-frontend-ui-ux-design-profile.md +189 -0
  38. package/.agent/agents/personas/da-vinci-agent/user-context-files/system/bootstrap.md +37 -0
  39. package/.agent/agents/personas/da-vinci-agent/user-context-files/system/user.md +45 -0
  40. package/.agent/agents/personas/duong-tang-agent/agent.json +10 -0
  41. package/.agent/agents/personas/duong-tang-agent/context-files/agents.md +55 -0
  42. package/.agent/agents/personas/duong-tang-agent/context-files/identity.md +23 -0
  43. package/.agent/agents/personas/duong-tang-agent/context-files/soul.md +51 -0
  44. package/.agent/agents/personas/duong-tang-agent/context-files/user-predefined.md +15 -0
  45. package/.agent/agents/personas/duong-tang-agent/tang-monk-quality-testing-documentation-profile.md +189 -0
  46. package/.agent/agents/personas/duong-tang-agent/user-context-files/system/bootstrap.md +37 -0
  47. package/.agent/agents/personas/duong-tang-agent/user-context-files/system/user.md +45 -0
  48. package/.agent/agents/personas/gia-cat-luong-agent/agent.json +10 -0
  49. package/.agent/agents/personas/gia-cat-luong-agent/context-files/agents.md +55 -0
  50. package/.agent/agents/personas/gia-cat-luong-agent/context-files/identity.md +23 -0
  51. package/.agent/agents/personas/gia-cat-luong-agent/context-files/soul.md +51 -0
  52. package/.agent/agents/personas/gia-cat-luong-agent/context-files/user-predefined.md +15 -0
  53. package/.agent/agents/personas/gia-cat-luong-agent/kongming-research-strategy-analysis-profile.md +189 -0
  54. package/.agent/agents/personas/gia-cat-luong-agent/user-context-files/system/bootstrap.md +37 -0
  55. package/.agent/agents/personas/gia-cat-luong-agent/user-context-files/system/user.md +45 -0
  56. package/.agent/agents/personas/mihata-agent/agent.json +10 -0
  57. package/.agent/agents/personas/mihata-agent/context-files/agents.md +55 -0
  58. package/.agent/agents/personas/mihata-agent/context-files/identity.md +23 -0
  59. package/.agent/agents/personas/mihata-agent/context-files/soul.md +51 -0
  60. package/.agent/agents/personas/mihata-agent/context-files/user-predefined.md +15 -0
  61. package/.agent/agents/personas/mihata-agent/mihata-multi-agent-orchestration-profile.md +189 -0
  62. package/.agent/agents/personas/mihata-agent/user-context-files/system/bootstrap.md +37 -0
  63. package/.agent/agents/personas/mihata-agent/user-context-files/system/user.md +45 -0
  64. package/.agent/agents/personas/tesla-agent/agent.json +10 -0
  65. package/.agent/agents/personas/tesla-agent/context-files/agents.md +55 -0
  66. package/.agent/agents/personas/tesla-agent/context-files/identity.md +23 -0
  67. package/.agent/agents/personas/tesla-agent/context-files/soul.md +51 -0
  68. package/.agent/agents/personas/tesla-agent/context-files/user-predefined.md +15 -0
  69. package/.agent/agents/personas/tesla-agent/tesla-fullstack-system-optimization-profile.md +189 -0
  70. package/.agent/agents/personas/tesla-agent/user-context-files/system/bootstrap.md +37 -0
  71. package/.agent/agents/personas/tesla-agent/user-context-files/system/user.md +45 -0
  72. package/.agent/agents/personas/tu-ma-y-agent/agent.json +10 -0
  73. package/.agent/agents/personas/tu-ma-y-agent/context-files/agents.md +55 -0
  74. package/.agent/agents/personas/tu-ma-y-agent/context-files/identity.md +23 -0
  75. package/.agent/agents/personas/tu-ma-y-agent/context-files/soul.md +51 -0
  76. package/.agent/agents/personas/tu-ma-y-agent/context-files/user-predefined.md +15 -0
  77. package/.agent/agents/personas/tu-ma-y-agent/simayi-feasibility-risk-control-profile.md +189 -0
  78. package/.agent/agents/personas/tu-ma-y-agent/user-context-files/system/bootstrap.md +37 -0
  79. package/.agent/agents/personas/tu-ma-y-agent/user-context-files/system/user.md +45 -0
  80. package/.agent/agents/personas/venti-agent/agent.json +10 -0
  81. package/.agent/agents/personas/venti-agent/context-files/agents.md +55 -0
  82. package/.agent/agents/personas/venti-agent/context-files/identity.md +23 -0
  83. package/.agent/agents/personas/venti-agent/context-files/soul.md +51 -0
  84. package/.agent/agents/personas/venti-agent/context-files/user-predefined.md +15 -0
  85. package/.agent/agents/personas/venti-agent/user-context-files/system/bootstrap.md +37 -0
  86. package/.agent/agents/personas/venti-agent/user-context-files/system/user.md +45 -0
  87. package/.agent/agents/personas/venti-agent/venti-learning-communication-mentoring-profile.md +189 -0
  88. package/.agent/agents/product-manager.md +112 -112
  89. package/.agent/agents/product-owner.md +95 -95
  90. package/.agent/agents/project-planner.md +406 -406
  91. package/.agent/agents/qa-automation-engineer.md +103 -103
  92. package/.agent/agents/security-auditor.md +170 -170
  93. package/.agent/agents/seo-specialist.md +111 -111
  94. package/.agent/agents/test-engineer.md +158 -158
  95. package/.agent/contexts/dev.md +20 -0
  96. package/.agent/contexts/research.md +26 -0
  97. package/.agent/contexts/review.md +22 -0
  98. package/.agent/hooks/hooks.json +395 -0
  99. package/.agent/hooks/readme.md +222 -0
  100. package/.agent/mcp-configs/mcp-servers.json +181 -0
  101. package/.agent/rules/ARCHITECTURAL_BLUEPRINTS.md +62 -62
  102. package/.agent/rules/CODE_CRAFTSMANSHIP.md +69 -69
  103. package/.agent/rules/CORE_RULES.md +72 -72
  104. package/.agent/rules/PROJECT_MAP.md +58 -58
  105. package/.agent/rules/QUALITY_ASSURANCE.md +54 -54
  106. package/.agent/rules/SECURITY_ARMOR.md +44 -44
  107. package/.agent/rules/VERSION_ORCHESTRATION.md +64 -64
  108. package/.agent/rules/WORKFLOW_ORCHESTRATION.md +55 -55
  109. package/.agent/rules/common/agents.md +50 -0
  110. package/.agent/rules/common/code-review.md +124 -0
  111. package/.agent/rules/common/coding-style.md +48 -0
  112. package/.agent/rules/common/development-workflow.md +44 -0
  113. package/.agent/rules/common/git-workflow.md +24 -0
  114. package/.agent/rules/common/hooks.md +30 -0
  115. package/.agent/rules/common/patterns.md +31 -0
  116. package/.agent/rules/common/performance.md +55 -0
  117. package/.agent/rules/common/security.md +29 -0
  118. package/.agent/rules/common/testing.md +29 -0
  119. package/.agent/rules/cpp/coding-style.md +44 -0
  120. package/.agent/rules/cpp/hooks.md +39 -0
  121. package/.agent/rules/cpp/patterns.md +51 -0
  122. package/.agent/rules/cpp/security.md +51 -0
  123. package/.agent/rules/cpp/testing.md +44 -0
  124. package/.agent/rules/csharp/coding-style.md +72 -0
  125. package/.agent/rules/csharp/hooks.md +25 -0
  126. package/.agent/rules/csharp/patterns.md +50 -0
  127. package/.agent/rules/csharp/security.md +58 -0
  128. package/.agent/rules/csharp/testing.md +46 -0
  129. package/.agent/rules/dart/coding-style.md +159 -0
  130. package/.agent/rules/dart/hooks.md +66 -0
  131. package/.agent/rules/dart/patterns.md +261 -0
  132. package/.agent/rules/dart/security.md +135 -0
  133. package/.agent/rules/dart/testing.md +215 -0
  134. package/.agent/rules/golang/coding-style.md +32 -0
  135. package/.agent/rules/golang/hooks.md +17 -0
  136. package/.agent/rules/golang/patterns.md +45 -0
  137. package/.agent/rules/golang/security.md +34 -0
  138. package/.agent/rules/golang/testing.md +31 -0
  139. package/.agent/rules/java/coding-style.md +114 -0
  140. package/.agent/rules/java/hooks.md +18 -0
  141. package/.agent/rules/java/patterns.md +146 -0
  142. package/.agent/rules/java/security.md +100 -0
  143. package/.agent/rules/java/testing.md +131 -0
  144. package/.agent/rules/kotlin/coding-style.md +86 -0
  145. package/.agent/rules/kotlin/hooks.md +17 -0
  146. package/.agent/rules/kotlin/patterns.md +146 -0
  147. package/.agent/rules/kotlin/security.md +82 -0
  148. package/.agent/rules/kotlin/testing.md +128 -0
  149. package/.agent/rules/perl/coding-style.md +46 -0
  150. package/.agent/rules/perl/hooks.md +22 -0
  151. package/.agent/rules/perl/patterns.md +76 -0
  152. package/.agent/rules/perl/security.md +69 -0
  153. package/.agent/rules/perl/testing.md +54 -0
  154. package/.agent/rules/php/coding-style.md +40 -0
  155. package/.agent/rules/php/hooks.md +24 -0
  156. package/.agent/rules/php/patterns.md +33 -0
  157. package/.agent/rules/php/security.md +37 -0
  158. package/.agent/rules/php/testing.md +39 -0
  159. package/.agent/rules/python/coding-style.md +42 -0
  160. package/.agent/rules/python/hooks.md +19 -0
  161. package/.agent/rules/python/patterns.md +39 -0
  162. package/.agent/rules/python/security.md +30 -0
  163. package/.agent/rules/python/testing.md +38 -0
  164. package/.agent/rules/readme.md +111 -0
  165. package/.agent/rules/rust/coding-style.md +151 -0
  166. package/.agent/rules/rust/hooks.md +16 -0
  167. package/.agent/rules/rust/patterns.md +168 -0
  168. package/.agent/rules/rust/security.md +141 -0
  169. package/.agent/rules/rust/testing.md +154 -0
  170. package/.agent/rules/swift/coding-style.md +47 -0
  171. package/.agent/rules/swift/hooks.md +20 -0
  172. package/.agent/rules/swift/patterns.md +66 -0
  173. package/.agent/rules/swift/security.md +33 -0
  174. package/.agent/rules/swift/testing.md +45 -0
  175. package/.agent/rules/typescript/coding-style.md +199 -0
  176. package/.agent/rules/typescript/hooks.md +22 -0
  177. package/.agent/rules/typescript/patterns.md +52 -0
  178. package/.agent/rules/typescript/security.md +28 -0
  179. package/.agent/rules/typescript/testing.md +18 -0
  180. package/.agent/rules/web/coding-style.md +96 -0
  181. package/.agent/rules/web/design-quality.md +63 -0
  182. package/.agent/rules/web/hooks.md +120 -0
  183. package/.agent/rules/web/patterns.md +79 -0
  184. package/.agent/rules/web/performance.md +64 -0
  185. package/.agent/rules/web/security.md +57 -0
  186. package/.agent/rules/web/testing.md +55 -0
  187. package/.agent/rules/zh/agents.md +50 -0
  188. package/.agent/rules/zh/code-review.md +124 -0
  189. package/.agent/rules/zh/coding-style.md +48 -0
  190. package/.agent/rules/zh/development-workflow.md +44 -0
  191. package/.agent/rules/zh/git-workflow.md +24 -0
  192. package/.agent/rules/zh/hooks.md +30 -0
  193. package/.agent/rules/zh/patterns.md +31 -0
  194. package/.agent/rules/zh/performance.md +55 -0
  195. package/.agent/rules/zh/readme.md +108 -0
  196. package/.agent/rules/zh/security.md +29 -0
  197. package/.agent/rules/zh/testing.md +29 -0
  198. package/.agent/scripts/auto_preview.py +148 -148
  199. package/.agent/scripts/checklist.py +217 -217
  200. package/.agent/scripts/session_manager.py +120 -120
  201. package/.agent/scripts/verify_all.py +327 -327
  202. package/.agent/skills/agent-eval/SKILL.md +145 -0
  203. package/.agent/skills/agent-harness-construction/SKILL.md +73 -0
  204. package/.agent/skills/agent-payment-x402/SKILL.md +178 -0
  205. package/.agent/skills/agentic-engineering/SKILL.md +63 -0
  206. package/.agent/skills/ai-first-engineering/SKILL.md +51 -0
  207. package/.agent/skills/ai-regression-testing/SKILL.md +385 -0
  208. package/.agent/skills/android-clean-architecture/SKILL.md +339 -0
  209. package/.agent/skills/api-design/SKILL.md +523 -0
  210. package/.agent/skills/api-patterns/SKILL.md +81 -81
  211. package/.agent/skills/api-patterns/api-style.md +42 -42
  212. package/.agent/skills/api-patterns/auth.md +24 -24
  213. package/.agent/skills/api-patterns/documentation.md +26 -26
  214. package/.agent/skills/api-patterns/graphql.md +41 -41
  215. package/.agent/skills/api-patterns/rate-limiting.md +31 -31
  216. package/.agent/skills/api-patterns/response.md +37 -37
  217. package/.agent/skills/api-patterns/rest.md +40 -40
  218. package/.agent/skills/api-patterns/scripts/api_validator.py +211 -211
  219. package/.agent/skills/api-patterns/security-testing.md +122 -122
  220. package/.agent/skills/api-patterns/trpc.md +41 -41
  221. package/.agent/skills/api-patterns/versioning.md +22 -22
  222. package/.agent/skills/app-builder/SKILL.md +75 -75
  223. package/.agent/skills/app-builder/agent-coordination.md +71 -71
  224. package/.agent/skills/app-builder/feature-building.md +53 -53
  225. package/.agent/skills/app-builder/project-detection.md +34 -34
  226. package/.agent/skills/app-builder/scaffolding.md +118 -118
  227. package/.agent/skills/app-builder/tech-stack.md +41 -41
  228. package/.agent/skills/app-builder/templates/SKILL.md +39 -39
  229. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -76
  230. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -92
  231. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -88
  232. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -88
  233. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -83
  234. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -90
  235. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -90
  236. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -122
  237. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -122
  238. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -169
  239. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -134
  240. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -83
  241. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -119
  242. package/.agent/skills/architecture/SKILL.md +55 -55
  243. package/.agent/skills/architecture/context-discovery.md +43 -43
  244. package/.agent/skills/architecture/examples.md +94 -94
  245. package/.agent/skills/architecture/pattern-selection.md +68 -68
  246. package/.agent/skills/architecture/patterns-reference.md +50 -50
  247. package/.agent/skills/architecture/trade-off-analysis.md +77 -77
  248. package/.agent/skills/architecture-decision-records/SKILL.md +179 -0
  249. package/.agent/skills/article-writing/SKILL.md +79 -0
  250. package/.agent/skills/autonomous-agent-harness/SKILL.md +267 -0
  251. package/.agent/skills/autonomous-loops/SKILL.md +610 -0
  252. package/.agent/skills/backend-patterns/SKILL.md +598 -0
  253. package/.agent/skills/bash-linux/SKILL.md +199 -199
  254. package/.agent/skills/behavioral-modes/SKILL.md +242 -242
  255. package/.agent/skills/benchmark/SKILL.md +93 -0
  256. package/.agent/skills/blueprint/SKILL.md +105 -0
  257. package/.agent/skills/brainstorming/SKILL.md +163 -163
  258. package/.agent/skills/brainstorming/dynamic-questioning.md +350 -350
  259. package/.agent/skills/brand-voice/SKILL.md +97 -0
  260. package/.agent/skills/brand-voice/references/voice-profile-schema.md +55 -0
  261. package/.agent/skills/browser-qa/SKILL.md +87 -0
  262. package/.agent/skills/bun-runtime/SKILL.md +84 -0
  263. package/.agent/skills/canary-watch/SKILL.md +99 -0
  264. package/.agent/skills/carrier-relationship-management/SKILL.md +212 -0
  265. package/.agent/skills/ck/SKILL.md +147 -0
  266. package/.agent/skills/ck/commands/forget.mjs +44 -0
  267. package/.agent/skills/ck/commands/info.mjs +24 -0
  268. package/.agent/skills/ck/commands/init.mjs +143 -0
  269. package/.agent/skills/ck/commands/list.mjs +40 -0
  270. package/.agent/skills/ck/commands/migrate.mjs +202 -0
  271. package/.agent/skills/ck/commands/resume.mjs +36 -0
  272. package/.agent/skills/ck/commands/save.mjs +210 -0
  273. package/.agent/skills/ck/commands/shared.mjs +387 -0
  274. package/.agent/skills/ck/hooks/session-start.mjs +224 -0
  275. package/.agent/skills/claude-api/SKILL.md +337 -0
  276. package/.agent/skills/claude-devfleet/SKILL.md +103 -0
  277. package/.agent/skills/clean-code/SKILL.md +201 -201
  278. package/.agent/skills/click-path-audit/SKILL.md +244 -0
  279. package/.agent/skills/clickhouse-io/SKILL.md +439 -0
  280. package/.agent/skills/code-review-checklist/SKILL.md +109 -109
  281. package/.agent/skills/codebase-onboarding/SKILL.md +233 -0
  282. package/.agent/skills/coding-standards/SKILL.md +530 -0
  283. package/.agent/skills/compose-multiplatform-patterns/SKILL.md +299 -0
  284. package/.agent/skills/configure-ecc/SKILL.md +367 -0
  285. package/.agent/skills/connections-optimizer/SKILL.md +189 -0
  286. package/.agent/skills/content-engine/SKILL.md +131 -0
  287. package/.agent/skills/content-hash-cache-pattern/SKILL.md +161 -0
  288. package/.agent/skills/context-budget/SKILL.md +135 -0
  289. package/.agent/skills/continuous-agent-loop/SKILL.md +45 -0
  290. package/.agent/skills/continuous-learning/SKILL.md +119 -0
  291. package/.agent/skills/continuous-learning/config.json +18 -0
  292. package/.agent/skills/continuous-learning/evaluate-session.sh +69 -0
  293. package/.agent/skills/continuous-learning-v2/SKILL.md +365 -0
  294. package/.agent/skills/continuous-learning-v2/agents/observer-loop.sh +271 -0
  295. package/.agent/skills/continuous-learning-v2/agents/observer.md +198 -0
  296. package/.agent/skills/continuous-learning-v2/agents/session-guardian.sh +150 -0
  297. package/.agent/skills/continuous-learning-v2/agents/start-observer.sh +244 -0
  298. package/.agent/skills/continuous-learning-v2/config.json +8 -0
  299. package/.agent/skills/continuous-learning-v2/hooks/observe.sh +428 -0
  300. package/.agent/skills/continuous-learning-v2/scripts/detect-project.sh +228 -0
  301. package/.agent/skills/continuous-learning-v2/scripts/instinct-cli.py +1426 -0
  302. package/.agent/skills/continuous-learning-v2/scripts/test-parse-instinct.py +984 -0
  303. package/.agent/skills/cost-aware-llm-pipeline/SKILL.md +183 -0
  304. package/.agent/skills/cpp-coding-standards/SKILL.md +723 -0
  305. package/.agent/skills/cpp-testing/SKILL.md +324 -0
  306. package/.agent/skills/crosspost/SKILL.md +111 -0
  307. package/.agent/skills/csharp-testing/SKILL.md +321 -0
  308. package/.agent/skills/customer-billing-ops/SKILL.md +140 -0
  309. package/.agent/skills/customs-trade-compliance/SKILL.md +263 -0
  310. package/.agent/skills/dart-flutter-patterns/SKILL.md +563 -0
  311. package/.agent/skills/data-scraper-agent/SKILL.md +764 -0
  312. package/.agent/skills/database-design/SKILL.md +52 -52
  313. package/.agent/skills/database-design/database-selection.md +43 -43
  314. package/.agent/skills/database-design/indexing.md +39 -39
  315. package/.agent/skills/database-design/migrations.md +48 -48
  316. package/.agent/skills/database-design/optimization.md +36 -36
  317. package/.agent/skills/database-design/orm-selection.md +30 -30
  318. package/.agent/skills/database-design/schema-design.md +56 -56
  319. package/.agent/skills/database-design/scripts/schema_validator.py +172 -172
  320. package/.agent/skills/database-migrations/SKILL.md +429 -0
  321. package/.agent/skills/deep-research/SKILL.md +155 -0
  322. package/.agent/skills/deployment-patterns/SKILL.md +427 -0
  323. package/.agent/skills/deployment-procedures/SKILL.md +241 -241
  324. package/.agent/skills/design-system/SKILL.md +82 -0
  325. package/.agent/skills/django-patterns/SKILL.md +734 -0
  326. package/.agent/skills/django-security/SKILL.md +593 -0
  327. package/.agent/skills/django-tdd/SKILL.md +729 -0
  328. package/.agent/skills/django-verification/SKILL.md +469 -0
  329. package/.agent/skills/dmux-workflows/SKILL.md +191 -0
  330. package/.agent/skills/doc.md +177 -177
  331. package/.agent/skills/docker-patterns/SKILL.md +364 -0
  332. package/.agent/skills/documentation-lookup/SKILL.md +90 -0
  333. package/.agent/skills/documentation-templates/SKILL.md +194 -194
  334. package/.agent/skills/dotnet-patterns/SKILL.md +321 -0
  335. package/.agent/skills/e2e-testing/SKILL.md +326 -0
  336. package/.agent/skills/energy-procurement/SKILL.md +228 -0
  337. package/.agent/skills/enterprise-agent-ops/SKILL.md +50 -0
  338. package/.agent/skills/eval-harness/SKILL.md +270 -0
  339. package/.agent/skills/exa-search/SKILL.md +103 -0
  340. package/.agent/skills/fal-ai-media/SKILL.md +284 -0
  341. package/.agent/skills/flutter-dart-code-review/SKILL.md +435 -0
  342. package/.agent/skills/foundation-models-on-device/SKILL.md +243 -0
  343. package/.agent/skills/frontend-design/SKILL.md +452 -452
  344. package/.agent/skills/frontend-design/animation-guide.md +331 -331
  345. package/.agent/skills/frontend-design/color-system.md +311 -311
  346. package/.agent/skills/frontend-design/decision-trees.md +418 -418
  347. package/.agent/skills/frontend-design/motion-graphics.md +306 -306
  348. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -183
  349. package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -722
  350. package/.agent/skills/frontend-design/typography-system.md +345 -345
  351. package/.agent/skills/frontend-design/ux-psychology.md +1116 -1116
  352. package/.agent/skills/frontend-design/visual-effects.md +383 -383
  353. package/.agent/skills/frontend-patterns/SKILL.md +642 -0
  354. package/.agent/skills/frontend-slides/SKILL.md +184 -0
  355. package/.agent/skills/frontend-slides/style-presets.md +330 -0
  356. package/.agent/skills/game-development/2d-games/SKILL.md +119 -119
  357. package/.agent/skills/game-development/3d-games/SKILL.md +135 -135
  358. package/.agent/skills/game-development/SKILL.md +167 -167
  359. package/.agent/skills/game-development/game-art/SKILL.md +185 -185
  360. package/.agent/skills/game-development/game-audio/SKILL.md +190 -190
  361. package/.agent/skills/game-development/game-design/SKILL.md +129 -129
  362. package/.agent/skills/game-development/mobile-games/SKILL.md +108 -108
  363. package/.agent/skills/game-development/multiplayer/SKILL.md +132 -132
  364. package/.agent/skills/game-development/pc-games/SKILL.md +144 -144
  365. package/.agent/skills/game-development/vr-ar/SKILL.md +123 -123
  366. package/.agent/skills/game-development/web-games/SKILL.md +150 -150
  367. package/.agent/skills/gan-style-harness/SKILL.md +278 -0
  368. package/.agent/skills/geo-fundamentals/SKILL.md +156 -156
  369. package/.agent/skills/geo-fundamentals/scripts/geo_checker.py +289 -289
  370. package/.agent/skills/git-workflow/SKILL.md +715 -0
  371. package/.agent/skills/golang-patterns/SKILL.md +674 -0
  372. package/.agent/skills/golang-testing/SKILL.md +720 -0
  373. package/.agent/skills/google-workspace-ops/SKILL.md +95 -0
  374. package/.agent/skills/healthcare-cdss-patterns/SKILL.md +245 -0
  375. package/.agent/skills/healthcare-emr-patterns/SKILL.md +159 -0
  376. package/.agent/skills/healthcare-eval-harness/SKILL.md +207 -0
  377. package/.agent/skills/healthcare-phi-compliance/SKILL.md +145 -0
  378. package/.agent/skills/hexagonal-architecture/SKILL.md +276 -0
  379. package/.agent/skills/i18n-localization/SKILL.md +154 -154
  380. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -241
  381. package/.agent/skills/intelligent-routing/SKILL.md +335 -335
  382. package/.agent/skills/inventory-demand-planning/SKILL.md +247 -0
  383. package/.agent/skills/investor-materials/SKILL.md +96 -0
  384. package/.agent/skills/investor-outreach/SKILL.md +91 -0
  385. package/.agent/skills/iterative-retrieval/SKILL.md +211 -0
  386. package/.agent/skills/java-coding-standards/SKILL.md +147 -0
  387. package/.agent/skills/jira-integration/SKILL.md +293 -0
  388. package/.agent/skills/jpa-patterns/SKILL.md +151 -0
  389. package/.agent/skills/kotlin-coroutines-flows/SKILL.md +284 -0
  390. package/.agent/skills/kotlin-exposed-patterns/SKILL.md +719 -0
  391. package/.agent/skills/kotlin-ktor-patterns/SKILL.md +689 -0
  392. package/.agent/skills/kotlin-patterns/SKILL.md +711 -0
  393. package/.agent/skills/kotlin-testing/SKILL.md +824 -0
  394. package/.agent/skills/laravel-patterns/SKILL.md +415 -0
  395. package/.agent/skills/laravel-plugin-discovery/SKILL.md +229 -0
  396. package/.agent/skills/laravel-security/SKILL.md +285 -0
  397. package/.agent/skills/laravel-tdd/SKILL.md +283 -0
  398. package/.agent/skills/laravel-verification/SKILL.md +179 -0
  399. package/.agent/skills/lead-intelligence/SKILL.md +321 -0
  400. package/.agent/skills/lead-intelligence/agents/enrichment-agent.md +85 -0
  401. package/.agent/skills/lead-intelligence/agents/mutual-mapper.md +75 -0
  402. package/.agent/skills/lead-intelligence/agents/outreach-drafter.md +98 -0
  403. package/.agent/skills/lead-intelligence/agents/signal-scorer.md +60 -0
  404. package/.agent/skills/lint-and-validate/SKILL.md +45 -45
  405. package/.agent/skills/lint-and-validate/scripts/lint_runner.py +184 -184
  406. package/.agent/skills/lint-and-validate/scripts/type_coverage.py +173 -173
  407. package/.agent/skills/liquid-glass-design/SKILL.md +279 -0
  408. package/.agent/skills/logistics-exception-management/SKILL.md +222 -0
  409. package/.agent/skills/manim-video/SKILL.md +89 -0
  410. package/.agent/skills/manim-video/assets/network-graph-scene.py +52 -0
  411. package/.agent/skills/market-research/SKILL.md +75 -0
  412. package/.agent/skills/mcp-builder/SKILL.md +173 -113
  413. package/.agent/skills/mcp-builder/license.txt +202 -0
  414. package/.agent/skills/mcp-builder/reference/evaluation.md +602 -0
  415. package/.agent/skills/mcp-builder/reference/mcp-best-practices.md +249 -0
  416. package/.agent/skills/mcp-builder/reference/node-mcp-server.md +970 -0
  417. package/.agent/skills/mcp-builder/reference/python-mcp-server.md +719 -0
  418. package/.agent/skills/mcp-builder/scripts/connections.py +151 -0
  419. package/.agent/skills/mcp-builder/scripts/evaluation.py +373 -0
  420. package/.agent/skills/mcp-builder/scripts/example-evaluation.xml +22 -0
  421. package/.agent/skills/mcp-builder/scripts/requirements.txt +2 -0
  422. package/.agent/skills/mcp-server-patterns/SKILL.md +67 -0
  423. package/.agent/skills/mobile-design/SKILL.md +394 -394
  424. package/.agent/skills/mobile-design/decision-trees.md +516 -516
  425. package/.agent/skills/mobile-design/mobile-backend.md +491 -491
  426. package/.agent/skills/mobile-design/mobile-color-system.md +420 -420
  427. package/.agent/skills/mobile-design/mobile-debugging.md +122 -122
  428. package/.agent/skills/mobile-design/mobile-design-thinking.md +357 -357
  429. package/.agent/skills/mobile-design/mobile-navigation.md +458 -458
  430. package/.agent/skills/mobile-design/mobile-performance.md +767 -767
  431. package/.agent/skills/mobile-design/mobile-testing.md +356 -356
  432. package/.agent/skills/mobile-design/mobile-typography.md +433 -433
  433. package/.agent/skills/mobile-design/platform-android.md +666 -666
  434. package/.agent/skills/mobile-design/platform-ios.md +561 -561
  435. package/.agent/skills/mobile-design/scripts/mobile_audit.py +670 -670
  436. package/.agent/skills/mobile-design/touch-psychology.md +537 -537
  437. package/.agent/skills/nanoclaw-repl/SKILL.md +33 -0
  438. package/.agent/skills/nestjs-patterns/SKILL.md +230 -0
  439. package/.agent/skills/nextjs-react-expert/1-async-eliminating-waterfalls.md +351 -351
  440. package/.agent/skills/nextjs-react-expert/2-bundle-bundle-size-optimization.md +240 -240
  441. package/.agent/skills/nextjs-react-expert/3-server-server-side-performance.md +490 -490
  442. package/.agent/skills/nextjs-react-expert/4-client-client-side-data-fetching.md +264 -264
  443. package/.agent/skills/nextjs-react-expert/5-rerender-re-render-optimization.md +581 -581
  444. package/.agent/skills/nextjs-react-expert/6-rendering-rendering-performance.md +432 -432
  445. package/.agent/skills/nextjs-react-expert/7-js-javascript-performance.md +684 -684
  446. package/.agent/skills/nextjs-react-expert/8-advanced-advanced-patterns.md +150 -150
  447. package/.agent/skills/nextjs-react-expert/9-cache-components.md +103 -103
  448. package/.agent/skills/nextjs-react-expert/SKILL.md +293 -293
  449. package/.agent/skills/nextjs-react-expert/scripts/convert_rules.py +222 -222
  450. package/.agent/skills/nextjs-react-expert/scripts/react_performance_checker.py +252 -252
  451. package/.agent/skills/nextjs-turbopack/SKILL.md +44 -0
  452. package/.agent/skills/nodejs-best-practices/SKILL.md +333 -333
  453. package/.agent/skills/nutrient-document-processing/SKILL.md +167 -0
  454. package/.agent/skills/nuxt4-patterns/SKILL.md +100 -0
  455. package/.agent/skills/openclaw-persona-forge/SKILL.md +296 -0
  456. package/.agent/skills/openclaw-persona-forge/gacha.py +224 -0
  457. package/.agent/skills/openclaw-persona-forge/gacha.sh +5 -0
  458. package/.agent/skills/openclaw-persona-forge/references/avatar-style.md +124 -0
  459. package/.agent/skills/openclaw-persona-forge/references/boundary-rules.md +53 -0
  460. package/.agent/skills/openclaw-persona-forge/references/error-handling.md +53 -0
  461. package/.agent/skills/openclaw-persona-forge/references/identity-tension.md +48 -0
  462. package/.agent/skills/openclaw-persona-forge/references/naming-system.md +39 -0
  463. package/.agent/skills/openclaw-persona-forge/references/output-template.md +166 -0
  464. package/.agent/skills/opensource-pipeline/SKILL.md +255 -0
  465. package/.agent/skills/parallel-agents/SKILL.md +175 -175
  466. package/.agent/skills/performance-profiling/SKILL.md +143 -143
  467. package/.agent/skills/performance-profiling/scripts/lighthouse_audit.py +76 -76
  468. package/.agent/skills/perl-patterns/SKILL.md +504 -0
  469. package/.agent/skills/perl-security/SKILL.md +503 -0
  470. package/.agent/skills/perl-testing/SKILL.md +475 -0
  471. package/.agent/skills/plan-writing/SKILL.md +152 -152
  472. package/.agent/skills/plankton-code-quality/SKILL.md +236 -0
  473. package/.agent/skills/postgres-patterns/SKILL.md +147 -0
  474. package/.agent/skills/powershell-windows/SKILL.md +167 -167
  475. package/.agent/skills/product-lens/SKILL.md +85 -0
  476. package/.agent/skills/production-scheduling/SKILL.md +238 -0
  477. package/.agent/skills/project-flow-ops/SKILL.md +111 -0
  478. package/.agent/skills/project-guidelines-example/SKILL.md +349 -0
  479. package/.agent/skills/prompt-optimizer/SKILL.md +397 -0
  480. package/.agent/skills/python-patterns/SKILL.md +750 -441
  481. package/.agent/skills/python-testing/SKILL.md +816 -0
  482. package/.agent/skills/pytorch-patterns/SKILL.md +396 -0
  483. package/.agent/skills/quality-nonconformance/SKILL.md +260 -0
  484. package/.agent/skills/ralphinho-rfc-pipeline/SKILL.md +67 -0
  485. package/.agent/skills/red-team-tactics/SKILL.md +199 -199
  486. package/.agent/skills/regex-vs-llm-structured-text/SKILL.md +220 -0
  487. package/.agent/skills/remotion-video-creation/SKILL.md +43 -0
  488. package/.agent/skills/remotion-video-creation/rules/3d.md +86 -0
  489. package/.agent/skills/remotion-video-creation/rules/animations.md +29 -0
  490. package/.agent/skills/remotion-video-creation/rules/assets/charts-bar-chart.tsx +173 -0
  491. package/.agent/skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx +100 -0
  492. package/.agent/skills/remotion-video-creation/rules/assets/text-animations-word-highlight.tsx +108 -0
  493. package/.agent/skills/remotion-video-creation/rules/assets.md +78 -0
  494. package/.agent/skills/remotion-video-creation/rules/audio.md +172 -0
  495. package/.agent/skills/remotion-video-creation/rules/calculate-metadata.md +104 -0
  496. package/.agent/skills/remotion-video-creation/rules/can-decode.md +75 -0
  497. package/.agent/skills/remotion-video-creation/rules/charts.md +58 -0
  498. package/.agent/skills/remotion-video-creation/rules/compositions.md +146 -0
  499. package/.agent/skills/remotion-video-creation/rules/display-captions.md +126 -0
  500. package/.agent/skills/remotion-video-creation/rules/extract-frames.md +229 -0
  501. package/.agent/skills/remotion-video-creation/rules/fonts.md +152 -0
  502. package/.agent/skills/remotion-video-creation/rules/get-audio-duration.md +58 -0
  503. package/.agent/skills/remotion-video-creation/rules/get-video-dimensions.md +68 -0
  504. package/.agent/skills/remotion-video-creation/rules/get-video-duration.md +58 -0
  505. package/.agent/skills/remotion-video-creation/rules/gifs.md +138 -0
  506. package/.agent/skills/remotion-video-creation/rules/images.md +130 -0
  507. package/.agent/skills/remotion-video-creation/rules/import-srt-captions.md +67 -0
  508. package/.agent/skills/remotion-video-creation/rules/lottie.md +67 -0
  509. package/.agent/skills/remotion-video-creation/rules/measuring-dom-nodes.md +34 -0
  510. package/.agent/skills/remotion-video-creation/rules/measuring-text.md +143 -0
  511. package/.agent/skills/remotion-video-creation/rules/sequencing.md +106 -0
  512. package/.agent/skills/remotion-video-creation/rules/tailwind.md +11 -0
  513. package/.agent/skills/remotion-video-creation/rules/text-animations.md +20 -0
  514. package/.agent/skills/remotion-video-creation/rules/timing.md +179 -0
  515. package/.agent/skills/remotion-video-creation/rules/transcribe-captions.md +19 -0
  516. package/.agent/skills/remotion-video-creation/rules/transitions.md +122 -0
  517. package/.agent/skills/remotion-video-creation/rules/trimming.md +52 -0
  518. package/.agent/skills/remotion-video-creation/rules/videos.md +171 -0
  519. package/.agent/skills/repo-scan/SKILL.md +78 -0
  520. package/.agent/skills/returns-reverse-logistics/SKILL.md +240 -0
  521. package/.agent/skills/rules-distill/SKILL.md +264 -0
  522. package/.agent/skills/rules-distill/scripts/scan-rules.sh +58 -0
  523. package/.agent/skills/rules-distill/scripts/scan-skills.sh +129 -0
  524. package/.agent/skills/rust-patterns/SKILL.md +499 -0
  525. package/.agent/skills/rust-pro/SKILL.md +175 -175
  526. package/.agent/skills/rust-testing/SKILL.md +500 -0
  527. package/.agent/skills/safety-guard/SKILL.md +75 -0
  528. package/.agent/skills/santa-method/SKILL.md +306 -0
  529. package/.agent/skills/search-first/SKILL.md +161 -0
  530. package/.agent/skills/security-review/SKILL.md +495 -0
  531. package/.agent/skills/security-review/cloud-infrastructure-security.md +361 -0
  532. package/.agent/skills/security-scan/SKILL.md +165 -0
  533. package/.agent/skills/seo-fundamentals/SKILL.md +129 -129
  534. package/.agent/skills/seo-fundamentals/scripts/seo_checker.py +219 -219
  535. package/.agent/skills/server-management/SKILL.md +161 -161
  536. package/.agent/skills/skill-comply/SKILL.md +58 -0
  537. package/.agent/skills/skill-comply/fixtures/compliant-trace.jsonl +5 -0
  538. package/.agent/skills/skill-comply/fixtures/noncompliant-trace.jsonl +3 -0
  539. package/.agent/skills/skill-comply/fixtures/tdd-spec.yaml +44 -0
  540. package/.agent/skills/skill-comply/prompts/classifier.md +24 -0
  541. package/.agent/skills/skill-comply/prompts/scenario-generator.md +62 -0
  542. package/.agent/skills/skill-comply/prompts/spec-generator.md +42 -0
  543. package/.agent/skills/skill-comply/pyproject.toml +15 -0
  544. package/.agent/skills/skill-comply/scripts/classifier.py +85 -0
  545. package/.agent/skills/skill-comply/scripts/grader.py +122 -0
  546. package/.agent/skills/skill-comply/scripts/init.py +0 -0
  547. package/.agent/skills/skill-comply/scripts/parser.py +107 -0
  548. package/.agent/skills/skill-comply/scripts/report.py +170 -0
  549. package/.agent/skills/skill-comply/scripts/run.py +127 -0
  550. package/.agent/skills/skill-comply/scripts/runner.py +161 -0
  551. package/.agent/skills/skill-comply/scripts/scenario-generator.py +70 -0
  552. package/.agent/skills/skill-comply/scripts/spec-generator.py +72 -0
  553. package/.agent/skills/skill-comply/scripts/utils.py +13 -0
  554. package/.agent/skills/skill-comply/tests/test-grader.py +137 -0
  555. package/.agent/skills/skill-comply/tests/test-parser.py +90 -0
  556. package/.agent/skills/skill-creator/SKILL.md +485 -0
  557. package/.agent/skills/skill-creator/agents/analyzer.md +274 -0
  558. package/.agent/skills/skill-creator/agents/comparator.md +202 -0
  559. package/.agent/skills/skill-creator/agents/grader.md +223 -0
  560. package/.agent/skills/skill-creator/assets/eval-review.html +146 -0
  561. package/.agent/skills/skill-creator/eval-viewer/generate-review.py +471 -0
  562. package/.agent/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  563. package/.agent/skills/skill-creator/license.txt +202 -0
  564. package/.agent/skills/skill-creator/references/schemas.md +430 -0
  565. package/.agent/skills/skill-creator/scripts/aggregate-benchmark.py +401 -0
  566. package/.agent/skills/skill-creator/scripts/generate-report.py +326 -0
  567. package/.agent/skills/skill-creator/scripts/improve-description.py +247 -0
  568. package/.agent/skills/skill-creator/scripts/init.py +0 -0
  569. package/.agent/skills/skill-creator/scripts/package-skill.py +136 -0
  570. package/.agent/skills/skill-creator/scripts/quick-validate.py +103 -0
  571. package/.agent/skills/skill-creator/scripts/run-eval.py +310 -0
  572. package/.agent/skills/skill-creator/scripts/run-loop.py +328 -0
  573. package/.agent/skills/skill-creator/scripts/utils.py +47 -0
  574. package/.agent/skills/skill-stocktake/SKILL.md +193 -0
  575. package/.agent/skills/skill-stocktake/scripts/quick-diff.sh +87 -0
  576. package/.agent/skills/skill-stocktake/scripts/save-results.sh +56 -0
  577. package/.agent/skills/skill-stocktake/scripts/scan.sh +170 -0
  578. package/.agent/skills/social-graph-ranker/SKILL.md +154 -0
  579. package/.agent/skills/springboot-patterns/SKILL.md +314 -0
  580. package/.agent/skills/springboot-security/SKILL.md +272 -0
  581. package/.agent/skills/springboot-tdd/SKILL.md +158 -0
  582. package/.agent/skills/springboot-verification/SKILL.md +231 -0
  583. package/.agent/skills/strategic-compact/SKILL.md +131 -0
  584. package/.agent/skills/strategic-compact/suggest-compact.sh +54 -0
  585. package/.agent/skills/swift-actor-persistence/SKILL.md +143 -0
  586. package/.agent/skills/swift-concurrency-6-2/SKILL.md +216 -0
  587. package/.agent/skills/swift-protocol-di-testing/SKILL.md +190 -0
  588. package/.agent/skills/swiftui-patterns/SKILL.md +259 -0
  589. package/.agent/skills/systematic-debugging/SKILL.md +109 -109
  590. package/.agent/skills/tailwind-patterns/SKILL.md +269 -269
  591. package/.agent/skills/tdd-workflow/SKILL.md +463 -149
  592. package/.agent/skills/team-builder/SKILL.md +168 -0
  593. package/.agent/skills/testing-patterns/SKILL.md +178 -178
  594. package/.agent/skills/testing-patterns/scripts/test_runner.py +219 -219
  595. package/.agent/skills/token-budget-advisor/SKILL.md +133 -0
  596. package/.agent/skills/ui-demo/SKILL.md +465 -0
  597. package/.agent/skills/ui-ux-pro-max/SKILL.md +292 -292
  598. package/.agent/skills/ui-ux-pro-max/data/icons.csv +101 -101
  599. package/.agent/skills/ui-ux-pro-max/data/landing.csv +3 -3
  600. package/.agent/skills/ui-ux-pro-max/data/react-performance.csv +45 -45
  601. package/.agent/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -54
  602. package/.agent/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -53
  603. package/.agent/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -51
  604. package/.agent/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -59
  605. package/.agent/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -61
  606. package/.agent/skills/ui-ux-pro-max/data/typography.csv +57 -57
  607. package/.agent/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -101
  608. package/.agent/skills/ui-ux-pro-max/data/web-interface.csv +31 -31
  609. package/.agent/skills/ui-ux-pro-max/scripts/core.py +253 -253
  610. package/.agent/skills/ui-ux-pro-max/scripts/design_system.py +1067 -1067
  611. package/.agent/skills/verification-loop/SKILL.md +126 -0
  612. package/.agent/skills/video-editing/SKILL.md +310 -0
  613. package/.agent/skills/videodb/SKILL.md +374 -0
  614. package/.agent/skills/videodb/reference/api-reference.md +550 -0
  615. package/.agent/skills/videodb/reference/capture-reference.md +407 -0
  616. package/.agent/skills/videodb/reference/capture.md +101 -0
  617. package/.agent/skills/videodb/reference/editor.md +443 -0
  618. package/.agent/skills/videodb/reference/generative.md +331 -0
  619. package/.agent/skills/videodb/reference/rtstream-reference.md +564 -0
  620. package/.agent/skills/videodb/reference/rtstream.md +65 -0
  621. package/.agent/skills/videodb/reference/search.md +230 -0
  622. package/.agent/skills/videodb/reference/streaming.md +406 -0
  623. package/.agent/skills/videodb/reference/use-cases.md +118 -0
  624. package/.agent/skills/videodb/scripts/ws-listener.py +282 -0
  625. package/.agent/skills/visa-doc-translate/SKILL.md +117 -0
  626. package/.agent/skills/visa-doc-translate/readme.md +86 -0
  627. package/.agent/skills/vulnerability-scanner/SKILL.md +276 -276
  628. package/.agent/skills/vulnerability-scanner/checklists.md +121 -121
  629. package/.agent/skills/vulnerability-scanner/scripts/security_scan.py +458 -458
  630. package/.agent/skills/web-design-guidelines/SKILL.md +57 -57
  631. package/.agent/skills/webapp-testing/SKILL.md +187 -187
  632. package/.agent/skills/webapp-testing/scripts/playwright_runner.py +173 -173
  633. package/.agent/skills/workspace-surface-audit/SKILL.md +125 -0
  634. package/.agent/skills/x-api/SKILL.md +230 -0
  635. package/.agent/tasks/lessons.md +40 -40
  636. package/.agent/tasks/todo.md +33 -33
  637. package/.agent/tasks/two-track-merge-contract.md +29 -0
  638. package/.agent/workflows/aside.md +3 -3
  639. package/.agent/workflows/brainstorm.md +113 -113
  640. package/.agent/workflows/claw.md +13 -41
  641. package/.agent/workflows/clean-memory.md +34 -0
  642. package/.agent/workflows/code-review.md +260 -11
  643. package/.agent/workflows/context-budget.md +12 -18
  644. package/.agent/workflows/cpp-build.md +1 -1
  645. package/.agent/workflows/cpp-review.md +4 -4
  646. package/.agent/workflows/create.md +59 -59
  647. package/.agent/workflows/debug.md +103 -103
  648. package/.agent/workflows/deploy.md +176 -176
  649. package/.agent/workflows/devfleet.md +13 -82
  650. package/.agent/workflows/docs.md +13 -21
  651. package/.agent/workflows/e2e.md +38 -135
  652. package/.agent/workflows/enhance.md +63 -63
  653. package/.agent/workflows/eval.md +15 -112
  654. package/.agent/workflows/flutter-build.md +164 -0
  655. package/.agent/workflows/flutter-review.md +116 -0
  656. package/.agent/workflows/flutter-test.md +144 -0
  657. package/.agent/workflows/gan-build.md +99 -0
  658. package/.agent/workflows/gan-design.md +35 -0
  659. package/.agent/workflows/go-build.md +1 -1
  660. package/.agent/workflows/go-review.md +4 -4
  661. package/.agent/workflows/harness-audit.md +5 -3
  662. package/.agent/workflows/init-docs.md +46 -46
  663. package/.agent/workflows/instinct-import.md +4 -4
  664. package/.agent/workflows/jira.md +106 -0
  665. package/.agent/workflows/kotlin-build.md +1 -1
  666. package/.agent/workflows/kotlin-review.md +5 -5
  667. package/.agent/workflows/learn-eval.md +9 -9
  668. package/.agent/workflows/multi-plan.md +10 -10
  669. package/.agent/workflows/orchestrate.md +23 -119
  670. package/.agent/workflows/plan.md +2 -0
  671. package/.agent/workflows/preview.md +81 -81
  672. package/.agent/workflows/prompt-optimize.md +13 -28
  673. package/.agent/workflows/prp-commit.md +112 -0
  674. package/.agent/workflows/prp-implement.md +385 -0
  675. package/.agent/workflows/prp-plan.md +502 -0
  676. package/.agent/workflows/prp-pr.md +184 -0
  677. package/.agent/workflows/prp-prd.md +447 -0
  678. package/.agent/workflows/python-review.md +5 -5
  679. package/.agent/workflows/refactor-clean.md +1 -1
  680. package/.agent/workflows/resume-session.md +10 -10
  681. package/.agent/workflows/rules-distill.md +14 -5
  682. package/.agent/workflows/santa-loop.md +175 -0
  683. package/.agent/workflows/save-session.md +9 -9
  684. package/.agent/workflows/status.md +86 -86
  685. package/.agent/workflows/tdd.md +30 -127
  686. package/.agent/workflows/test-coverage.md +1 -1
  687. package/.agent/workflows/test.md +144 -144
  688. package/.agent/workflows/ui-ux-pro-max.md +295 -295
  689. package/.agent/workflows/verify.md +15 -51
  690. package/README.md +163 -136
  691. package/RELEASE.md +32 -36
  692. package/SLASH_COMMANDS.md +121 -0
  693. package/package.json +12 -3
  694. package/scripts/release-check.js +1 -1
  695. package/src/bin/cli.js +399 -53
  696. package/src/lib/installer.js +360 -114
  697. package/src/lib/manifests/stacks.js +122 -0
  698. package/src/lib/slash-commands.js +28 -0
  699. package/src/templates/claude/CLAUDE.en.md +42 -0
  700. package/src/templates/claude/CLAUDE.md +42 -0
  701. package/src/templates/claude/CLAUDE.vi.md +42 -0
  702. package/src/templates/codex/AGENTS.en.md +40 -0
  703. package/src/templates/codex/AGENTS.md +40 -0
  704. package/src/templates/codex/AGENTS.vi.md +40 -0
  705. package/src/templates/cursor/pilo-masterkit.mdc +20 -0
  706. package/src/templates/gemini/GEMINI.en.md +56 -0
  707. package/src/templates/gemini/GEMINI.md +56 -0
  708. package/src/templates/gemini/GEMINI.vi.md +56 -0
  709. package/src/templates/github/copilot-instructions.md +16 -0
@@ -1,684 +1,684 @@
1
- # 7. JavaScript Performance
2
-
3
- > **Impact:** LOW-MEDIUM
4
- > **Focus:** Micro-optimizations for hot paths can add up to meaningful improvements.
5
-
6
- ---
7
-
8
- ## Overview
9
-
10
- This section contains **12 rules** focused on javascript performance.
11
-
12
- ---
13
-
14
- ## Rule 7.1: Avoid Layout Thrashing
15
-
16
- **Impact:** MEDIUM
17
- **Tags:** javascript, dom, css, performance, reflow, layout-thrashing
18
-
19
- ## Avoid Layout Thrashing
20
-
21
- Avoid interleaving style writes with layout reads. When you read a layout property (like `offsetWidth`, `getBoundingClientRect()`, or `getComputedStyle()`) between style changes, the browser is forced to trigger a synchronous reflow.
22
-
23
- **This is OK (browser batches style changes):**
24
- ```typescript
25
- function updateElementStyles(element: HTMLElement) {
26
- // Each line invalidates style, but browser batches the recalculation
27
- element.style.width = '100px'
28
- element.style.height = '200px'
29
- element.style.backgroundColor = 'blue'
30
- element.style.border = '1px solid black'
31
- }
32
- ```
33
-
34
- **Incorrect (interleaved reads and writes force reflows):**
35
- ```typescript
36
- function layoutThrashing(element: HTMLElement) {
37
- element.style.width = '100px'
38
- const width = element.offsetWidth // Forces reflow
39
- element.style.height = '200px'
40
- const height = element.offsetHeight // Forces another reflow
41
- }
42
- ```
43
-
44
- **Correct (batch writes, then read once):**
45
- ```typescript
46
- function updateElementStyles(element: HTMLElement) {
47
- // Batch all writes together
48
- element.style.width = '100px'
49
- element.style.height = '200px'
50
- element.style.backgroundColor = 'blue'
51
- element.style.border = '1px solid black'
52
-
53
- // Read after all writes are done (single reflow)
54
- const { width, height } = element.getBoundingClientRect()
55
- }
56
- ```
57
-
58
- **Correct (batch reads, then writes):**
59
- ```typescript
60
- function avoidThrashing(element: HTMLElement) {
61
- // Read phase - all layout queries first
62
- const rect1 = element.getBoundingClientRect()
63
- const offsetWidth = element.offsetWidth
64
- const offsetHeight = element.offsetHeight
65
-
66
- // Write phase - all style changes after
67
- element.style.width = '100px'
68
- element.style.height = '200px'
69
- }
70
- ```
71
-
72
- **Better: use CSS classes**
73
- ```css
74
- .highlighted-box {
75
- width: 100px;
76
- height: 200px;
77
- background-color: blue;
78
- border: 1px solid black;
79
- }
80
- ```
81
- ```typescript
82
- function updateElementStyles(element: HTMLElement) {
83
- element.classList.add('highlighted-box')
84
-
85
- const { width, height } = element.getBoundingClientRect()
86
- }
87
- ```
88
-
89
- **React example:**
90
- ```tsx
91
- // Incorrect: interleaving style changes with layout queries
92
- function Box({ isHighlighted }: { isHighlighted: boolean }) {
93
- const ref = useRef<HTMLDivElement>(null)
94
-
95
- useEffect(() => {
96
- if (ref.current && isHighlighted) {
97
- ref.current.style.width = '100px'
98
- const width = ref.current.offsetWidth // Forces layout
99
- ref.current.style.height = '200px'
100
- }
101
- }, [isHighlighted])
102
-
103
- return <div ref={ref}>Content</div>
104
- }
105
-
106
- // Correct: toggle class
107
- function Box({ isHighlighted }: { isHighlighted: boolean }) {
108
- return (
109
- <div className={isHighlighted ? 'highlighted-box' : ''}>
110
- Content
111
- </div>
112
- )
113
- }
114
- ```
115
-
116
- Prefer CSS classes over inline styles when possible. CSS files are cached by the browser, and classes provide better separation of concerns and are easier to maintain.
117
-
118
- See [this gist](https://gist.github.com/paulirish/5d52fb081b3570c81e3a) and [CSS Triggers](https://csstriggers.com/) for more information on layout-forcing operations.
119
-
120
- ---
121
-
122
- ## Rule 7.2: Build Index Maps for Repeated Lookups
123
-
124
- **Impact:** LOW-MEDIUM
125
- **Tags:** javascript, map, indexing, optimization, performance
126
-
127
- ## Build Index Maps for Repeated Lookups
128
-
129
- Multiple `.find()` calls by the same key should use a Map.
130
-
131
- **Incorrect (O(n) per lookup):**
132
-
133
- ```typescript
134
- function processOrders(orders: Order[], users: User[]) {
135
- return orders.map(order => ({
136
- ...order,
137
- user: users.find(u => u.id === order.userId)
138
- }))
139
- }
140
- ```
141
-
142
- **Correct (O(1) per lookup):**
143
-
144
- ```typescript
145
- function processOrders(orders: Order[], users: User[]) {
146
- const userById = new Map(users.map(u => [u.id, u]))
147
-
148
- return orders.map(order => ({
149
- ...order,
150
- user: userById.get(order.userId)
151
- }))
152
- }
153
- ```
154
-
155
- Build map once (O(n)), then all lookups are O(1).
156
- For 1000 orders × 1000 users: 1M ops → 2K ops.
157
-
158
- ---
159
-
160
- ## Rule 7.3: Cache Property Access in Loops
161
-
162
- **Impact:** LOW-MEDIUM
163
- **Tags:** javascript, loops, optimization, caching
164
-
165
- ## Cache Property Access in Loops
166
-
167
- Cache object property lookups in hot paths.
168
-
169
- **Incorrect (3 lookups × N iterations):**
170
-
171
- ```typescript
172
- for (let i = 0; i < arr.length; i++) {
173
- process(obj.config.settings.value)
174
- }
175
- ```
176
-
177
- **Correct (1 lookup total):**
178
-
179
- ```typescript
180
- const value = obj.config.settings.value
181
- const len = arr.length
182
- for (let i = 0; i < len; i++) {
183
- process(value)
184
- }
185
- ```
186
-
187
- ---
188
-
189
- ## Rule 7.4: Cache Repeated Function Calls
190
-
191
- **Impact:** MEDIUM
192
- **Tags:** javascript, cache, memoization, performance
193
-
194
- ## Cache Repeated Function Calls
195
-
196
- Use a module-level Map to cache function results when the same function is called repeatedly with the same inputs during render.
197
-
198
- **Incorrect (redundant computation):**
199
-
200
- ```typescript
201
- function ProjectList({ projects }: { projects: Project[] }) {
202
- return (
203
- <div>
204
- {projects.map(project => {
205
- // slugify() called 100+ times for same project names
206
- const slug = slugify(project.name)
207
-
208
- return <ProjectCard key={project.id} slug={slug} />
209
- })}
210
- </div>
211
- )
212
- }
213
- ```
214
-
215
- **Correct (cached results):**
216
-
217
- ```typescript
218
- // Module-level cache
219
- const slugifyCache = new Map<string, string>()
220
-
221
- function cachedSlugify(text: string): string {
222
- if (slugifyCache.has(text)) {
223
- return slugifyCache.get(text)!
224
- }
225
- const result = slugify(text)
226
- slugifyCache.set(text, result)
227
- return result
228
- }
229
-
230
- function ProjectList({ projects }: { projects: Project[] }) {
231
- return (
232
- <div>
233
- {projects.map(project => {
234
- // Computed only once per unique project name
235
- const slug = cachedSlugify(project.name)
236
-
237
- return <ProjectCard key={project.id} slug={slug} />
238
- })}
239
- </div>
240
- )
241
- }
242
- ```
243
-
244
- **Simpler pattern for single-value functions:**
245
-
246
- ```typescript
247
- let isLoggedInCache: boolean | null = null
248
-
249
- function isLoggedIn(): boolean {
250
- if (isLoggedInCache !== null) {
251
- return isLoggedInCache
252
- }
253
-
254
- isLoggedInCache = document.cookie.includes('auth=')
255
- return isLoggedInCache
256
- }
257
-
258
- // Clear cache when auth changes
259
- function onAuthChange() {
260
- isLoggedInCache = null
261
- }
262
- ```
263
-
264
- Use a Map (not a hook) so it works everywhere: utilities, event handlers, not just React components.
265
-
266
- Reference: [How we made the Vercel Dashboard twice as fast](https://vercel.com/blog/how-we-made-the-vercel-dashboard-twice-as-fast)
267
-
268
- ---
269
-
270
- ## Rule 7.5: Cache Storage API Calls
271
-
272
- **Impact:** LOW-MEDIUM
273
- **Tags:** javascript, localStorage, storage, caching, performance
274
-
275
- ## Cache Storage API Calls
276
-
277
- `localStorage`, `sessionStorage`, and `document.cookie` are synchronous and expensive. Cache reads in memory.
278
-
279
- **Incorrect (reads storage on every call):**
280
-
281
- ```typescript
282
- function getTheme() {
283
- return localStorage.getItem('theme') ?? 'light'
284
- }
285
- // Called 10 times = 10 storage reads
286
- ```
287
-
288
- **Correct (Map cache):**
289
-
290
- ```typescript
291
- const storageCache = new Map<string, string | null>()
292
-
293
- function getLocalStorage(key: string) {
294
- if (!storageCache.has(key)) {
295
- storageCache.set(key, localStorage.getItem(key))
296
- }
297
- return storageCache.get(key)
298
- }
299
-
300
- function setLocalStorage(key: string, value: string) {
301
- localStorage.setItem(key, value)
302
- storageCache.set(key, value) // keep cache in sync
303
- }
304
- ```
305
-
306
- Use a Map (not a hook) so it works everywhere: utilities, event handlers, not just React components.
307
-
308
- **Cookie caching:**
309
-
310
- ```typescript
311
- let cookieCache: Record<string, string> | null = null
312
-
313
- function getCookie(name: string) {
314
- if (!cookieCache) {
315
- cookieCache = Object.fromEntries(
316
- document.cookie.split('; ').map(c => c.split('='))
317
- )
318
- }
319
- return cookieCache[name]
320
- }
321
- ```
322
-
323
- **Important (invalidate on external changes):**
324
-
325
- If storage can change externally (another tab, server-set cookies), invalidate cache:
326
-
327
- ```typescript
328
- window.addEventListener('storage', (e) => {
329
- if (e.key) storageCache.delete(e.key)
330
- })
331
-
332
- document.addEventListener('visibilitychange', () => {
333
- if (document.visibilityState === 'visible') {
334
- storageCache.clear()
335
- }
336
- })
337
- ```
338
-
339
- ---
340
-
341
- ## Rule 7.6: Combine Multiple Array Iterations
342
-
343
- **Impact:** LOW-MEDIUM
344
- **Tags:** javascript, arrays, loops, performance
345
-
346
- ## Combine Multiple Array Iterations
347
-
348
- Multiple `.filter()` or `.map()` calls iterate the array multiple times. Combine into one loop.
349
-
350
- **Incorrect (3 iterations):**
351
-
352
- ```typescript
353
- const admins = users.filter(u => u.isAdmin)
354
- const testers = users.filter(u => u.isTester)
355
- const inactive = users.filter(u => !u.isActive)
356
- ```
357
-
358
- **Correct (1 iteration):**
359
-
360
- ```typescript
361
- const admins: User[] = []
362
- const testers: User[] = []
363
- const inactive: User[] = []
364
-
365
- for (const user of users) {
366
- if (user.isAdmin) admins.push(user)
367
- if (user.isTester) testers.push(user)
368
- if (!user.isActive) inactive.push(user)
369
- }
370
- ```
371
-
372
- ---
373
-
374
- ## Rule 7.7: Early Length Check for Array Comparisons
375
-
376
- **Impact:** MEDIUM-HIGH
377
- **Tags:** javascript, arrays, performance, optimization, comparison
378
-
379
- ## Early Length Check for Array Comparisons
380
-
381
- When comparing arrays with expensive operations (sorting, deep equality, serialization), check lengths first. If lengths differ, the arrays cannot be equal.
382
-
383
- In real-world applications, this optimization is especially valuable when the comparison runs in hot paths (event handlers, render loops).
384
-
385
- **Incorrect (always runs expensive comparison):**
386
-
387
- ```typescript
388
- function hasChanges(current: string[], original: string[]) {
389
- // Always sorts and joins, even when lengths differ
390
- return current.sort().join() !== original.sort().join()
391
- }
392
- ```
393
-
394
- Two O(n log n) sorts run even when `current.length` is 5 and `original.length` is 100. There is also overhead of joining the arrays and comparing the strings.
395
-
396
- **Correct (O(1) length check first):**
397
-
398
- ```typescript
399
- function hasChanges(current: string[], original: string[]) {
400
- // Early return if lengths differ
401
- if (current.length !== original.length) {
402
- return true
403
- }
404
- // Only sort when lengths match
405
- const currentSorted = current.toSorted()
406
- const originalSorted = original.toSorted()
407
- for (let i = 0; i < currentSorted.length; i++) {
408
- if (currentSorted[i] !== originalSorted[i]) {
409
- return true
410
- }
411
- }
412
- return false
413
- }
414
- ```
415
-
416
- This new approach is more efficient because:
417
- - It avoids the overhead of sorting and joining the arrays when lengths differ
418
- - It avoids consuming memory for the joined strings (especially important for large arrays)
419
- - It avoids mutating the original arrays
420
- - It returns early when a difference is found
421
-
422
- ---
423
-
424
- ## Rule 7.8: Early Return from Functions
425
-
426
- **Impact:** LOW-MEDIUM
427
- **Tags:** javascript, functions, optimization, early-return
428
-
429
- ## Early Return from Functions
430
-
431
- Return early when result is determined to skip unnecessary processing.
432
-
433
- **Incorrect (processes all items even after finding answer):**
434
-
435
- ```typescript
436
- function validateUsers(users: User[]) {
437
- let hasError = false
438
- let errorMessage = ''
439
-
440
- for (const user of users) {
441
- if (!user.email) {
442
- hasError = true
443
- errorMessage = 'Email required'
444
- }
445
- if (!user.name) {
446
- hasError = true
447
- errorMessage = 'Name required'
448
- }
449
- // Continues checking all users even after error found
450
- }
451
-
452
- return hasError ? { valid: false, error: errorMessage } : { valid: true }
453
- }
454
- ```
455
-
456
- **Correct (returns immediately on first error):**
457
-
458
- ```typescript
459
- function validateUsers(users: User[]) {
460
- for (const user of users) {
461
- if (!user.email) {
462
- return { valid: false, error: 'Email required' }
463
- }
464
- if (!user.name) {
465
- return { valid: false, error: 'Name required' }
466
- }
467
- }
468
-
469
- return { valid: true }
470
- }
471
- ```
472
-
473
- ---
474
-
475
- ## Rule 7.9: Hoist RegExp Creation
476
-
477
- **Impact:** LOW-MEDIUM
478
- **Tags:** javascript, regexp, optimization, memoization
479
-
480
- ## Hoist RegExp Creation
481
-
482
- Don't create RegExp inside render. Hoist to module scope or memoize with `useMemo()`.
483
-
484
- **Incorrect (new RegExp every render):**
485
-
486
- ```tsx
487
- function Highlighter({ text, query }: Props) {
488
- const regex = new RegExp(`(${query})`, 'gi')
489
- const parts = text.split(regex)
490
- return <>{parts.map((part, i) => ...)}</>
491
- }
492
- ```
493
-
494
- **Correct (memoize or hoist):**
495
-
496
- ```tsx
497
- const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
498
-
499
- function Highlighter({ text, query }: Props) {
500
- const regex = useMemo(
501
- () => new RegExp(`(${escapeRegex(query)})`, 'gi'),
502
- [query]
503
- )
504
- const parts = text.split(regex)
505
- return <>{parts.map((part, i) => ...)}</>
506
- }
507
- ```
508
-
509
- **Warning (global regex has mutable state):**
510
-
511
- Global regex (`/g`) has mutable `lastIndex` state:
512
-
513
- ```typescript
514
- const regex = /foo/g
515
- regex.test('foo') // true, lastIndex = 3
516
- regex.test('foo') // false, lastIndex = 0
517
- ```
518
-
519
- ---
520
-
521
- ## Rule 7.10: Use Loop for Min/Max Instead of Sort
522
-
523
- **Impact:** LOW
524
- **Tags:** javascript, arrays, performance, sorting, algorithms
525
-
526
- ## Use Loop for Min/Max Instead of Sort
527
-
528
- Finding the smallest or largest element only requires a single pass through the array. Sorting is wasteful and slower.
529
-
530
- **Incorrect (O(n log n) - sort to find latest):**
531
-
532
- ```typescript
533
- interface Project {
534
- id: string
535
- name: string
536
- updatedAt: number
537
- }
538
-
539
- function getLatestProject(projects: Project[]) {
540
- const sorted = [...projects].sort((a, b) => b.updatedAt - a.updatedAt)
541
- return sorted[0]
542
- }
543
- ```
544
-
545
- Sorts the entire array just to find the maximum value.
546
-
547
- **Incorrect (O(n log n) - sort for oldest and newest):**
548
-
549
- ```typescript
550
- function getOldestAndNewest(projects: Project[]) {
551
- const sorted = [...projects].sort((a, b) => a.updatedAt - b.updatedAt)
552
- return { oldest: sorted[0], newest: sorted[sorted.length - 1] }
553
- }
554
- ```
555
-
556
- Still sorts unnecessarily when only min/max are needed.
557
-
558
- **Correct (O(n) - single loop):**
559
-
560
- ```typescript
561
- function getLatestProject(projects: Project[]) {
562
- if (projects.length === 0) return null
563
-
564
- let latest = projects[0]
565
-
566
- for (let i = 1; i < projects.length; i++) {
567
- if (projects[i].updatedAt > latest.updatedAt) {
568
- latest = projects[i]
569
- }
570
- }
571
-
572
- return latest
573
- }
574
-
575
- function getOldestAndNewest(projects: Project[]) {
576
- if (projects.length === 0) return { oldest: null, newest: null }
577
-
578
- let oldest = projects[0]
579
- let newest = projects[0]
580
-
581
- for (let i = 1; i < projects.length; i++) {
582
- if (projects[i].updatedAt < oldest.updatedAt) oldest = projects[i]
583
- if (projects[i].updatedAt > newest.updatedAt) newest = projects[i]
584
- }
585
-
586
- return { oldest, newest }
587
- }
588
- ```
589
-
590
- Single pass through the array, no copying, no sorting.
591
-
592
- **Alternative (Math.min/Math.max for small arrays):**
593
-
594
- ```typescript
595
- const numbers = [5, 2, 8, 1, 9]
596
- const min = Math.min(...numbers)
597
- const max = Math.max(...numbers)
598
- ```
599
-
600
- This works for small arrays, but can be slower or just throw an error for very large arrays due to spread operator limitations. Maximal array length is approximately 124000 in Chrome 143 and 638000 in Safari 18; exact numbers may vary - see [the fiddle](https://jsfiddle.net/qw1jabsx/4/). Use the loop approach for reliability.
601
-
602
- ---
603
-
604
- ## Rule 7.11: Use Set/Map for O(1) Lookups
605
-
606
- **Impact:** LOW-MEDIUM
607
- **Tags:** javascript, set, map, data-structures, performance
608
-
609
- ## Use Set/Map for O(1) Lookups
610
-
611
- Convert arrays to Set/Map for repeated membership checks.
612
-
613
- **Incorrect (O(n) per check):**
614
-
615
- ```typescript
616
- const allowedIds = ['a', 'b', 'c', ...]
617
- items.filter(item => allowedIds.includes(item.id))
618
- ```
619
-
620
- **Correct (O(1) per check):**
621
-
622
- ```typescript
623
- const allowedIds = new Set(['a', 'b', 'c', ...])
624
- items.filter(item => allowedIds.has(item.id))
625
- ```
626
-
627
- ---
628
-
629
- ## Rule 7.12: Use toSorted() Instead of sort() for Immutability
630
-
631
- **Impact:** MEDIUM-HIGH
632
- **Tags:** javascript, arrays, immutability, react, state, mutation
633
-
634
- ## Use toSorted() Instead of sort() for Immutability
635
-
636
- `.sort()` mutates the array in place, which can cause bugs with React state and props. Use `.toSorted()` to create a new sorted array without mutation.
637
-
638
- **Incorrect (mutates original array):**
639
-
640
- ```typescript
641
- function UserList({ users }: { users: User[] }) {
642
- // Mutates the users prop array!
643
- const sorted = useMemo(
644
- () => users.sort((a, b) => a.name.localeCompare(b.name)),
645
- [users]
646
- )
647
- return <div>{sorted.map(renderUser)}</div>
648
- }
649
- ```
650
-
651
- **Correct (creates new array):**
652
-
653
- ```typescript
654
- function UserList({ users }: { users: User[] }) {
655
- // Creates new sorted array, original unchanged
656
- const sorted = useMemo(
657
- () => users.toSorted((a, b) => a.name.localeCompare(b.name)),
658
- [users]
659
- )
660
- return <div>{sorted.map(renderUser)}</div>
661
- }
662
- ```
663
-
664
- **Why this matters in React:**
665
-
666
- 1. Props/state mutations break React's immutability model - React expects props and state to be treated as read-only
667
- 2. Causes stale closure bugs - Mutating arrays inside closures (callbacks, effects) can lead to unexpected behavior
668
-
669
- **Browser support (fallback for older browsers):**
670
-
671
- `.toSorted()` is available in all modern browsers (Chrome 110+, Safari 16+, Firefox 115+, Node.js 20+). For older environments, use spread operator:
672
-
673
- ```typescript
674
- // Fallback for older browsers
675
- const sorted = [...items].sort((a, b) => a.value - b.value)
676
- ```
677
-
678
- **Other immutable array methods:**
679
-
680
- - `.toSorted()` - immutable sort
681
- - `.toReversed()` - immutable reverse
682
- - `.toSpliced()` - immutable splice
683
- - `.with()` - immutable element replacement
684
-
1
+ # 7. JavaScript Performance
2
+
3
+ > **Impact:** LOW-MEDIUM
4
+ > **Focus:** Micro-optimizations for hot paths can add up to meaningful improvements.
5
+
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ This section contains **12 rules** focused on javascript performance.
11
+
12
+ ---
13
+
14
+ ## Rule 7.1: Avoid Layout Thrashing
15
+
16
+ **Impact:** MEDIUM
17
+ **Tags:** javascript, dom, css, performance, reflow, layout-thrashing
18
+
19
+ ## Avoid Layout Thrashing
20
+
21
+ Avoid interleaving style writes with layout reads. When you read a layout property (like `offsetWidth`, `getBoundingClientRect()`, or `getComputedStyle()`) between style changes, the browser is forced to trigger a synchronous reflow.
22
+
23
+ **This is OK (browser batches style changes):**
24
+ ```typescript
25
+ function updateElementStyles(element: HTMLElement) {
26
+ // Each line invalidates style, but browser batches the recalculation
27
+ element.style.width = '100px'
28
+ element.style.height = '200px'
29
+ element.style.backgroundColor = 'blue'
30
+ element.style.border = '1px solid black'
31
+ }
32
+ ```
33
+
34
+ **Incorrect (interleaved reads and writes force reflows):**
35
+ ```typescript
36
+ function layoutThrashing(element: HTMLElement) {
37
+ element.style.width = '100px'
38
+ const width = element.offsetWidth // Forces reflow
39
+ element.style.height = '200px'
40
+ const height = element.offsetHeight // Forces another reflow
41
+ }
42
+ ```
43
+
44
+ **Correct (batch writes, then read once):**
45
+ ```typescript
46
+ function updateElementStyles(element: HTMLElement) {
47
+ // Batch all writes together
48
+ element.style.width = '100px'
49
+ element.style.height = '200px'
50
+ element.style.backgroundColor = 'blue'
51
+ element.style.border = '1px solid black'
52
+
53
+ // Read after all writes are done (single reflow)
54
+ const { width, height } = element.getBoundingClientRect()
55
+ }
56
+ ```
57
+
58
+ **Correct (batch reads, then writes):**
59
+ ```typescript
60
+ function avoidThrashing(element: HTMLElement) {
61
+ // Read phase - all layout queries first
62
+ const rect1 = element.getBoundingClientRect()
63
+ const offsetWidth = element.offsetWidth
64
+ const offsetHeight = element.offsetHeight
65
+
66
+ // Write phase - all style changes after
67
+ element.style.width = '100px'
68
+ element.style.height = '200px'
69
+ }
70
+ ```
71
+
72
+ **Better: use CSS classes**
73
+ ```css
74
+ .highlighted-box {
75
+ width: 100px;
76
+ height: 200px;
77
+ background-color: blue;
78
+ border: 1px solid black;
79
+ }
80
+ ```
81
+ ```typescript
82
+ function updateElementStyles(element: HTMLElement) {
83
+ element.classList.add('highlighted-box')
84
+
85
+ const { width, height } = element.getBoundingClientRect()
86
+ }
87
+ ```
88
+
89
+ **React example:**
90
+ ```tsx
91
+ // Incorrect: interleaving style changes with layout queries
92
+ function Box({ isHighlighted }: { isHighlighted: boolean }) {
93
+ const ref = useRef<HTMLDivElement>(null)
94
+
95
+ useEffect(() => {
96
+ if (ref.current && isHighlighted) {
97
+ ref.current.style.width = '100px'
98
+ const width = ref.current.offsetWidth // Forces layout
99
+ ref.current.style.height = '200px'
100
+ }
101
+ }, [isHighlighted])
102
+
103
+ return <div ref={ref}>Content</div>
104
+ }
105
+
106
+ // Correct: toggle class
107
+ function Box({ isHighlighted }: { isHighlighted: boolean }) {
108
+ return (
109
+ <div className={isHighlighted ? 'highlighted-box' : ''}>
110
+ Content
111
+ </div>
112
+ )
113
+ }
114
+ ```
115
+
116
+ Prefer CSS classes over inline styles when possible. CSS files are cached by the browser, and classes provide better separation of concerns and are easier to maintain.
117
+
118
+ See [this gist](https://gist.github.com/paulirish/5d52fb081b3570c81e3a) and [CSS Triggers](https://csstriggers.com/) for more information on layout-forcing operations.
119
+
120
+ ---
121
+
122
+ ## Rule 7.2: Build Index Maps for Repeated Lookups
123
+
124
+ **Impact:** LOW-MEDIUM
125
+ **Tags:** javascript, map, indexing, optimization, performance
126
+
127
+ ## Build Index Maps for Repeated Lookups
128
+
129
+ Multiple `.find()` calls by the same key should use a Map.
130
+
131
+ **Incorrect (O(n) per lookup):**
132
+
133
+ ```typescript
134
+ function processOrders(orders: Order[], users: User[]) {
135
+ return orders.map(order => ({
136
+ ...order,
137
+ user: users.find(u => u.id === order.userId)
138
+ }))
139
+ }
140
+ ```
141
+
142
+ **Correct (O(1) per lookup):**
143
+
144
+ ```typescript
145
+ function processOrders(orders: Order[], users: User[]) {
146
+ const userById = new Map(users.map(u => [u.id, u]))
147
+
148
+ return orders.map(order => ({
149
+ ...order,
150
+ user: userById.get(order.userId)
151
+ }))
152
+ }
153
+ ```
154
+
155
+ Build map once (O(n)), then all lookups are O(1).
156
+ For 1000 orders × 1000 users: 1M ops → 2K ops.
157
+
158
+ ---
159
+
160
+ ## Rule 7.3: Cache Property Access in Loops
161
+
162
+ **Impact:** LOW-MEDIUM
163
+ **Tags:** javascript, loops, optimization, caching
164
+
165
+ ## Cache Property Access in Loops
166
+
167
+ Cache object property lookups in hot paths.
168
+
169
+ **Incorrect (3 lookups × N iterations):**
170
+
171
+ ```typescript
172
+ for (let i = 0; i < arr.length; i++) {
173
+ process(obj.config.settings.value)
174
+ }
175
+ ```
176
+
177
+ **Correct (1 lookup total):**
178
+
179
+ ```typescript
180
+ const value = obj.config.settings.value
181
+ const len = arr.length
182
+ for (let i = 0; i < len; i++) {
183
+ process(value)
184
+ }
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Rule 7.4: Cache Repeated Function Calls
190
+
191
+ **Impact:** MEDIUM
192
+ **Tags:** javascript, cache, memoization, performance
193
+
194
+ ## Cache Repeated Function Calls
195
+
196
+ Use a module-level Map to cache function results when the same function is called repeatedly with the same inputs during render.
197
+
198
+ **Incorrect (redundant computation):**
199
+
200
+ ```typescript
201
+ function ProjectList({ projects }: { projects: Project[] }) {
202
+ return (
203
+ <div>
204
+ {projects.map(project => {
205
+ // slugify() called 100+ times for same project names
206
+ const slug = slugify(project.name)
207
+
208
+ return <ProjectCard key={project.id} slug={slug} />
209
+ })}
210
+ </div>
211
+ )
212
+ }
213
+ ```
214
+
215
+ **Correct (cached results):**
216
+
217
+ ```typescript
218
+ // Module-level cache
219
+ const slugifyCache = new Map<string, string>()
220
+
221
+ function cachedSlugify(text: string): string {
222
+ if (slugifyCache.has(text)) {
223
+ return slugifyCache.get(text)!
224
+ }
225
+ const result = slugify(text)
226
+ slugifyCache.set(text, result)
227
+ return result
228
+ }
229
+
230
+ function ProjectList({ projects }: { projects: Project[] }) {
231
+ return (
232
+ <div>
233
+ {projects.map(project => {
234
+ // Computed only once per unique project name
235
+ const slug = cachedSlugify(project.name)
236
+
237
+ return <ProjectCard key={project.id} slug={slug} />
238
+ })}
239
+ </div>
240
+ )
241
+ }
242
+ ```
243
+
244
+ **Simpler pattern for single-value functions:**
245
+
246
+ ```typescript
247
+ let isLoggedInCache: boolean | null = null
248
+
249
+ function isLoggedIn(): boolean {
250
+ if (isLoggedInCache !== null) {
251
+ return isLoggedInCache
252
+ }
253
+
254
+ isLoggedInCache = document.cookie.includes('auth=')
255
+ return isLoggedInCache
256
+ }
257
+
258
+ // Clear cache when auth changes
259
+ function onAuthChange() {
260
+ isLoggedInCache = null
261
+ }
262
+ ```
263
+
264
+ Use a Map (not a hook) so it works everywhere: utilities, event handlers, not just React components.
265
+
266
+ Reference: [How we made the Vercel Dashboard twice as fast](https://vercel.com/blog/how-we-made-the-vercel-dashboard-twice-as-fast)
267
+
268
+ ---
269
+
270
+ ## Rule 7.5: Cache Storage API Calls
271
+
272
+ **Impact:** LOW-MEDIUM
273
+ **Tags:** javascript, localStorage, storage, caching, performance
274
+
275
+ ## Cache Storage API Calls
276
+
277
+ `localStorage`, `sessionStorage`, and `document.cookie` are synchronous and expensive. Cache reads in memory.
278
+
279
+ **Incorrect (reads storage on every call):**
280
+
281
+ ```typescript
282
+ function getTheme() {
283
+ return localStorage.getItem('theme') ?? 'light'
284
+ }
285
+ // Called 10 times = 10 storage reads
286
+ ```
287
+
288
+ **Correct (Map cache):**
289
+
290
+ ```typescript
291
+ const storageCache = new Map<string, string | null>()
292
+
293
+ function getLocalStorage(key: string) {
294
+ if (!storageCache.has(key)) {
295
+ storageCache.set(key, localStorage.getItem(key))
296
+ }
297
+ return storageCache.get(key)
298
+ }
299
+
300
+ function setLocalStorage(key: string, value: string) {
301
+ localStorage.setItem(key, value)
302
+ storageCache.set(key, value) // keep cache in sync
303
+ }
304
+ ```
305
+
306
+ Use a Map (not a hook) so it works everywhere: utilities, event handlers, not just React components.
307
+
308
+ **Cookie caching:**
309
+
310
+ ```typescript
311
+ let cookieCache: Record<string, string> | null = null
312
+
313
+ function getCookie(name: string) {
314
+ if (!cookieCache) {
315
+ cookieCache = Object.fromEntries(
316
+ document.cookie.split('; ').map(c => c.split('='))
317
+ )
318
+ }
319
+ return cookieCache[name]
320
+ }
321
+ ```
322
+
323
+ **Important (invalidate on external changes):**
324
+
325
+ If storage can change externally (another tab, server-set cookies), invalidate cache:
326
+
327
+ ```typescript
328
+ window.addEventListener('storage', (e) => {
329
+ if (e.key) storageCache.delete(e.key)
330
+ })
331
+
332
+ document.addEventListener('visibilitychange', () => {
333
+ if (document.visibilityState === 'visible') {
334
+ storageCache.clear()
335
+ }
336
+ })
337
+ ```
338
+
339
+ ---
340
+
341
+ ## Rule 7.6: Combine Multiple Array Iterations
342
+
343
+ **Impact:** LOW-MEDIUM
344
+ **Tags:** javascript, arrays, loops, performance
345
+
346
+ ## Combine Multiple Array Iterations
347
+
348
+ Multiple `.filter()` or `.map()` calls iterate the array multiple times. Combine into one loop.
349
+
350
+ **Incorrect (3 iterations):**
351
+
352
+ ```typescript
353
+ const admins = users.filter(u => u.isAdmin)
354
+ const testers = users.filter(u => u.isTester)
355
+ const inactive = users.filter(u => !u.isActive)
356
+ ```
357
+
358
+ **Correct (1 iteration):**
359
+
360
+ ```typescript
361
+ const admins: User[] = []
362
+ const testers: User[] = []
363
+ const inactive: User[] = []
364
+
365
+ for (const user of users) {
366
+ if (user.isAdmin) admins.push(user)
367
+ if (user.isTester) testers.push(user)
368
+ if (!user.isActive) inactive.push(user)
369
+ }
370
+ ```
371
+
372
+ ---
373
+
374
+ ## Rule 7.7: Early Length Check for Array Comparisons
375
+
376
+ **Impact:** MEDIUM-HIGH
377
+ **Tags:** javascript, arrays, performance, optimization, comparison
378
+
379
+ ## Early Length Check for Array Comparisons
380
+
381
+ When comparing arrays with expensive operations (sorting, deep equality, serialization), check lengths first. If lengths differ, the arrays cannot be equal.
382
+
383
+ In real-world applications, this optimization is especially valuable when the comparison runs in hot paths (event handlers, render loops).
384
+
385
+ **Incorrect (always runs expensive comparison):**
386
+
387
+ ```typescript
388
+ function hasChanges(current: string[], original: string[]) {
389
+ // Always sorts and joins, even when lengths differ
390
+ return current.sort().join() !== original.sort().join()
391
+ }
392
+ ```
393
+
394
+ Two O(n log n) sorts run even when `current.length` is 5 and `original.length` is 100. There is also overhead of joining the arrays and comparing the strings.
395
+
396
+ **Correct (O(1) length check first):**
397
+
398
+ ```typescript
399
+ function hasChanges(current: string[], original: string[]) {
400
+ // Early return if lengths differ
401
+ if (current.length !== original.length) {
402
+ return true
403
+ }
404
+ // Only sort when lengths match
405
+ const currentSorted = current.toSorted()
406
+ const originalSorted = original.toSorted()
407
+ for (let i = 0; i < currentSorted.length; i++) {
408
+ if (currentSorted[i] !== originalSorted[i]) {
409
+ return true
410
+ }
411
+ }
412
+ return false
413
+ }
414
+ ```
415
+
416
+ This new approach is more efficient because:
417
+ - It avoids the overhead of sorting and joining the arrays when lengths differ
418
+ - It avoids consuming memory for the joined strings (especially important for large arrays)
419
+ - It avoids mutating the original arrays
420
+ - It returns early when a difference is found
421
+
422
+ ---
423
+
424
+ ## Rule 7.8: Early Return from Functions
425
+
426
+ **Impact:** LOW-MEDIUM
427
+ **Tags:** javascript, functions, optimization, early-return
428
+
429
+ ## Early Return from Functions
430
+
431
+ Return early when result is determined to skip unnecessary processing.
432
+
433
+ **Incorrect (processes all items even after finding answer):**
434
+
435
+ ```typescript
436
+ function validateUsers(users: User[]) {
437
+ let hasError = false
438
+ let errorMessage = ''
439
+
440
+ for (const user of users) {
441
+ if (!user.email) {
442
+ hasError = true
443
+ errorMessage = 'Email required'
444
+ }
445
+ if (!user.name) {
446
+ hasError = true
447
+ errorMessage = 'Name required'
448
+ }
449
+ // Continues checking all users even after error found
450
+ }
451
+
452
+ return hasError ? { valid: false, error: errorMessage } : { valid: true }
453
+ }
454
+ ```
455
+
456
+ **Correct (returns immediately on first error):**
457
+
458
+ ```typescript
459
+ function validateUsers(users: User[]) {
460
+ for (const user of users) {
461
+ if (!user.email) {
462
+ return { valid: false, error: 'Email required' }
463
+ }
464
+ if (!user.name) {
465
+ return { valid: false, error: 'Name required' }
466
+ }
467
+ }
468
+
469
+ return { valid: true }
470
+ }
471
+ ```
472
+
473
+ ---
474
+
475
+ ## Rule 7.9: Hoist RegExp Creation
476
+
477
+ **Impact:** LOW-MEDIUM
478
+ **Tags:** javascript, regexp, optimization, memoization
479
+
480
+ ## Hoist RegExp Creation
481
+
482
+ Don't create RegExp inside render. Hoist to module scope or memoize with `useMemo()`.
483
+
484
+ **Incorrect (new RegExp every render):**
485
+
486
+ ```tsx
487
+ function Highlighter({ text, query }: Props) {
488
+ const regex = new RegExp(`(${query})`, 'gi')
489
+ const parts = text.split(regex)
490
+ return <>{parts.map((part, i) => ...)}</>
491
+ }
492
+ ```
493
+
494
+ **Correct (memoize or hoist):**
495
+
496
+ ```tsx
497
+ const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
498
+
499
+ function Highlighter({ text, query }: Props) {
500
+ const regex = useMemo(
501
+ () => new RegExp(`(${escapeRegex(query)})`, 'gi'),
502
+ [query]
503
+ )
504
+ const parts = text.split(regex)
505
+ return <>{parts.map((part, i) => ...)}</>
506
+ }
507
+ ```
508
+
509
+ **Warning (global regex has mutable state):**
510
+
511
+ Global regex (`/g`) has mutable `lastIndex` state:
512
+
513
+ ```typescript
514
+ const regex = /foo/g
515
+ regex.test('foo') // true, lastIndex = 3
516
+ regex.test('foo') // false, lastIndex = 0
517
+ ```
518
+
519
+ ---
520
+
521
+ ## Rule 7.10: Use Loop for Min/Max Instead of Sort
522
+
523
+ **Impact:** LOW
524
+ **Tags:** javascript, arrays, performance, sorting, algorithms
525
+
526
+ ## Use Loop for Min/Max Instead of Sort
527
+
528
+ Finding the smallest or largest element only requires a single pass through the array. Sorting is wasteful and slower.
529
+
530
+ **Incorrect (O(n log n) - sort to find latest):**
531
+
532
+ ```typescript
533
+ interface Project {
534
+ id: string
535
+ name: string
536
+ updatedAt: number
537
+ }
538
+
539
+ function getLatestProject(projects: Project[]) {
540
+ const sorted = [...projects].sort((a, b) => b.updatedAt - a.updatedAt)
541
+ return sorted[0]
542
+ }
543
+ ```
544
+
545
+ Sorts the entire array just to find the maximum value.
546
+
547
+ **Incorrect (O(n log n) - sort for oldest and newest):**
548
+
549
+ ```typescript
550
+ function getOldestAndNewest(projects: Project[]) {
551
+ const sorted = [...projects].sort((a, b) => a.updatedAt - b.updatedAt)
552
+ return { oldest: sorted[0], newest: sorted[sorted.length - 1] }
553
+ }
554
+ ```
555
+
556
+ Still sorts unnecessarily when only min/max are needed.
557
+
558
+ **Correct (O(n) - single loop):**
559
+
560
+ ```typescript
561
+ function getLatestProject(projects: Project[]) {
562
+ if (projects.length === 0) return null
563
+
564
+ let latest = projects[0]
565
+
566
+ for (let i = 1; i < projects.length; i++) {
567
+ if (projects[i].updatedAt > latest.updatedAt) {
568
+ latest = projects[i]
569
+ }
570
+ }
571
+
572
+ return latest
573
+ }
574
+
575
+ function getOldestAndNewest(projects: Project[]) {
576
+ if (projects.length === 0) return { oldest: null, newest: null }
577
+
578
+ let oldest = projects[0]
579
+ let newest = projects[0]
580
+
581
+ for (let i = 1; i < projects.length; i++) {
582
+ if (projects[i].updatedAt < oldest.updatedAt) oldest = projects[i]
583
+ if (projects[i].updatedAt > newest.updatedAt) newest = projects[i]
584
+ }
585
+
586
+ return { oldest, newest }
587
+ }
588
+ ```
589
+
590
+ Single pass through the array, no copying, no sorting.
591
+
592
+ **Alternative (Math.min/Math.max for small arrays):**
593
+
594
+ ```typescript
595
+ const numbers = [5, 2, 8, 1, 9]
596
+ const min = Math.min(...numbers)
597
+ const max = Math.max(...numbers)
598
+ ```
599
+
600
+ This works for small arrays, but can be slower or just throw an error for very large arrays due to spread operator limitations. Maximal array length is approximately 124000 in Chrome 143 and 638000 in Safari 18; exact numbers may vary - see [the fiddle](https://jsfiddle.net/qw1jabsx/4/). Use the loop approach for reliability.
601
+
602
+ ---
603
+
604
+ ## Rule 7.11: Use Set/Map for O(1) Lookups
605
+
606
+ **Impact:** LOW-MEDIUM
607
+ **Tags:** javascript, set, map, data-structures, performance
608
+
609
+ ## Use Set/Map for O(1) Lookups
610
+
611
+ Convert arrays to Set/Map for repeated membership checks.
612
+
613
+ **Incorrect (O(n) per check):**
614
+
615
+ ```typescript
616
+ const allowedIds = ['a', 'b', 'c', ...]
617
+ items.filter(item => allowedIds.includes(item.id))
618
+ ```
619
+
620
+ **Correct (O(1) per check):**
621
+
622
+ ```typescript
623
+ const allowedIds = new Set(['a', 'b', 'c', ...])
624
+ items.filter(item => allowedIds.has(item.id))
625
+ ```
626
+
627
+ ---
628
+
629
+ ## Rule 7.12: Use toSorted() Instead of sort() for Immutability
630
+
631
+ **Impact:** MEDIUM-HIGH
632
+ **Tags:** javascript, arrays, immutability, react, state, mutation
633
+
634
+ ## Use toSorted() Instead of sort() for Immutability
635
+
636
+ `.sort()` mutates the array in place, which can cause bugs with React state and props. Use `.toSorted()` to create a new sorted array without mutation.
637
+
638
+ **Incorrect (mutates original array):**
639
+
640
+ ```typescript
641
+ function UserList({ users }: { users: User[] }) {
642
+ // Mutates the users prop array!
643
+ const sorted = useMemo(
644
+ () => users.sort((a, b) => a.name.localeCompare(b.name)),
645
+ [users]
646
+ )
647
+ return <div>{sorted.map(renderUser)}</div>
648
+ }
649
+ ```
650
+
651
+ **Correct (creates new array):**
652
+
653
+ ```typescript
654
+ function UserList({ users }: { users: User[] }) {
655
+ // Creates new sorted array, original unchanged
656
+ const sorted = useMemo(
657
+ () => users.toSorted((a, b) => a.name.localeCompare(b.name)),
658
+ [users]
659
+ )
660
+ return <div>{sorted.map(renderUser)}</div>
661
+ }
662
+ ```
663
+
664
+ **Why this matters in React:**
665
+
666
+ 1. Props/state mutations break React's immutability model - React expects props and state to be treated as read-only
667
+ 2. Causes stale closure bugs - Mutating arrays inside closures (callbacks, effects) can lead to unexpected behavior
668
+
669
+ **Browser support (fallback for older browsers):**
670
+
671
+ `.toSorted()` is available in all modern browsers (Chrome 110+, Safari 16+, Firefox 115+, Node.js 20+). For older environments, use spread operator:
672
+
673
+ ```typescript
674
+ // Fallback for older browsers
675
+ const sorted = [...items].sort((a, b) => a.value - b.value)
676
+ ```
677
+
678
+ **Other immutable array methods:**
679
+
680
+ - `.toSorted()` - immutable sort
681
+ - `.toReversed()` - immutable reverse
682
+ - `.toSpliced()` - immutable splice
683
+ - `.with()` - immutable element replacement
684
+