# Run Solution Analyzer

> Run Solution Analyzer is an Agent Skill for documents published in the Azure/Azure-Sentinel repository on GitHub: a SKILL.md instruction file an AI agent can load to do this task.

Run the Solutions Analyzer scripts: mapper, documentation generator, ASIM browser. Use when: running solution analyzer, generating CSVs, generating docs, refreshing caches, force-refresh, invalidating caches, generating ASIM browser, running mapper, running collect_table_info, running collect_asim_fields.

- Skill name: `run-solution-analyzer`
- Category: [Documents](https://www.openparable.com/skill/documents/1)
- Source: https://github.com/Azure/Azure-Sentinel/blob/HEAD/.github/skills/run-solution-analyzer/SKILL.md
- Repository: Azure/Azure-Sentinel (5,980 GitHub stars when collected)

## SKILL.md

# Run Solution Analyzer

This skill covers running the Solutions Analyzer locally against this clone of
Azure-Sentinel. Each script writes CSVs or docs to a directory you choose; the
scripts themselves are agnostic to where that directory lives.

If your workflow includes publishing the generated CSVs/docs to additional
repositories, GitHub Pages, or Kusto, those targets are user-specific and
should be recorded in agent memory (workspace or user scope) rather than in
this skill.

## Scripts Overview

| Script                               | Purpose                                                            | Invocation                                        |
| ------------------------------------ | ------------------------------------------------------------------ | ------------------------------------------------- |
| `map_solutions_connectors_tables.py` | Mapper: generates all CSV data                                     | Run directly                                      |
| `generate_connector_docs.py`         | Doc generator: markdown + HTML pages, static + interactive indexes | Run directly                                      |
| `generate_asim_browser.py`           | ASIM browser: interactive HTML schema browser                      | Run directly                                      |
| `upload_to_kusto.py`                 | Upload CSVs to Azure Data Explorer (Kusto) cluster                 | Run directly                                      |
| `collect_table_info.py`              | Fetch table reference data from Microsoft docs                     | Auto-invoked by mapper (`--force-refresh=tables`) |
| `collect_asim_fields.py`             | Fetch ASIM field/schema definitions from Microsoft docs            | Auto-invoked by mapper (`--force-refresh=asim`)   |
| `generate_interactive_docs.py`       | Generate `index.html` and HTML entity pages                        | Auto-invoked by `generate_connector_docs.py`      |

All scripts run from `Tools/Solutions Analyzer`.

## Default Output Location

By default the mapper writes CSVs into `Tools/Solutions Analyzer/` in the
current branch. The doc generator and ASIM browser require an explicit
`--output-dir` so they never pollute the source tree.

## Sync the Working Branch With `origin/master`

**Always do this before any analyzer run.** A working branch that has drifted
from master makes the mapper analyze a stale source tree — every connector
merged to master after the divergence point can appear as a new "added"
connector in subsequent diffs, even though no mapper logic changed.

```powershell
git fetch origin master
git merge origin/master --no-edit
```

- Use `git merge`, not `git rebase`, so subsequent
  `git log --first-parent origin/master` analysis (used by `compare_runs.py`
  and friends) still reflects merge dates correctly.
- Resolve any conflicts before running the mapper.
- Do this even for incremental/docs-only runs: docs link to GitHub paths that
  may have moved.

After merging, verify the working tree is clean of unintended changes:

```powershell
git status --short | Select-Object -First 20
```

## Cache Invalidation Model

The mapper's analysis cache is keyed by `(analysis_type, file_path)` and
stores the source file `mtime`. When a source file is modified (including via
`git merge`), its mtime changes and the entry is automatically re-analyzed on
the next run. **Source-content changes do NOT require `--force-refresh`.**

`--force-refresh` exists for two distinct reasons:

1. **Analyzer logic changed** (mapper code modified) — invalidate cached
   results for the affected analysis types so they get recomputed from current
   source. This is the **local-only** case.
2. **Network-fetched data is stale** — re-fetch tables / marketplace / ASIM
   schema fields from external sources. This is the **network** case and is
   reserved for explicit full refresh.

| Type          | Triggers network fetch?                                    | When to refresh                                        |
| ------------- | ---------------------------------------------------------- | ------------------------------------------------------ |
| `parsers`     | No                                                         | Mapper parser-analysis logic changed                   |
| `solutions`   | No                                                         | Mapper solution-analysis logic changed                 |
| `standalone`  | No                                                         | Mapper standalone-content logic changed                |
| `asim`        | **Yes** — re-runs `collect_asim_fields.py` against MS docs | ASIM analyzer logic changed AND network refresh wanted |
| `marketplace` | Yes — Azure Marketplace API                                | Marketplace data is stale                              |
| `tables`      | **Yes** — re-runs `collect_table_info.py` against MS docs  | Table reference info is stale                          |

Note: `asim` is hybrid — it invalidates the local ASIM-parser analysis cache
**and** re-runs `collect_asim_fields.py`. There is currently no flag to do
only the local half.

### After a `git merge` from master

Default: just run the mapper with no flags. Mtime-based invalidation re-analyzes
every file that changed during the merge:

```powershell
python map_solutions_connectors_tables.py
```

Network-fetched CSVs (`tables_reference.csv`, `asim_fields.csv`,
`asim_entity_fields.csv`, `asim_logical_types.csv`,
`asim_vendors_products.csv`, marketplace cache) will be reused from cache.
That's expected — they shouldn't drift just because master moved forward.

## Full Mapper Run (Invalidating All Caches)

Use only when explicitly asked to do a full/clean run, when "invalidate all
caches" is requested, or when analyzer logic was modified across multiple
analysis types.

```powershell
cd "Tools/Solutions Analyzer"
python map_solutions_connectors_tables.py --force-refresh=all
```

- `--force-refresh=all` clears all 6 cache types (asim, parsers, solutions,
  standalone, marketplace, tables) AND re-runs `collect_asim_fields.py` and
  `collect_table_info.py` against the network.
- `--force-refresh=all-offline` clears `parsers`, `solutions`, `standalone`,
  AND `asim` (which still re-runs `collect_asim_fields.py` despite the name;
  only `marketplace`/`tables` are skipped).
- Multiple types: `--force-refresh=parsers,solutions,standalone` (purely
  local, no network calls).
- Run with `isBackground: false` and `timeout: 0`.
- Do NOT truncate/filter output (no `Select-Object` piping).

**Known issue (as of 2026-04-28):** `collect_asim_fields.py` fails with HTTP
404 because the Microsoft Sentinel docs were migrated out of
`MicrosoftDocs/azure-docs`. The mapper logs a warning and proceeds, leaving
`asim_fields.csv`, `asim_entity_fields.csv`, `asim_logical_types.csv`, and
`asim_vendors_products.csv` empty/stale. Until the script is updated to fetch
from the new source, avoid `--force-refresh=all` and `--force-refresh=asim`
unless you accept stale ASIM schema CSVs.

## Generate Documentation

```powershell
python generate_connector_docs.py --output-dir <DOCS_DIR> [--skip-input-generation] [--html-output-dir <HTML_DIR>] [--html-docs-path <REL_PATH>] [--html-index-url <URL>]
```

- `--output-dir` — **mandatory**, never omit.
- `--skip-input-generation` — skip the embedded mapper invocation when CSVs
  are already fresh.
- `--html-output-dir`, `--html-docs-path`, `--html-index-url` — control where
  `index.html` and the interactive entity pages are written and how they
  link back to the index. These are typically only set when publishing to a
  static-site / GitHub Pages location; defaults are sensible for a local
  preview.
- Run with `isBackground: false` and `timeout: 0`. Do NOT truncate output.

## Generate ASIM Browser

```powershell
python generate_asim_browser.py --output-dir <DIR> [--docs-base-path <REL_PATH>] [--index-url <URL>] [--link-extension <EXT>]
```

`--docs-base-path` and `--index-url` make sense only when the browser is
deployed alongside an interactive docs index. For a standalone local
preview, `--output-dir` alone is enough.

## When to Re-Run the Mapper Before Docs

Run mapper before generating docs if:

- The mapper script itself was modified.
- Any override YAML file in the `overrides/` folder was modified.
- You specifically need to refresh the CSV data.
- You are explicitly asked to run the mapper.

Otherwise, just run the doc generator with `--skip-input-generation`.

## Caching and Logging

- **Cache:** `Tools/Solutions Analyzer/.cache/`
- **Logs:** `Tools/Solutions Analyzer/.logs/`
- **Log file:** `Tools/Solutions Analyzer/.logs/map_solutions_connectors_tables.log`

### Watching Mapper Progress While It Runs

The mapper writes timestamped progress lines (`[ N.Ns] ...`) to its own log
file in real time. To see live status during a run, tail that file directly:

```powershell
Get-Content "Tools/Solutions Analyzer/.logs/map_solutions_connectors_tables.log" -Tail 12
```

**Do NOT rely on `... | Tee-Object -FilePath <log> | Select-Object -Last N`
for live progress.** PowerShell pipelines buffer until the upstream command
finishes, so the Tee'd file stays empty until the entire run completes
(including the post-processing/CSV-write phase, which can be many minutes
after the per-parser progress lines were emitted). The mapper's own
`.logs/map_solutions_connectors_tables.log` is unbuffered and updates within
seconds.

## Upload to Kusto

```powershell
python upload_to_kusto.py -c <cluster-url> -d <database> --solution-analyzer --source-dir ./
```

- `--solution-analyzer` uploads the standard set of CSVs defined in
  `SOLUTION_ANALYZER_FILES`.
- `--source-dir ./` uses local CSVs instead of downloading from GitHub.
- Without `--source-dir`, downloads CSVs from the public Azure-Sentinel
  GitHub repo.
- `--dry-run` shows what would be uploaded without making changes.
- Requires Azure CLI authentication (`az login`).

The cluster URL and database name are environment-specific and not part of
this skill.

## User-Specific Publishing Pipelines

If you maintain a publishing pipeline (e.g. CSV output worktree, separate
docs repository, GitHub Pages site, specific Kusto cluster), record the
concrete paths, URLs, and the order of copy/commit/push steps in agent
memory — for example, in `/memories/repo/` for a workspace-scoped note or in
`/memories/` for a cross-workspace one. The agent should consult that memory
to resolve any placeholders above before running.

---

Source: https://www.openparable.com/skill/documents/run-solution-analyzer (OpenParable). Cite the canonical URL above.
