| name | gost-report |
| description | Generate Russian academic reports (.docx) formatted to GOST 7.32 — лабораторные, отчёты по практике, курсовые, ВКР, домашние задания для любого российского вуза (ИТМО, МГУ, СПбГУ, МФТИ, Бауманка, и т.д.). Use whenever the user asks for a report по ГОСТ, лабораторную, отчёт по практике, курсовой, ВКР, или любую Russian-language student paper needing proper title page, headings, page numbers, figure/table captions. Triggers even when only "лабораторная" or "отчёт" is mentioned — Russian-language context (ИТМО / МГУ / СПбГУ / университет / ГОСТ) is enough. ITMO is the default profile; other universities via UniversityProfile. |
GOST report generator
⛔ Правило №1 — приоритет выше всего остального
Никогда не пиши длинное (—) или среднее (–) тире в тексте отчёта. Ни в одном тексте, который ты передаёшь в r.text(...), r.task(...), r.h1/h2/h3(...), r.numbered([...]), r.bullet([...]), в caption у r.figure/r.table, и в ячейках таблиц. Это правило важнее любых стилистических соображений — даже если ИИ-«хороший вкус» подсказывает, что тире здесь к месту, не ставь его.
Вместо тире: между словами — запятая или точка с запятой («Москва, столица России»); в диапазонах — дефис (1-5); прямую речь и тире-связку переписывай. Санитайзер дублирует замену (—→, , —→-), но пиши сразу без тире. Авто-санитайз покрывает прозу, ячейки таблиц и текст графиков r.plot.* (легенда labels=, xlabel/ylabel, label опорных линий, text аннотаций) — он запекается в PNG, поэтому чистится у источника. Валидатор _check_dashes дополнительно сканирует ячейки таблиц и жёстко падает на тире в них (см. references/api.md).
Без «ИИ-тона». Живой русский, без канцеляризмов, лишних кавычек и шаблонов. Не пиши: «В ходе выполнения работы…», «В результате проведённого исследования…», «Данный / вышеуказанный…», «является / представляет собой…», «Стоит отметить…», «Таким образом, можно сделать вывод…». Коротко по делу: «Команда ls -la показывает все файлы» вместо «Для решения данной задачи была применена команда…».
Исключения (тут тире и формулировки ставит сама библиотека — не трогай): авто-подписи «Рисунок N — …» / «Таблица N — …» (твой caption уже очищен), канонические заголовки («Введение», «Заключение», «Список использованных источников»), прямые цитаты.
When to use
Любая русскоязычная академическая работа по ГОСТ: лабораторная, отчёт по практике, курсовая/курсовой проект, ВКР, домашнее задание/РГР. Не используй для презентаций, не-ГОСТ-документов, нерусских работ.
Quickstart
Запускай билд командой gr (ставится на PATH установщиком вместе со скиллом):
gr твой_скрипт.py
gr
gr сам поднимает venv скилла (бутстрап + изоляция зависимостей) и выполняет билд. Без аргумента ищет дефолтный билд .gost-report/build.py (обходя дерево вверх от текущей папки) — именно туда рекомендуется класть build-скрипт. Легаси-путь .claude/gost-report/build.py ещё резолвится (с предупреждением об устаревании) — перенеси скрипт в .gost-report/.
Если gr не на PATH (установщик пропустил из-за конфликта имён, либо ручная установка) — fallback на длинную форму:
python3 <skill_dir>/scripts/ensure_env.py твой_скрипт.py
(Скилл управляет своим venv в глобальном state-dir вне кода: ADR-008 — $GOST_REPORT_HOME или ${XDG_DATA_HOME:-~/.local/share}/agentpipe/gost-report/venv. Не запускай pip install глобально. Тёплые запуски ~30 мс.)
Персональный конфиг (ФИО, группа, преподаватель, год)
Не хардкодь личные данные без необходимости — скилл берёт их из ~/.config/gost-report/config (env-формат), который install.sh кладёт шаблоном при первой установке:
GOST_REPORT_STUDENT_NAME="Иванов И.И."
GOST_REPORT_STUDENT_GROUP="P3XXX"
GOST_REPORT_TEACHER_NAME="Сидоров С.С."
GOST_REPORT_TEACHER_DEGREE="к.т.н."
GOST_REPORT_TEACHER_POSITION="доцент"
GOST_REPORT_YEAR="2026"
- Значение с токеном
ЗАПОЛНИ = незаполнено → первый r.save() падает с ValueError (в тексте — путь конфига). Так юзер не отправит отчёт с плейсхолдером на титуле.
- Под предмет — свой
.gost-report.env рядом с проектом курса (ищется вверх от build.py): обычно только преподаватель/кафедра.
- Приоритет (первый непустой): env-переменные →
<курс>/.gost-report.env → глобальный конфиг → TitleConfig(...) в build.py. Env побеждает build.py.
Командная работа
Несколько участников — student_names (список):
r = Report(TitleConfig(
work_type="Лабораторная работа",
work_number="№3",
topic="Командный проект",
student_names=["Иванов И.И.", "Петров П.П.", "Сидоров С.С."],
student_group="P3XXX",
))
На титульной странице автоматически пишется «Выполнили: …» вместо «Выполнил», все имена выровнены под первое. То же через env: GOST_REPORT_STUDENT_NAMES="Иванов И.И., Петров П.П., Сидоров С.С." (CSV).
Если у участников разные группы — указывай это прямо в строке имени: "Иванов И.И. (P3XXX)". Кастомный label (например, «Выполнила» для женщины-одиночки) — через student_label="Выполнила" или GOST_REPORT_STUDENT_LABEL.
Project layout (рекомендуемая конвенция)
Скрипт-генератор кладётся в <project>/.gost-report/build.py. Артефакты идут в <project>/docs/:
<project>/
├── .gost-report/
│ └── build.py # скрипт (инструмент, не артефакт)
├── docs/
│ ├── figures/*.png # картинки
│ ├── tables/*.tex # таблицы (если есть)
│ └── report.docx # сгенерированный отчёт
├── Makefile или .git/ # маркер project root
└── ...
Project root определяется автоматически (обход вверх до первого маркера: .git/ → Makefile → pyproject.toml → .gost-report/ → .claude/). Из этого выводятся:
r.figure("name.png", ...) — резолвится от <project>/docs/figures/
r.save() без аргумента — кладёт в <project>/docs/report.docx
paths() — (root, docs, figures, tables, out, tex) если нужен явный доступ
Готовый скелет: references/templates/build.py.
Минимальный пример (ИТМО, дефолт):
from gost_report import Report, TitleConfig
r = Report(TitleConfig(
work_type="Лабораторная работа",
work_number="№1",
topic="Основы работы в командной строке Unix",
))
r.toc()
r.h1("Введение")
r.text("Цель работы освоить базовые команды Unix.")
r.h1("Выполнение работы")
r.task("Задание 1. Вывести список файлов.")
r.code("ls -la")
r.text("Команда показывает все файлы, включая скрытые.")
f1 = r.formula(r"\sum_{i=1}^{n} i = \frac{n(n+1)}{2}")
r.text(f"Сумма вычисляется {r.ref.by_formula(f1)}.")
r.h1("Заключение")
r.numbered(["Команда ls освоена.", "Опции -a и -l изучены."])
r.figure("schema.png", "Архитектура")
r.save()
Без титульного листа
Когда титульник не нужен (черновик, вставка-фрагмент, свой титул отдельным файлом) — title_page=False. Документ начинается сразу с основного текста, поля основного текста, нумерация страниц с первой страницы. TitleConfig в этом режиме необязателен, обязательные поля (work_type/topic/ФИО/группа/год) не проверяются:
from gost_report import Report
r = Report(title_page=False)
r.h1("Введение")
r.text("Текст без титульного листа.")
r.save("draft.docx")
То же через env (полезно для автоматизации — гасит титул, не трогая build.py): GOST_REPORT_NO_TITLE_PAGE=1. Env только отключает титул; чтобы включить обратно, убери переменную (параметр title_page=True её не перебивает). r.toc() работает и без титульника.
API
Палитра для build.py — что можно вставлять в отчёт:
- Структура:
r.toc(), r.h1/h2/h3, r.text, r.task, r.numbered/bullet, r.code, r.page_break
- Формулы:
r.formula(latex, where=) (блочные, с номером) + инлайн $...$ в любом тексте
- Графики (тир
[viz]): r.plot.line/scatter/bar/grouped_bar/stacked_bar/area/histogram → ГОСТ-стиль, Ч/Б-safe
- Диаграммы (Graphviz):
r.diagram(dot) → структурные схемы, блок-схемы алгоритмов, деревья, ER
- Картинки/таблицы:
r.figure(path|fig, caption), r.table(rows, caption)
- Литература/ссылки:
r.bib.add/cite/references (ГОСТ Р 7.0.5), r.ref.on_figure/in_table/by_formula
Графики, диаграммы и картинки делят единый счётчик «Рисунок N». Детали каждого — в таблице ниже и секциях после неё.
| Method | What it does |
|---|
r.toc() | Поле Word TOC + флаг updateFields=true в settings.xml. Word/Pages при первом открытии файла спросит «Update fields?» — нажми «Yes», и оглавление с нумерацией обновится автоматически. |
r.h1(text), r.h2(text), r.h3(text) | Заголовки. h1 авто-капс и с новой страницы (профиль). |
r.text(text, bold=False, italic=False) | Абзац основного текста (justify, отступ 1.25 см). |
r.task(text) | Жирный «Задание N. ...». |
r.code(code) | Блок моноширинного кода (Courier New 11). |
r.figure(image, caption, width_cm=None) → int | Картинка + «Рисунок N — caption». Возвращает номер (для r.ref.on_figure). image — путь ИЛИ Figure из модуля (r.plot.*, r.diagram). Ширина клампится по печатной области. Относительный путь → <project>/docs/figures/. |
r.plot.line/scatter/bar/grouped_bar/stacked_bar/area/histogram(...) | График matplotlib в ГОСТ-стиле (opt-in тир [viz]). С caption=... → встраивает и возвращает номер рисунка; без — возвращает Figure для r.figure(fig, caption). Общие kw: hlines/vlines (опорные линии), ylim/xlim, yscale='log', annotations. Bar/grouped/stacked: value_labels, value_fmt, colors, horizontal. См. ниже. |
r.diagram(dot, caption=None) | Диаграмма Graphviz (DOT) → PNG. Нужен системный dot (brew/apt install graphviz). С caption → номер рисунка; без — Figure. |
r.formula(latex, where=None) → int | LaTeX-формула как нативное Word-уравнение, авто-номер «(N)» справа. Возвращает номер для ссылок. Реализация вынесена в модуль gost_report_math (доступно и как r.math.formula); поведение идентично. |
r.table(rows, caption, has_header=True) → int | Таблица + «Таблица N — caption». Возвращает номер (для r.ref.in_table). В заголовках столбцов указывай единицы измерения (см. ниже). |
r.bib.add(key, type=, ...) / r.bib.cite(key)→"[N]" / r.bib.references() | Список литературы по ГОСТ Р 7.0.5: регистрация источника, ссылка [N] (номер по порядку цитирования), структурный элемент «Список использованных источников». |
r.ref.on_figure(n) / r.ref.in_table(n) / r.ref.by_formula(n) / r.ref.figure(n) … | ГОСТ-фразы для ссылок: «на рисунке 3», «в таблице 2», «по формуле (4)». cap=True для начала предложения. |
r.numbered(items), r.bullet(items) | Списки. Каждый вызов стартует с 1 заново. |
r.page_break() | Принудительный разрыв (редко нужен — h1 сам ставит). |
r.save(path=None) | Сохранить .docx. Без аргумента → <project>/docs/report.docx. Относительный путь → от <project>/docs/. Возвращает абсолютный Path. |
paths(start=None) → ProjectPaths | (root, docs, figures, tables, out, tex). По умолчанию резолвит от file caller'а. |
TitleConfig — часто переопределяемые поля
| Поле | Дефолт | Когда менять |
|---|
teacher_label | "Проверил" | Женщина-преподаватель: "Проверила". ВКР/курсовая: "Руководитель" / "Руководительница". |
work_number | "" | Лабы с номерами: "№1", "№3". |
variant | "" | Лабы с вариантами: "3". |
teacher_degree | "" | "к.т.н.", "д.ф.-м.н.". |
teacher_position | "" | "доцент", "профессор", "ст. преподаватель". |
Обязательные: work_type, topic, student_name, student_group, year. Полный список (включая city, ministry, university_*, faculty для override профиля) — в references/api.md.
Графики и диаграммы (подключаемые модули, opt-in)
Сверх готовых PNG скилл умеет строить графики и диаграммы прямо в сборке. Это
подключаемые модули с тяжёлыми зависимостями — они не входят в lightweight-
дефолт и активируются тиром через GOST_REPORT_EXTRAS:
GOST_REPORT_EXTRAS=viz gr build.py
brew install graphviz
Графики (r.plot) — opt-in тир [viz]; без него падают с внятной инструкцией
(обычный отчёт matplotlib не тянет). Диаграммы (r.diagram) — нужен только
системный dot; pip-зависимостей нет.
Ключевая гарантия ГОСТ: график, диаграмма и готовый PNG делят ОДИН сквозной
счётчик «Рисунок N — …» (§6.5). Заголовок внутри графика не ставится — подпись
делает r.figure/embed_figure.
r.plot.line([0,1,2,3], [[0,1,4,9],[0,2,4,6]], labels=["y=x²","y=2x"],
xlabel="x", ylabel="y", caption="Сравнение зависимостей")
r.plot.bar(["A","B","C"], [3,7,5], ylabel="Значение", caption="Распределение")
r.plot.histogram(data, bins=20, xlabel="x", caption="Гистограмма выборки")
r.plot.grouped_bar(["Q1","Q2","Q3"], [[95,97,99],[88,91,94]], labels=["A","B"],
value_labels=True, value_fmt="{:.0f}", ylabel="%",
hlines=[{"value":98,"label":"SLA"}], caption="Доступность по кварталам")
r.plot.line(t, v, xlabel="t, с", ylabel="U, В",
hlines=[{"value":3.3,"label":"номинал"}], vlines=[{"value":2.0,"label":"сбой"}],
caption="Переходный процесс")
r.plot.line(x, y, yscale="log", ylim=(1,1e3), caption="Сходимость")
r.plot.line(x, y, colors=["#111","#999"], linestyles=["-",":"], markers=False)
r.plot.line(x, y, annotations=[{"x":10,"y":42,"text":"экстремум","arrow":True}])
r.plot.bar(["a","b","c"], [3,7,5], horizontal=True, value_labels=True)
r.plot.stacked_bar(["A","B"], [[1,2],[3,4]], labels=["низ","верх"])
r.plot.area(x, [y1, y2], labels=["band","mean"], stacked=False)
fig = r.plot.scatter(xs, ys, xlabel="x", ylabel="y")
r.figure(fig, "Корреляция величин")
r.diagram("digraph { Пользователь -> Сервис -> БД }",
caption="Структурная схема системы")
r.diagram('''digraph { rankdir=TB
s [shape=ellipse label="Начало"]; d [shape=diamond label="x > 0?"]
a [label="y = x"]; b [label="y = -x"]; e [shape=ellipse label="Конец"]
s -> d; d -> a [label="да"]; d -> b [label="нет"]; a -> e; b -> e }''',
caption="Блок-схема алгоритма")
Диаграммы рендерит системный Graphviz (dot) — PNG напрямую, без Node и без
растеризатора; покрывает структурные схемы, блок-схемы алгоритмов, деревья, ER,
графы зависимостей. Из коробки инжектится ГОСТ-оформление: светло-серые
скруглённые блоки, тёмная рамка, чёрный текст, serif-шрифт под Times New Roman
(читается в Ч/Б). Пользовательские атрибуты в DOT (shape, rankdir, …)
переопределяют дефолты. Опции: engine= (dot/neato/fdp/circo/twopi), font=,
rankdir=. Детерминизм — best-effort (зависит от версии dot).
Новые модули штампуются скриптом scripts/new_module.py <namespace> [--visual].
Эталонный пример модуля — gost_report_math/ (формулы вынесены из ядра без
изменения поведения). Архитектура подробно — research/19_gost_report_module_architecture.md.
Список литературы и ссылки (модули bib, ref)
Pure-python, в default-тире (без доп. зависимостей). Источники нумеруются по
порядку первого цитирования (vancouver-стиль), номера в [N] совпадают со
списком.
r.bib.add("vasiliev2020", type="book", authors=["Васильев А.А."],
title="Машинное обучение", city="М.", publisher="ДМК Пресс",
year=2020, pages=420)
r.bib.add("smith2021", type="article", authors=["Smith J."], title="Deep nets",
journal="Nature", year=2021, volume=5, issue=3, pages="12-18",
doi="10.1000/xyz")
r.bib.add("docs", type="web", authors=["Иванов И.И."], title="Руководство",
url="https://example.org", accessed="01.06.2026")
r.text(f"Метод описан в источнике {r.bib.cite('vasiliev2020')}.")
r.text(f"Сравнение приведено в работах {r.bib.cite('smith2021','docs')}.")
...
r.bib.references()
Типы: book / article / web / conference / standard / thesis. Поля:
authors (список или строка), title, city, publisher, year, pages,
journal, volume, issue, url, accessed, doi, edition. Тире « — » в
описаниях — обязательный разделитель ГОСТ Р 7.0.5 (валидатор его не трогает в
секции списка литературы).
Ссылки в тексте — словом, не цифрой (ГОСТ 7.32: сокращения «рис.»/«табл.»
запрещены):
n = r.figure(img, "Схема системы")
t = r.table(rows, caption="Параметры модели")
f = r.formula(r"y = kx + b", where=r"$k$ — наклон, $b$ — сдвиг")
r.text(f"{r.ref.on_figure(n, cap=True)} показана схема.")
r.text(f"Параметры сведены {r.ref.in_table(t)}.")
r.text(f"Значение считается {r.ref.by_formula(f)}.")
Методы ref: figure/table/formula (именительный), on_figure/in_table/by_formula
(предложные обороты), per_figure/per_table («в соответствии с …»), see_figure/ see_table (скобочные). Все принимают номер или зарегистрированную метку
(r.ref.set("arch", n)); cap=True — заглавная для начала предложения.
Инлайн-математика ($...$)
Внутри любой прозы — r.text, r.task, where= у формул, подписи рисунков/
таблиц, пункты списков, ячейки таблиц — математику пишут в долларах, как в LaTeX:
$...$. Она рендерится в нативное Word-уравнение (настоящие индексы, дроби,
греческие буквы), а не в голый текст.
r.text(r"Среднее $\bar{x}$ при дисперсии $\sigma^2$ устойчиво.")
r.formula(r"\sigma = \sqrt{D}", where=r"$D$ — дисперсия, $\sigma$ — СКО")
r.table([["Параметр", r"$\sigma$, ед."], ["Значение", "0,5"]], caption="Сводка")
r.numbered([r"Коэффициент $k$ найден", "Второй пункт"])
- LaTeX внутри
$...$ не санируется (синтаксис не искажается); прозовые
сегменты вокруг — проходят обычные правила (без длинных тире).
- Литеральный знак доллара — экранируй:
\$ (например, "5\\$ за штуку").
- Текст без
$ работает ровно как раньше (тот же результат, байт-в-байт).
- Те же LaTeX-конструкции, что и в
r.formula — см. references/formulas.md.
Правила оформления (по замечаниям нормоконтроля)
- Запятая перед «где» после формулы ставится автоматически, если задан
where=. Просто передавай расшифровку: r.formula(expr, where="…").
- Единицы измерения в заголовках таблиц. Не «Образцов», а «Количество
образцов»; не «Доля», а «Доля, %». Если величина имеет единицу — указывай её
в заголовке столбца: «Масса, г», «Время, с», «Точность, %».
- Ссылки — словом + номер через
r.ref.* (см. выше), не голой цифрой (N).
Подробности — see references/
Загружай по необходимости (агент не должен держать это в контексте каждый раз):
references/profiles.md — другие вузы: GOST_PROFILE, кастомный UniversityProfile, переопределение полей через TitleConfig.
references/formulas.md — полный список поддерживаемых LaTeX-конструкций, edge cases, санитайзер vs LaTeX, отладка.
references/patterns.md — структура для лаб, ВКР, курсовых, отчёта по практике, ДЗ.
references/api.md — TitleConfig полный, поведенческие заметки (TOC поле, рестарт списков, нет кавычек у topic, картинки клампятся, санитайзер семантика).
Dependencies
Управляются автоматически через scripts/ensure_env.py. Lightweight-дефолт (см. scripts/requirements.txt):
python-docx>=1.1.0
latex2mathml>=3.77.0
Opt-in тир (requirements.d/<extra>.txt, активируется GOST_REPORT_EXTRAS=...):
[viz] — numpy, matplotlib (~66 МБ). Графики r.plot.*. scipy/pandas НЕ тянем.
Диаграммы r.diagram (Graphviz) — это не pip-тир, а системный бинарь dot
(brew install graphviz / sudo apt install graphviz). Pip-зависимостей нет.
Переключение тира меняет хэш окружения → доустановка в тот же venv; тёплый запуск без тиров остаётся ~30 мс.
При первом запуске bootstrap пишет gost_report.pth в site-packages venv'а — поэтому в твоём скрипте достаточно from gost_report import Report, TitleConfig. Никаких sys.path.insert(...) не нужно. Если IDE настроен на venv скилла — импорт тоже работает напрямую.
License
MIT — see LICENSE.