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.
- config/adapters_config.json +450 -0
- config/antigravity_agent_template.json +31 -0
- config/app_config.json +174 -0
- config/context_engine.json +33 -0
- config/environments/model_defaults.json +5 -0
- config/governance/branching_strategy.json +36 -0
- config/governance/deployment_gates.json +30 -0
- config/governance/guidelines_contract.json +54 -0
- config/governance/quality_gates.json +39 -0
- config/governance/section_rules.json +22 -0
- config/governance/security_guardrails.json +52 -0
- config/hooks/README.md +35 -0
- config/hooks/custom/test_output_limiter.json +9 -0
- config/hooks/global/session_prompt.json +9 -0
- config/htx_config.json +24 -0
- config/profile_learner.json +18 -0
- config/profiles/base_agent.json +40 -0
- config/profiles/base_auditor.json +19 -0
- config/profiles/base_developer.json +19 -0
- config/profiles/base_operator.json +16 -0
- config/profiles/global.json +33 -0
- config/profiles/software_developer.json +23 -0
- config/router_content.json +137 -0
- config/semantic_graph.json +66 -0
- config/workflows/ado_release_flow.json +38 -0
- config/workflows/docs-update.json +33 -0
- config/workflows/governance-check.yaml +26 -0
- config/workflows/guidelines-sync.json +40 -0
- config/workflows/higpertext-build.json +73 -0
- config/workflows/higpertext-plan.json +38 -0
- config/workflows/higpertext-review.json +41 -0
- config/workflows/pr-quality-check.json +56 -0
- config/workflows/quality-remediation.json +57 -0
- higpertext/__init__.py +18 -0
- higpertext/adapters/__init__.py +27 -0
- higpertext/adapters/adapter_utils.py +604 -0
- higpertext/adapters/claude_adapter/__init__.py +0 -0
- higpertext/adapters/claude_adapter/claude_adapter.py +154 -0
- higpertext/adapters/copilot_adapter/__init__.py +0 -0
- higpertext/adapters/copilot_adapter/copilot_adapter.py +231 -0
- higpertext/adapters/gemini_adapter/__init__.py +0 -0
- higpertext/adapters/gemini_adapter/gemini_adapter.py +211 -0
- higpertext/adapters/llm_formatter.py +46 -0
- higpertext/adapters/open_code_adapter/__init__.py +0 -0
- higpertext/adapters/open_code_adapter/open_code_adapter.py +480 -0
- higpertext/capabilities/capabilities_runner.py +216 -0
- higpertext/capabilities/common/agent-builder.json +54 -0
- higpertext/capabilities/common/agent-sync.json +34 -0
- higpertext/capabilities/common/code-skeletonizer.json +35 -0
- higpertext/capabilities/common/commit-report.json +42 -0
- higpertext/capabilities/common/context-assembler.json +37 -0
- higpertext/capabilities/common/context-budget-report.json +15 -0
- higpertext/capabilities/common/dep-manager.json +43 -0
- higpertext/capabilities/common/docs-sync.json +14 -0
- higpertext/capabilities/common/doctor.json +18 -0
- higpertext/capabilities/common/efficiency-meter.json +31 -0
- higpertext/capabilities/common/env-catalog.json +13 -0
- higpertext/capabilities/common/env-clean.json +14 -0
- higpertext/capabilities/common/env-logs.json +16 -0
- higpertext/capabilities/common/env-runner.json +23 -0
- higpertext/capabilities/common/env-status.json +13 -0
- higpertext/capabilities/common/env-stop.json +14 -0
- higpertext/capabilities/common/env-template.json +14 -0
- higpertext/capabilities/common/error-context-locator.json +23 -0
- higpertext/capabilities/common/eval-agent.json +33 -0
- higpertext/capabilities/common/file-map.json +17 -0
- higpertext/capabilities/common/governance-exception.json +54 -0
- higpertext/capabilities/common/graph-query.json +59 -0
- higpertext/capabilities/common/graph-rebuild.json +31 -0
- higpertext/capabilities/common/graph-visualize.json +37 -0
- higpertext/capabilities/common/grep-search.json +176 -0
- higpertext/capabilities/common/higpertext-tester.json +25 -0
- higpertext/capabilities/common/hook-health.json +19 -0
- higpertext/capabilities/common/hook-sync-check.json +19 -0
- higpertext/capabilities/common/hooks-manager.json +55 -0
- higpertext/capabilities/common/knowledge-asker.json +27 -0
- higpertext/capabilities/common/list-rules.json +27 -0
- higpertext/capabilities/common/llm-invoke.json +59 -0
- higpertext/capabilities/common/load-rules.json +37 -0
- higpertext/capabilities/common/memory-manager.json +65 -0
- higpertext/capabilities/common/quality-scan.json +21 -0
- higpertext/capabilities/common/quality-updater.json +35 -0
- higpertext/capabilities/common/rag-index.json +17 -0
- higpertext/capabilities/common/report-viewer.json +24 -0
- higpertext/capabilities/common/roadmap-report.json +37 -0
- higpertext/capabilities/common/scripts/_env_cli.py +65 -0
- higpertext/capabilities/common/scripts/agent_builder.py +60 -0
- higpertext/capabilities/common/scripts/agent_sync.py +56 -0
- higpertext/capabilities/common/scripts/ask_higpertext.py +38 -0
- higpertext/capabilities/common/scripts/code_skeletonizer.py +225 -0
- higpertext/capabilities/common/scripts/commit_report.py +134 -0
- higpertext/capabilities/common/scripts/context_assembler.py +70 -0
- higpertext/capabilities/common/scripts/context_budget_report.py +53 -0
- higpertext/capabilities/common/scripts/dep_manager.py +81 -0
- higpertext/capabilities/common/scripts/docs_sync.py +981 -0
- higpertext/capabilities/common/scripts/doctor.py +144 -0
- higpertext/capabilities/common/scripts/efficiency_meter.py +83 -0
- higpertext/capabilities/common/scripts/env_catalog.py +47 -0
- higpertext/capabilities/common/scripts/env_clean.py +30 -0
- higpertext/capabilities/common/scripts/env_logs.py +32 -0
- higpertext/capabilities/common/scripts/env_runner.py +53 -0
- higpertext/capabilities/common/scripts/env_status.py +38 -0
- higpertext/capabilities/common/scripts/env_stop.py +30 -0
- higpertext/capabilities/common/scripts/env_template.py +73 -0
- higpertext/capabilities/common/scripts/error_context_locator.py +138 -0
- higpertext/capabilities/common/scripts/eval_agent.py +80 -0
- higpertext/capabilities/common/scripts/file_map.py +95 -0
- higpertext/capabilities/common/scripts/governance_exception.py +116 -0
- higpertext/capabilities/common/scripts/graph_query.py +104 -0
- higpertext/capabilities/common/scripts/graph_rebuild.py +107 -0
- higpertext/capabilities/common/scripts/graph_visualize.py +76 -0
- higpertext/capabilities/common/scripts/grep_search.py +648 -0
- higpertext/capabilities/common/scripts/higpertext_tester.py +102 -0
- higpertext/capabilities/common/scripts/hook_health.py +149 -0
- higpertext/capabilities/common/scripts/hook_sync_check.py +134 -0
- higpertext/capabilities/common/scripts/hooks_manager.py +171 -0
- higpertext/capabilities/common/scripts/list_rules.py +175 -0
- higpertext/capabilities/common/scripts/llm_invoke.py +135 -0
- higpertext/capabilities/common/scripts/load_rules.py +379 -0
- higpertext/capabilities/common/scripts/memory_manager.py +210 -0
- higpertext/capabilities/common/scripts/presentation_engine.py +63 -0
- higpertext/capabilities/common/scripts/quality_scan.py +132 -0
- higpertext/capabilities/common/scripts/rag_index.py +39 -0
- higpertext/capabilities/common/scripts/report_viewer.py +106 -0
- higpertext/capabilities/common/scripts/roadmap_report.py +73 -0
- higpertext/capabilities/common/scripts/search_router.py +111 -0
- higpertext/capabilities/common/scripts/semantic_diff.py +166 -0
- higpertext/capabilities/common/scripts/semantic_search.py +43 -0
- higpertext/capabilities/common/scripts/session_control.py +136 -0
- higpertext/capabilities/common/scripts/smart_read.py +232 -0
- higpertext/capabilities/common/scripts/subagent_executor.py +143 -0
- higpertext/capabilities/common/scripts/sync_agents.py +353 -0
- higpertext/capabilities/common/scripts/task_decomposer.py +78 -0
- higpertext/capabilities/common/scripts/telemetry_report.py +36 -0
- higpertext/capabilities/common/search-router.json +24 -0
- higpertext/capabilities/common/semantic-diff.json +40 -0
- higpertext/capabilities/common/semantic-search.json +19 -0
- higpertext/capabilities/common/session-clean.json +20 -0
- higpertext/capabilities/common/session-start.json +44 -0
- higpertext/capabilities/common/smart-read.json +28 -0
- higpertext/capabilities/common/subagent-executor.json +25 -0
- higpertext/capabilities/common/sync-agents.json +32 -0
- higpertext/capabilities/common/task-decomposer.json +37 -0
- higpertext/capabilities/common/telemetry-report.json +23 -0
- higpertext/capabilities/git/__init__.py +0 -0
- higpertext/capabilities/git/committer.json +61 -0
- higpertext/capabilities/git/diff.json +33 -0
- higpertext/capabilities/git/ls-files.json +44 -0
- higpertext/capabilities/git/rm.json +27 -0
- higpertext/capabilities/git/scripts/__init__.py +0 -0
- higpertext/capabilities/git/scripts/commit_changes.py +1077 -0
- higpertext/capabilities/git/scripts/git_diff.py +171 -0
- higpertext/capabilities/git/scripts/git_ls_files.py +376 -0
- higpertext/capabilities/git/scripts/git_rm.py +62 -0
- higpertext/capabilities/security/k8s-auditor.json +33 -0
- higpertext/capabilities/security/scripts/k8s_auditor.py +307 -0
- higpertext/capabilities/security/scripts/secret_scanner.py +235 -0
- higpertext/capabilities/security/secret-scanner.json +32 -0
- higpertext/hooks/__init__.py +28 -0
- higpertext/hooks/_compat.py +27 -0
- higpertext/hooks/hook_tasks/__init__.py +1 -0
- higpertext/hooks/hook_tasks/_rules/__init__.py +0 -0
- higpertext/hooks/hook_tasks/_rules/bash_rules.py +635 -0
- higpertext/hooks/hook_tasks/_rules/context_engine_rule.py +79 -0
- higpertext/hooks/hook_tasks/_rules/context_rules.py +199 -0
- higpertext/hooks/hook_tasks/_rules/governance_adapter.py +72 -0
- higpertext/hooks/hook_tasks/_rules/profile_rules.json +25 -0
- higpertext/hooks/hook_tasks/_rules/quality_rules.py +86 -0
- higpertext/hooks/hook_tasks/_rules/security_rules.py +214 -0
- higpertext/hooks/hook_tasks/_rules/session_rules.py +316 -0
- higpertext/hooks/hook_tasks/_rules/telemetry_rules.py +121 -0
- higpertext/hooks/hook_tasks/audit_logger_hook.py +28 -0
- higpertext/hooks/hook_tasks/hook_bash_guard.py +101 -0
- higpertext/hooks/hook_tasks/hook_code_quality.py +48 -0
- higpertext/hooks/hook_tasks/hook_context_hint.py +46 -0
- higpertext/hooks/hook_tasks/hook_context_manager.py +44 -0
- higpertext/hooks/hook_tasks/hook_io.py +122 -0
- higpertext/hooks/hook_tasks/hook_loop_guard.py +182 -0
- higpertext/hooks/hook_tasks/hook_post_observer.py +54 -0
- higpertext/hooks/hook_tasks/hook_read_guard.py +85 -0
- higpertext/hooks/hook_tasks/hook_security_guard.py +81 -0
- higpertext/hooks/hook_tasks/hook_session_prompt.py +83 -0
- higpertext/hooks/hook_tasks/hook_session_stop.py +115 -0
- higpertext/hooks/hook_tasks/hook_utils.py +144 -0
- higpertext/hooks/hook_tasks/session_guard_hook.py +23 -0
- higpertext/hooks/hook_tasks/telemetry_utils.py +176 -0
- higpertext/hooks/hook_tasks/test_echo_hook.py +33 -0
- higpertext/hooks/hook_tasks/webhook_hook.py +54 -0
- higpertext/hooks/hook_tasks/workflow_runner_hook.py +49 -0
- higpertext/hooks/hooks_catalog.json +116 -0
- higpertext/kernel/__init__.py +63 -0
- higpertext/kernel/_compat.py +138 -0
- higpertext/kernel/app_config.py +117 -0
- higpertext/kernel/application/__init__.py +13 -0
- higpertext/kernel/application/agent_registry.py +102 -0
- higpertext/kernel/application/capability_manager.py +61 -0
- higpertext/kernel/application/commit_reporter.py +247 -0
- higpertext/kernel/application/context_builder.py +166 -0
- higpertext/kernel/application/context_engine.py +409 -0
- higpertext/kernel/application/engine.py +41 -0
- higpertext/kernel/application/env_runtime.py +174 -0
- higpertext/kernel/application/environment_manager.py +154 -0
- higpertext/kernel/application/governance.py +192 -0
- higpertext/kernel/application/hook_registry.py +102 -0
- higpertext/kernel/application/hook_renderer.py +720 -0
- higpertext/kernel/application/ports.py +49 -0
- higpertext/kernel/application/profile_learner.py +358 -0
- higpertext/kernel/application/profile_service.py +205 -0
- higpertext/kernel/application/profile_services.py +6 -0
- higpertext/kernel/application/profile_use_cases.py +93 -0
- higpertext/kernel/application/rag_service.py +75 -0
- higpertext/kernel/application/roadmap_reporter.py +178 -0
- higpertext/kernel/application/semantic_engine.py +258 -0
- higpertext/kernel/application/session_services.py +33 -0
- higpertext/kernel/application/skill_hook_compiler.py +85 -0
- higpertext/kernel/application/telemetry.py +326 -0
- higpertext/kernel/application/workflow_manager.py +176 -0
- higpertext/kernel/config_paths.py +66 -0
- higpertext/kernel/domain/__init__.py +12 -0
- higpertext/kernel/domain/agent_registry.py +23 -0
- higpertext/kernel/domain/commit_reporter.py +155 -0
- higpertext/kernel/domain/compilers.py +7 -0
- higpertext/kernel/domain/context_engine.py +319 -0
- higpertext/kernel/domain/entities.py +51 -0
- higpertext/kernel/domain/env_runtime.py +62 -0
- higpertext/kernel/domain/governance.py +198 -0
- higpertext/kernel/domain/hook_models.py +29 -0
- higpertext/kernel/domain/profile_learner.py +186 -0
- higpertext/kernel/domain/rag.py +70 -0
- higpertext/kernel/domain/repositories.py +8 -0
- higpertext/kernel/domain/roadmap_reporter.py +80 -0
- higpertext/kernel/domain/semantic_engine.py +107 -0
- higpertext/kernel/engine.py +42 -0
- higpertext/kernel/htx_resolver.py +69 -0
- higpertext/kernel/infrastructure/__init__.py +13 -0
- higpertext/kernel/infrastructure/agent_registry.py +40 -0
- higpertext/kernel/infrastructure/cache/capability_cache.py +319 -0
- higpertext/kernel/infrastructure/capability_helper.py +40 -0
- higpertext/kernel/infrastructure/cli/__init__.py +1 -0
- higpertext/kernel/infrastructure/cli/agent_commands.py +62 -0
- higpertext/kernel/infrastructure/cli/arguments.py +39 -0
- higpertext/kernel/infrastructure/cli/capability_command_builder.py +86 -0
- higpertext/kernel/infrastructure/cli/capability_task_service.py +234 -0
- higpertext/kernel/infrastructure/cli/cli_search.py +234 -0
- higpertext/kernel/infrastructure/cli/parameter_contracts.py +83 -0
- higpertext/kernel/infrastructure/cli/parser_builder.py +122 -0
- higpertext/kernel/infrastructure/cli/profile_commands.py +89 -0
- higpertext/kernel/infrastructure/cli/roadmap_commands.py +117 -0
- higpertext/kernel/infrastructure/cli/router.py +1110 -0
- higpertext/kernel/infrastructure/cli/session_commands.py +36 -0
- higpertext/kernel/infrastructure/cli/task_commands.py +23 -0
- higpertext/kernel/infrastructure/cli/task_result_reporter.py +56 -0
- higpertext/kernel/infrastructure/cli/workflow_commands.py +25 -0
- higpertext/kernel/infrastructure/compilers/__init__.py +3 -0
- higpertext/kernel/infrastructure/compilers/factory.py +27 -0
- higpertext/kernel/infrastructure/compilers/graph_compiler.py +20 -0
- higpertext/kernel/infrastructure/compilers/guide_compiler.py +50 -0
- higpertext/kernel/infrastructure/compilers/hook_compiler.py +69 -0
- higpertext/kernel/infrastructure/compilers/playbook_compiler.py +154 -0
- higpertext/kernel/infrastructure/context_engine.py +303 -0
- higpertext/kernel/infrastructure/database/local_vector_store.py +99 -0
- higpertext/kernel/infrastructure/deployment/__init__.py +1 -0
- higpertext/kernel/infrastructure/deployment/resource_deployer.py +283 -0
- higpertext/kernel/infrastructure/diagnostics/__init__.py +1 -0
- higpertext/kernel/infrastructure/diagnostics/health.py +191 -0
- higpertext/kernel/infrastructure/env_runtime.py +227 -0
- higpertext/kernel/infrastructure/execution/__init__.py +1 -0
- higpertext/kernel/infrastructure/execution/parallel.py +188 -0
- higpertext/kernel/infrastructure/execution/resilience.py +155 -0
- higpertext/kernel/infrastructure/file_repositories.py +213 -0
- higpertext/kernel/infrastructure/governance.py +198 -0
- higpertext/kernel/infrastructure/hook_config_loader.py +53 -0
- higpertext/kernel/infrastructure/hook_webhook_dispatcher.py +61 -0
- higpertext/kernel/infrastructure/hook_workflow_bridge.py +60 -0
- higpertext/kernel/infrastructure/llm/__init__.py +6 -0
- higpertext/kernel/infrastructure/llm/provider.py +46 -0
- higpertext/kernel/infrastructure/llm/providers/__init__.py +0 -0
- higpertext/kernel/infrastructure/llm/providers/anthropic_provider.py +94 -0
- higpertext/kernel/infrastructure/llm/providers/gemini_embeddings.py +74 -0
- higpertext/kernel/infrastructure/llm/providers/gemini_provider.py +101 -0
- higpertext/kernel/infrastructure/llm/providers/ollama_provider.py +110 -0
- higpertext/kernel/infrastructure/llm/providers/openai_provider.py +98 -0
- higpertext/kernel/infrastructure/llm/registry.py +81 -0
- higpertext/kernel/infrastructure/logger.py +303 -0
- higpertext/kernel/infrastructure/output_store.py +70 -0
- higpertext/kernel/infrastructure/parser/__init__.py +1 -0
- higpertext/kernel/infrastructure/parser/code_chunker.py +144 -0
- higpertext/kernel/infrastructure/parser/language/__init__.py +14 -0
- higpertext/kernel/infrastructure/parser/language/base.py +41 -0
- higpertext/kernel/infrastructure/parser/language/powershell_parser.py +35 -0
- higpertext/kernel/infrastructure/parser/language/python_parser.py +98 -0
- higpertext/kernel/infrastructure/parser/language/typescript_parser.py +91 -0
- higpertext/kernel/infrastructure/parser/semantic_graph.py +409 -0
- higpertext/kernel/infrastructure/presentation/__init__.py +1 -0
- higpertext/kernel/infrastructure/presentation/html_renderer.py +137 -0
- higpertext/kernel/infrastructure/presentation/markdown_renderer.py +84 -0
- higpertext/kernel/infrastructure/presentation/markdown_report_renderer.py +97 -0
- higpertext/kernel/infrastructure/profile_store.py +28 -0
- higpertext/kernel/infrastructure/semantic_engine.py +289 -0
- higpertext/kernel/infrastructure/telemetry_reporter.py +132 -0
- higpertext/kernel/infrastructure/validation/__init__.py +1 -0
- higpertext/kernel/infrastructure/validation/contract_validator.py +163 -0
- higpertext/kernel/pkg_resources.py +38 -0
- higpertext/kernel/session_manager.py +319 -0
- higpertext/templates/env/generic-shell.yaml +21 -0
- higpertext/templates/env/node-vitest.yaml +27 -0
- higpertext/templates/env/python-pytest.yaml +29 -0
- higpertext/templates/html/commit_body.html +20 -0
- higpertext/templates/html/commit_diff.html +4 -0
- higpertext/templates/html/commit_index.html +29 -0
- higpertext/templates/html/commit_layer.html +11 -0
- higpertext/templates/html/commit_shell.html +28 -0
- higpertext/templates/html/graph_visualize.html +86 -0
- higpertext/templates/html/roadmap_body.html +12 -0
- higpertext/templates/html/roadmap_phase.html +5 -0
- higpertext/templates/html/roadmap_shell.html +29 -0
- higpertext/templates/markdown/commit_report.md +18 -0
- higpertext/templates/markdown/efficiency_report.md +12 -0
- higpertext/templates/markdown/roadmap_report.md +25 -0
- higpertext/templates/skills/best-practices.md +7 -0
- higpertext/templates/skills/clean-code.md +8 -0
- higpertext/templates/skills/ddd-standards.md +7 -0
- higpertext/templates/skills/tdd-practices.md +7 -0
- higpertext/templates/subagents/architect.md +7 -0
- higpertext/templates/subagents/test-engineer.md +7 -0
- higpertext/templates/workflows/build.json +23 -0
- higpertext/templates/workflows/compact.json +21 -0
- higpertext/templates/workflows/plan.json +59 -0
- higpertext/templates/workflows/review.json +26 -0
- higpertext/templates/workflows/spec.json +27 -0
- higpertext_cli-0.8.0.dist-info/METADATA +35 -0
- higpertext_cli-0.8.0.dist-info/RECORD +335 -0
- higpertext_cli-0.8.0.dist-info/WHEEL +5 -0
- higpertext_cli-0.8.0.dist-info/entry_points.txt +2 -0
- higpertext_cli-0.8.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"""higpertext Memory Manager — persiste acciones, aprendizajes y contexto del agente en .memory/."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import argparse
|
|
5
|
+
import secrets
|
|
6
|
+
import time
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
11
|
+
_log = get_logger()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def generate_action_id() -> str:
|
|
15
|
+
"""Genera un action_id único con timestamp y sufijo criptográfico."""
|
|
16
|
+
timestamp = int(time.time())
|
|
17
|
+
rand_suffix = secrets.token_hex(2)
|
|
18
|
+
return f"act_{timestamp}_{rand_suffix}"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _parse_csv(value: str | None) -> list[str]:
|
|
22
|
+
"""Parsea una cadena separada por comas en una lista limpia."""
|
|
23
|
+
if not value:
|
|
24
|
+
return []
|
|
25
|
+
return [item.strip() for item in value.split(",") if item.strip()]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _build_entry(
|
|
29
|
+
action: str,
|
|
30
|
+
status: str,
|
|
31
|
+
notes: str,
|
|
32
|
+
action_id: str,
|
|
33
|
+
learned: list,
|
|
34
|
+
tags: list,
|
|
35
|
+
failure_root_cause: str | None,
|
|
36
|
+
) -> dict:
|
|
37
|
+
"""Construye el diccionario de entrada para el journal."""
|
|
38
|
+
return {
|
|
39
|
+
"action_id": action_id,
|
|
40
|
+
"timestamp": datetime.now().isoformat(),
|
|
41
|
+
"action": action,
|
|
42
|
+
"status": status,
|
|
43
|
+
"tags": tags,
|
|
44
|
+
"notes": notes,
|
|
45
|
+
"learned": learned,
|
|
46
|
+
"failure_root_cause": failure_root_cause if status == "failure" else None,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _load_json_file(path: Path, default):
|
|
51
|
+
"""Carga un archivo JSON; retorna default si no existe o hay error."""
|
|
52
|
+
if not path.exists():
|
|
53
|
+
return default
|
|
54
|
+
try:
|
|
55
|
+
return json.loads(path.read_text(encoding="utf-8"))
|
|
56
|
+
except (OSError, json.JSONDecodeError):
|
|
57
|
+
return default
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _update_learnings(learnings: dict, tags: list, entry: dict, learned: list, notes: str) -> None:
|
|
61
|
+
"""Actualiza el dict de learnings con la nueva entrada por cada tag."""
|
|
62
|
+
for tag in tags:
|
|
63
|
+
if tag not in learnings:
|
|
64
|
+
learnings[tag] = []
|
|
65
|
+
if learned or notes:
|
|
66
|
+
learnings[tag].append(
|
|
67
|
+
{
|
|
68
|
+
"action_id": entry["action_id"],
|
|
69
|
+
"timestamp": entry["timestamp"],
|
|
70
|
+
"action": entry["action"],
|
|
71
|
+
"status": entry["status"],
|
|
72
|
+
"notes": notes,
|
|
73
|
+
"learned": learned,
|
|
74
|
+
"failure_root_cause": entry["failure_root_cause"],
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def save_memory(
|
|
80
|
+
action: str,
|
|
81
|
+
status: str,
|
|
82
|
+
notes: str,
|
|
83
|
+
action_id: str | None = None,
|
|
84
|
+
learned_str: str | None = None,
|
|
85
|
+
failure_root_cause: str | None = None,
|
|
86
|
+
tags_str: str | None = None,
|
|
87
|
+
) -> None:
|
|
88
|
+
"""Persiste una acción en journal.json, learnings.json y regenera context.md."""
|
|
89
|
+
memory_dir = Path(".memory")
|
|
90
|
+
memory_dir.mkdir(exist_ok=True)
|
|
91
|
+
|
|
92
|
+
journal_file = memory_dir / "journal.json"
|
|
93
|
+
learnings_file = memory_dir / "learnings.json"
|
|
94
|
+
context_file = memory_dir / "context.md"
|
|
95
|
+
|
|
96
|
+
action_id = action_id or generate_action_id()
|
|
97
|
+
learned = _parse_csv(learned_str)
|
|
98
|
+
tags = _parse_csv(tags_str) or ["general"]
|
|
99
|
+
tags = [t.lower() for t in tags]
|
|
100
|
+
|
|
101
|
+
entry = _build_entry(action, status, notes, action_id, learned, tags, failure_root_cause)
|
|
102
|
+
|
|
103
|
+
journal: list = _load_json_file(journal_file, [])
|
|
104
|
+
journal.append(entry)
|
|
105
|
+
journal_file.write_text(json.dumps(journal, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
106
|
+
|
|
107
|
+
learnings: dict = _load_json_file(learnings_file, {})
|
|
108
|
+
_update_learnings(learnings, tags, entry, learned, notes)
|
|
109
|
+
learnings_file.write_text(json.dumps(learnings, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
110
|
+
|
|
111
|
+
regenerate_context_markdown(journal, learnings, context_file)
|
|
112
|
+
_log.ok(f"[SUCCESS] Memoria registrada en .memory/. Action ID: {action_id}")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _render_learnings_section(learnings: dict) -> list[str]:
|
|
116
|
+
"""Renderiza la sección de aprendizajes agrupados por categoría."""
|
|
117
|
+
lines = ["\n## Aprendizajes y Lecciones Clave"]
|
|
118
|
+
has_learnings = False
|
|
119
|
+
for tag, items in sorted(learnings.items()):
|
|
120
|
+
tag_entries = [lrn for item in items for lrn in item.get("learned", [])]
|
|
121
|
+
if not tag_entries:
|
|
122
|
+
continue
|
|
123
|
+
has_learnings = True
|
|
124
|
+
lines.append(f"\n### Categoría: `{tag.upper()}`")
|
|
125
|
+
for entry in sorted(set(tag_entries)):
|
|
126
|
+
lines.append(f"- {entry}")
|
|
127
|
+
if not has_learnings:
|
|
128
|
+
lines.append(
|
|
129
|
+
"\n*No se han registrado aprendizajes específicos aún. "
|
|
130
|
+
"Los aprendizajes se acumulan a través del parámetro `--learned`.*"
|
|
131
|
+
)
|
|
132
|
+
return lines
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _render_failures_section(journal: list) -> list[str]:
|
|
136
|
+
"""Renderiza la sección de historial de fallas con causa raíz."""
|
|
137
|
+
lines = ["\n---\n\n## Historial de Fallas y Causa Raíz"]
|
|
138
|
+
failures = [j for j in journal if j["status"] == "failure"]
|
|
139
|
+
if not failures:
|
|
140
|
+
lines.append("\n*No se han registrado fallas de ejecución en el historial de memoria.*")
|
|
141
|
+
return lines
|
|
142
|
+
lines.append("\n| ID | Acción | Causa Raíz | Notas | Timestamp |")
|
|
143
|
+
lines.append("|---|---|---|---|---|")
|
|
144
|
+
for f in reversed(failures[-10:]):
|
|
145
|
+
root_cause = f.get("failure_root_cause") or "No especificada"
|
|
146
|
+
lines.append(
|
|
147
|
+
f"| `{f['action_id']}` | `{f['action']}` | **{root_cause}** "
|
|
148
|
+
f"| {f['notes']} | `{f['timestamp']}` |"
|
|
149
|
+
)
|
|
150
|
+
return lines
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _render_journal_section(journal: list) -> list[str]:
|
|
154
|
+
"""Renderiza la sección del historial secuencial reciente."""
|
|
155
|
+
lines = ["\n---\n\n## Historial Reciente de Operaciones"]
|
|
156
|
+
lines.append("\n| ID | Timestamp | Acción | Estado | Tags |")
|
|
157
|
+
lines.append("|---|---|---|---|---|")
|
|
158
|
+
for j in reversed(journal[-15:]):
|
|
159
|
+
tags_str = ", ".join(f"`{t}`" for t in j.get("tags", []))
|
|
160
|
+
symbol = "SUCCESS" if j["status"] == "success" else "FAILURE"
|
|
161
|
+
lines.append(
|
|
162
|
+
f"| `{j['action_id']}` | `{j['timestamp'][:19]}` "
|
|
163
|
+
f"| `{j['action']}` | {symbol} | {tags_str} |"
|
|
164
|
+
)
|
|
165
|
+
return lines
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def regenerate_context_markdown(journal: list, learnings: dict, context_file: Path) -> None:
|
|
169
|
+
"""Genera un reporte Markdown limpio y estructurado de la memoria acumulada."""
|
|
170
|
+
lines = [
|
|
171
|
+
"# Registro de Memoria y Aprendizaje del Agente",
|
|
172
|
+
"\nEste archivo es autogenerado por el `memory-manager` de higpertext.",
|
|
173
|
+
"\n---",
|
|
174
|
+
]
|
|
175
|
+
lines.extend(_render_learnings_section(learnings))
|
|
176
|
+
lines.extend(_render_failures_section(journal))
|
|
177
|
+
lines.extend(_render_journal_section(journal))
|
|
178
|
+
context_file.write_text("\n".join(lines), encoding="utf-8")
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _build_parser() -> argparse.ArgumentParser:
|
|
182
|
+
"""Construye el parser CLI compatible con capabilities_runner."""
|
|
183
|
+
parser = argparse.ArgumentParser()
|
|
184
|
+
parser.add_argument("--action", required=True)
|
|
185
|
+
parser.add_argument("--status", required=True, choices=("success", "failure"))
|
|
186
|
+
parser.add_argument("--notes", required=True)
|
|
187
|
+
parser.add_argument("--action_id", required=False)
|
|
188
|
+
parser.add_argument("--learned", required=False)
|
|
189
|
+
parser.add_argument("--failure_root_cause", required=False)
|
|
190
|
+
parser.add_argument("--tags", required=False)
|
|
191
|
+
return parser
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def main(argv: list[str] | None = None) -> None:
|
|
195
|
+
"""Punto de entrada de la capability common.memory-manager."""
|
|
196
|
+
args = _build_parser().parse_args(argv)
|
|
197
|
+
|
|
198
|
+
save_memory(
|
|
199
|
+
action=args.action,
|
|
200
|
+
status=args.status,
|
|
201
|
+
notes=args.notes,
|
|
202
|
+
action_id=args.action_id,
|
|
203
|
+
learned_str=args.learned,
|
|
204
|
+
failure_root_cause=args.failure_root_cause,
|
|
205
|
+
tags_str=args.tags,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
if __name__ == "__main__":
|
|
210
|
+
main()
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""higpertext Presentation Engine — convierte Markdown en presentaciones HTML Premium."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import shutil
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
8
|
+
_log = get_logger()
|
|
9
|
+
|
|
10
|
+
_SCRIPT_DIR = Path(__file__).parent.absolute()
|
|
11
|
+
_CAP_ROOT = _SCRIPT_DIR.parent
|
|
12
|
+
_ASSETS_DIR = _CAP_ROOT / "assets"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _copy_js_assets(output_file: Path) -> None:
|
|
16
|
+
"""Copia las librerías JS al directorio de salida."""
|
|
17
|
+
output_js_dir = output_file.parent / "assets" / "js"
|
|
18
|
+
output_js_dir.mkdir(parents=True, exist_ok=True)
|
|
19
|
+
source_js_dir = _ASSETS_DIR / "js"
|
|
20
|
+
if source_js_dir.exists():
|
|
21
|
+
for js_file in source_js_dir.glob("*.js"):
|
|
22
|
+
shutil.copy(js_file, output_js_dir)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _copy_css_assets(output_file: Path) -> None:
|
|
26
|
+
"""Copia los archivos CSS al directorio de salida."""
|
|
27
|
+
output_css_dir = output_file.parent / "assets" / "css"
|
|
28
|
+
output_css_dir.mkdir(parents=True, exist_ok=True)
|
|
29
|
+
source_css_dir = _ASSETS_DIR / "css"
|
|
30
|
+
if source_css_dir.exists():
|
|
31
|
+
for css_file in source_css_dir.glob("*.css"):
|
|
32
|
+
shutil.copy(css_file, output_css_dir)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def generate_presentation(md_path: str, output_path: str) -> None:
|
|
36
|
+
"""Genera una presentación HTML a partir de un archivo Markdown."""
|
|
37
|
+
input_file = Path(md_path)
|
|
38
|
+
if not input_file.exists():
|
|
39
|
+
_log.error(f"Error: Archivo {md_path} no encontrado.")
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
template_path = _ASSETS_DIR / "base-template.html"
|
|
43
|
+
if not template_path.exists():
|
|
44
|
+
_log.error(f"Error: No se encuentra la plantilla base en {template_path}")
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
md_content = input_file.read_text(encoding="utf-8")
|
|
48
|
+
html_template = template_path.read_text(encoding="utf-8")
|
|
49
|
+
final_html = html_template.replace("{{SLIDES_CONTENT}}", md_content)
|
|
50
|
+
|
|
51
|
+
output_file = Path(output_path)
|
|
52
|
+
_copy_js_assets(output_file)
|
|
53
|
+
_copy_css_assets(output_file)
|
|
54
|
+
output_file.write_text(final_html, encoding="utf-8")
|
|
55
|
+
_log.ok(f"[SUCCESS] Presentación generada en: {output_path}")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
if __name__ == "__main__":
|
|
59
|
+
parser = argparse.ArgumentParser()
|
|
60
|
+
parser.add_argument("--input", required=True)
|
|
61
|
+
parser.add_argument("--output", default="presentation.html")
|
|
62
|
+
args = parser.parse_args()
|
|
63
|
+
generate_presentation(args.input, args.output)
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"""common.quality-scan — genera un reporte Markdown básico de calidad Python."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import ast
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
10
|
+
_log = get_logger()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class FileQuality:
|
|
15
|
+
path: Path
|
|
16
|
+
score: int
|
|
17
|
+
penalties: list[str]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def scan_python_file(path: Path, max_function_lines: int, max_class_lines: int) -> FileQuality:
|
|
21
|
+
penalties: list[str] = []
|
|
22
|
+
try:
|
|
23
|
+
source = path.read_text(encoding="utf-8")
|
|
24
|
+
tree = ast.parse(source)
|
|
25
|
+
except (OSError, SyntaxError) as exc:
|
|
26
|
+
return FileQuality(path, 50, [f"No se pudo parsear el archivo: {exc}"])
|
|
27
|
+
|
|
28
|
+
lines = source.splitlines()
|
|
29
|
+
for node in ast.walk(tree):
|
|
30
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
31
|
+
length = _node_length(node)
|
|
32
|
+
if length > max_function_lines:
|
|
33
|
+
penalties.append(f"Función `{
|
|
34
|
+
node.name}` excede {max_function_lines} líneas L{
|
|
35
|
+
node.lineno}-L{
|
|
36
|
+
getattr(
|
|
37
|
+
node,
|
|
38
|
+
'end_lineno',
|
|
39
|
+
node.lineno)}")
|
|
40
|
+
if isinstance(node, ast.ClassDef):
|
|
41
|
+
length = _node_length(node)
|
|
42
|
+
if length > max_class_lines:
|
|
43
|
+
penalties.append(f"Clase `{
|
|
44
|
+
node.name}` excede {max_class_lines} líneas L{
|
|
45
|
+
node.lineno}-L{
|
|
46
|
+
getattr(
|
|
47
|
+
node,
|
|
48
|
+
'end_lineno',
|
|
49
|
+
node.lineno)}")
|
|
50
|
+
|
|
51
|
+
if lines and not _has_module_docstring(tree):
|
|
52
|
+
penalties.append("Sin comentarios/docstring de módulo")
|
|
53
|
+
|
|
54
|
+
score = max(0, 100 - (len(penalties) * 10))
|
|
55
|
+
return FileQuality(path, score, penalties)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def scan_tree(root: Path, max_function_lines: int, max_class_lines: int) -> list[FileQuality]:
|
|
59
|
+
try:
|
|
60
|
+
from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
|
|
61
|
+
except ImportError:
|
|
62
|
+
WORKSPACE_DIR_NAME = ".higpertext"
|
|
63
|
+
ignored = {".git", ".venv", "venv", "__pycache__", "node_modules", WORKSPACE_DIR_NAME}
|
|
64
|
+
files = [path for path in root.rglob("*.py") if not ignored.intersection(path.parts)]
|
|
65
|
+
return [scan_python_file(path, max_function_lines, max_class_lines) for path in sorted(files)]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def write_report(results: list[FileQuality], root: Path, output: Path) -> None:
|
|
69
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
70
|
+
lines = ["# Code Quality Report", "", f"Archivos analizados: `{len(results)}`", ""]
|
|
71
|
+
for result in results:
|
|
72
|
+
rel = _relative(result.path, root)
|
|
73
|
+
icon = "🟢" if result.score >= 90 else "🟡" if result.score >= 70 else "🔴"
|
|
74
|
+
lines += [
|
|
75
|
+
f"### {icon} `{rel}` — {result.score}/100",
|
|
76
|
+
"",
|
|
77
|
+
"**Penalizaciones aplicadas:**",
|
|
78
|
+
]
|
|
79
|
+
if result.penalties:
|
|
80
|
+
lines.extend(f"- {penalty}" for penalty in result.penalties)
|
|
81
|
+
else:
|
|
82
|
+
lines.append("- Sin penalizaciones")
|
|
83
|
+
lines += ["", "---", ""]
|
|
84
|
+
output.write_text("\n".join(lines), encoding="utf-8")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _node_length(node: ast.AST) -> int:
|
|
88
|
+
return int(
|
|
89
|
+
getattr(node, "end_lineno", getattr(node, "lineno", 0)) - getattr(node, "lineno", 0) + 1
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _has_module_docstring(tree: ast.Module) -> bool:
|
|
94
|
+
return ast.get_docstring(tree) is not None
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _relative(path: Path, root: Path) -> str:
|
|
98
|
+
try:
|
|
99
|
+
return path.relative_to(root).as_posix()
|
|
100
|
+
except ValueError:
|
|
101
|
+
return path.as_posix()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def main() -> None:
|
|
105
|
+
parser = argparse.ArgumentParser(description="Genera reporte de calidad Python")
|
|
106
|
+
parser.add_argument("--target", default="src", help="Directorio o archivo objetivo")
|
|
107
|
+
parser.add_argument("--output", default=".higpertext/reports/code_quality_report.md")
|
|
108
|
+
parser.add_argument("--max_function_lines", type=int, default=30)
|
|
109
|
+
parser.add_argument("--max_class_lines", type=int, default=200)
|
|
110
|
+
args = parser.parse_args()
|
|
111
|
+
|
|
112
|
+
root = Path.cwd()
|
|
113
|
+
target = Path(args.target)
|
|
114
|
+
if not target.is_absolute():
|
|
115
|
+
target = root / target
|
|
116
|
+
output = Path(args.output)
|
|
117
|
+
if not output.is_absolute():
|
|
118
|
+
output = root / output
|
|
119
|
+
|
|
120
|
+
results = (
|
|
121
|
+
[scan_python_file(target, args.max_function_lines, args.max_class_lines)]
|
|
122
|
+
if target.is_file()
|
|
123
|
+
else scan_tree(target, args.max_function_lines, args.max_class_lines)
|
|
124
|
+
)
|
|
125
|
+
write_report(results, root, output)
|
|
126
|
+
violations = sum(1 for result in results if result.penalties)
|
|
127
|
+
_log.ok(f"[SUCCESS] Reporte de calidad generado en: {output}")
|
|
128
|
+
_log.info(f"[*] Archivos analizados: {len(results)} · con violaciones: {violations}")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
if __name__ == "__main__":
|
|
132
|
+
main()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Capacidad para indexar el proyecto para RAG Semántico."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
import argparse
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
# Configurar path para importar higpertext
|
|
9
|
+
_ROOT = Path(__file__).resolve().parents[5]
|
|
10
|
+
sys.path.insert(0, str(_ROOT / "src"))
|
|
11
|
+
|
|
12
|
+
from higpertext.kernel.infrastructure.llm.providers.gemini_embeddings import GeminiEmbeddingProvider
|
|
13
|
+
from higpertext.kernel.infrastructure.database.local_vector_store import LocalVectorStore
|
|
14
|
+
from higpertext.kernel.application.rag_service import RAGService
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def main() -> None:
|
|
18
|
+
parser = argparse.ArgumentParser(description="Indexa el proyecto para búsqueda semántica (RAG).")
|
|
19
|
+
parser.add_argument("--root", type=str, default=".", help="Ruta al proyecto.")
|
|
20
|
+
args = parser.parse_args()
|
|
21
|
+
|
|
22
|
+
project_root = Path(args.root).resolve()
|
|
23
|
+
print(f"[*] Iniciando indexación semántica en: {project_root}")
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
embedder = GeminiEmbeddingProvider(project_root)
|
|
27
|
+
store = LocalVectorStore(project_root)
|
|
28
|
+
service = RAGService(embedder, store)
|
|
29
|
+
|
|
30
|
+
chunks_indexed = service.index_project(project_root)
|
|
31
|
+
print(f"[+] Indexación completada. {chunks_indexed} fragmentos semánticos indexados con éxito.")
|
|
32
|
+
sys.exit(0)
|
|
33
|
+
except Exception as e:
|
|
34
|
+
print(f"[ERROR] Falló la indexación: {e}", file=sys.stderr)
|
|
35
|
+
sys.exit(1)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
if __name__ == "__main__":
|
|
39
|
+
main()
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Capacidad common.report-viewer — Dashboard HTML Interactivo de Reportes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
import argparse
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
|
|
8
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
9
|
+
_log = get_logger()
|
|
10
|
+
|
|
11
|
+
# Resuelve raíz del proyecto
|
|
12
|
+
_HERE = Path(__file__).resolve()
|
|
13
|
+
_ROOT = next(
|
|
14
|
+
(p for p in _HERE.parents if (p / "src/config/htx_config.json").exists()),
|
|
15
|
+
_HERE.parents[4],
|
|
16
|
+
)
|
|
17
|
+
sys.path.insert(0, str(_ROOT / "src"))
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
from higpertext.kernel.infrastructure.output_store import OutputStore
|
|
21
|
+
except ImportError:
|
|
22
|
+
OutputStore = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def main() -> None:
|
|
26
|
+
parser = argparse.ArgumentParser(description="higpertext Premium Report Dashboard Compiler")
|
|
27
|
+
parser.add_argument(
|
|
28
|
+
"--output",
|
|
29
|
+
default=".higpertext/reports/index.html",
|
|
30
|
+
help="Ruta de destino del dashboard HTML resultante.",
|
|
31
|
+
)
|
|
32
|
+
args = parser.parse_args()
|
|
33
|
+
|
|
34
|
+
out_path = _ROOT / args.output
|
|
35
|
+
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
|
|
37
|
+
# 1. Leer los componentes Markdown
|
|
38
|
+
telemetry_file = _ROOT / WORKSPACE_DIR_NAME / "reports" / "common_telemetry_report.txt"
|
|
39
|
+
rationale_file = _ROOT / WORKSPACE_DIR_NAME / "reports" / "commit_rationale_history.md"
|
|
40
|
+
drift_file = _ROOT / WORKSPACE_DIR_NAME / "reports" / "architecture_drift.md"
|
|
41
|
+
|
|
42
|
+
telemetry_content = (
|
|
43
|
+
telemetry_file.read_text(encoding="utf-8")
|
|
44
|
+
if telemetry_file.exists()
|
|
45
|
+
else "Sin datos de telemetría."
|
|
46
|
+
)
|
|
47
|
+
rationale_content = (
|
|
48
|
+
rationale_file.read_text(encoding="utf-8")
|
|
49
|
+
if rationale_file.exists()
|
|
50
|
+
else "Sin diario de decisiones."
|
|
51
|
+
)
|
|
52
|
+
drift_content = (
|
|
53
|
+
drift_file.read_text(encoding="utf-8")
|
|
54
|
+
if drift_file.exists()
|
|
55
|
+
else "Sin análisis de desviación."
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# 2. Generar el documento Markdown consolidado con formato ATX
|
|
59
|
+
# Las secciones usan '##' para convertirse en slides del HTML Presentation Engine
|
|
60
|
+
slides = [
|
|
61
|
+
"# Dashboard de Entrega & Decisiones Técnicas",
|
|
62
|
+
"Resumen ejecutivo de telemetría, diario de decisiones de diseño y análisis de desviación del higpertext Engine.", # noqa: E501
|
|
63
|
+
"",
|
|
64
|
+
"## Resumen de Telemetría (Consumo & ROI)",
|
|
65
|
+
"<!-- tipo: grid -->",
|
|
66
|
+
f"```text\n{telemetry_content}\n```",
|
|
67
|
+
"",
|
|
68
|
+
"## Análisis de Desviación Arquitectónica",
|
|
69
|
+
"---",
|
|
70
|
+
drift_content,
|
|
71
|
+
"",
|
|
72
|
+
"## Diario Histórico de Decisiones",
|
|
73
|
+
"---",
|
|
74
|
+
rationale_content,
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
temp_md_path = out_path.parent / "temp_dashboard.md"
|
|
78
|
+
temp_md_path.write_text("\n".join(slides), encoding="utf-8")
|
|
79
|
+
|
|
80
|
+
# 3. Invocar al motor de presentaciones HTML local
|
|
81
|
+
try:
|
|
82
|
+
from higpertext.capabilities.common.scripts.presentation_engine import (
|
|
83
|
+
generate_presentation,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
generate_presentation(str(temp_md_path), str(out_path))
|
|
87
|
+
except Exception as e:
|
|
88
|
+
_log.error(f"[ERROR] No se pudo generar la presentación HTML: {e}")
|
|
89
|
+
finally:
|
|
90
|
+
# Limpiar archivo markdown temporal
|
|
91
|
+
if temp_md_path.exists():
|
|
92
|
+
try:
|
|
93
|
+
temp_md_path.unlink()
|
|
94
|
+
except OSError: # nosec B110
|
|
95
|
+
pass
|
|
96
|
+
|
|
97
|
+
if OutputStore:
|
|
98
|
+
OutputStore(_ROOT).write(
|
|
99
|
+
"common.report-viewer", out_path.read_text(encoding="utf-8"), fmt="html"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
_log.ok(f"[SUCCESS] Dashboard Premium HTML compilado en: {args.output}")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
if __name__ == "__main__":
|
|
106
|
+
main()
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Capability common.roadmap-report — reporte explicativo del roadmap activo."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from higpertext.kernel.application.roadmap_reporter import RoadmapReportBuilder, ProgressAnalyzer, RoadmapParser
|
|
5
|
+
import argparse
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
|
|
9
|
+
|
|
10
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
11
|
+
_log = get_logger()
|
|
12
|
+
|
|
13
|
+
_HERE = Path(__file__).resolve()
|
|
14
|
+
_ROOT = next((p for p in _HERE.parents if (p / "src/config/htx_config.json").exists()), _HERE.parents[4])
|
|
15
|
+
sys.path.insert(0, str(_ROOT / "src"))
|
|
16
|
+
sys.path.insert(0, str(_ROOT))
|
|
17
|
+
|
|
18
|
+
def _parse_args() -> argparse.Namespace:
|
|
19
|
+
parser = argparse.ArgumentParser(description="Genera reporte explicativo del roadmap.")
|
|
20
|
+
parser.add_argument("--roadmap", default=str(_ROOT / WORKSPACE_DIR_NAME / "roadmap.json"))
|
|
21
|
+
parser.add_argument("--format", dest="fmt", default="markdown", choices=["markdown", "html"])
|
|
22
|
+
parser.add_argument("--output", default=None)
|
|
23
|
+
return parser.parse_args()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _resolve_output(args: argparse.Namespace, roadmap_id: str) -> Path:
|
|
27
|
+
if args.output:
|
|
28
|
+
return Path(args.output)
|
|
29
|
+
ext = "html" if args.fmt == "html" else "md"
|
|
30
|
+
out_dir = _ROOT / WORKSPACE_DIR_NAME / "reports" / "roadmap"
|
|
31
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
32
|
+
return out_dir / f"{roadmap_id}_report.{ext}"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _print_summary(report, analysis, out: Path) -> None:
|
|
36
|
+
r = report.roadmap
|
|
37
|
+
_log.info("╔─ HIGPERTEXT · Roadmap Report ───────────────────────────────")
|
|
38
|
+
_log.info(f"│ Roadmap : {r.name} ({r.id})")
|
|
39
|
+
_log.info(f"│ Fases : {report.done_phases}/{report.total_phases} completadas")
|
|
40
|
+
_log.info(f"│ Progreso : {analysis.completion_pct:.0f}%")
|
|
41
|
+
_log.info(f"│ Tags : {', '.join(analysis.impact_tags)}")
|
|
42
|
+
_log.info(f"│ Skills : {', '.join(report.all_skills_used) or '—'}")
|
|
43
|
+
_log.info(f"│ Reporte : {out.relative_to(_ROOT)}")
|
|
44
|
+
_log.info("╚───────────────────────────────────────────────────────")
|
|
45
|
+
_log.info(f"\n{analysis.summary}")
|
|
46
|
+
_log.ok(f"\n[SUCCESS] Reporte generado: {out}")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def main() -> None:
|
|
50
|
+
args = _parse_args()
|
|
51
|
+
roadmap_path = Path(args.roadmap)
|
|
52
|
+
if not roadmap_path.exists():
|
|
53
|
+
_log.error(f"[ERROR] Roadmap no encontrado: {roadmap_path}")
|
|
54
|
+
sys.exit(1)
|
|
55
|
+
try:
|
|
56
|
+
report = RoadmapParser().parse_file(roadmap_path)
|
|
57
|
+
except ValueError as exc:
|
|
58
|
+
_log.error(f"[ERROR] {exc}")
|
|
59
|
+
sys.exit(1)
|
|
60
|
+
analysis = ProgressAnalyzer().analyze(report)
|
|
61
|
+
builder = RoadmapReportBuilder()
|
|
62
|
+
content = (
|
|
63
|
+
builder.to_html(report, analysis)
|
|
64
|
+
if args.fmt == "html"
|
|
65
|
+
else builder.to_markdown(report, analysis)
|
|
66
|
+
)
|
|
67
|
+
out = _resolve_output(args, report.roadmap.id)
|
|
68
|
+
out.write_text(content, encoding="utf-8")
|
|
69
|
+
_print_summary(report, analysis, out)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == "__main__":
|
|
73
|
+
main()
|