diff --git a/.scratch/handoffs/20260721-0343-xray-proxy-after-04.md b/.scratch/handoffs/20260721-0343-xray-proxy-after-04.md deleted file mode 100644 index d0781e3..0000000 --- a/.scratch/handoffs/20260721-0343-xray-proxy-after-04.md +++ /dev/null @@ -1,74 +0,0 @@ -# Handoff: headless-xray-proxy — после задачи 04, перед 05 - -Дата: 2026-07-21. Одноразовый документ (правило AGENTS.md): следующая -сессия читает, продолжает, по завершении вехи удаляет и пишет новый. - -## Состояние конвейера - -- Порядок прогона: 06 (done, baseline high) → 03 (done) → 04 (done) → - **следующая — 05**. -- 04 закрыта полным конвейером и закоммичена: - `0432c4a feat(xray-proxy): добавлена проверяемая установка Xray командой install`. - Резолюция и детали — в - `.scratch/headless-xray-proxy/issues/04-verified-xray-installation.md` - (Status: done). Тесты после 04: **79 OK + 8 PASS** - (`PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests`, - `bash tests/test_proxy_launchers.sh`). -- Эксперимент «реализация на medium» завершён и зафиксирован (см. ниже); - затраты по этапам — `.scratch/headless-xray-proxy/token-ledger.md` - (итоги 03/04, сводка 06/03/04, наблюдения). - -## Решения пользователя 2026-07-21 (обязательны для 05) - -Зафиксированы в `~/.claude/skills/claude-subagent-playbook/` -(SKILL.md — эффорт-карта Claude-субагентов; references/codex-exec.md — -уточнение к правилу эффорта 2026-07-19; references/lessons.md — эмпирика -прогонов 03/04) и в памяти `codex-effort-calibration.md`. Кратко: - -- Codex: реализация по отревьюированному тикету → medium допустима; - экономию эффорта считать по конвейеру целиком. -- Claude-субагентам effort задавать ЯВНО при спавне: xhigh — ревью - постановок/планов; high — слепое TASK-ревью (ниже не опускать); - medium/default — узкие перепроверки. Внутри одного агента effort между - резюмами не менять. -- Высокий effort не страхует от выдумки внешних фактов (казус `.dgst` в - 04) — форматы артефактов/версии проверять первоисточником или фикстурой. - -## Следующий шаг: задача 05 - -`.scratch/headless-xray-proxy/issues/05-package-delivery-and-acceptance.md` -— доставка пакета и приёмка. Особенность: включает РУЧНЫЕ приёмочные -прогоны пользователя на Ubuntu / РЕД ОС / Astra / Alt (по доступности) — -планируй конвейер с точками ожидания пользователя. Старт — по команде -пользователя («поехали по 5»): постановка → Codex spec-review (high) → -переписывание тикета оркестратором → реализация (medium, если типовая) → -саморевью (resume, medium) → два слепых ревью (Opus TASK high + Codex -CODE high свежим тредом) → триаж (resume) → узкие перепроверки (medium) → -приёмка → conventional commit (русский, Зачем/Что/Проверка). - -## Механика и грабли (проверено в 03/04) - -- Codex-вызовы, шаблоны промптов, правила resume — playbook - references/codex-exec.md. Критично: `codex exec resume ` принимает - ТОЛЬКО `-c`-оверрайды; thread_id забирать из первой строки stdout-JSONL - сразу после старта; usage убитого хода теряется (нет `turn.completed`). -- Смена `model_reasoning_effort` при resume кэш Codex-треда не сбрасывает. -- Леджер: Codex — `grep '"usage"' stdout*.jsonl` (последняя строка хода), - Claude-субагенты — `subagent_tokens` из task-notification; сравнивать по - «свежий input + output». -- Scratch прогонов 03/04: `/tmp/xray-lifecycle-OZHc`, `/tmp/xray-04-H156` - (архив, для 05 создать свой каталог). -- Секреты: реальные VLESS/UUID/ключи — никогда в репо/выводы; чужие - untracked-артефакты (`zed/.config/*`, `agents/.agents/skills/*`, - `scripts/setup-xray-proxy.sh`) не трогать и не коммитить; git add — только - адресно или `-u`. - -## Suggested skills - -- `codex-subagent-playbook` — оптика делегирования; конвейер и механика - Codex — в `~/.claude/skills/claude-subagent-playbook/` (SKILL.md + - references), читать перед стартом 05. -- `conventional-commits` — для коммитов (русский, совершенный вид, - Зачем/Что/Проверка). -- `handoff` — по завершении 05 обновить этот документ (удалить, создать - новый по той же схеме). diff --git a/.scratch/handoffs/20260721-0743-xray-proxy-05-ready-for-human.md b/.scratch/handoffs/20260721-0743-xray-proxy-05-ready-for-human.md new file mode 100644 index 0000000..a3ad669 --- /dev/null +++ b/.scratch/handoffs/20260721-0743-xray-proxy-05-ready-for-human.md @@ -0,0 +1,62 @@ +# Handoff: headless-xray-proxy — задача 05 готова к ручной приёмке + +Дата: 2026-07-21 07:43 EDT. Заменяет прежние handoff задачи 05. + +## Состояние + +Тикет `.scratch/headless-xray-proxy/issues/05-package-delivery-and-acceptance.md` +переведён в `ready-for-human`. Автоматическая часть выполнена; продуктовый CLI +менять не потребовалось. + +## Что изменено + +- Корневой `README.md` описывает готовый управляемый Xray и отдельное + подключение через `stow xray-proxy`. +- `xray-proxy/README.md` явно фиксирует отсутствие systemd, автозапуска и + автоматического перехода между прокси. +- `tests/test_xray_proxy_full.sh` запускает полный набор под системным Python и + CPython 3.8 через `uv`, а также Bash-тесты и проверку установки. +- Поддельный Xray в `tests/test_xray_proxy_managed.py` сохраняет отдельный + исполняемый файл и получает доступ к библиотекам исходного Python. Это + устраняет ложные падения переносимой сборки `uv`, не ломая тест удалённого + исполняемого файла. +- `tests/test_install.sh` создаёт тестовые деревья только из отслеживаемых + Git-файлов внутри одного временного каталога и удаляет его при выходе. + +## Проверка + +`bash tests/test_xray_proxy_full.sh` завершился с кодом 0: + +- системный Python 3.14: 79 тестов, `OK`; +- Bash-интеграция: 8 проверок, `PASS`; +- установка: `All install tests passed`, остатков `dotfiles-install-test.*` в + `/tmp` нет; +- CPython 3.8.20 через `uv`: 79 тестов, `OK`. + +Двухосевое ревью относительно `92cf339`: + +- Standards: 3 документационных замечания исправлены, повторная проверка PASS; +- Spec: 2 документационных замечания исправлены, повторная проверка PASS; +- запахов кода и незапрошенного расширения области не найдено. + +## Что осталось пользователю + +Выполнить ручные команды из раздела `## Comments` тикета 05: + +1. На доступной Ubuntu с Python 3.10 — установка, жизненный цикл, + `xray run -test`, HTTP и SOCKS через один локальный вход. +2. На РЕД ОС, Astra Linux или Alt Linux по доступности — тот же сценарий после + проверки версии Python. + +В отчёт не копировать VLESS-ссылку, UUID, ключи, `shortId`, `path` и +сгенерированный JSON. Достаточно версии системы/Python, кодов возврата и итога +HTTP/SOCKS. Недоступную систему отметить как неподтверждённую. + +## После ручного результата + +1. Отметить только фактически выполненные пункты тикета 05. +2. Обновить статус исходного дизайна и заявления о поддержке. +3. Обновить или удалить этот handoff. +4. По навыку `implement` выполнить итоговую проверку и conventional commit. + +До ручной приёмки коммита задачи 05 нет. diff --git a/.scratch/headless-xray-proxy/issues/05-package-delivery-and-acceptance.md b/.scratch/headless-xray-proxy/issues/05-package-delivery-and-acceptance.md index 8f39488..c62c922 100644 --- a/.scratch/headless-xray-proxy/issues/05-package-delivery-and-acceptance.md +++ b/.scratch/headless-xray-proxy/issues/05-package-delivery-and-acceptance.md @@ -1,36 +1,103 @@ # 05 — Доставка пакета и итоговая приёмка -**What to build:** Завершённая прокси-подсистема устанавливается отдельно или -вместе с dotfiles, снабжена безопасными шаблонами и понятной инструкцией, а её -заявленные сценарии подтверждены автоматическими и доступными системными -проверками. +**What to build:** Поставка `xray-proxy` проверена целиком: корневой обзор +соответствует готовым возможностям, автоматические проверки воспроизводимы, а +ручная приёмка на доступных системах подготовлена для пользователя. -**Blocked by:** 03 — Безопасный жизненный цикл управляемого процесса; 04 — -Проверяемая пользовательская установка Xray. +**Blocked by:** 03 — безопасный жизненный цикл; 04 — проверяемая установка. -**Status:** ready-for-agent +**Status:** ready-for-human -- [ ] Самостоятельный stow-совместимый пакет доставляет CLI, Bash-модуль и - вымышленные шаблоны машинного INI и VLESS-профиля; реальные пользовательские - настройки, UUID, ссылки и ключи не входят в репозиторий. -- [ ] Пакет можно подключить отдельно через stow, эквивалентные ручные симлинки - или копирование; общий установщик использует тот же пакет без отдельной - реализации и сохраняет повторяемость установки. -- [ ] Основная инструкция объясняет внешний Hiddify и управляемый Xray, - подготовку двух файлов настройки, все команды управления, `proxy_on/off`, - `pclaude/pcodex`, `NO_PROXY`, ограничения CIDR и диагностику. -- [ ] Инструкция фиксирует две поддержанные семьи VLESS, Xray 26.3.27, - современную проверку сертификата и отсутствие systemd, автозапуска и - автоматического перехода между типами прокси. -- [ ] Корневой обзор кратко описывает подсистему, показывает подключение пакета - и направляет к полной инструкции, не дублируя её. -- [ ] Полный автоматический прогон подтверждает Python 3.8-совместимый синтаксис, - внешний Hiddify-сценарий, обе семьи VLESS, Xray 26.3.27, установку, - жизненный цикл, Bash-интеграцию и отсутствие утечки секретов. -- [ ] На доступной Ubuntu с Python 3.10 проверены установка, `xray run -test` и - работа HTTP и SOCKS через один локальный вход для Xray 26.3.27. -- [ ] На целевой удалённой системе выполнен тот же пользовательский сценарий; - версия Python в РЕД ОС проверена до заявления поддержки, а недоступная среда - явно записана как неподтверждённая вместо неподкреплённого обещания. -- [ ] После приёмки статус исходной спецификации и документация соответствуют - фактически подтверждённому объёму, включая все оставшиеся ограничения. +## Границы задачи + +Тикеты 03/04/06 уже доставили CLI, Bash-модуль, установку и жизненный цикл. +Задача 05 их проверяет, но не переписывает. Источники истины: + +- [`xray-proxy/README.md`](../../../xray-proxy/README.md) — пользовательские + команды, настройка и ограничения; +- [исходный дизайн](../../../docs/specs/2026-07-15-headless-xray-proxy-design.md) + — границы и принятые решения. + +- [x] Корневой `README.md` кратко описывает внешний Hiddify и управляемый Xray, + показывает `stow xray-proxy` и ссылается на полную инструкцию. +- [x] Пакет подключается через stow, ручные ссылки или копирование; общий + установщик использует тот же пакет. +- [x] Инструкция покрывает две семьи VLESS, Xray 26.3.27, отсутствие systemd, + автозапуска и автоматического перехода между прокси. +- [x] Тест + `ManagedXrayCliTest.test_exact_boolean_version_alpn_and_extra_branches` + подтверждает, что устаревшие `allowInsecure`/`insecure` не попадают в + TLS-конфиг, а истинное значение даёт предупреждение. + +## Секретные данные + +- [x] В отслеживаемых файлах, тестовых данных, аргументах, выводе и отчёте нет + настоящих VLESS-ссылок, UUID, ключей, `shortId` и `path`. Автоматические тесты + используют только вымышленные контрольные значения. Настоящий профиль и + сгенерированный JSON остаются в закрытых пользовательских файлах и не + копируются в отчёт. + +## Автоматическая проверка + +- [x] `tests/test_xray_proxy_full.sh` запускает весь Python-набор под системным + `python3` и CPython 3.8 через `uv`, затем Bash-тесты и проверку установки. +- [x] Тестовый Xray остаётся отдельным исполняемым файлом и получает доступ к + библиотекам исходного Python. Это устраняет ложные падения переносимой сборки + `uv`, не ослабляя проверки личности процесса. +- [x] `tests/test_install.sh` собирает небольшие тестовые деревья только из + отслеживаемых Git-файлов и удаляет общий временный каталог при выходе. + +## Приёмка пользователем + +Исполнитель готовит команды и останавливается. Результат отмечает пользователь; +недоступная система остаётся неподтверждённой. + +- [ ] Ubuntu с Python 3.10: установка, жизненный цикл, `xray run -test`, HTTP и + SOCKS через один локальный вход Xray 26.3.27. +- [ ] РЕД ОС, Astra Linux или Alt Linux по доступности: тот же сценарий после + проверки фактической версии Python. + +## После приёмки + +- [ ] Статус исходного дизайна и заявления о поддержке приведены в соответствие + только с фактически выполненными прогонами. + +## Comments + +### 2026-07-21 — автоматическая проверка + +`bash tests/test_xray_proxy_full.sh` завершился с кодом 0: + +- системный Python 3.14: 79 тестов, `OK`, 57,276 с; +- Bash-интеграция: 8 проверок, `PASS`; `shellcheck` отсутствует и явно пропущен; +- установка: `All install tests passed`; в `/tmp` не осталось каталогов + `dotfiles-install-test.*`; +- CPython 3.8.20 через `uv`: 79 тестов, `OK`, 51,412 с. + +### 2026-07-21 — команды ручной приёмки + +В первой панели tmux, после подготовки закрытого `default.url` и машинного +конфига с `type = xray`: + +```bash +python3 --version +cd ~/dotfiles +stow xray-proxy +source ~/.config/xray-proxy/shell.bash +xray-proxy install +xray-proxy start +``` + +Во второй панели, пока `start` работает: + +```bash +xray-proxy status +xray run -test -c "${XDG_STATE_HOME:-$HOME/.local/state}/xray-proxy/client.json" +curl --proxy http://127.0.0.1:12334 https://api.ipify.org +curl --proxy socks5h://127.0.0.1:12334 https://api.ipify.org +xray-proxy stop +``` + +Если настроен другой локальный адрес или порт, те же значения подставляются в +обе команды `curl`. В отчёт записываются только версии, коды возврата и итог +проверки HTTP/SOCKS. diff --git a/.scratch/headless-xray-proxy/token-ledger.md b/.scratch/headless-xray-proxy/token-ledger.md index 10cfb49..c197b15 100644 --- a/.scratch/headless-xray-proxy/token-ledger.md +++ b/.scratch/headless-xray-proxy/token-ledger.md @@ -77,6 +77,12 @@ Claude-доля — 61k суммарно (TASK-ревью + перепровер | 03 | medium | ~636k + 77k | 80.5k | 4 (гонки) | | 04 | medium | ~822k + 135k | 61k | 2 (1 — вина постановки) | +## Задача 05 — доставка пакета и приёмка + +| Этап | Агент / модель | Effort | Токены | Прочее | +|---|---|---|---|---| +| 05: ревью постановки, попытки 1–2 (убиты) | Codex gpt-5.6-sol | high | расход токенов потерян (нет `turn.completed`) | обе умерли на `Quota exceeded (os error 122)`: набор `test_install.sh` заполнял `/tmp` тестовыми деревьями по ~1,8 ГБ; потеряно ~2 и ~10 мин работы, сеансы невосстановимы из-за сбоя журнала | + ## Наблюдения - Кэш у Codex покрывает ~93% входа ревью-этапа: длинные треды с большим diff --git a/README.md b/README.md index 4dd8c00..b2e3a6e 100644 --- a/README.md +++ b/README.md @@ -98,11 +98,12 @@ export ZAI_API_KEY="..." # https://z.ai ### Прокси (`xray-proxy`) Linux/Bash-команды `proxy_on/off`, `pclaude`, `pcodex` и `myip` находятся в -самостоятельном пакете [`xray-proxy`](xray-proxy/README.md). Он читает строгий -машинный INI, проверяет доступность явно выбранного внешнего прокси и не -запускает команду при ошибке. Без конфига сохраняется внешний Hiddify -`hproxy.local:12334`. Управление процессом Xray будет добавлено отдельно; -`type = xray` пока даёт безопасный отказ. +самостоятельном пакете [`xray-proxy`](xray-proxy/README.md). Он поддерживает +явно выбранный внешний Hiddify или управляемый пользовательский Xray 26.3.27 с +профилями VLESS TCP/RAW + REALITY и XHTTP + TLS. Для отдельного подключения +выполните `stow xray-proxy`. Команды `xray-proxy install/start/stop/status` +работают без systemd, автозапуска и автоматического перехода между прокси. Без +конфига сохраняется внешний Hiddify `hproxy.local:12334`. Имя `hproxy.local` — прежний алиас хоста с внешним прокси. Windows и VS Code Server продолжают использовать его напрямую. diff --git a/agents/.agents/skills/.gitignore b/agents/.agents/skills/.gitignore new file mode 100644 index 0000000..e5b9030 --- /dev/null +++ b/agents/.agents/skills/.gitignore @@ -0,0 +1,23 @@ +# Matt Pocock skills +writing-great-skills/ +wayfinder/ +triage/ +to-tickets/ +to-spec/ +teach/ +tdd/ +setup-matt-pocock-skills/ +resolving-merge-conflicts/ +research/ +prototype/ +improve-codebase-architecture/ +implement/ +handoff/ +grilling/ +grill-with-docs/ +grill-me/ +domain-modeling/ +diagnosing-bugs/ +codebase-design/ +code-review/ +ask-matt/ diff --git a/tests/test_install.sh b/tests/test_install.sh index 8d6c2da..7a1b56c 100755 --- a/tests/test_install.sh +++ b/tests/test_install.sh @@ -3,6 +3,11 @@ set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +# Один корневой временный каталог на прогон: тестовые деревья копируют заметную +# часть репозитория и без уборки переполняют /tmp за несколько прогонов. +TEST_TMP_ROOT="$(mktemp -d /tmp/dotfiles-install-test.XXXXXX)" +trap 'rm -rf "$TEST_TMP_ROOT"' EXIT + fail() { echo "FAIL: $*" >&2 exit 1 @@ -21,26 +26,21 @@ assert_not_exists() { setup_fixture() { local fixture_root repo_root bin_dir - fixture_root="$(mktemp -d /tmp/dotfiles-install-test.XXXXXX)" + fixture_root="$(mktemp -d "$TEST_TMP_ROOT/fixture.XXXXXX")" repo_root="$fixture_root/repo" bin_dir="$fixture_root/bin" mkdir -p "$repo_root" "$bin_dir" - cp -a \ - "$REPO_ROOT/install.sh" \ - "$REPO_ROOT/bash" \ - "$REPO_ROOT/tmux" \ - "$REPO_ROOT/vim" \ - "$REPO_ROOT/zed" \ - "$REPO_ROOT/vscode" \ - "$REPO_ROOT/agents" \ - "$REPO_ROOT/opencode" \ - "$REPO_ROOT/codex" \ - "$REPO_ROOT/gemini" \ - "$REPO_ROOT/claude" \ - "$REPO_ROOT/xray-proxy" \ - "$REPO_ROOT/scripts" \ - "$repo_root/" + # Список файлов соответствует свежему клону: только отслеживаемые Git-файлы + # (новые файлы видны после git add). Содержимое берётся из текущего рабочего + # дерева. Локальные данные инструментов внутри пакетов (vscode/.vscode-server, + # zed/.config/opencode и т.п.) весят гигабайты, переполняют /tmp и ломают + # stow конфликтами, поэтому в тестовое дерево не попадает. + git -C "$REPO_ROOT" ls-files -z --cached -- \ + install.sh bash tmux vim zed vscode agents opencode codex gemini \ + claude xray-proxy scripts \ + | tar -C "$REPO_ROOT" --null -T - -cf - \ + | tar -xf - -C "$repo_root" cat > "$bin_dir/fake-git" <<'EOF' #!/usr/bin/env bash diff --git a/tests/test_xray_proxy_full.sh b/tests/test_xray_proxy_full.sh new file mode 100755 index 0000000..4f2ca36 --- /dev/null +++ b/tests/test_xray_proxy_full.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$REPO_ROOT" + +if ! command -v uv >/dev/null 2>&1; then + echo "Ошибка: для полной проверки требуется uv" >&2 + exit 1 +fi + +export PYTHONDONTWRITEBYTECODE=1 + +python3 -m unittest discover -s tests +bash tests/test_proxy_launchers.sh +bash tests/test_install.sh +uv run --python 3.8 --no-project python -m unittest discover -s tests diff --git a/tests/test_xray_proxy_managed.py b/tests/test_xray_proxy_managed.py index e431d5b..d3bdf81 100644 --- a/tests/test_xray_proxy_managed.py +++ b/tests/test_xray_proxy_managed.py @@ -166,6 +166,10 @@ class ManagedXrayCliTest(unittest.TestCase): self.bin_dir.mkdir() self.log = self.root / "xray.log" self.xray = self.bin_dir / "xray" + python_prefix = Path(sys.executable).resolve().parent.parent + python_lib = python_prefix / "lib" + if python_lib.is_dir(): + (self.root / "lib").symlink_to(python_lib, target_is_directory=True) shutil.copy2(sys.executable, self.xray) self.xray.chmod(0o755) for operand in ("version", "run"): diff --git a/xray-proxy/README.md b/xray-proxy/README.md index b151419..3e73d8b 100644 --- a/xray-proxy/README.md +++ b/xray-proxy/README.md @@ -132,7 +132,8 @@ PID не принимается. `run` никогда не запускает Xr отдельную панель tmux. После готовности один loopback-порт принимает HTTP и SOCKS. `stop` ограниченно ждёт завершения супервизора и Xray, очищает служебные файлы и возвращает исходный `start` в терминал. Команда `stop` работает и после -явного переключения машинного типа на `external`. +явного переключения машинного типа на `external`. CLI не создаёт systemd-службу, +не запускает Xray автоматически и не переключается между типами прокси. `run` передаёт восемь proxy-переменных только дочернему процессу и сохраняет аргументы и код возврата. `proxy_on` атомарно применяет те же восемь переменных