{# Audit's object-overview detail page. Lists EVERY active issue + EVERY available SQL-rewrite suggestion for the requested opportunity's destination_table - not just one rule's findings. The cohort view at /jobs/{table} stays as the deep-dive (cost chart, Query versions). PR / dry-run / shadow surfaces are deliberately absent - audit is read-only and never generates solutions. #} {% extends "layout.html" %} {% block content %} {% from "components/_page_header.html" import back_link, header_card %} {# Hoisted from per-section conditional blocks because Jinja {% from %} scope is the enclosing block: when issue_cards is empty (suggestion- only opportunity) the issue-section's import never fires, but later sections like Available improvements still reference the macro - produces ``'section_title' is undefined``. Hoisting once at the top of the content block makes the macro available everywhere below. #} {% from "components/_section_title.html" import section_title %} {% from "components/_sql_panel.html" import sql_panel %}
{{ back_link("/opportunities", "Issues & Suggestions") }} {% set _path_parts = (row.affected_table or '').split('.') %} {% set _dataset = _path_parts[1] if _path_parts | length >= 2 else '' %} {% set _table = _path_parts[2] if _path_parts | length >= 3 else (row.affected_table or '') %} {% set _title %}{% if _dataset %}{{ _dataset }}.{% endif %}{{ row.dbt_model_name or _table }}{% endset %} {% call header_card(_title) %} {% if row.dbt_model_name %} dbt {% endif %} {% if row.author_email %} {{ row.author_email }} {% endif %} {# Spec 156 - origin chip in the header. Mirrors the Origin column on /opportunities. Click filters the workspace to this origin. Suppress it when it would just duplicate the green "dbt" marker above (origin 'dbt' on a dbt model) - keep it for Looker / Hex / Fivetran / etc. where it adds information. #} {% if row.origin_tool and row.origin_tool != 'ad_hoc' and not (row.origin_tool == 'dbt' and row.dbt_model_name) %} {{ row.origin_tool | replace('_', ' ') }} {% endif %} {% endcall %} {# Spec 156 - Origin subsection. Shows the per-tool metadata (looker_dashboard_id, fivetran_connector_id, airflow_dag_id, etc.) when present. classifier_signal is rendered at the bottom for audit-of-audit transparency. Only rendered when we have actual metadata to show. #} {% if row.origin_metadata and (row.origin_metadata.keys() | reject('equalto', 'classifier_signal') | list | length > 0) %}
{{ section_title("Where this came from") }}
Tool
{{ row.origin_tool or 'ad_hoc' }}
{% for key, value in row.origin_metadata.items() %} {% if key != 'classifier_signal' %}
{{ key | replace('_', ' ') | title }}
{{ value }}
{% endif %} {% endfor %}
Classifier signal
{{ row.origin_metadata.classifier_signal or 'fallback:none_matched' }}
{% endif %} {# Six-card stat strip - aggregated lifetime metrics on the left half, last-execution snapshot on the right half. Lives outside the ``ui-surface`` header so the cards read as a standalone strip (mirrors the dashboard's cost-summary row). ``grid-cols-6`` isn't in the pre-compiled Tailwind bundle (same constraint as ``_cost_summary.html``), so we inline the 6-column rule below the xl breakpoint and rely on Tailwind's built-in 1/2/3 cols at smaller widths. #} {% from "components/_stat_card.html" import stat_card %} {%- set _exec_meta = ("across " ~ row.execution_count ~ " executions") if (row.execution_count and row.execution_count > 1) else None -%}
{{ stat_card("Cost (aggregated)", row.query_cost_value | format_usd, meta=_exec_meta) }} {% if row.aggregated_bytes_processed %} {{ stat_card("Bytes Processed (aggregated)", row.aggregated_bytes_processed | format_bytes, meta=_exec_meta, accent="brand") }} {% elif job and job.total_bytes_processed is not none %} {{ stat_card("Bytes Processed (aggregated)", job.total_bytes_processed | format_bytes, accent="brand") }} {% else %} {{ stat_card("Bytes Processed (aggregated)", "-", accent="slate") }} {% endif %} {% if row.aggregated_slot_time_ms %} {{ stat_card("Slot Time (aggregated, hours)", "%.1f" | format((row.aggregated_slot_time_ms or 0) / 3600000), meta=_exec_meta) }} {% elif job and job.total_slot_ms is not none %} {{ stat_card("Slot Time (aggregated, hours)", "%.1f" | format((job.total_slot_ms or 0) / 3600000)) }} {% else %} {{ stat_card("Slot Time (aggregated, hours)", "-", accent="slate") }} {% endif %} {# Last-execution trio - same three metrics for the most-recent cached run so the user can compare the freshest point against the aggregated lifetime view to its left. Hidden when no cached execution exists for the affected_table. #} {% if latest_job %} {{ stat_card( "Last Execution Cost", (latest_job.total_cost or 0) | float | format_usd, meta=latest_job.creation_time.strftime("%Y-%m-%d %H:%M UTC") if latest_job.creation_time else None ) }} {% if latest_job.total_bytes_processed is not none %} {{ stat_card( "Last Execution Bytes", latest_job.total_bytes_processed | format_bytes, meta=("billed: " ~ (latest_job.total_bytes_billed | format_bytes)) if latest_job.total_bytes_billed is not none else None, accent="brand" ) }} {% else %} {{ stat_card("Last Execution Bytes", "-", accent="slate") }} {% endif %} {% if latest_job.total_slot_ms is not none %} {{ stat_card( "Last Execution Slot (hours)", "%.1f" | format((latest_job.total_slot_ms or 0) / 3600000), meta=("duration: " ~ (latest_job.duration_ms | format_duration)) if latest_job.duration_ms is not none else None ) }} {% else %} {{ stat_card("Last Execution Slot (hours)", "-", accent="slate") }} {% endif %} {% endif %}
{# Cost trend collapsible. "Cost trend" (not "for this table") because the same partial is used for consumption queries that have no destination table. The full job-history cohort link is passed into the partial as ``chart_history_href`` so it renders inside the collapsible's expanded body. #} {% if chart_points_payload %} {% set chart_title = "Cost trend and issues" %} {% set chart_subtitle = "One point per day across the scan window. Days without executions are skipped. Red dots mark days when this table's executions tripped a detection rule." %} {% set chart_collapsible = true %} {% set chart_history_href = "/jobs/" ~ row.affected_table %} {% include "jobs/_cost_chart.html" %} {% endif %} {# Issues found - one bordered card per issue rule that fired on this table. Each card has a 2-column Why-this-fired / Recommended- fix split, so readers can pair the cause with the fix per rule. When a rule has no template SQL diff, Recommended-fix points to the Available improvements section below rather than repeating the Why-this-fired text verbatim. When zero issues fired (suggestion-only object), this section is hidden. #} {% if issue_cards %}
{{ section_title( "Issues found", description="One card per issue that fired on this table. Each card pairs the issue's evidence (slot contention, shuffle spill, etc.) with a recommended fix.", aside=((issue_cards | length) ~ (' issue' if issue_cards | length == 1 else ' issues')) ) }}
{% for issue in issue_cards %}
{# Red issue pill - matches the red "issue count" pill in the dashboard's Top Cost Drivers table so the visual grammar is consistent across pages. #} {{ issue.row.opportunity_type | replace('_', ' ') }}
{# "Why this fired" is the single narrative on each issue card. The recommended-fix details used to live in their own section; per user feedback (v3.4) we fold the pointer to the rewrite list into this prose so the card reads as one coherent block. The full diffs / display names still live in the Available improvements section further down the page; we just don't repeat them here. #}

Why this fired

{{ issue.row.explanation }}

{% if issue.rule_meta and issue.rule_meta.description %}

{{ issue.rule_meta.description }}

{% endif %} {% if issue.template_result %}

{{ issue.template_result.explanation }}

{% if issue.diff_lines %}

Recommendations available below.

{% endif %} {% elif improvements %}

Recommendations available below.

{% else %}

No single-query SQL rewrite is available for this issue type. The fix is typically at the workload-scheduling, slot-reservation, or schema layer.

{% if layout_chip_targets %}

Partition / cluster recommendations are available - see the chips above.

{% endif %} {% endif %}
{% endfor %}
{% endif %} {# Spec 148 - Recommended physical layout. Read-only suggestion of partition + cluster keys based on how the table is queried. The partial gates on ``layout_recommendation`` so a None recommendation produces zero markup. #} {% include "opportunities/_layout_recommendation.html" %} {# Spec 154 v2 - Materialization recommendations folded into the opportunity detail page. Renders one card per audit-detected MV candidate (with generated CREATE MATERIALIZED VIEW SQL) and per BigQuery MV Recommender pass-through. The partial gates on non-empty input lists so it produces zero markup when this table has no MV signals. #} {% include "opportunities/_materialization.html" %} {# Spec 155 - Unused destination table section. Renders when the anchor opportunity_type is "unused_destination_table". The partial gates on a non-empty input list so it produces zero markup otherwise. Kept separate from the Materialization section because the question is different (should the table exist at all? vs. how should it be persisted?). #} {% include "opportunities/_unused_table.html" %} {# Available improvements - every SQL-rewrite suggestion that fired on any opportunity for this table, deduped by rule_type. Each is a deterministic rewrite (no LLM) and renders inline as its own green/red diff. #} {% if improvements %}
{{ section_title( "Available improvements", description="Deterministic SQL rewrites the audit can suggest for this table. Each card carries a green/red diff plus a rollback path.", aside=((improvements | length) ~ (' suggestion' if improvements | length == 1 else ' suggestions')) ) }}
{% for imp in improvements %}
{{ imp.display_name }} {% if imp.template_id %} deterministic rewrite {% endif %} {% if imp.occurrences and imp.occurrences > 1 %} ×{{ imp.occurrences }} {% endif %}
{# Only show the explanation prose when there's NO diff to render - the diff already conveys "what changed" visually, and the prose generated by core's templates duplicates the column / CTE names plus a boilerplate "What changed" paragraph that adds nothing. #} {% if imp.explanation and not (imp.diff_lines or imp.before_content) %}

{{ imp.explanation }}

{% endif %} {% if imp.diff_lines or imp.before_content %}
{% if imp.after_content %} {% endif %}
{% if imp.diff_lines %} {% set diff_lines = imp.diff_lines %} {% set file_path = imp.template_id %} {% include "components/code_diff.html" %} {% else %}

No diff available - template did not produce a change.

{% endif %}
{% if imp.after_content %} {% endif %}
{% endif %} {% if imp.rollback %}
Rollback instructions

{{ imp.rollback }}

{% endif %}
{% endfor %}
{% endif %} {# Query fallback - when no SQL-rewrite suggestions fired on this opportunity, the user still needs to see the underlying query so they can manually inspect what's running. Suggestion cards already include an "Original SQL" tab; this block is the fallback path when ``improvements`` is empty. Renders only when we have a representative job with a query body. #} {% if not improvements and job and job.query %}
{{ section_title( "Query", description="The latest execution of this query. No deterministic SQL-rewrite suggestion is available for this opportunity - the fix is at the workload-scheduling or schema layer." ) }}
{% for line in job.query.split('\n') %}{{ loop.index }}{{ line }}
{% endfor %}
{% endif %} {# Evidence + BigQuery query lookup - two side-by-side cards on >=lg, stacked on smaller screens. Each card collapses independently. The right-hand card renders the ``INFORMATION_SCHEMA.JOBS_BY_PROJECT`` SELECT pre-filtered by job_id so the user can paste it into the BigQuery console and inspect the row themselves. Evidence + lookup come from the representative opportunity (highest-priority for this table). #} {% if visible_evidence or job_lookup_sql %}
{% if visible_evidence %}

Evidence

{% for key, value in visible_evidence.items() %}
{{ key }}
{% if value is mapping or (value is iterable and value is not string) %} {{ value | tojson }} {% else %} {{ value }} {% endif %}
{% endfor %}
{% endif %} {% if job_lookup_sql %} {{ sql_panel("job-lookup-sql", "BigQuery query", job_lookup_sql) }} {% endif %}
{% endif %}
{# Generic tab toggler - picks up every ``[data-tab]`` / ``[data-tab-pane]`` pair inside an ancestor with ``[data-active-tab]``. Same script as the cohort page so suggestion cards' Diff / Original SQL tabs work without coupling to the class name. #} {% endblock %}