@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,490 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Pre-write file snapshots, and the one explicit command that rolls one back.
|
|
3
|
+
|
|
4
|
+
`capture(tool, inp, cwd, session_id)` copies the current bytes of every file a
|
|
5
|
+
write tool is about to change into the snapshot store, and appends one
|
|
6
|
+
`snapshot` ledger row (id, path, sha256) naming what it saved.
|
|
7
|
+
`restore(snapshot_id)` puts those bytes back, and `restore_session(session_id)`
|
|
8
|
+
does it for every path one session changed; both have exactly one caller:
|
|
9
|
+
`bin/tezgah-rollback`, which a user runs.
|
|
10
|
+
|
|
11
|
+
There is deliberately NO automatic rollback anywhere in tezgah. A hook that
|
|
12
|
+
undoes work on its own can cause more damage than the failure it answers: the
|
|
13
|
+
half-finished edit it would revert is indistinguishable from the user's own
|
|
14
|
+
work, a restore nobody asked for destroys the only copy of whatever it replaced,
|
|
15
|
+
and the trigger would be a guess about intent ("this edit looks wrong") wearing
|
|
16
|
+
a check's clothes. A snapshot is a pre-state to reach for; the decision to reach
|
|
17
|
+
for it stays with the user.
|
|
18
|
+
"""
|
|
19
|
+
import hashlib
|
|
20
|
+
import json
|
|
21
|
+
import os
|
|
22
|
+
import re
|
|
23
|
+
import time
|
|
24
|
+
import uuid
|
|
25
|
+
|
|
26
|
+
import tezgah_integrity as ti
|
|
27
|
+
from tezgah_paths import cache_dir, root_for
|
|
28
|
+
|
|
29
|
+
# A snapshot id is exactly what `capture` generates: 12 hex chars. Validated
|
|
30
|
+
# before it is used as a path segment, so an id typed at a shell cannot walk out
|
|
31
|
+
# of the store with `..` or an absolute path and read some other file's manifest.
|
|
32
|
+
SNAPSHOT_ID = re.compile(r"\A[0-9a-f]{12}\Z")
|
|
33
|
+
|
|
34
|
+
# The store is capped, because copying every file the agent touches with no
|
|
35
|
+
# bound is a disk leak: one long turn edits dozens of files, and a session runs
|
|
36
|
+
# for hours. Two limits, and what each one costs:
|
|
37
|
+
#
|
|
38
|
+
# CAP snapshots, and the OLDEST IS EVICTED when a capture crosses it. Eviction
|
|
39
|
+
# rather than refusing to capture: a store that starts refusing is a snapshot
|
|
40
|
+
# guard that silently turns itself off inside the long, busy session where a
|
|
41
|
+
# mistake is most likely and most expensive, while the snapshot anyone actually
|
|
42
|
+
# asks for is about a recent mistake - the oldest one is what nobody is coming
|
|
43
|
+
# back for. Worst case on disk is CAP * MAX_BYTES = 400 MB; the realistic case
|
|
44
|
+
# is a few MB, because source files are kilobytes.
|
|
45
|
+
#
|
|
46
|
+
# MAX_BYTES per file, above which nothing is captured at all. `capture` runs
|
|
47
|
+
# synchronously in the gate a host calls before the write, so copying a
|
|
48
|
+
# multi-gigabyte file the agent is about to append to would stall the very call
|
|
49
|
+
# it protects. ponytail: an over-large file is left un-snapshotted - capture
|
|
50
|
+
# returns None and writes no row, so nothing claims a copy that is not there.
|
|
51
|
+
# Raise MAX_BYTES where editing big files is the common case.
|
|
52
|
+
CAP = 200
|
|
53
|
+
MAX_BYTES = 2 * 1024 * 1024
|
|
54
|
+
# HASH_MAX_BYTES caps `_hash_file`, which runs after every write the host
|
|
55
|
+
# reports. A file over it gets no digest - None, the "not readable" answer every
|
|
56
|
+
# caller already handles: the row carries no after-state and a rollback over it
|
|
57
|
+
# needs --force. Eight times MAX_BYTES, so a file small enough to snapshot has
|
|
58
|
+
# to grow eightfold in one write to lose its after-state; sha256 of 16 MiB is
|
|
59
|
+
# ~8 ms on an M-series core.
|
|
60
|
+
HASH_MAX_BYTES = 8 * MAX_BYTES
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _store():
|
|
64
|
+
"""Where the pre-write bytes go: beside the evidence ledger, in whichever
|
|
65
|
+
cache dir tezgah settled on for this environment (a sandboxed host has no
|
|
66
|
+
writable ~/.cache and falls back to temp), so all tezgah state sits under
|
|
67
|
+
one root."""
|
|
68
|
+
return os.path.join(cache_dir(), "snapshots")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _dir(snapshot_id):
|
|
72
|
+
return os.path.join(_store(), str(snapshot_id))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _blob(snapshot_id):
|
|
76
|
+
return os.path.join(_dir(snapshot_id), "file")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _manifest(snapshot_id):
|
|
80
|
+
return os.path.join(_dir(snapshot_id), "meta.json")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _dirs():
|
|
84
|
+
try:
|
|
85
|
+
return [os.path.join(_store(), n) for n in os.listdir(_store())]
|
|
86
|
+
except OSError:
|
|
87
|
+
return []
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _evict(keep=None):
|
|
91
|
+
"""Drop snapshot directories, oldest first, until `keep` (CAP) remain.
|
|
92
|
+
|
|
93
|
+
The order is each directory's own mtime, which is when its capture created
|
|
94
|
+
it - nothing writes inside a snapshot directory afterwards. Best effort: an
|
|
95
|
+
entry that cannot be read or removed costs the cap, never the capture the
|
|
96
|
+
gate is waiting on."""
|
|
97
|
+
keep = CAP if keep is None else keep
|
|
98
|
+
try:
|
|
99
|
+
# ns rather than the float mtime: two captures inside one tick must not
|
|
100
|
+
# evict an arbitrary one of the pair
|
|
101
|
+
entries = sorted((os.stat(p).st_mtime_ns, p) for p in _dirs())
|
|
102
|
+
except OSError:
|
|
103
|
+
return
|
|
104
|
+
for _, path in entries[:-keep]:
|
|
105
|
+
import shutil # deferred: ~3.7 ms of import for a path only a write takes
|
|
106
|
+
shutil.rmtree(path, ignore_errors=True)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _hash_file(path):
|
|
110
|
+
"""sha256 of a file's bytes, or None when it is not there / not readable /
|
|
111
|
+
over HASH_MAX_BYTES.
|
|
112
|
+
|
|
113
|
+
Read in blocks: this hashes the file as it is NOW, which a capture cannot
|
|
114
|
+
bound - the copy was capped at MAX_BYTES, but the file it came from may have
|
|
115
|
+
grown since. The read stops one byte past the cap, so a file that grows
|
|
116
|
+
during the read is bounded too."""
|
|
117
|
+
try:
|
|
118
|
+
digest = hashlib.sha256()
|
|
119
|
+
left = HASH_MAX_BYTES + 1
|
|
120
|
+
with open(path, "rb") as fh:
|
|
121
|
+
while left > 0:
|
|
122
|
+
block = fh.read(min(1 << 20, left))
|
|
123
|
+
if not block:
|
|
124
|
+
return digest.hexdigest()
|
|
125
|
+
digest.update(block)
|
|
126
|
+
left -= len(block)
|
|
127
|
+
return None
|
|
128
|
+
except OSError:
|
|
129
|
+
return None
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _write_paths(inp):
|
|
133
|
+
"""The files this call writes, from tezgah_gate's own reader.
|
|
134
|
+
|
|
135
|
+
That reader is the one definition of each host dialect (`file_path`,
|
|
136
|
+
`filePath`, `path`, and the `*** Update File:` headers of an apply_patch
|
|
137
|
+
body), and a second copy here would drift from the file the gate's own rules
|
|
138
|
+
read. Imported inside the call because the gate imports this module: a
|
|
139
|
+
module-level import would close the cycle. A missing name costs the
|
|
140
|
+
snapshot, never the call."""
|
|
141
|
+
try:
|
|
142
|
+
from tezgah_gate import write_paths
|
|
143
|
+
except ImportError:
|
|
144
|
+
return []
|
|
145
|
+
return write_paths(inp if isinstance(inp, dict) else {})
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _append(session_id, row):
|
|
149
|
+
"""Append one ledger row, including the keys tezgah_integrity.note() drops.
|
|
150
|
+
|
|
151
|
+
`note()` keeps only the LEDGER_FIELDS keys and truncates `detail` to 200
|
|
152
|
+
chars, so a row carrying a sha256 - and a path longer than the truncation -
|
|
153
|
+
cannot go through it. This writes the same file that writer names, from the
|
|
154
|
+
same derivation (`tezgah_integrity._path`), so there is one ledger and one
|
|
155
|
+
rule for where it is; every reader treats an unknown key as nothing, so the
|
|
156
|
+
extra `hash` costs no existing reader anything. Best effort, like `note()`:
|
|
157
|
+
a write failure is not the caller's failure."""
|
|
158
|
+
if not session_id:
|
|
159
|
+
return
|
|
160
|
+
try:
|
|
161
|
+
# through the ledger's own writer: its flock, its torn-tail repair and
|
|
162
|
+
# its owner-only modes (audit SEC-05 / L-6), not a second open()
|
|
163
|
+
ti._append(ti._path(session_id),
|
|
164
|
+
json.dumps({k: v for k, v in row.items() if v is not None})
|
|
165
|
+
+ "\n")
|
|
166
|
+
except (OSError, AttributeError):
|
|
167
|
+
pass
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
# The files whose bytes are a credential: dotenv files, key and keystore files,
|
|
171
|
+
# SSH private keys and the per-tool credential stores. Their pre-write bytes are
|
|
172
|
+
# never copied into the store - a plain copy under the cache is the secret
|
|
173
|
+
# outside the file that guards it (audit SEC-05 / L-6). The row still records
|
|
174
|
+
# the file, its size and its sha256, so the after-state comparison (`changed`)
|
|
175
|
+
# and the freshness rule see the write exactly as they see any other.
|
|
176
|
+
SECRET_FILE = re.compile(
|
|
177
|
+
r"\A(?:\.env(?:rc|\..*)?|.*\.env|.*\.(?:pem|key|p12|pfx|jks|keystore)"
|
|
178
|
+
r"|id_(?:rsa|dsa|ecdsa|ed25519)[\w-]*|credentials(?:\.json)?|\.netrc|_netrc"
|
|
179
|
+
r"|\.npmrc|\.pypirc|\.pgpass|\.git-credentials)\Z", re.I)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _private_open(path):
|
|
183
|
+
"""An owner-only (0600) file for the store, opened for binary writing: a
|
|
184
|
+
snapshot is a copy of the user's file, and the default umask left it
|
|
185
|
+
readable by every local user (audit SEC-05 / L-6)."""
|
|
186
|
+
return os.fdopen(os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
|
|
187
|
+
0o600), "wb")
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _capture_one(path, cwd, session_id):
|
|
191
|
+
"""One file: copy its bytes in, write its row, return the snapshot id.
|
|
192
|
+
|
|
193
|
+
A credential file (`SECRET_FILE`) gets the row alone - name, size, sha256
|
|
194
|
+
and no id, because there is no copy to restore - and returns None."""
|
|
195
|
+
apath = os.path.realpath(
|
|
196
|
+
str(path) if os.path.isabs(str(path))
|
|
197
|
+
else os.path.join(cwd or ".", str(path)))
|
|
198
|
+
try:
|
|
199
|
+
if not os.path.isfile(apath) or os.path.getsize(apath) > MAX_BYTES:
|
|
200
|
+
return None
|
|
201
|
+
with open(apath, "rb") as fh:
|
|
202
|
+
data = fh.read()
|
|
203
|
+
except OSError: # unreadable, or gone between the size check and the read
|
|
204
|
+
return None
|
|
205
|
+
digest = hashlib.sha256(data).hexdigest()
|
|
206
|
+
ts = int(time.time())
|
|
207
|
+
workspace = root_for(cwd) if cwd else None
|
|
208
|
+
if SECRET_FILE.match(os.path.basename(apath)):
|
|
209
|
+
_append(session_id, {"kind": "snapshot", "ts": ts, "detail": apath,
|
|
210
|
+
"hash": digest, "out_bytes": len(data),
|
|
211
|
+
"workspace": workspace})
|
|
212
|
+
return None
|
|
213
|
+
sid = _save(data, {"path": apath, "hash": digest, "session": session_id,
|
|
214
|
+
"workspace": workspace, "bytes": len(data), "ts": ts})
|
|
215
|
+
if not sid:
|
|
216
|
+
return None
|
|
217
|
+
# the row comes last: it must never name a copy that is not on disk
|
|
218
|
+
_append(session_id, {"kind": "snapshot", "ts": ts, "detail": apath,
|
|
219
|
+
"id": sid, "hash": digest, "out_bytes": len(data),
|
|
220
|
+
"workspace": workspace})
|
|
221
|
+
return sid
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def _save(data, meta):
|
|
225
|
+
"""Write one blob and its manifest under a fresh id, evict past CAP, and
|
|
226
|
+
return the id - or None, with nothing left behind, when the write failed."""
|
|
227
|
+
sid = uuid.uuid4().hex[:12]
|
|
228
|
+
try:
|
|
229
|
+
os.makedirs(_store(), mode=0o700, exist_ok=True)
|
|
230
|
+
os.makedirs(_dir(sid), mode=0o700, exist_ok=True)
|
|
231
|
+
with _private_open(_blob(sid)) as fh:
|
|
232
|
+
fh.write(data)
|
|
233
|
+
with _private_open(_manifest(sid)) as fh:
|
|
234
|
+
fh.write(json.dumps(dict(meta, id=sid)).encode("utf-8"))
|
|
235
|
+
except OSError:
|
|
236
|
+
import shutil # deferred: see _evict
|
|
237
|
+
shutil.rmtree(_dir(sid), ignore_errors=True) # no half a snapshot
|
|
238
|
+
return None
|
|
239
|
+
_evict()
|
|
240
|
+
return sid
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def capture_after(path, cwd=None, session_id=None):
|
|
244
|
+
"""Copy the bytes a write left behind into the store; return (id, sha256),
|
|
245
|
+
or None when there is nothing to keep.
|
|
246
|
+
|
|
247
|
+
The post-write half of a taste signal (tezgah_taste): the after-state of the
|
|
248
|
+
agent's edit is what a later user correction is compared against, and the
|
|
249
|
+
file will have moved on by the time anything reads it. Same limits and same
|
|
250
|
+
eviction as a pre-write capture - a credential file (`SECRET_FILE`), a file
|
|
251
|
+
over MAX_BYTES or an unreadable one is not copied. No ledger row: the
|
|
252
|
+
pre-state reader (`tezgah_integrity._snapshot_hash`) and a session rollback
|
|
253
|
+
read `snapshot` rows, and an after-state there would be taken for a
|
|
254
|
+
pre-state. The manifest says `after`, so a reader of the store can tell."""
|
|
255
|
+
apath = os.path.realpath(
|
|
256
|
+
str(path) if os.path.isabs(str(path))
|
|
257
|
+
else os.path.join(cwd or ".", str(path)))
|
|
258
|
+
if SECRET_FILE.match(os.path.basename(apath)):
|
|
259
|
+
return None
|
|
260
|
+
try:
|
|
261
|
+
if not os.path.isfile(apath) or os.path.getsize(apath) > MAX_BYTES:
|
|
262
|
+
return None
|
|
263
|
+
with open(apath, "rb") as fh:
|
|
264
|
+
data = fh.read()
|
|
265
|
+
except OSError:
|
|
266
|
+
return None
|
|
267
|
+
digest = hashlib.sha256(data).hexdigest()
|
|
268
|
+
sid = _save(data, {"path": apath, "hash": digest, "session": session_id,
|
|
269
|
+
"workspace": root_for(cwd) if cwd else None,
|
|
270
|
+
"bytes": len(data), "ts": int(time.time()),
|
|
271
|
+
"after": True})
|
|
272
|
+
return (sid, digest) if sid else None
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def capture(tool, inp, cwd, session_id):
|
|
276
|
+
"""Snapshot every file this call is about to change; return the first id.
|
|
277
|
+
|
|
278
|
+
None means there was nothing to capture: a tool that is not a write tool, a
|
|
279
|
+
file that does not exist yet (a new file has no bytes to lose), a path that
|
|
280
|
+
is not a readable regular file, a file over MAX_BYTES, or no session to
|
|
281
|
+
record the row in. A call that writes several files (an apply_patch body
|
|
282
|
+
names them) captures each and returns the first: every capture gets its own
|
|
283
|
+
id, its own row and its own directory.
|
|
284
|
+
|
|
285
|
+
Never raises. The gate calls this on the way to allowing a write, so the
|
|
286
|
+
worst a snapshot may cost is the snapshot."""
|
|
287
|
+
if not session_id or str(tool or "").lower() not in ti.WRITE_TOOLS:
|
|
288
|
+
return None
|
|
289
|
+
ids = []
|
|
290
|
+
for path in _write_paths(inp):
|
|
291
|
+
sid = _capture_one(path, cwd, session_id)
|
|
292
|
+
if sid:
|
|
293
|
+
ids.append(sid)
|
|
294
|
+
return ids[0] if ids else None
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class SnapshotError(Exception):
|
|
298
|
+
"""A rollback that must not proceed, with the reason the user reads."""
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def restore(snapshot_id, force=False, expect=None):
|
|
302
|
+
"""Put a snapshot's bytes back, write the `rollback` row, name the file.
|
|
303
|
+
|
|
304
|
+
Returns the restored paths, as a list (a snapshot holds one file; the shape
|
|
305
|
+
is what the contract declares). Raises SnapshotError - its only failure
|
|
306
|
+
mode, so a caller never has to guess - when the id is unknown (never taken,
|
|
307
|
+
or evicted), when the stored bytes do not match the hash the snapshot
|
|
308
|
+
recorded (so restoring them would write corruption), or when the file has
|
|
309
|
+
changed since the capture and putting the old bytes back would silently
|
|
310
|
+
clobber that change. `force` overrides that last refusal and only that one,
|
|
311
|
+
and the row records that it was used.
|
|
312
|
+
|
|
313
|
+
`expect` is another sha256 the file may have now without counting as moved
|
|
314
|
+
on: the session's own last recorded state of it, which is what a session
|
|
315
|
+
rollback passes. Its earliest snapshot is the pre-state of the session's
|
|
316
|
+
FIRST write, so the file differs from it by construction - the session's own
|
|
317
|
+
later writes, not someone else's - and without `expect` every path of every
|
|
318
|
+
session rollback would need --force, which is a check that refuses nothing.
|
|
319
|
+
|
|
320
|
+
Not called by any hook: see the module docstring for why."""
|
|
321
|
+
sid = str(snapshot_id or "")
|
|
322
|
+
meta, data = None, b""
|
|
323
|
+
if SNAPSHOT_ID.match(sid):
|
|
324
|
+
try:
|
|
325
|
+
with open(_manifest(sid), encoding="utf-8") as fh:
|
|
326
|
+
meta = json.load(fh)
|
|
327
|
+
with open(_blob(sid), "rb") as fh:
|
|
328
|
+
data = fh.read()
|
|
329
|
+
except (OSError, ValueError):
|
|
330
|
+
meta = None
|
|
331
|
+
if not meta:
|
|
332
|
+
raise SnapshotError(
|
|
333
|
+
"unknown snapshot id %r: the store holds no snapshot for it (CAP "
|
|
334
|
+
"keeps the newest %d, and an evicted one is gone for good)"
|
|
335
|
+
% (snapshot_id, CAP))
|
|
336
|
+
path = str(meta.get("path") or "")
|
|
337
|
+
if not path or hashlib.sha256(data).hexdigest() != meta.get("hash"):
|
|
338
|
+
raise SnapshotError(
|
|
339
|
+
"snapshot %r is damaged: its stored bytes do not match the hash it "
|
|
340
|
+
"recorded, so nothing was restored" % sid)
|
|
341
|
+
digest = meta.get("hash")
|
|
342
|
+
current = _hash_file(path)
|
|
343
|
+
# a set without None: a file that is gone never matches, so `expect=None`
|
|
344
|
+
# cannot wave through a deleted file
|
|
345
|
+
if current not in {digest, expect} - {None} and not force:
|
|
346
|
+
since = ("this session last wrote it" if expect
|
|
347
|
+
else "snapshot %r was taken" % sid)
|
|
348
|
+
raise SnapshotError(
|
|
349
|
+
"%s has changed since %s%s; --force restores the captured bytes "
|
|
350
|
+
"over it" % (path, since, "" if current else " (it is gone now)"))
|
|
351
|
+
try:
|
|
352
|
+
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
353
|
+
with open(path, "wb") as fh:
|
|
354
|
+
fh.write(data)
|
|
355
|
+
except OSError as exc:
|
|
356
|
+
raise SnapshotError("could not write %s (%s)" % (path, exc))
|
|
357
|
+
_append(meta.get("session"),
|
|
358
|
+
{"kind": "rollback", "ts": int(time.time()), "detail": path,
|
|
359
|
+
"id": meta.get("id") or sid, "out_bytes": len(data),
|
|
360
|
+
"workspace": meta.get("workspace"), "forced": force or None})
|
|
361
|
+
return [path]
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def _row_path(row, resolved=()):
|
|
365
|
+
"""The resolved file a write row names, or "".
|
|
366
|
+
|
|
367
|
+
An `edit` row's detail is the tool's own path argument; a `run` row's is the
|
|
368
|
+
command, whose target is the redirect tezgah_gate.write_paths reads (the same
|
|
369
|
+
reader `_post_write` hashed it through).
|
|
370
|
+
|
|
371
|
+
A relative target is resolved against `resolved` - the paths the ledger has
|
|
372
|
+
already resolved, which are the snapshot rows' own: the gate's capture
|
|
373
|
+
resolved that same target against the call's cwd, which the row does not
|
|
374
|
+
keep, and wrote the answer there. A target that names the tail of exactly one
|
|
375
|
+
of them IS that path; the row's `workspace` (the root, not the cwd) is the
|
|
376
|
+
fallback. ponytail: two candidates - the same name under two directories the
|
|
377
|
+
session touched - and a relative fallback that resolves to a file the ledger
|
|
378
|
+
never named both stay unmatched, so the row lands outside the plan rather
|
|
379
|
+
than on a guessed path."""
|
|
380
|
+
detail = str(row.get("detail") or "")
|
|
381
|
+
mark = " " + ti.FAILED_MARK
|
|
382
|
+
if detail.endswith(mark):
|
|
383
|
+
detail = detail[:-len(mark)]
|
|
384
|
+
if row.get("kind") == "run":
|
|
385
|
+
detail = str((_write_paths({"command": detail}) or [""])[0])
|
|
386
|
+
if not detail:
|
|
387
|
+
return ""
|
|
388
|
+
if os.path.isabs(detail):
|
|
389
|
+
return os.path.realpath(detail)
|
|
390
|
+
detail = os.path.normpath(detail)
|
|
391
|
+
tails = [p for p in resolved if p.endswith(os.sep + detail)]
|
|
392
|
+
if len(tails) == 1:
|
|
393
|
+
return tails[0]
|
|
394
|
+
if not row.get("workspace"):
|
|
395
|
+
return ""
|
|
396
|
+
return os.path.realpath(os.path.join(str(row["workspace"]), detail))
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def session_plan(session_id):
|
|
400
|
+
"""What rolling a session back would do, one entry per path, in the order
|
|
401
|
+
the session first touched them: {"path", "id", "action", "expect"}.
|
|
402
|
+
|
|
403
|
+
`id` is the EARLIEST snapshot the session took of the path - the state before
|
|
404
|
+
its first write. `expect` is the session's last recorded hash of it (the
|
|
405
|
+
newest `snapshot`, `edit` or `run` row that carries one), which `restore`
|
|
406
|
+
reads to tell the session's own writes from a later change.
|
|
407
|
+
|
|
408
|
+
`action` is "restore" only for a path with a snapshot that a write tool
|
|
409
|
+
changed (an `edit` row, or a snapshot with no row of its own - the second
|
|
410
|
+
file of an apply_patch body, and then only when no shell row's target could
|
|
411
|
+
not be re-read: see `blind_run`). A path only a shell command touched is
|
|
412
|
+
listed, never reverted, even when the gate snapshotted its redirect target:
|
|
413
|
+
which file a command wrote is read off its text, not reported by a tool, so a
|
|
414
|
+
rollback does not act on it (the id is shown for a deliberate single-id
|
|
415
|
+
restore). The row has to name the target and need not carry a hash: a
|
|
416
|
+
redirect's file that was gone by the time the after-state was read is still
|
|
417
|
+
a shell write, and reading it as a write tool's would revert it. A path with
|
|
418
|
+
no snapshot - a file the session created - has no pre-state to put back and
|
|
419
|
+
is listed too. Reads the ledger, writes nothing."""
|
|
420
|
+
order, first, expect, named = [], {}, {}, {}
|
|
421
|
+
blind_run = False
|
|
422
|
+
for row in ti.events(session_id):
|
|
423
|
+
kind = row.get("kind")
|
|
424
|
+
if kind == "snapshot":
|
|
425
|
+
path = str(row.get("detail") or "")
|
|
426
|
+
# a credential file's row has no id: no copy was kept, so it is
|
|
427
|
+
# listed as having no snapshot rather than restored from nothing
|
|
428
|
+
if path and path not in first and row.get("id"):
|
|
429
|
+
first[path] = row.get("id")
|
|
430
|
+
elif kind in ("edit", "run"):
|
|
431
|
+
path = _row_path(row, order)
|
|
432
|
+
if path:
|
|
433
|
+
named.setdefault(path, set()).add(kind)
|
|
434
|
+
elif kind == "run":
|
|
435
|
+
# A shell row whose target cannot be re-read - the ledger keeps
|
|
436
|
+
# the command cut to DETAIL_MAX, so a redirect past the cut names
|
|
437
|
+
# nothing. Which path it wrote is then unknown, and an unknown
|
|
438
|
+
# write is the one thing this plan must not turn into a revert:
|
|
439
|
+
# it makes every snapshot path with no `edit` row of its own a
|
|
440
|
+
# listing. Not a rare shape: 275 of the 276 ledgers holding a
|
|
441
|
+
# non-check `run` row carry one, so a multi-file patch's second
|
|
442
|
+
# file is listed here rather than restored - which is what it was
|
|
443
|
+
# already, since its after-state hash never reaches the ledger
|
|
444
|
+
# and `expect` keeps the pre-state, so `restore` refused it.
|
|
445
|
+
blind_run = True
|
|
446
|
+
else:
|
|
447
|
+
continue
|
|
448
|
+
if not path:
|
|
449
|
+
continue
|
|
450
|
+
if path not in order:
|
|
451
|
+
order.append(path)
|
|
452
|
+
if row.get("hash"):
|
|
453
|
+
expect[path] = row["hash"]
|
|
454
|
+
plan = []
|
|
455
|
+
for path in order:
|
|
456
|
+
if path not in first:
|
|
457
|
+
action = "list (no snapshot)"
|
|
458
|
+
elif named.get(path) == {"run"}:
|
|
459
|
+
action = "list (shell only)"
|
|
460
|
+
elif blind_run and "edit" not in named.get(path, ()):
|
|
461
|
+
# A shell row's target could not be re-read somewhere in this
|
|
462
|
+
# session, so this path's writer is unknown rather than absent: it is
|
|
463
|
+
# listed, and the label says which of the two reasons applies. In the
|
|
464
|
+
# corpus such a row is the rule and not the exception (275 of the 276
|
|
465
|
+
# ledgers that hold a non-check `run` row), so the second file of a
|
|
466
|
+
# multi-file patch lands here more often than in `restore`.
|
|
467
|
+
action = "list (unknown writer)"
|
|
468
|
+
else:
|
|
469
|
+
action = "restore"
|
|
470
|
+
plan.append({"path": path, "id": first.get(path), "action": action,
|
|
471
|
+
"expect": expect.get(path)})
|
|
472
|
+
return plan
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
def restore_session(session_id, force=False):
|
|
476
|
+
"""Restore every "restore" entry of `session_plan` through `restore`, so the
|
|
477
|
+
moved-on refusal and --force are the single-id rollback's own.
|
|
478
|
+
|
|
479
|
+
Returns (plan, refused): refused maps a path to the reason it was left
|
|
480
|
+
alone. One refusal does not stop the others - each path is its own file and
|
|
481
|
+
its own decision. Not called by any hook: see the module docstring."""
|
|
482
|
+
plan, refused = session_plan(session_id), {}
|
|
483
|
+
for entry in plan:
|
|
484
|
+
if entry["action"] != "restore":
|
|
485
|
+
continue
|
|
486
|
+
try:
|
|
487
|
+
restore(entry["id"], force=force, expect=entry["expect"])
|
|
488
|
+
except SnapshotError as exc:
|
|
489
|
+
refused[entry["path"]] = str(exc)
|
|
490
|
+
return plan, refused
|