diffninja 0.1.0

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.
Files changed (154) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +259 -0
  3. package/dist/calltree.d.ts +47 -0
  4. package/dist/calltree.js +296 -0
  5. package/dist/cli.d.ts +57 -0
  6. package/dist/cli.js +340 -0
  7. package/dist/diff.d.ts +7 -0
  8. package/dist/diff.js +114 -0
  9. package/dist/extract.d.ts +26 -0
  10. package/dist/extract.js +152 -0
  11. package/dist/git.d.ts +40 -0
  12. package/dist/git.js +288 -0
  13. package/dist/index.d.ts +9 -0
  14. package/dist/index.js +8 -0
  15. package/dist/infer.d.ts +21 -0
  16. package/dist/infer.js +189 -0
  17. package/dist/languages/bash.d.ts +2 -0
  18. package/dist/languages/bash.js +208 -0
  19. package/dist/languages/c.d.ts +2 -0
  20. package/dist/languages/c.js +218 -0
  21. package/dist/languages/call-syntax.d.ts +125 -0
  22. package/dist/languages/call-syntax.js +997 -0
  23. package/dist/languages/cpp.d.ts +2 -0
  24. package/dist/languages/cpp.js +321 -0
  25. package/dist/languages/csharp.d.ts +2 -0
  26. package/dist/languages/csharp.js +324 -0
  27. package/dist/languages/elixir.d.ts +2 -0
  28. package/dist/languages/elixir.js +331 -0
  29. package/dist/languages/go.d.ts +2 -0
  30. package/dist/languages/go.js +299 -0
  31. package/dist/languages/grammars.d.ts +50 -0
  32. package/dist/languages/grammars.js +351 -0
  33. package/dist/languages/haskell.d.ts +2 -0
  34. package/dist/languages/haskell.js +250 -0
  35. package/dist/languages/java.d.ts +2 -0
  36. package/dist/languages/java.js +351 -0
  37. package/dist/languages/javascript.d.ts +4 -0
  38. package/dist/languages/javascript.js +648 -0
  39. package/dist/languages/kotlin.d.ts +2 -0
  40. package/dist/languages/kotlin.js +368 -0
  41. package/dist/languages/lua.d.ts +2 -0
  42. package/dist/languages/lua.js +212 -0
  43. package/dist/languages/ocaml.d.ts +2 -0
  44. package/dist/languages/ocaml.js +291 -0
  45. package/dist/languages/perl.d.ts +2 -0
  46. package/dist/languages/perl.js +418 -0
  47. package/dist/languages/php.d.ts +2 -0
  48. package/dist/languages/php.js +397 -0
  49. package/dist/languages/python.d.ts +2 -0
  50. package/dist/languages/python.js +376 -0
  51. package/dist/languages/registry.d.ts +7 -0
  52. package/dist/languages/registry.js +69 -0
  53. package/dist/languages/ruby.d.ts +2 -0
  54. package/dist/languages/ruby.js +391 -0
  55. package/dist/languages/rust.d.ts +2 -0
  56. package/dist/languages/rust.js +261 -0
  57. package/dist/languages/scala.d.ts +2 -0
  58. package/dist/languages/scala.js +307 -0
  59. package/dist/languages/solidity.d.ts +2 -0
  60. package/dist/languages/solidity.js +240 -0
  61. package/dist/languages/swift.d.ts +2 -0
  62. package/dist/languages/swift.js +268 -0
  63. package/dist/languages/types.d.ts +36 -0
  64. package/dist/languages/types.js +74 -0
  65. package/dist/languages/typescript-contracts.d.ts +57 -0
  66. package/dist/languages/typescript-contracts.js +528 -0
  67. package/dist/languages/typescript-dispatch.d.ts +68 -0
  68. package/dist/languages/typescript-dispatch.js +710 -0
  69. package/dist/languages/typescript.d.ts +4 -0
  70. package/dist/languages/typescript.js +722 -0
  71. package/dist/languages/zig.d.ts +2 -0
  72. package/dist/languages/zig.js +243 -0
  73. package/dist/loc.d.ts +17 -0
  74. package/dist/loc.js +34 -0
  75. package/dist/reach.d.ts +17 -0
  76. package/dist/reach.js +65 -0
  77. package/dist/render.d.ts +18 -0
  78. package/dist/render.js +83 -0
  79. package/dist/review/brand.d.ts +8 -0
  80. package/dist/review/brand.js +25 -0
  81. package/dist/review/call-context.d.ts +27 -0
  82. package/dist/review/call-context.js +446 -0
  83. package/dist/review/call-flow-html.d.ts +32 -0
  84. package/dist/review/call-flow-html.js +1870 -0
  85. package/dist/review/call-flow-nav.d.ts +151 -0
  86. package/dist/review/call-flow-nav.js +317 -0
  87. package/dist/review/call-flow.d.ts +47 -0
  88. package/dist/review/call-flow.js +229 -0
  89. package/dist/review/change-facts.d.ts +69 -0
  90. package/dist/review/change-facts.js +729 -0
  91. package/dist/review/cli.d.ts +2 -0
  92. package/dist/review/cli.js +50 -0
  93. package/dist/review/connected-analysis.d.ts +100 -0
  94. package/dist/review/connected-analysis.js +163 -0
  95. package/dist/review/connected-html.d.ts +17 -0
  96. package/dist/review/connected-html.js +2853 -0
  97. package/dist/review/connected.d.ts +23 -0
  98. package/dist/review/connected.js +141 -0
  99. package/dist/review/escape-html.d.ts +2 -0
  100. package/dist/review/escape-html.js +9 -0
  101. package/dist/review/evidence-html.d.ts +21 -0
  102. package/dist/review/evidence-html.js +521 -0
  103. package/dist/review/evidence-syntax.d.ts +132 -0
  104. package/dist/review/evidence-syntax.js +478 -0
  105. package/dist/review/evidence-types.d.ts +62 -0
  106. package/dist/review/evidence-types.js +1 -0
  107. package/dist/review/evidence.d.ts +31 -0
  108. package/dist/review/evidence.js +1603 -0
  109. package/dist/review/file-role.d.ts +9 -0
  110. package/dist/review/file-role.js +29 -0
  111. package/dist/review/github.d.ts +204 -0
  112. package/dist/review/github.js +1245 -0
  113. package/dist/review/history.d.ts +101 -0
  114. package/dist/review/history.js +412 -0
  115. package/dist/review/html.d.ts +34 -0
  116. package/dist/review/html.js +1104 -0
  117. package/dist/review/input.d.ts +10 -0
  118. package/dist/review/input.js +113 -0
  119. package/dist/review/intent.d.ts +4 -0
  120. package/dist/review/intent.js +75 -0
  121. package/dist/review/mcp-cli.d.ts +2 -0
  122. package/dist/review/mcp-cli.js +25 -0
  123. package/dist/review/mcp.d.ts +12 -0
  124. package/dist/review/mcp.js +414 -0
  125. package/dist/review/module-resolution.d.ts +2 -0
  126. package/dist/review/module-resolution.js +86 -0
  127. package/dist/review/palette.d.ts +7 -0
  128. package/dist/review/palette.js +104 -0
  129. package/dist/review/pipeline.d.ts +77 -0
  130. package/dist/review/pipeline.js +227 -0
  131. package/dist/review/pr-input.d.ts +19 -0
  132. package/dist/review/pr-input.js +130 -0
  133. package/dist/review/questions.d.ts +201 -0
  134. package/dist/review/questions.js +174 -0
  135. package/dist/review/reference-check.d.ts +7 -0
  136. package/dist/review/reference-check.js +733 -0
  137. package/dist/review/report-pages.d.ts +109 -0
  138. package/dist/review/report-pages.js +328 -0
  139. package/dist/review/service.d.ts +23 -0
  140. package/dist/review/service.js +198 -0
  141. package/dist/review/setup.d.ts +112 -0
  142. package/dist/review/setup.js +549 -0
  143. package/dist/review/source.d.ts +26 -0
  144. package/dist/review/source.js +276 -0
  145. package/dist/review/toml.d.ts +38 -0
  146. package/dist/review/toml.js +565 -0
  147. package/dist/review/types.d.ts +179 -0
  148. package/dist/review/types.js +1 -0
  149. package/dist/run.d.ts +49 -0
  150. package/dist/run.js +311 -0
  151. package/dist/types.d.ts +366 -0
  152. package/dist/types.js +83 -0
  153. package/package.json +88 -0
  154. package/scripts/ensure-native-grammar.mjs +188 -0
@@ -0,0 +1,366 @@
1
+ export type CallNodeKind = "call" | "branch";
2
+ /** Longest argument expression kept verbatim; longer text is cut and flagged. */
3
+ export declare const MAX_ARGUMENT_CHARS = 120;
4
+ /** Most arguments read from one call; the rest are flagged, not guessed. */
5
+ export declare const MAX_CALL_ARGUMENTS = 8;
6
+ /**
7
+ * `lexical` — an unambiguous same-file declaration with matching AST provenance;
8
+ * `candidate` — a name/member heuristic that may reach a definition, so argument
9
+ * binding is never assumed; `unresolved` — dynamic or not found in the index.
10
+ */
11
+ export type CallTargetKind = "lexical" | "candidate" | "unresolved";
12
+ /**
13
+ * How call arguments line up with the callee's declared parameters:
14
+ * `positional` — arguments bind to parameter slots in order; `named` — the call
15
+ * supplies at least one keyword argument, bound by name; `partial` — some
16
+ * argument could not be bound reliably (spread, destructuring, rest, extras);
17
+ * `unknown` — no reliable association (unindexed or dynamic target).
18
+ */
19
+ export type CallArgumentMapping = "positional" | "named" | "partial" | "unknown";
20
+ /**
21
+ * Honesty of an extracted call context. This describes what the extractor
22
+ * knows, not whether the call is valid:
23
+ * `complete` — arguments were read and every one binds to a declared parameter;
24
+ * `partial` — arguments were read, but a binding, parameter list, or the
25
+ * argument list itself is incomplete; `unavailable` — the call site has no
26
+ * readable argument list at all (`arguments` is then absent).
27
+ */
28
+ export type CallContextCompleteness = "complete" | "partial" | "unavailable";
29
+ /** One argument as written at the call site, with its binding when reliable. */
30
+ export interface CallArgument {
31
+ /** 1-based order in the call's argument list. */
32
+ position: number;
33
+ /**
34
+ * Argument source text, byte-for-byte as written (whitespace, quotes and
35
+ * escapes preserved), at most {@link MAX_ARGUMENT_CHARS} characters. Keyword
36
+ * arguments keep their `param=` spelling.
37
+ */
38
+ expression: string;
39
+ /** Declared parameter this argument binds to, when the binding is reliable. */
40
+ parameter?: string;
41
+ /** `expression` was cut to {@link MAX_ARGUMENT_CHARS}; see `originalLength`. */
42
+ truncated?: boolean;
43
+ /** Length of the full expression before truncation. */
44
+ originalLength?: number;
45
+ }
46
+ /** Everything extracted about one call site, alongside its definition. */
47
+ export interface CallContext {
48
+ /**
49
+ * Source text of the target expression. Cut at {@link MAX_ARGUMENT_CHARS}
50
+ * when longer, which `expression-truncated` reports.
51
+ */
52
+ callee: string;
53
+ /** How `callee` was associated with a definition. */
54
+ target: CallTargetKind;
55
+ /** Verbatim declared parameter list of the callee, when one is known. */
56
+ parameters?: string;
57
+ /** How `arguments` line up with `parameters`. */
58
+ mapping: CallArgumentMapping;
59
+ /**
60
+ * Arguments in call order. Absent when the call site has no readable argument
61
+ * list; `[]` means the call was written with an empty one.
62
+ */
63
+ arguments?: CallArgument[];
64
+ /** Written argument entries omitted by the eight-argument extraction limit. */
65
+ omittedArguments?: number;
66
+ completeness: CallContextCompleteness;
67
+ /** Factual, stable identifiers for every limit; see {@link CALL_REASONS}. */
68
+ reasons: string[];
69
+ /** Callee-body steps not expanded below this node (depth cut, recursion). */
70
+ omittedChildren?: number;
71
+ /** Calls dropped inside this call's own arguments at the depth cut. */
72
+ omittedInlineChildren?: number;
73
+ }
74
+ /**
75
+ * Stable identifiers for `CallContext.reasons`. They are facts about the
76
+ * extraction (`spread-argument`), never judgments about the change.
77
+ */
78
+ export declare const CALL_REASONS: {
79
+ /** Target is not a plain name or member chain (`arg[0]()`, `callee()()`). */
80
+ readonly dynamicCallee: "dynamic-callee";
81
+ /** A parameter of the enclosing function shadows the target name. */
82
+ readonly parameterShadow: "parameter-shadow";
83
+ /** A local variable of an enclosing scope shadows the target name. */
84
+ readonly localShadow: "local-shadow";
85
+ /** Nothing in the index defines the target name. */
86
+ readonly targetNotIndexed: "target-not-indexed";
87
+ /** Several definitions share the target name, none local to the call. */
88
+ readonly targetAmbiguous: "target-ambiguous";
89
+ /** The call site has no argument list, or it could not be read. */
90
+ readonly argumentsUnavailable: "arguments-unavailable";
91
+ /** More than {@link MAX_CALL_ARGUMENTS} arguments; the rest were not read. */
92
+ readonly argumentsTruncated: "arguments-truncated";
93
+ /** An argument or target expression was cut to {@link MAX_ARGUMENT_CHARS}. */
94
+ readonly expressionTruncated: "expression-truncated";
95
+ /** A spread/star argument makes positions after it unreliable. */
96
+ readonly spreadArgument: "spread-argument";
97
+ /** A destructuring pattern argument or parameter cannot be named. */
98
+ readonly destructuredBinding: "destructured-binding";
99
+ /** A keyword argument binds to a declared parameter. */
100
+ readonly keywordBinding: "keyword-binding";
101
+ /** An argument binds through a rest (`...param`, `*param`, `**param`). */
102
+ readonly restBinding: "rest-binding";
103
+ /** More arguments than declared parameters; the extras bind to nothing. */
104
+ readonly extraArguments: "extra-arguments";
105
+ /** More than one argument tries to bind the same declared slot. */
106
+ readonly duplicateBinding: "duplicate-argument-binding";
107
+ /** Argument-to-parameter binding was not derived for this call. */
108
+ readonly bindingUnavailable: "binding-unavailable";
109
+ };
110
+ /** One declared parameter slot, in source order. */
111
+ export type ParamSlot = {
112
+ /** Positional or keyword-only parameter with a bindable name. */
113
+ form: "positional" | "keyword";
114
+ name: string;
115
+ hasDefault: boolean;
116
+ /** Python parameters before `/` cannot be bound by keyword. */
117
+ positionalOnly?: boolean;
118
+ }
119
+ /** Rest parameters take an unbounded run of arguments. */
120
+ | {
121
+ form: "rest" | "keyword-rest";
122
+ name: string | null;
123
+ }
124
+ /** Destructuring pattern with no single bindable name. */
125
+ | {
126
+ form: "pattern";
127
+ hasDefault: boolean;
128
+ };
129
+ /** Declared parameter list of one definition, read from its AST node. */
130
+ export interface DeclaredParams {
131
+ /** Verbatim declared list including parentheses, e.g. `(param1, param2 = 1)`. */
132
+ text: string;
133
+ /**
134
+ * Bindable slots in source order, when the extractor read them from the AST.
135
+ * `[]` is a parameter list that really declares nothing. Absent means only
136
+ * `text` was read, which leaves argument binding `unknown` rather than
137
+ * guessed.
138
+ */
139
+ slots?: ParamSlot[];
140
+ /** Parameter AST offsets; disambiguate the declaration without parsing labels. */
141
+ start?: number;
142
+ end?: number;
143
+ }
144
+ /** How one written argument participates in binding. */
145
+ export type ArgumentRole = "positional" | "keyword" | "star" | "star-star";
146
+ /** One argument captured from the AST, before a definition is known. */
147
+ export interface CallArgumentSyntax {
148
+ position: number;
149
+ role: ArgumentRole;
150
+ /** Keyword name for `param=arg` arguments. */
151
+ keyword?: string;
152
+ expression: string;
153
+ truncated?: boolean;
154
+ originalLength?: number;
155
+ }
156
+ /**
157
+ * AST-side material for one call site: the target expression, its lexical
158
+ * association, and the arguments as written. The public contract is
159
+ * {@link CallContext}, which `calltree.ts` derives from this once the callee's
160
+ * definition is known.
161
+ */
162
+ export interface CallSyntax {
163
+ /** Verbatim target expression text. */
164
+ callee: string;
165
+ target: CallTargetKind;
166
+ /** Declared parameters of a lexically bound target. */
167
+ params?: DeclaredParams;
168
+ /** Absent when the call site has no readable argument list. */
169
+ arguments?: CallArgumentSyntax[];
170
+ /** Written argument entries omitted by the extraction limit. */
171
+ omittedArguments?: number;
172
+ /** Extraction-side reasons; see {@link CALL_REASONS}. */
173
+ reasons: string[];
174
+ }
175
+ /** Source location as shown in editors: `file:line` or `file:line-line`. */
176
+ export interface SourceLoc {
177
+ file: string;
178
+ /** 1-based start line */
179
+ line: number;
180
+ /** 1-based end line when the span covers multiple lines */
181
+ endLine?: number;
182
+ }
183
+ export interface CallNode {
184
+ /** Stable identity used for matching across versions, e.g. "PiService.createAgentSession" */
185
+ key: string;
186
+ /** Display label, e.g. "PiService.createAgentSession" or "if (!options.sessionId)" */
187
+ label: string;
188
+ /** Branches omit the continuing │ rail so arms read as alternate paths */
189
+ kind?: CallNodeKind;
190
+ /**
191
+ * Root: definition location. Children: call-site (or branch keyword) in the parent.
192
+ * Matching/diff keys ignore these fields.
193
+ */
194
+ file?: string;
195
+ line?: number;
196
+ endLine?: number;
197
+ /**
198
+ * Definition this call resolved to, which for a child is a different place
199
+ * than the call site in `file`/`line`. Absent when the callee has no indexed
200
+ * definition (dynamic calls, libraries, unsupported files).
201
+ */
202
+ definition?: SourceLoc;
203
+ /** Target expression, declared parameters, and arguments as written. */
204
+ context?: CallContext;
205
+ children: CallNode[];
206
+ }
207
+ /** One step in a function body: a call, or a conditional branch with nested steps. */
208
+ export type CallStep = {
209
+ type: "call";
210
+ key: string;
211
+ /** Call-expression span in the caller file. */
212
+ file?: string;
213
+ line?: number;
214
+ endLine?: number;
215
+ /** Inline children (e.g. JSX component children at the call site). */
216
+ children?: CallStep[];
217
+ /** AST-side call material; `calltree.ts` turns it into `CallContext`. */
218
+ syntax?: CallSyntax;
219
+ } | {
220
+ type: "branch";
221
+ key: string;
222
+ label: string;
223
+ /** Branch keyword / condition span. */
224
+ file?: string;
225
+ line?: number;
226
+ endLine?: number;
227
+ children: CallStep[];
228
+ };
229
+ export type DiffStatus = "same" | "added" | "removed";
230
+ export interface DiffNode {
231
+ key: string;
232
+ label: string;
233
+ status: DiffStatus;
234
+ kind?: CallNodeKind;
235
+ file?: string;
236
+ line?: number;
237
+ endLine?: number;
238
+ /**
239
+ * Definition the call resolved to, taken from the `after` snapshot, or from
240
+ * `before` for a `removed` node. Call sites keep `file`/`line`.
241
+ */
242
+ definition?: SourceLoc;
243
+ children: DiffNode[];
244
+ }
245
+ export interface FunctionInfo {
246
+ /** Review-only syntax evidence; declarations here are never callable targets. */
247
+ review?: {
248
+ kind?: "interface" | "type" | "enum";
249
+ references?: {
250
+ name: string;
251
+ module?: string;
252
+ imported?: string;
253
+ }[];
254
+ dispatches?: {
255
+ kind: "event" | "queue";
256
+ direction: "emit" | "handle";
257
+ key: string;
258
+ channel?: string;
259
+ line: number;
260
+ evidence: string;
261
+ }[];
262
+ };
263
+ /** Stable key: "foo" or "ClassName.method" or "ClassName.constructor" */
264
+ key: string;
265
+ label: string;
266
+ file: string;
267
+ /** Ordered body steps (calls + if/else branches) */
268
+ steps: CallStep[];
269
+ exported: boolean;
270
+ /**
271
+ * Declared inside another function body (a helper or closure) rather than at
272
+ * file top level. Locals only answer calls made from their own file, so a
273
+ * helper never shadows a top-level definition elsewhere in the repo.
274
+ */
275
+ local?: boolean;
276
+ /** Source span for change detection */
277
+ start: number;
278
+ end: number;
279
+ /** 1-based definition line (derived from start/end + source) */
280
+ line?: number;
281
+ endLine?: number;
282
+ /**
283
+ * Declared parameter list read from the definition's AST node. Present when
284
+ * the extractor could read one; `slots` drives argument binding, `text` is
285
+ * shown verbatim.
286
+ */
287
+ params?: DeclaredParams;
288
+ }
289
+ export interface Snapshot {
290
+ kind: "commit" | "worktree";
291
+ /** Commit-ish, or "WORKTREE" */
292
+ ref: string;
293
+ }
294
+ export interface SnapshotPair {
295
+ from: Snapshot;
296
+ to: Snapshot;
297
+ }
298
+ export interface SnapshotPairWithPaths extends SnapshotPair {
299
+ paths: string[];
300
+ }
301
+ export interface SnapshotWithPaths {
302
+ snapshot: Snapshot;
303
+ paths: string[];
304
+ }
305
+ /** Copy optional location / kind fields onto a tree node without empty spreads. */
306
+ export declare function assignOptionalTreeFields<T extends {
307
+ kind?: CallNodeKind;
308
+ file?: string;
309
+ line?: number;
310
+ endLine?: number;
311
+ definition?: SourceLoc;
312
+ context?: CallContext;
313
+ }>(target: T, source: {
314
+ kind?: CallNodeKind;
315
+ file?: string;
316
+ line?: number;
317
+ endLine?: number;
318
+ definition?: SourceLoc;
319
+ context?: CallContext;
320
+ }): T;
321
+ /** Deep enough copy that a serialized node never aliases engine state. */
322
+ export declare function copyCallContext(context: CallContext): CallContext;
323
+ export type CliMode = "diff" | "tree" | "reach";
324
+ export interface DiffTreeResult {
325
+ entry: string;
326
+ /** Colorless ASCII rendering of this entry's diff tree. */
327
+ ascii: string;
328
+ tree: DiffNode;
329
+ }
330
+ export interface DiffResult {
331
+ mode: "diff";
332
+ from: string;
333
+ to: string;
334
+ message?: string;
335
+ trees: DiffTreeResult[];
336
+ /** Full human-oriented ASCII output (may include ANSI colors). */
337
+ ascii: string;
338
+ }
339
+ export interface TreeEntryResult {
340
+ entry: string;
341
+ /** Colorless ASCII rendering of this entry's call tree. */
342
+ ascii: string;
343
+ tree: CallNode;
344
+ }
345
+ export interface TreeResult {
346
+ mode: "tree";
347
+ ref: string;
348
+ trees: TreeEntryResult[];
349
+ /** Full human-oriented ASCII output (may include ANSI colors). */
350
+ ascii: string;
351
+ }
352
+ export interface ReachPathResult {
353
+ /** Colorless ASCII rendering of this path. */
354
+ ascii: string;
355
+ tree: CallNode;
356
+ }
357
+ export interface ReachResult {
358
+ mode: "reach";
359
+ ref: string;
360
+ from: string;
361
+ to: string;
362
+ message?: string;
363
+ paths: ReachPathResult[];
364
+ /** Full human-oriented ASCII output (may include ANSI colors). */
365
+ ascii: string;
366
+ }
package/dist/types.js ADDED
@@ -0,0 +1,83 @@
1
+ /** Longest argument expression kept verbatim; longer text is cut and flagged. */
2
+ export const MAX_ARGUMENT_CHARS = 120;
3
+ /** Most arguments read from one call; the rest are flagged, not guessed. */
4
+ export const MAX_CALL_ARGUMENTS = 8;
5
+ /**
6
+ * Stable identifiers for `CallContext.reasons`. They are facts about the
7
+ * extraction (`spread-argument`), never judgments about the change.
8
+ */
9
+ export const CALL_REASONS = {
10
+ /** Target is not a plain name or member chain (`arg[0]()`, `callee()()`). */
11
+ dynamicCallee: "dynamic-callee",
12
+ /** A parameter of the enclosing function shadows the target name. */
13
+ parameterShadow: "parameter-shadow",
14
+ /** A local variable of an enclosing scope shadows the target name. */
15
+ localShadow: "local-shadow",
16
+ /** Nothing in the index defines the target name. */
17
+ targetNotIndexed: "target-not-indexed",
18
+ /** Several definitions share the target name, none local to the call. */
19
+ targetAmbiguous: "target-ambiguous",
20
+ /** The call site has no argument list, or it could not be read. */
21
+ argumentsUnavailable: "arguments-unavailable",
22
+ /** More than {@link MAX_CALL_ARGUMENTS} arguments; the rest were not read. */
23
+ argumentsTruncated: "arguments-truncated",
24
+ /** An argument or target expression was cut to {@link MAX_ARGUMENT_CHARS}. */
25
+ expressionTruncated: "expression-truncated",
26
+ /** A spread/star argument makes positions after it unreliable. */
27
+ spreadArgument: "spread-argument",
28
+ /** A destructuring pattern argument or parameter cannot be named. */
29
+ destructuredBinding: "destructured-binding",
30
+ /** A keyword argument binds to a declared parameter. */
31
+ keywordBinding: "keyword-binding",
32
+ /** An argument binds through a rest (`...param`, `*param`, `**param`). */
33
+ restBinding: "rest-binding",
34
+ /** More arguments than declared parameters; the extras bind to nothing. */
35
+ extraArguments: "extra-arguments",
36
+ /** More than one argument tries to bind the same declared slot. */
37
+ duplicateBinding: "duplicate-argument-binding",
38
+ /** Argument-to-parameter binding was not derived for this call. */
39
+ bindingUnavailable: "binding-unavailable",
40
+ };
41
+ /** Copy optional location / kind fields onto a tree node without empty spreads. */
42
+ export function assignOptionalTreeFields(target, source) {
43
+ if (source.kind)
44
+ target.kind = source.kind;
45
+ if (source.file)
46
+ target.file = source.file;
47
+ if (source.line != null)
48
+ target.line = source.line;
49
+ if (source.endLine != null)
50
+ target.endLine = source.endLine;
51
+ // Copied, not aliased: a serialized tree must not share mutable state with
52
+ // the engine tree it came from.
53
+ if (source.definition)
54
+ target.definition = { ...source.definition };
55
+ if (source.context)
56
+ target.context = copyCallContext(source.context);
57
+ return target;
58
+ }
59
+ /** Deep enough copy that a serialized node never aliases engine state. */
60
+ export function copyCallContext(context) {
61
+ const copy = {
62
+ callee: context.callee,
63
+ target: context.target,
64
+ mapping: context.mapping,
65
+ completeness: context.completeness,
66
+ reasons: [...context.reasons],
67
+ };
68
+ if (context.parameters !== undefined)
69
+ copy.parameters = context.parameters;
70
+ if (context.arguments !== undefined) {
71
+ copy.arguments = context.arguments.map((argument) => ({ ...argument }));
72
+ }
73
+ if (context.omittedArguments !== undefined) {
74
+ copy.omittedArguments = context.omittedArguments;
75
+ }
76
+ if (context.omittedChildren !== undefined) {
77
+ copy.omittedChildren = context.omittedChildren;
78
+ }
79
+ if (context.omittedInlineChildren !== undefined) {
80
+ copy.omittedInlineChildren = context.omittedInlineChildren;
81
+ }
82
+ return copy;
83
+ }
package/package.json ADDED
@@ -0,0 +1,88 @@
1
+ {
2
+ "name": "diffninja",
3
+ "version": "0.1.0",
4
+ "description": "Local, deterministic PR review for coding agents over MCP: call flows, change facts, and a human review workspace",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js"
10
+ }
11
+ },
12
+ "bin": {
13
+ "diffninja": "dist/review/cli.js",
14
+ "diffninja-mcp": "dist/review/mcp-cli.js"
15
+ },
16
+ "files": [
17
+ "dist/**/*.js",
18
+ "dist/**/*.d.ts",
19
+ "scripts/ensure-native-grammar.mjs"
20
+ ],
21
+ "scripts": {
22
+ "clean": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('dist', { recursive: true, force: true });\"",
23
+ "build": "npm run clean && tsc",
24
+ "prepack": "npm run build",
25
+ "postinstall": "node scripts/ensure-native-grammar.mjs",
26
+ "rebuild:native": "node scripts/ensure-native-grammar.mjs",
27
+ "dev": "tsx src/review/mcp-cli.ts",
28
+ "start": "node dist/review/cli.js",
29
+ "lint": "oxlint",
30
+ "test": "vitest run"
31
+ },
32
+ "engines": {
33
+ "node": ">=22.18.0"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public",
37
+ "registry": "https://registry.npmjs.org/"
38
+ },
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "git+https://github.com/marcelormendes/diffninja.git"
42
+ },
43
+ "bugs": {
44
+ "url": "https://github.com/marcelormendes/diffninja/issues"
45
+ },
46
+ "homepage": "https://github.com/marcelormendes/diffninja#readme",
47
+ "keywords": [
48
+ "callgraph",
49
+ "diff",
50
+ "callstack",
51
+ "tree-sitter",
52
+ "git",
53
+ "multi-language",
54
+ "typescript",
55
+ "python",
56
+ "rust",
57
+ "go"
58
+ ],
59
+ "author": "marcelormendes",
60
+ "license": "MIT",
61
+ "dependencies": {
62
+ "@modelcontextprotocol/sdk": "^1.30.0",
63
+ "incur": "^0.4.26",
64
+ "picocolors": "^1.1.1",
65
+ "smol-toml": "^1.8.0",
66
+ "tree-sitter": "^0.25.1",
67
+ "tree-sitter-javascript": "^0.25.0",
68
+ "zod": "^4.6.5"
69
+ },
70
+ "optionalDependencies": {
71
+ "tree-sitter-typescript": "^0.23.2"
72
+ },
73
+ "overrides": {
74
+ "tree-sitter-typescript": {
75
+ "tree-sitter": "$tree-sitter",
76
+ "tree-sitter-javascript": "0.25.0"
77
+ }
78
+ },
79
+ "devDependencies": {
80
+ "@oxlint/plugins": "^1.79.0",
81
+ "@types/node": "^24.2.0",
82
+ "outdent": "^0.8.0",
83
+ "oxlint": "^1.79.0",
84
+ "tsx": "^4.20.3",
85
+ "typescript": "^5.9.2",
86
+ "vitest": "^4.1.10"
87
+ }
88
+ }