typedef-data-intelligence 0.40.0__tar.gz → 0.41.0__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.
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/CHANGELOG.md +7 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/PKG-INFO +1 -1
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/pyproject.toml +1 -1
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/desktop_sync.py +33 -24
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_setup.py +69 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_sync.py +365 -4
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/.dockerignore +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/.env.example +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/.gitignore +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/.justfile_help.txt +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/Dockerfile +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/Dockerfile.dev +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/Justfile +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/README.pypi.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/config.api.yml +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/config.cli.yml +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/config.desktop.yml +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/config.ingest.unified.yml +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/config.ingest.yml +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docker-entrypoint.dev.sh +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/LINEAR_TICKETING_BACKEND.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/architecture/BUSINESS_CONCEPT_INDEX.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/architecture/CLUSTERING_ALGORITHM_DECISION.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/architecture/GENERIC_REPORT_SCHEMA.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/architecture/HYBRID_ANALYSIS_ARCHITECTURE.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/architecture/PHASE2_IR_STITCHING.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/architecture/PIPELINE_PRIMITIVES_USECASES.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/architecture/SALESFORCE_REPORT_IR.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/architecture/SEMANTIC_JOIN_RESOLUTION.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/architecture/SEMANTIC_SCHEMA_DESIGN.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/design/AGENT_DESIGN_NOTES.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/design/COLUMN_PROFILING.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/design/COLUMN_PROFILING_IMPLEMENTATION.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/design/EXTRACTION_DETECTION.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/design/PERFORMANCE_AND_QUALITY_SPECIALISTS.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/design/STREAMING_SUBAGENT_ARCHITECTURE.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/examples/memory_usage_examples.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/examples/pydantic_tool_customization_example.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/reference/AGENT_USER_GUIDE.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/reference/GETTING_STARTED.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/reference/MIGRATION_THREE_SQL.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/reference/SCOPE_LEVEL_LINEAGE_GUIDE.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/reference/SEMANTIC_DIFF_HARNESS.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/reference/SEMANTIC_DIMENSIONS_GUIDE.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docs/reference/TYPE_ENUMS.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/pytest.ini +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/scripts/create_salesforce_reports.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/scripts/data_generation/utils.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/scripts/databricks-smoke.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/scripts/delete_salesforce_reports.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/scripts/populate_salesforce_schema.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/scripts/reset_demo_git_workspace.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/scripts/reset_demo_linear.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/scripts/snowflake_server.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/scripts/surreal-engine-bench.sh +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/scripts/surreal-fts-b2-corpus.sh +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/scripts/surreal-fts-bench.sh +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/scripts/surreal-fts-quality.sh +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/snowflake-mcp-config.yaml +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/app.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/auth_context.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/concept_cards.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/controlplane_identity.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/desktop_agents.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/desktop_context.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/desktop_logs.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/desktop_quickstart.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/desktop_runtime.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/desktop_semdiff_provision.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/desktop_setup.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/desktop_wizard_sync.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/desktop_workspaces.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/desktop_worktree.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/graph_availability.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/posthog_analytics.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/semantic_runtime.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/api/serve.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/context_projects/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/context_projects/airflow_discovery.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/context_projects/dbt_plugin.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/backward_dryrun.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/clustering_metrics.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/drop_snowflake_tables.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/ephemeral_lineage_report.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/eval_clustering.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/list_ephemeral_models.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/refingerprint_cache.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/regen_semantic_goldens.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/reset_git_workspace.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/reset_linear_workspace.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/reset_project.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/run_dbt_workflow.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/seed_census.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/semantic_goldens.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/fts_bench.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/fts_cells.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/fts_corpus.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/fts_corpus_dump.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/fts_coverage.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/fts_coverage_report.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/fts_oracle.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/fts_quality.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/fts_quality_bench.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/log_parse.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/membership.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/membership_qualification.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/membership_runner.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/membership_storage.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/membership_storage_support.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/report.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/surreal_bench/runner.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/README.md +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/cli.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/db_names.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/dbt_compile.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/diff_runner.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/expected_changes.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/column_rename_downstream/fixture.yaml +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/column_rename_downstream/mutation.diff +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_coarsen/fixture.yaml +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_coarsen/mutation.diff +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_deleted_leaf_model/fixture.yaml +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_deleted_leaf_model/mutation.diff +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_fanout_compound_oli/fixture.yaml +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_fanout_compound_oli/mutation.diff +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_gold_control/fixture.yaml +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_gold_control/mutation.diff +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_v1_003_user_telemetry/fixture.yaml +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_v1_003_user_telemetry/mutation.diff +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures_loader.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/ingest.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/lifecycle.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/semantic_diff/source_prep.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/surreal/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/surreal/desktop_mcp.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/devtools/unified_graph/unified_cli.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/mcp/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/mcp/runner.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/mcp/server.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/observability/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/observability/desktop_logfire.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/observability/local_otlp_export.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/observability/local_span_export.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/templates/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/templates/typedef_config.yaml.j2 +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/typedef_cli.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/utils/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/utils/databricks.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/utils/databricks_oauth.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/utils/dbt.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/utils/dbt_profile.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/utils/env.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/utils/git.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/utils/gitignore.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/utils/logging.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/src/lineage/utils/snowflake.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_app_lifespan.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_app_logfire.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_app_retention_wiring.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_concept_cards.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_databricks_auth_wiring.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_agents_clone_backend.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_agents_runtime.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_agents_ticket_resolution.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_airflow_snapshot.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_clerk_auth.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_context_reader_cache.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_databases_delete.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_databases_edit.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_databricks_oauth.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_databricks_setup.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_delete_endpoints.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_diagnostics.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_local_clone.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_logs.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_orphan_flags.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_posthog.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_quickstart.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_repo_projects_discovery.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_runtime.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_salesforce.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_save_env_credentials.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_search.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_secondary_roles_hook.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_semdiff_provision.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_setup_clone.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_setup_env_vars.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_sync_render_profile.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_telemetry.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_workspaces.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_workspaces_adopt.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_workspaces_context_kinds.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_workspaces_delete.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_workspaces_gold_triggers.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_workspaces_integrations.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_workspaces_preview_name.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_workspaces_projects_and_repos.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_workspaces_r3_r10.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_workspaces_summary.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_workspaces_target_scope.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_workspaces_wizard.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_worktree.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_worktree_clone.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_worktree_clone_token_scope.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_worktree_gold_queue.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_worktree_kind_target.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_worktree_resolution_scope.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_graph_availability_any_sentinel.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_local_otlp_export.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_no_legacy_surface.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_surreal_graph_availability.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_target_envelope_reads.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_validate_project_collisions.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_wizard_create_project_integration_persistence.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_workspace_clone_settings.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_worktree_registry_workspaces_shape.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/backends/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/backends/lineage/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/backends/lineage/test_search_enum_coverage.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/backends/lineage/test_surreal_search.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/conftest.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/surreal_bench/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/surreal_bench/test_fts_cells.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/surreal_bench/test_fts_coverage.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/surreal_bench/test_fts_quality.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/surreal_bench/test_log_parse.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/surreal_bench/test_membership.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/surreal_bench/test_membership_runner.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/surreal_bench/test_report.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/test_databricks_prepare_benchmark.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/test_justfile_recipes.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/test_repo_skill_docs.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/test_sf_login.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/test_tdh_doctor.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/test_typedef_home_provision.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/devtools/test_worktree_reclaim.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/docs/test_desktop_posthog_event_docs.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/integration/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/integration/test_semantic_diff_harness.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/mcp/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/mcp/test_desktop_graph_inventory_surface.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/mcp/test_desktop_mcp_retry.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/mcp/test_list_projects.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/mcp/test_server.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/observability/test_no_raw_stream_filehandler.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/test_git_utils.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/test_gitignore_utils.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/test_helpers_semantic.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/test_local_clone_util.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/test_model_tier_validation.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/test_template_yaml_escaping.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/test_typedef_cli_import_budget.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/test_unified_cli_airflow.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/test_unified_cli_fast.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/test_unified_cli_semantic.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/context_projects/test_airflow_discovery.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/context_projects/test_dbt_plugin.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/devtools/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/devtools/test_semdiff_expected_changes.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/devtools/test_semdiff_harness_units.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/devtools/test_semdiff_lifecycle.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/devtools/test_semdiff_lifecycle_io.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/devtools/test_semdiff_lifecycle_provisioning.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/formula/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/utils/__init__.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/utils/test_databricks_utils.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/utils/test_dbt_docs_generate.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/utils/test_dbt_profile.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/utils/test_logging.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/utils/test_run_dbt_command.py +0 -0
- {typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/unit/utils/test_snowflake_utils.py +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.41.0](https://github.com/typedef-ai/typedef/compare/typedef-data-intelligence-v0.40.0...typedef-data-intelligence-v0.41.0) (2026-07-13)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **graph:** activate lightweight system membership (TD-3882) ([#1173](https://github.com/typedef-ai/typedef/issues/1173)) ([e91c42c](https://github.com/typedef-ai/typedef/commit/e91c42cc491b2fc8265536b8f467b61527e67071))
|
|
9
|
+
|
|
3
10
|
## [0.40.0](https://github.com/typedef-ai/typedef/compare/typedef-data-intelligence-v0.39.1...typedef-data-intelligence-v0.40.0) (2026-07-10)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: typedef-data-intelligence
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.41.0
|
|
4
4
|
Summary: Unified lineage management and AI-powered analytics platform for dbt projects
|
|
5
5
|
Project-URL: Homepage, https://typedef.ai
|
|
6
6
|
Project-URL: Repository, https://github.com/typedef-ai/data-intelligence
|
|
@@ -25,6 +25,7 @@ from typing import TYPE_CHECKING, Any
|
|
|
25
25
|
from agent.api import shutdown_event
|
|
26
26
|
from agent.controlplane_context import get_typedef_context
|
|
27
27
|
from core.backends.controlplane import LLMProxyConfig
|
|
28
|
+
from core.models.desktop import ProjectHealthInfo, ProjectsHealthResponse
|
|
28
29
|
from core.models.observability import Outcome
|
|
29
30
|
from core.observability.manifest import record_op_end, record_op_start
|
|
30
31
|
from fastapi import APIRouter, Depends, HTTPException, Request
|
|
@@ -2478,12 +2479,9 @@ def _maybe_migrate_workspace_graph(
|
|
|
2478
2479
|
return True
|
|
2479
2480
|
except RuntimeError:
|
|
2480
2481
|
raise
|
|
2481
|
-
except Exception: # noqa: BLE001
|
|
2482
|
-
log.
|
|
2483
|
-
|
|
2484
|
-
exc_info=True,
|
|
2485
|
-
)
|
|
2486
|
-
return False
|
|
2482
|
+
except Exception as exc: # noqa: BLE001
|
|
2483
|
+
log.error("graph migration probe failed; aborting sync", exc_info=True)
|
|
2484
|
+
raise RuntimeError(f"Graph migration probe failed: {exc}") from exc
|
|
2487
2485
|
|
|
2488
2486
|
|
|
2489
2487
|
def _build_one_project(
|
|
@@ -3403,8 +3401,8 @@ def _project_has_graph_data(graph_db: str, project_name: str) -> bool:
|
|
|
3403
3401
|
return False
|
|
3404
3402
|
|
|
3405
3403
|
|
|
3406
|
-
@router.get("/projects/health")
|
|
3407
|
-
async def projects_health():
|
|
3404
|
+
@router.get("/projects/health", response_model=ProjectsHealthResponse)
|
|
3405
|
+
async def projects_health() -> ProjectsHealthResponse:
|
|
3408
3406
|
"""Per-project sync health for all configured projects.
|
|
3409
3407
|
|
|
3410
3408
|
Returns sync_status and sync_error per project so the frontend
|
|
@@ -3458,12 +3456,22 @@ async def projects_health():
|
|
|
3458
3456
|
active_graph_db = gdb if (isinstance(gdb, str) and gdb) else active_ws_name
|
|
3459
3457
|
elif active_ws_name:
|
|
3460
3458
|
active_graph_db = active_ws_name
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3459
|
+
active_migration_error: str | None = None
|
|
3460
|
+
try:
|
|
3461
|
+
active_needs_migration = bool(
|
|
3462
|
+
active_ws_name and workspace_needs_graph_migration(active_ws_name)
|
|
3463
|
+
)
|
|
3464
|
+
except Exception as exc: # noqa: BLE001
|
|
3465
|
+
logger.debug(
|
|
3466
|
+
"graph marker probe failed for %r; reporting migration required",
|
|
3467
|
+
active_ws_name,
|
|
3468
|
+
exc_info=True,
|
|
3469
|
+
)
|
|
3470
|
+
active_needs_migration = True
|
|
3471
|
+
active_migration_error = str(exc)
|
|
3464
3472
|
|
|
3465
3473
|
projects = list_all_projects_raw(cfg)
|
|
3466
|
-
result: list[
|
|
3474
|
+
result: list[ProjectHealthInfo] = []
|
|
3467
3475
|
# Pool one SurrealDB connection per graph_db across the per-project
|
|
3468
3476
|
# ingest-version probes. This endpoint is polled every ~5s, so opening a
|
|
3469
3477
|
# fresh connection per project was O(projects) churn (TD-3196 review).
|
|
@@ -3520,19 +3528,20 @@ async def projects_health():
|
|
|
3520
3528
|
_active_running_sync_id(name, ws_name) if sync_status == "running" else None
|
|
3521
3529
|
)
|
|
3522
3530
|
result.append(
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3531
|
+
ProjectHealthInfo(
|
|
3532
|
+
name=name,
|
|
3533
|
+
graph_name=proj.get("graph_name"),
|
|
3534
|
+
sync_status=sync_status,
|
|
3535
|
+
sync_error=sync_error,
|
|
3536
|
+
last_synced_commit=proj.get("last_synced_commit"),
|
|
3537
|
+
needs_migration=needs_migration,
|
|
3538
|
+
migration_error=active_migration_error,
|
|
3539
|
+
ingest_version_mismatch=version_mismatch,
|
|
3540
|
+
workspace=ws_name,
|
|
3532
3541
|
# sync_id of the in-flight sync (when running) so a client that
|
|
3533
3542
|
# didn't start it can attach to the progress stream.
|
|
3534
|
-
|
|
3535
|
-
|
|
3543
|
+
active_sync_id=active_sync_id,
|
|
3544
|
+
)
|
|
3536
3545
|
)
|
|
3537
3546
|
|
|
3538
3547
|
for _c in _conn_cache.values():
|
|
@@ -3542,7 +3551,7 @@ async def projects_health():
|
|
|
3542
3551
|
except Exception: # noqa: BLE001
|
|
3543
3552
|
logger.debug("graph conn close failed", exc_info=True)
|
|
3544
3553
|
|
|
3545
|
-
return
|
|
3554
|
+
return ProjectsHealthResponse(projects=result)
|
|
3546
3555
|
|
|
3547
3556
|
|
|
3548
3557
|
# ── Endpoints ─────────────────────────────────────────────────────────
|
|
@@ -13,6 +13,7 @@ import yaml
|
|
|
13
13
|
from fastapi import FastAPI
|
|
14
14
|
from fastapi.testclient import TestClient
|
|
15
15
|
from lineage.api import desktop_setup
|
|
16
|
+
from lineage.api.desktop_workspaces import router as workspaces_router
|
|
16
17
|
from lineage.utils.dbt import DbtDocsResult
|
|
17
18
|
|
|
18
19
|
|
|
@@ -29,6 +30,38 @@ def _build_client(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> TestClient
|
|
|
29
30
|
return TestClient(app)
|
|
30
31
|
|
|
31
32
|
|
|
33
|
+
def test_workspace_crud_creation_stamps_current_marker_without_graph_drop(
|
|
34
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
35
|
+
) -> None:
|
|
36
|
+
from core.migrations import graph_migration
|
|
37
|
+
|
|
38
|
+
client = _build_client(tmp_path, monkeypatch)
|
|
39
|
+
core_paths.config_path().write_text(
|
|
40
|
+
yaml.safe_dump(
|
|
41
|
+
{
|
|
42
|
+
"lineage": {
|
|
43
|
+
"backend": "surrealdb",
|
|
44
|
+
"url": "ws://127.0.0.1:3567",
|
|
45
|
+
},
|
|
46
|
+
"repos": {},
|
|
47
|
+
"workspaces": {},
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
encoding="utf-8",
|
|
51
|
+
)
|
|
52
|
+
client.app.include_router(workspaces_router)
|
|
53
|
+
monkeypatch.setattr(
|
|
54
|
+
graph_migration,
|
|
55
|
+
"drop_legacy_graph",
|
|
56
|
+
lambda *_args, **_kwargs: pytest.fail("fresh creation must not drop a graph"),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
response = client.post("/desktop/workspaces", json={"name": "ws2"})
|
|
60
|
+
|
|
61
|
+
assert response.status_code == 200
|
|
62
|
+
assert graph_migration.workspace_needs_graph_migration("ws2") is False
|
|
63
|
+
|
|
64
|
+
|
|
32
65
|
def _reset_manifest(monkeypatch: pytest.MonkeyPatch) -> str:
|
|
33
66
|
monkeypatch.setattr(session_mod, "_session_id", None)
|
|
34
67
|
monkeypatch.delenv(session_mod.SESSION_ID_ENV, raising=False)
|
|
@@ -99,6 +132,42 @@ def _seed_repo(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> tuple[TestCli
|
|
|
99
132
|
return client, "repo1"
|
|
100
133
|
|
|
101
134
|
|
|
135
|
+
def test_setup_creation_stamps_current_marker_without_graph_drop(
|
|
136
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
137
|
+
) -> None:
|
|
138
|
+
from core.migrations import graph_migration
|
|
139
|
+
|
|
140
|
+
client, repo_key = _seed_repo(tmp_path, monkeypatch)
|
|
141
|
+
expected_clone = core_paths.projects_dir() / "analytics"
|
|
142
|
+
expected_clone.mkdir(parents=True)
|
|
143
|
+
(expected_clone / "dbt_project.yml").write_text(
|
|
144
|
+
"name: analytics\nprofile: analytics_profile\n",
|
|
145
|
+
encoding="utf-8",
|
|
146
|
+
)
|
|
147
|
+
monkeypatch.setattr(
|
|
148
|
+
graph_migration,
|
|
149
|
+
"drop_legacy_graph",
|
|
150
|
+
lambda *_args, **_kwargs: pytest.fail("fresh setup must not drop a graph"),
|
|
151
|
+
)
|
|
152
|
+
monkeypatch.setattr(
|
|
153
|
+
"lineage.api.desktop_worktree._queue_gold_provisioning",
|
|
154
|
+
lambda *_args, **_kwargs: None,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
response = client.post(
|
|
158
|
+
"/desktop/setup/create-project",
|
|
159
|
+
json={
|
|
160
|
+
"name": repo_key,
|
|
161
|
+
"git_url": "https://github.com/acme/analytics.git",
|
|
162
|
+
"backend": "duckdb",
|
|
163
|
+
"duckdb_path": str(tmp_path / "warehouse.duckdb"),
|
|
164
|
+
},
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
assert response.status_code == 200, response.text
|
|
168
|
+
assert graph_migration.workspace_needs_graph_migration(repo_key) is False
|
|
169
|
+
|
|
170
|
+
|
|
102
171
|
def _collect_sse(response) -> list[tuple[str, dict]]:
|
|
103
172
|
events: list[tuple[str, dict]] = []
|
|
104
173
|
event_type: str | None = None
|
{typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/tests/api/test_desktop_sync.py
RENAMED
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import json
|
|
3
4
|
import logging
|
|
5
|
+
import sys
|
|
6
|
+
from collections.abc import Iterable
|
|
4
7
|
from pathlib import Path
|
|
5
8
|
from types import SimpleNamespace
|
|
9
|
+
from typing import Callable
|
|
10
|
+
from unittest.mock import AsyncMock, Mock
|
|
6
11
|
|
|
7
12
|
import core.observability.manifest as manifest_mod
|
|
8
13
|
import core.observability.session as session_mod
|
|
9
14
|
import pytest
|
|
15
|
+
from fastapi import FastAPI
|
|
16
|
+
from fastapi.testclient import TestClient
|
|
10
17
|
from lineage.api import desktop_sync
|
|
11
18
|
|
|
12
19
|
|
|
20
|
+
def _collect_sse_data(lines: Iterable[str | bytes]) -> list[dict[str, object]]:
|
|
21
|
+
events: list[dict[str, object]] = []
|
|
22
|
+
for line in lines:
|
|
23
|
+
text = line.decode("utf-8") if isinstance(line, bytes) else line
|
|
24
|
+
if text.startswith("data: "):
|
|
25
|
+
payload = json.loads(text.removeprefix("data: "))
|
|
26
|
+
assert isinstance(payload, dict)
|
|
27
|
+
events.append(payload)
|
|
28
|
+
return events
|
|
29
|
+
|
|
30
|
+
|
|
13
31
|
class EscalatingProcess:
|
|
14
32
|
def __init__(self):
|
|
15
33
|
self.pid = 4242
|
|
@@ -337,6 +355,270 @@ class _NotSetEvent:
|
|
|
337
355
|
return False
|
|
338
356
|
|
|
339
357
|
|
|
358
|
+
def _stub_sync_worker_shell(
|
|
359
|
+
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
360
|
+
) -> None:
|
|
361
|
+
shared_pool = SimpleNamespace(
|
|
362
|
+
install_pool_signal_handlers=lambda: None,
|
|
363
|
+
shutdown_shared_executor=lambda: None,
|
|
364
|
+
)
|
|
365
|
+
monkeypatch.setitem(
|
|
366
|
+
sys.modules,
|
|
367
|
+
"ingest.static_loaders.shared_pool",
|
|
368
|
+
shared_pool,
|
|
369
|
+
)
|
|
370
|
+
monkeypatch.setattr(
|
|
371
|
+
desktop_sync, "_filter_syncable_specs", lambda _ws, specs, _log: specs
|
|
372
|
+
)
|
|
373
|
+
monkeypatch.setattr(
|
|
374
|
+
desktop_sync, "_workspace_syncable_project_names", lambda *_: set()
|
|
375
|
+
)
|
|
376
|
+
monkeypatch.setattr(desktop_sync, "_child_resource_diagnostics", lambda: "test")
|
|
377
|
+
monkeypatch.setattr(desktop_sync, "_capture_sync_failed_analytics", lambda *_: None)
|
|
378
|
+
monkeypatch.setattr("core.paths.logs_dir", lambda: tmp_path)
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
@pytest.mark.parametrize(
|
|
382
|
+
"migration_error",
|
|
383
|
+
(
|
|
384
|
+
"Graph migration probe failed: marker unreadable",
|
|
385
|
+
"Graph migration failed: reset denied",
|
|
386
|
+
),
|
|
387
|
+
)
|
|
388
|
+
def test_sync_worker_migration_failure_emits_one_terminal_error_and_skips_builds(
|
|
389
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
390
|
+
tmp_path: Path,
|
|
391
|
+
migration_error: str,
|
|
392
|
+
) -> None:
|
|
393
|
+
_stub_sync_worker_shell(monkeypatch, tmp_path)
|
|
394
|
+
|
|
395
|
+
def _raise_reset_failure(
|
|
396
|
+
_workspace: str,
|
|
397
|
+
_projects: list[desktop_sync.ProjectBuildSpec],
|
|
398
|
+
_queue: _RecordingQueue,
|
|
399
|
+
_log: logging.Logger,
|
|
400
|
+
) -> bool:
|
|
401
|
+
raise RuntimeError(migration_error)
|
|
402
|
+
|
|
403
|
+
build_one_project = Mock()
|
|
404
|
+
monkeypatch.setattr(
|
|
405
|
+
desktop_sync,
|
|
406
|
+
"_maybe_migrate_workspace_graph",
|
|
407
|
+
_raise_reset_failure,
|
|
408
|
+
)
|
|
409
|
+
monkeypatch.setattr(desktop_sync, "_build_one_project", build_one_project)
|
|
410
|
+
queue = _RecordingQueue()
|
|
411
|
+
|
|
412
|
+
desktop_sync._sync_worker(
|
|
413
|
+
"ws",
|
|
414
|
+
"sync-reset-failure",
|
|
415
|
+
[desktop_sync.ProjectBuildSpec(name="analytics")],
|
|
416
|
+
queue,
|
|
417
|
+
_NotSetEvent(),
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
terminal_errors = [
|
|
421
|
+
event
|
|
422
|
+
for event in queue.events
|
|
423
|
+
if event["stage"] == "error" and event["status"] == "error"
|
|
424
|
+
]
|
|
425
|
+
assert len(terminal_errors) == 1
|
|
426
|
+
build_one_project.assert_not_called()
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
def test_sync_probe_failure_serializes_one_terminal_sse_error_without_builds(
|
|
430
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
431
|
+
tmp_path: Path,
|
|
432
|
+
) -> None:
|
|
433
|
+
_stub_sync_worker_shell(monkeypatch, tmp_path)
|
|
434
|
+
_stub_drain_finalization(monkeypatch)
|
|
435
|
+
desktop_sync._sync_ops.clear()
|
|
436
|
+
desktop_sync.shutdown_event.clear()
|
|
437
|
+
build_one_project = Mock()
|
|
438
|
+
|
|
439
|
+
def _raise_probe_failure(
|
|
440
|
+
_workspace: str,
|
|
441
|
+
_projects: list[desktop_sync.ProjectBuildSpec],
|
|
442
|
+
_queue: _RecordingQueue,
|
|
443
|
+
_log: logging.Logger,
|
|
444
|
+
) -> bool:
|
|
445
|
+
raise RuntimeError("Graph migration probe failed: marker unreadable")
|
|
446
|
+
|
|
447
|
+
process = Mock(pid=4242, exitcode=0)
|
|
448
|
+
process.is_alive.return_value = False
|
|
449
|
+
process_factory = Mock(return_value=process)
|
|
450
|
+
|
|
451
|
+
def _run_worker() -> None:
|
|
452
|
+
call = process_factory.call_args
|
|
453
|
+
call.kwargs["target"](*call.kwargs["args"])
|
|
454
|
+
|
|
455
|
+
process.start.side_effect = _run_worker
|
|
456
|
+
monkeypatch.setattr(desktop_sync, "Process", process_factory)
|
|
457
|
+
monkeypatch.setattr(
|
|
458
|
+
desktop_sync, "_maybe_migrate_workspace_graph", _raise_probe_failure
|
|
459
|
+
)
|
|
460
|
+
monkeypatch.setattr(desktop_sync, "_build_one_project", build_one_project)
|
|
461
|
+
monkeypatch.setattr(
|
|
462
|
+
desktop_sync, "capture_backend_event_from_request", AsyncMock()
|
|
463
|
+
)
|
|
464
|
+
app = FastAPI()
|
|
465
|
+
app.include_router(desktop_sync.router)
|
|
466
|
+
|
|
467
|
+
with TestClient(app) as client:
|
|
468
|
+
started = client.post(
|
|
469
|
+
"/desktop/sync/",
|
|
470
|
+
json={
|
|
471
|
+
"workspace_name": "ws",
|
|
472
|
+
"project_name": "analytics",
|
|
473
|
+
},
|
|
474
|
+
)
|
|
475
|
+
assert started.status_code == 200
|
|
476
|
+
sync_id = started.json()["sync_id"]
|
|
477
|
+
with client.stream("GET", f"/desktop/sync/{sync_id}/progress") as response:
|
|
478
|
+
serialized = _collect_sse_data(response.iter_lines())
|
|
479
|
+
|
|
480
|
+
terminal_errors = [
|
|
481
|
+
event
|
|
482
|
+
for event in serialized
|
|
483
|
+
if event["stage"] == "error" and event["status"] == "error"
|
|
484
|
+
]
|
|
485
|
+
assert len(terminal_errors) == 1
|
|
486
|
+
build_one_project.assert_not_called()
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def test_collect_sse_data_decodes_byte_lines() -> None:
|
|
490
|
+
assert _collect_sse_data([b'data: {"status": "completed"}']) == [
|
|
491
|
+
{"status": "completed"}
|
|
492
|
+
]
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
def test_migration_forces_every_context_full_then_second_worker_run_is_incremental(
|
|
496
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
497
|
+
tmp_path: Path,
|
|
498
|
+
) -> None:
|
|
499
|
+
_stub_sync_worker_shell(monkeypatch, tmp_path)
|
|
500
|
+
migration_results = iter((True, False))
|
|
501
|
+
monkeypatch.setattr(
|
|
502
|
+
desktop_sync,
|
|
503
|
+
"_maybe_migrate_workspace_graph",
|
|
504
|
+
lambda *_: next(migration_results),
|
|
505
|
+
)
|
|
506
|
+
build_one_project = Mock(
|
|
507
|
+
return_value=desktop_sync._ProjectOutcome(status="completed")
|
|
508
|
+
)
|
|
509
|
+
monkeypatch.setattr(desktop_sync, "_build_one_project", build_one_project)
|
|
510
|
+
monkeypatch.setattr(desktop_sync, "_workspace_l1_missing", lambda _db: False)
|
|
511
|
+
monkeypatch.setattr(
|
|
512
|
+
desktop_sync, "_run_concepts_finalize", lambda *_args, **_kwargs: None
|
|
513
|
+
)
|
|
514
|
+
specs = [
|
|
515
|
+
desktop_sync.ProjectBuildSpec(name="orders"),
|
|
516
|
+
desktop_sync.ProjectBuildSpec(name="customers"),
|
|
517
|
+
]
|
|
518
|
+
|
|
519
|
+
for sync_id in ("sync-migrate", "sync-noop"):
|
|
520
|
+
desktop_sync._sync_worker(
|
|
521
|
+
"ws",
|
|
522
|
+
sync_id,
|
|
523
|
+
specs,
|
|
524
|
+
_RecordingQueue(),
|
|
525
|
+
_NotSetEvent(),
|
|
526
|
+
)
|
|
527
|
+
|
|
528
|
+
assert [call.args[3] for call in build_one_project.call_args_list] == [
|
|
529
|
+
True,
|
|
530
|
+
True,
|
|
531
|
+
False,
|
|
532
|
+
False,
|
|
533
|
+
]
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
def test_sync_route_migrates_once_and_forces_every_context_full(
|
|
537
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
538
|
+
tmp_path: Path,
|
|
539
|
+
) -> None:
|
|
540
|
+
import core.paths as core_paths
|
|
541
|
+
from core.migrations import graph_migration
|
|
542
|
+
|
|
543
|
+
_stub_sync_worker_shell(monkeypatch, tmp_path)
|
|
544
|
+
_stub_drain_finalization(monkeypatch)
|
|
545
|
+
monkeypatch.setenv("TYPEDEF_HOME", str(tmp_path))
|
|
546
|
+
monkeypatch.setenv("TYPEDEF_DEV_MODE", "1")
|
|
547
|
+
core_paths.typedef_home.cache_clear()
|
|
548
|
+
desktop_sync._sync_ops.clear()
|
|
549
|
+
desktop_sync.shutdown_event.clear()
|
|
550
|
+
marker = graph_migration.graph_marker_path(tmp_path, "ws")
|
|
551
|
+
marker.parent.mkdir(parents=True)
|
|
552
|
+
marker.write_text('{"workspace": "ws"}', encoding="utf-8")
|
|
553
|
+
drop_calls: list[str] = []
|
|
554
|
+
|
|
555
|
+
def _drop_and_stamp(
|
|
556
|
+
workspace: str, *, progress_cb: Callable[[str, int, int], None]
|
|
557
|
+
) -> SimpleNamespace:
|
|
558
|
+
drop_calls.append(workspace)
|
|
559
|
+
progress_cb("drop", 1, 1)
|
|
560
|
+
graph_migration.mark_workspace_graph_compatible(
|
|
561
|
+
workspace, home=tmp_path, reason="test_migration"
|
|
562
|
+
)
|
|
563
|
+
return SimpleNamespace(applied=True, cleared_context_entries=2, errors=[])
|
|
564
|
+
|
|
565
|
+
monkeypatch.setattr(graph_migration, "drop_legacy_graph", _drop_and_stamp)
|
|
566
|
+
build_one_project = Mock(
|
|
567
|
+
return_value=desktop_sync._ProjectOutcome(status="completed")
|
|
568
|
+
)
|
|
569
|
+
monkeypatch.setattr(desktop_sync, "_build_one_project", build_one_project)
|
|
570
|
+
monkeypatch.setattr(desktop_sync, "_workspace_l1_missing", lambda _db: False)
|
|
571
|
+
monkeypatch.setattr(
|
|
572
|
+
desktop_sync, "_run_concepts_finalize", lambda *_args, **_kwargs: None
|
|
573
|
+
)
|
|
574
|
+
process_factory = Mock()
|
|
575
|
+
processes = [Mock(pid=4242, exitcode=0), Mock(pid=4243, exitcode=0)]
|
|
576
|
+
for process in processes:
|
|
577
|
+
process.is_alive.return_value = False
|
|
578
|
+
|
|
579
|
+
def _run_worker() -> None:
|
|
580
|
+
call = process_factory.call_args
|
|
581
|
+
call.kwargs["target"](*call.kwargs["args"])
|
|
582
|
+
|
|
583
|
+
process.start.side_effect = _run_worker
|
|
584
|
+
process_factory.side_effect = processes
|
|
585
|
+
monkeypatch.setattr(desktop_sync, "Process", process_factory)
|
|
586
|
+
monkeypatch.setattr(
|
|
587
|
+
desktop_sync, "capture_backend_event_from_request", AsyncMock()
|
|
588
|
+
)
|
|
589
|
+
app = FastAPI()
|
|
590
|
+
app.include_router(desktop_sync.router)
|
|
591
|
+
request_body = {
|
|
592
|
+
"workspace_name": "ws",
|
|
593
|
+
"project_name": "orders",
|
|
594
|
+
"projects": [
|
|
595
|
+
{"name": "orders", "full": False},
|
|
596
|
+
{"name": "customers", "full": False},
|
|
597
|
+
],
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
with TestClient(app) as client:
|
|
601
|
+
for _expected_drop_count in (1, 1):
|
|
602
|
+
started = client.post("/desktop/sync/", json=request_body)
|
|
603
|
+
assert started.status_code == 200
|
|
604
|
+
sync_id = started.json()["sync_id"]
|
|
605
|
+
with client.stream(
|
|
606
|
+
"GET", f"/desktop/sync/{sync_id}/progress"
|
|
607
|
+
) as response:
|
|
608
|
+
assert any(
|
|
609
|
+
event["status"] == "completed"
|
|
610
|
+
for event in _collect_sse_data(response.iter_lines())
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
assert drop_calls == ["ws"]
|
|
614
|
+
assert [call.args[3] for call in build_one_project.call_args_list] == [
|
|
615
|
+
True,
|
|
616
|
+
True,
|
|
617
|
+
False,
|
|
618
|
+
False,
|
|
619
|
+
]
|
|
620
|
+
|
|
621
|
+
|
|
340
622
|
def test_graph_migration_progress_events_are_nonterminal(monkeypatch):
|
|
341
623
|
from core.migrations import graph_migration
|
|
342
624
|
|
|
@@ -365,6 +647,28 @@ def test_graph_migration_progress_events_are_nonterminal(monkeypatch):
|
|
|
365
647
|
assert any("flagged for resync" in event["message"] for event in migrate_events)
|
|
366
648
|
|
|
367
649
|
|
|
650
|
+
def test_graph_migration_probe_error_aborts_before_project_build(monkeypatch) -> None:
|
|
651
|
+
"""An unreadable marker must stop sync before any project work begins."""
|
|
652
|
+
from core.migrations import graph_migration
|
|
653
|
+
|
|
654
|
+
def _raise_marker_io_error(_workspace: str) -> bool:
|
|
655
|
+
raise OSError("marker unreadable")
|
|
656
|
+
|
|
657
|
+
monkeypatch.setattr(
|
|
658
|
+
graph_migration,
|
|
659
|
+
"workspace_needs_graph_migration",
|
|
660
|
+
_raise_marker_io_error,
|
|
661
|
+
)
|
|
662
|
+
|
|
663
|
+
with pytest.raises(RuntimeError, match="Graph migration probe failed"):
|
|
664
|
+
desktop_sync._maybe_migrate_workspace_graph(
|
|
665
|
+
"ws",
|
|
666
|
+
[],
|
|
667
|
+
_RecordingQueue(),
|
|
668
|
+
logging.getLogger("test"),
|
|
669
|
+
)
|
|
670
|
+
|
|
671
|
+
|
|
368
672
|
def _write_project_config(
|
|
369
673
|
cfg_path: Path,
|
|
370
674
|
project_name: str,
|
|
@@ -1410,18 +1714,75 @@ def test_projects_health_stamps_active_workspace_on_name_collision(
|
|
|
1410
1714
|
)
|
|
1411
1715
|
|
|
1412
1716
|
res = asyncio.run(desktop_sync.projects_health())
|
|
1413
|
-
rows = res
|
|
1717
|
+
rows = res.projects
|
|
1414
1718
|
|
|
1415
1719
|
# Only the ACTIVE workspace's projects are enumerated.
|
|
1416
|
-
assert {r
|
|
1720
|
+
assert {r.name for r in rows} == {"shared", "alpha"}
|
|
1417
1721
|
# Every row — including the colliding ``shared`` — is stamped with the
|
|
1418
1722
|
# active workspace, NOT ws_b (the old last-writer-wins bug).
|
|
1419
1723
|
for r in rows:
|
|
1420
|
-
assert r
|
|
1421
|
-
f"{r
|
|
1724
|
+
assert r.workspace == "ws_a", (
|
|
1725
|
+
f"{r.name!r} mis-stamped {r.workspace!r} (expected ws_a)"
|
|
1422
1726
|
)
|
|
1423
1727
|
|
|
1424
1728
|
|
|
1729
|
+
def test_projects_health_reports_marker_io_error_without_crashing(
|
|
1730
|
+
monkeypatch, tmp_path, caplog
|
|
1731
|
+
) -> None:
|
|
1732
|
+
"""Health remains available when sync's marker probe must fail closed."""
|
|
1733
|
+
import asyncio
|
|
1734
|
+
|
|
1735
|
+
import yaml
|
|
1736
|
+
from core import paths as core_paths
|
|
1737
|
+
from core.migrations import graph_migration
|
|
1738
|
+
|
|
1739
|
+
cfg_file = tmp_path / "config.yaml"
|
|
1740
|
+
cfg_file.write_text(
|
|
1741
|
+
yaml.safe_dump(
|
|
1742
|
+
{
|
|
1743
|
+
"active_workspace": "ws",
|
|
1744
|
+
"repos": {},
|
|
1745
|
+
"workspaces": {
|
|
1746
|
+
"ws": {
|
|
1747
|
+
"graph_db": "ws",
|
|
1748
|
+
"context": [{"project": {"name": "project"}}],
|
|
1749
|
+
}
|
|
1750
|
+
},
|
|
1751
|
+
}
|
|
1752
|
+
),
|
|
1753
|
+
encoding="utf-8",
|
|
1754
|
+
)
|
|
1755
|
+
monkeypatch.setattr(core_paths, "config_path", lambda: cfg_file)
|
|
1756
|
+
|
|
1757
|
+
def _raise_marker_io_error(_workspace: str) -> bool:
|
|
1758
|
+
raise OSError("marker unreadable")
|
|
1759
|
+
|
|
1760
|
+
monkeypatch.setattr(
|
|
1761
|
+
graph_migration,
|
|
1762
|
+
"workspace_needs_graph_migration",
|
|
1763
|
+
_raise_marker_io_error,
|
|
1764
|
+
)
|
|
1765
|
+
monkeypatch.setattr(desktop_sync, "_open_surreal_for_graph", lambda _gdb: None)
|
|
1766
|
+
monkeypatch.setattr(
|
|
1767
|
+
desktop_sync,
|
|
1768
|
+
"_project_has_graph_data",
|
|
1769
|
+
lambda _gdb, _name: False,
|
|
1770
|
+
)
|
|
1771
|
+
|
|
1772
|
+
with caplog.at_level(logging.DEBUG, logger=desktop_sync.logger.name):
|
|
1773
|
+
response = asyncio.run(desktop_sync.projects_health())
|
|
1774
|
+
|
|
1775
|
+
assert len(response.projects) == 1
|
|
1776
|
+
project = response.projects[0]
|
|
1777
|
+
assert project.name == "project"
|
|
1778
|
+
assert project.needs_migration is True
|
|
1779
|
+
assert project.migration_error == "marker unreadable"
|
|
1780
|
+
marker_logs = [
|
|
1781
|
+
record for record in caplog.records if "graph marker probe failed" in record.message
|
|
1782
|
+
]
|
|
1783
|
+
assert [record.levelno for record in marker_logs] == [logging.DEBUG]
|
|
1784
|
+
|
|
1785
|
+
|
|
1425
1786
|
# ── TD-2950: silent-sync-death diagnostics ────────────────────────────
|
|
1426
1787
|
|
|
1427
1788
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/config.ingest.unified.yml
RENAMED
|
File without changes
|
|
File without changes
|
{typedef_data_intelligence-0.40.0 → typedef_data_intelligence-0.41.0}/docker-entrypoint.dev.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|