# How to Auto-Fix Section Order Issues with the Fixer Handler in DESIGN.md

> Auto-fix DESIGN.md section order with the Fixer API.  Automatically reorder sections to match the canonical spec, preserving prelude content. Learn how to use this powerful tool.

- Repository: [Google Labs Code/design.md](https://github.com/google-labs-code/design.md)
- Tags: how-to-guide
- Published: 2026-07-01

---

**The Fixer API automatically reorders DESIGN.md sections to match the canonical specification defined in [`spec-config.yaml`](https://github.com/google-labs-code/design.md/blob/main/spec-config.yaml), preserving prelude content at the top and appending unknown sections to the end.**

The [`google-labs-code/design.md`](https://github.com/google-labs-code/design.md/blob/main/google-labs-code/design.md) repository provides a deterministic Fixer API that eliminates manual reordering of markdown sections. By leveraging the `fixSectionOrder` handler implemented in [`packages/cli/src/linter/fixer/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/handler.ts), you can programmatically enforce canonical section ordering while maintaining content integrity. This guide explains how to auto-fix section order issues using the TypeScript handler and its associated configuration files.

## Understanding the Fixer API Architecture

The Fixer API serves as a thin wrapper around the *section-order* logic used by the DESIGN.md linter. It receives a document split into discrete sections, re-orders those sections to match the canonical order defined in the spec, and returns a new document string together with optional ordering details.

Unlike simple text replacement, the handler respects the semantic structure of DESIGN.md files, handling front matter, section aliases, and custom content intelligently.

## How the Section Order Fixer Works

The `fixSectionOrder` function in [`packages/cli/src/linter/fixer/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/handler.ts) executes a five-step pipeline to normalize document structure:

### Input Validation with FixerInputSchema

The request body must match `FixerInputSchema`, which expects the original document (`content`) and an array of parsed sections (`sections`). Each section contains a `heading` (the section title) and its raw `content` according to the Zod schema defined in [`packages/cli/src/linter/fixer/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/spec.ts).

### Prelude Preservation

A section whose heading is an empty string is treated as the "prelude" and is always kept at the very top of the output. This ensures that introductory material, front matter, or free-form text preceding the first heading remains intact as implemented in [`handler.ts`](https://github.com/google-labs-code/design.md/blob/main/handler.ts) at line 21.

### Known vs Unknown Section Separation

The handler separates sections into two categories:

- **Known sections** are those whose canonical heading appears in `CANONICAL_ORDER` (the ordered list derived from [`spec-config.yaml`](https://github.com/google-labs-code/design.md/blob/main/spec-config.yaml)). The helper `resolveAlias` expands any alias to its canonical form before the check, as seen in [`packages/cli/src/linter/spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.ts) at line 60.
- **Unknown sections** are left untouched but are appended after all known sections, implemented in [`handler.ts`](https://github.com/google-labs-code/design.md/blob/main/handler.ts) at lines 28-32.

### Canonical Sorting Logic

The sorter uses the index of each canonical heading inside `CANONICAL_ORDER` to produce the correct sequence. This deterministic sorting occurs in [`handler.ts`](https://github.com/google-labs-code/design.md/blob/main/handler.ts) at lines 33-36, ensuring every run yields consistent output regardless of input order.

### Document Reassembly

Sections are concatenated (prelude → sorted known → unknown) using a single newline between each piece. The result string is returned as `fixedContent`. Optional `details` contain the original and final heading orders for debugging, as defined in [`handler.ts`](https://github.com/google-labs-code/design.md/blob/main/handler.ts) at lines 51-60.

## Implementation Examples

### Programmatic Usage with fixSectionOrder

Import the handler directly to integrate auto-fixing into build scripts or editor plugins:

```typescript
import { fixSectionOrder } from
  '@design-md/cli/src/linter/fixer/handler.js';
import type { FixerInput } from
  '@design-md/cli/src/linter/fixer/spec.js';

// Assume `parseDesignMd` is a helper that splits a DESIGN.md file
// into the `sections` shape required by the fixer.
const { sections, rawContent } = parseDesignMd('my-design.md');

const input: FixerInput = {
  content: rawContent,
  sections,
};

const result = fixSectionOrder(input);

if (result.success) {
  console.log('✅ Fixed document:');
  console.log(result.fixedContent);
  // Optional debugging info:
  console.log('Before order:', result.details?.beforeOrder);
  console.log('After order: ', result.details?.afterOrder);
} else {
  console.error('❌ Fix failed:', result.error);
}

```

### CLI Command

The CLI bundles the fixer under the `design-md fix` command. This command internally parses the file into sections, calls `fixSectionOrder`, and writes the output:

```bash
design-md fix path/to/DESIGN.md --output fixed.md

```

### Web Service Integration

Expose the fixer as an HTTP endpoint using Express:

```typescript
import express from 'express';
import { fixSectionOrder } from
  '@design-md/cli/src/linter/fixer/handler.js';
import type { FixerInput } from
  '@design-md/cli/src/linter/fixer/spec.js';

const app = express();
app.use(express.json());

app.post('/api/fix-section-order', (req, res) => {
  const input: FixerInput = req.body;
  const result = fixSectionOrder(input);
  res.json(result);
});

app.listen(3000, () => console.log('API listening on :3000'));

```

The endpoint expects the same `FixerInput` shape and returns either a successful `fixedContent` or an error payload.

## Key Source Files

- **[`packages/cli/src/linter/fixer/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/handler.ts)**: Contains the core `fixSectionOrder` implementation that orchestrates the reordering logic.
- **[`packages/cli/src/linter/fixer/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/spec.ts)**: Defines the Zod schema for the fixer request and result types, including `FixerInputSchema`.
- **[`packages/cli/src/linter/spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.ts)**: Defines `CANONICAL_ORDER`, the alias map, and the `resolveAlias` helper used to normalize section headings before sorting.
- **[`packages/cli/src/linter/linter/rules/section-order.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/linter/rules/section-order.ts)**: Implements the linter rule that detects out-of-order sections, sharing the same canonical ordering logic as the fixer.
- **[`packages/cli/src/linter/fixer/handler.test.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/handler.test.ts)**: Provides the test suite demonstrating expected behavior for various input scenarios.

## Summary

- **The Fixer API** in [`google-labs-code/design.md`](https://github.com/google-labs-code/design.md/blob/main/google-labs-code/design.md) provides deterministic reordering through the `fixSectionOrder` handler.
- **Prelude safety** guarantees that content with empty headings remains at the document top.
- **Alias resolution** via `resolveAlias` ensures that alternative section titles map to their canonical positions.
- **Unknown section preservation** means custom or future sections are never dropped, only relegated to the end.
- **Validation** occurs through `FixerInputSchema`, requiring both original content and parsed section arrays.

## Frequently Asked Questions

### What is the FixerInputSchema?

`FixerInputSchema` is a Zod validation schema defined in [`packages/cli/src/linter/fixer/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/spec.ts) that enforces the structure of fixer requests. It requires the original document string (`content`) and an array of parsed sections, where each section contains a `heading` and its raw `content`. This schema ensures type safety before the reordering logic executes.

### How does the fixer handle unknown sections?

Unknown sections—those whose headings do not appear in `CANONICAL_ORDER`—are preserved but appended after all known sections. This behavior, implemented in [`handler.ts`](https://github.com/google-labs-code/design.md/blob/main/handler.ts) at lines 28-32, ensures that custom or experimental sections are not deleted during the fix process, only moved to the end of the document.

### What happens to the prelude section?

The prelude, defined as any section with an empty string heading, is automatically identified and pinned to the top of the output document. According to the source code in [`handler.ts`](https://github.com/google-labs-code/design.md/blob/main/handler.ts) at line 21, this ensures that front matter, metadata, or introductory text remains in the leading position regardless of sorting operations.

### How are section aliases resolved?

The fixer uses the `resolveAlias` helper from [`packages/cli/src/linter/spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.ts) (line 60) to expand alternative section titles to their canonical forms before checking against `CANONICAL_ORDER`. This allows documents using abbreviated or alternative headings to be correctly sorted according to the official specification.