Claude
Skills
Sign in
Back

running-check-script

Included with Lifetime
$97 forever

Single source of truth for running the package.json `check` script across lt-dev review and rebase workflows. Defines discovery (multi-package monorepo aware), the iterate-until-green auto-fix loop, the mandatory audit-finding fix escalation ladder, residual classification (Accepted vs Critical), test-duplication avoidance, and report formatting. Activates whenever an agent or command needs to validate runnability via `check` — currently used by `/lt-dev:review`, `code-reviewer`, `branch-rebaser`, and `test-reviewer`. NOT for general npm package maintenance (use maintaining-npm-packages). NOT for the rebase orchestration itself (use rebasing-branches).

AI Agents

What this skill does


# Running the `check` Script

This skill is the **single source of truth** for executing the `package.json` `check` script in lt-dev workflows. Every reviewer, rebaser, and orchestrator that needs to guarantee project runnability must follow this procedure verbatim — duplicating the rules across agents leads to drift.

> **Goal:** A truly green `check` run (exit 0) is a non-negotiable prerequisite for any review or rebase to be considered complete. The only acceptable residual is an upstream dependency vulnerability where the full fix escalation ladder has been exhausted.

## When to Use This Skill

| Caller | Phase | Trigger |
|--------|-------|---------|
| `/lt-dev:review` | Phase 1.5 | Before spawning any specialized reviewer |
| `lt-dev:code-reviewer` | Phase 1.5 | Before single-pass review (skip if orchestrator already ran it) |
| `lt-dev:branch-rebaser` | Phase 6.5 | After lint/format, before tests |
| `lt-dev:test-reviewer` | (input briefing) | Honors the skip semantics defined here |

## Procedure

### Step 1 — Discover `check` scripts

Use the dedicated helper script (located in the lt-dev plugin):

```bash
bash "${CLAUDE_PLUGIN_ROOT}/scripts/discover-check-scripts.sh" "$(pwd)"
```

Output is TSV, one project per line:

```
<package.json path>\t<check script>\t<includes_tests:yes|no>\t<package manager>
```

The helper:
- Uses `git ls-files "package.json" "**/package.json"` so it respects `.gitignore` and skips `node_modules`
- Parses JSON via `jq` → `node -e` → `grep+sed` fallback chain (works even without `jq` installed)
- Resolves single-level composite scripts (`"check": "pnpm run ci"` → looks up `ci`)
- Detects whether `check` transitively invokes a test runner (`test`, `vitest`, `jest`, `playwright`)
- Detects the package manager per project via lockfile (`pnpm-lock.yaml` → `pnpm`, etc.; default `pnpm`)

If the helper returns nothing → no project defines `check` → skip the rest of this skill.

### Step 2 — Run `check` per project

For each discovered project, `cd` into its directory and run the `check` script with the detected package manager:

```bash
cd "$(dirname <package.json path>)"
<package manager> run check
```

Capture stdout, stderr, and exit code. Track an iteration counter starting at 1.

### Step 3 — Auto-fix loop (iterate until truly green)

If a project's `check` exits non-zero:

1. **Parse all errors** from the current run (typecheck, lint, build, missing imports, type mismatches, unused symbols, audit findings, etc.)
2. **Fix each error at the root cause** via `Read` + `Edit`. Includes pre-existing errors unrelated to the diff — runnability overrides scope boundaries.
3. **Re-run `check` from scratch.** Never trust partial state.
4. **Continue iterating** until one of these terminal conditions:
   - **(a) GREEN** — `check` exits 0 → done for this project
   - **(b) STALLED** — a full iteration produced no net reduction in error count → stop and classify residuals
5. **No hard iteration cap.** As long as each iteration strictly reduces the error count, keep going. The goal is true green.

### Step 4 — Audit findings: mandatory fix escalation ladder

When `pnpm audit` / `npm audit` / `yarn audit` (invoked by `check`) reports a vulnerability, you MUST exhaust this ladder **before** classifying the finding as Accepted. Re-run `check` after every step.

| # | Step | Command (pnpm / npm / yarn) |
|---|------|------------------------------|
| 1 | Update to latest compatible | `pnpm update <pkg>` / `npm update <pkg>` / `yarn upgrade <pkg>` |
| 2 | Automatic remediation | `pnpm audit --fix` / `npm audit fix` / `yarn audit --fix` |
| 3 | Force semver-major upgrade | `pnpm audit --fix --force` / `npm audit fix --force` |
| 4 | Bump direct dep to next major if advisory lists fix there | `pnpm add <pkg>@<major>` / `npm install <pkg>@<major>` / `yarn add <pkg>@<major>` |
| 5 | Force a transitive dep version | `pnpm.overrides` / `resolutions` (yarn) / `overrides` (npm) block in `package.json`, then re-install |
| 6 | Replace the package | Switch to a maintained alternative if abandoned |

A finding may only be classified as Accepted after **every** applicable step has been tried and verified, with documented evidence that no patched version exists anywhere in the ecosystem.

### Step 5 — Residual classification

Only after a project has STALLED (and, for audit findings, only after the escalation ladder is exhausted):

| Residual type | Treatment |
|---------------|-----------|
| Vulnerable dependency where the full ladder has been tried and no patched version exists (verified via registry, advisory database, upstream repo) | **Accepted Residual** — document with package name, advisory ID, ladder steps tried, why each failed, evidence of unfixability. NOT a blocker. |
| Vulnerable dependency where the ladder has NOT been fully tried | **Critical blocker** — the loop is not allowed to terminate until the ladder is exhausted. |
| Any other residual (typecheck, lint, build, test, import, etc.) | **Critical blocker** — add to Remediation Catalog with Critical priority. |

### Step 6 — Bypass policy (hard rules)

Never use any of the following to silence errors:

- `git commit --no-verify`
- `@ts-ignore`, `@ts-expect-error`, `@ts-nocheck`
- `eslint-disable`, `eslint-disable-next-line`, `eslint-disable-line`
- `/* istanbul ignore */`
- Lint rule downgrades in config files
- Commenting out broken code
- Deleting failing tests
- `it.skip(...)`, `describe.skip(...)`, `test.skip(...)` in test files
- `--passWithNoTests` flags on the test command
- Adding `oxlint-disable` directives to suppress real findings

The ONLY permitted "non-fix" is an upstream dependency vulnerability where the escalation ladder has been fully exhausted. Everything else must be fixed at the root.

### Step 6.5 — `check-server-start.sh` failure modes (Nitro/Nest port hazards)

The starter `check` pipeline ends with `bash scripts/check-server-start.sh`, which boots the production build and waits for the readiness log. Three known failure modes — all surface as the same symptom (`ERR_SOCKET_BAD_PORT` from `node:net`) but have different root causes:

1. **Nitro `PORT`-string bug** (App side): the script must use `NITRO_PORT=$FREE_PORT`, never `PORT=$FREE_PORT`. Some Nitro versions read `process.env.PORT` without `parseInt` and crash; `NITRO_PORT` is the documented Nitro-specific knob, goes through Nitro's own env loader, and is coerced to number reliably. Nest does not have this issue — `NSC__PORT` is fine on the API side.

2. **lerna/nx ANSI-injection** (BOTH api and app, only when `check` is invoked from a workspace runner): the runner wraps subprocess stdout and may inject ANSI color escape sequences (`\x1b[33m...\x1b[39m`) into command output. A naive `FREE_PORT=$(node -e "...console.log(p)")` captures the codes too. **A naive `tr -cd '0-9'` makes it worse** — the codes contain digits (33, 39) themselves, producing nonsense ports like 335454639. The only correct fix is to strip the ANSI sequence pattern explicitly with `sed`:
   ```bash
   FREE_PORT=$(node -e "..." | sed $'s/\x1b\\[[0-9;]*m//g' | tr -d '[:space:]')
   ```

3. **Phantom Unix-domain-sockets** named `[33m12345[39m` next to the package.json (mode `srwx`): leftover from earlier failed runs. When Nest's port-parser fell through "string with weird chars" → "treat as Unix socket path", it actually bound a socket file. `cleanup()` SIGTERM kills the process, the file stays. Delete with:
   ```bash
   rm -f $'\x1b[33m'*$'\x1b[39m'
   ```
   Then re-run `check`.

These hazards are documented in detail in the `modernizing-toolchain` skill (Phase 6). When a `check` run fails with `ERR_SOCKET_BAD_PORT`, the first triage step is to confirm the script in question already has both the `NITRO_PORT` and ANSI-strip fixes applied.

### Step 7 — Test-duplication avoidance

Tests must not run twice if `check` already covered them on an unchanged working tree.

After each project completes Step 3 with a GREEN result, record a

Related in AI Agents