context-map-ai 2.2.0__tar.gz → 2.2.1__tar.gz
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.
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.github/copilot-instructions.md +1 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/CHANGELOG.md +13 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/PKG-INFO +2 -2
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/README.md +1 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/README_EN.md +1 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_ast_summary.py +0 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_cyclomatic.py +0 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_doctor.py +5 -6
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_domain_extractor.py +1 -3
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_hardware.py +1 -2
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_hooks.py +0 -1
- context_map_ai-2.2.1/context_map/__tests__/test_mcp_server_seguridad.py +31 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_ollama.py +0 -1
- context_map_ai-2.2.1/context_map/__tests__/test_pack_unpack.py +135 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_scan_cache.py +1 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_security_scanner.py +1 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_similarity.py +1 -2
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_tokenization.py +0 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_wrap.py +0 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/cli/parser.py +9 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/doctor_cmd.py +3 -6
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/enrich.py +4 -6
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/export.py +5 -6
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/hook.py +7 -3
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/refresh.py +1 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/update.py +101 -15
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/watch.py +2 -2
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/__init__.py +0 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/generators/generadores.py +16 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/tokenization.py +2 -5
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/analysis/checker.py +20 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/analysis/reporting.py +1 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/analysis/signals.py +0 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/analyzers/ast_audit.py +21 -18
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/analyzers/ast_summary.py +7 -8
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/analyzers/cyclomatic.py +3 -4
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/ecosystem/hooks.py +3 -3
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/health/doctor.py +2 -4
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/health/hardware.py +2 -3
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/normalization/domain_extractor.py +2 -3
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/normalization/similarity.py +6 -5
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/reglas/reglas.py +1 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/scanning/cache.py +5 -5
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/scanning/security.py +4 -5
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/storage/packer.py +70 -29
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/synchronization/watcher.py +2 -2
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/infrastructure/integrations/ollama.py +6 -6
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/infrastructure/mcp_server.py +85 -16
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/infrastructure/version_check.py +11 -4
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/briefs/brief.py +0 -2
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/briefs/extractors.py +1 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/briefs/sections.py +1 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/pyproject.toml +1 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/uv.lock +3 -3
- context_map_ai-2.2.0/context_map/__tests__/test_pack_unpack.py +0 -60
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.github/workflows/ci.yml +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.github/workflows/docs.yml +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.github/workflows/publish.yml +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.gitignore +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.hermes/config.yaml +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.hermes/shields/pre-commit.md +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.hermes/triggers/post-commit.md +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.hermes/workflows/dev-loop.md +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/.pre-commit-hooks.yaml +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/AGENTS.md +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/CODE_OF_CONDUCT.md +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/CONTRIBUTING.md +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/LICENSE +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/Makefile +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/action.yml +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/conftest.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/smoke.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_ast_audit.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_checker_frescura.py +1 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_cli.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_conexiones.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_diario_consolidado.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_ecosistema.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_enterprise_features.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_export.py +1 -1
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_hermes_clasificacion.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_hook_memoria_viva.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_ingest.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_mermaid.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_metrica_memoria_viva.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_parsing.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_personal.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_refresh_temporales.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_reglas_catalogo.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_scanner.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_standardize.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_topologia_arbol.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_vault_consolidation.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_watcher.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/cli/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/cli/cli.py +3 -3
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/__init__.py +2 -2
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/_helpers.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/adapt.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/auto.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/build.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/importers.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/ingest.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/pack.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/personal.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/scan.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/sync.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/tools.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/wrap.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/cli.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/generators/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/generators/narrative_templates.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/logging_setup.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/models/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/models/config.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/models/models.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/normalization/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/normalization/cleaning.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/normalization/inference.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/normalization/mappings.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/normalization/standardize.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/parsing/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/parsing/cargadores.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/parsing/clasificacion.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/parsing/dedup.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/parsing/grafo.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/personal/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/personal/bd.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/storage/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/storage/config_loader.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/core/storage/store.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/analysis/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/analysis/complexity.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/analysis/models.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/ecosystem/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/ecosystem/adaptador.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/ecosystem/detector.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/ecosystem/rules_templates.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/health/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/ingestion/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/ingestion/ingest.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/reporting/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/reporting/reporter.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/scanning/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/scanning/scanner.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/synchronization/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/synchronization/relaciones.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/domain/synchronization/sync.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/infrastructure/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/infrastructure/analyzers/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/infrastructure/analyzers/content.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/infrastructure/analyzers/structure.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/infrastructure/integrations/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/infrastructure/integrations/antigravity.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/infrastructure/integrations/chat_export.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/infrastructure/integrations/git.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/infrastructure/integrations/hermes.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/briefs/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/briefs/agents.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/briefs/skill.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/atomic.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/__init__.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/canvas.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/common.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/consolidado.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/jerarquico.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/notas_ideas.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/rutas.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/secciones_backlog.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/secciones_estructura.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/secciones_historial.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/secciones_ideas.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/secciones_proposito.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/consolidated/secciones_riesgos.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/mermaid.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/preservar.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/templates.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/presentation/vault/writer.py +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/docs/LAUNCH_KIT.md +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/docs/plans/2026-08-10-mapa-mental-conectado.md +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/docs/plans/PLAN-MEJORAS-CONTEXTO-VIVO-2026-08-14.md +0 -0
- {context_map_ai-2.2.0 → context_map_ai-2.2.1}/mkdocs.yml +0 -0
|
@@ -5,6 +5,19 @@ Todas las notas de versión y cambios destacables en este proyecto serán docume
|
|
|
5
5
|
El formato está basado en [Keep a Changelog](https://keepachangelog.com/es-ES/1.0.0/),
|
|
6
6
|
y este proyecto adhiere a [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.2.1] — 2026-08-21
|
|
9
|
+
|
|
10
|
+
### 🔧 Correcciones — Saneamiento de release
|
|
11
|
+
|
|
12
|
+
- **fix: flag `--version` real**: `ctxmap --version` ahora imprime la versión instalada (antes no existía y `update` mostraba un mensaje hardcodeado).
|
|
13
|
+
- **fix: detección de versión con el paquete renombrado**: `version_check` prioriza `context-map-ai` (nombre canónico actual) sobre el heredado `context-map`, eliminando avisos falsos de actualización.
|
|
14
|
+
- **fix: lint (ruff) 100% limpio**: corregidos 11 errores (`F811` redefinición en `brief.py`, `F841` variables sin usar, `SIM102/105/108`).
|
|
15
|
+
- **style: ruff --fix e isort** aplicados en todo el paquete (anotaciones modernas `dict`/`| None` y orden de imports).
|
|
16
|
+
|
|
17
|
+
Suite: 176/176 tests verdes · ruff limpio.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
8
21
|
## [2.2.0] — 2026-08-19
|
|
9
22
|
|
|
10
23
|
### 🗜️ Nuevo — Paquetes de Contexto Portátiles Offline, Escáner de Auditoría AST & Fallback de Modelos
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: context-map-ai
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: Mapa mental narrativo de proyectos para agentes de IA
|
|
5
5
|
Project-URL: Homepage, https://github.com/kudawasama/ContextMap
|
|
6
6
|
Project-URL: Repository, https://github.com/kudawasama/ContextMap
|
|
@@ -41,7 +41,7 @@ Description-Content-Type: text/markdown
|
|
|
41
41
|
|
|
42
42
|
*Captura el alma de tu proyecto, establece gobernanza automática y mantiene vivo el contexto para cualquier Agente de IA (`Antigravity`, `Cursor`, `Claude`, `Hermes`, `Copilot`, `Windsurf`, `Gemini`).*
|
|
43
43
|
|
|
44
|
-
[](https://github.com/kudawasama/ContextMap)
|
|
45
45
|
[](https://pypi.org/project/context-map-ai/)
|
|
46
46
|
[](https://www.python.org/downloads/)
|
|
47
47
|
[](LICENSE)
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
*Captura el alma de tu proyecto, establece gobernanza automática y mantiene vivo el contexto para cualquier Agente de IA (`Antigravity`, `Cursor`, `Claude`, `Hermes`, `Copilot`, `Windsurf`, `Gemini`).*
|
|
11
11
|
|
|
12
|
-
[](https://github.com/kudawasama/ContextMap)
|
|
13
13
|
[](https://pypi.org/project/context-map-ai/)
|
|
14
14
|
[](https://www.python.org/downloads/)
|
|
15
15
|
[](LICENSE)
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
*Capture the soul of your project, establish automated governance, and keep living context available for any AI Agent (`Antigravity`, `Cursor`, `Claude Code`, `Hermes`, `Copilot`, `Windsurf`, `Gemini`).*
|
|
11
11
|
|
|
12
|
-
[](https://github.com/kudawasama/ContextMap)
|
|
13
13
|
[](https://pypi.org/project/context-map-ai/)
|
|
14
14
|
[](https://www.python.org/downloads/)
|
|
15
15
|
[](LICENSE)
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
from context_map.domain.health.doctor import diagnosticar_salud, reparar_salud
|
|
7
8
|
from context_map.presentation.briefs.extractors import vault_nombre
|
|
8
9
|
|
|
9
10
|
|
|
@@ -13,7 +14,7 @@ def test_doctor_diagnosticar_salud(tmp_path, monkeypatch):
|
|
|
13
14
|
fake_home = tmp_path / "fake_home"
|
|
14
15
|
fake_home.mkdir()
|
|
15
16
|
monkeypatch.setattr("os.path.expanduser", lambda path: str(fake_home) if "~" in path else os.path.expanduser(path))
|
|
16
|
-
|
|
17
|
+
|
|
17
18
|
report = diagnosticar_salud(str(tmp_path))
|
|
18
19
|
assert report.ok
|
|
19
20
|
assert len(report.checks) >= 4
|
|
@@ -41,8 +42,6 @@ def test_doctor_reparar_vaults_desalineados(tmp_path):
|
|
|
41
42
|
(ctx_dir / "vault-Viejo").mkdir(parents=True)
|
|
42
43
|
(ctx_dir / "vault-Viejo" / "nota.md").write_text("# Nota", encoding="utf-8")
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
report = reparar_salud(str(tmp_path))
|
|
45
|
+
# El vault esperado para tmp_path será vault-<nombre del directorio>
|
|
46
|
+
reparar_salud(str(tmp_path))
|
|
48
47
|
assert os.path.isdir(ctx_dir / "_legacy" / "vault-Viejo")
|
{context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/__tests__/test_domain_extractor.py
RENAMED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"""Pruebas unitarias para el módulo context_map.domain.normalization.domain_extractor."""
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from context_map.domain.normalization.domain_extractor import DomainConceptExtractor, extraer_conceptos_proyecto
|
|
3
|
+
from context_map.domain.normalization.domain_extractor import DomainConceptExtractor
|
|
6
4
|
|
|
7
5
|
|
|
8
6
|
def test_domain_concept_extractor() -> None:
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""Pruebas unitarias para el módulo context_map.domain.health.hardware."""
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
from context_map.domain.health.hardware import evaluar_hardware_pc, EspecificacionesHardware
|
|
3
|
+
from context_map.domain.health.hardware import EspecificacionesHardware, evaluar_hardware_pc
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
def test_evaluar_hardware_pc() -> None:
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Tests de seguridad del servidor MCP: confirmación destructiva y validación de rutas."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from context_map.infrastructure import mcp_server
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_mcp_build_clean_sin_confirmacion_es_rechazado():
|
|
9
|
+
"""Verifica que build(clean=True) exige confirm=True."""
|
|
10
|
+
res = mcp_server.build(target=".", clean=True)
|
|
11
|
+
assert "rechazada por seguridad" in res
|
|
12
|
+
assert "confirm=True" in res
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_mcp_doctor_fix_sin_confirmacion_es_rechazado():
|
|
16
|
+
"""Verifica que doctor(fix=True) exige confirm=True."""
|
|
17
|
+
res = mcp_server.doctor(target=".", fix=True)
|
|
18
|
+
assert "rechazada por seguridad" in res
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_mcp_install_hooks_sin_confirmacion_es_rechazado():
|
|
22
|
+
"""Verifica que install_hooks exige confirm=True."""
|
|
23
|
+
res = mcp_server.install_hooks(target=".", force=True)
|
|
24
|
+
assert "rechazada por seguridad" in res
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_mcp_target_invalido_devuelve_error():
|
|
28
|
+
"""Verifica que un target inexistente no se procesa."""
|
|
29
|
+
res = mcp_server.check(target="/ruta/inexistente/xyz-123")
|
|
30
|
+
assert "ERROR" in res
|
|
31
|
+
assert "no es un directorio" in res
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Tests unitarios para el empaquetado y desempaquetado de contexto (.ctxpack)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import io
|
|
6
|
+
import os
|
|
7
|
+
import tarfile
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
from context_map.domain.storage.packer import (
|
|
12
|
+
_sha256_archivo,
|
|
13
|
+
crear_paquete_contexto,
|
|
14
|
+
desempaquetar_contexto,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_pack_y_unpack_flujo_completo(tmp_path):
|
|
19
|
+
"""Verifica la creación y extracción completa de un archivo .ctxpack."""
|
|
20
|
+
# 1. Crear estructura simulada .context-map/
|
|
21
|
+
src_dir = tmp_path / "proyecto_origen"
|
|
22
|
+
ctx_dir = src_dir / ".context-map"
|
|
23
|
+
state_dir = ctx_dir / "state"
|
|
24
|
+
state_dir.mkdir(parents=True)
|
|
25
|
+
|
|
26
|
+
graph_file = state_dir / "graph.jsonl"
|
|
27
|
+
graph_file.write_text(
|
|
28
|
+
'{"id": "idea_1", "type": "IDEA", "title": "Idea 1"}\n'
|
|
29
|
+
'{"id": "base_1", "type": "BASE", "title": "Base 1"}\n',
|
|
30
|
+
encoding="utf-8",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
brief_file = ctx_dir / "CONTEXT.md"
|
|
34
|
+
brief_file.write_text("# Brief de Contexto", encoding="utf-8")
|
|
35
|
+
|
|
36
|
+
agents_file = src_dir / "AGENTS.md"
|
|
37
|
+
agents_file.write_text("# Reglas Agénticas", encoding="utf-8")
|
|
38
|
+
|
|
39
|
+
# 2. Empaquetar
|
|
40
|
+
out_file = tmp_path / "backup.ctxpack"
|
|
41
|
+
ruta_gen, size, manifest = crear_paquete_contexto(
|
|
42
|
+
target_dir=str(src_dir),
|
|
43
|
+
output_path=str(out_file),
|
|
44
|
+
project_name="ProyectoPrueba",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
assert os.path.isfile(ruta_gen)
|
|
48
|
+
assert size > 0
|
|
49
|
+
assert manifest["project"] == "ProyectoPrueba"
|
|
50
|
+
assert manifest["node_count"] == 2
|
|
51
|
+
|
|
52
|
+
# 3. Desempaquetar en directorio destino
|
|
53
|
+
dst_dir = tmp_path / "proyecto_destino"
|
|
54
|
+
res_manifest = desempaquetar_contexto(
|
|
55
|
+
archive_path=str(out_file),
|
|
56
|
+
target_dir=str(dst_dir),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
assert res_manifest["project"] == "ProyectoPrueba"
|
|
60
|
+
assert (dst_dir / ".context-map" / "state" / "graph.jsonl").exists()
|
|
61
|
+
assert (dst_dir / ".context-map" / "CONTEXT.md").exists()
|
|
62
|
+
assert (dst_dir / "AGENTS.md").exists()
|
|
63
|
+
|
|
64
|
+
content = (dst_dir / ".context-map" / "state" / "graph.jsonl").read_text(encoding="utf-8")
|
|
65
|
+
assert "idea_1" in content
|
|
66
|
+
assert "base_1" in content
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_manifest_incluye_checksums_sha256(tmp_path):
|
|
70
|
+
"""Verifica que el manifiesto registra un checksum SHA-256 por archivo."""
|
|
71
|
+
src_dir = tmp_path / "origen"
|
|
72
|
+
state_dir = src_dir / ".context-map" / "state"
|
|
73
|
+
state_dir.mkdir(parents=True)
|
|
74
|
+
(state_dir / "graph.jsonl").write_text("hola\n", encoding="utf-8")
|
|
75
|
+
|
|
76
|
+
out_file = tmp_path / "backup.ctxpack"
|
|
77
|
+
_, _, manifest = crear_paquete_contexto(str(src_dir), str(out_file), project_name="Checksums")
|
|
78
|
+
|
|
79
|
+
ruta_rel = os.path.join(".context-map", "state", "graph.jsonl")
|
|
80
|
+
assert ruta_rel in manifest["files"]
|
|
81
|
+
assert manifest["files"][ruta_rel] == _sha256_archivo(str(state_dir / "graph.jsonl"))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_unpack_detecta_integridad_comprometida(tmp_path):
|
|
85
|
+
"""Verifica que un paquete con contenido alterado se rechaza por checksum."""
|
|
86
|
+
src_dir = tmp_path / "origen"
|
|
87
|
+
state_dir = src_dir / ".context-map" / "state"
|
|
88
|
+
state_dir.mkdir(parents=True)
|
|
89
|
+
(state_dir / "graph.jsonl").write_text('{"id": "a", "type": "IDEA"}\n', encoding="utf-8")
|
|
90
|
+
|
|
91
|
+
out_file = tmp_path / "backup.ctxpack"
|
|
92
|
+
crear_paquete_contexto(str(src_dir), str(out_file), project_name="Integridad")
|
|
93
|
+
|
|
94
|
+
# Reescribir el tar alterando graph.jsonl sin actualizar el manifiesto
|
|
95
|
+
tampered = tmp_path / "tampered.ctxpack"
|
|
96
|
+
with tarfile.open(str(out_file), "r:gz") as tar, tarfile.open(str(tampered), "w:gz") as out:
|
|
97
|
+
for m in tar.getmembers():
|
|
98
|
+
f = tar.extractfile(m)
|
|
99
|
+
contenido = f.read() if f else b""
|
|
100
|
+
if m.name == ".context-map/state/graph.jsonl":
|
|
101
|
+
contenido = b'{"id": "ALTERADO_TAMPERED"}\n'
|
|
102
|
+
ti = tarfile.TarInfo(m.name)
|
|
103
|
+
ti.size = len(contenido)
|
|
104
|
+
ti.mode = m.mode
|
|
105
|
+
out.addfile(ti, io.BytesIO(contenido))
|
|
106
|
+
|
|
107
|
+
with pytest.raises(ValueError, match="Integridad"):
|
|
108
|
+
desempaquetar_contexto(str(tampered), str(tmp_path / "destino"))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _crear_tar_con_symlink(path: str) -> None:
|
|
112
|
+
"""Crea un .ctxpack malicioso con un symlink apuntando fuera del destino."""
|
|
113
|
+
with tarfile.open(path, "w:gz") as tar:
|
|
114
|
+
data = b"contenido"
|
|
115
|
+
ti = tarfile.TarInfo(".context-map/state/graph.jsonl")
|
|
116
|
+
ti.size = len(data)
|
|
117
|
+
tar.addfile(ti, io.BytesIO(data))
|
|
118
|
+
|
|
119
|
+
# Symlink malicioso que apunta fuera del directorio destino
|
|
120
|
+
sl = tarfile.TarInfo("escape")
|
|
121
|
+
sl.type = tarfile.SYMTYPE
|
|
122
|
+
sl.linkname = "/tmp/ctxmap_escape_target"
|
|
123
|
+
tar.addfile(sl)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def test_unpack_rechaza_symlinks(tmp_path):
|
|
127
|
+
"""Verifica que un .ctxpack con symlinks no los extrae (hardening)."""
|
|
128
|
+
archivo = tmp_path / "malicioso.ctxpack"
|
|
129
|
+
_crear_tar_con_symlink(str(archivo))
|
|
130
|
+
|
|
131
|
+
destino = tmp_path / "destino"
|
|
132
|
+
desempaquetar_contexto(str(archivo), str(destino))
|
|
133
|
+
|
|
134
|
+
assert (destino / ".context-map" / "state" / "graph.jsonl").exists()
|
|
135
|
+
assert not (destino / "escape").exists() # el symlink no se extrae
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"""Pruebas unitarias para el módulo context_map.domain.normalization.similarity."""
|
|
2
2
|
|
|
3
|
-
import pytest
|
|
4
3
|
from context_map.domain.normalization.similarity import (
|
|
4
|
+
deduplicar_elementos_similares,
|
|
5
5
|
distancia_levenshtein,
|
|
6
6
|
similitud_jaccard_ngramas,
|
|
7
7
|
son_textos_similares,
|
|
8
|
-
deduplicar_elementos_similares,
|
|
9
8
|
)
|
|
10
9
|
|
|
11
10
|
|
|
@@ -8,6 +8,8 @@ from __future__ import annotations
|
|
|
8
8
|
|
|
9
9
|
import argparse
|
|
10
10
|
|
|
11
|
+
from context_map.infrastructure.version_check import version_local
|
|
12
|
+
|
|
11
13
|
|
|
12
14
|
def create_parser() -> argparse.ArgumentParser:
|
|
13
15
|
"""Construye y configura el parser principal con sus subcomandos.
|
|
@@ -20,6 +22,12 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
20
22
|
description="Mapa mental narrativo de proyectos para agentes de IA",
|
|
21
23
|
)
|
|
22
24
|
p.add_argument("-v", "--verbose", action="store_true", help="Logs detallados (nivel DEBUG)")
|
|
25
|
+
p.add_argument(
|
|
26
|
+
"--version",
|
|
27
|
+
action="version",
|
|
28
|
+
version=f"ContextMap v{version_local()}",
|
|
29
|
+
help="Muestra la versión instalada y sale",
|
|
30
|
+
)
|
|
23
31
|
sub = p.add_subparsers(dest="cmd", help="Comandos disponibles")
|
|
24
32
|
|
|
25
33
|
s_auto = sub.add_parser("auto", help="Automatización completa en 1 paso (scan + git + build)")
|
|
@@ -136,7 +144,7 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
136
144
|
s_antigravity.add_argument("--limit", type=int, default=5, help="Máximo de conversaciones")
|
|
137
145
|
|
|
138
146
|
sub.add_parser("update", help="Actualiza ContextMap a la última versión")
|
|
139
|
-
|
|
147
|
+
|
|
140
148
|
s_doctor = sub.add_parser("doctor", help="Diagnóstico y auto-reparación (Self-Healing) del proyecto")
|
|
141
149
|
s_doctor.add_argument("target", nargs="?", default=".", help="Ruta del proyecto a diagnosticar")
|
|
142
150
|
s_doctor.add_argument("--fix", action="store_true", help="Auto-reparar anomalías e inconsistencias encontradas")
|
{context_map_ai-2.2.0 → context_map_ai-2.2.1}/context_map/application/commands/doctor_cmd.py
RENAMED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
from context_map.domain.health.doctor import diagnosticar_salud, reparar_salud
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def cmd_doctor(args:
|
|
11
|
+
def cmd_doctor(args: dict[str, Any]) -> None:
|
|
12
12
|
"""Manejador del comando CLI `ctxmap doctor`.
|
|
13
13
|
|
|
14
14
|
Args:
|
|
@@ -18,10 +18,7 @@ def cmd_doctor(args: Dict[str, Any]) -> None:
|
|
|
18
18
|
fix = bool(args.get("fix", False))
|
|
19
19
|
as_json = bool(args.get("json", False))
|
|
20
20
|
|
|
21
|
-
if fix
|
|
22
|
-
report = reparar_salud(target_dir)
|
|
23
|
-
else:
|
|
24
|
-
report = diagnosticar_salud(target_dir)
|
|
21
|
+
report = reparar_salud(target_dir) if fix else diagnosticar_salud(target_dir)
|
|
25
22
|
|
|
26
23
|
if as_json:
|
|
27
24
|
data = {
|
|
@@ -4,13 +4,13 @@ Analiza archivos Python mediante AST y genera docstrings formales en Español T
|
|
|
4
4
|
(Google Style) utilizando Ollama local si está disponible o inferencia AST estática.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
import ast
|
|
8
7
|
import argparse
|
|
8
|
+
import ast
|
|
9
9
|
from pathlib import Path
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
from context_map.domain.analyzers.ast_summary import ASTSummaryExtractor
|
|
11
12
|
from context_map.domain.health.hardware import evaluar_hardware_pc
|
|
12
13
|
from context_map.infrastructure.integrations.ollama import OllamaLocalClient
|
|
13
|
-
from context_map.domain.analyzers.ast_summary import ASTSummaryExtractor
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def cmd_enrich(args: argparse.Namespace) -> int:
|
|
@@ -23,7 +23,6 @@ def cmd_enrich(args: argparse.Namespace) -> int:
|
|
|
23
23
|
Código de salida 0 (éxito) o 1 (error).
|
|
24
24
|
"""
|
|
25
25
|
ruta_target = Path(args.path).resolve() if hasattr(args, "path") and args.path else Path(".").resolve()
|
|
26
|
-
dry_run = getattr(args, "dry_run", False)
|
|
27
26
|
|
|
28
27
|
print(f"[enrich] Analizando directorio: {ruta_target}")
|
|
29
28
|
|
|
@@ -32,7 +31,7 @@ def cmd_enrich(args: argparse.Namespace) -> int:
|
|
|
32
31
|
print(f"[enrich] Hardware: {hw.mensaje_diagnostico}")
|
|
33
32
|
|
|
34
33
|
# 2. Inicializar cliente Ollama si es apto
|
|
35
|
-
ollama_client:
|
|
34
|
+
ollama_client: OllamaLocalClient | None = None
|
|
36
35
|
if hw.es_apto_para_ollama:
|
|
37
36
|
client = OllamaLocalClient(model_name=getattr(args, "model", None) or hw.modelo_recomendado)
|
|
38
37
|
if client.esta_disponible():
|
|
@@ -57,7 +56,6 @@ def cmd_enrich(args: argparse.Namespace) -> int:
|
|
|
57
56
|
except Exception:
|
|
58
57
|
continue
|
|
59
58
|
|
|
60
|
-
modificado = False
|
|
61
59
|
lineas = contenido.splitlines()
|
|
62
60
|
|
|
63
61
|
for node in ast.walk(tree):
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"""Comando de exportación portable (XML/JSON/Markdown) para chats web de LLMs."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Dict, List, Optional
|
|
6
4
|
import xml.etree.ElementTree as ET
|
|
5
|
+
from pathlib import Path
|
|
7
6
|
from xml.dom import minidom
|
|
8
7
|
|
|
9
8
|
from context_map.core.models import Node
|
|
@@ -16,7 +15,7 @@ from context_map.presentation.briefs.brief import generar_brief
|
|
|
16
15
|
def exportar_contexto(
|
|
17
16
|
project_path: Path,
|
|
18
17
|
format_type: str = "xml",
|
|
19
|
-
output_file:
|
|
18
|
+
output_file: Path | None = None,
|
|
20
19
|
brief_only: bool = False,
|
|
21
20
|
model_name: str = "gpt-4o",
|
|
22
21
|
) -> Path:
|
|
@@ -42,7 +41,7 @@ def exportar_contexto(
|
|
|
42
41
|
output_file = project_path / f"contextmap_export.{ext}"
|
|
43
42
|
|
|
44
43
|
# Cargar nodos y edges del mapa
|
|
45
|
-
nodos:
|
|
44
|
+
nodos: list[Node] = []
|
|
46
45
|
edges: list = []
|
|
47
46
|
graph_file = project_path / ".context-map" / "maps" / "graph.jsonl"
|
|
48
47
|
edges_file = project_path / ".context-map" / "maps" / "edges.jsonl"
|
|
@@ -50,7 +49,7 @@ def exportar_contexto(
|
|
|
50
49
|
if graph_file.exists():
|
|
51
50
|
records = load_jsonl(str(graph_file))
|
|
52
51
|
nodos = [Node.from_dict(r) for r in records if isinstance(r, dict)]
|
|
53
|
-
|
|
52
|
+
|
|
54
53
|
if edges_file.exists():
|
|
55
54
|
edges = load_jsonl(str(edges_file))
|
|
56
55
|
|
|
@@ -87,7 +86,7 @@ def exportar_contexto(
|
|
|
87
86
|
output_file.write_text(json.dumps(data_json, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
88
87
|
|
|
89
88
|
elif fmt == "markdown":
|
|
90
|
-
parts:
|
|
89
|
+
parts: list[str] = [
|
|
91
90
|
f"# ContextMap Export: {project_path.name}",
|
|
92
91
|
f"> **Target Model:** {model_name} | **Brief Tokens:** {tokens_brief} | **Nodes:** {len(nodos)}",
|
|
93
92
|
"",
|
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Any
|
|
6
6
|
|
|
7
|
-
from context_map.domain.ecosystem.hooks import
|
|
7
|
+
from context_map.domain.ecosystem.hooks import (
|
|
8
|
+
PRE_COMMIT_SCRIPT,
|
|
9
|
+
desinstalar_git_hooks,
|
|
10
|
+
instalar_git_hooks,
|
|
11
|
+
)
|
|
8
12
|
|
|
9
13
|
|
|
10
14
|
def _script_hook() -> str:
|
|
@@ -22,7 +26,7 @@ def cmd_hook_install(args=None) -> None:
|
|
|
22
26
|
print(f"[OK] Pre-commit hook de ContextMap instalado en: {target_dir}/.git/hooks/pre-commit")
|
|
23
27
|
|
|
24
28
|
|
|
25
|
-
def cmd_hook(args:
|
|
29
|
+
def cmd_hook(args: dict[str, Any]) -> None:
|
|
26
30
|
"""Manejador del comando CLI `ctxmap hook`.
|
|
27
31
|
|
|
28
32
|
Args:
|