OR Key
drop another .md file to compare - side-by-side diff against skill

skill

Scaffolds a new skill for your assistant to use.
description: "Triggers on prompt mention of 'skill'."
personal 2 files 10 recent evals

What it does for you

Scaffolds a new skill for your assistant to use.

What it produces

A recent result, so you can see the kind of work it returns.

loading…

How to get it

These run inside the Snappy workspace. Want this working in your business? I set skills like this up with you, in one focused week.

Work with me
For developers how this skill is built, graded, and how it runs

at a glance- the short version

actorExported functions in state/lib/skill.ts.
auditorState/lint/check.ts (structural) +…
eval modeshape
categorySystem
stages1

what's inside - the parts that make up a skill 3/4 present

A skill is just a few plain-text files. Only the main one is required. The rest are optional, added as the work needs them. This is what the skill is made of; how it runs is just below.

The skill
state/skills/skill/SKILL.md present
the skill itself, in plain text
The main file. It says what the skill is and lays out the steps in plain English.
Code
state/lib/skill.ts present
code the skill can run
Reusable code this skill can call when it needs to.
Scripts
state/bin/skill/ not present
helper scripts
Optional. Added when a skill has a few commands to run.
Loader
state/skills/skill/AGENTS.md present
what the AI loads on the fly
Loaded automatically the moment this skill is needed. Kept short on purpose.

how it's graded - what counts as a good run 3 criteria · 2 deterministic · 1 judge

Each row is one thing a good run has to get right. deterministic means a quick check decides, pass or fail. judge means the AI reads the result and rates it. Grading each piece on its own (instead of one overall score) shows exactly where a run fell short, so the fix is obvious.

name
kind
check
scaffold_script_usage
judge
The new skill page's frontmatter, specifically the 'eval:' field, appears to be generated by 'bash state/bin/skill/scaffold.sh <name>' or 'bash state/bin/skill/validate.sh <name>', avoiding manual evaluation field errors.
index_skill_count_updated
deterministic
The skill count in 'state/index.md' is correctly updated to reflect the addition or removal of the skill, and 'check.ts' passes without 'index-skill-count-drift' errors.
lint_passes_cleanly
deterministic
'npx tsx state/lint/check.ts' exits with status 0, indicating no 'eval-required' or 'shape-contract-mismatch' errors for the new skill.

how it runs - the shared frame every skill uses 5/5 present

Every skill runs the same way. One part does the work, a separate part checks it, and a short loader hands the AI exactly what it needs for the job. Anything this skill doesn't use shows a one-line note saying why, on purpose, not by accident.

makes the work The worker
present
Exported functions in state/lib/skill.ts. the worker
Does the actual work. Whatever it produces is what gets checked next.
checks the work The reviewer
present
State/lint/check.ts (structural) +… the checker
A separate checker grades the work, so the part that made it can't approve its own work.
frame
learns Self-correction
present
fixes itself learns from gaps
When a run hits a gap, the skill gets edited on the spot [FIXED] or queued for a bigger rewrite [LOGGED], so it keeps getting better.
tidies up Background fixes
present
queued for rewrite runs in the background
Bigger fixes that can't be made on the spot get queued and rewritten in the background later.
remembers Run history
present
state/log/evals.ndjson unknown runs
Every run is written down here, so the next time this skill is used it already knows how the last runs went.
Critical rules the things this skill must not get wrong
  1. Use state/bin/skill/scaffold.sh <name> to author frontmatter, never hand-write it. The script reads the filesystem (lib + bin presence) and emits the mechanically-correct name, description, and eval lines. 2026-04-18 saw three new-skills-unregistered / shape-contract-mismatch incidents in one hour because agents picked the eval: value from memory. If scaffold.sh is unavailable, run bash state/bin/skill/validate.sh <name> (read-only) and copy the printed value verbatim.
  2. The eval: enum is exactly auto | shape | auto-shape | manual (per CONSTITUTION invariant #4 and state/lint/check.ts). Pick mechanically from the table — picking shape without a backing state/lib/<name>.ts (≥1 named export) trips shape-contract-mismatch in state/lint/library-shape.ts. Do NOT default to manual; it is reserved for genuine human-review-only cases. Default for prose-only slash commands is auto-shape.
  3. Folder layout is mandatory. A skill lives at state/skills/<name>/SKILL.md plus state/skills/<name>/AGENTS.md — never the flat state/skills/<name>.md form. The optional sidecar lives at state/lib/<name>.ts or state/bin/<name>/. snappy-os owns state/skills/ directly; the per-skill folder IS the canonical home.
  4. Bump state/index.md skill count in the SAME commit. The ## Skills (N total · ...) header is derived from the filesystem and enforced by index-skill-count-drift (error severity in state/lint/check.ts). One skill added → +1 to the count. One skill removed → -1. Never batch index.md updates across multiple skills.
  5. Actor ≠ auditor (CONSTITUTION invariant #3). The thing that scaffolds a skill cannot also grade it. The auditor for new skills is state/lint/check.ts + state/lint/library-shape.ts, not the scaffolder. Run lint BEFORE committing — eval-required, index-skill-count-drift, and shape-contract-mismatch all block.

what it has learned - fixes written back in over time sample

When a run hits something this skill didn't handle, the fix gets written back into the skill so it doesn't happen again. FIXED means it was corrected on the spot. LOGGED means it's queued for a bigger rewrite. Either way, the skill gets a little better and never makes the same mistake twice.

  1. Loading feedback rows…

how the work flows- who makes it, who checks it

actor Exported functions in state/lib/skill.ts.
auditor State/lint/check.ts (structural) +…
1 data
eval log
`state/log/evals.ndjson` (skill: "skill", per CONSTITUTION invariant #4)

SKILL.md- the skill, written out in plain English

skill

state/lib/skill.ts - Meta-skill scaffolder for the snappy-os namespace. See that file for the full API surface.

Pre-flight checklist - REQUIRED before shipping a new skill page

Three class defects have recurred (2026-04-18: 3 incidents in one hour). Complete every item before committing a new state/skills/<name>/SKILL.md:

  • [ ] Use the scaffold script, not hand-written frontmatter.
  bash state/bin/skill/scaffold.sh <name>

The script reads the filesystem, prints the correct frontmatter block (name, description, eval), and stages it. Do not hand-write the eval: line - that is where the defect class originates.

  • [ ] Verify the eval: value before commit.

If you cannot run scaffold.sh, run the validator:

  bash state/bin/skill/validate.sh <name>

It prints the mechanically-correct value. Copy it verbatim.

  • [ ] Bump state/index.md skill count in the same commit.

The ## Skills (N total · ...) header is derived from the filesystem. Update it manually in the same commit as the new skill page, or check.ts will fail with index-skill-count-drift. The count is derived - do not edit it without adding or removing a skill file.

  • [ ] Run lint before committing.
  npx tsx state/lint/check.ts

Blocks on eval-required, index-skill-count-drift, and shape-contract-mismatch. Fix all errors before pushing.

Steps

  • scaffold() - see state/lib/skill.ts

Scaffold flow

# 1. Generate correct frontmatter + stage the file
bash state/bin/skill/scaffold.sh <name>

# 2. Fill in the description and body in state/skills/<name>/SKILL.md

# 3. Bump state/index.md skill count (one number, same commit)

# 4. Run lint; fix any errors
npx tsx state/lint/check.ts

# 5. Commit skill page + index.md together
git add state/skills/<name>/SKILL.md state/skills/<name>/AGENTS.md state/index.md
git commit -m "skill: add <name>"

Required frontmatter for state/skills/<name>/SKILL.md

Every skill page MUST carry name:, description:, and eval:. The eval: value is mechanical - it follows from whether the skill has a backing library and/or a script. Third-recurrence check: 2026-04-18 saw three rounds of new-skills-unregistered / shape-contract-mismatch because new skills shipped with name + description only, or picked shape when the backing lib didn't exist.

Has state/lib/<name>.ts?Has script state/bin/<name>/?Correct eval:
yesnoshape
yesyesauto or shape
noyesauto
nonoauto-shape (prose-only slash commands)

The eval enum (per state/CONSTITUTION.md invariant #4 and state/lint/check.ts) is exactly: auto, shape, auto-shape, manual.

  • auto - auditor code exists (state/lib/<name>.ts OR script) that

returns a machine score on each run.

  • shape - mechanical contract: the page documents a wrapper around

state/lib/<name>.ts, and the lib file MUST exist with ≥1 named export. Validated by state/lint/library-shape.ts.

  • auto-shape - prose-only slash-command skills (no backing lib, no

script). Counted as auto by state/lint/check.ts.

  • manual - human review only. Avoid unless a real reason exists.

Picking the wrong value is a recurring class defect. Use bash state/bin/skill/scaffold.sh <name> (preferred) or bash state/bin/skill/validate.sh <name> (read-only check) to get the correct value mechanically.

Optional frontmatter for external-dependency skills

Some skills (like impeccable) are thin pointers at canonical installs that live OUTSIDE the snappy-os repo (typically under $HOME/.agents/skills/...). For those skills, declare two extra fields so bash state/bin/preflight.sh can prove the install is reachable at dispatch time:

install: "npx -y skills add <author>/<skill-name> -g -y"
install_check: "$HOME/.agents/skills/<skill-name>/scripts/<entrypoint-extension>"

(See state/skills/impeccable/SKILL.md for the canonical concrete example.)

  • install_check: - single absolute path (or comma-separated list) the

preflight verifies via test -e. $HOME and $SNAPPY_REPO are expanded. This is the contract the harness relies on to know "the script the loader will tell the agent to run actually exists."

  • install: - shell one-liner that brings the install into existence

(idempotent - running twice must be safe). Run automatically by preflight when install_check fails.

The state/lint/check.ts rule external-dep-no-bootstrap enforces this: if any SKILL.md or sibling AGENTS.md references an external script under $HOME/.agents/... (matching *.mjs, *.js, *.sh, *.ts, *.py), the SKILL.md MUST declare install_check:. Skills with no external dependencies (the vast majority) need neither field.

state/index.md skill-count rule

The ## Skills (N total · ...) header in state/index.md is derived from the number of .md files in state/skills/ (excluding _template.md and *AGENTS.md). It is NOT authored - it is maintained.

  • Every new skill file bumps the count by 1. Update it in the same commit.
  • Every deleted skill file decrements the count by 1. Update it in the same commit.
  • check.ts enforces this as index-skill-count-drift (error severity).
  • Do not batch index.md count updates - one skill, one count bump.

Eval

Actor: the exported functions in state/lib/skill.ts. Auditor: state/lint/check.ts (structural) + state/lint/library-shape.ts (shape contract). Score 0.0 when new-skills-unregistered or shape-contract-mismatch recurs within 7 days - the fix must be structural (scaffold script + pre-flight checklist), not another manual frontmatter patch.

Score convention:

OutcomeScore
New skill ships with scaffold.sh output, lint passes, index updated1.0
Lint error caught and fixed before merge0.5
eval-required / shape-contract-mismatch reaches main0.0

Gotchas

via the Phase 0.5 driver. Only these rewrites were applied: already in state/lib/)

  1. realpathSync(process.argv[1]) CLI guard wrapped in try/catch
  • See the kernel SKILL.md for the original long-form guidance if you need it

(read-only reference at the kernel path above).

Rubric

criteria:
  - name: scaffold_script_usage
    kind: judge
    check: "The new skill page's frontmatter, specifically the 'eval:' field, appears to be generated by 'bash state/bin/skill/scaffold.sh <name>' or 'bash state/bin/skill/validate.sh <name>', avoiding manual evaluation field errors."
  - name: index_skill_count_updated
    kind: deterministic
    check: "The skill count in 'state/index.md' is correctly updated to reflect the addition or removal of the skill, and 'check.ts' passes without 'index-skill-count-drift' errors."
  - name: lint_passes_cleanly
    kind: deterministic
    check: "'npx tsx state/lint/check.ts' exits with status 0, indicating no 'eval-required' or 'shape-contract-mismatch' errors for the new skill."

AGENTS.md- what the AI loads when this skill comes up

skill - loader

Per-turn rules for the skill skill. Full reference: state/skills/skill/SKILL.md. Do not skip these.

Critical Rules

  • Use state/bin/skill/scaffold.sh <name> to author frontmatter, never hand-write it. The script reads the filesystem (lib + bin presence) and emits the mechanically-correct name, description, and eval lines. 2026-04-18 saw three new-skills-unregistered / shape-contract-mismatch incidents in one hour because agents picked the eval: value from memory. If scaffold.sh is unavailable, run bash state/bin/skill/validate.sh <name> (read-only) and copy the printed value verbatim.
  • The eval: enum is exactly auto | shape | auto-shape | manual (per CONSTITUTION invariant #4 and state/lint/check.ts). Pick mechanically from the table - picking shape without a backing state/lib/<name>.ts (≥1 named export) trips shape-contract-mismatch in state/lint/library-shape.ts. Do NOT default to manual; it is reserved for genuine human-review-only cases. Default for prose-only slash commands is auto-shape.
  • Folder layout is mandatory. A skill lives at state/skills/<name>/SKILL.md plus state/skills/<name>/AGENTS.md - never the flat state/skills/<name>.md form. The optional sidecar lives at state/lib/<name>.ts or state/bin/<name>/. snappy-os owns state/skills/ directly; the per-skill folder IS the canonical home.
  • Bump state/index.md skill count in the SAME commit. The ## Skills (N total · ...) header is derived from the filesystem and enforced by index-skill-count-drift (error severity in state/lint/check.ts). One skill added → +1 to the count. One skill removed → -1. Never batch index.md updates across multiple skills.
  • Actor ≠ auditor (CONSTITUTION invariant #3). The thing that scaffolds a skill cannot also grade it. The auditor for new skills is state/lint/check.ts + state/lint/library-shape.ts, not the scaffolder. Run lint BEFORE committing - eval-required, index-skill-count-drift, and shape-contract-mismatch all block.

Commands

| ui dashboard | state/skills/skill/resources/ui.openui | |scaffold a new skill: bash state/bin/skill/scaffold.sh <name> (writes SKILL.md + AGENTS.md, prints correct eval) |validate eval value only: bash state/bin/skill/validate.sh <name> (read-only check) |library: state/lib/skill.ts - scaffold(name, examplePrompts?) |new skill paths: state/skills/<name>/SKILL.md + state/skills/<name>/AGENTS.md |optional sidecar: state/lib/<name>.ts or state/bin/<name>/ |catalog (must update by hand): state/index.md |lint before commit: npx tsx state/lint/check.ts |commit pattern: git commit -m "skill: add <name>" -- state/skills/<name>/SKILL.md state/skills/<name>/AGENTS.md state/index.md |eval log: state/log/evals.ndjson (skill: "skill", per CONSTITUTION invariant #4)

Eval value decision table

Has state/lib/<name>.ts?Has script state/bin/<name>/?Correct eval:
yesnoshape
yesyesauto or shape
noyesauto
nonoauto-shape (prose-only slash commands)

Self-Test

An agent reading this should correctly:

  1. [ ] Run bash state/bin/skill/scaffold.sh <name> (or validate.sh) instead of hand-writing the eval: line?
  2. [ ] Scaffold into state/skills/<name>/ (folder), with both SKILL.md and AGENTS.md?
  3. [ ] Pick eval: mechanically from auto | shape | auto-shape | manual based on which backing artifacts exist?
  4. [ ] Bump state/index.md skill count in the same commit, run npx tsx state/lint/check.ts before pushing, and use pathspec on git commit to avoid sweeping parallel-agent WIP?

Self-report

If this loader fell short, append a line:

echo "[$(date -u +%FT%TZ)] skill: <what was missing>" >> state/log/loader-feedback.log

<!-- kernel-ok: historical attribution for the PID-loader pattern. -->

Self-correcting loader (PID feedback)

This is the rule that makes loaders learn. Ported from snappy-kernel, where it demonstrably worked: the snappy-dom-cartographer skill mapped Skool admin UI once, every later ship-agent inherited the full map for free.

Before you finish, do two things:

1. Fix gaps (P - proportional). MANDATORY. If this loader didn't cover your case - if you had to read another file, run an undocumented command, work around a wrong selector, or discover a quirk - you MUST attempt an Edit to this AGENTS.md before you log.

  • Default action: edit this file. Surgical. Add the missing line, table

row, or code example where it belongs. No restructuring.

  • Only LOGGED is allowed when: the fix needs >10 lines, spans multiple

files, or requires a structural rewrite. In that case the state/regen/drain.sh queue picks it up asynchronously.

  • "I didn't have time" / "it's minor" / "the next agent will figure it out"

are NOT valid reasons. Minor gaps compound - that's the whole point of this loop.

  • Concrete example of a valid P-fix: discover agent-browser screenshot

takes path positionally not as --output <path>. One line in a table. Edit it in. Do not just log it.

  • The goal: the next agent never has to leave the loader.

2. Log the result.

echo "[$(date -u +%FT%TZ)] skill: <what was missing or fixed> [FIXED|LOGGED]" >> state/log/loader-feedback.log
  • FIXED = you patched this loader inline (P-fix).
  • LOGGED = too large for inline; the PostToolUse enqueue + Stop-hook drain

will rewrite the loader from scratch on next session-end.

Do not skip this. Every agent run must leave the system better than it found it. The loader is the setpoint; you are the sensor; the gap is the error signal; closing the gap is the correction.

OpenUI Resource

  • Skill-owned OpenUI Lang resource: state/skills/skill/resources/ui.openui. Read it before rendering or editing this skill's generated component surface.
  • Treat this resource as a first-class artifact of the skill, not a generic chat response. Improve it when the skill's user-facing output needs to become richer.
  • System resources compose OpenUI primitives and inherit SnappyChat tokens. Use ui_contract: branded in SKILL.md only for deliberate platform or client visuals.

api.ts- the code it can call

#!/usr/bin/env npx tsx
/**
 * state/lib/skill.ts — Meta-skill scaffolder for the snappy-os namespace.
 *
 * One verb: scaffold(name, examplePrompts?). Idempotent.
 *   - Creates the dir if missing, fills in any of SKILL.md/AGENTS.md/api.ts
 *     that don't already exist. Never overwrites content.
 *   - Appends the self-correcting footer to a freshly-written AGENTS.md.
 *   - Purpose is inferred from an existing SKILL.md, or the first non-empty
 *     paragraph of the largest top-level .md in the dir, or the skill name.
 *   - When `examplePrompts` is provided and non-empty, an
 *     `## Observed user requests` subsection is injected into a freshly-
 *     written SKILL.md just before `## Steps` so the cluster of prompts that
 *     triggered the scaffold becomes part of the skill's prose memory.
 *
 * Templates live as real files in ./templates/ — edit those to change the
 * shape of a skill, not the string literals in this file.
 */
import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
import { spawnSync } from "child_process";
import { join, dirname } from "path";
import { fileURLToPath } from "url";

const HERE = dirname(realpathSync(fileURLToPath(import.meta.url)));
// HERE = state/lib. Skills live at state/skills/, repo root is dirname(state/).
const STATE_ROOT = dirname(HERE);
const REPO_ROOT = dirname(STATE_ROOT);
const SKILLS_ROOT = join(STATE_ROOT, "skills");
const FOOTER_PATH = join(REPO_ROOT, "hooks/agents-md-footer.md");
const REGEN_INDEX = join(STATE_ROOT, "skills/snappy-settings/scripts/regenerate-skill-indices.sh");
const TEMPLATES = ["SKILL.md", "AGENTS.md", "api.ts"] as const;

export interface ScaffoldResult {
  path: string;
  created: string[];
  untouched: string[];
}

export function scaffold(name: string, examplePrompts: string[] = []): ScaffoldResult {
  if (!name.startsWith("snappy-")) throw new Error(`name must start with "snappy-": ${name}`);
  const dir = join(SKILLS_ROOT, name);
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });

  const purpose = inferPurpose(dir, name);
  const triggers = `${name}, ${name.replace(/^snappy-/, "")}`;
  const vars = { NAME: name, PURPOSE: purpose, TRIGGERS: triggers };

  const created: string[] = [];
  const untouched: string[] = [];
  for (const f of TEMPLATES) {
    const dst = join(dir, f);
    if (existsSync(dst)) { untouched.push(f); continue; }
    let body = render(readFileSync(join(HERE, "templates", f), "utf-8"), vars);
    if (f === "SKILL.md" && examplePrompts.length > 0) {
      body = injectObservedUserRequests(body, examplePrompts);
    }
    writeFileSync(dst, body);
    if (f === "AGENTS.md" && existsSync(FOOTER_PATH)) {
      appendFileSync(dst, "\n" + readFileSync(FOOTER_PATH, "utf-8"));
    }
    created.push(f);
  }
  if (existsSync(REGEN_INDEX)) {
    spawnSync("bash", [REGEN_INDEX, name], {
      stdio: "inherit",
      env: { ...process.env, SNAPPY_SKILLS_DIR: SKILLS_ROOT },
    });
  }
  return { path: dir, created, untouched };
}

/**
 * Inject an "## Observed user requests" subsection immediately before the
 * first `## Steps` heading. If the template has no `## Steps` heading, the
 * block is appended at the end so the data isn't silently dropped.
 */
function injectObservedUserRequests(body: string, prompts: string[]): string {
  const block = [
    "## Observed user requests",
    "",
    "These are the prompts that triggered this skill being scaffolded:",
    "",
    ...prompts.map((p) => `- ${JSON.stringify(p)}`),
    "",
    "The Steps section below is a first-draft response to this cluster — refine",
    "as eval scores accumulate.",
    "",
  ].join("\n");

  const stepsRe = /^## Steps\b/m;
  if (stepsRe.test(body)) {
    return body.replace(stepsRe, `${block}\n## Steps`);
  }
  return `${body.replace(/\s+$/, "")}\n\n${block}`;
}

function render(tmpl: string, vars: Record<string, string>): string {
  return tmpl.replace(/\{\{(\w+)\}\}/g, (_, k) => vars[k] ?? `{{${k}}}`);
}

function inferPurpose(dir: string, name: string): string {
  const skillMd = join(dir, "SKILL.md");
  if (existsSync(skillMd)) {
    const m = readFileSync(skillMd, "utf-8").match(/^purpose:\s*(.+)$/m);
    if (m) return m[1].trim();
  }
  const mds = existsSync(dir)
    ? readdirSync(dir).filter(f => f.endsWith(".md") && f !== "AGENTS.md" && f !== "SKILL.md")
    : [];
  if (mds.length) {
    mds.sort((a, b) => statSync(join(dir, b)).size - statSync(join(dir, a)).size);
    const text = readFileSync(join(dir, mds[0]), "utf-8");
    const body = text.replace(/^---[\s\S]*?---\n/, "").replace(/^#.*\n/gm, "").trim();
    const first = body.split(/\n\s*\n/)[0]?.replace(/\s+/g, " ").trim();
    if (first) return first.slice(0, 140);
  }
  return `The ${name.replace(/^snappy-/, "")} skill — purpose TBD.`;
}

// --- CLI ---
if ((() => { try { return import.meta.url === `file://${realpathSync(process.argv[1])}`; } catch { return false; } })()) {
  const [, , cmd, name, ...rest] = process.argv;
  if (!cmd || cmd === "help") {
    console.log("Usage: npx tsx state/lib/skill.ts scaffold <snappy-name> [--prompt <text> ...]");
    process.exit(0);
  }
  if (cmd === "scaffold") {
    if (!name) { console.error("scaffold needs a name"); process.exit(1); }
    const examplePrompts: string[] = [];
    for (let i = 0; i < rest.length; i++) {
      if (rest[i] === "--prompt" && i + 1 < rest.length) {
        examplePrompts.push(rest[++i]);
      }
    }
    const r = scaffold(name, examplePrompts);
    console.log(`${r.path}`);
    if (r.created.length) console.log(`created:   ${r.created.join(", ")}`);
    if (r.untouched.length) console.log(`untouched: ${r.untouched.join(", ")}`);
    process.exit(0);
  }
  console.error(`unknown: ${cmd}`);
  process.exit(1);
}

scripts- helper scripts it can run

prose-only skill - 3 inline code blocks live in SKILL.md above (no state/bin/ sidecar yet).

how we check it- the checks, plus the last 10 runs

rubric shape schema-shape check (no inline rubric)
recent mean 0.90 · 10 runs actor/auditor: unverifiable
deps none declared
timestamp verb score primary_issue artifact
2026-04-26 23:47Z - 0.50 - -
2026-04-25 04:11Z - 1.00 - -
2026-04-21 15:58Z - 1.00 - -
2026-04-21 15:57Z - 1.00 - -
2026-04-21 03:53Z - 1.00 - -
2026-04-26 23:47Z - 0.50 - -
2026-04-25 04:11Z - 1.00 - -
2026-04-21 15:58Z - 1.00 - -
2026-04-21 15:57Z - 1.00 - -
2026-04-21 03:53Z - 1.00 - -