Skip to content

Specs

No template or pipeline change lands in this repo without a spec it implements. A spec captures the driver, the decisions, and the reasoning behind them — in a single, reviewable document — before any templates/ file changes. See Explanation: spec-first development for why this discipline exists; this page is the how.

Specs directory

All specs live in docs/development/specs/ and follow the naming convention:

YYYY-MM-DD-<slug>.md

The ISO 8601 date prefix keeps them in creation order. Examples:

  • 2026-06-03-go-track-v0.9.md
  • 2026-06-23-change-detection.md
  • 2026-06-30-docs-diataxis-restructure.md

Process

  1. Identify the driver. What problem does this solve? What's the concrete trigger — a bug, a new track, a pain point on the runner? Be specific; "improve performance" is not a driver, "the docs site rebuilds on every Go-only MR" is.
  2. Draft with an AI assistant if you like (this repo's specs consistently are) — see the suggested prompt below. Iterate: answer open questions, correct assumptions, push back on a decision that doesn't hold up.
  3. Number the decisions (D1, D2, …) so a review, an MR, or a later spec can reference one precisely — see Spec structure.
  4. Add the frontmatter (see template) with status: draft, save to docs/development/specs/YYYY-MM-DD-<slug>.md, and open an MR for review.
  5. Get it to approved before implementing. Only an approved spec is safe to build against.
  6. Implement — write the template, its self-test, and its reference page — see Contributing: the workflow for the full component-authoring sequence.
  7. Flip status: implemented when it ships, and add a row to the decision log.

Suggested prompt

I want you to draft a spec for a change to phpboyscout/cicd (a monorepo
of reusable GitLab CI/CD components).

## Driver

<What problem does this solve? What's the concrete trigger?>

## Scope

<Which component(s) does this touch — a new one, or an existing one's
input shape? List them.>

## Context

I have attached the following files for reference:
- docs/contributing/index.md — the authoring conventions (no global
  keywords, stage/image always inputs, path-lists as strings, the
  token-input convention, rules: shape).
- <the existing templates/<name>.yml this touches, if any>
- <a similar recent spec, as a structure/depth reference — see
  docs/development/specs/ for examples>

## Instructions

- Follow the authoring conventions in docs/contributing/index.md exactly.
- Structure the decisions as a numbered list (D1, D2, …), each with enough
  reasoning that a reader understands *why*, not just *what*.
- Consider: does this change input shape (minor bump) or not (patch)?
  Does it need a self-test? Does an existing consumer need a follow-up
  change?
- Flag any open questions explicitly rather than silently picking an
  answer.
- Set status: draft in the frontmatter.
- Save to docs/development/specs/YYYY-MM-DD-<slug>.md.

Spec structure

A well-formed spec covers, adapted to scope:

  1. Header — repository, released-as version, driver (2-3 sentences).
  2. Summary (optional, for larger specs) — the shape of the change in a paragraph, before the numbered decisions.
  3. DecisionsD1, D2, … each a heading with the reasoning, code examples where useful, and cross-references to related specs.
  4. Consumers (where relevant) — which projects pick this up, and how.
  5. Risk register (for higher-stakes changes) — what could go wrong, and the mitigation.
  6. Resolved — open questions settled during review, dated, so the why survives past the discussion that produced it.
  7. Follow-ups — deliberately deferred work, so it's recorded rather than forgotten.

Browse existing specs (via the sidebar, or the decision log) for real examples at every scale — from a one-input patch to a multi-component track.

Status lifecycle

Every spec carries a status field in its frontmatter:

Status Icon Meaning
draft Under discussion. Not yet safe to implement against.
approved Reviewed and accepted. Safe to implement.
implemented Shipped — flip this when the change merges or tags.
rejected Considered and declined. Kept, not deleted — see below.

The icon appears next to the page's title in the nav sidebar automatically — no extra step, it's driven by the status: frontmatter every spec already carries.

Handling a rejection

When a spec is rejected, keep the file — it's the record that the proposal was considered and why it didn't proceed, so the same idea isn't re-raised from scratch without that context. Add a short Rejection rationale note near the top explaining the reasoning, and set status: rejected.

Amending a spec after the fact

A decision occasionally proves wrong once it meets a real build or a real consumer — this happened twice to 2026-06-30-docs-diataxis-restructure.md's navigation approach. The house style: add a dated note under a ## Resolved section explaining what changed and why, rather than silently rewriting the original decision text. The spec should show its own history, the same way the decision log shows the project's.

Frontmatter template

---
title: phpboyscout/cicd — <slug in words>
description: <one or two sentences — what this decides and why, specific enough to stand alone in the decision log>
status: draft
date: YYYY-MM-DD
authors: [Your Name]
tags: [spec, cicd, components, <relevant tags>]
---