xtrm-tools 0.5.25 → 0.5.27
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/CHANGELOG.md +4 -0
- package/README.md +7 -1
- package/cli/dist/index.cjs +319 -355
- package/cli/dist/index.cjs.map +1 -1
- package/cli/package.json +1 -1
- package/config/hooks.json +11 -10
- package/config/pi/extensions/beads/index.ts +103 -77
- package/config/pi/extensions/custom-footer/index.ts +40 -7
- package/config/pi/extensions/quality-gates/index.ts +28 -29
- package/config/pi/extensions/session-flow/index.ts +50 -21
- package/config/pi/extensions/xtrm-loader/index.ts +38 -24
- package/hooks/beads-claim-sync.mjs +1 -3
- package/hooks/hooks.json +14 -0
- 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 +129 -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
|
@@ -25,8 +25,18 @@ function findMarkdownFiles(dir: string, basePath: string = ""): string[] {
|
|
|
25
25
|
return results;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
const
|
|
28
|
+
function resolveUsingXtrmSkillPath(cwd: string): string | null {
|
|
29
|
+
const candidates = [
|
|
30
|
+
path.join(homedir(), ".agents", "skills", "using-xtrm", "SKILL.md"),
|
|
31
|
+
path.join(homedir(), ".pi", "agent", "skills", "using-xtrm", "SKILL.md"),
|
|
32
|
+
path.join(cwd, ".pi", "skills", "using-xtrm", "SKILL.md"),
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
for (const candidate of candidates) {
|
|
36
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
30
40
|
|
|
31
41
|
/**
|
|
32
42
|
* Load a skill file, stripping YAML frontmatter.
|
|
@@ -34,8 +44,7 @@ const GLOBAL_SKILLS_DIR = path.join(homedir(), ".agents", "skills");
|
|
|
34
44
|
function loadSkillContent(skillPath: string): string | null {
|
|
35
45
|
try {
|
|
36
46
|
const content = fs.readFileSync(skillPath, "utf8");
|
|
37
|
-
|
|
38
|
-
return content.replace(/^---\n[\s\S]*?\n---\n/, "").trim();
|
|
47
|
+
return content.replace(/^---[\s\S]*?---\n/, "").trim();
|
|
39
48
|
} catch {
|
|
40
49
|
return null;
|
|
41
50
|
}
|
|
@@ -49,18 +58,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
49
58
|
const cwd = ctx.cwd;
|
|
50
59
|
const contextParts: string[] = [];
|
|
51
60
|
|
|
52
|
-
// 0. Load using-xtrm skill (global)
|
|
53
|
-
const usingXtrmPath =
|
|
54
|
-
usingXtrmContent = loadSkillContent(usingXtrmPath);
|
|
55
|
-
if (
|
|
56
|
-
logger.info(
|
|
61
|
+
// 0. Load using-xtrm skill (global/project fallback paths)
|
|
62
|
+
const usingXtrmPath = resolveUsingXtrmSkillPath(cwd);
|
|
63
|
+
usingXtrmContent = usingXtrmPath ? loadSkillContent(usingXtrmPath) : null;
|
|
64
|
+
if (usingXtrmPath && usingXtrmContent) {
|
|
65
|
+
logger.info(`Loaded using-xtrm skill from ${usingXtrmPath}`);
|
|
57
66
|
}
|
|
58
67
|
|
|
59
68
|
// 1. Architecture & Roadmap
|
|
60
69
|
const roadmapPaths = [
|
|
61
70
|
path.join(cwd, "architecture", "project_roadmap.md"),
|
|
62
71
|
path.join(cwd, "ROADMAP.md"),
|
|
63
|
-
path.join(cwd, "architecture", "index.md")
|
|
72
|
+
path.join(cwd, "architecture", "index.md"),
|
|
64
73
|
];
|
|
65
74
|
|
|
66
75
|
for (const p of roadmapPaths) {
|
|
@@ -76,10 +85,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
76
85
|
if (fs.existsSync(rulesDir)) {
|
|
77
86
|
const ruleFiles = findMarkdownFiles(rulesDir);
|
|
78
87
|
if (ruleFiles.length > 0) {
|
|
79
|
-
const rulesContent = (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
88
|
+
const rulesContent = (
|
|
89
|
+
await Promise.all(
|
|
90
|
+
ruleFiles.map(async (f) => {
|
|
91
|
+
const content = await fs.promises.readFile(path.join(rulesDir, f), "utf8");
|
|
92
|
+
return `### Rule: ${f}\n${content}`;
|
|
93
|
+
}),
|
|
94
|
+
)
|
|
95
|
+
).join("\n\n");
|
|
83
96
|
contextParts.push(`## Project Rules\n\n${rulesContent}`);
|
|
84
97
|
}
|
|
85
98
|
}
|
|
@@ -89,16 +102,17 @@ export default function (pi: ExtensionAPI) {
|
|
|
89
102
|
if (fs.existsSync(skillsDir)) {
|
|
90
103
|
const skillFiles = findMarkdownFiles(skillsDir);
|
|
91
104
|
if (skillFiles.length > 0) {
|
|
92
|
-
const skillsContent = skillFiles
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
105
|
+
const skillsContent = skillFiles
|
|
106
|
+
.map((f) => `- ${f} (Path: .claude/skills/${f})`)
|
|
107
|
+
.join("\n");
|
|
108
|
+
contextParts.push(
|
|
109
|
+
`## Available Project Skills\n\nExisting service skills and workflows found in .claude/skills/:\n\n${skillsContent}\n\nUse the read tool to load any of these skills if relevant to the current task.`,
|
|
110
|
+
);
|
|
97
111
|
}
|
|
98
112
|
}
|
|
99
113
|
|
|
100
114
|
projectContext = contextParts.join("\n\n---\n\n");
|
|
101
|
-
|
|
115
|
+
|
|
102
116
|
if (projectContext && ctx.hasUI) {
|
|
103
117
|
ctx.ui.notify("XTRM-Loader: Project context and skills indexed", "info");
|
|
104
118
|
}
|
|
@@ -106,21 +120,21 @@ export default function (pi: ExtensionAPI) {
|
|
|
106
120
|
|
|
107
121
|
pi.on("before_agent_start", async (event) => {
|
|
108
122
|
const parts: string[] = [];
|
|
109
|
-
|
|
123
|
+
|
|
110
124
|
// Prepend using-xtrm skill (session operating manual)
|
|
111
125
|
if (usingXtrmContent) {
|
|
112
126
|
parts.push("# XTRM Session Operating Manual\n\n" + usingXtrmContent);
|
|
113
127
|
}
|
|
114
|
-
|
|
128
|
+
|
|
115
129
|
// Append project context
|
|
116
130
|
if (projectContext) {
|
|
117
131
|
parts.push("# Project Intelligence Context\n\n" + projectContext);
|
|
118
132
|
}
|
|
119
|
-
|
|
133
|
+
|
|
120
134
|
if (parts.length === 0) return undefined;
|
|
121
135
|
|
|
122
136
|
return {
|
|
123
|
-
systemPrompt: event.systemPrompt + "\n\n" + parts.join("\n\n---\n\n")
|
|
137
|
+
systemPrompt: event.systemPrompt + "\n\n" + parts.join("\n\n---\n\n"),
|
|
124
138
|
};
|
|
125
139
|
});
|
|
126
140
|
}
|
|
@@ -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/hooks/hooks.json
CHANGED
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
"type": "command",
|
|
17
17
|
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/quality-check-env.mjs",
|
|
18
18
|
"timeout": 5000
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"type": "command",
|
|
22
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/xtrm-session-logger.mjs",
|
|
23
|
+
"timeout": 3000
|
|
19
24
|
}
|
|
20
25
|
]
|
|
21
26
|
}
|
|
@@ -82,6 +87,15 @@
|
|
|
82
87
|
"timeout": 10000
|
|
83
88
|
}
|
|
84
89
|
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"hooks": [
|
|
93
|
+
{
|
|
94
|
+
"type": "command",
|
|
95
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/xtrm-tool-logger.mjs",
|
|
96
|
+
"timeout": 3000
|
|
97
|
+
}
|
|
98
|
+
]
|
|
85
99
|
}
|
|
86
100
|
],
|
|
87
101
|
"Stop": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xtrm-tools",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.27",
|
|
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);
|