{# 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 %} {% from "components/_signal_chip.html" import signal_chip %}
{{ 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) %} {# Build vs consumption - same classification the dashboard uses (build = writes a destination; consumption = read-only). Makes it explicit on the detail page which kind of workload this is. #} {% if row.query_workload_kind == 'build' %} {{ signal_chip("Build", color="brand", title="Build - this query writes a destination table") }} {% elif row.query_workload_kind == 'consumption' %} {{ signal_chip("Consumption", color="teal", title="Consumption - read-only query, no destination written") }} {% endif %} {% if issue_cards %} {% for issue in issue_cards[:3] %} {{ signal_chip(issue.display_name, color="rose", title="Issue found on this object") }} {% endfor %} {% if issue_cards | length > 3 %} {{ signal_chip("issues", color="rose", overflow=("+" ~ (issue_cards | length - 3)), title="More issue rules found on this object") }} {% endif %} {% endif %} {% if row.dbt_model_name %} dbt {% endif %} {% if row.author_email %} {% set _author_label %}{{ row.author_email }}{% endset %} {{ signal_chip(_author_label, color="slate") }} {% 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) %} {% set _origin_label %}{{ row.origin_tool | replace('_', ' ') }}{% endset %} {{ signal_chip(_origin_label, color="slate") }} {% endif %} {% endcall %} {# "What changed" signal for the current query version - the same chips the /jobs version cards show. A resolved rule (e.g. "cross join unaggregated resolved") is good news: it fired on an earlier version and the current query no longer triggers it. This is why the suggestion count can be 0 here while /jobs' history shows the rule - it was already fixed. #} {% if resolved_rules_current or new_rules_current %}
{% for rt in resolved_rules_current %} {{ rt | replace('_', ' ') }} resolved in current version {% endfor %} {% for rt in new_rules_current %} {{ rt | replace('_', ' ') }} new in current version {% endfor %}
{% endif %} {# Cohesive metric strip - one connected band of columns (cost / bytes / slot / executions) rather than separate boxes. Big aggregated value up top, latest-execution detail on the muted line beneath. #} {%- set _runs = row.execution_count or 1 -%} {%- set _last_ts = latest_job.creation_time.strftime("%Y-%m-%d %H:%M UTC") if (latest_job and latest_job.creation_time) else "" -%} {%- set _agg_bytes = row.aggregated_bytes_processed or (job.total_bytes_processed if job else none) -%} {%- set _agg_slot_ms = row.aggregated_slot_time_ms or (job.total_slot_ms if job else none) -%} {%- set _cost_meta = ( "last " ~ ((latest_job.total_cost or 0) | float | format_usd) ~ ((" · " ~ _last_ts) if _last_ts else "") ) if latest_job else None -%} {%- set _bytes_meta = ( "last " ~ (latest_job.total_bytes_processed | format_bytes) ~ ((" · billed " ~ (latest_job.total_bytes_billed | format_bytes)) if latest_job.total_bytes_billed is not none else "") ) if (latest_job and latest_job.total_bytes_processed is not none) else None -%} {%- set _slot_meta = ( ("last " ~ (latest_job.duration_ms | format_duration) ~ " wall") if (latest_job and latest_job.duration_ms is not none) else None ) -%}

Cost

{{ row.query_cost_value | format_usd }}

{% if _cost_meta %}

{{ _cost_meta }}

{% endif %}

Bytes processed

{{ (_agg_bytes | format_bytes) if _agg_bytes is not none else "-" }}

{% if _bytes_meta %}

{{ _bytes_meta }}

{% endif %}

Slot time

{{ ("%.1f" | format((_agg_slot_ms or 0) / 3600000) ~ " hrs") if _agg_slot_ms is not none else "-" }}

{% if _slot_meta %}

{{ _slot_meta }}

{% endif %}

Executions

{{ "{:,}".format(_runs) }}

in scan window

{# 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" %} {# Subtitle is derived from the payload granularity inside the partial (per-execution vs daily roll-up). The chart spans every query version, matching the headline cost/executions (both full history) and the /jobs page. Amber rings mark version changes; red points 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 decision card per detector/advisory rule surfaced on this table. The card mirrors the Materialization rhythm: Evidence / Action / Impact. SQL rewrite cards stay below only when there is a deterministic before/after change to review. #} {% if issue_cards %}
{{ section_title( "Issues found", description="One card per issue that fired on this table. Each card pairs the detector evidence with the action and expected operational impact.", aside=((issue_cards | length) ~ (' issue' if issue_cards | length == 1 else ' issues')) ) }}
{% for issue in issue_cards %}
{{ signal_chip(issue.display_name, color="rose", title="Issue found on this object") }}

Evidence

{{ issue.evidence_text }}

Action

{{ issue.action_text }}

Impact

{{ issue.impact_text }}

{% 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 suggestion card already carries SQL, the user still needs to see the underlying query so they can manually inspect what's running. Rewrite cards include an "Original SQL" tab; advisory-only cards (slot contention, etc.) do not. Renders only when we have a representative job with a query body. #} {% if not improvements_have_sql and job and job.query %}

Query

No deterministic SQL rewrite is available. Expand only when you need to inspect the latest execution.

minimized
{% for line in job.query.split('\n') %}{{ loop.index }}{{ line }}
{% endfor %}
{% endif %} {# Evidence + job lookup SQL - 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", "Job lookup SQL", 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 %}