SaferSkills independently audited prototype-annotation-skill (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.
════════════════════════════════════════════════════════════ 第零步:内容盘点(静默执行,写入注释) ════════════════════════════════════════════════════════════
在输出 HTML 之前,请在内部完成以下内容盘点,将结果以 <!-- --> 注释写入 HTML 文件头部,直接进入第一步,无需等待我确认:
内容盘点完成后,立即进入自查流程:逐项核对原型中的每一个页面、每一个弹窗、每一个组件是否已被完整记录,若发现遗漏立即补全,确认无误后方可开始输出 HTML。
════════════════════════════════════════════════════════════ 第一步:分批自动输出(无需等待我回复) ════════════════════════════════════════════════════════════
分批规则(自动连续执行,不等待我的任何指令):
════════════════════════════════════════════════════════════ 第二步:原型内容输出(零删减原则) ════════════════════════════════════════════════════════════
以下为最高优先级要求,任何情况下不得违反。违反任意一条均视为输出不合格,必须自行重新输出对应区块:
原型内容零删减:
════════════════════════════════════════════════════════════ 第三步:页面布局结构 ════════════════════════════════════════════════════════════
每个页面区块结构如下,严格按此实现:
---------- HTML 结构 ----------
<div class="page-canvas"> <section class="page-block"> <div class="page-label">页面一:首页</div> <div class="page-inner"> <div class="proto-area"> <div class="proto-inner"> <!-- 完整原型 HTML,零删减 --> </div> </div> <div class="annotation-area"> <!-- 标注卡片 --> </div> </div> </section> </div>
---------- 关键 CSS 规则 ----------
box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: #e8eaed; overflow-x: hidden; }
.page-canvas { width: 100%; padding: 32px 16px; }
.page-block { position: relative; width: 100%; background: #f0f2f5; border-radius: 12px; padding: 36px 20px; margin-bottom: 48px; break-inside: avoid; }
.page-label { font-size: 15px; font-weight: bold; color: #fff; background: #1a1a2e; display: inline-block; padding: 6px 16px; border-radius: 20px; margin-bottom: 20px; }
.page-inner { display: flex; flex-direction: row; align-items: flex-start; width: 100%; position: relative; }
/ 原型区:70%,内容不压缩不裁切 / .proto-area { width: 70%; min-width: 70%; flex-shrink: 0; position: relative; z-index: 1; background: #fff; border-radius: 8px; box-shadow: 0 2px 12px rgba(0,0,0,0.08); padding: 16px; overflow: visible; }
.proto-inner { transform-origin: top left; }
/ 标注区:30% / .annotation-area { width: 30%; min-width: 30%; position: relative; z-index: 100; padding-left: 16px; }
/ 折叠态卡片 / .annot-card { position: absolute; width: calc(100% - 16px); z-index: 100; transition: box-shadow 0.2s; }
.annot-card:hover { z-index: 500; }
.annot-card-collapsed { display: flex; align-items: center; background: #fff; border-radius: 8px; padding: 8px 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); cursor: pointer; gap: 8px; transition: box-shadow 0.2s; }
.annot-card:hover .annot-card-collapsed { box-shadow: 0 6px 20px rgba(0,0,0,0.18); }
.annot-card[data-color="blue"] .annot-card-collapsed { border-left: 4px solid #4A90E2; } .annot-card[data-color="orange"] .annot-card-collapsed { border-left: 4px solid #F5A623; } .annot-card[data-color="green"] .annot-card-collapsed { border-left: 4px solid #27AE60; } .annot-card[data-color="red"] .annot-card-collapsed { border-left: 4px solid #E74C3C; }
.annot-number { width: 20px; height: 20px; border-radius: 50%; color: #fff; font-size: 11px; font-weight: bold; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.annot-card[data-color="blue"] .annot-number { background: #4A90E2; } .annot-card[data-color="orange"] .annot-number { background: #F5A623; } .annot-card[data-color="green"] .annot-number { background: #27AE60; } .annot-card[data-color="red"] .annot-number { background: #E74C3C; }
.annot-title { font-weight: bold; font-size: 13px; color: #1a1a2e; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.annot-toggle-icon { font-size: 16px; color: #999; font-weight: bold; transition: transform 0.2s; flex-shrink: 0; }
.annot-card.is-open .annot-toggle-icon { transform: rotate(45deg); color: #555; }
/ 展开态:fixed 定位,z-index 最高 / .annot-card-expanded { display: none; position: fixed; width: 360px; background: #fff; border-radius: 8px; padding: 14px 16px; box-shadow: 0 8px 28px rgba(0,0,0,0.2); z-index: 9999; border-top: 2px solid currentColor; }
.annot-card.is-open .annot-card-expanded { display: block; }
.annot-trigger { font-size: 12px; color: #888; margin-bottom: 8px; line-height: 1.6; padding-bottom: 8px; border-bottom: 1px solid #f0f0f0; }
.annot-detail { font-size: 13px; color: #333; line-height: 1.8; margin-top: 8px; }
/ 标注区镜像序号徽标,与折叠卡片垂直对齐 / .annot-mirror-badge { position: absolute; left: -8px; width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; color: #fff; z-index: 200; box-shadow: 0 2px 6px rgba(0,0,0,0.2); pointer-events: none; } .annot-mirror-badge[data-color="blue"] { background: #4A90E2; } .annot-mirror-badge[data-color="orange"] { background: #F5A623; } .annot-mirror-badge[data-color="green"] { background: #27AE60; } .annot-mirror-badge[data-color="red"] { background: #E74C3C; }
/ 原型区序号徽标 / .annot-badge { position: absolute; top: -10px; right: -10px; width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; color: #fff; z-index: 200; cursor: pointer; box-shadow: 0 2px 6px rgba(0,0,0,0.2); transition: transform 0.2s; } .annot-badge:hover { transform: scale(1.15); } .annot-badge[data-color="blue"] { background: #4A90E2; } .annot-badge[data-color="orange"] { background: #F5A623; } .annot-badge[data-color="green"] { background: #27AE60; } .annot-badge[data-color="red"] { background: #E74C3C; }
════════════════════════════════════════════════════════════ 第四步:标注内容(详尽丰富,禁止省略) ════════════════════════════════════════════════════════════
标注内容输出标准:
════════════════════════════════════════════════════════════ 第五步:标注定位与交互 ════════════════════════════════════════════════════════════
---------- 标注卡片 HTML 结构 ----------
<div class="annot-card" data-color="blue" data-num="1"> <div class="annot-card-collapsed"> <span class="annot-number">1</span> <span class="annot-title">全局检索机制</span> <span class="annot-toggle-icon">+</span> </div> <div class="annot-card-expanded"> <div class="annot-trigger">触发条件:...</div> <div class="annot-detail">详细说明:...</div> </div> </div>
---------- JS:定位 + 防重叠 + 悬停置顶 + 展开交互 ----------
window.addEventListener('load', () => { setTimeout(() => {
document.querySelectorAll('.page-block').forEach(block => { const blockTop = block.getBoundingClientRect().top + window.scrollY; const inner = block.querySelector('.page-inner'); const innerTop = inner.offsetTop; const annotArea = block.querySelector('.annotation-area'); const protoArea = block.querySelector('.proto-area'); const protoInner = block.querySelector('.proto-inner');
// Step1:等比缩放原型内容,消除横向滚动条 if (protoInner) { const containerWidth = protoArea.clientWidth - 32; const contentWidth = protoInner.scrollWidth; if (contentWidth > containerWidth) { const scale = containerWidth / contentWidth; protoInner.style.transform = 'scale(' + scale + ')'; protoInner.style.width = contentWidth + 'px'; protoArea.style.height = (protoInner.scrollHeight * scale + 32) + 'px'; } }
// Step2:收集所有徽标的目标 top,按序号升序排序 const items = []; block.querySelectorAll('.annot-badge').forEach(badge => { const num = parseInt(badge.dataset.num); const card = block.querySelector('.annot-card[data-num="' + num + '"]'); if (!card) return; const badgeRect = badge.getBoundingClientRect(); const rawTop = badgeRect.top + window.scrollY - blockTop - innerTop - 11; items.push({ badge, card, rawTop: Math.max(0, rawTop), num }); }); items.sort((a, b) => a.num - b.num);
// Step3:防重叠,折叠卡片按序号升序排列,间距至少12px // 同时在标注区生成与卡片对齐的镜像徽标 const CARD_HEIGHT = 44; const GAP = 12; let lastBottom = -Infinity;
items.forEach(({ badge, card, rawTop, num }) => { const cardTop = Math.max(rawTop, lastBottom + GAP); card.style.top = cardTop + 'px'; lastBottom = cardTop + CARD_HEIGHT;
const mirrorBadge = document.createElement('span'); mirrorBadge.className = 'annot-mirror-badge'; mirrorBadge.textContent = num; mirrorBadge.dataset.color = badge.dataset.color; mirrorBadge.style.top = (cardTop + CARD_HEIGHT / 2 - 11) + 'px'; annotArea.appendChild(mirrorBadge); });
// Step4:同步标注区最小高度 annotArea.style.minHeight = protoArea.offsetHeight + 'px'; });
// 悬停预览:挂载在 body 的全局单例浮层,z-index:99999,不受任何层叠上下文限制 const hoverPreview = document.createElement('div'); hoverPreview.id = 'hover-preview'; hoverPreview.style.cssText = [ 'display:none', 'position:fixed', 'width:360px', 'background:#fff', 'border-radius:8px', 'padding:14px 16px', 'box-shadow:0 8px 28px rgba(0,0,0,0.22)', 'z-index:99999', 'pointer-events:none', 'border-left:4px solid #ccc', 'font-size:13px', 'line-height:1.8', 'color:#333', 'max-height:400px', 'overflow-y:auto' ].join(';'); document.body.appendChild(hoverPreview);
let hoverTimer = null; const colorMap = { blue: '#4A90E2', orange: '#F5A623', green: '#27AE60', red: '#E74C3C' };
document.querySelectorAll('.annot-card-collapsed').forEach(header => { const card = header.closest('.annot-card'); const color = card.dataset.color;
// 悬停展示预览浮层 header.addEventListener('mouseenter', () => { hoverTimer = setTimeout(() => { const trigger = card.querySelector('.annot-trigger')?.innerHTML || ''; const detail = card.querySelector('.annot-detail')?.innerHTML || ''; const title = card.querySelector('.annot-title')?.textContent || ''; const num = card.dataset.num; const hex = colorMap[color] || '#ccc';
hoverPreview.style.borderLeftColor = hex; hoverPreview.innerHTML = '<div style="font-weight:bold;font-size:14px;color:#1a1a2e;margin-bottom:8px;display:flex;align-items:center;gap:8px;">' + '<span style="width:20px;height:20px;border-radius:50%;background:' + hex + ';color:#fff;font-size:11px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;">' + num + '</span>' + title + '</div>' + '<div style="font-size:12px;color:#888;margin-bottom:8px;padding-bottom:8px;border-bottom:1px solid #f0f0f0;">' + trigger + '</div>' + '<div>' + detail + '</div>';
const rect = header.getBoundingClientRect(); const viewportHeight = window.innerHeight; const spaceBelow = viewportHeight - rect.bottom;
hoverPreview.style.left = rect.left + 'px'; hoverPreview.style.width = Math.min(360, window.innerWidth - rect.left - 16) + 'px';
if (spaceBelow >= 280) { hoverPreview.style.top = (rect.bottom + 6) + 'px'; hoverPreview.style.bottom = 'auto'; } else { hoverPreview.style.top = 'auto'; hoverPreview.style.bottom = (viewportHeight - rect.top + 6) + 'px'; }
hoverPreview.style.display = 'block'; }, 200); });
header.addEventListener('mouseleave', () => { clearTimeout(hoverTimer); hoverPreview.style.display = 'none'; });
// 点击展开 header.addEventListener('click', (e) => { e.stopPropagation(); hoverPreview.style.display = 'none'; const isOpen = card.classList.contains('is-open'); document.querySelectorAll('.annot-card.is-open').forEach(c => c.classList.remove('is-open')); if (!isOpen) { card.classList.add('is-open'); positionExpanded(card); } }); });
function positionExpanded(card) { const expanded = card.querySelector('.annot-card-expanded'); const header = card.querySelector('.annot-card-collapsed'); const rect = header.getBoundingClientRect(); const expandedHeight = expanded.scrollHeight || 280; const viewportHeight = window.innerHeight; const spaceBelow = viewportHeight - rect.bottom; const spaceAbove = rect.top;
expanded.style.left = rect.left + 'px'; expanded.style.width = Math.min(360, window.innerWidth - rect.left - 16) + 'px';
if (spaceBelow >= expandedHeight || spaceBelow >= spaceAbove) { expanded.style.top = (rect.bottom + 6) + 'px'; expanded.style.bottom = 'auto'; expanded.style.borderRadius = '0 0 8px 8px'; } else { expanded.style.top = 'auto'; expanded.style.bottom = (viewportHeight - rect.top + 6) + 'px'; expanded.style.borderRadius = '8px 8px 0 0'; } }
document.addEventListener('click', (e) => { if (!e.target.closest('.annot-card')) { document.querySelectorAll('.annot-card.is-open').forEach(c => c.classList.remove('is-open')); } });
window.addEventListener('scroll', () => { const openCard = document.querySelector('.annot-card.is-open'); if (openCard) positionExpanded(openCard); hoverPreview.style.display = 'none'; }, { passive: true });
}, 150); });
════════════════════════════════════════════════════════════ 最终自查清单(强制执行,不通过则自动修正) ════════════════════════════════════════════════════════════
全部内容输出完成后,必须逐项执行以下自查。每一项结果写入 HTML 尾部注释。凡标记为不通过的项,必须立即定位对应区块并重新输出修正版本,修正完成后再次执行该项自查,直至全部通过为止:
<!-- 最终自查结果:
【内容完整性】
【标注质量】
【布局与交互】
所有项目均通过后,输出完成。 -->
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.