fix(team): make worker startup acknowledgement durable #4651
Workflow file for this run
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: CI | |
| on: | |
| push: | |
| branches: [main, dev] | |
| pull_request: | |
| branches: [main, dev] | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| lint-and-typecheck: | |
| name: Lint & Type Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Type check | |
| run: npx tsc --noEmit | |
| - name: Lint | |
| run: npm run lint --if-present | |
| test: | |
| name: Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run functional tests | |
| run: npm test -- --run | |
| - name: Run subagent-lock performance test | |
| run: npm exec vitest -- run tests/perf/subagent-lock.bench.ts --fileParallelism=false --maxWorkers=1 | |
| test-windows: | |
| name: Test (Windows path suite) | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| # Scoped to the cross-platform path/encoding suites on a real Windows | |
| # runner. The ubuntu-only `test` job exercises POSIX separators, so | |
| # forward-slash assumptions in project-dir encoding and worktree | |
| # transcript resolution (see #3274, #3276) can slip through it. Running | |
| # the full `npm test` suite here is not yet possible: it has pre-existing | |
| # platform-specific failures on Windows (e.g. python-repl sandbox, lsp | |
| # devcontainer, session-end path interpolation) that are out of scope for | |
| # this gate. Keep this list in sync with the path-handling test files. | |
| - name: Run Windows path-handling tests | |
| run: >- | |
| npx vitest run | |
| src/utils/__tests__/encode-project-path.test.ts | |
| src/__tests__/resolve-transcript-path.test.ts | |
| src/__tests__/session-history-search.test.ts | |
| src/cli/__tests__/session-search.test.ts | |
| src/lib/__tests__/worktree-paths.test.ts | |
| src/hooks/project-memory/__tests__/hot-path-tracker.test.ts | |
| src/hooks/merge-readiness/__tests__/win-cross-platform.test.ts | |
| src/hooks/merge-readiness/__tests__/runtime.test.ts | |
| src/hooks/merge-readiness/__tests__/tool-flow.test.ts | |
| src/__tests__/windows-prompt-hook-runner.test.ts | |
| src/installer/__tests__/claude-md-transaction.test.ts | |
| src/team/__tests__/cli-detection.windows.integration.test.ts | |
| build: | |
| name: Build | |
| runs-on: ubuntu-latest | |
| needs: [lint-and-typecheck, test] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Verify committed plugin shipping surface | |
| run: npm run plugin:shipping:verify | |
| - name: Build | |
| run: npm run build | |
| - name: Verify bridge registers all merge-readiness tools (source/packaged parity) | |
| run: | | |
| set -e | |
| for tool in merge_readiness_start merge_readiness_set_content merge_readiness_record_answer merge_readiness_report merge_readiness_cancel; do | |
| if ! grep -q "\"$tool\"" bridge/mcp-server.cjs; then | |
| echo "::error::Packaged bridge/mcp-server.cjs is missing tool: $tool. Source/packaged parity broken (run npm run build)." | |
| exit 1 | |
| fi | |
| echo "bridge registers $tool" | |
| done | |
| - name: Check dist size | |
| run: | | |
| DIST_SIZE=$(du -sm dist | cut -f1) | |
| echo "📦 Dist size: ${DIST_SIZE}MB" | |
| if [ "$DIST_SIZE" -gt 50 ]; then | |
| echo "⚠️ Warning: dist folder is larger than 50MB!" | |
| fi | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| retention-days: 7 | |
| no-committed-build-artifacts: | |
| name: No Committed Build Artifacts | |
| runs-on: ubuntu-latest | |
| # This candidate-side classifier is credential-free containment only; it | |
| # never authorizes generated artifacts or supplies merge approval. | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Hold candidate generated changes | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: node scripts/ci/check-no-committed-build-artifacts.mjs --base "$BASE_SHA" --head "$HEAD_SHA" | |
| multirepo-paths-gate: | |
| name: Multi-repo Path Gate (AST-grep) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, windows-latest] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Check for raw .omc path constructions | |
| run: node scripts/ci/check-multirepo-paths.mjs | |
| version-check: | |
| name: Version Consistency Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - name: Check version consistency | |
| run: | | |
| PKG_VERSION=$(node -p "require('./package.json').version") | |
| PLUGIN_VERSION=$(node -p "require('./.claude-plugin/plugin.json').version") | |
| MARKET_VERSION=$(node -p "require('./.claude-plugin/marketplace.json').version") | |
| echo "package.json: $PKG_VERSION" | |
| echo ".claude-plugin/plugin.json: $PLUGIN_VERSION" | |
| echo ".claude-plugin/marketplace.json: $MARKET_VERSION" | |
| if [ "$PKG_VERSION" != "$PLUGIN_VERSION" ] || [ "$PKG_VERSION" != "$MARKET_VERSION" ]; then | |
| echo "" | |
| echo "❌ Version mismatch!" | |
| echo " package.json: $PKG_VERSION" | |
| echo " plugin.json: $PLUGIN_VERSION" | |
| echo " marketplace.json: $MARKET_VERSION" | |
| echo "" | |
| echo "All three files must have the same version." | |
| exit 1 | |
| fi | |
| echo "✅ All versions match: $PKG_VERSION" | |
| npm-pack-test: | |
| name: npm pack + install test | |
| runs-on: ubuntu-latest | |
| needs: build | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build | |
| run: npm run build | |
| - name: npm pack test | |
| run: | | |
| echo "📦 Creating tarball..." | |
| npm pack | |
| TARBALL=$(ls -t oh-my-claude-sisyphus-*.tgz | head -1) | |
| echo "📦 Tarball: $TARBALL" | |
| echo "🔎 Verifying the packaged MCP bridge registers every merge-readiness tool..." | |
| for tool in merge_readiness_start merge_readiness_set_content merge_readiness_record_answer merge_readiness_report merge_readiness_cancel; do | |
| if ! tar -xOf "$TARBALL" package/bridge/mcp-server.cjs | grep -q "\"$tool\""; then | |
| echo "::error::npm package bridge/mcp-server.cjs is missing tool: $tool" | |
| exit 1 | |
| fi | |
| echo "packaged bridge registers $tool" | |
| done | |
| # ENOTEMPTY hardening (mirrors .github/workflows/upgrade-test.yml): | |
| # the global node_modules dir is reused across runs on GitHub-hosted | |
| # runners and inside the GitHub-hosted tool cache. A previously | |
| # interrupted `npm install -g` can leave the resolved package dir | |
| # and/or npm's staging temp dirs (`.oh-my-claude-sisyphus-*`) behind, | |
| # so the next install fails with | |
| # npm ERR! ENOTEMPTY: directory not empty, rename | |
| # '.../oh-my-claude-sisyphus' -> '.../.oh-my-claude-sisyphus-XXXX' | |
| # Remove any stale global package + npm staging dirs before | |
| # installing, then retry a few times so a transient rename race does | |
| # not fail the run. A persistent install failure still exits non-zero. | |
| PKG=oh-my-claude-sisyphus | |
| GLOBAL_ROOT="$(npm root -g)" | |
| clean_stale_global_pkg() { | |
| # `:?` guards against an empty GLOBAL_ROOT so we never rm -rf "/". | |
| rm -rf "${GLOBAL_ROOT:?}/$PKG" 2>/dev/null || true | |
| find "$GLOBAL_ROOT" -maxdepth 1 -name ".$PKG-*" -exec rm -rf {} + 2>/dev/null || true | |
| } | |
| echo "📦 Testing global install from tarball..." | |
| clean_stale_global_pkg | |
| ATTEMPTS=3 | |
| INSTALLED=false | |
| for attempt in $(seq 1 "$ATTEMPTS"); do | |
| echo "Installing $TARBALL globally (attempt $attempt/$ATTEMPTS)" | |
| if npm install -g "./$TARBALL" --no-audit --no-fund; then | |
| INSTALLED=true | |
| break | |
| fi | |
| echo "Install attempt $attempt failed; cleaning stale global state and retrying." | |
| clean_stale_global_pkg | |
| sleep 2 | |
| done | |
| if [ "$INSTALLED" != "true" ]; then | |
| echo "❌ npm install -g ./$TARBALL failed after $ATTEMPTS attempts" | |
| exit 1 | |
| fi | |
| echo "🔍 Checking omc command..." | |
| which omc | |
| echo "🔍 Testing omc --version..." | |
| omc --version | |
| VERSION_OUTPUT=$(omc --version 2>&1) | |
| if [ $? -ne 0 ]; then | |
| echo "❌ omc --version failed!" | |
| echo "$VERSION_OUTPUT" | |
| exit 1 | |
| fi | |
| echo "✅ omc --version: $VERSION_OUTPUT" | |
| echo "🔍 Testing omc --help..." | |
| omc --help | |
| HELP_OUTPUT=$(omc --help 2>&1) | |
| if [ $? -ne 0 ]; then | |
| echo "❌ omc --help failed!" | |
| echo "$HELP_OUTPUT" | |
| exit 1 | |
| fi | |
| echo "✅ npm pack + install test passed!" |