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:
The ISO 8601 date prefix keeps them in creation order. Examples:
2026-06-03-go-track-v0.9.md2026-06-23-change-detection.md2026-06-30-docs-diataxis-restructure.md
Process¶
- 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.
- 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.
- Number the decisions (
D1,D2, …) so a review, an MR, or a later spec can reference one precisely — see Spec structure. - Add the frontmatter (see template) with
status: draft, save todocs/development/specs/YYYY-MM-DD-<slug>.md, and open an MR for review. - Get it to
approvedbefore implementing. Only anapprovedspec is safe to build against. - Implement — write the template, its self-test, and its reference page — see Contributing: the workflow for the full component-authoring sequence.
- Flip
status: implementedwhen 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:
- Header — repository, released-as version, driver (2-3 sentences).
- Summary (optional, for larger specs) — the shape of the change in a paragraph, before the numbered decisions.
- Decisions —
D1,D2, … each a heading with the reasoning, code examples where useful, and cross-references to related specs. - Consumers (where relevant) — which projects pick this up, and how.
- Risk register (for higher-stakes changes) — what could go wrong, and the mitigation.
- Resolved — open questions settled during review, dated, so the why survives past the discussion that produced it.
- 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>]
---