codehere 0.2.2 → 0.3.0-rc.10

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 (238) 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 +261 -1224
  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/conductor-adapter.js +340 -0
  16. package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
  17. package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
  18. package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
  19. package/dist/infrastructure/orchestration/readiness.js +106 -0
  20. package/dist/infrastructure/orchestration/session-manager.js +278 -0
  21. package/dist/infrastructure/orchestration/session-persistence.js +109 -0
  22. package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
  23. package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
  24. package/dist/infrastructure/protocols/probe-port.js +36 -0
  25. package/dist/infrastructure/protocols/ui-page.js +1827 -0
  26. package/dist/infrastructure/security/file-collection.js +115 -0
  27. package/dist/infrastructure/security/trust-scorer.js +301 -56
  28. package/dist/infrastructure/storage/task-repository.js +8 -7
  29. package/dist/monitoring.js +9 -38
  30. package/dist/presentation/cli/commands/help-command.js +96 -139
  31. package/dist/presentation/cli/commands/hook-command.js +17 -24
  32. package/dist/presentation/cli/commands/report-command.js +59 -72
  33. package/dist/presentation/cli/commands/setup-command.js +4 -4
  34. package/dist/presentation/cli/commands/status-command.js +321 -30
  35. package/dist/presentation/cli/commands/trust-command.js +84 -72
  36. package/dist/presentation/cli/error-display.js +17 -21
  37. package/dist/presentation/cli/repl.js +474 -0
  38. package/dist/ui.js +11 -11
  39. package/package.json +24 -62
  40. package/dist/agents/base.js +0 -101
  41. package/dist/agents/orchestrator-model-driven.js +0 -141
  42. package/dist/agents/react-orchestrator-agent.js +0 -54
  43. package/dist/application/agents/execution-agent.js +0 -508
  44. package/dist/application/agents/multi-agent-orchestrator.js +0 -295
  45. package/dist/application/agents/planning-agent.js +0 -433
  46. package/dist/application/agents/validation-agent.js +0 -317
  47. package/dist/application/architectures/plan-and-act.js +0 -242
  48. package/dist/application/index.js +0 -12
  49. package/dist/application/services/agent-factory.js +0 -28
  50. package/dist/application/services/dependency-container.js +0 -596
  51. package/dist/application/services/git-context-service.js +0 -83
  52. package/dist/application/services/intelligent-router.js +0 -934
  53. package/dist/application/services/tool-executor-service.js +0 -94
  54. package/dist/application/use-cases/ask-question-use-case.js +0 -338
  55. package/dist/application/use-cases/edit-file-use-case.js +0 -830
  56. package/dist/application/use-cases/explain-file-use-case.js +0 -50
  57. package/dist/application/use-cases/index-codebase-use-case.js +0 -113
  58. package/dist/application/use-cases/planning-use-case.js +0 -276
  59. package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
  60. package/dist/application/use-cases/reflexion-use-case.js +0 -30
  61. package/dist/application/workflows/deterministic-workflows.js +0 -189
  62. package/dist/ast-parser.js +0 -331
  63. package/dist/cache.js +0 -180
  64. package/dist/chat.js +0 -251
  65. package/dist/code-analysis.js +0 -327
  66. package/dist/context.js +0 -187
  67. package/dist/docs.js +0 -146
  68. package/dist/domain/entities/code-chunk.js +0 -6
  69. package/dist/domain/entities/decision.js +0 -9
  70. package/dist/domain/entities/edit.js +0 -6
  71. package/dist/domain/entities/knowledge-node.js +0 -9
  72. package/dist/domain/entities/knowledge-preservation.js +0 -10
  73. package/dist/domain/entities/memory.js +0 -6
  74. package/dist/domain/entities/pattern.js +0 -7
  75. package/dist/domain/entities/plan.js +0 -6
  76. package/dist/domain/entities/query.js +0 -6
  77. package/dist/domain/errors/embeddings-not-found-error.js +0 -13
  78. package/dist/domain/index.js +0 -19
  79. package/dist/domain/interfaces/ai-service.interface.js +0 -6
  80. package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
  81. package/dist/domain/interfaces/decision-repository.interface.js +0 -9
  82. package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
  83. package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
  84. package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
  85. package/dist/domain/interfaces/memory-repository.interface.js +0 -6
  86. package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
  87. package/dist/domain/interfaces/verification-service.interface.js +0 -6
  88. package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
  89. package/dist/domain/services/decision-recorder.js +0 -223
  90. package/dist/domain/services/decision-retriever.js +0 -133
  91. package/dist/domain/services/environment-mode-manager.js +0 -22
  92. package/dist/domain/services/graded-memory-activation.js +0 -69
  93. package/dist/domain/services/knowledge-access.js +0 -132
  94. package/dist/domain/services/knowledge-extractor.js +0 -247
  95. package/dist/domain/services/knowledge-graph-builder.js +0 -268
  96. package/dist/domain/services/knowledge-graph-query.js +0 -187
  97. package/dist/domain/services/memory-retriever.js +0 -82
  98. package/dist/domain/services/memory-synthesizer.js +0 -91
  99. package/dist/domain/services/pattern-extractor.js +0 -442
  100. package/dist/domain/services/query-intent-classifier.js +0 -140
  101. package/dist/domain/services/react-loop.js +0 -186
  102. package/dist/domain/services/risk-tier-detector.js +0 -78
  103. package/dist/edit.js +0 -319
  104. package/dist/embed.js +0 -459
  105. package/dist/formatter.js +0 -168
  106. package/dist/git.js +0 -198
  107. package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
  108. package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
  109. package/dist/infrastructure/ai/model-config.js +0 -84
  110. package/dist/infrastructure/ai/provider-ai-service.js +0 -477
  111. package/dist/infrastructure/cache/embedding-cache.js +0 -175
  112. package/dist/infrastructure/cache/query-result-cache.js +0 -66
  113. package/dist/infrastructure/cache/response-cache.js +0 -48
  114. package/dist/infrastructure/cache/security-scan-cache.js +0 -47
  115. package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
  116. package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
  117. package/dist/infrastructure/context/context-compressor.js +0 -329
  118. package/dist/infrastructure/context/conversation-context.js +0 -128
  119. package/dist/infrastructure/context/session-manager.js +0 -94
  120. package/dist/infrastructure/cost/cost-tracker.js +0 -360
  121. package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
  122. package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
  123. package/dist/infrastructure/governance/policy-as-code.js +0 -258
  124. package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
  125. package/dist/infrastructure/index.js +0 -7
  126. package/dist/infrastructure/observability/prompt-versioner.js +0 -145
  127. package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
  128. package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
  129. package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
  130. package/dist/infrastructure/protocols/mcp-server.js +0 -333
  131. package/dist/infrastructure/protocols/streaming-handler.js +0 -103
  132. package/dist/infrastructure/providers/cohere-provider.js +0 -444
  133. package/dist/infrastructure/providers/fake-provider.js +0 -130
  134. package/dist/infrastructure/providers/local-llm-provider.js +0 -330
  135. package/dist/infrastructure/providers/model-config.types.js +0 -9
  136. package/dist/infrastructure/providers/model-provider.interface.js +0 -8
  137. package/dist/infrastructure/providers/openai-provider.js +0 -413
  138. package/dist/infrastructure/providers/openrouter-provider.js +0 -399
  139. package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
  140. package/dist/infrastructure/providers/provider-config-loader.js +0 -120
  141. package/dist/infrastructure/providers/provider-registry.js +0 -88
  142. package/dist/infrastructure/safety/pattern-detector.js +0 -133
  143. package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
  144. package/dist/infrastructure/security/docker-sandbox.js +0 -178
  145. package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
  146. package/dist/infrastructure/security/license-scanner.js +0 -167
  147. package/dist/infrastructure/security/provider-bias-detector.js +0 -164
  148. package/dist/infrastructure/security/sandbox-executor.js +0 -64
  149. package/dist/infrastructure/serialization/toon-serializer.js +0 -119
  150. package/dist/infrastructure/storage/memory-stream-service.js +0 -204
  151. package/dist/infrastructure/storage/plan-repository.js +0 -96
  152. package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
  153. package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
  154. package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
  155. package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
  156. package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
  157. package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
  158. package/dist/infrastructure/storage/task-helpers.js +0 -197
  159. package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
  160. package/dist/infrastructure/ux/appropriate-friction.js +0 -213
  161. package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
  162. package/dist/infrastructure/ux/capability-boundaries.js +0 -42
  163. package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
  164. package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
  165. package/dist/infrastructure/ux/expectation-management.js +0 -327
  166. package/dist/infrastructure/ux/feature-discovery.js +0 -14
  167. package/dist/infrastructure/ux/feedback-prompt.js +0 -45
  168. package/dist/infrastructure/ux/hitl-validation.js +0 -297
  169. package/dist/infrastructure/ux/progress-indicator.js +0 -116
  170. package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
  171. package/dist/infrastructure/ux/review-checkpoint.js +0 -72
  172. package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
  173. package/dist/infrastructure/ux/stream-markdown.js +0 -151
  174. package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
  175. package/dist/infrastructure/ux/team-standards.js +0 -196
  176. package/dist/infrastructure/ux/transparency.js +0 -71
  177. package/dist/infrastructure/validation/agent-feedback.js +0 -55
  178. package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
  179. package/dist/infrastructure/validation/review-handler.js +0 -40
  180. package/dist/infrastructure/validation/summary-aggregator.js +0 -70
  181. package/dist/infrastructure/validation/summary-extractor.js +0 -45
  182. package/dist/infrastructure/validation/trace-summary.js +0 -52
  183. package/dist/infrastructure/verification/verification-service.js +0 -47
  184. package/dist/infrastructure/xai/attention-visualizer.js +0 -172
  185. package/dist/infrastructure/xai/cot-visualizer.js +0 -283
  186. package/dist/infrastructure/xai/decision-tree-log.js +0 -212
  187. package/dist/infrastructure/xai/interactive-xai.js +0 -260
  188. package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
  189. package/dist/intelligent-retrieval.js +0 -272
  190. package/dist/intent/classifier.js +0 -2
  191. package/dist/intent/context.js +0 -2
  192. package/dist/iterative-refinement.js +0 -189
  193. package/dist/learning.js +0 -232
  194. package/dist/log.js +0 -31
  195. package/dist/migrate.js +0 -133
  196. package/dist/parallel-processor.js +0 -534
  197. package/dist/planner.js +0 -198
  198. package/dist/policy.js +0 -26
  199. package/dist/presentation/cli/commands/ask-command.js +0 -314
  200. package/dist/presentation/cli/commands/cost-command.js +0 -191
  201. package/dist/presentation/cli/commands/decision-command.js +0 -207
  202. package/dist/presentation/cli/commands/docs-command.js +0 -25
  203. package/dist/presentation/cli/commands/fix-command.js +0 -53
  204. package/dist/presentation/cli/commands/knowledge-command.js +0 -129
  205. package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
  206. package/dist/presentation/cli/commands/models-command.js +0 -194
  207. package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
  208. package/dist/presentation/cli/commands/plan-command.js +0 -246
  209. package/dist/presentation/cli/commands/product-command.js +0 -199
  210. package/dist/presentation/cli/commands/react-command.js +0 -181
  211. package/dist/presentation/cli/commands/review-command.js +0 -154
  212. package/dist/presentation/cli/commands/run-command.js +0 -188
  213. package/dist/presentation/cli/commands/smart-command.js +0 -395
  214. package/dist/presentation/cli/commands/suggest-command.js +0 -138
  215. package/dist/presentation/cli/commands/trace-command.js +0 -129
  216. package/dist/presentation/cli/commands/undo-command.js +0 -150
  217. package/dist/query-optimizer.js +0 -205
  218. package/dist/refactor.js +0 -116
  219. package/dist/review.js +0 -206
  220. package/dist/search.js +0 -163
  221. package/dist/session.js +0 -704
  222. package/dist/task-verification.js +0 -336
  223. package/dist/testgen.js +0 -166
  224. package/dist/token-optimizer.js +0 -277
  225. package/dist/tools/bash.js +0 -213
  226. package/dist/tools/edit.js +0 -235
  227. package/dist/tools/executor.js +0 -153
  228. package/dist/tools/git-tool.js +0 -292
  229. package/dist/tools/parser.js +0 -158
  230. package/dist/tools/registry.js +0 -302
  231. package/dist/tools/search.js +0 -100
  232. package/dist/types.js +0 -2
  233. package/dist/utils/check-api-status.js +0 -100
  234. package/dist/utils/diff-parser.js +0 -162
  235. package/dist/verification/backup.js +0 -259
  236. package/dist/verification/compiler.js +0 -264
  237. package/dist/verification/index.js +0 -273
  238. 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