aidp 0.3.0 → 0.5.0

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +59 -4
  3. data/lib/aidp/analyze/agent_personas.rb +1 -1
  4. data/lib/aidp/analyze/database.rb +99 -82
  5. data/lib/aidp/analyze/error_handler.rb +12 -76
  6. data/lib/aidp/analyze/focus_guidance.rb +2 -2
  7. data/lib/aidp/analyze/metrics_storage.rb +336 -0
  8. data/lib/aidp/analyze/prioritizer.rb +2 -2
  9. data/lib/aidp/analyze/ruby_maat_integration.rb +6 -102
  10. data/lib/aidp/analyze/runner.rb +107 -191
  11. data/lib/aidp/analyze/steps.rb +29 -30
  12. data/lib/aidp/analyze/storage.rb +233 -171
  13. data/lib/aidp/cli/jobs_command.rb +489 -0
  14. data/lib/aidp/cli/terminal_io.rb +52 -0
  15. data/lib/aidp/cli.rb +104 -45
  16. data/lib/aidp/core_ext/class_attribute.rb +36 -0
  17. data/lib/aidp/database/pg_adapter.rb +148 -0
  18. data/lib/aidp/database_config.rb +69 -0
  19. data/lib/aidp/database_connection.rb +72 -0
  20. data/lib/aidp/database_migration.rb +158 -0
  21. data/lib/aidp/execute/runner.rb +65 -92
  22. data/lib/aidp/execute/steps.rb +81 -82
  23. data/lib/aidp/job_manager.rb +41 -0
  24. data/lib/aidp/jobs/base_job.rb +47 -0
  25. data/lib/aidp/jobs/provider_execution_job.rb +96 -0
  26. data/lib/aidp/provider_manager.rb +25 -0
  27. data/lib/aidp/providers/agent_supervisor.rb +348 -0
  28. data/lib/aidp/providers/anthropic.rb +166 -3
  29. data/lib/aidp/providers/base.rb +153 -6
  30. data/lib/aidp/providers/cursor.rb +247 -43
  31. data/lib/aidp/providers/gemini.rb +166 -3
  32. data/lib/aidp/providers/supervised_base.rb +317 -0
  33. data/lib/aidp/providers/supervised_cursor.rb +22 -0
  34. data/lib/aidp/version.rb +1 -1
  35. data/lib/aidp.rb +25 -34
  36. data/templates/ANALYZE/01_REPOSITORY_ANALYSIS.md +4 -4
  37. metadata +72 -35
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "sqlite3"
3
+ require "pg"
4
4
  require "json"
5
5
  require "yaml"
6
6
 
@@ -12,7 +12,6 @@ module Aidp
12
12
  def initialize(project_dir = Dir.pwd, config = {})
13
13
  @project_dir = project_dir
14
14
  @config = config
15
- @db_path = config[:db_path] || File.join(project_dir, ".aidp-analysis.db")
16
15
  @db = nil
17
16
 
18
17
  ensure_database_exists
@@ -36,14 +35,24 @@ module Aidp
36
35
  }
37
36
 
38
37
  # Insert or update analysis result
39
- @db.execute(
40
- "INSERT OR REPLACE INTO analysis_results (execution_id, step_name, data, metadata, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)",
41
- execution_id,
42
- step_name,
43
- JSON.generate(data),
44
- JSON.generate(analysis_data[:metadata]),
45
- timestamp.to_i,
46
- timestamp.to_i
38
+ @db.exec_params(
39
+ <<~SQL,
40
+ INSERT INTO analysis_results (execution_id, step_name, data, metadata, created_at, updated_at)
41
+ VALUES ($1, $2, $3, $4, $5, $6)
42
+ ON CONFLICT (execution_id, step_name)
43
+ DO UPDATE SET
44
+ data = EXCLUDED.data,
45
+ metadata = EXCLUDED.metadata,
46
+ updated_at = EXCLUDED.updated_at
47
+ SQL
48
+ [
49
+ execution_id,
50
+ step_name,
51
+ data.to_json,
52
+ analysis_data[:metadata].to_json,
53
+ timestamp,
54
+ timestamp
55
+ ]
47
56
  )
48
57
 
49
58
  # Store metrics with indefinite retention
@@ -72,14 +81,19 @@ module Aidp
72
81
  metrics = extract_metrics(data)
73
82
 
74
83
  metrics.each do |metric_name, metric_value|
75
- @db.execute(
76
- "INSERT INTO metrics (execution_id, step_name, metric_name, metric_value, metric_type, created_at) VALUES (?, ?, ?, ?, ?, ?)",
77
- execution_id,
78
- step_name,
79
- metric_name,
80
- metric_value.to_s,
81
- metric_value.class.name,
82
- timestamp.to_i
84
+ @db.exec_params(
85
+ <<~SQL,
86
+ INSERT INTO metrics (execution_id, step_name, metric_name, metric_value, metric_type, created_at)
87
+ VALUES ($1, $2, $3, $4, $5, $6)
88
+ SQL
89
+ [
90
+ execution_id,
91
+ step_name,
92
+ metric_name,
93
+ metric_value.to_s,
94
+ metric_value.class.name,
95
+ timestamp
96
+ ]
83
97
  )
84
98
  end
85
99
 
@@ -93,28 +107,35 @@ module Aidp
93
107
 
94
108
  result = if step_name
95
109
  # Get specific step result
96
- @db.execute(
97
- "SELECT * FROM analysis_results WHERE execution_id = ? AND step_name = ? ORDER BY updated_at DESC LIMIT 1",
98
- execution_id,
99
- step_name
100
- ).first
110
+ @db.exec_params(
111
+ <<~SQL,
112
+ SELECT * FROM analysis_results
113
+ WHERE execution_id = $1 AND step_name = $2
114
+ ORDER BY updated_at DESC
115
+ LIMIT 1
116
+ SQL
117
+ [execution_id, step_name]
118
+ )
101
119
  else
102
120
  # Get all results for execution
103
- @db.execute(
104
- "SELECT * FROM analysis_results WHERE execution_id = ? ORDER BY updated_at DESC",
105
- execution_id
121
+ @db.exec_params(
122
+ <<~SQL,
123
+ SELECT * FROM analysis_results
124
+ WHERE execution_id = $1
125
+ ORDER BY updated_at DESC
126
+ SQL
127
+ [execution_id]
106
128
  )
107
129
  end
108
130
 
109
- return nil unless result
131
+ return nil if result.ntuples.zero?
110
132
 
111
- if result.is_a?(Array) && result.length > 1
133
+ if result.ntuples > 1
112
134
  # Multiple results
113
135
  result.map { |row| parse_analysis_result(row) }
114
136
  else
115
137
  # Single result
116
- row = result.is_a?(Array) ? result.first : result
117
- parse_analysis_result(row)
138
+ parse_analysis_result(result[0])
118
139
  end
119
140
  end
120
141
 
@@ -124,26 +145,31 @@ module Aidp
124
145
 
125
146
  query = "SELECT * FROM metrics WHERE 1=1"
126
147
  params = []
148
+ param_index = 1
127
149
 
128
150
  if execution_id
129
- query += " AND execution_id = ?"
151
+ query += " AND execution_id = $#{param_index}"
130
152
  params << execution_id
153
+ param_index += 1
131
154
  end
132
155
 
133
156
  if step_name
134
- query += " AND step_name = ?"
157
+ query += " AND step_name = $#{param_index}"
135
158
  params << step_name
159
+ param_index += 1
136
160
  end
137
161
 
138
162
  if metric_name
139
- query += " AND metric_name = ?"
163
+ query += " AND metric_name = $#{param_index}"
140
164
  params << metric_name
165
+ param_index += 1
141
166
  end
142
167
 
143
- query += " ORDER BY created_at DESC LIMIT ?"
168
+ query += " ORDER BY created_at DESC"
169
+ query += " LIMIT $#{param_index}"
144
170
  params << limit
145
171
 
146
- results = @db.execute(query, *params)
172
+ results = @db.exec_params(query, params)
147
173
  results.map { |row| parse_metric(row) }
148
174
  end
149
175
 
@@ -153,25 +179,29 @@ module Aidp
153
179
 
154
180
  query = "SELECT * FROM aggregated_metrics WHERE 1=1"
155
181
  params = []
182
+ param_index = 1
156
183
 
157
184
  if execution_id
158
- query += " AND execution_id = ?"
185
+ query += " AND execution_id = $#{param_index}"
159
186
  params << execution_id
187
+ param_index += 1
160
188
  end
161
189
 
162
190
  if step_name
163
- query += " AND step_name = ?"
191
+ query += " AND step_name = $#{param_index}"
164
192
  params << step_name
193
+ param_index += 1
165
194
  end
166
195
 
167
196
  if metric_name
168
- query += " AND metric_name = ?"
197
+ query += " AND metric_name = $#{param_index}"
169
198
  params << metric_name
199
+ param_index + 1
170
200
  end
171
201
 
172
202
  query += " ORDER BY created_at DESC"
173
203
 
174
- results = @db.execute(query, *params)
204
+ results = @db.exec_params(query, params)
175
205
  results.map { |row| parse_aggregated_metric(row) }
176
206
  end
177
207
 
@@ -179,9 +209,14 @@ module Aidp
179
209
  def get_execution_history(limit = 50)
180
210
  ensure_connection
181
211
 
182
- results = @db.execute(
183
- "SELECT DISTINCT execution_id, step_name, created_at, updated_at FROM analysis_results ORDER BY created_at DESC LIMIT ?",
184
- limit
212
+ results = @db.exec_params(
213
+ <<~SQL,
214
+ SELECT DISTINCT execution_id, step_name, created_at, updated_at
215
+ FROM analysis_results
216
+ ORDER BY created_at DESC
217
+ LIMIT $1
218
+ SQL
219
+ [limit]
185
220
  )
186
221
 
187
222
  results.map { |row| parse_execution_history(row) }
@@ -194,30 +229,34 @@ module Aidp
194
229
  stats = {}
195
230
 
196
231
  # Total executions
197
- total_executions = @db.execute("SELECT COUNT(DISTINCT execution_id) FROM analysis_results").first[0]
232
+ total_executions = @db.exec("SELECT COUNT(DISTINCT execution_id) FROM analysis_results").first["count"].to_i
198
233
  stats[:total_executions] = total_executions
199
234
 
200
235
  # Total steps
201
- total_steps = @db.execute("SELECT COUNT(*) FROM analysis_results").first[0]
236
+ total_steps = @db.exec("SELECT COUNT(*) FROM analysis_results").first["count"].to_i
202
237
  stats[:total_steps] = total_steps
203
238
 
204
239
  # Steps by type
205
- steps_by_type = @db.execute("SELECT step_name, COUNT(*) FROM analysis_results GROUP BY step_name")
206
- stats[:steps_by_type] = steps_by_type.to_h
240
+ steps_by_type = @db.exec("SELECT step_name, COUNT(*) FROM analysis_results GROUP BY step_name")
241
+ stats[:steps_by_type] = steps_by_type.each_with_object({}) do |row, hash|
242
+ hash[row["step_name"]] = row["count"].to_i
243
+ end
207
244
 
208
245
  # Total metrics
209
- total_metrics = @db.execute("SELECT COUNT(*) FROM metrics").first[0]
246
+ total_metrics = @db.exec("SELECT COUNT(*) FROM metrics").first["count"].to_i
210
247
  stats[:total_metrics] = total_metrics
211
248
 
212
249
  # Metrics by type
213
- metrics_by_type = @db.execute("SELECT metric_name, COUNT(*) FROM metrics GROUP BY metric_name")
214
- stats[:metrics_by_type] = metrics_by_type.to_h
250
+ metrics_by_type = @db.exec("SELECT metric_name, COUNT(*) FROM metrics GROUP BY metric_name")
251
+ stats[:metrics_by_type] = metrics_by_type.each_with_object({}) do |row, hash|
252
+ hash[row["metric_name"]] = row["count"].to_i
253
+ end
215
254
 
216
255
  # Date range
217
- date_range = @db.execute("SELECT MIN(created_at), MAX(created_at) FROM analysis_results").first
256
+ date_range = @db.exec("SELECT MIN(created_at), MAX(created_at) FROM analysis_results").first
218
257
  stats[:date_range] = {
219
- earliest: date_range[0] ? Time.at(date_range[0]) : nil,
220
- latest: date_range[1] ? Time.at(date_range[1]) : nil
258
+ earliest: date_range["min"] ? Time.parse(date_range["min"]) : nil,
259
+ latest: date_range["max"] ? Time.parse(date_range["max"]) : nil
221
260
  }
222
261
 
223
262
  stats
@@ -228,10 +267,9 @@ module Aidp
228
267
  ensure_connection
229
268
 
230
269
  # Delete existing analysis result
231
- @db.execute(
232
- "DELETE FROM analysis_results WHERE execution_id = ? AND step_name = ?",
233
- execution_id,
234
- step_name
270
+ @db.exec_params(
271
+ "DELETE FROM analysis_results WHERE execution_id = $1 AND step_name = $2",
272
+ [execution_id, step_name]
235
273
  )
236
274
 
237
275
  # Store new analysis result
@@ -243,17 +281,16 @@ module Aidp
243
281
  ensure_connection
244
282
 
245
283
  if execution_id && step_name
246
- @db.execute(
247
- "DELETE FROM analysis_results WHERE execution_id = ? AND step_name = ?",
248
- execution_id,
249
- step_name
284
+ @db.exec_params(
285
+ "DELETE FROM analysis_results WHERE execution_id = $1 AND step_name = $2",
286
+ [execution_id, step_name]
250
287
  )
251
288
  elsif execution_id
252
- @db.execute("DELETE FROM analysis_results WHERE execution_id = ?", execution_id)
289
+ @db.exec_params("DELETE FROM analysis_results WHERE execution_id = $1", [execution_id])
253
290
  elsif step_name
254
- @db.execute("DELETE FROM analysis_results WHERE step_name = ?", step_name)
291
+ @db.exec_params("DELETE FROM analysis_results WHERE step_name = $1", [step_name])
255
292
  else
256
- @db.execute("DELETE FROM analysis_results")
293
+ @db.exec("DELETE FROM analysis_results")
257
294
  end
258
295
 
259
296
  {success: true, deleted_execution_id: execution_id, deleted_step_name: step_name}
@@ -295,27 +332,43 @@ module Aidp
295
332
 
296
333
  # Import analysis results
297
334
  parsed_data["analysis_results"]&.each do |result|
298
- @db.execute(
299
- "INSERT OR REPLACE INTO analysis_results (execution_id, step_name, data, metadata, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)",
300
- result["execution_id"],
301
- result["step_name"],
302
- result["data"],
303
- result["metadata"],
304
- result["created_at"],
305
- result["updated_at"]
335
+ @db.exec_params(
336
+ <<~SQL,
337
+ INSERT INTO analysis_results (execution_id, step_name, data, metadata, created_at, updated_at)
338
+ VALUES ($1, $2, $3, $4, $5, $6)
339
+ ON CONFLICT (execution_id, step_name)
340
+ DO UPDATE SET
341
+ data = EXCLUDED.data,
342
+ metadata = EXCLUDED.metadata,
343
+ updated_at = EXCLUDED.updated_at
344
+ SQL
345
+ [
346
+ result["execution_id"],
347
+ result["step_name"],
348
+ result["data"],
349
+ result["metadata"],
350
+ result["created_at"],
351
+ result["updated_at"]
352
+ ]
306
353
  )
307
354
  end
308
355
 
309
356
  # Import metrics
310
357
  parsed_data["metrics"]&.each do |metric|
311
- @db.execute(
312
- "INSERT OR REPLACE INTO metrics (execution_id, step_name, metric_name, metric_value, metric_type, created_at) VALUES (?, ?, ?, ?, ?, ?)",
313
- metric["execution_id"],
314
- metric["step_name"],
315
- metric["metric_name"],
316
- metric["metric_value"],
317
- metric["metric_type"],
318
- metric["created_at"]
358
+ @db.exec_params(
359
+ <<~SQL,
360
+ INSERT INTO metrics (execution_id, step_name, metric_name, metric_value, metric_type, created_at)
361
+ VALUES ($1, $2, $3, $4, $5, $6)
362
+ ON CONFLICT DO NOTHING
363
+ SQL
364
+ [
365
+ metric["execution_id"],
366
+ metric["step_name"],
367
+ metric["metric_name"],
368
+ metric["metric_value"],
369
+ metric["metric_type"],
370
+ metric["created_at"]
371
+ ]
319
372
  )
320
373
  end
321
374
 
@@ -331,71 +384,78 @@ module Aidp
331
384
  private
332
385
 
333
386
  def ensure_database_exists
334
- return if File.exist?(@db_path)
335
-
336
- @db = SQLite3::Database.new(@db_path)
387
+ ensure_connection
337
388
  create_schema
338
389
  end
339
390
 
340
391
  def ensure_connection
341
- @db ||= SQLite3::Database.new(@db_path)
392
+ return if @db
393
+
394
+ @db = PG.connect(
395
+ host: ENV["AIDP_DB_HOST"] || "localhost",
396
+ port: ENV["AIDP_DB_PORT"] || 5432,
397
+ dbname: ENV["AIDP_DB_NAME"] || "aidp",
398
+ user: ENV["AIDP_DB_USER"] || ENV["USER"],
399
+ password: ENV["AIDP_DB_PASSWORD"]
400
+ )
401
+ @db.type_map_for_results = PG::BasicTypeMapForResults.new(@db)
342
402
  end
343
403
 
344
404
  def create_schema
345
405
  # Create analysis_results table
346
- @db.execute(<<~SQL)
406
+ @db.exec(<<~SQL)
347
407
  CREATE TABLE IF NOT EXISTS analysis_results (
348
- id INTEGER PRIMARY KEY AUTOINCREMENT,
408
+ id SERIAL PRIMARY KEY,
349
409
  execution_id TEXT NOT NULL,
350
410
  step_name TEXT NOT NULL,
351
- data TEXT NOT NULL,
352
- metadata TEXT,
353
- created_at INTEGER NOT NULL,
354
- updated_at INTEGER NOT NULL,
411
+ data JSONB NOT NULL,
412
+ metadata JSONB,
413
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL,
414
+ updated_at TIMESTAMP WITH TIME ZONE NOT NULL,
355
415
  UNIQUE(execution_id, step_name)
356
416
  )
357
417
  SQL
358
418
 
359
419
  # Create metrics table (indefinite retention)
360
- @db.execute(<<~SQL)
420
+ @db.exec(<<~SQL)
361
421
  CREATE TABLE IF NOT EXISTS metrics (
362
- id INTEGER PRIMARY KEY AUTOINCREMENT,
422
+ id SERIAL PRIMARY KEY,
363
423
  execution_id TEXT NOT NULL,
364
424
  step_name TEXT NOT NULL,
365
425
  metric_name TEXT NOT NULL,
366
426
  metric_value TEXT NOT NULL,
367
427
  metric_type TEXT NOT NULL,
368
- created_at INTEGER NOT NULL
428
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL
369
429
  )
370
430
  SQL
371
431
 
372
432
  # Create aggregated_metrics table
373
- @db.execute(<<~SQL)
433
+ @db.exec(<<~SQL)
374
434
  CREATE TABLE IF NOT EXISTS aggregated_metrics (
375
- id INTEGER PRIMARY KEY AUTOINCREMENT,
435
+ id SERIAL PRIMARY KEY,
376
436
  execution_id TEXT NOT NULL,
377
437
  step_name TEXT NOT NULL,
378
438
  metric_name TEXT NOT NULL,
379
- min_value REAL,
380
- max_value REAL,
381
- avg_value REAL,
439
+ min_value DOUBLE PRECISION,
440
+ max_value DOUBLE PRECISION,
441
+ avg_value DOUBLE PRECISION,
382
442
  count INTEGER NOT NULL,
383
- created_at INTEGER NOT NULL
443
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL
384
444
  )
385
445
  SQL
386
446
 
387
447
  # Create indexes
388
- @db.execute("CREATE INDEX IF NOT EXISTS idx_analysis_results_execution_id ON analysis_results(execution_id)")
389
- @db.execute("CREATE INDEX IF NOT EXISTS idx_analysis_results_step_name ON analysis_results(step_name)")
390
- @db.execute("CREATE INDEX IF NOT EXISTS idx_analysis_results_created_at ON analysis_results(created_at)")
391
- @db.execute("CREATE INDEX IF NOT EXISTS idx_metrics_execution_id ON metrics(execution_id)")
392
- @db.execute("CREATE INDEX IF NOT EXISTS idx_metrics_step_name ON metrics(step_name)")
393
- @db.execute("CREATE INDEX IF NOT EXISTS idx_metrics_metric_name ON metrics(metric_name)")
394
- @db.execute("CREATE INDEX IF NOT EXISTS idx_metrics_created_at ON metrics(created_at)")
448
+ @db.exec("CREATE INDEX IF NOT EXISTS idx_analysis_results_execution_id ON analysis_results(execution_id)")
449
+ @db.exec("CREATE INDEX IF NOT EXISTS idx_analysis_results_step_name ON analysis_results(step_name)")
450
+ @db.exec("CREATE INDEX IF NOT EXISTS idx_analysis_results_created_at ON analysis_results(created_at)")
451
+ @db.exec("CREATE INDEX IF NOT EXISTS idx_metrics_execution_id ON metrics(execution_id)")
452
+ @db.exec("CREATE INDEX IF NOT EXISTS idx_metrics_step_name ON metrics(step_name)")
453
+ @db.exec("CREATE INDEX IF NOT EXISTS idx_metrics_metric_name ON metrics(metric_name)")
454
+ @db.exec("CREATE INDEX IF NOT EXISTS idx_metrics_created_at ON metrics(created_at)")
395
455
 
396
456
  # Store schema version
397
- @db.execute("CREATE TABLE IF NOT EXISTS schema_version (version INTEGER NOT NULL)")
398
- @db.execute("INSERT OR REPLACE INTO schema_version (version) VALUES (?)", SCHEMA_VERSION)
457
+ @db.exec("CREATE TABLE IF NOT EXISTS schema_version (version INTEGER NOT NULL)")
458
+ @db.exec_params("INSERT INTO schema_version (version) VALUES ($1) ON CONFLICT DO NOTHING", [SCHEMA_VERSION])
399
459
  end
400
460
 
401
461
  def generate_execution_id
@@ -436,41 +496,37 @@ module Aidp
436
496
  next unless metric_value.is_a?(Numeric)
437
497
 
438
498
  # Get existing aggregated metric
439
- existing = @db.execute(
440
- "SELECT * FROM aggregated_metrics WHERE execution_id = ? AND step_name = ? AND metric_name = ?",
441
- execution_id,
442
- step_name,
443
- metric_name
499
+ existing = @db.exec_params(
500
+ <<~SQL,
501
+ SELECT * FROM aggregated_metrics
502
+ WHERE execution_id = $1 AND step_name = $2 AND metric_name = $3
503
+ SQL
504
+ [execution_id, step_name, metric_name]
444
505
  ).first
445
506
 
446
507
  if existing
447
508
  # Update existing aggregated metric
448
- count = existing[7] + 1
449
- min_value = [existing[3], metric_value].min
450
- max_value = [existing[4], metric_value].max
451
- avg_value = ((existing[5] * existing[7]) + metric_value) / count
452
-
453
- @db.execute(
454
- "UPDATE aggregated_metrics SET min_value = ?, max_value = ?, avg_value = ?, count = ?, created_at = ? WHERE id = ?",
455
- min_value,
456
- max_value,
457
- avg_value,
458
- count,
459
- timestamp.to_i,
460
- existing[0]
509
+ count = existing["count"].to_i + 1
510
+ min_value = [existing["min_value"].to_f, metric_value].min
511
+ max_value = [existing["max_value"].to_f, metric_value].max
512
+ avg_value = ((existing["avg_value"].to_f * existing["count"].to_i) + metric_value) / count
513
+
514
+ @db.exec_params(
515
+ <<~SQL,
516
+ UPDATE aggregated_metrics
517
+ SET min_value = $1, max_value = $2, avg_value = $3, count = $4, created_at = $5
518
+ WHERE id = $6
519
+ SQL
520
+ [min_value, max_value, avg_value, count, timestamp, existing["id"]]
461
521
  )
462
522
  else
463
523
  # Create new aggregated metric
464
- @db.execute(
465
- "INSERT INTO aggregated_metrics (execution_id, step_name, metric_name, min_value, max_value, avg_value, count, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
466
- execution_id,
467
- step_name,
468
- metric_name,
469
- metric_value,
470
- metric_value,
471
- metric_value,
472
- 1,
473
- timestamp.to_i
524
+ @db.exec_params(
525
+ <<~SQL,
526
+ INSERT INTO aggregated_metrics (execution_id, step_name, metric_name, min_value, max_value, avg_value, count, created_at)
527
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
528
+ SQL
529
+ [execution_id, step_name, metric_name, metric_value, metric_value, metric_value, 1, timestamp]
474
530
  )
475
531
  end
476
532
  end
@@ -480,13 +536,13 @@ module Aidp
480
536
  return nil unless row
481
537
 
482
538
  {
483
- id: row[0],
484
- execution_id: row[1],
485
- step_name: row[2],
486
- data: JSON.parse(row[3]),
487
- metadata: JSON.parse(row[4] || "{}"),
488
- created_at: Time.at(row[5]),
489
- updated_at: Time.at(row[6])
539
+ id: row["id"].to_i,
540
+ execution_id: row["execution_id"],
541
+ step_name: row["step_name"],
542
+ data: JSON.parse(row["data"]),
543
+ metadata: JSON.parse(row["metadata"] || "{}"),
544
+ created_at: Time.parse(row["created_at"]),
545
+ updated_at: Time.parse(row["updated_at"])
490
546
  }
491
547
  end
492
548
 
@@ -494,13 +550,13 @@ module Aidp
494
550
  return nil unless row
495
551
 
496
552
  {
497
- id: row[0],
498
- execution_id: row[1],
499
- step_name: row[2],
500
- metric_name: row[3],
501
- metric_value: row[4],
502
- metric_type: row[5],
503
- created_at: Time.at(row[6])
553
+ id: row["id"].to_i,
554
+ execution_id: row["execution_id"],
555
+ step_name: row["step_name"],
556
+ metric_name: row["metric_name"],
557
+ metric_value: row["metric_value"],
558
+ metric_type: row["metric_type"],
559
+ created_at: Time.parse(row["created_at"])
504
560
  }
505
561
  end
506
562
 
@@ -508,15 +564,15 @@ module Aidp
508
564
  return nil unless row
509
565
 
510
566
  {
511
- id: row[0],
512
- execution_id: row[1],
513
- step_name: row[2],
514
- metric_name: row[3],
515
- min_value: row[4],
516
- max_value: row[5],
517
- avg_value: row[6],
518
- count: row[7],
519
- created_at: Time.at(row[8])
567
+ id: row["id"].to_i,
568
+ execution_id: row["execution_id"],
569
+ step_name: row["step_name"],
570
+ metric_name: row["metric_name"],
571
+ min_value: row["min_value"].to_f,
572
+ max_value: row["max_value"].to_f,
573
+ avg_value: row["avg_value"].to_f,
574
+ count: row["count"].to_i,
575
+ created_at: Time.parse(row["created_at"])
520
576
  }
521
577
  end
522
578
 
@@ -524,10 +580,10 @@ module Aidp
524
580
  return nil unless row
525
581
 
526
582
  {
527
- execution_id: row[0],
528
- step_name: row[1],
529
- created_at: Time.at(row[2]),
530
- updated_at: Time.at(row[3])
583
+ execution_id: row["execution_id"],
584
+ step_name: row["step_name"],
585
+ created_at: Time.parse(row["created_at"]),
586
+ updated_at: Time.parse(row["updated_at"])
531
587
  }
532
588
  end
533
589
 
@@ -536,20 +592,22 @@ module Aidp
536
592
 
537
593
  query = "SELECT * FROM analysis_results"
538
594
  params = []
595
+ param_index = 1
539
596
 
540
597
  if options[:execution_id]
541
- query += " WHERE execution_id = ?"
598
+ query += " WHERE execution_id = $#{param_index}"
542
599
  params << options[:execution_id]
600
+ param_index += 1
543
601
  end
544
602
 
545
603
  query += " ORDER BY created_at DESC"
546
604
 
547
605
  if options[:limit]
548
- query += " LIMIT ?"
606
+ query += " LIMIT $#{param_index}"
549
607
  params << options[:limit]
550
608
  end
551
609
 
552
- results = @db.execute(query, *params)
610
+ results = @db.exec_params(query, params)
553
611
  results.map { |row| parse_analysis_result(row) }
554
612
  end
555
613
 
@@ -558,20 +616,22 @@ module Aidp
558
616
 
559
617
  query = "SELECT * FROM metrics"
560
618
  params = []
619
+ param_index = 1
561
620
 
562
621
  if options[:execution_id]
563
- query += " WHERE execution_id = ?"
622
+ query += " WHERE execution_id = $#{param_index}"
564
623
  params << options[:execution_id]
624
+ param_index += 1
565
625
  end
566
626
 
567
627
  query += " ORDER BY created_at DESC"
568
628
 
569
629
  if options[:limit]
570
- query += " LIMIT ?"
630
+ query += " LIMIT $#{param_index}"
571
631
  params << options[:limit]
572
632
  end
573
633
 
574
- results = @db.execute(query, *params)
634
+ results = @db.exec_params(query, params)
575
635
  results.map { |row| parse_metric(row) }
576
636
  end
577
637
 
@@ -580,20 +640,22 @@ module Aidp
580
640
 
581
641
  query = "SELECT * FROM aggregated_metrics"
582
642
  params = []
643
+ param_index = 1
583
644
 
584
645
  if options[:execution_id]
585
- query += " WHERE execution_id = ?"
646
+ query += " WHERE execution_id = $#{param_index}"
586
647
  params << options[:execution_id]
648
+ param_index += 1
587
649
  end
588
650
 
589
651
  query += " ORDER BY created_at DESC"
590
652
 
591
653
  if options[:limit]
592
- query += " LIMIT ?"
654
+ query += " LIMIT $#{param_index}"
593
655
  params << options[:limit]
594
656
  end
595
657
 
596
- results = @db.execute(query, *params)
658
+ results = @db.exec_params(query, params)
597
659
  results.map { |row| parse_aggregated_metric(row) }
598
660
  end
599
661
  end