Skip to content

Commit ffd7d66

Browse files
committed
Merge remote-tracking branch 'origin/development' into claude/vigorous-williams-ec7017
# Conflicts: # packages/cli/src/index.ts # packages/core/src/query.ts
2 parents fcff3b5 + 9b0d9e6 commit ffd7d66

160 files changed

Lines changed: 9036 additions & 348 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# CodeRadar CI — the Gate 0 pipeline.
2+
#
3+
# Every PR must pass: build (strict TS), typecheck, unit tests, and the eval
4+
# gate (eval/thresholds.json). The scorecard is uploaded as an artifact on
5+
# every run, pass or fail, so regressions are inspectable.
6+
#
7+
# Threshold ratchet rule (docs/testing-strategy.md): eval/thresholds.json
8+
# values may be RAISED in any PR; LOWERING one requires a written
9+
# justification in the PR body. Thresholds never loosen silently.
10+
11+
name: CI
12+
13+
on:
14+
push:
15+
branches: [main, development]
16+
pull_request:
17+
18+
concurrency:
19+
group: ci-${{ github.workflow }}-${{ github.ref }}
20+
cancel-in-progress: true
21+
22+
jobs:
23+
ci:
24+
runs-on: ubuntu-latest
25+
timeout-minutes: 15
26+
steps:
27+
- uses: actions/checkout@v4
28+
29+
- uses: pnpm/action-setup@v4 # reads the packageManager field
30+
31+
- uses: actions/setup-node@v4
32+
with:
33+
node-version: 22
34+
cache: pnpm
35+
36+
- name: Install
37+
run: pnpm install --frozen-lockfile
38+
39+
- name: Build (strict TS)
40+
run: pnpm build
41+
42+
- name: Typecheck
43+
run: pnpm typecheck
44+
45+
- name: Unit tests
46+
run: pnpm test
47+
48+
- name: Eval gate
49+
run: node eval/dist/run.js
50+
51+
- name: Upload scorecard
52+
if: always()
53+
uses: actions/upload-artifact@v4
54+
with:
55+
name: eval-scorecard
56+
path: eval/scorecard.json
57+
if-no-files-found: ignore

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,6 @@ dist
141141
vite.config.js.timestamp-*
142142
vite.config.ts.timestamp-*
143143
.vite/
144+
145+
# Eval outputs (scorecard is regenerated every run; history is recorded deliberately)
146+
eval/scorecard.json

README.md

Lines changed: 112 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,146 @@
1-
# CodeRadar
1+
# 📡 CodeRadar
22

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.
45
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**:
625

726
```
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
932
```
1033

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+
1136
## Quick start
1237

1338
```bash
14-
pnpm install && pnpm build
39+
git clone https://github.com/officialCodeWork/CodeRadar.git
40+
cd CodeRadar && pnpm install && pnpm build
41+
```
1542

16-
# 1. Scan a React codebase into a lineage graph
43+
**1 — Scan a React codebase into a lineage graph**
44+
45+
```bash
1746
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)
1850

19-
# 2. Find the component behind a screenshot (use text visible in the image)
51+
```bash
2052
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**
2260

23-
# 3. Trace everything that feeds it
61+
```bash
2462
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
3475
```
3576

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.
37106

38107
## Packages
39108

40109
| Package | Purpose |
41110
|---------|---------|
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` |
47114

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
53116

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`
55122

56-
## Architecture
123+
## Where this is going
57124

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.
59126

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 |
61132

62-
## Roadmap & planning
133+
Milestones at a glance:
63134

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)
66140

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
70142

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.
72144

73145
## License
74146

0 commit comments

Comments
 (0)