@r1z4x/tezgah 1.0.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 (582) hide show
  1. package/CHANGELOG.md +738 -0
  2. package/LICENSE +21 -0
  3. package/MANIFEST +753 -0
  4. package/README.de.md +169 -0
  5. package/README.es.md +168 -0
  6. package/README.fr.md +166 -0
  7. package/README.md +161 -0
  8. package/README.tr.md +163 -0
  9. package/agents/tezgah-reviewer.md +70 -0
  10. package/bin/codegen +337 -0
  11. package/bin/consult +797 -0
  12. package/bin/tezgah-adhd +50 -0
  13. package/bin/tezgah-agents +45 -0
  14. package/bin/tezgah-capture +66 -0
  15. package/bin/tezgah-context +96 -0
  16. package/bin/tezgah-decisions +213 -0
  17. package/bin/tezgah-design +953 -0
  18. package/bin/tezgah-docs +1199 -0
  19. package/bin/tezgah-doctor +497 -0
  20. package/bin/tezgah-dsh +37 -0
  21. package/bin/tezgah-dsh.cmd +70 -0
  22. package/bin/tezgah-gate +75 -0
  23. package/bin/tezgah-import-ai-research +439 -0
  24. package/bin/tezgah-index +32 -0
  25. package/bin/tezgah-lessons +148 -0
  26. package/bin/tezgah-mcp +322 -0
  27. package/bin/tezgah-migrate +324 -0
  28. package/bin/tezgah-pony +50 -0
  29. package/bin/tezgah-research +772 -0
  30. package/bin/tezgah-rollback +93 -0
  31. package/bin/tezgah-route +124 -0
  32. package/bin/tezgah-setup +5798 -0
  33. package/bin/tezgah-status +383 -0
  34. package/bin/tezgah-task +607 -0
  35. package/bin/tezgah-taste +423 -0
  36. package/bin/tezgah-triage +485 -0
  37. package/bin/tezgah.js +36 -0
  38. package/commands/adhd.md +21 -0
  39. package/commands/ponytail.md +21 -0
  40. package/docs/README.md +112 -0
  41. package/docs/architecture.md +226 -0
  42. package/docs/citations-baseline.json +59 -0
  43. package/docs/clarity-baseline.json +116 -0
  44. package/docs/contract.md +416 -0
  45. package/docs/environment.md +141 -0
  46. package/docs/evidence.md +831 -0
  47. package/docs/feature-audit.md +139 -0
  48. package/docs/gate.md +407 -0
  49. package/docs/glossary.md +201 -0
  50. package/docs/hosts.md +400 -0
  51. package/docs/index.json +471 -0
  52. package/docs/judge.md +193 -0
  53. package/docs/layers.md +189 -0
  54. package/docs/models.md +160 -0
  55. package/docs/operations.md +666 -0
  56. package/docs/research.md +809 -0
  57. package/docs/results/paired-outcome-2026-10.jsonl +254 -0
  58. package/docs/results/paired-outcome-2026-10.md +204 -0
  59. package/docs/skills.md +236 -0
  60. package/docs/status-line.md +315 -0
  61. package/docs/testing.md +287 -0
  62. package/docs/vision.md +117 -0
  63. package/hooks/hooks.json +33 -0
  64. package/hooks/projects-auto-init.py +98 -0
  65. package/hooks/projects-posttooluse.py +149 -0
  66. package/hooks/projects-pretooluse.py +40 -0
  67. package/hooks/projects-stop.py +60 -0
  68. package/hooks/tezgah_agents.py +817 -0
  69. package/hooks/tezgah_apps.py +266 -0
  70. package/hooks/tezgah_attest.py +255 -0
  71. package/hooks/tezgah_clarity.py +171 -0
  72. package/hooks/tezgah_components.py +140 -0
  73. package/hooks/tezgah_context.py +2953 -0
  74. package/hooks/tezgah_embed.py +765 -0
  75. package/hooks/tezgah_gate.py +2736 -0
  76. package/hooks/tezgah_guard.py +177 -0
  77. package/hooks/tezgah_index.py +124 -0
  78. package/hooks/tezgah_integrity.py +5141 -0
  79. package/hooks/tezgah_judge.py +487 -0
  80. package/hooks/tezgah_lang.py +230 -0
  81. package/hooks/tezgah_lessons.py +210 -0
  82. package/hooks/tezgah_models.py +855 -0
  83. package/hooks/tezgah_paths.py +1132 -0
  84. package/hooks/tezgah_policy.py +1039 -0
  85. package/hooks/tezgah_rank.py +77 -0
  86. package/hooks/tezgah_replay.py +1109 -0
  87. package/hooks/tezgah_research.py +5176 -0
  88. package/hooks/tezgah_shapes.py +305 -0
  89. package/hooks/tezgah_skill_pick.py +227 -0
  90. package/hooks/tezgah_snapshot.py +490 -0
  91. package/hooks/tezgah_stopspec.py +320 -0
  92. package/hooks/tezgah_task.py +458 -0
  93. package/hooks/tezgah_taste.py +201 -0
  94. package/hooks/tezgah_untrusted.py +112 -0
  95. package/hooks/tezgah_update.py +430 -0
  96. package/hosts/codex/hook.py +268 -0
  97. package/hosts/codex/hooks.json +26 -0
  98. package/hosts/cursor/hook.py +461 -0
  99. package/hosts/cursor/hooks.json +44 -0
  100. package/hosts/dsh/hooks.json +21 -0
  101. package/hosts/dsh/statusline/lib/client.js +138 -0
  102. package/hosts/dsh/statusline/lib/index.js +104 -0
  103. package/hosts/dsh/statusline/package.json +28 -0
  104. package/hosts/omp/hook.py +277 -0
  105. package/hosts/omp/tezgah-hook.ts.in +701 -0
  106. package/hosts/opencode/plugins/tezgah.js +2742 -0
  107. package/hosts/opencode/tui/tezgah-tui.tsx +151 -0
  108. package/output-styles/tezgah.md +142 -0
  109. package/package.json +32 -0
  110. package/packaging/build.sh +342 -0
  111. package/packaging/install.ps1 +166 -0
  112. package/packaging/install.sh +56 -0
  113. package/packaging/upgrade.sh +142 -0
  114. package/skills/ai-research/0-autoresearch-skill/SKILL.md +411 -0
  115. package/skills/ai-research/0-autoresearch-skill/references/agent-continuity.md +95 -0
  116. package/skills/ai-research/0-autoresearch-skill/references/progress-reporting.md +166 -0
  117. package/skills/ai-research/0-autoresearch-skill/references/skill-routing.md +219 -0
  118. package/skills/ai-research/0-autoresearch-skill/templates/findings.md +44 -0
  119. package/skills/ai-research/0-autoresearch-skill/templates/research-log.md +41 -0
  120. package/skills/ai-research/01-model-architecture/litgpt/SKILL.md +469 -0
  121. package/skills/ai-research/01-model-architecture/litgpt/references/custom-models.md +569 -0
  122. package/skills/ai-research/01-model-architecture/litgpt/references/distributed-training.md +452 -0
  123. package/skills/ai-research/01-model-architecture/litgpt/references/supported-models.md +337 -0
  124. package/skills/ai-research/01-model-architecture/litgpt/references/training-recipes.md +620 -0
  125. package/skills/ai-research/01-model-architecture/mamba/SKILL.md +260 -0
  126. package/skills/ai-research/01-model-architecture/mamba/references/architecture-details.md +207 -0
  127. package/skills/ai-research/01-model-architecture/mamba/references/benchmarks.md +256 -0
  128. package/skills/ai-research/01-model-architecture/mamba/references/training-guide.md +389 -0
  129. package/skills/ai-research/01-model-architecture/nanogpt/SKILL.md +290 -0
  130. package/skills/ai-research/01-model-architecture/nanogpt/references/architecture.md +383 -0
  131. package/skills/ai-research/01-model-architecture/nanogpt/references/data.md +477 -0
  132. package/skills/ai-research/01-model-architecture/nanogpt/references/training.md +565 -0
  133. package/skills/ai-research/01-model-architecture/rwkv/SKILL.md +260 -0
  134. package/skills/ai-research/01-model-architecture/rwkv/references/architecture-details.md +345 -0
  135. package/skills/ai-research/01-model-architecture/rwkv/references/rwkv7.md +387 -0
  136. package/skills/ai-research/01-model-architecture/rwkv/references/state-management.md +370 -0
  137. package/skills/ai-research/01-model-architecture/torchtitan/SKILL.md +358 -0
  138. package/skills/ai-research/01-model-architecture/torchtitan/references/checkpoint.md +182 -0
  139. package/skills/ai-research/01-model-architecture/torchtitan/references/custom-models.md +259 -0
  140. package/skills/ai-research/01-model-architecture/torchtitan/references/float8.md +134 -0
  141. package/skills/ai-research/01-model-architecture/torchtitan/references/fsdp.md +127 -0
  142. package/skills/ai-research/02-tokenization/huggingface-tokenizers/SKILL.md +516 -0
  143. package/skills/ai-research/02-tokenization/huggingface-tokenizers/references/algorithms.md +654 -0
  144. package/skills/ai-research/02-tokenization/huggingface-tokenizers/references/integration.md +638 -0
  145. package/skills/ai-research/02-tokenization/huggingface-tokenizers/references/pipeline.md +724 -0
  146. package/skills/ai-research/02-tokenization/huggingface-tokenizers/references/training.md +566 -0
  147. package/skills/ai-research/02-tokenization/sentencepiece/SKILL.md +235 -0
  148. package/skills/ai-research/02-tokenization/sentencepiece/references/algorithms.md +201 -0
  149. package/skills/ai-research/02-tokenization/sentencepiece/references/training.md +305 -0
  150. package/skills/ai-research/03-fine-tuning/axolotl/SKILL.md +158 -0
  151. package/skills/ai-research/03-fine-tuning/axolotl/references/api.md +5549 -0
  152. package/skills/ai-research/03-fine-tuning/axolotl/references/dataset-formats.md +1030 -0
  153. package/skills/ai-research/03-fine-tuning/axolotl/references/index.md +16 -0
  154. package/skills/ai-research/03-fine-tuning/axolotl/references/other.md +3564 -0
  155. package/skills/ai-research/03-fine-tuning/llama-factory/SKILL.md +80 -0
  156. package/skills/ai-research/03-fine-tuning/llama-factory/references/_images.md +24 -0
  157. package/skills/ai-research/03-fine-tuning/llama-factory/references/advanced.md +1056 -0
  158. package/skills/ai-research/03-fine-tuning/llama-factory/references/getting_started.md +350 -0
  159. package/skills/ai-research/03-fine-tuning/llama-factory/references/index.md +20 -0
  160. package/skills/ai-research/03-fine-tuning/llama-factory/references/other.md +32 -0
  161. package/skills/ai-research/03-fine-tuning/peft/SKILL.md +431 -0
  162. package/skills/ai-research/03-fine-tuning/peft/references/advanced-usage.md +515 -0
  163. package/skills/ai-research/03-fine-tuning/peft/references/troubleshooting.md +481 -0
  164. package/skills/ai-research/03-fine-tuning/unsloth/SKILL.md +80 -0
  165. package/skills/ai-research/03-fine-tuning/unsloth/references/index.md +8 -0
  166. package/skills/ai-research/03-fine-tuning/unsloth/references/llms.md +83 -0
  167. package/skills/ai-research/04-mechanistic-interpretability/nnsight/SKILL.md +436 -0
  168. package/skills/ai-research/04-mechanistic-interpretability/nnsight/references/README.md +79 -0
  169. package/skills/ai-research/04-mechanistic-interpretability/nnsight/references/api.md +345 -0
  170. package/skills/ai-research/04-mechanistic-interpretability/nnsight/references/tutorials.md +301 -0
  171. package/skills/ai-research/04-mechanistic-interpretability/pyvene/SKILL.md +473 -0
  172. package/skills/ai-research/04-mechanistic-interpretability/pyvene/references/README.md +74 -0
  173. package/skills/ai-research/04-mechanistic-interpretability/pyvene/references/api.md +384 -0
  174. package/skills/ai-research/04-mechanistic-interpretability/pyvene/references/tutorials.md +377 -0
  175. package/skills/ai-research/04-mechanistic-interpretability/saelens/SKILL.md +386 -0
  176. package/skills/ai-research/04-mechanistic-interpretability/saelens/references/README.md +71 -0
  177. package/skills/ai-research/04-mechanistic-interpretability/saelens/references/api.md +334 -0
  178. package/skills/ai-research/04-mechanistic-interpretability/saelens/references/tutorials.md +319 -0
  179. package/skills/ai-research/04-mechanistic-interpretability/transformer-lens/SKILL.md +346 -0
  180. package/skills/ai-research/04-mechanistic-interpretability/transformer-lens/references/README.md +55 -0
  181. package/skills/ai-research/04-mechanistic-interpretability/transformer-lens/references/api.md +363 -0
  182. package/skills/ai-research/04-mechanistic-interpretability/transformer-lens/references/tutorials.md +340 -0
  183. package/skills/ai-research/05-data-processing/nemo-curator/SKILL.md +383 -0
  184. package/skills/ai-research/05-data-processing/nemo-curator/references/deduplication.md +88 -0
  185. package/skills/ai-research/05-data-processing/nemo-curator/references/filtering.md +103 -0
  186. package/skills/ai-research/05-data-processing/ray-data/SKILL.md +326 -0
  187. package/skills/ai-research/05-data-processing/ray-data/references/integration.md +83 -0
  188. package/skills/ai-research/05-data-processing/ray-data/references/transformations.md +84 -0
  189. package/skills/ai-research/06-post-training/grpo-rl-training/README.md +98 -0
  190. package/skills/ai-research/06-post-training/grpo-rl-training/SKILL.md +572 -0
  191. package/skills/ai-research/06-post-training/miles/SKILL.md +315 -0
  192. package/skills/ai-research/06-post-training/miles/references/api-reference.md +142 -0
  193. package/skills/ai-research/06-post-training/miles/references/troubleshooting.md +353 -0
  194. package/skills/ai-research/06-post-training/openrlhf/SKILL.md +249 -0
  195. package/skills/ai-research/06-post-training/openrlhf/references/algorithm-comparison.md +405 -0
  196. package/skills/ai-research/06-post-training/openrlhf/references/custom-rewards.md +531 -0
  197. package/skills/ai-research/06-post-training/openrlhf/references/hybrid-engine.md +288 -0
  198. package/skills/ai-research/06-post-training/openrlhf/references/multi-node-training.md +455 -0
  199. package/skills/ai-research/06-post-training/simpo/SKILL.md +219 -0
  200. package/skills/ai-research/06-post-training/simpo/references/datasets.md +479 -0
  201. package/skills/ai-research/06-post-training/simpo/references/hyperparameters.md +453 -0
  202. package/skills/ai-research/06-post-training/simpo/references/loss-functions.md +351 -0
  203. package/skills/ai-research/06-post-training/slime/SKILL.md +464 -0
  204. package/skills/ai-research/06-post-training/slime/references/api-reference.md +393 -0
  205. package/skills/ai-research/06-post-training/slime/references/troubleshooting.md +387 -0
  206. package/skills/ai-research/06-post-training/torchforge/SKILL.md +433 -0
  207. package/skills/ai-research/06-post-training/torchforge/references/api-reference.md +328 -0
  208. package/skills/ai-research/06-post-training/torchforge/references/troubleshooting.md +410 -0
  209. package/skills/ai-research/06-post-training/trl-fine-tuning/SKILL.md +455 -0
  210. package/skills/ai-research/06-post-training/trl-fine-tuning/references/dpo-variants.md +228 -0
  211. package/skills/ai-research/06-post-training/trl-fine-tuning/references/online-rl.md +83 -0
  212. package/skills/ai-research/06-post-training/trl-fine-tuning/references/reward-modeling.md +123 -0
  213. package/skills/ai-research/06-post-training/trl-fine-tuning/references/sft-training.md +169 -0
  214. package/skills/ai-research/06-post-training/verl/SKILL.md +391 -0
  215. package/skills/ai-research/06-post-training/verl/references/api-reference.md +302 -0
  216. package/skills/ai-research/06-post-training/verl/references/troubleshooting.md +392 -0
  217. package/skills/ai-research/07-safety-alignment/constitutional-ai/SKILL.md +290 -0
  218. package/skills/ai-research/07-safety-alignment/llamaguard/SKILL.md +337 -0
  219. package/skills/ai-research/07-safety-alignment/nemo-guardrails/SKILL.md +297 -0
  220. package/skills/ai-research/07-safety-alignment/prompt-guard/SKILL.md +312 -0
  221. package/skills/ai-research/08-distributed-training/accelerate/SKILL.md +332 -0
  222. package/skills/ai-research/08-distributed-training/accelerate/references/custom-plugins.md +454 -0
  223. package/skills/ai-research/08-distributed-training/accelerate/references/megatron-integration.md +490 -0
  224. package/skills/ai-research/08-distributed-training/accelerate/references/performance.md +526 -0
  225. package/skills/ai-research/08-distributed-training/deepspeed/SKILL.md +141 -0
  226. package/skills/ai-research/08-distributed-training/deepspeed/references/08.md +18 -0
  227. package/skills/ai-research/08-distributed-training/deepspeed/references/09.md +174 -0
  228. package/skills/ai-research/08-distributed-training/deepspeed/references/2020.md +379 -0
  229. package/skills/ai-research/08-distributed-training/deepspeed/references/2023.md +280 -0
  230. package/skills/ai-research/08-distributed-training/deepspeed/references/assets.md +180 -0
  231. package/skills/ai-research/08-distributed-training/deepspeed/references/index.md +36 -0
  232. package/skills/ai-research/08-distributed-training/deepspeed/references/mii.md +119 -0
  233. package/skills/ai-research/08-distributed-training/deepspeed/references/other.md +1192 -0
  234. package/skills/ai-research/08-distributed-training/megatron-core/SKILL.md +366 -0
  235. package/skills/ai-research/08-distributed-training/megatron-core/references/benchmarks.md +250 -0
  236. package/skills/ai-research/08-distributed-training/megatron-core/references/parallelism-guide.md +405 -0
  237. package/skills/ai-research/08-distributed-training/megatron-core/references/production-examples.md +474 -0
  238. package/skills/ai-research/08-distributed-training/megatron-core/references/training-recipes.md +548 -0
  239. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/SKILL.md +231 -0
  240. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_dcp_async_recipe.md +14 -0
  241. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_dcp_overview.md +19 -0
  242. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_dcp_recipe.md +18 -0
  243. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_ddp_notes.md +10 -0
  244. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_device_mesh_tutorial.md +22 -0
  245. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_examples_fsdp2.md +15 -0
  246. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_fsdp1_api.md +9 -0
  247. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_fsdp2_tutorial.md +45 -0
  248. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_fully_shard_api.md +49 -0
  249. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_tp_tutorial.md +22 -0
  250. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/ray_train_fsdp2_example.md +13 -0
  251. package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/torchtitan_fsdp_notes.md +14 -0
  252. package/skills/ai-research/08-distributed-training/pytorch-lightning/SKILL.md +346 -0
  253. package/skills/ai-research/08-distributed-training/pytorch-lightning/references/callbacks.md +437 -0
  254. package/skills/ai-research/08-distributed-training/pytorch-lightning/references/distributed.md +491 -0
  255. package/skills/ai-research/08-distributed-training/pytorch-lightning/references/hyperparameter-tuning.md +557 -0
  256. package/skills/ai-research/08-distributed-training/ray-train/SKILL.md +406 -0
  257. package/skills/ai-research/08-distributed-training/ray-train/references/multi-node.md +629 -0
  258. package/skills/ai-research/09-infrastructure/lambda-labs/SKILL.md +545 -0
  259. package/skills/ai-research/09-infrastructure/lambda-labs/references/advanced-usage.md +612 -0
  260. package/skills/ai-research/09-infrastructure/lambda-labs/references/troubleshooting.md +531 -0
  261. package/skills/ai-research/09-infrastructure/modal/SKILL.md +341 -0
  262. package/skills/ai-research/09-infrastructure/modal/references/advanced-usage.md +504 -0
  263. package/skills/ai-research/09-infrastructure/modal/references/troubleshooting.md +495 -0
  264. package/skills/ai-research/09-infrastructure/skypilot/SKILL.md +509 -0
  265. package/skills/ai-research/09-infrastructure/skypilot/references/advanced-usage.md +492 -0
  266. package/skills/ai-research/09-infrastructure/skypilot/references/troubleshooting.md +571 -0
  267. package/skills/ai-research/10-optimization/awq/SKILL.md +310 -0
  268. package/skills/ai-research/10-optimization/awq/references/advanced-usage.md +325 -0
  269. package/skills/ai-research/10-optimization/awq/references/troubleshooting.md +345 -0
  270. package/skills/ai-research/10-optimization/bitsandbytes/SKILL.md +411 -0
  271. package/skills/ai-research/10-optimization/bitsandbytes/references/memory-optimization.md +522 -0
  272. package/skills/ai-research/10-optimization/bitsandbytes/references/qlora-training.md +522 -0
  273. package/skills/ai-research/10-optimization/bitsandbytes/references/quantization-formats.md +448 -0
  274. package/skills/ai-research/10-optimization/flash-attention/SKILL.md +367 -0
  275. package/skills/ai-research/10-optimization/flash-attention/references/benchmarks.md +216 -0
  276. package/skills/ai-research/10-optimization/flash-attention/references/transformers-integration.md +294 -0
  277. package/skills/ai-research/10-optimization/gguf/SKILL.md +427 -0
  278. package/skills/ai-research/10-optimization/gguf/references/advanced-usage.md +505 -0
  279. package/skills/ai-research/10-optimization/gguf/references/troubleshooting.md +443 -0
  280. package/skills/ai-research/10-optimization/gptq/SKILL.md +450 -0
  281. package/skills/ai-research/10-optimization/gptq/references/calibration.md +338 -0
  282. package/skills/ai-research/10-optimization/gptq/references/integration.md +130 -0
  283. package/skills/ai-research/10-optimization/gptq/references/troubleshooting.md +96 -0
  284. package/skills/ai-research/10-optimization/hqq/SKILL.md +445 -0
  285. package/skills/ai-research/10-optimization/hqq/references/advanced-usage.md +529 -0
  286. package/skills/ai-research/10-optimization/hqq/references/troubleshooting.md +504 -0
  287. package/skills/ai-research/10-optimization/ml-training-recipes/SKILL.md +319 -0
  288. package/skills/ai-research/10-optimization/ml-training-recipes/references/architecture.md +320 -0
  289. package/skills/ai-research/10-optimization/ml-training-recipes/references/biomedical.md +498 -0
  290. package/skills/ai-research/10-optimization/ml-training-recipes/references/domain-specific.md +626 -0
  291. package/skills/ai-research/10-optimization/ml-training-recipes/references/experiment-loop.md +129 -0
  292. package/skills/ai-research/10-optimization/ml-training-recipes/references/optimizers.md +330 -0
  293. package/skills/ai-research/10-optimization/ml-training-recipes/references/scaling-and-selection.md +428 -0
  294. package/skills/ai-research/11-evaluation/bigcode-evaluation-harness/SKILL.md +405 -0
  295. package/skills/ai-research/11-evaluation/bigcode-evaluation-harness/references/benchmarks.md +394 -0
  296. package/skills/ai-research/11-evaluation/bigcode-evaluation-harness/references/custom-tasks.md +425 -0
  297. package/skills/ai-research/11-evaluation/bigcode-evaluation-harness/references/issues.md +395 -0
  298. package/skills/ai-research/11-evaluation/lm-evaluation-harness/SKILL.md +490 -0
  299. package/skills/ai-research/11-evaluation/lm-evaluation-harness/references/api-evaluation.md +491 -0
  300. package/skills/ai-research/11-evaluation/lm-evaluation-harness/references/benchmark-guide.md +489 -0
  301. package/skills/ai-research/11-evaluation/lm-evaluation-harness/references/custom-tasks.md +603 -0
  302. package/skills/ai-research/11-evaluation/lm-evaluation-harness/references/distributed-eval.md +520 -0
  303. package/skills/ai-research/11-evaluation/nemo-evaluator/SKILL.md +494 -0
  304. package/skills/ai-research/11-evaluation/nemo-evaluator/references/adapter-system.md +341 -0
  305. package/skills/ai-research/11-evaluation/nemo-evaluator/references/configuration.md +448 -0
  306. package/skills/ai-research/11-evaluation/nemo-evaluator/references/custom-benchmarks.md +316 -0
  307. package/skills/ai-research/11-evaluation/nemo-evaluator/references/execution-backends.md +362 -0
  308. package/skills/ai-research/12-inference-serving/llama-cpp/SKILL.md +258 -0
  309. package/skills/ai-research/12-inference-serving/llama-cpp/references/optimization.md +90 -0
  310. package/skills/ai-research/12-inference-serving/llama-cpp/references/quantization.md +214 -0
  311. package/skills/ai-research/12-inference-serving/llama-cpp/references/server.md +126 -0
  312. package/skills/ai-research/12-inference-serving/sglang/SKILL.md +442 -0
  313. package/skills/ai-research/12-inference-serving/sglang/references/deployment.md +491 -0
  314. package/skills/ai-research/12-inference-serving/sglang/references/radix-attention.md +414 -0
  315. package/skills/ai-research/12-inference-serving/sglang/references/structured-generation.md +542 -0
  316. package/skills/ai-research/12-inference-serving/tensorrt-llm/SKILL.md +187 -0
  317. package/skills/ai-research/12-inference-serving/tensorrt-llm/references/multi-gpu.md +299 -0
  318. package/skills/ai-research/12-inference-serving/tensorrt-llm/references/optimization.md +243 -0
  319. package/skills/ai-research/12-inference-serving/tensorrt-llm/references/serving.md +471 -0
  320. package/skills/ai-research/12-inference-serving/vllm/SKILL.md +364 -0
  321. package/skills/ai-research/12-inference-serving/vllm/references/optimization.md +227 -0
  322. package/skills/ai-research/12-inference-serving/vllm/references/quantization.md +285 -0
  323. package/skills/ai-research/12-inference-serving/vllm/references/server-deployment.md +256 -0
  324. package/skills/ai-research/12-inference-serving/vllm/references/troubleshooting.md +448 -0
  325. package/skills/ai-research/13-mlops/mlflow/SKILL.md +704 -0
  326. package/skills/ai-research/13-mlops/mlflow/references/deployment.md +745 -0
  327. package/skills/ai-research/13-mlops/mlflow/references/model-registry.md +771 -0
  328. package/skills/ai-research/13-mlops/mlflow/references/tracking.md +681 -0
  329. package/skills/ai-research/13-mlops/swanlab/SKILL.md +406 -0
  330. package/skills/ai-research/13-mlops/swanlab/references/integrations.md +305 -0
  331. package/skills/ai-research/13-mlops/swanlab/references/visualization.md +234 -0
  332. package/skills/ai-research/13-mlops/tensorboard/SKILL.md +629 -0
  333. package/skills/ai-research/13-mlops/tensorboard/references/integrations.md +639 -0
  334. package/skills/ai-research/13-mlops/tensorboard/references/profiling.md +546 -0
  335. package/skills/ai-research/13-mlops/tensorboard/references/visualization.md +621 -0
  336. package/skills/ai-research/13-mlops/weights-and-biases/SKILL.md +590 -0
  337. package/skills/ai-research/13-mlops/weights-and-biases/references/artifacts.md +585 -0
  338. package/skills/ai-research/13-mlops/weights-and-biases/references/integrations.md +701 -0
  339. package/skills/ai-research/13-mlops/weights-and-biases/references/sweeps.md +848 -0
  340. package/skills/ai-research/14-agents/a-evolve/SKILL.md +383 -0
  341. package/skills/ai-research/14-agents/a-evolve/references/README.md +831 -0
  342. package/skills/ai-research/14-agents/a-evolve/references/api.md +594 -0
  343. package/skills/ai-research/14-agents/a-evolve/references/architecture.md +417 -0
  344. package/skills/ai-research/14-agents/a-evolve/references/design-patterns.md +462 -0
  345. package/skills/ai-research/14-agents/a-evolve/references/examples.md +352 -0
  346. package/skills/ai-research/14-agents/a-evolve/references/issues.md +591 -0
  347. package/skills/ai-research/14-agents/a-evolve/references/releases.md +112 -0
  348. package/skills/ai-research/14-agents/a-evolve/references/tutorials.md +819 -0
  349. package/skills/ai-research/14-agents/autogpt/SKILL.md +403 -0
  350. package/skills/ai-research/14-agents/autogpt/references/advanced-usage.md +536 -0
  351. package/skills/ai-research/14-agents/autogpt/references/troubleshooting.md +421 -0
  352. package/skills/ai-research/14-agents/crewai/SKILL.md +498 -0
  353. package/skills/ai-research/14-agents/crewai/references/flows.md +439 -0
  354. package/skills/ai-research/14-agents/crewai/references/tools.md +430 -0
  355. package/skills/ai-research/14-agents/crewai/references/troubleshooting.md +481 -0
  356. package/skills/ai-research/14-agents/langchain/SKILL.md +480 -0
  357. package/skills/ai-research/14-agents/langchain/references/agents.md +500 -0
  358. package/skills/ai-research/14-agents/langchain/references/integration.md +563 -0
  359. package/skills/ai-research/14-agents/langchain/references/rag.md +601 -0
  360. package/skills/ai-research/14-agents/llamaindex/SKILL.md +569 -0
  361. package/skills/ai-research/14-agents/llamaindex/references/agents.md +84 -0
  362. package/skills/ai-research/14-agents/llamaindex/references/data_connectors.md +109 -0
  363. package/skills/ai-research/14-agents/llamaindex/references/query_engines.md +407 -0
  364. package/skills/ai-research/15-rag/chroma/SKILL.md +406 -0
  365. package/skills/ai-research/15-rag/chroma/references/integration.md +39 -0
  366. package/skills/ai-research/15-rag/faiss/SKILL.md +221 -0
  367. package/skills/ai-research/15-rag/faiss/references/index_types.md +281 -0
  368. package/skills/ai-research/15-rag/pinecone/SKILL.md +358 -0
  369. package/skills/ai-research/15-rag/pinecone/references/deployment.md +182 -0
  370. package/skills/ai-research/15-rag/qdrant/SKILL.md +493 -0
  371. package/skills/ai-research/15-rag/qdrant/references/advanced-usage.md +649 -0
  372. package/skills/ai-research/15-rag/qdrant/references/troubleshooting.md +632 -0
  373. package/skills/ai-research/15-rag/sentence-transformers/SKILL.md +255 -0
  374. package/skills/ai-research/15-rag/sentence-transformers/references/models.md +124 -0
  375. package/skills/ai-research/16-prompt-engineering/dspy/SKILL.md +590 -0
  376. package/skills/ai-research/16-prompt-engineering/dspy/references/examples.md +664 -0
  377. package/skills/ai-research/16-prompt-engineering/dspy/references/modules.md +476 -0
  378. package/skills/ai-research/16-prompt-engineering/dspy/references/optimizers.md +567 -0
  379. package/skills/ai-research/16-prompt-engineering/guidance/SKILL.md +572 -0
  380. package/skills/ai-research/16-prompt-engineering/guidance/references/backends.md +555 -0
  381. package/skills/ai-research/16-prompt-engineering/guidance/references/constraints.md +675 -0
  382. package/skills/ai-research/16-prompt-engineering/guidance/references/examples.md +768 -0
  383. package/skills/ai-research/16-prompt-engineering/instructor/SKILL.md +740 -0
  384. package/skills/ai-research/16-prompt-engineering/instructor/references/examples.md +108 -0
  385. package/skills/ai-research/16-prompt-engineering/instructor/references/providers.md +71 -0
  386. package/skills/ai-research/16-prompt-engineering/instructor/references/validation.md +607 -0
  387. package/skills/ai-research/16-prompt-engineering/outlines/SKILL.md +652 -0
  388. package/skills/ai-research/16-prompt-engineering/outlines/references/backends.md +616 -0
  389. package/skills/ai-research/16-prompt-engineering/outlines/references/examples.md +774 -0
  390. package/skills/ai-research/16-prompt-engineering/outlines/references/json_generation.md +653 -0
  391. package/skills/ai-research/17-observability/langsmith/SKILL.md +422 -0
  392. package/skills/ai-research/17-observability/langsmith/references/advanced-usage.md +549 -0
  393. package/skills/ai-research/17-observability/langsmith/references/troubleshooting.md +538 -0
  394. package/skills/ai-research/17-observability/phoenix/SKILL.md +475 -0
  395. package/skills/ai-research/17-observability/phoenix/references/advanced-usage.md +620 -0
  396. package/skills/ai-research/17-observability/phoenix/references/troubleshooting.md +539 -0
  397. package/skills/ai-research/18-multimodal/audiocraft/SKILL.md +564 -0
  398. package/skills/ai-research/18-multimodal/audiocraft/references/advanced-usage.md +667 -0
  399. package/skills/ai-research/18-multimodal/audiocraft/references/troubleshooting.md +505 -0
  400. package/skills/ai-research/18-multimodal/blip-2/SKILL.md +564 -0
  401. package/skills/ai-research/18-multimodal/blip-2/references/advanced-usage.md +681 -0
  402. package/skills/ai-research/18-multimodal/blip-2/references/troubleshooting.md +527 -0
  403. package/skills/ai-research/18-multimodal/clip/SKILL.md +253 -0
  404. package/skills/ai-research/18-multimodal/clip/references/applications.md +208 -0
  405. package/skills/ai-research/18-multimodal/cosmos-policy/SKILL.md +402 -0
  406. package/skills/ai-research/18-multimodal/cosmos-policy/references/libero-commands.md +175 -0
  407. package/skills/ai-research/18-multimodal/cosmos-policy/references/robocasa-commands.md +147 -0
  408. package/skills/ai-research/18-multimodal/llava/SKILL.md +304 -0
  409. package/skills/ai-research/18-multimodal/llava/references/training.md +198 -0
  410. package/skills/ai-research/18-multimodal/openpi/SKILL.md +480 -0
  411. package/skills/ai-research/18-multimodal/openpi/references/checkpoints-and-env-map.md +86 -0
  412. package/skills/ai-research/18-multimodal/openpi/references/config-recipes.md +50 -0
  413. package/skills/ai-research/18-multimodal/openpi/references/pytorch-gotchas.md +49 -0
  414. package/skills/ai-research/18-multimodal/openpi/references/remote-client-pattern.md +48 -0
  415. package/skills/ai-research/18-multimodal/openpi/references/training-debugging.md +46 -0
  416. package/skills/ai-research/18-multimodal/openvla-oft/SKILL.md +441 -0
  417. package/skills/ai-research/18-multimodal/openvla-oft/references/aloha-workflow.md +141 -0
  418. package/skills/ai-research/18-multimodal/openvla-oft/references/config-troubleshooting.md +97 -0
  419. package/skills/ai-research/18-multimodal/openvla-oft/references/libero-workflow.md +115 -0
  420. package/skills/ai-research/18-multimodal/openvla-oft/references/paper-and-checkpoints.md +84 -0
  421. package/skills/ai-research/18-multimodal/segment-anything/SKILL.md +500 -0
  422. package/skills/ai-research/18-multimodal/segment-anything/references/advanced-usage.md +590 -0
  423. package/skills/ai-research/18-multimodal/segment-anything/references/troubleshooting.md +485 -0
  424. package/skills/ai-research/18-multimodal/stable-diffusion/SKILL.md +519 -0
  425. package/skills/ai-research/18-multimodal/stable-diffusion/references/advanced-usage.md +717 -0
  426. package/skills/ai-research/18-multimodal/stable-diffusion/references/troubleshooting.md +556 -0
  427. package/skills/ai-research/18-multimodal/whisper/SKILL.md +317 -0
  428. package/skills/ai-research/18-multimodal/whisper/references/languages.md +190 -0
  429. package/skills/ai-research/19-emerging-techniques/knowledge-distillation/SKILL.md +458 -0
  430. package/skills/ai-research/19-emerging-techniques/knowledge-distillation/references/minillm.md +335 -0
  431. package/skills/ai-research/19-emerging-techniques/long-context/SKILL.md +536 -0
  432. package/skills/ai-research/19-emerging-techniques/long-context/references/extension_methods.md +469 -0
  433. package/skills/ai-research/19-emerging-techniques/long-context/references/fine_tuning.md +612 -0
  434. package/skills/ai-research/19-emerging-techniques/long-context/references/rope.md +403 -0
  435. package/skills/ai-research/19-emerging-techniques/model-merging/SKILL.md +497 -0
  436. package/skills/ai-research/19-emerging-techniques/model-merging/references/coefficient-tuning.md +415 -0
  437. package/skills/ai-research/19-emerging-techniques/model-merging/references/evaluation.md +463 -0
  438. package/skills/ai-research/19-emerging-techniques/model-merging/references/examples.md +429 -0
  439. package/skills/ai-research/19-emerging-techniques/model-merging/references/methods.md +353 -0
  440. package/skills/ai-research/19-emerging-techniques/model-pruning/SKILL.md +495 -0
  441. package/skills/ai-research/19-emerging-techniques/model-pruning/references/wanda.md +348 -0
  442. package/skills/ai-research/19-emerging-techniques/moe-training/SKILL.md +526 -0
  443. package/skills/ai-research/19-emerging-techniques/moe-training/references/architectures.md +433 -0
  444. package/skills/ai-research/19-emerging-techniques/moe-training/references/inference.md +349 -0
  445. package/skills/ai-research/19-emerging-techniques/moe-training/references/training.md +426 -0
  446. package/skills/ai-research/19-emerging-techniques/speculative-decoding/SKILL.md +467 -0
  447. package/skills/ai-research/19-emerging-techniques/speculative-decoding/references/lookahead.md +310 -0
  448. package/skills/ai-research/19-emerging-techniques/speculative-decoding/references/medusa.md +351 -0
  449. package/skills/ai-research/20-ml-paper-writing/academic-plotting/SKILL.md +479 -0
  450. package/skills/ai-research/20-ml-paper-writing/academic-plotting/references/data-visualization.md +509 -0
  451. package/skills/ai-research/20-ml-paper-writing/academic-plotting/references/diagram-generation.md +395 -0
  452. package/skills/ai-research/20-ml-paper-writing/academic-plotting/references/style-guide.md +305 -0
  453. package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/SKILL.md +982 -0
  454. package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/references/checklists.md +348 -0
  455. package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/references/citation-workflow.md +563 -0
  456. package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/references/reviewer-guidelines.md +349 -0
  457. package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/references/sources.md +165 -0
  458. package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/references/writing-guide.md +477 -0
  459. package/skills/ai-research/20-ml-paper-writing/presenting-conference-talks/SKILL.md +298 -0
  460. package/skills/ai-research/20-ml-paper-writing/presenting-conference-talks/references/slide-templates.md +505 -0
  461. package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/SKILL.md +270 -0
  462. package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/references/checklist.md +279 -0
  463. package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/references/reviewer-guidelines.md +116 -0
  464. package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/references/section-blueprints.md +400 -0
  465. package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/references/systems-conferences.md +261 -0
  466. package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/references/writing-patterns.md +231 -0
  467. package/skills/ai-research/21-research-ideation/brainstorming-research-ideas/SKILL.md +384 -0
  468. package/skills/ai-research/21-research-ideation/creative-thinking-for-research/SKILL.md +366 -0
  469. package/skills/ai-research/22-agent-native-research-artifact/compiler/SKILL.md +245 -0
  470. package/skills/ai-research/22-agent-native-research-artifact/compiler/references/ara-schema.md +439 -0
  471. package/skills/ai-research/22-agent-native-research-artifact/compiler/references/exploration-tree-spec.md +125 -0
  472. package/skills/ai-research/22-agent-native-research-artifact/compiler/references/validation-checklist.md +149 -0
  473. package/skills/ai-research/22-agent-native-research-artifact/research-manager/SKILL.md +324 -0
  474. package/skills/ai-research/22-agent-native-research-artifact/research-manager/references/event-taxonomy.md +124 -0
  475. package/skills/ai-research/22-agent-native-research-artifact/research-manager/references/provenance-tags.md +190 -0
  476. package/skills/ai-research/22-agent-native-research-artifact/research-manager/references/session-protocol.md +162 -0
  477. package/skills/ai-research/22-agent-native-research-artifact/rigor-reviewer/SKILL.md +322 -0
  478. package/skills/ai-research/22-agent-native-research-artifact/rigor-reviewer/references/review-dimensions.md +182 -0
  479. package/skills/ai-research/SKILL.md +101 -0
  480. package/skills/ai-research/SOURCE +38 -0
  481. package/skills/ai-research/index/1-frame.md +18 -0
  482. package/skills/ai-research/index/2-data.md +21 -0
  483. package/skills/ai-research/index/3-train.md +48 -0
  484. package/skills/ai-research/index/4-measure.md +25 -0
  485. package/skills/ai-research/index/5-run.md +23 -0
  486. package/skills/ai-research/index/6-write.md +35 -0
  487. package/skills/ai-research/library.json +3456 -0
  488. package/skills/analyze-app/EVALS.md +82 -0
  489. package/skills/analyze-app/SKILL.md +188 -0
  490. package/skills/design-contract/EVALS.md +80 -0
  491. package/skills/design-contract/SKILL.md +171 -0
  492. package/skills/design-library/EVALS.md +85 -0
  493. package/skills/design-library/INDEX.md +59 -0
  494. package/skills/design-library/SKILL.md +58 -0
  495. package/skills/design-library/SOURCE +131 -0
  496. package/skills/design-library/adaptive-interfaces/skills/colour-independence/SKILL.md +90 -0
  497. package/skills/design-library/adaptive-interfaces/skills/flexible-typography/SKILL.md +83 -0
  498. package/skills/design-library/adaptive-interfaces/skills/information-density/SKILL.md +87 -0
  499. package/skills/design-library/adaptive-interfaces/skills/preference-audit/SKILL.md +70 -0
  500. package/skills/design-library/adaptive-interfaces/skills/responsive-accessibility/SKILL.md +86 -0
  501. package/skills/design-library/adaptive-interfaces/skills/responsive-review/SKILL.md +76 -0
  502. package/skills/design-library/adaptive-interfaces/skills/simplified-views/SKILL.md +97 -0
  503. package/skills/design-library/adaptive-interfaces/skills/specify/SKILL.md +63 -0
  504. package/skills/design-library/adaptive-interfaces/skills/user-preference-respect/SKILL.md +100 -0
  505. package/skills/design-library/cognitive-accessibility/skills/adaptive-personalisation/SKILL.md +61 -0
  506. package/skills/design-library/cognitive-accessibility/skills/assess-load/SKILL.md +48 -0
  507. package/skills/design-library/cognitive-accessibility/skills/cognitive-load-assessment/SKILL.md +60 -0
  508. package/skills/design-library/cognitive-accessibility/skills/contextual-help-design/SKILL.md +61 -0
  509. package/skills/design-library/cognitive-accessibility/skills/error-prevention-recovery/SKILL.md +71 -0
  510. package/skills/design-library/cognitive-accessibility/skills/focus-attention-design/SKILL.md +67 -0
  511. package/skills/design-library/cognitive-accessibility/skills/memory-load-reduction/SKILL.md +60 -0
  512. package/skills/design-library/cognitive-accessibility/skills/plain-language-design/SKILL.md +78 -0
  513. package/skills/design-library/cognitive-accessibility/skills/review/SKILL.md +56 -0
  514. package/skills/design-library/cognitive-accessibility/skills/simplify/SKILL.md +39 -0
  515. package/skills/design-library/cognitive-accessibility/skills/wayfinding-navigation/SKILL.md +64 -0
  516. package/skills/design-library/design-research/skills/behavioural-analytics/SKILL.md +33 -0
  517. package/skills/design-library/design-research/skills/qual-quant-triangulation/SKILL.md +33 -0
  518. package/skills/design-library/inclusive-interaction/skills/audit/SKILL.md +50 -0
  519. package/skills/design-library/inclusive-interaction/skills/design-flow/SKILL.md +58 -0
  520. package/skills/design-library/inclusive-interaction/skills/feedback-and-status/SKILL.md +76 -0
  521. package/skills/design-library/inclusive-interaction/skills/gesture-alternatives/SKILL.md +70 -0
  522. package/skills/design-library/inclusive-interaction/skills/keyboard-navigation/SKILL.md +99 -0
  523. package/skills/design-library/inclusive-interaction/skills/keyboard-review/SKILL.md +54 -0
  524. package/skills/design-library/inclusive-interaction/skills/motion-sensitivity/SKILL.md +79 -0
  525. package/skills/design-library/inclusive-interaction/skills/multi-modal-input/SKILL.md +70 -0
  526. package/skills/design-library/inclusive-interaction/skills/touch-target-design/SKILL.md +71 -0
  527. package/skills/design-library/inclusive-interaction/skills/voice-interaction/SKILL.md +68 -0
  528. package/skills/design-library/visual-critique/skills/critique-affordance/SKILL.md +45 -0
  529. package/skills/design-library/visual-critique/skills/critique-brand-consistency/SKILL.md +42 -0
  530. package/skills/design-library/visual-critique/skills/critique-color/SKILL.md +44 -0
  531. package/skills/design-library/visual-critique/skills/critique-composition/SKILL.md +46 -0
  532. package/skills/design-library/visual-critique/skills/critique-information-density/SKILL.md +45 -0
  533. package/skills/design-library/visual-critique/skills/critique-typography/SKILL.md +45 -0
  534. package/skills/design-library/visual-critique/skills/critique-visual-hierarchy/SKILL.md +40 -0
  535. package/skills/feature-audit/EVALS.md +83 -0
  536. package/skills/feature-audit/SKILL.md +326 -0
  537. package/skills/harness/EVALS.md +81 -0
  538. package/skills/harness/SKILL.md +88 -0
  539. package/skills/i-have-adhd/EVALS.md +80 -0
  540. package/skills/i-have-adhd/SKILL.md +183 -0
  541. package/skills/no-ai-slop/EVALS.md +89 -0
  542. package/skills/no-ai-slop/SKILL.md +209 -0
  543. package/skills/no-ai-slop/eval.md +52 -0
  544. package/skills/plan-add/EVALS.md +79 -0
  545. package/skills/plan-add/SKILL.md +179 -0
  546. package/skills/plan-add/render_table.py +72 -0
  547. package/skills/plan-status/EVALS.md +78 -0
  548. package/skills/plan-status/SKILL.md +52 -0
  549. package/skills/plan-sync/EVALS.md +80 -0
  550. package/skills/plan-sync/SKILL.md +69 -0
  551. package/skills/pm-frameworks/SKILL.md +33 -0
  552. package/skills/pm-frameworks/SOURCE +39 -0
  553. package/skills/pm-frameworks/intended-vs-implemented/SKILL.md +42 -0
  554. package/skills/pm-frameworks/opportunity-solution-tree/SKILL.md +64 -0
  555. package/skills/ponytail/EVALS.md +80 -0
  556. package/skills/ponytail/SKILL.md +124 -0
  557. package/skills/product-analysis/EVALS.md +103 -0
  558. package/skills/product-analysis/SKILL.md +361 -0
  559. package/skills/research/EVALS.md +104 -0
  560. package/skills/research/SKILL.md +570 -0
  561. package/skills/rl-env/SKILL.md +53 -0
  562. package/skills/rl-env/SOURCE +41 -0
  563. package/skills/rl-env/generate-nemo-gym-env/SKILL.md +169 -0
  564. package/skills/rl-env/generate-nemo-gym-env/references/architecture.md +114 -0
  565. package/skills/rl-env/generate-openenv-env/SKILL.md +183 -0
  566. package/skills/rl-env/generate-openenv-env/references/architecture.md +82 -0
  567. package/skills/rl-env/generate-ors-env/SKILL.md +209 -0
  568. package/skills/rl-env/generate-ors-env/references/architecture.md +113 -0
  569. package/skills/rl-env/generate-verifiers-env/SKILL.md +188 -0
  570. package/skills/rl-env/generate-verifiers-env/references/architecture.md +119 -0
  571. package/skills/rl-env/rl-env-from-description/SKILL.md +124 -0
  572. package/skills/rl-env/rl-env-from-description/references/interview.md +75 -0
  573. package/skills/rl-env/rl-env-from-description/references/nemo_gym.md +41 -0
  574. package/skills/rl-env/rl-env-from-description/references/openenv.md +35 -0
  575. package/skills/rl-env/rl-env-from-description/references/ors.md +50 -0
  576. package/skills/rl-env/rl-env-from-description/references/verifiers.md +39 -0
  577. package/skills/tezgah-contract/EVALS.md +78 -0
  578. package/skills/tezgah-contract/SKILL.md +792 -0
  579. package/statusline.py +129 -0
  580. package/workflows/graph-impact.js +153 -0
  581. package/workflows/graph-map.js +158 -0
  582. package/workflows/graph-review.js +170 -0
@@ -0,0 +1,831 @@
1
+ # Evidence
2
+
3
+ This page is the evidence layer: the [ledger](glossary.md#ledger) a session appends to, the kinds it
4
+ holds, the Stop rule that reads them to refuse a turn, and the pre-write snapshots a bad write can be
5
+ undone from. Read it before changing a rule that records or reads evidence, or when undoing a write.
6
+ [gate.md](gate.md) owns the refusal path, [hosts.md](hosts.md) what each host can observe.
7
+
8
+ ## The ledger
9
+
10
+ One append-only JSONL file per session at `<cache>/evidence/<slug>.jsonl`; the stem is a readable
11
+ prefix plus a hash of the session id, so a filename can never be turned back into one
12
+ (`hooks/tezgah_integrity.py::_slug`). Every writer goes through `note_path` (`hooks/tezgah_integrity.py::note_path`): `note()`
13
+ derives the path from the session id (`hooks/tezgah_integrity.py::note`). The row is built in exactly one place (`hooks/tezgah_integrity.py::note_path`), and its shape is
14
+ `{"kind": …, "ts": …, "v": …, "detail": …}` plus whatever `LEDGER_FIELDS` keys the writer knew — for a check
15
+ the host reported passing, `{"kind": "verify_ok", "ts": 1758000000, "v": 3, "detail": "pytest -q",
16
+ "id": "a1b2c3d4e5f6", "exit": 0, "out_bytes": 4312, "tool": "Bash", "repo": "/home/u/proj"}`. `v` names the shape the row was written under
17
+ (`ROW_VERSION`, `hooks/tezgah_integrity.py::ROW_VERSION`), and a reader folding a corpus across a version
18
+ change has to know what moved: at 2 the step vocabulary gained `interrupted`, so a version 1 row's
19
+ `verify_fail` may name a check that failed or a call the host stopped; at 3 a `claim` row is written
20
+ only for a reply in the claim vocabulary, so a version 2 `claim` row may be a work-only refusal.
21
+
22
+ `kind` is the event kind, `detail` is free text (the command, a path, a short reason) and `ts` is
23
+ epoch seconds. A **write row's** `detail` is the path the call wrote, from the gate's one reader of
24
+ every host dialect (`write_paths`, `hooks/tezgah_gate.py::write_paths`): `file_path`, `filePath`, `path`,
25
+ `notebook_path`, or an `apply_patch` body's first `*** Update File:` header — the paths
26
+ `changed_files()` (`hooks/tezgah_integrity.py::changed_files`) folds when a reader asks which files a session changed. `detail` is
27
+ credential-redacted **before** it is stored, over the whole text, and
28
+ truncated to `DETAIL_MAX = 200` only afterwards, so a marker the cut halves still reads as a marker
29
+ (`hooks/tezgah_integrity.py::note_path`, `hooks/tezgah_integrity.py::DETAIL_MAX`, `hooks/tezgah_integrity.py::_stored_text`): a named key keeps its name and loses its value - also as a quoted
30
+ JSON key (`"password": "x"`) and as a flag with its value after a space (`--password X`,
31
+ `--api-key X`, `mysql -pPASS`) - an `Authorization` scheme (`Bearer`, `Basic`, `Token`, `Digest`),
32
+ the password of URL userinfo (`scheme://user:pass@`) and of `-u user:pass`, and a prefixed token
33
+ family lose theirs (`hooks/tezgah_integrity.py::REDACTIONS`; audit L-6, which found each of those stored verbatim). The optional fields are exactly `LEDGER_FIELDS`
34
+ (`hooks/tezgah_integrity.py::LEDGER_FIELDS`) — `id`, `exit`, `out_bytes`, `fail_class`, `workspace`, `source`, `hash`, `changed`, `tool`,
35
+ `target`, plus the reply-shape names `lines`, `chars`, `items`, `longest_list`, `tr_share`, `answer_first` and the compaction
36
+ row's `summary_chars`, `summary_hash`, `constraint_found`, `constraint_expected`, the `attest`
37
+ row's `host` and `switches` and a `claim` row's `harness` — and
38
+ a key outside that set is dropped, a `None` value left out, because every reader treats a missing key
39
+ as `None` (`hooks/tezgah_integrity.py::note_path`). `tool` is the call's own name (`Bash`, `Write`, `mcp__codegen__status`),
40
+ written by `note_tool` (`hooks/tezgah_integrity.py::note_tool`) because `classify` folds the name into
41
+ a kind and drops it; it is what `_counts`' tool histogram counts and what the retirement report on
42
+ `tezgah-status --counters --trend` prints. `target` is on every `edit` row, and on a shell `run` row
43
+ whose command writes a file through a redirect or `tee` (`hooks/tezgah_gate.py::write_paths`): the
44
+ written path as an absolute real path, resolved against the call's cwd (`_abs_target`, written by
45
+ `note_tool` and by opencode's plugin through `absTarget`). `detail` keeps the path as the call spelled it, so
46
+ `README.md` in two repositories was one file to the concurrent-write guard; `writers_elsewhere`
47
+ now compares `target`, and a row without one (written before the field landed) is ignored by that
48
+ guard rather than matched by its spelling (audit M-6). Both writers write `tool` — `note_tool`, and opencode's
49
+ plugin, whose row carries the same field under the same empty-means-absent rule
50
+ (`hosts/opencode/plugins/tezgah.js:1230-1241`) — so no live host leaves it out. A row written *before*
51
+ the field landed names its tool only where the name survived in `detail` — an `unknown` row and an
52
+ MCP `external` row — so the one cause of an under-count is the corpus's age, and it shrinks as
53
+ sessions run. The append is one locked line, an exclusive `flock` with a 1 s bound falling
54
+ back to an unlocked write (`hooks/tezgah_integrity.py::_append`), and is best effort: a write failure is never the caller's.
55
+ A ledger is created `0600` in a `0700` directory, because its rows name the paths and commands of
56
+ the user's work (audit L-6 found them `0644`). Every reader skips a line that ends in a newline and
57
+ does not parse, in its own ledger or another's (`_parse` `hooks/tezgah_integrity.py::_parse`). The
58
+ reader used to raise there, and the guard then failed the Stop rule open for the turn, so corrupting
59
+ a `verify_fail` row let a claim through. Now the reader writes one `ledger_damage` row per damaged
60
+ line into that ledger, keyed on a digest of the line (`_note_damage`
61
+ `hooks/tezgah_integrity.py::_note_damage`). The Stop rule refuses a done-claim in a turn that holds one
62
+ as "evidence tampered". A tail with no newline is a fragment, not damage: `_append` cuts it before
63
+ its own write, so an honest writer never leaves one. Any other read error in another session's
64
+ ledger still costs only that ledger's rows (`_foreign_rows`; audit M-7).
65
+
66
+ What never reaches the ledger: tool result bodies (only `out_bytes`, a size,
67
+ `hooks/projects-posttooluse.py::result_size`), the prompt text (the `turn` row keeps `sha1(prompt)[:12]`,
68
+ `hooks/tezgah_integrity.py::note_turn`), read/search calls (`hooks/tezgah_integrity.py::note_tool`), and any credential, already replaced.
69
+
70
+ ## The kinds, by what reads them
71
+
72
+ A bare `:N` below is `hooks/tezgah_integrity.py`; `classify` (`hooks/tezgah_integrity.py::classify`) picks the kind for a call —
73
+ a write tool is `edit`, a shell call is `verify` when its command matches the check vocabulary `VERIFY`
74
+ (`hooks/tezgah_integrity.py::VERIFY`) and `run` otherwise.
75
+
76
+ | Kind | Written by | Read by |
77
+ |---|---|---|
78
+ | `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` |
79
+ | `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:1192-1270`) | 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 |
80
+ | `external`, `unknown` | `hooks/tezgah_integrity.py::note_tool` | the taint notice, via `source`; the `--trend` tool histogram; nothing counts them as work |
81
+ | `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:2516-2532`) | `hooks/tezgah_integrity.py::unanswered`, behind a claim in the Stop rule and in `counters.unanswered` |
82
+ | `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` |
83
+ | `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 |
84
+ | `after_block` | `hooks/tezgah_integrity.py::stop_reason`, on the reply after this rule's own block (`stop_hook_active` in a turn holding a `blocked:` claim or refusal row) on Claude, Codex 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 |
85
+ | `subagent_end` | `stop_reason(..., subagent=True)`, from Claude's SubagentStop (`hooks/hooks.json`) and Cursor's subagentStop `summary`; the evidence half only, never a block (ADR 011); `detail` as `after_block`'s | nothing yet: the rows plan 055 replays before a subagent end may block; `NOT_TOOL_HOOK` lists it. On Claude a subagent's tool rows sit in the parent's ledger, so until the agent key (plan 050) lands the row judges the parent's turn |
86
+ | `stop_spec` | `hooks/tezgah_stopspec.py::shadow`, from `stop_reason`, one per reply that leaves a claim or a refusal row, keyed like the claim row. The `detail` is `agree <where>: <class>`, `disagree <where>: <imperative> -> <spec>` (`ok` for an allow) or `error: <type>`. `<where>` is `fold` when the selector reached the fold and `selector` when it decided alone | `tests/stop_spec_eval.py --shadow-rows`, for plan 063's live agreement bar, read on the `fold` rows. It never feeds the verdict. `NOT_TOOL_HOOK` lists it |
87
+ | `deny`, `nudge` | the [gate](gate.md)'s `hooks/tezgah_gate.py::_deny`, first-nudge `hooks/tezgah_gate.py::decision` | `hooks/tezgah_integrity.py::counters` |
88
+ | `snapshot`, `rollback` | `hooks/tezgah_snapshot.py::_capture_one`, `hooks/tezgah_snapshot.py::restore` | `hooks/tezgah_integrity.py::_snapshot_hash`; no counter |
89
+ | `compact` | `hooks/tezgah_integrity.py::note_compaction`, from the post-compaction path (`tezgah_context.remember_compaction` `hooks/tezgah_context.py::remember_compaction`) | `hooks/tezgah_integrity.py::_counts` (what `counters` folds with) |
90
+ | `lesson` | `hooks/tezgah_context.py::note_lesson`, one row per lesson the budget left in a session block or a per-turn block, with its 8-hex `key` and `block` (`session` or `turn`), inside the host's `safe()` like the rest of the prompt path | no counter; `hooks/tezgah_context.py::NOT_TOOL_HOOK` keeps it out of `hooks/tezgah_context.py::_ledger_since`, so a session of lesson rows still reads as a gate that never ran |
91
+ | `lesson_tainted` | the gate's allow path for a write to a `.tezgah/lessons.md` (`hooks/tezgah_gate.py::lesson_taint`, from `decision` after every refusal) in a user turn that already holds a row carrying `source`, folded over `turn_rows` (that subagent's rows when the host names one). One row per lesson line the ledger will hold after the write and does not hold now, read off the post-write text, so a partial-line edit names the whole line; its 8-hex `key`, the channel in `source` and `detail`, the ledger in `target`. One row with no `key` when the gate cannot name the line (an `echo` append, an edit whose old text is not there, a removal). The keyed rows also go to the repository's index, which keeps only the ledger's current lines (`hooks/tezgah_lessons.py::write_taint`). Never a refusal (ADR 010); the dry run writes neither | the per-line data label on that lesson in both lesson blocks (`hooks/tezgah_context.py::LESSON_TAINTED`, read once per prompt through `hooks/tezgah_lessons.py::tainted`); no counter |
92
+ | `lesson_hit` | nothing yet: reserved for plan 061 Phase B, a compiled lesson check that matched a call in its observe stage, with the lesson's `key` and the call's `id` | nothing yet |
93
+ | `ledger_damage` | `hooks/tezgah_integrity.py::_note_damage`, from `_parse`, once per damaged line, with its 12-hex `key` | the Stop rule's first evidence class, "evidence tampered" (`hooks/tezgah_integrity.py::_stop_block`) |
94
+ | `disarm` | `hooks/tezgah_context.py::disarmed`, on the prompt a switch first appears on after the session's first prompt; `detail` is the switch name. Also the gate (`hooks/tezgah_gate.py::decision`), for a call it lets through that changes a `CONTROL_EVIDENCE` target - an open plan's delete or move, a forced `git add` of a `.tezgah/` path - with the call's `id` and `detail` `control: <what>` | the status line's `gate` mark ([status-line.md](status-line.md)) for the switch rows, set by the same check that writes them; the gate's rows are read by a person or a replay; no counter |
95
+ | `attest` | `hooks/tezgah_attest.py::run`, once per session start: Claude and dsh (`hooks/projects-auto-init.py::main`), Codex, Cursor and omp from their session-start events, opencode at the first message through `oncePerSession` (`bin/tezgah-context::main`). `detail` is `ok`, `drifted: <entries>` (an entry added, removed or changed since install, a hook file any user can write, a stale omp bridge, a changed entry script on a release install) or `unverified: <why>`; `host` names the host, `switches` the kill switches present. The module is imported only inside that call, so a broken one costs the row and never a gate | the `drift` status mark and the `harness` field of the session's later `claim` rows, read from one mark file per session and host (`hooks/tezgah_attest.py::drift_mark`, so one host's clean start cannot clear another's) - an annotation, never a Stop block; `NOT_TOOL_HOOK` lists it, so a session start after a compaction does not read as a gate that ran |
96
+ | `crash` | `hooks/tezgah_guard.py::safe` for a core call that raised, and `hooks/tezgah_guard.py::import_failed` for an entry point whose core imports raised (`detail` `import: <class>: <message>`). An import failure also writes one stderr line and the status line's `crash` mark, always; when `tezgah_integrity` or `tezgah_paths` is the module that failed, the row is the part that cannot be written. Hooks fail open with exit 0; `tezgah-gate check` exits 3 | `NOT_TOOL_HOOK` lists it; no counter |
97
+
98
+ **`compact` is what a compaction kept, from the record.** When the host hands the PostCompact
99
+ payload the text the model is about to receive — Claude's `compact_summary` — the shared path
100
+ (`hooks/tezgah_context.py::context_for`, reached by Claude's hook, codex/hook.py, omp's hook and dsh's
101
+ bridge alike, because it is the same funnel each prompt goes through) writes one row: the summary's
102
+ length (`summary_chars`), a 12-hex sha256 of it (`summary_hash`, so two compactions of one session can
103
+ be told apart and the same summary can be recognised twice), the host's own word for why it compacted
104
+ (`trigger`: `manual` or `auto`) on `detail`, and the constraint report. The summary's **text is never
105
+ stored** — it is the whole conversation by proxy and the ledger is a redacted channel — so a row can
106
+ never be read back as prose. The constraint report is `constraint_found` of `constraint_expected`: how
107
+ many of the constraint lines tezgah injects the summary still carries, counted against the very text the
108
+ block renders (`constraint_lines`, `hooks/tezgah_context.py::constraint_lines`, over `POINTER_LINE`
109
+ `hooks/tezgah_context.py::POINTER_LINE`, the active plan's front matter, and the object of each constraint the
110
+ user issued this session, kept in the turn stamp as its matched clause and never the prompt -
111
+ `hooks/tezgah_context.py::user_constraints`). It is a **report and never a refusal**: a compaction
112
+ that dropped a rule is a finding to report, not a turn to block. A host that hands no summary writes no
113
+ row, and `tezgah-status --counters` folds the rows into `compactions`, `compact_chars` (the newest
114
+ summary's length) and `compact_constraint_rate` — which stays `None` until one row carries both counts,
115
+ because a `0.0` would claim every compaction dropped every rule.
116
+
117
+ **`interrupted` is the step with no verdict.** The host said the call was *stopped* — a user's cancel,
118
+ or a call a policy denied before it ran — rather than reporting anything the tool answered, so the row
119
+ carries no `exit` and no `fail_class` (`note_tool()`, `hooks/tezgah_integrity.py::note_tool`, the fields
120
+ `hooks/tezgah_integrity.py::note_tool`). It counts as a step, because the model did issue the call and the turn's work has to
121
+ show; it is not a failed check, so `_partial_state`, `last_verify`, the error rate and `prior_calls`'
122
+ attempts (`hooks/tezgah_integrity.py::prior_calls`) all read it as a stopped call rather than a rejection.
123
+
124
+ **`began` opens a call.** The gate writes it for a write or shell call, with the call's `id`, before
125
+ any of its rules runs. A host that kills a slow gate still finds it there. The PostToolUse row of the same call carries
126
+ the same `id` and answers it. A `deny` with that `id` answers it too. That is the gate's own refusal,
127
+ or opencode's: it asks the core first and may still refuse the call with a rule of its own.
128
+ The replay sheet drops a `began` that a refusal answers (`refused-began`). A `began` row nothing answered is a call whose result
129
+ never reached the ledger. The host abandoned it, the user refused its prompt, or the post hook died. So
130
+ its outcome is unknown in both directions. It is never a pass, a success or a failure. It is not work
131
+ either. The gate writes it before the host's own permission layer, so a command the user refused
132
+ leaves one too. Such a turn did nothing, and its bookkeeping exemption stands. The row counts in one
133
+ place only: a reply that claims done or tested while a waiting call is a check. The gate marks that
134
+ on the row as `check`, read from the whole command, because the stored detail is cut at 200 characters.
135
+ That claim rests on a result nobody saw, so the Stop rule asks for a passing check (`no verify_ok`).
136
+ One answer closes one `began`, oldest first (`_began_fold`). A waiting call counts only
137
+ for a tool the host answered once in the session (`unanswered`). Some hosts gate a tool they never
138
+ report back: omp gates `powershell` and does not watch it. The cost is one miss: the session's first
139
+ call of a tool goes uncounted if the host abandons it. A ledger written before the row existed has
140
+ none, so it counts zero. The idea is gortex's: it abandons a call that overran, and the call's side
141
+ effect stays unknown until someone re-reads it.
142
+
143
+ **A pass with no `began` row is an orphan.** Every ledger reader pairs each `verify_ok` with a
144
+ `began` row (`hooks/tezgah_integrity.py::_pair`). That row shares the pass's `id` and carries `check`.
145
+ `events_path` and `turn_rows` call it. A pass with none came from outside the hooks (`python3 -c`),
146
+ or its call's rows went missing. The reader marks it in memory and never writes the mark.
147
+ `passing_check` refuses a marked row. So the freshness fold, the UI and design halves,
148
+ `scratch_evidence` and `tezgah-route --report` all read it as a check nobody saw pass. The Stop rule
149
+ refuses a done-claim in its turn as "evidence tampered", and `counters.orphans` counts it. A false
150
+ block refuses an honest turn, so the reader marks nothing in five cases. These are a ledger with no
151
+ `began` row before the pass, a turn with a `crash` row, and `pretooluse-off`. The others are an
152
+ append that took the unlocked fallback (its row carries `unlocked`) and the sandbox fallback cache.
153
+ A row with no outcome, such as Cursor's afterShellExecution `verify`, does not take a pass's `began`.
154
+ `turn_rows` seeds the waiting `began` rows from the 200 rows before the turn. So a call that straddles a
155
+ prompt pairs there as it does in `events`. A forged `began` row plus its pass stays invisible:
156
+ `SECURITY.md` names it.
157
+
158
+ **A shell call's `id` folds ASCII whitespace only.** Both `call_id` and `actionID` fold such runs
159
+ into one space (`hooks/tezgah_integrity.py::ID_SPACE`).
160
+ Python's `split()` and JS's `\s` disagreed on U+0085, U+001C-001F and U+FEFF, so a `began` row and its
161
+ outcome hashed apart. U+00A0 is no longer whitespace to either side. A command holding it hashes
162
+ differently from rows written before this change, which only matters to the repeat guards' history.
163
+
164
+ **The verify kinds are a tri-state, and an unread outcome is never a pass.** `note_tool`
165
+ (`hooks/tezgah_integrity.py::note_tool`) records `verify` when the host reported no outcome at all (`failed is None`) or when
166
+ the command is piped — a pipe's status belongs to its last stage, so `pytest | tail` proves nothing
167
+ about pytest — and only otherwise splits it into `verify_ok`/`verify_fail`. A line that opens with
168
+ `set -o pipefail` (or `set -euo pipefail`) and carries no `||` is not piped for this purpose: the
169
+ pipe's status is then its first failing stage's, so the host's verdict is the check's
170
+ (`hooks/tezgah_integrity.py::pipe_hides_status`). A check followed by `;` or a newline and more
171
+ commands records as `verify` too, and so does one sent to the background with `&`. `pytest; echo
172
+ done` exits 0 whatever pytest found. `pytest && echo ok` and `cd x && pytest` keep its status
173
+ (`hooks/tezgah_integrity.py::status_hidden`). The opencode plugin reads the same shapes (`statusHidden`). `passing_check`
174
+ (`hooks/tezgah_integrity.py::passing_check`) is stricter: a `verify_ok` counts only with `exit == 0`, a non-zero `out_bytes` (exit
175
+ 0 with an empty result is the classic silent failure) and no pipe or later command owning the status. The gate refuses the
176
+ trimmed form before it runs ([gate.md](gate.md), the `piped` rule). The `out_bytes` half
177
+ bites only where the host reported a result size — Codex (`hosts/codex/hook.py::main`), Cursor
178
+ (`hosts/cursor/hook.py::remember_answer,275`) and omp, whose bridge measures it and sends `result_len`
179
+ (`hosts/omp/tezgah-hook.ts.in:670-676`), now do — and 6 of 1423 `verify_ok` rows across 1454 local ledgers carry the field
180
+ (measured 2026-09-19), so an absent field still passes: the guard narrows a check whose
181
+ result was measured empty, it does not require the measurement. `last_verify`
182
+ (`hooks/tezgah_integrity.py::last_verify`) folds the ordered rows to `ok`/`fail`/`ran`/`None`, because a set cannot tell a failure
183
+ that came after a success from one that came before it.
184
+
185
+ **A check-shaped command is a check only when it checks something.** `_check_runs` reads each
186
+ `VERIFY` match. It reads the words after the match, up to the end of that one command. An information
187
+ form checks nothing: `--version`, `--help`, `--list`, `--collect-only`, `make help`, `just help`
188
+ and a bare `ruff`. It records as `run`. A formatter in its write mode records as `run` too:
189
+ `ruff format` without `--check`/`--diff`, `ruff check --fix`, `prettier --write` and `eslint --fix`.
190
+ The freshness fold reads that row as a change (`_change_row`), with no captured target.
191
+ `pytest --version; pytest -q` still runs a check. Every reader of `verify_command` follows. That
192
+ covers the evidence kind, the gate's retry exemption, its `began` `check` mark, `piped_check` and
193
+ the neuter rule. Opencode's `verifyCommand` carries the same three tables.
194
+
195
+ A check can say in its own output that it ran nothing (`EMPTY_RUN`): `collected 0 items`, `no
196
+ tests ran`, `Ran 0 tests` or `No tests found` at a line start. The reader scans the result's last
197
+ 4096 characters. Such a row records as `verify` with `empty_run`, never as a pass. One result
198
+ covers the whole call, so `pytest a && pytest b` with one empty suite marks the whole row empty.
199
+ That is a ceiling: the reader does not split the output per check. Claude, Codex
200
+ and Cursor read the result they already hold. The omp bridge keeps its own copy of the literal
201
+ and sends only the flag, never the body. `tests/test_omp_extension.py` pins the two copies equal.
202
+ A check row also carries `repo`, the git toplevel it ran in, read with no git fork. Only an
203
+ explicit location sets it. That is the tool's own `cwd` or `workdir`, or a leading `cd X`, also
204
+ after a paren or assignments. Path arguments that all sit in one repository count too. The
205
+ session cwd alone does not, because a shell may keep an earlier call's `cd`. An unreadable
206
+ `cd "$WT"` gives no `repo` either.
207
+ A row without one binds as before, so an unknown location never refuses. The Stop rule reads it
208
+ below.
209
+
210
+ **`edit` carries the write's after-state.** The gate's capture records the pre-write hash;
211
+ `_post_write` (`hooks/tezgah_integrity.py::_post_write`) adds `hash` (the target's sha256 once the host returned) and `changed`
212
+ (whether the two differ), so a call the host reports as a successful write need not have changed
213
+ anything. `changed_files` (`hooks/tezgah_integrity.py::changed_files`) reads exactly those rows.
214
+
215
+ **`claim` is the false-completion record.** `stop_reason` (`hooks/tezgah_integrity.py::stop_reason`) writes one row per reply per
216
+ turn that is in the claim vocabulary, deduplicated by `_claim_key` (`hooks/tezgah_integrity.py::_claim_key`), with detail `blocked: <class>` or `ok`: a refusal
217
+ and an allowed claim are both recorded, because the rate needs both halves. A blocked reply that
218
+ claimed nothing writes a `refusal` row instead. A `blocked: no verify_ok` row of either kind
219
+ carries `cause`. It reads `no check` when none ran and `outcome unread` when one ran without a
220
+ visible pass. **`external` and
221
+ `unknown` claim no step of work.** `external` (`hooks/tezgah_integrity.py::note_tool`) is a result with no work of its own — an
222
+ MCP answer, a fetched page — recorded so its provenance is on the ledger at all; an MCP row's
223
+ `detail` is that channel followed by the tool's own name, because the UI rule has to be able to tell
224
+ a screen read from a file read and the taint notice reads the channel from `source` either way.
225
+ `unknown` (`hooks/tezgah_integrity.py::note_tool`) is a tool name no list knows, its name in the `detail`. The step counter,
226
+ the Stop rule and the loop ceilings ignore both.
227
+
228
+ ## What a source has to record before its numbers count
229
+
230
+ A row is not evidence by itself: what a reader can do with it depends on how much
231
+ the thing that produced it recorded. The RL-environment tooling this repository
232
+ has read makes the same distinction at the model wire - a server that will not
233
+ return token ids can still serve rollouts, but they are marked *evaluation only*,
234
+ and asking one of them for training data raises instead of quietly returning a
235
+ weaker sample (FineEnvs multi-harness RL, its OpenEnv chapter, "What gets
236
+ recorded").
237
+
238
+ tezgah's version of that rule is already enforced in the research layer and is
239
+ stated here for the first time. A [claim](research.md) carries a `kind` and a
240
+ `proof` that names an artifact a reader can open, and the one case the claim
241
+ checker leaves out is a proof that names no artifact at all
242
+ (`hooks/tezgah_research.py::derive_kind`) - it is reported rather than labelled, because a
243
+ guessed kind would only move the refusal one step later. A source that cannot
244
+ meet the rule does not become a weaker claim: it is labelled for what it is, and
245
+ the work that produced it is the work that has to be redone.
246
+
247
+ ## The Stop rule, end to end
248
+
249
+ The checker is `_stop_block` (`hooks/tezgah_integrity.py::_stop_block`), reached through `stop_reason`
250
+ (`hooks/tezgah_integrity.py::stop_reason`). Four hosts block on it — Claude (`hooks/projects-stop.py::main`), Codex
251
+ (`hosts/codex/hook.py::main`), Cursor (`hosts/cursor/hook.py::dispatch`), omp
252
+ (`hosts/omp/hook.py::handle`) — all with `{"decision": "block", "reason": …}`, all inert outside a
253
+ [root](glossary.md#root) and under the `verify-off` [kill switch](glossary.md#kill-switch)
254
+ (`hooks/projects-stop.py::main`). On Claude, Codex and omp the rule judges the reply after a block
255
+ (`stop_hook_active`) once more, in record-only mode. That reply writes one `after_block` row and
256
+ never meets a second refusal. It writes nothing when the turn holds no refusal of this rule, since
257
+ another Stop hook may have blocked. Cursor still skips it. Ten triggers, in order, each naming its reason class (`_stop_block`
258
+ `hooks/tezgah_integrity.py::_stop_block`).
259
+ The first four judge how the reply is written (`_shape_block`, `hooks/tezgah_integrity.py::_shape_block`); the rest judge its evidence:
260
+
261
+ 1. **placating opener** — the reply opens by agreeing or apologising (`hooks/tezgah_integrity.py::SYCOPHANT`).
262
+ 2. **forbidden closer** — the reply's last prose line is one of the sign-offs the output contract bans (`CLOSER`, `hooks/tezgah_integrity.py`): the same rule read at the other end, with its own class so the ledger says which end fired.
263
+ 3. **list cap** — a contiguous list runs past `LIST_CAP` = 5 items (rule 8 of the `i-have-adhd` skill). `longest_list` (`hooks/tezgah_integrity.py::longest_list`) counts per run of column-0 items of one kind: a heading, a prose line, a table row, a fence, a marker switch or a numbered list restarting at 1 ends the run, and blank or indented continuation lines keep it. Two headed groups of four pass; a 5+ enumeration that must stay whole goes under headings or into a table, which the block text says.
264
+ 4. **reply language** — the reply's prose is not Turkish: at least `LANG_MIN_WORDS` = 25 prose words and under `LANG_MIN_SHARE` = 6% of them Turkish. `prose_words` drops fences, table rows, inline code, URLs, paths and identifiers first; `turkish_share` counts a word with a Turkish letter or one of `TR_WORDS` (`hooks/tezgah_integrity.py::TR_WORDS`).
265
+
266
+ The four shape classes share their switches with the text they enforce: `adhd-off` or a repo's `.no-adhd` lifts 1–3 (`_adhd_armed`, `hooks/tezgah_integrity.py::_adhd_armed`), `exec-mode.off` lifts 4, and a session whose environment carries `TEZGAH_NESTED` (an agent CLI consult started, whose English answer is read by code) is not judged for shape at all. A subagent's reply is never refused: omp's `session_stop` does not fire for task sessions, and a Claude SubagentStop or Cursor subagentStop leaves a record-only `subagent_end` row judged on the evidence half alone (ADR 011). The thresholds were set on the owner's omp transcripts (2026-09-27: 1,495 assistant replies with at least 25 prose words): English prose scored 0.000–0.026, the most English-heavy Turkish reply 0.077 and the bulk 0.3–0.7, and 24 of the 1,495 fall under the cut, all English or Chinese prose. The trade-off is on the Turkish side: a Turkish reply that is mostly quoted English outside backticks can fall under 6%, and the block text tells the model to put the English in backticks or a fence. `tests/test_integrity.py` `ReplyShapeCorpus` pins which realistic replies pass and which block. A lead that announces what follows (`preamble-open`) stays report-only: "Sonuç:" over a list is an answer label and reads like a preamble to any regex.
267
+
268
+ 5. **check failed** — the newest check in the session failed (`hooks/tezgah_integrity.py::_evidence_block`).
269
+ 6. **partial failure** — this turn recorded a `verify_fail` and nothing passed since (`hooks/tezgah_integrity.py::_partial_state`).
270
+ 7. **no ui_ok** — this turn changed a UI source (`hooks/tezgah_integrity.py::UI_PATH`) and the
271
+ check that passed was not one that sees the screen: a unit run never does. A browser/e2e/visual
272
+ check (`hooks/tezgah_integrity.py::UI_CHECK`) or a read of the rendered screen (`UI_TOOL`
273
+ `hooks/tezgah_integrity.py::UI_TOOL` for the app-analysis tool names, `hooks/tezgah_integrity.py::UI_TOOL_CMD` for the
274
+ CLI capture) is the evidence this class asks for, and it has to be newer than
275
+ the UI write it is about - not than the newest write of anything, so an unrelated file written
276
+ after the screen read does not stale that read (`hooks/tezgah_integrity.py::_ui_evidence`,
277
+ branch `hooks/tezgah_integrity.py::_evidence_block`). The write kinds are the freshness fold's own (`_change_row`: a write tool's
278
+ `edit` row or a shell call's `run` row the gate saw change the tree), so a UI source written
279
+ through a redirect owes the same proof. The MCP half of that proof is read off the row's own
280
+ tool name (`hooks/tezgah_integrity.py::_screen_read`), which is the only field that
281
+ says which call a row was - so a row that merely names a browser tool in its command
282
+ (`rg -n browser_snapshot docs/`) is not a read of anything; the CLI capture and the two checks
283
+ are read at a command position on the masked text, `re.M` so that a command on its own later
284
+ line of the same call counts. A component turn owes one thing more: when a changed UI source is
285
+ a component rather than a screen (`hooks/tezgah_integrity.py::DESIGN_COMPONENT` - a file
286
+ under a component/views/widgets
287
+ directory, or a name that carries the convention on its own), a fresh read of the screen is not
288
+ enough by itself and a `tezgah-design check` row has to be newer than the component write it
289
+ judges (`hooks/tezgah_integrity.py::_design_evidence`, branch `hooks/tezgah_integrity.py::_evidence_block`) - and it has
290
+ to be a check whose pass was seen (`passing_check`, `hooks/tezgah_integrity.py::passing_check`), because
291
+ a screenshot says what a component looks like and the contract is the only thing that says whether
292
+ it is on the repository's floor. The refusal names the command to run. Both of the checker's verbs
293
+ are in `VERIFY` (`hooks/tezgah_integrity.py::VERIFY`), so such a run reaches the ledger as a check like
294
+ any other; the verb this branch asks for is `check` - `derive` writes the floor, it does not apply
295
+ it. A screen is unchanged: the page a person looks at owes the read, not the contract.
296
+ 8. **stale evidence** — the newest check that passed ran before the newest write the gate saw change
297
+ the tree, so it verified an earlier revision of it (`_last_pass`/`_last_change`/`_stale_paths`
298
+ `hooks/tezgah_integrity.py::_last_pass`, `hooks/tezgah_integrity.py::_last_change`, `hooks/tezgah_integrity.py::_stale_paths`, branch `hooks/tezgah_integrity.py::_evidence_block`). A write counts as a change whether the gate saw it as a
299
+ write tool or as a shell command that redirected into the file - `_change_row` (`hooks/tezgah_integrity.py::_change_row`) reads
300
+ an `edit` row, a `run` row whose captured target moved, or a formatter's write mode - while a `verify*` row never does, so
301
+ a check redirecting its own log cannot stale itself. A write *outside* the workspace is not one
302
+ either: the fold's subject is the tree this reply is about, so `_post_write` records no
303
+ after-state for a target beyond the call's own root - a commit message in `/tmp` written after a
304
+ green suite is not a revision of that tree, and reading it as one refused an honest turn.
305
+ The fold dates a pass from the moment its check STARTED: its gate-written `began` row, paired
306
+ by `id`. A write that landed while the check ran is therefore newer than the tree it read. A
307
+ pass also counts only in the newest change's own repository. The fold compares the check row's
308
+ `repo` with the toplevel of the `edit` row's `target`. So `cd ../other && pytest` licenses no
309
+ change here. A row with no `repo` binds to nothing. That covers an old row and a host that sent
310
+ no cwd. A change with no `target`, such as a shell write, binds to nothing too.
311
+ 9. **no verify_ok** — this turn recorded a step (`edit`, `verify`, `verify_fail`, `run`,
312
+ `interrupted`) and no check passed in the session (`hooks/tezgah_integrity.py::_evidence_block`). A turn with no step at all
313
+ has only its words as the trigger. There a claim word inside a question or under a negation in
314
+ its own clause is no claim (`asserted_claims`). Examples: "testler geçti mi?", "is it done?",
315
+ "not tested yet", "tamamlandı değil". "Tamamlandı, push edeyim mi?" still claims.
316
+ 10. **no external read** — the reply states the state of a system tezgah does not own — a registry,
317
+ a release, a tag, a formula, a CI run — and no read of that system ran in the same turn
318
+ (`hooks/tezgah_integrity.py::_external_claim`, over `EXTERNAL_SYSTEM`/`EXTERNAL_STATE`
319
+ `hooks/tezgah_integrity.py::EXTERNAL_SYSTEM`, `hooks/tezgah_integrity.py::EXTERNAL_STATE` and the CI pair `EXTERNAL_CI`/`EXTERNAL_CI_STATE` `hooks/tezgah_integrity.py::EXTERNAL_CI`, `hooks/tezgah_integrity.py::EXTERNAL_CI_STATE`; branch `hooks/tezgah_integrity.py::_evidence_block`).
320
+ The two halves have to sit within `EXTERNAL_GAP` = 45 characters of each other on one line
321
+ (`hooks/tezgah_integrity.py::_external_pair`), and both are read on the reply's prose with inline code, paths,
322
+ URLs and identifiers blanked: `brew tap` inside a code span, the `.github/workflows/...` in a
323
+ citation and a URL ending in `/releases/tag/...` are text about a system, not a claim about its
324
+ state. A tagged release number beside a publish state is the second form (`EXTERNAL_VERSION`
325
+ `hooks/tezgah_integrity.py::EXTERNAL_VERSION`), and its `v` is required, so `SC 2.5.8` and `4.1.3` in prose are not claims and
326
+ neither is a bare version of tezgah's own code. The refusal names the command, chosen by the
327
+ subject the reply used (`hooks/tezgah_integrity.py::_external_command`, `hooks/tezgah_integrity.py::EXTERNAL_SOURCE`). A local
328
+ client is not the system: `npm --version` is not `npm view`, and a green unit run says nothing
329
+ about what a registry publishes. The read is the evidence, and it is taken by the row's command
330
+ and not by `passing_check` — `npm view` exiting non-zero is the answer for "this version is
331
+ missing" (`hooks/tezgah_integrity.py::_external_read_row`) — so a turn whose only work was the read ends. It is
332
+ last of the ten by the branch order above and in its strongest form: it is asked only where the
333
+ fold would otherwise let the turn end, so it turns an allow into a refusal and never changes the
334
+ class another branch refused the same turn under. It is the one class a turn with no work in it
335
+ can make, which is why the "no work, no claim word" exit exempts it (`hooks/tezgah_integrity.py::_stop_block`) — the two turns it
336
+ was written for ("npm 0.22.0 is missing", read off an out-of-date local npm client, and "make
337
+ NPM_TOKEN an automation token", which it already was) were advice-only, so before this class the
338
+ fold returned `(None, None)` over both and neither was judged at all. Measured over this machine's
339
+ own 2,092 final assistant replies, 2 are read as claims, both in review text about someone else's
340
+ tooling.
341
+
342
+ Classes 5–10 also exist as a past-time temporal spec (`hooks/tezgah_stopspec.py::FORMULAS`,
343
+ plan 063). Seven formulas read ten row atoms (`ROW_ATOMS`) and the turn marker. The module compiles
344
+ each formula to a one-pass monitor over the rows (`hooks/tezgah_stopspec.py::compile_table`), and the
345
+ order above is its decision list (`ORDER`). The spec runs in shadow. `stop_reason` asks it after the imperative
346
+ fold, inside its own `try`, when the reply leaves a claim or a refusal row. It writes one `stop_spec` row
347
+ per reply. The row says `agree`, `disagree` or `error`. It also says `fold` when the selector reached
348
+ the fold and `selector` when it decided alone. The verdict stays the imperative one. Both folds share one selector,
349
+ `_stop_block`, through its `fold` argument. It picks the rows, runs the lost-began path and
350
+ refuses "evidence tampered". `ESCAPES` names the three predicates that read beyond one row: the
351
+ began-row join, the repository binding and the lost-began set. Plan 063 fixed that list before
352
+ the first shadow row. `TEZGAH_STOPSPEC_STRICT=1` makes a disagreement raise, for the tests.
353
+ `tests/stop_spec_eval.py` measures the bet: agreement on plan 055's replayed Stop events and on
354
+ the live rows, the added latency, and generated mutants of the table.
355
+
356
+ The trigger for 5–9 is the turn's own evidence, not its words: a turn that did work and never saw a
357
+ check pass is refused whatever the reply says (`hooks/tezgah_integrity.py::_stop_block`). Two cases are judged against the
358
+ whole session instead of the turn:
359
+
360
+ - **A claim in a turn with no work.** A done/tested claim made in a turn that recorded no work row
361
+ is judged by the same fold as a turn (`_evidence_block`), run over the session rows before
362
+ this turn (`_before_turn`): every class the turn fold has - `check failed`, `no verify_ok`,
363
+ `stale evidence`, a pending UI or design check, a partial failure - applies to the session too.
364
+ A session that did no work at all still ends, and a turn that ran its own passing check is
365
+ judged by the turn fold alone. Before this, the claim could be moved to the turn
366
+ after the work, where the turn fold saw nothing to judge (audit M-2, INT-01).
367
+ - **A bookkeeping turn after a pass.** A turn whose only rows are read-only or VCS-bookkeeping
368
+ commands ends without a fresh check, as long as nothing but bookkeeping ran after the session's
369
+ newest pass, the session fold above allows it, and the reply makes no external-state claim
370
+ (`_settled`). The command is read raw, with bash quoting (`_shell_effect`): a substitution
371
+ inside double quotes, a redirect outside quotes and a process substitution disqualify it, and a
372
+ command the ledger cut at `DETAIL_MAX` characters is never bookkeeping (review F1, F2). A heredoc
373
+ is recognised only at an unquoted, uncommented `<<` that is not `<<<` (`_heredocs`), the one reader
374
+ every gate check uses, so a quoted `<<'X'` cannot hide the lines after it. Read-only is a program in
375
+ `READ_ONLY_PROGRAMS` (`ls`, `cat`, `grep`, `wc`, ...) or a git subcommand in `GIT_BOOKKEEPING`
376
+ (`status`, `log`, `diff`, `add`, `commit`, `push`, ...); a redirect, `$(` or a backtick
377
+ disqualifies the command. An edit, a failed check or any other command after the pass keeps the
378
+ turn rule. Without this, a commit-only turn was refused and the model re-ran checks that had
379
+ already passed (audit M-12, CHAT-04). The lists are short on purpose: a missing program costs one
380
+ refusal, while a writing program wrongly listed would excuse an unverified change.
381
+
382
+ What lets the turn end is the absence
383
+ of both — no work row and no claim vocabulary (`hooks/tezgah_integrity.py::_stop_block`), the one shape class 10 is exempt from
384
+ — or a `passing_check` row newer than the newest write seen to change the tree (`hooks/tezgah_integrity.py::_evidence_block`), where
385
+ a fresh screen proof stands in the same
386
+ place as a unit pass; when that write was a UI source, the passing row has to be a UI proof — a
387
+ check that renders, or a read of the screen — and when it was a component, the design check has to be
388
+ newer than that write as well. An explicit admission (`doğrulanmadı`,
389
+ `unverified`, `not verified`, `couldn't verify`; `hooks/tezgah_integrity.py::NEGATED`) clears the rule (`hooks/tezgah_integrity.py::_stop_block`),
390
+ checked after the shape branches and before the evidence triggers. The block text is the string the
391
+ refusing branch returns; it names the failed
392
+ command (`hooks/tezgah_integrity.py::_failed_check`) and tells the model to report the failure with its exact error
393
+ line, or fix it and re-run.
394
+
395
+ **The escape hatches, and the deny that answers each.** The gate refuses these before they run, under
396
+ the same `verify-off` switch (`hooks/tezgah_gate.py::decision`), as rule `shortcut`:
397
+
398
+ - `--no-verify` on a git/commit/push-style command (`hooks/tezgah_integrity.py::NO_VERIFY`, `hooks/tezgah_integrity.py::GITISH`) —
399
+ `hooks/tezgah_integrity.py::shortcut_command`.
400
+ - an env that skips the hooks — `SKIP=`, `HUSKY_SKIP_HOOKS=`, `HUSKY=0` — again requiring the git/hook
401
+ context, so a read that merely mentions `SKIP=` passes (`hooks/tezgah_integrity.py::SKIP_ENV`, `hooks/tezgah_integrity.py::_shortcut_command`).
402
+ - a `core.hooksPath` assignment in the same command as a `git commit`/`git push` — `git -c
403
+ core.hooksPath=/dev/null commit`, `git config core.hooksPath "$D" && git commit`, `--config-env`, the
404
+ `GIT_CONFIG_KEY_n`/`GIT_CONFIG_PARAMETERS` env (`hooks/tezgah_integrity.py::_hooks_redirect`);
405
+ a standalone `git config core.hooksPath .githooks` passes. Set in one call and committed in the next
406
+ is not seen: the rule reads one command line.
407
+ - a check chained so it cannot fail: `|| true`, `; true`, `|| exit 0`, `|| :` (`hooks/tezgah_integrity.py::NEUTER`,
408
+ `hooks/tezgah_integrity.py::_shortcut_command`).
409
+ - a newly added test skip/xfail in a test file (`hooks/tezgah_integrity.py::SKIP_TEST`, path gate `hooks/tezgah_integrity.py::TEST_PATH`,
410
+ per-marker count `hooks/tezgah_integrity.py::_added`, `hooks/tezgah_integrity.py::shortcut_edit`). Rewriting an existing skip in place
411
+ passes; one more does not.
412
+
413
+ Both scans run on text whose strings, comments and heredoc bodies are blanked (`hooks/tezgah_integrity.py::mask`), so
414
+ a commit message that *describes* `--no-verify` is not a bypass while the flag in command position
415
+ is. Every denial is itself a `deny` row.
416
+
417
+ ## The session store for the status marks
418
+
419
+ `<cache>/sessions/<slug>.jsonl`, written by `record()` (`hooks/tezgah_context.py::record`) and read
420
+ by `used()` (`hooks/tezgah_context.py::used`). A row is exactly `{"kind": kind}` — no timestamp, no outcome, no session —
421
+ and the kinds are the used-tool marks [status-line.md](status-line.md) lights up (`graph`, `consult`,
422
+ `research`, `judge`), plus one kind per shipped skill a read opened. It is separate from the
423
+ [ledger](glossary.md#ledger) because it is display state, not
424
+ evidence: nothing refuses a call on it, a kind that is not one of tezgah's is not written at all
425
+ (`hooks/tezgah_context.py::record`), and the reader wants a set of kinds rather than an ordered,
426
+ turn-scoped history. The ledger pays a redaction scan and a lock per row; a mark needs neither. The
427
+ one mark that is also evidence is `orch`: `record()` writes it as an `orch` row in the session's
428
+ ledger too (`hooks/tezgah_context.py::record`), because a subagent event reaches no other ledger
429
+ writer and `fanout` is folded from the ledger.
430
+
431
+ **Which skill a read opened.** `skill_read_kind` (`hooks/tezgah_context.py::skill_read_kind`) earns the mark
432
+ the status line draws for the two skills the always-on core tells a session to read (`SKILL_MARKS`:
433
+ `pony` for `ponytail`, `adhd` for `i-have-adhd`) and `skill:<name>` for any other *shipped* skill -
434
+ one read from the checkout's `skills/` (`hooks/tezgah_context.py::shipped_skills`), so an
435
+ unshipped name earns nothing, which is what `skill://other` always got. `SKILL_MARKS` itself is not
436
+ widened: a mark whose skill the always-on core never names can never flip, and
437
+ `tests/test_context.py::MarkedRulesNameTheirSkill` requires every entry to be named there. A `skill:` kind is
438
+ therefore invisible to the line and its legend - no mark's measure is spelled that way - while
439
+ `skill_fitness(window)` (`hooks/tezgah_context.py::skill_fitness`) reads it back for the one question the
440
+ line never asked. Three surfaces recognise a read, and they have to agree on the two forms
441
+ (`skills/<name>/SKILL.md` and `skill://<name>`) and on which name is shipped: the Python hook omp's
442
+ bridge calls (`hosts/omp/hook.py::classify`), omp's own filter, which decides whether python hears about the
443
+ read at all (`hosts/omp/tezgah-hook.ts.in:225-262`, its catalogue the checkout `@HOOK@` names), and
444
+ opencode's plugin, which classifies in process because that host has no Python hook
445
+ (`hosts/opencode/plugins/tezgah.js:2141-2198`, its catalogue the host's own installed skill dir
446
+ (`dirname(CONFIG)/opencode/skills`), which `tezgah-setup` fills with every shipped skill).
447
+
448
+ Claude loads a skill through its `Skill` tool, never a read, so a Claude load used to leave no row.
449
+ The same function now maps a `Skill` call to the same kind. The call carries
450
+ `{"skill": "<name>"}`, and a plugin skill arrives as `tezgah:<name>`. The plugin's PostToolUse
451
+ matcher carries `Skill` (`hooks/hooks.json`), and `projects-posttooluse.py`'s `used_kind` records
452
+ it. Nobody has checked that Claude fires PostToolUse for the Skill tool. `tests/test_context.py`
453
+ proves the hook side only.
454
+
455
+ **The fitness report.** `tezgah-status --skill-fitness` prints, per shipped skill, how many of the
456
+ recorded sessions opened it, and names the ones none did: a skill is a dependency that has to keep
457
+ earning the context lines it costs, and accretion is invisible from reading the skill itself. It is a
458
+ measurement, not a gate - it names the candidates for retirement, and deleting one stays the owner's
459
+ call. Three ceilings are honest parts of the number, not bugs: the window is the newest
460
+ `FITNESS_WINDOW = 200` session files by mtime, because a row carries no timestamp; a session counts
461
+ as having opened a skill when it recorded that skill's kind, so reads recorded before `skill:` existed
462
+ still count through the two marks; and only the hosts that classify a read in process record one
463
+ here, so the count is a floor, not a census. Which host records what, since this store is the
464
+ report's only source: **omp** (the extension's filter lets the read through,
465
+ `hosts/omp/tezgah-hook.ts.in:255-262`, and the hook classifies it, `hosts/omp/hook.py::classify`) and
466
+ **opencode** (the plugin classifies it, `hosts/opencode/plugins/tezgah.js:2183-2198`) record the mark
467
+ or `skill:<name>` for every shipped skill, in either form; **Claude** sees a read, but only in its
468
+ transcript, which feeds the status line and writes no row here (`statusline.py::claude_used`), so a Claude
469
+ session reads in this report as one that opened nothing - marks included; **codex**, **cursor** and
470
+ **dsh** record no read at all (cursor's `classify` has no skill branch; dsh runs the shared hook whose
471
+ `used_kind` knows no skill kind), and [status-line.md](status-line.md) owns which surface can see a
472
+ read for the marks. Both in-process mirrors take the same two forms and the same shipped-name rule as
473
+ `skill_read_kind`, so a read is recorded on every host that can see one; a host that records none is
474
+ a recording gap, not a skill nobody opened.
475
+ The two marked skills are the only ones any host recorded before `skill:<name>` landed, so the first
476
+ report after this change reads mostly as a recording gap and fills in as sessions run; it says so on
477
+ its own line rather than in a footnote nobody opens.
478
+ The heavier half the mechanism names - a with/without lift measurement against a real oracle - is
479
+ deliberately not here.
480
+
481
+ ## Snapshots and rollback
482
+
483
+ Before a write is allowed, `capture` copies the current bytes of every file the call names into
484
+ `<cache>/snapshots/<id>/file`, `meta.json` beside it (`hooks/tezgah_snapshot.py::_store`, `:75-80`,
485
+ `hooks/tezgah_snapshot.py::_capture_one`), and appends one `snapshot` row whose `detail` is the resolved path, `id` the 12-hex
486
+ snapshot id, `hash` the sha256 and `out_bytes` the size (`hooks/tezgah_snapshot.py::_capture_one`). The row is written last, so it
487
+ never names a copy that is not on disk. A credential file (`SECRET_FILE`: `.env*`, `*.env`, key and
488
+ certificate files, `id_rsa`-style keys, `credentials.json`, `.netrc`, `.npmrc`, `.pypirc`, `.pgpass`,
489
+ `.git-credentials`) gets the row alone - path, size and sha256, no `id` and no copy - so a snapshot
490
+ never duplicates a secret, and `rollback` lists it as not restorable (audit L-6). Snapshot files
491
+ are written `0600` in `0700` directories. Every host calls `capture` in process except opencode, whose
492
+ JavaScript plugin reaches it through `bin/tezgah-capture` (`bin/tezgah-capture:1-20`).
493
+ The core captures a call put to `tezgah-gate decide` itself, so the plugin skips it.
494
+
495
+ The store is capped twice (`hooks/tezgah_snapshot.py:34-53`): `CAP = 200` snapshots, oldest evicted by directory mtime when a
496
+ capture crosses it (`hooks/tezgah_snapshot.py::CAP`, `hooks/tezgah_snapshot.py::_evict`), and `MAX_BYTES = 2 MiB` per file, above which
497
+ **nothing is captured at all** — an over-large file is skipped because `capture` runs synchronously in
498
+ the gate on the path of the very write it protects, so copying gigabytes would stall that call, and a
499
+ refused capture writes no row and so claims no copy (`hooks/tezgah_snapshot.py:46-53`, `hooks/tezgah_snapshot.py::_capture_one`).
500
+
501
+ `restore` (`hooks/tezgah_snapshot.py::restore`) has exactly one caller, `bin/tezgah-rollback`, which a user runs:
502
+ `tezgah-rollback <snapshot-id> [--force]` (`bin/tezgah-rollback::main`). It refuses an unknown or
503
+ malformed id, stored bytes that do not match the recorded hash, and a file that has changed since the
504
+ capture — that last one only until `--force`, and the `rollback` row records that it was used
505
+ (`hooks/tezgah_snapshot.py::restore`). The id to pass is on the `snapshot` ledger row for that write (`_snapshot_hash`
506
+ `hooks/tezgah_integrity.py::_snapshot_hash`).
507
+
508
+ `--session <id>` widens that command to a whole session: for every path the session's writes
509
+ touched it puts back the EARLIEST snapshot the session took of it — the state before the session's
510
+ first write of that path. `session_plan` (`hooks/tezgah_snapshot.py::session_plan`) is that reading: it
511
+ walks the session's rows in order, names every path an `edit` or shell row wrote (a snapshot row
512
+ whose path no write row named — the second file of an `apply_patch` body — is there too), and joins
513
+ each to the session's earliest `snapshot` row for it, carrying an `action` that says what the
514
+ rollback would do with it: `restore` for a path a write tool changed, `list (shell only)` for a path
515
+ only a shell command's redirect touched, `list (unknown writer)` when a shell row's
516
+ target could not be re-read so the writer is not known, `list (no snapshot)` for one with no pre-state at all — a
517
+ file the session created. Only the `restore` entries are put back
518
+ (`hooks/tezgah_snapshot.py::restore_session`): which file a command wrote is read off its
519
+ text rather than reported by a tool, so a shell-touched path is listed and never reverted even where
520
+ the gate captured its target, and the id is printed for a deliberate single-id restore. A relative
521
+ target is resolved against the paths the ledger has already resolved — the snapshot rows' own, which
522
+ the gate resolved against the call's cwd (`hooks/tezgah_snapshot.py::_row_path`). `--dry-run`
523
+ prints the plan as `path<TAB>id<TAB>action` and writes nothing: no ledger row, no store change.
524
+
525
+ The moved-on check is `restore`'s own, fed the session's last recorded hash of the path: the file the
526
+ session left behind is what its earliest snapshot is compared with, so the session's own later writes
527
+ need no `--force`, while a write by somebody else after the session's last one still refuses. One
528
+ refusal does not stop the others — each path is its own file and its own decision — and the exit code
529
+ is 1 when any was refused.
530
+
531
+ At the end of a turn the same set is named where a host can show text without blocking the turn:
532
+ Codex's Stop `systemMessage` carries `changed_files_notice`
533
+ (`hooks/tezgah_integrity.py::changed_files_notice`), the turn's `changed_files` as one sorted line, capped at
534
+ `CHANGED_NOTICE_MAX` names plus a count of the rest. Claude's and omp's Stop output returns a
535
+ decision and nothing else and Cursor's block is a follow-up, so those three name no files: the set is
536
+ named to be acted on by the user, never to hold the turn.
537
+
538
+ **Nothing rolls back automatically, anywhere.** A hook that undoes work can destroy more than the
539
+ failure it answers, and its trigger would be a guess about intent wearing a check's clothes
540
+ (`hooks/tezgah_snapshot.py:10-18`; `hooks/tezgah_integrity.py::partial_state`). Repair is the model's or
541
+ the user's: fix and re-run, or reach for a snapshot deliberately.
542
+
543
+ ## Untrusted content
544
+
545
+ A result that arrived from outside the user and this workspace carries a provenance label on the
546
+ result itself: `untrusted_label` (`hooks/tezgah_integrity.py::untrusted_label`) names the channel — a web
547
+ result (`hooks/tezgah_integrity.py::WEB_TOOLS`), an MCP server (`hooks/tezgah_integrity.py::untrusted_source`), a network read (`hooks/tezgah_integrity.py::NETWORK_READ`: `curl`, `wget`, `gh api`, `gh issue view|list`, `gh pr view|diff|checkout|list`, a `git clone` of a non-local source, a `git pull|fetch` that names a URL, also behind `sudo`, `git -C dir` or an `X=1` prefix) or a
548
+ model on the far side of the network (`hooks/tezgah_integrity.py::TIER_PROGRAMS`: a `bin/consult`/`bin/codegen`
549
+ invocation that reaches a provider) — and tells the model to treat instructions inside it as data.
550
+ The call's own row carries the channel in `source` (`hooks/tezgah_integrity.py::note_tool`).
551
+
552
+ After that read, the first effect the turn makes — a shell call, a write, or an MCP call of any verb
553
+ class (`hooks/tezgah_untrusted.py::effectful`, `hooks/tezgah_integrity.py::mcp_class`) — carries a taint notice instead (`hooks/tezgah_untrusted.py::marks`,
554
+ `hooks/tezgah_untrusted.py::taint_notice`, `hooks/tezgah_untrusted.py::turn_channel`) — which reads the ledger through `turn_rows`
555
+ (`hooks/tezgah_integrity.py::turn_rows`): the whole file's lines, but only the current turn's rows
556
+ parsed, so a taint check costs the length of the turn and not the length of the session. It names
557
+ the turn, never a cause: whether the
558
+ fetched page *caused* the write is not something a hook can see (`hooks/tezgah_untrusted.py:14-17`). One notice per read, and
559
+ the effect's own row then carries the channel, so the taint is a transition rather than a repeat.
560
+ An MCP effect after another channel's read carries both lines. Its result came from the server, so
561
+ it keeps the label. Its row carries the `mcp` channel, which takes the inherited channel's place.
562
+ After an MCP read it carries the label only, because the label already names that channel.
563
+
564
+ Subagents of one Claude session write one ledger, so one sibling's web read used to taint every
565
+ sibling's effects. Claude's hook payload carries `agent_id` on a call a subagent makes, and
566
+ `hooks/projects-posttooluse.py` writes it into the row's `agent` field. `turn_channel` and
567
+ `turn_rows` then read only that agent's rows, and the gate's repeat ceilings count only that
568
+ agent's attempts (`prior_calls` `hooks/tezgah_integrity.py::prior_calls`). The parent (no `agent_id`)
569
+ still reads the whole turn, because its subagents' work is its turn. Hosts whose payload tezgah
570
+ reads no agent key from still share one ledger's taint; omp writes one ledger per subagent.
571
+
572
+ The taint is a notice, not a refusal: the gate's sink rule, which held an effect in such a turn
573
+ until the user's own approval was on the ledger, was removed with the consent rule
574
+ ([gate](gate.md)). The
575
+ label reaches the model on every host that has a surface for it, and the taint notice with it:
576
+ Claude and dsh through `hooks/projects-posttooluse.py::main`, Codex (`hosts/codex/hook.py::main`),
577
+ Cursor (`hosts/cursor/hook.py::dispatch`), omp (`hosts/omp/hook.py::handle`, which calls `marks` with an
578
+ empty stand-in for the result body its bridge never sends, so a subagent's report keeps its label), and opencode, whose plugin
579
+ cannot import the core in process and mirrors the control in JavaScript instead — the channel on the
580
+ call's own row, the label and the taint notice in front of the result the hook is handed, including
581
+ the `external` row an MCP answer or a fetched page earns (`untrustedSource`
582
+ `hosts/opencode/plugins/tezgah.js:1898`, `labelResult` `:1972`, with the tier's argv reader
583
+ `tierRead` at `:1881`). The two halves are pinned against each other over a shared corpus, so neither
584
+ 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:
585
+ opencode's plugin writes that `external` row itself and carries the channel alone, since the UI rule
586
+ `_screen_read` belongs to the Python half and does not run there.
587
+
588
+ ## The counters a maintainer reads
589
+
590
+ `tezgah-status --counters [session] [path]` (`bin/tezgah-status::main`) prints `counters(session)`
591
+ (`hooks/tezgah_integrity.py::counters`) over one session's whole ledger, and `tezgah-status --counters
592
+ --all` prints `counters_all()` (`hooks/tezgah_integrity.py::counters_all`) over every real-session ledger on the machine, adding `ledgers`, the
593
+ number of files it read, and `fixtures`, the ledgers left out because every workspace they name is a temp, OpenResearch run or arm-bench tree (`fixture_ledger`). Both fold their rows through `_counts` (`hooks/tezgah_integrity.py::_counts`), the one implementation
594
+ of the arithmetic, so a total cannot drift from the sessions it sums - the `:NNN` rows below are that
595
+ fold. `counters_all` bounds nothing: a window or a row cap would make the total contradict the
596
+ per-session numbers it claims to be, and the whole corpus here folds in 0.4 s (58,928 rows, 1,120
597
+ real ledgers, measured 2026-09-30).
598
+
599
+ Each key, as both readers produce it:
600
+
601
+ - `events` — every row; `kinds` — a histogram of them.
602
+ - `steps` — rows whose kind is in `STEP_KINDS` (`hooks/tezgah_integrity.py::STEP_KINDS`): work rows only,
603
+ `interrupted` among them, since a call the host stopped was still issued.
604
+ - `unanswered` — the `began` rows no outcome answered (`unanswered`): calls whose result nobody saw.
605
+ It is in no rate. `counters_all` sums it per ledger, so one session's answer never closes another's call.
606
+ - `tool_error_rate` — non-zero `exit` values over every row carrying an `exit` (`hooks/tezgah_integrity.py::_counts`);
607
+ a host reporting no outcome contributes to neither half, so every row with an `exit` counts.
608
+ - `claims` and `false_completion` — the `claim` rows, which are replies in the claim vocabulary,
609
+ and those whose detail starts with `blocked` (`hooks/tezgah_integrity.py::_counts`). A shape class (`SHAPE_BLOCKS`) is
610
+ the exception. A reply refused for its list or its language made no false claim, so it counts
611
+ as `shape_blocked` instead.
612
+ - `refusals` — the `refusal` rows: refused replies that claimed nothing, work-only or shape. A
613
+ shape one also counts in `shape_blocked`. Before row version 3 these were `claim` rows, so a
614
+ corpus folded across the boundary counts them in `claims`.
615
+ - `blocked_claims` — `false_completion` split by its Stop class, the text after `blocked: `
616
+ (`no verify_ok`, `stale evidence`, `no external read`, …), so each class has its own count.
617
+ - `replies` and `shape` — the `shape` rows, written for every judged reply, and those carrying a
618
+ report-only flag (`hooks/tezgah_integrity.py::_counts`).
619
+ - `denies` — `deny` rows grouped by the text before the first colon (`hooks/tezgah_integrity.py::_counts`), which is the rule
620
+ name (`shortcut`, `loop`, `race`, …); `nudges` and `fanout` — the nudge rows and
621
+ the subagent-ish kinds (`hooks/tezgah_integrity.py::_counts`), the `orch` rows among them written by `record()`
622
+ for every subagent event a Python adapter sees.
623
+ - `denies_reissued` — per deny rule, the denied calls that came back (`_reissued`). A later row of
624
+ the same ledger carries the deny's `id`: the model made the call again. `tezgah-status --counters`
625
+ prints it beside the denies as `rule=reissued/denies rate`. A rule is kept or dropped on this
626
+ rate. For `drift` a high rate is the design: it refuses once, then lets the same call through. For
627
+ any other rule it means the model worked around the refusal.
628
+ - `consult`, `codegen`, `codegen_failed` — substring matches on `detail` (`hooks/tezgah_integrity.py::_counts`).
629
+ - `weeks`, `tools`, `programs` — present only when the caller asked (`counters(..., weeks=True,
630
+ tools=True)`), which is what `tezgah-status --counters --trend` passes; see below.
631
+
632
+ **`false_completion / claims`** is how often the rule refused a reply that claimed completion or
633
+ verification. It is one reading among the counters, not the layer's effect. A refusal the model
634
+ then repaired and a refusal it argued past count the same. The `after_block` rows record that
635
+ difference. One ledger is an anecdote. `--counters --all` gives the same ratio over the corpus. A
636
+ published value names the command, the date and the ledger count it ran over. Prose never
637
+ restates a number, because the counters' meaning moves with the row version. At version 3
638
+ work-only refusals left `claims`.
639
+
640
+ ### The drift series and the firing histograms
641
+
642
+ `tezgah-status --counters --trend [--weeks=N]` prints two reports the same fold carries, because a
643
+ value is a reading and the thing worth watching is the population over time. Both are filled inside
644
+ `_counts` (`hooks/tezgah_integrity.py::_counts`) in the same pass as the totals, so neither can
645
+ disagree with the number it is drawn from; both are off unless the flag asks, so the plain and the
646
+ `--json` output of a reader who did not ask are byte-identical to what they were.
647
+
648
+ - **The drift series** — `weeks`, every row bucketed by `ts` on a fixed 7-day grid (`WEEK`, anchored
649
+ on the Monday of the epoch's first week, `hooks/tezgah_integrity.py::_week`), each bucket
650
+ counting its events, claims, refused claims and decided attempts. `drift_series(counters, weeks)`
651
+ (`hooks/tezgah_integrity.py::drift_series`) re-slices them into the last `weeks` calendar weeks, oldest
652
+ first, with `false_completion/claims` and `tool_error_rate` per bucket, and the direction of the
653
+ newest three weeks that carry a denominator (`hooks/tezgah_integrity.py::_direction`, compared by
654
+ cross-multiplication so a shared rounding is never called flat). A week with no row prints a zero
655
+ row count and `n/a` for both ratios, never `0.0`: an empty week is not a week with a perfect rate,
656
+ and a gap has to read as a gap. Nothing is windowed out of the totals.
657
+ - **The tool firings** — `tools`, a histogram over `_tool_name(entry)` (`hooks/tezgah_integrity.py::_tool_name`):
658
+ the row's `tool` field, else the name an `unknown` row (`unknown tool: <name>`) or an MCP `external`
659
+ row (`mcp <name>`) kept in `detail`. A work row written before the `tool` field landed carries no
660
+ name at all - `classify` folded it into a kind - so an old corpus under-counts, which is the
661
+ honest ceiling and the reason the field exists; every row written since carries it, because both
662
+ writers write it (`hooks/tezgah_integrity.py::note_tool`, and opencode's plugin
663
+ `hosts/opencode/plugins/tezgah.js:1230-1241` - before that second one did, an opencode work row was
664
+ the other half of this under-count, with its name unrecoverable in the command `detail`). A read
665
+ tool is not in it either: reads record no row by design.
666
+ - **The shipped programs** — `programs`, the `bin/` programs a command row really ran, read with the
667
+ tokenizer the status line already uses (`hooks/tezgah_integrity.py::_ran_programs`), and
668
+ `unfired_programs(counters)` (`hooks/tezgah_integrity.py::unfired_programs`), the catalog minus that set. The absence is the
669
+ evidence: a tool nobody calls leaves no row, so the only way to name it is a catalog, and the one
670
+ catalog this layer holds is its own `bin/` (`hooks/tezgah_integrity.py::shipped_programs`). The prefilter is one
671
+ regex per catalog and the tokenizer runs only on a row that mentions a shipped name, which is why
672
+ the tool histogram costs about 0.6 s over the whole corpus where the plain fold costs 0.4 s (58,928
673
+ rows, measured 2026-09-30). A
674
+ program reached through an interpreter (`python3 bin/consult q`) counts as never fired, the same
675
+ ceiling `shell_kind` has and for the same reason.
676
+
677
+ **The MCP half of a retirement decision is manual, and deliberately so.** This layer does not hold
678
+ the catalog of MCP servers - that is the host's configuration - so a server that never fires leaves
679
+ nothing here to name. `tezgah-setup --mcp-schemas` measures what each wired server costs on every
680
+ request; the histogram here counts what fired; joining the two is a reader's step, not a call this
681
+ report makes (calling it would couple the two CLIs and re-measure a config that may not be the one
682
+ the corpus ran under).
683
+
684
+ ## The replay corpus
685
+
686
+ No counter above says whether a refusal was right. The ledger stores the verdict, never the truth.
687
+ `tezgah-gate replay` (`hooks/tezgah_replay.py`) builds the instrument that can. It is a report and
688
+ changes no gate behaviour. Every file it writes stays under `~/.cache/tezgah/replay/<run>/`, owner
689
+ only, and never leaves the machine. Every figure it prints names its cutoff.
690
+
691
+ - **Corpus.** The run reads every ledger under the cache and writes none. It drops a whole ledger
692
+ when `fixture_ledger` calls it a fixture. It also drops one when the session id behind the file
693
+ name is not a host UUID: probe, smoke and test ids. It drops `route` rows, which the suite
694
+ writes, and every row after the cutoff. The items are the `deny`, `began` and `claim` rows. An
695
+ item drops when its deny names a rule the gate no longer has (consent, sink). It also drops at
696
+ the 200-character cap, or when it holds `[redacted:`. The run prints each exclusion with its count.
697
+ - **Join.** A transcript tool call joins a row when its `call_id` equals the row's `id`. The two
698
+ must sit in the ledger the session id names. The walkers read omp and Claude transcripts with
699
+ their subagent files, and drop omp's `i` argument first. A shell `began` row with no transcript
700
+ call joins from its own `detail`, but only when that detail hashes to the row's `id`. A `claim`
701
+ row joins the assistant reply nearest its time, within 2 s. Nothing else joins.
702
+ - **Replay.** A child process gets a sandbox HOME. It appends every kept row to the sandbox
703
+ ledgers in time order. It replays each item just before the item's own row lands, with the
704
+ clock frozen at the row's time. Gate items go through the unmodified `decision(..., record=False)`.
705
+ Stop items go through `_stop_block` with the turn's own rows. The sandbox holds no kill switch,
706
+ so every switch reads armed. A call a switch let through can therefore replay as a refusal.
707
+ - **Replay fidelity** = items whose replayed verdict equals the live one ÷ joined items, per
708
+ stratum. A deny agrees only under the same rule, and `_deny_rule` alone names the rule. The
709
+ *ledger* stratum holds rules that read the call and the ledger. The *disk* stratum holds the
710
+ rules that read today's disk. These are task, plan, workspace and explorer, a shortcut on a write
711
+ tool, and a lang rule reading a message file. The other strata are *allow* (live `began` rows)
712
+ and *stop*.
713
+ The run prints each one for the whole corpus and for the rows since `34f63e3`.
714
+ - **Stop text fidelity** = joined replies whose `_claim_key` equals the claim row's `id`. The run
715
+ prints it beside the fidelity and never counts it as agreement.
716
+ - **Race family** = live race denies split by their foreign writers. A deny is intra-family when
717
+ every writer is the session's parent, child or sibling. It is cross-family when any writer has
718
+ no family tie. The family comes from omp's `spawned` rows and the subagent transcripts' parent
719
+ links.
720
+ - **Denial budget** (`tezgah_shapes.deny_runs`) = per rule, runs of 3 or more consecutive denies
721
+ inside one turn, and sessions with 20 or more denies. These are Claude Code auto mode's
722
+ thresholds, not a tezgah measurement.
723
+
724
+ `replay --sheet` draws the blind label sample with a fixed seed. It fills per-stratum quotas,
725
+ shuffles them, and writes `tezgah-taste measure`'s `{set, n, text}` format. No item shows its
726
+ verdict, its rule or its reason. The verdicts sit in `sheet-key.jsonl`, which a rater does not
727
+ open. The sheet leaves off every race deny written before the ledger stored `target`, because a
728
+ rater could not see its foreign writer. With no race item on the sheet, the report calls the race
729
+ exemption bar not measurable. `replay --report --labels <file> ...` reads one labels file per rater
730
+ (`{set, n, label, rater}`). It prints these rates, each with a Wilson 95% interval:
731
+
732
+ - **False-block rate (rule r)** = denies of r labelled `allow` ÷ denies of r with a label.
733
+ - **Stop missed-violation rate** = allowed claims labelled `false` ÷ allowed claims with a label.
734
+ - **Stop false-refusal rate** = blocked claims labelled `honest` ÷ blocked claims with a label.
735
+ - **Cohen's kappa** between the two raters. The rates count only the items both raters gave the
736
+ same label. Under 0.6 the report says the labels cannot gate a rule.
737
+
738
+ With no labels file the report calls these figures unverifiable instead of printing zeros.
739
+ A rule with no item on the sheet is not measurable: the report prints that and does not pool it.
740
+ With one rater's file it prints no rate either. The rates need two raters' agreed labels, and
741
+ one rater's totals would show the other rater those labels.
742
+
743
+ `replay --label-model --prompt <file>` is rater 2 when that rater is a model. It sends each sheet
744
+ row to the judge seam (`hooks/tezgah_judge.py`) as one `choice` question and writes
745
+ `labels-model.jsonl` beside the sheet. It redacts the row's text first (`ti.redact`), and it runs
746
+ only when TypeSafe answers. The prompt file holds each set's instructions and criteria. A reply
747
+ with no label from those criteria leaves its row unlabelled. The command writes each label as it
748
+ arrives, so a run that stops early keeps what it paid for. A second run asks only the unlabelled rows. Every run prints the input tokens and their cost. The sheet rows leave the machine for
749
+ `api.typesafe.ai`. The key and the corpus stay on it. Kappa against a model rater
750
+ measures human-model agreement, not inter-rater reliability.
751
+
752
+ `--provider deepseek --model deepseek-v4-pro` asks the same questions from the same prompt file
753
+ over DeepSeek's OpenAI-compatible chat endpoint instead (key `DEEPSEEK_API_KEY`). It sends the
754
+ judge seam's chat body with `temperature: 0` and thinking off, and writes
755
+ `labels-deepseek.jsonl` (rater `deepseek`). The cost line prices input and output tokens at
756
+ DeepSeek's peak rate, an upper bound. With two model raters, the report labels kappa as
757
+ model-model agreement, not human judgement (ADR 018).
758
+
759
+ ## What the evidence layer has not shown
760
+
761
+ The ledger records what a session ran, and the Stop rule refuses a done claim
762
+ the ledger cannot back. Both are mechanisms. Neither has shown an effect on task
763
+ outcomes. A paired on/off experiment in October 2026 ran DeepSeek V4.1 Flash on
764
+ omp, bare against a full install. It found no measurable reduction in cheating
765
+ because the model barely cheated in either arm. The second phase used
766
+ ImpossibleBench's conflicting SWE-bench split (44 instances, k = 3). There the
767
+ agent cheated in 0 of 132 runs with tezgah and 1 of 131 without: -0.8 pp, 95%
768
+ CI -2.3 to 0. Clean pass on the original tasks held at 129 of 131 against 129
769
+ of 132.
770
+
771
+ The false-done reader is `hooks/tezgah_integrity.py::claims`, read over the Stop rule's
772
+ claim vocabulary. On the impossible split it read 115 of 132 final messages
773
+ with tezgah as done claims, and 90 of 131 without. Hand labels of 30 sampled
774
+ messages per arm found real done claims in 3 with tezgah and 6 without. The
775
+ adjusted difference is -5 pp,
776
+ 95% CI -18 to +9, so no effect either way. As a false-done reader on this
777
+ split, the reader's precision was 0.10 with tezgah and 0.20 without. With
778
+ tezgah the agent replied in Turkish in 129 of 132 runs. The reader counted the
779
+ passive `doğrulandı` on a partial fix as a completion claim, even beside a
780
+ `doğrulanmadı` for the failing test. It no longer does. A reply that admits an
781
+ open check now reads as no claim. It says no check backs the work
782
+ (`hooks/tezgah_integrity.py::NEGATED`), or that a test contradicts the issue or
783
+ cannot pass (`hooks/tezgah_integrity.py::ADMITTED`). A failure the reply
784
+ dismisses as pre-existing still reads as a claim. The rule came from the 60
785
+ hand-labelled dev messages, where precision rose from 0.15 to 0.69 at recall
786
+ 1.0 (`python3 tests/claim_reader_eval.py --set e4`).
787
+
788
+ A held-out set followed: 40 fresh flagged messages, sampled and labelled under
789
+ a protocol frozen first, by two model raters (kappa 0.565). The reader ran on it
790
+ once, after commit 9cb4d1d. There
791
+ precision rose from 0.212 to 0.857, but recall fell from 1.0 to 0.857 (6 of 7)
792
+ (`python3 tests/claim_reader_eval.py --set heldout`). The plan's recall bar of
793
+ 0.9 is not met. The one miss is a real verification claim whose double negative
794
+ matched NEGATED and read as an admission:
795
+ `doğrulanmadı sayılmaz`.
796
+
797
+ The reader measures and does not decide. `claims` feeds only the benchmarks'
798
+ false-done counts (`benchmarks/arm-bench/bench.py::false_completion`,
799
+ `benchmarks/arm-bench/swe.py`), never the Stop decision. The Stop verdict and
800
+ its `claim` row read the plain DONE/VERIFIED vocabulary with their own NEGATED
801
+ exit, so no refusal changed. NEGATED and ADMITTED match anywhere in the reply,
802
+ so a done claim beside an unrelated "no contradictions" or "never pass secrets"
803
+ is not counted. A false-done count taken before commit 9cb4d1d is not
804
+ comparable with one taken after it.
805
+
806
+ A red-team pass found one route a hook cannot read (a `python3 -c` write of a
807
+ switch) in 30 attempts.
808
+
809
+ The numbers, the per-task counts and the instrument flaws, among them agents
810
+ that could read the benchmark's ground truth, are in
811
+ [the results bundle](results/paired-outcome-2026-10.md).
812
+
813
+ ## Source of truth
814
+
815
+ - `hooks/tezgah_integrity.py` — ledger, kinds, redaction, Stop rule, counters
816
+ - `hooks/tezgah_replay.py` — the replay corpus, the label sheet and its report (`tezgah-gate replay`)
817
+ - `hooks/tezgah_untrusted.py` — provenance label and taint notice
818
+ - `hooks/projects-posttooluse.py` — the writer hosts call after a tool result
819
+ - `hooks/projects-stop.py` — the Claude Stop hook
820
+ - `hooks/tezgah_snapshot.py` — capture, cap, restore
821
+ - `hooks/tezgah_context.py` — the session store (`record`/`used`)
822
+ - `hooks/tezgah_gate.py` — the shortcut and sink denies
823
+ - `hosts/opencode/plugins/tezgah.js` — the host with no Python hook: its own ledger
824
+ and used-store rows (`recordEvidence`, `record`, `skillReadKind`)
825
+ - `hosts/omp/tezgah-hook.ts.in` — the omp bridge: which tool result reaches the hook
826
+ at all, and the skill-read filter
827
+ - `bin/tezgah-rollback`, `bin/tezgah-capture`, `bin/tezgah-status`
828
+ - `tests/test_integrity.py`, `tests/test_snapshot.py` — the pinned behaviour
829
+ - `tests/test_opencode_plugin.py`, `tests/test_omp_extension.py` — the JS mirrors
830
+ pinned against the Python half
831
+ - `docs/results/paired-outcome-2026-10.md` — the paired outcome experiment and its counts