@grafema/util 0.3.0-beta

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 (324) hide show
  1. package/LICENSE +190 -0
  2. package/dist/api/GraphAPI.d.ts +87 -0
  3. package/dist/api/GraphAPI.d.ts.map +1 -0
  4. package/dist/api/GraphAPI.js +212 -0
  5. package/dist/api/GraphAPI.js.map +1 -0
  6. package/dist/api/GuaranteeAPI.d.ts +147 -0
  7. package/dist/api/GuaranteeAPI.d.ts.map +1 -0
  8. package/dist/api/GuaranteeAPI.js +290 -0
  9. package/dist/api/GuaranteeAPI.js.map +1 -0
  10. package/dist/config/ConfigLoader.d.ts +214 -0
  11. package/dist/config/ConfigLoader.d.ts.map +1 -0
  12. package/dist/config/ConfigLoader.js +441 -0
  13. package/dist/config/ConfigLoader.js.map +1 -0
  14. package/dist/config/index.d.ts +6 -0
  15. package/dist/config/index.d.ts.map +1 -0
  16. package/dist/config/index.js +5 -0
  17. package/dist/config/index.js.map +1 -0
  18. package/dist/core/CoverageAnalyzer.d.ts +65 -0
  19. package/dist/core/CoverageAnalyzer.d.ts.map +1 -0
  20. package/dist/core/CoverageAnalyzer.js +199 -0
  21. package/dist/core/CoverageAnalyzer.js.map +1 -0
  22. package/dist/core/FileExplainer.d.ts +101 -0
  23. package/dist/core/FileExplainer.d.ts.map +1 -0
  24. package/dist/core/FileExplainer.js +140 -0
  25. package/dist/core/FileExplainer.js.map +1 -0
  26. package/dist/core/FileOverview.d.ts +124 -0
  27. package/dist/core/FileOverview.d.ts.map +1 -0
  28. package/dist/core/FileOverview.js +279 -0
  29. package/dist/core/FileOverview.js.map +1 -0
  30. package/dist/core/GrafemaUri.d.ts +66 -0
  31. package/dist/core/GrafemaUri.d.ts.map +1 -0
  32. package/dist/core/GrafemaUri.js +191 -0
  33. package/dist/core/GrafemaUri.js.map +1 -0
  34. package/dist/core/GraphBackend.d.ts +158 -0
  35. package/dist/core/GraphBackend.d.ts.map +1 -0
  36. package/dist/core/GraphBackend.js +85 -0
  37. package/dist/core/GraphBackend.js.map +1 -0
  38. package/dist/core/GraphFreshnessChecker.d.ts +33 -0
  39. package/dist/core/GraphFreshnessChecker.d.ts.map +1 -0
  40. package/dist/core/GraphFreshnessChecker.js +104 -0
  41. package/dist/core/GraphFreshnessChecker.js.map +1 -0
  42. package/dist/core/GuaranteeManager.d.ts +254 -0
  43. package/dist/core/GuaranteeManager.d.ts.map +1 -0
  44. package/dist/core/GuaranteeManager.js +447 -0
  45. package/dist/core/GuaranteeManager.js.map +1 -0
  46. package/dist/core/HashUtils.d.ts +24 -0
  47. package/dist/core/HashUtils.d.ts.map +1 -0
  48. package/dist/core/HashUtils.js +46 -0
  49. package/dist/core/HashUtils.js.map +1 -0
  50. package/dist/core/IncrementalReanalyzer.d.ts +33 -0
  51. package/dist/core/IncrementalReanalyzer.d.ts.map +1 -0
  52. package/dist/core/IncrementalReanalyzer.js +67 -0
  53. package/dist/core/IncrementalReanalyzer.js.map +1 -0
  54. package/dist/core/ResourceRegistry.d.ts +17 -0
  55. package/dist/core/ResourceRegistry.d.ts.map +1 -0
  56. package/dist/core/ResourceRegistry.js +32 -0
  57. package/dist/core/ResourceRegistry.js.map +1 -0
  58. package/dist/core/SemanticId.d.ts +159 -0
  59. package/dist/core/SemanticId.d.ts.map +1 -0
  60. package/dist/core/SemanticId.js +291 -0
  61. package/dist/core/SemanticId.js.map +1 -0
  62. package/dist/core/VersionManager.d.ts +166 -0
  63. package/dist/core/VersionManager.d.ts.map +1 -0
  64. package/dist/core/VersionManager.js +239 -0
  65. package/dist/core/VersionManager.js.map +1 -0
  66. package/dist/core/brandNodeInternal.d.ts +14 -0
  67. package/dist/core/brandNodeInternal.d.ts.map +1 -0
  68. package/dist/core/brandNodeInternal.js +4 -0
  69. package/dist/core/brandNodeInternal.js.map +1 -0
  70. package/dist/core/nodes/GuaranteeNode.d.ts +76 -0
  71. package/dist/core/nodes/GuaranteeNode.d.ts.map +1 -0
  72. package/dist/core/nodes/GuaranteeNode.js +118 -0
  73. package/dist/core/nodes/GuaranteeNode.js.map +1 -0
  74. package/dist/core/nodes/IssueNode.d.ts +73 -0
  75. package/dist/core/nodes/IssueNode.d.ts.map +1 -0
  76. package/dist/core/nodes/IssueNode.js +130 -0
  77. package/dist/core/nodes/IssueNode.js.map +1 -0
  78. package/dist/core/nodes/NodeKind.d.ts +104 -0
  79. package/dist/core/nodes/NodeKind.d.ts.map +1 -0
  80. package/dist/core/nodes/NodeKind.js +166 -0
  81. package/dist/core/nodes/NodeKind.js.map +1 -0
  82. package/dist/diagnostics/DiagnosticCollector.d.ts +103 -0
  83. package/dist/diagnostics/DiagnosticCollector.d.ts.map +1 -0
  84. package/dist/diagnostics/DiagnosticCollector.js +133 -0
  85. package/dist/diagnostics/DiagnosticCollector.js.map +1 -0
  86. package/dist/diagnostics/DiagnosticReporter.d.ts +122 -0
  87. package/dist/diagnostics/DiagnosticReporter.d.ts.map +1 -0
  88. package/dist/diagnostics/DiagnosticReporter.js +300 -0
  89. package/dist/diagnostics/DiagnosticReporter.js.map +1 -0
  90. package/dist/diagnostics/DiagnosticWriter.d.ts +31 -0
  91. package/dist/diagnostics/DiagnosticWriter.d.ts.map +1 -0
  92. package/dist/diagnostics/DiagnosticWriter.js +44 -0
  93. package/dist/diagnostics/DiagnosticWriter.js.map +1 -0
  94. package/dist/diagnostics/categories.d.ts +57 -0
  95. package/dist/diagnostics/categories.d.ts.map +1 -0
  96. package/dist/diagnostics/categories.js +71 -0
  97. package/dist/diagnostics/categories.js.map +1 -0
  98. package/dist/diagnostics/index.d.ts +17 -0
  99. package/dist/diagnostics/index.d.ts.map +1 -0
  100. package/dist/diagnostics/index.js +15 -0
  101. package/dist/diagnostics/index.js.map +1 -0
  102. package/dist/errors/GrafemaError.d.ts +200 -0
  103. package/dist/errors/GrafemaError.d.ts.map +1 -0
  104. package/dist/errors/GrafemaError.js +209 -0
  105. package/dist/errors/GrafemaError.js.map +1 -0
  106. package/dist/index.d.ts +75 -0
  107. package/dist/index.d.ts.map +1 -0
  108. package/dist/index.js +76 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/instructions/index.d.ts +8 -0
  111. package/dist/instructions/index.d.ts.map +1 -0
  112. package/dist/instructions/index.js +20 -0
  113. package/dist/instructions/index.js.map +1 -0
  114. package/dist/instructions/onboarding.md +133 -0
  115. package/dist/knowledge/KnowledgeBase.d.ts +113 -0
  116. package/dist/knowledge/KnowledgeBase.d.ts.map +1 -0
  117. package/dist/knowledge/KnowledgeBase.js +420 -0
  118. package/dist/knowledge/KnowledgeBase.js.map +1 -0
  119. package/dist/knowledge/SemanticAddressResolver.d.ts +59 -0
  120. package/dist/knowledge/SemanticAddressResolver.d.ts.map +1 -0
  121. package/dist/knowledge/SemanticAddressResolver.js +160 -0
  122. package/dist/knowledge/SemanticAddressResolver.js.map +1 -0
  123. package/dist/knowledge/git-ingest.d.ts +58 -0
  124. package/dist/knowledge/git-ingest.d.ts.map +1 -0
  125. package/dist/knowledge/git-ingest.js +301 -0
  126. package/dist/knowledge/git-ingest.js.map +1 -0
  127. package/dist/knowledge/git-queries.d.ts +86 -0
  128. package/dist/knowledge/git-queries.d.ts.map +1 -0
  129. package/dist/knowledge/git-queries.js +177 -0
  130. package/dist/knowledge/git-queries.js.map +1 -0
  131. package/dist/knowledge/index.d.ts +14 -0
  132. package/dist/knowledge/index.d.ts.map +1 -0
  133. package/dist/knowledge/index.js +10 -0
  134. package/dist/knowledge/index.js.map +1 -0
  135. package/dist/knowledge/parser.d.ts +39 -0
  136. package/dist/knowledge/parser.d.ts.map +1 -0
  137. package/dist/knowledge/parser.js +292 -0
  138. package/dist/knowledge/parser.js.map +1 -0
  139. package/dist/knowledge/types.d.ts +133 -0
  140. package/dist/knowledge/types.d.ts.map +1 -0
  141. package/dist/knowledge/types.js +8 -0
  142. package/dist/knowledge/types.js.map +1 -0
  143. package/dist/logging/Logger.d.ts +98 -0
  144. package/dist/logging/Logger.d.ts.map +1 -0
  145. package/dist/logging/Logger.js +274 -0
  146. package/dist/logging/Logger.js.map +1 -0
  147. package/dist/notation/archetypes.d.ts +36 -0
  148. package/dist/notation/archetypes.d.ts.map +1 -0
  149. package/dist/notation/archetypes.js +173 -0
  150. package/dist/notation/archetypes.js.map +1 -0
  151. package/dist/notation/fold.d.ts +25 -0
  152. package/dist/notation/fold.d.ts.map +1 -0
  153. package/dist/notation/fold.js +598 -0
  154. package/dist/notation/fold.js.map +1 -0
  155. package/dist/notation/index.d.ts +18 -0
  156. package/dist/notation/index.d.ts.map +1 -0
  157. package/dist/notation/index.js +16 -0
  158. package/dist/notation/index.js.map +1 -0
  159. package/dist/notation/lodExtractor.d.ts +32 -0
  160. package/dist/notation/lodExtractor.d.ts.map +1 -0
  161. package/dist/notation/lodExtractor.js +149 -0
  162. package/dist/notation/lodExtractor.js.map +1 -0
  163. package/dist/notation/nameShortener.d.ts +22 -0
  164. package/dist/notation/nameShortener.d.ts.map +1 -0
  165. package/dist/notation/nameShortener.js +24 -0
  166. package/dist/notation/nameShortener.js.map +1 -0
  167. package/dist/notation/perspectives.d.ts +11 -0
  168. package/dist/notation/perspectives.d.ts.map +1 -0
  169. package/dist/notation/perspectives.js +16 -0
  170. package/dist/notation/perspectives.js.map +1 -0
  171. package/dist/notation/renderer.d.ts +31 -0
  172. package/dist/notation/renderer.d.ts.map +1 -0
  173. package/dist/notation/renderer.js +315 -0
  174. package/dist/notation/renderer.js.map +1 -0
  175. package/dist/notation/traceRenderer.d.ts +39 -0
  176. package/dist/notation/traceRenderer.d.ts.map +1 -0
  177. package/dist/notation/traceRenderer.js +358 -0
  178. package/dist/notation/traceRenderer.js.map +1 -0
  179. package/dist/notation/types.d.ts +66 -0
  180. package/dist/notation/types.d.ts.map +1 -0
  181. package/dist/notation/types.js +10 -0
  182. package/dist/notation/types.js.map +1 -0
  183. package/dist/queries/NodeContext.d.ts +81 -0
  184. package/dist/queries/NodeContext.d.ts.map +1 -0
  185. package/dist/queries/NodeContext.js +196 -0
  186. package/dist/queries/NodeContext.js.map +1 -0
  187. package/dist/queries/findCallsInFunction.d.ts +62 -0
  188. package/dist/queries/findCallsInFunction.d.ts.map +1 -0
  189. package/dist/queries/findCallsInFunction.js +169 -0
  190. package/dist/queries/findCallsInFunction.js.map +1 -0
  191. package/dist/queries/findContainingFunction.d.ts +57 -0
  192. package/dist/queries/findContainingFunction.d.ts.map +1 -0
  193. package/dist/queries/findContainingFunction.js +91 -0
  194. package/dist/queries/findContainingFunction.js.map +1 -0
  195. package/dist/queries/index.d.ts +18 -0
  196. package/dist/queries/index.d.ts.map +1 -0
  197. package/dist/queries/index.js +14 -0
  198. package/dist/queries/index.js.map +1 -0
  199. package/dist/queries/traceDataflow.d.ts +65 -0
  200. package/dist/queries/traceDataflow.d.ts.map +1 -0
  201. package/dist/queries/traceDataflow.js +754 -0
  202. package/dist/queries/traceDataflow.js.map +1 -0
  203. package/dist/queries/traceValues.d.ts +70 -0
  204. package/dist/queries/traceValues.d.ts.map +1 -0
  205. package/dist/queries/traceValues.js +373 -0
  206. package/dist/queries/traceValues.js.map +1 -0
  207. package/dist/queries/types.d.ts +166 -0
  208. package/dist/queries/types.d.ts.map +1 -0
  209. package/dist/queries/types.js +10 -0
  210. package/dist/queries/types.js.map +1 -0
  211. package/dist/schema/GraphSchemaExtractor.d.ts +53 -0
  212. package/dist/schema/GraphSchemaExtractor.d.ts.map +1 -0
  213. package/dist/schema/GraphSchemaExtractor.js +125 -0
  214. package/dist/schema/GraphSchemaExtractor.js.map +1 -0
  215. package/dist/schema/InterfaceSchemaExtractor.d.ts +73 -0
  216. package/dist/schema/InterfaceSchemaExtractor.d.ts.map +1 -0
  217. package/dist/schema/InterfaceSchemaExtractor.js +113 -0
  218. package/dist/schema/InterfaceSchemaExtractor.js.map +1 -0
  219. package/dist/schema/index.d.ts +5 -0
  220. package/dist/schema/index.d.ts.map +1 -0
  221. package/dist/schema/index.js +3 -0
  222. package/dist/schema/index.js.map +1 -0
  223. package/dist/storage/backends/RFDBServerBackend.d.ts +356 -0
  224. package/dist/storage/backends/RFDBServerBackend.d.ts.map +1 -0
  225. package/dist/storage/backends/RFDBServerBackend.js +748 -0
  226. package/dist/storage/backends/RFDBServerBackend.js.map +1 -0
  227. package/dist/storage/backends/typeValidation.d.ts +47 -0
  228. package/dist/storage/backends/typeValidation.d.ts.map +1 -0
  229. package/dist/storage/backends/typeValidation.js +141 -0
  230. package/dist/storage/backends/typeValidation.js.map +1 -0
  231. package/dist/utils/findRfdbBinary.d.ts +67 -0
  232. package/dist/utils/findRfdbBinary.d.ts.map +1 -0
  233. package/dist/utils/findRfdbBinary.js +261 -0
  234. package/dist/utils/findRfdbBinary.js.map +1 -0
  235. package/dist/utils/lazyDownload.d.ts +43 -0
  236. package/dist/utils/lazyDownload.d.ts.map +1 -0
  237. package/dist/utils/lazyDownload.js +175 -0
  238. package/dist/utils/lazyDownload.js.map +1 -0
  239. package/dist/utils/moduleResolution.d.ts +134 -0
  240. package/dist/utils/moduleResolution.d.ts.map +1 -0
  241. package/dist/utils/moduleResolution.js +189 -0
  242. package/dist/utils/moduleResolution.js.map +1 -0
  243. package/dist/utils/resolveNodeFile.d.ts +13 -0
  244. package/dist/utils/resolveNodeFile.d.ts.map +1 -0
  245. package/dist/utils/resolveNodeFile.js +18 -0
  246. package/dist/utils/resolveNodeFile.js.map +1 -0
  247. package/dist/utils/startRfdbServer.d.ts +63 -0
  248. package/dist/utils/startRfdbServer.d.ts.map +1 -0
  249. package/dist/utils/startRfdbServer.js +142 -0
  250. package/dist/utils/startRfdbServer.js.map +1 -0
  251. package/dist/validation/PathValidator.d.ts +80 -0
  252. package/dist/validation/PathValidator.d.ts.map +1 -0
  253. package/dist/validation/PathValidator.js +252 -0
  254. package/dist/validation/PathValidator.js.map +1 -0
  255. package/dist/version.d.ts +11 -0
  256. package/dist/version.d.ts.map +1 -0
  257. package/dist/version.js +26 -0
  258. package/dist/version.js.map +1 -0
  259. package/package.json +50 -0
  260. package/src/api/GraphAPI.ts +307 -0
  261. package/src/api/GuaranteeAPI.ts +402 -0
  262. package/src/config/ConfigLoader.ts +653 -0
  263. package/src/config/index.ts +13 -0
  264. package/src/core/CoverageAnalyzer.ts +243 -0
  265. package/src/core/FileExplainer.ts +179 -0
  266. package/src/core/FileOverview.ts +397 -0
  267. package/src/core/GrafemaUri.ts +216 -0
  268. package/src/core/GraphBackend.ts +266 -0
  269. package/src/core/GraphFreshnessChecker.ts +145 -0
  270. package/src/core/GuaranteeManager.ts +684 -0
  271. package/src/core/HashUtils.ts +48 -0
  272. package/src/core/IncrementalReanalyzer.ts +106 -0
  273. package/src/core/ResourceRegistry.ts +39 -0
  274. package/src/core/SemanticId.ts +423 -0
  275. package/src/core/VersionManager.ts +405 -0
  276. package/src/core/brandNodeInternal.ts +16 -0
  277. package/src/core/nodes/GuaranteeNode.ts +162 -0
  278. package/src/core/nodes/IssueNode.ts +177 -0
  279. package/src/core/nodes/NodeKind.ts +192 -0
  280. package/src/diagnostics/DiagnosticCollector.ts +170 -0
  281. package/src/diagnostics/DiagnosticReporter.ts +395 -0
  282. package/src/diagnostics/DiagnosticWriter.ts +50 -0
  283. package/src/diagnostics/categories.ts +104 -0
  284. package/src/diagnostics/index.ts +30 -0
  285. package/src/errors/GrafemaError.ts +297 -0
  286. package/src/index.ts +261 -0
  287. package/src/instructions/index.ts +21 -0
  288. package/src/instructions/onboarding.md +133 -0
  289. package/src/knowledge/KnowledgeBase.ts +486 -0
  290. package/src/knowledge/SemanticAddressResolver.ts +191 -0
  291. package/src/knowledge/git-ingest.ts +402 -0
  292. package/src/knowledge/git-queries.ts +269 -0
  293. package/src/knowledge/index.ts +29 -0
  294. package/src/knowledge/parser.ts +294 -0
  295. package/src/knowledge/types.ts +146 -0
  296. package/src/logging/Logger.ts +303 -0
  297. package/src/notation/archetypes.ts +189 -0
  298. package/src/notation/fold.ts +696 -0
  299. package/src/notation/index.ts +27 -0
  300. package/src/notation/lodExtractor.ts +177 -0
  301. package/src/notation/nameShortener.ts +24 -0
  302. package/src/notation/perspectives.ts +18 -0
  303. package/src/notation/renderer.ts +394 -0
  304. package/src/notation/traceRenderer.ts +458 -0
  305. package/src/notation/types.ts +79 -0
  306. package/src/queries/NodeContext.ts +280 -0
  307. package/src/queries/findCallsInFunction.ts +249 -0
  308. package/src/queries/findContainingFunction.ts +124 -0
  309. package/src/queries/index.ts +44 -0
  310. package/src/queries/traceDataflow.ts +838 -0
  311. package/src/queries/traceValues.ts +531 -0
  312. package/src/queries/types.ts +191 -0
  313. package/src/schema/GraphSchemaExtractor.ts +177 -0
  314. package/src/schema/InterfaceSchemaExtractor.ts +173 -0
  315. package/src/schema/index.ts +5 -0
  316. package/src/storage/backends/RFDBServerBackend.ts +895 -0
  317. package/src/storage/backends/typeValidation.ts +154 -0
  318. package/src/utils/findRfdbBinary.ts +288 -0
  319. package/src/utils/lazyDownload.ts +206 -0
  320. package/src/utils/moduleResolution.ts +271 -0
  321. package/src/utils/resolveNodeFile.ts +18 -0
  322. package/src/utils/startRfdbServer.ts +197 -0
  323. package/src/validation/PathValidator.ts +334 -0
  324. package/src/version.ts +28 -0
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Knowledge Base Types
3
+ *
4
+ * Semantic types for the persistent knowledge layer.
5
+ * KB nodes are stored as git-tracked markdown files with YAML frontmatter.
6
+ */
7
+
8
+ /** Node types in the knowledge graph */
9
+ export type KBNodeType = 'DECISION' | 'FACT' | 'SESSION' | 'COMMIT' | 'FILE_CHANGE' | 'AUTHOR' | 'TICKET' | 'INCIDENT';
10
+
11
+ /** Lifecycle derived from directory path */
12
+ export type KBLifecycle = 'declared' | 'derived' | 'synced';
13
+
14
+ /** Scope of a knowledge node */
15
+ export type KBScope = 'global' | 'project' | 'module';
16
+
17
+ /** Base fields shared by all KB nodes */
18
+ export interface KBNodeBase {
19
+ /** Semantic ID in format kb:<type>:<slug> */
20
+ id: string;
21
+ /** Node type */
22
+ type: KBNodeType;
23
+ /** Subtype within the node type (e.g., FACT: domain|error|preference, DECISION: adr|runbook) */
24
+ subtype?: string;
25
+ /** Scope of applicability */
26
+ scope?: KBScope;
27
+ /** Projections this node belongs to (e.g., 'epistemic', 'temporal') */
28
+ projections: string[];
29
+ /** Source node that produced this (e.g., session ID) */
30
+ source?: string;
31
+ /** Creation date (YYYY-MM-DD) */
32
+ created: string;
33
+ /** Markdown body content */
34
+ content: string;
35
+ /** Path to the .md file on disk */
36
+ filePath: string;
37
+ /** Lifecycle derived from directory structure */
38
+ lifecycle: KBLifecycle;
39
+ /** Semantic IDs of related nodes */
40
+ relates_to?: string[];
41
+ }
42
+
43
+ /** Decision node — architectural/design decisions */
44
+ export interface KBDecision extends KBNodeBase {
45
+ type: 'DECISION';
46
+ /** Decision status */
47
+ status: 'active' | 'superseded' | 'deprecated' | 'proposed';
48
+ /** Date when decision took effect */
49
+ effective_from?: string;
50
+ /** Date when decision was superseded/deprecated */
51
+ effective_until?: string;
52
+ /** Semantic addresses of code this applies to */
53
+ applies_to?: string[];
54
+ /** ID of the decision that superseded this one */
55
+ superseded_by?: string;
56
+ }
57
+
58
+ /** Fact node — observed facts about the codebase */
59
+ export interface KBFact extends KBNodeBase {
60
+ type: 'FACT';
61
+ /** Confidence level */
62
+ confidence?: 'high' | 'medium' | 'low';
63
+ /** ID of the fact that superseded this one */
64
+ superseded_by?: string;
65
+ }
66
+
67
+ /** Session node — records of design/work sessions */
68
+ export interface KBSession extends KBNodeBase {
69
+ type: 'SESSION';
70
+ /** Associated Linear task ID */
71
+ task_id?: string;
72
+ /** Path to session transcript */
73
+ session_path?: string;
74
+ /** IDs of nodes produced during this session */
75
+ produced?: string[];
76
+ }
77
+
78
+ /** Union of all KB node types */
79
+ export type KBNode = KBDecision | KBFact | KBSession | KBNodeBase;
80
+
81
+ /** Edge in the knowledge graph */
82
+ export interface KBEdge {
83
+ /** Edge type (e.g., PRODUCED, IMPLEMENTS, INFORMED_BY) */
84
+ type: string;
85
+ /** Source node semantic ID */
86
+ from: string;
87
+ /** Target node semantic ID */
88
+ to: string;
89
+ /** Optional evidence for the relationship */
90
+ evidence?: string;
91
+ }
92
+
93
+ /** Statistics about the knowledge base */
94
+ export interface KBStats {
95
+ /** Total node count */
96
+ totalNodes: number;
97
+ /** Counts by node type */
98
+ byType: Partial<Record<KBNodeType, number>>;
99
+ /** Counts by lifecycle */
100
+ byLifecycle: Partial<Record<KBLifecycle, number>>;
101
+ /** Total edge count */
102
+ totalEdges: number;
103
+ /** Edge counts by type */
104
+ edgesByType: Record<string, number>;
105
+ /** Dangling edge references (from/to IDs that don't exist as nodes) */
106
+ danglingRefs: string[];
107
+ /** KB nodes referencing code addresses that don't resolve to graph nodes */
108
+ danglingCodeRefs: DanglingCodeRef[];
109
+ }
110
+
111
+ /** Filter for querying KB nodes */
112
+ export interface KBQueryFilter {
113
+ /** Filter by node type */
114
+ type?: KBNodeType;
115
+ /** Filter by projection */
116
+ projection?: string;
117
+ /** Case-insensitive text search in body content */
118
+ text?: string;
119
+ /** Filter by decision status */
120
+ status?: string;
121
+ /** Filter by relates_to containing this ID */
122
+ relates_to?: string;
123
+ /** When true, return only nodes with dangling code references */
124
+ include_dangling_only?: boolean;
125
+ }
126
+
127
+ /** Parsed semantic address: file:name:TYPE or file:scope1:...:scopeN:name:TYPE */
128
+ export interface ParsedSemanticAddress {
129
+ file: string;
130
+ name: string;
131
+ type: string;
132
+ scopePath: string[];
133
+ }
134
+
135
+ /** Result of resolving a semantic address to a code graph node */
136
+ export interface ResolvedAddress {
137
+ address: string;
138
+ codeNodeId: string | null;
139
+ status: 'resolved' | 'dangling';
140
+ }
141
+
142
+ /** A dangling code reference from a KB node */
143
+ export interface DanglingCodeRef {
144
+ nodeId: string;
145
+ address: string;
146
+ }
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Logger - Lightweight logging for Grafema
3
+ *
4
+ * Features:
5
+ * - 5 log levels: silent, errors, warnings, info, debug
6
+ * - Context support for structured logging
7
+ * - Console and file output (or both via MultiLogger)
8
+ * - Safe handling of circular references
9
+ *
10
+ * Usage:
11
+ * const logger = createLogger('info');
12
+ * logger.info('Processing files', { count: 150 });
13
+ *
14
+ * // Write logs to file (REG-199):
15
+ * const logger = createLogger('info', { logFile: '.grafema/analysis.log' });
16
+ */
17
+
18
+ import { createWriteStream, writeFileSync, mkdirSync, accessSync, statSync, constants, type WriteStream } from 'fs';
19
+ import { dirname, resolve } from 'path';
20
+
21
+ /**
22
+ * Log level type
23
+ */
24
+ export type LogLevel = 'silent' | 'errors' | 'warnings' | 'info' | 'debug';
25
+
26
+ /**
27
+ * Logger interface
28
+ */
29
+ export interface Logger {
30
+ error(message: string, context?: Record<string, unknown>): void;
31
+ warn(message: string, context?: Record<string, unknown>): void;
32
+ info(message: string, context?: Record<string, unknown>): void;
33
+ debug(message: string, context?: Record<string, unknown>): void;
34
+ trace(message: string, context?: Record<string, unknown>): void;
35
+ }
36
+
37
+ /**
38
+ * Log level priorities (higher = more verbose)
39
+ */
40
+ const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {
41
+ silent: 0,
42
+ errors: 1,
43
+ warnings: 2,
44
+ info: 3,
45
+ debug: 4,
46
+ };
47
+
48
+ /**
49
+ * Minimum level required for each method
50
+ */
51
+ const METHOD_LEVELS = {
52
+ error: LOG_LEVEL_PRIORITY.errors,
53
+ warn: LOG_LEVEL_PRIORITY.warnings,
54
+ info: LOG_LEVEL_PRIORITY.info,
55
+ debug: LOG_LEVEL_PRIORITY.debug,
56
+ trace: LOG_LEVEL_PRIORITY.debug,
57
+ };
58
+
59
+ /**
60
+ * Safe JSON stringify that handles circular references
61
+ */
62
+ function safeStringify(obj: unknown): string {
63
+ const seen = new WeakSet();
64
+ return JSON.stringify(obj, (_key, value) => {
65
+ if (typeof value === 'object' && value !== null) {
66
+ if (seen.has(value)) {
67
+ return '[Circular]';
68
+ }
69
+ seen.add(value);
70
+ }
71
+ return value;
72
+ });
73
+ }
74
+
75
+ /**
76
+ * Format log message with optional context
77
+ */
78
+ function formatMessage(message: string, context?: Record<string, unknown>): string {
79
+ if (!context || Object.keys(context).length === 0) {
80
+ return message;
81
+ }
82
+ try {
83
+ return `${message} ${safeStringify(context)}`;
84
+ } catch {
85
+ return `${message} [context serialization failed]`;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Console-based Logger implementation
91
+ *
92
+ * Respects log level threshold - methods below threshold are no-ops.
93
+ */
94
+ export class ConsoleLogger implements Logger {
95
+ private readonly level: LogLevel;
96
+ private readonly priority: number;
97
+
98
+ constructor(logLevel: LogLevel = 'info') {
99
+ this.level = logLevel;
100
+ this.priority = LOG_LEVEL_PRIORITY[logLevel];
101
+ }
102
+
103
+ private shouldLog(methodLevel: number): boolean {
104
+ return this.priority >= methodLevel;
105
+ }
106
+
107
+ error(message: string, context?: Record<string, unknown>): void {
108
+ if (!this.shouldLog(METHOD_LEVELS.error)) return;
109
+ try {
110
+ console.error(formatMessage(`[ERROR] ${message}`, context));
111
+ } catch {
112
+ console.log(`[ERROR] ${message} [logging failed]`);
113
+ }
114
+ }
115
+
116
+ warn(message: string, context?: Record<string, unknown>): void {
117
+ if (!this.shouldLog(METHOD_LEVELS.warn)) return;
118
+ try {
119
+ console.warn(formatMessage(`[WARN] ${message}`, context));
120
+ } catch {
121
+ console.log(`[WARN] ${message} [logging failed]`);
122
+ }
123
+ }
124
+
125
+ info(message: string, context?: Record<string, unknown>): void {
126
+ if (!this.shouldLog(METHOD_LEVELS.info)) return;
127
+ try {
128
+ console.info(formatMessage(`[INFO] ${message}`, context));
129
+ } catch {
130
+ console.log(`[INFO] ${message} [logging failed]`);
131
+ }
132
+ }
133
+
134
+ debug(message: string, context?: Record<string, unknown>): void {
135
+ if (!this.shouldLog(METHOD_LEVELS.debug)) return;
136
+ try {
137
+ console.debug(formatMessage(`[DEBUG] ${message}`, context));
138
+ } catch {
139
+ console.log(`[DEBUG] ${message} [logging failed]`);
140
+ }
141
+ }
142
+
143
+ trace(message: string, context?: Record<string, unknown>): void {
144
+ if (!this.shouldLog(METHOD_LEVELS.trace)) return;
145
+ try {
146
+ console.debug(formatMessage(`[TRACE] ${message}`, context));
147
+ } catch {
148
+ console.log(`[TRACE] ${message} [logging failed]`);
149
+ }
150
+ }
151
+ }
152
+
153
+ /**
154
+ * File-based Logger implementation (REG-199)
155
+ *
156
+ * Writes log messages to a file with ISO timestamps using a write stream
157
+ * (non-blocking I/O). File is truncated on construction (overwritten each run).
158
+ * Parent directories are created automatically.
159
+ *
160
+ * Validates path on construction — throws if the directory is not writable
161
+ * or the path points to a directory.
162
+ */
163
+ export class FileLogger implements Logger {
164
+ private readonly priority: number;
165
+ private readonly stream: WriteStream;
166
+
167
+ constructor(logLevel: LogLevel, filePath: string) {
168
+ this.priority = LOG_LEVEL_PRIORITY[logLevel];
169
+ const resolvedPath = resolve(filePath);
170
+
171
+ // Create parent directories
172
+ const dir = dirname(resolvedPath);
173
+ mkdirSync(dir, { recursive: true });
174
+
175
+ // Validate: parent directory must be writable
176
+ try {
177
+ accessSync(dir, constants.W_OK);
178
+ } catch {
179
+ throw new Error(`Cannot write log file: directory '${dir}' is not writable`);
180
+ }
181
+
182
+ // Validate: path must not point to an existing directory
183
+ try {
184
+ if (statSync(resolvedPath).isDirectory()) {
185
+ throw new Error(`Cannot write log file: '${resolvedPath}' is a directory`);
186
+ }
187
+ } catch (e) {
188
+ // If stat throws, file doesn't exist yet — that's fine
189
+ if (e instanceof Error && e.message.includes('is a directory')) throw e;
190
+ }
191
+
192
+ // Truncate/create file synchronously (validates writeability),
193
+ // then open stream in append mode for non-blocking writes
194
+ writeFileSync(resolvedPath, '');
195
+ this.stream = createWriteStream(resolvedPath, { flags: 'a' });
196
+ this.stream.on('error', () => {
197
+ // Silently ignore stream errors — don't crash analysis for logging failures
198
+ });
199
+ }
200
+
201
+ private shouldLog(methodLevel: number): boolean {
202
+ return this.priority >= methodLevel;
203
+ }
204
+
205
+ private writeLine(level: string, message: string, context?: Record<string, unknown>): void {
206
+ const timestamp = new Date().toISOString();
207
+ const formatted = formatMessage(`${timestamp} [${level}] ${message}`, context);
208
+ this.stream.write(formatted + '\n');
209
+ }
210
+
211
+ error(message: string, context?: Record<string, unknown>): void {
212
+ if (!this.shouldLog(METHOD_LEVELS.error)) return;
213
+ this.writeLine('ERROR', message, context);
214
+ }
215
+
216
+ warn(message: string, context?: Record<string, unknown>): void {
217
+ if (!this.shouldLog(METHOD_LEVELS.warn)) return;
218
+ this.writeLine('WARN', message, context);
219
+ }
220
+
221
+ info(message: string, context?: Record<string, unknown>): void {
222
+ if (!this.shouldLog(METHOD_LEVELS.info)) return;
223
+ this.writeLine('INFO', message, context);
224
+ }
225
+
226
+ debug(message: string, context?: Record<string, unknown>): void {
227
+ if (!this.shouldLog(METHOD_LEVELS.debug)) return;
228
+ this.writeLine('DEBUG', message, context);
229
+ }
230
+
231
+ trace(message: string, context?: Record<string, unknown>): void {
232
+ if (!this.shouldLog(METHOD_LEVELS.trace)) return;
233
+ this.writeLine('TRACE', message, context);
234
+ }
235
+
236
+ /** Flush and close the write stream. Returns when all data is written. */
237
+ close(): Promise<void> {
238
+ return new Promise((resolve) => {
239
+ this.stream.end(resolve);
240
+ });
241
+ }
242
+ }
243
+
244
+ /**
245
+ * Multi-output Logger that delegates to multiple Logger instances.
246
+ *
247
+ * Each inner logger applies its own level filtering independently.
248
+ * Used to write to both console and file simultaneously.
249
+ */
250
+ export class MultiLogger implements Logger {
251
+ private readonly loggers: Logger[];
252
+
253
+ constructor(loggers: Logger[]) {
254
+ this.loggers = loggers;
255
+ }
256
+
257
+ error(message: string, context?: Record<string, unknown>): void {
258
+ for (const logger of this.loggers) logger.error(message, context);
259
+ }
260
+
261
+ warn(message: string, context?: Record<string, unknown>): void {
262
+ for (const logger of this.loggers) logger.warn(message, context);
263
+ }
264
+
265
+ info(message: string, context?: Record<string, unknown>): void {
266
+ for (const logger of this.loggers) logger.info(message, context);
267
+ }
268
+
269
+ debug(message: string, context?: Record<string, unknown>): void {
270
+ for (const logger of this.loggers) logger.debug(message, context);
271
+ }
272
+
273
+ trace(message: string, context?: Record<string, unknown>): void {
274
+ for (const logger of this.loggers) logger.trace(message, context);
275
+ }
276
+
277
+ /** Close all inner loggers that have a close() method (e.g., FileLogger). */
278
+ async close(): Promise<void> {
279
+ for (const logger of this.loggers) {
280
+ if (logger instanceof FileLogger) {
281
+ await logger.close();
282
+ }
283
+ }
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Create a Logger instance with the specified log level.
289
+ *
290
+ * When logFile is specified, returns a MultiLogger that writes to both
291
+ * console and file. The file logger always captures at 'debug' level
292
+ * for complete post-mortem debugging, regardless of the console level.
293
+ */
294
+ export function createLogger(level: LogLevel, options?: { logFile?: string }): Logger {
295
+ const consoleLogger = new ConsoleLogger(level);
296
+
297
+ if (options?.logFile) {
298
+ const fileLogger = new FileLogger('debug', options.logFile);
299
+ return new MultiLogger([consoleLogger, fileLogger]);
300
+ }
301
+
302
+ return consoleLogger;
303
+ }
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Edge → Archetype Mapping Table
3
+ *
4
+ * Maps every EDGE_TYPE from @grafema/types to a visual archetype + operator + verb.
5
+ * Pure data — no side effects.
6
+ *
7
+ * Archetypes (7 base + 2 structural):
8
+ * contains (implicit nesting, no operator)
9
+ * depends o- dependency/import
10
+ * flow_out > outward data/call flow
11
+ * flow_in < inward data/type flow
12
+ * write => persistent side effect
13
+ * exception >x error/rejection
14
+ * publishes ~>> event/message
15
+ * gates ?| conditional guard
16
+ * governs |= governance/invariant
17
+ *
18
+ * @module notation/archetypes
19
+ */
20
+
21
+ import type { Archetype, EdgeMapping } from './types.js';
22
+
23
+ // Sort order by archetype: input → process → output
24
+ // flow_in first (receives, reads), then deps, then calls, then side effects
25
+ const SORT: Record<Archetype, number> = {
26
+ contains: 0,
27
+ flow_in: 1,
28
+ depends: 2,
29
+ flow_out: 3,
30
+ write: 4,
31
+ publishes: 5,
32
+ exception: 6,
33
+ gates: 7,
34
+ governs: 8,
35
+ };
36
+
37
+ /** Sort order for "returns" verbs — output comes last */
38
+ const RETURNS_SORT = 9;
39
+
40
+ function m(archetype: Archetype, operator: string, verb: string, sortOverride?: number): EdgeMapping {
41
+ return { archetype, operator, verb, sortOrder: sortOverride ?? SORT[archetype] };
42
+ }
43
+
44
+ /**
45
+ * Complete mapping of all edge types to archetypes.
46
+ *
47
+ * Keys match EDGE_TYPE values from @grafema/types/edges.
48
+ */
49
+ export const EDGE_ARCHETYPE_MAP: Record<string, EdgeMapping> = {
50
+ // === Containment (operator='', defines { } nesting) ===
51
+ CONTAINS: m('contains', '', 'contains'),
52
+ HAS_SCOPE: m('contains', '', 'scopes'),
53
+ HAS_MEMBER: m('contains', '', 'has'),
54
+ HAS_BODY: m('contains', '', 'body'),
55
+ HAS_PROPERTY: m('contains', '', 'property'),
56
+ HAS_ELEMENT: m('contains', '', 'element'),
57
+ HAS_INIT: m('contains', '', 'init'),
58
+ HAS_UPDATE: m('contains', '', 'update'),
59
+ HAS_CALLBACK: m('contains', '', 'callback'),
60
+ HAS_CATCH: m('contains', '', 'catch'),
61
+ HAS_FINALLY: m('contains', '', 'finally'),
62
+ DECLARES: m('contains', '', 'declares'),
63
+ DEFINES: m('contains', '', 'defines'),
64
+ MOUNTS: m('contains', '', 'mounts'),
65
+ PROPERTY_KEY: m('contains', '', 'key'),
66
+ PROPERTY_VALUE: m('contains', '', 'value'),
67
+
68
+ // === Depends (o-) ===
69
+ DEPENDS_ON: m('depends', 'o-', 'depends on'),
70
+ IMPORTS: m('depends', 'o-', 'imports'),
71
+ IMPORTS_FROM: m('depends', 'o-', 'imports from'),
72
+ EXPORTS: m('depends', 'o-', 'exports'),
73
+ USES: m('depends', 'o-', 'uses'),
74
+ USES_CONFIG: m('depends', 'o-', 'uses config'),
75
+ USES_SECRET: m('depends', 'o-', 'uses secret'),
76
+ DEPLOYED_TO: m('depends', 'o-', 'deployed to'),
77
+ SCHEDULED_BY: m('depends', 'o-', 'scheduled by'),
78
+
79
+ // === Flow Out (>) ===
80
+ CALLS: m('flow_out', '>', 'calls'),
81
+ DELEGATES_TO: m('flow_out', '>', 'delegates to'),
82
+ ROUTES_TO: m('flow_out', '>', 'routes to'),
83
+ HANDLED_BY: m('flow_out', '>', 'handled by'),
84
+ MAKES_REQUEST: m('flow_out', '>', 'requests'),
85
+ CALLS_API: m('flow_out', '>', 'calls API'),
86
+ INVOKES_FUNCTION: m('flow_out', '>', 'invokes'),
87
+ PASSES_ARGUMENT: m('flow_out', '>', 'passes'),
88
+ RETURNS: m('flow_out', '>', 'returns', RETURNS_SORT),
89
+ CALL_RETURNS: m('flow_out', '>', 'call returns', RETURNS_SORT),
90
+ YIELDS: m('flow_out', '>', 'yields', RETURNS_SORT),
91
+ RESPONDS_WITH: m('flow_out', '>', 'responds with', RETURNS_SORT),
92
+ INTERACTS_WITH: m('flow_out', '>', 'interacts with'),
93
+ ITERATES_OVER: m('flow_out', '>', 'iterates'),
94
+ ASSIGNS_TO: m('flow_out', '>', 'assigns to'),
95
+ MODIFIES: m('flow_out', '>', 'modifies'),
96
+ CAPTURES: m('flow_out', '>', 'captures'),
97
+ FLOWS_INTO: m('flow_out', '>', 'flows into'),
98
+
99
+ // === Flow In (<) ===
100
+ READS_FROM: m('flow_in', '<', 'reads'),
101
+ RECEIVES_ARGUMENT: m('flow_in', '<', 'receives'),
102
+ ASSIGNED_FROM: m('flow_in', '<', 'assigned from'),
103
+ DERIVES_FROM: m('flow_in', '<', 'derives from'),
104
+ SPREADS_FROM: m('flow_in', '<', 'spreads from'),
105
+ ELEMENT_OF: m('flow_in', '<', 'element of'),
106
+ KEY_OF: m('flow_in', '<', 'key of'),
107
+ DESTRUCTURED_FROM: m('flow_in', '<', 'destructured from'),
108
+ HTTP_RECEIVES: m('flow_in', '<', 'receives HTTP'),
109
+ EXTENDS: m('flow_in', '<', 'extends'),
110
+ IMPLEMENTS: m('flow_in', '<', 'implements'),
111
+ INSTANCE_OF: m('flow_in', '<', 'instance of'),
112
+
113
+ // === Write (=>) ===
114
+ WRITES_TO: m('write', '=>', 'writes'),
115
+ LOGS_TO: m('write', '=>', 'logs to'),
116
+ PERFORMS_REDIS: m('write', '=>', 'redis'),
117
+
118
+ // === Exception (>x) ===
119
+ THROWS: m('exception', '>x', 'throws'),
120
+ REJECTS: m('exception', '>x', 'rejects'),
121
+ CATCHES_FROM: m('exception', '>x', 'catches from'),
122
+
123
+ // === Publishes (~>>) ===
124
+ EMITS_EVENT: m('publishes', '~>>', 'emits'),
125
+ LISTENS_TO: m('publishes', '~>>', 'listens to'),
126
+ PUBLISHES_TO: m('publishes', '~>>', 'publishes to'),
127
+ SUBSCRIBES_TO: m('publishes', '~>>', 'subscribes to'),
128
+ EXPOSED_VIA: m('publishes', '~>>', 'exposed via'),
129
+ EXPOSES: m('publishes', '~>>', 'exposes'),
130
+ JOINS_ROOM: m('publishes', '~>>', 'joins room'),
131
+
132
+ // === Gates (?|) ===
133
+ HAS_CONDITION: m('gates', '?|', 'guards'),
134
+ HAS_CONSEQUENT: m('gates', '?|', 'then'),
135
+ HAS_ALTERNATE: m('gates', '?|', 'else'),
136
+ HAS_CASE: m('gates', '?|', 'case'),
137
+ HAS_DEFAULT: m('gates', '?|', 'default'),
138
+
139
+ // === Governs (|=) ===
140
+ GOVERNS: m('governs', '|=', 'governs'),
141
+ VIOLATES: m('governs', '|=', 'violates'),
142
+ AFFECTS: m('governs', '|=', 'affects'),
143
+ MONITORED_BY: m('governs', '|=', 'monitored by'),
144
+ MEASURED_BY: m('governs', '|=', 'measured by'),
145
+ PROVISIONED_BY: m('governs', '|=', 'provisioned by'),
146
+ REGISTERS_VIEW: m('governs', '|=', 'registers view'),
147
+
148
+ // === Fallback ===
149
+ UNKNOWN: m('flow_out', '>', 'unknown'),
150
+ };
151
+
152
+ /**
153
+ * Look up edge mapping. Returns a fallback for unmapped types.
154
+ */
155
+ export function lookupEdge(edgeType: string): EdgeMapping {
156
+ return EDGE_ARCHETYPE_MAP[edgeType] ?? {
157
+ archetype: 'flow_out',
158
+ operator: '>',
159
+ verb: edgeType.toLowerCase().replace(/_/g, ' '),
160
+ sortOrder: SORT.flow_out,
161
+ };
162
+ }
163
+
164
+ /**
165
+ * Canonical operator → verb mapping, one entry per unique operator.
166
+ * Derived from the archetype table — single source of truth.
167
+ */
168
+ const CANONICAL_OPERATORS: Array<{ operator: string; verb: string }> = (() => {
169
+ const seen = new Set<string>();
170
+ const result: Array<{ operator: string; verb: string }> = [];
171
+ const entries = Object.values(EDGE_ARCHETYPE_MAP);
172
+ // Sort by archetype sort order for consistent legend ordering
173
+ entries.sort((a, b) => a.sortOrder - b.sortOrder);
174
+ for (const entry of entries) {
175
+ if (!entry.operator || seen.has(entry.operator)) continue;
176
+ seen.add(entry.operator);
177
+ result.push({ operator: entry.operator, verb: entry.verb });
178
+ }
179
+ return result;
180
+ })();
181
+
182
+ /**
183
+ * Generate a legend string from the archetype table.
184
+ * Single source of truth for all tools (describe, trace_dataflow, CLI).
185
+ */
186
+ export function generateLegend(): string {
187
+ const parts = CANONICAL_OPERATORS.map(({ operator, verb }) => `${operator} ${verb}`);
188
+ return `Legend: ${parts.join(' ')} {} contains`;
189
+ }