@r1z4x/tezgah 1.9.2 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (426) hide show
  1. package/CHANGELOG.md +83 -1
  2. package/MANIFEST +382 -144
  3. package/README.de.md +1 -1
  4. package/README.es.md +1 -1
  5. package/README.fr.md +1 -1
  6. package/README.md +1 -1
  7. package/README.tr.md +1 -1
  8. package/bin/codegen +5 -2
  9. package/bin/tezgah-design +288 -1
  10. package/bin/tezgah-docs +1 -1
  11. package/bin/tezgah-doctor +39 -2
  12. package/bin/tezgah-import-ai-research +26 -12
  13. package/bin/tezgah-ocr-review +296 -0
  14. package/bin/tezgah-research +216 -40
  15. package/bin/tezgah-review-quote +185 -0
  16. package/bin/tezgah-setup +136 -33
  17. package/bin/tezgah-skill +1 -1
  18. package/bin/tezgah-status +201 -3
  19. package/bin/tezgah-task +203 -3
  20. package/commands/adhd.md +2 -2
  21. package/commands/ponytail.md +4 -4
  22. package/docs/architecture.md +2 -2
  23. package/docs/citations-baseline.json +2 -2
  24. package/docs/clarity-baseline.json +2 -2
  25. package/docs/contract.md +87 -42
  26. package/docs/environment.md +2 -0
  27. package/docs/evidence.md +28 -9
  28. package/docs/feature-audit.md +2 -2
  29. package/docs/gate.md +54 -31
  30. package/docs/glossary.md +5 -2
  31. package/docs/hosts.md +17 -3
  32. package/docs/index.json +34 -8
  33. package/docs/judge.md +4 -2
  34. package/docs/layers.md +3 -3
  35. package/docs/models.md +31 -9
  36. package/docs/operations.md +126 -1
  37. package/docs/research.md +786 -5
  38. package/docs/skills.md +137 -13
  39. package/docs/status-line.md +115 -1
  40. package/hooks/hooks.json +1 -1
  41. package/hooks/lang/en.json +10 -0
  42. package/hooks/lang/tr.json +11 -1
  43. package/hooks/tezgah_agents.py +38 -22
  44. package/hooks/tezgah_apps.py +18 -0
  45. package/hooks/tezgah_components.py +4 -0
  46. package/hooks/tezgah_context.py +189 -50
  47. package/hooks/tezgah_extension.py +337 -0
  48. package/hooks/tezgah_gate.py +188 -56
  49. package/hooks/tezgah_integrity.py +652 -105
  50. package/hooks/tezgah_judge.py +6 -4
  51. package/hooks/tezgah_models.py +59 -19
  52. package/hooks/tezgah_orca.py +1 -1
  53. package/hooks/tezgah_paths.py +102 -6
  54. package/hooks/tezgah_policy.py +94 -45
  55. package/hooks/tezgah_rank.py +9 -6
  56. package/hooks/tezgah_replay.py +4 -4
  57. package/hooks/tezgah_research.py +1260 -65
  58. package/hooks/tezgah_research_capture.py +1544 -0
  59. package/hooks/tezgah_research_evidence.py +842 -0
  60. package/hooks/tezgah_research_stats.py +258 -0
  61. package/hooks/tezgah_skill_pick.py +408 -106
  62. package/hooks/tezgah_stopspec.py +8 -1
  63. package/hooks/tezgah_task.py +12 -4
  64. package/hooks/tezgah_taste_ledger.py +1 -1
  65. package/hosts/cursor/hook.py +29 -2
  66. package/hosts/opencode/plugins/tezgah.js +307 -46
  67. package/hosts/opencode/tui/cli/tui.tsx +100 -0
  68. package/hosts/opencode/tui/tezgah-tui.tsx +2 -1
  69. package/output-styles/tezgah.md +10 -10
  70. package/package.json +1 -1
  71. package/skills/ai-research/SKILL.md +21 -14
  72. package/skills/ai-research/SOURCE +7 -5
  73. package/skills/ai-research/index/1-frame.md +6 -6
  74. package/skills/ai-research/index/2-data.md +9 -9
  75. package/skills/ai-research/index/3-train.md +36 -36
  76. package/skills/ai-research/index/4-measure.md +13 -13
  77. package/skills/ai-research/index/5-run.md +11 -11
  78. package/skills/ai-research/index/6-write.md +23 -23
  79. package/skills/ai-research/library.json +104 -104
  80. package/skills/analyze-app/SKILL.md +17 -12
  81. package/skills/design-contract/SKILL.md +42 -7
  82. package/skills/design-contract/data-views.md +2 -2
  83. package/skills/design-library/EVALS.md +1 -1
  84. package/skills/design-library/INDEX.md +39 -39
  85. package/skills/design-library/SKILL.md +19 -13
  86. package/skills/design-library/SOURCE +45 -43
  87. package/skills/feature-audit/SKILL.md +20 -14
  88. package/skills/hallmark/LICENSE +21 -0
  89. package/skills/hallmark/SKILL.md +154 -0
  90. package/skills/hallmark/SOURCE +207 -0
  91. package/skills/hallmark/agents/openai.yaml +13 -0
  92. package/skills/hallmark/references/anatomy.md +71 -0
  93. package/skills/hallmark/references/brand-truth.md +40 -0
  94. package/skills/hallmark/references/comp.md +104 -0
  95. package/skills/hallmark/references/craft.md +116 -0
  96. package/skills/hallmark/references/dark-mode.md +49 -0
  97. package/skills/hallmark/references/data-viz.md +48 -0
  98. package/skills/hallmark/references/design-md.md +53 -0
  99. package/skills/hallmark/references/direction.md +52 -0
  100. package/skills/hallmark/references/export-formats.md +80 -0
  101. package/skills/hallmark/references/flow.md +131 -0
  102. package/skills/hallmark/references/fonts.md +58 -0
  103. package/skills/hallmark/references/gates.md +243 -0
  104. package/skills/hallmark/references/genres/atmospheric.md +24 -0
  105. package/skills/hallmark/references/genres/editorial.md +24 -0
  106. package/skills/hallmark/references/genres/modern-minimal.md +24 -0
  107. package/skills/hallmark/references/genres/playful.md +24 -0
  108. package/skills/hallmark/references/imagery.md +99 -0
  109. package/skills/hallmark/references/interaction-and-states.md +89 -0
  110. package/skills/hallmark/references/layout.md +104 -0
  111. package/skills/hallmark/references/macrostructures/01-bento-grid.md +21 -0
  112. package/skills/hallmark/references/macrostructures/02-long-document.md +35 -0
  113. package/skills/hallmark/references/macrostructures/03-marquee-hero.md +21 -0
  114. package/skills/hallmark/references/macrostructures/04-stat-led.md +21 -0
  115. package/skills/hallmark/references/macrostructures/05-workbench.md +21 -0
  116. package/skills/hallmark/references/macrostructures/06-conversational-faq.md +28 -0
  117. package/skills/hallmark/references/macrostructures/07-manifesto.md +28 -0
  118. package/skills/hallmark/references/macrostructures/08-photographic.md +21 -0
  119. package/skills/hallmark/references/macrostructures/09-quote-led.md +21 -0
  120. package/skills/hallmark/references/macrostructures/10-specimen.md +21 -0
  121. package/skills/hallmark/references/macrostructures/11-catalogue.md +21 -0
  122. package/skills/hallmark/references/macrostructures/12-letter.md +21 -0
  123. package/skills/hallmark/references/macrostructures/13-index-first.md +21 -0
  124. package/skills/hallmark/references/macrostructures/14-narrative-workflow.md +21 -0
  125. package/skills/hallmark/references/macrostructures/15-split-studio.md +21 -0
  126. package/skills/hallmark/references/macrostructures/16-feature-stack.md +23 -0
  127. package/skills/hallmark/references/macrostructures/17-type-specimen.md +19 -0
  128. package/skills/hallmark/references/macrostructures/18-portfolio-grid.md +21 -0
  129. package/skills/hallmark/references/macrostructures/19-map-diagram.md +21 -0
  130. package/skills/hallmark/references/macrostructures/20-ecosystem-index.md +19 -0
  131. package/skills/hallmark/references/macrostructures/21-component-playground.md +21 -0
  132. package/skills/hallmark/references/macrostructures.md +119 -0
  133. package/skills/hallmark/references/microinteractions.md +80 -0
  134. package/skills/hallmark/references/patterns.md +202 -0
  135. package/skills/hallmark/references/redesign.md +88 -0
  136. package/skills/hallmark/references/responsive.md +46 -0
  137. package/skills/hallmark/references/review-finish.md +19 -0
  138. package/skills/hallmark/references/review-hero.md +20 -0
  139. package/skills/hallmark/references/scroll-choreography.md +110 -0
  140. package/skills/hallmark/references/texture.md +90 -0
  141. package/skills/hallmark/references/themes/README.md +58 -0
  142. package/skills/hallmark/references/themes/almanac.jpg +0 -0
  143. package/skills/hallmark/references/themes/almanac.md +103 -0
  144. package/skills/hallmark/references/themes/arcade.jpg +0 -0
  145. package/skills/hallmark/references/themes/arcade.md +102 -0
  146. package/skills/hallmark/references/themes/atelier.jpg +0 -0
  147. package/skills/hallmark/references/themes/atelier.md +98 -0
  148. package/skills/hallmark/references/themes/bloom.jpg +0 -0
  149. package/skills/hallmark/references/themes/bloom.md +102 -0
  150. package/skills/hallmark/references/themes/blueprint.jpg +0 -0
  151. package/skills/hallmark/references/themes/blueprint.md +103 -0
  152. package/skills/hallmark/references/themes/broadside.jpg +0 -0
  153. package/skills/hallmark/references/themes/broadside.md +108 -0
  154. package/skills/hallmark/references/themes/brutal.jpg +0 -0
  155. package/skills/hallmark/references/themes/brutal.md +95 -0
  156. package/skills/hallmark/references/themes/carnival.jpg +0 -0
  157. package/skills/hallmark/references/themes/carnival.md +104 -0
  158. package/skills/hallmark/references/themes/cobalt.jpg +0 -0
  159. package/skills/hallmark/references/themes/cobalt.md +101 -0
  160. package/skills/hallmark/references/themes/console.jpg +0 -0
  161. package/skills/hallmark/references/themes/console.md +99 -0
  162. package/skills/hallmark/references/themes/coral.jpg +0 -0
  163. package/skills/hallmark/references/themes/coral.md +102 -0
  164. package/skills/hallmark/references/themes/darkroom.jpg +0 -0
  165. package/skills/hallmark/references/themes/darkroom.md +99 -0
  166. package/skills/hallmark/references/themes/dose.jpg +0 -0
  167. package/skills/hallmark/references/themes/dose.md +98 -0
  168. package/skills/hallmark/references/themes/dusk.jpg +0 -0
  169. package/skills/hallmark/references/themes/dusk.md +105 -0
  170. package/skills/hallmark/references/themes/editorial.jpg +0 -0
  171. package/skills/hallmark/references/themes/editorial.md +97 -0
  172. package/skills/hallmark/references/themes/formwork.jpg +0 -0
  173. package/skills/hallmark/references/themes/formwork.md +107 -0
  174. package/skills/hallmark/references/themes/furrow.jpg +0 -0
  175. package/skills/hallmark/references/themes/furrow.md +98 -0
  176. package/skills/hallmark/references/themes/garden.jpg +0 -0
  177. package/skills/hallmark/references/themes/garden.md +97 -0
  178. package/skills/hallmark/references/themes/grid.jpg +0 -0
  179. package/skills/hallmark/references/themes/grid.md +101 -0
  180. package/skills/hallmark/references/themes/halftone.jpg +0 -0
  181. package/skills/hallmark/references/themes/halftone.md +106 -0
  182. package/skills/hallmark/references/themes/hedgerow.jpg +0 -0
  183. package/skills/hallmark/references/themes/hedgerow.md +104 -0
  184. package/skills/hallmark/references/themes/hum.jpg +0 -0
  185. package/skills/hallmark/references/themes/hum.md +99 -0
  186. package/skills/hallmark/references/themes/index.json +2191 -0
  187. package/skills/hallmark/references/themes/ink.jpg +0 -0
  188. package/skills/hallmark/references/themes/ink.md +106 -0
  189. package/skills/hallmark/references/themes/kiln.jpg +0 -0
  190. package/skills/hallmark/references/themes/kiln.md +108 -0
  191. package/skills/hallmark/references/themes/loom.jpg +0 -0
  192. package/skills/hallmark/references/themes/loom.md +106 -0
  193. package/skills/hallmark/references/themes/lumen.jpg +0 -0
  194. package/skills/hallmark/references/themes/lumen.md +103 -0
  195. package/skills/hallmark/references/themes/manifesto.jpg +0 -0
  196. package/skills/hallmark/references/themes/manifesto.md +101 -0
  197. package/skills/hallmark/references/themes/midnight.jpg +0 -0
  198. package/skills/hallmark/references/themes/midnight.md +97 -0
  199. package/skills/hallmark/references/themes/newsprint.jpg +0 -0
  200. package/skills/hallmark/references/themes/newsprint.md +102 -0
  201. package/skills/hallmark/references/themes/overprint.jpg +0 -0
  202. package/skills/hallmark/references/themes/overprint.md +101 -0
  203. package/skills/hallmark/references/themes/pasteup.jpg +0 -0
  204. package/skills/hallmark/references/themes/pasteup.md +100 -0
  205. package/skills/hallmark/references/themes/piste.jpg +0 -0
  206. package/skills/hallmark/references/themes/piste.md +99 -0
  207. package/skills/hallmark/references/themes/ribbon.jpg +0 -0
  208. package/skills/hallmark/references/themes/ribbon.md +106 -0
  209. package/skills/hallmark/references/themes/rim.jpg +0 -0
  210. package/skills/hallmark/references/themes/rim.md +96 -0
  211. package/skills/hallmark/references/themes/riso.jpg +0 -0
  212. package/skills/hallmark/references/themes/riso.md +98 -0
  213. package/skills/hallmark/references/themes/solstice.jpg +0 -0
  214. package/skills/hallmark/references/themes/solstice.md +104 -0
  215. package/skills/hallmark/references/themes/specimen.jpg +0 -0
  216. package/skills/hallmark/references/themes/specimen.md +100 -0
  217. package/skills/hallmark/references/themes/spore.jpg +0 -0
  218. package/skills/hallmark/references/themes/spore.md +104 -0
  219. package/skills/hallmark/references/themes/sport.jpg +0 -0
  220. package/skills/hallmark/references/themes/sport.md +101 -0
  221. package/skills/hallmark/references/themes/squeeze.jpg +0 -0
  222. package/skills/hallmark/references/themes/squeeze.md +99 -0
  223. package/skills/hallmark/references/themes/sticker.jpg +0 -0
  224. package/skills/hallmark/references/themes/sticker.md +106 -0
  225. package/skills/hallmark/references/themes/studio.jpg +0 -0
  226. package/skills/hallmark/references/themes/studio.md +99 -0
  227. package/skills/hallmark/references/themes/terminal.jpg +0 -0
  228. package/skills/hallmark/references/themes/terminal.md +96 -0
  229. package/skills/hallmark/references/themes/terrazzo.jpg +0 -0
  230. package/skills/hallmark/references/themes/terrazzo.md +106 -0
  231. package/skills/hallmark/references/themes/ultraviolet.jpg +0 -0
  232. package/skills/hallmark/references/themes/ultraviolet.md +106 -0
  233. package/skills/hallmark/references/themes/vellum.jpg +0 -0
  234. package/skills/hallmark/references/themes/vellum.md +105 -0
  235. package/skills/hallmark/references/themes/wayfind.jpg +0 -0
  236. package/skills/hallmark/references/themes/wayfind.md +105 -0
  237. package/skills/hallmark/references/themes/werkstatt.jpg +0 -0
  238. package/skills/hallmark/references/themes/werkstatt.md +105 -0
  239. package/skills/hallmark/scripts/capture.mjs +125 -0
  240. package/skills/hallmark/scripts/fixtures/exemplars/atmospheric.html +324 -0
  241. package/skills/hallmark/scripts/fixtures/exemplars/editorial.html +363 -0
  242. package/skills/hallmark/scripts/fixtures/exemplars/modern-minimal.html +527 -0
  243. package/skills/hallmark/scripts/fixtures/exemplars/playful.html +353 -0
  244. package/skills/hallmark/scripts/fixtures/eyebrow-fail/index.html +118 -0
  245. package/skills/hallmark/scripts/fixtures/eyebrow-pass/index.html +137 -0
  246. package/skills/hallmark/scripts/fixtures/kept/after.html +27 -0
  247. package/skills/hallmark/scripts/fixtures/kept/before.html +26 -0
  248. package/skills/hallmark/scripts/fixtures/slopped.html +145 -0
  249. package/skills/hallmark/scripts/fixtures/tailwind-fail/Feature.vue +14 -0
  250. package/skills/hallmark/scripts/fixtures/tailwind-fail/Hero.tsx +33 -0
  251. package/skills/hallmark/scripts/fixtures/tailwind-fail/index.html +74 -0
  252. package/skills/hallmark/scripts/fixtures/tailwind-fail/style.css +6 -0
  253. package/skills/hallmark/scripts/fixtures/tailwind-pass/Hero.tsx +33 -0
  254. package/skills/hallmark/scripts/fixtures/tailwind-pass/index.html +57 -0
  255. package/skills/hallmark/scripts/fixtures/tailwind-pass/style.css +15 -0
  256. package/skills/hallmark/scripts/fixtures/waiver/index.html +54 -0
  257. package/skills/hallmark/scripts/imagegen.mjs +85 -0
  258. package/skills/hallmark/scripts/install-hook.mjs +70 -0
  259. package/skills/hallmark/scripts/install.mjs +141 -0
  260. package/skills/hallmark/scripts/lint-hook.mjs +49 -0
  261. package/skills/hallmark/scripts/photos.json +1 -0
  262. package/skills/hallmark/scripts/picture.mjs +71 -0
  263. package/skills/hallmark/scripts/refcheck.mjs +352 -0
  264. package/skills/hallmark/scripts/sloplint-render.mjs +1252 -0
  265. package/skills/hallmark/scripts/sloplint.mjs +4422 -0
  266. package/skills/hallmark/scripts/theme.mjs +650 -0
  267. package/skills/harness/SKILL.md +15 -8
  268. package/skills/i-have-adhd/SKILL.md +22 -11
  269. package/skills/no-ai-slop/SKILL.md +15 -1
  270. package/skills/plan-add/SKILL.md +33 -26
  271. package/skills/plan-status/SKILL.md +13 -7
  272. package/skills/plan-sync/SKILL.md +18 -12
  273. package/skills/pm-frameworks/SKILL.md +19 -10
  274. package/skills/pm-frameworks/SOURCE +7 -5
  275. package/skills/ponytail/SKILL.md +19 -14
  276. package/skills/product-analysis/SKILL.md +22 -18
  277. package/skills/product-flow/SKILL.md +14 -9
  278. package/skills/research/SKILL.md +75 -39
  279. package/skills/rl-env/SKILL.md +25 -13
  280. package/skills/rl-env/SOURCE +8 -6
  281. package/skills/tezgah-contract/SKILL.md +47 -42
  282. package/bin/tezgah-skill.py +0 -59
  283. /package/skills/ai-research/0-autoresearch-skill/{SKILL.md → ENTRY.md} +0 -0
  284. /package/skills/ai-research/01-model-architecture/litgpt/{SKILL.md → ENTRY.md} +0 -0
  285. /package/skills/ai-research/01-model-architecture/mamba/{SKILL.md → ENTRY.md} +0 -0
  286. /package/skills/ai-research/01-model-architecture/nanogpt/{SKILL.md → ENTRY.md} +0 -0
  287. /package/skills/ai-research/01-model-architecture/rwkv/{SKILL.md → ENTRY.md} +0 -0
  288. /package/skills/ai-research/01-model-architecture/torchtitan/{SKILL.md → ENTRY.md} +0 -0
  289. /package/skills/ai-research/02-tokenization/huggingface-tokenizers/{SKILL.md → ENTRY.md} +0 -0
  290. /package/skills/ai-research/02-tokenization/sentencepiece/{SKILL.md → ENTRY.md} +0 -0
  291. /package/skills/ai-research/03-fine-tuning/axolotl/{SKILL.md → ENTRY.md} +0 -0
  292. /package/skills/ai-research/03-fine-tuning/llama-factory/{SKILL.md → ENTRY.md} +0 -0
  293. /package/skills/ai-research/03-fine-tuning/peft/{SKILL.md → ENTRY.md} +0 -0
  294. /package/skills/ai-research/03-fine-tuning/unsloth/{SKILL.md → ENTRY.md} +0 -0
  295. /package/skills/ai-research/04-mechanistic-interpretability/nnsight/{SKILL.md → ENTRY.md} +0 -0
  296. /package/skills/ai-research/04-mechanistic-interpretability/pyvene/{SKILL.md → ENTRY.md} +0 -0
  297. /package/skills/ai-research/04-mechanistic-interpretability/saelens/{SKILL.md → ENTRY.md} +0 -0
  298. /package/skills/ai-research/04-mechanistic-interpretability/transformer-lens/{SKILL.md → ENTRY.md} +0 -0
  299. /package/skills/ai-research/05-data-processing/nemo-curator/{SKILL.md → ENTRY.md} +0 -0
  300. /package/skills/ai-research/05-data-processing/ray-data/{SKILL.md → ENTRY.md} +0 -0
  301. /package/skills/ai-research/06-post-training/grpo-rl-training/{SKILL.md → ENTRY.md} +0 -0
  302. /package/skills/ai-research/06-post-training/miles/{SKILL.md → ENTRY.md} +0 -0
  303. /package/skills/ai-research/06-post-training/openrlhf/{SKILL.md → ENTRY.md} +0 -0
  304. /package/skills/ai-research/06-post-training/simpo/{SKILL.md → ENTRY.md} +0 -0
  305. /package/skills/ai-research/06-post-training/slime/{SKILL.md → ENTRY.md} +0 -0
  306. /package/skills/ai-research/06-post-training/torchforge/{SKILL.md → ENTRY.md} +0 -0
  307. /package/skills/ai-research/06-post-training/trl-fine-tuning/{SKILL.md → ENTRY.md} +0 -0
  308. /package/skills/ai-research/06-post-training/verl/{SKILL.md → ENTRY.md} +0 -0
  309. /package/skills/ai-research/07-safety-alignment/constitutional-ai/{SKILL.md → ENTRY.md} +0 -0
  310. /package/skills/ai-research/07-safety-alignment/llamaguard/{SKILL.md → ENTRY.md} +0 -0
  311. /package/skills/ai-research/07-safety-alignment/nemo-guardrails/{SKILL.md → ENTRY.md} +0 -0
  312. /package/skills/ai-research/07-safety-alignment/prompt-guard/{SKILL.md → ENTRY.md} +0 -0
  313. /package/skills/ai-research/08-distributed-training/accelerate/{SKILL.md → ENTRY.md} +0 -0
  314. /package/skills/ai-research/08-distributed-training/deepspeed/{SKILL.md → ENTRY.md} +0 -0
  315. /package/skills/ai-research/08-distributed-training/megatron-core/{SKILL.md → ENTRY.md} +0 -0
  316. /package/skills/ai-research/08-distributed-training/pytorch-fsdp2/{SKILL.md → ENTRY.md} +0 -0
  317. /package/skills/ai-research/08-distributed-training/pytorch-lightning/{SKILL.md → ENTRY.md} +0 -0
  318. /package/skills/ai-research/08-distributed-training/ray-train/{SKILL.md → ENTRY.md} +0 -0
  319. /package/skills/ai-research/09-infrastructure/lambda-labs/{SKILL.md → ENTRY.md} +0 -0
  320. /package/skills/ai-research/09-infrastructure/modal/{SKILL.md → ENTRY.md} +0 -0
  321. /package/skills/ai-research/09-infrastructure/skypilot/{SKILL.md → ENTRY.md} +0 -0
  322. /package/skills/ai-research/10-optimization/awq/{SKILL.md → ENTRY.md} +0 -0
  323. /package/skills/ai-research/10-optimization/bitsandbytes/{SKILL.md → ENTRY.md} +0 -0
  324. /package/skills/ai-research/10-optimization/flash-attention/{SKILL.md → ENTRY.md} +0 -0
  325. /package/skills/ai-research/10-optimization/gguf/{SKILL.md → ENTRY.md} +0 -0
  326. /package/skills/ai-research/10-optimization/gptq/{SKILL.md → ENTRY.md} +0 -0
  327. /package/skills/ai-research/10-optimization/hqq/{SKILL.md → ENTRY.md} +0 -0
  328. /package/skills/ai-research/10-optimization/ml-training-recipes/{SKILL.md → ENTRY.md} +0 -0
  329. /package/skills/ai-research/11-evaluation/bigcode-evaluation-harness/{SKILL.md → ENTRY.md} +0 -0
  330. /package/skills/ai-research/11-evaluation/lm-evaluation-harness/{SKILL.md → ENTRY.md} +0 -0
  331. /package/skills/ai-research/11-evaluation/nemo-evaluator/{SKILL.md → ENTRY.md} +0 -0
  332. /package/skills/ai-research/12-inference-serving/llama-cpp/{SKILL.md → ENTRY.md} +0 -0
  333. /package/skills/ai-research/12-inference-serving/sglang/{SKILL.md → ENTRY.md} +0 -0
  334. /package/skills/ai-research/12-inference-serving/tensorrt-llm/{SKILL.md → ENTRY.md} +0 -0
  335. /package/skills/ai-research/12-inference-serving/vllm/{SKILL.md → ENTRY.md} +0 -0
  336. /package/skills/ai-research/13-mlops/mlflow/{SKILL.md → ENTRY.md} +0 -0
  337. /package/skills/ai-research/13-mlops/swanlab/{SKILL.md → ENTRY.md} +0 -0
  338. /package/skills/ai-research/13-mlops/tensorboard/{SKILL.md → ENTRY.md} +0 -0
  339. /package/skills/ai-research/13-mlops/weights-and-biases/{SKILL.md → ENTRY.md} +0 -0
  340. /package/skills/ai-research/14-agents/a-evolve/{SKILL.md → ENTRY.md} +0 -0
  341. /package/skills/ai-research/14-agents/autogpt/{SKILL.md → ENTRY.md} +0 -0
  342. /package/skills/ai-research/14-agents/crewai/{SKILL.md → ENTRY.md} +0 -0
  343. /package/skills/ai-research/14-agents/langchain/{SKILL.md → ENTRY.md} +0 -0
  344. /package/skills/ai-research/14-agents/llamaindex/{SKILL.md → ENTRY.md} +0 -0
  345. /package/skills/ai-research/15-rag/chroma/{SKILL.md → ENTRY.md} +0 -0
  346. /package/skills/ai-research/15-rag/faiss/{SKILL.md → ENTRY.md} +0 -0
  347. /package/skills/ai-research/15-rag/pinecone/{SKILL.md → ENTRY.md} +0 -0
  348. /package/skills/ai-research/15-rag/qdrant/{SKILL.md → ENTRY.md} +0 -0
  349. /package/skills/ai-research/15-rag/sentence-transformers/{SKILL.md → ENTRY.md} +0 -0
  350. /package/skills/ai-research/16-prompt-engineering/dspy/{SKILL.md → ENTRY.md} +0 -0
  351. /package/skills/ai-research/16-prompt-engineering/guidance/{SKILL.md → ENTRY.md} +0 -0
  352. /package/skills/ai-research/16-prompt-engineering/instructor/{SKILL.md → ENTRY.md} +0 -0
  353. /package/skills/ai-research/16-prompt-engineering/outlines/{SKILL.md → ENTRY.md} +0 -0
  354. /package/skills/ai-research/17-observability/langsmith/{SKILL.md → ENTRY.md} +0 -0
  355. /package/skills/ai-research/17-observability/phoenix/{SKILL.md → ENTRY.md} +0 -0
  356. /package/skills/ai-research/18-multimodal/audiocraft/{SKILL.md → ENTRY.md} +0 -0
  357. /package/skills/ai-research/18-multimodal/blip-2/{SKILL.md → ENTRY.md} +0 -0
  358. /package/skills/ai-research/18-multimodal/clip/{SKILL.md → ENTRY.md} +0 -0
  359. /package/skills/ai-research/18-multimodal/cosmos-policy/{SKILL.md → ENTRY.md} +0 -0
  360. /package/skills/ai-research/18-multimodal/llava/{SKILL.md → ENTRY.md} +0 -0
  361. /package/skills/ai-research/18-multimodal/openpi/{SKILL.md → ENTRY.md} +0 -0
  362. /package/skills/ai-research/18-multimodal/openvla-oft/{SKILL.md → ENTRY.md} +0 -0
  363. /package/skills/ai-research/18-multimodal/segment-anything/{SKILL.md → ENTRY.md} +0 -0
  364. /package/skills/ai-research/18-multimodal/stable-diffusion/{SKILL.md → ENTRY.md} +0 -0
  365. /package/skills/ai-research/18-multimodal/whisper/{SKILL.md → ENTRY.md} +0 -0
  366. /package/skills/ai-research/19-emerging-techniques/knowledge-distillation/{SKILL.md → ENTRY.md} +0 -0
  367. /package/skills/ai-research/19-emerging-techniques/long-context/{SKILL.md → ENTRY.md} +0 -0
  368. /package/skills/ai-research/19-emerging-techniques/model-merging/{SKILL.md → ENTRY.md} +0 -0
  369. /package/skills/ai-research/19-emerging-techniques/model-pruning/{SKILL.md → ENTRY.md} +0 -0
  370. /package/skills/ai-research/19-emerging-techniques/moe-training/{SKILL.md → ENTRY.md} +0 -0
  371. /package/skills/ai-research/19-emerging-techniques/speculative-decoding/{SKILL.md → ENTRY.md} +0 -0
  372. /package/skills/ai-research/20-ml-paper-writing/academic-plotting/{SKILL.md → ENTRY.md} +0 -0
  373. /package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/{SKILL.md → ENTRY.md} +0 -0
  374. /package/skills/ai-research/20-ml-paper-writing/presenting-conference-talks/{SKILL.md → ENTRY.md} +0 -0
  375. /package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/{SKILL.md → ENTRY.md} +0 -0
  376. /package/skills/ai-research/21-research-ideation/brainstorming-research-ideas/{SKILL.md → ENTRY.md} +0 -0
  377. /package/skills/ai-research/21-research-ideation/creative-thinking-for-research/{SKILL.md → ENTRY.md} +0 -0
  378. /package/skills/ai-research/22-agent-native-research-artifact/compiler/{SKILL.md → ENTRY.md} +0 -0
  379. /package/skills/ai-research/22-agent-native-research-artifact/research-manager/{SKILL.md → ENTRY.md} +0 -0
  380. /package/skills/ai-research/22-agent-native-research-artifact/rigor-reviewer/{SKILL.md → ENTRY.md} +0 -0
  381. /package/skills/design-library/adaptive-interfaces/skills/colour-independence/{SKILL.md → ENTRY.md} +0 -0
  382. /package/skills/design-library/adaptive-interfaces/skills/flexible-typography/{SKILL.md → ENTRY.md} +0 -0
  383. /package/skills/design-library/adaptive-interfaces/skills/information-density/{SKILL.md → ENTRY.md} +0 -0
  384. /package/skills/design-library/adaptive-interfaces/skills/preference-audit/{SKILL.md → ENTRY.md} +0 -0
  385. /package/skills/design-library/adaptive-interfaces/skills/responsive-accessibility/{SKILL.md → ENTRY.md} +0 -0
  386. /package/skills/design-library/adaptive-interfaces/skills/responsive-review/{SKILL.md → ENTRY.md} +0 -0
  387. /package/skills/design-library/adaptive-interfaces/skills/simplified-views/{SKILL.md → ENTRY.md} +0 -0
  388. /package/skills/design-library/adaptive-interfaces/skills/specify/{SKILL.md → ENTRY.md} +0 -0
  389. /package/skills/design-library/adaptive-interfaces/skills/user-preference-respect/{SKILL.md → ENTRY.md} +0 -0
  390. /package/skills/design-library/cognitive-accessibility/skills/adaptive-personalisation/{SKILL.md → ENTRY.md} +0 -0
  391. /package/skills/design-library/cognitive-accessibility/skills/assess-load/{SKILL.md → ENTRY.md} +0 -0
  392. /package/skills/design-library/cognitive-accessibility/skills/cognitive-load-assessment/{SKILL.md → ENTRY.md} +0 -0
  393. /package/skills/design-library/cognitive-accessibility/skills/contextual-help-design/{SKILL.md → ENTRY.md} +0 -0
  394. /package/skills/design-library/cognitive-accessibility/skills/error-prevention-recovery/{SKILL.md → ENTRY.md} +0 -0
  395. /package/skills/design-library/cognitive-accessibility/skills/focus-attention-design/{SKILL.md → ENTRY.md} +0 -0
  396. /package/skills/design-library/cognitive-accessibility/skills/memory-load-reduction/{SKILL.md → ENTRY.md} +0 -0
  397. /package/skills/design-library/cognitive-accessibility/skills/plain-language-design/{SKILL.md → ENTRY.md} +0 -0
  398. /package/skills/design-library/cognitive-accessibility/skills/review/{SKILL.md → ENTRY.md} +0 -0
  399. /package/skills/design-library/cognitive-accessibility/skills/simplify/{SKILL.md → ENTRY.md} +0 -0
  400. /package/skills/design-library/cognitive-accessibility/skills/wayfinding-navigation/{SKILL.md → ENTRY.md} +0 -0
  401. /package/skills/design-library/design-research/skills/behavioural-analytics/{SKILL.md → ENTRY.md} +0 -0
  402. /package/skills/design-library/design-research/skills/qual-quant-triangulation/{SKILL.md → ENTRY.md} +0 -0
  403. /package/skills/design-library/inclusive-interaction/skills/audit/{SKILL.md → ENTRY.md} +0 -0
  404. /package/skills/design-library/inclusive-interaction/skills/design-flow/{SKILL.md → ENTRY.md} +0 -0
  405. /package/skills/design-library/inclusive-interaction/skills/feedback-and-status/{SKILL.md → ENTRY.md} +0 -0
  406. /package/skills/design-library/inclusive-interaction/skills/gesture-alternatives/{SKILL.md → ENTRY.md} +0 -0
  407. /package/skills/design-library/inclusive-interaction/skills/keyboard-navigation/{SKILL.md → ENTRY.md} +0 -0
  408. /package/skills/design-library/inclusive-interaction/skills/keyboard-review/{SKILL.md → ENTRY.md} +0 -0
  409. /package/skills/design-library/inclusive-interaction/skills/motion-sensitivity/{SKILL.md → ENTRY.md} +0 -0
  410. /package/skills/design-library/inclusive-interaction/skills/multi-modal-input/{SKILL.md → ENTRY.md} +0 -0
  411. /package/skills/design-library/inclusive-interaction/skills/touch-target-design/{SKILL.md → ENTRY.md} +0 -0
  412. /package/skills/design-library/inclusive-interaction/skills/voice-interaction/{SKILL.md → ENTRY.md} +0 -0
  413. /package/skills/design-library/visual-critique/skills/critique-affordance/{SKILL.md → ENTRY.md} +0 -0
  414. /package/skills/design-library/visual-critique/skills/critique-brand-consistency/{SKILL.md → ENTRY.md} +0 -0
  415. /package/skills/design-library/visual-critique/skills/critique-color/{SKILL.md → ENTRY.md} +0 -0
  416. /package/skills/design-library/visual-critique/skills/critique-composition/{SKILL.md → ENTRY.md} +0 -0
  417. /package/skills/design-library/visual-critique/skills/critique-information-density/{SKILL.md → ENTRY.md} +0 -0
  418. /package/skills/design-library/visual-critique/skills/critique-typography/{SKILL.md → ENTRY.md} +0 -0
  419. /package/skills/design-library/visual-critique/skills/critique-visual-hierarchy/{SKILL.md → ENTRY.md} +0 -0
  420. /package/skills/pm-frameworks/intended-vs-implemented/{SKILL.md → ENTRY.md} +0 -0
  421. /package/skills/pm-frameworks/opportunity-solution-tree/{SKILL.md → ENTRY.md} +0 -0
  422. /package/skills/rl-env/generate-nemo-gym-env/{SKILL.md → ENTRY.md} +0 -0
  423. /package/skills/rl-env/generate-openenv-env/{SKILL.md → ENTRY.md} +0 -0
  424. /package/skills/rl-env/generate-ors-env/{SKILL.md → ENTRY.md} +0 -0
  425. /package/skills/rl-env/generate-verifiers-env/{SKILL.md → ENTRY.md} +0 -0
  426. /package/skills/rl-env/rl-env-from-description/{SKILL.md → ENTRY.md} +0 -0
@@ -2,13 +2,15 @@
2
2
  """tezgah-research - the research workspace CLI.
3
3
 
4
4
  tezgah-research init <slug> --ask "<the user's words>" [--question "..."]
5
- [--method qualitative|measured|exploratory] [--in "<covered>"]...
6
- [--out "<left alone>"]... [--allow-open "<why>"] [--supersedes <slug>]
5
+ [--method qualitative|measured|exploratory] [--class R1..R12]
6
+ [--in "<covered>"]... [--out "<left alone>"]... [--allow-open "<why>"]
7
+ [--supersedes <slug>]
7
8
  [--arena "<problem>" --budget "<budget>" [--evaluator <path> --metric "<m>"]]
8
9
  scaffold a line
9
10
  tezgah-research commit <slug> "<message>" commit the line in .tezgah's own repo
10
- tezgah-research check [<slug>] [--json] [--strict] [--orx] [--all-lines] [-- <slug>]
11
- the discipline checks
11
+ (the project's, when it tracks .tezgah)
12
+ tezgah-research check [<slug>] [--json] [--strict] [--orx] [--online] [--all-lines]
13
+ [-- <slug>] the discipline checks
12
14
  tezgah-research status one line per research line
13
15
  tezgah-research --all every checkout's lines (git worktrees)
14
16
  tezgah-research claim <slug> record one claim from stdin
@@ -16,7 +18,9 @@
16
18
  tezgah-research components [--json] what predicts what, per component
17
19
  tezgah-research migrate <slug> [--dry-run] derive fields the rules require
18
20
  tezgah-research source <slug> <hypothesis> --run <orxRunId> [--command "<cmd>"]
21
+ [--instrument <name>] [--arm <a>] [--item <i>] [--value <field>=<number>]...
19
22
  [--scope real|fixture|derived] [--fixture "<what was generated>"]
23
+ [--ack "<the user's words>"]
20
24
  tezgah-research compare <slug> <decision> record one variants x criteria cell from stdin
21
25
  tezgah-research verdict <slug> <id> met|not-met|unanswerable --evidence "<ref>"
22
26
  record one success criterion's verdict
@@ -37,6 +41,23 @@
37
41
  tezgah-research dedup <slug> [--threshold <(0,1]>] [--json]
38
42
  cluster the proposed ideas, write nothing
39
43
  tezgah-research yield [--json] [--all-lines] how far ideas got, per operator and family
44
+ tezgah-research cite <slug> query four registries for each formal INDEX id
45
+ tezgah-research fetch <slug> <note> [--file <path> --ack "<the user's words>" | --orx]
46
+ capture a note's source text and its quotes
47
+ tezgah-research search <slug> --tag primary|snowball|counter|known [--item "<scope.in item>"]
48
+ -- <connector> <args...> capture one search on an allowlisted connector
49
+ tezgah-research instrument add <slug> <name> --kind measure|verdict --rung R1|R2|R3|R4
50
+ --construct "<text>" register an instrument
51
+ tezgah-research gold <slug> <instrument> --arm <a> --n N --seed S
52
+ draw an arm's seeded gold sample
53
+ tezgah-research label <slug> <instrument> --arm <a> (--human "<name>" --ack "<the user's words>"
54
+ | --provider openrouter --model <m>)
55
+ label an arm's gold sample
56
+ tezgah-research switch <slug> <instrument> (--to R1|R2|R3|R4|<method> | --narrow "<what the
57
+ claims now say>") --reason "<why>"
58
+ record a switch away from an instrument
59
+ tezgah-research release-check [--fixtures <dir>] score the known-truth cases, exit 1 past the bounds
60
+ tezgah-research calibration Brier score over resolved hypotheses
40
61
 
41
62
  A research line lives at <repo>/.tezgah/research/<slug>/ and holds the state an
42
63
  auditable investigation needs: the question, the decision log, the findings, the
@@ -47,7 +68,11 @@ and the review a concluded line reports. `check` exits 1 when a line breaks thos
47
68
  rules, so a hook or a person can act on it. The project ignores `.tezgah/`; the
48
69
  commits the order rule reads are made in `.tezgah`'s own private git repository,
49
70
  which `init` creates and `commit` writes to, and a line the project itself
50
- committed before the move keeps its order proof in the project's history.
71
+ committed before the move keeps its order proof in the project's history. A
72
+ folded `.tezgah` - one the project tracks, with no repository of its own - has
73
+ only the project's history, so `commit` commits the line there, after the
74
+ message passes the gate's own language and attribution readers (exit 2 and
75
+ the gate's refusal when it does not, nothing committed).
51
76
 
52
77
  `check` with no slug reports the open lines in full; a line under `done/` is
53
78
  verified by its order seal's hashes alone and named only when they fail, with
@@ -116,7 +141,8 @@ append. `board`, `dedup` and `yield` are reports: they write nothing and exit 0.
116
141
  Exit codes: 0 clean, 1 problems found - a broken line for `check`, a refused
117
142
  claim for `claim`, a refused row for `predict`, `idea`, `stage` or `match`, which
118
143
  writes nothing and prints one reason per problem, or a new line refused for
119
- `init` over unfinished ones - 2 misuse.
144
+ `init` over unfinished ones - 2 misuse, or a folded `commit` whose message the
145
+ gate would refuse.
120
146
  """
121
147
  import json
122
148
  import os
@@ -158,9 +184,28 @@ def misuse(message):
158
184
  return 2
159
185
 
160
186
 
187
+ INIT_USAGE = ('init <slug> --ask "<the user\'s words>" [--tier quick|study|program]'
188
+ ' [--method qualitative|measured|exploratory] [--class R1..R12]'
189
+ ' [--in "<covered>"]... [--out "<left alone>"]... [--question "..."]'
190
+ ' [--allow-open "<reason>"] [--supersedes <slug>]'
191
+ ' [--arena "<problem>" --budget "<budget>"'
192
+ ' [--evaluator <path> --metric "<metric>"]]')
193
+ INIT_EXAMPLE = ('tezgah-research init cache-latency --ask "does the cache cut p95?" '
194
+ '--method measured --in "p95 of the read path" --out "write path"')
195
+
196
+
161
197
  def cmd_init(args):
198
+ # R0 is refused before any other argument is read (spec 3.3): a factual or
199
+ # reference question gets its answer in the reply, never a line
200
+ if any(a == "--class" and b == "R0" for a, b in zip(args, args[1:])):
201
+ print("FAIL init: R0 gets no line: a factual or reference question is answered "
202
+ "in the reply with its evidence")
203
+ return 1
162
204
  if not args:
163
205
  return misuse("init needs a slug")
206
+ if args[0] in ("-h", "--help"):
207
+ print("usage: tezgah-research %s\nexample: %s" % (INIT_USAGE, INIT_EXAMPLE))
208
+ return 0
164
209
  slug = args[0].strip().lower().replace(" ", "-")
165
210
  if not tr.valid_slug(slug):
166
211
  # A slug is the directory name the other commands list, so anything that
@@ -170,7 +215,7 @@ def cmd_init(args):
170
215
  "and dashes" % args[0])
171
216
  question, allow, supersedes = "", None, None
172
217
  ask, tier, method, scope_in, scope_out = "", str(tr.DEFAULT_TIER), "", [], []
173
- arena = {}
218
+ arena, question_class = {}, ""
174
219
  rest = args[1:]
175
220
  while rest:
176
221
  flag = rest.pop(0)
@@ -184,6 +229,9 @@ def cmd_init(args):
184
229
  method = rest.pop(0)
185
230
  elif flag == "--in" and rest:
186
231
  scope_in.append(rest.pop(0))
232
+ elif flag == "--class" and rest and rest[0] in tr.QUESTION_CLASSES[1:] \
233
+ and not question_class:
234
+ question_class = rest.pop(0)
187
235
  elif flag == "--out" and rest:
188
236
  scope_out.append(rest.pop(0))
189
237
  elif flag == "--allow-open" and rest:
@@ -194,12 +242,7 @@ def cmd_init(args):
194
242
  and flag not in arena:
195
243
  arena[flag] = rest.pop(0)
196
244
  else:
197
- return misuse('init <slug> --ask "<the user\'s words>" [--tier quick|study|program]'
198
- ' [--method qualitative|measured|exploratory] [--in "<covered>"]...'
199
- ' [--out "<left alone>"]... [--question "..."]'
200
- ' [--allow-open "<reason>"] [--supersedes <slug>]'
201
- ' [--arena "<problem>" --budget "<budget>"'
202
- ' [--evaluator <path> --metric "<metric>"]]')
245
+ return misuse(INIT_USAGE)
203
246
  if method == "exploratory":
204
247
  # The arena is the lock an exploratory line commits before its first idea,
205
248
  # so a line without one is a call that cannot work, not a line to repair.
@@ -222,6 +265,9 @@ def cmd_init(args):
222
265
  if problems:
223
266
  for problem in problems:
224
267
  print("FAIL init: %s" % problem)
268
+ if not ask.strip():
269
+ print("usage: tezgah-research %s\nexample: %s" % (INIT_USAGE, INIT_EXAMPLE),
270
+ file=sys.stderr)
225
271
  return 1
226
272
  if allow is not None and not allow.strip():
227
273
  return misuse("--allow-open needs the reason the new line is worth opening "
@@ -267,7 +313,8 @@ def cmd_init(args):
267
313
  arena.get("--metric", "").strip())
268
314
  made = tr.init(repo, slug, question=question, created=created,
269
315
  supersedes=supersedes, ask=ask, tier=tier, method=method,
270
- scope_in=scope_in, scope_out=scope_out, arena=record)
316
+ scope_in=scope_in, scope_out=scope_out, arena=record,
317
+ question_class=question_class)
271
318
  if allow is not None:
272
319
  problem = tr.note_open(repo, slug, allow, created)
273
320
  if problem:
@@ -278,12 +325,17 @@ def cmd_init(args):
278
325
  print(" wrote %s" % path)
279
326
  for problem in tr.scope_problems(tr.line_state(repo, slug)):
280
327
  print(" owed: %s" % problem)
328
+ if question_class:
329
+ print("obligations: %s" % ", ".join(tr.obligations(question_class, method)))
330
+ print(tr.budget(slug, tr.line_dir(repo, slug), tr.line_state(repo, slug))[0])
331
+ for line, cid, status, sim in tr.overlaps(repo, question or ask, slug):
332
+ print("overlap: %s/%s %s %.2f" % (line, cid, status, sim))
281
333
  if method == "exploratory":
282
- print("\nnext: commit the arena now, before any idea - `tezgah-research commit "
334
+ print("\nnext: commit the arena now, before any idea - `~/.config/tezgah/bin/tezgah-research commit "
283
335
  "%s \"arena\"`; an idea committed with it or before it is refused. Then "
284
- "record ideas (`tezgah-research idea %s`, one JSON row on stdin, each "
336
+ "record ideas (`~/.config/tezgah/bin/tezgah-research idea %s`, one JSON row on stdin, each "
285
337
  "naming its operator, generator and kill result), commit them, and "
286
- "follow `tezgah-research board %s`: dedup, prior art, matches, pilots, a "
338
+ "follow `~/.config/tezgah/bin/tezgah-research board %s`: dedup, prior art, matches, pilots, a "
287
339
  "full run, a confirmation on unseen data." % (slug, slug, slug))
288
340
  elif method == "qualitative":
289
341
  print("\nnext: read the primary sources for each state.json scope.in item "
@@ -293,7 +345,7 @@ def cmd_init(args):
293
345
  else:
294
346
  print("\nnext: write experiments/<hypothesis>/protocol.md - what the change "
295
347
  "is, what it predicts, what result would falsify it, why - and COMMIT "
296
- "it before the run: `tezgah-research commit %s \"protocol "
348
+ "it before the run: `~/.config/tezgah/bin/tezgah-research commit %s \"protocol "
297
349
  "<hypothesis>\"`. Then record the run in results.jsonl and commit it "
298
350
  "the same way, in a later commit. The commits land in `.tezgah`'s own "
299
351
  "git repository (the project ignores `.tezgah/`). Then analyse it in "
@@ -304,8 +356,10 @@ def cmd_init(args):
304
356
 
305
357
 
306
358
  def cmd_commit(args):
307
- """Commit one line in the private `.tezgah` repository - the commit the order
308
- rule reads. Only the line's own path is staged and committed."""
359
+ """Commit one line in the private `.tezgah` repository, or in the project's
360
+ when `.tezgah` is folded - the commit the order rule reads. Only the line's
361
+ own paths are staged and committed: every layout location of the slug, so
362
+ the move `conclude` makes from `open/` to `done/` lands whole."""
309
363
  if len(args) != 2 or not args[1].strip():
310
364
  return misuse('commit <slug> "<message>"')
311
365
  slug, message = args
@@ -313,21 +367,41 @@ def cmd_commit(args):
313
367
  known = tr.slugs(repo)
314
368
  if slug not in known:
315
369
  return misuse("no such research line (have: %s)" % (", ".join(known) or "none"))
316
- return commit_path(repo, tr.line_dir(repo, slug), message)
370
+ return commit_path(repo, [os.path.join(f, slug) for f in tr.layout_roots(repo)],
371
+ message)
372
+
317
373
 
374
+ def present(paths, base, ls_files):
375
+ """The paths relative to `base` that exist on disk or that git still
376
+ tracks: a pathspec matching nothing would make `git add` fail."""
377
+ rels = [os.path.relpath(p, base) for p in paths]
378
+ tracked = ls_files(*rels).splitlines() if rels else []
379
+ return [r for r, p in zip(rels, paths) if os.path.lexists(p) or any(
380
+ t == r or t.startswith(r + "/") for t in tracked)]
318
381
 
319
- def commit_path(repo, path, message):
320
- """Stage and commit `path` alone in the private repository of `repo`."""
382
+
383
+ def commit_path(repo, paths, message):
384
+ """Stage and commit `paths` alone in the private repository of `repo`, or in
385
+ the project's own when `.tezgah` is folded - tracked by the project, with no
386
+ repository of its own (`tr.folded`)."""
321
387
  ws = tp.ensure_workspace(repo)
388
+ if ws is None and tr.folded(repo):
389
+ return commit_project(repo, paths, message)
322
390
  if ws is None:
323
391
  print("commit refused: %s is not a git work tree (or .tezgah could not be "
324
392
  "set up), so there is no private repository to commit into" % repo)
325
393
  return 1
326
- rel = os.path.relpath(path, ws)
327
394
  try:
328
- done = tp.ws_git(repo, "add", "-A", "--", rel)
395
+ rels = present(paths, ws, lambda *r: tp.ws_git(repo, "ls-files", "--", *r).stdout)
396
+ done = tp.ws_git(repo, "add", "-A", "--", *rels)
397
+ if not done.returncode and not tp.ws_git(repo, "diff", "--cached", "--quiet",
398
+ "--", *rels).returncode:
399
+ # a writer that commits its own capture (`source`, `cite`) leaves nothing
400
+ # for the session's commit, which is not a failure (plan 128 K10)
401
+ print("nothing to commit: %s is already committed in %s" % (" ".join(rels), ws))
402
+ return 0
329
403
  if not done.returncode:
330
- done = tp.ws_git(repo, "commit", "-q", "-m", message, "--", rel)
404
+ done = tp.ws_git(repo, "commit", "-q", "-m", message, "--", *rels)
331
405
  except OSError as exc:
332
406
  print("commit failed: %s" % exc)
333
407
  return 1
@@ -335,7 +409,62 @@ def commit_path(repo, path, message):
335
409
  print("commit failed: %s" % (done.stderr or done.stdout).strip())
336
410
  return 1
337
411
  sha = tp.ws_git(repo, "rev-parse", "HEAD").stdout.strip()
338
- print("committed %s in %s at %s" % (rel, ws, sha))
412
+ print("committed %s in %s at %s" % (" ".join(rels), ws, sha))
413
+ return 0
414
+
415
+
416
+ def message_refusal(message):
417
+ """The refusal the gate prints for `message` as a `git commit -m` value, or
418
+ None. A folded `commit` writes the project's own history, which the gate
419
+ never sees through this command, so the message meets the gate's own
420
+ readers here: the language reader `lang_reason` hands each subject to
421
+ (`tezgah_lang.refusal`), then the credit forms `attribution` matches
422
+ (`ATTRIB`), under the same switches."""
423
+ if tp.off("pretooluse-off"):
424
+ return None
425
+ import tezgah_gate as gate # deferred: only a folded commit pays the import
426
+ if gate.tezgah_lang is not None and not tp.off("lang-off"):
427
+ reason = gate.tezgah_lang.refusal("commit subject", message)
428
+ if reason:
429
+ return reason
430
+ return gate.ATTRIB_DENY if gate.ATTRIB.search(message) else None
431
+
432
+
433
+ def commit_project(repo, paths, message):
434
+ """Stage and commit `paths` alone in the project's repository: the history a
435
+ folded `.tezgah` lives in. Anything else the owner staged stays staged and
436
+ out of this commit (`commit -- <paths>`); the project's identity, signing and
437
+ hooks apply, since this is the project's own history. A message the gate
438
+ would refuse is refused first, exit 2, and nothing is staged."""
439
+ refused = message_refusal(message)
440
+ if refused:
441
+ print("commit refused: %s" % refused, file=sys.stderr)
442
+ return 2
443
+ git = ["git", "-C", repo]
444
+ try:
445
+ rels = present(paths, repo, lambda *r: subprocess.run(
446
+ git + ["ls-files", "--"] + list(r), capture_output=True, text=True).stdout)
447
+ done = subprocess.run(git + ["add", "-A", "--"] + rels, capture_output=True,
448
+ text=True)
449
+ if not done.returncode and not subprocess.run(
450
+ git + ["diff", "--cached", "--quiet", "--"] + rels).returncode:
451
+ print("nothing to commit: %s is already committed in the project repository %s"
452
+ % (" ".join(rels), repo))
453
+ return 0
454
+ if not done.returncode:
455
+ done = subprocess.run(git + ["commit", "-q", "-m", message, "--"] + rels,
456
+ capture_output=True, text=True)
457
+ except OSError as exc:
458
+ print("commit failed: %s" % exc)
459
+ return 1
460
+ if done.returncode:
461
+ print("commit failed: %s" % (done.stderr or done.stdout).strip())
462
+ return 1
463
+ sha = subprocess.run(git + ["rev-parse", "HEAD"], capture_output=True,
464
+ text=True).stdout.strip()
465
+ print("committed %s in the project repository %s at %s (.tezgah is tracked by "
466
+ "the project, so the project's history carries the line)"
467
+ % (" ".join(rels), repo, sha))
339
468
  return 0
340
469
 
341
470
 
@@ -346,13 +475,14 @@ def cmd_check(args):
346
475
  as_json = "--json" in flags
347
476
  strict = "--strict" in flags
348
477
  ask_orx = "--orx" in flags
478
+ online = "--online" in flags
349
479
  all_lines = "--all-lines" in flags
350
480
  rest = [a for a in flags
351
- if a not in ("--json", "--strict", "--orx", "--all-lines")] + after
481
+ if a not in ("--json", "--strict", "--orx", "--online", "--all-lines")] + after
352
482
  repo = repo_root(os.getcwd())
353
483
  if len(rest) > 1:
354
- return misuse("check [<slug>] [--json] [--strict] [--orx] [--all-lines] "
355
- "[-- <slug>]")
484
+ return misuse("check [<slug>] [--json] [--strict] [--orx] [--online] "
485
+ "[--all-lines] [-- <slug>]")
356
486
  known = tr.slugs(repo)
357
487
  if rest and rest[0] not in known:
358
488
  print("FAIL %s: no such research line (have: %s)"
@@ -362,13 +492,18 @@ def cmd_check(args):
362
492
  report = {}
363
493
  if known:
364
494
  report = tr.check(repo, rest[0] if rest else None, strict=strict,
365
- all_lines=all_lines, code=checkout_root(os.getcwd()))
495
+ all_lines=all_lines, code=checkout_root(os.getcwd()),
496
+ flags={"online": online, "orx": ask_orx})
366
497
  for slug, row in report.items():
367
498
  for err in row["errors"]:
368
499
  problems += 1
369
500
  print("FAIL %s: %s" % (slug, err))
370
501
  for warn in row["warnings"]:
371
502
  print("warn %s: %s" % (slug, warn))
503
+ # rules 8's report lines (certainty, stats, effect, budget, ...): never
504
+ # problems, and inside the JSON row rather than before it
505
+ for line in [] if as_json else row.get("report", []):
506
+ print(line)
372
507
  else:
373
508
  print("no research line under %s" % tr.root(repo))
374
509
  lines = len(report)
@@ -559,13 +694,21 @@ def cmd_migrate(args):
559
694
 
560
695
  def cmd_source(args):
561
696
  """File one orx run's log as the receipt of an experiment."""
562
- usage = ('source <slug> <hypothesis> --run <orxRunId> [--command "<cmd>"] '
563
- '[--scope real|fixture|derived] [--fixture "<what was generated>"]')
697
+ import re
698
+ import tezgah_research_capture as cap
699
+ reserved = ("source", "log", "run", "arm", "item", "instrument", "scope", "fixture",
700
+ "status", "command", "ack")
701
+ usage = ('source <slug> <hypothesis> --run <orxRunId> [--instrument <name>] [--arm <a>] '
702
+ '[--item <i>] [--value <field>=<number>]... [--command "<cmd>"] '
703
+ '[--scope real|fixture|derived] [--fixture "<what was generated>"] '
704
+ '[--ack "<the user\'s words>"]')
564
705
  if len(args) < 2:
565
706
  return misuse(usage)
566
707
  slug, hypothesis = args[0], args[1]
567
- run = command = scope = ""
708
+ run = command = scope = arm = item = ack = ""
709
+ instrument = None
568
710
  fixture = None
711
+ values = []
569
712
  rest = args[2:]
570
713
  while rest:
571
714
  flag = rest.pop(0)
@@ -577,6 +720,22 @@ def cmd_source(args):
577
720
  scope = rest.pop(0)
578
721
  elif flag == "--fixture" and rest:
579
722
  fixture = rest.pop(0)
723
+ elif flag == "--instrument" and rest:
724
+ instrument = rest.pop(0)
725
+ elif flag == "--arm" and rest:
726
+ arm = rest.pop(0)
727
+ elif flag == "--item" and rest:
728
+ item = rest.pop(0)
729
+ elif flag == "--ack" and rest:
730
+ ack = rest.pop(0)
731
+ elif flag == "--value" and rest:
732
+ field, _eq, number = rest.pop(0).partition("=")
733
+ if field in reserved:
734
+ return misuse("--value %s: %s is a reserved row key" % (field, field))
735
+ if not re.fullmatch(r"[A-Za-z_][\w.-]*", field) or not re.fullmatch(
736
+ cap.VALUE_NUMBER, number):
737
+ return misuse("--value needs <field>=<number>, not %r" % (field + _eq + number))
738
+ values.append((field, number))
580
739
  else:
581
740
  return misuse(usage)
582
741
  if "/" in hypothesis or "\\" in hypothesis or hypothesis.startswith("."):
@@ -588,6 +747,10 @@ def cmd_source(args):
588
747
  return misuse("--scope %r is not one of %s" % (scope, ", ".join(tr.SCOPES)))
589
748
  if fixture is not None and not fixture.strip():
590
749
  return misuse("--fixture needs the text naming what was generated")
750
+ if instrument is not None and not instrument.strip():
751
+ return misuse("--instrument needs the instrument's name")
752
+ if ack and not ack.strip():
753
+ return misuse('--ack needs "<the user\'s words>" for a log above the bound')
591
754
  repo = repo_root(os.getcwd())
592
755
  known = tr.slugs(repo)
593
756
  if slug not in known:
@@ -597,16 +760,15 @@ def cmd_source(args):
597
760
  return misuse("orx is not installed, so no run log can be read; nothing "
598
761
  "was written (TEZGAH_ORX_BIN overrides the lookup)")
599
762
  path, problems = tr.source_run(repo, slug, hypothesis, run, orx, command, scope,
600
- fixture or "")
763
+ fixture or "", arm, item, values, instrument or "", ack)
601
764
  if problems:
602
765
  for problem in problems:
603
766
  print("FAIL %s: %s" % (slug, problem))
604
767
  return 1
605
768
  print("receipt %s" % path)
606
- print('row {"source": "orx:%s", "log": "raw/%s.log"%s%s%s}'
607
- % (run, run, ', "command": %s' % json.dumps(command) if command else "",
608
- ', "scope": %s' % json.dumps(scope) if scope else "",
609
- ', "fixture": %s' % json.dumps(fixture) if fixture else ""))
769
+ rows = tr._row_objects(os.path.join(os.path.dirname(os.path.dirname(path)),
770
+ "results.jsonl"))
771
+ print("row %s" % json.dumps(rows[-1] if rows else {}))
610
772
  if not scope:
611
773
  print("note: the row declares no scope, so nothing says whether this run "
612
774
  "measured the running system or an input you generated; re-file with "
@@ -1062,9 +1224,23 @@ def main(argv):
1062
1224
  "board": cmd_board, "dedup": cmd_dedup, "yield": cmd_yield}
1063
1225
  if cmd in campaign:
1064
1226
  return campaign[cmd](rest)
1227
+ # rules 8's capture and evidence commands, imported only when asked for so a
1228
+ # missing optional module never breaks another command. Each handler takes
1229
+ # (repo, args), prints its own output and returns its exit code; `release-check`
1230
+ # and `calibration` need no line and run from any directory.
1231
+ import importlib
1232
+ for name in ("tezgah_research_capture", "tezgah_research_evidence"):
1233
+ try:
1234
+ commands = importlib.import_module(name).COMMANDS
1235
+ except (ImportError, AttributeError):
1236
+ continue
1237
+ if cmd in commands:
1238
+ return commands[cmd](repo_root(os.getcwd()), rest)
1065
1239
  return misuse("unknown command %r (init, commit, check, status, --all, claim, predict, "
1066
1240
  "components, migrate, source, compare, verdict, conclude, migrate-layout, "
1067
- "close, seal, import, next, idea, stage, match, board, dedup, yield)" % cmd)
1241
+ "close, seal, import, next, idea, stage, match, board, dedup, yield, cite, "
1242
+ "fetch, search, instrument, gold, label, switch, release-check, "
1243
+ "calibration)" % cmd)
1068
1244
 
1069
1245
 
1070
1246
  if __name__ == "__main__":
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env python3
2
+ """tezgah-review-quote - place review findings on the diff by their quoted code.
3
+
4
+ tezgah-review-quote [--repo DIR] --from BASE [--to HEAD] FINDINGS_JSON
5
+
6
+ FINDINGS_JSON is a file (or `-` for stdin) holding a JSON list of objects with
7
+ at least `path` and `quote`. Prints that list with `status` added:
8
+ `located` (the quote is in its own file), `relocated` (it is nowhere in its own
9
+ file but exactly once in another changed file; `path` moves there) or
10
+ `unlocated`; a placed finding gets `start_line`/`end_line`, plus `side: "old"`
11
+ when the lines are pre-change. A quote found several times in its own file is
12
+ placed on the match covering the finding's own `start_line`, else it is
13
+ `unlocated` with `reason: "ambiguous: N matches"`.
14
+
15
+ A Python port of the deterministic comment positioning in
16
+ alibaba/open-code-review (internal/diff/resolver.go: ResolveComment,
17
+ RelocateAcrossFiles; Apache-2.0): each line is trimmed, one leading `+` then
18
+ `-` marker is stripped, blank quote lines are dropped, and the quote must match
19
+ consecutive lines - the hunks' new side, then their old side, then the whole
20
+ new file (where blank file lines are skipped too). Unlike OCR, which takes the
21
+ first match, every match is collected so a repeated quote is never placed on
22
+ the wrong copy; a cited line only chooses among the quote's matches.
23
+ """
24
+ import argparse
25
+ import json
26
+ import subprocess
27
+ import sys
28
+
29
+
30
+ def norm(line):
31
+ return line.strip().removeprefix("+").removeprefix("-").strip()
32
+
33
+
34
+ def quote_lines(text):
35
+ return [n for n in map(norm, text.split("\n")) if n]
36
+
37
+
38
+ def git(repo, *args):
39
+ return subprocess.run(["git", "-C", repo, *args], capture_output=True,
40
+ text=True, errors="replace")
41
+
42
+
43
+ def strip_prefix(path):
44
+ # ponytail: C-quoted paths (tabs, quotes in names) are not unquoted
45
+ if path == "/dev/null":
46
+ return None
47
+ return path[2:] if path[:2] in ("a/", "b/") else path
48
+
49
+
50
+ def parse_diff(text):
51
+ """One dict per changed file: old/new path and the hunks' two sides as
52
+ [(line_number, normalised_text, removed)] lists, one pair per hunk."""
53
+ files, cur, old_no, new_no = [], None, 0, 0
54
+ for line in text.split("\n"):
55
+ if line.startswith("diff --git "):
56
+ cur = {"old": None, "new": None, "hunks": []}
57
+ files.append(cur)
58
+ elif cur is None:
59
+ continue
60
+ elif line.startswith("--- ") and not cur["hunks"]:
61
+ cur["old"] = strip_prefix(line[4:].rstrip("\t"))
62
+ elif line.startswith("+++ ") and not cur["hunks"]:
63
+ cur["new"] = strip_prefix(line[4:].rstrip("\t"))
64
+ elif line.startswith("@@"):
65
+ spans = line.split("@@")[1].split()
66
+ old_no = int(spans[0][1:].split(",")[0])
67
+ new_no = int(spans[1][1:].split(",")[0])
68
+ cur["hunks"].append(([], []))
69
+ elif cur["hunks"] and not line.startswith("\\"):
70
+ new_side, old_side = cur["hunks"][-1]
71
+ mark, body = line[:1], norm(line[1:])
72
+ if mark in (" ", ""):
73
+ new_side.append((new_no, body, False))
74
+ old_side.append((old_no, body, False))
75
+ new_no += 1
76
+ old_no += 1
77
+ elif mark == "+":
78
+ new_side.append((new_no, body, False))
79
+ new_no += 1
80
+ elif mark == "-":
81
+ old_side.append((old_no, body, True))
82
+ old_no += 1
83
+ return files
84
+
85
+
86
+ def matches(side, target):
87
+ """Every consecutive run of `target` in `side`: (start, end, run)."""
88
+ n = len(target)
89
+ return [(side[i][0], side[i + n - 1][0], side[i:i + n])
90
+ for i in range(len(side) - n + 1)
91
+ if all(side[i + j][1] == target[j] for j in range(n))]
92
+
93
+
94
+ def resolve(f, target, content):
95
+ """Every distinct (start, end, side) of `target` in one changed file: the
96
+ hunks' new side, their old side, then the whole new file."""
97
+ hits = [(s, e, "new") for hunk in f["hunks"] for s, e, _ in matches(hunk[0], target)]
98
+ # an old-side run of context lines only repeats a new-side one
99
+ hits += [(s, e, "old") for hunk in f["hunks"]
100
+ for s, e, run in matches(hunk[1], target) if any(p[2] for p in run)]
101
+ if content is not None:
102
+ lines = [(i, norm(t.rstrip("\r")))
103
+ for i, t in enumerate(content.split("\n"), 1)]
104
+ hits += [(s, e, "new") for s, e, _ in matches([p for p in lines if p[1]], target)]
105
+ return list(dict.fromkeys(hits))
106
+
107
+
108
+ def cited(finding):
109
+ try:
110
+ return int(finding.get("start_line"))
111
+ except (TypeError, ValueError):
112
+ return None
113
+
114
+
115
+ def place(finding, f, hit):
116
+ out = dict(finding, path=f["new"] or f["old"],
117
+ start_line=hit[0], end_line=hit[1])
118
+ out.pop("side", None)
119
+ if hit[2] == "old":
120
+ out["side"] = "old"
121
+ return out
122
+
123
+
124
+ def main(argv=None):
125
+ ap = argparse.ArgumentParser(prog="tezgah-review-quote")
126
+ ap.add_argument("--repo", default=".")
127
+ ap.add_argument("--from", dest="base", required=True)
128
+ ap.add_argument("--to", default="HEAD")
129
+ ap.add_argument("findings")
130
+ a = ap.parse_args(argv)
131
+ try:
132
+ src = sys.stdin if a.findings == "-" else open(a.findings, encoding="utf-8")
133
+ with src:
134
+ findings = json.load(src)
135
+ if not isinstance(findings, list) or not all(
136
+ isinstance(x, dict) and "path" in x and "quote" in x for x in findings):
137
+ raise ValueError("expected a JSON list of objects with path and quote")
138
+ except (OSError, ValueError) as e:
139
+ print(f"tezgah-review-quote: {a.findings}: {e}", file=sys.stderr)
140
+ return 2
141
+ diff = git(a.repo, "diff", "--no-ext-diff", "--no-textconv", "--no-color",
142
+ "--src-prefix=a/", "--dst-prefix=b/", "-U3", a.base, a.to)
143
+ if diff.returncode != 0:
144
+ print(f"tezgah-review-quote: git diff: {diff.stderr.strip()}", file=sys.stderr)
145
+ return 2
146
+ files, contents = parse_diff(diff.stdout), {}
147
+
148
+ def content(f):
149
+ if f["new"] and f["new"] not in contents:
150
+ r = git(a.repo, "show", f"{a.to}:{f['new']}")
151
+ contents[f["new"]] = r.stdout if r.returncode == 0 else None
152
+ return contents.get(f["new"])
153
+
154
+ out = []
155
+ for finding in findings:
156
+ target = quote_lines(str(finding["quote"] or ""))
157
+ own = [f for f in files if finding["path"] in (f["new"], f["old"])]
158
+ mine = resolve(own[0], target, content(own[0])) if target and own else []
159
+ line = cited(finding)
160
+ covering = [h for h in mine if line is not None and h[0] <= line <= h[1]]
161
+ # OCR's order: the new side wins over the old one, so a whitespace-only
162
+ # change matching on both sides is one new-side hit, not an ambiguity
163
+ new = [h for h in mine if h[2] == "new"]
164
+ pick = covering or (new if len(new) == 1 else []) or (mine if len(mine) == 1 else [])
165
+ if pick:
166
+ out.append(dict(place(finding, own[0], pick[0]), status="located"))
167
+ continue
168
+ if mine:
169
+ out.append(dict(finding, status="unlocated",
170
+ reason=f"ambiguous: {len(new) or len(mine)} matches"))
171
+ continue
172
+ hits = [] if not target else [
173
+ (f, h) for f in files if f not in own
174
+ for h in resolve(f, target, content(f))]
175
+ if len(hits) == 1:
176
+ out.append(dict(place(finding, *hits[0]), status="relocated"))
177
+ else:
178
+ out.append(dict(finding, status="unlocated"))
179
+ json.dump(out, sys.stdout, indent=2)
180
+ sys.stdout.write("\n")
181
+ return 0
182
+
183
+
184
+ if __name__ == "__main__":
185
+ sys.exit(main())