singularity-forge/scripts/ci_monitor.cjs

562 lines
16 KiB
JavaScript
Raw Normal View History

feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
#!/usr/bin/env node
/**
* GitHub Actions CI/CD Workflow Monitor - Pure Node.js implementation
*/
2026-05-05 14:46:18 +02:00
const { spawnSync } = require("node:child_process");
const fs = require("node:fs");
const path = require("node:path");
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
2026-05-05 14:31:16 +02:00
const EMOJI = {
success: "✅",
failure: "❌",
cancelled: "🚫",
skipped: "⏭️",
timed_out: "⏱️",
in_progress: "▶️",
queued: "⏳",
};
const INTERVAL = 10,
TIMEOUT = 3600,
MAXBUF = 50 * 1024 * 1024;
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
// Pure Node.js gh CLI helpers - no shell strings
const gh = (args, opts = {}) => {
2026-05-05 14:31:16 +02:00
const r = spawnSync("gh", args, {
encoding: "utf-8",
maxBuffer: opts.maxBuffer || MAXBUF,
cwd: opts.cwd,
});
if (r.error) throw r.error;
if (r.status !== 0 && !opts.allowFail)
throw new Error(r.stderr || `gh exited ${r.status}`);
return r.stdout;
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
};
const ghJson = (args, opts) => JSON.parse(gh(args, opts));
const cliRepo = (() => {
2026-05-05 14:31:16 +02:00
const a = process.argv;
const i = a.findIndex((x) => x === "--repo" || x === "-R");
return i >= 0 && a[i + 1] ? a[i + 1] : null;
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
})();
let _repo = null;
2026-05-05 14:31:16 +02:00
const getRepo = () =>
_repo ||
(_repo =
cliRepo ||
process.env.GITHUB_REPOSITORY ||
ghJson(["repo", "view", "--json", "nameWithOwner"]).nameWithOwner);
const runView = (id, f = "status,conclusion,jobs") =>
ghJson(["run", "view", String(id), "--repo", getRepo(), "--json", f]);
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
const runList = (opts = {}) => {
2026-05-05 14:31:16 +02:00
const args = [
"run",
"list",
"--repo",
getRepo(),
"--limit",
String(opts.limit || 10),
"--json",
"databaseId,status,conclusion,headBranch,createdAt,displayTitle,event",
];
if (opts.branch) args.push("--branch", opts.branch);
return ghJson(args);
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
};
2026-05-05 14:31:16 +02:00
const getLogs = (runId, jobId) =>
gh(
[
"run",
"view",
String(runId),
"--repo",
getRepo(),
"--log",
"--job",
String(jobId),
],
{ maxBuffer: MAXBUF },
);
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
const findJob = (runId, name) => {
2026-05-05 14:31:16 +02:00
const job = runView(runId, "jobs").jobs?.find((j) => j.name === name);
if (!job) {
console.error(`❌ Job "${name}" not found`);
process.exit(1);
}
return job;
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
};
2026-05-05 14:31:16 +02:00
const emoji = (s, c) => EMOJI[c || s] || "❓";
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
// Commands
const cmd = {
2026-05-05 14:31:16 +02:00
runs: (opts = {}) => {
2026-05-05 14:46:18 +02:00
const list = runList({ ...opts, limit: parseInt(opts.limit, 10) || 15 });
2026-05-05 14:31:16 +02:00
console.log(
`\n📋 Recent runs${opts.branch ? ` for "${opts.branch}"` : ""}:\n`,
);
for (const r of list) {
console.log(
`${emoji(r.status, r.conclusion)} ${String(r.databaseId).padEnd(12)} ${new Date(r.createdAt).toLocaleDateString()} [${(r.headBranch || "").padEnd(20)}] (${r.event || ""})`,
);
if (r.displayTitle)
console.log(` ${r.displayTitle.substring(0, 60)}`);
}
return list;
},
watch: async (id, opts = {}) => {
2026-05-05 14:46:18 +02:00
const int = parseInt(opts.interval, 10) || INTERVAL;
2026-05-05 14:31:16 +02:00
console.log(`👁️ Watching run ${id}...\n`);
const last = new Map();
while (true) {
const run = runView(id);
const rs = `${run.status}:${run.conclusion}`;
if (last.get("run") !== rs) {
console.log(
`${emoji(run.status, run.conclusion)} Run: ${run.status}${run.conclusion ? " → " + run.conclusion : ""}`,
);
last.set("run", rs);
}
for (const j of run.jobs || []) {
const js = `${j.status}:${j.conclusion}`;
if (last.get(`job:${j.id}`) !== js) {
console.log(
` ${emoji(j.status, j.conclusion)} ${j.name}: ${j.status}${j.conclusion ? " → " + j.conclusion : ""}`,
);
last.set(`job:${j.id}`, js);
}
}
if (run.status === "completed") {
console.log(
`\n${emoji(run.status, run.conclusion)} Completed: ${run.conclusion}`,
);
process.exit(run.conclusion === "success" ? 0 : 1);
}
await sleep(int * 1000);
}
},
"fail-fast": async (id, opts = {}) => {
2026-05-05 14:46:18 +02:00
const int = parseInt(opts.interval, 10) || INTERVAL;
2026-05-05 14:31:16 +02:00
console.log(`🔍 Watching run ${id} (fail-fast)...\n`);
const seen = new Set();
while (true) {
const run = runView(id);
for (const j of run.jobs || []) {
if (!seen.has(j.id)) {
console.log(
`${emoji(j.status, j.conclusion)} ${j.name}: ${j.conclusion || j.status}`,
);
seen.add(j.id);
}
if (j.conclusion === "failure") {
console.log(
`\n❌ Job "${j.name}" failed!\n📋 Run: ci_monitor.cjs log-failed ${id}`,
);
process.exit(1);
}
}
if (run.status === "completed") {
console.log(
`\n${emoji(run.status, run.conclusion)} Run completed: ${run.conclusion}`,
);
process.exit(run.conclusion === "success" ? 0 : 1);
}
await sleep(int * 1000);
}
},
"list-jobs": (id, opts = {}) => {
let jobs = runView(id).jobs || [];
if (opts.status)
jobs = jobs.filter(
(j) => j.conclusion === opts.status || j.status === opts.status,
);
console.log(`\n📋 Jobs in run ${id}:\n`);
for (const j of jobs)
console.log(
`${emoji(j.status, j.conclusion)} ${(j.conclusion || j.status || "?").padEnd(12)} ${j.name}`,
);
},
"log-failed": (id, opts = {}) => {
const run = runView(id, "jobs");
if (!(run.jobs || []).some((j) => j.conclusion === "failure")) {
console.log("✅ No failed jobs found.");
return;
}
console.log(`\n❌ Failed jobs in run ${id}:\n`);
try {
console.log(
gh(["run", "view", String(id), "--repo", getRepo(), "--log-failed"], {
maxBuffer: MAXBUF,
})
.split(/\r?\n/)
2026-05-05 14:46:18 +02:00
.slice(-(parseInt(opts.lines, 10) || 200))
2026-05-05 14:31:16 +02:00
.join("\n"),
);
} catch (e) {
console.error(`Could not fetch logs: ${e.message}`);
}
},
log: (id, opts = {}) => {
console.log(`\n📋 Full logs for run ${id}:\n`);
try {
let lines = gh(
["run", "view", String(id), "--repo", getRepo(), "--log"],
{ maxBuffer: MAXBUF },
).split(/\r?\n/);
if (opts.filter) {
const re = new RegExp(opts.filter, "gi");
lines = lines.filter((l) => re.test(l));
console.log(`🔍 Filtered (${lines.length} lines):\n`);
}
2026-05-05 14:46:18 +02:00
console.log(lines.slice(-(parseInt(opts.lines, 10) || 500)).join("\n"));
2026-05-05 14:31:16 +02:00
} catch (e) {
console.error(`Could not fetch logs: ${e.message}`);
}
},
grep: (id, opts = {}) => {
if (!opts.pattern) {
console.error("❌ --pattern required");
process.exit(1);
}
console.log(`\n🔍 Searching for "${opts.pattern}" in run ${id}:\n`);
try {
const lines = gh(
["run", "view", String(id), "--repo", getRepo(), "--log"],
{ maxBuffer: MAXBUF },
).split(/\r?\n/);
const re = new RegExp(opts.pattern, "gi");
const matches = lines
.map((l, i) => (re.test(l) ? { i, l } : null))
.filter(Boolean);
if (!matches.length) {
console.log("No matches found.");
return;
}
console.log(`Found ${matches.length} matches:\n`);
2026-05-05 14:46:18 +02:00
const ctx = parseInt(opts.context, 10) || 3;
2026-05-05 14:31:16 +02:00
for (const m of matches.slice(0, 20)) {
console.log(`--- Line ${m.i} ---`);
for (
let j = Math.max(0, m.i - ctx);
j < Math.min(lines.length, m.i + ctx + 1);
j++
)
console.log(`${j === m.i ? ">>>" : " "} ${lines[j]}`);
}
if (matches.length > 20)
console.log(`\n... and ${matches.length - 20} more`);
} catch (e) {
console.error(`Could not fetch logs: ${e.message}`);
}
},
2026-05-05 14:46:18 +02:00
"test-summary": (id, _opts = {}) => {
2026-05-05 14:31:16 +02:00
console.log(`\n📊 Test summary for run ${id}:\n`);
try {
const logs = gh(
["run", "view", String(id), "--repo", getRepo(), "--log"],
{ maxBuffer: MAXBUF },
);
const t = logs.match(/# tests[\s:]+(\d+)/i),
p = logs.match(/# pass[\s:]+(\d+)/i),
f = logs.match(/# fail[\s:]+(\d+)/i);
const notOk = logs.match(/^not ok .+$/gm);
if (t) console.log(` Total tests: ${t[1]}`);
if (p) console.log(` ✅ Passed: ${p[1]}`);
if (f) console.log(` ❌ Failed: ${f[1]}`);
if (notOk?.length) {
console.log(`\nFailed tests:`);
notOk.slice(0, 15).forEach((x) => console.log(` ${x}`));
if (notOk.length > 15)
console.log(` ... and ${notOk.length - 15} more`);
}
} catch (e) {
console.error(`Could not fetch logs: ${e.message}`);
}
},
tail: (id, job, opts = {}) =>
console.log(
getLogs(id, findJob(id, job).id)
.split(/\r?\n/)
2026-05-05 14:46:18 +02:00
.slice(-(parseInt(opts.lines, 10) || 100))
2026-05-05 14:31:16 +02:00
.join("\n"),
),
"wait-for": async (id, jobName, opts = {}) => {
if (!opts.keyword) {
console.error("❌ --keyword required");
process.exit(1);
}
2026-05-05 14:46:18 +02:00
const to = (parseInt(opts.timeout, 10) || TIMEOUT) * 1000,
int = (parseInt(opts.interval, 10) || 5) * 1000;
2026-05-05 14:31:16 +02:00
console.log(`🔍 Waiting for "${opts.keyword}" in "${jobName}"...\n`);
const start = Date.now();
let job = null;
while (!job && Date.now() - start < to) {
job = runView(id).jobs?.find((j) => j.name === jobName);
if (!job) {
console.log(`⏳ Waiting...`);
await sleep(int);
}
}
if (!job) {
console.error("❌ Timeout waiting for job");
process.exit(1);
}
console.log(`▶️ Job started (ID: ${job.id})`);
while (Date.now() - start < to) {
try {
const logs = getLogs(id, job.id);
if (logs.includes(opts.keyword)) {
console.log(`\n✅ Found "${opts.keyword}"!`);
const lines = logs.split(/\r?\n/),
idx = lines.findIndex((l) => l.includes(opts.keyword));
if (idx >= 0)
console.log(
"\n" + lines.slice(Math.max(0, idx - 2), idx + 3).join("\n"),
);
process.exit(0);
}
console.log(
`📝 Log: ${logs.length} chars (${Math.floor((Date.now() - start) / 1000)}s)`,
);
2026-05-05 14:46:18 +02:00
} catch (_e) {
2026-05-05 14:31:16 +02:00
/* ignore */
}
await sleep(int);
}
console.error(`❌ Timeout waiting for "${opts.keyword}"`);
process.exit(1);
},
analyze: (id, jobName) => {
const logs = getLogs(id, findJob(id, jobName).id);
const patterns = [
["Errors", /error[:]\s*(.+)/gi],
["NPM Errors", /npm ERR!\s*(.+)/gi],
["TypeScript", /error TS\d+:\s*(.+)/gi],
["Timeout", /timeout|timed?\s*out/gi],
["OOM", /out of memory|OOM|heap.*exceeded/gi],
["Network", /ECONNREFUSED|ETIMEDOUT|ENOTFOUND/gi],
["Bad Option", /bad option[:]\s*(.+)/gi],
];
console.log(`🔍 Analyzing "${jobName}"...\n`);
for (const [name, re] of patterns) {
const m = [...logs.matchAll(re)].slice(0, 5);
if (m.length) {
console.log(`${name}:`);
m.forEach((x) =>
console.log(`${(x[1] || x[0]).trim().substring(0, 80)}`),
);
}
}
},
compare: (id1, id2) => {
const j1 = new Map(
(runView(id1, "jobs").jobs || []).map((j) => [j.name, j]),
);
const j2 = new Map(
(runView(id2, "jobs").jobs || []).map((j) => [j.name, j]),
);
console.log(`\n🔍 Comparing ${id1} vs ${id2}:\n`);
for (const name of new Set([...j1.keys(), ...j2.keys()])) {
const a = j1.get(name)?.conclusion || "missing",
b = j2.get(name)?.conclusion || "missing";
console.log(
`${emoji(0, a)} ${emoji(0, b)} ${name.padEnd(25)} ${a.padEnd(10)}${b}${a !== b ? " ⚠️" : ""}`,
);
}
},
"branch-runs": (branch, opts = {}) => {
2026-05-05 14:46:18 +02:00
const list = runList({ branch, limit: parseInt(opts.limit, 10) || 10 });
2026-05-05 14:31:16 +02:00
console.log(`\n📋 Runs for "${branch}":\n`);
for (const r of list)
console.log(
`${emoji(r.status, r.conclusion)} ${String(r.databaseId).padEnd(10)} ${new Date(r.createdAt).toLocaleDateString()} ${r.displayTitle?.substring(0, 40) || ""}`,
);
},
2026-05-05 14:46:18 +02:00
"list-workflows": (_opts = {}) => {
2026-05-05 14:31:16 +02:00
const dir = path.join(".github", "workflows");
if (!fs.existsSync(dir)) {
console.error("❌ No .github/workflows directory");
process.exit(1);
}
const files = fs
.readdirSync(dir)
.filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"))
.sort();
if (!files.length) {
console.log("No workflow files found.");
return [];
}
console.log("\n📋 Workflow files:\n");
for (const f of files) {
const c = fs.readFileSync(path.join(dir, f), "utf-8");
const nm = c.match(/^name:\s*['"]?(.+?)['"]?\s*$/m)?.[1] || "(unnamed)";
const tr = [
"push",
"pull_request",
"schedule",
"workflow_dispatch",
"release",
].filter((x) => c.includes(`${x}:`));
console.log(
`📄 ${f.padEnd(30)} ${nm.padEnd(30)} ${tr.length ? `[${tr.join(", ")}]` : ""}`,
);
}
return files;
},
2026-05-05 14:46:18 +02:00
"check-actions": (wf, _opts = {}) => {
2026-05-05 14:31:16 +02:00
const fp = wf || path.join(".github", "workflows", "ci.yml");
if (!fs.existsSync(fp)) {
console.error(`❌ File not found: ${fp}`);
process.exit(1);
}
const c = fs.readFileSync(fp, "utf-8");
// Find all uses: statements
const actions = new Set();
const lines = c.split(/\r?\n/);
for (const line of lines) {
const m = line.match(/uses:\s*['"]?([^'"\s]+)['"]?/);
if (m && !m[1].startsWith("./") && !m[1].startsWith("docker://")) {
actions.add(m[1].split("@")[0]);
}
}
if (!actions.size) {
console.log("No external actions found.");
return;
}
console.log(`\n🔍 Checking ${actions.size} actions in ${fp}:\n`);
for (const a of actions) {
const [owner, repo] = a.split("/");
if (!owner || !repo) continue;
try {
const res = ghJson([
"api",
"graphql",
"-f",
`query=query { repository(owner: "${owner}", name: "${repo}") { latestRelease { tagName } } }`,
]);
const latest = res?.data?.repository?.latestRelease?.tagName;
const curMatch = c.match(
new RegExp(`${a.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}@([\\w.-]+)`),
);
const cur = curMatch?.[1] || "unknown";
if (latest) {
const ok = cur === latest || cur === latest.replace(/^v/, "");
console.log(
`${ok ? "✅" : "⚠️"} ${a.padEnd(35)} current: ${cur.padEnd(15)} latest: ${latest}`,
);
} else
console.log(
`${a.padEnd(35)} current: ${cur.padEnd(15)} (no releases)`,
);
} catch (e) {
console.log(
`${a.padEnd(35)} Error: ${e.message?.substring(0, 50) || e}`,
);
}
}
},
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
};
// CLI
2026-05-05 14:31:16 +02:00
const parseArgs = (args) => {
const r = { command: null, positional: [], options: {} };
for (let i = 0; i < args.length; i++) {
const a = args[i];
if (a.startsWith("--")) {
const k = a.slice(2);
const n = args[i + 1];
if (n && !n.startsWith("-")) {
r.options[k] = n;
i++;
} else r.options[k] = true;
} else if (a.startsWith("-")) {
const k = a.slice(1);
const n = args[i + 1];
if (n && !n.startsWith("-")) {
r.options[k] = n;
i++;
} else r.options[k] = true;
} else if (r.command === null) r.command = a;
else r.positional.push(a);
}
return r;
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
};
const HELP = `
GitHub Actions CI/CD Workflow Monitor
COMMANDS:
runs [--branch <name>] List recent runs
watch <run-id> Watch run with status changes
fail-fast <run-id> Watch run, exit 1 on first failure
list-jobs <run-id> List jobs in run
log-failed <run-id> Show logs for failed jobs
log <run-id> [--filter <regex>] Show full run logs
grep <run-id> --pattern <regex> Search logs with context
test-summary <run-id> Extract test pass/fail counts
tail <run-id> <job-name> Get last N lines of job log
wait-for <run-id> <job> --keyword Block until keyword appears
analyze <run-id> <job> Pattern analysis for failures
compare <run1> <run2> Compare job statuses between runs
branch-runs <branch> List recent runs for branch
list-workflows List all workflow files
check-actions [file] Check action versions via GraphQL
OPTIONS: --interval, --timeout, --lines, --filter, --pattern, --context, --branch, --keyword, --limit, --repo/-R
`;
const REQ = {
2026-05-05 14:31:16 +02:00
watch: ["run-id"],
"fail-fast": ["run-id"],
"list-jobs": ["run-id"],
"log-failed": ["run-id"],
log: ["run-id"],
grep: ["run-id"],
"test-summary": ["run-id"],
tail: ["run-id", "job-name"],
"wait-for": ["run-id", "job-name"],
analyze: ["run-id", "job-name"],
compare: ["run-id-1", "run-id-2"],
"branch-runs": ["branch"],
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
};
async function main() {
2026-05-05 14:31:16 +02:00
const args = process.argv.slice(2);
if (!args.length || args[0] === "help" || args[0] === "--help") {
console.log(HELP);
process.exit(0);
}
const { command, positional, options } = parseArgs(args);
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
2026-05-05 14:31:16 +02:00
if (!cmd[command]) {
console.error(`❌ Unknown command: ${command}`);
console.log(HELP);
process.exit(1);
}
const req = REQ[command] || [];
if (req.some((_, i) => !positional[i])) {
console.error(
`❌ Missing: ${req.filter((_, i) => !positional[i]).join(", ")}`,
);
process.exit(1);
}
if (command === "grep" && !options.pattern) {
console.error("❌ --pattern required");
process.exit(1);
}
if (command === "wait-for" && !options.keyword) {
console.error("❌ --keyword required");
process.exit(1);
}
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
2026-05-05 14:31:16 +02:00
try {
await cmd[command](...positional, options);
} catch (e) {
console.error(`❌ Error: ${e.message}`);
if (process.env.DEBUG) console.error(e.stack);
process.exit(1);
}
feat: add GitHub Workflows skill with CI workflow and ci_monitor tool (#294) * feat: add GitHub Workflows skill with CI workflow and ci_monitor tool - Runs on push to main and feature branches - Runs on pull requests to main - Build + test pipeline using Node 22 Cross-platform CI monitoring tool for debugging GitHub Actions: - `runs` - List recent workflow runs - `watch` - Monitor running workflow - `fail-fast` - Exit 1 on first failure (for scripts) - `log-failed` - Show failed job logs - `test-summary` - Extract test pass/fail counts - `check-actions` - GraphQL query for action versions - `grep` - Search logs with context - `wait-for` - Block until deployment keyword appears Pure Node.js - no shell interpolation, works on macOS/Windows/Linux. Drift-immune skill that: - Routes all CI operations through ci_monitor.cjs - Fetches live docs from docs.github.com (no stale training data) - Provides validation constraints (BEFORE/AFTER/EVIDENCE) - Split tests into test:unit (141 tests, ~12s) and test:integration (5 tests) - Fixed idle-recovery.test.ts for current implementation - Removed AGENTS.md dead code from resource-loader.ts - Moved npm run build out of tests (fixes ENOBUFS) When CI fails, you need observable diagnostics: - `gh run` output is not script-friendly - ci_monitor.cjs provides structured output for automation - The skill ensures AI uses the tool, not stale training data * fix: resolve imports and path for current upstream version - Updated imports from @mariozechner/pi-coding-agent to @gsd/pi-coding-agent - Fixed integration test path calculation to use process.cwd() - Kept test:unit and test:integration scripts * fix: replace search provider preference instead of accumulating AuthStorage.set() for api_key credentials appends to the existing list rather than replacing. When setSearchProviderPreference was called twice with different values, the second call appended the new value, leaving the first value at index 0, which get() returned. Fix: call auth.remove() before auth.set() to ensure only the latest preference is stored. https://claude.ai/code/session_01Qx7HRSDb117KzDZzdKk1KB * fix: address all 10 open PR review comments - package.json: run build before test:integration so a fresh checkout works - pack-install.test.ts: replace execSync+shell redirects with execFileSync argument arrays (portable, no shell parsing, paths with spaces safe) - ci_monitor.test.ts: remove unconditional passed++ after assert; move success message after the failed > 0 check so it only prints on success - setup_gh.cjs: replace unzip/tar shell-outs with platform-specific execFileSync calls (unzip on macOS, PowerShell Expand-Archive on Windows); add compareVersions() for correct element-by-element semver comparison - ci_monitor.cjs: add --repo/-R global option so repo is overrideable; fix getLogs() to use gh run view --log --job instead of binary REST endpoint https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: make all changed files fully cross-platform (Windows/macOS/Linux) - pack-install.test.ts: use tar npm package instead of tar CLI; resolve gsd binary as gsd.cmd on Windows; skip shebang check on Windows - setup_gh.cjs: use execFileSync for all binary invocations; replace which with where on Windows; add Windows PATH guidance; filter preferred install dirs by platform; unify ZIP extraction to use process.platform consistently; escape single quotes in PowerShell Expand-Archive args - ci_monitor.cjs: use path.join for .github/workflows paths; replace all split('\n') with split(/\r?\n/) to handle Windows CRLF output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: simplify and deduplicate changed files - ci_monitor.cjs: memoize getRepo() so gh repo view subprocess runs at most once per invocation instead of once per command call in watch loops - pack-install.test.ts: extract packTarball() helper to eliminate duplicate npm pack logic across two tests; remove unused contents variable https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * refactor: remove redundant existsSync before canWrite() in findInstallDir canWrite() already returns false for non-existent directories, so the pre-check was a TOCTOU-style redundancy with no behavioral value. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: replace tar npm package with Node built-ins (zlib + manual tar parsing) tar is not in the dependency tree. listTarEntries() decompresses via createGunzip() and parses the 512-byte tar block format directly, reading name/prefix/type/size fields per POSIX ustar spec. No external dependency required. Also fixes the broken tarball variable reference left over from the packTarball() refactor. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * remove: drop setup_gh scripts in favour of ci_monitor setup_gh.cjs and setup_gh.py were one-shot gh CLI installers. ci_monitor.cjs covers the day-to-day CI use case and is the tool the skill routes through. Environments that need gh installed can use brew/winget/distro packages directly. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run only unit tests in CI — integration tests cause ENOBUFS The integration tests (npm pack → npm install → spawn node) exceed the buffer limits of the CI runner environment. They are documented as requiring a manual build+run step. CI now runs test:unit only. https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: run all tests in CI without ENOBUFS - ci.yml: run unit and integration as separate steps; build is already its own step so test:integration doesn't need to rebuild - package.json: remove npm run build from test:integration script - pack-install.test.ts: npm install uses stdio:'ignore' to avoid piping large output through Node buffers (root cause of ENOBUFS); add early dist/ check with clear error message instead of rebuilding https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: resolve ENOBUFS and clean up setup_gh references - pack-install.test.ts: derive tarball filename from package.json instead of piping npm pack --json stdout; use stdio:ignore throughout to avoid exhausting OS pipe buffers on CI runners - SKILL.md: remove setup_gh install instructions; assume gh is pre-installed via system package manager; point to ci_monitor.cjs - github_project_setup.py: remove setup_gh.py reference from error message https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM * fix: address Copilot review comments on pack-install.test.ts - listTarEntries: collect chunks in array, Buffer.concat once on end instead of O(n²) repeated concat in data handler - listTarEntries: attach error handler to createReadStream so read errors reject the Promise instead of crashing the process - npm pack: use stdio:['ignore','ignore','pipe'] to preserve stderr for diagnostics while still avoiding ENOBUFS on stdout - npm install: same — pipe stderr so failures include error output https://claude.ai/code/session_01AT6CgcAB62kWcDsTJg9HZM --------- Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 00:31:17 -04:00
}
2026-05-05 14:31:16 +02:00
main();