Paths: File paths (
references/,../ln-*) are relative to this skill directory.
Resource Lifecycle Auditor (L3 Worker)
Type: L3 Worker
Specialized worker auditing resource acquisition/release patterns, scope mismatches, and connection pool hygiene.
Purpose & Scope
- Audit resource lifecycle (Priority: HIGH)
- Check session/connection scope mismatch, streaming endpoint resource holding, cleanup patterns, pool config
- Write structured findings to file with severity, location, effort, recommendations
- Calculate compliance score (X/10) for Resource Lifecycle category
Inputs
MANDATORY READ: Load references/audit_worker_core_contract.md.
Tool policy: follow host AGENTS.md MCP preferences; load references/mcp_tool_preferences.md and references/mcp_integration_patterns.md only when host policy is absent or MCP behavior is unclear.
Receives contextStore with: tech_stack, best_practices, db_config (database type, ORM settings, pool config, session factory), codebase_root, output_dir.
Domain-aware: Supports domain_mode + current_domain.
Use hex-graph first when reference chains or call paths materially improve lifecycle findings. Use hex-line first for local code/config reads when available. If MCP is unavailable, unsupported, or not indexed, continue with built-in Read/Grep/Glob/Bash and state the fallback in the report.
Workflow
Detection policy: use two-layer detection (candidate scan, then context verification); load references/two_layer_detection.md only when the verification method is ambiguous.
-
Parse context from contextStore
- Extract tech_stack, best_practices, db_config, output_dir
- Determine scan_path
-
Detect DI framework
- FastAPI
Depends(), Django middleware, Spring@Autowired/@PersistenceContext, Express middleware, Go wire/fx
- FastAPI
-
Discover resource infrastructure
- Find session/connection factory patterns (
sessionmaker,create_engine,DataSource, pool creation) - Find DI registration (
Depends(),@Inject, providers, middleware mounting) - Find streaming endpoints (SSE, WebSocket, long-poll, streaming response)
- Map: which endpoints receive which resources via DI
- Find session/connection factory patterns (
-
Scan codebase for violations (6 checks)
- Trace resource injection -> usage -> release across endpoint lifetime
- Analyze streaming endpoints for held resources
- Check error paths for cleanup
-
Collect findings with severity, location, effort, recommendation
-
Calculate score using penalty algorithm
-
Write Report: Build full markdown report in memory per
references/templates/audit_worker_report_template.md, write to{output_dir}/ln-654--global.mdin single Write call -
Return Summary: Return minimal summary to coordinator (see Output Format)
Audit Rules (Priority: HIGH)
1. Resource Scope Mismatch
What: Resource injected via DI lives for entire request/connection scope but is used for only a fraction of it.
Detection (Python/FastAPI):
- Step 1 - Find endpoints with DB session dependency:
- Grep:
async def\s+\w+\(.*Depends\(get_db\)|Depends\(get_session\)|db:\s*AsyncSession|session:\s*AsyncSession
- Grep:
- Step 2 - Measure session usage span within endpoint body:
- Count lines between first and last
session\.|db\.|await.*repousage - Count total lines in endpoint function body
- Count lines between first and last
- Step 3 - Flag if
usage_lines / total_lines < 0.2(session used in <20% of function body)- Especially: session used only at function start (auth check, initial load) but function continues with non-DB work
Detection (Node.js/Express):
- Middleware injects
req.dborreq.knexat request start - Grep:
app\.use.*pool|app\.use.*knex|app\.use.*prisma(middleware injection) - Route handler uses
req.dbonly in first 20% of function body
Detection (Java/Spring):
@Transactionalon method with long non-DB processingEntityManagerinjected but used only briefly- Grep:
@Autowired.*EntityManager|@PersistenceContext+ method body analysis
Detection (Go):
sql.DBor*gorm.DBpassed to handler, used once, then long processing- Grep:
func.*Handler.*\*sql\.DB|func.*Handler.*\*gorm\.DB
Severity:
- CRITICAL: Session scope mismatch in streaming endpoint (SSE, WebSocket) - session held for minutes/hours
- HIGH: Session scope mismatch in endpoint with external API calls (session held during network latency)
- MEDIUM: Session scope mismatch in endpoint with >50 lines of non-DB processing
Recommendation: Extract DB operations into scoped function; acquire session only for the duration needed; use async with get_session() as session: block instead of endpoint-level DI injection.
Effort: M (refactor DI to scoped acquisition)
2. Streaming Endpoint Resource Holding
What: SSE, WebSocket, or long-poll endpoint holds DB session/connection for stream duration.
Detection (Python/FastAPI):
- Step 1 - Find streaming endpoints:
- Grep:
StreamingResponse|EventSourceResponse|SSE|async def.*websocket|@app\.websocket - Grep:
yield\s+.*event|yield\s+.*data:|async for.*yield(SSE generator pattern)
- Grep:
- Step 2 - Check if streaming function/generator has DB session in scope:
- Session from
Depends()in endpoint signature -> held for entire stream - Session from context manager inside generator -> scoped (OK)
- Session from
- Step 3 - Analyze session usage inside generator:
- If session used once at start (auth/permission check) then stream loops without DB -> scope mismatch
Detection (Node.js):
- Grep:
res\.write\(|res\.flush\(|Server-Sent Events|new WebSocket|ws\.on\( - Check if connection/pool client acquired before stream loop and not released
Detection (Java/Spring):
- Grep:
SseEmitter|WebSocketHandler|StreamingResponseBody - Check if
@Transactionalwraps streaming method
Detection (Go):
- Grep:
Flusher|http\.Flusher|websocket\.Conn - Check if
*sql.DBor transaction held during flush loop
Severity:
- CRITICAL: DB session/connection held for entire SSE/WebSocket stream duration (pool exhaustion under load)
- HIGH: DB connection held during long-poll (>30s timeout)
Recommendation: Move auth/permission check BEFORE stream: acquire session, check auth, release session, THEN start streaming. Use separate scoped session for any mid-stream DB access.
Effort: M (restructure endpoint to release session before streaming)
3. Missing Resource Cleanup Patterns
What: Resource acquired without guaranteed cleanup (no try/finally, no context manager, no close()).
Detection (Python):
- Grep:
session\s*=\s*Session\(\)|session\s*=\s*sessionmaker|engine\.connect\(\)NOT insidewithorasync with - Grep:
connection\s*=\s*pool\.acquire\(\)|conn\s*=\s*await.*connect\(\)NOT followed bytry:.*finally:.*close\(\) - Pattern: bare
session = get_session()without context manager - Safe patterns to exclude:
async with session_factory() as session:,with engine.connect() as conn:
Detection (Node.js):
- Grep:
pool\.connect\(\)|knex\.client\.acquireConnection|\.getConnection\(\)without corresponding.release()or.end()in same function - Grep:
createConnection\(\)without.destroy()in try/finally
Detection (Java):
- Grep:
getConnection\(\)|dataSource\.getConnection\(\)without try-with-resources - Pattern:
Connection conn = ds.getConnection()withouttry (Connection conn = ...)syntax
Detection (Go):
- Grep:
sql\.Open\(|db\.Begin\(\)withoutdefer.*Close\(\)|defer.*Rollback\(\) - Pattern:
tx, err := db.Begin()withoutdefer tx.Rollback()
Severity:
- HIGH: Session/connection acquired without cleanup guarantee (leak on exception)
- MEDIUM: File handle or cursor without cleanup in non-critical path
Exception: Session acquired and released before streaming/long-poll begins -> skip. NullPool / pool_size config documented as serverless design -> skip.
**Recommendati