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
5 changes: 3 additions & 2 deletions .agent/skills/maintenance/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ The registry is the single source of truth for which sync skills exist in this r
| `update-manpages` | `man/oss-spec.md` vs. `src/cli.rs` clap definitions | 2 |
| `update-docs` | `docs/*.md` vs. source of truth | 3 |
| `update-readme` | `README.md` vs. CLI, spec, and supported languages | 4 |
| `update-website` | `website/` vs. `README.md`, `docs/`, and `OSS_SPEC.md` | 5 |
| `sync-oss-spec` | Repo contents vs. `OSS_SPEC.md` (runs `oss-spec validate .`) | 6 — run last, it verifies that every upstream fix landed correctly |
| `update-prompts` | `prompts/**` vs. `OSS_SPEC.md`, validator, manifest enums, ai glue | 5 |
| `update-website` | `website/` vs. `README.md`, `docs/`, and `OSS_SPEC.md` | 6 |
| `sync-oss-spec` | Repo contents vs. `OSS_SPEC.md` (runs `oss-spec validate .`) | 7 — run last, it verifies that every upstream fix landed correctly |

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

Expand Down
2 changes: 1 addition & 1 deletion .agent/skills/sync-oss-spec/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ This skill is complementary to `update-spec`. `update-spec` propagates a spec ed
| §10.3 floating or under-pinned toolchain | Edit the workflow to pin at or above the spec minimums in `MIN_TOOLCHAIN_VERSIONS` (`validate.rs`) |
| §11.1 missing `docs/` content | Create the topic file, then run `update-docs` |
| §11.2 website drift | Run `make website` and inspect `website/src/generated/`; follow up with `update-website` |
| §13.5 `prompts/<name>/` has no versioned file | Add `prompts/<name>/1_0.md` with the required `## System` / `## User` sections |
| §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 raw print statement outside `src/output.rs` | Route the call through `output::status` / `output::info` / `output::warn` / `output::error` |
| §20 inline `#[cfg(test)] mod { … }` block in `src/` | Move the tests to `tests/<module>_test.rs` and replace with `#[cfg(test)] mod <name>_test;` or delete the gate |
Expand Down
Empty file.
87 changes: 87 additions & 0 deletions .agent/skills/update-prompts/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
name: update-prompts
description: "Use when prompts under prompts/ may be stale. Discovers changes to OSS_SPEC.md, the validator, manifest enums, and the ai/fix glue since the last run, and rewrites the affected prompt templates so they stay aligned with their sources of truth."
---

# Updating the LLM prompts

Every LLM-driven step in this CLI 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 version. Prompts drift whenever:

- `OSS_SPEC.md` changes — `verify-conformance` embeds the full spec and `fix-conformance` references section numbers, so any spec edit may invalidate them.
- `src/validate.rs` grows a new structural rule — the fix agent needs new guidance to handle the new violation shape.
- `src/ai.rs` or `src/fix.rs` change the rendering context — new Jinja placeholders may appear or disappear.
- `src/manifest.rs` gains or removes a `Language` / `Kind` / `License` enum variant — the `interpret-prompt` JSON schema must track it.

This skill exists so that drift between prompt text and the rest of the codebase is caught by the same `maintenance` sweep that keeps `README.md`, `docs/`, `man/`, and `website/` in sync.

## Tracking mechanism

`.agent/skills/update-prompts/.last-updated` contains the git commit hash from the last successful run. Empty means "never run" — fall back to the initial commit.

## Discovery process

1. Read the baseline:

```sh
BASELINE=$(cat .agent/skills/update-prompts/.last-updated)
```

2. Enumerate every prompt file and note its current version:

```sh
find prompts -name '[0-9]*_[0-9]*.md' | sort
```

3. Diff the watched paths against the baseline:

```sh
git diff --name-only "$BASELINE"..HEAD -- \
OSS_SPEC.md src/ai.rs src/fix.rs src/validate.rs src/manifest.rs prompts/
```

4. For each path that appears in the diff, walk the mapping table below and decide which prompts are now stale.

## Mapping table

| Source-of-truth change | Prompt(s) to audit | What to check |
|---|---|---|
| `OSS_SPEC.md` body (any `§N` edit) | `prompts/verify-conformance/*.md` | Embedded checklist — make sure every new or changed mandate is represented. |
| `OSS_SPEC.md` body (any `§N` edit) | `prompts/fix-conformance/*.md` | Per-section guidance block — add or amend bullets so the agent knows how to fix the new rule. |
| `OSS_SPEC.md` version field | all prompts that render `{{ spec_version }}` | Nothing to edit — version is pulled from `embedded::oss_spec_version()` at render time. Verify the placeholder is still referenced. |
| New check in `src/validate.rs` (new `Violation` producer) | `prompts/fix-conformance/*.md` | Add handling guidance; if the check is AI-only, make sure it is mentioned as a quality finding category. |
| New placeholder added in `src/ai.rs` `context! { ... }` | the matching prompt's `## User` section | Reference the new placeholder; re-render to confirm no leftover `{{ unused }}` tokens. |
| New `Language` / `Kind` / `License` variant in `src/manifest.rs` | `prompts/interpret-prompt/*.md` | Update the JSON schema `enum` list embedded in the prompt. |
| New versioned prompt added under `prompts/<name>/<major>_<minor>_<patch>.md` | `src/ai.rs` / `src/fix.rs` callers | Confirm the caller loads by name (not a pinned version) so the new file is auto-picked; if a caller pins a specific version, bump it. |

## Update checklist

- [ ] Read the baseline from `.last-updated`
- [ ] Run the `git diff --name-only` above; bail out if nothing watched changed
- [ ] **Never edit an existing `<major>_<minor>_<patch>.md` file** (§13.5). Every change — typo to rewrite — lands as a new file. Decide the semver bump:
- **patch** (`1_0_0` → `1_0_1`): wording / typo / clarification, contract unchanged
- **minor** (`1_0_0` → `1_1_0`): new placeholder, expanded scope, new guidance
- **major** (`1_0_0` → `2_0_0`): breaking rewrite, removed placeholder, changed JSON schema
- [ ] Copy the latest version to the new filename, then edit; keep every prior version on disk for diff/bisect
- [ ] Update the YAML front matter in the new file: `version: <major>.<minor>.<patch>` must match the stem
- [ ] Update any callers in `src/ai.rs` or `src/fix.rs` that pin a specific prompt version
- [ ] Re-run `cargo test` — `prompts_test.rs` must still load every prompt
- [ ] Run `make fmt`, `make lint`, `make test`
- [ ] Run `oss-spec validate .` — the self-conformance check exercises §13.5 prompt layout
- [ ] Write the new baseline:

git rev-parse HEAD > .agent/skills/update-prompts/.last-updated

## Verification

1. Every prompt that references a `{{ placeholder }}` must have a matching key in its caller's `context! { ... }` in `src/ai.rs`.
2. Every placeholder a caller passes must be referenced at least once by the rendered prompt.
3. `cargo test` passes — this covers prompt loading, rendering, and the self-conformance test.
4. `.last-updated` has been rewritten with the current `HEAD`.

## Skill self-improvement

After a run, edit this file in place:

1. **Grow the mapping table** with any new source → prompt path you discovered.
2. **Record drift signals** — if a prompt went stale through a path not captured above, add the path.
3. **Commit the skill edit** together with the prompt edits so the knowledge compounds.
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ When you change… | Update…
A CLI flag or subcommand | `man/oss-spec.md`, `docs/agent/help-agent.txt`, `agent_help::COMMANDS_TABLE`, `agent_help::COMMAND_SPECS`, `README.md` Usage table
A template file | `templates/_common/` (or overlay) — and re-run `oss-spec validate` against a generated demo
A §19 rule | `src/validate.rs`, `OSS_SPEC.md`, this `## Documentation sync points` table
A toolchain version bump (Rust / Python / Node / Go) | the repo-root pin file (`rust-toolchain.toml`, `.python-version`, `.nvmrc`, or `go.mod`'s `toolchain` directive), its `templates/<lang>/` counterpart, `templates/_common/.github/workflows/ci.yml.tmpl`, and `MIN_TOOLCHAIN_VERSIONS` in `src/validate.rs` (§10.5 local/CI parity)
A toolchain version bump (Rust / Python / Node / Go) | the repo-root pin file (`rust-toolchain.toml`, `.python-version`, `.nvmrc`, or `go.mod`'s `toolchain` directive), its `templates/<lang>/` counterpart, `templates/_common/.github/workflows/ci.yml.tmpl`, and `MIN_TOOLCHAIN_VERSIONS` in `src/validate.rs` (§10.5 local/CI parity, §10.3 minimums)
An LLM prompt's source of truth (spec text, validator rule, manifest enum, rendering-context key) | A new file under `prompts/<name>/<major>_<minor>_<patch>.md` (never edit an existing versioned file — bump semver and create a new one per §13.5). Run the `update-prompts` skill or let the `maintenance` sweep pick it up.
The list of supported languages | `manifest::Language`, `templates/<lang>/`, `Makefile.tmpl`, `ci.yml.tmpl`, `dependabot.yml.tmpl`
`OSS_SPEC.md` | Bump the `version` field in its YAML front matter (semver — `feat!`/breaking bumps major, `feat` or new mandate bumps minor, pure clarifications bump patch). Also update `README.md`, `docs/`, `templates/_common/AGENTS.md.tmpl`, and this file as needed. The spec is mirrored into generated projects via the symlink `templates/_common/OSS_SPEC.md -> ../../OSS_SPEC.md`, so there is only one source of truth.

Expand Down Expand Up @@ -115,6 +116,7 @@ Per §21 of `OSS_SPEC.md`, this repo ships agent skills for keeping drift-prone
| `update-manpages` | Whenever `src/cli.rs` clap definitions change | `man/oss-spec.md` |
| `update-docs` | Whenever user-visible behavior described in `docs/` changes | `docs/*.md` |
| `update-readme` | Whenever a CLI flag, subcommand, §19 rule, supported language, or the spec version changes | `README.md` |
| `update-prompts` | Whenever `OSS_SPEC.md`, `src/validate.rs`, `src/ai.rs`, `src/fix.rs`, or `src/manifest.rs` changes in a way that could leave a prompt template stale | `prompts/**/*.md` |
| `update-website` | Whenever a source-derived section of the website (hero, version, CLI table) drifts from README / docs / spec | `website/` |
| `sync-oss-spec` | Whenever `oss-spec validate .` reports violations, or after a spec bump — brings repo contents back into conformance with `OSS_SPEC.md` | repo-wide §19 conformance |
| `commit` | After any feature or fix, to run quality gates, commit, push, and open/update the PR | — |
Expand Down
60 changes: 42 additions & 18 deletions OSS_SPEC.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Open Source Project Bootstrap Specification
description: A prescriptive, language-agnostic specification for bootstrapping a new open source project with the licensing, documentation, automation, governance, and release plumbing that users and contributors expect from a well-run OSS codebase.
version: 2.1.0
version: 2.2.0
---

# Open Source Project Bootstrap Specification
Expand Down Expand Up @@ -1092,24 +1092,46 @@ version inside it:
```
prompts/
├── interpret-prompt/
│ ├── 1_0.md
│ └── 1_1.md
│ ├── 1_0_0.md
│ └── 1_1_0.md
├── fix-conformance/
│ └── 1_0.md
│ ├── 1_0_0.md
│ └── 1_1_0.md
└── …
```

**File name.** `<major>_<minor>.md`. The version number is bumped on
every meaningful change to the prompt: `1_0` → `1_1` for an in-place
edit, `1_x` → `2_0` for a breaking rewrite. Old versions are kept on
disk so behavior changes can be diffed and bisected. Loaders must
always pick the highest version of a prompt unless explicitly pinned.

**File content.** Each prompt file is plain Markdown with two required
section headings, in this order:
**File name.** `<major>_<minor>_<patch>.md`, matching [semver]
(https://semver.org/). Bump **patch** for wording fixes that do not
change the contract (typos, clarifications). Bump **minor** for
non-breaking additions (new placeholders, expanded scope, new
guidance bullets). Bump **major** for breaking rewrites (removed
placeholders, changed JSON schema, fundamentally new task). Loaders
must always pick the highest version of a prompt unless explicitly
pinned.

**Never edit an existing versioned file.** Once a `<major>_<minor>_
<patch>.md` file is committed, its contents are immutable — every
change, no matter how small, lands as a new file at a new version.
This keeps every prompt a point-in-time artifact that can be diffed,
bisected, and blamed. The only time you may edit an existing file is
to correct a bug *before* it has ever been shipped or referenced from
a tagged release.

**Required YAML front matter.** Every prompt file must begin with a
YAML front-matter block declaring the prompt's `name`, `description`,
and `version`. The `version` value must match the filename stem
(e.g. `1_0_0.md` → `version: 1.0.0`). Loaders must strip the front
matter before passing the prompt to the model — it is metadata, not
instruction content.

```markdown
# <prompt-name> — v<major>.<minor>
---
name: <prompt-name>
description: "<one-sentence description of what this prompt does>"
version: <major>.<minor>.<patch>
---

# <prompt-name>

## System

Expand All @@ -1124,9 +1146,9 @@ loader renders with runtime values…
The `## System` section is sent verbatim as the system prompt. The
`## User` section is rendered with whatever templating engine the
project already uses (this repo uses minijinja) and sent as the user
message. Anything outside those two sections (the `# Title` line,
notes, examples) is ignored by the loader and is purely for humans
reading the file.
message. The YAML front matter, the `# Title` heading, and any other
prose outside the two required sections are ignored by the loader and
exist purely for humans reading the file.

**Why.** Inline prompts are invisible to reviewers, impossible to diff
across versions without reading source, and indistinguishable from
Expand Down Expand Up @@ -1577,8 +1599,10 @@ checked before the first public tag.
[ ] pages workflow deploys website on every main push (§10.4, §11.2)
[ ] Website staleness CI check (§11.2)
[ ] examples/ (if applicable) exercised by CI (§13)
[ ] prompts/<name>/<major>_<minor>.md for every LLM
prompt the project sends (if applicable) (§13.5)
[ ] prompts/<name>/<major>_<minor>_<patch>.md for every
LLM prompt the project sends (if applicable) (§13.5)
[ ] Every prompt has YAML front matter with name,
description, and version fields matching the stem (§13.5)
[ ] Dependabot / Renovate configured (§14)
[ ] Secret scanning enabled (§14)
[ ] CI actions pinned by SHA (§14)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![release](https://github.com/niclaslindstedt/oss-spec/actions/workflows/release.yml/badge.svg)](https://github.com/niclaslindstedt/oss-spec/actions/workflows/release.yml)
[![pages](https://github.com/niclaslindstedt/oss-spec/actions/workflows/pages.yml/badge.svg)](https://github.com/niclaslindstedt/oss-spec/actions/workflows/pages.yml)
[![crates](https://img.shields.io/crates/v/oss-spec.svg)](https://crates.io/crates/oss-spec)
[![spec](https://img.shields.io/badge/OSS__SPEC-v2.0.2-blueviolet)](OSS_SPEC.md)
[![spec](https://img.shields.io/badge/OSS__SPEC-v2.2.0-blueviolet)](OSS_SPEC.md)
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

## Why?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# draft-readme-why — v1.0
---
name: draft-readme-why
description: "Draft 3-5 concrete 'Why?' bullets for the README of a newly bootstrapped project."
version: 1.0.0
---

# draft-readme-why

## System

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# file-conformance-issues — v1.0
---
name: file-conformance-issues
description: "Drive a zag agent loop that files one grouped GitHub issue per OSS_SPEC.md violation cluster via the gh CLI."
version: 1.0.0
---

# file-conformance-issues

## System

Expand Down
39 changes: 39 additions & 0 deletions prompts/file-conformance-issues/1_0_1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
name: file-conformance-issues
description: "Drive a zag agent loop that files one grouped GitHub issue per OSS_SPEC.md violation cluster via the gh CLI. Preamble echoes the target spec version."
version: 1.0.1
---

# file-conformance-issues

## System

You are a repository triage agent. Your job is to file GitHub issues for
the listed `OSS_SPEC.md` violations using the `gh` CLI in the current
working directory.

Each issue must have:

1. A clear title that names the missing artifact.
2. A body that cites the spec section, explains why the rule exists, and
lists concrete acceptance criteria.
3. The label `oss-spec`. If the label does not yet exist in the repo,
create it with `gh label create oss-spec --color BFD4F2 --description "OSS_SPEC.md conformance" --force`.

Group obviously-related violations (e.g. all four CI workflow files) into
a single issue when it makes sense — one issue per *cluster*, not
necessarily one per line.

Do **not** modify any source files. When done, print the URLs of the
issues you filed.

## User

Target spec: **OSS_SPEC.md v{{ spec_version }}**.

Detected violations:

{{violations}}

For each cluster, run `gh issue create` in this repo. Stop after every
violation has either an issue or is part of a grouped issue.
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# fix-conformance — v1.0
---
name: fix-conformance
description: "Drive a zag agent loop that brings an existing repo into OSS_SPEC.md conformance by resolving a list of detected structural violations."
version: 1.0.0
---

# fix-conformance

## System

Expand Down
Loading