higpertext-cli 0.8.0__py3-none-any.whl

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 (335) hide show
  1. config/adapters_config.json +450 -0
  2. config/antigravity_agent_template.json +31 -0
  3. config/app_config.json +174 -0
  4. config/context_engine.json +33 -0
  5. config/environments/model_defaults.json +5 -0
  6. config/governance/branching_strategy.json +36 -0
  7. config/governance/deployment_gates.json +30 -0
  8. config/governance/guidelines_contract.json +54 -0
  9. config/governance/quality_gates.json +39 -0
  10. config/governance/section_rules.json +22 -0
  11. config/governance/security_guardrails.json +52 -0
  12. config/hooks/README.md +35 -0
  13. config/hooks/custom/test_output_limiter.json +9 -0
  14. config/hooks/global/session_prompt.json +9 -0
  15. config/htx_config.json +24 -0
  16. config/profile_learner.json +18 -0
  17. config/profiles/base_agent.json +40 -0
  18. config/profiles/base_auditor.json +19 -0
  19. config/profiles/base_developer.json +19 -0
  20. config/profiles/base_operator.json +16 -0
  21. config/profiles/global.json +33 -0
  22. config/profiles/software_developer.json +23 -0
  23. config/router_content.json +137 -0
  24. config/semantic_graph.json +66 -0
  25. config/workflows/ado_release_flow.json +38 -0
  26. config/workflows/docs-update.json +33 -0
  27. config/workflows/governance-check.yaml +26 -0
  28. config/workflows/guidelines-sync.json +40 -0
  29. config/workflows/higpertext-build.json +73 -0
  30. config/workflows/higpertext-plan.json +38 -0
  31. config/workflows/higpertext-review.json +41 -0
  32. config/workflows/pr-quality-check.json +56 -0
  33. config/workflows/quality-remediation.json +57 -0
  34. higpertext/__init__.py +18 -0
  35. higpertext/adapters/__init__.py +27 -0
  36. higpertext/adapters/adapter_utils.py +604 -0
  37. higpertext/adapters/claude_adapter/__init__.py +0 -0
  38. higpertext/adapters/claude_adapter/claude_adapter.py +154 -0
  39. higpertext/adapters/copilot_adapter/__init__.py +0 -0
  40. higpertext/adapters/copilot_adapter/copilot_adapter.py +231 -0
  41. higpertext/adapters/gemini_adapter/__init__.py +0 -0
  42. higpertext/adapters/gemini_adapter/gemini_adapter.py +211 -0
  43. higpertext/adapters/llm_formatter.py +46 -0
  44. higpertext/adapters/open_code_adapter/__init__.py +0 -0
  45. higpertext/adapters/open_code_adapter/open_code_adapter.py +480 -0
  46. higpertext/capabilities/capabilities_runner.py +216 -0
  47. higpertext/capabilities/common/agent-builder.json +54 -0
  48. higpertext/capabilities/common/agent-sync.json +34 -0
  49. higpertext/capabilities/common/code-skeletonizer.json +35 -0
  50. higpertext/capabilities/common/commit-report.json +42 -0
  51. higpertext/capabilities/common/context-assembler.json +37 -0
  52. higpertext/capabilities/common/context-budget-report.json +15 -0
  53. higpertext/capabilities/common/dep-manager.json +43 -0
  54. higpertext/capabilities/common/docs-sync.json +14 -0
  55. higpertext/capabilities/common/doctor.json +18 -0
  56. higpertext/capabilities/common/efficiency-meter.json +31 -0
  57. higpertext/capabilities/common/env-catalog.json +13 -0
  58. higpertext/capabilities/common/env-clean.json +14 -0
  59. higpertext/capabilities/common/env-logs.json +16 -0
  60. higpertext/capabilities/common/env-runner.json +23 -0
  61. higpertext/capabilities/common/env-status.json +13 -0
  62. higpertext/capabilities/common/env-stop.json +14 -0
  63. higpertext/capabilities/common/env-template.json +14 -0
  64. higpertext/capabilities/common/error-context-locator.json +23 -0
  65. higpertext/capabilities/common/eval-agent.json +33 -0
  66. higpertext/capabilities/common/file-map.json +17 -0
  67. higpertext/capabilities/common/governance-exception.json +54 -0
  68. higpertext/capabilities/common/graph-query.json +59 -0
  69. higpertext/capabilities/common/graph-rebuild.json +31 -0
  70. higpertext/capabilities/common/graph-visualize.json +37 -0
  71. higpertext/capabilities/common/grep-search.json +176 -0
  72. higpertext/capabilities/common/higpertext-tester.json +25 -0
  73. higpertext/capabilities/common/hook-health.json +19 -0
  74. higpertext/capabilities/common/hook-sync-check.json +19 -0
  75. higpertext/capabilities/common/hooks-manager.json +55 -0
  76. higpertext/capabilities/common/knowledge-asker.json +27 -0
  77. higpertext/capabilities/common/list-rules.json +27 -0
  78. higpertext/capabilities/common/llm-invoke.json +59 -0
  79. higpertext/capabilities/common/load-rules.json +37 -0
  80. higpertext/capabilities/common/memory-manager.json +65 -0
  81. higpertext/capabilities/common/quality-scan.json +21 -0
  82. higpertext/capabilities/common/quality-updater.json +35 -0
  83. higpertext/capabilities/common/rag-index.json +17 -0
  84. higpertext/capabilities/common/report-viewer.json +24 -0
  85. higpertext/capabilities/common/roadmap-report.json +37 -0
  86. higpertext/capabilities/common/scripts/_env_cli.py +65 -0
  87. higpertext/capabilities/common/scripts/agent_builder.py +60 -0
  88. higpertext/capabilities/common/scripts/agent_sync.py +56 -0
  89. higpertext/capabilities/common/scripts/ask_higpertext.py +38 -0
  90. higpertext/capabilities/common/scripts/code_skeletonizer.py +225 -0
  91. higpertext/capabilities/common/scripts/commit_report.py +134 -0
  92. higpertext/capabilities/common/scripts/context_assembler.py +70 -0
  93. higpertext/capabilities/common/scripts/context_budget_report.py +53 -0
  94. higpertext/capabilities/common/scripts/dep_manager.py +81 -0
  95. higpertext/capabilities/common/scripts/docs_sync.py +981 -0
  96. higpertext/capabilities/common/scripts/doctor.py +144 -0
  97. higpertext/capabilities/common/scripts/efficiency_meter.py +83 -0
  98. higpertext/capabilities/common/scripts/env_catalog.py +47 -0
  99. higpertext/capabilities/common/scripts/env_clean.py +30 -0
  100. higpertext/capabilities/common/scripts/env_logs.py +32 -0
  101. higpertext/capabilities/common/scripts/env_runner.py +53 -0
  102. higpertext/capabilities/common/scripts/env_status.py +38 -0
  103. higpertext/capabilities/common/scripts/env_stop.py +30 -0
  104. higpertext/capabilities/common/scripts/env_template.py +73 -0
  105. higpertext/capabilities/common/scripts/error_context_locator.py +138 -0
  106. higpertext/capabilities/common/scripts/eval_agent.py +80 -0
  107. higpertext/capabilities/common/scripts/file_map.py +95 -0
  108. higpertext/capabilities/common/scripts/governance_exception.py +116 -0
  109. higpertext/capabilities/common/scripts/graph_query.py +104 -0
  110. higpertext/capabilities/common/scripts/graph_rebuild.py +107 -0
  111. higpertext/capabilities/common/scripts/graph_visualize.py +76 -0
  112. higpertext/capabilities/common/scripts/grep_search.py +648 -0
  113. higpertext/capabilities/common/scripts/higpertext_tester.py +102 -0
  114. higpertext/capabilities/common/scripts/hook_health.py +149 -0
  115. higpertext/capabilities/common/scripts/hook_sync_check.py +134 -0
  116. higpertext/capabilities/common/scripts/hooks_manager.py +171 -0
  117. higpertext/capabilities/common/scripts/list_rules.py +175 -0
  118. higpertext/capabilities/common/scripts/llm_invoke.py +135 -0
  119. higpertext/capabilities/common/scripts/load_rules.py +379 -0
  120. higpertext/capabilities/common/scripts/memory_manager.py +210 -0
  121. higpertext/capabilities/common/scripts/presentation_engine.py +63 -0
  122. higpertext/capabilities/common/scripts/quality_scan.py +132 -0
  123. higpertext/capabilities/common/scripts/rag_index.py +39 -0
  124. higpertext/capabilities/common/scripts/report_viewer.py +106 -0
  125. higpertext/capabilities/common/scripts/roadmap_report.py +73 -0
  126. higpertext/capabilities/common/scripts/search_router.py +111 -0
  127. higpertext/capabilities/common/scripts/semantic_diff.py +166 -0
  128. higpertext/capabilities/common/scripts/semantic_search.py +43 -0
  129. higpertext/capabilities/common/scripts/session_control.py +136 -0
  130. higpertext/capabilities/common/scripts/smart_read.py +232 -0
  131. higpertext/capabilities/common/scripts/subagent_executor.py +143 -0
  132. higpertext/capabilities/common/scripts/sync_agents.py +353 -0
  133. higpertext/capabilities/common/scripts/task_decomposer.py +78 -0
  134. higpertext/capabilities/common/scripts/telemetry_report.py +36 -0
  135. higpertext/capabilities/common/search-router.json +24 -0
  136. higpertext/capabilities/common/semantic-diff.json +40 -0
  137. higpertext/capabilities/common/semantic-search.json +19 -0
  138. higpertext/capabilities/common/session-clean.json +20 -0
  139. higpertext/capabilities/common/session-start.json +44 -0
  140. higpertext/capabilities/common/smart-read.json +28 -0
  141. higpertext/capabilities/common/subagent-executor.json +25 -0
  142. higpertext/capabilities/common/sync-agents.json +32 -0
  143. higpertext/capabilities/common/task-decomposer.json +37 -0
  144. higpertext/capabilities/common/telemetry-report.json +23 -0
  145. higpertext/capabilities/git/__init__.py +0 -0
  146. higpertext/capabilities/git/committer.json +61 -0
  147. higpertext/capabilities/git/diff.json +33 -0
  148. higpertext/capabilities/git/ls-files.json +44 -0
  149. higpertext/capabilities/git/rm.json +27 -0
  150. higpertext/capabilities/git/scripts/__init__.py +0 -0
  151. higpertext/capabilities/git/scripts/commit_changes.py +1077 -0
  152. higpertext/capabilities/git/scripts/git_diff.py +171 -0
  153. higpertext/capabilities/git/scripts/git_ls_files.py +376 -0
  154. higpertext/capabilities/git/scripts/git_rm.py +62 -0
  155. higpertext/capabilities/security/k8s-auditor.json +33 -0
  156. higpertext/capabilities/security/scripts/k8s_auditor.py +307 -0
  157. higpertext/capabilities/security/scripts/secret_scanner.py +235 -0
  158. higpertext/capabilities/security/secret-scanner.json +32 -0
  159. higpertext/hooks/__init__.py +28 -0
  160. higpertext/hooks/_compat.py +27 -0
  161. higpertext/hooks/hook_tasks/__init__.py +1 -0
  162. higpertext/hooks/hook_tasks/_rules/__init__.py +0 -0
  163. higpertext/hooks/hook_tasks/_rules/bash_rules.py +635 -0
  164. higpertext/hooks/hook_tasks/_rules/context_engine_rule.py +79 -0
  165. higpertext/hooks/hook_tasks/_rules/context_rules.py +199 -0
  166. higpertext/hooks/hook_tasks/_rules/governance_adapter.py +72 -0
  167. higpertext/hooks/hook_tasks/_rules/profile_rules.json +25 -0
  168. higpertext/hooks/hook_tasks/_rules/quality_rules.py +86 -0
  169. higpertext/hooks/hook_tasks/_rules/security_rules.py +214 -0
  170. higpertext/hooks/hook_tasks/_rules/session_rules.py +316 -0
  171. higpertext/hooks/hook_tasks/_rules/telemetry_rules.py +121 -0
  172. higpertext/hooks/hook_tasks/audit_logger_hook.py +28 -0
  173. higpertext/hooks/hook_tasks/hook_bash_guard.py +101 -0
  174. higpertext/hooks/hook_tasks/hook_code_quality.py +48 -0
  175. higpertext/hooks/hook_tasks/hook_context_hint.py +46 -0
  176. higpertext/hooks/hook_tasks/hook_context_manager.py +44 -0
  177. higpertext/hooks/hook_tasks/hook_io.py +122 -0
  178. higpertext/hooks/hook_tasks/hook_loop_guard.py +182 -0
  179. higpertext/hooks/hook_tasks/hook_post_observer.py +54 -0
  180. higpertext/hooks/hook_tasks/hook_read_guard.py +85 -0
  181. higpertext/hooks/hook_tasks/hook_security_guard.py +81 -0
  182. higpertext/hooks/hook_tasks/hook_session_prompt.py +83 -0
  183. higpertext/hooks/hook_tasks/hook_session_stop.py +115 -0
  184. higpertext/hooks/hook_tasks/hook_utils.py +144 -0
  185. higpertext/hooks/hook_tasks/session_guard_hook.py +23 -0
  186. higpertext/hooks/hook_tasks/telemetry_utils.py +176 -0
  187. higpertext/hooks/hook_tasks/test_echo_hook.py +33 -0
  188. higpertext/hooks/hook_tasks/webhook_hook.py +54 -0
  189. higpertext/hooks/hook_tasks/workflow_runner_hook.py +49 -0
  190. higpertext/hooks/hooks_catalog.json +116 -0
  191. higpertext/kernel/__init__.py +63 -0
  192. higpertext/kernel/_compat.py +138 -0
  193. higpertext/kernel/app_config.py +117 -0
  194. higpertext/kernel/application/__init__.py +13 -0
  195. higpertext/kernel/application/agent_registry.py +102 -0
  196. higpertext/kernel/application/capability_manager.py +61 -0
  197. higpertext/kernel/application/commit_reporter.py +247 -0
  198. higpertext/kernel/application/context_builder.py +166 -0
  199. higpertext/kernel/application/context_engine.py +409 -0
  200. higpertext/kernel/application/engine.py +41 -0
  201. higpertext/kernel/application/env_runtime.py +174 -0
  202. higpertext/kernel/application/environment_manager.py +154 -0
  203. higpertext/kernel/application/governance.py +192 -0
  204. higpertext/kernel/application/hook_registry.py +102 -0
  205. higpertext/kernel/application/hook_renderer.py +720 -0
  206. higpertext/kernel/application/ports.py +49 -0
  207. higpertext/kernel/application/profile_learner.py +358 -0
  208. higpertext/kernel/application/profile_service.py +205 -0
  209. higpertext/kernel/application/profile_services.py +6 -0
  210. higpertext/kernel/application/profile_use_cases.py +93 -0
  211. higpertext/kernel/application/rag_service.py +75 -0
  212. higpertext/kernel/application/roadmap_reporter.py +178 -0
  213. higpertext/kernel/application/semantic_engine.py +258 -0
  214. higpertext/kernel/application/session_services.py +33 -0
  215. higpertext/kernel/application/skill_hook_compiler.py +85 -0
  216. higpertext/kernel/application/telemetry.py +326 -0
  217. higpertext/kernel/application/workflow_manager.py +176 -0
  218. higpertext/kernel/config_paths.py +66 -0
  219. higpertext/kernel/domain/__init__.py +12 -0
  220. higpertext/kernel/domain/agent_registry.py +23 -0
  221. higpertext/kernel/domain/commit_reporter.py +155 -0
  222. higpertext/kernel/domain/compilers.py +7 -0
  223. higpertext/kernel/domain/context_engine.py +319 -0
  224. higpertext/kernel/domain/entities.py +51 -0
  225. higpertext/kernel/domain/env_runtime.py +62 -0
  226. higpertext/kernel/domain/governance.py +198 -0
  227. higpertext/kernel/domain/hook_models.py +29 -0
  228. higpertext/kernel/domain/profile_learner.py +186 -0
  229. higpertext/kernel/domain/rag.py +70 -0
  230. higpertext/kernel/domain/repositories.py +8 -0
  231. higpertext/kernel/domain/roadmap_reporter.py +80 -0
  232. higpertext/kernel/domain/semantic_engine.py +107 -0
  233. higpertext/kernel/engine.py +42 -0
  234. higpertext/kernel/htx_resolver.py +69 -0
  235. higpertext/kernel/infrastructure/__init__.py +13 -0
  236. higpertext/kernel/infrastructure/agent_registry.py +40 -0
  237. higpertext/kernel/infrastructure/cache/capability_cache.py +319 -0
  238. higpertext/kernel/infrastructure/capability_helper.py +40 -0
  239. higpertext/kernel/infrastructure/cli/__init__.py +1 -0
  240. higpertext/kernel/infrastructure/cli/agent_commands.py +62 -0
  241. higpertext/kernel/infrastructure/cli/arguments.py +39 -0
  242. higpertext/kernel/infrastructure/cli/capability_command_builder.py +86 -0
  243. higpertext/kernel/infrastructure/cli/capability_task_service.py +234 -0
  244. higpertext/kernel/infrastructure/cli/cli_search.py +234 -0
  245. higpertext/kernel/infrastructure/cli/parameter_contracts.py +83 -0
  246. higpertext/kernel/infrastructure/cli/parser_builder.py +122 -0
  247. higpertext/kernel/infrastructure/cli/profile_commands.py +89 -0
  248. higpertext/kernel/infrastructure/cli/roadmap_commands.py +117 -0
  249. higpertext/kernel/infrastructure/cli/router.py +1110 -0
  250. higpertext/kernel/infrastructure/cli/session_commands.py +36 -0
  251. higpertext/kernel/infrastructure/cli/task_commands.py +23 -0
  252. higpertext/kernel/infrastructure/cli/task_result_reporter.py +56 -0
  253. higpertext/kernel/infrastructure/cli/workflow_commands.py +25 -0
  254. higpertext/kernel/infrastructure/compilers/__init__.py +3 -0
  255. higpertext/kernel/infrastructure/compilers/factory.py +27 -0
  256. higpertext/kernel/infrastructure/compilers/graph_compiler.py +20 -0
  257. higpertext/kernel/infrastructure/compilers/guide_compiler.py +50 -0
  258. higpertext/kernel/infrastructure/compilers/hook_compiler.py +69 -0
  259. higpertext/kernel/infrastructure/compilers/playbook_compiler.py +154 -0
  260. higpertext/kernel/infrastructure/context_engine.py +303 -0
  261. higpertext/kernel/infrastructure/database/local_vector_store.py +99 -0
  262. higpertext/kernel/infrastructure/deployment/__init__.py +1 -0
  263. higpertext/kernel/infrastructure/deployment/resource_deployer.py +283 -0
  264. higpertext/kernel/infrastructure/diagnostics/__init__.py +1 -0
  265. higpertext/kernel/infrastructure/diagnostics/health.py +191 -0
  266. higpertext/kernel/infrastructure/env_runtime.py +227 -0
  267. higpertext/kernel/infrastructure/execution/__init__.py +1 -0
  268. higpertext/kernel/infrastructure/execution/parallel.py +188 -0
  269. higpertext/kernel/infrastructure/execution/resilience.py +155 -0
  270. higpertext/kernel/infrastructure/file_repositories.py +213 -0
  271. higpertext/kernel/infrastructure/governance.py +198 -0
  272. higpertext/kernel/infrastructure/hook_config_loader.py +53 -0
  273. higpertext/kernel/infrastructure/hook_webhook_dispatcher.py +61 -0
  274. higpertext/kernel/infrastructure/hook_workflow_bridge.py +60 -0
  275. higpertext/kernel/infrastructure/llm/__init__.py +6 -0
  276. higpertext/kernel/infrastructure/llm/provider.py +46 -0
  277. higpertext/kernel/infrastructure/llm/providers/__init__.py +0 -0
  278. higpertext/kernel/infrastructure/llm/providers/anthropic_provider.py +94 -0
  279. higpertext/kernel/infrastructure/llm/providers/gemini_embeddings.py +74 -0
  280. higpertext/kernel/infrastructure/llm/providers/gemini_provider.py +101 -0
  281. higpertext/kernel/infrastructure/llm/providers/ollama_provider.py +110 -0
  282. higpertext/kernel/infrastructure/llm/providers/openai_provider.py +98 -0
  283. higpertext/kernel/infrastructure/llm/registry.py +81 -0
  284. higpertext/kernel/infrastructure/logger.py +303 -0
  285. higpertext/kernel/infrastructure/output_store.py +70 -0
  286. higpertext/kernel/infrastructure/parser/__init__.py +1 -0
  287. higpertext/kernel/infrastructure/parser/code_chunker.py +144 -0
  288. higpertext/kernel/infrastructure/parser/language/__init__.py +14 -0
  289. higpertext/kernel/infrastructure/parser/language/base.py +41 -0
  290. higpertext/kernel/infrastructure/parser/language/powershell_parser.py +35 -0
  291. higpertext/kernel/infrastructure/parser/language/python_parser.py +98 -0
  292. higpertext/kernel/infrastructure/parser/language/typescript_parser.py +91 -0
  293. higpertext/kernel/infrastructure/parser/semantic_graph.py +409 -0
  294. higpertext/kernel/infrastructure/presentation/__init__.py +1 -0
  295. higpertext/kernel/infrastructure/presentation/html_renderer.py +137 -0
  296. higpertext/kernel/infrastructure/presentation/markdown_renderer.py +84 -0
  297. higpertext/kernel/infrastructure/presentation/markdown_report_renderer.py +97 -0
  298. higpertext/kernel/infrastructure/profile_store.py +28 -0
  299. higpertext/kernel/infrastructure/semantic_engine.py +289 -0
  300. higpertext/kernel/infrastructure/telemetry_reporter.py +132 -0
  301. higpertext/kernel/infrastructure/validation/__init__.py +1 -0
  302. higpertext/kernel/infrastructure/validation/contract_validator.py +163 -0
  303. higpertext/kernel/pkg_resources.py +38 -0
  304. higpertext/kernel/session_manager.py +319 -0
  305. higpertext/templates/env/generic-shell.yaml +21 -0
  306. higpertext/templates/env/node-vitest.yaml +27 -0
  307. higpertext/templates/env/python-pytest.yaml +29 -0
  308. higpertext/templates/html/commit_body.html +20 -0
  309. higpertext/templates/html/commit_diff.html +4 -0
  310. higpertext/templates/html/commit_index.html +29 -0
  311. higpertext/templates/html/commit_layer.html +11 -0
  312. higpertext/templates/html/commit_shell.html +28 -0
  313. higpertext/templates/html/graph_visualize.html +86 -0
  314. higpertext/templates/html/roadmap_body.html +12 -0
  315. higpertext/templates/html/roadmap_phase.html +5 -0
  316. higpertext/templates/html/roadmap_shell.html +29 -0
  317. higpertext/templates/markdown/commit_report.md +18 -0
  318. higpertext/templates/markdown/efficiency_report.md +12 -0
  319. higpertext/templates/markdown/roadmap_report.md +25 -0
  320. higpertext/templates/skills/best-practices.md +7 -0
  321. higpertext/templates/skills/clean-code.md +8 -0
  322. higpertext/templates/skills/ddd-standards.md +7 -0
  323. higpertext/templates/skills/tdd-practices.md +7 -0
  324. higpertext/templates/subagents/architect.md +7 -0
  325. higpertext/templates/subagents/test-engineer.md +7 -0
  326. higpertext/templates/workflows/build.json +23 -0
  327. higpertext/templates/workflows/compact.json +21 -0
  328. higpertext/templates/workflows/plan.json +59 -0
  329. higpertext/templates/workflows/review.json +26 -0
  330. higpertext/templates/workflows/spec.json +27 -0
  331. higpertext_cli-0.8.0.dist-info/METADATA +35 -0
  332. higpertext_cli-0.8.0.dist-info/RECORD +335 -0
  333. higpertext_cli-0.8.0.dist-info/WHEEL +5 -0
  334. higpertext_cli-0.8.0.dist-info/entry_points.txt +2 -0
  335. higpertext_cli-0.8.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,115 @@
1
+ """Hook Stop — cierra sesión automáticamente y muestra resumen de turno."""
2
+
3
+ from __future__ import annotations
4
+ from higpertext.hooks.hook_tasks._rules.governance_adapter import get_session_limits
5
+ import higpertext.hooks.hook_tasks.telemetry_utils as telem
6
+ from higpertext.hooks.hook_tasks.hook_utils import get_project_root
7
+ from higpertext.hooks.hook_tasks.hook_io import (
8
+ hook_main,
9
+ read_json_file,
10
+ emit_stop_reason,
11
+ )
12
+ import sys
13
+ import subprocess # nosec B404
14
+ from pathlib import Path
15
+
16
+ _SRC = Path(__file__).resolve().parents[3] # src/
17
+ if str(_SRC) not in sys.path:
18
+ sys.path.insert(0, str(_SRC))
19
+ from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
20
+
21
+
22
+ def _pending(root: Path) -> tuple[list[str], int, bool]:
23
+ try:
24
+ r = subprocess.run( # nosec B603 B607
25
+ ["git", "status", "--porcelain"],
26
+ capture_output=True,
27
+ text=True,
28
+ cwd=str(root),
29
+ timeout=10,
30
+ )
31
+ lines = [line[3:] for line in r.stdout.strip().splitlines() if line.strip()]
32
+ limit = get_session_limits(root)
33
+ return lines, limit, len(lines) > limit
34
+ except (OSError, subprocess.TimeoutExpired):
35
+ return [], 5, False
36
+
37
+
38
+ def _last_commit(root: Path) -> str:
39
+ try:
40
+ r = subprocess.run( # nosec B603 B607
41
+ ["git", "log", "--oneline", "-1"],
42
+ capture_output=True,
43
+ text=True,
44
+ cwd=str(root),
45
+ timeout=5,
46
+ )
47
+ return r.stdout.strip()
48
+ except (OSError, subprocess.TimeoutExpired):
49
+ return "—"
50
+
51
+
52
+ def _clean_session(root: Path) -> bool:
53
+ """Ejecuta session-clean y devuelve True si tuvo éxito."""
54
+ from higpertext.hooks.hook_tasks.hook_utils import get_htx
55
+
56
+ try:
57
+ r = subprocess.run( # nosec B603
58
+ [get_htx(root), "task", "common.session-clean", "--action", "clean"],
59
+ capture_output=True,
60
+ text=True,
61
+ cwd=str(root),
62
+ timeout=20,
63
+ )
64
+ return r.returncode == 0
65
+ except Exception:
66
+ return False
67
+
68
+
69
+ def _build_banner(
70
+ files: list[str],
71
+ limit: int,
72
+ exceeded: bool,
73
+ commit: str,
74
+ active: bool,
75
+ sid: str,
76
+ profile: str,
77
+ ) -> str:
78
+ lines = ["╔─ HIGPERTEXT · Fin de turno ──────────────────────────────"]
79
+ if files:
80
+ indicator = "❌ [GOBERNANZA]" if exceeded else "⚠"
81
+ lines.append(f"│ {indicator} {len(files)} archivo(s) sin commitear (Límite: {limit}):")
82
+ for f in files[:8]:
83
+ lines.append(f"│ • {f}")
84
+ if len(files) > 8:
85
+ lines.append(f"│ ... y {len(files) - 8} más")
86
+ lines.append('│ → committer --message "tipo(scope): descripción"')
87
+ else:
88
+ lines.append(f"│ ✓ Working tree limpio · {commit}")
89
+ if active:
90
+ lines.append(f"│ Sesión : {sid} · perfil: {profile}")
91
+ lines.append("│ ✓ Workspace restablecido al estado inicial")
92
+ lines.append("╚───────────────────────────────────────────────────────")
93
+ return "\n".join(lines)
94
+
95
+
96
+ @hook_main
97
+ def main() -> None:
98
+ root = get_project_root()
99
+ session = read_json_file(root / WORKSPACE_DIR_NAME / "state" / "session.json")
100
+ env = read_json_file(root / WORKSPACE_DIR_NAME / "config" / "environment.json")
101
+ active = session.get("status") == "active"
102
+ sid = session.get("session_id", "—")
103
+ profile = env.get("active_profile", "global")
104
+ files, limit, exceeded = _pending(root)
105
+ commit = _last_commit(root)
106
+
107
+ if active:
108
+ telem.session_stop(root, sid, profile)
109
+ _clean_session(root)
110
+
111
+ emit_stop_reason(_build_banner(files, limit, exceeded, commit, active, sid, profile))
112
+
113
+
114
+ if __name__ == "__main__":
115
+ main()
@@ -0,0 +1,144 @@
1
+ """Utilidades compartidas para hook tasks de higpertext."""
2
+
3
+ from __future__ import annotations
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ # Add src to sys.path so we can import from higpertext
8
+
9
+ import json
10
+ import platform
11
+ import shutil
12
+ # Helpers ejecutan htx con shell=False.
13
+ import subprocess # nosec B404
14
+ from datetime import datetime, timezone
15
+
16
+ sys_path_src = Path(__file__).resolve().parents[3]
17
+ if str(sys_path_src) not in sys.path:
18
+ sys.path.insert(0, str(sys_path_src))
19
+ from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
20
+ HIGPERTEXT_DIR = WORKSPACE_DIR_NAME
21
+
22
+
23
+
24
+ def get_project_root() -> Path:
25
+ """Resuelve la raíz del proyecto desde environment.json.
26
+
27
+ Cuando un hook task se despliega en .<assistant>/hooks/, el archivo
28
+ environment.json se encuentra en ../../.higpertext/environment.json relativo
29
+ al script. Siempre hay un htx.py launcher en esa raíz.
30
+ """
31
+ # Busca environment.json en dos ubicaciones candidatas:
32
+ # 1. Relativo al script (cuando el hook está desplegado en .<assistant>/hooks/)
33
+ # 2. Relativo al CWD del proceso (cuando se ejecuta desde la raíz del proyecto)
34
+ candidates = [
35
+ Path(__file__).resolve().parent
36
+ / ".."
37
+ / ".."
38
+ / HIGPERTEXT_DIR
39
+ / "config"
40
+ / "environment.json",
41
+ Path.cwd() / HIGPERTEXT_DIR / "config" / "environment.json",
42
+ ]
43
+ for env_path in candidates:
44
+ env_path = env_path.resolve()
45
+ if env_path.exists():
46
+ try:
47
+ data = json.loads(env_path.read_text(encoding="utf-8"))
48
+ root = data.get("system_environment", {}).get("project_root")
49
+ if root:
50
+ return Path(root)
51
+ except (OSError, json.JSONDecodeError): # nosec B110
52
+ pass
53
+ # Fallback: CWD si contiene htx.py (indica que somos la raíz del proyecto)
54
+ cwd = Path.cwd()
55
+ if (cwd / "htx.py").exists():
56
+ return cwd
57
+ return Path(__file__).resolve().parents[1]
58
+
59
+
60
+ def get_htx() -> str:
61
+ """Retorna el primer elemento del comando htx resuelto via htx_resolver."""
62
+ root = get_project_root()
63
+ try:
64
+ from higpertext.kernel.htx_resolver import get_htx_cmd
65
+
66
+ cmd = get_htx_cmd(root)
67
+ return cmd[0]
68
+ except ImportError:
69
+ venv_htx = root / ".venv" / ("Scripts" if platform.system() == "Windows" else "bin") / "htx"
70
+ if venv_htx.exists():
71
+ return str(venv_htx)
72
+ if htx := shutil.which("htx"):
73
+ return htx
74
+ return str(root / ".venv" / "bin" / "python")
75
+
76
+
77
+ def _htx_args(capability: str, params: dict) -> list[str]:
78
+ htx = get_htx()
79
+ base = (
80
+ [htx, "task", capability]
81
+ if not htx.endswith("python")
82
+ else [htx, "htx.py", "task", capability]
83
+ )
84
+ return base + [arg for k, v in params.items() for arg in (f"--{k}", str(v))]
85
+
86
+
87
+ def hook_log_path(root: Path | None = None) -> Path:
88
+ """Retorna la ruta del log estructurado de hooks."""
89
+ base = root or get_project_root()
90
+ return base / HIGPERTEXT_DIR / "logs" / "hooks.jsonl"
91
+
92
+
93
+ def log_hook_event(event: dict, root: Path | None = None) -> None:
94
+ """Registra un evento JSONL de hook sin interrumpir la ejecución."""
95
+ try:
96
+ path = hook_log_path(root)
97
+ path.parent.mkdir(parents=True, exist_ok=True)
98
+ payload = {
99
+ "timestamp": datetime.now(timezone.utc).isoformat(),
100
+ **event,
101
+ }
102
+ with path.open("a", encoding="utf-8") as fh:
103
+ fh.write(json.dumps(payload, ensure_ascii=False, sort_keys=True) + "\n")
104
+ except OSError: # nosec B110
105
+ pass
106
+
107
+
108
+ def log_hook_error(hook_id: str, message: str, root: Path | None = None, **extra: object) -> None:
109
+ """Registra errores no bloqueantes de hooks."""
110
+ log_hook_event(
111
+ {
112
+ "severity": "error",
113
+ "hook_id": hook_id,
114
+ "message": message[:1000],
115
+ **extra,
116
+ },
117
+ root=root,
118
+ )
119
+
120
+
121
+ def run_higpertext_task(capability: str, params: dict) -> str:
122
+ """Ejecuta una capability higpertext y retorna su output combinado."""
123
+ root = get_project_root()
124
+ args = _htx_args(capability, params)
125
+ try:
126
+ result = subprocess.run(args, capture_output=True, text=True, cwd=str(root), timeout=30)
127
+ except subprocess.TimeoutExpired as exc:
128
+ log_hook_error(
129
+ "run_higpertext_task",
130
+ f"Timeout ejecutando capability {capability}",
131
+ root=root,
132
+ capability=capability,
133
+ timeout=exc.timeout,
134
+ )
135
+ return str(exc)
136
+ if result.returncode != 0:
137
+ log_hook_error(
138
+ "run_higpertext_task",
139
+ f"Capability {capability} terminó con código {result.returncode}",
140
+ root=root,
141
+ capability=capability,
142
+ returncode=result.returncode,
143
+ )
144
+ return (result.stdout or "") + (result.stderr or "")
@@ -0,0 +1,23 @@
1
+ """Hook SessionStart — verifica estado de la sesión y emite continue."""
2
+
3
+ from __future__ import annotations
4
+ import json
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ _SRC = Path(__file__).resolve().parents[3]
9
+ if str(_SRC) not in sys.path:
10
+ sys.path.insert(0, str(_SRC))
11
+
12
+
13
+ def main() -> None:
14
+ raw = sys.stdin.read().strip()
15
+ try:
16
+ json.loads(raw) if raw else {}
17
+ except json.JSONDecodeError: # nosec B110
18
+ pass
19
+ print(json.dumps({"continue": True}))
20
+
21
+
22
+ if __name__ == "__main__":
23
+ main()
@@ -0,0 +1,176 @@
1
+ """Wrapper liviano de telemetría para uso desde hook tasks desplegados."""
2
+
3
+ from __future__ import annotations
4
+ from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
5
+
6
+ import json
7
+ from datetime import datetime, timezone
8
+ from pathlib import Path
9
+
10
+
11
+ def _now() -> str:
12
+ return datetime.now(timezone.utc).isoformat(timespec="seconds")
13
+
14
+
15
+ def _store(root: Path) -> Path:
16
+ return root / WORKSPACE_DIR_NAME / "state" / "telemetry.jsonl"
17
+
18
+
19
+ def _project_id(root: Path) -> str:
20
+ """Lee project_id desde environment.json → variables.repository_id."""
21
+ env_file = root / WORKSPACE_DIR_NAME / "config" / "environment.json"
22
+ try:
23
+ data = json.loads(env_file.read_text(encoding="utf-8"))
24
+ return (
25
+ data.get("variables", {}).get("repository_id") or data.get("project_name") or root.name
26
+ )
27
+ except (OSError, json.JSONDecodeError):
28
+ return root.name
29
+
30
+
31
+ def record(root: Path, event: str, **fields) -> None:
32
+ entry = {"ts": _now(), "event": event, "project_id": _project_id(root), **fields}
33
+ try:
34
+ with _store(root).open("a", encoding="utf-8") as fh:
35
+ fh.write(json.dumps(entry, ensure_ascii=False) + "\n")
36
+ except OSError: # nosec B110
37
+ pass
38
+
39
+
40
+ def session_start(root: Path, session_id: str, profile: str) -> None:
41
+ record(root, "session_start", session_id=session_id, profile=profile)
42
+
43
+
44
+ def session_stop(root: Path, session_id: str, profile: str) -> None:
45
+ """Calcula duración buscando el session_start correspondiente en el store."""
46
+ duration_min = _calc_duration(root, session_id)
47
+ record(
48
+ root,
49
+ "session_stop",
50
+ session_id=session_id,
51
+ profile=profile,
52
+ duration_min=round(duration_min, 2),
53
+ )
54
+
55
+
56
+ def tool_call(
57
+ root: Path,
58
+ session_id: str,
59
+ tool_name: str,
60
+ input_chars: int,
61
+ output_chars: int,
62
+ is_higpertext_call: bool = False,
63
+ ) -> None:
64
+ # Precios claude-sonnet-4-6 (junio 2026, por millón de tokens)
65
+ # Distribución real del usuario: 98% cache_read, 2% output/write
66
+ # input=$3/M output=$15/M cache_write=$3.75/M cache_read=$0.30/M
67
+ input_tokens = input_chars // 4
68
+ output_tokens = output_chars // 4
69
+ # Aproximación: input_chars del LLM son mayoritariamente cache_read
70
+ # Se estima 80% cache_read + 20% cache_write del input
71
+ cache_read_tokens = int(input_tokens * 0.80)
72
+ cache_write_tokens = int(input_tokens * 0.20)
73
+ estimated_tokens = input_tokens + output_tokens
74
+
75
+ cost = (
76
+ cache_read_tokens * 0.30 / 1_000_000
77
+ + cache_write_tokens * 3.75 / 1_000_000
78
+ + output_tokens * 15.0 / 1_000_000
79
+ )
80
+ record(
81
+ root,
82
+ "tool_call",
83
+ session_id=session_id,
84
+ tool=tool_name,
85
+ input_chars=input_chars,
86
+ output_chars=output_chars,
87
+ estimated_tokens=estimated_tokens,
88
+ estimated_cost_usd=round(cost, 6),
89
+ is_higpertext_call=is_higpertext_call,
90
+ )
91
+
92
+
93
+ def activity(
94
+ root: Path,
95
+ session_id: str,
96
+ tool: str,
97
+ op_type: str,
98
+ target: str,
99
+ scope: str = "",
100
+ higpertext_related: bool = False,
101
+ ) -> None:
102
+ """Registra una operación atómica del agente (Edit, Write, Read, Bash, etc.)."""
103
+ record(
104
+ root,
105
+ "activity",
106
+ session_id=session_id,
107
+ tool=tool,
108
+ op_type=op_type,
109
+ target=target[:120],
110
+ scope=scope,
111
+ higpertext_related=higpertext_related,
112
+ )
113
+
114
+
115
+ def hook_intercept(root: Path, session_id: str, capability_id: str, fragment: str) -> None:
116
+ record(
117
+ root,
118
+ "hook_intercept",
119
+ session_id=session_id,
120
+ capability=capability_id,
121
+ fragment=fragment[:80],
122
+ )
123
+
124
+
125
+ def capability_used(root: Path, session_id: str, capability_id: str) -> None:
126
+ record(root, "capability_used", session_id=session_id, capability=capability_id)
127
+
128
+
129
+ def commit_event(
130
+ root: Path,
131
+ session_id: str,
132
+ commit_hash: str,
133
+ commit_type: str,
134
+ scope: str,
135
+ profile: str,
136
+ ) -> None:
137
+ record(
138
+ root,
139
+ "commit",
140
+ session_id=session_id,
141
+ hash=commit_hash,
142
+ type=commit_type,
143
+ scope=scope,
144
+ profile=profile,
145
+ )
146
+
147
+
148
+ # ------------------------------------------------------------------
149
+ # Helpers
150
+ # ------------------------------------------------------------------
151
+
152
+
153
+ def _calc_duration(root: Path, session_id: str) -> float:
154
+ """Busca el session_start del session_id y retorna minutos transcurridos."""
155
+ store = _store(root)
156
+ if not store.exists():
157
+ return 0.0
158
+ start_ts = None
159
+ try:
160
+ for line in store.read_text(encoding="utf-8").splitlines():
161
+ try:
162
+ e = json.loads(line)
163
+ if e.get("event") == "session_start" and e.get("session_id") == session_id:
164
+ start_ts = e.get("ts")
165
+ except (json.JSONDecodeError, KeyError):
166
+ continue
167
+ except OSError:
168
+ return 0.0
169
+ if not start_ts:
170
+ return 0.0
171
+ try:
172
+ t0 = datetime.fromisoformat(start_ts)
173
+ t1 = datetime.now(timezone.utc)
174
+ return (t1 - t0).total_seconds() / 60
175
+ except ValueError:
176
+ return 0.0
@@ -0,0 +1,33 @@
1
+ """Hook de diagnóstico — devuelve continue:true con echo del payload."""
2
+
3
+ from __future__ import annotations
4
+ import json
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ _SRC = Path(__file__).resolve().parents[3]
9
+ if str(_SRC) not in sys.path:
10
+ sys.path.insert(0, str(_SRC))
11
+
12
+
13
+ def main() -> None:
14
+ raw = sys.stdin.read().strip()
15
+ try:
16
+ payload = json.loads(raw) if raw else {}
17
+ except json.JSONDecodeError:
18
+ payload = {}
19
+ print(
20
+ json.dumps(
21
+ {
22
+ "continue": True,
23
+ "hookSpecificOutput": {
24
+ "hookEventName": "PreToolUse",
25
+ "additionalContext": f"[hooks] echo: {json.dumps(payload)}",
26
+ },
27
+ }
28
+ )
29
+ )
30
+
31
+
32
+ if __name__ == "__main__":
33
+ main()
@@ -0,0 +1,54 @@
1
+ """Hook PostToolUse/Stop — dispara webhooks configurados en hooks_config.json."""
2
+ from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
3
+
4
+ import sys
5
+ import json
6
+ from pathlib import Path
7
+
8
+
9
+ def main() -> None:
10
+ data = json.load(sys.stdin)
11
+ event = data.get("hook_event", "PostToolUse")
12
+ tool_name = data.get("tool_name", "")
13
+ session_id = data.get("session_id", "")
14
+
15
+ root = Path(__file__).resolve().parents[5]
16
+
17
+ # Importación dinámica para evitar dependencia de sys.path en tiempo de hook
18
+ import importlib.util
19
+
20
+ spec = importlib.util.spec_from_file_location(
21
+ "webhook_dispatcher",
22
+ root / "src" / "higpertext" / "hooks" / "webhook_dispatcher.py",
23
+ )
24
+ mod = importlib.util.module_from_spec(spec) # type: ignore[arg-type]
25
+ spec.loader.exec_module(mod) # type: ignore[union-attr]
26
+
27
+ env_path = root / WORKSPACE_DIR_NAME / "config" / "environment.json"
28
+ assistant = "claude"
29
+ profile = "software_developer"
30
+ if env_path.exists():
31
+ try:
32
+ env = json.loads(env_path.read_text(encoding="utf-8"))
33
+ assistant = env.get("assistant", assistant)
34
+ profile = env.get("active_profile", profile)
35
+ except (OSError, json.JSONDecodeError): # nosec B110
36
+ pass
37
+
38
+ dispatcher = mod.WebhookDispatcher(root)
39
+ dispatcher.dispatch(
40
+ event,
41
+ assistant,
42
+ {
43
+ "tool": tool_name,
44
+ "session_id": session_id,
45
+ "profile": profile,
46
+ "assistant": assistant,
47
+ },
48
+ )
49
+
50
+ print(json.dumps({"continue": True}))
51
+
52
+
53
+ if __name__ == "__main__":
54
+ main()
@@ -0,0 +1,49 @@
1
+ """Hook task — ejecuta un workflow higpertext como hook PostToolUse o Stop."""
2
+
3
+ import sys
4
+ import json
5
+ import argparse
6
+ from higpertext.hooks.hook_tasks.hook_utils import get_project_root, get_htx
7
+ # Workflow runner usa comando htx controlado.
8
+ import subprocess # nosec B404
9
+
10
+ from higpertext.kernel.infrastructure.logger import get_logger
11
+ _log = get_logger()
12
+
13
+
14
+ def main() -> None:
15
+ parser = argparse.ArgumentParser()
16
+ parser.add_argument("--workflow", required=True)
17
+ args, _ = parser.parse_known_args()
18
+
19
+ hook_data: dict = {}
20
+ if not sys.stdin.isatty():
21
+ try:
22
+ hook_data = json.load(sys.stdin)
23
+ except (json.JSONDecodeError, ValueError): # nosec B110
24
+ pass
25
+
26
+ root = get_project_root()
27
+ result = subprocess.run(
28
+ [get_htx(root), "workflow", "run", args.workflow],
29
+ capture_output=True,
30
+ text=True,
31
+ cwd=str(root),
32
+ )
33
+ output = result.stdout or result.stderr
34
+
35
+ print(
36
+ json.dumps(
37
+ {
38
+ "continue": True,
39
+ "hookSpecificOutput": {
40
+ "hookEventName": hook_data.get("hook_event", "PostToolUse"),
41
+ "additionalContext": output[:2000],
42
+ },
43
+ }
44
+ )
45
+ )
46
+
47
+
48
+ if __name__ == "__main__":
49
+ main()