@r1z4x/tezgah 1.9.2 → 1.13.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 (445) hide show
  1. package/CHANGELOG.md +415 -1
  2. package/MANIFEST +404 -144
  3. package/README.de.md +1 -1
  4. package/README.es.md +1 -1
  5. package/README.fr.md +1 -1
  6. package/README.md +5 -4
  7. package/README.tr.md +1 -1
  8. package/bin/codegen +5 -2
  9. package/bin/tezgah-design +288 -1
  10. package/bin/tezgah-docs +1 -1
  11. package/bin/tezgah-doctor +39 -2
  12. package/bin/tezgah-import-ai-research +26 -12
  13. package/bin/tezgah-ocr-review +296 -0
  14. package/bin/tezgah-research +255 -44
  15. package/bin/tezgah-review-quote +185 -0
  16. package/bin/tezgah-setup +1365 -55
  17. package/bin/tezgah-skill +1 -1
  18. package/bin/tezgah-status +201 -3
  19. package/bin/tezgah-task +258 -20
  20. package/commands/adhd.md +2 -2
  21. package/commands/ponytail.md +4 -4
  22. package/docs/architecture.md +2 -2
  23. package/docs/citations-baseline.json +3 -3
  24. package/docs/clarity-baseline.json +11 -5
  25. package/docs/contract.md +91 -43
  26. package/docs/environment.md +5 -2
  27. package/docs/evidence.md +109 -17
  28. package/docs/feature-audit.md +2 -2
  29. package/docs/gate.md +60 -33
  30. package/docs/glossary.md +6 -3
  31. package/docs/hosts.md +313 -17
  32. package/docs/index.json +34 -8
  33. package/docs/judge.md +4 -2
  34. package/docs/layers.md +4 -4
  35. package/docs/models.md +37 -9
  36. package/docs/operations.md +141 -5
  37. package/docs/research.md +815 -8
  38. package/docs/skills.md +137 -13
  39. package/docs/status-line.md +121 -1
  40. package/docs/testing.md +3 -1
  41. package/hooks/hooks.json +2 -2
  42. package/hooks/lang/en.json +21 -0
  43. package/hooks/lang/tr.json +22 -1
  44. package/hooks/projects-stop.py +2 -1
  45. package/hooks/tezgah_agents.py +65 -25
  46. package/hooks/tezgah_apps.py +18 -0
  47. package/hooks/tezgah_attest.py +79 -10
  48. package/hooks/tezgah_components.py +4 -0
  49. package/hooks/tezgah_context.py +207 -55
  50. package/hooks/tezgah_extension.py +337 -0
  51. package/hooks/tezgah_gate.py +267 -79
  52. package/hooks/tezgah_integrity.py +864 -143
  53. package/hooks/tezgah_judge.py +6 -4
  54. package/hooks/tezgah_models.py +59 -19
  55. package/hooks/tezgah_orca.py +1 -1
  56. package/hooks/tezgah_paths.py +145 -8
  57. package/hooks/tezgah_policy.py +128 -57
  58. package/hooks/tezgah_rank.py +9 -6
  59. package/hooks/tezgah_replay.py +12 -6
  60. package/hooks/tezgah_research.py +1414 -76
  61. package/hooks/tezgah_research_capture.py +1544 -0
  62. package/hooks/tezgah_research_evidence.py +842 -0
  63. package/hooks/tezgah_research_stats.py +258 -0
  64. package/hooks/tezgah_skill_pick.py +408 -106
  65. package/hooks/tezgah_stack.py +236 -1
  66. package/hooks/tezgah_stopspec.py +8 -1
  67. package/hooks/tezgah_task.py +14 -5
  68. package/hooks/tezgah_taste_ledger.py +1 -1
  69. package/hosts/amp/hook.py +217 -0
  70. package/hosts/amp/tezgah-plugin.ts.in +386 -0
  71. package/hosts/antigravity/hook.py +255 -0
  72. package/hosts/codex/hook.py +2 -1
  73. package/hosts/commandcode/hook.py +239 -0
  74. package/hosts/copilot/hook.py +284 -0
  75. package/hosts/cursor/hook.py +31 -3
  76. package/hosts/droid/hook.py +259 -0
  77. package/hosts/dsh/hooks.json +1 -1
  78. package/hosts/gemini/hook.py +213 -0
  79. package/hosts/goose/hook.py +145 -0
  80. package/hosts/omp/hook.py +4 -1
  81. package/hosts/omp/tezgah-hook.ts.in +30 -7
  82. package/hosts/opencode/plugins/tezgah.js +309 -48
  83. package/hosts/opencode/tui/cli/tui.tsx +100 -0
  84. package/hosts/opencode/tui/tezgah-tui.tsx +2 -1
  85. package/hosts/qwen/hook.py +206 -0
  86. package/output-styles/tezgah.md +20 -15
  87. package/package.json +1 -1
  88. package/skills/ai-research/SKILL.md +21 -14
  89. package/skills/ai-research/SOURCE +7 -5
  90. package/skills/ai-research/index/1-frame.md +6 -6
  91. package/skills/ai-research/index/2-data.md +9 -9
  92. package/skills/ai-research/index/3-train.md +36 -36
  93. package/skills/ai-research/index/4-measure.md +13 -13
  94. package/skills/ai-research/index/5-run.md +11 -11
  95. package/skills/ai-research/index/6-write.md +23 -23
  96. package/skills/ai-research/library.json +104 -104
  97. package/skills/analyze-app/SKILL.md +17 -12
  98. package/skills/design-contract/SKILL.md +42 -7
  99. package/skills/design-contract/data-views.md +2 -2
  100. package/skills/design-library/EVALS.md +1 -1
  101. package/skills/design-library/INDEX.md +39 -39
  102. package/skills/design-library/SKILL.md +19 -13
  103. package/skills/design-library/SOURCE +45 -43
  104. package/skills/feature-audit/SKILL.md +20 -14
  105. package/skills/hallmark/LICENSE +21 -0
  106. package/skills/hallmark/SKILL.md +154 -0
  107. package/skills/hallmark/SOURCE +207 -0
  108. package/skills/hallmark/agents/openai.yaml +13 -0
  109. package/skills/hallmark/references/anatomy.md +71 -0
  110. package/skills/hallmark/references/brand-truth.md +40 -0
  111. package/skills/hallmark/references/comp.md +104 -0
  112. package/skills/hallmark/references/craft.md +116 -0
  113. package/skills/hallmark/references/dark-mode.md +49 -0
  114. package/skills/hallmark/references/data-viz.md +48 -0
  115. package/skills/hallmark/references/design-md.md +53 -0
  116. package/skills/hallmark/references/direction.md +52 -0
  117. package/skills/hallmark/references/export-formats.md +80 -0
  118. package/skills/hallmark/references/flow.md +131 -0
  119. package/skills/hallmark/references/fonts.md +58 -0
  120. package/skills/hallmark/references/gates.md +243 -0
  121. package/skills/hallmark/references/genres/atmospheric.md +24 -0
  122. package/skills/hallmark/references/genres/editorial.md +24 -0
  123. package/skills/hallmark/references/genres/modern-minimal.md +24 -0
  124. package/skills/hallmark/references/genres/playful.md +24 -0
  125. package/skills/hallmark/references/imagery.md +99 -0
  126. package/skills/hallmark/references/interaction-and-states.md +89 -0
  127. package/skills/hallmark/references/layout.md +104 -0
  128. package/skills/hallmark/references/macrostructures/01-bento-grid.md +21 -0
  129. package/skills/hallmark/references/macrostructures/02-long-document.md +35 -0
  130. package/skills/hallmark/references/macrostructures/03-marquee-hero.md +21 -0
  131. package/skills/hallmark/references/macrostructures/04-stat-led.md +21 -0
  132. package/skills/hallmark/references/macrostructures/05-workbench.md +21 -0
  133. package/skills/hallmark/references/macrostructures/06-conversational-faq.md +28 -0
  134. package/skills/hallmark/references/macrostructures/07-manifesto.md +28 -0
  135. package/skills/hallmark/references/macrostructures/08-photographic.md +21 -0
  136. package/skills/hallmark/references/macrostructures/09-quote-led.md +21 -0
  137. package/skills/hallmark/references/macrostructures/10-specimen.md +21 -0
  138. package/skills/hallmark/references/macrostructures/11-catalogue.md +21 -0
  139. package/skills/hallmark/references/macrostructures/12-letter.md +21 -0
  140. package/skills/hallmark/references/macrostructures/13-index-first.md +21 -0
  141. package/skills/hallmark/references/macrostructures/14-narrative-workflow.md +21 -0
  142. package/skills/hallmark/references/macrostructures/15-split-studio.md +21 -0
  143. package/skills/hallmark/references/macrostructures/16-feature-stack.md +23 -0
  144. package/skills/hallmark/references/macrostructures/17-type-specimen.md +19 -0
  145. package/skills/hallmark/references/macrostructures/18-portfolio-grid.md +21 -0
  146. package/skills/hallmark/references/macrostructures/19-map-diagram.md +21 -0
  147. package/skills/hallmark/references/macrostructures/20-ecosystem-index.md +19 -0
  148. package/skills/hallmark/references/macrostructures/21-component-playground.md +21 -0
  149. package/skills/hallmark/references/macrostructures.md +119 -0
  150. package/skills/hallmark/references/microinteractions.md +80 -0
  151. package/skills/hallmark/references/patterns.md +202 -0
  152. package/skills/hallmark/references/redesign.md +88 -0
  153. package/skills/hallmark/references/responsive.md +46 -0
  154. package/skills/hallmark/references/review-finish.md +19 -0
  155. package/skills/hallmark/references/review-hero.md +20 -0
  156. package/skills/hallmark/references/scroll-choreography.md +110 -0
  157. package/skills/hallmark/references/texture.md +90 -0
  158. package/skills/hallmark/references/themes/README.md +58 -0
  159. package/skills/hallmark/references/themes/almanac.jpg +0 -0
  160. package/skills/hallmark/references/themes/almanac.md +103 -0
  161. package/skills/hallmark/references/themes/arcade.jpg +0 -0
  162. package/skills/hallmark/references/themes/arcade.md +102 -0
  163. package/skills/hallmark/references/themes/atelier.jpg +0 -0
  164. package/skills/hallmark/references/themes/atelier.md +98 -0
  165. package/skills/hallmark/references/themes/bloom.jpg +0 -0
  166. package/skills/hallmark/references/themes/bloom.md +102 -0
  167. package/skills/hallmark/references/themes/blueprint.jpg +0 -0
  168. package/skills/hallmark/references/themes/blueprint.md +103 -0
  169. package/skills/hallmark/references/themes/broadside.jpg +0 -0
  170. package/skills/hallmark/references/themes/broadside.md +108 -0
  171. package/skills/hallmark/references/themes/brutal.jpg +0 -0
  172. package/skills/hallmark/references/themes/brutal.md +95 -0
  173. package/skills/hallmark/references/themes/carnival.jpg +0 -0
  174. package/skills/hallmark/references/themes/carnival.md +104 -0
  175. package/skills/hallmark/references/themes/cobalt.jpg +0 -0
  176. package/skills/hallmark/references/themes/cobalt.md +101 -0
  177. package/skills/hallmark/references/themes/console.jpg +0 -0
  178. package/skills/hallmark/references/themes/console.md +99 -0
  179. package/skills/hallmark/references/themes/coral.jpg +0 -0
  180. package/skills/hallmark/references/themes/coral.md +102 -0
  181. package/skills/hallmark/references/themes/darkroom.jpg +0 -0
  182. package/skills/hallmark/references/themes/darkroom.md +99 -0
  183. package/skills/hallmark/references/themes/dose.jpg +0 -0
  184. package/skills/hallmark/references/themes/dose.md +98 -0
  185. package/skills/hallmark/references/themes/dusk.jpg +0 -0
  186. package/skills/hallmark/references/themes/dusk.md +105 -0
  187. package/skills/hallmark/references/themes/editorial.jpg +0 -0
  188. package/skills/hallmark/references/themes/editorial.md +97 -0
  189. package/skills/hallmark/references/themes/formwork.jpg +0 -0
  190. package/skills/hallmark/references/themes/formwork.md +107 -0
  191. package/skills/hallmark/references/themes/furrow.jpg +0 -0
  192. package/skills/hallmark/references/themes/furrow.md +98 -0
  193. package/skills/hallmark/references/themes/garden.jpg +0 -0
  194. package/skills/hallmark/references/themes/garden.md +97 -0
  195. package/skills/hallmark/references/themes/grid.jpg +0 -0
  196. package/skills/hallmark/references/themes/grid.md +101 -0
  197. package/skills/hallmark/references/themes/halftone.jpg +0 -0
  198. package/skills/hallmark/references/themes/halftone.md +106 -0
  199. package/skills/hallmark/references/themes/hedgerow.jpg +0 -0
  200. package/skills/hallmark/references/themes/hedgerow.md +104 -0
  201. package/skills/hallmark/references/themes/hum.jpg +0 -0
  202. package/skills/hallmark/references/themes/hum.md +99 -0
  203. package/skills/hallmark/references/themes/index.json +2191 -0
  204. package/skills/hallmark/references/themes/ink.jpg +0 -0
  205. package/skills/hallmark/references/themes/ink.md +106 -0
  206. package/skills/hallmark/references/themes/kiln.jpg +0 -0
  207. package/skills/hallmark/references/themes/kiln.md +108 -0
  208. package/skills/hallmark/references/themes/loom.jpg +0 -0
  209. package/skills/hallmark/references/themes/loom.md +106 -0
  210. package/skills/hallmark/references/themes/lumen.jpg +0 -0
  211. package/skills/hallmark/references/themes/lumen.md +103 -0
  212. package/skills/hallmark/references/themes/manifesto.jpg +0 -0
  213. package/skills/hallmark/references/themes/manifesto.md +101 -0
  214. package/skills/hallmark/references/themes/midnight.jpg +0 -0
  215. package/skills/hallmark/references/themes/midnight.md +97 -0
  216. package/skills/hallmark/references/themes/newsprint.jpg +0 -0
  217. package/skills/hallmark/references/themes/newsprint.md +102 -0
  218. package/skills/hallmark/references/themes/overprint.jpg +0 -0
  219. package/skills/hallmark/references/themes/overprint.md +101 -0
  220. package/skills/hallmark/references/themes/pasteup.jpg +0 -0
  221. package/skills/hallmark/references/themes/pasteup.md +100 -0
  222. package/skills/hallmark/references/themes/piste.jpg +0 -0
  223. package/skills/hallmark/references/themes/piste.md +99 -0
  224. package/skills/hallmark/references/themes/ribbon.jpg +0 -0
  225. package/skills/hallmark/references/themes/ribbon.md +106 -0
  226. package/skills/hallmark/references/themes/rim.jpg +0 -0
  227. package/skills/hallmark/references/themes/rim.md +96 -0
  228. package/skills/hallmark/references/themes/riso.jpg +0 -0
  229. package/skills/hallmark/references/themes/riso.md +98 -0
  230. package/skills/hallmark/references/themes/solstice.jpg +0 -0
  231. package/skills/hallmark/references/themes/solstice.md +104 -0
  232. package/skills/hallmark/references/themes/specimen.jpg +0 -0
  233. package/skills/hallmark/references/themes/specimen.md +100 -0
  234. package/skills/hallmark/references/themes/spore.jpg +0 -0
  235. package/skills/hallmark/references/themes/spore.md +104 -0
  236. package/skills/hallmark/references/themes/sport.jpg +0 -0
  237. package/skills/hallmark/references/themes/sport.md +101 -0
  238. package/skills/hallmark/references/themes/squeeze.jpg +0 -0
  239. package/skills/hallmark/references/themes/squeeze.md +99 -0
  240. package/skills/hallmark/references/themes/sticker.jpg +0 -0
  241. package/skills/hallmark/references/themes/sticker.md +106 -0
  242. package/skills/hallmark/references/themes/studio.jpg +0 -0
  243. package/skills/hallmark/references/themes/studio.md +99 -0
  244. package/skills/hallmark/references/themes/terminal.jpg +0 -0
  245. package/skills/hallmark/references/themes/terminal.md +96 -0
  246. package/skills/hallmark/references/themes/terrazzo.jpg +0 -0
  247. package/skills/hallmark/references/themes/terrazzo.md +106 -0
  248. package/skills/hallmark/references/themes/ultraviolet.jpg +0 -0
  249. package/skills/hallmark/references/themes/ultraviolet.md +106 -0
  250. package/skills/hallmark/references/themes/vellum.jpg +0 -0
  251. package/skills/hallmark/references/themes/vellum.md +105 -0
  252. package/skills/hallmark/references/themes/wayfind.jpg +0 -0
  253. package/skills/hallmark/references/themes/wayfind.md +105 -0
  254. package/skills/hallmark/references/themes/werkstatt.jpg +0 -0
  255. package/skills/hallmark/references/themes/werkstatt.md +105 -0
  256. package/skills/hallmark/scripts/capture.mjs +125 -0
  257. package/skills/hallmark/scripts/fixtures/exemplars/atmospheric.html +324 -0
  258. package/skills/hallmark/scripts/fixtures/exemplars/editorial.html +363 -0
  259. package/skills/hallmark/scripts/fixtures/exemplars/modern-minimal.html +527 -0
  260. package/skills/hallmark/scripts/fixtures/exemplars/playful.html +353 -0
  261. package/skills/hallmark/scripts/fixtures/eyebrow-fail/index.html +118 -0
  262. package/skills/hallmark/scripts/fixtures/eyebrow-pass/index.html +137 -0
  263. package/skills/hallmark/scripts/fixtures/kept/after.html +27 -0
  264. package/skills/hallmark/scripts/fixtures/kept/before.html +26 -0
  265. package/skills/hallmark/scripts/fixtures/slopped.html +145 -0
  266. package/skills/hallmark/scripts/fixtures/tailwind-fail/Feature.vue +14 -0
  267. package/skills/hallmark/scripts/fixtures/tailwind-fail/Hero.tsx +33 -0
  268. package/skills/hallmark/scripts/fixtures/tailwind-fail/index.html +74 -0
  269. package/skills/hallmark/scripts/fixtures/tailwind-fail/style.css +6 -0
  270. package/skills/hallmark/scripts/fixtures/tailwind-pass/Hero.tsx +33 -0
  271. package/skills/hallmark/scripts/fixtures/tailwind-pass/index.html +57 -0
  272. package/skills/hallmark/scripts/fixtures/tailwind-pass/style.css +15 -0
  273. package/skills/hallmark/scripts/fixtures/waiver/index.html +54 -0
  274. package/skills/hallmark/scripts/imagegen.mjs +85 -0
  275. package/skills/hallmark/scripts/install-hook.mjs +70 -0
  276. package/skills/hallmark/scripts/install.mjs +141 -0
  277. package/skills/hallmark/scripts/lint-hook.mjs +49 -0
  278. package/skills/hallmark/scripts/photos.json +1 -0
  279. package/skills/hallmark/scripts/picture.mjs +71 -0
  280. package/skills/hallmark/scripts/refcheck.mjs +352 -0
  281. package/skills/hallmark/scripts/sloplint-render.mjs +1252 -0
  282. package/skills/hallmark/scripts/sloplint.mjs +4422 -0
  283. package/skills/hallmark/scripts/theme.mjs +650 -0
  284. package/skills/harness/SKILL.md +17 -8
  285. package/skills/i-have-adhd/SKILL.md +32 -12
  286. package/skills/no-ai-slop/SKILL.md +15 -1
  287. package/skills/plan-add/SKILL.md +38 -27
  288. package/skills/plan-status/SKILL.md +13 -7
  289. package/skills/plan-sync/SKILL.md +18 -12
  290. package/skills/pm-frameworks/SKILL.md +19 -10
  291. package/skills/pm-frameworks/SOURCE +7 -5
  292. package/skills/ponytail/SKILL.md +19 -14
  293. package/skills/product-analysis/SKILL.md +22 -18
  294. package/skills/product-flow/SKILL.md +14 -9
  295. package/skills/research/SKILL.md +97 -48
  296. package/skills/rl-env/SKILL.md +25 -13
  297. package/skills/rl-env/SOURCE +8 -6
  298. package/skills/tezgah-contract/SKILL.md +65 -47
  299. package/statusline.py +20 -9
  300. package/workflows/graph-review.js +14 -2
  301. package/bin/tezgah-skill.py +0 -59
  302. /package/skills/ai-research/0-autoresearch-skill/{SKILL.md → ENTRY.md} +0 -0
  303. /package/skills/ai-research/01-model-architecture/litgpt/{SKILL.md → ENTRY.md} +0 -0
  304. /package/skills/ai-research/01-model-architecture/mamba/{SKILL.md → ENTRY.md} +0 -0
  305. /package/skills/ai-research/01-model-architecture/nanogpt/{SKILL.md → ENTRY.md} +0 -0
  306. /package/skills/ai-research/01-model-architecture/rwkv/{SKILL.md → ENTRY.md} +0 -0
  307. /package/skills/ai-research/01-model-architecture/torchtitan/{SKILL.md → ENTRY.md} +0 -0
  308. /package/skills/ai-research/02-tokenization/huggingface-tokenizers/{SKILL.md → ENTRY.md} +0 -0
  309. /package/skills/ai-research/02-tokenization/sentencepiece/{SKILL.md → ENTRY.md} +0 -0
  310. /package/skills/ai-research/03-fine-tuning/axolotl/{SKILL.md → ENTRY.md} +0 -0
  311. /package/skills/ai-research/03-fine-tuning/llama-factory/{SKILL.md → ENTRY.md} +0 -0
  312. /package/skills/ai-research/03-fine-tuning/peft/{SKILL.md → ENTRY.md} +0 -0
  313. /package/skills/ai-research/03-fine-tuning/unsloth/{SKILL.md → ENTRY.md} +0 -0
  314. /package/skills/ai-research/04-mechanistic-interpretability/nnsight/{SKILL.md → ENTRY.md} +0 -0
  315. /package/skills/ai-research/04-mechanistic-interpretability/pyvene/{SKILL.md → ENTRY.md} +0 -0
  316. /package/skills/ai-research/04-mechanistic-interpretability/saelens/{SKILL.md → ENTRY.md} +0 -0
  317. /package/skills/ai-research/04-mechanistic-interpretability/transformer-lens/{SKILL.md → ENTRY.md} +0 -0
  318. /package/skills/ai-research/05-data-processing/nemo-curator/{SKILL.md → ENTRY.md} +0 -0
  319. /package/skills/ai-research/05-data-processing/ray-data/{SKILL.md → ENTRY.md} +0 -0
  320. /package/skills/ai-research/06-post-training/grpo-rl-training/{SKILL.md → ENTRY.md} +0 -0
  321. /package/skills/ai-research/06-post-training/miles/{SKILL.md → ENTRY.md} +0 -0
  322. /package/skills/ai-research/06-post-training/openrlhf/{SKILL.md → ENTRY.md} +0 -0
  323. /package/skills/ai-research/06-post-training/simpo/{SKILL.md → ENTRY.md} +0 -0
  324. /package/skills/ai-research/06-post-training/slime/{SKILL.md → ENTRY.md} +0 -0
  325. /package/skills/ai-research/06-post-training/torchforge/{SKILL.md → ENTRY.md} +0 -0
  326. /package/skills/ai-research/06-post-training/trl-fine-tuning/{SKILL.md → ENTRY.md} +0 -0
  327. /package/skills/ai-research/06-post-training/verl/{SKILL.md → ENTRY.md} +0 -0
  328. /package/skills/ai-research/07-safety-alignment/constitutional-ai/{SKILL.md → ENTRY.md} +0 -0
  329. /package/skills/ai-research/07-safety-alignment/llamaguard/{SKILL.md → ENTRY.md} +0 -0
  330. /package/skills/ai-research/07-safety-alignment/nemo-guardrails/{SKILL.md → ENTRY.md} +0 -0
  331. /package/skills/ai-research/07-safety-alignment/prompt-guard/{SKILL.md → ENTRY.md} +0 -0
  332. /package/skills/ai-research/08-distributed-training/accelerate/{SKILL.md → ENTRY.md} +0 -0
  333. /package/skills/ai-research/08-distributed-training/deepspeed/{SKILL.md → ENTRY.md} +0 -0
  334. /package/skills/ai-research/08-distributed-training/megatron-core/{SKILL.md → ENTRY.md} +0 -0
  335. /package/skills/ai-research/08-distributed-training/pytorch-fsdp2/{SKILL.md → ENTRY.md} +0 -0
  336. /package/skills/ai-research/08-distributed-training/pytorch-lightning/{SKILL.md → ENTRY.md} +0 -0
  337. /package/skills/ai-research/08-distributed-training/ray-train/{SKILL.md → ENTRY.md} +0 -0
  338. /package/skills/ai-research/09-infrastructure/lambda-labs/{SKILL.md → ENTRY.md} +0 -0
  339. /package/skills/ai-research/09-infrastructure/modal/{SKILL.md → ENTRY.md} +0 -0
  340. /package/skills/ai-research/09-infrastructure/skypilot/{SKILL.md → ENTRY.md} +0 -0
  341. /package/skills/ai-research/10-optimization/awq/{SKILL.md → ENTRY.md} +0 -0
  342. /package/skills/ai-research/10-optimization/bitsandbytes/{SKILL.md → ENTRY.md} +0 -0
  343. /package/skills/ai-research/10-optimization/flash-attention/{SKILL.md → ENTRY.md} +0 -0
  344. /package/skills/ai-research/10-optimization/gguf/{SKILL.md → ENTRY.md} +0 -0
  345. /package/skills/ai-research/10-optimization/gptq/{SKILL.md → ENTRY.md} +0 -0
  346. /package/skills/ai-research/10-optimization/hqq/{SKILL.md → ENTRY.md} +0 -0
  347. /package/skills/ai-research/10-optimization/ml-training-recipes/{SKILL.md → ENTRY.md} +0 -0
  348. /package/skills/ai-research/11-evaluation/bigcode-evaluation-harness/{SKILL.md → ENTRY.md} +0 -0
  349. /package/skills/ai-research/11-evaluation/lm-evaluation-harness/{SKILL.md → ENTRY.md} +0 -0
  350. /package/skills/ai-research/11-evaluation/nemo-evaluator/{SKILL.md → ENTRY.md} +0 -0
  351. /package/skills/ai-research/12-inference-serving/llama-cpp/{SKILL.md → ENTRY.md} +0 -0
  352. /package/skills/ai-research/12-inference-serving/sglang/{SKILL.md → ENTRY.md} +0 -0
  353. /package/skills/ai-research/12-inference-serving/tensorrt-llm/{SKILL.md → ENTRY.md} +0 -0
  354. /package/skills/ai-research/12-inference-serving/vllm/{SKILL.md → ENTRY.md} +0 -0
  355. /package/skills/ai-research/13-mlops/mlflow/{SKILL.md → ENTRY.md} +0 -0
  356. /package/skills/ai-research/13-mlops/swanlab/{SKILL.md → ENTRY.md} +0 -0
  357. /package/skills/ai-research/13-mlops/tensorboard/{SKILL.md → ENTRY.md} +0 -0
  358. /package/skills/ai-research/13-mlops/weights-and-biases/{SKILL.md → ENTRY.md} +0 -0
  359. /package/skills/ai-research/14-agents/a-evolve/{SKILL.md → ENTRY.md} +0 -0
  360. /package/skills/ai-research/14-agents/autogpt/{SKILL.md → ENTRY.md} +0 -0
  361. /package/skills/ai-research/14-agents/crewai/{SKILL.md → ENTRY.md} +0 -0
  362. /package/skills/ai-research/14-agents/langchain/{SKILL.md → ENTRY.md} +0 -0
  363. /package/skills/ai-research/14-agents/llamaindex/{SKILL.md → ENTRY.md} +0 -0
  364. /package/skills/ai-research/15-rag/chroma/{SKILL.md → ENTRY.md} +0 -0
  365. /package/skills/ai-research/15-rag/faiss/{SKILL.md → ENTRY.md} +0 -0
  366. /package/skills/ai-research/15-rag/pinecone/{SKILL.md → ENTRY.md} +0 -0
  367. /package/skills/ai-research/15-rag/qdrant/{SKILL.md → ENTRY.md} +0 -0
  368. /package/skills/ai-research/15-rag/sentence-transformers/{SKILL.md → ENTRY.md} +0 -0
  369. /package/skills/ai-research/16-prompt-engineering/dspy/{SKILL.md → ENTRY.md} +0 -0
  370. /package/skills/ai-research/16-prompt-engineering/guidance/{SKILL.md → ENTRY.md} +0 -0
  371. /package/skills/ai-research/16-prompt-engineering/instructor/{SKILL.md → ENTRY.md} +0 -0
  372. /package/skills/ai-research/16-prompt-engineering/outlines/{SKILL.md → ENTRY.md} +0 -0
  373. /package/skills/ai-research/17-observability/langsmith/{SKILL.md → ENTRY.md} +0 -0
  374. /package/skills/ai-research/17-observability/phoenix/{SKILL.md → ENTRY.md} +0 -0
  375. /package/skills/ai-research/18-multimodal/audiocraft/{SKILL.md → ENTRY.md} +0 -0
  376. /package/skills/ai-research/18-multimodal/blip-2/{SKILL.md → ENTRY.md} +0 -0
  377. /package/skills/ai-research/18-multimodal/clip/{SKILL.md → ENTRY.md} +0 -0
  378. /package/skills/ai-research/18-multimodal/cosmos-policy/{SKILL.md → ENTRY.md} +0 -0
  379. /package/skills/ai-research/18-multimodal/llava/{SKILL.md → ENTRY.md} +0 -0
  380. /package/skills/ai-research/18-multimodal/openpi/{SKILL.md → ENTRY.md} +0 -0
  381. /package/skills/ai-research/18-multimodal/openvla-oft/{SKILL.md → ENTRY.md} +0 -0
  382. /package/skills/ai-research/18-multimodal/segment-anything/{SKILL.md → ENTRY.md} +0 -0
  383. /package/skills/ai-research/18-multimodal/stable-diffusion/{SKILL.md → ENTRY.md} +0 -0
  384. /package/skills/ai-research/18-multimodal/whisper/{SKILL.md → ENTRY.md} +0 -0
  385. /package/skills/ai-research/19-emerging-techniques/knowledge-distillation/{SKILL.md → ENTRY.md} +0 -0
  386. /package/skills/ai-research/19-emerging-techniques/long-context/{SKILL.md → ENTRY.md} +0 -0
  387. /package/skills/ai-research/19-emerging-techniques/model-merging/{SKILL.md → ENTRY.md} +0 -0
  388. /package/skills/ai-research/19-emerging-techniques/model-pruning/{SKILL.md → ENTRY.md} +0 -0
  389. /package/skills/ai-research/19-emerging-techniques/moe-training/{SKILL.md → ENTRY.md} +0 -0
  390. /package/skills/ai-research/19-emerging-techniques/speculative-decoding/{SKILL.md → ENTRY.md} +0 -0
  391. /package/skills/ai-research/20-ml-paper-writing/academic-plotting/{SKILL.md → ENTRY.md} +0 -0
  392. /package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/{SKILL.md → ENTRY.md} +0 -0
  393. /package/skills/ai-research/20-ml-paper-writing/presenting-conference-talks/{SKILL.md → ENTRY.md} +0 -0
  394. /package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/{SKILL.md → ENTRY.md} +0 -0
  395. /package/skills/ai-research/21-research-ideation/brainstorming-research-ideas/{SKILL.md → ENTRY.md} +0 -0
  396. /package/skills/ai-research/21-research-ideation/creative-thinking-for-research/{SKILL.md → ENTRY.md} +0 -0
  397. /package/skills/ai-research/22-agent-native-research-artifact/compiler/{SKILL.md → ENTRY.md} +0 -0
  398. /package/skills/ai-research/22-agent-native-research-artifact/research-manager/{SKILL.md → ENTRY.md} +0 -0
  399. /package/skills/ai-research/22-agent-native-research-artifact/rigor-reviewer/{SKILL.md → ENTRY.md} +0 -0
  400. /package/skills/design-library/adaptive-interfaces/skills/colour-independence/{SKILL.md → ENTRY.md} +0 -0
  401. /package/skills/design-library/adaptive-interfaces/skills/flexible-typography/{SKILL.md → ENTRY.md} +0 -0
  402. /package/skills/design-library/adaptive-interfaces/skills/information-density/{SKILL.md → ENTRY.md} +0 -0
  403. /package/skills/design-library/adaptive-interfaces/skills/preference-audit/{SKILL.md → ENTRY.md} +0 -0
  404. /package/skills/design-library/adaptive-interfaces/skills/responsive-accessibility/{SKILL.md → ENTRY.md} +0 -0
  405. /package/skills/design-library/adaptive-interfaces/skills/responsive-review/{SKILL.md → ENTRY.md} +0 -0
  406. /package/skills/design-library/adaptive-interfaces/skills/simplified-views/{SKILL.md → ENTRY.md} +0 -0
  407. /package/skills/design-library/adaptive-interfaces/skills/specify/{SKILL.md → ENTRY.md} +0 -0
  408. /package/skills/design-library/adaptive-interfaces/skills/user-preference-respect/{SKILL.md → ENTRY.md} +0 -0
  409. /package/skills/design-library/cognitive-accessibility/skills/adaptive-personalisation/{SKILL.md → ENTRY.md} +0 -0
  410. /package/skills/design-library/cognitive-accessibility/skills/assess-load/{SKILL.md → ENTRY.md} +0 -0
  411. /package/skills/design-library/cognitive-accessibility/skills/cognitive-load-assessment/{SKILL.md → ENTRY.md} +0 -0
  412. /package/skills/design-library/cognitive-accessibility/skills/contextual-help-design/{SKILL.md → ENTRY.md} +0 -0
  413. /package/skills/design-library/cognitive-accessibility/skills/error-prevention-recovery/{SKILL.md → ENTRY.md} +0 -0
  414. /package/skills/design-library/cognitive-accessibility/skills/focus-attention-design/{SKILL.md → ENTRY.md} +0 -0
  415. /package/skills/design-library/cognitive-accessibility/skills/memory-load-reduction/{SKILL.md → ENTRY.md} +0 -0
  416. /package/skills/design-library/cognitive-accessibility/skills/plain-language-design/{SKILL.md → ENTRY.md} +0 -0
  417. /package/skills/design-library/cognitive-accessibility/skills/review/{SKILL.md → ENTRY.md} +0 -0
  418. /package/skills/design-library/cognitive-accessibility/skills/simplify/{SKILL.md → ENTRY.md} +0 -0
  419. /package/skills/design-library/cognitive-accessibility/skills/wayfinding-navigation/{SKILL.md → ENTRY.md} +0 -0
  420. /package/skills/design-library/design-research/skills/behavioural-analytics/{SKILL.md → ENTRY.md} +0 -0
  421. /package/skills/design-library/design-research/skills/qual-quant-triangulation/{SKILL.md → ENTRY.md} +0 -0
  422. /package/skills/design-library/inclusive-interaction/skills/audit/{SKILL.md → ENTRY.md} +0 -0
  423. /package/skills/design-library/inclusive-interaction/skills/design-flow/{SKILL.md → ENTRY.md} +0 -0
  424. /package/skills/design-library/inclusive-interaction/skills/feedback-and-status/{SKILL.md → ENTRY.md} +0 -0
  425. /package/skills/design-library/inclusive-interaction/skills/gesture-alternatives/{SKILL.md → ENTRY.md} +0 -0
  426. /package/skills/design-library/inclusive-interaction/skills/keyboard-navigation/{SKILL.md → ENTRY.md} +0 -0
  427. /package/skills/design-library/inclusive-interaction/skills/keyboard-review/{SKILL.md → ENTRY.md} +0 -0
  428. /package/skills/design-library/inclusive-interaction/skills/motion-sensitivity/{SKILL.md → ENTRY.md} +0 -0
  429. /package/skills/design-library/inclusive-interaction/skills/multi-modal-input/{SKILL.md → ENTRY.md} +0 -0
  430. /package/skills/design-library/inclusive-interaction/skills/touch-target-design/{SKILL.md → ENTRY.md} +0 -0
  431. /package/skills/design-library/inclusive-interaction/skills/voice-interaction/{SKILL.md → ENTRY.md} +0 -0
  432. /package/skills/design-library/visual-critique/skills/critique-affordance/{SKILL.md → ENTRY.md} +0 -0
  433. /package/skills/design-library/visual-critique/skills/critique-brand-consistency/{SKILL.md → ENTRY.md} +0 -0
  434. /package/skills/design-library/visual-critique/skills/critique-color/{SKILL.md → ENTRY.md} +0 -0
  435. /package/skills/design-library/visual-critique/skills/critique-composition/{SKILL.md → ENTRY.md} +0 -0
  436. /package/skills/design-library/visual-critique/skills/critique-information-density/{SKILL.md → ENTRY.md} +0 -0
  437. /package/skills/design-library/visual-critique/skills/critique-typography/{SKILL.md → ENTRY.md} +0 -0
  438. /package/skills/design-library/visual-critique/skills/critique-visual-hierarchy/{SKILL.md → ENTRY.md} +0 -0
  439. /package/skills/pm-frameworks/intended-vs-implemented/{SKILL.md → ENTRY.md} +0 -0
  440. /package/skills/pm-frameworks/opportunity-solution-tree/{SKILL.md → ENTRY.md} +0 -0
  441. /package/skills/rl-env/generate-nemo-gym-env/{SKILL.md → ENTRY.md} +0 -0
  442. /package/skills/rl-env/generate-openenv-env/{SKILL.md → ENTRY.md} +0 -0
  443. /package/skills/rl-env/generate-ors-env/{SKILL.md → ENTRY.md} +0 -0
  444. /package/skills/rl-env/generate-verifiers-env/{SKILL.md → ENTRY.md} +0 -0
  445. /package/skills/rl-env/rl-env-from-description/{SKILL.md → ENTRY.md} +0 -0
@@ -0,0 +1,239 @@
1
+ #!/usr/bin/env python3
2
+ """Command Code lifecycle hook. Reads Command Code's JSON on stdin and answers
3
+ in its own output shape, onto the shared tezgah core (hooks/).
4
+
5
+ Command Code fires four hook events (commandcode.ai/docs/hooks): SessionStart,
6
+ PreToolUse, PostToolUse and Stop (`bin/tezgah-setup::COMMANDCODE_HOOK_EVENTS`);
7
+ anything else is ignored. Inert outside the roots. Its settings hooks see only
8
+ four tools - shell, read, write, edit - so MCP, subagent and web calls never
9
+ reach this file, and plan mode skips every hook.
10
+
11
+ The always-on core is the managed block in `~/.commandcode/AGENTS.md`, the user
12
+ memory file Command Code puts in the system prompt, so SessionStart repeats it
13
+ only when that block is missing. There is no prompt event: no per-turn reminder
14
+ and no turn rows. PreToolUse translates the tool ids and input fields into the
15
+ gate's vocabulary (`gate_name`, `gate_input`) and denies with
16
+ `hookSpecificOutput.permissionDecision` on exit 0. PostToolUse's `tool_response`
17
+ is the text the model sees; a shell call's outcome is read off an `exit code N`
18
+ in it (`call_failed`).
19
+
20
+ Stop carries no reply text (`stop_hook_active` only), so it reads the last
21
+ assistant text from `transcript_path` (`last_reply`). When that read yields
22
+ nothing the turn end is a `reply_unread` row, never judged. The status segment
23
+ rides `systemMessage`, which Command Code shows in the TUI and never to the
24
+ model, at SessionStart and Stop (`hosts/codex/hook.py` does the same).
25
+ """
26
+ import json
27
+ import os
28
+ import re
29
+ import shlex
30
+ import sys
31
+
32
+ ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
33
+ sys.path.insert(0, os.path.join(ROOT, "hooks"))
34
+ from tezgah_guard import attest_session, import_failed, safe # noqa: E402
35
+ try:
36
+ from tezgah_context import ( # noqa: E402
37
+ TOOL_USE_MEASURES, _tail_lines, command_text, context_for, health_lines,
38
+ record, shell_kind)
39
+ from tezgah_gate import cross_project_note, decision, graph_advice # noqa: E402
40
+ from tezgah_integrity import ( # noqa: E402
41
+ bind_session, note, note_tool, ran_nothing, stop_reason)
42
+ from tezgah_paths import HOST_DIRS, off, root_for # noqa: E402
43
+ from tezgah_taste import write_note # noqa: E402
44
+ from tezgah_untrusted import marks # noqa: E402
45
+ except Exception as exc:
46
+ import_failed(exc)
47
+
48
+ # Command Code's canonical tool ids (hooks "Tool-call fields") -> the gate's
49
+ # vocabulary. `read_file` maps for the ledger only: the PreToolUse matcher never
50
+ # sends it here.
51
+ GATE_TOOLS = {
52
+ "shell_command": "Bash",
53
+ "write_file": "Write",
54
+ "edit_file": "Edit",
55
+ "read_file": "Read",
56
+ }
57
+ # The result text names no documented exit-code format; the shell tool reports
58
+ # the code to the model, so the last `exit code N` in the text is taken.
59
+ EXIT_CODE = re.compile(r"(?i)exit code[: ]+(-?\d+)")
60
+
61
+
62
+ def gate_name(name):
63
+ """The tool name the gate denies under and the ledger row records; both
64
+ halves map through here so a call hashes to one id."""
65
+ return GATE_TOOLS.get(name, name)
66
+
67
+
68
+ def gate_input(name, inp):
69
+ """The tool input in the gate's fields. A shell call may split its command
70
+ into `command` + `args` (Command Code shell-quotes the args itself), and an
71
+ edit names its strings `old_value`/`new_value` in the hooks reference but
72
+ `old_string`/`new_string` in the tools reference, so either is read. `args`
73
+ is dropped once folded in: the gate reads an `args` key as a Task's object."""
74
+ inp = dict(inp) if isinstance(inp, dict) else {}
75
+ if name == "shell_command":
76
+ args = inp.pop("args", None)
77
+ if isinstance(args, list) and args and all(isinstance(a, str) for a in args):
78
+ inp["command"] = ("%s %s" % (inp.get("command") or "", shlex.join(args))).strip()
79
+ elif name == "edit_file":
80
+ for src, dst in (("old_value", "old_string"), ("new_value", "new_string")):
81
+ if src in inp and dst not in inp:
82
+ inp[dst] = inp[src]
83
+ return inp
84
+
85
+
86
+ def classify(payload):
87
+ """The used-tool kind for a tool payload, or None."""
88
+ if payload.get("tool_name") == "shell_command":
89
+ return shell_kind(command_text(gate_input("shell_command", payload.get("tool_input"))))
90
+ return None
91
+
92
+
93
+ def call_failed(payload):
94
+ """`note_tool`'s `failed` for a shell call: the last `exit code N` in the
95
+ result, and None when the result names no code - a call that RAN, never a
96
+ pass."""
97
+ if payload.get("tool_name") != "shell_command":
98
+ return None
99
+ resp = payload.get("tool_response")
100
+ codes = EXIT_CODE.findall(resp) if isinstance(resp, str) else []
101
+ return int(codes[-1]) != 0 if codes else None
102
+
103
+
104
+ def _text(content):
105
+ """The text blocks of a message's content, a string or a block list."""
106
+ if isinstance(content, str):
107
+ return [content]
108
+ if not isinstance(content, list):
109
+ return []
110
+ return [b.get("text") for b in content if isinstance(b, dict)
111
+ and b.get("type") == "text" and isinstance(b.get("text"), str)]
112
+
113
+
114
+ def last_reply(path):
115
+ """The text of the assistant reply that ends the transcript, or "".
116
+
117
+ Command Code documents its transcript only as JSONL. Two row shapes are
118
+ read: Claude's `{"type": "assistant", "message": {"content": [...]}}` and a
119
+ bare `{"role": "assistant", "content": ...}`. The reply is the text of the
120
+ trailing assistant rows; a transcript that ends on a user or tool row has
121
+ no reply written yet and answers ""."""
122
+ parts = []
123
+ for raw in reversed(_tail_lines(path)):
124
+ try:
125
+ row = json.loads(raw)
126
+ except ValueError:
127
+ continue
128
+ if not isinstance(row, dict):
129
+ continue
130
+ msg = row.get("message") if isinstance(row.get("message"), dict) else row
131
+ role = row.get("type") if row.get("type") in ("user", "assistant") else msg.get("role")
132
+ if role not in ("user", "assistant", "tool"):
133
+ continue
134
+ if role != "assistant":
135
+ break
136
+ parts[:0] = _text(msg.get("content"))
137
+ return "\n".join(t for t in parts if t.strip())
138
+
139
+
140
+ def rules_carry_core():
141
+ """True when `AGENTS.md` in Command Code's home holds the managed block."""
142
+ try:
143
+ with open(os.path.join(HOST_DIRS["commandcode"], "AGENTS.md"),
144
+ encoding="utf-8") as fh:
145
+ return "<!-- tezgah:start" in fh.read()
146
+ except OSError:
147
+ return False
148
+
149
+
150
+ def post_tool(payload, cwd, session_id):
151
+ """The ledger row for one finished call, and the notice for the model."""
152
+ name = payload.get("tool_name", "") or ""
153
+ tool = gate_name(name)
154
+ inp = gate_input(name, payload.get("tool_input"))
155
+ safe(session_id, record, session_id, classify(payload))
156
+ if not root_for(cwd):
157
+ return None
158
+ result = payload.get("tool_response")
159
+ failed = call_failed(payload)
160
+ # read before this call's row lands: `source` is the taint's own mark
161
+ got = safe(session_id, marks, tool, inp, session_id, result)
162
+ source, notice = got or (None, None)
163
+ safe(session_id, note_tool, session_id, tool, inp, failed=failed,
164
+ source=source, cwd=cwd,
165
+ out_bytes=len(result) if isinstance(result, str) else None,
166
+ empty_run=ran_nothing(result))
167
+ advice = safe(session_id, graph_advice, tool, inp, cwd, "commandcode")
168
+ taste = cross = None
169
+ if not failed:
170
+ taste = safe(session_id, write_note, session_id, inp, cwd, tool)
171
+ cross = safe(session_id, cross_project_note, session_id, tool, inp, cwd)
172
+ return "\n".join(p for p in (notice, advice, taste, cross) if p)
173
+
174
+
175
+ def context(event, text):
176
+ return {"hookSpecificOutput": {"hookEventName": event,
177
+ "additionalContext": text}} if text else {}
178
+
179
+
180
+ def status(out, cwd, session_id):
181
+ """Add the status segment as `systemMessage` (TUI only)."""
182
+ seg = safe(session_id, health_lines, cwd, session_id, observable=TOOL_USE_MEASURES)
183
+ if seg:
184
+ out["systemMessage"] = "tezgah " + seg
185
+ return out
186
+
187
+
188
+ def main():
189
+ try:
190
+ payload = json.load(sys.stdin)
191
+ except Exception:
192
+ return
193
+ if not isinstance(payload, dict):
194
+ return
195
+ event = payload.get("hook_event_name") or ""
196
+ cwd = payload.get("cwd") or os.getcwd()
197
+ session_id = payload.get("session_id")
198
+ safe(session_id, bind_session, session_id) # the switch latch (tezgah_paths.off)
199
+ out = {}
200
+ if event == "PreToolUse":
201
+ name = payload.get("tool_name", "") or ""
202
+ reason = safe(session_id, decision, gate_name(name),
203
+ gate_input(name, payload.get("tool_input")), cwd, session_id)
204
+ if reason:
205
+ out = {"hookSpecificOutput": {
206
+ "hookEventName": "PreToolUse",
207
+ "permissionDecision": "deny",
208
+ "permissionDecisionReason": reason,
209
+ }}
210
+ elif event == "PostToolUse":
211
+ out = context(event, post_tool(payload, cwd, session_id))
212
+ elif event == "SessionStart":
213
+ safe(session_id, attest_session, "commandcode", session_id, cwd)
214
+ out = status(context(event, safe(session_id, context_for, "session_start", cwd,
215
+ payload, with_core=not rules_carry_core())),
216
+ cwd, session_id)
217
+ elif event == "Stop":
218
+ # {"decision": "block", "reason": ...} retries the turn, at most 3 times
219
+ # (the host's cap); the reply after a block is judged again and refused
220
+ # at most once more (tezgah_integrity).
221
+ if not off("verify-off") and root_for(cwd):
222
+ path = payload.get("transcript_path")
223
+ text = safe(session_id, last_reply, path)
224
+ if text:
225
+ reason = safe(session_id, stop_reason, text, session_id, cwd=cwd,
226
+ after_block=bool(payload.get("stop_hook_active")),
227
+ mode=payload.get("permission_mode"))
228
+ if reason:
229
+ out = {"decision": "block", "reason": reason}
230
+ else:
231
+ safe(session_id, note, session_id, "reply_unread",
232
+ "no assistant text at the end of %s" % path if path
233
+ else "no transcript_path")
234
+ out = status(out, cwd, session_id)
235
+ if out:
236
+ print(json.dumps(out))
237
+
238
+
239
+ main()
@@ -0,0 +1,284 @@
1
+ #!/usr/bin/env python3
2
+ """GitHub Copilot CLI lifecycle hook. Reads Copilot's JSON on stdin and answers
3
+ in its own output shape, onto the shared tezgah core (hooks/).
4
+
5
+ tezgah's entries live in their own file, `$COPILOT_HOME/hooks/tezgah.json`
6
+ (`bin/tezgah-setup::COPILOT_HOOK_EVENTS`). They use the PascalCase event names,
7
+ so the payloads carry snake_case fields and Claude tool names
8
+ (docs.github.com hooks-reference "Hook event input payloads"): SessionStart,
9
+ UserPromptSubmit, PreToolUse, PostToolUse, PostToolUseFailure, Stop and
10
+ SubagentStop. `subagentStart` has no PascalCase form; its camelCase payload
11
+ names no event, so its command passes the event as the first argument.
12
+ Anything else is ignored. Inert outside the roots.
13
+
14
+ The always-on core is the managed block in `$COPILOT_HOME/copilot-instructions.md`,
15
+ so SessionStart repeats it only when that block is missing. A command hook's
16
+ UserPromptSubmit output is dropped by Copilot, so there is no per-turn
17
+ reminder; the event still writes the turn row. PreToolUse translates the tool
18
+ names into the gate's vocabulary and denies with a top-level
19
+ `permissionDecision: deny` on exit 0. Copilot denies the call itself when this
20
+ hook crashes, and lets it through when the hook times out.
21
+
22
+ Copilot fires PostToolUse for a successful call and PostToolUseFailure for a
23
+ failed one, so the event is the outcome; a shell result's `exit code N` text
24
+ overrides it (`call_failed`). Stop carries no reply text, so it reads the last
25
+ `assistant.message` from `transcript_path` (`last_reply`); none there is a
26
+ `reply_unread` row, never judged. SubagentStop is judged record-only. The status
27
+ line is `tezgah-statusline --copilot`, Copilot's `statusLine` command.
28
+ """
29
+ import json
30
+ import os
31
+ import re
32
+ import sys
33
+
34
+ ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
35
+ sys.path.insert(0, os.path.join(ROOT, "hooks"))
36
+ from tezgah_guard import attest_session, import_failed, safe # noqa: E402
37
+ try:
38
+ from tezgah_context import ( # noqa: E402
39
+ _tail_lines, command_text, context_for, record, shell_kind)
40
+ from tezgah_gate import cross_project_note, decision, graph_advice # noqa: E402
41
+ from tezgah_integrity import ( # noqa: E402
42
+ SUBAGENT_CHANNEL, bind_session, note, note_tool, ran_nothing, report_bytes,
43
+ stop_reason, untrusted_source)
44
+ from tezgah_paths import HOST_DIRS, off, root_for # noqa: E402
45
+ from tezgah_taste import write_note # noqa: E402
46
+ from tezgah_untrusted import marks # noqa: E402
47
+ except Exception as exc:
48
+ import_failed(exc)
49
+
50
+ # Copilot's tool names -> the gate's vocabulary. A PascalCase PreToolUse
51
+ # reports the Claude name (hooks-reference "Claude-format matchers"); the
52
+ # runtime spellings map to the same names, since no doc says the other events
53
+ # translate theirs.
54
+ GATE_TOOLS = {
55
+ "bash": "Bash", "powershell": "Bash",
56
+ "create": "Write",
57
+ "edit": "Edit", "str_replace_editor": "Edit", "apply_patch": "Edit",
58
+ "Agent": "Task", "task": "Task",
59
+ "grep": "Grep", "rg": "Grep",
60
+ "view": "Read",
61
+ }
62
+ # The result text names no documented exit-code format; the last `exit code N`
63
+ # in it is taken.
64
+ EXIT_CODE = re.compile(r"(?i)exit code[: ]+(-?\d+)")
65
+
66
+
67
+ def mcp_servers():
68
+ """The server names in `$COPILOT_HOME/mcp-config.json`, sanitized the way
69
+ Copilot builds a tool name (cli-command-reference "MCP tool name
70
+ sanitization"), longest first."""
71
+ try:
72
+ with open(os.path.join(HOST_DIRS["copilot"], "mcp-config.json"),
73
+ encoding="utf-8") as fh:
74
+ servers = json.load(fh).get("mcpServers")
75
+ except (OSError, ValueError, AttributeError):
76
+ return []
77
+ names = {re.sub(r"[^A-Za-z0-9_-]", "-", s) for s in servers or {}
78
+ if isinstance(s, str)}
79
+ return sorted(names, key=len, reverse=True)
80
+
81
+
82
+ def is_patch(name, inp):
83
+ """An Edit that names no file but carries a patch string: `apply_patch`."""
84
+ if GATE_TOOLS.get(name, name) != "Edit":
85
+ return False
86
+ if isinstance(inp, str):
87
+ return True
88
+ return (isinstance(inp, dict) and not (inp.get("path") or inp.get("file_path"))
89
+ and any(isinstance(inp.get(k), str) for k in ("patch", "input")))
90
+
91
+
92
+ def gate_name(name, inp=None):
93
+ """The tool name the gate denies under and the ledger row records; both
94
+ halves map through here so a call hashes to one id. An MCP tool arrives as
95
+ `<server>-<tool>` and leaves in the shared `mcp__<server>__<tool>` form when
96
+ the server is one `mcp-config.json` names."""
97
+ if is_patch(name, inp):
98
+ return "apply_patch"
99
+ if name in GATE_TOOLS:
100
+ return GATE_TOOLS[name]
101
+ for server in mcp_servers() if "-" in name else ():
102
+ if name.startswith(server + "-") and len(name) > len(server) + 1:
103
+ return "mcp__%s__%s" % (server, name[len(server) + 1:])
104
+ return name
105
+
106
+
107
+ def gate_input(name, inp):
108
+ """The tool input in the gate's fields. The gate already reads Copilot's
109
+ `path`, `file_text`, `old_str` and `new_str`; a patch is handed over as
110
+ `patch`."""
111
+ if is_patch(name, inp):
112
+ if isinstance(inp, str):
113
+ return {"patch": inp}
114
+ return dict(inp, patch=inp["patch"] if isinstance(inp.get("patch"), str)
115
+ else inp["input"])
116
+ return inp if isinstance(inp, dict) else {}
117
+
118
+
119
+ def classify(tool, inp):
120
+ """The used-tool kind for a mapped call, or None."""
121
+ if tool.startswith("mcp__") and "codegraph" in tool:
122
+ return "graph"
123
+ if tool == "Task":
124
+ return "orch"
125
+ if tool == "Bash":
126
+ return shell_kind(command_text(inp))
127
+ return None
128
+
129
+
130
+ def subagent_id(payload):
131
+ """The subagent id Copilot adds to a hook input fired inside a subagent."""
132
+ aid = payload.get("agent_id")
133
+ return aid if isinstance(aid, str) and aid else None
134
+
135
+
136
+ def result_text(payload):
137
+ """The text the model saw: PostToolUse's `tool_result.text_result_for_llm`,
138
+ PostToolUseFailure's `error`."""
139
+ res = payload.get("tool_result")
140
+ if isinstance(res, dict) and isinstance(res.get("text_result_for_llm"), str):
141
+ return res["text_result_for_llm"]
142
+ err = payload.get("error")
143
+ return err if isinstance(err, str) else None
144
+
145
+
146
+ def call_failed(tool, failed, text):
147
+ """`note_tool`'s `failed`: the event's outcome, unless a shell result names
148
+ an exit code. A shell success that names none is None (ran, never a pass):
149
+ a background launch returns before its command ends, with no code."""
150
+ if tool != "Bash":
151
+ return failed
152
+ codes = EXIT_CODE.findall(text) if isinstance(text, str) else []
153
+ if codes:
154
+ return int(codes[-1]) != 0
155
+ return failed or None
156
+
157
+
158
+ def last_reply(path):
159
+ """The reply that ends the transcript, or "".
160
+
161
+ Copilot keeps a session's event log as JSONL (`session-state/<id>/events.jsonl`,
162
+ cli-config-dir-reference); an assistant reply is an `assistant.message` event
163
+ whose `data.content` is the text. A transcript whose last message is the
164
+ user's has no reply written yet."""
165
+ for raw in reversed(_tail_lines(path)):
166
+ try:
167
+ row = json.loads(raw)
168
+ except ValueError:
169
+ continue
170
+ kind = row.get("type") if isinstance(row, dict) else None
171
+ if kind == "user.message":
172
+ break
173
+ data = row.get("data") if kind == "assistant.message" else None
174
+ text = data.get("content") if isinstance(data, dict) else None
175
+ if isinstance(text, str) and text.strip():
176
+ return text
177
+ return ""
178
+
179
+
180
+ def rules_carry_core():
181
+ """True when Copilot's personal instructions file holds the managed block."""
182
+ try:
183
+ with open(os.path.join(HOST_DIRS["copilot"], "copilot-instructions.md"),
184
+ encoding="utf-8") as fh:
185
+ return "<!-- tezgah:start" in fh.read()
186
+ except OSError:
187
+ return False
188
+
189
+
190
+ def post_tool(payload, cwd, session_id, failed):
191
+ """The ledger row for one finished call, and the notice for the model."""
192
+ name = payload.get("tool_name", "") or ""
193
+ raw = payload.get("tool_input")
194
+ tool, inp = gate_name(name, raw), gate_input(name, raw)
195
+ safe(session_id, record, session_id, classify(tool, inp))
196
+ if not root_for(cwd):
197
+ return None
198
+ result = result_text(payload)
199
+ failed = call_failed(tool, failed, result)
200
+ # read before this call's row lands: `source` is the taint's own mark
201
+ got = safe(session_id, marks, tool, inp, session_id, result)
202
+ source, notice = got or (None, None)
203
+ safe(session_id, note_tool, session_id, tool, inp, failed=failed,
204
+ source=source, cwd=cwd,
205
+ out_bytes=(report_bytes(result)
206
+ if untrusted_source(tool, inp) == SUBAGENT_CHANNEL
207
+ else len(result) if isinstance(result, str) else None),
208
+ empty_run=ran_nothing(result), agent=subagent_id(payload))
209
+ advice = safe(session_id, graph_advice, tool, inp, cwd, "copilot")
210
+ taste = cross = None
211
+ if not failed:
212
+ taste = safe(session_id, write_note, session_id, inp, cwd, tool)
213
+ cross = safe(session_id, cross_project_note, session_id, tool, inp, cwd)
214
+ return "\n".join(p for p in (notice, advice, taste, cross) if p)
215
+
216
+
217
+ def context(text):
218
+ return {"additionalContext": text} if text else {}
219
+
220
+
221
+ def main():
222
+ try:
223
+ payload = json.load(sys.stdin)
224
+ except Exception:
225
+ return
226
+ if not isinstance(payload, dict):
227
+ return
228
+ event = payload.get("hook_event_name") or (sys.argv[1] if len(sys.argv) > 1 else "")
229
+ cwd = payload.get("cwd") or os.getcwd()
230
+ session_id = payload.get("session_id") or payload.get("sessionId")
231
+ safe(session_id, bind_session, session_id) # the switch latch (tezgah_paths.off)
232
+ out = {}
233
+ if event == "PreToolUse":
234
+ name = payload.get("tool_name", "") or ""
235
+ raw = payload.get("tool_input")
236
+ reason = safe(session_id, decision, gate_name(name, raw), gate_input(name, raw),
237
+ cwd, session_id, agent=subagent_id(payload))
238
+ if reason:
239
+ # top level, not wrapped (hooks-reference "preToolUse decision control")
240
+ out = {"permissionDecision": "deny", "permissionDecisionReason": reason}
241
+ elif event in ("PostToolUse", "PostToolUseFailure"):
242
+ out = context(post_tool(payload, cwd, session_id, event == "PostToolUseFailure"))
243
+ elif event == "SessionStart":
244
+ safe(session_id, attest_session, "copilot", session_id, cwd)
245
+ out = context(safe(session_id, context_for, "session_start", cwd, payload,
246
+ with_core=not rules_carry_core()))
247
+ elif event == "UserPromptSubmit":
248
+ # the turn row only: Copilot drops a command hook's output here
249
+ safe(session_id, context_for, "user_prompt", cwd, payload)
250
+ elif event == "subagentStart":
251
+ # additionalContext is prepended to the subagent's first message
252
+ safe(session_id, record, session_id, "orch")
253
+ out = context(safe(session_id, context_for, "subagent_start", cwd,
254
+ dict(payload, session_id=session_id)))
255
+ elif event == "SubagentStop":
256
+ # a subagent's end is judged record-only (ADR 011): one `subagent_end`
257
+ # row from its last message, never a block
258
+ safe(session_id, record, session_id, "orch")
259
+ if not off("verify-off") and root_for(cwd):
260
+ text = payload.get("last_assistant_message")
261
+ safe(session_id, stop_reason, text if isinstance(text, str) else "",
262
+ session_id, cwd=cwd, subagent=True)
263
+ elif event == "Stop":
264
+ # {"decision": "block", "reason": ...} forces another turn; Copilot ends
265
+ # the turn anyway after 8 blocks in a row. The reply after a block is
266
+ # judged again and refused at most once more (tezgah_integrity).
267
+ if not off("verify-off") and root_for(cwd):
268
+ path = payload.get("transcript_path")
269
+ text = safe(session_id, last_reply, path)
270
+ if text:
271
+ reason = safe(session_id, stop_reason, text, session_id, cwd=cwd,
272
+ after_block=bool(payload.get("stop_hook_active")),
273
+ mode=payload.get("permission_mode"))
274
+ if reason:
275
+ out = {"decision": "block", "reason": reason}
276
+ else:
277
+ safe(session_id, note, session_id, "reply_unread",
278
+ "no assistant.message at the end of %s" % path if path
279
+ else "no transcript_path")
280
+ if out:
281
+ print(json.dumps(out))
282
+
283
+
284
+ main()
@@ -24,7 +24,10 @@ so this adapter translates them onto the shared tezgah core:
24
24
  ({"decision": "block", "reason": ...}, which Cursor
25
25
  documents as an automatic follow-up - the native
26
26
  spelling is {"followup_message": ...})
27
- beforeSubmitPrompt -> {"continue": true}
27
+ beforeSubmitPrompt -> {"continue": true, "additional_context": <per-turn>}
28
+ (the docs list only continue/user_message, but
29
+ cursor-agent 2026.10.01-2026.10.19 forwards
30
+ additional_context for this event; see CONTEXT_MAX)
28
31
  Everything else answers "{}" and never blocks.
29
32
 
30
33
  Cursor names its own tools, so `hooks.json` has to name them too: the matcher on
@@ -105,6 +108,30 @@ REINFORCE = ("tezgah contract active: keep using the code graph "
105
108
  RECOVERY = ("tezgah: tool call failed. Read the error, fix the cause, then "
106
109
  "re-run; prefer codegraph_explore/codegraph_callers over guessing "
107
110
  "at code.")
111
+ # cursor-agent (2026.10.01-2026.10.19, bundled `HookAdditionalContextTooLargeError`)
112
+ # trims the additional_context of beforeSubmitPrompt, preToolUse, postToolUse and
113
+ # postToolUseFailure and drops it WHOLE when its JavaScript length - UTF-16 code
114
+ # units, so an emoji counts two - is over 10000; a busy turn (every conditional
115
+ # armed) measured 10288. Cutting the tail keeps the reminder and the first rules
116
+ # instead of nothing. sessionStart is not capped: its text goes to the request
117
+ # context (`hooksAdditionalContextPromise`) without that check, and stored Cursor
118
+ # chats carry 15000-character session contexts whole, so the core is not cut.
119
+ # Known limit: with a custom mode on, cursor-agent appends "\n\n" and that mode's
120
+ # text to beforeSubmitPrompt's context before the length check; the hook cannot
121
+ # see it, so a turn cut to exactly the limit is then dropped whole.
122
+ CONTEXT_MAX = 10000
123
+ CONTEXT_CUT = "\n[... cut to Cursor's %d-character hook limit]" % CONTEXT_MAX
124
+
125
+
126
+ def fit(text):
127
+ """The text as Cursor will carry it: at most CONTEXT_MAX UTF-16 code units."""
128
+ text = text.strip()
129
+ data = text.encode("utf-16-le", "surrogatepass")
130
+ if len(data) <= 2 * CONTEXT_MAX:
131
+ return text
132
+ keep = 2 * (CONTEXT_MAX - len(CONTEXT_CUT)) # the marker is ASCII: one unit a char
133
+ # "ignore" drops the high half of a pair the cut split, never adding a unit
134
+ return data[:keep].decode("utf-16-le", "ignore") + CONTEXT_CUT
108
135
 
109
136
 
110
137
  def cwd_of(payload):
@@ -442,7 +469,8 @@ def dispatch(payload):
442
469
  if (payload.get("status") in (None, "completed")
443
470
  and not off("verify-off") and under(cwd)):
444
471
  reason = stop_reason(last_answer(session_id), session_id, cwd=cwd,
445
- after_block=asked(payload))
472
+ after_block=asked(payload),
473
+ mode=payload.get("permission_mode"))
446
474
  if reason:
447
475
  out = {"decision": "block", "reason": reason}
448
476
  elif event == "beforeSubmitPrompt":
@@ -451,7 +479,7 @@ def dispatch(payload):
451
479
  text = context_for("user_prompt", cwd, payload)
452
480
  out = {"continue": True}
453
481
  if text:
454
- out["additional_context"] = text
482
+ out["additional_context"] = fit(text)
455
483
  else:
456
484
  out = {}
457
485
  return out