@harness-engineering/graph 0.4.2 → 0.5.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.
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { z } from 'zod';
2
2
 
3
- declare const NODE_TYPES: readonly ["repository", "module", "file", "class", "interface", "function", "method", "variable", "adr", "decision", "learning", "failure", "issue", "document", "skill", "conversation", "commit", "build", "test_result", "span", "metric", "log", "layer", "pattern", "constraint", "violation", "design_token", "aesthetic_intent", "design_constraint", "requirement"];
3
+ declare const NODE_TYPES: readonly ["repository", "module", "file", "class", "interface", "function", "method", "variable", "adr", "decision", "learning", "failure", "issue", "document", "skill", "conversation", "commit", "build", "test_result", "execution_outcome", "span", "metric", "log", "layer", "pattern", "constraint", "violation", "design_token", "aesthetic_intent", "design_constraint", "image_annotation", "requirement", "business_rule", "business_process", "business_concept", "business_term", "business_metric", "business_fact", "packed_summary"];
4
4
  type NodeType = (typeof NODE_TYPES)[number];
5
- declare const EDGE_TYPES: readonly ["contains", "imports", "calls", "implements", "inherits", "references", "applies_to", "caused_by", "resolved_by", "documents", "violates", "specifies", "decided", "co_changes_with", "triggered_by", "failed_in", "executed_by", "measured_by", "uses_token", "declares_intent", "violates_design", "platform_binding", "requires", "verified_by", "tested_by"];
5
+ declare const EDGE_TYPES: readonly ["contains", "imports", "calls", "implements", "inherits", "references", "applies_to", "caused_by", "resolved_by", "documents", "violates", "specifies", "decided", "co_changes_with", "triggered_by", "failed_in", "outcome_of", "executed_by", "measured_by", "uses_token", "declares_intent", "violates_design", "platform_binding", "requires", "verified_by", "tested_by", "governs", "measures", "annotates", "caches"];
6
6
  type EdgeType = (typeof EDGE_TYPES)[number];
7
7
  declare const OBSERVABILITY_TYPES: ReadonlySet<NodeType>;
8
8
  interface SourceLocation {
@@ -68,9 +68,18 @@ interface GraphMetadata {
68
68
  readonly edgeCount: number;
69
69
  }
70
70
  declare const CURRENT_SCHEMA_VERSION = 1;
71
+ /** Stability classification for prompt caching -- mirrors StabilityTier from @harness-engineering/types. */
72
+ type GraphStabilityTier = 'static' | 'session' | 'ephemeral';
73
+ /**
74
+ * Maps graph node types to their caching stability tier.
75
+ * Used by provider cache adapters to determine cache directives.
76
+ *
77
+ * Node types not listed here default to 'ephemeral' at resolution time.
78
+ */
79
+ declare const NODE_STABILITY: Record<string, GraphStabilityTier>;
71
80
  declare const GraphNodeSchema: z.ZodObject<{
72
81
  id: z.ZodString;
73
- type: z.ZodEnum<["repository", "module", "file", "class", "interface", "function", "method", "variable", "adr", "decision", "learning", "failure", "issue", "document", "skill", "conversation", "commit", "build", "test_result", "span", "metric", "log", "layer", "pattern", "constraint", "violation", "design_token", "aesthetic_intent", "design_constraint", "requirement"]>;
82
+ type: z.ZodEnum<["repository", "module", "file", "class", "interface", "function", "method", "variable", "adr", "decision", "learning", "failure", "issue", "document", "skill", "conversation", "commit", "build", "test_result", "execution_outcome", "span", "metric", "log", "layer", "pattern", "constraint", "violation", "design_token", "aesthetic_intent", "design_constraint", "image_annotation", "requirement", "business_rule", "business_process", "business_concept", "business_term", "business_metric", "business_fact", "packed_summary"]>;
74
83
  name: z.ZodString;
75
84
  path: z.ZodOptional<z.ZodString>;
76
85
  location: z.ZodOptional<z.ZodObject<{
@@ -99,7 +108,7 @@ declare const GraphNodeSchema: z.ZodObject<{
99
108
  lastModified: z.ZodOptional<z.ZodString>;
100
109
  }, "strip", z.ZodTypeAny, {
101
110
  id: string;
102
- type: "function" | "repository" | "module" | "file" | "class" | "interface" | "method" | "variable" | "adr" | "decision" | "learning" | "failure" | "issue" | "document" | "skill" | "conversation" | "commit" | "build" | "test_result" | "span" | "metric" | "log" | "layer" | "pattern" | "constraint" | "violation" | "design_token" | "aesthetic_intent" | "design_constraint" | "requirement";
111
+ type: "function" | "repository" | "module" | "file" | "class" | "interface" | "method" | "variable" | "adr" | "decision" | "learning" | "failure" | "issue" | "document" | "skill" | "conversation" | "commit" | "build" | "test_result" | "execution_outcome" | "span" | "metric" | "log" | "layer" | "pattern" | "constraint" | "violation" | "design_token" | "aesthetic_intent" | "design_constraint" | "image_annotation" | "requirement" | "business_rule" | "business_process" | "business_concept" | "business_term" | "business_metric" | "business_fact" | "packed_summary";
103
112
  name: string;
104
113
  metadata: Record<string, unknown>;
105
114
  path?: string | undefined;
@@ -116,7 +125,7 @@ declare const GraphNodeSchema: z.ZodObject<{
116
125
  lastModified?: string | undefined;
117
126
  }, {
118
127
  id: string;
119
- type: "function" | "repository" | "module" | "file" | "class" | "interface" | "method" | "variable" | "adr" | "decision" | "learning" | "failure" | "issue" | "document" | "skill" | "conversation" | "commit" | "build" | "test_result" | "span" | "metric" | "log" | "layer" | "pattern" | "constraint" | "violation" | "design_token" | "aesthetic_intent" | "design_constraint" | "requirement";
128
+ type: "function" | "repository" | "module" | "file" | "class" | "interface" | "method" | "variable" | "adr" | "decision" | "learning" | "failure" | "issue" | "document" | "skill" | "conversation" | "commit" | "build" | "test_result" | "execution_outcome" | "span" | "metric" | "log" | "layer" | "pattern" | "constraint" | "violation" | "design_token" | "aesthetic_intent" | "design_constraint" | "image_annotation" | "requirement" | "business_rule" | "business_process" | "business_concept" | "business_term" | "business_metric" | "business_fact" | "packed_summary";
120
129
  name: string;
121
130
  metadata: Record<string, unknown>;
122
131
  path?: string | undefined;
@@ -135,17 +144,17 @@ declare const GraphNodeSchema: z.ZodObject<{
135
144
  declare const GraphEdgeSchema: z.ZodObject<{
136
145
  from: z.ZodString;
137
146
  to: z.ZodString;
138
- type: z.ZodEnum<["contains", "imports", "calls", "implements", "inherits", "references", "applies_to", "caused_by", "resolved_by", "documents", "violates", "specifies", "decided", "co_changes_with", "triggered_by", "failed_in", "executed_by", "measured_by", "uses_token", "declares_intent", "violates_design", "platform_binding", "requires", "verified_by", "tested_by"]>;
147
+ type: z.ZodEnum<["contains", "imports", "calls", "implements", "inherits", "references", "applies_to", "caused_by", "resolved_by", "documents", "violates", "specifies", "decided", "co_changes_with", "triggered_by", "failed_in", "outcome_of", "executed_by", "measured_by", "uses_token", "declares_intent", "violates_design", "platform_binding", "requires", "verified_by", "tested_by", "governs", "measures", "annotates", "caches"]>;
139
148
  confidence: z.ZodOptional<z.ZodNumber>;
140
149
  metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
141
150
  }, "strip", z.ZodTypeAny, {
142
- type: "contains" | "imports" | "calls" | "implements" | "inherits" | "references" | "applies_to" | "caused_by" | "resolved_by" | "documents" | "violates" | "specifies" | "decided" | "co_changes_with" | "triggered_by" | "failed_in" | "executed_by" | "measured_by" | "uses_token" | "declares_intent" | "violates_design" | "platform_binding" | "requires" | "verified_by" | "tested_by";
151
+ type: "contains" | "imports" | "calls" | "implements" | "inherits" | "references" | "applies_to" | "caused_by" | "resolved_by" | "documents" | "violates" | "specifies" | "decided" | "co_changes_with" | "triggered_by" | "failed_in" | "outcome_of" | "executed_by" | "measured_by" | "uses_token" | "declares_intent" | "violates_design" | "platform_binding" | "requires" | "verified_by" | "tested_by" | "governs" | "measures" | "annotates" | "caches";
143
152
  from: string;
144
153
  to: string;
145
154
  metadata?: Record<string, unknown> | undefined;
146
155
  confidence?: number | undefined;
147
156
  }, {
148
- type: "contains" | "imports" | "calls" | "implements" | "inherits" | "references" | "applies_to" | "caused_by" | "resolved_by" | "documents" | "violates" | "specifies" | "decided" | "co_changes_with" | "triggered_by" | "failed_in" | "executed_by" | "measured_by" | "uses_token" | "declares_intent" | "violates_design" | "platform_binding" | "requires" | "verified_by" | "tested_by";
157
+ type: "contains" | "imports" | "calls" | "implements" | "inherits" | "references" | "applies_to" | "caused_by" | "resolved_by" | "documents" | "violates" | "specifies" | "decided" | "co_changes_with" | "triggered_by" | "failed_in" | "outcome_of" | "executed_by" | "measured_by" | "uses_token" | "declares_intent" | "violates_design" | "platform_binding" | "requires" | "verified_by" | "tested_by" | "governs" | "measures" | "annotates" | "caches";
149
158
  from: string;
150
159
  to: string;
151
160
  metadata?: Record<string, unknown> | undefined;
@@ -245,6 +254,45 @@ interface SerializedGraph {
245
254
  declare function saveGraph(dirPath: string, nodes: readonly GraphNode[], edges: readonly GraphEdge[]): Promise<void>;
246
255
  declare function loadGraph(dirPath: string): Promise<SerializedGraph | null>;
247
256
 
257
+ /**
258
+ * Minimal PackedEnvelope shape -- avoids circular dep on @harness-engineering/core.
259
+ * Canonical type: packages/core/src/compaction/envelope.ts — keep in sync.
260
+ */
261
+ interface PackedEnvelope {
262
+ meta: {
263
+ strategy: string[];
264
+ originalTokenEstimate: number;
265
+ compactedTokenEstimate: number;
266
+ reductionPct: number;
267
+ cached: boolean;
268
+ };
269
+ sections: Array<{
270
+ source: string;
271
+ content: string;
272
+ }>;
273
+ }
274
+
275
+ /** Normalize an intent string for deterministic cache keying. */
276
+ declare function normalizeIntent(intent: string): string;
277
+ /** Reads/writes PackedSummary nodes in the GraphStore. Validates via TTL + source freshness. */
278
+ declare class PackedSummaryCache {
279
+ private readonly store;
280
+ private readonly ttlMs;
281
+ constructor(store: GraphStore, ttlMs?: number);
282
+ /** Returns cached envelope with `cached: true` if valid, or null if miss/stale. */
283
+ get(intent: string): PackedEnvelope | null;
284
+ /** Parse and validate createdAt. Returns epoch ms or null if missing/malformed (GC-002). */
285
+ private parseCreatedMs;
286
+ /** GC-001: Checks source nodes exist and are unmodified since cache creation. */
287
+ private areSourcesFresh;
288
+ /** Parse envelope JSON and set cached: true. Returns null on invalid JSON. */
289
+ private parseEnvelope;
290
+ /** Write a PackedSummary node with caches edges to source nodes. */
291
+ set(intent: string, envelope: PackedEnvelope, sourceNodeIds: string[]): void;
292
+ /** Explicitly invalidate a cached packed summary. */
293
+ invalidate(intent: string): void;
294
+ }
295
+
248
296
  declare class ContextQL {
249
297
  private readonly store;
250
298
  constructor(store: GraphStore);
@@ -274,8 +322,8 @@ interface ImpactGroups {
274
322
  declare function groupNodesByImpact(nodes: readonly GraphNode[], excludeId?: string): ImpactGroups;
275
323
 
276
324
  /**
277
- * Ingests TypeScript/JavaScript files into the graph via regex-based parsing.
278
- * Future: upgrade to tree-sitter for full AST parsing.
325
+ * Ingests source files into the graph via regex-based parsing.
326
+ * Supports TypeScript, JavaScript, Python, Go, Rust, and Java.
279
327
  */
280
328
  declare class CodeIngestor {
281
329
  private readonly store;
@@ -285,12 +333,22 @@ declare class CodeIngestor {
285
333
  private trackCallable;
286
334
  private findSourceFiles;
287
335
  private extractSymbols;
336
+ private processSymbolLine;
337
+ private matchFunction;
288
338
  private tryExtractFunction;
339
+ private matchClass;
289
340
  private tryExtractClass;
341
+ private matchInterface;
290
342
  private tryExtractInterface;
343
+ /**
344
+ * Enter an impl block (Rust) or Java class body — sets class context without creating a node.
345
+ */
346
+ private tryEnterImplBlock;
291
347
  /** Update brace tracking; returns true when line is consumed (class ended or tracked). */
292
348
  private updateClassContext;
349
+ private matchMethod;
293
350
  private tryExtractMethod;
351
+ private matchVariable;
294
352
  private tryExtractVariable;
295
353
  /**
296
354
  * Find the closing brace for a construct starting at the given line.
@@ -298,11 +356,21 @@ declare class CodeIngestor {
298
356
  */
299
357
  private findClosingBrace;
300
358
  /**
301
- * Second pass: scan each file for identifiers matching known callable names,
359
+ * Find the end of an indentation-based block (Python).
360
+ * The block ends when a subsequent non-empty line has indentation <= the starting line.
361
+ */
362
+ private findEndOfIndentBlock;
363
+ /**
364
+ * Update class context for Python using indentation tracking.
365
+ */
366
+ private updatePythonClassContext;
367
+ /**
368
+ * Scan a file for identifiers matching known callable names,
302
369
  * then create file-to-file "calls" edges. Uses regex heuristic (not AST).
303
370
  */
304
- private extractCallsEdges;
371
+ private extractCallsEdgesForFile;
305
372
  private extractImports;
373
+ private extractImportPaths;
306
374
  private resolveImportPath;
307
375
  private computeCyclomaticComplexity;
308
376
  private computeMaxNesting;
@@ -313,7 +381,7 @@ declare class CodeIngestor {
313
381
  * linking requirement nodes to the annotated files.
314
382
  * Format: // @req <feature-name>#<index>
315
383
  */
316
- private extractReqAnnotations;
384
+ private extractReqAnnotationsForFile;
317
385
  }
318
386
 
319
387
  type GitRunner = (rootDir: string, args: string[]) => Promise<string>;
@@ -369,6 +437,18 @@ declare class KnowledgeIngestor {
369
437
  private findMarkdownFiles;
370
438
  }
371
439
 
440
+ declare class BusinessKnowledgeIngestor {
441
+ private readonly store;
442
+ constructor(store: GraphStore);
443
+ ingest(knowledgeDir: string): Promise<IngestResult>;
444
+ private createNodes;
445
+ private parseAndAddNode;
446
+ private createEdges;
447
+ private linkToNodes;
448
+ private linkToBusinessNodes;
449
+ private findMarkdownFiles;
450
+ }
451
+
372
452
  declare class RequirementIngestor {
373
453
  private readonly store;
374
454
  constructor(store: GraphStore);
@@ -406,6 +486,279 @@ declare class RequirementIngestor {
406
486
  private linkByKeywordOverlap;
407
487
  }
408
488
 
489
+ type DriftClassification = 'new' | 'drifted' | 'stale' | 'contradicting';
490
+ interface KnowledgeSnapshotEntry {
491
+ readonly id: string;
492
+ readonly type: NodeType;
493
+ readonly contentHash: string;
494
+ readonly source: string;
495
+ readonly name: string;
496
+ }
497
+ interface KnowledgeSnapshot {
498
+ readonly entries: readonly KnowledgeSnapshotEntry[];
499
+ readonly timestamp: string;
500
+ }
501
+ interface DriftFinding {
502
+ readonly entryId: string;
503
+ readonly classification: DriftClassification;
504
+ readonly current?: KnowledgeSnapshotEntry;
505
+ readonly fresh?: KnowledgeSnapshotEntry;
506
+ readonly severity: 'critical' | 'high' | 'medium' | 'low';
507
+ }
508
+ interface DriftResult {
509
+ readonly findings: readonly DriftFinding[];
510
+ readonly driftScore: number;
511
+ readonly summary: {
512
+ readonly new: number;
513
+ readonly drifted: number;
514
+ readonly stale: number;
515
+ readonly contradicting: number;
516
+ };
517
+ }
518
+ interface DriftDetector {
519
+ detect(current: KnowledgeSnapshot, fresh: KnowledgeSnapshot): DriftResult;
520
+ }
521
+ declare class StructuralDriftDetector implements DriftDetector {
522
+ detect(current: KnowledgeSnapshot, fresh: KnowledgeSnapshot): DriftResult;
523
+ }
524
+
525
+ /**
526
+ * Knowledge Staging Aggregator
527
+ *
528
+ * Merges extraction results from multiple sources (code extractors, linkers, diagrams),
529
+ * deduplicates by contentHash, writes staged JSONL, and generates gap reports.
530
+ */
531
+
532
+ interface StagedEntry {
533
+ readonly id: string;
534
+ readonly source: 'extractor' | 'linker' | 'diagram';
535
+ readonly extractorName?: string;
536
+ readonly nodeType: NodeType;
537
+ readonly name: string;
538
+ readonly confidence: number;
539
+ readonly contentHash: string;
540
+ readonly timestamp: string;
541
+ }
542
+ interface DomainCoverage {
543
+ readonly domain: string;
544
+ readonly entryCount: number;
545
+ }
546
+ interface GapReport {
547
+ readonly domains: readonly DomainCoverage[];
548
+ readonly totalEntries: number;
549
+ readonly generatedAt: string;
550
+ }
551
+ interface AggregateResult {
552
+ readonly staged: number;
553
+ }
554
+ declare class KnowledgeStagingAggregator {
555
+ private readonly projectDir;
556
+ constructor(projectDir: string);
557
+ aggregate(extractorResults: readonly StagedEntry[], linkerResults: readonly StagedEntry[], diagramResults: readonly StagedEntry[]): Promise<AggregateResult>;
558
+ generateGapReport(knowledgeDir: string): Promise<GapReport>;
559
+ writeGapReport(report: GapReport): Promise<void>;
560
+ }
561
+
562
+ interface AnalysisRequest {
563
+ prompt: string;
564
+ systemPrompt?: string;
565
+ responseSchema: unknown;
566
+ model?: string;
567
+ maxTokens?: number;
568
+ }
569
+ interface AnalysisResponse<T> {
570
+ result: T;
571
+ tokenUsage: {
572
+ inputTokens: number;
573
+ outputTokens: number;
574
+ totalTokens: number;
575
+ };
576
+ model: string;
577
+ latencyMs: number;
578
+ }
579
+ interface AnalysisProvider {
580
+ analyze<T>(request: AnalysisRequest): Promise<AnalysisResponse<T>>;
581
+ }
582
+ interface DetectedElement {
583
+ readonly type: string;
584
+ readonly label: string;
585
+ readonly confidence: number;
586
+ }
587
+ interface ImageAnalysisResult {
588
+ readonly description: string;
589
+ readonly detectedElements: readonly DetectedElement[];
590
+ readonly extractedText: readonly string[];
591
+ readonly designPatterns: readonly string[];
592
+ readonly accessibilityNotes: readonly string[];
593
+ }
594
+ interface ImageAnalysisExtractorOptions {
595
+ readonly analysisProvider: AnalysisProvider;
596
+ readonly maxFileSizeMB?: number;
597
+ }
598
+ declare class ImageAnalysisExtractor {
599
+ private readonly provider;
600
+ /** Maximum file size in bytes. Reserved for future file-size filtering. */
601
+ readonly maxFileSizeBytes: number;
602
+ constructor(options: ImageAnalysisExtractorOptions);
603
+ analyze(store: GraphStore, imagePaths: readonly string[]): Promise<IngestResult>;
604
+ }
605
+
606
+ type ConflictType = 'value_mismatch' | 'definition_conflict' | 'status_divergence' | 'temporal_conflict';
607
+ interface ContradictionEntry {
608
+ readonly nodeId: string;
609
+ readonly source: string;
610
+ readonly name: string;
611
+ readonly content: string;
612
+ readonly lastModified?: string | undefined;
613
+ }
614
+ interface Contradiction {
615
+ readonly id: string;
616
+ readonly entityA: ContradictionEntry;
617
+ readonly entityB: ContradictionEntry;
618
+ readonly similarity: number;
619
+ readonly conflictType: ConflictType;
620
+ readonly severity: 'critical' | 'high' | 'medium';
621
+ readonly description: string;
622
+ }
623
+ interface ContradictionResult {
624
+ readonly contradictions: readonly Contradiction[];
625
+ readonly sourcePairCounts: Record<string, number>;
626
+ readonly totalChecked: number;
627
+ }
628
+ declare class ContradictionDetector {
629
+ detect(store: GraphStore): ContradictionResult;
630
+ }
631
+
632
+ interface DomainCoverageScore {
633
+ readonly domain: string;
634
+ readonly score: number;
635
+ readonly knowledgeEntries: number;
636
+ readonly codeEntities: number;
637
+ readonly linkedEntities: number;
638
+ readonly unlinkedEntities: number;
639
+ readonly sourceBreakdown: Record<string, number>;
640
+ readonly grade: 'A' | 'B' | 'C' | 'D' | 'F';
641
+ }
642
+ interface CoverageReport {
643
+ readonly domains: readonly DomainCoverageScore[];
644
+ readonly overallScore: number;
645
+ readonly overallGrade: 'A' | 'B' | 'C' | 'D' | 'F';
646
+ readonly generatedAt: string;
647
+ }
648
+ declare class CoverageScorer {
649
+ score(store: GraphStore): CoverageReport;
650
+ private domainFromPath;
651
+ }
652
+
653
+ /**
654
+ * KnowledgePipelineRunner — 4-phase convergence loop for knowledge extraction,
655
+ * reconciliation, drift detection, and remediation.
656
+ *
657
+ * Phases:
658
+ * 1. EXTRACT — Run code signal extractors, diagram parsers, image analysis, business knowledge ingestor, linker
659
+ * 2. RECONCILE — Compare pre-extraction graph snapshot against post-extraction snapshot + cross-source contradiction detection
660
+ * 3. DETECT — Classify findings by severity, generate gap report + coverage scoring
661
+ * 4. REMEDIATE — Apply safe fixes, converge (only with `fix: true`)
662
+ */
663
+
664
+ interface KnowledgePipelineOptions {
665
+ readonly projectDir: string;
666
+ readonly fix: boolean;
667
+ readonly ci: boolean;
668
+ readonly domain?: string;
669
+ readonly graphDir?: string;
670
+ readonly maxIterations?: number;
671
+ readonly analyzeImages?: boolean;
672
+ readonly analysisProvider?: AnalysisProvider;
673
+ readonly imagePaths?: readonly string[];
674
+ }
675
+ interface ExtractionCounts {
676
+ readonly codeSignals: number;
677
+ readonly diagrams: number;
678
+ readonly linkerFacts: number;
679
+ readonly businessKnowledge: number;
680
+ readonly images: number;
681
+ }
682
+ interface KnowledgePipelineResult {
683
+ readonly verdict: 'pass' | 'warn' | 'fail';
684
+ readonly driftScore: number;
685
+ readonly iterations: number;
686
+ readonly findings: DriftResult['summary'];
687
+ readonly extraction: ExtractionCounts;
688
+ readonly gaps: GapReport;
689
+ readonly remediations: readonly string[];
690
+ readonly contradictions: ContradictionResult;
691
+ readonly coverage: CoverageReport;
692
+ }
693
+ declare class KnowledgePipelineRunner {
694
+ private readonly store;
695
+ constructor(store: GraphStore);
696
+ run(options: KnowledgePipelineOptions): Promise<KnowledgePipelineResult>;
697
+ private extract;
698
+ private buildSnapshot;
699
+ private reconcile;
700
+ private detect;
701
+ private remediate;
702
+ private stageNewFindings;
703
+ private classifySource;
704
+ private computeVerdict;
705
+ }
706
+
707
+ /**
708
+ * Diagram-as-code parser types and format-specific implementations.
709
+ *
710
+ * Extracts entities and relationships from diagram files (Mermaid, D2, PlantUML)
711
+ * and maps them to the knowledge graph.
712
+ */
713
+
714
+ interface DiagramEntity {
715
+ readonly id: string;
716
+ readonly label: string;
717
+ readonly type?: string;
718
+ }
719
+ interface DiagramRelationship {
720
+ readonly from: string;
721
+ readonly to: string;
722
+ readonly label?: string;
723
+ }
724
+ interface DiagramParseResult {
725
+ readonly entities: readonly DiagramEntity[];
726
+ readonly relationships: readonly DiagramRelationship[];
727
+ readonly metadata: {
728
+ readonly format: 'mermaid' | 'd2' | 'plantuml';
729
+ readonly diagramType: string;
730
+ };
731
+ }
732
+ interface DiagramFormatParser {
733
+ canParse(content: string, ext: string): boolean;
734
+ parse(content: string, filePath: string): DiagramParseResult;
735
+ }
736
+ declare class MermaidParser implements DiagramFormatParser {
737
+ canParse(_content: string, ext: string): boolean;
738
+ parse(content: string, _filePath: string): DiagramParseResult;
739
+ private detectDiagramType;
740
+ private parseFlowchart;
741
+ private isDecisionNode;
742
+ private parseSequence;
743
+ }
744
+ declare class D2Parser implements DiagramFormatParser {
745
+ canParse(_content: string, ext: string): boolean;
746
+ parse(content: string, _filePath: string): DiagramParseResult;
747
+ }
748
+ declare class PlantUmlParser implements DiagramFormatParser {
749
+ canParse(_content: string, ext: string): boolean;
750
+ parse(content: string, _filePath: string): DiagramParseResult;
751
+ private detectDiagramType;
752
+ }
753
+ declare class DiagramParser {
754
+ private readonly store;
755
+ private readonly parsers;
756
+ constructor(store: GraphStore);
757
+ parse(content: string, filePath: string): DiagramParseResult;
758
+ ingest(projectDir: string): Promise<IngestResult>;
759
+ private findDiagramFiles;
760
+ }
761
+
409
762
  type HttpClient = (url: string, options?: {
410
763
  headers?: Record<string, string>;
411
764
  }) => Promise<{
@@ -419,6 +772,7 @@ interface ConnectorConfig {
419
772
  schedule?: string;
420
773
  lookbackDays?: number;
421
774
  filters?: Record<string, unknown>;
775
+ maxContentLength?: number;
422
776
  [key: string]: unknown;
423
777
  }
424
778
  interface GraphConnector {
@@ -458,6 +812,7 @@ declare class JiraConnector implements GraphConnector {
458
812
  ingest(store: GraphStore, config: ConnectorConfig): Promise<IngestResult>;
459
813
  private fetchAllIssues;
460
814
  private processIssue;
815
+ private fetchComments;
461
816
  }
462
817
 
463
818
  declare class SlackConnector implements GraphConnector {
@@ -467,6 +822,7 @@ declare class SlackConnector implements GraphConnector {
467
822
  constructor(httpClient?: HttpClient);
468
823
  ingest(store: GraphStore, config: ConnectorConfig): Promise<IngestResult>;
469
824
  private processChannel;
825
+ private fetchThreadReplies;
470
826
  }
471
827
 
472
828
  declare class ConfluenceConnector implements GraphConnector {
@@ -489,6 +845,24 @@ declare class CIConnector implements GraphConnector {
489
845
  private fetchAndIngestRuns;
490
846
  }
491
847
 
848
+ declare class FigmaConnector implements GraphConnector {
849
+ readonly name = "figma";
850
+ readonly source = "figma";
851
+ private readonly httpClient;
852
+ constructor(httpClient?: HttpClient);
853
+ ingest(store: GraphStore, config: ConnectorConfig): Promise<IngestResult>;
854
+ private processFile;
855
+ }
856
+
857
+ declare class MiroConnector implements GraphConnector {
858
+ readonly name = "miro";
859
+ readonly source = "miro";
860
+ private readonly httpClient;
861
+ constructor(httpClient?: HttpClient);
862
+ ingest(store: GraphStore, config: ConnectorConfig): Promise<IngestResult>;
863
+ private processBoard;
864
+ }
865
+
492
866
  interface FusionResult {
493
867
  readonly nodeId: string;
494
868
  readonly node: GraphNode;
@@ -951,6 +1325,161 @@ declare class GraphConstraintAdapter {
951
1325
  private resolveLayer;
952
1326
  }
953
1327
 
1328
+ /** Languages supported by the code signal extractors. */
1329
+ type Language = 'typescript' | 'javascript' | 'python' | 'go' | 'rust' | 'java';
1330
+ /**
1331
+ * A single business-signal extraction record.
1332
+ * Written to JSONL and used to create provisional graph nodes.
1333
+ */
1334
+ interface ExtractionRecord {
1335
+ /** Deterministic ID: `extracted:<extractor>:<hash(filePath+':'+patternKey)>` */
1336
+ readonly id: string;
1337
+ /** Which extractor produced this record. */
1338
+ readonly extractor: string;
1339
+ /** Source language of the file. */
1340
+ readonly language: Language;
1341
+ /** File path relative to project root. */
1342
+ readonly filePath: string;
1343
+ /** Start line of the extracted pattern (1-based). */
1344
+ readonly line: number;
1345
+ /** Graph node type this maps to. */
1346
+ readonly nodeType: NodeType;
1347
+ /** Human-readable label for the extracted fact. */
1348
+ readonly name: string;
1349
+ /** Raw extracted text. */
1350
+ readonly content: string;
1351
+ /** Extraction confidence (0.0-1.0). */
1352
+ readonly confidence: number;
1353
+ /** Extractor-specific metadata. */
1354
+ readonly metadata: Record<string, unknown>;
1355
+ }
1356
+ /**
1357
+ * Interface for pluggable code signal extractors.
1358
+ * Each extractor scans file content and returns extraction records.
1359
+ */
1360
+ interface SignalExtractor {
1361
+ /** Unique extractor identifier (e.g. 'test-descriptions'). */
1362
+ readonly name: string;
1363
+ /** File extensions this extractor can process. */
1364
+ readonly supportedExtensions: readonly string[];
1365
+ /** Extract signals from a single file's content. */
1366
+ extract(content: string, filePath: string, language: Language): ExtractionRecord[];
1367
+ }
1368
+
1369
+ /** Detect language from a file path. Returns undefined if unsupported. */
1370
+ declare function detectLanguage(filePath: string): Language | undefined;
1371
+ /**
1372
+ * Orchestrates code signal extraction across a project.
1373
+ * Walks files, dispatches to registered extractors, writes JSONL,
1374
+ * persists to graph, and handles stale detection.
1375
+ */
1376
+ declare class ExtractionRunner {
1377
+ private readonly extractors;
1378
+ constructor(extractors: readonly SignalExtractor[]);
1379
+ /**
1380
+ * Run all extractors against a project directory.
1381
+ * @param projectDir - Project root directory
1382
+ * @param store - GraphStore for node/edge persistence
1383
+ * @param outputDir - Directory for JSONL output (e.g. .harness/knowledge/extracted/)
1384
+ */
1385
+ run(projectDir: string, store: GraphStore, outputDir: string): Promise<IngestResult>;
1386
+ /** Write extraction records to JSONL file. */
1387
+ writeJsonl(records: readonly ExtractionRecord[], outputDir: string, extractorName: string): Promise<void>;
1388
+ /** Create or update a graph node from an extraction record. */
1389
+ private persistRecord;
1390
+ /**
1391
+ * Mark nodes from previous extractions that are no longer present as stale.
1392
+ * Returns the number of nodes marked stale.
1393
+ */
1394
+ markStale(store: GraphStore, currentIds: Set<string>): number;
1395
+ /** Recursively find source files, skipping common non-source directories. */
1396
+ findSourceFiles(dir: string): Promise<string[]>;
1397
+ }
1398
+
1399
+ /**
1400
+ * Extracts business rules from test descriptions.
1401
+ * Finds describe/it/test blocks (TS/JS), test_ functions (Python),
1402
+ * Test* functions + t.Run subtests (Go), #[test] fns (Rust),
1403
+ * @Test + @DisplayName (Java).
1404
+ */
1405
+ declare class TestDescriptionExtractor implements SignalExtractor {
1406
+ readonly name = "test-descriptions";
1407
+ readonly supportedExtensions: string[];
1408
+ extract(content: string, filePath: string, language: Language): ExtractionRecord[];
1409
+ private extractJsTs;
1410
+ private extractPython;
1411
+ private extractGo;
1412
+ private extractRust;
1413
+ private extractJava;
1414
+ }
1415
+
1416
+ /**
1417
+ * Extracts domain vocabulary from enum and constant definitions.
1418
+ * Finds enum declarations (all langs), as const objects (TS),
1419
+ * Object.freeze (JS), StrEnum/IntEnum (Python), iota (Go).
1420
+ */
1421
+ declare class EnumConstantExtractor implements SignalExtractor {
1422
+ readonly name = "enum-constants";
1423
+ readonly supportedExtensions: string[];
1424
+ extract(content: string, filePath: string, language: Language): ExtractionRecord[];
1425
+ private extractTypeScript;
1426
+ private extractJavaScript;
1427
+ private extractPython;
1428
+ private extractGo;
1429
+ private extractRust;
1430
+ private extractJava;
1431
+ private collectEnumMembers;
1432
+ private collectObjectKeys;
1433
+ private findClosingBrace;
1434
+ private collectPythonEnumMembers;
1435
+ private collectRustEnumVariants;
1436
+ private collectJavaEnumConstants;
1437
+ }
1438
+
1439
+ /**
1440
+ * Extracts business constraints from validation schemas and decorators.
1441
+ * Finds Zod schemas (TS/JS), Pydantic models (Python), struct validate
1442
+ * tags (Go), #[validate] macros (Rust), Bean Validation (Java).
1443
+ */
1444
+ declare class ValidationRuleExtractor implements SignalExtractor {
1445
+ readonly name = "validation-rules";
1446
+ readonly supportedExtensions: string[];
1447
+ extract(content: string, filePath: string, language: Language): ExtractionRecord[];
1448
+ private extractZod;
1449
+ private collectZodConstraints;
1450
+ private extractPydantic;
1451
+ private collectPydanticConstraints;
1452
+ private extractGoValidate;
1453
+ private collectGoValidateTags;
1454
+ private extractRustValidate;
1455
+ private collectRustValidateAttrs;
1456
+ private extractBeanValidation;
1457
+ private findJavaClasses;
1458
+ private findClosingBrace;
1459
+ private collectBeanConstraints;
1460
+ }
1461
+
1462
+ /**
1463
+ * Extracts API route definitions revealing the domain model.
1464
+ * Finds Express/Hono routes (TS/JS), FastAPI/Flask decorators (Python),
1465
+ * Gin/Echo/http handlers (Go), Actix macros (Rust), Spring annotations (Java).
1466
+ */
1467
+ declare class ApiPathExtractor implements SignalExtractor {
1468
+ readonly name = "api-paths";
1469
+ readonly supportedExtensions: string[];
1470
+ extract(content: string, filePath: string, language: Language): ExtractionRecord[];
1471
+ private extractJsTs;
1472
+ private extractPython;
1473
+ private extractGo;
1474
+ private extractRust;
1475
+ private extractJava;
1476
+ }
1477
+
1478
+ /** All built-in code signal extractors. */
1479
+ declare const ALL_EXTRACTORS: readonly SignalExtractor[];
1480
+ /** Create an ExtractionRunner with all built-in extractors. */
1481
+ declare function createExtractionRunner(): ExtractionRunner;
1482
+
954
1483
  declare class DesignIngestor {
955
1484
  private readonly store;
956
1485
  constructor(store: GraphStore);
@@ -1171,6 +1700,6 @@ declare class CascadeSimulator {
1171
1700
  private buildResult;
1172
1701
  }
1173
1702
 
1174
- declare const VERSION = "0.4.1";
1703
+ declare const VERSION = "0.4.3";
1175
1704
 
1176
- export { type AnomalyDetectionOptions, type AnomalyReport, type ArticulationPoint, type AskGraphResult, type AssembledContext, Assembler, CIConnector, CURRENT_SCHEMA_VERSION, type CascadeLayer, type CascadeNode, type CascadeResult, type CascadeSimulationOptions, CascadeSimulator, type ClassificationResult, CodeIngestor, CompositeProbabilityStrategy, type ConflictDetail, type ConflictPrediction, ConflictPredictor, type ConflictSeverity, ConfluenceConnector, type ConnectorConfig, ContextQL, type ContextQLParams, type ContextQLResult, DesignConstraintAdapter, DesignIngestor, type DesignStrictness, type DesignViolation, EDGE_TYPES, type EdgeQuery, type EdgeType, EntityExtractor, EntityResolver, FusionLayer, type FusionResult, GitIngestor, type GitRunner, GraphAnomalyAdapter, type GraphBudget, GraphComplexityAdapter, type GraphComplexityHotspot, type GraphComplexityResult, type GraphConnector, GraphConstraintAdapter, GraphCouplingAdapter, type GraphCouplingFileData, type GraphCouplingResult, type GraphCoverageReport, type GraphDeadCodeData, type GraphDependencyData, type GraphDriftData, type GraphEdge, GraphEdgeSchema, GraphEntropyAdapter, GraphFeedbackAdapter, type GraphFilterResult, type GraphHarnessCheckData, type GraphImpactData, type GraphLayerViolation, type GraphMetadata, type GraphNode, GraphNodeSchema, type GraphSnapshotSummary, GraphStore, type HttpClient, INTENTS, type ImpactGroups, type IndependenceCheckParams, type IndependenceResult, type IngestResult, type Intent, IntentClassifier, JiraConnector, KnowledgeIngestor, type LinkResult, NODE_TYPES, type NodeCategory, type NodeQuery, type NodeType, OBSERVABILITY_TYPES, type OverlapDetail, type PairResult, type ProbabilityStrategy, type ProjectionSpec, type RequirementCoverage, RequirementIngestor, type ResolvedEntity, ResponseFormatter, SlackConnector, type SourceLocation, type StatisticalOutlier, SyncManager, type SyncMetadata, type TaskDefinition, TaskIndependenceAnalyzer, TopologicalLinker, type TraceabilityOptions, type TraceabilityResult, type TracedFile, VERSION, type VectorSearchResult, VectorStore, askGraph, classifyNodeCategory, groupNodesByImpact, linkToCode, loadGraph, project, queryTraceability, saveGraph };
1705
+ export { ALL_EXTRACTORS, type AggregateResult, type AnomalyDetectionOptions, type AnomalyReport, ApiPathExtractor, type ArticulationPoint, type AskGraphResult, type AssembledContext, Assembler, BusinessKnowledgeIngestor, CIConnector, CURRENT_SCHEMA_VERSION, type PackedEnvelope as CacheableEnvelope, type CascadeLayer, type CascadeNode, type CascadeResult, type CascadeSimulationOptions, CascadeSimulator, type ClassificationResult, CodeIngestor, CompositeProbabilityStrategy, type ConflictDetail, type ConflictPrediction, ConflictPredictor, type ConflictSeverity, type ConflictType, ConfluenceConnector, type ConnectorConfig, ContextQL, type ContextQLParams, type ContextQLResult, type Contradiction, ContradictionDetector, type ContradictionEntry, type ContradictionResult, type CoverageReport, CoverageScorer, D2Parser, DesignConstraintAdapter, DesignIngestor, type DesignStrictness, type DesignViolation, type DetectedElement, type DiagramEntity, type DiagramFormatParser, type DiagramParseResult, DiagramParser, type DiagramRelationship, type DomainCoverage, type DomainCoverageScore, type DriftClassification, type DriftDetector, type DriftFinding, type DriftResult, EDGE_TYPES, type EdgeQuery, type EdgeType, EntityExtractor, EntityResolver, EnumConstantExtractor, type ExtractionCounts, type ExtractionRecord, ExtractionRunner, FigmaConnector, FusionLayer, type FusionResult, type GapReport, GitIngestor, type GitRunner, GraphAnomalyAdapter, type GraphBudget, GraphComplexityAdapter, type GraphComplexityHotspot, type GraphComplexityResult, type GraphConnector, GraphConstraintAdapter, GraphCouplingAdapter, type GraphCouplingFileData, type GraphCouplingResult, type GraphCoverageReport, type GraphDeadCodeData, type GraphDependencyData, type GraphDriftData, type GraphEdge, GraphEdgeSchema, GraphEntropyAdapter, GraphFeedbackAdapter, type GraphFilterResult, type GraphHarnessCheckData, type GraphImpactData, type GraphLayerViolation, type GraphMetadata, type GraphNode, GraphNodeSchema, type GraphSnapshotSummary, type GraphStabilityTier, GraphStore, type HttpClient, INTENTS, ImageAnalysisExtractor, type ImageAnalysisExtractorOptions, type AnalysisProvider as ImageAnalysisProvider, type ImageAnalysisResult, type ImpactGroups, type IndependenceCheckParams, type IndependenceResult, type IngestResult, type Intent, IntentClassifier, JiraConnector, KnowledgeIngestor, type KnowledgePipelineOptions, type KnowledgePipelineResult, KnowledgePipelineRunner, type KnowledgeSnapshot, type KnowledgeSnapshotEntry, KnowledgeStagingAggregator, type Language, type LinkResult, MermaidParser, MiroConnector, NODE_STABILITY, NODE_TYPES, type NodeCategory, type NodeQuery, type NodeType, OBSERVABILITY_TYPES, type OverlapDetail, PackedSummaryCache, type PairResult, PlantUmlParser, type ProbabilityStrategy, type ProjectionSpec, type RequirementCoverage, RequirementIngestor, type ResolvedEntity, ResponseFormatter, type SignalExtractor, SlackConnector, type SourceLocation, type StagedEntry, type StatisticalOutlier, StructuralDriftDetector, SyncManager, type SyncMetadata, type TaskDefinition, TaskIndependenceAnalyzer, TestDescriptionExtractor, TopologicalLinker, type TraceabilityOptions, type TraceabilityResult, type TracedFile, VERSION, ValidationRuleExtractor, type VectorSearchResult, VectorStore, askGraph, classifyNodeCategory, createExtractionRunner, detectLanguage, groupNodesByImpact, linkToCode, loadGraph, normalizeIntent, project, queryTraceability, saveGraph };