@lvlup-sw/axiom 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: distill
3
+ description: "Strip backend code to its essence by identifying dead code, vestigial patterns, and unnecessary complexity. Use when cleaning up after refactoring or reducing cognitive load. Triggers: 'simplify code', 'find dead code', 'clean up', or /axiom:distill. Do NOT use for error handling — use axiom:harden instead."
4
+ user-invokable: true
5
+ metadata:
6
+ author: lvlup-sw
7
+ version: 0.1.0
8
+ category: assessment
9
+ dimensions:
10
+ - hygiene
11
+ - topology
12
+ ---
13
+
14
+ # Distill Skill
15
+
16
+ ## Overview
17
+
18
+ Simplification skill for the axiom backend quality plugin. Covers DIM-5 (Hygiene) and DIM-1 (Topology) dimensions to strip code down to its essential form by identifying dead code, vestigial patterns, and unnecessary complexity.
19
+
20
+ ## Triggers
21
+
22
+ Activate this skill when:
23
+ - User says "simplify code", "find dead code", "clean up"
24
+ - User runs `/axiom:distill`
25
+ - Post-refactoring cleanup is needed
26
+ - Reducing cognitive load in a module
27
+
28
+ Do NOT activate when:
29
+ - Error handling improvements are needed — use `axiom:harden` instead
30
+ - Performance optimization is the goal — performance profiling is out of scope for axiom
31
+ - Security hardening is required — use `axiom:harden` instead
32
+
33
+ ## Process
34
+
35
+ ### 1. Load Dimensions
36
+
37
+ Load the relevant quality dimensions from `@skills/backend-quality/references/dimensions.md`:
38
+ - **DIM-5 (Hygiene):** Dead code, commented-out code, unused imports/exports, vestigial patterns
39
+ - **DIM-1 (Topology):** Module structure, dependency direction, wiring complexity
40
+
41
+ ### 2. Run Deterministic Checks
42
+
43
+ Run `axiom:scan` for deterministic checks on Hygiene and Topology dimensions. This produces machine-verifiable findings for:
44
+ - Unused exports and imports
45
+ - Unreachable code paths
46
+ - Circular dependencies
47
+ - Excessive module fan-out
48
+
49
+ ### 3. Layer Qualitative Assessment
50
+
51
+ Beyond deterministic checks, apply human-judgment analysis:
52
+
53
+ #### Dead Code Identification
54
+ Identify unreachable branches (code after `return`/`throw`), unused exports (exported but never imported elsewhere), commented-out code (version control exists for history), and feature-flagged-off code that shipped long ago.
55
+
56
+ See `@skills/distill/references/dead-code-patterns.md` for detection heuristics and false positive guidance.
57
+
58
+ #### Vestigial Pattern Detection
59
+ Find evolutionary leftovers from previous designs. Look for divergent implementations that suggest a pattern was partially migrated, adapter layers wrapping things that no longer need adapting, and configuration for features that were removed.
60
+
61
+ #### Wiring Simplification
62
+ Identify manual DI that could be simpler, unnecessary indirection layers, over-abstracted factory/builder patterns where direct construction suffices, and registration ceremonies that add complexity without value.
63
+
64
+ #### Abstraction Audit
65
+ Flag premature abstractions, over-engineering, and single-use helpers. Ask: does this abstraction serve more than one caller? Would inlining it make the code clearer?
66
+
67
+ #### Code Archaeology
68
+ Identify patterns that were once necessary but no longer serve a purpose. Look for workarounds for bugs that have since been fixed, compatibility shims for deprecated APIs, and defensive code guarding against conditions that can no longer occur.
69
+
70
+ ### 4. Output Findings
71
+
72
+ Format all findings per `@skills/backend-quality/references/findings-format.md`. Each finding includes:
73
+ - Dimension (DIM-5 or DIM-1)
74
+ - Severity (HIGH, MEDIUM, LOW)
75
+ - Location (file, line range)
76
+ - Description and recommended action
77
+
78
+ See also `@skills/distill/references/simplification-guide.md` for guidance on when to simplify vs remove.
79
+
80
+ ## Error Handling
81
+
82
+ - **Empty scope:** If no files match the target scope, output an informative message explaining that no files were found and suggesting the user verify the path or scope parameters.
83
+ - **No findings:** If analysis completes with zero findings, report a clean result rather than failing silently.
@@ -0,0 +1,152 @@
1
+ # Dead Code Patterns
2
+
3
+ Reference guide for identifying, classifying, and triaging dead code in backend systems.
4
+
5
+ ## Dead Code Categories
6
+
7
+ ### 1. Unreachable Code
8
+
9
+ Code that can never execute because control flow prevents reaching it.
10
+
11
+ **Examples:**
12
+ - Statements after unconditional `return`, `throw`, `break`, or `continue`
13
+ - Branches guarded by conditions that are always false (e.g., `if (false)`, constant expressions)
14
+ - `catch` blocks for exceptions that are never thrown by the `try` body
15
+ - `switch` cases for enum values that no longer exist
16
+
17
+ **Detection heuristics:**
18
+ - Static analysis tools (TypeScript `--noUnusedLocals`, ESLint `no-unreachable`)
19
+ - Grep for code after `return`/`throw` at the same indentation level
20
+ - Analyze control flow graphs for unreachable nodes
21
+ - Look for `if` conditions comparing against removed enum values or deleted constants
22
+
23
+ ### 2. Unused Exports
24
+
25
+ Symbols that are exported from a module but never imported by any other module.
26
+
27
+ **Examples:**
28
+ - Functions exported from a utility module that no consumer calls
29
+ - Types/interfaces exported but never referenced externally
30
+ - Re-exports from barrel files (`index.ts`) where the re-exported symbol has no importers
31
+ - Constants exported "just in case" during initial development
32
+
33
+ **Detection heuristics:**
34
+ - Grep for the export name across all importing files; zero hits means unused
35
+ - Use `ts-prune`, `knip`, or similar tools to detect unused exports
36
+ - Analyze barrel file re-exports: if the barrel is imported but only a subset of its exports are used, the rest are dead
37
+ - Check test files separately — an export used only in tests may still be dead from a production perspective
38
+
39
+ ### 3. Commented-Out Code
40
+
41
+ Code that has been commented out rather than deleted. Version control exists for history.
42
+
43
+ **Examples:**
44
+ - Block comments containing syntactically valid code
45
+ - Lines prefixed with `//` that contain function calls, variable assignments, or imports
46
+ - `/* ... */` blocks wrapping entire functions or class methods
47
+ - TODO comments referencing code that should be "re-enabled" but never was
48
+
49
+ **Detection heuristics:**
50
+ - Grep for multi-line comments containing keywords like `function`, `const`, `import`, `export`, `class`, `return`
51
+ - Look for `// ` followed by valid statement syntax (assignments, function calls)
52
+ - Identify comments with version control references ("removed in v2", "old implementation")
53
+ - Check git blame — if commented-out code has been that way for more than 2 sprints, it is dead
54
+
55
+ ### 4. Feature-Flagged-Off Code
56
+
57
+ Code behind feature flags that have been permanently disabled or the flag has shipped long ago.
58
+
59
+ **Examples:**
60
+ - `if (featureFlags.enableNewParser)` where the flag has been `false` in all environments for months
61
+ - A/B test branches where the experiment concluded and only one path is active
62
+ - Migration code behind a flag that completed its rollout
63
+ - Fallback paths for flags that have been `true` in production for multiple releases
64
+
65
+ **Detection heuristics:**
66
+ - Cross-reference feature flag names with the flag configuration store
67
+ - Analyze flag usage: if a flag is always `true` or always `false` across all environments, the guarded code (or its inverse) is dead
68
+ - Check flag creation dates — flags older than 90 days without recent changes are candidates
69
+ - Look for TODO comments referencing flag cleanup
70
+
71
+ ## False Positive Guidance
72
+
73
+ Not all apparently unused code is dead. Be cautious with:
74
+
75
+ - **Intentional stubs:** Interface methods with empty bodies that exist to satisfy a contract, or template methods meant for subclass override
76
+ - **Forward declarations:** Types or constants declared for planned but not-yet-implemented features (check the roadmap/backlog before flagging)
77
+ - **Public API surface:** Libraries and packages intentionally export symbols for external consumers; check if the module is consumed outside the repository
78
+ - **Plugin entry points:** Functions registered via reflection, dependency injection, or naming convention (e.g., `handle_*`, `on_*`) that are invoked dynamically
79
+ - **Test helpers and fixtures:** Utility functions in test support files that may be imported conditionally or by test files not in the current scope
80
+ - **Event handlers and callbacks:** Functions registered as listeners that are invoked indirectly through event dispatch
81
+
82
+ **Verification steps before reporting:**
83
+ 1. Search the entire repository, not just the immediate module
84
+ 2. Check for dynamic invocation patterns (reflection, `eval`, dynamic imports)
85
+ 3. Look for references in configuration files, scripts, and documentation
86
+ 4. Verify whether the module is published as a package with external consumers
87
+
88
+ ## Severity Guide
89
+
90
+ ### HIGH Severity — Misleading Dead Code
91
+
92
+ Dead code that actively misleads developers or creates risk:
93
+
94
+ - Commented-out code that appears to be an alternative implementation, confusing future readers about which path is correct
95
+ - Unreachable error handling that gives false confidence about fault tolerance
96
+ - Unused exports that appear in IDE autocomplete, leading developers to use dead APIs
97
+ - Feature-flagged code where the flag check masks a bug in the "live" path
98
+
99
+ ### MEDIUM Severity — Noise
100
+
101
+ Dead code that adds cognitive load without active harm:
102
+
103
+ - Unused utility functions that clutter the module
104
+ - Old commented-out code that has been superseded by a different approach
105
+ - Barrel file re-exports of symbols no one imports
106
+ - Test helpers that are no longer called by any test
107
+
108
+ ### LOW Severity — Minor
109
+
110
+ Dead code with minimal impact:
111
+
112
+ - Single unused constants or type aliases
113
+ - Commented-out log/debug statements
114
+ - Unused function parameters (often enforced by interface contracts)
115
+ - Empty catch blocks that were once meaningful but the try body changed
116
+
117
+ ## Examples
118
+
119
+ ### HIGH: Misleading unreachable error handler
120
+
121
+ ```typescript
122
+ async function processOrder(order: Order): Promise<Result> {
123
+ const validated = validateOrder(order);
124
+ return submitOrder(validated);
125
+
126
+ // This catch-all never executes — gives false sense of error handling
127
+ try {
128
+ return submitOrder(validated);
129
+ } catch (error) {
130
+ await notifyOps(error);
131
+ return { status: 'failed', error };
132
+ }
133
+ }
134
+ ```
135
+
136
+ ### MEDIUM: Unused export cluttering module
137
+
138
+ ```typescript
139
+ // utils.ts
140
+ export function formatDate(d: Date): string { /* ... */ }
141
+ export function parseDate(s: string): Date { /* ... */ }
142
+ export function dateToEpoch(d: Date): number { /* ... */ } // zero importers
143
+ ```
144
+
145
+ ### LOW: Commented-out debug logging
146
+
147
+ ```typescript
148
+ function handleRequest(req: Request) {
149
+ // console.log('incoming request:', req.headers);
150
+ return processRequest(req);
151
+ }
152
+ ```
@@ -0,0 +1,128 @@
1
+ # Simplification Guide
2
+
3
+ Reference guide for reducing code complexity, identifying vestigial patterns, and deciding when to simplify versus when to remove entirely.
4
+
5
+ ## Complexity Reduction Patterns
6
+
7
+ ### When to Inline vs Extract
8
+
9
+ **Inline when:**
10
+ - A function is called exactly once and its name does not add clarity beyond reading the body
11
+ - A wrapper function merely delegates to another function without transformation
12
+ - An abstraction layer adds indirection but no behavioral difference (pass-through adapters)
13
+ - The extraction was premature — the "reusable" function is only used in one place
14
+
15
+ **Extract when:**
16
+ - The same logic appears in three or more locations (see "three uses" rule below)
17
+ - A block of code has a clear name that communicates intent better than the implementation details
18
+ - Testing the logic in isolation would significantly improve test coverage or clarity
19
+ - The extracted function represents a domain concept that should be named
20
+
21
+ **Decision heuristic:** If removing the function name forces the reader to re-derive the intent from the implementation, keep the extraction. If the name is just a restatement of the single line it wraps, inline it.
22
+
23
+ ### When Abstraction Helps vs Hurts
24
+
25
+ **Abstraction helps when:**
26
+ - Multiple concrete implementations exist and the abstraction captures their shared contract
27
+ - The abstraction enables meaningful testability (swapping real for fake implementations)
28
+ - Domain boundaries are clarified by the interface
29
+
30
+ **Abstraction hurts when:**
31
+ - Only one implementation exists and no second is planned or plausible
32
+ - The abstraction mirrors the implementation 1:1 (an interface with the same shape as the single class)
33
+ - Navigating through the abstraction layer requires more cognitive effort than understanding the concrete code
34
+ - "Dependency injection" is really just passing a single concrete instance through extra layers
35
+
36
+ ### Reducing Conditional Complexity
37
+
38
+ - **Collapse nested conditionals:** Replace `if (a) { if (b) { ... } }` with `if (a && b) { ... }` when the nesting adds no clarity
39
+ - **Use early returns:** Convert deep nesting into guard clauses that return/throw early
40
+ - **Replace flag variables:** When a boolean flag is set and then checked once, inline the condition
41
+ - **Simplify boolean expressions:** `if (x === true)` becomes `if (x)`; `if (!x === false)` becomes `if (x)`
42
+
43
+ ## Vestigial Pattern Identification
44
+
45
+ ### Code Archaeology Approach
46
+
47
+ Vestigial patterns are evolutionary leftovers — code structures that made sense in a previous design but persist after the design changed. To identify them:
48
+
49
+ 1. **Look for patterns that reference removed features:** Search for imports of deleted modules, references to renamed types, or configuration keys for features that no longer exist
50
+ 2. **Identify partial migrations:** When a codebase migrated from pattern A to pattern B, look for leftover pattern A code that was never converted
51
+ 3. **Check adapter layers:** If an adapter wraps a dependency that was replaced, and the adapter's interface matches the new dependency's interface directly, the adapter is vestigial
52
+ 4. **Examine defensive code:** Guards against conditions that were possible in a previous version but are now structurally impossible (e.g., null checks after a field became required)
53
+
54
+ ### Common Vestigial Pattern Types
55
+
56
+ - **Dead adapters:** Wrapper classes that were introduced to bridge between two APIs, but one API was since removed or the wrapper now delegates directly
57
+ - **Orphaned configuration:** Config keys, environment variables, or feature flags that no active code reads
58
+ - **Compatibility shims:** Polyfills or compatibility layers for platform versions no longer supported
59
+ - **Migration scaffolding:** Temporary code introduced to migrate data or APIs that was never removed after migration completed
60
+ - **Defensive checks for impossible states:** Null checks, type guards, or fallback values for conditions that the current type system or architecture prevents
61
+
62
+ ## Wiring Simplification
63
+
64
+ ### From Manual Configure/Register to Simpler Patterns
65
+
66
+ **Identify over-engineered wiring when:**
67
+ - A registration function manually lists every dependency and wires them together, but the dependency graph is simple and linear
68
+ - A factory creates objects by resolving dependencies one-by-one when direct construction with `new` would suffice
69
+ - A configuration object has dozens of keys, most of which are always set to the same default value
70
+ - A "plugin system" exists but there is only one plugin and no mechanism for external plugins
71
+
72
+ **Simplification strategies:**
73
+ - Replace manual DI containers with direct construction when there are fewer than 3 dependencies
74
+ - Replace factory functions with constructors when the factory adds no logic beyond `new`
75
+ - Replace configuration objects with sensible defaults and optional overrides
76
+ - Replace event bus / pub-sub patterns with direct function calls when there is only one subscriber
77
+
78
+ ### Recognizing Unnecessary Indirection
79
+
80
+ Indirection that does not serve a purpose:
81
+
82
+ - **Pass-through functions:** `function doThing(x) { return actuallyDoThing(x); }` with no additional logic
83
+ - **Single-method interfaces with one implementation:** The interface and class are isomorphic
84
+ - **Manager/controller classes that only delegate:** A `FooManager` that holds a `Foo` and forwards all calls
85
+ - **Middleware chains with one middleware:** The chain infrastructure adds complexity but only one handler exists
86
+
87
+ ## The "Three Uses" Rule
88
+
89
+ Do not abstract until you have seen the pattern three times:
90
+
91
+ 1. **First occurrence:** Write the code inline. Do not extract.
92
+ 2. **Second occurrence:** Note the duplication but tolerate it. Copy-paste is acceptable.
93
+ 3. **Third occurrence:** Now extract. You have enough examples to see the true shape of the abstraction.
94
+
95
+ **Why three?** Two occurrences often look similar by coincidence. The third occurrence confirms the pattern is real and reveals which parts vary (parameters) and which are fixed (the abstraction body). Abstracting after two uses risks creating an abstraction shaped for the wrong generalization.
96
+
97
+ **Exception:** If the duplicated code is long (>20 lines) or contains complex logic with known bug risk, extract after two uses. The cost of a slightly wrong abstraction is lower than the cost of a bug fix applied to only one copy.
98
+
99
+ ## Simplification vs Deletion
100
+
101
+ ### When to Simplify
102
+
103
+ Simplify (reduce complexity without removing) when:
104
+ - The code serves a current purpose but is more complicated than necessary
105
+ - The functionality is needed but the implementation has accumulated accidental complexity
106
+ - A refactoring pass changed the surroundings but left this code with now-unnecessary guards or abstractions
107
+ - The code works but is hard to understand — simplification improves readability without changing behavior
108
+
109
+ ### When to Remove Entirely
110
+
111
+ Remove (delete the code) when:
112
+ - The code is unreachable or provably never executed
113
+ - The feature the code supports has been decommissioned
114
+ - The code is commented out and has been for more than one release cycle
115
+ - A replacement implementation exists and the old one is no longer used
116
+ - The code is a workaround for a bug that has been fixed at its source
117
+
118
+ ### Decision Framework
119
+
120
+ Ask these questions in order:
121
+
122
+ 1. **Is this code reachable?** If no, delete it.
123
+ 2. **Does this code serve an active feature?** If no, delete it.
124
+ 3. **Is this code more complex than it needs to be?** If yes, simplify it.
125
+ 4. **Is there a simpler way to achieve the same result?** If yes, simplify to that.
126
+ 5. **Would a reader understand this code without extra context?** If no, simplify for clarity.
127
+
128
+ When in doubt, prefer deletion over simplification. Dead code that is simplified is still dead code. Version control preserves history — you can always retrieve deleted code if needed.
@@ -0,0 +1,161 @@
1
+ ---
2
+ name: harden
3
+ description: "Strengthen backend resilience by finding silent catches, missing error context, resource leaks, and operational fragility. Use when hardening error handling or preparing for production deployment. Triggers: 'harden code', 'check error handling', 'resilience review', or /axiom:harden. Do NOT use for dead code — use axiom:distill instead."
4
+ user-invokable: true
5
+ metadata:
6
+ author: lvlup-sw
7
+ version: 0.1.0
8
+ category: assessment
9
+ dimensions:
10
+ - observability
11
+ - resilience
12
+ ---
13
+
14
+ # Harden Skill
15
+
16
+ ## Overview
17
+
18
+ Resilience-focused assessment skill covering DIM-2 (Observability) and DIM-7 (Resilience) from the backend quality dimension taxonomy. Finds error handling gaps, silent catches, resource leaks, and operational fragility that could cause cascading failures under stress.
19
+
20
+ This skill combines deterministic pattern detection (via `axiom:scan`) with qualitative judgment to assess how well code handles failure, communicates errors, and manages resources.
21
+
22
+ ## Triggers
23
+
24
+ ### Positive Triggers
25
+
26
+ Activate this skill when:
27
+ - User says "harden code", "harden this", or "resilience review"
28
+ - User says "check error handling" or "audit error handling"
29
+ - User runs `/axiom:harden`
30
+ - Preparing code for production deployment
31
+ - After an incident exposed error handling gaps
32
+
33
+ ### Negative Triggers
34
+
35
+ Do NOT use this skill when:
36
+ - Looking for dead code or vestigial patterns — use `axiom:distill` instead
37
+ - Reviewing architecture or SOLID compliance — use `axiom:critique` instead
38
+ - Checking test quality or mock fidelity — use `axiom:verify` instead
39
+ - Running a comprehensive audit — use `axiom:audit` instead
40
+
41
+ ## Process
42
+
43
+ ### Step 1: Load Dimension Definitions
44
+
45
+ Load the relevant dimensions from the shared taxonomy:
46
+
47
+ - `@skills/backend-quality/references/dimensions.md` — read the DIM-2 (Observability) and DIM-7 (Resilience) sections for invariants, signals, and severity guides.
48
+
49
+ ### Step 2: Run Deterministic Checks
50
+
51
+ Invoke `axiom:scan` for mechanical pattern detection on the Observability and Resilience dimensions:
52
+
53
+ - DIM-2 checks: empty catch blocks, log-only catches, swallowed promise rejections
54
+ - DIM-7 checks: unbounded collections, missing timeouts, unbounded retry loops
55
+
56
+ Collect all deterministic findings. These form the baseline that qualitative assessment builds upon.
57
+
58
+ ### Step 3: Qualitative Assessment
59
+
60
+ Layer judgment-based analysis on top of the deterministic results. For each area, review the flagged code regions and nearby context:
61
+
62
+ #### 3a. Empty Catch Audit
63
+
64
+ Classify every catch block in scope into one of four categories:
65
+
66
+ | Category | Definition | Action |
67
+ |----------|-----------|--------|
68
+ | **Silent** | Empty catch body, no logging, no recovery | HIGH — must add handling or documented rationale |
69
+ | **Log-only** | Logs the error but takes no recovery action | MEDIUM — evaluate whether recovery is needed |
70
+ | **Recovery** | Catches, logs, and takes corrective action | OK — verify recovery is correct |
71
+ | **Intentional** | Documented rationale for swallowing (e.g., `// Intentional: probe-only, failure is expected`) | OK — verify comment is accurate |
72
+
73
+ Consult `@skills/harden/references/error-patterns.md` for the full silent catch taxonomy and classification guidance.
74
+
75
+ #### 3b. Error Context Propagation
76
+
77
+ For each error path, evaluate whether errors include sufficient context:
78
+
79
+ - **What** failed? (operation name, inputs, resource identifier)
80
+ - **Why** did it fail? (root cause, constraint violation)
81
+ - **How to fix?** (retry guidance, configuration check, escalation path)
82
+ - **Cause chain?** (is the original error preserved via `{ cause: e }`?)
83
+
84
+ Generic error messages like "Something went wrong" or "Operation failed" are a MEDIUM finding.
85
+
86
+ #### 3c. Fallback Behavior Analysis
87
+
88
+ Identify all fallback paths and evaluate visibility:
89
+
90
+ - Are fallbacks logged or metriced so operators know degraded mode is active?
91
+ - Do fallbacks silently switch behavior modes without signaling?
92
+ - Is best-effort behavior clearly documented and visible in monitoring?
93
+
94
+ Silent degradation — where the system quietly switches to a less capable mode — is a HIGH finding.
95
+
96
+ #### 3d. Resource Lifecycle
97
+
98
+ Verify open/close symmetry and acquire/release patterns:
99
+
100
+ - File handles opened in try blocks — are they closed in finally?
101
+ - Database connections — are they released on both success and error paths?
102
+ - Event listeners — are they removed when no longer needed?
103
+ - Streams — are they properly ended/destroyed on error?
104
+
105
+ Consult `@skills/harden/references/resilience-checklist.md` for the full resource management checklist.
106
+
107
+ #### 3e. Timeout and Retry Evaluation
108
+
109
+ For every external call (HTTP, database, file system, IPC):
110
+
111
+ - Is there a timeout? (missing timeout = MEDIUM)
112
+ - Is the timeout reasonable for the operation? (60s for a health check = LOW)
113
+ - Are retries bounded? (unbounded retry = HIGH)
114
+ - Is there backoff? (no backoff = MEDIUM)
115
+
116
+ #### 3f. Cache Bound Verification
117
+
118
+ For every in-memory collection that persists beyond a single request:
119
+
120
+ - Is there a maximum size? (unbounded Map/Set/Array = HIGH)
121
+ - Is there an eviction policy? (LRU, TTL, or manual clear)
122
+ - Do collections grow monotonically without cleanup?
123
+
124
+ ### Step 4: Output Findings
125
+
126
+ Format all findings per the standard finding schema: `@skills/backend-quality/references/findings-format.md`
127
+
128
+ Group findings by severity (HIGH, MEDIUM, LOW). Each finding must include:
129
+ - Dimension (DIM-2 or DIM-7)
130
+ - Evidence (file:line references)
131
+ - Explanation (what is wrong and why it matters)
132
+ - Suggestion (how to fix, when actionable)
133
+ - Whether it was found deterministically or qualitatively
134
+
135
+ ## Error Handling
136
+
137
+ ### Empty Scope
138
+
139
+ If the provided scope is empty or contains no files to analyze, return an informative message:
140
+
141
+ > "No files found in the provided scope. Specify a file path, directory, or glob pattern. Example: `/axiom:harden src/` or `/axiom:harden src/events/`."
142
+
143
+ Do not return an empty finding set without explanation.
144
+
145
+ ## Anti-Patterns
146
+
147
+ | Don't | Do Instead |
148
+ |-------|------------|
149
+ | Flag every catch block as a problem | Classify — many catches are correct and intentional |
150
+ | Ignore log-only catches | Evaluate whether the error needs recovery, not just logging |
151
+ | Treat all fallbacks as bad | Evaluate whether degradation is visible and documented |
152
+ | Skip resource lifecycle in test code | Test helpers leak resources too |
153
+ | Assume timeouts are always present | Verify each external call individually |
154
+ | Report cache concerns for request-scoped collections | Only flag persistent/growing collections |
155
+
156
+ ## References
157
+
158
+ - `@skills/backend-quality/references/dimensions.md` — DIM-2 and DIM-7 definitions
159
+ - `@skills/backend-quality/references/findings-format.md` — finding output schema
160
+ - `@skills/harden/references/error-patterns.md` — silent catch taxonomy and error context checklist
161
+ - `@skills/harden/references/resilience-checklist.md` — resource management, timeouts, retries, concurrency checklist