diff --git a/.github/workflows/README.md b/.github/workflows/README.md
index 583e188..9ae3d34 100644
--- a/.github/workflows/README.md
+++ b/.github/workflows/README.md
@@ -3,6 +3,40 @@
Org-wide CI building blocks. Callable from any `resq-software/*` repo via
`uses: resq-software/.github/.github/workflows/.yml@main`.
+## `repo-standards.yml`
+
+Template/standards conformance check. Validates that a repo has a detectable
+`LICENSE`, a non-stub `README.md` with a title, and no leftover
+`{{PLACEHOLDER}}` tokens or `ResQ README Template` scaffold markers.
+
+It is already wired into `required.yml` (so every consumer repo inherits it
+through the `required` status check) and into `required-gate.yml` (so this
+repo dogfoods it). You don't call it directly unless you want a standalone
+conformance job.
+
+**Warn-by-default**, matching the org's audit → enforce pattern
+(harden-runner audit, rulesets evaluate). Violations surface as
+`::warning` annotations without failing the build. Once a repo is clean,
+flip enforcement on by passing `repo-standards-strict: true` to
+`required.yml`:
+
+```yaml
+jobs:
+ ci:
+ uses: resq-software/.github/.github/workflows/required.yml@main
+ with:
+ lang: rust
+ repo-standards-strict: true # turn conformance violations into a hard failure
+```
+
+### Inputs (when called directly)
+
+| Input | Type | Default | Notes |
+| :-- | :-- | :-- | :-- |
+| `strict` | bool | `false` | Fail the job on any violation. Default warns only. |
+| `require-license` | bool | `true` | Require a `LICENSE`/`COPYING` file at the repo root. |
+| `readme-min-bytes` | string | `"500"` | README smaller than this is treated as a stub. |
+
## `security-scan.yml`
Defense-in-depth security scan. All third-party `uses:` refs are SHA-pinned
diff --git a/.github/workflows/repo-standards.yml b/.github/workflows/repo-standards.yml
new file mode 100644
index 0000000..3266d88
--- /dev/null
+++ b/.github/workflows/repo-standards.yml
@@ -0,0 +1,124 @@
+# Copyright 2026 ResQ Software
+# SPDX-License-Identifier: Apache-2.0
+#
+# Reusable repo-conformance check. Validates that a consumer repo meets
+# the org template/standards baseline:
+# * a detectable LICENSE file (Apache-2.0 across the org)
+# * a non-stub README.md with a title and no leftover template tokens
+# * no unrendered {{PLACEHOLDER}} tokens or template scaffold markers
+#
+# Wired into required.yml (consumer repos) and required-gate.yml (this
+# repo), so the single `required` status check (gated by org ruleset
+# `default-branch-baseline`, id 15191038) also covers template
+# conformance. Warn-by-default to match the org's audit -> enforce
+# rollout pattern (harden-runner audit, rulesets evaluate). Flip
+# `strict: true` once a repo is clean to turn violations into a hard
+# CI failure.
+#
+# Security: inputs that reach `run:` are forwarded through `env:` and
+# referenced as "$VAR" to prevent template-time expansion of
+# caller-controlled strings into the shell.
+
+name: repo-standards
+
+on:
+ workflow_call:
+ inputs:
+ strict:
+ description: Fail the job on any violation. Default warns (annotations only).
+ type: boolean
+ required: false
+ default: false
+ require-license:
+ description: Require a detectable LICENSE/COPYING file at the repo root.
+ type: boolean
+ required: false
+ default: true
+ readme-min-bytes:
+ description: Minimum README.md size in bytes; smaller is treated as a stub.
+ type: string
+ required: false
+ default: "500"
+
+permissions:
+ contents: read
+
+jobs:
+ repo-standards:
+ name: repo-standards
+ runs-on: ubuntu-latest
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2
+ with:
+ egress-policy: audit
+
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
+
+ - name: Check repo conformance
+ env:
+ STRICT: ${{ inputs.strict }}
+ REQUIRE_LICENSE: ${{ inputs.require-license }}
+ README_MIN_BYTES: ${{ inputs.readme-min-bytes }}
+ run: |
+ set -eu
+ violations=0
+ note() {
+ printf '::warning title=repo-standards::%s\n' "$1"
+ violations=$((violations + 1))
+ }
+
+ # ── LICENSE ──────────────────────────────────────────────────────
+ # POSIX glob loop (not ls/find) so shellcheck stays happy and odd
+ # filenames are handled safely. Unmatched globs stay literal, so the
+ # `[ -e ]` test is false for them.
+ if [ "$REQUIRE_LICENSE" = "true" ]; then
+ license_found=no
+ for f in LICENSE LICENSE.* COPYING COPYING.*; do
+ if [ -e "$f" ]; then license_found=yes; break; fi
+ done
+ if [ "$license_found" = yes ]; then
+ echo "ok: LICENSE present"
+ else
+ note "No LICENSE/COPYING file at repo root (org standard: Apache-2.0)."
+ fi
+ fi
+
+ # ── README ───────────────────────────────────────────────────────
+ if [ ! -f README.md ]; then
+ note "No README.md at repo root."
+ else
+ bytes=$(wc -c < README.md | tr -d ' ')
+ if [ "$bytes" -lt "$README_MIN_BYTES" ]; then
+ note "README.md is a stub ($bytes bytes < $README_MIN_BYTES required)."
+ fi
+ if ! grep -qE '^[[:space:]]*(#[[:space:]]|')."
+ fi
+ # Count DISTINCT {{TOKEN}} occurrences, excluding the literal
+ # meta-example {{PLACEHOLDER}} (which docs legitimately mention).
+ # An unrendered template carries many distinct tokens
+ # ({{PROJECT_NAME}}, {{REPO}}, ...); a doc mentioning the syntax
+ # once should not trip. Threshold: 3 distinct tokens.
+ ph_count=$(grep -oE '\{\{[A-Z0-9_]+\}\}' README.md \
+ | grep -vxF '{{PLACEHOLDER}}' | sort -u | wc -l | tr -d ' ')
+ if [ "$ph_count" -ge 3 ]; then
+ note "README.md still has $ph_count distinct {{PLACEHOLDER}} tokens (unrendered template?)."
+ fi
+ if grep -q 'ResQ README Template' README.md; then
+ note "README.md still contains the template scaffold marker comment."
+ fi
+ fi
+
+ # ── Summary ──────────────────────────────────────────────────────
+ if [ "$violations" -eq 0 ]; then
+ echo "repo-standards: all checks passed."
+ exit 0
+ fi
+ echo "repo-standards: $violations violation(s) found."
+ if [ "$STRICT" = "true" ]; then
+ echo "::error title=repo-standards::strict mode — failing on $violations violation(s)."
+ exit 1
+ fi
+ echo "repo-standards: warn mode — not failing the build. Set strict:true to enforce."
+ exit 0
diff --git a/.github/workflows/required-gate.yml b/.github/workflows/required-gate.yml
index 5e03adf..44fa12d 100644
--- a/.github/workflows/required-gate.yml
+++ b/.github/workflows/required-gate.yml
@@ -28,12 +28,27 @@ concurrency:
cancel-in-progress: true
jobs:
+ # Dogfood the org template/standards check on this repo itself.
+ repo-standards:
+ name: Repo standards
+ uses: ./.github/workflows/repo-standards.yml
+
required:
name: required
+ needs: [repo-standards]
+ if: always()
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2
with:
egress-policy: audit
- - run: echo "ok — .github repo has no language CI to gate on"
+ - name: Evaluate upstream results
+ env:
+ REPO_STANDARDS_RESULT: ${{ needs.repo-standards.result }}
+ run: |
+ set -eu
+ case "$REPO_STANDARDS_RESULT" in
+ success|skipped|"") echo "ok — .github repo has no language CI to gate on" ;;
+ *) echo "::error::repo-standards returned: $REPO_STANDARDS_RESULT"; exit 1 ;;
+ esac
diff --git a/.github/workflows/required.yml b/.github/workflows/required.yml
index ae1c8a9..d8b6a96 100644
--- a/.github/workflows/required.yml
+++ b/.github/workflows/required.yml
@@ -105,6 +105,15 @@ on:
type: string
required: false
default: ""
+ repo-standards-strict:
+ description: >
+ Fail `required` when the repo violates template/standards
+ conformance (LICENSE present, non-stub README, no leftover
+ {{PLACEHOLDER}} tokens). Default warns only — flip to true once
+ the repo is clean.
+ type: boolean
+ required: false
+ default: false
permissions:
contents: read
@@ -198,10 +207,17 @@ jobs:
source-dir: ${{ inputs.cpp-source-dir }}
cmake-flags: ${{ inputs.cpp-cmake-flags }}
+ # Template/standards conformance — lang-independent, runs for every repo.
+ repo-standards:
+ name: Repo standards
+ uses: ./.github/workflows/repo-standards.yml
+ with:
+ strict: ${{ inputs.repo-standards-strict }}
+
# `required` is the single status-check context consumed by Ruleset A.
required:
name: required
- needs: [validate-lang, security, rust, python, node, dotnet, cpp]
+ needs: [validate-lang, security, rust, python, node, dotnet, cpp, repo-standards]
if: always()
runs-on: ubuntu-latest
steps:
@@ -218,6 +234,7 @@ jobs:
NODE_RESULT: ${{ needs.node.result }}
DOTNET_RESULT: ${{ needs.dotnet.result }}
CPP_RESULT: ${{ needs.cpp.result }}
+ REPO_STANDARDS_RESULT: ${{ needs.repo-standards.result }}
run: |
set -eu
# validate-lang must be success — typo defenses handled there
@@ -226,7 +243,7 @@ jobs:
exit 1
fi
fail=0
- for r in "$SECURITY_RESULT" "$RUST_RESULT" "$PYTHON_RESULT" "$NODE_RESULT" "$DOTNET_RESULT" "$CPP_RESULT"; do
+ for r in "$SECURITY_RESULT" "$RUST_RESULT" "$PYTHON_RESULT" "$NODE_RESULT" "$DOTNET_RESULT" "$CPP_RESULT" "$REPO_STANDARDS_RESULT"; do
case "$r" in
success|skipped|"") ;;
*) echo "::error::Upstream job returned: $r"; fail=1 ;;
diff --git a/README.template.md b/README.template.md
index 0265fc4..3e69273 100644
--- a/README.template.md
+++ b/README.template.md
@@ -83,20 +83,38 @@
+
+
+ Documentation
+ ·
+ Website
+ ·
+ Quick Start
+ ·
+ Report Bug
+ ·
+ Request Feature
+
+
---
## Table of Contents
- [Overview](#overview)
+- [Demo](#demo)
- [Features](#features)
+- [Prerequisites](#prerequisites)
- [Install](#install)
- [Quick Start](#quick-start)
- [Usage](#usage)
- [Configuration](#configuration)
- [Contributing](#contributing)
+- [Security](#security)
+- [Support](#support)
- [Changelog](#changelog)
- [License](#license)
+- [Acknowledgements](#acknowledgements)
---
@@ -123,9 +141,28 @@ It {{CORE_VALUE_PROPOSITION}}.
---
+## Demo
+
+
+
+
+
+
+
+> **Try it live:** [{{LIVE_DEMO_URL}}]({{LIVE_DEMO_URL}}) · [Playground](https://resq.software)
+
+---
+
## Features
-
+
- **{{FEATURE_1}}** — {{FEATURE_1_DESCRIPTION}}
- **{{FEATURE_2}}** — {{FEATURE_2_DESCRIPTION}}
@@ -133,11 +170,46 @@ It {{CORE_VALUE_PROPOSITION}}.
---
+## Prerequisites
+
+
+
+| Requirement | Minimum | Notes |
+|-------------|---------|-------|
+| `{{RUNTIME}}` | `{{MIN_VERSION}}` | {{RUNTIME_NOTE}} |
+| Platform | Linux / macOS / Windows | {{PLATFORM_NOTE}} |
+
+---
+
## Install
+
+
+### ResQ CLI
+
+Install the [`resq`](https://github.com/resq-software/crates) toolchain (and,
+when run inside a repo, the canonical git hooks) in one line:
+
+```sh
+curl -fsSL https://get.resq.software | sh
+```
+
+Prefer to read before piping to a shell:
+
+```sh
+curl -fsSL https://get.resq.software -o install-resq.sh
+less install-resq.sh
+sh install-resq.sh
+```
+
### Node / Bun
```sh
@@ -259,6 +331,30 @@ All PRs must follow the `type(scope): subject` format — see the table below.
| `BREAKING CHANGE` footer or `!` suffix | Major bump (`x.0.0`) |
| `docs:` `style:` `refactor:` `test:` `chore:` | No version bump |
+**CI gate:** every PR must keep the `required` status check green (org
+ruleset `default-branch-baseline`). That single check aggregates language
+CI, the security scan, and repo-standards conformance — see
+[resq-software/.github](https://github.com/resq-software/.github).
+
+---
+
+## Security
+
+Found a vulnerability? **Do not open a public issue.** Follow the
+coordinated-disclosure process in [`SECURITY.md`](./SECURITY.md) (inherited
+org-wide from [resq-software/.github](https://github.com/resq-software/.github/blob/main/SECURITY.md)).
+
+This project ships SHA-pinned CI actions and is scanned for vulnerable
+dependencies and leaked secrets on every push.
+
+---
+
+## Support
+
+- 📖 **Docs:** [docs.resq.software](https://docs.resq.software)
+- 💬 **Questions / help:** see [`SUPPORT.md`](./SUPPORT.md)
+- 🐛 **Bugs & features:** [open an issue](https://github.com/resq-software/{{REPO}}/issues/new/choose)
+
---
## Changelog
@@ -278,6 +374,17 @@ Licensed under the [Apache License, Version 2.0](./LICENSE).
---
+## Acknowledgements
+
+
+
+- Built on the [ResQ platform](https://resq.software).
+- {{ACKNOWLEDGEMENT_1}}
+
+---
+