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.
Files changed (252) hide show
  1. package/.claude-plugin/marketplace.json +19 -0
  2. package/.claude-plugin/plugin.json +9 -0
  3. package/cli/dist/index.cjs +59 -52
  4. package/cli/dist/index.cjs.map +1 -1
  5. package/cli/package.json +1 -1
  6. package/hooks/beads-claim-sync.mjs +1 -3
  7. package/package.json +5 -1
  8. package/plugins/xtrm-tools/.claude-plugin/plugin.json +9 -0
  9. package/plugins/xtrm-tools/.mcp.json +18 -0
  10. package/plugins/xtrm-tools/hooks/README.md +61 -0
  11. package/plugins/xtrm-tools/hooks/beads-claim-sync.mjs +223 -0
  12. package/plugins/xtrm-tools/hooks/beads-commit-gate.mjs +70 -0
  13. package/plugins/xtrm-tools/hooks/beads-compact-restore.mjs +69 -0
  14. package/plugins/xtrm-tools/hooks/beads-compact-save.mjs +51 -0
  15. package/plugins/xtrm-tools/hooks/beads-edit-gate.mjs +85 -0
  16. package/plugins/xtrm-tools/hooks/beads-gate-core.mjs +236 -0
  17. package/plugins/xtrm-tools/hooks/beads-gate-messages.mjs +68 -0
  18. package/plugins/xtrm-tools/hooks/beads-gate-utils.mjs +194 -0
  19. package/plugins/xtrm-tools/hooks/beads-memory-gate.mjs +81 -0
  20. package/plugins/xtrm-tools/hooks/beads-stop-gate.mjs +53 -0
  21. package/plugins/xtrm-tools/hooks/gitnexus/gitnexus-hook.cjs +222 -0
  22. package/plugins/xtrm-tools/hooks/hooks.json +115 -0
  23. package/plugins/xtrm-tools/hooks/quality-check-env.mjs +79 -0
  24. package/plugins/xtrm-tools/hooks/quality-check.cjs +1286 -0
  25. package/plugins/xtrm-tools/hooks/quality-check.py +345 -0
  26. package/plugins/xtrm-tools/hooks/statusline.mjs +145 -0
  27. package/plugins/xtrm-tools/hooks/using-xtrm-reminder.mjs +35 -0
  28. package/plugins/xtrm-tools/hooks/worktree-boundary.mjs +33 -0
  29. package/plugins/xtrm-tools/hooks/xtrm-logger.mjs +123 -0
  30. package/plugins/xtrm-tools/hooks/xtrm-session-logger.mjs +27 -0
  31. package/plugins/xtrm-tools/hooks/xtrm-tool-logger.mjs +53 -0
  32. package/plugins/xtrm-tools/skills/README.txt +31 -0
  33. package/plugins/xtrm-tools/skills/clean-code/SKILL.md +201 -0
  34. package/plugins/xtrm-tools/skills/creating-service-skills/SKILL.md +433 -0
  35. package/plugins/xtrm-tools/skills/creating-service-skills/references/script_quality_standards.md +425 -0
  36. package/plugins/xtrm-tools/skills/creating-service-skills/references/service_skill_system_guide.md +278 -0
  37. package/plugins/xtrm-tools/skills/creating-service-skills/scripts/bootstrap.py +326 -0
  38. package/plugins/xtrm-tools/skills/creating-service-skills/scripts/deep_dive.py +304 -0
  39. package/plugins/xtrm-tools/skills/creating-service-skills/scripts/scaffolder.py +482 -0
  40. package/plugins/xtrm-tools/skills/delegating/SKILL.md +196 -0
  41. package/plugins/xtrm-tools/skills/delegating/config.yaml +210 -0
  42. package/plugins/xtrm-tools/skills/delegating/references/orchestration-protocols.md +41 -0
  43. package/plugins/xtrm-tools/skills/docker-expert/SKILL.md +409 -0
  44. package/plugins/xtrm-tools/skills/documenting/CHANGELOG.md +23 -0
  45. package/plugins/xtrm-tools/skills/documenting/README.md +148 -0
  46. package/plugins/xtrm-tools/skills/documenting/SKILL.md +113 -0
  47. package/plugins/xtrm-tools/skills/documenting/examples/example_pattern.md +70 -0
  48. package/plugins/xtrm-tools/skills/documenting/examples/example_reference.md +70 -0
  49. package/plugins/xtrm-tools/skills/documenting/examples/example_ssot_analytics.md +64 -0
  50. package/plugins/xtrm-tools/skills/documenting/examples/example_workflow.md +141 -0
  51. package/plugins/xtrm-tools/skills/documenting/references/changelog-format.md +97 -0
  52. package/plugins/xtrm-tools/skills/documenting/references/metadata-schema.md +136 -0
  53. package/plugins/xtrm-tools/skills/documenting/references/taxonomy.md +81 -0
  54. package/plugins/xtrm-tools/skills/documenting/references/versioning-rules.md +78 -0
  55. package/plugins/xtrm-tools/skills/documenting/scripts/bump_version.sh +60 -0
  56. package/plugins/xtrm-tools/skills/documenting/scripts/changelog/__init__.py +0 -0
  57. package/plugins/xtrm-tools/skills/documenting/scripts/changelog/add_entry.py +216 -0
  58. package/plugins/xtrm-tools/skills/documenting/scripts/changelog/bump_release.py +117 -0
  59. package/plugins/xtrm-tools/skills/documenting/scripts/changelog/init_changelog.py +54 -0
  60. package/plugins/xtrm-tools/skills/documenting/scripts/changelog/validate_changelog.py +128 -0
  61. package/plugins/xtrm-tools/skills/documenting/scripts/drift_detector.py +266 -0
  62. package/plugins/xtrm-tools/skills/documenting/scripts/generate_template.py +311 -0
  63. package/plugins/xtrm-tools/skills/documenting/scripts/list_by_category.sh +84 -0
  64. package/plugins/xtrm-tools/skills/documenting/scripts/orchestrator.py +255 -0
  65. package/plugins/xtrm-tools/skills/documenting/scripts/validate_metadata.py +242 -0
  66. package/plugins/xtrm-tools/skills/documenting/templates/CHANGELOG.md.template +13 -0
  67. package/plugins/xtrm-tools/skills/documenting/tests/integration_test.sh +70 -0
  68. package/plugins/xtrm-tools/skills/documenting/tests/test_changelog.py +201 -0
  69. package/plugins/xtrm-tools/skills/documenting/tests/test_drift_detector.py +80 -0
  70. package/plugins/xtrm-tools/skills/documenting/tests/test_orchestrator.py +52 -0
  71. package/plugins/xtrm-tools/skills/documenting/tests/test_validate_metadata.py +64 -0
  72. package/plugins/xtrm-tools/skills/find-skills/SKILL.md +133 -0
  73. package/plugins/xtrm-tools/skills/gitnexus-debugging/SKILL.md +85 -0
  74. package/plugins/xtrm-tools/skills/gitnexus-exploring/SKILL.md +75 -0
  75. package/plugins/xtrm-tools/skills/gitnexus-impact-analysis/SKILL.md +94 -0
  76. package/plugins/xtrm-tools/skills/gitnexus-refactoring/SKILL.md +113 -0
  77. package/plugins/xtrm-tools/skills/hook-development/SKILL.md +797 -0
  78. package/plugins/xtrm-tools/skills/hook-development/examples/load-context.sh +55 -0
  79. package/plugins/xtrm-tools/skills/hook-development/examples/quality-check.js +1168 -0
  80. package/plugins/xtrm-tools/skills/hook-development/examples/validate-bash.sh +43 -0
  81. package/plugins/xtrm-tools/skills/hook-development/examples/validate-write.sh +38 -0
  82. package/plugins/xtrm-tools/skills/hook-development/references/advanced.md +527 -0
  83. package/plugins/xtrm-tools/skills/hook-development/references/migration.md +369 -0
  84. package/plugins/xtrm-tools/skills/hook-development/references/patterns.md +412 -0
  85. package/plugins/xtrm-tools/skills/hook-development/scripts/README.md +164 -0
  86. package/plugins/xtrm-tools/skills/hook-development/scripts/hook-linter.sh +153 -0
  87. package/plugins/xtrm-tools/skills/hook-development/scripts/test-hook.sh +252 -0
  88. package/plugins/xtrm-tools/skills/hook-development/scripts/validate-hook-schema.sh +159 -0
  89. package/plugins/xtrm-tools/skills/obsidian-cli/SKILL.md +106 -0
  90. package/plugins/xtrm-tools/skills/orchestrating-agents/SKILL.md +135 -0
  91. package/plugins/xtrm-tools/skills/orchestrating-agents/config.yaml +45 -0
  92. package/plugins/xtrm-tools/skills/orchestrating-agents/references/agent-context-integration.md +37 -0
  93. package/plugins/xtrm-tools/skills/orchestrating-agents/references/examples.md +45 -0
  94. package/plugins/xtrm-tools/skills/orchestrating-agents/references/handover-protocol.md +31 -0
  95. package/plugins/xtrm-tools/skills/orchestrating-agents/references/workflows.md +42 -0
  96. package/plugins/xtrm-tools/skills/orchestrating-agents/scripts/detect_neighbors.py +23 -0
  97. package/plugins/xtrm-tools/skills/prompt-improving/README.md +162 -0
  98. package/plugins/xtrm-tools/skills/prompt-improving/SKILL.md +74 -0
  99. package/plugins/xtrm-tools/skills/prompt-improving/references/analysis_commands.md +24 -0
  100. package/plugins/xtrm-tools/skills/prompt-improving/references/chain_of_thought.md +24 -0
  101. package/plugins/xtrm-tools/skills/prompt-improving/references/mcp_definitions.md +20 -0
  102. package/plugins/xtrm-tools/skills/prompt-improving/references/multishot.md +23 -0
  103. package/plugins/xtrm-tools/skills/prompt-improving/references/xml_core.md +60 -0
  104. package/plugins/xtrm-tools/skills/python-testing/SKILL.md +815 -0
  105. package/plugins/xtrm-tools/skills/scoping-service-skills/SKILL.md +231 -0
  106. package/plugins/xtrm-tools/skills/scoping-service-skills/scripts/scope.py +74 -0
  107. package/plugins/xtrm-tools/skills/senior-backend/SKILL.md +209 -0
  108. package/plugins/xtrm-tools/skills/senior-backend/references/api_design_patterns.md +103 -0
  109. package/plugins/xtrm-tools/skills/senior-backend/references/backend_security_practices.md +103 -0
  110. package/plugins/xtrm-tools/skills/senior-backend/references/database_optimization_guide.md +103 -0
  111. package/plugins/xtrm-tools/skills/senior-backend/scripts/api_load_tester.py +114 -0
  112. package/plugins/xtrm-tools/skills/senior-backend/scripts/api_scaffolder.py +114 -0
  113. package/plugins/xtrm-tools/skills/senior-backend/scripts/database_migration_tool.py +114 -0
  114. package/plugins/xtrm-tools/skills/senior-data-scientist/SKILL.md +226 -0
  115. package/plugins/xtrm-tools/skills/senior-data-scientist/references/experiment_design_frameworks.md +80 -0
  116. package/plugins/xtrm-tools/skills/senior-data-scientist/references/feature_engineering_patterns.md +80 -0
  117. package/plugins/xtrm-tools/skills/senior-data-scientist/references/statistical_methods_advanced.md +80 -0
  118. package/plugins/xtrm-tools/skills/senior-data-scientist/scripts/experiment_designer.py +100 -0
  119. package/plugins/xtrm-tools/skills/senior-data-scientist/scripts/feature_engineering_pipeline.py +100 -0
  120. package/plugins/xtrm-tools/skills/senior-data-scientist/scripts/model_evaluation_suite.py +100 -0
  121. package/plugins/xtrm-tools/skills/senior-devops/SKILL.md +209 -0
  122. package/plugins/xtrm-tools/skills/senior-devops/references/cicd_pipeline_guide.md +103 -0
  123. package/plugins/xtrm-tools/skills/senior-devops/references/deployment_strategies.md +103 -0
  124. package/plugins/xtrm-tools/skills/senior-devops/references/infrastructure_as_code.md +103 -0
  125. package/plugins/xtrm-tools/skills/senior-devops/scripts/deployment_manager.py +114 -0
  126. package/plugins/xtrm-tools/skills/senior-devops/scripts/pipeline_generator.py +114 -0
  127. package/plugins/xtrm-tools/skills/senior-devops/scripts/terraform_scaffolder.py +114 -0
  128. package/plugins/xtrm-tools/skills/senior-security/SKILL.md +209 -0
  129. package/plugins/xtrm-tools/skills/senior-security/references/cryptography_implementation.md +103 -0
  130. package/plugins/xtrm-tools/skills/senior-security/references/penetration_testing_guide.md +103 -0
  131. package/plugins/xtrm-tools/skills/senior-security/references/security_architecture_patterns.md +103 -0
  132. package/plugins/xtrm-tools/skills/senior-security/scripts/pentest_automator.py +114 -0
  133. package/plugins/xtrm-tools/skills/senior-security/scripts/security_auditor.py +114 -0
  134. package/plugins/xtrm-tools/skills/senior-security/scripts/threat_modeler.py +114 -0
  135. package/plugins/xtrm-tools/skills/skill-creator/LICENSE.txt +202 -0
  136. package/plugins/xtrm-tools/skills/skill-creator/SKILL.md +479 -0
  137. package/plugins/xtrm-tools/skills/skill-creator/agents/analyzer.md +274 -0
  138. package/plugins/xtrm-tools/skills/skill-creator/agents/comparator.md +202 -0
  139. package/plugins/xtrm-tools/skills/skill-creator/agents/grader.md +223 -0
  140. package/plugins/xtrm-tools/skills/skill-creator/assets/eval_review.html +146 -0
  141. package/plugins/xtrm-tools/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  142. package/plugins/xtrm-tools/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  143. package/plugins/xtrm-tools/skills/skill-creator/references/schemas.md +430 -0
  144. package/plugins/xtrm-tools/skills/skill-creator/scripts/__init__.py +0 -0
  145. package/plugins/xtrm-tools/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  146. package/plugins/xtrm-tools/skills/skill-creator/scripts/generate_report.py +326 -0
  147. package/plugins/xtrm-tools/skills/skill-creator/scripts/improve_description.py +248 -0
  148. package/plugins/xtrm-tools/skills/skill-creator/scripts/package_skill.py +136 -0
  149. package/plugins/xtrm-tools/skills/skill-creator/scripts/quick_validate.py +103 -0
  150. package/plugins/xtrm-tools/skills/skill-creator/scripts/run_eval.py +310 -0
  151. package/plugins/xtrm-tools/skills/skill-creator/scripts/run_loop.py +332 -0
  152. package/plugins/xtrm-tools/skills/skill-creator/scripts/utils.py +47 -0
  153. package/plugins/xtrm-tools/skills/sync-docs/SKILL.md +155 -0
  154. package/plugins/xtrm-tools/skills/sync-docs/evals/evals.json +89 -0
  155. package/plugins/xtrm-tools/skills/sync-docs/references/doc-structure.md +99 -0
  156. package/plugins/xtrm-tools/skills/sync-docs/references/schema.md +103 -0
  157. package/plugins/xtrm-tools/skills/sync-docs/scripts/changelog/add_entry.py +216 -0
  158. package/plugins/xtrm-tools/skills/sync-docs/scripts/context_gatherer.py +240 -0
  159. package/plugins/xtrm-tools/skills/sync-docs/scripts/doc_structure_analyzer.py +495 -0
  160. package/plugins/xtrm-tools/skills/sync-docs/scripts/drift_detector.py +563 -0
  161. package/plugins/xtrm-tools/skills/sync-docs/scripts/validate_doc.py +365 -0
  162. package/plugins/xtrm-tools/skills/sync-docs/scripts/validate_metadata.py +185 -0
  163. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/benchmark.json +293 -0
  164. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/benchmark.md +13 -0
  165. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/eval_metadata.json +27 -0
  166. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/with_skill/outputs/result.md +210 -0
  167. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/with_skill/run-1/grading.json +28 -0
  168. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/with_skill/run-1/timing.json +1 -0
  169. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/without_skill/outputs/result.md +101 -0
  170. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/without_skill/run-1/grading.json +28 -0
  171. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/without_skill/run-1/timing.json +5 -0
  172. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-doc-audit/without_skill/timing.json +5 -0
  173. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/eval_metadata.json +27 -0
  174. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/with_skill/outputs/result.md +198 -0
  175. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/with_skill/run-1/grading.json +28 -0
  176. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/with_skill/run-1/timing.json +1 -0
  177. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/without_skill/outputs/result.md +94 -0
  178. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/without_skill/run-1/grading.json +28 -0
  179. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-fix-mode/without_skill/run-1/timing.json +1 -0
  180. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/eval_metadata.json +27 -0
  181. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/with_skill/outputs/result.md +237 -0
  182. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/with_skill/run-1/grading.json +28 -0
  183. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/with_skill/run-1/timing.json +1 -0
  184. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/without_skill/outputs/result.md +134 -0
  185. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/without_skill/run-1/grading.json +28 -0
  186. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/without_skill/run-1/timing.json +1 -0
  187. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/benchmark.json +297 -0
  188. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/benchmark.md +13 -0
  189. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/eval_metadata.json +27 -0
  190. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/with_skill/outputs/result.md +137 -0
  191. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/with_skill/run-1/grading.json +92 -0
  192. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/with_skill/run-1/timing.json +1 -0
  193. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/without_skill/outputs/result.md +134 -0
  194. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/without_skill/run-1/grading.json +86 -0
  195. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-doc-audit/without_skill/run-1/timing.json +1 -0
  196. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/eval_metadata.json +27 -0
  197. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/with_skill/outputs/result.md +193 -0
  198. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/with_skill/run-1/grading.json +72 -0
  199. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/with_skill/run-1/timing.json +1 -0
  200. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/without_skill/outputs/result.md +211 -0
  201. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/without_skill/run-1/grading.json +91 -0
  202. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-fix-mode/without_skill/run-1/timing.json +5 -0
  203. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/eval_metadata.json +27 -0
  204. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/with_skill/outputs/result.md +182 -0
  205. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/with_skill/run-1/grading.json +95 -0
  206. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/with_skill/run-1/timing.json +1 -0
  207. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/without_skill/outputs/result.md +222 -0
  208. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/without_skill/run-1/grading.json +88 -0
  209. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/without_skill/run-1/timing.json +5 -0
  210. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/benchmark.json +298 -0
  211. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/benchmark.md +13 -0
  212. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/eval_metadata.json +27 -0
  213. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/with_skill/outputs/result.md +125 -0
  214. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/with_skill/run-1/grading.json +97 -0
  215. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/with_skill/run-1/timing.json +5 -0
  216. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/without_skill/outputs/result.md +144 -0
  217. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/without_skill/run-1/grading.json +78 -0
  218. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-doc-audit/without_skill/run-1/timing.json +5 -0
  219. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/eval_metadata.json +27 -0
  220. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/with_skill/outputs/result.md +104 -0
  221. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/with_skill/run-1/grading.json +91 -0
  222. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/with_skill/run-1/timing.json +5 -0
  223. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/without_skill/outputs/result.md +79 -0
  224. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/without_skill/run-1/grading.json +82 -0
  225. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-fix-mode/without_skill/run-1/timing.json +5 -0
  226. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/eval_metadata.json +27 -0
  227. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase1_context.json +302 -0
  228. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase2_drift.txt +33 -0
  229. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase3_analysis.json +114 -0
  230. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase4_fix.txt +118 -0
  231. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase5_validate.txt +38 -0
  232. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/result.md +158 -0
  233. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/run-1/grading.json +95 -0
  234. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/run-1/timing.json +5 -0
  235. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/without_skill/outputs/result.md +71 -0
  236. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/without_skill/run-1/grading.json +90 -0
  237. package/plugins/xtrm-tools/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/without_skill/run-1/timing.json +5 -0
  238. package/plugins/xtrm-tools/skills/test-planning/SKILL.md +208 -0
  239. package/plugins/xtrm-tools/skills/test-planning/evals/evals.json +23 -0
  240. package/plugins/xtrm-tools/skills/updating-service-skills/SKILL.md +136 -0
  241. package/plugins/xtrm-tools/skills/updating-service-skills/scripts/drift_detector.py +222 -0
  242. package/plugins/xtrm-tools/skills/using-TDD/SKILL.md +410 -0
  243. package/plugins/xtrm-tools/skills/using-quality-gates/SKILL.md +254 -0
  244. package/plugins/xtrm-tools/skills/using-serena-lsp/README.md +8 -0
  245. package/plugins/xtrm-tools/skills/using-serena-lsp/REFERENCE.md +194 -0
  246. package/plugins/xtrm-tools/skills/using-serena-lsp/SKILL.md +82 -0
  247. package/plugins/xtrm-tools/skills/using-service-skills/SKILL.md +108 -0
  248. package/plugins/xtrm-tools/skills/using-service-skills/scripts/cataloger.py +74 -0
  249. package/plugins/xtrm-tools/skills/using-service-skills/scripts/skill_activator.py +152 -0
  250. package/plugins/xtrm-tools/skills/using-service-skills/scripts/test_skill_activator.py +58 -0
  251. package/plugins/xtrm-tools/skills/using-xtrm/SKILL.md +124 -0
  252. package/plugins/xtrm-tools/skills/xt-end/SKILL.md +128 -0
@@ -0,0 +1,236 @@
1
+ #!/usr/bin/env node
2
+ // beads-gate-core.mjs — pure decision functions for beads gate hooks
3
+ // Import from sibling hooks using: import { ... } from './beads-gate-core.mjs';
4
+ //
5
+ // All functions are pure: they return decision objects, never call process.exit()
6
+ // or write to stdout/stderr. Side effects belong in entrypoint wrappers.
7
+ //
8
+ // Dependencies: beads-gate-utils.mjs (adapters)
9
+
10
+ import { readFileSync } from 'node:fs';
11
+ import { resolve } from 'node:path';
12
+ import {
13
+ resolveCwd,
14
+ resolveSessionId,
15
+ isBeadsProject,
16
+ getSessionClaim,
17
+ getTotalWork,
18
+ getInProgress,
19
+ isIssueInProgress,
20
+ resolveWorktreeRoot,
21
+ } from './beads-gate-utils.mjs';
22
+
23
+ // ── Input parsing ────────────────────────────────────────────────────────────
24
+
25
+ /**
26
+ * Read and parse hook input from stdin. Returns null on parse error.
27
+ * Entrypoints should exit 0 if this returns null (fail-open).
28
+ */
29
+ export function readHookInput() {
30
+ try {
31
+ return JSON.parse(readFileSync(0, 'utf8'));
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+
37
+ // ── Session context resolution ───────────────────────────────────────────────
38
+
39
+ /**
40
+ * Resolve session context from hook input.
41
+ * Returns { cwd, sessionId, isBeadsProject } or null if cwd can't be resolved.
42
+ */
43
+ export function resolveSessionContext(input) {
44
+ const cwd = resolveCwd(input);
45
+ if (!cwd) return null;
46
+ return {
47
+ cwd,
48
+ sessionId: resolveSessionId(input),
49
+ isBeadsProject: isBeadsProject(cwd),
50
+ };
51
+ }
52
+
53
+ // ── Claim and work state resolution ──────────────────────────────────────────
54
+
55
+ /**
56
+ * Resolve the claim and work state for a session.
57
+ * Returns { claimed, claimId, totalWork, inProgress } or null if bd unavailable.
58
+ */
59
+ export function resolveClaimAndWorkState(ctx) {
60
+ if (!ctx.isBeadsProject) {
61
+ return { claimed: false, claimId: null, totalWork: 0, inProgress: null };
62
+ }
63
+
64
+ const totalWork = getTotalWork(ctx.cwd);
65
+ if (totalWork === null) return null; // bd unavailable
66
+
67
+ const inProgress = getInProgress(ctx.cwd);
68
+
69
+ if (ctx.sessionId) {
70
+ const claimId = getSessionClaim(ctx.sessionId, ctx.cwd);
71
+ if (claimId === null) return null; // bd kv unavailable
72
+ return {
73
+ claimed: !!claimId,
74
+ claimId: claimId || null,
75
+ claimInProgress: claimId ? isIssueInProgress(claimId, ctx.cwd) : false,
76
+ totalWork,
77
+ inProgress,
78
+ };
79
+ }
80
+
81
+ // No session_id: fallback to global in_progress check
82
+ return {
83
+ claimed: false,
84
+ claimId: null,
85
+ claimInProgress: false,
86
+ totalWork,
87
+ inProgress,
88
+ };
89
+ }
90
+
91
+ // ── Decision functions ───────────────────────────────────────────────────────
92
+
93
+ /**
94
+ * Decide whether a file edit is within the active worktree boundary.
95
+ * If the session cwd is inside .xtrm/worktrees/<name>, block any edit whose
96
+ * resolved path falls outside that worktree root.
97
+ * Returns { allow: boolean, filePath?: string, worktreeRoot?: string }
98
+ */
99
+ export function decideWorktreeBoundary(input, cwd) {
100
+ const filePath = input?.tool_input?.file_path;
101
+ if (!filePath) return { allow: true };
102
+
103
+ const worktreeRoot = resolveWorktreeRoot(cwd);
104
+ if (!worktreeRoot) return { allow: true }; // not in a worktree — no constraint
105
+
106
+ const abs = resolve(cwd, filePath);
107
+ if (abs === worktreeRoot || abs.startsWith(worktreeRoot + '/')) return { allow: true };
108
+
109
+ return { allow: false, filePath: abs, worktreeRoot };
110
+ }
111
+
112
+ /**
113
+ * Decide whether to allow or block an edit operation.
114
+ * Returns { allow: boolean, reason?: string, sessionId?: string }
115
+ */
116
+ export function decideEditGate(ctx, state) {
117
+ // Not a beads project → allow
118
+ if (!ctx.isBeadsProject) {
119
+ return { allow: true };
120
+ }
121
+
122
+ // bd unavailable → fail open
123
+ if (state === null) {
124
+ return { allow: true };
125
+ }
126
+
127
+ // Session has an active claim → allow
128
+ if (state.claimed) {
129
+ return { allow: true };
130
+ }
131
+
132
+ // No trackable work → allow (clean-start state)
133
+ if (state.totalWork === 0) {
134
+ return { allow: true };
135
+ }
136
+
137
+ // Has session_id but no claim + has work → block
138
+ if (ctx.sessionId) {
139
+ return {
140
+ allow: false,
141
+ reason: 'no_claim_with_work',
142
+ sessionId: ctx.sessionId,
143
+ };
144
+ }
145
+
146
+ // Fallback: no session_id, check global in_progress
147
+ if (state.inProgress && state.inProgress.count > 0) {
148
+ return { allow: true };
149
+ }
150
+
151
+ // No session_id, no in_progress, but has open work → block
152
+ if (state.totalWork > 0) {
153
+ return {
154
+ allow: false,
155
+ reason: 'no_claim_fallback',
156
+ };
157
+ }
158
+
159
+ return { allow: true };
160
+ }
161
+
162
+ /**
163
+ * Decide whether to allow or block a git commit operation.
164
+ * Returns { allow: boolean, reason?: string, summary?: string, claimed?: string }
165
+ */
166
+ export function decideCommitGate(ctx, state) {
167
+ // Not a beads project → allow
168
+ if (!ctx.isBeadsProject) {
169
+ return { allow: true };
170
+ }
171
+
172
+ // bd unavailable → fail open
173
+ if (state === null) {
174
+ return { allow: true };
175
+ }
176
+
177
+ // No active claim → allow (nothing to close)
178
+ if (!state.claimed) {
179
+ return { allow: true };
180
+ }
181
+
182
+ // Claimed issue is no longer in_progress → allow (closed or transferred to another agent)
183
+ if (!state.claimInProgress) {
184
+ return { allow: true };
185
+ }
186
+
187
+ // Session's own claimed issue is still in_progress → block (need to close first)
188
+ return {
189
+ allow: false,
190
+ reason: 'unclosed_claim',
191
+ summary: ` Claimed: ${state.claimId} (still in_progress)`,
192
+ claimed: state.claimId,
193
+ };
194
+ }
195
+
196
+ /**
197
+ * Decide whether to allow or block a stop operation.
198
+ * Returns { allow: boolean, reason?: string, summary?: string, claimed?: string }
199
+ */
200
+ export function decideStopGate(ctx, state) {
201
+ // Not a beads project → allow
202
+ if (!ctx.isBeadsProject) {
203
+ return { allow: true };
204
+ }
205
+
206
+ // bd unavailable → fail open
207
+ if (state === null) {
208
+ return { allow: true };
209
+ }
210
+
211
+ // No active claim → allow
212
+ if (!state.claimed) {
213
+ // But check for global in_progress (no session_id fallback)
214
+ if (!ctx.sessionId && state.inProgress && state.inProgress.count > 0) {
215
+ return {
216
+ allow: false,
217
+ reason: 'global_in_progress',
218
+ summary: state.inProgress.summary,
219
+ };
220
+ }
221
+ return { allow: true };
222
+ }
223
+
224
+ // Claimed issue is no longer in_progress → allow (stale claim)
225
+ if (!state.claimInProgress) {
226
+ return { allow: true };
227
+ }
228
+
229
+ // Session's own claimed issue is still in_progress → block
230
+ return {
231
+ allow: false,
232
+ reason: 'unclosed_claim',
233
+ summary: ` Claimed: ${state.claimId} (still in_progress)`,
234
+ claimed: state.claimId,
235
+ };
236
+ }
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ // beads-gate-messages.mjs — centralized message templates for beads gate hooks
3
+ // Import from sibling hooks using: import { ... } from './beads-gate-messages.mjs';
4
+ //
5
+ // All user-facing strings live here. Edit this file to change messaging.
6
+ // Policy logic lives in beads-gate-core.mjs.
7
+
8
+ // ── Shared workflow steps ────────────────────────────────────────────
9
+
10
+ export const SESSION_CLOSE_PROTOCOL =
11
+ ' bd close <id> --reason="..."\n' +
12
+ ' xt end\n';
13
+
14
+ export const COMMIT_NEXT_STEPS =
15
+ ' bd close <id> --reason="..." ← closes issue + auto-commits\n' +
16
+ ' xt end ← push, PR, merge, worktree cleanup\n';
17
+
18
+ // ── Edit gate messages ───────────────────────────────────────────
19
+
20
+ export function editBlockMessage(_sessionId) {
21
+ return (
22
+ '🚫 No active claim — claim an issue first.\n' +
23
+ ' bd update <id> --claim\n'
24
+ );
25
+ }
26
+
27
+ export function editBlockFallbackMessage() {
28
+ return (
29
+ '🚫 No active issue — create one before editing.\n' +
30
+ ' bd create --title="<task>" --type=task --priority=2\n' +
31
+ ' bd update <id> --claim\n'
32
+ );
33
+ }
34
+
35
+ // ── Commit gate messages ─────────────────────────────────────────
36
+
37
+ export function commitBlockMessage(summary, claimed) {
38
+ const issueSummary = summary ?? ` Claimed: ${claimed}`;
39
+ return (
40
+ '🚫 Close open issues before committing.\n\n' +
41
+ `${issueSummary}\n\n` +
42
+ 'Next steps:\n' + COMMIT_NEXT_STEPS
43
+ );
44
+ }
45
+
46
+ // ── Stop gate messages ───────────────────────────────────────────
47
+
48
+ export function stopBlockMessage(summary, claimed) {
49
+ const issueSummary = summary ?? ` Claimed: ${claimed}`;
50
+ return (
51
+ '🚫 Unresolved issues — close before stopping.\n\n' +
52
+ `${issueSummary}\n\n` +
53
+ 'Next steps:\n' + SESSION_CLOSE_PROTOCOL
54
+ );
55
+ }
56
+
57
+ // ── Memory gate messages ─────────────────────────────────────────
58
+
59
+ export function memoryPromptMessage(claimId) {
60
+ const claimLine = claimId ? `claim \`${claimId}\` was closed.\n` : '';
61
+ return (
62
+ `\u25cf Memory gate: ${claimLine}` +
63
+ 'Ask: "Would this be useful in 14 days on a fresh session?"\n' +
64
+ ' YES → `bd remember "<insight>"`\n' +
65
+ ' NO → note "nothing to persist"\n' +
66
+ ' Then: `touch .beads/.memory-gate-done`\n'
67
+ );
68
+ }
@@ -0,0 +1,194 @@
1
+ #!/usr/bin/env node
2
+ // beads-gate-utils.mjs — shared infrastructure for beads gate hooks
3
+ // Import from sibling hooks using: import { ... } from './beads-gate-utils.mjs';
4
+ // Static ES module imports resolve relative to the importing file's location,
5
+ // not CWD, so this works regardless of the project directory.
6
+
7
+ import { execSync } from 'node:child_process';
8
+ import { existsSync } from 'node:fs';
9
+ import { join } from 'node:path';
10
+
11
+ /** Resolve project cwd from hook input JSON. */
12
+ export function resolveCwd(input) {
13
+ return input.cwd ?? process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
14
+ }
15
+
16
+ /**
17
+ * Resolve a stable session key for beads hooks.
18
+ * Priority: explicit hook session id -> cwd fallback.
19
+ */
20
+ export function resolveSessionId(input) {
21
+ return input?.session_id ?? input?.sessionId ?? resolveCwd(input);
22
+ }
23
+
24
+ /** Return true if the directory contains a .beads project. */
25
+ export function isBeadsProject(cwd) {
26
+ return existsSync(join(cwd, '.beads'));
27
+ }
28
+
29
+ /**
30
+ * Get the claimed issue ID for a session from bd kv.
31
+ * Returns: issue ID string if claimed, '' if not set, null if bd kv unavailable.
32
+ * Note: bd kv get exits 1 for missing keys — execSync throws, so we check err.status.
33
+ */
34
+ export function getSessionClaim(sessionId, cwd) {
35
+ try {
36
+ return execSync(`bd kv get "claimed:${sessionId}"`, {
37
+ encoding: 'utf8',
38
+ cwd,
39
+ stdio: ['pipe', 'pipe', 'pipe'],
40
+ timeout: 5000,
41
+ }).trim();
42
+ } catch (err) {
43
+ if (err.status === 1) return ''; // key not found — no claim
44
+ return null; // command failed — bd kv unavailable
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Parse work counts from a bd list output string.
50
+ * Reads the "Total: N issues (X open, Y in progress)" summary line.
51
+ * Returns { open, inProgress } or null if the line is absent.
52
+ *
53
+ * This is more reliable than counting symbols or tokens: the Total line is
54
+ * a structured summary that doesn't depend on status-legend text or box-drawing
55
+ * characters, and it's present in all non-empty bd list outputs.
56
+ */
57
+ function parseCounts(output) {
58
+ const m = output.match(/Total:\s*\d+\s+issues?\s*\((\d+)\s+open,\s*(\d+)\s+in progress\)/);
59
+ if (!m) return null;
60
+ return { open: parseInt(m[1], 10), inProgress: parseInt(m[2], 10) };
61
+ }
62
+
63
+ /**
64
+ * Get in_progress issues as { count, summary }.
65
+ * Returns null if bd is unavailable.
66
+ */
67
+ export function getInProgress(cwd) {
68
+ try {
69
+ const output = execSync('bd list --status=in_progress', {
70
+ encoding: 'utf8', cwd, stdio: ['pipe', 'pipe', 'pipe'], timeout: 8000,
71
+ });
72
+ const counts = parseCounts(output);
73
+ return {
74
+ count: counts?.inProgress ?? 0,
75
+ summary: output.trim(),
76
+ };
77
+ } catch {
78
+ return null;
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Return true if a specific issue ID is currently in in_progress status.
84
+ * Used by commit/stop gates to scope the check to the session's own claimed issue.
85
+ * Returns false (fail open) if bd is unavailable.
86
+ */
87
+ export function isIssueInProgress(issueId, cwd) {
88
+ if (!issueId) return false;
89
+ try {
90
+ const output = execSync('bd list --status=in_progress', {
91
+ encoding: 'utf8', cwd, stdio: ['pipe', 'pipe', 'pipe'], timeout: 8000,
92
+ });
93
+ return output.includes(issueId);
94
+ } catch {
95
+ return false;
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Count total trackable work (open + in_progress issues) using a single bd list call.
101
+ * Returns the count, or null if bd is unavailable.
102
+ */
103
+ export function getTotalWork(cwd) {
104
+ try {
105
+ // Use default status filter (non-closed) and parse Total summary.
106
+ // Repeating --status is not additive in bd CLI and can collapse to one status.
107
+ const output = execSync('bd list', {
108
+ encoding: 'utf8', cwd, stdio: ['pipe', 'pipe', 'pipe'], timeout: 8000,
109
+ });
110
+ const counts = parseCounts(output);
111
+ if (!counts) return 0; // "No issues found." — nothing to track
112
+ return counts.open + counts.inProgress;
113
+ } catch {
114
+ return null;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Get the closed-this-session issue ID for a session from bd kv.
120
+ * Returns: issue ID string if set, '' if not set, null if bd kv unavailable.
121
+ */
122
+ export function getClosedThisSession(sessionId, cwd) {
123
+ try {
124
+ return execSync(`bd kv get "closed-this-session:${sessionId}"`, {
125
+ encoding: 'utf8',
126
+ cwd,
127
+ stdio: ['pipe', 'pipe', 'pipe'],
128
+ timeout: 5000,
129
+ }).trim();
130
+ } catch (err) {
131
+ if (err.status === 1) return ''; // key not found
132
+ return null; // bd kv unavailable
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Return true if the memory gate is pending acknowledgment for this session.
138
+ * Pending = closed-this-session kv is set AND .beads/.memory-gate-done marker is absent.
139
+ */
140
+ export function isMemoryGatePending(sessionId, cwd) {
141
+ if (existsSync(join(cwd, '.beads', '.memory-gate-done'))) return false;
142
+ const closed = getClosedThisSession(sessionId, cwd);
143
+ return !!closed; // null (unavailable) is falsy → fail open
144
+ }
145
+
146
+ /**
147
+ * Return true if a Bash command is a memory-gate acknowledgment command.
148
+ * These commands are allowed even while the memory gate is pending.
149
+ */
150
+ export function isMemoryAckCommand(command) {
151
+ return /\bbd\s+remember\b/.test(command) || /\btouch\s+\.beads\/\.memory-gate-done\b/.test(command);
152
+ }
153
+
154
+ /**
155
+ * If cwd is inside a .xtrm/worktrees/<name> directory, return the worktree root path.
156
+ * Returns null if not in a worktree.
157
+ */
158
+ export function resolveWorktreeRoot(cwd) {
159
+ const m = cwd.match(/^(.+\/\.xtrm\/worktrees\/[^/]+)/);
160
+ return m ? m[1] : null;
161
+ }
162
+
163
+ /**
164
+ * Clear the session claim key from bd kv. Non-fatal — best-effort cleanup.
165
+ */
166
+ export function clearSessionClaim(sessionId, cwd) {
167
+ try {
168
+ execSync(`bd kv clear "claimed:${sessionId}"`, {
169
+ encoding: 'utf8', cwd, stdio: ['pipe', 'pipe', 'pipe'], timeout: 5000,
170
+ });
171
+ } catch {
172
+ // non-fatal
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Option C: wrap hook body with uniform fail-open error handling.
178
+ * Any unexpected top-level throw exits 0 (allow) rather than crashing visibly.
179
+ *
180
+ * Usage:
181
+ * withSafeBdContext(() => {
182
+ * // hook logic here — call process.exit() to set exit code
183
+ * });
184
+ */
185
+ export function withSafeBdContext(fn) {
186
+ try {
187
+ fn();
188
+ } catch (err) {
189
+ if (err instanceof TypeError || err instanceof ReferenceError || err instanceof SyntaxError) {
190
+ throw err;
191
+ }
192
+ process.exit(0);
193
+ }
194
+ }
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+ // beads-memory-gate — Claude Code Stop hook
3
+ // At session end, forces the agent to evaluate whether this session's work
4
+ // produced insights worth persisting via `bd remember`.
5
+ // Runs after beads-stop-gate (all issues already closed by that point).
6
+ // Exit 0: allow stop | Exit 2: block stop (stderr shown to Claude)
7
+ //
8
+ // Installed by: xtrm install
9
+
10
+ import { execSync } from 'node:child_process';
11
+ import { existsSync, unlinkSync } from 'node:fs';
12
+ import { join } from 'node:path';
13
+ import { readHookInput } from './beads-gate-core.mjs';
14
+ import { resolveCwd, resolveSessionId, isBeadsProject, getSessionClaim, clearSessionClaim } from './beads-gate-utils.mjs';
15
+ import { memoryPromptMessage } from './beads-gate-messages.mjs';
16
+ import { logEvent } from './xtrm-logger.mjs';
17
+
18
+ const input = readHookInput();
19
+ if (!input) process.exit(0);
20
+
21
+ const cwd = resolveCwd(input);
22
+ if (!cwd || !isBeadsProject(cwd)) process.exit(0);
23
+
24
+ const sessionId = resolveSessionId(input);
25
+
26
+ // Agent signals evaluation complete by touching this marker, then stops again
27
+ const marker = join(cwd, '.beads', '.memory-gate-done');
28
+ if (existsSync(marker)) {
29
+ try { unlinkSync(marker); } catch { /* ignore */ }
30
+ // Clear the claim and closed-this-session marker
31
+ clearSessionClaim(sessionId, cwd);
32
+ try {
33
+ execSync(`bd kv clear "closed-this-session:${sessionId}"`, {
34
+ cwd,
35
+ stdio: ['pipe', 'pipe', 'pipe'],
36
+ timeout: 5000,
37
+ });
38
+ } catch { /* ignore */ }
39
+ logEvent({
40
+ cwd,
41
+ runtime: 'claude',
42
+ sessionId,
43
+ layer: 'gate',
44
+ kind: 'gate.memory.acked',
45
+ outcome: 'allow',
46
+ });
47
+ process.exit(0);
48
+ }
49
+
50
+ // Check if an issue was closed this session (set by beads-claim-sync on bd close)
51
+ let closedIssueId = null;
52
+ try {
53
+ closedIssueId = execSync(`bd kv get "closed-this-session:${sessionId}"`, {
54
+ encoding: 'utf8',
55
+ cwd,
56
+ stdio: ['pipe', 'pipe', 'pipe'],
57
+ timeout: 5000,
58
+ }).trim();
59
+ } catch (err) {
60
+ if (err.status === 1) {
61
+ // No closed-this-session marker → nothing to prompt about
62
+ process.exit(0);
63
+ }
64
+ process.exit(0); // fail open
65
+ }
66
+
67
+ if (!closedIssueId) process.exit(0);
68
+
69
+ const memoryMessage = memoryPromptMessage();
70
+ logEvent({
71
+ cwd,
72
+ runtime: 'claude',
73
+ sessionId,
74
+ layer: 'gate',
75
+ kind: 'gate.memory.triggered',
76
+ outcome: 'block',
77
+ issueId: closedIssueId,
78
+ message: memoryMessage,
79
+ });
80
+ process.stderr.write(memoryMessage);
81
+ process.exit(2);
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ // beads-stop-gate — Claude Code Stop hook
3
+ // Blocks the agent from stopping when this session has an unclosed claim in bd kv.
4
+ // Also blocks when xtrm session state indicates unfinished closure phases.
5
+ // Exit 0: allow stop | Exit 2: block stop (stderr shown to Claude)
6
+
7
+ import {
8
+ readHookInput,
9
+ resolveSessionContext,
10
+ resolveClaimAndWorkState,
11
+ decideStopGate,
12
+ } from './beads-gate-core.mjs';
13
+ import { withSafeBdContext } from './beads-gate-utils.mjs';
14
+ import { stopBlockMessage } from './beads-gate-messages.mjs';
15
+ import { logEvent } from './xtrm-logger.mjs';
16
+
17
+ const input = readHookInput();
18
+ if (!input) process.exit(0);
19
+
20
+ withSafeBdContext(() => {
21
+ const ctx = resolveSessionContext(input);
22
+ if (!ctx || !ctx.isBeadsProject) process.exit(0);
23
+
24
+ const state = resolveClaimAndWorkState(ctx);
25
+ const decision = decideStopGate(ctx, state);
26
+
27
+ if (!decision.allow) {
28
+ const message = stopBlockMessage(decision.summary, decision.claimed);
29
+ logEvent({
30
+ cwd: ctx.cwd,
31
+ runtime: 'claude',
32
+ sessionId: ctx.sessionId,
33
+ layer: 'gate',
34
+ kind: 'gate.stop.block',
35
+ outcome: 'block',
36
+ issueId: decision.claimed ?? null,
37
+ message,
38
+ extra: { reason_code: decision.reason },
39
+ });
40
+ process.stderr.write(message);
41
+ process.exit(2);
42
+ }
43
+
44
+ logEvent({
45
+ cwd: ctx.cwd,
46
+ runtime: 'claude',
47
+ sessionId: ctx.sessionId,
48
+ layer: 'gate',
49
+ kind: 'session.end',
50
+ outcome: 'allow',
51
+ });
52
+ process.exit(0);
53
+ });