capt-hook 12.75.2__tar.gz → 12.76.0__tar.gz

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 (229) hide show
  1. {capt_hook-12.75.2 → capt_hook-12.76.0}/PKG-INFO +2 -2
  2. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/.claude-plugin/plugin.json +1 -1
  3. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/steering/hooks/steering.py +29 -27
  4. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/context.py +4 -2
  5. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/primitives/llm.py +2 -2
  6. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/primitives/nudge.py +1 -1
  7. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/signals/__init__.py +12 -8
  8. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/client.py +9 -2
  9. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/schemas/host-request.schema.json +6 -1
  10. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/schemas/host-response.schema.json +6 -1
  11. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/schemas/request.schema.json +6 -1
  12. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/types.py +5 -0
  13. {capt_hook-12.75.2 → capt_hook-12.76.0}/pyproject.toml +2 -2
  14. {capt_hook-12.75.2 → capt_hook-12.76.0}/.gitignore +0 -0
  15. {capt_hook-12.75.2 → capt_hook-12.76.0}/LICENSE +0 -0
  16. {capt_hook-12.75.2 → capt_hook-12.76.0}/README.md +0 -0
  17. {capt_hook-12.75.2 → capt_hook-12.76.0}/capt_hook_client/__init__.py +0 -0
  18. {capt_hook-12.75.2 → capt_hook-12.76.0}/capt_hook_client/__main__.py +0 -0
  19. {capt_hook-12.75.2 → capt_hook-12.76.0}/capt_hook_client/client.py +0 -0
  20. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/.mcp.json +0 -0
  21. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/__init__.py +0 -0
  22. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/__init__.pyi +0 -0
  23. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/__main__.py +0 -0
  24. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/app.py +0 -0
  25. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/ast_grep.py +0 -0
  26. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/__init__.py +0 -0
  27. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/fixes/__init__.py +0 -0
  28. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/fixes/hooks/__init__.py +0 -0
  29. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/fixes/hooks/_lib.py +0 -0
  30. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/fixes/hooks/scratch_writes.py +0 -0
  31. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/fixes/hooks/teammate_permissions.py +0 -0
  32. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/__init__.py +0 -0
  33. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/__init__.py +0 -0
  34. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/_lib.py +0 -0
  35. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/_sessions.py +0 -0
  36. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/commands.py +0 -0
  37. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/comments.py +0 -0
  38. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/deletions.py +0 -0
  39. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/detours.py +0 -0
  40. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/docs.py +0 -0
  41. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/hook_files.py +0 -0
  42. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/models.py +0 -0
  43. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/plain_english.py +0 -0
  44. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/plans.py +0 -0
  45. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/fragments/deliverable_rubric.md +0 -0
  46. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/fragments/workflow_script_header.md +0 -0
  47. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/models/browser_delegation_nudge.md +0 -0
  48. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/models/implementation_spawn_nudge.md +0 -0
  49. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/models/inline_edit_nudge.md +0 -0
  50. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/models/prose_spawn_gate.md +0 -0
  51. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/models/prose_workflow_nudge.md +0 -0
  52. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/models/review_routing_spawn_nudge.md +0 -0
  53. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/models/review_routing_workflow_nudge.md +0 -0
  54. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/models/writing_docs_spawn_nudge.md +0 -0
  55. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/models/writing_docs_workflow_nudge.md +0 -0
  56. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/plain_english_rules.md +0 -0
  57. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts/tools/preload_nudge.md +0 -0
  58. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/prompts.py +0 -0
  59. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/questions.py +0 -0
  60. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/review.py +0 -0
  61. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/sessions.py +0 -0
  62. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/tasks.py +0 -0
  63. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/tombstones.py +0 -0
  64. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/tooling.py +0 -0
  65. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/hooks/tools.py +0 -0
  66. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/general/pack.toml +0 -0
  67. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/go/__init__.py +0 -0
  68. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/go/hooks/__init__.py +0 -0
  69. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/go/hooks/testing.py +0 -0
  70. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/go/hooks/toolchain.py +0 -0
  71. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/graphite/__init__.py +0 -0
  72. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/graphite/gitdir/.graphite_repo_config +0 -0
  73. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/graphite/hooks/__init__.py +0 -0
  74. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/graphite/hooks/_lib.py +0 -0
  75. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/graphite/hooks/queue.py +0 -0
  76. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/graphite/hooks/vcs.py +0 -0
  77. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/performance/__init__.py +0 -0
  78. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/performance/hooks/__init__.py +0 -0
  79. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/performance/hooks/filesystem.py +0 -0
  80. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/performance/hooks/pipelining.py +0 -0
  81. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/python/__init__.py +0 -0
  82. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/python/hooks/__init__.py +0 -0
  83. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/python/hooks/style.py +0 -0
  84. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/python/hooks/testing.py +0 -0
  85. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/python/hooks/toolchain.py +0 -0
  86. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/steering/__init__.py +0 -0
  87. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/steering/hooks/__init__.py +0 -0
  88. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/steering/hooks/teammates.py +0 -0
  89. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/steering/hooks/workarounds.py +0 -0
  90. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/builtin_packs/steering/pack.toml +0 -0
  91. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/classifiers/__init__.py +0 -0
  92. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/classifiers/conductor.py +0 -0
  93. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/classifiers/droid.py +0 -0
  94. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/classifiers/lane.py +0 -0
  95. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/classifiers/native.py +0 -0
  96. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/cli.py +0 -0
  97. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/cmd.py +0 -0
  98. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/command_schema.py +0 -0
  99. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/command_schemas.py +0 -0
  100. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/conditions.py +0 -0
  101. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/contexts.py +0 -0
  102. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/daemon/__init__.py +0 -0
  103. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/daemon/context.py +0 -0
  104. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/daemon/decision_writer.py +0 -0
  105. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/daemon/logsink.py +0 -0
  106. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/daemon/registry.py +0 -0
  107. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/daemon/tree.py +0 -0
  108. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/decisions.py +0 -0
  109. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/desktop/__init__.py +0 -0
  110. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/desktop/cli.py +0 -0
  111. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/desktop/client.py +0 -0
  112. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/dispatch.py +0 -0
  113. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/doc_conventions.py +0 -0
  114. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/durable.py +0 -0
  115. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/events.py +0 -0
  116. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/faults.py +0 -0
  117. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/fields.py +0 -0
  118. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/file.py +0 -0
  119. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/guard_literal.py +0 -0
  120. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/guard_literal.sh +0 -0
  121. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/heartbeat.py +0 -0
  122. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/hook_lint.py +0 -0
  123. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/hooks/hooks.json +0 -0
  124. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/loader.py +0 -0
  125. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/log.py +0 -0
  126. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/mcp_server.py +0 -0
  127. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/packs/__init__.py +0 -0
  128. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/packs/manager.py +0 -0
  129. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/packs/plugins.py +0 -0
  130. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/primitives/__init__.py +0 -0
  131. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/primitives/commands.py +0 -0
  132. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/primitives/lint.py +0 -0
  133. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/primitives/permissions.py +0 -0
  134. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/primitives/provision.py +0 -0
  135. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/primitives/rewrite.py +0 -0
  136. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/primitives/workflow.py +0 -0
  137. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/prompt.py +0 -0
  138. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/py.typed +0 -0
  139. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/__init__.py +0 -0
  140. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/announce.py +0 -0
  141. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/cli.py +0 -0
  142. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/dashboard.py +0 -0
  143. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/fix.py +0 -0
  144. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/formats.py +0 -0
  145. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/judge.py +0 -0
  146. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/notify.py +0 -0
  147. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/pipeline.py +0 -0
  148. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/prompts.py +0 -0
  149. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/repo.py +0 -0
  150. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/routing.py +0 -0
  151. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/scan.py +0 -0
  152. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/settings.py +0 -0
  153. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/snapshot.py +0 -0
  154. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/status.py +0 -0
  155. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/store.py +0 -0
  156. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/sync.py +0 -0
  157. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/review/triage.py +0 -0
  158. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/scripts/install-binary.sh +0 -0
  159. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/scripts/install-mcp.sh +0 -0
  160. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/session.py +0 -0
  161. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/settings.py +0 -0
  162. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/signals/nlp.py +0 -0
  163. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/authoring-hooks/SKILL.md +0 -0
  164. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/authoring-hooks/references/capt-hook-api.md +0 -0
  165. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/authoring-hooks/references/pattern-catalog.md +0 -0
  166. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/authoring-hooks/references/pitfalls.md +0 -0
  167. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/authoring-hooks/references/testing-hooks.md +0 -0
  168. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/bootstrapping-hooks/SKILL.md +0 -0
  169. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/scanning-sessions/SKILL.md +0 -0
  170. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/scanning-sessions/references/pr-workflow.md +0 -0
  171. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/scanning-sessions/references/review-cli.md +0 -0
  172. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/translating-styleguides/SKILL.md +0 -0
  173. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/translating-styleguides/references/llm-rule-patterns.md +0 -0
  174. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/translating-styleguides/references/matcher-reference.md +0 -0
  175. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/skills/translating-styleguides/references/tier-rubric.md +0 -0
  176. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/__init__.py +0 -0
  177. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/contracts.py +0 -0
  178. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/review.py +0 -0
  179. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/schema.py +0 -0
  180. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/schemas/config.schema.json +0 -0
  181. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/schemas/context.schema.json +0 -0
  182. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/schemas/response.schema.json +0 -0
  183. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/schemas/tool_registry.schema.json +0 -0
  184. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/validation.py +0 -0
  185. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/snapshots/worker.py +0 -0
  186. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/state.py +0 -0
  187. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/style/__init__.py +0 -0
  188. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/style/ast_grep.py +0 -0
  189. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/style/matchers.py +0 -0
  190. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/style/scope.py +0 -0
  191. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/style/types.py +0 -0
  192. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/tasks.py +0 -0
  193. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/templates/example_hook.py.tmpl +0 -0
  194. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/testing/__init__.py +0 -0
  195. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/testing/fixtures.py +0 -0
  196. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/testing/helpers.py +0 -0
  197. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/testing/session_cache.py +0 -0
  198. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/testing/snapshots.py +0 -0
  199. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/testing/types.py +0 -0
  200. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/transcripts.py +0 -0
  201. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/turn.py +0 -0
  202. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/update/__init__.py +0 -0
  203. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/update/cli.py +0 -0
  204. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/update/settings.py +0 -0
  205. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/update/updater.py +0 -0
  206. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/__init__.py +0 -0
  207. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/automode.py +0 -0
  208. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/caching.py +0 -0
  209. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/fs.py +0 -0
  210. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/globbing.py +0 -0
  211. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/http.py +0 -0
  212. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/model_cache.py +0 -0
  213. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/paths.py +0 -0
  214. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/payload.py +0 -0
  215. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/proc.py +0 -0
  216. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/reqenv.py +0 -0
  217. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/scratch.py +0 -0
  218. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/shell.py +0 -0
  219. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/text.py +0 -0
  220. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/userpath.py +0 -0
  221. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/util/vcs.py +0 -0
  222. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/worker/__init__.py +0 -0
  223. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/worker/__main__.py +0 -0
  224. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/worker/fail_open.py +0 -0
  225. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/worker/protocol.py +0 -0
  226. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/worker/runtime.py +0 -0
  227. {capt_hook-12.75.2 → capt_hook-12.76.0}/captain_hook/worker/service.py +0 -0
  228. {capt_hook-12.75.2 → capt_hook-12.76.0}/hatch_build.py +0 -0
  229. {capt_hook-12.75.2 → capt_hook-12.76.0}/internal/wireproto/guard.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: capt-hook
3
- Version: 12.75.2
3
+ Version: 12.76.0
4
4
  Summary: Stop repeating yourself to Claude.
5
5
  Project-URL: Homepage, https://github.com/yasyf/captain-hook
6
6
  Project-URL: Documentation, https://yasyf.github.io/captain-hook/
@@ -22,7 +22,7 @@ Classifier: Topic :: Software Development :: Testing
22
22
  Classifier: Typing :: Typed
23
23
  Requires-Python: >=3.13
24
24
  Requires-Dist: ast-grep-py<0.45,>=0.44
25
- Requires-Dist: cc-transcript[judge]==14.32.1
25
+ Requires-Dist: cc-transcript[judge]==14.33.0
26
26
  Requires-Dist: click>=8
27
27
  Requires-Dist: filelock>=3
28
28
  Requires-Dist: funcy>=2.0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "captain-hook",
3
- "version": "12.75.0",
3
+ "version": "12.75.2",
4
4
  "displayName": "Captain Hook",
5
5
  "description": "Skills for the capt-hook declarative hook framework: bootstrap gates and nudges from a repo's conventions, and translate style guides into enforced StyleRules.",
6
6
  "author": {
@@ -25,6 +25,31 @@ from captain_hook import (
25
25
  nudge,
26
26
  )
27
27
 
28
+ THINKING_MISFIRES = (
29
+ "Thinking it through more, the deploy applies the stack at the dev commit, so this addon update is likely just "
30
+ "dev catching up to whatever live already has — not something new introduced by my change.",
31
+ "Before escalating, I want to pin down whether TS release still runs anywhere, since if it doesn't, switching "
32
+ "pr-reviewer to target names might just be fixing an existing mismatch rather than introducing a new behavior "
33
+ "change.",
34
+ "The deeper problem is that leading-option binding stops at any unrecognized flag, meaning something like "
35
+ "`cc-notes --foo task validate x` would leave the verb words undetected and get approved by mistake — and the "
36
+ "old check has this same evasion flaw, so I need a more robust way to detect the dangerous verb regardless of "
37
+ "leading options.",
38
+ "The worktree removal is stuck on an idle-check tied to a known refusal pattern, so I'll leave it as a minor "
39
+ "issue to report later.",
40
+ "The root cause traces to deploy 8fbf85b landing outside the release pointer process, leaving SSM still pointing "
41
+ "at an older release expecting an outdated alembic revision while the DB had already migrated further — then a "
42
+ "box resize/reboot re-triggered that stale pointer deploy, causing a migration failure and 502s, which was "
43
+ "ultimately fixed by restoring 8fbf85b.",
44
+ 'But I\'m second-guessing whether "placeholder" as a literal string is the right approach versus leaving it '
45
+ 'unset, since a consumer that checks truthiness would pass the check with "placeholder" and then fail later with '
46
+ 'a confusing opaque OAuth error rather than a clear "not configured" message — whereas leaving it empty/unset '
47
+ "lets the existing guard clauses report the clean error upfront.",
48
+ "For OUTAGE-level customer monitors I need to wrap handles with the pageOnAlert helper instead, covering chime "
49
+ "run errors, sofi ATO errors, the sofi pager stopped handles, and the polar undelivered/ATO run errors—while "
50
+ "leaving the chime composite alerts alone since they're already properly gated.",
51
+ )
52
+
28
53
 
29
54
  class TypeCheckerContext(CustomCondition):
30
55
  """True when the recent assistant transcript is discussing a type checker / diagnostics."""
@@ -80,6 +105,7 @@ nudge(
80
105
  threshold=2,
81
106
  window=15,
82
107
  scope="text",
108
+ thinking=False,
83
109
  vetoes=[
84
110
  Signal(pattern=r"(?i)\b(?:which|that)\s+leaves?\b"),
85
111
  Signal(pattern=r"(?i)\bleaving\b[^.!?]{0,80}?\bmeans?\b"),
@@ -268,36 +294,12 @@ nudge(
268
294
  ]
269
295
  ): Allow(),
270
296
  Input(transcript=[T.assistant("I'll leave that CLAUDE.md issue unaddressed for now.")]): Warn(),
297
+ **{Input(transcript=[T.assistant(T.thinking(text))]): Allow() for text in THINKING_MISFIRES},
271
298
  Input(
272
299
  transcript=[
273
300
  T.assistant(
274
- T.thinking(
275
- "Thinking it through more, the deploy applies the stack at the dev commit, so this addon "
276
- "update is likely just dev catching up to whatever live already has — not something new "
277
- "introduced by my change."
278
- )
279
- )
280
- ]
281
- ): Allow(),
282
- Input(
283
- transcript=[
284
- T.assistant(
285
- T.thinking(
286
- "Before escalating, I want to pin down whether TS release still runs anywhere, since if it "
287
- "doesn't, switching pr-reviewer to target names might just be fixing an existing mismatch "
288
- "rather than introducing a new behavior change."
289
- )
290
- )
291
- ]
292
- ): Allow(),
293
- Input(
294
- transcript=[
295
- T.assistant(
296
- T.thinking(
297
- "That test failure on #28529's own branch looks like a pre-existing bug in deploy-go, not "
298
- "something caused by my change, so I should report it upstream rather than try to fix it "
299
- "myself."
300
- )
301
+ "That test failure on #28529's own branch looks like a pre-existing bug in deploy-go, not "
302
+ "something caused by my change, so I should report it upstream rather than try to fix it myself."
301
303
  )
302
304
  ]
303
305
  ): Warn(),
@@ -101,7 +101,7 @@ class HookEvidence:
101
101
  event_count: int
102
102
  window_start: int
103
103
  current_turn_event_count: int
104
- signal_texts: tuple[tuple[tuple[int | Literal["turn"], str], tuple[str, ...]], ...]
104
+ signal_texts: tuple[tuple[tuple[int | Literal["turn"], str, bool], tuple[str, ...]], ...]
105
105
  prompt: str
106
106
 
107
107
 
@@ -116,7 +116,9 @@ class HookContext:
116
116
  transcript: Session | RemoteSession | LazyTranscript
117
117
  settings: HooksSettings | None
118
118
  project_root: Path | None = None
119
- signal_evidence: dict[tuple[int | Literal["turn"], str], tuple[str, ...]] = field(default_factory=dict, init=False)
119
+ signal_evidence: dict[tuple[int | Literal["turn"], str, bool], tuple[str, ...]] = field(
120
+ default_factory=dict, init=False
121
+ )
120
122
  prepared_evidence: HookEvidence | None = field(default=None, init=False)
121
123
 
122
124
  def fork(self, transcript: Session | RemoteSession | LazyTranscript) -> HookContext:
@@ -111,7 +111,7 @@ def llm_evaluate[M: BaseModel](
111
111
 
112
112
  if sig := resolve_signals(signals):
113
113
  ps = evt.ctx.s[PrimitiveState].get(PrimitiveState())
114
- texts = ps.unechoed_candidates(transcript_texts(evt, sig.window, sig.origin))
114
+ texts = ps.unechoed_candidates(transcript_texts(evt, sig.window, sig.origin, sig.thinking))
115
115
  if not (contributing_texts := ps.match_signals(sig, texts, hook)):
116
116
  return None
117
117
  elif contexts and when is None:
@@ -183,7 +183,7 @@ def consume_signals(evt: BaseHookEvent, sig: Signals | None, hook: str) -> list[
183
183
  """
184
184
  if not sig:
185
185
  return None
186
- texts = transcript_texts(evt, sig.window, sig.origin)
186
+ texts = transcript_texts(evt, sig.window, sig.origin, sig.thinking)
187
187
  with evt.ctx.s[PrimitiveState].mutate() as ps:
188
188
  return ps.match_signals(sig, ps.unechoed_candidates(texts), hook)
189
189
 
@@ -92,7 +92,7 @@ def nudge(
92
92
  tracker = EchoTracker(
93
93
  window=ECHO_WINDOW + (sig.window if isinstance(sig.window, int) else TURN_ECHO_LOOKBACK)
94
94
  )
95
- candidates = tracker.survivors(transcript_texts(evt, sig.window, sig.origin), evt=evt)
95
+ candidates = tracker.survivors(transcript_texts(evt, sig.window, sig.origin, sig.thinking), evt=evt)
96
96
  matches = matching_texts(sig, candidates, consumed=evt.ctx.s.load(PrimitiveState).consumed.get(name, ()))
97
97
  if not matches:
98
98
  return None
@@ -76,11 +76,11 @@ def extract_signal_context(patterns: Sequence[TSignalPattern], text: str) -> lis
76
76
  return result
77
77
 
78
78
 
79
- def block_texts(event: UserEvent | AssistantEvent) -> Iterator[str]:
79
+ def block_texts(event: UserEvent | AssistantEvent, *, thinking: bool) -> Iterator[str]:
80
80
  for block in event.blocks:
81
81
  match block:
82
- case ThinkingBlock(thinking=thinking):
83
- yield thinking
82
+ case ThinkingBlock(thinking=text) if thinking:
83
+ yield text
84
84
  case ToolUseBlock(name=name, input=payload):
85
85
  match parse_tool_call(name, payload, on_error="other"):
86
86
  case (
@@ -97,7 +97,10 @@ def block_texts(event: UserEvent | AssistantEvent) -> Iterator[str]:
97
97
 
98
98
 
99
99
  def transcript_texts(
100
- evt: BaseHookEvent, window: int | Literal["turn"], origin: Literal["assistant", "any"] = "any"
100
+ evt: BaseHookEvent,
101
+ window: int | Literal["turn"],
102
+ origin: Literal["assistant", "any"] = "any",
103
+ thinking: bool = True,
101
104
  ) -> list[str]:
102
105
  """Extract prose from recent transcript events for signal scoring.
103
106
 
@@ -111,7 +114,8 @@ def transcript_texts(
111
114
  assistant prose alike, while ``"assistant"`` drops user messages (and, on
112
115
  ``UserPromptSubmit``, the just-submitted prompt) so a stance hook scores only the
113
116
  agent's own words. Signal-driven hooks thread ``Signals.origin`` here, which
114
- defaults to ``"assistant"``.
117
+ defaults to ``"assistant"``. ``thinking=False`` drops thinking blocks, so a hook scores
118
+ only what the agent wrote; signal-driven hooks thread ``Signals.thinking`` here.
115
119
 
116
120
  A fixed ``window`` counts scored prose entries, not raw JSONL events: tool calls
117
121
  and their results carry no prose, so they never crowd a message out of the window,
@@ -135,7 +139,7 @@ def transcript_texts(
135
139
  transcript, so scoring it would let one agent's words trip this agent's gate.
136
140
  """
137
141
 
138
- key = (window, origin)
142
+ key = (window, origin, thinking)
139
143
  if (prepared := evt.ctx.prepared_evidence) is not None:
140
144
  for saved_key, texts in prepared.signal_texts:
141
145
  if saved_key == key:
@@ -144,7 +148,7 @@ def transcript_texts(
144
148
  if key in evt.ctx.signal_evidence:
145
149
  return list(evt.ctx.signal_evidence[key])
146
150
  if isinstance(evt.ctx.t, RemoteSession):
147
- texts = evt.ctx.t.signal_texts(window=window, origin=origin)
151
+ texts = evt.ctx.t.signal_texts(window=window, origin=origin, thinking=thinking)
148
152
  if origin == "any" and evt.event == Event.UserPromptSubmit and evt.user_prompt:
149
153
  texts = [evt.user_prompt, *texts]
150
154
  evt.ctx.signal_evidence[key] = tuple(texts)
@@ -159,7 +163,7 @@ def transcript_texts(
159
163
  )
160
164
 
161
165
  def texts_of(event: UserEvent | AssistantEvent) -> list[str]:
162
- return [text for text in (event.text, *block_texts(event)) if text]
166
+ return [text for text in (event.text, *block_texts(event, thinking=thinking)) if text]
163
167
 
164
168
  if window == "turn":
165
169
  texts = [text for event in evt.ctx.turn.events if eligible(event) for text in texts_of(event)]
@@ -988,9 +988,16 @@ class RemoteSession:
988
988
  def assistant_text(self, n: int = 10, *, max_per_msg: int = 500) -> str:
989
989
  return "\n---\n".join(self.query({"kind": "assistant_text", "count": n, "max_per_message": max_per_msg}))
990
990
 
991
- def signal_texts(self, window: int | Literal["turn"], origin: Literal["assistant", "any"]) -> list[str]:
991
+ def signal_texts(
992
+ self, window: int | Literal["turn"], origin: Literal["assistant", "any"], thinking: bool
993
+ ) -> list[str]:
992
994
  return self.query(
993
- {"kind": "signal_texts", "window": "current_turn" if window == "turn" else window, "origin": origin}
995
+ {
996
+ "kind": "signal_texts",
997
+ "window": "current_turn" if window == "turn" else window,
998
+ "origin": origin,
999
+ "thinking": thinking,
1000
+ }
994
1001
  )
995
1002
 
996
1003
  def render(self, *, budget: Budget, tool_results: bool = False) -> str:
@@ -3228,6 +3228,10 @@
3228
3228
  "title": "Origin",
3229
3229
  "type": "string"
3230
3230
  },
3231
+ "thinking": {
3232
+ "title": "Thinking",
3233
+ "type": "boolean"
3234
+ },
3231
3235
  "window": {
3232
3236
  "anyOf": [
3233
3237
  {
@@ -3246,7 +3250,8 @@
3246
3250
  "required": [
3247
3251
  "kind",
3248
3252
  "window",
3249
- "origin"
3253
+ "origin",
3254
+ "thinking"
3250
3255
  ],
3251
3256
  "title": "SignalTexts",
3252
3257
  "type": "object"
@@ -3228,6 +3228,10 @@
3228
3228
  "title": "Origin",
3229
3229
  "type": "string"
3230
3230
  },
3231
+ "thinking": {
3232
+ "title": "Thinking",
3233
+ "type": "boolean"
3234
+ },
3231
3235
  "window": {
3232
3236
  "anyOf": [
3233
3237
  {
@@ -3246,7 +3250,8 @@
3246
3250
  "required": [
3247
3251
  "kind",
3248
3252
  "window",
3249
- "origin"
3253
+ "origin",
3254
+ "thinking"
3250
3255
  ],
3251
3256
  "title": "SignalTexts",
3252
3257
  "type": "object"
@@ -2006,6 +2006,10 @@
2006
2006
  "title": "Origin",
2007
2007
  "type": "string"
2008
2008
  },
2009
+ "thinking": {
2010
+ "title": "Thinking",
2011
+ "type": "boolean"
2012
+ },
2009
2013
  "window": {
2010
2014
  "anyOf": [
2011
2015
  {
@@ -2024,7 +2028,8 @@
2024
2028
  "required": [
2025
2029
  "kind",
2026
2030
  "window",
2027
- "origin"
2031
+ "origin",
2032
+ "thinking"
2028
2033
  ],
2029
2034
  "title": "SignalTexts",
2030
2035
  "type": "object"
@@ -948,6 +948,10 @@ class Signals:
948
948
  prompt or correction (a ``UserPromptSubmit`` nudge, say), where the just-submitted
949
949
  prompt is prepended to the scan only under ``"any"``.
950
950
 
951
+ ``thinking`` keeps the agent's thinking blocks among the candidate texts. Pass
952
+ ``thinking=False`` for a stance nudge that judges what the agent wrote, not the
953
+ options it weighed privately on the way there.
954
+
951
955
  ``vetoes`` are presence-only suppressors: if any veto matches any window entry
952
956
  — including already-consumed ones — the bundle does not fire and consumes
953
957
  nothing. A veto's ``weight`` is meaningless and must be left at its default.
@@ -964,6 +968,7 @@ class Signals:
964
968
  window: int | Literal["turn"] = 15
965
969
  scope: Literal["text", "window"] = field(default="window", kw_only=True)
966
970
  origin: Literal["assistant", "any"] = field(default="assistant", kw_only=True)
971
+ thinking: bool = field(default=True, kw_only=True)
967
972
  vetoes: Sequence[Signal | NlpSignal] = ()
968
973
 
969
974
  def __post_init__(self) -> None:
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "capt-hook"
3
3
  # Inert sentinel — the real version is stamped from the release tag (uv version --frozen).
4
- version = "12.75.2"
4
+ version = "12.76.0"
5
5
  description = "Stop repeating yourself to Claude."
6
6
  readme = "README.md"
7
7
  license = "PolyForm-Noncommercial-1.0.0"
@@ -29,7 +29,7 @@ classifiers = [
29
29
  ]
30
30
  requires-python = ">=3.13"
31
31
  dependencies = [
32
- "cc-transcript[judge]==14.32.1",
32
+ "cc-transcript[judge]==14.33.0",
33
33
  "pydantic>=2.0",
34
34
  "jsonschema>=4.26",
35
35
  "pydantic-settings>=2.0",
File without changes
File without changes
File without changes