@neurcode-ai/cli 0.9.50 → 0.9.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/commands/fix.d.ts.map +1 -1
  2. package/dist/commands/fix.js +307 -31
  3. package/dist/commands/fix.js.map +1 -1
  4. package/dist/commands/verify.d.ts.map +1 -1
  5. package/dist/commands/verify.js +264 -13
  6. package/dist/commands/verify.js.map +1 -1
  7. package/dist/daemon/server.d.ts +23 -0
  8. package/dist/daemon/server.d.ts.map +1 -0
  9. package/dist/daemon/server.js +226 -0
  10. package/dist/daemon/server.js.map +1 -0
  11. package/dist/index.js +8 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/intent-engine/coverage.d.ts +69 -0
  14. package/dist/intent-engine/coverage.d.ts.map +1 -0
  15. package/dist/intent-engine/coverage.js +140 -0
  16. package/dist/intent-engine/coverage.js.map +1 -0
  17. package/dist/intent-engine/flow-rules.d.ts +21 -0
  18. package/dist/intent-engine/flow-rules.d.ts.map +1 -0
  19. package/dist/intent-engine/flow-rules.js +83 -0
  20. package/dist/intent-engine/flow-rules.js.map +1 -0
  21. package/dist/intent-engine/flow-validator.d.ts +29 -0
  22. package/dist/intent-engine/flow-validator.d.ts.map +1 -0
  23. package/dist/intent-engine/flow-validator.js +202 -0
  24. package/dist/intent-engine/flow-validator.js.map +1 -0
  25. package/dist/intent-engine/graph.d.ts +33 -0
  26. package/dist/intent-engine/graph.d.ts.map +1 -0
  27. package/dist/intent-engine/graph.js +67 -0
  28. package/dist/intent-engine/graph.js.map +1 -0
  29. package/dist/intent-engine/index.d.ts +35 -0
  30. package/dist/intent-engine/index.d.ts.map +1 -0
  31. package/dist/intent-engine/index.js +94 -0
  32. package/dist/intent-engine/index.js.map +1 -0
  33. package/dist/intent-engine/indexer.d.ts +18 -0
  34. package/dist/intent-engine/indexer.d.ts.map +1 -0
  35. package/dist/intent-engine/indexer.js +100 -0
  36. package/dist/intent-engine/indexer.js.map +1 -0
  37. package/dist/intent-engine/matcher.d.ts +35 -0
  38. package/dist/intent-engine/matcher.d.ts.map +1 -0
  39. package/dist/intent-engine/matcher.js +522 -0
  40. package/dist/intent-engine/matcher.js.map +1 -0
  41. package/dist/intent-engine/parser.d.ts +12 -0
  42. package/dist/intent-engine/parser.d.ts.map +1 -0
  43. package/dist/intent-engine/parser.js +93 -0
  44. package/dist/intent-engine/parser.js.map +1 -0
  45. package/dist/intent-engine/regression.d.ts +32 -0
  46. package/dist/intent-engine/regression.d.ts.map +1 -0
  47. package/dist/intent-engine/regression.js +166 -0
  48. package/dist/intent-engine/regression.js.map +1 -0
  49. package/dist/intent-engine/requirements.d.ts +22 -0
  50. package/dist/intent-engine/requirements.d.ts.map +1 -0
  51. package/dist/intent-engine/requirements.js +147 -0
  52. package/dist/intent-engine/requirements.js.map +1 -0
  53. package/dist/intent-engine/state.d.ts +44 -0
  54. package/dist/intent-engine/state.d.ts.map +1 -0
  55. package/dist/intent-engine/state.js +83 -0
  56. package/dist/intent-engine/state.js.map +1 -0
  57. package/dist/utils/ai-debt-budget.d.ts +3 -2
  58. package/dist/utils/ai-debt-budget.d.ts.map +1 -1
  59. package/dist/utils/ai-debt-budget.js +83 -2
  60. package/dist/utils/ai-debt-budget.js.map +1 -1
  61. package/package.json +1 -1
@@ -0,0 +1,35 @@
1
+ export { parseIntent, type ParsedIntent } from './parser';
2
+ export { indexDiffFiles, type FileMeta, type FileLayer } from './indexer';
3
+ export { matchIntentToCode, type IntentIssue, type MatchResult, type ComponentQualityLevel, } from './matcher';
4
+ export { computeCoverage, computeIntentSummary, formatCoverageBar, formatComponentLabel, type DomainCoverage, type IntentSummary, type ConfidenceLevel, type SystemStatus, } from './coverage';
5
+ export { requirementsForDomain, labelForComponent, type ComponentKey } from './requirements';
6
+ export { buildFlowGraph, type FileNode, type GraphLayer } from './graph';
7
+ export { validateFlows, type FlowIssue } from './flow-validator';
8
+ export { type FlowRule, type FlowRuleType } from './flow-rules';
9
+ export { loadPreviousState, saveCurrentState, buildCurrentState, type IntentState } from './state';
10
+ export { detectRegressions, type RegressionIssue, type RegressionType } from './regression';
11
+ import type { DiffFile } from '@neurcode-ai/diff-parser';
12
+ import { type IntentIssue, type ComponentQualityLevel } from './matcher';
13
+ import { type IntentSummary } from './coverage';
14
+ import { type FlowIssue } from './flow-validator';
15
+ import { type RegressionIssue } from './regression';
16
+ export interface IntentEngineResult {
17
+ intentIssues: IntentIssue[];
18
+ checkedDomains: string[];
19
+ foundComponents: Record<string, string[]>;
20
+ componentMap: Record<string, string[]>;
21
+ componentQuality: Record<string, ComponentQualityLevel>;
22
+ intentSummary: IntentSummary | null;
23
+ /** V5: wiring and connectivity issues between components */
24
+ flowIssues: FlowIssue[];
25
+ /** V6: previously-working behaviour that has now degraded */
26
+ regressions: RegressionIssue[];
27
+ intentText: string;
28
+ }
29
+ /**
30
+ * Single entry point: parse intent → index → match → coverage → flow → regression.
31
+ * Returns empty result if intent is blank or diff is empty.
32
+ * Never throws — errors are caught and return a safe empty result.
33
+ */
34
+ export declare function runIntentEngine(intentText: string, diffFiles: DiffFile[], projectRoot?: string): IntentEngineResult;
35
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/intent-engine/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EACL,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,qBAAqB,GAC3B,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAE5F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGzD,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAC5F,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAEtE,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEjE,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAEvE,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1C,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IACxD,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC,4DAA4D;IAC5D,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,6DAA6D;IAC7D,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAaD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,QAAQ,EAAE,EACrB,WAAW,CAAC,EAAE,MAAM,GACnB,kBAAkB,CA2DpB"}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectRegressions = exports.buildCurrentState = exports.saveCurrentState = exports.loadPreviousState = exports.validateFlows = exports.buildFlowGraph = exports.labelForComponent = exports.requirementsForDomain = exports.formatComponentLabel = exports.formatCoverageBar = exports.computeIntentSummary = exports.computeCoverage = exports.matchIntentToCode = exports.indexDiffFiles = exports.parseIntent = void 0;
4
+ exports.runIntentEngine = runIntentEngine;
5
+ var parser_1 = require("./parser");
6
+ Object.defineProperty(exports, "parseIntent", { enumerable: true, get: function () { return parser_1.parseIntent; } });
7
+ var indexer_1 = require("./indexer");
8
+ Object.defineProperty(exports, "indexDiffFiles", { enumerable: true, get: function () { return indexer_1.indexDiffFiles; } });
9
+ var matcher_1 = require("./matcher");
10
+ Object.defineProperty(exports, "matchIntentToCode", { enumerable: true, get: function () { return matcher_1.matchIntentToCode; } });
11
+ var coverage_1 = require("./coverage");
12
+ Object.defineProperty(exports, "computeCoverage", { enumerable: true, get: function () { return coverage_1.computeCoverage; } });
13
+ Object.defineProperty(exports, "computeIntentSummary", { enumerable: true, get: function () { return coverage_1.computeIntentSummary; } });
14
+ Object.defineProperty(exports, "formatCoverageBar", { enumerable: true, get: function () { return coverage_1.formatCoverageBar; } });
15
+ Object.defineProperty(exports, "formatComponentLabel", { enumerable: true, get: function () { return coverage_1.formatComponentLabel; } });
16
+ var requirements_1 = require("./requirements");
17
+ Object.defineProperty(exports, "requirementsForDomain", { enumerable: true, get: function () { return requirements_1.requirementsForDomain; } });
18
+ Object.defineProperty(exports, "labelForComponent", { enumerable: true, get: function () { return requirements_1.labelForComponent; } });
19
+ var graph_1 = require("./graph");
20
+ Object.defineProperty(exports, "buildFlowGraph", { enumerable: true, get: function () { return graph_1.buildFlowGraph; } });
21
+ var flow_validator_1 = require("./flow-validator");
22
+ Object.defineProperty(exports, "validateFlows", { enumerable: true, get: function () { return flow_validator_1.validateFlows; } });
23
+ var state_1 = require("./state");
24
+ Object.defineProperty(exports, "loadPreviousState", { enumerable: true, get: function () { return state_1.loadPreviousState; } });
25
+ Object.defineProperty(exports, "saveCurrentState", { enumerable: true, get: function () { return state_1.saveCurrentState; } });
26
+ Object.defineProperty(exports, "buildCurrentState", { enumerable: true, get: function () { return state_1.buildCurrentState; } });
27
+ var regression_1 = require("./regression");
28
+ Object.defineProperty(exports, "detectRegressions", { enumerable: true, get: function () { return regression_1.detectRegressions; } });
29
+ const parser_2 = require("./parser");
30
+ const indexer_2 = require("./indexer");
31
+ const matcher_2 = require("./matcher");
32
+ const coverage_2 = require("./coverage");
33
+ const graph_2 = require("./graph");
34
+ const flow_validator_2 = require("./flow-validator");
35
+ const state_2 = require("./state");
36
+ const regression_2 = require("./regression");
37
+ const EMPTY_RESULT = {
38
+ intentIssues: [],
39
+ checkedDomains: [],
40
+ foundComponents: {},
41
+ componentMap: {},
42
+ componentQuality: {},
43
+ intentSummary: null,
44
+ flowIssues: [],
45
+ regressions: [],
46
+ };
47
+ /**
48
+ * Single entry point: parse intent → index → match → coverage → flow → regression.
49
+ * Returns empty result if intent is blank or diff is empty.
50
+ * Never throws — errors are caught and return a safe empty result.
51
+ */
52
+ function runIntentEngine(intentText, diffFiles, projectRoot) {
53
+ try {
54
+ const parsed = (0, parser_2.parseIntent)(intentText);
55
+ if (parsed.domains.length === 0) {
56
+ return { ...EMPTY_RESULT, intentText };
57
+ }
58
+ const index = (0, indexer_2.indexDiffFiles)(diffFiles);
59
+ const { intentIssues, checkedDomains, foundComponents, componentMap, componentQuality } = (0, matcher_2.matchIntentToCode)(parsed, index);
60
+ const intentSummary = (0, coverage_2.computeIntentSummary)(checkedDomains, foundComponents, componentMap, componentQuality);
61
+ // V5: build dependency graph and run flow validation
62
+ const graph = (0, graph_2.buildFlowGraph)(index);
63
+ const flowIssues = (0, flow_validator_2.validateFlows)(checkedDomains, componentMap, graph);
64
+ // V6: regression detection
65
+ let regressions = [];
66
+ if (projectRoot) {
67
+ try {
68
+ const previousState = (0, state_2.loadPreviousState)(projectRoot);
69
+ regressions = (0, regression_2.detectRegressions)(previousState, intentSummary, flowIssues, componentMap, intentText);
70
+ // Persist current state for the next run
71
+ const flowIssueIds = flowIssues.map((fi) => fi.rule);
72
+ (0, state_2.saveCurrentState)(projectRoot, (0, state_2.buildCurrentState)(intentText, intentSummary, flowIssueIds, componentMap));
73
+ }
74
+ catch {
75
+ // Non-fatal: regression errors must never break verification
76
+ }
77
+ }
78
+ return {
79
+ intentIssues,
80
+ checkedDomains,
81
+ foundComponents,
82
+ componentMap,
83
+ componentQuality,
84
+ intentSummary,
85
+ flowIssues,
86
+ regressions,
87
+ intentText,
88
+ };
89
+ }
90
+ catch {
91
+ return { ...EMPTY_RESULT, intentText };
92
+ }
93
+ }
94
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/intent-engine/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Code Indexer — builds a lightweight FileMeta index from diff hunks.
3
+ * Operates entirely on the parsed diff (no disk I/O beyond what the diff
4
+ * parser has already done), so it adds negligible time to verify.
5
+ */
6
+ import type { DiffFile } from '@neurcode-ai/diff-parser';
7
+ export type FileLayer = 'ui' | 'api' | 'service' | 'core' | 'config' | 'test' | 'unknown';
8
+ export interface FileMeta {
9
+ path: string;
10
+ layer: FileLayer;
11
+ imports: string[];
12
+ keywords: string[];
13
+ addedLines: number;
14
+ removedLines: number;
15
+ addedContent: string;
16
+ }
17
+ export declare function indexDiffFiles(diffFiles: DiffFile[]): Map<string, FileMeta>;
18
+ //# sourceMappingURL=indexer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../../src/intent-engine/indexer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAUzD,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AA+D1F,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IAErB,YAAY,EAAE,MAAM,CAAC;CACtB;AAID,wBAAgB,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CA0B3E"}
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ /**
3
+ * Code Indexer — builds a lightweight FileMeta index from diff hunks.
4
+ * Operates entirely on the parsed diff (no disk I/O beyond what the diff
5
+ * parser has already done), so it adds negligible time to verify.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.indexDiffFiles = indexDiffFiles;
9
+ // ── Layer detection ───────────────────────────────────────────────────────────
10
+ const UI_PATH = /(\/|^)(components?|pages?|views?|screens?|containers?|ui)[/\\]|\.tsx$/i;
11
+ const API_PATH = /(\/|^)(routes?|controllers?|handlers?|api|endpoints?)[/\\]/i;
12
+ const SERVICE_PATH = /(\/|^)(services?|repositories?|domain|usecases?)[/\\]/i;
13
+ const TEST_PATH = /\.(test|spec)\.[jt]sx?$|(\/|^)(__tests?__|tests?)[/\\]/i;
14
+ const CONFIG_PATH = /(\/|^)(config|configs?|settings?)[/\\]|\.config\.[jt]sx?$/i;
15
+ function inferLayer(filePath) {
16
+ if (TEST_PATH.test(filePath))
17
+ return 'test';
18
+ if (UI_PATH.test(filePath))
19
+ return 'ui';
20
+ if (API_PATH.test(filePath))
21
+ return 'api';
22
+ if (SERVICE_PATH.test(filePath))
23
+ return 'service';
24
+ if (CONFIG_PATH.test(filePath))
25
+ return 'config';
26
+ return 'unknown';
27
+ }
28
+ // ── Keyword extraction ────────────────────────────────────────────────────────
29
+ const IMPORT_RE = /import\s+.*from\s+['"]([^'"]+)['"]/g;
30
+ const REQUIRE_RE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
31
+ function extractImports(code) {
32
+ const imports = [];
33
+ let m;
34
+ IMPORT_RE.lastIndex = 0;
35
+ while ((m = IMPORT_RE.exec(code)) !== null)
36
+ imports.push(m[1]);
37
+ REQUIRE_RE.lastIndex = 0;
38
+ while ((m = REQUIRE_RE.exec(code)) !== null)
39
+ imports.push(m[1]);
40
+ return imports;
41
+ }
42
+ const KEYWORD_TOKENS = new Set([
43
+ // auth
44
+ 'jwt', 'token', 'session', 'login', 'logout', 'auth', 'password', 'hash',
45
+ 'bcrypt', 'role', 'permission', 'bearer', 'oauth', 'middleware',
46
+ // validation
47
+ 'validate', 'validation', 'schema', 'zod', 'joi', 'yup', 'sanitize',
48
+ 'sanitization', 'parse',
49
+ // db
50
+ 'prisma', 'db', 'database', 'query', 'findMany', 'findOne', 'create',
51
+ 'update', 'delete', 'transaction', 'pool', 'knex', 'sequelize',
52
+ // api
53
+ 'req', 'res', 'request', 'response', 'router', 'route', 'endpoint',
54
+ 'controller', 'handler', 'express', 'fastify', 'hono', 'next',
55
+ // payment
56
+ 'stripe', 'payment', 'checkout', 'invoice', 'billing', 'webhook',
57
+ // security
58
+ 'encrypt', 'decrypt', 'crypto', 'hmac', 'tls', 'ssl',
59
+ // test
60
+ 'describe', 'it', 'test', 'expect', 'mock', 'beforeEach', 'afterEach',
61
+ ]);
62
+ function extractKeywords(code) {
63
+ const tokens = code.split(/\W+/).filter(Boolean);
64
+ const found = [];
65
+ const seen = new Set();
66
+ for (const tok of tokens) {
67
+ const lower = tok.toLowerCase();
68
+ if (KEYWORD_TOKENS.has(lower) && !seen.has(lower)) {
69
+ found.push(lower);
70
+ seen.add(lower);
71
+ }
72
+ }
73
+ return found;
74
+ }
75
+ // ── Public API ────────────────────────────────────────────────────────────────
76
+ function indexDiffFiles(diffFiles) {
77
+ const index = new Map();
78
+ for (const file of diffFiles) {
79
+ const addedLines = [];
80
+ for (const hunk of file.hunks ?? []) {
81
+ for (const line of hunk.lines ?? []) {
82
+ if (line.type === 'added')
83
+ addedLines.push(line.content);
84
+ }
85
+ }
86
+ const addedContent = addedLines.join('\n');
87
+ const meta = {
88
+ path: file.path,
89
+ layer: inferLayer(file.path),
90
+ imports: extractImports(addedContent),
91
+ keywords: extractKeywords(addedContent),
92
+ addedLines: file.addedLines,
93
+ removedLines: file.removedLines,
94
+ addedContent,
95
+ };
96
+ index.set(file.path, meta);
97
+ }
98
+ return index;
99
+ }
100
+ //# sourceMappingURL=indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.js","sourceRoot":"","sources":["../../src/intent-engine/indexer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Intent–Code Matcher — compares a ParsedIntent against a FileMeta index and
3
+ * returns:
4
+ *
5
+ * IntentIssue[] — missing / misplaced / partial issues
6
+ * componentMap — component → files where it was detected
7
+ * componentQuality — component → 'strong' | 'weak' quality signal
8
+ *
9
+ * No LLM calls. All checks are deterministic keyword/pattern matching.
10
+ */
11
+ import type { ParsedIntent } from './parser';
12
+ import type { FileMeta } from './indexer';
13
+ export interface IntentIssue {
14
+ type: 'missing' | 'misplaced' | 'partial';
15
+ message: string;
16
+ files?: string[];
17
+ severity: 'high' | 'medium';
18
+ rule: string;
19
+ }
20
+ export type ComponentQualityLevel = 'strong' | 'weak';
21
+ export interface MatchResult {
22
+ intentIssues: IntentIssue[];
23
+ checkedDomains: string[];
24
+ /** component key → files where it was detected in added diff content */
25
+ componentMap: Record<string, string[]>;
26
+ /** component key → quality of the detected implementation */
27
+ componentQuality: Record<string, ComponentQualityLevel>;
28
+ /**
29
+ * @deprecated Use componentMap instead. Kept for backward compatibility with
30
+ * coverage.ts which previously received Record<string, string[]> per domain.
31
+ */
32
+ foundComponents: Record<string, string[]>;
33
+ }
34
+ export declare function matchIntentToCode(intent: ParsedIntent, index: Map<string, FileMeta>): MatchResult;
35
+ //# sourceMappingURL=matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../src/intent-engine/matcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAI1C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,6DAA6D;IAC7D,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IACxD;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC3C;AA2cD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC3B,WAAW,CA0Hb"}