diff --git a/COMMUNITY_RELEASE.md b/COMMUNITY_RELEASE.md index 8696f22781..bdb5487d75 100644 --- a/COMMUNITY_RELEASE.md +++ b/COMMUNITY_RELEASE.md @@ -194,6 +194,11 @@ wire_specification = "responses" ### 1. If using Git clone (Windows / Linux / macOS) Pull the latest commits from the fork and start as usual (dependencies and DB migrations are applied automatically): +Source launchers require uv and Bun 1.3.14 for missing dashboard assets; see +the [checkout guide](docs/deployment/python.md#run-from-a-fork-checkout). +After updating frontend sources, rebuild them with the pinned Bun/frozen lock +before restarting, since complete existing assets are reused. + **Windows (PowerShell / Command Prompt):** ```powershell git pull origin main diff --git a/README.md b/README.md index 27d79d59fe..b542fc3f7a 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ Load balancer for ChatGPT accounts. Pool multiple accounts, track usage, manage > git clone https://github.com/Frozen811/codex-lb.git > cd codex-lb > +> # Source prerequisites: uv + Bun 1.3.14; see docs/deployment/python.md > # Windows: double-click start.bat or run: > .\run.ps1 > diff --git a/docs/deployment/python.md b/docs/deployment/python.md index d4e54a5037..1b934fd3a2 100644 --- a/docs/deployment/python.md +++ b/docs/deployment/python.md @@ -78,6 +78,108 @@ the corrected source distribution includes build helpers, frontend inputs and assets, and excludes local dependencies/worktrees. The ordinary GitHub source archive has no prebuilt assets and requires the pinned Bun prerequisite. +## Run from a fork checkout + +Clone the fork and select the source revision you want to run. Source launchers +need [uv](https://docs.astral.sh/uv/) and Bun **1.3.14** on PATH. uv supplies a +compatible Python if one is unavailable. The launchers honor `uv.lock`, prepare +missing dashboard assets, and run from their own checkout even when invoked +from another directory. They do not install Bun automatically. + +To install the pinned Bun with its official installer, use one of these +[version-specific commands](https://bun.sh/docs/installation#installing-older-versions), +then reopen the terminal and check `bun --version`: + +```powershell +iex "& {$(irm https://bun.com/install.ps1)} -Version 1.3.14" +``` + +```bash +curl -fsSL https://bun.com/install | bash -s "bun-v1.3.14" +``` + +These optional setup commands install Bun in your user environment. The audit +used checksum-verified isolated binaries instead of changing the user's install. + +```bash +git clone https://github.com/Frozen811/codex-lb.git +cd codex-lb +git checkout +``` + +Windows PowerShell: + +```powershell +.\run.ps1 +# Alternate port and a log path containing spaces: +.\run.ps1 --port 2547 --log-file "logs with spaces/server.log" +``` + +If script execution policy prevents that command, invoke it explicitly with +`powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\run.ps1`. You can +also double-click `start.bat`; the batch wrapper delegates to the same launcher +and pauses after an interactive no-argument session ends. With explicit +arguments, it returns the CLI's status without requiring a key press. + +Linux/WSL and macOS Bash: + +```bash +./run.sh +./run.sh --port 2547 --log-file "logs with spaces/server.log" +``` + +The Git checkout preserves its executable bit. `./run.sh --help` and +`.\run.ps1 --help` work without frontend build prerequisites; normal startup +with missing assets fails clearly if Bun is absent or incompatible. Frontend +build tools are forced to use Bun, so an older host Node.js is not selected +by a Vite shebang, as described in the [Bun runtime guide](https://bun.sh/docs/runtime#--bun). + +For manual development preparation: run `uv sync --dev --frozen`, then in +`frontend` run `bun install --frozen-lockfile` and `bun --bun run build`. +`uv run --frozen codex-lb` starts the CLI after that preparation. Editable +dependency setup alone does not build the dashboard. After changing frontend +sources or updating the checkout, rebuild the frontend explicitly; existing +complete assets are reused on subsequent launcher starts. + +WSL uses Linux uv/Bun/Python inside its distribution. A Windows tool on PATH +is not a substitute for Linux dependencies. Keep its checkout/cache/data on +the Linux filesystem for reliable executable permissions and build behavior; +do not share one SQLite data directory with a simultaneously running Windows +instance. Default listeners are local; opening the service to a LAN requires +the [remote-access configuration](remote.md), not a launcher-specific firewall rule. + +## Optional native transport helper + +Basic source startup and the Python fallback do not require Rust. To build +the native transport helper, use the repository's pinned Rust **1.96.0** with +the platform linker/toolchain (MSVC Build Tools on Windows): + +```bash +cargo build --release --locked --package codex-lb-egress-worker --bin codex-lb-native-egress +``` + +The application discovers `codex-lb-native-egress` through PATH. Add the +checkout's `target/release` directory for the current process before launching: + +```powershell +$env:PATH = "$((Get-Location).Path)\target\release;$env:PATH" +.\run.ps1 +``` + +```bash +PATH="$PWD/target/release:$PATH" ./run.sh +``` + +Use `codex-lb-native-egress --help` to verify the executable can run. This +does not prove real upstream transport or account routing. Prefer the tested +Docker source path when you want the helper and CA trust built into the image. + +Windows PowerShell/cmd and Ubuntu 24.04 WSL launchers were exercised on paths +with spaces, foreign cwd, failures, readiness/assets and retained data. WSL +SIGTERM forwarding completed application shutdown and removed its listener; +uv returned signal status 143. macOS native startup remains an unexecuted +platform boundary rather than a claimed successful install. + ## Startup and retained data Open `http://localhost:2455` and check `/health/ready`. Both `codex-lb` and diff --git a/issues-check.md b/issues-check.md index 9012f457d8..2215a69e20 100644 --- a/issues-check.md +++ b/issues-check.md @@ -4,7 +4,7 @@ Этот файл фиксирует доказательства, замечания, исправляющие коммиты и повторные проверки. Нормативные контракты остаются в [openspec/specs](openspec/specs), работа по изменению поведения — в [openspec/changes](openspec/changes). Заявления автора, зелёная сборка образа и наличие теста сами по себе не означают, что проблема решена. -**Последнее обновление: 2026-10-01.** Предыдущие локальные исправления и новый пакет INSTALL-06/07/08 закоммичены и отправлены в `fix/python-install-audit`; текущие результаты — §20. Stable main и публичные release artifacts не обновлялись. Реестр полного аудита установки — §15; прежние утверждения о неопубликованных правках ниже сохранены как история соответствующих прогонов. +**Последнее обновление: 2026-10-01.** Предыдущие batches перенесены в main через PR #2–#5 после exact-head CI/review checks; main `8a2b706e`. INSTALL-09/10/11 исправлены и проверены на Windows/Linux в следующей ветке; §21. Public release artifacts остаются историческими. Реестр полного аудита установки — §15; предыдущие статусы сохранены как история соответствующих прогонов. ## 1. Правила ведения @@ -104,6 +104,11 @@ | F-022 | P1 | ИСПРАВЛЕНО ЛОКАЛЬНО | Чистый Git/source install выпускал wheel без dashboard assets. Custom Hatch hook собирает assets закреплённым Bun/frozen lock либо отказывает с prerequisite guidance; actual clean source wheel/sdist и 11 regressions PASS; §20 | | F-023 | P1 | ИСПРАВЛЕНО ЛОКАЛЬНО | Explicit-root sdist selector всё ещё допускал worktrees/credentials внутри выбранных frontend/app folders. Inert marker archive probe воспроизвёл 4 leaks; explicit nested exclusions устранили все markers; §20 | | F-024 | P1 | ИСПРАВЛЕНО / WINDOWS CLOUD PASS | Новый build hook требовал Bun при editable uv sync и сломал первый Windows run. Editable-only exemption и CI guard проверены локально и на опубликованном SHA 4dce7220; §20.5 | +| F-025 | P1 | ИСПРАВЛЕНО / SOURCE SMOKE PASS | Checkout launchers не выбирали собственный проект и не готовили dashboard; clean baseline readiness 200, UI 503. Frozen project-bound startup теперь готовит assets; foreign cwd/paths with spaces Windows/Linux PASS; §21 | +| F-026 | P2 | ИСПРАВЛЕНО / SOURCE SMOKE PASS | PowerShell терял CLI exit 2, batch также не сохранял errorlevel, run.sh был 100644. Exit status/args исправлены, Bash 100755; actual PS/pwsh/cmd/Linux failure/signal tests PASS; §21 | +| F-027 | P1 | ИСПРАВЛЕНО / WINDOWS+LINUX PASS | Bun build выбирал host Node 18 через Vite shebang и падал на node:util styleText. Frontend tools теперь --bun runtime, pinned 1.3.14; actual builds PASS; §21 | +| F-028 | P2 | ИСПРАВЛЕНО / PR CI PASS | Affinity/close-1009 fixtures обходили committed account routing notification. Fixtures приведены к реальному import lifecycle, runtime Pause guard не ослаблялся; 11 routes + 25 Pause local PASS и full PR CI; §21 | +| F-029 | P1 | ИСПРАВЛЕНО / NIX CLOUD PASS | Explicit Nix sources не включали объявленный Hatch hook/helper; wheel build падал до assets reuse. Узкие source filters исправлены, actual Nix flake check на f61669d6 PASS; §21 | ### F-001 — ORM-объекты покидают сессию до чтения ID @@ -1286,9 +1291,9 @@ OpenSpec: [2026-10-01-guard-paused-websocket-dispatch](openspec/changes/archive/ | INSTALL-06 | Wheel из GitHub Release через pip | Правильная ссылка и версия форка; чистая venv на поддерживаемых ОС; зависимости, console scripts, frontend/config/migrations; импорт и старт вне checkout; сеть и подключение Codex | PUBLIC ПРОВЕРЕН Windows/Python 3.13: actual pip + uv pip, CLI/migrations/readiness/assets вне checkout, root code соответствует tag после newline normalization; historical runtime drift раскрыт. Real OAuth/Codex/native Linux/macOS отдельно; §20 | | INSTALL-07 | Sdist / source archive из Release | Метаданные, состав без чужих worktrees и credentials, сборка wheel из sdist, установка вне checkout, dashboard/config/migrations; скачивание и инструкции | PUBLIC ПРОВЕРЕН: clean rebuild/install/startup, но 5967 nested worktree entries и runtime drift остаются в старом asset. Исправленный local sdist также исключает nested markers, содержит build hooks/assets и перестраивается без Bun; F-014/023, §20 | | INSTALL-08 | `uv` / `uvx` / установка из индекса | Каждая заявленная команда и канал: действительно ли устанавливает форк, а не upstream `codex-lb`; version pinning, runtime deps, config/data directory и дальнейшие обновления | ПРОВЕРЕНО Windows: isolated uvx/uv tool public wheel, source replacement сохраняет data/key; corrected published Git SHA install PASS. Editable-only uv sync exemption проверен после cloud failure; §20 | -| INSTALL-09 | Запуск из Git checkout | clone URL/ref форка, `uv sync --frozen`, frontend и Rust prerequisites, подготовка assets, CLI/start команды; чистое окружение без существующей `.venv` и кешей разработчика | НЕ ПРОВЕРЕНО | -| INSTALL-10 | Windows скрипты / Desktop + WSL | `run.ps1`, `start.bat` и остальные найденные entrypoints; пути с пробелами, PowerShell/cmd синтаксис, prerequisites, Docker Desktop/WSL границы, firewall и startup failures | НЕ ПРОВЕРЕНО | -| INSTALL-11 | Linux/macOS скрипты | `run.sh` и документированные команды; shell/permissions, Python/native helper архитектура, env/config paths, background/foreground/restart и корректный выход | НЕ ПРОВЕРЕНО | +| INSTALL-09 | Запуск из Git checkout | clone URL/ref форка, `uv sync --frozen`, frontend и Rust prerequisites, подготовка assets, CLI/start команды; чистое окружение без существующей `.venv` и кешей разработчика | WINDOWS/LINUX SOURCE ПРОВЕРЕНО: fresh no-venv/assets copies + actual anonymous Git clone b5aa440b, frozen setup, frontend/readiness/assets/data recreate; optional Windows native build/discovery/handshake PASS; F-025/027, §21 | +| INSTALL-10 | Windows скрипты / Desktop + WSL | `run.ps1`, `start.bat` и остальные найденные entrypoints; пути с пробелами, PowerShell/cmd синтаксис, prerequisites, Docker Desktop/WSL границы, firewall и startup failures | WINDOWS SOURCE ПРОВЕРЕНО: PS5/pwsh/cmd foreign cwd/path spaces, help, missing uv/wrong Bun, real startup/assets, preserved exit 1/2, data/key reuse; WSL Linux tested separately, no system firewall changes; §21 | +| INSTALL-11 | Linux/macOS скрипты | `run.sh` и документированные команды; shell/permissions, Python/native helper архитектура, env/config paths, background/foreground/restart и корректный выход | LINUX/WSL ПРОВЕРЕНО: executable Bash, clean setup, cwd/args/spaces, readiness/assets, repeat data/key, SIGTERM forwarding/app shutdown/no listener, exit 143. Native macOS не исполнялся и остаётся отдельной границей; §21 | | INSTALL-12 | Helm / Kubernetes | Fork chart/package/image repository и version; values, secrets, PVC/DB, migrations, probes, service/ingress/OAuth/TLS/WS; clean install, upgrade, rollback; одиночный и документированный multi-replica режим | НЕ ПРОВЕРЕНО | | INSTALL-13 | Nix / flake | Все опубликованные `nix run`/build команды, fork URL/ref, locked inputs, Python/native/frontend contents, runtime/data paths; доступность реального Nix стенда | НЕ ПРОВЕРЕНО | | INSTALL-14 | Прочие найденные способы | System service, reverse proxy, удалённый сервер, установщик или сторонняя инструкция — отдельная карточка на каждый реально обещанный путь | НЕ ПРОВЕРЕНО: требуется завершить инвентаризацию | @@ -1622,3 +1627,60 @@ Source push в [fork branch](https://github.com/Frozen811/codex-lb/tree/fix/pyth Повторный exact-source Windows run [36905440811](https://github.com/Frozen811/codex-lb/actions/runs/36905440811), SHA **`4dce7220eed12da1b3b1890af48c09d66eb07ee6`**: terminal API result **completed/success**. Dependency setup, editable guard, portability tests, Bun/frontend build и installed-wheel readiness/assets smoke прошли. Этот manual Windows run не заменяет полный main-push CI/review gates и не разрешает выпуск релиза сам по себе. Следующий commit лишь архивирует verification/report; cloud result относится именно к указанному source SHA. Follow-up OpenSpec: [repair-editable-package-setup](openspec/changes/archive/2026-10-01-repair-editable-package-setup/), owning spec/context/docs синхронизированы. Source остаётся в отдельной fork branch; F-010 и исторические package/image artifacts не обновлялись. + +## 21. Main integration и INSTALL-09 / INSTALL-10 / INSTALL-11 — 2026-10-01 + +### 21.1. Предыдущие исправления перенесены в main + +Пользователь поручил перенос после обсуждения main/PR gates. Действующий GitHub аккаунт — owner Frozen811. Использованы четыре тематических PR, merge с сохранением commit ancestry, без force-push. Перед каждым merge проверены exact-head check-runs, успешный CI Required, REST mergeable_state=clean, отсутствие CHANGES_REQUESTED и unresolved non-outdated review threads через GitHub GraphQL; review pagination завершена, findings не пропускались. + +| PR | Проверенный source SHA | Merge SHA в main | +|---|---|---| +| [#2 proxy](https://github.com/Frozen811/codex-lb/pull/2) | `feadca30900411efaa2523351315218d5d721c5f` | `f847fc5718f3971ad7bb4c99137b23c007ebc634` | +| [#3 release gates](https://github.com/Frozen811/codex-lb/pull/3) | `72487a38c4daaed70f5633bff76a03829c61da0d` | `245152d7931244f37044713ec0f630cecc42051f` | +| [#4 Docker](https://github.com/Frozen811/codex-lb/pull/4) | `904efd6653a08cd14cc4a6b75547a0690828822e` | `bff1bd56a915cede3c366c124f8d4f11c5cd7e19` | +| [#5 Python](https://github.com/Frozen811/codex-lb/pull/5) | `f61669d62acfe69a15e982d3afadf8a28c1b8b14` | **`8a2b706e4d5ec86f71ec84bd704be8cfde98b7d8`** | + +Full CI обнаружил проблемы, не покрытые прежними targeted tests: affinity fixtures raw-inserted accounts после startup snapshot без import availability callback; close-1009 test мокал connected account без committed row. Исправлены только fixtures после реального commit, не Pause/runtime routing guard. Local **11** affinity/close route tests и **25** Pause cases прошли. Дополнительно Nix source filter не включал новый Hatch hook; добавлены только два declared helper files для package/editable variants. Actual [Nix job](https://github.com/Frozen811/codex-lb/actions/runs/36917479916/job/110555586516) на f61669d6 — success. + +PR2 final run [36916078511](https://github.com/Frozen811/codex-lb/actions/runs/36916078511), attempt 2 — **success**. В attempt 1 shard2 закончил **1085 passed / 327 skipped**, но job помечен cancelled и aggregate отказал; это не assertion regression. Повторены только failed/cancelled jobs, gate не ослаблен. PR3/4/5 CI Required также success на указанных heads. Новые main-push runs после merge — отдельная evidence chain; не выдавать PR success за уже прошедший final-main CI. Release/tag/GHCR/PyPI publication не выполнялась. + +### 21.2. Реальные source-launcher дефекты и исправления + +- **F-025:** scripts использовали caller cwd и `uv run codex-lb`, поэтому editable install не готовил ignored dashboard. Isolated Windows cold-source baseline имел `/health/ready` 200, `/` **503**. Added shared `scripts/source_startup.py`: missing assets через pinned helper, затем app.cli в том же interpreter. Helpers honor frozen uv.lock and own checkout; help не требует frontend prerequisites. Внешний cwd не используется для выбора чужого проекта/config. +- **F-026:** Windows PowerShell native CLI error возвращал launcher exit **0**. PS5/pwsh теперь сохраняют $LASTEXITCODE, batch делегирует через quoted own path/system PowerShell и сохраняет errorlevel; interactive pause только без аргументов. Bash shipped mode был **100644**, стал **100755**, script anchors dirname и execs uv. +- **F-027:** реальный Linux source build выбрал Node **18.19.1** через Vite shebang и упал на absent `node:util.styleText`. `build_dashboard.py` теперь использует `bun --bun run build`; это confirmed runtime selection fix, не версия зависимости. Windows/Linux isolated Bun **1.3.14** archives сверены с official SHASUMS256. + +### 21.3. Доказательства INSTALL-09/10/11 + +Windows audit root: `C:\Users\ext\AppData\Local\Temp\codex-lb-install-batch7-20261001\`; fresh source snapshots не содержали .venv/static/node_modules/env. Logs/result scripts retained. Ubuntu 24.04 WSL final source audit: `/home/ext/.cache/codex-lb-launcher-audits/batch7-v22xztgg/`; uv **0.11.16**, isolated Python/cache/data and Bun **1.3.14**, host Node **18.19.1**. + +| Продуктовый путь | Итог | +|---|---| +| Cold Windows PowerShell 5 source | **PASS** frontend install/build, readiness/HTML/JS/CSS from foreign cwd, checkout path with spaces | +| Windows pwsh repeat | **PASS** same data/key after restart | +| cmd/start.bat | **PASS** real startup, quoted checkout path/foreign cwd, preserved CLI exit 2 | +| Windows log argument containing spaces | **PASS** actual CLI created the supplied log path; fresh rebuild with forced Bun runtime passed | +| Missing uv | **PASS refusal**, PS and batch exit 1 with actionable diagnostic | +| Wrong Bun 1.4.2 | **PASS refusal**, no dashboard-less server started | +| Help without pinned Bun | **PASS**, CLI options available, no frontend output created | +| Invalid CLI arguments | **PASS**, PS5/pwsh/cmd/Linux returned CLI exit 2 | +| Windows retained state | **PASS**, synthetic dashboard setting false and encryption-key hash survived PS/pwsh/batch restarts | +| Linux executable source run | **PASS**, direct run.sh from foreign cwd/path spaces, cold source build, readiness/HTML/JS/CSS and log-path args | +| Linux repeat/state | **PASS**, setting/key retained on second start | +| Linux foreground SIGTERM | **PASS**, uv forwarded termination; application shutdown completed, listener removed, supervisor returned expected signal exit **143** | +| Optional Windows Rust/native helper | **PASS**, pinned Rust **1.96.0**, own CARGO_HOME/TARGET_DIR build --release --locked; native --help, PATH discovery, protocol handshake and child cleanup | + +Windows server tests use only owned process-tree cleanup; graceful Windows console Ctrl+C/close GUI semantics не заявлены выполненными. No real account/OAuth/Codex traffic, native macOS execution, LAN firewall changes или production data. Native transport handshake — не реальный upstream request. WSL tools/data отдельны от Windows, общая SQLite между двумя instances не использовалась. + +Intermediate harness failures recorded: baseline incorrectly expected dashboard 404, observed 503; initial cmd nested quote form was wrong, actual cmd call form passed; Python 3.14 module-style help differs from Python 3.13 prog name, assertion now checks product description/options; initial Linux SIGTERM assertion expected zero although uv legitimately returned 143 with complete shutdown; first Linux build failed on old Node and caused the actual --bun fix. None counted as green before correction. Automatic cleanup review rejected removing the disposable static directory without stated reason; no retry deletion, final Windows build used another fresh copy. + +### 21.4. Проверки, документация и следующий PR + +**35 focused unit cases PASS**, включая 7 new source-startup tests; full Ruff check/format, ty, architecture и strict OpenSpec **68 main specs PASS**. README **222/225**, headings **10/10**, budgets unchanged. PS/pwsh/Bash/cmd source commands, prerequisite pins, explicit frontend rebuild after update, optional Rust PATH setup и WSL/native OS boundaries отражены в owning Python guide/context; CHANGELOG не редактировался. + +OpenSpec: [repair-checkout-launchers](openspec/changes/archive/2026-10-01-repair-checkout-launchers/), verified and archived. Ветка **fix/checkout-launchers** опубликована и открыта как [PR #6](https://github.com/Frozen811/codex-lb/pull/6) в main; fixing commit `742fc58d`, main integration commit `7bc6c8f1`, Nix verification archive `b5aa440b`. + +Actual anonymous `git clone --branch fix/checkout-launchers` с пустым developer credential helper получил exact source **`b5aa440bccbd4ed9ed5f1e8c86f8aa973a3de579`**. Clone path содержит пробелы, .venv/static absent before launch. PowerShell из foreign cwd с isolated data/cache и pinned Bun выполнил cold build; readiness/HTML/JS/CSS passed. Это независимая проверка опубликованного checkout, не только local source snapshot. Последующий report commit не меняет launcher behavior. + +Final main-push [CI 36923500040](https://github.com/Frozen811/codex-lb/actions/runs/36923500040) на **`8a2b706e4d5ec86f71ec84bd704be8cfde98b7d8`** и новый PR6 CI ещё выполнялись при записи отчёта; completed jobs нового PR без failure. Successful preceding PR gates не выдаются за terminal main-push conclusion. No release/tag/image publication. Historical packages/images F-010 не обновлены; release timing остаётся gated по exact-source main CI и artifact verification. diff --git a/openspec/changes/archive/2026-10-01-repair-checkout-launchers/design.md b/openspec/changes/archive/2026-10-01-repair-checkout-launchers/design.md new file mode 100644 index 0000000000..c894e9a4d5 --- /dev/null +++ b/openspec/changes/archive/2026-10-01-repair-checkout-launchers/design.md @@ -0,0 +1,11 @@ +## Decisions + +Use one Python source-start helper under scripts to reuse pinned dashboard preparation and delegate to app.cli in the same interpreter. PowerShell changes to PSScriptRoot and preserves the CLI result; batch delegates to PowerShell rather than duplicating prerequisites and restores the CLI error after an interactive pause. Bash resolves its own directory and execs uv to preserve signals/exit status. + +Use uv run --frozen so launchers honor the project lock. Skip dashboard preparation for help flags only; normal startup must provide working dashboard assets. Do not auto-install Bun/Rust or change account configuration. The optional native helper remains discoverable through runtime PATH and is documented with pinned Rust and platform prerequisites. + +Linux source startup exposed an old-host-Node trap: Bun's build script launched Vite via its node shebang and selected Node 18, which lacks node:util styleText. Dashboard preparation now forces the pinned Bun runtime with --bun, keeping the documented source prerequisite sufficient. SIGTERM is forwarded through uv; a supervisor exit 143 with complete application shutdown and no listener is expected signal semantics, not a failed graceful stop. + +## Verification + +Run scripts from outside copies whose paths contain spaces, with isolated cache/venv/data/key/SQLite and loopback ports. Test missing uv/Bun, incompatible Bun, bad CLI arguments and preserved failure status. Reproduce baseline behavior first, then validate readiness/assets, argument forwarding, persistence and cleanup. Use real Windows PowerShell/cmd and Linux WSL; document macOS as an unexecuted platform boundary. diff --git a/openspec/changes/archive/2026-10-01-repair-checkout-launchers/proposal.md b/openspec/changes/archive/2026-10-01-repair-checkout-launchers/proposal.md new file mode 100644 index 0000000000..80b25e8eac --- /dev/null +++ b/openspec/changes/archive/2026-10-01-repair-checkout-launchers/proposal.md @@ -0,0 +1,23 @@ +## Why + +INSTALL-09/10/11 need clean checkout and source-launcher verification. Current scripts run uv from the caller's working directory, editable dependency setup leaves dashboard assets absent, PowerShell/batch failure status is not preserved, and run.sh is not executable in Git. A clean clone can report ready while its dashboard is missing. + +## What Changes + +- Anchor launchers at their own checkout, preserve argument forwarding and exit status, and make the Bash script executable. +- Prepare missing dashboard assets through the existing pinned frontend helper before starting the owned CLI; keep CLI help independent of frontend build prerequisites. +- Verify clean Windows/PowerShell/cmd and Linux/WSL source startup on isolated data, paths with spaces, failure paths and shutdown; document source/native-helper prerequisites without claiming untested macOS behavior. + +## Capabilities + +### New Capabilities + +None. + +### Modified Capabilities + +- `deployment-installation`: checkout launcher preparation, path/argument/exit contracts and prerequisites. + +## Impact + +run.ps1, start.bat, run.sh, shared source-start helper, focused launcher tests and installation docs/context. No new runtime setting, account operation or production deployment. diff --git a/openspec/changes/archive/2026-10-01-repair-checkout-launchers/specs/deployment-installation/spec.md b/openspec/changes/archive/2026-10-01-repair-checkout-launchers/specs/deployment-installation/spec.md new file mode 100644 index 0000000000..ee753a4268 --- /dev/null +++ b/openspec/changes/archive/2026-10-01-repair-checkout-launchers/specs/deployment-installation/spec.md @@ -0,0 +1,23 @@ +## ADDED Requirements + +### Requirement: Checkout launchers prepare a ready source installation + +Checkout launchers MUST select their own project directory independently of the caller's working directory and honor the frozen Python dependency lock. Normal source startup MUST prepare missing dashboard assets with the pinned frontend toolchain before invoking the owned app CLI; prerequisite/build failure MUST prevent server startup. Frontend preparation SHALL execute node-shebang build tools with the pinned Bun runtime rather than an unrelated host Node.js. CLI help MUST remain available without frontend preparation. Launchers MUST preserve user arguments and resulting CLI failure status. The Bash launcher MUST ship with Git executable permission and preserve foreground signal semantics. + +#### Scenario: Invoke a source launcher from another directory + +- **WHEN** an operator invokes a launcher by path from outside a checkout whose path contains spaces +- **THEN** it runs that checkout with the forwarded arguments +- **AND** the server provides readiness and bundled dashboard assets using the configured data directory + +#### Scenario: Missing or incompatible frontend prerequisite + +- **WHEN** normal startup needs dashboard assets but the pinned Bun toolchain is unavailable +- **THEN** startup fails with actionable prerequisite guidance and nonzero exit status +- **AND** no dashboard-less server is started + +#### Scenario: CLI help or failure + +- **WHEN** the operator requests help without frontend prerequisites or passes an invalid CLI argument +- **THEN** help is available without building the frontend +- **AND** invalid arguments return the CLI's nonzero failure status through the launcher diff --git a/openspec/changes/archive/2026-10-01-repair-checkout-launchers/tasks.md b/openspec/changes/archive/2026-10-01-repair-checkout-launchers/tasks.md new file mode 100644 index 0000000000..456ab9bee7 --- /dev/null +++ b/openspec/changes/archive/2026-10-01-repair-checkout-launchers/tasks.md @@ -0,0 +1,19 @@ +## 1. Checkout path (INSTALL-09) + +- [x] 1.1 Inventory actual source prerequisites and reproduce clean no-asset checkout behavior with isolated data. +- [x] 1.2 Add shared dashboard preparation/CLI delegation using frozen uv and verify clean checkout startup and persisted data. + +## 2. Windows launchers (INSTALL-10) + +- [x] 2.1 Anchor PowerShell and batch to the selected checkout, forward args and preserve native-command exit codes. +- [x] 2.2 Exercise PowerShell/cmd from foreign cwd and paths with spaces; verify help, failures, real readiness/assets and cleanup. + +## 3. Bash launchers (INSTALL-11) + +- [x] 3.1 Anchor Bash and preserve exec/args/signal semantics; set the Git executable bit. +- [x] 3.2 Verify real Linux/WSL startup, no-asset preparation, failure paths, data retention and stop; disclose macOS boundary. + +## 4. Closure + +- [x] 4.1 Update spec-owned source installation instructions/context and tracker with prerequisites/evidence/limits. +- [x] 4.2 Run focused checks and strict OpenSpec, sync/verify/archive and publish the next focused fixing commits. diff --git a/openspec/changes/archive/2026-10-01-repair-checkout-launchers/verification.md b/openspec/changes/archive/2026-10-01-repair-checkout-launchers/verification.md new file mode 100644 index 0000000000..f2287151e2 --- /dev/null +++ b/openspec/changes/archive/2026-10-01-repair-checkout-launchers/verification.md @@ -0,0 +1,22 @@ +# Verification — checkout launchers + +Eight implementation tasks complete for INSTALL-09/10/11. macOS native execution is explicitly unverified. Main integration of the preceding audited changes is recorded separately in issues-check.md §21. + +## Product-path coverage + +- Baseline clean source: backend ready, dashboard 503; Windows native CLI failure returned wrapper zero. +- Fresh Windows PowerShell 5/pwsh/cmd sources from foreign cwd and paths with spaces passed actual readiness, HTML/JS/CSS, log-path argument forwarding and data/key reuse. +- Help avoids frontend compilation; missing uv/wrong Bun and invalid CLI argument paths preserve nonzero status. Source helper tests cover delegation/preparation/args/failure semantics. +- Ubuntu 24.04 WSL fresh no-asset source passed pinned Bun build, direct executable Bash startup, foreign cwd/args/spaces, repeated data/key retention and SIGTERM application shutdown with no surviving listener. uv signal return 143 is expected, not forced to zero. +- Linux host Node 18.19.1 broke the Vite shebang path; forced Bun runtime fixed it and passed actual builds on both Windows and Linux. +- Optional Windows Rust 1.96.0 helper build used isolated cargo directories and passed executable help, PATH discovery, protocol handshake and process cleanup. + +## Coherence/checks + +Normative requirement is synced to deployment-installation, narrative decisions/failure modes in context, user instructions in the linked Python guide. No new runtime setting, dependency floor or README heading; existing source prerequisites are explicit. Thirty-five focused tests passed, with one existing Starlette warning. Full Ruff/format/ty, architecture, simplicity and strict 68 specs passed. Bash Git mode is 100755. + +## Boundaries + +No real accounts/OAuth/Codex, native macOS, production/LAN firewall or graceful Windows GUI-console-close proof. Test processes were stopped; disposable downloads/cache/source/data retained. A policy rejection prevented one test-directory cleanup; another clean copy completed the final smoke without repeating deletion. Intermediate harness failures and the old-host-Node defect are recorded in issues-check.md §21 rather than counted as successes. + +This local source verification does not assert that the new launcher branch has completed cloud CI or been merged into main. Publication follows the focused branch/PR workflow and release/image publication remains separate. diff --git a/openspec/changes/repair-nix-hook-source-filter/design.md b/openspec/changes/archive/2026-10-01-repair-nix-hook-source-filter/design.md similarity index 100% rename from openspec/changes/repair-nix-hook-source-filter/design.md rename to openspec/changes/archive/2026-10-01-repair-nix-hook-source-filter/design.md diff --git a/openspec/changes/repair-nix-hook-source-filter/proposal.md b/openspec/changes/archive/2026-10-01-repair-nix-hook-source-filter/proposal.md similarity index 100% rename from openspec/changes/repair-nix-hook-source-filter/proposal.md rename to openspec/changes/archive/2026-10-01-repair-nix-hook-source-filter/proposal.md diff --git a/openspec/changes/repair-nix-hook-source-filter/specs/deployment-installation/spec.md b/openspec/changes/archive/2026-10-01-repair-nix-hook-source-filter/specs/deployment-installation/spec.md similarity index 100% rename from openspec/changes/repair-nix-hook-source-filter/specs/deployment-installation/spec.md rename to openspec/changes/archive/2026-10-01-repair-nix-hook-source-filter/specs/deployment-installation/spec.md diff --git a/openspec/changes/archive/2026-10-01-repair-nix-hook-source-filter/tasks.md b/openspec/changes/archive/2026-10-01-repair-nix-hook-source-filter/tasks.md new file mode 100644 index 0000000000..6bda45a2eb --- /dev/null +++ b/openspec/changes/archive/2026-10-01-repair-nix-hook-source-filter/tasks.md @@ -0,0 +1,2 @@ +- [x] 1.1 Include declared hook/helper in both filtered source variants and run local source/strict spec checks. +- [x] 1.2 Verify actual corrected Nix CI, sync context/requirements and archive the compatibility fix. diff --git a/openspec/changes/archive/2026-10-01-repair-nix-hook-source-filter/verification.md b/openspec/changes/archive/2026-10-01-repair-nix-hook-source-filter/verification.md new file mode 100644 index 0000000000..0cb825d0e6 --- /dev/null +++ b/openspec/changes/archive/2026-10-01-repair-nix-hook-source-filter/verification.md @@ -0,0 +1,9 @@ +# Verification — Nix hook source filtering + +Both tasks complete. The initial PR Nix build failed with OSError for scripts/hatch_build.py missing from its explicit source filter. + +Package and editable source variants now include only scripts/hatch_build.py and scripts/build_dashboard.py alongside their original explicit inputs. Existing prebuilt frontend and editable dependency-setup behavior is preserved; no flake lock or runtime setting changed. Local input membership and strict OpenSpec validation passed. + +Actual Nix flake check succeeded on f61669d62acfe69a15e982d3afadf8a28c1b8b14: https://github.com/Frozen811/codex-lb/actions/runs/36917479916/job/110555586516. Its full PR CI Required also succeeded; PR #5 subsequently merged into main as 8a2b706e4d5ec86f71ec84bd704be8cfde98b7d8. Normative requirement/context were synchronized before merge. + +This verifies the packaging compatibility seam. Native Nix installs across every advertised platform and user data/update behavior remain INSTALL-13 audit work. The archive/report commit adds no new build behavior. diff --git a/openspec/changes/repair-nix-hook-source-filter/tasks.md b/openspec/changes/repair-nix-hook-source-filter/tasks.md deleted file mode 100644 index 6a3089ddae..0000000000 --- a/openspec/changes/repair-nix-hook-source-filter/tasks.md +++ /dev/null @@ -1,2 +0,0 @@ -- [ ] 1.1 Include declared hook/helper in both filtered source variants and run local source/strict spec checks. -- [ ] 1.2 Verify actual corrected Nix CI, sync context/requirements and archive the compatibility fix. diff --git a/openspec/specs/deployment-installation/context.md b/openspec/specs/deployment-installation/context.md index 70abd6faf4..cf54c179e1 100644 --- a/openspec/specs/deployment-installation/context.md +++ b/openspec/specs/deployment-installation/context.md @@ -54,6 +54,12 @@ Windows diagnostic run 36904727598 on b89bd0a1 failed during uv sync, before Bun PR CI failed with missing scripts/hatch_build.py because explicit Nix source filesets selected metadata without its referenced plugin. Both packageSource and editableSource now include only scripts/hatch_build.py and scripts/build_dashboard.py. Complete standard Nix builds reuse the existing frontendAssets output; editable metadata loads the hook but leaves compilation explicit. This corrects a packaging compatibility seam without copying broad workstation state or changing Nix inputs/dependencies. +## Source checkout launchers + +The source wrappers select their own checkout, use frozen uv dependencies, and prepare missing frontend assets before delegating to app.cli in the same interpreter. Help bypasses frontend preparation. PowerShell/batch preserve CLI failure status; batch pauses only for no-argument interactive use. Bash ships executable and execs uv, preserving foreground termination semantics. Paths with spaces and a foreign caller cwd were exercised on Windows PowerShell 5/pwsh/cmd and Ubuntu 24.04 WSL. A clean baseline was backend-ready but returned dashboard 503; the old PowerShell launcher returned zero on a CLI failure. + +Linux startup revealed that bun run build can select host Node 18 via Vite shebang; build_dashboard now forces the pinned Bun runtime with --bun. The Linux audit used a checksum-verified isolated Bun 1.3.14 and forwarded SIGTERM: application shutdown completed, the listener disappeared, and uv returned expected signal code 143. Windows isolated Rust 1.96.0 native-helper build, discovery, protocol handshake and cleanup passed. These are source-install signals, not real account/OAuth/Codex traffic or macOS-native proof. Complete assets are reused; rebuild frontend explicitly after source changes. See the owning Python deployment page for prerequisite/setup/update commands. + ## Nix flake workflow The root flake is an additive installation and development path for Nix users. diff --git a/openspec/specs/deployment-installation/spec.md b/openspec/specs/deployment-installation/spec.md index f667fd6bd9..46ed634556 100644 --- a/openspec/specs/deployment-installation/spec.md +++ b/openspec/specs/deployment-installation/spec.md @@ -5,6 +5,28 @@ Define installation modes, smoke-test expectations, and the operator environment-variable contract at settings-load time, so the Helm chart remains portable across supported deployments and the configuration surface stays minimal (PRINCIPLES.md P2). ## Requirements +### Requirement: Checkout launchers prepare a ready source installation + +Checkout launchers MUST select their own project directory independently of the caller's working directory and honor the frozen Python dependency lock. Normal source startup MUST prepare missing dashboard assets with the pinned frontend toolchain before invoking the owned app CLI; prerequisite/build failure MUST prevent server startup. Frontend preparation SHALL execute node-shebang build tools with the pinned Bun runtime rather than an unrelated host Node.js. CLI help MUST remain available without frontend preparation. Launchers MUST preserve user arguments and resulting CLI failure status. The Bash launcher MUST ship with Git executable permission and preserve foreground signal semantics. + +#### Scenario: Invoke a source launcher from another directory + +- **WHEN** an operator invokes a launcher by path from outside a checkout whose path contains spaces +- **THEN** it runs that checkout with the forwarded arguments +- **AND** the server provides readiness and bundled dashboard assets using the configured data directory + +#### Scenario: Missing or incompatible frontend prerequisite + +- **WHEN** normal startup needs dashboard assets but the pinned Bun toolchain is unavailable +- **THEN** startup fails with actionable prerequisite guidance and nonzero exit status +- **AND** no dashboard-less server is started + +#### Scenario: CLI help or failure + +- **WHEN** the operator requests help without frontend prerequisites or passes an invalid CLI argument +- **THEN** help is available without building the frontend +- **AND** invalid arguments return the CLI's nonzero failure status through the launcher + ### Requirement: Nix filtered sources include declared package build hooks Both Nix package and editable source filters MUST include the custom build hook declared by project metadata and the helper it loads. They MUST preserve explicit exclusion of unrelated workstation state. Standard Nix builds SHALL reuse their prebuilt dashboard assets, while editable builds SHALL retain explicit frontend preparation. diff --git a/run.ps1 b/run.ps1 index 11864e291b..3c67e34ed3 100644 --- a/run.ps1 +++ b/run.ps1 @@ -1,4 +1,7 @@ # PowerShell launcher for codex-lb (Hardened Community Edition) +$ErrorActionPreference = 'Stop' +$PSNativeCommandUseErrorActionPreference = $false +Set-Location -LiteralPath $PSScriptRoot Write-Host "========================================================" -ForegroundColor Cyan Write-Host " codex-lb (Hardened Community Edition)" -ForegroundColor Cyan Write-Host " Web Dashboard: http://localhost:2455" -ForegroundColor Green @@ -11,4 +14,5 @@ if (-not (Get-Command uv -ErrorAction SilentlyContinue)) { exit 1 } -uv run codex-lb @args +uv run --frozen python -m scripts.source_startup @args +exit $LASTEXITCODE diff --git a/run.sh b/run.sh old mode 100644 new mode 100755 index b3169cbcd6..4c6366fcf1 --- a/run.sh +++ b/run.sh @@ -1,6 +1,8 @@ #!/usr/bin/env bash set -euo pipefail +cd -- "$(dirname -- "${BASH_SOURCE[0]}")" + echo "========================================================" echo " codex-lb (Hardened Community Edition)" echo " Web Dashboard: http://localhost:2455" @@ -13,4 +15,4 @@ if ! command -v uv >/dev/null 2>&1; then exit 1 fi -exec uv run codex-lb "$@" +exec uv run --frozen python -m scripts.source_startup "$@" diff --git a/scripts/source_startup.py b/scripts/source_startup.py new file mode 100644 index 0000000000..08ad8eb733 --- /dev/null +++ b/scripts/source_startup.py @@ -0,0 +1,27 @@ +"""Prepare the dashboard before starting the CLI from a source checkout.""" + +from __future__ import annotations + +import subprocess +import sys +from pathlib import Path + +from scripts.build_dashboard import ensure_dashboard + + +def main() -> None: + root = Path(__file__).resolve().parents[1] + if not any(argument in {"-h", "--help"} for argument in sys.argv[1:]): + try: + ensure_dashboard(root) + except (OSError, RuntimeError, subprocess.SubprocessError) as exc: + print(f"Source startup failed: {exc}", file=sys.stderr) + raise SystemExit(1) from None + from app.cli import main as cli_main + + sys.argv[0] = "codex-lb" + cli_main() + + +if __name__ == "__main__": + main() diff --git a/start.bat b/start.bat index 3f63451d6e..8689c34ee4 100644 --- a/start.bat +++ b/start.bat @@ -1,15 +1,11 @@ @echo off +setlocal title codex-lb (Hardened Community Edition) echo ======================================================== echo codex-lb (Hardened Community Edition) echo Dashboard: http://localhost:2455 echo ======================================================== -where uv >nul 2>nul -if %errorlevel% neq 0 ( - echo [ERROR] 'uv' was not found in PATH. - echo Install uv: powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" - pause - exit /b 1 -) -uv run codex-lb %* -pause +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -ExecutionPolicy Bypass -File "%~dp0run.ps1" %* +set "launcher_exit=%errorlevel%" +if "%~1"=="" pause +exit /b %launcher_exit% diff --git a/tests/unit/test_source_startup.py b/tests/unit/test_source_startup.py new file mode 100644 index 0000000000..e2ab363259 --- /dev/null +++ b/tests/unit/test_source_startup.py @@ -0,0 +1,68 @@ +from __future__ import annotations + +import subprocess +import sys +from unittest.mock import Mock + +import pytest + +from scripts import source_startup + +pytestmark = pytest.mark.unit + + +@pytest.mark.parametrize("flag", ["-h", "--help"]) +def test_source_help_does_not_require_frontend(flag: str, monkeypatch: pytest.MonkeyPatch) -> None: + prepare = Mock(side_effect=AssertionError("help must not compile frontend")) + cli = Mock() + monkeypatch.setattr(source_startup, "ensure_dashboard", prepare) + monkeypatch.setattr("app.cli.main", cli) + monkeypatch.setattr(sys, "argv", ["source_startup.py", flag]) + source_startup.main() + prepare.assert_not_called() + cli.assert_called_once_with() + assert sys.argv == ["codex-lb", flag] + + +def test_source_startup_prepares_assets_and_preserves_arguments(monkeypatch: pytest.MonkeyPatch) -> None: + prepare = Mock() + cli = Mock() + args = ["--port", "2547", "--log-file", "directory with spaces/server.log"] + monkeypatch.setattr(source_startup, "ensure_dashboard", prepare) + monkeypatch.setattr("app.cli.main", cli) + monkeypatch.setattr(sys, "argv", ["source_startup.py", *args]) + source_startup.main() + prepare.assert_called_once_with(source_startup.Path(source_startup.__file__).resolve().parents[1]) + cli.assert_called_once_with() + assert sys.argv == ["codex-lb", *args] + + +@pytest.mark.parametrize( + "failure", + [ + RuntimeError("Install bun@1.3.14"), + OSError("tool unavailable"), + subprocess.CalledProcessError(1, ["bun", "build"]), + ], +) +def test_frontend_failure_prevents_server_start( + failure: Exception, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] +) -> None: + cli = Mock() + monkeypatch.setattr(source_startup, "ensure_dashboard", Mock(side_effect=failure)) + monkeypatch.setattr("app.cli.main", cli) + monkeypatch.setattr(sys, "argv", ["source_startup.py"]) + with pytest.raises(SystemExit) as exc: + source_startup.main() + assert exc.value.code == 1 + assert "Source startup failed:" in capsys.readouterr().err + cli.assert_not_called() + + +def test_cli_failure_status_is_preserved(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setattr(source_startup, "ensure_dashboard", Mock()) + monkeypatch.setattr("app.cli.main", Mock(side_effect=SystemExit(2))) + monkeypatch.setattr(sys, "argv", ["source_startup.py", "--unknown-option"]) + with pytest.raises(SystemExit) as exc: + source_startup.main() + assert exc.value.code == 2