Начни здесь

skills-reasoning: четыре навыка мышления для агента

Практический курс по @dzhechkov/skills-reasoning — паку из четырёх навыков, которые меняют не то, что агент знает, а то, как он думает. Вместе с Костей ты поставишь пак, разведёшь расследование и починку, научишься требовать от агента проговорённых допущений и хирургических правок, разберёшь цикл красный-зелёный-рефакторинг и соберёшь для трёх репозиториев AGENTS.md с таблицей заморозки на измеренных числах.

Знакомься: Костя

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

Содержание курса

1. Зачем паку рассуждения отдельное место

Что такое skills-reasoning одной фразой — и почему это не сборник промптов.

Ключевая мысль: рассуждение как устанавливаемый навык

Костя начал неделю плохо. Он попросил агента починить одну падающую проверку — и получил дифф на четыреста строк: заодно переформатирован соседний модуль, заодно «улучшены» комментарии, заодно удалён кусок кода, который никто не просил трогать. Проверка, кстати, чинилась одной строкой.

Вот в чём фокус: агенту не хватало не знаний. Ему не хватало дисциплины рассуждения. Именно это и ставит пак @dzhechkov/skills-reasoning — четыре навыка, которые меняют не то, ЧТО агент знает, а то, КАК он думает:

  • investigate — расследовать, не хватаясь за правку;
  • solid — писать код как старший инженер: SOLID, TDD, чистый код;
  • karpathy-guidelines — поведенческие ограничители против типовых ошибок языковой модели;
  • agents-md-creator — собирать для каждого репозитория архитектурный скелет AGENTS.md.

Ключевое слово — устанавливаемый. Это не советы в чате, которые улетают вместе с историей диалога: каждый такой навык лежит файлом в твоём харнесе, агент подхватывает его по описанию задачи или ты называешь его сам.

Второе ключевое слово — нейтральный к стеку. Пак обезличен: из него вычищены упоминания конкретных продуктов, фреймворков и репозиториев, и это проверяется отдельной проверкой на нулевую связанность. Поэтому он одинаково ложится и на Python-монолит Кости, и на твой TypeScript.

Компромисс: ты платишь тем, что агент становится медленнее и разговорчивее — он теперь останавливается и спрашивает. Взамен ты перестаёшь читать диффы, в которых девяносто процентов строк никто не заказывал.

2. Ставим пак: пресет целиком или один навык

Три способа поставить пак и одно правило, которое избавляет от дублей.

Ключевая мысль: пресет reasoning ставит все четыре навыка разом

Костя не любит длинные инструкции по установке, и здесь ему повезло: способов ровно три, и все помещаются в четыре строки.

  1. Весь пак пресетом — dz init --target claude-code --preset reasoning. Пресет reasoning собирает все четыре навыка разом, это дорога по умолчанию.
  2. Один навык точечно — dz init --target claude-code --select karpathy-guidelines. Берёшь ровно то, чего не хватает.
  3. Голым npm — npm install @dzhechkov/skills-reasoning; файлы навыков копируются в твой .claude/skills/.

Страница пакета: npm: @dzhechkov/skills-reasoning, исходники и зеркало — GitHub: dz-harness.

Одно правило, которое стоит запомнить сразу. Ищешь systematic-debugging? Его здесь нет и не будет: он уже живёт в @dzhechkov/skills-qe, и пак сознательно не дублирует чужие навыки. Костя потратил полчаса на поиск, прежде чем прочитал эту строчку в README — не повторяй.

Компромисс: пресет ставит четыре навыка вместо одного нужного, и агент читает описания всех четырёх. Взамен ты не собираешь арсенал по кусочкам и не гадаешь, что забыл.

3. Карта четырёх навыков: идём от задачи

Какой навык включается на какой задаче — и почему имена запоминать не нужно.

Ключевая мысль: выбор навыка идёт от задачи, а не от имени

Костя сделал типичную ошибку новичка: выучил четыре имени и стал думать, какое из них подходит. Правильный порядок обратный — сначала задача, потом навык.

Таблица в README пака построена ровно так: первая колонка — не имя, а ситуация, в которой ты оказался.

  • «Разберись, почему падает, но НЕ чини» → investigate;
  • «Пишу, рефакторю, проектирую, ревьюю код» → solid;
  • «Хочу, чтобы агент перестал делать типовые ошибки модели» → karpathy-guidelines;
  • «У меня три репозитория, и агент каждый раз заново ищет, куда класть код» → agents-md-creator.

Практическое следствие: имена не заучивают. Агент выбирает навык по описанию задачи — ты просто говоришь «разберись, почему падает импорт, но пока ничего не чини», и включается investigate. Имена в этом курсе нужны, чтобы ты понимал, что происходит под капотом, а не чтобы их помнить.

Компромисс: выбор по описанию удобнее, но менее предсказуем — формулировка «почини быстренько» включит совсем не тот навык, который ты имел в виду. Если нужна гарантия, называй навык явно.

4. Правило «только расследуй»

Почему расследование и починка — две разные работы, и как поймать себя на подмене.

Ключевая мысль: расследование без правок кода

У навыка investigate есть ровно одно правило, и оно написано капслоком: расследуй, не меняй код. Выход — документ с диагнозом, а не дифф.

Звучит как формальность, пока не прочитаешь причину. Навык существует потому, что желание починить прямо во время расследования — источник плохих патчей номер один. Ты ещё не знаешь первопричину, но уже правишь то, что попалось под руку, — и симптом уходит, а причина остаётся.

В навыке перечислены красные флаги — фразы, на которых надо остановиться:

  • «сейчас быстренько починю, раз уж я здесь»;
  • «это же очевидный однострочник»;
  • «расследую и сразу поправлю, сэкономлю время»;
  • ты открыл файл инструментом правки вместо чтения.

Костя узнал в этом списке себя целиком. Его личный рекорд — «очевидный однострочник», который через два дня пришлось откатывать, потому что настоящая причина лежала слоем ниже.

Что делать, если чинить хочется невыносимо: записать предполагаемое направление починки словами в раздел «Suggested Fix Direction» и остановиться. Направление словами — часть диагноза; готовый код — уже другая работа.

Компромисс: ты теряешь один проход — расследование и починка станут двумя заходами вместо одного. Взамен ты не платишь за откат патча, который лечил симптом.

5. Обратная трассировка: от симптома к первопричине

Пять шагов расследования и правило проверять данные на каждой границе слоёв.

Ключевая мысль: обратная трассировка от симптома к первопричине

Костя привык искать баг вперёд: «где мы стартуем и что происходит дальше». Навык investigate разворачивает движение — обратная трассировка идёт от симптома назад.

Механика простая и повторяемая:

  1. начни с симптома — того, что видит пользователь;
  2. найди непосредственную причину этого симптома;
  3. спроси: а что вызвало ЕЁ;
  4. повторяй, пока не упрёшься в первопричину;
  5. на каждой границе слоёв проверяй реальные данные — журналы, отладчик, отпечатки значений.

Пятый пункт — тот, ради которого всё и затевалось. Для системы из нескольких компонентов навык предлагает пройти каждую границу и ответить на три вопроса: какие данные входят, какие выходят и где именно они расходятся с ожидаемыми.

Целиком путь расследования — пять шагов: понять симптом, воспроизвести, трассировать назад, назвать сопутствующие факторы, написать диагноз. Костя раньше начинал сразу с третьего и поэтому регулярно объяснял не тот дефект.

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

Компромисс: проверка данных на каждой границе стоит времени и требует доступа к живой системе. Взамен ты не принимаешь за первопричину первое правдоподобное объяснение.

6. Честное «не знаю» и стоп-кран расследования

Что писать, когда первопричина не найдена, и когда пора звать независимых проверяющих.

Ключевая мысль: честное «не знаю» сильнее правдоподобной догадки

Самая неудобная часть навыка investigate — та, где расследование не сошлось. Костя в такой ситуации всегда писал что-нибудь уверенное: отчёт без вывода выглядит как признание собственной некомпетентности.

Навык утверждает обратное: честное «не знаю» сильнее правдоподобной догадки, выданной за диагноз. Формула незакрытого расследования — четыре пункта:

  1. что проверил и что исключил;
  2. что подозреваешь, но подтвердить не смог;
  3. какой конкретный диагностический шаг развёл бы гипотезы;
  4. прямая формулировка пробела: «я не смог определить X, потому что Y».

Отдельно есть стоп-кран: если ты прочитал десятки файлов, выполнил кучу команд, а первопричина всё ещё не видна — расследование не сходится. Тогда не углубляешься, а останавливаешься, подводишь итог по тем же пунктам и спрашиваешь у человека направление.

Есть и защита от собственной предвзятости — независимая проверка субагентами, и её объём привязан к размеру задачи: маленькая задача (один файл, очевидная трассировка) — ноль проверяющих; средняя (несколько файлов, один сервис) — один; большая (несколько сервисов, неясная трассировка) — два-три, каждый со своего угла. Проверяющие читают только на чтение: они подтверждают или спорят, но не чинят. Несогласие проверяющего — ценная находка, а не помеха: его разбирают до того, как диагноз объявлен окончательным.

Компромисс: отчёт без вывода некомфортно отдавать заказчику. Взамен никто не строит починку на догадке, которую выдали за факт.

7. Думай до кода: допущения вслух

Первое правило karpathy-guidelines: не додумывай молча и не прячь непонимание.

Ключевая мысль: допущения проговариваются до первой строки кода

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

Четыре требования перед тем, как написать первую строку:

  • допущения проговариваются вслух; сомневаешься — спроси;
  • есть несколько прочтений задачи — покажи их все, а не выбери одно молча;
  • знаешь способ проще — скажи об этом и поспорь, если есть основания;
  • что-то непонятно — остановись, назови, ЧТО именно непонятно, и спроси.

Обрати внимание на формулировку третьего пункта: не «сделай проще», а «скажи, что проще, и поспорь». Навык явно разрешает агенту возражать — молчаливое согласие с неудачной постановкой стоит дороже спора.

Четвёртый пункт — самый недооценённый. Разница между «я не понял задачу» и «мне неясно, считаем ли мы отменённые заказы» — это разница между потерянным днём и одним уточняющим вопросом.

Костя завёл себе привычку: если в ответе агента нет ни одного проговорённого допущения, значит агент их не осознал, а не «их не было».

Компромисс: ты получаешь больше вопросов и медленнее стартуешь. Взамен ты не оплачиваешь реализацию не того требования.

8. Хирургические правки и простота

Каждая изменённая строка ведёт к запросу — и почему сирот убирают только своих.

Ключевая мысль: хирургическая правка: каждая строка ведёт к запросу

Вернёмся к диффу на четыреста строк из первой секции. У навыка karpathy-guidelines для него есть проверка в одну фразу: каждая изменённая строка должна напрямую восходить к запросу пользователя. Костя прогнал свой дифф через неё — прошли одиннадцать строк из четырёхсот.

Правило хирургической правки состоит из запретов, и каждый из них закрывает знакомую подмену:

  • не «улучшай» соседний код, комментарии и форматирование;
  • не рефактори то, что не сломано;
  • держись существующего стиля, даже если сам писал бы иначе;
  • увидел посторонний мёртвый код — скажи о нём, но не удаляй.

И одно симметричное разрешение: убирай сирот, которых создали ТВОИ правки — импорты, переменные, функции, ставшие ненужными из-за твоего изменения. Чужой мёртвый код — не твоя уборка.

Рядом живёт правило простоты: минимум кода, решающий задачу, и ничего впрок. Ни фич сверх заказанных, ни абстракций ради одного использования, ни «гибкости», которую не просили, ни обработки невозможных ситуаций. Контрольный вопрос навыка звучит так: написал двести строк там, где хватило бы пятидесяти — перепиши.

Компромисс: ты сознательно оставляешь в репозитории замеченную грязь. Взамен ревьюер видит дифф, в котором каждая строка объяснима, и не ищет твою правку среди косметики.

9. Проверяемый критерий вместо «сделай, чтобы работало»

Как превратить размытую задачу в цель, которую агент может проверить сам.

Ключевая мысль: проверяемый критерий успеха вместо «сделай, чтобы работало»

Четвёртое правило навыка — про то, почему агент постоянно возвращается за уточнениями. Причина обычно не в агенте, а в постановке: сильный критерий успеха позволяет работать самостоятельно, слабый («сделай, чтобы работало») требует непрерывных вопросов.

Навык показывает превращение прямо в виде трёх пар:

  • «добавь валидацию» → «напиши тесты на невалидный вход, потом сделай их зелёными»;
  • «почини баг» → «напиши тест, воспроизводящий баг, потом сделай его зелёным»;
  • «отрефактори X» → «убедись, что тесты зелёные до и после».

Видишь общий приём? В каждой паре справа появляется проверка, которую можно выполнить, а не оценить на глаз. Костя теперь переписывает так каждую задачу, прежде чем отдать её агенту.

Для многошаговых задач навык требует короткого плана в жёсткой форме: каждая строка — это шаг и его проверка.

1. [шаг] → проверка: [чем убедимся]
2. [шаг] → проверка: [чем убедимся]

Строка без правой части — это не шаг плана, а намерение. Именно она потом и превращается в «вроде работает».

Компромисс: формулировка проверяемого критерия — это работа до работы, и на «поменяй цвет кнопки» она выглядит бюрократией. Взамен агент перестаёт возвращаться с вопросом «а как понять, что готово».

10. Красный — зелёный — рефакторинг

Почему навык solid называет цикл необсуждаемым и где на самом деле рождается дизайн.

Ключевая мысль: красный — зелёный — рефакторинг

Навык solid включается на любой работе с кодом и начинается с процесса, который в нём назван необсуждаемым: красный — зелёный — рефакторинг.

Три фазы читаются буквально:

  1. красный — напиши падающий тест, описывающий нужное поведение;
  2. зелёный — напиши самый простой код, который его проходит;
  3. рефакторинг — почисти, убери дублирование по правилу трёх повторений.

Три закона TDD в навыке сформулированы как ограничения на каждое следующее действие: production-код пишется только чтобы сделать зелёным падающий тест; теста пишется ровно столько, чтобы он упал; кода — ровно столько, чтобы он прошёл.

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

Это переворачивает привычный порядок. Костя раньше проектировал заранее и потом защищал спроектированное. Теперь структура появляется там, где её уже страхуют зелёные тесты.

Компромисс: цикл дороже на старте и требует, чтобы код вообще был тестируемым — на прототипе и в исследовательском коде он тормозит. Взамен рефакторинг перестаёт быть страшным: спину держат тесты.

11. Приоритет простого дизайна и таблица запахов

Четыре элемента простого дизайна в жёстком порядке — и почему таблица запахов не декорация.

Ключевая мысль: приоритет простого дизайна: сначала тесты, потом ясность

Костя третий год слушает в своей команде один и тот же спор: что важнее — читаемо или без дублирования. Навык solid спор закрывает, потому что даёт приоритет, а не список: четыре элемента простого дизайна перечислены строго по важности.

  1. проходят все тесты — код обязан работать правильно;
  2. выражает намерение — читается и раскрывает смысл;
  3. нет дублирования — но с оговоркой про правило трёх повторений;
  4. минимальность — как можно меньше классов и методов.

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

Теперь про таблицу запахов кода. Легко пролистать её как справочный придаток — и это ошибка: таблица устроена как рабочий инструмент, где у каждого запаха уже назван приём исправления. Длинный метод → извлечение метода. Большой класс → извлечение класса. Длинный список параметров → объект-параметр. Одержимость примитивами → объект-значение. Оператор выбора по типу → полиморфизм. Спекулятивная общность → выкинуть неиспользуемую абстракцию.

Рядом лежит список красных флагов «остановись и подумай»: код без теста, класс больше чем с двумя полями, метод длиннее десяти строк, больше одного уровня вложенности, else там, где хватило бы раннего возврата, абстракция раньше третьего дубликата.

Компромисс: пороги в навыке заданы жёстко и местами спорны — десять строк на метод и два поля на класс подойдут не каждому языку. Взамен у тебя есть измеримая планка вместо «пиши хорошо».

12. AGENTS.md: постоянно включённый скелет

Что кладут в AGENTS.md, чего туда класть нельзя и когда файл вообще не нужен.

Ключевая мысль: скелет всегда включён, детали навыков — по требованию

У Кости три репозитория, и каждую сессию агент заново выясняет, куда класть код. Ровно на этот случай существует навык agents-md-creator: он собирает по одному файлу AGENTS.md на репозиторий.

Главная идея — разделение слоёв:

  • AGENTS.md — постоянно включённый архитектурный скелет: направление зависимостей, ответственности пакетов («можно» и «нельзя»), запрещённые имена файлов, таблица заморозки god-объектов с измеренными числами, инварианты репозитория, дисциплина рефакторинга, чек-лист изменений. Агент читает его в начале каждой сессии.
  • Навыки — деталь по требованию: антипаттерны, признаки обнаружения, решающие ворота. Подгружаются, когда нужны.

Правило, которое навык повторяет несколько раз: скелет не дублирует содержимое навыков. Ловишь себя на том, что пишешь в AGENTS.md список антипаттернов — остановись, это материал навыка; в скелете должна стоять ссылка по имени.

Есть и честное «не применяй». Навык прямо перечисляет случаи пропуска: один маленький репозиторий (хватит одного файла в корне) и уже сильный существующий AGENTS.md, которому нужна пара точечных правок, а не полный конвейер.

А для существующих файлов есть жёсткая установка: считать их мусором и писать заново. Причина названа: старые файлы писались, когда репозиторий был маленьким, и с тех пор разошлись с реальностью. Костя сначала возмутился, потом открыл свой CLAUDE.md двухлетней давности и молча согласился.

Компромисс: «писать заново» иногда выбрасывает пару верных абзацев из старого файла. Взамен ты не наследуешь дрейф, который никто не отслеживал.

13. Таблица заморозки и два независимых проверяющих

Финальная секция: измеряешь числа сам, замораживаешь god-объекты и решаешь, что применять.

Ключевая мысль: таблица заморозки god-объектов на измеренных числах

Финальная секция — та, где решения принимаешь ты, а Костя только задаёт вопросы.

Самая ошибкоопасная часть AGENTS.md — числа. Навык говорит об этом прямо: измеренные значения строк и методов дают наибольшую долю ошибок в готовых файлах, поэтому их считают командами (wc -l, grep -c), а не оценивают на глаз, и хранят в одном файле измерений, который читают все анализаторы. Одно измерение на всех — иначе анализаторы разойдутся в числах.

Пороги таблицы заморозки заданы двумя уровнями:

  • кандидат на заморозку — от 700 строк для сервера и от 500 для интерфейса;
  • жёсткий блок — больше 1000 строк ИЛИ больше 50 методов или маршрутов; такой файл не просто замораживают, ему предписывают конкретное действие по расколу.

Почему нижний порог именно 700, объяснено измерением: прогон с порогом «больше 1000» пропускает целую полосу 700–1000, а это ровно та зона, где новые god-объекты копятся незаметно.

Проверяют результат два независимых проверяющих на файл, и роли у них принципиально разные: один смотрит качество содержания (есть ли направление зависимостей, конкретны ли «можно/нельзя», не продублирован ли материал навыков), второй проверяет факты (существуют ли пути, совпадают ли числа с wc -l, ведут ли ссылки на разделы навыков туда, куда обещают). Один проверяющий видит только половину: качественный пропустит неверное число, фактический — отсутствие чек-листа.

Правило применения находок: находка идёт в работу, если её подтвердили минимум двое проверяющих ИЛИ если это объективный факт — число, путь, ссылка на строку. Единичное суждение применяют с оглядкой на эталон качества.

И бюджет длины: 200–400 строк на файл. Меньше 200 обычно означает отсутствие ограничений, но у этого есть законные исключения — чистый индекс-файл и тонкий переходный сервис. Больше 400 означает, что файл начал делать работу навыка.

Компромисс: конвейер тяжёлый — измерения, параллельные анализаторы, две проверки на файл. Для одного маленького репозитория это перебор, и навык сам просит его пропустить.

Частые вопросы

Где в паке systematic-debugging? Я его не нашёл.

Его здесь нет намеренно: он уже входит в пакет @dzhechkov/skills-qe (https://www.npmjs.com/package/@dzhechkov/skills-qe), и пак не дублирует чужие навыки. Связка выглядит так: investigate доводит дело до диагноза, а починку по готовой первопричине ведёт systematic-debugging.

Нужно ли ставить весь пресет, если мне нужен один навык?

Нет. Точечная установка — dz init --target claude-code --select karpathy-guidelines. Пресет reasoning удобен, когда ты хочешь весь набор разом; для одного навыка достаточно флага --select.

Как агент понимает, что пора включить investigate, а не solid?

По описанию задачи. Навыки подбираются по формулировке: «разберись, но не чини» ведёт в investigate, «напиши фичу» — в solid. Если нужна гарантия, назови навык по имени явно — автоподбор чувствителен к формулировке.

Правила solid требуют метод короче десяти строк и не больше двух полей в классе. Это обязательные пороги?

Это красные флаги «остановись и подумай», а не проверка сборки. Пороги заданы жёстко намеренно — чтобы дать измеримую планку вместо «пиши хорошо», — но они языкозависимы. Читай их как повод перепроверить решение, а не как запрет.

У меня один небольшой репозиторий. Нужен ли мне agents-md-creator?

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

Почему пак называют нейтральным к стеку и можно ли это проверить?

Навыки обезличены: из них убраны упоминания конкретных продуктов, фреймворков и репозиториев, и отсутствие такой связанности проверяется отдельной проверкой grep-гейтом. Оговорка честная: примеры команд измерения в agents-md-creator написаны под Python, Go и TypeScript — для другого языка их адаптируют, цель измерения при этом не меняется.

Курс закончился. С чего начать на своём проекте завтра?

С самой дешёвой из четырёх привычек: перед следующей задачей агенту перепиши постановку в проверяемый критерий («напиши тест на X, потом сделай его зелёным»). Это одно изменение даёт видимый эффект уже на первой задаче и не требует ни одной новой команды.

Бесплатный интерактивный курс · aicoding.space

Лицензии шрифтов

Onest

Copyright 2021 The Onest Project Authors (https://github.com/googlefonts/onest)

This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://scripts.sil.org/OFL


-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------

PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.

The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded, 
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.

DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.

"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).

"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).

"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.

"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.

PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:

1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.

2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.

3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.

4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.

5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.

TERMINATION
This license becomes null and void if any of the above conditions are
not met.

DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

JetBrainsMono

Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)

This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://scripts.sil.org/OFL


-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------

PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.

The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded, 
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.

DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.

"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).

"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).

"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.

"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.

PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:

1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.

2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.

3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.

4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.

5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.

TERMINATION
This license becomes null and void if any of the above conditions are
not met.

DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.