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,247 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass, field
3
+
4
+ from higpertext.kernel.domain.commit_reporter import Commit, FileChange, CommitReport, CommitType, Layer
5
+ from higpertext.kernel.app_config import LOG_SEP as _LOG_SEP
6
+ from higpertext.kernel.infrastructure.presentation.html_renderer import HtmlReportRenderer
7
+ from higpertext.kernel.infrastructure.presentation.markdown_report_renderer import MarkdownReportRenderer
8
+
9
+ def parse_git_stat_line(line: str) -> tuple[str, str] | None:
10
+ """Parsea una línea de `git --stat` en tiempo lineal, sin regex con cuantificadores."""
11
+ path_part, separator, rest = line.strip().partition("|")
12
+ if not separator:
13
+ return None
14
+ path = path_part.strip()
15
+ if not path:
16
+ return None
17
+ fields = rest.strip().split(maxsplit=1)
18
+ if not fields or not fields[0].isdigit():
19
+ return None
20
+ markers = fields[1].strip() if len(fields) > 1 else ""
21
+ if any(char not in "+-" for char in markers):
22
+ return None
23
+ return path, markers
24
+
25
+
26
+ def parse_git_header(line: str) -> tuple[str, str] | None:
27
+ commit_hash, separator, message = line.strip().partition(" ")
28
+ if not separator or len(commit_hash) < 6:
29
+ return None
30
+ if any(char not in "0123456789abcdef" for char in commit_hash.lower()):
31
+ return None
32
+ return commit_hash, message.strip()
33
+
34
+
35
+ def first_prefixed_value(lines: list[str], prefix: str) -> str:
36
+ for line in lines:
37
+ if line.startswith(prefix):
38
+ return line.removeprefix(prefix).strip()
39
+ return "unknown"
40
+
41
+ class CommitParser:
42
+ """Parsea salida de git show/log en objetos de dominio."""
43
+
44
+ def parse_show(self, output: str) -> CommitReport | None:
45
+ if not output.strip():
46
+ return None
47
+ lines = output.strip().splitlines()
48
+ header = parse_git_header(lines[0])
49
+ if not header:
50
+ return None
51
+
52
+ commit_hash, message = header
53
+
54
+ commit = Commit(
55
+ hash=commit_hash,
56
+ message=message,
57
+ author=first_prefixed_value(lines, "Author:"),
58
+ date=first_prefixed_value(lines, "Date:"),
59
+ )
60
+ changes = self._parse_stat_lines(lines)
61
+ return CommitReport(commit=commit, changes=changes)
62
+
63
+ def parse_log(self, output: str) -> list[Commit]:
64
+ commits = []
65
+ for line in output.strip().splitlines():
66
+ if _LOG_SEP not in line:
67
+ continue
68
+ parts = line.split(_LOG_SEP)
69
+ if len(parts) < 4:
70
+ continue
71
+ commits.append(
72
+ Commit(
73
+ hash=parts[0].strip(),
74
+ message=parts[1].strip(),
75
+ author=parts[2].strip(),
76
+ date=parts[3].strip(),
77
+ )
78
+ )
79
+ return commits
80
+
81
+ def _parse_stat_lines(self, lines: list[str]) -> list[FileChange]:
82
+ changes = []
83
+ for line in lines:
84
+ parsed = parse_git_stat_line(line)
85
+ if not parsed:
86
+ continue
87
+ path, markers = parsed
88
+ additions = markers.count("+")
89
+ deletions = markers.count("-")
90
+ changes.append(FileChange(path=path, additions=additions, deletions=deletions))
91
+ return changes
92
+
93
+
94
+ _TYPE_LABELS = {
95
+ CommitType.FEAT: "new feature",
96
+ CommitType.FIX: "bug fix",
97
+ CommitType.DOCS: "documentation update",
98
+ CommitType.REFACTOR: "refactor",
99
+ CommitType.TEST: "test improvement",
100
+ CommitType.CHORE: "chore/maintenance",
101
+ CommitType.PERF: "performance improvement",
102
+ CommitType.CI: "CI/CD change",
103
+ CommitType.OTHER: "change",
104
+ }
105
+
106
+
107
+ @dataclass
108
+ class CommitAnalysis:
109
+ summary: str
110
+ has_new_tests: bool
111
+ has_new_capabilities: bool
112
+ impact_tags: list[str] = field(default_factory=list)
113
+
114
+
115
+ class ImpactAnalyzer:
116
+ """Analiza un CommitReport y produce un resumen explicativo."""
117
+
118
+ def analyze(self, report: CommitReport) -> CommitAnalysis:
119
+ commit = report.commit
120
+ type_label = _TYPE_LABELS.get(commit.commit_type, "change")
121
+ scope_part = f" in `{commit.scope}`" if commit.scope else ""
122
+ summary = f"This commit introduces a {type_label}{scope_part}: {commit.subject}."
123
+
124
+ tags = self._build_tags(report)
125
+ return CommitAnalysis(
126
+ summary=summary,
127
+ has_new_tests=report.has_new_tests,
128
+ has_new_capabilities=report.has_new_capabilities,
129
+ impact_tags=tags,
130
+ )
131
+
132
+ def _build_tags(self, report: CommitReport) -> list[str]:
133
+ tags = [report.commit.commit_type.value]
134
+ by_layer = report.files_by_layer()
135
+ if Layer.TEST in by_layer:
136
+ tags.append("tested")
137
+ if Layer.CAPABILITY in by_layer:
138
+ tags.append("new-capability")
139
+ if Layer.DOMAIN in by_layer:
140
+ tags.append("domain-change")
141
+ if Layer.INFRASTRUCTURE in by_layer:
142
+ tags.append("infra-change")
143
+ return tags
144
+
145
+
146
+ _LAYER_ORDER = [
147
+ Layer.DOMAIN,
148
+ Layer.APPLICATION,
149
+ Layer.INFRASTRUCTURE,
150
+ Layer.CAPABILITY,
151
+ Layer.TEST,
152
+ Layer.OTHER,
153
+ ]
154
+
155
+ _TYPE_COLOR = {
156
+ CommitType.FEAT: "#3fb950",
157
+ CommitType.FIX: "#f85149",
158
+ CommitType.DOCS: "#79c0ff",
159
+ CommitType.REFACTOR: "#d2a8ff",
160
+ CommitType.TEST: "#e3b341",
161
+ CommitType.CHORE: "#8b949e",
162
+ CommitType.PERF: "#ffa657",
163
+ CommitType.CI: "#bc8cff",
164
+ CommitType.OTHER: "#8b949e",
165
+ }
166
+
167
+
168
+ class ReportBuilder:
169
+ """Genera reportes Markdown y HTML a partir de CommitReport + CommitAnalysis."""
170
+
171
+ def to_markdown(
172
+ self, report: CommitReport, analysis: CommitAnalysis, diff: str | None = None
173
+ ) -> str:
174
+ c = report.commit
175
+ renderer = MarkdownReportRenderer()
176
+ tags = " ".join(f"`{t}`" for t in analysis.impact_tags)
177
+ layers_md = self._build_layers_md(report)
178
+ diff_section = "\n---\n\n## Diff completo\n```diff\n" + diff + "\n```" if diff else ""
179
+ return renderer.render_commit_report(
180
+ short_hash=c.short_hash,
181
+ date=c.date,
182
+ author=c.author,
183
+ summary=analysis.summary,
184
+ tags=tags,
185
+ changed_files_count=report.changed_files_count,
186
+ total_additions=report.total_additions,
187
+ total_deletions=report.total_deletions,
188
+ layers_md=layers_md,
189
+ diff_section=diff_section,
190
+ )
191
+
192
+ @staticmethod
193
+ def _build_layers_md(report: CommitReport) -> str:
194
+ by_layer = report.files_by_layer()
195
+ sections: list[str] = []
196
+ for layer in _LAYER_ORDER:
197
+ files = by_layer.get(layer, [])
198
+ if not files:
199
+ continue
200
+ sections.append(f"\n### {layer.value.capitalize()}")
201
+ for f in files:
202
+ sections.append(f"- `{f.path}` — +{f.additions} / -{f.deletions}")
203
+ return "\n".join(sections)
204
+
205
+ def to_html(
206
+ self, report: CommitReport, analysis: CommitAnalysis, diff: str | None = None
207
+ ) -> str:
208
+ c = report.commit
209
+ renderer = HtmlReportRenderer()
210
+ color = _TYPE_COLOR.get(c.commit_type, "#8b949e")
211
+ tags_html = " ".join(
212
+ f'<span class="tag">{t}</span>' for t in analysis.impact_tags
213
+ )
214
+ layers_html = self._build_layers_html(report, renderer)
215
+ diff_section = renderer.render_diff(renderer.build_diff_lines(diff)) if diff else ""
216
+ body = renderer.render_body(
217
+ commit_type=c.commit_type.value,
218
+ subject=c.subject,
219
+ short_hash=c.short_hash,
220
+ date=c.date,
221
+ author=c.author,
222
+ summary=analysis.summary,
223
+ tags_html=tags_html,
224
+ changed_files_count=report.changed_files_count,
225
+ total_additions=report.total_additions,
226
+ total_deletions=report.total_deletions,
227
+ layers_html=layers_html,
228
+ diff_section=diff_section,
229
+ )
230
+ return renderer.render_shell(c.short_hash, color, body)
231
+
232
+ @staticmethod
233
+ def _build_layers_html(report: CommitReport, renderer: HtmlReportRenderer) -> str:
234
+ by_layer = report.files_by_layer()
235
+ sections: list[str] = []
236
+ for layer in _LAYER_ORDER:
237
+ files = by_layer.get(layer, [])
238
+ if not files:
239
+ continue
240
+ rows = "".join(
241
+ f"<tr><td><code>{f.path}</code></td>"
242
+ f'<td class="add">+{f.additions}</td>'
243
+ f'<td class="del">-{f.deletions}</td></tr>'
244
+ for f in files
245
+ )
246
+ sections.append(renderer.render_layer(layer.value.capitalize(), rows))
247
+ return "\n".join(sections)
@@ -0,0 +1,166 @@
1
+ """SessionContextBuilder — resuelve skills y subagentes para una sesión (Aplicación)."""
2
+
3
+ from __future__ import annotations
4
+ from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
5
+ import json
6
+ from pathlib import Path
7
+
8
+ from higpertext.kernel.infrastructure.logger import get_logger
9
+ from higpertext.kernel.app_config import UNIVERSAL_SKILLS as _UNIVERSAL_SKILLS
10
+ _log = get_logger()
11
+
12
+ _UNIVERSAL_SUBAGENTS = []
13
+
14
+
15
+ class SessionContextBuilder:
16
+ """Responsabilidad única: determinar qué skills/subagentes montar en sesión."""
17
+
18
+ def __init__(self, project_root: Path, root_dir: Path) -> None:
19
+ self.project_root = project_root
20
+ self.root_dir = root_dir
21
+
22
+ def resolve_resources(
23
+ self,
24
+ profile_name: str,
25
+ skills: list | None,
26
+ subagents: list | None,
27
+ ) -> tuple[list, list]:
28
+ if not skills and not subagents:
29
+ skills, subagents, loaded = self.load_resources_from_roadmap(profile_name)
30
+ if not loaded:
31
+ skills, subagents = self.load_resources_from_profile(profile_name)
32
+ return skills or [], subagents or []
33
+
34
+ def load_resources_from_roadmap(self, profile_name: str = "") -> tuple[list, list, bool]:
35
+ roadmaps_dir = self.project_root / WORKSPACE_DIR_NAME / "config" / "roadmaps"
36
+ active_index = roadmaps_dir / "active.json"
37
+ if active_index.exists():
38
+ return self._load_from_roadmaps_dir(roadmaps_dir, active_index, profile_name)
39
+ return self._load_from_single_roadmap(profile_name)
40
+
41
+ def _load_from_roadmaps_dir(
42
+ self, roadmaps_dir: Path, active_index: Path, profile_name: str
43
+ ) -> tuple[list, list, bool]:
44
+ try:
45
+ active_ids: list[str] = json.loads(active_index.read_text(encoding="utf-8")).get(
46
+ "active", []
47
+ )
48
+ except (OSError, json.JSONDecodeError):
49
+ return [], [], False
50
+
51
+ if not active_ids:
52
+ return [], [], False
53
+
54
+ merged_skills: list[str] = []
55
+ merged_subagents: list[str] = []
56
+ loaded: list[str] = []
57
+
58
+ for rid in active_ids:
59
+ roadmap_file = roadmaps_dir / f"{rid}.json"
60
+ if not roadmap_file.exists():
61
+ _log.warning(f"[!] Roadmap '{rid}' no encontrado en roadmaps/ — omitiendo.")
62
+ continue
63
+ try:
64
+ self._process_roadmap_file(
65
+ roadmap_file, rid, profile_name, merged_skills, merged_subagents, loaded
66
+ )
67
+ except (OSError, json.JSONDecodeError):
68
+ continue
69
+
70
+ if not loaded:
71
+ return [], [], False
72
+
73
+ projects_str = ", ".join(f"'{p}'" for p in loaded)
74
+ _log.info(
75
+ f"[*] Roadmaps activos: {projects_str} — montando {len(merged_skills)} "
76
+ f"skill(s) y {len(merged_subagents)} subagente(s)."
77
+ )
78
+ return merged_skills, merged_subagents, True
79
+
80
+ def _process_roadmap_file(
81
+ self,
82
+ roadmap_file: Path,
83
+ rid: str,
84
+ profile_name: str,
85
+ merged_skills: list[str],
86
+ merged_subagents: list[str],
87
+ loaded: list[str],
88
+ ) -> None:
89
+ data = json.loads(roadmap_file.read_text(encoding="utf-8"))
90
+ roadmap_profile = data.get("profile", "")
91
+ if roadmap_profile and profile_name and roadmap_profile != profile_name:
92
+ _log.warning(
93
+ f"[!] Roadmap '{rid}' es de perfil '{roadmap_profile}'"
94
+ f" (activo: '{profile_name}') — omitiendo."
95
+ )
96
+ return
97
+ res = data.get("session_resources", {})
98
+ for s in res.get("skills", []):
99
+ if s not in merged_skills:
100
+ merged_skills.append(s)
101
+ for sa in res.get("subagents", []):
102
+ if sa not in merged_subagents:
103
+ merged_subagents.append(sa)
104
+ loaded.append(data.get("project", rid))
105
+
106
+ def _load_from_single_roadmap(self, profile_name: str) -> tuple[list, list, bool]:
107
+ roadmap_file = self.project_root / WORKSPACE_DIR_NAME / "config" / "roadmap.json"
108
+ if not roadmap_file.exists():
109
+ return [], [], False
110
+ try:
111
+ data = json.loads(roadmap_file.read_text(encoding="utf-8"))
112
+ roadmap_profile = data.get("profile", "")
113
+ if roadmap_profile and profile_name and roadmap_profile != profile_name:
114
+ _log.warning(
115
+ f"[!] Roadmap '{data.get('project', '')}' es de perfil"
116
+ f" '{roadmap_profile}' (activo: '{profile_name}') — ignorando roadmap."
117
+ )
118
+ return [], [], False
119
+ res = data.get("session_resources", {})
120
+ skills = res.get("skills", [])
121
+ subagents = res.get("subagents", [])
122
+ if skills or subagents:
123
+ _log.info(f"[*] Roadmap detectado: '{
124
+ data.get(
125
+ 'project',
126
+ '')}' — montando {
127
+ len(skills)} skill(s) y {
128
+ len(subagents)} subagente(s).")
129
+ return skills, subagents, True
130
+ except (OSError, json.JSONDecodeError): # nosec B110
131
+ pass
132
+ return [], [], False
133
+
134
+ def load_resources_from_profile(self, profile_name: str) -> tuple[list, list]:
135
+ skills, subagents = self._resolve_profile_resources(profile_name)
136
+ if not skills and not subagents:
137
+ skills, subagents = _UNIVERSAL_SKILLS[:], _UNIVERSAL_SUBAGENTS[:]
138
+ _log.info(
139
+ f"[*] Sin roadmap ni recursos en perfil '{profile_name}'"
140
+ f" — montando Set Universal de Desarrollo."
141
+ )
142
+ else:
143
+ _log.info(f"[*] Sin roadmap activo — usando recursos del perfil '{profile_name}'.")
144
+ return skills, subagents
145
+
146
+ def _resolve_profile_resources(self, profile_name: str) -> tuple[list, list]:
147
+ """Delega en ProfileService para resolver la jerarquía de perfiles."""
148
+ try:
149
+ from higpertext.kernel.infrastructure.file_repositories import (
150
+ FileProfileRepository,
151
+ FileCapabilityRepository,
152
+ )
153
+ from higpertext.kernel.application.profile_service import ProfileService
154
+ from higpertext.kernel.pkg_resources import resolve_resource
155
+
156
+ profiles_repo = FileProfileRepository(
157
+ resolve_resource(self.root_dir, "src", "config", "profiles")
158
+ )
159
+ caps_repo = FileCapabilityRepository(
160
+ resolve_resource(self.root_dir, "src", "higpertext", "capabilities")
161
+ )
162
+ service = ProfileService(profiles_repo, caps_repo, self.root_dir)
163
+ profile = service.resolve_hierarchy(profile_name)
164
+ return list(profile.session_skills), list(profile.session_subagents)
165
+ except (FileNotFoundError, ValueError):
166
+ return [], []