From 950686def40e7011037cdb6aad08f3cdbf05905d Mon Sep 17 00:00:00 2001 From: Colby McHenry Date: Fri, 28 Aug 2026 13:45:38 -0500 Subject: [PATCH] =?UTF-8?q?feat(ui):=20Steps=20for=20servers=20=E2=80=94?= =?UTF-8?q?=20route=20roots,=20server=20effects,=20request/decorator=20tri?= =?UTF-8?q?ggers,=20guards=20for=20Python/Java/Kotlin/C#/Go/C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - api/route-roots.ts: the symbol a route runs (references-edge handler, exported page component, or the route itself for an inline handler), shared by steps and screens; the bare Steps tab lists an API's endpoints by router file - api/effects.ts: database / response / queue / email / payments / cache / auth / process / network / storage / device / telemetry, matched on the call as written per language family, with model + read/write and the literal status on a response site - graph/branch-guards.ts: callSitesForFile (the whole member chain), memberTypesInTree, decoratorsForFile, request/decorator triggers with the middleware/guard chain; guard + argument rules for Python, Java, Kotlin, C#, Go and C - steps.ts: classify on the chain before trusting a name match, retarget this.x.y() by declared type, skip test doubles after the effect pre-check, project kind on the wire - viewer: kindWord/kindWords per project kind, endpoint chooser, response boxes labelled by status codes - python.ts: FastAPI detected from a monorepo sub-directory; is-test-file: samples/examples package paths are not tests - tests: ui-steps-api-servers, ui-effects, branch-guards-languages; spec §3.13 Servers paragraph, CHANGELOG, plan doc Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01REFyW9hmNrxhwN5wxRoAkC --- CHANGELOG.md | 12 + CLAUDE.md | 2 +- __tests__/branch-guards-languages.test.ts | 336 +++++ __tests__/branch-guards.test.ts | 4 +- __tests__/is-test-file.test.ts | 20 + __tests__/ui-effects.test.ts | 246 ++++ __tests__/ui-steps-api-servers.test.ts | 332 +++++ __tests__/ui-steps-model.test.ts | 24 +- docs/design/codegraph-ui-design-spec.md | 50 +- ...8-28-steps-and-screens-for-apis-and-web.md | 446 +++++++ src/graph/branch-guards.ts | 1081 ++++++++++++++++- src/resolution/frameworks/python.ts | 16 + src/search/query-utils.ts | 13 +- src/ui-server/api/effects.ts | 509 ++++++++ src/ui-server/api/route-roots.ts | 92 ++ src/ui-server/api/screens.ts | 20 +- src/ui-server/api/steps.ts | 508 ++++++-- src/ui-server/api/when.ts | 32 + ui/src/components/steps/StepNode.svelte | 5 +- ui/src/lib/steps-model.ts | 61 +- ui/src/lib/wire.ts | 41 +- ui/src/views/StepsView.svelte | 209 +++- 22 files changed, 3869 insertions(+), 190 deletions(-) create mode 100644 __tests__/branch-guards-languages.test.ts create mode 100644 __tests__/ui-effects.test.ts create mode 100644 __tests__/ui-steps-api-servers.test.ts create mode 100644 docs/plans/2026-08-28-steps-and-screens-for-apis-and-web.md create mode 100644 src/ui-server/api/effects.ts create mode 100644 src/ui-server/api/route-roots.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e1ce71..25a5509 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,12 +14,24 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### New Features +- **The Steps tab now draws an API as well as an app.** Anchor on an endpoint — `POST /users` in Express, NestJS, Fastify, FastAPI, Flask, Django, Spring (Java or Kotlin), ASP.NET, Vapor or Gin — and the viewer starts at the handler the route runs (or at the route itself when the handler is an inline arrow), says what fires it (`FIRES FROM POST /users · after authenticate, validate(…)` — the middleware arguments at the registration, or the guard decorators on the method and its class, or a FastAPI `dependencies=[…]`), and draws what the request sets in motion: the database calls with the model and whether they read or write (`prisma.user.create({ data })` · `database · user · write`), jobs put on a queue, emails, payments, cache reads, token checks, calls to other services, files and processes — and the **responses**, one box per handler whose label is the status codes it can send (`201 · 404`) and whose panel rows are the endpoint's contract as the code has it: `WHEN NOT user → 404 · NotFoundException('no such user')`, `always → 201 · res.status(201).json(user)`. A queue consumer or a scheduled job anchored by name says the decorator that fires it (`@Process('email')`). The legend, the panel and the chooser use the project's own words — endpoint, data call, another tier — and the bare Steps tab lists an API's endpoints by router file when there are no screens. Re-index is not needed: everything new is read from the source at request time. + +- **Calls are read as written, so the database is the database.** The index keeps only the last segment of a deep member call (`create` for `prisma.user.create`), and a bare name matches by name alone — often to the wrong `create`. The Steps walk now reads each call from the source as written, classifies `prisma.user.create`, `this.usersRepository.save`, `session.commit`, `owners.save` and `_context.TodoItems.Add` by the whole chain and by the receiver's declared type (`OwnerRepository owners`, `private readonly usersService: UsersService`, `val owners: OwnerRepository`, read from the class body), and follows `this.usersService.findByEmail(…)` into the class the type names instead of the name-only guess. A hop resolved this way says so in the panel. + +- **Conditions and arguments for Python, Java, Kotlin, C#, Go and C.** The `when` on a call — `if` / `elif` / `else`, `switch` / `when` / `match`, the ternary and Kotlin's `if` expression, `try` / `except` / `catch`, `and` / `or`, and the early exits before it (`if err != nil { return }` reads as `err == nil`, `if not item.title: raise` as `item.title`) — and what each call passes (`HTTPException(status_code=422, detail="bad price")`, `c.JSON(http.StatusCreated, gin.H{…})`) are now read for those languages too, in `codegraph ui`'s rails, Flow strip and Steps tab and in `codegraph_explore`'s Flow section. As before: read from the source as it stands, never stored, and a language without rules yields nothing rather than a wrong label. + - **A Steps tab in `codegraph ui` — what happens from here.** Pick a screen (or search any symbol and choose *What happens from here*) and the viewer draws everything it sets in motion as typed steps: the handlers wired to its taps and listeners, the calls that cross into native code, the native events that come back, the store actions it writes, and the calls that leave the app into the network, storage, the device or telemetry — one box per step, an arrow for every way one leads to the next, and on each arrow the condition under which it happens. The plumbing between two steps (hooks, helpers, the components in between) is folded into the arrow and listed in the side panel, exactly as the Screens tab folds a tap's chain into one transition — and every call the panel lists says what it passes, read from the source as written (`SecureStore.setItemAsync('userEmail', values.email)`, `axios.post('/auth/login', { email, password })`), so a step is not just *that* something was stored or sent but *what*. And each handler says what fires it — the JSX prop and its element (`onPress · + {/each} {/if} @@ -730,6 +833,19 @@ margin-top: 12px; border-top: 1px solid var(--rule-soft); } + /* A router file heading over its endpoints; the list under it keeps its own top rule. */ + .group-h { + display: flex; + justify-content: space-between; + align-items: baseline; + gap: 12px; + margin-top: 18px; + font-size: 11.5px; + color: var(--ink-2); + } + .group-h + .chooser-list { + margin-top: 6px; + } .pick { display: block; padding: 7px 8px; @@ -984,6 +1100,11 @@ text-decoration: none; overflow-wrap: anywhere; } + /* A response's status code leads its row: the number is the fact. */ + .status { + color: var(--ink); + font-weight: 600; + } a.site:hover { text-decoration: underline; }