Skip to content

Aburi

A library that reproduces, as a tool, the process a senior engineer performs mentally during code review: stripping away decoration and looking only at meaningful control flow, domain rules, and module boundaries.

For the roadmap and per-version scope, see roadmap.md. Detailed designs live in this directory.


1. Purpose and Use Cases

Aburi outputs an intermediate representation (IR) that is neither full source code nor a natural-language summary.

Primary use cases

  • Review large AI-generated implementation diffs at the granularity of business logic and architecture
  • Let newcomers quickly understand the structure of a large codebase
  • Visualize the impact of a change per PR as a semantic diff rather than lines of code

Primary comparison axis

Time-series comparison within the same project (PR diffs, between releases, against past versions) is the first-class use case and what the design optimizes for. Cross-project comparison is secondary.

2. Core Design Decisions

DecisionAdoptedRejected, and why
IR formatJSON, fixed (Markdown is a deterministic derivation)Markdown as primary IR (weak machine processing / schema validation)
Config formatJSONC (biome.json style)TypeScript / YAML (no dynamic logic needed; static is better given AI integration)
Extraction strategy"Drop" as primary, "keep" as secondaryDefining only "what to keep" (decoration is finite, logic is infinite)
Parser layerTree-sitter core, always resident + optional LSP enrichmentLSP only (unstable in CI; large per-language variance)
Structural interpretationStatic heuristics + symbol graphLLM judgment (verifiability and diff stability disappear)
Diff stabilitySemantic ID + 3-layer fingerprint (api/logic/syntax) + rename trackingLine-based diff
Diff statusesadded/removed/moved/changed/moved+changedadded/removed only (loses trust on file moves)
Configuration philosophyRobust defaults + minimal overridesHighly configurable (time-series comparison breaks on config updates)
Language vocabularyCommon core vocabulary + language extensions (<namespace>:<kind>)Core vocabulary only (cannot express functional ADT/match etc.)
ConfidenceCategorical (high / medium / low)Numeric (breeding ground for false precision)
DeliveryCLI + bundled GitHub Action wrapperCLI only / Web UI

3. Output Architecture

3.1 Horizontal layers

LayerContentForm
L3Symbol IR — the source of truthJSON
L2Module logic: control flow, rules, effects, per function or methodMarkdown
L1Component architecture: public API, effect boundaries, owning modulesMarkdown
L0Workspace overview: dependency direction and component boundariesMarkdown

L3 is the truth. L0/L1/L2 are all derived from it deterministically.

3.2 Vertical view (Slice View)

Horizontal layers are good at bundling like with like, but for a single feature addition that cuts vertically through Controller→Service→Repository→Migration, the diff scatters.

Slice View: cluster the set of changed symbols into connected components over the call graph and display them as vertical slices (per feature). It is derived from the same L3 IR.

Full specification: slice-view.md.

4. Extraction Pipeline

#StageProduces
1tree-sitter parse (plus LSP enrichment when available)AST
2Drop list — .scm queries and the decoration callee setFiltered AST
3Tag propagation — Boundary / Effect / Rule / DataModel / language extensionsTagged nodes
4Score and filter — untagged symbols are droppedSymbols
5Normalize — callee whitespace, expression canonicalization, sortNormalized symbols
6Call resolution — fill in Symbol.calls[].resolvedCallEdge[]
7Effect propagation — augment Symbol.effects[] along resolved edgesPropagated effects
8Fingerprint — api / logic / syntaxL3 IR (JSON)
9ProjectL2 / L1 / L0 Markdown + Slice View

The tag vocabulary applied at step 3:

  • Boundary: framework decorator / exported symbol / route handler
  • Effect: db.* / network.* / queue.* / event.* / fs.* / state.* / time.* / random / env.* / process.*
  • Rule: guard (if + throw/return) / loop / try / switch / match / non-trivial return
  • DataModel: interface / type alias / pure DTO
  • Language extensions: fp:match / fp:adt / fp:effect / oop:abstract / meta:macro / …

Details are covered by the documents in this directory:

5. IR and Config

The IR schema (aburi.ir.v1) is defined in ir-schema.md; the JSON Schema is schema/aburi.ir.v1.json.

The configuration file is aburi.json or aburi.jsonc (workspace root). Details in config.md.

Deliberately not configurable (to keep time-series comparison stable):

  • score weights
  • output ordering
  • IR schema
  • AST traversal details
  • raw per-language node kind specification

Config is version-controlled; when regenerating a past IR, the operational rule is to check out the Config of that time from git and use it.

6. CLI

bash
aburi init                       # generate config (autodetect: workspace manager / framework / language)
aburi scan                       # generate full IR → out/aburi.ir.json + out/workspace.md + out/components/*.md
aburi diff <base>..<head>        # semantic diff → out/diff.md (for pasting as a PR comment)
aburi explain <file-or-symbol>   # L2 Markdown for a single symbol to stdout

Automatic PR comment posting is bundled as a thin @aburi/github-action (github-action.md). Detailed CLI specification: cli-spec.md.

7. Diff Strategy

StatusDetection method
addedSymbol absent from the old IR and present in the new IR
removedSymbol present in the old IR and absent from the new IR
movedgit rename detection + differing path but matching remainder of the symbol ID, or fingerprint match
changedSame ID with a change in either the api or logic fingerprint
moved+changedRenamed and the fingerprint changed as well

Move detection runs in order, each stage handling what the previous one left:

  1. Physical rename mapping from git diff --find-renames
  2. Logic fingerprint equality
  3. Name + signature similarity, above a threshold
  4. Anything left is treated as add + remove

A pure moved (no semantic change) is explicitly labeled "move only" in the diff report, reducing review load to zero. Algorithm details: diff-algorithm.md.

8. Non-Goals

Explicitly out of scope:

  • Semantic judgment by an LLM (verifiability and diff stability disappear)
  • Beautiful SVG visualization (diff-unstable / overlaps with existing tools)
  • Lint use cases (Biome/ESLint own that)
  • Natural-language summaries (that is the job of whatever consumes the IR downstream, e.g. an AI)
  • Exposing score weights in configuration
  • Tracking the IR in git (by default)

9. Failure Patterns and Mitigations

FailureMitigation
"Plausible-looking summary that cannot be trusted"Every IR element carries source range + confidence (high/medium/low) + derivedBy
Over-abstraction drops edge cases and yields a false LGTM"Drop" takes priority; guard/throw is always kept; low confidence is called out explicitly in the report
Minor refactors turn the diff bright redSemantic ID + 3-layer fingerprint + normalization pass
File moves produce mass add/removegit rename detection + fingerprint matching + moved status
Config updates break time-series comparisonStrictly limit configurable options; config is itself version-controlled
Functional languages become inexpressibleTwo-layer vocabulary: core + language extensions (<namespace>:<kind>)
AI progress erases the IR's reason to exist"A diff representation that is easy for AI to read" is itself the primary value — smaller, faster, and more reliable than reading all code directly

10. Project Layout

PathContents
docs/design/Detailed designs — IR schema, plugin interfaces, fingerprint, diff, and so on
docs/The published documentation site (guide, reference, extension docs)
schema/JSON Schema for the IR, diff, config, and plugin manifest
packages/Published npm packages, named @aburi/<type>-<name>

Tooling: tsdown (bundle) / Vitest (test) / Biome (lint + format) / pnpm workspaces.

Released under the Apache License 2.0.