Back to the examples

Example report

Architecture audit.

This is the full architecture audit report for the same app: file size, change hotspots, files that change together, tests and dependencies, with a refactoring plan in small steps.

System: Example App (npm workspaces monorepo: api/ Hono on Cloud Run, frontend/ Next.js, 12 packages/*) Date: 2026-11-04 Scope: whole repository except audit archive/. Not examined: runtime behaviour, production data. Data handled: Google OAuth tokens and Google Ads access, user emails, Stripe payments (from the code; you said no other sensitive data). Online checks (circular dependencies, outdated packages): run on 2026-11-04 Method: scanner (scripts/scan.sh) + manual verification + checklist + rubric. Not worked through item by item: references/checklist.md sections on API design and observability.

Example report from a real audit of an AI-built app. Names, identifiers and customer details have been changed.

Summary

The structure is healthier than the size suggests: 207 test files for 512 source files, no circular dependencies in any of 12 packages, and clear boundaries between api, frontend and packages. The risk is concentrated in a few very large functions in the workflow workers and in copy-pasted request handling across frontend API routes. Findings: 0 Critical, 2 High, 1 Medium, 3 Low. The biggest structural risk is the workflow executor files, which are large, change together, and sit on the money path.

Critical High Medium Low
0 2 1 3

Measurements

  • Size: 512 source files, 109,418 lines; 20 package.json files; 32 runtime and 13 dev dependencies.
  • Largest files: packages/scraper/src/page-scraper.ts 1,958; api/src/workers/run-executor.ts 1,789; packages/scrape-enricher/src/index.ts 1,593; api/src/workers/wf3-executor.ts 1,569; frontend/src/app/dashboard/components/cycle-card.tsx 1,380 lines.
  • Change hotspots (6 months, 125 commits): wf3-executor.ts 7; api/src/lib/stage-executor.ts 6; frontend/src/app/dashboard/run-item.tsx 5; api/src/lib/cycle-stage-seeds.ts 5 (docs/session-handoff-*.md 12 and packages/shared/package.json 5 are not code hotspots).
  • Files that change together (last 500 commits): wf2-chunk-worker.ts with wf2-executor.ts 15; wf4-executor.ts with wf5-executor.ts 13; run-executor.ts with packages/scraper/src/index.ts 13; wf2-executor.ts with wf5-executor.ts 12, with wf4-executor.ts 12, with packages/scrape-enricher/src/index.ts 9.
  • Ownership: single maintainer (all 125 commits in six months carry one author identity, which differs from the current git user; confirm these are the same person). Reported once here, not per finding.
  • Tests: 207 test files for 512 source files; 55 test files under api/src/lib and api/src/workers. Which flows are covered was not mapped.
  • Circular dependencies: 0 found in the 12 packages and api/frontend scanned.
  • Debt markers: 2 TODO/FIXME/HACK, 32 lint or type suppressions, 21 uses of any.
  • Outdated: 5 of 12 (api), 5 of 17 (frontend), 6 of 25 (root) packages a major version or more behind.

Top 3 actions

  1. This month: break executeRun and the wf3 coordinator/chunk/finalize functions into steps (H1).
  2. This month: extract the repeated auth/error handling in frontend API routes into one helper (H2).
  3. This quarter: plan the major-version upgrades, starting with the ones npm audit flags (M1).

Findings

[H1] Workflow executors are huge, tightly coupled and change together — High

  • Where: api/src/workers/run-executor.ts (1,789 lines), wf3-executor.ts (1,569), wf2-executor.ts, wf4-executor.ts, wf5-executor.ts, wf2-chunk-worker.ts
  • Evidence: In run-executor.ts, executeRun runs from line 60 to about line 1,560, one function of roughly 1,500 lines. In wf3, executeWf3FeedOptimizerCoordinatorInner is ~415 lines (198-615), ChunkInner ~340 (718-1059), FinalizeInner ~260 (1095-1357). wf3 is the most-changed file in six months (7 commits). Six coupled pairs change together 9-15 times in 500 commits. A recent bug (a finalizer read truncated at 1,000 rows) was found in this file.
  • Severity reasoning: Cost B (hotspot, slows safe changes), Trend 1 (each new workflow or language option adds to the same functions). No adjustment (the credit ledger, which handles money, is a separate package).
  • Cost in plain words: Every change to a workflow means re-reading a 1,500-line function; changing WF2 usually also means editing WF4 and WF5, so a missed spot becomes a regression in a paid run.
  • Fix: First add characterization tests around executeRun inputs and outputs. Then extract one phase at a time (scrape, enrich, estimate, persist, finalize) into functions in new files, without behaviour changes. After that, move code the WF2/4/5 executors share into one module.
  • Fix prompt:
    In api/src/workers/run-executor.ts, identify the distinct phases inside executeRun (progress reporting, CrUX lookup, scrape, persistence, finalization). Without changing behaviour, extract the first phase only into api/src/workers/run-executor/<phase>.ts with an explicit input/output type, keeping executeRun as the caller. First add or confirm tests that pin current behaviour. One extraction per commit; run npm test in api after each.
    
  • Verify: Re-run the scanner: run-executor.ts line count drops and the largest function is under ~300 lines; the existing test suite still passes.

[H2] Auth and error handling copy-pasted across frontend API routes — High

  • Where: frontend/src/app/api/**/route.ts (22 files with the same error line, 18 with the same auth status mapping, 12 with the same auth early-return)
  • Evidence: The scanner found { status: auth.error === "rate_limited" ? 429 : auth.error === "csrf_rejected" ? 403 : 401 in 18 files and if (auth.error) return NextResponse.json({ error: auth.error }, ... in 12 files.
  • Severity reasoning: Cost C (no failure traced to it yet), Trend 1 (every new route copies it again), plus one level for the authentication path = High.
  • Cost in plain words: A change to how authentication failures are reported (or a bug in it) must be made in 12-18 places; a missed copy leaves one route behaving differently on a security-relevant path.
  • Fix: One helper respondToAuthError(auth) (and a handleRoute wrapper) in frontend/src/lib/auth, adopted route by route.
  • Fix prompt:
    Add frontend/src/lib/auth/respond-auth-error.ts exporting respondToAuthError(auth) that returns the same NextResponse the routes build today (429 rate_limited, 403 csrf_rejected, otherwise 401). Replace the duplicated inline code in the three most recently changed route.ts files under frontend/src/app/api, keeping responses byte-identical, and add a unit test. Do not touch the other routes yet.
    
  • Verify: Re-run the scanner: the DUPLICATED_LINE count for these lines falls from 18/12 files toward 0.

[M1] Major-version drift in dependencies — Medium

  • Where: api/package.json, frontend/package.json, root package.json
  • Evidence: 5 of 12, 5 of 17 and 6 of 25 outdated packages are a major version or more behind (scanner OUTDATED_MAJOR). next 16.2.2 is also flagged by npm audit.
  • Severity reasoning: Cost C, Trend 1 (the gap and upgrade pain grow each release). No adjustment.
  • Cost in plain words: Delayed upgrades pile up and eventually must be done together, under pressure from a security advisory.
  • Also reported in: SECURITY-AUDIT-REPORT.md, H1 and M1 (the security side of the same packages)
  • Fix: Upgrade one major per week, starting with the packages that have advisories; list them with npm outdated.
  • Fix prompt:
    Run npm outdated in api/, frontend/ and the repo root. For each package that is a major version behind, read its changelog and list the breaking changes that affect this codebase, in order of risk. Do not upgrade anything yet.
    
  • Verify: npm outdated shows fewer majors behind.

[L1] Two very large scraper files that rarely change — Low

  • Where: packages/scraper/src/page-scraper.ts (1,958 lines), packages/scrape-enricher/src/index.ts (1,593 lines)
  • Evidence: scrapePage spans lines 618-1333 (~715 lines); page-scraper.ts also holds readability maths, image checks, redirect following and challenge detection. Only 3 commits in six months.
  • Severity reasoning: Cost C, Trend 2. No adjustment.
  • Cost in plain words: Harder to understand and test in parts, but it is not causing trouble today.
  • Fix: When next touching them, move pure helpers (fleschKincaidGrade, checkImages, followRedirectChain) into their own files.
  • Fix prompt:
    In packages/scraper/src/page-scraper.ts move the pure helpers fleschKincaidGrade, countSyllables, stripTags, extractFirst and extractAll into packages/scraper/src/text-utils.ts and import them back. No behaviour change; run the package tests.
    
  • Verify: page-scraper.ts is shorter and package tests pass.

[L2] Large UI component and repeated markup and fetch calls — Low

  • Where: frontend/src/app/dashboard/components/cycle-card.tsx (1,380 lines); frontend/src/app/settings/prompt-settings/page.tsx and 8 other pages repeat the same nav bar markup; 11 UI files call fetch directly
  • Evidence: Scanner LARGE_FILE, DUPLICATED_LINE (9 and 8 files), HTTP_IN_UI (11 files).
  • Severity reasoning: Cost C, Trend 2. No adjustment.
  • Cost in plain words: Visual or API changes need edits in many places; not yet causing failures.
  • Fix: Extract a shared PageNav component and a small api-client.ts; split cycle-card.tsx by section when next changed.
  • Fix prompt:
    Create frontend/src/components/page-nav.tsx with the nav markup repeated in frontend/src/app/settings/prompt-settings/page.tsx and the 8 other pages found by grepping for 'border-b border-gray-800 px-6 py-4 flex items-center justify-between'. Replace the duplicates, keeping rendered HTML identical.
    
  • Verify: The grep returns one result; npm run build passes.

[L3] No README — Low

  • Where: repository root (an ARCHITECTURE.md exists)
  • Evidence: Scanner NO_README.
  • Severity reasoning: Cost C, Trend 2. No adjustment.
  • Cost in plain words: A new person (or you after a break) lacks a start-here page for setup, running and deploying.
  • Fix: A short README linking to ARCHITECTURE.md, the deploy scripts and the runbooks.
  • Fix prompt:
    Write README.md at the repo root: what Example App is, repo layout (api, frontend, packages), how to install, run and test locally, how to deploy (scripts/deploy-*.sh), and links to ARCHITECTURE.md and docs/runbooks. Base it only on files in the repo.
    
  • Verify: README.md exists and its commands work.

Refactoring plan

  1. Add characterization tests for executeRun and the wf3 executor entry points.
  2. Extract one phase from executeRun per commit.
  3. Do the same for the three wf3 ...Inner functions.
  4. Move code shared by WF2/4/5 executors into one module so the co-changing pairs stop co-changing.
  5. Add respondToAuthError and adopt it route by route (H2).
  6. Plan major upgrades (M1), one per week.
  7. Low items when touching the area.

Checked and found fine

  • No circular dependencies in api, frontend or the 10 packages checked.
  • Test coverage by file count is high (207 for 512 sources) and CI runs typecheck, build, tests and structure checks as blocking jobs (.github/workflows/ci.yml).
  • Workspace package boundaries are guarded by scripts/check-workspace-package-consistency.sh.
  • Debt markers are low (2 TODO/FIXME, 21 any).

Not checked or not verified

  • Your answers to what is most painful to change and plans for the next 12 months (not given; "everything AI-written" noted).
  • Whether the system map is correct (to be confirmed).
  • Which critical flows the 207 tests actually cover.
  • Whether the commit author and the git user are the same person.

Appendix: scanner output

SUMMARY|HIGH|GOD_FILE|8
SUMMARY|LOW|HTTP_IN_UI|1
SUMMARY|MEDIUM|CO_CHANGE|6
SUMMARY|MEDIUM|DUPLICATED_LINE|5
SUMMARY|MEDIUM|LARGE_FILE|8
SUMMARY|MEDIUM|NO_README|1

The full scanner output is in ARCHITECTURE-AUDIT-SCAN.txt.


This report is guidance produced with an AI assistant. It does not replace a review by an engineer who knows your business.

Want this for your project?

See pricing