@neurcode-ai/cli 0.9.44 → 0.9.46

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 (181) hide show
  1. package/README.md +7 -3
  2. package/dist/commands/contract.js +47 -0
  3. package/dist/commands/plan.js +40 -0
  4. package/dist/commands/ship.js +10 -3
  5. package/dist/commands/verify.d.ts +2 -0
  6. package/dist/commands/verify.js +251 -118
  7. package/dist/index.js +41 -5
  8. package/dist/utils/advisory-signals.d.ts +20 -0
  9. package/dist/utils/advisory-signals.js +177 -0
  10. package/dist/utils/change-contract.d.ts +105 -1
  11. package/dist/utils/change-contract.js +685 -12
  12. package/dist/utils/diff-symbols.d.ts +10 -0
  13. package/dist/utils/diff-symbols.js +218 -0
  14. package/dist/utils/governance.d.ts +1 -0
  15. package/dist/utils/governance.js +1 -1
  16. package/dist/utils/plan-symbols.d.ts +17 -0
  17. package/dist/utils/plan-symbols.js +209 -0
  18. package/package.json +6 -14
  19. package/LICENSE +0 -201
  20. package/dist/api-client.d.ts.map +0 -1
  21. package/dist/api-client.js.map +0 -1
  22. package/dist/commands/allow.d.ts.map +0 -1
  23. package/dist/commands/allow.js.map +0 -1
  24. package/dist/commands/apply.d.ts.map +0 -1
  25. package/dist/commands/apply.js.map +0 -1
  26. package/dist/commands/approve.d.ts.map +0 -1
  27. package/dist/commands/approve.js.map +0 -1
  28. package/dist/commands/ask.d.ts.map +0 -1
  29. package/dist/commands/ask.js.map +0 -1
  30. package/dist/commands/audit.d.ts.map +0 -1
  31. package/dist/commands/audit.js.map +0 -1
  32. package/dist/commands/bootstrap.d.ts.map +0 -1
  33. package/dist/commands/bootstrap.js.map +0 -1
  34. package/dist/commands/brain.d.ts.map +0 -1
  35. package/dist/commands/brain.js.map +0 -1
  36. package/dist/commands/check.d.ts.map +0 -1
  37. package/dist/commands/check.js.map +0 -1
  38. package/dist/commands/config.d.ts.map +0 -1
  39. package/dist/commands/config.js.map +0 -1
  40. package/dist/commands/contract.d.ts.map +0 -1
  41. package/dist/commands/contract.js.map +0 -1
  42. package/dist/commands/doctor.d.ts.map +0 -1
  43. package/dist/commands/doctor.js.map +0 -1
  44. package/dist/commands/feedback.d.ts.map +0 -1
  45. package/dist/commands/feedback.js.map +0 -1
  46. package/dist/commands/guard.d.ts.map +0 -1
  47. package/dist/commands/guard.js.map +0 -1
  48. package/dist/commands/init.d.ts.map +0 -1
  49. package/dist/commands/init.js.map +0 -1
  50. package/dist/commands/login.d.ts.map +0 -1
  51. package/dist/commands/login.js.map +0 -1
  52. package/dist/commands/logout.d.ts.map +0 -1
  53. package/dist/commands/logout.js.map +0 -1
  54. package/dist/commands/map.d.ts.map +0 -1
  55. package/dist/commands/map.js.map +0 -1
  56. package/dist/commands/plan-slo.d.ts.map +0 -1
  57. package/dist/commands/plan-slo.js.map +0 -1
  58. package/dist/commands/plan.d.ts.map +0 -1
  59. package/dist/commands/plan.js.map +0 -1
  60. package/dist/commands/policy.d.ts.map +0 -1
  61. package/dist/commands/policy.js.map +0 -1
  62. package/dist/commands/prompt.d.ts.map +0 -1
  63. package/dist/commands/prompt.js.map +0 -1
  64. package/dist/commands/refactor.d.ts.map +0 -1
  65. package/dist/commands/refactor.js.map +0 -1
  66. package/dist/commands/remediate.d.ts.map +0 -1
  67. package/dist/commands/remediate.js.map +0 -1
  68. package/dist/commands/repo.d.ts.map +0 -1
  69. package/dist/commands/repo.js.map +0 -1
  70. package/dist/commands/revert.d.ts.map +0 -1
  71. package/dist/commands/revert.js.map +0 -1
  72. package/dist/commands/security.d.ts.map +0 -1
  73. package/dist/commands/security.js.map +0 -1
  74. package/dist/commands/session.d.ts.map +0 -1
  75. package/dist/commands/session.js.map +0 -1
  76. package/dist/commands/ship.d.ts.map +0 -1
  77. package/dist/commands/ship.js.map +0 -1
  78. package/dist/commands/simulate.d.ts.map +0 -1
  79. package/dist/commands/simulate.js.map +0 -1
  80. package/dist/commands/verify.d.ts.map +0 -1
  81. package/dist/commands/verify.js.map +0 -1
  82. package/dist/commands/watch.d.ts.map +0 -1
  83. package/dist/commands/watch.js.map +0 -1
  84. package/dist/commands/whoami.d.ts.map +0 -1
  85. package/dist/commands/whoami.js.map +0 -1
  86. package/dist/config.d.ts.map +0 -1
  87. package/dist/config.js.map +0 -1
  88. package/dist/index.d.ts.map +0 -1
  89. package/dist/index.js.map +0 -1
  90. package/dist/rules.d.ts.map +0 -1
  91. package/dist/rules.js.map +0 -1
  92. package/dist/services/integrations/TicketService.d.ts.map +0 -1
  93. package/dist/services/integrations/TicketService.js.map +0 -1
  94. package/dist/services/mapper/ProjectScanner.d.ts.map +0 -1
  95. package/dist/services/mapper/ProjectScanner.js.map +0 -1
  96. package/dist/services/project-knowledge-service.d.ts.map +0 -1
  97. package/dist/services/project-knowledge-service.js.map +0 -1
  98. package/dist/services/security/SecurityGuard.d.ts.map +0 -1
  99. package/dist/services/security/SecurityGuard.js.map +0 -1
  100. package/dist/services/toolbox-service.d.ts.map +0 -1
  101. package/dist/services/toolbox-service.js.map +0 -1
  102. package/dist/services/watch/BlobStore.d.ts.map +0 -1
  103. package/dist/services/watch/BlobStore.js.map +0 -1
  104. package/dist/services/watch/CommandPoller.d.ts.map +0 -1
  105. package/dist/services/watch/CommandPoller.js.map +0 -1
  106. package/dist/services/watch/Journal.d.ts.map +0 -1
  107. package/dist/services/watch/Journal.js.map +0 -1
  108. package/dist/services/watch/Sentinel.d.ts.map +0 -1
  109. package/dist/services/watch/Sentinel.js.map +0 -1
  110. package/dist/services/watch/Syncer.d.ts.map +0 -1
  111. package/dist/services/watch/Syncer.js.map +0 -1
  112. package/dist/utils/ROILogger.d.ts.map +0 -1
  113. package/dist/utils/ROILogger.js.map +0 -1
  114. package/dist/utils/RelevanceScorer.d.ts.map +0 -1
  115. package/dist/utils/RelevanceScorer.js.map +0 -1
  116. package/dist/utils/ai-debt-budget.d.ts.map +0 -1
  117. package/dist/utils/ai-debt-budget.js.map +0 -1
  118. package/dist/utils/artifact-signature.d.ts.map +0 -1
  119. package/dist/utils/artifact-signature.js.map +0 -1
  120. package/dist/utils/ask-cache.d.ts.map +0 -1
  121. package/dist/utils/ask-cache.js.map +0 -1
  122. package/dist/utils/box.d.ts.map +0 -1
  123. package/dist/utils/box.js.map +0 -1
  124. package/dist/utils/brain-context.d.ts.map +0 -1
  125. package/dist/utils/brain-context.js.map +0 -1
  126. package/dist/utils/breakage-simulator.d.ts.map +0 -1
  127. package/dist/utils/breakage-simulator.js.map +0 -1
  128. package/dist/utils/change-contract.d.ts.map +0 -1
  129. package/dist/utils/change-contract.js.map +0 -1
  130. package/dist/utils/cli-json.d.ts.map +0 -1
  131. package/dist/utils/cli-json.js.map +0 -1
  132. package/dist/utils/custom-policy-rules.d.ts.map +0 -1
  133. package/dist/utils/custom-policy-rules.js.map +0 -1
  134. package/dist/utils/git.d.ts.map +0 -1
  135. package/dist/utils/git.js.map +0 -1
  136. package/dist/utils/gitignore.d.ts.map +0 -1
  137. package/dist/utils/gitignore.js.map +0 -1
  138. package/dist/utils/governance.d.ts.map +0 -1
  139. package/dist/utils/governance.js.map +0 -1
  140. package/dist/utils/ignore.d.ts.map +0 -1
  141. package/dist/utils/ignore.js.map +0 -1
  142. package/dist/utils/manual-approvals.d.ts.map +0 -1
  143. package/dist/utils/manual-approvals.js.map +0 -1
  144. package/dist/utils/messages.d.ts.map +0 -1
  145. package/dist/utils/messages.js.map +0 -1
  146. package/dist/utils/neurcode-context.d.ts.map +0 -1
  147. package/dist/utils/neurcode-context.js.map +0 -1
  148. package/dist/utils/plan-cache.d.ts.map +0 -1
  149. package/dist/utils/plan-cache.js.map +0 -1
  150. package/dist/utils/plan-slo.d.ts.map +0 -1
  151. package/dist/utils/plan-slo.js.map +0 -1
  152. package/dist/utils/policy-audit.d.ts.map +0 -1
  153. package/dist/utils/policy-audit.js.map +0 -1
  154. package/dist/utils/policy-compiler.d.ts.map +0 -1
  155. package/dist/utils/policy-compiler.js.map +0 -1
  156. package/dist/utils/policy-exceptions.d.ts.map +0 -1
  157. package/dist/utils/policy-exceptions.js.map +0 -1
  158. package/dist/utils/policy-governance.d.ts.map +0 -1
  159. package/dist/utils/policy-governance.js.map +0 -1
  160. package/dist/utils/policy-packs.d.ts.map +0 -1
  161. package/dist/utils/policy-packs.js.map +0 -1
  162. package/dist/utils/project-detector.d.ts.map +0 -1
  163. package/dist/utils/project-detector.js.map +0 -1
  164. package/dist/utils/project-root.d.ts.map +0 -1
  165. package/dist/utils/project-root.js.map +0 -1
  166. package/dist/utils/repo-links.d.ts.map +0 -1
  167. package/dist/utils/repo-links.js.map +0 -1
  168. package/dist/utils/restore.d.ts.map +0 -1
  169. package/dist/utils/restore.js.map +0 -1
  170. package/dist/utils/runtime-guard.d.ts.map +0 -1
  171. package/dist/utils/runtime-guard.js.map +0 -1
  172. package/dist/utils/scope-telemetry.d.ts.map +0 -1
  173. package/dist/utils/scope-telemetry.js.map +0 -1
  174. package/dist/utils/secret-masking.d.ts.map +0 -1
  175. package/dist/utils/secret-masking.js.map +0 -1
  176. package/dist/utils/state.d.ts.map +0 -1
  177. package/dist/utils/state.js.map +0 -1
  178. package/dist/utils/tier.d.ts.map +0 -1
  179. package/dist/utils/tier.js.map +0 -1
  180. package/dist/utils/user-context.d.ts.map +0 -1
  181. package/dist/utils/user-context.js.map +0 -1
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.evaluateAdvisorySignals = evaluateAdvisorySignals;
4
+ function toUnixPath(filePath) {
5
+ return String(filePath || '').replace(/\\/g, '/');
6
+ }
7
+ function unique(items) {
8
+ return [...new Set(items)];
9
+ }
10
+ function isRequestLayerPath(path) {
11
+ return /(\/|^)(route|routes|controller|controllers|handler|handlers|api)(\/|$)/i.test(path);
12
+ }
13
+ function isTestPath(path) {
14
+ return /(^|\/)(__tests__|tests?|test)(\/|$)|\.(test|spec)\.[A-Za-z0-9]+$/i.test(path);
15
+ }
16
+ function isCodePath(path) {
17
+ return /\.(ts|tsx|js|jsx|mjs|cjs|py|go|java|rb|cs|php|rs|kt|swift)$/i.test(path);
18
+ }
19
+ function isInfraPath(path) {
20
+ return /(\/|^)(infra|terraform|k8s|kubernetes|helm|ansible|iac|cloudformation|pulumi|\.github\/workflows)(\/|$)/i.test(path);
21
+ }
22
+ function isAppPath(path) {
23
+ return /(\/|^)(src|app|services|packages|web)(\/|$)/i.test(path);
24
+ }
25
+ function isGeneratedArtifactPath(path) {
26
+ const normalized = path.toLowerCase();
27
+ return (normalized.endsWith('.map')
28
+ || normalized.includes('/dist/')
29
+ || normalized.includes('/build/')
30
+ || normalized.includes('/coverage/')
31
+ || normalized.includes('/.next/')
32
+ || normalized.includes('/out/')
33
+ || /\.min\.(js|css)$/.test(normalized));
34
+ }
35
+ function classifySensitiveDomains(path) {
36
+ const normalized = path.toLowerCase();
37
+ const domains = [];
38
+ if (/\b(auth|rbac|permission|acl|identity|oauth|session|jwt)\b/.test(normalized)) {
39
+ domains.push('auth');
40
+ }
41
+ if (/\b(payment|billing|invoice|refund|wallet|checkout)\b/.test(normalized)) {
42
+ domains.push('payment');
43
+ }
44
+ if (/\b(db|database|prisma|migration|sql|repository|repositories)\b/.test(normalized)) {
45
+ domains.push('data');
46
+ }
47
+ if (isInfraPath(normalized)) {
48
+ domains.push('infra');
49
+ }
50
+ return domains;
51
+ }
52
+ function findAddedLines(diffFiles) {
53
+ const lines = [];
54
+ for (const file of diffFiles) {
55
+ const filePath = toUnixPath(file.path);
56
+ for (const hunk of file.hunks || []) {
57
+ for (const line of hunk.lines || []) {
58
+ if (line.type === 'added') {
59
+ lines.push({ file: filePath, content: line.content });
60
+ }
61
+ }
62
+ }
63
+ }
64
+ return lines;
65
+ }
66
+ function limitFiles(files, max = 6) {
67
+ const deduped = unique(files);
68
+ if (deduped.length <= max)
69
+ return deduped;
70
+ return deduped.slice(0, max);
71
+ }
72
+ function evaluateAdvisorySignals(input) {
73
+ const diffFiles = input.diffFiles || [];
74
+ const changedPaths = unique(diffFiles.map((file) => toUnixPath(file.path)).filter(Boolean));
75
+ const totalFiles = input.summary?.totalFiles ?? changedPaths.length;
76
+ const totalAdded = input.summary?.totalAdded ?? 0;
77
+ const totalRemoved = input.summary?.totalRemoved ?? 0;
78
+ const signals = [];
79
+ const sensitiveDomains = new Set();
80
+ const filesBySensitiveDomain = {};
81
+ for (const path of changedPaths) {
82
+ const domains = classifySensitiveDomains(path);
83
+ for (const domain of domains) {
84
+ sensitiveDomains.add(domain);
85
+ if (!filesBySensitiveDomain[domain]) {
86
+ filesBySensitiveDomain[domain] = [];
87
+ }
88
+ filesBySensitiveDomain[domain].push(path);
89
+ }
90
+ }
91
+ if (sensitiveDomains.size >= 2) {
92
+ const domains = [...sensitiveDomains].sort((a, b) => a.localeCompare(b));
93
+ const files = limitFiles(domains.flatMap((domain) => filesBySensitiveDomain[domain] || []));
94
+ signals.push({
95
+ code: 'SENSITIVE_DOMAIN_SPAN',
96
+ severity: 'warn',
97
+ title: 'Changes span multiple sensitive domains',
98
+ detail: `Changes touch ${domains.join(' + ')} modules in one diff. ` +
99
+ 'This pattern often indicates unintended side effects or architectural drift.',
100
+ files,
101
+ });
102
+ }
103
+ const dbCallPattern = /\b(prisma|db|sequelize)\.[A-Za-z_$][A-Za-z0-9_$]*\.[A-Za-z_$][A-Za-z0-9_$]*\s*\(|\bknex\s*\(/;
104
+ const directDbRequestLayerFiles = findAddedLines(diffFiles)
105
+ .filter((line) => isRequestLayerPath(line.file) && dbCallPattern.test(line.content))
106
+ .map((line) => line.file);
107
+ if (directDbRequestLayerFiles.length > 0) {
108
+ signals.push({
109
+ code: 'DIRECT_DB_IN_REQUEST_LAYER',
110
+ severity: 'warn',
111
+ title: 'Direct DB access detected in request layer',
112
+ detail: 'Route/controller code now calls the DB directly. This can bypass service-layer controls and increase drift risk.',
113
+ files: limitFiles(directDbRequestLayerFiles),
114
+ });
115
+ }
116
+ const totalDelta = totalAdded + totalRemoved;
117
+ if (totalFiles >= 15 || totalDelta >= 600) {
118
+ signals.push({
119
+ code: 'LARGE_CHANGE_SURFACE',
120
+ severity: 'warn',
121
+ title: 'Large change surface',
122
+ detail: `This diff touches ${totalFiles} file(s) and ${totalDelta} changed line(s). ` +
123
+ 'Large surfaces reduce review certainty and raise drift probability.',
124
+ files: limitFiles(changedPaths),
125
+ });
126
+ }
127
+ const codeFilesTouched = changedPaths.filter((path) => isCodePath(path) && !isTestPath(path) && !path.startsWith('docs/'));
128
+ const nonGeneratedCodeFilesTouched = codeFilesTouched.filter((path) => !isGeneratedArtifactPath(path));
129
+ const testFilesTouched = changedPaths.filter((path) => isTestPath(path));
130
+ if (nonGeneratedCodeFilesTouched.length >= 3 && testFilesTouched.length === 0) {
131
+ signals.push({
132
+ code: 'CODE_WITHOUT_TEST_UPDATES',
133
+ severity: nonGeneratedCodeFilesTouched.length >= 8 ? 'warn' : 'info',
134
+ title: 'Code changed without test updates',
135
+ detail: `Detected ${nonGeneratedCodeFilesTouched.length} code file change(s) with no test file updates. ` +
136
+ 'Behavior drift may go unnoticed without verification tests.',
137
+ files: limitFiles(nonGeneratedCodeFilesTouched),
138
+ });
139
+ }
140
+ const infraFiles = changedPaths.filter((path) => isInfraPath(path));
141
+ const appFiles = changedPaths.filter((path) => isAppPath(path) && !isInfraPath(path));
142
+ if (infraFiles.length > 0 && appFiles.length > 0) {
143
+ signals.push({
144
+ code: 'INFRA_AND_APP_MIXED',
145
+ severity: 'warn',
146
+ title: 'Infra and app code changed together',
147
+ detail: 'This diff mixes infrastructure and application edits. Consider splitting for clearer intent and rollback safety.',
148
+ files: limitFiles([...infraFiles, ...appFiles]),
149
+ });
150
+ }
151
+ const secretPattern = /(AKIA[0-9A-Z]{16}|-----BEGIN [A-Z ]*PRIVATE KEY-----|(?:api[_-]?key|secret|password)\s*[:=]\s*(?:"[^"]{8,}"|'[^']{8,}'|`[^`]{8,}`))/i;
152
+ const possibleSecretFiles = findAddedLines(diffFiles)
153
+ .filter((line) => !isGeneratedArtifactPath(line.file))
154
+ .filter((line) => line.content.trim().length <= 240)
155
+ .filter((line) => !/\[REDACTED\]|process\.env\./i.test(line.content))
156
+ .filter((line) => secretPattern.test(line.content))
157
+ .map((line) => line.file);
158
+ if (possibleSecretFiles.length > 0) {
159
+ signals.push({
160
+ code: 'POSSIBLE_SECRET_ADDITION',
161
+ severity: 'warn',
162
+ title: 'Possible secret-like value added',
163
+ detail: 'Detected new lines resembling secrets or credentials. Validate redaction and secret management before merge.',
164
+ files: limitFiles(possibleSecretFiles),
165
+ });
166
+ }
167
+ const precedence = { warn: 0, info: 1 };
168
+ return signals
169
+ .sort((left, right) => {
170
+ const severityDelta = precedence[left.severity] - precedence[right.severity];
171
+ if (severityDelta !== 0)
172
+ return severityDelta;
173
+ return left.title.localeCompare(right.title);
174
+ })
175
+ .slice(0, 4);
176
+ }
177
+ //# sourceMappingURL=advisory-signals.js.map
@@ -10,9 +10,69 @@ export interface ChangeContract {
10
10
  intentHash: string;
11
11
  expectedFiles: string[];
12
12
  expectedFilesFingerprint: string;
13
+ planFiles?: ChangeContractPlanFile[];
14
+ expectedSymbols?: ChangeContractExpectedSymbol[];
15
+ options?: ChangeContractOptions;
13
16
  policyLockFingerprint: string | null;
14
17
  compiledPolicyFingerprint: string | null;
15
18
  }
19
+ export type ChangeContractPlanAction = 'CREATE' | 'MODIFY' | 'BLOCK';
20
+ export type ChangeContractDiffAction = 'add' | 'delete' | 'modify' | 'rename';
21
+ export type ChangeContractSymbolAction = 'CREATE' | 'MODIFY' | 'BLOCK';
22
+ export type ChangeContractSymbolType = 'function' | 'class' | 'interface' | 'type' | 'method' | 'const' | 'unknown';
23
+ export type ChangeContractDiffSymbolAction = 'add' | 'delete' | 'modify';
24
+ export interface ChangeContractPlanFile {
25
+ path: string;
26
+ action: ChangeContractPlanAction;
27
+ reason?: string;
28
+ }
29
+ export interface ChangeContractExpectedSymbol {
30
+ name: string;
31
+ action: ChangeContractSymbolAction;
32
+ type?: ChangeContractSymbolType;
33
+ file?: string;
34
+ reason?: string;
35
+ }
36
+ export interface ChangeContractOptions {
37
+ /**
38
+ * When enabled, files expected by the contract must be changed in the current diff.
39
+ * This is opt-in to avoid breaking partial/iterative delivery workflows.
40
+ */
41
+ enforceExpectedFiles?: boolean;
42
+ /**
43
+ * When enabled, diff operations are validated against planned file actions.
44
+ */
45
+ enforceActionMatching?: boolean;
46
+ /**
47
+ * Allows rename operations to satisfy MODIFY expectations.
48
+ * Defaults to true when action matching is enabled.
49
+ */
50
+ allowRenameForModify?: boolean;
51
+ /**
52
+ * When enabled, symbols expected by the contract must be present in changed symbol declarations.
53
+ */
54
+ enforceExpectedSymbols?: boolean;
55
+ /**
56
+ * When enabled, symbol-level operation matching is validated against expected symbol actions.
57
+ */
58
+ enforceSymbolActionMatching?: boolean;
59
+ /**
60
+ * When enabled (default), function/method/const symbol kinds can match compatible declarations.
61
+ */
62
+ symbolTypeRelaxedMatching?: boolean;
63
+ /**
64
+ * Allows expected symbol file constraints to fallback to basename matching.
65
+ */
66
+ symbolFileBasenameFallback?: boolean;
67
+ /**
68
+ * Tolerate this many out-of-contract file touches before failing.
69
+ */
70
+ maxUnexpectedFiles?: number;
71
+ /**
72
+ * Tolerate this many missing expected symbols before failing.
73
+ */
74
+ maxMissingExpectedSymbols?: number;
75
+ }
16
76
  export interface ReadChangeContractResult {
17
77
  path: string;
18
78
  exists: boolean;
@@ -20,9 +80,11 @@ export interface ReadChangeContractResult {
20
80
  error?: string;
21
81
  }
22
82
  export interface ChangeContractViolation {
23
- code: 'CHANGE_CONTRACT_PLAN_MISMATCH' | 'CHANGE_CONTRACT_UNEXPECTED_FILE' | 'CHANGE_CONTRACT_POLICY_LOCK_MISMATCH' | 'CHANGE_CONTRACT_COMPILED_POLICY_MISMATCH';
83
+ code: 'CHANGE_CONTRACT_PLAN_MISMATCH' | 'CHANGE_CONTRACT_UNEXPECTED_FILE' | 'CHANGE_CONTRACT_MISSING_EXPECTED_FILE' | 'CHANGE_CONTRACT_BLOCKED_FILE_TOUCHED' | 'CHANGE_CONTRACT_ACTION_MISMATCH' | 'CHANGE_CONTRACT_MISSING_EXPECTED_SYMBOL' | 'CHANGE_CONTRACT_BLOCKED_SYMBOL_TOUCHED' | 'CHANGE_CONTRACT_SYMBOL_ACTION_MISMATCH' | 'CHANGE_CONTRACT_POLICY_LOCK_MISMATCH' | 'CHANGE_CONTRACT_COMPILED_POLICY_MISMATCH';
24
84
  message: string;
25
85
  file?: string;
86
+ symbol?: string;
87
+ symbolType?: string;
26
88
  expected?: string;
27
89
  actual?: string;
28
90
  }
@@ -33,6 +95,17 @@ export interface ChangeContractEvaluation {
33
95
  expectedFiles: number;
34
96
  changedFiles: number;
35
97
  outOfContractFiles: number;
98
+ missingExpectedFiles: number;
99
+ blockedFilesTouched: number;
100
+ actionMismatches: number;
101
+ expectedSymbols: number;
102
+ changedSymbols: number;
103
+ missingExpectedSymbols: number;
104
+ blockedSymbolsTouched: number;
105
+ symbolActionMismatches: number;
106
+ symbolRenameMatches: number;
107
+ toleratedUnexpectedFiles: number;
108
+ toleratedMissingExpectedSymbols: number;
36
109
  };
37
110
  }
38
111
  export declare function createChangeContract(input: {
@@ -42,6 +115,19 @@ export declare function createChangeContract(input: {
42
115
  projectId?: string | null;
43
116
  intent: string;
44
117
  expectedFiles: string[];
118
+ planFiles?: Array<{
119
+ path: string;
120
+ action: ChangeContractPlanAction;
121
+ reason?: string;
122
+ }>;
123
+ expectedSymbols?: Array<{
124
+ name: string;
125
+ action: ChangeContractSymbolAction;
126
+ type?: ChangeContractSymbolType;
127
+ file?: string;
128
+ reason?: string;
129
+ }>;
130
+ options?: ChangeContractOptions;
45
131
  policyLockFingerprint?: string | null;
46
132
  compiledPolicyFingerprint?: string | null;
47
133
  }): ChangeContract;
@@ -51,7 +137,25 @@ export declare function readChangeContract(projectRoot: string, inputPath?: stri
51
137
  export declare function evaluateChangeContract(contract: ChangeContract, input: {
52
138
  planId: string;
53
139
  changedFiles: string[];
140
+ changedFileEntries?: Array<{
141
+ path: string;
142
+ changeType: ChangeContractDiffAction;
143
+ }>;
144
+ changedSymbols?: Array<{
145
+ name: string;
146
+ action: ChangeContractDiffSymbolAction;
147
+ type?: ChangeContractSymbolType;
148
+ file?: string;
149
+ }>;
54
150
  policyLockFingerprint?: string | null;
55
151
  compiledPolicyFingerprint?: string | null;
56
152
  }): ChangeContractEvaluation;
153
+ export interface ChangeContractViolationGroup {
154
+ key: 'out_of_scope_changes' | 'missing_expected_files' | 'blocked_files_touched' | 'file_action_mismatches' | 'missing_expected_symbols' | 'blocked_symbols_touched' | 'symbol_action_mismatches' | 'contract_metadata_mismatches' | 'other';
155
+ title: string;
156
+ impact: string;
157
+ items: string[];
158
+ count: number;
159
+ }
160
+ export declare function groupChangeContractViolations(violations: ChangeContractViolation[]): ChangeContractViolationGroup[];
57
161
  //# sourceMappingURL=change-contract.d.ts.map