Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions templates/_common/.agent/skills/maintenance/SKILL.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: "Use when you want to bring every drift-prone artifact in the repo

# Maintenance

This is the umbrella skill for {{ name }}. It does no rewriting itself — it decides which sync skills are stale, runs each one, and reports a combined summary. Use it when you do not know which specific artifact is out of date, or when several have likely drifted at once (for example, after a large merge).
This is the umbrella skill for {{ name }}, mandated by §21.6 of `OSS_SPEC.md`. It does no rewriting itself — it decides which sync skills are stale, runs each one, and reports a combined summary. Use it when you do not know which specific artifact is out of date, or when several have likely drifted at once (for example, after a large merge).

## When to run

Expand All @@ -19,13 +19,17 @@ Do **not** use this skill for a targeted fix — if you know exactly which artif

The registry is the single source of truth for which sync skills exist in this repo. Every `update-*` directory under `.agent/skills/` must appear here exactly once. New projects start with the entries below; add rows whenever you create a new sync skill.

| Skill | Fixes | Run order |
|---|---|---|
| `update-docs` | `docs/*.md` vs. source of truth | 1 |
| `update-readme` | `README.md` vs. current public surface | 2 |
| `update-prompts` | `prompts/**` vs. code and embedded sources | 3 |
| Skill | Fixes | Spec sections | Run order |
|---|---|---|---|
| `sync-oss-spec` | Repo contents vs. the latest `OSS_SPEC.md` fetched from GitHub (standalone — no external validator binary) | all structural §§ + §21.5 | 1 — run first so every downstream skill reads the freshest spec |
| `update-docs` | `docs/*.md` vs. source of truth | §11.1 | 2 |
| `update-readme` | `README.md` vs. current public surface | §3 | 3 |
| `update-prompts` | `prompts/**` vs. code and embedded sources | §13.5 | 4 |

Run order matters: upstream fixes must land before downstream skills read them. A skill that depends on README text (for example, an `update-website` skill if you add one) must run *after* `update-readme`.
Run order matters:

- `sync-oss-spec` runs **first** so every downstream skill sees the current spec — it may overwrite the local `OSS_SPEC.md` with the upstream copy, which downstream skills then read.
- The per-artifact skills (`update-docs`, `update-readme`, `update-prompts`, and any `update-website` / `update-manpages` / other skills this project adds) run afterwards in dependency order: a skill that reads files another skill rewrites must run *after* that other skill.

## Discovery process

Expand Down
Empty file.
191 changes: 191 additions & 0 deletions templates/_common/.agent/skills/sync-oss-spec/SKILL.md.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
---
name: sync-oss-spec
description: "Use when {{ name }} may have drifted from OSS_SPEC.md. Fetches the latest spec from GitHub, walks its mandates, and fixes each violation so the repository keeps conforming. Runs standalone — it does not shell out to any external validator binary."
---

# Syncing {{ name }} with OSS_SPEC.md

**Governing spec sections:** the entire `OSS_SPEC.md` (this skill is the propagation channel for every structural mandate), plus §21.5 (which recommends every project claiming conformance to the spec ship a `sync-oss-spec` skill).

`OSS_SPEC.md` is the specification this repository claims to conform to. This skill brings the repository back into conformance whenever the spec moves or the repo drifts. It is fully standalone: it fetches the canonical spec from GitHub, walks the mandates by hand, and fixes each gap it finds on disk. **Do not depend on any external validator binary** — generated projects that do not ship the `oss-spec` CLI must still be able to run this skill end-to-end.

## Tracking mechanism

`.agent/skills/sync-oss-spec/.last-updated` contains the git commit hash of the last successful run. Empty means "never run" — use the repo's initial commit (`git rev-list --max-parents=0 HEAD`) as the baseline.

## Fetch the canonical spec

The upstream source of truth is the `main` branch of `niclaslindstedt/oss-spec`. Pull it into a scratch file at the start of every run:

```sh
SPEC_URL="https://raw.githubusercontent.com/niclaslindstedt/oss-spec/main/OSS_SPEC.md"
SPEC_TMP="$(mktemp -t oss-spec.XXXXXX.md)"
curl -fsSL "$SPEC_URL" -o "$SPEC_TMP"
```

If `curl` is unavailable, fall back to `wget -qO "$SPEC_TMP" "$SPEC_URL"`. Never proceed with a stale local copy — a failed fetch is a hard stop, not a silent skip.

Record the upstream spec version so every downstream decision is made against a known target:

```sh
SPEC_VERSION=$(awk '/^version:/ {print $2; exit}' "$SPEC_TMP")
echo "upstream OSS_SPEC.md version: $SPEC_VERSION"
```

Compare the fetched copy against the local one (if any) and overwrite on drift:

```sh
if [ -f OSS_SPEC.md ]; then
diff -u OSS_SPEC.md "$SPEC_TMP" || cp "$SPEC_TMP" OSS_SPEC.md
else
cp "$SPEC_TMP" OSS_SPEC.md
fi
```

## Discovery process

1. Read the baseline and list every commit that may have introduced drift since then:

```sh
BASELINE=$(cat .agent/skills/sync-oss-spec/.last-updated)
git log --oneline "$BASELINE"..HEAD
git diff --name-only "$BASELINE"..HEAD
```

2. Walk the **structural mandates** in the freshly-fetched spec (`$SPEC_TMP`) and assert each on disk. The checks below mirror every §19 conformance rule in the spec. Run each one and record failures — any output means a violation.

```sh
# §2/§3/§4/§5/§6/§7/§8.4/§9/§19 — required root files
for f in LICENSE README.md CONTRIBUTING.md CODE_OF_CONDUCT.md SECURITY.md \
AGENTS.md CHANGELOG.md Makefile .gitignore .editorconfig; do
[ -e "$f" ] || echo "MISSING: $f"
done

# §7.1 — AGENTS.md symlinks
for link in CLAUDE.md .cursorrules .windsurfrules GEMINI.md \
.github/copilot-instructions.md; do
[ -L "$link" ] || echo "NOT-A-SYMLINK: $link (must point to AGENTS.md)"
done

# §10/§11/§13.5/§15 — required directories
for d in .github/workflows .github/ISSUE_TEMPLATE docs prompts scripts; do
[ -d "$d" ] || echo "MISSING-DIR: $d"
done

# §10.1/§10.3/§10.4 — required workflows
for w in ci.yml version-bump.yml release.yml pages.yml; do
[ -f ".github/workflows/$w" ] || echo "MISSING-WORKFLOW: $w"
done

# §10.3 — no floating toolchain specifiers in CI workflows
grep -nE '(rust-toolchain@|(python|node|go)-version:)[^\n]*\b(stable|latest|lts|\*)\b' \
.github/workflows/ci.yml .github/workflows/release.yml 2>/dev/null

# §10.5 — local pin file matches CI. Presence-only check; cross-check
# values by eye against ci.yml.
[ -f Cargo.toml ] && { [ -f rust-toolchain.toml ] || echo "MISSING: rust-toolchain.toml"; }
[ -f pyproject.toml ] || [ -f setup.py ] && { [ -f .python-version ] || echo "MISSING: .python-version"; }
[ -f package.json ] && { [ -f .nvmrc ] || echo "MISSING: .nvmrc"; }
[ -f go.mod ] && { grep -q '^toolchain ' go.mod || echo "MISSING: go.mod toolchain directive"; }

# §13.5 — every prompts/<name>/ must have a versioned <major>_<minor>_<patch>.md
for d in prompts/*/; do
[ -d "$d" ] || continue
ls "$d" | grep -qE '^[0-9]+_[0-9]+_[0-9]+\.md$' \
|| echo "UNVERSIONED-PROMPT: $d"
done

# §15 — issue + PR templates
for f in .github/PULL_REQUEST_TEMPLATE.md \
.github/ISSUE_TEMPLATE/bug_report.md \
.github/ISSUE_TEMPLATE/feature_request.md \
.github/ISSUE_TEMPLATE/config.yml \
.github/dependabot.yml; do
[ -f "$f" ] || echo "MISSING: $f"
done

# §19.4 — central output module (only if the repo has src/ or lib/)
if [ -d src ] || [ -d lib ]; then
ls src/output.* lib/output.* src/output/ lib/output/ internal/output/ 2>/dev/null \
| head -1 | grep -q . || echo "MISSING: central output module (§19.4)"
fi

# §20.2 — every tests/*.<ext> stem must end with _test(s) or Test(s)
if [ -d tests ]; then
find tests -maxdepth 1 -type f \
| grep -vE '(_test(s)?|Test(s)?)\.[^/]+$' \
| sed 's/^/BAD-TEST-NAME: /'
fi

# §21 — agent skills tree
[ -d .agent/skills ] || echo "MISSING-DIR: .agent/skills"
[ "$(readlink .claude/skills)" = "../.agent/skills" ] \
|| echo "BAD-SYMLINK: .claude/skills -> ../.agent/skills"
for d in .agent/skills/*/; do
[ -f "$d/SKILL.md" ] || echo "MISSING: $d/SKILL.md"
[ -f "$d/.last-updated" ] || echo "MISSING: $d/.last-updated"
done
```

3. For each failure, re-read the relevant section of `$SPEC_TMP` so the fix matches the spec's intent rather than silencing the symptom:

```sh
# Jump to a section, e.g. §21, in the fetched spec.
awk '/^## 21\. /,/^## 22\. /' "$SPEC_TMP"
```

## Mapping table

| Violation spec section | Where to fix it |
|---|---|
| §2 missing `LICENSE` | Create `LICENSE` with the SPDX-identified license text and the correct copyright holder |
| §3 missing `README.md` sections | Edit `README.md`; hand off to `update-readme` if extensive rewording is needed |
| §4/§5/§6 missing `CONTRIBUTING.md` / `CODE_OF_CONDUCT.md` / `SECURITY.md` | Create the file with the minimum content mandated by the corresponding spec section |
| §7.1 tool-specific guidance file is not a symlink | Replace the regular file with `ln -s AGENTS.md <path>` (or `ln -s ../AGENTS.md .github/copilot-instructions.md`) |
| §8.4 missing `CHANGELOG.md` | Create an empty Keep-a-Changelog-formatted file; do **not** hand-author entries |
| §9 Makefile target missing | Add the missing target to `Makefile` and verify it runs end-to-end |
| §10.1/§10.3/§10.4 missing workflow | Create `.github/workflows/<file>.yml` |
| §10.3 floating or under-pinned toolchain | Edit the workflow to pin at or above the minimums declared in the fetched `OSS_SPEC.md` §10.3 table |
| §10.5 missing pin file / pin ↔ CI mismatch | Add the language's repo-root pin (`rust-toolchain.toml`, `.python-version`, `.nvmrc`, or `go.mod` `toolchain` directive) and align it with `ci.yml` |
| §11.1 missing `docs/` content | Create the topic file, then hand off to `update-docs` |
| §11.2 website drift | Regenerate website sources, hand off to `update-website` |
| §13.5 `prompts/<name>/` has no versioned file | Add `prompts/<name>/1_0_0.md` with the required YAML front matter (`name`, `description`, `version: 1.0.0`) and `## System` / `## User` sections |
| §15 missing issue / PR templates | Create the templates under `.github/ISSUE_TEMPLATE/` or `.github/PULL_REQUEST_TEMPLATE.md` |
| §19.4 missing central output module | Add `src/output.<ext>` (or `lib/output.<ext>`) with semantic helpers (`status`, `info`, `warn`, `error`, `header`) and route existing prints through it |
| §20.2 test file stem does not end with `_test(s)` / `Test(s)` | Rename the file so the stem matches the regex `_?[Tt]ests?$` |
| §21.2 `.claude/skills` is not a symlink | Replace it with `ln -s ../.agent/skills .claude/skills` |
| §21.3 SKILL.md missing front matter fields | Add `name:` / `description:` to the front matter |
| §21.4 missing `.last-updated` | `git rev-parse HEAD > .agent/skills/<skill>/.last-updated` |
| §21.5 missing required `update-*` skill | Create `.agent/skills/<skill>/SKILL.md` (+ `.last-updated`); register it in `maintenance/SKILL.md` |
| §21.6 `maintenance` skill registry row missing | Add the row in `maintenance/SKILL.md`, alphabetical, with a run-order slot |

## Update checklist

- [ ] Fetch `$SPEC_URL` into `$SPEC_TMP`; abort on failure
- [ ] Compare `$SPEC_TMP` with local `OSS_SPEC.md`; overwrite the local copy on drift
- [ ] Read the baseline from `.last-updated` and diff the working tree
- [ ] Walk every structural check in "Discovery process" step 2 and collect failures
- [ ] For each failure, read the matching section of `$SPEC_TMP` and apply the fix
- [ ] Re-run every shell check from step 2 — it must produce no output
- [ ] Run `make fmt`, `make lint`, `make test`
- [ ] Write the new baseline:

git rev-parse HEAD > .agent/skills/sync-oss-spec/.last-updated

## Verification

1. Every shell check in "Discovery process" step 2 prints nothing.
2. `diff OSS_SPEC.md "$SPEC_TMP"` is empty.
3. `make test` passes.
4. Every failure seen before this run has a matching edit in the diff — no violation was silenced by loosening a check.
5. `.last-updated` was rewritten with the current `HEAD`.

## Skill self-improvement

After a run, extend this file:

1. **Grow the mapping table** whenever a new §X.Y section starts producing violations that the table does not yet cover.
2. **Extend the step-2 shell checks** whenever a new mandate lands upstream — the checks must stay a faithful, binary-free mirror of the spec's structural rules.
3. **Record fix recipes** (exact commands or edit patterns) for violations that required more than a one-line change.
4. **Flag recurring drift** — if the same violation keeps coming back, either a CI check or a different skill's mapping table is missing a row. Fix the upstream cause, not just the symptom.
5. **Commit the skill edit** alongside the repo fixes so the knowledge compounds.
2 changes: 2 additions & 0 deletions templates/_common/.agent/skills/update-docs/SKILL.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ description: "Use when files under docs/ may be stale. Discovers commits since t

# Updating the Docs

**Governing spec sections:** §11.1 (`docs/` directory — the required conceptual docs tree), §21.5 (this skill is mandated because `docs/` is a drift-prone artifact in every project).

The `docs/` directory contains conceptual documentation for {{ name }}. Unlike the README (overview) or man pages (command reference), `docs/` explains *why* and *how* in depth. It goes stale whenever a user-visible behavior, configuration key, or supported surface changes without a matching edit.

## Tracking mechanism
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ description: "Use when LLM prompts under prompts/ may be stale. Discovers change

# Updating the LLM prompts

**Governing spec sections:** §13.5 (LLM prompts — versioned `prompts/<name>/<major>_<minor>_<patch>.md` files with required YAML front matter), §21.5 (this skill is mandated because `prompts/` is a drift-prone artifact whenever a project ships LLM-driven behaviour).

Every LLM-driven step in {{ name }} is defined by a versioned prompt under `prompts/<name>/<major>_<minor>_<patch>.md` with a required YAML front matter block (`name`, `description`, `version`) — see §13.5 of `OSS_SPEC.md`. Prompt files are **immutable once committed**: every change lands as a new file at a new semver (patch for wording, minor for additive changes, major for breaking rewrites). Prompts drift whenever the code that renders them, the sources of truth they embed, or the section numbering they reference changes.

## Tracking mechanism
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ description: "Use when README.md may be stale. Discovers commits since the last

# Updating the README

`README.md` is the primary user-facing documentation for {{ name }}. It covers installation, quick start, the feature list, and any user-visible defaults. It goes stale whenever a CLI flag, subcommand, default, or supported surface changes without a matching edit.
**Governing spec sections:** §3 (`README.md` — required sections and content), §21.5 (this skill is mandated because `README.md` is a drift-prone artifact).

`README.md` is the primary user-facing documentation for {{ name }}. Per §3 of `OSS_SPEC.md` it must cover the project description, installation, a quick-start, usage, contribution pointer, license, and a link to `OSS_SPEC.md`. It goes stale whenever a CLI flag, subcommand, default, or supported surface changes without a matching edit.

## Tracking mechanism

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ description: "Use when the marketing website may be stale. Discovers commits sin

# Updating the Website

**Governing spec sections:** §11.2 (`website/` — source-derived content, no double-authoring, staleness CI check), §21.5 (this skill is mandated when the project publishes a website).

The `website/` directory contains the marketing site for `{{ name }}`. Per §11.2 of `OSS_SPEC.md`, its source-derived content (hero copy, feature lists, version strings) must not be authored twice — it is extracted from `README.md`, `docs/`, and `OSS_SPEC.md`, then rendered by the website build.

## Tracking mechanism
Expand Down
2 changes: 2 additions & 0 deletions templates/cli/.agent/skills/update-manpages/SKILL.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ description: "Use when files under man/ may be stale. Discovers commits since th

# Updating the Manpages

**Governing spec sections:** §12.3 (`docs` and `man` commands — every CLI subcommand must have a `man/<cmd>.md` page exposed through `<project> man <cmd>`), §12.5 (discoverability contract), §21.5 (this skill is mandated because `man/` is a drift-prone artifact in every CLI project).

`man/` contains the reference-style command documentation shipped with {{ name }} — one markdown file per command. These pages are the authoritative command-level reference and rot whenever a flag, subcommand, or default changes without a matching edit.

## Tracking mechanism
Expand Down