home / skills / outfitter-dev / agents / stack-review

This skill audits Outfitter Stack compliance in TypeScript code, enforcing Result patterns, error handling, and safe logging for robust pre-commit reviews.

npx playbooks add skill outfitter-dev/agents --skill stack-review

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
5.6 KB
---
name: stack-review
version: 0.1.0
description: Audits code for Outfitter Stack compliance including Result types, error handling, logging patterns, and path safety. Use for pre-commit reviews, code quality checks, migration validation, or when "audit", "check compliance", "review stack", or "stack patterns" are mentioned.
context: fork
agent: stacker
allowed-tools: Read Grep Glob Bash(rg *)
---

# Stack Compliance Review

Audit code for @outfitter/* pattern compliance.

## 6-Step Audit Process

### Step 1: Scan for Anti-Patterns

Run searches to identify issues:

```bash
# Thrown exceptions (Critical)
rg "throw new" --type ts

# try/catch control flow (Critical)
rg "try \{" --type ts

# Console usage (High)
rg "console\.(log|error|warn)" --type ts

# Hardcoded paths (High)
rg "(homedir|~\/\.)" --type ts

# Custom error classes (Medium)
rg "class \w+Error extends Error" --type ts
```

### Step 2: Review Handler Signatures

Check each handler for:

- Returns `Result<T, E>` not `Promise<T>`
- Has context parameter as second argument
- Error types explicitly listed in union
- Uses `Handler<TInput, TOutput, TError>` type

```bash
# Find handlers
rg "Handler<" --type ts -A 2

# Find missing context
rg "Handler<.*> = async \(input\)" --type ts
```

### Step 3: Check Error Usage

Verify errors:

- Use `@outfitter/contracts` classes
- Have correct category for use case
- Include appropriate details
- Are returned via `Result.err()`, not thrown

### Step 4: Validate Logging

Check logging:

- Uses `ctx.logger`, not console
- Metadata is object, not string concatenation
- Sensitive fields would be redacted
- Child loggers used for request context

### Step 5: Check Path Safety

Verify paths:

- User paths validated with `securePath()`
- XDG helpers used (`getConfigDir`, etc.)
- Atomic writes for file modifications
- No hardcoded home paths

### Step 6: Review Context

Check context:

- `createContext()` at entry points
- Context passed through handler chain
- `requestId` used for tracing

## Quick Audit

```bash
# Critical issues (count)
rg "throw new|catch \(" --type ts -c

# Console usage (count)
rg "console\.(log|error|warn)" --type ts -c

# Handler patterns
rg "Handler<" --type ts -A 2
```

## Checklist

### Result Types

- [ ] Handlers return `Result<T, E>`, not thrown exceptions
- [ ] Errors use taxonomy classes (`ValidationError`, `NotFoundError`, etc.)
- [ ] Result checks use `isOk()` / `isErr()`, not try/catch
- [ ] Combined results use `combine2`, `combine3`, etc.

**Anti-patterns:**

```typescript
// BAD: Throwing
if (!user) throw new Error("Not found");

// GOOD: Result.err
if (!user) return Result.err(new NotFoundError("user", id));

// BAD: try/catch for control flow
try { await handler(input, ctx); } catch (e) { ... }

// GOOD: Result checking
const result = await handler(input, ctx);
if (result.isErr()) { ... }
```

### Error Taxonomy

- [ ] Errors from `@outfitter/contracts`
- [ ] `category` matches use case
- [ ] `_tag` used for pattern matching

| Category | Use For |
|----------|---------|
| `validation` | Invalid input, schema failures |
| `not_found` | Resource doesn't exist |
| `conflict` | Already exists, version mismatch |
| `permission` | Forbidden action |
| `internal` | Unexpected errors, bugs |

### Logging

- [ ] Uses `ctx.logger`, not `console.log`
- [ ] Metadata is object, not string concatenation
- [ ] Sensitive fields redacted

**Anti-patterns:**

```typescript
// BAD
console.log("User " + user.name);
logger.info("Config: " + JSON.stringify(config));

// GOOD
ctx.logger.info("Processing", { userId: user.id });
ctx.logger.debug("Config loaded", { config });  // redaction enabled
```

### Path Safety

- [ ] User paths validated with `securePath()`
- [ ] No hardcoded `~/.` paths
- [ ] XDG paths via `@outfitter/config`
- [ ] Atomic writes for file modifications

**Anti-patterns:**

```typescript
// BAD
const configPath = path.join(os.homedir(), ".myapp", "config.json");
const userFile = path.join(baseDir, userInput);  // traversal risk!

// GOOD
const configDir = getConfigDir("myapp");
const result = securePath(userInput, workspaceRoot);
await atomicWriteJson(configPath, data);
```

### Context Propagation

- [ ] `createContext()` at entry points
- [ ] Context passed through handler chain
- [ ] `requestId` used for tracing

### Validation

- [ ] Uses `createValidator()` with Zod
- [ ] Validation at handler entry
- [ ] Validation errors returned, not thrown

### Output

- [ ] CLI uses `await output()` with mode detection
- [ ] `exitWithError()` for error exits
- [ ] Exit codes from error categories

## Audit Commands

```bash
# Find thrown exceptions
rg "throw new" --type ts

# Find console usage
rg "console\.(log|error|warn)" --type ts

# Find hardcoded paths
rg "(homedir|~\/\.)" --type ts

# Find custom errors
rg "class \w+Error extends Error" --type ts

# Find handlers without context
rg "Handler<.*> = async \(input\)" --type ts
```

## Severity Levels

| Level | Examples |
|-------|----------|
| **Critical** | Thrown exceptions, unvalidated paths, missing error handling |
| **High** | Console logging, hardcoded paths, missing context |
| **Medium** | Missing type annotations, non-atomic writes |
| **Low** | Style issues, missing documentation |

## Report Format

```markdown
## Stack Compliance: [file/module]

**Status**: PASS | WARNINGS | FAIL
**Issues**: X critical, Y high, Z medium

### Critical
1. [file:line] Issue description

### High
1. [file:line] Issue description

### Recommendations
- Recommendation with fix
```

## Related Skills

- `outfitter-stack:stack-patterns` — Correct patterns reference
- `outfitter-stack:stack-audit` — Scan codebase for adoption scope
- `outfitter-stack:stack-debug` — Troubleshooting issues

Overview

This skill audits TypeScript code for Outfitter Stack compliance, focusing on Result types, error taxonomy, logging practices, path safety, and context propagation. It produces actionable findings and a severity-scored report suitable for pre-commit checks, migrations, or code reviews. Use it to ensure handlers follow Result-based flows and platform logging/path conventions.

How this skill works

The skill scans code for anti-patterns (throws, try/catch control flow, console usage, hardcoded paths, custom error classes) and inspects handler signatures, error construction, logging calls, path handling, and context propagation. It applies checklist rules (Result<T,E> returns, @outfitter error types, ctx.logger usage, securePath/XDG helpers, createContext usage) and emits categorized issues with recommendations. Quick counts and command snippets are provided for local verification and automation.

When to use it

  • Pre-commit or CI quality checks for TypeScript repos
  • Before or during migrations to Outfitter Stack conventions
  • Code reviews mentioning "audit", "check compliance", "review stack", or "stack patterns"
  • Validating handlers, error handling, or logging changes
  • Assessing path safety for file I/O and config handling

Best practices

  • Return Result<T, E> from handlers; avoid throwing for control flow
  • Use @outfitter/contracts error classes with correct category and _tag
  • Always use ctx.logger with structured metadata; redact sensitive fields
  • Validate user paths with securePath() and use XDG helpers for config dirs
  • Create and pass createContext() at entry points; include requestId for tracing
  • Prefer atomic writes for file modifications and combineN utilities for multi-result aggregation

Example use cases

  • Pre-commit hook that flags throws, console.* usage, and hardcoded home paths
  • Migration audit to convert handlers from Promise/throw semantics to Result-based returns
  • CI job that counts critical anti-patterns and fails the build on high-severity findings
  • Reviewer checklist for PRs touching error construction, logging, or filesystem operations
  • Manual audit before releasing code that touches user data paths or application config

FAQ

What counts as a critical issue?

Critical issues include thrown exceptions used for control flow, unvalidated user paths, and missing error handling that can cause uncaught failures.

How do I fix a thrown exception found by the audit?

Replace throw with Result.err(new AppropriateError(...)) and ensure callers check result.isErr() instead of using try/catch for control flow.