projscan 4.0.0 → 4.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.
Files changed (39) hide show
  1. package/README.md +480 -24
  2. package/dist/cli/commands/route.js +1 -0
  3. package/dist/cli/commands/route.js.map +1 -1
  4. package/dist/cli/commands/semanticGraph.js +27 -0
  5. package/dist/cli/commands/semanticGraph.js.map +1 -1
  6. package/dist/cli/commands/start.js +1095 -2
  7. package/dist/cli/commands/start.js.map +1 -1
  8. package/dist/core/dependencyAnalyzer.js +172 -0
  9. package/dist/core/dependencyAnalyzer.js.map +1 -1
  10. package/dist/core/intentRouter.d.ts +8 -1
  11. package/dist/core/intentRouter.js +2186 -22
  12. package/dist/core/intentRouter.js.map +1 -1
  13. package/dist/core/issueEngine.js +6 -7
  14. package/dist/core/issueEngine.js.map +1 -1
  15. package/dist/core/onboarding.d.ts +2 -2
  16. package/dist/core/onboarding.js +29 -5
  17. package/dist/core/onboarding.js.map +1 -1
  18. package/dist/core/start.d.ts +1 -0
  19. package/dist/core/start.js +3047 -10
  20. package/dist/core/start.js.map +1 -1
  21. package/dist/mcp/server.d.ts +1 -1
  22. package/dist/mcp/server.js +14 -5
  23. package/dist/mcp/server.js.map +1 -1
  24. package/dist/mcp/tools/start.js +6 -1
  25. package/dist/mcp/tools/start.js.map +1 -1
  26. package/dist/projscan-sbom.cdx.json +6 -6
  27. package/dist/reporters/consoleReporter.js +19 -0
  28. package/dist/reporters/consoleReporter.js.map +1 -1
  29. package/dist/reporters/markdownReporter.js +19 -0
  30. package/dist/reporters/markdownReporter.js.map +1 -1
  31. package/dist/tool-manifest.json +6 -2
  32. package/dist/types.d.ts +275 -0
  33. package/docs/GUIDE.md +1567 -0
  34. package/docs/ROADMAP.md +219 -0
  35. package/docs/demos/projscan-4-1-demo.html +677 -0
  36. package/docs/projscan-mission-control.png +0 -0
  37. package/docs/projscan-proof-router.png +0 -0
  38. package/package.json +8 -1
  39. package/scripts/capture-readme-assets.mjs +60 -0
package/docs/GUIDE.md ADDED
@@ -0,0 +1,1567 @@
1
+ # ProjScan - Full Guide
2
+
3
+ A deep dive into everything ProjScan can do. For a quick overview, see the [README](../README.md).
4
+
5
+ **ProjScan is agent-first**: the MCP server is the primary interface, and the CLI is a consumer of the same primitives. This guide covers both, but if you're integrating with Claude Code / Cursor / Windsurf / Codex, start with [MCP Server for AI Agents](#mcp-server-for-ai-agents).
6
+
7
+ ---
8
+
9
+ ## Table of Contents
10
+
11
+ - [Installation](#installation)
12
+ - [Your First Scan](#your-first-scan)
13
+ - [The agent journey](#the-agent-journey)
14
+ - [Commands In Depth](#commands-in-depth)
15
+ - [analyze](#analyze)
16
+ - [doctor](#doctor)
17
+ - [hotspots](#hotspots)
18
+ - [semantic-graph](#semantic-graph)
19
+ - [dataflow](#dataflow)
20
+ - [search](#search)
21
+ - [file](#file)
22
+ - [ci](#ci)
23
+ - [diff](#diff)
24
+ - [fix](#fix)
25
+ - [explain](#explain)
26
+ - [diagram](#diagram)
27
+ - [structure](#structure)
28
+ - [dependencies](#dependencies)
29
+ - [outdated](#outdated)
30
+ - [audit](#audit)
31
+ - [upgrade](#upgrade)
32
+ - [coverage](#coverage)
33
+ - [badge](#badge)
34
+ - [mcp](#mcp)
35
+ - [dogfood](#dogfood)
36
+ - [Health Score](#health-score)
37
+ - [Output Formats](#output-formats)
38
+ - [Console](#console-default)
39
+ - [JSON](#json)
40
+ - [Markdown](#markdown)
41
+ - [HTML](#html)
42
+ - [SARIF](#sarif)
43
+ - [Configuration (`.projscanrc`)](#configuration-projscanrc)
44
+ - [PR-Diff Mode (`--changed-only`)](#pr-diff-mode---changed-only)
45
+ - [Global Options](#global-options)
46
+ - [What ProjScan Detects](#what-projscan-detects)
47
+ - [Languages](#languages)
48
+ - [Frameworks and Libraries](#frameworks-and-libraries)
49
+ - [Issues and Health Checks](#issues-and-health-checks)
50
+ - [Auto-Fix System](#auto-fix-system)
51
+ - [Architecture Diagrams](#architecture-diagrams)
52
+ - [File Explanation Engine](#file-explanation-engine)
53
+ - [Hotspots & Ownership](#hotspots--ownership)
54
+ - [MCP Server for AI Agents](#mcp-server-for-ai-agents)
55
+ - [Performance](#performance)
56
+ - [Common Workflows](#common-workflows)
57
+ - [CI/CD Integration](#cicd-integration)
58
+ - [Troubleshooting](#troubleshooting)
59
+ - [Project Internals](#project-internals)
60
+
61
+ ---
62
+
63
+ ## Installation
64
+
65
+ ### Global install (recommended)
66
+
67
+ ```bash
68
+ npm install -g projscan
69
+ ```
70
+
71
+ After installing, the `projscan` command is available everywhere.
72
+
73
+ ### Run without installing
74
+
75
+ ```bash
76
+ npx projscan
77
+ ```
78
+
79
+ ### Requirements
80
+
81
+ - Node.js >= 18
82
+ - npm, yarn, or pnpm
83
+ - Git (optional - unlocks `hotspots` and `--changed-only`)
84
+
85
+ ---
86
+
87
+ ## Your First Scan
88
+
89
+ Navigate into any repository and run:
90
+
91
+ ```bash
92
+ cd your-project
93
+ projscan
94
+ ```
95
+
96
+ This runs the default `analyze` command. Within a second or two you'll see a full report covering:
97
+
98
+ <img src="https://abhiyoheswaran.com/images/projscan/hero-poster.png" alt="npx projscan: banner, scan progress, full project report" width="700">
99
+
100
+ 1. **Project overview** - name, total files, total directories, scan time
101
+ 2. **Language breakdown** - primary language, percentages per language
102
+ 3. **Frameworks detected** - with confidence levels and categories
103
+ 4. **Dependency summary** - production vs. dev count, package manager, lock file status
104
+ 5. **Issues found** - grouped by severity (error, warning, info)
105
+
106
+ ---
107
+
108
+ ## The agent journey
109
+
110
+ projscan is structured around the four questions an AI coding agent (or a careful human reviewer) asks at every code-change moment. Each phase has a small set of tools that compose well; the deeper reference for each tool is in the [Commands In Depth](#commands-in-depth) section below. Mapping the question to the tool is what this section is for.
111
+
112
+ ### 1. Diagnose — "what's wrong here?"
113
+
114
+ When the agent first opens a repo, or before starting a refactor, the question is: *is anything obviously broken or risky?*
115
+
116
+ - **`projscan privacy-check`** — trust boundary report. Shows telemetry/offline status, scan root, Git ignore handling, `.env` content handling, plugin execution status, local write surfaces, report-export sensitivity, and network-capable endpoints.
117
+ - **`projscan_start` / `projscan start`** — first-60-seconds workflow orientation. Composes setup diagnostics, Mission Control, the recommended workflow recipe, `firstTenMinutes`, workplan, quality scorecard, top risks, adoption gaps, repeat-use metrics, next commands, optional handoff payload, and a split between current Git/worktree evidence and remembered session context. Pass `intent` / `--intent "<goal>"` when the developer or agent wants one routed action plan with route confidence, immediately callable `readyActions`, and proof commands, such as `projscan start --intent "what breaks if I rename this API?"`. For fuzzy impact targets, Mission Control searches first, then gives symbol and file impact follow-ups for the search result. For exact symbols or paths, such as `projscan start --intent "what breaks if I change src/core/start.ts?"`, `projscan start --intent "where is runAudit used?"`, `projscan start --intent "what depends on src/core/start.ts?"`, or `projscan start --intent "can I delete src/core/start.ts?"`, it runs impact directly. For repo-orientation questions, such as `projscan start --intent "summarize this repo"`, `projscan start --intent "what files should I read first?"`, `projscan start --intent "where do I start in this codebase?"`, `projscan start --intent "give me a tour of the repo"`, or `projscan start --intent "explain the architecture"`, it routes to `projscan_understand --view map` so the developer gets cited read-first files, entrypoints, boundaries, risks, and unknowns. For public surface questions, such as `projscan start --intent "what are the public contracts?"` or `projscan start --intent "how do I safely deprecate this API?"`, it routes to `projscan_understand --view contracts` so public exports, config contracts, and likely breaking-change risks are reviewed before touching API surfaces. For API breakage questions, such as `projscan start --intent "what will this API change break?"`, it searches for the exact public symbol or file before continuing to impact analysis. For broad quality/risk questions, such as `projscan start --intent "what is risky in this repo?"`, it routes to `projscan_quality_scorecard` so health, security, tests, maintainability, coordination, and top risks are reviewed before choosing work. For file-orientation questions, such as `projscan start --intent "what should I read before changing src/core/start.ts?"`, `projscan start --intent "explain src/core/start.ts"`, `projscan start --intent "who owns src/core/start.ts?"`, `projscan start --intent "who should review src/core/start.ts?"`, or `projscan start --intent "who last touched src/core/start.ts?"`, it routes to `projscan_file` so the developer sees purpose, imports, exports, ownership, history, reviewer context, and risk before editing. For targeted graph questions, such as `projscan start --intent "who imports src/core/start.ts?"`, it routes to `projscan_semantic_graph` query mode instead of dumping the full graph. For security source-to-sink questions, such as `projscan start --intent "is user input reaching SQL sinks?"`, it routes to `projscan_dataflow` and infers the `hardening` workflow. For coverage-gap questions, such as `projscan start --intent "what are the scariest untested files?"`, it routes to `projscan_coverage` so the next test target is chosen by risk. For dependency inventory questions, such as `projscan start --intent "what dependencies does this repo use?"`, it routes to `projscan_dependencies` instead of an upgrade preview. For dependency vulnerability questions, such as `projscan start --intent "does lodash have a CVE?"`, `projscan start --intent "what CVEs affect this repo?"`, or `projscan start --intent "find vulnerable packages"`, it routes to `projscan_audit`, scoped with `--package` when the package can be inferred. For package-bump or package-update questions, such as `projscan start --intent "what breaks if I bump chalk to 6?"` or `projscan start --intent "what breaks if I update react?"`, it routes to `projscan_upgrade`; if no package is named, Mission Control runs `projscan outdated --format json` first and marks the package name as `Needs Input`. For "what changed in this PR?", it routes to `projscan_pr_diff` before full review. For "what should I fix first?" or "what is the fastest safe fix?", it routes to `projscan_bug_hunt` instead of issue-specific fix-suggest or generic preflight. For open-ended next-step questions, such as `projscan start --intent "what should I do next?"`, it routes to `projscan_workplan --mode before_edit` so the developer gets an ordered plan with verification before editing. For "give the next agent a handoff", it routes to `projscan_agent_brief` with `intent: "next_agent"`. For issue context, such as `projscan start --intent "explain issue missing-test-framework"`, it routes to `projscan_explain_issue`; if no issue id is named, Mission Control runs `projscan doctor --format json` first and marks the issue id as `Needs Input`. For direct issue repair, such as `projscan start --intent "fix issue missing-test-framework"`, it routes to `projscan_fix_suggest`; if no issue id is named, Mission Control runs `projscan doctor --format json` first and marks the fix-suggest issue id as `Needs Input`. For failing CI or tests, such as `projscan start --intent "CI is failing after this PR"`, it routes to `projscan_regression_plan` with a focused verification plan. For right-sized verification questions, such as `projscan start --intent "what smoke checks should I run before commit?"` or `projscan start --intent "what full regression should I run before merge?"`, Mission Control preserves the requested `smoke` or `full` regression depth.
118
+ For rollback and revert questions, such as `projscan start --intent "revert src/core/start.ts safely"` or `projscan start --intent "how do I revert this change safely?"`, it routes to `projscan_impact`; exact files run impact directly, while vague rollback phrasing searches for the target before impact continues.
119
+ For package usage questions, such as `projscan start --intent "who uses lodash?"`, `projscan start --intent "what depends on lodash?"`, or `projscan start --intent "why do we depend on lodash?"`, it routes to `projscan_semantic_graph --query package_importers` so importers are known before removal or upgrade work starts.
120
+ For bundle-size and dependency-bloat questions, such as `projscan start --intent "why is the bundle so large?"`, `projscan start --intent "reduce bundle size"`, or `projscan start --intent "find package bloat"`, it routes to `projscan_dependencies`, whose report includes installed package-size totals and largest local packages when `node_modules` metadata is available.
121
+ For dependency license and compliance questions, such as `projscan start --intent "what licenses do our dependencies use?"`, `projscan start --intent "third party notices"`, or `projscan start --intent "open source compliance check"`, it routes to `projscan_dependencies`, whose report includes local `node_modules` license counts, unknown licenses, notice candidates, and copyleft risks when installed package metadata is available.
122
+ For monorepo workspace questions, such as `projscan start --intent "what workspaces are in this repo?"`, `projscan start --intent "which workspace owns auth?"`, or `projscan start --intent "where should I put this in the monorepo?"`, it routes to `projscan_workspaces` so package names and paths are known before package-scoped work begins.
123
+ For trust-boundary questions, such as `projscan start --intent "what can projscan read?"`, `projscan start --intent "does projscan read .env values?"`, or `projscan start --intent "will projscan upload my code?"`, it routes to `projscan privacy-check --offline` so telemetry, offline mode, scan root, ignored-file handling, `.env` content policy, plugin execution, local writes, and network-capable endpoints are reviewed before broader analysis.
124
+ For project-run and setup questions, such as `projscan start --intent "how do I run this project?"`, `projscan start --intent "what command starts the dev server?"`, or `projscan start --intent "how do I set up this repo locally?"`, it routes to `projscan_understand --view map` so entrypoints, read-first files, boundaries, risks, and unknowns guide first local execution. Package script discovery such as `projscan start --intent "what npm scripts exist?"`, `projscan start --intent "which script runs e2e tests?"`, `projscan start --intent "what command runs lint?"`, or `projscan start --intent "how do I run typecheck?"` routes to `projscan_understand --view contracts` instead of dependency freshness or regression debugging. Failure wording such as `projscan start --intent "e2e tests are failing"` or `projscan start --intent "lint is failing"` still routes to focused regression planning.
125
+ For local database setup commands, such as `projscan start --intent "how do I seed the database?"`, `projscan start --intent "what command resets the database?"`, or `projscan start --intent "what command runs migrations?"`, it routes to `projscan_understand --view contracts` so package scripts and config contracts are reviewed before guessing shell commands.
126
+ For feature-placement and change-planning questions, such as `projscan start --intent "where should I put this new feature?"`, `projscan start --intent "implement OAuth login"`, `projscan start --intent "add billing webhook support"`, `projscan start --intent "where should I add a new endpoint?"`, or `projscan start --intent "what files do I need to change for auth?"`, it routes to `projscan_understand --view change` so change-readiness risks, likely touched files, blast radius, and verification tiers are reviewed before editing.
127
+ For documentation-change questions, such as `projscan start --intent "what docs should I update for this change?"` or `projscan start --intent "does this change need docs?"`, it also routes to `projscan_understand --view change` instead of package upgrade.
128
+ For database migration and schema-planning questions, such as `projscan start --intent "where should I add this database migration?"` or `projscan start --intent "does this change need a migration?"`, it routes to `projscan_understand --view change`; migration inventory wording such as `projscan start --intent "which migrations exist?"` or `projscan start --intent "what migration files exist?"` routes to focused search; destructive schema wording such as `projscan start --intent "what breaks if I change the schema?"` or `projscan start --intent "can I drop this column?"` routes to impact analysis and searches first when no exact target is named.
129
+ For API deprecation and breakage questions, such as `projscan start --intent "how do I safely deprecate this API?"` or `projscan start --intent "what will this API change break?"`, it separates contract discovery from blast-radius analysis: deprecation starts with `projscan_understand --view contracts`, while broad breakage searches for the exact API target before impact continues.
130
+ For repo env-var requirement questions, such as `projscan start --intent "what env vars does this repo need?"`, it routes to `projscan_understand --view contracts` so environment/config reads are treated as repo contracts instead of trust-boundary questions about projscan itself.
131
+ For exact env-var lookup questions, such as `projscan start --intent "where is NEXT_PUBLIC_API_URL used?"`, `projscan start --intent "find process.env.NODE_ENV"`, or `projscan start --intent "which env var controls auth?"`, it routes to `projscan_search` with a focused env query before broader impact or dataflow tools run.
132
+ For missing setup/config wording, such as `projscan start --intent "environment variables missing"`, it also routes to `projscan_understand --view contracts`.
133
+ For local setup blockers, such as `projscan start --intent "port 3000 already in use"`, `projscan start --intent "EADDRINUSE on startup"`, `projscan start --intent "permission denied when running dev server"`, `projscan start --intent "ENOENT package.json missing"`, or `projscan start --intent "peer dependency conflict after npm install"`, it routes to `projscan_regression_plan --level focused` so the failing local command and smallest rerun proof are chosen before package or config rabbit holes.
134
+ For config-file lookup questions, such as `projscan start --intent "where is eslint config?"`, `projscan start --intent "find vite config"`, or `projscan start --intent "which config file defines aliases?"`, it routes to `projscan_search` with a focused config query. For build/tooling config lookup, such as `projscan start --intent "where is tsconfig path aliases configured?"`, `projscan start --intent "where is Vitest config?"`, `projscan start --intent "find Babel config"`, `projscan start --intent "where is package manager configured?"`, or `projscan start --intent "where is pnpm workspace file?"`, it routes to `projscan_search` with focused tsconfig-alias, test-runner/Babel/Webpack config, package-manager, and workspace-file queries instead of treating `file`, `workspace`, `package`, or `vitest` as file inspection, workspace inventory, dependency inventory, or issue explanation. Failure wording such as `projscan start --intent "why is vitest failing"` still routes to regression planning, and script inventory such as `projscan start --intent "what npm scripts exist"` still routes to contract orientation.
135
+ For blocker-discovery questions, such as `projscan start --intent "what is blocking this PR?"`, it routes to `projscan_preflight --mode before_commit` so blockers, owners, and follow-up commands are surfaced before review continues.
136
+ For code-location questions, such as `projscan start --intent "what code handles billing?"`, `projscan start --intent "which file contains checkout logic?"`, `projscan start --intent "find the Stripe webhook handler"`, `projscan start --intent "find the handler for POST /api/users"`, `projscan start --intent "where is the /checkout route handled?"`, `projscan start --intent "which feature flags exist?"`, or `projscan start --intent "show me generated files"`, it routes to `projscan_search` with a focused code query before deeper inspection.
137
+ For frontend page-route lookup, such as `projscan start --intent "where is /settings page rendered?"`, `projscan start --intent "which page renders /billing?"`, `projscan start --intent "where is route segment for dashboard?"`, or `projscan start --intent "where is not-found page handled?"`, it routes to `projscan_search` with focused URL page, route-segment, and not-found-page queries instead of losing page context to a generic route-path search. Runtime troubleshooting wording such as `projscan start --intent "why is /settings returning 404?"` still routes to regression planning.
138
+ For authorization lookup, such as `projscan start --intent "where are permissions checked for checkout?"`, `projscan start --intent "which role can access admin?"`, `projscan start --intent "where is RBAC defined?"`, or `projscan start --intent "what routes require login?"`, it routes to `projscan_search` with a focused permissions, role, RBAC, or login query instead of treating `defined`, `routes`, or `login` as graph, planning, or incident signals.
139
+ For reliability-control lookup, such as `projscan start --intent "where is rate limiting configured?"`, `projscan start --intent "where is cache invalidated for products?"`, `projscan start --intent "find retry logic for payments"`, `projscan start --intent "what sets request timeout?"`, `projscan start --intent "find idempotency key handling"`, or `projscan start --intent "where is webhook signature verified?"`, it routes to `projscan_search` with focused rate-limit, cache-invalidation, retry, timeout, idempotency, or signature-verification queries instead of treating words like `request`, `failed`, or `used` as dataflow, regression, or impact signals.
140
+ For data-contract and persistence-invariant lookup, such as `projscan start --intent "where is input validation for signup?"`, `projscan start --intent "which schema validates checkout?"`, `projscan start --intent "where are request params parsed?"`, `projscan start --intent "what serializes API response?"`, `projscan start --intent "where is database transaction started?"`, `projscan start --intent "where do we lock the order row?"`, `projscan start --intent "what validates email uniqueness?"`, or `projscan start --intent "what builds pagination cursors?"`, it routes to `projscan_search` with focused validation, parsing, serialization, transaction, locking, uniqueness, or pagination queries instead of treating `schema`, `database`, `request`, `email`, or `lock` as impact, broad understand, dataflow, or claim signals.
141
+ For ORM and data-access lookup, such as `projscan start --intent "where is Prisma model for User?"`, `projscan start --intent "find Drizzle schema for invoices"`, `projscan start --intent "where is SQL query for invoices?"`, `projscan start --intent "which repository saves orders?"`, or `projscan start --intent "find DAO for payments"`, it routes to `projscan_search` with focused Prisma/Drizzle, SQL-query, repository, and DAO queries instead of treating `sql`, `schema`, or `query` as dataflow, validation-contract, or API-query signals. Security wording such as `projscan start --intent "is user input reaching SQL sinks?"` still routes to dataflow, and destructive schema wording such as `projscan start --intent "can I drop this column?"` still routes to impact analysis.
142
+ For UI interaction lookup, such as `projscan start --intent "where is the signup form submitted?"`, `projscan start --intent "where is loading state for dashboard?"`, `projscan start --intent "where is error boundary for settings?"`, `projscan start --intent "find command palette actions"`, `projscan start --intent "what component renders the billing page?"`, `projscan start --intent "where are i18n translations for checkout?"`, or `projscan start --intent "where is aria label for submit button?"`, it routes to `projscan_search` with focused form-submit, loading-state, empty-state, error-boundary, toast, shortcut, command-palette, component, translation, and accessibility queries instead of treating UI vocabulary as privacy, regression, hotspot, or planning signals.
143
+ For styling and design-system lookup, such as `projscan start --intent "where are design tokens defined?"`, `projscan start --intent "where is Tailwind theme configured?"`, `projscan start --intent "where is global CSS imported?"`, `projscan start --intent "which CSS module styles Button?"`, `projscan start --intent "where is dark mode configured?"`, or `projscan start --intent "what breakpoints are defined?"`, it routes to `projscan_search` with focused design-token, Tailwind-theme, global-CSS, CSS-module, dark-mode, and breakpoint queries instead of treating `tokens`, `defined`, `module`, `button`, or `theme` as dataflow, semantic-graph, infra, generic UI, or state-provider signals. Implementation wording such as `projscan start --intent "add dark mode"` still routes to change planning, and failure wording such as `projscan start --intent "why is dark mode failing"` still routes to regression planning.
144
+ For navigation and layout lookup, such as `projscan start --intent "where is sidebar nav item for billing?"`, `projscan start --intent "which breadcrumb renders settings?"`, `projscan start --intent "where is page title set for checkout?"`, or `projscan start --intent "where is Next.js layout for dashboard?"`, it routes to `projscan_search` with focused sidebar/nav, breadcrumb, page-title/metadata, and Next.js-layout queries instead of treating `route`, `page`, `set`, `dashboard`, or `next` as API-route, UI-component, reliability, observability, or planning signals. Implementation wording such as `projscan start --intent "add sidebar nav item"` still routes to change planning.
145
+ For state management and data-fetching lookup, such as `projscan start --intent "where is auth state stored?"`, `projscan start --intent "find Redux slice for cart"`, `projscan start --intent "where is Zustand store for user settings?"`, `projscan start --intent "which context provider supplies theme?"`, `projscan start --intent "which hook fetches invoices?"`, or `projscan start --intent "where is React Query mutation for checkout?"`, it routes to `projscan_search` with focused state-store, Redux/Zustand, provider, hook, and React Query queries instead of treating `store`, `state`, `query`, or `fetch` as dataflow, generic UI state, data-contract, or integration signals. Implementation wording such as `projscan start --intent "implement Redux store"` still routes to change planning, and sensitive storage wording such as `projscan start --intent "where do we store access tokens?"` still routes to dataflow.
146
+ For integration touchpoint lookup, such as `projscan start --intent "where do we call Stripe?"`, `projscan start --intent "which code sends email through SendGrid?"`, `projscan start --intent "where is S3 upload implemented?"`, `projscan start --intent "find GitHub API client"`, `projscan start --intent "where is GraphQL query for invoices?"`, or `projscan start --intent "where is websocket connection opened?"`, it routes to `projscan_search` with focused service/API/client/email/storage/query/socket queries instead of treating words like `github`, `email`, `upload`, `query`, or `connection` as CI, privacy, data-contract, or regression signals.
147
+ For API contract artifact lookup, such as `projscan start --intent "where is OpenAPI spec defined?"`, `projscan start --intent "where is Swagger docs configured?"`, `projscan start --intent "where is tRPC router for billing?"`, `projscan start --intent "which GraphQL resolver handles invoices?"`, `projscan start --intent "which protobuf defines user service?"`, or `projscan start --intent "where is gRPC client for payments?"`, it routes to `projscan_search` with focused OpenAPI, Swagger, tRPC, GraphQL resolver/schema, protobuf/proto, and gRPC queries while broad `public contracts` wording still routes to cited contract orientation.
148
+ For infrastructure and deployment artifact lookup, such as `projscan start --intent "where is the Dockerfile?"`, `projscan start --intent "where is docker compose for local dev?"`, `projscan start --intent "where are Kubernetes manifests?"`, `projscan start --intent "find Helm chart for payments"`, `projscan start --intent "where is Terraform module for S3?"`, `projscan start --intent "which GitHub workflow deploys staging?"`, or `projscan start --intent "where is Vercel config?"`, it routes to `projscan_search` with focused Docker, Compose, Kubernetes, Helm, Terraform, deployment-workflow, and hosted-config queries while readiness wording such as `can I deploy this?` still routes to release readiness and failing workflow wording still routes to regression planning.
149
+ For domain workflow lookup, such as `projscan start --intent "where is password reset handled?"`, `projscan start --intent "where is team invite flow?"`, `projscan start --intent "where is onboarding flow implemented?"`, `projscan start --intent "find CSV export for users"`, `projscan start --intent "what creates audit log entries?"`, `projscan start --intent "where is refund handling for payments?"`, or `projscan start --intent "where is subscription renewal handled?"`, it routes to `projscan_search` with focused product-workflow queries instead of treating words like `password`, `team`, `onboarding`, `log`, or `payments` as dataflow, ownership, orientation, regression, or release signals. Implementation wording such as `projscan start --intent "implement password reset"` still routes to change planning.
150
+ For communication and content artifact lookup, such as `projscan start --intent "where is welcome email template?"`, `projscan start --intent "find password reset email copy"`, `projscan start --intent "where is push notification copy for invites?"`, `projscan start --intent "where is SMS verification template?"`, `projscan start --intent "which template sends receipt email?"`, or `projscan start --intent "where is invoice PDF generated?"`, it routes to `projscan_search` with focused email-template, email-copy, push/SMS notification, receipt, and invoice-PDF queries instead of treating words like `email`, `notification`, `generated`, or `sends` as dataflow, UI, build-artifact, observability, or regression signals. Explicit leakage/security wording such as `projscan start --intent "is customer email leaking to logs?"` still routes to dataflow.
151
+ For background-work discovery, such as `projscan start --intent "what background jobs exist?"`, `projscan start --intent "which cron jobs exist?"`, `projscan start --intent "find the email queue processor"`, or `projscan start --intent "where are scheduled tasks defined"`, it routes to `projscan_search` with a focused operational-code query instead of treating words like `email`, `processes`, or `tasks` as dataflow or workplan signals.
152
+ For observability lookup, such as `projscan start --intent "where are metrics emitted?"`, `projscan start --intent "find prometheus metrics"`, `projscan start --intent "where do we initialize Sentry?"`, `projscan start --intent "what logs should I check for checkout?"`, or `projscan start --intent "find the dashboard for payments"`, it routes to `projscan_search` with a focused monitoring query before broader debugging or dataflow tools run.
153
+ For test-data and UI-story lookup, such as `projscan start --intent "where is seed data defined?"`, `projscan start --intent "find fixtures for checkout"`, `projscan start --intent "which mocks are used for payments?"`, `projscan start --intent "find factory for users"`, or `projscan start --intent "where are Storybook stories for Button?"`, it routes to `projscan_search` with a focused fixture/mock/story query instead of treating `data`, `defined`, or `used` as dataflow, graph, or impact signals.
154
+ For pasted error/log string lookup, such as `projscan start --intent "where is \"Invalid token\" thrown?"`, `projscan start --intent "find error message \"Payment failed\""`, or `projscan start --intent "where do we log \"could not connect\""`, it routes to `projscan_search` with the quoted text as the query instead of treating words like `token`, `log`, or `failed` as broader dataflow/regression signals.
155
+ For area ownership and human-routing lookup, such as `projscan start --intent "who owns auth?"`, `projscan start --intent "which team owns payments?"`, `projscan start --intent "who should I ask about auth?"`, `projscan start --intent "find expert for billing"`, or `projscan start --intent "who owns this area?"`, it routes to `projscan_search` before deeper file ownership inspection; advisory claims are reserved for explicit claim, reserve, lock, or active-claim wording.
156
+ For documentation lookup questions, such as `projscan start --intent "find documentation for auth"` or `projscan start --intent "where is the API documented?"`, it routes to `projscan_search` with a focused docs query.
157
+ For test-location and existing-test lookup questions, such as `projscan start --intent "where are the tests for src/core/start.ts?"`, `projscan start --intent "where are tests for auth?"`, `projscan start --intent "which tests cover auth?"`, or `projscan start --intent "locate specs for checkout"`, it routes to `projscan_search` with a focused test query before suggesting broader regression planning.
158
+ For proactive proof-selection questions, such as `projscan start --intent "which tests should I run for src/core/start.ts?"` or `projscan start --intent "what should I test before pushing?"`, it routes to `projscan_understand --view verify` so the developer gets verification tiers, direct-test gaps, and the smallest rerunnable proof command before review.
159
+ For exact-file coverage questions, such as `projscan start --intent "is src/core/start.ts covered by tests?"`, it routes to `projscan_file` so coverage, hotspot risk, ownership, and follow-up test evidence are reviewed for that file before editing.
160
+ For broad coverage-gap questions, such as `projscan start --intent "which files have no tests?"`, it routes to `projscan_coverage` so missing-test work is ranked by hotspot risk instead of becoming a generic regression plan.
161
+ For exact-file test-design questions, such as `projscan start --intent "what tests should I add for src/core/start.ts?"`, it routes to `projscan_file` so purpose, risky functions, existing coverage, and related test evidence shape the test before code is written.
162
+ For package-removal questions, such as `projscan start --intent "can I remove lodash?"` or `projscan start --intent "is lodash safe to remove?"`, it routes to `projscan_upgrade` so importer and package-impact evidence are checked before removing the dependency.
163
+ For merge-readiness questions, such as `projscan start --intent "is my branch ready to merge?"`, it routes to `projscan_preflight --mode before_merge` so the branch gets the merge gate instead of the PR-opening evidence pack.
164
+ For PR-risk questions, such as `projscan start --intent "how risky is this PR?"`, `projscan start --intent "what are the risks in my PR?"`, or `projscan start --intent "what are the risky changes in this PR?"`, it routes to `projscan_review` so structural risk, verdict, and owner follow-up are checked before reviewers are asked to approve.
165
+ For merge-risk summary questions, such as `projscan start --intent "what are the top risks before merge?"`, it routes to `projscan_preflight --mode before_merge` so merge blockers and manual-review items are surfaced before integration.
166
+ For risky-file, complexity, refactor-priority, and codebase-performance questions, such as `projscan start --intent "what files are risky to touch?"`, `projscan start --intent "which files are too complex?"`, `projscan start --intent "what file should I refactor first?"`, `projscan start --intent "find performance bottlenecks"`, or `projscan start --intent "where are the slow files?"`, it routes to `projscan_hotspots` so the developer sees the highest-risk files before editing. For exact-file risk questions, such as `projscan start --intent "why is src/core/start.ts risky?"`, it routes to `projscan_file` so the file's hotspot, ownership, issue, import, and export context explains the risk. For cleanup questions, such as `projscan start --intent "find dead code"`, `projscan start --intent "find dead code and unused exports I can delete"`, `projscan start --intent "what can I safely delete?"`, or `projscan start --intent "what can I remove safely?"`, it routes to `projscan_doctor` so dead code, unused exports, and adjacent health issues are reviewed before files are removed.
167
+ For tech-debt and simplification questions, such as `projscan start --intent "what tech debt should I pay down?"` or `projscan start --intent "what code should I simplify?"`, it routes to `projscan_hotspots` instead of incident handling for the word `down`.
168
+ For reviewer-proof requests, such as `projscan start --intent "write a PR comment for reviewers"`, `projscan start --intent "write a PR description"`, `projscan start --intent "what should my PR say?"`, `projscan start --intent "make a PR checklist"`, `projscan start --intent "summarize my changes for reviewers"`, or `projscan start --intent "what should I tell my team about this change?"`, it routes to `projscan_evidence_pack` with `pr_comment: true` so the developer gets a paste-ready verdict, top risks, owner routing, and next commands.
169
+ For reviewer-routing questions, such as `projscan start --intent "who should review this PR?"`, it routes to `projscan_evidence_pack` so likely owners and reviewer-facing context are prepared before a full review.
170
+ For PR-readiness questions, such as `projscan start --intent "am I ready to open a PR?"`, it routes to `projscan_evidence_pack` so preflight, owner routing, top risks, and reviewer-facing proof are prepared before review starts.
171
+ For changed-file owner questions, such as `projscan start --intent "who owns the changed files?"`, it routes to `projscan_evidence_pack` so changed-file owner routing is prepared without confusing it with single-file ownership inspection.
172
+ For direct security-flow questions, such as `projscan start --intent "is user input reaching SQL sinks?"`, `projscan start --intent "does this endpoint expose secrets?"`, or `projscan start --intent "is user input sanitized?"`, it routes to `projscan_dataflow` and infers the `hardening` workflow. For current-change security review questions, such as `projscan start --intent "is this change secure?"` or `projscan start --intent "check this PR for security issues"`, it routes to `projscan_review` so the whole changed surface is reviewed before approval.
173
+ For PII, privacy, and data-handling questions, such as `projscan start --intent "where is PII handled?"`, `projscan start --intent "does this endpoint leak PII?"`, `projscan start --intent "GDPR compliance check"`, or `projscan start --intent "where do we store access tokens?"`, it routes to `projscan_dataflow` instead of dependency compliance or generic search.
174
+ For direct failure-debugging, flaky-test, and verification-speed questions, such as `projscan start --intent "why did CI fail?"`, `projscan start --intent "why is GitHub Actions failing?"`, `projscan start --intent "which GitHub Actions job failed?"`, `projscan start --intent "CI is flaky"`, `projscan start --intent "what command reproduces the flake?"`, `projscan start --intent "quarantine flaky test"`, `projscan start --intent "why is CI slow?"`, `projscan start --intent "why did the build fail?"`, `projscan start --intent "what is making builds slow?"`, `projscan start --intent "lint is failing"`, `projscan start --intent "typecheck is failing"`, `projscan start --intent "npm install is failing"`, or `projscan start --intent "debug this stack trace"`, it routes to `projscan_regression_plan --level focused` before generic issue explanation or broad health checks.
175
+ For incident and runtime-failure questions, such as `projscan start --intent "production is down"`, `projscan start --intent "triage this incident"`, `projscan start --intent "why is the login endpoint returning 500?"`, or `projscan start --intent "where is this stack trace from?"`, it also routes to `projscan_regression_plan --level focused`; explicit code-location wording such as `projscan start --intent "what code handles this error message?"` still routes to search first.
176
+ For local service failures, such as `projscan start --intent "database connection refused locally"`, it routes to `projscan_regression_plan --level focused` instead of schema-impact analysis.
177
+ For test-plan questions, such as `projscan start --intent "what tests should I run for my changes?"` or `projscan start --intent "how can I speed up tests?"`, it routes to `projscan_regression_plan --level focused` so the developer gets the smallest useful verification loop before commit.
178
+ For proof-command questions, such as `projscan start --intent "what commands prove this works?"` or `projscan start --intent "what commands benchmark this repo?"`, it routes to `projscan_regression_plan --level focused` so runnable proof is chosen before claims are made.
179
+ For short proof-command phrasing, such as `projscan start --intent "give me proof commands"`, it also routes to `projscan_regression_plan --level focused`; reviewer-proof wording with PR comments still routes to `projscan_evidence_pack`.
180
+ For pre-push command questions, such as `projscan start --intent "what commands should I run before pushing?"`, it routes to `projscan_regression_plan --level focused` so the branch has a small verification loop before it leaves the workstation.
181
+ For release-readiness wording, such as `projscan start --intent "what should I check before release?"`, `projscan start --intent "can I deploy this?"`, `projscan start --intent "prepare this branch for deployment"`, `projscan start --intent "what changed since last release?"`, `projscan start --intent "write a release note for this change"`, or `projscan start --intent "draft changelog entry"`, it routes to `projscan_release_train` so changelog, package, SBOM, provenance, and blockers are reviewed before deploying or publishing.
182
+ For quick-win and low-risk improvement wording, such as `projscan start --intent "find a quick win"`, `projscan start --intent "what is a low risk improvement?"`, or `projscan start --intent "pick a small safe task"`, it routes to `projscan_bug_hunt` so a ranked, verifiable fix queue is selected instead of a generic quality readout.
183
+ For tiny-task and beginner-safe wording, such as `projscan start --intent "what can I do in five minutes?"`, `projscan start --intent "pick an easy task for me"`, or `projscan start --intent "what should an intern work on?"`, it also routes to `projscan_bug_hunt`.
184
+ For branch-diff, PR-size, and commit-message questions, such as `projscan start --intent "what did I change since main?"`, `projscan start --intent "is this PR too large?"`, `projscan start --intent "how big is this change?"`, `projscan start --intent "write a commit message for these changes"`, or `projscan start --intent "summarize my changes for a commit"`, it routes to `projscan_pr_diff` so changed exports, imports, call sites, complexity, and fan-in are reviewed before full review.
185
+ For branch freshness and comparison questions, such as `projscan start --intent "is my branch stale?"` or `projscan start --intent "compare my branch with main"`, it also routes to `projscan_pr_diff` so the developer checks the structural diff before rebasing or asking for review. For rebase and merge-conflict recovery, such as `projscan start --intent "rebase went wrong"` or `projscan start --intent "resolve merge conflicts"`, it routes to `projscan_preflight --mode before_merge`; post-conflict test-plan wording such as `projscan start --intent "what should I test after resolving conflicts?"` stays on `projscan_regression_plan`.
186
+ For resume questions, such as `projscan start --intent "where did I leave off?"`, `projscan start --intent "what changed while I was away?"`, `projscan start --intent "what changed while I was offline?"`, `projscan start --intent "what changed while I was asleep?"`, `projscan start --intent "what did the last agent touch?"`, or `projscan start --intent "what did the last agent do?"`, it routes to `projscan_session { action: "touched" }` so remembered touched files are reviewed before live preflight evidence gates the next edit.
187
+ For parallel-agent coordination questions, such as `projscan start --intent "show coordination status for parallel agents"`, `projscan start --intent "who else is working on this?"`, `projscan start --intent "am I going to collide with another agent?"`, or `projscan start --intent "what worktrees are active?"`, it routes to `projscan_coordinate` so collisions, claims, and merge order are reviewed through one readiness verdict before editing continues. For merge-order wording, such as `projscan start --intent "what should merge first?"`, it routes to `projscan_merge_risk`; for overlap wording, such as `projscan start --intent "show me overlapping changes"`, it routes to `projscan_collision`.
188
+ For active-claim questions, such as `projscan start --intent "show active claims"`, it routes to `projscan_claim { action: "list" }` so owners, leases, and contention warnings are reviewed before parallel work continues.
189
+ For file-claim requests, such as `projscan start --intent "claim src/core/start.ts for me"`, it routes to `projscan_claim`, lists active claims first, then adds the requested target only after a real agent name replaces `Needs Input`.
190
+ For architecture-coupling questions, such as `projscan start --intent "show circular dependencies"` or `projscan start --intent "find dependency cycles"`, it routes to `projscan_coupling` with `direction: "cycles_only"` / `projscan coupling --cycles-only --format json`; broader wording such as `projscan start --intent "what modules are tightly coupled"` routes to the full fan-in, fan-out, instability, cross-package-edge, and cycle report.
191
+ - **`projscan_workplan` / `projscan workplan`** — agent mission control. Composes preflight, review, session, hotspot, plugin-policy, and supply-chain evidence into prioritized tasks with suggested tools, exact verification commands, and short handoff text. Modes: `before_edit`, `before_commit`, `before_merge`, `refactor`, `release`, `bug_hunt`, and `hardening`.
192
+ - **`projscan_bug_hunt` / `projscan bug-hunt`** — bug-hunt fix queue. Combines doctor issues, preflight, hotspots, and session coordination into ranked fix targets with verification commands; pure hotspot churn stays as watchlist/top-suspect evidence when health and gates are clean.
193
+ - **`projscan_agent_brief` / `projscan agent-brief`** — compact next-agent context packet with focus items, repo context, coordination hints, guardrails, and suggested next actions.
194
+ - **`projscan_quality_scorecard` / `projscan quality-scorecard`** — dimensioned quality view across health, security, tests, maintainability, coordination, top risks, and verification commands.
195
+ - **`projscan_understand` / `projscan understand`** — cited repo-comprehension surface. Returns repo maps, runtime flow maps, contract maps, change-readiness guidance, verification tiers, unknowns, read-first files, and exact next commands.
196
+ - **`projscan_adoption` / `projscan init team` / `projscan init mcp` / `projscan mcp doctor` / `projscan init policy` / `projscan init github-action` / `projscan recipes` / `projscan first-run` / `projscan telemetry` / `projscan dogfood`** — adoption layer. Returns MCP client config snippets, setup verification, policy starters, PR workflow scaffolding with validated PR comments and block-only enforcement, baseline memory, ownership routing, first-PR onboarding steps, repeatable team-bootstrap and PR-automation recipes, multi-repo dogfood evidence, measured reviewer feedback, default-off telemetry controls, adoption trial reports, and setup diagnostics.
197
+ - **`projscan_release_train` / `projscan release-train`** — product-line readiness planner. Plans upcoming product lines with version, scope, readiness, and next-action evidence.
198
+ - **`projscan_evidence_pack` / `projscan evidence-pack`** — approval packet. Combines planning, bug-hunt, workplan, preflight, trust calibration, owner routing, baseline trend, changelog, suggested next actions, and optional website prompt or validated PR-comment evidence in one response.
199
+ - **`projscan_regression_plan` / `projscan regression-plan`** — regression matrix. Builds smoke, focused, or full verification plans from bug-hunt, preflight, and product risk.
200
+ - **`projscan_doctor` / `projscan doctor`** — single 0–100 health score plus a list of issues across linting, formatting, tests, security, supply-chain trust, dependencies, dead code, and circular imports. Each issue carries a `suggestedAction` hint pointing at the fix-suggest pipeline (0.14+).
201
+ - **`projscan_preflight` / `projscan preflight`** — agent safety gate. Returns `proceed`, `caution`, or `block` with health, changed-file, review, remembered session, hotspot, plugin-policy, supply-chain, and release-scale evidence. `evidence.riskSources.currentWorktree` is current Git/worktree evidence; `evidence.riskSources.sessionMemory` is remembered handoff context. Use `--mode before_edit` at the start of work and `--mode before_commit` / `--mode before_merge` before handing off or merging; scale-only commit blocks are cautions, while merge gates still require manual release sign-off.
202
+ - **`projscan_hotspots` / `projscan hotspots`** — files ranked by `git churn × AST cyclomatic complexity × open issues × ownership × coverage`. Pass `view: "functions"` for top-N risky individual functions across the repo (0.13+).
203
+ - **`projscan_semantic_graph` / `projscan semantic-graph`** — stable v3 graph contract with file, function, package, and symbol nodes plus imports, exports, definitions, and calls edges. Use it when an agent needs one normalized graph shape instead of several targeted queries.
204
+ - **`projscan_dataflow` / `projscan dataflow`** — direct, propagated, and bridge source-to-sink dataflow risks. Use it for a focused safety pass before touching command execution, raw SQL, filesystem writes, or DOM sinks.
205
+ - **`projscan_coupling` / `projscan coupling`** — per-file fan-in / fan-out / instability plus circular-import cycles (Tarjan SCC). Use `direction: cycles_only` or `projscan coupling --cycles-only` to surface architectural debt directly.
206
+ - **`projscan_analyze` / `projscan analyze`** — the everything report; useful at session start but verbose.
207
+
208
+ **Typical agent flow:** start with `projscan privacy-check`, then `projscan_start` with an optional plain-language intent. If no explicit mode is supplied, start infers the workflow mode from the intent, such as `before_commit` for commit-safety checks; read `modeSource` and `modeReason` to see whether the mode was explicit, inferred, or defaulted. `modeReason` distinguishes workflow-mode defaulting from action routing, so an impact intent can still route through Mission Control while the workflow stays `before_edit`. The `firstTenMinutes` path and current-worktree coordination hint follow that resolved mode, so a commit-safety start does not send the developer back through a before-edit gate. Follow `missionControl.actionPlan`, call `missionControl.readyActions` immediately, use `missionControl.executionPlan.currentPhase` as the cursor-aligned phase pointer, and use `missionControl.executionPlan.cursor.tool` / `args` when the cursor is directly MCP-callable. Use routed-intent weighted `confidence`, `score`, and `matchedKeywords` to judge weak or ambiguous matches, and read the same confidence line in console output when working manually. Fill any `missionControl.unresolvedInputs` before running placeholder follow-ups, inspect `missionControl.alternatives` when the intent mixes goals, stop only when `missionControl.successCriteria` is satisfied, and hand off with `missionControl.handoff`, `missionControl.runbook`, or the concise `missionControl.handoffPrompt`. Use `missionControl.reviewGate` as the autonomous-work stop boundary: finish the current checklist and proof, capture `git status --short` and `git diff --stat`, then wait for approval before another slice, release, publish, or deploy. Read `missionControl.reviewGate.worktree` for current worktree availability, changed-file count, base ref, and visible changed files. Use `missionControl.reviewGate.proof` when the reviewer needs the remaining proof queue without reading the full resume object. Read `missionControl.reviewGate.doneWhen` for the success criteria the reviewer must confirm before approving more work. Read `missionControl.reviewGate.policy` before continuing from a review handoff; it lists the actions blocked until explicit reviewer approval: another slice, release, publish, deploy, push, merge, and version bump. Use `projscan start --review-gate-json --intent "<goal>"` or saved `review-gate.json` when a script needs proof, worktree evidence, done criteria, decisions, and policy in one review object. Use `projscan start --review-policy --intent "<goal>"` or saved `review-policy.json` when a script only needs that approval boundary. Use `missionControl.reviewGate.decisions` as the approval menu in review gates, task cards, and runbooks; each decision includes copyable reviewer reply text so agents do not infer permission to continue, release, or publish. The default console review gate, saved mission bundle README, concise handoff prompt, `--review-replies`, and saved `review-replies.txt` show those replies for first-open review. `missionControl.handoff.reviewGate`, `--handoff-json`, and saved `handoff.json` carry that same gate for transfer-only flows. The handoff prompt starts with `missionControl.resume.prompt`, so it carries the current cursor, runnable command or blocked input instruction, labeled unlocks or blockers, done criteria, ready proof, review stop condition, and reviewer replies in one copyable sentence; the normal console prints that same value as `Handoff Prompt` without requiring JSON or `--include-handoff`, `projscan start --handoff-prompt --intent "<goal>"` prints only that prompt for piping or copy/paste, and the Markdown runbook renders it as `## Handoff Prompt` so copied runbooks carry the same next-agent prompt. When a human just needs the runnable shell step, `projscan start --next-command --intent "<goal>"` prints only the current cursor command; when an MCP agent needs the callable equivalent, `projscan start --next-tool-call --intent "<goal>"` prints the current cursor tool call as compact JSON. Cite `missionControl.proofSummary` plus the runnable-only `missionControl.proofCommands` in broad handoff notes, and use `missionControl.handoff.readyProof.items` when resuming because it is the complete ordered remaining-proof queue; each item carries its CLI command and an optional MCP `toolCall`. `missionControl.handoff.readyProof.commands` and `toolCalls` remain convenient command-only and MCP-callable views. MCP agents should use `missionControl.resume.toolCall` when present, use `missionControl.resume.inputBindings` to map unlocked placeholders to input steps, then call `missionControl.resume.followUps` as the next template calls; when they need one ordered sequence, follow `missionControl.resume.checklist`, whose `run_proof` rows include `tool` and `args` for MCP-callable proof steps. The normal console `Resume Checklist` and Markdown runbook checklist print callable rows inline as `(MCP: ...)` and mark unmapped proof rows as `(CLI only)`, so a copied runbook or default terminal run remains self-contained even outside the JSON payload. After the current action, prefer `missionControl.resume.remainingProofItems` for complete proof, using `remainingProofToolCalls` for the callable MCP subset without rerunning the current command. Humans can run the matching `command`; the normal console `Ready Proof` command list, normal console `Proof Queue`, and runbook `Proof queue` all use remaining proof so the current cursor command is not repeated, and each queued item shows either its MCP call or `CLI only`. Use `projscan_understand` and `projscan_preflight` when you need broader context or a safety gate. Use `projscan_workplan` when you need an ordered execution plan, `projscan_agent_brief` for a compact handoff, and `projscan_evidence_pack --pr-comment` when you need reviewer-facing proof. Deeper tools such as `doctor`, `hotspots`, `dataflow`, `review`, `bug-hunt`, `quality-scorecard`, `dogfood`, and `trial` are follow-up tools.
209
+
210
+ For shortcut discovery, `projscan start --shortcuts --intent "<goal>"` prints the copyable command menu for the current mission, and `projscan start --shortcuts-json --intent "<goal>"` prints the same menu as JSON for agents and scripts. For shell copy/paste, `projscan start --mission-script --intent "<goal>"` prints a POSIX script that runs the current cursor command, then the remaining proof queue, then prints the review evidence commands. For MCP queue copy/paste, `projscan start --ready-tool-calls --intent "<goal>"` prints the current cursor call followed by remaining MCP-callable proof as compact JSON. For structured resume handoff, `projscan start --resume-json --intent "<goal>"` prints only `missionControl.resume`. For the complete transfer object, `projscan start --handoff-json --intent "<goal>"` prints only `missionControl.handoff`. For a file bundle, `projscan start --save-mission .projscan/mission --intent "<goal>"` writes `README.md`, `next-command.txt`, `next-tool-call.json`, `handoff-prompt.txt`, `resume-prompt.txt`, `task-card.md`, `review-gate.md`, `review-gate.json`, `review-policy.json`, `review-replies.txt`, the runbook, handoff JSON, resume JSON, `ready-tool-calls.json`, `shortcuts.json`, `mission.sh`, `status.sh`, `proof-logs/README.md`, `proof-logs/status.jsonl`, `proof-logs/run-report.md`, `proof-logs/summary.json`, proof commands, and manifest. Saved `mission.sh` writes current-command and proof-command output under `proof-logs/`, appends exit-code rows to `status.jsonl`, refreshes `run-report.md`, and writes `summary.json`, so reviewers and wrappers can scan pass/fail proof before opening raw logs. Bundle `status.sh` reads `summary.json` and uses exit codes `0`, `1`, and `2` for passed, failed, and not-ready states. For verification-only copy/paste, `projscan start --proof-commands --intent "<goal>"` prints the remaining ready proof commands one per line without the rest of the start report. For an ordered checklist without the full report, `projscan start --checklist --intent "<goal>"` prints only the resume checklist rows. For paste-ready PR, issue, or handoff notes, `projscan start --task-card --intent "<goal>"` prints the Markdown task card. MCP agents can read `missionControl.taskCard.markdown` when they need the same checklist without rendering it from `resume.checklist`. For stop-and-review notes, `projscan start --review-gate --intent "<goal>"` prints only `missionControl.reviewGate.markdown`, `projscan start --review-gate-json --intent "<goal>"` prints only the review gate JSON, `projscan start --review-policy --intent "<goal>"` prints only the review policy JSON, and `projscan start --review-replies --intent "<goal>"` prints only the copyable reviewer replies. For a full Markdown artifact, `projscan start --runbook --intent "<goal>"` prints the mission runbook.
211
+
212
+ ### 2. Review — "is this PR safe to merge?"
213
+
214
+ When the agent has changes in flight (or is asked to review someone else's), the question shifts from "what's wrong globally" to "what changed, and does the change introduce risk?"
215
+
216
+ - **`projscan_pr_diff` / `projscan pr-diff`** *(0.11+)* — structural (AST) diff between two refs. Returns added / removed / modified files with explicit lists of exports, imports, call sites, and ΔCC / Δfan-in. Not a text diff: surfaces the symbols that moved, not the whitespace.
217
+ - **`projscan_review` / `projscan review`** *(0.13+)* — **the headline tool for this phase**. Composes `pr_diff` + per-file risk + new/expanded import cycles + risky function additions + dependency changes + optional `contractChanges` for export and package-entrypoint changes + `newTaintFlows`, hardened `newDataflowRisks`, compact `graphEvidence`, and a verdict (`ok` / `review` / `block`). One tool call answers the whole question.
218
+ - **`projscan_preflight --mode before_merge` / `projscan_preflight { mode: "before_merge" }`** — smaller merge gate over review, changed-file health, taint, dataflow, session, hotspot, plugin, supply-chain, and release-scale signals. `evidence.releaseScale` marks large platform-release sign-off when review blocks on scale/complexity rather than a concrete defect. Use it when the agent needs the decision before reading the full review payload.
219
+
220
+ **Typical agent flow:** start with `projscan_review` for the verdict + summary; if it returns `review` or `block`, drill into the `riskyFunctions` and `newCycles` arrays for specifics.
221
+
222
+ ### 3. Fix — "what should I do about it?"
223
+
224
+ projscan diagnoses but does not run an LLM. The agent (the LLM) is what writes the fix. projscan's job in this phase is to package the issue context into something the agent can act on.
225
+
226
+ - **`projscan_fix_suggest` / `projscan fix-suggest`** *(0.14+)* — given an issue id (or a `file` + `rule` pair), return a structured action prompt: headline, why it matters, where to change, one-paragraph instruction, optional suggested test. Hand-tuned templates for ~12 common issue families plus a severity-anchored generic fallback.
227
+ - **`projscan_explain_issue` / `projscan explain-issue`** *(0.14+)* — deep dive: code excerpt around the location, related issues touching the same file, similar past commits via `git log --grep=<rule>`. Use when an agent wants more context than `doctor` gave.
228
+ - **`projscan fix`** — rule-based auto-fix (ESLint, Prettier, Vitest scaffolding, EditorConfig). Pre-dates the `fix_suggest` flow; useful for the no-LLM-required class of fixes.
229
+
230
+ **Typical agent flow:** read an issue from `projscan_doctor`, call `projscan_fix_suggest` with its id, paste the `instruction` field into the agent's plan.
231
+
232
+ ### 4. Reach — "what breaks if I change this?"
233
+
234
+ Before the agent commits to a refactor (or accepts a name-rename suggestion), the question is: *who depends on this thing, transitively?*
235
+
236
+ - **`projscan_impact` / `projscan impact`** *(0.15+)* — transitive blast-radius. File mode returns every file that transitively imports the target, ranked by BFS distance. Symbol mode returns the symbol's definition file(s), the files that directly call it (their callSites match), and the transitive importers of those callers. Cycle-safe; depth-bounded.
237
+ - **`projscan_semantic_graph` (`query` mode) / `projscan semantic-graph`** — direct one-hop queries via `query: { direction, file?, symbol? }`: `imports`, `exports`, `importers`, `symbol_defs`, `package_importers`. Use when impact is overkill and you want a pin-point answer. Package wording such as `which files import package chalk`, `who uses lodash`, or `why do we depend on lodash` maps to `package_importers`. With no `query`, returns the full graph projection (file, function, package, and symbol context in one contract). *(Subsumes the former `projscan_graph`, removed in 4.0.)*
238
+
239
+ **Typical agent flow:** before renaming or deleting an export, call `projscan_impact --symbol <name>` to see the dependent set; before deleting a file, call `projscan_impact <path>`. The truncated flag tells you whether the actual blast radius extends beyond what you saw.
240
+
241
+ ### 5. Live — "keep the index fresh while I work"
242
+
243
+ Long agent sessions edit files repeatedly. Each edit could otherwise cost a full repo re-scan. The watch infrastructure keeps the graph current at low cost.
244
+
245
+ - **`projscan watch`** *(0.16+)* — long-running CLI command. On file change, debounces 200ms then runs the incremental graph update + re-runs `doctor`, printing a one-line status. Uses `node:fs.watch`, no new runtime dep. Filters out `node_modules`, `.git`, build dirs, etc.
246
+ - **`incrementallyUpdateGraph(graph, rootPath, changedPaths[])`** — the public API the watcher uses; exported so callers maintaining their own state can patch the graph in place after handling their own change events.
247
+ - **`--format html`** *(0.16+, expanded in 2.x)* — for sharing review snapshots: `projscan analyze --format html > report.html` produces a self-contained HTML page suitable for posting as a PR comment or saving as a CI artifact. Renderers exist for `analyze`, `doctor`, `hotspots`, `coupling`, `pr-diff`, `review`, `impact`, and `coverage`.
248
+ - **`projscan mcp --watch`** *(1.3+)* — when projscan runs as an MCP server with this flag, it pushes JSON-RPC `notifications/file_changed` events to the connected agent on every debounced batch. Long-session agents stop polling. The capability is advertised under `experimental.fileChanged` on the `initialize` response so clients can detect support.
249
+ - **`projscan_session` MCP tool + `projscan session` CLI** *(1.4+)* — durable cross-invocation session. Auto-records every file path that any tool returned (`tool-result` source) and every fs-watch batch (`fs-watch` source), so multiple agent invocations against the same project share a "what's been touched here" view without re-running git. Idle window 1 hour by default; subactions: `current` / `touched` / `events` / `reset`. State lives at `.projscan-cache/session.json`.
250
+ - **MCP resources** *(2.1+)* — `projscan://session/summary`, `projscan://handoff`, and `projscan://risk-now` expose the shared session as resource reads. Agents can pick up touched files, coordination conflicts, remaining risks, `coordinationHints`, and recommended next tool calls without spending a tool call on discovery. The hints separate current worktree checks from remembered session context and conflict resolution.
251
+
252
+ **Typical workflow:** start `projscan watch` in a side terminal at the start of a long session; subsequent agent tool calls hit a warm graph cache. With multi-agent setups, every MCP tool call additionally records into the session, so a coordinator agent can ask `projscan_session { action: "touched" }` to see what its peers have touched.
253
+
254
+ ---
255
+
256
+ ## Commands In Depth
257
+
258
+ ### analyze
259
+
260
+ ```bash
261
+ projscan analyze
262
+ ```
263
+
264
+ The flagship command. Runs every detection module and produces the full project report.
265
+
266
+ **What it does internally:**
267
+ 1. Builds the scan file set. In Git repos, projscan uses `git ls-files --cached --others --exclude-standard` by default, then applies built-in noise ignores and `.projscanrc` `ignore` globs. Non-Git folders fall back to the local file walker.
268
+ 2. Builds a language breakdown by mapping file extensions to language names
269
+ 3. Detects frameworks by inspecting `package.json` dependencies and config file presence
270
+ 4. Analyzes dependencies from `package.json`
271
+ 5. Runs all issue analyzers (ESLint, Prettier, tests, architecture, dependency risk, security)
272
+ 6. Applies `.projscanrc` rules (disabled rules, severity overrides)
273
+ 7. Renders the combined report
274
+
275
+ **Options:**
276
+
277
+ | Flag | Description |
278
+ |------|-------------|
279
+ | `--changed-only` | Only report issues on files changed vs base ref |
280
+ | `--base-ref <ref>` | Git base ref for `--changed-only` (default: origin/main) |
281
+
282
+ <img src="https://abhiyoheswaran.com/images/projscan/hero-poster.png" alt="npx projscan analyze: banner, scan progress, full project report" width="700">
283
+
284
+ ### doctor
285
+
286
+ ```bash
287
+ projscan doctor
288
+ ```
289
+
290
+ A focused health check. Runs only the issue detection pipeline and presents results as a health report with a health score and letter grade.
291
+
292
+ Use this when you want a quick "is this project in good shape?" answer without the full language/framework breakdown.
293
+
294
+ **Options:**
295
+
296
+ | Flag | Description |
297
+ |------|-------------|
298
+ | `--changed-only` | Only report issues on files changed vs base ref |
299
+ | `--base-ref <ref>` | Git base ref for `--changed-only` (default: origin/main) |
300
+
301
+ <img src="npx%20projscan%20doctor.gif" alt="npx projscan doctor" width="700">
302
+
303
+ **Severity levels:**
304
+ - **error** (✖) - Problems that should be addressed immediately
305
+ - **warning** (⚠) - Issues that affect code quality or maintainability
306
+ - **info** (ℹ) - Suggestions for best practices
307
+
308
+ ### hotspots
309
+
310
+ ```bash
311
+ projscan hotspots
312
+ ```
313
+
314
+ <img src="https://abhiyoheswaran.com/images/projscan/hotspots-poster.png" alt="projscan hotspots output ranking files by composite risk score" width="700">
315
+
316
+ Ranks files by **risk** - a combination of git churn, complexity (lines of code), open issues, recency, and ownership (bus-factor). Turns a flat health score into a prioritized "fix these first" list.
317
+
318
+ **Options:**
319
+
320
+ | Flag | Description | Default |
321
+ |------|-------------|---------|
322
+ | `--limit <n>` | Number of hotspots to show | 10 (or `hotspots.limit` from `.projscanrc`) |
323
+ | `--since <when>` | Git history window (e.g. `"6 months ago"`, `"2024-01-01"`) | `12 months ago` |
324
+
325
+ **What you get per file:**
326
+ - `riskScore` - combined score (0–100)
327
+ - `churn` - number of commits touching the file in the window
328
+ - `distinctAuthors` - how many people have touched it
329
+ - `primaryAuthor` / `primaryAuthorShare` - who owns most of the history
330
+ - `busFactorOne` - **true** if a single author dominates AND churn is high (organizational risk)
331
+ - `issueIds` - open issues that reference the file
332
+ - `reasons` - human-readable tags explaining the score
333
+
334
+ **Fallback:** If the project isn't a git repository, hotspots returns `available: false` with a friendly reason - it does not crash.
335
+
336
+ ### semantic-graph
337
+
338
+ ```bash
339
+ projscan semantic-graph --format json
340
+ projscan semantic-graph --query importers --file src/auth.ts --format json
341
+ projscan semantic-graph --query exports --file src/auth.ts --format json
342
+ projscan semantic-graph --query symbol_defs --symbol authenticate --format json
343
+ projscan semantic-graph --query package_importers --symbol chalk --format json
344
+ ```
345
+
346
+ Returns the stable semantic graph contract: `schemaVersion: 3`, `nodes`, `edges`,
347
+ `metrics`, `truncated`, and `limits`. Nodes use stable prefixes (`file:`,
348
+ `function:`, `package:`, `symbol:`); edges use `defines`, `imports`,
349
+ `imports_package`, `exports`, and `calls`.
350
+
351
+ Use this when an agent needs one graph-shaped payload for planning, ownership
352
+ analysis, plugin logic, or custom visualization instead of making several
353
+ targeted `projscan_semantic_graph` queries.
354
+ Use `--query` when the agent needs one pin-point answer from the CLI: who imports
355
+ a file, what a file imports or exports, where a symbol is defined, or which files
356
+ import a package.
357
+
358
+ **Options:**
359
+
360
+ | Flag | Description | Default |
361
+ |------|-------------|---------|
362
+ | `--max-nodes <n>` | Maximum nodes to return | 10000 |
363
+ | `--max-edges <n>` | Maximum edges to return | 25000 |
364
+ | `--query <direction>` | Targeted query: `imports`, `exports`, `importers`, `symbol_defs`, or `package_importers` | full graph |
365
+ | `--file <path>` | Repo-relative file for `imports`, `exports`, or `importers` | - |
366
+ | `--symbol <name>` | Symbol/package for `symbol_defs` or `package_importers` | - |
367
+ | `--limit <n>` | Maximum targeted query entries | 50 |
368
+
369
+ ### understand
370
+
371
+ ```bash
372
+ projscan understand --view map --format json
373
+ projscan understand --view flow --format json
374
+ projscan understand --view contracts --format json
375
+ projscan understand --view change --intent "rename auth token loader" --format json
376
+ projscan understand --view verify --format json
377
+ ```
378
+
379
+ Repo understanding for engineers before they edit. The command returns a cited report with `claims`, `readFirst`, `entrypoints`, `boundaries`, `flows`, `contracts`, `changeReadiness`, `verification`, `risks`, `unknowns`, and exact next commands.
380
+
381
+ Views:
382
+
383
+ | View | Use it for |
384
+ |------|------------|
385
+ | `map` | Orient around entrypoints, package boundaries, read-first files, risks, and unknowns |
386
+ | `flow` | Trace runtime paths and side-effect sinks through graph-backed evidence |
387
+ | `contracts` | Inspect public exports, config/env contracts, and likely breaking-change risks |
388
+ | `change` | Tie an intent to blast radius, first safe edit, owner state, rollback, and verification commands |
389
+ | `verify` | Build minimal, focused, and full proof tiers plus direct-test gap evidence |
390
+
391
+ **Options:**
392
+
393
+ | Flag | Description | Default |
394
+ |------|-------------|---------|
395
+ | `--view <view>` | `map`, `flow`, `contracts`, `change`, or `verify` | `map` |
396
+ | `--intent <text>` | Planned change or question for change-readiness output | none |
397
+ | `--max-items <n>` | Maximum items per section | 8 |
398
+
399
+ ### dataflow
400
+
401
+ ```bash
402
+ projscan dataflow --format json
403
+ ```
404
+
405
+ Reports focused direct, propagated, and bridge source-to-sink risks over the function
406
+ graph. Bridge risks are graph-backed dataflow additions: a wrapper that calls a source reader
407
+ and a sink wrapper is surfaced even when legacy taint reachability cannot see a
408
+ downstream call path from source to sink. By default, dataflow suppresses test-file paths,
409
+ broad readFile/writeFile-style noise, and JavaScript RegExp.exec false positives.
410
+
411
+ For release hardening, `npm run check:graph-corpus` compares bundled fixture metrics against `docs/graph-corpus-baseline.json`. The gate fails only when graph coverage drops below the baseline or dataflow risks rise above it.
412
+
413
+ **Options:**
414
+
415
+ | Flag | Description | Default |
416
+ |------|-------------|---------|
417
+ | `--source <name...>` | Add custom source identifiers | Built-ins + config |
418
+ | `--sink <name...>` | Add custom sink identifiers | Built-ins + config |
419
+ | `--max-risks <n>` | Maximum risks to return | 50 |
420
+ | `--include-tests` | Include risks that touch test files | false |
421
+ | `--include-broad-file-io` | Include broad default readFile/writeFile-style risks | false |
422
+
423
+ ### search
424
+
425
+ ```bash
426
+ projscan search <query>
427
+ projscan search "npm audit" --scope auto
428
+ projscan search authenticate --scope symbols
429
+ projscan search stripe --scope files
430
+ ```
431
+
432
+ <img src="https://abhiyoheswaran.com/images/projscan/search-poster.png" alt="projscan search output showing ranked results for the query ContactForm" width="700">
433
+
434
+ BM25-ranked search across content, symbol names, and path tokens. No embeddings, no model download - just a solid classical IR implementation that beats substring matching for typical code queries.
435
+
436
+ **Scopes:**
437
+
438
+ | Scope | What it matches | Ranking |
439
+ |-------|-----------------|---------|
440
+ | `auto` (default) | Content, with symbol + path boost | BM25 + symbol boost × 2.0 + path boost × 0.5 |
441
+ | `content` | Same as `auto` | BM25 |
442
+ | `symbols` | Names of exported functions/classes/types/etc. | Exact → prefix → substring |
443
+ | `files` | Relative path substring | Path order |
444
+
445
+ **Query handling:**
446
+ - Tokens are split on camelCase, snake_case, and digits. `userAuthToken` indexes as `user`, `auth`, `token`.
447
+ - Light stemming (trailing `-s`, `-ing`, `-ed` stripped).
448
+ - Stopwords and TypeScript keywords filtered (`the`, `function`, `class`, `export`, …).
449
+ - Multi-word queries are OR across tokens, ranked by sum of BM25 scores.
450
+
451
+ **Output includes:** file path, line number, a one-line excerpt centered on the first matching line, the match score, and which tokens matched.
452
+
453
+ **Limitations:**
454
+ - No real semantic understanding by default. Searching for *"payment processing"* won't find a file that implements Stripe under the name `charge()`. True semantic search (local embeddings) shipped in 0.9.0 as an opt-in peer dep - install `@xenova/transformers` and pass `--mode semantic` (or `--mode hybrid` for BM25 + semantic via reciprocal rank fusion).
455
+ - Index is rebuilt on every run (fast - the AST is already parsed from the code-graph cache).
456
+
457
+ ### file
458
+
459
+ ```bash
460
+ projscan file src/cli/index.ts
461
+ ```
462
+
463
+ Per-file drill-down. Combines everything ProjScan knows about a file into one view:
464
+
465
+ - **Purpose** - inferred from name and directory
466
+ - **Imports** / **exports** - from regex-based static analysis
467
+ - **Hotspot risk** - the file's entry from `hotspots` (churn, score, owner, bus factor)
468
+ - **Related issues** - every open issue whose `locations` reference the file
469
+ - **Inline smells** - large files, `console.log`, TODO/FIXME, `any` types
470
+
471
+ Natural follow-up to `projscan hotspots` - once hotspots tells you *which* file to look at, `file` tells you *what* to do about it.
472
+
473
+ ### ci
474
+
475
+ ```bash
476
+ projscan ci
477
+ ```
478
+
479
+ A CI-pipeline-friendly health gate. Runs the full health check and exits with code 1 if the score falls below a threshold. No spinners or banners - clean output for CI logs.
480
+
481
+ **Options:**
482
+
483
+ | Flag | Description | Default |
484
+ |------|-------------|---------|
485
+ | `--min-score <n>` | Minimum passing score (0–100) | `minScore` from `.projscanrc`, else 70 |
486
+ | `--changed-only` | Gate only on issues in files changed vs base ref | off |
487
+ | `--base-ref <ref>` | Git base ref for `--changed-only` | auto (origin/main → origin/master → main → master → HEAD~1) |
488
+
489
+ **Example:**
490
+
491
+ ```bash
492
+ $ projscan ci --min-score 80
493
+
494
+ projscan: B (82/100) - 0 errors, 2 warnings, 1 info - PASS (threshold: 80)
495
+ ```
496
+
497
+ <img src="npx%20projscan%20ci%20--min-score%2070.gif" alt="npx projscan ci" width="700">
498
+
499
+ **Exit codes:**
500
+ - `0` - Score meets or exceeds the threshold
501
+ - `1` - Score is below the threshold
502
+
503
+ **JSON output** (useful for scripts):
504
+
505
+ ```bash
506
+ projscan ci --min-score 70 --format json
507
+ ```
508
+
509
+ **SARIF output** (for GitHub Code Scanning or any SARIF consumer):
510
+
511
+ ```bash
512
+ projscan ci --format sarif > projscan.sarif
513
+ ```
514
+
515
+ **PR-diff mode** (only gate on issues in changed files):
516
+
517
+ ```bash
518
+ projscan ci --changed-only
519
+ projscan ci --changed-only --base-ref origin/develop
520
+ ```
521
+
522
+ See [PR-Diff Mode](#pr-diff-mode---changed-only) for details.
523
+
524
+ ### diff
525
+
526
+ ```bash
527
+ projscan diff
528
+ ```
529
+
530
+ Compare your project's current health and hotspots against a saved baseline. Useful for tracking whether a codebase is improving or degrading over time.
531
+
532
+ **Options:**
533
+
534
+ | Flag | Description |
535
+ |------|-------------|
536
+ | `--save-baseline` | Save current health + top hotspots as the baseline |
537
+ | `--baseline <path>` | Path to baseline file (default: `.projscan-baseline.json`) |
538
+
539
+ **Workflow:**
540
+
541
+ ```bash
542
+ # Step 1: Save current state as baseline
543
+ $ projscan diff --save-baseline
544
+
545
+ Baseline saved to /path/to/project/.projscan-baseline.json
546
+ Score: D (60/100)
547
+ Issues: 2
548
+ Hotspots snapshotted: 14
549
+
550
+ # Step 2: Make changes, then compare
551
+ $ projscan diff
552
+ ```
553
+
554
+ The diff reports four hotspot movements: files that **rose**, **fell**, **appeared**, or were **resolved** since the baseline - alongside the usual new/resolved issue lists.
555
+
556
+ <img src="npx%20projscan%20diff%20--save-baseline.gif" alt="npx projscan diff --save-baseline" width="700">
557
+
558
+ ### fix
559
+
560
+ ```bash
561
+ projscan fix
562
+ ```
563
+
564
+ Detects fixable issues and offers to auto-remediate them. Shows you exactly what will change before applying anything.
565
+
566
+ **Non-interactive mode:**
567
+
568
+ ```bash
569
+ projscan fix -y
570
+ ```
571
+
572
+ **Available fixes:**
573
+
574
+ | Fix | What it creates | What it installs |
575
+ |-----|----------------|-----------------|
576
+ | ESLint | `eslint.config.js` (with TypeScript support if TS is detected) | `eslint`, `@eslint/js`, optionally `typescript-eslint` |
577
+ | Prettier | `.prettierrc` with sensible defaults | `prettier` |
578
+ | Test framework | `vitest.config.ts` + sample test file, adds `test` script to package.json | `vitest` |
579
+ | EditorConfig | `.editorconfig` (UTF-8, LF, 2-space indent, trim trailing whitespace) | Nothing |
580
+
581
+ ### diagram
582
+
583
+ ```bash
584
+ projscan diagram
585
+ ```
586
+
587
+ Generates an ASCII architecture diagram. Scans your directory structure and framework detection results to identify architectural layers.
588
+
589
+ <img src="npx%20projscan%20diagram.gif" alt="npx projscan diagram" width="700">
590
+
591
+ ### structure
592
+
593
+ ```bash
594
+ projscan structure
595
+ ```
596
+
597
+ Renders a tree view of the project directory with file counts per directory.
598
+
599
+ <img src="npx%20projscan%20structure.gif" alt="npx projscan structure" width="700">
600
+
601
+ ### dependencies
602
+
603
+ ```bash
604
+ projscan dependencies
605
+ ```
606
+
607
+ Deep dive into your project's dependency graph - production/dev counts, package manager, lock file presence, and risk analysis (wildcard versions, `latest` tags, excessive counts).
608
+
609
+ <img src="npx%20projscan%20dependencies.gif" alt="npx projscan dependencies" width="700">
610
+
611
+ ### outdated
612
+
613
+ ```bash
614
+ projscan outdated
615
+ ```
616
+
617
+ Offline drift check - compares the version declared in `package.json` against the version installed under `node_modules/<pkg>/package.json`. Classifies each package as `patch`, `minor`, `major`, `same`, or `unknown` drift. Does **not** hit the npm registry.
618
+
619
+ **Output fields per package:**
620
+ - `declared` - the range in `package.json` (e.g., `^1.2.3`)
621
+ - `installed` - the concrete version in `node_modules`, or `null` if not installed
622
+ - `latest` - same as `installed` in this offline drift check
623
+ - `drift` - classification
624
+ - `scope` - `dependency` or `devDependency`
625
+
626
+ JSON, Markdown, and SARIF formats are supported.
627
+
628
+ ### audit
629
+
630
+ ```bash
631
+ projscan audit
632
+ ```
633
+
634
+ Wraps `npm audit --json` and normalizes the output. Requires a `package-lock.json`. Graceful error for `yarn.lock` / `pnpm-lock.yaml` projects (suggests the right native command).
635
+
636
+ **Per-finding fields:** `name`, `severity` (`critical` / `high` / `moderate` / `low` / `info`), `title`, `url`, `cve`, `via`, `range`, `fixAvailable`.
637
+
638
+ **Summary:** counts per severity.
639
+
640
+ **SARIF output:**
641
+
642
+ ```bash
643
+ projscan audit --format sarif > audit.sarif
644
+ ```
645
+
646
+ Each finding becomes a SARIF result with `ruleId: audit-<pkg>`, severity mapped to `error` / `warning` / `note`, anchored to `package.json`. Pipe into `github/codeql-action/upload-sarif` or the first-party projscan Action and vulnerabilities show up in the Security → Code scanning tab.
647
+
648
+ **Options:**
649
+
650
+ | Flag | Description | Default |
651
+ |------|-------------|---------|
652
+ | `--timeout <ms>` | Override npm audit timeout | 60000 |
653
+
654
+ ### upgrade
655
+
656
+ ```bash
657
+ projscan upgrade <package>
658
+ ```
659
+
660
+ Preview the impact of upgrading a package. The default path is fully offline; pass `--check-registry` when you explicitly want npm registry lookup for the current latest version.
661
+
662
+ **What you get:**
663
+ - Drift classification (`patch` / `minor` / `major`)
664
+ - Breaking-change markers found in the CHANGELOG: scans for `BREAKING CHANGE`, `deprecated`, `removed support`, `no longer supported`, and section headers containing "breaking"
665
+ - CHANGELOG excerpt sliced to the relevant version range (read from `node_modules/<pkg>/CHANGELOG.md`)
666
+ - Importer list - every file in your source tree that imports the package (direct or sub-path)
667
+
668
+ **Example:**
669
+
670
+ ```bash
671
+ $ projscan upgrade react --format markdown
672
+
673
+ # Upgrade Preview - `react`
674
+ - Declared: `^18.2.0`
675
+ - Installed: `18.3.1`
676
+ - Drift: **minor**
677
+
678
+ ## Importers (14)
679
+ - `src/App.tsx`
680
+ - `src/components/Button.tsx`
681
+ - ...
682
+ ```
683
+
684
+ **Limitations:**
685
+ - Reads the CHANGELOG that npm already placed in `node_modules/`. If the package author doesn't ship one, you'll see "No local CHANGELOG found."
686
+ - Without `--check-registry`, works with what's **installed** and reports `latestSource: "installed"`. With `--check-registry`, npm registry lookup is attempted and failures fall back to the installed version with `registryError`.
687
+
688
+ ### coverage
689
+
690
+ ```bash
691
+ projscan coverage
692
+ ```
693
+
694
+ Joins test coverage with the hotspot ranking and produces a list sorted by "risk × uncovered fraction" - the files that most deserve tests.
695
+
696
+ **Supported formats** (auto-detected in this order):
697
+ - `coverage/lcov.info` - lcov format (Vitest, Jest, c8)
698
+ - `coverage/coverage-final.json` - Istanbul per-file detail
699
+ - `coverage/coverage-summary.json` - Istanbul summary
700
+
701
+ **Output fields per entry:**
702
+ - `relativePath` - file path
703
+ - `riskScore` - the file's hotspot risk
704
+ - `coverage` - line coverage %, or `null` if the file isn't in the coverage report
705
+ - `priority` - `riskScore × (0.3 + 0.7 × uncoveredFraction)`; files without coverage data treat `uncovered = 1`
706
+ - `reasons` - inherited from the hotspot entry, including any `low coverage (X%)` or `moderate coverage (X%)` tags
707
+
708
+ **Options:**
709
+
710
+ | Flag | Description | Default |
711
+ |------|-------------|---------|
712
+ | `--limit <n>` | Number of entries to return | 30 (max 200) |
713
+
714
+ **How it feeds into `hotspots`:** when any coverage file exists, `projscan hotspots` automatically passes it into the risk calculator. Uncovered churning files get a score bump and a `low coverage (X%)` reason tag. No coverage file? Hotspots behaves exactly as before.
715
+
716
+ ### badge
717
+
718
+ ```bash
719
+ projscan badge
720
+ ```
721
+
722
+ Calculates the project health score and generates a [shields.io](https://shields.io) badge you can add to your README.
723
+
724
+ <img src="npx%20projscan%20badge.gif" alt="npx projscan badge" width="700">
725
+
726
+ ### mcp
727
+
728
+ ```bash
729
+ projscan mcp
730
+ projscan mcp --watch # 1.3+: also push notifications/file_changed on every batch
731
+ ```
732
+
733
+ Runs ProjScan as an [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server over stdio. AI coding agents (Claude Code, Cursor, Windsurf, any MCP client) can call ProjScan during a session to ground their suggestions in live project state.
734
+
735
+ With `--watch`, the server starts an in-process file watcher and emits a JSON-RPC `notifications/file_changed` notification on every debounced batch (paths + post-update graph size + timestamp). The capability is advertised under `experimental.fileChanged` on the `initialize` response so clients can detect support before subscribing. Off by default — agents that don't need push updates pay nothing for it.
736
+
737
+ See [MCP Server for AI Agents](#mcp-server-for-ai-agents).
738
+
739
+ ### session *(1.4+)*
740
+
741
+ ```bash
742
+ projscan session # current session summary
743
+ projscan session touched # files touched this session, newest-first
744
+ projscan session touched --source fs-watch
745
+ projscan session events # event log, newest-first
746
+ projscan session reset # discard the current session
747
+ ```
748
+
749
+ Inspects the durable cross-invocation session that the MCP server populates as agents work. State lives at `.projscan-cache/session.json` and is shared by every agent invocation against the same project. A new session starts when no previous session exists or when the previous one has been idle for more than an hour.
750
+
751
+ Touches come from three sources:
752
+
753
+ - **`tool-result`** — every MCP `tools/call` result is scanned for repo-relative file paths under known fields (`file`, `relativePath`, `paths`, `definitions`, `importers`, `reachable`, etc.) and each is auto-recorded.
754
+ - **`fs-watch`** — when `projscan mcp --watch` is on, every debounced file-change batch also records each changed path.
755
+ - **`explicit`** — reserved for future "agent says it edited X" hooks.
756
+
757
+ `projscan_session { action: "current" | "touched" | "events" | "reset" }` is the MCP-side mirror. Session resources and `projscan_agent_brief` include `coordinationHints` such as `current-worktree-check`, `remembered-session-context`, and `resolve-conflicts`, each with an exact follow-up command.
758
+
759
+ ---
760
+
761
+ ### trial
762
+
763
+ `projscan trial` is the top-level local adoption-readiness report. It wraps first-run activation, multi-repo dogfood, reviewer feedback summary, market validation, trust signals, and website proof into one verdict: `adopt`, `pilot`, `tune`, or `setup`.
764
+
765
+ ```bash
766
+ projscan trial --repo ../api --repo ../web --repo ../worker --feedback .projscan-feedback.json --format json
767
+ ```
768
+
769
+ Use it when deciding whether projscan is useful enough for a team to run on every PR.
770
+
771
+ ### telemetry
772
+
773
+ `projscan telemetry` exposes explicit default-off telemetry controls. It is for anonymous product-health metrics only; it never sends source code, file paths, repo names, branch names, package names, usernames, emails, raw findings, secrets, environment values, or scan reports.
774
+
775
+ ```bash
776
+ projscan telemetry status
777
+ projscan telemetry explain
778
+ projscan telemetry enable
779
+ projscan telemetry disable
780
+ ```
781
+
782
+ Use it alongside `projscan feedback`: telemetry can show whether teams finish setup and come back next week, while explicit feedback is still the evidence for minutes saved, prevented bad edits, and false positives.
783
+
784
+ ### dogfood
785
+
786
+ `projscan dogfood` is the adoption proof loop. It evaluates one or more real repositories and reports whether each repo can produce a validated PR comment, expose the repeat-use loop in `projscan start`, and pass basic MCP/setup readiness.
787
+
788
+ ```bash
789
+ projscan dogfood --repo ../api --repo ../web --repo ../worker --format json
790
+ ```
791
+
792
+ For market validation, capture structured reviewer feedback first:
793
+
794
+ ```bash
795
+ projscan feedback init --output .projscan-feedback.json
796
+ projscan feedback add --file .projscan-feedback.json --repo api --pr https://github.com/acme/api/pull/42 --reviewer @alice --useful true --minutes-saved 10
797
+ projscan feedback summary --file .projscan-feedback.json --format json
798
+ projscan dogfood --repo ../api --repo ../web --repo ../worker --feedback .projscan-feedback.json --format json
799
+ ```
800
+
801
+ Use it before broader rollout. The report includes feedback questions for the first real PR: did the comment save 10-20 minutes, what was missing or noisy, and which owner or command should have been clearer. With `--feedback`, the report also includes `marketValidation`: useful response count, total minutes saved, risky edits prevented, repeat PR use, false-positive reports, and website-ready proof markdown.
802
+
803
+ ## Health Score
804
+
805
+ Every `projscan doctor` and `projscan badge` run calculates a health score from 0 to 100 based on detected issues.
806
+
807
+ **Scoring:**
808
+
809
+ | Severity | Deduction per issue |
810
+ |----------|-------------------|
811
+ | Error | -20 points |
812
+ | Warning | -10 points |
813
+ | Info | -3 points |
814
+
815
+ **Grade thresholds:**
816
+
817
+ | Grade | Score Range | Meaning |
818
+ |-------|-------------|---------|
819
+ | A | 90–100 | Excellent - project follows best practices |
820
+ | B | 80–89 | Good - minor improvements possible |
821
+ | C | 70–79 | Fair - several issues to address |
822
+ | D | 60–69 | Poor - significant issues found |
823
+ | F | < 60 | Critical - major issues need attention |
824
+
825
+ The score appears in all output formats:
826
+ - **Console**: Shown at the top of the doctor report
827
+ - **JSON**: Included as `health.score` and `health.grade` fields
828
+ - **Markdown**: Shown as a heading with an auto-generated shields.io badge
829
+ - **HTML**: Shown in the health summary card
830
+ - **SARIF**: Not surfaced directly - SARIF is per-issue, not per-project. The score still drives `ci`'s exit code.
831
+
832
+ ---
833
+
834
+ ## Output Formats
835
+
836
+ Every command accepts the `--format` flag, but supported formats are command-dependent. Unsupported combinations fail with a clear message instead of falling back to console output.
837
+
838
+ ### Console (default)
839
+
840
+ Rich, colored terminal output with Unicode box-drawing characters and status icons. Best for interactive use.
841
+
842
+ ### JSON
843
+
844
+ Machine-readable output. Useful for piping into other tools, storing results, or building dashboards.
845
+
846
+ ```bash
847
+ projscan analyze --format json | jq '.issues[] | select(.severity == "error")'
848
+ projscan analyze --format json > analysis.json
849
+ ```
850
+
851
+ ### Markdown
852
+
853
+ Formatted Markdown suitable for saving as documentation or pasting into a PR description.
854
+
855
+ ```bash
856
+ projscan doctor --format markdown > HEALTH.md
857
+ ```
858
+
859
+ ### HTML
860
+
861
+ Self-contained HTML output for sharing scan, health, review, and risk snapshots.
862
+
863
+ ```bash
864
+ projscan analyze --format html > analysis.html
865
+ projscan doctor --format html > HEALTH.html
866
+ ```
867
+
868
+ Supported on `analyze`, `doctor`, `hotspots`, `coupling`, `pr-diff`, `review`, `impact`, and `coverage`.
869
+
870
+ ### SARIF
871
+
872
+ [SARIF 2.1.0](https://sarifweb.azurewebsites.net/) output - the industry standard for static analysis results. GitHub Code Scanning, Azure DevOps, GitLab, and many other systems consume SARIF natively.
873
+
874
+ ```bash
875
+ projscan ci --format sarif > projscan.sarif
876
+ ```
877
+
878
+ Supported on `analyze`, `audit`, `ci`, `doctor`, and `outdated`. Each issue is emitted as a SARIF `result` with:
879
+ - `ruleId` - stable rule identifier (e.g., `hardcoded-secret`, `missing-prettier`)
880
+ - `level` - `error`, `warning`, or `note` (mapped from projscan severity)
881
+ - `message.text` - the issue description
882
+ - `locations` - real file + line/column when the analyzer can supply them (security findings include line numbers); project-level issues anchor to repo root
883
+ - `properties.category` - the analyzer category (`security`, `formatting`, `architecture`, …)
884
+ - `properties.fixAvailable` - whether `projscan fix` can remediate it
885
+
886
+ When uploaded to GitHub Code Scanning, findings appear in the **Security → Code scanning** tab and (for PRs) as inline annotations on changed lines.
887
+
888
+ ---
889
+
890
+ ## Configuration (`.projscanrc`)
891
+
892
+ ProjScan loads a project-wide config from one of:
893
+
894
+ 1. A path passed via `--config <path>`
895
+ 2. `.projscanrc.json` at the repository root
896
+ 3. `.projscanrc` at the repository root (JSON format)
897
+ 4. A `"projscan"` key in `package.json`
898
+
899
+ **CLI flags always win over config.** The config provides defaults; flags override on a per-run basis.
900
+
901
+ ### Example `.projscanrc.json`
902
+
903
+ ```json
904
+ {
905
+ "minScore": 80,
906
+ "baseRef": "origin/main",
907
+ "ignore": ["**/fixtures/**", "**/generated/**"],
908
+ "scan": {
909
+ "includeIgnored": false,
910
+ "scanEnvValues": false,
911
+ "offline": false
912
+ },
913
+ "disableRules": ["missing-editorconfig", "large-*"],
914
+ "severityOverrides": {
915
+ "missing-prettier": "info"
916
+ },
917
+ "hotspots": {
918
+ "limit": 20,
919
+ "since": "6 months ago"
920
+ }
921
+ }
922
+ ```
923
+
924
+ ### Fields
925
+
926
+ | Field | Type | Effect |
927
+ |-------|------|--------|
928
+ | `minScore` | number (0–100) | Default threshold for `projscan ci`. Clamped to 0–100. |
929
+ | `baseRef` | string | Default base ref for `--changed-only`. |
930
+ | `ignore` | string[] | Extra glob patterns added to the built-in ignore list (`node_modules`, `.git`, `dist`, `build`, `coverage`, `.next`, `.nuxt`, `.cache`, `.turbo`, `.output`). |
931
+ | `scan.includeIgnored` | boolean | Explicitly include files hidden by Git ignore rules. Default `false`. |
932
+ | `scan.scanEnvValues` | boolean | Explicitly read `.env*` contents during secret-pattern checks. Default `false`; `.env` files are path-only. |
933
+ | `scan.offline` | boolean | Block projscan network-capable features: telemetry sending, `audit`, registry checks, and optional semantic model loading. Default `false`. |
934
+ | `disableRules` | string[] | Silence rules by id. Exact match (`missing-prettier`) or wildcard prefix (`large-*`). |
935
+ | `severityOverrides` | `Record<string, 'info' \| 'warning' \| 'error'>` | Remap a rule's severity. Useful for downgrading project-specific false positives without disabling them. |
936
+ | `hotspots.limit` | number (1–100) | Default limit for `projscan hotspots`. |
937
+ | `hotspots.since` | string | Default git history window for `projscan hotspots`. |
938
+
939
+ Invalid JSON in a discovered config file is a hard error - projscan exits rather than silently ignoring it.
940
+
941
+ ### Embedded config in `package.json`
942
+
943
+ If you prefer to keep everything in `package.json`:
944
+
945
+ ```json
946
+ {
947
+ "name": "my-app",
948
+ "projscan": {
949
+ "minScore": 80,
950
+ "disableRules": ["missing-editorconfig"]
951
+ }
952
+ }
953
+ ```
954
+
955
+ ### Monorepo: cross-package import policy *(0.14+)*
956
+
957
+ In a monorepo, you can declare which packages may import which. Violations surface as `cross-package-violation-N` issues in `projscan_doctor` and on the CLI. The analyzer is **off by default**; adding any rule turns it on for the matching `from` package.
958
+
959
+ ```json
960
+ {
961
+ "monorepo": {
962
+ "importPolicy": [
963
+ { "from": "web", "allow": ["shared", "ui-kit"] },
964
+ { "from": "shared", "deny": ["web", "api"] },
965
+ { "from": "scripts", "allow": ["*"] }
966
+ ]
967
+ }
968
+ }
969
+ ```
970
+
971
+ Each rule has a `from` (source package name, matches `WorkspacePackage.name`) plus exactly one of `allow` or `deny`:
972
+
973
+ - **`allow`** is allow-list semantics: edges out of `from` are only permitted to packages in the list. Anything else is denied.
974
+ - **`deny`** is deny-list semantics: edges out of `from` are permitted unless the target is in the list.
975
+
976
+ Patterns support `*` (wildcard), `pkg/*` (suffix glob), `*/sub` (prefix glob), and exact package names. The check runs once per `buildCodeGraph` call; capped at 50 reported violations per run to keep doctor output bounded.
977
+
978
+ **Why use it:** to keep refactoring options open inside a package. If `web` is only allowed to import from `shared` and `ui-kit`, then changes inside `api`'s internals can't break `web` no matter how aggressive. The rules document the intended layering and the CI guard enforces it.
979
+
980
+ ---
981
+
982
+ ## PR-Diff Mode (`--changed-only`)
983
+
984
+ For CI on pull requests, you usually only care about issues that **this PR introduced** - not the long tail of legacy warnings elsewhere in the repo. `--changed-only` scopes the report to files changed vs a base ref.
985
+
986
+ **How it decides what's "changed":**
987
+
988
+ 1. If `--base-ref <ref>` is passed explicitly, use that.
989
+ 2. Otherwise, try in order: `origin/main`, `origin/master`, `main`, `master`, `HEAD~1`.
990
+ 3. If none of those refs exist, fall back to uncommitted working-tree changes (`git status --porcelain`).
991
+ 4. If the project isn't a git repository, skip the filter and report everything, with a warning on stderr.
992
+
993
+ **How it filters:**
994
+
995
+ Issues that carry a `location` (file path) are kept only if that file appears in the changed set. **Project-level issues without a location are dropped** in `--changed-only` mode - that's intentional: "No ESLint config" is a real issue, but it shouldn't block every PR that doesn't touch ESLint.
996
+
997
+ **When to use it:**
998
+
999
+ - `projscan ci --changed-only` on every PR
1000
+ - Skip it on pushes to `main` (you want to see all project-level issues there)
1001
+ - Combine with a looser `--min-score` on PRs and a stricter one on `main`
1002
+
1003
+ Example GitHub Actions snippet:
1004
+
1005
+ ```yaml
1006
+ - uses: abhiyoheswaran1/projscan@v1
1007
+ with:
1008
+ min-score: ${{ github.event_name == 'pull_request' && '60' || '70' }}
1009
+ changed-only: ${{ github.event_name == 'pull_request' }}
1010
+ ```
1011
+
1012
+ ---
1013
+
1014
+ ## Global Options
1015
+
1016
+ | Option | Description |
1017
+ |--------|-------------|
1018
+ | `--format <type>` | Output format: `console` (default), `json`, `markdown`, `sarif`, `html` (command-dependent) |
1019
+ | `--config <path>` | Path to a `.projscanrc` config file |
1020
+ | `--include-ignored` | Explicitly include files hidden by Git ignore rules |
1021
+ | `--scan-env-values` | Explicitly read `.env*` contents during secret checks |
1022
+ | `--offline` | Block projscan network-capable features for this run |
1023
+ | `--changed-only` | Scope to files changed vs base ref (applies to `analyze`, `doctor`, `ci`) |
1024
+ | `--base-ref <ref>` | Git base ref for `--changed-only` (default: origin/main) |
1025
+ | `--verbose` | Show debug-level logging - useful for diagnosing scan issues |
1026
+ | `--quiet` | Suppress all non-essential output (spinners, status messages) |
1027
+ | `-V, --version` | Print the version number |
1028
+ | `-h, --help` | Print help for any command |
1029
+
1030
+ **Per-command help:**
1031
+
1032
+ ```bash
1033
+ projscan fix --help
1034
+ projscan ci --help
1035
+ ```
1036
+
1037
+ ---
1038
+
1039
+ ## What ProjScan Detects
1040
+
1041
+ ### Languages
1042
+
1043
+ ProjScan maps file extensions to language names. Supported languages include TypeScript, JavaScript, Python, Go, Rust, Java, C#, C++, C, Ruby, PHP, Swift, Kotlin, Dart, Lua, Scala, R, Shell, CSS, SCSS/Sass, HTML, JSON, YAML, Markdown, SQL, and more.
1044
+
1045
+ The **primary language** is the one with the most files.
1046
+
1047
+ ### Frameworks and Libraries
1048
+
1049
+ Detection uses two strategies:
1050
+
1051
+ **1. Dependency scanning** - checks `package.json` for known framework packages:
1052
+
1053
+ React, Next.js, Vue.js, Nuxt.js, Svelte, SvelteKit, Angular, Solid.js, Express, Fastify, NestJS, Hono, Koa, Apollo Server, tRPC, Prisma, Drizzle ORM, Mongoose, TypeORM, Sequelize, Tailwind CSS, Vite, Webpack, Rollup, esbuild, Vitest, Jest, Mocha, Cypress, Playwright, Storybook, and more.
1054
+
1055
+ **2. Config file presence** - checks for known configuration files:
1056
+
1057
+ `next.config.js`, `nuxt.config.ts`, `svelte.config.js`, `angular.json`, `vite.config.ts`, `webpack.config.js`, `tailwind.config.js`, `prisma/schema.prisma`, `docker-compose.yml`, `Dockerfile`, and more.
1058
+
1059
+ Each detection has a **confidence level** (high, medium, low) and a **category** (frontend, backend, testing, bundler, css, other).
1060
+
1061
+ ### Issues and Health Checks
1062
+
1063
+ ProjScan ships with six analyzer modules:
1064
+
1065
+ #### 1. ESLint Check
1066
+ - Looks for `.eslintrc.*`, `eslint.config.*`, or `eslintConfig` in package.json
1067
+ - If missing: warning with auto-fix available
1068
+
1069
+ #### 2. Prettier Check
1070
+ - Looks for `.prettierrc`, `.prettierrc.*`, `prettier.config.*`, or `prettier` in package.json
1071
+ - If missing: warning with auto-fix available
1072
+
1073
+ #### 3. Test Check
1074
+ - Looks for test frameworks in devDependencies (vitest, jest, mocha, etc.)
1075
+ - Looks for test files (`*.test.*`, `*.spec.*`, `__tests__/`)
1076
+ - If no framework: warning with auto-fix available
1077
+ - If framework exists but zero test files: separate warning
1078
+
1079
+ #### 4. Architecture Check
1080
+ - **Large utility directories**: warns if `utils/`, `helpers/`, or `lib/` contains 10+ files (issue anchored to the directory path)
1081
+ - **Missing .editorconfig**: info with auto-fix available
1082
+ - **Missing/empty README**: warning / info
1083
+
1084
+ #### 5. Dependency Risk Check
1085
+ - Warns if production dependencies exceed 50
1086
+ - Errors if total dependencies exceed 100
1087
+ - Flags `*` or `latest` version ranges
1088
+ - Warns if no lock file is present
1089
+
1090
+ #### 6. Security Check
1091
+ - **Committed `.env` files**: Flags `.env`, `.env.local`, `.env.production`, etc. (but not `.env.example`, `.env.sample`, `.env.template`) - location anchored to the file
1092
+ - **Private key files**: Detects `.pem`, `.key`, `id_rsa`, `id_ed25519`, `.p12`, `.pfx` files
1093
+ - **Hardcoded secrets**: Scans file contents (files under 512KB) for:
1094
+ - AWS Access Keys (`AKIA...`)
1095
+ - GitHub tokens (`ghp_...`, `ghs_...`)
1096
+ - Slack tokens (`xoxb-...`, `xoxp-...`)
1097
+ - Generic patterns (`password=`, `secret=`, `api_key=` with quoted values)
1098
+ - PEM private key headers
1099
+ Each finding carries the exact **line number** of the match, which SARIF and GitHub Code Scanning use for inline PR annotations.
1100
+ - **Missing `.gitignore` entries**: Warns if `.env` is not in `.gitignore`
1101
+ - **Path-only `.env` handling**: Tracked `.env*` files are flagged by filename, but their values are not read unless `--scan-env-values` or `scan.scanEnvValues: true` is set
1102
+
1103
+ Every issue carries an optional `locations: IssueLocation[]` field. Analyzers populate it when the finding is tied to a specific file (and sometimes a specific line). This field powers SARIF output and `--changed-only` filtering.
1104
+
1105
+ ---
1106
+
1107
+ ## Auto-Fix System
1108
+
1109
+ The fix system is intentionally conservative. It only creates configuration files and installs well-known packages. It never modifies your source code.
1110
+
1111
+ ### How fixes work
1112
+
1113
+ 1. `projscan fix` runs the issue detection pipeline
1114
+ 2. Filters to issues where `fixAvailable: true`
1115
+ 3. Shows you exactly what each fix will do
1116
+ 4. Prompts for confirmation (unless `-y` is passed)
1117
+ 5. Applies fixes sequentially, showing progress
1118
+ 6. Reports success/failure for each fix
1119
+
1120
+ ### Fix details
1121
+
1122
+ **ESLint fix:**
1123
+ - Creates `eslint.config.js` using the flat config format (ESLint v9+)
1124
+ - If TypeScript files are detected, includes `typescript-eslint` plugin
1125
+ - Installs `eslint` and `@eslint/js` via the detected package manager
1126
+
1127
+ **Prettier fix:**
1128
+ - Creates `.prettierrc` with these defaults:
1129
+ ```json
1130
+ {
1131
+ "semi": true,
1132
+ "singleQuote": true,
1133
+ "trailingComma": "all",
1134
+ "printWidth": 100,
1135
+ "tabWidth": 2
1136
+ }
1137
+ ```
1138
+ - Installs `prettier`
1139
+
1140
+ **Test framework fix:**
1141
+ - Creates `vitest.config.ts`
1142
+ - Creates a sample test file at `tests/example.test.ts`
1143
+ - Adds `"test": "vitest run"` to package.json scripts (if not already present)
1144
+ - Installs `vitest`
1145
+
1146
+ **EditorConfig fix:**
1147
+ - Creates `.editorconfig`
1148
+ - Installs nothing - EditorConfig is handled by editor plugins
1149
+
1150
+ ---
1151
+
1152
+ ## Architecture Diagrams
1153
+
1154
+ The `diagram` command builds a layered view of your application. It works by:
1155
+
1156
+ 1. Scanning the top-level directory names in your project
1157
+ 2. Matching them against known patterns (e.g., `components/` -> Frontend, `routes/` -> API)
1158
+ 3. Cross-referencing with detected frameworks
1159
+ 4. Rendering only the layers that are present
1160
+
1161
+ This is heuristic-based and works best with conventional project structures. Projects with unconventional layouts will get a generic "Application" layer.
1162
+
1163
+ ---
1164
+
1165
+ ## File Explanation Engine
1166
+
1167
+ The `explain` command performs regex-based static analysis. It does not execute your code or make network calls.
1168
+
1169
+ **Import detection** handles:
1170
+ - ES modules: `import { foo } from 'bar'`
1171
+ - Default imports: `import foo from 'bar'`
1172
+ - Namespace imports: `import * as foo from 'bar'`
1173
+ - Side-effect imports: `import 'bar'`
1174
+ - CommonJS: `const foo = require('bar')`
1175
+
1176
+ **Export detection** handles:
1177
+ - Named exports: `export function`, `export class`, `export const`
1178
+ - Type exports: `export interface`, `export type`
1179
+ - Default exports: `export default`
1180
+
1181
+ **Purpose inference** is based on file name and directory conventions. For example:
1182
+ - Files named `*.test.*` or `*.spec.*` → "Test file"
1183
+ - Files in `routes/` → "Route definitions"
1184
+ - Files named `index.ts` → "Module entry point"
1185
+ - Files in `components/` → "UI component"
1186
+
1187
+ ---
1188
+
1189
+ ## Hotspots & Ownership
1190
+
1191
+ The `hotspots` command reads `git log` to build a per-file risk picture. The risk score combines five signals:
1192
+
1193
+ | Signal | Weight | Intuition |
1194
+ |--------|--------|-----------|
1195
+ | Churn | 0.40 | Files that change often are more likely to harbor bugs |
1196
+ | Complexity (AST CC) | 0.30 | Files with more decision points are harder to reason about. **AST-derived McCabe cyclomatic complexity for JS/TS, Python, Go, Java, Ruby, Rust, PHP, and C#; falls back to LOC for non-AST languages.** |
1197
+ | Issue density | 0.20 | Files that already have open issues need help |
1198
+ | Recency | 0.10 | Recently touched hot files deserve attention first |
1199
+ | Bus factor | penalty tag | Single-author + high churn = organizational risk |
1200
+
1201
+ **Ownership signals:**
1202
+ - `primaryAuthor` - the top committer by share
1203
+ - `primaryAuthorShare` - fraction of commits (0–1)
1204
+ - `topAuthors` - ranked list
1205
+ - `busFactorOne` - `true` if the primary author owns > 80% of commits **and** churn is above the median
1206
+
1207
+ **Bus-factor-one files get a score penalty and a `bus-factor-one` reason tag** - they show up higher in the ranking because if that one author leaves, the knowledge is gone.
1208
+
1209
+ **What "hotspots" can't do:**
1210
+ - It's a heuristic, not a proof. Low-risk files may still have bugs.
1211
+ - It weights LOC as a proxy for complexity; a clean 1,000-line file may rank higher than it deserves.
1212
+ - It has no visibility into logical coupling - two small files that change together still look independent.
1213
+
1214
+ `projscan diff` snapshots the top 20 hotspots and tracks which ones **rose** / **fell** / **appeared** / **resolved** over time.
1215
+
1216
+ ---
1217
+
1218
+ ## MCP Server for AI Agents
1219
+
1220
+ `projscan mcp` runs ProjScan as an [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server over stdio. AI coding agents can query ProjScan during a session to ground their suggestions in live project state.
1221
+
1222
+ **Core tools include:**
1223
+
1224
+ *Structural / agent-native:*
1225
+ - `projscan_start` — first-60-seconds repo orientation with setup diagnostics, recommended workflow, top risks, adoption gaps, and next commands.
1226
+ - `projscan_semantic_graph` — the code graph, two ways. With no `query`: the stable v3 semantic graph (file/function/package/symbol nodes and normalized structural edges). With `query: { direction, file?, symbol? }`: a targeted structural query (`imports`, `exports`, `importers`, `symbol_defs`, `package_importers`) in milliseconds on a warm cache. *(Subsumes the former `projscan_graph`, removed in 4.0.)*
1227
+ - `projscan_dataflow` — direct, propagated, and bridge source-to-sink dataflow risks over the function graph.
1228
+ - `projscan_search` — BM25-ranked search. Scopes: `auto` / `content` (ranked content + symbol + path boosts, line excerpts), `symbols` (exported names), `files` (path substring). Optional semantic mode + sub-file chunking with the `@xenova/transformers` peer dep.
1229
+ - `projscan_coupling` — per-file fan-in / fan-out / instability + Tarjan circular-import cycles.
1230
+ - `projscan_pr_diff` — structural (AST) diff between two refs. Returns added / removed / modified files with explicit lists of exports, imports, call sites, and ΔCC / Δfan-in.
1231
+ - `projscan_review` — one-call PR review composing `pr_diff` + per-changed-file risk + new/expanded cycles + risky function additions + dependency changes + a verdict (`ok` / `review` / `block`).
1232
+ - `projscan_workplan` — prioritized agent execution plan with evidence, suggested tools, verification commands, coordination context, and handoff text.
1233
+ - `projscan_bug_hunt` — prioritized bug-hunt fix queue with per-target verification.
1234
+ - `projscan_agent_brief` — compact next-agent context packet with focus items, guardrails, repo context, and suggested next actions.
1235
+ - `projscan_quality_scorecard` — dimensioned quality view with top risks and verification commands.
1236
+ - `projscan_adoption` — adoption helper for MCP client snippets, MCP setup doctor, agent workflow recipes, and first-run diagnostics.
1237
+ - `projscan_release_train` — product-line readiness plan with scope and next-action evidence.
1238
+ - `projscan_evidence_pack` — approval packet with planning, bug-hunt, workplan, preflight, changelog, and website prompt evidence.
1239
+ - `projscan_regression_plan` — smoke/focused/full regression matrix with deduplicated verification commands.
1240
+ - `projscan_fix_suggest` — rule-driven action prompt for any open issue: headline, why, where, instruction, optional suggested test.
1241
+ - `projscan_explain_issue` — deep dive on one issue: code excerpt, related issues, similar past commits via `git log --grep`, plus the structured FixSuggestion.
1242
+ - `projscan_impact` — transitive blast-radius for a file or symbol. BFS over reverse imports + symbol callsites. Cycle-safe; depth-bounded.
1243
+
1244
+ *Analysis:*
1245
+ - `projscan_analyze` — full project snapshot.
1246
+ - `projscan_doctor` — health score + issues with inline `suggestedAction` hints.
1247
+ - `projscan_preflight` — compact `proceed` / `caution` / `block` gate with health, changed-file, review, session, plugin, and supply-chain evidence.
1248
+ - `projscan_hotspots` — ranked file risk (or top-N risky functions with `view: "functions"`).
1249
+ - `projscan_file` — per-file inspection (purpose, imports, exports, smells, risk, ownership, related issues, CC, fan-in/out, per-function CC table).
1250
+ - `projscan_structure` — directory tree.
1251
+ - `projscan_coverage` — coverage × hotspots, ranked by "risk × uncovered fraction".
1252
+
1253
+ *Dependencies (workspace-aware in monorepos):*
1254
+ - `projscan_dependencies` — declared deps + risks, with a `byWorkspace` breakdown.
1255
+ - `projscan_outdated` — declared-vs-installed drift (offline), per-package.
1256
+ - `projscan_audit` — npm audit, normalized; `package` arg scopes findings to one workspace's direct deps.
1257
+ - `projscan_upgrade` — upgrade preview: drift + local CHANGELOG + importers.
1258
+
1259
+ *Workspace:*
1260
+ - `projscan_workspaces` — list monorepo packages (npm/yarn/pnpm/Nx/Turbo/Lerna).
1261
+
1262
+ *Session (1.4+):*
1263
+ - `projscan_session` — durable cross-invocation session. Subactions: `current`, `touched`, `events`, `reset`. Auto-populated from every tool result and from `notifications/file_changed` push events when `--watch` is on.
1264
+
1265
+ **Every tool accepts `max_tokens` (optional).** projscan estimates serialized output and truncates the largest array field until it fits. Over-budget responses include a `_budget: { truncated: true, estimatedTokens, maxTokens }` field. Tools that return arrays also support cursor pagination via `cursor` + `page_size`.
1266
+
1267
+ **Every tool result also carries a `_cost` sidecar (1.5+).** `_cost: { estimatedTokens: N }` lets agents see what they paid for a call without counting tokens themselves — useful for budgeting tool sequences. Cost is the chars-divided-by-4 approximation of the serialized payload (within ~±15% of GPT/Claude tokenizers for code-shaped output).
1268
+
1269
+ **`projscan_review` accepts `max_cost_tokens` (1.5+).** Adaptive shape budget. The tool picks a tier based on the value and reshapes the response *before* serializing — different from `max_tokens` (post-hoc truncation):
1270
+
1271
+ - **full** (no budget, or ≥ 7000): everything — full structural diff + per-changed-file lists + all cycles + risky functions + dependency changes.
1272
+ - **summary** (3000–6999): verdict + summary + top-5 changed files + top-3 of each list, with the heavy per-file expansion arrays stripped.
1273
+ - **verdict-only** (<3000): verdict + summary + base/head + aggregate `totals`. Roughly 500 tokens.
1274
+
1275
+ The chosen tier is surfaced as a top-level `tier` field on the response and lifted into `_cost.tier` so an agent sees it in one place. Both `_cost` and `_budget` can appear on the same response when both `max_cost_tokens` and `max_tokens` are passed.
1276
+
1277
+ **Incremental cache:** projscan caches parsed ASTs at `.projscan-cache/graph.json`. First run populates, subsequent runs re-parse only files whose `mtime` changed. Auto-gitignored. Delete the directory to force a rebuild.
1278
+
1279
+ For the analyzer and reporter plugin platform, including minimal manifests, analyzer modules, and `--reporter <name>`, see [Plugin Authoring](PLUGIN-AUTHORING.md). Reporter plugins are the supported boundary for custom presentation, white-label reports, and team-branded CLI summaries; the built-in HTML reporter remains the default core renderer.
1280
+
1281
+ **Prompts (6, parameterized with live project data):**
1282
+ - `prioritize_refactoring` — ranked plan grounded in current hotspots
1283
+ - `investigate_file` — senior-engineer brief for a specific file
1284
+ - `refactor_hotspot` *(1.5+)* — step-by-step refactor plan for one hotspot file
1285
+ - `triage_doctor_issues` *(1.5+)* — critical / important / backlog ordering of open issues
1286
+ - `review_this_pr` *(1.5+)* — PR-comment-ready review primed with the structural diff and verdict
1287
+ - `safely_rename_symbol` *(1.5+)* — ordered rename + verification checklist via `projscan_impact` blast radius
1288
+
1289
+ **Resources (3, readable on demand):**
1290
+ - `projscan://health`
1291
+ - `projscan://hotspots`
1292
+ - `projscan://structure`
1293
+
1294
+ ### Setup: Claude Code
1295
+
1296
+ ```bash
1297
+ claude mcp add projscan -- npx projscan mcp
1298
+ ```
1299
+
1300
+ ### Setup: Cursor / Windsurf / any MCP client
1301
+
1302
+ ```json
1303
+ {
1304
+ "mcpServers": {
1305
+ "projscan": {
1306
+ "command": "npx",
1307
+ "args": ["projscan", "mcp"]
1308
+ }
1309
+ }
1310
+ }
1311
+ ```
1312
+
1313
+ Once connected, your agent can ask *"what are the riskiest files in this repo?"* or *"run projscan_doctor before proposing an edit"* and get grounded answers.
1314
+
1315
+ ---
1316
+
1317
+ ## Performance
1318
+
1319
+ ProjScan is designed to be fast enough to run on every save or as a pre-commit hook.
1320
+
1321
+ | Metric | Target |
1322
+ |--------|--------|
1323
+ | 5,000 files | < 1.5 seconds |
1324
+ | 20,000 files | < 3 seconds |
1325
+ | Network requests | Zero |
1326
+ | Runtime dependencies | 4 packages |
1327
+
1328
+ **How it stays fast:**
1329
+ - Uses `fast-glob` for file walking
1330
+ - Language detection is a pure function - no I/O, just extension mapping
1331
+ - Framework detection reads at most one file (`package.json`) plus checks file names already in memory
1332
+ - Hotspots is the only command that shells out to `git`; that's ~1s on a 5k-commit repo
1333
+ - `--changed-only` mode scopes reporting (not scanning), so scan time is unchanged - but CI jobs with heavy parsing can pair it with a smaller file set if you want faster runs
1334
+
1335
+ ---
1336
+
1337
+ ## Common Workflows
1338
+
1339
+ ### Onboarding to a new codebase
1340
+
1341
+ ```bash
1342
+ cd new-project
1343
+ projscan # Full overview
1344
+ projscan structure # Understand the layout
1345
+ projscan diagram # See the architecture
1346
+ projscan hotspots # Which files are risky?
1347
+ projscan file <path> # Drill into a hotspot
1348
+ ```
1349
+
1350
+ ### Pre-commit health check
1351
+
1352
+ ```bash
1353
+ projscan doctor
1354
+ ```
1355
+
1356
+ ### Setting up a new project
1357
+
1358
+ ```bash
1359
+ mkdir my-project && cd my-project
1360
+ npm init -y
1361
+ projscan fix -y # Set up ESLint, Prettier, Vitest, EditorConfig
1362
+ ```
1363
+
1364
+ ### Generating a project report for a PR
1365
+
1366
+ ```bash
1367
+ projscan analyze --format markdown > ANALYSIS.md
1368
+ ```
1369
+
1370
+ ### Tech-debt prioritization
1371
+
1372
+ ```bash
1373
+ projscan hotspots --format markdown > HOTSPOTS.md
1374
+ # Paste into a tech-debt ticket
1375
+ ```
1376
+
1377
+ ### Extracting data for a dashboard
1378
+
1379
+ ```bash
1380
+ projscan analyze --format json > /tmp/projscan-report.json
1381
+ ```
1382
+
1383
+ ---
1384
+
1385
+ ## CI/CD Integration
1386
+
1387
+ ProjScan has three first-class CI integration paths:
1388
+
1389
+ ### 1. First-party GitHub Action (recommended)
1390
+
1391
+ The easiest path - installs projscan, runs the health gate, uploads SARIF to GitHub Code Scanning.
1392
+
1393
+ ```yaml
1394
+ name: ProjScan
1395
+ on:
1396
+ push: { branches: [main] }
1397
+ pull_request: { branches: [main] }
1398
+
1399
+ permissions:
1400
+ contents: read
1401
+ security-events: write # required for SARIF upload
1402
+
1403
+ jobs:
1404
+ scan:
1405
+ runs-on: ubuntu-latest
1406
+ steps:
1407
+ - uses: actions/checkout@v4
1408
+ with: { fetch-depth: 0 } # needed for --changed-only
1409
+ - uses: actions/setup-node@v4
1410
+ with: { node-version: 22 }
1411
+ - uses: abhiyoheswaran1/projscan@v1
1412
+ with:
1413
+ min-score: '70'
1414
+ changed-only: 'true'
1415
+ ```
1416
+
1417
+ **Inputs:** `min-score`, `changed-only`, `base-ref`, `config`, `sarif-file`, `upload-sarif`, `working-directory`, `version`.
1418
+
1419
+ **Outputs:** `score`, `grade`.
1420
+
1421
+ Findings show up in **Security → Code scanning**; PR annotations are automatic.
1422
+
1423
+ ### 2. Plain workflow (no SARIF upload)
1424
+
1425
+ If you'd rather skip Code Scanning, `projscan init github-action` writes a pull-request workflow that builds a projscan evidence comment, validates required review sections before posting, and fails only on concrete preflight blocks. The repo also ships `.github/projscan-ci.yml` as a lower-level health-report workflow.
1426
+
1427
+ ### 3. Any CI - raw `projscan ci`
1428
+
1429
+ The `ci` command is purpose-built for pipelines:
1430
+
1431
+ ```bash
1432
+ projscan ci # Fail if score < 70 (default)
1433
+ projscan ci --min-score 80 # Custom threshold
1434
+ projscan ci --changed-only # Gate only on PR diff
1435
+ projscan ci --format json # JSON output for scripts
1436
+ projscan ci --format sarif > projscan.sarif # SARIF for any consumer
1437
+ ```
1438
+
1439
+ **JSON output in a script:**
1440
+
1441
+ ```bash
1442
+ result=$(projscan ci --min-score 0 --format json)
1443
+ pass=$(echo "$result" | jq '.ci.pass')
1444
+ score=$(echo "$result" | jq '.ci.score')
1445
+ echo "Score: $score, Pass: $pass"
1446
+ ```
1447
+
1448
+ ### Tracking health over time in CI
1449
+
1450
+ Combine `ci` with `diff` to track regressions:
1451
+
1452
+ ```bash
1453
+ projscan diff --save-baseline # Run once to create baseline
1454
+ # Commit .projscan-baseline.json to your repo
1455
+
1456
+ # In CI, compare against baseline:
1457
+ projscan diff --format json # Shows new/resolved issues + hotspot movements
1458
+ ```
1459
+
1460
+ ---
1461
+
1462
+ ## Troubleshooting
1463
+
1464
+ ### "No package.json found"
1465
+
1466
+ The `dependencies` and `fix` commands require a `package.json` in the current directory. Other commands (`analyze`, `structure`, `diagram`, `explain`) work without one.
1467
+
1468
+ ### Scan is slow
1469
+
1470
+ If scanning takes more than a few seconds, check whether you have large unignored directories. ProjScan ignores `node_modules`, `.git`, `dist`, `build`, `coverage`, `.next`, `.nuxt`, `.cache`, `.turbo`, and `.output` by default. Add your own patterns via `.projscanrc` → `ignore`.
1471
+
1472
+ ### Hotspots shows "not a git repository"
1473
+
1474
+ `hotspots` needs git history to compute churn and ownership. Either run it inside a git repo, or skip the command.
1475
+
1476
+ ### `--changed-only` reports everything
1477
+
1478
+ Check stderr for a warning. Most common causes:
1479
+ - Running outside a git repository
1480
+ - The base ref doesn't exist (e.g., `origin/main` isn't fetched in a shallow CI clone - set `fetch-depth: 0` in checkout)
1481
+ - Fresh commit with no parent (no `HEAD~1`)
1482
+
1483
+ ### SARIF upload fails with "permission denied"
1484
+
1485
+ The workflow needs `permissions: security-events: write`. The first-party Action sets this implicitly; plain workflows need to add it explicitly.
1486
+
1487
+ ### Fix command fails to install packages
1488
+
1489
+ The fix system uses `npm install` by default. If you use yarn or pnpm, the install step may behave differently. Check your package manager's output for errors.
1490
+
1491
+ ---
1492
+
1493
+ ## Project Internals
1494
+
1495
+ For contributors and the curious - here's how ProjScan is structured:
1496
+
1497
+ ```
1498
+ src/
1499
+ ├── cli/
1500
+ │ └── index.ts # CLI entry point; all commands defined here
1501
+ ├── core/
1502
+ │ ├── repositoryScanner.ts # File tree walking, directory tree building
1503
+ │ ├── languageDetector.ts # Extension -> language mapping
1504
+ │ ├── frameworkDetector.ts # Framework detection from deps + config files
1505
+ │ ├── dependencyAnalyzer.ts # package.json parsing, risk detection
1506
+ │ ├── issueEngine.ts # Runs all analyzers, aggregates issues
1507
+ │ ├── hotspotAnalyzer.ts # git churn × complexity × issues × ownership
1508
+ │ ├── fileInspector.ts # Per-file inspection (purpose, imports, exports, risk)
1509
+ │ ├── importGraph.ts # Source-wide import graph for unused-dep / dead-code
1510
+ │ ├── outdatedDetector.ts # Declared-vs-installed drift check (offline)
1511
+ │ ├── auditRunner.ts # npm audit wrapper + SARIF normalization
1512
+ │ ├── upgradePreview.ts # Offline upgrade preview (CHANGELOG + importers)
1513
+ │ ├── coverageParser.ts # lcov / coverage-final / coverage-summary parser
1514
+ │ ├── coverageJoin.ts # Join hotspots × coverage - "scariest untested files"
1515
+ │ ├── ast.ts # @babel/parser wrapper → imports + exports + call sites
1516
+ │ ├── codeGraph.ts # Bidirectional file×symbol graph built from AST
1517
+ │ ├── indexCache.ts # mtime-keyed .projscan-cache/graph.json
1518
+ │ └── searchIndex.ts # BM25-ranked inverted index (content + symbols + path)
1519
+ ├── analyzers/
1520
+ │ ├── eslintCheck.ts
1521
+ │ ├── prettierCheck.ts
1522
+ │ ├── testCheck.ts
1523
+ │ ├── architectureCheck.ts
1524
+ │ ├── dependencyRiskCheck.ts
1525
+ │ ├── securityCheck.ts
1526
+ │ ├── unusedDependencyCheck.ts
1527
+ │ └── deadCodeCheck.ts
1528
+ ├── fixes/
1529
+ │ ├── eslintFix.ts
1530
+ │ ├── prettierFix.ts
1531
+ │ ├── testFix.ts
1532
+ │ ├── editorconfigFix.ts
1533
+ │ └── fixRegistry.ts
1534
+ ├── reporters/
1535
+ │ ├── consoleReporter.ts # Rich terminal output with chalk
1536
+ │ ├── jsonReporter.ts # JSON output
1537
+ │ ├── markdownReporter.ts # Markdown output
1538
+ │ └── sarifReporter.ts # SARIF 2.1.0 output
1539
+ ├── mcp/
1540
+ │ ├── server.ts # JSON-RPC 2.0 dispatcher, stdio transport, negotiation
1541
+ │ ├── tools.ts # 41 MCP tools (barrel; per-tool files under tools/)
1542
+ │ ├── tokenBudget.ts # Record-aware response truncator
1543
+ │ ├── pagination.ts # Cursor-based pagination (opaque base64 + checksum)
1544
+ │ ├── progress.ts # notifications/progress plumbing
1545
+ │ ├── chunker.ts # Opt-in response chunking (stream: true)
1546
+ │ ├── prompts.ts # 2 parameterized prompts
1547
+ │ └── resources.ts # 3 on-demand resources
1548
+ ├── utils/
1549
+ │ ├── fileWalker.ts # fast-glob wrapper with ignore patterns
1550
+ │ ├── logger.ts # Structured logger with levels
1551
+ │ ├── scoreCalculator.ts # Health score + shields.io badge
1552
+ │ ├── baseline.ts # Baseline save/load/diff (issues + hotspots)
1553
+ │ ├── config.ts # .projscanrc loader + rule application
1554
+ │ ├── changedFiles.ts # git-based changed-files detector
1555
+ │ ├── packageJsonLocator.ts # Line-number lookup for package.json deps
1556
+ │ ├── semver.ts # Tiny semver parser/compare/drift
1557
+ │ ├── banner.ts # CLI banner + help rendering
1558
+ │ └── cache.ts # Small LRU for hot paths
1559
+ └── types.ts # All shared TypeScript interfaces
1560
+ ```
1561
+
1562
+ **Key design decisions:**
1563
+ - **Single `types.ts`** - avoids circular dependencies between modules
1564
+ - **ESM-only** - required by chalk v5 and ora v8; all imports use `.js` extensions
1565
+ - **Pure functions where possible** - `detectLanguages` is pure (no I/O), trivially testable
1566
+ - **No class hierarchies** - analyzers, fixes, reporters, and MCP tools are plain functions with consistent signatures
1567
+ - **Opt-in config** - `.projscanrc` is never required, but when present it tunes defaults without needing to change CI scripts