Repository navigation
v1.91.94.0 feat(codex): --effort <level> overrides reasoning effort for one run (#3146) #1045
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Windows Setup E2E | |
| # End-to-end fresh-install gate for Windows. Builds a clean windows-latest | |
| # checkout and asserts the build completes, binaries resolve via | |
| # find-browse, and the gstack-paths state root resolves cleanly. Catches Bun | |
| # shell-parser regressions in package.json's build chain (#1538, #1537, | |
| # #1530, #1457, #1561) before they reach users. Then it runs `./setup` into | |
| # an isolated HOME and drives the installed runtime root's browse from an | |
| # unrelated directory: a piped two-command `chain` flow must print the page | |
| # text (the runtime root has no node_modules, so this is the checkout-bundle | |
| # path from #3026, and the piped-stdin path from #3039). Every compiled | |
| # binary must answer the side-effect-free --version that setup's Smart App | |
| # Control probe runs (#2595). Last, two forced CSO failures: fatal under | |
| # GSTACK_STRICT_BUILD=1, and a completed setup with the failure reported | |
| # under GSTACK_STRICT_BUILD=0 (#3071). Git Bash path spelling (#3088, | |
| # #3100): the hook check passes on this checkout, /gstack-upgrade's checkout | |
| # guard passes at its root, and an install stuck on a release whose checker | |
| # had the false positive recovers with the documented | |
| # `git pull --ff-only --autostash && ./setup`. | |
| # | |
| # Separate from windows-free-tests.yml because that one runs a curated | |
| # unit-test subset; this one exercises the install path itself. | |
| # | |
| # Runner: GitHub-hosted free windows-latest. ~6-10 min total. | |
| on: | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - 'package.json' | |
| - 'scripts/build.sh' | |
| - 'scripts/build-cso.sh' | |
| - 'scripts/build-cso-windows.ps1' | |
| - 'scripts/write-version-files.sh' | |
| - 'setup' | |
| - 'browse/src/cli.ts' | |
| - 'browse/src/find-browse.ts' | |
| - 'browse/src/server.ts' | |
| - 'browse/src/meta-commands.ts' | |
| - 'browse/scripts/build-node-server.sh' | |
| - 'design/src/cli.ts' | |
| - 'make-pdf/src/cli.ts' | |
| - 'bin/gstack-global-discover.ts' | |
| - 'bin/gstack-paths' | |
| - 'bin/gstack-doctor' | |
| - 'bin/gstack-launch-probe.sh' | |
| - 'bin/gstack-hook-check' | |
| - 'bin/gstack-session-update' | |
| - 'bin/gstack-path-spelling.sh' | |
| - 'lib/path-spelling.ts' | |
| - 'hosts/claude/hooks/**' | |
| - 'gstack-upgrade/**' | |
| - '.github/workflows/windows-setup-e2e.yml' | |
| workflow_dispatch: | |
| concurrency: | |
| # PR-number keyed: head_ref carries no fork prefix, so same-name branches | |
| # from two forks would share one group and cancel each other's runs. | |
| group: windows-setup-e2e-${{ github.event.pull_request.number || github.run_id }} | |
| cancel-in-progress: true | |
| # Install-path exercise only — no token writes. | |
| permissions: | |
| contents: read | |
| jobs: | |
| windows-setup: | |
| runs-on: windows-latest | |
| timeout-minutes: 35 | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version: 1.4.2 | |
| # Same lockfile-keyed install cache as windows-free-tests.yml (install | |
| # was 45s of a 64s job, all network). | |
| - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: windows-bun-${{ hashFiles('bun.lock') }} | |
| # A lockfile bump starts from the previous cache instead of cold | |
| # (restore alone costs ~43s; without this a bump pays it for nothing). | |
| restore-keys: | | |
| windows-bun- | |
| - name: Configure git identity | |
| run: | | |
| git config --global user.email "windows-setup-e2e@gstack.test" | |
| git config --global user.name "Windows Setup E2E" | |
| git config --global init.defaultBranch main | |
| shell: bash | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| shell: bash | |
| - name: Run bun run build (the previously-broken path) | |
| # This is the regression gate. Bun's Windows shell parser rejected | |
| # multiple constructs the old inline build chain used; the wave | |
| # moved the build to scripts/build.sh. If this step fails on | |
| # Windows, the build chain regressed. | |
| run: bun run build | |
| shell: bash | |
| env: | |
| GSTACK_SKIP_PLAYWRIGHT: '1' | |
| GSTACK_STRICT_BUILD: '1' | |
| - name: Verify binaries exist (with .exe extension on Windows) | |
| run: | | |
| set -e | |
| test -f browse/dist/browse.exe || test -f browse/dist/browse || (echo "MISSING: browse" && exit 1) | |
| test -f browse/dist/find-browse.exe || test -f browse/dist/find-browse || (echo "MISSING: find-browse" && exit 1) | |
| test -f design/dist/design.exe || test -f design/dist/design || (echo "MISSING: design" && exit 1) | |
| test -f bin/gstack-global-discover.exe || test -f bin/gstack-global-discover || (echo "MISSING: gstack-global-discover" && exit 1) | |
| echo "All binaries present" | |
| shell: bash | |
| - name: 'Every compiled binary launches with --version (Smart App Control probe, #2595)' | |
| run: | | |
| set -euo pipefail | |
| . bin/gstack-launch-probe.sh | |
| gstack_launch_probe_all "$PWD" .exe | |
| printf 'blocked: %s\nbroken: %s\nmissing: %s\n' "$_glp_blocked" "$_glp_broken" "$_glp_missing" | |
| test -z "$_glp_blocked$_glp_broken$_glp_missing" || (echo "a compiled binary did not answer --version" && exit 1) | |
| shell: bash | |
| - name: Verify find-browse resolves to the .exe variant | |
| run: | | |
| set -e | |
| OUT=$(bun browse/src/find-browse.ts 2>&1) || true | |
| echo "find-browse output: $OUT" | |
| # On Windows, find-browse should successfully resolve to a binary, | |
| # whether or not it has the .exe extension on disk. Empty output | |
| # or "not found" means the .exe extension resolver regressed. | |
| echo "$OUT" | grep -qE '(browse\.exe|browse)$' || (echo "find-browse failed to resolve binary on Windows" && exit 1) | |
| shell: bash | |
| - name: Verify gstack-paths state root resolves | |
| run: | | |
| set -e | |
| eval "$(bash bin/gstack-paths)" | |
| test -n "$GSTACK_STATE_ROOT" || (echo "GSTACK_STATE_ROOT empty" && exit 1) | |
| test -n "$PLAN_ROOT" || (echo "PLAN_ROOT empty" && exit 1) | |
| test -n "$TMP_ROOT" || (echo "TMP_ROOT empty" && exit 1) | |
| echo "GSTACK_STATE_ROOT=$GSTACK_STATE_ROOT" | |
| echo "PLAN_ROOT=$PLAN_ROOT" | |
| echo "TMP_ROOT=$TMP_ROOT" | |
| shell: bash | |
| - name: Install with ./setup into an isolated HOME | |
| # A real install: the codex host's runtime root is a copy of the | |
| # runtime files with no node_modules beside it. setup installs | |
| # Playwright's Chromium (best-effort) for the journey below. | |
| run: | | |
| set -euo pipefail | |
| E2E_HOME="$RUNNER_TEMP/gstack-e2e-home" | |
| mkdir -p "$E2E_HOME" | |
| HOME="$E2E_HOME" USERPROFILE="$(cygpath -w "$E2E_HOME")" GSTACK_STRICT_BUILD=1 ./setup --host codex | |
| ROOT="$E2E_HOME/.codex/skills/gstack" | |
| test -f "$ROOT/.source-path" || (echo "MISSING: $ROOT/.source-path" && exit 1) | |
| test ! -e "$ROOT/node_modules" || (echo "UNEXPECTED: $ROOT/node_modules (the journey must exercise the copy without it)" && exit 1) | |
| echo "runtime root: $ROOT -> source $(cat "$ROOT/.source-path")" | |
| shell: bash | |
| - name: Installed browse runs a piped chain flow from an unrelated directory | |
| run: | | |
| set -euo pipefail | |
| E2E_HOME="$RUNNER_TEMP/gstack-e2e-home" | |
| USERPROFILE="$(cygpath -w "$E2E_HOME")" | |
| export HOME="$E2E_HOME" USERPROFILE | |
| BROWSE="$E2E_HOME/.codex/skills/gstack/browse/dist/browse.exe" | |
| [ -f "$BROWSE" ] || BROWSE="$E2E_HOME/.codex/skills/gstack/browse/dist/browse" | |
| test -f "$BROWSE" || (echo "MISSING: installed browse" && exit 1) | |
| bun -e 'Bun.serve({ hostname: "127.0.0.1", port: 47123, fetch: () => new Response("<title>gstack e2e</title><h1>gstack-windows-chain-ok</h1>", { headers: { "content-type": "text/html" } }) }); setInterval(() => {}, 1 << 30);' & | |
| PAGE_PID=$! | |
| trap 'kill "$PAGE_PID" 2>/dev/null || true; "$BROWSE" stop >/dev/null 2>&1 || true' EXIT | |
| UNRELATED="$RUNNER_TEMP/unrelated-dir" | |
| mkdir -p "$UNRELATED" && cd "$UNRELATED" | |
| set +e | |
| OUT=$(printf '%s\n' '[["goto","http://127.0.0.1:47123/"],["text"]]' | "$BROWSE" chain 2>&1) | |
| CODE=$? | |
| set -e | |
| echo "$OUT" | |
| if [ "$CODE" -ne 0 ]; then | |
| echo "browse chain exited $CODE; server logs:" | |
| find "$UNRELATED" "$E2E_HOME" -maxdepth 4 \( -name 'browse-daemon.log' -o -name 'browse-startup-error.log' \) -print -exec tail -n 60 {} \; 2>/dev/null || true | |
| cat "$E2E_HOME/.codex/skills/gstack/.source-path" 2>/dev/null || true | |
| exit 1 | |
| fi | |
| echo "$OUT" | grep -q 'gstack-windows-chain-ok' || (echo "chain output lacks the page text: the flow did not run" && exit 1) | |
| # Empty piped input is a usage error, never a silent exit 0. | |
| set +e | |
| EMPTY_OUT=$(printf '' | "$BROWSE" chain 2>&1) | |
| EMPTY_CODE=$? | |
| set -e | |
| echo "$EMPTY_OUT" | |
| test "$EMPTY_CODE" -eq 1 || (echo "empty chain exited $EMPTY_CODE, expected 1" && exit 1) | |
| echo "$EMPTY_OUT" | grep -q 'no flow to run' || (echo "empty chain lacks the usage error" && exit 1) | |
| shell: bash | |
| - name: The hook check passes on this checkout under Git Bash (#3088, #3100) | |
| run: | | |
| set -uo pipefail | |
| OUT=$(bash bin/gstack-hook-check "$PWD" 2>&1) | |
| CODE=$? | |
| echo "$OUT" | |
| test "$CODE" -eq 0 || (echo "gstack-hook-check exited $CODE" && exit 1) | |
| ! echo "$OUT" | grep -q '^fail ' || (echo "gstack-hook-check reported a fail line" && exit 1) | |
| echo "$OUT" | grep -q '^ok hosts/claude/hooks/question-log-hook$' || (echo "the TypeScript hooks were not checked" && exit 1) | |
| shell: bash | |
| - name: /gstack-upgrade's checkout guard passes at the checkout root and refuses below it | |
| run: | | |
| set -euo pipefail | |
| GUARD=$(grep -m1 -- '--show-prefix' gstack-upgrade/SKILL.md.tmpl) | |
| echo "guard: $GUARD" | |
| INSTALL_DIR="$PWD" bash -c "cd \"\$INSTALL_DIR\" && $GUARD && echo GUARD_OK" | grep -q GUARD_OK || (echo "the guard refused the checkout root" && exit 1) | |
| if INSTALL_DIR="$PWD/bin" bash -c "cd \"\$INSTALL_DIR\" && $GUARD && echo GUARD_OK" 2>/dev/null | grep -q GUARD_OK; then | |
| echo "the guard accepted a directory below the root" && exit 1 | |
| fi | |
| shell: bash | |
| - name: An install stuck on the false positive recovers with the documented command (#3088, #3100) | |
| # A release whose bin/gstack-hook-check had the Git Bash false positive | |
| # (v1.91.83.0's checker on this tree), then this revision on top. The | |
| # recovery is the one docs/troubleshooting.md gives. | |
| run: | | |
| set -euo pipefail | |
| OLD_RELEASE=5cb5e1cfc115e82388df07896664640a1224fe5d | |
| T="$RUNNER_TEMP/recovery" | |
| E2E_HOME="$T/home" | |
| INSTALL="$E2E_HOME/.claude/skills/gstack" | |
| mkdir -p "$E2E_HOME/.claude/skills" "$T" | |
| git fetch -q --no-tags --depth=1 origin "$OLD_RELEASE" | |
| git show "$OLD_RELEASE:bin/gstack-hook-check" > "$T/old-check" | |
| git init -q --bare -b main "$T/origin.git" | |
| git -C "$T/origin.git" config receive.shallowUpdate true | |
| git clone -q --no-local "$PWD" "$T/work" | |
| cp "$T/old-check" "$T/work/bin/gstack-hook-check" | |
| git -C "$T/work" commit -qam "release with the false positive" | |
| STUCK=$(git -C "$T/work" rev-parse HEAD) | |
| git -C "$T/work" checkout -q HEAD~1 -- bin/gstack-hook-check | |
| git -C "$T/work" commit -qm "this revision" | |
| git -C "$T/work" push -q "$T/origin.git" HEAD:refs/heads/main | |
| git clone -q "$T/origin.git" "$INSTALL" | |
| git -C "$INSTALL" reset -q --hard "$STUCK" | |
| set +e | |
| BEFORE=$(bash "$INSTALL/bin/gstack-hook-check" "$INSTALL" 2>&1) | |
| set -e | |
| echo "$BEFORE" | |
| echo "$BEFORE" | grep -q 'bun could not bundle the TypeScript entry' || (echo "the old release's checker did not show the false positive" && exit 1) | |
| set +e | |
| OUT=$(cd "$INSTALL" && git pull --ff-only --autostash && HOME="$E2E_HOME" USERPROFILE="$(cygpath -w "$E2E_HOME")" \ | |
| GSTACK_SKIP_PLAYWRIGHT=1 GSTACK_STRICT_BUILD=0 ./setup 2>&1) | |
| CODE=$? | |
| set -e | |
| echo "$OUT" | tail -n 40 | |
| test "$CODE" -eq 0 || (echo "the documented recovery exited $CODE" && exit 1) | |
| ! echo "$OUT" | grep -q 'refusing to register hooks' || (echo "setup still refused hooks after the recovery" && exit 1) | |
| test "$(git -C "$INSTALL" rev-parse HEAD)" != "$STUCK" || (echo "the recovery did not move the checkout" && exit 1) | |
| shell: bash | |
| - name: A forced CSO failure is fatal under GSTACK_STRICT_BUILD=1 (#3071) | |
| run: | | |
| set -uo pipefail | |
| rm -f browse/dist/.build-complete | |
| set +e | |
| GSTACK_SKIP_PLAYWRIGHT=1 GSTACK_STRICT_BUILD=1 GSTACK_CSO_BUILD_TESTING=1 GSTACK_CSO_BUILD_TEST_FAIL_AFTER=core bun run build > strict.log 2>&1 | |
| CODE=$? | |
| set -e | |
| tail -n 20 strict.log | |
| test "$CODE" -ne 0 || (echo "strict build passed despite the injected CSO failure" && exit 1) | |
| grep -q 'GSTACK_STRICT_BUILD=1 makes it fatal' strict.log || (echo "strict failure lacks its message" && exit 1) | |
| shell: bash | |
| - name: A forced CSO publish failure still completes setup (#3071) | |
| run: | | |
| set -euo pipefail | |
| E2E_HOME="$RUNNER_TEMP/gstack-e2e-cso-fail" | |
| mkdir -p "$E2E_HOME" | |
| rm -f browse/dist/.build-complete | |
| set +e | |
| OUT=$(HOME="$E2E_HOME" USERPROFILE="$(cygpath -w "$E2E_HOME")" GSTACK_SKIP_PLAYWRIGHT=1 GSTACK_STRICT_BUILD=0 \ | |
| GSTACK_CSO_BUILD_TESTING=1 GSTACK_CSO_BUILD_TEST_FAIL_AFTER=publish-core ./setup --host codex 2>&1) | |
| CODE=$? | |
| set -e | |
| echo "$OUT" | tail -n 40 | |
| test "$CODE" -eq 0 || (echo "setup exited $CODE after an optional CSO failure" && exit 1) | |
| echo "$OUT" | grep -qE 'CSO publish step failed \(exit 86\).*previous CSO kept|CSO unavailable: the native helper.s publish step failed' || (echo "setup did not report the CSO publish failure" && exit 1) | |
| grep -q '^result=failed' bin/.gstack-cso-build-result | |
| grep -q '^stage=publish' bin/.gstack-cso-build-result | |
| test -f browse/dist/.build-complete || (echo "the build stopped at CSO" && exit 1) | |
| DOCTOR=$(HOME="$E2E_HOME" bash bin/gstack-doctor 2>&1 || true) | |
| echo "$DOCTOR" | |
| echo "$DOCTOR" | grep -qE '^warn +cso +' || (echo "doctor did not report the CSO failure" && exit 1) | |
| shell: bash |