# Gost Report

> 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, figur…

- **Type:** Skill
- **Install:** `agentstack add skill-zevtos-agentpipe-gost-report`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [zevtos](https://agentstack.voostack.com/s/zevtos)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [zevtos](https://github.com/zevtos)
- **Source:** https://github.com/zevtos/agentpipe/tree/main/skills/gost-report

## Install

```sh
agentstack add skill-zevtos-agentpipe-gost-report
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# 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 установщиком вместе со скиллом):

```bash
gr твой_скрипт.py     # запустить конкретный билд
gr                    # без аргумента: найти .gost-report/build.py и запустить
```

`gr` сам поднимает venv скилла (бутстрап + изоляция зависимостей) и выполняет билд. Без аргумента ищет дефолтный билд `.gost-report/build.py` (обходя дерево вверх от текущей папки) — именно туда рекомендуется класть build-скрипт. Легаси-путь `.claude/gost-report/build.py` ещё резолвится (с предупреждением об устаревании) — перенеси скрипт в `.gost-report/`.

Если `gr` не на PATH (установщик пропустил из-за конфликта имён, либо ручная установка) — fallback на длинную форму:

```bash
python3 /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` (список):

```python
r = Report(TitleConfig(
    work_type="Лабораторная работа",
    work_number="№3",
    topic="Командный проект",
    student_names=["Иванов И.И.", "Петров П.П.", "Сидоров С.С."],
    student_group="P3XXX",   # общая для всех; из env, если не задано тут
))
```

На титульной странице автоматически пишется «Выполнили: …» вместо «Выполнил», все имена выровнены под первое. То же через env: `GOST_REPORT_STUDENT_NAMES="Иванов И.И., Петров П.П., Сидоров С.С."` (CSV).

Если у участников разные группы — указывай это прямо в строке имени: `"Иванов И.И. (P3XXX)"`. Кастомный label (например, «Выполнила» для женщины-одиночки) — через `student_label="Выполнила"` или `GOST_REPORT_STUDENT_LABEL`.

## Project layout (рекомендуемая конвенция)

Скрипт-генератор кладётся в `/.gost-report/build.py`. Артефакты идут в `/docs/`:

```
/
├── .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", ...)` — резолвится от `/docs/figures/`
- `r.save()` без аргумента — кладёт в `/docs/report.docx`
- `paths()` — `(root, docs, figures, tables, out, tex)` если нужен явный доступ

Готовый скелет: `references/templates/build.py`.

**Минимальный пример** (ИТМО, дефолт):

```python
from gost_report import Report, TitleConfig

# ФИО, группа, преподаватель и год — из ~/.config/gost-report/config (env-формат).
# install.sh кладёт туда шаблон при первой установке скилла. Если предпочитаешь
# хардкод — передай аргументы явно в 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)}.")   # «… по формуле (1).», не голой цифрой
r.h1("Заключение")
r.numbered(["Команда ls освоена.", "Опции -a и -l изучены."])
r.figure("schema.png", "Архитектура")  # относительный путь → /docs/figures/

r.save()  # без аргумента → /docs/report.docx; mkdir parents автоматический
```

## Без титульного листа

Когда титульник не нужен (черновик, вставка-фрагмент, свой титул отдельным файлом) — `title_page=False`. Документ начинается сразу с основного текста, поля основного текста, нумерация страниц с первой страницы. `TitleConfig` в этом режиме необязателен, обязательные поля (`work_type`/`topic`/ФИО/группа/год) не проверяются:

```python
from gost_report import Report

r = Report(title_page=False)        # TitleConfig можно не передавать
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`). Ширина клампится по печатной области. Относительный путь → `/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. Без аргумента → `/docs/report.docx`. Относительный путь → от `/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`:

```bash
GOST_REPORT_EXTRAS=viz gr build.py   # тир viz (numpy+matplotlib) ставится и билд запускается
brew install graphviz                # или: sudo apt install graphviz — для диаграмм (бинарь dot)
```

Графики (`r.plot`) — opt-in тир `[viz]`; без него падают с внятной инструкцией
(обычный отчёт matplotlib не тянет). Диаграммы (`r.diagram`) — нужен только
системный `dot`; pip-зависимостей нет.

**Ключевая гарантия ГОСТ:** график, диаграмма и готовый PNG делят ОДИН сквозной
счётчик «Рисунок N — …» (§6.5). Заголовок внутри графика не ставится — подпись
делает `r.figure`/`embed_figure`.

```python
# Графики (тир [viz]) — Okabe-Ito + второй канал (linestyle/hatch) для Ч/Б печати.
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="Гистограмма выборки")

# Опорные линии + подписи значений (1-2 строки на «публикационный» график):
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="Переходный процесс")

# Лог-ось, лимиты, аннотации, escape hatch цветов/линий (детерминизм сохранён):
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)

# Вернуть Figure и встроить вручную (один call-site с готовым PNG):
fig = r.plot.scatter(xs, ys, xlabel="x", ylabel="y")
r.figure(fig, "Корреляция величин")

# Диаграммы (Graphviz/DOT) — ГОСТ-стиль инжектится из коробки.
r.diagram("digraph { Пользователь -> Сервис -> БД }",
          caption="Структурная схема системы")
# Блок-схема алгоритма (ГОСТ 19.701 — фигуры через DOT):
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  [--visual]`.
Эталонный пример модуля — `gost_report_math/` (формулы вынесены из ядра без
изменения поведения). Архитектура подробно — `research/19_gost_report_module_architecture.md`.

## Список литературы и ссылки (модули bib, ref)

Pure-python, в default-тире (без доп. зависимостей). Источники нумеруются по
порядку первого цитирования (vancouver-стиль), номера в `[N]` совпадают со
списком.

```python
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')}.")   # «… [1]

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [zevtos](https://github.com/zevtos)
- **Source:** [zevtos/agentpipe](https://github.com/zevtos/agentpipe)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-zevtos-agentpipe-gost-report
- Seller: https://agentstack.voostack.com/s/zevtos
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
