xtrm-tools 0.5.25 → 0.5.26
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/.claude-plugin/marketplace.json +19 -0
- package/.claude-plugin/plugin.json +9 -0
- package/cli/dist/index.cjs +59 -52
- package/cli/dist/index.cjs.map +1 -1
- package/cli/package.json +1 -1
- package/hooks/beads-claim-sync.mjs +1 -3
- package/package.json +5 -1
- package/plugins/xtrm-tools/.claude-plugin/plugin.json +9 -0
- package/plugins/xtrm-tools/.mcp.json +18 -0
- package/plugins/xtrm-tools/hooks/README.md +61 -0
- package/plugins/xtrm-tools/hooks/beads-claim-sync.mjs +223 -0
- package/plugins/xtrm-tools/hooks/beads-commit-gate.mjs +70 -0
- package/plugins/xtrm-tools/hooks/beads-compact-restore.mjs +69 -0
- package/plugins/xtrm-tools/hooks/beads-compact-save.mjs +51 -0
- package/plugins/xtrm-tools/hooks/beads-edit-gate.mjs +85 -0
- package/plugins/xtrm-tools/hooks/beads-gate-core.mjs +236 -0
- package/plugins/xtrm-tools/hooks/beads-gate-messages.mjs +68 -0
- package/plugins/xtrm-tools/hooks/beads-gate-utils.mjs +194 -0
- package/plugins/xtrm-tools/hooks/beads-memory-gate.mjs +81 -0
- package/plugins/xtrm-tools/hooks/beads-stop-gate.mjs +53 -0
- package/plugins/xtrm-tools/hooks/gitnexus/gitnexus-hook.cjs +222 -0
- package/plugins/xtrm-tools/hooks/hooks.json +115 -0
- package/plugins/xtrm-tools/hooks/quality-check-env.mjs +79 -0
- package/plugins/xtrm-tools/hooks/quality-check.cjs +1286 -0
- package/plugins/xtrm-tools/hooks/quality-check.py +345 -0
- package/plugins/xtrm-tools/hooks/statusline.mjs +145 -0
- package/plugins/xtrm-tools/hooks/using-xtrm-reminder.mjs +35 -0
- package/plugins/xtrm-tools/hooks/worktree-boundary.mjs +33 -0
- package/plugins/xtrm-tools/hooks/xtrm-logger.mjs +123 -0
- package/plugins/xtrm-tools/hooks/xtrm-session-logger.mjs +27 -0
- package/plugins/xtrm-tools/hooks/xtrm-tool-logger.mjs +53 -0
- package/plugins/xtrm-tools/skills/README.txt +31 -0
- package/plugins/xtrm-tools/skills/clean-code/SKILL.md +201 -0
- package/plugins/xtrm-tools/skills/creating-service-skills/SKILL.md +433 -0
- package/plugins/xtrm-tools/skills/creating-service-skills/references/script_quality_standards.md +425 -0
- package/plugins/xtrm-tools/skills/creating-service-skills/references/service_skill_system_guide.md +278 -0
- package/plugins/xtrm-tools/skills/creating-service-skills/scripts/bootstrap.py +326 -0
- package/plugins/xtrm-tools/skills/creating-service-skills/scripts/deep_dive.py +304 -0
- package/plugins/xtrm-tools/skills/creating-service-skills/scripts/scaffolder.py +482 -0
- package/plugins/xtrm-tools/skills/delegating/SKILL.md +196 -0
- package/plugins/xtrm-tools/skills/delegating/config.yaml +210 -0
- package/plugins/xtrm-tools/skills/delegating/references/orchestration-protocols.md +41 -0
- package/plugins/xtrm-tools/skills/docker-expert/SKILL.md +409 -0
- package/plugins/xtrm-tools/skills/documenting/CHANGELOG.md +23 -0
- package/plugins/xtrm-tools/skills/documenting/README.md +148 -0
- package/plugins/xtrm-tools/skills/documenting/SKILL.md +113 -0
- package/plugins/xtrm-tools/skills/documenting/examples/example_pattern.md +70 -0
- package/plugins/xtrm-tools/skills/documenting/examples/example_reference.md +70 -0
- package/plugins/xtrm-tools/skills/documenting/examples/example_ssot_analytics.md +64 -0
- package/plugins/xtrm-tools/skills/documenting/examples/example_workflow.md +141 -0
- package/plugins/xtrm-tools/skills/documenting/references/changelog-format.md +97 -0
- package/plugins/xtrm-tools/skills/documenting/references/metadata-schema.md +136 -0
- package/plugins/xtrm-tools/skills/documenting/references/taxonomy.md +81 -0
- package/plugins/xtrm-tools/skills/documenting/references/versioning-rules.md +78 -0
- package/plugins/xtrm-tools/skills/documenting/scripts/bump_version.sh +60 -0
- package/plugins/xtrm-tools/skills/documenting/scripts/changelog/__init__.py +0 -0
- package/plugins/xtrm-tools/skills/documenting/scripts/changelog/add_entry.py +216 -0
- package/plugins/xtrm-tools/skills/documenting/scripts/changelog/bump_release.py +117 -0
- package/plugins/xtrm-tools/skills/documenting/scripts/changelog/init_changelog.py +54 -0
- package/plugins/xtrm-tools/skills/documenting/scripts/changelog/validate_changelog.py +128 -0
- package/plugins/xtrm-tools/skills/documenting/scripts/drift_detector.py +266 -0
- package/plugins/xtrm-tools/skills/documenting/scripts/generate_template.py +311 -0
- package/plugins/xtrm-tools/skills/documenting/scripts/list_by_category.sh +84 -0
- package/plugins/xtrm-tools/skills/documenting/scripts/orchestrator.py +255 -0
- package/plugins/xtrm-tools/skills/documenting/scripts/validate_metadata.py +242 -0
- package/plugins/xtrm-tools/skills/documenting/templates/CHANGELOG.md.template +13 -0
- package/plugins/xtrm-tools/skills/documenting/tests/integration_test.sh +70 -0
- package/plugins/xtrm-tools/skills/documenting/tests/test_changelog.py +201 -0
- package/plugins/xtrm-tools/skills/documenting/tests/test_drift_detector.py +80 -0
- package/plugins/xtrm-tools/skills/documenting/tests/test_orchestrator.py +52 -0
- package/plugins/xtrm-tools/skills/documenting/tests/test_validate_metadata.py +64 -0
- package/plugins/xtrm-tools/skills/find-skills/SKILL.md +133 -0
- package/plugins/xtrm-tools/skills/gitnexus-debugging/SKILL.md +85 -0
- package/plugins/xtrm-tools/skills/gitnexus-exploring/SKILL.md +75 -0
- package/plugins/xtrm-tools/skills/gitnexus-impact-analysis/SKILL.md +94 -0
- package/plugins/xtrm-tools/skills/gitnexus-refactoring/SKILL.md +113 -0
- package/plugins/xtrm-tools/skills/hook-development/SKILL.md +797 -0
- package/plugins/xtrm-tools/skills/hook-development/examples/load-context.sh +55 -0
- package/plugins/xtrm-tools/skills/hook-development/examples/quality-check.js +1168 -0
- package/plugins/xtrm-tools/skills/hook-development/examples/validate-bash.sh +43 -0
- package/plugins/xtrm-tools/skills/hook-development/examples/validate-write.sh +38 -0
- package/plugins/xtrm-tools/skills/hook-development/references/advanced.md +527 -0
- package/plugins/xtrm-tools/skills/hook-development/references/migration.md +369 -0
- package/plugins/xtrm-tools/skills/hook-development/references/patterns.md +412 -0
- package/plugins/xtrm-tools/skills/hook-development/scripts/README.md +164 -0
- package/plugins/xtrm-tools/skills/hook-development/scripts/hook-linter.sh +153 -0
- package/plugins/xtrm-tools/skills/hook-development/scripts/test-hook.sh +252 -0
- package/plugins/xtrm-tools/skills/hook-development/scripts/validate-hook-schema.sh +159 -0
- package/plugins/xtrm-tools/skills/obsidian-cli/SKILL.md +106 -0
- package/plugins/xtrm-tools/skills/orchestrating-agents/SKILL.md +135 -0
- package/plugins/xtrm-tools/skills/orchestrating-agents/config.yaml +45 -0
- package/plugins/xtrm-tools/skills/orchestrating-agents/references/agent-context-integration.md +37 -0
- package/plugins/xtrm-tools/skills/orchestrating-agents/references/examples.md +45 -0
- package/plugins/xtrm-tools/skills/orchestrating-agents/references/handover-protocol.md +31 -0
- package/plugins/xtrm-tools/skills/orchestrating-agents/references/workflows.md +42 -0
- package/plugins/xtrm-tools/skills/orchestrating-agents/scripts/detect_neighbors.py +23 -0
- package/plugins/xtrm-tools/skills/prompt-improving/README.md +162 -0
- package/plugins/xtrm-tools/skills/prompt-improving/SKILL.md +74 -0
- package/plugins/xtrm-tools/skills/prompt-improving/references/analysis_commands.md +24 -0
- package/plugins/xtrm-tools/skills/prompt-improving/references/chain_of_thought.md +24 -0
- package/plugins/xtrm-tools/skills/prompt-improving/references/mcp_definitions.md +20 -0
- package/plugins/xtrm-tools/skills/prompt-improving/references/multishot.md +23 -0
- package/plugins/xtrm-tools/skills/prompt-improving/references/xml_core.md +60 -0
- package/plugins/xtrm-tools/skills/python-testing/SKILL.md +815 -0
- package/plugins/xtrm-tools/skills/scoping-service-skills/SKILL.md +231 -0
- package/plugins/xtrm-tools/skills/scoping-service-skills/scripts/scope.py +74 -0
- package/plugins/xtrm-tools/skills/senior-backend/SKILL.md +209 -0
- package/plugins/xtrm-tools/skills/senior-backend/references/api_design_patterns.md +103 -0
- package/plugins/xtrm-tools/skills/senior-backend/references/backend_security_practices.md +103 -0
- package/plugins/xtrm-tools/skills/senior-backend/references/database_optimization_guide.md +103 -0
- package/plugins/xtrm-tools/skills/senior-backend/scripts/api_load_tester.py +114 -0
- package/plugins/xtrm-tools/skills/senior-backend/scripts/api_scaffolder.py +114 -0
- package/plugins/xtrm-tools/skills/senior-backend/scripts/database_migration_tool.py +114 -0
- package/plugins/xtrm-tools/skills/senior-data-scientist/SKILL.md +226 -0
- package/plugins/xtrm-tools/skills/senior-data-scientist/references/experiment_design_frameworks.md +80 -0
- package/plugins/xtrm-tools/skills/senior-data-scientist/references/feature_engineering_patterns.md +80 -0
- package/plugins/xtrm-tools/skills/senior-data-scientist/references/statistical_methods_advanced.md +80 -0
- package/plugins/xtrm-tools/skills/senior-data-scientist/scripts/experiment_designer.py +100 -0
- package/plugins/xtrm-tools/skills/senior-data-scientist/scripts/feature_engineering_pipeline.py +100 -0
- package/plugins/xtrm-tools/skills/senior-data-scientist/scripts/model_evaluation_suite.py +100 -0
- package/plugins/xtrm-tools/skills/senior-devops/SKILL.md +209 -0
- package/plugins/xtrm-tools/skills/senior-devops/references/cicd_pipeline_guide.md +103 -0
- package/plugins/xtrm-tools/skills/senior-devops/references/deployment_strategies.md +103 -0
- package/plugins/xtrm-tools/skills/senior-devops/references/infrastructure_as_code.md +103 -0
- package/plugins/xtrm-tools/skills/senior-devops/scripts/deployment_manager.py +114 -0
- package/plugins/xtrm-tools/skills/senior-devops/scripts/pipeline_generator.py +114 -0
- package/plugins/xtrm-tools/skills/senior-devops/scripts/terraform_scaffolder.py +114 -0
- package/plugins/xtrm-tools/skills/senior-security/SKILL.md +209 -0
- package/plugins/xtrm-tools/skills/senior-security/references/cryptography_implementation.md +103 -0
- package/plugins/xtrm-tools/skills/senior-security/references/penetration_testing_guide.md +103 -0
- package/plugins/xtrm-tools/skills/senior-security/references/security_architecture_patterns.md +103 -0
- package/plugins/xtrm-tools/skills/senior-security/scripts/pentest_automator.py +114 -0
- package/plugins/xtrm-tools/skills/senior-security/scripts/security_auditor.py +114 -0
- package/plugins/xtrm-tools/skills/senior-security/scripts/threat_modeler.py +114 -0
- package/plugins/xtrm-tools/skills/skill-creator/LICENSE.txt +202 -0
- package/plugins/xtrm-tools/skills/skill-creator/SKILL.md +479 -0
- package/plugins/xtrm-tools/skills/skill-creator/agents/analyzer.md +274 -0
- package/plugins/xtrm-tools/skills/skill-creator/agents/comparator.md +202 -0
- package/plugins/xtrm-tools/skills/skill-creator/agents/grader.md +223 -0
- package/plugins/xtrm-tools/skills/skill-creator/assets/eval_review.html +146 -0
- package/plugins/xtrm-tools/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/plugins/xtrm-tools/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/plugins/xtrm-tools/skills/skill-creator/references/schemas.md +430 -0
- package/plugins/xtrm-tools/skills/skill-creator/scripts/__init__.py +0 -0
- package/plugins/xtrm-tools/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/plugins/xtrm-tools/skills/skill-creator/scripts/generate_report.py +326 -0
- package/plugins/xtrm-tools/skills/skill-creator/scripts/improve_description.py +248 -0
- package/plugins/xtrm-tools/skills/skill-creator/scripts/package_skill.py +136 -0
- package/plugins/xtrm-tools/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/plugins/xtrm-tools/skills/skill-creator/scripts/run_eval.py +310 -0
- package/plugins/xtrm-tools/skills/skill-creator/scripts/run_loop.py +332 -0
- package/plugins/xtrm-tools/skills/skill-creator/scripts/utils.py +47 -0
- package/plugins/xtrm-tools/skills/sync-docs/SKILL.md +155 -0
- package/plugins/xtrm-tools/skills/sync-docs/evals/evals.json +89 -0
- package/plugins/xtrm-tools/skills/sync-docs/references/doc-structure.md +99 -0
- package/plugins/xtrm-tools/skills/sync-docs/references/schema.md +103 -0
- package/plugins/xtrm-tools/skills/sync-docs/scripts/changelog/add_entry.py +216 -0
- package/plugins/xtrm-tools/skills/sync-docs/scripts/context_gatherer.py +240 -0
- package/plugins/xtrm-tools/skills/sync-docs/scripts/doc_structure_analyzer.py +495 -0
- package/plugins/xtrm-tools/skills/sync-docs/scripts/drift_detector.py +563 -0
- package/plugins/xtrm-tools/skills/sync-docs/scripts/validate_doc.py +365 -0
- package/plugins/xtrm-tools/skills/sync-docs/scripts/validate_metadata.py +185 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/benchmark.json +293 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/benchmark.md +13 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/eval_metadata.json +27 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/with_skill/outputs/result.md +210 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/with_skill/run-1/grading.json +28 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/with_skill/run-1/timing.json +1 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/without_skill/outputs/result.md +101 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/without_skill/run-1/grading.json +28 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/without_skill/run-1/timing.json +5 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/without_skill/timing.json +5 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/eval_metadata.json +27 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/with_skill/outputs/result.md +198 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/with_skill/run-1/grading.json +28 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/with_skill/run-1/timing.json +1 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/without_skill/outputs/result.md +94 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/without_skill/run-1/grading.json +28 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/without_skill/run-1/timing.json +1 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/eval_metadata.json +27 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/with_skill/outputs/result.md +237 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/with_skill/run-1/grading.json +28 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/with_skill/run-1/timing.json +1 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/without_skill/outputs/result.md +134 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/without_skill/run-1/grading.json +28 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/without_skill/run-1/timing.json +1 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/benchmark.json +297 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/benchmark.md +13 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/eval_metadata.json +27 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/with_skill/outputs/result.md +137 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/with_skill/run-1/grading.json +92 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/with_skill/run-1/timing.json +1 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/without_skill/outputs/result.md +134 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/without_skill/run-1/grading.json +86 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/without_skill/run-1/timing.json +1 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/eval_metadata.json +27 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/with_skill/outputs/result.md +193 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/with_skill/run-1/grading.json +72 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/with_skill/run-1/timing.json +1 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/without_skill/outputs/result.md +211 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/without_skill/run-1/grading.json +91 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/without_skill/run-1/timing.json +5 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/eval_metadata.json +27 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/with_skill/outputs/result.md +182 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/with_skill/run-1/grading.json +95 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/with_skill/run-1/timing.json +1 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/without_skill/outputs/result.md +222 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/without_skill/run-1/grading.json +88 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/without_skill/run-1/timing.json +5 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/benchmark.json +298 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/benchmark.md +13 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/eval_metadata.json +27 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/with_skill/outputs/result.md +125 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/with_skill/run-1/grading.json +97 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/with_skill/run-1/timing.json +5 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/without_skill/outputs/result.md +144 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/without_skill/run-1/grading.json +78 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/without_skill/run-1/timing.json +5 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/eval_metadata.json +27 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/with_skill/outputs/result.md +104 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/with_skill/run-1/grading.json +91 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/with_skill/run-1/timing.json +5 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/without_skill/outputs/result.md +79 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/without_skill/run-1/grading.json +82 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/without_skill/run-1/timing.json +5 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/eval_metadata.json +27 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase1_context.json +302 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase2_drift.txt +33 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase3_analysis.json +114 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase4_fix.txt +118 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase5_validate.txt +38 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/result.md +158 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/run-1/grading.json +95 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/run-1/timing.json +5 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/without_skill/outputs/result.md +71 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/without_skill/run-1/grading.json +90 -0
- package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/without_skill/run-1/timing.json +5 -0
- package/plugins/xtrm-tools/skills/test-planning/SKILL.md +208 -0
- package/plugins/xtrm-tools/skills/test-planning/evals/evals.json +23 -0
- package/plugins/xtrm-tools/skills/updating-service-skills/SKILL.md +136 -0
- package/plugins/xtrm-tools/skills/updating-service-skills/scripts/drift_detector.py +222 -0
- package/plugins/xtrm-tools/skills/using-TDD/SKILL.md +410 -0
- package/plugins/xtrm-tools/skills/using-quality-gates/SKILL.md +254 -0
- package/plugins/xtrm-tools/skills/using-serena-lsp/README.md +8 -0
- package/plugins/xtrm-tools/skills/using-serena-lsp/REFERENCE.md +194 -0
- package/plugins/xtrm-tools/skills/using-serena-lsp/SKILL.md +82 -0
- package/plugins/xtrm-tools/skills/using-service-skills/SKILL.md +108 -0
- package/plugins/xtrm-tools/skills/using-service-skills/scripts/cataloger.py +74 -0
- package/plugins/xtrm-tools/skills/using-service-skills/scripts/skill_activator.py +152 -0
- package/plugins/xtrm-tools/skills/using-service-skills/scripts/test_skill_activator.py +58 -0
- package/plugins/xtrm-tools/skills/using-xtrm/SKILL.md +124 -0
- package/plugins/xtrm-tools/skills/xt-end/SKILL.md +128 -0
package/cli/package.json
CHANGED
|
@@ -150,7 +150,6 @@ function main() {
|
|
|
150
150
|
kind: 'bd.claimed',
|
|
151
151
|
outcome: 'allow',
|
|
152
152
|
issueId,
|
|
153
|
-
message: `Session ${sessionId} claimed issue ${issueId}`,
|
|
154
153
|
});
|
|
155
154
|
|
|
156
155
|
process.stdout.write(JSON.stringify({
|
|
@@ -191,7 +190,6 @@ function main() {
|
|
|
191
190
|
kind: 'bd.closed',
|
|
192
191
|
outcome: 'allow',
|
|
193
192
|
issueId: closedIssueId,
|
|
194
|
-
message: `Issue ${closedIssueId} closed`,
|
|
195
193
|
});
|
|
196
194
|
}
|
|
197
195
|
if (commit) {
|
|
@@ -203,7 +201,7 @@ function main() {
|
|
|
203
201
|
kind: 'bd.committed',
|
|
204
202
|
outcome: commit.ok ? 'allow' : 'block',
|
|
205
203
|
issueId: closedIssueId ?? null,
|
|
206
|
-
|
|
204
|
+
data: { msg: commit.message },
|
|
207
205
|
extra: { ok: commit.ok },
|
|
208
206
|
});
|
|
209
207
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xtrm-tools",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.26",
|
|
4
4
|
"description": "Claude Code tools installer (skills, hooks, MCP servers)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
"hooks",
|
|
21
21
|
"skills",
|
|
22
22
|
"project-skills",
|
|
23
|
+
".claude-plugin",
|
|
24
|
+
"plugins",
|
|
23
25
|
"!**/__pycache__/**",
|
|
24
26
|
"!**/*.pyc",
|
|
25
27
|
"!project-skills/service-skills-set/.claude/skills/using-service-skills/scripts/test_*.py",
|
|
@@ -48,6 +50,8 @@
|
|
|
48
50
|
"lint": "echo 'No linting configured'",
|
|
49
51
|
"test": "npm test --workspace cli",
|
|
50
52
|
"version": "npm run sync:cli-version && git add cli/package.json",
|
|
53
|
+
"prepack": "node scripts/prepack-plugin.mjs",
|
|
54
|
+
"postpack": "node scripts/postpack-plugin.mjs",
|
|
51
55
|
"prepublishOnly": "npm run sync:cli-version && npm run build"
|
|
52
56
|
},
|
|
53
57
|
"engines": {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"github-grep": {
|
|
4
|
+
"type": "http",
|
|
5
|
+
"url": "https://mcp.grep.app"
|
|
6
|
+
},
|
|
7
|
+
"deepwiki": {
|
|
8
|
+
"type": "http",
|
|
9
|
+
"url": "https://mcp.deepwiki.com/mcp"
|
|
10
|
+
},
|
|
11
|
+
"gitnexus": {
|
|
12
|
+
"type": "stdio",
|
|
13
|
+
"command": "npx",
|
|
14
|
+
"args": ["-y", "gitnexus", "mcp"],
|
|
15
|
+
"env": {}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Hooks
|
|
2
|
+
|
|
3
|
+
Claude Code hooks that extend agent behavior with automated checks, workflow enhancements, and safety guardrails.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Hooks intercept specific events in the Claude Code lifecycle. Following architecture decisions in v2.0.0+, the hook ecosystem is designed exclusively for Claude Code.
|
|
8
|
+
|
|
9
|
+
*Note: In v2.1.15+, several older hooks (`skill-suggestion.py`, `skill-discovery.py`, `gitnexus-impact-reminder.py`, and `type-safety-enforcement.py`) were removed or superseded by native capabilities, CLI commands, and consolidated quality gates.*
|
|
10
|
+
|
|
11
|
+
## Project Hooks
|
|
12
|
+
|
|
13
|
+
### gitnexus-hook.cjs
|
|
14
|
+
|
|
15
|
+
**Purpose**: Enriches tool calls with knowledge graph context via `gitnexus augment`. Now supports Serena tools and uses a deduplication cache for efficiency.
|
|
16
|
+
|
|
17
|
+
**Trigger**: PostToolUse (Grep|Glob|Bash|Serena edit tools)
|
|
18
|
+
|
|
19
|
+
## Beads Issue Tracking Gates
|
|
20
|
+
|
|
21
|
+
The beads gate hooks integrate the `bd` (beads) issue tracker directly into Claude's workflow, ensuring no code changes happen without an active ticket.
|
|
22
|
+
|
|
23
|
+
**Installation**: Installed with `xtrm install all` or included when `beads`+`dolt` is available.
|
|
24
|
+
|
|
25
|
+
### Core Gates
|
|
26
|
+
- **`beads-edit-gate.mjs`** (PreToolUse) — Blocks writes/edits without an active issue claim.
|
|
27
|
+
- **`beads-commit-gate.mjs`** (PreToolUse) — Blocks commits with an unresolved session claim.
|
|
28
|
+
- **`beads-stop-gate.mjs`** (Stop) — Blocks session stop while a claim remains open.
|
|
29
|
+
- **`beads-close-memory-prompt.mjs`** (PostToolUse) — Prompts memory handoff after `bd close`.
|
|
30
|
+
|
|
31
|
+
### Compaction & State Preservation (v2.1.18+)
|
|
32
|
+
- **`beads-pre-compact.mjs`** (PreCompact) — Saves the currently `in_progress` beads state before Claude clears context.
|
|
33
|
+
- **`beads-session-start.mjs`** (SessionStart) — Restores the `in_progress` state when the session restarts after compaction.
|
|
34
|
+
|
|
35
|
+
*Note: As of v2.1.18+, hook blocking messages are quieted and compacted to save tokens.*
|
|
36
|
+
|
|
37
|
+
## Hook Timeouts
|
|
38
|
+
|
|
39
|
+
Adjust hook execution timeouts in `settings.json` if commands take longer than expected:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"hooks": {
|
|
44
|
+
"PostToolUse": [{
|
|
45
|
+
"hooks": [{
|
|
46
|
+
"timeout": 5000 // Timeout in milliseconds (5000ms = 5 seconds)
|
|
47
|
+
}]
|
|
48
|
+
}]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Creating Custom Hooks
|
|
54
|
+
|
|
55
|
+
To create new project-specific hooks, use the `hook-development` global skill. Follow the canonical structure defined in the `xtrm-tools` core libraries.
|
|
56
|
+
|
|
57
|
+
For debugging orphaned hooks, use `xtrm clean`.
|
|
58
|
+
|
|
59
|
+
## Pi Extensions Migration
|
|
60
|
+
|
|
61
|
+
Core workflow hooks have been migrated to native Pi Extensions for better performance and integration. See the [Pi Extensions Migration Guide](../docs/pi-extensions-migration.md) for details.
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// beads-claim-sync — PostToolUse hook
|
|
3
|
+
// bd update --claim → set kv claim
|
|
4
|
+
// bd close → auto-commit staged changes, set closed-this-session kv for memory gate
|
|
5
|
+
|
|
6
|
+
import { spawnSync } from 'node:child_process';
|
|
7
|
+
import { readFileSync, existsSync, writeFileSync, unlinkSync, mkdirSync } from 'node:fs';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { resolveSessionId } from './beads-gate-utils.mjs';
|
|
10
|
+
import { logEvent } from './xtrm-logger.mjs';
|
|
11
|
+
|
|
12
|
+
function readInput() {
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse(readFileSync(0, 'utf-8'));
|
|
15
|
+
} catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isBeadsProject(cwd) {
|
|
21
|
+
return existsSync(join(cwd, '.beads'));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function isShellTool(toolName) {
|
|
25
|
+
return toolName === 'Bash' || toolName === 'bash' || toolName === 'execute_shell_command';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function commandSucceeded(payload) {
|
|
29
|
+
const tr = payload?.tool_response ?? payload?.tool_result ?? payload?.result;
|
|
30
|
+
if (!tr || typeof tr !== 'object') return true;
|
|
31
|
+
|
|
32
|
+
if (tr.success === false) return false;
|
|
33
|
+
if (tr.error) return false;
|
|
34
|
+
|
|
35
|
+
const numeric = [tr.exit_code, tr.exitCode, tr.status, tr.returncode].find((v) => Number.isInteger(v));
|
|
36
|
+
if (typeof numeric === 'number' && numeric !== 0) return false;
|
|
37
|
+
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function runGit(args, cwd, timeout = 8000) {
|
|
42
|
+
return spawnSync('git', args, {
|
|
43
|
+
cwd,
|
|
44
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
45
|
+
encoding: 'utf8',
|
|
46
|
+
timeout,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function runBd(args, cwd, timeout = 5000) {
|
|
51
|
+
return spawnSync('bd', args, {
|
|
52
|
+
cwd,
|
|
53
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
54
|
+
encoding: 'utf8',
|
|
55
|
+
timeout,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function hasGitChanges(cwd) {
|
|
60
|
+
const result = runGit(['status', '--porcelain'], cwd);
|
|
61
|
+
if (result.status !== 0) return false;
|
|
62
|
+
return result.stdout.trim().length > 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function getCloseReason(cwd, issueId, command) {
|
|
66
|
+
// 1. Parse --reason "..." from the command itself (fastest, no extra call)
|
|
67
|
+
const reasonMatch = command.match(/--reason[=\s]+["']([^"']+)["']/);
|
|
68
|
+
if (reasonMatch) return reasonMatch[1].trim();
|
|
69
|
+
|
|
70
|
+
// 2. Fall back to bd show <id> --json
|
|
71
|
+
const show = runBd(['show', issueId, '--json'], cwd);
|
|
72
|
+
if (show.status === 0 && show.stdout) {
|
|
73
|
+
try {
|
|
74
|
+
const parsed = JSON.parse(show.stdout);
|
|
75
|
+
const reason = parsed?.[0]?.close_reason;
|
|
76
|
+
if (typeof reason === 'string' && reason.trim().length > 0) return reason.trim();
|
|
77
|
+
} catch { /* fall through */ }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return `Close ${issueId}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function stageUntracked(cwd) {
|
|
84
|
+
const result = runGit(['ls-files', '--others', '--exclude-standard'], cwd);
|
|
85
|
+
if (result.status !== 0) return;
|
|
86
|
+
const untracked = result.stdout.trim().split('\n').filter(Boolean);
|
|
87
|
+
if (untracked.length === 0) return;
|
|
88
|
+
runGit(['add', '--', ...untracked], cwd);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function autoCommit(cwd, issueId, command) {
|
|
92
|
+
if (!hasGitChanges(cwd)) {
|
|
93
|
+
return { ok: true, message: 'No changes detected — auto-commit skipped.' };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
stageUntracked(cwd);
|
|
97
|
+
|
|
98
|
+
const reason = getCloseReason(cwd, issueId, command);
|
|
99
|
+
const commitMessage = `${reason} (${issueId})`;
|
|
100
|
+
const result = runGit(['commit', '-am', commitMessage], cwd, 15000);
|
|
101
|
+
if (result.status !== 0) {
|
|
102
|
+
const err = (result.stderr || result.stdout || '').trim();
|
|
103
|
+
return { ok: false, message: `Auto-commit failed: ${err || 'unknown error'}` };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return { ok: true, message: `Auto-committed: \`${commitMessage}\`` };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
function main() {
|
|
111
|
+
const input = readInput();
|
|
112
|
+
if (!input || input.hook_event_name !== 'PostToolUse') process.exit(0);
|
|
113
|
+
if (!isShellTool(input.tool_name)) process.exit(0);
|
|
114
|
+
|
|
115
|
+
const cwd = input.cwd || process.cwd();
|
|
116
|
+
if (!isBeadsProject(cwd)) process.exit(0);
|
|
117
|
+
|
|
118
|
+
const command = input.tool_input?.command || '';
|
|
119
|
+
const sessionId = resolveSessionId(input);
|
|
120
|
+
|
|
121
|
+
// Auto-claim: bd update <id> --claim (fire regardless of exit code — bd returns 1 for "already in_progress")
|
|
122
|
+
if (/\bbd\s+update\b/.test(command) && /--claim\b/.test(command)) {
|
|
123
|
+
const match = command.match(/\bbd\s+update\s+(\S+)/);
|
|
124
|
+
if (match) {
|
|
125
|
+
const issueId = match[1];
|
|
126
|
+
const result = spawnSync('bd', ['kv', 'set', `claimed:${sessionId}`, issueId], {
|
|
127
|
+
cwd,
|
|
128
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
129
|
+
timeout: 5000,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
if (result.status !== 0) {
|
|
133
|
+
const err = (result.stderr || result.stdout || '').toString().trim();
|
|
134
|
+
if (err) process.stderr.write(`Beads claim sync warning: ${err}\n`);
|
|
135
|
+
process.exit(0);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Write claim state for statusline
|
|
139
|
+
try {
|
|
140
|
+
const xtrmDir = join(cwd, '.xtrm');
|
|
141
|
+
mkdirSync(xtrmDir, { recursive: true });
|
|
142
|
+
writeFileSync(join(xtrmDir, 'statusline-claim'), issueId);
|
|
143
|
+
} catch { /* non-fatal */ }
|
|
144
|
+
|
|
145
|
+
logEvent({
|
|
146
|
+
cwd,
|
|
147
|
+
runtime: 'claude',
|
|
148
|
+
sessionId,
|
|
149
|
+
layer: 'bd',
|
|
150
|
+
kind: 'bd.claimed',
|
|
151
|
+
outcome: 'allow',
|
|
152
|
+
issueId,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
process.stdout.write(JSON.stringify({
|
|
156
|
+
additionalContext: `\n✅ **Beads**: Session \`${sessionId}\` claimed issue \`${issueId}\`.`,
|
|
157
|
+
}));
|
|
158
|
+
process.stdout.write('\n');
|
|
159
|
+
process.exit(0);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// On bd close: auto-commit staged changes, then mark closed-this-session for memory gate
|
|
164
|
+
if (/\bbd\s+close\b/.test(command) && commandSucceeded(input)) {
|
|
165
|
+
const match = command.match(/\bbd\s+close\s+(\S+)/);
|
|
166
|
+
const closedIssueId = match?.[1];
|
|
167
|
+
|
|
168
|
+
// Auto-commit before marking the gate (no-op if clean)
|
|
169
|
+
const commit = closedIssueId ? autoCommit(cwd, closedIssueId, command) : null;
|
|
170
|
+
|
|
171
|
+
// Clear claim state for statusline
|
|
172
|
+
try { unlinkSync(join(cwd, '.xtrm', 'statusline-claim')); } catch { /* ok if missing */ }
|
|
173
|
+
|
|
174
|
+
// Mark this issue as closed this session (memory gate reads this)
|
|
175
|
+
if (closedIssueId) {
|
|
176
|
+
spawnSync('bd', ['kv', 'set', `closed-this-session:${sessionId}`, closedIssueId], {
|
|
177
|
+
cwd,
|
|
178
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
179
|
+
timeout: 5000,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Log bd lifecycle events
|
|
184
|
+
if (closedIssueId) {
|
|
185
|
+
logEvent({
|
|
186
|
+
cwd,
|
|
187
|
+
runtime: 'claude',
|
|
188
|
+
sessionId,
|
|
189
|
+
layer: 'bd',
|
|
190
|
+
kind: 'bd.closed',
|
|
191
|
+
outcome: 'allow',
|
|
192
|
+
issueId: closedIssueId,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
if (commit) {
|
|
196
|
+
logEvent({
|
|
197
|
+
cwd,
|
|
198
|
+
runtime: 'claude',
|
|
199
|
+
sessionId,
|
|
200
|
+
layer: 'bd',
|
|
201
|
+
kind: 'bd.committed',
|
|
202
|
+
outcome: commit.ok ? 'allow' : 'block',
|
|
203
|
+
issueId: closedIssueId ?? null,
|
|
204
|
+
data: { msg: commit.message },
|
|
205
|
+
extra: { ok: commit.ok },
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const commitLine = commit
|
|
210
|
+
? `\n${commit.ok ? '✅' : '⚠️'} **Session Flow**: ${commit.message}`
|
|
211
|
+
: '';
|
|
212
|
+
|
|
213
|
+
process.stdout.write(JSON.stringify({
|
|
214
|
+
additionalContext: `\n🔓 **Beads**: Issue closed.${commitLine}\nEvaluate insights, then acknowledge:\n \`bd remember "<insight>"\` (or note "nothing")\n \`touch .beads/.memory-gate-done\``,
|
|
215
|
+
}));
|
|
216
|
+
process.stdout.write('\n');
|
|
217
|
+
process.exit(0);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
process.exit(0);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
main();
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// beads-commit-gate — Claude Code PreToolUse hook
|
|
3
|
+
// Blocks `git commit` when this session still has an unclosed claim in bd kv.
|
|
4
|
+
// Falls back to global in_progress check when session_id is unavailable.
|
|
5
|
+
// Forces: close issues first, THEN commit.
|
|
6
|
+
// Exit 0: allow | Exit 2: block (stderr shown to Claude)
|
|
7
|
+
//
|
|
8
|
+
// Installed by: xtrm install
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
readHookInput,
|
|
12
|
+
resolveSessionContext,
|
|
13
|
+
resolveClaimAndWorkState,
|
|
14
|
+
decideCommitGate,
|
|
15
|
+
} from './beads-gate-core.mjs';
|
|
16
|
+
import { withSafeBdContext } from './beads-gate-utils.mjs';
|
|
17
|
+
import { commitBlockMessage } from './beads-gate-messages.mjs';
|
|
18
|
+
import { logEvent } from './xtrm-logger.mjs';
|
|
19
|
+
|
|
20
|
+
const input = readHookInput();
|
|
21
|
+
if (!input) process.exit(0);
|
|
22
|
+
|
|
23
|
+
if ((input.tool_name ?? '') !== 'Bash') process.exit(0);
|
|
24
|
+
|
|
25
|
+
const command = input.tool_input?.command ?? '';
|
|
26
|
+
// Strip quoted strings to avoid matching patterns inside --reason "..." or similar args
|
|
27
|
+
const commandUnquoted = command.replace(/'[^']*'|"[^"]*"/g, '');
|
|
28
|
+
|
|
29
|
+
withSafeBdContext(() => {
|
|
30
|
+
const ctx = resolveSessionContext(input);
|
|
31
|
+
if (!ctx || !ctx.isBeadsProject) process.exit(0);
|
|
32
|
+
|
|
33
|
+
// Only intercept git commit for the claim-gate check
|
|
34
|
+
if (!/\bgit\s+commit\b/.test(commandUnquoted)) process.exit(0);
|
|
35
|
+
|
|
36
|
+
const state = resolveClaimAndWorkState(ctx);
|
|
37
|
+
const decision = decideCommitGate(ctx, state);
|
|
38
|
+
|
|
39
|
+
if (decision.allow) {
|
|
40
|
+
logEvent({
|
|
41
|
+
cwd: ctx.cwd,
|
|
42
|
+
runtime: 'claude',
|
|
43
|
+
sessionId: ctx.sessionId,
|
|
44
|
+
layer: 'gate',
|
|
45
|
+
kind: 'gate.commit.allow',
|
|
46
|
+
outcome: 'allow',
|
|
47
|
+
toolName: 'Bash',
|
|
48
|
+
issueId: state?.claimId ?? null,
|
|
49
|
+
});
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Block with structured decision
|
|
54
|
+
const reason = commitBlockMessage(decision.summary, decision.claimed);
|
|
55
|
+
logEvent({
|
|
56
|
+
cwd: ctx.cwd,
|
|
57
|
+
runtime: 'claude',
|
|
58
|
+
sessionId: ctx.sessionId,
|
|
59
|
+
layer: 'gate',
|
|
60
|
+
kind: 'gate.commit.block',
|
|
61
|
+
outcome: 'block',
|
|
62
|
+
toolName: 'Bash',
|
|
63
|
+
issueId: decision.claimed ?? null,
|
|
64
|
+
message: reason,
|
|
65
|
+
extra: { reason_code: decision.reason },
|
|
66
|
+
});
|
|
67
|
+
process.stdout.write(JSON.stringify({ decision: 'block', reason }));
|
|
68
|
+
process.stdout.write('\n');
|
|
69
|
+
process.exit(0);
|
|
70
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Claude Code SessionStart hook — restore in_progress beads issues after context compaction.
|
|
3
|
+
// Reads .beads/.last_active (written by beads-compact-save.mjs), reinstates statuses,
|
|
4
|
+
// restores session state file, deletes the marker, and injects a brief agent context message.
|
|
5
|
+
// Exit 0 in all paths (informational only).
|
|
6
|
+
|
|
7
|
+
import { execSync } from 'node:child_process';
|
|
8
|
+
import { readFileSync, existsSync, unlinkSync } from 'node:fs';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
|
|
11
|
+
let input;
|
|
12
|
+
try {
|
|
13
|
+
input = JSON.parse(readFileSync(0, 'utf8'));
|
|
14
|
+
} catch {
|
|
15
|
+
process.exit(0);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const cwd = input.cwd ?? process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
19
|
+
const lastActivePath = path.join(cwd, '.beads', '.last_active');
|
|
20
|
+
|
|
21
|
+
if (!existsSync(lastActivePath)) process.exit(0);
|
|
22
|
+
|
|
23
|
+
let ids = [];
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const raw = readFileSync(lastActivePath, 'utf8').trim();
|
|
27
|
+
if (raw.startsWith('{')) {
|
|
28
|
+
const parsed = JSON.parse(raw);
|
|
29
|
+
ids = Array.isArray(parsed.ids) ? parsed.ids.filter(Boolean) : [];
|
|
30
|
+
} else {
|
|
31
|
+
// Backward compatibility: legacy newline format
|
|
32
|
+
ids = raw.split('\n').filter(Boolean);
|
|
33
|
+
}
|
|
34
|
+
} catch {
|
|
35
|
+
// If file is malformed, just delete and continue fail-open.
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Clean up regardless of whether restore succeeds
|
|
39
|
+
unlinkSync(lastActivePath);
|
|
40
|
+
|
|
41
|
+
let restored = 0;
|
|
42
|
+
for (const id of ids) {
|
|
43
|
+
try {
|
|
44
|
+
execSync(`bd update ${id} --status in_progress`, {
|
|
45
|
+
encoding: 'utf8',
|
|
46
|
+
cwd,
|
|
47
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
48
|
+
timeout: 5000,
|
|
49
|
+
});
|
|
50
|
+
restored++;
|
|
51
|
+
} catch {
|
|
52
|
+
// ignore — issue may no longer exist
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (restored > 0) {
|
|
57
|
+
const lines = [`Restored ${restored} in_progress issue${restored === 1 ? '' : 's'} from last session before compaction.`];
|
|
58
|
+
|
|
59
|
+
process.stdout.write(
|
|
60
|
+
JSON.stringify({
|
|
61
|
+
hookSpecificOutput: {
|
|
62
|
+
hookEventName: 'SessionStart',
|
|
63
|
+
additionalSystemPrompt: `${lines.join(' ')} Check \`bd list\` for details.`,
|
|
64
|
+
},
|
|
65
|
+
}) + '\n',
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
process.exit(0);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Claude Code PreCompact hook — save in_progress beads issues before context is compacted.
|
|
3
|
+
// Writes a compact bundle to .beads/.last_active for restore hook.
|
|
4
|
+
// Bundle includes issue IDs and xtrm session state when available.
|
|
5
|
+
// Exit 0 in all paths (informational only).
|
|
6
|
+
|
|
7
|
+
import { execSync } from 'node:child_process';
|
|
8
|
+
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
|
|
11
|
+
let input;
|
|
12
|
+
try {
|
|
13
|
+
input = JSON.parse(readFileSync(0, 'utf8'));
|
|
14
|
+
} catch {
|
|
15
|
+
process.exit(0);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const cwd = input.cwd ?? process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
19
|
+
const beadsDir = path.join(cwd, '.beads');
|
|
20
|
+
|
|
21
|
+
if (!existsSync(beadsDir)) process.exit(0);
|
|
22
|
+
|
|
23
|
+
let output = '';
|
|
24
|
+
try {
|
|
25
|
+
output = execSync('bd list --status=in_progress', {
|
|
26
|
+
encoding: 'utf8',
|
|
27
|
+
cwd,
|
|
28
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
29
|
+
timeout: 8000,
|
|
30
|
+
}).trim();
|
|
31
|
+
} catch {
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Parse issue IDs — lines like "◐ proj-abc123 ● P1 Title"
|
|
36
|
+
const ids = [];
|
|
37
|
+
for (const line of output.split('\n')) {
|
|
38
|
+
const match = line.trim().match(/^[○◐●✓❄]\s+([\w-]+)\s/u);
|
|
39
|
+
if (match) ids.push(match[1]);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const bundle = {
|
|
43
|
+
ids,
|
|
44
|
+
savedAt: new Date().toISOString(),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
if (bundle.ids.length === 0) process.exit(0);
|
|
48
|
+
|
|
49
|
+
writeFileSync(path.join(beadsDir, '.last_active'), JSON.stringify(bundle, null, 2) + '\n', 'utf8');
|
|
50
|
+
|
|
51
|
+
process.exit(0);
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// beads-edit-gate — Claude Code PreToolUse hook
|
|
3
|
+
// Blocks file edits when this session has not claimed a beads issue via bd kv.
|
|
4
|
+
// Falls back to global in_progress check when session_id is unavailable.
|
|
5
|
+
// Only active in projects with a .beads/ directory.
|
|
6
|
+
// Exit 0: allow | Exit 2: block (stderr shown to Claude)
|
|
7
|
+
//
|
|
8
|
+
// Installed by: xtrm install
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
readHookInput,
|
|
12
|
+
resolveSessionContext,
|
|
13
|
+
resolveClaimAndWorkState,
|
|
14
|
+
decideEditGate,
|
|
15
|
+
decideWorktreeBoundary,
|
|
16
|
+
} from './beads-gate-core.mjs';
|
|
17
|
+
import { withSafeBdContext, resolveCwd, resolveSessionId } from './beads-gate-utils.mjs';
|
|
18
|
+
import { editBlockMessage, editBlockFallbackMessage } from './beads-gate-messages.mjs';
|
|
19
|
+
import { logEvent } from './xtrm-logger.mjs';
|
|
20
|
+
|
|
21
|
+
const input = readHookInput();
|
|
22
|
+
if (!input) process.exit(0);
|
|
23
|
+
|
|
24
|
+
// Worktree boundary check — independent of beads, fires first
|
|
25
|
+
const _cwd = resolveCwd(input);
|
|
26
|
+
const _boundary = decideWorktreeBoundary(input, _cwd);
|
|
27
|
+
if (!_boundary.allow) {
|
|
28
|
+
const _wbReason = `🚫 Edit outside worktree boundary.\n File: ${_boundary.filePath}\n Allowed: ${_boundary.worktreeRoot}\n\n All edits must stay within the active worktree.`;
|
|
29
|
+
logEvent({
|
|
30
|
+
cwd: _cwd,
|
|
31
|
+
runtime: 'claude',
|
|
32
|
+
sessionId: resolveSessionId(input),
|
|
33
|
+
layer: 'gate',
|
|
34
|
+
kind: 'gate.worktree.block',
|
|
35
|
+
outcome: 'block',
|
|
36
|
+
toolName: input.tool_name,
|
|
37
|
+
message: _wbReason,
|
|
38
|
+
extra: { file: _boundary.filePath, worktree_root: _boundary.worktreeRoot },
|
|
39
|
+
});
|
|
40
|
+
process.stdout.write(JSON.stringify({ decision: 'block', reason: _wbReason }));
|
|
41
|
+
process.stdout.write('\n');
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
withSafeBdContext(() => {
|
|
46
|
+
const ctx = resolveSessionContext(input);
|
|
47
|
+
if (!ctx || !ctx.isBeadsProject) process.exit(0);
|
|
48
|
+
|
|
49
|
+
const state = resolveClaimAndWorkState(ctx);
|
|
50
|
+
const decision = decideEditGate(ctx, state);
|
|
51
|
+
|
|
52
|
+
if (decision.allow) {
|
|
53
|
+
logEvent({
|
|
54
|
+
cwd: ctx.cwd,
|
|
55
|
+
runtime: 'claude',
|
|
56
|
+
sessionId: ctx.sessionId,
|
|
57
|
+
layer: 'gate',
|
|
58
|
+
kind: 'gate.edit.allow',
|
|
59
|
+
outcome: 'allow',
|
|
60
|
+
toolName: input.tool_name,
|
|
61
|
+
issueId: state?.claimId ?? null,
|
|
62
|
+
extra: { file: input.tool_input?.file_path ?? null },
|
|
63
|
+
});
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Block with appropriate message
|
|
68
|
+
const reason = decision.reason === 'no_claim_with_work'
|
|
69
|
+
? editBlockMessage(decision.sessionId)
|
|
70
|
+
: editBlockFallbackMessage();
|
|
71
|
+
logEvent({
|
|
72
|
+
cwd: ctx.cwd,
|
|
73
|
+
runtime: 'claude',
|
|
74
|
+
sessionId: ctx.sessionId,
|
|
75
|
+
layer: 'gate',
|
|
76
|
+
kind: 'gate.edit.block',
|
|
77
|
+
outcome: 'block',
|
|
78
|
+
toolName: input.tool_name,
|
|
79
|
+
message: reason,
|
|
80
|
+
extra: { file: input.tool_input?.file_path ?? null, reason_code: decision.reason },
|
|
81
|
+
});
|
|
82
|
+
process.stdout.write(JSON.stringify({ decision: 'block', reason }));
|
|
83
|
+
process.stdout.write('\n');
|
|
84
|
+
process.exit(0);
|
|
85
|
+
});
|