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,171 @@
1
+ """higpertext Git Diff — detecta y muestra cambios locales en el repositorio Git."""
2
+
3
+ import sys
4
+ import subprocess # nosec B404
5
+ import argparse
6
+ from pathlib import Path
7
+
8
+ from higpertext.kernel.infrastructure.logger import get_logger
9
+ from higpertext.kernel.app_config import GIT_STATUS_LABELS as _STATUS_LABELS
10
+ _log = get_logger()
11
+
12
+
13
+ def run_cmd(cmd: list[str], cwd: str | None = None) -> tuple[int, str, str]:
14
+ """Ejecuta un comando y retorna (returncode, stdout, stderr)."""
15
+ res = subprocess.run(cmd, capture_output=True, text=True, cwd=cwd) # nosec B603
16
+ return res.returncode, res.stdout, res.stderr
17
+
18
+
19
+ def get_rel_prefix() -> str:
20
+ """Retorna la ruta relativa del CWD respecto a la raíz Git."""
21
+ _, out, _ = run_cmd(["git", "rev-parse", "--show-toplevel"]) # nosec B607
22
+ if out.strip():
23
+ git_root = Path(out.strip()).resolve()
24
+ try:
25
+ return Path.cwd().resolve().relative_to(git_root).as_posix()
26
+ except ValueError: # nosec B110
27
+ pass
28
+ return ""
29
+
30
+
31
+ def _classify_line(line: str, prefix_slash: str, prefix_len: int) -> tuple[str, str, str] | None:
32
+ """Clasifica una línea de git status; retorna (status_code, work_code, display_path) o None."""
33
+ if len(line) < 3:
34
+ return None
35
+ if prefix_slash and not line[3:].startswith(prefix_slash):
36
+ return None
37
+ display = line[3:][prefix_len:] if prefix_slash else line[3:]
38
+ return line[0], line[1], display
39
+
40
+
41
+ def get_git_status() -> tuple[dict | None, str | None]:
42
+ """Parsea `git status --porcelain` y clasifica archivos en staged/unstaged/untracked."""
43
+ ret, out, err = run_cmd(["git", "status", "--porcelain"])
44
+ if ret != 0:
45
+ return None, f"Error ejecutando git status: {err}"
46
+
47
+ staged, unstaged, untracked = [], [], []
48
+ prefix = get_rel_prefix()
49
+ prefix_slash = prefix + "/" if prefix else ""
50
+ prefix_len = len(prefix_slash)
51
+
52
+ for line in out.splitlines():
53
+ result = _classify_line(line, prefix_slash, prefix_len)
54
+ if result is None:
55
+ continue
56
+ idx_status, work_status, display_path = result
57
+ if idx_status in ("A", "M", "D", "R", "C"):
58
+ staged.append((idx_status, display_path))
59
+ if work_status in ("M", "D"):
60
+ unstaged.append((work_status, display_path))
61
+ elif idx_status == "?" and work_status == "?":
62
+ untracked.append(display_path)
63
+
64
+ return {"staged": staged, "unstaged": unstaged, "untracked": untracked}, None
65
+
66
+
67
+ def _adjust_files(files_list: list[str], prefix: str) -> list[str]:
68
+ """Prepende el prefijo de repo a los paths si es necesario."""
69
+ if not prefix:
70
+ return files_list
71
+ return [f if f.startswith(prefix + "/") else f"{prefix}/{f}" for f in files_list]
72
+
73
+
74
+ def show_detailed_diff(files_list: list[str] | None = None) -> None:
75
+ """Muestra los diffs preparados y no preparados en formato markdown."""
76
+ prefix = get_rel_prefix()
77
+ adjusted = _adjust_files(files_list or [], prefix) or (["."] if prefix else [])
78
+
79
+ cmd_staged = ["git", "diff", "--cached"] + adjusted
80
+ cmd_unstaged = ["git", "diff"] + adjusted
81
+
82
+ _, out_staged, _ = run_cmd(cmd_staged)
83
+ _, out_unstaged, _ = run_cmd(cmd_unstaged)
84
+
85
+ if out_staged.strip():
86
+ _log.info("\n### Cambios Preparados (Staged Diffs)")
87
+ _log.info("```diff")
88
+ _log.info(out_staged)
89
+ _log.info("```")
90
+
91
+ if out_unstaged.strip():
92
+ _log.info("\n### Cambios No Preparados (Unstaged Diffs)")
93
+ _log.info("```diff")
94
+ _log.info(out_unstaged)
95
+ _log.info("```")
96
+
97
+
98
+ def _print_status_summary(staged: list, unstaged: list, untracked: list) -> None:
99
+ """Imprime el resumen tabular de cambios locales."""
100
+ _log.info("=" * 50)
101
+ _log.info("RESUMEN DE CAMBIOS LOCALES (Git Status)")
102
+ _log.info("=" * 50)
103
+ if staged:
104
+ _log.info("\nCambios Preparados para Commit (Staged):")
105
+ for st, f in staged:
106
+ _log.info(f" [{st}] {f} ({_STATUS_LABELS.get(st, st)})")
107
+ if unstaged:
108
+ _log.info("\nCambios No Preparados (Unstaged):")
109
+ for st, f in unstaged:
110
+ _log.info(f" [{st}] {f} ({_STATUS_LABELS.get(st, st)})")
111
+ if untracked:
112
+ _log.info("\nArchivos Sin Seguimiento (Untracked):")
113
+ for f in untracked:
114
+ _log.info(f" [?] {f}")
115
+ _log.info("\n" + "=" * 50)
116
+
117
+
118
+ def _print_branch_info() -> None:
119
+ """Muestra branch actual y último commit como cabecera de contexto."""
120
+ ret, branch, _ = run_cmd(["git", "branch", "--show-current"])
121
+ ret2, last, _ = run_cmd(["git", "log", "--oneline", "-1"], cwd=None)
122
+ if ret == 0 and branch:
123
+ _log.info(f" Branch : {branch}")
124
+ if ret2 == 0 and last:
125
+ _log.info(f" Último : {last}")
126
+
127
+
128
+ def main() -> None:
129
+ """Punto de entrada del diff helper."""
130
+ parser = argparse.ArgumentParser(description="Git Diff Task Helper")
131
+ parser.add_argument("--detail", default="false", help="Muestra el diff detallado")
132
+ parser.add_argument("--files", default=None, help="Lista de archivos separados por comas")
133
+ args = parser.parse_args()
134
+
135
+ detail_active = args.detail.lower() in ("true", "1", "yes")
136
+
137
+ status, err = get_git_status()
138
+ if err:
139
+ _log.warning(f"[!] Error: {err}")
140
+ sys.exit(1)
141
+
142
+ staged = status["staged"]
143
+ unstaged = status["unstaged"]
144
+ untracked = status["untracked"]
145
+
146
+ if not staged and not unstaged and not untracked:
147
+ _log.info("")
148
+ _log.info("╔" + "═" * 52 + "╗")
149
+ _log.info("║ ESTADO DEL REPOSITORIO" + " " * 28 + "║")
150
+ _log.info("╚" + "═" * 52 + "╝")
151
+ _print_branch_info()
152
+ _log.info("─" * 50)
153
+ _log.ok(" ✓ Working tree limpio — sin cambios pendientes.")
154
+ _log.info("")
155
+ sys.exit(0)
156
+
157
+ _log.info("")
158
+ _log.info("╔" + "═" * 52 + "╗")
159
+ _log.info("║ ESTADO DEL REPOSITORIO" + " " * 28 + "║")
160
+ _log.info("╚" + "═" * 52 + "╝")
161
+ _print_branch_info()
162
+ _log.info("─" * 50)
163
+ _print_status_summary(staged, unstaged, untracked)
164
+
165
+ if detail_active:
166
+ target_files = [f.strip() for f in args.files.split(",") if f.strip()] if args.files else []
167
+ show_detailed_diff(target_files)
168
+
169
+
170
+ if __name__ == "__main__":
171
+ main()
@@ -0,0 +1,376 @@
1
+ """higpertext Git Ls-Files — inventario compacto de archivos trackeados."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import json
7
+ import subprocess # nosec B404
8
+ import sys
9
+ from collections import Counter, defaultdict
10
+ from dataclasses import dataclass
11
+ from fnmatch import fnmatch
12
+ from pathlib import Path
13
+
14
+ from higpertext.kernel.infrastructure.logger import get_logger
15
+ _log = get_logger()
16
+
17
+ _SEP = "─" * 50
18
+ _PRESET_GLOBS = {
19
+ "all": ["*"],
20
+ "code": [
21
+ "*.py",
22
+ "*.js",
23
+ "*.jsx",
24
+ "*.ts",
25
+ "*.tsx",
26
+ "*.go",
27
+ "*.rs",
28
+ "*.java",
29
+ "*.cs",
30
+ ],
31
+ "python": ["*.py"],
32
+ "web": ["*.js", "*.jsx", "*.ts", "*.tsx", "*.css", "*.scss", "*.html"],
33
+ "docs": ["*.md", "*.txt", "*.rst"],
34
+ "config": ["*.json", "*.jsonc", "*.yaml", "*.yml", "*.toml", "*.ini"],
35
+ "tests": ["tests/*", "test/*", "*_test.*", "test_*"],
36
+ }
37
+
38
+
39
+ @dataclass(frozen=True)
40
+ class FileEntry:
41
+ """Archivo listado por git con metadatos opcionales."""
42
+
43
+ path: str
44
+ size: int = 0
45
+ tracked: bool = True
46
+
47
+ @property
48
+ def extension(self) -> str:
49
+ return Path(self.path).suffix or "[sin extensión]"
50
+
51
+ @property
52
+ def directory(self) -> str:
53
+ parent = Path(self.path).parent.as_posix()
54
+ return "." if parent == "." else parent
55
+
56
+
57
+ def run_cmd(cmd: list[str]) -> tuple[int, str, str]:
58
+ """Ejecuta comandos git sin shell."""
59
+ res = subprocess.run(cmd, capture_output=True, text=True) # nosec B603
60
+ return res.returncode, res.stdout.strip(), res.stderr.strip()
61
+
62
+
63
+ def _parse_bool(value: str) -> bool:
64
+ return value.lower() in {"true", "1", "yes", "y"}
65
+
66
+
67
+ def _csv(value: str | None) -> list[str]:
68
+ if not value:
69
+ return []
70
+ return [item.strip() for item in value.split(",") if item.strip()]
71
+
72
+
73
+ def _normalize_globs(value: str | None) -> list[str]:
74
+ globs = _csv(value)
75
+ return [g if any(ch in g for ch in "*/?[]") else f"*.{g.lstrip('.')}" for g in globs]
76
+
77
+
78
+ def _include_globs(include: str | None, extension: str | None, preset: str) -> list[str]:
79
+ explicit = _normalize_globs(include or extension)
80
+ return explicit or _PRESET_GLOBS[preset]
81
+
82
+
83
+ def _matches_any(path: str, globs: list[str]) -> bool:
84
+ return any(fnmatch(path, glob) or fnmatch(Path(path).name, glob) for glob in globs)
85
+
86
+
87
+ def _path_matches(path: str, prefix: str | None) -> bool:
88
+ if not prefix or prefix in {".", "./"}:
89
+ return True
90
+ clean = prefix.strip().strip("/")
91
+ return path == clean or path.startswith(f"{clean}/") or clean in path
92
+
93
+
94
+ def _load_files(include_untracked: bool) -> tuple[list[str], str]:
95
+ ret, out, err = run_cmd(["git", "ls-files"]) # nosec B607
96
+ if ret != 0:
97
+ _log.error(f"[ERROR] {err}")
98
+ sys.exit(1)
99
+ tracked = out.splitlines() if out else []
100
+ if not include_untracked:
101
+ return tracked, "tracked"
102
+ ret_untracked, extra, _ = run_cmd(
103
+ ["git", "ls-files", "--others", "--exclude-standard"]
104
+ ) # nosec B607
105
+ if ret_untracked == 0 and extra:
106
+ tracked.extend(extra.splitlines())
107
+ return sorted(set(tracked)), "tracked+untracked"
108
+
109
+
110
+ def _filter_files(files: list[str], args: argparse.Namespace) -> list[str]:
111
+ include_globs = _include_globs(args.include, args.extension, args.preset)
112
+ exclude_globs = _csv(args.exclude)
113
+ result = []
114
+ for file in files:
115
+ if not _path_matches(file, args.path):
116
+ continue
117
+ if args.pattern and args.pattern not in file:
118
+ continue
119
+ if include_globs != ["*"] and not _matches_any(file, include_globs):
120
+ continue
121
+ if exclude_globs and _matches_any(file, exclude_globs):
122
+ continue
123
+ result.append(file)
124
+ return result
125
+
126
+
127
+ def _entry_for(path: str) -> FileEntry:
128
+ p = Path(path)
129
+ try:
130
+ size = p.stat().st_size if p.exists() else 0
131
+ except OSError:
132
+ size = 0
133
+ return FileEntry(path=path, size=size)
134
+
135
+
136
+ def _sort_entries(entries: list[FileEntry], mode: str) -> list[FileEntry]:
137
+ if mode == "size":
138
+ return sorted(entries, key=lambda e: (-e.size, e.path))
139
+ if mode == "extension":
140
+ return sorted(entries, key=lambda e: (e.extension, e.path))
141
+ return sorted(entries, key=lambda e: e.path)
142
+
143
+
144
+ def _limited(entries: list[FileEntry], max_results: int) -> list[FileEntry]:
145
+ return entries[:max_results]
146
+
147
+
148
+ def _human_size(size: int) -> str:
149
+ if size >= 1024 * 1024:
150
+ return f"{size / (1024 * 1024):.1f} MB"
151
+ if size >= 1024:
152
+ return f"{size / 1024:.1f} KB"
153
+ return f"{size} B"
154
+
155
+
156
+ def _print_header(args: argparse.Namespace, branch: str, source: str, total: int) -> None:
157
+ _log.info("")
158
+ _log.info("╔" + "═" * 52 + "╗")
159
+ _log.info("║ INVENTARIO DE ARCHIVOS GIT" + " " * 25 + "║")
160
+ _log.info("╚" + "═" * 52 + "╝")
161
+ _log.info(f" Branch : {branch or 'desconocido'}")
162
+ _log.info(f" Fuente : {source}")
163
+ _log.info(f" Modo : {args.mode}")
164
+ if args.path:
165
+ _log.info(f" Path : {args.path}")
166
+ if args.pattern:
167
+ _log.info(f" Filtro : {args.pattern}")
168
+ _log.info(f" Total : {total} archivo(s)")
169
+ _log.info(_SEP)
170
+
171
+
172
+ def _print_list(entries: list[FileEntry], args: argparse.Namespace, total: int) -> None:
173
+ for entry in _limited(entries, args.max_results):
174
+ suffix = ""
175
+ if args.show_size:
176
+ suffix = f" ({_human_size(entry.size)})"
177
+ marker = " ⚠ grande" if entry.size / 1024 >= args.large_threshold_kb else ""
178
+ _log.info(f" {entry.path}{suffix}{marker}")
179
+ _print_truncated_hint(total, args.max_results)
180
+
181
+
182
+ def _print_grouped(entries: list[FileEntry], args: argparse.Namespace, total: int) -> None:
183
+ key_fn = (
184
+ (lambda e: e.extension)
185
+ if args.group_by == "extension"
186
+ else (lambda e: e.directory.split("/")[0])
187
+ )
188
+ groups: dict[str, list[FileEntry]] = defaultdict(list)
189
+ for entry in entries:
190
+ groups[key_fn(entry)].append(entry)
191
+ shown = 0
192
+ for group in sorted(groups):
193
+ if shown >= args.max_results:
194
+ break
195
+ _log.info(f" {group}/ ({len(groups[group])})")
196
+ for entry in groups[group][: min(5, args.max_results - shown)]:
197
+ _log.info(f" {entry.path}")
198
+ shown += 1
199
+ _print_truncated_hint(total, args.max_results)
200
+
201
+
202
+ def _print_dirs(entries: list[FileEntry], args: argparse.Namespace) -> None:
203
+ dirs = sorted(
204
+ {_trim_depth(_relative_path(e.directory, args.path), args.max_depth) for e in entries}
205
+ )
206
+ for directory in dirs[: args.max_results]:
207
+ _log.info(f" {directory}")
208
+ _print_truncated_hint(len(dirs), args.max_results)
209
+
210
+
211
+ def _print_tree(entries: list[FileEntry], args: argparse.Namespace) -> None:
212
+ tree: dict[str, set[str]] = defaultdict(set)
213
+ for entry in entries:
214
+ parts = Path(_relative_path(entry.path, args.path)).parts[: args.max_depth]
215
+ if not parts:
216
+ continue
217
+ parent = "/".join(parts[:-1]) or "."
218
+ tree[parent].add(parts[-1])
219
+ shown = 0
220
+ for parent in sorted(tree):
221
+ if shown >= args.max_results:
222
+ break
223
+ _log.info(f" {parent}/")
224
+ shown += 1
225
+ for child in sorted(tree[parent])[:5]:
226
+ _log.info(f" └─ {child}")
227
+ _print_truncated_hint(len(tree), args.max_results)
228
+
229
+
230
+ def _print_summary(entries: list[FileEntry], args: argparse.Namespace) -> None:
231
+ by_ext = Counter(e.extension for e in entries)
232
+ by_dir = Counter(e.directory.split("/")[0] for e in entries)
233
+ large = [e for e in entries if e.size / 1024 >= args.large_threshold_kb]
234
+ _log.info(" Por extensión:")
235
+ for ext, count in by_ext.most_common(10):
236
+ _log.info(f" {ext}: {count}")
237
+ _log.info("\n Directorios top:")
238
+ for directory, count in by_dir.most_common(10):
239
+ _log.info(f" {directory}: {count}")
240
+ if large:
241
+ _log.info("\n Archivos grandes:")
242
+ for entry in large[:10]:
243
+ _log.info(f" {entry.path} ({_human_size(entry.size)})")
244
+ if entry.path.endswith((".py", ".js", ".ts", ".tsx")):
245
+ _log.info(f" sugerencia: htx task common.code-skeletonizer --path {entry.path}")
246
+ _log.info("\n Ejemplos:")
247
+ for entry in entries[: min(10, args.max_results)]:
248
+ _log.info(f" {entry.path}")
249
+
250
+
251
+ def _print_json(
252
+ entries: list[FileEntry], args: argparse.Namespace, branch: str, source: str
253
+ ) -> None:
254
+ payload = {
255
+ "branch": branch,
256
+ "source": source,
257
+ "mode": args.mode,
258
+ "total": len(entries),
259
+ "files": [
260
+ {
261
+ "path": e.path,
262
+ "size": e.size,
263
+ "extension": e.extension,
264
+ "directory": e.directory,
265
+ }
266
+ for e in _limited(entries, args.max_results)
267
+ ],
268
+ }
269
+ print(json.dumps(payload, ensure_ascii=False, indent=2))
270
+
271
+
272
+ def _trim_depth(path: str, max_depth: int) -> str:
273
+ if path == ".":
274
+ return path
275
+ return "/".join(Path(path).parts[:max_depth])
276
+
277
+
278
+ def _relative_path(path: str, base: str) -> str:
279
+ """Muestra árboles relativos al path solicitado para evitar ruido."""
280
+ clean_base = base.strip().strip("/")
281
+ if not clean_base or path in {".", clean_base}:
282
+ return path if not clean_base else "."
283
+ if path.startswith(f"{clean_base}/"):
284
+ return path[len(clean_base) + 1 :]
285
+ return path
286
+
287
+
288
+ def _print_truncated_hint(total: int, max_results: int) -> None:
289
+ if total > max_results:
290
+ _log.info(f" ... {total - max_results} resultado(s) omitidos; usa filtros o --max_results")
291
+
292
+
293
+ def _positive_int(value: str) -> int:
294
+ parsed = int(value)
295
+ if parsed <= 0:
296
+ raise argparse.ArgumentTypeError("debe ser mayor que 0")
297
+ return parsed
298
+
299
+
300
+ def _non_negative_int(value: str) -> int:
301
+ parsed = int(value)
302
+ if parsed < 0:
303
+ raise argparse.ArgumentTypeError("no puede ser negativo")
304
+ return parsed
305
+
306
+
307
+ def _choice(value: str, allowed: set[str], label: str) -> str:
308
+ if value not in allowed:
309
+ raise argparse.ArgumentTypeError(f"{label} inválido: {value}")
310
+ return value
311
+
312
+
313
+ def main() -> None:
314
+ parser = argparse.ArgumentParser(description="Git Ls-Files Task Helper")
315
+ parser.add_argument("--path", default="", help="Prefijo/ruta a explorar")
316
+ parser.add_argument("--pattern", default="", help="Filtro substring opcional")
317
+ parser.add_argument("--include", default="", help="Globs incluidos separados por coma")
318
+ parser.add_argument("--exclude", default="", help="Globs excluidos separados por coma")
319
+ parser.add_argument("--extension", default="", help="Alias de include: py,json o *.py")
320
+ parser.add_argument(
321
+ "--preset",
322
+ default="all",
323
+ type=lambda v: _choice(v, set(_PRESET_GLOBS), "preset"),
324
+ )
325
+ parser.add_argument(
326
+ "--mode",
327
+ default="summary",
328
+ type=lambda v: _choice(v, {"list", "tree", "summary", "dirs", "json"}, "mode"),
329
+ )
330
+ parser.add_argument("--max_results", default="100", type=_positive_int)
331
+ parser.add_argument("--max_depth", default="3", type=_positive_int)
332
+ parser.add_argument("--show_size", default="false")
333
+ parser.add_argument("--large_threshold_kb", default="100", type=_non_negative_int)
334
+ parser.add_argument(
335
+ "--sort",
336
+ default="path",
337
+ type=lambda v: _choice(v, {"path", "size", "extension"}, "sort"),
338
+ )
339
+ parser.add_argument(
340
+ "--group_by",
341
+ default="none",
342
+ type=lambda v: _choice(v, {"none", "dir", "extension"}, "group_by"),
343
+ )
344
+ parser.add_argument("--files_only", default="false")
345
+ parser.add_argument("--json", default="false")
346
+ parser.add_argument("--include_untracked", default="false")
347
+ args = parser.parse_args()
348
+
349
+ files, source = _load_files(_parse_bool(args.include_untracked))
350
+ _, branch, _ = run_cmd(["git", "branch", "--show-current"]) # nosec B607
351
+ entries = _sort_entries([_entry_for(path) for path in _filter_files(files, args)], args.sort)
352
+
353
+ if args.mode == "json" or _parse_bool(args.json):
354
+ _print_json(entries, args, branch, source)
355
+ return
356
+ if _parse_bool(args.files_only):
357
+ for entry in _limited(entries, args.max_results):
358
+ _log.info(entry.path)
359
+ return
360
+
361
+ _print_header(args, branch, source, len(entries))
362
+ if args.mode == "summary":
363
+ _print_summary(entries, args)
364
+ elif args.mode == "tree":
365
+ _print_tree(entries, args)
366
+ elif args.mode == "dirs":
367
+ _print_dirs(entries, args)
368
+ elif args.group_by != "none":
369
+ _print_grouped(entries, args, len(entries))
370
+ else:
371
+ _print_list(entries, args, len(entries))
372
+ _log.info(_SEP)
373
+ _log.info(f" Total: {len(entries)} archivo(s)")
374
+ _log.info("")
375
+ if __name__ == "__main__":
376
+ main()
@@ -0,0 +1,62 @@
1
+ """higpertext Git Rm — remueve archivos del índice git sin eliminarlos del filesystem."""
2
+
3
+ import sys
4
+ import subprocess # nosec B404
5
+ import argparse
6
+
7
+ from higpertext.kernel.infrastructure.logger import get_logger
8
+ _log = get_logger()
9
+
10
+ _SEP = "─" * 50
11
+
12
+
13
+ def run_cmd(cmd: list[str]) -> tuple[int, str, str]:
14
+ res = subprocess.run(cmd, capture_output=True, text=True) # nosec B603
15
+ return res.returncode, res.stdout.strip(), res.stderr.strip()
16
+
17
+
18
+ def main() -> None:
19
+ parser = argparse.ArgumentParser(description="Git Rm --cached Task Helper")
20
+ parser.add_argument("--files", required=True, help="Archivos separados por comas")
21
+ args = parser.parse_args()
22
+
23
+ files = [f.strip() for f in args.files.split(",") if f.strip()]
24
+ if not files:
25
+ _log.error("[ERROR] No se especificaron archivos.")
26
+ sys.exit(1)
27
+
28
+ _, branch, _ = run_cmd(["git", "branch", "--show-current"])
29
+
30
+ removed, warned = [], []
31
+ for f in files:
32
+ ret, _, err = run_cmd(["git", "rm", "--cached", f]) # nosec B607
33
+ if ret == 0:
34
+ removed.append(f)
35
+ else:
36
+ warned.append((f, err))
37
+
38
+ _log.info("")
39
+ _log.info("╔" + "═" * 52 + "╗")
40
+ _log.info("║ REMOVIENDO ARCHIVOS DEL ÍNDICE GIT" + " " * 16 + "║")
41
+ _log.info("╚" + "═" * 52 + "╝")
42
+ _log.info(f" Branch : {branch or 'desconocido'}")
43
+ _log.info(_SEP)
44
+
45
+ for f in removed:
46
+ _log.ok(f" [OK] {f}")
47
+ for f, err in warned:
48
+ _log.warning(f" [WARN] {f} — {err or 'no estaba trackeado'}")
49
+
50
+ _log.info(_SEP)
51
+ _log.warning(f" Removidos: {len(removed)} | Advertencias: {len(warned)}")
52
+ _log.info("")
53
+ _log.info(" ℹ Los archivos NO fueron eliminados del sistema de archivos local.")
54
+ _log.info("")
55
+ if removed and warned:
56
+ sys.exit(0)
57
+ if warned and not removed:
58
+ sys.exit(1)
59
+
60
+
61
+ if __name__ == "__main__":
62
+ main()
@@ -0,0 +1,33 @@
1
+ {
2
+ "id": "security.k8s-auditor",
3
+ "version": "1.0.0",
4
+ "name": "Auditor de Manifiestos Kubernetes (K8s Auditor)",
5
+ "description": "Audita archivos YAML de Kubernetes buscando fallos de seguridad o malas prácticas de configuración.",
6
+ "entrypoint": "capabilities/security/scripts/k8s_auditor.py",
7
+ "language": "python",
8
+ "parameters": [
9
+ {
10
+ "name": "target",
11
+ "type": "string",
12
+ "required": false,
13
+ "default": ".",
14
+ "description": "Directorio o archivo YAML a auditar."
15
+ },
16
+ {
17
+ "name": "save_report",
18
+ "type": "string",
19
+ "required": false,
20
+ "default": "k8s_security_report.md",
21
+ "description": "Nombre del archivo de reporte Markdown resultante."
22
+ }
23
+ ],
24
+ "contract": {
25
+ "format": "Markdown K8s Security Report",
26
+ "rules": [
27
+ "Debe buscar archivos .yaml o .yml recursivamente.",
28
+ "Debe evaluar el contexto de seguridad (privileged, runAsNonRoot, readOnlyRootFilesystem, allowPrivilegeEscalation).",
29
+ "Debe reportar riesgos de red (hostNetwork, hostPort) e inyecciones de volumen.",
30
+ "Debe clasificar los hallazgos por severidad: CRITICAL, HIGH, MEDIUM, LOW."
31
+ ]
32
+ }
33
+ }