DigitableCourses

Цифровой портрет владельца: digit portrait

Команда digit portrait: измеренная манера речи владельца, журнал его решений со ссылкой на сессию и время, отдельно помеченная догадка. Накопление выключено по умолчанию, портрет лежит отдельно от памяти с правами 0700 и не уезжает в системный промпт.

Цифровой портрет владельца: digit portrait

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

Поэтому слои разделены в коде, а не в описании.

Слой Что это Чем проверяется Кому можно показать
Стиль как владелец формулирует: длина фраз, лексика, формы отказа и согласия пересчётом на том же корпусе; у каждой цифры хранится n никому, кроме владельца
Решение что он решил: дословная цитата + сессия + время + свидетельство цитата дословна, источник назван можно: получатель проверит, а не поверит
Догадка что он мог бы ответить на новый вопрос ничем: это сочинение модели только владельцу, всегда под шапкой

Граница проходит между вторым и третьим слоем. Она и есть смысл этой команды.

Накопление выключено по умолчанию

digit portrait on      # включить накопление
digit portrait off     # выключить

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

Живой прогон на машине, где портрет не включали:

$ digit portrait style
[СТИЛЬ · измерено]
Стиль не измерен: ни одного сообщения владельца не наблюдалось.

$ digit portrait decisions
Ничего не найдено. Поиск лексический — синонимов не понимает; попробуйте
другие слова, прежде чем считать, что решений не было.

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

Слой 1: стиль — измеренный, а не приписанный

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

В портрет кладётся дословная поверхность («мимо» ×7), а не имя класса «отказ»: воспроизводить придётся именно её. Отличительность считается лог-шансами к фону из ответов ассистента, поэтому у слова «отличительное» появляется точный смысл — то, что владелец говорит, а модель на его месте не говорит.

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

Психотипов здесь нет. Ни MBTI, ни соционики, ни архетипов: у них нет доказанной предсказательной силы, а система, на них построенная, звучит уверенно ровно там, где не знает ничего. «Логик-интроверт» нельзя ни проверить, ни опровергнуть; «отказывает словом „мимо“, 7 раз из 9 отказов» — можно и то, и другое.

Слой 2: решения — факты с происхождением

digit portrait decisions [слова для поиска] — журнал прежних решений дословно, со ссылкой на сессию и время. Не пересказ: пересказывает модель, и тогда запись перестаёт отличаться от догадки.

Фраза попадает в журнал, только если в ней есть и маркер обязательства («переходим на», «не будем», «с этого момента»), и конкретный предмет (путь, идентификатор, версия, имя в обратных кавычках). «Давай сделаем красиво» — маркер без предмета, то есть сказано мимоходом. Плюс вето: вопрос, гипотеза, пересказ чужого решения, указательное без предмета, строка структуры данных.

У записи два уровня свидетельства, и разница видна в отчёте:

  • сказано — фраза была, действий за ней в этом ходу не последовало;
  • сделано — в том же ходу агент вызывал изменяющие инструменты, и их имена записаны.

Читающие инструменты свидетельством не считаются намеренно: с bash и git в списке «сделано» становилось истинным почти всегда, то есть переставало что-либо значить.

Позднее решение не стирает прежнее, а помечает его отменённым отдельной строкой журнала (--all покажет и отменённые). История выбора — часть портрета: «уходили с X на Y, потом вернулись» знает только тот, кто хранит оба хода.

Слой 3: догадка — и три ограды вокруг неё

digit portrait draft "вопрос" собирает бриф для ответа в манере владельца. Сам модуль текста не сочиняет: он выдаёт ограничения стиля, найденные решения с цитатами и раздел ПРОБЕЛЫ — чего в портрете нет.

Живой прогон на пустом портрете:

$ digit portrait draft "стоит ли переходить на pnpm"
[СТИЛЬ · измерено]
Стиль не измерен: ни одного сообщения владельца не наблюдалось.

[РЕШЕНИЕ · факт со ссылкой]
Ничего: в портрете нет решений по этому вопросу.
Всё, что будет сказано ниже, — сочинено.

[ДОГАДКА · сочинено моделью, не владельцем]
…

[ПРОБЕЛЫ]
— стиль не измерен — воспроизводить нечего
— решений по этому вопросу нет — поиск лексический, попробуйте другие слова

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

Вся конструкция Digit держится на том, что содержание не сочиняется моделью; двойник по определению сочиняет. Совместить нельзя — можно только огородить, и ограда стоит в трёх местах кода:

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

digit portrait draft --outside показывает то же глазами не владельца: только записи со ссылками. Когда их нет, ответ — «сказать от его имени нечего». Это правильный ответ, а не сбой, который надо чинить.

Где это лежит и что при передаче машины

Портрет — самые чувствительные данные в системе: не «что человек делал», а «как он устроен в речи». Поэтому он живёт отдельно:

  • $DIGIT_HOME/portrait/ — своя директория с правами 0700, файлы 0600;
  • memories/ лежит рядом и попадает в digit backup, импорт агента и профили — портрет там оказаться не должен;
  • в системный промпт не уходит ничего. Ни блока промпта, ни предзагрузки. Иначе за портрет пришлось бы платить каждым запросом и вынести профиль речи владельца в каждый лог каждого провайдера модели. Читается портрет явно — этой командой или соответствующим инструментом;
  • во внешние провайдеры памяти не передаётся.

Файлов ровно два: style.json (достаточные статистики) и decisions.jsonl (журнал, только дописывание). Третьего нет и не будет — это и есть отсутствие файла у догадки.

Посмотреть весь портрет машиночитаемо: digit portrait --json. В этой выдаче у догадки стоит "stored": false с примечанием «догадка не хранится; собирается на запрос» — то же свойство, но в виде, который можно проверить скриптом.

Передача сессии другому человеку портрет не передаёт: записи ссылаются на сессию, обратной ссылки нет, а другой человек работает под своим $DIGIT_HOME. Если передаётся сама машина:

digit portrait forget --session <префикс id>   # убрать одну сессию
digit portrait forget --all                    # снести всё

Набрать портрет из архива

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

digit portrait ingest ПУТЬ [ПУТЬ …]   # файлы или каталоги с *.jsonl
digit portrait ingest ПУТЬ --dry-run  # посчитать, но не писать

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

Что измерено

На живом архиве: 487 транскриптов, 6 146 сообщений роли «user».

2 613 из них отброшены как шаблонная рассылка — в архивах роль «user» носит не только человек, и один и тот же зачин встретился 468 раз. Портрет, собранный без этого отсева, измерял оркестратора: эмодзи 1,40 на сообщение против 0,33 после.

Остаётся 3 533 сообщения владельца → 650 записей решений (18 на 100 сообщений); 519 «сделано», 131 «сказано»; действующих 316, отменённых 334. На коротком разговорном корпусе плотность ниже: 34 сообщения → 5 записей.

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

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

Доля фактов и догадок в том, что портрет хранит: 100 % — записи с дословной цитатой и ссылкой на источник. Догадок ноль, и не по совпадению — для них нет файла.

Цена хода при портрете из 3 533 сообщений и 650 решений — 17 мс медиана, и считается это в фоновом потоке, не на пути пользователя. Чтение журнала — 7,7 мс, поиск по нему — 26 мс, сборка отчёта стиля — 11 мс.

Границы, названные вслух

Поиск лексический. Синонимов он не понимает, и пустая выдача не доказывает отсутствия решения. Ровно поэтому и черновик, и командная строка говорят об этом в самом ответе.

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

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

Точность извлечения — 37 из 40, а не 40 из 40. Описательная проза иногда проходит под маркер обязательства. Цитата при этом остаётся дословной: ошибочной оказывается не запись, а её отнесение к решениям.

Код: agent/portrait/, навык skills/productivity/digital-portrait/. В английской документации этой команды нет — она описана только здесь.

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

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

Доска запросов
Дальше