Skip to content

tdfs4ds.serve.panels

tdfs4ds.serve.panels

Gradio-free panel logic for the tdfs4ds admin web shell.

Each function here returns plain JSON-serialisable data or HTML strings — never gradio objects — so they can back FastAPI routes (see :mod:tdfs4ds.serve.app). The heavy lifting (Plotly figures, business-dictionary queries, optimiser, evaluation) is delegated to the already-module-level builder functions in :mod:tdfs4ds.agent.chatbot; this module only orchestrates them and strips the Gradio presentation layer.

logger module-attribute

logger = getLogger('tdfs4ds.serve.panels')

_LAST_QOPT_PENDING module-attribute

_LAST_QOPT_PENDING: dict | None = None

_LAST_EVAL_RESULTS module-attribute

_LAST_EVAL_RESULTS: dict | None = None

_LAST_DASHBOARD_STORAGE module-attribute

_LAST_DASHBOARD_STORAGE: dict | None = None

_LAST_ORPHAN_SCAN module-attribute

_LAST_ORPHAN_SCAN: dict | None = None

_TD_MD_CSS module-attribute

_TD_MD_CSS = "<style>.td-md { font-family: system-ui, -apple-system, Segoe UI, sans-serif; color:#2c3e50; }.td-md h1, .td-md h2, .td-md h3 { color:#00233C; }.td-md h2 { border-bottom:2px solid #FF5F00; padding-bottom:4px; margin-top:18px; }.td-md h3 { margin-top:14px; }.td-md p { margin:6px 0; }.td-md pre { background:#0f172a; color:#e2e8f0; padding:12px 16px; border-radius:8px; overflow-x:auto; margin:8px 0; font-size:.85rem; }.td-md code { font-family:'Courier New', monospace; font-size:.88em; color:#c0392b; }.td-md pre code { color:#e2e8f0; background:transparent; }.td-md table { border-collapse:collapse; width:100%; margin:10px 0; font-size:.9rem; }.td-md th, .td-md td { border:1px solid #E3E8EE; padding:6px 12px; text-align:left; }.td-md th { background:#00233C; color:#fff; font-weight:600; }.td-md tr:nth-child(even) { background:#f8fafc; }.td-md blockquote { border-left:4px solid #FF5F00; margin:0; padding:4px 12px; background:#f8fafc; color:#555; }.td-md strong { color:#00233C; }.td-md th * { color:#fff; }.td-md ul, .td-md ol { margin:6px 0; padding-left:24px; }.td-md li { margin:2px 0; }</style>"

_LIST_ITEM_RE module-attribute

_LIST_ITEM_RE = compile('^(\\s*)([-*+]|\\d{1,3}[.)])\\s+')

_FENCE_RE module-attribute

_FENCE_RE = compile('^\\s*(```|~~~)')

_LAST_EFS_MAP module-attribute

_LAST_EFS_MAP: dict = {}

_LAST_FEATURE_CATALOG module-attribute

_LAST_FEATURE_CATALOG: dict = {'key': None, 'data': None, 'model': None, 'graph': None}

FEATURE_CATALOG_PAGE module-attribute

FEATURE_CATALOG_PAGE = 20

_FEATURE_CATALOG_LOCK module-attribute

_FEATURE_CATALOG_LOCK = RLock()

_DATASET_NAME_OK module-attribute

_DATASET_NAME_OK = compile('^[A-Za-z][A-Za-z0-9_$#]{0,127}$')

SAMPLE_ROWS module-attribute

SAMPLE_ROWS = 20

_DATASET_DEFECTS module-attribute

_DATASET_DEFECTS: dict = {}

VIEW_MISSING_CAUSE module-attribute

VIEW_MISSING_CAUSE = 'the dataset view no longer exists (only its catalog entry remains)'

_SECTION_ORDER module-attribute

_SECTION_ORDER = ['OVERVIEW', 'ENTITY', 'FEATURE_THEMES', 'BUSINESS_QUESTIONS', 'INTENDED_AUDIENCE']

_LAST_DOC_MODEL module-attribute

_LAST_DOC_MODEL: dict = {}

_DATASET_SECTION_LABELS module-attribute

_DATASET_SECTION_LABELS = {'OVERVIEW': 'Overview', 'ENTITY': 'Entity', 'FEATURE_THEMES': 'Feature themes', 'BUSINESS_QUESTIONS': 'Business questions', 'INTENDED_AUDIENCE': 'Intended audience'}

SAMPLE_MAX_SECONDS module-attribute

SAMPLE_MAX_SECONDS = 60

SAMPLE_MAX_SPOOL_GB module-attribute

SAMPLE_MAX_SPOOL_GB = 10

_SAMPLE_JOBS module-attribute

_SAMPLE_JOBS: dict = {}

SAMPLE_JOB_MAX_SECONDS module-attribute

SAMPLE_JOB_MAX_SECONDS = 600

_MIG_STAGED module-attribute

_MIG_STAGED: dict | None = None

_EVAL_SCENARIOS module-attribute

_EVAL_SCENARIOS: dict = {'scenarios': []}

_LAST_BENCHMARK_RESULT module-attribute

_LAST_BENCHMARK_RESULT: dict | None = None

_LAST_MAINTENANCE module-attribute

_LAST_MAINTENANCE: dict | None = None

_DATASET_STATUS_COLOURS module-attribute

_DATASET_STATUS_COLOURS = {'OK': '#16a34a', 'REPAIR': '#FF5F00', 'REGISTER': '#2563eb', 'DUPLICATE': '#a16207', 'ORPHAN': '#dc2626', 'UNPARSEABLE': '#64748b'}

_MAINTENANCE_LABELS module-attribute

_MAINTENANCE_LABELS = {'lineage': 'Lineage graph', 'documentation': 'Documentation', 'vector': 'Vector index', 'all': 'Lineage, documentation and vector index', 'statistics': 'Storage statistics', 'dataset_catalog': 'Dataset catalog', 'process_sql': 'Process SQL versions', 'resources': 'Execution history'}

NO_STORE_STATUS module-attribute

NO_STORE_STATUS = '⚠️ No feature store is selected. Choose one in Settings → Parameters, or set TDFS4DS_SCHEMA in the .env file passed to the app and restart it.'

_CHECK_ICON module-attribute

_CHECK_ICON = {'ok': '✅', 'failed': '❌', 'skipped': '⏭️'}

_FEATURE_STORES module-attribute

_FEATURE_STORES: dict = {'stores': None, 'error': '', 'at': None}

_SWITCH_STATE module-attribute

_SWITCH_STATE = ('SCHEMA', 'SCHEMA_VIEW', 'DATA_DOMAIN', 'SCHEMA_READONLY', 'FOLLOW_UP_NAME', 'DATASET_CATALOG_NAME', 'DATA_DISTRIBUTION_TEMPORAL')

_LAST_WORKFLOW_SCAN module-attribute

_LAST_WORKFLOW_SCAN: dict | None = None

_LAST_WORKFLOW_MODEL module-attribute

_LAST_WORKFLOW_MODEL: dict | None = None

_WORKFLOW_MODEL_TTL_S module-attribute

_WORKFLOW_MODEL_TTL_S = 600

_LAST_REMOVAL_PLAN module-attribute

_LAST_REMOVAL_PLAN: dict | None = None

_LAST_RELOCATION_PLAN module-attribute

_LAST_RELOCATION_PLAN: dict | None = None

_PROGRESS_RE module-attribute

_PROGRESS_RE = compile('PROGRESS\\s+(\\d+)\\s*/\\s*(\\d+)')

dashboard_storage module-attribute

dashboard_storage: dict = _tracked('report:storage', 'Report — storage counts')(dashboard_storage)

Streamed live storage-count build: treemap + stacked bar + orphans + table.

progress is a callable(str) hook (per-table PROGRESS k/N lines).

documentation_run module-attribute

documentation_run: dict = _tracked('documentation:run', 'Documentation')(documentation_run)

Actions of the Documentation panels.

op='document': document the objects named by keys (model row keys), or every object whose documentation is missing or partial when keys is empty; then, if refresh_index, update the vector index. op='index': update the vector index only (build_vector_index(force_rebuild=False): Chroma embeds only missing or changed rows; Teradata refreshes its collections).

doc_edit_apply module-attribute

doc_edit_apply: dict = _tracked('documentation:edit', 'Documentation edit')(doc_edit_apply)

Preview (dry_run) or apply a hand edit from the Objects panel.

migration_run module-attribute

migration_run: dict = _tracked('migration:run', 'Migration')(migration_run)

Execute the staged migration (must call migration_stage first).

eval_run module-attribute

eval_run: dict = _tracked('evaluation:run', 'Evaluation')(eval_run)

Run the evaluation; return {results, report_html, radar_html, table_html}.

benchmark_run module-attribute

benchmark_run: dict = _tracked('benchmark:run', 'Benchmark')(benchmark_run)

Run the benchmark for dataset; return the rendered HTML report.

workflow_scan module-attribute

workflow_scan: dict = _tracked('workflow:scan', 'Workflow assessment — entity scan')(workflow_scan)

The entity scan (one pass per entity over its largest storage table), then the whole model. Streamed: progress gets PROGRESS k/N lines.

removal_dryrun module-attribute

removal_dryrun: dict = _tracked('removal:dryrun', 'Remove objects — dry run')(removal_dryrun)

What each step of the last plan would remove: counts and existence only.

_split_inline_enumeration

_split_inline_enumeration(line: str) -> list

'1. a? 2. b? 3. c' (one line) -> three lines, when the numbers follow on.

LLM-written documentation stores numbered questions on one line; Markdown then renders a single list item. Only a run starting at 1 and counting up is split, so a sentence quoting "version 2. something" is left alone.

_normalize_md

_normalize_md(md: str) -> str

Adapt LLM/GFM-style Markdown to Python-Markdown's stricter rules.

Python-Markdown (unlike GitHub, the chatbot and every LLM's habits) needs a blank line before a list, and 4 spaces to nest one; without them a list renders as one paragraph with literal dashes, and sub-items flatten. Also splits inline "1. … 2. …" enumerations. Fenced code is never touched.

_md_to_html_fragment

_md_to_html_fragment(md: str, with_css: bool = True) -> str

Render a Markdown string to a styled, self-contained HTML fragment.

Uses the markdown package (declared in the serve extra) with the fenced_code, tables and sane_lists extensions so GFM pipe tables, fenced code blocks and lists render properly — unlike the minimal client-side marked() in app.js. Scoped via the .td-md class. Fail-open: returns an escaped <pre> block on any error so the panel never breaks, and says why (the fallback was silent at DEBUG, so a server without the markdown package showed raw Markdown everywhere with nothing in the log).

dashboard

dashboard() -> dict

Return the dashboard payload: KPI/tree HTML + Plotly-iframe blocks.

dashboard_scope

dashboard_scope() -> dict

Domain + process lists for the storage-build cascading selectors.

_pid_to_tables_map

_pid_to_tables_map()

{PROCESS_ID: {"DB.TABLE", ...}} - which storage tables each process writes.

Delegates to the package (feature_store.statistics.process_storage_tables), the one authority shared with check_storage_statistics. Fail-open.

dashboard_run_detail

dashboard_run_detail(process_id: str) -> str

Full run-log table HTML for a single process (drill-down).

_consistency

_consistency(snapshot, log_df=None)

Consistency model for a snapshot, with the cached storage scan when it was taken at the same valid time. Fail-open: None.

dashboard_orphan_scan

dashboard_orphan_scan(as_of=None, progress=None) -> dict

Streamed storage scan (button 'Scan storage for orphans'); cached for the report and the EFS map at that valid time.

dashboard_report_data

dashboard_report_data(window_days: int = 90, as_of=None) -> dict

Assemble the plain data dict the inline-SVG report renders from.

Catalog + run-history + cached storage build → JSON-serialisable records (no Plotly). Storage block is the last streamed build (_LAST_DASHBOARD_STORAGE) or None (→ the report shows a 'build first' note). window_days bounds the run-history timeline/calendar. as_of reads the catalogs at that valid time (None = current); every count states the valid time it was read at. Fail-open per section.

_doc_activity

_doc_activity(limit: int = 25) -> dict

Latest documentation events + counts per action (FS_DOCUMENTATION_LOG). Fail-open.

_short_view

_short_view(name) -> str

Bare view name from a possibly-quoted FQN: '"db"."vw_x"' → 'vw_x'.

_table_to_process_map

_table_to_process_map(feat_df, proc_df) -> dict

{TABLE_UPPER: {view_name, view_short, process_id}} — the first process that writes each storage table. Fail-open: {} on error.

_storage_hierarchy

_storage_hierarchy(storage, feat_df, proc_df, orphan_ids) -> dict

Nested {table: {label, nonseq, processes:[{view, process_id, n_features, rows_share, features:[{feature, type, entity, orphan}]}]}} for tile drill-down.

Built in pandas from the already-loaded catalogs (no per-row DB query). Row share = table nonseq rows split evenly across the table's features.

_to_int

_to_int(v)

_run_history_records

_run_history_records(log_df, window_days: int = 90) -> dict | None

Run history bounded to the last window_days.

Returns {rows, t_min, t_max, calendar, last_runs} where rows is a flat list of {view, start, end, status, filter} (ISO strings) the inline-JS timeline consumes; filter carries APPLIED_FILTER / VALIDTIME_DATE for the hover. calendar is {view:{day:ok}}. Fail-open → None.

_freshness_alert_records

_freshness_alert_records(proc_ids, pid_to_view) -> list

For each process, flag the stalest segment when it runs segmented.

_lineage_count_records

_lineage_count_records(proc_df, ds_df) -> list

Per process/dataset upstream + downstream counts from the persisted graph.

dashboard_report_html

dashboard_report_html(window_days: int = 90, as_of=None) -> dict

Render the exportable report inline for the panel.

dashboard_report_file

dashboard_report_file(window_days: int = 90, as_of=None) -> str | None

Write the report to disk and return its path (for download).

_process_view_nodes

_process_view_nodes() -> set

Node ids ('DB.OBJECT') of the registered process views. Fail-open.

lineage

lineage(layout: str = 'flow', seed: str | None = None) -> dict

Return the lineage graph HTML + the node choices for inspection.

layout: 'flow' (default; left-to-right, zoomable, focus on click, search, filters) or 'network' (free pyvis network). 'sankey' is still accepted and now shows the Flow view: the Sankey did not scale.

_datasets_missing_from_lineage

_datasets_missing_from_lineage(graph_dict: dict) -> list

db.name of every registered dataset absent from the lineage graph.

lineage_add_datasets

lineage_add_datasets(datasets: list | None = None) -> dict

Record the lineage of datasets missing from the graph (scoped, diff-based).

datasets=None takes every registered dataset the graph lacks. A dataset whose view is gone is reported, never fatal for the others.

efs_map

efs_map(exact: bool = False, as_of=None) -> dict

The EFS map as HTML (+ KPIs). exact=True counts rows with COUNT(*); as_of reads the catalogs at that valid time (None = current).

efs_table

efs_table(database: str, table: str) -> dict

Rows per feature of one storage table, as HTML (bar chart).

efs_map_file

efs_map_file(exact: bool = False, as_of=None) -> str | None

Write the EFS map to a standalone HTML file and return its path (download).

_feature_catalog_model

_feature_catalog_model(as_of='', refresh: bool = False) -> dict

_feature_catalog_graph

_feature_catalog_graph(cache: dict)

The lineage graph used for the SQL chains, loaded once per catalog build (None if unreadable).

_as_list

_as_list(domains) -> list

feature_catalog_page

feature_catalog_page(page: int = 0, size: int = FEATURE_CATALOG_PAGE, q: str = '', domains=(), as_of: str = '', refresh: bool = False, processes=()) -> dict

One page of the feature catalog (feature x producing process) for the panel.

domains: names (or '|'-joined); empty = all. processes: PROCESS_IDs (or '|'-joined); empty = all. q: text searched in feature, entity, description and process view. as_of: blank = current. processes_all lists the processes of the selected domains, for the filter.

_producers_by_feature

_producers_by_feature(features) -> dict

{(domain, entity, name): [{pid, view}]} over the feature rows (rows without a producer left out).

_render_sql_chain

_render_sql_chain(sql_chain: dict, feature: str = '') -> dict

The chain as the panel shows it: highlighted steps, the computation of feature in the process view, the inputs.

_ts_text

_ts_text(x) -> str

_process_versions

_process_versions(pid: str, live_chain: Optional[dict], process_row: Optional[dict] = None) -> dict

The SQL versions of a process for the feature report.

state: off (PROCESS_SQL_VERSIONING False), not_installed (no FS_PROCESS_SQL on this store), none (nothing stored yet: before 0.3.3.12), ok. versions: one row per version, with the runs whose valid time falls in it. drift: the live SQL differs from the current stored version (captured at the next run or upload_features).

feature_catalog_process

feature_catalog_process(pid: str, as_of: str = '', feature: str = '', version: str = '') -> dict

A process of the feature catalog with its SQL.

The SQL shown: the stored version when given; at a past valid time, the process version in force then (FS_PROCESS_SQL); otherwise the live view definitions (one SHOW VIEW per view). versions lists the stored process versions (see :func:_process_versions).

With feature, the SQL comes back with the feature's computation and its mentions highlighted, and computation gives each level's expression and the grain (sql_context.computation_context).

_domain_clocks

_domain_clocks(domains) -> dict

{data_domain: 'db.view'} of the domains that have a clock (0.3.6.0). Fail-open: {} (no FS_DATA_DOMAIN_SETTINGS table, an older store, or an unreadable one).

_domain_clock_relation

_domain_clock_relation(row) -> Optional[dict]

How a process stands with the clock of its data domain, for the process card, or None when the domain has no clock: {clock, relation, text} with relation clock (reads the clock itself), clone (its own soft clone of it), none (no TimeManager) or other (another calendar). Fail-open: None.

feature_catalog_process_diff

feature_catalog_process_diff(pid: str, v1, v2) -> dict

A unified diff of two stored process versions, as text and highlighted HTML.

feature_catalog_process_capture

feature_catalog_process_capture(pid: str) -> dict

Capture the SQL beneath a process now (a new process version when it changed).

_html_escape

_html_escape(s) -> str

_require_store

_require_store() -> Optional[dict]

A 'no feature store selected' payload when SCHEMA is unset (the app can start connected but without a store), else None.

_runs_window

_runs_window(days, as_of)

execution_log

execution_log(days=30, processes='', status='', as_of='') -> dict

The Execution log panel: executions of the window with their resource use, per-process and per-version statistics (serve/execution_log).

execution_log_statements

execution_log_statements(execution_id: str) -> dict

The statements of one execution (DBQL, else the stored history).

process_consumption

process_consumption(pid: str, days=30, as_of='') -> dict

The feature catalog card's "Runs and consumption" block: the process's runs and resource use in the window ending at as_of, per process version, and the version in force at as_of.

execution_log_harvest

execution_log_harvest() -> dict

Copy finished executions out of DBQL now (Maintenance / the panel's button).

execution_log_file

execution_log_file(days=30, processes='', status='', as_of='') -> str

The Execution log as an XLSX file (executions + processes); returns its path.

feature_catalog_file

feature_catalog_file(fmt: str = 'xlsx', domains=(), as_of: str = '', processes=()) -> str

Write the export (with SQL) for the panel's filters; returns the path.

_split_list

_split_list(text) -> list

_builder_rows

_builder_rows()

Feature rows that can go in a dataset (a producing process), current valid time.

dataset_builder_entities

dataset_builder_entities(refresh: bool = False) -> dict

The entities features can be combined on, per data domain, with their datasets.

dataset_builder_features

dataset_builder_features(domain: str, entity: str) -> dict

The features of one entity: description, type, producing processes (latest run first), and the existing datasets on that entity with the features each one exposes.

dataset_name_status

dataset_name_status(name: str) -> dict

May a dataset be created as name in the view database?

status: available, invalid (not a plain identifier), registered (a dataset of the catalog), exists (a table or view of that name: creating would replace it) or check_failed (never treated as free). Reads the database now, never a cache: a dataset created a minute ago must count.

_builder_kind

_builder_kind(p: dict) -> dict

The dataset kind from the form: snapshot (current / as of / TimeManager) or history.

_builder_selection

_builder_selection(chosen: dict, aliases: Optional[dict] = None) -> dict

The form's choice as build_dataset's selected_features.

One process for a feature: {feature: PROCESS_ID}, the column keeps the feature's name. Several processes (several versions side by side): {feature: [{"process_id", "process_view_name"}, ...]}, one column per version named <feature>_<process view> (the rule of build_dataset). aliases {feature: {PROCESS_ID: column name}}: a version with a name of its own gets alias (one version: {"process_id", "alias"}). Without aliases the result is exactly what it was.

dataset_versions_columns

dataset_versions_columns(name: str, views) -> list

The column names a feature gets in the dataset: its name for one version, <name>_<process view> for each of several (as build_dataset names them).

_builder_offsets

_builder_offsets(raw) -> dict

The form's offsets as build_dataset's feature_offsets ({} when none).

raw: {feature: "0, -1 day, +1 month"} (a comma list) or a list of strings. Each value is checked here, so a typo is reported with the feature it belongs to rather than as a failed creation. Raises ValueError.

dataset_builder_columns

dataset_builder_columns(payload: dict) -> dict

The column names the form's choice gives, per feature, and the offset errors.

Same rule as build_dataset (version suffix, then offset suffix, then _2/_3 for a repeat): tdfs4ds.dataset.builder.preview_column_names. No database access beyond the cached builder rows (process view names).

dataset_builder_create

dataset_builder_create(payload: dict, preview: bool = False) -> dict

Create (or, with preview, only render the SQL of) a dataset from the builder form.

payload: domain, entity, features ({feature name: PROCESS_ID}), name, kind (current / as_of / time_manager / history) and its parameters, join_type, document. The name is checked again here (the button state is only a hint): an existing dataset or object is never replaced.

dataset_builder_python

dataset_builder_python(payload: dict) -> dict

The Python that creates the form's dataset, and what each argument does.

The arguments come from the same parsing as :func:dataset_builder_create, so the code is the call Create makes (skill_build_dataset passes them on unchanged). Nothing is run. The password is never written: the code asks for it.

dataset_builder_datasets

dataset_builder_datasets(entity: str = '', domain: str = '', with_attached: bool = True) -> dict

The registered datasets (all, or those on entity): kind, features, entity.

Same reading as the chat's dataset list (skill_list_datasets), read now: the agent's per-turn cache is reset first, so a dataset created a minute ago shows.

_sample_rows

_sample_rows(sql: str) -> dict

Run sql (a SELECT, read only) and return {columns, rows} as text.

_view_body

_view_body(ddl: str) -> str

The SELECT of a REPLACE VIEW x AS <body> statement (what the view would return).

dataset_sample

dataset_sample(name: str = '', payload: Optional[dict] = None, n: int = SAMPLE_ROWS) -> dict

20 rows of a registered dataset (name), or of the dataset the builder form describes (payload), before it is created: its query is run with SAMPLE n and nothing is created.

name must be a registered dataset: the panel never runs a SELECT on an arbitrary object.

dataset_defect_cause

dataset_defect_cause(message: str, name: str = '') -> str

A short cause for a failed dataset read, from the database message's wording (never from an error number alone). name: the dataset (db.view), to tell its own view missing from an object it reads. Pure.

_record_dataset_defect

_record_dataset_defect(name: str, message: str, found_by: str, cause: str = None) -> dict

dataset_check_all

dataset_check_all(entity: str = '', domain: str = '') -> dict

EXPLAIN SELECT * FROM every registered dataset (no data read): flags those whose query no longer compiles, reads a missing object or is refused.

_existing_views

_existing_views(names)

{(DB, OBJ)} of the named objects present in DBC.TablesV (one read per database, raw SQL), or None when the dictionary cannot be read.

dataset_remove

dataset_remove(name: str, drop_view: bool = False, dry_run: bool = True) -> dict

Remove a dataset of the primary store from the catalog (with its documentation, index entries and lineage); dry_run lists what would go.

_name_message

_name_message(check: dict) -> str

_object_documentation_md

_object_documentation_md(obj: str) -> list

Markdown blocks of an object's business documentation: description, sections in _SECTION_ORDER, and a table of documented columns.

Shared by the Lineage node detail and the Documentation panels, so both show the same thing. A failed read is said, never silently dropped; when nothing is stored, a block says so.

lineage_node_detail

lineage_node_detail(node_id: str) -> str

Assemble DDL + business documentation for a lineage node as styled HTML.

The documentation is composed as Markdown (description, sections, a GFM pipe table of documented columns, a fenced SQL DDL block) then rendered to HTML via :func:_md_to_html_fragment so tables/lists/code render properly in the admin shell (the client-side marked() cannot handle pipe tables).

_doc_model

_doc_model(refresh: bool = False) -> dict

The documentation model, collected once and cached until refreshed or changed.

_doc_status_line

_doc_status_line(model: dict) -> str

documentation_coverage

documentation_coverage(refresh: bool = False) -> dict

Overview: documented / missing per kind, collection status, gap lists.

_doc_provenance_card

_doc_provenance_card() -> str

Who wrote the documentation: parts imported / edited by people, copies, the rest.

documentation_objects

documentation_objects(refresh: bool = False) -> dict

Every object as a JSON row (the panel filters client-side).

documentation_object

documentation_object(key: str) -> dict

Summary + documentation of one object (key from the model rows).

documentation_gaps_file

documentation_gaps_file() -> str | None

Write the gaps (documentation and index) to a CSV file and return its path.

documentation_export_file

documentation_export_file(fmt: str = 'xlsx', scope: str = 'all', databases=()) -> str

Write the documentation export (business dictionary, inside / outside the feature store) and return its path. Raises ValueError on a bad fmt/scope.

_document_rows

_document_rows(rows: list, emit) -> dict

Generate documentation for rows (model rows), one object at a time.

Process (or one of its features) -> document_process_incremental; dataset -> document_dataset_incremental; intermediate view -> _document_intermediate_view over the persisted graph, as rebuild_documentation does. Source tables are never generated (their documentation is user-supplied) and are skipped.

_read_only_message

_read_only_message(row) -> str

_doc_row

_doc_row(key: str, for_write: bool = False)

_object_columns

_object_columns(db: str, obj: str) -> list

Column names of a table or view (DBC), so undocumented columns can be written.

doc_edit_form

doc_edit_form(key: str) -> dict

The editable parts of one object, with who wrote each (Objects panel > Edit).

_edit_call

_edit_call(row: dict, changes: dict, options: dict, editor: str, dry_run: bool) -> dict

Route the changed fields to the manual-documentation API.

_edit_report_html

_edit_report_html(rep: dict) -> str

doc_edit_protect

doc_edit_protect(payload: dict) -> dict

Protect (mark as written by a person) or release one part to the LLM.

_object_names

_object_names(value) -> list

Object names from a list or from text (one per line, or comma-separated).

_attach_kind

_attach_kind(kind) -> str

attached_overview

attached_overview() -> dict

The attached objects, the data domains and whether the LLM can document.

attached_suggest

attached_suggest(databases) -> dict

Views of databases that read a dataset or a process view, attached or not (read only).

_attach_report_row

_attach_report_row(rep: dict, obj: str) -> dict

attached_attach

attached_attach(payload: dict, progress=None) -> dict

Preview (dry_run) or attach objects. Each object is attached on its own, so a refused one (a process view, a dataset, a name not found) does not stop the others.

attached_detach

attached_detach(payload: dict) -> dict

End the attachment of objects; their documentation stays.

attached_sample

attached_sample(obj: str, force: bool = False, n: int = SAMPLE_ROWS) -> dict

n rows of an attached object or of a view that reads the feature store, read only after its EXPLAIN shows the query stays within the limits.

SAMPLE applies to the view's result, so the view's whole query runs: the EXPLAIN of SELECT * FROM <obj> SAMPLE n is what the sample will cost. Above a limit nothing is read and the plan is returned; force reads it anyway. Only an attached object or a suggested view can be sampled, never an arbitrary name.

_format_rows

_format_rows(cols, data) -> dict

_start_sample_job

_start_sample_job(obj: str, sql: str) -> str

Run sql in a worker thread on its OWN raw connection, so that connection.cancel() stops it in the database (verified live: Error 3110, the session idle within a second). Returns the job token.

_cancel_job

_cancel_job(job: dict) -> None

attached_sample_job

attached_sample_job(token: str) -> dict

State of a cancellable sample: running (with elapsed seconds), done (rows), cancelled, failed.

attached_sample_cancel

attached_sample_cancel(token: str) -> dict

attached_check

attached_check(payload: dict, progress=None) -> dict

What changed in the attached objects (dry_run), or apply the refresh.

_parse_seeds

_parse_seeds(seeds: str | None)

Comma-separated seed string -> list, or None (whole store) when blank.

parallel_seeds

parallel_seeds() -> dict

Selectable seeds for the Execution plan panel: datasets + process views.

_short

_short(view_name: str) -> str

_plan_summary_html

_plan_summary_html(plan: dict) -> str

Compact HTML summary of the plan (waves, groups, conflicts, unify, unresolved).

parallel_plan

parallel_plan(seeds: str | None = None) -> dict

Build the plan for the given seeds and render the interactive workflow + summary.

parallel_script_file

parallel_script_file(seeds: str | None = None, mode: str = 'process_pool', force_compute: bool = False, max_workers: Optional[int] = None, wave_on_failure: str = 'skip_descendants') -> Optional[str]

Build the plan and write the executable .py script; return its path.

migration_sources

migration_sources() -> dict

Attached read-only stores available as migration sources (any schema name can also be typed — plan_migration attaches it read-only).

migration_seeds

migration_seeds(source: str | None = None) -> dict

Source-scoped datasets + process views selectable as migration seeds.

migration_plan

migration_plan(source: str | None = None, seeds: str | None = None, target_data_domain: str | None = None, data_strategy: str = 'recompute') -> dict

Build the migration manifest and render the approval report + conflict controls. READ-ONLY (nothing is written).

migration_stage

migration_stage(source: str, seeds: str | None, target_data_domain: str | None, data_strategy: str, approvals: dict) -> dict

Re-plan freshly, validate the approvals, and stash {plan, approvals} for the streamed run. Returns the validation verdict.

migration_script_file

migration_script_file(source: str, seeds: str | None = None, target_data_domain: str | None = None, data_strategy: str = 'recompute', approvals: dict | None = None) -> Optional[str]

Build the plan and write a standalone migration .py with baked-in approvals.

qopt_scores

qopt_scores() -> dict

Score overview chart + the list of optimisable processes.

qopt_detail

qopt_detail(process_id: str) -> str

HTML detail for one process.

qopt_optimize

qopt_optimize(process_id: str) -> dict

Run the optimiser; return the rendered report + a pending-replacement token.

qopt_approve

qopt_approve() -> dict

Apply the approved REPLACE VIEW (uses the last optimisation's pending state).

qopt_report_file

qopt_report_file(fmt: str = 'md') -> str | None

Write the last optimisation report to a temp file and return its path.

eval_generate

eval_generate(skills=None, multi_turn=True, use_pronouns=True, per_skill=1, fact_first=True, temporal=True, seed=0, mcp_enabled=False) -> dict

eval_import

eval_import(md_text: str, mode: str = 'append') -> dict

Import scenarios JSON (replace/append) and merge into the current set.

eval_scenarios_export_file

eval_scenarios_export_file() -> Optional[str]

Write the current scenario set to a temp JSON and return its path.

eval_report_file

eval_report_file(fmt: str = 'html') -> str | None

benchmark_datasets

benchmark_datasets() -> dict

List datasets (+ auto-derived entity columns) for the Benchmark dropdown.

benchmark_last

benchmark_last() -> dict

Re-render the most recent benchmark report (panel revisit).

benchmark_report_file

benchmark_report_file(fmt: str = 'html') -> str | None

Write the last benchmark result to a temp file for download; return path.

_capture_tdfs4ds_logs

_capture_tdfs4ds_logs(emit)

Forward 'tdfs4ds' logger records to emit(str) for the duration.

The rebuild cores already log per-object lines ("documenting X", "skipped", "absent from graph — fallback", per-seed lineage, per-collection indexing). Capturing them is how the Maintenance panel streams progress WITHOUT adding a progress= param to those cores. Temporarily forces DISPLAY_LOGS=True so the lines actually emit.

maintenance_status

maintenance_status() -> dict

Current lineage / documentation / vector-index sizes for the status card.

datasets_overview

datasets_overview() -> dict

Registered datasets with how they were built (Maintenance → Datasets card).

One row per dataset: name, strategy, join type and time mode. They come from the build table; a dataset registered before it existed shows not recorded (its strategy is still detected when converting).

dataset_grouped

dataset_grouped(view: str, in_place: bool = False, target: str = '', overwrite: bool = False, preview: bool = False) -> dict

Build the grouped version of a dataset — a new view, or in place.

preview=True only returns the DDL. The package logs the reason of a refusal (target exists, not a dataset view); it is captured and returned so the panel shows it instead of a bare failure.

_find_registered_dataset

_find_registered_dataset(overview: list, qualified: str, default_db: str = '')

The overview row naming qualified (db.name or bare name), or None.

Case-insensitive, quote-tolerant: the catalog stores raw names while the caller may pass a quoted or differently-cased one.

_dataset_catalog_html

_dataset_catalog_html(df, applied=False) -> str

The dataset-catalog check/restore report as an HTML table (Maintenance panel).

_statistics_html

_statistics_html(df, mode='check') -> str

The storage-statistics report as an HTML table (Maintenance panel).

_process_sql_html

_process_sql_html(results: list, applied: bool) -> str

The backfill report: one row per process, its status and version.

maintenance_stores

maintenance_stores() -> dict

The stores the Maintenance vector-index step can re-index, with what the local index holds for each.

Every store found by the feature-store discovery (as in Parameters), the attached ones first and ticked. A store that is not attached can be indexed too: it is read through its public views, nothing is written to it. On the Teradata Vector Store backend the list is informative only (that backend indexes the primary, in its own database).

_wait_for_index_job

_wait_for_index_job(key, emit, timeout_s=3600.0)

Wait for a background build of the same store to end (two builds of one store's collections at once would race).

rebuild_run

rebuild_run(op: str, opts: dict = None, progress=None) -> dict

Run a rebuild operation, streaming the cores' log lines via progress.

op ∈ {'lineage', 'documentation', 'vector', 'all'}. Flags in opts: force_update, force_rebuild, all_data_domains, extra_views, stores (the vector-index step on Chroma: the stores to re-index, a list or a comma-separated string; default every attached store).

The run is shown in the status bar while it lasts.

_rebuild_run

_rebuild_run(op: str, opts: dict = None, progress=None) -> dict

_rebuild_chroma_stores

_rebuild_chroma_stores(stores, force_rebuild, emit) -> dict

Re-index the Chroma collections of each store in stores, one status-bar job per store; {store: {'embedded', 'skipped', 'errors'}}.

A store whose build fails is reported and the next one still runs.

connection_status

connection_status() -> dict

Current Teradata connection status for /health and the UI status dot.

connect_fields

connect_fields() -> dict

Pre-fill values for the Connect form (password is never returned).

connect

connect(host=None, username=None, password=None, logmech=None, database=None, encrypt=None) -> dict

Open (or re-open) the Teradata context from the Connect form.

_require_database

_require_database() -> Optional[dict]

Return a 'not connected' payload when disconnected, else None.

For the few panels that work without a feature store (the store list, the Parameters toggles).

_require_connection

_require_connection() -> Optional[dict]

Return a payload naming what is missing (connection, feature store), else None.

Every panel that reads the store calls this. Without a store, its SQL would read FROM .FS_FEATURE_CATALOG and fail with Error 3707, a syntax error that names nothing (seen at a site whose .env set the connection but not TDFS4DS_SCHEMA).

store_selected

store_selected() -> bool

True when tdfs4ds.SCHEMA names a database.

params_current

params_current() -> dict

Snapshot of the live tdfs4ds config used to pre-fill the Parameters form.

check_row_html

check_row_html(check: dict) -> str

One check of the report as the Parameters panel shows it (status, detail, error, fix hint, and the time it took when it is noticeable).

check_configuration

check_configuration(live: bool = True, progress=None) -> dict

Run tdfs4ds.check_configuration() and render it for the Parameters panel.

Returns the raw report plus an html fragment, so the panel shows the per-check status and — the point of the feature — the fix hint for anything that did not pass. progress is passed through ((event, data), see diagnostics.check_configuration) so the panel shows each row as it comes.

feature_stores

feature_stores(refresh: bool = False) -> dict

The databases holding a feature store, for the Parameters list.

Looked for once at app startup and again on demand (refresh=True); the result is kept so opening the panel costs nothing. Never raises: a failed search returns the reason, and the panel then offers free text.

app_status

app_status() -> dict

What the status bar shows: the connection, the stores read, and the jobs.

No database read: the store names are the session's, the jobs come from tdfs4ds.serve.activity.

read_only_store_names

read_only_store_names() -> list

View databases of the attached read-only stores, in attach order.

_clear_store_caches

_clear_store_caches() -> None

Forget every panel result computed for the previous set of stores.

shared_feature_count

shared_feature_count() -> int

Features (DATA_DOMAIN, ENTITY_NAME, FEATURE_NAME) present in more than one attached store: the assistant's internal identity is store-blind, so each is treated as one (the primary's). 0 with a single store or on a read error.

apply_database

apply_database(db_name: str, readonly=None) -> dict

Make db_name the primary feature store and, when readonly is given (a list of database names, possibly empty), read from exactly those stores too.

readonly=None keeps the stores already attached. The vector index of each store is then brought up to date in the background (only missing or changed rows are embedded: each store has its own collections, so nothing is wiped).

apply_vector_store

apply_vector_store(backend: str, path: str) -> dict

refresh_vector_store

refresh_vector_store() -> dict

apply_instruct

apply_instruct(provider, model, url, key, proxy) -> dict

apply_embedding

apply_embedding(provider, model, url, key, proxy, dim) -> dict

apply_execution_log

apply_execution_log(query_band, execution_resources) -> dict

Switch the query band and the execution history on or off for this app process; when on, create the history tables if missing and say whether this user's runs can be measured (query band settable, DBQL readable and logging).

apply_skills_folder

apply_skills_folder(folder: str) -> dict

skills_list

skills_list() -> list

skill_export_path

skill_export_path(name: str) -> str | None

skill_import

skill_import(name: str, md_text: str) -> dict

_workflow_domains

_workflow_domains(domains)

_workflow_model

_workflow_model(days: int = 90, domains=None, scan: bool = False, progress=None) -> dict

The model, with the cached entity scan when one exists (or a new scan).

_workflow_status

_workflow_status(model) -> str

workflow_page

workflow_page(days: int = 90, domains=None) -> dict

{"html", "status", "summary"} of the cheap checks (+ the cached scan).

workflow_file

workflow_file(days: int = 90, domains=None, fmt: str = 'html') -> str

The assessment as html (standalone page), md or csv, written under tdfs4ds.DASHBOARD_REPORT_DIR. Reuses the panel's last model when it is recent and for the same scope (with its entity scan), else the cheap checks.

workflow_report_html

workflow_report_html(days: int = 90) -> str

The Report's 'Workflow assessment' section: the panel's last model when it is recent and for every domain, else the cheap checks. Fail-open: ''.

_parse_removal_objects

_parse_removal_objects(objects) -> list

The objects of the panel: a JSON list of process ids, dataset ids and features [name, [entity], domain, process_id], or a comma list of ids.

removal_objects

removal_objects(domains=None) -> dict

The processes, datasets and features the panel lists (current catalogs).

_removal_plan_html

_removal_plan_html(plan) -> str

removal_plan

removal_plan(objects, purge_values: bool = False, drop_views: bool = False) -> dict

The ordered removal plan of objects and of everything depending on them.

removal_verify

removal_verify() -> dict

After the script ran: what each step of the last plan left behind (catalog rows, documentation, provenance, SQL versions, vector-index entries). Read only.

removal_script_file

removal_script_file() -> Optional[str]

Write the script of the last plan; return its path (None without a plan).

relocation_plan

relocation_plan(features=None, tag: str = '', rewrite_dataset: str = '') -> dict

Plan (read only) the relocation of features, or preview the rewrite of a dataset's table references, and show each step's dry run. Nothing is changed; the script does it.

relocation_script_file

relocation_script_file() -> Optional[str]

Write the script of the last relocation plan; return its path (None without a plan).

_tracked

_tracked(key: str, label: str)

Show a streamed panel job in the status bar while it runs.

The job's own progress messages become the bar's detail, and a PROGRESS k/N (or PHASE k/N) line its count. A returned status starting with ❌ marks the job failed; so does an exception (re-raised).