ship-feed — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ship-feed (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 shipping log is great prose, but prose can't be embedded, subscribed to, or read by code. This skill makes the same release history machine-readable and embeddable:
docs/changelog.json — structured releases (version, date, title, summary, items by category)docs/changelog.xml — an RSS 2.0 (or Atom 1.0) feed of releases, for feed readers + botsdocs/ship-changelog.js — a self-contained <ship-changelog> web component (full or badge)docs/whats-new.embed.html — a static, data-inlined page for an <iframe> or a no-JS hostAll four are static, brand-themed from docs/brand.json, and derive from one source of truth — your existing shipping log. Write the prose once (with shipping-log); syndicate it everywhere.
ship-feed is the distribution layer of the docs + release pack. It consumes what the other skills produce; it never invents content.
docs/VERSION ── single semver anchor ──┐
docs/brand.json ── brand as data ───────┤
docs/SHIPPING-LOG.md (← shipping-log) │
│ parse │
▼ ▼
docs/changelog.json ──► docs/changelog.xml (RSS/Atom feed)
│ ──► docs/ship-changelog.js (<ship-changelog> component)
│ ──► docs/whats-new.embed.html (iframe / no-JS embed)docs/SHIPPING-LOG.md and the prosedocs/whats-new.html. Run it first — this skill parses its output. If the log is missing, stop and offer to run it.
share the same docs/VERSION anchor so "what changed" and "how it works" stay in lockstep.
docs/brand.json.The widget links and the feed point back to whats-new.html#v<version>, so the data layer and the prose page reinforce each other.
Before generating anything, inspect what already exists and report it:
node <skill>/scripts/version.mjs get → current semver (or "no anchor").docs/brand.json (colors + fonts). If absent, the renderers fall back to a neutralslate+blue theme (never purple) — note that in your report and offer to create brand.json.
ls docs/SHIPPING-LOG.md — required. If missing, stop and offer to run shipping-log.docs/whats-new.embed.html` — note what you'll be regenerating so the user knows what changes.
want RSS or Atom, and whether they need the component, the iframe embed, or both.
version.mjs is shared with the pack — call it, don't reinvent version handling.
Run scripts from the repo root; reference them by absolute skill path. They are dependency-free .mjs (Node ≥ 16, cross-platform) — run them, never inline their logic.
node <skill>/scripts/parse-changelog.mjs --pretty --site-url https://<your-site>Reads docs/SHIPPING-LOG.md (+ docs/VERSION, docs/brand.json), writes docs/changelog.json. It prints N release(s), M item(s). Read the printed counts — if it warns "parsed 0 releases", the log isn't in the pack's ## v1.2.3 — YYYY-MM-DD shape; fix the headings (or regenerate via shipping-log) rather than hand-editing JSON.
node <skill>/scripts/emit-feed.mjs --format rss --site-url https://<your-site>
# Atom instead: --format atom --out docs/changelog.atom.xmlOne <item>/<entry> per release; categories become <category> tags; the release body is HTML-in-CDATA so readers render it. Pass --site-url for portable absolute links.
node <skill>/scripts/render-widget.mjs --mode bothWrites docs/ship-changelog.js (the <ship-changelog> component) and docs/whats-new.embed.html (static embed). Both are themed from docs/brand.json. Use --mode component or --mode page to emit just one. --src <url> sets the JSON URL the component fetches at runtime (default ./changelog.json).
node --check docs/ship-changelog.js (valid JS).<item> open/close counts match in the XML and that --site-url produced absolutelinks.
backdrop-filter / feTurbulence — there must be none in realCSS (they hang renderers).
changelog.json stats against the log (release + item counts).references/embedding.md and give the user the exact snippets for theircase: company-page component, in-app badge (badge limit="1" + the unread-dot pattern), the <iframe> embed, and the <link rel="alternate"> feed auto-discovery tag.
brand.jsonthemed it or defaults were used, whether links are absolute (site URL known) or relative, and which categories appeared. If you regenerated existing files, say so.
Input — docs/SHIPPING-LOG.md (MyFieldTime), heading + first bullet:
## v0.8.0 — 2026-06-17 · Money & decisions
_The homeowner finally sees the money — and signs off without the email chase._
### ✨ New
- **Money & Progress portal for homeowners.** Clients open one page to see how much of the
budget is spent, what's left, and how far along the job is — no spreadsheet, no phone call.Run: parse-changelog.mjs --pretty --site-url https://myfieldtime.com
Output — docs/changelog.json (excerpt): 3 release(s), 18 item(s), the bold lead split from its body, the italic line captured as summary:
{
"$schema": "ship-feed/changelog@1",
"product": "MyFieldTime", "tagline": "Run your jobs. Not your inbox.",
"currentVersion": "0.8.0",
"stats": { "releases": 3, "items": 18, "latestVersion": "0.8.0", "latestDate": "2026-06-17" },
"releases": [{
"version": "0.8.0", "date": "2026-06-17", "title": "Money & decisions", "id": "v0.8.0",
"summary": "The homeowner finally sees the money — and signs off without the email chase.",
"items": [{
"category": "new",
"title": "Money & Progress portal for homeowners",
"body": "Clients open one page to see how much of the budget is spent, what's left, and how far along the job is — no spreadsheet, no phone call."
}]
}]
}Then emit-feed.mjs turns the same release into:
<item>
<title>MyFieldTime 0.8.0 — Money & decisions</title>
<link>https://myfieldtime.com/whats-new.html#v0.8.0</link>
<guid isPermaLink="false">v0.8.0</guid>
<pubDate>Wed, 17 Jun 2026 12:00:00 GMT</pubDate>
<category>new</category> …
</item>…and render-widget.mjs themes the <ship-changelog> component with MyFieldTime's tokens (--sc-brand: #2f7dff; --sc-accent: #FFDD00;) — on-brand, never purple.
Hold the output to this standard before you call it done:
SHIPPING-LOG.md. The scriptsparse; they never write copy. If the data looks thin, the log is thin — fix it upstream with shipping-log, don't pad the JSON.
references/data-contract.md, carries $schema,newest-first releases, canonical category ids. A downstream app can depend on its shape.
links are absolute when a site URL is known. It validates in a feed reader.
colors + fonts from brand.json, exposes --sc-* tokens for host overrides, and defaults to a neutral slate+blue — never purple. No `backdrop-filter`, no SVG `feTurbulence`.
release (or wire into /ship-release). Don't imply a live API where there's a static file.
and site URL all come from that project's docs/. Deploy targets are referenced via adapters (any static host / CDN / CI), never assumed.
scripts/parse-changelog.mjs — SHIPPING-LOG.md (+ VERSION + brand) → changelog.json.scripts/emit-feed.mjs — changelog.json → changelog.xml (RSS 2.0 or Atom 1.0).scripts/render-widget.mjs — changelog.json → ship-changelog.js + whats-new.embed.html.scripts/version.mjs — the shared pack semver anchor manager (get/init/set/bump/date).references/data-contract.md — the changelog.json schema + downstream-stability rules.references/embedding.md — copy-paste snippets: company page, in-app badge, iframe, RSS link,host theming, and the renderer-safety rules.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.