@r1z4x/tezgah 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +738 -0
- package/LICENSE +21 -0
- package/MANIFEST +753 -0
- package/README.de.md +169 -0
- package/README.es.md +168 -0
- package/README.fr.md +166 -0
- package/README.md +161 -0
- package/README.tr.md +163 -0
- package/agents/tezgah-reviewer.md +70 -0
- package/bin/codegen +337 -0
- package/bin/consult +797 -0
- package/bin/tezgah-adhd +50 -0
- package/bin/tezgah-agents +45 -0
- package/bin/tezgah-capture +66 -0
- package/bin/tezgah-context +96 -0
- package/bin/tezgah-decisions +213 -0
- package/bin/tezgah-design +953 -0
- package/bin/tezgah-docs +1199 -0
- package/bin/tezgah-doctor +497 -0
- package/bin/tezgah-dsh +37 -0
- package/bin/tezgah-dsh.cmd +70 -0
- package/bin/tezgah-gate +75 -0
- package/bin/tezgah-import-ai-research +439 -0
- package/bin/tezgah-index +32 -0
- package/bin/tezgah-lessons +148 -0
- package/bin/tezgah-mcp +322 -0
- package/bin/tezgah-migrate +324 -0
- package/bin/tezgah-pony +50 -0
- package/bin/tezgah-research +772 -0
- package/bin/tezgah-rollback +93 -0
- package/bin/tezgah-route +124 -0
- package/bin/tezgah-setup +5798 -0
- package/bin/tezgah-status +383 -0
- package/bin/tezgah-task +607 -0
- package/bin/tezgah-taste +423 -0
- package/bin/tezgah-triage +485 -0
- package/bin/tezgah.js +36 -0
- package/commands/adhd.md +21 -0
- package/commands/ponytail.md +21 -0
- package/docs/README.md +112 -0
- package/docs/architecture.md +226 -0
- package/docs/citations-baseline.json +59 -0
- package/docs/clarity-baseline.json +116 -0
- package/docs/contract.md +416 -0
- package/docs/environment.md +141 -0
- package/docs/evidence.md +831 -0
- package/docs/feature-audit.md +139 -0
- package/docs/gate.md +407 -0
- package/docs/glossary.md +201 -0
- package/docs/hosts.md +400 -0
- package/docs/index.json +471 -0
- package/docs/judge.md +193 -0
- package/docs/layers.md +189 -0
- package/docs/models.md +160 -0
- package/docs/operations.md +666 -0
- package/docs/research.md +809 -0
- package/docs/results/paired-outcome-2026-10.jsonl +254 -0
- package/docs/results/paired-outcome-2026-10.md +204 -0
- package/docs/skills.md +236 -0
- package/docs/status-line.md +315 -0
- package/docs/testing.md +287 -0
- package/docs/vision.md +117 -0
- package/hooks/hooks.json +33 -0
- package/hooks/projects-auto-init.py +98 -0
- package/hooks/projects-posttooluse.py +149 -0
- package/hooks/projects-pretooluse.py +40 -0
- package/hooks/projects-stop.py +60 -0
- package/hooks/tezgah_agents.py +817 -0
- package/hooks/tezgah_apps.py +266 -0
- package/hooks/tezgah_attest.py +255 -0
- package/hooks/tezgah_clarity.py +171 -0
- package/hooks/tezgah_components.py +140 -0
- package/hooks/tezgah_context.py +2953 -0
- package/hooks/tezgah_embed.py +765 -0
- package/hooks/tezgah_gate.py +2736 -0
- package/hooks/tezgah_guard.py +177 -0
- package/hooks/tezgah_index.py +124 -0
- package/hooks/tezgah_integrity.py +5141 -0
- package/hooks/tezgah_judge.py +487 -0
- package/hooks/tezgah_lang.py +230 -0
- package/hooks/tezgah_lessons.py +210 -0
- package/hooks/tezgah_models.py +855 -0
- package/hooks/tezgah_paths.py +1132 -0
- package/hooks/tezgah_policy.py +1039 -0
- package/hooks/tezgah_rank.py +77 -0
- package/hooks/tezgah_replay.py +1109 -0
- package/hooks/tezgah_research.py +5176 -0
- package/hooks/tezgah_shapes.py +305 -0
- package/hooks/tezgah_skill_pick.py +227 -0
- package/hooks/tezgah_snapshot.py +490 -0
- package/hooks/tezgah_stopspec.py +320 -0
- package/hooks/tezgah_task.py +458 -0
- package/hooks/tezgah_taste.py +201 -0
- package/hooks/tezgah_untrusted.py +112 -0
- package/hooks/tezgah_update.py +430 -0
- package/hosts/codex/hook.py +268 -0
- package/hosts/codex/hooks.json +26 -0
- package/hosts/cursor/hook.py +461 -0
- package/hosts/cursor/hooks.json +44 -0
- package/hosts/dsh/hooks.json +21 -0
- package/hosts/dsh/statusline/lib/client.js +138 -0
- package/hosts/dsh/statusline/lib/index.js +104 -0
- package/hosts/dsh/statusline/package.json +28 -0
- package/hosts/omp/hook.py +277 -0
- package/hosts/omp/tezgah-hook.ts.in +701 -0
- package/hosts/opencode/plugins/tezgah.js +2742 -0
- package/hosts/opencode/tui/tezgah-tui.tsx +151 -0
- package/output-styles/tezgah.md +142 -0
- package/package.json +32 -0
- package/packaging/build.sh +342 -0
- package/packaging/install.ps1 +166 -0
- package/packaging/install.sh +56 -0
- package/packaging/upgrade.sh +142 -0
- package/skills/ai-research/0-autoresearch-skill/SKILL.md +411 -0
- package/skills/ai-research/0-autoresearch-skill/references/agent-continuity.md +95 -0
- package/skills/ai-research/0-autoresearch-skill/references/progress-reporting.md +166 -0
- package/skills/ai-research/0-autoresearch-skill/references/skill-routing.md +219 -0
- package/skills/ai-research/0-autoresearch-skill/templates/findings.md +44 -0
- package/skills/ai-research/0-autoresearch-skill/templates/research-log.md +41 -0
- package/skills/ai-research/01-model-architecture/litgpt/SKILL.md +469 -0
- package/skills/ai-research/01-model-architecture/litgpt/references/custom-models.md +569 -0
- package/skills/ai-research/01-model-architecture/litgpt/references/distributed-training.md +452 -0
- package/skills/ai-research/01-model-architecture/litgpt/references/supported-models.md +337 -0
- package/skills/ai-research/01-model-architecture/litgpt/references/training-recipes.md +620 -0
- package/skills/ai-research/01-model-architecture/mamba/SKILL.md +260 -0
- package/skills/ai-research/01-model-architecture/mamba/references/architecture-details.md +207 -0
- package/skills/ai-research/01-model-architecture/mamba/references/benchmarks.md +256 -0
- package/skills/ai-research/01-model-architecture/mamba/references/training-guide.md +389 -0
- package/skills/ai-research/01-model-architecture/nanogpt/SKILL.md +290 -0
- package/skills/ai-research/01-model-architecture/nanogpt/references/architecture.md +383 -0
- package/skills/ai-research/01-model-architecture/nanogpt/references/data.md +477 -0
- package/skills/ai-research/01-model-architecture/nanogpt/references/training.md +565 -0
- package/skills/ai-research/01-model-architecture/rwkv/SKILL.md +260 -0
- package/skills/ai-research/01-model-architecture/rwkv/references/architecture-details.md +345 -0
- package/skills/ai-research/01-model-architecture/rwkv/references/rwkv7.md +387 -0
- package/skills/ai-research/01-model-architecture/rwkv/references/state-management.md +370 -0
- package/skills/ai-research/01-model-architecture/torchtitan/SKILL.md +358 -0
- package/skills/ai-research/01-model-architecture/torchtitan/references/checkpoint.md +182 -0
- package/skills/ai-research/01-model-architecture/torchtitan/references/custom-models.md +259 -0
- package/skills/ai-research/01-model-architecture/torchtitan/references/float8.md +134 -0
- package/skills/ai-research/01-model-architecture/torchtitan/references/fsdp.md +127 -0
- package/skills/ai-research/02-tokenization/huggingface-tokenizers/SKILL.md +516 -0
- package/skills/ai-research/02-tokenization/huggingface-tokenizers/references/algorithms.md +654 -0
- package/skills/ai-research/02-tokenization/huggingface-tokenizers/references/integration.md +638 -0
- package/skills/ai-research/02-tokenization/huggingface-tokenizers/references/pipeline.md +724 -0
- package/skills/ai-research/02-tokenization/huggingface-tokenizers/references/training.md +566 -0
- package/skills/ai-research/02-tokenization/sentencepiece/SKILL.md +235 -0
- package/skills/ai-research/02-tokenization/sentencepiece/references/algorithms.md +201 -0
- package/skills/ai-research/02-tokenization/sentencepiece/references/training.md +305 -0
- package/skills/ai-research/03-fine-tuning/axolotl/SKILL.md +158 -0
- package/skills/ai-research/03-fine-tuning/axolotl/references/api.md +5549 -0
- package/skills/ai-research/03-fine-tuning/axolotl/references/dataset-formats.md +1030 -0
- package/skills/ai-research/03-fine-tuning/axolotl/references/index.md +16 -0
- package/skills/ai-research/03-fine-tuning/axolotl/references/other.md +3564 -0
- package/skills/ai-research/03-fine-tuning/llama-factory/SKILL.md +80 -0
- package/skills/ai-research/03-fine-tuning/llama-factory/references/_images.md +24 -0
- package/skills/ai-research/03-fine-tuning/llama-factory/references/advanced.md +1056 -0
- package/skills/ai-research/03-fine-tuning/llama-factory/references/getting_started.md +350 -0
- package/skills/ai-research/03-fine-tuning/llama-factory/references/index.md +20 -0
- package/skills/ai-research/03-fine-tuning/llama-factory/references/other.md +32 -0
- package/skills/ai-research/03-fine-tuning/peft/SKILL.md +431 -0
- package/skills/ai-research/03-fine-tuning/peft/references/advanced-usage.md +515 -0
- package/skills/ai-research/03-fine-tuning/peft/references/troubleshooting.md +481 -0
- package/skills/ai-research/03-fine-tuning/unsloth/SKILL.md +80 -0
- package/skills/ai-research/03-fine-tuning/unsloth/references/index.md +8 -0
- package/skills/ai-research/03-fine-tuning/unsloth/references/llms.md +83 -0
- package/skills/ai-research/04-mechanistic-interpretability/nnsight/SKILL.md +436 -0
- package/skills/ai-research/04-mechanistic-interpretability/nnsight/references/README.md +79 -0
- package/skills/ai-research/04-mechanistic-interpretability/nnsight/references/api.md +345 -0
- package/skills/ai-research/04-mechanistic-interpretability/nnsight/references/tutorials.md +301 -0
- package/skills/ai-research/04-mechanistic-interpretability/pyvene/SKILL.md +473 -0
- package/skills/ai-research/04-mechanistic-interpretability/pyvene/references/README.md +74 -0
- package/skills/ai-research/04-mechanistic-interpretability/pyvene/references/api.md +384 -0
- package/skills/ai-research/04-mechanistic-interpretability/pyvene/references/tutorials.md +377 -0
- package/skills/ai-research/04-mechanistic-interpretability/saelens/SKILL.md +386 -0
- package/skills/ai-research/04-mechanistic-interpretability/saelens/references/README.md +71 -0
- package/skills/ai-research/04-mechanistic-interpretability/saelens/references/api.md +334 -0
- package/skills/ai-research/04-mechanistic-interpretability/saelens/references/tutorials.md +319 -0
- package/skills/ai-research/04-mechanistic-interpretability/transformer-lens/SKILL.md +346 -0
- package/skills/ai-research/04-mechanistic-interpretability/transformer-lens/references/README.md +55 -0
- package/skills/ai-research/04-mechanistic-interpretability/transformer-lens/references/api.md +363 -0
- package/skills/ai-research/04-mechanistic-interpretability/transformer-lens/references/tutorials.md +340 -0
- package/skills/ai-research/05-data-processing/nemo-curator/SKILL.md +383 -0
- package/skills/ai-research/05-data-processing/nemo-curator/references/deduplication.md +88 -0
- package/skills/ai-research/05-data-processing/nemo-curator/references/filtering.md +103 -0
- package/skills/ai-research/05-data-processing/ray-data/SKILL.md +326 -0
- package/skills/ai-research/05-data-processing/ray-data/references/integration.md +83 -0
- package/skills/ai-research/05-data-processing/ray-data/references/transformations.md +84 -0
- package/skills/ai-research/06-post-training/grpo-rl-training/README.md +98 -0
- package/skills/ai-research/06-post-training/grpo-rl-training/SKILL.md +572 -0
- package/skills/ai-research/06-post-training/miles/SKILL.md +315 -0
- package/skills/ai-research/06-post-training/miles/references/api-reference.md +142 -0
- package/skills/ai-research/06-post-training/miles/references/troubleshooting.md +353 -0
- package/skills/ai-research/06-post-training/openrlhf/SKILL.md +249 -0
- package/skills/ai-research/06-post-training/openrlhf/references/algorithm-comparison.md +405 -0
- package/skills/ai-research/06-post-training/openrlhf/references/custom-rewards.md +531 -0
- package/skills/ai-research/06-post-training/openrlhf/references/hybrid-engine.md +288 -0
- package/skills/ai-research/06-post-training/openrlhf/references/multi-node-training.md +455 -0
- package/skills/ai-research/06-post-training/simpo/SKILL.md +219 -0
- package/skills/ai-research/06-post-training/simpo/references/datasets.md +479 -0
- package/skills/ai-research/06-post-training/simpo/references/hyperparameters.md +453 -0
- package/skills/ai-research/06-post-training/simpo/references/loss-functions.md +351 -0
- package/skills/ai-research/06-post-training/slime/SKILL.md +464 -0
- package/skills/ai-research/06-post-training/slime/references/api-reference.md +393 -0
- package/skills/ai-research/06-post-training/slime/references/troubleshooting.md +387 -0
- package/skills/ai-research/06-post-training/torchforge/SKILL.md +433 -0
- package/skills/ai-research/06-post-training/torchforge/references/api-reference.md +328 -0
- package/skills/ai-research/06-post-training/torchforge/references/troubleshooting.md +410 -0
- package/skills/ai-research/06-post-training/trl-fine-tuning/SKILL.md +455 -0
- package/skills/ai-research/06-post-training/trl-fine-tuning/references/dpo-variants.md +228 -0
- package/skills/ai-research/06-post-training/trl-fine-tuning/references/online-rl.md +83 -0
- package/skills/ai-research/06-post-training/trl-fine-tuning/references/reward-modeling.md +123 -0
- package/skills/ai-research/06-post-training/trl-fine-tuning/references/sft-training.md +169 -0
- package/skills/ai-research/06-post-training/verl/SKILL.md +391 -0
- package/skills/ai-research/06-post-training/verl/references/api-reference.md +302 -0
- package/skills/ai-research/06-post-training/verl/references/troubleshooting.md +392 -0
- package/skills/ai-research/07-safety-alignment/constitutional-ai/SKILL.md +290 -0
- package/skills/ai-research/07-safety-alignment/llamaguard/SKILL.md +337 -0
- package/skills/ai-research/07-safety-alignment/nemo-guardrails/SKILL.md +297 -0
- package/skills/ai-research/07-safety-alignment/prompt-guard/SKILL.md +312 -0
- package/skills/ai-research/08-distributed-training/accelerate/SKILL.md +332 -0
- package/skills/ai-research/08-distributed-training/accelerate/references/custom-plugins.md +454 -0
- package/skills/ai-research/08-distributed-training/accelerate/references/megatron-integration.md +490 -0
- package/skills/ai-research/08-distributed-training/accelerate/references/performance.md +526 -0
- package/skills/ai-research/08-distributed-training/deepspeed/SKILL.md +141 -0
- package/skills/ai-research/08-distributed-training/deepspeed/references/08.md +18 -0
- package/skills/ai-research/08-distributed-training/deepspeed/references/09.md +174 -0
- package/skills/ai-research/08-distributed-training/deepspeed/references/2020.md +379 -0
- package/skills/ai-research/08-distributed-training/deepspeed/references/2023.md +280 -0
- package/skills/ai-research/08-distributed-training/deepspeed/references/assets.md +180 -0
- package/skills/ai-research/08-distributed-training/deepspeed/references/index.md +36 -0
- package/skills/ai-research/08-distributed-training/deepspeed/references/mii.md +119 -0
- package/skills/ai-research/08-distributed-training/deepspeed/references/other.md +1192 -0
- package/skills/ai-research/08-distributed-training/megatron-core/SKILL.md +366 -0
- package/skills/ai-research/08-distributed-training/megatron-core/references/benchmarks.md +250 -0
- package/skills/ai-research/08-distributed-training/megatron-core/references/parallelism-guide.md +405 -0
- package/skills/ai-research/08-distributed-training/megatron-core/references/production-examples.md +474 -0
- package/skills/ai-research/08-distributed-training/megatron-core/references/training-recipes.md +548 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/SKILL.md +231 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_dcp_async_recipe.md +14 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_dcp_overview.md +19 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_dcp_recipe.md +18 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_ddp_notes.md +10 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_device_mesh_tutorial.md +22 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_examples_fsdp2.md +15 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_fsdp1_api.md +9 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_fsdp2_tutorial.md +45 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_fully_shard_api.md +49 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/pytorch_tp_tutorial.md +22 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/ray_train_fsdp2_example.md +13 -0
- package/skills/ai-research/08-distributed-training/pytorch-fsdp2/references/torchtitan_fsdp_notes.md +14 -0
- package/skills/ai-research/08-distributed-training/pytorch-lightning/SKILL.md +346 -0
- package/skills/ai-research/08-distributed-training/pytorch-lightning/references/callbacks.md +437 -0
- package/skills/ai-research/08-distributed-training/pytorch-lightning/references/distributed.md +491 -0
- package/skills/ai-research/08-distributed-training/pytorch-lightning/references/hyperparameter-tuning.md +557 -0
- package/skills/ai-research/08-distributed-training/ray-train/SKILL.md +406 -0
- package/skills/ai-research/08-distributed-training/ray-train/references/multi-node.md +629 -0
- package/skills/ai-research/09-infrastructure/lambda-labs/SKILL.md +545 -0
- package/skills/ai-research/09-infrastructure/lambda-labs/references/advanced-usage.md +612 -0
- package/skills/ai-research/09-infrastructure/lambda-labs/references/troubleshooting.md +531 -0
- package/skills/ai-research/09-infrastructure/modal/SKILL.md +341 -0
- package/skills/ai-research/09-infrastructure/modal/references/advanced-usage.md +504 -0
- package/skills/ai-research/09-infrastructure/modal/references/troubleshooting.md +495 -0
- package/skills/ai-research/09-infrastructure/skypilot/SKILL.md +509 -0
- package/skills/ai-research/09-infrastructure/skypilot/references/advanced-usage.md +492 -0
- package/skills/ai-research/09-infrastructure/skypilot/references/troubleshooting.md +571 -0
- package/skills/ai-research/10-optimization/awq/SKILL.md +310 -0
- package/skills/ai-research/10-optimization/awq/references/advanced-usage.md +325 -0
- package/skills/ai-research/10-optimization/awq/references/troubleshooting.md +345 -0
- package/skills/ai-research/10-optimization/bitsandbytes/SKILL.md +411 -0
- package/skills/ai-research/10-optimization/bitsandbytes/references/memory-optimization.md +522 -0
- package/skills/ai-research/10-optimization/bitsandbytes/references/qlora-training.md +522 -0
- package/skills/ai-research/10-optimization/bitsandbytes/references/quantization-formats.md +448 -0
- package/skills/ai-research/10-optimization/flash-attention/SKILL.md +367 -0
- package/skills/ai-research/10-optimization/flash-attention/references/benchmarks.md +216 -0
- package/skills/ai-research/10-optimization/flash-attention/references/transformers-integration.md +294 -0
- package/skills/ai-research/10-optimization/gguf/SKILL.md +427 -0
- package/skills/ai-research/10-optimization/gguf/references/advanced-usage.md +505 -0
- package/skills/ai-research/10-optimization/gguf/references/troubleshooting.md +443 -0
- package/skills/ai-research/10-optimization/gptq/SKILL.md +450 -0
- package/skills/ai-research/10-optimization/gptq/references/calibration.md +338 -0
- package/skills/ai-research/10-optimization/gptq/references/integration.md +130 -0
- package/skills/ai-research/10-optimization/gptq/references/troubleshooting.md +96 -0
- package/skills/ai-research/10-optimization/hqq/SKILL.md +445 -0
- package/skills/ai-research/10-optimization/hqq/references/advanced-usage.md +529 -0
- package/skills/ai-research/10-optimization/hqq/references/troubleshooting.md +504 -0
- package/skills/ai-research/10-optimization/ml-training-recipes/SKILL.md +319 -0
- package/skills/ai-research/10-optimization/ml-training-recipes/references/architecture.md +320 -0
- package/skills/ai-research/10-optimization/ml-training-recipes/references/biomedical.md +498 -0
- package/skills/ai-research/10-optimization/ml-training-recipes/references/domain-specific.md +626 -0
- package/skills/ai-research/10-optimization/ml-training-recipes/references/experiment-loop.md +129 -0
- package/skills/ai-research/10-optimization/ml-training-recipes/references/optimizers.md +330 -0
- package/skills/ai-research/10-optimization/ml-training-recipes/references/scaling-and-selection.md +428 -0
- package/skills/ai-research/11-evaluation/bigcode-evaluation-harness/SKILL.md +405 -0
- package/skills/ai-research/11-evaluation/bigcode-evaluation-harness/references/benchmarks.md +394 -0
- package/skills/ai-research/11-evaluation/bigcode-evaluation-harness/references/custom-tasks.md +425 -0
- package/skills/ai-research/11-evaluation/bigcode-evaluation-harness/references/issues.md +395 -0
- package/skills/ai-research/11-evaluation/lm-evaluation-harness/SKILL.md +490 -0
- package/skills/ai-research/11-evaluation/lm-evaluation-harness/references/api-evaluation.md +491 -0
- package/skills/ai-research/11-evaluation/lm-evaluation-harness/references/benchmark-guide.md +489 -0
- package/skills/ai-research/11-evaluation/lm-evaluation-harness/references/custom-tasks.md +603 -0
- package/skills/ai-research/11-evaluation/lm-evaluation-harness/references/distributed-eval.md +520 -0
- package/skills/ai-research/11-evaluation/nemo-evaluator/SKILL.md +494 -0
- package/skills/ai-research/11-evaluation/nemo-evaluator/references/adapter-system.md +341 -0
- package/skills/ai-research/11-evaluation/nemo-evaluator/references/configuration.md +448 -0
- package/skills/ai-research/11-evaluation/nemo-evaluator/references/custom-benchmarks.md +316 -0
- package/skills/ai-research/11-evaluation/nemo-evaluator/references/execution-backends.md +362 -0
- package/skills/ai-research/12-inference-serving/llama-cpp/SKILL.md +258 -0
- package/skills/ai-research/12-inference-serving/llama-cpp/references/optimization.md +90 -0
- package/skills/ai-research/12-inference-serving/llama-cpp/references/quantization.md +214 -0
- package/skills/ai-research/12-inference-serving/llama-cpp/references/server.md +126 -0
- package/skills/ai-research/12-inference-serving/sglang/SKILL.md +442 -0
- package/skills/ai-research/12-inference-serving/sglang/references/deployment.md +491 -0
- package/skills/ai-research/12-inference-serving/sglang/references/radix-attention.md +414 -0
- package/skills/ai-research/12-inference-serving/sglang/references/structured-generation.md +542 -0
- package/skills/ai-research/12-inference-serving/tensorrt-llm/SKILL.md +187 -0
- package/skills/ai-research/12-inference-serving/tensorrt-llm/references/multi-gpu.md +299 -0
- package/skills/ai-research/12-inference-serving/tensorrt-llm/references/optimization.md +243 -0
- package/skills/ai-research/12-inference-serving/tensorrt-llm/references/serving.md +471 -0
- package/skills/ai-research/12-inference-serving/vllm/SKILL.md +364 -0
- package/skills/ai-research/12-inference-serving/vllm/references/optimization.md +227 -0
- package/skills/ai-research/12-inference-serving/vllm/references/quantization.md +285 -0
- package/skills/ai-research/12-inference-serving/vllm/references/server-deployment.md +256 -0
- package/skills/ai-research/12-inference-serving/vllm/references/troubleshooting.md +448 -0
- package/skills/ai-research/13-mlops/mlflow/SKILL.md +704 -0
- package/skills/ai-research/13-mlops/mlflow/references/deployment.md +745 -0
- package/skills/ai-research/13-mlops/mlflow/references/model-registry.md +771 -0
- package/skills/ai-research/13-mlops/mlflow/references/tracking.md +681 -0
- package/skills/ai-research/13-mlops/swanlab/SKILL.md +406 -0
- package/skills/ai-research/13-mlops/swanlab/references/integrations.md +305 -0
- package/skills/ai-research/13-mlops/swanlab/references/visualization.md +234 -0
- package/skills/ai-research/13-mlops/tensorboard/SKILL.md +629 -0
- package/skills/ai-research/13-mlops/tensorboard/references/integrations.md +639 -0
- package/skills/ai-research/13-mlops/tensorboard/references/profiling.md +546 -0
- package/skills/ai-research/13-mlops/tensorboard/references/visualization.md +621 -0
- package/skills/ai-research/13-mlops/weights-and-biases/SKILL.md +590 -0
- package/skills/ai-research/13-mlops/weights-and-biases/references/artifacts.md +585 -0
- package/skills/ai-research/13-mlops/weights-and-biases/references/integrations.md +701 -0
- package/skills/ai-research/13-mlops/weights-and-biases/references/sweeps.md +848 -0
- package/skills/ai-research/14-agents/a-evolve/SKILL.md +383 -0
- package/skills/ai-research/14-agents/a-evolve/references/README.md +831 -0
- package/skills/ai-research/14-agents/a-evolve/references/api.md +594 -0
- package/skills/ai-research/14-agents/a-evolve/references/architecture.md +417 -0
- package/skills/ai-research/14-agents/a-evolve/references/design-patterns.md +462 -0
- package/skills/ai-research/14-agents/a-evolve/references/examples.md +352 -0
- package/skills/ai-research/14-agents/a-evolve/references/issues.md +591 -0
- package/skills/ai-research/14-agents/a-evolve/references/releases.md +112 -0
- package/skills/ai-research/14-agents/a-evolve/references/tutorials.md +819 -0
- package/skills/ai-research/14-agents/autogpt/SKILL.md +403 -0
- package/skills/ai-research/14-agents/autogpt/references/advanced-usage.md +536 -0
- package/skills/ai-research/14-agents/autogpt/references/troubleshooting.md +421 -0
- package/skills/ai-research/14-agents/crewai/SKILL.md +498 -0
- package/skills/ai-research/14-agents/crewai/references/flows.md +439 -0
- package/skills/ai-research/14-agents/crewai/references/tools.md +430 -0
- package/skills/ai-research/14-agents/crewai/references/troubleshooting.md +481 -0
- package/skills/ai-research/14-agents/langchain/SKILL.md +480 -0
- package/skills/ai-research/14-agents/langchain/references/agents.md +500 -0
- package/skills/ai-research/14-agents/langchain/references/integration.md +563 -0
- package/skills/ai-research/14-agents/langchain/references/rag.md +601 -0
- package/skills/ai-research/14-agents/llamaindex/SKILL.md +569 -0
- package/skills/ai-research/14-agents/llamaindex/references/agents.md +84 -0
- package/skills/ai-research/14-agents/llamaindex/references/data_connectors.md +109 -0
- package/skills/ai-research/14-agents/llamaindex/references/query_engines.md +407 -0
- package/skills/ai-research/15-rag/chroma/SKILL.md +406 -0
- package/skills/ai-research/15-rag/chroma/references/integration.md +39 -0
- package/skills/ai-research/15-rag/faiss/SKILL.md +221 -0
- package/skills/ai-research/15-rag/faiss/references/index_types.md +281 -0
- package/skills/ai-research/15-rag/pinecone/SKILL.md +358 -0
- package/skills/ai-research/15-rag/pinecone/references/deployment.md +182 -0
- package/skills/ai-research/15-rag/qdrant/SKILL.md +493 -0
- package/skills/ai-research/15-rag/qdrant/references/advanced-usage.md +649 -0
- package/skills/ai-research/15-rag/qdrant/references/troubleshooting.md +632 -0
- package/skills/ai-research/15-rag/sentence-transformers/SKILL.md +255 -0
- package/skills/ai-research/15-rag/sentence-transformers/references/models.md +124 -0
- package/skills/ai-research/16-prompt-engineering/dspy/SKILL.md +590 -0
- package/skills/ai-research/16-prompt-engineering/dspy/references/examples.md +664 -0
- package/skills/ai-research/16-prompt-engineering/dspy/references/modules.md +476 -0
- package/skills/ai-research/16-prompt-engineering/dspy/references/optimizers.md +567 -0
- package/skills/ai-research/16-prompt-engineering/guidance/SKILL.md +572 -0
- package/skills/ai-research/16-prompt-engineering/guidance/references/backends.md +555 -0
- package/skills/ai-research/16-prompt-engineering/guidance/references/constraints.md +675 -0
- package/skills/ai-research/16-prompt-engineering/guidance/references/examples.md +768 -0
- package/skills/ai-research/16-prompt-engineering/instructor/SKILL.md +740 -0
- package/skills/ai-research/16-prompt-engineering/instructor/references/examples.md +108 -0
- package/skills/ai-research/16-prompt-engineering/instructor/references/providers.md +71 -0
- package/skills/ai-research/16-prompt-engineering/instructor/references/validation.md +607 -0
- package/skills/ai-research/16-prompt-engineering/outlines/SKILL.md +652 -0
- package/skills/ai-research/16-prompt-engineering/outlines/references/backends.md +616 -0
- package/skills/ai-research/16-prompt-engineering/outlines/references/examples.md +774 -0
- package/skills/ai-research/16-prompt-engineering/outlines/references/json_generation.md +653 -0
- package/skills/ai-research/17-observability/langsmith/SKILL.md +422 -0
- package/skills/ai-research/17-observability/langsmith/references/advanced-usage.md +549 -0
- package/skills/ai-research/17-observability/langsmith/references/troubleshooting.md +538 -0
- package/skills/ai-research/17-observability/phoenix/SKILL.md +475 -0
- package/skills/ai-research/17-observability/phoenix/references/advanced-usage.md +620 -0
- package/skills/ai-research/17-observability/phoenix/references/troubleshooting.md +539 -0
- package/skills/ai-research/18-multimodal/audiocraft/SKILL.md +564 -0
- package/skills/ai-research/18-multimodal/audiocraft/references/advanced-usage.md +667 -0
- package/skills/ai-research/18-multimodal/audiocraft/references/troubleshooting.md +505 -0
- package/skills/ai-research/18-multimodal/blip-2/SKILL.md +564 -0
- package/skills/ai-research/18-multimodal/blip-2/references/advanced-usage.md +681 -0
- package/skills/ai-research/18-multimodal/blip-2/references/troubleshooting.md +527 -0
- package/skills/ai-research/18-multimodal/clip/SKILL.md +253 -0
- package/skills/ai-research/18-multimodal/clip/references/applications.md +208 -0
- package/skills/ai-research/18-multimodal/cosmos-policy/SKILL.md +402 -0
- package/skills/ai-research/18-multimodal/cosmos-policy/references/libero-commands.md +175 -0
- package/skills/ai-research/18-multimodal/cosmos-policy/references/robocasa-commands.md +147 -0
- package/skills/ai-research/18-multimodal/llava/SKILL.md +304 -0
- package/skills/ai-research/18-multimodal/llava/references/training.md +198 -0
- package/skills/ai-research/18-multimodal/openpi/SKILL.md +480 -0
- package/skills/ai-research/18-multimodal/openpi/references/checkpoints-and-env-map.md +86 -0
- package/skills/ai-research/18-multimodal/openpi/references/config-recipes.md +50 -0
- package/skills/ai-research/18-multimodal/openpi/references/pytorch-gotchas.md +49 -0
- package/skills/ai-research/18-multimodal/openpi/references/remote-client-pattern.md +48 -0
- package/skills/ai-research/18-multimodal/openpi/references/training-debugging.md +46 -0
- package/skills/ai-research/18-multimodal/openvla-oft/SKILL.md +441 -0
- package/skills/ai-research/18-multimodal/openvla-oft/references/aloha-workflow.md +141 -0
- package/skills/ai-research/18-multimodal/openvla-oft/references/config-troubleshooting.md +97 -0
- package/skills/ai-research/18-multimodal/openvla-oft/references/libero-workflow.md +115 -0
- package/skills/ai-research/18-multimodal/openvla-oft/references/paper-and-checkpoints.md +84 -0
- package/skills/ai-research/18-multimodal/segment-anything/SKILL.md +500 -0
- package/skills/ai-research/18-multimodal/segment-anything/references/advanced-usage.md +590 -0
- package/skills/ai-research/18-multimodal/segment-anything/references/troubleshooting.md +485 -0
- package/skills/ai-research/18-multimodal/stable-diffusion/SKILL.md +519 -0
- package/skills/ai-research/18-multimodal/stable-diffusion/references/advanced-usage.md +717 -0
- package/skills/ai-research/18-multimodal/stable-diffusion/references/troubleshooting.md +556 -0
- package/skills/ai-research/18-multimodal/whisper/SKILL.md +317 -0
- package/skills/ai-research/18-multimodal/whisper/references/languages.md +190 -0
- package/skills/ai-research/19-emerging-techniques/knowledge-distillation/SKILL.md +458 -0
- package/skills/ai-research/19-emerging-techniques/knowledge-distillation/references/minillm.md +335 -0
- package/skills/ai-research/19-emerging-techniques/long-context/SKILL.md +536 -0
- package/skills/ai-research/19-emerging-techniques/long-context/references/extension_methods.md +469 -0
- package/skills/ai-research/19-emerging-techniques/long-context/references/fine_tuning.md +612 -0
- package/skills/ai-research/19-emerging-techniques/long-context/references/rope.md +403 -0
- package/skills/ai-research/19-emerging-techniques/model-merging/SKILL.md +497 -0
- package/skills/ai-research/19-emerging-techniques/model-merging/references/coefficient-tuning.md +415 -0
- package/skills/ai-research/19-emerging-techniques/model-merging/references/evaluation.md +463 -0
- package/skills/ai-research/19-emerging-techniques/model-merging/references/examples.md +429 -0
- package/skills/ai-research/19-emerging-techniques/model-merging/references/methods.md +353 -0
- package/skills/ai-research/19-emerging-techniques/model-pruning/SKILL.md +495 -0
- package/skills/ai-research/19-emerging-techniques/model-pruning/references/wanda.md +348 -0
- package/skills/ai-research/19-emerging-techniques/moe-training/SKILL.md +526 -0
- package/skills/ai-research/19-emerging-techniques/moe-training/references/architectures.md +433 -0
- package/skills/ai-research/19-emerging-techniques/moe-training/references/inference.md +349 -0
- package/skills/ai-research/19-emerging-techniques/moe-training/references/training.md +426 -0
- package/skills/ai-research/19-emerging-techniques/speculative-decoding/SKILL.md +467 -0
- package/skills/ai-research/19-emerging-techniques/speculative-decoding/references/lookahead.md +310 -0
- package/skills/ai-research/19-emerging-techniques/speculative-decoding/references/medusa.md +351 -0
- package/skills/ai-research/20-ml-paper-writing/academic-plotting/SKILL.md +479 -0
- package/skills/ai-research/20-ml-paper-writing/academic-plotting/references/data-visualization.md +509 -0
- package/skills/ai-research/20-ml-paper-writing/academic-plotting/references/diagram-generation.md +395 -0
- package/skills/ai-research/20-ml-paper-writing/academic-plotting/references/style-guide.md +305 -0
- package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/SKILL.md +982 -0
- package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/references/checklists.md +348 -0
- package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/references/citation-workflow.md +563 -0
- package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/references/reviewer-guidelines.md +349 -0
- package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/references/sources.md +165 -0
- package/skills/ai-research/20-ml-paper-writing/ml-paper-writing/references/writing-guide.md +477 -0
- package/skills/ai-research/20-ml-paper-writing/presenting-conference-talks/SKILL.md +298 -0
- package/skills/ai-research/20-ml-paper-writing/presenting-conference-talks/references/slide-templates.md +505 -0
- package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/SKILL.md +270 -0
- package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/references/checklist.md +279 -0
- package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/references/reviewer-guidelines.md +116 -0
- package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/references/section-blueprints.md +400 -0
- package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/references/systems-conferences.md +261 -0
- package/skills/ai-research/20-ml-paper-writing/systems-paper-writing/references/writing-patterns.md +231 -0
- package/skills/ai-research/21-research-ideation/brainstorming-research-ideas/SKILL.md +384 -0
- package/skills/ai-research/21-research-ideation/creative-thinking-for-research/SKILL.md +366 -0
- package/skills/ai-research/22-agent-native-research-artifact/compiler/SKILL.md +245 -0
- package/skills/ai-research/22-agent-native-research-artifact/compiler/references/ara-schema.md +439 -0
- package/skills/ai-research/22-agent-native-research-artifact/compiler/references/exploration-tree-spec.md +125 -0
- package/skills/ai-research/22-agent-native-research-artifact/compiler/references/validation-checklist.md +149 -0
- package/skills/ai-research/22-agent-native-research-artifact/research-manager/SKILL.md +324 -0
- package/skills/ai-research/22-agent-native-research-artifact/research-manager/references/event-taxonomy.md +124 -0
- package/skills/ai-research/22-agent-native-research-artifact/research-manager/references/provenance-tags.md +190 -0
- package/skills/ai-research/22-agent-native-research-artifact/research-manager/references/session-protocol.md +162 -0
- package/skills/ai-research/22-agent-native-research-artifact/rigor-reviewer/SKILL.md +322 -0
- package/skills/ai-research/22-agent-native-research-artifact/rigor-reviewer/references/review-dimensions.md +182 -0
- package/skills/ai-research/SKILL.md +101 -0
- package/skills/ai-research/SOURCE +38 -0
- package/skills/ai-research/index/1-frame.md +18 -0
- package/skills/ai-research/index/2-data.md +21 -0
- package/skills/ai-research/index/3-train.md +48 -0
- package/skills/ai-research/index/4-measure.md +25 -0
- package/skills/ai-research/index/5-run.md +23 -0
- package/skills/ai-research/index/6-write.md +35 -0
- package/skills/ai-research/library.json +3456 -0
- package/skills/analyze-app/EVALS.md +82 -0
- package/skills/analyze-app/SKILL.md +188 -0
- package/skills/design-contract/EVALS.md +80 -0
- package/skills/design-contract/SKILL.md +171 -0
- package/skills/design-library/EVALS.md +85 -0
- package/skills/design-library/INDEX.md +59 -0
- package/skills/design-library/SKILL.md +58 -0
- package/skills/design-library/SOURCE +131 -0
- package/skills/design-library/adaptive-interfaces/skills/colour-independence/SKILL.md +90 -0
- package/skills/design-library/adaptive-interfaces/skills/flexible-typography/SKILL.md +83 -0
- package/skills/design-library/adaptive-interfaces/skills/information-density/SKILL.md +87 -0
- package/skills/design-library/adaptive-interfaces/skills/preference-audit/SKILL.md +70 -0
- package/skills/design-library/adaptive-interfaces/skills/responsive-accessibility/SKILL.md +86 -0
- package/skills/design-library/adaptive-interfaces/skills/responsive-review/SKILL.md +76 -0
- package/skills/design-library/adaptive-interfaces/skills/simplified-views/SKILL.md +97 -0
- package/skills/design-library/adaptive-interfaces/skills/specify/SKILL.md +63 -0
- package/skills/design-library/adaptive-interfaces/skills/user-preference-respect/SKILL.md +100 -0
- package/skills/design-library/cognitive-accessibility/skills/adaptive-personalisation/SKILL.md +61 -0
- package/skills/design-library/cognitive-accessibility/skills/assess-load/SKILL.md +48 -0
- package/skills/design-library/cognitive-accessibility/skills/cognitive-load-assessment/SKILL.md +60 -0
- package/skills/design-library/cognitive-accessibility/skills/contextual-help-design/SKILL.md +61 -0
- package/skills/design-library/cognitive-accessibility/skills/error-prevention-recovery/SKILL.md +71 -0
- package/skills/design-library/cognitive-accessibility/skills/focus-attention-design/SKILL.md +67 -0
- package/skills/design-library/cognitive-accessibility/skills/memory-load-reduction/SKILL.md +60 -0
- package/skills/design-library/cognitive-accessibility/skills/plain-language-design/SKILL.md +78 -0
- package/skills/design-library/cognitive-accessibility/skills/review/SKILL.md +56 -0
- package/skills/design-library/cognitive-accessibility/skills/simplify/SKILL.md +39 -0
- package/skills/design-library/cognitive-accessibility/skills/wayfinding-navigation/SKILL.md +64 -0
- package/skills/design-library/design-research/skills/behavioural-analytics/SKILL.md +33 -0
- package/skills/design-library/design-research/skills/qual-quant-triangulation/SKILL.md +33 -0
- package/skills/design-library/inclusive-interaction/skills/audit/SKILL.md +50 -0
- package/skills/design-library/inclusive-interaction/skills/design-flow/SKILL.md +58 -0
- package/skills/design-library/inclusive-interaction/skills/feedback-and-status/SKILL.md +76 -0
- package/skills/design-library/inclusive-interaction/skills/gesture-alternatives/SKILL.md +70 -0
- package/skills/design-library/inclusive-interaction/skills/keyboard-navigation/SKILL.md +99 -0
- package/skills/design-library/inclusive-interaction/skills/keyboard-review/SKILL.md +54 -0
- package/skills/design-library/inclusive-interaction/skills/motion-sensitivity/SKILL.md +79 -0
- package/skills/design-library/inclusive-interaction/skills/multi-modal-input/SKILL.md +70 -0
- package/skills/design-library/inclusive-interaction/skills/touch-target-design/SKILL.md +71 -0
- package/skills/design-library/inclusive-interaction/skills/voice-interaction/SKILL.md +68 -0
- package/skills/design-library/visual-critique/skills/critique-affordance/SKILL.md +45 -0
- package/skills/design-library/visual-critique/skills/critique-brand-consistency/SKILL.md +42 -0
- package/skills/design-library/visual-critique/skills/critique-color/SKILL.md +44 -0
- package/skills/design-library/visual-critique/skills/critique-composition/SKILL.md +46 -0
- package/skills/design-library/visual-critique/skills/critique-information-density/SKILL.md +45 -0
- package/skills/design-library/visual-critique/skills/critique-typography/SKILL.md +45 -0
- package/skills/design-library/visual-critique/skills/critique-visual-hierarchy/SKILL.md +40 -0
- package/skills/feature-audit/EVALS.md +83 -0
- package/skills/feature-audit/SKILL.md +326 -0
- package/skills/harness/EVALS.md +81 -0
- package/skills/harness/SKILL.md +88 -0
- package/skills/i-have-adhd/EVALS.md +80 -0
- package/skills/i-have-adhd/SKILL.md +183 -0
- package/skills/no-ai-slop/EVALS.md +89 -0
- package/skills/no-ai-slop/SKILL.md +209 -0
- package/skills/no-ai-slop/eval.md +52 -0
- package/skills/plan-add/EVALS.md +79 -0
- package/skills/plan-add/SKILL.md +179 -0
- package/skills/plan-add/render_table.py +72 -0
- package/skills/plan-status/EVALS.md +78 -0
- package/skills/plan-status/SKILL.md +52 -0
- package/skills/plan-sync/EVALS.md +80 -0
- package/skills/plan-sync/SKILL.md +69 -0
- package/skills/pm-frameworks/SKILL.md +33 -0
- package/skills/pm-frameworks/SOURCE +39 -0
- package/skills/pm-frameworks/intended-vs-implemented/SKILL.md +42 -0
- package/skills/pm-frameworks/opportunity-solution-tree/SKILL.md +64 -0
- package/skills/ponytail/EVALS.md +80 -0
- package/skills/ponytail/SKILL.md +124 -0
- package/skills/product-analysis/EVALS.md +103 -0
- package/skills/product-analysis/SKILL.md +361 -0
- package/skills/research/EVALS.md +104 -0
- package/skills/research/SKILL.md +570 -0
- package/skills/rl-env/SKILL.md +53 -0
- package/skills/rl-env/SOURCE +41 -0
- package/skills/rl-env/generate-nemo-gym-env/SKILL.md +169 -0
- package/skills/rl-env/generate-nemo-gym-env/references/architecture.md +114 -0
- package/skills/rl-env/generate-openenv-env/SKILL.md +183 -0
- package/skills/rl-env/generate-openenv-env/references/architecture.md +82 -0
- package/skills/rl-env/generate-ors-env/SKILL.md +209 -0
- package/skills/rl-env/generate-ors-env/references/architecture.md +113 -0
- package/skills/rl-env/generate-verifiers-env/SKILL.md +188 -0
- package/skills/rl-env/generate-verifiers-env/references/architecture.md +119 -0
- package/skills/rl-env/rl-env-from-description/SKILL.md +124 -0
- package/skills/rl-env/rl-env-from-description/references/interview.md +75 -0
- package/skills/rl-env/rl-env-from-description/references/nemo_gym.md +41 -0
- package/skills/rl-env/rl-env-from-description/references/openenv.md +35 -0
- package/skills/rl-env/rl-env-from-description/references/ors.md +50 -0
- package/skills/rl-env/rl-env-from-description/references/verifiers.md +39 -0
- package/skills/tezgah-contract/EVALS.md +78 -0
- package/skills/tezgah-contract/SKILL.md +792 -0
- package/statusline.py +129 -0
- package/workflows/graph-impact.js +153 -0
- package/workflows/graph-map.js +158 -0
- package/workflows/graph-review.js +170 -0
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""The active task: one plan file's phase and its path allowlist.
|
|
3
|
+
|
|
4
|
+
A task is not a second record beside the plan - it IS the plan file under
|
|
5
|
+
`.tezgah/plans/open/`, with two optional frontmatter keys that the user's own CLI
|
|
6
|
+
(bin/tezgah-task) writes and no agent ever does:
|
|
7
|
+
|
|
8
|
+
phase: implementation # discovery | implementation | verification
|
|
9
|
+
allowed_paths: # globs, relative to the repo root
|
|
10
|
+
- hooks/**
|
|
11
|
+
|
|
12
|
+
`phase` is the activation key: the first open plan carrying a valid one is the
|
|
13
|
+
active task, and `allowed_paths` is read only then. A plan whose phase is not
|
|
14
|
+
one of the three is ignored by every reader rather than refused - a reader that
|
|
15
|
+
failed closed on a typo would block work the user never restricted, while the
|
|
16
|
+
absence of a task must never be read as a requirement.
|
|
17
|
+
|
|
18
|
+
The gate, the per-turn context line and the opencode plugin's path to both read
|
|
19
|
+
the record from here (through bin/tezgah-gate), so the phase that stops a write
|
|
20
|
+
before it happens is decided once. This module is on the gate's hot path for
|
|
21
|
+
every write, so it imports nothing from tezgah_context and shells out to
|
|
22
|
+
nothing.
|
|
23
|
+
|
|
24
|
+
A plan's body is read here too, and only here: the acceptance report
|
|
25
|
+
(`tezgah-render-table --acceptance`) counts the items that name no command, so
|
|
26
|
+
the record the gate reads and the items the report counts have one reader. Two
|
|
27
|
+
readers of the body were added beside it and read in the same place - the
|
|
28
|
+
`## Acceptance` items a plan cannot enter a writing phase without
|
|
29
|
+
(`acceptance_gap`), and the spike a plan declares and has not answered
|
|
30
|
+
(`spike_unanswered`) - for the same reason: the CLI refuses the phase move and
|
|
31
|
+
the CI report counts the same items, and one module keeps them agreeing.
|
|
32
|
+
|
|
33
|
+
The `checkpoint:` key is read here for the same reason again: bin/tezgah-task
|
|
34
|
+
writes it when the phase moves to `implementation` - the pre-work commit's sha
|
|
35
|
+
when the tree was clean, or `pending <sha>` when it was not, `<sha>` being the
|
|
36
|
+
`HEAD` the commit the phase waits for has to move off (`checkpoint_sha`, the one
|
|
37
|
+
reader of that form). The gate refuses a write in that phase only while the
|
|
38
|
+
recorded sha is still HEAD and the tree is still dirty, so the commit its refusal
|
|
39
|
+
names clears it by itself.
|
|
40
|
+
"""
|
|
41
|
+
import os
|
|
42
|
+
import re
|
|
43
|
+
|
|
44
|
+
TASK_PHASES = ("discovery", "implementation", "verification")
|
|
45
|
+
WRITE_PHASES = ("implementation", "verification")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def repo_root(cwd, base):
|
|
49
|
+
"""The git top-level at or above cwd and under base, else the first path
|
|
50
|
+
component below base. Walks up for a `.git` entry (dir or file: a worktree's
|
|
51
|
+
is a file); no subprocess. Same answer as tezgah_context.repo_root without
|
|
52
|
+
importing the context module into the gate's hot path."""
|
|
53
|
+
cwd = os.path.realpath(cwd)
|
|
54
|
+
inside = os.path.realpath(base) if base else None
|
|
55
|
+
cur = cwd
|
|
56
|
+
while True:
|
|
57
|
+
if os.path.exists(os.path.join(cur, ".git")):
|
|
58
|
+
if inside and _under(cur, inside):
|
|
59
|
+
return cur
|
|
60
|
+
break
|
|
61
|
+
parent = os.path.dirname(cur)
|
|
62
|
+
if parent == cur:
|
|
63
|
+
break
|
|
64
|
+
cur = parent
|
|
65
|
+
if not inside:
|
|
66
|
+
return cwd
|
|
67
|
+
first = os.path.relpath(cwd, inside).split(os.sep)[0]
|
|
68
|
+
if first in (".", "..", ""):
|
|
69
|
+
return cwd
|
|
70
|
+
return os.path.join(inside, first)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _under(path, base):
|
|
74
|
+
return path == base or path.startswith(base + os.sep)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _frontmatter_lines(text):
|
|
78
|
+
"""The lines between the first two `---` lines, [] when the file has none.
|
|
79
|
+
An unclosed block is not frontmatter: the markers are its boundary, and half
|
|
80
|
+
of one leaves every `key: value` line in the body's hands."""
|
|
81
|
+
lines = text.splitlines()
|
|
82
|
+
if not lines or lines[0].strip() != "---":
|
|
83
|
+
return []
|
|
84
|
+
for i in range(1, len(lines)):
|
|
85
|
+
if lines[i].strip() == "---":
|
|
86
|
+
return lines[1:i]
|
|
87
|
+
return []
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def frontmatter(text):
|
|
91
|
+
"""The plan file's frontmatter as a dict of str -> str (the text between the
|
|
92
|
+
first two `---` lines, `key: value` lines only). {} when there is none."""
|
|
93
|
+
out = {}
|
|
94
|
+
for line in _frontmatter_lines(text):
|
|
95
|
+
if line.lstrip().startswith("- "):
|
|
96
|
+
continue
|
|
97
|
+
key, sep, value = line.partition(":")
|
|
98
|
+
if sep and key.strip():
|
|
99
|
+
out[key.strip()] = value.strip()
|
|
100
|
+
return out
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def allowed_paths(text):
|
|
104
|
+
"""The `allowed_paths:` list as a list of globs, [] when absent."""
|
|
105
|
+
out = []
|
|
106
|
+
collecting = False
|
|
107
|
+
for line in _frontmatter_lines(text):
|
|
108
|
+
stripped = line.strip()
|
|
109
|
+
if collecting and stripped.startswith("- "):
|
|
110
|
+
out.append(stripped[2:].strip())
|
|
111
|
+
continue
|
|
112
|
+
collecting = (not stripped.startswith("- ") and ":" in stripped
|
|
113
|
+
and stripped.partition(":")[0].strip() == "allowed_paths")
|
|
114
|
+
return out
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def section_lines(text, heading):
|
|
118
|
+
"""The lines of one `## <heading>` section with their 1-based numbers, []
|
|
119
|
+
when the file has no such heading: the lines after the heading up to the next
|
|
120
|
+
`## ` line. A heading is a whole line, so `## Acceptance` and
|
|
121
|
+
`## Acceptance criteria` are two different sections."""
|
|
122
|
+
out = []
|
|
123
|
+
inside = False
|
|
124
|
+
for number, line in enumerate(text.split("\n"), 1):
|
|
125
|
+
if line.lstrip().startswith("## "):
|
|
126
|
+
inside = line.strip() == "## " + heading
|
|
127
|
+
elif inside:
|
|
128
|
+
out.append((number, line))
|
|
129
|
+
return out
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
_ITEM = re.compile(r"^\s*- \[[ xX]\]\s*(.*)$")
|
|
133
|
+
# The word `unverifiable`, as a word: the lookahead is a boundary a hyphen and a
|
|
134
|
+
# letter both fail, so `unverifiable-ness` is not a marker.
|
|
135
|
+
_MARKER = re.compile(r"unverifiable(?![-\w])", re.I)
|
|
136
|
+
# What a declaration puts between the marker and its why. An item that merely
|
|
137
|
+
# names the word ("either the command or the word `unverifiable` followed by
|
|
138
|
+
# why") has no separator there and is not a declaration.
|
|
139
|
+
_SEPARATORS = ":,;(-"
|
|
140
|
+
_SPAN = re.compile(r"`([^`\n]+)`")
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _argument(token):
|
|
144
|
+
"""One token only a command carries: an option (`--citations`), a path
|
|
145
|
+
(`bin/tezgah-docs`, `hooks/x.py`), the current directory (`.`, `..`) or a
|
|
146
|
+
script (`run.sh`). A bare word is not one, so a backticked phrase is not read
|
|
147
|
+
as a command. `.` counts because it is a path like any other and is what the
|
|
148
|
+
commonest lint invocation ends in (`ruff check .`) - read as a bare word, the
|
|
149
|
+
item that names it was reported as naming no command at all."""
|
|
150
|
+
if len(token) > 1 and token.startswith("-"):
|
|
151
|
+
return True
|
|
152
|
+
if token in (".", ".."):
|
|
153
|
+
return True
|
|
154
|
+
if token.endswith((".py", ".sh", ".js", ".bash")):
|
|
155
|
+
return True
|
|
156
|
+
_, _, tail = token.partition("/")
|
|
157
|
+
return bool(tail) and any(char.isalnum() for char in tail)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def names_command(text):
|
|
161
|
+
"""Does this acceptance item name the command that proves it? A command is a
|
|
162
|
+
backticked run of two or more words carrying an option, a path or a script:
|
|
163
|
+
`bin/tezgah-docs --citations`, `python3 -m unittest tests/test_task.py`. A
|
|
164
|
+
citation (`hooks/tezgah_task.py`, `plan:line`) is not one, and an invocation
|
|
165
|
+
with no argument at all is not recognised either - both are reported, which
|
|
166
|
+
is the safe direction for a report a person reads."""
|
|
167
|
+
for span in _SPAN.findall(text):
|
|
168
|
+
tokens = span.split()
|
|
169
|
+
if len(tokens) > 1 and any(_argument(token) for token in tokens[1:]):
|
|
170
|
+
return True
|
|
171
|
+
return False
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def unverifiable_reason(text):
|
|
175
|
+
"""The why that follows the word `unverifiable`, or None when the item does
|
|
176
|
+
not declare itself unverifiable. Two shapes are declarations: the marker at
|
|
177
|
+
the item's start, and the marker followed by a why after a separator
|
|
178
|
+
(`unverifiable: no fixture exists`, `unverifiable - the file has none`). A
|
|
179
|
+
bare marker has no why, and a sentence that only names the word is not a
|
|
180
|
+
declaration of anything - both are the same gap the report is about."""
|
|
181
|
+
for found in _MARKER.finditer(text):
|
|
182
|
+
head = text[:found.start()].strip(" `")
|
|
183
|
+
tail = text[found.end():].lstrip(" `")
|
|
184
|
+
if head and tail[:1] not in _SEPARATORS:
|
|
185
|
+
continue
|
|
186
|
+
reason = tail.lstrip(_SEPARATORS + " ").strip()
|
|
187
|
+
if reason:
|
|
188
|
+
return reason
|
|
189
|
+
return None
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def acceptance_items(text):
|
|
193
|
+
"""One plan file's `## Acceptance` items: a list of
|
|
194
|
+
{"line", "text", "state"}, plus "reason" when the state is "unverifiable".
|
|
195
|
+
One field and not two - "checkable" (the item names a command),
|
|
196
|
+
"unverifiable" (it says so and why) or "missing" (neither) - so no caller can
|
|
197
|
+
read two answers about one item.
|
|
198
|
+
|
|
199
|
+
An item is one `- [ ]`/`- [x]` line plus the lines it wraps onto, up to the
|
|
200
|
+
next item or a blank line: the format wraps at 79 columns, so an item is more
|
|
201
|
+
than one line in most plans and a reader that counted lines would point at
|
|
202
|
+
the wrong one."""
|
|
203
|
+
out = []
|
|
204
|
+
for number, line in section_lines(text, "Acceptance"):
|
|
205
|
+
found = _ITEM.match(line)
|
|
206
|
+
if found:
|
|
207
|
+
out.append({"line": number, "text": " ".join(found.group(1).split()),
|
|
208
|
+
"state": "missing"})
|
|
209
|
+
elif out and line.strip():
|
|
210
|
+
out[-1]["text"] = " ".join((out[-1]["text"] + " " + line).split())
|
|
211
|
+
for item in out:
|
|
212
|
+
reason = unverifiable_reason(item["text"])
|
|
213
|
+
if reason is not None:
|
|
214
|
+
item["state"], item["reason"] = "unverifiable", reason
|
|
215
|
+
elif names_command(item["text"]):
|
|
216
|
+
item["state"] = "checkable"
|
|
217
|
+
return out
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def acceptance_gap(text):
|
|
221
|
+
"""The plan's Acceptance items when nothing in them can check the work: every
|
|
222
|
+
item the section carries is `missing`, so none names a command and none
|
|
223
|
+
declares itself `unverifiable`. [] otherwise, and [] when the plan has no
|
|
224
|
+
Acceptance items at all.
|
|
225
|
+
|
|
226
|
+
A plan with an empty or absent section is a different defect - the format asks
|
|
227
|
+
plan-add to write the items, and the render_table report does not gate that
|
|
228
|
+
case either - so refusing it here would tax every plan that predates the rule
|
|
229
|
+
while the two readers still agreed about every item either of them can see.
|
|
230
|
+
Returns the items so a refusal can count them."""
|
|
231
|
+
items = acceptance_items(text)
|
|
232
|
+
return items if items and all(item["state"] == "missing" for item in items) else []
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
# The `checkpoint:` values a plan can carry: a commit sha (the tree was clean at
|
|
236
|
+
# the phase move, so the boundary is already real), or `pending <sha>` while the
|
|
237
|
+
# tree still holds work no commit names - `<sha>` being the `HEAD` the commit the
|
|
238
|
+
# gate's refusal names has to move off. The CLI writes both, the gate reads both.
|
|
239
|
+
CHECKPOINT_PENDING = "pending"
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def checkpoint(text):
|
|
243
|
+
"""The plan's `checkpoint:` value: the pre-work commit the phase's work
|
|
244
|
+
branches from, `pending <sha>` while that work is uncommitted, or None when
|
|
245
|
+
the plan carries no such field - a phase started before the field existed,
|
|
246
|
+
which no rule holds to it."""
|
|
247
|
+
return frontmatter(text).get("checkpoint")
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def checkpoint_sha(value):
|
|
251
|
+
"""The `HEAD` a `pending` checkpoint has to move off, or "" when the value
|
|
252
|
+
names no tree to compare: a plain sha (the boundary is already real), a bare
|
|
253
|
+
`pending` (a record written before the sha was recorded, or a branch with no
|
|
254
|
+
commit to name at all), None, or any other shape. The gate fails open on ""
|
|
255
|
+
because it cannot tell whether the commit landed, and a refusal it cannot
|
|
256
|
+
answer would lock the very phase it guards - the defect this sha exists to
|
|
257
|
+
close."""
|
|
258
|
+
parts = str(value or "").split()
|
|
259
|
+
if len(parts) == 2 and parts[0] == CHECKPOINT_PENDING:
|
|
260
|
+
return parts[1]
|
|
261
|
+
return ""
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def slug(path):
|
|
265
|
+
"""A plan file's slug: its name without `.md` (`001-add-login`), which
|
|
266
|
+
is the branch's own tail (`plan/NNN-slug`) and what a checkpoint commit names.
|
|
267
|
+
Built here so the CLI's note and the gate's refusal cannot spell it two
|
|
268
|
+
ways."""
|
|
269
|
+
name = os.path.basename(path)
|
|
270
|
+
return name[:-3] if name.endswith(".md") else name
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def checkpoint_command(path):
|
|
274
|
+
"""The one command that makes a plan's boundary real: a commit whose message
|
|
275
|
+
marks where the risky work starts. Named by the CLI's note and by the gate's
|
|
276
|
+
refusal - the same string, from the same caller-visible place - and running it
|
|
277
|
+
is also what clears the refusal: it moves HEAD off the sha the record wrote
|
|
278
|
+
(`checkpoint_sha`)."""
|
|
279
|
+
return 'git add -A && git commit -m "checkpoint: before %s"' % slug(path)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def spike_unanswered(text):
|
|
283
|
+
"""True when the plan runs a spike (`spike:` names its one question) that has
|
|
284
|
+
not answered yet (`spike_recorded:` names nothing), else False.
|
|
285
|
+
|
|
286
|
+
The four keys are optional and their absence invents nothing: no `spike:`
|
|
287
|
+
question means no spike, which is how a plan that predates the field is never
|
|
288
|
+
held to it - the fail-open direction every reader here takes. `spike_box:` is
|
|
289
|
+
the time box and `spike_throwaway:` the throwaway contract; nothing reads
|
|
290
|
+
either, because the throwaway half is already enforceable through
|
|
291
|
+
`allowed_paths` (a spike pins its allowlist to a scratch path that is never
|
|
292
|
+
merged) and a second mechanism for one rule is the copy that drifts."""
|
|
293
|
+
fields = frontmatter(text)
|
|
294
|
+
return bool(fields.get("spike")) and not fields.get("spike_recorded")
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
ACCEPTANCE_DIRS = ("open", "done")
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def acceptance_report(root):
|
|
301
|
+
"""Every acceptance item of every plan under `<root>/.tezgah/plans/open` and
|
|
302
|
+
`.tezgah/plans/done`: {"plans": how many plan files were read, "items": [item, ...]},
|
|
303
|
+
each item carrying acceptance_items()'s keys plus "plan" - its path relative
|
|
304
|
+
to root, so a row reads `plan:line` and a person can open it.
|
|
305
|
+
|
|
306
|
+
The counts are half the answer: a report that read nothing must not read as
|
|
307
|
+
"everything is checkable", so the caller prints them. Never raises - an
|
|
308
|
+
absent directory or an unreadable file is skipped, not refused: this feeds a
|
|
309
|
+
report, not a gate."""
|
|
310
|
+
items = []
|
|
311
|
+
plans = 0
|
|
312
|
+
for sub in ACCEPTANCE_DIRS:
|
|
313
|
+
directory = os.path.join(root, ".tezgah", "plans", sub)
|
|
314
|
+
try:
|
|
315
|
+
names = sorted(os.listdir(directory))
|
|
316
|
+
except OSError:
|
|
317
|
+
continue
|
|
318
|
+
for name in names:
|
|
319
|
+
if not name.endswith(".md"):
|
|
320
|
+
continue
|
|
321
|
+
path = os.path.join(directory, name)
|
|
322
|
+
try:
|
|
323
|
+
with open(path, "r", encoding="utf-8") as fh:
|
|
324
|
+
text = fh.read()
|
|
325
|
+
except OSError:
|
|
326
|
+
continue
|
|
327
|
+
plans += 1
|
|
328
|
+
for item in acceptance_items(text):
|
|
329
|
+
item["plan"] = ".tezgah/plans/%s/%s" % (sub, name)
|
|
330
|
+
items.append(item)
|
|
331
|
+
return {"plans": plans, "items": items}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def active(cwd, base):
|
|
335
|
+
"""The active task as a dict, or None. Scans `<repo_root>/.tezgah/plans/open/*.md`
|
|
336
|
+
sorted by name, first file whose frontmatter carries a valid `phase`.
|
|
337
|
+
Dict: {"id","title","phase","allowed_paths","checkpoint","path"}: id/title are
|
|
338
|
+
the frontmatter values (id falls back to the filename's NNN), checkpoint is
|
|
339
|
+
the frontmatter value or None when the plan carries none, path is the file.
|
|
340
|
+
Never raises: an unreadable directory or file means None (readers fail
|
|
341
|
+
open)."""
|
|
342
|
+
root = repo_root(cwd, base)
|
|
343
|
+
directory = os.path.join(root, ".tezgah", "plans", "open")
|
|
344
|
+
try:
|
|
345
|
+
names = sorted(os.listdir(directory))
|
|
346
|
+
except OSError:
|
|
347
|
+
return None
|
|
348
|
+
for name in names:
|
|
349
|
+
if not name.endswith(".md"):
|
|
350
|
+
continue
|
|
351
|
+
path = os.path.join(directory, name)
|
|
352
|
+
try:
|
|
353
|
+
with open(path, "r", encoding="utf-8") as fh:
|
|
354
|
+
text = fh.read()
|
|
355
|
+
except OSError:
|
|
356
|
+
return None
|
|
357
|
+
fields = frontmatter(text)
|
|
358
|
+
if fields.get("phase") not in TASK_PHASES:
|
|
359
|
+
continue
|
|
360
|
+
# A plan the repository shipped is data, not the user's task: its phase
|
|
361
|
+
# and allowlist would lock writes in a cloned repo (audit L-16). Only
|
|
362
|
+
# positive evidence turns the rule off - the index tracks `.tezgah` -
|
|
363
|
+
# never a can't-tell, which would switch the user's own guard off in
|
|
364
|
+
# silence (review R2); the answer is cached on the index's stat.
|
|
365
|
+
from tezgah_paths import workspace_tracked
|
|
366
|
+
if workspace_tracked(root):
|
|
367
|
+
return None
|
|
368
|
+
return {"id": fields.get("id") or name.split("-")[0],
|
|
369
|
+
"title": fields.get("title", ""),
|
|
370
|
+
"phase": fields["phase"],
|
|
371
|
+
"allowed_paths": allowed_paths(text),
|
|
372
|
+
# read from the frontmatter already in hand, so the gate's
|
|
373
|
+
# checkpoint rule costs this module no second read of the plan
|
|
374
|
+
"checkpoint": fields.get("checkpoint"),
|
|
375
|
+
"path": path}
|
|
376
|
+
return None
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def match(rel, pattern):
|
|
380
|
+
"""Glob match for one allowlist pattern against a repo-relative posix path.
|
|
381
|
+
`**` crosses separators, `*` does not, everything else is literal."""
|
|
382
|
+
out = []
|
|
383
|
+
i = 0
|
|
384
|
+
while i < len(pattern):
|
|
385
|
+
if pattern.startswith("**/", i):
|
|
386
|
+
# `**` glued to a `/` also stands for no directory at all, so
|
|
387
|
+
# `**/tests/**` covers a `tests/x.py` at the root as a reader expects
|
|
388
|
+
out.append("(?:.*/)?")
|
|
389
|
+
i += 3
|
|
390
|
+
elif pattern.startswith("**", i):
|
|
391
|
+
out.append(".*")
|
|
392
|
+
i += 2
|
|
393
|
+
elif pattern[i] == "*":
|
|
394
|
+
out.append("[^/]*")
|
|
395
|
+
i += 1
|
|
396
|
+
else:
|
|
397
|
+
out.append(re.escape(pattern[i]))
|
|
398
|
+
i += 1
|
|
399
|
+
return re.fullmatch("".join(out), rel) is not None
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def relative(path, cwd, base):
|
|
403
|
+
"""The realpath of `path` (absolute or relative to cwd) as a posix path
|
|
404
|
+
relative to repo_root(cwd, base), or None when it resolves outside that root
|
|
405
|
+
(so an outside write can never be inside the allowlist)."""
|
|
406
|
+
root = repo_root(cwd, base)
|
|
407
|
+
real = os.path.realpath(path if os.path.isabs(path) else os.path.join(cwd, path))
|
|
408
|
+
if real == root or not _under(real, root):
|
|
409
|
+
# the root itself is not a path inside the root: an allowlist is about
|
|
410
|
+
# files under it, so this is a None like any other, and every caller
|
|
411
|
+
# fails in the refusing direction
|
|
412
|
+
return None
|
|
413
|
+
return real[len(root) + 1:].replace(os.sep, "/")
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def set_fields(path, **fields):
|
|
417
|
+
"""Rewrite these frontmatter keys in the plan file in place: replace the
|
|
418
|
+
`key: value` line when present, insert it before the closing `---` when not.
|
|
419
|
+
`allowed_paths` takes a list and is written as a `- item` block, replacing an
|
|
420
|
+
existing block. `updated` is not special-cased here: the CLI passes today's
|
|
421
|
+
date under it, as it does for a research line's `created:`, so this module
|
|
422
|
+
needs no clock of its own. Raises OSError."""
|
|
423
|
+
with open(path, "r", encoding="utf-8") as fh:
|
|
424
|
+
lines = fh.read().split("\n")
|
|
425
|
+
if not lines or lines[0].strip() != "---":
|
|
426
|
+
lines = ["---", "---"] + lines
|
|
427
|
+
close = next((i for i in range(1, len(lines)) if lines[i].strip() == "---"), None)
|
|
428
|
+
if close is None:
|
|
429
|
+
lines.insert(1, "---")
|
|
430
|
+
close = 1
|
|
431
|
+
block = lines[1:close]
|
|
432
|
+
for key, value in fields.items():
|
|
433
|
+
fresh = _field_lines(key, value)
|
|
434
|
+
head = next((i for i, line in enumerate(block)
|
|
435
|
+
if not line.lstrip().startswith("- ")
|
|
436
|
+
and line.partition(":")[0].strip() == key), None)
|
|
437
|
+
if head is None:
|
|
438
|
+
block += fresh
|
|
439
|
+
continue
|
|
440
|
+
end = head + 1
|
|
441
|
+
while end < len(block) and block[end].lstrip().startswith("- "):
|
|
442
|
+
end += 1
|
|
443
|
+
block[head:end] = fresh
|
|
444
|
+
lines[1:close] = block
|
|
445
|
+
with open(path, "w", encoding="utf-8") as fh:
|
|
446
|
+
fh.write("\n".join(lines))
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def _field_lines(key, value):
|
|
450
|
+
"""The frontmatter lines for one key: a `- item` block for a list (the form
|
|
451
|
+
`allowed_paths` uses, indented so the block reads as one value), a bare
|
|
452
|
+
`key:` for an empty value - which is how a phase is cleared - else
|
|
453
|
+
`key: value`."""
|
|
454
|
+
if isinstance(value, (list, tuple)):
|
|
455
|
+
return [key + ":"] + [" - %s" % item for item in value]
|
|
456
|
+
if value is None or value == "":
|
|
457
|
+
return [key + ":"]
|
|
458
|
+
return ["%s: %s" % (key, value)]
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Taste signals: the user's prompts, the agent's edits and the bytes those
|
|
3
|
+
edits left behind, stored per repository so a later miner can read them.
|
|
4
|
+
|
|
5
|
+
Opt-in and off by default. A row is written only when the `taste-on` marker is
|
|
6
|
+
armed (`tezgah_paths.armed`), the repository carries no `.no-taste` mark, its
|
|
7
|
+
`.tezgah/` already exists and is the user's own (`workspace_from_repo`: a
|
|
8
|
+
workspace that came with the clone is data, and nothing of the user's is
|
|
9
|
+
written into it). The store is `<git root>/.tezgah/taste/signals.jsonl`, one
|
|
10
|
+
JSON object per line, owner-only.
|
|
11
|
+
|
|
12
|
+
Every public function is total: it never raises, makes no network call and
|
|
13
|
+
appends at most one row. They run on the prompt and PostToolUse hot paths, so
|
|
14
|
+
the switch is read before anything else is.
|
|
15
|
+
|
|
16
|
+
Nothing here is learned or fed back into a prompt; this is capture only.
|
|
17
|
+
"""
|
|
18
|
+
import datetime
|
|
19
|
+
import json
|
|
20
|
+
import os
|
|
21
|
+
|
|
22
|
+
import tezgah_integrity as ti
|
|
23
|
+
from tezgah_paths import _toplevel, armed, root_for, workspace_from_repo
|
|
24
|
+
|
|
25
|
+
ARM = "taste-on"
|
|
26
|
+
MARK = ".no-taste"
|
|
27
|
+
VERSION = 1
|
|
28
|
+
PROMPT_MAX = 2000
|
|
29
|
+
EDIT_MAX = 4000
|
|
30
|
+
# The input fields a write carries its old and new text in, per host dialect -
|
|
31
|
+
# the same names tezgah_gate.EDIT_TEXT and `shortcut_edit` read.
|
|
32
|
+
OLD_KEYS = ("old_string", "oldString", "old_str")
|
|
33
|
+
NEW_KEYS = ("new_string", "newString", "new_str")
|
|
34
|
+
WHOLE_KEYS = ("content", "file_text", "text", "new_source")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def enabled(cwd):
|
|
38
|
+
"""The git root taste rows for `cwd` go to, or None when capture is off
|
|
39
|
+
there. The marker is read first, so the default costs two stats."""
|
|
40
|
+
try:
|
|
41
|
+
if not cwd or not armed(ARM):
|
|
42
|
+
return None
|
|
43
|
+
real = os.path.realpath(cwd)
|
|
44
|
+
if not root_for(real):
|
|
45
|
+
return None
|
|
46
|
+
top = _toplevel(real)
|
|
47
|
+
if not top or not os.path.isdir(os.path.join(top, ".tezgah")):
|
|
48
|
+
return None
|
|
49
|
+
from tezgah_context import repo_marks # imports this module's callers
|
|
50
|
+
if MARK in repo_marks(real)[1] or workspace_from_repo(top):
|
|
51
|
+
return None
|
|
52
|
+
return top
|
|
53
|
+
except Exception:
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _cut(text, limit):
|
|
58
|
+
"""(redacted text cut to `limit`, whether it was cut); None stays None."""
|
|
59
|
+
if text is None:
|
|
60
|
+
return None, False
|
|
61
|
+
text = ti.redact(str(text))
|
|
62
|
+
return text[:limit], len(text) > limit
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _rel(root, path, cwd):
|
|
66
|
+
"""`path` relative to `root`, or None when it resolves outside it."""
|
|
67
|
+
apath = os.path.realpath(
|
|
68
|
+
str(path) if os.path.isabs(str(path)) else os.path.join(cwd, str(path)))
|
|
69
|
+
rel = os.path.relpath(apath, root)
|
|
70
|
+
return None if rel == ".." or rel.startswith(".." + os.sep) else rel
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _write(root, kind, session_id, host, **fields):
|
|
74
|
+
row = {"v": VERSION,
|
|
75
|
+
"ts": datetime.datetime.now(datetime.timezone.utc)
|
|
76
|
+
.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
77
|
+
"kind": kind, "session": str(session_id or ""), "host": host or _host()}
|
|
78
|
+
row.update(fields)
|
|
79
|
+
# the ledger's own writer: its flock, torn-tail repair and 0700/0600 modes
|
|
80
|
+
ti._append(os.path.join(root, ".tezgah", "taste", "signals.jsonl"),
|
|
81
|
+
json.dumps(row, ensure_ascii=False) + "\n")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _host():
|
|
85
|
+
"""The host this hook process runs for, named the way the guard's debug log
|
|
86
|
+
names it: `hosts/<name>/...` by its directory, the shared scripts as
|
|
87
|
+
`claude/dsh`, and None when it cannot be told."""
|
|
88
|
+
try:
|
|
89
|
+
from tezgah_guard import _host as named
|
|
90
|
+
return named()
|
|
91
|
+
except Exception:
|
|
92
|
+
return None
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def note_prompt(session_id, prompt, cwd, host=None):
|
|
96
|
+
"""One `prompt` row: the user's text, redacted and cut."""
|
|
97
|
+
try:
|
|
98
|
+
root = enabled(cwd)
|
|
99
|
+
if not root or not prompt:
|
|
100
|
+
return
|
|
101
|
+
text, cut = _cut(prompt, PROMPT_MAX)
|
|
102
|
+
fields = {"text": text}
|
|
103
|
+
if cut:
|
|
104
|
+
fields["cut"] = True
|
|
105
|
+
_write(root, "prompt", session_id, host, **fields)
|
|
106
|
+
except Exception:
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _edit_row(root, session_id, row_id, path, old, new, cwd, host):
|
|
111
|
+
rel = _rel(root, path, cwd)
|
|
112
|
+
if rel is None:
|
|
113
|
+
return
|
|
114
|
+
old, old_cut = _cut(old, EDIT_MAX)
|
|
115
|
+
new, new_cut = _cut(new, EDIT_MAX)
|
|
116
|
+
fields = {"id": row_id, "path": rel, "old": old, "new": new}
|
|
117
|
+
if old_cut or new_cut:
|
|
118
|
+
fields["cut"] = True
|
|
119
|
+
_write(root, "edit", session_id, host, **fields)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _after_row(root, session_id, path, snapshot_id, sha, cwd, host):
|
|
123
|
+
rel = _rel(root, path, cwd)
|
|
124
|
+
if rel is not None:
|
|
125
|
+
_write(root, "after", session_id, host, path=rel,
|
|
126
|
+
snapshot=snapshot_id, sha=sha)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def edit_text(inp):
|
|
130
|
+
"""(old, new) a write tool's input carries: the replaced and the new text of
|
|
131
|
+
an edit, None and the whole body of a write, None and the patch of an
|
|
132
|
+
apply_patch, the joined pairs of a multi-edit."""
|
|
133
|
+
def first(keys):
|
|
134
|
+
for k in keys:
|
|
135
|
+
if isinstance(inp.get(k), str):
|
|
136
|
+
return inp[k]
|
|
137
|
+
return None
|
|
138
|
+
new = first(NEW_KEYS)
|
|
139
|
+
if new is not None:
|
|
140
|
+
return first(OLD_KEYS), new
|
|
141
|
+
whole = first(WHOLE_KEYS)
|
|
142
|
+
if whole is not None:
|
|
143
|
+
return None, whole
|
|
144
|
+
if isinstance(inp.get("patch"), str):
|
|
145
|
+
return None, inp["patch"]
|
|
146
|
+
edits = [e for e in inp.get("edits") or () if isinstance(e, dict)]
|
|
147
|
+
if edits:
|
|
148
|
+
def joined(keys):
|
|
149
|
+
parts = [next((e[k] for k in keys if isinstance(e.get(k), str)), "")
|
|
150
|
+
for e in edits]
|
|
151
|
+
return "\n".join(parts)
|
|
152
|
+
return joined(OLD_KEYS), joined(NEW_KEYS)
|
|
153
|
+
return None, None
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def note_write(session_id, row_id, inp, cwd, host=None):
|
|
157
|
+
"""The taste rows of one landed write call: its `edit` row, then an `after`
|
|
158
|
+
row per file it wrote, each backed by an after blob in the snapshot store.
|
|
159
|
+
Called from PostToolUse, so the bytes read are the ones the write left. A
|
|
160
|
+
call touching a credential file gets nothing: its text would be the secret
|
|
161
|
+
outside the file that guards it (`tezgah_snapshot.SECRET_FILE`)."""
|
|
162
|
+
try:
|
|
163
|
+
if not armed(ARM) or not isinstance(inp, dict) or inp.get("command") == "view":
|
|
164
|
+
return # off first; str_replace_editor's `view` reads, writes nothing
|
|
165
|
+
import tezgah_snapshot as ts
|
|
166
|
+
from tezgah_gate import write_paths
|
|
167
|
+
paths = write_paths(inp)
|
|
168
|
+
root = enabled(cwd)
|
|
169
|
+
if not root or not paths or any(
|
|
170
|
+
ts.SECRET_FILE.match(os.path.basename(str(p))) for p in paths):
|
|
171
|
+
return
|
|
172
|
+
old, new = edit_text(inp)
|
|
173
|
+
_edit_row(root, session_id, row_id, paths[0], old, new, cwd, host)
|
|
174
|
+
for path in paths:
|
|
175
|
+
if _rel(root, path, cwd) is None:
|
|
176
|
+
continue # outside the repository: no row, so no orphan blob
|
|
177
|
+
saved = ts.capture_after(path, cwd, session_id)
|
|
178
|
+
if saved:
|
|
179
|
+
_after_row(root, session_id, path, saved[0], saved[1], cwd, host)
|
|
180
|
+
except Exception:
|
|
181
|
+
pass
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def main(argv):
|
|
185
|
+
"""`tezgah_taste.py '<json>'`: `note_write` for a host that cannot call it
|
|
186
|
+
in process (opencode's plugin is JavaScript). The one argument is
|
|
187
|
+
{"session_id", "id", "input", "cwd", "host"}. Silent, exit 0 always."""
|
|
188
|
+
try:
|
|
189
|
+
payload = json.loads(argv[0]) if argv else {}
|
|
190
|
+
if isinstance(payload, dict):
|
|
191
|
+
note_write(payload.get("session_id"), payload.get("id"),
|
|
192
|
+
payload.get("input"), payload.get("cwd") or os.getcwd(),
|
|
193
|
+
payload.get("host"))
|
|
194
|
+
except Exception:
|
|
195
|
+
pass
|
|
196
|
+
return 0
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
if __name__ == "__main__":
|
|
200
|
+
import sys
|
|
201
|
+
sys.exit(main(sys.argv[1:]))
|