jq, python3, git, доступ на запись в каталог с контентом
exiftool — консольная утилита, которая пишет в файл EXIF (поля камеры) и XMP (текстовые поля метаданных стандарта Adobe/IPTC). Установка: sudo apt install libimage-exiftool-perl (Debian/Ubuntu) или brew install exiftool (macOS). Конкретную версию сверьте с документацией вашего дистрибутива — она должна поддерживать запись XMP-iptcExt.jq — консольный парсер JSON, нужен для валидации реестра.python3 — для скрипта аудита; проверьте python3 --version.Что сделать: создать рабочую структуру и завести реестр всех материалов, где участвовала генеративная модель. Реестр — файл registry.jsonl, где каждая строка это один JSON-объект (формат JSONL: одна запись — одна строка, удобно диффить в git).
Зачем: без инвентаризации нельзя ни промаркировать файлы, ни доказать, что пометка стоит везде. Реестр — единственный источник правды: по нему скрипт из Шага 3 находит пропуски.
Пример: структура каталогов и первая запись.
mkdir -p ~/ai-marking/{assets,registry,reports}
cd ~/ai-marking
cat > registry/registry.jsonl <<'EOF'
{"asset_id":"img-2027-0001","file":"assets/hero-banner.png","model":"<название-модели>","generated_at":"2027-03-01T10:15:00Z","operator":"ivan.petrov","prompt_ref":"prompts/hero-0001.txt","review":"human-edited","mark":"ai-generated"}
EOF
Поля реестра:
| Поле | Что писать | Пример |
|---|---|---|
| `asset_id` | внутренний неизменяемый ID | `img-2027-0001` |
| `file` | путь относительно корня проекта | `assets/hero-banner.png` |
| `model` | название модели или сервиса | `<название-модели>` |
| `generated_at` | дата генерации, ISO 8601, UTC | `2027-03-01T10:15:00Z` |
| `operator` | кто запускал генерацию | `ivan.petrov` |
| `prompt_ref` | путь к файлу с промптом | `prompts/hero-0001.txt` |
| `review` | степень участия человека | `human-edited` / `no-edits` |
| `mark` | тип пометки для публикации | `ai-generated` |
Как проверить: валидность JSON и число записей.
jq -c . registry/registry.jsonl > /dev/null && echo "OK: JSONL валиден"
wc -l registry/registry.jsonl
Ожидаемый вывод:
OK: JSONL валиден
1 registry/registry.jsonl
Если jq ругается — синтаксис сломан, читайте раздел «Возможные проблемы». Почему это работает: jq разбирает файл построчно и падает на первой некорректной строке, поэтому валидация одновременно служит проверкой целостности.
Текстовые материалы, которые модель переписала или сократила, заводятся в тот же реестр — с путём к .md-файлу. Подходящие сценарии обработки текста разобраны в гайде по нейросетям для текста.

Что сделать: записать метаданные в сам файл и добавить видимую глазом пометку в публикацию. Машинная часть — поля XMP-dc:Description (человекочитаемое описание) и XMP-iptcExt:DigitalSourceType (стандартный словарь IPTC, где trainedAlgorithmicMedia означает «создано обученной моделью»; актуальный URL значения сверьте с документацией словаря).
Зачем: метаданные переживают скачивание файла и читаются автоматикой площадок, а видимая пометка остаётся, даже если метаданные вырезаны при загрузке.
Пример: маркировка одного изображения.
exiftool -overwrite_original \
-XMP-dc:Description="Сгенерировано ИИ: <название-модели>. Изменено человеком: да." \
-XMP-iptcExt:DigitalSourceType="http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia" \
assets/hero-banner.png
Пакетная обработка всех ассетов из реестра:
jq -r '.file' registry/registry.jsonl | while read -r f; do
[ -f "$f" ] || { echo "MISSING: $f"; continue; }
exiftool -overwrite_original \
-XMP-dc:Description="Сгенерировано ИИ. Изменено человеком: да." \
-XMP-iptcExt:DigitalSourceType="http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia" \
"$f" > /dev/null && echo "OK: $f"
done
Для текстовых страниц видимую пометку удобно держать в front matter (YAML-блок в начале markdown-файла), из которого шаблон выводит подпись под материалом:
---
title: "Как мы собрали лендинг"
ai_generated: true
ai_model: "<название-модели>"
ai_reviewed_by: "ivan.petrov"
---
Чек-лист перед публикацией:
registry.jsonl создана и валидна (jq)DigitalSourceTypereview)prompts/Если пометку нужно ставить в потоке из десятков файлов, пакетную часть имеет смысл вынести в автоматический шаг — общий подход к таким сценариям описан в гиде по ИИ-агентам для автоматизации.
Как проверить: прочитать метаданные обратно.
exiftool -XMP-dc:Description -XMP-iptcExt:DigitalSourceType assets/hero-banner.png
Ожидаемый вывод:
Description : Сгенерировано ИИ: <название-модели>. Изменено человеком: да.
Digital Source Type : http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia
Пустая строка после Description означает, что запись не прошла — вернитесь к команде exiftool и проверьте путь к файлу.

Что сделать: прогнать автоматическую сверку «реестр ↔ файлы» и сохранить отчёт с датой. Отчёт — доказательство, что на момент публикации пометка стояла везде.
Зачем: ручная проверка 50 файлов даёт ошибки; скрипт проверяет все записи за секунды и печатает список пропусков.
Пример: скрипт аудита.
python3 - <<'PY' | tee reports/audit-$(date +%F).txt
import json, subprocess, pathlib
missing = []
lines = pathlib.Path("registry/registry.jsonl").read_text().splitlines()
for line in lines:
if not line.strip():
continue
rec = json.loads(line)
out = subprocess.run(
["exiftool", "-s3", "-XMP-iptcExt:DigitalSourceType", rec["file"]],
capture_output=True, text=True).stdout.strip()
if not out:
missing.append(rec["file"])
print("Записей в реестре:", len([l for l in lines if l.strip()]))
print("Без маркировки:", len(missing))
for f in missing:
print(" -", f)
PY
Ожидаемый вывод при успехе:
Записей в реестре: 12
Без маркировки: 0
Тот же результат сохраняется в reports/audit-2027-03-01.txt. Почему это работает: exiftool -s3 печатает только значение поля без имени тега, поэтому пустой ответ однозначно означает отсутствие метки.
Второй контур проверки — публичный манифест для площадок, которые вырезают EXIF/XMP при загрузке:
jq -s '{generated: "2027-03-01", items: .}' registry/registry.jsonl > ~/ai-marking/public/ai-manifest.json
curl -s https://<ваш-домен>/ai-manifest.json | jq '.items | length'
<ваш-домен> — домен, на котором лежит сайт; файл кладётся в корень статики. Ожидаемый ответ — число, равное количеству записей в реестре (в примере 12). Если вернулся 0 или ошибка парсинга — файл не выложен или отдаётся с неверным Content-Type.
Проблема. ExifTool не находит файл при пакетной обработке
Error: File not found - assets/hero-banner.pngpwd && ls -l assets/hero-banner.png
cd ~/ai-marking && exiftool -XMP-iptcExt:DigitalSourceType assets/hero-banner.png
Проблема. Реестр перестал парситься после ручной правки
jq: error (at registry/registry.jsonl:3): Expected separator between values at line 3, column 42sed -n '3p' registry/registry.jsonl
sed -n '3p' registry/registry.jsonl | jq -c .
Проблема. После загрузки на площадку метаданные исчезли
exiftool -XMP-iptcExt:DigitalSourceType на скачанном файле печатает пустую строкуcurl -s https://<ваш-домен>/ai-manifest.json | jq '.items[] | select(.asset_id=="img-2027-0001")'
Реестр registry.jsonl плюс метка DigitalSourceType в файле и видимая подпись закрывают три точки контроля: что сгенерировано, чем помечено и где подтверждение. Дальше расширьте реестр на архивные материалы и добавьте reports/audit-*.txt в git, чтобы отчёты шли вместе с контентом.
Нужно ли маркировать текст, который модель только переписала?
Да, фиксируйте его в реестре с полем review (human-edited или no-edits) — это показывает степень участия человека. Точный порог «существенной переработки» задан в акте — сверьтесь с документацией.
Что делать, если площадка удаляет метаданные?
Оставляйте видимую пометку в тексте или на изображении и публикуйте ai-manifest.json на своём домене; в отчёте аудита указывайте, что проверялся исходный файл.
Кто отвечает за маркировку — автор или компания?
Технически метку ставит тот, кто публикует. Поэтому реестр ведётся в репозитории контента: поле operator фиксирует исполнителя, а ai_reviewed_by — того, кто выпустил материал.
Нужно ли маркировать внутренние черновики?
Достаточно записи в реестре без публикации манифеста: черновик не выходит к аудитории. Перед публикацией прогоните Шаг 2 и Шаг 3 — метка ставится на файл, который уходит наружу.