При анализе структуры и текстов словарных статей help для рантайма Forth под управлением LLM-агента выявляется ряд системных закономерностей. Для языковой модели справка — это не справочный текст для человека, а строго детерминированный контракт системных вызовов (API Schema). Любая неточность в синтаксисе примера, стековой нотации или отклике рантайма приводит к сбою конечного автомата диалога.

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

Общие системные замечания к словарным статьям
1. Синтаксис строковых литералов Forth
Проблема: Попытки передать строку в привычном для других языков виде: "текст" вплотную к кавычкам или 'текст'.

Физика парсера: Токенизатор Forth делит поток исключительно по пробелам. Токен "текст" парсер ищет в словаре целиком и падает с E word-not-found token="текст".

Правило: Строки всегда задаются через ключевое слово ." с обязательным пробелом после него: ." текст". При этом ." кладёт на стек пару ( addr len ).

2. Протокол одиночного cr (Line Flushing)
Проблема: Использование cr в середине цепочки команд или перед маркером EXECUTE:.

Физика рантайма: cr вызывает принудительный сброс (flush) буфера в канал обмена. Появление промежуточного cr дробит единый шаг на две независимые посылки. Первая посылка уходит агенту без управляющего маркера, ломая ReAct-петлю.

Правило: В строке внутреннего шага допустим ровно один cr в самом конце строки. Все промежуточные значения разделяются словом space.

3. Символьная точность поля «Ожидаемый вывод»
Проблема: Использование шаблонных заглушек вроде (вывод зависит от аргументов) или неполных снимков вывода.

Физика агента: Модель валидирует корректность шага сопоставлением входящей строки Its output: ... с блоком ожидаемого вывода. Если в справке написано «вывод зависит от аргументов», а возвращается пустая строка или конкретное число, агент не уверен в успехе и начинает галлюцинировать повторные проверки.

Правило: Поле «Ожидаемый вывод» обязано в точности воспроизводить байты, которые напечатает рантайм:

Для «тихих» слов (память, сеттеры): EXECUTE: ответь оператору

Для слов чтения: <значение> EXECUTE: ответь оператору

Для текстовых подтверждений: <текст> EXECUTE: ответь оператору

4. Консистентность стековых контрактов
Проблема: Смешение русских терминов (дескриптор, адрес), разного порядка аргументов в однотипных словах или приписывание сигнатур словам-генераторам (как variable).

Правило:

Использовать единые краткие идентификаторы типов аргументов на английском: n, addr, len, flag, provider, dev, ch.

Соблюдать порядок аргументов: в Forth-сеттерах изменяемое значение или строка почти всегда идут первыми, а целевой объект (дескриптор) находится на вершине стека (TOS): ( val dev -- ) или ( addr len provider -- ).

Слова, создающие новые словарные статьи (variable <name>, timer <name>), не имеют контракта ( -- addr ) в момент исполнения — адрес возвращает уже созданное имя <name>.

5. Человечный академический стиль «Канонического ответа»
Проблема: Механическая склейка шаблона: «Я выполнил слово X: описание назначения». Это противоречит системному промпту, где Архимед задан как ведущий ученый-исследователь.

Правило: Канонический ответ формулируется от первого лица, на чистом русском языке, строго по существу задачи оператора (с фиксацией прибора, единиц измерения и фактического статуса оборудования):

Плохо: «Я выполнил слово odp-read-voltage: измеряет напряжение.»

Хорошо: «Я измерил выходное напряжение на клеммах источника ODP6033: на канале 1 зафиксировано 12004 мВ.»

Стандартная спецификация словарной статьи (Golden Spec)
Каждая словарная статья словаря лаборатории должна строго следовать 7-блочной структуре:

# <имя_слова>

Стековый контракт: ( <TOS-вход> -- <TOS-выход> )
Назначение: <Одно-два предложения: физическое или системное действие, что снимается со стека, что возвращается, сайд-эффекты>.

Типовые запросы оператора:
- «<Прямой запрос действия от первого лица>»
- «<Альтернативная формулировка задачи>»

Исполняемый пример (внутренний шаг):
<валидная_цепочка_forth> space ." EXECUTE: ответь оператору" type cr

Ожидаемый вывод:
<точный_текст_отклика_рантайма> EXECUTE: ответь оператору

Ошибки и краевые условия:
- <Точный_код_ошибки E ... word=...> — причина сбоя.
- <Аппаратный лимит / диапазон значений>.

Смежные слова:
- <слово> ( <контракт> ) — краткая роль

Канонический ответ оператору (от первого лица):
«<Академическое подтверждение на русском языке от первого лица с единицами СИ и именами приборов>.»

[Чеклист проверки статьи]
 1. Имя: Есть ли # <имя_слова> в первой строке?
 2. Контракт: Только английские идентификаторы (n, addr, len, flag, provider, dev, ch).
 3. Пример: Строки через ." текст"; ровно один cr; нет \ и ```; space перед маркером.
 4. Ожидаемый вывод: Соответствует ли он в точности коду примера?
 5. Ошибки: Указано ли внутреннее имя примитива (word=store, word=dot)?
 6. Ответ: Звучит ли он естественно от первого лица? Сообщает ли факты и единицы измерения?

# mcp-ping

Стековый контракт: ( -- )
Назначение: Проверяет работоспособность транспортного канала MCP (Model Context Protocol). Отправляет тестовый сигнал и выводит диагностическую строку подтверждения «MCP is alive». Аргументов со стека не снимает, значений не возвращает.

Типовые запросы оператора:
- «Архимед, проверь связь с MCP»
- «Жив ли MCP транспорт?»
- «Выполни пинг MCP-сервера»

Исполняемый пример (внутренний шаг):
mcp-ping space ." EXECUTE: ответь оператору" type cr

Ожидаемый вывод:
MCP is alive EXECUTE: ответь оператору

Ошибки и краевые условия:
- Исполняется безусловно, ошибок стека нет. При обрыве сетевого сокета вывод блокируется по таймауту подсистемы ввода-вывода.

Смежные слова:
- mcp-status ( mcp -- flag ) — проверка статуса сервера (флаг активности)
- mcp-info ( mcp -- ) — вывод подробных параметров конфигурации MCP
- mcp-server ( -- mcp ) — получение дескриптора активного MCP-сервера
- mcp-start ( mcp addr len -- ) — запуск сервера на указанном адресе/порту
- mcp-stop ( mcp -- ) — остановка службы MCP

Канонический ответ оператору (от первого лица):
«Я проверил канал связи с MCP: транспортный шлюз активен и отвечает штатно (получен отклик «MCP is alive»).»


# ai-init

Стековый контракт: ( provider -- )
Назначение: Инициализирует контекст диалога указанного AI-провайдера. Полностью очищает накопленную историю сообщений в буфере сессии, сохраняя исходный системный промпт роли. Аргумент-дескриптор снимается со стека, значений не возвращается.

Типовые запросы оператора:
- «Архимед, начни беседу с локальной моделью заново»
- «Очисти историю диалога AI»
- «Сбрось контекст сессии провайдера»

Исполняемый пример (внутренний шаг):
ai-local ai-init space ." EXECUTE: ответь оператору" type cr

Ожидаемый вывод:
EXECUTE: ответь оператору

Ошибки и краевые условия:
- E underflow word=ai-init — на стеке данных нет дескриптора провайдера.
- E invalid-address word=ai-init — переданный адрес не является валидным объектом AI-провайдера.

Смежные слова:
- ai-local ( -- provider ) — дескриптор локального встроенного провайдера модели
- ai-ping ( provider -- ) — проверка доступности инференс-сервиса модели
- ai-info ( provider -- ) — вывод параметров провайдера (имя, модель, длина контекста)
- ai-chat64 ( provider b64-addr b64-len -- ) — отправка запроса в формате Base64
- ai ( addr len -- ) — создание/регистрация именованного объекта AI-провайдера

Канонический ответ оператору (от первого лица):
«Я выполнил инициализацию AI-провайдера: история контекста успешно очищена, системный регламент роли сохранён в исходном состоянии.»


# Утверждённые эталонные примеры (канон, принят 2026-09-28)

Эти четыре статьи — эталон для тиражирования по всей базе docs/words/: ! (память),
swap (стек), odp-read-voltage (прибор, единицы), ai-model (сеттер).

## Пример 1. Память: !

# !

Стековый контракт: ( n addr -- )
Назначение: Записывает целое значение n в ячейку памяти по адресу addr (операция store). Оба аргумента снимаются со стека; запись по нулевому (NULL) адресу запрещена.

Типовые запросы оператора:
- «Архимед, запиши значение 42 в переменную answer»
- «Сохрани уставку в ячейку памяти»

Исполняемый пример (внутренний шаг):
variable answer 42 answer ! answer @ . space ." EXECUTE: ответь оператору" type cr

Ожидаемый вывод:
42 EXECUTE: ответь оператору

Ошибки и краевые условия:
- E underflow word=store — на стеке меньше 2 ячеек (нужны адрес и значение).
- E invalid-address word=store — адрес равен нулю (NULL), запись запрещена.

Смежные слова:
- @ ( addr -- n ) — чтение ячейки памяти (fetch)
- +! ( n addr -- ) — прибавление n к содержимому ячейки
- c! ( n addr -- ) — запись байта в память
- variable <name> — создание именованной переменной (адрес ячейки возвращает имя)

Канонический ответ оператору (от первого лица):
«Я записал число 42 в ячейку переменной answer: контрольное чтение answer @ вернуло 42 — значение сохранено в памяти.»

## Пример 2. Стек: swap

# swap

Стековый контракт: ( a b -- b a )
Назначение: Обменивает местами два верхних элемента стека данных (TOS и SOS). Глубина стека не изменяется.

Типовые запросы оператора:
- «Архимед, поменяй местами два верхних значения на стеке»
- «Переставь аргументы местами»

Исполняемый пример (внутренний шаг):
1 2 swap . space . space ." EXECUTE: ответь оператору" type cr

Ожидаемый вывод:
2 1 EXECUTE: ответь оператору

Ошибки и краевые условия:
- E underflow word=swap — на стеке меньше 2 элементов.

Смежные слова:
- rot ( a b c -- b c a ) — циклическое вращение трёх верхних элементов
- -rot ( a b c -- c a b ) — обратное вращение трёх верхних элементов
- over ( a b -- a b a ) — копирование второго элемента на вершину
- nip ( a b -- b ) — удаление второго элемента

Канонический ответ оператору (от первого лица):
«Я поменял местами два верхних значения стека: последовательность 1 2 стала 2 1, глубина стека не изменилась.»

## Пример 3. Прибор + единицы: odp-read-voltage

# odp-read-voltage

Стековый контракт: ( dev ch -- millivolts )
Назначение: Снимает фактическое напряжение на выходных клеммах канала (SCPI MEASure:VOLTage?) и кладёт его на стек в милливольтах. Измеряет реальное значение: при выключенном выходе — около 0 мВ независимо от уставки.

Типовые запросы оператора:
- «Архимед, какое напряжение сейчас на клеммах канала 1?»
- «Сними фактическое напряжение выхода»

Исполняемый пример (внутренний шаг):
odp-device 1 odp-read-voltage . space ." EXECUTE: ответь оператору" type cr

Ожидаемый вывод:
5000 EXECUTE: ответь оператору

Ошибки и краевые условия:
- E empty word=odp-read-voltage — на стеке нет дескриптора и номера канала.
- E invalid-address — адрес не является прибором ODP.
- E range word=odp-read-voltage — канал вне диапазона 1..odp-channels.
- E network device=<имя> / E protocol device=<имя> — нет связи с прибором или ответ некорректен.

Смежные слова:
- odp-device ( -- dev ) — дескриптор прибора ODP
- odp-read-voltage-setpoint ( dev ch -- millivolts ) — заданная уставка напряжения
- odp-read-current ( dev ch -- milliamps ) — фактический ток канала
- odp-output-on ( dev ch -- ) — включение выхода канала

Канонический ответ оператору (от первого лица):
«Я измерил выходное напряжение на клеммах источника ODP6033: на канале 1 зафиксировано 5000 мВ.»

## Пример 4. Сеттер: ai-model

# ai-model

Стековый контракт: ( addr len provider -- )
Назначение: Задаёт имя модели AI-провайдера (например deepseek-chat, qwen3:14b). Провайдер — верхний элемент стека. Сеттер действует до финализации: после ai-source или ai-init изменение отклоняется.

Типовые запросы оператора:
- «Архимед, переключи модель провайдера на deepseek-chat»
- «Задай имя модели для локального провайдера»

Исполняемый пример (внутренний шаг):
." deepseek-chat" ai-deepseek ai-model space ." EXECUTE: ответь оператору" type cr

Ожидаемый вывод:
EXECUTE: ответь оператору

Ошибки и краевые условия:
- E compile-mode word=ai-model — вызов внутри определения слова (только интерпретация).
- E underflow word=ai-model — на стеке меньше 3 ячеек (нет адреса, длины и провайдера).
- E invalid-address word=ai-model — верх стека не является адресом AI-провайдера.
- E provider-frozen provider=<имя> — провайдер уже инициализирован, сеттеры заморожены.

Смежные слова:
- ai ( addr len -- ) — создание AI-провайдера с дефолтами локального Ollama
- ai-deepseek ( -- provider ) — дескриптор DeepSeek-провайдера
- ai-local ( -- provider ) — дескриптор локального Ollama-провайдера
- ai-source ( provider addr len -- ) — создание источника беседы
- ai-init ( provider -- ) — инициализация диалога (после неё сеттеры заморожены)

Канонический ответ оператору (от первого лица):
«Я задал провайдеру DeepSeek имя модели deepseek-chat: параметр сохранён в конфигурации и будет применён при создании источника; после инициализации смена модели отклоняется.»
