@neurcode-ai/cli 0.9.66 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/.telemetry-bundle/dist/__tests__/harvest-verify.test.d.ts +1 -0
  2. package/.telemetry-bundle/dist/__tests__/harvest-verify.test.js +86 -0
  3. package/.telemetry-bundle/dist/contracts.d.ts +58 -0
  4. package/.telemetry-bundle/dist/contracts.js +8 -0
  5. package/.telemetry-bundle/dist/harvest-verify.d.ts +9 -0
  6. package/.telemetry-bundle/dist/harvest-verify.js +128 -0
  7. package/.telemetry-bundle/dist/index.d.ts +10 -0
  8. package/.telemetry-bundle/dist/index.js +22 -0
  9. package/.telemetry-bundle/dist/precision/leaderboards.d.ts +20 -0
  10. package/.telemetry-bundle/dist/precision/leaderboards.js +72 -0
  11. package/.telemetry-bundle/dist/reader.d.ts +5 -0
  12. package/.telemetry-bundle/dist/reader.js +46 -0
  13. package/.telemetry-bundle/dist/stable-json.d.ts +5 -0
  14. package/.telemetry-bundle/dist/stable-json.js +24 -0
  15. package/.telemetry-bundle/dist/store.d.ts +10 -0
  16. package/.telemetry-bundle/dist/store.js +52 -0
  17. package/.telemetry-bundle/dist/trust-scoring.d.ts +20 -0
  18. package/.telemetry-bundle/dist/trust-scoring.js +58 -0
  19. package/.telemetry-bundle/package.json +8 -0
  20. package/dist/commands/governance.d.ts +3 -0
  21. package/dist/commands/governance.d.ts.map +1 -0
  22. package/dist/commands/governance.js +390 -0
  23. package/dist/commands/governance.js.map +1 -0
  24. package/dist/commands/quickstart.js +3 -3
  25. package/dist/commands/quickstart.js.map +1 -1
  26. package/dist/commands/remediate-export.d.ts +5 -0
  27. package/dist/commands/remediate-export.d.ts.map +1 -1
  28. package/dist/commands/remediate-export.js +803 -14
  29. package/dist/commands/remediate-export.js.map +1 -1
  30. package/dist/commands/replay.d.ts.map +1 -1
  31. package/dist/commands/replay.js +14 -0
  32. package/dist/commands/replay.js.map +1 -1
  33. package/dist/commands/session.d.ts +7 -0
  34. package/dist/commands/session.d.ts.map +1 -1
  35. package/dist/commands/session.js +156 -0
  36. package/dist/commands/session.js.map +1 -1
  37. package/dist/commands/start-intent.d.ts.map +1 -1
  38. package/dist/commands/start-intent.js +61 -11
  39. package/dist/commands/start-intent.js.map +1 -1
  40. package/dist/commands/verify-guidance.d.ts +5 -0
  41. package/dist/commands/verify-guidance.d.ts.map +1 -0
  42. package/dist/commands/verify-guidance.js +49 -0
  43. package/dist/commands/verify-guidance.js.map +1 -0
  44. package/dist/commands/verify-output.d.ts +37 -0
  45. package/dist/commands/verify-output.d.ts.map +1 -0
  46. package/dist/commands/verify-output.js +572 -0
  47. package/dist/commands/verify-output.js.map +1 -0
  48. package/dist/commands/verify-render.d.ts +41 -0
  49. package/dist/commands/verify-render.d.ts.map +1 -0
  50. package/dist/commands/verify-render.js +457 -0
  51. package/dist/commands/verify-render.js.map +1 -0
  52. package/dist/commands/verify.d.ts.map +1 -1
  53. package/dist/commands/verify.js +278 -1081
  54. package/dist/commands/verify.js.map +1 -1
  55. package/dist/commands/workspace.d.ts.map +1 -1
  56. package/dist/commands/workspace.js +3 -14
  57. package/dist/commands/workspace.js.map +1 -1
  58. package/dist/context-engine/graph.d.ts.map +1 -1
  59. package/dist/context-engine/graph.js +69 -7
  60. package/dist/context-engine/graph.js.map +1 -1
  61. package/dist/context-engine/scanner.d.ts.map +1 -1
  62. package/dist/context-engine/scanner.js +9 -2
  63. package/dist/context-engine/scanner.js.map +1 -1
  64. package/dist/daemon/compatibility/execution.d.ts +42 -0
  65. package/dist/daemon/compatibility/execution.d.ts.map +1 -0
  66. package/dist/daemon/compatibility/execution.js +183 -0
  67. package/dist/daemon/compatibility/execution.js.map +1 -0
  68. package/dist/daemon/compatibility/mutation.d.ts +24 -0
  69. package/dist/daemon/compatibility/mutation.d.ts.map +1 -0
  70. package/dist/daemon/compatibility/mutation.js +724 -0
  71. package/dist/daemon/compatibility/mutation.js.map +1 -0
  72. package/dist/daemon/routes.d.ts +19 -0
  73. package/dist/daemon/routes.d.ts.map +1 -0
  74. package/dist/daemon/routes.js +123 -0
  75. package/dist/daemon/routes.js.map +1 -0
  76. package/dist/daemon/runtime/execution-bus.d.ts +217 -0
  77. package/dist/daemon/runtime/execution-bus.d.ts.map +1 -0
  78. package/dist/daemon/runtime/execution-bus.js +1420 -0
  79. package/dist/daemon/runtime/execution-bus.js.map +1 -0
  80. package/dist/daemon/runtime/workspace-runtime.d.ts +280 -0
  81. package/dist/daemon/runtime/workspace-runtime.d.ts.map +1 -0
  82. package/dist/daemon/runtime/workspace-runtime.js +1473 -0
  83. package/dist/daemon/runtime/workspace-runtime.js.map +1 -0
  84. package/dist/daemon/server.d.ts.map +1 -1
  85. package/dist/daemon/server.js +171 -874
  86. package/dist/daemon/server.js.map +1 -1
  87. package/dist/daemon/shaping.d.ts +11 -0
  88. package/dist/daemon/shaping.d.ts.map +1 -0
  89. package/dist/daemon/shaping.js +240 -0
  90. package/dist/daemon/shaping.js.map +1 -0
  91. package/dist/governance/canonical-pipeline.d.ts +2 -1
  92. package/dist/governance/canonical-pipeline.d.ts.map +1 -1
  93. package/dist/governance/canonical-pipeline.js +259 -84
  94. package/dist/governance/canonical-pipeline.js.map +1 -1
  95. package/dist/governance/structural-cache.d.ts.map +1 -1
  96. package/dist/governance/structural-cache.js +2 -7
  97. package/dist/governance/structural-cache.js.map +1 -1
  98. package/dist/index.js +230 -66
  99. package/dist/index.js.map +1 -1
  100. package/dist/utils/active-engineering-context.d.ts +12 -0
  101. package/dist/utils/active-engineering-context.d.ts.map +1 -0
  102. package/dist/utils/active-engineering-context.js +67 -0
  103. package/dist/utils/active-engineering-context.js.map +1 -0
  104. package/dist/utils/artifact-io.d.ts +33 -0
  105. package/dist/utils/artifact-io.d.ts.map +1 -0
  106. package/dist/utils/artifact-io.js +183 -0
  107. package/dist/utils/artifact-io.js.map +1 -0
  108. package/dist/utils/change-contract.d.ts +6 -2
  109. package/dist/utils/change-contract.d.ts.map +1 -1
  110. package/dist/utils/change-contract.js +175 -0
  111. package/dist/utils/change-contract.js.map +1 -1
  112. package/dist/utils/context-pack.d.ts +12 -0
  113. package/dist/utils/context-pack.d.ts.map +1 -0
  114. package/dist/utils/context-pack.js +147 -0
  115. package/dist/utils/context-pack.js.map +1 -0
  116. package/dist/utils/control-plane.d.ts +18 -0
  117. package/dist/utils/control-plane.d.ts.map +1 -1
  118. package/dist/utils/control-plane.js +31 -4
  119. package/dist/utils/control-plane.js.map +1 -1
  120. package/dist/utils/drift-intelligence.d.ts +47 -0
  121. package/dist/utils/drift-intelligence.d.ts.map +1 -0
  122. package/dist/utils/drift-intelligence.js +2099 -0
  123. package/dist/utils/drift-intelligence.js.map +1 -0
  124. package/dist/utils/execution-actions.d.ts +22 -0
  125. package/dist/utils/execution-actions.d.ts.map +1 -0
  126. package/dist/utils/execution-actions.js +103 -0
  127. package/dist/utils/execution-actions.js.map +1 -0
  128. package/dist/utils/execution-bus.d.ts +1 -214
  129. package/dist/utils/execution-bus.d.ts.map +1 -1
  130. package/dist/utils/execution-bus.js +15 -1359
  131. package/dist/utils/execution-bus.js.map +1 -1
  132. package/dist/utils/git.d.ts +1 -0
  133. package/dist/utils/git.d.ts.map +1 -1
  134. package/dist/utils/git.js +13 -3
  135. package/dist/utils/git.js.map +1 -1
  136. package/dist/utils/governance-decisions.d.ts +75 -0
  137. package/dist/utils/governance-decisions.d.ts.map +1 -0
  138. package/dist/utils/governance-decisions.js +412 -0
  139. package/dist/utils/governance-decisions.js.map +1 -0
  140. package/dist/utils/governance-provenance.d.ts +1 -1
  141. package/dist/utils/governance-provenance.d.ts.map +1 -1
  142. package/dist/utils/governance-provenance.js +5 -7
  143. package/dist/utils/governance-provenance.js.map +1 -1
  144. package/dist/utils/governance.d.ts +108 -0
  145. package/dist/utils/governance.d.ts.map +1 -1
  146. package/dist/utils/governance.js +209 -7
  147. package/dist/utils/governance.js.map +1 -1
  148. package/dist/utils/intelligence-runtime-common.d.ts +30 -0
  149. package/dist/utils/intelligence-runtime-common.d.ts.map +1 -0
  150. package/dist/utils/intelligence-runtime-common.js +156 -0
  151. package/dist/utils/intelligence-runtime-common.js.map +1 -0
  152. package/dist/utils/intent-contract-diagnostics.d.ts +9 -0
  153. package/dist/utils/intent-contract-diagnostics.d.ts.map +1 -0
  154. package/dist/utils/intent-contract-diagnostics.js +322 -0
  155. package/dist/utils/intent-contract-diagnostics.js.map +1 -0
  156. package/dist/utils/intent-pack.d.ts +15 -0
  157. package/dist/utils/intent-pack.d.ts.map +1 -0
  158. package/dist/utils/intent-pack.js +196 -0
  159. package/dist/utils/intent-pack.js.map +1 -0
  160. package/dist/utils/plan-sync.d.ts +1 -0
  161. package/dist/utils/plan-sync.d.ts.map +1 -1
  162. package/dist/utils/plan-sync.js +23 -0
  163. package/dist/utils/plan-sync.js.map +1 -1
  164. package/dist/utils/policy-decision.d.ts +5 -0
  165. package/dist/utils/policy-decision.d.ts.map +1 -0
  166. package/dist/utils/policy-decision.js +17 -0
  167. package/dist/utils/policy-decision.js.map +1 -0
  168. package/dist/utils/replay-custody.d.ts +43 -0
  169. package/dist/utils/replay-custody.d.ts.map +1 -0
  170. package/dist/utils/replay-custody.js +168 -0
  171. package/dist/utils/replay-custody.js.map +1 -0
  172. package/dist/utils/replay-runtime.d.ts +13 -0
  173. package/dist/utils/replay-runtime.d.ts.map +1 -1
  174. package/dist/utils/replay-runtime.js +96 -9
  175. package/dist/utils/replay-runtime.js.map +1 -1
  176. package/dist/utils/repository-intelligence.d.ts +9 -0
  177. package/dist/utils/repository-intelligence.d.ts.map +1 -0
  178. package/dist/utils/repository-intelligence.js +372 -0
  179. package/dist/utils/repository-intelligence.js.map +1 -0
  180. package/dist/utils/runtime-events.d.ts.map +1 -1
  181. package/dist/utils/runtime-events.js +25 -6
  182. package/dist/utils/runtime-events.js.map +1 -1
  183. package/dist/utils/semantic-contract-intelligence.d.ts +20 -0
  184. package/dist/utils/semantic-contract-intelligence.d.ts.map +1 -0
  185. package/dist/utils/semantic-contract-intelligence.js +825 -0
  186. package/dist/utils/semantic-contract-intelligence.js.map +1 -0
  187. package/dist/utils/session-continuity.d.ts +56 -0
  188. package/dist/utils/session-continuity.d.ts.map +1 -0
  189. package/dist/utils/session-continuity.js +318 -0
  190. package/dist/utils/session-continuity.js.map +1 -0
  191. package/dist/utils/verification-evidence.d.ts.map +1 -1
  192. package/dist/utils/verification-evidence.js +4 -1
  193. package/dist/utils/verification-evidence.js.map +1 -1
  194. package/dist/utils/workspace-runtime.d.ts +1 -266
  195. package/dist/utils/workspace-runtime.d.ts.map +1 -1
  196. package/dist/utils/workspace-runtime.js +15 -1412
  197. package/dist/utils/workspace-runtime.js.map +1 -1
  198. package/package.json +13 -11
  199. package/LICENSE +0 -201
@@ -0,0 +1,2099 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildDriftIntelligence = buildDriftIntelligence;
4
+ exports.buildContextAwareBlastRadius = buildContextAwareBlastRadius;
5
+ const crypto_1 = require("crypto");
6
+ const child_process_1 = require("child_process");
7
+ const fs_1 = require("fs");
8
+ const path_1 = require("path");
9
+ const intelligence_runtime_common_1 = require("./intelligence-runtime-common");
10
+ const governance_decisions_1 = require("./governance-decisions");
11
+ function hashId(parts) {
12
+ return (0, crypto_1.createHash)('sha256').update(parts.join('|')).digest('hex').slice(0, 16);
13
+ }
14
+ function governanceLineageHash(parts) {
15
+ return (0, crypto_1.createHash)('sha256').update(parts.join('|')).digest('hex').slice(0, 24);
16
+ }
17
+ function emptyDecisionSummary(sourcePath = null, expiredOverrides = 0) {
18
+ return {
19
+ sourcePath,
20
+ decisionsApplied: 0,
21
+ activeOverrides: 0,
22
+ expiredOverrides,
23
+ findingsChanged: 0,
24
+ lineage: [],
25
+ };
26
+ }
27
+ function deriveModulePath(filePath) {
28
+ const normalized = (0, intelligence_runtime_common_1.normalizeRepoPath)(filePath);
29
+ const parts = normalized.split('/').filter(Boolean);
30
+ if (parts.length <= 1)
31
+ return parts[0] || normalized;
32
+ if (['src', 'app', 'apps', 'services', 'packages', 'libs', 'lib', 'web'].includes(parts[0]) && parts.length >= 2) {
33
+ return `${parts[0]}/${parts[1]}`;
34
+ }
35
+ return parts[0];
36
+ }
37
+ function classifyArchitectureLayer(pathValue) {
38
+ const normalized = (0, intelligence_runtime_common_1.normalizeRepoPath)(pathValue).toLowerCase();
39
+ if (normalized.startsWith('.github/') || normalized.includes('/ci/'))
40
+ return 'ci';
41
+ if (normalized.startsWith('infra/')
42
+ || normalized.startsWith('terraform/')
43
+ || normalized.startsWith('helm/')
44
+ || normalized.startsWith('k8s/')
45
+ || normalized.includes('/deploy/')
46
+ || normalized.includes('/docker/')) {
47
+ return 'infra';
48
+ }
49
+ if (normalized.includes('/migrations/')
50
+ || normalized.includes('/db/')
51
+ || normalized.includes('/database/')
52
+ || normalized.includes('/models/')
53
+ || normalized.includes('/model/')
54
+ || normalized.includes('prisma')
55
+ || normalized.includes('typeorm')
56
+ || normalized.includes('sequelize')) {
57
+ return 'data';
58
+ }
59
+ if (normalized.includes('openapi')
60
+ || normalized.includes('graphql')
61
+ || normalized.includes('schema')
62
+ || normalized.includes('contract')
63
+ || normalized.includes('/dto/')
64
+ || normalized.endsWith('.proto')) {
65
+ return 'contract';
66
+ }
67
+ if (normalized.includes('/routes/')
68
+ || normalized.includes('/route/')
69
+ || normalized.includes('/controllers/')
70
+ || normalized.includes('/controller/')
71
+ || normalized.includes('/handlers/')
72
+ || normalized.includes('/handler/')
73
+ || normalized.includes('/api/')) {
74
+ return 'api';
75
+ }
76
+ if (normalized.includes('/ui/')
77
+ || normalized.includes('/web/')
78
+ || normalized.includes('/frontend/')
79
+ || normalized.includes('/components/')
80
+ || normalized.includes('/pages/')
81
+ || normalized.includes('/views/')) {
82
+ return 'ui';
83
+ }
84
+ if (normalized.includes('/worker/')
85
+ || normalized.includes('/workers/')
86
+ || normalized.includes('/queue/')
87
+ || normalized.includes('/queues/')
88
+ || normalized.includes('/events/')
89
+ || normalized.includes('/jobs/')
90
+ || normalized.includes('/job/')) {
91
+ return 'worker';
92
+ }
93
+ if (normalized.includes('/shared/')
94
+ || normalized.includes('/common/')
95
+ || normalized.includes('/lib/')
96
+ || normalized.includes('/libs/')) {
97
+ return 'shared';
98
+ }
99
+ if (normalized.startsWith('docs/') || normalized.endsWith('.md')) {
100
+ return 'docs';
101
+ }
102
+ if (normalized.endsWith('.rst')
103
+ || normalized.endsWith('.adoc')
104
+ || normalized === 'readme'
105
+ || normalized.startsWith('readme.')
106
+ || normalized === 'changelog'
107
+ || normalized.startsWith('changelog.')
108
+ || normalized === 'changes'
109
+ || normalized.startsWith('changes.')) {
110
+ return 'docs';
111
+ }
112
+ if (normalized.includes('/test/')
113
+ || normalized.includes('/tests/')
114
+ || normalized.includes('/__tests__/')
115
+ || normalized.endsWith('.spec.ts')
116
+ || normalized.endsWith('.test.ts')
117
+ || normalized.endsWith('.spec.tsx')
118
+ || normalized.endsWith('.test.tsx')
119
+ || normalized.endsWith('.spec.js')
120
+ || normalized.endsWith('.test.js')
121
+ || normalized.endsWith('.spec.py')
122
+ || normalized.endsWith('.test.py')) {
123
+ return 'test';
124
+ }
125
+ return 'service';
126
+ }
127
+ function isSupportOnlyPath(pathValue) {
128
+ const layer = classifyArchitectureLayer(pathValue);
129
+ return layer === 'docs' || layer === 'test';
130
+ }
131
+ function matchServiceBoundary(boundaries, fileOrModulePath) {
132
+ const normalized = (0, intelligence_runtime_common_1.normalizeRepoPath)(fileOrModulePath);
133
+ let best = null;
134
+ let bestLength = -1;
135
+ for (const boundary of boundaries) {
136
+ const pathValue = (0, intelligence_runtime_common_1.normalizeRepoPath)(boundary.path);
137
+ if (normalized === pathValue
138
+ || normalized.startsWith(`${pathValue}/`)
139
+ || pathValue.startsWith(`${normalized}/`)) {
140
+ if (pathValue.length > bestLength) {
141
+ best = boundary.name;
142
+ bestLength = pathValue.length;
143
+ }
144
+ }
145
+ }
146
+ return best;
147
+ }
148
+ function matchOwnershipBoundary(boundaries, fileOrModulePath) {
149
+ const normalized = (0, intelligence_runtime_common_1.normalizeRepoPath)(fileOrModulePath);
150
+ let best = null;
151
+ let bestLength = -1;
152
+ for (const boundary of boundaries) {
153
+ const pathValue = (0, intelligence_runtime_common_1.normalizeRepoPath)(boundary.path);
154
+ if (normalized === pathValue
155
+ || normalized.startsWith(`${pathValue}/`)
156
+ || pathValue.startsWith(`${normalized}/`)) {
157
+ if (pathValue.length > bestLength) {
158
+ best = boundary;
159
+ bestLength = pathValue.length;
160
+ }
161
+ }
162
+ }
163
+ return best;
164
+ }
165
+ const RESPONSIBILITY_PATTERNS = {
166
+ authentication: [/\b(auth|oauth|rbac|permission|jwt|session|identity|token)\b/i],
167
+ authorization: [/\b(authz|authorize|permission|access control|rbac|acl)\b/i],
168
+ 'credential-validation': [/\b(secret|credential|password|token|api[_-]?key|process\.env)\b/i],
169
+ 'payment-orchestration': [/\b(payment|billing|invoice|refund|charge|settlement|checkout)\b/i],
170
+ 'billing-state': [/\b(invoice|ledger|refund|charge|billing)\b/i],
171
+ 'settlement-coordination': [/\b(settle|reconcile|payout|refund)\b/i],
172
+ 'notification-delivery': [/\b(notification|notify|email|sms|alert|webhook)\b/i],
173
+ 'message-formatting': [/\b(template|render|subject|body|payload)\b/i],
174
+ 'event-fanout': [/\b(publish|subscribe|fanout|topic|event bus|kafka|sqs|sns)\b/i],
175
+ 'request-routing': [/\b(route|router|controller|handler|gateway|graphql|rest)\b/i],
176
+ 'contract-translation': [/\b(schema|dto|openapi|proto|graphql|contract|serialize|deserialize)\b/i],
177
+ 'boundary-validation': [/\b(validate|validator|schema|guard)\b/i],
178
+ 'background-processing': [/\b(worker|job|queue|consumer|cron|schedule)\b/i],
179
+ 'event-consumption': [/\b(consume|consumer|listen|listener|handler|event)\b/i],
180
+ 'async-coordination': [/\b(async|await|queue|retry|backoff|schedule)\b/i],
181
+ 'shared-utilities': [/\b(util|helper|common|shared|format|parse)\b/i],
182
+ 'cross-cutting-support': [/\b(logging|metrics|telemetry|tracing|feature flag)\b/i],
183
+ 'common-types': [/\b(type|interface|schema|contract)\b/i],
184
+ 'persistence-modeling': [/\b(model|entity|schema|migration|prisma|sequelize|typeorm)\b/i],
185
+ 'data-access': [/\b(select|insert|update|delete|query|transaction|redis|postgres|mysql|mongo)\b/i],
186
+ 'storage-schema': [/\b(migration|ddl|table|column|index|constraint)\b/i],
187
+ 'presentation': [/\b(component|view|page|template|render|jsx|tsx)\b/i],
188
+ 'interaction-handling': [/\b(click|submit|form|input|event handler|useState)\b/i],
189
+ 'view-composition': [/\b(layout|section|component|view model)\b/i],
190
+ 'service-domain-logic': [/\b(rule|policy|eligibility|orchestrate|business|workflow)\b/i],
191
+ 'bounded-business-behavior': [/\b(domain|service|policy|workflow|orchestrate)\b/i],
192
+ 'direct-persistence-mutation': [/\b(prisma|sequelize|typeorm|knex|insert|update|delete|redis|postgres|mysql|mongo)\b/i],
193
+ 'credential-authority': [/\b(secret|credential|password|api[_-]?key|process\.env|oauth|jwt)\b/i],
194
+ 'deployment-control': [/\b(terraform|helm|k8s|deploy|deployment|docker|rollout|release)\b/i],
195
+ 'auth-state-mutation': [/\b(auth|identity|session|permission|rbac|token)\b/i],
196
+ 'payment-settlement': [/\b(payment|billing|invoice|refund|charge|settlement)\b/i],
197
+ 'business-orchestration': [/\b(orchestrate|workflow|coordinator|saga|pipeline)\b/i],
198
+ 'domain-orchestration': [/\b(orchestrate|workflow|coordinator|eligibility|settlement|checkout)\b/i],
199
+ 'cross-domain-orchestration': [/\b(orchestrate|workflow|coordinator|saga|fanout)\b/i],
200
+ 'ui-presentation': [/\b(component|view|page|template|render|css|jsx|tsx)\b/i],
201
+ };
202
+ const EVIDENCE_PATTERNS = {
203
+ stateMutation: /(prisma|typeorm|sequelize|knex|select\s+|insert\s+|update\s+|delete\s+|redis|postgres|mysql|mongo|session\.commit|transaction)/i,
204
+ externalSideEffect: /(webhook|httpx|requests\.|fetch\(|axios|kafka|sqs|sns|publish|subscribe|send_email|smtp|external)/i,
205
+ deploymentSemantic: /(rollout|deploy|deployment|helm|kubernetes|docker|terraform)/i,
206
+ sensitiveRuntime: /(process\.env|secret|token|jwt|credential|password|api[_-]?key)/i,
207
+ contractSurface: /(graphql|openapi|proto|dto|schema|contract)/i,
208
+ };
209
+ function detectResponsibilitySignals(content) {
210
+ const matches = Object.entries(RESPONSIBILITY_PATTERNS)
211
+ .filter(([, patterns]) => patterns.some((pattern) => pattern.test(content)))
212
+ .map(([responsibility]) => responsibility);
213
+ return (0, intelligence_runtime_common_1.dedupeSorted)(matches);
214
+ }
215
+ function criticalityToSeverity(criticality, defaultSeverity) {
216
+ if (criticality === 'critical') {
217
+ return defaultSeverity === 'medium' || defaultSeverity === 'low' ? 'high' : 'critical';
218
+ }
219
+ if (criticality === 'sensitive' && defaultSeverity === 'medium') {
220
+ return 'high';
221
+ }
222
+ return defaultSeverity;
223
+ }
224
+ function buildModuleAdjacency(graph) {
225
+ const outgoing = new Map();
226
+ const incoming = new Map();
227
+ for (const edge of graph.edges) {
228
+ if (edge.type !== 'imports')
229
+ continue;
230
+ if (!edge.from.startsWith('module:') || !edge.to.startsWith('module:'))
231
+ continue;
232
+ const from = edge.from.slice('module:'.length);
233
+ const to = edge.to.slice('module:'.length);
234
+ if (!outgoing.has(from))
235
+ outgoing.set(from, new Set());
236
+ if (!incoming.has(to))
237
+ incoming.set(to, new Set());
238
+ outgoing.get(from)?.add(to);
239
+ incoming.get(to)?.add(from);
240
+ }
241
+ return { outgoing, incoming };
242
+ }
243
+ function severityRank(severity) {
244
+ switch (severity) {
245
+ case 'critical':
246
+ return 5;
247
+ case 'high':
248
+ return 4;
249
+ case 'medium':
250
+ return 3;
251
+ case 'low':
252
+ return 2;
253
+ default:
254
+ return 1;
255
+ }
256
+ }
257
+ function narrativeSeverityRank(severity) {
258
+ return severityRank(severity);
259
+ }
260
+ function maxRisk(left, right) {
261
+ const rank = (value) => (value === 'high' ? 3 : value === 'medium' ? 2 : 1);
262
+ return rank(left) >= rank(right) ? left : right;
263
+ }
264
+ function severityToRisk(severity) {
265
+ if (severity === 'critical')
266
+ return 'critical';
267
+ if (severity === 'high')
268
+ return 'high';
269
+ if (severity === 'medium')
270
+ return 'medium';
271
+ return 'low';
272
+ }
273
+ function maxSeverity(left, right) {
274
+ return severityRank(left) >= severityRank(right) ? left : right;
275
+ }
276
+ function findBoundaryPolicy(boundaries, filePath) {
277
+ const normalized = (0, intelligence_runtime_common_1.normalizeRepoPath)(filePath);
278
+ let best = null;
279
+ let bestLength = -1;
280
+ for (const boundary of boundaries) {
281
+ const pathValue = (0, intelligence_runtime_common_1.normalizeRepoPath)(boundary.path);
282
+ if (normalized === pathValue
283
+ || normalized.startsWith(`${pathValue}/`)
284
+ || pathValue.startsWith(`${normalized}/`)) {
285
+ if (pathValue.length > bestLength) {
286
+ best = boundary;
287
+ bestLength = pathValue.length;
288
+ }
289
+ }
290
+ }
291
+ return best;
292
+ }
293
+ function containsCriticalDomain(value) {
294
+ if (!value)
295
+ return false;
296
+ return /(auth|token|secret|credential|permission|billing|payment|deploy|infra|migration|database|db)/i.test(value);
297
+ }
298
+ function summarizeValues(values, maxItems = 3) {
299
+ const unique = (0, intelligence_runtime_common_1.dedupeSorted)(values).filter(Boolean);
300
+ if (unique.length === 0)
301
+ return 'none';
302
+ const head = unique.slice(0, maxItems);
303
+ return `${head.join(', ')}${unique.length > maxItems ? ` +${unique.length - maxItems} more` : ''}`;
304
+ }
305
+ function safeReadRepoFile(projectRoot, filePath) {
306
+ const fullPath = (0, path_1.join)(projectRoot, (0, intelligence_runtime_common_1.normalizeRepoPath)(filePath));
307
+ if (!(0, fs_1.existsSync)(fullPath)) {
308
+ return null;
309
+ }
310
+ try {
311
+ const content = (0, fs_1.readFileSync)(fullPath, 'utf-8');
312
+ return content.slice(0, 24_000);
313
+ }
314
+ catch {
315
+ return null;
316
+ }
317
+ }
318
+ function collectGitAddedLines(projectRoot, changedFiles) {
319
+ const eligibleFiles = changedFiles
320
+ .map(intelligence_runtime_common_1.normalizeRepoPath)
321
+ .filter((filePath) => filePath && !isSupportOnlyPath(filePath))
322
+ .slice(0, 96);
323
+ if (eligibleFiles.length === 0) {
324
+ return new Map();
325
+ }
326
+ let diffOutput = '';
327
+ try {
328
+ diffOutput = (0, child_process_1.execFileSync)('git', ['diff', '--no-ext-diff', '--unified=0', '--', ...eligibleFiles], { cwd: projectRoot, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] });
329
+ }
330
+ catch {
331
+ return new Map();
332
+ }
333
+ const addedLinesByFile = new Map();
334
+ let currentFile = null;
335
+ let currentLine = 0;
336
+ for (const rawLine of diffOutput.split(/\r?\n/)) {
337
+ if (rawLine.startsWith('+++ b/')) {
338
+ currentFile = (0, intelligence_runtime_common_1.normalizeRepoPath)(rawLine.slice('+++ b/'.length));
339
+ if (!addedLinesByFile.has(currentFile)) {
340
+ addedLinesByFile.set(currentFile, []);
341
+ }
342
+ continue;
343
+ }
344
+ const hunk = rawLine.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
345
+ if (hunk) {
346
+ currentLine = Number(hunk[1]);
347
+ continue;
348
+ }
349
+ if (!currentFile || rawLine.length === 0) {
350
+ continue;
351
+ }
352
+ if (rawLine.startsWith('+') && !rawLine.startsWith('+++')) {
353
+ const text = rawLine.slice(1);
354
+ addedLinesByFile.get(currentFile)?.push({
355
+ file: currentFile,
356
+ line: currentLine,
357
+ text: text.length > 220 ? `${text.slice(0, 217)}...` : text,
358
+ });
359
+ currentLine += 1;
360
+ continue;
361
+ }
362
+ if (!rawLine.startsWith('-')) {
363
+ currentLine += 1;
364
+ }
365
+ }
366
+ return addedLinesByFile;
367
+ }
368
+ function selectLineEvidence(addedLinesByFile, filePath, pattern) {
369
+ return (addedLinesByFile.get((0, intelligence_runtime_common_1.normalizeRepoPath)(filePath)) || [])
370
+ .filter((line) => pattern.test(line.text))
371
+ .slice(0, 6);
372
+ }
373
+ function collectChangedFileEvidence(projectRoot, changedFiles) {
374
+ const stateMutationFiles = [];
375
+ const externalSideEffectFiles = [];
376
+ const deploymentSemanticFiles = [];
377
+ const sensitiveRuntimeFiles = [];
378
+ const contractSurfaceFiles = [];
379
+ const stateMutationLines = [];
380
+ const externalSideEffectLines = [];
381
+ const deploymentSemanticLines = [];
382
+ const sensitiveRuntimeLines = [];
383
+ const contractSurfaceLines = [];
384
+ const addedLinesByFile = collectGitAddedLines(projectRoot, changedFiles);
385
+ for (const filePath of changedFiles.slice(0, 32)) {
386
+ if (isSupportOnlyPath(filePath))
387
+ continue;
388
+ const content = safeReadRepoFile(projectRoot, filePath);
389
+ if (!content)
390
+ continue;
391
+ const stateLines = selectLineEvidence(addedLinesByFile, filePath, EVIDENCE_PATTERNS.stateMutation);
392
+ const sideEffectLines = selectLineEvidence(addedLinesByFile, filePath, EVIDENCE_PATTERNS.externalSideEffect);
393
+ const deploymentLines = selectLineEvidence(addedLinesByFile, filePath, EVIDENCE_PATTERNS.deploymentSemantic);
394
+ const sensitiveLines = selectLineEvidence(addedLinesByFile, filePath, EVIDENCE_PATTERNS.sensitiveRuntime);
395
+ const contractLines = selectLineEvidence(addedLinesByFile, filePath, EVIDENCE_PATTERNS.contractSurface);
396
+ stateMutationLines.push(...stateLines);
397
+ externalSideEffectLines.push(...sideEffectLines);
398
+ deploymentSemanticLines.push(...deploymentLines);
399
+ sensitiveRuntimeLines.push(...sensitiveLines);
400
+ contractSurfaceLines.push(...contractLines);
401
+ if (EVIDENCE_PATTERNS.stateMutation.test(content)) {
402
+ stateMutationFiles.push(filePath);
403
+ }
404
+ if (EVIDENCE_PATTERNS.externalSideEffect.test(content)) {
405
+ externalSideEffectFiles.push(filePath);
406
+ }
407
+ if (EVIDENCE_PATTERNS.deploymentSemantic.test(content)) {
408
+ deploymentSemanticFiles.push(filePath);
409
+ }
410
+ if (EVIDENCE_PATTERNS.sensitiveRuntime.test(content)) {
411
+ sensitiveRuntimeFiles.push(filePath);
412
+ }
413
+ if (EVIDENCE_PATTERNS.contractSurface.test(content)) {
414
+ contractSurfaceFiles.push(filePath);
415
+ }
416
+ }
417
+ return {
418
+ stateMutationFiles: (0, intelligence_runtime_common_1.dedupeSortedPaths)(stateMutationFiles),
419
+ externalSideEffectFiles: (0, intelligence_runtime_common_1.dedupeSortedPaths)(externalSideEffectFiles),
420
+ deploymentSemanticFiles: (0, intelligence_runtime_common_1.dedupeSortedPaths)(deploymentSemanticFiles),
421
+ sensitiveRuntimeFiles: (0, intelligence_runtime_common_1.dedupeSortedPaths)(sensitiveRuntimeFiles),
422
+ contractSurfaceFiles: (0, intelligence_runtime_common_1.dedupeSortedPaths)(contractSurfaceFiles),
423
+ stateMutationLines,
424
+ externalSideEffectLines,
425
+ deploymentSemanticLines,
426
+ sensitiveRuntimeLines,
427
+ contractSurfaceLines,
428
+ addedLinesByFile,
429
+ };
430
+ }
431
+ function linesForFile(lines, filePath) {
432
+ if (!filePath)
433
+ return [];
434
+ const normalized = (0, intelligence_runtime_common_1.normalizeRepoPath)(filePath);
435
+ return lines.filter((line) => (0, intelligence_runtime_common_1.normalizeRepoPath)(line.file) === normalized).slice(0, 6);
436
+ }
437
+ function categoryLineEvidence(category, filePath, changedFileEvidence) {
438
+ switch (category) {
439
+ case 'state-ownership-risk':
440
+ case 'layer-violation':
441
+ return linesForFile(changedFileEvidence.stateMutationLines, filePath);
442
+ case 'deployment-coupling':
443
+ case 'rollout-risk':
444
+ case 'infra-leakage':
445
+ return linesForFile(changedFileEvidence.deploymentSemanticLines, filePath);
446
+ case 'sensitive-boundary':
447
+ return linesForFile(changedFileEvidence.sensitiveRuntimeLines, filePath);
448
+ case 'contract-misuse':
449
+ return linesForFile(changedFileEvidence.contractSurfaceLines, filePath);
450
+ case 'behavioral-drift':
451
+ case 'runtime-coupling':
452
+ return linesForFile(changedFileEvidence.externalSideEffectLines, filePath);
453
+ default:
454
+ return filePath ? (changedFileEvidence.addedLinesByFile.get((0, intelligence_runtime_common_1.normalizeRepoPath)(filePath)) || []).slice(0, 3) : [];
455
+ }
456
+ }
457
+ function defaultEvidenceTier(finding, changedFileEvidence) {
458
+ if (finding.file && categoryLineEvidence(finding.category, finding.file, changedFileEvidence).length > 0) {
459
+ return 'direct-diff';
460
+ }
461
+ if (finding.file) {
462
+ return 'direct-file';
463
+ }
464
+ if (finding.category === 'blast-radius' || finding.category === 'rollout-risk' || finding.category === 'runtime-coupling') {
465
+ return 'topology-only';
466
+ }
467
+ return 'bounded-inference';
468
+ }
469
+ function defaultActionability(category, severity, evidenceTier) {
470
+ if (evidenceTier === 'direct-diff') {
471
+ return 'directly-actionable';
472
+ }
473
+ if (evidenceTier === 'topology-only' && (severity === 'info' || severity === 'low')) {
474
+ return 'informational';
475
+ }
476
+ if (category === 'blast-radius' || category === 'rollout-risk') {
477
+ return 'review-required';
478
+ }
479
+ return 'review-required';
480
+ }
481
+ function isBoundaryViolationCategory(category) {
482
+ return [
483
+ 'scope-expansion',
484
+ 'cross-service',
485
+ 'dependency-spread',
486
+ 'infra-leakage',
487
+ 'sensitive-boundary',
488
+ 'ownership-inversion',
489
+ 'layer-violation',
490
+ 'contract-misuse',
491
+ 'responsibility-drift',
492
+ 'invariant-violation',
493
+ 'deployment-coupling',
494
+ 'state-ownership-risk',
495
+ ].includes(category);
496
+ }
497
+ function isDeploymentRelevantCategory(category) {
498
+ return category === 'deployment-coupling'
499
+ || category === 'infra-leakage'
500
+ || category === 'rollout-risk'
501
+ || category === 'dependency-spread';
502
+ }
503
+ function deriveGovernancePriority(finding) {
504
+ const evidenceTier = finding.evidenceTier || 'bounded-inference';
505
+ const actionability = finding.actionability || defaultActionability(finding.category, finding.severity, evidenceTier);
506
+ if (isDeploymentRelevantCategory(finding.category)
507
+ && actionability === 'directly-actionable'
508
+ && (finding.severity === 'critical' || finding.severity === 'high')) {
509
+ return 'p0-rollout-blocker';
510
+ }
511
+ if (isBoundaryViolationCategory(finding.category)
512
+ && evidenceTier !== 'topology-only'
513
+ && (finding.severity === 'critical' || finding.severity === 'high')) {
514
+ return 'p1-architecture-blocker';
515
+ }
516
+ if (actionability === 'review-required' || finding.severity === 'medium') {
517
+ return 'p2-review-required';
518
+ }
519
+ return 'p3-advisory';
520
+ }
521
+ function deriveGovernanceGate(priority, category) {
522
+ if (category === 'sensitive-boundary' && priority === 'p1-architecture-blocker') {
523
+ return 'policy-blocker';
524
+ }
525
+ if (priority === 'p0-rollout-blocker')
526
+ return 'rollout-blocker';
527
+ if (priority === 'p1-architecture-blocker')
528
+ return 'architecture-blocker';
529
+ if (priority === 'p2-review-required')
530
+ return 'review-blocker';
531
+ return 'advisory';
532
+ }
533
+ function deriveRolloutTrust(finding, priority) {
534
+ if (priority === 'p0-rollout-blocker')
535
+ return 'deployment-sensitive';
536
+ if (priority === 'p1-architecture-blocker') {
537
+ return finding.category === 'cross-service'
538
+ || finding.category === 'scope-expansion'
539
+ || finding.category === 'ownership-inversion'
540
+ ? 'boundary-violating'
541
+ : 'architecture-risk';
542
+ }
543
+ if (finding.evidenceTier === 'topology-only')
544
+ return 'topology-advisory';
545
+ if (priority === 'p2-review-required')
546
+ return 'review-required';
547
+ return 'rollout-safe';
548
+ }
549
+ function defaultMinimalCorrection(finding) {
550
+ switch (finding.category) {
551
+ case 'dependency-spread':
552
+ return 'Remove the undeclared dependency or update the intent contract only if the dependency expansion is intentionally approved.';
553
+ case 'infra-leakage':
554
+ return 'Move infra/CI changes out of this remediation path, or explicitly declare the infrastructure boundary before re-verifying.';
555
+ case 'sensitive-boundary':
556
+ return 'Keep credential, token, and secret-handling logic inside the approved owner boundary; remove incidental sensitive handling from this change.';
557
+ case 'cross-service':
558
+ case 'scope-expansion':
559
+ case 'ownership-inversion':
560
+ return 'Pull the edit back into the approved service/module boundary, or intentionally expand the intent contract through review.';
561
+ case 'layer-violation':
562
+ return 'Move persistence/runtime behavior back behind the proper service or data layer rather than handling it in the changed presentation/API layer.';
563
+ case 'contract-misuse':
564
+ return 'Keep contract/schema changes within the approved API boundary, or split the contract change into an explicitly declared intent.';
565
+ case 'state-ownership-risk':
566
+ return 'Confirm the intended state owner, then remove undeclared mutation paths or route the change through the approved state-owning service.';
567
+ case 'deployment-coupling':
568
+ return 'Separate deployment/rollout changes from implementation edits unless the rollout unit is explicitly declared in the intent.';
569
+ case 'behavioral-drift':
570
+ case 'runtime-coupling':
571
+ return 'Keep runtime behavior within the declared behavior envelope; remove incidental orchestration, eventing, or side-effect expansion.';
572
+ case 'responsibility-drift':
573
+ case 'invariant-violation':
574
+ case 'architectural-leakage':
575
+ return 'Restore the module to its declared responsibility boundary, or update the semantic contract through explicit review.';
576
+ case 'blast-radius':
577
+ case 'rollout-risk':
578
+ return 'Review the impacted topology and either narrow the dependency/service spread or declare the broader rollout scope before re-verification.';
579
+ default:
580
+ return 'Narrow the change to the declared intent boundary, then re-run deterministic verification.';
581
+ }
582
+ }
583
+ function uncertaintyForTier(evidenceTier) {
584
+ if (evidenceTier === 'direct-diff') {
585
+ return ['The triggering evidence appears in added lines for this working-tree diff.'];
586
+ }
587
+ if (evidenceTier === 'direct-file') {
588
+ return ['The pattern exists in a changed file, but git hunk evidence did not prove it was newly introduced. Review for pre-existing code before remediation.'];
589
+ }
590
+ if (evidenceTier === 'topology-only') {
591
+ return ['This is inferred from repository topology only; confirm the service/module impact before treating it as a direct defect.'];
592
+ }
593
+ return ['This is bounded deterministic inference; verify the architectural intent before making code changes.'];
594
+ }
595
+ function defaultEvidenceExplanation(evidenceTier) {
596
+ if (evidenceTier === 'direct-diff')
597
+ return 'Matched evidence appears in added diff lines.';
598
+ if (evidenceTier === 'direct-file')
599
+ return 'Matched evidence appears in a changed file, but not in added-line provenance.';
600
+ if (evidenceTier === 'topology-only')
601
+ return 'Evidence is derived from import/service topology rather than changed-line content.';
602
+ return 'Evidence is derived from bounded deterministic inference over runtime and ownership context.';
603
+ }
604
+ function dedupeFindings(findings) {
605
+ const seen = new Set();
606
+ const deduped = [];
607
+ for (const finding of findings) {
608
+ const key = [
609
+ finding.category,
610
+ finding.severity,
611
+ finding.file || '',
612
+ finding.module || '',
613
+ finding.service || '',
614
+ finding.message,
615
+ ].join('|');
616
+ if (seen.has(key))
617
+ continue;
618
+ seen.add(key);
619
+ deduped.push(finding);
620
+ }
621
+ return deduped;
622
+ }
623
+ function computeCouplingSeverity(sourceLayer, targetLayer, targetValues, evidenceLevel = 'direct') {
624
+ const targetIsCriticalLayer = targetLayer === 'infra' || targetLayer === 'ci' || targetLayer === 'data';
625
+ if (evidenceLevel === 'topology-only') {
626
+ return targetIsCriticalLayer || targetValues.some((value) => containsCriticalDomain(value))
627
+ ? 'medium'
628
+ : 'low';
629
+ }
630
+ if (evidenceLevel === 'bounded-inference') {
631
+ return targetIsCriticalLayer || targetValues.some((value) => containsCriticalDomain(value))
632
+ ? 'high'
633
+ : 'medium';
634
+ }
635
+ if (targetIsCriticalLayer
636
+ || targetValues.some((value) => containsCriticalDomain(value))) {
637
+ return 'critical';
638
+ }
639
+ if ((sourceLayer === 'ui' || sourceLayer === 'api') &&
640
+ targetIsCriticalLayer) {
641
+ return 'critical';
642
+ }
643
+ if (sourceLayer !== targetLayer && targetLayer !== 'shared') {
644
+ return 'high';
645
+ }
646
+ return 'medium';
647
+ }
648
+ function buildNarrative(category, primaryCategory, findings, options) {
649
+ const affectedFiles = (0, intelligence_runtime_common_1.dedupeSortedPaths)(findings.map((item) => item.file || '').filter(Boolean));
650
+ const affectedModules = (0, intelligence_runtime_common_1.dedupeSorted)(findings.map((item) => item.module || '').filter(Boolean));
651
+ const affectedServices = (0, intelligence_runtime_common_1.dedupeSorted)(findings.map((item) => item.service || '').filter(Boolean));
652
+ const severity = findings.reduce((current, finding) => maxSeverity(current, finding.severity), 'low');
653
+ const confidence = findings.some((item) => item.severity === 'critical' || item.severity === 'high')
654
+ ? 'high'
655
+ : findings.length > 1
656
+ ? 'medium'
657
+ : 'low';
658
+ return {
659
+ id: `${category}-${hashId([category, options.summary, affectedFiles[0] || '', affectedModules[0] || ''])}`,
660
+ category,
661
+ severity,
662
+ confidence,
663
+ primaryCategory,
664
+ rootCause: options.rootCause,
665
+ summary: options.summary,
666
+ operationalRisk: options.operationalRisk,
667
+ remediationBoundary: options.remediationBoundary,
668
+ causalChain: options.causalChain,
669
+ affectedFiles,
670
+ affectedModules,
671
+ affectedServices,
672
+ evidenceFindingIds: findings.map((item) => item.id),
673
+ };
674
+ }
675
+ function buildDriftNarratives(input) {
676
+ const findings = input.findings;
677
+ const boundaryFindings = findings.filter((item) => item.category === 'infra-leakage' || item.category === 'sensitive-boundary');
678
+ const dependencyFindings = findings.filter((item) => item.category === 'dependency-spread');
679
+ const serviceFindings = findings.filter((item) => item.category === 'cross-service' || item.category === 'scope-expansion');
680
+ const ownershipFindings = findings.filter((item) => item.category === 'ownership-inversion' || item.category === 'responsibility-drift');
681
+ const behaviorFindings = findings.filter((item) => item.category === 'behavioral-drift');
682
+ const deploymentFindings = findings.filter((item) => item.category === 'deployment-coupling');
683
+ const stateFindings = findings.filter((item) => item.category === 'state-ownership-risk');
684
+ const semanticFindings = findings.filter((item) => item.category === 'runtime-coupling'
685
+ || item.category === 'architectural-leakage'
686
+ || item.category === 'layer-violation'
687
+ || item.category === 'contract-misuse'
688
+ || item.category === 'invariant-violation');
689
+ const blastFindings = findings.filter((item) => item.category === 'blast-radius' || item.category === 'rollout-risk');
690
+ const narratives = [];
691
+ const consumed = new Set();
692
+ if (serviceFindings.length > 0 || input.unexpectedServices.length > 0 || input.unexpectedModules.length > 0) {
693
+ const evidence = dedupeFindings([
694
+ ...serviceFindings,
695
+ ...dependencyFindings,
696
+ ...blastFindings.filter((item) => item.category === 'rollout-risk'),
697
+ ]);
698
+ if (evidence.length > 0) {
699
+ const spreadTarget = input.unexpectedServices.length > 0
700
+ ? summarizeValues(input.unexpectedServices, 3)
701
+ : summarizeValues(input.unexpectedModules, 3);
702
+ const summary = `Implementation escaped the approved ${input.approvedBoundaryLabel} boundary` +
703
+ `${spreadTarget !== 'none' ? ` and spread into ${spreadTarget}` : ''}` +
704
+ `${dependencyFindings.length > 0 ? ' via dependency surface expansion' : ''}.`;
705
+ narratives.push(buildNarrative('service-boundary-escape', 'cross-service', evidence, {
706
+ summary,
707
+ rootCause: 'Unexpected files and direct topology expansion moved the change outside the intended service or module envelope.',
708
+ operationalRisk: 'Cross-service drift weakens ownership assumptions, widens rollout coordination, and makes AI-generated changes harder to review safely.',
709
+ remediationBoundary: 'Constrain remediation to the approved modules or explicitly expand the intent pack before re-verifying.',
710
+ causalChain: [
711
+ `The approved intent envelope was ${input.approvedBoundaryLabel}.`,
712
+ dependencyFindings.length > 0
713
+ ? 'Dependency or manifest changes widened the reachable engineering surface.'
714
+ : 'Unexpected edits appeared outside the approved service or module scope.',
715
+ input.impactedServices.length > 1
716
+ ? `Repository topology propagated impact into ${summarizeValues(input.impactedServices, 4)}.`
717
+ : `Repository topology propagated impact into ${summarizeValues(input.impactedModules, 4)}.`,
718
+ ],
719
+ }));
720
+ evidence.forEach((item) => consumed.add(item.id));
721
+ }
722
+ }
723
+ if (ownershipFindings.length > 0) {
724
+ const ownershipTargets = (0, intelligence_runtime_common_1.dedupeSorted)(ownershipFindings.map((item) => item.service || item.module || item.file || 'unknown').filter(Boolean));
725
+ narratives.push(buildNarrative('ownership-boundary-breach', ownershipFindings[0]?.category || 'ownership-inversion', ownershipFindings, {
726
+ summary: `Implementation crossed ownership boundaries and mixed responsibilities across ${summarizeValues(ownershipTargets, 4)}.`,
727
+ rootCause: 'The change set now spans ownership domains or introduces responsibilities that do not belong to the touched service boundary.',
728
+ operationalRisk: 'Ownership mixing is a strong signal of AI implementation overreach because review, rollout, and on-call boundaries stop matching the code that changed.',
729
+ remediationBoundary: 'Constrain remediation to the original owner boundary or explicitly expand the intent pack and review scope before continuing.',
730
+ causalChain: [
731
+ 'Changed files or modules no longer stay inside the originally approved ownership envelope.',
732
+ ownershipTargets.length > 1
733
+ ? `Responsibilities now span ${summarizeValues(ownershipTargets, 4)}.`
734
+ : 'Responsibility drift introduced a new owner concern inside the touched boundary.',
735
+ input.rolloutRisk === 'high'
736
+ ? 'That ownership spread also increases rollout coordination and approval load.'
737
+ : 'This breaks the assumption that one bounded owner can safely review the change.',
738
+ ],
739
+ }));
740
+ ownershipFindings.forEach((item) => consumed.add(item.id));
741
+ }
742
+ if (behaviorFindings.length > 0) {
743
+ narratives.push(buildNarrative('runtime-behavior-shift', 'behavioral-drift', behaviorFindings, {
744
+ summary: `Runtime behavior shifted beyond the declared implementation role${input.impactedServices.length > 0 ? ` across ${summarizeValues(input.impactedServices, 4)}` : ''}.`,
745
+ rootCause: 'The changed boundaries now behave as orchestrators, state mutators, event participants, or side-effect surfaces that were not declared in the active intent runtime.',
746
+ operationalRisk: 'Behavioral drift is more dangerous than raw file spread because the production role of the service changes even if the diff looks bounded.',
747
+ remediationBoundary: 'Remove undeclared runtime responsibilities or explicitly expand the intent pack to include the new operational role before re-verifying.',
748
+ causalChain: [
749
+ 'Changed boundaries acquired runtime roles that were not part of the declared session contract.',
750
+ input.rolloutRisk === 'high'
751
+ ? 'The resulting runtime behavior also expands rollout coordination and production review scope.'
752
+ : 'The resulting behavior changes how the service participates in production flows.',
753
+ ],
754
+ }));
755
+ behaviorFindings.forEach((item) => consumed.add(item.id));
756
+ }
757
+ if (deploymentFindings.length > 0) {
758
+ narratives.push(buildNarrative('deployment-semantics-breach', 'deployment-coupling', deploymentFindings, {
759
+ summary: `Deployment semantics expanded beyond the approved rollout envelope${input.impactedModules.length > 0 ? ` into ${summarizeValues(input.impactedModules, 4)}` : ''}.`,
760
+ rootCause: 'CI, infra, or rollout units now depend on changed boundaries that were supposed to remain outside this implementation session.',
761
+ operationalRisk: 'Undeclared deployment coupling increases rollout blast radius, merge risk, and the chance of hidden environment-specific regressions.',
762
+ remediationBoundary: 'Keep remediation inside the approved rollout units or update the intent pack to declare the deployment expansion before continuing.',
763
+ causalChain: [
764
+ 'Deployment or infrastructure manifests now reference the changed boundary set.',
765
+ 'That turns a bounded code change into a broader production rollout concern.',
766
+ ],
767
+ }));
768
+ deploymentFindings.forEach((item) => consumed.add(item.id));
769
+ }
770
+ if (stateFindings.length > 0) {
771
+ narratives.push(buildNarrative('state-ownership-erosion', 'state-ownership-risk', stateFindings, {
772
+ summary: 'Changed state-owning boundary needs explicit rollback and coordination review.',
773
+ rootCause: 'Changed files touch state-related semantics inside or near a state-owning boundary.',
774
+ operationalRisk: 'State-related edits can affect rollback and data consistency, but this finding remains bounded unless multiple owners or direct persistence changes are shown.',
775
+ remediationBoundary: 'Keep state mutation inside the declared owner boundary or explicitly expand the intent pack before re-verifying.',
776
+ causalChain: [
777
+ 'A state-owning runtime boundary is involved in the changed scope.',
778
+ 'Review should confirm whether the actual change mutates persistence or only touches adjacent request/config behavior.',
779
+ ],
780
+ }));
781
+ stateFindings.forEach((item) => consumed.add(item.id));
782
+ }
783
+ if (boundaryFindings.length > 0) {
784
+ const boundaryTargets = boundaryFindings.map((item) => item.file || item.module || item.service || 'unknown');
785
+ const summary = `Implementation crossed forbidden engineering boundaries` +
786
+ `${boundaryTargets.length > 0 ? ` at ${summarizeValues(boundaryTargets, 3)}` : ''}.`;
787
+ narratives.push(buildNarrative('forbidden-boundary-breach', boundaryFindings[0]?.category || 'infra-leakage', boundaryFindings, {
788
+ summary,
789
+ rootCause: 'The active intent pack marked these paths as forbidden, but the change still expanded into them.',
790
+ operationalRisk: 'Forbidden CI, infra, secret, auth, or sensitive boundary edits create rollout and compliance risk that cannot be treated as incidental drift.',
791
+ remediationBoundary: 'Remove the forbidden edits or explicitly re-authorize the boundary in the intent pack before remediation continues.',
792
+ causalChain: [
793
+ `The intent pack explicitly disallowed ${summarizeValues(boundaryTargets, 3)}.`,
794
+ input.dependencyManifestTouched
795
+ ? 'Dependency expansion and topology spread increased the chance of boundary escape.'
796
+ : 'Unexpected architectural spread carried the change into a forbidden path.',
797
+ input.deploymentTouched || input.infraTouched
798
+ ? 'Deployment or infrastructure surfaces are now coupled to the remediation path.'
799
+ : 'The resulting change set now crosses a protected trust boundary.',
800
+ ],
801
+ }));
802
+ boundaryFindings.forEach((item) => consumed.add(item.id));
803
+ }
804
+ if (semanticFindings.length > 0) {
805
+ const semanticIsBounded = semanticFindings.every((item) => item.severity === 'medium' || item.severity === 'low' || item.severity === 'info');
806
+ const summary = (semanticIsBounded
807
+ ? 'Semantic contract checks found bounded responsibility concerns'
808
+ : 'Semantic coupling crossed architecture-layer expectations') +
809
+ `${input.impactedServices.length > 0 ? `, affecting ${summarizeValues(input.impactedServices, 4)}` : ''}.`;
810
+ narratives.push(buildNarrative(semanticFindings.some((item) => item.category === 'invariant-violation')
811
+ ? 'architectural-invariant-erosion'
812
+ : 'semantic-coupling', semanticFindings[0]?.category || 'runtime-coupling', semanticFindings, {
813
+ summary,
814
+ rootCause: semanticIsBounded
815
+ ? 'Changed files or direct import topology overlap responsibilities that the inferred contract normally keeps separate.'
816
+ : 'Direct imports, layer violations, or contract-surface edits introduced runtime responsibilities outside the approved design boundary.',
817
+ operationalRisk: semanticIsBounded
818
+ ? 'This is an architecture-review signal, not confirmed production danger; reviewers should verify whether the responsibility overlap is intentional.'
819
+ : 'Semantic coupling is harder to spot than raw file drift and can create latent production behavior changes or ownership confusion.',
820
+ remediationBoundary: 'Keep remediation inside the intended layer or explicitly update the intent contract before re-running verify.',
821
+ causalChain: [
822
+ semanticIsBounded
823
+ ? 'Changed modules have bounded semantic overlap with responsibilities outside the approved intent envelope.'
824
+ : 'Changed modules now depend on responsibilities outside their intended architectural layer.',
825
+ input.authTouched
826
+ ? 'Sensitive auth or credential handling is now closer to the changed runtime surface.'
827
+ : semanticIsBounded
828
+ ? 'No direct forbidden boundary was confirmed by this narrative.'
829
+ : 'The change set mixes architectural responsibilities that should remain isolated.',
830
+ input.rolloutRisk === 'high'
831
+ ? 'This coupling also increases rollout coordination and hidden regression risk.'
832
+ : semanticIsBounded
833
+ ? 'Impact remains bounded unless additional direct runtime or deployment evidence appears.'
834
+ : 'Even localized changes now carry non-local semantic impact.',
835
+ ],
836
+ }));
837
+ semanticFindings.forEach((item) => consumed.add(item.id));
838
+ }
839
+ const unconsumedDependency = dependencyFindings.filter((item) => !consumed.has(item.id));
840
+ if (unconsumedDependency.length > 0) {
841
+ narratives.push(buildNarrative('dependency-expansion', 'dependency-spread', unconsumedDependency, {
842
+ summary: `Dependency surface expanded beyond the declared intent envelope${input.impactedServices.length > 0 ? ` and now reaches ${summarizeValues(input.impactedServices, 4)}` : ''}.`,
843
+ rootCause: 'Manifest or direct dependency additions introduced new operational surface that was not declared in the intent pack.',
844
+ operationalRisk: 'Unexpected dependency changes widen blast radius, review scope, and downstream rollout obligations.',
845
+ remediationBoundary: 'Either remove the undeclared dependency changes or explicitly declare them in intent before re-verifying.',
846
+ causalChain: [
847
+ 'A dependency manifest or package change occurred outside the approved scope.',
848
+ input.impactedModules.length > input.unexpectedModules.length
849
+ ? `Transitive graph impact reached ${summarizeValues(input.impactedModules, 4)}.`
850
+ : 'The dependency change widened the reachable change surface.',
851
+ ],
852
+ }));
853
+ unconsumedDependency.forEach((item) => consumed.add(item.id));
854
+ }
855
+ const unconsumedBlast = blastFindings.filter((item) => !consumed.has(item.id));
856
+ if (unconsumedBlast.length > 0) {
857
+ const blastIsTopologyOnly = unconsumedBlast.every((item) => item.rationale.toLowerCase().includes('topology only')
858
+ || item.rationale.toLowerCase().includes('inferred from import topology')
859
+ || item.severity === 'medium'
860
+ || item.severity === 'low');
861
+ narratives.push(buildNarrative('blast-radius-expansion', 'blast-radius', unconsumedBlast, {
862
+ summary: blastIsTopologyOnly
863
+ ? `Repository topology suggests possible adjacent impact outside approved scope in ${summarizeValues(input.impactedModules, 4)}.`
864
+ : `Graph-aware blast radius expanded beyond the approved scope into ${summarizeValues(input.impactedModules, 4)}.`,
865
+ rootCause: blastIsTopologyOnly
866
+ ? 'Import topology indicates adjacency beyond the approved scope, but direct changed-file evidence did not confirm systemic expansion.'
867
+ : 'Repository topology indicates the changed modules now influence adjacent modules or services outside the original plan.',
868
+ operationalRisk: blastIsTopologyOnly
869
+ ? 'Treat this as a bounded review hint. It should not be interpreted as confirmed rollout or production impact without direct evidence.'
870
+ : 'Expanded blast radius increases regression surface and rollout coordination even if the raw diff looked locally bounded.',
871
+ remediationBoundary: blastIsTopologyOnly
872
+ ? 'Confirm whether adjacent modules are intentionally affected; if not, keep remediation within the approved module scope.'
873
+ : 'Pull the change back to the approved scope or extend intent to cover the expanded impact set before remediation proceeds.',
874
+ causalChain: [
875
+ blastIsTopologyOnly
876
+ ? 'Changed modules have import-graph adjacency outside the approved intent envelope.'
877
+ : 'Changed modules have direct or transitive topology edges outside the approved intent envelope.',
878
+ input.impactedServices.length > 1
879
+ ? `Service impact now spans ${summarizeValues(input.impactedServices, 4)}.`
880
+ : `Module impact now spans ${summarizeValues(input.impactedModules, 4)}.`,
881
+ ],
882
+ }));
883
+ unconsumedBlast.forEach((item) => consumed.add(item.id));
884
+ }
885
+ const leftovers = findings.filter((item) => !consumed.has(item.id));
886
+ if (leftovers.length > 0) {
887
+ narratives.push(buildNarrative('localized-scope-drift', leftovers[0]?.category || 'scope-expansion', leftovers, {
888
+ summary: `Implementation drift remained localized but still exceeded the approved ${input.approvedBoundaryLabel} boundary.`,
889
+ rootCause: 'Unexpected files or modules were touched even though the larger service topology did not explode.',
890
+ operationalRisk: 'Even localized drift weakens trust in bounded AI-assisted implementation and should be reconciled before rollout.',
891
+ remediationBoundary: 'Remove the localized scope spillover or revise the intent pack to make the expansion explicit.',
892
+ causalChain: [
893
+ 'Unexpected files were changed outside the approved intent envelope.',
894
+ 'The overall topology remained comparatively contained, but the bounded contract was still violated.',
895
+ ],
896
+ }));
897
+ }
898
+ return narratives.sort((left, right) => narrativeSeverityRank(right.severity) - narrativeSeverityRank(left.severity));
899
+ }
900
+ function emptyPriorityCounts() {
901
+ return {
902
+ p0RolloutBlockers: 0,
903
+ p1ArchitectureBlockers: 0,
904
+ p2ReviewRequired: 0,
905
+ p3Advisory: 0,
906
+ };
907
+ }
908
+ function computePriorityCounts(findings) {
909
+ const counts = emptyPriorityCounts();
910
+ findings.forEach((finding) => {
911
+ switch (finding.priority) {
912
+ case 'p0-rollout-blocker':
913
+ counts.p0RolloutBlockers += 1;
914
+ break;
915
+ case 'p1-architecture-blocker':
916
+ counts.p1ArchitectureBlockers += 1;
917
+ break;
918
+ case 'p2-review-required':
919
+ counts.p2ReviewRequired += 1;
920
+ break;
921
+ default:
922
+ counts.p3Advisory += 1;
923
+ break;
924
+ }
925
+ });
926
+ return counts;
927
+ }
928
+ function gateRank(gate) {
929
+ switch (gate) {
930
+ case 'policy-blocker':
931
+ return 5;
932
+ case 'rollout-blocker':
933
+ return 4;
934
+ case 'architecture-blocker':
935
+ return 3;
936
+ case 'review-blocker':
937
+ return 2;
938
+ default:
939
+ return 1;
940
+ }
941
+ }
942
+ function rolloutTrustRank(posture) {
943
+ switch (posture) {
944
+ case 'deployment-sensitive':
945
+ return 6;
946
+ case 'boundary-violating':
947
+ return 5;
948
+ case 'architecture-risk':
949
+ return 4;
950
+ case 'review-required':
951
+ return 3;
952
+ case 'topology-advisory':
953
+ return 2;
954
+ default:
955
+ return 1;
956
+ }
957
+ }
958
+ function highestGate(findings) {
959
+ return findings.reduce((current, finding) => gateRank(finding.governanceGate || 'advisory') > gateRank(current)
960
+ ? finding.governanceGate || 'advisory'
961
+ : current, 'advisory');
962
+ }
963
+ function highestRolloutTrust(findings) {
964
+ return findings.reduce((current, finding) => rolloutTrustRank(finding.rolloutTrust || 'rollout-safe') > rolloutTrustRank(current)
965
+ ? finding.rolloutTrust || 'rollout-safe'
966
+ : current, 'rollout-safe');
967
+ }
968
+ function remediationPriorityRank(finding) {
969
+ const priorityRank = finding.priority === 'p0-rollout-blocker'
970
+ ? 400
971
+ : finding.priority === 'p1-architecture-blocker'
972
+ ? 300
973
+ : finding.priority === 'p2-review-required'
974
+ ? 200
975
+ : 100;
976
+ const evidenceRank = finding.evidenceTier === 'direct-diff'
977
+ ? 40
978
+ : finding.evidenceTier === 'direct-file'
979
+ ? 30
980
+ : finding.evidenceTier === 'bounded-inference'
981
+ ? 20
982
+ : 10;
983
+ return priorityRank + evidenceRank + severityRank(finding.severity);
984
+ }
985
+ function buildRemediationOrder(findings) {
986
+ return findings
987
+ .slice()
988
+ .sort((left, right) => remediationPriorityRank(right) - remediationPriorityRank(left))
989
+ .map((finding) => finding.id)
990
+ .slice(0, 12);
991
+ }
992
+ function attachFindingRelationships(findings) {
993
+ const directParents = findings.filter((finding) => finding.actionability === 'directly-actionable'
994
+ && finding.evidenceTier !== 'topology-only'
995
+ && finding.priority !== 'p3-advisory');
996
+ if (directParents.length === 0) {
997
+ return findings;
998
+ }
999
+ return findings.map((finding) => {
1000
+ if (finding.relationships && finding.relationships.length > 0) {
1001
+ return finding;
1002
+ }
1003
+ if (finding.evidenceTier !== 'topology-only' && finding.category !== 'blast-radius' && finding.category !== 'rollout-risk') {
1004
+ return finding;
1005
+ }
1006
+ const parent = directParents.find((candidate) => candidate.id !== finding.id
1007
+ && ((candidate.module && finding.module && candidate.module === finding.module)
1008
+ || (candidate.service && finding.service && candidate.service === finding.service)
1009
+ || (candidate.file && finding.evidence?.dependencyEdges.some((edge) => edge.includes(candidate.module || candidate.file || ''))))) || directParents[0];
1010
+ return {
1011
+ ...finding,
1012
+ relationships: [
1013
+ {
1014
+ type: finding.category === 'rollout-risk' ? 'deployment-derived' : 'topology-derived',
1015
+ targetFindingId: parent.id,
1016
+ rationale: 'This finding is a rollout/topology consequence of a higher-priority direct governance finding; remediate the direct finding first.',
1017
+ },
1018
+ ],
1019
+ };
1020
+ });
1021
+ }
1022
+ function buildGovernancePostureSummary(findings) {
1023
+ const priorityCounts = computePriorityCounts(findings);
1024
+ const governanceGate = highestGate(findings);
1025
+ const rolloutTrust = highestRolloutTrust(findings);
1026
+ const reasons = (0, intelligence_runtime_common_1.dedupeSorted)(findings
1027
+ .slice()
1028
+ .sort((left, right) => remediationPriorityRank(right) - remediationPriorityRank(left))
1029
+ .slice(0, 4)
1030
+ .map((finding) => `${finding.priority || 'p3-advisory'}: ${finding.message}`));
1031
+ const summary = findings.length === 0
1032
+ ? 'Architectural integrity preserved; no direct runtime-boundary or rollout-trust violations were detected.'
1033
+ : governanceGate === 'policy-blocker'
1034
+ ? 'Policy-sensitive boundary drift requires remediation before rollout.'
1035
+ : governanceGate === 'rollout-blocker'
1036
+ ? 'Deployment-relevant drift blocks rollout until the affected boundary is corrected or explicitly approved.'
1037
+ : governanceGate === 'architecture-blocker'
1038
+ ? 'Direct architectural boundary drift requires correction or explicit review before rollout.'
1039
+ : governanceGate === 'review-blocker'
1040
+ ? 'Review is required before rollout; no deterministic rollout blocker was established.'
1041
+ : 'Only advisory or topology-derived drift was detected; rollout posture remains bounded.';
1042
+ return {
1043
+ rolloutTrust,
1044
+ governanceGate,
1045
+ summary,
1046
+ reasons,
1047
+ priorityCounts,
1048
+ remediationOrder: buildRemediationOrder(findings),
1049
+ };
1050
+ }
1051
+ function decisionMatchesFinding(decision, finding) {
1052
+ if (decision.findingId && decision.findingId === finding.id) {
1053
+ return true;
1054
+ }
1055
+ if (decision.category && decision.category !== finding.category) {
1056
+ return false;
1057
+ }
1058
+ const fileMatches = !decision.file || (0, intelligence_runtime_common_1.normalizeRepoPath)(decision.file) === (0, intelligence_runtime_common_1.normalizeRepoPath)(finding.file || '');
1059
+ const moduleMatches = !decision.module || (0, intelligence_runtime_common_1.normalizeRepoPath)(decision.module) === (0, intelligence_runtime_common_1.normalizeRepoPath)(finding.module || '');
1060
+ const serviceMatches = !decision.service || decision.service === finding.service;
1061
+ return Boolean(decision.category) && fileMatches && moduleMatches && serviceMatches;
1062
+ }
1063
+ function applyDecisionToFinding(finding, decision, sourcePath) {
1064
+ const expired = (0, governance_decisions_1.isGovernanceDecisionExpired)(decision);
1065
+ const previousGate = finding.governanceGate || null;
1066
+ const previousRolloutTrust = finding.rolloutTrust || null;
1067
+ let governanceGate = finding.governanceGate || 'advisory';
1068
+ let rolloutTrust = finding.rolloutTrust || 'rollout-safe';
1069
+ let priority = finding.priority || 'p3-advisory';
1070
+ let actionability = finding.actionability || 'review-required';
1071
+ if (!expired) {
1072
+ if (decision.state === 'accepted-risk' || decision.state === 'rollout-approved' || decision.state === 'temporary-exception') {
1073
+ governanceGate = governanceGate === 'policy-blocker' ? 'review-blocker' : 'advisory';
1074
+ rolloutTrust = decision.state === 'rollout-approved' ? 'review-required' : 'topology-advisory';
1075
+ priority = 'p3-advisory';
1076
+ actionability = 'informational';
1077
+ }
1078
+ else if (decision.state === 'advisory-dismissed' && governanceGate === 'advisory') {
1079
+ rolloutTrust = 'rollout-safe';
1080
+ priority = 'p3-advisory';
1081
+ actionability = 'informational';
1082
+ }
1083
+ else if (decision.state === 'review-required' || decision.state === 'acknowledged') {
1084
+ governanceGate = governanceGate === 'advisory' ? 'review-blocker' : governanceGate;
1085
+ rolloutTrust = rolloutTrust === 'rollout-safe' ? 'review-required' : rolloutTrust;
1086
+ priority = priority === 'p3-advisory' ? 'p2-review-required' : priority;
1087
+ }
1088
+ else if (decision.state === 'rollout-blocked') {
1089
+ governanceGate = 'rollout-blocker';
1090
+ rolloutTrust = 'deployment-sensitive';
1091
+ priority = 'p0-rollout-blocker';
1092
+ }
1093
+ }
1094
+ const resultingGate = expired ? previousGate : governanceGate;
1095
+ const resultingRolloutTrust = expired ? previousRolloutTrust : rolloutTrust;
1096
+ const lineage = {
1097
+ decisionId: decision.id,
1098
+ state: decision.state,
1099
+ findingId: finding.id,
1100
+ category: finding.category,
1101
+ reason: decision.reason,
1102
+ actor: decision.actor,
1103
+ decidedAt: decision.decidedAt,
1104
+ expiresAt: decision.expiresAt,
1105
+ temporary: decision.temporary,
1106
+ expired,
1107
+ previousGate,
1108
+ resultingGate,
1109
+ previousRolloutTrust,
1110
+ resultingRolloutTrust,
1111
+ sourcePath,
1112
+ lineageHash: governanceLineageHash([
1113
+ decision.id,
1114
+ decision.state,
1115
+ finding.id,
1116
+ decision.reason,
1117
+ decision.actor,
1118
+ decision.decidedAt,
1119
+ decision.expiresAt || '',
1120
+ previousGate || '',
1121
+ resultingGate || '',
1122
+ previousRolloutTrust || '',
1123
+ resultingRolloutTrust || '',
1124
+ ]),
1125
+ };
1126
+ if (expired) {
1127
+ return {
1128
+ ...finding,
1129
+ governanceDecision: lineage,
1130
+ };
1131
+ }
1132
+ return {
1133
+ ...finding,
1134
+ actionability,
1135
+ priority,
1136
+ governanceGate,
1137
+ rolloutTrust,
1138
+ governanceDecision: lineage,
1139
+ remediationGuidance: finding.remediationGuidance
1140
+ ? {
1141
+ ...finding.remediationGuidance,
1142
+ actionability,
1143
+ uncertainty: (0, intelligence_runtime_common_1.dedupeSorted)([
1144
+ ...finding.remediationGuidance.uncertainty,
1145
+ `Governance decision ${decision.id} (${decision.state}) is active and audit-visible; reason: ${decision.reason}`,
1146
+ ]),
1147
+ }
1148
+ : finding.remediationGuidance,
1149
+ };
1150
+ }
1151
+ function applyGovernanceDecisions(findings, registry) {
1152
+ if (registry.decisions.length === 0) {
1153
+ return {
1154
+ findings,
1155
+ summary: emptyDecisionSummary(registry.sourcePath, registry.invalidEntries),
1156
+ };
1157
+ }
1158
+ let activeOverrides = 0;
1159
+ let expiredOverrides = registry.invalidEntries;
1160
+ let findingsChanged = 0;
1161
+ const lineage = [];
1162
+ const nextFindings = findings.map((finding) => {
1163
+ const decision = registry.decisions.find((candidate) => decisionMatchesFinding(candidate, finding));
1164
+ if (!decision)
1165
+ return finding;
1166
+ const next = applyDecisionToFinding(finding, decision, registry.sourcePath);
1167
+ if (next.governanceDecision) {
1168
+ lineage.push(next.governanceDecision);
1169
+ if (next.governanceDecision.expired) {
1170
+ expiredOverrides += 1;
1171
+ }
1172
+ else {
1173
+ activeOverrides += 1;
1174
+ if (next.governanceGate !== finding.governanceGate
1175
+ || next.rolloutTrust !== finding.rolloutTrust
1176
+ || next.priority !== finding.priority) {
1177
+ findingsChanged += 1;
1178
+ }
1179
+ }
1180
+ }
1181
+ return next;
1182
+ });
1183
+ return {
1184
+ findings: nextFindings,
1185
+ summary: {
1186
+ sourcePath: registry.sourcePath,
1187
+ decisionsApplied: lineage.length,
1188
+ activeOverrides,
1189
+ expiredOverrides,
1190
+ findingsChanged,
1191
+ lineage,
1192
+ },
1193
+ };
1194
+ }
1195
+ function buildRiskSynthesis(input) {
1196
+ const highestNarrativeSeverity = input.narratives.reduce((current, item) => maxSeverity(current, item.severity), 'low');
1197
+ let overallRisk = severityToRisk(highestNarrativeSeverity);
1198
+ if ((input.authTouched || input.infraTouched || input.deploymentTouched)
1199
+ && (overallRisk === 'high' || overallRisk === 'critical')) {
1200
+ overallRisk = 'critical';
1201
+ }
1202
+ if (input.dependencyManifestTouched && overallRisk === 'medium') {
1203
+ overallRisk = 'high';
1204
+ }
1205
+ const primaryNarratives = input.narratives.slice(0, 3).map((item) => item.summary);
1206
+ const contributingCategories = (0, intelligence_runtime_common_1.dedupeSorted)(input.findings.map((item) => item.category));
1207
+ const posture = buildGovernancePostureSummary(input.findings);
1208
+ const summary = primaryNarratives.length > 0
1209
+ ? primaryNarratives.slice(0, 2).join(' ')
1210
+ : 'No compressed drift narratives were required; no high-confidence engineering drift was detected.';
1211
+ let cascadingRisk = overallRisk;
1212
+ if (input.directDeploymentEvidence
1213
+ && (input.deploymentTouched
1214
+ || input.infraTouched
1215
+ || input.affectedRolloutUnits.length >= 2)) {
1216
+ cascadingRisk = overallRisk === 'critical' || input.authTouched ? 'critical' : 'high';
1217
+ }
1218
+ else if (!input.topologyOnlyPropagation
1219
+ && (input.externalSideEffectExposure || input.stateOwnershipExposure)) {
1220
+ cascadingRisk = overallRisk === 'low' ? 'medium' : overallRisk;
1221
+ }
1222
+ else if (input.topologyOnlyPropagation && (cascadingRisk === 'high' || cascadingRisk === 'critical')) {
1223
+ cascadingRisk = 'medium';
1224
+ }
1225
+ return {
1226
+ overallRisk,
1227
+ summary,
1228
+ primaryNarratives,
1229
+ contributingCategories,
1230
+ rawFindingCount: input.findings.length,
1231
+ compressedNarrativeCount: input.narratives.length,
1232
+ authExposure: input.authTouched,
1233
+ infraExposure: input.infraTouched,
1234
+ deploymentExposure: input.deploymentTouched,
1235
+ dependencyExposure: input.dependencyManifestTouched,
1236
+ transitiveImpactCount: input.transitiveImpactCount,
1237
+ runtimeFlowExposure: input.impactedRuntimeFlows.length > 0,
1238
+ externalSideEffectExposure: input.externalSideEffectExposure,
1239
+ stateOwnershipExposure: input.stateOwnershipExposure,
1240
+ affectedRolloutUnits: input.affectedRolloutUnits,
1241
+ cascadingRisk,
1242
+ rolloutTrust: posture.rolloutTrust,
1243
+ governanceGate: posture.governanceGate,
1244
+ postureSummary: posture.summary,
1245
+ priorityCounts: posture.priorityCounts,
1246
+ remediationOrder: posture.remediationOrder,
1247
+ };
1248
+ }
1249
+ function buildDriftIntelligence(changeSet, runtime) {
1250
+ const changedFiles = (0, intelligence_runtime_common_1.dedupeSortedPaths)(changeSet.changedFiles);
1251
+ const governanceChangedFiles = changedFiles.filter((filePath) => !isSupportOnlyPath(filePath));
1252
+ const evaluatedChangedFiles = governanceChangedFiles.length > 0 ? governanceChangedFiles : changedFiles;
1253
+ const changedModules = (0, intelligence_runtime_common_1.dedupeSorted)(evaluatedChangedFiles.map(deriveModulePath));
1254
+ const authTouched = evaluatedChangedFiles.some((filePath) => /(auth|token|secret|permission|billing|payment)/i.test(filePath));
1255
+ const deploymentTouched = evaluatedChangedFiles.some((filePath) => /(\.github\/workflows|deploy|terraform|helm|k8s|docker-compose)/i.test(filePath));
1256
+ const infraTouched = evaluatedChangedFiles.some((filePath) => {
1257
+ const flags = (0, intelligence_runtime_common_1.classifyBoundaryPath)(filePath);
1258
+ return flags.infra || flags.ci;
1259
+ });
1260
+ const dependencyManifestTouched = evaluatedChangedFiles.some((filePath) => (0, intelligence_runtime_common_1.classifyBoundaryPath)(filePath).dependencyManifest);
1261
+ if (!runtime) {
1262
+ const emptyNarratives = [];
1263
+ const governancePosture = buildGovernancePostureSummary([]);
1264
+ const governanceDecisions = emptyDecisionSummary(null);
1265
+ return {
1266
+ schemaVersion: 1,
1267
+ source: 'fallback-plan',
1268
+ flagged: false,
1269
+ confidence: 'low',
1270
+ changedFiles,
1271
+ changedModules,
1272
+ changedServices: [],
1273
+ impactedModules: changedModules,
1274
+ impactedServices: [],
1275
+ impactedRuntimeFlows: [],
1276
+ affectedRolloutUnits: [],
1277
+ unexpectedFiles: [],
1278
+ unexpectedModules: [],
1279
+ unexpectedServices: [],
1280
+ rolloutRisk: 'low',
1281
+ findings: [],
1282
+ narratives: emptyNarratives,
1283
+ riskSynthesis: {
1284
+ overallRisk: 'low',
1285
+ summary: 'Intent runtime unavailable; drift synthesis fell back to legacy plan-derived scope reasoning.',
1286
+ primaryNarratives: [],
1287
+ contributingCategories: [],
1288
+ rawFindingCount: 0,
1289
+ compressedNarrativeCount: 0,
1290
+ authExposure: authTouched,
1291
+ infraExposure: infraTouched,
1292
+ deploymentExposure: deploymentTouched,
1293
+ dependencyExposure: dependencyManifestTouched,
1294
+ transitiveImpactCount: 0,
1295
+ runtimeFlowExposure: false,
1296
+ externalSideEffectExposure: false,
1297
+ stateOwnershipExposure: false,
1298
+ affectedRolloutUnits: [],
1299
+ cascadingRisk: 'low',
1300
+ rolloutTrust: governancePosture.rolloutTrust,
1301
+ governanceGate: governancePosture.governanceGate,
1302
+ postureSummary: governancePosture.summary,
1303
+ priorityCounts: governancePosture.priorityCounts,
1304
+ remediationOrder: governancePosture.remediationOrder,
1305
+ },
1306
+ governancePosture,
1307
+ governanceDecisions,
1308
+ explanation: ['Intent runtime unavailable; drift intelligence fell back to legacy plan-based scope reasoning.'],
1309
+ };
1310
+ }
1311
+ const approvedFiles = new Set(runtime.intentPack.approvedScope.files.map(intelligence_runtime_common_1.normalizeRepoPath));
1312
+ const approvedModules = new Set(runtime.intentPack.approvedScope.modules.map(intelligence_runtime_common_1.normalizeRepoPath));
1313
+ const approvedServices = new Set(runtime.intentPack.approvedScope.services.map(intelligence_runtime_common_1.normalizeRepoPath));
1314
+ const approvedBoundaryLabel = runtime.intentPack.approvedScope.services.length > 0
1315
+ ? summarizeValues(runtime.intentPack.approvedScope.services, 2)
1316
+ : runtime.intentPack.approvedScope.modules.length > 0
1317
+ ? summarizeValues(runtime.intentPack.approvedScope.modules, 2)
1318
+ : 'intent scope';
1319
+ const approvedLayers = new Set([
1320
+ ...runtime.intentPack.approvedScope.files.map(classifyArchitectureLayer),
1321
+ ...runtime.intentPack.approvedScope.modules.map(classifyArchitectureLayer),
1322
+ ]);
1323
+ const dependencyManifestSet = new Set(runtime.repositoryGraph.boundaries.dependencyManifests.map(intelligence_runtime_common_1.normalizeRepoPath));
1324
+ const ownershipBoundaries = runtime.repositoryGraph.semantic?.ownershipBoundaries || [];
1325
+ const semanticContracts = runtime.repositoryGraph.semantic?.contracts || [];
1326
+ const knownInvariants = runtime.invariantMemory?.invariants || runtime.repositoryGraph.semantic?.invariants || [];
1327
+ const serviceBoundaries = runtime.contextPack.serviceBoundaries.map((boundary) => ({
1328
+ name: boundary.name,
1329
+ path: (0, intelligence_runtime_common_1.normalizeRepoPath)(boundary.path),
1330
+ }));
1331
+ const projectRoot = runtime.sessionRuntime.repoRoot || runtime.intentPack.governanceContext.projectRoot;
1332
+ const governanceDecisionRegistry = (0, governance_decisions_1.readGovernanceDecisionRegistry)(projectRoot);
1333
+ const changedFileEvidence = collectChangedFileEvidence(projectRoot, evaluatedChangedFiles);
1334
+ const directDeploymentEvidence = infraTouched
1335
+ || deploymentTouched
1336
+ || dependencyManifestTouched
1337
+ || changedFileEvidence.deploymentSemanticFiles.length > 0;
1338
+ const directRuntimeEvidence = changedFileEvidence.stateMutationFiles.length > 0
1339
+ || changedFileEvidence.externalSideEffectFiles.length > 0
1340
+ || changedFileEvidence.sensitiveRuntimeFiles.length > 0
1341
+ || changedFileEvidence.contractSurfaceFiles.length > 0;
1342
+ const changedServices = (0, intelligence_runtime_common_1.dedupeSorted)(evaluatedChangedFiles
1343
+ .map((filePath) => matchServiceBoundary(serviceBoundaries, filePath) || matchServiceBoundary(serviceBoundaries, deriveModulePath(filePath)))
1344
+ .filter((value) => Boolean(value)));
1345
+ const { outgoing, incoming } = buildModuleAdjacency(runtime.repositoryGraph);
1346
+ const impactedModulesSet = new Set(changedModules);
1347
+ for (const moduleName of changedModules) {
1348
+ for (const downstream of outgoing.get(moduleName) || []) {
1349
+ impactedModulesSet.add(downstream);
1350
+ }
1351
+ for (const upstream of incoming.get(moduleName) || []) {
1352
+ impactedModulesSet.add(upstream);
1353
+ }
1354
+ }
1355
+ const impactedModules = (0, intelligence_runtime_common_1.dedupeSorted)([...impactedModulesSet]);
1356
+ const impactedServices = (0, intelligence_runtime_common_1.dedupeSorted)(impactedModules
1357
+ .map((moduleName) => matchServiceBoundary(serviceBoundaries, moduleName))
1358
+ .filter((value) => Boolean(value)));
1359
+ const unexpectedFiles = evaluatedChangedFiles.filter((filePath) => !approvedFiles.has(filePath));
1360
+ const unexpectedModules = (0, intelligence_runtime_common_1.dedupeSorted)(changedModules.filter((moduleName) => !approvedModules.has(moduleName)));
1361
+ const unexpectedServices = approvedServices.size > 0
1362
+ ? (0, intelligence_runtime_common_1.dedupeSorted)(changedServices.filter((serviceName) => !approvedServices.has(serviceName)))
1363
+ : [];
1364
+ const approvedOwnershipBoundaryNames = new Set((0, intelligence_runtime_common_1.dedupeSorted)([...runtime.intentPack.approvedScope.modules, ...runtime.intentPack.approvedScope.services]
1365
+ .map((pathValue) => matchOwnershipBoundary(ownershipBoundaries, pathValue)?.name || '')
1366
+ .filter(Boolean)));
1367
+ const approvedOwnershipDomains = new Set(Array.from(approvedOwnershipBoundaryNames)
1368
+ .map((name) => ownershipBoundaries.find((boundary) => boundary.name === name)?.domain || '')
1369
+ .filter(Boolean));
1370
+ const runtimeModel = runtime.repositoryGraph.semantic?.runtime;
1371
+ const behaviorProfiles = runtimeModel?.behaviorProfiles || [];
1372
+ const runtimeInteractions = runtimeModel?.interactions || [];
1373
+ const deploymentBoundaries = runtimeModel?.deploymentBoundaries || [];
1374
+ const changedBoundaryIds = new Set((0, intelligence_runtime_common_1.dedupeSorted)(changedFiles
1375
+ .filter((filePath) => !isSupportOnlyPath(filePath))
1376
+ .map((filePath) => {
1377
+ const boundary = matchOwnershipBoundary(ownershipBoundaries, filePath)
1378
+ || matchOwnershipBoundary(ownershipBoundaries, deriveModulePath(filePath));
1379
+ return boundary?.id || '';
1380
+ })
1381
+ .filter(Boolean)));
1382
+ const changedBehaviorProfiles = behaviorProfiles.filter((profile) => changedBoundaryIds.has(profile.boundaryId));
1383
+ const impactedRuntimeFlows = (0, intelligence_runtime_common_1.dedupeSorted)([
1384
+ ...changedBehaviorProfiles.flatMap((profile) => profile.criticalFlows),
1385
+ ...runtimeInteractions
1386
+ .filter((interaction) => changedBoundaryIds.has(interaction.fromBoundaryId)
1387
+ || (interaction.toBoundaryId ? changedBoundaryIds.has(interaction.toBoundaryId) : false))
1388
+ .map((interaction) => `${interaction.kind}:${interaction.fromBoundaryName}->${interaction.toBoundaryName || interaction.subject}`),
1389
+ ]).slice(0, 24);
1390
+ const affectedRolloutUnits = (0, intelligence_runtime_common_1.dedupeSorted)([
1391
+ ...changedBehaviorProfiles.flatMap((profile) => profile.rolloutUnits),
1392
+ ...deploymentBoundaries
1393
+ .filter((boundary) => boundary.dependentBoundaryIds.some((id) => changedBoundaryIds.has(id)))
1394
+ .flatMap((boundary) => boundary.rolloutUnits),
1395
+ ]).slice(0, 20);
1396
+ const profileSideEffectExposure = changedBehaviorProfiles.some((profile) => profile.sideEffectKinds.length > 0);
1397
+ const profileStateOwnershipExposure = changedBehaviorProfiles.some((profile) => profile.behaviorKinds.includes('state-owner') || profile.behaviorKinds.includes('state-mutator'));
1398
+ const externalSideEffectExposure = profileSideEffectExposure && changedFileEvidence.externalSideEffectFiles.length > 0;
1399
+ const stateOwnershipExposure = profileStateOwnershipExposure && changedFileEvidence.stateMutationFiles.length > 0;
1400
+ const findings = [];
1401
+ const pushFinding = (finding) => {
1402
+ const evidenceTier = finding.evidenceTier || defaultEvidenceTier(finding, changedFileEvidence);
1403
+ const actionability = finding.actionability || defaultActionability(finding.category, finding.severity, evidenceTier);
1404
+ const findingForPriority = { ...finding, evidenceTier, actionability };
1405
+ const priority = finding.priority || deriveGovernancePriority(findingForPriority);
1406
+ const governanceGate = finding.governanceGate || deriveGovernanceGate(priority, finding.category);
1407
+ const rolloutTrust = finding.rolloutTrust || deriveRolloutTrust(findingForPriority, priority);
1408
+ const changedLines = finding.evidence?.changedLines
1409
+ || categoryLineEvidence(finding.category, finding.file, changedFileEvidence);
1410
+ const changedFilesForFinding = finding.evidence?.changedFiles
1411
+ || (0, intelligence_runtime_common_1.dedupeSortedPaths)([finding.file || '', ...changedLines.map((line) => line.file)].filter(Boolean));
1412
+ const evidence = finding.evidence || {
1413
+ tier: evidenceTier,
1414
+ changedFiles: changedFilesForFinding,
1415
+ changedLines,
1416
+ dependencyEdges: [],
1417
+ boundary: finding.service || finding.module || null,
1418
+ explanation: defaultEvidenceExplanation(evidenceTier),
1419
+ };
1420
+ const remediationGuidance = finding.remediationGuidance || {
1421
+ actionability,
1422
+ evidenceTier,
1423
+ minimalCorrection: defaultMinimalCorrection(finding),
1424
+ boundaryToPreserve: approvedBoundaryLabel,
1425
+ verifyAfterRemediation: 'Run `neurcode verify --evidence` after narrowing the change to confirm deterministic governance and replay lineage.',
1426
+ uncertainty: uncertaintyForTier(evidenceTier),
1427
+ };
1428
+ findings.push({
1429
+ id: `${finding.category}-${hashId([
1430
+ finding.category,
1431
+ finding.severity,
1432
+ finding.file || '',
1433
+ finding.module || '',
1434
+ finding.service || '',
1435
+ finding.message,
1436
+ ])}`,
1437
+ ...finding,
1438
+ evidenceTier,
1439
+ actionability,
1440
+ priority,
1441
+ governanceGate,
1442
+ rolloutTrust,
1443
+ relationships: finding.relationships || [],
1444
+ evidence,
1445
+ remediationGuidance,
1446
+ });
1447
+ };
1448
+ if (approvedOwnershipBoundaryNames.size > 0) {
1449
+ const changedOwnershipBoundaries = (0, intelligence_runtime_common_1.dedupeSorted)(changedFiles
1450
+ .map((filePath) => {
1451
+ const matched = matchOwnershipBoundary(ownershipBoundaries, filePath)
1452
+ || matchOwnershipBoundary(ownershipBoundaries, deriveModulePath(filePath));
1453
+ return matched?.name || '';
1454
+ })
1455
+ .filter(Boolean)).map((name) => ownershipBoundaries.find((boundary) => boundary.name === name))
1456
+ .filter((value) => Boolean(value));
1457
+ const unexpectedOwnershipBoundaries = changedOwnershipBoundaries.filter((boundary) => !approvedOwnershipBoundaryNames.has(boundary.name));
1458
+ if (unexpectedOwnershipBoundaries.length > 0) {
1459
+ pushFinding({
1460
+ category: 'ownership-inversion',
1461
+ severity: unexpectedOwnershipBoundaries.some((boundary) => boundary.criticality === 'critical')
1462
+ || unexpectedOwnershipBoundaries.some((boundary) => !approvedOwnershipDomains.has(boundary.domain))
1463
+ ? 'critical'
1464
+ : unexpectedOwnershipBoundaries.some((boundary) => boundary.criticality === 'sensitive')
1465
+ ? 'high'
1466
+ : 'medium',
1467
+ module: unexpectedOwnershipBoundaries[0]?.path || null,
1468
+ service: unexpectedOwnershipBoundaries[0]?.name || null,
1469
+ message: `Implementation crossed ownership boundary into ${summarizeValues(unexpectedOwnershipBoundaries.map((item) => item.name), 4)}.`,
1470
+ rationale: 'The active intent pack approved one bounded owner envelope, but the change now spans additional domain responsibilities.',
1471
+ expected: Array.from(approvedOwnershipBoundaryNames).join(', '),
1472
+ actual: unexpectedOwnershipBoundaries.map((item) => item.name).join(', '),
1473
+ });
1474
+ }
1475
+ }
1476
+ const unexpectedBehaviorKinds = (0, intelligence_runtime_common_1.dedupeSorted)(changedBehaviorProfiles
1477
+ .flatMap((profile) => profile.behaviorKinds)
1478
+ .filter((kind) => !runtime.intentPack.semanticExpectations.expectedBehaviorKinds.includes(kind)));
1479
+ if (unexpectedBehaviorKinds.length > 0) {
1480
+ const strongBehaviorEvidence = directRuntimeEvidence
1481
+ || unexpectedBehaviorKinds.includes('workflow-orchestrator')
1482
+ || unexpectedBehaviorKinds.includes('event-producer');
1483
+ pushFinding({
1484
+ category: 'behavioral-drift',
1485
+ severity: strongBehaviorEvidence
1486
+ ? authTouched || infraTouched ? 'critical' : 'high'
1487
+ : 'medium',
1488
+ module: changedModules[0] || null,
1489
+ service: changedServices[0] || null,
1490
+ message: `Runtime behavior expanded into undeclared ${summarizeValues(unexpectedBehaviorKinds, 4)} role(s).`,
1491
+ rationale: strongBehaviorEvidence
1492
+ ? 'The active intent runtime did not declare these runtime behaviors, and changed-file evidence supports a runtime role change.'
1493
+ : 'Repository topology suggests an undeclared runtime role, but no direct changed-file runtime signal was found; treat this as bounded inference.',
1494
+ expected: runtime.intentPack.semanticExpectations.expectedBehaviorKinds.join(', '),
1495
+ actual: unexpectedBehaviorKinds.join(', '),
1496
+ evidenceTier: strongBehaviorEvidence
1497
+ ? [
1498
+ ...changedFileEvidence.stateMutationLines,
1499
+ ...changedFileEvidence.externalSideEffectLines,
1500
+ ...changedFileEvidence.sensitiveRuntimeLines,
1501
+ ...changedFileEvidence.contractSurfaceLines,
1502
+ ].length > 0 ? 'direct-diff' : 'direct-file'
1503
+ : 'bounded-inference',
1504
+ evidence: {
1505
+ tier: strongBehaviorEvidence
1506
+ ? [
1507
+ ...changedFileEvidence.stateMutationLines,
1508
+ ...changedFileEvidence.externalSideEffectLines,
1509
+ ...changedFileEvidence.sensitiveRuntimeLines,
1510
+ ...changedFileEvidence.contractSurfaceLines,
1511
+ ].length > 0 ? 'direct-diff' : 'direct-file'
1512
+ : 'bounded-inference',
1513
+ changedFiles: (0, intelligence_runtime_common_1.dedupeSortedPaths)([
1514
+ ...changedFileEvidence.stateMutationFiles,
1515
+ ...changedFileEvidence.externalSideEffectFiles,
1516
+ ...changedFileEvidence.sensitiveRuntimeFiles,
1517
+ ...changedFileEvidence.contractSurfaceFiles,
1518
+ ]).slice(0, 8),
1519
+ changedLines: [
1520
+ ...changedFileEvidence.stateMutationLines,
1521
+ ...changedFileEvidence.externalSideEffectLines,
1522
+ ...changedFileEvidence.sensitiveRuntimeLines,
1523
+ ...changedFileEvidence.contractSurfaceLines,
1524
+ ].slice(0, 8),
1525
+ dependencyEdges: [],
1526
+ boundary: changedServices[0] || changedModules[0] || null,
1527
+ explanation: strongBehaviorEvidence
1528
+ ? 'Runtime behavior evidence appears in changed files.'
1529
+ : 'Runtime behavior evidence is inferred from repository behavior profiles.',
1530
+ },
1531
+ });
1532
+ }
1533
+ if (affectedRolloutUnits.length > 0 && !runtime.intentPack.semanticExpectations.expectedRolloutUnits.some((entry) => affectedRolloutUnits.includes(entry))) {
1534
+ const hasExplicitBoundarySpread = unexpectedServices.length > 0 || unexpectedModules.length > 1;
1535
+ if (directDeploymentEvidence || hasExplicitBoundarySpread) {
1536
+ pushFinding({
1537
+ category: 'deployment-coupling',
1538
+ severity: directDeploymentEvidence && (infraTouched || deploymentTouched || affectedRolloutUnits.length > 1) ? 'high' : 'medium',
1539
+ module: changedModules[0] || null,
1540
+ service: changedServices[0] || null,
1541
+ message: directDeploymentEvidence
1542
+ ? `Change has direct deployment evidence and reaches rollout unit(s) ${summarizeValues(affectedRolloutUnits, 4)} outside the declared envelope.`
1543
+ : `Repository topology suggests rollout unit(s) ${summarizeValues(affectedRolloutUnits, 4)} may be adjacent to this boundary change.`,
1544
+ rationale: directDeploymentEvidence
1545
+ ? 'Changed files include deployment, CI, dependency, or rollout semantics that make deployment propagation directly relevant.'
1546
+ : 'No deployment file changed; this is bounded topology inference from service/module spread, so severity stays conservative.',
1547
+ expected: runtime.intentPack.semanticExpectations.expectedRolloutUnits.join(', '),
1548
+ actual: affectedRolloutUnits.join(', '),
1549
+ evidenceTier: directDeploymentEvidence
1550
+ ? changedFileEvidence.deploymentSemanticLines.length > 0 ? 'direct-diff' : 'direct-file'
1551
+ : 'bounded-inference',
1552
+ evidence: {
1553
+ tier: directDeploymentEvidence
1554
+ ? changedFileEvidence.deploymentSemanticLines.length > 0 ? 'direct-diff' : 'direct-file'
1555
+ : 'bounded-inference',
1556
+ changedFiles: changedFileEvidence.deploymentSemanticFiles.slice(0, 8),
1557
+ changedLines: changedFileEvidence.deploymentSemanticLines.slice(0, 8),
1558
+ dependencyEdges: [],
1559
+ boundary: changedServices[0] || changedModules[0] || null,
1560
+ explanation: directDeploymentEvidence
1561
+ ? 'Deployment evidence appears in changed files or deployment-class paths.'
1562
+ : 'Deployment impact is inferred from service/module topology.',
1563
+ },
1564
+ });
1565
+ }
1566
+ }
1567
+ if (profileStateOwnershipExposure && (stateOwnershipExposure || unexpectedServices.length > 0)) {
1568
+ const stateDomains = (0, intelligence_runtime_common_1.dedupeSorted)(changedBehaviorProfiles
1569
+ .filter((profile) => profile.behaviorKinds.includes('state-owner') || profile.behaviorKinds.includes('state-mutator'))
1570
+ .map((profile) => profile.domain));
1571
+ if (stateOwnershipExposure || stateDomains.length > 1 || unexpectedServices.length > 0) {
1572
+ pushFinding({
1573
+ category: 'state-ownership-risk',
1574
+ severity: stateOwnershipExposure && (stateDomains.length > 1 || authTouched || changedBehaviorProfiles.some((profile) => profile.sideEffectKinds.includes('queue')))
1575
+ ? 'high'
1576
+ : 'medium',
1577
+ module: changedModules[0] || null,
1578
+ service: changedServices[0] || null,
1579
+ message: stateOwnershipExposure
1580
+ ? `Changed-file evidence touches state mutation in ${summarizeValues(changedFileEvidence.stateMutationFiles, 3)} while state-owning boundary ${summarizeValues(stateDomains, 4)} is in scope.`
1581
+ : `State-owning boundary ${summarizeValues(stateDomains, 4)} is adjacent to the change, but direct mutation evidence was not observed.`,
1582
+ rationale: stateOwnershipExposure
1583
+ ? 'State mutation appears directly in changed files, so rollback and coordination risk are concrete.'
1584
+ : 'This is topology-derived state exposure only; treat it as an architectural review prompt rather than confirmed corruption risk.',
1585
+ expected: Array.from(approvedOwnershipDomains).join(', '),
1586
+ actual: stateDomains.join(', '),
1587
+ evidenceTier: stateOwnershipExposure
1588
+ ? changedFileEvidence.stateMutationLines.length > 0 ? 'direct-diff' : 'direct-file'
1589
+ : 'topology-only',
1590
+ evidence: {
1591
+ tier: stateOwnershipExposure
1592
+ ? changedFileEvidence.stateMutationLines.length > 0 ? 'direct-diff' : 'direct-file'
1593
+ : 'topology-only',
1594
+ changedFiles: changedFileEvidence.stateMutationFiles.slice(0, 8),
1595
+ changedLines: changedFileEvidence.stateMutationLines.slice(0, 8),
1596
+ dependencyEdges: [],
1597
+ boundary: changedServices[0] || changedModules[0] || null,
1598
+ explanation: stateOwnershipExposure
1599
+ ? 'State mutation evidence appears in changed files.'
1600
+ : 'State exposure is inferred from ownership topology without direct mutation evidence.',
1601
+ },
1602
+ });
1603
+ }
1604
+ }
1605
+ for (const filePath of unexpectedFiles) {
1606
+ const boundary = findBoundaryPolicy(runtime.intentPack.forbiddenBoundaries, filePath);
1607
+ const moduleName = deriveModulePath(filePath);
1608
+ const serviceName = matchServiceBoundary(serviceBoundaries, filePath) || matchServiceBoundary(serviceBoundaries, moduleName);
1609
+ const flags = (0, intelligence_runtime_common_1.classifyBoundaryPath)(filePath);
1610
+ if (boundary?.policy === 'forbidden') {
1611
+ pushFinding({
1612
+ category: boundary.type === 'infra' || boundary.type === 'ci'
1613
+ ? 'infra-leakage'
1614
+ : boundary.type === 'dependency-manifest'
1615
+ ? 'dependency-spread'
1616
+ : 'sensitive-boundary',
1617
+ severity: boundary.type === 'sensitive' || containsCriticalDomain(boundary.path) ? 'critical' : 'high',
1618
+ file: filePath,
1619
+ module: moduleName,
1620
+ service: serviceName,
1621
+ message: `Intent drift crossed a forbidden ${boundary.type} boundary at ${filePath}.`,
1622
+ rationale: boundary.reason,
1623
+ expected: runtime.intentPack.approvedScope.files.join(', '),
1624
+ actual: filePath,
1625
+ evidenceTier: 'direct-file',
1626
+ actionability: 'directly-actionable',
1627
+ });
1628
+ continue;
1629
+ }
1630
+ if (flags.dependencyManifest || dependencyManifestSet.has(filePath)) {
1631
+ pushFinding({
1632
+ category: 'dependency-spread',
1633
+ severity: containsCriticalDomain(filePath) ? 'critical' : 'high',
1634
+ file: filePath,
1635
+ module: moduleName,
1636
+ service: serviceName,
1637
+ message: `Dependency surface expanded outside approved scope via ${filePath}.`,
1638
+ rationale: 'Manifest or dependency changes widen blast radius and should be explicitly declared in the intent pack.',
1639
+ expected: runtime.intentPack.expectedDependencies.join(', '),
1640
+ actual: filePath,
1641
+ evidenceTier: 'direct-file',
1642
+ actionability: 'directly-actionable',
1643
+ });
1644
+ continue;
1645
+ }
1646
+ if (flags.infra || flags.ci) {
1647
+ pushFinding({
1648
+ category: 'infra-leakage',
1649
+ severity: deploymentTouched ? 'critical' : 'high',
1650
+ file: filePath,
1651
+ module: moduleName,
1652
+ service: serviceName,
1653
+ message: `Infrastructure or delivery path drift detected at ${filePath}.`,
1654
+ rationale: 'Infra and CI changes materially increase rollout risk and should not appear as incidental AI edits.',
1655
+ expected: runtime.intentPack.expectedInfrastructure.join(', '),
1656
+ actual: filePath,
1657
+ evidenceTier: 'direct-file',
1658
+ actionability: 'directly-actionable',
1659
+ });
1660
+ continue;
1661
+ }
1662
+ if (unexpectedModules.includes(moduleName) || (serviceName && unexpectedServices.includes(serviceName))) {
1663
+ pushFinding({
1664
+ category: serviceName ? 'cross-service' : 'scope-expansion',
1665
+ severity: serviceName && (containsCriticalDomain(serviceName) || authTouched) ? 'critical' : serviceName ? 'high' : 'medium',
1666
+ file: filePath,
1667
+ module: moduleName,
1668
+ service: serviceName,
1669
+ message: serviceName
1670
+ ? `Implementation drift spread into unapproved service boundary ${serviceName}.`
1671
+ : `Implementation drift spread into unapproved module ${moduleName}.`,
1672
+ rationale: 'Neurcode expected work to remain within the declared service and module envelope for this intent.',
1673
+ expected: runtime.intentPack.approvedScope.modules.join(', '),
1674
+ actual: moduleName,
1675
+ evidenceTier: 'direct-file',
1676
+ actionability: 'directly-actionable',
1677
+ });
1678
+ }
1679
+ }
1680
+ for (const moduleName of changedModules) {
1681
+ const sourceLayer = classifyArchitectureLayer(moduleName);
1682
+ const unexpectedTargets = [...(outgoing.get(moduleName) || [])].filter((target) => !approvedModules.has(target));
1683
+ if (unexpectedTargets.length === 0) {
1684
+ continue;
1685
+ }
1686
+ const sourceOwnershipBoundary = matchOwnershipBoundary(ownershipBoundaries, moduleName);
1687
+ const sourceContracts = sourceOwnershipBoundary
1688
+ ? semanticContracts.filter((contract) => contract.boundaryId === sourceOwnershipBoundary.id)
1689
+ : [];
1690
+ const targetOwnershipKinds = (0, intelligence_runtime_common_1.dedupeSorted)(unexpectedTargets.map((target) => matchOwnershipBoundary(ownershipBoundaries, target)?.kind || classifyArchitectureLayer(target)));
1691
+ const forbiddenDependencyKinds = (0, intelligence_runtime_common_1.dedupeSorted)(sourceContracts.flatMap((contract) => contract.forbiddenDependencyKinds));
1692
+ const violatedDependencyKinds = targetOwnershipKinds.filter((kind) => forbiddenDependencyKinds.includes(kind));
1693
+ const targetLayer = classifyArchitectureLayer(unexpectedTargets[0] || moduleName);
1694
+ const targetServices = (0, intelligence_runtime_common_1.dedupeSorted)(unexpectedTargets
1695
+ .map((target) => matchServiceBoundary(serviceBoundaries, target))
1696
+ .filter((value) => Boolean(value)));
1697
+ const evidenceLevel = violatedDependencyKinds.length > 0 || targetServices.length > 0
1698
+ ? 'bounded-inference'
1699
+ : 'topology-only';
1700
+ const baseSeverity = computeCouplingSeverity(sourceLayer, targetLayer, [...unexpectedTargets, ...targetServices], evidenceLevel);
1701
+ const severity = sourceOwnershipBoundary && violatedDependencyKinds.length > 0
1702
+ ? criticalityToSeverity(sourceOwnershipBoundary.criticality, baseSeverity)
1703
+ : baseSeverity;
1704
+ const targetIsShared = targetLayer === 'shared';
1705
+ const targetIsCriticalLayer = targetLayer === 'data' || targetLayer === 'infra' || targetLayer === 'ci';
1706
+ const category = violatedDependencyKinds.length > 0
1707
+ ? 'invariant-violation'
1708
+ : sourceLayer === 'shared'
1709
+ || targetIsShared
1710
+ || ((sourceLayer === 'ui' || sourceLayer === 'api') && targetIsCriticalLayer)
1711
+ ? 'layer-violation'
1712
+ : targetLayer === 'contract'
1713
+ ? 'contract-misuse'
1714
+ : targetLayer !== sourceLayer && !targetIsShared
1715
+ ? 'architectural-leakage'
1716
+ : 'runtime-coupling';
1717
+ pushFinding({
1718
+ category,
1719
+ severity,
1720
+ module: moduleName,
1721
+ service: matchServiceBoundary(serviceBoundaries, moduleName),
1722
+ message: violatedDependencyKinds.length > 0
1723
+ ? `${moduleName} now depends on forbidden ${summarizeValues(violatedDependencyKinds, 3)} surface(s) via ${summarizeValues(unexpectedTargets, 3)}.`
1724
+ : `Direct runtime coupling from ${moduleName} now reaches unapproved module(s) ${summarizeValues(unexpectedTargets, 3)}.`,
1725
+ rationale: violatedDependencyKinds.length > 0
1726
+ ? sourceContracts[0]?.rationale || 'The inferred service contract forbids this dependency direction because it weakens architectural invariants.'
1727
+ : evidenceLevel === 'topology-only'
1728
+ ? 'Repository import topology suggests adjacent module impact, but no explicit service or forbidden dependency boundary was crossed.'
1729
+ : 'Repository import topology shows direct dependency movement outside the approved engineering boundary.',
1730
+ expected: runtime.intentPack.approvedScope.modules.join(', '),
1731
+ actual: violatedDependencyKinds.length > 0 ? violatedDependencyKinds.join(', ') : unexpectedTargets.join(', '),
1732
+ evidenceTier: evidenceLevel === 'topology-only' ? 'topology-only' : 'bounded-inference',
1733
+ evidence: {
1734
+ tier: evidenceLevel === 'topology-only' ? 'topology-only' : 'bounded-inference',
1735
+ changedFiles: [],
1736
+ changedLines: [],
1737
+ dependencyEdges: unexpectedTargets.map((target) => `${moduleName}->${target}`).slice(0, 8),
1738
+ boundary: matchServiceBoundary(serviceBoundaries, moduleName) || moduleName,
1739
+ explanation: evidenceLevel === 'topology-only'
1740
+ ? 'Dependency evidence comes from repository import topology only.'
1741
+ : 'Dependency evidence comes from import topology plus service/contract boundary context.',
1742
+ },
1743
+ });
1744
+ }
1745
+ for (const filePath of evaluatedChangedFiles.slice(0, 24)) {
1746
+ const layer = classifyArchitectureLayer(filePath);
1747
+ if (layer === 'docs' || layer === 'test') {
1748
+ continue;
1749
+ }
1750
+ const content = safeReadRepoFile(projectRoot, filePath);
1751
+ if (!content) {
1752
+ continue;
1753
+ }
1754
+ const lower = content.toLowerCase();
1755
+ const moduleName = deriveModulePath(filePath);
1756
+ const serviceName = matchServiceBoundary(serviceBoundaries, filePath) || matchServiceBoundary(serviceBoundaries, moduleName);
1757
+ const ownershipBoundary = matchOwnershipBoundary(ownershipBoundaries, filePath)
1758
+ || matchOwnershipBoundary(ownershipBoundaries, moduleName);
1759
+ const serviceContract = ownershipBoundary
1760
+ ? semanticContracts.find((contract) => contract.boundaryId === ownershipBoundary.id && contract.kind === 'service-contract') || null
1761
+ : null;
1762
+ const knownInvariant = ownershipBoundary
1763
+ ? knownInvariants.find((invariant) => invariant.boundaryId === ownershipBoundary.id) || null
1764
+ : null;
1765
+ const addedLineText = (changedFileEvidence.addedLinesByFile.get((0, intelligence_runtime_common_1.normalizeRepoPath)(filePath)) || [])
1766
+ .map((line) => line.text)
1767
+ .join('\n');
1768
+ const observedResponsibilitiesFromDiff = addedLineText
1769
+ ? detectResponsibilitySignals(addedLineText)
1770
+ : [];
1771
+ const observedResponsibilities = observedResponsibilitiesFromDiff.length > 0
1772
+ ? observedResponsibilitiesFromDiff
1773
+ : detectResponsibilitySignals(content);
1774
+ const semanticEvidenceTier = observedResponsibilitiesFromDiff.length > 0 ? 'direct-diff' : 'direct-file';
1775
+ if (ownershipBoundary && serviceContract) {
1776
+ const violatedResponsibilities = (0, intelligence_runtime_common_1.dedupeSorted)(serviceContract.forbiddenResponsibilities.filter((responsibility) => observedResponsibilities.includes(responsibility)));
1777
+ if (violatedResponsibilities.length > 0) {
1778
+ const baseSeverity = criticalityToSeverity(ownershipBoundary.criticality, violatedResponsibilities.length > 1 ? 'high' : 'medium');
1779
+ pushFinding({
1780
+ category: ownershipBoundary.kind === 'infra'
1781
+ || ownershipBoundary.kind === 'shared'
1782
+ || ownershipBoundary.kind === 'api'
1783
+ ? 'invariant-violation'
1784
+ : 'responsibility-drift',
1785
+ severity: semanticEvidenceTier === 'direct-file' && baseSeverity === 'critical'
1786
+ ? 'high'
1787
+ : semanticEvidenceTier === 'direct-file' && baseSeverity === 'high'
1788
+ ? 'medium'
1789
+ : baseSeverity,
1790
+ file: filePath,
1791
+ module: moduleName,
1792
+ service: serviceName || ownershipBoundary.name,
1793
+ message: `${filePath} carries ${summarizeValues(violatedResponsibilities, 3)} semantics that violate the ${ownershipBoundary.name} contract.`,
1794
+ rationale: semanticEvidenceTier === 'direct-diff'
1795
+ ? knownInvariant?.rationale || serviceContract.rationale
1796
+ : `${knownInvariant?.rationale || serviceContract.rationale} The signal is present in a changed file but was not proven to be introduced by added lines, so remediation should verify whether it is pre-existing.`,
1797
+ expected: serviceContract.expectedResponsibilities.join(', '),
1798
+ actual: violatedResponsibilities.join(', '),
1799
+ evidenceTier: semanticEvidenceTier,
1800
+ });
1801
+ }
1802
+ }
1803
+ const persistenceLines = linesForFile(changedFileEvidence.stateMutationLines, filePath);
1804
+ const sensitiveLines = linesForFile(changedFileEvidence.sensitiveRuntimeLines, filePath);
1805
+ const contractLines = linesForFile(changedFileEvidence.contractSurfaceLines, filePath);
1806
+ const touchesPersistence = persistenceLines.length > 0 || EVIDENCE_PATTERNS.stateMutation.test(content);
1807
+ const touchesSensitiveRuntime = sensitiveLines.length > 0 || EVIDENCE_PATTERNS.sensitiveRuntime.test(content);
1808
+ const touchesContractSurface = contractLines.length > 0 || EVIDENCE_PATTERNS.contractSurface.test(content);
1809
+ const outsideApprovedFileOrModule = !approvedFiles.has(filePath) || !approvedModules.has(moduleName);
1810
+ if ((layer === 'ui' || layer === 'api') && touchesPersistence && persistenceLines.length > 0) {
1811
+ pushFinding({
1812
+ category: 'layer-violation',
1813
+ severity: layer === 'ui' ? 'critical' : 'high',
1814
+ file: filePath,
1815
+ module: moduleName,
1816
+ service: serviceName,
1817
+ message: `${filePath} now mixes ${layer.toUpperCase()} logic with persistence-layer behavior.`,
1818
+ rationale: 'Cross-layer persistence access is a semantic architectural shortcut that expands hidden runtime coupling.',
1819
+ expected: Array.from(approvedLayers).join(', '),
1820
+ actual: 'data-layer behavior in unexpected runtime layer',
1821
+ evidenceTier: 'direct-diff',
1822
+ });
1823
+ continue;
1824
+ }
1825
+ if ((layer === 'ui' || layer === 'shared' || layer === 'api') && touchesSensitiveRuntime && outsideApprovedFileOrModule && sensitiveLines.length > 0) {
1826
+ pushFinding({
1827
+ category: containsCriticalDomain(filePath) || authTouched ? 'sensitive-boundary' : 'architectural-leakage',
1828
+ severity: authTouched || containsCriticalDomain(filePath) ? 'critical' : 'high',
1829
+ file: filePath,
1830
+ module: moduleName,
1831
+ service: serviceName,
1832
+ message: `${filePath} now carries sensitive runtime or credential-handling semantics outside the expected boundary.`,
1833
+ rationale: 'Credential, secret, or token handling outside the intended runtime layer creates hidden security and ownership risk.',
1834
+ expected: runtime.intentPack.approvedScope.files.join(', '),
1835
+ actual: lower.includes('process.env') ? 'process.env or secret handling introduced' : 'sensitive runtime handling introduced',
1836
+ evidenceTier: 'direct-diff',
1837
+ });
1838
+ continue;
1839
+ }
1840
+ if (touchesContractSurface && (unexpectedServices.length > 0 || impactedServices.length > 1)) {
1841
+ const contractEvidenceTier = contractLines.length > 0 ? 'direct-diff' : 'direct-file';
1842
+ pushFinding({
1843
+ category: 'contract-misuse',
1844
+ severity: contractEvidenceTier === 'direct-diff' && impactedServices.length > 1 ? 'high' : 'medium',
1845
+ file: filePath,
1846
+ module: moduleName,
1847
+ service: serviceName,
1848
+ message: `${filePath} carries contract-surface semantics outside the approved service boundary.`,
1849
+ rationale: contractEvidenceTier === 'direct-diff'
1850
+ ? 'API, schema, or contract edits in a broadened change set indicate interface drift rather than a bounded implementation.'
1851
+ : 'Contract-surface semantics are present in a changed file, but added-line evidence did not prove the contract change was newly introduced.',
1852
+ expected: runtime.intentPack.approvedScope.modules.join(', '),
1853
+ actual: 'contract or schema surface drift',
1854
+ evidenceTier: contractEvidenceTier,
1855
+ });
1856
+ }
1857
+ }
1858
+ for (const dependency of changeSet.dependencyChanges) {
1859
+ if (dependency.kind === 'added' && !runtime.intentPack.expectedDependencies.includes(dependency.name)) {
1860
+ pushFinding({
1861
+ category: 'dependency-spread',
1862
+ severity: containsCriticalDomain(dependency.name) ? 'critical' : 'high',
1863
+ file: dependency.file,
1864
+ module: deriveModulePath(dependency.file),
1865
+ message: `Unexpected dependency addition detected: ${dependency.name}.`,
1866
+ rationale: 'New dependencies expand operational and rollout risk and should be declared up front in intent runtime.',
1867
+ expected: runtime.intentPack.expectedDependencies.join(', '),
1868
+ actual: dependency.name,
1869
+ evidenceTier: 'direct-file',
1870
+ actionability: 'directly-actionable',
1871
+ });
1872
+ }
1873
+ }
1874
+ const impactedOutsideApproved = impactedModules.filter((moduleName) => !approvedModules.has(moduleName));
1875
+ if (impactedOutsideApproved.length > 0) {
1876
+ const directServiceSpread = unexpectedServices.length > 0 || changedServices.length > 1;
1877
+ pushFinding({
1878
+ category: 'blast-radius',
1879
+ severity: directServiceSpread || authTouched || infraTouched || dependencyManifestTouched
1880
+ ? 'high'
1881
+ : impactedOutsideApproved.length >= 4
1882
+ ? 'medium'
1883
+ : 'low',
1884
+ module: impactedOutsideApproved[0] || null,
1885
+ message: directServiceSpread
1886
+ ? `Graph-aware blast radius crosses explicit service/module boundaries (${impactedOutsideApproved.length} impacted module(s) outside scope).`
1887
+ : `Repository topology suggests adjacent module impact outside approved scope (${impactedOutsideApproved.length} module(s)).`,
1888
+ rationale: directServiceSpread
1889
+ ? 'Changed files crossed an explicit service or sensitive boundary, so blast-radius escalation is evidence-backed.'
1890
+ : 'This is inferred from import topology only; severity is bounded unless direct boundary or runtime evidence appears.',
1891
+ expected: runtime.intentPack.approvedScope.modules.join(', '),
1892
+ actual: impactedOutsideApproved.join(', '),
1893
+ });
1894
+ }
1895
+ if (impactedServices.length > 1 || unexpectedServices.length > 0) {
1896
+ const directServiceSpread = unexpectedServices.length > 0 || changedServices.length > 1;
1897
+ pushFinding({
1898
+ category: 'rollout-risk',
1899
+ severity: directServiceSpread || deploymentTouched || infraTouched
1900
+ ? 'high'
1901
+ : 'medium',
1902
+ service: impactedServices[0] || null,
1903
+ message: directServiceSpread
1904
+ ? `Rollout review scope includes ${impactedServices.length} service boundary/boundaries with direct changed-service evidence.`
1905
+ : `Repository topology suggests rollout adjacency across ${impactedServices.length} service boundary/boundaries.`,
1906
+ rationale: directServiceSpread
1907
+ ? 'Direct changed files crossed service boundaries, so coordination risk should be reviewed.'
1908
+ : 'Service spread is inferred from topology only; use this as a review hint, not a confirmed rollout expansion.',
1909
+ expected: runtime.intentPack.approvedScope.services.join(', '),
1910
+ actual: impactedServices.join(', '),
1911
+ });
1912
+ }
1913
+ const decisionResult = applyGovernanceDecisions(attachFindingRelationships(dedupeFindings(findings)), governanceDecisionRegistry);
1914
+ const dedupedFindings = decisionResult.findings.sort((left, right) => remediationPriorityRank(right) - remediationPriorityRank(left));
1915
+ const governanceDecisions = decisionResult.summary;
1916
+ const rolloutRisk = dedupedFindings.reduce((current, finding) => {
1917
+ if (finding.severity === 'critical' || finding.severity === 'high')
1918
+ return 'high';
1919
+ if (finding.severity === 'medium')
1920
+ return maxRisk(current, 'medium');
1921
+ return current;
1922
+ }, changedFiles.length > 8 ? 'medium' : 'low');
1923
+ const narratives = buildDriftNarratives({
1924
+ findings: dedupedFindings,
1925
+ approvedBoundaryLabel,
1926
+ unexpectedModules,
1927
+ unexpectedServices,
1928
+ impactedModules,
1929
+ impactedServices,
1930
+ rolloutRisk,
1931
+ authTouched,
1932
+ infraTouched,
1933
+ deploymentTouched,
1934
+ dependencyManifestTouched,
1935
+ });
1936
+ const riskSynthesis = buildRiskSynthesis({
1937
+ findings: dedupedFindings,
1938
+ narratives,
1939
+ authTouched,
1940
+ infraTouched,
1941
+ deploymentTouched,
1942
+ dependencyManifestTouched,
1943
+ transitiveImpactCount: Math.max(0, impactedModules.length - changedModules.length),
1944
+ impactedRuntimeFlows,
1945
+ affectedRolloutUnits,
1946
+ externalSideEffectExposure,
1947
+ stateOwnershipExposure,
1948
+ directPropagationEvidence: directRuntimeEvidence
1949
+ || directDeploymentEvidence
1950
+ || unexpectedServices.length > 0
1951
+ || dependencyManifestTouched,
1952
+ directDeploymentEvidence,
1953
+ topologyOnlyPropagation: !directRuntimeEvidence
1954
+ && !directDeploymentEvidence
1955
+ && unexpectedServices.length === 0
1956
+ && dependencyManifestTouched === false
1957
+ && (impactedRuntimeFlows.length > 0 || affectedRolloutUnits.length > 0 || impactedModules.length > changedModules.length),
1958
+ });
1959
+ const governancePosture = buildGovernancePostureSummary(dedupedFindings);
1960
+ const confidence = dedupedFindings.some((finding) => (finding.severity === 'critical' || finding.severity === 'high')
1961
+ && Boolean(finding.file)
1962
+ && finding.category !== 'blast-radius'
1963
+ && finding.category !== 'rollout-risk'
1964
+ && finding.category !== 'deployment-coupling')
1965
+ ? 'high'
1966
+ : dedupedFindings.length > 0
1967
+ ? 'medium'
1968
+ : 'low';
1969
+ const historicalPatternNotes = (0, intelligence_runtime_common_1.dedupeSorted)(dedupedFindings
1970
+ .map((finding) => {
1971
+ const pattern = runtime.invariantMemory?.historicalDriftPatterns.find((entry) => entry.category === finding.category);
1972
+ if (!pattern || pattern.count < 1) {
1973
+ return '';
1974
+ }
1975
+ return `${finding.category} has appeared ${pattern.count} time(s) in invariant memory lineage.`;
1976
+ })
1977
+ .filter(Boolean));
1978
+ return {
1979
+ schemaVersion: 1,
1980
+ source: 'intent-runtime',
1981
+ flagged: dedupedFindings.length > 0,
1982
+ confidence,
1983
+ changedFiles,
1984
+ changedModules,
1985
+ changedServices,
1986
+ impactedModules,
1987
+ impactedServices,
1988
+ impactedRuntimeFlows,
1989
+ affectedRolloutUnits,
1990
+ unexpectedFiles,
1991
+ unexpectedModules,
1992
+ unexpectedServices,
1993
+ rolloutRisk,
1994
+ findings: dedupedFindings,
1995
+ narratives,
1996
+ riskSynthesis,
1997
+ governancePosture,
1998
+ governanceDecisions,
1999
+ explanation: [
2000
+ `Changed files: ${changedFiles.length}, changed modules: ${changedModules.length}, impacted modules: ${impactedModules.length}.`,
2001
+ impactedRuntimeFlows.length > 0
2002
+ ? `Runtime flows impacted: ${summarizeValues(impactedRuntimeFlows, 4)}.`
2003
+ : '',
2004
+ affectedRolloutUnits.length > 0
2005
+ ? directDeploymentEvidence
2006
+ ? `Rollout units affected with direct deployment evidence: ${summarizeValues(affectedRolloutUnits, 4)}.`
2007
+ : `Rollout units inferred from topology only: ${summarizeValues(affectedRolloutUnits, 4)}.`
2008
+ : '',
2009
+ directRuntimeEvidence || directDeploymentEvidence
2010
+ ? `Direct propagation evidence: ${summarizeValues([
2011
+ ...changedFileEvidence.stateMutationFiles,
2012
+ ...changedFileEvidence.externalSideEffectFiles,
2013
+ ...changedFileEvidence.deploymentSemanticFiles,
2014
+ ...changedFileEvidence.sensitiveRuntimeFiles,
2015
+ ...changedFileEvidence.contractSurfaceFiles,
2016
+ ], 4)}.`
2017
+ : impactedRuntimeFlows.length > 0 || affectedRolloutUnits.length > 0
2018
+ ? 'Propagation is topology-only; severity is intentionally bounded without changed-file runtime or deployment evidence.'
2019
+ : '',
2020
+ `Approved scope: ${runtime.intentPack.approvedScope.files.length} file(s), ${runtime.intentPack.approvedScope.modules.length} module(s), ${runtime.intentPack.approvedScope.services.length} service(s).`,
2021
+ `Governance posture: ${governancePosture.summary}`,
2022
+ governanceDecisions.decisionsApplied > 0
2023
+ ? `Governance decisions applied: ${governanceDecisions.activeOverrides} active, ${governanceDecisions.expiredOverrides} expired/invalid.`
2024
+ : governanceDecisions.expiredOverrides > 0
2025
+ ? `Governance decision file contained ${governanceDecisions.expiredOverrides} expired/invalid entr${governanceDecisions.expiredOverrides === 1 ? 'y' : 'ies'}.`
2026
+ : '',
2027
+ `Compressed ${dedupedFindings.length} raw drift signal(s) into ${narratives.length} operator narrative(s).`,
2028
+ historicalPatternNotes[0] || '',
2029
+ narratives.length > 0
2030
+ ? riskSynthesis.summary
2031
+ : 'No high-signal architectural drift was detected against the active intent runtime.',
2032
+ ].filter(Boolean),
2033
+ };
2034
+ }
2035
+ function buildContextAwareBlastRadius(changeSet, runtime, baseline, drift) {
2036
+ const flags = changeSet.changedFiles.map(intelligence_runtime_common_1.classifyBoundaryPath);
2037
+ const infraTouched = flags.some((item) => item.infra || item.ci);
2038
+ const dependencyManifestTouched = flags.some((item) => item.dependencyManifest);
2039
+ const authTouched = changeSet.changedFiles.some((filePath) => /(auth|token|secret|permission|billing|payment)/i.test(filePath));
2040
+ const apiTouched = changeSet.changedFiles.some((filePath) => /(api|route|controller|handler|graphql|rest)/i.test(filePath));
2041
+ const deploymentTouched = changeSet.changedFiles.some((filePath) => /(\.github\/workflows|deploy|terraform|helm|k8s|docker-compose)/i.test(filePath));
2042
+ let riskScore = baseline.riskScore;
2043
+ if (drift.riskSynthesis.overallRisk === 'critical'
2044
+ || drift.rolloutRisk === 'high'
2045
+ || drift.findings.some((item) => item.severity === 'critical')) {
2046
+ riskScore = 'high';
2047
+ }
2048
+ else if (drift.riskSynthesis.overallRisk === 'high'
2049
+ || (drift.rolloutRisk === 'medium' && riskScore === 'low')) {
2050
+ riskScore = 'medium';
2051
+ }
2052
+ const rationale = (0, intelligence_runtime_common_1.dedupeSorted)([
2053
+ ...baseline.rationale,
2054
+ infraTouched ? 'Infrastructure or CI surfaces were touched.' : '',
2055
+ dependencyManifestTouched ? 'Dependency manifests changed, widening blast radius.' : '',
2056
+ drift.impactedModules.length > baseline.modulesAffected.length
2057
+ ? `Repository graph expands module impact to ${drift.impactedModules.length} module(s).`
2058
+ : '',
2059
+ drift.impactedRuntimeFlows.length > 0
2060
+ ? `Runtime flow exposure now reaches ${summarizeValues(drift.impactedRuntimeFlows, 4)}.`
2061
+ : '',
2062
+ drift.affectedRolloutUnits.length > 0
2063
+ ? `Deployment spread reaches rollout unit(s) ${summarizeValues(drift.affectedRolloutUnits, 4)}.`
2064
+ : '',
2065
+ drift.riskSynthesis.externalSideEffectExposure
2066
+ ? 'External side effects are part of the changed runtime path.'
2067
+ : '',
2068
+ drift.riskSynthesis.stateOwnershipExposure
2069
+ ? 'State ownership or mutation now spans multiple runtime boundaries.'
2070
+ : '',
2071
+ drift.unexpectedServices.length > 0
2072
+ ? `Unexpected services impacted: ${drift.unexpectedServices.join(', ')}.`
2073
+ : '',
2074
+ drift.riskSynthesis.summary,
2075
+ ]);
2076
+ return {
2077
+ ...baseline,
2078
+ modulesAffected: (0, intelligence_runtime_common_1.dedupeSorted)([...baseline.modulesAffected, ...drift.impactedModules]),
2079
+ riskScore,
2080
+ rationale,
2081
+ affectedServices: drift.changedServices,
2082
+ impactedModules: drift.impactedModules,
2083
+ impactedServices: drift.impactedServices,
2084
+ infraTouched,
2085
+ authTouched,
2086
+ apiTouched,
2087
+ deploymentTouched,
2088
+ dependencyManifestTouched,
2089
+ rolloutComplexity: drift.rolloutRisk,
2090
+ transitiveImpactCount: Math.max(0, drift.impactedModules.length - drift.changedModules.length),
2091
+ affectedRuntimeFlows: drift.impactedRuntimeFlows,
2092
+ affectedRolloutUnits: drift.affectedRolloutUnits,
2093
+ cascadingRisk: drift.riskSynthesis.cascadingRisk,
2094
+ stateOwnershipExposure: drift.riskSynthesis.stateOwnershipExposure,
2095
+ externalSideEffectExposure: drift.riskSynthesis.externalSideEffectExposure,
2096
+ contextSource: drift.source,
2097
+ };
2098
+ }
2099
+ //# sourceMappingURL=drift-intelligence.js.map