| 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:
rg "throw new" --type ts
rg "try \{" --type ts
rg "console\.(log|error|warn)" --type ts
rg "(homedir|~\/\.)" --type ts
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
rg "Handler<" --type ts -A 2
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
rg "throw new|catch \(" --type ts -c
rg "console\.(log|error|warn)" --type ts -c
rg "Handler<" --type ts -A 2
Checklist
Result Types
Anti-patterns:
if (!user) throw new Error("Not found");
if (!user) return Result.err(new NotFoundError("user", id));
try { await handler(input, ctx); } catch (e) { ... }
const result = await handler(input, ctx);
if (result.isErr()) { ... }
Error Taxonomy
| 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
Anti-patterns:
console.log("User " + user.name);
logger.info("Config: " + JSON.stringify(config));
ctx.logger.info("Processing", { userId: user.id });
ctx.logger.debug("Config loaded", { config });
Path Safety
Anti-patterns:
const configPath = path.join(os.homedir(), ".myapp", "config.json");
const userFile = path.join(baseDir, userInput);
const configDir = getConfigDir("myapp");
const result = securePath(userInput, workspaceRoot);
await atomicWriteJson(configPath, data);
Context Propagation
Validation
Output
Audit Commands
rg "throw new" --type ts
rg "console\.(log|error|warn)" --type ts
rg "(homedir|~\/\.)" --type ts
rg "class \w+Error extends Error" --type ts
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
## 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