chat-and-narration — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited chat-and-narration (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 judgment layer over the six chat tools. The tools own correctness (visibility mapping, enrichment, deletes, transcript building); this skill maps the user's intent to the right tool + mode + house formatting. It adds NO new mechanics.
The tools: send-chat-message, list-chat-messages, delete-chat-messages, export-chat-log, post-item-card, request-roll.
send-chat-message takes visibility (public / gm / blind / self) plus an optional speakerActor. Map intent:
| The user wants… | mode | notes |
|---|---|---|
| Narration, announcements, read-aloud, handouts | public | the whole table |
| An NPC to speak | public + speakerActor: "<npc>" | "public as character" — renders as that NPC |
| A GM-only aside / secret note | gm | whispered to all GMs |
| A hidden check the GM resolves privately | blind | whispers GMs + hides content from others; mainly meaningful for rolls — for plain text it behaves like gm |
| A private scratch note to yourself | self | only the bridge user sees it |
When in doubt between gm and blind for plain text, use gm — blind only differs for dice rolls.
Content is HTML. Keep these shapes consistent:
speakerActor = the NPC, default style: ic. Put the spoken line in content;use flavor for a stage direction if useful. Example: send-chat-message { content: "<p>\"You shall not pass.\"</p>", visibility: "public", speakerActor: "Gandalf" }
public, wrap in a consistent block, e.g.<blockquote>…</blockquote> or <section class="read-aloud">…</section>.
images param; do NOT hand-write <img> or guessURLs. Each image has an embed mode. If the user gives an image but does NOT make the placement clear, ASK which they want before posting (don't silently pick):
embed: "dataUri") — the image bytes are read and inlined into the messageitself as a base64 data: URI. Self-contained, nothing left at a path on the server, but it bloats the message in the world DB — keep it for small images.
embed: "webdav", the default) — confirm/choose aData-relative folder (default worlds/<world>/assets/chat), upload the file there, and link its public URL. Permanent and reusable. ⚠️ Served PUBLICLY with no auth — nothing sensitive. If the user already signalled which (e.g. "just embed it" / "put it at worlds/.../maps"), skip the ask and do that. Example: send-chat-message { content: "<p>You find a map.</p>", visibility: "public", images: [{ path: "C:/maps/treasure.webp", caption: "The treasure map", embed: "webdav" }] }
post-item-card { actor, item, action: "use" }.This drives the dnd5e Activity system, so the Attack/Damage/Apply-Effects buttons actually work. If the item has no activity the tool says so — fall back to a plain send-chat-message description card.
request-roll { kind: "save"|"check"|"skill", ability/skill, dc }.Posts a clickable prompt players use to roll their own check.
@UUID links are interactive without aninstalled module. Never claim a hand-written custom <button> will do anything — it won't.
When the user wants to save or archive the chat, call export-chat-log once with BOTH destinations so it lands on their machine AND in the world's public area:
export-chat-log {
format: "markdown",
localPath: "C:/Users/<you>/sessions/session-3.md",
remotePath: "worlds/<world>/exports/session-3.md"
}Then report the local path AND the returned public URL. If MOLTEN_WEBDAV_PASSWORD isn't set, the WebDAV copy is skipped — fall back to local-only and say so. Formats: markdown/plaintext (readable, HTML stripped, roll totals kept), html (raw markup, unstyled — not the rendered card), json (lossless structured records).
Long chat logs are a known Molten performance drag. To prune:
list-chat-messages (use contentMode: "none" on a big log) to preview.delete-chat-messages { beforeTimestamp: <ms epoch> } to purge old noise, or { ids: [...] } forspecific messages (a single id is just an array of one).
it requires confirm: true.
images param.clearAll or any bulk/beforeTimestamp delete that isn't clearlywhat the user asked for.
working around it.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.