@harness-engineering/graph 0.6.0 → 0.7.1

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
@@ -512,6 +512,33 @@ declare class RequirementIngestor {
512
512
  private linkByKeywordOverlap;
513
513
  }
514
514
 
515
+ /**
516
+ * Domain inference for graph nodes.
517
+ *
518
+ * Precedence (highest to lowest):
519
+ * 1. node.metadata.domain (explicit)
520
+ * 2. extraPatterns (config-provided)
521
+ * 3. DEFAULT_PATTERNS (built-in)
522
+ * 4. Generic first non-blocklisted path segment
523
+ * 5. KnowledgeLinker connector source (path-less facts)
524
+ * 6. 'unknown'
525
+ *
526
+ * Pattern format: 'prefix/<dir>'. Single-segment prefix only. <dir> captures
527
+ * the segment immediately after the prefix.
528
+ */
529
+ interface DomainInferenceOptions {
530
+ /** Additional patterns beyond the built-in defaults. Format: 'prefix/<dir>'. */
531
+ extraPatterns?: readonly string[];
532
+ /** Additional blocklisted segments beyond the built-in defaults. */
533
+ extraBlocklist?: readonly string[];
534
+ }
535
+ declare const DEFAULT_PATTERNS: readonly string[];
536
+ declare const DEFAULT_BLOCKLIST: ReadonlySet<string>;
537
+ declare function inferDomain(node: {
538
+ path?: string;
539
+ metadata?: Record<string, unknown>;
540
+ }, options?: DomainInferenceOptions): string;
541
+
515
542
  type DriftClassification = 'new' | 'drifted' | 'stale' | 'contradicting';
516
543
  interface KnowledgeSnapshotEntry {
517
544
  readonly id: string;
@@ -591,7 +618,8 @@ interface AggregateResult {
591
618
  }
592
619
  declare class KnowledgeStagingAggregator {
593
620
  private readonly projectDir;
594
- constructor(projectDir: string);
621
+ private readonly inferenceOptions;
622
+ constructor(projectDir: string, inferenceOptions?: DomainInferenceOptions);
595
623
  aggregate(extractorResults: readonly StagedEntry[], linkerResults: readonly StagedEntry[], diagramResults: readonly StagedEntry[]): Promise<AggregateResult>;
596
624
  private extractDocName;
597
625
  generateGapReport(knowledgeDir: string, store?: GraphStore): Promise<GapReport>;
@@ -691,8 +719,9 @@ interface CoverageReport {
691
719
  readonly generatedAt: string;
692
720
  }
693
721
  declare class CoverageScorer {
722
+ private readonly inferenceOptions;
723
+ constructor(inferenceOptions?: DomainInferenceOptions);
694
724
  score(store: GraphStore): CoverageReport;
695
- private domainFromPath;
696
725
  }
697
726
 
698
727
  /**
@@ -725,7 +754,8 @@ interface SkippedEntry {
725
754
  }
726
755
  declare class KnowledgeDocMaterializer {
727
756
  private readonly store;
728
- constructor(store: GraphStore);
757
+ private readonly inferenceOptions;
758
+ constructor(store: GraphStore, inferenceOptions?: DomainInferenceOptions);
729
759
  materialize(gapEntries: readonly GapEntry[], options: MaterializeOptions): Promise<MaterializeResult>;
730
760
  private resolveEntry;
731
761
  inferDomain(node: GraphNode): string | null;
@@ -758,6 +788,13 @@ interface KnowledgePipelineOptions {
758
788
  readonly analyzeImages?: boolean;
759
789
  readonly analysisProvider?: AnalysisProvider;
760
790
  readonly imagePaths?: readonly string[];
791
+ /**
792
+ * Domain-inference overrides threaded into KnowledgeStagingAggregator,
793
+ * CoverageScorer, and KnowledgeDocMaterializer. Sourced by the CLI from
794
+ * `harness.config.json#knowledge.domainPatterns` (→ extraPatterns) and
795
+ * `knowledge.domainBlocklist` (→ extraBlocklist). Defaults to {} when absent.
796
+ */
797
+ readonly inferenceOptions?: DomainInferenceOptions;
761
798
  }
762
799
  interface ExtractionCounts {
763
800
  readonly codeSignals: number;
@@ -782,6 +819,8 @@ interface KnowledgePipelineResult {
782
819
  declare class KnowledgePipelineRunner {
783
820
  private readonly store;
784
821
  constructor(store: GraphStore);
822
+ /** Resolved per-`run()` inference options. Set on entry to `run()`. */
823
+ private inferenceOptions;
785
824
  run(options: KnowledgePipelineOptions): Promise<KnowledgePipelineResult>;
786
825
  /** Run the remediation convergence loop; returns iteration count and accumulated materialization. */
787
826
  private runRemediationLoop;
@@ -1827,4 +1866,4 @@ declare class CascadeSimulator {
1827
1866
 
1828
1867
  declare const VERSION = "0.6.0";
1829
1868
 
1830
- 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, DecisionIngestor, 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 GapEntry, 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, KnowledgeDocMaterializer, KnowledgeIngestor, type KnowledgePipelineOptions, type KnowledgePipelineResult, KnowledgePipelineRunner, type KnowledgeSnapshot, type KnowledgeSnapshotEntry, KnowledgeStagingAggregator, type Language, type LinkResult, type LoadGraphResult, type MaterializeOptions, type MaterializeResult, type MaterializedDoc, 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, type SkippedEntry, 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 };
1869
+ 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, DEFAULT_BLOCKLIST, DEFAULT_PATTERNS, DecisionIngestor, DesignConstraintAdapter, DesignIngestor, type DesignStrictness, type DesignViolation, type DetectedElement, type DiagramEntity, type DiagramFormatParser, type DiagramParseResult, DiagramParser, type DiagramRelationship, type DomainCoverage, type DomainCoverageScore, type DomainInferenceOptions, 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 GapEntry, 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, KnowledgeDocMaterializer, KnowledgeIngestor, type KnowledgePipelineOptions, type KnowledgePipelineResult, KnowledgePipelineRunner, type KnowledgeSnapshot, type KnowledgeSnapshotEntry, KnowledgeStagingAggregator, type Language, type LinkResult, type LoadGraphResult, type MaterializeOptions, type MaterializeResult, type MaterializedDoc, 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, type SkippedEntry, 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, inferDomain, linkToCode, loadGraph, normalizeIntent, project, queryTraceability, saveGraph };
package/dist/index.d.ts CHANGED
@@ -512,6 +512,33 @@ declare class RequirementIngestor {
512
512
  private linkByKeywordOverlap;
513
513
  }
514
514
 
515
+ /**
516
+ * Domain inference for graph nodes.
517
+ *
518
+ * Precedence (highest to lowest):
519
+ * 1. node.metadata.domain (explicit)
520
+ * 2. extraPatterns (config-provided)
521
+ * 3. DEFAULT_PATTERNS (built-in)
522
+ * 4. Generic first non-blocklisted path segment
523
+ * 5. KnowledgeLinker connector source (path-less facts)
524
+ * 6. 'unknown'
525
+ *
526
+ * Pattern format: 'prefix/<dir>'. Single-segment prefix only. <dir> captures
527
+ * the segment immediately after the prefix.
528
+ */
529
+ interface DomainInferenceOptions {
530
+ /** Additional patterns beyond the built-in defaults. Format: 'prefix/<dir>'. */
531
+ extraPatterns?: readonly string[];
532
+ /** Additional blocklisted segments beyond the built-in defaults. */
533
+ extraBlocklist?: readonly string[];
534
+ }
535
+ declare const DEFAULT_PATTERNS: readonly string[];
536
+ declare const DEFAULT_BLOCKLIST: ReadonlySet<string>;
537
+ declare function inferDomain(node: {
538
+ path?: string;
539
+ metadata?: Record<string, unknown>;
540
+ }, options?: DomainInferenceOptions): string;
541
+
515
542
  type DriftClassification = 'new' | 'drifted' | 'stale' | 'contradicting';
516
543
  interface KnowledgeSnapshotEntry {
517
544
  readonly id: string;
@@ -591,7 +618,8 @@ interface AggregateResult {
591
618
  }
592
619
  declare class KnowledgeStagingAggregator {
593
620
  private readonly projectDir;
594
- constructor(projectDir: string);
621
+ private readonly inferenceOptions;
622
+ constructor(projectDir: string, inferenceOptions?: DomainInferenceOptions);
595
623
  aggregate(extractorResults: readonly StagedEntry[], linkerResults: readonly StagedEntry[], diagramResults: readonly StagedEntry[]): Promise<AggregateResult>;
596
624
  private extractDocName;
597
625
  generateGapReport(knowledgeDir: string, store?: GraphStore): Promise<GapReport>;
@@ -691,8 +719,9 @@ interface CoverageReport {
691
719
  readonly generatedAt: string;
692
720
  }
693
721
  declare class CoverageScorer {
722
+ private readonly inferenceOptions;
723
+ constructor(inferenceOptions?: DomainInferenceOptions);
694
724
  score(store: GraphStore): CoverageReport;
695
- private domainFromPath;
696
725
  }
697
726
 
698
727
  /**
@@ -725,7 +754,8 @@ interface SkippedEntry {
725
754
  }
726
755
  declare class KnowledgeDocMaterializer {
727
756
  private readonly store;
728
- constructor(store: GraphStore);
757
+ private readonly inferenceOptions;
758
+ constructor(store: GraphStore, inferenceOptions?: DomainInferenceOptions);
729
759
  materialize(gapEntries: readonly GapEntry[], options: MaterializeOptions): Promise<MaterializeResult>;
730
760
  private resolveEntry;
731
761
  inferDomain(node: GraphNode): string | null;
@@ -758,6 +788,13 @@ interface KnowledgePipelineOptions {
758
788
  readonly analyzeImages?: boolean;
759
789
  readonly analysisProvider?: AnalysisProvider;
760
790
  readonly imagePaths?: readonly string[];
791
+ /**
792
+ * Domain-inference overrides threaded into KnowledgeStagingAggregator,
793
+ * CoverageScorer, and KnowledgeDocMaterializer. Sourced by the CLI from
794
+ * `harness.config.json#knowledge.domainPatterns` (→ extraPatterns) and
795
+ * `knowledge.domainBlocklist` (→ extraBlocklist). Defaults to {} when absent.
796
+ */
797
+ readonly inferenceOptions?: DomainInferenceOptions;
761
798
  }
762
799
  interface ExtractionCounts {
763
800
  readonly codeSignals: number;
@@ -782,6 +819,8 @@ interface KnowledgePipelineResult {
782
819
  declare class KnowledgePipelineRunner {
783
820
  private readonly store;
784
821
  constructor(store: GraphStore);
822
+ /** Resolved per-`run()` inference options. Set on entry to `run()`. */
823
+ private inferenceOptions;
785
824
  run(options: KnowledgePipelineOptions): Promise<KnowledgePipelineResult>;
786
825
  /** Run the remediation convergence loop; returns iteration count and accumulated materialization. */
787
826
  private runRemediationLoop;
@@ -1827,4 +1866,4 @@ declare class CascadeSimulator {
1827
1866
 
1828
1867
  declare const VERSION = "0.6.0";
1829
1868
 
1830
- 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, DecisionIngestor, 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 GapEntry, 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, KnowledgeDocMaterializer, KnowledgeIngestor, type KnowledgePipelineOptions, type KnowledgePipelineResult, KnowledgePipelineRunner, type KnowledgeSnapshot, type KnowledgeSnapshotEntry, KnowledgeStagingAggregator, type Language, type LinkResult, type LoadGraphResult, type MaterializeOptions, type MaterializeResult, type MaterializedDoc, 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, type SkippedEntry, 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 };
1869
+ 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, DEFAULT_BLOCKLIST, DEFAULT_PATTERNS, DecisionIngestor, DesignConstraintAdapter, DesignIngestor, type DesignStrictness, type DesignViolation, type DetectedElement, type DiagramEntity, type DiagramFormatParser, type DiagramParseResult, DiagramParser, type DiagramRelationship, type DomainCoverage, type DomainCoverageScore, type DomainInferenceOptions, 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 GapEntry, 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, KnowledgeDocMaterializer, KnowledgeIngestor, type KnowledgePipelineOptions, type KnowledgePipelineResult, KnowledgePipelineRunner, type KnowledgeSnapshot, type KnowledgeSnapshotEntry, KnowledgeStagingAggregator, type Language, type LinkResult, type LoadGraphResult, type MaterializeOptions, type MaterializeResult, type MaterializedDoc, 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, type SkippedEntry, 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, inferDomain, linkToCode, loadGraph, normalizeIntent, project, queryTraceability, saveGraph };
package/dist/index.js CHANGED
@@ -45,6 +45,8 @@ __export(index_exports, {
45
45
  ContradictionDetector: () => ContradictionDetector,
46
46
  CoverageScorer: () => CoverageScorer,
47
47
  D2Parser: () => D2Parser,
48
+ DEFAULT_BLOCKLIST: () => DEFAULT_BLOCKLIST,
49
+ DEFAULT_PATTERNS: () => DEFAULT_PATTERNS,
48
50
  DecisionIngestor: () => DecisionIngestor,
49
51
  DesignConstraintAdapter: () => DesignConstraintAdapter,
50
52
  DesignIngestor: () => DesignIngestor,
@@ -97,6 +99,7 @@ __export(index_exports, {
97
99
  createExtractionRunner: () => createExtractionRunner,
98
100
  detectLanguage: () => detectLanguage,
99
101
  groupNodesByImpact: () => groupNodesByImpact,
102
+ inferDomain: () => inferDomain,
100
103
  linkToCode: () => linkToCode,
101
104
  loadGraph: () => loadGraph,
102
105
  normalizeIntent: () => normalizeIntent,
@@ -2049,6 +2052,7 @@ var BusinessKnowledgeIngestor = class {
2049
2052
  content: body.trim(),
2050
2053
  metadata: {
2051
2054
  domain,
2055
+ ...frontmatter.source && { source: frontmatter.source },
2052
2056
  ...frontmatter.tags && { tags: frontmatter.tags },
2053
2057
  ...frontmatter.related && { related: frontmatter.related }
2054
2058
  }
@@ -2496,6 +2500,88 @@ var RequirementIngestor = class {
2496
2500
  }
2497
2501
  };
2498
2502
 
2503
+ // src/ingest/domain-inference.ts
2504
+ var DEFAULT_PATTERNS = [
2505
+ "packages/<dir>",
2506
+ "apps/<dir>",
2507
+ "services/<dir>",
2508
+ "src/<dir>",
2509
+ "lib/<dir>"
2510
+ ];
2511
+ var DEFAULT_BLOCKLIST = /* @__PURE__ */ new Set([
2512
+ "node_modules",
2513
+ ".harness",
2514
+ "dist",
2515
+ "build",
2516
+ ".git",
2517
+ "coverage",
2518
+ ".next",
2519
+ ".turbo",
2520
+ ".cache",
2521
+ "out",
2522
+ "tmp"
2523
+ ]);
2524
+ var CODE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
2525
+ function matchPattern(filePath, pattern) {
2526
+ const patternParts = pattern.split("/").filter((s) => s.length > 0);
2527
+ if (patternParts.length !== 2 || patternParts[1] !== "<dir>") {
2528
+ return null;
2529
+ }
2530
+ const prefix = patternParts[0];
2531
+ const pathParts = filePath.split("/").filter((s) => s.length > 0);
2532
+ if (pathParts.length < 2) return null;
2533
+ if (pathParts[0] !== prefix) return null;
2534
+ let dir = pathParts[1];
2535
+ if (dir.length === 0) return null;
2536
+ if (CODE_EXTENSIONS.some((ext) => dir.endsWith(ext))) {
2537
+ const dotIdx = dir.lastIndexOf(".");
2538
+ if (dotIdx > 0) dir = dir.slice(0, dotIdx);
2539
+ }
2540
+ if (dir.length === 0) return null;
2541
+ return dir;
2542
+ }
2543
+ function inferDomain(node, options = {}) {
2544
+ if (node.metadata?.domain && typeof node.metadata.domain === "string" && node.metadata.domain.length > 0) {
2545
+ return node.metadata.domain;
2546
+ }
2547
+ const filePath = typeof node.path === "string" ? node.path : "";
2548
+ const blocklist = new Set(DEFAULT_BLOCKLIST);
2549
+ if (options.extraBlocklist) {
2550
+ for (const seg of options.extraBlocklist) {
2551
+ if (seg && seg.length > 0) blocklist.add(seg);
2552
+ }
2553
+ }
2554
+ if (filePath.length > 0) {
2555
+ const extraPatterns = options.extraPatterns ?? [];
2556
+ for (const pattern of extraPatterns) {
2557
+ const dir = matchPattern(filePath, pattern);
2558
+ if (dir !== null) {
2559
+ if (blocklist.has(dir)) return "unknown";
2560
+ return dir;
2561
+ }
2562
+ }
2563
+ for (const pattern of DEFAULT_PATTERNS) {
2564
+ const dir = matchPattern(filePath, pattern);
2565
+ if (dir !== null) {
2566
+ if (blocklist.has(dir)) return "unknown";
2567
+ return dir;
2568
+ }
2569
+ }
2570
+ const segments = filePath.split("/").filter((s) => s.length > 0);
2571
+ if (segments.length > 0) {
2572
+ const first = segments[0];
2573
+ if (!blocklist.has(first)) return first;
2574
+ }
2575
+ }
2576
+ const source = node.metadata?.source;
2577
+ if (source === "knowledge-linker" || source === "connector") {
2578
+ const connector = node.metadata?.connectorName;
2579
+ if (typeof connector === "string" && connector.length > 0) return connector;
2580
+ return "general";
2581
+ }
2582
+ return "unknown";
2583
+ }
2584
+
2499
2585
  // src/ingest/KnowledgePipelineRunner.ts
2500
2586
  var fs11 = __toESM(require("fs/promises"));
2501
2587
  var path12 = __toESM(require("path"));
@@ -3308,10 +3394,12 @@ var BUSINESS_NODE_TYPES = [
3308
3394
  "business_fact"
3309
3395
  ];
3310
3396
  var KnowledgeStagingAggregator = class {
3311
- constructor(projectDir) {
3397
+ constructor(projectDir, inferenceOptions = {}) {
3312
3398
  this.projectDir = projectDir;
3399
+ this.inferenceOptions = inferenceOptions;
3313
3400
  }
3314
3401
  projectDir;
3402
+ inferenceOptions;
3315
3403
  async aggregate(extractorResults, linkerResults, diagramResults) {
3316
3404
  const all = [...extractorResults, ...linkerResults, ...diagramResults];
3317
3405
  const byHash = /* @__PURE__ */ new Map();
@@ -3380,7 +3468,7 @@ var KnowledgeStagingAggregator = class {
3380
3468
  for (const nodeType of BUSINESS_NODE_TYPES) {
3381
3469
  const nodes = store.findNodes({ type: nodeType });
3382
3470
  for (const node of nodes) {
3383
- const domain = node.metadata?.domain ?? "unknown";
3471
+ const domain = inferDomain(node, this.inferenceOptions);
3384
3472
  const list = extractedByDomain.get(domain) ?? [];
3385
3473
  list.push(node);
3386
3474
  extractedByDomain.set(domain, list);
@@ -5058,10 +5146,10 @@ function toGrade(score) {
5058
5146
  if (score >= 20) return "D";
5059
5147
  return "F";
5060
5148
  }
5061
- function groupByDomain(nodes, fallback) {
5149
+ function groupByDomain(nodes, _fallback, options = {}) {
5062
5150
  const map = /* @__PURE__ */ new Map();
5063
5151
  for (const node of nodes) {
5064
- const domain = node.metadata.domain ?? fallback(node);
5152
+ const domain = inferDomain(node, options);
5065
5153
  const group = map.get(domain) ?? [];
5066
5154
  group.push(node);
5067
5155
  map.set(domain, group);
@@ -5117,11 +5205,15 @@ function scoreDomain(domain, knEntries, codeEntries, store) {
5117
5205
  };
5118
5206
  }
5119
5207
  var CoverageScorer = class {
5208
+ constructor(inferenceOptions = {}) {
5209
+ this.inferenceOptions = inferenceOptions;
5210
+ }
5211
+ inferenceOptions;
5120
5212
  score(store) {
5121
5213
  const knowledgeNodes = KNOWLEDGE_TYPES.flatMap((t) => store.findNodes({ type: t }));
5122
- const domainMap = groupByDomain(knowledgeNodes, () => "unclassified");
5214
+ const domainMap = groupByDomain(knowledgeNodes, void 0, this.inferenceOptions);
5123
5215
  const codeNodes = CODE_TYPES2.flatMap((t) => store.findNodes({ type: t }));
5124
- const codeDomains = groupByDomain(codeNodes, (n) => this.domainFromPath(n.path));
5216
+ const codeDomains = groupByDomain(codeNodes, void 0, this.inferenceOptions);
5125
5217
  const allDomains = /* @__PURE__ */ new Set([...domainMap.keys(), ...codeDomains.keys()]);
5126
5218
  const domains = [];
5127
5219
  for (const domain of allDomains) {
@@ -5137,15 +5229,6 @@ var CoverageScorer = class {
5137
5229
  generatedAt: (/* @__PURE__ */ new Date()).toISOString()
5138
5230
  };
5139
5231
  }
5140
- domainFromPath(filePath) {
5141
- if (!filePath) return "unclassified";
5142
- const parts = filePath.split("/");
5143
- const pkgIdx = parts.indexOf("packages");
5144
- if (pkgIdx >= 0 && parts[pkgIdx + 1]) return parts[pkgIdx + 1];
5145
- const srcIdx = parts.indexOf("src");
5146
- if (srcIdx >= 0 && parts[srcIdx + 1]) return parts[srcIdx + 1];
5147
- return parts[0] ?? "unclassified";
5148
- }
5149
5232
  };
5150
5233
 
5151
5234
  // src/ingest/KnowledgeDocMaterializer.ts
@@ -5161,10 +5244,12 @@ var VALID_BUSINESS_TYPES = /* @__PURE__ */ new Set([
5161
5244
  var DEFAULT_MAX_DOCS = 50;
5162
5245
  var MAX_COLLISION_SUFFIX = 10;
5163
5246
  var KnowledgeDocMaterializer = class {
5164
- constructor(store) {
5247
+ constructor(store, inferenceOptions = {}) {
5165
5248
  this.store = store;
5249
+ this.inferenceOptions = inferenceOptions;
5166
5250
  }
5167
5251
  store;
5252
+ inferenceOptions;
5168
5253
  async materialize(gapEntries, options) {
5169
5254
  const maxDocs = options.maxDocs ?? DEFAULT_MAX_DOCS;
5170
5255
  const created = [];
@@ -5220,21 +5305,8 @@ var KnowledgeDocMaterializer = class {
5220
5305
  return { node, domain, domainDir, nameKey };
5221
5306
  }
5222
5307
  inferDomain(node) {
5223
- if (node.metadata?.domain && typeof node.metadata.domain === "string") {
5224
- return node.metadata.domain;
5225
- }
5226
- if (node.path) {
5227
- const pkgMatch = node.path.match(/^packages\/([^/]+)/);
5228
- if (pkgMatch) return pkgMatch[1];
5229
- const srcMatch = node.path.match(/^src\/([^/]+)/);
5230
- if (srcMatch) return srcMatch[1];
5231
- }
5232
- if (node.metadata?.source === "knowledge-linker" || node.metadata?.source === "connector") {
5233
- const connector = node.metadata.connectorName;
5234
- if (typeof connector === "string") return connector;
5235
- return "general";
5236
- }
5237
- return null;
5308
+ const result = inferDomain(node, this.inferenceOptions);
5309
+ return result === "unknown" ? null : result;
5238
5310
  }
5239
5311
  generateFilename(name) {
5240
5312
  const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
@@ -5264,6 +5336,10 @@ var KnowledgeDocMaterializer = class {
5264
5336
  const mappedType = this.mapNodeType(node);
5265
5337
  const sanitize = (s) => s.replace(/[\n\r]/g, " ").replace(/:/g, "-");
5266
5338
  const lines = ["---", `type: ${sanitize(mappedType)}`, `domain: ${sanitize(domain)}`];
5339
+ const source = node.metadata?.source;
5340
+ if (typeof source === "string" && source.length > 0) {
5341
+ lines.push(`source: ${sanitize(source)}`);
5342
+ }
5267
5343
  const tags = node.metadata?.tags;
5268
5344
  if (Array.isArray(tags) && tags.length > 0) {
5269
5345
  lines.push(`tags: [${tags.map((t) => sanitize(String(t))).join(", ")}]`);
@@ -5328,7 +5404,10 @@ var KnowledgePipelineRunner = class {
5328
5404
  this.store = store;
5329
5405
  }
5330
5406
  store;
5407
+ /** Resolved per-`run()` inference options. Set on entry to `run()`. */
5408
+ inferenceOptions = {};
5331
5409
  async run(options) {
5410
+ this.inferenceOptions = options.inferenceOptions ?? {};
5332
5411
  const remediations = [];
5333
5412
  const preSnapshot = this.buildSnapshot(options.domain);
5334
5413
  const extraction = await this.extract(options);
@@ -5336,7 +5415,7 @@ var KnowledgePipelineRunner = class {
5336
5415
  let driftResult = this.reconcile(preSnapshot, postSnapshot);
5337
5416
  const contradictions = new ContradictionDetector().detect(this.store);
5338
5417
  let gapReport = await this.detect(options);
5339
- const coverage = new CoverageScorer().score(this.store);
5418
+ const coverage = new CoverageScorer(this.inferenceOptions).score(this.store);
5340
5419
  let materialization;
5341
5420
  let iterations = 1;
5342
5421
  if (options.fix) {
@@ -5499,7 +5578,7 @@ var KnowledgePipelineRunner = class {
5499
5578
  // ── Phase 3: DETECT ───────────────────────────────────────────────────────
5500
5579
  async detect(options) {
5501
5580
  const knowledgeDir = path12.join(options.projectDir, "docs", "knowledge");
5502
- const aggregator = new KnowledgeStagingAggregator(options.projectDir);
5581
+ const aggregator = new KnowledgeStagingAggregator(options.projectDir, this.inferenceOptions);
5503
5582
  const gapReport = await aggregator.generateGapReport(knowledgeDir, this.store);
5504
5583
  await aggregator.writeGapReport(gapReport);
5505
5584
  return gapReport;
@@ -5527,7 +5606,7 @@ var KnowledgePipelineRunner = class {
5527
5606
  const allGapEntries = gapReport.domains.flatMap((d) => d.gapEntries);
5528
5607
  const materializable = allGapEntries.filter((e) => e.hasContent);
5529
5608
  if (materializable.length > 0) {
5530
- const materializer = new KnowledgeDocMaterializer(this.store);
5609
+ const materializer = new KnowledgeDocMaterializer(this.store, this.inferenceOptions);
5531
5610
  const matResult = await materializer.materialize(materializable, {
5532
5611
  projectDir: options.projectDir,
5533
5612
  dryRun: false
@@ -5553,7 +5632,7 @@ var KnowledgePipelineRunner = class {
5553
5632
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
5554
5633
  }));
5555
5634
  if (stagedEntries.length > 0) {
5556
- const aggregator = new KnowledgeStagingAggregator(options.projectDir);
5635
+ const aggregator = new KnowledgeStagingAggregator(options.projectDir, this.inferenceOptions);
5557
5636
  await aggregator.aggregate(stagedEntries, [], []);
5558
5637
  }
5559
5638
  }
@@ -9527,6 +9606,8 @@ var VERSION = "0.6.0";
9527
9606
  ContradictionDetector,
9528
9607
  CoverageScorer,
9529
9608
  D2Parser,
9609
+ DEFAULT_BLOCKLIST,
9610
+ DEFAULT_PATTERNS,
9530
9611
  DecisionIngestor,
9531
9612
  DesignConstraintAdapter,
9532
9613
  DesignIngestor,
@@ -9579,6 +9660,7 @@ var VERSION = "0.6.0";
9579
9660
  createExtractionRunner,
9580
9661
  detectLanguage,
9581
9662
  groupNodesByImpact,
9663
+ inferDomain,
9582
9664
  linkToCode,
9583
9665
  loadGraph,
9584
9666
  normalizeIntent,
package/dist/index.mjs CHANGED
@@ -1941,6 +1941,7 @@ var BusinessKnowledgeIngestor = class {
1941
1941
  content: body.trim(),
1942
1942
  metadata: {
1943
1943
  domain,
1944
+ ...frontmatter.source && { source: frontmatter.source },
1944
1945
  ...frontmatter.tags && { tags: frontmatter.tags },
1945
1946
  ...frontmatter.related && { related: frontmatter.related }
1946
1947
  }
@@ -2388,6 +2389,88 @@ var RequirementIngestor = class {
2388
2389
  }
2389
2390
  };
2390
2391
 
2392
+ // src/ingest/domain-inference.ts
2393
+ var DEFAULT_PATTERNS = [
2394
+ "packages/<dir>",
2395
+ "apps/<dir>",
2396
+ "services/<dir>",
2397
+ "src/<dir>",
2398
+ "lib/<dir>"
2399
+ ];
2400
+ var DEFAULT_BLOCKLIST = /* @__PURE__ */ new Set([
2401
+ "node_modules",
2402
+ ".harness",
2403
+ "dist",
2404
+ "build",
2405
+ ".git",
2406
+ "coverage",
2407
+ ".next",
2408
+ ".turbo",
2409
+ ".cache",
2410
+ "out",
2411
+ "tmp"
2412
+ ]);
2413
+ var CODE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
2414
+ function matchPattern(filePath, pattern) {
2415
+ const patternParts = pattern.split("/").filter((s) => s.length > 0);
2416
+ if (patternParts.length !== 2 || patternParts[1] !== "<dir>") {
2417
+ return null;
2418
+ }
2419
+ const prefix = patternParts[0];
2420
+ const pathParts = filePath.split("/").filter((s) => s.length > 0);
2421
+ if (pathParts.length < 2) return null;
2422
+ if (pathParts[0] !== prefix) return null;
2423
+ let dir = pathParts[1];
2424
+ if (dir.length === 0) return null;
2425
+ if (CODE_EXTENSIONS.some((ext) => dir.endsWith(ext))) {
2426
+ const dotIdx = dir.lastIndexOf(".");
2427
+ if (dotIdx > 0) dir = dir.slice(0, dotIdx);
2428
+ }
2429
+ if (dir.length === 0) return null;
2430
+ return dir;
2431
+ }
2432
+ function inferDomain(node, options = {}) {
2433
+ if (node.metadata?.domain && typeof node.metadata.domain === "string" && node.metadata.domain.length > 0) {
2434
+ return node.metadata.domain;
2435
+ }
2436
+ const filePath = typeof node.path === "string" ? node.path : "";
2437
+ const blocklist = new Set(DEFAULT_BLOCKLIST);
2438
+ if (options.extraBlocklist) {
2439
+ for (const seg of options.extraBlocklist) {
2440
+ if (seg && seg.length > 0) blocklist.add(seg);
2441
+ }
2442
+ }
2443
+ if (filePath.length > 0) {
2444
+ const extraPatterns = options.extraPatterns ?? [];
2445
+ for (const pattern of extraPatterns) {
2446
+ const dir = matchPattern(filePath, pattern);
2447
+ if (dir !== null) {
2448
+ if (blocklist.has(dir)) return "unknown";
2449
+ return dir;
2450
+ }
2451
+ }
2452
+ for (const pattern of DEFAULT_PATTERNS) {
2453
+ const dir = matchPattern(filePath, pattern);
2454
+ if (dir !== null) {
2455
+ if (blocklist.has(dir)) return "unknown";
2456
+ return dir;
2457
+ }
2458
+ }
2459
+ const segments = filePath.split("/").filter((s) => s.length > 0);
2460
+ if (segments.length > 0) {
2461
+ const first = segments[0];
2462
+ if (!blocklist.has(first)) return first;
2463
+ }
2464
+ }
2465
+ const source = node.metadata?.source;
2466
+ if (source === "knowledge-linker" || source === "connector") {
2467
+ const connector = node.metadata?.connectorName;
2468
+ if (typeof connector === "string" && connector.length > 0) return connector;
2469
+ return "general";
2470
+ }
2471
+ return "unknown";
2472
+ }
2473
+
2391
2474
  // src/ingest/KnowledgePipelineRunner.ts
2392
2475
  import * as fs11 from "fs/promises";
2393
2476
  import * as path12 from "path";
@@ -3200,10 +3283,12 @@ var BUSINESS_NODE_TYPES = [
3200
3283
  "business_fact"
3201
3284
  ];
3202
3285
  var KnowledgeStagingAggregator = class {
3203
- constructor(projectDir) {
3286
+ constructor(projectDir, inferenceOptions = {}) {
3204
3287
  this.projectDir = projectDir;
3288
+ this.inferenceOptions = inferenceOptions;
3205
3289
  }
3206
3290
  projectDir;
3291
+ inferenceOptions;
3207
3292
  async aggregate(extractorResults, linkerResults, diagramResults) {
3208
3293
  const all = [...extractorResults, ...linkerResults, ...diagramResults];
3209
3294
  const byHash = /* @__PURE__ */ new Map();
@@ -3272,7 +3357,7 @@ var KnowledgeStagingAggregator = class {
3272
3357
  for (const nodeType of BUSINESS_NODE_TYPES) {
3273
3358
  const nodes = store.findNodes({ type: nodeType });
3274
3359
  for (const node of nodes) {
3275
- const domain = node.metadata?.domain ?? "unknown";
3360
+ const domain = inferDomain(node, this.inferenceOptions);
3276
3361
  const list = extractedByDomain.get(domain) ?? [];
3277
3362
  list.push(node);
3278
3363
  extractedByDomain.set(domain, list);
@@ -4950,10 +5035,10 @@ function toGrade(score) {
4950
5035
  if (score >= 20) return "D";
4951
5036
  return "F";
4952
5037
  }
4953
- function groupByDomain(nodes, fallback) {
5038
+ function groupByDomain(nodes, _fallback, options = {}) {
4954
5039
  const map = /* @__PURE__ */ new Map();
4955
5040
  for (const node of nodes) {
4956
- const domain = node.metadata.domain ?? fallback(node);
5041
+ const domain = inferDomain(node, options);
4957
5042
  const group = map.get(domain) ?? [];
4958
5043
  group.push(node);
4959
5044
  map.set(domain, group);
@@ -5009,11 +5094,15 @@ function scoreDomain(domain, knEntries, codeEntries, store) {
5009
5094
  };
5010
5095
  }
5011
5096
  var CoverageScorer = class {
5097
+ constructor(inferenceOptions = {}) {
5098
+ this.inferenceOptions = inferenceOptions;
5099
+ }
5100
+ inferenceOptions;
5012
5101
  score(store) {
5013
5102
  const knowledgeNodes = KNOWLEDGE_TYPES.flatMap((t) => store.findNodes({ type: t }));
5014
- const domainMap = groupByDomain(knowledgeNodes, () => "unclassified");
5103
+ const domainMap = groupByDomain(knowledgeNodes, void 0, this.inferenceOptions);
5015
5104
  const codeNodes = CODE_TYPES2.flatMap((t) => store.findNodes({ type: t }));
5016
- const codeDomains = groupByDomain(codeNodes, (n) => this.domainFromPath(n.path));
5105
+ const codeDomains = groupByDomain(codeNodes, void 0, this.inferenceOptions);
5017
5106
  const allDomains = /* @__PURE__ */ new Set([...domainMap.keys(), ...codeDomains.keys()]);
5018
5107
  const domains = [];
5019
5108
  for (const domain of allDomains) {
@@ -5029,15 +5118,6 @@ var CoverageScorer = class {
5029
5118
  generatedAt: (/* @__PURE__ */ new Date()).toISOString()
5030
5119
  };
5031
5120
  }
5032
- domainFromPath(filePath) {
5033
- if (!filePath) return "unclassified";
5034
- const parts = filePath.split("/");
5035
- const pkgIdx = parts.indexOf("packages");
5036
- if (pkgIdx >= 0 && parts[pkgIdx + 1]) return parts[pkgIdx + 1];
5037
- const srcIdx = parts.indexOf("src");
5038
- if (srcIdx >= 0 && parts[srcIdx + 1]) return parts[srcIdx + 1];
5039
- return parts[0] ?? "unclassified";
5040
- }
5041
5121
  };
5042
5122
 
5043
5123
  // src/ingest/KnowledgeDocMaterializer.ts
@@ -5053,10 +5133,12 @@ var VALID_BUSINESS_TYPES = /* @__PURE__ */ new Set([
5053
5133
  var DEFAULT_MAX_DOCS = 50;
5054
5134
  var MAX_COLLISION_SUFFIX = 10;
5055
5135
  var KnowledgeDocMaterializer = class {
5056
- constructor(store) {
5136
+ constructor(store, inferenceOptions = {}) {
5057
5137
  this.store = store;
5138
+ this.inferenceOptions = inferenceOptions;
5058
5139
  }
5059
5140
  store;
5141
+ inferenceOptions;
5060
5142
  async materialize(gapEntries, options) {
5061
5143
  const maxDocs = options.maxDocs ?? DEFAULT_MAX_DOCS;
5062
5144
  const created = [];
@@ -5112,21 +5194,8 @@ var KnowledgeDocMaterializer = class {
5112
5194
  return { node, domain, domainDir, nameKey };
5113
5195
  }
5114
5196
  inferDomain(node) {
5115
- if (node.metadata?.domain && typeof node.metadata.domain === "string") {
5116
- return node.metadata.domain;
5117
- }
5118
- if (node.path) {
5119
- const pkgMatch = node.path.match(/^packages\/([^/]+)/);
5120
- if (pkgMatch) return pkgMatch[1];
5121
- const srcMatch = node.path.match(/^src\/([^/]+)/);
5122
- if (srcMatch) return srcMatch[1];
5123
- }
5124
- if (node.metadata?.source === "knowledge-linker" || node.metadata?.source === "connector") {
5125
- const connector = node.metadata.connectorName;
5126
- if (typeof connector === "string") return connector;
5127
- return "general";
5128
- }
5129
- return null;
5197
+ const result = inferDomain(node, this.inferenceOptions);
5198
+ return result === "unknown" ? null : result;
5130
5199
  }
5131
5200
  generateFilename(name) {
5132
5201
  const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
@@ -5156,6 +5225,10 @@ var KnowledgeDocMaterializer = class {
5156
5225
  const mappedType = this.mapNodeType(node);
5157
5226
  const sanitize = (s) => s.replace(/[\n\r]/g, " ").replace(/:/g, "-");
5158
5227
  const lines = ["---", `type: ${sanitize(mappedType)}`, `domain: ${sanitize(domain)}`];
5228
+ const source = node.metadata?.source;
5229
+ if (typeof source === "string" && source.length > 0) {
5230
+ lines.push(`source: ${sanitize(source)}`);
5231
+ }
5159
5232
  const tags = node.metadata?.tags;
5160
5233
  if (Array.isArray(tags) && tags.length > 0) {
5161
5234
  lines.push(`tags: [${tags.map((t) => sanitize(String(t))).join(", ")}]`);
@@ -5220,7 +5293,10 @@ var KnowledgePipelineRunner = class {
5220
5293
  this.store = store;
5221
5294
  }
5222
5295
  store;
5296
+ /** Resolved per-`run()` inference options. Set on entry to `run()`. */
5297
+ inferenceOptions = {};
5223
5298
  async run(options) {
5299
+ this.inferenceOptions = options.inferenceOptions ?? {};
5224
5300
  const remediations = [];
5225
5301
  const preSnapshot = this.buildSnapshot(options.domain);
5226
5302
  const extraction = await this.extract(options);
@@ -5228,7 +5304,7 @@ var KnowledgePipelineRunner = class {
5228
5304
  let driftResult = this.reconcile(preSnapshot, postSnapshot);
5229
5305
  const contradictions = new ContradictionDetector().detect(this.store);
5230
5306
  let gapReport = await this.detect(options);
5231
- const coverage = new CoverageScorer().score(this.store);
5307
+ const coverage = new CoverageScorer(this.inferenceOptions).score(this.store);
5232
5308
  let materialization;
5233
5309
  let iterations = 1;
5234
5310
  if (options.fix) {
@@ -5391,7 +5467,7 @@ var KnowledgePipelineRunner = class {
5391
5467
  // ── Phase 3: DETECT ───────────────────────────────────────────────────────
5392
5468
  async detect(options) {
5393
5469
  const knowledgeDir = path12.join(options.projectDir, "docs", "knowledge");
5394
- const aggregator = new KnowledgeStagingAggregator(options.projectDir);
5470
+ const aggregator = new KnowledgeStagingAggregator(options.projectDir, this.inferenceOptions);
5395
5471
  const gapReport = await aggregator.generateGapReport(knowledgeDir, this.store);
5396
5472
  await aggregator.writeGapReport(gapReport);
5397
5473
  return gapReport;
@@ -5419,7 +5495,7 @@ var KnowledgePipelineRunner = class {
5419
5495
  const allGapEntries = gapReport.domains.flatMap((d) => d.gapEntries);
5420
5496
  const materializable = allGapEntries.filter((e) => e.hasContent);
5421
5497
  if (materializable.length > 0) {
5422
- const materializer = new KnowledgeDocMaterializer(this.store);
5498
+ const materializer = new KnowledgeDocMaterializer(this.store, this.inferenceOptions);
5423
5499
  const matResult = await materializer.materialize(materializable, {
5424
5500
  projectDir: options.projectDir,
5425
5501
  dryRun: false
@@ -5445,7 +5521,7 @@ var KnowledgePipelineRunner = class {
5445
5521
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
5446
5522
  }));
5447
5523
  if (stagedEntries.length > 0) {
5448
- const aggregator = new KnowledgeStagingAggregator(options.projectDir);
5524
+ const aggregator = new KnowledgeStagingAggregator(options.projectDir, this.inferenceOptions);
5449
5525
  await aggregator.aggregate(stagedEntries, [], []);
5450
5526
  }
5451
5527
  }
@@ -9418,6 +9494,8 @@ export {
9418
9494
  ContradictionDetector,
9419
9495
  CoverageScorer,
9420
9496
  D2Parser,
9497
+ DEFAULT_BLOCKLIST,
9498
+ DEFAULT_PATTERNS,
9421
9499
  DecisionIngestor,
9422
9500
  DesignConstraintAdapter,
9423
9501
  DesignIngestor,
@@ -9470,6 +9548,7 @@ export {
9470
9548
  createExtractionRunner,
9471
9549
  detectLanguage,
9472
9550
  groupNodesByImpact,
9551
+ inferDomain,
9473
9552
  linkToCode,
9474
9553
  loadGraph,
9475
9554
  normalizeIntent,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harness-engineering/graph",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "license": "MIT",
5
5
  "description": "Knowledge graph for context assembly in Harness Engineering",
6
6
  "main": "./dist/index.js",