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
37 changes: 11 additions & 26 deletions .agents/skills/bepinex-mono-mod-quality-check/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ Apply `prose-quality-check` only after ownership and technical evidence are sett
into reusable domain knowledge, and do not treat a well-structured document as proof that its game or release claim is
correct.

Use `github-actions-quality-check` for the shared event, trust, permission, concurrency, runner, action-pin,
artifact-lineage, and repository-enforcement baseline. This Skill owns only the BepInEx/.NET/Thunderstore commands,
release identity, package contract, and domain-specific templates layered on that baseline.

Use `unity-game-analyze` to establish version-specific game-code and serialized-asset evidence: the concrete call path,
effective prefab/scene values, object/load reachability, lifecycle timing, authority, and unresolved runtime inputs.
This Skill consumes that evidence to select and verify hooks, adapters, identity mappings, compatibility claims, and
Expand All @@ -59,15 +63,9 @@ namespace; they do not replace this Skill's quality bar.
- For C# changes, require locked restore, format verification without restore, and a no-restore build. For Markdown,
workflow, shell, APM, package, or release changes, apply the corresponding checks in
[repository-quality-template.md](references/repository-quality-template.md).
- Use event-owned CI entry workflows: pull requests (and merge queues when used) validate proposed source with a `lint`
job (and a `test` job when the repository has tests), while the integration branch re-runs those jobs on its exact
commit and directly gates `build`, retained edge artifacts, and `release` through `needs`. Keep `lint-source` as a
Composite Action name, not a catch-all job name. When version or publication state must be resolved, use a read-only
`plan` job and make `build` depend directly on `lint`, optional `test`, and `plan`; have `release` consume the
verified build artifact and any needed plan output. Here, read-only means that planning does not modify tracked
source/package files, tags, releases, or other GitHub state and has no write-capable token. It may fetch remote refs
needed to classify the current version. Do not add manual dispatch or polling jobs without a documented
operator/recovery need.
- Apply the event-owned workflow, direct-job-graph, read-only planning, permission, concurrency, and artifact-lineage
rules from `github-actions-quality-check`. This Skill supplies the BepInEx-specific source gate, release identity,
archive, edge-build, and Thunderstore extensions.
- When the target adopts a bundled CI or publishing contract, copy its files exactly from this Skill's canonical
`assets/` and verify them from the installed Skill during authoring and review. Consumer CI must run only committed
repository-owned actions and scripts; it must not execute `.agents/skills/` or require this Skill at workflow
Expand Down Expand Up @@ -282,20 +280,10 @@ conditional branches, verification matrix, and report format. Do not replace tha
or result. A generic exception or nonzero exit does not prove the advertised rejection branch.
- When the project derives manifest or package versions in CI, verify that the project version, generated version,
and loader-compatible version are deliberately handled for stable, prerelease, and edge builds.
6. Check GitHub repository settings, CI, and release automation when the repository uses GitHub Actions or GitHub
Releases.
- Require the repository or organization Actions setting that enforces full-length commit-SHA pins. Independently
verify every third-party `uses:` reference has a full commit SHA and an accurate version comment; inspect reusable
workflows, container digests, and downloaded-tool checksums too.
- When the repository publishes GitHub Releases, require repository-level immutable releases where GitHub makes the
setting available. Automation must attach every asset before publishing the release and must fail rather than
replace an existing tag, release, or asset. If the setting is unavailable, record the residual risk and require an
explicit fail-on-existing-release/tag/asset path instead of silently treating releases as immutable.
6. Check BepInEx release automation when the repository uses GitHub Actions or GitHub Releases. Apply
`github-actions-quality-check` for the shared workflow and repository-enforcement baseline.
- Keep checksum material used to verify the build-to-release handoff inside the workflow artifact by default.
Publish only the package archive unless the repository has an explicit user-facing checksum-asset contract.
- Trace one release from its source commit through locked restore, build, archived artifact, and release asset.
Publish only the artifact produced by that build; do not rebuild a separately checked-out revision in the release
job. Create and verify an artifact digest across the build and release jobs.
- Install the exact SDK selected by `global.json` in CI with a full-SHA-pinned setup action or another pinned,
verified mechanism before restore. Do not assume a hosted runner already contains the release-critical SDK.
- Separate validation artifacts, prereleases, and stable publishing according to the repository's version rules. Gate
Expand All @@ -310,16 +298,13 @@ conditional branches, verification matrix, and report format. Do not replace tha
- Keep archive creation CI-owned. A locally callable validator is useful, but a second repository-local production
packager, `release/` helper tree, or custom approval schema needs a distinct consumer and lifecycle. Never remove the
stable release path while consolidating packaging ownership.
- Default workflow permissions to read-only. Scope `contents: write` and publishing secrets to the release job that
needs them, and never expose a publish credential to pull-request validation.
7. Run the narrowest relevant checks, then widen for the changed surface.
- For C# or project changes, run locked restore, format verification, and no-restore build. Run the documented tests
when automated tests are present or changed. Use the solution or project path required by the repository layout.
- For documentation or package text, run Markdown lint over every committed Markdown file using the checked-in
configuration.
- For workflows, composite actions, or shell scripts, run ShellCheck, `actionlint`, and
`pinact run --check --min-age 7`; check full-SHA action pins, container digests, downloaded-tool checksums,
permissions, concurrency, and secret scope.
- For workflows, composite actions, or shell scripts, apply the automated and AI-assisted validation scopes from
`github-actions-quality-check`, then run the BepInEx/.NET/package checks enabled by this Skill.
- Reconcile declared tooling with execution. Every committed lint/check configuration and every command promised in
README or CONTRIBUTING must have a runnable documented command and an enabled CI invocation, or be removed with the
documented reason.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Generate Version
name: Generate BepInEx version
description: "Generate application and git version based on csproj version and git tags."

inputs:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Lint source
name: Lint BepInEx source
description: Run the repository's workflow, C#, and Markdown source checks.

runs:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Publish Thunderstore Package
name: Publish Thunderstore package
description: Upload and submit a prebuilt Thunderstore package zip.

inputs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,25 @@ defaults:
shell: bash

jobs:
lint:
# A merged commit is validated again in this workflow. This direct
# dependency is the release gate; do not replace it with workflow polling.
# A merged commit is validated again in this workflow. This direct
# dependency is the release gate; do not replace it with workflow polling.
checks:
name: Checks
runs-on: ubuntu-slim

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check out integrated source
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- uses: ./.github/actions/lint-source
- name: Run BepInEx source gate
uses: ./.github/actions/lint-source

# Resolve one release identity before build mutates package source files.
# Keep planning read-only so edge metadata remains reusable by its consumers.
plan:
# Resolve one release identity before build mutates package source files.
# Keep planning read-only so edge metadata remains reusable by its consumers.
name: Plan
runs-on: ubuntu-slim

outputs:
Expand All @@ -41,7 +45,8 @@ jobs:
manifest_version: ${{ steps.generate-version.outputs.manifest_version }}

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check out integrated source with tags
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
Expand All @@ -54,8 +59,9 @@ jobs:
write_files: false

build:
name: Build
needs:
- lint
- checks
- plan
# Build keeps ubuntu-latest because packaging currently relies on
# runner-provided shell tools such as jq and 7z.
Expand All @@ -70,7 +76,8 @@ jobs:
steps:
# Checkout is required before generating versions because the local
# composite action reads project files and fetches tags from this clone.
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check out integrated source
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Generate version
uses: ./.github/actions/generate-version
Expand All @@ -80,7 +87,7 @@ jobs:
app_version: ${{ needs.plan.outputs.app_version }}
manifest_version: ${{ needs.plan.outputs.manifest_version }}

- name: Setup .NET
- name: Set up .NET
# This shared action pins the SDK and restores the same locked graph
# used by source validation.
uses: ./.github/actions/setup-dotnet
Expand Down Expand Up @@ -182,6 +189,7 @@ jobs:
} >> "${GITHUB_STEP_SUMMARY}"

release:
name: Release
needs:
- build
- plan
Expand All @@ -201,7 +209,8 @@ jobs:
steps:
# Checkout is needed even though the package is downloaded, because the
# Thunderstore publisher is a repository-local composite action.
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check out release automation
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Download build artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ permissions:
contents: read

jobs:
lint:
# Keep proposed source validation separate from publishing privileges.
# Keep proposed source validation separate from publishing privileges.
checks:
name: Checks
runs-on: ubuntu-slim

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check out proposed source
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- uses: ./.github/actions/lint-source
- name: Run BepInEx source gate
uses: ./.github/actions/lint-source
Original file line number Diff line number Diff line change
Expand Up @@ -289,19 +289,10 @@ independent stages.
1. If APM is `yes`, preserve/create `apm.yml`, pin remote sources to full SHAs,
check provenance/license/last-changed-subdirectory cooldown, record third
party notices, then commit manifest, lockfile, and generated output together.
2. If GitHub Actions is `yes`, create/align event-owned entry workflows: `Pull
Request` for `pull_request` and `merge_group` when used; `Main` for the
protected integration-branch push. Both run the same lint gate on
their checked-out commit. `Main` uses direct `needs` dependencies to gate
read-only `plan`, build, artifact upload, and publication; never substitute
API polling or an `await-quality` job. `plan` owns the resolved version and
release state; build and release consume its outputs rather than resolving a
second identity. Run lint in this order: checkout; external-tool
setup and verification; ShellCheck; actionlint; pinact; SDK setup; locked
restore; format; no-restore build; tests; Markdown lint; archive validation
when relevant. Use read-only permissions, explicit Bash, and PR-only
cancellation concurrency. Add manual dispatch only for a documented
diagnostic or recovery operation.
2. If GitHub Actions is `yes`, apply `github-actions-quality-check` for entry
workflows, the direct job graph, planning, permissions, concurrency,
executable inputs, and validation tools. Extend that graph with this
repository's BepInEx/.NET source, archive, and publication contracts.
Read the SDK version from `global.json` and install it explicitly using a
full-SHA-pinned setup action or pinned verified equivalent before restore;
verify `dotnet --version` matches. Do not depend on runner inventory.
Expand All @@ -314,9 +305,8 @@ independent stages.
directory, or a repository-specific approval/evidence schema unless a named
consumer and distinct lifecycle require it. Consolidation must preserve the
stable release job and its verified artifact handoff.
3. Pin third-party actions by full SHA plus accurate version comment, containers
by digest, and downloaded executable tools by adjacent version and checksum.
Cache only verified archives and use committed lockfiles as NuGet cache keys.
3. Use committed lockfiles as NuGet cache keys. Do not cache restored package
directories or depend on ambient runner SDK state.
4. If GitHub Releases is `yes`, create a build job that creates one archive and
digest from the integration-branch commit, then uploads it for every build
including unpublished edge builds; publish only a downloaded-and-verified copy.
Expand Down Expand Up @@ -374,7 +364,7 @@ not passed; record the command, reason, and resulting risk.
| Identifier-dependent behavior | fixture where catalog/protocol index differs from stable domain ID | hash/persist/log/serialize result follows the contractually named identity |
| Lifecycle predicate change | positive-and-adjacent-negative truth table | every named positive passes; loading/departing/travelling/reset/unavailable negatives fail unless explicitly included |
| NuGet source/package/lock change | source/publisher/version/hash/license/transitive/age review | ledger records approval; mapping/locks cover every resolver |
| Workflow/action/shell change | ShellCheck, `actionlint`, `pinact run --check --min-age 7`, manual pin/permission/concurrency/secret review | all pass; every executable input is pinned/verified |
| Workflow/action/shell change | Complete `github-actions-quality-check` verification | shared automated and inspection checks pass; every executable input is verified |
| Bundled template adopted or changed | run `sync_templates.ps1 -Check` from the installed Skill during authoring with the repository's selected IDs in the canonical Skill and every opted-in consumer | every selected destination exists and satisfies its manifest comparison mode; exclusions and local variants are documented; consumer CI has no `.agents/skills/` runtime dependency |
| Lint/check config or contributor command | trace config to local command and enabled CI step | each retained config is consumed and every promised command is runnable in both documented and CI contexts |
| APM change | `apm lock`; lock review; `apm install --frozen`; `apm audit --ci` | expected refs/hashes and no drift |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,31 +89,16 @@ not automatic quality improvements.
## GitHub CI and release automation

For repositories that use GitHub Actions to build an archive and publish
releases, apply the following review baseline:

- Enable the repository or organization policy requiring GitHub Actions to use
full-length commit-SHA pins. Keep the exact SHA in each `uses:` reference and
retain a version comment that a reviewer can verify. Pin containers by digest
and verify checksums for downloaded executables.
- Keep ordinary CI read-only. Give the release job only the write permission it
needs, and pass package-host tokens only to that publishing step.
- Build once from the release commit, upload the completed archive and its
digest, then download and verify that exact artifact before publishing it.
Do not publish a separately rebuilt archive or accept zero or multiple
package artifacts.
- Enable GitHub immutable releases when available. Create the release as a
draft, attach all assets, then publish it so its tag and assets cannot be
changed afterward. If that setting is unavailable, record the residual risk;
still keep automation fail-closed if the intended release, tag, or asset
already exists.
releases, apply the shared workflow, artifact, permission, executable-input,
release, and repository-enforcement baseline from
`github-actions-quality-check`.

Extend that baseline with the BepInEx release modes:

- Distinguish edge validation artifacts, prereleases, and stable releases.
Publish to external package hosts only for the repository's intended stable
mode, after package inspection and runtime evidence are available.

GitHub documents the repository Actions setting for
[full-length commit-SHA pins](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository)
and [immutable releases](https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases).

## Transferable verification shape

Start with the repository's documented commands. Common categories include:
Expand All @@ -124,9 +109,9 @@ dotnet format --no-restore --verify-no-changes
DOTNET_CLI_UI_LANGUAGE=en dotnet build
```

They also lint Markdown, and run shell, GitHub Actions, and action-pin checks
when those surfaces change. These are examples, not commands to invent in a
repository that has not adopted the corresponding tools.
They also lint Markdown and apply `github-actions-quality-check` when automation
surfaces change. These are examples, not commands to invent in a repository
that has not adopted the corresponding tools.

For runtime validation, record the exact game build, BepInEx version, mod set,
and reproduction path. Build success alone does not establish patch timing,
Expand Down
Loading