fix(skills): auteur — proper upstream attribution, windows platform, trimmed tests
Review follow-ups on the port (all verified against the upstream snapshot, which I re-downloaded and diffed: every scripts/*.mjs and template is the upstream file byte-for-byte after CRLF→LF, except one `reference/` → `references/` path fix; the reference docs differ only by Hermes adaptation notes and the same path fix). - LICENSE: header naming the upstream repo, pinned commit 9bca227d… and the copyright holder above the verbatim MIT text. - SKILL.md frontmatter: `author` credits the upstream human first, Hermes Agent second (skills/AGENTS.md rule 4); `metadata.hermes.upstream` pin in the same shape mono-color/pr-lens use; `category: creative`; H1 `# Auteur Skill` with a linked provenance blockquote. - `platforms` gains `windows`: the declared prerequisites (Node 18+, Playwright, optional ffmpeg) all run on Windows and no script uses a POSIX-only primitive (audited: no /tmp, spawn/exec of shells, fcntl, etc). - Routing examples translated from Russian to English (marked as translated from upstream) so an English-language skill doesn't carry stray artefacts. - tests/skills/test_auteur_skill.py: keep the two port-specific invariants (path annotations, de-Claude residue). Dropped the exact-count tree snapshot (change detector), the `~/.hermes/hermes-agent` host-dependent related_skills fallback, and the frontmatter/description checks that tests/skills/test_authoring_standards.py already enforces repo-wide. - Regenerated the docs page with website/scripts/generate-skill-docs.py (scoped to this skill).
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
auteur — ported from https://github.com/agiwhitelist/auteur
|
||||
Upstream snapshot: commit 9bca227df9877e60dc45d49783c8cbd885eccd9b (2026-08-06)
|
||||
Upstream author / copyright holder: agiwhitelist (https://github.com/agiwhitelist)
|
||||
The MIT license text below is reproduced verbatim from the upstream LICENSE.
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 agiwhitelist
|
||||
|
||||
@@ -2,17 +2,23 @@
|
||||
name: auteur
|
||||
description: Design and build cinematic, award-level web pages.
|
||||
version: 1.3.1
|
||||
author: agiwhitelist (upstream) / Hermes port
|
||||
author: agiwhitelist (https://github.com/agiwhitelist, upstream agiwhitelist/auteur), ported by Hermes Agent
|
||||
license: MIT
|
||||
platforms: [linux, macos]
|
||||
platforms: [linux, macos, windows]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [web-design, cinematic, scroll-animation, design-system, anti-slop, frontend]
|
||||
category: creative
|
||||
related_skills: [popular-web-designs, design-md, p5js]
|
||||
upstream: https://github.com/agiwhitelist/auteur (pinned 9bca227d)
|
||||
---
|
||||
|
||||
Ported from agiwhitelist/auteur (MIT), snapshot 9bca227df9877e60dc45d49783c8cbd885eccd9b.
|
||||
# Auteur Skill
|
||||
|
||||
> Ported from [agiwhitelist/auteur](https://github.com/agiwhitelist/auteur) (MIT), snapshot
|
||||
> commit [`9bca227d`](https://github.com/agiwhitelist/auteur/commit/9bca227df9877e60dc45d49783c8cbd885eccd9b)
|
||||
> — see `LICENSE`. Scripts, templates and references are the upstream files (CRLF→LF), with
|
||||
> Hermes adaptation notes and `references/` path fixes as the only edits.
|
||||
|
||||
Auteur designs and builds web experiences the way a film director makes a film: script first, then assets, then the shoot, then the cut. It has three registers — **build** (an excellent conventional site), **direct** (a cinematic scroll-directed site) and **system** (a multi-screen product as one design system) — on one shared core of taste. Nothing ships until the page passes an executable anti-slop gate and the skill has looked at its own output.
|
||||
|
||||
@@ -86,9 +92,9 @@ Read the argument / brief and route:
|
||||
2. **`build`** or the brief is ONE conventional surface — a marketing page, a landing, a single product page → load `references/build.md`.
|
||||
3. **`system`** or the brief has **more than one screen that must feel like one product** — app, dashboard, admin, settings, onboarding, a docs or content site with real navigation → load `references/system.md`. The unit of design becomes the component × state, the failure mode becomes drift rather than boredom, and there is deliberately **no peak**. If you are already in `build` and a second screen appears, stop and switch: half a system is worse than either.
|
||||
4. **`edit`** or the request modifies a page this skill built (the project contains `design/DESIGN.md`) — "add a section", "change the pricing", "swap the hero copy" → read `design/DESIGN.md` FIRST and follow its Editing protocol: reuse its tokens, section-opening patterns, and motion families; after the change run slopscan and re-shoot the affected viewports. An edit that ignores DESIGN.md is a regression even if it looks good in isolation.
|
||||
5. **`recon <brief>`** or the ask is only for reference material — "найди референсы", "собери мудборд", "what's the state of the art for X sites" → load `references/recon.md` and run just that phase: scout live sites, build the moodboard, hand back `design/refs/REFERENCES.md` (with the `steal:` lines filled) and `design/moodboard/contact-sheet.png` (with the read filled). No commit-sheet, no build.
|
||||
5. **`recon <brief>`** or the ask is only for reference material — "find references", "put together a moodboard", "what's the state of the art for X sites" → load `references/recon.md` and run just that phase: scout live sites, build the moodboard, hand back `design/refs/REFERENCES.md` (with the `steal:` lines filled) and `design/moodboard/contact-sheet.png` (with the read filled). No commit-sheet, no build.
|
||||
6. **`audit <path-or-url>`** → load `references/verify.md` and run the verification pipeline on an auteur-built page. If the target is an existing UI auteur didn't build and the user wants it *polished* rather than *rebuilt*, say that a dedicated UI-polish/critique pass (upstream paired auteur with a separate 'impeccable' skill, not vendored here) is the right tool and offer to continue only if they want a rebuild.
|
||||
7. **Ambiguous** (e.g. plain "сделай лендинг") → ask exactly one question: "Обычный отличный лендинг или кино-режим со scroll-режиссурой и генерацией ассетов?" Then route. (Multi-screen briefs are not ambiguous — they are `system`.) Don't ask anything else yet — each register runs its own intake.
|
||||
7. **Ambiguous** (e.g. plain "make a landing page") → ask exactly one question: "A great conventional landing page, or cinema mode with scroll direction and generated assets?" (upstream phrased these example briefs in Russian; translated here.) Then route. (Multi-screen briefs are not ambiguous — they are `system`.) Don't ask anything else yet — each register runs its own intake.
|
||||
|
||||
All three registers share phase zero, and its centre of gravity is the commit-sheet. Order differs: **build** runs recon → commit-sheet → mockup; **direct** runs recon → storyboard → commit-sheet → mockup, because the film's scenes are what the six decisions get made *about*; **system** runs recon → system-sheet (route map + component inventory) → commit-sheet → mockup, because the six decisions get made about a product, not a page. Either way nothing is coded before the sheet is full.
|
||||
|
||||
|
||||
@@ -1,58 +1,20 @@
|
||||
"""Tests for the auteur optional skill (ported from agiwhitelist/auteur, MIT)."""
|
||||
"""Tests for the auteur optional skill (ported from agiwhitelist/auteur, MIT).
|
||||
|
||||
Frontmatter shape, description length and related_skills resolution are
|
||||
covered repo-wide by tests/skills/test_authoring_standards.py; this file only
|
||||
holds the two invariants specific to the port.
|
||||
"""
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
def _find_skill_dir() -> Path:
|
||||
base = Path(__file__).resolve().parents[2]
|
||||
candidate = base / "optional-skills" / "creative" / "auteur"
|
||||
if candidate.is_dir():
|
||||
return candidate
|
||||
# fallback: glob from repo root for any auteur skill dir
|
||||
for p in base.glob("**/optional-skills/**/auteur"):
|
||||
if (p / "SKILL.md").exists():
|
||||
return p
|
||||
raise AssertionError("auteur skill directory not found relative to test file")
|
||||
|
||||
SKILL_DIR = _find_skill_dir()
|
||||
SKILL_DIR = Path(__file__).resolve().parents[2] / "optional-skills" / "creative" / "auteur"
|
||||
SKILL_MD = SKILL_DIR / "SKILL.md"
|
||||
|
||||
|
||||
def _frontmatter() -> dict:
|
||||
text = SKILL_MD.read_text(encoding="utf-8")
|
||||
assert text.startswith("---\n"), "SKILL.md must start with YAML frontmatter"
|
||||
fm = text.split("---\n", 2)[1]
|
||||
data = yaml.safe_load(fm)
|
||||
assert isinstance(data, dict)
|
||||
return data
|
||||
|
||||
|
||||
def test_frontmatter_parses():
|
||||
fm = _frontmatter()
|
||||
assert fm["name"] == "auteur"
|
||||
|
||||
|
||||
def test_description_length():
|
||||
fm = _frontmatter()
|
||||
desc = fm["description"]
|
||||
assert isinstance(desc, str) and desc.strip()
|
||||
assert len(desc) <= 60, f"description is {len(desc)} chars, must be <= 60"
|
||||
|
||||
|
||||
def test_required_fields():
|
||||
fm = _frontmatter()
|
||||
assert fm.get("license") == "MIT"
|
||||
assert fm.get("author"), "author missing"
|
||||
platforms = fm.get("platforms")
|
||||
assert isinstance(platforms, list) and platforms, "platforms missing"
|
||||
assert set(platforms) <= {"linux", "macos", "windows"}
|
||||
assert fm.get("version")
|
||||
|
||||
|
||||
def test_mentioned_paths_exist_or_annotated():
|
||||
"""Every references/scripts/templates path mentioned in SKILL.md exists on
|
||||
disk, or its line carries an 'upstream' / 'not vendored' annotation."""
|
||||
disk, or its line carries an 'upstream' / 'not vendored' annotation (the
|
||||
port deliberately drops upstream's README gallery and CLI assets)."""
|
||||
pattern = re.compile(r"(references|scripts|templates)/[A-Za-z0-9._-]+")
|
||||
missing = []
|
||||
for line in SKILL_MD.read_text(encoding="utf-8").splitlines():
|
||||
@@ -68,31 +30,8 @@ def test_mentioned_paths_exist_or_annotated():
|
||||
|
||||
|
||||
def test_no_claude_residue():
|
||||
"""Upstream is a Claude Code plugin; its plugin-only frontmatter keys and
|
||||
harness name must not leak into the Hermes port."""
|
||||
text = SKILL_MD.read_text(encoding="utf-8").lower()
|
||||
for token in ("claude", "allowed-tools", "argument-hint"):
|
||||
assert token not in text, f"residual '{token}' in SKILL.md"
|
||||
|
||||
|
||||
def test_related_skills_resolve():
|
||||
fm = _frontmatter()
|
||||
related = (fm.get("metadata") or {}).get("hermes", {}).get("related_skills", [])
|
||||
if not related:
|
||||
return # empty list is allowed
|
||||
staging_root = Path(__file__).resolve().parents[2]
|
||||
repo_root = Path.home() / ".hermes" / "hermes-agent"
|
||||
roots = [
|
||||
staging_root / "skills",
|
||||
staging_root / "optional-skills",
|
||||
repo_root / "skills",
|
||||
repo_root / "optional-skills",
|
||||
]
|
||||
for name in related:
|
||||
found = any(r.is_dir() and list(r.glob(f"**/{name}")) for r in roots)
|
||||
assert found, f"related skill '{name}' not found in skills/optional-skills trees"
|
||||
|
||||
|
||||
def test_vendored_tree_shape():
|
||||
assert (SKILL_DIR / "LICENSE").exists()
|
||||
assert len(list((SKILL_DIR / "references").glob("*.md"))) == 11
|
||||
assert len(list((SKILL_DIR / "scripts").glob("*.mjs"))) == 8
|
||||
assert len(list((SKILL_DIR / "templates").iterdir())) == 6
|
||||
|
||||
@@ -17,9 +17,9 @@ Design and build cinematic, award-level web pages.
|
||||
| Source | Optional — install with `hermes skills install official/creative/auteur` |
|
||||
| Path | `optional-skills/creative/auteur` |
|
||||
| Version | `1.3.1` |
|
||||
| Author | agiwhitelist (upstream) / Hermes port |
|
||||
| Author | agiwhitelist (https://github.com/agiwhitelist, upstream agiwhitelist/auteur), ported by Hermes Agent |
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `web-design`, `cinematic`, `scroll-animation`, `design-system`, `anti-slop`, `frontend` |
|
||||
| Related skills | [`popular-web-designs`](/docs/user-guide/skills/bundled/creative/creative-popular-web-designs), [`design-md`](/docs/user-guide/skills/bundled/creative/creative-design-md), [`p5js`](/docs/user-guide/skills/bundled/creative/creative-p5js) |
|
||||
|
||||
@@ -29,8 +29,12 @@ Design and build cinematic, award-level web pages.
|
||||
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
||||
:::
|
||||
|
||||
Ported from agiwhitelist/auteur (MIT), snapshot 9bca227df9877e60dc45d49783c8cbd885eccd9b.
|
||||
# Auteur Skill
|
||||
|
||||
> Ported from [agiwhitelist/auteur](https://github.com/agiwhitelist/auteur) (MIT), snapshot
|
||||
> commit [`9bca227d`](https://github.com/agiwhitelist/auteur/commit/9bca227df9877e60dc45d49783c8cbd885eccd9b)
|
||||
> — see `LICENSE`. Scripts, templates and references are the upstream files (CRLF→LF), with
|
||||
> Hermes adaptation notes and `references/` path fixes as the only edits.
|
||||
|
||||
Auteur designs and builds web experiences the way a film director makes a film: script first, then assets, then the shoot, then the cut. It has three registers — **build** (an excellent conventional site), **direct** (a cinematic scroll-directed site) and **system** (a multi-screen product as one design system) — on one shared core of taste. Nothing ships until the page passes an executable anti-slop gate and the skill has looked at its own output.
|
||||
|
||||
@@ -104,9 +108,9 @@ Read the argument / brief and route:
|
||||
2. **`build`** or the brief is ONE conventional surface — a marketing page, a landing, a single product page → load `references/build.md`.
|
||||
3. **`system`** or the brief has **more than one screen that must feel like one product** — app, dashboard, admin, settings, onboarding, a docs or content site with real navigation → load `references/system.md`. The unit of design becomes the component × state, the failure mode becomes drift rather than boredom, and there is deliberately **no peak**. If you are already in `build` and a second screen appears, stop and switch: half a system is worse than either.
|
||||
4. **`edit`** or the request modifies a page this skill built (the project contains `design/DESIGN.md`) — "add a section", "change the pricing", "swap the hero copy" → read `design/DESIGN.md` FIRST and follow its Editing protocol: reuse its tokens, section-opening patterns, and motion families; after the change run slopscan and re-shoot the affected viewports. An edit that ignores DESIGN.md is a regression even if it looks good in isolation.
|
||||
5. **`recon <brief>`** or the ask is only for reference material — "найди референсы", "собери мудборд", "what's the state of the art for X sites" → load `references/recon.md` and run just that phase: scout live sites, build the moodboard, hand back `design/refs/REFERENCES.md` (with the `steal:` lines filled) and `design/moodboard/contact-sheet.png` (with the read filled). No commit-sheet, no build.
|
||||
5. **`recon <brief>`** or the ask is only for reference material — "find references", "put together a moodboard", "what's the state of the art for X sites" → load `references/recon.md` and run just that phase: scout live sites, build the moodboard, hand back `design/refs/REFERENCES.md` (with the `steal:` lines filled) and `design/moodboard/contact-sheet.png` (with the read filled). No commit-sheet, no build.
|
||||
6. **`audit <path-or-url>`** → load `references/verify.md` and run the verification pipeline on an auteur-built page. If the target is an existing UI auteur didn't build and the user wants it *polished* rather than *rebuilt*, say that a dedicated UI-polish/critique pass (upstream paired auteur with a separate 'impeccable' skill, not vendored here) is the right tool and offer to continue only if they want a rebuild.
|
||||
7. **Ambiguous** (e.g. plain "сделай лендинг") → ask exactly one question: "Обычный отличный лендинг или кино-режим со scroll-режиссурой и генерацией ассетов?" Then route. (Multi-screen briefs are not ambiguous — they are `system`.) Don't ask anything else yet — each register runs its own intake.
|
||||
7. **Ambiguous** (e.g. plain "make a landing page") → ask exactly one question: "A great conventional landing page, or cinema mode with scroll direction and generated assets?" (upstream phrased these example briefs in Russian; translated here.) Then route. (Multi-screen briefs are not ambiguous — they are `system`.) Don't ask anything else yet — each register runs its own intake.
|
||||
|
||||
All three registers share phase zero, and its centre of gravity is the commit-sheet. Order differs: **build** runs recon → commit-sheet → mockup; **direct** runs recon → storyboard → commit-sheet → mockup, because the film's scenes are what the six decisions get made *about*; **system** runs recon → system-sheet (route map + component inventory) → commit-sheet → mockup, because the six decisions get made about a product, not a page. Either way nothing is coded before the sheet is full.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user