From b41ee1fba0288dd594d13c26e56661569b364d8d Mon Sep 17 00:00:00 2001 From: Mark Larah Date: Mon, 2 Feb 2026 12:32:38 -0600 Subject: [PATCH 1/2] allow for multi-file spec formats --- CONTRIBUTING.md | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2806972..638c6f8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,13 +20,25 @@ that address issues outside the core GraphQL specifications. Each `GAP-NNNN` folder must include: -- `DRAFT.md` — the working document of the proposal/specification, written in - [`spec-md`](https://spec-md.com/) format +- `DRAFT.md` or `DRAFT/` — the working document of the proposal/specification, + written in [`spec-md`](https://spec-md.com/) format (see below) - `README.md` — a brief overview, why it exists, current status, challenges, drawbacks, and related resources/prior art (written in GitHub Flavoured Markdown) - `metadata.yml` — maintainers, status, and related metadata +#### Single-file vs split-file format + +Specifications may be authored as either: + +- **Single-file**: A single `DRAFT.md` file containing the entire specification. +- **Split-file**: A `DRAFT/` directory with an `Index.md` entry point that may + include other files. This is useful for larger specifications that benefit + from being organized into multiple sections. + +For split-file specs, the `DRAFT/index.md` file serves as the main entry point +and should use spec-md's import syntax to include other files as needed. + #### `metadata.yml` Required fields: @@ -67,11 +79,15 @@ by the TSC. The authors are responsible for guiding contribution to the GAP. ### Versioning -To release a version of a GAP, copy the current `DRAFT.md` into a `versions` -folder named for the year and month of release: +To release a version of a GAP, copy the current draft into a `versions` folder +named for the year and month of release: ```bash +# Single-file format cp GAP-NNNN/DRAFT.md GAP-NNNN/versions/YYYY-MM.md + +# Split-file format +cp -r GAP-NNNN/DRAFT GAP-NNNN/versions/YYYY-MM ``` Rules: From 11b80dfdb93c8ee90dd64ec727ce24347bf9ded8 Mon Sep 17 00:00:00 2001 From: Mark Larah Date: Mon, 16 Feb 2026 21:57:57 -0600 Subject: [PATCH 2/2] update scripts/validate-structure.js to allow for DRAFT folder --- scripts/validate-structure.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/scripts/validate-structure.js b/scripts/validate-structure.js index e1a88b6..46e625e 100755 --- a/scripts/validate-structure.js +++ b/scripts/validate-structure.js @@ -58,6 +58,28 @@ function validateReadmeExists(dirPath, gapName) { } } +function validateDraftExists(dirPath, gapName) { + const draftFilePath = join(dirPath, "DRAFT.md"); + const draftDirPath = join(dirPath, "DRAFT"); + const draftIndexPath = join(draftDirPath, "Index.md"); + + const hasDraftFile = existsSync(draftFilePath); + const hasDraftDir = existsSync(draftDirPath) && statSync(draftDirPath).isDirectory(); + const hasDraftIndex = hasDraftDir && existsSync(draftIndexPath); + + if (!hasDraftFile && !hasDraftDir) { + error(gapName, "No DRAFT.md file or DRAFT/ directory found"); + } + + if (hasDraftFile && hasDraftDir) { + error(gapName, "Both DRAFT.md and DRAFT/ directory exist - only one is allowed"); + } + + if (hasDraftDir && !hasDraftIndex) { + error(gapName, "DRAFT/ directory exists but DRAFT/Index.md is missing"); + } +} + function validateMetadata(dirPath, gapName) { const metadataPath = join(dirPath, "metadata.yml"); @@ -148,6 +170,9 @@ function main() { // Validate README.md exists validateReadmeExists(dirPath, gapName); + // Validate DRAFT.md or DRAFT/ exists + validateDraftExists(dirPath, gapName); + // Validate metadata.yml validateMetadata(dirPath, gapName); }