@harness-engineering/graph 0.8.0 → 0.10.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 +60 -2
- package/dist/index.d.ts +60 -2
- package/dist/index.js +160 -36
- package/dist/index.mjs +161 -38
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -497,6 +497,16 @@ declare function resolveSkipDirs(options?: {
|
|
|
497
497
|
skipDirs?: Iterable<string>;
|
|
498
498
|
additionalSkipDirs?: Iterable<string>;
|
|
499
499
|
}): ReadonlySet<string>;
|
|
500
|
+
/**
|
|
501
|
+
* Convert a skip-dirs set into minimatch glob patterns of the form
|
|
502
|
+
* `**\/<name>/\**`. Use for tools that exclude via globs (security scan, doc
|
|
503
|
+
* coverage, entropy analysis) rather than by reading directory names during
|
|
504
|
+
* traversal. Defaults to {@link DEFAULT_SKIP_DIRS}.
|
|
505
|
+
*
|
|
506
|
+
* Returns a fresh array each call so callers may freely mutate/append
|
|
507
|
+
* domain-specific patterns (e.g. test/fixture file globs).
|
|
508
|
+
*/
|
|
509
|
+
declare function skipDirGlobs(skipDirs?: ReadonlySet<string>): string[];
|
|
500
510
|
|
|
501
511
|
type GitRunner = (rootDir: string, args: string[]) => Promise<string>;
|
|
502
512
|
/**
|
|
@@ -544,11 +554,13 @@ declare class KnowledgeIngestor {
|
|
|
544
554
|
ingestADRs(adrDir: string): Promise<IngestResult>;
|
|
545
555
|
ingestLearnings(projectPath: string): Promise<IngestResult>;
|
|
546
556
|
ingestFailures(projectPath: string): Promise<IngestResult>;
|
|
557
|
+
ingestGeneralDocs(projectPath: string): Promise<IngestResult>;
|
|
547
558
|
ingestAll(projectPath: string, opts?: {
|
|
548
559
|
adrDir?: string;
|
|
549
560
|
}): Promise<IngestResult>;
|
|
550
561
|
private linkToCode;
|
|
551
562
|
private findMarkdownFiles;
|
|
563
|
+
private scanDocsDir;
|
|
552
564
|
}
|
|
553
565
|
|
|
554
566
|
declare class BusinessKnowledgeIngestor {
|
|
@@ -1766,6 +1778,28 @@ interface DesignViolation {
|
|
|
1766
1778
|
suggestion?: string;
|
|
1767
1779
|
}
|
|
1768
1780
|
type DesignStrictness = 'strict' | 'standard' | 'permissive';
|
|
1781
|
+
/**
|
|
1782
|
+
* Generic finding shape accepted by `recordFindings()` — covers ANAT-*
|
|
1783
|
+
* (audit-component-anatomy, design-pipeline #2) and CRAFT-*
|
|
1784
|
+
* (harness-design-craft, design-pipeline #6) namespaces. Skills convert
|
|
1785
|
+
* their internal finding types into this shape before recording.
|
|
1786
|
+
*/
|
|
1787
|
+
interface CraftFindingRecord {
|
|
1788
|
+
/** Finding code, e.g. "ANAT-D023", "CRAFT-C001", "CRAFT-P001" */
|
|
1789
|
+
code: string;
|
|
1790
|
+
/** Project-relative file path (becomes the `file` node id) */
|
|
1791
|
+
file: string;
|
|
1792
|
+
/** Line number, if known */
|
|
1793
|
+
line?: number;
|
|
1794
|
+
/** Human-readable message */
|
|
1795
|
+
message: string;
|
|
1796
|
+
/** Severity at emission time */
|
|
1797
|
+
severity: 'error' | 'warn' | 'info';
|
|
1798
|
+
/** Optional evidence snippet */
|
|
1799
|
+
evidence?: string;
|
|
1800
|
+
/** Optional run identifier so #4 verifier can detect fixpoint across runs */
|
|
1801
|
+
runId?: string;
|
|
1802
|
+
}
|
|
1769
1803
|
declare class DesignConstraintAdapter {
|
|
1770
1804
|
private readonly store;
|
|
1771
1805
|
constructor(store: GraphStore);
|
|
@@ -1773,6 +1807,30 @@ declare class DesignConstraintAdapter {
|
|
|
1773
1807
|
checkForHardcodedFonts(source: string, file: string, strictness?: DesignStrictness): DesignViolation[];
|
|
1774
1808
|
checkAll(source: string, file: string, strictness?: DesignStrictness): DesignViolation[];
|
|
1775
1809
|
private mapSeverity;
|
|
1810
|
+
/**
|
|
1811
|
+
* Record externally-computed craft findings (audit-component-anatomy,
|
|
1812
|
+
* harness-design-craft, etc.) as graph state. Idempotent — re-running on
|
|
1813
|
+
* the same findings produces no duplicate nodes or edges thanks to
|
|
1814
|
+
* GraphStore's keyed merge semantics.
|
|
1815
|
+
*
|
|
1816
|
+
* Each finding becomes:
|
|
1817
|
+
* • a `design_constraint` node keyed by finding code (created lazily
|
|
1818
|
+
* if absent; metadata merged on re-record so the most recent message
|
|
1819
|
+
* / severity wins)
|
|
1820
|
+
* • a `violates_design` edge from the source file (id = file path) to
|
|
1821
|
+
* the constraint node, with per-finding metadata (line, severity,
|
|
1822
|
+
* message, evidence, runId)
|
|
1823
|
+
*
|
|
1824
|
+
* The file node is NOT created here — it's assumed to already exist in
|
|
1825
|
+
* the graph from a prior ingest. If it does not, the edge will still be
|
|
1826
|
+
* created (graph stores edges by key, not by referential integrity) and
|
|
1827
|
+
* a subsequent ingest will populate the file node.
|
|
1828
|
+
*/
|
|
1829
|
+
recordFindings(findings: readonly CraftFindingRecord[]): {
|
|
1830
|
+
constraintsAdded: number;
|
|
1831
|
+
edgesAdded: number;
|
|
1832
|
+
};
|
|
1833
|
+
private labelForCode;
|
|
1776
1834
|
}
|
|
1777
1835
|
|
|
1778
1836
|
interface GraphImpactData {
|
|
@@ -1969,6 +2027,6 @@ declare class CascadeSimulator {
|
|
|
1969
2027
|
private buildResult;
|
|
1970
2028
|
}
|
|
1971
2029
|
|
|
1972
|
-
declare const VERSION = "0.
|
|
2030
|
+
declare const VERSION = "0.9.0";
|
|
1973
2031
|
|
|
1974
|
-
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, type CodeIngestorOptions, 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, DEFAULT_SKIP_DIRS, 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 LoadMetadataResult, 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, loadGraphMetadata, normalizeIntent, project, queryTraceability, resolveSkipDirs, saveGraph };
|
|
2032
|
+
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, type CodeIngestorOptions, 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, type CraftFindingRecord, D2Parser, DEFAULT_BLOCKLIST, DEFAULT_PATTERNS, DEFAULT_SKIP_DIRS, 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 LoadMetadataResult, 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, loadGraphMetadata, normalizeIntent, project, queryTraceability, resolveSkipDirs, saveGraph, skipDirGlobs };
|
package/dist/index.d.ts
CHANGED
|
@@ -497,6 +497,16 @@ declare function resolveSkipDirs(options?: {
|
|
|
497
497
|
skipDirs?: Iterable<string>;
|
|
498
498
|
additionalSkipDirs?: Iterable<string>;
|
|
499
499
|
}): ReadonlySet<string>;
|
|
500
|
+
/**
|
|
501
|
+
* Convert a skip-dirs set into minimatch glob patterns of the form
|
|
502
|
+
* `**\/<name>/\**`. Use for tools that exclude via globs (security scan, doc
|
|
503
|
+
* coverage, entropy analysis) rather than by reading directory names during
|
|
504
|
+
* traversal. Defaults to {@link DEFAULT_SKIP_DIRS}.
|
|
505
|
+
*
|
|
506
|
+
* Returns a fresh array each call so callers may freely mutate/append
|
|
507
|
+
* domain-specific patterns (e.g. test/fixture file globs).
|
|
508
|
+
*/
|
|
509
|
+
declare function skipDirGlobs(skipDirs?: ReadonlySet<string>): string[];
|
|
500
510
|
|
|
501
511
|
type GitRunner = (rootDir: string, args: string[]) => Promise<string>;
|
|
502
512
|
/**
|
|
@@ -544,11 +554,13 @@ declare class KnowledgeIngestor {
|
|
|
544
554
|
ingestADRs(adrDir: string): Promise<IngestResult>;
|
|
545
555
|
ingestLearnings(projectPath: string): Promise<IngestResult>;
|
|
546
556
|
ingestFailures(projectPath: string): Promise<IngestResult>;
|
|
557
|
+
ingestGeneralDocs(projectPath: string): Promise<IngestResult>;
|
|
547
558
|
ingestAll(projectPath: string, opts?: {
|
|
548
559
|
adrDir?: string;
|
|
549
560
|
}): Promise<IngestResult>;
|
|
550
561
|
private linkToCode;
|
|
551
562
|
private findMarkdownFiles;
|
|
563
|
+
private scanDocsDir;
|
|
552
564
|
}
|
|
553
565
|
|
|
554
566
|
declare class BusinessKnowledgeIngestor {
|
|
@@ -1766,6 +1778,28 @@ interface DesignViolation {
|
|
|
1766
1778
|
suggestion?: string;
|
|
1767
1779
|
}
|
|
1768
1780
|
type DesignStrictness = 'strict' | 'standard' | 'permissive';
|
|
1781
|
+
/**
|
|
1782
|
+
* Generic finding shape accepted by `recordFindings()` — covers ANAT-*
|
|
1783
|
+
* (audit-component-anatomy, design-pipeline #2) and CRAFT-*
|
|
1784
|
+
* (harness-design-craft, design-pipeline #6) namespaces. Skills convert
|
|
1785
|
+
* their internal finding types into this shape before recording.
|
|
1786
|
+
*/
|
|
1787
|
+
interface CraftFindingRecord {
|
|
1788
|
+
/** Finding code, e.g. "ANAT-D023", "CRAFT-C001", "CRAFT-P001" */
|
|
1789
|
+
code: string;
|
|
1790
|
+
/** Project-relative file path (becomes the `file` node id) */
|
|
1791
|
+
file: string;
|
|
1792
|
+
/** Line number, if known */
|
|
1793
|
+
line?: number;
|
|
1794
|
+
/** Human-readable message */
|
|
1795
|
+
message: string;
|
|
1796
|
+
/** Severity at emission time */
|
|
1797
|
+
severity: 'error' | 'warn' | 'info';
|
|
1798
|
+
/** Optional evidence snippet */
|
|
1799
|
+
evidence?: string;
|
|
1800
|
+
/** Optional run identifier so #4 verifier can detect fixpoint across runs */
|
|
1801
|
+
runId?: string;
|
|
1802
|
+
}
|
|
1769
1803
|
declare class DesignConstraintAdapter {
|
|
1770
1804
|
private readonly store;
|
|
1771
1805
|
constructor(store: GraphStore);
|
|
@@ -1773,6 +1807,30 @@ declare class DesignConstraintAdapter {
|
|
|
1773
1807
|
checkForHardcodedFonts(source: string, file: string, strictness?: DesignStrictness): DesignViolation[];
|
|
1774
1808
|
checkAll(source: string, file: string, strictness?: DesignStrictness): DesignViolation[];
|
|
1775
1809
|
private mapSeverity;
|
|
1810
|
+
/**
|
|
1811
|
+
* Record externally-computed craft findings (audit-component-anatomy,
|
|
1812
|
+
* harness-design-craft, etc.) as graph state. Idempotent — re-running on
|
|
1813
|
+
* the same findings produces no duplicate nodes or edges thanks to
|
|
1814
|
+
* GraphStore's keyed merge semantics.
|
|
1815
|
+
*
|
|
1816
|
+
* Each finding becomes:
|
|
1817
|
+
* • a `design_constraint` node keyed by finding code (created lazily
|
|
1818
|
+
* if absent; metadata merged on re-record so the most recent message
|
|
1819
|
+
* / severity wins)
|
|
1820
|
+
* • a `violates_design` edge from the source file (id = file path) to
|
|
1821
|
+
* the constraint node, with per-finding metadata (line, severity,
|
|
1822
|
+
* message, evidence, runId)
|
|
1823
|
+
*
|
|
1824
|
+
* The file node is NOT created here — it's assumed to already exist in
|
|
1825
|
+
* the graph from a prior ingest. If it does not, the edge will still be
|
|
1826
|
+
* created (graph stores edges by key, not by referential integrity) and
|
|
1827
|
+
* a subsequent ingest will populate the file node.
|
|
1828
|
+
*/
|
|
1829
|
+
recordFindings(findings: readonly CraftFindingRecord[]): {
|
|
1830
|
+
constraintsAdded: number;
|
|
1831
|
+
edgesAdded: number;
|
|
1832
|
+
};
|
|
1833
|
+
private labelForCode;
|
|
1776
1834
|
}
|
|
1777
1835
|
|
|
1778
1836
|
interface GraphImpactData {
|
|
@@ -1969,6 +2027,6 @@ declare class CascadeSimulator {
|
|
|
1969
2027
|
private buildResult;
|
|
1970
2028
|
}
|
|
1971
2029
|
|
|
1972
|
-
declare const VERSION = "0.
|
|
2030
|
+
declare const VERSION = "0.9.0";
|
|
1973
2031
|
|
|
1974
|
-
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, type CodeIngestorOptions, 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, DEFAULT_SKIP_DIRS, 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 LoadMetadataResult, 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, loadGraphMetadata, normalizeIntent, project, queryTraceability, resolveSkipDirs, saveGraph };
|
|
2032
|
+
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, type CodeIngestorOptions, 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, type CraftFindingRecord, D2Parser, DEFAULT_BLOCKLIST, DEFAULT_PATTERNS, DEFAULT_SKIP_DIRS, 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 LoadMetadataResult, 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, loadGraphMetadata, normalizeIntent, project, queryTraceability, resolveSkipDirs, saveGraph, skipDirGlobs };
|
package/dist/index.js
CHANGED
|
@@ -108,7 +108,8 @@ __export(index_exports, {
|
|
|
108
108
|
project: () => project,
|
|
109
109
|
queryTraceability: () => queryTraceability,
|
|
110
110
|
resolveSkipDirs: () => resolveSkipDirs,
|
|
111
|
-
saveGraph: () => saveGraph
|
|
111
|
+
saveGraph: () => saveGraph,
|
|
112
|
+
skipDirGlobs: () => skipDirGlobs
|
|
112
113
|
});
|
|
113
114
|
module.exports = __toCommonJS(index_exports);
|
|
114
115
|
|
|
@@ -978,6 +979,9 @@ function resolveSkipDirs(options) {
|
|
|
978
979
|
}
|
|
979
980
|
return base;
|
|
980
981
|
}
|
|
982
|
+
function skipDirGlobs(skipDirs = DEFAULT_SKIP_DIRS) {
|
|
983
|
+
return Array.from(skipDirs, (name) => `**/${name}/**`);
|
|
984
|
+
}
|
|
981
985
|
|
|
982
986
|
// src/ingest/CodeIngestor.ts
|
|
983
987
|
var SKIP_METHOD_NAMES = /* @__PURE__ */ new Set(["constructor", "if", "for", "while", "switch"]);
|
|
@@ -2005,6 +2009,7 @@ function emptyResult(durationMs = 0) {
|
|
|
2005
2009
|
|
|
2006
2010
|
// src/ingest/KnowledgeIngestor.ts
|
|
2007
2011
|
var CODE_NODE_TYPES = ["file", "function", "class", "method", "interface", "variable"];
|
|
2012
|
+
var DOCS_OWNED_BY_OTHER_INGESTORS = /* @__PURE__ */ new Set(["adr", "knowledge", "changes", "solutions"]);
|
|
2008
2013
|
var KnowledgeIngestor = class {
|
|
2009
2014
|
constructor(store) {
|
|
2010
2015
|
this.store = store;
|
|
@@ -2076,15 +2081,53 @@ var KnowledgeIngestor = class {
|
|
|
2076
2081
|
}
|
|
2077
2082
|
return buildResult(nodesAdded, edgesAdded, [], start);
|
|
2078
2083
|
}
|
|
2084
|
+
async ingestGeneralDocs(projectPath) {
|
|
2085
|
+
const start = Date.now();
|
|
2086
|
+
const errors = [];
|
|
2087
|
+
let nodesAdded = 0;
|
|
2088
|
+
let edgesAdded = 0;
|
|
2089
|
+
const files = /* @__PURE__ */ new Set();
|
|
2090
|
+
try {
|
|
2091
|
+
const entries = await fs2.readdir(projectPath, { withFileTypes: true });
|
|
2092
|
+
for (const entry of entries) {
|
|
2093
|
+
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
2094
|
+
files.add(path3.join(projectPath, entry.name));
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
} catch {
|
|
2098
|
+
return emptyResult(Date.now() - start);
|
|
2099
|
+
}
|
|
2100
|
+
const docsRoot = path3.join(projectPath, "docs");
|
|
2101
|
+
try {
|
|
2102
|
+
const scanned = await this.scanDocsDir(docsRoot);
|
|
2103
|
+
for (const f of scanned) files.add(f);
|
|
2104
|
+
} catch {
|
|
2105
|
+
}
|
|
2106
|
+
for (const filePath of files) {
|
|
2107
|
+
try {
|
|
2108
|
+
const content = await fs2.readFile(filePath, "utf-8");
|
|
2109
|
+
const relPath = path3.relative(projectPath, filePath).replaceAll("\\", "/");
|
|
2110
|
+
const nodeId = `doc:${relPath}`;
|
|
2111
|
+
if (this.store.getNode(nodeId)) continue;
|
|
2112
|
+
this.store.addNode(parseDocumentNode(nodeId, filePath, relPath, content));
|
|
2113
|
+
nodesAdded++;
|
|
2114
|
+
edgesAdded += this.linkToCode(content, nodeId, "documents");
|
|
2115
|
+
} catch (err) {
|
|
2116
|
+
errors.push(`${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
return buildResult(nodesAdded, edgesAdded, errors, start);
|
|
2120
|
+
}
|
|
2079
2121
|
async ingestAll(projectPath, opts) {
|
|
2080
2122
|
const start = Date.now();
|
|
2081
2123
|
const adrDir = opts?.adrDir ?? path3.join(projectPath, "docs", "adr");
|
|
2082
|
-
const [adrResult, learningsResult, failuresResult] = await Promise.all([
|
|
2124
|
+
const [adrResult, learningsResult, failuresResult, docsResult] = await Promise.all([
|
|
2083
2125
|
this.ingestADRs(adrDir),
|
|
2084
2126
|
this.ingestLearnings(projectPath),
|
|
2085
|
-
this.ingestFailures(projectPath)
|
|
2127
|
+
this.ingestFailures(projectPath),
|
|
2128
|
+
this.ingestGeneralDocs(projectPath)
|
|
2086
2129
|
]);
|
|
2087
|
-
const merged = mergeResults(adrResult, learningsResult, failuresResult);
|
|
2130
|
+
const merged = mergeResults(adrResult, learningsResult, failuresResult, docsResult);
|
|
2088
2131
|
return { ...merged, durationMs: Date.now() - start };
|
|
2089
2132
|
}
|
|
2090
2133
|
linkToCode(content, sourceNodeId, edgeType) {
|
|
@@ -2119,7 +2162,22 @@ var KnowledgeIngestor = class {
|
|
|
2119
2162
|
const entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
2120
2163
|
for (const entry of entries) {
|
|
2121
2164
|
const fullPath = path3.join(dir, entry.name);
|
|
2122
|
-
if (entry.isDirectory() &&
|
|
2165
|
+
if (entry.isDirectory() && !DEFAULT_SKIP_DIRS.has(entry.name)) {
|
|
2166
|
+
results.push(...await this.findMarkdownFiles(fullPath));
|
|
2167
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
2168
|
+
results.push(fullPath);
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
return results;
|
|
2172
|
+
}
|
|
2173
|
+
async scanDocsDir(docsRoot) {
|
|
2174
|
+
const results = [];
|
|
2175
|
+
const rootEntries = await fs2.readdir(docsRoot, { withFileTypes: true });
|
|
2176
|
+
for (const entry of rootEntries) {
|
|
2177
|
+
const fullPath = path3.join(docsRoot, entry.name);
|
|
2178
|
+
if (entry.isDirectory()) {
|
|
2179
|
+
if (DEFAULT_SKIP_DIRS.has(entry.name)) continue;
|
|
2180
|
+
if (DOCS_OWNED_BY_OTHER_INGESTORS.has(entry.name)) continue;
|
|
2123
2181
|
results.push(...await this.findMarkdownFiles(fullPath));
|
|
2124
2182
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
2125
2183
|
results.push(fullPath);
|
|
@@ -2145,6 +2203,17 @@ function buildResult(nodesAdded, edgesAdded, errors, start) {
|
|
|
2145
2203
|
durationMs: Date.now() - start
|
|
2146
2204
|
};
|
|
2147
2205
|
}
|
|
2206
|
+
function parseDocumentNode(nodeId, filePath, relPath, content) {
|
|
2207
|
+
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
2208
|
+
const title = titleMatch ? titleMatch[1].trim() : path3.basename(filePath, ".md");
|
|
2209
|
+
return {
|
|
2210
|
+
id: nodeId,
|
|
2211
|
+
type: "document",
|
|
2212
|
+
name: title,
|
|
2213
|
+
path: filePath,
|
|
2214
|
+
metadata: { relPath }
|
|
2215
|
+
};
|
|
2216
|
+
}
|
|
2148
2217
|
function parseADRNode(nodeId, filePath, filename, content) {
|
|
2149
2218
|
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
2150
2219
|
const title = titleMatch ? titleMatch[1].trim() : filename;
|
|
@@ -2431,7 +2500,7 @@ var BusinessKnowledgeIngestor = class {
|
|
|
2431
2500
|
const entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
2432
2501
|
for (const entry of entries) {
|
|
2433
2502
|
const fullPath = path4.join(dir, entry.name);
|
|
2434
|
-
if (entry.isDirectory() &&
|
|
2503
|
+
if (entry.isDirectory() && !DEFAULT_SKIP_DIRS.has(entry.name)) {
|
|
2435
2504
|
results.push(...await this.findMarkdownFiles(fullPath));
|
|
2436
2505
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
2437
2506
|
results.push(fullPath);
|
|
@@ -3275,7 +3344,6 @@ var PlantUmlParser = class {
|
|
|
3275
3344
|
|
|
3276
3345
|
// src/ingest/DiagramParser.ts
|
|
3277
3346
|
var DIAGRAM_EXTENSIONS = /* @__PURE__ */ new Set([".mmd", ".mermaid", ".d2", ".puml", ".plantuml"]);
|
|
3278
|
-
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".harness"]);
|
|
3279
3347
|
var DiagramParser = class {
|
|
3280
3348
|
constructor(store) {
|
|
3281
3349
|
this.store = store;
|
|
@@ -3380,7 +3448,7 @@ var DiagramParser = class {
|
|
|
3380
3448
|
}
|
|
3381
3449
|
for (const entry of entries) {
|
|
3382
3450
|
if (entry.isDirectory()) {
|
|
3383
|
-
if (!
|
|
3451
|
+
if (!DEFAULT_SKIP_DIRS.has(entry.name)) {
|
|
3384
3452
|
await walk(path7.join(currentDir, entry.name));
|
|
3385
3453
|
}
|
|
3386
3454
|
} else if (entry.isFile()) {
|
|
@@ -3904,31 +3972,6 @@ var KnowledgeStagingAggregator = class {
|
|
|
3904
3972
|
// src/ingest/extractors/ExtractionRunner.ts
|
|
3905
3973
|
var fs9 = __toESM(require("fs/promises"));
|
|
3906
3974
|
var path10 = __toESM(require("path"));
|
|
3907
|
-
var SKIP_DIRS2 = /* @__PURE__ */ new Set([
|
|
3908
|
-
"node_modules",
|
|
3909
|
-
"dist",
|
|
3910
|
-
"target",
|
|
3911
|
-
"build",
|
|
3912
|
-
".git",
|
|
3913
|
-
"__pycache__",
|
|
3914
|
-
".venv",
|
|
3915
|
-
".turbo",
|
|
3916
|
-
".harness",
|
|
3917
|
-
".next",
|
|
3918
|
-
".vscode",
|
|
3919
|
-
".idea",
|
|
3920
|
-
"vendor",
|
|
3921
|
-
"out",
|
|
3922
|
-
".gradle",
|
|
3923
|
-
".gradle-home",
|
|
3924
|
-
"bin",
|
|
3925
|
-
"obj",
|
|
3926
|
-
"venv",
|
|
3927
|
-
"_build",
|
|
3928
|
-
"deps",
|
|
3929
|
-
"coverage",
|
|
3930
|
-
".nyc_output"
|
|
3931
|
-
]);
|
|
3932
3975
|
var EXT_TO_LANGUAGE = {
|
|
3933
3976
|
".ts": "typescript",
|
|
3934
3977
|
".tsx": "typescript",
|
|
@@ -4107,7 +4150,7 @@ var ExtractionRunner = class {
|
|
|
4107
4150
|
}
|
|
4108
4151
|
for (const entry of entries) {
|
|
4109
4152
|
const fullPath = path10.join(dir, entry.name);
|
|
4110
|
-
if (entry.isDirectory() && !
|
|
4153
|
+
if (entry.isDirectory() && !DEFAULT_SKIP_DIRS.has(entry.name)) {
|
|
4111
4154
|
results.push(...await this.findSourceFiles(fullPath));
|
|
4112
4155
|
} else if (entry.isFile() && detectLanguage(fullPath) !== void 0) {
|
|
4113
4156
|
results.push(fullPath);
|
|
@@ -9340,6 +9383,16 @@ var DesignIngestor = class {
|
|
|
9340
9383
|
};
|
|
9341
9384
|
|
|
9342
9385
|
// src/constraints/DesignConstraintAdapter.ts
|
|
9386
|
+
var CODE_PREFIX_LABELS = {
|
|
9387
|
+
"ANAT-D": "Component anatomy (definition)",
|
|
9388
|
+
"ANAT-P": "Component anatomy (pattern presence)",
|
|
9389
|
+
"ANAT-U": "Component anatomy (usage)",
|
|
9390
|
+
"CRAFT-C": "Design craft (critique)",
|
|
9391
|
+
"CRAFT-P": "Design craft (polish)",
|
|
9392
|
+
"CRAFT-B": "Design craft (benchmark)",
|
|
9393
|
+
"DESIGN-": "Design constraint (legacy)",
|
|
9394
|
+
"A11Y-": "Accessibility"
|
|
9395
|
+
};
|
|
9343
9396
|
var DesignConstraintAdapter = class {
|
|
9344
9397
|
constructor(store) {
|
|
9345
9398
|
this.store = store;
|
|
@@ -9421,6 +9474,76 @@ var DesignConstraintAdapter = class {
|
|
|
9421
9474
|
return "error";
|
|
9422
9475
|
}
|
|
9423
9476
|
}
|
|
9477
|
+
/**
|
|
9478
|
+
* Record externally-computed craft findings (audit-component-anatomy,
|
|
9479
|
+
* harness-design-craft, etc.) as graph state. Idempotent — re-running on
|
|
9480
|
+
* the same findings produces no duplicate nodes or edges thanks to
|
|
9481
|
+
* GraphStore's keyed merge semantics.
|
|
9482
|
+
*
|
|
9483
|
+
* Each finding becomes:
|
|
9484
|
+
* • a `design_constraint` node keyed by finding code (created lazily
|
|
9485
|
+
* if absent; metadata merged on re-record so the most recent message
|
|
9486
|
+
* / severity wins)
|
|
9487
|
+
* • a `violates_design` edge from the source file (id = file path) to
|
|
9488
|
+
* the constraint node, with per-finding metadata (line, severity,
|
|
9489
|
+
* message, evidence, runId)
|
|
9490
|
+
*
|
|
9491
|
+
* The file node is NOT created here — it's assumed to already exist in
|
|
9492
|
+
* the graph from a prior ingest. If it does not, the edge will still be
|
|
9493
|
+
* created (graph stores edges by key, not by referential integrity) and
|
|
9494
|
+
* a subsequent ingest will populate the file node.
|
|
9495
|
+
*/
|
|
9496
|
+
recordFindings(findings) {
|
|
9497
|
+
let constraintsAdded = 0;
|
|
9498
|
+
let edgesAdded = 0;
|
|
9499
|
+
const seenConstraintIds = /* @__PURE__ */ new Set();
|
|
9500
|
+
for (const finding of findings) {
|
|
9501
|
+
const constraintId = `design_constraint:${finding.code}`;
|
|
9502
|
+
if (!seenConstraintIds.has(finding.code)) {
|
|
9503
|
+
const existing = this.store.getNode(constraintId);
|
|
9504
|
+
if (!existing) constraintsAdded += 1;
|
|
9505
|
+
this.store.addNode({
|
|
9506
|
+
id: constraintId,
|
|
9507
|
+
type: "design_constraint",
|
|
9508
|
+
name: finding.code,
|
|
9509
|
+
metadata: {
|
|
9510
|
+
code: finding.code,
|
|
9511
|
+
label: this.labelForCode(finding.code),
|
|
9512
|
+
mostRecentMessage: finding.message,
|
|
9513
|
+
mostRecentSeverity: finding.severity
|
|
9514
|
+
}
|
|
9515
|
+
});
|
|
9516
|
+
seenConstraintIds.add(finding.code);
|
|
9517
|
+
}
|
|
9518
|
+
const fileId = finding.file;
|
|
9519
|
+
const edgeMetadata = {
|
|
9520
|
+
message: finding.message,
|
|
9521
|
+
severity: finding.severity
|
|
9522
|
+
};
|
|
9523
|
+
if (finding.line !== void 0) edgeMetadata.line = finding.line;
|
|
9524
|
+
if (finding.evidence !== void 0) edgeMetadata.evidence = finding.evidence;
|
|
9525
|
+
if (finding.runId !== void 0) edgeMetadata.runId = finding.runId;
|
|
9526
|
+
const before = this.store.getEdges({
|
|
9527
|
+
from: fileId,
|
|
9528
|
+
to: constraintId,
|
|
9529
|
+
type: "violates_design"
|
|
9530
|
+
});
|
|
9531
|
+
this.store.addEdge({
|
|
9532
|
+
from: fileId,
|
|
9533
|
+
to: constraintId,
|
|
9534
|
+
type: "violates_design",
|
|
9535
|
+
metadata: edgeMetadata
|
|
9536
|
+
});
|
|
9537
|
+
if (before.length === 0) edgesAdded += 1;
|
|
9538
|
+
}
|
|
9539
|
+
return { constraintsAdded, edgesAdded };
|
|
9540
|
+
}
|
|
9541
|
+
labelForCode(code) {
|
|
9542
|
+
for (const prefix of Object.keys(CODE_PREFIX_LABELS)) {
|
|
9543
|
+
if (code.startsWith(prefix)) return CODE_PREFIX_LABELS[prefix];
|
|
9544
|
+
}
|
|
9545
|
+
return "Design constraint";
|
|
9546
|
+
}
|
|
9424
9547
|
};
|
|
9425
9548
|
|
|
9426
9549
|
// src/feedback/GraphFeedbackAdapter.ts
|
|
@@ -9948,7 +10071,7 @@ var ConflictPredictor = class {
|
|
|
9948
10071
|
};
|
|
9949
10072
|
|
|
9950
10073
|
// src/index.ts
|
|
9951
|
-
var VERSION = "0.
|
|
10074
|
+
var VERSION = "0.9.0";
|
|
9952
10075
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9953
10076
|
0 && (module.exports = {
|
|
9954
10077
|
ALL_EXTRACTORS,
|
|
@@ -10029,5 +10152,6 @@ var VERSION = "0.6.0";
|
|
|
10029
10152
|
project,
|
|
10030
10153
|
queryTraceability,
|
|
10031
10154
|
resolveSkipDirs,
|
|
10032
|
-
saveGraph
|
|
10155
|
+
saveGraph,
|
|
10156
|
+
skipDirGlobs
|
|
10033
10157
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -864,6 +864,9 @@ function resolveSkipDirs(options) {
|
|
|
864
864
|
}
|
|
865
865
|
return base;
|
|
866
866
|
}
|
|
867
|
+
function skipDirGlobs(skipDirs = DEFAULT_SKIP_DIRS) {
|
|
868
|
+
return Array.from(skipDirs, (name) => `**/${name}/**`);
|
|
869
|
+
}
|
|
867
870
|
|
|
868
871
|
// src/ingest/CodeIngestor.ts
|
|
869
872
|
var SKIP_METHOD_NAMES = /* @__PURE__ */ new Set(["constructor", "if", "for", "while", "switch"]);
|
|
@@ -1891,6 +1894,7 @@ function emptyResult(durationMs = 0) {
|
|
|
1891
1894
|
|
|
1892
1895
|
// src/ingest/KnowledgeIngestor.ts
|
|
1893
1896
|
var CODE_NODE_TYPES = ["file", "function", "class", "method", "interface", "variable"];
|
|
1897
|
+
var DOCS_OWNED_BY_OTHER_INGESTORS = /* @__PURE__ */ new Set(["adr", "knowledge", "changes", "solutions"]);
|
|
1894
1898
|
var KnowledgeIngestor = class {
|
|
1895
1899
|
constructor(store) {
|
|
1896
1900
|
this.store = store;
|
|
@@ -1962,15 +1966,53 @@ var KnowledgeIngestor = class {
|
|
|
1962
1966
|
}
|
|
1963
1967
|
return buildResult(nodesAdded, edgesAdded, [], start);
|
|
1964
1968
|
}
|
|
1969
|
+
async ingestGeneralDocs(projectPath) {
|
|
1970
|
+
const start = Date.now();
|
|
1971
|
+
const errors = [];
|
|
1972
|
+
let nodesAdded = 0;
|
|
1973
|
+
let edgesAdded = 0;
|
|
1974
|
+
const files = /* @__PURE__ */ new Set();
|
|
1975
|
+
try {
|
|
1976
|
+
const entries = await fs2.readdir(projectPath, { withFileTypes: true });
|
|
1977
|
+
for (const entry of entries) {
|
|
1978
|
+
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
1979
|
+
files.add(path3.join(projectPath, entry.name));
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
} catch {
|
|
1983
|
+
return emptyResult(Date.now() - start);
|
|
1984
|
+
}
|
|
1985
|
+
const docsRoot = path3.join(projectPath, "docs");
|
|
1986
|
+
try {
|
|
1987
|
+
const scanned = await this.scanDocsDir(docsRoot);
|
|
1988
|
+
for (const f of scanned) files.add(f);
|
|
1989
|
+
} catch {
|
|
1990
|
+
}
|
|
1991
|
+
for (const filePath of files) {
|
|
1992
|
+
try {
|
|
1993
|
+
const content = await fs2.readFile(filePath, "utf-8");
|
|
1994
|
+
const relPath = path3.relative(projectPath, filePath).replaceAll("\\", "/");
|
|
1995
|
+
const nodeId = `doc:${relPath}`;
|
|
1996
|
+
if (this.store.getNode(nodeId)) continue;
|
|
1997
|
+
this.store.addNode(parseDocumentNode(nodeId, filePath, relPath, content));
|
|
1998
|
+
nodesAdded++;
|
|
1999
|
+
edgesAdded += this.linkToCode(content, nodeId, "documents");
|
|
2000
|
+
} catch (err) {
|
|
2001
|
+
errors.push(`${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
return buildResult(nodesAdded, edgesAdded, errors, start);
|
|
2005
|
+
}
|
|
1965
2006
|
async ingestAll(projectPath, opts) {
|
|
1966
2007
|
const start = Date.now();
|
|
1967
2008
|
const adrDir = opts?.adrDir ?? path3.join(projectPath, "docs", "adr");
|
|
1968
|
-
const [adrResult, learningsResult, failuresResult] = await Promise.all([
|
|
2009
|
+
const [adrResult, learningsResult, failuresResult, docsResult] = await Promise.all([
|
|
1969
2010
|
this.ingestADRs(adrDir),
|
|
1970
2011
|
this.ingestLearnings(projectPath),
|
|
1971
|
-
this.ingestFailures(projectPath)
|
|
2012
|
+
this.ingestFailures(projectPath),
|
|
2013
|
+
this.ingestGeneralDocs(projectPath)
|
|
1972
2014
|
]);
|
|
1973
|
-
const merged = mergeResults(adrResult, learningsResult, failuresResult);
|
|
2015
|
+
const merged = mergeResults(adrResult, learningsResult, failuresResult, docsResult);
|
|
1974
2016
|
return { ...merged, durationMs: Date.now() - start };
|
|
1975
2017
|
}
|
|
1976
2018
|
linkToCode(content, sourceNodeId, edgeType) {
|
|
@@ -2005,7 +2047,22 @@ var KnowledgeIngestor = class {
|
|
|
2005
2047
|
const entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
2006
2048
|
for (const entry of entries) {
|
|
2007
2049
|
const fullPath = path3.join(dir, entry.name);
|
|
2008
|
-
if (entry.isDirectory() &&
|
|
2050
|
+
if (entry.isDirectory() && !DEFAULT_SKIP_DIRS.has(entry.name)) {
|
|
2051
|
+
results.push(...await this.findMarkdownFiles(fullPath));
|
|
2052
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
2053
|
+
results.push(fullPath);
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
return results;
|
|
2057
|
+
}
|
|
2058
|
+
async scanDocsDir(docsRoot) {
|
|
2059
|
+
const results = [];
|
|
2060
|
+
const rootEntries = await fs2.readdir(docsRoot, { withFileTypes: true });
|
|
2061
|
+
for (const entry of rootEntries) {
|
|
2062
|
+
const fullPath = path3.join(docsRoot, entry.name);
|
|
2063
|
+
if (entry.isDirectory()) {
|
|
2064
|
+
if (DEFAULT_SKIP_DIRS.has(entry.name)) continue;
|
|
2065
|
+
if (DOCS_OWNED_BY_OTHER_INGESTORS.has(entry.name)) continue;
|
|
2009
2066
|
results.push(...await this.findMarkdownFiles(fullPath));
|
|
2010
2067
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
2011
2068
|
results.push(fullPath);
|
|
@@ -2031,6 +2088,17 @@ function buildResult(nodesAdded, edgesAdded, errors, start) {
|
|
|
2031
2088
|
durationMs: Date.now() - start
|
|
2032
2089
|
};
|
|
2033
2090
|
}
|
|
2091
|
+
function parseDocumentNode(nodeId, filePath, relPath, content) {
|
|
2092
|
+
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
2093
|
+
const title = titleMatch ? titleMatch[1].trim() : path3.basename(filePath, ".md");
|
|
2094
|
+
return {
|
|
2095
|
+
id: nodeId,
|
|
2096
|
+
type: "document",
|
|
2097
|
+
name: title,
|
|
2098
|
+
path: filePath,
|
|
2099
|
+
metadata: { relPath }
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2034
2102
|
function parseADRNode(nodeId, filePath, filename, content) {
|
|
2035
2103
|
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
2036
2104
|
const title = titleMatch ? titleMatch[1].trim() : filename;
|
|
@@ -2317,7 +2385,7 @@ var BusinessKnowledgeIngestor = class {
|
|
|
2317
2385
|
const entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
2318
2386
|
for (const entry of entries) {
|
|
2319
2387
|
const fullPath = path4.join(dir, entry.name);
|
|
2320
|
-
if (entry.isDirectory() &&
|
|
2388
|
+
if (entry.isDirectory() && !DEFAULT_SKIP_DIRS.has(entry.name)) {
|
|
2321
2389
|
results.push(...await this.findMarkdownFiles(fullPath));
|
|
2322
2390
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
2323
2391
|
results.push(fullPath);
|
|
@@ -3161,7 +3229,6 @@ var PlantUmlParser = class {
|
|
|
3161
3229
|
|
|
3162
3230
|
// src/ingest/DiagramParser.ts
|
|
3163
3231
|
var DIAGRAM_EXTENSIONS = /* @__PURE__ */ new Set([".mmd", ".mermaid", ".d2", ".puml", ".plantuml"]);
|
|
3164
|
-
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".harness"]);
|
|
3165
3232
|
var DiagramParser = class {
|
|
3166
3233
|
constructor(store) {
|
|
3167
3234
|
this.store = store;
|
|
@@ -3266,7 +3333,7 @@ var DiagramParser = class {
|
|
|
3266
3333
|
}
|
|
3267
3334
|
for (const entry of entries) {
|
|
3268
3335
|
if (entry.isDirectory()) {
|
|
3269
|
-
if (!
|
|
3336
|
+
if (!DEFAULT_SKIP_DIRS.has(entry.name)) {
|
|
3270
3337
|
await walk(path7.join(currentDir, entry.name));
|
|
3271
3338
|
}
|
|
3272
3339
|
} else if (entry.isFile()) {
|
|
@@ -3790,31 +3857,6 @@ var KnowledgeStagingAggregator = class {
|
|
|
3790
3857
|
// src/ingest/extractors/ExtractionRunner.ts
|
|
3791
3858
|
import * as fs9 from "fs/promises";
|
|
3792
3859
|
import * as path10 from "path";
|
|
3793
|
-
var SKIP_DIRS2 = /* @__PURE__ */ new Set([
|
|
3794
|
-
"node_modules",
|
|
3795
|
-
"dist",
|
|
3796
|
-
"target",
|
|
3797
|
-
"build",
|
|
3798
|
-
".git",
|
|
3799
|
-
"__pycache__",
|
|
3800
|
-
".venv",
|
|
3801
|
-
".turbo",
|
|
3802
|
-
".harness",
|
|
3803
|
-
".next",
|
|
3804
|
-
".vscode",
|
|
3805
|
-
".idea",
|
|
3806
|
-
"vendor",
|
|
3807
|
-
"out",
|
|
3808
|
-
".gradle",
|
|
3809
|
-
".gradle-home",
|
|
3810
|
-
"bin",
|
|
3811
|
-
"obj",
|
|
3812
|
-
"venv",
|
|
3813
|
-
"_build",
|
|
3814
|
-
"deps",
|
|
3815
|
-
"coverage",
|
|
3816
|
-
".nyc_output"
|
|
3817
|
-
]);
|
|
3818
3860
|
var EXT_TO_LANGUAGE = {
|
|
3819
3861
|
".ts": "typescript",
|
|
3820
3862
|
".tsx": "typescript",
|
|
@@ -3993,7 +4035,7 @@ var ExtractionRunner = class {
|
|
|
3993
4035
|
}
|
|
3994
4036
|
for (const entry of entries) {
|
|
3995
4037
|
const fullPath = path10.join(dir, entry.name);
|
|
3996
|
-
if (entry.isDirectory() && !
|
|
4038
|
+
if (entry.isDirectory() && !DEFAULT_SKIP_DIRS.has(entry.name)) {
|
|
3997
4039
|
results.push(...await this.findSourceFiles(fullPath));
|
|
3998
4040
|
} else if (entry.isFile() && detectLanguage(fullPath) !== void 0) {
|
|
3999
4041
|
results.push(fullPath);
|
|
@@ -9003,7 +9045,7 @@ function queryTraceability(store, options) {
|
|
|
9003
9045
|
|
|
9004
9046
|
// src/constraints/GraphConstraintAdapter.ts
|
|
9005
9047
|
import { minimatch as minimatch2 } from "minimatch";
|
|
9006
|
-
import { relative as
|
|
9048
|
+
import { relative as relative6 } from "path";
|
|
9007
9049
|
var GraphConstraintAdapter = class {
|
|
9008
9050
|
constructor(store) {
|
|
9009
9051
|
this.store = store;
|
|
@@ -9032,8 +9074,8 @@ var GraphConstraintAdapter = class {
|
|
|
9032
9074
|
const { edges } = this.computeDependencyGraph();
|
|
9033
9075
|
const violations = [];
|
|
9034
9076
|
for (const edge of edges) {
|
|
9035
|
-
const fromRelative =
|
|
9036
|
-
const toRelative =
|
|
9077
|
+
const fromRelative = relative6(rootDir, edge.from).replaceAll("\\", "/");
|
|
9078
|
+
const toRelative = relative6(rootDir, edge.to).replaceAll("\\", "/");
|
|
9037
9079
|
const fromLayer = this.resolveLayer(fromRelative, layers);
|
|
9038
9080
|
const toLayer = this.resolveLayer(toRelative, layers);
|
|
9039
9081
|
if (!fromLayer || !toLayer) continue;
|
|
@@ -9226,6 +9268,16 @@ var DesignIngestor = class {
|
|
|
9226
9268
|
};
|
|
9227
9269
|
|
|
9228
9270
|
// src/constraints/DesignConstraintAdapter.ts
|
|
9271
|
+
var CODE_PREFIX_LABELS = {
|
|
9272
|
+
"ANAT-D": "Component anatomy (definition)",
|
|
9273
|
+
"ANAT-P": "Component anatomy (pattern presence)",
|
|
9274
|
+
"ANAT-U": "Component anatomy (usage)",
|
|
9275
|
+
"CRAFT-C": "Design craft (critique)",
|
|
9276
|
+
"CRAFT-P": "Design craft (polish)",
|
|
9277
|
+
"CRAFT-B": "Design craft (benchmark)",
|
|
9278
|
+
"DESIGN-": "Design constraint (legacy)",
|
|
9279
|
+
"A11Y-": "Accessibility"
|
|
9280
|
+
};
|
|
9229
9281
|
var DesignConstraintAdapter = class {
|
|
9230
9282
|
constructor(store) {
|
|
9231
9283
|
this.store = store;
|
|
@@ -9307,6 +9359,76 @@ var DesignConstraintAdapter = class {
|
|
|
9307
9359
|
return "error";
|
|
9308
9360
|
}
|
|
9309
9361
|
}
|
|
9362
|
+
/**
|
|
9363
|
+
* Record externally-computed craft findings (audit-component-anatomy,
|
|
9364
|
+
* harness-design-craft, etc.) as graph state. Idempotent — re-running on
|
|
9365
|
+
* the same findings produces no duplicate nodes or edges thanks to
|
|
9366
|
+
* GraphStore's keyed merge semantics.
|
|
9367
|
+
*
|
|
9368
|
+
* Each finding becomes:
|
|
9369
|
+
* • a `design_constraint` node keyed by finding code (created lazily
|
|
9370
|
+
* if absent; metadata merged on re-record so the most recent message
|
|
9371
|
+
* / severity wins)
|
|
9372
|
+
* • a `violates_design` edge from the source file (id = file path) to
|
|
9373
|
+
* the constraint node, with per-finding metadata (line, severity,
|
|
9374
|
+
* message, evidence, runId)
|
|
9375
|
+
*
|
|
9376
|
+
* The file node is NOT created here — it's assumed to already exist in
|
|
9377
|
+
* the graph from a prior ingest. If it does not, the edge will still be
|
|
9378
|
+
* created (graph stores edges by key, not by referential integrity) and
|
|
9379
|
+
* a subsequent ingest will populate the file node.
|
|
9380
|
+
*/
|
|
9381
|
+
recordFindings(findings) {
|
|
9382
|
+
let constraintsAdded = 0;
|
|
9383
|
+
let edgesAdded = 0;
|
|
9384
|
+
const seenConstraintIds = /* @__PURE__ */ new Set();
|
|
9385
|
+
for (const finding of findings) {
|
|
9386
|
+
const constraintId = `design_constraint:${finding.code}`;
|
|
9387
|
+
if (!seenConstraintIds.has(finding.code)) {
|
|
9388
|
+
const existing = this.store.getNode(constraintId);
|
|
9389
|
+
if (!existing) constraintsAdded += 1;
|
|
9390
|
+
this.store.addNode({
|
|
9391
|
+
id: constraintId,
|
|
9392
|
+
type: "design_constraint",
|
|
9393
|
+
name: finding.code,
|
|
9394
|
+
metadata: {
|
|
9395
|
+
code: finding.code,
|
|
9396
|
+
label: this.labelForCode(finding.code),
|
|
9397
|
+
mostRecentMessage: finding.message,
|
|
9398
|
+
mostRecentSeverity: finding.severity
|
|
9399
|
+
}
|
|
9400
|
+
});
|
|
9401
|
+
seenConstraintIds.add(finding.code);
|
|
9402
|
+
}
|
|
9403
|
+
const fileId = finding.file;
|
|
9404
|
+
const edgeMetadata = {
|
|
9405
|
+
message: finding.message,
|
|
9406
|
+
severity: finding.severity
|
|
9407
|
+
};
|
|
9408
|
+
if (finding.line !== void 0) edgeMetadata.line = finding.line;
|
|
9409
|
+
if (finding.evidence !== void 0) edgeMetadata.evidence = finding.evidence;
|
|
9410
|
+
if (finding.runId !== void 0) edgeMetadata.runId = finding.runId;
|
|
9411
|
+
const before = this.store.getEdges({
|
|
9412
|
+
from: fileId,
|
|
9413
|
+
to: constraintId,
|
|
9414
|
+
type: "violates_design"
|
|
9415
|
+
});
|
|
9416
|
+
this.store.addEdge({
|
|
9417
|
+
from: fileId,
|
|
9418
|
+
to: constraintId,
|
|
9419
|
+
type: "violates_design",
|
|
9420
|
+
metadata: edgeMetadata
|
|
9421
|
+
});
|
|
9422
|
+
if (before.length === 0) edgesAdded += 1;
|
|
9423
|
+
}
|
|
9424
|
+
return { constraintsAdded, edgesAdded };
|
|
9425
|
+
}
|
|
9426
|
+
labelForCode(code) {
|
|
9427
|
+
for (const prefix of Object.keys(CODE_PREFIX_LABELS)) {
|
|
9428
|
+
if (code.startsWith(prefix)) return CODE_PREFIX_LABELS[prefix];
|
|
9429
|
+
}
|
|
9430
|
+
return "Design constraint";
|
|
9431
|
+
}
|
|
9310
9432
|
};
|
|
9311
9433
|
|
|
9312
9434
|
// src/feedback/GraphFeedbackAdapter.ts
|
|
@@ -9834,7 +9956,7 @@ var ConflictPredictor = class {
|
|
|
9834
9956
|
};
|
|
9835
9957
|
|
|
9836
9958
|
// src/index.ts
|
|
9837
|
-
var VERSION = "0.
|
|
9959
|
+
var VERSION = "0.9.0";
|
|
9838
9960
|
export {
|
|
9839
9961
|
ALL_EXTRACTORS,
|
|
9840
9962
|
ApiPathExtractor,
|
|
@@ -9914,5 +10036,6 @@ export {
|
|
|
9914
10036
|
project,
|
|
9915
10037
|
queryTraceability,
|
|
9916
10038
|
resolveSkipDirs,
|
|
9917
|
-
saveGraph
|
|
10039
|
+
saveGraph,
|
|
10040
|
+
skipDirGlobs
|
|
9918
10041
|
};
|