stack-review
Stack Compliance Review
Audit code for @outfitter/* pattern compliance.
6-Step Audit Process
Step 1: Scan for Anti-Patterns
Run searches to identify issues:
# 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>notPromise<T> - Has context parameter as second argument
- Error types explicitly listed in union
- Uses
Handler<TInput, TOutput, TError>type
# 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/contractsclasses - 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
requestIdused for tracing
Quick Audit
# 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:
// 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 -
categorymatches use case -
_tagused 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, notconsole.log - Metadata is object, not string concatenation
- Sensitive fields redacted
Anti-patterns:
// 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:
// 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
-
requestIdused 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
# 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
## 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 referenceoutfitter-stack:stack-audit— Scan codebase for adoption scopeoutfitter-stack:stack-debug— Troubleshooting issues
More from outfitter-dev/agents
codebase-recon
This skill should be used when analyzing codebases, understanding architecture, or when "analyze", "investigate", "explore code", or "understand architecture" are mentioned.
92graphite-stacks
This skill should be used when the user asks to "create a stack", "submit stacked PRs", "gt submit", "gt create", "reorganize branches", "fix stack corruption", or mentions Graphite, stacked PRs, gt commands, or trunk-based development workflows.
76code-review
This skill should be used when reviewing code before commit, conducting quality gates, or when "review", "fresh eyes", "pre-commit review", or "quality gate" are mentioned.
34hono-dev
This skill should be used when building APIs with Hono, using hc client, implementing OpenAPI, or when "Hono", "RPC", or "type-safe API" are mentioned.
28software-craft
This skill should be used when making design decisions, evaluating trade-offs, assessing code quality, or when "engineering judgment" or "code quality" are mentioned.
28subagents
This skill should be used when coordinating agents, delegating tasks to specialists, or when "dispatch agents", "which agent", or "multi-agent" are mentioned.
25