040-discovery · diff

git:20260706.8f94af3 to git:20260822.79aa398

6 added, 6 removed. Audit A to A.

---
description: "When the user types /discovery or requests quality analysis, code audit, or issue detection"
globs: ""
alwaysApply: false
---
# Discovery — Quality Analysis & Issue Detection
Systematic quality discovery that runs modular probes adapted to the project's tech stack, presents findings interactively, and creates VCS issues for confirmed problems.
## Invocation
- **Standalone** (`/discovery [scope]`): Full flow with interactive triage (Phases 0-5 + Phase 6 stats)
- **Embedded** (from session-end when `discovery-on-close: true`): Phases 0-3 only, returns structured JSON to caller
Scope accepts: `all` (default), `code`, `infra`, `ui`, `arch`, `session`, `audit`, `vault`, `feature`, or comma-separated like `code,session`.
## Phase 0: Read Session Config
Read Session Config from CLAUDE.md. Parse discovery-specific fields:
- `discovery-probes`, `discovery-exclude-paths`, `discovery-severity-threshold`, `discovery-confidence-threshold`, `discovery-on-close`
## Phase 1: Stack Detection
Detect the project's tech stack via marker file checks (Glob):
| Marker File(s) | Activates |
|----------------|-----------|
| `package.json` | JS/TS probes |
| `tsconfig.json` | TypeScript probes |
| `requirements.txt` / `pyproject.toml` | Python probes |
| `Dockerfile` / `docker-compose.yml` | Container probes |
| `.github/workflows/` | GitHub CI probes |
| `.gitlab-ci.yml` | GitLab CI probes |
| `next.config.*` / `nuxt.config.*` | SSR probes |
| `tailwind.config.*` | Tailwind probes |
| `.orchestrator/` exists | Session probes |
Build activation set: start with marker-matched probes → intersect `discovery-probes` config (if set) → restrict to scope argument (if passed).
Default exclude paths (always apply): `node_modules/`, `.git/`, `dist/`, `build/`, `.next/`, `.nuxt/`, `coverage/`. Add paths from `discovery-exclude-paths`.
Report: "Discovery: [N] probes active across [categories]. Stack: [detected]. Threshold: [severity]."
## Phase 2: Probe Execution
Run probes **sequentially** — Cursor has no parallel agents. One category at a time. Complete each category's analysis before moving to the next.
### 6 Probe Categories
**Code probes** (any project with source files):
- `hardcoded-values`, `orphaned-annotations`, `dead-code`, `ai-slop`, `type-safety-gaps`, `test-coverage-gaps`, `test-anti-patterns`, `security-basics`
**Infra probes** (when CI/Docker markers found):
- CI configuration issues, Dockerfile anti-patterns
**UI probes** (when frontend frameworks detected):
- Accessibility gaps, component anti-patterns
**Arch probes** (any project):
- Circular dependencies, complexity hotspots, deep nesting
**Session probes** (when `.orchestrator/` exists):
- Session metric anomalies, recurring failures, stale learnings
For each probe match, record a finding in this exact format:
```
FINDING:
probe: <probe_name>
category: <category>
severity: <critical|high|medium|low>
file_path: <absolute path>
line_number: <number>
matched_text: <exact text from tool output>
title: <short title>
description: <1-2 sentence description>
recommended_fix: <concrete fix suggestion>
```
If a probe's activation condition is not met, skip with note. If a probe command fails, skip gracefully and continue.
**CRITICAL**: Do NOT fabricate findings. Only report what tool output confirms.
### Key Detection Patterns
| Probe | Severity | Pattern |
|-------|----------|---------|
| Hardcoded secrets | Critical | `(password\|api_key\|secret\|token)\s*[:=]\s*["'][^"']+["']` (exclude test/env/fixtures) |
| eval usage | High | `eval\s*\(` |
| XSS (React) | High | `dangerouslySetInnerHTML` |
| SQL injection | High | `` `[^`]*SELECT[^`]*\$\{`` |
| any type | Medium | `:\s*any\b` or `as\s+any\b` |
| TS suppression | Medium | `@ts-ignore` |
| AI filler | Medium | `(as you can see\|it's worth noting\|needless to say)` |
## Phase 3: Verification & Scoring
### 3.1 Verify Each Finding
For EACH finding: read the file at `file_path:line_number`. Confirm `matched_text` appears at or near that line (+/-3 lines tolerance). If NOT confirmed, discard as false positive.
Report: "Verification: N confirmed, M discarded as false positives"
### 3.2 Confidence Scoring
Start at 40 baseline, add factor scores, clamp to 0-100. Critical severity findings always get minimum 70.
| Factor | Low (+0) | Medium (+10) | High (+20) |
|--------|----------|-------------|------------|
| Pattern specificity | Generic (URL, TODO) | Moderate (orphaned annotation) | Specific (API key regex, eval()) |
| File context | Test/example/docs | Utility/config/scripts | Production source/API handler |
| Historical signal | Previously dismissed | No prior data | Recurring issue |
Read `discovery-confidence-threshold` from config (default: 60).
### 3.3 Deduplication
Same `file_path` + overlapping line range (+/-5 lines) + different probes = duplicate. Keep higher severity finding.
### 3.4 Apply Thresholds
Remove findings below `discovery-severity-threshold` and below `discovery-confidence-threshold`. Log auto-dismissed count.
### 3.5 Embedded Mode Exit
If in embedded mode (called from session-end): STOP HERE. Return this JSON schema:
```json
{
"findings": [
{"probe": "string", "category": "string", "severity": "critical|high|medium|low",
"confidence": 0, "file": "string", "line": 0, "description": "string", "recommendation": "string"}
],
"stats": {
"probes_run": 0, "findings_raw": 0, "verified": 0,
"false_positives": 0, "by_category": {"<category>": {"findings": 0}}
}
}
```
## Phase 4: Interactive Triage (Standalone Only)
Use **numbered Markdown lists** for all choices — Cursor does not have AskUserQuestion.
### Step 1: Summary Table
```
## Discovery Results
Probes run: [N] | Findings verified: [N] | False positives discarded: [N]
| Category | Critical | High | Medium | Low | Total |
|----------|----------|------|--------|-----|-------|
| Code | ... | ... | ... | ... | ... |
| Infra | ... | ... | ... | ... | ... |
| UI | ... | ... | ... | ... | ... |
| Arch | ... | ... | ... | ... | ... |
| Session | ... | ... | ... | ... | ... |
| Audit | ... | ... | ... | ... | ... |
| Vault | ... | ... | ... | ... | ... |
| Feature | ... | ... | ... | ... | ... |
```
### Step 2: Critical + High Findings — Review Individually
For each Critical or High finding, present with file context (+/-3 lines):
```
[CRITICAL] (confidence: 85) hardcoded-values: API key found in src/config.ts:42
<file context>
Recommended fix: <suggestion>
Options:
1. Create issue (critical)
2. Adjust priority
3. Dismiss — intentional
4. Dismiss — false positive
```
### Step 3: Medium + Low Findings — Review Batched
```
[N] medium/low findings in [category]:
1. [title] — [file_path]:[line] ([severity])
Options:
- 1. Accept all (Recommended) — create issues for all
- 2. Review individually
- 3. Dismiss all
+ 1. Accept all (Recommended) — one issue per finding. Fastest, and you can still close any of them later.
+ 2. Review individually — decide finding by finding. Costs about a minute per item.
+ 3. Dismiss all — no issues created, and the findings are gone when this session ends.
```
### Step 4: Batch Confirmation
```
Ready to create [N] issues? ([X] critical, [Y] high, [Z] medium, [W] low)
- 1. Create all [N] issues (Recommended)
- 2. Review list first
- 3. Cancel
+ 1. Create all [N] issues (Recommended) — the list is already filtered, so nothing here is noise. You can close any of them later.
+ 2. Review list first — read the titles before anything is written. Costs one extra step.
+ 3. Cancel — nothing is written, and this run's findings are not kept.
```
## Phase 5: Issue Creation
For each approved finding:
1. Format using gitlab-ops discovery issue template
2. Labels: `type:discovery` + `priority:<level>` + `area:<inferred>` + `status:ready`
3. **GitLab**: `glab issue create --title "[Discovery] <title>" --label "type:discovery,priority:<level>,area:<area>,status:ready" --description "<body>"`
4. **GitHub**: `gh issue create --title "[Discovery] <title>" --label "..." --body "<body>"`
5. Brief pause (1s) between creations
### Final Report
```
## Discovery Report
- Probes run: [N] across [categories]
- Verified: [N] (false positives: [M])
- User approved: [N]
- Issues created: [N]
| # | Title | Priority | Area | Probe |
|---|-------|----------|------|-------|
```
## Phase 6: Capture Stats (Standalone Only)
After Phase 5, prepare stats for session metrics (do NOT write to `sessions.jsonl` directly — session-end handles that):
- `probes_run`, `findings_raw`, `findings_verified`, `false_positives`, `user_dismissed`, `issues_created`, `by_category`
Report: "Discovery stats: [probes_run] probes, [findings_raw] raw → [findings_verified] verified ([false_positives] false positives). Created [issues_created] issues."
## Critical Rules
- **NEVER** fabricate findings — every finding must come from tool output with verifiable evidence
- **NEVER** create issues without user approval (standalone mode)
- **ALWAYS** verify findings by re-reading the file at the reported line (Phase 3)
- **ALWAYS** use numbered Markdown lists for choices — Cursor has no AskUserQuestion
- If a probe command fails, skip gracefully, continue with others
- If in embedded mode, stop after Phase 3, return findings as structured JSON
- Default exclude paths always apply