# How extract-summaries.ps1 Regenerates INDEX.md from Skill Frontmatter

> Learn how extract-summaries.ps1 regenerates INDEX.md from skill frontmatter by scanning SKILL.md files and compiling a synchronized navigation index. Run the script in write or CI check modes.

- Repository: [ZhaoXu/reverse-skill](https://github.com/zhaoxuya520/reverse-skill)
- Tags: how-to-guide
- Published: 2026-08-28

---

**The `extract-summaries.ps1` PowerShell script performs an idempotent workflow that scans the reverse-skill repository for [`SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/SKILL.md) files, extracts YAML front-matter metadata, and compiles a synchronized navigation index at [`skills/INDEX.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/INDEX.md) capable of running in both write and CI check modes.**

The reverse-skill repository organizes modular capabilities into dedicated directories, each documented by a [`SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/SKILL.md) file containing structured metadata. Maintaining a central index of these modules requires a reproducible, automated approach that eliminates manual editing drift. According to the reverse-skill source code, the `extract-summaries.ps1` script provides a deterministic workflow that derives [`skills/INDEX.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/INDEX.md) directly from declared front-matter fields across the entire codebase.

## Resolving Repository Paths and Layout

The script begins by establishing canonical paths relative to its execution context. In `skills/scripts/extract-summaries.ps1`, the script resolves `$PSScriptRoot` to determine its own directory, then calculates the repository root (`$skillsRoot`) and the target index file path (`$indexPath`).

```powershell

# Path resolution from extract-summaries.ps1 (lines 12-15)

$scriptDir = $PSScriptRoot
$skillsRoot = Join-Path $scriptDir ".."
$indexPath = Join-Path $skillsRoot "INDEX.md"

```

This ensures the script operates correctly regardless of the current working directory, provided it remains within the repository structure.

## Discovering SKILL.md Files via Git or Fallback

The extraction workflow prioritizes version-controlled files to ensure stability across different clones. The script first attempts to use `git ls-files` to list tracked [`SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/SKILL.md) files. If Git is unavailable, it falls back to `Get-ChildItem` with recursive directory traversal.

Files residing within ignored directories—specifically `ops`, `scripts`, `config`, `tests`, `field-journal`, and `references`—are explicitly excluded from indexing at lines 21-30 and 34-35 of the script. This filtering prevents build artifacts and utility directories from polluting the skill index.

## Parsing YAML Front-Matter Metadata

For each discovered [`SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/SKILL.md), the script reads the first 15 lines to locate YAML front-matter delimited by `---` markers. The parser walks these lines in block mode, extracting the `name` and `description` fields required for index generation.

When front-matter fields are missing, the script applies default values to maintain table integrity. Multi-line descriptions are supported through block parsing logic, though content exceeding 160 characters is truncated to preserve table readability in the final [`INDEX.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/INDEX.md).

## Building Structured Index Rows

Each valid module contributes a structured object to a master collection. The script constructs these rows using `[pscustomobject]` with four properties:

- **Dir** – The module's directory name
- **Name** – The extracted front-matter name
- **Desc** – The truncated description (max 160 characters)
- **Path** – The relative path to the module

This intermediate representation enables uniform processing before final Markdown assembly.

## Assembling the Markdown Document

The script utilizes a `StringBuilder` to construct [`INDEX.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/INDEX.md) with strict formatting rules. The generated document contains:

1. A header identifying the file as auto-generated
2. A Markdown table with columns for module and summary (摘要)
3. A plain-text directory tree representation
4. Routing references from [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json)

Pipe characters (`|`) within descriptions are escaped to prevent table corruption. The assembly logic appears at lines 75-88 and 92-98 of `extract-summaries.ps1`.

## Enforcing Line Ending Consistency

To match the repository's `.gitattributes` policy enforcing LF line endings, the script normalizes all output before writing. It replaces Windows-style CRLF sequences with Unix-style LF characters using a regex replacement at lines 104-105:

```powershell

# Line ending normalization

$newContent = $newContent -replace "`r`n", "`n"

```

This ensures the generated [`INDEX.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/INDEX.md) remains consistent across Windows, macOS, and Linux environments regardless of the execution platform.

## Executing Write or Check Mode

The script supports two execution modes controlled by the `-Check` switch.

**Write mode** (default) persists the generated content to disk using UTF-8 encoding with BOM:

```powershell

# Default write operation (lines 123-124)

[System.IO.File]::WriteAllText($indexPath, $newContent, [System.Text.Encoding]::UTF8)

```

**Check mode** performs drift detection suitable for CI pipelines. It compares the generated content against the existing file (ignoring CRLF differences) and exits with code 0 if identical, or code 1 if discrepancies exist, enabling automated validation that [`INDEX.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/INDEX.md) remains synchronized with source front-matter.

```powershell

# CI validation example

pwsh -File skills/scripts/extract-summaries.ps1 -Check

```

## Summary

- **Path resolution** establishes repository context using `$PSScriptRoot` and `Join-Path` to locate the target [`skills/INDEX.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/INDEX.md).
- **Git-aware discovery** prefers `git ls-files` over file system scanning, excluding utility directories like `scripts`, `tests`, and `config`.
- **Front-matter extraction** reads the first 15 lines of each [`SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/SKILL.md) to capture `name` and `description` fields from YAML blocks.
- **Content normalization** enforces LF line endings and truncates descriptions to 160 characters while escaping pipe characters for table safety.
- **Dual execution modes** support both local regeneration (write) and CI validation (check) with appropriate exit codes for automation.

## Frequently Asked Questions

### How does extract-summaries.ps1 handle missing front-matter fields?

The script applies default values when `name` or `description` fields are absent from a [`SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/SKILL.md) file's YAML front-matter. This ensures every discovered module appears in [`INDEX.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/INDEX.md) with complete table rows even if documentation is incomplete.

### What is the difference between Write mode and Check mode?

Write mode generates and saves the new [`INDEX.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/INDEX.md) content to disk using UTF-8 with BOM encoding, which is the standard workflow for updating documentation. Check mode compares the generated content against the existing file without writing changes, exiting with code 1 if differences are detected, making it suitable for continuous integration pipelines to enforce documentation synchronization.

### Why does the script prefer Git commands over file system scanning?

Using `git ls-files` ensures that only version-controlled modules are indexed, maintaining stability across different clones and preventing untracked local files from appearing in the public [`INDEX.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/INDEX.md). If Git is unavailable, the script falls back to `Get-ChildItem` with explicit exclusion patterns for directories like `ops`, `field-journal`, and `references`.

### How are special characters handled in the generated markdown?

Pipe characters (`|`) within description text are escaped to prevent corruption of the Markdown table structure. Additionally, all line endings are normalized to LF (`\n`) to comply with repository-wide `.gitattributes` policies, ensuring the file renders identically on Windows, macOS, and Linux systems.