# Markdown Formal

A VS Code-compatible Markdown preview extension and local CLI for mathematical and technical long-form writing: keep stable hash IDs in source, then render numbering, references, definitions, symbols, dependency graphs, AI artifacts, and publication exports from metadata.

## Metadata

- HTML: https://glenzli.com/en/projects/markdown-formal/
- Markdown: https://glenzli.com/en/projects/markdown-formal.md
- Collection: Projects
- Language: en
- Published: 2026-07-03
- Status: active
- Tags: markdown, math-writing, vscode, references, cli

## Content

Markdown Formal, published as `markdown-formal`, is a VS Code-compatible Markdown preview extension and local CLI for long-form mathematical and technical writing. Instead of asking authors to hand-maintain reader-facing numbers such as "Theorem 2.3" or "Equation (4.1)", it keeps stable hash IDs in source Markdown and renders numbering, references, navigation, definition lookup, symbol tables, dependency graphs, and publication outputs from generated metadata.

It is designed for AI-assisted editing. While drafting, an AI can use lightweight `tmp-*` markers. The CLI turns those temporary IDs into stable `h-*` hashes during `finish`; `verify` then checks broken references, stale temporary IDs, migration residue, and metadata consistency.

## Project Entry

  ![markdown-formal compiles stable Markdown references into preview and publication output](/images/projects/markdown-formal-banner.png)

## What It Solves

    **Stable numbering**
    Sections, theorem-like blocks, equations, figures, and tables use `#h-...` in source; reader-facing numbers are computed from the current structure.

    **Reorder-safe references**
    Prose references use `@h-...`, `@h-....title`, or `@h-....full`, so insertion, deletion, and chapter reordering do not require manual renumbering.

    **Definitions and symbols**
    Definitions stay outside the numbering system. Standard definitions are scanned automatically, and project-specific LaTeX notation is stored in `.markdown-formal/symbols.json`.

    **Verification and export**
    `prepare` generates the reference map, preview cache, and graph; `verify` runs the strict gate; exports lower formal source into ordinary Markdown before PDF or project-specific publishing.

The boundary is deliberately narrow. Markdown Formal is not a typesetting system and not a proof checker. It maintains numbering, references, and structural metadata in Markdown manuscripts, so humans and AI editors can work against the same stable reference layer.

## Preview

  ![markdown-formal multi-volume navigation, table of contents, symbols, and definition search](/images/projects/markdown-formal-navigation.png)
  The preview toolbar provides back navigation, chapter navigation, table of contents, the current-page symbol table, and definition search. Multi-volume projects fold naturally into volume-to-chapter navigation.

  ![markdown-formal reference recall preview](/images/projects/markdown-formal-recall-preview.png)
  Inline `@h-...` references render as current reader-facing numbers and support local recall previews while preserving readable Markdown and LaTeX source.

## Source To Output

These snippets come from the repository's `examples/book1` and generated `.markdown-formal/` reports. The important part is not fancy syntax, but how the source stores stable identity and what the tool can derive from it.

      **Stable IDs in source, reader numbers from the tool**
      The manuscript stores hash references; preview and export render current chapter-aware numbers.

    Source: `examples/book1/02-core-theorems.md`

```markdown
## #h-67631f13c67a6098 Main Result

Theorem #h-5815f80196c52eef (Operator Network Evolution Theorem): if an operator network satisfies all assumptions in @h-70c80dc9769686c0.title, its long-time evolution converges to a unique stationary state.

Equation #h-1f4b6c2d8e0a9b71:
$$
\rho(T_G) \leq \max_{\gamma} w(\gamma) < 1
$$

Figure #h-5c9e1b7a3d2f0e64 (Feedback loop): each closed feedback loop $\gamma$ contributes to the bound in @h-1f4b6c2d8e0a9b71.
```

    Generated reference map

```markdown
| Display | ID | Title | Location |
| --- | --- | --- | --- |
| § 2.2 | `h-67631f13c67a6098` | Main Result | `examples/book1/02-core-theorems.md:13` |
| Theorem 2.2 | `h-5815f80196c52eef` | Operator Network Evolution Theorem | `examples/book1/02-core-theorems.md:17` |
| Equation (2.1) | `h-1f4b6c2d8e0a9b71` |  | `examples/book1/02-core-theorems.md:23` |
| Figure 2.1 | `h-5c9e1b7a3d2f0e64` | Feedback loop | `examples/book1/02-core-theorems.md:30` |
```

The source hash does not care whether the object is currently theorem 2.2 or theorem 3.4. After structural edits, the reference map recomputes display numbers while prose references still point to the same object.

      **AI drafts with tmp IDs, the CLI finalizes them**
      New objects do not require the AI to invent hash IDs by hand.

    Draft

```markdown
# #tmp-1 Measure Theory

## #tmp-2 Weak Convergence

Definition (Tight family): A family of probability measures is tight if ...

Theorem #tmp-3 (Prokhorov Criterion): Let \(\mathcal{P}\) be a family of probability measures.

Proof: ...

The claim follows from @tmp-3.
```

    After `finish`

```markdown
# #h-0c9a8d1f67e42a30 Measure Theory

## #h-8a7f22b9c1d0e366 Weak Convergence

Definition (Tight family): A family of probability measures is tight if ...

Theorem #h-3f7a1c9d5b0e72aa (Prokhorov Criterion): Let \(\mathcal{P}\) be a family of probability measures.

Proof: ...

The claim follows from @h-3f7a1c9d5b0e72aa.
```

`#h-...` and `#tmp-*` are declaration syntax and only appear where numbered objects are declared. Prose references use `@h-...`. That separation keeps migration and verification simple.

      **The dependency graph comes from explicit references**
      The tool does not infer mathematics. It records explicit `@h-...` edges between propositions, lemmas, theorems, and corollaries.

    Graph commands

```bash
npm run formal -- graph summary
npm run formal -- graph focus <h-id> --depth 2
npm run formal -- graph impact <h-id>
npm run formal -- graph upstream <h-id>
npm run formal -- graph matrix chapter
```

    Generated graph report

```markdown
# Dependency Graph Report

Nodes: 34
Explicit edges: 29
Statement edges: 26
Proof edges: 3
Cross-chapter edges: 17
Cross-volume edges: 6
Cycles: 1

High Incoming Dependencies:
- Lemma 2.1 Network Boundary Operator Lemma
- Theorem 2.2 Compact Generation Descent Theorem
- Theorem 3.2 Moduli Space Gluing Theorem
```

This is structural auditing, not automated proof. Before changing a central lemma, you can inspect downstream impact and see which chapters or results are tied to it.

      **Definitions, symbols, and preview cache are separate**
      Standard definitions are scanned automatically; aliases, uncertain ranges, and project notation live in explicit metadata.

    Definition and symbol metadata

```json
[
  {
    "term": "bounded operator",
    "aliases": ["有界算子"],
    "source": "book/01-foundations.md:42",
    "content": "A bounded operator is a linear map satisfying \\(\\|Tx\\|\\le C\\|x\\|\\)."
  }
]
```

```json
[
  {
    "pattern": "\\operatorname{Spec}(${operator})",
    "meaning": "The spectrum of the matched operator.",
    "scope": "book"
  }
]
```

    Generated files

```text
.markdown-formal/reference-map.md
.markdown-formal/preview-cache.json
.markdown-formal/dependency-graph.json
.markdown-formal/dependency-report.md
.markdown-formal/report.md
.markdown-formal/audit.md
.markdown-formal/definitions.json
.markdown-formal/symbols.json
```

Definitions do not have to become numbered objects, and the symbol table only tracks project-specific notation. Generic variables and one-off formulas stay out of the maintenance surface.

## Normal Workflow

| Stage | Command | Purpose |
| --- | --- | --- |
| Development install | `npm install && npm run build` | Build the VS Code extension, CLI, and preview webview. |
| Target project integration | `node tools/markdown-formal/out/cli/formal-tools.js` | Vendor the CLI and let the writing project own its `.markdown-formal/` metadata. |
| npm CLI install | `npm install -D markdown-formal` | Use the `markdown-formal` command from project scripts. |
| Before writing | `npm run formal -- prepare` | Generate the reference map, agent guide, preview cache, and dependency graph. |
| After editing | `npm run formal -- finish path/to/chapter-or-dir` | Finalize `tmp-*`, refresh reports, and verify the workspace. |
| Before commit | `npm run formal -- verify` | Check broken references, stale temporary IDs, migration residue, and metadata consistency. |
| Publication export | `export-md` / `export-md-split` / `export-pdf` | Lower formal source into ordinary Markdown; PDF export supports title page, publication metadata, and front matter pages. |

## AI Artifacts And Generated Docs

Markdown Formal does not provide a remote auto-installed skill. It ships reviewed AI workflow artifacts inside the release bundle or npm package.

| Entry | Use |
| --- | --- |
| `skills/editor.md` | Detailed AI writing rules to merge into a target project's `AGENTS.md`, writing skill, or project guide. |
| `skills/integrator.md` | AI composition guidance for integrating Markdown Formal into an existing writing workflow. |
| `vasm-catalog/vasmc-catalog.yaml` | Catalog exports for VASMC projects, allowing the consumer lockfile to pin artifact hashes. |
| `node_modules/markdown-formal/skills/` | Skills path after npm installation. |
| `node_modules/markdown-formal/vasm-catalog/` | VASMC catalog path after npm installation. |

The CLI can print paths for the current installation:

```bash
npm run formal -- paths
```

Public documentation sources live in `docs-src/**/*.vasm.md`, and target-project AI skill sources live in `skills-src/**/*.vasm.md`. Generated outputs include `README.md`, `docs/*.md`, `skills/*.md`, and `vasm-catalog/`. After changing documentation or skill sources, run:

```bash
npm run content:build -- --dry-run
npm run content:build
```

`--plan` is an alias for `--dry-run`; it only inspects the plan and does not write generated outputs, build-state, or the default report. Before committing, read `.vasmc/build-report.yaml` and complete translate or review actions.

## Release Bundle

```text
dist/
  markdown-formal-<version>.vsix
  extension/
  cli/
  skills/
  vasm-catalog/
  docs/
  README.md
  LICENSE
  INSTALL.md
  manifest.json
  checksums.txt
```

Use the VSIX for editor installation, `cli/` for repo-local vendoring, the npm package for `markdown-formal` CLI installation, and `skills/` as reviewed AI workflow artifacts. `npm run release:check` is the pre-publish gate; `npm run release` orchestrates mixed GitHub, GitLab, and npm publishing.

## Best Fit

Markdown Formal fits documents that are long-lived, often reorganized, and dense with internal references: mathematical manuscripts, technical lectures, formal research notes, multi-volume manuals, and Markdown projects edited with AI assistance.

It is not necessary for short articles or one-off notes. Plain Markdown is cheaper there. The tool becomes useful once numbering, references, definitions, symbols, dependency structure, and exports start to constrain each other.
