Debug a Broken CI/CD Pipeline
Fix three progressive CI/CD failures using Claude Code's Plan Mode and checkpoints.
Introduction
30 Second Summary
Your CI/CD pipeline just went red. The code works fine on your machine, but the build log is full of cryptic errors and your team is blocked.
In this project, you will use Claude Code to systematically debug three independent failures in a broken TypeScript/Node.js pipeline. You will learn a repeatable debugging methodology using Plan Mode, checkpoints, and hypothesis-driven investigation.
What You'll Build
By the end, you can run the full pipeline locally, watch every stage pass green, and explain exactly what went wrong at each failure point.
By the end of this project, you'll have:
- A green CI pipeline that passes install, typecheck, test, build, and smoke-test stages for a TypeScript Express API.
- Three diagnosed and fixed failures, each requiring a different Claude Code technique: reading logs in Plan Mode, tracing silent skips through code, and using checkpoints to safely test hypotheses.
- A repeatable debugging workflow you can apply to any broken build you encounter in production.
- Secret Mission: Write a formal root-cause report documenting all three failures with symptoms, hypotheses tested, root causes, and prevention strategies.
Are there any prerequisites?
This project assumes you have Claude Code installed with a working subscription, plus Node.js, npm, Git, and VS Code on your machine. You should also be familiar with GitHub Actions workflow syntax and TypeScript basics.
Before We Start
Before we dive in, let's lock in what you're about to build and why it matters to your workflow as a developer.
Set Up the Broken Pipeline Project
Debugging a CI pipeline in a vacuum teaches nothing. You need a real codebase with real failure logs to investigate.
In this step, you'll scaffold a TypeScript/Node.js project that simulates a common nightmare: a teammate pushed code that breaks CI but passes locally. You'll confirm everything works on your machine, setting the stage for the debugging that follows.
In this step, get ready to:
- Create the project directory and scaffold the broken codebase using Claude Code.
- Install dependencies and confirm they work in your local environment.
- Run the test suite locally to prove the "works on my machine" scenario.
Create the project directory and scaffold the codebase
You'll create a project folder on your Desktop, then use Claude Code to generate all the source files, configuration, and CI log outputs.
- Open a new terminal. Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar, then type Terminal and press Enter.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir pipeline-debugger
cd pipeline-debugger
- Start Claude Code in this directory by running:
claude
Why use Claude Code for scaffolding?
Claude Code can generate entire project structures from a single prompt. Using it to scaffold the project gets you comfortable with how Claude Code creates files before you use it for the harder task of debugging.
- In Claude Code, enter the following prompt to create all the project source files:
Create a TypeScript/Node.js Express API project in this directory with these exact files:
1. package.json with name "pipeline-debugger", engines node >=20, scripts: build "tsc && tsc-alias", start "node dist/server.js", dev "tsx src/server.ts", test "vitest run", smoke:dist "node dist/server.js --check", typecheck "tsc --noEmit". Dependencies: express 5.2.1. DevDependencies: @types/express 5.0.6, @types/node 22.15.0, tsc-alias 1.9.1, tsx 4.19.4, typescript 5.8.3, vitest 4.1.10.
2. tsconfig.json targeting ES2022, module commonjs, outDir ./dist, rootDir ./src, strict true, baseUrl ".", paths @app/* mapping to ./src/*.
3. vitest.config.ts using defineConfig with globals false and resolve alias @app pointing to ./src.
4. src/config.ts exporting a config object with port (from PORT env or 3000), apiBaseUrl (from API_BASE_URL env or http://localhost:3000), environment (from NODE_ENV env or development).
5. src/utils/logger.ts exporting a logger with info, error, warn methods that log with [INFO]/[ERROR]/[WARN] prefixes and ISO timestamps.
6. src/routes/health.ts exporting healthRouter with a GET / that returns JSON with status "healthy", environment from config, and ISO timestamp.
7. src/server.ts importing express, config, healthRouter, logger. Mount healthRouter on /health. If --check flag present, log smoke test passed and exit 0. Otherwise listen on config.port.
8. tests/health.test.ts using vitest with describe.skipIf(!process.env.API_BASE_URL) wrapping 3 tests that fetch /health and check status, timestamp, and environment.
9. README.md with basic project docs.
What will Claude Code do?
Claude Code will read your prompt, plan the file structure, and create all the files. It may ask for permission to write files. Allow it to proceed.
Claude Code might produce slightly different formatting or comments. The critical parts are the file names, the dependency versions, and the describe.skipIf pattern in the test file.
- After Claude Code finishes creating the source files, enter this prompt to create the CI workflow:
Create .github/workflows/ci.yml - a GitHub Actions CI pipeline that triggers on push/PR to main. Use actions/checkout@v6 and actions/setup-node@v7 with node-version "18" and cache npm. Steps: npm ci, npm run typecheck, npm test, npm run build, npm run smoke:dist. Use ubuntu-latest. Do NOT add any env block to any step.
Why node-version 18?
This is the first bug you'll diagnose later. The workflow deliberately pins Node 18, but the project requires Node 20+. You're setting up the broken state on purpose.
- Now create the simulated CI log files by entering this prompt:
Create a ci-logs/ directory with three files:
1. run-001-node-mismatch.log - Shows setup-node@v7 installing Node 18.20.4, then npm ci with EBADENGINE warnings for pipeline-debugger (requires node >=20, current v18.20.4) and vitest@4.1.10 (requires node >=20.0.0, current v18.20.4). Packages install (added 247 packages in 8s) but typecheck fails with TS2307 Cannot find module 'express' error, exit code 2.
2. run-002-silent-test-skip.log - Shows Node 20.17.0 installed, npm ci succeeds, typecheck passes, but vitest reports 0 tests passed with 1 skipped in health.test.ts. Build succeeds, smoke test passes. Pipeline reports success despite zero assertions.
3. run-003-runtime-crash.log - Shows Node 20.17.0, npm ci succeeds, typecheck passes, vitest runs 3 passing tests, build succeeds (compiled 4 files), but smoke:dist crashes with Error: Cannot find module '@app/config' in dist/server.js with a full Node.js module resolution stack trace, exit code 1.
- Confirm the three CI log files exist by running this command in a separate terminal (not inside Claude Code):
ls ci-logs/
You should see run-001-node-mismatch.log, run-002-silent-test-skip.log, and run-003-runtime-crash.log.
Missing files or wrong structure?
If Claude Code didn't create all the expected files, ask it directly: "Can you check that ci-logs/ contains three .log files and .github/workflows/ci.yml exists?" Claude Code can fix missing files in a follow-up prompt.
If Claude Code is not responding, make sure you ran claude from inside the pipeline-debugger directory.
Help me fix my project file structure.
Install dependencies
The project has specific version pins for all dependencies. Installing them locally confirms your Node 20+ environment can handle what CI (running Node 18) could not.
- Install the project dependencies by running this in your terminal (outside Claude Code):
npm install
You should see output ending with a message like "added 247 packages" and no EBADENGINE warnings.
Why no warnings here?
Your local machine runs Node 20+, which satisfies the "engines": {"node": ">=20"} requirement in package.json. The CI workflow uses Node 18, which triggers EBADENGINE warnings. That mismatch is the first bug you'll fix.
Seeing EBADENGINE warnings?
If you see engine warnings locally, your Node version is below 20. Run node --version to check. You need v20.0.0 or higher for this project.
Help me upgrade Node.js.
Run the test suite locally
The ultimate proof that this is a "works on my machine" problem: the tests pass locally but behave differently in CI. Before you run this, what do you think will happen when you run the tests without setting an API_BASE_URL environment variable?
- Run the test suite by executing:
npm test
You'll see output showing the tests are skipped, but vitest still reports success:
✓ tests/health.test.ts (0 tests | 1 skipped) 2ms
Test Files 1 passed (1)
Tests 0 passed | 1 skipped (1)
Why do the tests skip?
The test file uses describe.skipIf(!process.env.API_BASE_URL) which skips the entire suite when API_BASE_URL is not set. Locally, this appears harmless because vitest exits with code 0.
In CI, this same skip behavior is the second bug: the pipeline reports "green" despite running zero assertions. A passing pipeline with no tests is worse than a failing one.
- Now verify the build and smoke test work locally by running:
npm run build && npm run smoke:dist
You should see [INFO] followed by "Smoke test passed: server boots successfully".
Why does this pass locally but crash in CI log 3?
The build script runs tsc && tsc-alias. The tsc-alias tool rewrites @app/ path aliases to relative paths in the compiled JavaScript. Node.js cannot resolve TypeScript path aliases at runtime without this step.
The third CI log (run-003-runtime-crash.log) represents an earlier state of the project where the build script was just tsc without tsc-alias. You'll investigate that crash in Step 4.
Build failing with module errors?
If npm run build fails, check that Claude Code created the tsconfig.json with "paths": {"@app/*": ["./src/*"]} and that tsc-alias is listed in devDependencies.
Help me debug my build configuration.
Your local environment is fully set up. Everything passes on your machine: the build compiles, aliases resolve, and the smoke test exits cleanly.
✔️ Awesome, I've got everything!
Make sure you've saved all files and that ls ci-logs/ shows all three log files.
ⓧ I'd like to double check the full code
Verify these key files match the expected content. Open each in VS Code and compare:
- package.json has "engines": {"node": ">=20"} and "build": "tsc && tsc-alias".
- tsconfig.json has "paths": {"@app/*": ["./src/*"]} under compilerOptions.
- tests/health.test.ts starts with describe.skipIf(!process.env.API_BASE_URL).
- .github/workflows/ci.yml has node-version: "18" and NO env: block on any step.
- ci-logs/ contains run-001-node-mismatch.log, run-002-silent-test-skip.log, and run-003-runtime-crash.log.
If any file is missing or incorrect, ask Claude Code to fix it by describing what needs to change.
Your broken pipeline is ready for investigation. Next up, you'll use Claude Code's Plan Mode to read the first CI log and diagnose why the install step fails in the workflow.
Explore the Repository and Diagnose Failure 1
Your tests pass locally, but the first CI run crashed during the install step. The log file shows EBADENGINE warnings. Something about the CI environment disagrees with what the project needs.
Instead of jumping straight into the workflow file and guessing, you will use Claude Code's Plan Mode to safely explore the repository. Plan Mode lets Claude read files and reason about them without making any edits. This is your first debugging technique: explore before you edit.
In this step, get ready to:
- Use Plan Mode to explore the CI workflow, package.json, and the first log file.
- Identify the root cause of the Node version mismatch.
- Apply the fix with a checkpoint so you can rewind if needed later.
Explore the repository in Plan Mode
Plan Mode tells Claude to read and analyze files without editing anything. This is perfect for the exploration phase of debugging, where you want to gather information before committing to a fix.
- Switch back to your Claude Code terminal session.
- Press Shift+Tab to cycle through modes until the status bar shows plan mode on.
What is Plan Mode?
Claude Code has three input modes you cycle through with Shift+Tab: default (reads and edits), acceptEdits (auto-accepts changes), and plan (reads only, no changes).
In Plan Mode, Claude reads files and answers questions without making changes. This is ideal for forming a hypothesis before you touch anything.
- Ask Claude to analyze the first CI failure by entering this prompt:
Read .github/workflows/ci.yml, the "engines" field in package.json, and ci-logs/run-001-node-mismatch.log. What is causing the CI failure? Form a hypothesis without making any changes.
Claude reads all three files and produces an analysis. You should see it identify the version conflict between the workflow and the project requirements.
Plan Mode not activating?
Make sure you are pressing Shift+Tab (not just Tab). The status bar at the bottom of the Claude Code interface should display the current mode. Keep pressing Shift+Tab until you see plan mode on.
help me activate Plan Mode in Claude Code
Confirm the root cause in the CI log
Claude's analysis should point to a Node version mismatch. The workflow pins Node 18 via actions/setup-node@v7, but package.json declares "engines": {"node": ">=20"} and vitest@4.1.10 also requires Node 20+. Now verify the hypothesis directly against the log.
- Search the first CI log for the engine warning by running this command in your terminal:
grep "EBADENGINE" ci-logs/run-001-node-mismatch.log
You should see multiple lines containing npm warn EBADENGINE, including the key line that says required: { node: '>=20' } and current: { node: 'v18.20.4' }. That confirms the mismatch.
Why did it still install packages?
The EBADENGINE message is a warning, not a hard failure. npm ci installed 247 packages despite the mismatch. The actual failure came later during npm run typecheck because the installed type definitions were incompatible with Node 18.
This is a classic CI trap: the real error and the root cause appear in different steps of the log.
Apply the fix with a checkpoint
You have confirmed the root cause. The fix is straightforward: change the workflow's node-version from "18" to "20". Before you make the change, you need to understand checkpoints.
What are Claude Code checkpoints?
Claude Code automatically creates a checkpoint before each prompt you send. If a fix goes wrong, you can run /rewind or press Esc twice to open the rewind menu and restore your code to a previous state.
This means the checkpoint for your fix is created automatically when you send the next prompt. You will use this rewind capability in a later step.
- Exit Plan Mode by pressing Shift+Tab until the status bar shows default mode (or no mode indicator).
- Ask Claude to apply the fix by entering this prompt:
In .github/workflows/ci.yml, change the node-version from "18" to "20" in the setup-node step.
- Claude will show you the proposed change. Accept the edit when prompted.
What just happened with checkpoints?
When you sent that prompt, Claude Code automatically created a checkpoint of your project state before processing the request. If the fix introduced a new problem, you could run /rewind to roll back to the pre-fix state.
Before you verify, what do you think the node-version line in the workflow file reads now?
- Verify the fix landed correctly by running:
grep -n "node" .github/workflows/ci.yml
You should see a line reading node-version: "20". The mismatch between the workflow and the project requirements is resolved.
Still seeing node-version 18?
If Claude's edit did not apply, open .github/workflows/ci.yml in VS Code and manually change node-version: "18" to node-version: "20" on the line inside the Setup Node.js step. Save the file and run the grep command again.
help me fix the node-version in my CI workflow
✔️ Awesome, I've got everything!
Great. Double check you have saved .github/workflows/ci.yml with the updated node-version.
ⓧ I'd like to double check the full code
Here is the complete .github/workflows/ci.yml file as it should look now:
name: CI Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: "20"
cache: npm
- name: Install dependencies
run: npm ci
- name: Typecheck
run: npm run typecheck
- name: Run tests
run: npm test
- name: Build
run: npm run build
- name: Smoke test
run: npm run smoke:dist
Failure 1 is resolved. You used Plan Mode to safely read across multiple files, formed a hypothesis, confirmed it against the log output, and applied a targeted fix. That is the explore-first methodology in action.
Next up, you will tackle a much sneakier problem. The second CI run reports a green pipeline, but something is very wrong with the test results.
Diagnose Failure 2 with Hypothesis-Driven Debugging
The first failure was loud. Error messages, non-zero exit codes, a red pipeline. This second failure is the opposite.
Look at the second CI log: every step exits with code 0. The pipeline reports Pipeline completed successfully. A green build. But buried in the output is a line that should alarm you: Tests 0 passed | 1 skipped (1). Zero test assertions ran, yet CI called it a success. "Green CI" does not always mean "correct CI."
In this step, get ready to:
- Use Plan Mode to analyze a passing-but-wrong CI log and form multiple hypotheses.
- Trace the test file's execution path to identify a conditional skip.
- Fix the workflow and verify tests actually run with assertions.
Analyze the second CI log in Plan Mode
The first step in debugging a deceptive green build is to read the logs carefully and form hypotheses before touching any code.
- Switch back to Claude Code in your terminal.
- Enter Plan Mode by pressing Shift+Tab until the status bar shows plan mode on.
- Ask Claude to read the second CI log and identify anything suspicious by typing this prompt:
Read ci-logs/run-002-silent-test-skip.log and tell me what's suspicious about this "successful" pipeline run. Don't make any changes.
What should Claude identify?
Claude should flag the test output line: ✓ tests/health.test.ts (0 tests | 1 skipped). The pipeline passed with zero test assertions executed. Every other step (typecheck, build, smoke test) completed normally.
This means something is silently skipping the test suite. The pipeline never actually verifies application behavior.
Before diving deeper, think about what could cause tests to be skipped. There are several possibilities:
- A test file pattern mismatch (vitest finds the file but collects no tests from it).
- A conditional skip based on a missing environment variable.
- A Vitest configuration issue filtering out all test cases.
You need to determine which hypothesis matches the evidence. The log shows vitest found and processed the file (it appears in output), so hypothesis 1 is unlikely.
Trace the test file to find the conditional skip
- Still in Plan Mode, ask Claude to read the test file and trace why it might skip:
Read tests/health.test.ts and explain why vitest would report "0 tests | 1 skipped" for this file. What condition controls whether the tests run?
Claude will identify the root cause in the very first line of the test's describe block.
What is the root cause?
The test file uses describe.skipIf(!process.env.API_BASE_URL) to wrap the entire test suite. When API_BASE_URL is not set, the condition !process.env.API_BASE_URL evaluates to true, and vitest silently skips every test inside the block.
Locally, your shell may have this variable set (or you never noticed because you haven't run these integration tests). In CI, the workflow has no env: block providing it to the test step. The tests skip, vitest exits 0, and CI reports success.
- Confirm the hypothesis by checking whether the workflow provides any environment variables. Ask Claude:
Read .github/workflows/ci.yml and check whether the "Run tests" step has an env block that provides API_BASE_URL.
Claude will confirm there is no env: block on the test step. Hypothesis confirmed.
Apply the fix and verify tests run with assertions
Now that you know the root cause, exit Plan Mode and apply the fix. First, create a checkpoint so you can rewind if anything goes wrong.
- Press Shift+Tab until the status bar shows the default mode (not plan).
- Ask Claude to add the API_BASE_URL environment variable to the workflow's test step:
Add an env block to the "Run tests" step in .github/workflows/ci.yml that sets API_BASE_URL to http://localhost:3000
What does this fix do?
Adding API_BASE_URL: http://localhost:3000 under an env: key on the test step means the environment variable will be present when vitest runs in CI.
The describe.skipIf(!process.env.API_BASE_URL) condition will evaluate to false, and all three tests will execute instead of being skipped.
- Verify Claude made the edit correctly. In VS Code, open .github/workflows/ci.yml and find the Run tests step. It should now look like this:
- name: Run tests
run: npm test
env:
API_BASE_URL: http://localhost:3000
Claude added the env block in the wrong place?
The env: block must be indented directly under the step (same level as run:), not under the top-level jobs: key. If Claude placed it at the wrong level, ask it to move the env block so it's a sibling of run: npm test inside the "Run tests" step.
Help me fix the YAML indentation
Now verify locally that the fix works. You need to start your server (so the health endpoint responds) and then run the tests with the environment variable set.
- Start the development server in the background by running:
npm run dev &
- Before you run the tests, predict: do you think all 3 tests will pass, or will something else go wrong?
- Run the tests with API_BASE_URL set:
API_BASE_URL=http://localhost:3000 npx vitest run
You should see output showing 3 tests passing with assertions:
✓ tests/health.test.ts (3 tests) 45ms
Test Files 1 passed (1)
Tests 3 passed (3)
- Stop the background server by running:
kill %1
Why is this different from the CI log?
Compare this output to the second CI log. The log showed 0 passed | 1 skipped. Now you see 3 passed. The only difference is the presence of the API_BASE_URL environment variable.
That single missing variable caused the entire test suite to silently skip.
Tests failing with connection refused?
If you see fetch failed or connection errors, your dev server is not running. Make sure you ran npm run dev & before executing the test command. Check that port 3000 is free by running lsof -i :3000 (macOS/Linux).
On Windows, use a separate terminal tab for the server instead of backgrounding with &. Run npm run dev in one tab, then switch to another tab and run the test command.
Help me get the server running before my tests
✔️ Awesome, I've got everything!
Great. Double check you've saved .github/workflows/ci.yml and confirm the env: block is present on the Run tests step.
ⓧ I'd like to double check the full code
The only file that changed in this step is .github/workflows/ci.yml. Confirm that the Run tests step now has exactly these lines:
- name: Run tests
run: npm test
env:
API_BASE_URL: http://localhost:3000
Everything else in the workflow file remains unchanged from the previous step.
Failure 2 is resolved. You proved that a green CI pipeline can lie to you when tests silently skip. Next up, you'll tackle the hardest failure: a build that compiles without errors but crashes at runtime.
Diagnose Failure 3 Using Checkpoints
Two failures diagnosed, two fixes applied. The third CI log presents the hardest debugging challenge yet.
In this case, the tsc build step succeeds with exit code 0, tests pass with assertions, and yet the smoke test crashes at runtime with a module resolution error. You will use Claude Code's checkpointing to safely experiment with hypotheses and /rewind to recover from dead ends.
In this step, get ready to:
- Trace how TypeScript path aliases compile to JavaScript output.
- Reproduce the runtime module resolution failure locally.
- Verify the tsc-alias fix resolves path aliases in the compiled output.
Explore the path alias compilation gap
The third CI log shows every prior step succeeding. Tests pass, tsc compiles without errors, but then the smoke test explodes.
- Switch back to Claude Code in your terminal.
- Activate Plan Mode by pressing Shift+Tab until the status bar shows plan mode on.
- Ask Claude to read the third CI log, the tsconfig.json paths configuration, and the compiled output structure, then form a hypothesis about why the smoke test crashes:
Read ci-logs/run-003-runtime-crash.log, then read tsconfig.json focusing on the paths
field, then check what files exist in dist/ after a build. Form a hypothesis about why
the smoke test crashes with "Cannot find module '@app/config'" even though tsc exits 0.
What is Plan Mode doing here?
In Plan Mode, Claude reads files and analyzes relationships without making any edits. This is critical for the exploration phase of debugging. You form a theory before touching anything.
Claude should identify that tsconfig.json declares @app/* as a path alias pointing to ./src/*. TypeScript uses this for type resolution during compilation, but does NOT rewrite the imports in the emitted JavaScript.
Claude's analysis should confirm the root cause: tsc leaves require("@app/config") in the compiled .js files, and Node.js cannot resolve that alias at runtime.
Reproduce the failure locally
Seeing the error yourself is more convincing than reading a log. You can reproduce the CI failure locally by compiling with only tsc (skipping the alias rewriting step) and running the output.
- Exit Plan Mode by pressing Shift+Tab until the status bar no longer shows plan mode.
- Compile the project with only tsc (no alias rewriting) by running:
npx tsc
- Inspect the compiled output to see the preserved alias by running:
grep -n "@app" dist/server.js
You should see lines like require("@app/config") still present in the compiled JavaScript. Node.js has no idea what @app means.
Before you run the smoke test, predict what will happen. Will node dist/server.js --check succeed or crash?
- Run the smoke test against the tsc-only output:
node dist/server.js --check
You see the same crash from the CI log: Error: Cannot find module '@app/config'. You have reproduced the third failure locally.
Why does tsc not rewrite path aliases?
TypeScript's paths field in tsconfig.json exists for type resolution only. It tells the compiler where to find type declarations during compilation. The emitted JavaScript retains the alias strings literally.
This is a well-known gap. Tools like tsc-alias exist specifically to rewrite path aliases in the compiled output as a post-compilation step.
Not seeing the error?
If node dist/server.js --check succeeded instead of crashing, you may have run npm run build (which includes tsc-alias) instead of just npx tsc. Delete the dist/ folder and recompile with npx tsc only.
Help me reproduce the @app/config failure
Verify the tsc-alias fix with a checkpoint
Now that you have seen the failure firsthand, you need a post-compilation tool that rewrites @app/* imports to relative paths in the dist/ output.
- Create a checkpoint before verifying the fix by prompting Claude Code:
Look at the build script in package.json. It should chain tsc with tsc-alias as a
post-compilation step to rewrite path aliases. Verify that tsc-alias is installed as
a dev dependency. If anything is missing, propose a fix.
Why create a checkpoint here?
Claude Code automatically creates a checkpoint before each prompt. If Claude's proposed fix breaks something, you can press Esc twice or type /rewind to open the rewind menu and restore your code to this point.
This is the safe experimentation loop: checkpoint, try a hypothesis, verify, and rewind if it fails.
Claude should confirm that package.json already has "build": "tsc && tsc-alias" and tsc-alias at version 1.9.1 in devDependencies. The fix is already wired up.
- Now run the full build script (which includes the alias rewriting) by running:
npm run build
- Verify that the aliases are now rewritten by running:
grep -n "@app" dist/server.js
This time, no matches appear. The @app/config imports have been replaced with relative paths like ./config.
Before you run the smoke test again, predict the outcome. Will it crash or succeed now that aliases are rewritten?
- Run the build and smoke test together to verify the full pipeline works:
npm run build && node dist/server.js --check
You see the success message: [INFO] followed by Smoke test passed: server boots successfully. The third failure is resolved.
Still seeing the module error?
Make sure tsc-alias is installed. Run npm ls tsc-alias to confirm it appears in your node_modules. If it is missing, run npm install to install all dependencies from package.json.
Also confirm the build script in package.json reads "tsc && tsc-alias" with the && chaining both commands.
Help me debug the tsc-alias path rewriting
All three CI failures are now diagnosed and resolved. You used Plan Mode to explore safely, checkpoints to experiment without fear, and /rewind as your safety net for failed hypotheses. Next up, you will document this entire debugging journey in a formal root-cause report.
Secret mission
Write a Root-Cause Report
You fixed the pipeline. Now document what broke, why, and how to prevent it from happening again. This is the skill that separates a senior engineer from someone who just applies patches.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally, so there are no ongoing costs. Decide whether to keep your project files as a reference or delete them entirely.
Resources you used:
- The pipeline-debugger project directory on your Desktop (source files, CI logs, compiled output, and node_modules).
- The ROOT_CAUSE_REPORT.md file inside the project directory.
- Claude Code checkpoints created during your debugging sessions.
Keep everything running
No action needed. Choose this if you want to keep the project as a reference for your debugging methodology or plan to push it to GitHub for live CI practice.
- Your pipeline-debugger folder stays on your Desktop with all files intact.
- Your Claude Code checkpoints remain available for review.
- The ROOT_CAUSE_REPORT.md serves as a template for future debugging sessions.
Pause - I'll come back to this later
Shut down any running processes to free up memory. Your files stay on disk for when you return.
- If the dev server is running, press Ctrl+C in the terminal to stop it.
- Close Claude Code by typing /exit in the Claude Code session.
- Your project files and checkpoints remain on disk. Reopen the folder in VS Code when you return.
Delete - I don't want to use this again
Remove all project files and start fresh. This deletes the source code, CI logs, node_modules, and your root-cause report.
- If the dev server is running, press Ctrl+C to stop it.
- Close Claude Code by typing /exit in the Claude Code session.
- Remove the project directory by running this command:
macOS
cd ~/Desktop
rm -rf pipeline-debugger
Windows
cd ~\Desktop
Remove-Item -Recurse -Force pipeline-debugger
- Confirm the folder is gone by running ls (macOS) or dir (Windows) on your Desktop. You should no longer see pipeline-debugger listed.
Nice Work!
Nice Work!
You just rescued a broken CI/CD pipeline by systematically diagnosing three independent failures using Claude Code.
You've learned how to:
- Diagnosed three CI failures using Claude Code's Plan Mode to explore logs, cross-reference config files, and form hypotheses before making any changes.
- Proved that a green pipeline does not mean a correct pipeline by uncovering a silent test skip from a missing environment variable and a runtime crash that passed the build step.
- Used Claude Code checkpoints to safely experiment with fixes and /rewind to recover from failed hypotheses.
- Secret Mission: Produced a structured root-cause report documenting all three failures with symptoms, hypotheses, root causes, fixes, and prevention strategies.
Ready to quiz yourself?