Kind: Service
Source: atloria-monorepo/apps/api/src/change-request/diff.service.ts
DiffService — the CR diff engine over the per-project docs git substrate (S2.2).
Two capabilities:
- diffRefs: a structured two-ref diff (per-file status, +/- counts, unified hunks with old/new line numbers, and heading-level SectionDiffs so the UI can say "§Setup changed").
- threeWaySections: a pure, heading-aligned three-way section classifier for CR merge (base vs mine vs theirs → unchanged / take-theirs / keep-mine / conflict).
ALL git invocation is via promisified execFile('git', [argv]) — never a shell string —
mirroring DocsRepoService. Renames are reported as delete+add for v1 (--no-renames).
DiffService is the change-request diff engine for a project's documentation Git repository. It produces structured two-ref diffs with file statuses, line counts, hunks, and heading-level section changes, and it classifies three-way section merges as unchanged, take-theirs, keep-mine, or conflict. Git commands are executed safely through execFile('git', argv) rather than shell command strings.
Methods
| Method | Signature | Returns | Description |
|---|---|---|---|
diffRefs | diffRefs(projectId: string, baseRef: string, headRef: string, paths: string[]) | Promise<CrDiff> | Structured diff of baseRef..headRef in the project's docs repo, optionally scoped to paths. |
threeWaySections | threeWaySections(base: string, mine: string, theirs: string) | ThreeWaySection[] | Pure three-way section classification (no I/O). |
Dependencies
DocsRepoService
Where it refuses work
DiffServicestops the work withErrorwhen!ref || ref.startsWith('-').DiffServicestops the work with an early return whenheading === undefined.DiffServicestops the work with an early return whenmineText === theirsText.DiffServicestops the work with an early return whenmineText === baseText.DiffServicestops the work with an early return whentheirsText === baseText.DiffServicestops the work with an early return whenraw === '/dev/null'.
When something fails
DiffServicehandles failure in 1 place: it turns it into a return value in all 1.
Diagram
mermaidsequenceDiagram participant Caller as CR Controller / Merge Flow participant DiffService participant Git as Project Docs Git Repository Caller->>DiffService: diffRefs(projectPath, baseRef, headRef) DiffService->>Git: git diff --no-renames --numstat baseRef headRef Git-->>DiffService: per-file additions/deletions/status DiffService->>Git: git diff --no-renames --unified=... baseRef headRef Git-->>DiffService: unified diff hunks DiffService->>Git: git show baseRef:path / headRef:path Git-->>DiffService: document contents DiffService-->>Caller: CrDiff with files, hunks, and SectionDiffs Caller->>DiffService: threeWaySections(base, mine, theirs) DiffService->>DiffService: Align sections by heading DiffService-->>Caller: ThreeWaySection[] classifications
Usage
tsimport { DiffService } from './diff.service';
async function reviewChangeRequest(
diffService: DiffService,
repoPath: string,
baseRef: string,
changeRequestRef: string,
) {
const diff = await diffService.diffRefs(repoPath, baseRef, changeRequestRef);
for (const file of diff.files) {
console.log(
`${file.status}: ${file.path} (+${file.additions} / -${file.deletions})`,
);
for (const section of file.sections) {
console.log(` Section "${section.heading}" changed`);
}
}
return diff;
}
async function classifyMerge(
diffService: DiffService,
baseMarkdown: string,
mineMarkdown: string,
theirsMarkdown: string,
) {
const sections = diffService.threeWaySections(
baseMarkdown,
mineMarkdown,
theirsMarkdown,
);
return sections.filter((section) => section.status === 'conflict');
}
AI Coding Instructions
- Invoke Git only through promisified
execFile('git', argv); never construct shell command strings or interpolate refs/paths into a shell command. - Preserve
--no-renamesbehavior for diffs: v1 intentionally represents renames as a deleted file plus an added file. - Keep
diffRefsoutput structured for UI consumers, including file-level status/counts, unified hunks with line numbers, and heading-levelSectionDiffdata. - Ensure three-way merge logic aligns Markdown content by headings before classifying each section as
unchanged,take-theirs,keep-mine, orconflict. - Treat Git refs and repository paths as external inputs: validate assumptions and surface actionable errors when refs, files, or repository state cannot be resolved.
Relationships
- DEPENDS_ON →
DocsRepoService
Referenced By
ChangeRequestModule(MODULE_PROVIDES)ChangeRequestModule(MODULE_EXPORTS)
Was this page helpful?