@praneeth_54/agentdoctor 0.3.0-beta → 1.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 (267) hide show
  1. package/CHANGELOG.md +105 -1
  2. package/README.md +64 -31
  3. package/dist/agents/inspect.js +58 -51
  4. package/dist/cli/commands/brain-mcp.d.ts +9 -0
  5. package/dist/cli/commands/brain-mcp.js +38 -0
  6. package/dist/cli/commands/explain.js +1 -1
  7. package/dist/cli/commands/fix.js +22 -6
  8. package/dist/cli/commands/scan.d.ts +5 -0
  9. package/dist/cli/commands/scan.js +25 -6
  10. package/dist/cli/commands/verify.d.ts +6 -0
  11. package/dist/cli/commands/verify.js +25 -11
  12. package/dist/cli/program.js +61 -7
  13. package/dist/constants.d.ts +1 -1
  14. package/dist/constants.js +1 -1
  15. package/dist/core/fix/apply.d.ts +5 -1
  16. package/dist/core/fix/apply.js +34 -14
  17. package/dist/core/fix/plan.d.ts +1 -1
  18. package/dist/core/fix/plan.js +110 -3
  19. package/dist/core/fix/render.d.ts +2 -0
  20. package/dist/core/fix/render.js +57 -9
  21. package/dist/core/fix/run.js +5 -1
  22. package/dist/core/fix/types.d.ts +1 -1
  23. package/dist/core/fix/types.js +5 -1
  24. package/dist/core/fix/writers/claude-settings.d.ts +16 -0
  25. package/dist/core/fix/writers/claude-settings.js +100 -0
  26. package/dist/core/fix/writers/codex-config.d.ts +22 -0
  27. package/dist/core/fix/writers/codex-config.js +183 -0
  28. package/dist/core/fix/writers/cursorignore.js +2 -8
  29. package/dist/core/path-resolution/index.d.ts +5 -0
  30. package/dist/core/path-resolution/index.js +5 -0
  31. package/dist/core/path-resolution/prepare.d.ts +33 -0
  32. package/dist/core/path-resolution/prepare.js +98 -0
  33. package/dist/core/policy/evaluate.d.ts +44 -0
  34. package/dist/core/policy/evaluate.js +120 -0
  35. package/dist/core/rules/claude-deny.d.ts +8 -0
  36. package/dist/core/rules/claude-deny.js +39 -0
  37. package/dist/core/rules/codex-deny.d.ts +5 -0
  38. package/dist/core/rules/codex-deny.js +42 -0
  39. package/dist/core/rules/context/generated-directory.js +43 -9
  40. package/dist/core/rules/context/large-log-file.js +27 -10
  41. package/dist/core/rules/ignore.js +2 -5
  42. package/dist/core/rules/instructions/missing-path-reference.d.ts +5 -1
  43. package/dist/core/rules/instructions/missing-path-reference.js +24 -6
  44. package/dist/core/rules/path-kind.d.ts +15 -2
  45. package/dist/core/rules/path-kind.js +113 -10
  46. package/dist/core/rules/security/env-file-exposure.js +9 -24
  47. package/dist/core/rules/text-cache.js +46 -40
  48. package/dist/core/understanding/architecture/index.d.ts +4 -0
  49. package/dist/core/understanding/architecture/index.js +3 -0
  50. package/dist/core/understanding/architecture/infer.d.ts +6 -0
  51. package/dist/core/understanding/architecture/infer.js +39 -0
  52. package/dist/core/understanding/architecture/models.d.ts +23 -0
  53. package/dist/core/understanding/architecture/models.js +127 -0
  54. package/dist/core/understanding/architecture/patterns/distribution.d.ts +2 -0
  55. package/dist/core/understanding/architecture/patterns/distribution.js +115 -0
  56. package/dist/core/understanding/architecture/patterns/index.d.ts +2 -0
  57. package/dist/core/understanding/architecture/patterns/index.js +8 -0
  58. package/dist/core/understanding/architecture/patterns/layered.d.ts +2 -0
  59. package/dist/core/understanding/architecture/patterns/layered.js +279 -0
  60. package/dist/core/understanding/architecture/patterns/structural.d.ts +2 -0
  61. package/dist/core/understanding/architecture/patterns/structural.js +197 -0
  62. package/dist/core/understanding/architecture/rules.d.ts +4 -0
  63. package/dist/core/understanding/architecture/rules.js +6 -0
  64. package/dist/core/understanding/architecture/types.d.ts +52 -0
  65. package/dist/core/understanding/architecture/types.js +1 -0
  66. package/dist/core/understanding/brain/build.d.ts +13 -0
  67. package/dist/core/understanding/brain/build.js +158 -0
  68. package/dist/core/understanding/brain/claims/index.d.ts +3 -0
  69. package/dist/core/understanding/brain/claims/index.js +2 -0
  70. package/dist/core/understanding/brain/claims/lifecycle.d.ts +16 -0
  71. package/dist/core/understanding/brain/claims/lifecycle.js +78 -0
  72. package/dist/core/understanding/brain/claims/types.d.ts +32 -0
  73. package/dist/core/understanding/brain/claims/types.js +25 -0
  74. package/dist/core/understanding/brain/components/index.d.ts +17 -0
  75. package/dist/core/understanding/brain/components/index.js +97 -0
  76. package/dist/core/understanding/brain/components/types.d.ts +16 -0
  77. package/dist/core/understanding/brain/components/types.js +8 -0
  78. package/dist/core/understanding/brain/confidence.d.ts +19 -0
  79. package/dist/core/understanding/brain/confidence.js +39 -0
  80. package/dist/core/understanding/brain/contract.d.ts +17 -0
  81. package/dist/core/understanding/brain/contract.js +100 -0
  82. package/dist/core/understanding/brain/contradictions/index.d.ts +12 -0
  83. package/dist/core/understanding/brain/contradictions/index.js +57 -0
  84. package/dist/core/understanding/brain/contradictions/types.d.ts +12 -0
  85. package/dist/core/understanding/brain/contradictions/types.js +8 -0
  86. package/dist/core/understanding/brain/delta.d.ts +25 -0
  87. package/dist/core/understanding/brain/delta.js +116 -0
  88. package/dist/core/understanding/brain/evidence/index.d.ts +3 -0
  89. package/dist/core/understanding/brain/evidence/index.js +2 -0
  90. package/dist/core/understanding/brain/evidence/redact.d.ts +4 -0
  91. package/dist/core/understanding/brain/evidence/redact.js +36 -0
  92. package/dist/core/understanding/brain/evidence/types.d.ts +34 -0
  93. package/dist/core/understanding/brain/evidence/types.js +35 -0
  94. package/dist/core/understanding/brain/explain.d.ts +17 -0
  95. package/dist/core/understanding/brain/explain.js +33 -0
  96. package/dist/core/understanding/brain/index.d.ts +28 -0
  97. package/dist/core/understanding/brain/index.js +16 -0
  98. package/dist/core/understanding/brain/migrate.d.ts +21 -0
  99. package/dist/core/understanding/brain/migrate.js +47 -0
  100. package/dist/core/understanding/brain/query.d.ts +60 -0
  101. package/dist/core/understanding/brain/query.js +92 -0
  102. package/dist/core/understanding/brain/security.d.ts +3 -0
  103. package/dist/core/understanding/brain/security.js +43 -0
  104. package/dist/core/understanding/brain/storage/index.d.ts +2 -0
  105. package/dist/core/understanding/brain/storage/index.js +1 -0
  106. package/dist/core/understanding/brain/storage/store.d.ts +53 -0
  107. package/dist/core/understanding/brain/storage/store.js +305 -0
  108. package/dist/core/understanding/brain/trace.d.ts +24 -0
  109. package/dist/core/understanding/brain/trace.js +207 -0
  110. package/dist/core/understanding/brain/types.d.ts +32 -0
  111. package/dist/core/understanding/brain/types.js +8 -0
  112. package/dist/core/understanding/brain/version.d.ts +13 -0
  113. package/dist/core/understanding/brain/version.js +7 -0
  114. package/dist/core/understanding/delta/compare.d.ts +26 -0
  115. package/dist/core/understanding/delta/compare.js +74 -0
  116. package/dist/core/understanding/delta/index.d.ts +2 -0
  117. package/dist/core/understanding/delta/index.js +1 -0
  118. package/dist/core/understanding/dependencies/discover.d.ts +7 -0
  119. package/dist/core/understanding/dependencies/discover.js +550 -0
  120. package/dist/core/understanding/dependencies/extract.d.ts +10 -0
  121. package/dist/core/understanding/dependencies/extract.js +189 -0
  122. package/dist/core/understanding/dependencies/index.d.ts +4 -0
  123. package/dist/core/understanding/dependencies/index.js +3 -0
  124. package/dist/core/understanding/dependencies/models.d.ts +12 -0
  125. package/dist/core/understanding/dependencies/models.js +125 -0
  126. package/dist/core/understanding/dependencies/types.d.ts +27 -0
  127. package/dist/core/understanding/dependencies/types.js +1 -0
  128. package/dist/core/understanding/domain/discover.d.ts +14 -0
  129. package/dist/core/understanding/domain/discover.js +90 -0
  130. package/dist/core/understanding/domain/index.d.ts +2 -0
  131. package/dist/core/understanding/domain/index.js +1 -0
  132. package/dist/core/understanding/entrypoints/discover.d.ts +6 -0
  133. package/dist/core/understanding/entrypoints/discover.js +62 -0
  134. package/dist/core/understanding/entrypoints/extract.d.ts +19 -0
  135. package/dist/core/understanding/entrypoints/extract.js +43 -0
  136. package/dist/core/understanding/entrypoints/index.d.ts +4 -0
  137. package/dist/core/understanding/entrypoints/index.js +3 -0
  138. package/dist/core/understanding/entrypoints/models.d.ts +26 -0
  139. package/dist/core/understanding/entrypoints/models.js +216 -0
  140. package/dist/core/understanding/entrypoints/types.d.ts +20 -0
  141. package/dist/core/understanding/entrypoints/types.js +1 -0
  142. package/dist/core/understanding/index.d.ts +32 -0
  143. package/dist/core/understanding/index.js +18 -0
  144. package/dist/core/understanding/mind/build.d.ts +16 -0
  145. package/dist/core/understanding/mind/build.js +134 -0
  146. package/dist/core/understanding/mind/index.d.ts +6 -0
  147. package/dist/core/understanding/mind/index.js +3 -0
  148. package/dist/core/understanding/mind/query.d.ts +33 -0
  149. package/dist/core/understanding/mind/query.js +39 -0
  150. package/dist/core/understanding/mind/types.d.ts +24 -0
  151. package/dist/core/understanding/mind/types.js +7 -0
  152. package/dist/core/understanding/model/builder.d.ts +9 -0
  153. package/dist/core/understanding/model/builder.js +209 -0
  154. package/dist/core/understanding/model/ids.d.ts +7 -0
  155. package/dist/core/understanding/model/ids.js +48 -0
  156. package/dist/core/understanding/model/index.d.ts +7 -0
  157. package/dist/core/understanding/model/index.js +6 -0
  158. package/dist/core/understanding/model/schema.d.ts +12 -0
  159. package/dist/core/understanding/model/schema.js +33 -0
  160. package/dist/core/understanding/model/serializer.d.ts +9 -0
  161. package/dist/core/understanding/model/serializer.js +46 -0
  162. package/dist/core/understanding/model/types.d.ts +110 -0
  163. package/dist/core/understanding/model/types.js +1 -0
  164. package/dist/core/understanding/model/validator.d.ts +5 -0
  165. package/dist/core/understanding/model/validator.js +126 -0
  166. package/dist/core/understanding/model/version.d.ts +9 -0
  167. package/dist/core/understanding/model/version.js +7 -0
  168. package/dist/core/understanding/ownership/discover.d.ts +12 -0
  169. package/dist/core/understanding/ownership/discover.js +242 -0
  170. package/dist/core/understanding/ownership/index.d.ts +2 -0
  171. package/dist/core/understanding/ownership/index.js +1 -0
  172. package/dist/core/understanding/ownership/types.d.ts +23 -0
  173. package/dist/core/understanding/ownership/types.js +1 -0
  174. package/dist/core/understanding/query/engine.d.ts +24 -0
  175. package/dist/core/understanding/query/engine.js +35 -0
  176. package/dist/core/understanding/query/errors.d.ts +13 -0
  177. package/dist/core/understanding/query/errors.js +26 -0
  178. package/dist/core/understanding/query/executor.d.ts +8 -0
  179. package/dist/core/understanding/query/executor.js +34 -0
  180. package/dist/core/understanding/query/index.d.ts +7 -0
  181. package/dist/core/understanding/query/index.js +5 -0
  182. package/dist/core/understanding/query/models.d.ts +102 -0
  183. package/dist/core/understanding/query/models.js +1 -0
  184. package/dist/core/understanding/query/query.d.ts +68 -0
  185. package/dist/core/understanding/query/query.js +145 -0
  186. package/dist/core/understanding/query/registry.d.ts +8 -0
  187. package/dist/core/understanding/query/registry.js +340 -0
  188. package/dist/core/understanding/query/types.d.ts +63 -0
  189. package/dist/core/understanding/query/types.js +1 -0
  190. package/dist/core/understanding/relationships/discover.d.ts +11 -0
  191. package/dist/core/understanding/relationships/discover.js +517 -0
  192. package/dist/core/understanding/relationships/extract.d.ts +14 -0
  193. package/dist/core/understanding/relationships/extract.js +165 -0
  194. package/dist/core/understanding/relationships/index.d.ts +4 -0
  195. package/dist/core/understanding/relationships/index.js +3 -0
  196. package/dist/core/understanding/relationships/models.d.ts +21 -0
  197. package/dist/core/understanding/relationships/models.js +185 -0
  198. package/dist/core/understanding/relationships/types.d.ts +42 -0
  199. package/dist/core/understanding/relationships/types.js +1 -0
  200. package/dist/core/understanding/risks/discover.d.ts +8 -0
  201. package/dist/core/understanding/risks/discover.js +155 -0
  202. package/dist/core/understanding/risks/index.d.ts +2 -0
  203. package/dist/core/understanding/risks/index.js +1 -0
  204. package/dist/core/understanding/risks/types.d.ts +26 -0
  205. package/dist/core/understanding/risks/types.js +1 -0
  206. package/dist/core/understanding/shared/domain-lexicon.d.ts +9 -0
  207. package/dist/core/understanding/shared/domain-lexicon.js +107 -0
  208. package/dist/core/understanding/shared/index.d.ts +2 -0
  209. package/dist/core/understanding/shared/index.js +2 -0
  210. package/dist/core/understanding/shared/tokens.d.ts +7 -0
  211. package/dist/core/understanding/shared/tokens.js +141 -0
  212. package/dist/core/understanding/snapshot/identity.d.ts +24 -0
  213. package/dist/core/understanding/snapshot/identity.js +79 -0
  214. package/dist/core/understanding/snapshot/index.d.ts +2 -0
  215. package/dist/core/understanding/snapshot/index.js +1 -0
  216. package/dist/core/understanding/types/index.d.ts +22 -0
  217. package/dist/core/understanding/types/index.js +1 -0
  218. package/dist/core/understanding/understand/formatter.d.ts +10 -0
  219. package/dist/core/understanding/understand/formatter.js +115 -0
  220. package/dist/core/understanding/understand/index.d.ts +4 -0
  221. package/dist/core/understanding/understand/index.js +3 -0
  222. package/dist/core/understanding/understand/service.d.ts +17 -0
  223. package/dist/core/understanding/understand/service.js +76 -0
  224. package/dist/core/understanding/understand/summary.d.ts +14 -0
  225. package/dist/core/understanding/understand/summary.js +39 -0
  226. package/dist/core/understanding/understand/types.d.ts +31 -0
  227. package/dist/core/understanding/understand/types.js +1 -0
  228. package/dist/discovery/files.js +7 -2
  229. package/dist/discovery/log-like.d.ts +2 -0
  230. package/dist/discovery/log-like.js +7 -0
  231. package/dist/index.d.ts +2 -0
  232. package/dist/index.js +1 -0
  233. package/dist/mcp/brain/compile.d.ts +9 -0
  234. package/dist/mcp/brain/compile.js +42 -0
  235. package/dist/mcp/brain/errors.d.ts +12 -0
  236. package/dist/mcp/brain/errors.js +23 -0
  237. package/dist/mcp/brain/index.d.ts +11 -0
  238. package/dist/mcp/brain/index.js +8 -0
  239. package/dist/mcp/brain/provenance.d.ts +29 -0
  240. package/dist/mcp/brain/provenance.js +59 -0
  241. package/dist/mcp/brain/schemas.d.ts +13 -0
  242. package/dist/mcp/brain/schemas.js +105 -0
  243. package/dist/mcp/brain/security/root.d.ts +6 -0
  244. package/dist/mcp/brain/security/root.js +66 -0
  245. package/dist/mcp/brain/server.d.ts +12 -0
  246. package/dist/mcp/brain/server.js +46 -0
  247. package/dist/mcp/brain/session.d.ts +33 -0
  248. package/dist/mcp/brain/session.js +117 -0
  249. package/dist/mcp/brain/tools/handlers.d.ts +13 -0
  250. package/dist/mcp/brain/tools/handlers.js +483 -0
  251. package/dist/mcp/brain/tools/registry.d.ts +9 -0
  252. package/dist/mcp/brain/tools/registry.js +191 -0
  253. package/dist/reporters/github/annotations.d.ts +8 -0
  254. package/dist/reporters/github/annotations.js +42 -0
  255. package/dist/reporters/github/emit.d.ts +23 -0
  256. package/dist/reporters/github/emit.js +31 -0
  257. package/dist/reporters/github/summary.d.ts +20 -0
  258. package/dist/reporters/github/summary.js +111 -0
  259. package/dist/reporters/terminal/report.d.ts +5 -0
  260. package/dist/reporters/terminal/report.js +68 -5
  261. package/dist/reporters/verify/terminal.d.ts +4 -0
  262. package/dist/reporters/verify/terminal.js +26 -0
  263. package/dist/utils/fs.d.ts +5 -0
  264. package/dist/utils/fs.js +34 -0
  265. package/dist/utils/path.d.ts +5 -0
  266. package/dist/utils/path.js +16 -0
  267. package/package.json +15 -1
@@ -32,55 +32,61 @@ export class TextCache {
32
32
  return blocked;
33
33
  }
34
34
  try {
35
- const stat = await fs.stat(absolute);
36
- if (!stat.isFile()) {
37
- const result = {
38
- relativePath: toPosixRelative(this.root, absolute),
39
- text: null,
40
- sizeBytes: 0,
41
- empty: true,
42
- binary: false,
43
- error: "Not a regular file",
44
- };
45
- this.cache.set(relativePath, result);
46
- return result;
47
- }
48
- const sizeBytes = Number(stat.size);
49
- if (sizeBytes > this.maxBytes) {
35
+ const handle = await fs.open(absolute, "r");
36
+ try {
37
+ const stat = await handle.stat();
38
+ if (!stat.isFile()) {
39
+ const result = {
40
+ relativePath: toPosixRelative(this.root, absolute),
41
+ text: null,
42
+ sizeBytes: 0,
43
+ empty: true,
44
+ binary: false,
45
+ error: "Not a regular file",
46
+ };
47
+ this.cache.set(relativePath, result);
48
+ return result;
49
+ }
50
+ const sizeBytes = Number(stat.size);
51
+ if (sizeBytes > this.maxBytes) {
52
+ const result = {
53
+ relativePath,
54
+ text: null,
55
+ sizeBytes,
56
+ empty: false,
57
+ binary: false,
58
+ error: "File exceeds max read size",
59
+ };
60
+ this.cache.set(relativePath, result);
61
+ return result;
62
+ }
63
+ const buffer = await handle.readFile();
64
+ if (looksBinary(buffer)) {
65
+ const result = {
66
+ relativePath,
67
+ text: null,
68
+ sizeBytes,
69
+ empty: sizeBytes === 0,
70
+ binary: true,
71
+ error: "Binary file skipped",
72
+ };
73
+ this.cache.set(relativePath, result);
74
+ return result;
75
+ }
76
+ const text = buffer.toString("utf8");
50
77
  const result = {
51
78
  relativePath,
52
- text: null,
79
+ text,
53
80
  sizeBytes,
54
- empty: false,
81
+ empty: text.trim().length === 0,
55
82
  binary: false,
56
- error: "File exceeds max read size",
57
83
  };
58
84
  this.cache.set(relativePath, result);
59
85
  return result;
60
86
  }
61
- const buffer = await fs.readFile(absolute);
62
- if (looksBinary(buffer)) {
63
- const result = {
64
- relativePath,
65
- text: null,
66
- sizeBytes,
67
- empty: sizeBytes === 0,
68
- binary: true,
69
- error: "Binary file skipped",
70
- };
71
- this.cache.set(relativePath, result);
72
- return result;
87
+ finally {
88
+ await handle.close();
73
89
  }
74
- const text = buffer.toString("utf8");
75
- const result = {
76
- relativePath,
77
- text,
78
- sizeBytes,
79
- empty: text.trim().length === 0,
80
- binary: false,
81
- };
82
- this.cache.set(relativePath, result);
83
- return result;
84
90
  }
85
91
  catch (error) {
86
92
  const message = error instanceof Error ? error.message : "Unable to read file";
@@ -0,0 +1,4 @@
1
+ export { inferArchitectures } from "./infer.js";
2
+ export { ARCHITECTURE_RULES, listArchitecturePatterns } from "./rules.js";
3
+ export { scorePatternConfidence, clampConfidence } from "./models.js";
4
+ export type { ArchitectureInferenceInput, ArchitectureInferenceOptions, ArchitectureInferenceResult, ArchitectureMatch, ArchitecturePattern, PatternRuleResult, } from "./types.js";
@@ -0,0 +1,3 @@
1
+ export { inferArchitectures } from "./infer.js";
2
+ export { ARCHITECTURE_RULES, listArchitecturePatterns } from "./rules.js";
3
+ export { scorePatternConfidence, clampConfidence } from "./models.js";
@@ -0,0 +1,6 @@
1
+ import type { ArchitectureInferenceInput, ArchitectureInferenceOptions, ArchitectureInferenceResult } from "./types.js";
2
+ /**
3
+ * Infer architectural patterns from prior discovery outputs only.
4
+ * Does not scan the filesystem or repository.
5
+ */
6
+ export declare function inferArchitectures(input: ArchitectureInferenceInput, options?: ArchitectureInferenceOptions): ArchitectureInferenceResult;
@@ -0,0 +1,39 @@
1
+ import { finalizeMatch } from "./models.js";
2
+ import { ARCHITECTURE_RULES } from "./rules.js";
3
+ function assertInput(input) {
4
+ if (!input.domains || !input.entrypoints || !input.dependencies || !input.relationships) {
5
+ throw new Error("inferArchitectures requires domains, entrypoints, dependencies, and relationships inputs");
6
+ }
7
+ }
8
+ /**
9
+ * Infer architectural patterns from prior discovery outputs only.
10
+ * Does not scan the filesystem or repository.
11
+ */
12
+ export function inferArchitectures(input, options = {}) {
13
+ const started = performance.now();
14
+ assertInput(input);
15
+ const minConfidence = options.minConfidence ?? 0.55;
16
+ const architectures = [];
17
+ for (const definition of ARCHITECTURE_RULES) {
18
+ const evaluated = definition.evaluate({ input });
19
+ const match = finalizeMatch(definition.pattern, evaluated);
20
+ if (!match) {
21
+ continue;
22
+ }
23
+ if (match.confidence < minConfidence) {
24
+ continue;
25
+ }
26
+ architectures.push(match);
27
+ }
28
+ architectures.sort((a, b) => {
29
+ if (b.confidence !== a.confidence) {
30
+ return b.confidence - a.confidence;
31
+ }
32
+ return a.pattern.localeCompare(b.pattern);
33
+ });
34
+ return {
35
+ architectures,
36
+ timingMs: Math.round(performance.now() - started),
37
+ patternsEvaluated: ARCHITECTURE_RULES.length,
38
+ };
39
+ }
@@ -0,0 +1,23 @@
1
+ import type { DependencyMatch } from "../dependencies/types.js";
2
+ import type { EntrypointMatch } from "../entrypoints/types.js";
3
+ import type { RelationshipMatch } from "../relationships/types.js";
4
+ import type { ArchitectureInferenceInput, ArchitectureMatch, PatternRuleResult, RelationPredicate } from "./types.js";
5
+ export declare function clampConfidence(value: number): number;
6
+ export declare function scorePatternConfidence(options: {
7
+ supportScore: number;
8
+ conflictScore: number;
9
+ matchedRuleCount: number;
10
+ }): number;
11
+ export declare function findRelationships(input: ArchitectureInferenceInput, predicate: RelationPredicate): RelationshipMatch[];
12
+ export declare function hasRelationship(input: ArchitectureInferenceInput, predicate: RelationPredicate): boolean;
13
+ export declare function relationshipEvidenceLines(rels: RelationshipMatch[], limit?: number): string[];
14
+ export declare function findDependencies(input: ArchitectureInferenceInput, options?: {
15
+ type?: DependencyMatch["type"] | DependencyMatch["type"][];
16
+ evidenceIncludes?: string | string[];
17
+ }): DependencyMatch[];
18
+ export declare function findEntrypoints(input: ArchitectureInferenceInput, options?: {
19
+ framework?: EntrypointMatch["framework"] | EntrypointMatch["framework"][];
20
+ evidenceIncludes?: string | string[];
21
+ }): EntrypointMatch[];
22
+ export declare function emptyRuleResult(unknowns?: string[]): PatternRuleResult;
23
+ export declare function finalizeMatch(pattern: ArchitectureMatch["pattern"], result: PatternRuleResult): ArchitectureMatch | null;
@@ -0,0 +1,127 @@
1
+ export function clampConfidence(value) {
2
+ if (value < 0) {
3
+ return 0;
4
+ }
5
+ // Never claim certainty.
6
+ if (value > 0.95) {
7
+ return 0.95;
8
+ }
9
+ return Math.round(value * 100) / 100;
10
+ }
11
+ export function scorePatternConfidence(options) {
12
+ const { supportScore, conflictScore, matchedRuleCount } = options;
13
+ if (matchedRuleCount <= 0 || supportScore <= 0) {
14
+ return 0;
15
+ }
16
+ const raw = supportScore / (supportScore + conflictScore * 1.25 + 0.35);
17
+ const ruleBonus = Math.min(matchedRuleCount, 4) * 0.03;
18
+ return clampConfidence(raw + ruleBonus);
19
+ }
20
+ function asList(value) {
21
+ if (!value) {
22
+ return [];
23
+ }
24
+ return Array.isArray(value) ? value : [value];
25
+ }
26
+ function includesAny(haystack, needles) {
27
+ if (needles.length === 0) {
28
+ return true;
29
+ }
30
+ const lower = haystack.toLowerCase();
31
+ return needles.some((n) => lower.includes(n.toLowerCase()));
32
+ }
33
+ export function findRelationships(input, predicate) {
34
+ const kinds = asList(predicate.relationship);
35
+ const sources = asList(predicate.sourceIncludes);
36
+ const targets = asList(predicate.targetIncludes);
37
+ const evidenceNeedles = asList(predicate.evidenceIncludes);
38
+ return input.relationships.relationships.filter((rel) => {
39
+ if (kinds.length > 0 && !kinds.includes(rel.relationship)) {
40
+ return false;
41
+ }
42
+ if (sources.length > 0 && !includesAny(rel.source, sources)) {
43
+ return false;
44
+ }
45
+ if (targets.length > 0 && !includesAny(rel.target, targets)) {
46
+ return false;
47
+ }
48
+ if (evidenceNeedles.length > 0) {
49
+ const blob = `${rel.source} ${rel.target} ${rel.evidence.join(" ")}`;
50
+ if (!includesAny(blob, evidenceNeedles)) {
51
+ return false;
52
+ }
53
+ }
54
+ return true;
55
+ });
56
+ }
57
+ export function hasRelationship(input, predicate) {
58
+ return findRelationships(input, predicate).length > 0;
59
+ }
60
+ export function relationshipEvidenceLines(rels, limit = 3) {
61
+ return rels
62
+ .slice(0, limit)
63
+ .flatMap((r) => r.evidence.slice(0, 1).map((e) => `${r.source} ${r.relationship} ${r.target}: ${e}`));
64
+ }
65
+ export function findDependencies(input, options = {}) {
66
+ const types = asList(options.type);
67
+ const needles = asList(options.evidenceIncludes);
68
+ return input.dependencies.dependencies.filter((dep) => {
69
+ if (types.length > 0 && !types.includes(dep.type)) {
70
+ return false;
71
+ }
72
+ if (needles.length > 0) {
73
+ const blob = `${dep.from} ${dep.to} ${dep.evidence.join(" ")}`;
74
+ if (!includesAny(blob, needles)) {
75
+ return false;
76
+ }
77
+ }
78
+ return true;
79
+ });
80
+ }
81
+ export function findEntrypoints(input, options = {}) {
82
+ const frameworks = asList(options.framework);
83
+ const needles = asList(options.evidenceIncludes);
84
+ return input.entrypoints.entrypoints.filter((entry) => {
85
+ if (frameworks.length > 0 && !frameworks.includes(entry.framework)) {
86
+ return false;
87
+ }
88
+ if (needles.length > 0) {
89
+ const blob = `${entry.file} ${entry.evidence.join(" ")}`;
90
+ if (!includesAny(blob, needles)) {
91
+ return false;
92
+ }
93
+ }
94
+ return true;
95
+ });
96
+ }
97
+ export function emptyRuleResult(unknowns = []) {
98
+ return {
99
+ matchedRules: [],
100
+ evidence: [],
101
+ conflictingEvidence: [],
102
+ unknowns,
103
+ supportScore: 0,
104
+ conflictScore: 0,
105
+ };
106
+ }
107
+ export function finalizeMatch(pattern, result) {
108
+ if (result.matchedRules.length === 0 || result.supportScore <= 0) {
109
+ return null;
110
+ }
111
+ const confidence = scorePatternConfidence({
112
+ supportScore: result.supportScore,
113
+ conflictScore: result.conflictScore,
114
+ matchedRuleCount: result.matchedRules.length,
115
+ });
116
+ if (confidence <= 0) {
117
+ return null;
118
+ }
119
+ return {
120
+ pattern,
121
+ confidence,
122
+ evidence: [...result.evidence].sort((a, b) => a.localeCompare(b)),
123
+ matchedRules: [...result.matchedRules].sort((a, b) => a.localeCompare(b)),
124
+ conflictingEvidence: [...result.conflictingEvidence].sort((a, b) => a.localeCompare(b)),
125
+ unknowns: [...result.unknowns].sort((a, b) => a.localeCompare(b)),
126
+ };
127
+ }
@@ -0,0 +1,2 @@
1
+ import type { ArchitecturePatternDefinition } from "../types.js";
2
+ export declare const distributionPatterns: ArchitecturePatternDefinition[];
@@ -0,0 +1,115 @@
1
+ import { emptyRuleResult, findDependencies, findEntrypoints, findRelationships, relationshipEvidenceLines, } from "../models.js";
2
+ function evaluateMicroservice(ctx) {
3
+ const result = emptyRuleResult();
4
+ const frameworks = new Set(ctx.input.entrypoints.entrypoints.map((e) => e.framework));
5
+ const packageDeps = findDependencies(ctx.input, { type: "package" });
6
+ if (frameworks.size >= 2) {
7
+ result.matchedRules.push("Multiple runtime entrypoint frameworks");
8
+ result.evidence.push(...ctx.input.entrypoints.entrypoints
9
+ .slice(0, 5)
10
+ .map((e) => `entrypoint:${e.framework}:${e.file}`));
11
+ result.supportScore += frameworks.size * 0.7;
12
+ }
13
+ if (packageDeps.length >= 2) {
14
+ result.matchedRules.push("Multiple independently versioned package boundaries");
15
+ result.evidence.push(...packageDeps.slice(0, 4).map((d) => `${d.from} package-depends ${d.to}`));
16
+ result.supportScore += 0.8;
17
+ }
18
+ const moduleConfig = findRelationships(ctx.input, { relationship: "CONFIGURES" });
19
+ if (frameworks.size >= 2 && moduleConfig.length > 0 && packageDeps.length <= 1) {
20
+ result.conflictingEvidence.push("Shared module configuration suggests modular monolith more than pure microservices");
21
+ result.conflictScore += 0.7;
22
+ }
23
+ if (result.matchedRules.length > 0 && frameworks.size < 2) {
24
+ result.unknowns.push("Package splits without multi-runtime entrypoint proof");
25
+ }
26
+ return result;
27
+ }
28
+ function evaluateModularMonolith(ctx) {
29
+ const result = emptyRuleResult();
30
+ const modules = findRelationships(ctx.input, {
31
+ relationship: ["PROVIDES", "CONFIGURES"],
32
+ sourceIncludes: "Module",
33
+ });
34
+ const nest = findEntrypoints(ctx.input, { framework: "NestJS" });
35
+ const packageDeps = findDependencies(ctx.input, { type: "package" });
36
+ const frameworks = new Set(ctx.input.entrypoints.entrypoints.map((e) => e.framework));
37
+ if (modules.length > 0) {
38
+ result.matchedRules.push("Internal modules provide/configure application parts");
39
+ result.evidence.push(...relationshipEvidenceLines(modules));
40
+ result.supportScore += 1.4;
41
+ }
42
+ if (nest.length > 0 || (frameworks.size === 1 && modules.length > 0)) {
43
+ result.matchedRules.push("Single primary application runtime hosts modules");
44
+ result.evidence.push(...[...frameworks].map((f) => `runtime:${f}`), ...nest.slice(0, 2).map((e) => `entrypoint:${e.file}`));
45
+ result.supportScore += 1;
46
+ }
47
+ if (packageDeps.length > 0 && modules.length > 0) {
48
+ result.matchedRules.push("Workspace packages compose one deployable system");
49
+ result.evidence.push(...packageDeps.slice(0, 3).map((d) => `${d.from}->${d.to}`));
50
+ result.supportScore += 0.8;
51
+ }
52
+ if (frameworks.size >= 3) {
53
+ result.conflictingEvidence.push("Many independent runtimes weaken modular-monolith claim");
54
+ result.conflictScore += 0.9;
55
+ }
56
+ if (result.matchedRules.length > 0 && modules.length === 0) {
57
+ result.unknowns.push("Monolith packaging without module wiring evidence");
58
+ }
59
+ return result;
60
+ }
61
+ function evaluatePlugin(ctx) {
62
+ const result = emptyRuleResult();
63
+ const dynamic = findDependencies(ctx.input, { type: "dynamic-import" });
64
+ const moduleProvides = findRelationships(ctx.input, {
65
+ relationship: "PROVIDES",
66
+ sourceIncludes: "Module",
67
+ });
68
+ if (dynamic.length > 0) {
69
+ result.matchedRules.push("Dynamic imports indicate pluggable extension points");
70
+ result.evidence.push(...dynamic.slice(0, 4).map((d) => `dynamic:${d.from}->${d.to} (${d.evidence[0] ?? ""})`));
71
+ result.supportScore += 1.5;
72
+ }
73
+ if (moduleProvides.length > 0 && dynamic.length > 0) {
74
+ result.matchedRules.push("Modules expose extension surfaces");
75
+ result.evidence.push(...relationshipEvidenceLines(moduleProvides));
76
+ result.supportScore += 0.9;
77
+ }
78
+ if (dynamic.length > 0 && moduleProvides.length === 0) {
79
+ result.unknowns.push("Dynamic loading without explicit module/plugin registry evidence");
80
+ }
81
+ return result;
82
+ }
83
+ function evaluateMonorepo(ctx) {
84
+ const result = emptyRuleResult();
85
+ const packageDeps = findDependencies(ctx.input, {
86
+ type: "package",
87
+ evidenceIncludes: ["declares dependency", "package"],
88
+ });
89
+ const owns = findRelationships(ctx.input, { relationship: "OWNS" });
90
+ const depends = findDependencies(ctx.input, { type: "package" });
91
+ if (depends.length > 0) {
92
+ result.matchedRules.push("Workspace package dependency edges");
93
+ result.evidence.push(...depends.slice(0, 5).map((d) => `${d.from} DEPENDS_ON ${d.to}: ${d.evidence[0] ?? d.type}`));
94
+ result.supportScore += Math.min(depends.length, 4) * 0.55;
95
+ }
96
+ if (packageDeps.length > 0) {
97
+ result.matchedRules.push("Manifest-declared workspace references");
98
+ result.supportScore += 0.8;
99
+ }
100
+ if (owns.length > 0) {
101
+ result.matchedRules.push("Packages own feature/module slices");
102
+ result.evidence.push(...relationshipEvidenceLines(owns));
103
+ result.supportScore += 0.7;
104
+ }
105
+ if (result.matchedRules.length > 0 && depends.length < 1) {
106
+ result.unknowns.push("Monorepo layout cues without package dependency edges");
107
+ }
108
+ return result;
109
+ }
110
+ export const distributionPatterns = [
111
+ { pattern: "Microservice", evaluate: evaluateMicroservice },
112
+ { pattern: "Modular Monolith", evaluate: evaluateModularMonolith },
113
+ { pattern: "Plugin Architecture", evaluate: evaluatePlugin },
114
+ { pattern: "Monorepo Workspace", evaluate: evaluateMonorepo },
115
+ ];
@@ -0,0 +1,2 @@
1
+ import type { ArchitecturePatternDefinition } from "../types.js";
2
+ export declare const ARCHITECTURE_PATTERNS: readonly ArchitecturePatternDefinition[];
@@ -0,0 +1,8 @@
1
+ import { distributionPatterns } from "./distribution.js";
2
+ import { layeredPatterns } from "./layered.js";
3
+ import { structuralPatterns } from "./structural.js";
4
+ export const ARCHITECTURE_PATTERNS = [
5
+ ...layeredPatterns,
6
+ ...structuralPatterns,
7
+ ...distributionPatterns,
8
+ ];
@@ -0,0 +1,2 @@
1
+ import type { ArchitecturePatternDefinition } from "../types.js";
2
+ export declare const layeredPatterns: ArchitecturePatternDefinition[];