# Output Schema

## High-level structure

`analyze_to_dict()` returns a JSON-serializable dictionary with:

- `path`: input path string
- `options`: the `AnalysisOptions` dict
- `issues`: top-level issues encountered
- `reports`: per-backend reports
- `graph`: the normalized graph

## Graph

`graph` has:

- `nodes`: list of node dictionaries
- `edges`: list of edge dictionaries
- `stats`: counts by node kind

Serialization is deterministic: nodes and edges are sorted to keep diffs stable.

## Node shape

Each node dictionary is an `Entity`:

- `id`: stable identifier (string)
- `kind`: entity kind (string)
- `key`: de-dupe key within kind (string)
- `attrs`: arbitrary metadata, depends on kind

## Edge shape

Each edge dictionary is an `Edge`:

- `src`: source node id
- `dst`: destination node id
- `kind`: relationship kind (string)
- `attrs`: arbitrary metadata

## Common kinds

The exact set of kinds can grow over time, but commonly:

- `sheet`
- `defined_name`
- `chart`
- `connection`
- `source`
- `powerquery`
- `m_script`
- `pivot_table`
- `pivot_cache`
- `vba_project`
- `formula_cell`
- `formula_group`
- `cell_block`

## Relationship kinds

Common edge kinds:

- `contains` (e.g., `sheet` → `formula_cell` / `cell_block`)
- `uses_source` (e.g., `connection` → `source`)
- `uses_connection` (e.g., `powerquery` → `connection`)
- `uses_cache` (e.g., `pivot_table` → `pivot_cache`)
- `scoped_to` (e.g., `defined_name` → `sheet`)
- `has_script` (e.g., `powerquery` → `m_script`)
- `uses_defined_name` (e.g., `chart` → `defined_name`)
- `member_of` (e.g., `formula_cell` → `formula_group`)

## Limitations & best-effort fields

`excelminer` aims to provide a stable, normalized graph, but some artifacts are inherently “best-effort” due to how Excel stores them.

- Power Query
	- If queries exist as `xl/queries/*.xml`, `powerquery.attrs.m_code` is extracted.
	- Per-script M code is also emitted as `m_script` nodes (linked via `has_script`).
	- Some workbooks store Power Query in binary mashup parts; `excelminer` attempts a best-effort M script extraction. When it cannot extract scripts, it reports mashup container metadata (e.g., `mashup_container=True`, `mashup_parts=[...]`).
	- `uses_source` edges are inferred by regex-scanning M text and can miss sources or produce partial details.

- Pivot tables
	- Pivot metadata is parsed from OOXML parts and may be incomplete depending on workbook complexity.
	- Cache/source linking is best-effort; not all pivots will resolve cleanly to a connection.

- Formulas
	- Formula nodes store formula text; formulas are not evaluated.
	- Dependency references are heuristically extracted from formula text and can miss complex cases.
	- `formula_group` nodes are only created when `post_analysis_distillation=True`.

- Connections
	- Connection strings are parsed and a sanitized KV view is produced, but raw strings may also be present.
	- Treat output as sensitive unless you explicitly disable connection extraction or redact.
