Tech Debt Audit Protocol
Model-agnostic technical debt audit for oh-my-openagent (OMO). Uses OMO's built-in tools (grep, glob, bash with sg, read, lsp_diagnostics, task). Produces a grounded, citable TECH_DEBT_AUDIT.md artifact.
Output
Write results to TECH_DEBT_AUDIT.md in the repo root with:
- Executive Summary — 3-5 sentences: overall health, worst dimension, quick wins count
- Mental Model — the repo's architecture in 1 paragraph (what it does, stack, module boundaries)
- Findings Table — columns: ID, Category, File:Line, Severity (Critical/High/Medium/Low), Effort (Hours), Description, Recommendation
- Top 5 Priorities — ranked by impact/effort ratio
- Quick Wins Checklist — items under 30 minutes each
- "Looks Bad But Is Fine" — patterns that look like debt but are intentional
- Open Questions — things the maintainer should clarify
Phase 0: Orient
Standard (always run)
glob("**/*.ts") / glob("**/*.py") / etc — map the language stack
glob("**/package.json") + read() — dependencies and build tooling
bash("git log --oneline -200") — churn: find highest-change files
glob("**/*") + basic math — find largest files (>300 LOC are candidates)
- Cross-reference high-churn + large = debt hot zones
- Write the mental model paragraph in your own working context
Phase 1: Audit Across 9 Dimensions
Use OMO tools for each dimension. Run parallel tool calls within each dimension. Every finding MUST cite file:line:col.
1. Architectural Decay
Standard (always run)
bash("sg -p \"import { $$$ } from '$SRC'\" -l ts .") — map module graph, look for circular patterns
bash("sg -p \"class $NAME { $$$ }\" -l ts .") — check for god classes
grep("TODO|FIXME|HACK|XXX|WORKAROUND|TEMP") — tagged debt markers
grep("async|await") on sync-looking files — misplaced async boundaries
bash("wc -l <file>") on each large file found in Phase 0
What to flag
- Files > 500 LOC (god files)
- Functions > 80 LOC or > 4 nesting levels
- Classes with > 15 methods or > 400 LOC
- Import cycles (A → B → A)
- Dead exports: function/class defined but never imported elsewhere (confirm with
lsp_find_references)
- Commented-out code blocks (>3 consecutive consecutive lines)
2. Consistency Rot
Standard (always run)
bash("sg -p \"import $CLIENT from '$PKG'\" -l ts .") — multiple HTTP clients
grep("console.log|console.error|console.warn") — direct console use vs logger
bash("sg -p \"try { $$$ } catch ($$$) { $$$ }\" -l ts .") — error handling patterns
grep("as any|@ts-ignore|@ts-expect-error|as unknown") — type escapes
grep("eslint-disable|prettier-ignore") — lint suppressions
What to flag
- 3+ ways of doing the same thing (HTTP, logging, validation, config)
- Mixed naming conventions (camelCase + snake_case + PascalCase)
- Multiple date/time handling libraries
- Mixed error response shapes across modules
3. Type & Contract Debt
Standard (always run)
bash("sg -p \"$VALUE as any\" -l ts .") — runtime type escapes
grep("@ts-expect-error") — suppressed errors
grep("@ts-ignore") — suppressed errors (legacy)
bash("sg -p \"$NAME: any\" -l ts .") — typed as any
lsp_diagnostics(filePath="<src-dir>") — current type errors
What to flag
any types on public APIs and exported interfaces
- Untyped function parameters
- Missing schema validation at API/IO boundaries
- LSP type errors grouped by file
4. Test Debt
Standard (always run)
glob("**/*.test.ts") — find all test files
bash("bun test 2>&1 | grep -E '(fail|skip|todo)'") — current test health
- Cross-reference Phase 0 high-churn files with test existence
What to flag
- Critical-path files with zero tests
- Skipped tests (
test.skip, describe.skip)
- Tests asserting implementation details vs behavior
- Slow tests (>1s each)
5. Dependency & Config Debt
Standard (always run)
bash("npm audit --omit=dev 2>&1 | head -40") — known CVEs (if node_modules present)
read("package.json") — check dependency count and stale deps
grep(".env|process.env|Bun.env") — env var usage
grep("API_KEY|SECRET|PASSWORD|TOKEN") in non-config files — hardcoded config
What to flag
- Outdated major-version deps
- Dependencies that do the same thing (duplicate libraries)
- Referenced env vars not documented in README
- Hardcoded environment-specific values
6. Performance & Resource Hygiene
Standard (always run)
bash("sg -p \"for ($$$ of $$$) { $$$ await $$$ }\" -l ts .") — async-in-loop
grep("await.*map|await.*filter|await.*forEach") — sequential async iteration
grep("Promise\\.all|Promise\\.allSettled") — existing parallel patterns (good signal)
grep("addEventListener|on\\(|subscribe") without removeEventListener|off\\(|unsubscribe nearby — listener hygiene
What to flag
await inside for/of loops (sequential when parallel possible)
- N+1 query patterns
- Missing cleanup on event listeners, intervals, handles
- Unnecessary serialization/deserialization
7. Error Handling & Observability
Standard (always run)
bash("sg -p \"catch ($$$) { $$$ }\" -l ts .") — catch blocks
grep("catch.*{}|catch.*{\\s*}") — empty catch blocks
grep("console.error|logger\\.error|log\\.error") — actual error logging
bash("sg -p \"throw new $ERR($$$)\" -l ts .") — error types used
What to flag
- Empty catch blocks (worst offense)
- Generic
catch (e) { console.error(e) } without recovery
- Inconsistent error shapes across modules
- Missing structured logging on critical paths
- Errors swallowed in promise chains (
.catch(() => {}))
8. Security Hygiene
Standard (always run)
grep("api[Kk]ey|api_secret|password|secret|token|credential") in source files (not config or env)
grep("SELECT .* FROM|INSERT INTO|UPDATE.*SET|DELETE FROM") — SQL construction
grep("innerHTML|dangerouslySetInnerHTML") — XSS vectors
grep("eval\\(|Function\\(|setTimeout\\(.*string|setInterval\\(.*string") — code injection
What to flag
- Hardcoded secrets in source
- String-concatenated SQL
innerHTML / dangerouslySetInnerHTML usage
eval() or string-based setTimeout/setInterval
- Permissive CORS or auth middleware
9. Documentation Drift
Standard (always run)
read("README.md") — check if claims match reality
grep("@param|@returns|@throws") — docstring coverage
grep("FIXME|TODO|HACK|XXX|WORKAROUND") — fixme density
- Compare README API examples with actual signatures
What to flag
- README claiming features that don't exist
- Public functions without any doc comment
- Comments that contradict the code
- Stale architecture decision records (ADRs) if present
Phase 2: Deeper Dives (Parallel Sub-Agents)
For large codebases (>50k LOC), delegate heavy dimensions to parallel sub-agents. Each sub-agent runs the standard tool passes for its dimensions:
task(category="unspecified-low", run_in_background=true, load_skills=[], prompt="[CONTEXT] Tech debt audit. [GOAL] Audit dimensions 1 (Architecture) and 2 (Consistency). [REQUEST] Run ast_grep and grep searches for dimensions 1-2 from the tech-debt-audit skill. Report every finding with file:line:col. Tag severity: Critical/High/Medium/Low.")
task(category="unspecified-low", run_in_background=true, load_skills=[], prompt="[CONTEXT] Tech debt audit. [GOAL] Audit dimensions 3 (Type debt) and 7 (Error handling). [REQUEST] Run searches for dimensions 3 and 7 from the tech-debt-audit skill. Report every finding with file:line:col. Tag severity.")
Spawn 2-3 sub-agents for the heaviest dimensions, collect results in parallel, then synthesize.
Phase 3: Synthesize & Deliver
- Collect all findings from direct tool calls and sub-agent results
- Deduplicate — same issue mentioned by multiple dimensions
- Classify severity:
- Critical — Causes incorrect behavior, data loss, or security vulnerability
- High — Will cause problems in production; blocks maintenance
- Medium — Reduces maintainability; violates conventions
- Low — Cosmetic; should fix when in the area
- Estimate effort in hours per finding (conservative)
- Write
TECH_DEBT_AUDIT.md with all required sections
- Report summary to the user
Severity Rubric
Critical = actively causing bugs or security holes
High = will cause problems under normal operation; blocks changes
Medium = reduces maintainability; inconsistent; violates team conventions
Low = cosmetic; would be nice to fix when nearby
Quick Checks Before Finishing
1---2name: tech-debt-audit3description: Thorough, file-cited technical debt audit across 9 dimensions using AST-grep (tree-sitter), grep, LSP, and language-native tooling. Produces TECH_DEBT_AUDIT.md with severity, effort estimates, and prioritized fixes. Use when asked for codebase health check, tech debt audit, architecture review, code quality assessment, or cleanup planning. Triggers: 'tech debt', 'technical debt', 'debt audit', 'code health', 'technical debt audit', 'codebase health check', 'find tech debt', 'debt analysis', 'audit code quality'.4---5
6# Tech Debt Audit Protocol
7
8Model-agnostic technical debt audit for oh-my-openagent (OMO). Uses OMO's built-in tools (`grep`, `glob`, `bash` with `sg`, `read`, `lsp_diagnostics`, `task`). Produces a grounded, citable `TECH_DEBT_AUDIT.md` artifact.
9
10## Output
11
12Write results to `TECH_DEBT_AUDIT.md` in the repo root with:
13
141. **Executive Summary** — 3-5 sentences: overall health, worst dimension, quick wins count
152. **Mental Model** — the repo's architecture in 1 paragraph (what it does, stack, module boundaries)
163. **Findings Table** — columns: ID, Category, File:Line, Severity (Critical/High/Medium/Low), Effort (Hours), Description, Recommendation
174. **Top 5 Priorities** — ranked by impact/effort ratio
185. **Quick Wins Checklist** — items under 30 minutes each
196. **"Looks Bad But Is Fine"** — patterns that look like debt but are intentional
207. **Open Questions** — things the maintainer should clarify
21
22## Phase 0: Orient
23
24### Standard (always run)
251. `glob("**/*.ts")` / `glob("**/*.py")` / etc — map the language stack
262. `glob("**/package.json")` + `read()` — dependencies and build tooling
273. `bash("git log --oneline -200")` — churn: find highest-change files
284. `glob("**/*")` + basic math — find largest files (>300 LOC are candidates)
295. Cross-reference high-churn + large = debt hot zones
306. Write the mental model paragraph in your own working context
31
32## Phase 1: Audit Across 9 Dimensions
33
34Use OMO tools for each dimension. Run parallel tool calls within each dimension. Every finding MUST cite `file:line:col`.
35
36### 1. Architectural Decay
37
38#### Standard (always run)
39- `bash("sg -p \"import { $$$ } from '$SRC'\" -l ts .")` — map module graph, look for circular patterns
40- `bash("sg -p \"class $NAME { $$$ }\" -l ts .")` — check for god classes
41- `grep("TODO|FIXME|HACK|XXX|WORKAROUND|TEMP")` — tagged debt markers
42- `grep("async|await")` on sync-looking files — misplaced async boundaries
43- `bash("wc -l <file>")` on each large file found in Phase 0
44
45#### What to flag
46- Files > 500 LOC (god files)
47- Functions > 80 LOC or > 4 nesting levels
48- Classes with > 15 methods or > 400 LOC
49- Import cycles (A → B → A)
50- Dead exports: function/class defined but never imported elsewhere (confirm with `lsp_find_references`)
51- Commented-out code blocks (>3 consecutive consecutive lines)
52
53### 2. Consistency Rot
54
55#### Standard (always run)
56- `bash("sg -p \"import $CLIENT from '$PKG'\" -l ts .")` — multiple HTTP clients
57- `grep("console.log|console.error|console.warn")` — direct console use vs logger
58- `bash("sg -p \"try { $$$ } catch ($$$) { $$$ }\" -l ts .")` — error handling patterns
59- `grep("as any|@ts-ignore|@ts-expect-error|as unknown")` — type escapes
60- `grep("eslint-disable|prettier-ignore")` — lint suppressions
61
62#### What to flag
63- 3+ ways of doing the same thing (HTTP, logging, validation, config)
64- Mixed naming conventions (camelCase + snake_case + PascalCase)
65- Multiple date/time handling libraries
66- Mixed error response shapes across modules
67
68### 3. Type & Contract Debt
69
70#### Standard (always run)
71- `bash("sg -p \"$VALUE as any\" -l ts .")` — runtime type escapes
72- `grep("@ts-expect-error")` — suppressed errors
73- `grep("@ts-ignore")` — suppressed errors (legacy)
74- `bash("sg -p \"$NAME: any\" -l ts .")` — typed as any
75- `lsp_diagnostics(filePath="<src-dir>")` — current type errors
76
77#### What to flag
78- `any` types on public APIs and exported interfaces
79- Untyped function parameters
80- Missing schema validation at API/IO boundaries
81- LSP type errors grouped by file
82
83### 4. Test Debt
84
85#### Standard (always run)
86- `glob("**/*.test.ts")` — find all test files
87- `bash("bun test 2>&1 | grep -E '(fail|skip|todo)'")` — current test health
88- Cross-reference Phase 0 high-churn files with test existence
89
90#### What to flag
91- Critical-path files with zero tests
92- Skipped tests (`test.skip`, `describe.skip`)
93- Tests asserting implementation details vs behavior
94- Slow tests (>1s each)
95
96### 5. Dependency & Config Debt
97
98#### Standard (always run)
99- `bash("npm audit --omit=dev 2>&1 | head -40")` — known CVEs (if node_modules present)
100- `read("package.json")` — check dependency count and stale deps
101- `grep(".env|process.env|Bun.env")` — env var usage
102- `grep("API_KEY|SECRET|PASSWORD|TOKEN")` in non-config files — hardcoded config
103
104#### What to flag
105- Outdated major-version deps
106- Dependencies that do the same thing (duplicate libraries)
107- Referenced env vars not documented in README
108- Hardcoded environment-specific values
109
110### 6. Performance & Resource Hygiene
111
112#### Standard (always run)
113- `bash("sg -p \"for ($$$ of $$$) { $$$ await $$$ }\" -l ts .")` — async-in-loop
114- `grep("await.*map|await.*filter|await.*forEach")` — sequential async iteration
115- `grep("Promise\\.all|Promise\\.allSettled")` — existing parallel patterns (good signal)
116- `grep("addEventListener|on\\(|subscribe")` without `removeEventListener|off\\(|unsubscribe` nearby — listener hygiene
117
118#### What to flag
119- `await` inside `for/of` loops (sequential when parallel possible)
120- N+1 query patterns
121- Missing cleanup on event listeners, intervals, handles
122- Unnecessary serialization/deserialization
123
124### 7. Error Handling & Observability
125
126#### Standard (always run)
127- `bash("sg -p \"catch ($$$) { $$$ }\" -l ts .")` — catch blocks
128- `grep("catch.*{}|catch.*{\\s*}")` — empty catch blocks
129- `grep("console.error|logger\\.error|log\\.error")` — actual error logging
130- `bash("sg -p \"throw new $ERR($$$)\" -l ts .")` — error types used
131
132#### What to flag
133- Empty catch blocks (worst offense)
134- Generic `catch (e) { console.error(e) }` without recovery
135- Inconsistent error shapes across modules
136- Missing structured logging on critical paths
137- Errors swallowed in promise chains (`.catch(() => {})`)
138
139### 8. Security Hygiene
140
141#### Standard (always run)
142- `grep("api[Kk]ey|api_secret|password|secret|token|credential")` in source files (not config or env)
143- `grep("SELECT .* FROM|INSERT INTO|UPDATE.*SET|DELETE FROM")` — SQL construction
144- `grep("innerHTML|dangerouslySetInnerHTML")` — XSS vectors
145- `grep("eval\\(|Function\\(|setTimeout\\(.*string|setInterval\\(.*string")` — code injection
146
147#### What to flag
148- Hardcoded secrets in source
149- String-concatenated SQL
150- `innerHTML` / `dangerouslySetInnerHTML` usage
151- `eval()` or string-based `setTimeout`/`setInterval`
152- Permissive CORS or auth middleware
153
154### 9. Documentation Drift
155
156#### Standard (always run)
157- `read("README.md")` — check if claims match reality
158- `grep("@param|@returns|@throws")` — docstring coverage
159- `grep("FIXME|TODO|HACK|XXX|WORKAROUND")` — fixme density
160- Compare README API examples with actual signatures
161
162#### What to flag
163- README claiming features that don't exist
164- Public functions without any doc comment
165- Comments that contradict the code
166- Stale architecture decision records (ADRs) if present
167
168## Phase 2: Deeper Dives (Parallel Sub-Agents)
169
170For large codebases (>50k LOC), delegate heavy dimensions to parallel sub-agents. Each sub-agent runs the standard tool passes for its dimensions:
171
172```
173task(category="unspecified-low", run_in_background=true, load_skills=[], prompt="[CONTEXT] Tech debt audit. [GOAL] Audit dimensions 1 (Architecture) and 2 (Consistency). [REQUEST] Run ast_grep and grep searches for dimensions 1-2 from the tech-debt-audit skill. Report every finding with file:line:col. Tag severity: Critical/High/Medium/Low.")
174task(category="unspecified-low", run_in_background=true, load_skills=[], prompt="[CONTEXT] Tech debt audit. [GOAL] Audit dimensions 3 (Type debt) and 7 (Error handling). [REQUEST] Run searches for dimensions 3 and 7 from the tech-debt-audit skill. Report every finding with file:line:col. Tag severity.")
175```
176
177Spawn 2-3 sub-agents for the heaviest dimensions, collect results in parallel, then synthesize.
178
179## Phase 3: Synthesize & Deliver
180
1811. Collect all findings from direct tool calls and sub-agent results
1822. Deduplicate — same issue mentioned by multiple dimensions
1833. Classify severity:
184 - **Critical** — Causes incorrect behavior, data loss, or security vulnerability
185 - **High** — Will cause problems in production; blocks maintenance
186 - **Medium** — Reduces maintainability; violates conventions
187 - **Low** — Cosmetic; should fix when in the area
1884. Estimate effort in hours per finding (conservative)
1895. Write `TECH_DEBT_AUDIT.md` with all required sections
1906. Report summary to the user
191
192## Severity Rubric
193
194```
195Critical = actively causing bugs or security holes
196High = will cause problems under normal operation; blocks changes
197Medium = reduces maintainability; inconsistent; violates team conventions
198Low = cosmetic; would be nice to fix when nearby
199```
200
201## Quick Checks Before Finishing
202
203- [ ] Every concrete finding has `file:line:col` citation
204- [ ] No generic claims without evidence
205- [ ] "Looks Bad But Is Fine" section explains at least 2-3 patterns
206- [ ] Top 5 priorities ranked by impact/effort
207- [ ] Quick wins are things that can be fixed in <30 minutes each