exonous 0.0.0-stage → 2.10.4

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 (385) hide show
  1. package/README.md +100 -2
  2. package/assets/THIRD-PARTY-NOTICES.md +29 -0
  3. package/assets/adapters/opencode/exonous.js +54 -0
  4. package/assets/agents/exo-backend.md +22 -0
  5. package/assets/agents/exo-cto.md +22 -0
  6. package/assets/agents/exo-data-ai.md +22 -0
  7. package/assets/agents/exo-designer.md +22 -0
  8. package/assets/agents/exo-devops.md +22 -0
  9. package/assets/agents/exo-frontend.md +22 -0
  10. package/assets/agents/exo-infra.md +22 -0
  11. package/assets/agents/exo-mobile.md +22 -0
  12. package/assets/agents/exo-pm.md +22 -0
  13. package/assets/agents/exo-qa.md +22 -0
  14. package/assets/agents/exo-researcher.md +22 -0
  15. package/assets/agents/exo-security.md +22 -0
  16. package/assets/agents/roster.json +209 -0
  17. package/assets/agents/taxis.js +189 -0
  18. package/assets/editors/cursor/frontend-skills.mdc +27 -0
  19. package/assets/editors/hooks/cursor/hooks.json +11 -0
  20. package/assets/machine/PR-TEMPLATE.md +21 -0
  21. package/assets/machine/hooks/anamnesis.cjs +61 -0
  22. package/assets/machine/hooks/ethos.cjs +48 -0
  23. package/assets/machine/hooks/kairos.cjs +46 -0
  24. package/assets/machine/hooks/lib/cli-options.cjs +133 -0
  25. package/assets/machine/hooks/lib/memory.cjs +488 -0
  26. package/assets/machine/hooks/lib/metron.cjs +52 -0
  27. package/assets/machine/hooks/lib/paths.cjs +99 -0
  28. package/assets/machine/hooks/lib/payload.cjs +81 -0
  29. package/assets/machine/hooks/lib/pr-template-validate.cjs +103 -0
  30. package/assets/machine/hooks/lib/release.cjs +58 -0
  31. package/assets/machine/hooks/lib/repo.cjs +138 -0
  32. package/assets/machine/hooks/lib/sanitize.cjs +37 -0
  33. package/assets/machine/hooks/lib/selfupdate.cjs +354 -0
  34. package/assets/machine/hooks/lib/shell.cjs +722 -0
  35. package/assets/machine/hooks/lib/template.cjs +70 -0
  36. package/assets/machine/hooks/lib/token.cjs +110 -0
  37. package/assets/machine/hooks/lib/validate-pr-body.cjs +21 -0
  38. package/assets/machine/hooks/pyle.cjs +302 -0
  39. package/assets/rules/nomos.md +59 -0
  40. package/assets/rules/praxis.md +38 -0
  41. package/assets/skills/code-review/SKILL.md +124 -0
  42. package/assets/skills/commit-changes/SKILL.md +49 -0
  43. package/assets/skills/deliver/SKILL.md +114 -0
  44. package/assets/skills/deliver/references/parallel.md +37 -0
  45. package/assets/skills/doc/SKILL.md +140 -0
  46. package/assets/skills/doc/doc.mjs +277 -0
  47. package/assets/skills/issue-board/SKILL.md +84 -0
  48. package/assets/skills/issue-board/board.mjs +389 -0
  49. package/assets/skills/issue-board/config.example.json +9 -0
  50. package/assets/skills/issue-board/render.py +189 -0
  51. package/assets/skills/make-pr/SKILL.md +24 -0
  52. package/assets/skills/native-ui/SKILL.md +67 -0
  53. package/assets/skills/native-ui/reference/apple.md +180 -0
  54. package/assets/skills/native-ui/reference/mobile-feel.md +221 -0
  55. package/assets/skills/native-ui/reference/swift.md +289 -0
  56. package/assets/skills/project-memory/SKILL.md +59 -0
  57. package/assets/skills/project-memory/config.example.json +4 -0
  58. package/assets/skills/project-memory/project-memory.mjs +478 -0
  59. package/assets/skills/security-review/SKILL.md +102 -0
  60. package/assets/skills/session-handoff/SKILL.md +23 -0
  61. package/assets/skills/session-handoff/config.example.json +3 -0
  62. package/assets/skills/ui-design/SKILL.md +75 -0
  63. package/assets/skills/ui-design/reference/adapt.md +151 -0
  64. package/assets/skills/ui-design/reference/adapt.native.md +35 -0
  65. package/assets/skills/ui-design/reference/android.md +50 -0
  66. package/assets/skills/ui-design/reference/animate.md +87 -0
  67. package/assets/skills/ui-design/reference/audit.md +76 -0
  68. package/assets/skills/ui-design/reference/audit.native.md +126 -0
  69. package/assets/skills/ui-design/reference/bolder.md +33 -0
  70. package/assets/skills/ui-design/reference/clarify.md +84 -0
  71. package/assets/skills/ui-design/reference/colorize.md +86 -0
  72. package/assets/skills/ui-design/reference/craft-floor.md +25 -0
  73. package/assets/skills/ui-design/reference/critique.md +345 -0
  74. package/assets/skills/ui-design/reference/degraded/asset-producer.md +35 -0
  75. package/assets/skills/ui-design/reference/degraded/documenter.md +23 -0
  76. package/assets/skills/ui-design/reference/degraded/finish-reviewer.md +43 -0
  77. package/assets/skills/ui-design/reference/degraded/manual-edit-applier.md +56 -0
  78. package/assets/skills/ui-design/reference/delight.md +63 -0
  79. package/assets/skills/ui-design/reference/distill.md +98 -0
  80. package/assets/skills/ui-design/reference/doctor.md +49 -0
  81. package/assets/skills/ui-design/reference/document.md +273 -0
  82. package/assets/skills/ui-design/reference/extract.md +52 -0
  83. package/assets/skills/ui-design/reference/harden.md +122 -0
  84. package/assets/skills/ui-design/reference/hooks.md +114 -0
  85. package/assets/skills/ui-design/reference/init.md +47 -0
  86. package/assets/skills/ui-design/reference/ios.md +55 -0
  87. package/assets/skills/ui-design/reference/layout.md +81 -0
  88. package/assets/skills/ui-design/reference/live-setup.md +75 -0
  89. package/assets/skills/ui-design/reference/live.md +326 -0
  90. package/assets/skills/ui-design/reference/new-work.md +350 -0
  91. package/assets/skills/ui-design/reference/onboard.md +85 -0
  92. package/assets/skills/ui-design/reference/operate.md +29 -0
  93. package/assets/skills/ui-design/reference/optimize.md +101 -0
  94. package/assets/skills/ui-design/reference/overdrive.md +83 -0
  95. package/assets/skills/ui-design/reference/polish.md +77 -0
  96. package/assets/skills/ui-design/reference/quieter.md +95 -0
  97. package/assets/skills/ui-design/reference/routing.md +37 -0
  98. package/assets/skills/ui-design/reference/shape.md +43 -0
  99. package/assets/skills/ui-design/reference/styles/brutalist.md +45 -0
  100. package/assets/skills/ui-design/reference/styles/design-md.md +70 -0
  101. package/assets/skills/ui-design/reference/styles/direction.md +95 -0
  102. package/assets/skills/ui-design/reference/styles/full-output.md +42 -0
  103. package/assets/skills/ui-design/reference/styles/minimalist.md +64 -0
  104. package/assets/skills/ui-design/reference/styles/premium.md +65 -0
  105. package/assets/skills/ui-design/reference/styles/redesign.md +59 -0
  106. package/assets/skills/ui-design/reference/typeset.md +73 -0
  107. package/assets/skills/ui-design/reference/visualize.md +156 -0
  108. package/assets/skills/ui-design/scripts/ENGINE-LICENSE +191 -0
  109. package/assets/skills/ui-design/scripts/VERSION +1 -0
  110. package/assets/skills/ui-design/scripts/bin/darwin-arm64/impeccable +0 -0
  111. package/assets/skills/ui-design/scripts/command-metadata.json +94 -0
  112. package/assets/skills/ui-design/scripts/data/font-index-failures.json +121 -0
  113. package/assets/skills/ui-design/scripts/data/font-index.json +1 -0
  114. package/assets/skills/ui-design/scripts/impeccable +206 -0
  115. package/assets/skills/ui-design/scripts/impeccable.cmd +214 -0
  116. package/assets/skills/ui-design/scripts/live-browser-dom.js +167 -0
  117. package/assets/skills/ui-design/scripts/live-browser-ignores.js +242 -0
  118. package/assets/skills/ui-design/scripts/live-browser-session.js +144 -0
  119. package/assets/skills/ui-design/scripts/live-browser.js +12990 -0
  120. package/assets/skills/ui-design/scripts/modern-screenshot.umd.js +14 -0
  121. package/assets/skills/ui-design/scripts/ui-design +6 -0
  122. package/assets/skills/ui-design/scripts/ui-design.cmd +3 -0
  123. package/assets/skills/ui-design/scripts/ui-design.mjs +124 -0
  124. package/assets/skills/ui-mockup/SKILL.md +68 -0
  125. package/assets/skills/ui-mockup/reference/brandkit.md +101 -0
  126. package/assets/skills/ui-mockup/reference/image-to-code.md +83 -0
  127. package/assets/skills/ui-mockup/reference/mobile-comps.md +94 -0
  128. package/assets/skills/ui-mockup/reference/web-comps.md +83 -0
  129. package/assets/skills/ui-motion/SKILL.md +112 -0
  130. package/assets/skills/ui-motion/reference/expo.md +224 -0
  131. package/assets/skills/ui-motion/reference/opportunities.md +81 -0
  132. package/assets/skills/ui-motion/reference/prototype.md +238 -0
  133. package/assets/skills/ui-motion/reference/review.md +163 -0
  134. package/assets/skills/ui-motion/reference/toasts.md +144 -0
  135. package/assets/skills/ui-motion/reference/ui-libraries.md +71 -0
  136. package/assets/skills/ui-motion/reference/vocabulary.md +130 -0
  137. package/assets/skills/ui-motion/reference/web.md +294 -0
  138. package/assets/skills/ui-patterns/SKILL.md +105 -0
  139. package/assets/skills/ui-patterns/references/stacks/html-tailwind.md +40 -0
  140. package/assets/skills/ui-patterns/references/stacks/nextjs.md +52 -0
  141. package/assets/skills/ui-patterns/references/stacks/nuxt.md +100 -0
  142. package/assets/skills/ui-patterns/references/stacks/react-native.md +48 -0
  143. package/assets/skills/ui-patterns/references/stacks/react.md +49 -0
  144. package/assets/skills/ui-patterns/references/stacks/shadcn.md +57 -0
  145. package/assets/skills/ui-patterns/references/stacks/vue.md +37 -0
  146. package/assets/techne/.claude-plugin/marketplace.json +31 -0
  147. package/assets/techne/.claude-plugin/plugin.json +24 -0
  148. package/assets/techne/.mcp.json +8 -0
  149. package/assets/techne/commands/build-fix.md +48 -0
  150. package/assets/techne/commands/refactor-clean.md +46 -0
  151. package/assets/techne/commands/test-coverage.md +42 -0
  152. package/assets/techne/hooks/hooks.json +49 -0
  153. package/assets/techne/rules/angular/coding-style.md +49 -0
  154. package/assets/techne/rules/angular/hooks.md +23 -0
  155. package/assets/techne/rules/angular/patterns.md +48 -0
  156. package/assets/techne/rules/angular/security.md +26 -0
  157. package/assets/techne/rules/angular/testing.md +46 -0
  158. package/assets/techne/rules/arkts/coding-style.md +63 -0
  159. package/assets/techne/rules/arkts/hooks.md +38 -0
  160. package/assets/techne/rules/arkts/patterns.md +42 -0
  161. package/assets/techne/rules/arkts/security.md +35 -0
  162. package/assets/techne/rules/arkts/testing.md +39 -0
  163. package/assets/techne/rules/common/agents.md +6 -0
  164. package/assets/techne/rules/common/code-review.md +15 -0
  165. package/assets/techne/rules/common/coding-style.md +13 -0
  166. package/assets/techne/rules/common/development-workflow.md +5 -0
  167. package/assets/techne/rules/common/git-workflow.md +30 -0
  168. package/assets/techne/rules/common/hooks.md +7 -0
  169. package/assets/techne/rules/common/patterns.md +3 -0
  170. package/assets/techne/rules/common/performance.md +3 -0
  171. package/assets/techne/rules/common/security.md +5 -0
  172. package/assets/techne/rules/common/testing.md +3 -0
  173. package/assets/techne/rules/cpp/coding-style.md +31 -0
  174. package/assets/techne/rules/cpp/hooks.md +26 -0
  175. package/assets/techne/rules/cpp/patterns.md +31 -0
  176. package/assets/techne/rules/cpp/security.md +37 -0
  177. package/assets/techne/rules/cpp/testing.md +31 -0
  178. package/assets/techne/rules/csharp/coding-style.md +30 -0
  179. package/assets/techne/rules/csharp/hooks.md +24 -0
  180. package/assets/techne/rules/csharp/patterns.md +28 -0
  181. package/assets/techne/rules/csharp/security.md +32 -0
  182. package/assets/techne/rules/csharp/testing.md +27 -0
  183. package/assets/techne/rules/dart/coding-style.md +47 -0
  184. package/assets/techne/rules/dart/hooks.md +26 -0
  185. package/assets/techne/rules/dart/patterns.md +38 -0
  186. package/assets/techne/rules/dart/security.md +44 -0
  187. package/assets/techne/rules/dart/testing.md +39 -0
  188. package/assets/techne/rules/fsharp/coding-style.md +34 -0
  189. package/assets/techne/rules/fsharp/hooks.md +25 -0
  190. package/assets/techne/rules/fsharp/patterns.md +43 -0
  191. package/assets/techne/rules/fsharp/security.md +32 -0
  192. package/assets/techne/rules/fsharp/testing.md +27 -0
  193. package/assets/techne/rules/golang/coding-style.md +30 -0
  194. package/assets/techne/rules/golang/hooks.md +17 -0
  195. package/assets/techne/rules/golang/patterns.md +43 -0
  196. package/assets/techne/rules/golang/security.md +33 -0
  197. package/assets/techne/rules/golang/testing.md +20 -0
  198. package/assets/techne/rules/java/coding-style.md +51 -0
  199. package/assets/techne/rules/java/hooks.md +18 -0
  200. package/assets/techne/rules/java/patterns.md +55 -0
  201. package/assets/techne/rules/java/security.md +33 -0
  202. package/assets/techne/rules/java/testing.md +33 -0
  203. package/assets/techne/rules/kotlin/coding-style.md +50 -0
  204. package/assets/techne/rules/kotlin/hooks.md +17 -0
  205. package/assets/techne/rules/kotlin/patterns.md +44 -0
  206. package/assets/techne/rules/kotlin/security.md +34 -0
  207. package/assets/techne/rules/kotlin/testing.md +38 -0
  208. package/assets/techne/rules/nuxt/coding-style.md +20 -0
  209. package/assets/techne/rules/nuxt/hooks.md +16 -0
  210. package/assets/techne/rules/nuxt/patterns.md +46 -0
  211. package/assets/techne/rules/nuxt/security.md +19 -0
  212. package/assets/techne/rules/nuxt/testing.md +15 -0
  213. package/assets/techne/rules/perl/coding-style.md +33 -0
  214. package/assets/techne/rules/perl/hooks.md +22 -0
  215. package/assets/techne/rules/perl/patterns.md +43 -0
  216. package/assets/techne/rules/perl/security.md +39 -0
  217. package/assets/techne/rules/perl/testing.md +42 -0
  218. package/assets/techne/rules/php/coding-style.md +30 -0
  219. package/assets/techne/rules/php/hooks.md +24 -0
  220. package/assets/techne/rules/php/patterns.md +26 -0
  221. package/assets/techne/rules/php/security.md +27 -0
  222. package/assets/techne/rules/php/testing.md +28 -0
  223. package/assets/techne/rules/python/coding-style.md +38 -0
  224. package/assets/techne/rules/python/fastapi.md +57 -0
  225. package/assets/techne/rules/python/hooks.md +19 -0
  226. package/assets/techne/rules/python/patterns.md +37 -0
  227. package/assets/techne/rules/python/security.md +26 -0
  228. package/assets/techne/rules/python/testing.md +32 -0
  229. package/assets/techne/rules/react/coding-style.md +24 -0
  230. package/assets/techne/rules/react/hooks.md +62 -0
  231. package/assets/techne/rules/react/patterns.md +48 -0
  232. package/assets/techne/rules/react/security.md +45 -0
  233. package/assets/techne/rules/react/testing.md +42 -0
  234. package/assets/techne/rules/react-native/accessibility.md +14 -0
  235. package/assets/techne/rules/react-native/coding-style.md +16 -0
  236. package/assets/techne/rules/react-native/hooks.md +16 -0
  237. package/assets/techne/rules/react-native/patterns.md +18 -0
  238. package/assets/techne/rules/react-native/performance.md +14 -0
  239. package/assets/techne/rules/react-native/production-readiness.md +16 -0
  240. package/assets/techne/rules/react-native/security.md +16 -0
  241. package/assets/techne/rules/react-native/testing.md +14 -0
  242. package/assets/techne/rules/ruby/coding-style.md +40 -0
  243. package/assets/techne/rules/ruby/hooks.md +33 -0
  244. package/assets/techne/rules/ruby/patterns.md +33 -0
  245. package/assets/techne/rules/ruby/security.md +39 -0
  246. package/assets/techne/rules/ruby/testing.md +35 -0
  247. package/assets/techne/rules/rust/coding-style.md +41 -0
  248. package/assets/techne/rules/rust/hooks.md +16 -0
  249. package/assets/techne/rules/rust/patterns.md +42 -0
  250. package/assets/techne/rules/rust/security.md +33 -0
  251. package/assets/techne/rules/rust/testing.md +30 -0
  252. package/assets/techne/rules/swift/coding-style.md +30 -0
  253. package/assets/techne/rules/swift/hooks.md +20 -0
  254. package/assets/techne/rules/swift/patterns.md +30 -0
  255. package/assets/techne/rules/swift/security.md +22 -0
  256. package/assets/techne/rules/swift/testing.md +28 -0
  257. package/assets/techne/rules/typescript/coding-style.md +38 -0
  258. package/assets/techne/rules/typescript/hooks.md +14 -0
  259. package/assets/techne/rules/typescript/patterns.md +12 -0
  260. package/assets/techne/rules/typescript/security.md +14 -0
  261. package/assets/techne/rules/typescript/testing.md +12 -0
  262. package/assets/techne/rules/vue/coding-style.md +19 -0
  263. package/assets/techne/rules/vue/hooks.md +13 -0
  264. package/assets/techne/rules/vue/patterns.md +29 -0
  265. package/assets/techne/rules/vue/security.md +11 -0
  266. package/assets/techne/rules/vue/testing.md +11 -0
  267. package/assets/techne/rules/web/coding-style.md +25 -0
  268. package/assets/techne/rules/web/design-quality.md +21 -0
  269. package/assets/techne/rules/web/hooks.md +39 -0
  270. package/assets/techne/rules/web/patterns.md +23 -0
  271. package/assets/techne/rules/web/performance.md +25 -0
  272. package/assets/techne/rules/web/security.md +23 -0
  273. package/assets/techne/rules/web/testing.md +21 -0
  274. package/assets/techne/scripts/hooks/config-guard.js +50 -0
  275. package/assets/techne/scripts/hooks/edit-tracker.js +26 -0
  276. package/assets/techne/scripts/hooks/lib/shell.js +204 -0
  277. package/assets/techne/scripts/hooks/no-verify-guard.js +205 -0
  278. package/assets/techne/scripts/hooks/run.js +92 -0
  279. package/assets/techne/scripts/hooks/stop-checks.js +136 -0
  280. package/assets/techne/skills/angular/SKILL.md +34 -0
  281. package/assets/techne/skills/angular/reference/components-and-templates.md +63 -0
  282. package/assets/techne/skills/angular/reference/dependency-injection.md +44 -0
  283. package/assets/techne/skills/angular/reference/forms.md +97 -0
  284. package/assets/techne/skills/angular/reference/routing.md +50 -0
  285. package/assets/techne/skills/angular/reference/signals-and-state.md +59 -0
  286. package/assets/techne/skills/angular/reference/styling-motion-a11y.md +54 -0
  287. package/assets/techne/skills/angular/reference/testing.md +52 -0
  288. package/assets/techne/skills/angular/reference/tooling.md +31 -0
  289. package/assets/techne/skills/cpp/SKILL.md +27 -0
  290. package/assets/techne/skills/cpp/reference/coding-standards.md +160 -0
  291. package/assets/techne/skills/databases/SKILL.md +35 -0
  292. package/assets/techne/skills/databases/reference/clickhouse.md +102 -0
  293. package/assets/techne/skills/databases/reference/migrations.md +94 -0
  294. package/assets/techne/skills/databases/reference/mysql.md +101 -0
  295. package/assets/techne/skills/databases/reference/postgres.md +72 -0
  296. package/assets/techne/skills/databases/reference/prisma.md +105 -0
  297. package/assets/techne/skills/databases/reference/redis.md +108 -0
  298. package/assets/techne/skills/delivery/SKILL.md +35 -0
  299. package/assets/techne/skills/delivery/reference/deployment-patterns.md +58 -0
  300. package/assets/techne/skills/delivery/reference/docker-patterns.md +77 -0
  301. package/assets/techne/skills/delivery/reference/git-workflow.md +64 -0
  302. package/assets/techne/skills/delivery/reference/github-ops.md +67 -0
  303. package/assets/techne/skills/delivery/reference/jira-integration.md +53 -0
  304. package/assets/techne/skills/delivery/reference/kubernetes-patterns.md +67 -0
  305. package/assets/techne/skills/dotnet/SKILL.md +27 -0
  306. package/assets/techne/skills/dotnet/reference/dotnet-core.md +131 -0
  307. package/assets/techne/skills/flutter/SKILL.md +29 -0
  308. package/assets/techne/skills/flutter/reference/code-review.md +76 -0
  309. package/assets/techne/skills/flutter/reference/patterns.md +201 -0
  310. package/assets/techne/skills/go/SKILL.md +28 -0
  311. package/assets/techne/skills/go/reference/patterns.md +87 -0
  312. package/assets/techne/skills/go/reference/testing.md +142 -0
  313. package/assets/techne/skills/java/SKILL.md +29 -0
  314. package/assets/techne/skills/java/reference/java-standards.md +117 -0
  315. package/assets/techne/skills/java/reference/springboot.md +108 -0
  316. package/assets/techne/skills/kotlin/SKILL.md +35 -0
  317. package/assets/techne/skills/kotlin/reference/android-clean-architecture.md +115 -0
  318. package/assets/techne/skills/kotlin/reference/compose-multiplatform-patterns.md +113 -0
  319. package/assets/techne/skills/kotlin/reference/kotlin-coroutines-flows.md +93 -0
  320. package/assets/techne/skills/kotlin/reference/kotlin-patterns.md +74 -0
  321. package/assets/techne/skills/kotlin/reference/kotlin-testing.md +115 -0
  322. package/assets/techne/skills/ml/SKILL.md +34 -0
  323. package/assets/techne/skills/ml/reference/ai-regression-testing.md +99 -0
  324. package/assets/techne/skills/ml/reference/cost-aware-llm-pipeline.md +133 -0
  325. package/assets/techne/skills/ml/reference/eval-harness.md +94 -0
  326. package/assets/techne/skills/ml/reference/mle-workflow.md +177 -0
  327. package/assets/techne/skills/ml/reference/prompt-optimizer.md +107 -0
  328. package/assets/techne/skills/ml/reference/pytorch-patterns.md +164 -0
  329. package/assets/techne/skills/php/SKILL.md +27 -0
  330. package/assets/techne/skills/php/reference/laravel.md +142 -0
  331. package/assets/techne/skills/python/SKILL.md +33 -0
  332. package/assets/techne/skills/python/reference/django.md +104 -0
  333. package/assets/techne/skills/python/reference/fastapi.md +118 -0
  334. package/assets/techne/skills/python/reference/python-core.md +88 -0
  335. package/assets/techne/skills/python/reference/python-testing.md +105 -0
  336. package/assets/techne/skills/quality/SKILL.md +34 -0
  337. package/assets/techne/skills/quality/reference/benchmark.md +55 -0
  338. package/assets/techne/skills/quality/reference/browser-qa.md +60 -0
  339. package/assets/techne/skills/quality/reference/coding-standards.md +88 -0
  340. package/assets/techne/skills/quality/reference/e2e-testing.md +99 -0
  341. package/assets/techne/skills/quality/reference/tdd-workflow.md +89 -0
  342. package/assets/techne/skills/quality/reference/verification-loop.md +80 -0
  343. package/assets/techne/skills/react/SKILL.md +30 -0
  344. package/assets/techne/skills/react/reference/nextjs-turbopack.md +42 -0
  345. package/assets/techne/skills/react/reference/react-patterns.md +139 -0
  346. package/assets/techne/skills/react/reference/react-performance.md +101 -0
  347. package/assets/techne/skills/react/reference/react-testing.md +139 -0
  348. package/assets/techne/skills/react-native/SKILL.md +28 -0
  349. package/assets/techne/skills/react-native/reference/expo-patterns.md +196 -0
  350. package/assets/techne/skills/research/SKILL.md +35 -0
  351. package/assets/techne/skills/research/reference/architecture-decision-records.md +65 -0
  352. package/assets/techne/skills/research/reference/codebase-onboarding.md +44 -0
  353. package/assets/techne/skills/research/reference/deep-research.md +50 -0
  354. package/assets/techne/skills/research/reference/iterative-retrieval.md +62 -0
  355. package/assets/techne/skills/research/reference/product-lens.md +38 -0
  356. package/assets/techne/skills/research/reference/search-first.md +50 -0
  357. package/assets/techne/skills/rust/SKILL.md +28 -0
  358. package/assets/techne/skills/rust/reference/patterns.md +108 -0
  359. package/assets/techne/skills/rust/reference/testing.md +142 -0
  360. package/assets/techne/skills/services/SKILL.md +32 -0
  361. package/assets/techne/skills/services/reference/api-contracts.md +139 -0
  362. package/assets/techne/skills/services/reference/backend-layers.md +95 -0
  363. package/assets/techne/skills/services/reference/errors-and-resilience.md +146 -0
  364. package/assets/techne/skills/services/reference/hexagonal-boundaries.md +93 -0
  365. package/assets/techne/skills/services/reference/mcp-servers.md +50 -0
  366. package/assets/techne/skills/services/reference/nestjs.md +96 -0
  367. package/assets/techne/skills/swift/SKILL.md +29 -0
  368. package/assets/techne/skills/swift/reference/concurrency.md +83 -0
  369. package/assets/techne/skills/swift/reference/swiftui.md +139 -0
  370. package/assets/techne/skills/vue/SKILL.md +29 -0
  371. package/assets/techne/skills/vue/reference/nuxt4-patterns.md +90 -0
  372. package/assets/techne/skills/vue/reference/ui-to-vue.md +90 -0
  373. package/assets/techne/skills/vue/reference/vue-patterns.md +151 -0
  374. package/assets/techne/skills/web/SKILL.md +30 -0
  375. package/assets/techne/skills/web/reference/bun-runtime.md +55 -0
  376. package/assets/techne/skills/web/reference/frontend-patterns.md +54 -0
  377. package/assets/techne/skills/web/reference/seo.md +77 -0
  378. package/assets/techne/skills/web/reference/vite-patterns.md +96 -0
  379. package/bin/native.cjs +30 -0
  380. package/native/aarch64-apple-darwin/exonous +0 -0
  381. package/native/aarch64-unknown-linux-gnu/exonous +0 -0
  382. package/native/x86_64-apple-darwin/exonous +0 -0
  383. package/native/x86_64-pc-windows-msvc/exonous.exe +0 -0
  384. package/native/x86_64-unknown-linux-gnu/exonous +0 -0
  385. package/package.json +1 -6
@@ -0,0 +1,25 @@
1
+ ---
2
+ paths:
3
+ - "**/*.css"
4
+ - "**/*.scss"
5
+ - "**/*.sass"
6
+ - "**/*.less"
7
+ - "**/*.html"
8
+ - "**/*.tsx"
9
+ - "**/*.jsx"
10
+ - "**/*.vue"
11
+ - "**/*.svelte"
12
+ ---
13
+ > Builds on the shared rules in `../common/coding-style.md`.
14
+
15
+ # Web coding style
16
+
17
+ Group by feature (component folders with colocated styles). Design tokens in CSS variables — spacing, type, color, motion — not scattered literals.
18
+
19
+ Animate `transform`, `opacity`, `clip-path`; avoid layout properties (`width`, `margin`, `top`, etc.).
20
+
21
+ Semantic HTML (`header`, `nav`, `main`, `section`) before div soup.
22
+
23
+ Naming: PascalCase components; `use*` hooks; kebab-case classes; camelCase animation ids.
24
+
25
+ Deep patterns: load **techne:web** skill on demand.
@@ -0,0 +1,21 @@
1
+ ---
2
+ paths:
3
+ - "**/*.css"
4
+ - "**/*.scss"
5
+ - "**/*.sass"
6
+ - "**/*.less"
7
+ - "**/*.html"
8
+ - "**/*.tsx"
9
+ - "**/*.jsx"
10
+ - "**/*.vue"
11
+ - "**/*.svelte"
12
+ ---
13
+ > Builds on the shared rules in `../common/patterns.md`.
14
+
15
+ # Web design quality
16
+
17
+ Avoid generic template UI. Before coding: pick a deliberate direction (not vague "clean minimal"); define palette and type; gather references; use **ui-design** (`audit`, `harden`) for a11y/finish.
18
+
19
+ Ship hierarchy, rhythm, states (hover/focus/active), and intentional light/dark when both exist. Skip stock hero + gradient blob defaults and uniform card grids with no POV.
20
+
21
+ Checklist: not a default component-library clone; believable in a product screenshot; meaningful interaction states.
@@ -0,0 +1,39 @@
1
+ ---
2
+ paths:
3
+ - "**/*.css"
4
+ - "**/*.scss"
5
+ - "**/*.sass"
6
+ - "**/*.less"
7
+ - "**/*.html"
8
+ - "**/*.tsx"
9
+ - "**/*.jsx"
10
+ - "**/*.vue"
11
+ - "**/*.svelte"
12
+ ---
13
+ > Builds on the shared rules in `../common/hooks.md`.
14
+
15
+ # Web hooks
16
+
17
+ Wire hooks to the repo package manager (`pnpm`/`yarn`/`npm exec`) — never remote one-off runners.
18
+
19
+ ## PostToolUse (Write|Edit)
20
+
21
+ 1. Format (`prettier --write "$FILE_PATH"`)
22
+ 2. Lint (`eslint --fix "$FILE_PATH"`)
23
+ 3. Typecheck (project): `timeout 60 pnpm tsc --noEmit --incremental --tsBuildInfoFile node_modules/.cache/tsc-hook.tsbuildinfo`
24
+
25
+ Without `--incremental` + cache path, rapid edits stack concurrent `tsc` processes. Without `timeout`, hung checks orphan shells.
26
+
27
+ Optional: `stylelint --fix` on stylesheets.
28
+
29
+ ## PreToolUse
30
+
31
+ Reject Write tool payloads over ~800 lines — split modules instead.
32
+
33
+ ## Stop
34
+
35
+ Run production `build` when the session touched bundler config or shared components.
36
+
37
+ ## Controls
38
+
39
+ `EXONOUS_HOOK_PROFILE`, `EXONOUS_DISABLED_HOOKS`.
@@ -0,0 +1,23 @@
1
+ ---
2
+ paths:
3
+ - "**/*.css"
4
+ - "**/*.scss"
5
+ - "**/*.sass"
6
+ - "**/*.less"
7
+ - "**/*.html"
8
+ - "**/*.tsx"
9
+ - "**/*.jsx"
10
+ - "**/*.vue"
11
+ - "**/*.svelte"
12
+ ---
13
+ > Builds on the shared rules in `../common/patterns.md`.
14
+
15
+ # Web patterns
16
+
17
+ Compound components + context for complex widgets. Container/presentational split: data vs pure UI.
18
+
19
+ State: server cache (TanStack Query/SWR), client store only for UI, URL for filters/tabs/pagination, form library for forms — no duplicated server cache in client stores.
20
+
21
+ Stale-while-revalidate and optimistic updates with rollback UX. Parallel fetches; avoid request waterfalls.
22
+
23
+ See **techne:web** for Vite/SEO depth.
@@ -0,0 +1,25 @@
1
+ ---
2
+ paths:
3
+ - "**/*.css"
4
+ - "**/*.scss"
5
+ - "**/*.sass"
6
+ - "**/*.less"
7
+ - "**/*.html"
8
+ - "**/*.tsx"
9
+ - "**/*.jsx"
10
+ - "**/*.vue"
11
+ - "**/*.svelte"
12
+ ---
13
+ > Builds on the shared rules in `../common/performance.md`.
14
+
15
+ # Web performance
16
+
17
+ Targets: LCP <2.5s, INP <200ms, CLS <0.1. Budgets (~150kb gzip JS landing, ~300kb app — tune per product).
18
+
19
+ Inline critical CSS when justified; preload hero font/image; defer rest; dynamic-import heavy libs.
20
+
21
+ Images: dimensions set; lazy below fold; modern formats. Fonts: ≤2 families, `font-display: swap`.
22
+
23
+ Motion on compositor props only; narrow `will-change`.
24
+
25
+ Checklist: no layout shift from late content; third parties async/defer.
@@ -0,0 +1,23 @@
1
+ ---
2
+ paths:
3
+ - "**/*.css"
4
+ - "**/*.scss"
5
+ - "**/*.sass"
6
+ - "**/*.less"
7
+ - "**/*.html"
8
+ - "**/*.tsx"
9
+ - "**/*.jsx"
10
+ - "**/*.vue"
11
+ - "**/*.svelte"
12
+ ---
13
+ > Builds on the shared rules in `../common/security.md`.
14
+
15
+ # Web security
16
+
17
+ Production CSP with nonces for scripts where possible; tighten per project. No unsanitized HTML (`innerHTML` / framework escape hatches) without sanitizer.
18
+
19
+ Third-party scripts: async, SRI on CDNs, periodic audit. Security headers: HSTS, `nosniff`, frame deny, referrer policy, permissions policy.
20
+
21
+ Forms: CSRF on mutations; server validation; rate limits.
22
+
23
+ **exo-security** for deep review.
@@ -0,0 +1,21 @@
1
+ ---
2
+ paths:
3
+ - "**/*.css"
4
+ - "**/*.scss"
5
+ - "**/*.sass"
6
+ - "**/*.less"
7
+ - "**/*.html"
8
+ - "**/*.tsx"
9
+ - "**/*.jsx"
10
+ - "**/*.vue"
11
+ - "**/*.svelte"
12
+ ---
13
+ > Builds on the shared rules in `../common/testing.md`.
14
+
15
+ # Web testing
16
+
17
+ Priority: visual regression at key breakpoints → a11y (keyboard, contrast, reduced motion) → Lighthouse/CWV → cross-browser (Chrome/Firefox/Safari) → responsive widths.
18
+
19
+ Playwright for E2E/visual; unit tests for utilities/hooks. Deterministic waits, not arbitrary sleeps.
20
+
21
+ **techne:quality** skill for broader QA patterns.
@@ -0,0 +1,50 @@
1
+ // PreToolUse(Write|Edit|MultiEdit): keep agents from loosening lint/format configs to make checks pass.
2
+ // Creating a config that does not exist yet is allowed; editing an existing one is not.
3
+ 'use strict';
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+
8
+ const EXACT = new Set([
9
+ '.eslintrc', '.eslintignore',
10
+ '.prettierrc', '.prettierignore',
11
+ 'biome.json', 'biome.jsonc', '.biome.json', '.biome.jsonc',
12
+ 'ruff.toml', '.ruff.toml', '.flake8', '.pylintrc',
13
+ '.stylelintrc', '.stylelintignore',
14
+ '.markdownlintrc', '.markdownlintignore',
15
+ '.shellcheckrc',
16
+ '.golangci.yml', '.golangci.yaml', '.golangci.toml', '.golangci.json',
17
+ '.rubocop.yml', '.swiftlint.yml', '.oxlintrc.json',
18
+ ]);
19
+
20
+ const PATTERNS = [
21
+ // eslint.config.mjs, prettier.config.base.cjs, stylelint.config.shared.ts, …
22
+ /^(eslint|prettier|stylelint|commitlint|oxlint)\.config(\.[\w-]+)*\.(js|mjs|cjs|ts|mts|cts)$/,
23
+ // .eslintrc.json, .prettierrc.shared.yml, .stylelintrc.base.cjs, .markdownlint.jsonc, …
24
+ /^\.(eslintrc|prettierrc|stylelintrc|markdownlintrc|markdownlint|markdownlint-cli2)(\.[\w-]+)*\.(js|mjs|cjs|ts|json|jsonc|yml|yaml|toml)$/,
25
+ ];
26
+
27
+ function isGuarded(file) {
28
+ const name = path.basename(file).toLowerCase();
29
+ return EXACT.has(name) || PATTERNS.some((re) => re.test(name));
30
+ }
31
+
32
+ module.exports = function configGuard(payload, { truncated }) {
33
+ if (process.env.EXONOUS_ALLOW_CONFIG_EDITS === '1') return null;
34
+ if (truncated) return { block: 'Hook payload too large to inspect; refusing the edit. Make a smaller edit.' };
35
+ const input = payload?.tool_input || {};
36
+ const file = input.file_path || input.path;
37
+ if (typeof file !== 'string' || !isGuarded(file)) return null;
38
+
39
+ const absolute = path.resolve(payload.cwd || process.cwd(), file);
40
+ try {
41
+ fs.lstatSync(absolute);
42
+ } catch (err) {
43
+ if (err.code === 'ENOENT') return null;
44
+ }
45
+ return {
46
+ block: `${path.basename(file)} is a lint/format config. Fix the code so it satisfies the rules instead of weakening them. If the user asked for this config change, they can allow it with EXONOUS_ALLOW_CONFIG_EDITS=1.`,
47
+ };
48
+ };
49
+
50
+ module.exports.isGuarded = isGuarded;
@@ -0,0 +1,26 @@
1
+ // PostToolUse(Edit|Write|MultiEdit): remember which files this session touched, for stop:checks.
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const os = require('os');
6
+ const path = require('path');
7
+
8
+ function listFile(sessionId) {
9
+ const id = String(sessionId || 'default').replace(/[^A-Za-z0-9_-]/g, '_').slice(0, 128) || 'default';
10
+ return path.join(os.tmpdir(), `techne-edits-${id}.txt`);
11
+ }
12
+
13
+ module.exports = function editTracker(payload) {
14
+ const input = payload?.tool_input || {};
15
+ const file = input.file_path || input.path;
16
+ if (typeof file !== 'string' || !file) return null;
17
+ const absolute = path.resolve(payload.cwd || process.cwd(), file);
18
+ try {
19
+ fs.appendFileSync(listFile(payload.session_id), `${absolute}\n`, 'utf8');
20
+ } catch (err) {
21
+ process.stderr.write(`[techne] edit list not updated: ${err.message}\n`);
22
+ }
23
+ return null;
24
+ };
25
+
26
+ module.exports.listFile = listFile;
@@ -0,0 +1,204 @@
1
+ // Minimal POSIX-shell lexer for hook guards. It does not evaluate anything; it answers
2
+ // "which simple commands would run, with which words" well enough to spot flags.
3
+ // Output: flat list of { words: string[], heredocs: string[] } — one per simple command,
4
+ // including commands inside $(...), backticks and ( ... ) subshells.
5
+ 'use strict';
6
+
7
+ const SEPARATORS = new Set([';', '&', '|']);
8
+ const WORD_BREAK = /[\s;&|<>()]/;
9
+
10
+ function lex(src, maxDepth = 8) {
11
+ const out = [];
12
+ scan(src, 0, null, out, maxDepth);
13
+ return out;
14
+ }
15
+
16
+ function scan(src, start, closer, out, depth) {
17
+ let segment = { words: [], heredocs: [] };
18
+ let word = null;
19
+ let skipNext = false;
20
+ let pending = [];
21
+ let i = start;
22
+
23
+ const endWord = () => {
24
+ if (word === null) return;
25
+ if (skipNext) skipNext = false;
26
+ else segment.words.push(word);
27
+ word = null;
28
+ };
29
+ const endSegment = () => {
30
+ endWord();
31
+ if (segment.words.length || segment.heredocs.length) out.push(segment);
32
+ segment = { words: [], heredocs: [] };
33
+ };
34
+ const nested = (from, close) => {
35
+ if (depth <= 0) return skipTo(src, from, close);
36
+ return scan(src, from, close, out, depth - 1);
37
+ };
38
+ const readBodies = (from) => {
39
+ let pos = from;
40
+ for (const doc of pending) {
41
+ const lines = [];
42
+ while (pos < src.length) {
43
+ const nl = src.indexOf('\n', pos);
44
+ const line = src.slice(pos, nl === -1 ? src.length : nl);
45
+ pos = nl === -1 ? src.length : nl + 1;
46
+ if ((doc.strip ? line.replace(/^\t+/, '') : line) === doc.delim) break;
47
+ lines.push(line);
48
+ }
49
+ doc.segment.heredocs.push(lines.join('\n'));
50
+ }
51
+ pending = [];
52
+ return pos;
53
+ };
54
+
55
+ while (i < src.length) {
56
+ const c = src[i];
57
+
58
+ if (closer && c === closer && closer !== '`') {
59
+ endSegment();
60
+ return i + 1;
61
+ }
62
+ if (closer === '`' && c === '`') {
63
+ endSegment();
64
+ return i + 1;
65
+ }
66
+ if (c === '\n') {
67
+ endSegment();
68
+ i = pending.length ? readBodies(i + 1) : i + 1;
69
+ continue;
70
+ }
71
+ if (c === ' ' || c === '\t' || c === '\r') {
72
+ endWord();
73
+ i++;
74
+ continue;
75
+ }
76
+ if (SEPARATORS.has(c)) {
77
+ endSegment();
78
+ i++;
79
+ continue;
80
+ }
81
+ if (c === '#' && word === null) {
82
+ while (i < src.length && src[i] !== '\n') i++;
83
+ continue;
84
+ }
85
+ if (c === '(' && word === null) {
86
+ endSegment();
87
+ i = nested(i + 1, ')');
88
+ continue;
89
+ }
90
+ if (c === '<' || c === '>') {
91
+ endWord();
92
+ if (src.startsWith('<<<', i)) {
93
+ skipNext = true;
94
+ i += 3;
95
+ continue;
96
+ }
97
+ if (c === '<' && src[i + 1] === '<') {
98
+ i += 2;
99
+ const strip = src[i] === '-';
100
+ if (strip) i++;
101
+ while (src[i] === ' ' || src[i] === '\t') i++;
102
+ const delim = readDelimiter(src, i);
103
+ i = delim.end;
104
+ pending.push({ delim: delim.text, strip, segment });
105
+ continue;
106
+ }
107
+ i++;
108
+ while (src[i] === '>' || src[i] === '&' || src[i] === '|') i++;
109
+ if (/\d/.test(src[i] || '')) {
110
+ while (/\d/.test(src[i] || '')) i++;
111
+ if (src[i] === '-') i++;
112
+ continue;
113
+ }
114
+ skipNext = true;
115
+ continue;
116
+ }
117
+ if (c === '\\') {
118
+ if (src[i + 1] !== '\n') word = (word ?? '') + (src[i + 1] ?? '');
119
+ i += 2;
120
+ continue;
121
+ }
122
+ if (c === "'") {
123
+ const end = src.indexOf("'", i + 1);
124
+ const stop = end === -1 ? src.length : end;
125
+ word = (word ?? '') + src.slice(i + 1, stop);
126
+ i = stop + 1;
127
+ continue;
128
+ }
129
+ if (c === '$' && src[i + 1] === "'") {
130
+ let j = i + 2;
131
+ let text = '';
132
+ while (j < src.length && src[j] !== "'") {
133
+ if (src[j] === '\\' && j + 1 < src.length) j++;
134
+ text += src[j++];
135
+ }
136
+ word = (word ?? '') + text;
137
+ i = j + 1;
138
+ continue;
139
+ }
140
+ if (c === '"') {
141
+ word = word ?? '';
142
+ i++;
143
+ while (i < src.length && src[i] !== '"') {
144
+ if (src[i] === '\\' && '"\\$`\n'.includes(src[i + 1])) {
145
+ if (src[i + 1] !== '\n') word += src[i + 1];
146
+ i += 2;
147
+ } else if (src[i] === '$' && src[i + 1] === '(' && src[i + 2] !== '(') {
148
+ i = nested(i + 2, ')');
149
+ } else if (src[i] === '`') {
150
+ i = nested(i + 1, '`');
151
+ } else {
152
+ word += src[i++];
153
+ }
154
+ }
155
+ i++;
156
+ continue;
157
+ }
158
+ if (c === '$' && src[i + 1] === '(') {
159
+ if (src[i + 2] === '(') {
160
+ i = skipTo(src, i + 3, '))');
161
+ } else {
162
+ word = word ?? '';
163
+ i = nested(i + 2, ')');
164
+ }
165
+ continue;
166
+ }
167
+ if (c === '`') {
168
+ word = word ?? '';
169
+ i = nested(i + 1, '`');
170
+ continue;
171
+ }
172
+ word = (word ?? '') + c;
173
+ i++;
174
+ }
175
+ endSegment();
176
+ return src.length;
177
+ }
178
+
179
+ function readDelimiter(src, i) {
180
+ let text = '';
181
+ while (i < src.length && !WORD_BREAK.test(src[i])) {
182
+ const c = src[i];
183
+ if (c === "'" || c === '"') {
184
+ const end = src.indexOf(c, i + 1);
185
+ const stop = end === -1 ? src.length : end;
186
+ text += src.slice(i + 1, stop);
187
+ i = stop + 1;
188
+ } else if (c === '\\') {
189
+ text += src[i + 1] ?? '';
190
+ i += 2;
191
+ } else {
192
+ text += c;
193
+ i++;
194
+ }
195
+ }
196
+ return { text, end: i };
197
+ }
198
+
199
+ function skipTo(src, from, token) {
200
+ const at = src.indexOf(token, from);
201
+ return at === -1 ? src.length : at + token.length;
202
+ }
203
+
204
+ module.exports = { lex };
@@ -0,0 +1,205 @@
1
+ // PreToolUse(Bash): refuse git invocations that would skip the repository's git hooks.
2
+ 'use strict';
3
+
4
+ const path = require('path');
5
+ const { lex } = require('./lib/shell');
6
+
7
+ const HOOK_RUNNING = new Set(['commit', 'push', 'merge', 'cherry-pick', 'rebase', 'am']);
8
+ const SHELLS = new Set(['sh', 'bash', 'dash', 'zsh', 'ksh']);
9
+ const KEYWORDS = new Set(['if', 'then', 'else', 'elif', 'do', 'while', 'until', '!', '{', '}', 'time']);
10
+ const GIT_GLOBALS_WITH_VALUE = new Set(['-C', '--work-tree', '--git-dir', '--namespace', '--super-prefix', '--exec-path']);
11
+ const SUDO_WITH_VALUE = new Set(['-u', '-g', '-h', '-p', '-C', '-D', '-r', '-t', '-U']);
12
+ const ASSIGNMENT = /^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/s;
13
+ const NO_VERIFY = '--no-verify';
14
+
15
+ // Long options that consume the next word, per subcommand (values are data, not flags).
16
+ const LONG_WITH_VALUE = {
17
+ commit: ['--message', '--file', '--reuse-message', '--reedit-message', '--template', '--author', '--date', '--cleanup', '--fixup', '--squash', '--trailer', '--pathspec-from-file'],
18
+ merge: ['--message', '--file', '--strategy', '--strategy-option', '--into-name'],
19
+ push: ['--push-option', '--repo', '--receive-pack', '--exec'],
20
+ rebase: ['--exec', '--strategy', '--strategy-option', '--onto'],
21
+ 'cherry-pick': ['--mainline', '--strategy', '--strategy-option'],
22
+ am: ['--patch-format', '--directory', '--exclude', '--include', '--resolvemsg'],
23
+ };
24
+ // Short options whose value is the rest of the cluster or the next word.
25
+ const SHORT_WITH_VALUE = {
26
+ commit: 'mFCct',
27
+ merge: 'mFsX',
28
+ push: 'o',
29
+ rebase: 'xsX',
30
+ 'cherry-pick': 'msX',
31
+ am: 'pC',
32
+ };
33
+ const SHORT_OPTIONAL_VALUE = { commit: 'uS', merge: 'S', rebase: 'S', 'cherry-pick': 'S', am: 'S' };
34
+
35
+ const isNoVerify = (word) => word.length >= 9 && NO_VERIFY.startsWith(word);
36
+ const isHooksPathKey = (key) => key.trim().toLowerCase() === 'core.hookspath';
37
+
38
+ function overridesHooksPath(env) {
39
+ for (const [name, value] of env) {
40
+ if (/^GIT_CONFIG_KEY_\d+$/.test(name) && isHooksPathKey(value)) return true;
41
+ if (name === 'GIT_CONFIG_PARAMETERS' && value.toLowerCase().includes('core.hookspath')) return true;
42
+ }
43
+ return false;
44
+ }
45
+
46
+ // Strips wrappers (env, sudo, command, …) and prefix assignments; returns the real command words.
47
+ function unwrap(words, env) {
48
+ let i = 0;
49
+ const take = () => {
50
+ while (i < words.length) {
51
+ const m = words[i].match(ASSIGNMENT);
52
+ if (m) env.set(m[1], m[2]);
53
+ else if (!KEYWORDS.has(words[i])) break;
54
+ i++;
55
+ }
56
+ };
57
+ take();
58
+ for (;;) {
59
+ const cmd = path.basename(words[i] || '');
60
+ if (cmd === 'env') {
61
+ i++;
62
+ while (i < words.length && (words[i].startsWith('-') || ASSIGNMENT.test(words[i]))) {
63
+ if (words[i] === '-u' || words[i] === '-S') i++;
64
+ else if (!words[i].startsWith('-')) {
65
+ const m = words[i].match(ASSIGNMENT);
66
+ env.set(m[1], m[2]);
67
+ }
68
+ i++;
69
+ }
70
+ } else if (cmd === 'sudo' || cmd === 'doas' || cmd === 'nice' || cmd === 'nohup' || cmd === 'command' || cmd === 'exec' || cmd === 'builtin') {
71
+ i++;
72
+ while (i < words.length && words[i].startsWith('-')) {
73
+ if (SUDO_WITH_VALUE.has(words[i]) || (cmd === 'nice' && words[i] === '-n')) i++;
74
+ i++;
75
+ }
76
+ } else break;
77
+ take();
78
+ }
79
+ return words.slice(i);
80
+ }
81
+
82
+ function checkGit(args, env, scanNested) {
83
+ let i = 1;
84
+ let hooksOverride = overridesHooksPath(env);
85
+ while (i < args.length && args[i].startsWith('-')) {
86
+ const arg = args[i];
87
+ if (arg === '-c') {
88
+ if (isHooksPathKey((args[i + 1] || '').split('=')[0])) hooksOverride = true;
89
+ i += 2;
90
+ } else if (arg.startsWith('-c')) {
91
+ if (isHooksPathKey(arg.slice(2).split('=')[0])) hooksOverride = true;
92
+ i++;
93
+ } else if (arg === '--config-env') {
94
+ if (isHooksPathKey((args[i + 1] || '').split('=')[0])) hooksOverride = true;
95
+ i += 2;
96
+ } else if (arg.startsWith('--config-env=')) {
97
+ if (isHooksPathKey(arg.slice('--config-env='.length).split('=')[0])) hooksOverride = true;
98
+ i++;
99
+ } else if (GIT_GLOBALS_WITH_VALUE.has(arg)) {
100
+ i += 2;
101
+ } else {
102
+ i++;
103
+ }
104
+ }
105
+ const sub = args[i];
106
+ const rest = args.slice(i + 1);
107
+
108
+ if (sub === 'config' && setsHooksPath(rest)) {
109
+ return 'Setting core.hooksPath is not allowed: it disables the repository git hooks.';
110
+ }
111
+ if (!HOOK_RUNNING.has(sub)) return null;
112
+ if (hooksOverride) return `Overriding core.hooksPath on git ${sub} is not allowed: git hooks must run.`;
113
+
114
+ const longValue = new Set(LONG_WITH_VALUE[sub]);
115
+ const shortValue = SHORT_WITH_VALUE[sub] || '';
116
+ const shortOptional = SHORT_OPTIONAL_VALUE[sub] || '';
117
+ for (let j = 0; j < rest.length; j++) {
118
+ const word = rest[j];
119
+ if (word === '--') break;
120
+ if (word.startsWith('--')) {
121
+ const [name, inline] = word.split(/=(.*)/s);
122
+ if (isNoVerify(name)) return `git ${sub} ${NO_VERIFY} is not allowed: fix what the hook reports instead of skipping it.`;
123
+ if (longValue.has(name) && inline === undefined) {
124
+ if (sub === 'rebase' && name === '--exec' && rest[j + 1]) scanNested(rest[j + 1]);
125
+ j++;
126
+ } else if (sub === 'rebase' && name === '--exec' && inline) {
127
+ scanNested(inline);
128
+ }
129
+ continue;
130
+ }
131
+ if (!/^-[A-Za-z]/.test(word)) continue;
132
+ for (let k = 1; k < word.length; k++) {
133
+ const flag = word[k];
134
+ if (flag === 'n' && sub === 'commit') return 'git commit -n skips the commit hooks and is not allowed.';
135
+ if (shortOptional.includes(flag)) break;
136
+ if (shortValue.includes(flag)) {
137
+ const value = k + 1 < word.length ? word.slice(k + 1) : rest[++j];
138
+ if (sub === 'rebase' && flag === 'x' && value) scanNested(value);
139
+ break;
140
+ }
141
+ }
142
+ }
143
+ return null;
144
+ }
145
+
146
+ function setsHooksPath(rest) {
147
+ const positional = [];
148
+ for (const word of rest) {
149
+ if (word === '--unset' || word === '--unset-all' || word === '--get' || word === '--get-all' || word === 'unset' || word === 'get') return false;
150
+ if (!word.startsWith('-')) positional.push(word);
151
+ }
152
+ if (positional[0] === 'set') positional.shift();
153
+ if (!positional.length) return false;
154
+ const [key, inline] = positional[0].split(/=(.*)/s);
155
+ return isHooksPathKey(key) && (inline !== undefined || positional.length >= 2);
156
+ }
157
+
158
+ function inspect(command, depth = 0) {
159
+ if (depth > 4) return null;
160
+ const env = new Map();
161
+ const nestedReasons = [];
162
+ const scanNested = (script) => {
163
+ const reason = inspect(script, depth + 1);
164
+ if (reason) nestedReasons.push(reason);
165
+ };
166
+
167
+ for (const segment of lex(command)) {
168
+ const local = new Map(env);
169
+ const words = unwrap(segment.words, local);
170
+ if (!words.length) {
171
+ for (const [k, v] of local) env.set(k, v);
172
+ continue;
173
+ }
174
+ const cmd = path.basename(words[0]);
175
+ if (cmd === 'export') {
176
+ for (const word of words.slice(1)) {
177
+ const m = word.match(ASSIGNMENT);
178
+ if (m) env.set(m[1], m[2]);
179
+ }
180
+ continue;
181
+ }
182
+ if (cmd === 'git') {
183
+ const reason = checkGit(words, local, scanNested);
184
+ if (reason) return reason;
185
+ } else if (SHELLS.has(cmd)) {
186
+ const flagIndex = words.findIndex((w, idx) => idx > 0 && /^-[a-zA-Z]*c[a-zA-Z]*$/.test(w));
187
+ if (flagIndex !== -1 && words[flagIndex + 1]) scanNested(words[flagIndex + 1]);
188
+ else segment.heredocs.forEach(scanNested);
189
+ } else if (cmd === 'eval') {
190
+ scanNested(words.slice(1).join(' '));
191
+ }
192
+ if (nestedReasons.length) return nestedReasons[0];
193
+ }
194
+ return nestedReasons[0] || null;
195
+ }
196
+
197
+ module.exports = function noVerifyGuard(payload, { truncated }) {
198
+ if (truncated) return { block: 'Hook payload too large to inspect; refusing the command. Split it into smaller commands.' };
199
+ const command = payload?.tool_input?.command;
200
+ if (typeof command !== 'string' || !/git|GIT_CONFIG/.test(command)) return null;
201
+ const reason = inspect(command);
202
+ return reason ? { block: reason } : null;
203
+ };
204
+
205
+ module.exports.inspect = inspect;