feat: панель как фоновая служба без iTerm2 + цвет фона на клиенте #5

Merged
aep merged 16 commits from feat/4-headless-panel into main 2026-10-18 21:58:14 +03:00
Owner

Closes #4. Частично закрывает #3: O-1 (устаревший docstring) и O-3 (__pycache__/ в .gitignore), коммит 4686cd1.

Что сделано

Сервер панели больше не живёт внутри iTerm2:

  • claude_agents.py --headless — постоянная служба launchd (com.andrey.claude-agents), слушает только 127.0.0.1:8766, доступна с iPad через туннель Termius при закрытом iTerm2.
  • Скрипт AutoLaunch в iTerm2 только регистрирует инструмент Toolbelt; если служба не отвечает — launchctl kickstart и ожидание порта до ~5 с.
  • files/launchagent.py — генератор plist (plistlib, атомарная запись, пути с пробелами).
  • install.sh / uninstall.sh ставят/удаляют службу, отказываются работать из SSH-сессии, bootstrap с повторами, один процесс регистратора.
  • Связь с живым iTerm2 убрана (theme_poller, переходы во вкладки вне tmux); действия по tmux работают как раньше.
  • Цвет фона панели выбирается в браузере (⚙ → образцы / свой цвет), хранится в localStorage, текст подбирается по контрасту WCAG.
  • Сервер отвечает 403 на чужой Host и на cross-site /activate, /open-wt (защита от DNS rebinding и CSRF).
  • Тесты: 32 на unittest (python3 -m unittest discover -s tests -v), все OK.

Спека: openspec/changes/headless-panel/. План: docs/superpowers/plans/2026-10-18-headless-panel.md.

Приёмка (Task 6)

Проведена 2026-10-18 с iPad через Termius; подробности — design.md, раздел «Результаты приёмки» (3fc719b).

  • ✅ Step 1, 2, 3, 4, 6, 8, 9: служба launchd, работа при закрытом iTerm2, переходы в tmux, перезапуск после kill, цвета, повторная установка, отказ из SSH.
  • ✅ Step 5: после запуска iTerm2 один регистратор, порт держит служба, Toolbelt показывает страницу службы.
  • ✅ Step 7: выбранный в Toolbelt фон сохраняется после перезапуска iTerm2 (871d604). Step 10 (удаление) не выполнялся — по желанию.
  • Найдено и исправлено: H-1 — «⎇ папка» мигала и закрывалась, т. к. у службы launchd PATH без Homebrew и lf не находился (c810f5a).

Rulings I made

  • R-1 (design #12) — тесты, прошедшие до реализации Task 1, оставлены как фиксаторы поведения.
  • R-2 (design #13) — build_tree не трогали (требование плана); мёртвый код → M-9.
  • R-3 (design #14) — RED для test_install показан порчей текста охраны, а не запуском без охраны.
  • R-4 (design #15) — триаж финального ревью: исправить I-1…I-4, M-1, M-2, M-3, M-5, M-7, M-8, M-12; отложить M-4, M-6, M-9, M-11. I-3 существовал до ветки, но исправлен сразу.
  • R-5 (design #16) — запрос без Host или с Host без порта → 403.
  • R-6 (design #17) — тесты к исправлениям проверены прогоном на коде до исправлений (2e8ab31): 6/6 падают.
  • R-7 (design #18) — служба получает PATH оболочки, из которой запущен install.sh (EnvironmentVariables в plist), чтобы панели tmux от службы находили lf и его инстру��енты.

Находки

Маркер Суть Статус
I-1 Нечитаемый текст на средних тонах фона (порог 0.4) fixed 081b469
I-2 Служба привязана к версионному python@3.x из Homebrew fixed ac33099
I-3 Нет проверки Host/Sec-Fetch-Site: DNS rebinding, CSRF fixed 1613246
I-4 Перезагрузка раз в минуту закрывает строку цветов и палитру iPad fixed 1613246
M-1 Повторный install.sh плодит процессы регистратора fixed ac33099
M-2 Мерцание ⚙ при обновлении лимитов fixed 1613246
M-3 Нет подсказки при отказе SSH-охраны в tmux-панели fixed ac33099
M-4 Порт 8766 зашит в install.sh/uninstall.sh deferred
M-5 Гонка bootout → bootstrap при переустановке fixed ac33099
M-6 panel.log не ротируется; занятый порт → трейсбек каждые 10 с deferred
M-7 Безопасность test_install держится только на охране fixed ed159ea
M-8 Тесты serve трогают настоящий ~/.cache/claude-agents fixed 1613246
M-9 Мёртвый код iTerm2-эпохи в build_tree deferred
M-10 Рулинги не записаны в design.md fixed 6626bb4
M-11 Области нажатия 36 px < 44 pt deferred (оценить в Task 6 Step 6)
M-12 Toolbelt может остаться пустым после kickstart fixed 1613246
H-1 «⎇ папка» мигает и закрывается: lf не в PATH службы fixed c810f5a
O-1 Полный вывод упавшего теста в контексте rejected: процессная заметка
O-2 guard-main блокирует сабагентов при cwd сессии на main rejected: окружение, решено EnterWorktree
O-3 При приёмке запущен старый install.sh из main rejected: окружение, восстановлено; после merge неактуально

🤖 Generated with Claude Code

Closes #4. Частично закрывает #3: O-1 (устаревший docstring) и O-3 (`__pycache__/` в `.gitignore`), коммит 4686cd1. ## Что сделано Сервер панели больше не живёт внутри iTerm2: - `claude_agents.py --headless` — постоянная служба launchd (`com.andrey.claude-agents`), слушает только `127.0.0.1:8766`, доступна с iPad через туннель Termius при закрытом iTerm2. - Скрипт AutoLaunch в iTerm2 только регистрирует инструмент Toolbelt; если служба не отвечает — `launchctl kickstart` и ожидание порта до ~5 с. - `files/launchagent.py` — генератор plist (`plistlib`, атомарная запись, пути с пробелами). - `install.sh` / `uninstall.sh` ставят/удаляют службу, отказываются работать из SSH-сессии, `bootstrap` с повторами, один процесс регистратора. - Связь с живым iTerm2 убрана (theme_poller, переходы во вкладки вне tmux); действия по tmux работают как раньше. - Цвет фона панели выбирается в браузере (⚙ → образцы / свой цвет), хранится в `localStorage`, текст подбирается по контрасту WCAG. - Сервер отвечает 403 на чужой `Host` и на cross-site `/activate`, `/open-wt` (защита от DNS rebinding и CSRF). - Тесты: 32 на `unittest` (`python3 -m unittest discover -s tests -v`), все OK. Спека: `openspec/changes/headless-panel/`. План: `docs/superpowers/plans/2026-10-18-headless-panel.md`. ## Приёмка (Task 6) Проведена 2026-10-18 с iPad через Termius; подробности — `design.md`, раздел «Результаты приёмки» (3fc719b). - ✅ Step 1, 2, 3, 4, 6, 8, 9: служба launchd, работа при закрытом iTerm2, переходы в tmux, перезапуск после `kill`, цвета, повторная установка, отказ из SSH. - ✅ Step 5: после запуска iTerm2 один регистратор, порт держит служба, Toolbelt показывает страницу службы. - ✅ Step 7: выбранный в Toolbelt фон сохраняется после перезапуска iTerm2 (871d604). Step 10 (удаление) не выполнялся — по желанию. - Найдено и исправлено: H-1 — «⎇ папка» мигала и закрывалась, т. к. у службы launchd `PATH` без Homebrew и `lf` не находился (c810f5a). ## Rulings I made - R-1 (design #12) — тесты, прошедшие до реализации Task 1, оставлены как фиксаторы поведения. - R-2 (design #13) — `build_tree` не трогали (требование плана); мёртвый код → M-9. - R-3 (design #14) — RED для `test_install` показан порчей текста охраны, а не запуском без охраны. - R-4 (design #15) — триаж финального ревью: исправить I-1…I-4, M-1, M-2, M-3, M-5, M-7, M-8, M-12; отложить M-4, M-6, M-9, M-11. I-3 существовал до ветки, но исправлен сразу. - R-5 (design #16) — запрос без `Host` или с `Host` без порта → 403. - R-6 (design #17) — тесты к исправлениям проверены прогоном на коде до исправлений (2e8ab31): 6/6 падают. - R-7 (design #18) — служба получает `PATH` оболочки, из которой запущен `install.sh` (`EnvironmentVariables` в plist), чтобы панели tmux от службы находили `lf` и его инстру��енты. ## Находки | Маркер | Суть | Статус | |---|---|---| | I-1 | Нечитаемый текст на средних тонах фона (порог 0.4) | fixed 081b469 | | I-2 | Служба привязана к версионному python@3.x из Homebrew | fixed ac33099 | | I-3 | Нет проверки Host/Sec-Fetch-Site: DNS rebinding, CSRF | fixed 1613246 | | I-4 | Перезагрузка раз в минуту закрывает строку цветов и палитру iPad | fixed 1613246 | | M-1 | Повторный install.sh плодит процессы регистратора | fixed ac33099 | | M-2 | Мерцание ⚙ при обновлении лимитов | fixed 1613246 | | M-3 | Нет подсказки при отказе SSH-охраны в tmux-панели | fixed ac33099 | | M-4 | Порт 8766 зашит в install.sh/uninstall.sh | **deferred** | | M-5 | Гонка bootout → bootstrap при переустановке | fixed ac33099 | | M-6 | panel.log не ротируется; занятый порт → трейсбек каждые 10 с | **deferred** | | M-7 | Безопасность test_install держится только на охране | fixed ed159ea | | M-8 | Тесты serve трогают настоящий ~/.cache/claude-agents | fixed 1613246 | | M-9 | Мёртвый код iTerm2-эпохи в build_tree | **deferred** | | M-10 | Рулинги не записаны в design.md | fixed 6626bb4 | | M-11 | Области нажатия 36 px < 44 pt | **deferred** (оценить в Task 6 Step 6) | | M-12 | Toolbelt может остаться пустым после kickstart | fixed 1613246 | | H-1 | «⎇ папка» мигает и закрывается: `lf` не в PATH службы | fixed c810f5a | | O-1 | Полный вывод упавшего теста в контексте | rejected: процессная заметка | | O-2 | guard-main блокирует сабагентов при cwd сессии на main | rejected: окружение, решено EnterWorktree | | O-3 | При приёмке запущен старый install.sh из main | rejected: окружение, восстановлено; после merge неактуально | 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 13 commits 2026-10-18 20:21:44 +03:00
Refs #4

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #4

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #4

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aep added 2 commits 2026-10-18 21:53:51 +03:00
The launchd service runs with PATH=/usr/bin:/bin:/usr/sbin:/sbin; tmux
split-window gives the new pane the caller's PATH, so 'exec lf' failed
and the pane closed at once. install.sh now records its own PATH in the
plist EnvironmentVariables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aep added 1 commit 2026-10-18 21:57:02 +03:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aep merged commit 5320bc2c46 into main 2026-10-18 21:58:14 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: aep/cc-agents-iterm-plugin#5
No description provided.