sql-code-graph 1.5.0__tar.gz → 1.33.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.
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.claude/agents/architect-planner.md +28 -7
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.claude/agents/developer.md +69 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.claude/agents/sprint-planner.md +5 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.github/workflows/release.yml +9 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.gitignore +2 -0
- sql_code_graph-1.33.0/ARCHITECTURE_REVIEW.md +364 -0
- sql_code_graph-1.5.0/ARCHITECTURE_REVIEW.md → sql_code_graph-1.33.0/ARCHITECTURE_REVIEW_ARCHIVE.md +10 -1
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/CHANGELOG.md +34 -1
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/CLAUDE.md +38 -11
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/PKG-INFO +79 -18
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/README.md +78 -17
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/docs/cli.md +128 -13
- sql_code_graph-1.33.0/docs/getting-started.md +392 -0
- sql_code_graph-1.33.0/docs/releasing-pypi.md +112 -0
- sql_code_graph-1.33.0/plan/measurements/pr2_catalog_load_eval.json +81 -0
- sql_code_graph-1.33.0/plan/measurements/pr3_repo_native_plateau.json +52 -0
- sql_code_graph-1.33.0/plan/measurements/pr4_transform_kinds.json +55 -0
- sql_code_graph-1.33.0/plan/measurements/pr5_extraction_recall_taxonomy.json +118 -0
- sql_code_graph-1.33.0/plan/measurements/sprint_08_changelogs_fullindex.json +37 -0
- sql_code_graph-1.33.0/plan/measurements/sprint_08_fullcorpus_index.json +37 -0
- sql_code_graph-1.33.0/plan/metrics/gain_1.29.0_05c6943.json +1 -0
- sql_code_graph-1.33.0/plan/metrics/gain_1.30.0_2c8ac25.json +29 -0
- sql_code_graph-1.33.0/plan/metrics/gain_1.30.1_26271fc.json +30 -0
- sql_code_graph-1.33.0/plan/metrics/gain_1.31.0_a40c837.json +30 -0
- sql_code_graph-1.33.0/plan/metrics/gain_1.32.0_c1bec3c.json +30 -0
- {sql_code_graph-1.5.0/plan/measurements → sql_code_graph-1.33.0/plan/metrics}/sprint_08_changelogs_fullindex.json +6 -6
- {sql_code_graph-1.5.0/plan/measurements → sql_code_graph-1.33.0/plan/metrics}/sprint_08_fullcorpus_index.json +13 -13
- sql_code_graph-1.33.0/plan/reports/column_coverage_diagnostic.md +220 -0
- sql_code_graph-1.33.0/plan/reports/column_coverage_findings.md +235 -0
- sql_code_graph-1.33.0/plan/reports/dwh_graph_analysis.md +245 -0
- sql_code_graph-1.33.0/plan/reports/dwh_positional_insert_column_blindspot.md +215 -0
- sql_code_graph-1.33.0/plan/reports/feature_acceptance_dwh.md +380 -0
- sql_code_graph-1.33.0/plan/reports/graph_health_sprint_postmortem.md +85 -0
- sql_code_graph-1.33.0/plan/reports/island_lever_live_verification.md +170 -0
- sql_code_graph-1.33.0/plan/reports/issue38_pr2_live_acceptance.md +127 -0
- sql_code_graph-1.33.0/plan/reports/issue38_pr3_live_acceptance.md +75 -0
- sql_code_graph-1.33.0/plan/reports/lineage_identity_sprint_postmortem.md +237 -0
- sql_code_graph-1.33.0/plan/reports/pr_impact_followups_2026-06-14.md +53 -0
- sql_code_graph-1.33.0/plan/reports/v1_14_dialect_query_config_postmortem.md +93 -0
- sql_code_graph-1.33.0/plan/research/coverage_parse_failure_diagnosis.md +138 -0
- sql_code_graph-1.33.0/plan/research/observed_usage_overlay_query_history_tableau.md +550 -0
- sql_code_graph-1.33.0/plan/research/sql_only_coverage_lever_post_pr2.md +344 -0
- sql_code_graph-1.33.0/plan/sprints/ci_tests_pool_flake_fix.md +257 -0
- sql_code_graph-1.33.0/plan/sprints/column_lineage_recall_metric.md +304 -0
- sql_code_graph-1.33.0/plan/sprints/coverage_p1_p3_p4.md +653 -0
- sql_code_graph-1.33.0/plan/sprints/coverage_p1_p5_metric.md +595 -0
- sql_code_graph-1.33.0/plan/sprints/coverage_parse_failures.md +522 -0
- sql_code_graph-1.33.0/plan/sprints/e8_dual_emission.md +155 -0
- sql_code_graph-1.33.0/plan/sprints/fix_backward_self_heal_index_at_sha.md +404 -0
- sql_code_graph-1.33.0/plan/sprints/gain_coverage_metrics.md +402 -0
- sql_code_graph-1.33.0/plan/sprints/graph_health_catalog_and_metrics.md +640 -0
- sql_code_graph-1.33.0/plan/sprints/issue-38-residual-source-extraction.md +391 -0
- sql_code_graph-1.33.0/plan/sprints/issue-38-selects-from-island-lever.md +600 -0
- sql_code_graph-1.33.0/plan/sprints/mcp_server_self_healing.md +546 -0
- sql_code_graph-1.33.0/plan/sprints/positional_insert_clone_blindspot.md +885 -0
- sql_code_graph-1.33.0/plan/sprints/sprint_lineage_identity_and_session_context.md +423 -0
- sql_code_graph-1.33.0/plan/sprints/sprint_postmortem_fixes.md +560 -0
- sql_code_graph-1.33.0/plan/sprints/temp_table_namespacing.md +674 -0
- sql_code_graph-1.33.0/plan/sprints/unfilled_table_impact.md +2023 -0
- sql_code_graph-1.33.0/plan/sprints/v1.14.0_dialect_and_query_config_fixes.md +750 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/pyproject.toml +2 -1
- sql_code_graph-1.33.0/scripts/column_coverage_check.py +356 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/__init__.py +1 -1
- sql_code_graph-1.33.0/src/sqlcg/cli/commands/analyze.py +750 -0
- sql_code_graph-1.33.0/src/sqlcg/cli/commands/catalog.py +313 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/commands/db.py +23 -2
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/commands/find.py +3 -3
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/commands/gain.py +42 -14
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/commands/git.py +22 -3
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/commands/index.py +70 -33
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/commands/install.py +4 -1
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/commands/mcp.py +94 -20
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/commands/reindex.py +134 -2
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/commands/watch.py +10 -2
- sql_code_graph-1.33.0/src/sqlcg/cli/coverage.py +966 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/main.py +2 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/core/config.py +158 -4
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/core/duckdb_backend.py +255 -32
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/core/freshness.py +46 -2
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/core/graph_db.py +49 -7
- sql_code_graph-1.33.0/src/sqlcg/core/noise_match.py +125 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/core/queries.py +3 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/core/queries.sql +62 -3
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/core/schema.cypher +2 -1
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/core/schema.py +1 -1
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/indexer/error_classify.py +47 -1
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/indexer/git_delta.py +18 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/indexer/indexer.py +681 -30
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/indexer/pool.py +12 -2
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/indexer/walker.py +2 -2
- sql_code_graph-1.33.0/src/sqlcg/lineage/aggregator.py +256 -0
- sql_code_graph-1.33.0/src/sqlcg/parsers/ansi_parser.py +812 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/parsers/base.py +722 -68
- sql_code_graph-1.33.0/src/sqlcg/parsers/snowflake_parser.py +976 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/server/models.py +202 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/server/noise_filter.py +26 -34
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/server/read_client.py +59 -2
- sql_code_graph-1.33.0/src/sqlcg/server/selfheal.py +209 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/server/server.py +267 -10
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/server/skill.py +12 -1
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/server/tools.py +1084 -83
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/server/writer.py +12 -14
- sql_code_graph-1.33.0/src/sqlcg/utils/ignore.py +52 -0
- sql_code_graph-1.33.0/tests/conftest.py +41 -0
- sql_code_graph-1.33.0/tests/e2e/test_empty_impact_cli_e2e.py +161 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/e2e/test_golden_lineage.py +190 -31
- sql_code_graph-1.33.0/tests/e2e/test_pr_impact_cli_e2e.py +235 -0
- sql_code_graph-1.33.0/tests/e2e/test_selfheal_e2e.py +394 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/duckdb_parity/kuzu_reference.json +1 -1
- sql_code_graph-1.33.0/tests/integration/snowflake/test_qualify_bare_tables_command_guard_integration.py +179 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_T35_external_consumers.py +12 -4
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_anchor_tools.py +14 -4
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_backfill_impact_consistency.py +102 -27
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_bare_column_cte_lineage.py +41 -11
- sql_code_graph-1.33.0/tests/integration/test_catalog_kind_upgrade.py +323 -0
- sql_code_graph-1.33.0/tests/integration/test_catalog_load_integration.py +528 -0
- sql_code_graph-1.33.0/tests/integration/test_cli_index_clear_before_rebuild.py +210 -0
- sql_code_graph-1.33.0/tests/integration/test_column_coverage_patterns.py +858 -0
- sql_code_graph-1.33.0/tests/integration/test_coverage_metrics_integration.py +702 -0
- sql_code_graph-1.33.0/tests/integration/test_cte_key_namespacing_integration.py +252 -0
- sql_code_graph-1.33.0/tests/integration/test_empty_impact_blast_radius.py +490 -0
- sql_code_graph-1.33.0/tests/integration/test_empty_index_rollback_guard.py +235 -0
- sql_code_graph-1.33.0/tests/integration/test_gating_join_retrofit.py +317 -0
- sql_code_graph-1.33.0/tests/integration/test_identity_counters_integration.py +281 -0
- sql_code_graph-1.33.0/tests/integration/test_index_degraded_files_metric.py +148 -0
- sql_code_graph-1.33.0/tests/integration/test_index_filter_node_exclusion.py +264 -0
- sql_code_graph-1.33.0/tests/integration/test_issue38_cte_insert_regression.py +185 -0
- sql_code_graph-1.33.0/tests/integration/test_key_normalization_chokepoint.py +200 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_parse_diagnostics.py +10 -3
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_pr2_source_location.py +5 -2
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_pr3_kind_tagging.py +57 -16
- sql_code_graph-1.33.0/tests/integration/test_pr_impact_integration.py +585 -0
- sql_code_graph-1.33.0/tests/integration/test_qualify_failed_persist.py +175 -0
- sql_code_graph-1.33.0/tests/integration/test_repo_relative_cte_namespaces.py +161 -0
- sql_code_graph-1.33.0/tests/integration/test_resolvable_write_col_edges_integration.py +220 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_resync.py +127 -0
- sql_code_graph-1.33.0/tests/integration/test_selects_from_completeness.py +405 -0
- sql_code_graph-1.33.0/tests/integration/test_selects_from_cte_body_source.py +320 -0
- sql_code_graph-1.33.0/tests/integration/test_selects_from_subscope_source.py +389 -0
- sql_code_graph-1.33.0/tests/integration/test_skip_counts_integration.py +252 -0
- sql_code_graph-1.33.0/tests/integration/test_temp_table_namespacing.py +853 -0
- sql_code_graph-1.33.0/tests/integration/test_tool_version_stamp_integration.py +164 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_union_cte_star_recall_guard.py +62 -16
- sql_code_graph-1.33.0/tests/integration/test_usage_derived_catalog.py +311 -0
- sql_code_graph-1.33.0/tests/integration/test_use_schema_session_context_integration.py +141 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_user_surface_recall_guard.py +49 -56
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_v141_surface_guards.py +21 -6
- sql_code_graph-1.33.0/tests/integration/test_v1_14_0_dialect_and_query_config_fixes.py +771 -0
- sql_code_graph-1.33.0/tests/integration/test_view_kind_in_graph.py +39 -0
- sql_code_graph-1.33.0/tests/integration/test_write_memory_ceiling.py +201 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E12/test_e12.py +1 -1
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E16/test_e16.py +2 -2
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E27/test_e27.py +1 -1
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/test_plan_review_gates.py +3 -3
- sql_code_graph-1.33.0/tests/unit/snowflake/test_qualify_bare_tables_command_guard.py +173 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_F2_install_skill.py +10 -4
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_F2_skill_render.py +19 -10
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_F2_uninstall_skill.py +1 -1
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_analyze_case_fold.py +65 -30
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_base_parser.py +22 -15
- sql_code_graph-1.33.0/tests/unit/test_catalog_csv_parsing.py +392 -0
- sql_code_graph-1.33.0/tests/unit/test_catalog_missing_warning.py +219 -0
- sql_code_graph-1.33.0/tests/unit/test_cli_doc_flag_staleness.py +283 -0
- sql_code_graph-1.33.0/tests/unit/test_clone_positional_insert_blindspot.py +279 -0
- sql_code_graph-1.33.0/tests/unit/test_coverage_metrics.py +360 -0
- sql_code_graph-1.33.0/tests/unit/test_cte_key_namespacing.py +251 -0
- sql_code_graph-1.33.0/tests/unit/test_cte_source_gap_metric.py +273 -0
- sql_code_graph-1.33.0/tests/unit/test_db_info_coverage.py +111 -0
- sql_code_graph-1.33.0/tests/unit/test_db_path_isolation_fixture.py +60 -0
- sql_code_graph-1.33.0/tests/unit/test_doc_links.py +83 -0
- sql_code_graph-1.33.0/tests/unit/test_doc_markdown_link_existence.py +151 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_duckdb_backend.py +39 -0
- sql_code_graph-1.33.0/tests/unit/test_e5_view_alias_resolution.py +189 -0
- sql_code_graph-1.33.0/tests/unit/test_e8_dual_emission.py +299 -0
- sql_code_graph-1.33.0/tests/unit/test_e8_temp_chain_key_mismatch.py +365 -0
- sql_code_graph-1.33.0/tests/unit/test_empty_propagation_unit.py +328 -0
- sql_code_graph-1.33.0/tests/unit/test_extract_select_output_columns.py +169 -0
- sql_code_graph-1.33.0/tests/unit/test_file_ignore_defaults.py +115 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_find_cmd.py +24 -8
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_firstuser_findings.py +19 -3
- sql_code_graph-1.33.0/tests/unit/test_gain_coverage.py +168 -0
- sql_code_graph-1.33.0/tests/unit/test_gating_join_field_docstrings.py +66 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_git_delta.py +23 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_git_hooks.py +81 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_graph_backend.py +3 -0
- sql_code_graph-1.33.0/tests/unit/test_has_column_precedence_upsert.py +162 -0
- sql_code_graph-1.33.0/tests/unit/test_hook_reindex_detach.py +481 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_hygiene_config_warning.py +15 -4
- sql_code_graph-1.33.0/tests/unit/test_identity_counters.py +295 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_include_working_tree.py +4 -1
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_index_cmd.py +20 -2
- sql_code_graph-1.33.0/tests/unit/test_index_filter_config.py +76 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_index_flags.py +16 -2
- sql_code_graph-1.33.0/tests/unit/test_index_summary_degraded_metric.py +329 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_install.py +8 -1
- sql_code_graph-1.33.0/tests/unit/test_issue_63_readonly_lock.py +153 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_mcp_control.py +151 -14
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_noise_filter.py +10 -3
- sql_code_graph-1.33.0/tests/unit/test_normalize_keys.py +353 -0
- sql_code_graph-1.33.0/tests/unit/test_parse_failed_classification.py +174 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_perf_scaling_guard.py +86 -2
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_pr07_observability.py +35 -10
- sql_code_graph-1.33.0/tests/unit/test_pr6_execute_immediate_unwrap.py +197 -0
- sql_code_graph-1.33.0/tests/unit/test_pr_impact_unit.py +499 -0
- sql_code_graph-1.33.0/tests/unit/test_qualify_failed_unit.py +157 -0
- sql_code_graph-1.33.0/tests/unit/test_repo_relative_cte_namespaces.py +247 -0
- sql_code_graph-1.33.0/tests/unit/test_resolvable_write_col_edges_unit.py +261 -0
- sql_code_graph-1.33.0/tests/unit/test_selects_from_completeness_unit.py +159 -0
- sql_code_graph-1.33.0/tests/unit/test_selfheal_detector.py +162 -0
- sql_code_graph-1.33.0/tests/unit/test_selfheal_pr1_messages.py +133 -0
- sql_code_graph-1.33.0/tests/unit/test_selfheal_reexec.py +357 -0
- sql_code_graph-1.33.0/tests/unit/test_selfheal_watcher.py +280 -0
- sql_code_graph-1.33.0/tests/unit/test_skip_counts_persistence.py +162 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_star_schema_unit.py +10 -5
- sql_code_graph-1.33.0/tests/unit/test_temp_table_namespacing.py +797 -0
- sql_code_graph-1.33.0/tests/unit/test_tool_version_stamp.py +405 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_tools_hints.py +22 -6
- sql_code_graph-1.33.0/tests/unit/test_transform_kind_classification.py +265 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_uninstall.py +67 -6
- sql_code_graph-1.33.0/tests/unit/test_unknown_sentinel_skip.py +184 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_upsert_batch_invariant.py +60 -0
- sql_code_graph-1.33.0/tests/unit/test_use_schema_session_context.py +446 -0
- sql_code_graph-1.33.0/tests/unit/test_view_classification.py +82 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_walker.py +66 -0
- sql_code_graph-1.33.0/tests/unit/test_worker_error_classification.py +101 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/uv.lock +1 -1
- sql_code_graph-1.5.0/src/sqlcg/cli/commands/analyze.py +0 -345
- sql_code_graph-1.5.0/src/sqlcg/lineage/aggregator.py +0 -86
- sql_code_graph-1.5.0/src/sqlcg/parsers/ansi_parser.py +0 -462
- sql_code_graph-1.5.0/src/sqlcg/parsers/snowflake_parser.py +0 -351
- sql_code_graph-1.5.0/src/sqlcg/utils/ignore.py +0 -38
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.claude/agents/api-documenter.md +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.claude/agents/architect-reviewer.md +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.claude/agents/code-reviewer.md +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.claude/agents/plan-reviewer.md +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.github/workflows/benchmark.yml +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.github/workflows/e2e-tests.yml +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.github/workflows/test.yml +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.pre-commit-config.yaml +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/.sqlcgignore +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/docs/AIRBNB_PARSE_REPORT.md +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/e2e_firstuser_report.md +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/e2e_run_20260528_101413.output +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/main.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/plan/WORKFLOW.md +0 -0
- {sql_code_graph-1.5.0/plan/measurements → sql_code_graph-1.33.0/plan/metrics}/schema_comparison_with_schema.json +0 -0
- {sql_code_graph-1.5.0/plan/measurements → sql_code_graph-1.33.0/plan/metrics}/schema_comparison_without_schema.json +0 -0
- {sql_code_graph-1.5.0/plan/measurements → sql_code_graph-1.33.0/plan/metrics}/sprint_pool_300s_plan.json +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/reports}/sprint_03_v0.3.1_postmortem.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/reports}/sprint_3.1_postmortem.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/research}/blueprint.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/research}/investigation_e5_e4.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/research}/parse_diagnostics.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/research}/parsing_errors_experiment.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/research}/snowflake_en_test_suite.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/research}/sqlcg.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/bundle_claude_skill.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/diff-impact-producer-file.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/feature_34_unused_presentation_segregation.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/feature_35_external_downstream_injection.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/feature_F2_bundle_claude_skill.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/feature_kuzu_to_duckdb_migration.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/fix_downstream_sink_location.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/fix_dynamic_table_parsing.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/fix_expand_qualify_perf.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/fix_firstuser_findings.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/fix_issue29_live_test_followups.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/fix_schema_case_mismatch.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/hygiene_config_path_and_survivors.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/issue-38-backfill-cte-bridge.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/living_codebase_resync.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_01.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_01_deployment_pypi.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_02.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_02_v0.3.0_core.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_03.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_04_column_lineage.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_04_column_lineage_fix.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_05_star_resolution.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_06_lineage_coverage.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_07_open_ecodes.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_07_perf_and_live_test.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_08_perf_upsert.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_09_lineage_coverage.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_10_anchor_tools.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_11_v1.0.2_bugfix.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_12_v1.1.0.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/sprint_13_v1.1.0_cluster_b.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/trust_layer.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/v1.1.0_cluster_b_provenance_trust.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/v1.1.0_live_graph_freshness.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/v1.1.1_batch_upsert_perf.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/v1_1_2_bugfix.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/v1_1_3_union_cte_star.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/v1_2_0_read_proxy.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/v1_2_1_bugfix.md +0 -0
- {sql_code_graph-1.5.0/plan → sql_code_graph-1.33.0/plan/sprints}/version-parity-and-restart.md +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/profile.html +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/pyrightconfig.json +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/scripts/collect_parse_errors.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/scripts/generate_cli_docs.sh +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/__main__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/commands/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/commands/report.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/cli/commands/uninstall.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/core/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/core/jobs.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/core/queries.cypher +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/indexer/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/indexer/dbt_adapter.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/indexer/watcher.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/lineage/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/lineage/schema_resolver.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/metrics/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/metrics/store.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/parsers/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/parsers/bigquery_parser.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/parsers/postgres_parser.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/parsers/registry.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/parsers/tsql_parser.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/server/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/server/control.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/server/exceptions.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/utils/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/utils/hashing.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/src/sqlcg/utils/logging.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/adversarial/200_join.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/adversarial/500_union.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/bench_indexer.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/conftest.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/golden_corpus/snowflake/case_normalization.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/golden_corpus/snowflake/colon_cast.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/golden_corpus/snowflake/colon_reserved_word.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/golden_corpus/snowflake/copy_into.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/golden_corpus/snowflake/create_procedure.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/golden_corpus/snowflake/identifier_dynamic.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/golden_corpus/snowflake/lateral_flatten.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/golden_corpus/snowflake/qualify.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/golden_corpus/snowflake/scripting_block.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/golden_corpus/snowflake/three_part.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/tpch/q01.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/tpch/q02.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/tpch/q03.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/tpch/q04.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/benchmarks/tpch/q05.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/e2e/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/e2e/conftest.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/e2e/test_F2_skill_install_e2e.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/e2e/test_airbnb_e2e.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/e2e/test_cli_index.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/e2e/test_git_hook_install.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/e2e/test_mcp_lifecycle.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/e2e/test_mcp_tools.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/e2e/test_parse_diagnostics_cli.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/e2e/test_star_resolution_e2e.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/e2e/test_watch.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/airbnb/dim_hosts_cleansed.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/airbnb/dim_listings_cleansed.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/airbnb/fct_reviews.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/airbnb/mart_fullmoon_reviews.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/airbnb/raw_hosts.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/airbnb/raw_listings.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/airbnb/raw_reviews.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/airbnb/src_hosts.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/airbnb/src_listings.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/airbnb/src_reviews.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/bigquery/.gitkeep +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/jaffle_shop/customers.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/jaffle_shop/orders.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/jaffle_shop/raw_orders.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/snowflake/base_tables.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/snowflake/reports.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/snowflake/views.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/star_corpus/ddl_src.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/star_corpus/ddl_tgt.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/star_corpus/etl_alias_star.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/star_corpus/etl_star.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/synthetic/base_tables.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/synthetic/reports.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/fixtures/synthetic/views.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/snowflake/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/snowflake/test_insert_select.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_T34_presentation_segregation.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_analyze_case_fold.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_bulk_upsert.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_case_split_seed_regression.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_column_lineage_e2e.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_cross_file_lineage.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_cte_recall_guard.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_cte_schema_alias_guard.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_cte_source_node_invariant.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_dialect_auto_resolution.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_dialect_matrix.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_duckdb_parity.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_e36_xfile_regression_guard.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_freshness_mcp.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_hygiene_config_root_reconciliation.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_indexer_batching.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_indexer_commits.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_indexer_to_graph.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_live_anchors.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_mvcc_rebuild.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_pr1_confidence_reason.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_read_via_server.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_readonly_under_lock.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_reindex_via_server.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_single_writer_queue.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_star_resolution.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/integration/test_temp_table_lineage.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/perf/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/perf/test_perf.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E10/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E11/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E12/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E12/e12_json_path.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E12/e12_lateral_flatten.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E13/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E14/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E15/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E16/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E16/e16_merge.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E16/e16_merge_delete.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E17/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E18/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E18/e18_decode.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E18/e18_iff_decode.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E18/e18_nvl2.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E18/test_e18.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E19/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E2/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E2/e2_expr_alias.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E2/e2_function_alias.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E2/e2_multiply_alias.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E2/test_e2.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E20/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E21/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E21/e21_alias_forward_ref.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E21/e21_three_level_chain.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E21/test_e21.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E22/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E23/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E23/e23_stored_proc.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E23/e23_stored_proc_multi.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E23/test_e23.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E24/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E25/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E25/e25_cross_db.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E25/e25_two_part.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E25/test_e25.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E25/test_e25_full_id.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E26/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E27/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E27/e27_nested_udf.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E27/e27_udf.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E28/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E29/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E3/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E3/e3_alter_table.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E3/e3_create_sequence.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E3/e3_ddl_only.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E3/test_e3.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E30/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E31/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E32/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E33/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E34/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E35/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E36/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E36/e36_temp_multi_use.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E36/e36_temp_table.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E36/test_e36.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E36/test_e36_xfile.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E37/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E38/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E4/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E4/e4_execute_immediate.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E4/e4_if_not_exists.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E4/e4_unexpected_token.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E4/e4_unpivot.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E4/test_e4.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E5/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E5/e5_cte_missing_source.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E5/e5_multi_cte.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E5/e5_nested_cte.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E5/test_e5.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E5/test_e5_cte_projection.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E8/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E8/e8_dynamic_sources.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E8/e8_seq_nextval.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E8/e8_uuid.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E8/test_e8.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E9/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E_aggregates/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E_aggregates/fixture_sum_absent_cross_schema.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E_aggregates/fixture_sum_case_when.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E_aggregates/fixture_sum_present_source.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E_aggregates/test_e_aggregates.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E_date_functions/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E_date_functions/fixture_date_aliased.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E_date_functions/fixture_date_unaliased.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E_date_functions/fixture_datediff_unaliased.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E_date_functions/fixture_year_unaliased.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/E_date_functions/test_e_date_functions.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/README.md +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/anchors/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/anchors/fixture_etl.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/anchors/fixture_omloopsnelheid.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/anchors/fixture_semantic.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/anchors/fixture_source.sql +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/anchors/test_anchor_ma_aantal_op_order.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/anchors/test_anchor_omloopsnelheid.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/snowflake/conftest.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/snowflake/__init__.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/snowflake/test_scripting_noise.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_BugB_escalation_uses_init_path.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_BugC_hook_upgrade.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_T09_01_qualify_once.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_T09_02_ddl_skip.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_T09_04_subprocess_isolate.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_T09_06_log_verbosity.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_T35_config_external_consumers.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_aggregator.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_aggregator_skip.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_branch_monitor.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_bulk_upsert_invariant.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_canonical_target_resolution.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_cli.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_cli_help.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_closure_depth.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_column_lineage_wiring.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_config.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_data_models.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_db_info.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_dominant_cause.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_duckdb_backend_shared.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_freshness_helper.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_gain_ratio.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_git_hooks_notify.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_graph_completeness_invariant.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_hard_kill_pool.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_index_progress.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_indexer_progress.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_indexer_quality.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_install_message.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_jobs.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_judgement.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_lineage_conversion.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_literal_column_skip.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_mcp_best_practices.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_mcp_stdio_smoke.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_metrics.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_parse_file_dependency_filter.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_parse_quality.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_parser.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_queries_loader.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_read_client.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_resolve_pass2_passes_dependency_filter.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_schema_resolver.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_server.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_snowflake_strip_alter_set_tag.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_sprint_06_t04_t05.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_star_resolution_unit.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_submit_feedback.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_subprocess_isolate.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_t02_expression_name_extraction.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_t03_ddl_skip.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_timeout_cancel.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_tools_warnings.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_unqualified_fallback.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_version_parity.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_watcher.py +0 -0
- {sql_code_graph-1.5.0 → sql_code_graph-1.33.0}/tests/unit/test_writer_queue.py +0 -0
|
@@ -91,6 +91,12 @@ Before starting work, call `list_graph_stats_tool` once.
|
|
|
91
91
|
- Unit tests: ...
|
|
92
92
|
- Integration tests: ...
|
|
93
93
|
|
|
94
|
+
> Describe each test by the **behavior** it verifies, never by a task/case code
|
|
95
|
+
> (`TC1`, `T-03`, …). The developer names tests `test_<unit>_<scenario>_<expected>`
|
|
96
|
+
> and links this plan in the docstring — see *Test naming* in
|
|
97
|
+
> [`developer.md`](.claude/agents/developer.md). Do not seed opaque codes the
|
|
98
|
+
> developer will copy into test names.
|
|
99
|
+
|
|
94
100
|
## Acceptance Criteria
|
|
95
101
|
- [ ] Criterion 1
|
|
96
102
|
- [ ] Criterion 2
|
|
@@ -139,14 +145,29 @@ code-reviewer's job).
|
|
|
139
145
|
|
|
140
146
|
Steps:
|
|
141
147
|
|
|
142
|
-
1. Read `git diff main...HEAD` and the plan side-by-side.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
148
|
+
1. Read `git diff main...HEAD` and the plan side-by-side. **The developer's
|
|
149
|
+
handoff/PR body is a claim, not evidence — never quote it as verification.**
|
|
150
|
+
Presence of code that "looks like" a step is not compliance; trace what the
|
|
151
|
+
code DOES.
|
|
152
|
+
2. For each implementation step in the plan, verify it was addressed and record
|
|
153
|
+
the **evidence**: the diff file:line that implements it, and the test that
|
|
154
|
+
pins it. A step with no citable diff hunk or no pinning test is not PASS.
|
|
155
|
+
3. For each plan **acceptance criterion**, run its test yourself (or execute the
|
|
156
|
+
criterion's repro directly) and record the observed output. Check the test
|
|
157
|
+
asserts the criterion itself, not adjacent behavior — and that fixtures model
|
|
158
|
+
the live configuration the criterion will face (schema aliases, USE SCHEMA
|
|
159
|
+
context, real-corpus statement shapes), not a minimal idealized case. A
|
|
160
|
+
criterion whose test passes on a fixture that cannot exhibit the failure mode
|
|
161
|
+
is UNVERIFIED, not PASS (this is how the v1.21.0 dual-write shipped green).
|
|
162
|
+
4. Append a `## Plan Compliance — YYYY-MM-DD` section to `plan/<feature>.md`,
|
|
163
|
+
one row per step/criterion: PASS with evidence (diff hunk + test + observed
|
|
164
|
+
output), FAIL with reason, or UNVERIFIED with what's missing.
|
|
165
|
+
- `PASS` — every row PASS (deviations are documented)
|
|
146
166
|
- `FAIL — <step>: <reason>` — a step was skipped or implemented contrary
|
|
147
|
-
to the plan
|
|
148
|
-
|
|
149
|
-
|
|
167
|
+
to the plan; UNVERIFIED rows also block an overall PASS
|
|
168
|
+
5. Commit the compliance result.
|
|
169
|
+
6. If `FAIL` (or any UNVERIFIED), tell the developer what to fix before code
|
|
170
|
+
review starts.
|
|
150
171
|
|
|
151
172
|
## MUST NOT
|
|
152
173
|
|
|
@@ -78,6 +78,24 @@ Before starting work, call `list_graph_stats_tool` once.
|
|
|
78
78
|
13. Say **"finished"** — this signals the idle architect-planner to perform the
|
|
79
79
|
plan-compliance check before the PR moves to code review.
|
|
80
80
|
|
|
81
|
+
## Report facts, not verdicts
|
|
82
|
+
|
|
83
|
+
Your handoff, PR body, and final report state **what is** — never whether it
|
|
84
|
+
satisfies the plan. That judgment belongs to the compliance check and the
|
|
85
|
+
shepherd, who verify against the diff, not your summary.
|
|
86
|
+
|
|
87
|
+
- DO report: files changed with file:line, exact test counts (collected/passed/
|
|
88
|
+
failed/skipped), commands run with their observable output, deviations with
|
|
89
|
+
their mechanism, anything NOT done or NOT verified.
|
|
90
|
+
- DO NOT write: "implemented as planned", "all acceptance criteria met",
|
|
91
|
+
"no deviations" as a conclusion you reasoned to, "plan compliant", or any
|
|
92
|
+
equivalent verdict. If you believe a criterion is met, cite the test name and
|
|
93
|
+
its asserted output instead — the evidence, not the judgment.
|
|
94
|
+
- A claim of "pre-existing failure" requires proof in the report: the exact
|
|
95
|
+
command run on clean master and its output. No proof → don't make the claim.
|
|
96
|
+
- Never record decisions in progress.txt that were not explicitly made by the
|
|
97
|
+
user or the shepherd in this session.
|
|
98
|
+
|
|
81
99
|
## PR Review Iteration
|
|
82
100
|
|
|
83
101
|
When addressing review comments:
|
|
@@ -115,6 +133,57 @@ Run through this before marking work done:
|
|
|
115
133
|
feature produces observable output (e.g., non-empty list, specific field value). Tests
|
|
116
134
|
that only cover exception handling or log messages are insufficient on their own.
|
|
117
135
|
|
|
136
|
+
## Test naming — describe behavior, link the doc
|
|
137
|
+
|
|
138
|
+
Tests are read far more often than the plan that spawned them. A name like
|
|
139
|
+
`test_tc2_*` or `test_T35_DOWN_1_*` is meaningless once the sprint closes — the
|
|
140
|
+
reader has to go find the plan to learn what broke. Use a name that stands on its
|
|
141
|
+
own and a docstring that links the governing doc.
|
|
142
|
+
|
|
143
|
+
**Convention (standard three-part name — nothing to install):**
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
test_<unit>_<scenario>_<expected>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Forbidden: opaque plan-internal codes in the test name.** These families are all
|
|
150
|
+
ephemeral identifiers that mean nothing outside their plan — never use them as the
|
|
151
|
+
name:
|
|
152
|
+
|
|
153
|
+
| Family | Example | Origin |
|
|
154
|
+
|--------|---------|--------|
|
|
155
|
+
| `TC<n>` | `test_tc6b_*` | "test case" numbers in a plan |
|
|
156
|
+
| `T<nn>` task IDs | `test_T01_*`, `test_T09_06_*` | sprint task IDs |
|
|
157
|
+
| `T34`/`T35` (+ `CFG`/`DIFF`/`DOWN`/`IDX` sub-codes) | `test_T35_DOWN_1_*` | feature task IDs |
|
|
158
|
+
| `F<n>` feature IDs | `test_F2_*` | feature IDs |
|
|
159
|
+
| `gap<n>` / `issue<n>` | `test_gap3_*`, `test_issue38_*` | blueprint-gap / issue numbers |
|
|
160
|
+
|
|
161
|
+
The code goes in the **docstring**, not the name. Link the plan doc (markdown link,
|
|
162
|
+
real path — see the link convention in `ARCHITECTURE_REVIEW.md`) so the reader can
|
|
163
|
+
jump to the rationale:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
def test_filtered_surface_recall_physical_sources(indexed_db):
|
|
167
|
+
"""Physical source tables survive the default analyze filter.
|
|
168
|
+
|
|
169
|
+
Guards the #40 user-surface recall plan
|
|
170
|
+
([plan doc](plan/sprints/v1_2_1_bugfix.md)).
|
|
171
|
+
"""
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Two exceptions** (these codes are durable, documented vocabulary — keep the code,
|
|
175
|
+
just add the doc-link docstring):
|
|
176
|
+
- The **`E{n}` lineage-failure taxonomy** (`test_e27_*` etc.) — `E{n}` *is* the
|
|
177
|
+
shared name; renaming it loses meaning. Link the taxonomy doc in the docstring.
|
|
178
|
+
- **CLAUDE.md-pinned regression guards** (`test_T09_01_qualify_once.py`,
|
|
179
|
+
`*_invariant.py`) are referenced *by filename* in `CLAUDE.md`. Do not rename the
|
|
180
|
+
file without updating CLAUDE.md in lockstep; prefer leaving the filename and giving
|
|
181
|
+
the test functions behavioral names + docstrings.
|
|
182
|
+
|
|
183
|
+
**Rename-on-touch, not big-bang.** Do not open a PR that mass-renames existing tests.
|
|
184
|
+
When you next implement in or edit a test (or its area), bring the tests you touch up
|
|
185
|
+
to this convention as part of that change. New tests follow it from the start.
|
|
186
|
+
|
|
118
187
|
## Performance invariants — MUST preserve
|
|
119
188
|
|
|
120
189
|
`src/sqlcg/parsers/base.py` contains hard-won performance fixes. Before touching this
|
|
@@ -168,6 +168,11 @@ critical finding before shipping. Place it in `## Test Strategy` under
|
|
|
168
168
|
- Include a failure message that names the original regression
|
|
169
169
|
(e.g., `"Column lineage edges must be non-zero — guards against v0.3.0 regression"`)
|
|
170
170
|
|
|
171
|
+
> Refer to tests by the **behavior** they verify, not by a task/case code (`TC1`,
|
|
172
|
+
> `T-03`, …). The developer names tests `test_<unit>_<scenario>_<expected>` and links
|
|
173
|
+
> the plan in the docstring — see *Test naming* in
|
|
174
|
+
> [`developer.md`](.claude/agents/developer.md). Don't seed codes into "Tests to add".
|
|
175
|
+
|
|
171
176
|
## Sprint-Level Acceptance Criteria — Always Required
|
|
172
177
|
|
|
173
178
|
End every plan with `## Acceptance Criteria (sprint-level)` — a checklist of
|
|
@@ -4,6 +4,11 @@ on:
|
|
|
4
4
|
push:
|
|
5
5
|
tags: ["v*"]
|
|
6
6
|
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
ref:
|
|
9
|
+
description: "Tag or commit to build and publish (e.g. v1.6.0). Leave blank to use the current HEAD of the default branch."
|
|
10
|
+
required: false
|
|
11
|
+
default: ""
|
|
7
12
|
|
|
8
13
|
permissions:
|
|
9
14
|
contents: write
|
|
@@ -14,6 +19,8 @@ jobs:
|
|
|
14
19
|
runs-on: ubuntu-latest
|
|
15
20
|
steps:
|
|
16
21
|
- uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
ref: ${{ github.event.inputs.ref || github.ref }}
|
|
17
24
|
- uses: astral-sh/setup-uv@v4
|
|
18
25
|
- run: uv sync --all-extras
|
|
19
26
|
- run: uv run pytest tests/unit tests/integration -v --tb=short
|
|
@@ -26,6 +33,8 @@ jobs:
|
|
|
26
33
|
environment: pypi
|
|
27
34
|
steps:
|
|
28
35
|
- uses: actions/checkout@v4
|
|
36
|
+
with:
|
|
37
|
+
ref: ${{ github.event.inputs.ref || github.ref }}
|
|
29
38
|
- uses: astral-sh/setup-uv@v4
|
|
30
39
|
- run: uv build
|
|
31
40
|
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -65,6 +65,8 @@ tests/e2e/test_dwh_schema_e2e.py
|
|
|
65
65
|
.claude/progress.txt
|
|
66
66
|
columns.csv
|
|
67
67
|
results_*.json
|
|
68
|
+
# Large scratch data export (811k rows) — never commit
|
|
69
|
+
anomaly.csv
|
|
68
70
|
|
|
69
71
|
# Local-only golden lineage ground truth — names private DWH columns
|
|
70
72
|
tests/e2e/golden_lineage.yaml
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# Architecture Review — sql-code-graph (`sqlcg`)
|
|
2
|
+
|
|
3
|
+
**Current as of:** v1.25.0 · DuckDB backend · Python 3.12
|
|
4
|
+
**Status:** living document — describes the system as it stands today.
|
|
5
|
+
**History:** the pre-1.4 blueprint review, PR/issue reviews, and every sprint
|
|
6
|
+
postmortem (§1–20 + the Kuzu→DuckDB migration review) are preserved verbatim in
|
|
7
|
+
[`ARCHITECTURE_REVIEW_ARCHIVE.md`](ARCHITECTURE_REVIEW_ARCHIVE.md). This file was
|
|
8
|
+
overhauled on 2026-06-08 to drop content made stale by the DuckDB migration and the
|
|
9
|
+
v1.x releases. See [§8 History](#8-history) for the timeline.
|
|
10
|
+
|
|
11
|
+
> **Link convention.** Links here use real repo paths (e.g.
|
|
12
|
+
> [`base.py`](src/sqlcg/parsers/base.py)) so a rename breaks the link *visibly*. The
|
|
13
|
+
> guard test [`test_doc_links.py`](tests/unit/test_doc_links.py) fails CI if any link
|
|
14
|
+
> in a maintained doc points at a missing file.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 1. What `sqlcg` is
|
|
19
|
+
|
|
20
|
+
`sqlcg` indexes a corpus of `.sql` files into an embedded **DuckDB** graph and answers
|
|
21
|
+
**lineage** questions over it — "what feeds this column?", "what breaks if I change this
|
|
22
|
+
table?", "which views are downstream?". It parses SQL with `sqlglot`, persists tables /
|
|
23
|
+
columns / queries / lineage edges as graph nodes and relationships, and exposes the graph
|
|
24
|
+
two ways: a `typer` **CLI** (`sqlcg …`) and an **MCP server** for use from Claude.
|
|
25
|
+
|
|
26
|
+
It targets both ends of a scale spectrum — a ~20-file ETL repo and a 1,000–1,600 file
|
|
27
|
+
data warehouse — from the same zero-config `sqlcg index ./sql` entry point. The scale
|
|
28
|
+
rules and performance budget live in [`CLAUDE.md`](CLAUDE.md); the invariants that enforce
|
|
29
|
+
them are summarised in [§4](#4-performance-invariants).
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 2. Component map
|
|
34
|
+
|
|
35
|
+
```mermaid
|
|
36
|
+
flowchart TD
|
|
37
|
+
subgraph entry[Entry points]
|
|
38
|
+
CLI["CLI — typer<br/>cli/main.py"]
|
|
39
|
+
MCP["MCP server — FastMCP<br/>server/server.py + tools.py"]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
subgraph index[Indexing pipeline]
|
|
43
|
+
WALK["walker — find .sql"]
|
|
44
|
+
POOL["pool — spawn workers<br/>+ hard-kill timeouts"]
|
|
45
|
+
PARSE["parsers — sqlglot<br/>per dialect"]
|
|
46
|
+
AGG["aggregator — 2-pass<br/>cross-file lineage"]
|
|
47
|
+
IDX["indexer — orchestrate<br/>+ batched bulk upsert"]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
subgraph store[Graph store]
|
|
51
|
+
BACKEND[("DuckDBBackend<br/>7 node / 12 edge tables")]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
subgraph readpath[Read / query]
|
|
55
|
+
ANALYZE["analyze / find queries<br/>recursive-CTE traversal"]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
subgraph live[Liveness]
|
|
59
|
+
FRESH["freshness — indexed vs HEAD"]
|
|
60
|
+
WRITER["writer — single-writer drain"]
|
|
61
|
+
JOBS["jobs / watcher — file events"]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
CLI --> IDX
|
|
65
|
+
CLI --> ANALYZE
|
|
66
|
+
MCP --> ANALYZE
|
|
67
|
+
MCP --> WRITER --> IDX
|
|
68
|
+
IDX --> WALK --> POOL --> PARSE --> AGG --> IDX
|
|
69
|
+
IDX --> BACKEND
|
|
70
|
+
ANALYZE --> BACKEND
|
|
71
|
+
FRESH -.-> BACKEND
|
|
72
|
+
JOBS --> WRITER
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Read path** (`analyze`, `find`, most MCP tools) and **write path** (`index`, `reindex`)
|
|
76
|
+
both go through `DuckDBBackend`. When the MCP server is running, the CLI routes reads to it
|
|
77
|
+
([`read_client.py`](src/sqlcg/server/read_client.py)) and serialises all writes through a
|
|
78
|
+
single-writer drain ([`writer.py`](src/sqlcg/server/writer.py)) so there is exactly one
|
|
79
|
+
writer per database.
|
|
80
|
+
|
|
81
|
+
### 2.1 Responsibilities
|
|
82
|
+
|
|
83
|
+
| Module | Job |
|
|
84
|
+
|---|---|
|
|
85
|
+
| [`cli/main.py`](src/sqlcg/cli/main.py) + [`cli/commands/`](src/sqlcg/cli/commands) | Typer CLI. Commands: `index`, `reindex`, `watch`, `report`, `gain`, `install`, `uninstall`; groups `db` (`init`/`reset`/`info`/`list-repos`), `find` (`table`/`column`/`pattern`), `analyze` (`upstream`/`downstream`/`impact`/`failures`/`unused`), `mcp`, `git` (`install-hooks`). |
|
|
86
|
+
| [`server/server.py`](src/sqlcg/server/server.py) | FastMCP instance + stdio entry. Constructs `mcp` at module scope (after the stdout→stderr guard) so [`tools.py`](src/sqlcg/server/tools.py) can register tools onto it. |
|
|
87
|
+
| [`server/tools.py`](src/sqlcg/server/tools.py) | The 18 MCP tools — `trace_column_lineage`, `get_upstream_dependencies`, `get_downstream_dependencies`, `diff_impact`, `find_table_usages`, `find_definition`, `search_sql_pattern`, `analyze_unused`, `get_hub_ranking`, `index_repo`, `execute_sql`, `get_empty_propagation`, `get_pr_impact`, etc. |
|
|
88
|
+
| [`server/writer.py`](src/sqlcg/server/writer.py) | Single-writer queue + drain task. The drain holds `backend_lock` and runs the indexer op directly — the sole backend writer. |
|
|
89
|
+
| [`server/read_client.py`](src/sqlcg/server/read_client.py) | Routes CLI read commands through the live server socket when one is running. |
|
|
90
|
+
| [`server/control.py`](src/sqlcg/server/control.py) | `.pid` / `.sock` control files for server discovery, status, and stop — keyed off the db path. |
|
|
91
|
+
| [`server/models.py`](src/sqlcg/server/models.py) · [`server/exceptions.py`](src/sqlcg/server/exceptions.py) | Pydantic return types for tools; the tool error hierarchy. |
|
|
92
|
+
| [`server/noise_filter.py`](src/sqlcg/server/noise_filter.py) | Filters backup tables and schema-alias mirrors out of user-facing surfaces. |
|
|
93
|
+
| [`server/skill.py`](src/sqlcg/server/skill.py) | Pure renderer for the bundled Claude skill (`SKILL.md`); the installer writes its output to disk. |
|
|
94
|
+
| [`indexer/indexer.py`](src/sqlcg/indexer/indexer.py) | Orchestrates parse → persist. Two-pass index, batched bulk upsert (`_flush_row_batch`), atomic SHA stamping. |
|
|
95
|
+
| [`indexer/walker.py`](src/sqlcg/indexer/walker.py) | Walks the corpus for `.sql` files honouring ignore patterns. |
|
|
96
|
+
| [`indexer/pool.py`](src/sqlcg/indexer/pool.py) | Spawn-mode worker pool; each worker holds pass-1/pass-2 parsers. Per-task hard-kill timeout + respawn (what `concurrent.futures` can't do). |
|
|
97
|
+
| [`indexer/dbt_adapter.py`](src/sqlcg/indexer/dbt_adapter.py) | Enriches `SchemaResolver` from a dbt `manifest.json`. |
|
|
98
|
+
| [`indexer/git_delta.py`](src/sqlcg/indexer/git_delta.py) | Computes the changed-file set between two git SHAs for incremental reindex. |
|
|
99
|
+
| [`indexer/watcher.py`](src/sqlcg/indexer/watcher.py) | `watchdog` file-event source for `sqlcg watch`. |
|
|
100
|
+
| [`indexer/error_classify.py`](src/sqlcg/indexer/error_classify.py) | Maps lineage-extraction failures to the `E{n}` taxonomy for measurement/reporting. |
|
|
101
|
+
| [`lineage/aggregator.py`](src/sqlcg/lineage/aggregator.py) | `CrossFileAggregator` — pass-1 source harvest, pass-2 cross-file lineage resolution. |
|
|
102
|
+
| [`lineage/schema_resolver.py`](src/sqlcg/lineage/schema_resolver.py) | `SchemaResolver` — table/view/column resolution with a lock-guarded cache. One instance per re-index job (never shared across threads). |
|
|
103
|
+
| [`parsers/base.py`](src/sqlcg/parsers/base.py) | Base data models + abstract parser; column-lineage extraction via `sg_lineage`. **Hot path — see [§4](#4-performance-invariants).** |
|
|
104
|
+
| [`parsers/registry.py`](src/sqlcg/parsers/registry.py) | Dialect → parser factory. |
|
|
105
|
+
| [`parsers/{ansi,snowflake,bigquery,postgres,tsql}_parser.py`](src/sqlcg/parsers) | Per-dialect parsers; Snowflake carries the scripting-block / gap handlers. |
|
|
106
|
+
| [`core/duckdb_backend.py`](src/sqlcg/core/duckdb_backend.py) | `DuckDBBackend` — the graph store. 7 node + 12 edge tables, bulk upsert via `unnest`, reentrant `transaction()`, `run_read`, recursive-CTE traversal SQL. |
|
|
107
|
+
| [`core/graph_db.py`](src/sqlcg/core/graph_db.py) | `GraphBackend` ABC. Single-impl today (see [§5](#5-active-findings)); kept for the v2 second-source path. |
|
|
108
|
+
| [`core/schema.py`](src/sqlcg/core/schema.py) | Node/edge labels + `SCHEMA_VERSION` (the schema gate). |
|
|
109
|
+
| [`core/queries.py`](src/sqlcg/core/queries.py) | Loader for query strings in `queries.sql`. |
|
|
110
|
+
| [`core/config.py`](src/sqlcg/core/config.py) | `DbConfig.from_env()` — resolves the db path and settings. |
|
|
111
|
+
| [`core/freshness.py`](src/sqlcg/core/freshness.py) | Backend-free indexed-SHA-vs-HEAD delta; unit-testable with only a git repo. |
|
|
112
|
+
| [`core/jobs.py`](src/sqlcg/core/jobs.py) | Watch job manager — debounced reindex on file-change events. |
|
|
113
|
+
| [`metrics/store.py`](src/sqlcg/metrics/store.py) | SQLite metrics store; opt-out via `SQLCG_METRICS=0`. |
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 3. Key flows
|
|
118
|
+
|
|
119
|
+
### 3.1 Indexing (`sqlcg index`)
|
|
120
|
+
[`walker`](src/sqlcg/indexer/walker.py) enumerates `.sql` files →
|
|
121
|
+
[`pool`](src/sqlcg/indexer/pool.py) farms them to spawn workers → each
|
|
122
|
+
[`parser`](src/sqlcg/parsers/base.py) produces tables/columns/queries and per-statement
|
|
123
|
+
column lineage. The [`aggregator`](src/sqlcg/lineage/aggregator.py) runs **two passes**:
|
|
124
|
+
pass-1 harvests CTE/CTAS bodies and DDL into the `SchemaResolver`; pass-2 reparses with a
|
|
125
|
+
`dependency_filter` to resolve cross-file lineage. [`indexer`](src/sqlcg/indexer/indexer.py)
|
|
126
|
+
accumulates rows across a batch and issues **one bulk upsert per node/edge label per batch**
|
|
127
|
+
into [`DuckDBBackend`](src/sqlcg/core/duckdb_backend.py), stamping the indexed SHA inside the
|
|
128
|
+
same transaction.
|
|
129
|
+
|
|
130
|
+
### 3.2 Query / lineage (`sqlcg analyze`, MCP tools)
|
|
131
|
+
Lineage traversal is a recursive CTE in DuckDB with a depth cap + path-based cycle guard.
|
|
132
|
+
A kind-filter (`WHERE kind IS NULL OR kind IN ('table','external')`) keeps CTE/derived
|
|
133
|
+
scratch nodes out of user-facing surfaces. Up/down direction differ only in which
|
|
134
|
+
`COLUMN_LINEAGE` edge endpoint binds the result's `file:line`.
|
|
135
|
+
|
|
136
|
+
> **Mental model — CTE/derived edges are structural, not coverage gaps.** For
|
|
137
|
+
> `INSERT INTO t (cols) WITH cte … SELECT … FROM cte`, the parser emits two *different,
|
|
138
|
+
> both-correct* edge families: (1) **CTE chain edges** where the CTE node is the `dst`
|
|
139
|
+
> (`src.x → cte.col`, from the CTE-projection block) and (2) **positional edges** where the
|
|
140
|
+
> CTE is the `src` and the real target is the `dst` (`cte.col → t.col`, from the `#25`
|
|
141
|
+
> block). Multi-hop **upstream** traversal walks *both* to chain `t.col ← cte.col ← src.x`.
|
|
142
|
+
> A `kind='cte'`/`kind='derived'` node is a scratch intermediate, never persistent schema,
|
|
143
|
+
> so it can **never** carry a `HAS_COLUMN` row — but it is *required* in the edge set for
|
|
144
|
+
> traversal. Suppressing family (1) (an earlier "P1 de-leak" attempt) dead-ends upstream
|
|
145
|
+
> traversal at the CTE node and was reverted; the canary is
|
|
146
|
+
> [`test_analyze_case_fold`](tests/integration/test_analyze_case_fold.py)
|
|
147
|
+
> (`test_uppercase_upstream_anchor_returns_same_ids_as_lowercase`).
|
|
148
|
+
|
|
149
|
+
> **Coverage-metric formula — edge health is scoped to real-table destinations.** The
|
|
150
|
+
> `edge_health` and `blindspot` metrics in [`coverage.py`](src/sqlcg/cli/coverage.py)
|
|
151
|
+
> count a `COLUMN_LINEAGE` edge as "good" only when its stripped dst table has a
|
|
152
|
+
> `HAS_COLUMN` entry. Because CTE/derived dst edges can never be catalogued (above), they
|
|
153
|
+
> are **excluded from both numerator and denominator** via
|
|
154
|
+
> `WHERE EXISTS (SELECT 1 FROM "SqlTable" t WHERE t.qualified = <dst_table strip> AND
|
|
155
|
+
> t.kind NOT IN ('cte','derived'))`. This mirrors the analyze-surface kind-filter: scratch
|
|
156
|
+
> nodes are scored out of coverage exactly as they are filtered out of user surfaces.
|
|
157
|
+
> Counting them (the pre-2026-06 formula) made ≥95 % edge health mathematically impossible
|
|
158
|
+
> — ~29 % of all edges legitimately point at CTE/derived intermediates.
|
|
159
|
+
|
|
160
|
+
### 3.2b INFORMATION_SCHEMA catalog enrichment (PR 2, 2026-06-10)
|
|
161
|
+
|
|
162
|
+
**Why the 2026-05 prohibition is lifted.** The 2026-05 removal of INFORMATION_SCHEMA
|
|
163
|
+
CSV ingestion was based on a "zero edge delta" measurement — true but wrong-axis: schema
|
|
164
|
+
never creates edges, it makes edge *targets resolvable* (`HAS_COLUMN`). The strict
|
|
165
|
+
column-level health metric that shows the win didn't exist until v1.6.1 (PR 1).
|
|
166
|
+
|
|
167
|
+
Measured root cause (2026-06-10, DWH, ~69k edges): 94 % of all bad edges (18,244/19,438)
|
|
168
|
+
come from ETL files writing to tables whose DDL lives in Liquibase **XML** changelogs
|
|
169
|
+
(not indexed). An INFORMATION_SCHEMA export covers those tables directly, falsifying
|
|
170
|
+
wrong positional guesses (contradicted bucket) rather than hiding them.
|
|
171
|
+
|
|
172
|
+
**Design rule (replaces the old prohibition):**
|
|
173
|
+
- `sqlcg catalog load <csv>` loads `INFORMATION_SCHEMA.COLUMNS` into the graph as
|
|
174
|
+
`HAS_COLUMN(source='information_schema')` rows **post-index** (never at parse time).
|
|
175
|
+
- Precedence: `ddl > information_schema > usage` — enforced in `upsert_edges_bulk`
|
|
176
|
+
via `ON CONFLICT (src_key, dst_key) DO UPDATE SET source = CASE … END`.
|
|
177
|
+
- **Parse-time schema feeding remains forbidden.** Passing `schema_sources` into
|
|
178
|
+
`exp.expand()` or `qualify()` is still prohibited (the hot-loop path that measured
|
|
179
|
+
zero and regressed performance in 2026-05).
|
|
180
|
+
- Per-file reindex (`delete_nodes_for_file`) is **source-aware**: only `ddl`/NULL rows
|
|
181
|
+
are deleted; `information_schema` and `usage` rows survive incremental reindex.
|
|
182
|
+
- Config persistence: `[sqlcg.catalog] path = "..."` in `.sqlcg.toml` causes
|
|
183
|
+
`index_repo` to re-apply the catalog at the end of every full rebuild (zero parse-time
|
|
184
|
+
cost, one-shot bulk upsert outside all hot loops).
|
|
185
|
+
|
|
186
|
+
### 3.3 MCP server + single-writer model
|
|
187
|
+
[`server.py`](src/sqlcg/server/server.py) runs FastMCP over stdio. Writes (`index`,
|
|
188
|
+
`reindex`) are enqueued and drained by [`writer.py`](src/sqlcg/server/writer.py) under
|
|
189
|
+
`backend_lock` — one writer per db. The full-rebuild drain wraps `clear_all_tables()` +
|
|
190
|
+
`index_repo()` in one reentrant transaction, so a mid-rebuild failure rolls back to the
|
|
191
|
+
prior graph. Reads currently share that lock (see [§5](#5-active-findings)).
|
|
192
|
+
|
|
193
|
+
### 3.4 Freshness / reindex / watch
|
|
194
|
+
[`freshness`](src/sqlcg/core/freshness.py) compares the stored `indexed_sha` to git HEAD;
|
|
195
|
+
[`git_delta`](src/sqlcg/indexer/git_delta.py) yields the changed files; `reindex` /
|
|
196
|
+
[`jobs`](src/sqlcg/core/jobs.py) + [`watcher`](src/sqlcg/indexer/watcher.py) drive
|
|
197
|
+
incremental updates (`git install-hooks` wires this to commits).
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## 4. Performance invariants
|
|
202
|
+
|
|
203
|
+
These are **not duplicated here** — the canonical table (parser hot-path rules, bulk-upsert
|
|
204
|
+
and batch-flush invariants, the named regressions each guards) lives in
|
|
205
|
+
[`CLAUDE.md`](CLAUDE.md) under *Performance invariants — DO NOT REMOVE OR SIMPLIFY*. They
|
|
206
|
+
are pinned by [`test_perf_scaling_guard.py`](tests/unit/test_perf_scaling_guard.py),
|
|
207
|
+
[`test_bulk_upsert_invariant.py`](tests/unit/test_bulk_upsert_invariant.py),
|
|
208
|
+
[`test_upsert_batch_invariant.py`](tests/unit/test_upsert_batch_invariant.py), and
|
|
209
|
+
[`test_T09_01_qualify_once.py`](tests/unit/test_T09_01_qualify_once.py). Any refactor of
|
|
210
|
+
[`base.py`](src/sqlcg/parsers/base.py) or [`indexer.py`](src/sqlcg/indexer/indexer.py) must
|
|
211
|
+
keep them green.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## 5. Active findings
|
|
216
|
+
|
|
217
|
+
Only genuinely-open items live here. Resolved findings and their reasoning are in the
|
|
218
|
+
[archive](ARCHITECTURE_REVIEW_ARCHIVE.md).
|
|
219
|
+
|
|
220
|
+
| # | Sev | Finding | Where | Plan |
|
|
221
|
+
|---|-----|---------|-------|------|
|
|
222
|
+
| F1 | LOW | **Scratch-object leak into the default `analyze` surface.** ~22% of `kind='table'` nodes carry `tmp_*`/`temp_*` prefixes and leak into filtered output. Fix belongs at **classification time** (emit `kind='derived'` for TEMP/TRANSIENT CTAS targets), never in the name-blind filter. | [`aggregator.py`](src/sqlcg/lineage/aggregator.py) `_build_file_rows`, [`analyze.py`](src/sqlcg/cli/commands/analyze.py) | none yet |
|
|
223
|
+
| F2 | LOW | **RESOLVED (v1.28.2, PR #119+#120)** `run_read` now uses `self._conn.cursor()` for a per-call snapshot; the read dispatch path in `server.py` no longer acquires `backend_lock`. Reads during a rebuild see the last committed graph immediately. Drain (writer.py:330) still holds `backend_lock` for the full write transaction. Proven by `test_write_memory_ceiling.py` Scenario A (read returns in <1 s with non-empty result while write transaction open). | [`duckdb_backend.py`](src/sqlcg/core/duckdb_backend.py) `run_read`, [`server.py`](src/sqlcg/server/server.py) `query` op | sprint_backlog_q2_bugfix §PR-E |
|
|
224
|
+
| F3 | LOW | **RESOLVED (v1.28.2, PR #119+#120)** 1,600-file write-memory ceiling measured and verified. Peak RSS in a dedicated subprocess (1,600 minimal SQL fixtures, batch_size=50): **0.154 GiB (165 MB)** — well under the 3.8 GiB gate. Pinned by [`test_write_memory_ceiling.py`](tests/integration/test_write_memory_ceiling.py) Scenario B. | [`indexer.py`](src/sqlcg/indexer/indexer.py), [`duckdb_backend.py`](src/sqlcg/core/duckdb_backend.py) | sprint_backlog_q2_bugfix §PR-E |
|
|
225
|
+
| F4 | LOW | **Single-impl ABC + stale Cypher/Kuzu docstrings.** `GraphBackend` adds indirection without polymorphism now; `clear_all_tables` is a `NotImplementedError`-default on the ABC; a docstring still says "skipped by KuzuDB's MERGE semantics". De-Cypher the docstrings and relocate `clear_all_tables` off the ABC, or collapse the ABC if v2 ACCESS_HISTORY is shelved. | [`graph_db.py`](src/sqlcg/core/graph_db.py) | none yet |
|
|
226
|
+
| F5 | LOW | **TC6b guard reconstructs the query.** The terminal-sink test rebuilds the downstream Cypher/SQL string instead of running `analyze downstream` end-to-end, so it can drift from the shipped query. Replace with a `CliRunner`-based guard. | [`test_user_surface_recall_guard.py`](tests/integration/test_user_surface_recall_guard.py) | none yet |
|
|
227
|
+
| F6 | LOW | **Dead `_set_backend_lock` stub.** Defined but never called (the escalation plumbing it belonged to was deleted in the DuckDB migration). Violates the CLAUDE.md "every new method has a grep-confirmed call site" rule — remove it. | [`tools.py`](src/sqlcg/server/tools.py) | none yet |
|
|
228
|
+
| F7 | MED | **95 % edge-health milestone is ~30 points short after P1/P3/P4.** With the scoped metric (CTE/derived excluded) the DWH baseline is ≈41 %; P3 (+6,045 edges) + P4 lift it to ≈55–65 %. Reaching ≥95 % needs catalogs for ~566 residual **real-table** blindspots — the P2 cohort (temp / cross-file / unseen-DDL tables) and the deferred P5 `USE SCHEMA` bare-name group (956 tables). **RESOLVED (GitHub #124, PR fix/coverage-metric-baselining)**: 95 % numeric gate dropped; coverage is now reported as an observed metric with no pass/fail target. BQ-2 is the follow-up sprint. | [`coverage.py`](src/sqlcg/cli/coverage.py), [`base.py`](src/sqlcg/parsers/base.py) | [coverage_p1_p3_p4](plan/sprints/coverage_p1_p3_p4.md) §95 % Feasibility Analysis |
|
|
229
|
+
| F8 | MED | **Index-summary metric undercount masks coverage gaps.** End-of-`sqlcg index` prints "1 failed" while 410 files carry `parse_failed=True` in the live DWH (1,335 files indexed, v1.25.0). The printed count reflects only the final-phase summary, not the full parse-failure population. Users and agents see a misleadingly-healthy finish line. Being addressed in the coverage sprint. | [`indexer.py`](src/sqlcg/indexer/indexer.py) summary path | `plan/sprints/coverage_parse_failures.md` (pending creation) |
|
|
230
|
+
| F9 | LOW | **`pr-impact` rename suppression renders no "verify consumers updated" label.** The help text promises a dedicated labelled section when a rename is detected with consumers updated; the actual output emits only "No genuine lost producers detected" with no rename callout. Suppression logic is correct; the label is missing. | [`server/tools.py`](src/sqlcg/server/tools.py) `get_pr_impact` | none yet |
|
|
231
|
+
| F10 | LOW | **`git install-hooks` embeds venv path, not user-installed binary.** Hooks installed via `sqlcg git install-hooks` point at `.venv/bin/sqlcg`, not `~/.local/bin/sqlcg`. If the project venv is rebuilt or deleted, the hooks become stale silently while the user-installed PyPI copy is current. Observed live on v1.25.0 (both pointed at 1.25.0 coincidentally — but this is a version-skew surface). | [`indexer/`](src/sqlcg/indexer/) install path | none yet |
|
|
232
|
+
| F11 | LOW | **`mcp restart` is stop-only by design but misnamed.** The command stops the server and instructs the user to reconnect via `/mcp`; it does NOT restart the server process. For a stdio MCP server this is architecturally correct (the client owns the lifecycle), but the name and the live-verify expectation are contradicted by the observed behaviour. Either rename to `mcp stop` or document prominently in `--help` that the client must reconnect. Honest reframe shipped in v1.20.0; the naming gap remains. | [`server/control.py`](src/sqlcg/server/control.py), [`cli/commands/`](src/sqlcg/cli/commands) | none yet |
|
|
233
|
+
| F12 | MED | **`pr-impact` requires graph to be indexed at base-ref; not self-healing.** Each `pr-impact --base X` run leaves the graph indexed at HEAD. A second run fails with a hint to manually reindex. Worse, the installed git post-checkout/post-merge hooks fire a background `sqlcg reindex` on every branch switch, racing `pr-impact` off the base. Reproduced on the live DWH (2026-06-13). Working protocol: chain `reindex --from <current_sha> --to <base>` immediately before `pr-impact`. A self-healing reindex-to-base step inside `pr-impact` itself is the right fix. | [`server/tools.py`](src/sqlcg/server/tools.py) `get_pr_impact`, [`indexer/git_delta.py`](src/sqlcg/indexer/git_delta.py) | backlog (deferred post data-loss-impact sprint) |
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## 6. DWH graph topology insights (2026-06-13, v1.25.0)
|
|
238
|
+
|
|
239
|
+
Source: [`plan/reports/dwh_graph_analysis.md`](plan/reports/dwh_graph_analysis.md) —
|
|
240
|
+
full tables, method, and candidate lists live there; this section captures the
|
|
241
|
+
actionable architectural findings only.
|
|
242
|
+
|
|
243
|
+
Graph: **2,030 nodes · 2,930 directed edges** (table-level, noise-filtered), built from
|
|
244
|
+
1,335 files, 52,514 column-lineage edges (schema v8, DWH corpus, 2026-06-13).
|
|
245
|
+
|
|
246
|
+
### 6.1 Centrality — VALIDATED
|
|
247
|
+
|
|
248
|
+
Ground-truth check: `ba.wtdh_artikel` (degree rank #3, total=107) and
|
|
249
|
+
`ba.wtfe_verkoopinfo` (rank #6, total=57) independently reproduced as top hubs.
|
|
250
|
+
**Out-degree / total-degree is the right blast-radius metric** — it answers "what breaks
|
|
251
|
+
the most downstream if this table is wrong". PageRank is the wrong metric here: it ranks
|
|
252
|
+
hubs low because they are *sources*, not sinks.
|
|
253
|
+
|
|
254
|
+
The warehouse is anchored on five conformed dimensions (store, banner, article, date,
|
|
255
|
+
week) and one dominant fact hub (verkoopinfo) — exactly the expected retail star-schema
|
|
256
|
+
shape.
|
|
257
|
+
|
|
258
|
+
**Surprising high-centrality tables** (not obvious from name alone):
|
|
259
|
+
`da.ttint_verkooptransactie` (PageRank #4 — a quiet integration staging table is the
|
|
260
|
+
single biggest convergence point with in=25), `ba.wtfe_korting` (PageRank #1 — discount
|
|
261
|
+
logic far more central than its name suggests), `ba.wtfi_axi_ail` +
|
|
262
|
+
`ba.wtfe_artikel_inteken_lijst` (intake-list pipeline dense hub, not a leaf report).
|
|
263
|
+
|
|
264
|
+
### 6.2 Named single-points-of-failure (high betweenness bridges)
|
|
265
|
+
|
|
266
|
+
These four permanent tables sit on the most shortest-paths; an outage in any of them
|
|
267
|
+
**fragments lineage across subject areas**. Directly actionable for outage planning.
|
|
268
|
+
|
|
269
|
+
| Table | Betweenness | Role |
|
|
270
|
+
|---|---|---|
|
|
271
|
+
| `ba.wtfe_verkoopinfo` | 0.00372 | #1 bridge AND top hub (sales fact) |
|
|
272
|
+
| `da.ttint_verkooptransactie` | 0.00340 | Transaction integration bridge (in=25 → upstream of sales + promotions) |
|
|
273
|
+
| `ba.wtfe_promotie_artikel_bouwmarkt` | 0.00175 | Bridges promotions ↔ sales ↔ store |
|
|
274
|
+
| `ba.wtfv_voorraad_dagstand` | 0.00120 | Inventory daily-snapshot bridge |
|
|
275
|
+
|
|
276
|
+
Betweenness floats are meaningful only as a ranking; computed on the 2,030-node
|
|
277
|
+
filtered DiGraph.
|
|
278
|
+
|
|
279
|
+
### 6.3 Communities
|
|
280
|
+
|
|
281
|
+
171 communities, modularity **0.763** (strong, well-separated). Communities map
|
|
282
|
+
cleanly onto retail subject areas. Two notable anomalies:
|
|
283
|
+
|
|
284
|
+
- `ba.wtfe_loyalty` sits in the **Webshop** community (#32), not a
|
|
285
|
+
customer/CRM community — candidate for a real coupling or mis-placement.
|
|
286
|
+
- **HR/workforce fused into the Store community (#4)** — staffing data has no independent
|
|
287
|
+
lineage island; it only exists hanging off the store dimension.
|
|
288
|
+
|
|
289
|
+
Cross-community bridge edges concentrate on the same four betweenness tables (§6.2) —
|
|
290
|
+
confirming that any refactor touching those tables has the widest blast radius.
|
|
291
|
+
|
|
292
|
+
### 6.4 Orphan / satellite belt
|
|
293
|
+
|
|
294
|
+
~4,417 SqlTable nodes have zero table-level lineage edges. The headline is **not
|
|
295
|
+
"4,000 dead tables"**: that population is dominated by parse-failure coverage gaps
|
|
296
|
+
(410 parse-failed files) + targetless write queries (1,090 of 2,349) + downstream
|
|
297
|
+
export mirrors (`ia_*` schemas) — not genuinely standalone business tables. Only ~57
|
|
298
|
+
clean-parse standalone DDL tables are confidently business isolates.
|
|
299
|
+
|
|
300
|
+
This orphan belt is the main driver of the coverage sprint (F8 +
|
|
301
|
+
`plan/sprints/coverage_parse_failures.md` — being produced separately).
|
|
302
|
+
|
|
303
|
+
### 6.5 Tier-2 "refactor advisor" candidate (feature opportunity)
|
|
304
|
+
|
|
305
|
+
The `wtfv_`/`wtfs_` prefix-split pattern surfaces as a recurring topology signal: 7
|
|
306
|
+
ranked candidate groups where a fact-view and a fact-snapshot table share J=1.0 leaf
|
|
307
|
+
sets and 8–71 shared columns (see the full table in
|
|
308
|
+
[`plan/reports/dwh_graph_analysis.md`](plan/reports/dwh_graph_analysis.md) §Lens 4).
|
|
309
|
+
The strongest candidate is the `*voorraad_dagstand*` inventory family (3 tables, J=1.0,
|
|
310
|
+
33 shared leaves, 33–71 shared columns).
|
|
311
|
+
|
|
312
|
+
**This is a topology + column-name hypothesis, NOT a confirmed refactor recommendation.**
|
|
313
|
+
The `manus_export` false positive (J=1.0, 50 shared leaves, only 5 shared columns of 84)
|
|
314
|
+
proves same inputs ≠ same logic. Confirming evidence a tier-2 pass needs before any
|
|
315
|
+
prescriptive recommendation:
|
|
316
|
+
|
|
317
|
+
- **(a) SQL-expression comparison** — prove the *logic* (not just the inputs) is duplicated.
|
|
318
|
+
Compare actual SELECT projections / WHERE / join logic per `SqlQuery.sql`.
|
|
319
|
+
- **(b) Shared grain / PK** — a conformed hub is only legal if the candidates share a
|
|
320
|
+
grain. PK/grain metadata is **not in the graph today**.
|
|
321
|
+
|
|
322
|
+
Record as a feature opportunity. Do not implement until (a) and (b) are available.
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## 7. Deferred / roadmap
|
|
327
|
+
|
|
328
|
+
- **Coverage sprint — parse-failure diagnosis (active).** 410/1,335 files
|
|
329
|
+
parse-failed on the live DWH, dominated by error classes **E5 (217)** and **E8 (184)**;
|
|
330
|
+
only 1 timeout. This is the dominant driver of the satellite/orphan belt (§6.4) and the
|
|
331
|
+
F7/F8 findings. Diagnosis: [`plan/research/coverage_parse_failure_diagnosis.md`](plan/research/coverage_parse_failure_diagnosis.md);
|
|
332
|
+
sprint plan: `plan/sprints/coverage_parse_failures.md` (being produced separately).
|
|
333
|
+
- **v2 — Snowflake `ACCESS_HISTORY` as a second lineage source.** Fuse query-history lineage
|
|
334
|
+
to *enrich* (not replace) static parsing. This is the main reason the `GraphBackend` ABC
|
|
335
|
+
(F4) is kept rather than collapsed.
|
|
336
|
+
- **ETL session-context limits (fundamental).** Cross-session temp tables, `COPY INTO`
|
|
337
|
+
column mapping, and dynamic `IDENTIFIER()` references are static-analysis limits — they
|
|
338
|
+
need runtime information. Intra-file temp-table chains resolve via pass-1 DDL sniffing;
|
|
339
|
+
cross-file/cross-session chains do not. Full analysis in the
|
|
340
|
+
[archive §6](ARCHITECTURE_REVIEW_ARCHIVE.md).
|
|
341
|
+
- **Incremental reindex** (vs. full rebuild) — the real fix for F2/F3's lock-duration and
|
|
342
|
+
memory pressure; explicitly deferred during the DuckDB migration.
|
|
343
|
+
- **PyPI publish pipeline — batch-push root cause resolved; re-publish backlog pending.**
|
|
344
|
+
PyPI is stuck at v1.5.1 because tags v1.6.0–v1.14.2 were pushed as a batch (GitHub
|
|
345
|
+
Actions silently drops triggers for all but ~3 tags in a single push). The v1.14.2
|
|
346
|
+
`workflow_dispatch` run also failed its `test` gate. A `workflow_dispatch` re-publish
|
|
347
|
+
path exists (`docs/releasing-pypi.md`); actual tagging and per-tag republishing are
|
|
348
|
+
user-gated. v1.15.0–v1.25.x are not yet tagged or published.
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## 8. History
|
|
353
|
+
|
|
354
|
+
Earlier content is preserved verbatim in
|
|
355
|
+
[`ARCHITECTURE_REVIEW_ARCHIVE.md`](ARCHITECTURE_REVIEW_ARCHIVE.md). Detailed per-release
|
|
356
|
+
plans live in [`plan/`](plan) (a frozen historical archive — see
|
|
357
|
+
[`plan/WORKFLOW.md`](plan/WORKFLOW.md) for the agent pipeline that produced them).
|
|
358
|
+
|
|
359
|
+
| Era | What it covered |
|
|
360
|
+
|---|---|
|
|
361
|
+
| Pre-1.4 blueprint review (archive §1–7) | Original design review, ETL-lineage gap analysis, open questions. |
|
|
362
|
+
| PR/issue reviews (archive §8, §10) | PR #1 inline comments; issues #5/#6 LLM-experience feedback. |
|
|
363
|
+
| v0.3–v1.3 sprint postmortems (archive §11–20) | Column-lineage diagnostics, the `E{n}` taxonomy, bulk-upsert/perf work, freshness + single-writer queue, recall guards. |
|
|
364
|
+
| Kuzu → DuckDB migration (archive, v1.4.0) | Backend swap, perf-invariant re-verification, the concurrency-model deviation that became F2. |
|
sql_code_graph-1.5.0/ARCHITECTURE_REVIEW.md → sql_code_graph-1.33.0/ARCHITECTURE_REVIEW_ARCHIVE.md
RENAMED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
# Architecture Review — sql-code-graph
|
|
1
|
+
# Architecture Review — ARCHIVE (sql-code-graph)
|
|
2
|
+
|
|
3
|
+
> **Frozen historical record.** This is the pre-overhaul `ARCHITECTURE_REVIEW.md`,
|
|
4
|
+
> captured verbatim on 2026-06-08 (through the v1.4.0 Kuzu→DuckDB migration). It is **not
|
|
5
|
+
> maintained** — links and findings reflect the repo as it was when each section was
|
|
6
|
+
> written. For the current architecture see
|
|
7
|
+
> [`ARCHITECTURE_REVIEW.md`](ARCHITECTURE_REVIEW.md). Kept for the decision/postmortem
|
|
8
|
+
> trail; nothing below should be treated as current.
|
|
9
|
+
|
|
10
|
+
---
|
|
2
11
|
|
|
3
12
|
Blueprint version: v1.2 (May 2026)
|
|
4
13
|
Review date: 2026-05-02 (updated 2026-05-06)
|
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
## v1.25.0 (2026-06-13)
|
|
2
|
+
|
|
3
|
+
> **Re-index recommended (no schema change).** `SCHEMA_VERSION` unchanged.
|
|
4
|
+
> View classification (`kind='view'`) and the `gating_join_tables` supplement only
|
|
5
|
+
> take effect on a fresh `sqlcg index <path>`.
|
|
6
|
+
|
|
7
|
+
### Feat
|
|
8
|
+
|
|
9
|
+
- **view classification**: `CREATE VIEW` targets now stamped `kind='view'` so they
|
|
10
|
+
persist as `SqlTable.kind='view'` instead of being indistinguishable from tables;
|
|
11
|
+
live-verified on a ~1,400-file DWH (582 views classified)
|
|
12
|
+
- **empty-impact** (`sqlcg analyze empty-impact` / `get_empty_propagation` MCP tool):
|
|
13
|
+
downstream blast radius when named table(s) are empty — two views: value-derivation
|
|
14
|
+
(primary, column-lineage refinement) and row-reachability (supplement, direct
|
|
15
|
+
gating-join reads)
|
|
16
|
+
- **pr-impact** (`sqlcg analyze pr-impact` / `get_pr_impact` MCP tool): detect
|
|
17
|
+
producers a PR dropped + their blast radius; code-regression detection (not runtime
|
|
18
|
+
monitoring); rename-handling via column-set AND consumer Jaccard ≥ 0.6
|
|
19
|
+
- **gating-join supplement** (`get_change_scope` / `diff_impact`): `gating_join_tables`
|
|
20
|
+
field added — tables that row-empty via direct gating-join reads supplementing the
|
|
21
|
+
column-lineage blast radius; caveat: depends on join type (not recorded on edges)
|
|
22
|
+
- **3-signal unused** (`analyze_unused` / `sqlcg analyze unused`): redefines "used"
|
|
23
|
+
as the union of (D1) direct `SELECTS_FROM`, (D2) `STAR_SOURCE`, and (D3)
|
|
24
|
+
column-lineage CTE-derived read; `find_table_usages` augmented with `via_lineage`
|
|
25
|
+
entries for the same D3 signal
|
|
26
|
+
|
|
27
|
+
### Fix
|
|
28
|
+
|
|
29
|
+
- **pr-impact BUG-A**: CLI path was not initialising the backend before calling
|
|
30
|
+
`_compute_pr_impact`, causing `RuntimeError: Backend not initialized`
|
|
31
|
+
- **pr-impact BUG-B**: blast-radius engine was zeroing the result when the resync
|
|
32
|
+
produced no new edges; now computed on the pre-resync graph (Option i)
|
|
33
|
+
|
|
1
34
|
## v1.1.3 (2026-06-01)
|
|
2
35
|
|
|
3
36
|
> **Re-index recommended (no schema change).** `SCHEMA_VERSION` stays `6`, so no
|
|
@@ -38,7 +71,7 @@
|
|
|
38
71
|
> `SCHEMA_VERSION` 4 to 6 (added `start_line` on `SqlQuery`, repurposed
|
|
39
72
|
> `SqlTable.kind`, added the `ExternalConsumer` node + `CONSUMED_BY` edge). There
|
|
40
73
|
> is no in-place migration — re-run `sqlcg index <path>` to rebuild the graph. If
|
|
41
|
-
> you run the MCP server,
|
|
74
|
+
> you run the MCP server, stop it (`sqlcg mcp stop`) and reconnect via your editor after re-indexing. (Note: as of v1.20.0 the server self-heals on the next tool call — no manual stop needed.)
|
|
42
75
|
|
|
43
76
|
### Feat
|
|
44
77
|
|