How DESIGN.md Handles Unknown Section Headings and Custom Extension Keys

DESIGN.md gracefully tolerates unknown section headings and custom extension keys by preserving the original values while emitting linter warnings, ensuring forward compatibility without hard failures.

The google-labs-code/design.md parser and linter are architected for resilience, allowing documents to evolve with vendor-specific extensions or new sections. By implementing fallback mechanisms in the alias resolution and YAML parsing stages, the system handles unknown content without breaking the build.

Resolving Unknown Section Headings

The parser normalizes section headings through the resolveAlias utility, which implements a fail-soft strategy for unrecognized values.

Alias Resolution via resolveAlias

In packages/cli/src/linter/spec-config.ts, the resolveAlias function checks headings against the SECTION_ALIASES mapping. When a heading does not match any known alias, the function returns the original string unchanged using the nullish coalescing operator:

return SECTION_ALIASES[heading] ?? heading;

This behavior allows documents to contain non-standard section headings without triggering parsing errors. The section remains valid, though it is not mapped to a canonical specification name.

The following example demonstrates how known aliases resolve to canonical names while unknown section headings pass through unchanged:

import { resolveAlias } from './spec-config';

// Known alias – resolves to its canonical name
console.log(resolveAlias('Brand & Style')); // → "Overview"

// Unknown heading – returned unchanged
console.log(resolveAlias('NonExistentSection')); // → "NonExistentSection"

Section Order Validation

The section-order rule in section-order.ts interprets the resolved heading name. Since unknown headings return their original input rather than a canonical alias, the rule recognizes them as "unknown" and skips ordering validation for those specific sections. This prevents the linter from enforcing canonical sequence constraints on custom or future sections.

The test suite verifies this behavior through the case resolveAlias returns input for unknown heading, confirming that the system preserves custom headings exactly as authored.

Processing Custom Extension Keys

Beyond section headings, the system accommodates arbitrary top-level YAML keys through a dedicated collection mechanism.

Capture in Model Handler

In packages/cli/src/linter/model/handler.ts, the parser scans for keys that are not part of the core DESIGN.md specification. These custom extension keys are collected into the unknownKeys array, while their raw YAML values are stored in unknownKeyValues. This dual-storage approach allows downstream tooling to access extension data programmatically without interfering with standard spec generation.

import { parseDesignSystem } from './parser/handler';

// Suppose the DESIGN.md document contains:
//
// customExtension:
//   foo: bar
//   baz: 42
//
const parsed = parseDesignSystem(rawYaml, sourceMap, sections, docSections);

// `parsed.unknownKeys` lists the extra top‑level keys
console.log(parsed.unknownKeys); // → ["customExtension"]

// Raw values for those keys are kept intact
console.log(parsed.unknownKeyValues.customExtension);
// → { foo: "bar", baz: 42 }

Linting and Warnings

The linter surfaces these extensions through the unknownKey rule located in packages/cli/src/linter/linter/rules/unknown-key.ts. When state.unknownKeys contains entries, the rule emits a finding for each unrecognized key:

import { lint } from './linter';

// The linter will emit a finding for each unknown top‑level key
const result = lint(parsedDesignSystem);
result.findings.forEach(f => console.log(f.message));
// Example output: "Unknown top‑level key: customExtension"

This warning mechanism alerts authors to potential typos or experimental extensions while preserving the document's validity for custom workflows.

Key Implementation Files

The following source files implement the tolerance mechanisms for unknown section headings and custom extension keys:

File Role
packages/cli/src/linter/spec-config.ts Defines resolveAlias and the canonical/alias mapping.
packages/cli/src/linter/linter/rules/unknown-key.ts Linter rule that flags unknown top-level keys.
packages/cli/src/linter/model/handler.ts Parses the document, collects unknownKeys and unknownKeyValues.

Summary

  • DESIGN.md handles unknown section headings by returning them unchanged from resolveAlias, allowing the section-order rule to skip validation for non-canonical sections.
  • Custom extension keys are captured in unknownKeys and unknownKeyValues during parsing, preserving raw YAML without breaking spec generation.
  • The unknownKey linter rule emits warnings for unrecognized top-level keys, maintaining visibility into extensions while ensuring forward compatibility.
  • These mechanisms are implemented in spec-config.ts, model/handler.ts, and unknown-key.ts respectively.

Frequently Asked Questions

What happens when DESIGN.md encounters an unknown section heading?

The resolveAlias function in packages/cli/src/linter/spec-config.ts returns the original heading string unchanged. The section-order rule then identifies it as unknown and bypasses canonical ordering checks, keeping the document valid.

Can I use custom extension keys in DESIGN.md without breaking the parser?

Yes. The parser in packages/cli/src/linter/model/handler.ts collects custom top-level keys into unknownKeys and stores their values in unknownKeyValues. This allows arbitrary extensions to coexist with standard sections without causing parsing failures.

How does the linter report unknown keys in DESIGN.md?

The unknownKey rule in packages/cli/src/linter/linter/rules/unknown-key.ts checks state.unknownKeys and emits a finding for each unrecognized key, such as "Unknown top-level key: customExtension", alerting authors while preserving the document.

Where is the alias resolution logic implemented in DESIGN.md?

The alias resolution logic resides in packages/cli/src/linter/spec-config.ts, which exports the resolveAlias function and maintains the SECTION_ALIASES mapping used to normalize canonical section names.

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 →