typedef-data-intelligence 0.34.0__tar.gz → 0.35.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.
Files changed (256) hide show
  1. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/CHANGELOG.md +15 -0
  2. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/PKG-INFO +1 -1
  3. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/pyproject.toml +1 -1
  4. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/app.py +20 -0
  5. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/desktop_quickstart.py +73 -11
  6. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/desktop_setup.py +73 -0
  7. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/desktop_sync.py +130 -10
  8. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/desktop_workspaces.py +125 -69
  9. typedef_data_intelligence-0.35.0/src/lineage/context_projects/__init__.py +27 -0
  10. typedef_data_intelligence-0.35.0/src/lineage/context_projects/airflow_discovery.py +304 -0
  11. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/context_projects/dbt_plugin.py +6 -1
  12. typedef_data_intelligence-0.35.0/tests/api/test_app_lifespan.py +48 -0
  13. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_quickstart.py +191 -0
  14. typedef_data_intelligence-0.35.0/tests/api/test_desktop_repo_projects_discovery.py +272 -0
  15. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_setup.py +59 -0
  16. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_setup_clone.py +121 -0
  17. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_sync.py +394 -7
  18. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/devtools/test_typedef_home_provision.py +354 -9
  19. typedef_data_intelligence-0.35.0/tests/unit/context_projects/test_airflow_discovery.py +266 -0
  20. typedef_data_intelligence-0.34.0/src/lineage/context_projects/__init__.py +0 -18
  21. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/.dockerignore +0 -0
  22. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/.env.example +0 -0
  23. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/.gitignore +0 -0
  24. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/.justfile_help.txt +0 -0
  25. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/Dockerfile +0 -0
  26. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/Dockerfile.dev +0 -0
  27. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/Justfile +0 -0
  28. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/README.pypi.md +0 -0
  29. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/config.api.yml +0 -0
  30. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/config.cli.yml +0 -0
  31. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/config.desktop.yml +0 -0
  32. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/config.ingest.unified.yml +0 -0
  33. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/config.ingest.yml +0 -0
  34. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docker-entrypoint.dev.sh +0 -0
  35. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/LINEAR_TICKETING_BACKEND.md +0 -0
  36. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/architecture/BUSINESS_CONCEPT_INDEX.md +0 -0
  37. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/architecture/CLUSTERING_ALGORITHM_DECISION.md +0 -0
  38. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/architecture/GENERIC_REPORT_SCHEMA.md +0 -0
  39. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/architecture/HYBRID_ANALYSIS_ARCHITECTURE.md +0 -0
  40. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/architecture/PHASE2_IR_STITCHING.md +0 -0
  41. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/architecture/PIPELINE_PRIMITIVES_USECASES.md +0 -0
  42. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/architecture/SALESFORCE_REPORT_IR.md +0 -0
  43. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/architecture/SEMANTIC_JOIN_RESOLUTION.md +0 -0
  44. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/architecture/SEMANTIC_SCHEMA_DESIGN.md +0 -0
  45. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/design/AGENT_DESIGN_NOTES.md +0 -0
  46. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/design/COLUMN_PROFILING.md +0 -0
  47. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/design/COLUMN_PROFILING_IMPLEMENTATION.md +0 -0
  48. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/design/EXTRACTION_DETECTION.md +0 -0
  49. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/design/PERFORMANCE_AND_QUALITY_SPECIALISTS.md +0 -0
  50. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/design/STREAMING_SUBAGENT_ARCHITECTURE.md +0 -0
  51. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/examples/memory_usage_examples.py +0 -0
  52. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/examples/pydantic_tool_customization_example.py +0 -0
  53. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/reference/AGENT_USER_GUIDE.md +0 -0
  54. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/reference/GETTING_STARTED.md +0 -0
  55. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/reference/MIGRATION_THREE_SQL.md +0 -0
  56. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/reference/SCOPE_LEVEL_LINEAGE_GUIDE.md +0 -0
  57. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/reference/SEMANTIC_DIFF_HARNESS.md +0 -0
  58. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/reference/SEMANTIC_DIMENSIONS_GUIDE.md +0 -0
  59. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/docs/reference/TYPE_ENUMS.md +0 -0
  60. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/pytest.ini +0 -0
  61. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/scripts/create_salesforce_reports.py +0 -0
  62. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/scripts/data_generation/utils.py +0 -0
  63. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/scripts/databricks-smoke.py +0 -0
  64. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/scripts/delete_salesforce_reports.py +0 -0
  65. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/scripts/populate_salesforce_schema.py +0 -0
  66. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/scripts/reset_demo_git_workspace.py +0 -0
  67. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/scripts/reset_demo_linear.py +0 -0
  68. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/scripts/snowflake_server.py +0 -0
  69. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/scripts/surreal-engine-bench.sh +0 -0
  70. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/scripts/surreal-fts-b2-corpus.sh +0 -0
  71. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/scripts/surreal-fts-bench.sh +0 -0
  72. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/scripts/surreal-fts-quality.sh +0 -0
  73. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/snowflake-mcp-config.yaml +0 -0
  74. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/__init__.py +0 -0
  75. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/auth_context.py +0 -0
  76. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/concept_cards.py +0 -0
  77. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/controlplane_identity.py +0 -0
  78. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/desktop_agents.py +0 -0
  79. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/desktop_context.py +0 -0
  80. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/desktop_logs.py +0 -0
  81. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/desktop_runtime.py +0 -0
  82. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/desktop_semdiff_provision.py +0 -0
  83. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/desktop_wizard_sync.py +0 -0
  84. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/desktop_worktree.py +0 -0
  85. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/graph_availability.py +0 -0
  86. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/posthog_analytics.py +0 -0
  87. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/semantic_runtime.py +0 -0
  88. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/api/serve.py +0 -0
  89. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/__init__.py +0 -0
  90. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/backward_dryrun.py +0 -0
  91. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/clustering_metrics.py +0 -0
  92. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/drop_snowflake_tables.py +0 -0
  93. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/ephemeral_lineage_report.py +0 -0
  94. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/eval_clustering.py +0 -0
  95. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/list_ephemeral_models.py +0 -0
  96. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/refingerprint_cache.py +0 -0
  97. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/regen_semantic_goldens.py +0 -0
  98. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/reset_git_workspace.py +0 -0
  99. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/reset_linear_workspace.py +0 -0
  100. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/reset_project.py +0 -0
  101. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/run_dbt_workflow.py +0 -0
  102. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/seed_census.py +0 -0
  103. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/semantic_goldens.py +0 -0
  104. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/__init__.py +0 -0
  105. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/fts_bench.py +0 -0
  106. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/fts_cells.py +0 -0
  107. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/fts_corpus.py +0 -0
  108. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/fts_corpus_dump.py +0 -0
  109. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/fts_coverage.py +0 -0
  110. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/fts_coverage_report.py +0 -0
  111. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/fts_oracle.py +0 -0
  112. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/fts_quality.py +0 -0
  113. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/fts_quality_bench.py +0 -0
  114. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/log_parse.py +0 -0
  115. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/report.py +0 -0
  116. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/surreal_bench/runner.py +0 -0
  117. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/__init__.py +0 -0
  118. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/README.md +0 -0
  119. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/__init__.py +0 -0
  120. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/cli.py +0 -0
  121. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/db_names.py +0 -0
  122. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/dbt_compile.py +0 -0
  123. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/diff_runner.py +0 -0
  124. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/expected_changes.py +0 -0
  125. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/column_rename_downstream/fixture.yaml +0 -0
  126. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/column_rename_downstream/mutation.diff +0 -0
  127. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_coarsen/fixture.yaml +0 -0
  128. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_coarsen/mutation.diff +0 -0
  129. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_deleted_leaf_model/fixture.yaml +0 -0
  130. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_deleted_leaf_model/mutation.diff +0 -0
  131. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_fanout_compound_oli/fixture.yaml +0 -0
  132. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_fanout_compound_oli/mutation.diff +0 -0
  133. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_gold_control/fixture.yaml +0 -0
  134. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_gold_control/mutation.diff +0 -0
  135. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_v1_003_user_telemetry/fixture.yaml +0 -0
  136. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures/grain_v1_003_user_telemetry/mutation.diff +0 -0
  137. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/fixtures_loader.py +0 -0
  138. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/ingest.py +0 -0
  139. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/lifecycle.py +0 -0
  140. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/semantic_diff/source_prep.py +0 -0
  141. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/surreal/__init__.py +0 -0
  142. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/surreal/desktop_mcp.py +0 -0
  143. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/devtools/unified_graph/unified_cli.py +0 -0
  144. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/mcp/__init__.py +0 -0
  145. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/mcp/runner.py +0 -0
  146. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/mcp/server.py +0 -0
  147. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/templates/__init__.py +0 -0
  148. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/templates/typedef_config.yaml.j2 +0 -0
  149. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/typedef_cli.py +0 -0
  150. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/utils/__init__.py +0 -0
  151. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/utils/databricks.py +0 -0
  152. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/utils/databricks_oauth.py +0 -0
  153. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/utils/dbt.py +0 -0
  154. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/utils/dbt_profile.py +0 -0
  155. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/utils/env.py +0 -0
  156. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/utils/git.py +0 -0
  157. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/utils/gitignore.py +0 -0
  158. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/utils/logging.py +0 -0
  159. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/src/lineage/utils/snowflake.py +0 -0
  160. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/__init__.py +0 -0
  161. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_concept_cards.py +0 -0
  162. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_databricks_auth_wiring.py +0 -0
  163. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_agents_clone_backend.py +0 -0
  164. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_agents_runtime.py +0 -0
  165. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_agents_ticket_resolution.py +0 -0
  166. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_airflow_snapshot.py +0 -0
  167. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_clerk_auth.py +0 -0
  168. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_context_reader_cache.py +0 -0
  169. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_databases_delete.py +0 -0
  170. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_databases_edit.py +0 -0
  171. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_databricks_oauth.py +0 -0
  172. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_databricks_setup.py +0 -0
  173. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_delete_endpoints.py +0 -0
  174. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_diagnostics.py +0 -0
  175. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_logs.py +0 -0
  176. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_orphan_flags.py +0 -0
  177. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_posthog.py +0 -0
  178. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_runtime.py +0 -0
  179. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_salesforce.py +0 -0
  180. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_save_env_credentials.py +0 -0
  181. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_search.py +0 -0
  182. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_secondary_roles_hook.py +0 -0
  183. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_semdiff_provision.py +0 -0
  184. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_setup_env_vars.py +0 -0
  185. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_sync_render_profile.py +0 -0
  186. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_telemetry.py +0 -0
  187. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_workspaces.py +0 -0
  188. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_workspaces_adopt.py +0 -0
  189. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_workspaces_context_kinds.py +0 -0
  190. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_workspaces_delete.py +0 -0
  191. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_workspaces_gold_triggers.py +0 -0
  192. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_workspaces_integrations.py +0 -0
  193. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_workspaces_preview_name.py +0 -0
  194. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_workspaces_projects_and_repos.py +0 -0
  195. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_workspaces_r3_r10.py +0 -0
  196. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_workspaces_summary.py +0 -0
  197. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_workspaces_target_scope.py +0 -0
  198. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_workspaces_wizard.py +0 -0
  199. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_worktree.py +0 -0
  200. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_worktree_clone.py +0 -0
  201. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_worktree_clone_token_scope.py +0 -0
  202. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_worktree_gold_queue.py +0 -0
  203. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_worktree_kind_target.py +0 -0
  204. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_desktop_worktree_resolution_scope.py +0 -0
  205. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_graph_availability_any_sentinel.py +0 -0
  206. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_no_legacy_surface.py +0 -0
  207. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_surreal_graph_availability.py +0 -0
  208. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_target_envelope_reads.py +0 -0
  209. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_validate_project_collisions.py +0 -0
  210. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_wizard_create_project_integration_persistence.py +0 -0
  211. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_workspace_clone_settings.py +0 -0
  212. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/api/test_worktree_registry_workspaces_shape.py +0 -0
  213. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/backends/__init__.py +0 -0
  214. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/backends/lineage/__init__.py +0 -0
  215. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/backends/lineage/test_search_enum_coverage.py +0 -0
  216. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/backends/lineage/test_surreal_search.py +0 -0
  217. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/conftest.py +0 -0
  218. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/devtools/__init__.py +0 -0
  219. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/devtools/surreal_bench/__init__.py +0 -0
  220. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/devtools/surreal_bench/test_fts_cells.py +0 -0
  221. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/devtools/surreal_bench/test_fts_coverage.py +0 -0
  222. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/devtools/surreal_bench/test_fts_quality.py +0 -0
  223. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/devtools/surreal_bench/test_log_parse.py +0 -0
  224. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/devtools/surreal_bench/test_report.py +0 -0
  225. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/devtools/test_worktree_reclaim.py +0 -0
  226. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/docs/test_desktop_posthog_event_docs.py +0 -0
  227. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/integration/__init__.py +0 -0
  228. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/integration/test_semantic_diff_harness.py +0 -0
  229. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/mcp/__init__.py +0 -0
  230. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/mcp/test_desktop_mcp_retry.py +0 -0
  231. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/mcp/test_list_projects.py +0 -0
  232. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/mcp/test_server.py +0 -0
  233. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/test_git_utils.py +0 -0
  234. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/test_gitignore_utils.py +0 -0
  235. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/test_helpers_semantic.py +0 -0
  236. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/test_model_tier_validation.py +0 -0
  237. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/test_template_yaml_escaping.py +0 -0
  238. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/test_typedef_cli_import_budget.py +0 -0
  239. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/test_unified_cli_airflow.py +0 -0
  240. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/test_unified_cli_fast.py +0 -0
  241. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/test_unified_cli_semantic.py +0 -0
  242. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/context_projects/test_dbt_plugin.py +0 -0
  243. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/devtools/__init__.py +0 -0
  244. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/devtools/test_semdiff_expected_changes.py +0 -0
  245. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/devtools/test_semdiff_harness_units.py +0 -0
  246. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/devtools/test_semdiff_lifecycle.py +0 -0
  247. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/devtools/test_semdiff_lifecycle_io.py +0 -0
  248. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/devtools/test_semdiff_lifecycle_provisioning.py +0 -0
  249. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/formula/__init__.py +0 -0
  250. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/utils/__init__.py +0 -0
  251. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/utils/test_databricks_utils.py +0 -0
  252. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/utils/test_dbt_docs_generate.py +0 -0
  253. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/utils/test_dbt_profile.py +0 -0
  254. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/utils/test_logging.py +0 -0
  255. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/utils/test_run_dbt_command.py +0 -0
  256. {typedef_data_intelligence-0.34.0 → typedef_data_intelligence-0.35.0}/tests/unit/utils/test_snowflake_utils.py +0 -0
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.35.0](https://github.com/typedef-ai/typedef/compare/typedef-data-intelligence-v0.34.0...typedef-data-intelligence-v0.35.0) (2026-07-06)
4
+
5
+
6
+ ### Features
7
+
8
+ * **desktop:** Airflow context-project discovery + multi-kind picker (TD-2647) ([#1079](https://github.com/typedef-ai/typedef/issues/1079)) ([0436af1](https://github.com/typedef-ai/typedef/commit/0436af1f8720643405921759be411ef39c783172))
9
+ * **observability:** add session manifest core + call-site instrumentation (TD-3826) ([#1098](https://github.com/typedef-ai/typedef/issues/1098)) ([8c6406a](https://github.com/typedef-ai/typedef/commit/8c6406a5d31d4429e7dbe0de011361e8fa235239))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * **desktop:** honor dbt subprojects in test home provisioning ([#1093](https://github.com/typedef-ai/typedef/issues/1093)) ([0064597](https://github.com/typedef-ai/typedef/commit/0064597f2fa74452356061a8f7d69b2158106eb0))
15
+ * harden matrix sync completion validation ([#1096](https://github.com/typedef-ai/typedef/issues/1096)) ([afbc22e](https://github.com/typedef-ai/typedef/commit/afbc22eff571a69d56d6d764c6e79dc692d6cf96))
16
+ * **ingest:** bound RTIF snapshot reader run selection (TD-3823) ([#1095](https://github.com/typedef-ai/typedef/issues/1095)) ([fff7d65](https://github.com/typedef-ai/typedef/commit/fff7d6510f7d54b029dadb29dfa4ef6958239162))
17
+
3
18
  ## [0.34.0](https://github.com/typedef-ai/typedef/compare/typedef-data-intelligence-v0.33.0...typedef-data-intelligence-v0.34.0) (2026-07-01)
4
19
 
5
20
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: typedef-data-intelligence
3
- Version: 0.34.0
3
+ Version: 0.35.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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "typedef-data-intelligence"
3
- version = "0.34.0"
3
+ version = "0.35.0"
4
4
  description = "Unified lineage management and AI-powered analytics platform for dbt projects"
5
5
  readme = "README.pypi.md"
6
6
  license = "LicenseRef-Proprietary"
@@ -326,6 +326,19 @@ async def lifespan(app: FastAPI):
326
326
  len(removed_frontend_logs),
327
327
  )
328
328
 
329
+ try:
330
+ from core.observability.manifest import record_session_start
331
+ from core.observability.session import mint_session_id
332
+
333
+ mint_session_id()
334
+ record_session_start({})
335
+ except Exception as exc:
336
+ logger.warning(
337
+ "Observability session manifest startup failed: %s",
338
+ exc,
339
+ exc_info=True,
340
+ )
341
+
329
342
  # TD-3200 Phase 3: convert any already-workspaces-shape config from the
330
343
  # pre-envelope ContextEntry/flat-LineageTarget shape to the
331
344
  # ContextProject/BuildTarget envelope. Operates only on
@@ -733,6 +746,13 @@ async def lifespan(app: FastAPI):
733
746
  "Failed to terminate active gold workers", exc_info=True
734
747
  )
735
748
 
749
+ try:
750
+ from core.observability.manifest import finalize_open_ops
751
+
752
+ finalize_open_ops(outcome="cancelled")
753
+ except Exception:
754
+ logger.debug("Failed to finalize observability manifest ops", exc_info=True)
755
+
736
756
  try:
737
757
  from lineage.api.posthog_analytics import shutdown_shared_posthog_client
738
758
 
@@ -27,6 +27,8 @@ from typing import Any, Literal
27
27
  import yaml
28
28
  from agent.api import shutdown_event
29
29
  from core.backends.controlplane import LLMProxyConfig
30
+ from core.models.observability import Outcome
31
+ from core.observability.manifest import record_op_end, record_op_start
30
32
  from core.paths import (
31
33
  config_path,
32
34
  ensure_home,
@@ -144,6 +146,48 @@ _quickstart_ops: dict[str, QuickstartOperation] = {}
144
146
  _quickstart_lock = threading.Lock()
145
147
 
146
148
 
149
+ def _quickstart_manifest_attrs() -> dict[str, str]:
150
+ return {
151
+ "project_name": QUICKSTART_PROJECT_NAME,
152
+ "display_name": QUICKSTART_DISPLAY_NAME,
153
+ }
154
+
155
+
156
+ def _quickstart_manifest_outcome(status: str | None) -> Outcome:
157
+ if status == "error":
158
+ return "error"
159
+ if status == "cancelled":
160
+ return "cancelled"
161
+ return "ok"
162
+
163
+
164
+ def _record_quickstart_start(quickstart_id: str) -> None:
165
+ record_op_start(
166
+ "setup",
167
+ "quickstart",
168
+ quickstart_id,
169
+ attrs=_quickstart_manifest_attrs(),
170
+ )
171
+
172
+
173
+ def _record_quickstart_end(
174
+ quickstart_id: str,
175
+ outcome: Outcome,
176
+ *,
177
+ error: str | None = None,
178
+ ) -> None:
179
+ record_op_end("quickstart", quickstart_id, outcome, error=error)
180
+
181
+
182
+ def _record_quickstart_event_end(quickstart_id: str, event: dict[str, Any]) -> None:
183
+ status = event.get("status")
184
+ outcome = _quickstart_manifest_outcome(str(status) if status is not None else None)
185
+ error = None
186
+ if outcome == "error":
187
+ error = str(event.get("message") or "Quick Start failed")
188
+ _record_quickstart_end(quickstart_id, outcome, error=error)
189
+
190
+
147
191
  def _get_quickstart_op(quickstart_id: str) -> QuickstartOperation | None:
148
192
  with _quickstart_lock:
149
193
  return _quickstart_ops.get(quickstart_id)
@@ -908,6 +952,7 @@ def _watch_quickstart_process(quickstart_id: str) -> None:
908
952
  if terminal_event is not None:
909
953
  current.status = str(terminal_event.get("status", "completed"))
910
954
  current.last_event = terminal_event
955
+ _record_quickstart_event_end(quickstart_id, terminal_event)
911
956
  else:
912
957
  current.status = "completed"
913
958
  current.last_event = {
@@ -919,6 +964,7 @@ def _watch_quickstart_process(quickstart_id: str) -> None:
919
964
  ),
920
965
  "status": "completed",
921
966
  }
967
+ _record_quickstart_end(quickstart_id, "ok")
922
968
  elif exit_code == 128 + signal.SIGTERM:
923
969
  # TD-3192: SIGTERM-handler exit (143) is a clean cancel /
924
970
  # shutdown, not a crash — surface as cancelled.
@@ -929,6 +975,7 @@ def _watch_quickstart_process(quickstart_id: str) -> None:
929
975
  ),
930
976
  "status": "cancelled",
931
977
  }
978
+ _record_quickstart_end(quickstart_id, "cancelled")
932
979
  else:
933
980
  current.status = "error"
934
981
  current.error = f"Quick Start process exited unexpectedly (code {exit_code})"
@@ -936,6 +983,7 @@ def _watch_quickstart_process(quickstart_id: str) -> None:
936
983
  **_stage_event("clone", "error", current.error, terminal=True),
937
984
  "status": "error",
938
985
  }
986
+ _record_quickstart_end(quickstart_id, "error", error=current.error)
939
987
 
940
988
 
941
989
  def _cleanup_quickstart_op(operation: QuickstartOperation, *, force: bool) -> None:
@@ -1098,10 +1146,12 @@ async def start_quickstart() -> QuickstartStartResponse:
1098
1146
  terminal_event_path=_terminal_event_path(quickstart_id),
1099
1147
  )
1100
1148
  _quickstart_ops[quickstart_id] = op
1149
+ _record_quickstart_start(quickstart_id)
1101
1150
 
1102
1151
  try:
1103
1152
  proc.start()
1104
- except Exception:
1153
+ except Exception as exc:
1154
+ _record_quickstart_end(quickstart_id, "error", error=str(exc))
1105
1155
  _quickstart_ops.pop(quickstart_id, None)
1106
1156
  _delete_quickstart_project(previous_default_project)
1107
1157
  raise
@@ -1139,6 +1189,7 @@ async def quickstart_progress(quickstart_id: str):
1139
1189
  if op.status in {"completed", "error", "cancelled"} and op.last_event:
1140
1190
  _cleanup_op(op, force=True)
1141
1191
  last_event = op.last_event
1192
+ _record_quickstart_event_end(quickstart_id, last_event)
1142
1193
 
1143
1194
  async def terminal_event():
1144
1195
  yield _sse_event(f"quickstart.{last_event['status']}", last_event)
@@ -1151,6 +1202,7 @@ async def quickstart_progress(quickstart_id: str):
1151
1202
  while not shutdown_event.is_set():
1152
1203
  if op.status in {"completed", "error", "cancelled"}:
1153
1204
  if op.last_event is not None:
1205
+ _record_quickstart_event_end(quickstart_id, op.last_event)
1154
1206
  yield _sse_event(
1155
1207
  f"quickstart.{op.last_event['status']}", op.last_event
1156
1208
  )
@@ -1175,6 +1227,7 @@ async def quickstart_progress(quickstart_id: str):
1175
1227
  op.last_event = event
1176
1228
  if evt_status == "error":
1177
1229
  op.error = str(event.get("message") or "Quick Start failed")
1230
+ _record_quickstart_event_end(quickstart_id, event)
1178
1231
  break
1179
1232
 
1180
1233
  now = time.time()
@@ -1192,26 +1245,34 @@ async def quickstart_progress(quickstart_id: str):
1192
1245
  # TD-3192: SIGTERM-handler exit (143) — clean
1193
1246
  # cancel / shutdown, not a crash.
1194
1247
  op.status = "cancelled"
1248
+ op.last_event = {
1249
+ **_stage_event(
1250
+ "clone", "cancelled", "Quick Start cancelled"
1251
+ ),
1252
+ "status": "cancelled",
1253
+ }
1254
+ _record_quickstart_end(quickstart_id, "cancelled")
1195
1255
  yield _sse_event(
1196
1256
  "quickstart.cancelled",
1197
- {
1198
- **_stage_event(
1199
- "clone", "cancelled", "Quick Start cancelled"
1200
- ),
1201
- "status": "cancelled",
1202
- },
1257
+ op.last_event,
1203
1258
  )
1204
1259
  else:
1205
1260
  op.status = "error"
1206
1261
  op.error = (
1207
1262
  f"Quick Start process exited unexpectedly (code {exit_code})"
1208
1263
  )
1264
+ op.last_event = {
1265
+ **_stage_event("clone", "error", op.error),
1266
+ "status": "error",
1267
+ }
1268
+ _record_quickstart_end(
1269
+ quickstart_id,
1270
+ "error",
1271
+ error=op.error,
1272
+ )
1209
1273
  yield _sse_event(
1210
1274
  "quickstart.error",
1211
- {
1212
- **_stage_event("clone", "error", op.error),
1213
- "status": "error",
1214
- },
1275
+ op.last_event,
1215
1276
  )
1216
1277
  break
1217
1278
  finally:
@@ -1298,6 +1359,7 @@ async def cancel_quickstart(quickstart_id: str):
1298
1359
  }
1299
1360
  if op.terminal_event_path is not None:
1300
1361
  _persist_terminal_event(op.terminal_event_path, op.last_event)
1362
+ _record_quickstart_end(quickstart_id, "cancelled")
1301
1363
  _delete_quickstart_project(op.previous_default_project)
1302
1364
  _cleanup_quickstart_op(op, force=True)
1303
1365
  return {"message": f"Cancelled Quick Start '{quickstart_id}'"}
@@ -1053,6 +1053,8 @@ async def start_clone(req: CloneRequest):
1053
1053
  # repeat call with a different ``project_name`` (now reused as
1054
1054
  # ``display_name``) won't clobber the existing entry's display name.
1055
1055
  if dest.exists() and any(dest.iterdir()):
1056
+ from core.observability.manifest import record_op_end, record_op_start
1057
+
1056
1058
  _register_repo_pool_entry(req.git_url, dest, sanitized)
1057
1059
  _clone_ops[clone_id] = {
1058
1060
  "status": "complete",
@@ -1061,8 +1063,17 @@ async def start_clone(req: CloneRequest):
1061
1063
  "project_name": sanitized,
1062
1064
  "error": None,
1063
1065
  }
1066
+ record_op_start(
1067
+ "setup",
1068
+ "clone",
1069
+ clone_id,
1070
+ attrs={"project_name": sanitized},
1071
+ )
1072
+ record_op_end("clone", clone_id, "ok")
1064
1073
  return CloneResponse(clone_id=clone_id)
1065
1074
 
1075
+ from core.observability.manifest import record_op_start
1076
+
1066
1077
  _clone_ops[clone_id] = {
1067
1078
  "status": "pending",
1068
1079
  "dest": dest,
@@ -1070,6 +1081,12 @@ async def start_clone(req: CloneRequest):
1070
1081
  "project_name": sanitized,
1071
1082
  "error": None,
1072
1083
  }
1084
+ record_op_start(
1085
+ "setup",
1086
+ "clone",
1087
+ clone_id,
1088
+ attrs={"project_name": sanitized},
1089
+ )
1073
1090
 
1074
1091
  # Spawn clone in background; register pool entry on success.
1075
1092
  asyncio.create_task(
@@ -1186,6 +1203,7 @@ async def _run_clone(
1186
1203
  project creations against the same URL hit the dedupe path in
1187
1204
  :func:`start_clone`.
1188
1205
  """
1206
+ from core.observability.manifest import record_op_end
1189
1207
  from lineage.utils.git import clone_repo_with_progress
1190
1208
 
1191
1209
  _clone_ops[clone_id]["status"] = "running"
@@ -1195,6 +1213,12 @@ async def _run_clone(
1195
1213
  if progress.phase == "error":
1196
1214
  _clone_ops[clone_id]["status"] = "error"
1197
1215
  _clone_ops[clone_id]["error"] = progress.message
1216
+ record_op_end(
1217
+ "clone",
1218
+ clone_id,
1219
+ "error",
1220
+ error=progress.message,
1221
+ )
1198
1222
  return
1199
1223
  _clone_ops[clone_id]["status"] = "complete"
1200
1224
  try:
@@ -1205,9 +1229,11 @@ async def _run_clone(
1205
1229
  url,
1206
1230
  exc,
1207
1231
  )
1232
+ record_op_end("clone", clone_id, "ok")
1208
1233
  except Exception as exc:
1209
1234
  _clone_ops[clone_id]["status"] = "error"
1210
1235
  _clone_ops[clone_id]["error"] = str(exc)
1236
+ record_op_end("clone", clone_id, "error", error=str(exc))
1211
1237
 
1212
1238
 
1213
1239
  @router.get("/clone/{clone_id}/progress")
@@ -4213,6 +4239,33 @@ async def _create_project(
4213
4239
  _preflight_clone_locks: dict[str, asyncio.Lock] = {}
4214
4240
 
4215
4241
 
4242
+ def _preview_preflight_manifest_outcome(
4243
+ last_event: str | None,
4244
+ ) -> tuple[Literal["ok", "error", "cancelled"], str | None]:
4245
+ if last_event is None:
4246
+ return "cancelled", None
4247
+ event_type: str | None = None
4248
+ payload: dict[str, Any] = {}
4249
+ for line in last_event.splitlines():
4250
+ if line.startswith("event: "):
4251
+ event_type = line[len("event: ") :]
4252
+ elif line.startswith("data: "):
4253
+ try:
4254
+ parsed = json.loads(line[len("data: ") :])
4255
+ except json.JSONDecodeError:
4256
+ parsed = {}
4257
+ if isinstance(parsed, dict):
4258
+ payload = parsed
4259
+ if event_type is None:
4260
+ return "cancelled", None
4261
+ if event_type.endswith(".done"):
4262
+ return "ok", None
4263
+ if event_type.endswith(".error"):
4264
+ message = payload.get("message")
4265
+ return "error", message if isinstance(message, str) else None
4266
+ return "cancelled", None
4267
+
4268
+
4216
4269
  async def _run_preflight_sse(
4217
4270
  *,
4218
4271
  adapter: str,
@@ -4701,6 +4754,18 @@ async def start_preview_preflight(req: PreviewPreflightRequest):
4701
4754
  raise HTTPException(status_code=400, detail=str(exc)) from exc
4702
4755
 
4703
4756
  async def generate():
4757
+ from core.observability.manifest import record_op_end, record_op_start
4758
+
4759
+ record_op_start(
4760
+ "setup",
4761
+ "wizard_preflight",
4762
+ req.session_id,
4763
+ attrs={
4764
+ "backend": req.backend,
4765
+ "project_name": sanitized,
4766
+ },
4767
+ )
4768
+ last_event: str | None = None
4704
4769
  tmp_profiles_dir = Path(tempfile.mkdtemp(prefix="typedef-preview-preflight-"))
4705
4770
  try:
4706
4771
  shutil.rmtree(scratch_root, ignore_errors=True)
@@ -4726,8 +4791,16 @@ async def start_preview_preflight(req: PreviewPreflightRequest):
4726
4791
  and req.snowflake_inject_secondary_roles
4727
4792
  ),
4728
4793
  ):
4794
+ last_event = event
4729
4795
  yield event
4730
4796
  finally:
4797
+ outcome, error = _preview_preflight_manifest_outcome(last_event)
4798
+ record_op_end(
4799
+ "wizard_preflight",
4800
+ req.session_id,
4801
+ outcome,
4802
+ error=error,
4803
+ )
4731
4804
  shutil.rmtree(tmp_profiles_dir, ignore_errors=True)
4732
4805
 
4733
4806
  return StreamingResponse(generate(), media_type="text/event-stream")
@@ -25,6 +25,8 @@ 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.observability import Outcome
29
+ from core.observability.manifest import record_op_end, record_op_start
28
30
  from fastapi import APIRouter, Depends, HTTPException, Request
29
31
  from lineage.api.posthog_analytics import (
30
32
  backend_event_insert_id,
@@ -247,6 +249,7 @@ class SyncOperation:
247
249
  # loops cleanly.
248
250
  subscribers: set[Any] = field(default_factory=set)
249
251
  drain_task: Any | None = None
252
+ sync_project_started: set[str] = field(default_factory=set)
250
253
 
251
254
 
252
255
  @dataclass(frozen=True)
@@ -273,6 +276,76 @@ _sync_lock = threading.Lock()
273
276
  _op_state_lock = threading.Lock()
274
277
 
275
278
 
279
+ def _sync_manifest_attrs(op: SyncOperation) -> dict[str, str]:
280
+ return {"workspace_name": op.workspace_name, "project_name": op.project_name}
281
+
282
+
283
+ def _sync_project_manifest_attrs(project_name: str) -> dict[str, str]:
284
+ return {"project_name": project_name}
285
+
286
+
287
+ def _sync_outcome(status: str | None) -> Outcome:
288
+ if status == "error":
289
+ return "error"
290
+ if status == "cancelled":
291
+ return "cancelled"
292
+ return "ok"
293
+
294
+
295
+ def _sync_project_op_id(sync_id: str, project_name: str) -> str:
296
+ return f"{sync_id}/{project_name}"
297
+
298
+
299
+ def _record_sync_start(op: SyncOperation) -> None:
300
+ record_op_start("sync", "sync", op.sync_id, attrs=_sync_manifest_attrs(op))
301
+
302
+
303
+ def _record_sync_end(
304
+ sync_id: str,
305
+ outcome: Outcome,
306
+ *,
307
+ error: str | None = None,
308
+ ) -> None:
309
+ record_op_end("sync", sync_id, outcome, error=error)
310
+
311
+
312
+ def _record_sync_event_end(sync_id: str, event: dict[str, Any]) -> None:
313
+ status = event.get("status")
314
+ outcome = _sync_outcome(str(status) if status is not None else None)
315
+ error = str(event.get("message") or "Sync failed") if outcome == "error" else None
316
+ _record_sync_end(sync_id, outcome, error=error)
317
+
318
+
319
+ def _record_sync_project_start(op: SyncOperation, project_name: str) -> None:
320
+ if project_name in op.sync_project_started:
321
+ return
322
+ op.sync_project_started.add(project_name)
323
+ record_op_start(
324
+ "sync",
325
+ "sync_project",
326
+ _sync_project_op_id(op.sync_id, project_name),
327
+ parent_op_id=op.sync_id,
328
+ attrs=_sync_project_manifest_attrs(project_name),
329
+ )
330
+
331
+
332
+ def _record_sync_project_end(
333
+ op: SyncOperation,
334
+ project_name: str,
335
+ outcome: Outcome,
336
+ *,
337
+ error: str | None = None,
338
+ artifacts: list[str] | None = None,
339
+ ) -> None:
340
+ record_op_end(
341
+ "sync_project",
342
+ _sync_project_op_id(op.sync_id, project_name),
343
+ outcome,
344
+ error=error,
345
+ artifacts=artifacts or [],
346
+ )
347
+
348
+
276
349
  def _get_sync_op(sync_id: str) -> SyncOperation | None:
277
350
  """Read a sync operation from the registry under the module lock."""
278
351
  with _sync_lock:
@@ -580,12 +653,26 @@ async def _drain_op_queue(op: SyncOperation) -> None:
580
653
 
581
654
  if event is not None:
582
655
  evt_status = event.get("status", "running")
656
+ project_name = event.get("project")
657
+ if isinstance(project_name, str) and project_name:
658
+ _record_sync_project_start(op, project_name)
659
+ if event.get("stage") == "project_error":
660
+ _record_sync_project_end(
661
+ op,
662
+ project_name,
663
+ "error",
664
+ error=str(event.get("message") or "sync failed"),
665
+ )
583
666
  # TD-3196: per-project completion inside a workspace build —
584
667
  # persist THIS project's synced commit + build state (keyed on
585
668
  # the event's ``project``), non-terminal so the batch's other
586
669
  # projects + the final L1 pass keep streaming.
587
670
  if event.get("stage") == "project_complete":
588
- _proj = event.get("project") or op.project_name
671
+ _proj = (
672
+ project_name
673
+ if isinstance(project_name, str) and project_name
674
+ else op.project_name
675
+ )
589
676
  try:
590
677
  await asyncio.to_thread(
591
678
  _persist_synced_commit,
@@ -639,6 +726,12 @@ async def _drain_op_queue(op: SyncOperation) -> None:
639
726
  "failed for %s",
640
727
  _proj,
641
728
  )
729
+ _record_sync_project_end(
730
+ op,
731
+ _proj,
732
+ "ok",
733
+ artifacts=[str(v) for v in (event.get("artifacts") or [])],
734
+ )
642
735
  _record_and_broadcast(op, event)
643
736
  last_heartbeat = time.time()
644
737
  continue
@@ -707,6 +800,7 @@ async def _drain_op_queue(op: SyncOperation) -> None:
707
800
  "[desktop:sync] _persist_target_build_state failed for %s",
708
801
  op.project_name,
709
802
  )
803
+ _record_sync_event_end(op.sync_id, event)
710
804
  _record_and_broadcast(op, event)
711
805
  if evt_status in ("completed", "error", "cancelled"):
712
806
  break
@@ -739,6 +833,7 @@ async def _drain_op_queue(op: SyncOperation) -> None:
739
833
  "total": 0,
740
834
  },
741
835
  )
836
+ _record_sync_end(op.sync_id, "cancelled")
742
837
  else:
743
838
  op.status = "error"
744
839
  op.error = f"Sync process exited unexpectedly (code {exit_code})"
@@ -752,6 +847,7 @@ async def _drain_op_queue(op: SyncOperation) -> None:
752
847
  "total": 0,
753
848
  },
754
849
  )
850
+ _record_sync_end(op.sync_id, "error", error=op.error)
755
851
  break
756
852
  finally:
757
853
  # Tell every subscriber the stream is finished — they break
@@ -815,6 +911,7 @@ def _reap_dead_op_if_stale(op: SyncOperation) -> bool:
815
911
  op.sync_id,
816
912
  exc_info=True,
817
913
  )
914
+ _record_sync_end(op.sync_id, "error", error=op.error)
818
915
  _pop_sync_op(op.sync_id)
819
916
  return True
820
917
 
@@ -2353,7 +2450,7 @@ def _maybe_migrate_workspace_graph(
2353
2450
  "stage": "migrate",
2354
2451
  "current": current,
2355
2452
  "total": total,
2356
- "status": "running" if stage != "complete" else "completed",
2453
+ "status": "running",
2357
2454
  "message": f"Upgrading lineage graph: {stage}",
2358
2455
  }
2359
2456
  )
@@ -2370,7 +2467,7 @@ def _maybe_migrate_workspace_graph(
2370
2467
  "stage": "migrate",
2371
2468
  "current": cleared,
2372
2469
  "total": cleared,
2373
- "status": "completed",
2470
+ "status": "running",
2374
2471
  "message": (
2375
2472
  f"Lineage graph upgraded "
2376
2473
  f"({cleared} context entr{'y' if cleared == 1 else 'ies'} "
@@ -2470,12 +2567,25 @@ def _build_one_project(
2470
2567
  from ingest.unified.stages.registry import get_stage_label
2471
2568
  from ingest.unified.stages.types import UnifiedPipelineConfig
2472
2569
 
2473
- config = UnifiedPipelineConfig.from_project_name(
2474
- project_name,
2475
- workspace_name=workspace_name,
2476
- full=full,
2477
- llm_proxy=llm_proxy,
2478
- )
2570
+ try:
2571
+ config = UnifiedPipelineConfig.from_project_name(
2572
+ project_name,
2573
+ workspace_name=workspace_name,
2574
+ full=full,
2575
+ llm_proxy=llm_proxy,
2576
+ )
2577
+ except ValueError as exc:
2578
+ # TD-3823: a project's authored settings can fail integration-config
2579
+ # validation (e.g. airflow.rtif_k_runs outside the reader's ceiling).
2580
+ # This must stay a per-project failure — not caught here, it propagates
2581
+ # past this function's own try/except below (which only wraps
2582
+ # orchestrator.run()) straight out of the per-project loop in
2583
+ # _sync_worker and aborts the WHOLE workspace batch, contradicting this
2584
+ # function's own "per-project failures are non-fatal" contract.
2585
+ log.exception("[%s] config parsing failed", project_name)
2586
+ _capture_sync_failed_analytics(llm_proxy, analytics_context, sync_id, exc)
2587
+ return _ProjectOutcome(status="error", error=str(exc) or type(exc).__name__)
2588
+
2479
2589
  _apply_sync_run_overrides(config, run_overrides or SyncRunOverrides())
2480
2590
  # TD-3196: in a multi-project workspace build, skip the workspace-global
2481
2591
  # L1 concept rebuild on each per-project sync; the coordinator runs one
@@ -2562,6 +2672,7 @@ def _build_one_project(
2562
2672
  "total": total,
2563
2673
  "status": "running",
2564
2674
  "message": get_stage_label(stage_name),
2675
+ "project": project_name,
2565
2676
  **_outer,
2566
2677
  }
2567
2678
  )
@@ -2576,6 +2687,7 @@ def _build_one_project(
2576
2687
  "total": 0,
2577
2688
  "status": "running",
2578
2689
  "message": "Starting sync pipeline",
2690
+ "project": project_name,
2579
2691
  **_outer,
2580
2692
  }
2581
2693
  )
@@ -2913,6 +3025,7 @@ def _sync_worker(
2913
3025
  "total": 0,
2914
3026
  "status": "running",
2915
3027
  "message": f"{spec.name}: {outcome.error or 'sync failed'}",
3028
+ "project": spec.name,
2916
3029
  "outer_label": outer[0],
2917
3030
  "outer_current": outer[1],
2918
3031
  "outer_total": outer[2],
@@ -3523,11 +3636,17 @@ async def start_sync(req: SyncRequest, request: Request):
3523
3636
  started_at=time.time(),
3524
3637
  )
3525
3638
  _sync_ops[sync_id] = op
3639
+ _record_sync_start(op)
3526
3640
 
3527
3641
  # TD-3192: start the process INSIDE the lock so the shutdown
3528
3642
  # snapshot can't observe a registered-but-not-started op (which
3529
3643
  # would have a ``None`` pid and escape termination).
3530
- proc.start()
3644
+ try:
3645
+ proc.start()
3646
+ except Exception as exc:
3647
+ _record_sync_end(sync_id, "error", error=str(exc))
3648
+ _sync_ops.pop(sync_id, None)
3649
+ raise
3531
3650
 
3532
3651
  logger.info(
3533
3652
  "[desktop:sync] Started sync %s for project '%s' (pid=%d)",
@@ -3671,6 +3790,7 @@ async def cancel_sync(sync_id: str):
3671
3790
  pass # nosec B110 — best-effort queue teardown
3672
3791
 
3673
3792
  op.status = "cancelled"
3793
+ _record_sync_end(sync_id, "cancelled")
3674
3794
  logger.info("[desktop:sync] Cancelled sync %s", sync_id)
3675
3795
 
3676
3796
  # Remove from registry after brief delay