Cross-platform smoke test workflow (worldwonderer/oh-story-claudecode)
The Cross-platform smoke test workflow from worldwonderer/oh-story-claudecode, explained and optimized by Latchkey.
CI health: F - at risk
Point runs-on at Latchkey and get caching, run de-duplication, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Cross-platform smoke test workflow from the worldwonderer/oh-story-claudecode repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: Cross-platform smoke test
on: [push, pull_request]
jobs:
static-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Run skill static check
run: bash scripts/static-check.sh
- name: Check hook-regex sync
run: bash scripts/check-hook-regex-sync.sh
- name: Check shared-file consistency
run: bash scripts/check-shared-files.sh
- name: AI-pattern detector regression
run: bash scripts/test-ai-patterns.sh
- name: Degeneration detector regression
run: bash scripts/test-degeneration.sh
- name: Prose backstop hook regression
run: bash scripts/test-prose-backstop-hook.sh
- name: Prose net 3-CLI parity
run: bash scripts/test-prose-net-parity.sh
- name: Story continuity backstop regression
run: bash scripts/test-story-continuity.sh
- name: Check story-setup deployment
run: bash scripts/check-story-setup-deployment.sh
- name: Check Codex adapter
run: bash scripts/check-codex-adapter.sh
- name: Check OpenCode adapter
run: bash scripts/check-opencode-adapter.sh
- name: Check OpenClaw skill compatibility
run: bash scripts/check-openclaw-skills.sh
- name: Test Codex hook adapter
run: bash scripts/test-codex-hooks.sh
- name: Guard against bare python3 invocations
run: bash scripts/check-python-invocation.sh
- name: Guard hook locale safety (LC_ALL=C + no full-width char classes)
run: bash scripts/check-hook-locale-safety.sh
# Generate a GBK-class locale so the hook test's Part 2 runs end-to-end here,
# not just on macOS. Best-effort: if it fails the test self-skips Part 2.
- name: Generate zh_CN.GBK locale (Chinese Windows simulation)
run: sudo localedef -f GBK -i zh_CN zh_CN.GBK || sudo locale-gen zh_CN.GBK || true
- name: Hook path-encoding portability (cp936 + real GBK locale)
run: bash scripts/test-hook-encoding-portable.sh
- name: Portable char-count (real interpreter)
run: bash scripts/test-charcount-portable.sh
- name: Portable char-count (simulated Windows Store stub)
run: bash scripts/test-charcount-portable.sh --stub
- name: Syntax-check collection scripts
run: |
for f in $(find skills -name '*-scraper.js' -o -name 'cdp-utils.js' -o -name 'setup-cdp-chrome.js'); do
echo "node --check $f"
node --check "$f"
done
windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: AI-pattern detector regression
shell: bash
run: bash scripts/test-ai-patterns.sh
- name: Degeneration detector regression
shell: bash
run: bash scripts/test-degeneration.sh
- name: Prose backstop hook regression
shell: bash
run: bash scripts/test-prose-backstop-hook.sh
- name: Prose net 3-CLI parity
shell: bash
run: bash scripts/test-prose-net-parity.sh
- name: Story continuity backstop regression
shell: bash
run: bash scripts/test-story-continuity.sh
- name: Test Codex hook adapter
shell: bash
run: bash scripts/test-codex-hooks.sh
- name: Setup Chrome
uses: browser-actions/setup-chrome@v1
with:
chrome-version: stable
- name: Verify cdp-utils loads
run: node -e "const u = require('./skills/story-short-scan/scripts/cdp-utils.js'); console.log('exports:', Object.keys(u));"
- name: Verify sleep works
run: node -e "const { sleep } = require('./skills/story-short-scan/scripts/cdp-utils.js'); const t0 = Date.now(); sleep(100); console.log('slept', Date.now()-t0, 'ms');"
- name: Verify setup script dry-run
run: node skills/browser-cdp/scripts/setup-cdp-chrome.js 9222 --dry-run
# Run under Git Bash (shell: bash on windows-latest), matching how Claude Code
# executes its Bash tool on Windows - this is where the python3 exit-49 bug bites.
- name: Portable char-count (real interpreter)
shell: bash
run: bash scripts/test-charcount-portable.sh
- name: Portable char-count (simulated Windows Store stub)
shell: bash
run: bash scripts/test-charcount-portable.sh --stub
# Real Windows Git Bash path: the cp936 stdout bug (issue #164) bites here.
- name: Hook path-encoding portability (cp936 + GBK locale if present)
shell: bash
run: bash scripts/test-hook-encoding-portable.sh
macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: AI-pattern detector regression
run: bash scripts/test-ai-patterns.sh
- name: Degeneration detector regression
run: bash scripts/test-degeneration.sh
- name: Prose backstop hook regression
run: bash scripts/test-prose-backstop-hook.sh
- name: Prose net 3-CLI parity
run: bash scripts/test-prose-net-parity.sh
- name: Story continuity backstop regression
run: bash scripts/test-story-continuity.sh
- name: Check Codex adapter
run: bash scripts/check-codex-adapter.sh
- name: Test Codex hook adapter
run: bash scripts/test-codex-hooks.sh
- name: Setup Chrome
uses: browser-actions/setup-chrome@v1
with:
chrome-version: stable
- name: Verify cdp-utils loads
run: node -e "const u = require('./skills/story-short-scan/scripts/cdp-utils.js'); console.log('exports:', Object.keys(u));"
- name: Verify sleep works
run: node -e "const { sleep } = require('./skills/story-short-scan/scripts/cdp-utils.js'); const t0 = Date.now(); sleep(100); console.log('slept', Date.now()-t0, 'ms');"
- name: Verify setup script dry-run
run: node skills/browser-cdp/scripts/setup-cdp-chrome.js 9222 --dry-run
- name: Portable char-count (real interpreter)
run: bash scripts/test-charcount-portable.sh
- name: Portable char-count (simulated Windows Store stub)
run: bash scripts/test-charcount-portable.sh --stub
- name: Hook path-encoding portability (cp936 + GBK locale if present)
run: bash scripts/test-hook-encoding-portable.sh
The same workflow, on Latchkey
Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.
name: Cross-platform smoke test on: [push, pull_request] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: static-check: timeout-minutes: 30 runs-on: latchkey-small steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: cache: 'npm' node-version: 20 - uses: actions/setup-python@v5 with: python-version: '3.x' - name: Run skill static check run: bash scripts/static-check.sh - name: Check hook-regex sync run: bash scripts/check-hook-regex-sync.sh - name: Check shared-file consistency run: bash scripts/check-shared-files.sh - name: AI-pattern detector regression run: bash scripts/test-ai-patterns.sh - name: Degeneration detector regression run: bash scripts/test-degeneration.sh - name: Prose backstop hook regression run: bash scripts/test-prose-backstop-hook.sh - name: Prose net 3-CLI parity run: bash scripts/test-prose-net-parity.sh - name: Story continuity backstop regression run: bash scripts/test-story-continuity.sh - name: Check story-setup deployment run: bash scripts/check-story-setup-deployment.sh - name: Check Codex adapter run: bash scripts/check-codex-adapter.sh - name: Check OpenCode adapter run: bash scripts/check-opencode-adapter.sh - name: Check OpenClaw skill compatibility run: bash scripts/check-openclaw-skills.sh - name: Test Codex hook adapter run: bash scripts/test-codex-hooks.sh - name: Guard against bare python3 invocations run: bash scripts/check-python-invocation.sh - name: Guard hook locale safety (LC_ALL=C + no full-width char classes) run: bash scripts/check-hook-locale-safety.sh # Generate a GBK-class locale so the hook test's Part 2 runs end-to-end here, # not just on macOS. Best-effort: if it fails the test self-skips Part 2. - name: Generate zh_CN.GBK locale (Chinese Windows simulation) run: sudo localedef -f GBK -i zh_CN zh_CN.GBK || sudo locale-gen zh_CN.GBK || true - name: Hook path-encoding portability (cp936 + real GBK locale) run: bash scripts/test-hook-encoding-portable.sh - name: Portable char-count (real interpreter) run: bash scripts/test-charcount-portable.sh - name: Portable char-count (simulated Windows Store stub) run: bash scripts/test-charcount-portable.sh --stub - name: Syntax-check collection scripts run: | for f in $(find skills -name '*-scraper.js' -o -name 'cdp-utils.js' -o -name 'setup-cdp-chrome.js'); do echo "node --check $f" node --check "$f" done windows: timeout-minutes: 30 runs-on: windows-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: cache: 'npm' node-version: 20 - uses: actions/setup-python@v5 with: python-version: '3.x' - name: AI-pattern detector regression shell: bash run: bash scripts/test-ai-patterns.sh - name: Degeneration detector regression shell: bash run: bash scripts/test-degeneration.sh - name: Prose backstop hook regression shell: bash run: bash scripts/test-prose-backstop-hook.sh - name: Prose net 3-CLI parity shell: bash run: bash scripts/test-prose-net-parity.sh - name: Story continuity backstop regression shell: bash run: bash scripts/test-story-continuity.sh - name: Test Codex hook adapter shell: bash run: bash scripts/test-codex-hooks.sh - name: Setup Chrome uses: browser-actions/setup-chrome@v1 with: chrome-version: stable - name: Verify cdp-utils loads run: node -e "const u = require('./skills/story-short-scan/scripts/cdp-utils.js'); console.log('exports:', Object.keys(u));" - name: Verify sleep works run: node -e "const { sleep } = require('./skills/story-short-scan/scripts/cdp-utils.js'); const t0 = Date.now(); sleep(100); console.log('slept', Date.now()-t0, 'ms');" - name: Verify setup script dry-run run: node skills/browser-cdp/scripts/setup-cdp-chrome.js 9222 --dry-run # Run under Git Bash (shell: bash on windows-latest), matching how Claude Code # executes its Bash tool on Windows - this is where the python3 exit-49 bug bites. - name: Portable char-count (real interpreter) shell: bash run: bash scripts/test-charcount-portable.sh - name: Portable char-count (simulated Windows Store stub) shell: bash run: bash scripts/test-charcount-portable.sh --stub # Real Windows Git Bash path: the cp936 stdout bug (issue #164) bites here. - name: Hook path-encoding portability (cp936 + GBK locale if present) shell: bash run: bash scripts/test-hook-encoding-portable.sh macos: timeout-minutes: 30 runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: cache: 'npm' node-version: 20 - uses: actions/setup-python@v5 with: python-version: '3.x' - name: AI-pattern detector regression run: bash scripts/test-ai-patterns.sh - name: Degeneration detector regression run: bash scripts/test-degeneration.sh - name: Prose backstop hook regression run: bash scripts/test-prose-backstop-hook.sh - name: Prose net 3-CLI parity run: bash scripts/test-prose-net-parity.sh - name: Story continuity backstop regression run: bash scripts/test-story-continuity.sh - name: Check Codex adapter run: bash scripts/check-codex-adapter.sh - name: Test Codex hook adapter run: bash scripts/test-codex-hooks.sh - name: Setup Chrome uses: browser-actions/setup-chrome@v1 with: chrome-version: stable - name: Verify cdp-utils loads run: node -e "const u = require('./skills/story-short-scan/scripts/cdp-utils.js'); console.log('exports:', Object.keys(u));" - name: Verify sleep works run: node -e "const { sleep } = require('./skills/story-short-scan/scripts/cdp-utils.js'); const t0 = Date.now(); sleep(100); console.log('slept', Date.now()-t0, 'ms');" - name: Verify setup script dry-run run: node skills/browser-cdp/scripts/setup-cdp-chrome.js 9222 --dry-run - name: Portable char-count (real interpreter) run: bash scripts/test-charcount-portable.sh - name: Portable char-count (simulated Windows Store stub) run: bash scripts/test-charcount-portable.sh --stub - name: Hook path-encoding portability (cp936 + GBK locale if present) run: bash scripts/test-hook-encoding-portable.sh
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cancel superseded runs when a branch or PR gets a newer push.
- Cache dependency installs on the setup step so they are served from cache.
- Add a job timeout so a hung step cannot burn hours of runner time.
1 third-party action is referenced by a movable tag. Pin it to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.
This workflow runs 3 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.