1. One folder, one artifact
An artifact is one folder (or one file) in a repository, at a commit. The certificate covers a digest of every file in that folder, and names the repository, commit and path it came from. workrr never copies or hosts the artifact. Anyone gets it from your repository and checks that it hashes to the certified digest.
So the folder is the unit of trust. Keep everything the artifact needs inside it, and nothing it doesn't.
2. Location
| Artifact | Put it at | path in the workflow |
|---|---|---|
| Skill | skills/<name>/SKILL.md | skills/<name> |
| MCP server | servers/<name>/server.json, or the repo root for a one-server repo | servers/<name> or . |
| Agent context | AGENTS.md or CLAUDE.md at the repo root | AGENTS.md (a single file) |
| Ruleset | rules/<name>/ | rules/<name> |
A repo with a single skill may keep SKILL.md at the root and use path: .. That certifies the whole repository, so everything in it must follow §5. With more than one artifact, give each its own folder; never nest one artifact inside another's folder.
my-agent-tools/
├── skills/
│ ├── csv-summary/
│ │ ├── SKILL.md
│ │ ├── workrr.json # test command (optional, for Tested)
│ │ ├── LICENSE
│ │ ├── scripts/summarize.py
│ │ └── tests/test_summarize.py
│ └── pdf-extract/
│ └── SKILL.md …
├── servers/
│ └── weather/
│ ├── server.json
│ └── src/ …
├── rules/
│ └── secure-coding/ …
├── AGENTS.md
└── .github/workflows/
├── workrr-csv-summary.yml
└── workrr-pdf-extract.yml
3. Naming
- should Folder names are lowercase kebab-case:
csv-summary, notCSV_Summary. Letters, digits and hyphens, starting with a letter, at most 64 characters. - should The artifact's declared name matches its folder:
nameinSKILL.mdfrontmatter, ornameinserver.json. The certificate shows the declared name, and falls back to the folder name. - should Names stay stable. Renaming the folder changes the path in every future certificate. Old certificates still point at the old path at their own commit.
- should One workflow file per artifact:
.github/workflows/workrr-<name>.yml.
4. Files by type
The certifier detects the type from the folder's contents, in this order:
| If the folder contains | Type | Requirements |
|---|---|---|
SKILL.md | skill | must YAML frontmatter with non-empty name and description.should description says when to use it ("Use when …"), the body has headings or numbered steps, and allowed-tools lists the tools it needs. |
server.json | MCP server | should be valid JSON with a name, in the MCP registry server.json format, plus a README.md. |
AGENTS.md or CLAUDE.md | agent context | should be self-contained: anything it tells an agent to read is inside the certified path. |
| anything else | other (rulesets, prompts, configs) | should include a README.md that says what it is and how to load it. |
5. What may be inside
These are the baseline policy (workrr-baseline-v0.1). Every file in the folder is hashed, except .git.
- must At most 5 MB in total.
- must No compiled binaries:
.exe .dll .so .dylib .bin .jar .class .pyc. Ship source; build in your tests if needed. - must No symlinks that point outside the folder.
- must Pass the scanner: no high or critical findings: instruction-override or concealment phrasing, invisible Unicode tag or bidirectional characters, hidden HTML-comment instructions, remote scripts piped to a shell, or reading credential stores.
- should A
LICENSEfile in the folder (orlicenseinSKILL.mdfrontmatter). A repo-level licence outside the folder isn't part of the artifact. - should No build output, caches,
node_modules, virtualenvs or editor files. Exclude them with.gitignore; untracked files aren't checked out, so they're never hashed.
6. Tests
Declare a test command in workrr.json inside the artifact folder:
{ "test": { "command": "python -m pytest tests" } }
The tests are part of the artifact, so the digest covers them. The certifier runs them in a separate job that has no signing permission, and binds the result to the artifact digest.
- Tested (wire value
silver): your CI signed it, tests pass, and provenance, policy and scan all pass. - Signed (
banded): your CI signed it and the checks passed, but there are no tests. A Signed certificate also gets an A–E band: one point each for no scan warnings, declaredallowed-tools, structured docs (the "Use when" description plus headings, or aREADME.md), and a licence.
See the guide for test commands that work in the certifier's runner.
7. The certify workflow
One workflow file per artifact, calling the reusable certifier at a released tag:
# .github/workflows/workrr-csv-summary.yml
name: workrr-csv-summary
on:
push:
branches: [main] # your default branch
tags: ["v*"]
workflow_dispatch:
jobs:
certify:
permissions:
contents: read
id-token: write
attestations: write
uses: workrr-trust/certify/.github/workflows/certify.yml@v0.1.5
with:
path: skills/csv-summary
One file per artifact keeps each run and its certificate easy to find; several jobs in one workflow also work from @v0.1.5. The repository must be public for a public Rekor entry. The guide covers the rest.
No workflow: public scans
If you'd rather not add an outside workflow, you don't have to. workrr can run the same certifier in its own public repository (scan.yml) against a public commit of yours. It never runs your code. The result has the level scanned:
- Anyone can reproduce it: the same commit gives the same digest and check results (
workrr certify --observe). - It is not signed by you, so it ranks below Signed and never counts toward Reproduced. Badges show
scanned. - Once you add the workflow, your own certificate is shown instead.
The layout rules above apply the same way. Details: public scans.
When a scan fails: Flagged
A public scan that fails a security check (a high or critical scan rule, a compiled binary, or a symlink out of the folder) signs a finding instead of a certificate. It states the rule, file, line and commit, and anyone can reproduce it with workrr verify-finding. The artifact shows Flagged in the ledger, its badge and skills.workrr.ai, which offers no install for it. A finding states facts, not intent: some pattern matches are innocent. Push a fix and the new commit is re-scanned automatically; disagree with a finding in a public issue. There is no opt-out from scanning public code. How findings work.
Levels, least to most scrutiny: Scanned (workrr read a public commit) · Signed (your CI signed it) · Tested (and your tests passed) · Reproduced (two independent forges agree).
8. Checklist
- ☐ The artifact is its own folder (or a single
AGENTS.md/CLAUDE.md), not nested inside another. - ☐ The folder name is kebab-case and matches the declared
name. - ☐ Skills:
SKILL.mdfrontmatter hasnameanddescription("Use when …"). - ☐ Under 5 MB, no binaries, no symlinks out of the folder.
- ☐
LICENSEinside the folder. - ☐
workrr.jsonwith a test command that passes. - ☐ One
.github/workflows/workrr-<name>.ymlper artifact, pinned to a release tag.
This is version 0.1 of the layout. Changes are announced in the certifier changelog, and the certifier's checks are the reference: artifact.ts, policy.ts. The certificate format is in the spec.