@r1z4x/tezgah 1.9.2 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +415 -1
- package/MANIFEST +404 -144
- package/README.de.md +1 -1
- package/README.es.md +1 -1
- package/README.fr.md +1 -1
- package/README.md +5 -4
- package/README.tr.md +1 -1
- package/bin/codegen +5 -2
- package/bin/tezgah-design +288 -1
- package/bin/tezgah-docs +1 -1
- package/bin/tezgah-doctor +39 -2
- package/bin/tezgah-import-ai-research +26 -12
- package/bin/tezgah-ocr-review +296 -0
- package/bin/tezgah-research +255 -44
- package/bin/tezgah-review-quote +185 -0
- package/bin/tezgah-setup +1365 -55
- package/bin/tezgah-skill +1 -1
- package/bin/tezgah-status +201 -3
- package/bin/tezgah-task +258 -20
- package/commands/adhd.md +2 -2
- package/commands/ponytail.md +4 -4
- package/docs/architecture.md +2 -2
- package/docs/citations-baseline.json +3 -3
- package/docs/clarity-baseline.json +11 -5
- package/docs/contract.md +91 -43
- package/docs/environment.md +5 -2
- package/docs/evidence.md +109 -17
- package/docs/feature-audit.md +2 -2
- package/docs/gate.md +60 -33
- package/docs/glossary.md +6 -3
- package/docs/hosts.md +313 -17
- package/docs/index.json +34 -8
- package/docs/judge.md +4 -2
- package/docs/layers.md +4 -4
- package/docs/models.md +37 -9
- package/docs/operations.md +141 -5
- package/docs/research.md +815 -8
- package/docs/skills.md +137 -13
- package/docs/status-line.md +121 -1
- package/docs/testing.md +3 -1
- package/hooks/hooks.json +2 -2
- package/hooks/lang/en.json +21 -0
- package/hooks/lang/tr.json +22 -1
- package/hooks/projects-stop.py +2 -1
- package/hooks/tezgah_agents.py +65 -25
- package/hooks/tezgah_apps.py +18 -0
- package/hooks/tezgah_attest.py +79 -10
- package/hooks/tezgah_components.py +4 -0
- package/hooks/tezgah_context.py +207 -55
- package/hooks/tezgah_extension.py +337 -0
- package/hooks/tezgah_gate.py +267 -79
- package/hooks/tezgah_integrity.py +864 -143
- package/hooks/tezgah_judge.py +6 -4
- package/hooks/tezgah_models.py +59 -19
- package/hooks/tezgah_orca.py +1 -1
- package/hooks/tezgah_paths.py +145 -8
- package/hooks/tezgah_policy.py +128 -57
- package/hooks/tezgah_rank.py +9 -6
- package/hooks/tezgah_replay.py +12 -6
- package/hooks/tezgah_research.py +1414 -76
- package/hooks/tezgah_research_capture.py +1544 -0
- package/hooks/tezgah_research_evidence.py +842 -0
- package/hooks/tezgah_research_stats.py +258 -0
- package/hooks/tezgah_skill_pick.py +408 -106
- package/hooks/tezgah_stack.py +236 -1
- package/hooks/tezgah_stopspec.py +8 -1
- package/hooks/tezgah_task.py +14 -5
- package/hooks/tezgah_taste_ledger.py +1 -1
- package/hosts/amp/hook.py +217 -0
- package/hosts/amp/tezgah-plugin.ts.in +386 -0
- package/hosts/antigravity/hook.py +255 -0
- package/hosts/codex/hook.py +2 -1
- package/hosts/commandcode/hook.py +239 -0
- package/hosts/copilot/hook.py +284 -0
- package/hosts/cursor/hook.py +31 -3
- package/hosts/droid/hook.py +259 -0
- package/hosts/dsh/hooks.json +1 -1
- package/hosts/gemini/hook.py +213 -0
- package/hosts/goose/hook.py +145 -0
- package/hosts/omp/hook.py +4 -1
- package/hosts/omp/tezgah-hook.ts.in +30 -7
- package/hosts/opencode/plugins/tezgah.js +309 -48
- package/hosts/opencode/tui/cli/tui.tsx +100 -0
- package/hosts/opencode/tui/tezgah-tui.tsx +2 -1
- package/hosts/qwen/hook.py +206 -0
- package/output-styles/tezgah.md +20 -15
- package/package.json +1 -1
- package/skills/ai-research/SKILL.md +21 -14
- package/skills/ai-research/SOURCE +7 -5
- package/skills/ai-research/index/1-frame.md +6 -6
- package/skills/ai-research/index/2-data.md +9 -9
- package/skills/ai-research/index/3-train.md +36 -36
- package/skills/ai-research/index/4-measure.md +13 -13
- package/skills/ai-research/index/5-run.md +11 -11
- package/skills/ai-research/index/6-write.md +23 -23
- package/skills/ai-research/library.json +104 -104
- package/skills/analyze-app/SKILL.md +17 -12
- package/skills/design-contract/SKILL.md +42 -7
- package/skills/design-contract/data-views.md +2 -2
- package/skills/design-library/EVALS.md +1 -1
- package/skills/design-library/INDEX.md +39 -39
- package/skills/design-library/SKILL.md +19 -13
- package/skills/design-library/SOURCE +45 -43
- package/skills/feature-audit/SKILL.md +20 -14
- package/skills/hallmark/LICENSE +21 -0
- package/skills/hallmark/SKILL.md +154 -0
- package/skills/hallmark/SOURCE +207 -0
- package/skills/hallmark/agents/openai.yaml +13 -0
- package/skills/hallmark/references/anatomy.md +71 -0
- package/skills/hallmark/references/brand-truth.md +40 -0
- package/skills/hallmark/references/comp.md +104 -0
- package/skills/hallmark/references/craft.md +116 -0
- package/skills/hallmark/references/dark-mode.md +49 -0
- package/skills/hallmark/references/data-viz.md +48 -0
- package/skills/hallmark/references/design-md.md +53 -0
- package/skills/hallmark/references/direction.md +52 -0
- package/skills/hallmark/references/export-formats.md +80 -0
- package/skills/hallmark/references/flow.md +131 -0
- package/skills/hallmark/references/fonts.md +58 -0
- package/skills/hallmark/references/gates.md +243 -0
- package/skills/hallmark/references/genres/atmospheric.md +24 -0
- package/skills/hallmark/references/genres/editorial.md +24 -0
- package/skills/hallmark/references/genres/modern-minimal.md +24 -0
- package/skills/hallmark/references/genres/playful.md +24 -0
- package/skills/hallmark/references/imagery.md +99 -0
- package/skills/hallmark/references/interaction-and-states.md +89 -0
- package/skills/hallmark/references/layout.md +104 -0
- package/skills/hallmark/references/macrostructures/01-bento-grid.md +21 -0
- package/skills/hallmark/references/macrostructures/02-long-document.md +35 -0
- package/skills/hallmark/references/macrostructures/03-marquee-hero.md +21 -0
- package/skills/hallmark/references/macrostructures/04-stat-led.md +21 -0
- package/skills/hallmark/references/macrostructures/05-workbench.md +21 -0
- package/skills/hallmark/references/macrostructures/06-conversational-faq.md +28 -0
- package/skills/hallmark/references/macrostructures/07-manifesto.md +28 -0
- package/skills/hallmark/references/macrostructures/08-photographic.md +21 -0
- package/skills/hallmark/references/macrostructures/09-quote-led.md +21 -0
- package/skills/hallmark/references/macrostructures/10-specimen.md +21 -0
- package/skills/hallmark/references/macrostructures/11-catalogue.md +21 -0
- package/skills/hallmark/references/macrostructures/12-letter.md +21 -0
- package/skills/hallmark/references/macrostructures/13-index-first.md +21 -0
- package/skills/hallmark/references/macrostructures/14-narrative-workflow.md +21 -0
- package/skills/hallmark/references/macrostructures/15-split-studio.md +21 -0
- package/skills/hallmark/references/macrostructures/16-feature-stack.md +23 -0
- package/skills/hallmark/references/macrostructures/17-type-specimen.md +19 -0
- package/skills/hallmark/references/macrostructures/18-portfolio-grid.md +21 -0
- package/skills/hallmark/references/macrostructures/19-map-diagram.md +21 -0
- package/skills/hallmark/references/macrostructures/20-ecosystem-index.md +19 -0
- package/skills/hallmark/references/macrostructures/21-component-playground.md +21 -0
- package/skills/hallmark/references/macrostructures.md +119 -0
- package/skills/hallmark/references/microinteractions.md +80 -0
- package/skills/hallmark/references/patterns.md +202 -0
- package/skills/hallmark/references/redesign.md +88 -0
- package/skills/hallmark/references/responsive.md +46 -0
- package/skills/hallmark/references/review-finish.md +19 -0
- package/skills/hallmark/references/review-hero.md +20 -0
- package/skills/hallmark/references/scroll-choreography.md +110 -0
- package/skills/hallmark/references/texture.md +90 -0
- package/skills/hallmark/references/themes/README.md +58 -0
- package/skills/hallmark/references/themes/almanac.jpg +0 -0
- package/skills/hallmark/references/themes/almanac.md +103 -0
- package/skills/hallmark/references/themes/arcade.jpg +0 -0
- package/skills/hallmark/references/themes/arcade.md +102 -0
- package/skills/hallmark/references/themes/atelier.jpg +0 -0
- package/skills/hallmark/references/themes/atelier.md +98 -0
- package/skills/hallmark/references/themes/bloom.jpg +0 -0
- package/skills/hallmark/references/themes/bloom.md +102 -0
- package/skills/hallmark/references/themes/blueprint.jpg +0 -0
- package/skills/hallmark/references/themes/blueprint.md +103 -0
- package/skills/hallmark/references/themes/broadside.jpg +0 -0
- package/skills/hallmark/references/themes/broadside.md +108 -0
- package/skills/hallmark/references/themes/brutal.jpg +0 -0
- package/skills/hallmark/references/themes/brutal.md +95 -0
- package/skills/hallmark/references/themes/carnival.jpg +0 -0
- package/skills/hallmark/references/themes/carnival.md +104 -0
- package/skills/hallmark/references/themes/cobalt.jpg +0 -0
- package/skills/hallmark/references/themes/cobalt.md +101 -0
- package/skills/hallmark/references/themes/console.jpg +0 -0
- package/skills/hallmark/references/themes/console.md +99 -0
- package/skills/hallmark/references/themes/coral.jpg +0 -0
- package/skills/hallmark/references/themes/coral.md +102 -0
- package/skills/hallmark/references/themes/darkroom.jpg +0 -0
- package/skills/hallmark/references/themes/darkroom.md +99 -0
- package/skills/hallmark/references/themes/dose.jpg +0 -0
- package/skills/hallmark/references/themes/dose.md +98 -0
- package/skills/hallmark/references/themes/dusk.jpg +0 -0
- package/skills/hallmark/references/themes/dusk.md +105 -0
- package/skills/hallmark/references/themes/editorial.jpg +0 -0
- package/skills/hallmark/references/themes/editorial.md +97 -0
- package/skills/hallmark/references/themes/formwork.jpg +0 -0
- package/skills/hallmark/references/themes/formwork.md +107 -0
- package/skills/hallmark/references/themes/furrow.jpg +0 -0
- package/skills/hallmark/references/themes/furrow.md +98 -0
- package/skills/hallmark/references/themes/garden.jpg +0 -0
- package/skills/hallmark/references/themes/garden.md +97 -0
- package/skills/hallmark/references/themes/grid.jpg +0 -0
- package/skills/hallmark/references/themes/grid.md +101 -0
- package/skills/hallmark/references/themes/halftone.jpg +0 -0
- package/skills/hallmark/references/themes/halftone.md +106 -0
- package/skills/hallmark/references/themes/hedgerow.jpg +0 -0
- package/skills/hallmark/references/themes/hedgerow.md +104 -0
- package/skills/hallmark/references/themes/hum.jpg +0 -0
- package/skills/hallmark/references/themes/hum.md +99 -0
- package/skills/hallmark/references/themes/index.json +2191 -0
- package/skills/hallmark/references/themes/ink.jpg +0 -0
- package/skills/hallmark/references/themes/ink.md +106 -0
- package/skills/hallmark/references/themes/kiln.jpg +0 -0
- package/skills/hallmark/references/themes/kiln.md +108 -0
- package/skills/hallmark/references/themes/loom.jpg +0 -0
- package/skills/hallmark/references/themes/loom.md +106 -0
- package/skills/hallmark/references/themes/lumen.jpg +0 -0
- package/skills/hallmark/references/themes/lumen.md +103 -0
- package/skills/hallmark/references/themes/manifesto.jpg +0 -0
- package/skills/hallmark/references/themes/manifesto.md +101 -0
- package/skills/hallmark/references/themes/midnight.jpg +0 -0
- package/skills/hallmark/references/themes/midnight.md +97 -0
- package/skills/hallmark/references/themes/newsprint.jpg +0 -0
- package/skills/hallmark/references/themes/newsprint.md +102 -0
- package/skills/hallmark/references/themes/overprint.jpg +0 -0
- package/skills/hallmark/references/themes/overprint.md +101 -0
- package/skills/hallmark/references/themes/pasteup.jpg +0 -0
- package/skills/hallmark/references/themes/pasteup.md +100 -0
- package/skills/hallmark/references/themes/piste.jpg +0 -0
- package/skills/hallmark/references/themes/piste.md +99 -0
- package/skills/hallmark/references/themes/ribbon.jpg +0 -0
- package/skills/hallmark/references/themes/ribbon.md +106 -0
- package/skills/hallmark/references/themes/rim.jpg +0 -0
- package/skills/hallmark/references/themes/rim.md +96 -0
- package/skills/hallmark/references/themes/riso.jpg +0 -0
- package/skills/hallmark/references/themes/riso.md +98 -0
- package/skills/hallmark/references/themes/solstice.jpg +0 -0
- package/skills/hallmark/references/themes/solstice.md +104 -0
- package/skills/hallmark/references/themes/specimen.jpg +0 -0
- package/skills/hallmark/references/themes/specimen.md +100 -0
- package/skills/hallmark/references/themes/spore.jpg +0 -0
- package/skills/hallmark/references/themes/spore.md +104 -0
- package/skills/hallmark/references/themes/sport.jpg +0 -0
- package/skills/hallmark/references/themes/sport.md +101 -0
- package/skills/hallmark/references/themes/squeeze.jpg +0 -0
- package/skills/hallmark/references/themes/squeeze.md +99 -0
- package/skills/hallmark/references/themes/sticker.jpg +0 -0
- package/skills/hallmark/references/themes/sticker.md +106 -0
- package/skills/hallmark/references/themes/studio.jpg +0 -0
- package/skills/hallmark/references/themes/studio.md +99 -0
- package/skills/hallmark/references/themes/terminal.jpg +0 -0
- package/skills/hallmark/references/themes/terminal.md +96 -0
- package/skills/hallmark/references/themes/terrazzo.jpg +0 -0
- package/skills/hallmark/references/themes/terrazzo.md +106 -0
- package/skills/hallmark/references/themes/ultraviolet.jpg +0 -0
- package/skills/hallmark/references/themes/ultraviolet.md +106 -0
- package/skills/hallmark/references/themes/vellum.jpg +0 -0
- package/skills/hallmark/references/themes/vellum.md +105 -0
- package/skills/hallmark/references/themes/wayfind.jpg +0 -0
- package/skills/hallmark/references/themes/wayfind.md +105 -0
- package/skills/hallmark/references/themes/werkstatt.jpg +0 -0
- package/skills/hallmark/references/themes/werkstatt.md +105 -0
- package/skills/hallmark/scripts/capture.mjs +125 -0
- package/skills/hallmark/scripts/fixtures/exemplars/atmospheric.html +324 -0
- package/skills/hallmark/scripts/fixtures/exemplars/editorial.html +363 -0
- package/skills/hallmark/scripts/fixtures/exemplars/modern-minimal.html +527 -0
- package/skills/hallmark/scripts/fixtures/exemplars/playful.html +353 -0
- package/skills/hallmark/scripts/fixtures/eyebrow-fail/index.html +118 -0
- package/skills/hallmark/scripts/fixtures/eyebrow-pass/index.html +137 -0
- package/skills/hallmark/scripts/fixtures/kept/after.html +27 -0
- package/skills/hallmark/scripts/fixtures/kept/before.html +26 -0
- package/skills/hallmark/scripts/fixtures/slopped.html +145 -0
- package/skills/hallmark/scripts/fixtures/tailwind-fail/Feature.vue +14 -0
- package/skills/hallmark/scripts/fixtures/tailwind-fail/Hero.tsx +33 -0
- package/skills/hallmark/scripts/fixtures/tailwind-fail/index.html +74 -0
- package/skills/hallmark/scripts/fixtures/tailwind-fail/style.css +6 -0
- package/skills/hallmark/scripts/fixtures/tailwind-pass/Hero.tsx +33 -0
- package/skills/hallmark/scripts/fixtures/tailwind-pass/index.html +57 -0
- package/skills/hallmark/scripts/fixtures/tailwind-pass/style.css +15 -0
- package/skills/hallmark/scripts/fixtures/waiver/index.html +54 -0
- package/skills/hallmark/scripts/imagegen.mjs +85 -0
- package/skills/hallmark/scripts/install-hook.mjs +70 -0
- package/skills/hallmark/scripts/install.mjs +141 -0
- package/skills/hallmark/scripts/lint-hook.mjs +49 -0
- package/skills/hallmark/scripts/photos.json +1 -0
- package/skills/hallmark/scripts/picture.mjs +71 -0
- package/skills/hallmark/scripts/refcheck.mjs +352 -0
- package/skills/hallmark/scripts/sloplint-render.mjs +1252 -0
- package/skills/hallmark/scripts/sloplint.mjs +4422 -0
- package/skills/hallmark/scripts/theme.mjs +650 -0
- package/skills/harness/SKILL.md +17 -8
- package/skills/i-have-adhd/SKILL.md +32 -12
- package/skills/no-ai-slop/SKILL.md +15 -1
- package/skills/plan-add/SKILL.md +38 -27
- package/skills/plan-status/SKILL.md +13 -7
- package/skills/plan-sync/SKILL.md +18 -12
- package/skills/pm-frameworks/SKILL.md +19 -10
- package/skills/pm-frameworks/SOURCE +7 -5
- package/skills/ponytail/SKILL.md +19 -14
- package/skills/product-analysis/SKILL.md +22 -18
- package/skills/product-flow/SKILL.md +14 -9
- package/skills/research/SKILL.md +97 -48
- package/skills/rl-env/SKILL.md +25 -13
- package/skills/rl-env/SOURCE +8 -6
- package/skills/tezgah-contract/SKILL.md +65 -47
- package/statusline.py +20 -9
- package/workflows/graph-review.js +14 -2
- package/bin/tezgah-skill.py +0 -59
- /package/skills/ai-research/0-autoresearch-skill/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/01-model-architecture/litgpt/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/01-model-architecture/mamba/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/01-model-architecture/nanogpt/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/01-model-architecture/rwkv/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/01-model-architecture/torchtitan/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/02-tokenization/huggingface-tokenizers/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/02-tokenization/sentencepiece/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/03-fine-tuning/axolotl/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/03-fine-tuning/llama-factory/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/03-fine-tuning/peft/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/03-fine-tuning/unsloth/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/04-mechanistic-interpretability/nnsight/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/04-mechanistic-interpretability/pyvene/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/04-mechanistic-interpretability/saelens/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/04-mechanistic-interpretability/transformer-lens/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/05-data-processing/nemo-curator/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/05-data-processing/ray-data/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/06-post-training/grpo-rl-training/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/06-post-training/miles/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/06-post-training/openrlhf/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/06-post-training/simpo/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/06-post-training/slime/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/06-post-training/torchforge/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/06-post-training/trl-fine-tuning/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/06-post-training/verl/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/07-safety-alignment/constitutional-ai/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/07-safety-alignment/llamaguard/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/07-safety-alignment/nemo-guardrails/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/07-safety-alignment/prompt-guard/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/08-distributed-training/accelerate/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/08-distributed-training/deepspeed/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/08-distributed-training/megatron-core/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/08-distributed-training/pytorch-fsdp2/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/08-distributed-training/pytorch-lightning/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/08-distributed-training/ray-train/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/09-infrastructure/lambda-labs/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/09-infrastructure/modal/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/09-infrastructure/skypilot/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/10-optimization/awq/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/10-optimization/bitsandbytes/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/10-optimization/flash-attention/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/10-optimization/gguf/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/10-optimization/gptq/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/10-optimization/hqq/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/10-optimization/ml-training-recipes/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/11-evaluation/bigcode-evaluation-harness/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/11-evaluation/lm-evaluation-harness/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/11-evaluation/nemo-evaluator/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/12-inference-serving/llama-cpp/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/12-inference-serving/sglang/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/12-inference-serving/tensorrt-llm/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/12-inference-serving/vllm/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/13-mlops/mlflow/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/13-mlops/swanlab/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/13-mlops/tensorboard/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/13-mlops/weights-and-biases/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/14-agents/a-evolve/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/14-agents/autogpt/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/14-agents/crewai/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/14-agents/langchain/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/14-agents/llamaindex/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/15-rag/chroma/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/15-rag/faiss/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/15-rag/pinecone/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/15-rag/qdrant/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/15-rag/sentence-transformers/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/16-prompt-engineering/dspy/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/16-prompt-engineering/guidance/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/16-prompt-engineering/instructor/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/16-prompt-engineering/outlines/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/17-observability/langsmith/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/17-observability/phoenix/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/18-multimodal/audiocraft/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/18-multimodal/blip-2/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/18-multimodal/clip/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/18-multimodal/cosmos-policy/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/18-multimodal/llava/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/18-multimodal/openpi/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/18-multimodal/openvla-oft/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/18-multimodal/segment-anything/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/18-multimodal/stable-diffusion/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/18-multimodal/whisper/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/19-emerging-techniques/knowledge-distillation/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/19-emerging-techniques/long-context/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/19-emerging-techniques/model-merging/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/19-emerging-techniques/model-pruning/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/19-emerging-techniques/moe-training/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/19-emerging-techniques/speculative-decoding/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/20-ml-paper-writing/academic-plotting/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/20-ml-paper-writing/presenting-conference-talks/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/21-research-ideation/brainstorming-research-ideas/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/21-research-ideation/creative-thinking-for-research/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/22-agent-native-research-artifact/compiler/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/22-agent-native-research-artifact/research-manager/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/ai-research/22-agent-native-research-artifact/rigor-reviewer/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/adaptive-interfaces/skills/colour-independence/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/adaptive-interfaces/skills/flexible-typography/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/adaptive-interfaces/skills/information-density/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/adaptive-interfaces/skills/preference-audit/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/adaptive-interfaces/skills/responsive-accessibility/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/adaptive-interfaces/skills/responsive-review/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/adaptive-interfaces/skills/simplified-views/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/adaptive-interfaces/skills/specify/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/adaptive-interfaces/skills/user-preference-respect/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/cognitive-accessibility/skills/adaptive-personalisation/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/cognitive-accessibility/skills/assess-load/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/cognitive-accessibility/skills/cognitive-load-assessment/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/cognitive-accessibility/skills/contextual-help-design/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/cognitive-accessibility/skills/error-prevention-recovery/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/cognitive-accessibility/skills/focus-attention-design/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/cognitive-accessibility/skills/memory-load-reduction/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/cognitive-accessibility/skills/plain-language-design/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/cognitive-accessibility/skills/review/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/cognitive-accessibility/skills/simplify/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/cognitive-accessibility/skills/wayfinding-navigation/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/design-research/skills/behavioural-analytics/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/design-research/skills/qual-quant-triangulation/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/inclusive-interaction/skills/audit/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/inclusive-interaction/skills/design-flow/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/inclusive-interaction/skills/feedback-and-status/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/inclusive-interaction/skills/gesture-alternatives/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/inclusive-interaction/skills/keyboard-navigation/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/inclusive-interaction/skills/keyboard-review/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/inclusive-interaction/skills/motion-sensitivity/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/inclusive-interaction/skills/multi-modal-input/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/inclusive-interaction/skills/touch-target-design/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/inclusive-interaction/skills/voice-interaction/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/visual-critique/skills/critique-affordance/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/visual-critique/skills/critique-brand-consistency/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/visual-critique/skills/critique-color/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/visual-critique/skills/critique-composition/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/visual-critique/skills/critique-information-density/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/visual-critique/skills/critique-typography/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/design-library/visual-critique/skills/critique-visual-hierarchy/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/pm-frameworks/intended-vs-implemented/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/pm-frameworks/opportunity-solution-tree/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/rl-env/generate-nemo-gym-env/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/rl-env/generate-openenv-env/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/rl-env/generate-ors-env/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/rl-env/generate-verifiers-env/{SKILL.md → ENTRY.md} +0 -0
- /package/skills/rl-env/rl-env-from-description/{SKILL.md → ENTRY.md} +0 -0
package/bin/tezgah-skill
CHANGED
|
@@ -25,7 +25,7 @@ import json
|
|
|
25
25
|
import os
|
|
26
26
|
import sys
|
|
27
27
|
|
|
28
|
-
HERE = os.path.dirname(os.path.dirname(os.path.
|
|
28
|
+
HERE = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
|
29
29
|
sys.path.insert(0, os.path.join(HERE, "hooks"))
|
|
30
30
|
import tezgah_skill_pick as sp # noqa: E402
|
|
31
31
|
|
package/bin/tezgah-status
CHANGED
|
@@ -29,6 +29,22 @@ their status line; this CLI is how every host (and a human) gets it:
|
|
|
29
29
|
The MCP half of a retirement decision is manual:
|
|
30
30
|
`tezgah-setup --mcp-schemas` measures what a server
|
|
31
31
|
costs, this counts what it fires.
|
|
32
|
+
tezgah-status --rates --since DATE --until DATE [--json]
|
|
33
|
+
every real ledger's rows in [since, until), folded per
|
|
34
|
+
window and per calendar day: turns, `claim` rows and
|
|
35
|
+
the Stop classes that blocked them, the shape flags
|
|
36
|
+
every judged reply carried, denies by rule, and the
|
|
37
|
+
rates (blocks per 100 turns, denies per 100 sessions,
|
|
38
|
+
the claim block and Stop shape shares, blocked claims
|
|
39
|
+
per 100 sessions by class). A repeated `--since`/
|
|
40
|
+
`--until` pair prints one block each and the pp delta
|
|
41
|
+
between adjacent windows - the unit plan 066's 056 row
|
|
42
|
+
states its bar in. A window that read more than one
|
|
43
|
+
row contract prints the split, and a delta across two
|
|
44
|
+
contracts says so (plan 135). `--json` prints
|
|
45
|
+
`{"windows": [...]}`.
|
|
46
|
+
`--until` is exclusive, so adjacent windows partition
|
|
47
|
+
their span.
|
|
32
48
|
tezgah-status --skill-fitness
|
|
33
49
|
per shipped skill, over the recorded sessions: how
|
|
34
50
|
many opened it and which were never opened. A
|
|
@@ -78,6 +94,16 @@ their status line; this CLI is how every host (and a human) gets it:
|
|
|
78
94
|
the set renders as dim "no state" instead of claiming
|
|
79
95
|
"armed, not used yet". A host that cannot see a skill
|
|
80
96
|
read (dsh) passes the tool-use four.
|
|
97
|
+
tezgah-status --manifest=FILE
|
|
98
|
+
read the repository extension from FILE instead of
|
|
99
|
+
the `.tezgah/extension.json` discovered from PATH (a
|
|
100
|
+
manifest outside the tree, e.g. an engagement's).
|
|
101
|
+
With `statusline.override: true` in the manifest the
|
|
102
|
+
project owns its line and points its own statusLine
|
|
103
|
+
here: the host's status-line payload on stdin (its
|
|
104
|
+
`cwd`/`workspace.current_dir` and `session_id`) is
|
|
105
|
+
read when no PATH is given, so this is the only line
|
|
106
|
+
and it keeps the built-in marks and the chips.
|
|
81
107
|
|
|
82
108
|
The session id may be passed as the second argument or via TEZGAH_SESSION;
|
|
83
109
|
without it the "used" marks cannot light up, so a host that knows the id should
|
|
@@ -97,6 +123,26 @@ from tezgah_context import ( # noqa: E402
|
|
|
97
123
|
# the line and `--json` carries every row, so a reader can always see what was
|
|
98
124
|
# cut.
|
|
99
125
|
TOP = 15
|
|
126
|
+
# The host payload an override reads on stdin: a status-line host writes one
|
|
127
|
+
# small JSON object and closes the pipe, so the read is bounded in bytes and in
|
|
128
|
+
# how long an empty pipe is waited for - a caller that never writes costs this
|
|
129
|
+
# long, never a hang.
|
|
130
|
+
PAYLOAD_MAX = 65536
|
|
131
|
+
PAYLOAD_WAIT = 0.2
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def host_payload():
|
|
135
|
+
"""The status-line host's JSON payload on stdin, or {} - a terminal, an
|
|
136
|
+
empty or silent pipe, malformed JSON or no stdin at all."""
|
|
137
|
+
import select
|
|
138
|
+
try:
|
|
139
|
+
if sys.stdin.isatty() or not select.select([sys.stdin], [], [],
|
|
140
|
+
PAYLOAD_WAIT)[0]:
|
|
141
|
+
return {}
|
|
142
|
+
payload = json.loads(sys.stdin.read(PAYLOAD_MAX) or "{}")
|
|
143
|
+
except (OSError, ValueError, AttributeError):
|
|
144
|
+
return {}
|
|
145
|
+
return payload if isinstance(payload, dict) else {}
|
|
100
146
|
|
|
101
147
|
|
|
102
148
|
def weeks_arg(args):
|
|
@@ -241,6 +287,115 @@ def print_orca(cwd, as_json):
|
|
|
241
287
|
return 0
|
|
242
288
|
|
|
243
289
|
|
|
290
|
+
def window_pairs(args):
|
|
291
|
+
"""`args` with the `--since`/`--until` pairs folded out, and the pairs in the
|
|
292
|
+
order written. Each `--until` closes the `--since` before it, and a flag
|
|
293
|
+
without its partner is ValueError: half a window is a question the reader
|
|
294
|
+
did not finish asking.
|
|
295
|
+
|
|
296
|
+
The spaced form is read here for the reason `--weeks`' is: the split in
|
|
297
|
+
`main` sends every non-`--` argument to `pos`, where a date would be read as
|
|
298
|
+
a session id."""
|
|
299
|
+
out, pairs, since, i = [], [], None, 0
|
|
300
|
+
while i < len(args):
|
|
301
|
+
a = args[i]
|
|
302
|
+
name = a.split("=", 1)[0]
|
|
303
|
+
if name not in ("--since", "--until"):
|
|
304
|
+
out.append(a)
|
|
305
|
+
i += 1
|
|
306
|
+
continue
|
|
307
|
+
if "=" in a:
|
|
308
|
+
value, i = a.split("=", 1)[1], i + 1
|
|
309
|
+
else:
|
|
310
|
+
value = args[i + 1] if i + 1 < len(args) else ""
|
|
311
|
+
i += 2 if i + 1 < len(args) else 1
|
|
312
|
+
if name == "--since":
|
|
313
|
+
if since is not None:
|
|
314
|
+
raise ValueError("--since %s has no --until" % since)
|
|
315
|
+
since = value
|
|
316
|
+
else:
|
|
317
|
+
if since is None:
|
|
318
|
+
raise ValueError("--until %s has no --since" % value)
|
|
319
|
+
pairs.append((since, value))
|
|
320
|
+
since = None
|
|
321
|
+
if since is not None:
|
|
322
|
+
raise ValueError("--since %s has no --until" % since)
|
|
323
|
+
return out, pairs
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def share(value, numerator, denominator):
|
|
327
|
+
"""A share in the unit 056's `+2 pp` bar reads, or `n/a` with no
|
|
328
|
+
denominator - a window that decided nothing has no rate."""
|
|
329
|
+
return ("n/a" if value is None
|
|
330
|
+
else "%.2f%% (%d/%d)" % (100 * value, numerator, denominator))
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def dominant_contract(window):
|
|
334
|
+
"""The row contract that wrote most of a window's rows, or `-` for a window
|
|
335
|
+
that read none. `claims` is one quantity under a contract and another across
|
|
336
|
+
a change to it (plan 135), so the delta line names both sides' contract."""
|
|
337
|
+
counts = window.get("row_versions") or {}
|
|
338
|
+
if not counts:
|
|
339
|
+
return "-"
|
|
340
|
+
return max(sorted(counts), key=lambda name: counts[name])
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def print_rates(found):
|
|
344
|
+
"""The windowed rates, for `--rates`: one block per window, then the pp delta
|
|
345
|
+
between each adjacent pair - the unit plan 066's rows state their bars in."""
|
|
346
|
+
for w in found:
|
|
347
|
+
rates = w["rates"]
|
|
348
|
+
print("window %s..%s: %d days, %d sessions, %d turns, %d claims, %d "
|
|
349
|
+
"replies" % (w["since"], w["until"], w["days"], w["sessions"],
|
|
350
|
+
w["turns"], w["claims"], w["replies"]))
|
|
351
|
+
for key, label in (("blocked_claims", "blocked_claims"),
|
|
352
|
+
("shapes", "stop shapes"), ("denies", "denies")):
|
|
353
|
+
print(" %-15s %s" % (label, ", ".join(
|
|
354
|
+
"%s=%d" % kv for kv in sorted(w[key].items())) or "none"))
|
|
355
|
+
print(" %-15s %d" % ("shape_blocked", w["shape_blocked"]))
|
|
356
|
+
print(" %-15s blocks/100 turns %s, denies/100 sessions %s" % (
|
|
357
|
+
"rates", "n/a" if rates["blocks_per_100_turns"] is None
|
|
358
|
+
else "%.4f" % rates["blocks_per_100_turns"],
|
|
359
|
+
"n/a" if rates["denies_per_100_sessions"] is None
|
|
360
|
+
else "%.4f" % rates["denies_per_100_sessions"]))
|
|
361
|
+
print(" %-15s claim block %s, stop shape %s" % (
|
|
362
|
+
"shares", share(rates["claim_block_rate"],
|
|
363
|
+
sum(w["blocked_claims"].values()), w["claims"]),
|
|
364
|
+
share(rates["stop_shape_rate"], w["shape_flagged"], w["replies"])))
|
|
365
|
+
print(" %-15s %s" % ("blocked/100 sess", ", ".join(
|
|
366
|
+
"%s=%.4f" % kv for kv in
|
|
367
|
+
sorted(rates["blocked_claims_per_100_sessions"].items()))
|
|
368
|
+
or "none"))
|
|
369
|
+
# Which row contract wrote the rows, printed only when a window mixes
|
|
370
|
+
# two: `claims` means "every judged reply" before ROW_VERSION 3 and "a
|
|
371
|
+
# reply that claimed" after it, so a share read off a mixed or shifted
|
|
372
|
+
# window is not the same quantity as its neighbour's (plan 135).
|
|
373
|
+
if len(w["row_versions"]) > 1:
|
|
374
|
+
print(" %-15s %s" % ("contracts", ", ".join(
|
|
375
|
+
"%s=%d" % kv for kv in sorted(w["row_versions"].items()))))
|
|
376
|
+
for before, after in zip(found, found[1:]):
|
|
377
|
+
parts, unknown, over = [], False, False
|
|
378
|
+
for key, label in (("claim_block_rate", "claim block"),
|
|
379
|
+
("stop_shape_rate", "stop shape")):
|
|
380
|
+
a, b = before["rates"][key], after["rates"][key]
|
|
381
|
+
if a is None or b is None:
|
|
382
|
+
unknown = True
|
|
383
|
+
parts.append("%s n/a" % label)
|
|
384
|
+
continue
|
|
385
|
+
parts.append("%s %+.2f pp" % (label, 100 * (b - a)))
|
|
386
|
+
over = over or round(b - a, 4) > 0.02
|
|
387
|
+
shift = dominant_contract(before) != dominant_contract(after)
|
|
388
|
+
print("delta %s..%s -> %s..%s: %s; 056 bar (+2 pp): %s%s" % (
|
|
389
|
+
before["since"], before["until"], after["since"], after["until"],
|
|
390
|
+
", ".join(parts),
|
|
391
|
+
"unreadable (no denominator in a window)" if unknown
|
|
392
|
+
else "FAILS" if over else "holds",
|
|
393
|
+
"; the two windows' rows come from different contracts (%s vs %s), "
|
|
394
|
+
"so the shares are not one quantity" % (
|
|
395
|
+
dominant_contract(before), dominant_contract(after))
|
|
396
|
+
if shift else ""))
|
|
397
|
+
|
|
398
|
+
|
|
244
399
|
def main():
|
|
245
400
|
# `--` ends the options: what follows is PATH and SESSION_ID even when it
|
|
246
401
|
# starts with a dash. The dsh route and the MCP tool hand caller-chosen
|
|
@@ -250,6 +405,11 @@ def main():
|
|
|
250
405
|
rest = argv[argv.index("--") + 1:] if "--" in argv else []
|
|
251
406
|
argv = argv[:argv.index("--")] if "--" in argv else argv
|
|
252
407
|
args, weeks = weeks_arg(argv)
|
|
408
|
+
try:
|
|
409
|
+
args, windows = window_pairs(args)
|
|
410
|
+
except ValueError as err:
|
|
411
|
+
sys.stderr.write("tezgah-status: %s\n" % err)
|
|
412
|
+
return 2
|
|
253
413
|
# A sanity bound, not a policy: ten years of weeks is longer than any ledger
|
|
254
414
|
# this machine holds, and a number the reader mistyped should say so rather
|
|
255
415
|
# than print a thousand rows of nothing.
|
|
@@ -260,9 +420,11 @@ def main():
|
|
|
260
420
|
pos = [a for a in args if not a.startswith("--")] + rest
|
|
261
421
|
known = {"--legend", "--json", "--color", "--no-color", "--counters",
|
|
262
422
|
"--all", "--trend", "--skill-fitness", "--failure-shapes",
|
|
263
|
-
"--rule-yield", "--enforcers", "--orca", "--judge", "--
|
|
423
|
+
"--rule-yield", "--enforcers", "--orca", "--judge", "--rates",
|
|
424
|
+
"--help"}
|
|
264
425
|
unknown = sorted(f for f in flags
|
|
265
|
-
if f not in known
|
|
426
|
+
if f not in known
|
|
427
|
+
and not f.startswith(("--observable=", "--manifest=")))
|
|
266
428
|
if unknown:
|
|
267
429
|
sys.stderr.write("tezgah-status: unknown option(s): %s (try --help)\n"
|
|
268
430
|
% ", ".join(unknown))
|
|
@@ -293,6 +455,26 @@ def main():
|
|
|
293
455
|
sys.stderr.write("tezgah-status: %s only means something with "
|
|
294
456
|
"--counters\n" % modifier)
|
|
295
457
|
return 2
|
|
458
|
+
if windows and "--rates" not in flags:
|
|
459
|
+
sys.stderr.write("tezgah-status: --since/--until only mean something "
|
|
460
|
+
"with --rates\n")
|
|
461
|
+
return 2
|
|
462
|
+
if "--rates" in flags and not windows:
|
|
463
|
+
sys.stderr.write("tezgah-status: --rates wants --since and --until\n")
|
|
464
|
+
return 2
|
|
465
|
+
if "--rates" in flags:
|
|
466
|
+
import tezgah_integrity as ti
|
|
467
|
+
try:
|
|
468
|
+
found = [ti.rates(since, until) for since, until in windows]
|
|
469
|
+
except ValueError as err:
|
|
470
|
+
sys.stderr.write("tezgah-status: %s\n" % err)
|
|
471
|
+
return 2
|
|
472
|
+
if "--json" in flags:
|
|
473
|
+
# one shape for one window and for many: a consumer never branches
|
|
474
|
+
print(json.dumps({"windows": found}, sort_keys=True))
|
|
475
|
+
return 0
|
|
476
|
+
print_rates(found)
|
|
477
|
+
return 0
|
|
296
478
|
if "--judge" in flags:
|
|
297
479
|
import tezgah_judge as tj
|
|
298
480
|
last = tj.last_use()
|
|
@@ -430,7 +612,23 @@ def main():
|
|
|
430
612
|
spec = next((f.split("=", 1)[1] for f in flags
|
|
431
613
|
if f.startswith("--observable=")), None)
|
|
432
614
|
observable = set(spec.split(",")) if spec else None
|
|
433
|
-
|
|
615
|
+
manifest = next((f.split("=", 1)[1] for f in flags
|
|
616
|
+
if f.startswith("--manifest=")), None) or None
|
|
617
|
+
if not pos:
|
|
618
|
+
import tezgah_extension
|
|
619
|
+
if tezgah_extension.override(cwd, manifest):
|
|
620
|
+
# the project's own statusLine runs this renderer: the host says
|
|
621
|
+
# which directory and session the line is for
|
|
622
|
+
payload = host_payload()
|
|
623
|
+
workspace = payload.get("workspace")
|
|
624
|
+
where = ((workspace.get("current_dir")
|
|
625
|
+
if isinstance(workspace, dict) else None)
|
|
626
|
+
or payload.get("cwd"))
|
|
627
|
+
if isinstance(where, str) and where:
|
|
628
|
+
cwd = os.path.realpath(where)
|
|
629
|
+
if isinstance(payload.get("session_id"), str) and payload["session_id"]:
|
|
630
|
+
session = payload["session_id"]
|
|
631
|
+
segs = health_segments(cwd, session, observable=observable, manifest=manifest)
|
|
434
632
|
if "--json" in flags:
|
|
435
633
|
print(json.dumps(segs))
|
|
436
634
|
return 0
|
package/bin/tezgah-task
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
tezgah-task allow GLOB ... | --any-path --why REASON replace the allowlist, recording why
|
|
7
7
|
tezgah-task stop deactivate (clear phase)
|
|
8
8
|
tezgah-task status [--json] the active task, then every open plan: progress, what it waits on, what can run at once
|
|
9
|
-
tezgah-task review <NNN|path> <reviewer> approve|changes
|
|
9
|
+
tezgah-task review <NNN|path> <reviewer> approve|changes [--no-slice WHY] record a fresh review's verdict; approve needs the reviewer's slice record, or WHY it has none
|
|
10
10
|
tezgah-task close <NNN|path> done|discarded [--resolved TEXT] move a plan to .tezgah/plans/done, deactivate it, remove merged worktrees
|
|
11
11
|
tezgah-task tick <NNN|path> <n> [--undo] tick (or untick) Acceptance item n, counted from 1
|
|
12
12
|
tezgah-task note <NNN|path> state|next "<text>" replace the body of `## State` (the newest one) or `## Next`
|
|
@@ -122,7 +122,10 @@ history) is printed as `not judged` and the exit is 1. `review ... approve`
|
|
|
122
122
|
is refused while a record whose id or agent is that reviewer is not done.
|
|
123
123
|
|
|
124
124
|
Exit codes: 0 ok, 1 a refusal or a problem - one `FAIL <what>` line per problem,
|
|
125
|
-
with nothing written - 2 misuse.
|
|
125
|
+
with nothing written - 2 misuse. In a repository whose `tezgah.owner` says
|
|
126
|
+
`tasks: off` (or `harness: excluded`) every command above that writes a record
|
|
127
|
+
is refused, and the read-only ones still answer
|
|
128
|
+
(`bin/tezgah-task::owner_mark`).
|
|
126
129
|
"""
|
|
127
130
|
import glob
|
|
128
131
|
import json
|
|
@@ -136,7 +139,12 @@ import time
|
|
|
136
139
|
HERE = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
|
137
140
|
sys.path.insert(0, os.path.join(HERE, "hooks"))
|
|
138
141
|
import tezgah_task as tt # noqa: E402
|
|
139
|
-
from tezgah_paths import project_top, say, work_tree # noqa: E402
|
|
142
|
+
from tezgah_paths import config, ocr_bin, omp_bin, project_top, say, work_tree # noqa: E402
|
|
143
|
+
|
|
144
|
+
# Mirrors hooks/tezgah_gate.py::PLAN_TRUNKS: the gate reads these as unplanned
|
|
145
|
+
# whatever a plan declares, so `start --branch` refuses them (plan 113). Not
|
|
146
|
+
# imported: the gate hook pulls in every rule module for this one tuple.
|
|
147
|
+
PLAN_TRUNKS = ("main", "master")
|
|
140
148
|
|
|
141
149
|
|
|
142
150
|
def repo_root(path):
|
|
@@ -152,6 +160,43 @@ def repo_root(path):
|
|
|
152
160
|
return os.path.realpath(path)
|
|
153
161
|
|
|
154
162
|
|
|
163
|
+
# Commands that write a plan's record. A repository that carries `tezgah.owner`
|
|
164
|
+
# saying `tasks: off` (or `harness: excluded`) keeps its records to itself: the
|
|
165
|
+
# phase would arm nothing there - `tezgah_task._phased` answers no task
|
|
166
|
+
# (`hooks/tezgah_paths.py::tasks_disabled`) - so writing one would report
|
|
167
|
+
# success for a guard that never fired. `writes_a_record` reads both tuples, and
|
|
168
|
+
# the read-only commands are untouched.
|
|
169
|
+
RECORD_COMMANDS = ("start", "phase", "allow", "stop", "review", "close",
|
|
170
|
+
"tick", "note", "spike", "unmet")
|
|
171
|
+
# The journal's own writers, and `sweep`, which clears an orphan `phase:` and
|
|
172
|
+
# closes the slices of the worktrees it prunes. The rest of `slice` only reads
|
|
173
|
+
# (stats, board, merge-plan), and so does `status`.
|
|
174
|
+
SLICE_WRITERS = ("open", "done", "stop", "reconcile", "resume")
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def writes_a_record(cmd, rest):
|
|
178
|
+
"""True when this invocation writes the task machine's records: the plan
|
|
179
|
+
file, the slice journal, or the phases and slices `sweep` clears. The
|
|
180
|
+
readers write none, so a repository that is not this harness's still answers
|
|
181
|
+
them (`status`, `slice stats`, `slice board`, `slice merge-plan`)."""
|
|
182
|
+
if cmd in RECORD_COMMANDS:
|
|
183
|
+
return True
|
|
184
|
+
if cmd == "slice":
|
|
185
|
+
return bool(rest) and rest[0] in SLICE_WRITERS
|
|
186
|
+
return cmd == "sweep"
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def owner_mark(root):
|
|
190
|
+
"""Why this repository's records are not this machine's to write, else
|
|
191
|
+
None. Through `tasks_disabled`, so the CLI and the gate read one answer."""
|
|
192
|
+
from tezgah_paths import OWNER_MARKER, tasks_disabled
|
|
193
|
+
if not tasks_disabled(root):
|
|
194
|
+
return None
|
|
195
|
+
return ("%s says `tasks: off` in %s: its records are the repository's own, so "
|
|
196
|
+
"this machine writes none there - edit them directly"
|
|
197
|
+
% (root, os.path.join(root, OWNER_MARKER)))
|
|
198
|
+
|
|
199
|
+
|
|
155
200
|
def misuse(message):
|
|
156
201
|
"""Misuse exits 2, so a caller can tell it from a record that refuses."""
|
|
157
202
|
print("tezgah-task: %s" % message, file=sys.stderr)
|
|
@@ -434,6 +479,139 @@ MERGE_CHECKS = (
|
|
|
434
479
|
"python3 skills/plan-add/render_table.py --acceptance --strict"),
|
|
435
480
|
)
|
|
436
481
|
|
|
482
|
+
# OCR's texts vendored with tezgah (plan 125): the review prompt each per-group
|
|
483
|
+
# reviewer reads as an appendix, the filter prompt the refuter pass follows
|
|
484
|
+
OCR_PROMPTS = os.path.join(HERE, "third_party", "open-code-review", "prompts")
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def ocr_json(ocr, args):
|
|
488
|
+
"""One `ocr delegate ... --format json` answer as a dict, or the reason it
|
|
489
|
+
is not one: a non-zero exit, a timeout, output that is not a JSON object."""
|
|
490
|
+
try:
|
|
491
|
+
out = subprocess.run([ocr, "delegate"] + args, capture_output=True,
|
|
492
|
+
text=True, timeout=30,
|
|
493
|
+
env=dict(os.environ, OCR_NO_UPDATE="1"))
|
|
494
|
+
except subprocess.TimeoutExpired:
|
|
495
|
+
return "`ocr delegate %s` timed out after 30 s" % args[0]
|
|
496
|
+
except OSError as exc:
|
|
497
|
+
return "`ocr delegate %s` did not start: %s" % (args[0], exc)
|
|
498
|
+
if out.returncode:
|
|
499
|
+
return "`ocr delegate %s` exited %d" % (args[0], out.returncode)
|
|
500
|
+
try:
|
|
501
|
+
data = json.loads(out.stdout)
|
|
502
|
+
except ValueError:
|
|
503
|
+
data = None
|
|
504
|
+
return data if isinstance(data, dict) else \
|
|
505
|
+
"`ocr delegate %s` printed no JSON object" % args[0]
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
def ocr_spec(where, base):
|
|
509
|
+
"""OCR's deterministic review spec for `base..HEAD`: (preview, rule groups,
|
|
510
|
+
the rule command), the reason it is skipped, or None without `ocr` or with
|
|
511
|
+
the `ocr` feature not enabled (`tezgah-setup --enable ocr`) - the step is
|
|
512
|
+
then today's."""
|
|
513
|
+
ocr = ocr_bin()
|
|
514
|
+
if ocr is None or "ocr" not in (config().get("features") or []):
|
|
515
|
+
return None
|
|
516
|
+
if base == "<base>":
|
|
517
|
+
return "no diff base to preview"
|
|
518
|
+
preview = ocr_json(ocr, ["preview", "--format", "json", "--from", base,
|
|
519
|
+
"--to", "HEAD", "--repo", where])
|
|
520
|
+
if isinstance(preview, str):
|
|
521
|
+
return preview
|
|
522
|
+
# the JSON shape this reader was written against (OCR 375f64c / 1.13.2)
|
|
523
|
+
if preview.get("schema_version") != "1":
|
|
524
|
+
return "`ocr delegate preview` schema_version %r is not \"1\"" % (
|
|
525
|
+
preview.get("schema_version"),)
|
|
526
|
+
files = preview.get("reviewable_files")
|
|
527
|
+
excluded = preview.get("excluded_files", [])
|
|
528
|
+
if not isinstance(files, list) or not isinstance(excluded, list):
|
|
529
|
+
return "`ocr delegate preview` JSON has no file lists"
|
|
530
|
+
# a row with no string path is dropped here, so neither the rule argv nor
|
|
531
|
+
# the printed list can meet a None
|
|
532
|
+
files = [f for f in files if isinstance(f, dict) and isinstance(f.get("path"), str)]
|
|
533
|
+
preview["reviewable_files"] = files
|
|
534
|
+
paths = [f["path"] for f in files]
|
|
535
|
+
groups = []
|
|
536
|
+
# `--` ends OCR's options, so a changed file named like a flag stays a path
|
|
537
|
+
rule_cmd = [ocr, "delegate", "rule", "--format", "json", "--repo", where, "--"] + paths
|
|
538
|
+
if paths:
|
|
539
|
+
rule = ocr_json(ocr, rule_cmd[2:])
|
|
540
|
+
if isinstance(rule, str):
|
|
541
|
+
return rule
|
|
542
|
+
if rule.get("schema_version") != "1":
|
|
543
|
+
return "`ocr delegate rule` schema_version %r is not \"1\"" % (
|
|
544
|
+
rule.get("schema_version"),)
|
|
545
|
+
groups = rule.get("groups")
|
|
546
|
+
if not isinstance(groups, list):
|
|
547
|
+
return "`ocr delegate rule` JSON has no groups"
|
|
548
|
+
return preview, groups, rule_cmd
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
def print_ocr_spec(where, base):
|
|
552
|
+
"""Step 2's OCR lines: the reviewable files, the exclusions (still in scope),
|
|
553
|
+
one reviewer per rule group, the refuter pass and the quote check. Prints
|
|
554
|
+
nothing without `ocr`, one `OCR spec skipped:` line when it fails."""
|
|
555
|
+
spec = ocr_spec(where, base)
|
|
556
|
+
if spec is None:
|
|
557
|
+
return
|
|
558
|
+
if isinstance(spec, str):
|
|
559
|
+
print(" OCR spec skipped: %s" % spec)
|
|
560
|
+
return
|
|
561
|
+
preview, groups, rule_cmd = spec
|
|
562
|
+
paths = [f.get("path") for f in preview["reviewable_files"] if isinstance(f, dict)]
|
|
563
|
+
print(" OCR review spec (`ocr delegate`; its output is input to the "
|
|
564
|
+
"review, never a verdict):")
|
|
565
|
+
print(" - reviewable files (%d): %s" % (len(paths), ", ".join(paths) or "none"))
|
|
566
|
+
out = ["%s (%s)" % (f.get("path"), f.get("exclude_reason", "no reason"))
|
|
567
|
+
for f in preview.get("excluded_files", []) if isinstance(f, dict)]
|
|
568
|
+
print(" - excluded by OCR, NOT covered by OCR rules but still in the "
|
|
569
|
+
"reviewer's scope (tests and docs stay in scope; one more "
|
|
570
|
+
"tezgah-reviewer reads them over the dimensions above): %s"
|
|
571
|
+
% (", ".join(out) or "none"))
|
|
572
|
+
if groups:
|
|
573
|
+
# OCR's own bundling below its LLM-grouping threshold (task_template.json
|
|
574
|
+
# GROUPING_MIN_FILES 4, GROUPING_BUNDLE_LINE_THRESHOLD 200): fewer than 4
|
|
575
|
+
# files are one bundle under 200 changed lines, else one file each.
|
|
576
|
+
churn = sum(n for f in preview["reviewable_files"]
|
|
577
|
+
for n in (f.get("insertions"), f.get("deletions"))
|
|
578
|
+
if isinstance(n, int) and not isinstance(n, bool))
|
|
579
|
+
if len(paths) < 4 and churn < 200:
|
|
580
|
+
who = ("one tezgah-reviewer for the whole small change set (%d files, "
|
|
581
|
+
"%d changed lines), its brief carrying every group's rule text"
|
|
582
|
+
% (len(paths), churn))
|
|
583
|
+
elif len(paths) < 4:
|
|
584
|
+
who = "one tezgah-reviewer per file, in ONE message"
|
|
585
|
+
else:
|
|
586
|
+
who = "one tezgah-reviewer per rule group below, in ONE message"
|
|
587
|
+
print(" - instead of one reviewer per dimension, spawn %s: a brief "
|
|
588
|
+
"carries its group's rule text verbatim (`groups[].rule` of `%s`) "
|
|
589
|
+
"and names %s as an appendix to read; each reviewer accounts for "
|
|
590
|
+
"every file it owns as reviewed or skipped-with-reason"
|
|
591
|
+
% (who, shlex.join(rule_cmd),
|
|
592
|
+
os.path.join(OCR_PROMPTS, "main_task_system.md")))
|
|
593
|
+
for g in groups:
|
|
594
|
+
if isinstance(g, dict):
|
|
595
|
+
print(" - rule group %s: source %s, pattern %s, files %s"
|
|
596
|
+
% (g.get("group_id"), g.get("source"), g.get("pattern"),
|
|
597
|
+
", ".join(g.get("files") or []) or "none"))
|
|
598
|
+
else:
|
|
599
|
+
print(" - no OCR rule group: the dimension fan-out above stands")
|
|
600
|
+
print(" - refuter pass: after merging the findings, one fresh "
|
|
601
|
+
"tezgah-reviewer reads %s as its instructions and removes only "
|
|
602
|
+
"findings the diff proves wrong"
|
|
603
|
+
% os.path.join(OCR_PROMPTS, "review_filter_task_system.md"))
|
|
604
|
+
print(" - quote check: `tezgah-review-quote --repo %s --from %s "
|
|
605
|
+
"FINDINGS.json` over the merged findings (a JSON list of path, quote, "
|
|
606
|
+
"start_line, end_line); an `unlocated` finding goes back to its "
|
|
607
|
+
"reviewer" % (shlex.quote(where), base))
|
|
608
|
+
# V4, omp only: OCR's own loop on omp's model; candidates, never findings
|
|
609
|
+
if os.environ.get("OMPCODE") and omp_bin():
|
|
610
|
+
print(" - omp: `tezgah-ocr-review --repo %s --from %s --to HEAD "
|
|
611
|
+
"--output OCR.json` runs OCR's own review on omp's model; hand its "
|
|
612
|
+
"comments to the reviewers as candidates to confirm or refute, "
|
|
613
|
+
"never as findings" % (shlex.quote(where), base))
|
|
614
|
+
|
|
437
615
|
|
|
438
616
|
def verification_steps(text, path):
|
|
439
617
|
"""What the verification phase requires before the plan is done: the plan's
|
|
@@ -510,6 +688,7 @@ def verification_steps(text, path):
|
|
|
510
688
|
"without a new round, or recorded fix-later under ## State only "
|
|
511
689
|
"when it waits on a user decision (%s), and the verdict is "
|
|
512
690
|
"`approve`" % say()["decision"])
|
|
691
|
+
print_ocr_spec(where, base)
|
|
513
692
|
print(" 3. record its verdict: `tezgah-task review %s <reviewer> approve|changes`"
|
|
514
693
|
" (records the reviewed sha);"
|
|
515
694
|
" `tezgah-task close %s done` refuses without an approve" % (ident, ident))
|
|
@@ -552,6 +731,11 @@ def cmd_start(args):
|
|
|
552
731
|
if i + 1 >= len(rest) or rest[i + 1].startswith("--"):
|
|
553
732
|
return misuse("--branch needs the branch name to bind the plan to")
|
|
554
733
|
branch = rest[i + 1]
|
|
734
|
+
if branch in PLAN_TRUNKS:
|
|
735
|
+
return misuse("--branch %s: a trunk (%s) never binds a plan - the gate "
|
|
736
|
+
"reads every PLAN_TRUNKS name as unplanned; bind a "
|
|
737
|
+
"plan/NNN-slug branch instead"
|
|
738
|
+
% (branch, ", ".join(PLAN_TRUNKS)))
|
|
555
739
|
i += 2
|
|
556
740
|
continue
|
|
557
741
|
if rest[i] == ANY_PATH:
|
|
@@ -619,7 +803,19 @@ def cmd_start(args):
|
|
|
619
803
|
bad = write_fields(path, **fields)
|
|
620
804
|
if bad:
|
|
621
805
|
return problems(bad)
|
|
622
|
-
|
|
806
|
+
shown = show(path)
|
|
807
|
+
top = repo_root(os.getcwd())
|
|
808
|
+
if main_root(top) != top:
|
|
809
|
+
# a worktree bound to a plan gets its graph now, seeded from the main
|
|
810
|
+
# checkout's (plan 118); an index that cannot start costs the line, never
|
|
811
|
+
# the start the record already holds
|
|
812
|
+
try:
|
|
813
|
+
from tezgah_context import autoindex, under
|
|
814
|
+
if under(top):
|
|
815
|
+
print("graph: %s" % autoindex(top))
|
|
816
|
+
except Exception:
|
|
817
|
+
pass
|
|
818
|
+
return shown
|
|
623
819
|
|
|
624
820
|
|
|
625
821
|
def cmd_phase(args):
|
|
@@ -886,7 +1082,7 @@ def budget_spent(path, ident):
|
|
|
886
1082
|
% (path, REVIEW_ROUNDS, ident, say()["decision"], ident))
|
|
887
1083
|
|
|
888
1084
|
|
|
889
|
-
def unfinished_review(root, reviewer, plan="", since=0):
|
|
1085
|
+
def unfinished_review(root, reviewer, plan="", since=0, no_slice="", ran_since=0):
|
|
890
1086
|
"""The refusal of an `approve` while a slice journal record whose id or agent
|
|
891
1087
|
is `reviewer` is open, stopped or stale: a review slice that died on a
|
|
892
1088
|
provider limit had its approve recorded anyway, and a NameError it would have
|
|
@@ -901,7 +1097,11 @@ def unfinished_review(root, reviewer, plan="", since=0):
|
|
|
901
1097
|
`tt.open_slice`) counts too. Under TEZGAH_SESSION only this session's
|
|
902
1098
|
records and unowned ones count, by id, agent or name alike: another
|
|
903
1099
|
session's review is not this approve's. The refusal names the exact id,
|
|
904
|
-
which `slice resume` and `slice done` take from any session.
|
|
1100
|
+
which `slice resume` and `slice done` take from any session. No finished
|
|
1101
|
+
record changed at or after `ran_since` refuses too: a requested reviewer with
|
|
1102
|
+
no status did not run, and a plan-readiness review before the checkpoint, an
|
|
1103
|
+
earlier round's review or a `resumed` record with no re-run is not this
|
|
1104
|
+
review - unless `no_slice` says why the reviewer ran outside the journal."""
|
|
905
1105
|
from tezgah_paths import off
|
|
906
1106
|
if off("slices-off"):
|
|
907
1107
|
return []
|
|
@@ -917,21 +1117,42 @@ def unfinished_review(root, reviewer, plan="", since=0):
|
|
|
917
1117
|
return rec["plan"] == plan
|
|
918
1118
|
return (_stamp(rec.get("updated")) or 0) >= since
|
|
919
1119
|
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1120
|
+
found = [rec for rec in tt.slices(root) if named(rec) and ours(rec)]
|
|
1121
|
+
refusals = ["review slice %s is %s%s: let it finish, or resume it with `tezgah-task "
|
|
1122
|
+
"slice resume %s` and wait for that run; if the review was finished "
|
|
1123
|
+
"another way, record it with `tezgah-task slice done %s` - an approve "
|
|
1124
|
+
"from a review that did not finish reads nothing"
|
|
1125
|
+
% (rec["id"], rec.get("status"),
|
|
1126
|
+
(" (%s)" % rec["failure"]) if rec.get("failure") else "",
|
|
1127
|
+
rec["id"], rec["id"])
|
|
1128
|
+
for rec in found if rec.get("status") in ("open", "stopped", "stale")]
|
|
1129
|
+
ran = [rec for rec in found if rec.get("status") == "done"
|
|
1130
|
+
and (_stamp(rec.get("updated")) or 0) >= ran_since]
|
|
1131
|
+
if not ran and not refusals and not no_slice:
|
|
1132
|
+
# a requested reviewer with no finished record since the work is a
|
|
1133
|
+
# review that did not run
|
|
1134
|
+
refusals.append(
|
|
1135
|
+
"no finished review slice names %s for this plan since its work began: "
|
|
1136
|
+
"a reviewer with no record did not run, and a readiness review, an "
|
|
1137
|
+
"earlier round or a resumed record is not this review. Spawn the fresh "
|
|
1138
|
+
"reviewer and approve once its slice is done; a host that keeps no "
|
|
1139
|
+
"slice journal records why with "
|
|
1140
|
+
"`--no-slice \"<why: the reviewer ran outside the slice journal>\"`"
|
|
1141
|
+
% reviewer)
|
|
1142
|
+
return refusals
|
|
930
1143
|
|
|
931
1144
|
|
|
932
1145
|
def cmd_review(args):
|
|
1146
|
+
no_slice = ""
|
|
1147
|
+
if "--no-slice" in args:
|
|
1148
|
+
i = args.index("--no-slice")
|
|
1149
|
+
no_slice = " ".join((args[i + 1:i + 2] or [""])[0].split())
|
|
1150
|
+
args = args[:i] + args[i + 2:]
|
|
1151
|
+
if not no_slice:
|
|
1152
|
+
return misuse("--no-slice takes why the reviewer ran outside the slice journal")
|
|
933
1153
|
if len(args) != 3 or args[2] not in VERDICTS:
|
|
934
|
-
return misuse("review takes <NNN|path> <reviewer> %s
|
|
1154
|
+
return misuse("review takes <NNN|path> <reviewer> %s [--no-slice WHY]"
|
|
1155
|
+
% "|".join(VERDICTS))
|
|
935
1156
|
path, problem = open_plan(args[0])
|
|
936
1157
|
if problem:
|
|
937
1158
|
return problems([problem])
|
|
@@ -948,9 +1169,21 @@ def cmd_review(args):
|
|
|
948
1169
|
mark = (fields.get("checkpoint") or "").split()
|
|
949
1170
|
since = (git_out(root, "log", "-1", "--format=%ct", mark[-1])
|
|
950
1171
|
if mark and mark[-1] != tt.CHECKPOINT_PENDING else None)
|
|
1172
|
+
since = int(since) if (since or "").isdigit() else 0
|
|
1173
|
+
# this round's review finished after the first commit of the work it
|
|
1174
|
+
# reads: past the checkpoint in round one (a plan-readiness review ran
|
|
1175
|
+
# before it), past the commit round one read in round two (round one's
|
|
1176
|
+
# reviewer finished before it); with no such commit, after the base itself
|
|
951
1177
|
ident = fields.get("id") or os.path.basename(path).split("-")[0]
|
|
952
|
-
|
|
953
|
-
|
|
1178
|
+
base = fields.get("reviewed_sha") or (
|
|
1179
|
+
mark[-1] if mark and mark[-1] != tt.CHECKPOINT_PENDING else "")
|
|
1180
|
+
first = ""
|
|
1181
|
+
if base:
|
|
1182
|
+
after = (git_out(tt.plan_holders(root).get(ident) or root, "log",
|
|
1183
|
+
"--reverse", "--format=%ct", base + "..HEAD") or "").split()
|
|
1184
|
+
first = after[0] if after else git_out(root, "log", "-1", "--format=%ct", base)
|
|
1185
|
+
ran_since = max(since, int(first) if (first or "").isdigit() else 0)
|
|
1186
|
+
bad = unfinished_review(root, args[1], ident, since, no_slice, ran_since)
|
|
954
1187
|
if bad:
|
|
955
1188
|
return problems(bad)
|
|
956
1189
|
# a plan held by its own worktree is built on that branch: its HEAD is the
|
|
@@ -958,7 +1191,8 @@ def cmd_review(args):
|
|
|
958
1191
|
ident = fields.get("id") or os.path.basename(path).split("-")[0]
|
|
959
1192
|
where = tt.plan_holders(root).get(ident) or root
|
|
960
1193
|
sha = (git_out(where, "rev-parse", "HEAD") or "")[:12]
|
|
961
|
-
record = {"review": "%s %s %s" % (args[1], args[2], today()
|
|
1194
|
+
record = {"review": "%s %s %s%s" % (args[1], args[2], today(),
|
|
1195
|
+
" no-slice: " + no_slice if no_slice else ""),
|
|
962
1196
|
"review_round": str(int(prior) + 1 if prior.isdigit() else 1),
|
|
963
1197
|
"updated": today()}
|
|
964
1198
|
if sha:
|
|
@@ -1814,6 +2048,10 @@ def main(argv):
|
|
|
1814
2048
|
print(__doc__, file=sys.stderr)
|
|
1815
2049
|
return 2
|
|
1816
2050
|
cmd, rest = argv[1], argv[2:]
|
|
2051
|
+
if writes_a_record(cmd, rest):
|
|
2052
|
+
mark = owner_mark(repo_root(os.getcwd()))
|
|
2053
|
+
if mark:
|
|
2054
|
+
return problems([mark])
|
|
1817
2055
|
if cmd == "start":
|
|
1818
2056
|
return cmd_start(rest)
|
|
1819
2057
|
if cmd == "phase":
|
package/commands/adhd.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Run
|
|
1
|
+
Run `~/.config/tezgah/bin/tezgah-adhd $ARGUMENTS` and report the one line it prints.
|
|
2
2
|
|
|
3
3
|
The installed CLI owns the state: it writes or removes
|
|
4
4
|
`~/.config/tezgah/adhd-off`, the kill switch that drops the act-on-it rule from
|
|
@@ -6,7 +6,7 @@ the text every host injects. Never create or delete that file by hand, and never
|
|
|
6
6
|
edit any other rule's switch from here.
|
|
7
7
|
|
|
8
8
|
```sh
|
|
9
|
-
adhd
|
|
9
|
+
adhd="$HOME/.config/tezgah/bin/tezgah-adhd"
|
|
10
10
|
"$adhd" $ARGUMENTS
|
|
11
11
|
```
|
|
12
12
|
|