sumulige-claude 1.1.2 → 1.2.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 (102) hide show
  1. package/.claude/hooks/code-formatter.cjs +7 -2
  2. package/.claude/hooks/multi-session.cjs +9 -3
  3. package/.claude/hooks/pre-commit.cjs +0 -0
  4. package/.claude/hooks/pre-push.cjs +0 -0
  5. package/.claude/hooks/project-kickoff.cjs +22 -11
  6. package/.claude/hooks/rag-skill-loader.cjs +7 -0
  7. package/.claude/hooks/thinking-silent.cjs +9 -3
  8. package/.claude/hooks/todo-manager.cjs +19 -13
  9. package/.claude/hooks/verify-work.cjs +10 -4
  10. package/.claude/quality-gate.json +9 -3
  11. package/.claude/settings.local.json +16 -1
  12. package/.claude/templates/hooks/README.md +302 -0
  13. package/.claude/templates/hooks/hook.sh.template +94 -0
  14. package/.claude/templates/hooks/user-prompt-submit.cjs.template +116 -0
  15. package/.claude/templates/hooks/user-response-submit.cjs.template +94 -0
  16. package/.claude/templates/hooks/validate.js +173 -0
  17. package/.claude/workflow/document-scanner.js +426 -0
  18. package/.claude/workflow/knowledge-engine.js +941 -0
  19. package/.claude/workflow/notebooklm/browser.js +1028 -0
  20. package/.claude/workflow/phases/phase1-research.js +578 -0
  21. package/.claude/workflow/phases/phase1-research.ts +465 -0
  22. package/.claude/workflow/phases/phase2-approve.js +722 -0
  23. package/.claude/workflow/phases/phase3-plan.js +1200 -0
  24. package/.claude/workflow/phases/phase4-develop.js +894 -0
  25. package/.claude/workflow/search-cache.js +230 -0
  26. package/.claude/workflow/templates/approval.md +315 -0
  27. package/.claude/workflow/templates/development.md +377 -0
  28. package/.claude/workflow/templates/planning.md +328 -0
  29. package/.claude/workflow/templates/research.md +250 -0
  30. package/.claude/workflow/types.js +37 -0
  31. package/.claude/workflow/web-search.js +278 -0
  32. package/.claude-plugin/marketplace.json +2 -2
  33. package/AGENTS.md +176 -0
  34. package/CHANGELOG.md +7 -14
  35. package/cli.js +20 -0
  36. package/config/quality-gate.json +9 -3
  37. package/development/cache/web-search/search_1193d605f8eb364651fc2f2041b58a31.json +36 -0
  38. package/development/cache/web-search/search_3798bf06960edc125f744a1abb5b72c5.json +36 -0
  39. package/development/cache/web-search/search_37c7d4843a53f0d83f1122a6f908a2a3.json +36 -0
  40. package/development/cache/web-search/search_44166fa0153709ee168485a22aa0ab40.json +36 -0
  41. package/development/cache/web-search/search_4deaebb1f77e86a8ca066dc5a49c59fd.json +36 -0
  42. package/development/cache/web-search/search_94da91789466070a7f545612e73c7372.json +36 -0
  43. package/development/cache/web-search/search_dd5de8491b8b803a3cb01339cd210fb0.json +36 -0
  44. package/development/knowledge-base/.index.clean.json +0 -0
  45. package/development/knowledge-base/.index.json +486 -0
  46. package/development/knowledge-base/test-best-practices.md +29 -0
  47. package/development/projects/proj_mkh1pazz_ixmt1/phase1/feasibility-report.md +160 -0
  48. package/development/projects/proj_mkh4jvnb_z7rwf/phase1/feasibility-report.md +160 -0
  49. package/development/projects/proj_mkh4jxkd_ewz5a/phase1/feasibility-report.md +160 -0
  50. package/development/projects/proj_mkh4k84n_ni73k/phase1/feasibility-report.md +160 -0
  51. package/development/projects/proj_mkh4wfyd_u9w88/phase1/feasibility-report.md +160 -0
  52. package/development/projects/proj_mkh4wsbo_iahvf/development/projects/proj_mkh4xbpg_4na5w/phase1/feasibility-report.md +160 -0
  53. package/development/projects/proj_mkh4wsbo_iahvf/phase1/feasibility-report.md +160 -0
  54. package/development/projects/proj_mkh4xulg_1ka8x/phase1/feasibility-report.md +160 -0
  55. package/development/projects/proj_mkh4xwhj_gch8j/phase1/feasibility-report.md +160 -0
  56. package/development/projects/proj_mkh4y2qk_9lm8z/phase1/feasibility-report.md +160 -0
  57. package/development/projects/proj_mkh4y2qk_9lm8z/phase2/requirements.md +226 -0
  58. package/development/projects/proj_mkh4y2qk_9lm8z/phase3/PRD.md +345 -0
  59. package/development/projects/proj_mkh4y2qk_9lm8z/phase3/TASK_PLAN.md +284 -0
  60. package/development/projects/proj_mkh4y2qk_9lm8z/phase3/prototype/README.md +14 -0
  61. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/DEVELOPMENT_LOG.md +35 -0
  62. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/TASKS.md +34 -0
  63. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/.env.example +5 -0
  64. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/README.md +60 -0
  65. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/package.json +25 -0
  66. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/src/index.js +70 -0
  67. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/src/routes/index.js +48 -0
  68. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/tests/health.test.js +20 -0
  69. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/tests/jest.config.js +21 -0
  70. package/development/projects/proj_mkh7veqg_3lypc/phase1/feasibility-report.md +160 -0
  71. package/development/projects/proj_mkh7veqg_3lypc/phase2/requirements.md +226 -0
  72. package/development/projects/proj_mkh7veqg_3lypc/phase3/PRD.md +345 -0
  73. package/development/projects/proj_mkh7veqg_3lypc/phase3/TASK_PLAN.md +284 -0
  74. package/development/projects/proj_mkh7veqg_3lypc/phase3/prototype/README.md +14 -0
  75. package/development/projects/proj_mkh8k8fo_rmqn5/phase1/feasibility-report.md +160 -0
  76. package/development/projects/proj_mkh8xyhy_1vshq/phase1/feasibility-report.md +178 -0
  77. package/development/projects/proj_mkh8zddd_dhamf/phase1/feasibility-report.md +377 -0
  78. package/development/projects/proj_mkh8zddd_dhamf/phase2/requirements.md +442 -0
  79. package/development/projects/proj_mkh8zddd_dhamf/phase3/api-design.md +800 -0
  80. package/development/projects/proj_mkh8zddd_dhamf/phase3/architecture.md +625 -0
  81. package/development/projects/proj_mkh8zddd_dhamf/phase3/data-model.md +830 -0
  82. package/development/projects/proj_mkh8zddd_dhamf/phase3/risks.md +957 -0
  83. package/development/projects/proj_mkh8zddd_dhamf/phase3/wbs.md +381 -0
  84. package/development/todos/.state.json +14 -1
  85. package/development/todos/INDEX.md +31 -73
  86. package/development/todos/completed/develop/local-knowledge-index.md +85 -0
  87. package/development/todos/{active → completed/develop}/todo-system.md +13 -3
  88. package/development/todos/completed/develop/web-search-integration.md +83 -0
  89. package/development/todos/completed/test/phase1-e2e-test.md +103 -0
  90. package/lib/commands.js +388 -0
  91. package/package.json +3 -2
  92. package/tests/config-manager.test.js +677 -0
  93. package/tests/config-validator.test.js +436 -0
  94. package/tests/errors.test.js +477 -0
  95. package/tests/manual/phase1-e2e.sh +389 -0
  96. package/tests/manual/phase2-test-cases.md +311 -0
  97. package/tests/manual/phase3-test-cases.md +309 -0
  98. package/tests/manual/phase4-test-cases.md +414 -0
  99. package/tests/manual/test-cases.md +417 -0
  100. package/tests/quality-gate.test.js +679 -0
  101. package/tests/quality-rules.test.js +619 -0
  102. package/tests/version-check.test.js +75 -0
@@ -0,0 +1,830 @@
1
+ # Data Model Design Document
2
+
3
+ **Project**: proj_mkh8zddd_dhamf (AI 代码审查工具)
4
+ **Date**: 1/17/2026
5
+ **Phase**: 3 - Planning
6
+ **Status**: In Progress
7
+
8
+ ---
9
+
10
+ ## Executive Summary
11
+
12
+ 本文档定义 AI 代码审查工具的核心数据结构,包括 Issue 模型、ScanResult 数据结构和报告格式。
13
+
14
+ **设计原则**:
15
+ - **类型安全**: Go 结构体定义清晰的类型
16
+ - **可序列化**: 支持 JSON/YAML 序列化
17
+ - **可扩展**: 预留扩展字段
18
+ - **向后兼容**: 新字段不影响旧版本
19
+
20
+ ---
21
+
22
+ ## 1. Core Data Types
23
+
24
+ ### 1.1 Severity Levels
25
+
26
+ ```go
27
+ // Severity represents the severity level of an issue
28
+ type Severity string
29
+
30
+ const (
31
+ SeverityCritical Severity = "critical"
32
+ SeverityHigh Severity = "high"
33
+ SeverityMedium Severity = "medium"
34
+ SeverityLow Severity = "low"
35
+ SeverityInfo Severity = "info"
36
+ )
37
+
38
+ // Order returns the numeric ordering for comparison
39
+ func (s Severity) Order() int {
40
+ switch s {
41
+ case SeverityCritical:
42
+ return 4
43
+ case SeverityHigh:
44
+ return 3
45
+ case SeverityMedium:
46
+ return 2
47
+ case SeverityLow:
48
+ return 1
49
+ case SeverityInfo:
50
+ return 0
51
+ default:
52
+ return -1
53
+ }
54
+ }
55
+
56
+ // Color returns the terminal color for this severity
57
+ func (s Severity) Color() string {
58
+ switch s {
59
+ case SeverityCritical:
60
+ return "red"
61
+ case SeverityHigh:
62
+ return "lightRed"
63
+ case SeverityMedium:
64
+ return "yellow"
65
+ case SeverityLow:
66
+ return "lightBlue"
67
+ case SeverityInfo:
68
+ return "blue"
69
+ default:
70
+ return "white"
71
+ }
72
+ }
73
+ ```
74
+
75
+ ### 1.2 Issue Categories
76
+
77
+ ```go
78
+ // Category represents the type of issue
79
+ type Category string
80
+
81
+ const (
82
+ CategorySecurity Category = "security"
83
+ CategoryQuality Category = "quality"
84
+ CategoryPerformance Category = "performance"
85
+ CategoryStyle Category = "style"
86
+ CategoryDocumentation Category = "documentation"
87
+ )
88
+ ```
89
+
90
+ ### 1.3 Confidence Levels
91
+
92
+ ```go
93
+ // Confidence represents the confidence level of the detection
94
+ type Confidence string
95
+
96
+ const (
97
+ ConfidenceHigh Confidence = "high"
98
+ ConfidenceMedium Confidence = "medium"
99
+ ConfidenceLow Confidence = "low"
100
+ )
101
+ ```
102
+
103
+ ### 1.4 Language Support
104
+
105
+ ```go
106
+ // Language represents supported programming languages
107
+ type Language string
108
+
109
+ const (
110
+ LanguagePython Language = "python"
111
+ LanguageJavaScript Language = "javascript"
112
+ LanguageTypeScript Language = "typescript"
113
+ LanguageJSX Language = "jsx"
114
+ LanguageTSX Language = "tsx"
115
+ )
116
+
117
+ // Extension returns the common file extension for this language
118
+ func (l Language) Extension() string {
119
+ switch l {
120
+ case LanguagePython:
121
+ return ".py"
122
+ case LanguageJavaScript:
123
+ return ".js"
124
+ case LanguageTypeScript:
125
+ return ".ts"
126
+ case LanguageJSX:
127
+ return ".jsx"
128
+ case LanguageTSX:
129
+ return ".tsx"
130
+ default:
131
+ return ""
132
+ }
133
+ }
134
+ ```
135
+
136
+ ---
137
+
138
+ ## 2. Issue Data Model
139
+
140
+ ### 2.1 Issue Structure
141
+
142
+ ```go
143
+ // Issue represents a single code issue found during scanning
144
+ type Issue struct {
145
+ // Core identifiers
146
+ ID string `json:"id" yaml:"id"` // Unique issue ID (e.g., "issue_abc123")
147
+ RuleID string `json:"rule_id" yaml:"rule_id"` // Rule that generated this issue
148
+ ScanID string `json:"scan_id" yaml:"scan_id"` // Scan that found this issue
149
+
150
+ // Classification
151
+ Severity Severity `json:"severity" yaml:"severity"` // Issue severity
152
+ Category Category `json:"category" yaml:"category"` // Issue category
153
+ Confidence Confidence `json:"confidence" yaml:"confidence"` // Detection confidence
154
+
155
+ // Description
156
+ Title string `json:"title" yaml:"title"` // Short title
157
+ Description string `json:"description" yaml:"description"` // Detailed description
158
+ Message string `json:"message" yaml:"message"` // Formatted message for display
159
+
160
+ // Location
161
+ File string `json:"file" yaml:"file"` // Relative file path
162
+ Line int `json:"line" yaml:"line"` // Start line (1-indexed)
163
+ Column int `json:"column" yaml:"column"` // Start column (1-indexed)
164
+ EndLine int `json:"end_line" yaml:"end_line"` // End line
165
+ EndColumn int `json:"end_column" yaml:"end_column"` // End column
166
+
167
+ // Code context
168
+ CodeSnippet string `json:"code_snippet,omitempty" yaml:"code_snippet,omitempty"`
169
+ ContextBefore []string `json:"context_before,omitempty" yaml:"context_before,omitempty"`
170
+ ContextAfter []string `json:"context_after,omitempty" yaml:"context_after,omitempty"`
171
+
172
+ // Fix suggestions
173
+ Suggestion string `json:"suggestion,omitempty" yaml:"suggestion,omitempty"`
174
+ SuggestedCode string `json:"suggested_code,omitempty" yaml:"suggested_code,omitempty"`
175
+ Fixable bool `json:"fixable" yaml:"fixable"`
176
+ AutoFixAvailable bool `json:"auto_fix_available,omitempty" yaml:"auto_fix_available,omitempty"`
177
+
178
+ // References
179
+ References []string `json:"references,omitempty" yaml:"references,omitempty"`
180
+ CWE string `json:"cwe,omitempty" yaml:"cwe,omitempty"` // CWE ID if applicable
181
+ OWASP string `json:"owasp,omitempty" yaml:"owasp,omitempty"` // OWASP category if applicable
182
+
183
+ // Metadata
184
+ Language Language `json:"language,omitempty" yaml:"language,omitempty"`
185
+ AIEnhanced bool `json:"ai_enhanced" yaml:"ai_enhanced"`
186
+ AIModel string `json:"ai_model,omitempty" yaml:"ai_model,omitempty"`
187
+ CreatedAt time.Time `json:"created_at" yaml:"created_at"`
188
+
189
+ // Extension fields
190
+ Extra map[string]interface{} `json:"extra,omitempty" yaml:"extra,omitempty"`
191
+ }
192
+ ```
193
+
194
+ ### 2.2 Issue Methods
195
+
196
+ ```go
197
+ // LocationString returns a formatted location string
198
+ func (i *Issue) LocationString() string {
199
+ if i.EndLine > i.Line {
200
+ return fmt.Sprintf("%s:%d-%d", i.File, i.Line, i.EndLine)
201
+ }
202
+ return fmt.Sprintf("%s:%d", i.File, i.Line)
203
+ }
204
+
205
+ // FullLocationString returns a detailed location string
206
+ func (i *Issue) FullLocationString() string {
207
+ return fmt.Sprintf("%s:%d:%d", i.File, i.Line, i.Column)
208
+ }
209
+
210
+ // String returns a formatted string representation
211
+ func (i *Issue) String() string {
212
+ return fmt.Sprintf("[%s] %s: %s",
213
+ strings.ToUpper(string(i.Severity)),
214
+ i.FullLocationString(),
215
+ i.Title,
216
+ )
217
+ }
218
+
219
+ // IsSecurity returns true if this is a security issue
220
+ func (i *Issue) IsSecurity() bool {
221
+ return i.Category == CategorySecurity
222
+ }
223
+
224
+ // Hash returns a deterministic hash for deduplication
225
+ func (i *Issue) Hash() string {
226
+ data := fmt.Sprintf("%s:%s:%d:%d",
227
+ i.RuleID,
228
+ i.File,
229
+ i.Line,
230
+ i.Column,
231
+ )
232
+ return fmt.Sprintf("%x", sha256.Sum256([]byte(data)))
233
+ }
234
+ ```
235
+
236
+ ### 2.3 Issue Collection
237
+
238
+ ```go
239
+ // Issues is a collection of issues with utility methods
240
+ type Issues []Issue
241
+
242
+ // FilterBySeverity returns issues with severity >= min
243
+ func (is Issues) FilterBySeverity(min Severity) Issues {
244
+ var result Issues
245
+ for _, issue := range is {
246
+ if issue.Severity.Order() >= min.Order() {
247
+ result = append(result, issue)
248
+ }
249
+ }
250
+ return result
251
+ }
252
+
253
+ // FilterByCategory returns issues in the specified category
254
+ func (is Issues) FilterByCategory(cat Category) Issues {
255
+ var result Issues
256
+ for _, issue := range is {
257
+ if issue.Category == cat {
258
+ result = append(result, issue)
259
+ }
260
+ }
261
+ return result
262
+ }
263
+
264
+ // FilterByFile returns issues in the specified file
265
+ func (is Issues) FilterByFile(file string) Issues {
266
+ var result Issues
267
+ for _, issue := range is {
268
+ if issue.File == file {
269
+ result = append(result, issue)
270
+ }
271
+ }
272
+ return result
273
+ }
274
+
275
+ // BySeverity sorts issues by severity (highest first)
276
+ func (is Issues) BySeverity() Issues {
277
+ sorted := make(Issues, len(is))
278
+ copy(sorted, is)
279
+ sort.Slice(sorted, func(i, j int) bool {
280
+ return sorted[i].Severity.Order() > sorted[j].Severity.Order()
281
+ })
282
+ return sorted
283
+ }
284
+
285
+ // GroupByFile groups issues by file
286
+ func (is Issues) GroupByFile() map[string]Issues {
287
+ result := make(map[string]Issues)
288
+ for _, issue := range is {
289
+ result[issue.File] = append(result[issue.File], issue)
290
+ }
291
+ return result
292
+ }
293
+
294
+ // Deduplicate removes duplicate issues based on hash
295
+ func (is Issues) Deduplicate() Issues {
296
+ seen := make(map[string]bool)
297
+ var result Issues
298
+ for _, issue := range is {
299
+ hash := issue.Hash()
300
+ if !seen[hash] {
301
+ seen[hash] = true
302
+ result = append(result, issue)
303
+ }
304
+ }
305
+ return result
306
+ }
307
+ ```
308
+
309
+ ---
310
+
311
+ ## 3. ScanResult Data Structure
312
+
313
+ ### 3.1 ScanResult Structure
314
+
315
+ ```go
316
+ // ScanResult represents the complete results of a code scan
317
+ type ScanResult struct {
318
+ // Scan metadata
319
+ ScanID string `json:"scan_id" yaml:"scan_id"`
320
+ Version string `json:"version" yaml:"version"` // Tool version
321
+ Timestamp time.Time `json:"timestamp" yaml:"timestamp"`
322
+ Duration time.Duration `json:"duration" yaml:"duration"`
323
+
324
+ // Scan configuration
325
+ Config ScanConfig `json:"config,omitempty" yaml:"config,omitempty"`
326
+
327
+ // Files scanned
328
+ FilesScanned int `json:"files_scanned" yaml:"files_scanned"`
329
+ FilesSkipped int `json:"files_skipped" yaml:"files_skipped"`
330
+ Files []FileResult `json:"files,omitempty" yaml:"files,omitempty"`
331
+
332
+ // Issues
333
+ Issues Issues `json:"issues" yaml:"issues"`
334
+ Summary IssueSummary `json:"summary" yaml:"summary"`
335
+
336
+ // Performance metrics
337
+ Performance PerformanceMetrics `json:"performance" yaml:"performance"`
338
+
339
+ // AI usage (if applicable)
340
+ AIUsage *AIUsage `json:"ai_usage,omitempty" yaml:"ai_usage,omitempty"`
341
+
342
+ // Extension fields
343
+ Extra map[string]interface{} `json:"extra,omitempty" yaml:"extra,omitempty"`
344
+ }
345
+ ```
346
+
347
+ ### 3.2 Scan Configuration Snapshot
348
+
349
+ ```go
350
+ // ScanConfig captures the configuration used for a scan
351
+ type ScanConfig struct {
352
+ Path string `json:"path" yaml:"path"`
353
+ Include []string `json:"include,omitempty" yaml:"include,omitempty"`
354
+ Exclude []string `json:"exclude,omitempty" yaml:"exclude,omitempty"`
355
+ MinSeverity Severity `json:"min_severity" yaml:"min_severity"`
356
+ Recursive bool `json:"recursive" yaml:"recursive"`
357
+ DiffMode bool `json:"diff_mode" yaml:"diff_mode"`
358
+ AIEnabled bool `json:"ai_enabled" yaml:"ai_enabled"`
359
+ Jobs int `json:"jobs" yaml:"jobs"`
360
+ RulesEnabled []string `json:"rules_enabled,omitempty" yaml:"rules_enabled,omitempty"`
361
+ }
362
+ ```
363
+
364
+ ### 3.3 File Result
365
+
366
+ ```go
367
+ // FileResult represents the scan result for a single file
368
+ type FileResult struct {
369
+ Path string `json:"path" yaml:"path"`
370
+ Language Language `json:"language" yaml:"language"`
371
+ Lines int `json:"lines" yaml:"lines"`
372
+ Issues Issues `json:"issues" yaml:"issues"`
373
+ Error string `json:"error,omitempty" yaml:"error,omitempty"`
374
+ Skipped bool `json:"skipped" yaml:"skipped"`
375
+ SkipReason string `json:"skip_reason,omitempty" yaml:"skip_reason,omitempty"`
376
+ }
377
+ ```
378
+
379
+ ### 3.4 Issue Summary
380
+
381
+ ```go
382
+ // IssueSummary provides a summary of issues found
383
+ type IssueSummary struct {
384
+ Total int `json:"total" yaml:"total"`
385
+ BySeverity map[Severity]int `json:"by_severity" yaml:"by_severity"`
386
+ ByCategory map[Category]int `json:"by_category" yaml:"by_category"`
387
+ ByRule map[string]int `json:"by_rule,omitempty" yaml:"by_rule,omitempty"`
388
+ ByFile map[string]int `json:"by_file,omitempty" yaml:"by_file,omitempty"`
389
+ }
390
+
391
+ // NewIssueSummary creates a summary from a list of issues
392
+ func NewIssueSummary(issues Issues) IssueSummary {
393
+ summary := IssueSummary{
394
+ Total: len(issues),
395
+ BySeverity: make(map[Severity]int),
396
+ ByCategory: make(map[Category]int),
397
+ ByRule: make(map[string]int),
398
+ ByFile: make(map[string]int),
399
+ }
400
+
401
+ for _, issue := range issues {
402
+ summary.BySeverity[issue.Severity]++
403
+ summary.ByCategory[issue.Category]++
404
+ summary.ByRule[issue.RuleID]++
405
+ summary.ByFile[issue.File]++
406
+ }
407
+
408
+ return summary
409
+ }
410
+ ```
411
+
412
+ ### 3.5 Performance Metrics
413
+
414
+ ```go
415
+ // PerformanceMetrics captures scan performance data
416
+ type PerformanceMetrics struct {
417
+ // Timing
418
+ TotalDuration time.Duration `json:"total_duration" yaml:"total_duration"`
419
+ ParseDuration time.Duration `json:"parse_duration" yaml:"parse_duration"`
420
+ RuleDuration time.Duration `json:"rule_duration" yaml:"rule_duration"`
421
+ LLMDuration time.Duration `json:"llm_duration,omitempty" yaml:"llm_duration,omitempty"`
422
+
423
+ // Throughput
424
+ FilesPerSecond float64 `json:"files_per_second" yaml:"files_per_second"`
425
+ LinesPerSecond float64 `json:"lines_per_second" yaml:"lines_per_second"`
426
+ IssuesPerSecond float64 `json:"issues_per_second" yaml:"issues_per_second"`
427
+
428
+ // Cache effectiveness
429
+ CacheHitRate float64 `json:"cache_hit_rate" yaml:"cache_hit_rate"`
430
+
431
+ // Resource usage
432
+ MemoryUsedMB int64 `json:"memory_used_mb" yaml:"memory_used_mb"`
433
+ CPUUsagePercent float64 `json:"cpu_usage_percent,omitempty" yaml:"cpu_usage_percent,omitempty"`
434
+ }
435
+ ```
436
+
437
+ ### 3.6 AI Usage
438
+
439
+ ```go
440
+ // AIUsage captures AI-related usage data
441
+ type AIUsage struct {
442
+ Enabled bool `json:"enabled" yaml:"enabled"`
443
+ Provider string `json:"provider" yaml:"provider"`
444
+ Model string `json:"model" yaml:"model"`
445
+
446
+ // API calls
447
+ TotalRequests int `json:"total_requests" yaml:"total_requests"`
448
+ SuccessfulRequests int `json:"successful_requests" yaml:"successful_requests"`
449
+ FailedRequests int `json:"failed_requests" yaml:"failed_requests"`
450
+
451
+ // Tokens
452
+ TotalTokens int `json:"total_tokens" yaml:"total_tokens"`
453
+ InputTokens int `json:"input_tokens" yaml:"input_tokens"`
454
+ OutputTokens int `json:"output_tokens" yaml:"output_tokens"`
455
+
456
+ // Cost
457
+ EstimatedCostUSD float64 `json:"estimated_cost_usd" yaml:"estimated_cost_usd"`
458
+
459
+ // Issues enhanced by AI
460
+ IssuesEnhanced int `json:"issues_enhanced" yaml:"issues_enhanced"`
461
+ IssuesFound int `json:"issues_found" yaml:"issues_found"`
462
+ }
463
+ ```
464
+
465
+ ---
466
+
467
+ ## 4. Report Formats
468
+
469
+ ### 4.1 Report Metadata
470
+
471
+ ```go
472
+ // ReportMetadata contains metadata about a report
473
+ type ReportMetadata struct {
474
+ GeneratedAt time.Time `json:"generated_at" yaml:"generated_at"`
475
+ GeneratedBy string `json:"generated_by" yaml:"generated_by"` // Tool version
476
+ ScanID string `json:"scan_id" yaml:"scan_id"`
477
+ ProjectPath string `json:"project_path" yaml:"project_path"`
478
+ GitBranch string `json:"git_branch,omitempty" yaml:"git_branch,omitempty"`
479
+ GitCommit string `json:"git_commit,omitempty" yaml:"git_commit,omitempty"`
480
+ }
481
+ ```
482
+
483
+ ### 4.2 Trend Report
484
+
485
+ ```go
486
+ // TrendReport shows quality trends over time
487
+ type TrendReport struct {
488
+ Metadata ReportMetadata `json:"metadata" yaml:"metadata"`
489
+ Period Period `json:"period" yaml:"period"`
490
+ Current Snapshot `json:"current" yaml:"current"`
491
+ Previous Snapshot `json:"previous" yaml:"previous"`
492
+ Delta TrendDelta `json:"delta" yaml:"delta"`
493
+ History []Snapshot `json:"history,omitempty" yaml:"history,omitempty"`
494
+ }
495
+
496
+ // Period defines the time period for the trend report
497
+ type Period struct {
498
+ Start time.Time `json:"start" yaml:"start"`
499
+ End time.Time `json:"end" yaml:"end"`
500
+ Days int `json:"days" yaml:"days"`
501
+ }
502
+
503
+ // Snapshot represents a point-in-time state
504
+ type Snapshot struct {
505
+ Date time.Time `json:"date" yaml:"date"`
506
+ ScanID string `json:"scan_id" yaml:"scan_id"`
507
+ Summary IssueSummary `json:"summary" yaml:"summary"`
508
+ Files int `json:"files" yaml:"files"`
509
+ Lines int `json:"lines" yaml:"lines"`
510
+ }
511
+
512
+ // TrendDelta shows changes between snapshots
513
+ type TrendDelta struct {
514
+ TotalIssues int `json:"total_issues" yaml:"total_issues"`
515
+ CriticalDelta int `json:"critical_delta" yaml:"critical_delta"`
516
+ HighDelta int `json:"high_delta" yaml:"high_delta"`
517
+ MediumDelta int `json:"medium_delta" yaml:"medium_delta"`
518
+ LowDelta int `json:"low_delta" yaml:"low_delta"`
519
+ PercentChange float64 `json:"percent_change" yaml:"percent_change"`
520
+ Direction string `json:"direction" yaml:"direction"` // "up", "down", "same"
521
+ }
522
+ ```
523
+
524
+ ### 4.3 SARIF Report
525
+
526
+ ```go
527
+ // SARIFReport is the Static Analysis Results Interchange Format
528
+ // See: https://sarifweb.azurewebsites.net/
529
+ type SARIFReport struct {
530
+ Version string `json:"version"`
531
+ Schema string `json:"$schema"`
532
+ Runs []SARIFRun `json:"runs"`
533
+ }
534
+
535
+ type SARIFRun struct {
536
+ Tool SARIFTool `json:"tool"`
537
+ Results []SARIFResult `json:"results"`
538
+ Invocations []SARIFInvocation `json:"invocations,omitempty"`
539
+ }
540
+
541
+ type SARIFTool struct {
542
+ Driver SARIFToolDriver `json:"driver"`
543
+ }
544
+
545
+ type SARIFToolDriver struct {
546
+ Name string `json:"name"`
547
+ Version string `json:"version"`
548
+ InformationURI string `json:"informationUri,omitempty"`
549
+ Rules []SARIFRule `json:"rules,omitempty"`
550
+ }
551
+
552
+ type SARIFRule struct {
553
+ ID string `json:"id"`
554
+ Name string `json:"name,omitempty"`
555
+ ShortDescription SARIFMessage `json:"shortDescription"`
556
+ FullDescription SARIFMessage `json:"fullDescription,omitempty"`
557
+ HelpURI string `json:"helpUri,omitempty"`
558
+ Properties map[string]interface{} `json:"properties,omitempty"`
559
+ }
560
+
561
+ type SARIFResult struct {
562
+ RuleID string `json:"ruleId"`
563
+ Level string `json:"level"` // error, warning, note
564
+ Message SARIFMessage `json:"message"`
565
+ Locations []SARIFLocation `json:"locations"`
566
+ Fixes []SARIFFix `json:"fixes,omitempty"`
567
+ }
568
+
569
+ type SARIFMessage struct {
570
+ Text string `json:"text"`
571
+ Markdown string `json:"markdown,omitempty"`
572
+ }
573
+
574
+ type SARIFLocation struct {
575
+ PhysicalLocation SARIFPhysicalLocation `json:"physicalLocation"`
576
+ LogicalLocations []SARIFLogicalLocation `json:"logicalLocations,omitempty"`
577
+ }
578
+
579
+ type SARIFPhysicalLocation struct {
580
+ ArtifactLocation SARIFArtifactLocation `json:"artifactLocation"`
581
+ Region SARIFRegion `json:"region"`
582
+ }
583
+
584
+ type SARIFArtifactLocation struct {
585
+ URI string `json:"uri"`
586
+ }
587
+
588
+ type SARIFRegion struct {
589
+ StartLine int `json:"startLine"`
590
+ StartColumn int `json:"startColumn,omitempty"`
591
+ EndLine int `json:"endLine,omitempty"`
592
+ EndColumn int `json:"endColumn,omitempty"`
593
+ Snippet SARIFSnippet `json:"snippet,omitempty"`
594
+ }
595
+
596
+ type SARIFSnippet struct {
597
+ Text string `json:"text"`
598
+ }
599
+
600
+ type SARIFLogicalLocation struct {
601
+ Name string `json:"name,omitempty"`
602
+ Kind string `json:"kind,omitempty"` // function, module, etc.
603
+ }
604
+
605
+ type SARIFFix struct {
606
+ Description SARIFMessage `json:"description"`
607
+ ArtifactChanges []SARIFArtifactChange `json:"artifactChanges"`
608
+ }
609
+
610
+ type SARIFArtifactChange struct {
611
+ ArtifactLocation SARIFArtifactLocation `json:"artifactLocation"`
612
+ Replacements []SARIFReplacement `json:"replacements"`
613
+ }
614
+
615
+ type SARIFReplacement struct {
616
+ DeletedRegion SARIFRegion `json:"deletedRegion"`
617
+ InsertedContent SARIFContent `json:"insertedContent"`
618
+ }
619
+
620
+ type SARIFContent struct {
621
+ Text string `json:"text"`
622
+ }
623
+
624
+ type SARIFInvocation struct {
625
+ StartTimeUTC string `json:"startTimeUtc,omitempty"`
626
+ EndTimeUTC string `json:"endTimeUtc,omitempty"`
627
+ ExitStatus string `json:"exitStatus,omitempty"`
628
+ ExitStatusCode int `json:"exitStatusCode,omitempty"`
629
+ }
630
+ ```
631
+
632
+ ---
633
+
634
+ ## 5. Database Schema
635
+
636
+ ### 5.1 Scans Table
637
+
638
+ ```sql
639
+ CREATE TABLE scans (
640
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
641
+ scan_id VARCHAR(255) UNIQUE NOT NULL,
642
+ timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
643
+ duration_ms INTEGER NOT NULL,
644
+ config JSONB NOT NULL,
645
+
646
+ -- File counts
647
+ files_scanned INTEGER NOT NULL DEFAULT 0,
648
+ files_skipped INTEGER NOT NULL DEFAULT 0,
649
+
650
+ -- Issue summary
651
+ total_issues INTEGER NOT NULL DEFAULT 0,
652
+ critical_issues INTEGER NOT NULL DEFAULT 0,
653
+ high_issues INTEGER NOT NULL DEFAULT 0,
654
+ medium_issues INTEGER NOT NULL DEFAULT 0,
655
+ low_issues INTEGER NOT NULL DEFAULT 0,
656
+
657
+ -- Performance
658
+ performance JSONB,
659
+
660
+ -- AI usage
661
+ ai_enabled BOOLEAN NOT NULL DEFAULT false,
662
+ ai_usage JSONB,
663
+
664
+ -- Git context
665
+ git_branch VARCHAR(255),
666
+ git_commit VARCHAR(40),
667
+
668
+ -- Metadata
669
+ project_path VARCHAR(1024),
670
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
671
+
672
+ -- Indexes
673
+ INDEX idx_scans_timestamp (timestamp),
674
+ INDEX idx_scans_project (project_path)
675
+ );
676
+ ```
677
+
678
+ ### 5.2 Issues Table
679
+
680
+ ```sql
681
+ CREATE TABLE issues (
682
+ id BIGSERIAL PRIMARY KEY,
683
+ issue_id VARCHAR(255) UNIQUE NOT NULL,
684
+ scan_id VARCHAR(255) NOT NULL REFERENCES scans(scan_id),
685
+
686
+ -- Classification
687
+ rule_id VARCHAR(255) NOT NULL,
688
+ severity VARCHAR(50) NOT NULL,
689
+ category VARCHAR(50) NOT NULL,
690
+ confidence VARCHAR(50),
691
+
692
+ -- Location
693
+ file_path VARCHAR(1024) NOT NULL,
694
+ line_number INTEGER NOT NULL,
695
+ column_number INTEGER,
696
+ end_line INTEGER,
697
+ end_column INTEGER,
698
+
699
+ -- Description
700
+ title VARCHAR(512) NOT NULL,
701
+ description TEXT,
702
+ message TEXT,
703
+
704
+ -- Code context
705
+ code_snippet TEXT,
706
+ suggestion TEXT,
707
+ suggested_code TEXT,
708
+ fixable BOOLEAN DEFAULT false,
709
+
710
+ -- References
711
+ references JSONB,
712
+ cwe VARCHAR(20),
713
+ owasp VARCHAR(100),
714
+
715
+ -- AI
716
+ ai_enhanced BOOLEAN DEFAULT false,
717
+ ai_model VARCHAR(100),
718
+
719
+ -- Metadata
720
+ language VARCHAR(50),
721
+ extra JSONB,
722
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
723
+
724
+ -- Indexes
725
+ INDEX idx_issues_scan (scan_id),
726
+ INDEX idx_issues_file (file_path),
727
+ INDEX idx_issues_severity (severity),
728
+ INDEX idx_issues_rule (rule_id)
729
+ );
730
+ ```
731
+
732
+ ### 5.3 Rules Table
733
+
734
+ ```sql
735
+ CREATE TABLE rules (
736
+ id SERIAL PRIMARY KEY,
737
+ rule_id VARCHAR(255) UNIQUE NOT NULL,
738
+ name VARCHAR(255) NOT NULL,
739
+ category VARCHAR(50) NOT NULL,
740
+ default_severity VARCHAR(50) NOT NULL,
741
+
742
+ -- Definition
743
+ definition JSONB NOT NULL,
744
+ languages VARCHAR(50) [],
745
+
746
+ -- Configuration
747
+ enabled BOOLEAN DEFAULT true,
748
+ custom BOOLEAN DEFAULT false,
749
+
750
+ -- Documentation
751
+ title VARCHAR(512),
752
+ description TEXT,
753
+ references JSONB,
754
+
755
+ -- Metadata
756
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
757
+ updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
758
+ );
759
+ ```
760
+
761
+ ### 5.4 Scan History View
762
+
763
+ ```sql
764
+ CREATE VIEW scan_history AS
765
+ SELECT
766
+ date_trunc('day', timestamp) AS date,
767
+ COUNT(*) AS scan_count,
768
+ AVG(total_issues) AS avg_issues,
769
+ AVG(duration_ms) AS avg_duration_ms,
770
+ SUM(total_issues) AS total_issues,
771
+ AVG(critical_issues) AS avg_critical,
772
+ AVG(high_issues) AS avg_high,
773
+ AVG(medium_issues) AS avg_medium,
774
+ AVG(low_issues) AS avg_low
775
+ FROM scans
776
+ GROUP BY date_trunc('day', timestamp)
777
+ ORDER BY date DESC;
778
+ ```
779
+
780
+ ---
781
+
782
+ ## 6. Cache Schema
783
+
784
+ ### 6.1 Redis Cache Keys
785
+
786
+ ``# AST Cache
787
+ ast:{language}:{file_hash} -> {
788
+ "ast": <serialized AST>,
789
+ "timestamp": <unix timestamp>,
790
+ "file_size": <bytes>
791
+ }
792
+
793
+ # Rule Cache
794
+ rules:{rule_id} -> {
795
+ "compiled": <compiled rule>,
796
+ "timestamp": <unix timestamp>
797
+ }
798
+
799
+ # Scan Session
800
+ session:{scan_id} -> {
801
+ "config": <scan config>,
802
+ "start_time": <unix timestamp>,
803
+ "files_scanned": <count>,
804
+ "issues_found": <count>
805
+ }
806
+ ```
807
+
808
+ ---
809
+
810
+ ## 7. Next Steps
811
+
812
+ 1. Review data model with stakeholders
813
+ 2. Implement Go structs
814
+ 3. Create database migration scripts
815
+ 4. Implement JSON/YAML serialization
816
+ 5. Create unit tests for data structures
817
+ 6. Proceed to work breakdown (wbs.md)
818
+
819
+ ---
820
+
821
+ ## Metadata
822
+
823
+ - **Created**: 1/17/2026
824
+ - **Author**: Phase 3 Design Executor
825
+ - **Status**: Draft for Review
826
+ - **Related Docs**: phase3/architecture.md, phase3/api-design.md
827
+
828
+ ---
829
+
830
+ *This data model design document defines the core data structures for the AI Code Review Tool.*