# Как оценивается работа

> Два слоя проверки: агент считает баллы по критериям, человек ставит булевую приёмку

_Источник: https://sii.sergeivolchkov.ru/materials/labs/grading-system_





Оценивание устроено в два слоя, и они делают разное. **Агент считает
баллы по критериям** — это публичная величина, видная всему потоку.
**Человек ставит приёмку** — принято или нет, без полутонов.

Причина разделения простая: списать сгенерированное можно, защитить
непонятое — нельзя. Агент не отличит понимание от пересказа. Человек
отличает, но у него нет времени читать репозиторий целиком.

## Слой 1: баллы от агента [#слой-1-баллы-от-агента]

Агент проверяет pull request и выставляет балл по каждому критерию лабы.
Критерии известны заранее — они лежат на странице каждой лабы, и тот же
список агент получает по API. Скрытого чек-листа нет.

У каждого критерия есть **вес** от 1 до 3. Вес не про трудоёмкость, а про
то, насколько без этого артефакта разваливается остальное. Прод-URL весит
3, потому что без него не проверить ничего дальше; ретроспектива весит 1,
потому что её отсутствие не ломает проект.

Проверка бывает шести видов:

| Вид         | Что делает агент                                           |
| ----------- | ---------------------------------------------------------- |
| `command`   | запускает команду и смотрит код возврата                   |
| `files`     | ищет артефакт по смыслу, а не по пути                      |
| `structure` | проверяет, что внутри артефакта есть требуемое             |
| `http`      | дёргает публичный URL проекта                              |
| `llm`       | читает документ и сравнивает с признаками «хорошо / плохо» |
| `human`     | не проверяет — передаёт вопрос лаборанту                   |

<Callout title="Почему в критериях нет путей к файлам">
  Агент читает репозиторий целиком и находит артефакт, как бы тот ни
  назывался. Где что лежит — решает команда, и это часть работы, а не
  деталь оформления. Жёсткий путь превратил бы требование к результату в
  инструкцию к исполнению.
</Callout>

## Штрафы: от даты первого PR [#штрафы-от-даты-первого-pr]

Дедлайн на лабу один для всего потока. Опоздание умножает балл:

| Опоздание | Множитель |
| --------- | --------- |
| в срок    | ×1.0      |
| день      | ×0.9      |
| три дня   | ×0.7      |
| неделя    | ×0.5      |
| дальше    | ×0.2      |

Две особенности, которые стоит понять до начала работы.

**Штраф персональный.** Артефакты привязаны к ролям, каждый сдаёт своё
своим PR — значит опоздавший портит балл себе, а не команде. Вечный
конфликт «мы сделали, а он тянул» здесь не возникает.

**Считается дата первого PR, а не последнего коммита.** Открыл работу в
срок — дорабатывай сколько нужно, штрафа не будет. Правило поощряет
раннюю сдачу и итеративную доработку вместо привычки собирать всё в
последнюю ночь.

Открыть пустой PR в срок и делать всё потом не выйдет: агент читает
диффы, и если по теме лабы в PR ничего нет, дата не засчитывается.
Спорить с датой бессмысленно — она берётся из GitHub API.

## Один PR на роль и лабу [#один-pr-на-роль-и-лабу]

<Steps>
  <Step>
    ### Ветка своей роли [#ветка-своей-роли]

    Каждый работает в своей ветке: `lab3-ai`, `lab3-delivery`. Один PR на роль
    и лабу — вся переписка по этой работе идёт в нём.
  </Step>

  <Step>
    ### Комментарий агента [#комментарий-агента]

    Агент оставляет в PR результат проверки: что зачтено, что нет, по каким
    признакам. Не согласны — дорабатываете и просите перепроверку в том же PR.
  </Step>

  <Step>
    ### Приёмка на занятии [#приёмка-на-занятии]

    Лаборант задаёт вопросы по тем критериям, которые агент проверить не
    может, и ставит вердикт.
  </Step>

  <Step>
    ### Комментарий системы при закрытии [#комментарий-системы-при-закрытии]

    В тот же PR приходит итог: балл, штраф, приёмка. Переоткрывать PR
    невыгодно — штраф считается от первой даты и только вырастет.
  </Step>
</Steps>

## Слой 2: приёмка человеком [#слой-2-приёмка-человеком]

Финальный вердикт булевый: **принято или нет**. Торга за полбалла нет.

Лаборант не читает репозиторий целиком — это уже сделал агент. Он
работает с карточкой занятия: тайминг на 15–20 минут, три вещи, на
которые смотреть в первую очередь, и список случаев, где решать в одиночку
не стоит.

Вопросы известны заранее — они лежат в тех же критериях. Вопросов на
засыпку нет: если артефакт сделан руками команды, ответ очевиден.

Рядом с вопросом у лаборанта записан **признак того, что артефакт есть, а
понимания нет**. Для гипотез это «условие опровержения сформулировано
так, что не может наступить». Для разбора ошибок — «ошибки отсортированы
по частоте, а не по тому, как они бьют по пользователю». Для burndown —
«график нарисован ровной линией в последний день».

## Как складывается итог [#как-складывается-итог]

**Оценка = баллы со штрафом, при условии что приёмка получена.**

Приёмка — гейт, баллы — величина. Не принято — оценки нет, сколько бы
баллов ни набралось. Принято — идёт балл, посчитанный машиной и
объяснимый по пунктам.

Спорить в этой схеме не о чем: балл посчитан по критериям, штраф взят из
даты в GitHub, приёмка — да или нет с комментарием. Все три вещи видны
студенту в одном месте.

<Callout type="warn" title="Чего в критериях не бывает">
  Формулировок вроде «соблюдены best practices» нет и не будет: непонятно,
  сколько за них давать и за что снимать. Нет и требований «не меньше N» —
  число подменяет суть, глоссарий добьют водой до пятнадцати терминов и
  формально будут правы. Если критерий нельзя проверить по существу — его
  не должно быть.
</Callout>

## Что видно всем [#что-видно-всем]

Баллы публичны. Лидерборд потока показывает, какие лабы закрыты у каких
команд — не рейтинг симпатий, а чек-лист, одинаковый для всех.

Критерий считается закрытым, когда агент выставил по нему полный балл.
Лидерборд показывает состояние проектов, детали сдачи — оценку со всеми
штрафами.

## Если кто-то выбыл [#если-кто-то-выбыл]

Артефакты привязаны к ролям, поэтому выпадение человека не обваливает
команду: его ветку просто никто дальше не сдаёт. Кто-то может взять его
часть — тогда критерии закрываются, но штраф считается от даты его
первого PR. Не взял никто — эти критерии остаются незакрытыми, и баллы за
них не идут.
