code-verifier

Use when running a full quality gate after implementation — lint, type-check, tests, and import validation. Mandatory step in job-orchestrator after task-implementer and after fix iterations. Use standalone when you need a structured verification report.

Code Verifier

Purpose

Runs the full quality gate for a project: lint, type-check, tests, and import validation. Provides a structured, parseable result that the orchestrator uses to decide whether to proceed or trigger a fix loop.

Distinct from task-implementer Phase 5: task-implementer does inline self-verification during implementation. code-verifier is an independent gate that runs after all tasks in a wave are complete — giving a clean, consolidated view of the whole diff, not per-task.

Input: Codebase path + worktree path + scope (changed files or full project) Output: VERIFICATION_RESULT structured report — gate status (pass/fail), per-check results, actionable findings

When to Use

  • Dispatched by job-orchestrator after each task-implementer wave (mandatory)
  • Dispatched by job-orchestrator after each fix iteration
  • Run standalone: "verify my code", "run quality gate", "/code-verifier"
  • Any time you need a reproducible, structured view of project health

Architecture: 4 Phases

Phase 1: DETECT   →  Auto-detect stack, tooling, commands
Phase 2: RUN      →  Execute lint → type-check → tests → import-check
Phase 3: ANALYZE  →  Parse outputs, classify findings by severity
Phase 4: REPORT   →  Emit VERIFICATION_RESULT

Workflow

Code Verifier Progress:
- [ ] Phase 1: Detect stack and tooling
- [ ] Phase 2: Run verification checks
- [ ] Phase 3: Analyze and classify findings
- [ ] Phase 4: Report results

Phase 1: DETECT

Auto-detect the project stack and available verification tools.

1.1 Package manager and runner:

cd <codebase_path>

if   [ -f bun.lockb ];         then PM=bun;    RUNNER="bun run"
elif [ -f pnpm-lock.yaml ];    then PM=pnpm;   RUNNER="pnpm run"
elif [ -f yarn.lock ];         then PM=yarn;   RUNNER="yarn"
elif [ -f package-lock.json ]; then PM=npm;    RUNNER="npm run"
elif [ -f pyproject.toml ] || [ -f requirements.txt ]; then PM=python; RUNNER=""
elif [ -f go.mod ];            then PM=go;     RUNNER=""
else PM=unknown; RUNNER=""
fi

1.2 Detect available check commands:

CheckHow to detectCommand
Lintpackage.json has "lint" script$RUNNER lint
Lint (auto)eslint.config.* or .eslintrc* presentnpx eslint . --max-warnings 0
Biomebiome.json presentnpx biome check .
Type-checkpackage.json has "type-check" or "typecheck" script$RUNNER type-check
Type-check (auto)tsconfig.json presentnpx tsc --noEmit
Testspackage.json has "test" script$RUNNER test --run (vitest) or $RUNNER test
pytestpytest in pyproject.toml or requirements.txtpytest --tb=short -q
Go testsgo.mod presentgo test ./...
Circular importsmadge in devDependenciesnpx madge --circular src/

1.3 Determine scope:

IF scope = "changed" (default when dispatched by orchestrator):
  FILES = git diff --name-only <base_branch>...HEAD
  Run tests only for files related to changed code
  Run lint only on changed files: npx eslint <changed_files>
  Run type-check on full project (tsc doesn't support file-level scope)

IF scope = "full":
  Run all checks on full project

Output of Phase 1:

TOOLING:
  pm: bun | pnpm | yarn | npm | python | go | unknown
  runner: "bun run" | ...
  checks_available: [lint, type-check, tests, circular-imports]
  checks_skipped: [<reason>]
  scope: changed | full
  changed_files: [<paths>]

Phase 2: RUN

Execute each available check in order. Capture full output.

Execution order: lint → type-check → tests → import-check

Do NOT abort early — run all checks even if one fails. The orchestrator needs the complete picture.

2.1 Lint:

# Changed files only (faster, more actionable)
npx eslint <changed_files> --format=json --max-warnings 0
# OR if lint script exists:
$RUNNER lint

Capture:

  • Exit code (0 = pass, non-zero = fail)
  • Number of errors and warnings
  • Per-file error list (file path, line, column, rule, message)

2.2 Type-check:

npx tsc --noEmit 2>&1
# OR:
$RUNNER type-check

Capture:

  • Exit code
  • Number of errors
  • Per-error: file, line, column, message, TS error code

2.3 Tests:

$RUNNER test --run 2>&1        # vitest
# OR: npx jest --ci 2>&1
# OR: pytest --tb=short -q 2>&1
# OR: go test ./... 2>&1

Capture:

  • Exit code
  • Tests passed / failed / skipped counts
  • Per-failure: test name, file, error message, stack (first 5 lines)

2.4 Circular import check (if madge available):

npx madge --circular --extensions ts,tsx src/ 2>&1

Capture:

  • Exit code
  • List of circular chains (if any)

Phase 3: ANALYZE

Parse raw outputs into structured findings. Classify by severity.

3.1 Severity classification:

FindingSeverity
Type errorCRITICAL
Test failureCRITICAL
ESLint error (not warning)HIGH
Circular importHIGH
ESLint warningLOW
Skipped testINFO

3.2 Gate decision:

GATE = PASS
IF any CRITICAL findings  → GATE = FAIL (blocks proceed)
IF any HIGH findings      → GATE = FAIL (blocks proceed)
IF only LOW/INFO findings → GATE = PASS_WITH_WARNINGS

3.3 Actionable finding format:

Each finding must include enough context for task-implementer (fix mode) to resolve it without re-reading the full output:

{
  severity: CRITICAL | HIGH | LOW | INFO,
  check: lint | type-check | test | circular-import,
  file: <path>,
  line: <N> | null,
  column: <N> | null,
  rule: <ESLint rule or TS error code> | null,
  message: <error text>,
  suggestion: <optional fix hint>
}

Phase 4: REPORT

Emit the structured VERIFICATION_RESULT as the final message.

VERIFICATION_RESULT:
  gate: PASS | PASS_WITH_WARNINGS | FAIL
  scope: changed | full
  
  checks:
    lint:
      status: pass | fail | skipped
      errors: <N>
      warnings: <N>
      command_used: "<command>"
    
    type_check:
      status: pass | fail | skipped
      errors: <N>
      command_used: "<command>"
    
    tests:
      status: pass | fail | skipped
      passed: <N>
      failed: <N>
      skipped: <N>
      command_used: "<command>"
    
    circular_imports:
      status: pass | fail | skipped
      cycles: <N>
  
  findings:
    - severity: CRITICAL
      check: type-check
      file: src/services/UserService.ts
      line: 42
      rule: TS2345
      message: "Argument of type 'string' is not assignable to parameter of type 'number'"
    - severity: HIGH
      check: lint
      file: src/components/Form.tsx
      line: 18
      rule: "no-unused-vars"
      message: "'value' is defined but never used"
  
  summary: "<1-2 sentence human-readable summary>"

STATUS reporting:

STATUS: DONE          — gate PASS or PASS_WITH_WARNINGS, report follows
STATUS: DONE_WITH_CONCERNS — PASS_WITH_WARNINGS with notable warnings
STATUS: BLOCKED       — could not run checks (missing tooling, wrong directory)

If gate: FAIL → STATUS is still DONE (the gate result, not the skill's execution). The orchestrator reads gate: FAIL and decides to trigger fix.


Integration with job-orchestrator

The orchestrator dispatches code-verifier at two points:

After task-implementer wave (pre-review gate):

code-verifier:
  codebase_path: <worktree_path>
  scope: changed
  base_branch: <base_branch from JOB_STATE>
→ If gate: FAIL → dispatch fix tasks → re-run code-verifier
→ If gate: PASS → proceed to review

After fix iterations (post-fix gate):

code-verifier:
  codebase_path: <worktree_path>
  scope: changed
→ If gate still FAIL after 2 iterations → report as BLOCKED, skip to report
→ If gate: PASS → proceed to report

The orchestrator's internal "checks" step (2.8) is replaced by code-verifier dispatch.


Standalone Usage

# Run on current directory, changed files only
/code-verifier

# Run on specific project
/code-verifier --path /path/to/project

# Full project scan (not just changed files)
/code-verifier --scope full

Automation Settings

SettingDefaultOptionsDescription
scopechangedchanged / fullLimit checks to changed files or run full project
fail_on_warningsfalsetrue/falseTreat ESLint warnings as gate failures
include_circulartruetrue/falseRun circular import detection if madge available
max_findings_reported201-100Cap findings in report to avoid overflow

Error Handling

ErrorAction
Check command not foundMark check as skipped, continue others
Wrong working directoryABORT with STATUS: BLOCKED and directory hint
Command times out (>120s)Mark check as skipped (timeout), continue
Zero checks availableSTATUS: BLOCKED — cannot verify without any tooling
Circular import tool missingSkip silently (not installed in all projects)

Rules of Engagement

  1. Run ALL checks — never abort after first failure. The orchestrator needs the full picture.
  2. Do NOT modify files — this is read-only verification.
  3. Scope to changed files by default — full scans are slow and produce noise.
  4. Be specific in findings — include file, line, rule, message. Vague "lint failed" is not actionable.
  5. Return VERIFICATION_RESULT as the final message to the orchestrator.