Skip to content

fix: harden managed runtime events and voice transcripts #783

fix: harden managed runtime events and voice transcripts

fix: harden managed runtime events and voice transcripts #783

Workflow file for this run

name: CI
on:
push:
branches: [main, rust]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ci-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
quality:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.14"
cache: pip
cache-dependency-path: pyproject.toml
- name: Install quality dependencies
run: |
python -m pip install -U pip
python -m pip install pytest pyyaml ruff
- name: Run Ruff error checks
run: python -m ruff check scripts tests
- name: Test quality tooling and workflow contracts
run: python -m pytest -q
web:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Set up Node
uses: actions/setup-node@v7
with:
node-version: "24.19.0"
cache: npm
cache-dependency-path: web/package-lock.json
- name: Install Web dependencies
run: npm ci --prefix web
- name: Check Web
run: npm -C web run check
- name: Test Web
run: npm -C web test
- name: Build Web bundle
run: npm -C web run build
- name: Upload Web bundle
uses: actions/upload-artifact@v7
with:
name: bundled-web
path: web/dist
if-no-files-found: error
package:
needs: quality
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.14"
cache: pip
cache-dependency-path: pyproject.toml
- name: Verify Rust-only release packaging tools
run: |
python -m pip install -U pip twine pytest pyyaml
python -m pytest -q \
tests/test_build_native_wheel.py \
tests/test_build_standalone_archive.py \
tests/test_verify_release_set.py \
tests/test_smoke_wheel_frontdoor.py
mkdir -p native-wheel-smoke
python scripts/build_native_wheel.py \
/bin/true \
--platform-tag manylinux_2_28_x86_64 \
--output-dir native-wheel-smoke
native_wheel="$(find native-wheel-smoke -maxdepth 1 -name '*.whl' -print -quit)"
python scripts/verify_native_wheel.py \
"$native_wheel" \
--platform-tag manylinux_2_28_x86_64 \
--binary /bin/true
python -m twine check "$native_wheel"
python - <<'PY'
from pathlib import Path
import zipfile
wheel = next(Path("native-wheel-smoke").glob("*.whl"))
assert "-py3-none-manylinux_2_28_x86_64.whl" in wheel.name, wheel
with zipfile.ZipFile(wheel) as archive:
names = set(archive.namelist())
assert not any(name.endswith((".py", ".pyc")) for name in names)
assert not any(name.startswith("cccc/") for name in names)
assert any(name.endswith(".data/scripts/cccc") for name in names)
print("OK: CI exercises only the Rust-only release wheel shape")
PY
windows-smoke:
needs: web
runs-on: windows-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Download Web bundle
uses: actions/download-artifact@v8
with:
name: bundled-web
path: web/dist
- name: Set up Rust
uses: dtolnay/rust-toolchain@1.88.0
- uses: Swatinem/rust-cache@v2
- name: Verify Windows PTY UTF-8 message delivery
timeout-minutes: 10
run: >-
cargo test --package cccc-pair-runtime --lib --locked
manager_windows_tests::npm_style_batch_actor_survives_utf8_message_delivery
-- --test-threads=1
- name: Verify Windows suspended process launch
timeout-minutes: 2
run: >-
cargo test --package cccc-windows-process --lib --locked
-- --test-threads=1
- name: Verify Windows owned Job cleanup
timeout-minutes: 2
run: >-
cargo test --package cccc-pair-runtime --lib --locked
process_tree::windows_tests:: -- --test-threads=1
- name: Verify Windows console UTF-8 encoding lifecycle
timeout-minutes: 10
run: >-
cargo test --package cccc --bin cccc --locked
console_encoding::tests::console_uses_utf8_for_cli_lifetime_and_restores_both_original_pages
-- --test-threads=1
- name: Verify combined Web startup failure releases its daemon
timeout-minutes: 10
run: >-
cargo test --package cccc --test integration --locked
daemon_self_launch::combined_web_bind_failure_stops_its_owned_daemon
-- --test-threads=1
- name: Verify abrupt daemon process-tree cleanup
timeout-minutes: 10
run: >-
cargo test --package cccc-pair-daemon --lib --locked
process_tree::tests::abrupt_daemon_exit_reaps_child_and_grandchild_without_deleting_history
-- --test-threads=1
- name: Set up Node for Windows npm entrypoint tests
uses: actions/setup-node@v7
with:
node-version: "24.19.0"
- name: Verify Windows Kilo npm managed launch
timeout-minutes: 3
run: >-
cargo test --package cccc-pair-daemon --lib --locked
opencode::launch_tests:: -- --test-threads=1
rust-linux:
needs: web
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v7
- uses: actions/download-artifact@v8
with:
name: bundled-web
path: web/dist
- uses: dtolnay/rust-toolchain@1.88.0
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- name: Check Rust formatting
run: cargo fmt --all --check
- name: Lint Rust workspace
run: cargo clippy --workspace --all-targets --locked -- -D warnings
- name: Test installer and release assets
run: |
scripts/tests/install_unix.sh
scripts/tests/release_assets.sh
- name: Test Rust workspace
run: |
# Process lifecycle tests run serially in the final step because they
# spawn and stop a combined daemon/Web process.
cargo test --workspace --exclude cccc-pair-daemon --locked -- \
--skip daemon_self_launch::
cargo test --package cccc-pair-daemon --locked -- \
--test-threads=1
- name: Test combined daemon and Web process lifecycle serially
run: >-
cargo test --package cccc --test integration --locked
daemon_self_launch:: -- --test-threads=1
- name: Set up Node for offline native-runtime smoke tests
uses: actions/setup-node@v7
with:
node-version: "24.19.0"
- name: Install verified native CLI versions
run: npm install --global @openai/codex@0.153.2 @anthropic-ai/claude-code@2.1.261 @kilocode/cli@7.5.14
- name: Verify native sessions without external model access
timeout-minutes: 5
env:
CCCC_LAUNCHER_PATH: ${{ github.workspace }}/target/debug/cccc
CCCC_CODEX_EMPTY_LIVE: "1"
CCCC_CLAUDE_EMPTY_LIVE: "1"
CCCC_KILO_MANAGED_LIVE: "1"
CCCC_KILO_MODEL_SYNC_LIVE: "1"
run: |
cargo build --package cccc --bin cccc --locked
cargo test --package cccc-pair-daemon --lib --locked \
live_codex_empty_actor_and_analyst_resume_with_native_terminal -- --test-threads=1
cargo test --package cccc-pair-daemon --lib --locked \
live_claude_empty_session_resumes_without_a_prompt -- --test-threads=1
cargo test --package cccc-pair-daemon --lib --locked \
live_kilo -- --test-threads=1
ci-required:
if: always()
needs:
- quality
- web
- package
- windows-smoke
- rust-linux
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Verify required CI jobs
env:
NEEDS_CONTEXT: ${{ toJSON(needs) }}
shell: bash
run: |
failures="$(
jq -r '
to_entries[]
| select(.value.result != "success")
| "\(.key)=\(.value.result)"
' <<<"$NEEDS_CONTEXT"
)"
if [[ -n "$failures" ]]; then
echo "Required CI jobs did not succeed:"
echo "$failures"
exit 1
fi
echo "All required CI jobs succeeded."