pre-release — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited pre-release (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A structured pre-release workflow that runs automated checks, generates user-facing changesets from git history, and optionally spawns fresh-eyes README reviewers.
npm publish or version bumpThe target project must have @changesets/cli initialized:
npm install --save-dev @changesets/cli @changesets/changelog-github
npx changeset initSee Changesets Setup for first-time configuration.
Run these checks against the project root. Report each as ✅ / ❌ / ⚠️:
| # | Check | How | ||||||
|---|---|---|---|---|---|---|---|---|
| 1 | README.md exists with: purpose, install, usage, prerequisites, license | Read and verify sections | ||||||
| 2 | LICENSE file present and matches package.json license field | Compare files | ||||||
| 3 | No hardcoded credentials, API keys, or personal paths in tracked files | `git grep -iE '(api.key\ | secret\ | password\ | token\ | /Users/\ | /home/\ | C:\\\\Users)' -- ':!*.lock' ':!node_modules'` |
| 4 | No TODO/FIXME/HACK in shipped code | `git grep -iE '(TODO\ | FIXME\ | HACK)' -- '.ts' '.js' '.mjs' ':!node_modules' ':!.test.' ':!.spec.*'` | ||||
| 5 | Tests pass | npm test (or project's test command) | ||||||
| 6 | Lint passes | npm run lint (if script exists) | ||||||
| 7 | Build succeeds | npm run build (if script exists) | ||||||
| 8 | Git working tree clean | git status --porcelain | ||||||
| 9 | On correct branch | git branch --show-current (should be main or release branch) | ||||||
| 10 | .gitignore covers: node_modules, dist, .env, editor config | Read .gitignore | ||||||
| 11 | package.json has required fields: name, version, description, license, repository | Read and verify | ||||||
| 12 | .changeset/config.json exists and is configured | Read and verify | ||||||
| 13 | GitHub Actions release workflow uses Trusted Publishers (OIDC), not NPM_TOKEN | Read .github/workflows/release.yml; verify id-token: write permission present and no NPM_TOKEN / NODE_AUTH_TOKEN secrets used | ||||||
| 14 | Trusted Publisher configured on npmjs.com for this package | Ask user to confirm (cannot be checked programmatically) | ||||||
| 15 | History scan clean (gitleaks + trufflehog) | gitleaks detect --source . --verbose AND trufflehog git file://. --since-commit=HEAD~0 --fail — both must pass with zero findings | ||||||
| 16 | Workflow security audit | Read all .github/workflows/*.yml — verify: least-privilege permissions: (job-level, not write-all), actions pinned by SHA (not tag), no pull_request_target with PR head checkout, no secret interpolation in echo/$GITHUB_OUTPUT/$GITHUB_ENV, no broad GITHUB_TOKEN perms, no env dumping in debug steps | ||||||
| 17 | Template-only values in examples | `git grep -rE '(ghp_[A-Za-z0-9]{36}\ | npm_[A-Za-z0-9]{36}\ | sk-[A-Za-z0-9]{48}\ | AKIA[A-Z0-9]{16}\ | xox[bprs]-)' -- ':!node_modules' ':!*.lock' — must be zero; all example configs must use <REPLACE_ME>` placeholders | ||
| 18 | No .local files tracked | git ls-files '*.local' '*.local.*' '.env.local' — must return empty | ||||||
| 19 | Redaction review for docs & screenshots | Scan README, docs/, and any images for: internal domains (*.internal, *.corp), tenant/account IDs, internal route patterns, environment naming conventions, unredacted screenshots | ||||||
| 20 | Skills discovery (if project ships skills) | Only if SKILL.md files exist: (a) .well-known/skills/index.json exists and lists every skill found by find . -name SKILL.md, (b) README lists every skill in a discoverable table, (c) package.json files includes .well-known/. Run npx skills add . --list and verify output matches expectations. |
Blockers (must fix before release): checks 1-5, 8, 11-18, 20 (if applicable). Warnings (should fix): checks 6-7, 9-10, 19. Info: anything else notable.
This is the core value — AI-written, user-facing release notes instead of mechanical commit scraping.
#### 2a. Find the range
# Last release tag
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
# If no tags, use first commit
if [ -z "$LAST_TAG" ]; then
RANGE="$(git rev-list --max-parents=0 HEAD)..HEAD"
echo "No previous tags found — covering entire history"
else
RANGE="${LAST_TAG}..HEAD"
echo "Changes since $LAST_TAG"
fi#### 2b. Gather the raw material
# Commits with files changed
git log $RANGE --pretty=format:'%h %s' --no-merges
# For more context on what changed
git log $RANGE --pretty=format:'### %h %s%n%b' --no-merges
# Files changed (to understand scope)
git diff --stat $LAST_TAG..HEAD 2>/dev/null || git diff --stat $(git rev-list --max-parents=0 HEAD)..HEADAlso check for existing pending changesets — don't duplicate:
ls .changeset/*.md 2>/dev/null | grep -v README.mdIf there are already changeset files, read them and account for what's already covered.
#### 2c. Classify and write changesets
Group commits by impact and write changeset files. Each changeset is a markdown file in .changeset/:
File format (.changeset/<descriptive-name>.md):
---
"package-name": patch
---
Brief, user-facing description of what changed.Semver classification:
| Type | Bump | Examples |
|---|---|---|
| Breaking API changes | major | Removed function, changed signature, dropped Node version |
| New features, capabilities | minor | New command, new option, new API |
| Bug fixes, docs, internal | patch | Fix crash, update README, refactor internals |
Writing guidelines:
--verbose flag" not "refactored logger module"Name the files descriptively using kebab-case: add-verbose-flag.md, fix-auth-crash.md, initial-release.md.
#### 2d. For initial releases (no previous tags)
Write a single changeset covering the initial release:
---
"package-name": minor
---
Initial release.
- Feature 1: brief description
- Feature 2: brief description
- Feature 3: brief descriptionUse minor (0.1.0) for initial releases unless the project is already at 1.x.
Load the run-agents skill. Use pi-subagents to spawn 2 parallel agents on different models to review the README as first-time users:
{ "tasks": [
{ "agent": "_arch-reviewer", "task": "Read the README.md in <project-path>. You are a developer who has NEVER seen this project. Can you answer: (1) What does it do? (2) How to install? (3) How to use? (4) Prerequisites? (5) Where to get help? For each: quote relevant text or say MISSING. Then list anything confusing or that assumes prior knowledge.", "model": "google/gemini-3-pro" },
{ "agent": "_arch-reviewer", "task": "Read the README.md in <project-path>. You are a developer who has NEVER seen this project. Can you answer: (1) What does it do? (2) How to install? (3) How to use? (4) Prerequisites? (5) Where to get help? For each: quote relevant text or say MISSING. Then list anything confusing or that assumes prior knowledge.", "model": "github-copilot/gpt-5.3" }
]}Read both outputs and note any gaps.
Present the final report in this structure:
# Pre-Release Report: <package-name>
## Version: <current> → <proposed>
## Date: <today>
### Checklist
| # | Check | Status | Notes |
|---|-------|--------|-------|
| 1 | README | ✅/❌ | ... |
| ... |
### Changesets Generated
| File | Bump | Summary |
|------|------|---------|
| `add-feature-x.md` | minor | Add feature X |
| ... |
### README Review
(If Step 3 was run)
- **Gaps**: ...
- **Confusing**: ...
### Blockers (must fix)
1. ...
### Suggestions (can wait)
1. ...
### Ready to Release?
**YES** / **NO — N blockers remain**If the user approves, commit the changeset files:
git add .changeset/*.md
git commit -m "chore: add changesets for next release" -m "Co-Authored-By: Pi <[email protected]>"For projects that don't have changesets yet. Run once:
npm install --save-dev @changesets/cli @changesets/changelog-github
npx changeset init.changeset/config.json{
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
"changelog": "@changesets/changelog-github",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}Set "access": "public" for scoped packages (@scope/name). Set "baseBranch" to your default branch.
package.json{
"scripts": {
"changeset": "changeset",
"version-packages": "changeset version",
"release": "changeset publish"
}
}.github/workflows/release.yml)name: Release
on:
push:
branches: [main]
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: write
pull-requests: write
id-token: write # Required for npm Trusted Publishing (OIDC)
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24 # npm >= 11.5.1 required for Trusted Publishing
cache: npm
registry-url: https://registry.npmjs.org
- run: npm ci
- run: npm run build
- run: npm test
- name: Create Release PR or Publish
id: changesets
uses: changesets/action@v1
with:
publish: npx changeset publish
title: "chore: version packages"
commit: "chore: version packages"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}npm's Trusted Publishing uses OIDC to authenticate GitHub Actions with the npm registry. No NPM_TOKEN secret required.
release.ymlid-token: write permission in the workflow enables OIDC.Provenance attestations are generated automatically.
After verifying Trusted Publishing works, go to package Settings → Publishing access → "Require two-factor authentication and disallow tokens" for maximum security.
⚠️ NPM_TOKEN is deprecated: Do not use NPM_TOKEN secrets for publishing from GitHub Actions. Trusted Publishers (OIDC) is the only supported method. If you encounter an existing workflow using NPM_TOKEN, migrate it to Trusted Publishers. See: https://docs.npmjs.com/trusted-publishers
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.