git merge --dry-run, for architecture.
merge-auditor reads the source code of two repositories — not just their package.json files — and tells you, before you open the real pull request: whether they're compatible, what shape the merge is (frontend+backend, two frontends, a library, etc.), exactly what has to change, and how to change it. Output is a compatibility verdict, an actionable TODO checklist, and an integration plan rendered as real git log output.
## Compatibility
**NEEDS DECISIONS FIRST** — Not mergeable until blocking conflicts are resolved
-- these require a human decision, not just a rebase. Shape: frontend +
backend, already talking to each other: wire them as one app and one API.
- Repo A serves 0 endpoint(s) and makes 4 HTTP call(s); repo B serves 3 and
makes 0.
- 3 call site(s) in one repo already hit an endpoint the other serves, so a
real contract exists between them.
- Repo B serves repo A but configures no CORS.
Two repositories can each pass their own tests and still not merge cleanly: colliding routes, a major dependency bump on one side, an API contract that changed shape, a backend with no CORS configured for the frontend that's about to call it. Finding that out is normally a first afternoon of the merge spent reading both codebases side by side. merge-auditor does that reading for you and hands back a plan.
- Clones both repositories (a GitHub URL or a local path).
- Reads the source, not just the manifests: every HTTP endpoint each repo serves (Express routes, Next.js App Router handlers, Pages API routes), every outgoing HTTP call (
fetch,axios,useSWR), server ports, environment variables, and technology signatures (auth scheme, data layer, CORS, state management) — each fact captured with itsfile:line. - Cross-references the two: which calls in one repo are answered by an endpoint in the other (the integration seam), which are answered by neither, colliding ports, missing CORS, environment variable names that collide once both run in one process, incompatible auth schemes, overlapping data layers.
- Also runs the original conflict detectors: dependency version drift, colliding Next.js routes, a router-convention mismatch (App Router vs Pages Router), and duplicated components.
- Produces:
- A compatibility verdict —
ready/compatible-with-work/needs-decisions/unrelated— with the merge shape and the reasoning behind it, computed from the evidence, never from a model's guess. - A TODO checklist: one item per finding, each with what is wrong, how to fix it (ordered concrete steps — guidance, not generated code), which files are involved, and how to verify it worked.
- An integration plan rendered as an actual
git log: ordered proposed commits with conventional-commit subjects, a body citing the evidence, and the files each would touch.
- A compatibility verdict —
- Optionally actuates the plan on GitHub: a
feature/fusion-draftbranch, selected files copied over with TODO comments,FUSION_PLAN.md, a pull request, and labeled issues.
npm installnpx tsc --outDir dist
node dist/src/cli.js --repo-a <url-or-path> --repo-b <url-or-path> --target <owner/repo> --dry-run| Flag | Purpose |
|---|---|
--repo-a, --repo-b |
GitHub URL or local path for each repository |
--target |
owner/repo to receive the fusion draft (validated even in dry-run; only used for real without --dry-run) |
--dry-run |
Run detection and synthesis, print the report, skip GitHub entirely |
--json |
Also dump the raw AuditReport and SynthesisOutput |
Without --dry-run, a valid GITHUB_TOKEN is required and the tool pushes the fusion draft branch, PR, and issues to --target.
npm run webOpen http://localhost:8080, paste two GitHub URLs, click Run audit. Read-only — it runs detection and synthesis and renders the result, no GitHub token needed. Each request clones into a fresh temp directory and deletes it once the response is sent, success or failure.
An integration-plan commit, exactly as rendered by git log:
commit d25cc9665ee9ecbc3b60066a7aa5e7b8b16bf067
Author: merge-auditor <audit@merge-auditor.local>
Date: Sat Aug 1 20:50:10 2026 +0000
feat(api): enable CORS for the calling origin
Repo A makes browser-side calls into repo B's server, and no `cors`
usage was found anywhere in repo B. Cross-origin requests from the
browser will be blocked once the two run as separate origins.
Add the `cors` middleware to repo B's server with an explicit allowlist
containing repo A's origin, and enable credentials if auth uses cookies.
Files:
src/server.js
And the matching TODO item:
[ ] TODO-01 (runtime/blocker) [BLOCKING] Repo B serves repo A but configures no CORS
What: Repo A makes browser-side calls into repo B's server, and no `cors`
usage was found anywhere in repo B. Cross-origin requests from the browser
will be blocked once the two run as separate origins.
How:
1. Add the cors middleware to the serving repo, before the route handlers
are registered.
2. Configure an explicit origin allowlist rather than a wildcard -- a
wildcard cannot be combined with credentialed requests.
3. If auth uses cookies, set credentials: true on the server and
credentials: "include" on the client's fetch calls.
4. Confirm the allowed methods cover every verb the client actually uses.
Verify: From the browser (not curl -- curl ignores CORS), trigger one
cross-origin request and confirm no CORS error in the console.
Files: src/server.js
ingest ──▶ analyzers ──────────────────────────────▶ synthesis ──▶ actuation
clone dependencies · routes · components compatibility branch
codeIntel (A, B) ──▶ integration todoList PR
gitLog issues
fusionPlan
- Ingestion — shallow-clones both repos (or reads a local path) into
os.tmpdir(). - Detection analyzers — dependency drift, route collisions, router-convention mismatch, duplicate components: all diffed from manifests and file paths, deterministic, no model call.
- Code intelligence (
analyzers/codeIntel.ts) — regex extraction over the actual source of each repo: served endpoints, outgoing calls, ports, env vars, mounted router prefixes, tech signatures. Every fact carriesfile:line. - Integration analysis (
analyzers/integration.ts) — cross-references the two repos' code intelligence into concrete findings: matched call↔endpoint seams, orphan calls, port collisions, missing CORS, env-var collisions, auth mismatches, data-layer overlap. - Compatibility (
analyzers/compatibility.ts) — the up-front verdict, computed from the findings above. - Synthesis (
synth/) — one call to a model (routed through OpenRouter toopenai/gpt-4o-mini, using the officialopenaiSDK) with structured outputs, producing the executive summary and stack table; falls back to a deterministic template if no key is set or the call fails. The TODO checklist and commit hashes are always computed locally, never left to the model. - Actuation (
actuate/) —@octokit/restcalls that create the fusion-draft branch, copy flagged files, writeFUSION_PLAN.md, open the PR, and file labeled issues. - Two front doors — a
commander-based CLI, and a small Express web UI (web/) for pasting two URLs and reading the report in the browser.
Full stage-by-stage specification: AGENTS.md.
GITHUB_TOKEN=your_github_token # branch, PR, issues (only for a real, non-dry-run)
OPENROUTER_API_KEY=your_openrouter_key # synthesis; falls back to a template if unsetWEB_PORT optionally overrides the web UI's port (default 8080).
- Code intelligence is regex extraction, not AST or type analysis. It reads what the source literally says. Dynamically-built URLs, endpoints registered in a loop, routers mounted through a variable, and calls made through a pre-configured client wrapper are all missed — absence of a finding is not proof of absence.
- Next.js server actions and RSC data fetching are invisible to the call detector.
- Endpoint matching compares method + normalized path only, never request/response shape.
- Only the root
package.jsonis read; monorepo workspaces with multiple manifests aren't supported. - Component-duplicate detection compares filenames only, never file contents.
- Re-running against the same GitHub target creates duplicate issues; there's no dedup key.
See AGENTS.md for the complete list and the full data contract.
TypeScript · Node.js · Express · simple-git · fast-glob · semver · @octokit/rest · openai SDK (via OpenRouter) · commander · dotenv
The original architecture, data contracts, and stage-by-stage build specification (AGENTS.md) were produced with OpenAI Codex for the ChatGPT Codex Hackathon 2026: ingestion, the three detection analyzers, scoring, GitHub actuation, and the CLI. Later work — done with Claude — audited that build against its own specification, fixed the bugs that turned up (a semver crash on non-standard version ranges, a request that could hang for up to 30 minutes with no timeout, a demo fixture missing its intended router-mismatch conflict, among others), migrated synthesis to OpenRouter, and added the code intelligence and integration-analysis layers, the compatibility verdict, the TODO checklist, the git log-formatted plan, and the web UI.