How to Fix Section Ordering Issues Automatically with the Fixer API

The Fixer API deterministically reorders DESIGN.md sections according to canonical specifications while preserving preludes and custom sections, returning a corrected document string via the fixSectionOrder function.

The Fixer API in the google-labs-code/design.md repository provides a programmatic interface to automatically fix section ordering issues in DESIGN.md files. This API wraps the same validation logic used by the linter, ensuring your documentation follows the canonical structure defined in the project configuration.

How the Fixer API Works

The fixSectionOrder function in packages/cli/src/linter/fixer/handler.ts processes documents through a five-stage pipeline that guarantees deterministic output.

Input Validation

The API strictly enforces the FixerInputSchema defined in packages/cli/src/linter/fixer/spec.ts. The input must contain the original content string and a sections array, where each section object includes a heading (the section title) and its raw content.

Prelude Preservation

Any section with an empty string heading is identified as the "prelude" and locked to the top of the document. As implemented in handler.ts at line 21, this ensures introductory material such as front-matter or free-form text remains unchanged.

Section Classification

The fixer separates sections into known and unknown categories. Known sections are those whose canonical heading appears in CANONICAL_ORDER, the ordered list derived from spec-config.yaml. The resolveAlias helper in packages/cli/src/linter/spec-config.ts (line 60) expands aliases to canonical forms before checking. Unknown sections—custom or future sections not in the specification—are identified but left unsorted.

Canonical Sorting

Known sections are sorted according to their index within CANONICAL_ORDER. The implementation in handler.ts (lines 33-36) uses this index to determine the correct sequence, ensuring consistent ordering across all documents.

Document Reassembly

The final document is reconstructed by concatenating the prelude, followed by sorted known sections, then unknown sections. Each section is joined with a single newline. The function returns an object containing fixedContent (the reordered document) and optional details showing the before and after heading orders for debugging purposes (lines 51-60).

Implementing the Fixer API

You can integrate the fixer into your workflow through direct programmatic access, CLI commands, or web services.

Direct API Usage

Import fixSectionOrder from the handler module and provide a valid FixerInput object:

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` splits a DESIGN.md file into the required shape
const { sections, rawContent } = parseDesignMd('my-design.md');

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

const result = fixSectionOrder(input);

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

CLI Shortcut

For command-line usage, the design-md fix command wraps the API functionality:

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

This command parses the file into sections, invokes fixSectionOrder, and writes the fixedContent to the specified output file.

Web Service Integration

Deploy the fixer as an HTTP endpoint using Express:

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);

Configuration and Alias Resolution

The sorting logic relies on CANONICAL_ORDER defined in packages/cli/src/linter/spec-config.ts. This configuration determines the canonical sequence of sections. The resolveAlias function handles heading variations by mapping aliases to their canonical forms before sorting, ensuring that documents using synonyms or alternate titles are correctly ordered according to the specification.

Summary

  • The Fixer API automatically reorders DESIGN.md sections to match canonical specifications via the fixSectionOrder function.
  • Input requires validated FixerInput with content and sections array as defined in packages/cli/src/linter/fixer/spec.ts.
  • Prelude sections (empty headings) remain fixed at the top of the document according to handler.ts line 21.
  • Unknown sections are preserved and appended after known sections rather than being discarded.
  • The API returns both the corrected fixedContent string and optional debugging details showing the transformation.

Frequently Asked Questions

How does the Fixer API handle custom sections not in the canonical order?

Unknown sections—those whose headings do not match entries in CANONICAL_ORDER—are not deleted or modified. Instead, they are appended after all known sections in their original relative order, preserving custom content while standardizing the core structure.

What happens to the prelude or front-matter when fixing section order?

The fixer identifies any section with an empty string heading as the prelude. This section is always kept at the very top of the output document, ensuring that introductory content, front-matter, or free-form text remains unchanged regardless of the sorting operation.

Can I use the Fixer API without the CLI?

Yes. The fixSectionOrder function is exported from packages/cli/src/linter/fixer/handler.ts and can be imported directly into Node.js or TypeScript applications. This allows integration into custom build pipelines, pre-commit hooks, or web services without invoking the command-line interface.

How does the API resolve section aliases before sorting?

The resolveAlias helper in packages/cli/src/linter/spec-config.ts (line 60) maps alternate section titles to their canonical forms before checking against CANONICAL_ORDER. This ensures that documents using synonyms or legacy heading names are correctly positioned according to the specification.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →