@gitkraken/conflict-tools 0.2.4-beta.7 → 0.2.4-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
17
17
 
18
18
  ### Changed
19
19
 
20
+ - **Breaking**: consumer validation moved to a `Validator` port — `validate(sources: SourceOverlay): Promise<ValidatorFinding[]>` (replaces the per-file `ResolutionVerifier.verify`). It runs post-refine, non-blocking, over an overlay (one file for per-file validation, or the touched set for cross-file); its findings fold into the operation's detection findings and verdict. `Resolution.findings` replaces `Resolution.issues`. `Finding.category` is now an open `string` so a consumer validator can contribute its own categories — the package still emits the well-known `FindingCategory` values. `defaultVerifier` / `VerificationResult` are no longer exported (`checkResidualMarkers` stays internal, the built-in marker gate).
20
21
  - **Breaking**: the resolver's in-loop blocking check is now **residual conflict markers only** (built-in, language-agnostic). The `ResolverDeps.verifier` port no longer gates the resolve loop or triggers re-resolution — it runs once **after** refine, **non-blocking**, and its issues are attached to `Resolution.issues` (advisory) and reported. This stops the resolver from burning its step budget on non-marker validation (which was exhausting into a whole-file `take-theirs` fallback), and puts consumer validation in its intended post-refine, report-only role. `ResolverLoopResult` no longer carries `issues`.
21
22
 
22
23
  ### Fixed
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { AIError, AIErrorCode } from "./errors/ai.js";
2
2
  import { ConflictError, ConflictErrorCode } from "./errors/conflict.js";
3
3
  import { BlameOptions, ConflictDiffOptions, ConflictGitOps, ConflictGitPort, ConflictGitPortMissingOpError, GrepOptions, LogOptions, OpOptions, ShowFileOptions, ShowOptions, UnmergedEntry, UnmergedReason } from "./ports/git.js";
4
+ import { CheckStatus, DetectionReport, Finding, FindingCategory, FindingTier } from "./types/findings.js";
4
5
  import { IntraFileEditOp } from "./types/hints.js";
5
- import { Issue } from "./types/issue.js";
6
6
  import { DiffStats, Resolution, ResolutionContext, ResolutionMetrics, ResolutionRawSignals, ResolutionRefs, ResolutionStrategy, ResolvedChunk, ThreeWayDiff } from "./types/resolution.js";
7
7
  import { Conflict, ConflictMarker, ConflictMarkerUserInput, ConflictType } from "./types/conflict.js";
8
8
  import { extractConflict } from "./extraction/extract.js";
@@ -10,8 +10,8 @@ import { checkoutFile, removeFile, show } from "./git/port-dispatch.js";
10
10
  import { ToolCall, ToolDefinition, ToolResult } from "./types/tool.js";
11
11
  import { ConflictModelMessage, ConflictModelParams, ConflictModelPort, ConflictModelResult, ResolverConfig } from "./ports/model.js";
12
12
  import { ParsedFile, ParserPort, SourceOverlay, SymbolDefinition, SymbolReference, SyntaxIssue } from "./ports/parser.js";
13
- import { ResolutionVerifier, VerificationResult, defaultVerifier } from "./ports/verify.js";
14
- import { CheckStatus, DetectionReport, Finding, FindingCategory, FindingTier } from "./types/findings.js";
13
+ import { Issue } from "./types/issue.js";
14
+ import { Validator, ValidatorFinding } from "./ports/verify.js";
15
15
  import { DetectDeps, detect } from "./reference-integrity/detect.js";
16
16
  import { createResolution } from "./resolution/create-resolution.js";
17
17
  import { takeOurs, takeTheirs } from "./resolution/take-strategy.js";
@@ -22,4 +22,4 @@ import { FileRule, StepConfig, StepResult } from "./types/step.js";
22
22
  import { resolveConflicts } from "./resolver/resolve-conflicts.js";
23
23
  import { OperationDigest, OperationSummary, OperationVerdict, ReviewItem } from "./types/summary.js";
24
24
  import { SummarizeOperationOptions, buildOperationDigest, summarizeOperation } from "./resolver/summarize-operation.js";
25
- export { AIError, type AIErrorCode, type BlameOptions, type CheckStatus, type Conflict, type ConflictDiffOptions, ConflictError, type ConflictErrorCode, type ConflictGitOps, type ConflictGitPort, ConflictGitPortMissingOpError, type ConflictMarker, type ConflictMarkerUserInput, type ConflictModelMessage, type ConflictModelParams, type ConflictModelPort, type ConflictModelResult, type ConflictProgressEvent, type ConflictType, type DetectDeps, type DetectionReport, type DiffStats, type FileRule, type Finding, type FindingCategory, type FindingTier, type GrepOptions, type IntraFileEditOp, type Issue, type LogOptions, type OpOptions, type OperationDigest, type OperationSummary, type OperationVerdict, type ParsedFile, type ParserPort, type Resolution, type ResolutionContext, type ResolutionMetrics, type ResolutionRawSignals, type ResolutionRefs, type ResolutionStrategy, type ResolutionVerifier, type ResolvedChunk, type ResolverConfig, type ReviewItem, type ShowFileOptions, type ShowOptions, type SourceOverlay, type StepConfig, type StepResult, type SummarizeOperationOptions, type SymbolDefinition, type SymbolReference, type SyntaxIssue, type ThreeWayDiff, type ToolCall, type ToolDefinition, type ToolResult, type UnmergedEntry, type UnmergedReason, type VerificationResult, applyResolutions, buildOperationDigest, checkoutFile, createResolution, defaultVerifier, detect, extractConflict, removeFile, resolveConflict, resolveConflicts, show, summarizeOperation, takeOurs, takeTheirs };
25
+ export { AIError, type AIErrorCode, type BlameOptions, type CheckStatus, type Conflict, type ConflictDiffOptions, ConflictError, type ConflictErrorCode, type ConflictGitOps, type ConflictGitPort, ConflictGitPortMissingOpError, type ConflictMarker, type ConflictMarkerUserInput, type ConflictModelMessage, type ConflictModelParams, type ConflictModelPort, type ConflictModelResult, type ConflictProgressEvent, type ConflictType, type DetectDeps, type DetectionReport, type DiffStats, type FileRule, type Finding, type FindingCategory, type FindingTier, type GrepOptions, type IntraFileEditOp, type Issue, type LogOptions, type OpOptions, type OperationDigest, type OperationSummary, type OperationVerdict, type ParsedFile, type ParserPort, type Resolution, type ResolutionContext, type ResolutionMetrics, type ResolutionRawSignals, type ResolutionRefs, type ResolutionStrategy, type ResolvedChunk, type ResolverConfig, type ReviewItem, type ShowFileOptions, type ShowOptions, type SourceOverlay, type StepConfig, type StepResult, type SummarizeOperationOptions, type SymbolDefinition, type SymbolReference, type SyntaxIssue, type ThreeWayDiff, type ToolCall, type ToolDefinition, type ToolResult, type UnmergedEntry, type UnmergedReason, type Validator, type ValidatorFinding, applyResolutions, buildOperationDigest, checkoutFile, createResolution, detect, extractConflict, removeFile, resolveConflict, resolveConflicts, show, summarizeOperation, takeOurs, takeTheirs };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{AIError as e}from"./errors/ai.js";import{ConflictError as t}from"./errors/conflict.js";import{ConflictGitPortMissingOpError as n}from"./ports/git.js";import{checkoutFile as r,removeFile as i,show as a}from"./git/port-dispatch.js";import{extractConflict as o}from"./extraction/extract.js";import{defaultVerifier as s}from"./ports/verify.js";import{detect as c}from"./reference-integrity/detect.js";import{createResolution as l}from"./resolution/create-resolution.js";import{takeOurs as u,takeTheirs as d}from"./resolution/take-strategy.js";import{applyResolutions as f}from"./resolver/apply-resolutions.js";import{resolveConflict as p}from"./resolver/resolve-conflict.js";import{resolveConflicts as m}from"./resolver/resolve-conflicts.js";import{buildOperationDigest as h,summarizeOperation as g}from"./resolver/summarize-operation.js";export{e as AIError,t as ConflictError,n as ConflictGitPortMissingOpError,f as applyResolutions,h as buildOperationDigest,r as checkoutFile,l as createResolution,s as defaultVerifier,c as detect,o as extractConflict,i as removeFile,p as resolveConflict,m as resolveConflicts,a as show,g as summarizeOperation,u as takeOurs,d as takeTheirs};
1
+ import{AIError as e}from"./errors/ai.js";import{ConflictError as t}from"./errors/conflict.js";import{ConflictGitPortMissingOpError as n}from"./ports/git.js";import{checkoutFile as r,removeFile as i,show as a}from"./git/port-dispatch.js";import{extractConflict as o}from"./extraction/extract.js";import{detect as s}from"./reference-integrity/detect.js";import{createResolution as c}from"./resolution/create-resolution.js";import{takeOurs as l,takeTheirs as u}from"./resolution/take-strategy.js";import{applyResolutions as d}from"./resolver/apply-resolutions.js";import{resolveConflict as f}from"./resolver/resolve-conflict.js";import{resolveConflicts as p}from"./resolver/resolve-conflicts.js";import{buildOperationDigest as m,summarizeOperation as h}from"./resolver/summarize-operation.js";export{e as AIError,t as ConflictError,n as ConflictGitPortMissingOpError,d as applyResolutions,m as buildOperationDigest,r as checkoutFile,c as createResolution,s as detect,o as extractConflict,i as removeFile,f as resolveConflict,p as resolveConflicts,a as show,h as summarizeOperation,l as takeOurs,u as takeTheirs};
@@ -1,3 +1,4 @@
1
+ import { SourceOverlay } from "./parser.js";
1
2
  import { Issue } from "../types/issue.js";
2
3
 
3
4
  //#region src/ports/verify.d.ts
@@ -5,17 +6,25 @@ interface VerificationResult {
5
6
  valid: boolean;
6
7
  issues?: Issue[];
7
8
  }
9
+ interface ValidatorFinding {
10
+ /** Open category string set by the consumer (e.g. `'type-error'`, `'lint:no-console'`). */
11
+ category: string;
12
+ severity: 'error' | 'warning';
13
+ file: string;
14
+ /** 1-indexed. */
15
+ line?: number;
16
+ message: string;
17
+ }
8
18
  /**
9
- * The consumer's per-file validation port (stage 5). Plug in any per-file checks — syntax, imports,
10
- * lint, project rules. It is **non-blocking**: it runs on the final resolved content *after* refine,
11
- * and its `issues` are advisory (attached to the resolution and reported), never a re-resolve. The
12
- * only thing that blocks / re-resolves is residual conflict markers, which the resolver checks
13
- * built-in ({@link checkResidualMarkers}) — do not rely on this port for that. `valid` is advisory.
19
+ * The consumer's validation port (RFC stages 5/7). Plug in any checks — syntax, real import
20
+ * resolution, types, lint, project rules. **Non-blocking**: runs post-refine over an overlay (one file
21
+ * for per-file validation, or the whole touched set for cross-file); its findings are advisory (folded
22
+ * into the operation's findings and verdict), never a re-resolve. The only blocking gate is residual
23
+ * conflict markers, checked built-in by the resolver ({@link checkResidualMarkers}) — not this port.
14
24
  */
15
- interface ResolutionVerifier {
16
- verify(filePath: string, content: string): Promise<VerificationResult>;
25
+ interface Validator {
26
+ validate(sources: SourceOverlay): Promise<ValidatorFinding[]>;
17
27
  }
18
28
  declare function checkResidualMarkers(_filePath: string, content: string): VerificationResult;
19
- declare const defaultVerifier: ResolutionVerifier;
20
29
  //#endregion
21
- export { ResolutionVerifier, VerificationResult, checkResidualMarkers, defaultVerifier };
30
+ export { Validator, ValidatorFinding, VerificationResult, checkResidualMarkers };
@@ -1,2 +1,2 @@
1
1
  const e=[/^<{7}(\s|$)/,/^\|{7}(\s|$)/,/^={7}(\s|$)/,/^>{7}(\s|$)/];function t(t,n){let r=n.split(`
2
- `),i=[];for(let t=0;t<r.length;t++){let n=r[t]??``;for(let r of e)if(r.test(n)){i.push(t+1);break}}return i.length===0?{valid:!0}:{valid:!1,issues:[{severity:`error`,message:`Residual conflict markers found at line(s) ${i.join(`, `)}.`}]}}const n={async verify(e,n){return t(e,n)}};export{t as checkResidualMarkers,n as defaultVerifier};
2
+ `),i=[];for(let t=0;t<r.length;t++){let n=r[t]??``;for(let r of e)if(r.test(n)){i.push(t+1);break}}return i.length===0?{valid:!0}:{valid:!1,issues:[{severity:`error`,message:`Residual conflict markers found at line(s) ${i.join(`, `)}.`}]}}export{t as checkResidualMarkers};
@@ -1,7 +1,7 @@
1
1
  import { ConflictGitPort } from "../ports/git.js";
2
+ import { DetectionReport } from "../types/findings.js";
2
3
  import { Resolution, ResolutionContext } from "../types/resolution.js";
3
4
  import { ParserPort } from "../ports/parser.js";
4
- import { DetectionReport } from "../types/findings.js";
5
5
 
6
6
  //#region src/reference-integrity/detect.d.ts
7
7
  interface DetectDeps {
@@ -1,7 +1,7 @@
1
1
  import { ConflictGitPort } from "../ports/git.js";
2
2
  import { ConflictModelPort, ResolverConfig } from "../ports/model.js";
3
3
  import { ParserPort } from "../ports/parser.js";
4
- import { ResolutionVerifier } from "../ports/verify.js";
4
+ import { Validator } from "../ports/verify.js";
5
5
  import { ConflictProgressEvent } from "../types/events.js";
6
6
 
7
7
  //#region src/resolver/deps.d.ts
@@ -11,7 +11,7 @@ interface ResolverDeps<C extends ResolverConfig = ResolverConfig> {
11
11
  config?: C;
12
12
  onProgress?: (event: ConflictProgressEvent) => void;
13
13
  signal?: AbortSignal;
14
- verifier?: ResolutionVerifier;
14
+ validator?: Validator;
15
15
  parser?: ParserPort;
16
16
  }
17
17
  //#endregion
@@ -1 +1 @@
1
- import{checkResidualMarkers as e}from"../ports/verify.js";import{resolveChunkContent as t}from"../resolution/chunk-apply.js";import{createResolution as n}from"../resolution/create-resolution.js";import{mergeUsages as r}from"../resolution/metrics.js";import{runResolverLoop as i}from"./loop.js";import{runRefinePass as a}from"./refine-pass.js";import{buildThreeWayDiff as o}from"./three-way-diff.js";const s={refineNoAction:.6,refineApplied:.9};async function c(c,l,u){let d=l.threeWayDiff||!l.refs?l:{...l,threeWayDiff:await o(c.filePath,l.refs,{git:u.git,signal:u.signal})},{chunks:f,strategy:p,confidence:m,description:h,metrics:g,followUpInstructions:_}=await i(c,d,{model:u.model,git:u.git,config:u.config,onProgress:u.onProgress,signal:u.signal}),v=n(c,f,{confidence:m,description:h,metrics:g,...p?{fileStrategy:p}:{},...d.threeWayDiff?{threeWayDiff:d.threeWayDiff}:{}}),y=_&&_.length>0;if(c.type===`text`&&y){u.onProgress?.({type:`refine:started`,filePath:c.filePath});let n=0;try{let i=await a(v.content,v.description,_,{model:u.model,signal:u.signal,temperature:u.config?.temperature,refineMaxSteps:u.config?.refineMaxSteps,onProgress:u.onProgress,filePath:c.filePath});if(i.edits.length>0){let t=e(c.filePath,i.content);if(t.valid)v={...v,content:i.content,edits:i.edits,strategy:`ai`},n=i.edits.length;else{let e=(t.issues??[]).map(e=>e.message).join(` `);u.onProgress?.({type:`refine:discarded`,filePath:c.filePath,reason:`Edits introduced conflict markers: ${e}`})}}if(n>0){v={...v,confidence:Math.min(v.confidence,s.refineApplied)};let e=[];for(let n=0;n<c.markers.length;n++){let r=c.markers[n];if(!r||r.userResolution==null)continue;let a=t({markerIndex:n,...r.userResolution},r);a!==``&&(i.content.includes(a)||e.push(n))}e.length>0&&(u.onProgress?.({type:`refine:touched-user-region`,filePath:c.filePath,markerIndexes:e}),v={...v,note:`Refine modified user-resolved region(s): marker ${e.join(`, `)}.`})}else i.edits.length===0&&i.verifies>0||(v={...v,confidence:Math.min(v.confidence,s.refineNoAction)});if(i.usage){let e=r(v.metrics??{inputTokens:0,outputTokens:0},i.usage);v={...v,metrics:{...v.metrics,...e}}}u.onProgress?.({type:`refine:completed`,filePath:c.filePath,appliedCount:n})}catch(e){let t=e instanceof Error?e.message:String(e);throw u.onProgress?.({type:`refine:failed`,filePath:c.filePath,reason:t}),e}}else u.onProgress?.({type:`refine:skipped`,filePath:c.filePath,reason:`no-follow-ups`});if(u.verifier&&c.type===`text`){let e=(await u.verifier.verify(c.filePath,v.content)).issues??[];e.length>0&&(v={...v,issues:e},u.onProgress?.({type:`verification:issues`,filePath:c.filePath,issues:e}))}return u.onProgress?.({type:`resolver:completed`,filePath:c.filePath,stepCount:g.stepCount??0}),v}export{c as resolveConflict};
1
+ import{resolveChunkContent as e}from"../resolution/chunk-apply.js";import{createResolution as t}from"../resolution/create-resolution.js";import{checkResidualMarkers as n}from"../ports/verify.js";import{mergeUsages as r}from"../resolution/metrics.js";import{runResolverLoop as i}from"./loop.js";import{runRefinePass as a}from"./refine-pass.js";import{buildThreeWayDiff as o}from"./three-way-diff.js";const s={refineNoAction:.6,refineApplied:.9};async function c(c,l,u){let d=l.threeWayDiff||!l.refs?l:{...l,threeWayDiff:await o(c.filePath,l.refs,{git:u.git,signal:u.signal})},{chunks:f,strategy:p,confidence:m,description:h,metrics:g,followUpInstructions:_}=await i(c,d,{model:u.model,git:u.git,config:u.config,onProgress:u.onProgress,signal:u.signal}),v=t(c,f,{confidence:m,description:h,metrics:g,...p?{fileStrategy:p}:{},...d.threeWayDiff?{threeWayDiff:d.threeWayDiff}:{}}),y=_&&_.length>0;if(c.type===`text`&&y){u.onProgress?.({type:`refine:started`,filePath:c.filePath});let t=0;try{let i=await a(v.content,v.description,_,{model:u.model,signal:u.signal,temperature:u.config?.temperature,refineMaxSteps:u.config?.refineMaxSteps,onProgress:u.onProgress,filePath:c.filePath});if(i.edits.length>0){let e=n(c.filePath,i.content);if(e.valid)v={...v,content:i.content,edits:i.edits,strategy:`ai`},t=i.edits.length;else{let t=(e.issues??[]).map(e=>e.message).join(` `);u.onProgress?.({type:`refine:discarded`,filePath:c.filePath,reason:`Edits introduced conflict markers: ${t}`})}}if(t>0){v={...v,confidence:Math.min(v.confidence,s.refineApplied)};let t=[];for(let n=0;n<c.markers.length;n++){let r=c.markers[n];if(!r||r.userResolution==null)continue;let a=e({markerIndex:n,...r.userResolution},r);a!==``&&(i.content.includes(a)||t.push(n))}t.length>0&&(u.onProgress?.({type:`refine:touched-user-region`,filePath:c.filePath,markerIndexes:t}),v={...v,note:`Refine modified user-resolved region(s): marker ${t.join(`, `)}.`})}else i.edits.length===0&&i.verifies>0||(v={...v,confidence:Math.min(v.confidence,s.refineNoAction)});if(i.usage){let e=r(v.metrics??{inputTokens:0,outputTokens:0},i.usage);v={...v,metrics:{...v.metrics,...e}}}u.onProgress?.({type:`refine:completed`,filePath:c.filePath,appliedCount:t})}catch(e){let t=e instanceof Error?e.message:String(e);throw u.onProgress?.({type:`refine:failed`,filePath:c.filePath,reason:t}),e}}else u.onProgress?.({type:`refine:skipped`,filePath:c.filePath,reason:`no-follow-ups`});if(u.validator&&c.type===`text`){let e=await u.validator.validate(new Map([[c.filePath,v.content]]));if(e.length>0){let t=e.map(e=>({category:e.category,severity:e.severity,tier:`file`,location:{file:e.file,...e.line==null?{line:1}:{line:e.line}},message:e.message}));v={...v,findings:t}}}return u.onProgress?.({type:`resolver:completed`,filePath:c.filePath,stepCount:g.stepCount??0}),v}export{c as resolveConflict};
@@ -1 +1 @@
1
- import{AIError as e}from"../errors/ai.js";import{unmergedEntries as t}from"../git/port-dispatch.js";import{extractConflict as n}from"../extraction/extract.js";import{detect as r}from"../reference-integrity/detect.js";import{createResolution as i}from"../resolution/create-resolution.js";import{takeOurs as a,takeTheirs as o}from"../resolution/take-strategy.js";import{resolveConflict as s}from"./resolve-conflict.js";import c from"picomatch";function l(e){let t=e.map(e=>{let t=(Array.isArray(e.match)?e.match:[e.match]).map(e=>c(e,{basename:!e.includes(`/`)}));return{isMatch:e=>t.some(t=>t(e)),strategy:e.strategy}});return e=>{for(let{isMatch:n,strategy:r}of t)if(n(e))return r}}async function u(e,s){let c=e.config?.rules??[],u=e.config?.defaultStrategy??`ai`,p=l(c),m=await t(e.git,{signal:e.signal}),h={...s??{}},g=[],_=[],v=[];for(let t of m){if(e.signal?.aborted)break;let r=p(t.path)??u;if(r===`skip`){v.push({filePath:t.path,reason:`excluded`}),e.onProgress?.({type:`conflict:excluded`,filePath:t.path});continue}let s;try{s=await n(t.path,{git:e.git,signal:e.signal},t.reason)}catch(e){_.push({filePath:t.path,error:f(e)});continue}if(!s){v.push({filePath:t.path,reason:`no-markers`}),e.onProgress?.({type:`conflict:skipped`,filePath:t.path,reason:`no-markers`,entryReason:t.reason});continue}e.onProgress?.({type:`conflict:found`,filePath:s.filePath,conflictType:s.type,markerCount:s.markers.length});let c=null;c=r===`take-ours`?a(s):r===`take-theirs`?o(s):r===`deleted`?i(s,[],{confidence:1,fileStrategy:`deleted`}):await d(s,h,e,_),c&&(h.previousResolutions=[...h.previousResolutions??[],c],g.push(c),e.onProgress?.({type:`resolution:applied`,filePath:c.filePath,strategy:c.strategy,confidence:c.confidence,description:c.description}))}return{resolutions:g,errors:_,skipped:v,detection:await r(g,h,{git:e.git,parser:e.parser,signal:e.signal})}}async function d(t,n,r,i){try{return await s(t,n,{model:r.model,git:r.git,config:r.config,onProgress:r.onProgress,signal:r.signal,verifier:r.verifier})}catch(n){let s=f(n),c=r.config?.fallbackStrategy;return c?(r.onProgress?.({type:`resolution:fallback`,filePath:t.filePath,error:s,cause:s instanceof e?s.code:void 0}),{...c===`take-ours`?a(t):o(t),confidence:0}):(i.push({filePath:t.filePath,error:s}),r.onProgress?.({type:`resolution:failed`,filePath:t.filePath,error:s}),null)}}function f(e){return e instanceof Error?e:Error(String(e))}export{u as resolveConflicts};
1
+ import{AIError as e}from"../errors/ai.js";import{unmergedEntries as t}from"../git/port-dispatch.js";import{extractConflict as n}from"../extraction/extract.js";import{detect as r}from"../reference-integrity/detect.js";import{createResolution as i}from"../resolution/create-resolution.js";import{takeOurs as a,takeTheirs as o}from"../resolution/take-strategy.js";import{resolveConflict as s}from"./resolve-conflict.js";import c from"picomatch";function l(e){let t=e.map(e=>{let t=(Array.isArray(e.match)?e.match:[e.match]).map(e=>c(e,{basename:!e.includes(`/`)}));return{isMatch:e=>t.some(t=>t(e)),strategy:e.strategy}});return e=>{for(let{isMatch:n,strategy:r}of t)if(n(e))return r}}async function u(e,s){let c=e.config?.rules??[],u=e.config?.defaultStrategy??`ai`,p=l(c),m=await t(e.git,{signal:e.signal}),h={...s??{}},g=[],_=[],v=[];for(let t of m){if(e.signal?.aborted)break;let r=p(t.path)??u;if(r===`skip`){v.push({filePath:t.path,reason:`excluded`}),e.onProgress?.({type:`conflict:excluded`,filePath:t.path});continue}let s;try{s=await n(t.path,{git:e.git,signal:e.signal},t.reason)}catch(e){_.push({filePath:t.path,error:f(e)});continue}if(!s){v.push({filePath:t.path,reason:`no-markers`}),e.onProgress?.({type:`conflict:skipped`,filePath:t.path,reason:`no-markers`,entryReason:t.reason});continue}e.onProgress?.({type:`conflict:found`,filePath:s.filePath,conflictType:s.type,markerCount:s.markers.length});let c=null;c=r===`take-ours`?a(s):r===`take-theirs`?o(s):r===`deleted`?i(s,[],{confidence:1,fileStrategy:`deleted`}):await d(s,h,e,_),c&&(h.previousResolutions=[...h.previousResolutions??[],c],g.push(c),e.onProgress?.({type:`resolution:applied`,filePath:c.filePath,strategy:c.strategy,confidence:c.confidence,description:c.description}))}let y=await r(g,h,{git:e.git,parser:e.parser,signal:e.signal}),b=g.flatMap(e=>e.findings??[]);return{resolutions:g,errors:_,skipped:v,detection:b.length>0?{...y,findings:[...y.findings,...b]}:y}}async function d(t,n,r,i){try{return await s(t,n,{model:r.model,git:r.git,config:r.config,onProgress:r.onProgress,signal:r.signal,validator:r.validator})}catch(n){let s=f(n),c=r.config?.fallbackStrategy;return c?(r.onProgress?.({type:`resolution:fallback`,filePath:t.filePath,error:s,cause:s instanceof e?s.code:void 0}),{...c===`take-ours`?a(t):o(t),confidence:0}):(i.push({filePath:t.filePath,error:s}),r.onProgress?.({type:`resolution:failed`,filePath:t.filePath,error:s}),null)}}function f(e){return e instanceof Error?e:Error(String(e))}export{u as resolveConflicts};
@@ -5,7 +5,7 @@ import { OperationDigest, OperationSummary } from "../types/summary.js";
5
5
  //#region src/resolver/summarize-operation.d.ts
6
6
  /**
7
7
  * Options for {@link summarizeOperation}. Intentionally a flat bag rather than the resolver's
8
- * `ResolverDeps` shape: summarization is a leaf operation that needs no git, verifier, or progress
8
+ * `ResolverDeps` shape: summarization is a leaf operation that needs no git, validator, or progress
9
9
  * sink, and its `model` is optional — omit it for a digest-only result.
10
10
  */
11
11
  interface SummarizeOperationOptions {
@@ -1,6 +1,6 @@
1
- import { Issue } from "../types/issue.js";
2
1
  import { ResolvedChunk } from "../types/resolution.js";
3
2
  import { Conflict } from "../types/conflict.js";
3
+ import { Issue } from "../types/issue.js";
4
4
 
5
5
  //#region src/resolver/validate.d.ts
6
6
  interface ValidationResult {
@@ -1,6 +1,6 @@
1
- import { Issue } from "./issue.js";
2
1
  import { ResolutionStrategy, ResolvedChunk } from "./resolution.js";
3
2
  import { ConflictType } from "./conflict.js";
3
+ import { Issue } from "./issue.js";
4
4
  import { AiTokenUsage } from "@gitkraken/shared-tools";
5
5
 
6
6
  //#region src/types/events.d.ts
@@ -1,8 +1,13 @@
1
1
  //#region src/types/findings.d.ts
2
+ /** The package's own detection categories. `Finding.category` is an open `string` so consumer
3
+ * validators can contribute their own kinds (e.g. `'type-error'`, `'lint:no-console'`); these are the
4
+ * well-known values the package itself emits. */
2
5
  type FindingCategory = 'broken-reference' | 'duplicate-definition' | 'syntax-error' | 'dropped-side';
3
6
  type FindingTier = 'file' | 'project';
4
7
  interface Finding {
5
- category: FindingCategory;
8
+ /** Finding kind. Open string — the package emits {@link FindingCategory} values; a consumer
9
+ * validator may use its own category strings. */
10
+ category: string;
6
11
  severity: 'error' | 'warning';
7
12
  tier: FindingTier;
8
13
  location: {
@@ -1,5 +1,5 @@
1
+ import { Finding } from "./findings.js";
1
2
  import { IntraFileEditOp } from "./hints.js";
2
- import { Issue } from "./issue.js";
3
3
  import { ConflictType } from "./conflict.js";
4
4
  import { AiTokenUsage } from "@gitkraken/shared-tools";
5
5
 
@@ -26,7 +26,9 @@ interface Resolution {
26
26
  confidence: number;
27
27
  description: string;
28
28
  note?: string;
29
- issues?: Issue[];
29
+ /** Non-blocking per-file findings from the consumer's validator port (post-refine). Folded into
30
+ * the operation's detection findings, hence into the verdict. */
31
+ findings?: Finding[];
30
32
  chunks?: ResolvedChunk[];
31
33
  edits?: IntraFileEditOp[];
32
34
  metrics?: ResolutionMetrics;
@@ -1,6 +1,6 @@
1
+ import { DetectionReport } from "./findings.js";
1
2
  import { Resolution } from "./resolution.js";
2
3
  import { ResolverConfig } from "../ports/model.js";
3
- import { DetectionReport } from "./findings.js";
4
4
 
5
5
  //#region src/types/step.d.ts
6
6
  interface StepResult {
@@ -1,5 +1,4 @@
1
1
  import { ResolutionStrategy } from "./resolution.js";
2
- import { FindingCategory } from "./findings.js";
3
2
  import { AiTokenUsage } from "@gitkraken/shared-tools";
4
3
 
5
4
  //#region src/types/summary.d.ts
@@ -11,7 +10,7 @@ interface ReviewItem {
11
10
  confidence?: number;
12
11
  reason: 'low-confidence' | 'finding';
13
12
  /** Categories of the error-severity findings on this file; present when `reason` is `'finding'`. */
14
- findingCategories?: FindingCategory[];
13
+ findingCategories?: string[];
15
14
  }
16
15
  /** Suggested honest verdict for the operation. `blocked` when any error-severity finding exists;
17
16
  * `needs-review` when confidence is low, detection did not fully run, resolution errored, or a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitkraken/conflict-tools",
3
- "version": "0.2.4-beta.7",
3
+ "version": "0.2.4-beta.8",
4
4
  "description": "AI-powered git conflict resolution.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Axosoft, LLC dba GitKraken",