Всё началось с приглашения от @little_italy:
Привет! Меня зовут Катя Равальдини, я редактор из команды Хабра.
Мы приглашаем авторов хаба Искусственный интеллект поучаствовать в сезоне «Код будущего» — конкурсе статей о том, как ИИ меняет разработку ПО, open source и подходы к информационной безопасности.
В этом сезоне особенно ждём практические истории: что вы уже попробовали, что сработало, где ИИ действительно ускоряет работу, а где создаёт иллюзию продуктивности.
Я понял, что пора попробовать, тем более редактор ждёт практических историй.
Для начала я вспомнил весь свой небольшой, но всё же, опыт общения с ИИ.
Самым курьезным случай произошёл при издании книги. В издательстве, где я печатал книгу, просто настаивали на проверки ими текста рукописи, хотя у меня была уже готова и верстка книги. При этом они делали упор на то, что текст будет проверен ИИ. Мне стало интересно, тем более, что текст проверялся и перепроверялся, а сам я программист и понимаю цену ИИ (не надо забывать, что всё это происходило более двух лет назад). Вот далеко неполный перечень присланных мне ошибок:

В первое мгновение мне стало не по себе, количество ошибок зашкаливало. Но успокоившись, я внимательно всё изучил и пришел к выводу, что искусственный и естественный интеллект недалеко ушли друг от друга. Результатом этого анализа стало письмо, которое я отправил своему товарищу:
Понедельник, 20 января 2025, 14:50 -05:00 от vorlov@xxxx.ru:
На ночь глядя, посмеялся от души!
Анализ текста проводила какая-то плохенькая программ (ИИ - искусственный интеллект).
Просто бред.
Первое не знает буквы Ё, 90% так называемых ошибок.
Второе, не понимает переноса слов.
Третье, не знает слов, таких как гусарик, спецпроверки, импортозамещение и тд и тп.
Так, что можно посмеяться и забыть!
В. Орлов
И, конечно, был серьёзный разговор с издательством. Все проблемы мы решили.
Но дискуссию на Хабре, разгоревшуюся после одного моего комментария на эту тему, стоит посмотреть:

Другое общение с ИИ было более приятным для меня. Однажды ИИ социальной сети ВКонтакте вышел ко мне с предложением отметить себя на фотографии:

Без ложной скромности скажу, что за свою продолжительную жизнь, особенно в поездках по стране не раз приходилось сталкиваться с тем фактом, что меня часто путали с Никитой Сергеевичем Михалковым, а моя мама просто меня называла «наш Михалков». А люди не просто путали, но и просили автограф. Бывало, что я оставлял автограф, но подписывался своей подписью. Это бывало и в Москве на Пятницкой, и в Минске на железнодорожном вокзале, и в Екатеринбурге в гостинице... Про Чебоксары я просто умалчиваю. Так что в этом случае ИИ можно и понять и простить. А с Н.С. Михалковым мне всё же довелось встретиться и даже обменяться книгами:

Оставил он мне автограф и на введение к моей книге. А когда я ему рассказал про то, как меня путают с ним, и что я иногда даже даю автограф, он рассмеялся и сказал: «Давай и дальше». А еще на память о той встречи у меня осталась бейсболка. Бейсболка нет, не Трампа, а бейсболка Михалкова:

Был еще один опыт общения с ИИ. Оно состоялось ровно год назад в ноябре 1925 года, когда вышла новая модель генерации и редактирования изображений Nano Banana Pro. Именно с этого момента я стал с уважением относиться к ИИ:
Я никогда не думал, что фотографии из латвийской тайги из Вентспилс-8 когда-нибудь увижу в цвете, но пришла Nana Babano Pro, и на тебе

К этому времени я уже познакомился с Jeff Smith, более того он разместил на своём ресурсе демонстрацию моего пэт-проекта svgwidgets. Толчком для нашего знакомства послужила его разработка облачной технологии CloudTk на базе tcl/tk. В тот момент проект CloudTk был заточен под tcl/tk ветки 8.6.
Пару месяцев назад мне удалось добиться того, чтобы CloudTk заработал и на tcl/tk-9.0, и я написал об этом Jeff Smith:
Привет, Джефф,
Я отправляю вам сборку CloudTk_8_9.kit.
Эта сборка запускает ваш пример TkPool как на Tcl/Tk 8.6, так и на Tcl/Tk 9.
Мне пришлось внести несколько незначительных изменений в Xdisplay.tcl и в сам пример tkpool.tcl.
Кроме того, мне удалось собрать пакет bgexec для tcl/tk-9.0 через BAWT.
С уважением, Владимир
И тут мне на глаза попалась небольшая заметка Jeff Smith. Прочитав ее, я срочно написал письмо Jeff с просьбой прислать мне протоколы его общения с ИИ. Jeff любезно прислал протоколы его общения с Claude AI Sonnet 4.6:
claude-exports-20260916-230548.zip
Привет, Владимир!
Я действительно не понимал, что делаю, и после того, как Клод внес изменения, проводил много тестов самостоятельно, что шло медленно. Позже я попросил Клода провести тестирование, и все стало намного быстрее.
С уважением Джефф
>В среду, 16 сентября 2026 г., в 22:26:19 по австралийскому восточному времени, vorlov@xxxxxx.xx написал:
>Привет, Джефф! В своей статье вы написали:
>Я ничего не знаю о программировании на C, но, учитывая весь ажиотаж вокруг ИИ, мне стало интересно, сможет ли ИИ создать для >меня обертку для Critcl на Tcl 9.0. Последняя версия Critcl 3.3.1 может создавать обертки, работающие как с Tcl 8.6, так и с Tcl 9.0. Мне >же нужна была работа только на Unix, как в Standalone Bgexec, но я подумал, что если ИИ занимается этим, то стоит добавить >поддержку и Windows, так как это может быть полезно и для других операционных систем.
>Извините за беспокойство, но не могли бы вы поделиться своим опытом и показать, как вы это делали (какие подсказки вы использовали для ИИ, его ответы и т. д.)?
>Возможно, вы могли бы прислать вам журнал переписки?
>С уважением, Владимир
Чтение присланных протоколов мне доставило искреннее удовольствие. И тут, особенно когда пришло письмо от Кати Равальдини (смотри начало статьи), я понял, что время пришло и мне пообщаться с ИИ на тему программирования. Тем более, что с момента начала разработки проекта svgwidgets у меня в голове всё время сидит мысль кое-что доработать в проекте tkpath. Это кое-что уже частично выполнено, в него уже включена функция tkp::loupe для получения скриншота с экрана. А второе, это использование градиентной заливки для объектов векторной графики (в терминах пакета tkpath это объекты prect, circle, ellipse, path, pline и т.д), включая текст (ptext) и линию (pline), а также распространить действие опции -filloverstroke на объекты prect, circle, ellipse, path.
Моё общение с ИИ началось не совсем удачно. Мои попытки зарегистрироваться на каких-то сервисах кончались неудачей: по телефону до меня не могли дозвониться, а на электронную почту ссылка для регистрации приходила спустя несколько часов. На некоторых сервисах дело доходило до оплаты, ни сама оплата не проходила. Я не стал заморачиваться ни на регистрации, ни на оплате. Мне пришла по-своему гениальная мысль: «А что я мучаюсь, может стоит воспользоваться просто поисковиком dzen/yandex или того же google?». И получилось, и без всякой регистрации и платежей.
Начал я с простого вопроса на yandex.ru:
доработать код пакета tkpath для градиентной заливки обводки графических объектов
На этот вопрос получил обнадеживающий ответ:
Быстрый ответ Алисы AI
Содержимое ответа
Доработка пакета
tkpath
для градиентной заливки и обводки — задача интересная, но требует понимания внутренней архитектуры пакета и аккуратной работы с низкоуровневыми командами. Я подобрала для вас пошаговый план, который поможет избежать типичных ошибок.
. . .
Уже неплохо. Дальше - больше. Следующим вопросом стал такой:
рабочий пример на языке Си градиентной обводки в cairo 0.99.20 для прямоугольника с другой градиентной заливкой. Изображение сохранить в файле.
И снова Алиса впечатляет меня:

Но на этом мой восторг от Алисы и закончился. Попытка получить бинарник проваливается, ну не знает компилятор, что за функция «cairo_gradient_create». Но надо отдать должное Алисе. На мой изумленный вопрос, а где же найти эту функцию, она, не смущаясь, ответила:

Тут я понял, что yandex/dzen мне не помощники. Но я не терял надежду и решил обратиться к google:

#include <cairo.h>
int main() {
// 1. Создаем поверхность для рисования (изображение 400x300) и контекст cairo
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 400, 300);
cairo_t *cr = cairo_create(surface);
// Заливаем фон белым цветом
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
cairo_paint(cr);
// Параметры нашего прямоугольника
double x = 50.0, y = 50.0;
double width = 300.0, height = 200.0;
// --- ЭТАП 1: ЗАЛИВКА ПРЯМОУГОЛЬНИКА ---
// Создаем горизонтальный линейный градиент для заливки (слева направо)
cairo_pattern_t *fill_pattern = cairo_pattern_create_linear(x, y, x + width, y);
cairo_pattern_add_color_stop_rgb(fill_pattern, 0.0, 0.1, 0.4, 0.8); // Синий
cairo_pattern_add_color_stop_rgb(fill_pattern, 1.0, 0.8, 0.1, 0.1); // Красный
// Добавляем прямоугольник в текущий векторный контур
cairo_rectangle(cr, x, y, width, height);
// Устанавливаем паттерн заливки как источник и заполняем контур
// (cairo_fill сохраняет контур пустым после выполнения, поэтому для обводки зададим его заново)
cairo_set_source(cr, fill_pattern);
cairo_fill(cr);
// Освобождаем память паттерна заливки
cairo_pattern_destroy(fill_pattern);
// --- ЭТАП 2: ГРАДИЕНТНАЯ ОБВОДКА ---
// Создаем вертикальный линейный градиент для обводки (сверху вниз)
cairo_pattern_t *stroke_pattern = cairo_pattern_create_linear(x, y, x, y + height);
cairo_pattern_add_color_stop_rgb(stroke_pattern, 0.0, 1.0, 0.8, 0.0); // Желтый
cairo_pattern_add_color_stop_rgb(stroke_pattern, 0.5, 0.0, 0.8, 0.2); // Зеленый
cairo_pattern_add_color_stop_rgb(stroke_pattern, 1.0, 0.5, 0.0, 0.8); // Фиолетовый
// Снова добавляем прямоугольник в контур для выполнения обводки
cairo_rectangle(cr, x, y, width, height);
// Настраиваем толщину линии обводки
cairo_set_line_width(cr, 12.0);
// Устанавливаем паттерн обводки как источник и рисуем границы
cairo_set_source(cr, stroke_pattern);
cairo_stroke(cr);
// Освобождаем память паттерна обводки
cairo_pattern_destroy(stroke_pattern);
// 2. Сохраняем полученный результат в PNG-файл
cairo_surface_write_to_png(surface, "gradient_rect.png");
// 3. Очищаем основные ресурсы cairo
cairo_destroy(cr);
cairo_surface_destroy(surface);
return 0;
}
И совсем вишенкой на торте была инструкция по компиляции кода:

Я просто выполнил предлагаемую команду и получил бинарник. Но поскольку я хотел получить реализацию опции -filloverstroke для всех графических объектов, поддерживаемых пакетом tkpath, немного пошаманил над этим кодом и в итоге получил прямоугольник, у которого обводка находится на заднем плане:

Да, если кто не в курсе или забыл, то напомню, что в svg-графике обводка всегда располагается поверх самого графического объекта. При этом середина обводки совпадает с внешней границей объекта, которому она принадлежит. Это хорошо видно на скриншоте. И именно из-за того, что часть обводки закрывает сам объект, часто бывает полезным (чтобы не закрывала, например, текст) обводку убирать на задний план (-filloverstroke 1). После этого маленького успеха я забыл про чары Алисы.
И тут мне удалось получить доступ к Claude AI Sonnet 4.6:

И я повторил свой вопрос:
в проект https://github.com/tcltk-depot/tkpath/ добавить поддержку градиентной заливки для обводки (опция -stroke)
Ответ вселил в меня надежду, что мы с ИИ справимся с поставленной задачей:
Запрос сложный — включил рассуждения
Готово!
Нужно расширить -stroke, чтобы он принимал цвет или имя градиента, как -fill:
set g $t[.c gradient create linear \
-stops {{0 red} {1 blue}}]
$t.c create prect 20 20 240 140 \
-fill {} \
-stroke $g \
-strokewidth 12Это целевой синтаксис после доработки, а не утверждение, что он уже работает.
В README проекта указаны три бэкенда: Cairo, CoreGraphics и GDI+. Поэтому одной замены обработчика опции недостаточно: градиент нужно поддержать в модели стиля и при рисовании на каждой платформе.
Я посмотрел README и состав generic, но не прочитал реализации файлов. Поэтому не буду выдавать непроверенный diff за готовый патч. Ниже — необходимая схема изменения и самостоятельная реализация для Cairo.
Изменения в общей части
<дальше шли рекомендации от ИИ>
Я не буду здесь описывать весь процесс, но что укрепило мою веру в ИИ. Прежде всего то, что он понял, что придется работать на трех платформах, с разными библиотеками и средами разработки. Скажу, что мне удалось довести доработку проекта почти до конца (не сделал пока для macOS). Когда я показал ИИ доработанный мною код, то он вежливо указал на допущенные мною ошибки и очень толково разъяснил почему и как их исправить. Одна из ошибок была тяжелая в смысле её обнаружения, я переставил местам и параметры в функции создания радиального градиента:
5. Исправить radial gradient в старой Cairo-реализации
В текущем TkPathPrepareForStroke() radial pattern создаётся так:
pattern = cairo_pattern_create_radial(
gradientPtr->radialFill.radialPtr->centerX,
gradientPtr->radialFill.radialPtr->centerY,
0,
gradientPtr->radialFill.radialPtr->focalX,
gradientPtr->radialFill.radialPtr->focalY,
gradientPtr->radialFill.radialPtr->radius);Порядок параметров Cairo должен быть:
pattern = cairo_pattern_create_radial(
gradientPtr->radialFill.radialPtr->focalX,
gradientPtr->radialFill.radialPtr->focalY,
0.0,
gradientPtr->radialFill.radialPtr->centerX,
gradientPtr->radialFill.radialPtr->centerY,
gradientPtr->radialFill.radialPtr->radius);
Эти параметры имеют один тип и находятся в одной области значений. Увидел ИИ и то, что я не обрабатываю опцию -units и подсказал как это сделать.
ИИ обнаружил ошибку в моём C-коде и для Windows:
6. GDI+: исправить тип opacity
В tkWinGDIPlusPath.cpp сейчас есть ошибки:
int strokeOpacity = style->strokeOpacity;и:
int fillOpacity = style->fillOpacity;Они отбрасывают дробную часть. Например, 0.5 превращается в 0.
Замените на:
double strokeOpacity = style->strokeOpacity;и:
double fillOpacity = style->fillOpacity;Это нужно сделать в:
PathC::StrokeGradient()
PathC::FillGradient()
Я исправил все свои ошибки и провёл тестирование.
Кстати, сегодня утром Jeff Smith обновил по моей просьбе демонстрацию на своем сервере. Обновление заключалось в установке новой версии пакета tkpath:
Re:CloudTk. Update 2026-11-09. Update tkpath.
сегодня в 4:29
Привет Владимир,
Демонстрационная версия была обновлена с помощью DEMOSVG-Alpine-Tcl9_Update_2026_11_09.kit. Пожалуйста, проверьте.
С уважением
Джефф
Теперь каждый желающий может протестировать результат, запустив на облачной демонстрации следующий пример:
package require tkpath
set t ".c_over"
toplevel $t
wm geometry $t 900x550
tkp::canvas $t.c -bg yellow
pack $t.c -fill both -expand 1 -padx 1m -pady 1m
set unit "userspace"
$t.c gradient create linear -units $unit -lineartransition [list 900 0 0 90] -stops {{0 red 1} {1 gray80 1}}
$t.c gradient create linear -units $unit -lineartransition [list 90 0 0 90] -stops {{0 cyan 1} {1 chocolate 1}}
$t.c gradient create linear -units $unit -lineartransition [list 40 40 300 300] -stops {{0 red 1} {0.5 gray80 1} {1 cyan 1}}
set myGradient [$t.c gradient create linear -units $unit -stops {{0 "gray80"} {1 "blue"}}]
set rgr [$t.c gradient create radial -units bbox -stops {{0 cyan 1} {0.5 gray80 1} {0.75 red 1} {1 snow 1}}]
$t.c create prect 80 240 280 340 -fill $rgr -stroke gradient1 -strokewidth 10 -rx 6
$t.c create pline 20 40 280 300 -strokewidth 20 -stroke gradient2
$t.c create ptext 100 80 -text "Stroke and Fill gradient" -fontsize 70 -fontweight bold -stroke gradient0 -strokewidth 15 -fill gradient1 -filloverstroke 1
$t.c create ptext 160 140 -text "filloverstroke=0" -fontsize 70 -fontweight bold -stroke red -strokewidth 8 -fill black -filloverstroke 0
$t.c create ptext 220 200 -text "filloverstroke=1" -fontsize 70 -fontweight bold -stroke red -strokewidth 8 -fill black -filloverstroke 1
lassign "40 200 40 200" x0 x1 xs xe
for {set i 1} {$i < 5} {incr i} {
set obj$i [$t.c create prect $xs 400 $xe 520 -stroke {} -strokewidth 20 -fill cyan -stroke red]
$t.c create ptext $xs 400 -textanchor nw -text "-fill over stroke" -fontsize 20 -stroke black
incr xs $x1
incr xe $x1
}
$t.c itemconfigure $obj1 -stroke {}
$t.c itemconfigure [expr {$obj1 + 1}] -text "-stroke {}"
$t.c itemconfigure $obj2 -filloverstroke 0
$t.c itemconfigure [expr {$obj2 + 1}] -text "-filloverstroke 0\n-strokewidth 20"
$t.c itemconfigure $obj3 -filloverstroke 1
$t.c itemconfigure [expr {$obj3 + 1}] -text "-filloverstroke 1\n-strokewidth 20"
$t.c itemconfigure $obj4 -fillopacity 0.8 -strokeopacity 0.5
$t.c itemconfigure [expr {$obj4 + 1}] -text "-filloverstroke 0\n-strokewidth 20\n-fillopacity 0.8\n-strokeopacity 0.5"
После запуска примера на экране появится следующее изображение:

Если демонстрация в облаке не запускается, то это не наша вина, а наша беда …
После всех исправлений, я написал письмо Ashok P. Nadkarni руководителю opensource-ого проекта BAWT, что мною подготовлены патчи для пакета tkpath. Мне очень понравился его ответ, а вернее его вопрос про ИИ:
Re:TkPath and SVGwidgets
4 ноября в 9:00
Привет Владимир,
Всегда рад новым возможностям!
Для меня всегда проще всего принимать код через pull-request на Github, а не патчи или zip-архивы, поэтому, пожалуйста, сделайте это.
Кроме того, пожалуйста, уточните, был ли какой-либо код непосредственно сгенерирован искусственным интеллектом.
Спасибо
/Ашок
Естественно, я ему ответил, что pull-request сделаю и рассказал как было дело с ИИ.
Кстати, оконные интерпретаторы tcl/tk с новым tkpath (tclexecomp) можно найти в github в проекте svgwidgets.
Пока я не воспользовался рекомендациями ИИ по оптимизации кода, а они все по делу. Так что мы с ним будем теперь дружить.
И буквально на днях на Хабре вышла статья «Торвальдс: «Не доверяете ИИ — пишите на ассемблере». Мне очень импонирует постулат Торвальдса из этой статьи:
Люди, которые понимают, что делают и которые разбираются в системах, смогут правильно формулировать запросы для инструментов и получать хороший код. А тот, кто не понимает сложности систем, тоже будет писать промпты и создавать процессы — но эти процессы будут давать сбои. Поэтому, я думаю, вам всё‑таки нужно понимать, как всё работает.
Прочитав это высказывание, я вспомнил, как готовили программистов тогда в 60-70-80-х годах прошлого столетия. Тогда было четкое разделение на алгоритмистов и кодировщиков, то бишь программистов. Алгоритмисты выдавали блок-схемы будущих программ, по которым программисты писали код, практически не задумываясь о процессах, которые они автоматизируют:

Тут я подумал, если бы тем алгоритмистам да современный ИИ, но это прожектёрство. А вот подготовить для работы с ИИ специалистов на уровне тех алгоритмистов, мне кажется, возможно и тогда …
И в заключении я хотел сказать несколько слов о том, почему всё же tcl/tk:
Tcl/Tk — это не пережиток прошлого; это проверенная в боях модель для будущего. Пока современная программная инженерия продолжает гнаться за трендами на тяжелые слои абстракции, раздутые среды выполнения и ограничительные модели лицензирования, этот 35-летний инструментарий выделяется тем, что делает ровно противоположное. Он предлагает механическую определенность, крошечный размер, истинную кроссплатформенность и элегантную философию «всё есть строка», которая превращает код в текучие, легко управляемые данные.
В ландшафте, где доминируют мимолетные фреймворки, инвестиции в Tcl/Tk — это инвестиции в долговечность. Выпуск Tcl 9.0 доказывает, что экосистема активно модернизируется, яростно защищая обратную совместимость. Он остается ультимативным прагматичным выбором для инженеров, которые ценят стабильность, контроль и эффективность выше индустриального хайпа. Если вы еще не смотрели на него серьезно, определенно стоит потратить время: скачайте tclsh и постройте свой следующий инструмент на фундаменте, который создавался на века.
Кстати, про «скачайте tclsh» я уже сказал выше.
Спасибо за внимание.

Комментарии 0