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,316 @@
|
|
|
1
|
+
"""Reglas de sesión para UserPromptSubmit.
|
|
2
|
+
|
|
3
|
+
Inyecta estado de sesión y contexto de skills activas en cada prompt.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
|
|
8
|
+
import json
|
|
9
|
+
import platform
|
|
10
|
+
import shutil
|
|
11
|
+
# Auto-start usa lista de argumentos sin shell.
|
|
12
|
+
import subprocess # nosec B404
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Literal
|
|
16
|
+
|
|
17
|
+
from higpertext.kernel.infrastructure.logger import get_logger
|
|
18
|
+
|
|
19
|
+
_log = get_logger()
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
from higpertext.kernel.htx_resolver import get_htx_cmd
|
|
23
|
+
except ImportError:
|
|
24
|
+
get_htx_cmd = None
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
from higpertext.kernel.domain.context_engine import reset_window_state
|
|
28
|
+
except ImportError:
|
|
29
|
+
reset_window_state = None
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
import higpertext.hooks.hook_tasks.telemetry_utils as telem
|
|
33
|
+
except ImportError:
|
|
34
|
+
telem = None
|
|
35
|
+
|
|
36
|
+
from higpertext.kernel.app_config import (
|
|
37
|
+
ENVIRONMENT_FILE as _ENVIRONMENT_JSON,
|
|
38
|
+
SESSION_FILE as _SESSION_JSON,
|
|
39
|
+
SKILL_DIRS as _SKILL_DIRS,
|
|
40
|
+
AGENT_DIRS as _AGENT_DIRS,
|
|
41
|
+
)
|
|
42
|
+
RuleSeverity = Literal["continue", "context", "block"]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class RuleResult:
|
|
47
|
+
severity: RuleSeverity
|
|
48
|
+
message: str = ""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# ── Auto-inicio de sesión ─────────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _get_htx(root: Path) -> list[str]:
|
|
55
|
+
if get_htx_cmd is not None:
|
|
56
|
+
try:
|
|
57
|
+
return get_htx_cmd(root)
|
|
58
|
+
except Exception as exc:
|
|
59
|
+
_log.warning(f"[session] No se pudo resolver htx desde config: {exc}")
|
|
60
|
+
|
|
61
|
+
venv_htx = root / ".venv" / ("Scripts" if platform.system() == "Windows" else "bin") / "htx"
|
|
62
|
+
if venv_htx.exists():
|
|
63
|
+
return [str(venv_htx)]
|
|
64
|
+
if htx := shutil.which("htx"):
|
|
65
|
+
return [htx]
|
|
66
|
+
return [str(root / ".venv" / "bin" / "python"), str(root / "htx.py")]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def auto_start_session(root: Path) -> None:
|
|
70
|
+
"""Inicia sesión automáticamente si no hay una activa."""
|
|
71
|
+
env = _read_json(root / WORKSPACE_DIR_NAME / "config" / _ENVIRONMENT_JSON)
|
|
72
|
+
profile = env.get("active_profile", "software_developer")
|
|
73
|
+
cmd = _get_htx(root) + [
|
|
74
|
+
"task",
|
|
75
|
+
"common.session-start",
|
|
76
|
+
"--action",
|
|
77
|
+
"start",
|
|
78
|
+
"--profile",
|
|
79
|
+
profile,
|
|
80
|
+
]
|
|
81
|
+
try:
|
|
82
|
+
subprocess.run(cmd, cwd=str(root), timeout=20, capture_output=True) # nosec B603
|
|
83
|
+
except (OSError, subprocess.SubprocessError) as exc:
|
|
84
|
+
_log.warning(f"[session] Auto-start omitido: {exc}")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# ── Reset de ventana de contexto por turno ──────────────────────────────────
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def reset_window_accumulator(root: Path) -> None:
|
|
91
|
+
"""Reinicia el acumulador de tokens de la ventana para el nuevo turno."""
|
|
92
|
+
if reset_window_state is not None:
|
|
93
|
+
try:
|
|
94
|
+
reset_window_state(root)
|
|
95
|
+
except Exception as exc:
|
|
96
|
+
_log.warning(f"[session] No se pudo reiniciar window accumulator: {exc}")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# ── Regla 1: Estado de sesión (session_start) ─────────────────────────────────
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def inject_session_status(root: Path) -> RuleResult:
|
|
103
|
+
session = _read_json(root / WORKSPACE_DIR_NAME / "state" / _SESSION_JSON)
|
|
104
|
+
env = _read_json(root / WORKSPACE_DIR_NAME / "config" / _ENVIRONMENT_JSON)
|
|
105
|
+
profile = env.get("active_profile", "global")
|
|
106
|
+
asst = env.get("assistant", "claude")
|
|
107
|
+
active = session.get("status") == "active"
|
|
108
|
+
sid = session.get("session_id", "—")
|
|
109
|
+
|
|
110
|
+
if active and not _already_recorded(root, sid):
|
|
111
|
+
if telem is not None:
|
|
112
|
+
telem.session_start(root, sid, profile)
|
|
113
|
+
reset_window_accumulator(root)
|
|
114
|
+
|
|
115
|
+
if not active:
|
|
116
|
+
available = _available_skills(root, profile)
|
|
117
|
+
skills_hint = f"Skills disponibles : {', '.join(available)}" if available else ""
|
|
118
|
+
lines = [
|
|
119
|
+
"╔─ HIGPERTEXT · Sin sesión activa ────────────────────────",
|
|
120
|
+
f"│ Perfil : {profile}",
|
|
121
|
+
]
|
|
122
|
+
if skills_hint:
|
|
123
|
+
lines.append(f"│ {skills_hint}")
|
|
124
|
+
lines += [
|
|
125
|
+
f"│ → htx task common.session-start --profile {profile}",
|
|
126
|
+
"╚──────────────────────────────────────────────────────",
|
|
127
|
+
]
|
|
128
|
+
return RuleResult(severity="context", message="\n".join(lines))
|
|
129
|
+
|
|
130
|
+
skills = _list_dir_names(root / _SKILL_DIRS.get(asst, ".claude/skills"))
|
|
131
|
+
subagents = _list_dir_names(root / _AGENT_DIRS.get(asst, ".claude/subagents"), "*.md")
|
|
132
|
+
lines = [
|
|
133
|
+
"╔─ HIGPERTEXT · Sesión activa ─────────────────────────────",
|
|
134
|
+
f"│ {sid} · perfil: {profile}",
|
|
135
|
+
f"│ Skills : {', '.join(skills) or '—'}",
|
|
136
|
+
f"│ Subagentes : {', '.join(subagents) or '—'}",
|
|
137
|
+
"╚───────────────────────────────────────────────────────",
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
workflows = _available_workflows(root, profile)
|
|
141
|
+
if workflows:
|
|
142
|
+
wf_lines = ["╔─ HIGPERTEXT · Workflows del perfil ──────────────────────"]
|
|
143
|
+
for wf in workflows:
|
|
144
|
+
wf_lines.append(f"│ [{wf['id']}]")
|
|
145
|
+
wf_lines.append(f"│ Cuándo : {wf.get('when', '—')}")
|
|
146
|
+
wf_lines.append(f"│ Comando: {wf.get('command', '—')}")
|
|
147
|
+
wf_lines.append("╚───────────────────────────────────────────────────────")
|
|
148
|
+
lines.append("\n".join(wf_lines))
|
|
149
|
+
|
|
150
|
+
learned = _load_learned_profile(root)
|
|
151
|
+
profile_block = _render_profile_block(learned)
|
|
152
|
+
if profile_block:
|
|
153
|
+
lines.append(profile_block)
|
|
154
|
+
|
|
155
|
+
return RuleResult(severity="context", message="\n".join(lines))
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
# ── Regla 2: Contexto de skills activas (session_context) ────────────────────
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def inject_skills_context(root: Path) -> RuleResult | None:
|
|
162
|
+
session = _read_json(root / WORKSPACE_DIR_NAME / "state" / _SESSION_JSON)
|
|
163
|
+
env = _read_json(root / WORKSPACE_DIR_NAME / "config" / _ENVIRONMENT_JSON)
|
|
164
|
+
|
|
165
|
+
if session.get("status") != "active":
|
|
166
|
+
return None
|
|
167
|
+
|
|
168
|
+
asst = env.get("assistant", "claude")
|
|
169
|
+
sid = session.get("session_id", "—")
|
|
170
|
+
skills_dir = root / _SKILL_DIRS.get(asst, ".claude/skills")
|
|
171
|
+
|
|
172
|
+
skill_entries: list[tuple[str, str]] = []
|
|
173
|
+
if skills_dir.exists():
|
|
174
|
+
for d in sorted(skills_dir.iterdir()):
|
|
175
|
+
if d.is_dir():
|
|
176
|
+
summary = _skill_summary(d)
|
|
177
|
+
skill_entries.append((d.name, summary))
|
|
178
|
+
|
|
179
|
+
if not skill_entries:
|
|
180
|
+
return None
|
|
181
|
+
|
|
182
|
+
lines = [f"╔─ HIGPERTEXT · Contexto de sesión · {sid} ─────────────"]
|
|
183
|
+
lines.append("│ Skills activas:")
|
|
184
|
+
for name, summary in skill_entries:
|
|
185
|
+
desc = f" {summary}" if summary else ""
|
|
186
|
+
lines.append(f"│ • {name}{desc}")
|
|
187
|
+
lines.append("╚───────────────────────────────────────────────────────")
|
|
188
|
+
|
|
189
|
+
return RuleResult(severity="context", message="\n".join(lines))
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
# ── Helpers ───────────────────────────────────────────────────────────────────
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _read_json(path: Path) -> dict:
|
|
196
|
+
try:
|
|
197
|
+
return json.loads(path.read_text(encoding="utf-8"))
|
|
198
|
+
except (OSError, json.JSONDecodeError):
|
|
199
|
+
return {}
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def _list_dir_names(path: Path, glob: str = "*") -> list[str]:
|
|
203
|
+
if not path.exists():
|
|
204
|
+
return []
|
|
205
|
+
if glob == "*.md":
|
|
206
|
+
return sorted(f.stem for f in path.glob(glob))
|
|
207
|
+
return sorted(d.name for d in path.iterdir() if d.is_dir())
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _available_skills(root: Path, profile: str) -> list[str]:
|
|
211
|
+
data = _read_json(root / "src" / "config" / "profiles" / f"{profile}.json")
|
|
212
|
+
return data.get("session_skills", [])
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _available_workflows(root: Path, profile: str) -> list[dict]:
|
|
216
|
+
data = _read_json(root / "src" / "config" / "profiles" / f"{profile}.json")
|
|
217
|
+
return data.get("workflows", [])
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _already_recorded(root: Path, session_id: str) -> bool:
|
|
221
|
+
store = root / WORKSPACE_DIR_NAME / "state" / "telemetry.jsonl"
|
|
222
|
+
if not store.exists():
|
|
223
|
+
return False
|
|
224
|
+
try:
|
|
225
|
+
for line in store.read_text(encoding="utf-8").splitlines():
|
|
226
|
+
try:
|
|
227
|
+
e = json.loads(line)
|
|
228
|
+
if e.get("event") == "session_start" and e.get("session_id") == session_id:
|
|
229
|
+
return True
|
|
230
|
+
except (json.JSONDecodeError, TypeError):
|
|
231
|
+
continue
|
|
232
|
+
except OSError:
|
|
233
|
+
pass
|
|
234
|
+
return False
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _load_learned_profile(root: Path) -> dict:
|
|
238
|
+
return _read_json(root / WORKSPACE_DIR_NAME / "state" / "learned_profile.json")
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def _render_profile_block(profile: dict) -> str | None:
|
|
242
|
+
if not profile:
|
|
243
|
+
return None
|
|
244
|
+
strong = ", ".join(profile.get("strong_patterns", [])[:3]) or "—"
|
|
245
|
+
weak = ", ".join(profile.get("weak_patterns", [])[:3]) or "—"
|
|
246
|
+
adoption = profile.get("higpertext_adoption_trend", 0)
|
|
247
|
+
topics = ", ".join(profile.get("commit_topics", [])[:4]) or "—"
|
|
248
|
+
best = profile.get("best_session_pattern", "—")
|
|
249
|
+
cost = profile.get("cost_per_commit_avg", 0.0)
|
|
250
|
+
return "\n".join(
|
|
251
|
+
[
|
|
252
|
+
"╔─ HIGPERTEXT · Perfil aprendido ──────────────────────────",
|
|
253
|
+
f"│ Fortalezas : {strong}",
|
|
254
|
+
f"│ Debilidades : {weak}",
|
|
255
|
+
f"│ Adopción prom : {adoption}%",
|
|
256
|
+
f"│ Temas commits : {topics}",
|
|
257
|
+
f"│ Mejor patrón : {best}",
|
|
258
|
+
f"│ Costo/commit : ${cost:.4f} USD",
|
|
259
|
+
"╚───────────────────────────────────────────────────────",
|
|
260
|
+
]
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def _skill_summary(skill_dir: Path) -> str:
|
|
265
|
+
md = skill_dir / "SKILL.md"
|
|
266
|
+
if not md.exists():
|
|
267
|
+
return ""
|
|
268
|
+
try:
|
|
269
|
+
for line in md.read_text(encoding="utf-8").splitlines()[1:]:
|
|
270
|
+
s = line.strip()
|
|
271
|
+
if s and not s.startswith("#"):
|
|
272
|
+
return s[:90]
|
|
273
|
+
except OSError: # nosec B110
|
|
274
|
+
pass
|
|
275
|
+
return ""
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def handle_compact_command(root: Path) -> RuleResult:
|
|
279
|
+
"""Genera el reporte de compactación y avisa de resetear el chat."""
|
|
280
|
+
session = _read_json(root / WORKSPACE_DIR_NAME / "state" / _SESSION_JSON)
|
|
281
|
+
env = _read_json(root / WORKSPACE_DIR_NAME / "config" / _ENVIRONMENT_JSON)
|
|
282
|
+
sid = session.get("session_id", "—")
|
|
283
|
+
profile = env.get("active_profile", "—")
|
|
284
|
+
|
|
285
|
+
changed_files = []
|
|
286
|
+
git_path = shutil.which("git") or "git"
|
|
287
|
+
try:
|
|
288
|
+
r = subprocess.run(
|
|
289
|
+
[git_path, "status", "--porcelain"], # nosec B603 B607
|
|
290
|
+
capture_output=True,
|
|
291
|
+
text=True,
|
|
292
|
+
cwd=str(root),
|
|
293
|
+
timeout=5,
|
|
294
|
+
)
|
|
295
|
+
changed_files = [line[3:].strip() for line in r.stdout.splitlines() if line.strip()]
|
|
296
|
+
except (OSError, subprocess.SubprocessError):
|
|
297
|
+
pass
|
|
298
|
+
|
|
299
|
+
files_str = ", ".join(changed_files[:5]) or "Ninguno"
|
|
300
|
+
if len(changed_files) > 5:
|
|
301
|
+
files_str += f" y {len(changed_files) - 5} más"
|
|
302
|
+
|
|
303
|
+
msg = "\n".join(
|
|
304
|
+
[
|
|
305
|
+
"╔─ HIGPERTEXT · Checkpoint de Compactación ──────────────",
|
|
306
|
+
f"│ Sesión Activa: {sid} ({profile})",
|
|
307
|
+
f"│ Archivos Modificados: {files_str}",
|
|
308
|
+
"│",
|
|
309
|
+
"│ ⚠ ¡REQUERIDO!: Guarda/actualiza acuerdos y estado clave",
|
|
310
|
+
"│ en '.memory/context.md' (o similar) antes de continuar.",
|
|
311
|
+
"│ → Una vez guardado, escribe '/clear' o usa el botón de",
|
|
312
|
+
"│ reseteo del chat para vaciar el historial redundante.",
|
|
313
|
+
"╚───────────────────────────────────────────────────────",
|
|
314
|
+
]
|
|
315
|
+
)
|
|
316
|
+
return RuleResult(severity="context", message=msg)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""Reglas de observabilidad para tool calls (PostToolUse).
|
|
2
|
+
|
|
3
|
+
Registra telemetría de tokens y actividad. Sin efectos de bloqueo.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
|
|
8
|
+
import json
|
|
9
|
+
import os
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Literal
|
|
13
|
+
|
|
14
|
+
RuleSeverity = Literal["continue", "context", "block"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class RuleResult:
|
|
19
|
+
severity: RuleSeverity
|
|
20
|
+
message: str = ""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# ── Regla 1: Registro de telemetría de tokens ─────────────────────────────────
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def record_telemetry(payload: dict, root: Path) -> RuleResult:
|
|
27
|
+
import higpertext.hooks.hook_tasks.telemetry_utils as telem
|
|
28
|
+
|
|
29
|
+
session = _read_json(root / WORKSPACE_DIR_NAME / "state" / "session.json")
|
|
30
|
+
sid = session.get("session_id", "unknown")
|
|
31
|
+
|
|
32
|
+
tool_name = payload.get("tool_name", "unknown")
|
|
33
|
+
tool_input = payload.get("tool_input", {})
|
|
34
|
+
tool_response = payload.get("tool_response", {})
|
|
35
|
+
|
|
36
|
+
input_str = json.dumps(tool_input, ensure_ascii=False)
|
|
37
|
+
output_str = json.dumps(tool_response, ensure_ascii=False)
|
|
38
|
+
|
|
39
|
+
cmd = (
|
|
40
|
+
(tool_input.get("command") or tool_input.get("CommandLine") or "")
|
|
41
|
+
if isinstance(tool_input, dict)
|
|
42
|
+
else ""
|
|
43
|
+
)
|
|
44
|
+
is_higpertext_call = "htx.py" in cmd and "task" in cmd
|
|
45
|
+
|
|
46
|
+
telem.tool_call(
|
|
47
|
+
root,
|
|
48
|
+
session_id=sid,
|
|
49
|
+
tool_name=tool_name,
|
|
50
|
+
input_chars=len(input_str),
|
|
51
|
+
output_chars=len(output_str),
|
|
52
|
+
is_higpertext_call=is_higpertext_call,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
op_type, target, scope = _extract_activity(tool_name, tool_input, is_higpertext_call)
|
|
56
|
+
if op_type:
|
|
57
|
+
telem.activity(
|
|
58
|
+
root,
|
|
59
|
+
session_id=sid,
|
|
60
|
+
tool=tool_name,
|
|
61
|
+
op_type=op_type,
|
|
62
|
+
target=target,
|
|
63
|
+
scope=scope,
|
|
64
|
+
higpertext_related=is_higpertext_call,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
return RuleResult(severity="continue")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# ── Helpers ───────────────────────────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _rel(path_str: str) -> str:
|
|
74
|
+
try:
|
|
75
|
+
return str(Path(path_str).relative_to(os.getcwd()))
|
|
76
|
+
except ValueError:
|
|
77
|
+
return Path(path_str).name
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _extract_activity(
|
|
81
|
+
tool: str, tool_input: dict, is_higpertext_call: bool
|
|
82
|
+
) -> tuple[str, str, str]:
|
|
83
|
+
if not isinstance(tool_input, dict):
|
|
84
|
+
return "", "", ""
|
|
85
|
+
|
|
86
|
+
if tool == "Edit":
|
|
87
|
+
rel = _rel(tool_input.get("file_path", ""))
|
|
88
|
+
return "code-change", rel, str(Path(rel).parent)
|
|
89
|
+
|
|
90
|
+
if tool == "Write":
|
|
91
|
+
rel = _rel(tool_input.get("file_path", ""))
|
|
92
|
+
return "new-file", rel, str(Path(rel).parent)
|
|
93
|
+
|
|
94
|
+
if tool == "Read":
|
|
95
|
+
rel = _rel(tool_input.get("file_path", ""))
|
|
96
|
+
return "file-read", rel, str(Path(rel).parent)
|
|
97
|
+
|
|
98
|
+
if tool in ("Bash", "PowerShell"):
|
|
99
|
+
cmd = (tool_input.get("command") or tool_input.get("CommandLine") or "")[:100]
|
|
100
|
+
if is_higpertext_call:
|
|
101
|
+
parts = cmd.split()
|
|
102
|
+
try:
|
|
103
|
+
idx = parts.index("task")
|
|
104
|
+
cap = parts[idx + 1] if idx + 1 < len(parts) else cmd
|
|
105
|
+
except ValueError:
|
|
106
|
+
cap = cmd
|
|
107
|
+
return "higpertext-task", cap, "higpertext"
|
|
108
|
+
return "bash-cmd", cmd, "bash"
|
|
109
|
+
|
|
110
|
+
if tool == "Skill":
|
|
111
|
+
skill = tool_input.get("skill", tool_input.get("name", "unknown"))
|
|
112
|
+
return "skill-invoked", skill, "skill"
|
|
113
|
+
|
|
114
|
+
return "", "", ""
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _read_json(path: Path) -> dict:
|
|
118
|
+
try:
|
|
119
|
+
return json.loads(path.read_text(encoding="utf-8"))
|
|
120
|
+
except (OSError, json.JSONDecodeError):
|
|
121
|
+
return {}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Hook PostToolUse — registra cada tool use en .higpertext/audit.log."""
|
|
2
|
+
from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
import json
|
|
6
|
+
import datetime
|
|
7
|
+
from higpertext.hooks.hook_tasks.hook_utils import get_project_root
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main() -> None:
|
|
11
|
+
data = json.load(sys.stdin)
|
|
12
|
+
tool_name = data.get("tool_name", "unknown")
|
|
13
|
+
session_id = data.get("session_id", "")
|
|
14
|
+
timestamp = datetime.datetime.now(datetime.timezone.utc).isoformat()
|
|
15
|
+
|
|
16
|
+
log_dir = get_project_root() / WORKSPACE_DIR_NAME
|
|
17
|
+
log_dir.mkdir(parents=True, exist_ok=True)
|
|
18
|
+
log_file = log_dir / "audit.log"
|
|
19
|
+
|
|
20
|
+
entry = json.dumps({"ts": timestamp, "tool": tool_name, "session": session_id})
|
|
21
|
+
with log_file.open("a", encoding="utf-8") as f:
|
|
22
|
+
f.write(entry + "\n")
|
|
23
|
+
|
|
24
|
+
print(json.dumps({"continue": True}))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if __name__ == "__main__":
|
|
28
|
+
main()
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Hook PreToolUse:Bash — evalúa todas las reglas de comandos Bash en cadena."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from higpertext.hooks.hook_tasks._rules.bash_rules import (
|
|
5
|
+
RuleResult,
|
|
6
|
+
is_whitelisted,
|
|
7
|
+
check_git_commit_block,
|
|
8
|
+
check_hard_blocks,
|
|
9
|
+
check_branch_protection,
|
|
10
|
+
check_deployment_gate,
|
|
11
|
+
check_ls_redirect,
|
|
12
|
+
check_grep_redirect,
|
|
13
|
+
check_git_redirect,
|
|
14
|
+
check_knowledge_redirect,
|
|
15
|
+
check_large_file_read_redirect,
|
|
16
|
+
check_list_rules,
|
|
17
|
+
check_load_rules,
|
|
18
|
+
check_exit_guard,
|
|
19
|
+
check_higpertext_enforcer,
|
|
20
|
+
check_profile_rules,
|
|
21
|
+
)
|
|
22
|
+
import higpertext.hooks.hook_tasks.telemetry_utils as telem
|
|
23
|
+
from higpertext.hooks.hook_tasks.hook_utils import get_project_root
|
|
24
|
+
from higpertext.hooks.hook_tasks.hook_io import (
|
|
25
|
+
hook_main,
|
|
26
|
+
read_payload,
|
|
27
|
+
read_tool_command,
|
|
28
|
+
emit_continue,
|
|
29
|
+
emit_context,
|
|
30
|
+
emit_block,
|
|
31
|
+
)
|
|
32
|
+
import sys
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
|
|
35
|
+
_SRC = Path(__file__).resolve().parents[3] # src/
|
|
36
|
+
if str(_SRC) not in sys.path:
|
|
37
|
+
sys.path.insert(0, str(_SRC))
|
|
38
|
+
from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
42
|
+
|
|
43
|
+
_RULES = [
|
|
44
|
+
check_git_commit_block,
|
|
45
|
+
check_hard_blocks,
|
|
46
|
+
check_branch_protection,
|
|
47
|
+
check_deployment_gate,
|
|
48
|
+
check_ls_redirect,
|
|
49
|
+
check_grep_redirect,
|
|
50
|
+
check_git_redirect,
|
|
51
|
+
check_knowledge_redirect,
|
|
52
|
+
check_large_file_read_redirect,
|
|
53
|
+
check_list_rules,
|
|
54
|
+
check_load_rules,
|
|
55
|
+
check_exit_guard,
|
|
56
|
+
check_higpertext_enforcer,
|
|
57
|
+
check_profile_rules,
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@hook_main
|
|
62
|
+
def main() -> None:
|
|
63
|
+
payload = read_payload()
|
|
64
|
+
cmd = read_tool_command(payload)
|
|
65
|
+
|
|
66
|
+
if is_whitelisted(cmd):
|
|
67
|
+
emit_continue()
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
root = get_project_root()
|
|
71
|
+
session_data = {}
|
|
72
|
+
try:
|
|
73
|
+
import json
|
|
74
|
+
|
|
75
|
+
session_data = json.loads(
|
|
76
|
+
(root / WORKSPACE_DIR_NAME / "state" / "session.json").read_text(encoding="utf-8")
|
|
77
|
+
)
|
|
78
|
+
except Exception: # nosec B110
|
|
79
|
+
pass
|
|
80
|
+
sid = session_data.get("session_id", "unknown")
|
|
81
|
+
|
|
82
|
+
for rule_fn in _RULES:
|
|
83
|
+
result: RuleResult | None = rule_fn(cmd, root)
|
|
84
|
+
if result is None:
|
|
85
|
+
continue
|
|
86
|
+
|
|
87
|
+
if result.severity == "block":
|
|
88
|
+
telem.hook_intercept(root, sid, result.capability or "BLOCKED", cmd)
|
|
89
|
+
emit_block("PreToolUse", result.message)
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
if result.severity == "context":
|
|
93
|
+
telem.hook_intercept(root, sid, result.capability or "context", cmd)
|
|
94
|
+
emit_context("PreToolUse", result.message)
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
emit_continue()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if __name__ == "__main__":
|
|
101
|
+
main()
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Hook PreToolUse:Write|Edit — evalúa calidad de código Python antes de escribir."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from higpertext.hooks.hook_tasks._rules.quality_rules import (
|
|
5
|
+
check_code_length,
|
|
6
|
+
is_python_file,
|
|
7
|
+
)
|
|
8
|
+
from higpertext.hooks.hook_tasks.hook_utils import get_project_root
|
|
9
|
+
from higpertext.hooks.hook_tasks.hook_io import (
|
|
10
|
+
hook_main,
|
|
11
|
+
read_payload,
|
|
12
|
+
emit_continue,
|
|
13
|
+
emit_context,
|
|
14
|
+
)
|
|
15
|
+
import sys
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
_SRC = Path(__file__).resolve().parents[3] # src/
|
|
19
|
+
if str(_SRC) not in sys.path:
|
|
20
|
+
sys.path.insert(0, str(_SRC))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@hook_main
|
|
27
|
+
def main() -> None:
|
|
28
|
+
payload = read_payload()
|
|
29
|
+
tool_name = payload.get("tool_name", "")
|
|
30
|
+
tool_input = payload.get("tool_input", {})
|
|
31
|
+
|
|
32
|
+
file_path = tool_input.get("file_path", "") or tool_input.get("path", "")
|
|
33
|
+
if tool_name not in ("Write", "Edit") or not is_python_file(file_path):
|
|
34
|
+
emit_continue()
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
root = get_project_root()
|
|
38
|
+
result = check_code_length(file_path, root)
|
|
39
|
+
|
|
40
|
+
if result is None:
|
|
41
|
+
emit_continue()
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
emit_context("PreToolUse", result.message)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
if __name__ == "__main__":
|
|
48
|
+
main()
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Hook UserPromptSubmit — sugiere context-assembler ante prompts de tarea.
|
|
2
|
+
|
|
3
|
+
Entrega híbrida (parte ligera): detecta verbos de tarea e inyecta un índice
|
|
4
|
+
de pocas líneas. El agente decide invocar la capability pesada si lo necesita.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
import re
|
|
9
|
+
from higpertext.hooks.hook_tasks.hook_io import (
|
|
10
|
+
hook_main,
|
|
11
|
+
read_payload,
|
|
12
|
+
emit_continue,
|
|
13
|
+
emit_context,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# Verbos que indican una tarea de ingeniería sobre el código.
|
|
17
|
+
_TASK_VERBS = re.compile(
|
|
18
|
+
r"\b(refactoriz\w*|implement\w*|arregl\w*|corrig\w*|migr\w*|"
|
|
19
|
+
r"optimiz\w*|reestructur\w*|añad\w*|agreg\w*|crea\w+|"
|
|
20
|
+
r"refactor|implement|fix|bugfix|build|add)\b",
|
|
21
|
+
re.IGNORECASE,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
_HINT = (
|
|
25
|
+
"╔─ HIGPERTEXT · Context Pack disponible ─────────────────────\n"
|
|
26
|
+
"│ Detecté una tarea de ingeniería. Para recibir contexto\n"
|
|
27
|
+
"│ curado (símbolos relevantes bajo presupuesto de tokens):\n"
|
|
28
|
+
'│ → htx task common.context-assembler --goal "<objetivo>" --type <refactor|feature|bugfix>\n'
|
|
29
|
+
"╚───────────────────────────────────────────────────────"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@hook_main
|
|
34
|
+
def main() -> None:
|
|
35
|
+
payload = read_payload()
|
|
36
|
+
prompt = payload.get("prompt", "") or payload.get("user_prompt", "")
|
|
37
|
+
|
|
38
|
+
if not _TASK_VERBS.search(prompt):
|
|
39
|
+
emit_continue()
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
emit_context("UserPromptSubmit", _HINT)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
main()
|