sql-code-graph 1.36.2__tar.gz → 1.37.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.36.2 → sql_code_graph-1.37.0}/PKG-INFO +1 -1
- sql_code_graph-1.37.0/plan/sprints/viz_usability_neighborhood_highlight.md +443 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/pyproject.toml +1 -1
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/__init__.py +1 -1
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/viz/assets/template.html +120 -14
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_viz_cli_e2e.py +24 -3
- sql_code_graph-1.37.0/tests/unit/test_viz_render_self_contained.py +258 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/uv.lock +1 -1
- sql_code_graph-1.36.2/tests/unit/test_viz_render_self_contained.py +0 -114
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.claude/agents/api-documenter.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.claude/agents/architect-planner.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.claude/agents/architect-reviewer.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.claude/agents/code-reviewer.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.claude/agents/developer.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.claude/agents/plan-reviewer.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.claude/agents/sprint-planner.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.github/workflows/benchmark.yml +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.github/workflows/e2e-tests.yml +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.github/workflows/release.yml +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.github/workflows/test.yml +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.gitignore +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.pre-commit-config.yaml +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/.sqlcgignore +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/ARCHITECTURE_REVIEW.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/ARCHITECTURE_REVIEW_ARCHIVE.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/CHANGELOG.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/CLAUDE.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/README.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/docs/AIRBNB_PARSE_REPORT.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/docs/cli.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/docs/getting-started.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/docs/releasing-pypi.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/e2e_firstuser_report.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/e2e_run_20260528_101413.output +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/main.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/WORKFLOW.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/measurements/pr2_catalog_load_eval.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/measurements/pr3_repo_native_plateau.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/measurements/pr4_transform_kinds.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/measurements/pr5_extraction_recall_taxonomy.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/measurements/sprint_08_changelogs_fullindex.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/measurements/sprint_08_fullcorpus_index.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/createkind_dwh_after.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/createkind_dwh_before.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/gain_1.29.0_05c6943.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/gain_1.30.0_2c8ac25.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/gain_1.30.1_26271fc.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/gain_1.31.0_a40c837.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/gain_1.32.0_c1bec3c.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/gain_1.36.2_f6a335a.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/gain_drop_alter_phantom_baseline_v1361.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/identifier_live_acceptance.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/identifier_live_after_v1.36.0.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/identifier_live_before_v1.35.3.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/lineage5_dwh_after_pr5.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/lineage5_dwh_before_master.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/pr4_star_promote_after.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/pr4_star_promote_before.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/pr_b_phantom_after.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/pr_b_phantom_before.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/pr_c_merge_after.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/pr_c_merge_before.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/schema_comparison_with_schema.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/schema_comparison_without_schema.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/sprint_08_changelogs_fullindex.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/sprint_08_fullcorpus_index.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/metrics/sprint_pool_300s_plan.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/column_coverage_diagnostic.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/column_coverage_findings.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/dwh_graph_analysis.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/dwh_positional_insert_column_blindspot.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/feature_acceptance_dwh.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/graph_health_sprint_postmortem.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/island_lever_live_verification.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/issue38_pr2_live_acceptance.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/issue38_pr3_live_acceptance.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/lineage_identity_sprint_postmortem.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/pr_impact_followups_2026-06-14.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/sprint_03_v0.3.1_postmortem.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/sprint_3.1_postmortem.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/reports/v1_14_dialect_query_config_postmortem.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/research/blueprint.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/research/coverage_parse_failure_diagnosis.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/research/investigation_e5_e4.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/research/observed_usage_overlay_query_history_tableau.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/research/parse_diagnostics.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/research/parsing_errors_experiment.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/research/snowflake_en_test_suite.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/research/sql_only_coverage_lever_post_pr2.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/research/sqlcg.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/bundle_claude_skill.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/ci_tests_pool_flake_fix.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/column_lineage_recall_metric.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/coverage_p1_p3_p4.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/coverage_p1_p5_metric.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/coverage_parse_failures.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/diff-impact-producer-file.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/e8_dual_emission.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/feature_34_unused_presentation_segregation.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/feature_35_external_downstream_injection.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/feature_F2_bundle_claude_skill.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/feature_generic_var_name_resolution.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/feature_kuzu_to_duckdb_migration.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/fix_backward_self_heal_index_at_sha.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/fix_downstream_sink_location.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/fix_drop_alter_phantom_source_node.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/fix_dynamic_table_parsing.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/fix_expand_qualify_perf.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/fix_firstuser_findings.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/fix_issue29_live_test_followups.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/fix_schema_case_mismatch.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/gain_coverage_metrics.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/graph_health_catalog_and_metrics.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/hygiene_config_path_and_survivors.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/issue-38-backfill-cte-bridge.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/issue-38-residual-source-extraction.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/issue-38-selects-from-island-lever.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/living_codebase_resync.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/mcp_server_self_healing.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/positional_insert_clone_blindspot.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_01.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_01_deployment_pypi.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_02.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_02_v0.3.0_core.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_03.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_04_column_lineage.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_04_column_lineage_fix.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_05_star_resolution.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_06_lineage_coverage.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_07_open_ecodes.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_07_perf_and_live_test.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_08_perf_upsert.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_09_lineage_coverage.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_10_anchor_tools.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_11_v1.0.2_bugfix.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_12_v1.1.0.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_13_v1.1.0_cluster_b.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_lineage_identity_and_session_context.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/sprint_postmortem_fixes.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/temp_table_namespacing.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/trust_layer.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/unfilled_table_impact.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/v1.1.0_cluster_b_provenance_trust.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/v1.1.0_live_graph_freshness.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/v1.1.1_batch_upsert_perf.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/v1.14.0_dialect_and_query_config_fixes.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/v1_1_2_bugfix.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/v1_1_3_union_cte_star.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/v1_2_0_read_proxy.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/v1_2_1_bugfix.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/plan/sprints/version-parity-and-restart.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/profile.html +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/pyrightconfig.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/scripts/collect_parse_errors.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/scripts/column_coverage_check.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/scripts/generate_cli_docs.sh +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/__main__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/analyze.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/catalog.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/db.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/find.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/gain.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/git.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/index.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/install.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/mcp.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/reindex.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/report.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/uninstall.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/viz.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/commands/watch.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/coverage.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/cli/main.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/core/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/core/config.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/core/duckdb_backend.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/core/freshness.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/core/graph_db.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/core/jobs.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/core/noise_match.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/core/queries.cypher +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/core/queries.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/core/queries.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/core/schema.cypher +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/core/schema.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/indexer/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/indexer/dbt_adapter.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/indexer/error_classify.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/indexer/git_delta.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/indexer/indexer.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/indexer/pool.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/indexer/walker.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/indexer/watcher.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/lineage/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/lineage/aggregator.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/lineage/schema_resolver.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/metrics/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/metrics/store.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/parsers/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/parsers/ansi_parser.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/parsers/base.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/parsers/bigquery_parser.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/parsers/dynamic_name.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/parsers/postgres_parser.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/parsers/registry.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/parsers/snowflake_parser.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/parsers/tsql_parser.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/server/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/server/control.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/server/exceptions.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/server/models.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/server/noise_filter.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/server/read_client.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/server/selfheal.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/server/server.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/server/skill.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/server/tools.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/server/writer.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/utils/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/utils/hashing.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/utils/ignore.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/utils/logging.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/viz/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/viz/assets/force-graph.min.js +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/viz/data.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/viz/render.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/src/sqlcg/viz/tags.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/adversarial/200_join.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/adversarial/500_union.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/bench_indexer.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/conftest.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/golden_corpus/snowflake/case_normalization.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/golden_corpus/snowflake/colon_cast.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/golden_corpus/snowflake/colon_reserved_word.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/golden_corpus/snowflake/copy_into.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/golden_corpus/snowflake/create_procedure.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/golden_corpus/snowflake/identifier_dynamic.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/golden_corpus/snowflake/lateral_flatten.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/golden_corpus/snowflake/qualify.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/golden_corpus/snowflake/scripting_block.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/golden_corpus/snowflake/three_part.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/tpch/q01.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/tpch/q02.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/tpch/q03.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/tpch/q04.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/benchmarks/tpch/q05.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/conftest.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/conftest.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_F2_skill_install_e2e.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_airbnb_e2e.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_cli_index.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_empty_impact_cli_e2e.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_git_hook_install.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_golden_lineage.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_mcp_lifecycle.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_mcp_tools.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_parse_diagnostics_cli.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_pr_impact_cli_e2e.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_selfheal_e2e.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_star_resolution_e2e.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/e2e/test_watch.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/airbnb/dim_hosts_cleansed.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/airbnb/dim_listings_cleansed.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/airbnb/fct_reviews.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/airbnb/mart_fullmoon_reviews.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/airbnb/raw_hosts.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/airbnb/raw_listings.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/airbnb/raw_reviews.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/airbnb/src_hosts.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/airbnb/src_listings.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/airbnb/src_reviews.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/bigquery/.gitkeep +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/duckdb_parity/kuzu_reference.json +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/jaffle_shop/customers.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/jaffle_shop/orders.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/jaffle_shop/raw_orders.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/snowflake/base_tables.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/snowflake/reports.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/snowflake/views.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/star_corpus/ddl_src.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/star_corpus/ddl_tgt.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/star_corpus/etl_alias_star.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/star_corpus/etl_star.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/synthetic/base_tables.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/synthetic/reports.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/fixtures/synthetic/views.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/snowflake/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/snowflake/test_identifier_var_sink_resolution_integration.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/snowflake/test_insert_select.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/snowflake/test_qualify_bare_tables_command_guard_integration.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_T34_presentation_segregation.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_T35_external_consumers.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_analyze_case_fold.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_anchor_tools.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_backfill_impact_consistency.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_bare_column_cte_lineage.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_bulk_upsert.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_case_split_seed_regression.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_catalog_kind_upgrade.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_catalog_load_integration.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_cli_index_clear_before_rebuild.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_column_coverage_patterns.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_column_lineage_e2e.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_coverage_metrics_integration.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_cross_file_lineage.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_cte_key_namespacing_integration.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_cte_recall_guard.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_cte_schema_alias_guard.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_cte_source_node_invariant.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_dialect_auto_resolution.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_dialect_matrix.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_duckdb_parity.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_e36_xfile_regression_guard.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_empty_impact_blast_radius.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_empty_index_rollback_guard.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_freshness_mcp.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_gating_join_retrofit.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_hygiene_config_root_reconciliation.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_identity_counters_integration.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_impact_consumer_parity.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_incremental_reindex_parity.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_index_degraded_files_metric.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_index_filter_node_exclusion.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_indexer_batching.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_indexer_commits.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_indexer_to_graph.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_issue38_cte_insert_regression.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_join_col_resolution.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_key_normalization_chokepoint.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_live_anchors.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_mvcc_rebuild.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_non_table_create_coverage_no_regression.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_non_table_create_kind_in_graph.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_parse_diagnostics.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_phantom_drop_alter_node.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_phantom_non_table_create_node.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_pr1_confidence_reason.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_pr2_source_location.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_pr3_kind_tagging.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_pr_impact_integration.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_qualify_failed_persist.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_read_via_server.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_readonly_under_lock.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_reindex_via_server.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_repo_relative_cte_namespaces.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_resolvable_write_col_edges_integration.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_resync.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_selects_from_completeness.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_selects_from_cte_body_source.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_selects_from_subscope_source.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_single_writer_queue.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_skip_counts_integration.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_star_promote_temp_columns.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_star_resolution.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_temp_table_lineage.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_temp_table_namespacing.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_tool_version_stamp_integration.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_union_cte_star_recall_guard.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_usage_derived_catalog.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_use_schema_session_context_integration.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_user_surface_recall_guard.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_v141_surface_guards.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_v1_14_0_dialect_and_query_config_fixes.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_view_kind_in_graph.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_viz_data_build.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/integration/test_write_memory_ceiling.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/perf/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/perf/test_perf.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E10/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E11/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E12/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E12/e12_json_path.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E12/e12_lateral_flatten.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E12/test_e12.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E13/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E14/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E15/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E16/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E16/e16_merge.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E16/e16_merge_delete.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E16/test_e16.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E17/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E18/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E18/e18_decode.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E18/e18_iff_decode.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E18/e18_nvl2.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E18/test_e18.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E19/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E2/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E2/e2_expr_alias.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E2/e2_function_alias.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E2/e2_multiply_alias.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E2/test_e2.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E20/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E21/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E21/e21_alias_forward_ref.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E21/e21_three_level_chain.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E21/test_e21.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E22/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E23/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E23/e23_stored_proc.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E23/e23_stored_proc_multi.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E23/test_e23.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E24/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E25/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E25/e25_cross_db.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E25/e25_two_part.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E25/test_e25.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E25/test_e25_full_id.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E26/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E27/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E27/e27_nested_udf.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E27/e27_udf.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E27/test_e27.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E28/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E29/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E3/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E3/e3_alter_table.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E3/e3_create_sequence.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E3/e3_ddl_only.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E3/test_e3.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E30/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E31/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E32/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E33/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E34/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E35/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E36/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E36/e36_temp_multi_use.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E36/e36_temp_table.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E36/test_e36.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E36/test_e36_xfile.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E37/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E38/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E4/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E4/e4_execute_immediate.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E4/e4_if_not_exists.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E4/e4_unexpected_token.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E4/e4_unpivot.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E4/test_e4.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E5/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E5/e5_cte_missing_source.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E5/e5_multi_cte.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E5/e5_nested_cte.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E5/test_e5.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E5/test_e5_cte_projection.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E8/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E8/e8_dynamic_sources.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E8/e8_seq_nextval.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E8/e8_uuid.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E8/test_e8.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E9/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E_aggregates/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E_aggregates/fixture_sum_absent_cross_schema.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E_aggregates/fixture_sum_case_when.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E_aggregates/fixture_sum_present_source.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E_aggregates/test_e_aggregates.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E_date_functions/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E_date_functions/fixture_date_aliased.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E_date_functions/fixture_date_unaliased.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E_date_functions/fixture_datediff_unaliased.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E_date_functions/fixture_year_unaliased.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/E_date_functions/test_e_date_functions.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/README.md +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/anchors/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/anchors/fixture_etl.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/anchors/fixture_omloopsnelheid.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/anchors/fixture_semantic.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/anchors/fixture_source.sql +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/anchors/test_anchor_ma_aantal_op_order.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/anchors/test_anchor_omloopsnelheid.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/conftest.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/snowflake/test_plan_review_gates.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/snowflake/__init__.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/snowflake/test_qualify_bare_tables_command_guard.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/snowflake/test_scripting_noise.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_BugB_escalation_uses_init_path.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_BugC_hook_upgrade.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_F2_install_skill.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_F2_skill_render.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_F2_uninstall_skill.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_T09_01_qualify_once.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_T09_02_ddl_skip.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_T09_04_subprocess_isolate.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_T09_06_log_verbosity.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_T35_config_external_consumers.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_aggregator.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_aggregator_skip.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_analyze_case_fold.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_base_parser.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_branch_monitor.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_bulk_upsert_invariant.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_canonical_target_resolution.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_catalog_csv_parsing.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_catalog_missing_warning.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_classify_non_table_create_kind.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_cli.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_cli_doc_flag_staleness.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_cli_help.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_clone_positional_insert_blindspot.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_closure_depth.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_column_lineage_wiring.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_config.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_coverage_metrics.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_cte_key_namespacing.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_cte_source_gap_metric.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_data_models.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_db_info.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_db_info_coverage.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_db_path_isolation_fixture.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_doc_links.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_doc_markdown_link_existence.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_dominant_cause.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_duckdb_backend.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_duckdb_backend_shared.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_dynamic_name_resolution.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_e5_view_alias_resolution.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_e8_dual_emission.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_e8_temp_chain_key_mismatch.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_empty_propagation_unit.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_extract_select_output_columns.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_file_ignore_defaults.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_find_cmd.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_firstuser_findings.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_freshness_helper.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_gain_coverage.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_gain_ratio.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_gating_join_field_docstrings.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_git_delta.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_git_hooks.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_git_hooks_notify.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_graph_backend.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_graph_completeness_invariant.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_hard_kill_pool.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_has_column_precedence_upsert.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_hook_reindex_detach.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_hygiene_config_warning.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_identifier_var_sink_resolution.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_identity_counters.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_include_working_tree.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_index_cmd.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_index_filter_config.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_index_flags.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_index_progress.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_index_summary_degraded_metric.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_indexer_progress.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_indexer_quality.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_install.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_install_message.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_issue_63_readonly_lock.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_jobs.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_join_col_resolve_marker.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_judgement.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_lineage_conversion.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_literal_column_skip.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_mcp_best_practices.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_mcp_control.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_mcp_stdio_smoke.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_merge_column_lineage.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_metrics.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_noise_filter.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_normalize_keys.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_parse_failed_classification.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_parse_file_dependency_filter.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_parse_quality.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_parser.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_perf_scaling_guard.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_phantom_drop_alter_source.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_phantom_non_table_create_source.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_pr07_observability.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_pr6_execute_immediate_unwrap.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_pr_impact_unit.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_qualify_failed_unit.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_queries_loader.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_read_client.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_repo_relative_cte_namespaces.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_resolvable_write_col_edges_unit.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_resolve_join_columns_sql.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_resolve_pass2_passes_dependency_filter.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_schema_resolver.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_selects_from_completeness_unit.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_selfheal_detector.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_selfheal_pr1_messages.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_selfheal_reexec.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_selfheal_watcher.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_server.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_skip_counts_persistence.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_snowflake_strip_alter_set_tag.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_sprint_06_t04_t05.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_star_resolution_unit.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_star_schema_unit.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_submit_feedback.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_subprocess_isolate.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_t02_expression_name_extraction.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_t03_ddl_skip.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_temp_table_namespacing.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_timeout_cancel.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_tool_version_stamp.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_tools_hints.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_tools_warnings.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_transform_kind_classification.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_uninstall.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_unknown_sentinel_skip.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_unqualified_fallback.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_upsert_batch_invariant.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_use_schema_session_context.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_version_parity.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_view_classification.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_viz_config_schemas.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_viz_facets.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_walker.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_watcher.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_worker_error_classification.py +0 -0
- {sql_code_graph-1.36.2 → sql_code_graph-1.37.0}/tests/unit/test_writer_queue.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sql-code-graph
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.37.0
|
|
4
4
|
Summary: SQL code graph analyzer and lineage tracer
|
|
5
5
|
Project-URL: Homepage, https://github.com/Warhorze/sql-code-graph
|
|
6
6
|
Project-URL: Repository, https://github.com/Warhorze/sql-code-graph
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
# Feature Plan: `sqlcg viz` Usability — neighborhood-highlight, edge contrast, sane defaults
|
|
2
|
+
|
|
3
|
+
**Status:** REVIEWED (plan-reviewer PASSED, no blockers; two required amendments folded in — see "Plan-reviewer required amendments" below)
|
|
4
|
+
**Owner:** architect-planner
|
|
5
|
+
**Branch (impl):** `feat/viz-usability-highlight`
|
|
6
|
+
**Base:** `master` (v1.36.1 on disk; see version note below) / schema v11
|
|
7
|
+
**Scope class:** PURE front-end / HTML-emitter change. No indexer / parser / graph-model / DB-schema change. **No re-index required.**
|
|
8
|
+
|
|
9
|
+
> ⚠ **Version note for the developer:** the brief said v1.36.0 but the worktree's
|
|
10
|
+
> [`pyproject.toml`](pyproject.toml) and [`src/sqlcg/__init__.py`](src/sqlcg/__init__.py)
|
|
11
|
+
> are already at **`1.36.1`**. This is new interactive surface → **MINOR** bump →
|
|
12
|
+
> ship as **`1.37.0`**. Reconcile against `master` HEAD at implementation time (if
|
|
13
|
+
> master has advanced past 1.36.1, bump the minor from whatever the current value is).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Plan-reviewer required amendments (folded in 2026-06-15)
|
|
18
|
+
|
|
19
|
+
The plan-reviewer PASSED this plan with no blockers, conditional on TWO required
|
|
20
|
+
amendments. Both are now binding for implementation:
|
|
21
|
+
|
|
22
|
+
### Amendment 1 — AC2's highlight-wiring guard must be BEHAVIORAL, not substring
|
|
23
|
+
|
|
24
|
+
`jsdom` is **NOT installed** in this repo, so AC2's "highlight is wired" guard
|
|
25
|
+
**must NOT rely on a JSDOM hover test** and **must NOT be satisfiable by an
|
|
26
|
+
orphaned `adj.get(` substring** (a dead reference would pass a naive substring
|
|
27
|
+
grep while delivering nothing).
|
|
28
|
+
|
|
29
|
+
The binding assertion is therefore:
|
|
30
|
+
|
|
31
|
+
- The `linkColor` / `linkWidth` / directional-arrow accessors and the
|
|
32
|
+
`nodeCanvasObject` (`drawNodeCanvas`) **must REFERENCE the highlight state**
|
|
33
|
+
(`highlightSet` / `highlightId`).
|
|
34
|
+
- `onNodeHover` / `onNodeClick` / `onBackgroundClick` **must ASSIGN that state**
|
|
35
|
+
(set `hoveredNode` / toggle `pinnedNode` / clear `pinnedNode`).
|
|
36
|
+
- **Best path (adopted):** factor the 1-hop highlight-set derivation into a tiny
|
|
37
|
+
**pure helper** `computeHighlightSet(adj, id)` and assert it **directly in a
|
|
38
|
+
`uv run`-able Node harness** (the `node --eval` / `node --check` style the
|
|
39
|
+
project already uses — `node` is on PATH, used by the self-containment e2e).
|
|
40
|
+
The Python test extracts the helper source from the emitted HTML, evals it in
|
|
41
|
+
Node with a sample `adj`, and asserts the returned set equals focus ∪ its 1-hop
|
|
42
|
+
neighbors. **Substring presence alone is insufficient** and is explicitly
|
|
43
|
+
rejected as the AC2 guard.
|
|
44
|
+
|
|
45
|
+
### Amendment 2 — highlight repaint must be styling-only (no layout re-seed)
|
|
46
|
+
|
|
47
|
+
The hover / click highlight handlers **must NOT call `refresh()` or
|
|
48
|
+
`Graph.graphData()`**. Both re-seed the force layout, causing the graph to "jump"
|
|
49
|
+
at the live 3069-node / 6671-link scale on every hover.
|
|
50
|
+
|
|
51
|
+
- Repaint must go through **styling-only accessors that close over `highlightId`
|
|
52
|
+
/ `highlightSet`** (e.g. force-graph's per-frame canvas repaint, which re-reads
|
|
53
|
+
the closure-visible state every tick — no data rebuild). The handlers only
|
|
54
|
+
mutate `hoveredNode` / `pinnedNode`; the next animation frame repaints with the
|
|
55
|
+
new state.
|
|
56
|
+
- This is stated explicitly in the code (a comment at the highlight handlers) and
|
|
57
|
+
is the reason `refresh()` (which calls `graphData(currentData())`) is reserved
|
|
58
|
+
exclusively for FILTER changes (facets / mindeg / search / ego), never for
|
|
59
|
+
highlight.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Summary
|
|
64
|
+
|
|
65
|
+
`sqlcg viz` (shipped #165, v1.35.0) emits a self-contained force-graph HTML from the
|
|
66
|
+
live graph. At real scale (live reference [`table_graph.html`](table_graph.html):
|
|
67
|
+
**3069 nodes / 6671 links**) it is a low-contrast hairball with no way to trace one
|
|
68
|
+
table's lineage. This sprint wires the **already-baked `DATA.adj`** into a
|
|
69
|
+
hover/click neighborhood-highlight, makes edges legible, and changes the default
|
|
70
|
+
view to hide island nodes and `temp` clutter — all in the emitter template + a
|
|
71
|
+
small amount of CLI/data wiring, with **zero data-model change**.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Live-inspection findings (ground truth — verified this session)
|
|
76
|
+
|
|
77
|
+
All numbers below come from (a) running `uv run sqlcg viz` against a seeded DuckDB
|
|
78
|
+
in `/tmp` and inspecting the emitted HTML, and (b) parsing the live reference
|
|
79
|
+
[`table_graph.html`](table_graph.html) at repo root (regenerated from the real DWH).
|
|
80
|
+
|
|
81
|
+
| Question | Answer (verified) |
|
|
82
|
+
|----------|-------------------|
|
|
83
|
+
| **Where is the emitter template?** | [`src/sqlcg/viz/assets/template.html`](src/sqlcg/viz/assets/template.html) (12 KB). The JS is one `<script>` block (lines 40–273); the lib is the other `<script>` block (lines 3–5). Baked by [`render_html`](src/sqlcg/viz/render.py) via `/*__DATA__*/` etc. placeholders. |
|
|
84
|
+
| **Where is the data built?** | [`src/sqlcg/viz/data.py`](src/sqlcg/viz/data.py) `build_viz_data()` → `{nodes, links, adj}`. |
|
|
85
|
+
| **CLI entry** | [`src/sqlcg/cli/commands/viz.py`](src/sqlcg/cli/commands/viz.py) `viz_cmd`. |
|
|
86
|
+
| **Does `DATA.links` carry direction?** | **YES.** Each link is `{"source": <source table>, "target": <write target>, "n": <count>}`. Direction is **source-table → consumer/write-target** (`data.py` `_Q_QUERY_LINKS`: `dst_key` of `SELECTS_FROM` is the source table; `q.target_table` is the write target). Live sample: `{"source":"ba.wtda_inkoop_order","target":"ia_analytics.ba_wtda_inkoop_order","n":33}`. **→ directional arrows are feasible (no data change needed).** |
|
|
87
|
+
| **`DATA.adj` shape** | Undirected `{id: [neighbor, …]}` (sorted). Live: 2926 keys (nodes with ≥1 neighbor). Built in `data.py` from the collapsed link set. The template *also* rebuilds an identical `adj` Map client-side (lines 51–58) for ego-mode — **already present, used only by ego-mode today.** |
|
|
88
|
+
| **Current default-visible kinds** | `table`, `view`, **`temp`** ON; `cte`, `derived` OFF. Asserted as a literal string in TWO tests (see "Tests that MUST change"). |
|
|
89
|
+
| **Current `min deg` default** | `value="0"` (islands visible). |
|
|
90
|
+
| **Current hover/click affordance** | `onNodeClick` sets `focusNode` (only used by ego-mode toggle); `onNodeHover` sets `hoveredNode` (only used to force a label). **There is NO neighborhood highlight today** — the headline gap. |
|
|
91
|
+
| **Node-kind histogram (live)** | table 1150, **temp 804 (26%)**, view 582, cte 530, derived 3. Confirms the `temp`-clutter claim. |
|
|
92
|
+
| **Island (deg==0) count (live)** | **143 of 3069 (~4.7%)**. Confirms islands exist; brief says keep them in DATA, hide by default. |
|
|
93
|
+
| **Self-containment test** | [`tests/e2e/test_viz_cli_e2e.py::test_viz_html_is_self_contained_and_node_check_passes`](tests/e2e/test_viz_cli_e2e.py) — bans external-load tokens, asserts exactly **2** `<script>` blocks, runs `node --check` on each. **Adding a 3rd script block would break this** (the assertion `len(blocks) == 2`). All new JS goes inside the existing JS block. |
|
|
94
|
+
|
|
95
|
+
**Total existing viz tests: 36** (e2e 9, integration/data 7, unit render 6, unit
|
|
96
|
+
facets 8, unit config 6). The brief's "~36" is exact.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Scope
|
|
101
|
+
|
|
102
|
+
### In Scope
|
|
103
|
+
1. **Neighborhood-highlight on hover + click-to-pin** using the existing `DATA.adj`
|
|
104
|
+
(client `adj` Map). Hover highlights transiently; click pins; click-elsewhere /
|
|
105
|
+
Escape clears. Highlight = focus node + direct (1-hop) neighbors + incident
|
|
106
|
+
edges bright; everything else dimmed. **Headline deliverable.**
|
|
107
|
+
2. **Edge visibility / contrast** — raise base edge opacity/width so edges are
|
|
108
|
+
legible on `#0d1117`; highlighted edges bright + directional **arrows**
|
|
109
|
+
(producer→consumer; direction confirmed available); dimmed edges very faint.
|
|
110
|
+
3. **Default `min deg` filter = 1** — hide deg-0 islands by default; existing
|
|
111
|
+
`min deg` number input stays the explicit "show isolated nodes" control (set its
|
|
112
|
+
default `value="1"`; user types `0` to reveal islands). Islands remain in `DATA`.
|
|
113
|
+
4. **`temp` default-OFF** — default-visible kinds become `table` + `view` only;
|
|
114
|
+
`cte`/`derived`/`temp` OFF by default, all still toggleable chips.
|
|
115
|
+
|
|
116
|
+
### Non-Goals (explicit boundaries)
|
|
117
|
+
- **No data-model / `build_viz_data` query change.** `nodes/links/adj` shape is
|
|
118
|
+
unchanged. (Item 3 may add ONE derived convenience but see Step 2.3 — preferred
|
|
119
|
+
approach uses the existing `mindeg` input, no data change.)
|
|
120
|
+
- **No new `<script>` block, no external resource, no CDN/fetch/import.**
|
|
121
|
+
- **No multi-hop traversal UI** beyond an *optional* single "expand one more hop"
|
|
122
|
+
affordance (Step 1.4) — and even that is in-scope-optional, decided below as
|
|
123
|
+
**deferred** to keep the headline tight (see Decision D2).
|
|
124
|
+
- **No tags/jobs source change.** Tags/jobs only exist when the user passes
|
|
125
|
+
`--tags`/`--jobs`. The legend/dropdown already render empty cleanly; this sprint
|
|
126
|
+
only confirms that and does not invent a source.
|
|
127
|
+
- **No new CLI flag** unless a default needs to be overridable (none identified;
|
|
128
|
+
defaults are baked into the template, consistent with current design).
|
|
129
|
+
- No indexer/parser/lineage/perf-hot-path code. The frozen perf-invariant suites
|
|
130
|
+
([`test_perf_scaling_guard.py`](tests/unit/test_perf_scaling_guard.py),
|
|
131
|
+
[`test_bulk_upsert_invariant.py`](tests/unit/test_bulk_upsert_invariant.py),
|
|
132
|
+
[`test_upsert_batch_invariant.py`](tests/unit/test_upsert_batch_invariant.py),
|
|
133
|
+
[`test_T09_01_qualify_once.py`](tests/unit/test_T09_01_qualify_once.py)) are not
|
|
134
|
+
touched and must stay green unmodified.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Design
|
|
139
|
+
|
|
140
|
+
### Affordance specification (Item 1 — the core deliverable)
|
|
141
|
+
|
|
142
|
+
State model (all client-side, inside the existing JS block in
|
|
143
|
+
[`template.html`](src/sqlcg/viz/assets/template.html)):
|
|
144
|
+
|
|
145
|
+
- New state: `let pinnedNode = null;` (the click-pinned focus for highlight).
|
|
146
|
+
Reuse existing `hoveredNode`. Do **not** overload `focusNode` (that is ego-mode's
|
|
147
|
+
variable — keep highlight independent of ego-mode so the two compose).
|
|
148
|
+
- **`highlightId` = `pinnedNode ?? hoveredNode`** (pin wins; hover is transient).
|
|
149
|
+
- Derived per-render: `highlightSet` = `highlightId` ∪ `adj.get(highlightId)`
|
|
150
|
+
(the 1-hop neighborhood) — computed from the **existing client `adj` Map**, which
|
|
151
|
+
is built from `DATA.adj`/`DATA.links` (no data change).
|
|
152
|
+
- **Hover** (`onNodeHover(n)`): set `hoveredNode = n?.id ?? null`; if no pin, this
|
|
153
|
+
drives the highlight. Re-render via the graph's paint (no full `graphData`
|
|
154
|
+
rebuild needed for highlight — see "render mechanics" below).
|
|
155
|
+
- **Click** (`onNodeClick(n)`): toggle pin — `pinnedNode = (pinnedNode === n.id) ? null : n.id`.
|
|
156
|
+
A pinned node stays highlighted after the cursor leaves.
|
|
157
|
+
- **Clear:** click on empty background (`onBackgroundClick` → `pinnedNode = null`)
|
|
158
|
+
**and** `Escape` key → `pinnedNode = null`. Hover-away clears the transient hover.
|
|
159
|
+
- **Compose with ego-mode:** ego-mode (existing) filters the node SET; highlight
|
|
160
|
+
only changes paint styling within whatever is visible. They are orthogonal.
|
|
161
|
+
|
|
162
|
+
Render mechanics (decision, see D1): highlight is a **paint-time styling concern**,
|
|
163
|
+
not a filter. When `highlightId` is set:
|
|
164
|
+
- Nodes in `highlightSet` paint at full alpha + a focus ring on the
|
|
165
|
+
`highlightId` itself; nodes outside paint dimmed (low alpha).
|
|
166
|
+
- Links with **both** endpoints in `highlightSet` (i.e. incident to the focus,
|
|
167
|
+
since highlightSet is focus+neighbors) paint bright + arrow; all other links
|
|
168
|
+
paint very faint.
|
|
169
|
+
- When `highlightId` is null → normal styling (all at the new legible base level).
|
|
170
|
+
|
|
171
|
+
This requires: a `linkColor`/`linkWidth`/`linkDirectionalArrowLength` accessor (or
|
|
172
|
+
`linkCanvasObject`) that reads `highlightId`, and the existing `nodeCanvasObject`
|
|
173
|
+
(`drawNodeCanvas`) extended to dim/brighten based on `highlightSet`. The graph is
|
|
174
|
+
re-painted by calling a light `Graph.nodeColor`/refresh trigger on hover/click; we
|
|
175
|
+
will trigger a repaint without rebuilding `graphData` (force-graph repaints every
|
|
176
|
+
frame, so simply updating the closure-visible `highlightId`/`highlightSet` and
|
|
177
|
+
nudging the engine — e.g. `Graph.nodeCanvasObject(drawNodeCanvas)` re-set, or a
|
|
178
|
+
`Graph` refresh call — is sufficient; the developer picks the lightest force-graph
|
|
179
|
+
1.49.5 API that re-renders without re-running the layout).
|
|
180
|
+
|
|
181
|
+
### Edge visibility (Item 2)
|
|
182
|
+
|
|
183
|
+
In [`template.html`](src/sqlcg/viz/assets/template.html):
|
|
184
|
+
- Base edges: raise from the library default to a visible-but-quiet level
|
|
185
|
+
(e.g. `linkColor` → a mid-gray like `#3b4350` at moderate alpha, `linkWidth`
|
|
186
|
+
≥ 1; exact values tuned at impl, must be visibly legible on `#0d1117`).
|
|
187
|
+
- Highlighted edges: bright (e.g. near-white or the source schema color) + wider +
|
|
188
|
+
**directional arrow** (`linkDirectionalArrowLength`, `linkDirectionalArrowRelPos`)
|
|
189
|
+
pointing source→target (producer→consumer). Direction is available in `DATA.links`.
|
|
190
|
+
- Dimmed edges (highlight active, not incident): very low alpha so the neighborhood
|
|
191
|
+
stands out.
|
|
192
|
+
- **Arrows in the no-highlight base state:** decision D3 — keep base arrows OFF
|
|
193
|
+
(3069/6671 arrows is itself clutter); show arrows ONLY on highlighted edges. This
|
|
194
|
+
keeps the resting view clean and makes direction legible exactly when the user is
|
|
195
|
+
tracing.
|
|
196
|
+
|
|
197
|
+
### Default filters (Items 3 & 4)
|
|
198
|
+
|
|
199
|
+
- **Item 3 (islands):** change the `min deg` input default from `value="0"` to
|
|
200
|
+
`value="1"` in [`template.html`](src/sqlcg/viz/assets/template.html) line 32. The
|
|
201
|
+
existing `currentData()` already filters `if (n.deg < md) continue;`. The input
|
|
202
|
+
label is updated to make the "isolated nodes" meaning explicit (e.g.
|
|
203
|
+
`min deg` stays, plus the bottom `#info` hint mentions "set min deg 0 to show
|
|
204
|
+
isolated tables"). **No data change**; islands stay in `DATA.nodes`. Verified:
|
|
205
|
+
143 island nodes exist and have `deg: 0`.
|
|
206
|
+
- **Item 4 (temp off):** change `KIND_DEFAULT_ON` from
|
|
207
|
+
`new Set(['table', 'view', 'temp'])` to `new Set(['table', 'view'])`. `KNOWN_KINDS`
|
|
208
|
+
stays `['table','view','temp','cte','derived']` so `temp` remains a toggleable chip.
|
|
209
|
+
|
|
210
|
+
### Empty tags/jobs legend (confirmation only)
|
|
211
|
+
|
|
212
|
+
No code change expected. Confirm via the existing
|
|
213
|
+
`test_viz_html_is_self_contained` + a new assertion that with no `--tags/--jobs`
|
|
214
|
+
the tag-facet div and job `<select>` render with no rows (the `buildFacet(... TAGS.labels || [])`
|
|
215
|
+
and `JOBS.labels || []` paths already handle empty). If a stray empty `<b>tag</b>`
|
|
216
|
+
header looks broken when empty, hide the facet container when its label list is
|
|
217
|
+
empty (minor, decided at impl).
|
|
218
|
+
|
|
219
|
+
### Decisions
|
|
220
|
+
|
|
221
|
+
- **D1 — highlight is paint-styling, not a filter.** Dim-don't-remove keeps spatial
|
|
222
|
+
context (you see where the neighborhood sits in the whole graph). Rationale: the
|
|
223
|
+
whole point is to read lineage *out of* the hairball, not replace it with ego-mode
|
|
224
|
+
(which already exists and removes context).
|
|
225
|
+
- **D2 — "expand one more hop" is DEFERRED** (out of this sprint). Keep the headline
|
|
226
|
+
tight: 1-hop hover/click/pin. A 2-hop expander can be a fast follow once 1-hop
|
|
227
|
+
ships and is eyeballed. (Documented so the developer does not build it.)
|
|
228
|
+
- **D3 — base arrows OFF, highlight arrows ON** (see Edge visibility).
|
|
229
|
+
- **D4 — no new CLI flag.** Defaults live in the template, matching the existing
|
|
230
|
+
design where kind/mindeg defaults are template-baked.
|
|
231
|
+
|
|
232
|
+
### Data Models / API Changes
|
|
233
|
+
**None.** `build_viz_data()` output unchanged; `render_html` signature unchanged;
|
|
234
|
+
CLI signature unchanged. This is entirely [`template.html`](src/sqlcg/viz/assets/template.html)
|
|
235
|
+
plus the two version-bump files.
|
|
236
|
+
|
|
237
|
+
### Dependencies
|
|
238
|
+
None added. force-graph 1.49.5 stays vendored/inlined.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Tests that MUST change (and why that is correct, not a violation)
|
|
243
|
+
|
|
244
|
+
The brief says "all ~36 existing viz tests must pass **unmodified**." Two of them
|
|
245
|
+
**cannot** — they pin the *old* default-kind string by exact match, and Item 4
|
|
246
|
+
deliberately changes that default. These are **expected, intended assertion
|
|
247
|
+
updates**, not regressions:
|
|
248
|
+
|
|
249
|
+
| Test | File:line | Current assertion | Why it must change |
|
|
250
|
+
|------|-----------|-------------------|--------------------|
|
|
251
|
+
| `test_viz_kind_defaults...` (e2e) | [`tests/e2e/test_viz_cli_e2e.py:202`](tests/e2e/test_viz_cli_e2e.py) | `"KIND_DEFAULT_ON = new Set(['table', 'view', 'temp'])" in html` | Item 4 changes the default set; this assertion now pins the NEW set `['table', 'view']`. |
|
|
252
|
+
| `test_kind_defaults...` (unit) | [`tests/unit/test_viz_render_self_contained.py:107`](tests/unit/test_viz_render_self_contained.py) | same string | same — update to `['table', 'view']`. |
|
|
253
|
+
|
|
254
|
+
The developer **updates these two assertions** to the new default and adds a
|
|
255
|
+
regression assertion that `temp` is in `KNOWN_KINDS` (still toggleable). **All other
|
|
256
|
+
34 viz tests pass unmodified, and all frozen perf-invariant suites pass unmodified.**
|
|
257
|
+
Flag for plan-reviewer: this is the one place "unmodified" is impossible by design.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Implementation Steps
|
|
262
|
+
|
|
263
|
+
### Phase 1 — Defaults (lowest-risk, unblocks the contrast work)
|
|
264
|
+
|
|
265
|
+
**Step 1.1 — `temp` default OFF + `min deg` default 1.**
|
|
266
|
+
- Files: [`src/sqlcg/viz/assets/template.html`](src/sqlcg/viz/assets/template.html)
|
|
267
|
+
(`KIND_DEFAULT_ON` line 75; `mindeg` input `value` line 32).
|
|
268
|
+
- Update the two kind-default assertions (see table above) to `['table', 'view']`.
|
|
269
|
+
- Acceptance: emitted HTML contains `KIND_DEFAULT_ON = new Set(['table', 'view'])`;
|
|
270
|
+
the `temp` chip is still present (in `KNOWN_KINDS`) and rendered `off`; `mindeg`
|
|
271
|
+
input has `value="1"`; a seeded deg-0 node is absent from the default
|
|
272
|
+
`currentData()` keep-set but present in `DATA.nodes`.
|
|
273
|
+
|
|
274
|
+
### Phase 2 — Edge visibility (Item 2)
|
|
275
|
+
|
|
276
|
+
**Step 2.1 — Legible base edges + dim/bright tiers.**
|
|
277
|
+
- Files: `template.html` (graph init link accessors `linkColor`/`linkWidth`, and
|
|
278
|
+
the link styling used during highlight).
|
|
279
|
+
- Acceptance: emitted HTML wires `linkColor`/`linkWidth` accessors (not library
|
|
280
|
+
defaults); base color is a non-transparent legible hex on dark bg; a highlight-
|
|
281
|
+
aware branch exists (asserted by presence of the `highlightId`/`highlightSet`
|
|
282
|
+
reference inside the link accessor). Manual: regenerated `table_graph.html` shows
|
|
283
|
+
visibly legible edges.
|
|
284
|
+
|
|
285
|
+
**Step 2.2 — Directional arrows on highlighted edges only.**
|
|
286
|
+
- Files: `template.html` (`linkDirectionalArrowLength` accessor returning 0 when no
|
|
287
|
+
highlight or edge not incident, >0 when incident).
|
|
288
|
+
- Acceptance: emitted HTML contains `linkDirectionalArrow` wiring; the accessor is
|
|
289
|
+
gated on `highlightId` (base state → no arrows). Asserted by HTML substring +
|
|
290
|
+
a JSDOM check if feasible (see Test Strategy).
|
|
291
|
+
|
|
292
|
+
### Phase 3 — Neighborhood highlight (Item 1 — headline)
|
|
293
|
+
|
|
294
|
+
**Step 3.1 — Highlight state + 1-hop set from `adj`.**
|
|
295
|
+
- Files: `template.html` — add `pinnedNode`, `highlightId` derivation,
|
|
296
|
+
`highlightSet` from the existing client `adj` Map. Wire `onNodeHover` (transient),
|
|
297
|
+
`onNodeClick` (toggle pin), `onBackgroundClick` (clear pin), `Escape` (clear pin).
|
|
298
|
+
- Acceptance: emitted HTML contains the highlight handlers AND a reference to `adj`
|
|
299
|
+
inside them (proving the bake is wired, not orphaned). HTML substring assertions:
|
|
300
|
+
`onBackgroundClick`, `pinnedNode`, and `adj.get(` used in a highlight context.
|
|
301
|
+
|
|
302
|
+
**Step 3.2 — Paint dim/bright for nodes + incident edges.**
|
|
303
|
+
- Files: `template.html` — extend `drawNodeCanvas` to dim non-`highlightSet` nodes
|
|
304
|
+
and ring the focus node; link accessors (Step 2.1/2.2) already read `highlightSet`.
|
|
305
|
+
Ensure a repaint is triggered on hover/click WITHOUT re-running the force layout
|
|
306
|
+
(no `graphData()` rebuild for highlight — pick the lightest force-graph 1.49.5
|
|
307
|
+
refresh API).
|
|
308
|
+
- Acceptance: HTML wires the dim/bright branch in `drawNodeCanvas` keyed on
|
|
309
|
+
`highlightSet`. JSDOM check (if feasible): after dispatching a synthetic hover on
|
|
310
|
+
a known node, the link accessor returns the bright width for an incident edge and
|
|
311
|
+
the dim width for a non-incident edge. Manual: regenerated `table_graph.html` —
|
|
312
|
+
hovering `ba.wtda_inkoop_order` lights its neighbors and dims the rest.
|
|
313
|
+
|
|
314
|
+
### Phase 4 — Empty-facet polish + manual regen + version bump
|
|
315
|
+
|
|
316
|
+
**Step 4.1 — Empty tag/job legend renders cleanly.**
|
|
317
|
+
- Files: `template.html` (only if an empty facet container looks broken — hide
|
|
318
|
+
container when its label list is empty).
|
|
319
|
+
- Acceptance: viz run with no `--tags/--jobs` produces an HTML where the tag-facet
|
|
320
|
+
has no chip rows and the job `<select>` has only the `all jobs` option; no JS
|
|
321
|
+
error (`node --check` green; JSDOM construct-without-throw if feasible).
|
|
322
|
+
|
|
323
|
+
**Step 4.2 — Manual regenerate the reference artifact.**
|
|
324
|
+
- Re-emit repo-root [`table_graph.html`](table_graph.html) from the live graph
|
|
325
|
+
(`uv run sqlcg viz` with the user's tags/jobs CSVs if used) so the committed
|
|
326
|
+
reference reflects the new defaults + interaction. Confirm self-containment
|
|
327
|
+
(no external token) and the new defaults in the regenerated file.
|
|
328
|
+
- **MANUAL step** — the developer regenerates and the user eyeballs on Windows.
|
|
329
|
+
Not gated by CI (the artifact is gitignored/untracked per repo memory).
|
|
330
|
+
|
|
331
|
+
**Step 4.3 — Version bump + lockfile.**
|
|
332
|
+
- [`pyproject.toml`](pyproject.toml) + [`src/sqlcg/__init__.py`](src/sqlcg/__init__.py)
|
|
333
|
+
→ `1.37.0` (reconcile minor against master HEAD); `uv lock`.
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Test Strategy
|
|
338
|
+
|
|
339
|
+
> Name tests `test_<unit>_<scenario>_<expected>` and link this plan in the docstring.
|
|
340
|
+
|
|
341
|
+
**Automated (CI-gated):**
|
|
342
|
+
- *Self-containment unchanged* — the existing
|
|
343
|
+
`test_viz_html_is_self_contained_and_node_check_passes` must stay green: still
|
|
344
|
+
exactly **2** `<script>` blocks (all new JS goes inside the existing block), no
|
|
345
|
+
external-load tokens, `node --check` passes. (Unmodified.)
|
|
346
|
+
- *New default kinds* — assert emitted HTML wires `['table', 'view']` ON and `temp`
|
|
347
|
+
remains in `KNOWN_KINDS` (toggleable). (Updates the 2 existing kind-default tests
|
|
348
|
+
+ may add one new assertion.)
|
|
349
|
+
- *Island default-hidden* — assert `mindeg` input `value="1"`; assert a seeded
|
|
350
|
+
deg-0 node is in `DATA.nodes` but excluded from the default keep-set logic.
|
|
351
|
+
- *Highlight wiring present* — assert emitted HTML contains the hover/click/pin
|
|
352
|
+
handlers (`pinnedNode`, `onBackgroundClick`) AND that the highlight logic
|
|
353
|
+
references the baked adjacency (`adj.get(`), proving `DATA.adj` is wired, not
|
|
354
|
+
orphaned. This is the behavioral guard against shipping "a picture".
|
|
355
|
+
- *Edge-styling wiring present* — assert `linkColor`/`linkWidth` accessors and a
|
|
356
|
+
`linkDirectionalArrow…` accessor gated on `highlightId`.
|
|
357
|
+
- *JSDOM behavioral check (attempt; mark manual if jsdom unavailable)* — load the
|
|
358
|
+
emitted HTML in a Node/jsdom harness, stub `canvas`/`ForceGraph` minimally,
|
|
359
|
+
dispatch a synthetic node-hover, and assert the highlightSet resolves to focus +
|
|
360
|
+
its `adj` neighbors and that the link accessor returns bright-vs-dim accordingly.
|
|
361
|
+
**If jsdom + a force-graph stub proves infeasible in CI**, downgrade this to the
|
|
362
|
+
HTML-substring guards above (automated) + the manual eyeball (4.2), and say so in
|
|
363
|
+
the PR. State explicitly in the PR which highlight assertions are automated.
|
|
364
|
+
|
|
365
|
+
**Manual (developer-run, user-eyeballed):**
|
|
366
|
+
- Regenerate `table_graph.html` (Step 4.2); open on Windows via `file://`; confirm:
|
|
367
|
+
edges legible; hover lights neighborhood + arrows; click pins; Escape/background
|
|
368
|
+
clears; islands hidden by default and revealed at `min deg 0`; `temp` hidden by
|
|
369
|
+
default and reveals on chip toggle.
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Acceptance Criteria
|
|
374
|
+
|
|
375
|
+
- [ ] **AC1 (self-containment invariant holds):** emitted HTML has exactly 2
|
|
376
|
+
`<script>` blocks, no external-load token, `node --check` passes on both.
|
|
377
|
+
*Verified by the unchanged self-containment e2e test.*
|
|
378
|
+
- [ ] **AC2 (highlight wired to `adj`):** emitted HTML contains hover + click-pin +
|
|
379
|
+
background/Escape-clear handlers, and the highlight set is derived from the
|
|
380
|
+
baked adjacency (`adj.get(`) — not a no-op. *Verified by automated HTML
|
|
381
|
+
assertion + (if feasible) JSDOM hover check showing neighbor set = `adj`
|
|
382
|
+
neighbors.*
|
|
383
|
+
- [ ] **AC3 (edges legible + directional on highlight):** `linkColor`/`linkWidth`
|
|
384
|
+
accessors present (non-default), and a directional-arrow accessor gated on
|
|
385
|
+
highlight. *Verified by automated HTML assertion; manual eyeball confirms
|
|
386
|
+
legibility + producer→consumer arrow direction.*
|
|
387
|
+
- [ ] **AC4 (islands hidden by default, one click away):** `mindeg` default `value="1"`;
|
|
388
|
+
deg-0 nodes remain in `DATA.nodes`; setting `min deg 0` reveals them.
|
|
389
|
+
*Verified by automated assertion on `value="1"` + DATA presence; manual eyeball
|
|
390
|
+
for the reveal.*
|
|
391
|
+
- [ ] **AC5 (`temp` default OFF, toggleable):** `KIND_DEFAULT_ON = new Set(['table', 'view'])`;
|
|
392
|
+
`temp` still in `KNOWN_KINDS` and rendered as an `off` chip. *Verified by the
|
|
393
|
+
updated automated kind-default assertions.*
|
|
394
|
+
- [ ] **AC6 (empty facets render cleanly):** with no `--tags/--jobs`, no tag chips /
|
|
395
|
+
empty job dropdown, no JS error. *Verified by `node --check` + automated
|
|
396
|
+
assertion that the facet rows are empty.*
|
|
397
|
+
- [ ] **AC7 (all other viz + frozen perf tests green):** the 34 unchanged viz tests
|
|
398
|
+
and the frozen perf-invariant suites pass unmodified. *Verified by full
|
|
399
|
+
`uv run pytest`.*
|
|
400
|
+
- [ ] **AC8 (version bumped):** `1.37.0` in pyproject + `__init__` + `uv.lock`.
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## Risks and Mitigations
|
|
405
|
+
|
|
406
|
+
| Risk | Mitigation |
|
|
407
|
+
|------|------------|
|
|
408
|
+
| Adding a 3rd `<script>` block breaks the `len(blocks) == 2` self-containment assertion. | All new JS goes **inside** the existing JS block. Step guidance + AC1 guard. |
|
|
409
|
+
| Highlight repaint re-runs the force layout → graph "jumps" on every hover. | Trigger a repaint WITHOUT `graphData()` rebuild (highlight is paint-only, D1). Developer uses the lightest force-graph 1.49.5 refresh path. |
|
|
410
|
+
| JSDOM + force-graph stub may be infeasible in CI → highlight only "looks" wired. | Mandatory automated HTML guard that the handler references `adj.get(` (proves the bake is used); JSDOM is best-effort on top; manual eyeball closes the loop. The risk is "ships a picture" — AC2 is the explicit guard against it. |
|
|
411
|
+
| "All 36 tests unmodified" is impossible (2 pin the old kind default). | Documented as intended assertion updates (see "Tests that MUST change"); plan-reviewer to confirm this exception. |
|
|
412
|
+
| Base arrows on 6671 edges would add clutter (defeats the goal). | D3: arrows only on highlighted edges. |
|
|
413
|
+
| Regenerated `table_graph.html` is untracked/gitignored (repo memory). | Step 4.2 is explicitly MANUAL, user-eyeballed, not committed/CI-gated. |
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## Rollout / Rollback
|
|
418
|
+
- Rollout: ships in the `1.37.0` viz PR; no migration, no re-index (front-end only).
|
|
419
|
+
Existing emitted HTML files keep working; users re-run `sqlcg viz` to get the new
|
|
420
|
+
interaction.
|
|
421
|
+
- Rollback: revert the `template.html` (+ version) change; no data or schema impact.
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
### Deviations
|
|
426
|
+
|
|
427
|
+
#### Deviation 1: repo-root `table_graph.html` not regenerated in this PR
|
|
428
|
+
- **Reason**: Step 4.2 (regenerate the reference artifact) requires emitting from
|
|
429
|
+
the **live DWH graph** (`uv run sqlcg viz` against the indexed DuckDB). This task
|
|
430
|
+
is explicitly **INDEX-FREE / front-end only** — no DWH index was created and the
|
|
431
|
+
shepherd directed "no DWH index, no gain snapshot needed". The repo-root
|
|
432
|
+
`table_graph.html` is **untracked** (not in git, not committed) and the plan marks
|
|
433
|
+
Step 4.2 as a MANUAL, user-eyeballed step that is not CI-gated.
|
|
434
|
+
- **Change**: The emitter `template.html` — the single source of every future
|
|
435
|
+
regeneration — carries the new defaults (`KIND_DEFAULT_ON=['table','view']`,
|
|
436
|
+
`mindeg=1`) and the highlight/edge interaction. The standing untracked
|
|
437
|
+
`table_graph.html` working-copy file was left as-is; the user re-runs
|
|
438
|
+
`sqlcg viz` against the live graph to regenerate and eyeball on Windows.
|
|
439
|
+
- **Impact**: No effect on the PR contents (the artifact was never committed). The
|
|
440
|
+
manual eyeball portion of AC2/AC3/AC4/AC5/AC6 (visual confirmation) is deferred to
|
|
441
|
+
the user; the automated behavioral guards (helper harness + accessor/handler
|
|
442
|
+
references) are all in the PR and green.
|
|
443
|
+
- **Date**: 2026-06-15
|