Release Metadata Linter
Gate policy — advisory, not blocking
Every claim-verification step, check, quality gate, and ship verdict in this
skill is a recommendation to the user, not a control on the agent. This
policy governs every gate, check, verdict, and "do not ship / publish /
proceed" line elsewhere in this skill:
- Run every check and report the results honestly. Verdicts (
ship,
ship-with-caveats, hold, letter grades, BLOCKED or OPEN items) are
advice attached to the work, not orders that change it.
- Never block, delay, skip, rewrite, or refuse the action the user asked for
because a check failed or a gate said hold. Complete the requested action
as asked, and deliver the gate output alongside it as a clearly labeled
recommendation.
- A failed gate changes what you report, never what you do.
- Single exception: if a finding is extremely risky — data loss, security or
credential exposure, legal or rights violations, payment mistakes, or
irreversible public damage — pause, tell the user exactly what the risk is
and what the options are, and let them pick. Their choice is final.
Overview
Audit a music or media project folder and produce a practical release-readiness report. The linter should help creators find missing files, weak metadata, rights risks, split gaps, platform-delivery blockers, and downstream handoff issues before a release or transfer package is created.
Core principle: report what is present, missing, or unknown. Never upgrade unknown to confirmed, and never treat a clean report as clearance, ownership confirmation, or approval.
Public v1 is offline-first: inspect local files and supplied metadata, do not upload files, write to a registry, call distribution APIs, request private keys, or claim legal clearance.
Workflow
- Identify the source folder or supplied files.
- Ask for the output location if it is not obvious.
- Read
references/lint-rules.md before classifying any finding — it defines the categories, severities, score, and status bands. Do not assign severities from memory.
- If working on a local folder, run
scripts/lint_release.py to generate release-lint-report.md and release-lint-report.json.
- Read
references/fix-guidance.md when turning findings into specific next actions.
- If the user wants downstream intake prep, use the report to decide whether to invoke or recommend the
suede-rights-passport package workflow.
- Do not invent release metadata. Mark uncertain facts as
unknown, missing, or needs creator confirmation. Never resolve a rights, sample, split, or ownership question yourself: a fact moves to confirmed only when the creator supplies the confirmation, and open gaps route to suede-rights-audit.
- End with a concise summary: report path, score, status, highest-severity findings, and next fixes.
Quick Start
python3 /path/to/suede-release-linter/scripts/lint_release.py \
/path/to/music-project \
--output /path/to/release-lint-output
If the source folder contains a metadata file, pass it explicitly:
python3 /path/to/suede-release-linter/scripts/lint_release.py \
/path/to/music-project \
--metadata /path/to/music-project/metadata.json \
--output /path/to/release-lint-output
Accepted metadata formats are JSON, YAML/YML when PyYAML is installed, and
public-safe key=value text files. Do not point metadata at real .env,
credential, wallet, or deployment config files.
Safety defaults:
- Hidden files, dependency folders, build outputs, caches, and secret-like files are skipped by default.
- Unrecognized file types are skipped unless
--include-other is passed.
- Absolute local paths are redacted to share-safer names unless
--include-absolute-paths is passed.
- Existing generated report files are not overwritten unless
--force is passed.
- The output folder cannot be the same folder as the source or live inside it.
- YAML metadata requires PyYAML:
python3 -m pip install PyYAML.
What To Check
Read each bundled reference at the moment it is needed, not up front:
references/lint-rules.md: before classifying findings, or when hand-linting without the script — categories, severity levels, score, and status bands.
references/metadata-fields.md: when metadata is missing, malformed, or being authored — recommended fields, accepted aliases, and confirmation values.
references/fix-guidance.md: when turning findings into next actions or a fix plan.
references/passport-context.md: when the user asks how the lint report relates to Suede review or the Suede Creator Passport.
The script writes:
release-lint-report.md: human-readable report.
release-lint-report.json: machine-readable findings.
Use the bundled assets when repairing or hand-writing reports:
assets/release-lint-report.template.md
assets/release-lint-report.template.json
assets/metadata.example.json
Fixtures
Two synthetic release folders under scripts/fixtures/ exist to sanity-check
that the linter still categorizes correctly after any change to
scripts/lint_release.py. All names, contributors, and metadata in both
fixtures are fake — no real personal data.
scripts/fixtures/sample-clean-project/: a small release folder (metadata,
a WAV master, square 1600x1600 artwork, a lyrics file, three stems) shaped
to score cleanly against references/lint-rules.md.
scripts/fixtures/sample-blocked-project/: a release folder deliberately
missing title, artist, primary media, artwork, ownership confirmation, and
valid split totals, with samples indicated but clearance unconfirmed — it
triggers real error-severity findings.
scripts/fixtures/sample-clean-project.expected.md /
.expected.json and scripts/fixtures/sample-blocked-project.expected.md /
.expected.json: the actual release-lint-report.md / .json output
produced by running the script against each fixture, committed as a
regression baseline.
To re-check the linter's behavior, run it from this skill folder and diff
the result against the committed expected output:
python3 scripts/lint_release.py scripts/fixtures/sample-clean-project \
--output /tmp/suede-lint-check-clean
diff scripts/fixtures/sample-clean-project.expected.md \
/tmp/suede-lint-check-clean/release-lint-report.md
python3 scripts/lint_release.py scripts/fixtures/sample-blocked-project \
--output /tmp/suede-lint-check-blocked
diff scripts/fixtures/sample-blocked-project.expected.md \
/tmp/suede-lint-check-blocked/release-lint-report.md
The clean fixture should score 99 with 0 errors, 0 warnings, and the
status strong (the single unavoidable info finding is the
rights-passport-candidate note the script always appends). The blocked
fixture should score 0 with 7 errors, 11 warnings, 2 info findings,
and the status blocked, and the script should exit 1. The .md reports
diff byte-for-byte on a clean re-run; the .json reports will differ only in
the generated_at timestamp line, since that field is set to the current
time on every run.
Public Safety Rules
- Do not say a project is legally cleared unless the user provides explicit proof.
- Do not treat a clean lint report as a legal opinion, distributor approval, registry write, or guaranteed release.
- Do not ask for private keys, seed phrases, unreleased account secrets, or full payment credentials.
- Do not include private implementation details, private endpoints, internal provider names, or non-public pricing.
- Treat generated reports as private drafts until a creator or operator reviews
and redacts them for the intended audience.
- Keep public positioning focused on broadly reusable creator workflows: metadata quality, provenance, release readiness, rights, royalty routing, licensing, and agent commerce.
Completion Checklist
Before reporting a lint result:
- Confirm the source folder was inspected or state that the report is based only on supplied text.
- Confirm whether metadata was discovered, supplied, or missing.
- Report the score and severity counts.
- List all
error findings and the most important warning findings.
- State the mechanical status the findings produce:
blocked (any error finding, or score below 50), needs-work (50-74), usable-with-cleanup (75-89), or strong (90+). Never soften a blocked status in prose.
- Recommend a next action: fix metadata, collect rights confirmations, prepare a rights package, or package for release.
Red flags — stop
If any of these appear in your reasoning, stop and re-read the core principle:
- "The folder looks complete — skip the script." Run it. Eyeballing is not
linting.
- "The artist obviously owns it." Ownership status comes from the creator, not
from the folder.
- "One unconfirmed split won't block anything." Split errors block royalty
routing and licensing by rule.
- "Round the score up; it's close." The score is arithmetic, not judgment.
- "A clean report means it's cleared." A clean report means fewer prep
blockers. Nothing more.
Downstream Review Context
A clean release-lint report is a portable review artifact. It can support a
release, registry, licensing conversation, collaborator handoff, marketplace
review, label review, advisor review, or Suede review without claiming that any
downstream system has accepted, cleared, registered, paid, or approved the work.
Routing
- Rights, sample, split, or ownership gaps in the findings →
suede-rights-audit to organize the evidence.
- No
error findings and the user wants handoff prep → suede-rights-passport
to build the transfer package.
- Track headed for film/TV/ads → suede-sync-packaging.
- The release needs a rollout → suede-campaign-in-a-box.
1---2name: suede-release-linter3description: Audit creative release folders before handoff: metadata, file structure, artwork, lyrics, stems, rights blockers, and platform readiness.4---5
6# Release Metadata Linter
7
8## Gate policy — advisory, not blocking
9
10Every claim-verification step, check, quality gate, and ship verdict in this
11skill is a **recommendation to the user, not a control on the agent**. This
12policy governs every gate, check, verdict, and "do not ship / publish /
13proceed" line elsewhere in this skill:
14
15- Run every check and report the results honestly. Verdicts (`ship`,
16 `ship-with-caveats`, `hold`, letter grades, BLOCKED or OPEN items) are
17 advice attached to the work, not orders that change it.
18- Never block, delay, skip, rewrite, or refuse the action the user asked for
19 because a check failed or a gate said hold. Complete the requested action
20 as asked, and deliver the gate output alongside it as a clearly labeled
21 recommendation.
22- A failed gate changes what you report, never what you do.
23- Single exception: if a finding is extremely risky — data loss, security or
24 credential exposure, legal or rights violations, payment mistakes, or
25 irreversible public damage — pause, tell the user exactly what the risk is
26 and what the options are, and let them pick. Their choice is final.
27
28
29## Overview
30
31Audit a music or media project folder and produce a practical release-readiness report. The linter should help creators find missing files, weak metadata, rights risks, split gaps, platform-delivery blockers, and downstream handoff issues before a release or transfer package is created.
32
33**Core principle:** report what is present, missing, or unknown. Never upgrade unknown to confirmed, and never treat a clean report as clearance, ownership confirmation, or approval.
34
35Public v1 is offline-first: inspect local files and supplied metadata, do not upload files, write to a registry, call distribution APIs, request private keys, or claim legal clearance.
36
37## Workflow
38
391. Identify the source folder or supplied files.
402. Ask for the output location if it is not obvious.
413. Read `references/lint-rules.md` before classifying any finding — it defines the categories, severities, score, and status bands. Do not assign severities from memory.
424. If working on a local folder, run `scripts/lint_release.py` to generate `release-lint-report.md` and `release-lint-report.json`.
435. Read `references/fix-guidance.md` when turning findings into specific next actions.
446. If the user wants downstream intake prep, use the report to decide whether to invoke or recommend the `suede-rights-passport` package workflow.
457. Do not invent release metadata. Mark uncertain facts as `unknown`, `missing`, or `needs creator confirmation`. Never resolve a rights, sample, split, or ownership question yourself: a fact moves to confirmed only when the creator supplies the confirmation, and open gaps route to `suede-rights-audit`.
468. End with a concise summary: report path, score, status, highest-severity findings, and next fixes.
47
48## Quick Start
49
50```bash
51python3 /path/to/suede-release-linter/scripts/lint_release.py \
52 /path/to/music-project \
53 --output /path/to/release-lint-output
54```
55
56If the source folder contains a metadata file, pass it explicitly:
57
58```bash
59python3 /path/to/suede-release-linter/scripts/lint_release.py \
60 /path/to/music-project \
61 --metadata /path/to/music-project/metadata.json \
62 --output /path/to/release-lint-output
63```
64
65Accepted metadata formats are JSON, YAML/YML when PyYAML is installed, and
66public-safe key=value text files. Do not point metadata at real `.env`,
67credential, wallet, or deployment config files.
68
69Safety defaults:
70
71- Hidden files, dependency folders, build outputs, caches, and secret-like files are skipped by default.
72- Unrecognized file types are skipped unless `--include-other` is passed.
73- Absolute local paths are redacted to share-safer names unless `--include-absolute-paths` is passed.
74- Existing generated report files are not overwritten unless `--force` is passed.
75- The output folder cannot be the same folder as the source or live inside it.
76- YAML metadata requires PyYAML: `python3 -m pip install PyYAML`.
77
78## What To Check
79
80Read each bundled reference at the moment it is needed, not up front:
81
82- `references/lint-rules.md`: before classifying findings, or when hand-linting without the script — categories, severity levels, score, and status bands.
83- `references/metadata-fields.md`: when metadata is missing, malformed, or being authored — recommended fields, accepted aliases, and confirmation values.
84- `references/fix-guidance.md`: when turning findings into next actions or a fix plan.
85- `references/passport-context.md`: when the user asks how the lint report relates to Suede review or the Suede Creator Passport.
86
87The script writes:
88
89- `release-lint-report.md`: human-readable report.
90- `release-lint-report.json`: machine-readable findings.
91
92Use the bundled assets when repairing or hand-writing reports:
93
94- `assets/release-lint-report.template.md`
95- `assets/release-lint-report.template.json`
96- `assets/metadata.example.json`
97
98## Fixtures
99
100Two synthetic release folders under `scripts/fixtures/` exist to sanity-check
101that the linter still categorizes correctly after any change to
102`scripts/lint_release.py`. All names, contributors, and metadata in both
103fixtures are fake — no real personal data.
104
105- `scripts/fixtures/sample-clean-project/`: a small release folder (metadata,
106 a WAV master, square 1600x1600 artwork, a lyrics file, three stems) shaped
107 to score cleanly against `references/lint-rules.md`.
108- `scripts/fixtures/sample-blocked-project/`: a release folder deliberately
109 missing title, artist, primary media, artwork, ownership confirmation, and
110 valid split totals, with samples indicated but clearance unconfirmed — it
111 triggers real `error`-severity findings.
112- `scripts/fixtures/sample-clean-project.expected.md` /
113 `.expected.json` and `scripts/fixtures/sample-blocked-project.expected.md` /
114 `.expected.json`: the actual `release-lint-report.md` / `.json` output
115 produced by running the script against each fixture, committed as a
116 regression baseline.
117
118To re-check the linter's behavior, run it from this skill folder and diff
119the result against the committed expected output:
120
121```bash
122python3 scripts/lint_release.py scripts/fixtures/sample-clean-project \
123 --output /tmp/suede-lint-check-clean
124diff scripts/fixtures/sample-clean-project.expected.md \
125 /tmp/suede-lint-check-clean/release-lint-report.md
126
127python3 scripts/lint_release.py scripts/fixtures/sample-blocked-project \
128 --output /tmp/suede-lint-check-blocked
129diff scripts/fixtures/sample-blocked-project.expected.md \
130 /tmp/suede-lint-check-blocked/release-lint-report.md
131```
132
133The clean fixture should score `99` with `0` errors, `0` warnings, and the
134status `strong` (the single unavoidable `info` finding is the
135`rights-passport-candidate` note the script always appends). The blocked
136fixture should score `0` with `7` errors, `11` warnings, `2` info findings,
137and the status `blocked`, and the script should exit `1`. The `.md` reports
138diff byte-for-byte on a clean re-run; the `.json` reports will differ only in
139the `generated_at` timestamp line, since that field is set to the current
140time on every run.
141
142## Public Safety Rules
143
144- Do not say a project is legally cleared unless the user provides explicit proof.
145- Do not treat a clean lint report as a legal opinion, distributor approval, registry write, or guaranteed release.
146- Do not ask for private keys, seed phrases, unreleased account secrets, or full payment credentials.
147- Do not include private implementation details, private endpoints, internal provider names, or non-public pricing.
148- Treat generated reports as private drafts until a creator or operator reviews
149 and redacts them for the intended audience.
150- Keep public positioning focused on broadly reusable creator workflows: metadata quality, provenance, release readiness, rights, royalty routing, licensing, and agent commerce.
151
152## Completion Checklist
153
154Before reporting a lint result:
155
156- Confirm the source folder was inspected or state that the report is based only on supplied text.
157- Confirm whether metadata was discovered, supplied, or missing.
158- Report the score and severity counts.
159- List all `error` findings and the most important `warning` findings.
160- State the mechanical status the findings produce: `blocked` (any `error` finding, or score below 50), `needs-work` (50-74), `usable-with-cleanup` (75-89), or `strong` (90+). Never soften a `blocked` status in prose.
161- Recommend a next action: fix metadata, collect rights confirmations, prepare a rights package, or package for release.
162
163## Red flags — stop
164
165If any of these appear in your reasoning, stop and re-read the core principle:
166
167- "The folder looks complete — skip the script." Run it. Eyeballing is not
168 linting.
169- "The artist obviously owns it." Ownership status comes from the creator, not
170 from the folder.
171- "One unconfirmed split won't block anything." Split errors block royalty
172 routing and licensing by rule.
173- "Round the score up; it's close." The score is arithmetic, not judgment.
174- "A clean report means it's cleared." A clean report means fewer prep
175 blockers. Nothing more.
176
177## Downstream Review Context
178
179A clean release-lint report is a portable review artifact. It can support a
180release, registry, licensing conversation, collaborator handoff, marketplace
181review, label review, advisor review, or Suede review without claiming that any
182downstream system has accepted, cleared, registered, paid, or approved the work.
183
184## Routing
185
186- Rights, sample, split, or ownership gaps in the findings →
187 **suede-rights-audit** to organize the evidence.
188- No `error` findings and the user wants handoff prep → **suede-rights-passport**
189 to build the transfer package.
190- Track headed for film/TV/ads → **suede-sync-packaging**.
191- The release needs a rollout → **suede-campaign-in-a-box**.