|
1 | | -# CodeRadar |
| 1 | +# 📡 CodeRadar |
2 | 2 |
|
3 | | -Static analysis toolkit that maps UI components to their data sources (APIs, state, events) — enabling AI agents to trace any screenshot back to the code and data behind it. |
| 3 | +> **Screenshot in. Full data lineage out.** |
| 4 | +> Static analysis that maps every UI component to the APIs, state, and events behind it — built for AI agents doing real development work. |
4 | 5 |
|
5 | | -**The problem:** a Jira ticket has a screenshot of a broken screen. Which component is that? Where does its data come from? Today an engineer greps for the visible text, follows imports by hand, and reads hook bodies to find the API call. CodeRadar does that walk statically, once, and hands the result to an agent as a queryable graph. |
| 6 | +**Status:** pre-release · v0.1 proof of concept · [build plan](TRACKER.md) |
| 7 | + |
| 8 | +--- |
| 9 | + |
| 10 | +## The problem |
| 11 | + |
| 12 | +A Jira ticket lands with a screenshot: *"the numbers on this table are wrong."* |
| 13 | + |
| 14 | +Before any fix can start, someone has to answer: |
| 15 | + |
| 16 | +1. **Which component is that?** — grep for visible text, hope it isn't behind an i18n key |
| 17 | +2. **Where does its data come from?** — follow imports, unwrap hooks, find the API call |
| 18 | +3. **What happens if I change it?** — who else renders this component? who else calls this API? |
| 19 | + |
| 20 | +An engineer does this walk by hand, every ticket. An AI dev agent can't do it reliably at all — it sees files, not the *lineage* connecting a pixel on screen to the endpoint that produced it. |
| 21 | + |
| 22 | +## What CodeRadar does |
| 23 | + |
| 24 | +CodeRadar scans a React codebase **once, statically** — no running app required — and produces a queryable **lineage graph**: |
6 | 25 |
|
7 | 26 | ``` |
8 | | -Screenshot text ──find──▶ Component ──trace──▶ APIs · state · events |
| 27 | + find trace impact |
| 28 | +Screenshot ──▶ Component instance ──▶ APIs · state · events ──▶ Blast radius |
| 29 | + text │ |
| 30 | + └─ per call site: the same <DataTable> on the Users page |
| 31 | + is fed by /api/users; on the Invoices page by /api/invoices |
9 | 32 | ``` |
10 | 33 |
|
| 34 | +It's designed as a **context-provider node for multi-agent development pipelines**: a ticket goes in, and a budgeted context bundle comes out — matched components with evidence, their data sources, the relevant user journeys, blast radius, tests, and git history. Every answer carries confidence and evidence; when the graph isn't sure, it says `ambiguous` and tells you what would disambiguate — it never hands your pipeline a confident guess. |
| 35 | + |
11 | 36 | ## Quick start |
12 | 37 |
|
13 | 38 | ```bash |
14 | | -pnpm install && pnpm build |
| 39 | +git clone https://github.com/officialCodeWork/CodeRadar.git |
| 40 | +cd CodeRadar && pnpm install && pnpm build |
| 41 | +``` |
15 | 42 |
|
16 | | -# 1. Scan a React codebase into a lineage graph |
| 43 | +**1 — Scan a React codebase into a lineage graph** |
| 44 | + |
| 45 | +```bash |
17 | 46 | node packages/cli/dist/index.js scan ./my-app/src -o graph.json |
| 47 | +``` |
| 48 | + |
| 49 | +**2 — Find the component behind a screenshot** (use any text visible in the image) |
18 | 50 |
|
19 | | -# 2. Find the component behind a screenshot (use text visible in the image) |
| 51 | +```bash |
20 | 52 | node packages/cli/dist/index.js find "Team Members" -g graph.json |
21 | | -# UserList (components/UserList.tsx:4) score=1 |
| 53 | +``` |
| 54 | +``` |
| 55 | +UserList (components/UserList.tsx:4) score=1 |
| 56 | + matched: team members |
| 57 | +``` |
| 58 | + |
| 59 | +**3 — Trace everything that feeds it** |
22 | 60 |
|
23 | | -# 3. Trace everything that feeds it |
| 61 | +```bash |
24 | 62 | node packages/cli/dist/index.js trace UserList -g graph.json |
25 | | -# UserList (components/UserList.tsx:4) |
26 | | -# data sources: |
27 | | -# [fetch] GET /api/users (hooks/useUsers.ts:14) |
28 | | -# [fetch] DELETE /api/users/${user.id} (components/UserCard.tsx:5) |
29 | | -# state: |
30 | | -# [useState] users (hooks/useUsers.ts:10) |
31 | | -# events: |
32 | | -# onClick → handleDelete (components/UserCard.tsx:12) |
33 | | -# via: useUsers, UserCard |
| 63 | +``` |
| 64 | +``` |
| 65 | +UserList (components/UserList.tsx:4) |
| 66 | + data sources: |
| 67 | + [fetch] GET /api/users (hooks/useUsers.ts:14) |
| 68 | + [fetch] DELETE /api/users/${user.id} (components/UserCard.tsx:5) |
| 69 | + state: |
| 70 | + [useState] users (hooks/useUsers.ts:10) |
| 71 | + [useState] loading (hooks/useUsers.ts:11) |
| 72 | + events: |
| 73 | + onClick → handleDelete (components/UserCard.tsx:12) |
| 74 | + via: useUsers, UserCard |
34 | 75 | ``` |
35 | 76 |
|
36 | | -Try it on the bundled example: `node packages/cli/dist/index.js scan examples/demo-app/src`. |
| 77 | +Note the transitivity: `UserList` itself contains no fetch — the lineage flows through the `useUsers` hook and the `UserCard` child automatically. |
| 78 | + |
| 79 | +Try it immediately on the bundled example: `node packages/cli/dist/index.js scan examples/demo-app/src` |
| 80 | + |
| 81 | +## How it works |
| 82 | + |
| 83 | +``` |
| 84 | +┌────────────────────────────────────────────────────────────────┐ |
| 85 | +│ CodeRadar │ |
| 86 | +│ │ |
| 87 | +│ Parsers (language-specific) Graph (language-agnostic) │ |
| 88 | +│ ┌───────────────┐ │ |
| 89 | +│ │ parser-react │──┐ ┌─────────────────────────────────┐ │ |
| 90 | +│ │ (ts-morph) │ │ │ LineageGraph (JSON) │ │ |
| 91 | +│ └───────────────┘ ├──▶│ │ │ |
| 92 | +│ ┌───────────────┐ │ │ Component ──renders──▶ Component│ │ |
| 93 | +│ │ parser-python │ │ │ │ │ │ |
| 94 | +│ │ (planned) │──┤ │ fetches-from ──▶ DataSource │ │ |
| 95 | +│ └───────────────┘ │ │ reads-state ──▶ State │ │ |
| 96 | +│ ┌───────────────┐ │ │ handles ──▶ Event │ │ |
| 97 | +│ │ parser-go │──┘ └─────────────────────────────────┘ │ |
| 98 | +│ │ (planned) │ │ │ |
| 99 | +│ └───────────────┘ ▼ │ |
| 100 | +│ Query layer: find · trace · impact │ |
| 101 | +│ (CLI · SDK · MCP server, planned) │ |
| 102 | +└────────────────────────────────────────────────────────────────┘ |
| 103 | +``` |
| 104 | + |
| 105 | +**Parsers are language-specific; the graph is not.** Every parser emits the same `LineageGraph` JSON, and any agent — Python, Go, TypeScript — consumes it without touching a parser. The planned backend parsers make endpoints a *join key*: `fetches-from: /api/users` in your React repo links to `serves: /api/users` in your FastAPI repo, closing the loop from pixel to handler. |
37 | 106 |
|
38 | 107 | ## Packages |
39 | 108 |
|
40 | 109 | | Package | Purpose | |
41 | 110 | |---------|---------| |
42 | | -| [`@coderadar/core`](packages/core) | The `LineageGraph` schema (plain JSON, language-agnostic) + query helpers (`matchComponentsByText`, `traceLineage`) | |
43 | | -| [`@coderadar/parser-react`](packages/parser-react) | ts-morph–based parser: components, hooks, fetch/axios/react-query/swr calls, useState/useSelector/useContext, JSX event handlers, rendered text | |
44 | | -| [`@coderadar/cli`](packages/cli) | `coderadar scan` / `find` / `trace` | |
45 | | - |
46 | | -## What the graph captures |
| 111 | +| [`@coderadar/core`](packages/core) | The `LineageGraph` schema + query primitives (`matchComponentsByText`, `traceLineage`) | |
| 112 | +| [`@coderadar/parser-react`](packages/parser-react) | ts-morph static parser — components (incl. `memo`/`forwardRef`), hooks, `fetch`/`axios`/react-query/SWR endpoints, `useState`/`useSelector`/`useContext`, JSX event handlers, rendered-text extraction | |
| 113 | +| [`@coderadar/cli`](packages/cli) | `coderadar scan` · `find` · `trace` | |
47 | 114 |
|
48 | | -- **ComponentNode** — file, export, props, *rendered text* (JSX text + placeholder/label/title/alt/aria-label — the screenshot-matching signal), child components |
49 | | -- **DataSourceNode** — endpoint as written in source (template placeholders preserved), HTTP method, client kind (fetch / axios / react-query / swr) |
50 | | -- **StateNode** — useState / useReducer / useContext / redux useSelector / zustand useStore |
51 | | -- **EventNode** — `on*` JSX handlers and the functions they call |
52 | | -- **Edges** — `renders`, `uses-hook`, `fetches-from`, `reads-state`, `handles`, `triggers` |
| 115 | +### What the graph captures |
53 | 116 |
|
54 | | -Lineage is transitive: `trace UserList` follows `UserList → useUsers → fetch("/api/users")` and `UserList → UserCard → DELETE` in one query. |
| 117 | +- **Components** — file, exports, props, child components, and *rendered text* (JSX text + `placeholder`/`label`/`title`/`alt`/`aria-label`) — the screenshot-matching signal |
| 118 | +- **Data sources** — endpoint as written in source (template placeholders preserved), HTTP method, client kind (fetch / axios / react-query / SWR) |
| 119 | +- **State** — `useState` / `useReducer` / `useContext` / redux `useSelector` / zustand `useStore` |
| 120 | +- **Events** — `on*` handlers and the functions they invoke |
| 121 | +- **Edges** — `renders` · `uses-hook` · `fetches-from` · `reads-state` · `handles` · `triggers` |
55 | 122 |
|
56 | | -## Architecture |
| 123 | +## Where this is going |
57 | 124 |
|
58 | | -Parsers are language-specific; the graph is not. Any parser emits the same `LineageGraph` JSON, and any agent (Python, Go, TS) consumes it without touching the parsers. |
| 125 | +The v0.1 PoC proves the chain on clean code. Real codebases fight back — endpoints behind wrapper clients, text behind i18n keys, handlers drilled through four layers of props, one shared component fed different APIs per page. We catalogued **53 ways this can fail** before writing the plan, and every phase of the build is gated by evals that measure exactly those failure modes. |
59 | 126 |
|
60 | | -Planned parsers: Python (FastAPI/Django routes) and Go (handlers) so backend endpoints join the same graph as the frontend components that call them — closing the loop from pixel to database. |
| 127 | +| Document | What's in it | |
| 128 | +|----------|--------------| |
| 129 | +| **[TRACKER.md](TRACKER.md)** | The build plan: 8 phases, 40 steps, acceptance criteria per step — read this first | |
| 130 | +| **[docs/failure-modes.md](docs/failure-modes.md)** | The failure catalog (IDs `A1`–`G8`) every step and eval fixture maps to | |
| 131 | +| **[docs/testing-strategy.md](docs/testing-strategy.md)** | Eval harness, golden fixtures, metrics (incl. *poison rate* — confidently-wrong answers), phase gates | |
61 | 132 |
|
62 | | -## Roadmap & planning |
| 133 | +Milestones at a glance: |
63 | 134 |
|
64 | | -CodeRadar is built as a context-provider node for a multi-agent development pipeline: |
65 | | -Jira ticket in → context bundle (matched components, data lineage, journeys, blast radius) out. |
| 135 | +- **M2** — per-instance attribution: shared components correctly attributed per call site |
| 136 | +- **M3** — n-level user journeys, lazily expanded (cycles welcome) |
| 137 | +- **M4** — screenshot/text → ranked, calibrated, *honest* matches |
| 138 | +- **M5** — pluggable pipeline node: ticket in → budgeted context bundle out, over MCP |
| 139 | +- **M7** — full-stack lineage: pixel → backend handler (Python/Go parsers) |
66 | 140 |
|
67 | | -- **[TRACKER.md](TRACKER.md)** — the phased build plan (8 phases, one step = one PR). Read this first. |
68 | | -- **[docs/failure-modes.md](docs/failure-modes.md)** — the catalog of everything that can go wrong (IDs A1–G8); every plan step maps to the failure modes it addresses. |
69 | | -- **[docs/testing-strategy.md](docs/testing-strategy.md)** — eval harness, per-failure-mode fixtures, metrics, and the per-phase gates that tell us whether we're on track. |
| 141 | +## Contributing |
70 | 142 |
|
71 | | -Current state: v0.1 proof of concept (this repo). Next: Phase 0 — schema v2 (instance nodes), eval harness, CI. |
| 143 | +The project follows a strict step discipline: one TRACKER step = one branch = one PR, and a step is done only when its acceptance criteria and eval gate pass. Found a new way for this to fail? That's a contribution — add it to [failure-modes.md](docs/failure-modes.md) with a fixture. |
72 | 144 |
|
73 | 145 | ## License |
74 | 146 |
|
|
0 commit comments