Releases: L3DigitalNet/project-standards
Releases · L3DigitalNet/project-standards
v3.0.0 — adopt CLI, validate-id, frontmatter suite, pre-commit hooks
Migration from v2. This is a major release; adopt it deliberately. Full step-by-step runbook: UPGRADING.md.
Breaking changes requiring migration before re-pinning:
validate-idnow runs in CI. Ids in old-style kebab format (e.g.restart-netbox-after-config-change) will fail thevalidate-idstep. Runvalidate-id --fix --config .project-standards.ymlto auto-regenerate non-ADR ids. ADR ids must be updated by hand toadr-{NNNN}-{repo-name}-{short-title}.- Re-pin both refs to
@v3. Bumpvalidate-markdown-frontmatter.yml@v2→@v3and setstandards-ref: 'v3'together so the workflow definition and installed validator don't drift. - Remove any duplicate top-level frontmatter keys.
parse_frontmatternow rejects them (previously the last value silently won).
Added
format-frontmattercommand — reformats YAML frontmatter to canonical style (--write/--check). Applies key ordering, single-quote wrapping,type→doc_typerename, block-list style for non-empty arrays.validate-referencescommand — opt-in cross-file checker (setmarkdown.frontmatter.references.enabled: true). Enforces id uniqueness, referential integrity, supersede reciprocity, date ordering, ADR-number uniqueness. No-op until opted in.project-standards fixsubcommand — three-phase pipeline: format → regenerate ids → re-run fullvalidateas postcondition.project-standards validateruns all three validators —validate-frontmatter,validate-id, andvalidate-referencescombined.validate-idcommand — enforces{doc_type}-{6-char base36}-{slug}for standard doc types;adr-{NNNN}-{repo-name}-{short-title}for ADRs. Skips files with no frontmatter or a custom schema.project-standards adopt <standard>CLI — materializes canonical artifacts into a consumer repo. Idempotent, path-safe, atomic writes. Supports all four standards, individually or together.fragmentartifacts reported for manual merge, never written.- Per-standard
adopt.tomlmanifests undersrc/project_standards/bundles/. .pre-commit-hooks.yaml— six hooks:format-frontmatter-fix,format-frontmatter-check,validate-id-fix,validate-id-check,validate-frontmatter,validate-references.standards/python-coding/— Python Coding standard (in-development draft, version 0.4). Reference-only; unregistered; not adoptable via CLI.
Changed
- Reusable workflow now also runs
validate-idandvalidate-references(references is a self-gated no-op unless opted in). - Copy-adopt scaffolds relocated from README prose into packaged bundles; each standard's
adopt.mdnow referencesproject-standards adopt <id>.
v2.0.0
Migration from v1. This is a major release; adopt it deliberately:
- Re-pin to
@v2. Bump the reusable-workflow pinvalidate-markdown-frontmatter.yml@v1→@v2and setstandards-ref: 'v2'(the workflow now defaultsstandards-reftov2). The opt-in body linterlint-markdown.yml@v2becomes available at this tag. - The validator CLI now requires Python 3.14+. Installing the
project-standardspackage viauv tool installneeds Python 3.14 (requires-python>=3.11→>=3.14). - Copy-adopters, on re-sync only: the Python Tooling baseline is now 3.14, and the §15 CI template SHA-pins
astral-sh/setup-uv(the old@v8tag no longer resolves). - Doc deep-links moved into the per-standard bundles (
standards/<name>/…) andmeta/. The validation contract is unchanged — reusable-workflow names, thevalidate-frontmatterentry point, and the bundled schema path are identical — so a repo that passed on@v1keeps passing after re-pinning to@v2.
Added
- Python tooling stack adopted from
standards/python-tooling-ssot-standard.md:uv_buildbackend,src/layout, the validator moved tosrc/project_standards/with the schema bundled inside the package,basedpyright(strict), branch coverage (fail_under = 85), andpip-audit. CI gate consolidated tocheck.yml. - Opt-in ADR section check (
markdown.adr.require_sections). A new, default-off config flag makes the validator additionally assert that everydoc_type: adrdocument contains the three MADR-required level-2 sections —## Context and Problem Statement,## Considered Options,## Decision Outcome. The match is exact and case-sensitive; headings inside fenced code blocks (e.g. template snippets) and the optional MADR sections are correctly ignored. It lives under a separatemarkdown.adrconfig namespace, keeping the validator's frontmatter remit distinct. This repo enables it to dogfood the shipped ADR example. Additive (default off) → MINOR. - Opt-in Markdown body linting (Stack B). A new reusable workflow
.github/workflows/lint-markdown.ymlrunsmarkdownlint-cli2(viaDavidAnson/markdownlint-cli2-action@v23) against the repo's published.markdownlint.json, finally executing the Markdown body rules that previously shipped as config with no runner. It is separate fromvalidate-markdown-frontmatter.ymlso frontmatter-only consumers never inherit a Node toolchain — opt in withuses: L3DigitalNet/project-standards/.github/workflows/lint-markdown.yml@v2. The action bundles its own Node runtime and auto-discovers.markdownlint.json, so no committed Node project is required. Also adds.markdownlint-cli2.jsonc(a local-runner config that honors.gitignore, so a barenpx markdownlint-cli2matches CI) and agithub-actionsDependabot entry to keep the action pins current. Additive — pin@v2. - Per-standard contract versions. Each standard now carries its own
major.minorcontract version, selected independently in.project-standards.yml(markdown.frontmatter.version,markdown.adr.version,python_tooling.version). A bundled registry (src/project_standards/schemas/registry.json) maps versions to schemas and records ADR→Frontmatter compatibility, which the validator now enforces. All keys are optional and default to today's behaviour — a config with noversion:keys validates byte-identically. The Python Tooling internal-revision counter is replaced by contract version1.0. Additive — seemeta/versioning.md. - Markdown Tooling Standard (
standards/markdown-tooling/). A new governed bundle documenting the recommended linting/formatting tools and settings for Markdown and the structured-text files Prettier handles: markdownlint (the seedable.markdownlint.jsonrule set + the reusablelint-markdown.yml@v2workflow), Prettier (copy-adopt formatter config; no reusable workflow, DEC-9), and EditorConfig. Source-backed, parallel to the Python Tooling standard, and cross-linked from the tool-neutral Frontmatter standard. Adds a validatedmarkdown_toolingcontract version (1.0) toregistry.json, recognized by the validator (markdown_tooling.version; unknown values exit 2) likepython_tooling.version. Additive — MINOR.
Changed
- Python Tooling standard — lint/format/type-check scope made explicit and flexible. The
src/requirement now governs the importable package/product only; repo tooling,scripts/, archived, and non-product Python may live outsidesrc/(still linted + formatted, not held to the strict-src/typing bar). Directories owned by external programs (.claude/,.agents/,.codex/,.vscode/,.github/,.venv/,.continue/, …) are excluded from the toolchain (baseline gains[tool.ruff].extend-exclude). The full stack stays mandatory — only file scope is tunable. Loosening only; nothing previously-passing newly fails. - BREAKING (CLI consumers):
requires-pythonraised>=3.11→>=3.14. Installs viauv tool installnow require Python 3.14+. The repo dogfoods its own Python Tooling baseline —.python-version, Rufftarget-version, and BasedPyrightpythonVersionall track 3.14. - BREAKING (Python Tooling standard, copy-adopted): default Python baseline raised 3.13 → 3.14.
standards/python-tooling/now scaffoldsrequires-python = ">=3.14",.python-version3.14, Rufftarget-version = "py314", and BasedPyrightpythonVersion = "3.14"(3.14 is the current stable CPython release). Permeta/versioning.md, raising the required Python is MAJOR for a consumer that re-syncs scaffolds; thepython_toolingcontract-version label stays1.0(metadata-only, unenforced). - BREAKING (docs layout):
standards/restructured into one self-contained bundle per governing standard —standards/<name>/{README.md, adopt.md, templates/, examples/}. The flat top-leveltemplates/andexamples/trees were dissolved into the bundles, andversioning.mdmoved tometa/. Addedstandards/README.md(index + bundle anatomy) and per-standardadopt.mdentries. Doc deep-links change; the consumer contract is unchanged — reusable workflow names, thevalidate-frontmatterpackage + entry point, and the bundled schema path are identical. .markdownlint.jsonnow states every rule explicitly (53 rules), not just the 13 overrides. A consuming repo that seeds its config from ours now gets deterministic linting that isn't shadowed by a contributor's personal editor/global markdownlint settings, and is pinned against default drift across markdownlint versions. Behaviour is identical to the previous sparse config in a clean environment (verified: the repo lints with zero errors either way, and the explicit config validates against the v0.40.0 config schema). One subtlety encoded:MD043staystrue(inert) rather than its schema-declaredheadings: []default, which would otherwise demand zero headings (atests/test_markdownlint_config.pyguard pins that and the customisations). Because the explicit values track a markdownlint version, themarkdownlint-cli2-action@v23pin is load-bearing — re-verify on upgrade.- ADR Standard — body structure now lists three required sections, not four.
standards/adr/README.mdpreviously marked Consequences as a fourth required section; MADR 4.0 (and the repo's own templates and worked example) treat it as an optional### Consequencessub-section of Decision Outcome. The required set is now the three MADR-required##sections, matching the new opt-in validator check. Prose-only correction — no document that previously passed can newly fail. .markdownlint.json—MD024(no-duplicate-heading) nowfalse, matching MADR 4.0's owntemplate/.markdownlint.yml(was{ siblings_only: true }). MADR ADRs repeat option headings across the Considered Options and Pros and Cons sections; disabling the rule mirrors upstream tooling exactly. Strictly looser than before, so no previously-passing document can newly fail — additive.- ADR Standard — corrected the MADR acronym expansion from "Markdown Any Decision Records" to "Markdown Architectural Decision Records" in
standards/adr/README.md. MADR 4.0 (2024-09-17) reverted the name to "Architectural"; the prior wording tracked the superseded MADR 3.x spelling. - ADR Standard —
idnow embeds the repo-name for cross-repo uniqueness. ADR ids becomeadr-NNNN-repo-name-short-title(e.g.adr-0001-homelab-use-postgresql-for-persistent-storage) so that an ADR referenced from another repository'srelated:list stays globally unambiguous across a fleet of repos. The filename keeps theadr-NNNN-short-title.mdform —adr-prefix, no repo-name — making ADRs the one documented case where filename andiddiffer, consistent with the standard's existing "idis independent of file path" rule. Templates show therepo-nameslot plus a save-as comment; the worked example and its two inboundrelated:references were updated to match. Deliberately diverges from MADR's bare-number filenames (MADR tooling is an optional convenience here, not a conformance target). Greenfield (no consumer ADRs exist yet) and filenames are not schema-validated, so nothing can newly fail — additive. - ADR Standard promoted to the source-checked documentation tier.
standards/adr/README.mdgains an Evidence convention,[Sxx]citations at the load-bearing MADR claims, a dated Source register, a Source coverage map, and a "Last source check" status banner — matching the Python/Markdown Tooling standards (previously it followed the narrative tier like the Frontmatter standard). MADR was re-verified against the live spec on 2026-06-07: 4.0.0 (2024-09-17) is the current release, and the acronym, the three required + five optional sections, the status vocabulary, and the MADR→canonical field mappings all match. Also refreshed staleupdated/revieweddates on ...