model-card-lint-gpai / index.html
getreadystack's picture
Upload index.html with huggingface_hub
7912a82 verified
Raw History Blame Contribute Delete
51.6 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Hugging Face Model Card requirements — check model card fields and</title>
<meta name="description" content="This browser tool checks a Hugging Face model card against the Hub metadata spec and EU AI Act GPAI documentation duties, with line numbers, articles, and fixes.">
<style>
:root{color-scheme:light}body{margin:0;font:15px/1.55 system-ui,-apple-system,"Segoe UI",sans-serif;background:#faf9f5;color:#1a1512}
.wrap{max-width:960px;margin:0 auto;padding:28px 18px 60px}h1{font-size:26px;margin:0 0 6px}.lede{color:#4a403a;margin:0 0 16px}
textarea{width:100%;min-height:260px;font:13px/1.45 ui-monospace,Menlo,Consolas,monospace;padding:12px;border:1px solid #d9d0c4;border-radius:8px;box-sizing:border-box}
.bar{display:flex;gap:10px;align-items:center;margin:12px 0}button{font:600 15px system-ui;padding:10px 18px;border:0;border-radius:8px;background:#1a1512;color:#fff;cursor:pointer}
input[type=date]{font:14px system-ui;padding:8px;border:1px solid #d9d0c4;border-radius:6px}
table{border-collapse:collapse;width:100%;font-size:14px;margin-top:10px}th,td{text-align:left;padding:8px 10px;border-bottom:1px solid #eee;vertical-align:top}th{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:#7a6e65}
.sev.error{color:#a8551f;font-weight:700}.sev.warn,.sev.warning{color:#96691f}.ok{color:#2a6446;font-weight:600}.sum{font-weight:600}
.note{font-size:13px;color:#7a6e65;margin-top:18px}#paid{margin-top:22px;padding:14px 16px;border:1px solid #e2d8cb;border-radius:10px;background:#fffdfa}
</style>
<script data-grow-initializer="">!(function(){window.growMe||((window.growMe=function(e){window.growMe._.push(e);}),(window.growMe._=[]));var e=document.createElement("script");(e.type="text/javascript"),(e.src="https://faves.grow.me/main.js"),(e.defer=!0),e.setAttribute("data-grow-faves-site-id","U2l0ZTphZjljMzgyMC0yMmU5LTRhYjgtYTIxNS03OTRhMGY1N2ExYzM=");var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t);})();</script>
<!--yj-canon-s101--><link rel="canonical" href="https://getreadystack.com/tools/model-card-lint-gpai"></head>
<body>
<div class="wrap">
<h1>Hugging Face Model Card requirements — check model card fields and</h1>
<p class="lede">Lints a Hugging Face model card against the Hub metadata spec and the EU AI Act GPAI documentation duties. Line numbers, the article, the fix. Runs entirely in your browser — nothing is uploaded.</p>
<textarea id="src" spellcheck="false">---
license: other
tags:
pipeline_tag:
---
# clinical-notes-de-7b
&lt;!-- Provide a quick summary of what the model is/does. --&gt;
This model is a fine-tuned version of {{ base_model }} for German clinical note summarisation.
## Model Details
### Model Description
[More Information Needed]
- **Developed by:** [More Information Needed]
- **Funded by:** [More Information Needed]
- **Shared by:** your-username/clinical-notes-de-7b
## Uses
## Training Details
TODO: add the data card once legal signs off.
## Technical Specifications
[More Information Needed]
## Citation
Last updated 2025.</textarea>
<div class="bar"><button id="go">Check</button><label>as of <input type="date" id="today"></label></div>
<div id="out" aria-live="polite"></div>
<div id="paid"><strong>Free, right here:</strong> lint the model card you have open against every rule, as often as you like — line number, the rule, the article it comes from, and the line to write instead.<br><strong>In the editor ($29 once):</strong> lint every model card in the repository in one pass and export the dated audit as a file you keep (Markdown + JSON a CI step can fail on).<br><a href="https://getreadystack.com/api/buy/cl/polar_cl_mHiMKq8aRodhSAoK7NzNGXWSa5Nxn3sBnksN74QXeId">Get the full version — $29</a><br><small>$29 once · one licence key per person or team seat · A compliance consultant's model-documentation review is quoted in the hundreds of dollars per model.</small></div>
<p class="note">Same engine as the VS Code extension, byte for byte.</p>
</div>
<script>var MCL_RULES = [
{"id":"fm-missing","sev":"error","kind":"no_frontmatter","msg":"No YAML frontmatter block. A Hugging Face model card must open with a --- block; without it the Hub stores no licence, no task and no dataset link, and EU AI Act Annex XII information for downstream providers has nowhere to live. Add a --- block as line 1."},
{"id":"fm-license","sev":"error","kind":"fm_required","key":"license","msg":"Frontmatter has no license: key. The Hub refuses to show a licence it was not told, and a downstream provider cannot accept your model without one (AI Act Annex XII). Write license: apache-2.0 (or the SPDX id that applies)."},
{"id":"fm-license-other","sev":"error","kind":"fm_requires_when","key":"license","equals":"other","requires":["license_name","license_link"],"msg":"license: other is declared without license_name and license_link. 'other' is the one value the Hub cannot resolve on its own. Add both keys so the terms are readable."},
{"id":"fm-pipeline-tag","sev":"warn","kind":"fm_required","key":"pipeline_tag","msg":"Frontmatter has no pipeline_tag:. Without it the model is missing from task search and gets no inference widget. Write pipeline_tag: text-generation (or the task that applies)."},
{"id":"fm-library-name","sev":"info","kind":"fm_required","key":"library_name","msg":"Frontmatter has no library_name:. The Hub then guesses how to load the model and the usage snippet on the page can be wrong. Write library_name: transformers."},
{"id":"fm-language","sev":"warn","kind":"fm_required","key":"language","msg":"Frontmatter has no language:. Language is part of the intended-use statement a deployer needs (AI Act Annex XII) and it is how the model is filtered on the Hub. Write language: en (list every language)."},
{"id":"fm-datasets","sev":"error","kind":"fm_required","key":"datasets","msg":"Frontmatter has no datasets: key. Training-data provenance is the first thing an EU AI Act Art. 53(1)(d) reviewer looks for and the first thing an enterprise buyer asks for. List the dataset ids, or say in the body why they cannot be listed."},
{"id":"fm-tags","sev":"info","kind":"fm_required","key":"tags","msg":"Frontmatter has no tags:. Tags are how the model is found on the Hub at all. Add at least the task, the domain and the base architecture."},
{"id":"fm-model-index","sev":"info","kind":"fm_required","key":"model-index","msg":"Frontmatter has no model-index:. Without it the numbers in your Evaluation section are prose, not results the Hub can display or a buyer can compare. Add a model-index block with the metric, the dataset and the value."},
{"id":"tpl-more-info","sev":"error","kind":"body_forbidden","pattern":"\\[More Information Needed\\]","msg":"'[More Information Needed]' is still in the card. That is the Hugging Face template's own placeholder: this section was never written. Every one of these is a documentation gap an auditor can point at."},
{"id":"tpl-jinja","sev":"error","kind":"body_forbidden","pattern":"\\{\\{[^}]{1,80}\\}\\}","msg":"An unrendered template expression is still in the card. The card was generated from a template and never filled in, so the text on the page is not about this model."},
{"id":"tpl-todo","sev":"warn","kind":"body_forbidden","pattern":"\\b(TODO|TBD|FIXME|XXX)\\b","msg":"A TODO/TBD marker is still in the card. Published model cards are read by procurement and by regulators; an open marker reads as an admission that the section is unfinished."},
{"id":"tpl-placeholder","sev":"warn","kind":"body_forbidden","pattern":"(\u003cMODEL_NAME\u003e|\\[Your Name\\]|your-username/|lorem ipsum|YOUR_ORG)","msg":"A placeholder from the template is still in the card. Replace it with the real name, the real repository or the real contact before this page is quoted anywhere."},
{"id":"tpl-empty-section","sev":"warn","kind":"empty_section","msg":"This heading has no text under it — the next line is another heading. An empty section is the same gap as a missing one, but it looks answered."},
{"id":"gpai-training-summary","sev":"error","kind":"deadline","date":"2026-08-02","any":["training data summary","summary of training content","training-data summary","public summary of the content used for training"],"msg":"No public summary of training content. EU AI Act Art. 53(1)(d) requires a provider of a general-purpose AI model to publish a sufficiently detailed summary of the content used for training, on the Commission's template. Add a 'Training Data Summary' section that links it."},
{"id":"gpai-copyright","sev":"error","kind":"body_required","any":["copyright polic","text and data mining","tdm opt-out","opt-out","robots.txt reservation","rights reservation"],"msg":"No copyright policy is stated. EU AI Act Art. 53(1)(c) requires a policy to comply with Union copyright law, including honouring machine-readable rights reservations (TDM opt-outs). One paragraph saying what you crawled, and what you honoured, is the whole duty."},
{"id":"gpai-provider","sev":"error","kind":"body_required","any":["provider:","developed by","contact:","point of contact","@","maintainer"],"msg":"The card names no provider and no contact. Annex XII asks for the identity of the provider of the model; a downstream deployer with a question about your model has nobody to write to."},
{"id":"gpai-intended-use","sev":"error","kind":"body_required","any":["intended use","direct use","intended purpose"],"msg":"No intended-use section. This is the single sentence that decides whether a deployer may put your model into a high-risk system at all, and Annex XII expects it. Write what the model is for, in one paragraph."},
{"id":"gpai-out-of-scope","sev":"error","kind":"body_required","any":["out-of-scope","out of scope","misuse","should not be used","prohibited use","not intended for"],"msg":"No out-of-scope section. Saying what the model must not be used for is how a provider limits its own exposure and how a deployer knows where the line is. Name at least the uses you refuse."},
{"id":"gpai-eval","sev":"warn","kind":"body_required","any":["evaluation","benchmark","results","metric"],"msg":"No evaluation section. Annex XI expects the evaluation strategies and results to be documented. A number with the dataset and the metric beside it is worth more than a paragraph of description."},
{"id":"gpai-limitations","sev":"warn","kind":"body_required","any":["limitation","bias","risks and limitations","known risk"],"msg":"No limitations or bias section. Annex XI expects known limitations to be documented, and this is the section enterprise review reads first. Name the failure modes you already know about."},
{"id":"gpai-energy","sev":"warn","kind":"body_required","any":["energy consumption","kwh","co2","carbon","emissions"],"msg":"No energy consumption figure. Annex XI expects the known or estimated energy consumption of the model. An estimate with the method beside it satisfies this; silence does not."},
{"id":"gpai-compute","sev":"warn","kind":"body_required","any":["flop","training compute","gpu-hour","gpu hour","a100","h100"],"msg":"No training compute figure. Annex XI expects the computational resources used for training. It is also the number that decides Art. 51 systemic-risk classification, where training compute above 10^25 FLOP is presumed to be systemic risk — you cannot show you are under a threshold you never stated."},
{"id":"gpai-eu-rep","sev":"warn","kind":"body_required","any":["authorised representative","authorized representative","eu representative","established in the union"],"msg":"No authorised representative is named. EU AI Act Art. 54 requires a provider established outside the Union to appoint an authorised representative in the Union before placing a general-purpose AI model on the EU market. If you are established in the Union, say so in one line and this stops applying."},
{"id":"gpai-legacy-2027","sev":"info","kind":"deadline","date":"2027-08-02","any":["placed on the market","release date","released on","first published"],"msg":"The card gives no placing-on-the-market date. It decides which clock you are on: models placed on the EU market before 2 August 2025 have until 2 August 2027 to meet the Art. 53 duties, everything after is already due. One dated line settles it."},
{"id":"prov-base-model","sev":"warn","kind":"cond_fm","pattern":"(fine-?tun|derived from|based on the|continued pre-?train|distilled from|merge of)","key":"base_model","msg":"The text says this model is derived from another one, but frontmatter has no base_model:. The Hub then shows no lineage, and Annex XII information from the upstream provider is not linked to yours. Add base_model: org/name."},
{"id":"prov-license-inherit","sev":"warn","kind":"cond_body","pattern":"^base_model:","any":["upstream licence","upstream license","base model licence","base model license","inherit","the licence of the base","the license of the base"],"msg":"A base_model is declared but the card never says what the upstream licence permits. A restrictive base licence travels to your weights whatever your own license: key says. State in one line which terms you inherited."},
{"id":"stale-year","sev":"warn","kind":"stale_year","msg":"The card dates itself to a year that has already passed. A model card that still says 'as of' an earlier year tells a buyer the documentation stopped being maintained — and under Art. 53 the documentation has to be kept up to date."}
]
;</script>
<script>// Model Card Lint — EU GPAI. One engine, two homes: Node (require) and the browser (window).
(function (root, factory) {
var RULES = (typeof module !== 'undefined' && module.exports) ? require('./rules.json') : root.MCL_RULES;
var api = factory(RULES || []);
if (typeof module !== 'undefined' && module.exports) module.exports = api;
root.MCLENGINE = api;
})(typeof window !== 'undefined' ? window : globalThis, function (RULES) {
var MAX_PER_RULE = 20;
function parse(text) {
var lines = String(text == null ? '' : text).split(/\r?\n/);
var fm = null, bodyStart = 0, fmEnd = 0;
if (lines.length && lines[0].trim() === '---') {
for (var i = 1; i < lines.length; i++) {
if (lines[i].trim() === '---') { fmEnd = i; bodyStart = i + 1; break; }
}
if (fmEnd) {
fm = {};
for (var j = 1; j < fmEnd; j++) {
var m = /^([A-Za-z0-9_-]+):[ \t]*(.*)$/.exec(lines[j]);
if (!m) continue;
var child = '';
for (var k = j + 1; k < fmEnd; k++) {
if (/^[ \t]+\S/.test(lines[k])) child += lines[k].trim();
else if (lines[k].trim() === '') continue;
else break;
}
fm[m[1]] = { line: j + 1, value: m[2].trim(), child: child };
}
}
}
return { lines: lines, fm: fm, fmEnd: fmEnd || 0, bodyStart: bodyStart, anchor: (fmEnd ? fmEnd + 1 : 1) };
}
function has(fm, key) {
if (!fm || !Object.prototype.hasOwnProperty.call(fm, key)) return false;
var v = fm[key];
if (v.value && v.value !== '[]' && v.value !== '{}' && v.value !== 'null') return true;
return !!v.child;
}
// A line that is still a template placeholder documents nothing — it must not satisfy a required section.
var PLACEHOLDER = /\[More Information Needed\]|\{\{|\b(TODO|TBD|FIXME|XXX)\b/i;
function lower(doc) {
return doc.lines.filter(function (l) { return !PLACEHOLDER.test(l); }).join('\n').toLowerCase();
}
function anyPresent(hay, list) {
for (var i = 0; i < (list || []).length; i++) if (hay.indexOf(String(list[i]).toLowerCase()) !== -1) return true;
return false;
}
function scanLines(doc, pattern, flags) {
var out = [], re;
try { re = new RegExp(pattern, flags || 'i'); } catch (e) { return out; }
for (var i = 0; i < doc.lines.length && out.length < MAX_PER_RULE; i++) {
if (re.test(doc.lines[i])) out.push(i + 1);
}
return out;
}
function dayDiff(from, to) {
var a = Date.parse(from + 'T00:00:00Z'), b = Date.parse(to + 'T00:00:00Z');
if (isNaN(a) || isNaN(b)) return null;
return Math.round((b - a) / 86400000);
}
function check(text, opts) {
opts = opts || {};
var today = /^\d{4}-\d{2}-\d{2}$/.test(String(opts.today || '')) ? opts.today : new Date().toISOString().slice(0, 10);
var doc = parse(text), hay = lower(doc), findings = [];
var add = function (rule, line, extra) {
findings.push({ check: rule.id, sev: rule.sev || 'error', line: line || 1, msg: rule.msg + (extra || '') });
};
RULES.forEach(function (rule) {
switch (rule.kind) {
case 'no_frontmatter':
if (!doc.fm) add(rule, 1);
break;
case 'fm_required':
if (doc.fm && !has(doc.fm, rule.key)) add(rule, doc.fmEnd || 1);
break;
case 'fm_requires_when':
if (doc.fm && has(doc.fm, rule.key) && doc.fm[rule.key].value.toLowerCase() === String(rule.equals).toLowerCase()) {
var miss = (rule.requires || []).filter(function (k) { return !has(doc.fm, k); });
if (miss.length) add(rule, doc.fm[rule.key].line, ' Missing: ' + miss.join(', ') + '.');
}
break;
case 'body_forbidden':
scanLines(doc, rule.pattern, 'i').forEach(function (ln) { add(rule, ln); });
break;
case 'empty_section':
for (var i = 0; i < doc.lines.length; i++) {
if (i + 1 <= doc.bodyStart) continue;
if (!/^#{1,6}\s+\S/.test(doc.lines[i])) continue;
var n = i + 1;
while (n < doc.lines.length && doc.lines[n].trim() === '') n++;
if (n >= doc.lines.length || /^#{1,6}\s+\S/.test(doc.lines[n])) add(rule, i + 1);
}
break;
case 'body_required':
if (!anyPresent(hay, rule.any)) add(rule, doc.anchor);
break;
case 'deadline':
if (!anyPresent(hay, rule.any)) {
var d = dayDiff(today, rule.date);
var tail = d === null ? '' : (d < 0
? ' This duty came into force on ' + rule.date + ' — ' + Math.abs(d) + ' days ago.'
: ' The date that settles it is ' + rule.date + ' — ' + d + ' days from ' + today + '.');
add(rule, doc.anchor, tail);
}
break;
case 'cond_fm':
if (doc.fm && !has(doc.fm, rule.key)) {
var hits = scanLines(doc, rule.pattern, 'i');
if (hits.length) add(rule, hits[0]);
}
break;
case 'cond_body':
var trig = scanLines(doc, rule.pattern, 'i');
if (trig.length && !anyPresent(hay, rule.any)) add(rule, trig[0]);
break;
case 'stale_year':
var yr = Number(today.slice(0, 4));
var re = /(as of|last updated|updated|current as of|version dated|valid as of)\s+(?:[a-z]+\s+)?(20\d\d)/i;
for (var q = 0; q < doc.lines.length; q++) {
var mm = re.exec(doc.lines[q]);
if (mm && Number(mm[2]) < yr) add(rule, q + 1, ' It says ' + mm[2] + '; today is ' + today + '.');
}
break;
}
});
findings.sort(function (a, b) { return a.line - b.line || String(a.check).localeCompare(String(b.check)); });
var errors = findings.filter(function (f) { return f.sev === 'error'; }).length;
return { findings: findings, errors: errors, rules_checked: RULES.length, today: today };
}
return { engine: { check: check }, RULES: RULES, RULE_COUNT: RULES.length };
});
</script>
<script>// ⛔뼈대 — kit/scaffold.py 가 찍는다 (s143). findings [{check,sev,msg,line?}] → 글/HTML. 같은 파일이 Node 와 브라우저에서 산다.
'use strict';
function escapeHtml(s) { return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;'); }
function summaryLine(res) {
const f = (res && res.findings) || []; const e = f.filter(function (x) { return String(x.sev || 'error').toLowerCase().startsWith('err'); }).length;
return f.length ? (f.length + ' finding' + (f.length === 1 ? '' : 's') + ' (' + e + ' error' + (e === 1 ? '' : 's') + ')') : 'Clean — no findings.';
}
function toText(res, label) {
const f = (res && res.findings) || [];
const lines = ['== ' + (label || '') + ' — ' + summaryLine(res)];
f.forEach(function (x) { lines.push(' ' + String(x.sev || 'error').toUpperCase().slice(0, 4) + ' ' + (x.line ? 'L' + x.line + ' ' : '') + (x.check || x.id || '') + ' ' + (x.msg || x.message || '')); });
return lines.join('\n');
}
function toHtml(res) {
const f = (res && res.findings) || [];
if (!f.length) return '<p class="ok">' + escapeHtml(summaryLine(res)) + '</p>';
const rows = f.map(function (x) { return '<tr><td class="sev ' + escapeHtml(String(x.sev || 'error')) + '">' + escapeHtml(String(x.sev || 'error')) + '</td><td>' + (x.line ? 'L' + escapeHtml(x.line) : '') + '</td><td><code>' + escapeHtml(x.check || x.id || '') + '</code></td><td>' + escapeHtml(x.msg || x.message || '') + '</td></tr>'; }).join('');
return '<p class="sum">' + escapeHtml(summaryLine(res)) + '</p><table><thead><tr><th>Level</th><th>Line</th><th>Check</th><th>What</th></tr></thead><tbody>' + rows + '</tbody></table>';
}
var MCLREPORT = { escapeHtml: escapeHtml, summaryLine: summaryLine, toText: toText, toHtml: toHtml };
if (typeof module !== 'undefined' && module.exports) module.exports = MCLREPORT;
else window.MCLREPORT = MCLREPORT;
</script>
<script>
(function(){
var src=document.getElementById('src'), out=document.getElementById('out'), go=document.getElementById('go'), today=document.getElementById('today');
today.value=new Date().toISOString().slice(0,10);
function run(){ try { var res=window.MCLENGINE.engine.check(src.value,{today:today.value}); out.innerHTML=window.MCLREPORT.toHtml(res); } catch(e){ out.innerHTML='<p class="sev error">Could not run: '+String(e.message||e)+'</p>'; } }
go.onclick=run; if (src.value.trim()) run();
})();
</script>
<section data-yj-install="free" style="margin:2rem auto 1rem;max-width:46rem;padding:1.25rem 1.25rem;border:1px solid #cfe3d6;border-radius:12px;background:#f6fbf8;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .4rem;font-size:1.2rem">Install free</h2><p style="margin:0 0 .8rem;color:#41505f">Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.</p><a href="https://marketplace.visualstudio.com/items?itemName=ReadyStack.model-card-lint-gpai" rel="noopener" data-yj-install-door="mp" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'model-card-lint-gpai',src:'mp',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">VS Code Marketplace</a><a href="https://open-vsx.org/extension/readystack/model-card-lint-gpai" rel="noopener" data-yj-install-door="ovsx" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'model-card-lint-gpai',src:'ovsx',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Open VSX (Cursor, VSCodium)</a><a href="https://www.npmjs.com/package/@readystack/model-card-lint-gpai" rel="noopener" data-yj-install-door="npm" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'model-card-lint-gpai',src:'npm',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">npm</a><a href="https://www.npmjs.com/package/@readystack/model-card-lint-gpai" rel="noopener" data-yj-install-door="mcp" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'model-card-lint-gpai',src:'mcp',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">MCP server (npx)</a><a href="https://hub.docker.com/r/getreadystack/model-card-lint-gpai" rel="noopener" data-yj-install-door="docker" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'model-card-lint-gpai',src:'docker',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Docker Hub</a><pre style="margin:.5rem 0 0;padding:.6rem .8rem;background:#f3f5f8;border-radius:8px;font-size:.9rem;overflow:auto">ext install ReadyStack.model-card-lint-gpai
npx @readystack/model-card-lint-gpai &lt;file&gt;
npx @readystack/model-card-lint-gpai --mcp</pre><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://getreadystack.com/api/buy/cl/polar_cl_l6iN1uWt0FwWu7tBsczD0jWpP2vxFM54Wdwqb3KPi1G" rel="nofollow" style="color:#0f7b3f;text-decoration:underline">Team? One key for every ReadyStack linter, 5 seats, $149 once</a></p></section>
<section data-yj-alert="rule" style="margin:1rem auto 1.5rem;max-width:46rem;padding:1.1rem 1.25rem;border:1px solid #d9dee6;border-radius:12px;background:#fbfcfd;font:15px/1.55 system-ui,-apple-system,Segoe UI,sans-serif"><b style="font-size:1.05rem">Get the full rule table as a PDF</b><div style="opacity:.78;margin:.35rem 0 .8rem">All 28 rules Model Card Lint - EU GPAI (AI Act Art. 53) checks, each with its source and date, on printable pages you can hand to your team or auditor. We email it now, and once more only if a rule changes. No newsletter.</div><div style="display:flex;gap:8px;flex-wrap:wrap"><input id="yjae" type="email" placeholder="you@example.com" style="flex:1;min-width:210px;padding:11px 13px;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:#fff;color:inherit"><button id="yjab" style="padding:11px 18px;border-radius:8px;border:0;cursor:pointer;background:#0f7b3f;color:#fff;font:600 15px system-ui,sans-serif">Email me the PDF</button></div><div id="yjao" hidden style="margin-top:.6rem;color:#0f7b3f">Sent. It arrives within the hour - check spam too.</div><script>(function(){var b=document.getElementById("yjab"),e=document.getElementById("yjae");if(!b||!e)return;b.addEventListener("click",function(){var v=e.value.trim();if(!/.+@.+\..+/.test(v))return;try{localStorage.setItem("yj_em","1");}catch(_){}fetch(location.origin+"/api/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:v,slug:"model-card-lint-gpai",lang:"en",source:"rule_table"+((b.closest&&b.closest("section")&&b.closest("section").getAttribute("data-yj-moved"))?"_at_result":"")})}).then(function(r){var o=document.getElementById("yjao");o.hidden=false;if(!r.ok){o.textContent="Could not save - please try again.";}}).catch(function(){var o=document.getElementById("yjao");o.hidden=false;o.textContent="Could not save - please try again.";});});})();</script><script>(function(){var e=document.getElementById("yjae"),s=e&&e.closest?e.closest("section"):null,o=document.getElementById("out");if(!s||!o)return;var d=false;function mv(ev){if(d)return;if(ev&&ev.target&&s.contains(ev.target))return;d=true;var b=o;while(b.parentNode&&b.parentNode!==document.body&&b.parentNode.tagName!=="MAIN"&&b.parentNode.tagName!=="ARTICLE")b=b.parentNode;if(!b.parentNode||b===s||b.contains(s))return;try{b.parentNode.insertBefore(s,b.nextSibling);s.setAttribute("data-yj-moved","1");}catch(_){}}document.addEventListener("input",mv,true);document.addEventListener("change",mv,true);})();</script></section>
<section data-yj-cta="paid" style="margin:3rem auto;max-width:46rem;padding:1.5rem 1.25rem;border:1px solid #d8dee9;border-radius:12px;background:#fbfcfe;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .5rem;font-size:1.25rem">Get the complete version <span class="yj-price">$29</span></h2><p style="margin:.25rem 0 1rem;color:#41505f">This page is the working piece. The full pack has everything below.</p><p style="margin:0 0 1rem;color:#41505f">Lints a Hugging Face model card against the Hub metadata spec and the EU AI Act general-purpose AI documentation duties, line by line.</p><p style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">An hour of an EU AI Act compliance consultant starts near $200; the Act's own ceiling for a GPAI provider is EUR 15,000,000 or 3% of worldwide annual turnover (Art. 101).</p><a href="https://getreadystack.com/api/buy/cl/polar_cl_mHiMKq8aRodhSAoK7NzNGXWSa5Nxn3sBnksN74QXeId" rel="nofollow" style="display:inline-block;padding:.7rem 1.3rem;border-radius:8px;background:#1b64f2;color:#fff;text-decoration:none;font-weight:600">Buy the full version — $29</a></section>
<!--yj-share-s101--><div style="margin:28px 0 8px;text-align:center"><button id="yjcp" type="button" style="font:inherit;padding:10px 18px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Copy link</button><button id="yjimg" type="button" style="font:inherit;padding:10px 18px;margin-left:8px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Save result as image</button></div><script>(function(){var b=document.getElementById("yjimg");if(!b)return;b.addEventListener("click",function(){var o=document.getElementById("out");var txt=(o&&(o.innerText||o.textContent)||"").trim();if(!txt){b.textContent="(no result yet)";setTimeout(function(){b.textContent="Save result as image";},1500);return;}var lines=txt.split(String.fromCharCode(10)).filter(function(x){return x.trim();}).slice(0,10);var W=1200,P=56,c=document.createElement("canvas");c.width=W;var lh=38,H=P*2+70+lines.length*lh+60;c.height=H;var x=c.getContext("2d");x.fillStyle="#1a1512";x.fillRect(0,0,W,H);x.fillStyle="#f3e9d2";x.font="600 34px system-ui,Segoe UI,Arial";var t=(document.title||"").split("|")[0].trim();x.fillText(t.slice(0,54),P,P+34);x.font="22px ui-monospace,Menlo,Consolas,monospace";x.fillStyle="#e8dcc4";for(var i=0;i<lines.length;i++){x.fillText(lines[i].slice(0,88),P,P+70+i*lh+22);}x.font="600 22px system-ui,Segoe UI,Arial";x.fillStyle="#c9a227";var d=location.hostname.replace("www.","");x.fillText(d,W-P-x.measureText(d).width,H-P+6);c.toBlob(function(bl){var u=URL.createObjectURL(bl),a=document.createElement("a");a.href=u;a.download=(t||"result").replace(/[^a-z0-9]+/gi,"-").toLowerCase()+"-"+d+".png";document.body.appendChild(a);a.click();setTimeout(function(){URL.revokeObjectURL(u);a.remove();},2000);},"image/png");});})();</script><script>(function(){var b=document.getElementById("yjcp");if(!b)return;var t=b.textContent;b.addEventListener("click",function(){var u=location.href.split("#")[0];function d(){b.textContent="Link copied";setTimeout(function(){b.textContent=t;},1800);}if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(u).then(d,function(){prompt("",u);});}else{prompt("",u);}});})();</script><div class="yj-home-find"><div class="yj-lgbar"><a href="/" class="yj-lg on">EN</a><a href="/de/" class="yj-lg">DE</a><a href="/ja/" class="yj-lg">JA</a><a href="/es/" class="yj-lg">ES</a><a href="/pt/" class="yj-lg">PT</a></div><section class="yj-find"><h2>Find a tool</h2><input id="yjq" type="search" autocomplete="off" placeholder="Type a product name, format or task"><div id="yjr"></div></section><style>.yj-lgbar{position:absolute;top:14px;right:18px;display:flex;gap:6px;z-index:60}.yj-lg{font:600 12px/1 system-ui,sans-serif;padding:6px 9px;border-radius:4px;text-decoration:none;color:#8b96a3;border:1px solid rgba(140,150,165,.28)}.yj-lg:hover{color:#e8eaed;border-color:rgba(160,175,195,.6)}.yj-lg.on{color:#0e1116;background:#cfd6de;border-color:#cfd6de}.yj-find{max-width:760px;margin:34px auto 8px;padding:0 20px}.yj-find h2{font:600 20px/1.3 system-ui,sans-serif;margin:0 0 10px}#yjq{width:100%;box-sizing:border-box;padding:13px 15px;font:400 15.5px system-ui,sans-serif;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:rgba(255,255,255,.04);color:inherit}#yjq:focus{outline:none;border-color:#7FD1C4}#yjr{margin-top:10px;display:flex;flex-direction:column;gap:6px}#yjr a{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;border:1px solid rgba(140,150,165,.22);border-radius:6px;text-decoration:none;font:400 14.5px/1.4 system-ui,sans-serif;color:inherit}#yjr a:hover{border-color:#7FD1C4}#yjr .pr{font:600 13px system-ui,sans-serif;color:#5fbf9a;white-space:nowrap}</style><script>(function(){var q=document.getElementById("yjq"),r=document.getElementById("yjr"),D=null;function load(){if(D)return Promise.resolve(D);return fetch("/search-index.json").then(function(x){return x.json();}).then(function(j){D=j;return j;}).catch(function(){D=[];return D;});}function esc(t){return String(t).replace(/[&<>"]/g,function(c){return {"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"}[c];});}function run(){var v=q.value.trim().toLowerCase();if(v.length<2){r.innerHTML="";return;}load().then(function(j){var w=v.split(/\s+/),o=[];for(var i=0;i<j.length&&o.length<12;i++){var t=j[i].t.toLowerCase();var ok=true;for(var k=0;k<w.length;k++){if(t.indexOf(w[k])<0){ok=false;break;}}if(ok)o.push(j[i]);}r.innerHTML=o.length?o.map(function(x){return "<a href=\""+esc(x.u)+"\">"+"<span>"+esc(x.t)+"</span>"+(x.p?"<span class=\"pr\">$"+x.p+"</span>":"")+"</a>";}).join(""):"";});}q.addEventListener("input",run);q.addEventListener("focus",load);})();</script></div>
<script data-yj="yj-view-beacon">(function(){try{var p=location.pathname;var k='yjv:'+p;if(sessionStorage.getItem(k))return;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",ref:(document.referrer||''),src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}catch(e){}})();</script>
<script data-yj="yj-use-beacon">(function(){try{var o=document.getElementById('out');if(!o)return;var p=location.pathname,k='yju:'+p,sent=false;function fire(){if(sent||sessionStorage.getItem(k))return;if(!(o.textContent||'').replace(/\s+/g,'').length)return;sent=true;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",t:'use',src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}var mo=new MutationObserver(function(){fire();if(sent)mo.disconnect();});mo.observe(o,{childList:true,characterData:true,subtree:true});}catch(e){}})();</script>
<section data-yj="yj-facts-v1" style="max-width:920px;margin:48px auto 0;padding:0 20px;font-family:system-ui,sans-serif"><style>.yj-article p{font:400 15.5px/1.7 system-ui,sans-serif;color:#26313b;margin:0 0 12px;max-width:72ch}.yj-article h2,.yj-article h3,.yj-article h4{font:600 17px/1.35 system-ui,sans-serif;color:#1b1f24;margin:22px 0 8px}.yj-article table{border-collapse:collapse;margin:10px 0 16px;font:14px/1.45 system-ui,sans-serif}.yj-article th,.yj-article td{border:1px solid #e2e6ea;padding:6px 10px;text-align:left}.yj-article th{background:#f4f6f8}.yj-article pre{background:#0f1720;color:#e6edf3;padding:12px 14px;border-radius:8px;overflow:auto;font:13px/1.5 ui-monospace,Menlo,monospace}.yj-article code{font:13px ui-monospace,Menlo,monospace;background:#f1f3f5;padding:1px 4px;border-radius:3px}.yj-article pre code{background:none;padding:0}.yj-article ul,.yj-article ol{font:15px/1.6 system-ui,sans-serif;color:#26313b}</style><p style="font:400 13px/1.5 system-ui,sans-serif;color:#6b7680;margin:0 0 14px"><time datetime="2026-09-13">Updated 2026-09-13</time> · ReadyStack</p><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","dateModified":"2026-09-13","author":{"@type":"Organization","name":"ReadyStack"}}</script><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Worked example</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 16px;color:#5b6570">Real numbers from this tool, line by line.</p><div class="yj-article"><p><img src="https://getreadystack.com/img/promo/sku48562_result_card.jpg" alt="Model Card Lint - EU GPAI (AI Act Art. 53)" loading="lazy" style="max-width:100%;border-radius:6px"></p>
<p>Six lines in a 34-line German clinical model card, and an EU reviewer has enough to send it back. The card belonged to a Berlin ML engineer who was one commit from publishing: run the check over it and 29 findings come back, 12 of them errors, across 25 of the 28 rules.</p>
<p>None of the six were hard. <code>license: other</code> was declared with neither <code>license_name</code> nor <code>license_link</code>, so the Hub has terms it cannot resolve. <code>tags:</code> sat there with nothing under it. Four lines still read <code>[More Information Needed]</code> — the Hugging Face template&#x27;s own placeholder, saying in writing that the section was never filled in. One line still carried an unrendered <code>{{ base_model }}</code>. <code>## Uses</code> had another heading directly beneath it. And nowhere in the file was there a summary of training content.</p>
<p>That last one is the one with a date on it. The EU AI Act&#x27;s obligations for providers of general-purpose AI models sit in Article 53: a policy to comply with Union copyright law, including honouring machine-readable text-and-data-mining rights reservations, and a sufficiently detailed public summary of the content used for training, written on the Commission&#x27;s template. As of 12 September 2026 that duty has been in force for 41 days. Models placed on the EU market before 2 August 2025 have until 2 August 2027 — 324 days from today — and everything after that is already due. A model card that never states when the model was placed on the market never says which of the two clocks it is on.</p>
<h3>Why the obvious tool does not do this</h3>
<p>The obvious move is to paste the card into a chatbot and ask it to improve the documentation. It returns better prose. It does not count. It will not tell you there are four <code>[More Information Needed]</code> lines left, because counting is not what it is doing; it will not know that <code>license: other</code> needs two more keys, because that is a Hub rule and not a language rule; and asked which article carries the training-content summary, it will give you an article number in a confident sentence that may simply be wrong. A compliance checklist has to be reproducible; a generated answer is not.</p>
<h3>What the 28 rules are</h3>
<p>Nine are Hub metadata: the frontmatter block itself, <code>license</code>, the <code>license_name</code> + <code>license_link</code> pair that <code>license: other</code> drags in, <code>pipeline_tag</code>, <code>library_name</code>, <code>language</code>, <code>datasets</code>, <code>tags</code>, <code>model-index</code>. Five are template leftovers: <code>[More Information Needed]</code>, unrendered <code>{{ ... }}</code>, TODO markers, <code>your-username/</code> placeholders, and a heading with nothing under it. A line that is still a placeholder is also struck out before every other rule reads the file, so <code><strong>Developed by:</strong> [More Information Needed]</code> does not count as having named a provider.</p>
<p>Eleven are the AI Act GPAI duties: training-content summary, copyright policy, provider identity, intended use, out-of-scope use, evaluation, limitations and bias, energy consumption, training compute against the Article 51 presumption at 10^25 FLOP, the authorised representative Article 54 asks of a provider established outside the Union, and the placing-on-the-market date. Three are provenance and staleness, including an &quot;as of 2025&quot; line that has outlived its year.</p>
<h3>Calibration</h3>
<p>Two fixtures ship with it. <code>_fixtures/clean.md</code> returns 0 findings; <code>_fixtures/dirty.md</code>, 34 lines, returns 29 findings and 12 errors. Change the date in the box and the two date-aware rules change with it.</p>
<p>Linting the card you have open is free, every rule, nothing uploaded. The licence buys scope: every card in the repository in one pass, exported as Markdown and as JSON a CI step can fail on.</p></div><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:30px 0 10px;color:#1b1f24">15 seconds — what it actually does</h2><video controls muted playsinline preload="none" poster="/img/promo/sku48562_result_card.jpg" style="width:100%;max-width:360px;border-radius:10px;display:block;margin:0 auto"><source src="/media/sku48562_short.mp4" type="video/mp4"></video><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:34px 0 6px;color:#1b1f24">Questions people ask</h2><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does Model Card Lint actually check?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads the Markdown model card you have open and applies 28 rules: 9 on Hugging Face Hub frontmatter, 5 on template leftovers such as [More Information Needed], 11 on EU AI Act general-purpose AI duties, and 3 on provenance and staleness. Each finding carries a line number, the rule id, the article behind it, and the line to write instead.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Who is this for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">ML engineers and MLOps leads who publish models on the Hugging Face Hub or fine-tune one for a product that reaches EU users, and the person who has to sign the model off. If you have ever pasted the Hub template and shipped it with the sections half filled, this is aimed at you.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why will a chatbot not do this?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">A general model rewrites your prose and leaves the gaps. It does not count the four [More Information Needed] left in the file, it does not know that license: other needs license_name and license_link too, and it invents article numbers with total confidence. This runs 28 fixed rules and returns the same count every time.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What is free and what needs a licence?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Linting the card you have open is free forever, every rule, no key and no account, in the editor or in the browser. The licence is for scope and ownership: sweeping every model card in a repository in one pass, and exporting the dated audit as Markdown and as JSON a CI step can fail on.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What would this cost otherwise?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">An hour of an EU AI Act compliance consultant starts near $200, and a documentation review covers one model. The extension is $29 once, one licence key per person or CI seat,. The Act&#x27;s own ceiling for a GPAI provider is EUR 15,000,000 or 3% of worldwide annual turnover.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why not just ask ChatGPT or another AI chat?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. Model Card Lint - Hugging Face model card and EU GPAI (Art. checks the file you open against 28 rules from a rule set dated 2026-09-20, and points at the exact line. For a filing, an audit or a client you need that dated result on your own files.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does Model Card Lint actually check?", "acceptedAnswer": {"@type": "Answer", "text": "It reads the Markdown model card you have open and applies 28 rules: 9 on Hugging Face Hub frontmatter, 5 on template leftovers such as [More Information Needed], 11 on EU AI Act general-purpose AI duties, and 3 on provenance and staleness. Each finding carries a line number, the rule id, the article behind it, and the line to write instead."}}, {"@type": "Question", "name": "Who is this for?", "acceptedAnswer": {"@type": "Answer", "text": "ML engineers and MLOps leads who publish models on the Hugging Face Hub or fine-tune one for a product that reaches EU users, and the person who has to sign the model off. If you have ever pasted the Hub template and shipped it with the sections half filled, this is aimed at you."}}, {"@type": "Question", "name": "Why will a chatbot not do this?", "acceptedAnswer": {"@type": "Answer", "text": "A general model rewrites your prose and leaves the gaps. It does not count the four [More Information Needed] left in the file, it does not know that license: other needs license_name and license_link too, and it invents article numbers with total confidence. This runs 28 fixed rules and returns the same count every time."}}, {"@type": "Question", "name": "What is free and what needs a licence?", "acceptedAnswer": {"@type": "Answer", "text": "Linting the card you have open is free forever, every rule, no key and no account, in the editor or in the browser. The licence is for scope and ownership: sweeping every model card in a repository in one pass, and exporting the dated audit as Markdown and as JSON a CI step can fail on."}}, {"@type": "Question", "name": "What would this cost otherwise?", "acceptedAnswer": {"@type": "Answer", "text": "An hour of an EU AI Act compliance consultant starts near $200, and a documentation review covers one model. The extension is $29 once, one licence key per person or CI seat,. The Act's own ceiling for a GPAI provider is EUR 15,000,000 or 3% of worldwide annual turnover."}}, {"@type": "Question", "name": "Why not just ask ChatGPT or another AI chat?", "acceptedAnswer": {"@type": "Answer", "text": "A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. Model Card Lint - Hugging Face model card and EU GPAI (Art. checks the file you open against 28 rules from a rule set dated 2026-09-20, and points at the exact line. For a filing, an audit or a client you need that dated result on your own files."}}]}</script><div id="yj-ask" style="margin:36px 0 0;padding:18px 18px 16px;border:1px solid #e2e6ea;border-radius:10px;background:#fbfbfc"><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:0 0 4px;color:#1b1f24">Ask about this tool</h2><p style="font:400 13.5px/1.5 system-ui,sans-serif;margin:0 0 12px;color:#5b6570">One question, answered by the person who built it. Your email only if you want the answer sent.</p><form onsubmit="return yjAsk(event)" style="display:grid;gap:8px"><textarea name="question" required minlength="10" maxlength="2000" rows="3" placeholder="Your question" style="font:14px/1.5 system-ui,sans-serif;padding:10px;border:1px solid #cfd6dd;border-radius:6px"></textarea><div style="display:flex;gap:8px;flex-wrap:wrap"><input type="email" name="email" placeholder="Email (optional)" style="flex:1;min-width:200px;font:14px system-ui,sans-serif;padding:9px 10px;border:1px solid #cfd6dd;border-radius:6px"><button type="submit" style="font:600 14px system-ui,sans-serif;padding:9px 18px;border:0;border-radius:6px;background:#1b1f24;color:#fff;cursor:pointer">Send</button></div><p id="yj-ask-msg" style="font:13px system-ui,sans-serif;margin:2px 0 0;color:#0a6238;min-height:1em"></p></form><script>function yjAsk(e){e.preventDefault();var f=e.target,m=document.getElementById("yj-ask-msg");m.style.color="#0a6238";fetch(location.origin+"/api/ask",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sku:48562,slug:"model-card-lint-gpai",lang:"en",question:f.question.value,email:f.email.value,page:location.pathname})}).then(function(r){if(!r.ok)throw 0;m.textContent="Thanks \u2014 noted. Answers land on this page and, if you left an email, in your inbox.";f.question.value="";}).catch(function(){m.style.color="#a8551f";m.textContent="Could not send. Please try again in a minute.";});return false;}</script></div></section><section class="yj-related" style="max-width:920px;margin:56px auto 40px;padding:0 20px"><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Same job, next tool</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 20px;color:#5b6570">Free in the browser. The full version is a one-time licence.</p><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px"><a class="yj-rel-c" href="https://getreadystack.com/tools/huggingface-model-license-matrix"><span class="yj-rel-t">Hugging Face Model Licence Matrix — all 70 model-card `license:` identifiers ×</span><span class="yj-rel-p">$4.99</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/ai-disclosure-lint-sb942"><span class="yj-rel-t">AI Output Disclosure Lint SB 942</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/n8n-social-media-workflow-agency-content-approval"><span class="yj-rel-t">n8n Social Media Workflow for Agency Content Approval — 6 Client Sign-Off Auto</span><span class="yj-rel-p">$59</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/ai-model-license-lint"><span class="yj-rel-t">AI Model License Lint</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/ai-model-retirement-lint"><span class="yj-rel-t">AI Model Retirement Lint</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/accessibility-statement-lint"><span class="yj-rel-t">Accessibility Statement Lint (EU model)</span><span class="yj-rel-p">$29</span></a></div><style>.yj-rel-c{display:flex;flex-direction:column;gap:8px;padding:15px 16px;border:1px solid #e2e6ea;border-radius:6px;text-decoration:none;background:#fff}.yj-rel-c:hover{border-color:#b9c2cb;background:#fafbfc}.yj-rel-t{font:500 14.5px/1.42 system-ui,sans-serif;color:#1b1f24}.yj-rel-p{font:600 13px system-ui,sans-serif;color:#0a6238}</style></section></body>
</html>