codehere 0.2.2 → 0.3.0-rc.2

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 (235) hide show
  1. package/README.md +88 -68
  2. package/dist/domain/entities/task.js +4 -4
  3. package/dist/error-handler.js +4 -9
  4. package/dist/index.js +253 -1219
  5. package/dist/infrastructure/config/product-context.js +7 -6
  6. package/dist/infrastructure/hooks/claude-sdk-hook.js +348 -72
  7. package/dist/infrastructure/observability/execution-tracer.js +11 -6
  8. package/dist/infrastructure/orchestration/agent-adapter.js +13 -0
  9. package/dist/infrastructure/orchestration/agent-installer.js +101 -0
  10. package/dist/infrastructure/orchestration/agents-config-seed.js +56 -0
  11. package/dist/infrastructure/orchestration/aider-adapter.js +319 -0
  12. package/dist/infrastructure/orchestration/artifacts-extractor.js +175 -0
  13. package/dist/infrastructure/orchestration/claude-code-adapter.js +352 -0
  14. package/dist/infrastructure/orchestration/codex-adapter.js +310 -0
  15. package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
  16. package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
  17. package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
  18. package/dist/infrastructure/orchestration/readiness.js +106 -0
  19. package/dist/infrastructure/orchestration/session-manager.js +272 -0
  20. package/dist/infrastructure/orchestration/session-persistence.js +109 -0
  21. package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
  22. package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
  23. package/dist/infrastructure/protocols/ui-page.js +1827 -0
  24. package/dist/infrastructure/security/file-collection.js +115 -0
  25. package/dist/infrastructure/security/trust-scorer.js +301 -56
  26. package/dist/infrastructure/storage/task-repository.js +8 -7
  27. package/dist/monitoring.js +9 -38
  28. package/dist/presentation/cli/commands/help-command.js +96 -139
  29. package/dist/presentation/cli/commands/hook-command.js +17 -24
  30. package/dist/presentation/cli/commands/report-command.js +59 -72
  31. package/dist/presentation/cli/commands/setup-command.js +4 -4
  32. package/dist/presentation/cli/commands/status-command.js +321 -30
  33. package/dist/presentation/cli/commands/trust-command.js +84 -72
  34. package/dist/presentation/cli/error-display.js +17 -21
  35. package/dist/ui.js +11 -11
  36. package/package.json +24 -62
  37. package/dist/agents/base.js +0 -101
  38. package/dist/agents/orchestrator-model-driven.js +0 -141
  39. package/dist/agents/react-orchestrator-agent.js +0 -54
  40. package/dist/application/agents/execution-agent.js +0 -508
  41. package/dist/application/agents/multi-agent-orchestrator.js +0 -295
  42. package/dist/application/agents/planning-agent.js +0 -433
  43. package/dist/application/agents/validation-agent.js +0 -317
  44. package/dist/application/architectures/plan-and-act.js +0 -242
  45. package/dist/application/index.js +0 -12
  46. package/dist/application/services/agent-factory.js +0 -28
  47. package/dist/application/services/dependency-container.js +0 -596
  48. package/dist/application/services/git-context-service.js +0 -83
  49. package/dist/application/services/intelligent-router.js +0 -934
  50. package/dist/application/services/tool-executor-service.js +0 -94
  51. package/dist/application/use-cases/ask-question-use-case.js +0 -338
  52. package/dist/application/use-cases/edit-file-use-case.js +0 -830
  53. package/dist/application/use-cases/explain-file-use-case.js +0 -50
  54. package/dist/application/use-cases/index-codebase-use-case.js +0 -113
  55. package/dist/application/use-cases/planning-use-case.js +0 -276
  56. package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
  57. package/dist/application/use-cases/reflexion-use-case.js +0 -30
  58. package/dist/application/workflows/deterministic-workflows.js +0 -189
  59. package/dist/ast-parser.js +0 -331
  60. package/dist/cache.js +0 -180
  61. package/dist/chat.js +0 -251
  62. package/dist/code-analysis.js +0 -327
  63. package/dist/context.js +0 -187
  64. package/dist/docs.js +0 -146
  65. package/dist/domain/entities/code-chunk.js +0 -6
  66. package/dist/domain/entities/decision.js +0 -9
  67. package/dist/domain/entities/edit.js +0 -6
  68. package/dist/domain/entities/knowledge-node.js +0 -9
  69. package/dist/domain/entities/knowledge-preservation.js +0 -10
  70. package/dist/domain/entities/memory.js +0 -6
  71. package/dist/domain/entities/pattern.js +0 -7
  72. package/dist/domain/entities/plan.js +0 -6
  73. package/dist/domain/entities/query.js +0 -6
  74. package/dist/domain/errors/embeddings-not-found-error.js +0 -13
  75. package/dist/domain/index.js +0 -19
  76. package/dist/domain/interfaces/ai-service.interface.js +0 -6
  77. package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
  78. package/dist/domain/interfaces/decision-repository.interface.js +0 -9
  79. package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
  80. package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
  81. package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
  82. package/dist/domain/interfaces/memory-repository.interface.js +0 -6
  83. package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
  84. package/dist/domain/interfaces/verification-service.interface.js +0 -6
  85. package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
  86. package/dist/domain/services/decision-recorder.js +0 -223
  87. package/dist/domain/services/decision-retriever.js +0 -133
  88. package/dist/domain/services/environment-mode-manager.js +0 -22
  89. package/dist/domain/services/graded-memory-activation.js +0 -69
  90. package/dist/domain/services/knowledge-access.js +0 -132
  91. package/dist/domain/services/knowledge-extractor.js +0 -247
  92. package/dist/domain/services/knowledge-graph-builder.js +0 -268
  93. package/dist/domain/services/knowledge-graph-query.js +0 -187
  94. package/dist/domain/services/memory-retriever.js +0 -82
  95. package/dist/domain/services/memory-synthesizer.js +0 -91
  96. package/dist/domain/services/pattern-extractor.js +0 -442
  97. package/dist/domain/services/query-intent-classifier.js +0 -140
  98. package/dist/domain/services/react-loop.js +0 -186
  99. package/dist/domain/services/risk-tier-detector.js +0 -78
  100. package/dist/edit.js +0 -319
  101. package/dist/embed.js +0 -459
  102. package/dist/formatter.js +0 -168
  103. package/dist/git.js +0 -198
  104. package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
  105. package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
  106. package/dist/infrastructure/ai/model-config.js +0 -84
  107. package/dist/infrastructure/ai/provider-ai-service.js +0 -477
  108. package/dist/infrastructure/cache/embedding-cache.js +0 -175
  109. package/dist/infrastructure/cache/query-result-cache.js +0 -66
  110. package/dist/infrastructure/cache/response-cache.js +0 -48
  111. package/dist/infrastructure/cache/security-scan-cache.js +0 -47
  112. package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
  113. package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
  114. package/dist/infrastructure/context/context-compressor.js +0 -329
  115. package/dist/infrastructure/context/conversation-context.js +0 -128
  116. package/dist/infrastructure/context/session-manager.js +0 -94
  117. package/dist/infrastructure/cost/cost-tracker.js +0 -360
  118. package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
  119. package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
  120. package/dist/infrastructure/governance/policy-as-code.js +0 -258
  121. package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
  122. package/dist/infrastructure/index.js +0 -7
  123. package/dist/infrastructure/observability/prompt-versioner.js +0 -145
  124. package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
  125. package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
  126. package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
  127. package/dist/infrastructure/protocols/mcp-server.js +0 -333
  128. package/dist/infrastructure/protocols/streaming-handler.js +0 -103
  129. package/dist/infrastructure/providers/cohere-provider.js +0 -444
  130. package/dist/infrastructure/providers/fake-provider.js +0 -130
  131. package/dist/infrastructure/providers/local-llm-provider.js +0 -330
  132. package/dist/infrastructure/providers/model-config.types.js +0 -9
  133. package/dist/infrastructure/providers/model-provider.interface.js +0 -8
  134. package/dist/infrastructure/providers/openai-provider.js +0 -413
  135. package/dist/infrastructure/providers/openrouter-provider.js +0 -399
  136. package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
  137. package/dist/infrastructure/providers/provider-config-loader.js +0 -120
  138. package/dist/infrastructure/providers/provider-registry.js +0 -88
  139. package/dist/infrastructure/safety/pattern-detector.js +0 -133
  140. package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
  141. package/dist/infrastructure/security/docker-sandbox.js +0 -178
  142. package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
  143. package/dist/infrastructure/security/license-scanner.js +0 -167
  144. package/dist/infrastructure/security/provider-bias-detector.js +0 -164
  145. package/dist/infrastructure/security/sandbox-executor.js +0 -64
  146. package/dist/infrastructure/serialization/toon-serializer.js +0 -119
  147. package/dist/infrastructure/storage/memory-stream-service.js +0 -204
  148. package/dist/infrastructure/storage/plan-repository.js +0 -96
  149. package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
  150. package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
  151. package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
  152. package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
  153. package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
  154. package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
  155. package/dist/infrastructure/storage/task-helpers.js +0 -197
  156. package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
  157. package/dist/infrastructure/ux/appropriate-friction.js +0 -213
  158. package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
  159. package/dist/infrastructure/ux/capability-boundaries.js +0 -42
  160. package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
  161. package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
  162. package/dist/infrastructure/ux/expectation-management.js +0 -327
  163. package/dist/infrastructure/ux/feature-discovery.js +0 -14
  164. package/dist/infrastructure/ux/feedback-prompt.js +0 -45
  165. package/dist/infrastructure/ux/hitl-validation.js +0 -297
  166. package/dist/infrastructure/ux/progress-indicator.js +0 -116
  167. package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
  168. package/dist/infrastructure/ux/review-checkpoint.js +0 -72
  169. package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
  170. package/dist/infrastructure/ux/stream-markdown.js +0 -151
  171. package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
  172. package/dist/infrastructure/ux/team-standards.js +0 -196
  173. package/dist/infrastructure/ux/transparency.js +0 -71
  174. package/dist/infrastructure/validation/agent-feedback.js +0 -55
  175. package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
  176. package/dist/infrastructure/validation/review-handler.js +0 -40
  177. package/dist/infrastructure/validation/summary-aggregator.js +0 -70
  178. package/dist/infrastructure/validation/summary-extractor.js +0 -45
  179. package/dist/infrastructure/validation/trace-summary.js +0 -52
  180. package/dist/infrastructure/verification/verification-service.js +0 -47
  181. package/dist/infrastructure/xai/attention-visualizer.js +0 -172
  182. package/dist/infrastructure/xai/cot-visualizer.js +0 -283
  183. package/dist/infrastructure/xai/decision-tree-log.js +0 -212
  184. package/dist/infrastructure/xai/interactive-xai.js +0 -260
  185. package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
  186. package/dist/intelligent-retrieval.js +0 -272
  187. package/dist/intent/classifier.js +0 -2
  188. package/dist/intent/context.js +0 -2
  189. package/dist/iterative-refinement.js +0 -189
  190. package/dist/learning.js +0 -232
  191. package/dist/log.js +0 -31
  192. package/dist/migrate.js +0 -133
  193. package/dist/parallel-processor.js +0 -534
  194. package/dist/planner.js +0 -198
  195. package/dist/policy.js +0 -26
  196. package/dist/presentation/cli/commands/ask-command.js +0 -314
  197. package/dist/presentation/cli/commands/cost-command.js +0 -191
  198. package/dist/presentation/cli/commands/decision-command.js +0 -207
  199. package/dist/presentation/cli/commands/docs-command.js +0 -25
  200. package/dist/presentation/cli/commands/fix-command.js +0 -53
  201. package/dist/presentation/cli/commands/knowledge-command.js +0 -129
  202. package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
  203. package/dist/presentation/cli/commands/models-command.js +0 -194
  204. package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
  205. package/dist/presentation/cli/commands/plan-command.js +0 -246
  206. package/dist/presentation/cli/commands/product-command.js +0 -199
  207. package/dist/presentation/cli/commands/react-command.js +0 -181
  208. package/dist/presentation/cli/commands/review-command.js +0 -154
  209. package/dist/presentation/cli/commands/run-command.js +0 -188
  210. package/dist/presentation/cli/commands/smart-command.js +0 -395
  211. package/dist/presentation/cli/commands/suggest-command.js +0 -138
  212. package/dist/presentation/cli/commands/trace-command.js +0 -129
  213. package/dist/presentation/cli/commands/undo-command.js +0 -150
  214. package/dist/query-optimizer.js +0 -205
  215. package/dist/refactor.js +0 -116
  216. package/dist/review.js +0 -206
  217. package/dist/search.js +0 -163
  218. package/dist/session.js +0 -704
  219. package/dist/task-verification.js +0 -336
  220. package/dist/testgen.js +0 -166
  221. package/dist/token-optimizer.js +0 -277
  222. package/dist/tools/bash.js +0 -213
  223. package/dist/tools/edit.js +0 -235
  224. package/dist/tools/executor.js +0 -153
  225. package/dist/tools/git-tool.js +0 -292
  226. package/dist/tools/parser.js +0 -158
  227. package/dist/tools/registry.js +0 -302
  228. package/dist/tools/search.js +0 -100
  229. package/dist/types.js +0 -2
  230. package/dist/utils/check-api-status.js +0 -100
  231. package/dist/utils/diff-parser.js +0 -162
  232. package/dist/verification/backup.js +0 -259
  233. package/dist/verification/compiler.js +0 -264
  234. package/dist/verification/index.js +0 -273
  235. package/dist/verification/test-runner.js +0 -379
@@ -1,830 +0,0 @@
1
- /**
2
- * Application Use Case: EditFileUseCase
3
- * Handles file editing with verification and Reflexion
4
- */
5
- const DEBUG = process.env.CODEHERE_DEBUG === '1';
6
- import { container } from '../services/dependency-container.js';
7
- import { backupFile, rollbackFile } from '../../verification/backup.js';
8
- import { executionTracer } from '../../infrastructure/observability/execution-tracer.js';
9
- import { validateFilePath } from '../../infrastructure/security/input-validator.js';
10
- export class EditFileUseCase {
11
- aiService;
12
- verificationService;
13
- sastScanner;
14
- enhancedSecurityGate;
15
- appropriateFriction;
16
- hitlValidation;
17
- biDirectionalLearning;
18
- teamStandards;
19
- promptToCodeLineage;
20
- nistAIRMF;
21
- policyAsCode;
22
- constructor(aiService, verificationService, sastScanner, // Optional: AI SAST scanner (legacy, prefer enhancedSecurityGate)
23
- enhancedSecurityGate, // Optional: Enhanced security gate (all scanners)
24
- appropriateFriction, // Optional: Appropriate friction system
25
- hitlValidation, // Optional: HITL validation system
26
- biDirectionalLearning, // Optional: Bi-directional learning system
27
- teamStandards, // Optional: Team standards system
28
- promptToCodeLineage, // Optional: Prompt-to-code lineage tracking
29
- nistAIRMF, // Optional: NIST AI RMF for enterprise governance
30
- policyAsCode // Optional: Policy-as-Code for automated compliance
31
- ) {
32
- this.aiService = aiService;
33
- this.verificationService = verificationService;
34
- this.sastScanner = sastScanner;
35
- this.enhancedSecurityGate = enhancedSecurityGate;
36
- this.appropriateFriction = appropriateFriction;
37
- this.hitlValidation = hitlValidation;
38
- this.biDirectionalLearning = biDirectionalLearning;
39
- this.teamStandards = teamStandards;
40
- this.promptToCodeLineage = promptToCodeLineage;
41
- this.nistAIRMF = nistAIRMF;
42
- this.policyAsCode = policyAsCode;
43
- }
44
- async execute(request) {
45
- // 1. Start Prompt-to-Code Lineage tracking
46
- let lineageId;
47
- let rootNodeId;
48
- if (this.promptToCodeLineage) {
49
- const runId = executionTracer.getCurrentRunId();
50
- if (runId) {
51
- lineageId = this.promptToCodeLineage.createLineage(request.instruction, {
52
- sessionId: runId,
53
- workspace: process.cwd(),
54
- });
55
- const lineage = lineageId ? this.promptToCodeLineage.getLineage(lineageId) : undefined;
56
- rootNodeId = lineage?.rootNodeId;
57
- }
58
- else {
59
- // No run context - create lineage without sessionId
60
- lineageId = this.promptToCodeLineage.createLineage(request.instruction);
61
- const lineage = lineageId ? this.promptToCodeLineage.getLineage(lineageId) : undefined;
62
- rootNodeId = lineage?.rootNodeId;
63
- }
64
- }
65
- // Validate file path
66
- const pathValidation = validateFilePath(request.filepath);
67
- if (!pathValidation.valid) {
68
- return {
69
- success: false,
70
- error: `Invalid file path: ${pathValidation.errors.join(', ')}`,
71
- };
72
- }
73
- // NIST AI RMF: GOVERN - Establish risk culture and accountability (Enterprise Governance)
74
- if (this.nistAIRMF) {
75
- // Check if file exists for context type (quick check)
76
- const { existsSync } = await import('fs');
77
- const { join } = await import('path');
78
- const safeFilePath = pathValidation.sanitized || request.filepath;
79
- const fullPath = join(process.cwd(), safeFilePath);
80
- const fileExists = existsSync(fullPath);
81
- const riskContext = {
82
- contextType: fileExists ? 'code_edit' : 'code_generation',
83
- targetDomain: this.inferDomain(request.filepath, request.instruction),
84
- riskLevel: this.determineRiskLevel(request.instruction, ''),
85
- regulatoryRelevant: this.isRegulatoryRelevant(request.filepath, request.instruction),
86
- };
87
- const governDecision = await this.nistAIRMF.govern(riskContext);
88
- if (DEBUG)
89
- console.log(`[EditFileUseCase] NIST AI RMF Govern: ${governDecision.decision}`);
90
- if (governDecision.outcome === 'blocked') {
91
- return {
92
- success: false,
93
- error: `Operation blocked by governance policy: ${governDecision.rationale}`,
94
- };
95
- }
96
- if (governDecision.outcome === 'requires_review') {
97
- if (DEBUG)
98
- console.warn(`[EditFileUseCase] ⚠️ Governance requires review: ${governDecision.rationale}`);
99
- }
100
- }
101
- // NOTE: We do NOT scan the instruction text itself for security patterns.
102
- // The instruction is a human request like "fix the SQL injection" — scanning it
103
- // would block legitimate fix requests. Security scanning happens on the GENERATED
104
- // code output, not on what the user asked for.
105
- const { readFileSync, writeFileSync, existsSync, mkdirSync } = await import('fs');
106
- const { join, dirname } = await import('path');
107
- // Use sanitized path if validation found issues
108
- const safeFilePath = pathValidation.sanitized || request.filepath;
109
- const fullPath = join(process.cwd(), safeFilePath);
110
- const fileExists = existsSync(fullPath);
111
- // Determine risk level for friction/HITL
112
- const riskLevel = this.determineRiskLevel(request.instruction, fileExists ? '' : '');
113
- // 2. Check Appropriate Friction (after security check, before edit generation)
114
- let frictionApplied = null;
115
- if (this.appropriateFriction) {
116
- const frictionPoint = this.appropriateFriction.needsFriction('edit_file', {
117
- riskLevel,
118
- isDestructive: !fileExists || request.instruction.toLowerCase().includes('delete'),
119
- modifiesSecuritySensitiveCode: request.instruction.toLowerCase().includes('security') ||
120
- request.instruction.toLowerCase().includes('auth') ||
121
- request.instruction.toLowerCase().includes('password'),
122
- });
123
- if (frictionPoint) {
124
- frictionApplied = frictionPoint;
125
- if (DEBUG)
126
- console.log(`[EditFileUseCase] ⚠️ Friction applied: ${frictionPoint.message}`);
127
- // For CLI: Log warning. For UI: This would pause and wait for user interaction
128
- if (frictionPoint.requiresExplicitConfirmation) {
129
- // In CLI, we'll allow it but log the warning
130
- // In UI, this would block until user confirms
131
- if (DEBUG)
132
- console.warn(`[EditFileUseCase] Explicit confirmation required: ${frictionPoint.message}`);
133
- }
134
- }
135
- }
136
- // Handle file creation if file doesn't exist
137
- if (!fileExists) {
138
- if (DEBUG)
139
- console.log(`[EditFileUseCase] File does not exist, creating new file: ${fullPath}`);
140
- if (DEBUG)
141
- console.log(`[EditFileUseCase] Instruction: ${request.instruction}`);
142
- return await this.createFile(request, fullPath);
143
- }
144
- if (DEBUG)
145
- console.log(`[EditFileUseCase] Editing existing file: ${fullPath}`);
146
- if (DEBUG)
147
- console.log(`[EditFileUseCase] Instruction: ${request.instruction}`);
148
- // Read current content
149
- const currentContent = readFileSync(fullPath, 'utf-8');
150
- if (DEBUG)
151
- console.log(`[EditFileUseCase] File size: ${currentContent.length} chars`);
152
- // Update risk level with file context
153
- const updatedRiskLevel = this.determineRiskLevel(request.instruction, currentContent);
154
- // 3. Check HITL Validation requirement
155
- let hitlRequired = false;
156
- let hitlCheckpointId;
157
- if (this.hitlValidation && this.hitlValidation.requiresValidation({
158
- riskLevel: updatedRiskLevel,
159
- isDestructive: request.instruction.toLowerCase().includes('delete'),
160
- modifiesSecuritySensitiveCode: request.instruction.toLowerCase().includes('security') ||
161
- request.instruction.toLowerCase().includes('auth') ||
162
- request.instruction.toLowerCase().includes('password'),
163
- })) {
164
- hitlRequired = true;
165
- // Note: In CLI, we proceed with warning. In UI, this would block until approval
166
- if (DEBUG)
167
- console.warn(`[EditFileUseCase] ⚠️ HITL validation required for this operation`);
168
- }
169
- // Track edit generation in lineage
170
- if (this.promptToCodeLineage && lineageId && rootNodeId) {
171
- this.promptToCodeLineage.addNode(lineageId, {
172
- type: 'plan',
173
- timestamp: Date.now(),
174
- description: `Generating edit for ${request.filepath}`,
175
- input: { instruction: request.instruction, filepath: request.filepath },
176
- metadata: { riskLevel: updatedRiskLevel },
177
- }, rootNodeId);
178
- }
179
- // Generate edit (with progress indicator for better UX)
180
- let diff;
181
- try {
182
- // Show progress indicator for code generation (can take 20-30s)
183
- const { createSpinner } = await import('../../ui.js');
184
- const codeGenSpinner = createSpinner('Generating code changes...');
185
- codeGenSpinner.start();
186
- // Task 6.2: Include learned patterns and preferences in code generation
187
- let enhancedInstruction = request.instruction;
188
- if (this.biDirectionalLearning) {
189
- const userId = process.env.USER || 'default-user';
190
- const patternsContext = this.biDirectionalLearning.getPatternsAsPromptContext(userId, 3);
191
- const preferencesContext = this.biDirectionalLearning.getPreferencesAsPromptContext(userId);
192
- if (patternsContext || preferencesContext) {
193
- const contextParts = [];
194
- if (preferencesContext)
195
- contextParts.push(preferencesContext);
196
- if (patternsContext)
197
- contextParts.push(patternsContext);
198
- enhancedInstruction = `${request.instruction}\n\n${contextParts.join('\n\n')}`;
199
- }
200
- }
201
- diff = await this.aiService.generateEdit(currentContent, enhancedInstruction, request.filepath);
202
- codeGenSpinner.stop();
203
- if (DEBUG)
204
- console.log(`[EditFileUseCase] Generated diff length: ${diff.length} chars`);
205
- if (diff.length > 0) {
206
- if (DEBUG)
207
- console.log(`[EditFileUseCase] Diff preview: ${diff.substring(0, 200)}...`);
208
- }
209
- else {
210
- if (DEBUG)
211
- console.warn(`[EditFileUseCase] Warning: Empty diff generated`);
212
- }
213
- }
214
- catch (error) {
215
- if (DEBUG)
216
- console.error(`[EditFileUseCase] Failed to generate edit:`, error);
217
- return {
218
- success: false,
219
- error: `Failed to generate edit: ${error instanceof Error ? error.message : String(error)}`,
220
- };
221
- }
222
- // Apply diff
223
- let newContent;
224
- try {
225
- newContent = await this.applyDiff(currentContent, diff);
226
- if (DEBUG)
227
- console.log(`[EditFileUseCase] Applied diff, new content size: ${newContent.length} chars`);
228
- // Check if content actually changed
229
- if (newContent === currentContent) {
230
- if (DEBUG)
231
- console.warn(`[EditFileUseCase] Warning: Content unchanged after applying diff`);
232
- }
233
- else {
234
- const diffSize = newContent.length - currentContent.length;
235
- if (DEBUG)
236
- console.log(`[EditFileUseCase] Content changed: ${diffSize > 0 ? '+' : ''}${diffSize} chars difference`);
237
- }
238
- }
239
- catch (error) {
240
- if (DEBUG)
241
- console.error(`[EditFileUseCase] Failed to apply diff:`, error);
242
- return {
243
- success: false,
244
- error: `Failed to apply diff: ${error instanceof Error ? error.message : String(error)}`,
245
- };
246
- }
247
- // Security scan: compare BEFORE vs AFTER to detect NEW issues only.
248
- // We don't block edits for pre-existing vulnerabilities — that would prevent
249
- // users from fixing files that already have issues (the whole point of `codehere fix`).
250
- let securityResult = null;
251
- if (this.enhancedSecurityGate) {
252
- const { createSpinner } = await import('../../ui.js');
253
- const securitySpinner = createSpinner('Scanning for security vulnerabilities...');
254
- securitySpinner.start();
255
- // Scan the NEW content
256
- securityResult = await this.enhancedSecurityGate.scan(request.filepath, newContent, request.instruction, { query: request.instruction });
257
- // If the new content has issues, check if they're NEW or pre-existing
258
- if (!securityResult.passed && fileExists) {
259
- const originalContent = readFileSync(fullPath, 'utf-8');
260
- const originalResult = await this.enhancedSecurityGate.scan(request.filepath, originalContent, '', {});
261
- // Count findings: only block if the edit ADDED new vulnerabilities
262
- const originalCount = (originalResult.sast?.findings?.length || 0);
263
- const newCount = (securityResult.sast?.findings?.length || 0);
264
- if (newCount <= originalCount) {
265
- // Edit didn't make things worse — allow it, but warn
266
- securityResult.passed = true;
267
- if (newCount > 0) {
268
- securityResult.warnings = securityResult.warnings || [];
269
- securityResult.warnings.push(`File has ${newCount} pre-existing security finding(s). Consider fixing them too.`);
270
- }
271
- }
272
- }
273
- securitySpinner.stop();
274
- if (!securityResult.passed) {
275
- const errorMessages = [
276
- ...securityResult.errors,
277
- ...securityResult.warnings.map((w) => `Warning: ${w}`),
278
- ];
279
- return {
280
- success: false,
281
- error: `Edit would introduce new security vulnerabilities: ${errorMessages.join('; ')}`,
282
- securityFindings: securityResult.sast.findings,
283
- licenseFindings: securityResult.license.findings,
284
- providerBiasFindings: securityResult.providerBias.findings,
285
- uncertaintyFindings: securityResult.uncertainty,
286
- };
287
- }
288
- if (securityResult.warnings && securityResult.warnings.length > 0) {
289
- if (DEBUG)
290
- console.warn(`[EditFileUseCase] Security warnings: ${securityResult.warnings.join('; ')}`);
291
- }
292
- // NIST AI RMF: MAP - Context framing and risk identification (Enterprise Governance)
293
- if (this.nistAIRMF) {
294
- const riskContext = {
295
- contextType: fileExists ? 'code_edit' : 'code_generation',
296
- targetDomain: this.inferDomain(request.filepath, request.instruction),
297
- riskLevel: this.determineRiskLevel(request.instruction, newContent),
298
- regulatoryRelevant: this.isRegulatoryRelevant(request.filepath, request.instruction),
299
- };
300
- const { decision: mapDecision, riskProfile } = await this.nistAIRMF.map(riskContext, {
301
- security: {
302
- vulnerabilities: securityResult.sast.findings?.length || 0,
303
- licenseConflicts: securityResult.license.findings?.length || 0,
304
- providerBias: (securityResult.providerBias.findings?.length || 0) > 0,
305
- uncertainty: securityResult.uncertainty?.combined?.value || 0.5,
306
- },
307
- compliance: {
308
- gdprRelevant: riskContext.regulatoryRelevant,
309
- hipaaRelevant: this.inferDomain(request.filepath, request.instruction) === 'healthcare',
310
- },
311
- operational: {
312
- complexity: newContent.length > 1000 ? 0.8 : 0.5,
313
- dependencies: 0, // Could be enhanced
314
- },
315
- });
316
- if (DEBUG)
317
- console.log(`[EditFileUseCase] NIST AI RMF Map: ${mapDecision.decision}`);
318
- if (mapDecision.outcome === 'blocked') {
319
- return {
320
- success: false,
321
- error: `Operation blocked by risk mapping: ${mapDecision.rationale}`,
322
- securityFindings: securityResult.sast.findings,
323
- licenseFindings: securityResult.license.findings,
324
- providerBiasFindings: securityResult.providerBias.findings,
325
- uncertaintyFindings: securityResult.uncertainty,
326
- };
327
- }
328
- // NIST AI RMF: MEASURE - Quantify and monitor risks (Enterprise Governance)
329
- const measureDecision = await this.nistAIRMF.measure(riskProfile, {
330
- sastFindings: securityResult.sast.findings?.length || 0,
331
- licenseFindings: securityResult.license.findings?.length || 0,
332
- providerBiasFindings: securityResult.providerBias.findings?.length || 0,
333
- uncertaintyScore: securityResult.uncertainty?.combined?.value,
334
- });
335
- if (DEBUG)
336
- console.log(`[EditFileUseCase] NIST AI RMF Measure: ${measureDecision.decision}`);
337
- }
338
- // Policy-as-Code: Evaluate policies before proceeding (Enterprise Governance)
339
- // Skip policy check if the security gate already approved (edit didn't introduce new issues)
340
- if (this.policyAsCode && securityResult && !securityResult.passed) {
341
- // Debug: Log security findings before policy evaluation
342
- const criticalHighFindings = securityResult.sast.findings.filter((f) => f.severity === 'critical' || f.severity === 'high');
343
- if (DEBUG)
344
- console.log(`[EditFileUseCase] Security scan: ${securityResult.sast.findings.length} total findings, ${criticalHighFindings.length} critical/high`);
345
- if (criticalHighFindings.length > 0) {
346
- if (DEBUG)
347
- console.log(`[EditFileUseCase] Critical/High findings:`, criticalHighFindings.map((f) => `${f.severity}: ${f.category} - ${f.description}`).join('; '));
348
- }
349
- const policyEvaluation = await this.policyAsCode.evaluate({
350
- filepath: request.filepath,
351
- code: newContent,
352
- instruction: request.instruction,
353
- securityFindings: securityResult.sast.findings,
354
- licenseFindings: securityResult.license.findings,
355
- providerBiasFindings: securityResult.providerBias.findings,
356
- uncertainty: securityResult.uncertainty,
357
- });
358
- // Debug: Log policy evaluation results
359
- if (DEBUG)
360
- console.log(`[EditFileUseCase] Policy evaluation: ${policyEvaluation.results.length} rules evaluated, ${policyEvaluation.blockingRules.length} blocking`);
361
- policyEvaluation.results.forEach((result) => {
362
- if (!result.passed) {
363
- if (DEBUG)
364
- console.log(`[EditFileUseCase] Policy rule "${result.ruleName}": ${result.message}`);
365
- if (result.evidence) {
366
- if (DEBUG)
367
- console.log(`[EditFileUseCase] Evidence:`, JSON.stringify(result.evidence, null, 2));
368
- }
369
- }
370
- });
371
- if (!policyEvaluation.passed && policyEvaluation.blockingRules.length > 0) {
372
- const blockingRule = policyEvaluation.blockingRules[0];
373
- if (DEBUG)
374
- console.error(`[EditFileUseCase] Policy violation: ${blockingRule.ruleName} - ${blockingRule.message}`);
375
- return {
376
- success: false,
377
- error: `Policy violation: ${blockingRule.message}`,
378
- securityFindings: securityResult.sast.findings,
379
- licenseFindings: securityResult.license.findings,
380
- providerBiasFindings: securityResult.providerBias.findings,
381
- uncertaintyFindings: securityResult.uncertainty,
382
- };
383
- }
384
- if (policyEvaluation.results.length > 0) {
385
- if (DEBUG)
386
- console.log(`[EditFileUseCase] Policy evaluation: ${policyEvaluation.results.filter(r => r.passed).length}/${policyEvaluation.results.length} passed`);
387
- }
388
- }
389
- // Track security scan in lineage
390
- if (this.promptToCodeLineage && lineageId && rootNodeId) {
391
- this.promptToCodeLineage.addNode(lineageId, {
392
- type: 'verification',
393
- timestamp: Date.now(),
394
- description: 'Security scan completed',
395
- input: { filepath: request.filepath },
396
- output: { passed: securityResult.passed, findings: securityResult.errors.length },
397
- metadata: {
398
- securityScan: true,
399
- licenseIssues: securityResult.license.findings?.length || 0,
400
- providerBiasIssues: securityResult.providerBias.findings?.length || 0,
401
- },
402
- }, rootNodeId);
403
- }
404
- }
405
- else if (this.sastScanner) {
406
- // SAST-only scan: compare before vs after to only block NEW issues
407
- const securityCheck = await this.sastScanner.scan(request.filepath, newContent);
408
- const newFindings = securityCheck.findings || [];
409
- if (newFindings.length > 0 && fileExists) {
410
- const originalContent = readFileSync(fullPath, 'utf-8');
411
- const originalCheck = await this.sastScanner.scan(request.filepath, originalContent);
412
- const originalCount = originalCheck.findings?.length || 0;
413
- // Only block if the edit ADDED new vulnerabilities
414
- if (newFindings.length > originalCount) {
415
- const criticalFindings = newFindings.filter(f => f.severity === 'critical');
416
- const highFindings = newFindings.filter(f => f.severity === 'high');
417
- if (criticalFindings.length > 0 || highFindings.length > 0) {
418
- return {
419
- success: false,
420
- error: `Edit would introduce new security vulnerabilities: ${criticalFindings.length} critical, ${highFindings.length} high severity findings.`,
421
- securityFindings: newFindings,
422
- };
423
- }
424
- }
425
- }
426
- else if (newFindings.length > 0 && !fileExists) {
427
- // New file — block if it has critical/high issues
428
- const criticalFindings = newFindings.filter(f => f.severity === 'critical');
429
- const highFindings = newFindings.filter(f => f.severity === 'high');
430
- if (criticalFindings.length > 0 || highFindings.length > 0) {
431
- return {
432
- success: false,
433
- error: `Security vulnerabilities detected in new file: ${criticalFindings.length} critical, ${highFindings.length} high severity findings.`,
434
- securityFindings: newFindings,
435
- };
436
- }
437
- }
438
- }
439
- // Create backup before applying edit
440
- let backupPath;
441
- try {
442
- backupPath = await backupFile(fullPath);
443
- if (DEBUG)
444
- console.log(`[EditFileUseCase] Backup created: ${backupPath}`);
445
- // Link backup to current run for undo capability
446
- const runId = executionTracer.getCurrentRunId();
447
- if (runId) {
448
- executionTracer.trace({
449
- operationType: 'file_operation',
450
- operationName: 'backup',
451
- input: { filepath: fullPath },
452
- output: { backupPath },
453
- metadata: {
454
- runId,
455
- filepath: fullPath,
456
- },
457
- });
458
- }
459
- }
460
- catch (error) {
461
- if (DEBUG)
462
- console.warn(`[EditFileUseCase] Failed to create backup: ${error instanceof Error ? error.message : String(error)}`);
463
- // Continue anyway - backup failure shouldn't block edit
464
- }
465
- // 4. Team Standards Validation (before writing file)
466
- let teamStandardsApplied = false;
467
- if (this.teamStandards && newContent) {
468
- const teamId = 'default'; // TODO: Get from config or context
469
- const standardsResult = this.teamStandards.validateCode(teamId, newContent, request.filepath);
470
- if (!standardsResult.passed) {
471
- if (DEBUG)
472
- console.warn(`[EditFileUseCase] Team standards violations: ${standardsResult.violations.length}`);
473
- // Try auto-fix
474
- const fixedResult = this.teamStandards.applyStyleGuide(teamId, newContent, request.filepath);
475
- if (fixedResult.fixesApplied > 0) {
476
- newContent = fixedResult.modified;
477
- teamStandardsApplied = true;
478
- if (DEBUG)
479
- console.log(`[EditFileUseCase] Auto-fixed ${fixedResult.fixesApplied} style issues`);
480
- }
481
- else {
482
- // Critical violations that can't be auto-fixed
483
- const criticalViolations = standardsResult.issues.filter(i => i.severity === 'error');
484
- if (criticalViolations.length > 0) {
485
- return {
486
- success: false,
487
- error: `Team standards validation failed: ${criticalViolations.length} critical violations`,
488
- frictionApplied,
489
- hitlRequired,
490
- hitlCheckpointId,
491
- };
492
- }
493
- }
494
- }
495
- }
496
- // Review Checkpoint: Show summary before applying edits (Task 5.1)
497
- // Display review checkpoint with diff summary, security status, and risk level
498
- const { displayReviewCheckpoint, calculateDiffSummary } = await import('../../infrastructure/ux/review-checkpoint.js');
499
- const diffSummary = calculateDiffSummary(currentContent, newContent);
500
- // Determine risk level for review checkpoint
501
- let reviewRiskLevel = 'medium';
502
- if (securityResult) {
503
- if (securityResult.errors && securityResult.errors.length > 0) {
504
- reviewRiskLevel = 'critical';
505
- }
506
- else if (securityResult.warnings && securityResult.warnings.length > 0) {
507
- reviewRiskLevel = 'high';
508
- }
509
- else {
510
- reviewRiskLevel = 'low';
511
- }
512
- }
513
- const reviewInfo = {
514
- filesToModify: [{
515
- filepath: request.filepath,
516
- linesAdded: diffSummary.linesAdded,
517
- linesRemoved: diffSummary.linesRemoved,
518
- linesChanged: diffSummary.linesChanged,
519
- }],
520
- securityScanPassed: securityResult?.passed ?? true,
521
- compilationValid: true, // Will be verified after write
522
- riskLevel: reviewRiskLevel,
523
- uncertainty: securityResult?.uncertainty?.combined?.value,
524
- };
525
- displayReviewCheckpoint(reviewInfo);
526
- // Verify if verification service available
527
- let verification;
528
- if (this.verificationService) {
529
- if (DEBUG)
530
- console.log(`[EditFileUseCase] Writing file and verifying...`);
531
- writeFileSync(fullPath, newContent, 'utf-8');
532
- // Show progress indicator for verification (can take 5-10s)
533
- const { createSpinner } = await import('../../ui.js');
534
- const verificationSpinner = createSpinner('Verifying code compilation...');
535
- verificationSpinner.start();
536
- verification = await this.verificationService.verify(fullPath);
537
- if (verification.success) {
538
- verificationSpinner.succeed('Verification passed');
539
- }
540
- else {
541
- verificationSpinner.fail('Verification failed');
542
- }
543
- if (DEBUG)
544
- console.log(`[EditFileUseCase] Verification result: success=${verification.success}, compiled=${verification.compiled}, testsPassed=${verification.testsPassed}`);
545
- if (verification.errors && verification.errors.length > 0) {
546
- if (DEBUG)
547
- console.error(`[EditFileUseCase] Verification errors: ${verification.errors.join('; ')}`);
548
- }
549
- if (!verification.success) {
550
- if (DEBUG)
551
- console.warn(`[EditFileUseCase] Verification failed, rolling back...`);
552
- // Automatic rollback on verification failure
553
- if (backupPath) {
554
- try {
555
- await rollbackFile(fullPath, backupPath);
556
- if (DEBUG)
557
- console.log(`[EditFileUseCase] File rolled back successfully`);
558
- }
559
- catch (rollbackError) {
560
- if (DEBUG)
561
- console.error(`[EditFileUseCase] Rollback failed: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`);
562
- // Try to restore from original content as fallback
563
- try {
564
- writeFileSync(fullPath, currentContent, 'utf-8');
565
- if (DEBUG)
566
- console.log(`[EditFileUseCase] File restored from original content`);
567
- }
568
- catch (restoreError) {
569
- if (DEBUG)
570
- console.error(`[EditFileUseCase] Restore also failed: ${restoreError instanceof Error ? restoreError.message : String(restoreError)}`);
571
- }
572
- }
573
- }
574
- // Use Reflexion to learn from failure
575
- const reflexionUseCase = container.reflexionUseCase;
576
- const reflection = await reflexionUseCase.execute({
577
- trajectory: {
578
- query: request.instruction,
579
- steps: [{
580
- thought: { content: 'Attempting edit', reasoning: request.instruction },
581
- action: { type: 'tool', name: 'edit', parameters: {} },
582
- observation: { result: null, success: false, error: verification.errors.join('; ') },
583
- timestamp: new Date(),
584
- }],
585
- success: false,
586
- },
587
- reward: 0,
588
- errors: verification.errors,
589
- });
590
- return {
591
- success: false,
592
- verification,
593
- reflection: reflection.reflection,
594
- error: verification.errors.join('; '),
595
- };
596
- }
597
- }
598
- else {
599
- // No verification - just apply (still create backup for undo capability)
600
- if (DEBUG)
601
- console.log(`[EditFileUseCase] No verification service, writing file directly`);
602
- writeFileSync(fullPath, newContent, 'utf-8');
603
- }
604
- const edit = {
605
- filepath: request.filepath,
606
- oldContent: currentContent,
607
- newContent,
608
- instruction: request.instruction,
609
- diff,
610
- metadata: {
611
- verificationResult: verification,
612
- },
613
- };
614
- // 5. Record Bi-directional Learning
615
- if (this.biDirectionalLearning) {
616
- const userId = 'default'; // TODO: Get from context
617
- this.biDirectionalLearning.recordFeedback(userId, {
618
- type: 'edit',
619
- signal: 'positive', // Successful edit = positive signal
620
- originalCode: currentContent,
621
- modifiedCode: newContent,
622
- filepath: request.filepath,
623
- context: {
624
- query: request.instruction,
625
- generatedBy: 'EditFileUseCase',
626
- },
627
- });
628
- if (DEBUG)
629
- console.log(`[EditFileUseCase] Edit recorded for learning`);
630
- }
631
- // 6. Complete Prompt-to-Code Lineage tracking
632
- if (this.promptToCodeLineage && lineageId && rootNodeId) {
633
- this.promptToCodeLineage.trackCodeGeneration(lineageId, rootNodeId, {
634
- filepath: request.filepath,
635
- content: newContent,
636
- diff: diff,
637
- originalContent: currentContent,
638
- }, {
639
- verificationPassed: verification?.success || false,
640
- });
641
- if (DEBUG)
642
- console.log(`[EditFileUseCase] Lineage tracking complete`);
643
- }
644
- if (DEBUG)
645
- console.log(`[EditFileUseCase] Edit completed successfully`);
646
- return {
647
- success: true,
648
- edit,
649
- verification,
650
- frictionApplied,
651
- hitlRequired,
652
- hitlCheckpointId,
653
- };
654
- }
655
- /**
656
- * Create a new file with generated content
657
- */
658
- async createFile(request, fullPath) {
659
- const { writeFileSync, mkdirSync, existsSync } = await import('fs');
660
- const { dirname } = await import('path');
661
- try {
662
- // Ensure directory exists
663
- const dir = dirname(fullPath);
664
- if (!existsSync(dir)) {
665
- if (DEBUG)
666
- console.log(`[EditFileUseCase] Creating directory: ${dir}`);
667
- mkdirSync(dir, { recursive: true });
668
- }
669
- // Generate file content using AI
670
- if (DEBUG)
671
- console.log(`[EditFileUseCase] Generating new file content...`);
672
- let fileContent;
673
- try {
674
- fileContent = await this.aiService.generateFileContent(request.filepath, request.instruction, request.requirements || []);
675
- if (DEBUG)
676
- console.log(`[EditFileUseCase] Generated content length: ${fileContent.length} chars`);
677
- }
678
- catch (error) {
679
- if (DEBUG)
680
- console.error(`[EditFileUseCase] Failed to generate file content:`, error);
681
- return {
682
- success: false,
683
- error: `Failed to generate file content: ${error instanceof Error ? error.message : String(error)}`,
684
- };
685
- }
686
- // Security scan before writing
687
- if (this.sastScanner) {
688
- const securityCheck = await this.sastScanner.scan(request.filepath, fileContent);
689
- const criticalFindings = securityCheck.findings?.filter(f => f.severity === 'critical') || [];
690
- const highFindings = securityCheck.findings?.filter(f => f.severity === 'high') || [];
691
- if (criticalFindings.length > 0 || highFindings.length > 0) {
692
- return {
693
- success: false,
694
- error: `Security vulnerabilities detected: ${criticalFindings.length} critical, ${highFindings.length} high severity findings. Review and fix before creating.`,
695
- securityFindings: securityCheck.findings,
696
- };
697
- }
698
- }
699
- // Write file
700
- writeFileSync(fullPath, fileContent, 'utf-8');
701
- if (DEBUG)
702
- console.log(`[EditFileUseCase] File created successfully: ${fullPath}`);
703
- // Verify if verification service available
704
- let verification;
705
- if (this.verificationService) {
706
- if (DEBUG)
707
- console.log(`[EditFileUseCase] Verifying new file...`);
708
- verification = await this.verificationService.verify(fullPath);
709
- if (DEBUG)
710
- console.log(`[EditFileUseCase] Verification result: success=${verification.success}, compiled=${verification.compiled}, testsPassed=${verification.testsPassed}`);
711
- if (!verification.success) {
712
- if (DEBUG)
713
- console.warn(`[EditFileUseCase] Verification failed for new file, but keeping it for inspection`);
714
- return {
715
- success: false,
716
- verification,
717
- error: verification.errors?.join('; ') || 'Verification failed',
718
- };
719
- }
720
- }
721
- const edit = {
722
- filepath: request.filepath,
723
- oldContent: '', // No old content for new files
724
- newContent: fileContent,
725
- instruction: request.instruction,
726
- diff: `New file created: ${request.filepath}`,
727
- metadata: {
728
- verificationResult: verification,
729
- },
730
- };
731
- if (DEBUG)
732
- console.log(`[EditFileUseCase] File creation completed successfully`);
733
- return {
734
- success: true,
735
- edit,
736
- verification,
737
- };
738
- }
739
- catch (error) {
740
- if (DEBUG)
741
- console.error(`[EditFileUseCase] Failed to create file:`, error);
742
- return {
743
- success: false,
744
- error: `Failed to create file: ${error instanceof Error ? error.message : String(error)}`,
745
- };
746
- }
747
- }
748
- async applyDiff(content, diff) {
749
- try {
750
- const { applyEditFallback } = await import('../../utils/diff-parser.js');
751
- return applyEditFallback(content, diff);
752
- }
753
- catch (error) {
754
- console.error('Failed to apply diff:', error);
755
- // Fallback: if diff parsing fails, return original content
756
- // This prevents silent failures
757
- throw new Error(`Failed to apply diff: ${error instanceof Error ? error.message : String(error)}`);
758
- }
759
- }
760
- /**
761
- * Determine risk level based on instruction and content
762
- */
763
- determineRiskLevel(instruction, currentContent) {
764
- const instructionLower = instruction.toLowerCase();
765
- // Critical: Destructive operations
766
- if (instructionLower.includes('delete') ||
767
- instructionLower.includes('remove all') ||
768
- instructionLower.includes('drop table') ||
769
- instructionLower.includes('rm -rf')) {
770
- return 'critical';
771
- }
772
- // High: Security-sensitive operations
773
- if (instructionLower.includes('security') ||
774
- instructionLower.includes('auth') ||
775
- instructionLower.includes('password') ||
776
- instructionLower.includes('credential') ||
777
- instructionLower.includes('token') ||
778
- instructionLower.includes('api key')) {
779
- return 'high';
780
- }
781
- // High: Large file modifications
782
- if (currentContent.length > 5000 && instruction.split(' ').length > 30) {
783
- return 'high';
784
- }
785
- // Medium: Complex refactoring
786
- if (instructionLower.includes('refactor') ||
787
- instructionLower.includes('restructure') ||
788
- instructionLower.includes('rewrite')) {
789
- return 'medium';
790
- }
791
- // Low: Simple edits
792
- return 'low';
793
- }
794
- /**
795
- * Infer domain from filepath and instruction for NIST AI RMF
796
- */
797
- inferDomain(filepath, instruction) {
798
- const pathLower = filepath.toLowerCase();
799
- const instructionLower = instruction.toLowerCase();
800
- if (pathLower.includes('health') || instructionLower.includes('health')) {
801
- return 'healthcare';
802
- }
803
- if (pathLower.includes('finance') || pathLower.includes('payment') || instructionLower.includes('finance')) {
804
- return 'financial';
805
- }
806
- if (pathLower.includes('auth') || instructionLower.includes('authentication')) {
807
- return 'security';
808
- }
809
- return 'general';
810
- }
811
- /**
812
- * Determine if operation is regulatory relevant (GDPR, HIPAA, etc.)
813
- */
814
- isRegulatoryRelevant(filepath, instruction) {
815
- const pathLower = filepath.toLowerCase();
816
- const instructionLower = instruction.toLowerCase();
817
- // GDPR: Personal data processing
818
- if (pathLower.includes('user') || pathLower.includes('customer') ||
819
- instructionLower.includes('personal data') || instructionLower.includes('gdpr')) {
820
- return true;
821
- }
822
- // HIPAA: Healthcare data
823
- if (pathLower.includes('health') || instructionLower.includes('patient') ||
824
- instructionLower.includes('medical record')) {
825
- return true;
826
- }
827
- return false;
828
- }
829
- }
830
- //# sourceMappingURL=edit-file-use-case.js.map