@r1z4x/tezgah 1.9.0 → 1.11.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 (429) hide show
  1. package/CHANGELOG.md +98 -1
  2. package/MANIFEST +382 -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 +1 -1
  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 +216 -40
  15. package/bin/tezgah-review-quote +185 -0
  16. package/bin/tezgah-setup +136 -33
  17. package/bin/tezgah-skill +1 -1
  18. package/bin/tezgah-status +201 -3
  19. package/bin/tezgah-task +203 -3
  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 +2 -2
  24. package/docs/clarity-baseline.json +2 -2
  25. package/docs/contract.md +87 -42
  26. package/docs/environment.md +5 -3
  27. package/docs/evidence.md +28 -9
  28. package/docs/feature-audit.md +2 -2
  29. package/docs/gate.md +54 -31
  30. package/docs/glossary.md +5 -2
  31. package/docs/hosts.md +17 -3
  32. package/docs/index.json +34 -8
  33. package/docs/judge.md +4 -2
  34. package/docs/layers.md +3 -3
  35. package/docs/models.md +31 -9
  36. package/docs/operations.md +148 -8
  37. package/docs/research.md +786 -5
  38. package/docs/skills.md +137 -13
  39. package/docs/status-line.md +115 -1
  40. package/hooks/hooks.json +1 -1
  41. package/hooks/lang/en.json +10 -0
  42. package/hooks/lang/tr.json +11 -1
  43. package/hooks/tezgah_agents.py +38 -22
  44. package/hooks/tezgah_apps.py +18 -0
  45. package/hooks/tezgah_components.py +4 -0
  46. package/hooks/tezgah_context.py +189 -50
  47. package/hooks/tezgah_extension.py +337 -0
  48. package/hooks/tezgah_gate.py +188 -56
  49. package/hooks/tezgah_integrity.py +652 -105
  50. package/hooks/tezgah_judge.py +6 -4
  51. package/hooks/tezgah_models.py +59 -19
  52. package/hooks/tezgah_orca.py +1 -1
  53. package/hooks/tezgah_paths.py +102 -6
  54. package/hooks/tezgah_policy.py +94 -45
  55. package/hooks/tezgah_rank.py +9 -6
  56. package/hooks/tezgah_replay.py +4 -4
  57. package/hooks/tezgah_research.py +1260 -65
  58. package/hooks/tezgah_research_capture.py +1544 -0
  59. package/hooks/tezgah_research_evidence.py +842 -0
  60. package/hooks/tezgah_research_stats.py +258 -0
  61. package/hooks/tezgah_skill_pick.py +408 -106
  62. package/hooks/tezgah_stopspec.py +8 -1
  63. package/hooks/tezgah_task.py +12 -4
  64. package/hooks/tezgah_taste_ledger.py +1 -1
  65. package/hosts/cursor/hook.py +29 -2
  66. package/hosts/opencode/plugins/tezgah.js +307 -46
  67. package/hosts/opencode/tui/cli/tui.tsx +100 -0
  68. package/hosts/opencode/tui/tezgah-tui.tsx +2 -1
  69. package/output-styles/tezgah.md +10 -10
  70. package/package.json +1 -1
  71. package/packaging/install.ps1 +36 -3
  72. package/packaging/install.sh +13 -3
  73. package/packaging/upgrade.sh +61 -7
  74. package/skills/ai-research/SKILL.md +21 -14
  75. package/skills/ai-research/SOURCE +7 -5
  76. package/skills/ai-research/index/1-frame.md +6 -6
  77. package/skills/ai-research/index/2-data.md +9 -9
  78. package/skills/ai-research/index/3-train.md +36 -36
  79. package/skills/ai-research/index/4-measure.md +13 -13
  80. package/skills/ai-research/index/5-run.md +11 -11
  81. package/skills/ai-research/index/6-write.md +23 -23
  82. package/skills/ai-research/library.json +104 -104
  83. package/skills/analyze-app/SKILL.md +17 -12
  84. package/skills/design-contract/SKILL.md +42 -7
  85. package/skills/design-contract/data-views.md +2 -2
  86. package/skills/design-library/EVALS.md +1 -1
  87. package/skills/design-library/INDEX.md +39 -39
  88. package/skills/design-library/SKILL.md +19 -13
  89. package/skills/design-library/SOURCE +45 -43
  90. package/skills/feature-audit/SKILL.md +20 -14
  91. package/skills/hallmark/LICENSE +21 -0
  92. package/skills/hallmark/SKILL.md +154 -0
  93. package/skills/hallmark/SOURCE +207 -0
  94. package/skills/hallmark/agents/openai.yaml +13 -0
  95. package/skills/hallmark/references/anatomy.md +71 -0
  96. package/skills/hallmark/references/brand-truth.md +40 -0
  97. package/skills/hallmark/references/comp.md +104 -0
  98. package/skills/hallmark/references/craft.md +116 -0
  99. package/skills/hallmark/references/dark-mode.md +49 -0
  100. package/skills/hallmark/references/data-viz.md +48 -0
  101. package/skills/hallmark/references/design-md.md +53 -0
  102. package/skills/hallmark/references/direction.md +52 -0
  103. package/skills/hallmark/references/export-formats.md +80 -0
  104. package/skills/hallmark/references/flow.md +131 -0
  105. package/skills/hallmark/references/fonts.md +58 -0
  106. package/skills/hallmark/references/gates.md +243 -0
  107. package/skills/hallmark/references/genres/atmospheric.md +24 -0
  108. package/skills/hallmark/references/genres/editorial.md +24 -0
  109. package/skills/hallmark/references/genres/modern-minimal.md +24 -0
  110. package/skills/hallmark/references/genres/playful.md +24 -0
  111. package/skills/hallmark/references/imagery.md +99 -0
  112. package/skills/hallmark/references/interaction-and-states.md +89 -0
  113. package/skills/hallmark/references/layout.md +104 -0
  114. package/skills/hallmark/references/macrostructures/01-bento-grid.md +21 -0
  115. package/skills/hallmark/references/macrostructures/02-long-document.md +35 -0
  116. package/skills/hallmark/references/macrostructures/03-marquee-hero.md +21 -0
  117. package/skills/hallmark/references/macrostructures/04-stat-led.md +21 -0
  118. package/skills/hallmark/references/macrostructures/05-workbench.md +21 -0
  119. package/skills/hallmark/references/macrostructures/06-conversational-faq.md +28 -0
  120. package/skills/hallmark/references/macrostructures/07-manifesto.md +28 -0
  121. package/skills/hallmark/references/macrostructures/08-photographic.md +21 -0
  122. package/skills/hallmark/references/macrostructures/09-quote-led.md +21 -0
  123. package/skills/hallmark/references/macrostructures/10-specimen.md +21 -0
  124. package/skills/hallmark/references/macrostructures/11-catalogue.md +21 -0
  125. package/skills/hallmark/references/macrostructures/12-letter.md +21 -0
  126. package/skills/hallmark/references/macrostructures/13-index-first.md +21 -0
  127. package/skills/hallmark/references/macrostructures/14-narrative-workflow.md +21 -0
  128. package/skills/hallmark/references/macrostructures/15-split-studio.md +21 -0
  129. package/skills/hallmark/references/macrostructures/16-feature-stack.md +23 -0
  130. package/skills/hallmark/references/macrostructures/17-type-specimen.md +19 -0
  131. package/skills/hallmark/references/macrostructures/18-portfolio-grid.md +21 -0
  132. package/skills/hallmark/references/macrostructures/19-map-diagram.md +21 -0
  133. package/skills/hallmark/references/macrostructures/20-ecosystem-index.md +19 -0
  134. package/skills/hallmark/references/macrostructures/21-component-playground.md +21 -0
  135. package/skills/hallmark/references/macrostructures.md +119 -0
  136. package/skills/hallmark/references/microinteractions.md +80 -0
  137. package/skills/hallmark/references/patterns.md +202 -0
  138. package/skills/hallmark/references/redesign.md +88 -0
  139. package/skills/hallmark/references/responsive.md +46 -0
  140. package/skills/hallmark/references/review-finish.md +19 -0
  141. package/skills/hallmark/references/review-hero.md +20 -0
  142. package/skills/hallmark/references/scroll-choreography.md +110 -0
  143. package/skills/hallmark/references/texture.md +90 -0
  144. package/skills/hallmark/references/themes/README.md +58 -0
  145. package/skills/hallmark/references/themes/almanac.jpg +0 -0
  146. package/skills/hallmark/references/themes/almanac.md +103 -0
  147. package/skills/hallmark/references/themes/arcade.jpg +0 -0
  148. package/skills/hallmark/references/themes/arcade.md +102 -0
  149. package/skills/hallmark/references/themes/atelier.jpg +0 -0
  150. package/skills/hallmark/references/themes/atelier.md +98 -0
  151. package/skills/hallmark/references/themes/bloom.jpg +0 -0
  152. package/skills/hallmark/references/themes/bloom.md +102 -0
  153. package/skills/hallmark/references/themes/blueprint.jpg +0 -0
  154. package/skills/hallmark/references/themes/blueprint.md +103 -0
  155. package/skills/hallmark/references/themes/broadside.jpg +0 -0
  156. package/skills/hallmark/references/themes/broadside.md +108 -0
  157. package/skills/hallmark/references/themes/brutal.jpg +0 -0
  158. package/skills/hallmark/references/themes/brutal.md +95 -0
  159. package/skills/hallmark/references/themes/carnival.jpg +0 -0
  160. package/skills/hallmark/references/themes/carnival.md +104 -0
  161. package/skills/hallmark/references/themes/cobalt.jpg +0 -0
  162. package/skills/hallmark/references/themes/cobalt.md +101 -0
  163. package/skills/hallmark/references/themes/console.jpg +0 -0
  164. package/skills/hallmark/references/themes/console.md +99 -0
  165. package/skills/hallmark/references/themes/coral.jpg +0 -0
  166. package/skills/hallmark/references/themes/coral.md +102 -0
  167. package/skills/hallmark/references/themes/darkroom.jpg +0 -0
  168. package/skills/hallmark/references/themes/darkroom.md +99 -0
  169. package/skills/hallmark/references/themes/dose.jpg +0 -0
  170. package/skills/hallmark/references/themes/dose.md +98 -0
  171. package/skills/hallmark/references/themes/dusk.jpg +0 -0
  172. package/skills/hallmark/references/themes/dusk.md +105 -0
  173. package/skills/hallmark/references/themes/editorial.jpg +0 -0
  174. package/skills/hallmark/references/themes/editorial.md +97 -0
  175. package/skills/hallmark/references/themes/formwork.jpg +0 -0
  176. package/skills/hallmark/references/themes/formwork.md +107 -0
  177. package/skills/hallmark/references/themes/furrow.jpg +0 -0
  178. package/skills/hallmark/references/themes/furrow.md +98 -0
  179. package/skills/hallmark/references/themes/garden.jpg +0 -0
  180. package/skills/hallmark/references/themes/garden.md +97 -0
  181. package/skills/hallmark/references/themes/grid.jpg +0 -0
  182. package/skills/hallmark/references/themes/grid.md +101 -0
  183. package/skills/hallmark/references/themes/halftone.jpg +0 -0
  184. package/skills/hallmark/references/themes/halftone.md +106 -0
  185. package/skills/hallmark/references/themes/hedgerow.jpg +0 -0
  186. package/skills/hallmark/references/themes/hedgerow.md +104 -0
  187. package/skills/hallmark/references/themes/hum.jpg +0 -0
  188. package/skills/hallmark/references/themes/hum.md +99 -0
  189. package/skills/hallmark/references/themes/index.json +2191 -0
  190. package/skills/hallmark/references/themes/ink.jpg +0 -0
  191. package/skills/hallmark/references/themes/ink.md +106 -0
  192. package/skills/hallmark/references/themes/kiln.jpg +0 -0
  193. package/skills/hallmark/references/themes/kiln.md +108 -0
  194. package/skills/hallmark/references/themes/loom.jpg +0 -0
  195. package/skills/hallmark/references/themes/loom.md +106 -0
  196. package/skills/hallmark/references/themes/lumen.jpg +0 -0
  197. package/skills/hallmark/references/themes/lumen.md +103 -0
  198. package/skills/hallmark/references/themes/manifesto.jpg +0 -0
  199. package/skills/hallmark/references/themes/manifesto.md +101 -0
  200. package/skills/hallmark/references/themes/midnight.jpg +0 -0
  201. package/skills/hallmark/references/themes/midnight.md +97 -0
  202. package/skills/hallmark/references/themes/newsprint.jpg +0 -0
  203. package/skills/hallmark/references/themes/newsprint.md +102 -0
  204. package/skills/hallmark/references/themes/overprint.jpg +0 -0
  205. package/skills/hallmark/references/themes/overprint.md +101 -0
  206. package/skills/hallmark/references/themes/pasteup.jpg +0 -0
  207. package/skills/hallmark/references/themes/pasteup.md +100 -0
  208. package/skills/hallmark/references/themes/piste.jpg +0 -0
  209. package/skills/hallmark/references/themes/piste.md +99 -0
  210. package/skills/hallmark/references/themes/ribbon.jpg +0 -0
  211. package/skills/hallmark/references/themes/ribbon.md +106 -0
  212. package/skills/hallmark/references/themes/rim.jpg +0 -0
  213. package/skills/hallmark/references/themes/rim.md +96 -0
  214. package/skills/hallmark/references/themes/riso.jpg +0 -0
  215. package/skills/hallmark/references/themes/riso.md +98 -0
  216. package/skills/hallmark/references/themes/solstice.jpg +0 -0
  217. package/skills/hallmark/references/themes/solstice.md +104 -0
  218. package/skills/hallmark/references/themes/specimen.jpg +0 -0
  219. package/skills/hallmark/references/themes/specimen.md +100 -0
  220. package/skills/hallmark/references/themes/spore.jpg +0 -0
  221. package/skills/hallmark/references/themes/spore.md +104 -0
  222. package/skills/hallmark/references/themes/sport.jpg +0 -0
  223. package/skills/hallmark/references/themes/sport.md +101 -0
  224. package/skills/hallmark/references/themes/squeeze.jpg +0 -0
  225. package/skills/hallmark/references/themes/squeeze.md +99 -0
  226. package/skills/hallmark/references/themes/sticker.jpg +0 -0
  227. package/skills/hallmark/references/themes/sticker.md +106 -0
  228. package/skills/hallmark/references/themes/studio.jpg +0 -0
  229. package/skills/hallmark/references/themes/studio.md +99 -0
  230. package/skills/hallmark/references/themes/terminal.jpg +0 -0
  231. package/skills/hallmark/references/themes/terminal.md +96 -0
  232. package/skills/hallmark/references/themes/terrazzo.jpg +0 -0
  233. package/skills/hallmark/references/themes/terrazzo.md +106 -0
  234. package/skills/hallmark/references/themes/ultraviolet.jpg +0 -0
  235. package/skills/hallmark/references/themes/ultraviolet.md +106 -0
  236. package/skills/hallmark/references/themes/vellum.jpg +0 -0
  237. package/skills/hallmark/references/themes/vellum.md +105 -0
  238. package/skills/hallmark/references/themes/wayfind.jpg +0 -0
  239. package/skills/hallmark/references/themes/wayfind.md +105 -0
  240. package/skills/hallmark/references/themes/werkstatt.jpg +0 -0
  241. package/skills/hallmark/references/themes/werkstatt.md +105 -0
  242. package/skills/hallmark/scripts/capture.mjs +125 -0
  243. package/skills/hallmark/scripts/fixtures/exemplars/atmospheric.html +324 -0
  244. package/skills/hallmark/scripts/fixtures/exemplars/editorial.html +363 -0
  245. package/skills/hallmark/scripts/fixtures/exemplars/modern-minimal.html +527 -0
  246. package/skills/hallmark/scripts/fixtures/exemplars/playful.html +353 -0
  247. package/skills/hallmark/scripts/fixtures/eyebrow-fail/index.html +118 -0
  248. package/skills/hallmark/scripts/fixtures/eyebrow-pass/index.html +137 -0
  249. package/skills/hallmark/scripts/fixtures/kept/after.html +27 -0
  250. package/skills/hallmark/scripts/fixtures/kept/before.html +26 -0
  251. package/skills/hallmark/scripts/fixtures/slopped.html +145 -0
  252. package/skills/hallmark/scripts/fixtures/tailwind-fail/Feature.vue +14 -0
  253. package/skills/hallmark/scripts/fixtures/tailwind-fail/Hero.tsx +33 -0
  254. package/skills/hallmark/scripts/fixtures/tailwind-fail/index.html +74 -0
  255. package/skills/hallmark/scripts/fixtures/tailwind-fail/style.css +6 -0
  256. package/skills/hallmark/scripts/fixtures/tailwind-pass/Hero.tsx +33 -0
  257. package/skills/hallmark/scripts/fixtures/tailwind-pass/index.html +57 -0
  258. package/skills/hallmark/scripts/fixtures/tailwind-pass/style.css +15 -0
  259. package/skills/hallmark/scripts/fixtures/waiver/index.html +54 -0
  260. package/skills/hallmark/scripts/imagegen.mjs +85 -0
  261. package/skills/hallmark/scripts/install-hook.mjs +70 -0
  262. package/skills/hallmark/scripts/install.mjs +141 -0
  263. package/skills/hallmark/scripts/lint-hook.mjs +49 -0
  264. package/skills/hallmark/scripts/photos.json +1 -0
  265. package/skills/hallmark/scripts/picture.mjs +71 -0
  266. package/skills/hallmark/scripts/refcheck.mjs +352 -0
  267. package/skills/hallmark/scripts/sloplint-render.mjs +1252 -0
  268. package/skills/hallmark/scripts/sloplint.mjs +4422 -0
  269. package/skills/hallmark/scripts/theme.mjs +650 -0
  270. package/skills/harness/SKILL.md +15 -8
  271. package/skills/i-have-adhd/SKILL.md +22 -11
  272. package/skills/no-ai-slop/SKILL.md +15 -1
  273. package/skills/plan-add/SKILL.md +33 -26
  274. package/skills/plan-status/SKILL.md +13 -7
  275. package/skills/plan-sync/SKILL.md +18 -12
  276. package/skills/pm-frameworks/SKILL.md +19 -10
  277. package/skills/pm-frameworks/SOURCE +7 -5
  278. package/skills/ponytail/SKILL.md +19 -14
  279. package/skills/product-analysis/SKILL.md +22 -18
  280. package/skills/product-flow/SKILL.md +14 -9
  281. package/skills/research/SKILL.md +75 -39
  282. package/skills/rl-env/SKILL.md +25 -13
  283. package/skills/rl-env/SOURCE +8 -6
  284. package/skills/tezgah-contract/SKILL.md +47 -42
  285. package/bin/tezgah-skill.py +0 -59
  286. /package/skills/ai-research/0-autoresearch-skill/{SKILL.md → ENTRY.md} +0 -0
  287. /package/skills/ai-research/01-model-architecture/litgpt/{SKILL.md → ENTRY.md} +0 -0
  288. /package/skills/ai-research/01-model-architecture/mamba/{SKILL.md → ENTRY.md} +0 -0
  289. /package/skills/ai-research/01-model-architecture/nanogpt/{SKILL.md → ENTRY.md} +0 -0
  290. /package/skills/ai-research/01-model-architecture/rwkv/{SKILL.md → ENTRY.md} +0 -0
  291. /package/skills/ai-research/01-model-architecture/torchtitan/{SKILL.md → ENTRY.md} +0 -0
  292. /package/skills/ai-research/02-tokenization/huggingface-tokenizers/{SKILL.md → ENTRY.md} +0 -0
  293. /package/skills/ai-research/02-tokenization/sentencepiece/{SKILL.md → ENTRY.md} +0 -0
  294. /package/skills/ai-research/03-fine-tuning/axolotl/{SKILL.md → ENTRY.md} +0 -0
  295. /package/skills/ai-research/03-fine-tuning/llama-factory/{SKILL.md → ENTRY.md} +0 -0
  296. /package/skills/ai-research/03-fine-tuning/peft/{SKILL.md → ENTRY.md} +0 -0
  297. /package/skills/ai-research/03-fine-tuning/unsloth/{SKILL.md → ENTRY.md} +0 -0
  298. /package/skills/ai-research/04-mechanistic-interpretability/nnsight/{SKILL.md → ENTRY.md} +0 -0
  299. /package/skills/ai-research/04-mechanistic-interpretability/pyvene/{SKILL.md → ENTRY.md} +0 -0
  300. /package/skills/ai-research/04-mechanistic-interpretability/saelens/{SKILL.md → ENTRY.md} +0 -0
  301. /package/skills/ai-research/04-mechanistic-interpretability/transformer-lens/{SKILL.md → ENTRY.md} +0 -0
  302. /package/skills/ai-research/05-data-processing/nemo-curator/{SKILL.md → ENTRY.md} +0 -0
  303. /package/skills/ai-research/05-data-processing/ray-data/{SKILL.md → ENTRY.md} +0 -0
  304. /package/skills/ai-research/06-post-training/grpo-rl-training/{SKILL.md → ENTRY.md} +0 -0
  305. /package/skills/ai-research/06-post-training/miles/{SKILL.md → ENTRY.md} +0 -0
  306. /package/skills/ai-research/06-post-training/openrlhf/{SKILL.md → ENTRY.md} +0 -0
  307. /package/skills/ai-research/06-post-training/simpo/{SKILL.md → ENTRY.md} +0 -0
  308. /package/skills/ai-research/06-post-training/slime/{SKILL.md → ENTRY.md} +0 -0
  309. /package/skills/ai-research/06-post-training/torchforge/{SKILL.md → ENTRY.md} +0 -0
  310. /package/skills/ai-research/06-post-training/trl-fine-tuning/{SKILL.md → ENTRY.md} +0 -0
  311. /package/skills/ai-research/06-post-training/verl/{SKILL.md → ENTRY.md} +0 -0
  312. /package/skills/ai-research/07-safety-alignment/constitutional-ai/{SKILL.md → ENTRY.md} +0 -0
  313. /package/skills/ai-research/07-safety-alignment/llamaguard/{SKILL.md → ENTRY.md} +0 -0
  314. /package/skills/ai-research/07-safety-alignment/nemo-guardrails/{SKILL.md → ENTRY.md} +0 -0
  315. /package/skills/ai-research/07-safety-alignment/prompt-guard/{SKILL.md → ENTRY.md} +0 -0
  316. /package/skills/ai-research/08-distributed-training/accelerate/{SKILL.md → ENTRY.md} +0 -0
  317. /package/skills/ai-research/08-distributed-training/deepspeed/{SKILL.md → ENTRY.md} +0 -0
  318. /package/skills/ai-research/08-distributed-training/megatron-core/{SKILL.md → ENTRY.md} +0 -0
  319. /package/skills/ai-research/08-distributed-training/pytorch-fsdp2/{SKILL.md → ENTRY.md} +0 -0
  320. /package/skills/ai-research/08-distributed-training/pytorch-lightning/{SKILL.md → ENTRY.md} +0 -0
  321. /package/skills/ai-research/08-distributed-training/ray-train/{SKILL.md → ENTRY.md} +0 -0
  322. /package/skills/ai-research/09-infrastructure/lambda-labs/{SKILL.md → ENTRY.md} +0 -0
  323. /package/skills/ai-research/09-infrastructure/modal/{SKILL.md → ENTRY.md} +0 -0
  324. /package/skills/ai-research/09-infrastructure/skypilot/{SKILL.md → ENTRY.md} +0 -0
  325. /package/skills/ai-research/10-optimization/awq/{SKILL.md → ENTRY.md} +0 -0
  326. /package/skills/ai-research/10-optimization/bitsandbytes/{SKILL.md → ENTRY.md} +0 -0
  327. /package/skills/ai-research/10-optimization/flash-attention/{SKILL.md → ENTRY.md} +0 -0
  328. /package/skills/ai-research/10-optimization/gguf/{SKILL.md → ENTRY.md} +0 -0
  329. /package/skills/ai-research/10-optimization/gptq/{SKILL.md → ENTRY.md} +0 -0
  330. /package/skills/ai-research/10-optimization/hqq/{SKILL.md → ENTRY.md} +0 -0
  331. /package/skills/ai-research/10-optimization/ml-training-recipes/{SKILL.md → ENTRY.md} +0 -0
  332. /package/skills/ai-research/11-evaluation/bigcode-evaluation-harness/{SKILL.md → ENTRY.md} +0 -0
  333. /package/skills/ai-research/11-evaluation/lm-evaluation-harness/{SKILL.md → ENTRY.md} +0 -0
  334. /package/skills/ai-research/11-evaluation/nemo-evaluator/{SKILL.md → ENTRY.md} +0 -0
  335. /package/skills/ai-research/12-inference-serving/llama-cpp/{SKILL.md → ENTRY.md} +0 -0
  336. /package/skills/ai-research/12-inference-serving/sglang/{SKILL.md → ENTRY.md} +0 -0
  337. /package/skills/ai-research/12-inference-serving/tensorrt-llm/{SKILL.md → ENTRY.md} +0 -0
  338. /package/skills/ai-research/12-inference-serving/vllm/{SKILL.md → ENTRY.md} +0 -0
  339. /package/skills/ai-research/13-mlops/mlflow/{SKILL.md → ENTRY.md} +0 -0
  340. /package/skills/ai-research/13-mlops/swanlab/{SKILL.md → ENTRY.md} +0 -0
  341. /package/skills/ai-research/13-mlops/tensorboard/{SKILL.md → ENTRY.md} +0 -0
  342. /package/skills/ai-research/13-mlops/weights-and-biases/{SKILL.md → ENTRY.md} +0 -0
  343. /package/skills/ai-research/14-agents/a-evolve/{SKILL.md → ENTRY.md} +0 -0
  344. /package/skills/ai-research/14-agents/autogpt/{SKILL.md → ENTRY.md} +0 -0
  345. /package/skills/ai-research/14-agents/crewai/{SKILL.md → ENTRY.md} +0 -0
  346. /package/skills/ai-research/14-agents/langchain/{SKILL.md → ENTRY.md} +0 -0
  347. /package/skills/ai-research/14-agents/llamaindex/{SKILL.md → ENTRY.md} +0 -0
  348. /package/skills/ai-research/15-rag/chroma/{SKILL.md → ENTRY.md} +0 -0
  349. /package/skills/ai-research/15-rag/faiss/{SKILL.md → ENTRY.md} +0 -0
  350. /package/skills/ai-research/15-rag/pinecone/{SKILL.md → ENTRY.md} +0 -0
  351. /package/skills/ai-research/15-rag/qdrant/{SKILL.md → ENTRY.md} +0 -0
  352. /package/skills/ai-research/15-rag/sentence-transformers/{SKILL.md → ENTRY.md} +0 -0
  353. /package/skills/ai-research/16-prompt-engineering/dspy/{SKILL.md → ENTRY.md} +0 -0
  354. /package/skills/ai-research/16-prompt-engineering/guidance/{SKILL.md → ENTRY.md} +0 -0
  355. /package/skills/ai-research/16-prompt-engineering/instructor/{SKILL.md → ENTRY.md} +0 -0
  356. /package/skills/ai-research/16-prompt-engineering/outlines/{SKILL.md → ENTRY.md} +0 -0
  357. /package/skills/ai-research/17-observability/langsmith/{SKILL.md → ENTRY.md} +0 -0
  358. /package/skills/ai-research/17-observability/phoenix/{SKILL.md → ENTRY.md} +0 -0
  359. /package/skills/ai-research/18-multimodal/audiocraft/{SKILL.md → ENTRY.md} +0 -0
  360. /package/skills/ai-research/18-multimodal/blip-2/{SKILL.md → ENTRY.md} +0 -0
  361. /package/skills/ai-research/18-multimodal/clip/{SKILL.md → ENTRY.md} +0 -0
  362. /package/skills/ai-research/18-multimodal/cosmos-policy/{SKILL.md → ENTRY.md} +0 -0
  363. /package/skills/ai-research/18-multimodal/llava/{SKILL.md → ENTRY.md} +0 -0
  364. /package/skills/ai-research/18-multimodal/openpi/{SKILL.md → ENTRY.md} +0 -0
  365. /package/skills/ai-research/18-multimodal/openvla-oft/{SKILL.md → ENTRY.md} +0 -0
  366. /package/skills/ai-research/18-multimodal/segment-anything/{SKILL.md → ENTRY.md} +0 -0
  367. /package/skills/ai-research/18-multimodal/stable-diffusion/{SKILL.md → ENTRY.md} +0 -0
  368. /package/skills/ai-research/18-multimodal/whisper/{SKILL.md → ENTRY.md} +0 -0
  369. /package/skills/ai-research/19-emerging-techniques/knowledge-distillation/{SKILL.md → ENTRY.md} +0 -0
  370. /package/skills/ai-research/19-emerging-techniques/long-context/{SKILL.md → ENTRY.md} +0 -0
  371. /package/skills/ai-research/19-emerging-techniques/model-merging/{SKILL.md → ENTRY.md} +0 -0
  372. /package/skills/ai-research/19-emerging-techniques/model-pruning/{SKILL.md → ENTRY.md} +0 -0
  373. /package/skills/ai-research/19-emerging-techniques/moe-training/{SKILL.md → ENTRY.md} +0 -0
  374. /package/skills/ai-research/19-emerging-techniques/speculative-decoding/{SKILL.md → ENTRY.md} +0 -0
  375. /package/skills/ai-research/20-ml-paper-writing/academic-plotting/{SKILL.md → ENTRY.md} +0 -0
  376. /package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/{SKILL.md → ENTRY.md} +0 -0
  377. /package/skills/ai-research/20-ml-paper-writing/presenting-conference-talks/{SKILL.md → ENTRY.md} +0 -0
  378. /package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/{SKILL.md → ENTRY.md} +0 -0
  379. /package/skills/ai-research/21-research-ideation/brainstorming-research-ideas/{SKILL.md → ENTRY.md} +0 -0
  380. /package/skills/ai-research/21-research-ideation/creative-thinking-for-research/{SKILL.md → ENTRY.md} +0 -0
  381. /package/skills/ai-research/22-agent-native-research-artifact/compiler/{SKILL.md → ENTRY.md} +0 -0
  382. /package/skills/ai-research/22-agent-native-research-artifact/research-manager/{SKILL.md → ENTRY.md} +0 -0
  383. /package/skills/ai-research/22-agent-native-research-artifact/rigor-reviewer/{SKILL.md → ENTRY.md} +0 -0
  384. /package/skills/design-library/adaptive-interfaces/skills/colour-independence/{SKILL.md → ENTRY.md} +0 -0
  385. /package/skills/design-library/adaptive-interfaces/skills/flexible-typography/{SKILL.md → ENTRY.md} +0 -0
  386. /package/skills/design-library/adaptive-interfaces/skills/information-density/{SKILL.md → ENTRY.md} +0 -0
  387. /package/skills/design-library/adaptive-interfaces/skills/preference-audit/{SKILL.md → ENTRY.md} +0 -0
  388. /package/skills/design-library/adaptive-interfaces/skills/responsive-accessibility/{SKILL.md → ENTRY.md} +0 -0
  389. /package/skills/design-library/adaptive-interfaces/skills/responsive-review/{SKILL.md → ENTRY.md} +0 -0
  390. /package/skills/design-library/adaptive-interfaces/skills/simplified-views/{SKILL.md → ENTRY.md} +0 -0
  391. /package/skills/design-library/adaptive-interfaces/skills/specify/{SKILL.md → ENTRY.md} +0 -0
  392. /package/skills/design-library/adaptive-interfaces/skills/user-preference-respect/{SKILL.md → ENTRY.md} +0 -0
  393. /package/skills/design-library/cognitive-accessibility/skills/adaptive-personalisation/{SKILL.md → ENTRY.md} +0 -0
  394. /package/skills/design-library/cognitive-accessibility/skills/assess-load/{SKILL.md → ENTRY.md} +0 -0
  395. /package/skills/design-library/cognitive-accessibility/skills/cognitive-load-assessment/{SKILL.md → ENTRY.md} +0 -0
  396. /package/skills/design-library/cognitive-accessibility/skills/contextual-help-design/{SKILL.md → ENTRY.md} +0 -0
  397. /package/skills/design-library/cognitive-accessibility/skills/error-prevention-recovery/{SKILL.md → ENTRY.md} +0 -0
  398. /package/skills/design-library/cognitive-accessibility/skills/focus-attention-design/{SKILL.md → ENTRY.md} +0 -0
  399. /package/skills/design-library/cognitive-accessibility/skills/memory-load-reduction/{SKILL.md → ENTRY.md} +0 -0
  400. /package/skills/design-library/cognitive-accessibility/skills/plain-language-design/{SKILL.md → ENTRY.md} +0 -0
  401. /package/skills/design-library/cognitive-accessibility/skills/review/{SKILL.md → ENTRY.md} +0 -0
  402. /package/skills/design-library/cognitive-accessibility/skills/simplify/{SKILL.md → ENTRY.md} +0 -0
  403. /package/skills/design-library/cognitive-accessibility/skills/wayfinding-navigation/{SKILL.md → ENTRY.md} +0 -0
  404. /package/skills/design-library/design-research/skills/behavioural-analytics/{SKILL.md → ENTRY.md} +0 -0
  405. /package/skills/design-library/design-research/skills/qual-quant-triangulation/{SKILL.md → ENTRY.md} +0 -0
  406. /package/skills/design-library/inclusive-interaction/skills/audit/{SKILL.md → ENTRY.md} +0 -0
  407. /package/skills/design-library/inclusive-interaction/skills/design-flow/{SKILL.md → ENTRY.md} +0 -0
  408. /package/skills/design-library/inclusive-interaction/skills/feedback-and-status/{SKILL.md → ENTRY.md} +0 -0
  409. /package/skills/design-library/inclusive-interaction/skills/gesture-alternatives/{SKILL.md → ENTRY.md} +0 -0
  410. /package/skills/design-library/inclusive-interaction/skills/keyboard-navigation/{SKILL.md → ENTRY.md} +0 -0
  411. /package/skills/design-library/inclusive-interaction/skills/keyboard-review/{SKILL.md → ENTRY.md} +0 -0
  412. /package/skills/design-library/inclusive-interaction/skills/motion-sensitivity/{SKILL.md → ENTRY.md} +0 -0
  413. /package/skills/design-library/inclusive-interaction/skills/multi-modal-input/{SKILL.md → ENTRY.md} +0 -0
  414. /package/skills/design-library/inclusive-interaction/skills/touch-target-design/{SKILL.md → ENTRY.md} +0 -0
  415. /package/skills/design-library/inclusive-interaction/skills/voice-interaction/{SKILL.md → ENTRY.md} +0 -0
  416. /package/skills/design-library/visual-critique/skills/critique-affordance/{SKILL.md → ENTRY.md} +0 -0
  417. /package/skills/design-library/visual-critique/skills/critique-brand-consistency/{SKILL.md → ENTRY.md} +0 -0
  418. /package/skills/design-library/visual-critique/skills/critique-color/{SKILL.md → ENTRY.md} +0 -0
  419. /package/skills/design-library/visual-critique/skills/critique-composition/{SKILL.md → ENTRY.md} +0 -0
  420. /package/skills/design-library/visual-critique/skills/critique-information-density/{SKILL.md → ENTRY.md} +0 -0
  421. /package/skills/design-library/visual-critique/skills/critique-typography/{SKILL.md → ENTRY.md} +0 -0
  422. /package/skills/design-library/visual-critique/skills/critique-visual-hierarchy/{SKILL.md → ENTRY.md} +0 -0
  423. /package/skills/pm-frameworks/intended-vs-implemented/{SKILL.md → ENTRY.md} +0 -0
  424. /package/skills/pm-frameworks/opportunity-solution-tree/{SKILL.md → ENTRY.md} +0 -0
  425. /package/skills/rl-env/generate-nemo-gym-env/{SKILL.md → ENTRY.md} +0 -0
  426. /package/skills/rl-env/generate-openenv-env/{SKILL.md → ENTRY.md} +0 -0
  427. /package/skills/rl-env/generate-ors-env/{SKILL.md → ENTRY.md} +0 -0
  428. /package/skills/rl-env/generate-verifiers-env/{SKILL.md → ENTRY.md} +0 -0
  429. /package/skills/rl-env/rl-env-from-description/{SKILL.md → ENTRY.md} +0 -0
package/docs/evidence.md CHANGED
@@ -49,7 +49,7 @@ written path as an absolute real path, resolved against the call's cwd (`_abs_ta
49
49
  now compares `target`, and a row without one (written before the field landed) is ignored by that
50
50
  guard rather than matched by its spelling (audit M-6). Both writers write `tool` — `note_tool`, and opencode's
51
51
  plugin, whose row carries the same field under the same empty-means-absent rule
52
- (`hosts/opencode/plugins/tezgah.js:1253-1264`) — so no live host leaves it out. A row written *before*
52
+ (`hosts/opencode/plugins/tezgah.js:1282-1293`) — so no live host leaves it out. A row written *before*
53
53
  the field landed names its tool only where the name survived in `detail` — an `unknown` row and an
54
54
  MCP `external` row — so the one cause of an under-count is the corpus's age, and it shrinks as
55
55
  sessions run. The append is one INSERT in autocommit (`hooks/tezgah_integrity.py::_append`,
@@ -115,13 +115,13 @@ a write tool is `edit`, a shell call is `verify` when its command matches the ch
115
115
  | Kind | Written by | Read by |
116
116
  |---|---|---|
117
117
  | `turn` | `hooks/tezgah_integrity.py::note_turn`, from the prompt path | `hooks/tezgah_integrity.py::_turn_start`, scoping every turn rule; `hooks/tezgah_integrity.py::_claim_key` |
118
- | `run`, `edit`, `verify`, `verify_ok`, `verify_fail`, `interrupted` | `hooks/tezgah_integrity.py::note_tool`, the call's own name in `tool`, on opencode the plugin writes these same kinds and the same field (`hosts/opencode/plugins/tezgah.js:1215-1293`) | the Stop rule's `worked` set `hooks/tezgah_integrity.py::WORK_KINDS`; `counters.steps` `hooks/tezgah_integrity.py::_counts`; `last_verify`/`partial_state`; the `--trend` tool histogram |
118
+ | `run`, `edit`, `verify`, `verify_ok`, `verify_fail`, `interrupted` | `hooks/tezgah_integrity.py::note_tool`, the call's own name in `tool`, on opencode the plugin writes these same kinds and the same field (`hosts/opencode/plugins/tezgah.js:1244-1322`) | the Stop rule's `worked` set `hooks/tezgah_integrity.py::WORK_KINDS`; `counters.steps` `hooks/tezgah_integrity.py::_counts`; `last_verify`/`partial_state`; the `--trend` tool histogram |
119
119
  | `external`, `unknown` | `hooks/tezgah_integrity.py::note_tool` | the taint notice, via `source`; the `--trend` tool histogram; nothing counts them as work |
120
120
  | `todo` | `hooks/tezgah_integrity.py::note_todo`, from `note_tool` for a todo call: omp `todo` (the bridge sends the list from the result's `details`), Claude and dsh `TodoWrite` (their PostToolUse matcher), opencode `todowrite` (the plugin's own `recordTodo`), Cursor `todo_write` and Codex `update_plan`, which arrive with no matcher. `open`, `ready` and `blocked` count the list, `detail` holds the ready items' heads, one per line, `taken` holds the in-progress items' heads, and `partial` marks a Cursor `merge: true` list | the `ready steps` and `open todo` Stop classes (`hooks/tezgah_integrity.py::ready_left`, `hooks/tezgah_integrity.py::open_left`) and the idle-wait warning (`hooks/tezgah_gate.py::ready_advice`) |
121
121
  | `wait` | `hooks/tezgah_integrity.py::note_tool`, for omp's `wait` | `hooks/tezgah_gate.py::ready_advice`, which counts it as idle; nothing counts it as work |
122
122
  | `ask` | `hooks/tezgah_gate.py::ask_advice`, for an omp `ask` or Claude AskUserQuestion call: `detail` holds the questions, cut; `questions` counts them and `defaults` the ones with a recommended option | nothing refuses on it; the row is the record of what the session asked |
123
123
  | `grant` | `hooks/tezgah_context.py::context_for`, from each prompt's `user_grants` (`hooks/tezgah_context.py::user_grants`): `detail` holds the user's clause, `target` the outward class it covers (`push`, `release`, `publish`, `pr` or `all`), or `lift:<class>` when the prompt took it back | `hooks/tezgah_integrity.py::grants_in_force`, read by the `needless ask` Stop class and the ask-tool warning |
124
- | `began` | the gate's allow path for a write or shell call `hooks/tezgah_gate.py::decision`; on opencode the plugin's before-hook when the core was not asked (`hosts/opencode/plugins/tezgah.js:2572-2588`) | `hooks/tezgah_integrity.py::unanswered`, behind a claim in the Stop rule and in `counters.unanswered` |
124
+ | `began` | the gate's allow path for a write or shell call `hooks/tezgah_gate.py::decision`; on opencode the plugin's before-hook when the core was not asked (`hosts/opencode/plugins/tezgah.js:2602-2618`) | `hooks/tezgah_integrity.py::unanswered`, behind a claim in the Stop rule and in `counters.unanswered` |
125
125
  | `claim` | `hooks/tezgah_integrity.py::stop_reason`, only for a reply in the claim vocabulary - a completion or verification word (`DONE`/`VERIFIED`), blocked or allowed, or a refused claim about an external system's state (`_external_claim`) | `hooks/tezgah_integrity.py::counters` |
126
126
  | `refusal` | `stop_reason`, for a blocked reply that claimed nothing - a work-only or a shape refusal - with the same `blocked: <class>` detail (row version 3) | `counters.refusals`, and `shape_blocked` for a shape class; never a claim; `NOT_TOOL_HOOK` lists it |
127
127
  | `after_block` | `hooks/tezgah_integrity.py::stop_reason`, on a reply after this rule's own block (a turn holding a `blocked:` claim or refusal row) that is not refused again (`_record_only`) on Claude, Codex, Cursor and omp; `detail` is `would block: <class>`, `ok` or `no claim` | nothing yet: a record for the after-block observation window, not a claim and not a second `shape` row, so `counters` counts it neither as a claim nor as a reply; `NOT_TOOL_HOOK` lists it |
@@ -556,11 +556,30 @@ whole session instead of the turn:
556
556
  after the work, where the turn fold saw nothing to judge (audit M-2, INT-01).
557
557
  - **A turn of reads.** The rule treats a turn of known reads as a turn with no work (plan 086,
558
558
  S4). Each command in it is a known read: a program in `READ_ONLY_PROGRAMS` or a git read in
559
- `GIT_READS`, with no option in `WRITING_OPTIONS`. `sed`, `awk`, `uniq`, `gh` and `codegraph`
559
+ `GIT_READS`, with no option in `WRITING_OPTIONS`. `printf -v` assigns a variable, so `-v` is
560
+ such an option. `sed`, `awk`, `uniq`, `gh` and `codegraph`
560
561
  count with no writing script, one operand or a read verb. A `sqlite3` read-only open counts,
561
562
  from the option or the database URI, and so does an `ssh` whose remote command is
562
563
  such a read (`hooks/tezgah_integrity.py::_bookkeeping_command`). Any other command, a commit included,
563
- keeps the turn worked and owes the check.
564
+ keeps the turn worked and owes the check. So does a word bash turns into more than it shows
565
+ (`hooks/tezgah_integrity.py::_shell_read`). A brace list (`BRACE_EXPANSION`) is two words:
566
+ `{-delete,-print}`. A `$` other than a plain `$name` or `${name}` counts too (`PLAIN_DOLLAR`).
567
+ `${x:--delete}` gives an option, and the arithmetic in `$[x]`, `$((x))` and `${a[x]}` runs a
568
+ `$( )` held in its value. A function definition runs its body with arguments no reader saw.
569
+ Plan 126 measured 4 of 6
570
+ live advice turns refused for reads in a loop
571
+ (`for f in $(find src -type f); do cat -n "$f"; done`). Now a reply that claims
572
+ nothing also ends such a turn. The reader counts a `for NAME in WORDS` loop, the `if`/`while`/`{`
573
+ words around reads and an unquoted `$( )` whose body reads (`loops=True`). A value they bind, or a
574
+ positional parameter, reaches only a reader with no writing option (`OPTION_FREE`). The loop name
575
+ is one lowercase letter: not `PATH` or `IFS`, and not a zsh name tied to a setting (`path`,
576
+ `fpath`, `status`). A done/tested claim over such a turn keeps the worked turn's fold. A build
577
+ (`npm run build > log`) is a check, never a read. It records as `verify`, or as `verify_ok` or
578
+ `verify_fail` when its status shows. A `set` of shell options (`set -o pipefail;`, `set -eu`)
579
+ counts as a read, because the contract asks a check line to open with it. A `set` with any other
580
+ word stays work (`SET_FLAGS`, `SET_NAMES`). `find ... | xargs sh -c '...'` stays work: the
581
+ reader does not follow a command string into `sh -c`. A command of `DETAIL_MAX` (200) characters
582
+ or more stays work too, because the ledger cut it and the rest is unread.
564
583
  - **A bookkeeping turn after a pass.** A turn whose only rows are read-only or VCS-bookkeeping
565
584
  commands ends without a fresh check, as long as nothing but bookkeeping ran after the session's
566
585
  newest pass, the session fold above allows it, and the reply makes no external-state claim
@@ -653,7 +672,7 @@ line never asked. Three surfaces recognise a read, and they have to agree on the
653
672
  bridge calls (`hosts/omp/hook.py::classify`), omp's own filter, which decides whether python hears about the
654
673
  read at all (`hosts/omp/tezgah-hook.ts.in:227-264`, its catalogue the checkout `@HOOK@` names), and
655
674
  opencode's plugin, which classifies in process because that host has no Python hook
656
- (`hosts/opencode/plugins/tezgah.js:2185-2242`, its catalogue the host's own installed skill dir
675
+ (`hosts/opencode/plugins/tezgah.js:2214-2272`, its catalogue the host's own installed skill dir
657
676
  (`dirname(CONFIG)/opencode/skills`), which `tezgah-setup` fills with every shipped skill).
658
677
 
659
678
  Claude loads a skill through its `Skill` tool, never a read, so a Claude load used to leave no row.
@@ -675,7 +694,7 @@ still count through the two marks; and only the hosts that classify a read in pr
675
694
  here, so the count is a floor, not a census. Which host records what, since this store is the
676
695
  report's only source: **omp** (the extension's filter lets the read through,
677
696
  `hosts/omp/tezgah-hook.ts.in:257-264`, and the hook classifies it, `hosts/omp/hook.py::classify`) and
678
- **opencode** (the plugin classifies it, `hosts/opencode/plugins/tezgah.js:2227-2242`) record the mark
697
+ **opencode** (the plugin classifies it, `hosts/opencode/plugins/tezgah.js:2256-2272`) record the mark
679
698
  or `skill:<name>` for every shipped skill, in either form; **Claude** sees a read, but only in its
680
699
  transcript, which feeds the status line and writes no row here (`statusline.py::claude_used`), so a Claude
681
700
  session reads in this report as one that opened nothing - marks included; **codex**, **cursor** and
@@ -792,7 +811,7 @@ empty stand-in for the result body its bridge never sends, so a subagent's repor
792
811
  cannot import the core in process and mirrors the control in JavaScript instead — the channel on the
793
812
  call's own row, the label and the taint notice in front of the result the hook is handed, including
794
813
  the `external` row an MCP answer or a fetched page earns (`untrustedSource`
795
- `hosts/opencode/plugins/tezgah.js:1942`, `labelResult` `:1993`, with the tier's argv reader
814
+ `hosts/opencode/plugins/tezgah.js:1971`, `labelResult` `:2022`, with the tier's argv reader
796
815
  `tierRead` at `:1902`). The two halves are pinned against each other over a shared corpus, so neither
797
816
  can move without failing the other's test (`tests/test_opencode_plugin.py::OpenCodePlugin.test_the_classifier_agrees_with_the_python_half_on_a_shared_corpus`). One difference is deliberate:
798
817
  opencode's plugin writes that `external` row itself and carries the channel alone, since the UI rule
@@ -875,7 +894,7 @@ disagree with the number it is drawn from; both are off unless the flag asks, so
875
894
  name at all - `classify` folded it into a kind - so an old corpus under-counts, which is the
876
895
  honest ceiling and the reason the field exists; every row written since carries it, because both
877
896
  writers write it (`hooks/tezgah_integrity.py::note_tool`, and opencode's plugin
878
- `hosts/opencode/plugins/tezgah.js:1253-1264` - before that second one did, an opencode work row was
897
+ `hosts/opencode/plugins/tezgah.js:1282-1293` - before that second one did, an opencode work row was
879
898
  the other half of this under-count, with its name unrecoverable in the command `detail`). A read
880
899
  tool is not in it either: reads record no row by design.
881
900
  - **The shipped programs** — `programs`, the `bin/` programs a command row really ran, read with the
@@ -21,8 +21,8 @@ sourced to WAI-ARIA APG and WCAG 2.2.
21
21
  It is reached the same way `product-analysis` is: the `product` task class arms the
22
22
  rule (`hooks/tezgah_context.py::PROMPT_HINTS`), whose coherence paragraph
23
23
  (`hooks/tezgah_policy.py::CORE`) names the feature unit and the matrices, and
24
- `skills/product-analysis/SKILL.md:74` runs the coherence pass before its axes.
25
- `skills/tezgah-contract/SKILL.md:738-750` carries the long form for a session that
24
+ `skills/product-analysis/SKILL.md:78` runs the coherence pass before its axes.
25
+ `skills/tezgah-contract/SKILL.md:743-755` carries the long form for a session that
26
26
  reads the contract.
27
27
 
28
28
  The unit is the feature, not the screen, and every interface element and every data
package/docs/gate.md CHANGED
@@ -8,7 +8,10 @@ report, and for the session that has just met a refusal in its transcript. [arch
8
8
 
9
9
  One function decides every refusal: `decision(tool, inp, cwd, session_id)` returns a reason string or `None`, and nothing else
10
10
  (`hooks/tezgah_gate.py::decision`). It answers only inside a tezgah [root](glossary.md#root): outside one `root_for` returns nothing and every call passes
11
- (`hooks/tezgah_gate.py::decision`). The `pretooluse-off` kill switch drops the whole gate (`hooks/tezgah_gate.py::decision`). `decision` binds the session first.
11
+ (`hooks/tezgah_gate.py::decision`). A repository that commits `tezgah.owner` with `harness: excluded` is out of every root the same way. One that
12
+ says `tasks: off` keeps the root and turns off only the task rules. The record rule then holds no write to its own
13
+ plan files ([operations.md](operations.md#a-repository-that-is-not-this-harnesss)).
14
+ The `pretooluse-off` kill switch drops the whole gate (`hooks/tezgah_gate.py::decision`). `decision` binds the session first.
12
15
  It reads every switch through the session latch ([contract.md](contract.md#how-a-rule-is-disarmed)).
13
16
 
14
17
  Each host's pre-tool hook calls it and wraps the string in that host's own deny envelope — opencode's is its `tool.execute.before`, which throws
@@ -34,7 +37,7 @@ writes stays under `~/.cache/tezgah/replay`. The corpus, the exclusions and the
34
37
  |---|---|---|
35
38
  | claude, dsh | `hooks/projects-pretooluse.py::main` (`hosts/dsh/hooks.json:13-14`) | `hookSpecificOutput.permissionDecision: "deny"` |
36
39
  | codex, cursor, omp | `hosts/codex/hook.py::main`, `hosts/cursor/hook.py::dispatch`, `hosts/omp/hook.py::handle` | that host's own envelope — [hosts.md](hosts.md) |
37
- | opencode | `hosts/opencode/plugins/tezgah.js:2429` | `new Error(deny)` thrown at `hosts/opencode/plugins/tezgah.js:2590` |
40
+ | opencode | `hosts/opencode/plugins/tezgah.js:2988` | `new Error(deny)` thrown at `hosts/opencode/plugins/tezgah.js:3152` |
38
41
 
39
42
  Every refusal is also recorded before it is returned: `_deny` appends a ledger row `deny` whose `detail` is `"<rule>: <reason, first 80 chars>"`, plus any
40
43
  `extra` (`hooks/tezgah_gate.py::_deny`). That row, not the reason wording, is where "why was this denied" is answered, and `<rule>` is the name used below.
@@ -110,7 +113,7 @@ request is refused.
110
113
 
111
114
  Trigger, shell: `--no-verify`, or `SKIP=`/`HUSKY_SKIP_HOOKS=`/`HUSKY=0`, next to a git/hook word; or a `core.hooksPath` assignment (`git -c core.hooksPath=...`, `git config core.hooksPath <dir>` with a quoted value too, `--config-env`, `GIT_CONFIG_KEY_n`/`GIT_CONFIG_PARAMETERS`) in the same command as a `git commit`/`git push` (`HOOKS_KEY`/`GIT_VALUE_OPTS`/`CONFIG_READS`/`ROUGH_WORDS` `hooks/tezgah_integrity.py::HOOKS_KEY`, `hooks/tezgah_integrity.py::GIT_VALUE_OPTS`, `hooks/tezgah_integrity.py::CONFIG_READS`, `hooks/tezgah_integrity.py::ROUGH_WORDS`, `hooks/tezgah_integrity.py::_shell_segments` reads the line word by word the way shlex does - an unquoted backtick ends a command (`hooks/tezgah_integrity.py::_unquoted_backticks`; one inside double quotes is read as data, the blind spot `mask` has) and a line shlex cannot read is read roughly rather than dropped - `hooks/tezgah_integrity.py::_hooks_redirect`; husky's standalone setup, a read or `--unset`, a hook install naming `pre-push`, and a commit message naming the key or the env var pass); or a verification command chained with `|| true`/`; true`
112
115
  (`hooks/tezgah_integrity.py::_shortcut_command`, `hooks/tezgah_integrity.py::NO_VERIFY`, `hooks/tezgah_integrity.py::SKIP_ENV`, `hooks/tezgah_integrity.py::NEUTER`, `hooks/tezgah_integrity.py::GITISH`).
113
- These shell predicates read the line through `mask()` (`hooks/tezgah_integrity.py::mask`), which blanks quotes and comments the way bash reads them. A URL's `//`, a word's `#`, a `/* */` glob pair and `'x\'` are words there, so they do not hide the command after them. The word reader takes a `$'...'` as one word and a `$( )` or backtick body as a command of its own (`hooks/tezgah_integrity.py::_for_shlex`). Trigger, edit/write: a skip marker newly
116
+ These shell predicates read the line through `mask()` (`hooks/tezgah_integrity.py::mask`), which blanks quotes and comments the way bash reads them. A URL's `//`, a word's `#`, a `/* */` glob pair and `'x\'` are words there, so they do not hide the command after them. The word reader takes a `$'...'` as one word and a `$( )` or backtick body as a command of its own (`hooks/tezgah_integrity.py::_for_shlex`). Every shell reader asks one rule for a comment and a line continuation (`hooks/tezgah_integrity.py::_opens_comment`, `hooks/tezgah_integrity.py::CONTINUATION`). A `#` opens a comment only at a word's start, so `x\ #`, `x\<newline>#` and `x\r#` hide nothing. A `)` that closes a substitution or an array is no word end either (`$(:)#`, `<(:)#`, `x=(a)#`, `hooks/tezgah_integrity.py::_kept`). A subshell's `(true)#` does open a comment. The readers drop a backslash-newline where bash drops it, so `-de\<newline>lete` reads as `-delete`. `mask()` moves it to its word's start, so its rules read `tr\<newline>ue` as `true` and `|\<newline>|` as `||`. A rule that slices the raw line reads it at the same offsets (`hooks/tezgah_integrity.py::joined`). The opencode mirror asks its port, `opensComment`. Trigger, edit/write: a skip marker newly
114
117
  introduced into a test file — the path must match `tests?/`, `test_*`, `*_test`, `*.test.*` (`hooks/tezgah_integrity.py::TEST_PATH`), the marker must survive `mask_source()` so one
115
118
  inside a string or comment does not count, and `_added` compares against the file's own text on disk for a `Write` (`hooks/tezgah_integrity.py::_added`, `hooks/tezgah_integrity.py::SKIP_TEST`). Every write dialect is read
116
119
  through one reader (`hooks/tezgah_integrity.py::write_texts`, over `hooks/tezgah_taste.py::edit_text`): `new_string`/`newString`, `new_str`, `content`/`file_text`, `edits[]` and an `apply_patch` body, which is split per `*** Update File:`/`*** Add File:` header so the test-path gate and the count run per file (`hooks/tezgah_integrity.py::PATCH_FILE`). Told:
@@ -130,7 +133,7 @@ Passes: a line that opens with `set -o pipefail` (`hooks/tezgah_integrity.py::PI
130
133
  (`verify_ok`/`verify_fail`, [evidence.md](evidence.md)); a redirect to a file; a pipe of anything that is not a check (`git log | head`). The
131
134
  remedy is one sentence, `hooks/tezgah_integrity.py::PIPED_REMEDY`, which the always-on core and the contract skill quote too. Told: keep the check last with its output in a file, then read the file in a separate call, or open the line with `set -o pipefail;`. A `; tail` on the same line hands the status to `tail`. The refusal names the check as it was typed. Standing, under `verify-off`
132
135
  (`hooks/tezgah_gate.py::decision`). opencode asks the core for this rule on any shell line that pipes a check
133
- (`hosts/opencode/plugins/tezgah.js:2515-2519`) and records such a line as `verify` when a pipe or a later command owns its status (`statusHidden`, `hosts/opencode/plugins/tezgah.js:445`).
136
+ (`hosts/opencode/plugins/tezgah.js:3069-3073`) and records such a line as `verify` when a pipe or a later command owns its status (`statusHidden`, `hosts/opencode/plugins/tezgah.js:505`).
134
137
 
135
138
  ### Attribution — an AI/model credit on its way into an artifact
136
139
 
@@ -141,12 +144,13 @@ containing a line that *starts* with a credit (`hooks/tezgah_gate.py::ATTRIB_LIN
141
144
  as author is not (`hooks/tezgah_gate.py::ATTRIB_DENY`). Standing. The line anchor is why prose that merely names the banned forms passes (`hooks/tezgah_gate.py::_CREDIT`).
142
145
  The same twin as the shortcut rule's: a credit a heredoc writes into a file is refused from the body (`hooks/tezgah_gate.py::decision`), and no command has to be
143
146
  a `git`/`gh` write for it to be this rule's. An MCP `write` or `publish` call meets `ATTRIB_LINE` over its payload text ([MCP](#mcp-a-servers-effect-tool)).
147
+ A folded `.tezgah` (`hooks/tezgah_research.py::folded`) makes `tezgah-research commit` write the project's own history with a message the gate never reads in the command. The CLI runs it through this rule's reader, `hooks/tezgah_gate.py::ATTRIB`, and the language rule's (`hooks/tezgah_lang.py::refusal`, under `lang-off`) before committing. It prints the same refusal, with exit 2 and nothing committed (`bin/tezgah-research::message_refusal`).
144
148
 
145
149
  ### Language — an identifier or message that is not English
146
150
 
147
- Trigger, shell: a command that would create an identifier - `git checkout -b`/`git switch -c`, `git branch` with a new name, a commit subject (`git commit -m`/`--message`/`-F`), or a `gh pr|issue create --title` (the language section `hooks/tezgah_gate.py:355-468`, `hooks/tezgah_gate.py::created_texts`; the text is read from the raw command, because `mask()` blanks quoted strings and a commit subject is one) - whose name or subject is **not English**: a letter outside ASCII anywhere (`hooks/tezgah_lang.py::non_english` - a predicate rather than one language's letter list, so Russian, Greek, Arabic, Chinese and accented Latin hit it exactly as Turkish does) or an ASCII-folded Turkish word from the curated list (`hooks/tezgah_lang.py::ENGLISH`, wi…
151
+ Trigger, shell: a command that would create an identifier - `git checkout -b`/`git switch -c`, `git branch` with a new name, a commit subject (`git commit -m`/`--message`/`-F`), or a `gh pr|issue create --title` (the language section `hooks/tezgah_gate.py::lang_reason`, `hooks/tezgah_gate.py::BRANCH_NEW`, `hooks/tezgah_gate.py::COMMIT_MSG`, `hooks/tezgah_gate.py::GH_NEW`, `hooks/tezgah_gate.py::created_texts`; the text is read from the raw command, because `mask()` blanks quoted strings and a commit subject is one) - whose name or subject is **not English**: a letter outside ASCII anywhere (`hooks/tezgah_lang.py::non_english` - a predicate rather than one language's letter list, so Russian, Greek, Arabic, Chinese and accented Latin hit it exactly as Turkish does) or an ASCII-folded Turkish word from the curated list (`hooks/tezgah_lang.py::ENGLISH`, wi…
148
152
 
149
- The rule is a **heuristic** and its own text says so: a word list is not a language detector, so it cannot tell a proper noun or a product name in another language from a word that ought to be English, and a listed word may be the user's own term. A command that only names the words - `echo`, `grep`, `git log --grep` - creates nothing and passes. An identifier outlives the session that typed it, which is the reason the rule exists at all: `plan/004-admin-durum-onarimi` is in a public history from the moment it exists. On **opencode** the rule is not ported: the plugin asks the core for it through `bin/tezgah-gate check`, one spawn for a command its pre-test reads as identifier-creating (`IDENT_CMD` `hosts/opencode/plugins/tezgah.js:585`, the call site `hosts/opencode/plugins/tezgah.js:2515-2519`).
153
+ The rule is a **heuristic** and its own text says so: a word list is not a language detector, so it cannot tell a proper noun or a product name in another language from a word that ought to be English, and a listed word may be the user's own term. A command that only names the words - `echo`, `grep`, `git log --grep` - creates nothing and passes. An identifier outlives the session that typed it, which is the reason the rule exists at all: `plan/004-admin-durum-onarimi` is in a public history from the moment it exists. On **opencode** the rule is not ported: the plugin asks the core for it through `bin/tezgah-gate check`, one spawn for a command its pre-test reads as identifier-creating (`IDENT_CMD` `hosts/opencode/plugins/tezgah.js:632`, the call site `hosts/opencode/plugins/tezgah.js:3069-3073`).
150
154
 
151
155
  Off: `lang-off`, the rule's own switch (`hooks/tezgah_gate.py::decision`), and `pretooluse-off` drops it with the whole gate.
152
156
 
@@ -201,7 +205,7 @@ checkpoint that is a plain sha (the boundary is already real), a `pending` with
201
205
 
202
206
  ### Workspace — tezgah state outside `.tezgah/`
203
207
 
204
- Trigger: a write tool, or a shell redirect/`tee` (`write_paths`), whose target relative to the repo root starts with `plans/`, `research/` or `analysis/` while the project tracks no file under that directory (`workspace_reason`, `hooks/tezgah_gate.py`). The refusal names `.tezgah/<kind>/` as the place to write. A directory the project already tracks is its own and passes. `mkdir` and positional shell targets (`cp`, `mv`) are not read - the same ceiling as `write_paths`. Off: `workspace-off`.
208
+ Trigger: a write tool, or a shell redirect/`tee` (`write_paths`), whose target relative to the repo root starts with `plans/`, `research/` or `analysis/` while the project tracks no file under that directory (`workspace_reason`, `hooks/tezgah_gate.py`). The refusal names `.tezgah/<kind>/` as the place to write. It also names the commit form for the workspace's shape (`hooks/tezgah_research.py::folded`). An own repository gets `git -C .tezgah` (`hooks/tezgah_gate.py::WORKSPACE_OWN`). A folded one the project tracks gets its own `git add`/`git commit` (`hooks/tezgah_gate.py::WORKSPACE_FOLDED`). A directory the project already tracks is its own and passes. `mkdir` and positional shell targets (`cp`, `mv`) are not read - the same ceiling as `write_paths`. Off: `workspace-off`.
205
209
 
206
210
  ### Secret — a credential on its way into a file
207
211
 
@@ -250,9 +254,10 @@ nothing, and Orca's `r1z4x/<slug>` branches bind by declaration. The task rule h
250
254
  declares. The count folds the turn's own write rows (`hooks/tezgah_integrity.py::turn_rows`) together with the files the call in hand names, so it needs no state of its own, and it counts DISTINCT
251
255
  paths - a turn that rewrites one file three times is still one file's work. A product path is any path in the checkout, whatever the project's layout (`apps/`, `packages/`, `.maestro/` count as
252
256
  `hooks/` does). Tezgah's and git's own state does not count: `.tezgah/`, `.codegraph/` and `.git/` (`hooks/tezgah_gate.py::PLAN_SKIP`). Neither does a host's generated `agents/` set
253
- (`hooks/tezgah_gate.py::PLAN_AGENT_HOSTS`). A path outside any git repository never counts. Told: the branch it read, how many files the turn has written, and
254
- the command that opens a plan - the `plan-add` skill, `/tezgah:plan-add <description>` (`hooks/tezgah_gate.py::PLAN_DENY`). It also names the bind route: `tezgah-task start NNN --phase P --branch
255
- <branch>` writes the plan's `branch:` (`bin/tezgah-task::cmd_start`). The record rule refuses a hand edit of a phased record. Standing: only changing the tree's state changes it - the
257
+ (`hooks/tezgah_gate.py::PLAN_AGENT_HOSTS`). A path outside any git repository never counts. Nor does a path that names no file on this disk: a URI such as `agent://<id>` or `local://x.md`, or a `file://` URL naming another host. A local `file://` URL counts as the file it names, in the checkout that holds that file. The writer stores that file as the row's `target`, and any other URI's own spelling. The race guard compares that spelling, and this rule skips it (`hooks/tezgah_integrity.py::file_url_path`). Told: the branch it read, how many files the turn has written, and
258
+ the command that opens a plan - the `plan-add` skill, `/tezgah:plan-add <description>` (`hooks/tezgah_gate.py::PLAN_DENY`). Off the trunk it also names the bind route: `tezgah-task start NNN
259
+ --phase P --branch <branch>` writes the plan's `branch:` (`hooks/tezgah_gate.py::PLAN_BIND`, `bin/tezgah-task::cmd_start`). On `main` or `master` it names only the `plan/NNN-slug` route or
260
+ another branch an open plan declares (`hooks/tezgah_gate.py::PLAN_BIND_TRUNK`). `cmd_start` refuses `--branch main` or `--branch master` too. The record rule refuses a hand edit of a phased record. Standing: only changing the tree's state changes it - the
256
261
  work moves to the `plan/NNN-slug` branch the skill creates or to a bound branch (a one- or two-file fix is free either way), or the repository carries a `.no-plan-gate` mark (the shape of
257
262
  `.no-graph` and `.no-lessons`). It passes while a merge or rebase is in progress (`MERGE_HEAD`, `rebase-merge/` or `rebase-apply/` in the checkout's gitdir, `hooks/tezgah_gate.py::_merging`):
258
263
  resolving conflicts is not new work. It passes wherever the question cannot be answered: no session or ledger, a directory that is not a git repository, and a detached HEAD with no branch to name.
@@ -301,7 +306,11 @@ Codex and Cursor read it with their PostToolUse result (`hosts/codex/hook.py`, `
301
306
 
302
307
  Trigger: 25 work rows (`hooks/tezgah_gate.py::DRIFT_STEPS`) in the current user turn and an effectful call — a write tool, or a git/gh artifact command (`effectful`
303
308
  `hooks/tezgah_gate.py::effectful`). An MCP call of any verb class counts as an effectful call too. Told: the standing constraints re-stated, or the delta since the turn began; "re-issue this call unchanged and carry on" (`hooks/tezgah_gate.py::DRIFT_DENY`,
304
- `hooks/tezgah_gate.py::drift_reason`). A refusal, last in `decision` after every other rule, and its only delivery: no host's PostToolUse side carries it, and opencode gets it from the core through `bin/tezgah-gate` on its write path. Once per turn: the `drift` mark is written *before* the refusal, so the identical call passes on the next attempt, and the count behind it is the turn's own — a bounded read (`hooks/tezgah_gate.py::DRIFT_TAIL`) falls back to the turn's own start (`hooks/tezgah_integrity.py::turn_rows`) when the turn outgrew the window. Governed by `reminder-off`, not `verify-off` (`hooks/tezgah_gate.py::drift_reason`).
309
+ `hooks/tezgah_gate.py::drift_reason`). A refusal, last in `decision` after every other built-in rule. Only a repository's own rule runs after it ([Adding a rule](#a-repositorys-own-rule)). Its only delivery: no host's PostToolUse side carries it, and opencode gets it from the core through `bin/tezgah-gate` on its write path. Once per turn: the `drift` mark is written *before* the refusal, so the identical call passes on the next attempt. The count behind it is the turn's own — a bounded read (`hooks/tezgah_gate.py::DRIFT_TAIL`) falls back to the turn's own start (`hooks/tezgah_integrity.py::turn_rows`) when the turn outgrew the window. Governed by `reminder-off`, not `verify-off` (`hooks/tezgah_gate.py::drift_reason`).
310
+
311
+ ### Repo-rule — a repository's own `.tezgah/gate.py` refuses the call
312
+
313
+ Trigger: the repository's rule file, in the git index, answers `{"deny": "<reason>"}` for this call (`hooks/tezgah_gate.py::repo_rule_reason`). Told: that reason, capped at 600 characters, inside a label naming it repository-supplied (`hooks/tezgah_gate.py::REPO_RULE_DENY`). Last in `decision`, after every built-in refusal. A timeout, a non-zero exit or malformed output allows. Off with `pretooluse-off`, or `TEZGAH_REPO_RULE=0` in the environment. The contract is [A repository's own rule](#a-repositorys-own-rule).
305
314
 
306
315
  ### Ask — an ask-tool question with no recommended option
307
316
 
@@ -328,7 +337,7 @@ Read this before filing a security-ish issue; each is a decision, not an oversig
328
337
  A grant the user writes in chat ("bana sormadan pushla") lifts the ask for its class. Outward commands still run with no refusal.
329
338
  - A write inside the root after a fetch: left to the taint notice that `hooks/tezgah_untrusted.py` rides the first effect with, because it is recoverable from
330
339
  the snapshot.
331
- - `grep -A 3 foo`: a flag with its own value shifts the token, so the search passes unnudged (`hooks/tezgah_gate.py:166-167`).
340
+ - `grep -A 3 foo`: a flag with its own value shifts the token, so the search passes unnudged (`hooks/tezgah_gate.py::BASH_SEARCH`).
332
341
  - A foreign `apply_patch` write: the PostToolUse writer records no path for that row (`hooks/tezgah_gate.py::write_paths`); and the guard skips a row an older writer left with no
333
342
  `target`, because that row names no file (`hooks/tezgah_integrity.py::writers_elsewhere`).
334
343
  - Which rule the user meant when a turn drifts: "a guess about intent wearing a check's clothes" (`hooks/tezgah_gate.py::drift_reason`).
@@ -373,17 +382,17 @@ widen a list a regex already covers.
373
382
  ## The mirror: the opencode plugin
374
383
 
375
384
  opencode cannot run Python hooks, so `hosts/opencode/plugins/tezgah.js` is an independent JavaScript re-implementation of the same rules, dispatched from
376
- `tool.execute.before` (hosts/opencode/plugins/tezgah.js:2429, exported `hosts/opencode/plugins/tezgah.js:2365`) in the gate's own order (`hosts/opencode/plugins/tezgah.js:2429-2591`); its shortcut constants restate the same regexes (`NEUTER` `hosts/opencode/plugins/tezgah.js:270`,
377
- `SKIP_ENV` hosts/opencode/plugins/tezgah.js:271, `NO_VERIFY` hosts/opencode/plugins/tezgah.js:272, `GITISH` hosts/opencode/plugins/tezgah.js:273, `SKIP_TEST` hosts/opencode/plugins/tezgah.js:515). What keeps the two halves honest is a test, not a shared module:
385
+ `tool.execute.before` (hosts/opencode/plugins/tezgah.js:2988, exported `hosts/opencode/plugins/tezgah.js:2936`) in the gate's own order (`hosts/opencode/plugins/tezgah.js:2988-3153`); its shortcut constants restate the same regexes (`NEUTER` `hosts/opencode/plugins/tezgah.js:314`,
386
+ `SKIP_ENV` hosts/opencode/plugins/tezgah.js:315, `NO_VERIFY` hosts/opencode/plugins/tezgah.js:316, `GITISH` hosts/opencode/plugins/tezgah.js:317, `SKIP_TEST` hosts/opencode/plugins/tezgah.js:575). What keeps the two halves honest is a test, not a shared module:
378
387
  `tests/test_opencode_plugin.py` drives the plugin's hooks through a node harness with a throwaway HOME, and imports the Python `tezgah_integrity.call_id` so a
379
- separator or canonical-form drift in the action id fails there instead of silently in a session (`tests/test_opencode_plugin.py:1-7`, `tests/test_opencode_plugin.py:24-27`, `tests/test_opencode_plugin.py::OpenCodePlugin.test_the_id_is_the_hash_the_python_writer_computes`).
380
-
381
- The shell rule kinds mirrored last are each pinned in both suites: the shell's write body (`SHELL_WRITE` `hosts/opencode/plugins/tezgah.js:979`,
382
- `heredocBodies` `hosts/opencode/plugins/tezgah.js:985`, `shellWriteBody` `hosts/opencode/plugins/tezgah.js:1018`, the shortcut and attribution twins at
383
- `hosts/opencode/plugins/tezgah.js:2481-2485` and `hosts/opencode/plugins/tezgah.js:1670`, the credential twin at `hosts/opencode/plugins/tezgah.js:1630-1634`) and the
384
- ordering obligation (`COMMIT_CMD` `hosts/opencode/plugins/tezgah.js:1558`, `ORDER_DENY`
385
- `hosts/opencode/plugins/tezgah.js:1560`, `lastVerify` `hosts/opencode/plugins/tezgah.js:1571`, `orderReason` `hosts/opencode/plugins/tezgah.js:1596`, dispatched at
386
- `hosts/opencode/plugins/tezgah.js:2530-2533`). `lastVerify` folds the tail exactly as `_last_verify` does, minus the `passing_check` narrowing - this rule reads only
388
+ separator or canonical-form drift in the action id fails there instead of silently in a session (`tests/test_opencode_plugin.py:1-7`, `tests/test_opencode_plugin.py:27-30`, `tests/test_opencode_plugin.py::OpenCodePlugin.test_the_id_is_the_hash_the_python_writer_computes`).
389
+
390
+ The shell rule kinds mirrored last are each pinned in both suites: the shell's write body (`SHELL_WRITE` `hosts/opencode/plugins/tezgah.js:1039`,
391
+ `heredocBodies` `hosts/opencode/plugins/tezgah.js:1045`, `shellWriteBody` `hosts/opencode/plugins/tezgah.js:1078`, the shortcut and attribution twins at
392
+ `hosts/opencode/plugins/tezgah.js:3043-3044` and `hosts/opencode/plugins/tezgah.js:2010`, the credential twin at `hosts/opencode/plugins/tezgah.js:1970-1974`) and the
393
+ ordering obligation (`COMMIT_CMD` `hosts/opencode/plugins/tezgah.js:1899`, `ORDER_DENY`
394
+ `hosts/opencode/plugins/tezgah.js:1901`, `lastVerify` `hosts/opencode/plugins/tezgah.js:1911`, `orderReason` `hosts/opencode/plugins/tezgah.js:1936`, dispatched at
395
+ `hosts/opencode/plugins/tezgah.js:3084-3087`). `lastVerify` folds the tail exactly as `_last_verify` does, minus the `passing_check` narrowing - this rule reads only
387
396
  `fail`, and a row that narrowing would refuse reads `ok`/`ran` on both sides, so the outcome is identical.
388
397
 
389
398
  The control rule has no JavaScript copy. The plugin's `CONTROL_CMD` pre-test picks the shell lines that could touch the control plane. The plugin puts each
@@ -410,17 +419,18 @@ rule's triggers are the classes `_stop_block` returns, the four `_shape_block` h
410
419
  | `shortcut` | E7c: with the write tools refused, 3 of 25 armed runs wrote a test skip through a heredoc | an internal benchmark (block E7, not published) | `tests/test_gate.py::test_a_shell_write_that_disables_a_test_is_denied` |
411
420
  | `piped` | a real omp session: 13 checks ran piped and 3 of 6 completion claims were blocked | the Piped section above | `tests/test_gate.py::test_a_piped_check_is_refused_and_pipefail_passes` |
412
421
  | `attribution` | E7c: the same 3 of 25 runs, a credit written through a heredoc | an internal benchmark (block E7, not published) | `tests/test_gate.py::test_attribution_denies_a_credit_written_by_the_shell` |
413
- | `lang` | a plan branch was created as `plan/004-admin-durum-onarimi`, and its slug is in the public history for good | `hooks/tezgah_gate.py:355-364` | `tests/test_gate.py::test_a_turkish_branch_name_is_refused` |
414
- | `race` | two sessions on one file - a parent and its subagent, or two worktrees - landing on a stale read | `hooks/tezgah_gate.py:752-759` | `tests/test_gate.py::test_a_write_to_a_file_another_session_wrote_is_refused` |
422
+ | `lang` | a plan branch was created as `plan/004-admin-durum-onarimi`, and its slug is in the public history for good | the comment above `hooks/tezgah_gate.py::BRANCH_NEW` | `tests/test_gate.py::test_a_turkish_branch_name_is_refused` |
423
+ | `race` | two sessions on one file - a parent and its subagent, or two worktrees - landing on a stale read | the comment above `hooks/tezgah_gate.py::RACE_WINDOW_MIN` | `tests/test_gate.py::test_a_write_to_a_file_another_session_wrote_is_refused` |
415
424
  | `lease` | plan 086 wave 1: two slices wrote into the main checkout through relative paths; 24 sibling race refusals in real transcripts, all in a shared worktree, tree or record | the Lease section above | `tests/test_gate.py::test_a_sibling_slices_lease_refuses_its_file_and_frees_the_owner` |
416
425
  | `task` | E7: with the unlocking command printed, an armed arm removed or disabled the gate in 25 of 25 runs; E7b: the heredoc redirect in 3 of 25 | the Task section above (the checkpoint refusal) | `tests/test_gate.py::test_a_reading_phase_refuses_a_write_inside_the_allowlist` |
417
426
  | `secret` | E7c: the same 3 of 25 runs, a key written through a heredoc | an internal benchmark (block E7, not published) | `tests/test_gate.py::test_a_credential_written_by_a_heredoc_is_denied` |
418
- | `workspace` | sessions wrote root `plans/`, `research/` and `analysis/` (observed across several unrelated projects on one machine) | `hooks/tezgah_gate.py:1344-1348` | `tests/test_gate.py::test_untracked_root_kinds_are_refused_for_tools_and_redirects` |
419
- | `plan` | a turn wrote four product files - a hook, its tests, its docs and the changelog - straight onto `main` | `hooks/tezgah_gate.py:1624-1632` | `tests/test_gate.py::test_the_third_product_write_on_main_is_refused` |
427
+ | `workspace` | sessions wrote root `plans/`, `research/` and `analysis/` (observed across several unrelated projects on one machine) | the comment above `hooks/tezgah_gate.py::WORKSPACE_KINDS` | `tests/test_gate.py::test_untracked_root_kinds_are_refused_for_tools_and_redirects` |
428
+ | `plan` | a turn wrote four product files - a hook, its tests, its docs and the changelog - straight onto `main` | the comment above `hooks/tezgah_gate.py::PLAN_TRUNKS` | `tests/test_gate.py::test_the_third_product_write_on_main_is_refused` |
420
429
  | `order` | FAVA: the shape found in 90% of real agent-instruction projects ("do not commit before running the tests") | the Ordering section above | `tests/test_gate.py::test_a_commit_is_refused_while_the_newest_check_failed` |
421
430
  | `loop` | designed | the turn's own repeated failure; no incident recorded | `tests/test_gate.py::test_an_identical_failed_call_is_denied_after_the_ceiling` |
422
431
  | `retry` | designed | the session ceiling over the same guard; no incident recorded | `tests/test_gate.py::test_a_fourth_identical_call_is_refused_whatever_the_outcome` |
423
- | `drift` | an internal plan's flip rule on the 2026-09-20 move to a result-channel notice: at 27 sessions the blocked-claim rate in turns under 25 work rows read 112/140 = 0.8000, against 59/142 = 0.4155 before | `hooks/tezgah_gate.py:1517-1529` | `tests/test_gate.py::test_a_long_turn_restates_the_constraints_before_a_write` |
432
+ | `drift` | an internal plan's flip rule on the 2026-09-20 move to a result-channel notice: at 27 sessions the blocked-claim rate in turns under 25 work rows read 112/140 = 0.8000, against 59/142 = 0.4155 before | an internal plan (not published) | `tests/test_gate.py::test_a_long_turn_restates_the_constraints_before_a_write` |
433
+ | `repo-rule` | designed | a repository's own refusal through the extension seam (plan 124), no incident recorded | `tests/test_gate.py::test_a_repo_rule_denies_its_call_and_allows_the_rest` |
424
434
  | `evidence tampered` | a terminated garbage line made `_parse` raise, and the guard then failed the Stop rule open for the turn; corrupting a `verify_fail` row was an allow route. A `verify_ok` appended with `python3 -c` licensed a claim (security-03), so a pass with no `began` row is an orphan (`hooks/tezgah_integrity.py::_pair`) | `hooks/tezgah_integrity.py::_parse` | `tests/test_integrity.py::test_a_damaged_ledger_blocks_a_done_claim_as_evidence_tampered` |
425
435
  | `check failed` | designed | the newest check failing is its own class; no incident recorded | `tests/test_integrity.py::test_failed_check_blocks` |
426
436
  | `partial failure` | designed | a failure the turn never resolved; no incident recorded | `tests/test_integrity.py::test_an_unresolved_failure_blocks_even_after_an_earlier_pass` |
@@ -436,12 +446,12 @@ rule's triggers are the classes `_stop_block` returns, the four `_shape_block` h
436
446
  | `placating opener` | designed | output rule 10 read at the Stop event; no incident recorded | `tests/test_integrity.py::test_sycophantic_opener_blocks` |
437
447
  | `forbidden closer` | designed | output rule 10 read at the Stop event; no incident recorded | `tests/test_integrity.py::test_a_closer_from_the_skills_own_list_blocks` |
438
448
  | `list cap` | designed | output rule 8 read at the Stop event; no incident recorded | `tests/test_integrity.py::test_a_list_over_the_cap_blocks_with_its_size` |
439
- | `reply language` | measured 2026-09-19: the 161 final replies the claim vocabulary was read off | `hooks/tezgah_integrity.py:255-262` | `tests/test_integrity.py::test_english_prose_blocks_and_names_the_language` |
449
+ | `reply language` | measured 2026-09-19: the 161 final replies the claim vocabulary was read off | `hooks/tezgah_integrity.py::DONE` | `tests/test_integrity.py::test_english_prose_blocks_and_names_the_language` |
440
450
 
441
451
  ## Adding a rule
442
452
 
443
453
  1. Write the check inside `decision` (`hooks/tezgah_gate.py::decision`). A rule is a function returning a `str` reason or `None`; keep an argument-shaped rule
444
- above the repeat guards (`hooks/tezgah_gate.py::decision`) — the drift refusal stays last, below every other rule — and put its constants beside its own section.
454
+ above the repeat guards (`hooks/tezgah_gate.py::decision`) — the drift refusal stays last among the built-in rules, followed only by the repo rule below — and put its constants beside its own section.
445
455
  A citation into this file names its symbol, so moving code inside it shifts nothing. Renaming or removing a cited symbol does, and `bin/tezgah-docs --citations`
446
456
  flags it - re-run it in the same pass as the suite and re-anchor what it flags.
447
457
  2. Return through `_deny(session_id, "<rule>", reason, tool, inp, base)` so the ledger counts the refusal (`hooks/tezgah_gate.py::_deny`); gate it on the kill switch it belongs
@@ -457,12 +467,25 @@ rule's triggers are the classes `_stop_block` returns, the four `_shape_block` h
457
467
  A host gets the call only when its own matcher routes that name (`hooks/hooks.json`, `hosts/dsh/hooks.json`, `hosts/codex/hooks.json`, `hosts/cursor/hooks.json`,
458
468
  omp's `GATED` list). A cell that disagrees with the core fails the suite. The corpus may name it a ceiling, with the plan that closes it. A ceiling that agrees fails too.
459
469
 
470
+ ### A repository's own rule
471
+
472
+ A repository adds a refusal without editing the harness: it commits a Python file at `<repo>/.tezgah/gate.py`, run with the gate's own interpreter (`hooks/tezgah_gate.py::repo_rule_reason`).
473
+ The gate finds it with the status line's walk - nearest above the call's cwd, at most `MAX_WALK` levels, never above the configured root (`hooks/tezgah_gate.py::repo_rule_path`). A repo without one pays one `isfile` per level and no fork. Both it and the manifest are control plane (`hooks/tezgah_gate.py::_target_label`): the session stages them and the user's own terminal owns them.
474
+ The file runs only when it is in the git index of the repository that holds its directory - the project's, or the workspace's own `.tezgah` repository (`git ls-files --error-unmatch`, `hooks/tezgah_gate.py::_indexed`). An uncommitted drop is inert, and staging it is enough.
475
+ The file runs as a bounded child in the repo root, with one JSON object on stdin: `{"api": 1, "event": "pretool", "cwd", "repo_root", "session_id", "tool", "input"}` (the extension envelope, `hooks/tezgah_extension.py::call_envelope`, plus the call).
476
+ It answers `{"deny": "<reason>"}` on stdout to refuse, and nothing to allow. The reason reaches the agent cut to 600 characters (`hooks/tezgah_gate.py::REPO_RULE_CAP`). It opens with `Repository-supplied rule:`. A line then says the text is the repository's data, not tezgah's instruction (`hooks/tezgah_gate.py::REPO_RULE_DENY`). The labelled text leaves a `deny` row under `repo-rule`.
477
+ Fail-open: a non-zero exit, a timeout (1000 ms, `hooks/tezgah_extension.py::DEFAULT_TIMEOUT_MS`) and malformed output allow. The rule runs after every built-in refusal, so a built-in one wins and the repo rule only adds. `pretooluse-off` drops it with the whole gate. `TEZGAH_REPO_RULE=0` in the hook's environment skips it alone, before any fork (`hooks/tezgah_gate.py::REPO_RULE_VALVE`).
478
+ The dry check (`tezgah-gate check`) runs it too, since it is part of `decision`. What the file can do is in [SECURITY.md](../SECURITY.md#threat-model).
479
+ opencode runs the same file, with the same envelope, index check, valve, cap and label (`hosts/opencode/plugins/tezgah.js`, `repoRuleReason`). It does so when the core was not asked.
480
+ Its interpreter is the plugin's `pythonBin()`, not the gate's `sys.executable`. That is `TEZGAH_PYTHON`, else the first of `python3`, `python`, `py` on PATH.
481
+ The opencode classifier does not read the manifest's `checks`, so a declared check records there as a plain run. That is a lost credit, never a false one.
482
+
460
483
  ## Source of truth
461
484
 
462
- - `hooks/tezgah_gate.py` — `hooks/tezgah_gate.py::decision`; every rule constant and refusal text `hooks/tezgah_gate.py:165-2434`; `attribution`/`attribution_edit` `hooks/tezgah_gate.py::attribution`, `hooks/tezgah_gate.py::attribution_edit`; `explored`
485
+ - `hooks/tezgah_gate.py` — `hooks/tezgah_gate.py::decision`; every rule constant and refusal text `hooks/tezgah_gate.py::DENY_RULES`, `hooks/tezgah_gate.py::SECRET_DENY`, `hooks/tezgah_gate.py::SECRET_EDIT_DENY`, `hooks/tezgah_gate.py::SECRET_ADD_DENY`, `hooks/tezgah_gate.py::MCP_SECRET_DENY`, `hooks/tezgah_gate.py::EXPLORE_DENY`, `hooks/tezgah_gate.py::ATTRIB_DENY`, `hooks/tezgah_gate.py::RACE_DENY`, `hooks/tezgah_gate.py::RACE_WHO`, `hooks/tezgah_gate.py::LEASE_DENY`, `hooks/tezgah_gate.py::MAIN_CHECKOUT_DENY`, `hooks/tezgah_gate.py::TASK_PHASE_DENY`, `hooks/tezgah_gate.py::TASK_SCOPE_DENY`, `hooks/tezgah_gate.py::TASK_SCOPE_OUTSIDE`, `hooks/tezgah_gate.py::TASK_RECORD_DENY`, `hooks/tezgah_gate.py::TASK_SHELL_DENY`, `hooks/tezgah_gate.py::CHECKPOINT_DENY`, `hooks/tezgah_gate.py::WORKSPACE_DENY`, `hooks/tezgah_gate.py::ORDER_DENY`, `hooks/tezgah_gate.py::DRIFT_DENY`, `hooks/tezgah_gate.py::CONTROL_DENY`; `attribution`/`attribution_edit` `hooks/tezgah_gate.py::attribution`, `hooks/tezgah_gate.py::attribution_edit`; `explored`
463
486
  `hooks/tezgah_gate.py::explored`; `hooks/tezgah_gate.py::searched_symbol`, `hooks/tezgah_gate.py::index_slug`, `hooks/tezgah_gate.py::first_nudge`, `hooks/tezgah_gate.py::nudge_reason`, `hooks/tezgah_gate.py::graph_advice`; `hooks/tezgah_gate.py::LOOP_ATTEMPTS`, `hooks/tezgah_gate.py::loop_reason`,
464
487
  `hooks/tezgah_gate.py::RETRY_CEILING`, `hooks/tezgah_gate.py::retry_reason`; `hooks/tezgah_gate.py::secret_command`, `hooks/tezgah_gate.py::race_reason`,
465
- `hooks/tezgah_gate.py::drift_reason`, `hooks/tezgah_gate.py::effectful`, `hooks/tezgah_gate.py::_deny`; the plan rule's own section `hooks/tezgah_gate.py:1624-1821` — `hooks/tezgah_gate.py::plan_reason`, `hooks/tezgah_gate.py::_branch`, `hooks/tezgah_gate.py::_checkout`, `hooks/tezgah_gate.py::_product`, `hooks/tezgah_gate.py::PLAN_DENY`; `hooks/tezgah_gate.py::write_paths`, `hooks/tezgah_gate.py::shell_target`, `hooks/tezgah_gate.py::SHELL_AS_WRITE`; the `capture` call `hooks/tezgah_gate.py::decision` (a write tool's target, and a shell write's)
488
+ `hooks/tezgah_gate.py::drift_reason`, `hooks/tezgah_gate.py::effectful`, `hooks/tezgah_gate.py::_deny`; the plan rule's own section `hooks/tezgah_gate.py::PLAN_TRUNKS`, `hooks/tezgah_gate.py::PLAN_SKIP`, `hooks/tezgah_gate.py::PLAN_AGENT_HOSTS`, `hooks/tezgah_gate.py::PLAN_WRITES`, `hooks/tezgah_gate.py::PLAN_MERGING`, `hooks/tezgah_gate.py::PLAN_BIND`, `hooks/tezgah_gate.py::PLAN_BIND_TRUNK`, `hooks/tezgah_gate.py::_gitdir`, `hooks/tezgah_gate.py::_head`, `hooks/tezgah_gate.py::_merging`, `hooks/tezgah_gate.py::_unplanned` — `hooks/tezgah_gate.py::plan_reason`, `hooks/tezgah_gate.py::_branch`, `hooks/tezgah_gate.py::_checkout`, `hooks/tezgah_gate.py::_product`, `hooks/tezgah_gate.py::PLAN_DENY`; `hooks/tezgah_gate.py::write_paths`, `hooks/tezgah_gate.py::shell_target`, `hooks/tezgah_gate.py::SHELL_AS_WRITE`; the `capture` call `hooks/tezgah_gate.py::decision` (a write tool's target, and a shell write's)
466
489
  - `hooks/projects-pretooluse.py` — the Claude and dsh envelope; `hooks/tezgah_paths.py` — `off`, `root_for`, `cache_dir`
467
490
  - `hooks/tezgah_integrity.py` — `hooks/tezgah_integrity.py::WRITE_TOOLS`, `hooks/tezgah_integrity.py::BASH_TOOLS`; `NEUTER`/`SKIP_ENV`/`NO_VERIFY`/`GITISH` `hooks/tezgah_integrity.py::NEUTER`, `hooks/tezgah_integrity.py::SKIP_ENV`, `hooks/tezgah_integrity.py::NO_VERIFY`, `hooks/tezgah_integrity.py::GITISH`; `HOOKS_KEY`/`GIT_VALUE_OPTS`/`CONFIG_READS`/`ROUGH_WORDS` `hooks/tezgah_integrity.py::HOOKS_KEY`, `hooks/tezgah_integrity.py::GIT_VALUE_OPTS`, `hooks/tezgah_integrity.py::CONFIG_READS`, `hooks/tezgah_integrity.py::ROUGH_WORDS`; `hooks/tezgah_integrity.py::SKIP_TEST`; `TEST_PATH`
468
491
  `hooks/tezgah_integrity.py::TEST_PATH`; `hooks/tezgah_integrity.py::call_id`; `hooks/tezgah_integrity.py::_path`, `hooks/tezgah_integrity.py::note`, `hooks/tezgah_integrity.py::events`, `hooks/tezgah_integrity.py::writers_elsewhere`, `hooks/tezgah_integrity.py::mask`, `hooks/tezgah_integrity.py::shortcut_command`,
package/docs/glossary.md CHANGED
@@ -19,7 +19,7 @@ The part of the contract every session pays for - the invariants plus the one-li
19
19
  The per-session check of tezgah's own hook entries against the install record. `run()` (`hooks/tezgah_attest.py::run`) reads each host's entries. It compares them with the `hook:<host>:<entry>` lines in `contract.sha256` (`bin/tezgah-setup::record_hooks`). It writes one `attest` [row](#row) and sets or clears the `drift` [mark](#mark). Not integrity: whoever can edit a hook can edit the record. A clean row is evidence, not proof.
20
20
 
21
21
  ### budget
22
- The byte ceiling one injected event may spend: `CONTEXT_BUDGET` per event with `DEFAULT_BUDGET` behind it (`hooks/tezgah_context.py::CONTEXT_BUDGET`), enforced by `budgeted()` (`hooks/tezgah_context.py::budgeted`), which gives up blocks lowest value first along `DROP_ORDER` (`hooks/tezgah_context.py::DROP_ORDER`) - the skill hint among the first, the task phase, the delta and the pointer last - shrinking a block in `SHRINK` (the per-turn relevant lessons, to their first lesson) before it drops it (`hooks/tezgah_context.py::SHRINK`). The core, the reminder, an armed paragraph and the pinned user constraints sit outside `DROP_ORDER`. An event can therefore stay over its budget, and its note says so. The ceiling counts bytes, never tokens, because the module has no tokenizer. Not the [metadata band](#metadata-band), which is the installer's measurement of the same text rather than a runtime bound.
22
+ The byte ceiling one injected event may spend: `CONTEXT_BUDGET` per event with `DEFAULT_BUDGET` behind it (`hooks/tezgah_context.py::CONTEXT_BUDGET`), enforced by `budgeted()` (`hooks/tezgah_context.py::budgeted`), which gives up blocks lowest value first along `DROP_ORDER` (`hooks/tezgah_context.py::DROP_ORDER`) - the skill hint after the per-turn lessons and the index line, then the task phase, the delta and the pointer last - shrinking a block in `SHRINK` (the per-turn relevant lessons, to their first lesson) before it drops it (`hooks/tezgah_context.py::SHRINK`). The core, the reminder, an armed paragraph and the pinned user constraints sit outside `DROP_ORDER`. An event can therefore stay over its budget, and its note says so. The ceiling counts bytes, never tokens, because the module has no tokenizer. Not the [metadata band](#metadata-band), which is the installer's measurement of the same text rather than a runtime bound.
23
23
 
24
24
  ### capture
25
25
  The pre-write copy the gate takes of every file a write is about to change, `capture()` (`hooks/tezgah_snapshot.py::capture`), called on the gate's allow path (`hooks/tezgah_gate.py::decision`) and capped at `CAP` snapshots and `MAX_BYTES` per file (`hooks/tezgah_snapshot.py:55-56`); a file too large or unreadable is left uncaptured and writes no row, so nothing claims a copy that is not there. Not a transaction: the copy is bytes on disk, not a rollback that runs itself.
@@ -62,7 +62,7 @@ The partition a status [mark](#mark) carries so a renderer separates the marks t
62
62
  This project's own frame for the work, tezgah being the wrapper it puts around a coding agent - the injected contract, the [gate](#gate) and the [ledger](#evidence-ledger) - whose per-turn text still travels in the `<harness-reminder>` envelope (`hooks/tezgah_policy.py::PROMPT_REMINDER`). Two neighbours share the word: the agent runtime itself, which the current literature calls a complete agent harness (arXiv 2606.10106; `README.md:27-28` calls dsh one) and the multi-agent selection of the `harness` [skill](#skill), including the graph workflows the policy lists under "Graph harnesses" (`hooks/tezgah_policy.py::WORKFLOWS`); [layers](layers.md) draws the three apart. Not the [host](#host): the host is the agent, the harness is what tezgah puts around it.
63
63
 
64
64
  ### harness skill
65
- The [skill](#skill) that picks and runs a multi-agent harness for a task too wide for one context window - a code-graph workflow such as `graph-map` or a briefed subagent set (`skills/harness/SKILL.md:2-8`). Not tezgah's own wrapper around a [host](#host) ([harness](#harness), [layers](layers.md)).
65
+ The [skill](#skill) that picks and runs a multi-agent harness for a task too wide for one context window - a code-graph workflow such as `graph-map` or a briefed subagent set (`skills/harness/SKILL.md:11-20`). Not tezgah's own wrapper around a [host](#host) ([harness](#harness), [layers](layers.md)).
66
66
 
67
67
  ### host
68
68
  One coding agent tezgah is installed into - claude, codex, cursor, opencode, dsh, omp - with its config location in `HOST_DIRS` (`hooks/tezgah_paths.py::HOST_DIRS`), its presence test in `host_installed()` (`hooks/tezgah_paths.py::host_installed`) and its adapter under `hosts/<name>/` ([hosts](hosts.md)); also written "agent host", and the agent runtime the current literature calls the agent harness ([harness](#harness), [layers](layers.md)). Not a [root](#root): a host is a program, a root is a directory tezgah is armed over.
@@ -94,6 +94,9 @@ A used-mark a surface is able to see at all, so it can say "armed, not used yet"
94
94
  ### once-only
95
95
  A mark consumed by its own first use, so the thing it protects happens once: the grep [nudge](#nudge) is written before the deny so later greps pass (`hooks/tezgah_gate.py::decision`). Not a licence for the session: the identical call passes on the retry.
96
96
 
97
+ ### owner marker
98
+ The file a repository commits to say who owns its workspace: `tezgah.owner` at its own top, a few `key: value` lines read by `owner_marker()` (`hooks/tezgah_paths.py::owner_marker`). `tasks: off` stops the plan/task machine there (`hooks/tezgah_paths.py::tasks_disabled`) and `harness: excluded` makes `root_for` answer None, so nothing here runs at all (`hooks/tezgah_paths.py::harness_excluded`). Not a [per-repo mark](#per-repo-mark): it turns seams off rather than dropping one rule's paragraph, and not a [kill switch](#kill-switch), because it travels with the repository.
99
+
97
100
  ### per-repo mark
98
101
  An opt-out file in the repo tree - `.no-ponytail`, `.no-adhd`, `.no-graph`, `.no-lessons`, `.no-taste` - collected by `repo_marks()` walking up to the enclosing root (`hooks/tezgah_context.py::repo_marks`). Not a [kill switch](#kill-switch): a mark travels with the repo, a switch with the machine.
99
102
 
package/docs/hosts.md CHANGED
@@ -98,6 +98,15 @@ shared config, contract hash and the CLI symlinks every host shell can call
98
98
  (`instructions`, `mcp`, `permission.skill=deny`, `compaction.prune`,
99
99
  `watcher.ignore`, the two `external_directory` grants) and `tui.json` +
100
100
  `tui-plugins/tezgah-tui.tsx`.
101
+ The installer detects opencode 2 by its `cli.json` (`bin/tezgah-setup::opencode_v2`).
102
+ On opencode 2 the plugin, the skill links, `opencode.json` and its
103
+ `instructions` still load.
104
+ `tui.json` and `compaction.prune` are not written there: opencode 2 ignores
105
+ `tui.json` after its first start and does not support `compaction.prune`, a legacy setting.
106
+ The install report drops those two rows on opencode 2.
107
+ On opencode 2 the status line is `hosts/opencode/tui/cli/tui.tsx`. The installer
108
+ links it as the directory `tui-plugins/tezgah-cli` and lists it in `cli.json`
109
+ `plugins`. opencode 2 skips an entry that names a file. It loads a directory's `tui` module.
101
110
  - **dsh** - `install_dsh` (`bin/tezgah-setup::install_dsh`): `~/.dsh/skills/*` symlinks,
102
111
  a managed block in `~/.dsh/cordis.patch.yml` (`dsh_patch_block`, `bin/tezgah-setup::dsh_patch_block`) that
103
112
  mounts the Claude-code hook bridge on `hosts/dsh/hooks.json`, the MCP client
@@ -124,7 +133,7 @@ has to hash to one id - `hosts/codex/hook.py::gate_name`, `hosts/cursor/hook.py:
124
133
  draws the line, and returns the host's own output shape. The contract text, the
125
134
  gate decision, the evidence ledger, the untrusted-content marks and the segment
126
135
  builder stay in the shared core under `hooks/` (`hosts/omp/hook.py:1-12`,
127
- `hosts/cursor/hook.py:1-41`).
136
+ `hosts/cursor/hook.py:1-44`).
128
137
 
129
138
  ## Where the always-on core reaches each host
130
139
 
@@ -251,7 +260,7 @@ In order, each step verified by the one below it:
251
260
  (`hosts/omp/tezgah-hook.ts.in` rendered at `hooks/tezgah_attest.py::omp_bridge`).
252
261
  3. `install_<host>()` writing that host's files, registered in `INSTALLERS`
253
262
  (`bin/tezgah-setup::INSTALLERS`), and `uninstall_<host>()` removing only
254
- tezgah-managed links and blocks (`bin/tezgah-setup:3287-3419`).
263
+ tezgah-managed links and blocks (`bin/tezgah-setup:3331-3463`).
255
264
  4. `host_checks_<host>()` returning `(label, bool)` rows over what was actually
256
265
  written, registered in `HOST_CHECKS` (`bin/tezgah-setup::HOST_CHECKS`); the
257
266
  `--report` output is that list (`bin/tezgah-setup::report`). Give the row a home-qualified
@@ -398,8 +407,13 @@ In order, each step verified by the one below it:
398
407
  (`hosts/opencode/plugins/tezgah.js:11-14`).
399
408
  - **Cursor only runs a PreToolUse hook for the tool types its matcher names**, so
400
409
  the matcher must list the write spellings or the gate's edit branches are
401
- unreachable there (`hosts/cursor/hook.py:30-39`,
410
+ unreachable there (`hosts/cursor/hook.py:33-42`,
402
411
  `bin/tezgah-setup::CURSOR_PRETOOL_MATCHER`).
412
+ - **Cursor carries the per-turn text only up to 10000 characters.**
413
+ cursor-agent drops a `beforeSubmitPrompt` `additional_context` whole when it is
414
+ longer. A busy turn with every conditional rule armed measured 10288.
415
+ `fit()` cuts the tail to `CONTEXT_MAX` and marks the cut, so the reminder and
416
+ the first rules arrive (`hosts/cursor/hook.py::fit`, `hosts/cursor/hook.py::CONTEXT_MAX`).
403
417
  - **Claude, dsh, omp, codex and cursor run the gate only for the tool names
404
418
  their matcher carries**, so a name the PostToolUse side carries and the
405
419
  PreToolUse side does not is recorded in the ledger and never refused.
package/docs/index.json CHANGED
@@ -269,7 +269,13 @@
269
269
  "what lights the research mark and how is the layer switched off",
270
270
  "why may a new research line not be opened while another is unfinished",
271
271
  "what does tezgah-research next print for a product flow, and when is a decision due for re-measure",
272
- "how does an exploratory line run a campaign of new ideas (arena, stage funnel, tournament, board, dedup, yield)"
272
+ "how does an exploratory line run a campaign of new ideas (arena, stage funnel, tournament, board, dedup, yield)",
273
+ "how is a claim's certainty computed (rules 8 start level, steps, ceilings)",
274
+ "how do I record a citation receipt, a source capture or a search (cite, fetch, search)",
275
+ "what is a question class and what does init --class print",
276
+ "what does release-check do and what does calibration print",
277
+ "how does the instrument ledger validate an LLM judge (instrument, gold, label, switch)",
278
+ "what formats does a new line write by hand (INDEX note path, provenance values, review dimensions, deliverable)"
273
279
  ],
274
280
  "answers_tr": [
275
281
  "bir araştırma hattı nerede yaşar ve ne tutar",
@@ -279,7 +285,13 @@
279
285
  "araştırma işaretini ne yakar ve katman nasıl kapatılır",
280
286
  "başka biri bitmemişken neden yeni bir araştırma hattı açılamaz",
281
287
  "tezgah-research next bir ürün akışı için ne yazdırır ve bir karar ne zaman yeniden ölçülmeli",
282
- "keşif (exploratory) hattı yeni fikir kampanyasını nasıl yürütür (arena, aşama hunisi, turnuva, board, dedup, yield)"
288
+ "keşif (exploratory) hattı yeni fikir kampanyasını nasıl yürütür (arena, aşama hunisi, turnuva, board, dedup, yield)",
289
+ "bir iddianın kesinlik düzeyi nasıl hesaplanır (rules 8 başlangıç düzeyi, adımlar, tavanlar)",
290
+ "bir atıf makbuzu, kaynak yakalaması ya da arama nasıl kaydedilir (cite, fetch, search)",
291
+ "soru sınıfı nedir ve init --class ne yazdırır",
292
+ "release-check ne yapar ve calibration ne yazdırır",
293
+ "araç defteri bir LLM yargıcını nasıl doğrular (instrument, gold, label, switch)",
294
+ "yeni bir hat elle hangi biçimleri yazar (INDEX note yolu, provenance değerleri, review boyutları, deliverable)"
283
295
  ],
284
296
  "sources": [
285
297
  "hooks/tezgah_research.py",
@@ -288,7 +300,10 @@
288
300
  "hooks/tezgah_policy.py",
289
301
  "hooks/tezgah_context.py",
290
302
  "skills/research/SKILL.md",
291
- "tests/test_research.py"
303
+ "tests/test_research.py",
304
+ "hooks/tezgah_research_capture.py",
305
+ "hooks/tezgah_research_evidence.py",
306
+ "hooks/tezgah_research_stats.py"
292
307
  ]
293
308
  },
294
309
  {
@@ -302,7 +317,9 @@
302
317
  "how do I add a skill without breaking the router or the install report",
303
318
  "which skill designs a metric dashboard and where do its data-view rules live",
304
319
  "does the local skill search reach design-library's nested entries",
305
- "which skill carries a new metric dashboard or feature from research to re-measure"
320
+ "which skill carries a new metric dashboard or feature from research to re-measure",
321
+ "which floor wins between a repository's design.md and the design contract",
322
+ "what does tezgah-design slop run and where does its verdict go"
306
323
  ],
307
324
  "answers_tr": [
308
325
  "burada beceri nedir ve bir hosta nasıl ulaşır",
@@ -310,18 +327,23 @@
310
327
  "yönlendiriciyi veya kurulum raporunu bozmadan nasıl beceri eklerim",
311
328
  "metrik dashboard tasarımını hangi beceri yapar ve veri görünümü kuralları nerede",
312
329
  "yerel beceri araması design-library'nin iç girdilerine ulaşır mı",
313
- "yeni bir metrik dashboard'u veya özelliği araştırmadan yeniden ölçüme hangi beceri taşır"
330
+ "yeni bir metrik dashboard'u veya özelliği araştırmadan yeniden ölçüme hangi beceri taşır",
331
+ "bir deponun design.md dosyası ile tasarım sözleşmesi arasında hangi katman kazanır",
332
+ "tezgah-design slop neyi çalıştırır ve kararı nereye yazar"
314
333
  ],
315
334
  "sources": [
316
335
  "bin/tezgah-setup",
336
+ "bin/tezgah-design",
317
337
  "skills/",
318
338
  "skills/design-library/SOURCE",
339
+ "skills/hallmark/SOURCE",
319
340
  "tests/routing-fixtures.md",
320
341
  "commands/",
321
342
  "NOTICE",
322
343
  "tests/test_setup.py",
323
344
  "tests/test_skills.py",
324
345
  "hooks/tezgah_skill_pick.py",
346
+ "hooks/tezgah_integrity.py",
325
347
  "skills/design-contract/data-views.md",
326
348
  "skills/product-flow/SKILL.md"
327
349
  ]
@@ -386,7 +408,8 @@
386
408
  "something is broken what do I check first",
387
409
  "how do I turn on taste signal capture and measure my corrections",
388
410
  "how does taste learn my coding preferences and inject them",
389
- "how do I resume or clean up a delegated slice after a crash or a quota stop"
411
+ "how do I resume or clean up a delegated slice after a crash or a quota stop",
412
+ "how do I turn on the open-code-review spec for a plan's review"
390
413
  ],
391
414
  "answers_tr": [
392
415
  "bunu bir makineye nasıl kurar, doğrular ve yükseltirim",
@@ -396,7 +419,8 @@
396
419
  "bir şey bozuk, önce neyi kontrol etmeliyim",
397
420
  "zevk sinyali kaydını nasıl açar ve düzeltmelerimi nasıl ölçerim",
398
421
  "taste kodlama tercihlerimi nasıl öğrenir ve oturuma nasıl ekler",
399
- "bir çökme veya kota durmasından sonra devredilen bir dilimi nasıl sürdürür veya temizlerim"
422
+ "bir çökme veya kota durmasından sonra devredilen bir dilimi nasıl sürdürür veya temizlerim",
423
+ "bir planın incelemesi için open-code-review spesifikasyonunu nasıl açarım"
400
424
  ],
401
425
  "sources": [
402
426
  "bin/tezgah-setup",
@@ -413,7 +437,9 @@
413
437
  "hooks/tezgah_taste_ledger.py",
414
438
  "bin/tezgah-taste",
415
439
  "hooks/tezgah_task.py",
416
- "bin/tezgah-task"
440
+ "bin/tezgah-task",
441
+ "bin/tezgah-review-quote",
442
+ "bin/tezgah-ocr-review"
417
443
  ]
418
444
  },
419
445
  {
package/docs/judge.md CHANGED
@@ -118,8 +118,10 @@ The CLI runs headless in an empty temp dir. Its flags are `SESSION_ARGV`
118
118
  (`hooks/tezgah_judge.py::SESSION_ARGV`). The omp and claude runs drop tools,
119
119
  rules, skills, extensions, MCP servers and settings. The other three have no flag
120
120
  that drops their tools or takes a system prompt. They run with the least their
121
- `--help` offers: opencode `--pure`, cursor-agent `--mode ask`, codex
122
- `-s read-only --ephemeral`. Their prompt starts with the system prompt.
121
+ `--help` offers: cursor-agent `--mode ask`, codex `-s read-only --ephemeral`,
122
+ and opencode `--format json`. The 2.0 CLI dropped the `--pure` its 1.18
123
+ offered, so the judge's inline config stays what denies its tools. Their prompt
124
+ starts with the system prompt.
123
125
  `opencode run` ran a shell command its prompt asked for in a probe on
124
126
  2026-10-09. So it also gets an inline config that denies every tool
125
127
  (`SESSION_ENV`, `hooks/tezgah_judge.py::SESSION_ENV`). With it, the same probe
package/docs/layers.md CHANGED
@@ -94,8 +94,8 @@ frameworks.
94
94
  | agent framework | is it composed *from* elsewhere, or does it compose? A framework is composed from building blocks and stays a framework agent | tezgah plugs into its extension points, supplies none |
95
95
  | SDK | does it leave the iteration to its caller? A client library gives a call and stops | tezgah ships no client; it reads a host's event JSON on stdin (`hosts/codex/hook.py:1-2`) |
96
96
  | IDE plugin | is it a guest inside another program's surface? It draws and forwards and owns no task runtime | `hosts/opencode/plugins/tezgah.js:1-12` is one, and is a plugin |
97
- | eval harness | does it produce a score over a task set? It measures and enforces nothing | an eval scaffold is vendored as the `lm-evaluation-harness` skill body (`skills/ai-research/11-evaluation/lm-evaluation-harness/SKILL.md:11`), and this project's measurements live apart from the layer (`docs/README.md:88-89`) |
98
- | orchestrator | does it split one request across many runs and merge them? A harness runs one job to a report | the `harness` skill's route table (`skills/harness/SKILL.md:2-8`) and the graph workflows (`hooks/tezgah_policy.py::WORKFLOWS`) |
97
+ | eval harness | does it produce a score over a task set? It measures and enforces nothing | an eval scaffold is vendored as the `lm-evaluation-harness` skill body (`skills/ai-research/11-evaluation/lm-evaluation-harness/ENTRY.md:11`), and this project's measurements live apart from the layer (`docs/README.md:88-89`) |
98
+ | orchestrator | does it split one request across many runs and merge them? A harness runs one job to a report | the `harness` skill's route table (`skills/harness/SKILL.md:41-53`) and the graph workflows (`hooks/tezgah_policy.py::WORKFLOWS`) |
99
99
  | MCP | does it only carry a call and its result? Then it is transport, not a layer with policy or evidence | the section below |
100
100
 
101
101
  ## Why tezgah is not an agent harness
@@ -131,7 +131,7 @@ by solving the task.
131
131
  |---|---|---|
132
132
  | tezgah's own | the wrapper around a host - the injected contract, the per-turn text still travelling in the `<harness-reminder>` envelope (`hooks/tezgah_policy.py::PROMPT_REMINDER`), the gate and the ledger | [glossary](glossary.md#harness) |
133
133
  | the literature's | the host itself: a "complete agent runtime", which the README's intro also calls a harness for dsh (`README.md:27-28`) | [hosts](hosts.md) |
134
- | the skill's | multi-agent harness selection: which graph workflow or subagent set runs a task too wide for one window (`skills/harness/SKILL.md:2-8`, [skills](skills.md)) | [glossary](glossary.md#harness-skill) |
134
+ | the skill's | multi-agent harness selection: which graph workflow or subagent set runs a task too wide for one window (`skills/harness/SKILL.md:11-20`, [skills](skills.md)) | [glossary](glossary.md#harness-skill) |
135
135
 
136
136
  A claim that says "apply X to the harness" is therefore unreadable until it says
137
137
  which. Write **host** for the runtime, **the harness skill** for multi-agent