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,144 @@
|
|
|
1
|
+
"""common.doctor — diagnóstico integral rápido del workspace higpertext."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import json
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
11
|
+
_log = get_logger()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _read_json(path: Path) -> dict:
|
|
15
|
+
try:
|
|
16
|
+
return json.loads(path.read_text(encoding="utf-8"))
|
|
17
|
+
except (OSError, json.JSONDecodeError):
|
|
18
|
+
return {}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _check(name: str, ok: bool, message: str, severity: str = "critical") -> dict:
|
|
22
|
+
return {
|
|
23
|
+
"name": name,
|
|
24
|
+
"status": "ok" if ok else "fail",
|
|
25
|
+
"severity": "ok" if ok else severity,
|
|
26
|
+
"message": message,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def run_doctor(root: Path) -> list[dict]:
|
|
31
|
+
"""Ejecuta checks operativos sin requerir un asistente activo."""
|
|
32
|
+
checks = [
|
|
33
|
+
_check_htx(root),
|
|
34
|
+
_check_environment(root),
|
|
35
|
+
_check_capabilities(root),
|
|
36
|
+
_check_hooks(root),
|
|
37
|
+
_check_hook_sync(root),
|
|
38
|
+
_check_cache(root),
|
|
39
|
+
_check_reports(root),
|
|
40
|
+
]
|
|
41
|
+
return checks
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _check_htx(root: Path) -> dict:
|
|
45
|
+
candidates = [root / ".venv" / "bin" / "htx", root / "htx.py"]
|
|
46
|
+
return _check("htx", any(path.exists() for path in candidates), "launcher htx disponible")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _check_environment(root: Path) -> dict:
|
|
50
|
+
env = _read_json(root / WORKSPACE_DIR_NAME / "config" / "environment.json")
|
|
51
|
+
profile = env.get("active_profile") or env.get("profile")
|
|
52
|
+
assistant = env.get("assistant")
|
|
53
|
+
ok = bool(profile)
|
|
54
|
+
message = f"perfil={profile or '—'} assistant={assistant or '—'}"
|
|
55
|
+
return _check("environment", ok, message, "warning")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _check_capabilities(root: Path) -> dict:
|
|
59
|
+
cap_dir = root / "src" / "higpertext" / "capabilities"
|
|
60
|
+
invalid: list[str] = []
|
|
61
|
+
total = 0
|
|
62
|
+
for path in cap_dir.rglob("*.json") if cap_dir.exists() else []:
|
|
63
|
+
total += 1
|
|
64
|
+
if not _read_json(path):
|
|
65
|
+
invalid.append(str(path.relative_to(root)))
|
|
66
|
+
ok = total > 0 and not invalid
|
|
67
|
+
message = f"{total} capabilities JSON; inválidos={len(invalid)}"
|
|
68
|
+
return _check("capabilities", ok, message)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _check_hooks(root: Path) -> dict:
|
|
72
|
+
catalog = _read_json(root / "src" / "higpertext" / "hooks" / "hooks_catalog.json")
|
|
73
|
+
ids = {hook.get("id") for hook in catalog.get("hooks", [])}
|
|
74
|
+
required = {
|
|
75
|
+
"hook_bash_guard",
|
|
76
|
+
"hook_read_guard",
|
|
77
|
+
"hook_security_guard_pre",
|
|
78
|
+
"hook_security_guard_post",
|
|
79
|
+
"hook_post_observer",
|
|
80
|
+
}
|
|
81
|
+
missing = sorted(required - ids)
|
|
82
|
+
return _check("hooks", not missing, f"faltantes={missing or 'ninguno'}")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _check_hook_sync(root: Path) -> dict:
|
|
86
|
+
try:
|
|
87
|
+
from higpertext.capabilities.common.scripts.hook_sync_check import (
|
|
88
|
+
run_sync_check,
|
|
89
|
+
)
|
|
90
|
+
except ImportError:
|
|
91
|
+
return _check("hook_sync", False, "hook-sync-check no disponible", "warning")
|
|
92
|
+
result = run_sync_check(root)
|
|
93
|
+
drift = [item["assistant"] for item in result["assistants"] if item["status"] == "drift"]
|
|
94
|
+
missing = [item["assistant"] for item in result["assistants"] if item["status"] == "missing"]
|
|
95
|
+
ok = not drift
|
|
96
|
+
message = f"drift={drift or 'ninguno'} missing={missing or 'ninguno'}"
|
|
97
|
+
return _check("hook_sync", ok, message, "warning")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _check_cache(root: Path) -> dict:
|
|
101
|
+
cache_dir = root / WORKSPACE_DIR_NAME / "__cache__"
|
|
102
|
+
files = list(cache_dir.glob("*.json")) if cache_dir.exists() else []
|
|
103
|
+
stale = 0
|
|
104
|
+
for path in files:
|
|
105
|
+
data = _read_json(path)
|
|
106
|
+
if not data or "created_at" not in data:
|
|
107
|
+
stale += 1
|
|
108
|
+
ok = stale == 0
|
|
109
|
+
message = f"entradas={len(files)} corruptas={stale}"
|
|
110
|
+
return _check("cache", ok, message, "warning")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _check_reports(root: Path) -> dict:
|
|
114
|
+
reports = root / WORKSPACE_DIR_NAME / "reports"
|
|
115
|
+
expected = ["test_resolution_map.md"]
|
|
116
|
+
missing = [name for name in expected if not (reports / name).exists()]
|
|
117
|
+
return _check("reports", True, f"faltantes opcionales={missing or 'ninguno'}", "warning")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _print_human(checks: list[dict]) -> None:
|
|
121
|
+
_log.info("╔─ HIGPERTEXT · Doctor ─────────────────────────────────────")
|
|
122
|
+
for item in checks:
|
|
123
|
+
marker = "✓" if item["status"] == "ok" else "✗"
|
|
124
|
+
_log.info(f"│ {marker} {item['name']}: {item['message']}")
|
|
125
|
+
_log.info("╚────────────────────────────────────────────────────────────")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def main(argv: list[str] | None = None) -> None:
|
|
129
|
+
parser = argparse.ArgumentParser(description="Diagnóstico integral higpertext")
|
|
130
|
+
parser.add_argument("--json", default="false", help="Emitir JSON estructurado")
|
|
131
|
+
args = parser.parse_args(argv)
|
|
132
|
+
|
|
133
|
+
checks = run_doctor(Path.cwd())
|
|
134
|
+
ok = all(item["status"] == "ok" or item["severity"] == "warning" for item in checks)
|
|
135
|
+
if args.json.lower() in {"true", "1", "yes"}:
|
|
136
|
+
print(json.dumps({"ok": ok, "checks": checks}, ensure_ascii=False, indent=2))
|
|
137
|
+
else:
|
|
138
|
+
_print_human(checks)
|
|
139
|
+
if not ok:
|
|
140
|
+
sys.exit(1)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if __name__ == "__main__":
|
|
144
|
+
main()
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Capability common.efficiency-meter — mide la eficiencia de una sesión.
|
|
2
|
+
|
|
3
|
+
Cruza telemetry.jsonl + context_packs para calcular: tokens totales,
|
|
4
|
+
exploration_waste_ratio, context_hit_rate y hook_intercepts.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
import argparse
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
|
|
12
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
13
|
+
_log = get_logger()
|
|
14
|
+
|
|
15
|
+
def _resolve_core() -> Path:
|
|
16
|
+
here = Path(__file__).resolve()
|
|
17
|
+
for parent in here.parents:
|
|
18
|
+
core = parent / "src" / "core"
|
|
19
|
+
if core.exists():
|
|
20
|
+
return core
|
|
21
|
+
return here.parent
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def main() -> None:
|
|
25
|
+
parser = argparse.ArgumentParser(description="Mide la eficiencia de una sesión.")
|
|
26
|
+
parser.add_argument(
|
|
27
|
+
"--session",
|
|
28
|
+
required=False,
|
|
29
|
+
default="",
|
|
30
|
+
help="ID de sesión. Si no se indica, usa la sesión activa.",
|
|
31
|
+
)
|
|
32
|
+
parser.add_argument(
|
|
33
|
+
"--format",
|
|
34
|
+
default="table",
|
|
35
|
+
help="Formato de salida: table|json|markdown. Default: table.",
|
|
36
|
+
)
|
|
37
|
+
args = parser.parse_args()
|
|
38
|
+
|
|
39
|
+
core = _resolve_core()
|
|
40
|
+
if str(core) not in sys.path:
|
|
41
|
+
sys.path.insert(0, str(core))
|
|
42
|
+
|
|
43
|
+
from higpertext.context_engine.application.efficiency_meter import EfficiencyMeter
|
|
44
|
+
|
|
45
|
+
project_root = core.parent.parent
|
|
46
|
+
|
|
47
|
+
session_id = args.session
|
|
48
|
+
if not session_id:
|
|
49
|
+
session_file = project_root / WORKSPACE_DIR_NAME / "state" / "session.json"
|
|
50
|
+
if session_file.exists():
|
|
51
|
+
import json
|
|
52
|
+
|
|
53
|
+
data = json.loads(session_file.read_text(encoding="utf-8"))
|
|
54
|
+
session_id = data.get("session_id", "")
|
|
55
|
+
if not session_id:
|
|
56
|
+
_log.error("[ERROR] No se encontró sesión activa. Usa --session <id>.")
|
|
57
|
+
sys.exit(1)
|
|
58
|
+
|
|
59
|
+
meter = EfficiencyMeter(project_root)
|
|
60
|
+
report = meter.measure_session(session_id)
|
|
61
|
+
|
|
62
|
+
if args.format == "json":
|
|
63
|
+
import json
|
|
64
|
+
|
|
65
|
+
print(json.dumps(report.to_dict(), indent=2))
|
|
66
|
+
elif args.format == "markdown":
|
|
67
|
+
_log.info(report.to_markdown())
|
|
68
|
+
else:
|
|
69
|
+
waste_pct = f"{report.exploration_waste_ratio * 100:.1f}%"
|
|
70
|
+
hit_pct = f"{report.context_hit_rate * 100:.1f}%"
|
|
71
|
+
_log.info("╔─ HIGPERTEXT · Efficiency Report ────────────────────────────")
|
|
72
|
+
_log.info(f"│ Sesión : {report.session_id}")
|
|
73
|
+
_log.info(f"│ Tokens totales : {report.total_tokens:,}")
|
|
74
|
+
_log.info(f"│ Costo estimado : ${report.total_cost_usd:.4f} USD")
|
|
75
|
+
_log.info(f"│ Exploration waste: {waste_pct} ({report.exploration_reads} reads ciegos)")
|
|
76
|
+
_log.info(f"│ higpertext reads : {report.higpertext_reads}")
|
|
77
|
+
_log.info(f"│ Hook intercepts : {report.hook_intercepts}")
|
|
78
|
+
_log.info(f"│ Context hit rate: {hit_pct}")
|
|
79
|
+
_log.info("╚───────────────────────────────────────────────────────")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
if __name__ == "__main__":
|
|
83
|
+
main()
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Capability common.env-catalog — lista templates y motores disponibles."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
|
|
7
|
+
from higpertext.capabilities.common.scripts._env_cli import print_json, service
|
|
8
|
+
from higpertext.kernel.infrastructure import ComposeBackend
|
|
9
|
+
|
|
10
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
11
|
+
_log = get_logger()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main() -> None:
|
|
15
|
+
parser = argparse.ArgumentParser(description="Lista templates de entornos locales")
|
|
16
|
+
parser.add_argument("--engine", default="auto", choices=["auto", "docker", "podman"])
|
|
17
|
+
parser.add_argument("--json", default="false")
|
|
18
|
+
args = parser.parse_args()
|
|
19
|
+
templates = service().catalog()
|
|
20
|
+
payload = {
|
|
21
|
+
"engines": {
|
|
22
|
+
"docker": ComposeBackend("docker").available(),
|
|
23
|
+
"podman": ComposeBackend("podman").available(),
|
|
24
|
+
},
|
|
25
|
+
"templates": [
|
|
26
|
+
{
|
|
27
|
+
"id": item.id,
|
|
28
|
+
"description": item.description,
|
|
29
|
+
"source": str(item.source or ""),
|
|
30
|
+
}
|
|
31
|
+
for item in templates
|
|
32
|
+
],
|
|
33
|
+
}
|
|
34
|
+
if args.json.lower() in {"true", "1", "yes"}:
|
|
35
|
+
print_json(payload)
|
|
36
|
+
return
|
|
37
|
+
_log.info("╔─ HIGPERTEXT · Env Catalog ─────────────────────────────────")
|
|
38
|
+
_log.info(f"│ Docker : {'ok' if payload['engines']['docker'] else 'no disponible'}")
|
|
39
|
+
_log.info(f"│ Podman : {'ok' if payload['engines']['podman'] else 'no disponible'}")
|
|
40
|
+
_log.info("╠─ Templates ────────────────────────────────────────────────")
|
|
41
|
+
for item in payload["templates"]:
|
|
42
|
+
_log.info(f"│ {item['id']}: {item['description']}")
|
|
43
|
+
_log.info("╚────────────────────────────────────────────────────────────")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
if __name__ == "__main__":
|
|
47
|
+
main()
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Capability common.env-clean — limpia metadata de runs finalizados."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
7
|
+
_log = get_logger()
|
|
8
|
+
|
|
9
|
+
from higpertext.capabilities.common.scripts._env_cli import (
|
|
10
|
+
parse_bool,
|
|
11
|
+
print_json,
|
|
12
|
+
service,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main() -> None:
|
|
17
|
+
parser = argparse.ArgumentParser(description="Limpia runs de entorno")
|
|
18
|
+
parser.add_argument("--all", default="false")
|
|
19
|
+
parser.add_argument("--older_than", default="")
|
|
20
|
+
parser.add_argument("--json", default="false")
|
|
21
|
+
args = parser.parse_args()
|
|
22
|
+
count = service().clean(parse_bool(args.all))
|
|
23
|
+
if parse_bool(args.json):
|
|
24
|
+
print_json({"deleted": count})
|
|
25
|
+
return
|
|
26
|
+
_log.ok(f"[SUCCESS] {count} run(s) limpiado(s).")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
if __name__ == "__main__":
|
|
30
|
+
main()
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Capability common.env-logs — lee logs compactos de un run."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
7
|
+
_log = get_logger()
|
|
8
|
+
|
|
9
|
+
from higpertext.capabilities.common.scripts._env_cli import (
|
|
10
|
+
parse_bool,
|
|
11
|
+
print_json,
|
|
12
|
+
service,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main() -> None:
|
|
17
|
+
parser = argparse.ArgumentParser(description="Lee logs de entorno")
|
|
18
|
+
parser.add_argument("--run_id", required=True)
|
|
19
|
+
parser.add_argument("--service", default="")
|
|
20
|
+
parser.add_argument("--tail", type=int, default=200)
|
|
21
|
+
parser.add_argument("--errors_only", default="false")
|
|
22
|
+
parser.add_argument("--json", default="false")
|
|
23
|
+
args = parser.parse_args()
|
|
24
|
+
logs = service().logs(args.run_id, args.service, args.tail, parse_bool(args.errors_only))
|
|
25
|
+
if parse_bool(args.json):
|
|
26
|
+
print_json({"run_id": args.run_id, "logs": logs})
|
|
27
|
+
return
|
|
28
|
+
_log.info(logs)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
if __name__ == "__main__":
|
|
32
|
+
main()
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Capability common.env-runner — ejecuta un entorno Docker/Podman."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
|
|
7
|
+
from higpertext.capabilities.common.scripts._env_cli import (
|
|
8
|
+
parse_bool,
|
|
9
|
+
parse_env,
|
|
10
|
+
print_json,
|
|
11
|
+
print_state,
|
|
12
|
+
service,
|
|
13
|
+
state_payload,
|
|
14
|
+
)
|
|
15
|
+
from higpertext.kernel.domain import RunSpec
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main() -> None:
|
|
19
|
+
parser = argparse.ArgumentParser(description="Ejecuta entornos locales Docker/Podman")
|
|
20
|
+
parser.add_argument("--template", required=True)
|
|
21
|
+
parser.add_argument("--engine", default="auto", choices=["auto", "docker", "podman"])
|
|
22
|
+
parser.add_argument("--task", default="")
|
|
23
|
+
parser.add_argument("--command", default="")
|
|
24
|
+
parser.add_argument("--service", default="")
|
|
25
|
+
parser.add_argument("--detach", default="false")
|
|
26
|
+
parser.add_argument("--parallel", default="false")
|
|
27
|
+
parser.add_argument("--timeout", type=int, default=300)
|
|
28
|
+
parser.add_argument("--keep_alive", default="false")
|
|
29
|
+
parser.add_argument("--cleanup", default="true")
|
|
30
|
+
parser.add_argument("--env", default="")
|
|
31
|
+
parser.add_argument("--json", default="false")
|
|
32
|
+
args = parser.parse_args()
|
|
33
|
+
spec = RunSpec(
|
|
34
|
+
template_id=args.template,
|
|
35
|
+
engine=args.engine,
|
|
36
|
+
task=args.task,
|
|
37
|
+
command=args.command,
|
|
38
|
+
service=args.service,
|
|
39
|
+
detach=parse_bool(args.detach),
|
|
40
|
+
timeout_seconds=args.timeout,
|
|
41
|
+
keep_alive=parse_bool(args.keep_alive),
|
|
42
|
+
cleanup=parse_bool(args.cleanup),
|
|
43
|
+
env=parse_env(args.env),
|
|
44
|
+
)
|
|
45
|
+
state = service().run(spec)
|
|
46
|
+
if parse_bool(args.json):
|
|
47
|
+
print_json(state_payload(state))
|
|
48
|
+
return
|
|
49
|
+
print_state(state)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
if __name__ == "__main__":
|
|
53
|
+
main()
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Capability common.env-status — consulta estado de ejecuciones."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
7
|
+
_log = get_logger()
|
|
8
|
+
|
|
9
|
+
from higpertext.capabilities.common.scripts._env_cli import (
|
|
10
|
+
parse_bool,
|
|
11
|
+
print_json,
|
|
12
|
+
print_state,
|
|
13
|
+
service,
|
|
14
|
+
state_payload,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main() -> None:
|
|
19
|
+
parser = argparse.ArgumentParser(description="Consulta estado de env runs")
|
|
20
|
+
parser.add_argument("--run_id", default="")
|
|
21
|
+
parser.add_argument("--json", default="false")
|
|
22
|
+
args = parser.parse_args()
|
|
23
|
+
result = service().status(args.run_id or None)
|
|
24
|
+
if parse_bool(args.json):
|
|
25
|
+
payload = state_payload(result) if args.run_id else [state_payload(item) for item in result]
|
|
26
|
+
print_json(payload)
|
|
27
|
+
return
|
|
28
|
+
if args.run_id:
|
|
29
|
+
print_state(result)
|
|
30
|
+
return
|
|
31
|
+
_log.info("╔─ HIGPERTEXT · Env Runs ────────────────────────────────────")
|
|
32
|
+
for state in result:
|
|
33
|
+
_log.info(f"│ {state.run_id} · {state.template_id} · {state.status} · {state.engine}")
|
|
34
|
+
_log.info("╚────────────────────────────────────────────────────────────")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if __name__ == "__main__":
|
|
38
|
+
main()
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Capability common.env-stop — detiene un entorno."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
|
|
7
|
+
from higpertext.capabilities.common.scripts._env_cli import (
|
|
8
|
+
parse_bool,
|
|
9
|
+
print_json,
|
|
10
|
+
print_state,
|
|
11
|
+
service,
|
|
12
|
+
state_payload,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main() -> None:
|
|
17
|
+
parser = argparse.ArgumentParser(description="Detiene entorno local")
|
|
18
|
+
parser.add_argument("--run_id", required=True)
|
|
19
|
+
parser.add_argument("--volumes", default="false")
|
|
20
|
+
parser.add_argument("--json", default="false")
|
|
21
|
+
args = parser.parse_args()
|
|
22
|
+
state = service().stop(args.run_id, parse_bool(args.volumes))
|
|
23
|
+
if parse_bool(args.json):
|
|
24
|
+
print_json(state_payload(state))
|
|
25
|
+
return
|
|
26
|
+
print_state(state)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
if __name__ == "__main__":
|
|
30
|
+
main()
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Capability common.env-template — valida o muestra templates."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
8
|
+
_log = get_logger()
|
|
9
|
+
|
|
10
|
+
from higpertext.capabilities.common.scripts._env_cli import (
|
|
11
|
+
parse_bool,
|
|
12
|
+
print_json,
|
|
13
|
+
project_root,
|
|
14
|
+
service,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main() -> None:
|
|
19
|
+
parser = argparse.ArgumentParser(description="Gestiona templates de entorno")
|
|
20
|
+
parser.add_argument("--action", required=True, choices=["validate", "show", "create"])
|
|
21
|
+
parser.add_argument("--template", required=True)
|
|
22
|
+
parser.add_argument("--json", default="false")
|
|
23
|
+
args = parser.parse_args()
|
|
24
|
+
if args.action == "create":
|
|
25
|
+
target = project_root() / WORKSPACE_DIR_NAME / "env" / "templates" / f"{args.template}.yaml"
|
|
26
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
27
|
+
if not target.exists():
|
|
28
|
+
target.write_text(_starter_template(args.template), encoding="utf-8")
|
|
29
|
+
_log.ok(f"[SUCCESS] Template disponible en: {target}")
|
|
30
|
+
return
|
|
31
|
+
template = service().validate_template(args.template)
|
|
32
|
+
payload = {
|
|
33
|
+
"id": template.id,
|
|
34
|
+
"description": template.description,
|
|
35
|
+
"source": str(template.source or ""),
|
|
36
|
+
"services": list(template.services),
|
|
37
|
+
}
|
|
38
|
+
if parse_bool(args.json):
|
|
39
|
+
print_json(payload)
|
|
40
|
+
return
|
|
41
|
+
if args.action == "show":
|
|
42
|
+
print_json(payload)
|
|
43
|
+
else:
|
|
44
|
+
_log.ok(f"Template válido: {template.id}")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _starter_template(template_id: str) -> str:
|
|
48
|
+
return f"""id: {template_id}
|
|
49
|
+
description: Custom local environment
|
|
50
|
+
services:
|
|
51
|
+
app:
|
|
52
|
+
image: alpine:3.20
|
|
53
|
+
working_dir: /workspace
|
|
54
|
+
volumes:
|
|
55
|
+
- .:/workspace
|
|
56
|
+
command: sleep infinity
|
|
57
|
+
tasks:
|
|
58
|
+
test:
|
|
59
|
+
service: app
|
|
60
|
+
command: echo 'custom task'
|
|
61
|
+
defaults:
|
|
62
|
+
service: app
|
|
63
|
+
task: test
|
|
64
|
+
timeout_seconds: 300
|
|
65
|
+
cleanup: true
|
|
66
|
+
security:
|
|
67
|
+
network: isolated
|
|
68
|
+
privileged: false
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == "__main__":
|
|
73
|
+
main()
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""common.error-context-locator — localiza contexto mínimo desde errores/trazas."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
import sys
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
13
|
+
_log = get_logger()
|
|
14
|
+
|
|
15
|
+
_PY_TRACE = re.compile(r'File "(?P<file>[^"]+)", line (?P<line>\d+)')
|
|
16
|
+
_GENERIC = re.compile(
|
|
17
|
+
r"(?P<file>[\w./\\-]+\.(?:py|js|ts|tsx|jsx|json|yaml|yml|toml|md))[:(](?P<line>\d+)"
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True)
|
|
22
|
+
class ErrorLocation:
|
|
23
|
+
file: str
|
|
24
|
+
line: int
|
|
25
|
+
message: str = ""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _read_error(args: argparse.Namespace) -> str:
|
|
29
|
+
if args.error_file:
|
|
30
|
+
return Path(args.error_file).read_text(encoding="utf-8", errors="ignore")
|
|
31
|
+
return args.error or sys.stdin.read()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def extract_locations(text: str, include_tests: bool = True) -> list[ErrorLocation]:
|
|
35
|
+
"""Extrae ubicaciones file:line de trazas comunes."""
|
|
36
|
+
results: list[ErrorLocation] = []
|
|
37
|
+
for pattern in (_PY_TRACE, _GENERIC):
|
|
38
|
+
for match in pattern.finditer(text):
|
|
39
|
+
file = match.group("file").replace("\\", "/")
|
|
40
|
+
if not include_tests and _is_test_file(file):
|
|
41
|
+
continue
|
|
42
|
+
line = int(match.group("line"))
|
|
43
|
+
message = _nearby_error_line(text, match.start())
|
|
44
|
+
item = ErrorLocation(file=file, line=line, message=message)
|
|
45
|
+
if item not in results:
|
|
46
|
+
results.append(item)
|
|
47
|
+
return results
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _is_test_file(file: str) -> bool:
|
|
51
|
+
parts = set(Path(file).parts)
|
|
52
|
+
return bool(parts & {"tests", "test", "__tests__"}) or Path(file).name.startswith("test_")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _nearby_error_line(text: str, index: int) -> str:
|
|
56
|
+
prefix = text[:index].splitlines()[-3:]
|
|
57
|
+
suffix = text[index:].splitlines()[:3]
|
|
58
|
+
for line in reversed(prefix + suffix):
|
|
59
|
+
stripped = line.strip()
|
|
60
|
+
if stripped and any(
|
|
61
|
+
token in stripped.lower() for token in ("error", "exception", "failed", "assert")
|
|
62
|
+
):
|
|
63
|
+
return stripped[:240]
|
|
64
|
+
return ""
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _context_for(root: Path, location: ErrorLocation, max_context: int) -> str:
|
|
68
|
+
path = Path(location.file)
|
|
69
|
+
if not path.is_absolute():
|
|
70
|
+
path = root / path
|
|
71
|
+
if not path.exists() or not path.is_file():
|
|
72
|
+
return " [archivo no encontrado]"
|
|
73
|
+
lines = path.read_text(encoding="utf-8", errors="ignore").splitlines()
|
|
74
|
+
start = max(1, location.line - max_context)
|
|
75
|
+
end = min(len(lines), location.line + max_context)
|
|
76
|
+
output = []
|
|
77
|
+
for lineno in range(start, end + 1):
|
|
78
|
+
marker = ">>>" if lineno == location.line else " "
|
|
79
|
+
output.append(f" {marker} L{lineno:>4}: {lines[lineno - 1][:220]}")
|
|
80
|
+
return "\n".join(output)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def build_report(text: str, root: Path, max_context: int, include_tests: bool) -> str:
|
|
84
|
+
locations = extract_locations(text, include_tests)
|
|
85
|
+
if not locations:
|
|
86
|
+
return "[NOT FOUND] No se detectaron ubicaciones file:line en el error."
|
|
87
|
+
lines = ["╔─ HIGPERTEXT · Error Context Locator ───────────────────────"]
|
|
88
|
+
lines.append(f"│ Ubicaciones detectadas: {len(locations)}")
|
|
89
|
+
lines.append("╠────────────────────────────────────────────────────────────")
|
|
90
|
+
for loc in locations[:20]:
|
|
91
|
+
lines.append(f"│ {loc.file}:{loc.line}")
|
|
92
|
+
if loc.message:
|
|
93
|
+
lines.append(f"│ Error: {loc.message}")
|
|
94
|
+
lines.append("│ Contexto:")
|
|
95
|
+
lines.append(_context_for(root, loc, max_context))
|
|
96
|
+
lines.append("│ Sugerencia:")
|
|
97
|
+
lines.append(
|
|
98
|
+
f"│ htx task common.smart-read --path {loc.file} --around_line {loc.line} --limit {max_context}" # noqa: E501
|
|
99
|
+
)
|
|
100
|
+
lines.append("╚────────────────────────────────────────────────────────────")
|
|
101
|
+
return "\n".join(lines)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _json_report(text: str, root: Path, max_context: int, include_tests: bool) -> dict:
|
|
105
|
+
locations = extract_locations(text, include_tests)
|
|
106
|
+
return {
|
|
107
|
+
"locations": [loc.__dict__ for loc in locations],
|
|
108
|
+
"suggestions": [
|
|
109
|
+
f"htx task common.smart-read --path {loc.file} --around_line {loc.line} --limit {max_context}" # noqa: E501
|
|
110
|
+
for loc in locations
|
|
111
|
+
],
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def main() -> None:
|
|
116
|
+
parser = argparse.ArgumentParser(description="Localiza contexto mínimo desde trazas de error")
|
|
117
|
+
parser.add_argument("--error", default="")
|
|
118
|
+
parser.add_argument("--error_file", default="")
|
|
119
|
+
parser.add_argument("--max_context", type=int, default=5)
|
|
120
|
+
parser.add_argument("--include_tests", default="true")
|
|
121
|
+
parser.add_argument("--json", default="false")
|
|
122
|
+
args = parser.parse_args()
|
|
123
|
+
text = _read_error(args)
|
|
124
|
+
include_tests = args.include_tests.lower() in {"true", "1", "yes"}
|
|
125
|
+
if args.json.lower() in {"true", "1", "yes"}:
|
|
126
|
+
_log.info(
|
|
127
|
+
json.dumps(
|
|
128
|
+
_json_report(text, Path.cwd(), args.max_context, include_tests),
|
|
129
|
+
ensure_ascii=False,
|
|
130
|
+
indent=2,
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
return
|
|
134
|
+
_log.info(build_report(text, Path.cwd(), args.max_context, include_tests))
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
if __name__ == "__main__":
|
|
138
|
+
main()
|