@r1z4x/tezgah 1.9.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +98 -1
- package/MANIFEST +382 -144
- package/README.de.md +1 -1
- package/README.es.md +1 -1
- package/README.fr.md +1 -1
- package/README.md +1 -1
- 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 +216 -40
- package/bin/tezgah-review-quote +185 -0
- package/bin/tezgah-setup +136 -33
- package/bin/tezgah-skill +1 -1
- package/bin/tezgah-status +201 -3
- package/bin/tezgah-task +203 -3
- package/commands/adhd.md +2 -2
- package/commands/ponytail.md +4 -4
- package/docs/architecture.md +2 -2
- package/docs/citations-baseline.json +2 -2
- package/docs/clarity-baseline.json +2 -2
- package/docs/contract.md +87 -42
- package/docs/environment.md +5 -3
- package/docs/evidence.md +28 -9
- package/docs/feature-audit.md +2 -2
- package/docs/gate.md +54 -31
- package/docs/glossary.md +5 -2
- package/docs/hosts.md +17 -3
- package/docs/index.json +34 -8
- package/docs/judge.md +4 -2
- package/docs/layers.md +3 -3
- package/docs/models.md +31 -9
- package/docs/operations.md +148 -8
- package/docs/research.md +786 -5
- package/docs/skills.md +137 -13
- package/docs/status-line.md +115 -1
- package/hooks/hooks.json +1 -1
- package/hooks/lang/en.json +10 -0
- package/hooks/lang/tr.json +11 -1
- package/hooks/tezgah_agents.py +38 -22
- package/hooks/tezgah_apps.py +18 -0
- package/hooks/tezgah_components.py +4 -0
- package/hooks/tezgah_context.py +189 -50
- package/hooks/tezgah_extension.py +337 -0
- package/hooks/tezgah_gate.py +188 -56
- package/hooks/tezgah_integrity.py +652 -105
- 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 +102 -6
- package/hooks/tezgah_policy.py +94 -45
- package/hooks/tezgah_rank.py +9 -6
- package/hooks/tezgah_replay.py +4 -4
- package/hooks/tezgah_research.py +1260 -65
- 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_stopspec.py +8 -1
- package/hooks/tezgah_task.py +12 -4
- package/hooks/tezgah_taste_ledger.py +1 -1
- package/hosts/cursor/hook.py +29 -2
- package/hosts/opencode/plugins/tezgah.js +307 -46
- package/hosts/opencode/tui/cli/tui.tsx +100 -0
- package/hosts/opencode/tui/tezgah-tui.tsx +2 -1
- package/output-styles/tezgah.md +10 -10
- package/package.json +1 -1
- package/packaging/install.ps1 +36 -3
- package/packaging/install.sh +13 -3
- package/packaging/upgrade.sh +61 -7
- 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 +15 -8
- package/skills/i-have-adhd/SKILL.md +22 -11
- package/skills/no-ai-slop/SKILL.md +15 -1
- package/skills/plan-add/SKILL.md +33 -26
- 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 +75 -39
- package/skills/rl-env/SKILL.md +25 -13
- package/skills/rl-env/SOURCE +8 -6
- package/skills/tezgah-contract/SKILL.md +47 -42
- 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
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Statusline extensions: a repository's own metrics, on tezgah's line.
|
|
3
|
+
|
|
4
|
+
A repository adds chips to the status line without touching tezgah. It drops one
|
|
5
|
+
manifest at `<repo>/.tezgah/extension.json`:
|
|
6
|
+
|
|
7
|
+
{"statusline": {"command": ["bin/engagement-statusline", "--segments"],
|
|
8
|
+
"timeout_ms": 300}}
|
|
9
|
+
|
|
10
|
+
and that command prints structured segments on stdout:
|
|
11
|
+
|
|
12
|
+
{"segments": [{"key": "eng", "state": "info", "text": "pentest-001",
|
|
13
|
+
"glyph": "", "group": 0}]}
|
|
14
|
+
|
|
15
|
+
The command is handed its own call on stdin as one JSON object -
|
|
16
|
+
`{"api": 1, "event": "statusline", "cwd": ..., "repo_root": ...,
|
|
17
|
+
"session_id": ...}` (`call_envelope()`) - so it knows which repository and
|
|
18
|
+
session asked, rather than guessing from its environment.
|
|
19
|
+
|
|
20
|
+
tezgah discovers the manifest by walking up from the working directory, runs the
|
|
21
|
+
command once per render (bounded, fail-open) and appends what it returns after
|
|
22
|
+
its own marks. The core owns rendering: an extension produces data, never a
|
|
23
|
+
formatted line, so color, the narrow-surface drop and the group separators stay
|
|
24
|
+
identical for every extension, and the extension never has to know tezgah's
|
|
25
|
+
gutter.
|
|
26
|
+
|
|
27
|
+
Why a subprocess and not an import: the extension lives in the user's repo, in
|
|
28
|
+
whatever language, and may be slow or broken. Importing it runs its code in the
|
|
29
|
+
harness's own process; a bounded child is the seam that keeps a broken extension
|
|
30
|
+
costing one chip on one line, never the gate that carries every turn.
|
|
31
|
+
|
|
32
|
+
The line is drawn on every redraw, so the cost is bounded on purpose: the walk
|
|
33
|
+
stops at the first manifest, the child gets a hard timeout, and a repo with no
|
|
34
|
+
manifest pays a single `os.path.isfile` per level and nothing else.
|
|
35
|
+
|
|
36
|
+
The same manifest carries four more keys. Each is read here, consumed by one
|
|
37
|
+
caller and validated the way `statusline` is, so a broken value costs that key
|
|
38
|
+
and never the line or the gate (docs/status-line.md, "The manifest's other
|
|
39
|
+
keys"):
|
|
40
|
+
|
|
41
|
+
{"checks": ["./bin/run-tool"], # repo_checks
|
|
42
|
+
"untrusted": ["nmap", "sqlmap"], # untrusted_programs
|
|
43
|
+
"agents": [{"match": "(?i)recon", "agent": "recon"}], # repo_agent
|
|
44
|
+
"statusline": {"command": [...], "override": true}} # override
|
|
45
|
+
"""
|
|
46
|
+
import json
|
|
47
|
+
import os
|
|
48
|
+
import re
|
|
49
|
+
import shlex
|
|
50
|
+
import subprocess
|
|
51
|
+
|
|
52
|
+
EXT_DIR = ".tezgah"
|
|
53
|
+
MANIFEST_NAME = "extension.json"
|
|
54
|
+
# The variable a domain repository names its engagement root with: a session
|
|
55
|
+
# working anywhere under `$TEZGAH_ENGAGEMENTS_ROOT/<slug>` reads that
|
|
56
|
+
# engagement's own manifest even when the walk up ran out first.
|
|
57
|
+
ENGAGEMENTS_ENV = "TEZGAH_ENGAGEMENTS_ROOT"
|
|
58
|
+
# How far the walk climbs before giving up. A repo root is at most a few levels
|
|
59
|
+
# above any working directory an editor or a host opens; a bound keeps a
|
|
60
|
+
# manifest-less path from stat-ing every ancestor up to `/`.
|
|
61
|
+
MAX_WALK = 12
|
|
62
|
+
# A healthy extension costs one interpreter start (~25 ms measured 2026-10-19),
|
|
63
|
+
# but a cold start under a loaded machine spiked past 500 ms, so the default
|
|
64
|
+
# carries headroom: the budget is a hang detector, not a latency budget, and a
|
|
65
|
+
# manifest that knows its own cost lowers it.
|
|
66
|
+
DEFAULT_TIMEOUT_MS = 1000
|
|
67
|
+
# A chip budget, not a data budget: the status line is one row, and an extension
|
|
68
|
+
# that floods it is a bug in the extension. The per-extension cap keeps one
|
|
69
|
+
# broken manifest from pushing the built-in marks off the line.
|
|
70
|
+
MAX_SEGMENTS = 8
|
|
71
|
+
STATES = ("on", "ready", "off", "info")
|
|
72
|
+
# The call envelope's version, not this module's: it is what tells an extension
|
|
73
|
+
# which keys to expect on its stdin. Adding a key leaves it alone; changing what
|
|
74
|
+
# a key means bumps it.
|
|
75
|
+
CALL_API = 1
|
|
76
|
+
# The other keys' bounds. A list past its cap is cut, not refused, so a long
|
|
77
|
+
# manifest still contributes its first entries. A pattern is bounded in length
|
|
78
|
+
# and the brief it reads in characters, so a repo's regex cannot hold route() up.
|
|
79
|
+
MAX_CHECKS = 32
|
|
80
|
+
# A `checks` prefix that is one of these programs alone checks nothing, and a
|
|
81
|
+
# run of it would license a pass; with a word beyond the program (`echo tested`)
|
|
82
|
+
# it names one command and stays.
|
|
83
|
+
NO_OP_PROGRAMS = frozenset(("echo", "true", "cat", "printf", "ls"))
|
|
84
|
+
MAX_UNTRUSTED = 64
|
|
85
|
+
MAX_AGENTS = 32
|
|
86
|
+
MAX_PATTERN = 512
|
|
87
|
+
MAX_BRIEF = 4000
|
|
88
|
+
# An agent name lands in a ledger row's `agent=` word and in a spawn call, so it
|
|
89
|
+
# is one word of a file-name alphabet; a program name is one basename.
|
|
90
|
+
NAME = re.compile(r"^[A-Za-z0-9][\w.+-]{0,63}$")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def call_envelope(repo_root, cwd, session_id=None):
|
|
94
|
+
"""The one JSON object every extension call carries on stdin.
|
|
95
|
+
|
|
96
|
+
The child is told which repository it was called for, from which directory
|
|
97
|
+
and in which session, instead of inferring that from its own environment. A
|
|
98
|
+
key an extension does not know it ignores; `api` is the key it can gate on,
|
|
99
|
+
so a future envelope reads as a named refusal rather than a wrong chip."""
|
|
100
|
+
return {"api": CALL_API, "event": "statusline",
|
|
101
|
+
"cwd": os.path.realpath(cwd), "repo_root": repo_root,
|
|
102
|
+
"session_id": session_id or None}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def manifest_path(cwd):
|
|
106
|
+
"""(repo_root, manifest_path) for the nearest `.tezgah/extension.json` above
|
|
107
|
+
`cwd`, or (None, None) when there is none within MAX_WALK levels.
|
|
108
|
+
|
|
109
|
+
The first manifest wins: nesting is a mistake, not a feature, and stopping
|
|
110
|
+
early is what makes the walk cheap. When the walk finds none, a cwd under
|
|
111
|
+
`$TEZGAH_ENGAGEMENTS_ROOT/<slug>` reads that engagement's manifest however
|
|
112
|
+
deep it sits (`_engagement_manifest`)."""
|
|
113
|
+
path = os.path.realpath(cwd)
|
|
114
|
+
for _ in range(MAX_WALK):
|
|
115
|
+
candidate = os.path.join(path, EXT_DIR, MANIFEST_NAME)
|
|
116
|
+
if os.path.isfile(candidate):
|
|
117
|
+
return path, candidate
|
|
118
|
+
parent = os.path.dirname(path)
|
|
119
|
+
if parent == path:
|
|
120
|
+
break
|
|
121
|
+
path = parent
|
|
122
|
+
return _engagement_manifest(cwd)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _engagement_manifest(cwd):
|
|
126
|
+
"""(engagement_root, manifest_path) for a cwd under
|
|
127
|
+
`$TEZGAH_ENGAGEMENTS_ROOT/<slug>`, or (None, None): no root set, a cwd
|
|
128
|
+
outside it or at the root itself, or no manifest in that engagement. One
|
|
129
|
+
`isfile`, so an unset or unrelated root costs nothing."""
|
|
130
|
+
root = os.environ.get(ENGAGEMENTS_ENV)
|
|
131
|
+
if not root:
|
|
132
|
+
return None, None
|
|
133
|
+
root = os.path.realpath(os.path.expanduser(root))
|
|
134
|
+
rel = os.path.relpath(os.path.realpath(cwd), root)
|
|
135
|
+
slug = rel.split(os.sep, 1)[0]
|
|
136
|
+
if slug in (os.curdir, os.pardir):
|
|
137
|
+
return None, None
|
|
138
|
+
engagement = os.path.join(root, slug)
|
|
139
|
+
candidate = os.path.join(engagement, EXT_DIR, MANIFEST_NAME)
|
|
140
|
+
return (engagement, candidate) if os.path.isfile(candidate) else (None, None)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def given_manifest(manifest_file):
|
|
144
|
+
"""(repo_root, manifest_path) for a manifest named outright (the renderer's
|
|
145
|
+
`--manifest`): the repo root is the directory holding its `.tezgah`, else
|
|
146
|
+
the directory holding the file. (None, None) when it is no file."""
|
|
147
|
+
path = os.path.realpath(os.path.expanduser(manifest_file))
|
|
148
|
+
if not os.path.isfile(path):
|
|
149
|
+
return None, None
|
|
150
|
+
folder = os.path.dirname(path)
|
|
151
|
+
return (os.path.dirname(folder) if os.path.basename(folder) == EXT_DIR
|
|
152
|
+
else folder), path
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _load_manifest(manifest_file):
|
|
156
|
+
"""The manifest dict, or None when it is missing or malformed. A bad manifest
|
|
157
|
+
costs the extension, never the line."""
|
|
158
|
+
try:
|
|
159
|
+
with open(manifest_file, encoding="utf-8") as fh:
|
|
160
|
+
data = json.load(fh)
|
|
161
|
+
except (OSError, ValueError, UnicodeDecodeError):
|
|
162
|
+
return None
|
|
163
|
+
return data if isinstance(data, dict) else None
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def load(cwd, manifest_file=None):
|
|
167
|
+
"""(repo_root, manifest dict) for `cwd` - or for `manifest_file` when one
|
|
168
|
+
is named - else (None, None). Never raises: every key reader below goes
|
|
169
|
+
through it, and a reader that raised would cost its caller the call."""
|
|
170
|
+
try:
|
|
171
|
+
repo_root, found = (given_manifest(manifest_file) if manifest_file
|
|
172
|
+
else manifest_path(cwd))
|
|
173
|
+
except (OSError, ValueError, TypeError):
|
|
174
|
+
return None, None
|
|
175
|
+
manifest = _load_manifest(found) if found else None
|
|
176
|
+
return (repo_root, manifest) if manifest else (None, None)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def repo_checks(cwd):
|
|
180
|
+
"""[argv prefix] the manifest's `checks` declares, each a list of words.
|
|
181
|
+
|
|
182
|
+
An entry is a string split the shell's way (`"bin/audit --check"` is two
|
|
183
|
+
words) or a list of strings; anything else - a number, an empty string, a
|
|
184
|
+
line shlex rejects - is dropped alone. The first word is normalised
|
|
185
|
+
(`./bin/x` and `bin/x` are one prefix), the way a command word is read. A
|
|
186
|
+
lone NO_OP_PROGRAMS word (`echo`, `/bin/true`) is dropped too."""
|
|
187
|
+
_root, manifest = load(cwd)
|
|
188
|
+
raw = (manifest or {}).get("checks")
|
|
189
|
+
if not isinstance(raw, list):
|
|
190
|
+
return []
|
|
191
|
+
out = []
|
|
192
|
+
for entry in raw[:MAX_CHECKS]:
|
|
193
|
+
try:
|
|
194
|
+
words = (shlex.split(entry) if isinstance(entry, str)
|
|
195
|
+
else list(entry) if isinstance(entry, list) else [])
|
|
196
|
+
except ValueError:
|
|
197
|
+
continue
|
|
198
|
+
if words and all(isinstance(w, str) and w for w in words) and not (
|
|
199
|
+
len(words) == 1 and os.path.basename(words[0]) in NO_OP_PROGRAMS):
|
|
200
|
+
out.append([os.path.normpath(words[0])] + words[1:])
|
|
201
|
+
return out
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def untrusted_programs(cwd):
|
|
205
|
+
"""frozenset of the program names the manifest's `untrusted` declares: one
|
|
206
|
+
basename each, case kept (a shell's program word is case-sensitive). A
|
|
207
|
+
non-list, or an entry that is no name, is dropped."""
|
|
208
|
+
_root, manifest = load(cwd)
|
|
209
|
+
raw = (manifest or {}).get("untrusted")
|
|
210
|
+
if not isinstance(raw, list):
|
|
211
|
+
return frozenset()
|
|
212
|
+
return frozenset(os.path.basename(p) for p in raw[:MAX_UNTRUSTED]
|
|
213
|
+
if isinstance(p, str) and NAME.match(os.path.basename(p)))
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def repo_agent(brief, cwd):
|
|
217
|
+
"""(agent, pattern) of the first `agents` entry whose `match` regex finds
|
|
218
|
+
the brief, or None. An entry with no string pattern, a pattern longer than
|
|
219
|
+
MAX_PATTERN or one `re` rejects, or an agent that is no one-word name, is
|
|
220
|
+
dropped alone; the brief is read on its first MAX_BRIEF characters."""
|
|
221
|
+
_root, manifest = load(cwd)
|
|
222
|
+
raw = (manifest or {}).get("agents")
|
|
223
|
+
if not isinstance(raw, list):
|
|
224
|
+
return None
|
|
225
|
+
text = str(brief or "")[:MAX_BRIEF]
|
|
226
|
+
for entry in raw[:MAX_AGENTS]:
|
|
227
|
+
if not isinstance(entry, dict):
|
|
228
|
+
continue
|
|
229
|
+
pattern, agent = entry.get("match"), entry.get("agent")
|
|
230
|
+
if not (isinstance(pattern, str) and pattern and len(pattern) <= MAX_PATTERN
|
|
231
|
+
and isinstance(agent, str) and NAME.match(agent)):
|
|
232
|
+
continue
|
|
233
|
+
try:
|
|
234
|
+
if re.search(pattern, text):
|
|
235
|
+
return agent, pattern
|
|
236
|
+
except re.error:
|
|
237
|
+
continue
|
|
238
|
+
return None
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def override(cwd, manifest_file=None):
|
|
242
|
+
"""True when the manifest's `statusline.override` is literally `true`: the
|
|
243
|
+
project owns its status line and points it at tezgah's renderer, so that
|
|
244
|
+
renderer is the only line. Any other value is False."""
|
|
245
|
+
_root, manifest = load(cwd, manifest_file)
|
|
246
|
+
spec = (manifest or {}).get("statusline")
|
|
247
|
+
return isinstance(spec, dict) and spec.get("override") is True
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _valid_segment(seg, index):
|
|
251
|
+
"""One segment dict, normalized, or None when it cannot be rendered.
|
|
252
|
+
|
|
253
|
+
`text` and `state` are the only required fields: text is what the reader
|
|
254
|
+
sees, state is what the glyph and the color mean. A missing or unknown state
|
|
255
|
+
is `info` (the state-less mark), never a guess at "on"."""
|
|
256
|
+
if not isinstance(seg, dict):
|
|
257
|
+
return None
|
|
258
|
+
text = seg.get("text")
|
|
259
|
+
if not isinstance(text, str) or not text.strip():
|
|
260
|
+
return None
|
|
261
|
+
state = seg.get("state")
|
|
262
|
+
if state not in STATES:
|
|
263
|
+
state = "info"
|
|
264
|
+
key = seg.get("key")
|
|
265
|
+
if not isinstance(key, str) or not key:
|
|
266
|
+
key = "ext-%d" % index
|
|
267
|
+
glyph = seg.get("glyph")
|
|
268
|
+
if not isinstance(glyph, str):
|
|
269
|
+
glyph = ""
|
|
270
|
+
return {"key": key, "state": state, "glyph": glyph, "text": text.strip()}
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def run_manifest(repo_root, manifest, envelope=None):
|
|
274
|
+
"""The segments a manifest's command returns, or [] on any failure.
|
|
275
|
+
|
|
276
|
+
Failure is a closed door, not a raised one: a missing command, a non-zero
|
|
277
|
+
exit, a timeout, malformed JSON, a wrong shape and an over-budget list all
|
|
278
|
+
answer [] - the line loses this extension's chips and keeps its own.
|
|
279
|
+
|
|
280
|
+
`envelope` reaches the child as one JSON object on stdin. A command that
|
|
281
|
+
never reads its stdin sees the same closed, empty input it always did."""
|
|
282
|
+
spec = manifest.get("statusline")
|
|
283
|
+
if not isinstance(spec, dict):
|
|
284
|
+
return []
|
|
285
|
+
command = spec.get("command")
|
|
286
|
+
if (not isinstance(command, list) or not command
|
|
287
|
+
or not all(isinstance(a, str) for a in command)):
|
|
288
|
+
return []
|
|
289
|
+
timeout_ms = spec.get("timeout_ms", DEFAULT_TIMEOUT_MS)
|
|
290
|
+
if not isinstance(timeout_ms, (int, float)) or timeout_ms <= 0:
|
|
291
|
+
timeout_ms = DEFAULT_TIMEOUT_MS
|
|
292
|
+
argv = list(command)
|
|
293
|
+
# A bare program name resolves on PATH; a path is relative to the repo root,
|
|
294
|
+
# so a manifest travels with its clone instead of naming an absolute path.
|
|
295
|
+
if os.sep in argv[0] and not os.path.isabs(argv[0]):
|
|
296
|
+
argv[0] = os.path.join(repo_root, argv[0])
|
|
297
|
+
if os.sep in argv[0] and not os.path.isfile(argv[0]):
|
|
298
|
+
return []
|
|
299
|
+
try:
|
|
300
|
+
proc = subprocess.run(argv, cwd=repo_root, capture_output=True,
|
|
301
|
+
text=True, encoding="utf-8",
|
|
302
|
+
input=(json.dumps(envelope) if envelope is not None
|
|
303
|
+
else ""),
|
|
304
|
+
timeout=timeout_ms / 1000.0)
|
|
305
|
+
except (OSError, subprocess.SubprocessError, ValueError):
|
|
306
|
+
return []
|
|
307
|
+
if proc.returncode != 0:
|
|
308
|
+
return []
|
|
309
|
+
try:
|
|
310
|
+
payload = json.loads(proc.stdout or "")
|
|
311
|
+
except ValueError:
|
|
312
|
+
return []
|
|
313
|
+
if not isinstance(payload, dict):
|
|
314
|
+
return []
|
|
315
|
+
raw = payload.get("segments")
|
|
316
|
+
if not isinstance(raw, list):
|
|
317
|
+
return []
|
|
318
|
+
out = []
|
|
319
|
+
for index, seg in enumerate(raw[:MAX_SEGMENTS]):
|
|
320
|
+
clean = _valid_segment(seg, index)
|
|
321
|
+
if clean is not None:
|
|
322
|
+
out.append(clean)
|
|
323
|
+
return out
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def segments(cwd, session_id=None, manifest_file=None):
|
|
327
|
+
"""Every extension segment for a render of `cwd`, in manifest order.
|
|
328
|
+
`manifest_file` names the manifest outright (the renderer's `--manifest`)
|
|
329
|
+
instead of discovering it from `cwd`.
|
|
330
|
+
|
|
331
|
+
One manifest today (the first found); the return is a list so a second
|
|
332
|
+
extension is a discovery change, not a caller change."""
|
|
333
|
+
repo_root, manifest = load(cwd, manifest_file)
|
|
334
|
+
if not manifest:
|
|
335
|
+
return []
|
|
336
|
+
return run_manifest(repo_root, manifest,
|
|
337
|
+
call_envelope(repo_root, cwd, session_id))
|