Skip to content

gnu-emacs-ru/carriage

Repository files navigation

Carriage — «вязальная машинка для кода» на базе Emacs/Org

1 Философия

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

Принципы:

  • Прямой путь к результату: минимальные шаги, быстрый полезный отклик, прозрачные отчёты.
  • Контроль и воспроизводимость: изменения оформляются блоками, dry-run → apply выполняются явно; patch всегда через git-движок.
  • Прозрачность: видны логи трафика, стоимость (doc-cost), состояние документа и отпечатки (FINGERPRINT).
  • Литературное программирование и Reproducible Research: один Org-документ хранит задачу, контекст, код и полученные изменения; история в блоках и отпечатках делает процесс повторяемым.

Требования: Emacs 27+, установлен Git, локальный проект (без TRAMP для файловых операций и git).

2 Установка (use-package, рекомендуется)

Минимальная установка Carriage и gptel (OpenAI-совместимый API; ключ в окружении OPENAI_API_KEY).

;; gptel (минимум): задайте OPENAI_API_KEY в окружении
(use-package gptel
  :ensure t
  :init
  (setq gptel-model 'gpt-4o-mini)  ;; замените на доступную модель
  (setq gptel-backend
        (gptel-make-openai "OpenAI"
          :key (getenv "OPENAI_API_KEY")
          :host "api.openai.com"
          :endpoint "/v1/chat/completions")))

;; Carriage из локального клона:
;;   git clone https://github.com/<you>/carriage ~/.emacs.d/site-lisp/carriage
(use-package carriage
  :load-path "~/.emacs.d/site-lisp/carriage/lisp"
  :commands (carriage-mode carriage-global-mode)
  :init
  ;; (carriage-global-mode 1)  ;; опционально: глобальный префикс/меню под C-c e
  )

Альтернатива (из исходников проекта): добавьте в init.el:

(add-to-list 'load-path (expand-file-name "lisp" default-directory))
(require 'carriage)

Переключение языка UI (ru/en):

;; ru или en
(setq carriage-i18n-locale 'ru)

3 Пример 1 (чат, Intent=Ask)

Цель: быстро «задать вопрос» и увидеть потоковый ответ.

  1. Откройте Org-файл и включите режим: M-x carriage-mode
  2. Переключите Intent на Ask: C-c e i
  3. Отправьте запрос: C-c RET
  4. Остановите поток при необходимости: C-c e k
  5. Где смотреть:
    • Состояние/индикаторы — в modeline (см. «UI и modeline»)
    • Логи трафика — C-c e T (или M-x switch-to-buffer → carriage-traffic:…)
    • Отчёт — C-c e r

Подсказки:

  • Intent: Ask — диалог/вопросы; Code — запросы на генерацию кода/патчей; Hybrid — смешанный режим. Переключение: C-c e i.
  • Стоимость документа (doc-cost) накапливается по факту завершения запросов и показывается отдельным бейджем (см. ниже).

4 Пример 2 (патчи, Intent=Code или Hybrid)

Цель: получить begin_patch, безопасно применить и увидеть отчёт.

  1. Переключите Intent: C-c e i → выберите Code или Hybrid
  2. Сформулируйте задачу. Просите модель:
    • Генерировать один или несколько файлов или вснести правки (если задан контекст, сама Carriage не найдёт содержимое файла, если только его наличие через карту)
    • C-c RET - отправьте запрос
  3. Получили patch-блок(и) → примените:
    • Apply под точкой/в регионе: C-c C-c
    • Открыть отчёт: C-c e r (см. ok/skip/fail)
  4. После полного успеха:
    • В Messages появится сводка (carriage-announce)
    • Заголовок применённого #+begin_patch будет аннотирован (:applied t …); содержимое может быть скрыто политикой (см. «Настройки»)

Важно:

  • Патчи всегда идут через git-движок (даже если выбран другой движок в UI).
  • Файловые операции (create/rename/delete/sre/aibo) могут выполняться локальным emacs-движком; при включённом stage-policy=’index для git — через git add/rm/mv.

5 Пример 3 (begin_context — файлы как входной контекст)

Цель: управлять перечнем файлов, которые модель читает на вход.

Что такое begin_context: это блок со списком путей; их текущее содержимое добавляется к подсказке (в пределах лимитов профиля/скоупа).

Два способа получить begin_context:

  • Попросить модель в режиме Ask: «Собери begin_context по карте проекта для этой задачи».
  • Опционально — вставлять через «Context Navigator»: C-c n i

Профиль и скоуп:

  • Переключить профиль P1/P3: C-c e t P (влияет на лимиты контекста)
  • Переключить scope all/last: C-c e t s
  • Состав контекста и счётчик [Ctx:N] видны в modeline

6 Простой цикл (чек-лист)

  1. Описать задачу (Ask/Code/Hybrid) → отправить (C-c e RET)
  2. Получить begin_patch → Dry-run (C-c e d) → Apply (C-c e a) → Отчёт (C-c e r)
  3. При успехе убедиться в :applied t и сводке в Messages
  4. Повторить до «зелёного» отчёта

7 Расширенный цикл (typed blocks, структурированный подход)

Когда освоен простой цикл — добавьте структуру и контекст:

  • Минимум: #+begin_task / #+begin_analysis / #+begin_plan / #+begin_patch
  • Контекст: #+begin_context с путями (может генерироваться моделью или навигатором)
  • По ходу итераций просите модель уточнять/расширять begin_context, менять Intent (Ask ↔ Code/Hybrid) и дополнять план

Опционально: удобные Org-аббревиатуры для вставки блоков

(require 'carriage-typedblocks-templates)
(carriage-typedblocks-install-structure-templates)

8 UI и modeline: карта сегментов

Ниже — ориентир по ключевым сегментам (внешний вид и набор могут отличаться в зависимости от профиля/настроек).

СегментЧто показываетКлик/действие (пример)Tooltip/подсказка (пример)Быстрая клавиша
IntentAsk / Code / HybridМеню IntentТекущий Intent и эффект на подсказкуC-c e i
ModelТекущая модель gptelМеню выбора моделиИмя и детали моделиC-c e m
EngineДвижок применения (policy)Меню выбора движкаДля git — policy: in-place/wip/ephemeralC-c e E
Stateidle/sending/streaming/errorСтадия транспорта, спиннер/ожидание
Apply statusСводка последнего отчётаОткрыть отчётok/skip/fail/totalC-c e r
[Ctx:N]Кол-во файлов в контекстеВключатели/лимиты контекстаИсточники (doc/gptel/visible/patch/map)C-c e t … (см. «Клавиши»)
Doc-costСуммарная стоимость документаОткуда берётся и время обновления
AbortПрерывание текущего потокаЗавершит процесс, очистит ресурсыC-c e k

Doc-cost (коротко):

  • Источник: строки #+CARRIAGE_RESULT / служебный FINGERPRINT в документе после завершения запросов.
  • Обновление: автоматически по завершении; отображается сумма известных стоимостей.
  • Валюта: символ задаётся carriage-pricing-currency-symbol.

9 Клавиши

Префиксные (C-c e …):

КлавишаДействие
SPCМеню Carriage
?Справка по клавишам
RETОтправить буфер
M-RETОтправить поддерево
dDry-run под точкой
aApply под точкой/в регионе
AПрименить последнюю итерацию
rОткрыть отчёт
kAbort (прервать поток)
mВыбрать модель
SВыбрать Suite
iПереключить Intent
EВыбрать движок применения
t gКонтекст: gptel
t fКонтекст: файлы из begin_context
t pКонтекст: файлы из begin_patch
t mКонтекст: карта проекта (begin_map)
t vКонтекст: видимые буферы
t aScope = all
t lScope = last
t sПереключить scope
t PПрофиль контекста P1/P3
wПереключиться на WIP-ветку (git)
RSoft reset
ccCommit: все изменения
clCommit: последняя итерация
LОбщий лог
TЛог трафика
eОткрыть буфер Carriage
fЧат по текущему файлу
nСоздать документ задачи (если доступно)

Внутри carriage-mode (контекстные):

КлавишаДействие
C-c C-cКонтекстно: применить patch / собрать план
C-c !Применить последнюю итерацию
C-c RETОтправить буфер

Пользовательские/опциональные (пример привязки):

КлавишаДействие
C-c n eЗапуск «ветвления» (branching transient), пример
C-c n iВнешний context-navigator (пример)

Пример биндинга (пользовательская привязка):

(with-eval-after-load 'carriage-mode
  (define-key carriage-mode-map (kbd "C-c n e") #'carriage-branching-transient)
  (define-key carriage-mode-map (kbd "C-c n i") #'my-context-navigator-insert))

10 Настройки (важное)

КатегорияПеременнаяНазначение (кратко)
Контекстcarriage-mode-include-doc-contextВключать begin_context из документа
carriage-mode-include-visible-contextВключать видимые буферы (терминалы — хвост N строк)
carriage-mode-include-gptel-contextВключать внешние пути из gptel (если настроено)
carriage-mode-include-patched-filesВключать файлы, упомянутые в begin_patch
carriage-mode-context-max-filesЛимит количества файлов в контексте
carriage-mode-context-max-total-bytesЛимит общего объёма контента (байты)
Скоуп/Профильcarriage-doc-context-scope‘all или ‘last (какие begin_context учитывать)
(переключатели тумблеров)t a/t l/t s — scope; t P — профиль P1/P3
Apply/веткиcarriage-git-branch-policyПолитика git: in-place / wip / ephemeral
carriage-apply-stage-policyСтадирование: none / index
carriage-apply-applied-block-policyПост-обработка удачных patch (annotate/none)
carriage-apply-strip-body-on-annotateПри annotate — очищать тело блока
Стоимостьcarriage-pricing-currency-symbolСимвол валюты (UI/бейджи/подсказки)
Локализацияcarriage-i18n-locale‘ru или ‘en (надписи/подсказки в UI)

11 Engine UI и git-комбо

Выбор движка применения (C-c e E) отражает правила:

  • Для git-движка показываются только «комбо»: git:in-place / git:wip / git:ephemeral (bare «git» скрыт).
  • patch всегда выполняется git-движком, независимо от выбранного «общего» движка.
  • Tooltip у Engine показывает текущую политику веток.

12 Состояние документа и FINGERPRINT

Carriage «прикалывает» тонкие следы прямо в Org:

  • #+CARRIAGE_RESULT — метаданные последнего запроса (backend, модель, usage, стоимость, timestamp).
  • FINGERPRINT — служебная метка итерации, предотвращает дубликаты, помогает агрегировать стоимость.
  • Эти строки и служебные свойства не попадают в подсказку модели; они для воспроизводимости и UI.

13 Безопасность и ограничения

  • TRAMP-пути не поддерживаются в v1 (поиск корня, файловые операции и git — локальные).
  • Пути нормализуются и проверяются границами проекта; «опасные» или внешние пути отклоняются.
  • patch всегда через git-движок; emacs-движок обслуживает локальные ops.
  • Прерывание (Abort) и сторожевой таймер защищают от зависаний; состояние и процессы очищаются автоматически.

14 FAQ / Неполадки

  • «patch unsupported by emacs engine»: выберите git-движок (C-c e E) и один из git:in-place/wip/ephemeral; убедитесь, что проект — git-репозиторий.
  • Нет Git: инициализируйте репозиторий (git init) или используйте только файловые операции до инициализации.
  • Нет OPENAI_API_KEY / ошибки gptel: установите ключ в окружение, проверьте модель в gptel.
  • [Ctx:?] не обновляется: подождите 1–2 секунды (асинхронно) или перепроверьте тумблеры контекста (C-c e t …); откройте лог трафика (C-c e T).
  • Как прервать зависший поток: C-c e k; затем просмотрите общий лог (C-c e L) и лог трафика (C-c e T).
  • Стоимость документа не видна: сделайте хотя бы один успешный запрос; doc-cost строится по #+CARRIAGE_RESULT.

15 Где читать дальше

  • Спецификации: ./spec/index.org
    • apply-pipeline, engines, context-integration, ui, security, testing, pricing
  • Исходные модули: ./lisp/*.el
  • Тесты: ./test/*

16 Лицензия

См. файл LICENSE в корне репозитория.

About

Knitting machine for Code

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages